Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 2 additions & 0 deletions .gitignore
Original file line number Diff line number Diff line change
@@ -0,0 +1,2 @@
.env
.venv
Binary file added __pycache__/config.cpython-313.pyc
Binary file not shown.
Binary file added __pycache__/extensions.cpython-313.pyc
Binary file not shown.
40 changes: 40 additions & 0 deletions app.py
Original file line number Diff line number Diff line change
@@ -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)
14 changes: 14 additions & 0 deletions config.py
Original file line number Diff line number Diff line change
@@ -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
Binary file not shown.
Binary file not shown.
39 changes: 39 additions & 0 deletions controllers/auth_controller.py
Original file line number Diff line number Diff line change
@@ -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
71 changes: 71 additions & 0 deletions controllers/file_controller.py
Original file line number Diff line number Diff line change
@@ -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/<int:file_id>', 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/<int:file_id>', 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/<int:file_id>', 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
3 changes: 3 additions & 0 deletions extensions.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,3 @@
from flask_sqlalchemy import SQLAlchemy

db = SQLAlchemy()
Loading