| | import os |
| | from flask import Flask, session, redirect, url_for, request |
| | from flask_sqlalchemy import SQLAlchemy |
| | from flask_login import LoginManager, user_logged_in, current_user |
| | from flask_dance.contrib.google import make_google_blueprint |
| | from flask_socketio import SocketIO |
| | from flask_wtf.csrf import CSRFProtect |
| | from flask_mail import Mail |
| | from flask_migrate import Migrate |
| | from flask_limiter import Limiter |
| | from flask_limiter.util import get_remote_address |
| | from flask_cors import CORS |
| |
|
| | |
| | from .config import Config |
| |
|
| | |
| | db = SQLAlchemy() |
| | socketio = SocketIO() |
| | csrf = CSRFProtect() |
| | login_manager = LoginManager() |
| | mail = Mail() |
| | migrate = Migrate() |
| | limiter = Limiter(key_func=get_remote_address, default_limits=["200 per day", "50 per hour"]) |
| |
|
| | def create_app(): |
| | app = Flask(__name__) |
| | |
| | |
| | app.config.from_object(Config) |
| |
|
| | |
| | IS_CLOUD = os.environ.get('SPACE_ID') is not None |
| | if IS_CLOUD: |
| | |
| | app.config['SQLALCHEMY_DATABASE_URI'] = 'sqlite:///cloud_demo.db' |
| | print("[-] Running in CLOUD MODE (Hugging Face) - Using SQLite") |
| | else: |
| | print("[-] Running in LOCAL MODE - Using Configured Database (MySQL)") |
| |
|
| | |
| | db.init_app(app) |
| | |
| | |
| | socketio.init_app(app, async_mode='threading', cors_allowed_origins="*", manage_session=False) |
| | |
| | csrf.init_app(app) |
| | login_manager.init_app(app) |
| | mail.init_app(app) |
| | migrate.init_app(app, db) |
| | |
| | with app.app_context(): |
| | |
| | |
| | db.create_all() |
| | print(" [+] Database tables verified/created successfully.") |
| | |
| | CORS(app, resources={r"/*": {"origins": "*"}}, supports_credentials=True) |
| | |
| | login_manager.login_view = 'auth.login' |
| |
|
| | from webpass.models import User |
| | @login_manager.user_loader |
| | def load_user(user_id): |
| | return User.query.get(int(user_id)) |
| |
|
| | |
| | @user_logged_in.connect_via(app) |
| | def on_user_logged_in(sender, user, **extra): |
| | session['bio_verified'] = False |
| | session.permanent = True |
| |
|
| | |
| | from webpass.routes.auth import auth_bp |
| | from webpass.routes.dashboard import dashboard_bp |
| | from webpass.routes.bio_auth import bio_bp |
| | from webpass.routes.api import api_bp |
| | from webpass.routes.otp import otp_bp |
| | from webpass.routes.share import share_bp |
| | from webpass.routes.stego import stego_bp |
| | from webpass.routes.tools import tools_bp |
| |
|
| | app.register_blueprint(auth_bp) |
| | app.register_blueprint(dashboard_bp, url_prefix='/dashboard') |
| | app.register_blueprint(bio_bp) |
| | app.register_blueprint(api_bp, url_prefix='/api') |
| | app.register_blueprint(otp_bp) |
| | app.register_blueprint(share_bp) |
| | app.register_blueprint(stego_bp) |
| | app.register_blueprint(tools_bp) |
| | |
| | |
| | google_bp = make_google_blueprint( |
| | client_id = app.config["GOOGLE_OAUTH_CLIENT_ID"], |
| | client_secret = app.config["GOOGLE_OAUTH_CLIENT_SECRET"], |
| | scope = ["openid", "https://www.googleapis.com/auth/userinfo.email", "https://www.googleapis.com/auth/userinfo.profile"], |
| | redirect_to = "auth.authorize" |
| | ) |
| | google_bp.authorization_url_params["prompt"] = "select_account" |
| | app.register_blueprint(google_bp, url_prefix='/login') |
| |
|
| | |
| | @app.before_request |
| | def require_biometric_auth(): |
| | session.permanent = True |
| | allowed_endpoints = [ |
| | 'google.login', 'google.authorized', 'auth.login', 'auth.authorize', 'auth.logout', |
| | 'static', 'bio.lock_screen', 'bio.mobile_authenticate', 'bio.finalize_login', |
| | 'bio.register_begin', 'bio.register_complete', 'bio.auth_begin', 'bio.auth_complete', |
| | 'share.view_drop_page', 'share.reveal_drop_api', 'share.create_share', 'share.share_ui' |
| | ] |
| | if request.endpoint and request.endpoint not in allowed_endpoints: |
| | if current_user.is_authenticated: |
| | if not session.get('bio_verified'): |
| | return redirect(url_for('bio.lock_screen')) |
| |
|
| | |
| | @app.after_request |
| | def add_security_headers(response): |
| | response.headers['Strict-Transport-Security'] = 'max-age=31536000; includeSubDomains' |
| | |
| | |
| | |
| | response.headers['Content-Security-Policy'] = "frame-ancestors 'self' https://huggingface.co;" |
| | |
| | return response |
| |
|
| | from webpass.models import BiometricDevice |
| | @app.context_processor |
| | def inject_credential_status(): |
| | if current_user.is_authenticated: |
| | try: |
| | device = BiometricDevice.query.filter_by(user_id=current_user.id).first() |
| | return dict(has_credentials=bool(device)) |
| | except: pass |
| | return dict(has_credentials=False) |
| |
|
| | return app |