Skip to content

Add event check-in configuration API - #208

Open
choidanny719 wants to merge 4 commits into
CSSS:devfrom
choidanny719:add-event-check-ins
Open

choidanny719 wants to merge 4 commits into
CSSS:devfrom
choidanny719:add-event-check-ins

Conversation

@choidanny719

Copy link
Copy Markdown

Implements #201 by allowing CSSS events to have multiple configurable check-in periods.

  • Add endpoints to create, list, retrieve, update, and delete check-in configurations.
  • Use existing exec permissions for reads and event permissions for changes.
  • Validate opening and closing times, preserve omitted fields during updates, and restrict configurations to their owning event.
  • Add an Alembic migration with an event foreign key, index, and time-range constraint.

Configuration IDs are included in responses, and creation/update timestamps are managed by the server.

Validated locally with 13 unit tests and 37 integration tests covering CRUD operations, validation, permissions, missing events, and access through incorrect event IDs. Ruff lint and formatting checks passed.

index=True,
)

name: Mapped[str] = mapped_column(String(64))

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

Use the constant defined for the model for the length of the name.

class EventCheckInCreate(BaseModel):
model_config = ConfigDict(extra="forbid")

name: str = Field(min_length=1, max_length=64, pattern=r"\S")

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

Define a constant for the max_length.

class EventCheckInUpdate(BaseModel):
model_config = ConfigDict(extra="forbid")

name: str | None = Field(default=None, min_length=1, max_length=64, pattern=r"\S")

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

Use the constant defined for the model for the length of the name.

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

Have the fields in the models be Field(...) and add descriptions so our documentation is better. See src/users/models.py for examples.

sa.Column("id", sa.BigInteger(), sa.Identity(always=True), nullable=False),
sa.Column("event_id", sa.Integer(), nullable=False),
sa.Column("name", sa.String(length=64), nullable=False),
sa.Column("enabled", sa.Boolean(), server_default=sa.text("false"), nullable=False),

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

Suggested change
sa.Column("enabled", sa.Boolean(), server_default=sa.text("false"), nullable=False),
sa.Column("enabled", sa.Boolean(), server_default=sa.false(), nullable=False),

This is to prevent our SQL statement scanner from flagging this as unsafe.

from event_check_in.tables import EventCheckInDB
from utils.shared_models import DetailModel

CheckInIdPath = Annotated[int, Path(ge=1, le=9223372036854775807)]

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

Make a constant for the le number, put it in src/constants.py.

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

Add explicit operation IDs to endpoints as we use those to generate functions in other applications. For example, GET /api/event/{eid}/check-in has an implicit operation ID of list_check_ins_api_event__eid__check_in_get, which is a bit too long. Operation ID could be get_check_ins

Comment on lines +78 to +79
event_id = await _get_event_id(db_session, eid)
check_in = await event_check_in.crud.get_check_in(db_session, event_id, check_in_id)

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

We can reduce the number of trips to the database by using a join. This would involve modifying crud.get_check_in to take in eid instead of event_id and joining with EventDB. We can keep the error ambiguous by just saying "Event or event check-in configuration is missing".

Comment on lines +117 to +118
event_id = await _get_event_id(db_session, eid)
check_in = await event_check_in.crud.get_check_in(db_session, event_id, check_in_id, for_update=True)

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

We can reduce the number of trips to the database by using a join. This would involve modifying crud.get_check_in to take in eid instead of event_id and joining with EventDB. We can keep the error ambiguous by just saying "Event or event check-in configuration is missing".

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

Add a few more tests:

  • Check that multiple check-ins for a single event operates normally. Create multiple check-ins, update and/or delete them and ensure the other is not affected.
  • Check that deletion cascades. Create an event, add one or more check-in configurations, and delete the event. The result should be all check-in configurations are gone.
  • POST with invalid time ranges should return 422.
  • PATCH with a name of "null" should return 422.
  • Ensure created_at is preserved and updated_at is modified when an entry is updated.

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.

2 participants