You cannot select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

154 lines
5.2 KiB
Python

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()