Skip to content

Commit f45f464

Browse files
committed
allow changing computing_id by admins and add all TODOs
1 parent c1f3888 commit f45f464

File tree

5 files changed

+26
-30
lines changed

5 files changed

+26
-30
lines changed

src/officers/constants.py

Lines changed: 4 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -28,8 +28,7 @@ def position_list() -> list[str]:
2828

2929
@staticmethod
3030
def length_in_semesters(position: str) -> int | None:
31-
# TODO: ask the committee to maintain a json file with all the important details from the constitution
32-
# (I can create the version version of the file)
31+
# TODO (#101): ask the committee to maintain a json file with all the important details from the constitution
3332
"""How many semester position is active for, according to the CSSS Constitution"""
3433
return _LENGTH_MAP[position]
3534

@@ -71,6 +70,7 @@ def is_signer(position: str) -> bool:
7170

7271
@staticmethod
7372
def expected_positions() -> list[str]:
73+
# TODO (#93): use this function in the daily cronjobs
7474
return [
7575
OfficerPosition.PRESIDENT,
7676
OfficerPosition.VICE_PRESIDENT,
@@ -81,11 +81,11 @@ def expected_positions() -> list[str]:
8181
OfficerPosition.DIRECTOR_OF_EDUCATIONAL_EVENTS,
8282
OfficerPosition.ASSISTANT_DIRECTOR_OF_EVENTS,
8383
OfficerPosition.DIRECTOR_OF_COMMUNICATIONS,
84-
#OfficerPosition.DIRECTOR_OF_OUTREACH, # TODO: when https://github.com/CSSS/documents/pull/9/files merged
84+
#OfficerPosition.DIRECTOR_OF_OUTREACH, # TODO (#101): when https://github.com/CSSS/documents/pull/9/files merged
8585
OfficerPosition.DIRECTOR_OF_MULTIMEDIA,
8686
OfficerPosition.DIRECTOR_OF_ARCHIVES,
8787
OfficerPosition.EXECUTIVE_AT_LARGE,
88-
# TODO: expect these only during fall & spring semesters. Also, TODO: this todo is correct...
88+
# TODO (#101): expect these only during fall & spring semesters.
8989
#OfficerPosition.FIRST_YEAR_REPRESENTATIVE,
9090

9191
#ElectionsOfficer,

src/officers/crud.py

Lines changed: 3 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -196,8 +196,8 @@ async def update_officer_info(
196196
if officer_info is None:
197197
return False
198198

199-
# TODO: how to detect an entry insert error? For example, what happens if
200-
# we try to set our discord id to be the same as another executive's?
199+
# NOTE: if there's ever an insert entry error, it will raise SQLAlchemyError
200+
# see: https://stackoverflow.com/questions/2136739/how-to-check-and-handle-errors-in-sqlalchemy
201201
await db_session.execute(
202202
sqlalchemy
203203
.update(OfficerInfo)
@@ -211,7 +211,7 @@ async def update_officer_term(
211211
new_officer_term: OfficerTerm,
212212
) -> bool:
213213
"""
214-
Update based on the term id.
214+
Update all officer term data in `new_officer_term` based on the term id.
215215
Returns false if the above entry does not exist.
216216
"""
217217
officer_term = await db_session.scalar(
@@ -231,7 +231,6 @@ async def update_officer_term(
231231
return True
232232

233233
async def delete_officer_term_by_id(db_session: database.DBSession, term_id: int):
234-
# TODO: detect error and return the response
235234
await db_session.execute(
236235
sqlalchemy
237236
.delete(OfficerTerm)

src/officers/tables.py

Lines changed: 6 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -25,8 +25,7 @@
2525
class OfficerTerm(Base):
2626
__tablename__ = "officer_term"
2727

28-
# TODO: change primary key to computing_id, position, start_date?
29-
# nah, I like having a term-id -> just do a check when inserting?
28+
# TODO (#98): create a unique constraint for (computing_id, position, start_date).
3029
id = Column(Integer, primary_key=True, autoincrement=True)
3130

3231
computing_id = Column(
@@ -83,8 +82,7 @@ def is_filled_in(self):
8382

8483
def to_update_dict(self) -> dict:
8584
return {
86-
# TODO: do we want computing_id to be changeable?
87-
# "computing_id": self.computing_id,
85+
"computing_id": self.computing_id,
8886

8987
"position": self.position,
9088
"start_date": self.start_date,
@@ -114,24 +112,21 @@ class OfficerInfo(Base):
114112
legal_name = Column(String(128), nullable=False) # some people have long names, you never know
115113
phone_number = Column(String(24), nullable=True)
116114

117-
# a null discord id would mean you don't have discord
118-
# TODO: add unique constraints to these (stops users from stealing the username of someone else)
115+
# TODO (#99): add unique constraints to discord_id (stops users from stealing the username of someone else)
119116
discord_id = Column(String(DISCORD_ID_LEN), nullable=True)
120117
discord_name = Column(String(DISCORD_NAME_LEN), nullable=True)
121118
# this is their nickname in the csss server
122119
discord_nickname = Column(String(DISCORD_NICKNAME_LEN), nullable=True)
123120

124121
# Technically 320 is the most common max-size for emails, but we'll use 256 instead,
125122
# since it's reasonably large (input validate this too)
126-
# TODO: add unique constraint to this (stops users from stealing the username of someone else)
123+
# TODO (#99): add unique constraint to this (stops users from stealing the username of someone else)
127124
google_drive_email = Column(String(256), nullable=True)
128125

129-
# TODO: add unique constraint to this (stops users from stealing the username of someone else)
126+
# TODO (#99): add unique constraint to this (stops users from stealing the username of someone else)
130127
github_username = Column(String(GITHUB_USERNAME_LEN), nullable=True)
131128

132-
# NOTE: not sure if we'll need this, depending on implementation
133-
# TODO: get this data on the fly when requested, but rate limit users
134-
# to something like 1/s 100/hour
129+
# TODO (#22): add support for giving executives bitwarden access automagically
135130
# has_signed_into_bitwarden = Column(Boolean)
136131

137132
def serializable_dict(self) -> dict:

src/officers/types.py

Lines changed: 8 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -91,7 +91,7 @@ async def validate(self, computing_id: str, old_officer_info: OfficerInfo) -> tu
9191
corrected_officer_info.discord_id = discord_user.id
9292
corrected_officer_info.discord_nickname = discord_user.global_name
9393

94-
# TODO: validate google-email using google module, by trying to assign the user to a permission or something
94+
# TODO (#82): validate google-email using google module, by trying to assign the user to a permission or something
9595
if not utils.is_valid_email(self.google_drive_email):
9696
validation_failures += [f"invalid email format {self.google_drive_email}"]
9797
corrected_officer_info.google_drive_email = old_officer_info.google_drive_email
@@ -101,15 +101,16 @@ async def validate(self, computing_id: str, old_officer_info: OfficerInfo) -> tu
101101
validation_failures += [f"invalid github username {self.github_username}"]
102102
corrected_officer_info.github_username = old_officer_info.github_username
103103

104-
# TODO: if github user exists, invite the github user to the org (or can we simply add them directly?)
105-
# -> do so outside this function
106-
# TODO: detect if changing github username & uninvite old user
104+
# TODO (#93): add the following to the daily cronjob
105+
# TODO (#97): if github user exists, invite the github user to the org (or can we simply add them directly?)
106+
# -> do so outside this function. Also, detect if the github username is being changed & uninvite the old user
107107

108108
return validation_failures, corrected_officer_info
109109

110110
@dataclass
111111
class OfficerTermUpload:
112112
# only admins can change:
113+
computing_id: str
113114
position: str
114115
start_date: date
115116
end_date: None | date = None
@@ -122,22 +123,20 @@ class OfficerTermUpload:
122123
favourite_pl_1: None | str = None
123124
biography: None | str = None
124125

125-
# TODO: we're going to need an API call to upload images
126-
# NOTE: changing the name of this variable without changing all instances is breaking
126+
# TODO (#39): we're going to need an endpoint for uploading images
127127
photo_url: None | str = None
128128

129129
def valid_or_raise(self):
130-
# NOTE: An officer can change their own data for terms that are ongoing.
131130
if self.position not in OfficerPosition.position_list():
132131
raise HTTPException(status_code=400, detail=f"invalid new position={self.position}")
133132
elif self.end_date is not None and self.start_date > self.end_date:
134133
raise HTTPException(status_code=400, detail="end_date must be after start_date")
135134

136-
def to_officer_term(self, term_id: str, computing_id:str) -> OfficerTerm:
135+
def to_officer_term(self, term_id: str) -> OfficerTerm:
137136
return OfficerTerm(
138137
id = term_id,
139-
computing_id = computing_id,
140138

139+
computing_id = self.computing_id,
141140
position = self.position,
142141
start_date = self.start_date,
143142
end_date = self.end_date,

src/officers/urls.py

Lines changed: 5 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -262,7 +262,8 @@ async def update_term(
262262
)
263263

264264
if (
265-
officer_term_upload.position != old_officer_term.position
265+
officer_term_upload.computing_id != old_officer_term.computing_id
266+
or officer_term_upload.position != old_officer_term.position
266267
or officer_term_upload.start_date != old_officer_term.start_date
267268
or officer_term_upload.end_date != old_officer_term.end_date
268269
):
@@ -274,7 +275,7 @@ async def update_term(
274275
# TODO (#27): log all important changes to a .log file
275276
success = await officers.crud.update_officer_term(
276277
db_session,
277-
officer_term_upload.to_officer_term(term_id, old_officer_term.computing_id)
278+
officer_term_upload.to_officer_term(term_id)
278279
)
279280
if not success:
280281
raise HTTPException(status_code=400, detail="the associated officer_term does not exist yet, please create it first")
@@ -306,6 +307,8 @@ async def remove_officer(
306307
deleted_officer_term = await officers.crud.get_officer_term_by_id(db_session, term_id)
307308

308309
# TODO (#27): log all important changes to a .log file
310+
311+
# TODO (#100): return whether the deletion succeeded or not
309312
await officers.crud.delete_officer_term_by_id(db_session, term_id)
310313
await db_session.commit()
311314

0 commit comments

Comments
 (0)