portal: link to context-specific help where we can
This commit is contained in:
parent
2801eefd43
commit
5b9946c431
6 changed files with 76 additions and 31 deletions
|
@ -14,6 +14,12 @@ from app.portal.util import view_lifecycle, response_404
|
||||||
bp = Blueprint("automation", __name__)
|
bp = Blueprint("automation", __name__)
|
||||||
|
|
||||||
|
|
||||||
|
_SECTION_TEMPLATE_VARS = {
|
||||||
|
"section": "automation",
|
||||||
|
"help_url": "https://bypass.censorship.guide/user/automation.html"
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
class EditAutomationForm(FlaskForm): # type: ignore
|
class EditAutomationForm(FlaskForm): # type: ignore
|
||||||
enabled = BooleanField('Enabled')
|
enabled = BooleanField('Enabled')
|
||||||
submit = SubmitField('Save Changes')
|
submit = SubmitField('Save Changes')
|
||||||
|
@ -28,10 +34,10 @@ def automation_list() -> ResponseReturnValue:
|
||||||
automations
|
automations
|
||||||
))
|
))
|
||||||
return render_template("list.html.j2",
|
return render_template("list.html.j2",
|
||||||
section="automation",
|
|
||||||
title="Automation Jobs",
|
title="Automation Jobs",
|
||||||
item="automation",
|
item="automation",
|
||||||
items=automations)
|
items=automations,
|
||||||
|
**_SECTION_TEMPLATE_VARS)
|
||||||
|
|
||||||
|
|
||||||
@bp.route('/edit/<automation_id>', methods=['GET', 'POST'])
|
@bp.route('/edit/<automation_id>', 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()
|
automation: Optional[Automation] = Automation.query.filter(Automation.id == automation_id).first()
|
||||||
if automation is None:
|
if automation is None:
|
||||||
return Response(render_template("error.html.j2",
|
return Response(render_template("error.html.j2",
|
||||||
section="automation",
|
|
||||||
header="404 Automation Job Not Found",
|
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)
|
status=404)
|
||||||
form = EditAutomationForm(enabled=automation.enabled)
|
form = EditAutomationForm(enabled=automation.enabled)
|
||||||
if form.validate_on_submit():
|
if form.validate_on_submit():
|
||||||
|
@ -53,8 +59,9 @@ def automation_edit(automation_id: int) -> ResponseReturnValue:
|
||||||
except exc.SQLAlchemyError:
|
except exc.SQLAlchemyError:
|
||||||
flash("An error occurred saving the changes to the bridge configuration.", "danger")
|
flash("An error occurred saving the changes to the bridge configuration.", "danger")
|
||||||
return render_template("automation.html.j2",
|
return render_template("automation.html.j2",
|
||||||
section="automation",
|
automation=automation,
|
||||||
automation=automation, form=form)
|
form=form,
|
||||||
|
**_SECTION_TEMPLATE_VARS)
|
||||||
|
|
||||||
|
|
||||||
@bp.route("/kick/<automation_id>", methods=['GET', 'POST'])
|
@bp.route("/kick/<automation_id>", methods=['GET', 'POST'])
|
||||||
|
@ -69,7 +76,7 @@ def automation_kick(automation_id: int) -> ResponseReturnValue:
|
||||||
message=automation.description,
|
message=automation.description,
|
||||||
success_view="portal.automation.automation_list",
|
success_view="portal.automation.automation_list",
|
||||||
success_message="This automation job will next run within 1 minute.",
|
success_message="This automation job will next run within 1 minute.",
|
||||||
section="automation",
|
|
||||||
resource=automation,
|
resource=automation,
|
||||||
action="kick"
|
action="kick",
|
||||||
|
**_SECTION_TEMPLATE_VARS
|
||||||
)
|
)
|
||||||
|
|
|
@ -10,14 +10,20 @@ from app.portal.util import LifecycleForm
|
||||||
bp = Blueprint("bridge", __name__)
|
bp = Blueprint("bridge", __name__)
|
||||||
|
|
||||||
|
|
||||||
|
_SECTION_TEMPLATE_VARS = {
|
||||||
|
"section": "bridge",
|
||||||
|
"help_url": "https://bypass.censorship.guide/user/bridges.html"
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
@bp.route("/list")
|
@bp.route("/list")
|
||||||
def bridge_list() -> ResponseReturnValue:
|
def bridge_list() -> ResponseReturnValue:
|
||||||
bridges = Bridge.query.filter(Bridge.destroyed.is_(None)).all()
|
bridges = Bridge.query.filter(Bridge.destroyed.is_(None)).all()
|
||||||
return render_template("list.html.j2",
|
return render_template("list.html.j2",
|
||||||
section="bridge",
|
|
||||||
title="Tor Bridges",
|
title="Tor Bridges",
|
||||||
item="bridge",
|
item="bridge",
|
||||||
items=bridges)
|
items=bridges,
|
||||||
|
**_SECTION_TEMPLATE_VARS)
|
||||||
|
|
||||||
|
|
||||||
@bp.route("/block/<bridge_id>", methods=['GET', 'POST'])
|
@bp.route("/block/<bridge_id>", methods=['GET', 'POST'])
|
||||||
|
@ -26,7 +32,8 @@ def bridge_blocked(bridge_id: int) -> ResponseReturnValue:
|
||||||
if bridge is None:
|
if bridge is None:
|
||||||
return Response(render_template("error.html.j2",
|
return Response(render_template("error.html.j2",
|
||||||
header="404 Proxy Not Found",
|
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()
|
form = LifecycleForm()
|
||||||
if form.validate_on_submit():
|
if form.validate_on_submit():
|
||||||
bridge.deprecate(reason="manual")
|
bridge.deprecate(reason="manual")
|
||||||
|
@ -36,5 +43,5 @@ def bridge_blocked(bridge_id: int) -> ResponseReturnValue:
|
||||||
return render_template("lifecycle.html.j2",
|
return render_template("lifecycle.html.j2",
|
||||||
header=f"Mark bridge {bridge.hashed_fingerprint} as blocked?",
|
header=f"Mark bridge {bridge.hashed_fingerprint} as blocked?",
|
||||||
message=bridge.hashed_fingerprint,
|
message=bridge.hashed_fingerprint,
|
||||||
section="bridge",
|
form=form,
|
||||||
form=form)
|
**_SECTION_TEMPLATE_VARS)
|
||||||
|
|
|
@ -16,6 +16,12 @@ from app.portal.util import response_404, view_lifecycle
|
||||||
bp = Blueprint("bridgeconf", __name__)
|
bp = Blueprint("bridgeconf", __name__)
|
||||||
|
|
||||||
|
|
||||||
|
_SECTION_TEMPLATE_VARS = {
|
||||||
|
"section": "bridgeconf",
|
||||||
|
"help_url": "https://bypass.censorship.guide/user/bridges.html"
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
class NewBridgeConfForm(FlaskForm): # type: ignore
|
class NewBridgeConfForm(FlaskForm): # type: ignore
|
||||||
provider = SelectField('Provider', validators=[DataRequired()])
|
provider = SelectField('Provider', validators=[DataRequired()])
|
||||||
method = SelectField('Distribution Method', validators=[DataRequired()])
|
method = SelectField('Distribution Method', validators=[DataRequired()])
|
||||||
|
@ -35,11 +41,11 @@ class EditBridgeConfForm(FlaskForm): # type: ignore
|
||||||
def bridgeconf_list() -> ResponseReturnValue:
|
def bridgeconf_list() -> ResponseReturnValue:
|
||||||
bridgeconfs: List[BridgeConf] = BridgeConf.query.filter(BridgeConf.destroyed.is_(None)).all()
|
bridgeconfs: List[BridgeConf] = BridgeConf.query.filter(BridgeConf.destroyed.is_(None)).all()
|
||||||
return render_template("list.html.j2",
|
return render_template("list.html.j2",
|
||||||
section="bridgeconf",
|
|
||||||
title="Tor Bridge Configurations",
|
title="Tor Bridge Configurations",
|
||||||
item="bridge configuration",
|
item="bridge configuration",
|
||||||
items=bridgeconfs,
|
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'])
|
@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"))
|
return redirect(url_for("portal.bridgeconf.bridgeconf_list"))
|
||||||
if group_id:
|
if group_id:
|
||||||
form.group.data = 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/<bridgeconf_id>', methods=['GET', 'POST'])
|
@bp.route('/edit/<bridgeconf_id>', methods=['GET', 'POST'])
|
||||||
|
@ -87,9 +95,9 @@ def bridgeconf_edit(bridgeconf_id: int) -> ResponseReturnValue:
|
||||||
bridgeconf = BridgeConf.query.filter(BridgeConf.id == bridgeconf_id).first()
|
bridgeconf = BridgeConf.query.filter(BridgeConf.id == bridgeconf_id).first()
|
||||||
if bridgeconf is None:
|
if bridgeconf is None:
|
||||||
return Response(render_template("error.html.j2",
|
return Response(render_template("error.html.j2",
|
||||||
section="bridge",
|
|
||||||
header="404 Bridge Configuration Not Found",
|
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)
|
status=404)
|
||||||
form = EditBridgeConfForm(description=bridgeconf.description,
|
form = EditBridgeConfForm(description=bridgeconf.description,
|
||||||
number=bridgeconf.number)
|
number=bridgeconf.number)
|
||||||
|
@ -103,8 +111,9 @@ def bridgeconf_edit(bridgeconf_id: int) -> ResponseReturnValue:
|
||||||
except exc.SQLAlchemyError:
|
except exc.SQLAlchemyError:
|
||||||
flash("An error occurred saving the changes to the bridge configuration.", "danger")
|
flash("An error occurred saving the changes to the bridge configuration.", "danger")
|
||||||
return render_template("bridgeconf.html.j2",
|
return render_template("bridgeconf.html.j2",
|
||||||
section="bridgeconf",
|
bridgeconf=bridgeconf,
|
||||||
bridgeconf=bridgeconf, form=form)
|
form=form,
|
||||||
|
**_SECTION_TEMPLATE_VARS)
|
||||||
|
|
||||||
|
|
||||||
@bp.route("/destroy/<bridgeconf_id>", methods=['GET', 'POST'])
|
@bp.route("/destroy/<bridgeconf_id>", methods=['GET', 'POST'])
|
||||||
|
@ -117,7 +126,7 @@ def bridgeconf_destroy(bridgeconf_id: int) -> ResponseReturnValue:
|
||||||
message=bridgeconf.description,
|
message=bridgeconf.description,
|
||||||
success_view="portal.bridgeconf.bridgeconf_list",
|
success_view="portal.bridgeconf.bridgeconf_list",
|
||||||
success_message="All bridges from the destroyed configuration will shortly be destroyed at their providers.",
|
success_message="All bridges from the destroyed configuration will shortly be destroyed at their providers.",
|
||||||
section="bridgeconf",
|
|
||||||
resource=bridgeconf,
|
resource=bridgeconf,
|
||||||
action="destroy"
|
action="destroy",
|
||||||
|
**_SECTION_TEMPLATE_VARS
|
||||||
)
|
)
|
||||||
|
|
|
@ -8,14 +8,20 @@ from app.models.onions import Eotk
|
||||||
bp = Blueprint("eotk", __name__)
|
bp = Blueprint("eotk", __name__)
|
||||||
|
|
||||||
|
|
||||||
|
_SECTION_TEMPLATE_VARS = {
|
||||||
|
"section": "eotk",
|
||||||
|
"help_url": "https://bypass.censorship.guide/user/eotk.html"
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
@bp.route("/list")
|
@bp.route("/list")
|
||||||
def eotk_list() -> ResponseReturnValue:
|
def eotk_list() -> ResponseReturnValue:
|
||||||
instances = Eotk.query.filter(Eotk.destroyed.is_(None)).order_by(desc(Eotk.added)).all()
|
instances = Eotk.query.filter(Eotk.destroyed.is_(None)).order_by(desc(Eotk.added)).all()
|
||||||
return render_template("list.html.j2",
|
return render_template("list.html.j2",
|
||||||
section="eotk",
|
|
||||||
title="EOTK Instances",
|
title="EOTK Instances",
|
||||||
item="eotk",
|
item="eotk",
|
||||||
items=instances)
|
items=instances,
|
||||||
|
**_SECTION_TEMPLATE_VARS)
|
||||||
|
|
||||||
|
|
||||||
@bp.route("/conf/<group_id>")
|
@bp.route("/conf/<group_id>")
|
||||||
|
|
|
@ -19,6 +19,12 @@ from app.portal.util import response_404, view_lifecycle
|
||||||
bp = Blueprint("list", __name__)
|
bp = Blueprint("list", __name__)
|
||||||
|
|
||||||
|
|
||||||
|
_SECTION_TEMPLATE_VARS = {
|
||||||
|
"section": "list",
|
||||||
|
"help_url": "https://bypass.censorship.guide/user/lists.html"
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
@bp.app_template_filter("provider_name")
|
@bp.app_template_filter("provider_name")
|
||||||
def list_provider_name(key: str) -> str:
|
def list_provider_name(key: str) -> str:
|
||||||
return MirrorList.providers_supported.get(key, "Unknown")
|
return MirrorList.providers_supported.get(key, "Unknown")
|
||||||
|
@ -38,7 +44,6 @@ def list_encoding_name(key: str) -> str:
|
||||||
def list_list() -> ResponseReturnValue:
|
def list_list() -> ResponseReturnValue:
|
||||||
lists = MirrorList.query.filter(MirrorList.destroyed.is_(None)).all()
|
lists = MirrorList.query.filter(MirrorList.destroyed.is_(None)).all()
|
||||||
return render_template("list.html.j2",
|
return render_template("list.html.j2",
|
||||||
section="list",
|
|
||||||
title="Distribution Lists",
|
title="Distribution Lists",
|
||||||
item="distribution list",
|
item="distribution list",
|
||||||
new_link=url_for("portal.list.list_new"),
|
new_link=url_for("portal.list.list_new"),
|
||||||
|
@ -50,7 +55,8 @@ def list_list() -> ResponseReturnValue:
|
||||||
"style": "secondary"
|
"style": "secondary"
|
||||||
}
|
}
|
||||||
for k, v in MirrorList.formats_supported.items()
|
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"))
|
return redirect(url_for("portal.list.list_list"))
|
||||||
if group_id:
|
if group_id:
|
||||||
form.group.data = 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
|
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()
|
list_: Optional[MirrorList] = MirrorList.query.filter(MirrorList.id == list_id).first()
|
||||||
if list_ is None:
|
if list_ is None:
|
||||||
return Response(render_template("error.html.j2",
|
return Response(render_template("error.html.j2",
|
||||||
section="list",
|
|
||||||
header="404 Distribution List Not Found",
|
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)
|
status=404)
|
||||||
form = NewMirrorListForm(
|
form = NewMirrorListForm(
|
||||||
provider=list_.provider,
|
provider=list_.provider,
|
||||||
|
@ -167,5 +175,5 @@ def list_edit(list_id: int) -> ResponseReturnValue:
|
||||||
except exc.SQLAlchemyError:
|
except exc.SQLAlchemyError:
|
||||||
flash("An error occurred saving the changes to the distribution list.", "danger")
|
flash("An error occurred saving the changes to the distribution list.", "danger")
|
||||||
return render_template("distlist.html.j2",
|
return render_template("distlist.html.j2",
|
||||||
section="list",
|
list=list_, form=form,
|
||||||
list=list_, form=form)
|
**_SECTION_TEMPLATE_VARS)
|
||||||
|
|
|
@ -49,6 +49,14 @@
|
||||||
autocomplete="off" autocorrect="off" autocapitalize="off" spellcheck="false"
|
autocomplete="off" autocorrect="off" autocapitalize="off" spellcheck="false"
|
||||||
aria-label="Search">
|
aria-label="Search">
|
||||||
</form>
|
</form>
|
||||||
|
<div class="navbar-nav">
|
||||||
|
<div class="nav-item text-nowrap">
|
||||||
|
<a class="nav-link px-3"
|
||||||
|
href="{{ help_url | default("https://bypass.censorship.guide/") }}" target="_bypass">
|
||||||
|
{{ icon('life-preserver') }}
|
||||||
|
</a>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
<div class="navbar-nav">
|
<div class="navbar-nav">
|
||||||
<div class="nav-item text-nowrap">
|
<div class="nav-item text-nowrap">
|
||||||
<a class="nav-link px-3"
|
<a class="nav-link px-3"
|
||||||
|
|
Loading…
Add table
Add a link
Reference in a new issue