diff --git a/app/portal/automation.py b/app/portal/automation.py index e3e8aa2..6edd3d2 100644 --- a/app/portal/automation.py +++ b/app/portal/automation.py @@ -14,6 +14,12 @@ from app.portal.util import view_lifecycle, response_404 bp = Blueprint("automation", __name__) +_SECTION_TEMPLATE_VARS = { + "section": "automation", + "help_url": "https://bypass.censorship.guide/user/automation.html" +} + + class EditAutomationForm(FlaskForm): # type: ignore enabled = BooleanField('Enabled') submit = SubmitField('Save Changes') @@ -28,10 +34,10 @@ def automation_list() -> ResponseReturnValue: automations )) return render_template("list.html.j2", - section="automation", title="Automation Jobs", item="automation", - items=automations) + items=automations, + **_SECTION_TEMPLATE_VARS) @bp.route('/edit/', methods=['GET', 'POST']) @@ -39,9 +45,9 @@ def automation_edit(automation_id: int) -> ResponseReturnValue: automation: Optional[Automation] = Automation.query.filter(Automation.id == automation_id).first() if automation is None: return Response(render_template("error.html.j2", - section="automation", header="404 Automation Job Not Found", - message="The requested automation job could not be found."), + message="The requested automation job could not be found.", + **_SECTION_TEMPLATE_VARS), status=404) form = EditAutomationForm(enabled=automation.enabled) if form.validate_on_submit(): @@ -53,8 +59,9 @@ def automation_edit(automation_id: int) -> ResponseReturnValue: except exc.SQLAlchemyError: flash("An error occurred saving the changes to the bridge configuration.", "danger") return render_template("automation.html.j2", - section="automation", - automation=automation, form=form) + automation=automation, + form=form, + **_SECTION_TEMPLATE_VARS) @bp.route("/kick/", methods=['GET', 'POST']) @@ -69,7 +76,7 @@ def automation_kick(automation_id: int) -> ResponseReturnValue: message=automation.description, success_view="portal.automation.automation_list", success_message="This automation job will next run within 1 minute.", - section="automation", resource=automation, - action="kick" + action="kick", + **_SECTION_TEMPLATE_VARS ) diff --git a/app/portal/bridge.py b/app/portal/bridge.py index c6a20fe..0acdff8 100644 --- a/app/portal/bridge.py +++ b/app/portal/bridge.py @@ -10,14 +10,20 @@ from app.portal.util import LifecycleForm bp = Blueprint("bridge", __name__) +_SECTION_TEMPLATE_VARS = { + "section": "bridge", + "help_url": "https://bypass.censorship.guide/user/bridges.html" +} + + @bp.route("/list") def bridge_list() -> ResponseReturnValue: bridges = Bridge.query.filter(Bridge.destroyed.is_(None)).all() return render_template("list.html.j2", - section="bridge", title="Tor Bridges", item="bridge", - items=bridges) + items=bridges, + **_SECTION_TEMPLATE_VARS) @bp.route("/block/", methods=['GET', 'POST']) @@ -26,7 +32,8 @@ def bridge_blocked(bridge_id: int) -> ResponseReturnValue: if bridge is None: return Response(render_template("error.html.j2", header="404 Proxy Not Found", - message="The requested bridge could not be found.")) + message="The requested bridge could not be found.", + **_SECTION_TEMPLATE_VARS)) form = LifecycleForm() if form.validate_on_submit(): bridge.deprecate(reason="manual") @@ -36,5 +43,5 @@ def bridge_blocked(bridge_id: int) -> ResponseReturnValue: return render_template("lifecycle.html.j2", header=f"Mark bridge {bridge.hashed_fingerprint} as blocked?", message=bridge.hashed_fingerprint, - section="bridge", - form=form) + form=form, + **_SECTION_TEMPLATE_VARS) diff --git a/app/portal/bridgeconf.py b/app/portal/bridgeconf.py index 2d3bdcc..1b6d697 100644 --- a/app/portal/bridgeconf.py +++ b/app/portal/bridgeconf.py @@ -16,6 +16,12 @@ from app.portal.util import response_404, view_lifecycle bp = Blueprint("bridgeconf", __name__) +_SECTION_TEMPLATE_VARS = { + "section": "bridgeconf", + "help_url": "https://bypass.censorship.guide/user/bridges.html" +} + + class NewBridgeConfForm(FlaskForm): # type: ignore provider = SelectField('Provider', validators=[DataRequired()]) method = SelectField('Distribution Method', validators=[DataRequired()]) @@ -35,11 +41,11 @@ class EditBridgeConfForm(FlaskForm): # type: ignore def bridgeconf_list() -> ResponseReturnValue: bridgeconfs: List[BridgeConf] = BridgeConf.query.filter(BridgeConf.destroyed.is_(None)).all() return render_template("list.html.j2", - section="bridgeconf", title="Tor Bridge Configurations", item="bridge configuration", items=bridgeconfs, - new_link=url_for("portal.bridgeconf.bridgeconf_new")) + new_link=url_for("portal.bridgeconf.bridgeconf_new"), + **_SECTION_TEMPLATE_VARS) @bp.route("/new", methods=['GET', 'POST']) @@ -79,7 +85,9 @@ def bridgeconf_new(group_id: Optional[int] = None) -> ResponseReturnValue: return redirect(url_for("portal.bridgeconf.bridgeconf_list")) if group_id: form.group.data = group_id - return render_template("new.html.j2", section="bridgeconf", form=form) + return render_template("new.html.j2", + form=form, + **_SECTION_TEMPLATE_VARS) @bp.route('/edit/', methods=['GET', 'POST']) @@ -87,9 +95,9 @@ def bridgeconf_edit(bridgeconf_id: int) -> ResponseReturnValue: bridgeconf = BridgeConf.query.filter(BridgeConf.id == bridgeconf_id).first() if bridgeconf is None: return Response(render_template("error.html.j2", - section="bridge", header="404 Bridge Configuration Not Found", - message="The requested bridge configuration could not be found."), + message="The requested bridge configuration could not be found.", + **_SECTION_TEMPLATE_VARS), status=404) form = EditBridgeConfForm(description=bridgeconf.description, number=bridgeconf.number) @@ -103,8 +111,9 @@ def bridgeconf_edit(bridgeconf_id: int) -> ResponseReturnValue: except exc.SQLAlchemyError: flash("An error occurred saving the changes to the bridge configuration.", "danger") return render_template("bridgeconf.html.j2", - section="bridgeconf", - bridgeconf=bridgeconf, form=form) + bridgeconf=bridgeconf, + form=form, + **_SECTION_TEMPLATE_VARS) @bp.route("/destroy/", methods=['GET', 'POST']) @@ -117,7 +126,7 @@ def bridgeconf_destroy(bridgeconf_id: int) -> ResponseReturnValue: message=bridgeconf.description, success_view="portal.bridgeconf.bridgeconf_list", success_message="All bridges from the destroyed configuration will shortly be destroyed at their providers.", - section="bridgeconf", resource=bridgeconf, - action="destroy" + action="destroy", + **_SECTION_TEMPLATE_VARS ) diff --git a/app/portal/eotk.py b/app/portal/eotk.py index ef2eaa8..79f08ee 100644 --- a/app/portal/eotk.py +++ b/app/portal/eotk.py @@ -8,14 +8,20 @@ from app.models.onions import Eotk bp = Blueprint("eotk", __name__) +_SECTION_TEMPLATE_VARS = { + "section": "eotk", + "help_url": "https://bypass.censorship.guide/user/eotk.html" +} + + @bp.route("/list") def eotk_list() -> ResponseReturnValue: instances = Eotk.query.filter(Eotk.destroyed.is_(None)).order_by(desc(Eotk.added)).all() return render_template("list.html.j2", - section="eotk", title="EOTK Instances", item="eotk", - items=instances) + items=instances, + **_SECTION_TEMPLATE_VARS) @bp.route("/conf/") diff --git a/app/portal/list.py b/app/portal/list.py index 37efed8..77e7cb7 100644 --- a/app/portal/list.py +++ b/app/portal/list.py @@ -19,6 +19,12 @@ from app.portal.util import response_404, view_lifecycle bp = Blueprint("list", __name__) +_SECTION_TEMPLATE_VARS = { + "section": "list", + "help_url": "https://bypass.censorship.guide/user/lists.html" +} + + @bp.app_template_filter("provider_name") def list_provider_name(key: str) -> str: return MirrorList.providers_supported.get(key, "Unknown") @@ -38,7 +44,6 @@ def list_encoding_name(key: str) -> str: def list_list() -> ResponseReturnValue: lists = MirrorList.query.filter(MirrorList.destroyed.is_(None)).all() return render_template("list.html.j2", - section="list", title="Distribution Lists", item="distribution list", new_link=url_for("portal.list.list_new"), @@ -50,7 +55,8 @@ def list_list() -> ResponseReturnValue: "style": "secondary" } for k, v in MirrorList.formats_supported.items() - ] + ], + **_SECTION_TEMPLATE_VARS ) @@ -110,7 +116,9 @@ def list_new(group_id: Optional[int] = None) -> ResponseReturnValue: return redirect(url_for("portal.list.list_list")) if group_id: form.group.data = group_id - return render_template("new.html.j2", section="list", form=form) + return render_template("new.html.j2", + form=form, + **_SECTION_TEMPLATE_VARS) class NewMirrorListForm(FlaskForm): # type: ignore @@ -134,9 +142,9 @@ def list_edit(list_id: int) -> ResponseReturnValue: list_: Optional[MirrorList] = MirrorList.query.filter(MirrorList.id == list_id).first() if list_ is None: return Response(render_template("error.html.j2", - section="list", header="404 Distribution List Not Found", - message="The requested distribution list could not be found."), + message="The requested distribution list could not be found.", + **_SECTION_TEMPLATE_VARS), status=404) form = NewMirrorListForm( provider=list_.provider, @@ -167,5 +175,5 @@ def list_edit(list_id: int) -> ResponseReturnValue: except exc.SQLAlchemyError: flash("An error occurred saving the changes to the distribution list.", "danger") return render_template("distlist.html.j2", - section="list", - list=list_, form=form) + list=list_, form=form, + **_SECTION_TEMPLATE_VARS) diff --git a/app/portal/templates/base.html.j2 b/app/portal/templates/base.html.j2 index 6d21efd..91688c2 100644 --- a/app/portal/templates/base.html.j2 +++ b/app/portal/templates/base.html.j2 @@ -49,6 +49,14 @@ autocomplete="off" autocorrect="off" autocapitalize="off" spellcheck="false" aria-label="Search"> +