sudo mode
This commit is contained in:
parent
35f0c094fe
commit
f79eb90d2a
|
@ -9,6 +9,7 @@ from .views import (
|
||||||
api_key,
|
api_key,
|
||||||
custom_domain,
|
custom_domain,
|
||||||
alias_contact_manager,
|
alias_contact_manager,
|
||||||
|
enter_sudo,
|
||||||
mfa_setup,
|
mfa_setup,
|
||||||
mfa_cancel,
|
mfa_cancel,
|
||||||
fido_setup,
|
fido_setup,
|
||||||
|
|
31
app/dashboard/templates/dashboard/enter_sudo.html
Normal file
31
app/dashboard/templates/dashboard/enter_sudo.html
Normal file
|
@ -0,0 +1,31 @@
|
||||||
|
{% extends 'default.html' %}
|
||||||
|
{% set active_page = "setting" %}
|
||||||
|
{% block title %}
|
||||||
|
SUDO MODE
|
||||||
|
{% endblock %}
|
||||||
|
|
||||||
|
|
||||||
|
{% block default_content %}
|
||||||
|
<div class="card">
|
||||||
|
<div class="card-body">
|
||||||
|
<h1 class="h2">Entering Sudo Mode</h1>
|
||||||
|
<p>
|
||||||
|
You are trying to change sensitive settings
|
||||||
|
</p>
|
||||||
|
<p>
|
||||||
|
Please enter the password of your account so that we can ensure it's you.
|
||||||
|
</p>
|
||||||
|
|
||||||
|
<form method="post">
|
||||||
|
{{ password_check_form.csrf_token }}
|
||||||
|
|
||||||
|
<div class="font-weight-bold mt-5">Password</div>
|
||||||
|
|
||||||
|
{{ password_check_form.password(class="form-control", autofocus="true") }}
|
||||||
|
{{ render_field_errors(password_check_form.password) }}
|
||||||
|
<button class="btn btn-lg btn-danger mt-2">Submit</button>
|
||||||
|
</form>
|
||||||
|
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
{% endblock %}
|
55
app/dashboard/views/enter_sudo.py
Normal file
55
app/dashboard/views/enter_sudo.py
Normal file
|
@ -0,0 +1,55 @@
|
||||||
|
from time import time
|
||||||
|
|
||||||
|
from flask import render_template, flash, redirect, url_for, session, request
|
||||||
|
from flask_login import login_required, current_user
|
||||||
|
from flask_wtf import FlaskForm
|
||||||
|
from wtforms import PasswordField, validators
|
||||||
|
from functools import wraps
|
||||||
|
|
||||||
|
from app.dashboard.base import dashboard_bp
|
||||||
|
from app.config import DEBUG
|
||||||
|
from app.log import LOG
|
||||||
|
|
||||||
|
|
||||||
|
class LoginForm(FlaskForm):
|
||||||
|
password = PasswordField("Password", validators=[validators.DataRequired()])
|
||||||
|
|
||||||
|
|
||||||
|
@dashboard_bp.route("/enter_sudo", methods=["GET", "POST"])
|
||||||
|
@login_required
|
||||||
|
def enter_sudo():
|
||||||
|
password_check_form = LoginForm()
|
||||||
|
|
||||||
|
if password_check_form.validate_on_submit():
|
||||||
|
password = password_check_form.password.data
|
||||||
|
|
||||||
|
if current_user.check_password(password):
|
||||||
|
session["sudo_time"] = int(time())
|
||||||
|
|
||||||
|
# User comes to sudo page from another page
|
||||||
|
next_url = request.args.get("next")
|
||||||
|
if next_url:
|
||||||
|
LOG.debug("redirect user to %s", next_url)
|
||||||
|
return redirect(next_url)
|
||||||
|
else:
|
||||||
|
LOG.debug("redirect user to dashboard")
|
||||||
|
return redirect(url_for("dashboard.index"))
|
||||||
|
else:
|
||||||
|
flash("Incorrect password", "warning")
|
||||||
|
|
||||||
|
return render_template(
|
||||||
|
"dashboard/enter_sudo.html", password_check_form=password_check_form
|
||||||
|
)
|
||||||
|
|
||||||
|
def sudo_required(f):
|
||||||
|
@wraps(f)
|
||||||
|
def wrap(*args, **kwargs):
|
||||||
|
# Reset sudo mode in every 20s under dev mode
|
||||||
|
SUDO_GAP = 900 if not DEBUG else 20
|
||||||
|
if "sudo_time" not in session or (time() - int(session["sudo_time"])) > SUDO_GAP:
|
||||||
|
return redirect(
|
||||||
|
url_for("dashboard.enter_sudo", next=request.path)
|
||||||
|
)
|
||||||
|
return f(*args, **kwargs)
|
||||||
|
|
||||||
|
return wrap
|
|
@ -1,6 +1,7 @@
|
||||||
import json
|
import json
|
||||||
import secrets
|
import secrets
|
||||||
import uuid
|
import uuid
|
||||||
|
from time import time
|
||||||
|
|
||||||
import webauthn
|
import webauthn
|
||||||
from flask import render_template, flash, redirect, url_for, session
|
from flask import render_template, flash, redirect, url_for, session
|
||||||
|
@ -13,7 +14,7 @@ from app.dashboard.base import dashboard_bp
|
||||||
from app.extensions import db
|
from app.extensions import db
|
||||||
from app.log import LOG
|
from app.log import LOG
|
||||||
from app.models import FIDO
|
from app.models import FIDO
|
||||||
|
from app.dashboard.views.enter_sudo import sudo_required
|
||||||
|
|
||||||
class FidoTokenForm(FlaskForm):
|
class FidoTokenForm(FlaskForm):
|
||||||
sk_assertion = HiddenField("sk_assertion", validators=[validators.DataRequired()])
|
sk_assertion = HiddenField("sk_assertion", validators=[validators.DataRequired()])
|
||||||
|
@ -21,6 +22,7 @@ class FidoTokenForm(FlaskForm):
|
||||||
|
|
||||||
@dashboard_bp.route("/fido_setup", methods=["GET", "POST"])
|
@dashboard_bp.route("/fido_setup", methods=["GET", "POST"])
|
||||||
@login_required
|
@login_required
|
||||||
|
@sudo_required
|
||||||
def fido_setup():
|
def fido_setup():
|
||||||
if not current_user.can_use_fido:
|
if not current_user.can_use_fido:
|
||||||
flash(
|
flash(
|
||||||
|
|
|
@ -7,6 +7,7 @@ from wtforms import StringField, validators
|
||||||
from app.dashboard.base import dashboard_bp
|
from app.dashboard.base import dashboard_bp
|
||||||
from app.extensions import db
|
from app.extensions import db
|
||||||
from app.models import RecoveryCode
|
from app.models import RecoveryCode
|
||||||
|
from app.dashboard.views.enter_sudo import sudo_required
|
||||||
|
|
||||||
|
|
||||||
class OtpTokenForm(FlaskForm):
|
class OtpTokenForm(FlaskForm):
|
||||||
|
@ -15,6 +16,7 @@ class OtpTokenForm(FlaskForm):
|
||||||
|
|
||||||
@dashboard_bp.route("/mfa_cancel", methods=["GET", "POST"])
|
@dashboard_bp.route("/mfa_cancel", methods=["GET", "POST"])
|
||||||
@login_required
|
@login_required
|
||||||
|
@sudo_required
|
||||||
def mfa_cancel():
|
def mfa_cancel():
|
||||||
if not current_user.enable_otp:
|
if not current_user.enable_otp:
|
||||||
flash("you don't have MFA enabled", "warning")
|
flash("you don't have MFA enabled", "warning")
|
||||||
|
|
|
@ -7,6 +7,7 @@ from wtforms import StringField, validators
|
||||||
from app.dashboard.base import dashboard_bp
|
from app.dashboard.base import dashboard_bp
|
||||||
from app.extensions import db
|
from app.extensions import db
|
||||||
from app.log import LOG
|
from app.log import LOG
|
||||||
|
from app.dashboard.views.enter_sudo import sudo_required
|
||||||
|
|
||||||
|
|
||||||
class OtpTokenForm(FlaskForm):
|
class OtpTokenForm(FlaskForm):
|
||||||
|
@ -15,6 +16,7 @@ class OtpTokenForm(FlaskForm):
|
||||||
|
|
||||||
@dashboard_bp.route("/mfa_setup", methods=["GET", "POST"])
|
@dashboard_bp.route("/mfa_setup", methods=["GET", "POST"])
|
||||||
@login_required
|
@login_required
|
||||||
|
@sudo_required
|
||||||
def mfa_setup():
|
def mfa_setup():
|
||||||
if current_user.enable_otp:
|
if current_user.enable_otp:
|
||||||
flash("you have already enabled MFA", "warning")
|
flash("you have already enabled MFA", "warning")
|
||||||
|
|
Loading…
Reference in a new issue