[+] Upload route

This commit is contained in:
Charles Le Maux 2024-09-10 01:05:25 +02:00
parent a7decf8dac
commit c46e04f7f1

66
app.py
View File

@ -1,16 +1,23 @@
import atexit
import http import http
import inspect import inspect
import os
from mailbox import FormatError
from typing import Union from typing import Union
from apscheduler.schedulers.background import BackgroundScheduler
from apscheduler.schedulers.background import BackgroundScheduler
from firebase_admin.auth import UserNotFoundError, UserRecord
from flask import (Blueprint, Flask, Response, jsonify, request) from flask import (Blueprint, Flask, Response, jsonify, request)
from flask_cors import CORS from flask_cors import CORS
from werkzeug.datastructures import ImmutableMultiDict, FileStorage
from werkzeug.utils import secure_filename
import file_manager
import firebase_manager import firebase_manager
import generic_executor import generic_executor
import atexit
app = Flask(__name__) app = Flask(__name__)
app.config['MAX_CONTENT_LENGTH'] = 16 * 1000 * 1000 * 1000
cors = CORS(app, origins="*") cors = CORS(app, origins="*")
apiBP = Blueprint('apiBP', 'BPapi') apiBP = Blueprint('apiBP', 'BPapi')
@ -28,7 +35,7 @@ def generic_response_maker(status_code: http.HTTPStatus, _message: str = None) -
case http.HTTPStatus.ACCEPTED: case http.HTTPStatus.ACCEPTED:
message = jsonify({'message': 'Action successful.'}) message = jsonify({'message': 'Action successful.'})
case http.HTTPStatus.BAD_REQUEST: case http.HTTPStatus.BAD_REQUEST:
message = jsonify({'message': 'Bad Request, the property you tried to modify is not valid.'}) message = jsonify({'message': 'Bad Request.'})
case http.HTTPStatus.NOT_FOUND: case http.HTTPStatus.NOT_FOUND:
message = jsonify({'message': 'Server not found.'}) message = jsonify({'message': 'Server not found.'})
case http.HTTPStatus.UNSUPPORTED_MEDIA_TYPE: case http.HTTPStatus.UNSUPPORTED_MEDIA_TYPE:
@ -118,6 +125,59 @@ def dynamic_route_handler(path):
return generic_response_maker(http.HTTPStatus.BAD_REQUEST, str(e)) return generic_response_maker(http.HTTPStatus.BAD_REQUEST, str(e))
# [!] This route is specific and has to remain out of the dynamic route handler.
@apiBP.route('/Upload', methods=['POST'])
def upload():
form = request.form
token: str or None = form.get('token')
name: str or None = form.get('name')
files: ImmutableMultiDict[str, FileStorage] = request.files
try:
if not form:
raise FormatError(0)
if not files:
raise FormatError(1)
if not token:
raise KeyError('token')
if not name:
raise KeyError('name')
data: dict = {'token': token}
user: UserRecord = authenticate_request(data)
user_id: str = user.uid
for _, file in files.items():
filename = file.filename
internal_path = file_manager.get_path_from_extension(filename)
if internal_path is None:
continue
filename = secure_filename(filename)
file.save(os.path.join(f"users/{user_id}/{name}/{internal_path}", filename))
except FormatError as e:
match e:
case 0:
return generic_response_maker(http.HTTPStatus.BAD_REQUEST, "No FormData found in the payload.")
case 1:
return generic_response_maker(http.HTTPStatus.NOT_ACCEPTABLE, "No file(s) were uploaded.")
except FileNotFoundError as e:
return generic_response_maker(http.HTTPStatus.CONFLICT, "Please launch the server at least once.")
except KeyError as e:
return f"Missing parameter {e} in FormData.", http.HTTPStatus.BAD_REQUEST
except UserNotFoundError as e:
return str(e), http.HTTPStatus.BAD_REQUEST
except Exception as e:
file_manager.log_error(type(e).__name__, str(e))
return generic_response_maker(http.HTTPStatus.BAD_REQUEST, f"{type(e).__name__}, {str(e)}")
return generic_response_maker(http.HTTPStatus.OK, "Successfully uploaded files !")
def exit_safety() -> None: def exit_safety() -> None:
firebase_manager.set_servers_not_running() firebase_manager.set_servers_not_running()
return return