Refactoring: new multi app structure

This commit is contained in:
2023-08-15 03:13:07 +09:00
parent 30b3efa5fc
commit e45d1af857
94 changed files with 634 additions and 1548 deletions

View File

@@ -0,0 +1,50 @@
{% load static %}
<!DOCTYPE html>
<html lang="en" data-bs-theme="auto">
<head>
<meta charset="UTF-8" />
<meta name="viewport" content="width=device-width, initial-scale=1.0" />
<link
rel="stylesheet"
href="{% static '/css/bootstrap.min.css' %}"
rel="stylesheet"
>
<link
rel="apple-touch-icon"
sizes="180x180"
href="{% static '/img/apple-touch-icon.png' %}"
>
<link
rel="icon"
type="image/png"
sizes="32x32"
href="{% static '/img/favicon-32x32.png' %}"
>
<link
rel="icon"
type="image/png"
sizes="16x16"
href="{% static '/img/favicon-16x16.png' %}"
>
<link
rel="manifest"
href="{% static '/img/site.webmanifest' %}"
>
<link
rel="stylesheet"
href="https://cdn.jsdelivr.net/npm/bootstrap-icons@1.10.5/font/bootstrap-icons.css"
>
{% block collector_head %}{% endblock collector_head %}
{% block account_head %}{% endblock account_head %}
</head>
<body>
{% block collector_content %}{% endblock collector_content %}
{% block account_content %}{% endblock account_content %}
<script src="{% static '/js/bootstrap.bundle.min.js' %}"></script>
<script src="{% static '/js/bs.theme.mode.js' %}"></script>
{% block collector_scripts %}{% endblock collector_scripts %}
{% block account_scripts %}{% endblock account_scripts %}
</body>
</html>

View File

@@ -0,0 +1,146 @@
{% load collector_extras %}
{% get_platforms as platforms %}
<nav class="navbar navbar-expand-lg bg-body-tertiary">
<div class="container">
<a
class="navbar-brand"
href="{% url 'collector:index' %}">Logs Collector <i class="bi bi-file-earmark-zip-fill"></i>
</a>
<button
class="navbar-toggler"
type="button"
data-bs-toggle="collapse"
data-bs-target="#navbarSupportedContent"
aria-controls="navbarSupportedContent"
aria-expanded="false"
aria-label="Переключатель навигации"
>
<span class="navbar-toggler-icon"></span>
</button>
<div class="collapse navbar-collapse" id="navbarSupportedContent">
<ul class="navbar-nav ml-auto mb-2 mb-lg-0 me-md-auto">
<li class="nav-item dropdown">
<button
class="nav-link dropdown-toggle"
role="button"
data-bs-toggle="dropdown"
aria-expanded="false"
>Tickets</button>
<ul class="dropdown-menu">
{% for platform in platforms %}
<li>
<a
class="dropdown-item {% if request.resolver_match.kwargs.platform == platform.name %}active{% endif %}"
href="{{ platform.get_absolute_url }}"
>{{ platform.pretty_name}}
</a>
</li>
{% endfor %}
<li><hr class="dropdown-divider" /></li>
<li>
<a class="dropdown-item" href="{% url 'collector:tickets' %}">
<i class="bi bi-funnel"></i> Reset filter
</a>
</li>
</ul>
</li>
<li class="nav-item">
<a class="nav-link" aria-current="page" href="{% url 'collector:create' %}">
<i class="bi bi-pencil-square"></i> New
</a>
</li>
</ul>
<!-- Search -->
<ul class="navbar-nav flex-row flex-wrap me-md-auto">
<li class="nav-item py-2 col-12 col-lg-auto">
<form class="d-flex" role="search" action="{% url 'collector:tickets' %}">
<input
class="form-control me-2"
type="search"
placeholder="Search"
aria-label="Search"
name="search"
/>
<button
class="btn btn-outline-success"
type="submit">
<i class="bi bi-search"></i>
</button>
</form>
</li>
</ul>
<!-- Right fields -->
<ul class="navbar-nav flex-row flex-wrap ms-md-auto">
<!-- User settings -->
{% if request.user.is_authenticated %}
<li class="nav-item py-2 py-lg-1 col-12 col-lg-auto">
<div class="btn-group">
<button type="button" class="btn btn-outline-secondary">
<i class="bi bi-person-square"></i> {{ request.user }}
</button>
<button
type="button"
class="btn btn-outline-secondary dropdown-toggle dropdown-toggle-split"
data-bs-toggle="dropdown"
aria-expanded="false"
>
<span class="visually-hidden">Toggle Dropdown</span>
</button>
<ul class="dropdown-menu dropdown-menu-end">
{% if request.user.is_staff %}
<li>
<a class="dropdown-item" type="button" href="{% url 'admin:index' %}"
><i class="bi bi-shield-shaded"></i> Admin</a>
</li>
{% endif %}
<li>
<a class="dropdown-item" type="button" href="{% url 'swagger-ui' %}"
><i class="bi bi-braces-asterisk"></i> Swagger</a>
</li>
<li>
<a
href="{% url 'two_factor:profile' %}"
class="dropdown-item"
type="button">
<i class="bi bi-gear"></i> Settings
</a>
</li>
<li><hr class="dropdown-divider" /></li>
<li>
<a
href="{% url 'account:logout' %}"
class="dropdown-item"
type="button"><i class="bi bi-door-closed"></i> Logout
</a>
</li>
</ul>
</div>
</li>
{% else %}
<li class="nav-item py-2 py-lg-1 col-12 col-lg-auto">
<div class="btn-group">
<a
type="button"
href="{% url 'two_factor:login' %}"
class="btn btn-outline-secondary"
>
<i class="bi bi-box-arrow-in-right"></i></i> Login
</a>
</div>
</li>
{% endif %}
<!-- Separator -->
<li class="nav-item py-2 py-lg-1 col-12 col-lg-auto">
<div class="vr d-none d-lg-flex h-100 mx-lg-2 text-white"></div>
<hr class="d-lg-none my-2 text-white-50">
</li>
<!-- Theme switcher-->
<li class="nav-item dropdown">
<div class="dropdown bd-mode-toggle">
{% include 'includes/theme_switcher.html' %}
</div>
</li>
</ul>
</div>
</div>
</nav>

