Loading app/config.py +18 −12 Original line number Diff line number Diff line Loading @@ -5,17 +5,23 @@ from datetime import timedelta # Load environment variables load_dotenv() class Config: SECRET_KEY = os.getenv('SECRET_KEY') SQLALCHEMY_DATABASE_URI = os.getenv('DATABASE_URL') DEBUG = bool(os.getenv("DEBUG")) SECRET_KEY = os.getenv("SECRET_KEY") SQLALCHEMY_DATABASE_URI = os.getenv("DATABASE_URL") SQLALCHEMY_TRACK_MODIFICATIONS = False REDIS_HOST = os.getenv('REDIS_HOST') REDIS_PORT = os.getenv('REDIS_PORT') JWT_SECRET_KEY = os.getenv('JWT_SECRET_KEY') JWT_ACCESS_TOKEN_EXPIRES = timedelta(seconds=int(os.getenv('JWT_ACCESS_TOKEN_EXPIRES'))) JWT_REFRESH_TOKEN_EXPIRES = timedelta(seconds=int(os.getenv('JWT_REFRESH_TOKEN_EXPIRES'))) POSTGRES_HOST = os.getenv('POSTGRES_HOST') POSTGRES_PORT= os.getenv('POSTGRES_PORT') POSTGRES_DB= os.getenv('POSTGRES_DB') POSTGRES_USER= os.getenv('POSTGRES_USER') POSTGRES_PASSWORD= os.getenv('POSTGRES_PASSWORD') REDIS_HOST = os.getenv("REDIS_HOST") REDIS_PORT = os.getenv("REDIS_PORT") JWT_SECRET_KEY = os.getenv("JWT_SECRET_KEY") JWT_ACCESS_TOKEN_EXPIRES = timedelta( seconds=int(os.getenv("JWT_ACCESS_TOKEN_EXPIRES")) ) JWT_REFRESH_TOKEN_EXPIRES = timedelta( seconds=int(os.getenv("JWT_REFRESH_TOKEN_EXPIRES")) ) POSTGRES_HOST = os.getenv("POSTGRES_HOST") POSTGRES_PORT = os.getenv("POSTGRES_PORT") POSTGRES_DB = os.getenv("POSTGRES_DB") POSTGRES_USER = os.getenv("POSTGRES_USER") POSTGRES_PASSWORD = os.getenv("POSTGRES_PASSWORD") app/controller/auth.py +15 −5 Original line number Diff line number Diff line Loading @@ -2,11 +2,16 @@ from flask import Blueprint, request, jsonify, current_app from helpers.security import check_auth, revoke_jwt from helpers.limiter import limiter from flask_jwt_extended import ( JWTManager, create_access_token, create_refresh_token, jwt_required, get_jwt_identity, get_jwt JWTManager, create_access_token, create_refresh_token, jwt_required, get_jwt_identity, get_jwt, ) auth_bp = Blueprint('auth', __name__) auth_bp = Blueprint("auth", __name__) @auth_bp.route("/login", methods=["POST"]) def login(): Loading @@ -17,7 +22,11 @@ def login(): print(data) if not username or not password or not check_auth(username=username, password=password): if ( not username or not password or not check_auth(username=username, password=password) ): return jsonify({"error": "Invalid credentials"}), 401 # Create tokens Loading Loading @@ -46,6 +55,7 @@ def refresh(): new_access_token = create_access_token(identity=identity) return jsonify({"access_token": new_access_token}) @auth_bp.route("/CheckConnected", methods=["GET"]) @jwt_required(optional=True) def optionally_protected(): Loading app/controller/diploma.py +11 −11 Original line number Diff line number Diff line Loading @@ -2,24 +2,24 @@ from flask import Blueprint, request, jsonify, current_app from helpers.security import require_auth from helpers.limiter import limiter diploma_bp = Blueprint('diploma', __name__) diploma_bp = Blueprint("diploma", __name__) @diploma_bp.route('/diplomas', methods=['GET']) @diploma_bp.route("/diplomas", methods=["GET"]) @require_auth @limiter.limit("1/second", override_defaults=False) def get_diplomas(): return jsonify({"message": "list"}) @diploma_bp.route('/diplomas/<int:id>', methods=['GET']) @diploma_bp.route("/diplomas/<int:id>", methods=["GET"]) @require_auth @limiter.limit("1/second", override_defaults=False) def get_diploma(id): return jsonify({"message": "update", "id": id}) @diploma_bp.route('/diplomas', methods=['PUT']) @diploma_bp.route("/diplomas", methods=["PUT"]) @require_auth @limiter.limit("1/second", override_defaults=False) def create_diploma(): Loading @@ -27,14 +27,14 @@ def create_diploma(): return jsonify({"message": "create", "id": NewID}) @diploma_bp.route('/diplomas/<int:id>', methods=['POST']) @diploma_bp.route("/diplomas/<int:id>", methods=["POST"]) @require_auth @limiter.limit("1/second", override_defaults=False) def update_diploma(id): return jsonify({"message": "update", "id": id}) @diploma_bp.route('/diplomas/<int:id>', methods=['DELETE']) @diploma_bp.route("/diplomas/<int:id>", methods=["DELETE"]) @require_auth @limiter.limit("1/second", override_defaults=False) def delete_diploma(id): Loading app/controller/healthcheck.py +6 −7 Original line number Diff line number Diff line from flask import Blueprint, current_app from helpers.limiter import limiter healthcheck_bp = Blueprint('healthcheck', __name__) healthcheck_bp = Blueprint("healthcheck", __name__) @healthcheck_bp.route('/healthcheck', methods=['GET']) @healthcheck_bp.route("/healthcheck", methods=["GET"]) @limiter.exempt def healthcheck(): # Get a connection from the pool Loading @@ -12,10 +13,8 @@ def healthcheck(): cur.execute("SELECT version();") version = cur.fetchone()[0] count = current_app.redis.incr('hits') count = current_app.redis.incr("hits") current_app.redis.set("test_key", "Hello from Redis!") value = current_app.redis.get("test_key").decode('utf-8') value = current_app.redis.get("test_key").decode("utf-8") return f"Hello World! I have been seen {count} times.<br>{value}<br>PostgreSQL version: {version}<br>redis://{current_app.config['REDIS_HOST']}:{current_app.config['REDIS_PORT']}" app/helpers/limiter.py +7 −5 Original line number Diff line number Diff line Loading @@ -4,8 +4,10 @@ from app.config import Config # Initialize the Limiter instance limiter = Limiter(key_func=get_remote_address, limiter = Limiter( key_func=get_remote_address, storage_uri=f"redis://{Config.REDIS_HOST}:{Config.REDIS_PORT}", storage_options={"socket_connect_timeout": 30}, strategy="fixed-window", # or "moving-window" default_limits=["200 per day", "50 per hour", "5 per minute"]) default_limits=["200 per day", "50 per hour", "5 per minute"], ) Loading
app/config.py +18 −12 Original line number Diff line number Diff line Loading @@ -5,17 +5,23 @@ from datetime import timedelta # Load environment variables load_dotenv() class Config: SECRET_KEY = os.getenv('SECRET_KEY') SQLALCHEMY_DATABASE_URI = os.getenv('DATABASE_URL') DEBUG = bool(os.getenv("DEBUG")) SECRET_KEY = os.getenv("SECRET_KEY") SQLALCHEMY_DATABASE_URI = os.getenv("DATABASE_URL") SQLALCHEMY_TRACK_MODIFICATIONS = False REDIS_HOST = os.getenv('REDIS_HOST') REDIS_PORT = os.getenv('REDIS_PORT') JWT_SECRET_KEY = os.getenv('JWT_SECRET_KEY') JWT_ACCESS_TOKEN_EXPIRES = timedelta(seconds=int(os.getenv('JWT_ACCESS_TOKEN_EXPIRES'))) JWT_REFRESH_TOKEN_EXPIRES = timedelta(seconds=int(os.getenv('JWT_REFRESH_TOKEN_EXPIRES'))) POSTGRES_HOST = os.getenv('POSTGRES_HOST') POSTGRES_PORT= os.getenv('POSTGRES_PORT') POSTGRES_DB= os.getenv('POSTGRES_DB') POSTGRES_USER= os.getenv('POSTGRES_USER') POSTGRES_PASSWORD= os.getenv('POSTGRES_PASSWORD') REDIS_HOST = os.getenv("REDIS_HOST") REDIS_PORT = os.getenv("REDIS_PORT") JWT_SECRET_KEY = os.getenv("JWT_SECRET_KEY") JWT_ACCESS_TOKEN_EXPIRES = timedelta( seconds=int(os.getenv("JWT_ACCESS_TOKEN_EXPIRES")) ) JWT_REFRESH_TOKEN_EXPIRES = timedelta( seconds=int(os.getenv("JWT_REFRESH_TOKEN_EXPIRES")) ) POSTGRES_HOST = os.getenv("POSTGRES_HOST") POSTGRES_PORT = os.getenv("POSTGRES_PORT") POSTGRES_DB = os.getenv("POSTGRES_DB") POSTGRES_USER = os.getenv("POSTGRES_USER") POSTGRES_PASSWORD = os.getenv("POSTGRES_PASSWORD")
app/controller/auth.py +15 −5 Original line number Diff line number Diff line Loading @@ -2,11 +2,16 @@ from flask import Blueprint, request, jsonify, current_app from helpers.security import check_auth, revoke_jwt from helpers.limiter import limiter from flask_jwt_extended import ( JWTManager, create_access_token, create_refresh_token, jwt_required, get_jwt_identity, get_jwt JWTManager, create_access_token, create_refresh_token, jwt_required, get_jwt_identity, get_jwt, ) auth_bp = Blueprint('auth', __name__) auth_bp = Blueprint("auth", __name__) @auth_bp.route("/login", methods=["POST"]) def login(): Loading @@ -17,7 +22,11 @@ def login(): print(data) if not username or not password or not check_auth(username=username, password=password): if ( not username or not password or not check_auth(username=username, password=password) ): return jsonify({"error": "Invalid credentials"}), 401 # Create tokens Loading Loading @@ -46,6 +55,7 @@ def refresh(): new_access_token = create_access_token(identity=identity) return jsonify({"access_token": new_access_token}) @auth_bp.route("/CheckConnected", methods=["GET"]) @jwt_required(optional=True) def optionally_protected(): Loading
app/controller/diploma.py +11 −11 Original line number Diff line number Diff line Loading @@ -2,24 +2,24 @@ from flask import Blueprint, request, jsonify, current_app from helpers.security import require_auth from helpers.limiter import limiter diploma_bp = Blueprint('diploma', __name__) diploma_bp = Blueprint("diploma", __name__) @diploma_bp.route('/diplomas', methods=['GET']) @diploma_bp.route("/diplomas", methods=["GET"]) @require_auth @limiter.limit("1/second", override_defaults=False) def get_diplomas(): return jsonify({"message": "list"}) @diploma_bp.route('/diplomas/<int:id>', methods=['GET']) @diploma_bp.route("/diplomas/<int:id>", methods=["GET"]) @require_auth @limiter.limit("1/second", override_defaults=False) def get_diploma(id): return jsonify({"message": "update", "id": id}) @diploma_bp.route('/diplomas', methods=['PUT']) @diploma_bp.route("/diplomas", methods=["PUT"]) @require_auth @limiter.limit("1/second", override_defaults=False) def create_diploma(): Loading @@ -27,14 +27,14 @@ def create_diploma(): return jsonify({"message": "create", "id": NewID}) @diploma_bp.route('/diplomas/<int:id>', methods=['POST']) @diploma_bp.route("/diplomas/<int:id>", methods=["POST"]) @require_auth @limiter.limit("1/second", override_defaults=False) def update_diploma(id): return jsonify({"message": "update", "id": id}) @diploma_bp.route('/diplomas/<int:id>', methods=['DELETE']) @diploma_bp.route("/diplomas/<int:id>", methods=["DELETE"]) @require_auth @limiter.limit("1/second", override_defaults=False) def delete_diploma(id): Loading
app/controller/healthcheck.py +6 −7 Original line number Diff line number Diff line from flask import Blueprint, current_app from helpers.limiter import limiter healthcheck_bp = Blueprint('healthcheck', __name__) healthcheck_bp = Blueprint("healthcheck", __name__) @healthcheck_bp.route('/healthcheck', methods=['GET']) @healthcheck_bp.route("/healthcheck", methods=["GET"]) @limiter.exempt def healthcheck(): # Get a connection from the pool Loading @@ -12,10 +13,8 @@ def healthcheck(): cur.execute("SELECT version();") version = cur.fetchone()[0] count = current_app.redis.incr('hits') count = current_app.redis.incr("hits") current_app.redis.set("test_key", "Hello from Redis!") value = current_app.redis.get("test_key").decode('utf-8') value = current_app.redis.get("test_key").decode("utf-8") return f"Hello World! I have been seen {count} times.<br>{value}<br>PostgreSQL version: {version}<br>redis://{current_app.config['REDIS_HOST']}:{current_app.config['REDIS_PORT']}"
app/helpers/limiter.py +7 −5 Original line number Diff line number Diff line Loading @@ -4,8 +4,10 @@ from app.config import Config # Initialize the Limiter instance limiter = Limiter(key_func=get_remote_address, limiter = Limiter( key_func=get_remote_address, storage_uri=f"redis://{Config.REDIS_HOST}:{Config.REDIS_PORT}", storage_options={"socket_connect_timeout": 30}, strategy="fixed-window", # or "moving-window" default_limits=["200 per day", "50 per hour", "5 per minute"]) default_limits=["200 per day", "50 per hour", "5 per minute"], )