From 4b659be1e7ed2fefd2d7ea4962ba2386cda08795 Mon Sep 17 00:00:00 2001 From: Jon Andre Briones Date: Sat, 27 Sep 2025 00:10:49 -0700 Subject: [PATCH 1/6] wip: add GET all registrations --- src/registrations/crud.py | 9 +++++++++ src/registrations/urls.py | 11 +++++++++++ 2 files changed, 20 insertions(+) diff --git a/src/registrations/crud.py b/src/registrations/crud.py index 6d135b5..0a6d482 100644 --- a/src/registrations/crud.py +++ b/src/registrations/crud.py @@ -7,6 +7,15 @@ from registrations.tables import NomineeApplication +async def get_all_registrations( + db_session: AsyncSession +) -> Sequence[NomineeApplication]: + registrations = (await db_session.scalars( + sqlalchemy + .select(NomineeApplication) + )).all() + return registrations + async def get_all_registrations_of_user( db_session: AsyncSession, computing_id: str, diff --git a/src/registrations/urls.py b/src/registrations/urls.py index 1fe552f..7bbcaeb 100644 --- a/src/registrations/urls.py +++ b/src/registrations/urls.py @@ -25,6 +25,17 @@ tags=["registration"], ) +@router.get( + "", + description="get all the registrations", + response_model=list[NomineeApplicationModel], + operation_id="get_registrations" +) +async def get_all_registrations( + db_session: database.DBSession, +): + return await registrations.crud.get_all_registrations(db_session) + @router.get( "/{election_name:str}", description="get all the registrations of a single election", From a643224e84885e41a13e634ed943c25e127a288a Mon Sep 17 00:00:00 2001 From: Jon Andre Briones Date: Sat, 27 Sep 2025 00:38:16 -0700 Subject: [PATCH 2/6] wip: add POST nominee --- src/nominees/urls.py | 35 +++++++++++++++++++++++++++++++++++ 1 file changed, 35 insertions(+) diff --git a/src/nominees/urls.py b/src/nominees/urls.py index 15d8136..40da431 100644 --- a/src/nominees/urls.py +++ b/src/nominees/urls.py @@ -8,6 +8,7 @@ NomineeInfoUpdateParams, ) from nominees.tables import NomineeInfo +from utils.shared_models import DetailModel from utils.urls import admin_or_raise router = APIRouter( @@ -15,6 +16,39 @@ tags=["nominee"], ) +@router.post( + "", + description="Nominee info is always publically tied to election, so be careful!", + response_model=NomineeInfoModel, + responses={ + 500: { "description": "failed to fetch new nominee", "model": DetailModel } + }, + operation_id="create_nominee" +) +async def create_nominee( + request: Request, + db_session: database.DBSession, + body: NomineeInfoModel +): + await admin_or_raise(request, db_session) + await nominees.crud.create_nominee_info(db_session, NomineeInfo( + computing_id=body.computing_id, + full_name=body.full_name, + linked_in=body.linked_in, + instagram=body.instagram, + email=body.email, + discord_username=body.discord_username, + )) + + nominee_info = await nominees.crud.get_nominee_info(db_session, body.computing_id) + if nominee_info is None: + raise HTTPException( + status_code=status.HTTP_500_INTERNAL_SERVER_ERROR, + detail="couldn't fetch newly created nominee" + ) + + return JSONResponse(nominee_info) + @router.get( "/{computing_id:str}", description="Nominee info is always publically tied to election, so be careful!", @@ -71,6 +105,7 @@ async def provide_nominee_info( if body.discord_username is not None: updated_data["discord_username"] = body.discord_username + # TODO: Look into using something built into SQLAlchemy/Pydantic for better entry updates existing_info = await nominees.crud.get_nominee_info(db_session, computing_id) # if not already existing, create it if not existing_info: From e4035bd267c06b3ef2d7756aa3b2a8717e7704ba Mon Sep 17 00:00:00 2001 From: Jon Andre Briones Date: Sat, 27 Sep 2025 00:48:23 -0700 Subject: [PATCH 3/6] wip: add GET all nominees --- src/nominees/crud.py | 11 +++++++++++ src/nominees/urls.py | 21 +++++++++++++++++++++ 2 files changed, 32 insertions(+) diff --git a/src/nominees/crud.py b/src/nominees/crud.py index 372ed91..01dd7f8 100644 --- a/src/nominees/crud.py +++ b/src/nominees/crud.py @@ -1,9 +1,20 @@ +from collections.abc import Sequence + import sqlalchemy from sqlalchemy.ext.asyncio import AsyncSession from nominees.tables import NomineeInfo +async def get_all_nominees( + db_session: AsyncSession, +) -> Sequence[NomineeInfo]: + nominees = (await db_session.scalars( + sqlalchemy + .select(NomineeInfo) + )).all() + return nominees + async def get_nominee_info( db_session: AsyncSession, computing_id: str, diff --git a/src/nominees/urls.py b/src/nominees/urls.py index 40da431..c4d28ef 100644 --- a/src/nominees/urls.py +++ b/src/nominees/urls.py @@ -16,6 +16,27 @@ tags=["nominee"], ) +@router.get( + "", + description="Get all nominees", + response_model=list[NomineeInfoModel], + responses={ + 403: { "description": "need to be an admin", "model": DetailModel } + }, + operation_id="create_nominee" +) +async def get_all_nominees( + request: Request, + db_session: database.DBSession, +): + # Putting this behind a wall since there is private information here + await admin_or_raise(request, db_session) + nominees_list = await nominees.crud.get_all_nominees(db_session) + + return JSONResponse([ + item.serialize() for item in nominees_list + ]) + @router.post( "", description="Nominee info is always publically tied to election, so be careful!", From d4a2fdef36d05e71ab3b4d05ce870ec2038b452c Mon Sep 17 00:00:00 2001 From: Jon Andre Briones Date: Sat, 27 Sep 2025 12:41:42 -0700 Subject: [PATCH 4/6] wip: add DELETE nominee_info --- src/nominees/crud.py | 10 ++++++++++ src/nominees/urls.py | 16 +++++++++++++++- 2 files changed, 25 insertions(+), 1 deletion(-) diff --git a/src/nominees/crud.py b/src/nominees/crud.py index 01dd7f8..5861f01 100644 --- a/src/nominees/crud.py +++ b/src/nominees/crud.py @@ -41,3 +41,13 @@ async def update_nominee_info( .where(NomineeInfo.computing_id == info.computing_id) .values(info.to_update_dict()) ) + +async def delete_nominee_info( + db_session: AsyncSession, + computing_id: str, +): + await db_session.execute( + sqlalchemy + .delete(NomineeInfo) + .where(NomineeInfo.computing_id == computing_id) + ) diff --git a/src/nominees/urls.py b/src/nominees/urls.py index c4d28ef..357f568 100644 --- a/src/nominees/urls.py +++ b/src/nominees/urls.py @@ -8,7 +8,7 @@ NomineeInfoUpdateParams, ) from nominees.tables import NomineeInfo -from utils.shared_models import DetailModel +from utils.shared_models import DetailModel, SuccessResponse from utils.urls import admin_or_raise router = APIRouter( @@ -95,6 +95,20 @@ async def get_nominee_info( return JSONResponse(nominee_info.serialize()) +@router.delete( + "/{computing_id:str}", + description="Nominee info is always publically tied to election, so be careful!", + operation_id="delete_nominee" +) +async def delete_nominee_info( + request: Request, + db_session: database.DBSession, + computing_id: str +): + await admin_or_raise(request, db_session) + await nominees.crud.delete_nominee_info(db_session, computing_id) + await db_session.commit() + @router.patch( "/{computing_id:str}", description="Will create or update nominee info. Returns an updated copy of their nominee info.", From 2a5f562c9ff75eb95fcfe52465cd79d50d20297a Mon Sep 17 00:00:00 2001 From: Jon Andre Briones Date: Sun, 28 Sep 2025 14:10:48 -0700 Subject: [PATCH 5/6] fix(Elections): duplicate operation id in nominees URLs --- src/nominees/urls.py | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/src/nominees/urls.py b/src/nominees/urls.py index 357f568..d922eae 100644 --- a/src/nominees/urls.py +++ b/src/nominees/urls.py @@ -8,7 +8,7 @@ NomineeInfoUpdateParams, ) from nominees.tables import NomineeInfo -from utils.shared_models import DetailModel, SuccessResponse +from utils.shared_models import DetailModel from utils.urls import admin_or_raise router = APIRouter( @@ -23,7 +23,7 @@ responses={ 403: { "description": "need to be an admin", "model": DetailModel } }, - operation_id="create_nominee" + operation_id="get_all_nominees" ) async def get_all_nominees( request: Request, @@ -97,7 +97,7 @@ async def get_nominee_info( @router.delete( "/{computing_id:str}", - description="Nominee info is always publically tied to election, so be careful!", + description="Delete a nominee", operation_id="delete_nominee" ) async def delete_nominee_info( From 82dccf766d66608e518b099cfcf1c643b0963086 Mon Sep 17 00:00:00 2001 From: Jon Andre Briones Date: Sun, 28 Sep 2025 14:42:38 -0700 Subject: [PATCH 6/6] fix: patch to put --- src/nominees/urls.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/nominees/urls.py b/src/nominees/urls.py index d922eae..dfe2af4 100644 --- a/src/nominees/urls.py +++ b/src/nominees/urls.py @@ -109,7 +109,7 @@ async def delete_nominee_info( await nominees.crud.delete_nominee_info(db_session, computing_id) await db_session.commit() -@router.patch( +@router.put( "/{computing_id:str}", description="Will create or update nominee info. Returns an updated copy of their nominee info.", response_model=NomineeInfoModel,