refactor: moving more models to mapped_column

This commit is contained in:
Iain Learmonth 2024-11-10 15:13:29 +00:00
parent ea020d6edd
commit 75b2c1adf0
9 changed files with 272 additions and 94 deletions

View file

@ -13,10 +13,10 @@ class AbstractConfiguration(db.Model): # type: ignore
__abstract__ = True
id: Mapped[int] = mapped_column(db.Integer, primary_key=True)
description: Mapped[str] = mapped_column(db.String(255), nullable=False)
added: Mapped[datetime] = mapped_column(db.DateTime(), default=datetime.utcnow, nullable=False)
updated: Mapped[datetime] = mapped_column(db.DateTime(), default=datetime.utcnow, nullable=False)
destroyed: Mapped[datetime] = mapped_column(db.DateTime())
description: Mapped[str]
added: Mapped[datetime]
updated: Mapped[datetime]
destroyed: Mapped[Optional[datetime]]
@property
@abstractmethod

View file

@ -1,21 +1,36 @@
from datetime import datetime
from typing import List
from typing import List, TypedDict, Optional, TYPE_CHECKING
from sqlalchemy import and_
from sqlalchemy.orm import Mapped, aliased, mapped_column, relationship
from app.brm.brn import BRN
from app.extensions import db
from app.models import AbstractConfiguration
if TYPE_CHECKING:
from app.models.bridges import BridgeConf
from app.models.mirrors import Origin, Proxy, SmartProxy, StaticOrigin
from app.models.onions import Eotk, Onion
class GroupDict(TypedDict):
Id: int
GroupName: str
Description: str
ActiveOriginCount: int
class Group(AbstractConfiguration):
group_name = db.Column(db.String(80), unique=True, nullable=False)
eotk = db.Column(db.Boolean())
group_name: Mapped[str] = db.Column(db.String(80), unique=True, nullable=False)
eotk: Mapped[bool]
origins = db.relationship("Origin", back_populates="group")
statics = db.relationship("StaticOrigin", back_populates="group")
eotks = db.relationship("Eotk", back_populates="group")
onions = db.relationship("Onion", back_populates="group")
smart_proxies = db.relationship("SmartProxy", back_populates="group")
pools = db.relationship("Pool", secondary="pool_group", back_populates="groups")
origins: Mapped[List["Origin"]] = relationship("Origin", back_populates="group")
statics: Mapped[List["StaticOrigin"]] = relationship("StaticOrigin", back_populates="group")
eotks: Mapped[List["Eotk"]] = relationship("Eotk", back_populates="group")
onions: Mapped[List["Onion"]] = relationship("Onion", back_populates="group")
smart_proxies: Mapped[List["SmartProxy"]] = relationship("SmartProxy", back_populates="group")
pools: Mapped[List["Pool"]] = relationship("Pool", secondary="pool_group", back_populates="groups")
@classmethod
def csv_header(cls) -> List[str]:
@ -33,25 +48,29 @@ class Group(AbstractConfiguration):
resource_id=str(self.id)
)
def to_dict(self):
active_origins = [o for o in self.origins if o.destroyed is None]
def to_dict(self) -> GroupDict:
active_origins_query = (
db.session.query(aliased(Origin))
.filter(and_(Origin.group_id == self.id, Origin.destroyed.is_(None)))
)
active_origins_count = active_origins_query.count()
return {
"Id": self.id,
"GroupName": self.group_name,
"Description": self.description,
"ActiveOriginCount": len(active_origins),
"ActiveOriginCount": active_origins_count,
}
class Pool(AbstractConfiguration):
pool_name = db.Column(db.String(80), unique=True, nullable=False)
api_key = db.Column(db.String(80), nullable=False)
redirector_domain = db.Column(db.String(128), nullable=True)
pool_name: Mapped[str] = mapped_column(db.String, unique=True)
api_key: Mapped[str]
redirector_domain: Mapped[Optional[str]]
bridgeconfs = db.relationship("BridgeConf", back_populates="pool")
proxies = db.relationship("Proxy", back_populates="pool")
lists = db.relationship("MirrorList", back_populates="pool")
groups = db.relationship("Group", secondary="pool_group", back_populates="pools")
bridgeconfs: Mapped[List["BridgeConf"]] = relationship("BridgeConf", back_populates="pool")
proxies: Mapped[List["Proxy"]] = relationship("Proxy", back_populates="pool")
lists: Mapped[List["MirrorList"]] = relationship("MirrorList", back_populates="pool")
groups: Mapped[List[Group]] = relationship("Group", secondary="pool_group", back_populates="pools")
@classmethod
def csv_header(cls) -> List[str]:

