Initial Version

This commit is contained in:
Firq 2024-09-30 20:40:26 +02:00
commit 3046b1ee7b
Signed by: Firq
GPG key ID: 3ACC61C8CEC83C20
21 changed files with 491 additions and 0 deletions
support_formatter/routes

View file

@ -0,0 +1,7 @@
# pylint: disable=wrong-import-position,cyclic-import
from flask_smorest import Blueprint
interface_routes = Blueprint("interface", "interface", url_prefix="/", description="")
formatter_routes = Blueprint("formatter", "formatter", url_prefix="/", description="")
from . import interface, upload # avoids circular imports problem

View file

@ -0,0 +1,38 @@
from datetime import datetime
from flask import redirect, url_for
from flask.views import MethodView
from ..app import Application
from ..config import APISettings
from ..models.interface import ApiVersionGet, HealthGet, HealthStatus, OpenAPIGet
from . import interface_routes as blp
APP = Application.get_instance()
@blp.route("/health")
class ApiVersion(MethodView):
@blp.doc(summary="Returns the status and alive-time of the server")
@blp.response(200, HealthGet, description="Successful operation")
def get(self):
response = {
"alive_since": datetime.strftime(APP.alive_since, "%d.%m.%Y %H:%M:%S"),
"alive_for": str(datetime.now() - APP.alive_since),
"status": HealthStatus.OK
}
return response
@blp.route("/openapi")
class ApiVersion(MethodView):
@blp.doc(summary="Get the OpenAPI spec as a JSON.")
@blp.response(200, OpenAPIGet, description="Successful operation")
def get(self):
return redirect(url_for('api-docs.openapi_json'))
@blp.route("/version")
class ApiVersion(MethodView):
@blp.doc(summary="Get the REST interface version identification.")
@blp.response(200, ApiVersionGet, description="Successful operation")
def get(self):
return { "version": APISettings.API_VERSION }

View file

@ -0,0 +1,70 @@
import os
import pathlib
from typing import List
from flask import send_from_directory
import marshmallow as ma
from flask_smorest.fields import Upload
from werkzeug.datastructures import FileStorage
import uuid
from ..app import Application
from ..config import APISettings
from ..logic.csv_processor import process_csv, FileTypeInvalidError
from . import formatter_routes as blp
APP = Application.get_instance()
def allowed_file(filename):
return '.' in filename and filename.rsplit('.', 1)[1].lower() in APISettings.ALLOWED_EXTENSIONS
class MultipartFormSchema(ma.Schema):
username = ma.fields.String(required=True)
friendcode = ma.fields.String(required=False)
class MultipartFileSchema(ma.Schema):
servantdata = Upload()
cedata = Upload()
@blp.route("/", methods=["POST"])
@blp.arguments(MultipartFormSchema, location="form")
@blp.arguments(MultipartFileSchema, location="files")
@blp.response(200)
def upload_file(form: dict[str, str], files: dict[str, FileStorage]):
filepaths: List[pathlib.Path] = []
returndata = {
"username": form["username"],
"friendcode": form.get("friendcode", "")
}
for name, file in files.items():
if name not in ("servantdata", "cedata"):
return send_from_directory(APISettings.PAGES_DIRECTORY, "error.html")
filepath = APISettings.FILE_SAVE_DIRECTORY / f"{uuid.uuid4()}.csv"
file.save(filepath)
if os.stat(filepath).st_size < 1 or not allowed_file(file.filename):
filepath.unlink()
continue
filepaths.append(filepath)
if len(filepaths) == 0:
return send_from_directory(APISettings.PAGES_DIRECTORY, "error.html")
try:
for f in filepaths:
result = process_csv(f)
returndata = returndata | result
f.unlink()
except FileTypeInvalidError:
for f in filepaths:
f.unlink()
return send_from_directory(APISettings.PAGES_DIRECTORY, "error.html")
return returndata
@blp.route("/", methods=["GET"])
def file_dialog():
return send_from_directory(APISettings.PAGES_DIRECTORY, "index.html")