View File

@@ -22,7 +22,7 @@
/>
</symbol>
</svg>
<!--Theme switcher buttons-->
<!-- Theme switcher dropdown buttons -->
<button
class="btn btn-bd-primary py-2 dropdown-toggle d-flex align-items-center"
id="bd-theme"

Before

Width:  |  Height:  |  Size: 3.9 KiB

After

Width:  |  Height:  |  Size: 3.9 KiB

View File

@@ -1,42 +1,18 @@
{% extends 'base.html' %}
{% load static %}
<!DOCTYPE html>
<html lang="en" data-bs-theme="auto">
<head>
{% include 'collector/includes/metalinks.html' %}
<title>Collector - {% block title %}{% endblock %}</title>
{% block extra_media %}{% endblock %}
</head>
<body>
<!-- Two factor auth-->
<section>
<header>
{% block 'navigation' %}{% endblock 'navigation' %}
</header>
</section>
<section>
<main>
<div
class="d-flex min-vh-100 align-items-center py-4 bg-body-tertiary"
cz-shortcut-listen="true" >
{% block content_wrapper %}
<div class="container">
<div class="row">{% block content %}{% endblock %}</div>
</div>
{% endblock %}
</div>
</main>
</section>
<!-- Theme switcher-->
<section>
<footer>
<div
class="dropdown position-fixed bottom-0 end-0 mb-3 me-3 bd-mode-toggle"
>
{% include 'collector/includes/theme_swither.html' %}
</div>
</footer>
</section>
<script src="{% static 'collector/js/bootstrap.bundle.min.js' %}"></script>
<script src="{% static 'collector/js/bs.theme.mode.js' %}"></script>
</body>
</html>
{% block account_head %}
<title>Collector - {% block title %}{% endblock %}</title>
{% block extra_media %}{% endblock %}
{% endblock account_head %}
{% block account_content %}
{% block content_wrapper %}
{% block content %}{% endblock %}
{% endblock %}
<section>
<footer>
{% block theme_switcher %}{% endblock %}
</footer>
</section>
{% endblock account_content %}

View File

