User Management Feature

This document describes the user management feature implemented for administrators to manage users, their roles, and demographic information.

Overview

The user management feature provides administrators with the ability to:

  • View all registered users with search and filtering
  • Edit user roles (ADMIN, PREMIUM, FREE)
  • Manage user demographic information
  • Track user learning preferences and objectives

Architecture

Backend Components

1. Database Migration

File: backend/migrations/005_add_user_demographics.sql

Adds demographic fields to the users table:

Field Type Description
first_name VARCHAR(255) User’s first name
last_name VARCHAR(255) User’s last name
gender VARCHAR(50) Options: male, female, non-binary, prefer-not-to-say, other
age_group VARCHAR(50) Options: 18-24, 25-34, 35-44, 45-54, 55-64, 65+
location_country VARCHAR(100) User’s country
location_city VARCHAR(100) User’s city
timezone VARCHAR(100) User’s timezone
interests JSONB Array of interest strings
learning_objectives JSONB Array of learning goal strings
preferred_learning_style VARCHAR(50) Options: visual, reading, interactive, video
weekly_learning_hours INTEGER Target hours per week (1-40)
profile_completed BOOLEAN Whether profile is complete
onboarding_completed_at TIMESTAMP When onboarding was completed

Constraints:

  • Check constraints ensure valid enum values for gender, age_group, learning_style
  • Weekly learning hours limited to 1-40
  • Indexes added for common query patterns

2. Type Definitions

File: backend/shared/types/database.ts

export type Gender = 'male' | 'female' | 'non-binary' | 'prefer-not-to-say' | 'other';
export type AgeGroup = '18-24' | '25-34' | '35-44' | '45-54' | '55-64' | '65+';
export type LearningStyle = 'visual' | 'reading' | 'interactive' | 'video';

export interface User {
  id: string;
  cognito_sub: string;
  email: string;
  name: string;
  first_name?: string;
  last_name?: string;
  role: UserRole;
  avatar_url?: string;
  gender?: Gender;
  age_group?: AgeGroup;
  location_country?: string;
  location_city?: string;
  timezone?: string;
  interests?: string[];
  learning_objectives?: string[];
  preferred_learning_style?: LearningStyle;
  weekly_learning_hours?: number;
  profile_completed: boolean;
  onboarding_completed_at?: Date;
  created_at: Date;
  updated_at: Date;
}

export interface UpdateUserDTO {
  role?: UserRole;
  gender?: Gender;
  age_group?: AgeGroup;
  location_country?: string;
  location_city?: string;
  timezone?: string;
  interests?: string[];
  learning_objectives?: string[];
  preferred_learning_style?: LearningStyle;
  weekly_learning_hours?: number;
  profile_completed?: boolean;
}

export interface UserFilters {
  search?: string;
  role?: UserRole;
  profile_completed?: boolean;
}

3. UserRepository

File: backend/shared/repositories/UserRepository.ts

Repository methods:

Method Description
findAllWithFilters(limit, offset, filters) Get users with pagination and filters
findByCognitoSub(cognitoSub) Find user by Cognito sub ID
findByEmail(email) Find user by email address
search(searchTerm, limit, offset, filters) Search users by name or email
createUser(data) Create a new user
updateUser(id, data) Update user demographics and role
countByRole() Get user count grouped by role
getTotalCount(filters) Get total user count with filters
findByInterest(interest, limit, offset) Find users by interest (JSONB query)

4. Users Lambda Function

Files: backend/functions/users/

Endpoints:

Method Path Description
GET /users List users with search, filter, and pagination
PUT /users?id={userId} Update user role and demographics

Query Parameters (GET):

  • id - Get specific user by ID
  • search - Search by name or email
  • role - Filter by role (ADMIN, PREMIUM, FREE)
  • profile_completed - Filter by profile status
  • limit - Results per page (default: 20, max: 100)
  • offset - Pagination offset

Request Body (PUT):

{
  "role": "PREMIUM",
  "gender": "male",
  "age_group": "25-34",
  "location_country": "United States",
  "location_city": "New York",
  "timezone": "America/New_York",
  "interests": ["Technology", "Business"],
  "learning_objectives": ["Learn programming"],
  "preferred_learning_style": "video",
  "weekly_learning_hours": 5,
  "profile_completed": true
}

Authentication: Admin-only access via Cognito JWT validation

5. Input Validation

File: backend/shared/utils/validation.ts

The validateUpdateUserInput function validates:

  • Role must be ADMIN, PREMIUM, or FREE
  • Gender must be a valid option
  • Age group must be a valid range
  • Location country/city max 100 characters
  • Timezone max 100 characters
  • Interests array max 20 items, each max 100 characters
  • Learning objectives array max 20 items, each max 200 characters
  • Learning style must be a valid option
  • Weekly hours between 1-40
  • Profile completed must be boolean

