-
Notifications
You must be signed in to change notification settings - Fork 1
Description
Feature: Implement Lunch Groups & User Check-In
Summary
Implement the backend logic, storage, and API endpoints to manage "Lunch Groups" for hackers. This feature allows super_admins to manage group assignments. Additionally, update the user schema to support a check-in status and a group identifier.
For the initial implementation, group assignment should be random. Only super_admins should have control over creating/assigning these groups.
What to build
DB Migrations
Create a new migration file inside cmd/migrate/migrations/ to alter the users table and seed default settings.
Requirements:
Alter users table:
- Add column check_in: BOOLEAN, default FALSE. Used to determine if a user has checked into the event.
- Add column group: TEXT (or VARCHAR), nullable. Used to store the group identifier for the user.
- Keep the DB simple, enforce as a pseudo FK in the application
Update settings table:
- Add a new setting (e.g., check_in_groups) to store the list of available group names.
- This should be stored as a JSON array of strings.
- The default value should be ["A", "B", "C", "D"].
- These values must be editable via the API to allow for custom text names.
Store Layer
Groups Store Create internal/store/groups.go.
Concept: A store that handles the CRUD logic for group definitions (stored as a JSON list in settings) and the assignment of users to those groups.
Interface Methods:
List(ctx context.Context) ([]string, error): Retrieve the list of available group names.GetByUserID(ctx context.Context, userID string) error: Get a user's current group.Create(ctx context.Context, group string) error: Add a new group name to the list.Delete(ctx context.Context, group string) error: Remove a group name. Constraint: This must cascade to the users table (set the group column to NULL for users currently in the deleted group).Update(ctx context.Context, oldName, newName string) error: Rename a group. Constraint: This must cascade to the users table (update the group column for users currently in the old group).AssignUser(ctx context.Context, userID string, group string) error: Assign a specific user to a group.AssignRandom(ctx context.Context)error: Randomly assign unassigned users to the available groups.
Scans Store Update internal/store/scans.go
Check-In Logic:
Add SetCheckIn(ctx context.Context, userID string, checkedIn bool) error: Update the check_in status column for a specific user.
Infrastructure
Storage: Update internal/store/storage.go to include the new Groups interface and update the Scans interface.
Mocks: Update internal/store/mock_store.go to include mocks for all new methods in Groups and Scans.
API Handlers
Create cmd/api/groups.go.
Authorization: All new endpoints must be restricted to super admins using RequireRoleMiddleware(store.RoleSuperAdmin).
Handlers:
Group Definition Management:
listGroupsHandler: Retrieves the list of all available group names.createGroupHandler: Adds a new group name to the settings.updateGroupHandler: Renames an existing group, cascading the change to all assigned users.deleteGroupHandler: Deletes a group name from settings and un-assigns all users from it (sets their group to NULL).
User Assignment & Status:
assignRandomGroupsHandler: Triggers the random assignment of unassigned users to the available groups.assignUserGroupHandler: Assigns a single, specific user to a group.setCheckInHandler: Updates the check_in status for a specific user.
Viewing Assignments:
getGroupAssignmentsHandler: Retrieves all users, organized by their assigned group. The response should also include a list of any unassigned users.getByUserIDHandler: Get a user's current group.
Swagger Documentation: Ensure comprehensive Swagger documentation comments are included for all new handlers, detailing payloads, responses, and authorization requirements.
Wire Routes
Update cmd/api/api.go.
Requirements: Register the new routes under the /v1/superadmin group.
Proposed Structure:
Create a new route group for managing group definitions under /superadmin/groups:
GET /: listGroupsHandler
POST /: createGroupHandler
PUT /{oldName}: updateGroupHandler
DELETE /{groupName}: deleteGroupHandler
Create a new route group for managing assignments under /superadmin/group-assignments:
GET /: getGroupAssignmentsHandler
POST /random: assignRandomGroupsHandler
Add routes for individual user actions under the existing /superadmin/users/{userID} path:
PUT /group: assignUserGroupHandler
PUT /check-in: setCheckInHandler
Create a new route group for managing assignments under /group (hacker routes):
GET /: getByUserIDHandler
Testing
Create cmd/api/groups_test.go.
Test Cases:
Authorization:
❌ Fail if hacker or admin tries to access endpoints.
✅ Success if super_admin accesses endpoints.
Assignment:
✅ Successfully assigns groups to users (check DB state after request).
Check-In:
✅ Successfully toggles check-in status.
Group Definition
✅ Create group → appears in settings list
❌ Create duplicate group → should fail
❌ Create invalid group (empty string, too long, etc.)
Rename
✅ Rename group updates settings list
✅ All users in old group are updated to new group
❌ Rename to existing group name → should fail
Delete
✅ Delete group removes it from settings
✅ Users in that group get group = NULL
❌ Delete non-existent group → should fail
Constraint Behavior (important because you're using CHECK, not FK)
❌ Assign user to invalid group → should fail
✅ Assign user to valid group → succeeds
Random Assignment
✅ Only unassigned users are assigned
✅ Distribution is roughly even (optional but nice)
❌ No groups exist → should fail safely
Notes
The group column in the DB should be flexible enough to hold strings later, even if we start with single letters.
Cannot assign user to group if they are not checked in
Reuse existing patterns for error handling and JSON responses found in applications.go.
Once merged Hackathon Reset needs to clear groups in the settings table