From 79374b16b1cc4d512495c0bf0968ddbba8a3039e Mon Sep 17 00:00:00 2001 From: rhodinemma Date: Mon, 27 Jan 2025 16:56:54 +0300 Subject: [PATCH 1/5] feat: add pagination to database list endpoint --- app/routes.py | 50 +++++++++++++++++++++++++++++++++++++++----------- 1 file changed, 39 insertions(+), 11 deletions(-) diff --git a/app/routes.py b/app/routes.py index 115b079..b30d231 100644 --- a/app/routes.py +++ b/app/routes.py @@ -46,28 +46,56 @@ def fetch_database_stats(access_token: str = Depends(security), db: Session = De @router.get("/databases") def get_all_databases( - access_token: str = Depends(security), - db: Session = Depends(get_db), - project_id: str = Query(None, description="Project ID"), - database_flavour_name: str = Query(None, description="Database flavour name") - ): + access_token: str = Depends(security), + db: Session = Depends(get_db), + project_id: str = Query(None, description="Project ID"), + database_flavour_name: str = Query( + None, description="Database flavour name"), + page: int = Query(default=1, ge=1, description="Page number"), + per_page: int = Query(default=10, ge=1, le=100, + description="Items per page") +): current_user = get_current_user(access_token.credentials) check_authentication(current_user) - databases = db.query(Database) + query = db.query(Database) if current_user.role != "administrator": - databases = databases.filter( + query = query.filter( Database.owner_id == current_user.id) - + if project_id: - databases = databases.filter(Database.project_id == project_id) + query = query.filter(Database.project_id == project_id) if database_flavour_name: - databases = databases.filter( + query = query.filter( Database.database_flavour_name == database_flavour_name) - return {"status_code": 200, "data": {"databases": databases.all()}} + total_count = query.count() + total_pages = (total_count + per_page - 1) + + offset = (page - 1) * per_page + paginated_query = query.offset(offset).limit(per_page) + + databases = paginated_query.all() + + next_num = page + 1 if page < total_pages else None + prev_num = page - 1 if page > 1 else None + + return { + "status_code": 200, + "data": { + "pagination": { + "total": total_count, + "pages": total_pages, + "page": page, + "per_page": per_page, + "next": next_num, + "prev": prev_num + }, + "databases": databases + } + } @router.post("/databases") From 3d5b3f96d3f217806f5555c04ef33d2b8e15f0dc Mon Sep 17 00:00:00 2001 From: CHRISTOPHERKADOGO Date: Mon, 27 Jan 2025 18:45:02 +0300 Subject: [PATCH 2/5] corrected the get database graph data --- app/routes.py | 128 ++++++++++++++++++++++++++------------------------ 1 file changed, 66 insertions(+), 62 deletions(-) diff --git a/app/routes.py b/app/routes.py index b30d231..8c2366e 100644 --- a/app/routes.py +++ b/app/routes.py @@ -181,69 +181,7 @@ def create_database(database: DatabaseFlavor, access_token: str = Depends(securi return SimpleNamespace(status_code=201, data={"database": database}) -@router.get("/databases/{database_id}") -def single_database(database_id: str, access_token: str = Depends(security), db: Session = Depends(get_db)): - current_user = get_current_user(access_token.credentials) - check_authentication(current_user) - - user_database = db.query(Database).filter( - Database.id == database_id).first() - if not user_database: - raise HTTPException(status_code=404, detail="Database not found") - - flavour_name = user_database.database_flavour_name - if not flavour_name: - flavour_name = "mysql" - - db_flavour = get_db_flavour(flavour_name) - - if not db_flavour: - return dict( - status_code=404, - message=f"""Database flavour with name - {user_database.database_flavour_name} is not mysql or postgres.""" - ) - - database_service = db_flavour['class'] - - # Get db status - try: - database_connection = database_service.create_db_connection( - user=user_database.user, password=user_database.password, db_name=user_database.name) - if not database_connection: - db_status = False - else: - db_status = True - except: - db_status = False - finally: - if database_connection: - if database_service == MysqlDbService(): - if database_connection.is_connected(): - database_connection.close() - else: - database_connection.close() - - database_dict = { - **user_database.__dict__, - "db_status": db_status, - "default_storage_kb": database_service.get_database_size( - user=user_database.user, password=user_database.password, db_name=user_database.name) - } - - return SimpleNamespace(status_code=200, data={"database": database_dict}) - - -@router.get("/databases/{database_id}/password") -def get_database_password(database_id: str, access_token: str = Depends(security), db: Session = Depends(get_db)): - current_user = get_current_user(access_token.credentials) - check_authentication(current_user) - db_exists = db.query(Database).filter(Database.id == database_id).first() - if not db_exists: - raise HTTPException( - status_code=404, detail=f"Database with ID {database_id} not found") - return SimpleNamespace(status_code=200, data={"database": {"password": db_exists.password}}) @router.post("/databases/{database_id}/enable") @@ -683,6 +621,72 @@ def database_graph_data(start: Optional[str] = Query(description="Start date for return {"status_code": 200, 'data': {'metadata': metadata, 'graph_data': db_info}} + +@router.get("/databases/{database_id}") +def single_database(database_id: str, access_token: str = Depends(security), db: Session = Depends(get_db)): + current_user = get_current_user(access_token.credentials) + check_authentication(current_user) + + user_database = db.query(Database).filter( + Database.id == database_id).first() + if not user_database: + raise HTTPException(status_code=404, detail="Database not found") + + flavour_name = user_database.database_flavour_name + if not flavour_name: + flavour_name = "mysql" + + db_flavour = get_db_flavour(flavour_name) + + if not db_flavour: + return dict( + status_code=404, + message=f"""Database flavour with name + {user_database.database_flavour_name} is not mysql or postgres.""" + ) + + database_service = db_flavour['class'] + + # Get db status + try: + database_connection = database_service.create_db_connection( + user=user_database.user, password=user_database.password, db_name=user_database.name) + if not database_connection: + db_status = False + else: + db_status = True + except: + db_status = False + finally: + if database_connection: + if database_service == MysqlDbService(): + if database_connection.is_connected(): + database_connection.close() + else: + database_connection.close() + + database_dict = { + **user_database.__dict__, + "db_status": db_status, + "default_storage_kb": database_service.get_database_size( + user=user_database.user, password=user_database.password, db_name=user_database.name) + } + + return SimpleNamespace(status_code=200, data={"database": database_dict}) + + +@router.get("/databases/{database_id}/password") +def get_database_password(database_id: str, access_token: str = Depends(security), db: Session = Depends(get_db)): + current_user = get_current_user(access_token.credentials) + check_authentication(current_user) + + db_exists = db.query(Database).filter(Database.id == database_id).first() + if not db_exists: + raise HTTPException( + status_code=404, detail=f"Database with ID {database_id} not found") + return SimpleNamespace(status_code=200, data={"database": {"password": db_exists.password}}) + + @router.post("/databases/{database_id}/revoke_write_access") def revoke_write_access(database_id: str, access_token: str = Depends(security), db: Session = Depends(get_db)): current_user = get_current_user(access_token.credentials) From c1c5b725d0d6c3997c68d7035183c905604540bc Mon Sep 17 00:00:00 2001 From: Rhodin Nagwere <63339234+rhodinemma@users.noreply.github.com> Date: Tue, 28 Jan 2025 01:09:43 +0530 Subject: [PATCH 3/5] fix pagination total pages count --- app/routes.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/app/routes.py b/app/routes.py index 8c2366e..d049800 100644 --- a/app/routes.py +++ b/app/routes.py @@ -72,7 +72,7 @@ def get_all_databases( Database.database_flavour_name == database_flavour_name) total_count = query.count() - total_pages = (total_count + per_page - 1) + total_pages = (total_count + per_page - 1) // per_page offset = (page - 1) * per_page paginated_query = query.offset(offset).limit(per_page) From 76e753ae2f9cec9585ccb4b5d9610ae7a71cd90a Mon Sep 17 00:00:00 2001 From: Rhodin Nagwere <63339234+rhodinemma@users.noreply.github.com> Date: Tue, 28 Jan 2025 01:24:49 +0530 Subject: [PATCH 4/5] chore: sort databases by date --- app/routes.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/app/routes.py b/app/routes.py index d049800..ec59fe1 100644 --- a/app/routes.py +++ b/app/routes.py @@ -58,7 +58,7 @@ def get_all_databases( current_user = get_current_user(access_token.credentials) check_authentication(current_user) - query = db.query(Database) + query = db.query(Database).order_by(Database.date_created.desc()) if current_user.role != "administrator": query = query.filter( From 9c5dc7fff1dc118c8346b19443f3ec7076c71ad5 Mon Sep 17 00:00:00 2001 From: rhodinemma Date: Wed, 5 Mar 2025 15:44:29 +0300 Subject: [PATCH 5/5] chore: ensure exclusion of deleted database records from listings --- app/routes.py | 13 +++++++------ 1 file changed, 7 insertions(+), 6 deletions(-) diff --git a/app/routes.py b/app/routes.py index ec59fe1..95cbc4d 100644 --- a/app/routes.py +++ b/app/routes.py @@ -29,8 +29,10 @@ def fetch_database_stats(access_token: str = Depends(security), db: Session = De total = 0 for flavour in database_flavours: - databases = db.query(Database).filter_by( - database_flavour_name=flavour['name']).all() + databases = db.query(Database).filter( + Database.database_flavour_name == flavour['name'], + Database.deleted == False + ).all() database_count = len(databases) dbs_per_flavour[f"{flavour['name']}_db_count"] = database_count @@ -71,6 +73,9 @@ def get_all_databases( query = query.filter( Database.database_flavour_name == database_flavour_name) + # ensure at this point that deleted databases are not part of the query for the above filters + query = query.filter(Database.deleted == False) + total_count = query.count() total_pages = (total_count + per_page - 1) // per_page @@ -181,9 +186,6 @@ def create_database(database: DatabaseFlavor, access_token: str = Depends(securi return SimpleNamespace(status_code=201, data={"database": database}) - - - @router.post("/databases/{database_id}/enable") def enable_database(database_id: str, access_token: str = Depends(security), db: Session = Depends(get_db)): current_user = get_current_user(access_token.credentials) @@ -621,7 +623,6 @@ def database_graph_data(start: Optional[str] = Query(description="Start date for return {"status_code": 200, 'data': {'metadata': metadata, 'graph_data': db_info}} - @router.get("/databases/{database_id}") def single_database(database_id: str, access_token: str = Depends(security), db: Session = Depends(get_db)): current_user = get_current_user(access_token.credentials)