Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

First Elections PR #63

Open
wants to merge 34 commits into
base: main
Choose a base branch
from
Open

First Elections PR #63

wants to merge 34 commits into from

Conversation

EarthenSky
Copy link
Collaborator

@EarthenSky EarthenSky commented Aug 9, 2024

elections PR, woo!

@EarthenSky EarthenSky linked an issue Aug 9, 2024 that may be closed by this pull request
src/elections/models.py Outdated Show resolved Hide resolved
@EarthenSky EarthenSky changed the title Issue 25 First Elections PR Aug 18, 2024
@DerpyWasHere DerpyWasHere marked this pull request as ready for review September 27, 2024 01:48
Copy link
Collaborator Author

@EarthenSky EarthenSky left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I'll do another review round after, but 99% looks good!

src/elections/tables.py Show resolved Hide resolved
src/elections/tables.py Outdated Show resolved Hide resolved
src/elections/urls.py Outdated Show resolved Hide resolved
src/elections/urls.py Outdated Show resolved Hide resolved
src/elections/crud.py Outdated Show resolved Hide resolved
src/elections/crud.py Outdated Show resolved Hide resolved
src/elections/crud.py Outdated Show resolved Hide resolved
src/elections/tables.py Outdated Show resolved Hide resolved
src/elections/crud.py Outdated Show resolved Hide resolved
election = (await db_session.execute(sqlalchemy.select(Election).filter_by(slug=params["slug"]))).scalar_one()

if params["date"] is not None:
election.date = params["date"]
Copy link
Collaborator Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I'm not sure if this syntax actually emits an sql statement, but maybe we could use an update function?

Copy link
Member

@DerpyWasHere DerpyWasHere Jan 13, 2025

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This emits an SQL statement and will just fetch the first matching election (since slugs are supposed to be unique). An update isn't necessary as this isn't actually modifying anything. (We use an update later in this function though.)

Copy link
Collaborator Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Does setting election.date = datetime.now() emit an SQL UPDATE? or does it just update the local variable. iirc if you do this assignment then commit, it should update the assignment without the following UPDATE.

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Didn't you suggest above to not commit at the end of this and let API endpoints handle the commit? The elections/update_election endpoint has the commit for this function.

Copy link
Collaborator Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

that is true! i wasn't suggesting to commit here either, just talking about the hypothetical behaviour. I suppose even if you don't commit, doing db_session.execute(...) emits SQL statements.

Looks at this stackoverflow https://stackoverflow.com/questions/9667138/how-to-update-sqlalchemy-row-entry#:~:text=UPDATE%20using%20SQLAlchemy%3A-,user.no_of_logins%20%2B%3D%201,-session.commit()

it implies that setting election.start_datetime = params.start_datetime actually emits some SQL statements! I don't like this choice by sqlalchemy, but there's not much we can do... I think this means you do not need the update statement at the end of this file. Please test it & get back to me if possible!

Copy link
Collaborator Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

OR, you can just remove the update at the end & say yolo

@DerpyWasHere
Copy link
Member

Alright, brief high level summary. This PR introduces the following:

  • CRUD functions for creating, getting, updating, and deleting elections.
  • SQLAlchemy tables for elections, nominees, and nominee applications (election paired with nominee)
  • Endpoints for creating, deleting, and updating elections.

This still needs to introduce/do the following:

  • Endpoint for getting/viewing an election's data (public and private).
  • Test user validation.

I'll work on these in my next PR.

As of this comment, all of the above comments should have been addressed.

src/elections/tables.py Outdated Show resolved Hide resolved
Copy link
Collaborator Author

@EarthenSky EarthenSky left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Oops, since I made this PR originally I can't request changes. However, consider this "request changes".

The biggest issue is the uniqueness of the slug, the rest are medium level.

Mostly the logic is good!

Comment on lines +66 to +70
raise HTTPException(
status_code=status.HTTP_401_UNAUTHORIZED,
detail="You do not have permission to access this resource",
headers={"WWW-Authenticate": "Basic"},
)
Copy link
Collaborator Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

raise HTTPException(status_code=401, detail="only website admins can view all executive terms that have not started yet")

you can simplify exceptions a little bit

aaa
"""
session_id = request.cookies.get("session_id", None)
user_auth = await _validate_user(db_session, session_id)
Copy link
Collaborator Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

async def logged_in_or_raise(

I made a function which may have the same behaviour as _validate_user; maybe you can reuse the code?

sa.Column("nominee_election", sa.String(length=32), nullable=False),
sa.Column("speech", sa.Text(), nullable=True),
sa.Column("position", sa.String(length=64), nullable=False),
sa.ForeignKeyConstraint(["computing_id"], ["election_nominee.computing_id"], ),
Copy link
Collaborator Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Why is there a comma and the end of the inside of the function call? Any idea?

Comment on lines 50 to 58
async def create_election(
request: Request,
db_session: database.DBSession,
name: str,
election_type: str,
date: datetime | None = None,
end_date: datetime | None = None,
survey_link: str | None = None
):
Copy link
Collaborator Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

end_date and date should be changed to end_datetime and start_datetime respectively

Does not validate if an election _already_ exists
"""

election = (await db_session.execute(sqlalchemy.select(Election).filter_by(slug=params.slug))).scalar_one()
Copy link
Collaborator Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

to be consistent, let's only use the SQL syntax

Suggested change
election = (await db_session.execute(sqlalchemy.select(Election).filter_by(slug=params.slug))).scalar_one()
election = await db_session.scalar(sqlalchemy.select(Election).where(Election.slug == params.slug))

raise RequestValidationError()

params = ElectionParameters(
_slugify(name),
Copy link
Collaborator Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

since slug is used as a unique identifier, what if we have a duplicate slug here ("My election" vs "my election", etc...)? We should have a check to make sure that slug does not currently exist, so we don't accidentally overwrite a past election.

detail="You do not have permission to access this resource",
headers={"WWW-Authenticate": "Basic"},
)
if slug is not None:
Copy link
Collaborator Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

slug is not allowed to be none here, since fastapi actually enforces input types (iirc) -> it's worth a simple test anyways as a santity check

import officers.urls
import permission.urls
import tests.urls
Copy link
Collaborator Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

oops! This is from the merge of main into this branch; please remove this (was something weird I was doing, give it no mind)

Suggested change
import tests.urls

"""
An current elections officer has access to all elections, prior elections officers have no access.
"""
officer_terms = await officers.crud.current_executive_team(db_session, True)
Copy link
Collaborator Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

current_executive_team has been replaced with current_officers. The behaviour shooooould be the same

An current elections officer has access to all elections, prior elections officers have no access.
"""
officer_terms = await officers.crud.current_executive_team(db_session, True)
current_election_officer = officer_terms.get(officers.constants.OfficerPosition.ElectionsOfficer.value)[0]
Copy link
Collaborator Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

what if there are multiple active elections officers? I can imagine this scenario. Instead of using the function current_officers, instead get the list of all active officer positions a user has & check if one of them is elections officer. This can be done more easily using get_officer_terms

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

Successfully merging this pull request may close these issues.

Elections Info
3 participants