View file

@ -2,9 +2,12 @@ import enum
from datetime import datetime
from typing import List
from sqlalchemy.orm import Mapped, mapped_column, relationship
from app.brm.brn import BRN
from app.extensions import db
from app.models import AbstractConfiguration, AbstractResource
from app.models.base import Pool
class ProviderAllocation(enum.Enum):
@ -13,15 +16,15 @@ class ProviderAllocation(enum.Enum):
class BridgeConf(AbstractConfiguration):
pool_id = db.Column(db.Integer, db.ForeignKey("pool.id"), nullable=False)
method = db.Column(db.String(20), nullable=False)
target_number = db.Column(db.Integer())
max_number = db.Column(db.Integer())
expiry_hours = db.Column(db.Integer())
provider_allocation = db.Column(db.Enum(ProviderAllocation))
pool_id: Mapped[int] = mapped_column(db.Integer, db.ForeignKey("pool.id"))
method: Mapped[str]
target_number: Mapped[int]
max_number: Mapped[int]
expiry_hours: Mapped[int]
provider_allocation: Mapped[ProviderAllocation]
pool = db.relationship("Pool", back_populates="bridgeconfs")
bridges = db.relationship("Bridge", back_populates="conf")
pool: Mapped[Pool] = relationship("Pool", back_populates="bridgeconfs")
bridges: Mapped[List["Bridge"]] = relationship("Bridge", back_populates="conf")
@property
def brn(self) -> BRN:

View file

