Spaces:
Sleeping
Sleeping
| from ..models.requestModels import UpdateProjectState, CreateProject, EditMetadata | |
| from fastapi.security import HTTPAuthorizationCredentials, HTTPBearer | |
| from fastapi.exceptions import HTTPException | |
| from fastapi.responses import JSONResponse | |
| from ..utils.functions import verifyToken | |
| from fastapi import APIRouter, Depends | |
| from supabase import create_client | |
| from urllib.request import urlopen | |
| from typing import Annotated | |
| from . import pipeline | |
| from jose import jwt | |
| import pandas as pd | |
| import uuid | |
| import json | |
| import time | |
| import os | |
| import io | |
| router = APIRouter() | |
| security = HTTPBearer() | |
| client = create_client( | |
| supabase_url = os.environ["SUPABASE_URL"], | |
| supabase_key = os.environ["SUPABASE_KEY"] | |
| ) | |
| async def createProject(projectDetails: CreateProject, credentials: Annotated[HTTPAuthorizationCredentials, Depends(security)]): | |
| try: | |
| if verifyToken(token = credentials.credentials): | |
| projectId = str(uuid.uuid4()) | |
| decodedToken = jwt.decode( | |
| credentials.credentials, | |
| os.environ["SECRET_KEY"], | |
| algorithms = ["HS256"] | |
| ) | |
| _ = client.table("Projects").insert({ | |
| "projectId": projectId, | |
| "projectName": projectDetails.projectName, | |
| "projectDescription": projectDetails.projectDescription, | |
| "ownerUserId": decodedToken["userId"], | |
| "ownerUserMail": decodedToken["email"] | |
| }).execute() | |
| return JSONResponse(status_code = 200, content = {"status": "SUCCESS", "projectId": projectId, "message": "Project created successfully"}) | |
| else: | |
| return JSONResponse(status_code = 498, content = {"status": "ERROR", "errorDetail": "Invalid Token"}) | |
| except Exception as e: | |
| raise HTTPException(status_code = 500, detail = f"Endpoint says: {e}") | |
| async def listProjects(credentials: Annotated[HTTPAuthorizationCredentials, Depends(security)]): | |
| try: | |
| if verifyToken(token = credentials.credentials): | |
| decodedToken = jwt.decode( | |
| credentials.credentials, | |
| os.environ["SECRET_KEY"], | |
| algorithms = ["HS256"] | |
| ) | |
| data = pd.DataFrame(client.table("Projects").select("*").execute().data) | |
| data = data[data["ownerUserId"] == decodedToken["userId"]] | |
| return JSONResponse(status_code = 200, content = {"projects": data.to_dict(orient = "records")}) | |
| else: | |
| return JSONResponse(status_code = 498, content = {"status": "ERROR", "errorDetail": "Invalid Token"}) | |
| except Exception as e: | |
| raise HTTPException(status_code = 500, detail = f"Endpoint says: {e}") | |
| async def updateBookmark(updateBookmarkDetails: UpdateProjectState, credentials: Annotated[HTTPAuthorizationCredentials, Depends(security)]): | |
| try: | |
| if verifyToken(token = credentials.credentials): | |
| if updateBookmarkDetails.action == "add": | |
| _ = client.table("Projects").update({"isBookmarked": 1}).eq("projectId", updateBookmarkDetails.projectId).execute() | |
| else: | |
| _ = client.table("Projects").update({"isBookmarked": 0}).eq("projectId", updateBookmarkDetails.projectId).execute() | |
| return JSONResponse(status_code = 200, content = {"status": "SUCCESS", "message": "Project bookmark status updated successfully"}) | |
| else: | |
| return JSONResponse(status_code = 498, content = {"status": "ERROR", "errorDetail": "Invalid Token"}) | |
| except Exception as e: | |
| raise HTTPException(status_code = 500, detail = f"Endpoint says: {e}") | |
| async def updateArchive(updateArchiveDetails: UpdateProjectState, credentials: Annotated[HTTPAuthorizationCredentials, Depends(security)]): | |
| try: | |
| if verifyToken(token = credentials.credentials): | |
| if updateArchiveDetails.action == "add": | |
| _ = client.table("Projects").update({"isArchived": 1}).eq("projectId", updateArchiveDetails.projectId).execute() | |
| else: | |
| _ = client.table("Projects").update({"isArchived": 0}).eq("projectId", updateArchiveDetails.projectId).execute() | |
| return JSONResponse(status_code = 200, content = {"status": "SUCCESS", "message": "Project archive status updated successfully"}) | |
| else: | |
| return JSONResponse(status_code = 498, content = {"status": "ERROR", "errorDetail": "Invalid Token"}) | |
| except Exception as e: | |
| raise HTTPException(status_code = 500, detail = f"Endpoint says: {e}") | |
| async def updateTrash(updateTrashDetails: UpdateProjectState, credentials: Annotated[HTTPAuthorizationCredentials, Depends(security)]): | |
| try: | |
| if verifyToken(token = credentials.credentials): | |
| if updateTrashDetails.action == "add": | |
| _ = client.table("Projects").update({"isTrash": 1}).eq("projectId", updateTrashDetails.projectId).execute() | |
| else: | |
| _ = client.table("Projects").update({"isTrash": 0}).eq("projectId", updateTrashDetails.projectId).execute() | |
| return JSONResponse(status_code = 200, content = {"status": "SUCCESS", "message": "Project trash status updated successfully"}) | |
| else: | |
| return JSONResponse(status_code = 498, content = {"status": "ERROR", "errorDetail": "Invalid Token"}) | |
| except Exception as e: | |
| raise HTTPException(status_code = 500, detail = f"Endpoint says: {e}") | |
| async def generateMetadata(projectId: str, credentials: Annotated[HTTPAuthorizationCredentials, Depends(security)]): | |
| try: | |
| if verifyToken(token = credentials.credentials): | |
| filenames = [x.get("name") for x in client.storage.from_("AnalyticsHub").list(projectId)] | |
| if "metadata.json" in filenames: | |
| fileUrl = os.environ["FILE_URL"].format(projectId = projectId, fileName = "metadata.json").replace(".parquet", "") + f"?cb={int(time.time())}" | |
| jsonData = json.loads(urlopen(fileUrl).read()) | |
| jsonDataTables = set(jsonData.keys()) | |
| newMetadata = pipeline.generateMetadata(projectId = projectId) | |
| newMetadataTables = set(newMetadata.keys()) | |
| newKeys = newMetadataTables.difference(jsonDataTables) | |
| for key in newKeys: jsonData[key] = newMetadata[key] | |
| else: | |
| jsonData = pipeline.generateMetadata(projectId = projectId) | |
| with io.BytesIO() as buffer: | |
| buffer.write(json.dumps(jsonData, indent=4).encode("utf-8")) | |
| buffer.seek(0) | |
| client.storage.from_("AnalyticsHub").upload(path = f"{projectId}/metadata.json", file = buffer.getvalue(), file_options = {"upsert": "true"}) | |
| return JSONResponse(status_code = 200, content = {"status": "SUCCESS", "metadata": jsonData}) | |
| else: | |
| return JSONResponse(status_code = 498, content = {"status": "ERROR", "errorDetail": "Invalid Token"}) | |
| except Exception as e: | |
| raise HTTPException(status_code = 500, detail = f"Endpoint says: {e}") | |
| async def getMetadata(projectId: str, credentials: Annotated[HTTPAuthorizationCredentials, Depends(security)]): | |
| try: | |
| if verifyToken(token = credentials.credentials): | |
| fileUrl = os.environ["FILE_URL"].format(projectId = projectId, fileName = "metadata.json").replace(".parquet", "") + f"?cb={int(time.time())}" | |
| jsonData = json.loads(urlopen(fileUrl).read()) | |
| newJson = {"tables": []} | |
| for key in jsonData: | |
| tableJson = { | |
| "tableName": key, | |
| "tableDesc": jsonData.get(key).get("description"), | |
| "shape": jsonData.get(key).get("shape"), | |
| "columns": jsonData.get(key).get("columns") | |
| } | |
| newJson.get("tables").append(tableJson) | |
| return JSONResponse(status_code = 200, content = newJson) | |
| else: | |
| return JSONResponse(status_code = 498, content = {"status": "ERROR", "errorDetail": "Invalid Token"}) | |
| except Exception as e: | |
| raise HTTPException(status_code = 500, detail = f"Endpoint says: {e}") | |
| async def editMetadata(modifiedMetadata: EditMetadata, credentials: Annotated[HTTPAuthorizationCredentials, Depends(security)]): | |
| try: | |
| if verifyToken(token = credentials.credentials): | |
| fileUrl = os.environ["FILE_URL"].format(projectId = modifiedMetadata.projectId, fileName = "metadata.json").replace(".parquet", "") + f"?cb={int(time.time())}" | |
| jsonData = json.loads(urlopen(fileUrl).read()) | |
| if modifiedMetadata.tableDescription and not (modifiedMetadata.columnName or modifiedMetadata.columnDescription): | |
| jsonData[modifiedMetadata.tableName]["description"] = modifiedMetadata.tableDescription | |
| elif (modifiedMetadata.columnName and modifiedMetadata.columnDescription) and not modifiedMetadata.tableDescription: | |
| columns = jsonData[modifiedMetadata.tableName]["columns"] | |
| for column in columns: | |
| if column["name"] == modifiedMetadata.columnName: | |
| idx = columns.index(column) | |
| columns[idx]["description"] = modifiedMetadata.columnDescription | |
| jsonData[modifiedMetadata.tableName]["columns"] = columns | |
| else: | |
| raise AttributeError("Invalid combination of parameters provided") | |
| with io.BytesIO() as buffer: | |
| buffer.write(json.dumps(jsonData, indent=4).encode("utf-8")) | |
| buffer.seek(0) | |
| client.storage.from_("AnalyticsHub").upload(path = f"{modifiedMetadata.projectId}/metadata.json", file = buffer.getvalue(), file_options = {"upsert": "true"}) | |
| return JSONResponse(status_code = 200, content = {"status": "SUCCESS", "metadata": jsonData}) | |
| else: | |
| return JSONResponse(status_code = 498, content = {"status": "ERROR", "errorDetail": "Invalid Token"}) | |
| except Exception as e: | |
| raise HTTPException(status_code = 500, detail = f"Endpoint says: {e}") | |
| async def deleteProject(projectId: str, credentials: Annotated[HTTPAuthorizationCredentials, Depends(security)]): | |
| try: | |
| if verifyToken(token = credentials.credentials): | |
| _ = client.table("Projects").delete().eq("projectId", projectId).execute() | |
| allFiles = client.storage.from_("AnalyticsHub").list(projectId) | |
| fileNames = [os.path.join(projectId, x.get("name")) for x in allFiles] | |
| _ = client.storage.from_("AnalyticsHub").remove(fileNames) | |
| return JSONResponse(status_code = 200, content = {"status": "SUCCESS", "message": "Project deleted successfully"}) | |
| else: | |
| return JSONResponse(status_code = 498, content = {"status": "ERROR", "errorDetail": "Invalid Token"}) | |
| except Exception as e: | |
| raise HTTPException(status_code = 500, detail = f"Endpoint says: {e}") |