generated from GARAGENUM/flask_secure
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
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() |