@ -1,4 +1,7 @@
import enum
from typing import Any, Dict, List, TYPE_CHECKING
from sqlalchemy.orm import Mapped, mapped_column, relationship
from app.brm.brn import BRN
from app.extensions import db
@ -6,6 +9,10 @@ from app.models import AbstractConfiguration
from app.models.mirrors import StaticOrigin
if TYPE_CHECKING:
from app.models.bridges import Bridge
class CloudProvider(enum.Enum):
AWS = ("aws", "Amazon Web Services")
AZURE = ("azure", "Microsoft Azure")
@ -27,17 +34,17 @@ class CloudProvider(enum.Enum):
class CloudAccount(AbstractConfiguration):
provider = db.Column(db.Enum(CloudProvider))
credentials = db.Column(db.JSON())
enabled = db.Column(db.Boolean())
provider: Mapped[CloudProvider]
credentials: Mapped[Dict[str, Any]] = mapped_column(db.JSON())
enabled: Mapped[bool]
# CDN Quotas
max_distributions = db.Column(db.Integer())
max_sub_distributions = db.Column(db.Integer())
max_distributions: Mapped[int]
max_sub_distributions: Mapped[int]
# Compute Quotas
max_instances = db.Column(db.Integer())
max_instances: Mapped[int]
bridges = db.relationship("Bridge", back_populates="cloud_account")
statics = db.relationship("StaticOrigin", back_populates="storage_cloud_account", foreign_keys=[
bridges: Mapped[List["Bridge"]] = relationship("Bridge", back_populates="cloud_account")
statics: Mapped[List["StaticOrigin"]] = relationship("StaticOrigin", back_populates="storage_cloud_account", foreign_keys=[
StaticOrigin.storage_cloud_account_id])
@property

View file

@ -2,10 +2,10 @@ from __future__ import annotations
import json
from datetime import datetime, timedelta
from typing import Optional, List, Union, Any, Dict
from typing import Optional, List, Union, Any, Dict, TypedDict, Literal
import tldextract
from sqlalchemy.orm import Mapped, mapped_column
from sqlalchemy.orm import Mapped, mapped_column, relationship
from tldextract import extract
from werkzeug.datastructures import FileStorage
@ -13,7 +13,7 @@ from app.brm.brn import BRN
from app.brm.utils import thumbnail_uploaded_image, create_data_uri, normalize_color
from app.extensions import db
from app.models import AbstractConfiguration, AbstractResource, Deprecation
from app.models.base import Pool
from app.models.base import Pool, Group
from app.models.onions import Onion
country_origin = db.Table(
@ -25,17 +25,25 @@ country_origin = db.Table(
)
class Origin(AbstractConfiguration):
group_id = mapped_column(db.Integer, db.ForeignKey("group.id"), nullable=False)
domain_name = mapped_column(db.String(255), unique=True, nullable=False)
auto_rotation = mapped_column(db.Boolean, nullable=False)
smart = mapped_column(db.Boolean(), nullable=False)
assets = mapped_column(db.Boolean(), nullable=False)
risk_level_override = mapped_column(db.Integer(), nullable=True)
class OriginDict(TypedDict):
Id: int
Description: str
DomainName: str
RiskLevel: Dict[str, int]
RiskLevelOverride: Optional[int]
group = db.relationship("Group", back_populates="origins")
proxies = db.relationship("Proxy", back_populates="origin")
countries = db.relationship("Country", secondary=country_origin, back_populates='origins')
class Origin(AbstractConfiguration):
group_id: Mapped[int] = mapped_column(db.Integer, db.ForeignKey("group.id"))
domain_name: Mapped[str] = mapped_column(db.String(255), unique=True)
auto_rotation: Mapped[bool]
smart: Mapped[bool]
assets: Mapped[bool]
risk_level_override: Mapped[Optional[int]]
group: Mapped[Group] = relationship("Group", back_populates="origins")
proxies: Mapped[List[Proxy]] = relationship("Proxy", back_populates="origin")
countries: Mapped[List[Country]] = relationship("Country", secondary=country_origin, back_populates='origins')
@property
def brn(self) -> BRN:
@ -100,7 +108,7 @@ class Origin(AbstractConfiguration):
max(1, min(10, frequency_factor * recency_factor))) + country.risk_level
return risk_levels
def to_dict(self):
def to_dict(self) -> OriginDict:
return {
"Id": self.id,
"Description": self.description,
@ -250,6 +258,16 @@ class StaticOrigin(AbstractConfiguration):
self.updated = datetime.utcnow()
ResourceStatus = Union[Literal["active"], Literal["pending"], Literal["expiring"], Literal["destroyed"]]
class ProxyDict(TypedDict):
Id: int
OriginDomain: str
MirrorDomain: Optional[str]
Status: ResourceStatus
class Proxy(AbstractResource):
origin_id: Mapped[int] = mapped_column(db.Integer, db.ForeignKey("origin.id"), nullable=False)
pool_id: Mapped[Optional[int]] = mapped_column(db.Integer, db.ForeignKey("pool.id"))
@ -259,8 +277,8 @@ class Proxy(AbstractResource):
terraform_updated: Mapped[Optional[datetime]] = mapped_column(db.DateTime(), nullable=True)
url: Mapped[Optional[str]] = mapped_column(db.String(255), nullable=True)
origin: Mapped[Origin] = db.relationship("Origin", back_populates="proxies")
pool: Mapped[Pool] = db.relationship("Pool", back_populates="proxies")
origin: Mapped[Origin] = relationship("Origin", back_populates="proxies")
pool: Mapped[Pool] = relationship("Pool", back_populates="proxies")
@property
def brn(self) -> BRN:
@ -278,8 +296,8 @@ class Proxy(AbstractResource):
"origin_id", "provider", "psg", "slug", "terraform_updated", "url"
]
def to_dict(self):
status = "active"
def to_dict(self) -> ProxyDict:
status: ResourceStatus = "active"
if self.url is None:
status = "pending"
if self.deprecated is not None:

View file

@ -1,9 +1,13 @@
import base64
import hashlib
from typing import Optional
from sqlalchemy.orm import Mapped, mapped_column, relationship
from app.brm.brn import BRN
from app.extensions import db
from app.models import AbstractConfiguration, AbstractResource
from app.models.base import Group
class Onion(AbstractConfiguration):
@ -47,12 +51,12 @@ class Onion(AbstractConfiguration):
class Eotk(AbstractResource):
group_id = db.Column(db.Integer(), db.ForeignKey("group.id"), nullable=False)
instance_id = db.Column(db.String(100), nullable=True)
provider = db.Column(db.String(20), nullable=False)
region = db.Column(db.String(20), nullable=False)
group_id: Mapped[int] = mapped_column(db.Integer(), db.ForeignKey("group.id"))
instance_id: Mapped[Optional[str]]
provider: Mapped[str]
region: Mapped[str]
group = db.relationship("Group", back_populates="eotks")
group: Mapped[Group] = relationship("Group", back_populates="eotks")
@property
def brn(self) -> BRN:

View file

@ -1,7 +1,11 @@
from typing import Optional
from sqlalchemy.orm import Mapped, mapped_column
from app.extensions import db
class TerraformState(db.Model): # type: ignore
key = db.Column(db.String, primary_key=True)
state = db.Column(db.String)
lock = db.Column(db.String)
key: Mapped[str] = mapped_column(db.String, primary_key=True)
state: Mapped[str]
lock: Mapped[Optional[str]]