@@ -1,11 +1,22 @@
{% extends "two_factor/_base.html" %}
{% block content_wrapper %}
<div class="container">
<div class="row">
<div class="col-md-4 offset-md-4">
{% block content %}{% endblock %}
<section>
<header>
{% block nav %}{% endblock nav %}
</header>
</section>
<section>
<main>
<div class="container mt-3">
<div class="card">
<div class="card-body">
<div class="text-center">
{% block content %}{% endblock %}
</div>
</div>
</div>
</div>
</div>
</div>
</main>
</section>
{% endblock %}

View File

@@ -1,13 +1,15 @@
{% load i18n %}
{% if cancel_url %}
<a href="{{ cancel_url }}"
class="float-right btn btn-link">{% trans "Cancel" %}</a>
<a href="{{ cancel_url }}" class="float-right btn btn-link">{% trans "Cancel" %}</a>
{% endif %}
{% if wizard.steps.prev %}
<button name="wizard_goto_step" type="submit"
value="{{ wizard.steps.prev }}"
class="btn btn-secondary">{% trans "Back" %}</button>
<button
name="wizard_goto_step"
type="submit"
value="{{ wizard.steps.prev }}"
class="btn btn-secondary">{% trans "Back" %}
</button>
{% else %}
<button disabled name="" type="button" class="btn">{% trans "Back" %}</button>
{% endif %}

View File

@@ -1,18 +1,23 @@
{% extends "two_factor/_base_focus.html" %}
{% load i18n %}
{% load crispy_forms_tags %}
{% block nav %}{% include 'includes/navigation.html' %}{% endblock nav %}
{% block content %}
<h1>{% block title %}{% trans "Backup Tokens" %}{% endblock %}</h1>
<p>{% blocktrans trimmed %}Backup tokens can be used when your primary and backup
phone numbers aren't available. The backup tokens below can be used
for login verification. If you've used up all your backup tokens, you
can generate a new set of backup tokens. Only the backup tokens shown
below will be valid.{% endblocktrans %}</p>
<h1>{% block title %}{% trans "Backup Tokens" %}{% endblock %}</h1>
<div class="mb-3 d-flex justify-content-center">
<p>{% blocktrans trimmed %}Backup tokens can be used when your primary and backup
phone numbers aren't available. The backup tokens below can be used
for login verification. If you've used up all your backup tokens, you
can generate a new set of backup tokens. Only the backup tokens shown
below will be valid.{% endblocktrans %}</p>
</div>
{% if device.token_set.count %}
<ul>
<ul class="list-group">
{% for token in device.token_set.all %}
<li>{{ token.token }}</li>
<li class="list-group-item list-group-item-action">{{ token.token }}</li>
{% endfor %}
</ul>
<p>{% blocktrans %}Print these tokens and keep them somewhere safe.{% endblocktrans %}</p>
@@ -20,9 +25,11 @@
<p>{% trans "You don't have any backup codes yet." %}</p>
{% endif %}
<form method="post">{% csrf_token %}{{ form.as_p }}
<a href="{% url 'two_factor:profile'%}"
class="float-right btn btn-link">{% trans "Back to Account Security" %}</a>
<button class="btn btn-primary" type="submit">{% trans "Generate Tokens" %}</button>
<form method="post">{% csrf_token %}{{ form|crispy }}
<a
href="{% url 'two_factor:profile'%}"
class="float-right btn btn-link">{% trans "Back to Account Security" %}
</a>
<button class="btn btn-outline-primary" type="submit">{% trans "Generate Tokens" %}</button>
</form>
{% endblock %}

View File

