diff --git a/backend/controller_group.py b/backend/controller_group.py index ed715a4..71943e7 100644 --- a/backend/controller_group.py +++ b/backend/controller_group.py @@ -223,7 +223,6 @@ def get_group_members_control( raise BackendError("Backend Error: Group does not exist", "306") if not Validator().check_user_in_group(user_id, group_id): raise BackendError("Backend Error: User not in group", "308") - with db_operation() as data_cursor: # Get all users in the group data_cursor.execute( @@ -235,10 +234,10 @@ def get_group_members_control( (group_id,), ) user_ids = [row[0] for row in data_cursor.fetchall()] - + if not user_ids: return [] - + # Get user information for each member placeholders = ",".join("?" for _ in user_ids) data_cursor.execute( @@ -250,13 +249,13 @@ def get_group_members_control( user_ids, ) members_data = data_cursor.fetchall() - + # Create a list of member dictionaries members = [ {"user_id": member_id, "username": member_name, "email": member_email} for member_id, member_name, member_email in members_data ] - + return members diff --git a/backend/controller_image.py b/backend/controller_image.py new file mode 100644 index 0000000..0b1f598 --- /dev/null +++ b/backend/controller_image.py @@ -0,0 +1,267 @@ +# coding: utf-8 +"""This module handles image processing and storage.""" + +from os import remove +from os.path import exists, join +from typing import Any + +from werkzeug.utils import secure_filename + +from error import BackendError +from utils import db_operation +from validator import Validator, UPLOAD_FOLDER, ALLOWED_EXTENSIONS + + +class ImageController: + """This class will handle the image.""" + + def __init__(self) -> None: + """Initialize the image controller.""" + return + + def allowed_file(self, filename: str) -> bool: + """Check if the file has an allowed extension.""" + return ( + "." in filename and filename.rsplit(".", 1)[1].lower() in ALLOWED_EXTENSIONS + ) + + def get_user_image_control( + self, + image_url: str, + user_id: str, + password: str, + ) -> str: + """Gets the user image.""" + if not Validator().check_user_exists(user_id=user_id): + raise BackendError("Backend Error: User does not exist", "304") + if not Validator().check_password(user_id=user_id, password=password): + raise BackendError("Backend Error: Password is incorrect", "305") + if not exists(image_url): + raise BackendError("Backend Error: Image does not exist", "313") + return image_url + + def get_task_image_control( + self, + request_data: dict[str, Any], + ) -> str: + """Gets the task image.""" + if not Validator().check_user_exists(user_id=request_data["user_id"]): + raise BackendError("Backend Error: User does not exist", "304") + if not Validator().check_password( + user_id=request_data["user_id"], password=request_data["password"] + ): + raise BackendError("Backend Error: Password is incorrect", "305") + if not Validator().check_task_exists(task_id=request_data["task_id"]): + raise BackendError("Backend Error: Task does not exist", "309") + if (request_data["group_id"] != "0") and not Validator().check_group_exists( + group_id=request_data["group_id"] + ): + raise BackendError("Backend Error: Group does not exist", "306") + if not exists(request_data["image_url"]): + raise BackendError("Backend Error: Image does not exist", "313") + return request_data["image_url"] + + def upload_user_image_control( + self, + user_id: str, + password: str, + file, + ) -> str: + """Uploads the user image.""" + if not Validator().check_user_exists(user_id=user_id): + raise BackendError("Backend Error: User does not exist", "304") + if not Validator().check_password(user_id=user_id, password=password): + raise BackendError("Backend Error: Password is incorrect", "305") + + if not file or not self.allowed_file(file.filename): + raise BackendError("Backend Error: Invalid file type", "312") + + filename = secure_filename(file.filename) + file_path = join(UPLOAD_FOLDER, filename) + file.save(file_path) + + with db_operation() as data_cursor: + data_cursor.execute( + "UPDATE user SET image_path = ? WHERE uuid = ?;", + (file_path, user_id), + ) + + return file_path + + def upload_task_image_control( + self, + request_data: dict[str, Any], + file, + ) -> str: + """Uploads the task image.""" + if not Validator().check_user_exists(user_id=request_data["user_id"]): + raise BackendError("Backend Error: User does not exist", "304") + if not Validator().check_password( + user_id=request_data["user_id"], password=request_data["password"] + ): + raise BackendError("Backend Error: Password is incorrect", "305") + if not Validator().check_task_exists(task_id=request_data["task_id"]): + raise BackendError("Backend Error: Task does not exist", "309") + if (request_data["group_id"] != "0") and not Validator().check_group_exists( + group_id=request_data["group_id"] + ): + raise BackendError("Backend Error: Group does not exist", "306") + + if not file or not self.allowed_file(file.filename): + raise BackendError("Backend Error: Invalid file type", "312") + + filename = secure_filename(file.filename) + file_path = join(UPLOAD_FOLDER, filename) + file.save(file_path) + + with db_operation() as data_cursor: + data_cursor.execute( + "UPDATE task SET image_path = ? WHERE uuid = ?;", + (file_path, request_data["task_id"]), + ) + + return file_path + + def edit_user_image_control( + self, + user_id: str, + password: str, + file, + ) -> str: + """Edits the user image.""" + if not Validator().check_user_exists(user_id=user_id): + raise BackendError("Backend Error: User does not exist", "304") + if not Validator().check_password(user_id=user_id, password=password): + raise BackendError("Backend Error: Password is incorrect", "305") + + if not file or not self.allowed_file(file.filename): + raise BackendError("Backend Error: Invalid file type", "312") + + filename = secure_filename(file.filename) + file_path = join(UPLOAD_FOLDER, filename) + file.save(file_path) + + with db_operation() as data_cursor: + data_cursor.execute( + "UPDATE user SET image_path = ? WHERE uuid = ?;", + (file_path, user_id), + ) + + return file_path + + def edit_task_image_control( + self, + request_data: dict[str, Any], + file, + ) -> str: + """Edits the task image.""" + if not Validator().check_user_exists(user_id=request_data["user_id"]): + raise BackendError("Backend Error: User does not exist", "304") + if not Validator().check_password( + user_id=request_data["user_id"], password=request_data["password"] + ): + raise BackendError("Backend Error: Password is incorrect", "305") + if not Validator().check_task_exists(task_id=request_data["task_id"]): + raise BackendError("Backend Error: Task does not exist", "309") + if (request_data["group_id"] != "0") and not Validator().check_group_exists( + group_id=request_data["group_id"] + ): + raise BackendError("Backend Error: Group does not exist", "306") + + if not file or not self.allowed_file(file.filename): + raise BackendError("Backend Error: Invalid file type", "312") + + filename = secure_filename(file.filename) + file_path = join(UPLOAD_FOLDER, filename) + file.save(file_path) + + with db_operation() as data_cursor: + data_cursor.execute( + "UPDATE task SET image_path = ? WHERE uuid = ?;", + (file_path, request_data["task_id"]), + ) + + return file_path + + def delete_user_image_control( + self, + user_id: str, + password: str, + ) -> None: + """Deletes the user image.""" + if not Validator().check_user_exists(user_id=user_id): + raise BackendError("Backend Error: User does not exist", "304") + if not Validator().check_password(user_id=user_id, password=password): + raise BackendError("Backend Error: Password is incorrect", "305") + + with db_operation() as data_cursor: + data_cursor.execute( + "SELECT image_path FROM user WHERE uuid = ?;", + (user_id,), + ) + result = data_cursor.fetchone() + if not result: + raise BackendError("Backend Error: Image does not exist", "313") + remove(result[0]) + try: + remove(result[0]) + except FileNotFoundError as err: + raise BackendError( + "Backend Error: Image does not exist", "313" + ) from err + except Exception as err: + raise BackendError( + "Backend Error: Failed to delete image", "203" + ) from err + + data_cursor.execute( + "UPDATE user SET image_path = NULL WHERE uuid = ?;", + (user_id,), + ) + + def delete_task_image_control( + self, + request_data: dict[str, Any], + ) -> None: + """Deletes the task image.""" + if not Validator().check_user_exists(user_id=request_data["user_id"]): + raise BackendError("Backend Error: User does not exist", "304") + if not Validator().check_password( + user_id=request_data["user_id"], password=request_data["password"] + ): + raise BackendError("Backend Error: Password is incorrect", "305") + if not Validator().check_task_exists(task_id=request_data["task_id"]): + raise BackendError("Backend Error: Task does not exist", "309") + if (request_data["group_id"] != "0") and not Validator().check_group_exists( + group_id=request_data["group_id"] + ): + raise BackendError("Backend Error: Group does not exist", "306") + + with db_operation() as data_cursor: + data_cursor.execute( + "SELECT image_path FROM task WHERE uuid = ?;", + (request_data["task_id"],), + ) + result = data_cursor.fetchone() + if not result: + raise BackendError("Backend Error: Image does not exist", "313") + remove(result[0]) + try: + remove(result[0]) + except FileNotFoundError as err: + raise BackendError( + "Backend Error: Image does not exist", "313" + ) from err + except Exception as err: + raise BackendError( + "Backend Error: Failed to delete image", "203" + ) from err + + data_cursor.execute( + "UPDATE task SET image_path = NULL WHERE uuid = ?;", + (request_data["task_id"],), + ) + + +if __name__ == "__main__": + print("This module is not meant to be run directly.") diff --git a/backend/controller_invite.py b/backend/controller_invite.py index 92ed60d..720b0dc 100644 --- a/backend/controller_invite.py +++ b/backend/controller_invite.py @@ -1,3 +1,4 @@ +# coding: utf-8 """This module handles the functions related toi invites for database.""" from datetime import datetime, timezone @@ -68,7 +69,7 @@ def get_pending_control( invites_data: list[tuple] = data_cursor.fetchall() if not invites_data: - return {} # Return early if no invites + return {} # 2. Collect unique IDs group_ids = {item[2] for item in invites_data} diff --git a/backend/controller_task.py b/backend/controller_task.py index 0a53496..d01f1b4 100644 --- a/backend/controller_task.py +++ b/backend/controller_task.py @@ -1,6 +1,9 @@ # coding: utf-8 """This module controls the task data between the sqlite database.""" +from os import remove +from os.path import exists + from datetime import datetime from typing import Any from uuid import uuid4 @@ -37,7 +40,6 @@ def add_task_control( task_id: str = str(uuid4()) while Validator().check_duplicate_id(data_table="task", given_id=task_id): task_id = str(uuid4()) - image_path = "TODO CHANGE HERE" task_due: float = datetime( int(request_data.get("task_due_year", "2000")), int(request_data.get("task_due_month", "1")), @@ -63,7 +65,7 @@ def add_task_control( 0, # completed = 0 int(request_data.get("priority", "0")), int(request_data.get("recursive", "0")), - image_path, + "", # image_path = "" ), ) return task_id @@ -83,9 +85,10 @@ def edit_task_control( request_data["group_id"] ): raise BackendError("Backend Error: Group does not exist", "306") - if not Validator().check_password(user_id=assigner_id, password=password): + if not Validator().check_password( + user_id=request_data["assigner_id"], password=request_data["password"] + ): raise BackendError("Backend Error: Password is incorrect", "305") - image_path = "TODO CHANGE HERE" task_due: float = datetime( int(request_data.get("task_due_year", "2000")), int(request_data.get("task_due_month", "1")), @@ -112,7 +115,6 @@ def edit_task_control( request_data["group_id"], int(request_data.get("recursive", "0")), int(request_data.get("priority", "0")), - image_path, int(request_data.get("completed", "0")), request_data["task_id"], ), @@ -131,6 +133,22 @@ def delete_task_control( if not Validator().check_password(user_id=user_id, password=password): raise BackendError("Backend Error: Password is incorrect", "305") with db_operation() as data_cursor: + + data_cursor.execute( + "SELECT image_path FROM task WHERE uuid = ?;", + (task_id,), + ) + result = data_cursor.fetchone() + if result and result[0]: + image_path = result[0] + if exists(image_path): + try: + remove(image_path) + except Exception as err: + raise BackendError( + "Backend Error: Unable to delete image.", "203" + ) from err + data_cursor.execute("DELETE FROM task WHERE uuid = ?;", (task_id,)) def get_user_task_control(self, user_id: str, password: str) -> dict[str, dict]: @@ -147,11 +165,13 @@ def get_user_task_control(self, user_id: str, password: str) -> dict[str, dict]: # Get assigner username assigner_username = "Unknown" with db_operation() as username_cursor: - username_cursor.execute("SELECT username FROM user WHERE uuid = ?;", (task[7],)) + username_cursor.execute( + "SELECT username FROM user WHERE uuid = ?;", (task[7],) + ) username_result = username_cursor.fetchone() if username_result: assigner_username = username_result[0] - + # Get assignee username assignee_username = "Unknown" with db_operation() as username_cursor: @@ -159,7 +179,7 @@ def get_user_task_control(self, user_id: str, password: str) -> dict[str, dict]: username_result = username_cursor.fetchone() if username_result: assignee_username = username_result[0] - + new_task_list[task[0]] = { "name": task[1], "description": task[2], @@ -202,11 +222,13 @@ def get_group_task_control( # Get assigner username assigner_username = "Unknown" with db_operation() as username_cursor: - username_cursor.execute("SELECT username FROM user WHERE uuid = ?;", (task[7],)) + username_cursor.execute( + "SELECT username FROM user WHERE uuid = ?;", (task[7],) + ) username_result = username_cursor.fetchone() if username_result: assigner_username = username_result[0] - + # Get assignee username assignee_username = "Unknown" with db_operation() as username_cursor: @@ -214,7 +236,7 @@ def get_group_task_control( username_result = username_cursor.fetchone() if username_result: assignee_username = username_result[0] - + new_task_list[task[0]] = { "name": task[1], "description": task[2], @@ -265,11 +287,13 @@ def get_completed_task_control( # Get assigner username assigner_username = "Unknown" with db_operation() as username_cursor: - username_cursor.execute("SELECT username FROM user WHERE uuid = ?;", (task[7],)) + username_cursor.execute( + "SELECT username FROM user WHERE uuid = ?;", (task[7],) + ) username_result = username_cursor.fetchone() if username_result: assigner_username = username_result[0] - + new_task_list[task[0]] = { "name": task[1], "description": task[2], @@ -311,12 +335,6 @@ def toggle_complete_task_control( ), ) - def get_image_control(self, image_path: str) -> str: - """This will get the image.""" - if not exists(image_path): - raise BackendError("Backend Error: Image does not exist", "313") - return image_path - if __name__ == "__main__": print("This module is not intended to be run directly.") diff --git a/backend/controller_user.py b/backend/controller_user.py index f2a6f11..9e722b5 100644 --- a/backend/controller_user.py +++ b/backend/controller_user.py @@ -1,6 +1,9 @@ # coding: utf-8 """This module handles the functions related to user for database.""" +from os import remove +from os.path import exists + from typing import Any from uuid import uuid4 @@ -27,8 +30,8 @@ def add_user_control(self, username: str, email: str, password: str) -> str: raise BackendError("Backend Error: Email already exists", "302") with db_operation() as data_cursor: data_cursor.execute( - "INSERT INTO user VALUES (?, ?, ?, ?);", - (user_id, username, email, password), + "INSERT INTO user VALUES (?, ?, ?, ?, ?);", + (user_id, username, email, password, ""), ) return user_id @@ -46,10 +49,7 @@ def login_user_control( (email,), ) user_data = data_cursor.fetchone() - if user_data: - return {"user_id": user_data[0], "username": user_data[1]} - else: - raise BackendError("Backend Error: User not found after successful check", "500") + return {"user_id": user_data[0], "username": user_data[1]} def edit_user_control( self, @@ -68,7 +68,10 @@ def edit_user_control( raise BackendError("Backend Error: Password is incorrect", "305") with db_operation() as data_cursor: data_cursor.execute( - "UPDATE user SET username = ?, email = ?, password = ? WHERE uuid = ?;", + ( + "UPDATE user SET username = ?, email = ?, " + "password = ? WHERE uuid = ?;" + ), ( request_data["username"], request_data["email"], @@ -88,6 +91,21 @@ def delete_user_control( if not Validator().check_password(user_id=user_id, password=password): raise BackendError("Backend Error: Password is incorrect", "305") with db_operation() as data_cursor: + data_cursor.execute( + "SELECT image_path FROM user WHERE uuid = ?;", + (user_id,), + ) + result = data_cursor.fetchone() + if result and result[0]: + image_path = result[0] + if exists(image_path): + try: + remove(image_path) + except Exception as err: + raise BackendError( + "Backend Error: Unable to delete image.", "203" + ) from err + data_cursor.execute( "DELETE FROM user WHERE uuid = ?;", (user_id,), diff --git a/backend/handler_image.py b/backend/handler_image.py new file mode 100644 index 0000000..8d8ea47 --- /dev/null +++ b/backend/handler_image.py @@ -0,0 +1,187 @@ +# coding: utf-8 +"""Handles image processing and storage.""" + +from typing import Any + +from flask import Request +from error import BackendError, handle_backend_exceptions +from controller_image import ImageController +from utils import extract_request_data + + +class ImageHandle: + """This class will handle the image.""" + + def __init__(self, input_request: Request) -> None: + """Initialize the image handle.""" + self.user_request: Request = input_request + if self.user_request.method != "POST": + raise BackendError( + message="Wrong request type!", + error_code="100", + ) + + @handle_backend_exceptions + def get_user_image_request(self) -> str: + """Gets the user image.""" + request_data: dict[str, Any] = extract_request_data( + request=self.user_request, + required_fields=[ + "image_url", + "user_id", + "password", + ], + ) + return ImageController().get_user_image_control( + image_url=request_data["image_url"], + user_id=request_data["user_id"], + password=request_data["password"], + ) + + @handle_backend_exceptions + def get_task_image_request(self) -> str: + """Gets the task image.""" + request_data: dict[str, Any] = extract_request_data( + request=self.user_request, + required_fields=[ + "image_url", + "user_id", + "password", + "task_id", + "group_id", + ], + ) + return ImageController().get_task_image_control( + request_data=request_data, + ) + + @handle_backend_exceptions + def upload_user_image_request(self) -> str: + """Uploads the user image.""" + if "file" not in self.user_request.files: + raise BackendError( + message="No file part in the request", + error_code="314", + ) + file = self.user_request.files["file"] + request_data: dict[str, Any] = extract_request_data( + request=self.user_request, + required_fields=[ + "image_url", + "user_id", + "password", + ], + ) + return ImageController().upload_user_image_control( + user_id=request_data["user_id"], + password=request_data["password"], + file=file, + ) + + @handle_backend_exceptions + def upload_task_image_request(self) -> str: + """Uploads the task image.""" + if "file" not in self.user_request.files: + raise BackendError( + message="No file part in the request", + error_code="314", + ) + file = self.user_request.files["file"] + request_data: dict[str, Any] = extract_request_data( + request=self.user_request, + required_fields=[ + "image_url", + "user_id", + "password", + "task_id", + "group_id", + ], + ) + return ImageController().upload_task_image_control( + request_data=request_data, + file=file, + ) + + @handle_backend_exceptions + def edit_user_image_request(self) -> str: + """Edits the user image.""" + if "file" not in self.user_request.files: + raise BackendError( + message="No file part in the request", + error_code="314", + ) + file = self.user_request.files["file"] + request_data: dict[str, Any] = extract_request_data( + request=self.user_request, + required_fields=[ + "image_url", + "user_id", + "password", + ], + ) + return ImageController().edit_user_image_control( + user_id=request_data["user_id"], + password=request_data["password"], + file=file, + ) + + @handle_backend_exceptions + def edit_task_image_request(self) -> str: + """Edits the task image.""" + if "file" not in self.user_request.files: + raise BackendError( + message="No file part in the request", + error_code="314", + ) + file = self.user_request.files["file"] + request_data: dict[str, Any] = extract_request_data( + request=self.user_request, + required_fields=[ + "image_url", + "user_id", + "password", + "task_id", + "group_id", + ], + ) + return ImageController().edit_task_image_control( + request_data=request_data, + file=file, + ) + + @handle_backend_exceptions + def delete_user_image_request(self) -> None: + """Deletes the user image.""" + request_data: dict[str, Any] = extract_request_data( + request=self.user_request, + required_fields=[ + "image_url", + "user_id", + "password", + ], + ) + ImageController().delete_user_image_control( + user_id=request_data["user_id"], + password=request_data["password"], + ) + + @handle_backend_exceptions + def delete_task_image_request(self) -> None: + """Deletes the task image.""" + request_data: dict[str, Any] = extract_request_data( + request=self.user_request, + required_fields=[ + "image_url", + "user_id", + "password", + "task_id", + "group_id", + ], + ) + ImageController().delete_task_image_control( + request_data=request_data, + ) + + +if __name__ == "__main__": + print("This module is not meant to be run directly.") diff --git a/backend/handler_invite.py b/backend/handler_invite.py index 042f7de..9dafb36 100644 --- a/backend/handler_invite.py +++ b/backend/handler_invite.py @@ -60,20 +60,19 @@ def respond_invite_request(self) -> None: invite_id: str = request_data["invite_id"] password: str = request_data["password"] status: str = request_data["status"] - + # Get group_id from invite_id group_id = self._get_group_id_from_invite(invite_id, user_id) - + # Convert status to boolean accept accept = status.lower() == "accepted" - return InviteController().respond_invite_control( user_id=user_id, group_id=group_id, password=password, accept=accept, ) - + def _get_group_id_from_invite(self, invite_id: str, user_id: str) -> str: """Get group_id from invite_id.""" with db_operation() as data_cursor: diff --git a/backend/handler_task.py b/backend/handler_task.py index 8b15349..7e0eda3 100644 --- a/backend/handler_task.py +++ b/backend/handler_task.py @@ -97,21 +97,11 @@ def get_group_task_request(self) -> dict[str, dict[str, Any]]: group_id: str = request_data["group_id"] password: str = request_data["password"] return TaskController().get_group_task_control( - user_id=user_id, - group_id=group_id, + user_id=user_id, + group_id=group_id, password=password ) - @handle_backend_exceptions - def get_image_request(self) -> str: - """Gets the image.""" - request_data: dict[str, Any] = extract_request_data( - request=self.user_request, - required_fields=["image_path"], - ) - image_path: str = request_data["image_path"] - return TaskController().get_image_control(image_path=image_path) - if __name__ == "__main__": print("This is a module and should not be run directly.") diff --git a/backend/handler_user.py b/backend/handler_user.py index 7d12331..3a11160 100644 --- a/backend/handler_user.py +++ b/backend/handler_user.py @@ -52,7 +52,9 @@ def login_user_request(self) -> dict[str, str]: ) email: str = request_data["email"] password: str = request_data["password"] - user_info: dict[str, str] = UserController().login_user_control(email=email, password=password) + user_info: dict[str, str] = UserController().login_user_control( + email=email, password=password + ) return user_info @handle_backend_exceptions diff --git a/backend/main.py b/backend/main.py index 604d0de..6aa8384 100644 --- a/backend/main.py +++ b/backend/main.py @@ -1,7 +1,6 @@ # coding: utf-8 """This file will create the server and accept the backend processes.""" -# from os.path import join from typing import Any from flask import Flask, request, jsonify, Response, send_file @@ -15,6 +14,7 @@ from handler_task import TaskHandle from handler_group import GroupHandle from handler_invite import InviteHandle +from handler_image import ImageHandle app: Flask = Flask(__name__) @@ -58,13 +58,15 @@ def handle_signup() -> Response: def handle_login() -> Response: """Login a user.""" user_info: dict[str, str] = UserHandle(request).login_user_request() - # Extract user_id and username - user_id: str = user_info["user_id"] - username: str = user_info["username"] return jsonify( - # Include both user_id and username in the response - # (Front end expects this and needs it to store user info) - [{"error_no": "0", "message": "success", "user_id": user_id, "username": username}] + [ + { + "error_no": "0", + "message": "success", + "user_id": user_info["user_id"], + "username": user_info["username"], + } + ] ) @@ -220,6 +222,75 @@ def handle_sent_invite() -> Response: return jsonify([{"error_no": "0", "message": "success", "invites": invites}]) +# ----- File Upload Download ---- + + +@app.route("/get_user_image", methods=["POST"]) +@error_handling_decorator("get_user_image") +def handle_get_user_image() -> Response: + """Get an image.""" + return send_file( + ImageHandle(request).get_user_image_request(), mimetype="image/jpeg" + ) + + +@app.route("/get_task_image", methods=["POST"]) +@error_handling_decorator("get_task_image") +def handle_get_task_image() -> Response: + """Get an image.""" + return send_file( + ImageHandle(request).get_task_image_request(), mimetype="image/jpeg" + ) + + +@app.route("/upload_user_image", methods=["POST"]) +@error_handling_decorator("upload_user_image") +def handle_upload_user_image() -> Response: + """Upload an image.""" + image_url: str = ImageHandle(request).upload_user_image_request() + return jsonify([{"error_no": "0", "message": "success", "image_url": image_url}]) + + +@app.route("/upload_task_image", methods=["POST"]) +@error_handling_decorator("upload_task_image") +def handle_upload_task_image() -> Response: + """Upload an image.""" + image_url: str = ImageHandle(request).upload_task_image_request() + return jsonify([{"error_no": "0", "message": "success", "image_url": image_url}]) + + +@app.route("/edit_user_image", methods=["POST"]) +@error_handling_decorator("edit_user_image") +def handle_edit_user_image() -> Response: + """Edit an image.""" + image_url: str = ImageHandle(request).edit_user_image_request() + return jsonify([{"error_no": "0", "message": "success", "image_url": image_url}]) + + +@app.route("/edit_task_image", methods=["POST"]) +@error_handling_decorator("edit_task_image") +def handle_edit_task_image() -> Response: + """Edit an image.""" + image_url: str = ImageHandle(request).edit_task_image_request() + return jsonify([{"error_no": "0", "message": "success", "image_url": image_url}]) + + +@app.route("/delete_user_image", methods=["POST"]) +@error_handling_decorator("delete_user_image") +def handle_delete_user_image() -> Response: + """Delete an image.""" + ImageHandle(request).delete_user_image_request() + return jsonify([{"error_no": "0", "message": "success"}]) + + +@app.route("/delete_task_image", methods=["POST"]) +@error_handling_decorator("delete_task_image") +def handle_delete_task_image() -> Response: + """Delete an image.""" + ImageHandle(request).delete_task_image_request() + return jsonify([{"error_no": "0", "message": "success"}]) + + if __name__ == "__main__": print("Running main.py") make_new_log("main", "Server started") # type: ignore diff --git a/backend/validator.py b/backend/validator.py index 76c3800..d80886c 100644 --- a/backend/validator.py +++ b/backend/validator.py @@ -1,8 +1,9 @@ # coding: utf-8 """This function checks if the given data is valid.""" -from utils import db_operation +from os import makedirs +from utils import db_operation from error import BackendError CREATE_TASK_TABLE: str = ( @@ -18,7 +19,8 @@ CREATE_USER_TABLE: str = ( "CREATE TABLE IF NOT EXISTS user" "(uuid TEXT PRIMARY KEY, username TEXT NOT NULL, " - "email TEXT NOT NULL, password TEXT NOT NULL);" + "email TEXT NOT NULL, password TEXT NOT NULL, " + "image_path TEXT);" ) CREATE_GROUP_TABLE: str = ( "CREATE TABLE IF NOT EXISTS task_group" @@ -36,6 +38,8 @@ "inviter_id TEXT NOT NULL, invitee_id TEXT NOT NULL, " "day_created REAL NOT NULL);" ) +UPLOAD_FOLDER: str = "data/images" +ALLOWED_EXTENSIONS: set[str] = {"png", "jpg", "jpeg"} class Validator: @@ -48,6 +52,8 @@ def __init__(self) -> None: def initializer(self) -> None: """This function initializes to create the database.""" + makedirs(UPLOAD_FOLDER, exist_ok=True) + with db_operation() as data_cursor: data_cursor.execute(CREATE_TASK_TABLE) data_cursor.execute(CREATE_USER_TABLE) @@ -57,7 +63,7 @@ def initializer(self) -> None: if ( len(data_cursor.execute("SELECT * FROM task;").description) != 14 - or len(data_cursor.execute("SELECT * FROM user;").description) != 4 + or len(data_cursor.execute("SELECT * FROM user;").description) != 5 or len(data_cursor.execute("SELECT * FROM task_group;").description) != 4 or len(data_cursor.execute("SELECT * FROM group_user;").description) diff --git a/documentation/backend_error_code.txt b/documentation/backend_error_code.txt index 48904be..5df6e80 100644 --- a/documentation/backend_error_code.txt +++ b/documentation/backend_error_code.txt @@ -31,6 +31,8 @@ Backend error codes The backend has not been configured correctly. Please check the backend configuration. 202: "Database connection is not established" This happens because the function failed to conenct with the database. +203: Failed to delete file + The file was not deleted. Please check the file id and try again. ---------------- sqlite3 error codes @@ -59,12 +61,10 @@ sqlite3 error codes 310: "User is not in the group" The user is not in the group. Please check the group id and try again. 311: "Invitee already has an invite" -<<<<<<< Updated upstream - The invitee already has an invite. Please check the group id and try again. -======= The invitee already has an invite. Please check the group id and try again. 312: "invalid file type" The file type is not supported. Please check the file type and try again. 313: "File not found" The file was not found. Please check the file id and try again. ->>>>>>> Stashed changes +314: "File not attached" + The file was not attached. Please check the file id and try again.