From 18c85396466ece3b1a9e413048dc337e170bdd46 Mon Sep 17 00:00:00 2001 From: Dylan De Faoite Date: Mon, 2 Mar 2026 18:55:27 +0000 Subject: [PATCH] fix: server error when attmepting to access non-existant dataset --- db/database.py | 11 +++++- server/app.py | 97 ++++++++++++++++--------------------------------- server/utils.py | 16 +++++++- 3 files changed, 56 insertions(+), 68 deletions(-) diff --git a/db/database.py b/db/database.py index 1adae72..34c22ca 100644 --- a/db/database.py +++ b/db/database.py @@ -129,12 +129,19 @@ class PostgresConnector: def get_dataset_content(self, dataset_id: int) -> pd.DataFrame: query = "SELECT * FROM events WHERE dataset_id = %s" result = self.execute(query, (dataset_id,), fetch=True) - return pd.DataFrame(result) + + if result: + return pd.DataFrame(result) + + raise ValueError("Dataset does not exist") def get_dataset_info(self, dataset_id: int) -> dict: query = "SELECT * FROM datasets WHERE id = %s" result = self.execute(query, (dataset_id,), fetch=True) - return result[0] if result else None + if result: + return result[0] + + raise ValueError("Dataset does not exist") def close(self): if self.connection: diff --git a/server/app.py b/server/app.py index eef9d7a..7f10872 100644 --- a/server/app.py +++ b/server/app.py @@ -1,5 +1,4 @@ import os -import datetime from dotenv import load_dotenv from flask import Flask, jsonify, request @@ -14,9 +13,10 @@ from flask_jwt_extended import ( from server.stat_gen import StatGen from server.dataset_processor import DatasetProcessor +from server.exceptions import NotAuthorisedException from db.database import PostgresConnector from server.auth import AuthManager -from server.utils import get_request_filters, parse_datetime_filter +from server.utils import get_request_filters, get_dataset_and_validate import pandas as pd import traceback @@ -44,6 +44,7 @@ auth_manager = AuthManager(db, bcrypt) stat_gen = StatGen() + @app.route("/register", methods=["POST"]) def register_user(): data = request.get_json() @@ -152,34 +153,26 @@ def upload_data(): @app.route("/dataset/", methods=["GET"]) @jwt_required() def get_dataset(dataset_id): - current_user = get_jwt_identity() - dataset = db.get_dataset_info(dataset_id) - - if dataset.get("user_id") != int(current_user): - return jsonify({"error": "Unauthorized access to dataset"}), 403 - - dataset_content = db.get_dataset_content(dataset_id) - - if dataset_content.empty: - return jsonify({"error": "Dataset content not found"}), 404 - - filters = get_request_filters() - return jsonify(stat_gen.filter_dataset(dataset_content, filters)), 200 + try: + dataset_content = get_dataset_and_validate(dataset_id, db) + filters = get_request_filters() + filtered_dataset = stat_gen.filter_dataset(dataset_content, filters) + return jsonify(filtered_dataset), 200 + except NotAuthorisedException: + return jsonify({"error": "User is not authorised to access this content"}), 403 + except Exception: + return jsonify({"error": "An unexpected error occured"}), 500 @app.route("/dataset//content", methods=["GET"]) @jwt_required() def content_endpoint(dataset_id): - current_user = get_jwt_identity() - dataset = db.get_dataset_info(dataset_id) - - if dataset.get("user_id") != int(current_user): - return jsonify({"error": "Unauthorized access to dataset"}), 403 - - dataset_content = db.get_dataset_content(dataset_id) try: + dataset_content = get_dataset_and_validate(dataset_id, db) filters = get_request_filters() return jsonify(stat_gen.get_content_analysis(dataset_content, filters)), 200 + except NotAuthorisedException: + return jsonify({"error": "User is not authorised to access this content"}), 403 except ValueError as e: return jsonify({"error": f"Malformed or missing data: {str(e)}"}), 400 except Exception as e: @@ -190,17 +183,12 @@ def content_endpoint(dataset_id): @app.route("/dataset//summary", methods=["GET"]) @jwt_required() def get_summary(dataset_id): - current_user = get_jwt_identity() - dataset = db.get_dataset_info(dataset_id) - - if dataset.get("user_id") != int(current_user): - return jsonify({"error": "Unauthorized access to dataset"}), 403 - - dataset_content = db.get_dataset_content(dataset_id) - try: + dataset_content = get_dataset_and_validate(dataset_id, db) filters = get_request_filters() return jsonify(stat_gen.summary(dataset_content, filters)), 200 + except NotAuthorisedException: + return jsonify({"error": "User is not authorised to access this content"}), 403 except ValueError as e: return jsonify({"error": f"Malformed or missing data: {str(e)}"}), 400 except Exception as e: @@ -211,17 +199,12 @@ def get_summary(dataset_id): @app.route("/dataset//time", methods=["GET"]) @jwt_required() def get_time_analysis(dataset_id): - current_user = get_jwt_identity() - dataset = db.get_dataset_info(dataset_id) - - if dataset.get("user_id") != int(current_user): - return jsonify({"error": "Unauthorized access to dataset"}), 403 - - dataset_content = db.get_dataset_content(dataset_id) - try: + dataset_content = get_dataset_and_validate(dataset_id, db) filters = get_request_filters() return jsonify(stat_gen.get_time_analysis(dataset_content, filters)), 200 + except NotAuthorisedException: + return jsonify({"error": "User is not authorised to access this content"}), 403 except ValueError as e: return jsonify({"error": f"Malformed or missing data: {str(e)}"}), 400 except Exception as e: @@ -232,17 +215,12 @@ def get_time_analysis(dataset_id): @app.route("/dataset//user", methods=["GET"]) @jwt_required() def get_user_analysis(dataset_id): - current_user = get_jwt_identity() - dataset = db.get_dataset_info(dataset_id) - - if dataset.get("user_id") != int(current_user): - return jsonify({"error": "Unauthorized access to dataset"}), 403 - - dataset_content = db.get_dataset_content(dataset_id) - try: + dataset_content = get_dataset_and_validate(dataset_id, db) filters = get_request_filters() return jsonify(stat_gen.get_user_analysis(dataset_content, filters)), 200 + except NotAuthorisedException: + return jsonify({"error": "User is not authorised to access this content"}), 403 except ValueError as e: return jsonify({"error": f"Malformed or missing data: {str(e)}"}), 400 except Exception as e: @@ -253,17 +231,12 @@ def get_user_analysis(dataset_id): @app.route("/dataset//cultural", methods=["GET"]) @jwt_required() def get_cultural_analysis(dataset_id): - current_user = get_jwt_identity() - dataset = db.get_dataset_info(dataset_id) - - if dataset.get("user_id") != int(current_user): - return jsonify({"error": "Unauthorized access to dataset"}), 403 - - dataset_content = db.get_dataset_content(dataset_id) - try: + dataset_content = get_dataset_and_validate(dataset_id, db) filters = get_request_filters() return jsonify(stat_gen.get_cultural_analysis(dataset_content, filters)), 200 + except NotAuthorisedException: + return jsonify({"error": "User is not authorised to access this content"}), 403 except ValueError as e: return jsonify({"error": f"Malformed or missing data: {str(e)}"}), 400 except Exception as e: @@ -274,24 +247,18 @@ def get_cultural_analysis(dataset_id): @app.route("/dataset//interaction", methods=["GET"]) @jwt_required() def get_interaction_analysis(dataset_id): - current_user = get_jwt_identity() - dataset = db.get_dataset_info(dataset_id) - - if dataset.get("user_id") != int(current_user): - return jsonify({"error": "Unauthorized access to dataset"}), 403 - - dataset_content = db.get_dataset_content(dataset_id) - try: + dataset_content = get_dataset_and_validate(dataset_id, db) filters = get_request_filters() - return jsonify( - stat_gen.get_interactional_analysis(dataset_content, filters) - ), 200 + return jsonify(stat_gen.get_interactional_analysis(dataset_content, filters)), 200 + except NotAuthorisedException: + return jsonify({"error": "User is not authorised to access this content"}), 403 except ValueError as e: return jsonify({"error": f"Malformed or missing data: {str(e)}"}), 400 except Exception as e: print(traceback.format_exc()) return jsonify({"error": f"An unexpected error occurred: {str(e)}"}), 500 + if __name__ == "__main__": app.run(debug=True) diff --git a/server/utils.py b/server/utils.py index 078d1e7..71e593b 100644 --- a/server/utils.py +++ b/server/utils.py @@ -1,5 +1,10 @@ import datetime +import pandas as pd + from flask import request +from flask_jwt_extended import get_jwt_identity +from db.database import PostgresConnector +from server.exceptions import NotAuthorisedException def parse_datetime_filter(value): if not value: @@ -47,4 +52,13 @@ def get_request_filters() -> dict: if data_sources: filters["data_sources"] = data_sources - return filters \ No newline at end of file + return filters + +def get_dataset_and_validate(dataset_id: int, db: PostgresConnector) -> pd.DataFrame: + current_user = get_jwt_identity() + dataset = db.get_dataset_info(dataset_id) + + if dataset.get("user_id") != int(current_user): + raise NotAuthorisedException("This user is not authorised to access this dataset") + + return db.get_dataset_content(dataset_id)