Missing title field in database events column
#4
@@ -3,6 +3,7 @@ import psycopg2
|
|||||||
import pandas as pd
|
import pandas as pd
|
||||||
from psycopg2.extras import RealDictCursor
|
from psycopg2.extras import RealDictCursor
|
||||||
from psycopg2.extras import execute_batch, Json
|
from psycopg2.extras import execute_batch, Json
|
||||||
|
from server.exceptions import NotExistentDatasetException
|
||||||
|
|
||||||
|
|
||||||
class PostgresConnector:
|
class PostgresConnector:
|
||||||
@@ -67,6 +68,7 @@ class PostgresConnector:
|
|||||||
type,
|
type,
|
||||||
parent_id,
|
parent_id,
|
||||||
author,
|
author,
|
||||||
|
title,
|
||||||
content,
|
content,
|
||||||
timestamp,
|
timestamp,
|
||||||
date,
|
date,
|
||||||
@@ -88,7 +90,8 @@ class PostgresConnector:
|
|||||||
%s, %s, %s, %s, %s,
|
%s, %s, %s, %s, %s,
|
||||||
%s, %s, %s, %s, %s,
|
%s, %s, %s, %s, %s,
|
||||||
%s, %s, %s, %s, %s,
|
%s, %s, %s, %s, %s,
|
||||||
%s, %s, %s, %s, %s
|
%s, %s, %s, %s, %s,
|
||||||
|
%s
|
||||||
)
|
)
|
||||||
"""
|
"""
|
||||||
|
|
||||||
@@ -100,6 +103,7 @@ class PostgresConnector:
|
|||||||
row["type"],
|
row["type"],
|
||||||
row["parent_id"],
|
row["parent_id"],
|
||||||
row["author"],
|
row["author"],
|
||||||
|
row.get("title"),
|
||||||
row["content"],
|
row["content"],
|
||||||
row["timestamp"],
|
row["timestamp"],
|
||||||
row["date"],
|
row["date"],
|
||||||
@@ -126,12 +130,19 @@ class PostgresConnector:
|
|||||||
def get_dataset_content(self, dataset_id: int) -> pd.DataFrame:
|
def get_dataset_content(self, dataset_id: int) -> pd.DataFrame:
|
||||||
query = "SELECT * FROM events WHERE dataset_id = %s"
|
query = "SELECT * FROM events WHERE dataset_id = %s"
|
||||||
result = self.execute(query, (dataset_id,), fetch=True)
|
result = self.execute(query, (dataset_id,), fetch=True)
|
||||||
return pd.DataFrame(result)
|
|
||||||
|
if result:
|
||||||
|
return pd.DataFrame(result)
|
||||||
|
|
||||||
|
raise NotExistentDatasetException("Dataset does not exist")
|
||||||
|
|
||||||
def get_dataset_info(self, dataset_id: int) -> dict:
|
def get_dataset_info(self, dataset_id: int) -> dict:
|
||||||
query = "SELECT * FROM datasets WHERE id = %s"
|
query = "SELECT * FROM datasets WHERE id = %s"
|
||||||
result = self.execute(query, (dataset_id,), fetch=True)
|
result = self.execute(query, (dataset_id,), fetch=True)
|
||||||
return result[0] if result else None
|
if result:
|
||||||
|
return result[0]
|
||||||
|
|
||||||
|
raise NotExistentDatasetException("Dataset does not exist")
|
||||||
|
|
||||||
def close(self):
|
def close(self):
|
||||||
if self.connection:
|
if self.connection:
|
||||||
|
|||||||
@@ -30,7 +30,10 @@ CREATE TABLE events (
|
|||||||
hour INTEGER NOT NULL,
|
hour INTEGER NOT NULL,
|
||||||
weekday VARCHAR(255) NOT NULL,
|
weekday VARCHAR(255) NOT NULL,
|
||||||
|
|
||||||
/* Comments and Replies */
|
/* Posts Only */
|
||||||
|
title VARCHAR(255),
|
||||||
|
|
||||||
|
/* Comments Only*/
|
||||||
parent_id VARCHAR(255),
|
parent_id VARCHAR(255),
|
||||||
reply_to VARCHAR(255),
|
reply_to VARCHAR(255),
|
||||||
source VARCHAR(255) NOT NULL,
|
source VARCHAR(255) NOT NULL,
|
||||||
|
|||||||
100
server/app.py
100
server/app.py
@@ -1,5 +1,4 @@
|
|||||||
import os
|
import os
|
||||||
import datetime
|
|
||||||
|
|
||||||
from dotenv import load_dotenv
|
from dotenv import load_dotenv
|
||||||
from flask import Flask, jsonify, request
|
from flask import Flask, jsonify, request
|
||||||
@@ -14,9 +13,10 @@ from flask_jwt_extended import (
|
|||||||
|
|
||||||
from server.stat_gen import StatGen
|
from server.stat_gen import StatGen
|
||||||
from server.dataset_processor import DatasetProcessor
|
from server.dataset_processor import DatasetProcessor
|
||||||
|
from server.exceptions import NotAuthorisedException, NotExistentDatasetException
|
||||||
from db.database import PostgresConnector
|
from db.database import PostgresConnector
|
||||||
from server.auth import AuthManager
|
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 pandas as pd
|
||||||
import traceback
|
import traceback
|
||||||
@@ -44,6 +44,7 @@ auth_manager = AuthManager(db, bcrypt)
|
|||||||
|
|
||||||
stat_gen = StatGen()
|
stat_gen = StatGen()
|
||||||
|
|
||||||
|
|
||||||
@app.route("/register", methods=["POST"])
|
@app.route("/register", methods=["POST"])
|
||||||
def register_user():
|
def register_user():
|
||||||
data = request.get_json()
|
data = request.get_json()
|
||||||
@@ -152,34 +153,29 @@ def upload_data():
|
|||||||
@app.route("/dataset/<int:dataset_id>", methods=["GET"])
|
@app.route("/dataset/<int:dataset_id>", methods=["GET"])
|
||||||
@jwt_required()
|
@jwt_required()
|
||||||
def get_dataset(dataset_id):
|
def get_dataset(dataset_id):
|
||||||
current_user = get_jwt_identity()
|
try:
|
||||||
dataset = db.get_dataset_info(dataset_id)
|
dataset_content = get_dataset_and_validate(dataset_id, db)
|
||||||
|
filters = get_request_filters()
|
||||||
if dataset.get("user_id") != int(current_user):
|
filtered_dataset = stat_gen.filter_dataset(dataset_content, filters)
|
||||||
return jsonify({"error": "Unauthorized access to dataset"}), 403
|
return jsonify(filtered_dataset), 200
|
||||||
|
except NotAuthorisedException:
|
||||||
dataset_content = db.get_dataset_content(dataset_id)
|
return jsonify({"error": "User is not authorised to access this content"}), 403
|
||||||
|
except NotExistentDatasetException:
|
||||||
if dataset_content.empty:
|
return jsonify({"error": "Dataset does not exist"}), 404
|
||||||
return jsonify({"error": "Dataset content not found"}), 404
|
except Exception:
|
||||||
|
print(traceback.format_exc())
|
||||||
filters = get_request_filters()
|
return jsonify({"error": "An unexpected error occured"}), 500
|
||||||
return jsonify(stat_gen.filter_dataset(dataset_content, filters)), 200
|
|
||||||
|
|
||||||
|
|
||||||
@app.route("/dataset/<int:dataset_id>/content", methods=["GET"])
|
@app.route("/dataset/<int:dataset_id>/content", methods=["GET"])
|
||||||
@jwt_required()
|
@jwt_required()
|
||||||
def content_endpoint(dataset_id):
|
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:
|
try:
|
||||||
|
dataset_content = get_dataset_and_validate(dataset_id, db)
|
||||||
filters = get_request_filters()
|
filters = get_request_filters()
|
||||||
return jsonify(stat_gen.get_content_analysis(dataset_content, filters)), 200
|
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:
|
except ValueError as e:
|
||||||
return jsonify({"error": f"Malformed or missing data: {str(e)}"}), 400
|
return jsonify({"error": f"Malformed or missing data: {str(e)}"}), 400
|
||||||
except Exception as e:
|
except Exception as e:
|
||||||
@@ -190,17 +186,12 @@ def content_endpoint(dataset_id):
|
|||||||
@app.route("/dataset/<int:dataset_id>/summary", methods=["GET"])
|
@app.route("/dataset/<int:dataset_id>/summary", methods=["GET"])
|
||||||
@jwt_required()
|
@jwt_required()
|
||||||
def get_summary(dataset_id):
|
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:
|
try:
|
||||||
|
dataset_content = get_dataset_and_validate(dataset_id, db)
|
||||||
filters = get_request_filters()
|
filters = get_request_filters()
|
||||||
return jsonify(stat_gen.summary(dataset_content, filters)), 200
|
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:
|
except ValueError as e:
|
||||||
return jsonify({"error": f"Malformed or missing data: {str(e)}"}), 400
|
return jsonify({"error": f"Malformed or missing data: {str(e)}"}), 400
|
||||||
except Exception as e:
|
except Exception as e:
|
||||||
@@ -211,17 +202,12 @@ def get_summary(dataset_id):
|
|||||||
@app.route("/dataset/<int:dataset_id>/time", methods=["GET"])
|
@app.route("/dataset/<int:dataset_id>/time", methods=["GET"])
|
||||||
@jwt_required()
|
@jwt_required()
|
||||||
def get_time_analysis(dataset_id):
|
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:
|
try:
|
||||||
|
dataset_content = get_dataset_and_validate(dataset_id, db)
|
||||||
filters = get_request_filters()
|
filters = get_request_filters()
|
||||||
return jsonify(stat_gen.get_time_analysis(dataset_content, filters)), 200
|
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:
|
except ValueError as e:
|
||||||
return jsonify({"error": f"Malformed or missing data: {str(e)}"}), 400
|
return jsonify({"error": f"Malformed or missing data: {str(e)}"}), 400
|
||||||
except Exception as e:
|
except Exception as e:
|
||||||
@@ -232,17 +218,12 @@ def get_time_analysis(dataset_id):
|
|||||||
@app.route("/dataset/<int:dataset_id>/user", methods=["GET"])
|
@app.route("/dataset/<int:dataset_id>/user", methods=["GET"])
|
||||||
@jwt_required()
|
@jwt_required()
|
||||||
def get_user_analysis(dataset_id):
|
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:
|
try:
|
||||||
|
dataset_content = get_dataset_and_validate(dataset_id, db)
|
||||||
filters = get_request_filters()
|
filters = get_request_filters()
|
||||||
return jsonify(stat_gen.get_user_analysis(dataset_content, filters)), 200
|
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:
|
except ValueError as e:
|
||||||
return jsonify({"error": f"Malformed or missing data: {str(e)}"}), 400
|
return jsonify({"error": f"Malformed or missing data: {str(e)}"}), 400
|
||||||
except Exception as e:
|
except Exception as e:
|
||||||
@@ -253,17 +234,12 @@ def get_user_analysis(dataset_id):
|
|||||||
@app.route("/dataset/<int:dataset_id>/cultural", methods=["GET"])
|
@app.route("/dataset/<int:dataset_id>/cultural", methods=["GET"])
|
||||||
@jwt_required()
|
@jwt_required()
|
||||||
def get_cultural_analysis(dataset_id):
|
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:
|
try:
|
||||||
|
dataset_content = get_dataset_and_validate(dataset_id, db)
|
||||||
filters = get_request_filters()
|
filters = get_request_filters()
|
||||||
return jsonify(stat_gen.get_cultural_analysis(dataset_content, filters)), 200
|
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:
|
except ValueError as e:
|
||||||
return jsonify({"error": f"Malformed or missing data: {str(e)}"}), 400
|
return jsonify({"error": f"Malformed or missing data: {str(e)}"}), 400
|
||||||
except Exception as e:
|
except Exception as e:
|
||||||
@@ -274,24 +250,18 @@ def get_cultural_analysis(dataset_id):
|
|||||||
@app.route("/dataset/<int:dataset_id>/interaction", methods=["GET"])
|
@app.route("/dataset/<int:dataset_id>/interaction", methods=["GET"])
|
||||||
@jwt_required()
|
@jwt_required()
|
||||||
def get_interaction_analysis(dataset_id):
|
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:
|
try:
|
||||||
|
dataset_content = get_dataset_and_validate(dataset_id, db)
|
||||||
filters = get_request_filters()
|
filters = get_request_filters()
|
||||||
return jsonify(
|
return jsonify(stat_gen.get_interactional_analysis(dataset_content, filters)), 200
|
||||||
stat_gen.get_interactional_analysis(dataset_content, filters)
|
except NotAuthorisedException:
|
||||||
), 200
|
return jsonify({"error": "User is not authorised to access this content"}), 403
|
||||||
except ValueError as e:
|
except ValueError as e:
|
||||||
return jsonify({"error": f"Malformed or missing data: {str(e)}"}), 400
|
return jsonify({"error": f"Malformed or missing data: {str(e)}"}), 400
|
||||||
except Exception as e:
|
except Exception as e:
|
||||||
print(traceback.format_exc())
|
print(traceback.format_exc())
|
||||||
return jsonify({"error": f"An unexpected error occurred: {str(e)}"}), 500
|
return jsonify({"error": f"An unexpected error occurred: {str(e)}"}), 500
|
||||||
|
|
||||||
|
|
||||||
if __name__ == "__main__":
|
if __name__ == "__main__":
|
||||||
app.run(debug=True)
|
app.run(debug=True)
|
||||||
|
|||||||
5
server/exceptions.py
Normal file
5
server/exceptions.py
Normal file
@@ -0,0 +1,5 @@
|
|||||||
|
class NotAuthorisedException(Exception):
|
||||||
|
pass
|
||||||
|
|
||||||
|
class NotExistentDatasetException(Exception):
|
||||||
|
pass
|
||||||
@@ -1,5 +1,10 @@
|
|||||||
import datetime
|
import datetime
|
||||||
|
import pandas as pd
|
||||||
|
|
||||||
from flask import request
|
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):
|
def parse_datetime_filter(value):
|
||||||
if not value:
|
if not value:
|
||||||
@@ -47,4 +52,13 @@ def get_request_filters() -> dict:
|
|||||||
if data_sources:
|
if data_sources:
|
||||||
filters["data_sources"] = data_sources
|
filters["data_sources"] = data_sources
|
||||||
|
|
||||||
return filters
|
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)
|
||||||
|
|||||||
Reference in New Issue
Block a user