@@ -1,4 +1,4 @@
{% extends "two_factor/_base_focus.html" %}
{% extends "two_factor/_base.html" %}
{% load i18n %}
{% load two_factor_tags %}
@@ -7,51 +7,65 @@
{% endblock %}
{% block content %}
<h1>{% block title %}{% trans "Login" %}{% endblock %}</h1>
{% if wizard.steps.current == 'auth' %}
<p>{% blocktrans %}Enter your credentials.{% endblocktrans %}</p>
{% elif wizard.steps.current == 'token' %}
<p>{{ device|as_verbose_action }}</p>
{% elif wizard.steps.current == 'backup' %}
<p>{% blocktrans trimmed %}Use this form for entering backup tokens for logging in.
These tokens have been generated for you to print and keep safe. Please
enter one of these backup tokens to login to your account.{% endblocktrans %}</p>
{% endif %}
<form action="" method="post">{% csrf_token %}
{% include "two_factor/_wizard_forms.html" %}
{# hidden submit button to enable [enter] key #}
<input type="submit" value="" hidden />
{% if other_devices %}
<p>{% trans "Or, alternatively, use one of your other authentication methods:" %}</p>
<p>
{% for other in other_devices %}
<button name="challenge_device" value="{{ other.persistent_id }}"
class="btn btn-secondary btn-block" type="submit">
{{ other|as_action }}
</button>
{% endfor %}</p>
{% endif %}
{% include "two_factor/_wizard_actions.html" %}
</form>
{% block 'backup_tokens' %}
{% if backup_tokens %}
<hr>
<div class="backup_tokens_form">
<form action="" method="post">
{% csrf_token %}
<p>{% trans "As a last resort, you can use a backup token:" %}</p>
<div class="d-flex min-vh-100 align-items-center py-4" cz-shortcut-listen="true">
<div class="container">
<div class="row">
<div class="col-md-3 offset-md-4">
<h1>{% block title %}{% trans "Login" %}{% endblock %}</h1>
{% if wizard.steps.current == 'auth' %}
<p>{% blocktrans %}Enter your credentials.{% endblocktrans %}</p>
{% elif wizard.steps.current == 'token' %}
<p>{{ device|as_verbose_action }}</p>
{% elif wizard.steps.current == 'backup' %}
<p>{% blocktrans trimmed %}Use this form for entering backup tokens for logging in.
These tokens have been generated for you to print and keep safe. Please
enter one of these backup tokens to login to your account.{% endblocktrans %}</p>
{% endif %}
<form action="" method="post">{% csrf_token %}
{% include "two_factor/_wizard_forms.html" %}
{# hidden submit button to enable [enter] key #}
<input type="submit" value="" hidden />
{% if other_devices %}
<p>{% trans "Or, alternatively, use one of your other authentication methods:" %}</p>
<p>
<button name="wizard_goto_step" type="submit" value="backup"
class="btn btn-sm btn-secondary btn-block">{% trans "Use Backup Token" %}</button>
</p>
</form>
</div>
{% endif %}
{% endblock %}
{% for other in other_devices %}
<button name="challenge_device" value="{{ other.persistent_id }}"
class="btn btn-secondary btn-block" type="submit">
{{ other|as_action }}
</button>
{% endfor %}</p>
{% endif %}
{% include "two_factor/_wizard_actions.html" %}
</form>
{% block 'backup_tokens' %}
{% if backup_tokens %}
<hr>
<div class="backup_tokens_form">
<form action="" method="post">
{% csrf_token %}
<p>{% trans "As a last resort, you can use a backup token:" %}</p>
<p>
<button name="wizard_goto_step" type="submit" value="backup"
class="btn btn-sm btn-secondary btn-block">{% trans "Use Backup Token" %}</button>
</p>
</form>
</div>
{% endif %}
{% endblock %}
</div>
</div>
</div>
</div>
{% endblock %}
<!-- Theme switcher -->
{% block theme_switcher %}
<div class="dropdown position-fixed bottom-0 end-0 mb-3 me-3 bd-mode-toggle">
{% include 'includes/theme_switcher.html' %}
</div>
{% endblock theme_switcher %}

View File

@@ -1,20 +1,35 @@
{% extends "two_factor/_base_focus.html" %}
{% extends "two_factor/_base.html" %}
{% load i18n %}
{% block content %}
<h1>{% block title %}{% trans "Permission Denied" %}{% endblock %}</h1>
<div class="d-flex min-vh-100 align-items-center py-4" cz-shortcut-listen="true">
<div class="container">
<div class="row">
<div class="col-md-4 offset-md-4">
<h1>{% block title %}{% trans "Permission Denied" %}{% endblock %}</h1>
<p>{% blocktrans trimmed %}The page you requested, enforces users to verify using
two-factor authentication for security reasons. You need to enable these
security features in order to access this page.{% endblocktrans %}</p>
<p>{% blocktrans trimmed %}Two-factor authentication is not enabled for your
account. Enable two-factor authentication for enhanced account
security.{% endblocktrans %}</p>
<p>
<a href="javascript:history.go(-1)"
class="float-right btn btn-link">{% trans "Go back" %}</a>
<a href="{% url 'two_factor:setup' %}" class="btn btn-primary">
{% trans "Enable Two-Factor Authentication" %}</a>
</p>
<p>{% blocktrans trimmed %}The page you requested, enforces users to verify using
two-factor authentication for security reasons. You need to enable these
security features in order to access this page.{% endblocktrans %}</p>
<p>{% blocktrans trimmed %}Two-factor authentication is not enabled for your
account. Enable two-factor authentication for enhanced account
security.{% endblocktrans %}</p>
<p>
<a href="javascript:history.go(-1)"
class="float-right btn btn-link">{% trans "Go back" %}</a>
<a href="{% url 'two_factor:setup' %}" class="btn btn-primary">
{% trans "Enable Two-Factor Authentication" %}</a>
</p>
</div>
</div>
</div>
</div>
{% endblock %}
<!-- Theme switcher -->
{% block theme_switcher %}
<div class="dropdown position-fixed bottom-0 end-0 mb-3 me-3 bd-mode-toggle">
{% include 'includes/theme_switcher.html' %}
</div>
{% endblock theme_switcher %}

View File

@@ -5,6 +5,8 @@
{{ form.media }}
{% endblock %}
{% block nav %}{% include 'includes/navigation.html' %}{% endblock nav %}
{% block content %}
<h1>{% block title %}{% trans "Enable Two-Factor Authentication" %}{% endblock %}</h1>
{% if wizard.steps.current == 'welcome' %}
@@ -52,13 +54,14 @@
token in the field below. Your YubiKey will be linked to your
account.{% endblocktrans %}</p>
{% endif %}
<div class="input-group mb-3 d-flex justify-content-center">
<form action="" method="post">{% csrf_token %}
{% include "two_factor/_wizard_forms.html" %}
<form action="" method="post">{% csrf_token %}
{% include "two_factor/_wizard_forms.html" %}
{# hidden submit button to enable [enter] key #}
<input type="submit" value="" hidden />
{# hidden submit button to enable [enter] key #}
<input type="submit" value="" hidden />
{% include "two_factor/_wizard_actions.html" %}
</form>
{% include "two_factor/_wizard_actions.html" %}
</form>
</div>
{% endblock %}

View File

@@ -1,6 +1,8 @@
{% extends "two_factor/_base_focus.html" %}
{% load i18n %}
{% block nav %}{% include 'includes/navigation.html' %}{% endblock nav %}
{% block content %}
<h1>{% block title %}{% trans "Enable Two-Factor Authentication" %}{% endblock %}</h1>

View File

@@ -1,14 +1,19 @@
{% extends "two_factor/_base_focus.html" %}
{% load i18n %}
{% load crispy_forms_tags %}
{% block nav %}{% include 'includes/navigation.html' %}{% endblock nav %}
{% block content %}
<h1>{% block title %}{% trans "Disable Two-factor Authentication" %}{% endblock %}</h1>
<p>{% blocktrans trimmed %}You are about to disable two-factor authentication. This
weakens your account security, are you sure?{% endblocktrans %}</p>
<h1>{% block title %}{% trans "Disable Two-factor Authentication" %}{% endblock %}</h1>
<p>{% blocktrans trimmed %}You are about to disable two-factor authentication. This
weakens your account security, are you sure?{% endblocktrans %}</p>
<div class="input-group mb-3 d-flex justify-content-center">
<form method="post">
{% csrf_token %}
<table>{{ form.as_table }}</table>
<button class="btn btn-danger"
type="submit">{% trans "Disable" %}</button>
<div>{{ form|crispy }}</div>
<button class="btn btn-danger" type="submit">{% trans "Disable" %}</button>
</form>
</div>
{% endblock %}

View File

@@ -1,62 +1,59 @@
{% extends "two_factor/_base.html" %}
{% extends "two_factor/_base_focus.html" %}
{% load i18n %}
{% load two_factor_tags %}
{% block 'navigation' %}
{% include 'collector/includes/navigation.html' %}
{% endblock 'navigation' %}
{% block nav %}{% include 'includes/navigation.html' %}{% endblock nav %}
{% block content %}
<h1>{% block title %}{% trans "Account Security" %}{% endblock %}</h1>
<h1>{% block title %}{% trans "Account Security" %}{% endblock %}</h1>
{% if default_device %}
<p>{% blocktrans with primary=default_device|as_action %}Primary method: {{ primary }}{% endblocktrans %}</p>
{% if default_device %}
<p>{% blocktrans with primary=default_device|as_action %}Primary method: {{ primary }}{% endblocktrans %}</p>
{% if available_phone_methods %}
<h2>{% trans "Backup Phone Numbers" %}</h2>
<p>{% blocktrans trimmed %}If your primary method is not available, we are able to
send backup tokens to the phone numbers listed below.{% endblocktrans %}</p>
<ul>
{% for phone in backup_phones %}
<li>
{{ phone|as_action }}
<form method="post" action="{% url 'two_factor:phone_delete' phone.id %}"
onsubmit="return confirm({% trans 'Are you sure?' %})">
{% csrf_token %}
<button class="btn btn-sm btn-warning"
type="submit">{% trans "Unregister" %}</button>
</form>
</li>
{% endfor %}
</ul>
<p><a href="{% url 'two_factor:phone_create' %}"
class="btn btn-info">{% trans "Add Phone Number" %}</a></p>
{% endif %}
<h2>{% trans "Backup Tokens" %}</h2>
<p>
{% blocktrans trimmed %}If you don't have any device with you, you can access
your account using backup tokens.{% endblocktrans %}
{% blocktrans trimmed count counter=backup_tokens %}
You have only one backup token remaining.
{% plural %}
You have {{ counter }} backup tokens remaining.
{% endblocktrans %}
</p>
<p><a href="{% url 'two_factor:backup_tokens' %}"
class="btn btn-info">{% trans "Show Codes" %}</a></p>
{% if available_phone_methods %}
<h2>{% trans "Backup Phone Numbers" %}</h2>
<p>{% blocktrans trimmed %}If your primary method is not available, we are able to
send backup tokens to the phone numbers listed below.{% endblocktrans %}</p>
<ul>
{% for phone in backup_phones %}
<li>
{{ phone|as_action }}
<form method="post" action="{% url 'two_factor:phone_delete' phone.id %}"
onsubmit="return confirm({% trans 'Are you sure?' %})">
{% csrf_token %}
<button class="btn btn-sm btn-warning"
type="submit">{% trans "Unregister" %}</button>
</form>
</li>
{% endfor %}
</ul>
<p><a href="{% url 'two_factor:phone_create' %}"
class="btn btn-info">{% trans "Add Phone Number" %}</a></p>
{% endif %}
<h2>{% trans "Backup Tokens" %}</h2>
<p>
{% blocktrans trimmed %}If you don't have any device with you, you can access
your account using backup tokens.{% endblocktrans %}
{% blocktrans trimmed count counter=backup_tokens %}
You have only one backup token remaining.
{% plural %}
You have {{ counter }} backup tokens remaining.
{% endblocktrans %}
</p>
<p><a href="{% url 'two_factor:backup_tokens' %}"
class="btn btn-info">{% trans "Show Codes" %}</a></p>
<h3>{% trans "Disable Two-Factor Authentication" %}</h3>
<p>{% blocktrans trimmed %}However we strongly discourage you to do so, you can
also disable two-factor authentication for your account.{% endblocktrans %}</p>
<p><a class="btn btn-secondary" href="{% url 'two_factor:disable' %}">
{% trans "Disable Two-Factor Authentication" %}</a></p>
{% else %}
<p>{% blocktrans trimmed %}Two-factor authentication is not enabled for your
account. Enable two-factor authentication for enhanced account
security.{% endblocktrans %}</p>
<p><a href="{% url 'two_factor:setup' %}" class="btn btn-primary">
{% trans "Enable Two-Factor Authentication" %}</a>
</p>
{% endif %}
<h3>{% trans "Disable Two-Factor Authentication" %}</h3>
<p>{% blocktrans trimmed %}However we strongly discourage you to do so, you can
also disable two-factor authentication for your account.{% endblocktrans %}</p>
<p><a class="btn btn-secondary" href="{% url 'two_factor:disable' %}">
{% trans "Disable Two-Factor Authentication" %}</a></p>
{% else %}
<p>{% blocktrans trimmed %}Two-factor authentication is not enabled for your
account. Enable two-factor authentication for enhanced account
security.{% endblocktrans %}</p>
<p><a href="{% url 'two_factor:setup' %}" class="btn btn-primary">
{% trans "Enable Two-Factor Authentication" %}</a>
</p>
{% endif %}
{% endblock %}