55import database
66import officers .crud
77import utils
8- from officers .models import OfficerTermResponse , PrivateOfficerResponse , PublicOfficerResponse
8+ from officers .models import (
9+ OfficerSelfUpdate ,
10+ OfficerTermCreate ,
11+ OfficerTermResponse ,
12+ OfficerUpdate ,
13+ PrivateOfficerInfoResponse ,
14+ PublicOfficerInfoResponse ,
15+ )
916from officers .tables import OfficerInfo , OfficerTerm
1017from officers .types import InitialOfficerInfo , OfficerInfoUpload , OfficerTermUpload
1118from permission .types import OfficerPrivateInfo , WebsiteAdmin
12- from utils .shared_models import DetailModel
13- from utils .urls import logged_in_or_raise
19+ from utils .shared_models import DetailModel , SuccessResponse
20+ from utils .urls import admin_or_raise , is_website_admin , logged_in_or_raise
1421
1522router = APIRouter (
1623 prefix = "/officers" ,
@@ -42,7 +49,7 @@ async def _has_officer_private_info_access(
4249@router .get (
4350 "/current" ,
4451 description = "Get information about the current officers. With no authorization, only get basic info." ,
45- response_model = list [PrivateOfficerResponse ] | list [PublicOfficerResponse ],
52+ response_model = list [PrivateOfficerInfoResponse ] | list [PublicOfficerInfoResponse ],
4653 operation_id = "get_current_officers"
4754)
4855async def current_officers (
@@ -62,9 +69,9 @@ async def current_officers(
6269@router .get (
6370 "/all" ,
6471 description = "Information for all execs from all exec terms" ,
65- response_model = list [PrivateOfficerResponse ] | list [PublicOfficerResponse ],
72+ response_model = list [PrivateOfficerInfoResponse ] | list [PublicOfficerInfoResponse ],
6673 responses = {
67- 401 : { "description" : "not authorized to view private info" , "model" : DetailModel }
74+ 403 : { "description" : "not authorized to view private info" , "model" : DetailModel }
6875 },
6976 operation_id = "get_all_officers"
7077)
@@ -97,7 +104,7 @@ async def all_officers(
97104 responses = {
98105 401 : { "description" : "not authorized to view private info" , "model" : DetailModel }
99106 },
100- operation_id = "get_all_officers "
107+ operation_id = "get_officer_terms_by_id "
101108)
102109async def get_officer_terms (
103110 request : Request ,
@@ -121,8 +128,13 @@ async def get_officer_terms(
121128 ])
122129
123130@router .get (
124- "/info/{computing_id}" ,
131+ "/info/{computing_id:str }" ,
125132 description = "Get officer info for the current user, if they've ever been an exec. Only admins can get info about another user." ,
133+ response_model = PrivateOfficerInfoResponse ,
134+ responses = {
135+ 403 : { "description" : "not authorized to view author user info" , "model" : DetailModel }
136+ },
137+ operation_id = "get_officer_info_by_id"
126138)
127139async def get_officer_info (
128140 request : Request ,
@@ -145,28 +157,27 @@ async def get_officer_info(
145157 Only the sysadmin, president, or DoA can submit this request. It will usually be the DoA.
146158 Updates the system with a new officer, and enables the user to login to the system to input their information.
147159 """ ,
160+ response_model = SuccessResponse ,
161+ responses = {
162+ 403 : { "description" : "must be a website admin" , "model" : DetailModel },
163+ 500 : { "model" : DetailModel },
164+ },
165+ operation_id = "create_officer_term"
148166)
149167async def new_officer_term (
150168 request : Request ,
151169 db_session : database .DBSession ,
152- officer_info_list : list [InitialOfficerInfo ] = Body (), # noqa: B008
170+ officer_info_list : list [OfficerTermCreate ],
153171):
154- """
155- If the current computing_id is not already an officer, officer_info will be created for them.
156- """
157- for officer_info in officer_info_list :
158- officer_info .valid_or_raise ()
159-
160- _ , session_computing_id = await logged_in_or_raise (request , db_session )
161- await WebsiteAdmin .has_permission_or_raise (db_session , session_computing_id )
172+ await admin_or_raise (request , db_session )
162173
163174 for officer_info in officer_info_list :
164175 # if user with officer_info.computing_id has never logged into the website before,
165176 # a site_user tuple will be created for them.
166177 await officers .crud .create_new_officer_info (db_session , OfficerInfo (
167178 computing_id = officer_info .computing_id ,
168179 # TODO (#71): use sfu api to get legal name from officer_info.computing_id
169- legal_name = "default name" ,
180+ legal_name = officer_info . legal_name ,
170181 phone_number = None ,
171182
172183 discord_id = None ,
@@ -183,47 +194,43 @@ async def new_officer_term(
183194 ))
184195
185196 await db_session .commit ()
186- return PlainTextResponse ( "ok" )
197+ return JSONResponse ({ "success" : True } )
187198
188199@router .patch (
189- "/info/{computing_id}" ,
200+ "/info/{computing_id:str }" ,
190201 description = """
191202 After election, officer computing ids are input into our system.
192203 If you have been elected as a new officer, you may authenticate with SFU CAS,
193204 then input your information & the valid token for us. Admins may update this info.
194- """
205+ """ ,
206+ response_model = OfficerPrivateInfo ,
207+ responses = {
208+ 403 : { "description" : "must be a website admin" , "model" : DetailModel },
209+ 500 : { "description" : "failed to fetch after update" , "model" : DetailModel },
210+ },
211+ operation_id = "create_officer_term"
195212)
196213async def update_info (
197214 request : Request ,
198215 db_session : database .DBSession ,
199216 computing_id : str ,
200- officer_info_upload : OfficerInfoUpload = Body () # noqa: B008
217+ officer_info_upload : OfficerUpdate | OfficerSelfUpdate
201218):
202- officer_info_upload .valid_or_raise ()
203- _ , session_computing_id = await logged_in_or_raise (request , db_session )
219+ is_site_admin , _ , session_computing_id = await is_website_admin (request , db_session )
204220
205- if computing_id != session_computing_id :
206- await WebsiteAdmin .has_permission_or_raise (
207- db_session , session_computing_id ,
208- errmsg = "must have website admin permissions to update another user"
209- )
221+ if computing_id != session_computing_id and not is_site_admin :
222+ raise HTTPException (status_code = 403 , detail = "you may not update other officers" )
210223
211224 old_officer_info = await officers .crud .get_officer_info_or_raise (db_session , computing_id )
212- validation_failures , corrected_officer_info = await officer_info_upload .validate (computing_id , old_officer_info )
225+ old_officer_info .update_from_params (officer_info_upload )
226+ await officers .crud .update_officer_info (db_session , old_officer_info )
213227
214228 # TODO (#27): log all important changes just to a .log file & persist them for a few years
215229
216- success = await officers .crud .update_officer_info (db_session , corrected_officer_info )
217- if not success :
218- raise HTTPException (status_code = 400 , detail = "officer_info does not exist yet, please create the officer info entry first" )
219-
220230 await db_session .commit ()
221231
222- updated_officer_info = await officers .crud .get_officer_info_or_raise (db_session , computing_id )
223- return JSONResponse ({
224- "officer_info" : updated_officer_info .serializable_dict (),
225- "validation_failures" : validation_failures ,
226- })
232+ updated_officer_info = await officers .crud .get_new_officer_info_or_raise (db_session , computing_id )
233+ return JSONResponse (updated_officer_info )
227234
228235@router .patch (
229236 "/term/{term_id}" ,
0 commit comments