import os import sys import string import random import uuid from flask import Flask, session, render_template_string, render_template, redirect, url_for, flash, request, current_app from flask_security import Security, current_user, auth_required, hash_password, SQLAlchemySessionUserDatastore from flask_login import login_user, logout_user from flask_font_awesome import FontAwesome from flask_dance.contrib.google import make_google_blueprint, google from urllib.parse import urlencode from flask_mailman import Mail from werkzeug.middleware.proxy_fix import ProxyFix from werkzeug.security import generate_password_hash from .config import Config, ProductionConfig, DevelopmentConfig from dotenv import load_dotenv from .database import db_session, init_db from .models import User, Role from .views import views_bp fa = FontAwesome() # Create app def create_app(): app = Flask(__name__, instance_relative_config=True) app.config['MAX_CONTENT_LENGTH'] = 20 * 1024 * 1024 # Set the maximum allowed request size to 100MB debug_mode = False print("Creating app") for i, arg in enumerate(sys.argv): print("arg: " + str(arg)) if arg == "--debug": print("debug mode activé") app.config.from_object(DevelopmentConfig) debug_mode = True break print("end of variable retrieval") if not debug_mode: app.config.from_object(ProductionConfig) # Create Google OAuth blueprint google_blueprint = make_google_blueprint( client_id=app.config['GOOGLE_OAUTH_CLIENT_ID'], client_secret=app.config['GOOGLE_OAUTH_CLIENT_SECRET'], scope=["https://www.googleapis.com/auth/userinfo.email", "openid"], redirect_url="/authorized", ) # Register the Google OAuth blueprint app.register_blueprint(google_blueprint, url_prefix="/login") def google_login_url(): google_auth_url = url_for("google.login", _external=True) params = { "access_type": "offline", "prompt": "consent", } return f"{google_auth_url}?{urlencode(params)}" @app.context_processor def inject_google_login_url(): return dict(google_login_url=google_login_url) user_datastore = SQLAlchemySessionUserDatastore(db_session, User, Role) print("user_datastore retrieved in prod") app.security = Security(app, user_datastore) print("app.security initialized in prod") mail = Mail(app) app.wsgi_app = ProxyFix( app.wsgi_app, x_for=1, x_proto=1, x_host=1, x_prefix=1 ) @app.route('/authorized') def authorized(): if debug_mode: return "Not available in development mode", 404 if not google.authorized: return redirect(url_for("google.login")) resp = google.get("/oauth2/v3/tokeninfo") if not resp.ok: flash("Failed to authenticate with Google.", "danger") return redirect(url_for("views.home")) idinfo = resp.json() email = idinfo['email'] if 'name' in idinfo: name = idinfo['name'] else: name = email # Check if the user's email is in the allowed list if email not in app.config['ALLOWED_USERS']: flash("Your email is not authorized.", "danger") return redirect(url_for("views.home")) # Check if the user exists in the database user = app.security.datastore.find_user(email=email) # If the user does not exist, create a new user if not user: random_password = generate_random_password() hashed_password = generate_password_hash(random_password, method='sha256') #fs_uniquifier = str(uuid.uuid4()) user = app.security.datastore.create_user(email=email, username=name, password=hashed_password) db_session.commit() login_user(user) # Set the session variable session['logged_in_with_google'] = True # Redirect to the desired page after login, e.g., the index page return redirect(url_for("views.home")) # Register the Google authorized route only in production app.add_url_rule('/authorized', view_func=authorized) def generate_random_password(length=12): characters = string.ascii_letters + string.digits + string.punctuation return ''.join(random.choice(characters) for i in range(length)) @app.route("/logout") @auth_required() def logout(): logout_user() return redirect(url_for("views.home")) app.register_blueprint(views_bp) with app.app_context(): # Create a user to test with init_db() for user in app.config['ALLOWED_USERS']: if not (user.endswith("gmail.com") or user.endswith("thargo.io")) and not app.security.datastore.find_user(email=user): app.security.datastore.create_user(email=user, password=hash_password(generate_random_password())) db_session.commit() #from admin import admin #admin.init_app(app) fa.init_app(app) return app app = create_app() if __name__ == "__main__": app.run()