Identity & Members

Users Service

The Users service manages user accounts in the biztechUsers DynamoDB table. Handlers are in services/users/handler.js.


Endpoints

MethodPathAuthHandlerDescription
POST/usersPubliccreateCreate a user
GET/users/check/{email}PubliccheckUserCheck whether a user record exists
GET/users/checkMembership/{email}PubliccheckUserMembershipCheck isMember flag
GET/users/{email}CognitogetGet user record (see self pattern)
GET/usersCognitogetAllList all users (no handler-level admin check)
PATCH/users/{email}CognitoupdateUpdate a user
PATCH/users/favEvent/{email}CognitofavouriteEventToggle a favorite event
DELETE/users/{email}CognitodelDelete a user

GET /users/{email} Self vs. Admin Lookup

This endpoint has a special behavior: non-admin callers always get their own record, regardless of the {email} path param.

The handler reads the caller's email from the Cognito JWT claims:

let email = event.requestContext.authorizer.claims.email.toLowerCase()
// Only admins can override the email from path params:
if (
  email.endsWith('@ubcbiztech.com') &&
  isValidEmail(event.pathParameters.email)
) {
  email = event.pathParameters.email
}

This is why the frontend and middleware call GET /users/self. The string "self" is not a real path segment — it's a placeholder that gets ignored. The handler resolves identity from the Cognito token, so any value in {email} works for non-admins. Admins can pass a real email to fetch any user.


User Record Shape

FieldTypeDescription
idStringEmail address (primary key)
fnameStringFirst name
lnameStringLast name
emailStringEmail (redundant with id)
educationStringEducation status
studentIdNumberUBC student number
facultyStringFaculty
majorStringMajor/program
yearNumberYear of study
genderStringPronouns/gender
dietStringDietary restrictions
isMemberBooleantrue after membership payment or admin grant
adminBooleanAuto-set for @ubcbiztech.com emails. Immutable via API.
favedEventsID;yearStringSetFavorite event IDs in "eventId;year" format
createdAtNumberUnix timestamp (ms)
updatedAtNumberUnix timestamp (ms)

Immutable Fields

The admin field cannot be changed via PATCH /users/{email}. The handler checks for immutable props and throws an error (not a silent strip) if any are included in the update bodyhrows an error** (not a silent strip) if any are included in the update bodyhrows an error** (not a silent strip) if any are included in the update body. See constants/tables.jsIMMUTABLE_USER_PROPS.


POST /users Create User

Auth: Public (no Cognito required)

Creates a user record. The email is validated and lowercased.

  • If the email ends with @ubcbiztech.com, admin is set to true automatically
  • Returns 409 if a user with this email already exists (enforced by DynamoDB ConditionExpression: attribute_not_exists(id))
  • Returns 201 with the created user params on success
  • Optional favedEventsArray (array of strings, validated for uniqueness, stored as DynamoDB StringSet)

GET /users/check/{email}

Auth: Public

Returns true (200) if a user record exists, false (200) if not. Used before registration to check whether an account needs to be created.


GET /users/checkMembership/{email}

Auth: Public

Returns the value of isMember if the user exists, false if the user does not exist. Used by the membership signup flow to skip the payment step for existing members.


PATCH /users/{email} Update User

Auth: Cognito

Updates user fields. The handler validates the user exists first. If the request body contains any field in IMMUTABLE_USER_PROPS (currently ["admin"]), the handler throws an error — it does not silently strip the fieldshe fieldshe fields.


PATCH /users/favEvent/{email} Toggle Favorite Event

Auth: Cognito

Toggles a favorite event on or off.

Request body:

FieldTypeRequiredDescription
eventIDStringYesEvent ID
yearNumberYesEvent year
isFavouriteBooleanYestrue to add, false to remove

The handler validates that the event exists in biztechEvents and the user exists in biztechUsers. It uses DynamoDB ADD/DELETE operations on the favedEventsID;year StringSet.


DELETE /users/{email}

Auth: Cognito

Deletes the user record from biztechUsers. Validates the user exists first.


IAM Permissions

The users service has IAM access to:

  • biztechUsers* — Scan, GetItem, PutItem, UpdateItem, DeleteItem
  • biztechEvents* — GetItem (for favourite event validation)
  • inviteCodes* — GetItem (legacy invite code system)

Previous
User, Member & Profile Relationships