diff --git a/.gitignore b/.gitignore new file mode 100644 index 0000000..c66ba3a --- /dev/null +++ b/.gitignore @@ -0,0 +1,2 @@ +.env +.venv \ No newline at end of file diff --git a/__pycache__/config.cpython-313.pyc b/__pycache__/config.cpython-313.pyc new file mode 100644 index 0000000..6ebab11 Binary files /dev/null and b/__pycache__/config.cpython-313.pyc differ diff --git a/__pycache__/extensions.cpython-313.pyc b/__pycache__/extensions.cpython-313.pyc new file mode 100644 index 0000000..c21cca9 Binary files /dev/null and b/__pycache__/extensions.cpython-313.pyc differ diff --git a/app.py b/app.py new file mode 100644 index 0000000..7d8c551 --- /dev/null +++ b/app.py @@ -0,0 +1,40 @@ +import os +import logging +from flask import Flask +from config import Config +from extensions import db + +# initialize app + +app = Flask(__name__) +app.config.from_object(Config) + +# initialize db +db.init_app(app) + +# configure logging +os.makedirs(app.config['LOG_FOLDER'], exist_ok=True) +logging.basicConfig( + filename=f"{app.config['LOG_FOLDER']}/app.log", + level=logging.INFO, + format='%(asctime)s [%(levelname)s] %(message)s' +) + +# register blueprints +from controllers.file_controller import file_bp +from controllers.auth_controller import auth_bp +app.register_blueprint(file_bp) +app.register_blueprint(auth_bp) + +# Create tables if not exist +with app.app_context(): + print("Creating database tables...") + db.create_all() + print("Database tables created.") + +@app.route('/') +def index(): + return "✅ Flask app is running successfully!" + +if __name__ == '__main__': + app.run(debug=True, host='127.0.0.1', port=5000) \ No newline at end of file diff --git a/config.py b/config.py new file mode 100644 index 0000000..9e64997 --- /dev/null +++ b/config.py @@ -0,0 +1,14 @@ +import os +from dotenv import load_dotenv + +load_dotenv() + +class Config: + SQLALCHEMY_DATABASE_URI = ( + f"mysql+pymysql://{os.getenv('DB_USER')}:{os.getenv('DB_PASSWORD')}@" + f"{os.getenv('DB_HOST')}:{os.getenv('DB_PORT')}/{os.getenv('DB_NAME')}" + ) + SQLALCHEMY_TRACK_MODIFICATIONS = False + UPLOAD_FOLDER = os.getenv('UPLOAD_FOLDER', 'uploads') + LOG_FOLDER = 'logs' + DEBUG = True \ No newline at end of file diff --git a/controllers/__pycache__/auth_controller.cpython-313.pyc b/controllers/__pycache__/auth_controller.cpython-313.pyc new file mode 100644 index 0000000..41ab9da Binary files /dev/null and b/controllers/__pycache__/auth_controller.cpython-313.pyc differ diff --git a/controllers/__pycache__/file_controller.cpython-313.pyc b/controllers/__pycache__/file_controller.cpython-313.pyc new file mode 100644 index 0000000..518483f Binary files /dev/null and b/controllers/__pycache__/file_controller.cpython-313.pyc differ diff --git a/controllers/auth_controller.py b/controllers/auth_controller.py new file mode 100644 index 0000000..40e1e6a --- /dev/null +++ b/controllers/auth_controller.py @@ -0,0 +1,39 @@ +from flask import Blueprint, request, jsonify, current_app +import logging + +auth_bp = Blueprint('auth_bp', __name__) +logger = logging.getLogger(__name__) + +VALID_USERNAME = "admin" +VALID_PASSWORD = "1234" + +@auth_bp.route('/login', methods=['POST']) +def login(): + try: + data = request.get_json() + + if not data: + return jsonify({'message': 'No input data provided'}), 400 + + username = data.get('username') + password = data.get('password') + client_ip = request.remote_addr + + if not username or not password: + logger.info("Login ATTEMPT - missing credentials - ip=%s username=%s", client_ip, username) + return jsonify({'message': 'Username and password are required'}), 400 + + # Validate against static values + if username == VALID_USERNAME and password == VALID_PASSWORD: + logger.info("Login SUCCESS - user=%s ip=%s", username, client_ip) + return jsonify({ + "message": "Login successful", + "user": username + }), 200 + + logger.warning("Login FAILED - invalid credentials - user=%s ip=%s", username, client_ip) + return jsonify({"message": "Invalid username or password"}), 401 + + except Exception as e: + logger.exception("Login error") + return jsonify({'message': str(e)}), 400 \ No newline at end of file diff --git a/controllers/file_controller.py b/controllers/file_controller.py new file mode 100644 index 0000000..9714cd8 --- /dev/null +++ b/controllers/file_controller.py @@ -0,0 +1,71 @@ +from flask import Blueprint, request, jsonify, send_file, current_app +from services.file_service import save_file, update_file, delete_file +from models.uploaded_file import UploadedFile +from flask import send_from_directory +import logging +import uuid + +file_bp = Blueprint('file_bp', __name__) + +# POST - upload file +@file_bp.route('/upload', methods=['POST']) +def upload_file(): + try: + if 'file' not in request.files: + return jsonify({'message' : 'No file uploaded'}), 400 + + file = request.files['file'] + folder = f"{current_app.config['UPLOAD_FOLDER']}/{uuid.uuid4().hex}" + uploaded = save_file(file, folder) + return jsonify({ + 'message': 'Upload successful', + 'id': uploaded.id, + 'path': uploaded.file_path + }), 201 + + except Exception as e: + logging.error(f"Upload error: {e}") + return jsonify({'message': str(e)}), 400 + +# GET - retrieve file +@file_bp.route('/files/', methods=['GET']) +def get_file(file_id): + try: + file = UploadedFile.query.get(file_id) + if not file: + return jsonify({'message': 'File not found'}), 404 + + return send_file(file.file_path, as_attachment=True) + + except Exception as e: + logging.error(f"Get error: {e}") + return jsonify({'message': str(e)}), 400 + +# PUT - update file +@file_bp.route('/files/', methods=['PUT']) +def update_existing_file(file_id): + try: + if 'file' not in request.files: + return jsonify({'message' : 'No file provided'}), 400 + + file = request.files['file'] + updated = update_file(file_id, file, current_app.config['UPLOAD_FOLDER']) + return jsonify({ + 'message': 'File update successfully', + 'path': updated.file_path + }), 200 + + except Exception as e: + logging.error(f"Update error: {e}") + return jsonify({'message': str(e)}), 400 + +# DELETE - delete file +@file_bp.route('/files/', methods=['DELETE']) +def delete_existing_file(file_id): + try: + delete_file(file_id) + return jsonify({'message': 'File deleted successfully'}), 200 + + except Exception as e: + logging.error(f"Delete error: {e}") + return jsonify({'message': str(e)}), 400 \ No newline at end of file diff --git a/extensions.py b/extensions.py new file mode 100644 index 0000000..2e1eeb6 --- /dev/null +++ b/extensions.py @@ -0,0 +1,3 @@ +from flask_sqlalchemy import SQLAlchemy + +db = SQLAlchemy() \ No newline at end of file diff --git a/logs/app.log b/logs/app.log new file mode 100644 index 0000000..c8be4bb --- /dev/null +++ b/logs/app.log @@ -0,0 +1,372 @@ +2025-10-19 15:30:49,258 INFO: WARNING: This is a development server. Do not use it in a production deployment. Use a production WSGI server instead. + * Running on http://127.0.0.1:5000 +2025-10-19 15:30:49,258 INFO: Press CTRL+C to quit +2025-10-19 15:30:49,262 INFO: * Restarting with stat +2025-10-19 15:30:50,377 WARNING: * Debugger is active! +2025-10-19 15:30:50,384 INFO: * Debugger PIN: 587-549-864 +2025-10-19 15:31:13,386 INFO: WARNING: This is a development server. Do not use it in a production deployment. Use a production WSGI server instead. + * Running on http://127.0.0.1:5000 +2025-10-19 15:31:13,386 INFO: Press CTRL+C to quit +2025-10-19 15:31:13,387 INFO: * Restarting with stat +2025-10-19 15:31:14,405 WARNING: * Debugger is active! +2025-10-19 15:31:14,412 INFO: * Debugger PIN: 587-549-864 +2025-10-19 15:39:29,417 INFO: WARNING: This is a development server. Do not use it in a production deployment. Use a production WSGI server instead. + * Running on http://127.0.0.1:5000 +2025-10-19 15:39:29,417 INFO: Press CTRL+C to quit +2025-10-19 15:39:29,420 INFO: * Restarting with stat +2025-10-19 15:39:30,467 WARNING: * Debugger is active! +2025-10-19 15:39:30,475 INFO: * Debugger PIN: 587-549-864 +2025-10-19 20:46:23,354 INFO: WARNING: This is a development server. Do not use it in a production deployment. Use a production WSGI server instead. + * Running on http://127.0.0.1:5000 +2025-10-19 20:46:23,354 INFO: Press CTRL+C to quit +2025-10-19 20:46:23,356 INFO: * Restarting with stat +2025-10-19 20:46:24,228 WARNING: * Debugger is active! +2025-10-19 20:46:24,233 INFO: * Debugger PIN: 587-549-864 +2025-10-19 20:58:38,745 INFO: WARNING: This is a development server. Do not use it in a production deployment. Use a production WSGI server instead. + * Running on http://127.0.0.1:5000 +2025-10-19 20:58:38,745 INFO: Press CTRL+C to quit +2025-10-19 20:59:32,318 INFO: WARNING: This is a development server. Do not use it in a production deployment. Use a production WSGI server instead. + * Running on http://127.0.0.1:5000 +2025-10-19 20:59:32,318 INFO: Press CTRL+C to quit +2025-10-19 21:00:21,483 INFO: WARNING: This is a development server. Do not use it in a production deployment. Use a production WSGI server instead. + * Running on http://127.0.0.1:5000 +2025-10-19 21:00:21,483 INFO: Press CTRL+C to quit +2025-10-19 21:03:04,786 INFO: WARNING: This is a development server. Do not use it in a production deployment. Use a production WSGI server instead. + * Running on http://127.0.0.1:5000 +2025-10-19 21:03:04,787 INFO: Press CTRL+C to quit +2025-10-19 21:04:11,134 INFO: WARNING: This is a development server. Do not use it in a production deployment. Use a production WSGI server instead. + * Running on http://127.0.0.1:5000 +2025-10-19 21:04:11,135 INFO: Press CTRL+C to quit +2025-10-19 21:43:23,410 [INFO] WARNING: This is a development server. Do not use it in a production deployment. Use a production WSGI server instead. + * Running on http://127.0.0.1:5000 +2025-10-19 21:43:23,411 [INFO] Press CTRL+C to quit +2025-10-19 21:43:23,414 [INFO] * Restarting with stat +2025-10-19 21:43:24,626 [WARNING] * Debugger is active! +2025-10-19 21:43:24,637 [INFO] * Debugger PIN: 587-549-864 +2025-10-19 21:51:24,567 [INFO] WARNING: This is a development server. Do not use it in a production deployment. Use a production WSGI server instead. + * Running on http://127.0.0.1:5000 +2025-10-19 21:51:24,568 [INFO] Press CTRL+C to quit +2025-10-19 21:51:24,573 [INFO] * Restarting with stat +2025-10-19 21:51:25,527 [WARNING] * Debugger is active! +2025-10-19 21:51:25,532 [INFO] * Debugger PIN: 587-549-864 +2025-10-19 22:12:35,862 [INFO] 127.0.0.1 - - [19/Oct/2025 22:12:35] "GET / HTTP/1.1" 404 - +2025-10-19 22:12:45,394 [INFO] 127.0.0.1 - - [19/Oct/2025 22:12:45] "GET /files HTTP/1.1" 404 - +2025-10-19 22:12:54,769 [INFO] 127.0.0.1 - - [19/Oct/2025 22:12:54] "GET / HTTP/1.1" 404 - +2025-10-19 22:12:54,924 [INFO] 127.0.0.1 - - [19/Oct/2025 22:12:54] "GET /favicon.ico HTTP/1.1" 404 - +2025-10-19 22:13:35,848 [INFO] 127.0.0.1 - - [19/Oct/2025 22:13:35] "GET / HTTP/1.1" 404 - +2025-10-19 22:14:23,259 [INFO] WARNING: This is a development server. Do not use it in a production deployment. Use a production WSGI server instead. + * Running on http://127.0.0.1:5000 +2025-10-19 22:14:23,260 [INFO] Press CTRL+C to quit +2025-10-19 22:14:23,261 [INFO] * Restarting with stat +2025-10-19 22:14:24,469 [WARNING] * Debugger is active! +2025-10-19 22:14:24,474 [INFO] * Debugger PIN: 587-549-864 +2025-10-19 22:15:12,211 [INFO] * Detected change in 'C:\\Users\\Acer\\Documents\\PROGLAN\\Flask\\file-upload\\app.py', reloading +2025-10-19 22:15:12,341 [INFO] * Restarting with stat +2025-10-19 22:15:13,507 [WARNING] * Debugger is active! +2025-10-19 22:15:13,511 [INFO] * Debugger PIN: 587-549-864 +2025-10-19 22:15:17,025 [INFO] WARNING: This is a development server. Do not use it in a production deployment. Use a production WSGI server instead. + * Running on http://127.0.0.1:5000 +2025-10-19 22:15:17,025 [INFO] Press CTRL+C to quit +2025-10-19 22:15:17,032 [INFO] * Restarting with stat +2025-10-19 22:15:18,065 [WARNING] * Debugger is active! +2025-10-19 22:15:18,071 [INFO] * Debugger PIN: 587-549-864 +2025-10-19 22:15:42,934 [INFO] 127.0.0.1 - - [19/Oct/2025 22:15:42] "GET / HTTP/1.1" 404 - +2025-10-19 22:16:07,996 [INFO] 127.0.0.1 - - [19/Oct/2025 22:16:07] "GET / HTTP/1.1" 404 - +2025-10-19 22:17:28,989 [INFO] * Detected change in 'C:\\Users\\Acer\\Documents\\PROGLAN\\Flask\\file-upload\\app.py', reloading +2025-10-19 22:17:29,263 [INFO] * Restarting with stat +2025-10-19 22:17:30,466 [WARNING] * Debugger is active! +2025-10-19 22:17:30,477 [INFO] * Debugger PIN: 587-549-864 +2025-10-19 22:18:17,617 [INFO] * Detected change in 'C:\\Users\\Acer\\Documents\\PROGLAN\\Flask\\file-upload\\app.py', reloading +2025-10-19 22:18:17,774 [INFO] * Restarting with stat +2025-10-19 22:18:19,023 [WARNING] * Debugger is active! +2025-10-19 22:18:19,032 [INFO] * Debugger PIN: 587-549-864 +2025-10-19 22:19:55,638 [INFO] WARNING: This is a development server. Do not use it in a production deployment. Use a production WSGI server instead. + * Running on http://127.0.0.1:5000 +2025-10-19 22:19:55,638 [INFO] Press CTRL+C to quit +2025-10-19 22:19:55,640 [INFO] * Restarting with stat +2025-10-19 22:19:56,474 [WARNING] * Debugger is active! +2025-10-19 22:19:56,478 [INFO] * Debugger PIN: 587-549-864 +2025-10-19 22:20:07,138 [INFO] 127.0.0.1 - - [19/Oct/2025 22:20:07] "GET / HTTP/1.1" 200 - +2025-10-19 22:20:56,203 [INFO] 127.0.0.1 - - [19/Oct/2025 22:20:56] "GET /upload HTTP/1.1" 405 - +2025-10-19 22:32:14,264 [INFO] 127.0.0.1 - - [19/Oct/2025 22:32:14] "POST /upload HTTP/1.1" 400 - +2025-10-19 22:33:22,652 [INFO] 127.0.0.1 - - [19/Oct/2025 22:33:22] "POST /upload HTTP/1.1" 400 - +2025-10-19 22:35:12,511 [INFO] 127.0.0.1 - - [19/Oct/2025 22:35:12] "POST /upload HTTP/1.1" 400 - +2025-10-19 22:35:58,134 [INFO] 127.0.0.1 - - [19/Oct/2025 22:35:58] "POST /upload HTTP/1.1" 400 - +2025-10-19 22:36:02,933 [INFO] 127.0.0.1 - - [19/Oct/2025 22:36:02] "POST /upload HTTP/1.1" 400 - +2025-10-19 22:36:03,598 [INFO] 127.0.0.1 - - [19/Oct/2025 22:36:03] "POST /upload HTTP/1.1" 400 - +2025-10-19 22:36:03,757 [INFO] 127.0.0.1 - - [19/Oct/2025 22:36:03] "POST /upload HTTP/1.1" 400 - +2025-10-19 22:36:03,982 [INFO] 127.0.0.1 - - [19/Oct/2025 22:36:03] "POST /upload HTTP/1.1" 400 - +2025-10-19 22:36:04,094 [INFO] 127.0.0.1 - - [19/Oct/2025 22:36:04] "POST /upload HTTP/1.1" 400 - +2025-10-19 22:41:07,744 [INFO] 127.0.0.1 - - [19/Oct/2025 22:41:07] "GET /upload HTTP/1.1" 405 - +2025-10-19 22:41:18,247 [INFO] 127.0.0.1 - - [19/Oct/2025 22:41:18] "POST /upload HTTP/1.1" 400 - +2025-10-19 22:42:32,577 [INFO] 127.0.0.1 - - [19/Oct/2025 22:42:32] "GET /files/1 HTTP/1.1" 404 - +2025-10-19 22:43:03,272 [INFO] 127.0.0.1 - - [19/Oct/2025 22:43:03] "PUT /files/1 HTTP/1.1" 400 - +2025-10-19 22:43:19,023 [ERROR] Delete error: File not found +2025-10-19 22:43:19,025 [INFO] 127.0.0.1 - - [19/Oct/2025 22:43:19] "DELETE /files/1 HTTP/1.1" 400 - +2025-10-19 22:43:36,426 [INFO] * Detected change in 'C:\\Users\\Acer\\Documents\\PROGLAN\\Flask\\file-upload\\controllers\\file_controller.py', reloading +2025-10-19 22:43:36,617 [INFO] * Restarting with stat +2025-10-19 22:43:37,957 [WARNING] * Debugger is active! +2025-10-19 22:43:37,966 [INFO] * Debugger PIN: 587-549-864 +2025-10-19 22:43:44,280 [INFO] * Detected change in 'C:\\Users\\Acer\\Documents\\PROGLAN\\Flask\\file-upload\\controllers\\file_controller.py', reloading +2025-10-19 22:43:44,497 [INFO] * Restarting with stat +2025-10-19 22:43:45,465 [WARNING] * Debugger is active! +2025-10-19 22:43:45,477 [INFO] * Debugger PIN: 587-549-864 +2025-10-19 22:43:48,433 [INFO] WARNING: This is a development server. Do not use it in a production deployment. Use a production WSGI server instead. + * Running on http://127.0.0.1:5000 +2025-10-19 22:43:48,434 [INFO] Press CTRL+C to quit +2025-10-19 22:43:48,436 [INFO] * Restarting with stat +2025-10-19 22:43:49,444 [WARNING] * Debugger is active! +2025-10-19 22:43:49,449 [INFO] * Debugger PIN: 587-549-864 +2025-10-19 22:44:16,114 [INFO] 127.0.0.1 - - [19/Oct/2025 22:44:16] "POST /upload HTTP/1.1" 400 - +2025-10-19 22:44:21,596 [INFO] 127.0.0.1 - - [19/Oct/2025 22:44:21] "POST /upload HTTP/1.1" 400 - +2025-10-19 22:44:29,199 [INFO] 127.0.0.1 - - [19/Oct/2025 22:44:29] "POST /upload HTTP/1.1" 400 - +2025-10-19 22:44:48,615 [INFO] 127.0.0.1 - - [19/Oct/2025 22:44:48] "POST /upload HTTP/1.1" 400 - +2025-10-19 22:45:02,410 [INFO] * Detected change in 'C:\\Users\\Acer\\Documents\\PROGLAN\\Flask\\file-upload\\controllers\\file_controller.py', reloading +2025-10-19 22:45:02,539 [INFO] * Restarting with stat +2025-10-19 22:45:03,600 [WARNING] * Debugger is active! +2025-10-19 22:45:03,610 [INFO] * Debugger PIN: 587-549-864 +2025-10-19 22:45:10,946 [INFO] * Detected change in 'C:\\Users\\Acer\\Documents\\PROGLAN\\Flask\\file-upload\\controllers\\file_controller.py', reloading +2025-10-19 22:45:11,130 [INFO] * Restarting with stat +2025-10-19 22:45:12,126 [WARNING] * Debugger is active! +2025-10-19 22:45:12,137 [INFO] * Debugger PIN: 587-549-864 +2025-10-19 22:46:39,658 [INFO] 127.0.0.1 - - [19/Oct/2025 22:46:39] "POST /api/upload HTTP/1.1" 404 - +2025-10-19 22:47:22,913 [INFO] File saved: uploads/085a3deda4de4affbc3ebde2e84aa2b4\1f9b517f46df487f92bc406f49c04c27_pexels-diva-31759026.jpg +2025-10-19 22:47:22,922 [INFO] 127.0.0.1 - - [19/Oct/2025 22:47:22] "POST /upload HTTP/1.1" 201 - +2025-10-19 22:47:41,790 [INFO] 127.0.0.1 - - [19/Oct/2025 22:47:41] "POST /files HTTP/1.1" 404 - +2025-10-19 22:47:59,180 [INFO] 127.0.0.1 - - [19/Oct/2025 22:47:59] "POST /files/1 HTTP/1.1" 405 - +2025-10-19 22:48:04,744 [INFO] 127.0.0.1 - - [19/Oct/2025 22:48:04] "GET /files/1 HTTP/1.1" 200 - +2025-10-19 22:48:26,564 [INFO] File saved: uploads\e7397392533f47969c35392a182c498c_pexels-marek-piwnicki-3907296-11829369.jpg +2025-10-19 22:48:26,587 [INFO] File updated: ID=1 +2025-10-19 22:48:26,594 [INFO] 127.0.0.1 - - [19/Oct/2025 22:48:26] "PUT /files/1 HTTP/1.1" 200 - +2025-10-19 22:48:32,716 [INFO] 127.0.0.1 - - [19/Oct/2025 22:48:32] "GET /files/1 HTTP/1.1" 200 - +2025-10-19 22:48:38,846 [INFO] File deleted from storage: uploads\e7397392533f47969c35392a182c498c_pexels-marek-piwnicki-3907296-11829369.jpg +2025-10-19 22:48:38,857 [INFO] Record deleted: ID=1 +2025-10-19 22:48:38,858 [INFO] 127.0.0.1 - - [19/Oct/2025 22:48:38] "DELETE /files/1 HTTP/1.1" 200 - +2025-10-19 22:50:31,493 [INFO] WARNING: This is a development server. Do not use it in a production deployment. Use a production WSGI server instead. + * Running on http://127.0.0.1:5000 +2025-10-19 22:50:31,493 [INFO] Press CTRL+C to quit +2025-10-19 22:50:31,495 [INFO] * Restarting with stat +2025-10-19 22:50:32,756 [WARNING] * Debugger is active! +2025-10-19 22:50:32,767 [INFO] * Debugger PIN: 587-549-864 +2025-10-19 22:53:33,529 [INFO] File saved: uploads/76a9428a06704f839906bb239652e160\9527dee13c174d56bd669078d241b29a_Screenshot_2025-10-18-13-06-38-769_com.facebook.orca.jpg +2025-10-19 22:53:33,543 [INFO] 127.0.0.1 - - [19/Oct/2025 22:53:33] "POST /upload HTTP/1.1" 201 - +2025-10-19 22:53:48,333 [INFO] 127.0.0.1 - - [19/Oct/2025 22:53:48] "POST /files/3 HTTP/1.1" 405 - +2025-10-19 22:53:55,504 [INFO] 127.0.0.1 - - [19/Oct/2025 22:53:55] "GET /files/3 HTTP/1.1" 200 - +2025-11-15 00:24:01,634 [INFO] WARNING: This is a development server. Do not use it in a production deployment. Use a production WSGI server instead. + * Running on http://127.0.0.1:5000 +2025-11-15 00:24:01,635 [INFO] Press CTRL+C to quit +2025-11-15 00:24:01,639 [INFO] * Restarting with stat +2025-11-15 00:24:02,814 [WARNING] * Debugger is active! +2025-11-15 00:24:02,823 [INFO] * Debugger PIN: 735-403-005 +2025-11-15 00:29:28,357 [INFO] 127.0.0.1 - - [15/Nov/2025 00:29:28] "GET /file/1 HTTP/1.1" 404 - +2025-11-15 00:31:08,259 [INFO] 127.0.0.1 - - [15/Nov/2025 00:31:08] "GET /upload HTTP/1.1" 405 - +2025-11-15 00:32:18,071 [INFO] 127.0.0.1 - - [15/Nov/2025 00:32:18] "GET /upload HTTP/1.1" 405 - +2025-11-15 00:32:34,923 [INFO] 127.0.0.1 - - [15/Nov/2025 00:32:34] "GET /upload HTTP/1.1" 405 - +2025-11-15 00:33:01,070 [INFO] 127.0.0.1 - - [15/Nov/2025 00:33:01] "POST /upload HTTP/1.1" 400 - +2025-11-15 00:33:55,549 [INFO] 127.0.0.1 - - [15/Nov/2025 00:33:55] "POST /upload HTTP/1.1" 400 - +2025-11-15 00:34:30,958 [ERROR] Get error: [WinError 2] The system cannot find the file specified: 'C:\\Users\\Acer\\Documents\\PROGLAN\\Flask\\file-upload\\uploads\\e7397392533f47969c35392a182c498c_pexels-marek-piwnicki-3907296-11829369.jpg' +2025-11-15 00:34:30,961 [INFO] 127.0.0.1 - - [15/Nov/2025 00:34:30] "GET /files/2 HTTP/1.1" 400 - +2025-11-15 00:34:54,688 [INFO] 127.0.0.1 - - [15/Nov/2025 00:34:54] "GET /files/1 HTTP/1.1" 404 - +2025-11-15 00:34:59,866 [INFO] 127.0.0.1 - - [15/Nov/2025 00:34:59] "GET /files/3 HTTP/1.1" 200 - +2025-11-15 00:35:15,651 [INFO] 127.0.0.1 - - [15/Nov/2025 00:35:15] "POST /upload HTTP/1.1" 400 - +2025-11-15 00:36:27,595 [INFO] 127.0.0.1 - - [15/Nov/2025 00:36:27] "POST /upload HTTP/1.1" 400 - +2025-11-15 00:37:50,923 [INFO] 127.0.0.1 - - [15/Nov/2025 00:37:50] "POST /upload HTTP/1.1" 400 - +2025-11-15 00:38:06,609 [INFO] 127.0.0.1 - - [15/Nov/2025 00:38:06] "POST /upload HTTP/1.1" 400 - +2025-11-15 00:38:13,184 [INFO] 127.0.0.1 - - [15/Nov/2025 00:38:13] "POST /upload HTTP/1.1" 400 - +2025-11-15 00:39:07,513 [INFO] 127.0.0.1 - - [15/Nov/2025 00:39:07] "POST /upload HTTP/1.1" 400 - +2025-11-15 00:40:16,166 [INFO] 127.0.0.1 - - [15/Nov/2025 00:40:16] "POST /upload HTTP/1.1" 400 - +2025-11-15 00:40:57,725 [INFO] 127.0.0.1 - - [15/Nov/2025 00:40:57] "POST /upload HTTP/1.1" 400 - +2025-11-15 00:42:31,746 [INFO] 127.0.0.1 - - [15/Nov/2025 00:42:31] "GET /files/1 HTTP/1.1" 404 - +2025-11-15 00:42:34,105 [ERROR] Get error: [WinError 2] The system cannot find the file specified: 'C:\\Users\\Acer\\Documents\\PROGLAN\\Flask\\file-upload\\uploads\\e7397392533f47969c35392a182c498c_pexels-marek-piwnicki-3907296-11829369.jpg' +2025-11-15 00:42:34,107 [INFO] 127.0.0.1 - - [15/Nov/2025 00:42:34] "GET /files/2 HTTP/1.1" 400 - +2025-11-15 00:42:37,089 [INFO] 127.0.0.1 - - [15/Nov/2025 00:42:37] "GET /files/3 HTTP/1.1" 200 - +2025-11-15 00:43:04,050 [INFO] 127.0.0.1 - - [15/Nov/2025 00:43:04] "POST /post HTTP/1.1" 404 - +2025-11-15 00:43:14,520 [INFO] 127.0.0.1 - - [15/Nov/2025 00:43:14] "POST /upload HTTP/1.1" 400 - +2025-11-15 00:43:41,152 [INFO] 127.0.0.1 - - [15/Nov/2025 00:43:41] "POST /upload HTTP/1.1" 400 - +2025-11-15 00:43:53,662 [INFO] 127.0.0.1 - - [15/Nov/2025 00:43:53] "POST /api/upload HTTP/1.1" 404 - +2025-11-15 00:43:59,530 [INFO] 127.0.0.1 - - [15/Nov/2025 00:43:59] "POST /upload HTTP/1.1" 400 - +2025-11-15 00:44:00,227 [INFO] 127.0.0.1 - - [15/Nov/2025 00:44:00] "POST /upload HTTP/1.1" 400 - +2025-11-15 00:44:00,726 [INFO] 127.0.0.1 - - [15/Nov/2025 00:44:00] "POST /upload HTTP/1.1" 400 - +2025-11-15 00:44:00,916 [INFO] 127.0.0.1 - - [15/Nov/2025 00:44:00] "POST /upload HTTP/1.1" 400 - +2025-11-15 00:44:01,117 [INFO] 127.0.0.1 - - [15/Nov/2025 00:44:01] "POST /upload HTTP/1.1" 400 - +2025-11-15 00:44:01,288 [INFO] 127.0.0.1 - - [15/Nov/2025 00:44:01] "POST /upload HTTP/1.1" 400 - +2025-11-15 00:44:01,471 [INFO] 127.0.0.1 - - [15/Nov/2025 00:44:01] "POST /upload HTTP/1.1" 400 - +2025-11-15 00:44:01,652 [INFO] 127.0.0.1 - - [15/Nov/2025 00:44:01] "POST /upload HTTP/1.1" 400 - +2025-11-15 00:44:01,805 [INFO] 127.0.0.1 - - [15/Nov/2025 00:44:01] "POST /upload HTTP/1.1" 400 - +2025-11-15 00:44:01,931 [INFO] 127.0.0.1 - - [15/Nov/2025 00:44:01] "POST /upload HTTP/1.1" 400 - +2025-11-15 00:44:02,148 [INFO] 127.0.0.1 - - [15/Nov/2025 00:44:02] "POST /upload HTTP/1.1" 400 - +2025-11-15 00:44:37,624 [INFO] 127.0.0.1 - - [15/Nov/2025 00:44:37] "GET /upload HTTP/1.1" 405 - +2025-11-15 00:44:41,535 [INFO] 127.0.0.1 - - [15/Nov/2025 00:44:41] "POST /upload HTTP/1.1" 400 - +2025-11-15 00:44:49,139 [INFO] 127.0.0.1 - - [15/Nov/2025 00:44:49] "GET /files/3 HTTP/1.1" 200 - +2025-11-15 00:45:01,949 [INFO] 127.0.0.1 - - [15/Nov/2025 00:45:01] "GET /files HTTP/1.1" 404 - +2025-11-15 00:45:14,324 [INFO] 127.0.0.1 - - [15/Nov/2025 00:45:14] "POST /upload HTTP/1.1" 400 - +2025-11-15 00:45:55,814 [INFO] WARNING: This is a development server. Do not use it in a production deployment. Use a production WSGI server instead. + * Running on http://127.0.0.1:5000 +2025-11-15 00:45:55,814 [INFO] Press CTRL+C to quit +2025-11-15 00:45:55,816 [INFO] * Restarting with stat +2025-11-15 00:45:56,978 [WARNING] * Debugger is active! +2025-11-15 00:45:56,985 [INFO] * Debugger PIN: 735-403-005 +2025-11-15 00:46:02,352 [INFO] 127.0.0.1 - - [15/Nov/2025 00:46:02] "POST /upload HTTP/1.1" 400 - +2025-11-15 00:46:03,109 [INFO] 127.0.0.1 - - [15/Nov/2025 00:46:03] "POST /upload HTTP/1.1" 400 - +2025-11-15 00:46:03,633 [INFO] 127.0.0.1 - - [15/Nov/2025 00:46:03] "POST /upload HTTP/1.1" 400 - +2025-11-15 00:46:03,804 [INFO] 127.0.0.1 - - [15/Nov/2025 00:46:03] "POST /upload HTTP/1.1" 400 - +2025-11-15 00:46:04,005 [INFO] 127.0.0.1 - - [15/Nov/2025 00:46:04] "POST /upload HTTP/1.1" 400 - +2025-11-15 00:46:39,604 [INFO] 127.0.0.1 - - [15/Nov/2025 00:46:39] "POST /upload HTTP/1.1" 400 - +2025-11-15 00:46:40,376 [INFO] 127.0.0.1 - - [15/Nov/2025 00:46:40] "POST /upload HTTP/1.1" 400 - +2025-11-15 00:46:40,817 [INFO] 127.0.0.1 - - [15/Nov/2025 00:46:40] "POST /upload HTTP/1.1" 400 - +2025-11-15 00:46:55,786 [INFO] 127.0.0.1 - - [15/Nov/2025 00:46:55] "POST /upload HTTP/1.1" 400 - +2025-11-15 00:47:05,564 [INFO] 127.0.0.1 - - [15/Nov/2025 00:47:05] "POST /upload HTTP/1.1" 400 - +2025-11-15 00:47:10,233 [INFO] 127.0.0.1 - - [15/Nov/2025 00:47:10] "POST /upload HTTP/1.1" 400 - +2025-11-15 00:47:14,604 [INFO] 127.0.0.1 - - [15/Nov/2025 00:47:14] "POST /upload HTTP/1.1" 400 - +2025-11-15 00:47:26,979 [INFO] 127.0.0.1 - - [15/Nov/2025 00:47:26] "POST /upload HTTP/1.1" 400 - +2025-11-15 00:50:30,132 [INFO] File saved: uploads/2a048701f5d843598668de4561459bbb\7f88f9e2168a4844be751de23d34db1b_Untitled159_20251113190618_1.png +2025-11-15 00:50:30,144 [INFO] 127.0.0.1 - - [15/Nov/2025 00:50:30] "POST /upload HTTP/1.1" 201 - +2025-11-15 00:50:53,621 [INFO] 127.0.0.1 - - [15/Nov/2025 00:50:53] "GET /files/4 HTTP/1.1" 200 - +2025-11-15 01:05:08,731 [INFO] WARNING: This is a development server. Do not use it in a production deployment. Use a production WSGI server instead. + * Running on http://127.0.0.1:5000 +2025-11-15 01:05:08,732 [INFO] Press CTRL+C to quit +2025-11-15 01:05:08,734 [INFO] * Restarting with stat +2025-11-15 01:05:09,765 [WARNING] * Debugger is active! +2025-11-15 01:05:09,770 [INFO] * Debugger PIN: 898-574-838 +2025-11-15 01:06:15,721 [INFO] File saved: uploads/7511bc4a1c8645bcbef089483cd12939\1dbc7c5ae5614283b1115f60231371a3_Untitled159_20251113190618_1.png +2025-11-15 01:06:15,730 [INFO] 127.0.0.1 - - [15/Nov/2025 01:06:15] "POST /upload HTTP/1.1" 201 - +2025-11-15 01:06:47,886 [INFO] File saved: uploads/d353534fedc44726a3c20766c320bac4\083a03e9a44d4a81a9312981c053c5d8_Screenshot_2025-10-18-13-06-38-769_com.facebook.orca.jpg +2025-11-15 01:06:47,895 [INFO] 127.0.0.1 - - [15/Nov/2025 01:06:47] "POST /upload HTTP/1.1" 201 - +2025-11-15 01:07:01,822 [INFO] 127.0.0.1 - - [15/Nov/2025 01:07:01] "GET /files/1 HTTP/1.1" 404 - +2025-11-15 01:07:03,255 [ERROR] Get error: [WinError 2] The system cannot find the file specified: 'C:\\Users\\Acer\\Documents\\PROGLAN\\Flask\\jwt-authentication\\uploads\\e7397392533f47969c35392a182c498c_pexels-marek-piwnicki-3907296-11829369.jpg' +2025-11-15 01:07:03,258 [INFO] 127.0.0.1 - - [15/Nov/2025 01:07:03] "GET /files/2 HTTP/1.1" 400 - +2025-11-15 01:07:06,562 [INFO] 127.0.0.1 - - [15/Nov/2025 01:07:06] "GET /files/3 HTTP/1.1" 200 - +2025-11-15 01:07:09,282 [INFO] 127.0.0.1 - - [15/Nov/2025 01:07:09] "GET /files/4 HTTP/1.1" 200 - +2025-11-15 01:07:12,245 [INFO] 127.0.0.1 - - [15/Nov/2025 01:07:12] "GET /files/5 HTTP/1.1" 200 - +2025-11-15 01:07:16,624 [INFO] 127.0.0.1 - - [15/Nov/2025 01:07:16] "GET /files/6 HTTP/1.1" 200 - +2025-11-15 01:07:25,534 [ERROR] Delete error: File not found +2025-11-15 01:07:25,536 [INFO] 127.0.0.1 - - [15/Nov/2025 01:07:25] "DELETE /files/1 HTTP/1.1" 400 - +2025-11-15 01:07:28,222 [INFO] Record deleted: ID=2 +2025-11-15 01:07:28,222 [INFO] 127.0.0.1 - - [15/Nov/2025 01:07:28] "DELETE /files/2 HTTP/1.1" 200 - +2025-11-15 01:07:32,604 [INFO] File deleted from storage: uploads/7511bc4a1c8645bcbef089483cd12939\1dbc7c5ae5614283b1115f60231371a3_Untitled159_20251113190618_1.png +2025-11-15 01:07:32,607 [INFO] Record deleted: ID=5 +2025-11-15 01:07:32,608 [INFO] 127.0.0.1 - - [15/Nov/2025 01:07:32] "DELETE /files/5 HTTP/1.1" 200 - +2025-11-15 01:07:35,328 [INFO] File deleted from storage: uploads/d353534fedc44726a3c20766c320bac4\083a03e9a44d4a81a9312981c053c5d8_Screenshot_2025-10-18-13-06-38-769_com.facebook.orca.jpg +2025-11-15 01:07:35,336 [INFO] Record deleted: ID=6 +2025-11-15 01:07:35,337 [INFO] 127.0.0.1 - - [15/Nov/2025 01:07:35] "DELETE /files/6 HTTP/1.1" 200 - +2025-11-15 01:07:44,148 [INFO] 127.0.0.1 - - [15/Nov/2025 01:07:44] "GET /files/1 HTTP/1.1" 404 - +2025-11-15 01:07:45,291 [INFO] 127.0.0.1 - - [15/Nov/2025 01:07:45] "GET /files/2 HTTP/1.1" 404 - +2025-11-15 01:07:46,852 [INFO] 127.0.0.1 - - [15/Nov/2025 01:07:46] "GET /files/3 HTTP/1.1" 200 - +2025-11-15 01:07:50,058 [INFO] 127.0.0.1 - - [15/Nov/2025 01:07:50] "GET /files/4 HTTP/1.1" 200 - +2025-11-15 01:07:53,702 [INFO] 127.0.0.1 - - [15/Nov/2025 01:07:53] "GET /files/5 HTTP/1.1" 404 - +2025-11-15 01:33:31,607 [INFO] WARNING: This is a development server. Do not use it in a production deployment. Use a production WSGI server instead. + * Running on http://127.0.0.1:5000 +2025-11-15 01:33:31,608 [INFO] Press CTRL+C to quit +2025-11-15 01:33:31,610 [INFO] * Restarting with stat +2025-11-15 01:33:32,699 [WARNING] * Debugger is active! +2025-11-15 01:33:32,716 [INFO] * Debugger PIN: 898-574-838 +2025-11-15 01:36:12,916 [ERROR] Login error +Traceback (most recent call last): + File "C:\Users\Acer\Documents\PROGLAN\Flask\jwt-authentication\.venv\Lib\site-packages\werkzeug\wrappers\request.py", line 611, in get_json + rv = self.json_module.loads(data) + File "C:\Users\Acer\Documents\PROGLAN\Flask\jwt-authentication\.venv\Lib\site-packages\flask\json\provider.py", line 187, in loads + return json.loads(s, **kwargs) + ~~~~~~~~~~^^^^^^^^^^^^^ + File "C:\Program Files\Python313\Lib\json\__init__.py", line 346, in loads + return _default_decoder.decode(s) + ~~~~~~~~~~~~~~~~~~~~~~~^^^ + File "C:\Program Files\Python313\Lib\json\decoder.py", line 345, in decode + obj, end = self.raw_decode(s, idx=_w(s, 0).end()) + ~~~~~~~~~~~~~~~^^^^^^^^^^^^^^^^^^^^^^^ + File "C:\Program Files\Python313\Lib\json\decoder.py", line 361, in raw_decode + obj, end = self.scan_once(s, idx) + ~~~~~~~~~~~~~~^^^^^^^^ +json.decoder.JSONDecodeError: Expecting ',' delimiter: line 3 column 5 (char 32) + +During handling of the above exception, another exception occurred: + +Traceback (most recent call last): + File "C:\Users\Acer\Documents\PROGLAN\Flask\jwt-authentication\controllers\auth_controller.py", line 13, in login + data = request.get_json() + File "C:\Users\Acer\Documents\PROGLAN\Flask\jwt-authentication\.venv\Lib\site-packages\werkzeug\wrappers\request.py", line 620, in get_json + rv = self.on_json_loading_failed(e) + File "C:\Users\Acer\Documents\PROGLAN\Flask\jwt-authentication\.venv\Lib\site-packages\flask\wrappers.py", line 214, in on_json_loading_failed + return super().on_json_loading_failed(e) + ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~^^^ + File "C:\Users\Acer\Documents\PROGLAN\Flask\jwt-authentication\.venv\Lib\site-packages\werkzeug\wrappers\request.py", line 645, in on_json_loading_failed + raise BadRequest(f"Failed to decode JSON object: {e}") +werkzeug.exceptions.BadRequest: 400 Bad Request: Failed to decode JSON object: Expecting ',' delimiter: line 3 column 5 (char 32) +2025-11-15 01:36:13,123 [INFO] 127.0.0.1 - - [15/Nov/2025 01:36:13] "POST /login HTTP/1.1" 400 - +2025-11-15 01:36:24,631 [INFO] Login SUCCESS - user=admin ip=127.0.0.1 +2025-11-15 01:36:24,631 [INFO] 127.0.0.1 - - [15/Nov/2025 01:36:24] "POST /login HTTP/1.1" 200 - +2025-11-15 01:36:50,385 [WARNING] Login FAILED - invalid credentials - user=admin ip=127.0.0.1 +2025-11-15 01:36:50,386 [INFO] 127.0.0.1 - - [15/Nov/2025 01:36:50] "POST /login HTTP/1.1" 401 - +2025-11-15 01:37:32,783 [WARNING] Login FAILED - invalid credentials - user=admin ip=127.0.0.1 +2025-11-15 01:37:32,783 [INFO] 127.0.0.1 - - [15/Nov/2025 01:37:32] "POST /login HTTP/1.1" 401 - +2025-11-15 01:38:07,230 [INFO] WARNING: This is a development server. Do not use it in a production deployment. Use a production WSGI server instead. + * Running on http://127.0.0.1:5000 +2025-11-15 01:38:07,230 [INFO] Press CTRL+C to quit +2025-11-15 01:38:07,232 [INFO] * Restarting with stat +2025-11-15 01:38:08,217 [WARNING] * Debugger is active! +2025-11-15 01:38:08,228 [INFO] * Debugger PIN: 898-574-838 +2025-11-15 01:38:11,840 [WARNING] Login FAILED - invalid credentials - user=admin ip=127.0.0.1 +2025-11-15 01:38:11,841 [INFO] 127.0.0.1 - - [15/Nov/2025 01:38:11] "POST /login HTTP/1.1" 401 - +2025-11-15 01:38:32,889 [INFO] Login ATTEMPT - missing credentials - ip=127.0.0.1 username=admin +2025-11-15 01:38:32,890 [INFO] 127.0.0.1 - - [15/Nov/2025 01:38:32] "POST /login HTTP/1.1" 400 - +2025-11-15 01:39:34,672 [INFO] Login ATTEMPT - missing credentials - ip=127.0.0.1 username=None +2025-11-15 01:39:34,673 [INFO] 127.0.0.1 - - [15/Nov/2025 01:39:34] "POST /login HTTP/1.1" 400 - +2025-11-15 01:39:53,736 [INFO] Login ATTEMPT - missing credentials - ip=127.0.0.1 username=None +2025-11-15 01:39:53,737 [INFO] 127.0.0.1 - - [15/Nov/2025 01:39:53] "POST /login HTTP/1.1" 400 - +2025-11-15 01:40:22,205 [INFO] Login ATTEMPT - missing credentials - ip=127.0.0.1 username=None +2025-11-15 01:40:22,206 [INFO] 127.0.0.1 - - [15/Nov/2025 01:40:22] "POST /login HTTP/1.1" 400 - +2025-11-15 01:40:46,869 [ERROR] Login error +Traceback (most recent call last): + File "C:\Users\Acer\Documents\PROGLAN\Flask\jwt-authentication\.venv\Lib\site-packages\werkzeug\wrappers\request.py", line 611, in get_json + rv = self.json_module.loads(data) + File "C:\Users\Acer\Documents\PROGLAN\Flask\jwt-authentication\.venv\Lib\site-packages\flask\json\provider.py", line 187, in loads + return json.loads(s, **kwargs) + ~~~~~~~~~~^^^^^^^^^^^^^ + File "C:\Program Files\Python313\Lib\json\__init__.py", line 346, in loads + return _default_decoder.decode(s) + ~~~~~~~~~~~~~~~~~~~~~~~^^^ + File "C:\Program Files\Python313\Lib\json\decoder.py", line 345, in decode + obj, end = self.raw_decode(s, idx=_w(s, 0).end()) + ~~~~~~~~~~~~~~~^^^^^^^^^^^^^^^^^^^^^^^ + File "C:\Program Files\Python313\Lib\json\decoder.py", line 363, in raw_decode + raise JSONDecodeError("Expecting value", s, err.value) from None +json.decoder.JSONDecodeError: Expecting value: line 1 column 1 (char 0) + +During handling of the above exception, another exception occurred: + +Traceback (most recent call last): + File "C:\Users\Acer\Documents\PROGLAN\Flask\jwt-authentication\controllers\auth_controller.py", line 13, in login + data = request.get_json() + File "C:\Users\Acer\Documents\PROGLAN\Flask\jwt-authentication\.venv\Lib\site-packages\werkzeug\wrappers\request.py", line 620, in get_json + rv = self.on_json_loading_failed(e) + File "C:\Users\Acer\Documents\PROGLAN\Flask\jwt-authentication\.venv\Lib\site-packages\flask\wrappers.py", line 214, in on_json_loading_failed + return super().on_json_loading_failed(e) + ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~^^^ + File "C:\Users\Acer\Documents\PROGLAN\Flask\jwt-authentication\.venv\Lib\site-packages\werkzeug\wrappers\request.py", line 645, in on_json_loading_failed + raise BadRequest(f"Failed to decode JSON object: {e}") +werkzeug.exceptions.BadRequest: 400 Bad Request: Failed to decode JSON object: Expecting value: line 1 column 1 (char 0) +2025-11-15 01:40:46,883 [INFO] 127.0.0.1 - - [15/Nov/2025 01:40:46] "POST /login HTTP/1.1" 400 - +2025-11-15 01:41:21,221 [WARNING] Login FAILED - invalid credentials - user=admin ip=127.0.0.1 +2025-11-15 01:41:21,222 [INFO] 127.0.0.1 - - [15/Nov/2025 01:41:21] "POST /login HTTP/1.1" 401 - +2025-11-15 01:41:42,748 [INFO] Login SUCCESS - user=admin ip=127.0.0.1 +2025-11-15 01:41:42,749 [INFO] 127.0.0.1 - - [15/Nov/2025 01:41:42] "POST /login HTTP/1.1" 200 - +2025-11-15 01:42:10,045 [INFO] 127.0.0.1 - - [15/Nov/2025 01:42:10] "POST /files/3 HTTP/1.1" 405 - +2025-11-15 01:42:16,675 [INFO] 127.0.0.1 - - [15/Nov/2025 01:42:16] "GET /files/3 HTTP/1.1" 200 - +2025-11-15 01:42:20,140 [INFO] 127.0.0.1 - - [15/Nov/2025 01:42:20] "GET /files/4 HTTP/1.1" 200 - +2025-11-15 01:42:48,766 [INFO] 127.0.0.1 - - [15/Nov/2025 01:42:48] "PUT /files/4 HTTP/1.1" 400 - +2025-11-15 01:42:53,436 [INFO] File saved: uploads\5a438d6d81e24b8ca3183e90baede4d5_Untitled159_20251113190618.png +2025-11-15 01:42:53,452 [INFO] File updated: ID=4 +2025-11-15 01:42:53,457 [INFO] 127.0.0.1 - - [15/Nov/2025 01:42:53] "PUT /files/4 HTTP/1.1" 200 - +2025-11-15 01:43:05,610 [INFO] 127.0.0.1 - - [15/Nov/2025 01:43:05] "GET /files/4 HTTP/1.1" 200 - +2025-11-15 01:44:16,465 [INFO] File saved: uploads/0d438fc8728a46c4912349fd10fd144e\b672a14819a740a2820633e6d8a5b0d1_Foggy_Mountain.jpg +2025-11-15 01:44:16,476 [INFO] 127.0.0.1 - - [15/Nov/2025 01:44:16] "POST /upload HTTP/1.1" 201 - +2025-11-15 01:44:48,025 [INFO] 127.0.0.1 - - [15/Nov/2025 01:44:48] "GET /files/7 HTTP/1.1" 200 - +2025-11-15 01:44:53,542 [INFO] 127.0.0.1 - - [15/Nov/2025 01:44:53] "GET /files/6 HTTP/1.1" 404 - +2025-11-15 01:44:56,148 [INFO] 127.0.0.1 - - [15/Nov/2025 01:44:56] "GET /files/7 HTTP/1.1" 200 - +2025-11-15 01:44:58,416 [INFO] 127.0.0.1 - - [15/Nov/2025 01:44:58] "GET /files/8 HTTP/1.1" 200 - +2025-11-15 01:45:05,332 [INFO] File deleted from storage: uploads/0d438fc8728a46c4912349fd10fd144e\b672a14819a740a2820633e6d8a5b0d1_Foggy_Mountain.jpg +2025-11-15 01:45:05,342 [INFO] Record deleted: ID=8 +2025-11-15 01:45:05,342 [INFO] 127.0.0.1 - - [15/Nov/2025 01:45:05] "DELETE /files/8 HTTP/1.1" 200 - +2025-11-15 01:45:09,775 [INFO] File deleted from storage: uploads\5a438d6d81e24b8ca3183e90baede4d5_Untitled159_20251113190618.png +2025-11-15 01:45:09,783 [INFO] Record deleted: ID=7 +2025-11-15 01:45:09,784 [INFO] 127.0.0.1 - - [15/Nov/2025 01:45:09] "DELETE /files/7 HTTP/1.1" 200 - +2025-11-15 01:45:22,905 [INFO] 127.0.0.1 - - [15/Nov/2025 01:45:22] "GET /files HTTP/1.1" 404 - diff --git a/models/__pycache__/uploaded_file.cpython-313.pyc b/models/__pycache__/uploaded_file.cpython-313.pyc new file mode 100644 index 0000000..b300b70 Binary files /dev/null and b/models/__pycache__/uploaded_file.cpython-313.pyc differ diff --git a/models/uploaded_file.py b/models/uploaded_file.py new file mode 100644 index 0000000..73ac5be --- /dev/null +++ b/models/uploaded_file.py @@ -0,0 +1,6 @@ +from extensions import db + +class UploadedFile(db.Model): + id = db.Column(db.Integer, primary_key=True) + filename = db.Column(db.String(255), nullable=False) + file_path = db.Column(db.String(255), nullable=False) \ No newline at end of file diff --git a/requirements.txt b/requirements.txt new file mode 100644 index 0000000..a2fbb49 Binary files /dev/null and b/requirements.txt differ diff --git a/services/__pycache__/file_service.cpython-313.pyc b/services/__pycache__/file_service.cpython-313.pyc new file mode 100644 index 0000000..7982fee Binary files /dev/null and b/services/__pycache__/file_service.cpython-313.pyc differ diff --git a/services/file_service.py b/services/file_service.py new file mode 100644 index 0000000..12bc71d --- /dev/null +++ b/services/file_service.py @@ -0,0 +1,57 @@ +import os +import uuid +from werkzeug.utils import secure_filename +from models.uploaded_file import UploadedFile +from extensions import db +import logging + +ALLOWED_EXTENSIONS = {'png', 'jpg', 'jpeg', 'pdf', 'txt'} + +def allowed_file(filename): + return '.' in filename and filename.rsplit('.', 1)[1].lower() in ALLOWED_EXTENSIONS + +def save_file(file, folder): + if not allowed_file(file.filename): + raise ValueError("File type not allowed") + + os.makedirs(folder, exist_ok=True) + filename = secure_filename(file.filename) + unique_name = f"{uuid.uuid4().hex}_{filename}" + save_path = os.path.join(folder, unique_name) + file.save(save_path) + + new_file = UploadedFile(filename=unique_name, file_path=save_path) + db.session.add(new_file) + db.session.commit() + logging.info(f"File saved: {save_path}") + + return new_file + +def update_file(file_id, new_file, base_folder): + existing = UploadedFile.query.get(file_id) + if not existing: + raise ValueError("File not found") + + if os.path.exists(existing.file_path): + os.remove(existing.file_path) + + new_record = save_file(new_file, base_folder) + existing.filename = new_record.filename + existing.file_path = new_record.file_path + db.session.commit() + logging.info(f"File updated: ID={file_id}") + + return existing + +def delete_file(file_id): + file_record = UploadedFile.query.get(file_id) + if not file_record: + raise ValueError("File not found") + + if os.path.exists(file_record.file_path): + os.remove(file_record.file_path) + logging.info(f"File deleted from storage: {file_record.file_path}") + + db.session.delete(file_record) + db.session.commit() + logging.info(f"Record deleted: ID={file_id}") \ No newline at end of file diff --git a/uploads/76a9428a06704f839906bb239652e160/9527dee13c174d56bd669078d241b29a_Screenshot_2025-10-18-13-06-38-769_com.facebook.orca.jpg b/uploads/76a9428a06704f839906bb239652e160/9527dee13c174d56bd669078d241b29a_Screenshot_2025-10-18-13-06-38-769_com.facebook.orca.jpg new file mode 100644 index 0000000..69874eb Binary files /dev/null and b/uploads/76a9428a06704f839906bb239652e160/9527dee13c174d56bd669078d241b29a_Screenshot_2025-10-18-13-06-38-769_com.facebook.orca.jpg differ