Release v2.2: admin auth settings, Passkey RP ID, Cloudflare and Google captcha

Co-authored-by: Cursor <cursoragent@cursor.com>
This commit is contained in:
2026-06-07 02:57:49 +03:00
parent 0a51001791
commit 0584ebdc74
18 changed files with 458 additions and 4 deletions
+34 -1
View File
@@ -2,20 +2,35 @@ from flask import Blueprint, flash, redirect, render_template, request, url_for
from flask_login import current_user, login_user, logout_user
from app import db
from app.captcha_service import verify_captcha
from app.session_service import create_user_session, revoke_current_session
from app.email_service import send_password_reset_email, send_welcome_email
from app.folder_utils import process_pending_invites
from app.models import PasswordResetToken, User, UserGroup
from app.settings_service import get_auth_public_settings, get_settings
bp = Blueprint("auth", __name__, url_prefix="/auth")
def _registration_allowed():
return get_settings().registration_enabled
@bp.route("/register", methods=["GET", "POST"])
def register():
if current_user.is_authenticated:
return redirect(url_for("cabinet.index"))
if not _registration_allowed():
flash("Регистрация новых пользователей отключена", "error")
return redirect(url_for("auth.login"))
if request.method == "POST":
ok, captcha_msg = verify_captcha(request, "register")
if not ok:
flash(captcha_msg, "error")
return render_template("auth/register.html")
username = request.form.get("username", "").strip()
email = request.form.get("email", "").strip().lower()
password = request.form.get("password", "")
@@ -58,7 +73,18 @@ def login():
if current_user.is_authenticated:
return redirect(url_for("cabinet.index"))
auth = get_auth_public_settings()
if not auth["password_login_enabled"] and not auth["passkey_enabled"]:
flash("Вход временно недоступен", "error")
return render_template("auth/login.html")
if request.method == "POST":
if auth["password_login_enabled"]:
ok, captcha_msg = verify_captcha(request, "login")
if not ok:
flash(captcha_msg, "error")
return render_template("auth/login.html")
login = request.form.get("login", "").strip()
password = request.form.get("password", "")
remember = request.form.get("remember") == "on"
@@ -67,7 +93,9 @@ def login():
(User.username == login) | (User.email == login.lower())
).first()
if user is None or not user.check_password(password):
if not auth["password_login_enabled"]:
flash("Вход по паролю отключён. Используйте Passkey.", "error")
elif user is None or not user.check_password(password):
flash("Неверный логин или пароль", "error")
elif not user.is_active:
flash("Аккаунт заблокирован", "error")
@@ -94,6 +122,11 @@ def forgot_password():
return redirect(url_for("cabinet.index"))
if request.method == "POST":
ok, captcha_msg = verify_captcha(request, "forgot_password")
if not ok:
flash(captcha_msg, "error")
return render_template("auth/forgot_password.html")
email = request.form.get("email", "").strip().lower()
user = User.query.filter_by(email=email).first()
if user: