mirror of
https://github.com/simple-login/app.git
synced 2024-11-10 17:35:27 +08:00
create /recovery_code page
This commit is contained in:
parent
aaa1a869ea
commit
3f7842ed3e
5 changed files with 79 additions and 0 deletions
|
@ -20,4 +20,5 @@ from .views import (
|
|||
mailbox_detail,
|
||||
refused_email,
|
||||
referral,
|
||||
recovery_code,
|
||||
)
|
||||
|
|
40
app/dashboard/templates/dashboard/recovery_code.html
Normal file
40
app/dashboard/templates/dashboard/recovery_code.html
Normal file
|
@ -0,0 +1,40 @@
|
|||
{% extends 'default.html' %}
|
||||
{% set active_page = "setting" %}
|
||||
{% block title %}
|
||||
Recovery Codes
|
||||
{% endblock %}
|
||||
|
||||
{% block default_content %}
|
||||
<div class="card">
|
||||
<div class="card-body">
|
||||
<h1 class="h3">Recovery codes</h1>
|
||||
<p>
|
||||
If you lose access to your authentication device, you can use one of these backup codes to login to your
|
||||
account. Each code may be used only once. Make a copy of these codes, and store it somewhere safe.
|
||||
</p>
|
||||
|
||||
<ul>
|
||||
{% for recovery_code in recovery_codes %}
|
||||
{% if recovery_code.used %}
|
||||
<li>
|
||||
<span style="text-decoration: line-through">{{ recovery_code.code }}</span>.
|
||||
Used {{ recovery_code.used_at | dt }}.
|
||||
</li>
|
||||
{% else %}
|
||||
<li>
|
||||
{{ recovery_code.code }}
|
||||
</li>
|
||||
{% endif %}
|
||||
{% endfor %}
|
||||
</ul>
|
||||
|
||||
<form method="post" class="mt-6">
|
||||
<input type="submit" class="btn btn-outline-primary" value="Generate New Codes">
|
||||
</form>
|
||||
<div class="small-text">
|
||||
Beware: Generating new codes invalidates all the previous ones, make sure to write down the new ones!
|
||||
</div>
|
||||
|
||||
</div>
|
||||
</div>
|
||||
{% endblock %}
|
|
@ -98,6 +98,7 @@
|
|||
<a href="{{ url_for('dashboard.fido_setup') }}" class="btn btn-outline-primary">Setup WebAuthn</a>
|
||||
{% else %}
|
||||
<a href="{{ url_for('dashboard.fido_cancel') }}" class="btn btn-outline-danger">Disable WebAuthn</a>
|
||||
<a href="{{ url_for('dashboard.recovery_code_route') }}" class="btn btn-outline-secondary">Recovery Codes</a>
|
||||
{% endif %}
|
||||
</div>
|
||||
</div>
|
||||
|
@ -114,6 +115,7 @@
|
|||
<a href="{{ url_for('dashboard.mfa_setup') }}" class="btn btn-outline-primary">Setup TOTP</a>
|
||||
{% else %}
|
||||
<a href="{{ url_for('dashboard.mfa_cancel') }}" class="btn btn-outline-danger">Disable TOTP</a>
|
||||
<a href="{{ url_for('dashboard.recovery_code_route') }}" class="btn btn-outline-secondary">Recovery Codes</a>
|
||||
{% endif %}
|
||||
</div>
|
||||
</div>
|
||||
|
|
30
app/dashboard/views/recovery_code.py
Normal file
30
app/dashboard/views/recovery_code.py
Normal file
|
@ -0,0 +1,30 @@
|
|||
from flask import render_template, flash, redirect, url_for, request
|
||||
from flask_login import login_required, current_user
|
||||
|
||||
from app.dashboard.base import dashboard_bp
|
||||
from app.log import LOG
|
||||
from app.models import RecoveryCode
|
||||
|
||||
|
||||
@dashboard_bp.route("/recovery_code", methods=["GET", "POST"])
|
||||
@login_required
|
||||
def recovery_code_route():
|
||||
if not current_user.two_factor_authentication_enabled():
|
||||
flash("you need to enable either TOTP or WebAuthn", "warning")
|
||||
return redirect(url_for("dashboard.index"))
|
||||
|
||||
recovery_codes = RecoveryCode.query.filter_by(user_id=current_user.id).all()
|
||||
if request.method == "GET" and not recovery_codes:
|
||||
# user arrives at this page for the first time
|
||||
LOG.d("%s has no recovery keys, generate", current_user)
|
||||
RecoveryCode.generate(current_user)
|
||||
recovery_codes = RecoveryCode.query.filter_by(user_id=current_user.id).all()
|
||||
|
||||
if request.method == "POST":
|
||||
RecoveryCode.generate(current_user)
|
||||
flash("New recovery codes generated", "success")
|
||||
return redirect(url_for("dashboard.recovery_code_route"))
|
||||
|
||||
return render_template(
|
||||
"dashboard/recovery_code.html", recovery_codes=recovery_codes
|
||||
)
|
|
@ -1381,3 +1381,9 @@ class RecoveryCode(db.Model, ModelMixin):
|
|||
|
||||
LOG.d("Create recovery codes for %s", user)
|
||||
db.session.commit()
|
||||
|
||||
@classmethod
|
||||
def empty(cls, user):
|
||||
"""Delete all recovery codes for user"""
|
||||
cls.query.filter_by(user_id=user.id).delete()
|
||||
db.session.commit()
|
||||
|
|
Loading…
Reference in a new issue