User Management & Access Control System - User Story
Story Overview​
Story ID: EMTB-002
Epic: Data Management & User System Enhancement
Story Name: User Management & Access Control System
Story Type: Brownfield Enhancement
Priority: High
Estimated Effort: 21 Story Points
User Story​
As a system administrator and business user
I want comprehensive user management with role-based access control and secure authentication workflows
So that I can manage user access, ensure data security, maintain client-user relationships, and provide appropriate permissions across all system functions while preserving existing user-client associations.
Acceptance Criteria​
AC1: Enhanced User CRUD Operations with Role-Based Permissions​
Given the existing User model with basic fields (email, nom, prenom, role, password, clientId)
When I perform user management operations
Then the system must:
- Support comprehensive CRUD operations with role-based authorization
- Implement user creation with automatic reference generation and validation
- Provide user profile management with secure password handling
- Support role assignment and modification with proper authorization checks
- Maintain audit trails for all user management operations
- Preserve existing Client-User relationships and associations
AC2: User Authentication Workflows and Session Management​
Given users with different roles and access requirements
When they authenticate and use the system
Then the system must:
- Implement secure JWT-based authentication with refresh token support
- Support multi-factor authentication for administrative users
- Provide session management with configurable timeout policies
- Implement password strength validation and expiration policies
- Support account lockout mechanisms after failed login attempts
- Maintain authentication audit logs with security event tracking
AC3: Client-User Relationship Management with Access Restrictions​
Given the existing Client-User relationship structure
When managing user access to client data
Then the system must:
- Enforce client-specific data access based on user-client associations
- Support multiple users per client with different permission levels
- Implement hierarchical access control (admin > manager > user)
- Provide client-scoped data visibility and modification permissions
- Support temporary access delegation and time-limited permissions
- Maintain referential integrity for all client-user relationships
AC4: Role-Based System Integration and Access Control​
Given the comprehensive system entities (Sites, Reclamations, Factures, ApporteurAffaire, etc.)
When users access different system functions
Then the system must:
- Implement granular permissions for all entity operations (read, write, delete)
- Support role-based access to financial data (Factures, FacturePartenaire)
- Provide appropriate access controls for site management and reclamation workflows
- Implement data export permissions with audit logging
- Support bulk operation permissions with proper authorization
- Ensure secure access to document management and file operations
AC5: User Profile Management and Account Security​
Given users requiring profile management and security features
When they manage their accounts and security settings
Then the system must:
- Provide comprehensive user profile management with data validation
- Support secure password change workflows with current password verification
- Implement account recovery mechanisms with multi-step verification
- Support user preference management and system configuration
- Provide personal audit trail access for user activities
- Support account deactivation and reactivation workflows
AC6: Administrative User Management Tools​
Given system administrators requiring user management capabilities
When they perform administrative user operations
Then the system must:
- Provide comprehensive user search and filtering capabilities
- Support bulk user operations (creation, role updates, deactivation)
- Implement user activity monitoring and reporting
- Support user impersonation for troubleshooting (with audit trails)
- Provide role management and permission assignment interfaces
- Support user data export and backup operations
AC7: Integration with Existing System Components​
Given the established system architecture with ImportService, ClientService, etc.
When integrating user management across all components
Then the system must:
- Maintain backward compatibility with existing service patterns
- Integrate authentication checks into all existing controllers
- Support user context in import operations and audit trails
- Preserve existing Client service functionality with added user authorization
- Integrate user permissions into file upload and document management
- Support user-scoped data operations across all entities
Technical Requirements​
Enhanced User Service Architecture​
interface UserManagementService {
// CRUD Operations with Authorization
createUser(createUserDto: CreateUserDto, currentUser: AuthUser): Promise<User>;
updateUser(id: number, updateUserDto: UpdateUserDto, currentUser: AuthUser): Promise<User>;
deleteUser(id: number, currentUser: AuthUser): Promise<void>;
findUsersByClient(clientId: number, currentUser: AuthUser): Promise<User[]>;
// Role and Permission Management
assignRole(userId: number, role: UserRole, currentUser: AuthUser): Promise<User>;
updatePermissions(userId: number, permissions: Permission[], currentUser: AuthUser): Promise<User>;
validateUserAccess(userId: number, resource: string, action: string): Promise<boolean>;
// Account Security
changePassword(userId: number, passwordChangeDto: PasswordChangeDto): Promise<void>;
enableMFA(userId: number, mfaConfig: MFAConfiguration): Promise<MFASetupResult>;
lockAccount(userId: number, reason: string, currentUser: AuthUser): Promise<void>;
}
interface AuthenticationService {
// Authentication Workflows
authenticate(loginDto: LoginDto): Promise<AuthenticationResult>;
refreshToken(refreshToken: string): Promise<TokenResult>;
logout(userId: number, sessionId: string): Promise<void>;
// Session Management
validateSession(sessionToken: string): Promise<SessionValidationResult>;
getUserSessions(userId: number): Promise<UserSession[]>;
terminateSession(sessionId: string, currentUser: AuthUser): Promise<void>;
// Security Features
validateMFA(userId: number, mfaToken: string): Promise<boolean>;
recordSecurityEvent(event: SecurityEvent): Promise<void>;
checkAccountLockout(email: string): Promise<AccountLockoutStatus>;
}
User Model Enhancement​
interface ExtendedUser {
id: number;
email: string;
nom: string;
prenom: string;
role: UserRole;
password: string; // Hashed
clientId?: number;
client?: Client;
// Enhanced Security Fields
lastLogin?: Date;
failedLoginAttempts: number;
accountLockedUntil?: Date;
passwordChangedAt: Date;
mfaEnabled: boolean;
mfaSecret?: string;
// Permission and Access Control
permissions: Permission[];
isActive: boolean;
mustChangePassword: boolean;
sessionTimeout: number;
// Audit Fields
createdAt: Date;
updatedAt: Date;
createdBy?: number;
lastModifiedBy?: number;
}
enum UserRole {
SUPER_ADMIN = 'SUPER_ADMIN',
ADMIN = 'ADMIN',
MANAGER = 'MANAGER',
USER = 'USER',
CLIENT_USER = 'CLIENT_USER',
READONLY = 'READONLY'
}
interface Permission {
id: number;
resource: string; // 'client', 'site', 'reclamation', 'facture', etc.
action: string; // 'create', 'read', 'update', 'delete', 'export'
scope: 'all' | 'client' | 'own';
conditions?: Record<string, any>;
}
Authentication and Authorization Architecture​
interface AuthGuard {
canActivate(context: ExecutionContext): boolean | Promise<boolean>;
validatePermissions(user: AuthUser, resource: string, action: string): Promise<boolean>;
checkClientAccess(user: AuthUser, clientId: number): Promise<boolean>;
}
interface RoleBasedGuard extends AuthGuard {
requiredRoles: UserRole[];
allowClientUsers: boolean;
resourcePermissions: ResourcePermission[];
}
interface SessionManager {
createSession(user: User, loginContext: LoginContext): Promise<UserSession>;
validateSession(sessionToken: string): Promise<SessionValidationResult>;
refreshSession(sessionId: string): Promise<UserSession>;
terminateSession(sessionId: string): Promise<void>;
cleanupExpiredSessions(): Promise<number>;
}
Audit Trail Integration​
interface UserAuditLog {
id: string;
userId: number;
action: 'login' | 'logout' | 'create' | 'update' | 'delete' | 'access_denied' | 'password_change';
resource?: string;
resourceId?: string;
ipAddress: string;
userAgent: string;
timestamp: Date;
success: boolean;
details: Record<string, any>;
securityLevel: 'low' | 'medium' | 'high' | 'critical';
}
interface SecurityEventLogger {
logAuthentication(user: User, result: AuthenticationResult, context: LoginContext): Promise<void>;
logAuthorization(user: User, resource: string, action: string, granted: boolean): Promise<void>;
logSecurityViolation(violation: SecurityViolation): Promise<void>;
logDataAccess(user: User, entity: string, entityId: string, action: string): Promise<void>;
}
Test Automation Requirements​
Comprehensive User Management Test Coverage​
-
User CRUD Operations with Role-Based Permissions
describe('User CRUD Operations', () => {
test('Admin can create users with all roles', async () => {
const admin = createMockUser({ role: UserRole.ADMIN });
const newUser = await userService.createUser(createUserDto, admin);
expect(newUser).toHaveProperty('id');
expect(auditService.logs).toContain(expect.objectContaining({
action: 'create',
userId: admin.id
}));
});
test('Manager cannot create admin users', async () => {
const manager = createMockUser({ role: UserRole.MANAGER });
const createAdminDto = { ...createUserDto, role: UserRole.ADMIN };
await expect(userService.createUser(createAdminDto, manager))
.rejects.toThrow('Insufficient permissions');
});
test('Client users can only view their client data', async () => {
const clientUser = createMockUser({
role: UserRole.CLIENT_USER,
clientId: 1
});
const users = await userService.findUsersByClient(1, clientUser);
expect(users).toHaveLength(greaterThan(0));
await expect(userService.findUsersByClient(2, clientUser))
.rejects.toThrow('Access denied');
});
}); -
Authentication Workflows and Security Tests
describe('Authentication Security', () => {
test('Password strength validation enforced', async () => {
const weakPassword = 'weak';
const strongPassword = 'StrongP@ssw0rd123';
await expect(authService.authenticate({
email: 'user@test.com',
password: weakPassword
})).rejects.toThrow('Password does not meet requirements');
const result = await authService.authenticate({
email: 'user@test.com',
password: strongPassword
});
expect(result).toHaveProperty('accessToken');
});
test('Account lockout after failed attempts', async () => {
const email = 'user@test.com';
// Simulate 5 failed login attempts
for (let i = 0; i < 5; i++) {
await expect(authService.authenticate({
email,
password: 'wrongpassword'
})).rejects.toThrow();
}
const lockoutStatus = await authService.checkAccountLockout(email);
expect(lockoutStatus.isLocked).toBe(true);
expect(lockoutStatus.lockedUntil).toBeDefined();
});
test('MFA validation workflow', async () => {
const user = createMockUser({ mfaEnabled: true });
const authResult = await authService.authenticate({
email: user.email,
password: 'correct_password'
});
expect(authResult.requiresMFA).toBe(true);
expect(authResult.accessToken).toBeUndefined();
const mfaResult = await authService.validateMFA(
user.id,
generateValidMFAToken(user.mfaSecret)
);
expect(mfaResult).toBe(true);
});
}); -
Role-Based Access Control Integration Tests
describe('RBAC Integration', () => {
test('Client data access restrictions', async () => {
const clientUser = createMockUser({
role: UserRole.CLIENT_USER,
clientId: 1
});
// Can access own client's sites
const ownSites = await siteService.findByClient(1, clientUser);
expect(ownSites).toHaveLength(greaterThan(0));
// Cannot access other client's sites
await expect(siteService.findByClient(2, clientUser))
.rejects.toThrow('Access denied');
// Cannot access administrative functions
await expect(userService.findAll(clientUser))
.rejects.toThrow('Insufficient permissions');
});
test('Financial data access control', async () => {
const readOnlyUser = createMockUser({ role: UserRole.READONLY });
const managerUser = createMockUser({ role: UserRole.MANAGER });
// Read-only user can view but not modify
const factures = await factureService.findAll(readOnlyUser);
expect(factures).toBeDefined();
await expect(factureService.create(createFactureDto, readOnlyUser))
.rejects.toThrow('Insufficient permissions');
// Manager can create and modify
const newFacture = await factureService.create(createFactureDto, managerUser);
expect(newFacture).toHaveProperty('id');
});
test('Import operations with user context', async () => {
const adminUser = createMockUser({ role: UserRole.ADMIN });
const clientUser = createMockUser({
role: UserRole.CLIENT_USER,
clientId: 1
});
// Admin can import for any client
await expect(importService.importClients(importData, adminUser))
.resolves.toBeDefined();
// Client user cannot perform import operations
await expect(importService.importClients(importData, clientUser))
.rejects.toThrow('Insufficient permissions');
// Verify audit trails include user context
const auditLogs = await auditService.getImportLogs();
expect(auditLogs[0]).toHaveProperty('userId', adminUser.id);
});
}); -
Session Management and Security Tests
describe('Session Management', () => {
test('Session timeout enforcement', async () => {
const user = createMockUser({ sessionTimeout: 1800 }); // 30 minutes
const session = await sessionManager.createSession(user, loginContext);
// Fast-forward time beyond timeout
jest.advanceTimersByTime(1801 * 1000); // 30 minutes + 1 second
const validation = await sessionManager.validateSession(session.token);
expect(validation.isValid).toBe(false);
expect(validation.reason).toBe('session_expired');
});
test('Concurrent session limits', async () => {
const user = createMockUser({ maxConcurrentSessions: 2 });
// Create maximum allowed sessions
const session1 = await sessionManager.createSession(user, loginContext1);
const session2 = await sessionManager.createSession(user, loginContext2);
expect(session1.isValid).toBe(true);
expect(session2.isValid).toBe(true);
// Third session should invalidate oldest
const session3 = await sessionManager.createSession(user, loginContext3);
const validation1 = await sessionManager.validateSession(session1.token);
expect(validation1.isValid).toBe(false);
expect(validation1.reason).toBe('session_limit_exceeded');
});
test('Token refresh workflow', async () => {
const user = createMockUser();
const authResult = await authService.authenticate(loginDto);
expect(authResult).toHaveProperty('accessToken');
expect(authResult).toHaveProperty('refreshToken');
// Use refresh token to get new access token
const refreshResult = await authService.refreshToken(authResult.refreshToken);
expect(refreshResult).toHaveProperty('accessToken');
expect(refreshResult.accessToken).not.toBe(authResult.accessToken);
});
}); -
Integration with Existing System Components
describe('System Integration', () => {
test('Backward compatibility with existing services', async () => {
// Ensure existing client service methods work unchanged
const clients = await clientService.findAll();
expect(clients).toBeDefined();
expect(Array.isArray(clients)).toBe(true);
// New authorization should not break existing functionality
const admin = createMockUser({ role: UserRole.ADMIN });
const clientsWithAuth = await clientService.findAll(admin);
expect(clientsWithAuth).toEqual(clients);
});
test('User context preservation in all operations', async () => {
const user = createMockUser({ role: UserRole.MANAGER, clientId: 1 });
const client = await clientService.findOne(1, user);
const site = await siteService.create(createSiteDto, user);
const reclamation = await reclamationService.create(createReclamationDto, user);
// Verify all operations are audited with user context
const auditLogs = await auditService.getUserAuditLog(user.id);
expect(auditLogs).toHaveLength(3);
expect(auditLogs.every(log => log.userId === user.id)).toBe(true);
});
test('File operations with user authorization', async () => {
const clientUser = createMockUser({
role: UserRole.CLIENT_USER,
clientId: 1
});
// Can upload files for own client
const uploadResult = await fileService.uploadDocument(
'convention.pdf',
documentBuffer,
{ clientId: 1 },
clientUser
);
expect(uploadResult).toHaveProperty('path');
// Cannot upload files for other clients
await expect(fileService.uploadDocument(
'mandat.pdf',
documentBuffer,
{ clientId: 2 },
clientUser
)).rejects.toThrow('Access denied');
});
});
Performance and Security Tests​
describe('Performance and Security', () => {
test('Authentication performance under load', async () => {
const concurrentLogins = 100;
const startTime = Date.now();
const promises = Array.from({ length: concurrentLogins }, (_, i) =>
authService.authenticate({
email: `user${i}@test.com`,
password: 'ValidP@ssw0rd123'
})
);
const results = await Promise.allSettled(promises);
const endTime = Date.now();
expect(endTime - startTime).toBeLessThan(5000); // 5 seconds max
expect(results.filter(r => r.status === 'fulfilled')).toHaveLength(concurrentLogins);
});
test('SQL injection prevention in user queries', async () => {
const maliciousEmail = "admin@test.com'; DROP TABLE users; --";
await expect(authService.authenticate({
email: maliciousEmail,
password: 'password'
})).rejects.toThrow('Invalid email format');
// Verify users table still exists
const users = await userService.findAll(createMockAdmin());
expect(users).toBeDefined();
});
test('Password hash security validation', async () => {
const password = 'SecureP@ssw0rd123';
const user = await userService.create({
email: 'test@example.com',
password,
nom: 'Test',
prenom: 'User'
}, createMockAdmin());
// Password should be hashed, not stored in plain text
expect(user.password).not.toBe(password);
expect(user.password).toMatch(/^\$2[aby]\$\d+\$/); // bcrypt pattern
// Verify password validation works
const authResult = await authService.authenticate({
email: user.email,
password
});
expect(authResult).toHaveProperty('accessToken');
});
});
Definition of Done​
Functional Requirements​
- Enhanced User CRUD operations with comprehensive role-based authorization
- JWT-based authentication with refresh token support and session management
- Multi-factor authentication for administrative users operational
- Client-User relationship management with proper access restrictions
- Role-based access control integrated across all system entities
- User profile management and account security features functional
- Administrative user management tools with search, filtering, and bulk operations
- Integration with existing ImportService and audit trail systems
Quality Requirements​
- 98%+ test coverage for all user management and authentication logic
- All existing service functionality preserved without breaking changes
- Security audit completed for authentication and authorization implementation
- Performance benchmarks met for authentication under concurrent load
- Password security and encryption standards validated
- Session management security and timeout policies verified
- Comprehensive audit trail coverage for all user operations
Integration Requirements​
- Backward compatibility verified with all existing controllers and services
- User context properly integrated into ImportService operations
- Client-User relationships maintained with enhanced access control
- File upload and document management integrated with user permissions
- All entity services updated with role-based authorization
- Database migrations completed for user model enhancements
- API endpoints secured with appropriate authentication and authorization
Security Requirements​
- Authentication security measures validated (password strength, MFA, lockout)
- Authorization system tested against privilege escalation attempts
- Session security implemented with appropriate timeout and management
- Audit trails comprehensive and tamper-resistant
- Data access controls verified for client data segregation
- Security event logging operational with appropriate alerting
- Input validation and SQL injection prevention verified
Risk Mitigation​
Primary Risks and Mitigations​
-
Risk: Breaking existing user-client relationships during enhancement
- Mitigation: All database changes are additive, existing relationships preserved
- Testing: Comprehensive migration testing with existing data validation
-
Risk: Performance impact from authentication and authorization overhead
- Mitigation: Efficient JWT token validation and role caching mechanisms
- Monitoring: Real-time performance metrics for authentication endpoints
-
Risk: Security vulnerabilities in authentication implementation
- Mitigation: Industry-standard security practices, comprehensive security audit
- Testing: Penetration testing and security vulnerability assessments
-
Risk: User experience degradation from complex authorization
- Mitigation: Intuitive role-based permissions with clear error messages
- Validation: User acceptance testing with different role scenarios
-
Risk: Data access control bypass or privilege escalation
- Mitigation: Multi-layered authorization checks at service and controller levels
- Testing: Extensive RBAC testing with attack scenario simulations
Dependencies and Assumptions​
Technical Dependencies​
- Existing User model and Client relationships must remain functional
- JWT library integration for secure token management
- bcrypt or similar for password hashing and validation
- Database support for new user security and audit fields
- Integration with existing Prisma service patterns
Business Assumptions​
- Role hierarchy and permissions align with business requirements
- Client data segregation requirements are clearly defined
- Administrative access patterns support operational needs
- Password and security policies meet compliance requirements
- Audit retention and security logging meet regulatory needs
Integration Assumptions​
- All existing services can be enhanced with user context without breaking changes
- ImportService integration maintains existing functionality
- File upload and document management systems support user-based authorization
- Client-User relationship patterns remain consistent
- Audit trail integration aligns with existing logging infrastructure
Success Metrics​
Security Metrics​
- Authentication Success Rate: > 99.9% for valid credentials
- Security Incidents: Zero privilege escalation or unauthorized access incidents
- Session Security: 100% session validation accuracy
- Audit Coverage: 100% audit trail coverage for user operations
Performance Metrics​
- Authentication Latency: < 200ms average response time
- Authorization Check Latency: < 50ms for permission validation
- Concurrent User Support: Support for 500+ concurrent authenticated users
- Token Refresh Performance: < 100ms for token refresh operations
Business Metrics​
- User Adoption: > 95% successful user onboarding
- Role Assignment Accuracy: 100% correct role and permission assignments
- Client Data Segregation: Zero cross-client data access violations
- Administrative Efficiency: 80% reduction in user management time
Integration Metrics​
- Backward Compatibility: 100% existing functionality preserved
- Service Integration: All services successfully enhanced with user context
- Import Operation Security: 100% import operations include user audit trails
- File Operation Security: All file operations properly authorized
Implementation Notes​
Development Approach​
This enhancement follows a brownfield development pattern, significantly expanding the basic User model and empty UserModule into a comprehensive user management and access control system. The implementation preserves all existing Client-User relationships while adding robust authentication, authorization, and audit capabilities that integrate seamlessly with all system components.
Backward Compatibility Strategy​
All existing User model fields and Client relationships are preserved. The UserModule will be enhanced from its current empty state to include comprehensive service, controller, and authentication components. New security features are implemented as enhancements that work alongside existing patterns, ensuring zero disruption to current Client-User associations while providing significant security and management improvements.
Architecture Integration Considerations​
The user management system integrates deeply with the existing NestJS service architecture, following established patterns from ClientService and other entity services. Authentication and authorization are designed as cross-cutting concerns that enhance all existing controllers and services while maintaining their current interfaces and functionality. The role-based access control system leverages the existing Client relationships to provide appropriate data segregation and permissions.
Security Architecture Notes​
The implementation follows industry security best practices with JWT-based authentication, bcrypt password hashing, role-based authorization, and comprehensive audit logging. Multi-factor authentication is implemented for administrative users, and session management includes appropriate timeout and security policies. All user operations are logged for compliance and security monitoring, with audit trails integrated into the existing system logging infrastructure.