71 lines
		
	
	
		
			2.3 KiB
		
	
	
	
		
			Python
		
	
	
	
	
	
			
		
		
	
	
			71 lines
		
	
	
		
			2.3 KiB
		
	
	
	
		
			Python
		
	
	
	
	
	
from dotenv import load_dotenv
 | 
						|
from flask import Flask, jsonify
 | 
						|
from flask_jwt_extended import JWTManager
 | 
						|
from jwt import ExpiredSignatureError
 | 
						|
from models import db, RevokedToken
 | 
						|
import os
 | 
						|
from tech_views import tech_bp
 | 
						|
from utils import init_db, wait_for_db
 | 
						|
from views import user_bp
 | 
						|
from werkzeug.exceptions import HTTPException
 | 
						|
 | 
						|
def create_app(config_name="default"):
 | 
						|
    """Creates and returns a new instance of Flask app."""
 | 
						|
    load_dotenv()
 | 
						|
    app = Flask(__name__)
 | 
						|
    
 | 
						|
    # Database settings
 | 
						|
    if config_name == "testing":
 | 
						|
        app.config["SQLALCHEMY_DATABASE_URI"] = "sqlite:///:memory:"  # Database in memory
 | 
						|
        app.config["TESTING"] = True
 | 
						|
    else:
 | 
						|
        app.config["SQLALCHEMY_DATABASE_URI"] = os.getenv("SQLALCHEMY_DATABASE_URI")
 | 
						|
    app.config["SQLALCHEMY_TRACK_MODIFICATIONS"] = False
 | 
						|
 | 
						|
    # JWT settings
 | 
						|
    app.config["JWT_SECRET_KEY"] = os.getenv("JWT_SECRET_KEY", "changeme")
 | 
						|
 | 
						|
    # Blueprints registration
 | 
						|
    app.register_blueprint(user_bp)
 | 
						|
    app.register_blueprint(tech_bp)
 | 
						|
 | 
						|
    # Database and JWT initialization
 | 
						|
    db.init_app(app)
 | 
						|
    jwt = JWTManager(app)
 | 
						|
 | 
						|
    # Function to check if JWT token is revoked
 | 
						|
    @jwt.token_in_blocklist_loader
 | 
						|
    def check_if_token_revoked(jwt_header, jwt_payload):
 | 
						|
        token = db.session.get(RevokedToken, jwt_payload["jti"])
 | 
						|
        return token is not None
 | 
						|
 | 
						|
    # Global error handler
 | 
						|
    @app.errorhandler(Exception)
 | 
						|
    def global_error_handler(error):
 | 
						|
        if isinstance(error, HTTPException):
 | 
						|
            response = jsonify({"error": error.description})
 | 
						|
            response.status_code = error.code
 | 
						|
        elif isinstance(error, ExpiredSignatureError):
 | 
						|
            response = jsonify({"error": "Token has expired"})
 | 
						|
            response.status_code = 401
 | 
						|
        else:  # All other errors
 | 
						|
            response = jsonify({"error": str(error)})
 | 
						|
            response.status_code = 500
 | 
						|
        return response
 | 
						|
 | 
						|
    # Fill database by initial values (only if we are not testing)
 | 
						|
    with app.app_context():
 | 
						|
        wait_for_db(max_retries=100)
 | 
						|
        db.create_all()
 | 
						|
        if config_name != "testing":
 | 
						|
            init_db()
 | 
						|
    return app
 | 
						|
 | 
						|
 | 
						|
# Server start only if we run app directly
 | 
						|
if __name__ == "__main__":
 | 
						|
    from waitress import serve
 | 
						|
    app = create_app()
 | 
						|
    port = os.getenv("APP_PORT", "80")
 | 
						|
    serve(app, host="0.0.0.0", port=port)
 |