Skip to content

Commit 69469e1

Browse files
committed
fix(officers): tests now all work
1 parent 268fd97 commit 69469e1

6 files changed

Lines changed: 242 additions & 193 deletions

File tree

src/officers/crud.py

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -325,6 +325,10 @@ async def create_multiple_officers(db_session: database.DBSession, new_officers:
325325
# Flush gets the generated IDs, but does not commit
326326
await db_session.flush()
327327

328+
# Refresh each term to ensure all attributes are loaded for Pydantic validation
329+
for term in new_officer_terms:
330+
await db_session.refresh(term)
331+
328332
return new_officer_terms
329333

330334

src/officers/models.py

Lines changed: 20 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -19,6 +19,7 @@
1919

2020
# Officer Info Models
2121
class OfficerInfo(BaseModel):
22+
model_config = ConfigDict(from_attributes=True)
2223
computing_id: str = Field(..., max_length=COMPUTING_ID_LEN)
2324
legal_name: str = Field(..., max_length=OFFICER_LEGAL_NAME_MAX)
2425
phone_number: str | None = None
@@ -57,8 +58,8 @@ class OfficerTerm(OfficerTermCreate):
5758
class OfficerTermUpdate(BaseModel):
5859
"""Request body to patch an Officer Term"""
5960

60-
computing_id: str | None = Field(..., max_length=COMPUTING_ID_LEN)
61-
position: str | None = Field(..., max_length=128)
61+
computing_id: str | None = Field(None, max_length=COMPUTING_ID_LEN)
62+
position: str | None = Field(None, max_length=128)
6263
start_date: date | None = None
6364
end_date: date | None = None
6465
nickname: str | None = Field(None, max_length=128)
@@ -77,6 +78,9 @@ class OfficerBase(BaseModel):
7778
position: OfficerPositionEnum
7879
start_date: date
7980
end_date: date | None = None
81+
nickname: str | None = None
82+
biography: str | None = None
83+
csss_email: str | None = None
8084

8185

8286
class OfficerPublic(OfficerBase):
@@ -85,9 +89,6 @@ class OfficerPublic(OfficerBase):
8589
"""
8690

8791
is_active: bool
88-
nickname: str | None = None
89-
biography: str | None = None
90-
csss_email: str | None = None
9192

9293

9394
class OfficerPrivate(OfficerPublic):
@@ -105,7 +106,20 @@ class OfficerPrivate(OfficerPublic):
105106
photo_url: str | None = None
106107

107108

108-
class OfficerCreate(OfficerPrivate):
109+
class OfficerCreate(OfficerBase):
110+
"""
111+
Parameters when creating a new Officer
112+
"""
113+
114+
computing_id: str
115+
116+
discord_id: str | None = None
117+
discord_name: str | None = None
118+
discord_nickname: str | None = None
119+
phone_number: str | None = None
120+
github_username: str | None = None
121+
google_drive_email: str | None = None
122+
photo_url: str | None = None
109123
favourite_course_0: str | None = Field(None, max_length=64)
110124
favourite_course_1: str | None = Field(None, max_length=64)
111125
favourite_pl_0: str | None = Field(None, max_length=64)

src/officers/tables.py

Lines changed: 2 additions & 15 deletions
Original file line numberDiff line numberDiff line change
@@ -22,7 +22,7 @@
2222
)
2323
from database import Base
2424
from officers.constants import OFFICER_LEGAL_NAME_MAX, OFFICER_POSITION_MAX, OfficerPositionEnum
25-
from officers.models import OfficerInfo, OfficerTermUpdate, OfficerUpdate
25+
from officers.models import OfficerInfo, OfficerTerm, OfficerTermUpdate, OfficerUpdate
2626

2727

2828
# A row represents an assignment of a person to a position.
@@ -55,20 +55,7 @@ class OfficerTermDB(Base):
5555
__table_args__ = (UniqueConstraint("computing_id", "position", "start_date"),) # This needs a comma to work
5656

5757
def serializable_dict(self) -> dict:
58-
return {
59-
"id": self.id,
60-
"computing_id": self.computing_id,
61-
"position": self.position,
62-
"start_date": self.start_date.isoformat() if self.start_date is not None else None,
63-
"end_date": self.end_date.isoformat() if self.end_date is not None else None,
64-
"nickname": self.nickname,
65-
"favourite_course_0": self.favourite_course_0,
66-
"favourite_course_1": self.favourite_course_1,
67-
"favourite_pl_0": self.favourite_pl_0,
68-
"favourite_pl_1": self.favourite_pl_1,
69-
"biography": self.biography,
70-
"photo_url": self.photo_url,
71-
}
58+
return OfficerTerm.model_validate(self).model_dump(mode="json")
7259

7360
def update_from_params(self, params: OfficerTermUpdate, admin_update: bool = True):
7461
if admin_update:

src/officers/urls.py

Lines changed: 11 additions & 13 deletions
Original file line numberDiff line numberDiff line change
@@ -5,7 +5,7 @@
55
import database
66
import officers.crud
77
import utils
8-
from dependencies import LoggedInUser, perm_admin
8+
from dependencies import LoggedInUser, SessionUser, perm_admin
99
from officers.constants import OfficerPositionEnum
1010
from officers.models import (
1111
OfficerCreate,
@@ -16,7 +16,6 @@
1616
OfficerTermUpdate,
1717
OfficerUpdate,
1818
)
19-
from officers.tables import OfficerInfoDB
2019
from permission.types import OfficerPrivateInfo
2120
from utils.permissions import is_user_website_admin, verify_update
2221
from utils.shared_models import DetailModel, SuccessResponse
@@ -112,21 +111,18 @@ async def all_officers(
112111
operation_id="get_officer_terms_by_id",
113112
)
114113
async def get_officer_terms(
115-
request: Request, db_session: database.DBSession, computing_id: str, include_future_terms: bool = False
114+
user_id: SessionUser, db_session: database.DBSession, computing_id: str, include_future_terms: bool = False
116115
):
117116
if include_future_terms:
118-
await verify_update(request, db_session, computing_id)
119-
# _, session_computing_id = await get_user(request, db_session)
120-
# if computing_id != session_computing_id and not is_user_website_admin(session_computing_id, db_session):
121-
# raise HTTPException(status_code=status.HTTP_403_FORBIDDEN, detail="not authorized")
117+
await verify_update(user_id, db_session, computing_id)
122118

123119
# all term info is public, so anyone can get any of it
124120
officer_terms = await officers.crud.get_officer_terms(db_session, computing_id, include_future_terms)
125121
return JSONResponse([OfficerTerm.model_validate(term).model_dump(mode="json") for term in officer_terms])
126122

127123

128124
@router.get(
129-
"/info/{computing_id:str}",
125+
"/info/{computing_id}",
130126
description="Get officer info for the current user, if they've ever been an exec. Only admins can get info about another user.",
131127
response_model=OfficerInfo,
132128
responses={403: {"description": "not authorized to view author user info", "model": DetailModel}},
@@ -163,9 +159,10 @@ async def create_officer_term(
163159
officer_list: list[OfficerCreate],
164160
):
165161
new_terms = await officers.crud.create_multiple_officers(db_session, officer_list)
162+
content = [term.serializable_dict() for term in new_terms]
166163

167164
await db_session.commit()
168-
return JSONResponse([OfficerTerm.model_validate(term).model_dump(mode="json") for term in new_terms])
165+
return JSONResponse(content)
169166

170167

171168
@router.patch(
@@ -183,12 +180,12 @@ async def create_officer_term(
183180
operation_id="update_officer_info",
184181
)
185182
async def update_officer_info(
186-
request: Request,
183+
user_id: SessionUser,
187184
db_session: database.DBSession,
188185
computing_id: str,
189186
officer_info_upload: OfficerUpdate,
190187
):
191-
await verify_update(request, db_session, computing_id)
188+
await verify_update(user_id, db_session, computing_id)
192189

193190
old_officer_info = await officers.crud.get_officer_info_or_raise(db_session, computing_id)
194191
old_officer_info.update_from_params(officer_info_upload)
@@ -221,8 +218,9 @@ async def update_officer_term(db_session: database.DBSession, term_id: int, body
221218

222219
old_officer_term = await officers.crud.get_officer_term_by_id_or_raise(db_session, term_id)
223220

224-
if utils.is_past_term(old_officer_term):
225-
raise HTTPException(status_code=403, detail="you may not update past terms")
221+
# TODO: Enable this check if we allow non-website admins to change their information
222+
# if utils.is_past_term(old_officer_term):
223+
# raise HTTPException(status_code=403, detail="you may not update past terms")
226224

227225
new_data = body.model_dump(exclude_unset=True)
228226

0 commit comments

Comments
 (0)