diff --git a/app/cli/db.py b/app/cli/db.py index 0691951..a1d81dc 100644 --- a/app/cli/db.py +++ b/app/cli/db.py @@ -54,7 +54,7 @@ def impot(model: db.Model) -> None: line[i] = None # type: ignore else: line[i] = datetime.datetime.strptime(line[i], "%Y-%m-%d %H:%M:%S.%f") # type: ignore - elif header[i] in ["eotk"]: + elif header[i] in ["eotk", "auto_rotation", "smart"]: # boolean fields line[i] = line[i] == "True" # type: ignore elif header[i].endswith("_id") and line[i] == "": diff --git a/app/models/base.py b/app/models/base.py index 12ca543..d7fb5b6 100644 --- a/app/models/base.py +++ b/app/models/base.py @@ -13,6 +13,7 @@ class Group(AbstractConfiguration): bridgeconfs = db.relationship("BridgeConf", 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") @classmethod def csv_header(cls) -> List[str]: diff --git a/app/models/mirrors.py b/app/models/mirrors.py index b305b50..91da8f2 100644 --- a/app/models/mirrors.py +++ b/app/models/mirrors.py @@ -12,6 +12,7 @@ class Origin(AbstractConfiguration): group_id = db.Column(db.Integer, db.ForeignKey("group.id"), nullable=False) domain_name = db.Column(db.String(255), unique=True, nullable=False) auto_rotation = db.Column(db.Boolean, nullable=False) + smart = db.Column(db.Boolean(), nullable=False) group = db.relationship("Group", back_populates="origins") proxies = db.relationship("Proxy", back_populates="origin") @@ -23,7 +24,7 @@ class Origin(AbstractConfiguration): @classmethod def csv_header(cls) -> List[str]: return super().csv_header() + [ - "group_id", "domain_name" + "group_id", "domain_name", "auto_rotation", "smart" ] def destroy(self) -> None: @@ -59,3 +60,16 @@ class Proxy(AbstractResource): return super().csv_header() + [ "origin_id", "provider", "psg", "slug", "terraform_updated", "url" ] + + +class SmartProxy(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 = db.relationship("Group", back_populates="smart_proxies") + + @property + def brn(self) -> str: + return f"brn:{current_app.config['GLOBAL_NAMESPACE']}:{self.group_id}:mirror:{self.provider}:smart-proxy/1" diff --git a/app/portal/__init__.py b/app/portal/__init__.py index b7c8231..6257042 100644 --- a/app/portal/__init__.py +++ b/app/portal/__init__.py @@ -21,6 +21,7 @@ from app.portal.list import bp as list_ from app.portal.origin import bp as origin from app.portal.onion import bp as onion from app.portal.proxy import bp as proxy +from app.portal.smart_proxy import bp as smart_proxy from app.portal.webhook import bp as webhook portal = Blueprint("portal", __name__, template_folder="templates", static_folder="static") @@ -33,6 +34,7 @@ portal.register_blueprint(list_, url_prefix="/list") portal.register_blueprint(origin, url_prefix="/origin") portal.register_blueprint(onion, url_prefix="/onion") portal.register_blueprint(proxy, url_prefix="/proxy") +portal.register_blueprint(smart_proxy, url_prefix="/smart") portal.register_blueprint(webhook, url_prefix="/webhook") diff --git a/app/portal/origin.py b/app/portal/origin.py index 67182a1..1c7b496 100644 --- a/app/portal/origin.py +++ b/app/portal/origin.py @@ -21,6 +21,7 @@ class NewOriginForm(FlaskForm): # type: ignore description = StringField('Description', validators=[DataRequired()]) group = SelectField('Group', validators=[DataRequired()]) auto_rotate = BooleanField("Enable auto-rotation?", default=True) + smart_proxy = BooleanField("Requires smart proxy?", default=False) submit = SubmitField('Save Changes') @@ -28,6 +29,7 @@ class EditOriginForm(FlaskForm): # type: ignore description = StringField('Description', validators=[DataRequired()]) group = SelectField('Group', validators=[DataRequired()]) auto_rotate = BooleanField("Enable auto-rotation?") + smart_proxy = BooleanField("Requires smart proxy?") submit = SubmitField('Save Changes') @@ -42,6 +44,7 @@ def origin_new(group_id: Optional[int] = None) -> ResponseReturnValue: origin.domain_name = form.domain_name.data origin.description = form.description.data origin.auto_rotation = form.auto_rotate.data + origin.smart = form.smart_proxy.data origin.created = datetime.utcnow() origin.updated = datetime.utcnow() try: @@ -69,12 +72,14 @@ def origin_edit(origin_id: int) -> ResponseReturnValue: status=404) form = EditOriginForm(group=origin.group_id, description=origin.description, - auto_rotate=origin.auto_rotation) + auto_rotate=origin.auto_rotation, + smart_proxy=origin.smart) form.group.choices = [(x.id, x.group_name) for x in Group.query.all()] if form.validate_on_submit(): origin.group_id = form.group.data origin.description = form.description.data origin.auto_rotation = form.auto_rotate.data + origin.smart = form.smart_proxy.data origin.updated = datetime.utcnow() try: db.session.commit() diff --git a/app/portal/smart_proxy.py b/app/portal/smart_proxy.py new file mode 100644 index 0000000..d744e66 --- /dev/null +++ b/app/portal/smart_proxy.py @@ -0,0 +1,17 @@ +from flask import render_template, Blueprint +from flask.typing import ResponseReturnValue +from sqlalchemy import desc + +from app.models.mirrors import SmartProxy + +bp = Blueprint("smart_proxy", __name__) + + +@bp.route("/list") +def smart_proxy_list() -> ResponseReturnValue: + instances = SmartProxy.query.filter(SmartProxy.destroyed.is_(None)).order_by(desc(SmartProxy.added)).all() + return render_template("list.html.j2", + section="smart_proxy", + title="Smart Proxy Instances", + item="smart proxy", + items=instances) diff --git a/app/portal/templates/base.html.j2 b/app/portal/templates/base.html.j2 index 76c2065..2353040 100644 --- a/app/portal/templates/base.html.j2 +++ b/app/portal/templates/base.html.j2 @@ -132,8 +132,8 @@