import os import time from base64 import b64decode, b64encode from typing import Union from urllib.parse import quote, unquote from flask import (Flask, flash, redirect, render_template, request, send_from_directory, url_for) from flask_login import LoginManager, login_required, login_user, logout_user from auth import Auth from forms import LoginForm from latosa import LaToSa from user import User app = Flask(__name__) app.config.update( SECRET_KEY=os.urandom(32), SESSION_COOKIE_HTTPONLY=True, REMEMBER_COOKIE_HTTPONLY=True, SESSION_COOKIE_SAMESITE="Strict", ) login_manager = LoginManager() login_manager.init_app(app) latosa = LaToSa(app) @login_manager.user_loader def load_user(user_id) -> Union[User, None]: for user in latosa.get_users(): if user.uid == user_id: return user return None @app.route('/', methods=['GET', 'POST']) def index(): i18n = latosa.get_i18n(request) session = request.args.get('session', None) client_id = request.args.get('client_id', None) form = LoginForm() form.session.data = session form.session.data = client_id if request.method == 'POST': username = form.username.data password = form.password.data redirect_to = url_for('admin') user = latosa.login_user(username, password) if user: login_user(user) client_id = form.client_id.data session = form.session.data if session: session = unquote(b64decode(session)) if session and client_id: session_auth = Auth() session_data = session_auth.decrypt(client_id, session) session_key = session_data['session_key'] if 'redirect_to' in session_data: response_data = { 'status': 'success', 'uid': user.uid, 'email': user.email, 'display_name': user.display_name, 'groups': user.groups, 'timestamp': time.time() } cyphertext = session_auth.encrypt(session_key, response_data) b64 = quote(b64encode(cyphertext).decode('utf-8')) url = session_data['redirect_to'] redirect_to = f'{url}?session={b64}' return redirect(redirect_to) flash(i18n['login']['failed']) return render_template('index.html', i18n=i18n, form=form) @app.route('/admin', methods=['GET']) @login_required def admin(): i18n = latosa.get_i18n(request) return render_template('admin.html', i18n=i18n) @app.route('/favicon.ico') def favicon(): return send_from_directory(os.path.join(app.root_path, 'static'), 'favicon.ico', mimetype='image/vnd.microsoft.icon')