3030
3131async def has_officer_private_info_access (
3232 request : Request ,
33- db_session : database .DBSession ,
33+ db_session : database .DBSession
3434) -> tuple [None | str , None | str , bool ]:
35- # determine if the user has access to this private data
35+ """ determine if the user has access to private officer info"""
3636 session_id = request .cookies .get ("session_id" , None )
3737 if session_id is None :
3838 return None , None , False
@@ -44,6 +44,21 @@ async def has_officer_private_info_access(
4444 has_private_access = await OfficerPrivateInfo .has_permission (db_session , computing_id )
4545 return session_id , computing_id , has_private_access
4646
47+ async def logged_in_or_raise (
48+ request : Request ,
49+ db_session : database .DBSession
50+ ) -> tuple [str , str ]:
51+ """gets the user's computing_id, or raises an exception if the current request is not logged in"""
52+ session_id = request .cookies .get ("session_id" , None )
53+ if session_id is None :
54+ raise HTTPException (status_code = 401 )
55+
56+ session_computing_id = await auth .crud .get_computing_id (db_session , session_id )
57+ if session_computing_id is None :
58+ raise HTTPException (status_code = 401 )
59+
60+ return session_id , session_computing_id
61+
4762# ---------------------------------------- #
4863# endpoints
4964
@@ -58,62 +73,60 @@ async def current_officers(
5873):
5974 _ , _ , has_private_access = await has_officer_private_info_access (request , db_session )
6075 current_officers = await officers .crud .current_officers (db_session , has_private_access )
61- json_current_executives = {
76+ return JSONResponse ( {
6277 position : [
63- officer_data .serializable_dict () for officer_data in officer_data_list
64- ] for position , officer_data_list in current_officers . items ()
65- }
66-
67- return JSONResponse ( json_current_executives )
78+ officer_data .serializable_dict ()
79+ for officer_data in officer_data_list
80+ ]
81+ for position , officer_data_list in current_officers . items ()
82+ } )
6883
6984@router .get (
7085 "/all" ,
71- description = "Information for all execs from all exec terms" ,
86+ description = "Information for all execs from all exec terms"
7287)
7388async def all_officers (
7489 request : Request ,
7590 db_session : database .DBSession ,
7691 # Officer terms for officers which have not yet started their term yet are considered private,
77- # and may only be accessed by that officer and executives.
78- view_not_started_officer_terms : bool = False ,
92+ # and may only be accessed by that officer and executives. All other officer terms are public.
93+ include_future_terms : bool = False ,
7994):
8095 _ , computing_id , has_private_access = await has_officer_private_info_access (request , db_session )
81- if view_not_started_officer_terms :
96+ if include_future_terms :
8297 is_website_admin = (computing_id is not None ) and (await WebsiteAdmin .has_permission (db_session , computing_id ))
8398 if not is_website_admin :
8499 raise HTTPException (status_code = 401 , detail = "only website admins can view all executive terms that have not started yet" )
85100
86- all_officers = await officers .crud .all_officers (db_session , has_private_access , not view_not_started_officer_terms )
101+ all_officers = await officers .crud .all_officers (db_session , has_private_access , include_future_terms )
87102 return JSONResponse ([
88103 officer_data .serializable_dict ()
89104 for officer_data in all_officers
90105 ])
91106
92107@router .get (
93108 "/terms/{computing_id}" ,
94- description = "Get term info for an executive. Private info will be provided if you have permissions." ,
109+ description = """Get term info for an executive. All term info is public for all past or active terms.""" ,
110+ tags = ["login-required" ]
95111)
96112async def get_officer_terms (
97113 request : Request ,
98114 db_session : database .DBSession ,
99115 computing_id : str ,
116+ # TODO: remove `max_terms`
100117 # the maximum number of terms to return, in chronological order
118+ # helpful if you only want the most recent... though a person can have many active terms,
119+ # so not really that helpful imo....
101120 max_terms : int | None = None ,
102- include_inactive : bool = False ,
121+ include_future_terms : bool = False
103122):
104- # TODO: put these into a function
105- session_id = request .cookies .get ("session_id" , None )
106- if session_id is None :
107- raise HTTPException (status_code = 401 )
108-
109- # TODO: put these into a function
110- session_computing_id = await auth .crud .get_computing_id (db_session , session_id )
111- if session_computing_id is None :
112- raise HTTPException (status_code = 401 )
123+ # TODO: should this be login-required if a user does not want to include future terms? The info is
124+ # supposed to all be public
125+ _ , session_computing_id = await logged_in_or_raise (request , db_session )
113126
114127 if (
115128 computing_id != session_computing_id
116- and include_inactive
129+ and include_future_terms
117130 and not await WebsiteAdmin .has_permission (db_session , session_computing_id )
118131 ):
119132 raise HTTPException (status_code = 401 )
@@ -123,37 +136,33 @@ async def get_officer_terms(
123136 db_session ,
124137 computing_id ,
125138 max_terms ,
126- include_inactive = include_inactive
139+ include_future_terms
127140 )
128- return JSONResponse ([term .serializable_dict () for term in officer_terms ])
141+ return JSONResponse ([
142+ term .serializable_dict () for term in officer_terms
143+ ])
129144
130145@router .get (
131146 "/info/{computing_id}" ,
132- description = "Get officer info for the current user, if they've ever been an exec." ,
147+ description = "Get officer info for the current user, if they've ever been an exec. Only admins can get info about another user." ,
148+ tags = ["login-required" ]
133149)
134150async def get_officer_info (
135151 request : Request ,
136152 db_session : database .DBSession ,
137153 computing_id : str ,
138154):
139- session_id = request .cookies .get ("session_id" , None )
140- if session_id is None :
141- raise HTTPException (status_code = 401 )
142-
143- session_computing_id = await auth .crud .get_computing_id (db_session , session_id )
144- if session_computing_id is None :
145- raise HTTPException (status_code = 401 )
155+ _ , session_computing_id = await logged_in_or_raise (request , db_session )
146156
147- session_computing_id = await auth .crud .get_computing_id (db_session , session_id )
148157 if (
149158 computing_id != session_computing_id
150159 and not await WebsiteAdmin .has_permission (db_session , session_computing_id )
151160 ):
152- # the current user can only input the info for another user if they have permissions
153161 raise HTTPException (status_code = 401 , detail = "must have website admin permissions to get officer info about another user" )
154162
155- officer_info = await officers .crud .officer_info (db_session , computing_id )
163+ officer_info = await officers .crud .get_officer_info (db_session , computing_id )
156164 if officer_info is None :
165+ # this will be triggered if a non-officer calls the endpoint
157166 raise HTTPException (status_code = 404 , detail = "user has no officer info" )
158167
159168 return JSONResponse (officer_info .serializable_dict ())
@@ -210,7 +219,7 @@ async def new_officer_term(
210219 "After elections, officer computing ids are input into our system. "
211220 "If you have been elected as a new officer, you may authenticate with SFU CAS, "
212221 "then input your information & the valid token for us. Admins may update this info."
213- ),
222+ )
214223)
215224async def update_info (
216225 request : Request ,
@@ -236,7 +245,7 @@ async def update_info(
236245
237246 # TODO: log all important changes just to a .log file
238247
239- old_officer_info = await officers .crud .officer_info (db_session , computing_id )
248+ old_officer_info = await officers .crud .get_officer_info (db_session , computing_id )
240249 new_officer_info = officer_info_upload .to_officer_info (
241250 computing_id = computing_id ,
242251 discord_id = None ,
@@ -295,14 +304,15 @@ async def update_info(
295304
296305 await db_session .commit ()
297306
298- updated_officer_info = await officers .crud .officer_info (db_session , computing_id )
307+ updated_officer_info = await officers .crud .get_officer_info (db_session , computing_id )
299308 return JSONResponse ({
300309 "updated_officer_info" : updated_officer_info .serializable_dict (),
301310 "validation_failures" : validation_failures ,
302311 })
303312
304313@router .patch (
305314 "/term/{term_id}" ,
315+ description = ""
306316)
307317async def update_term (
308318 request : Request ,
@@ -321,7 +331,7 @@ async def update_term(
321331 if session_computing_id is None :
322332 raise HTTPException (status_code = 401 )
323333
324- old_officer_term = await officers .crud .officer_term (db_session , term_id )
334+ old_officer_term = await officers .crud .get_officer_term_by_id (db_session , term_id )
325335
326336 if (
327337 old_officer_term .computing_id != session_computing_id
@@ -354,17 +364,16 @@ async def update_term(
354364
355365 await db_session .commit ()
356366
357- new_officer_term = await officers .crud .officer_term (db_session , term_id )
367+ new_officer_term = await officers .crud .get_officer_term_by_id (db_session , term_id )
358368 return JSONResponse ({
359369 "updated_officer_term" : new_officer_term .serializable_dict (),
360370 "validation_failures" : [], # none for now, but may be important later
361371 })
362372
363- """
364373@router .post (
365- "/remove",
366- description="Only the sysadmin, president, or DoA can submit this request. It will usually be the DoA. Removes the officer from the system entirely . BE CAREFUL WITH THIS OPTION aaaaaaaaaaaaaaaaaa.",
374+ "/remove/{term_id} " ,
375+ description = "Remove the specified officer term. Only website admins can run this endpoint . BE CAREFUL WITH THIS!"
367376)
368377async def remove_officer ():
378+ # TODO: this
369379 return {}
370- """
0 commit comments