- JWT authentication with Supabase integration - Role-based access control (Admin, Owner, Staff, Auditor) - Universal database adapter (Prisma/Supabase/MongoDB support) - User management with hierarchical permissions - Redis caching service (configured but optional) - Comprehensive API documentation - Production-ready NestJS architecture - Migration scripts for provider switching - Swagger/OpenAPI documentation
130 lines
3.3 KiB
Markdown
130 lines
3.3 KiB
Markdown
# Adding a MANAGER Role - Complete Example
|
|
|
|
## 1. Update Types
|
|
```typescript
|
|
// src/shared/types/index.ts
|
|
export enum UserRole {
|
|
SYSTEM_ADMIN = 'SYSTEM_ADMIN',
|
|
BUSINESS_OWNER = 'BUSINESS_OWNER',
|
|
MANAGER = 'MANAGER', // ← NEW
|
|
STAFF = 'STAFF',
|
|
AUDITOR = 'AUDITOR',
|
|
}
|
|
```
|
|
|
|
## 2. Update Role Constants
|
|
```typescript
|
|
// src/shared/constants/roles.ts
|
|
export const ROLE_HIERARCHY = {
|
|
[UserRole.SYSTEM_ADMIN]: 4,
|
|
[UserRole.BUSINESS_OWNER]: 3,
|
|
[UserRole.MANAGER]: 2.5, // ← NEW (between business owner and staff)
|
|
[UserRole.STAFF]: 2,
|
|
[UserRole.AUDITOR]: 1,
|
|
};
|
|
|
|
export const ROLE_PERMISSIONS = {
|
|
// ... existing roles
|
|
[UserRole.MANAGER]: [
|
|
'manage_team_receipts',
|
|
'view_team_reports',
|
|
'verify_receipts',
|
|
'manage_staff_schedules', // ← NEW PERMISSIONS
|
|
],
|
|
};
|
|
```
|
|
|
|
## 3. Update Database Schema
|
|
```prisma
|
|
// prisma/schema.prisma
|
|
enum UserRole {
|
|
SYSTEM_ADMIN
|
|
BUSINESS_OWNER
|
|
MANAGER // ← ADD
|
|
STAFF
|
|
AUDITOR
|
|
}
|
|
```
|
|
|
|
## 4. Add Manager-Specific Endpoints
|
|
```typescript
|
|
// src/features/users/users.controller.ts
|
|
@Get('my-team')
|
|
@Roles(UserRole.MANAGER, UserRole.BUSINESS_OWNER, UserRole.SYSTEM_ADMIN)
|
|
@ApiOperation({ summary: 'Get team members (Manager access)' })
|
|
async getMyTeam(@CurrentUser() user: any) {
|
|
return this.usersService.getTeamByManager(user.id);
|
|
}
|
|
|
|
@Post('assign-staff')
|
|
@Roles(UserRole.MANAGER, UserRole.BUSINESS_OWNER)
|
|
@ApiOperation({ summary: 'Assign staff to manager' })
|
|
async assignStaff(@Body() assignDto: AssignStaffDto) {
|
|
return this.usersService.assignStaffToManager(assignDto);
|
|
}
|
|
```
|
|
|
|
## 5. Update Service Logic
|
|
```typescript
|
|
// src/features/users/users.service.ts
|
|
async getUsers(currentUserId: string, currentUserRole: UserRole) {
|
|
// ... existing logic
|
|
|
|
if (currentUserRole === UserRole.MANAGER) {
|
|
// Managers see their assigned team
|
|
const teamMembers = await this.supabaseDb.getUsersByManager(currentUserId);
|
|
const currentUser = await this.supabaseDb.findUserById(currentUserId);
|
|
return currentUser ? [currentUser, ...teamMembers] : teamMembers;
|
|
}
|
|
|
|
// ... rest of logic
|
|
}
|
|
|
|
async getTeamByManager(managerId: string): Promise<User[]> {
|
|
return this.supabaseDb.findUsers({
|
|
manager_id: managerId,
|
|
is_active: true
|
|
});
|
|
}
|
|
```
|
|
|
|
## 6. Database Migration
|
|
```sql
|
|
-- Add new role to enum
|
|
ALTER TYPE "UserRole" ADD VALUE 'MANAGER';
|
|
|
|
-- Add manager_id column to users table (optional)
|
|
ALTER TABLE users ADD COLUMN manager_id UUID REFERENCES users(id);
|
|
|
|
-- Create index for manager relationships
|
|
CREATE INDEX idx_users_manager_id ON users(manager_id);
|
|
```
|
|
|
|
## 7. Update DTOs
|
|
```typescript
|
|
// src/features/users/dto/user.dto.ts
|
|
export class CreateStaffDto {
|
|
@ApiProperty({
|
|
description: 'Staff role',
|
|
enum: [UserRole.STAFF, UserRole.AUDITOR, UserRole.MANAGER], // ← ADD MANAGER
|
|
example: UserRole.STAFF,
|
|
})
|
|
@IsEnum([UserRole.STAFF, UserRole.AUDITOR, UserRole.MANAGER])
|
|
role: UserRole.STAFF | UserRole.AUDITOR | UserRole.MANAGER;
|
|
|
|
@ApiPropertyOptional({
|
|
description: 'Manager ID (for staff assignments)',
|
|
})
|
|
@IsOptional()
|
|
@IsUUID()
|
|
managerId?: string;
|
|
}
|
|
```
|
|
|
|
## Result: Fully Functional Manager Role
|
|
- ✅ Hierarchical permissions (can access staff endpoints)
|
|
- ✅ Manager-specific endpoints
|
|
- ✅ Team management capabilities
|
|
- ✅ Database relationships
|
|
- ✅ Type safety maintained
|
|
- ✅ API documentation updated |