Skip to content

Query to grab applicant emails by status #6

@balebbae

Description

@balebbae

Summary

Implement a super admin endpoint that returns applicant emails filtered by decision status (accepted, rejected, waitlisted). This supports bulk email sending workflows — e.g., sending acceptance/rejection notifications.

Endpoint

GET /v1/superadmin/applications/emails?status=accepted

Auth: Requires super_admin role (behind RequireRoleMiddleware(store.RoleSuperAdmin))

Query Parameters

Param Type Required Description
status string Yes One of: accepted, rejected, waitlisted

Validation

  • status is required
  • Must be one of the three decision statuses (accepted, rejected, waitlisted) — draft and submitted are not valid filters for this endpoint

Response

200 OK

{
  "data": {
    "emails": ["alice@utdallas.edu", "bob@utdallas.edu"],
    "count": 2
  }
}
  • emails — flat array of email strings for all applicants matching the status
  • count — total number of emails returned

400 Bad Request — missing or invalid status parameter
403 Forbidden — caller is not a super admin

Implementation Details

Files to modify/create

File Change
internal/store/storage.go Add GetEmailsByStatus(ctx context.Context, status ApplicationStatus) ([]string, error) to the Application interface
internal/store/applications.go Implement GetEmailsByStatus (see query below)
cmd/api/applications.go Add getApplicantEmailsByStatusHandler handler
cmd/api/api.go Register r.Get("/applications/emails", app.getApplicantEmailsByStatusHandler) under the super admin route group

Store query

SELECT u.email
FROM applications a
INNER JOIN users u ON a.user_id = u.id
WHERE a.status = $1
ORDER BY u.email
  • The idx_applications_status index already exists on applications(status), so filtering is fast
  • users.email is CITEXT (case-insensitive), ordering by email gives a consistent, predictable result
  • No pagination needed — response is a lightweight flat array of strings. Even 1,000+ emails is a small payload

Handler logic

  1. Read status query parameter
  2. Validate it is one of: accepted, rejected, waitlisted
  3. Call store.Application.GetEmailsByStatus(ctx, status)
  4. Return { "emails": [...], "count": N }

Route registration

r.Route("/superadmin", func(r chi.Router) {
    // ... existing routes ...
    r.Get("/applications/emails", app.getApplicantEmailsByStatusHandler)
})

Acceptance Criteria

  • GetEmailsByStatus added to Application store interface and implemented
  • GET /v1/superadmin/applications/emails?status= handler created
  • Validates status is one of accepted/rejected/waitlisted
  • Returns flat email array with count
  • Only accessible to super admins

Metadata

Metadata

Assignees

Labels

Type

No type

Projects

No projects

Milestone

No milestone

Relationships

None yet

Development

No branches or pull requests

Issue actions