6. Terraform Configuration

Files:

  • infrastructure/terraform/lambda.tf - Users Lambda function
  • infrastructure/terraform/api-gateway.tf - API Gateway /users endpoint

Frontend Components

1. Type Definitions

File: frontend/lib/api/types.ts

Mirrors backend types for TypeScript type safety.

2. API Client

File: frontend/lib/api/users.ts

// Get users with filters and pagination
getUsers(options: GetUsersOptions): Promise<UsersListResponse>

// Get single user by ID
getUser(id: string): Promise<User>

// Update user
updateUser(id: string, data: UpdateUserDTO): Promise<User>

// Search users
searchUsers(searchTerm: string, options?): Promise<UsersListResponse>

3. Admin Users List Page

File: frontend/app/admin/users/page.tsx

Features:

  • Search users by name or email
  • Filter by role (ADMIN, PREMIUM, FREE)
  • Pagination
  • User table with:
    • Avatar/initials
    • Name and email
    • Role badge
    • Profile completion status
    • Location
    • Join date
    • Edit action

4. Admin User Edit Page

File: frontend/app/admin/users/[id]/edit/page.tsx

Sections:

  • User Information: Read-only display of email, name, Cognito sub, dates
  • Role & Status: Role dropdown, profile completion checkbox
  • Demographics: Gender, age group dropdowns
  • Location: Country, city, timezone inputs
  • Learning Preferences:
    • Preferred learning style dropdown
    • Weekly learning hours input
    • Interests (comma-separated)
    • Learning objectives (comma-separated)

5. Admin Dashboard

File: frontend/app/admin/page.tsx

Updated to display user count in the Users card.

Testing

Test Files

  • backend/__tests__/repositories/UserRepository.test.ts - 52 tests
  • backend/shared/utils/__tests__/user-validation.test.ts - 77 tests

Running Tests

cd backend

# Run all user management tests
npx jest __tests__/repositories/UserRepository.test.ts shared/utils/__tests__/user-validation.test.ts

# Run with coverage
npx jest __tests__/repositories/UserRepository.test.ts shared/utils/__tests__/user-validation.test.ts --coverage

Test Coverage

  • UserRepository.ts: 100% statement coverage
  • Total Tests: 129 passing

Deployment

Prerequisites

  1. AWS credentials configured
  2. Terraform installed
  3. Node.js 20.x

Steps

  1. Build the Lambda function:
    cd backend/functions/users
    npm install
    npm run build
    
  2. Run the database migration:
    -- Execute against your PostgreSQL database
    \i backend/migrations/005_add_user_demographics.sql
    
  3. Deploy infrastructure:
    cd infrastructure/terraform
    terraform plan
    terraform apply
    
  4. Deploy frontend: Push to main branch to trigger Amplify deployment.

API Usage Examples

List Users

curl -X GET "https://api.example.com/dev/users?limit=20&offset=0" \
  -H "x-api-key: YOUR_API_KEY" \
  -H "Authorization: Bearer YOUR_JWT_TOKEN"

Search Users

curl -X GET "https://api.example.com/dev/users?search=john&role=FREE" \
  -H "x-api-key: YOUR_API_KEY" \
  -H "Authorization: Bearer YOUR_JWT_TOKEN"

Get Single User

curl -X GET "https://api.example.com/dev/users?id=USER_ID" \
  -H "x-api-key: YOUR_API_KEY" \
  -H "Authorization: Bearer YOUR_JWT_TOKEN"

Update User

curl -X PUT "https://api.example.com/dev/users?id=USER_ID" \
  -H "x-api-key: YOUR_API_KEY" \
  -H "Authorization: Bearer YOUR_JWT_TOKEN" \
  -H "Content-Type: application/json" \
  -d '{
    "role": "PREMIUM",
    "gender": "male",
    "age_group": "25-34"
  }'

Security Considerations

  1. Admin-only access: All endpoints require admin role verification
  2. Input validation: All inputs validated and sanitized
  3. SQL injection prevention: Parameterized queries and field whitelisting
  4. XSS prevention: String sanitization removes HTML tags
  5. Audit logging: Admin actions logged for auditing

Future Enhancements

  1. Add bulk user operations (import/export)
  2. Add user activity history view
  3. Add user statistics and analytics
  4. Add email notifications for role changes
  5. Add user profile image upload
  6. Add user notes/comments for admins

Back to top

Momentum LMS © 2025. Distributed under the MIT license.