# -*- coding: UTF-8 -* """app.auth.logic.py """ import http import flask from flask import current_app, g, redirect, request, url_for from flask_httpauth import HTTPBasicAuth, HTTPTokenAuth import flask_login from app import db, log, login from app.auth.models import User, Role from app.models.config import ScoDocSiteConfig from app.scodoc.sco_utils import json_error basic_auth = HTTPBasicAuth() token_auth = HTTPTokenAuth() @basic_auth.verify_password def verify_password(username, password) -> User | None: """Verify password for this user Appelé lors d'une demande de jeton (normalement via la route /tokens) """ user: User = User.query.filter_by(user_name=username).first() if user and user.check_password(password): g.current_user = user # note: est aussi basic_auth.current_user() return user return None @basic_auth.error_handler def basic_auth_error(status): "error response (401 for invalid auth.)" return json_error(status) @login.user_loader def load_user(uid: str) -> User: "flask-login: accès à un utilisateur" return db.session.get(User, int(uid)) @token_auth.verify_token def verify_token(token) -> User: """Retrouve l'utilisateur à partir du jeton. Si la requête n'a pas de jeton, token == "". """ user = User.check_token(token) if token else None if user is not None: flask_login.login_user(user) g.current_user = user return user @token_auth.error_handler def token_auth_error(status): "Réponse en cas d'erreur d'auth." return json_error(status) @token_auth.get_user_roles def get_user_roles(user) -> list[Role]: "list roles" return user.roles @login.request_loader def load_user_from_request(req: flask.Request) -> User: """Custom Login using Request Loader""" # Try token try: auth_type, token = req.headers["Authorization"].split(None, 1) except (ValueError, KeyError): # The Authorization header is either empty or has no token return None if auth_type == "Bearer" and token: return verify_token(token) return None @login.unauthorized_handler def unauthorized(): "flask-login: si pas autorisé, redirige vers page login, sauf si API" if request.blueprint in ("api", "apiweb"): return json_error(http.HTTPStatus.UNAUTHORIZED, "Non autorise (logic)") return redirect(url_for("auth.login")) def logout() -> flask.Response: """Logout the current user: If CAS session, logout from CAS. Redirect.""" if flask_login.current_user: user_name = getattr(flask_login.current_user, "user_name", "anonymous") current_app.logger.info(f"logout user {user_name}") flask_login.logout_user() if ScoDocSiteConfig.is_cas_enabled() and flask.session.get("scodoc_cas_login_date"): flask.session.pop("scodoc_cas_login_date", None) return redirect(url_for("cas.logout")) return redirect(url_for("scodoc.index"))