Users Domain
The Users domain manages user accounts, authentication, authorization, identity verification (KYC), and user portfolios. It is the foundation of the 2KRIKA platform, providing the user management infrastructure for customers, sellers, and administrators.
Overview
The Users domain encompasses:
- User accounts – Registration, profiles, authentication
- Roles and permissions – RBAC (Role-Based Access Control)
- Identity verification – KYC (Know Your Customer) process
- User portfolios – Skills, projects, experience, education
Entities
User Entity
The core entity representing a platform user.
// domain/user/user.entity.ts
export class User {
id: string;
fullName: string;
email: string;
passwordHash: string;
username: string;
isActive: boolean;
isStaff: boolean;
isSuperuser: boolean;
isKYCVerified: boolean;
title: string;
description: string;
notes: string;
lastLogin: Date | null;
createdAt: Date;
updatedAt: Date;
private permissions?: Permission[];
static create(
id: string,
fullName: string,
username: string,
email: string,
passwordHash: string,
// ... other parameters
): User
// Business rules
activate(): void
deactivate(): void
approveKyc(): void
cancelKYC(): void
hasPermission(permission: Permission): boolean
setPermissions(permissions: Permission[]): void
getPermissions(): Permission[] | undefined
}
Key properties:
- id – Unique identifier (CUID)
- email – Unique email address
- username – Unique username
- passwordHash – Bcrypt hashed password
- isActive – Account activation status
- isStaff – Staff access flag
- isSuperuser – Superuser access (all permissions)
- isKYCVerified – KYC verification status
Business rules:
- activate() / deactivate() – Control account status
- approveKyc() / cancelKYC() – Manage KYC verification
- hasPermission() – Check authorization (superusers have all permissions)
Role Entity
Predefined roles with associated permissions.
// domain/user/role.entity.ts
export class Role {
id: string;
name: string;
permissions: Permission[];
static readonly ADMIN: Role
static readonly CUSTOMER: Role
static readonly SELLER: Role
hasPermission(permission: Permission): boolean
static all(): Role[]
static get(id: string): Role | undefined
static getByName(name: string): Role | undefined
}
Predefined roles:
- ADMIN
- Full platform administration
- User management
- Category and service moderation
- KYC approval/rejection
- Withdraw and refund processing
-
Access to all administrative features
-
CUSTOMER
- Browse services
- Place orders
- Submit KYC
- Participate in chats
-
View own data
-
SELLER
- Create and manage services
- Fulfill orders
- Initiate withdrawals
- View own sales data
- Participate in chats
Permission Value Object
Fine-grained permissions enum.
// domain/user/permission.vo.ts
export enum Permission {
VIEW_ME = "view_me",
CREATE_USER = "create_user",
DELETE_USER = "delete_user",
VIEW_USERS = "view_users",
ACTIVATE_USERS = "activate_users",
DEACTIVATE_USERS = "deactivate_users",
CREATE_SERVICE = "create_service",
UPDATE_SERVICE = "update_service",
DELETE_SERVICE = "delete_service",
APPROVE_SERVICE = "approve_service",
REJECT_SERVICE = "reject_service",
SUSPEND_SERVICE = "suspend_service",
CREATE_CATEGORY = "create_category",
UPDATE_CATEGORY = "update_category",
DELETE_CATEGORY = "delete_category",
SUBMIT_KYC = "submit_kyc",
APPROVE_KYC = "approve_kyc",
REJECT_KYC = "reject_kyc",
PASS_ORDER = "pass_order",
LIST_ORDERS = "list_orders",
VIEW_ORDER = "view_order",
INITIATE_WITHDRAW = "initiate_withdraw",
COMPLETE_WITHDRAW = "complete_withdraw",
VIEW_REFUND = "view_refund",
COMPLETE_REFUND = "complete_refund",
// ... many more permissions
}
Identity Entity
KYC identity information for users.
// domain/user/identiy.entity.ts
export class Identity {
id: string;
firstName: string;
lastName: string;
birthDate: Date;
nationality: string;
businessType: BusinessType; // 'individual' | 'company'
business: BusinessDetails | null;
addressLine1: string;
addressLine2: string;
city: string;
state: string;
postalCode: string;
country: string;
phoneNumber: string;
idDocumentType: IdDocumentType; // 'passport' | 'id_card' | 'driver_license'
idDocumentId: string;
userId: string;
status: IdentityStatus; // 'draft' | 'pending' | 'approved'
KYCValidationDate: Date | null;
createdAt: Date;
updatedAt: Date;
canBeSubmitted(): boolean
canBeApproved(): boolean
getMissingRequiredFields(): string[]
approve(): void
submit(): void
}
KYC workflow: 1. Draft – User fills identity information 2. Pending – User submits for review 3. Approved – Admin approves, user becomes KYC verified
Portfolio Entities
User portfolio components for sellers.
// domain/user/portfolio.entities.ts
class Skill {
id: string;
userId: string;
name: string;
}
class Project {
id: string;
userId: string;
title: string;
description: string;
bannerId: string | null;
serviceId: string | null;
}
class Experience {
id: string;
userId: string;
companyName: string;
position: string;
startDate: Date;
endDate: Date | null;
description: string;
}
class Education {
id: string;
userId: string;
institutionName: string;
degree: string;
deliveryDate: Date;
}
Repositories
UserRepository
// domain/user/user.repository.ts
export abstract class UserRepository extends AbstractRepository<User, string, UserQueryPolicy> {
abstract getKYCValidationDate(userId: string): Promise<Date | null>;
abstract approveKyc(id: string, opts?: any): Promise<void>;
abstract filterByIds(ids: string[]): Promise<User[]>;
}
export class UserQueryPolicy extends Pagination {
isActive?: boolean;
isKYCVerified?: boolean;
search?: string; // Search in fullName or email
roles?: string[]; // Filter by roles
orderBy?: string[]; // e.g., ["createdAt"] or ["-createdAt"]
}
Key operations:
- add() – Create new user
- get() – Get by ID
- getBy() – Get by criteria (email, username)
- all() – List with filters (search, roles, KYC status)
- approveKyc() – Mark user as KYC verified
- filterByIds() – Batch fetch users
IdentityRepository
// domain/user/identity.repository.ts
export abstract class IdentityRepository extends AbstractRepository<Identity> {
abstract getByUserId(userId: string): Promise<Identity>;
abstract listValidationRequests(filters: any): Promise<Paginated<Identity>>;
}
UserRoleRepository
// domain/user/userrole.repository.ts
export abstract class UserRoleRepository {
abstract assignRole(userId: string, roleId: string): Promise<void>;
abstract removeRole(userId: string, roleId: string): Promise<void>;
abstract getUserRoles(userId: string): Promise<Role[]>;
abstract getAllPermissions(user: User): Promise<void>;
}
CompetencyRepository
Manages user portfolio items (skills, projects, experience, education).
// domain/user/portfolio.repository.ts
export abstract class CompetencyRepository {
abstract addSkill(skill: Skill): Promise<Skill>;
abstract addProject(project: Project): Promise<Project>;
abstract addExperience(experience: Experience): Promise<Experience>;
abstract addEducation(education: Education): Promise<Education>;
abstract getUserSkills(userId: string): Promise<Skill[]>;
abstract getUserProjects(userId: string): Promise<Project[]>;
abstract getUserExperience(userId: string): Promise<Experience[]>;
abstract getUserEducation(userId: string): Promise<Education[]>;
abstract deleteSkill(id: string): Promise<void>;
abstract deleteProject(id: string): Promise<void>;
abstract deleteExperience(id: string): Promise<void>;
abstract deleteEducation(id: string): Promise<void>;
}
Business Rules
User Registration
- Email uniqueness – Enforced by database constraint
- Username uniqueness – Enforced by database constraint
- Password strength – Minimum 8 characters (validated in application layer)
- Default state – New users are inactive until they activate via email
- Automatic username generation – If not provided, generated from full name
User Activation
- Users receive activation email with token
- Clicking link activates account (
isActive = true) - Only active users can log in
KYC Verification
- Draft state – User can edit identity information
- Submission – Must have all required fields
- Pending review – Admin reviews documents
- Approval – Admin approves, user becomes
isKYCVerified = true - Business types:
- Individual – Only personal details required
- Company – Requires business name and details
Authorization
- Superusers – Have all permissions
- Role-based – Permissions assigned via roles
- Permission checking –
user.hasPermission(Permission.XXX) - Guards – Web layer enforces permissions on endpoints
User Deactivation
- Admin can deactivate users
- Deactivated users cannot log in
- User's services are also deactivated
- Existing orders continue normally
Use Cases
User Management
- Create user – Register new account
- Activate user – Email verification
- Update profile – Edit name, title, description
- Upload profile picture – Attach image
- Deactivate user – Admin action
- List users – With filters (search, role, KYC status)
- Get user details – View profile
KYC Management
- Create identity – Initialize KYC profile
- Update identity – Edit KYC information
- Submit KYC – Request admin review
- List KYC requests – Admin view pending verifications
- Approve KYC – Admin approves verification
- Reject KYC – Admin rejects with reason
Portfolio Management
- Add skill – Add skill to portfolio
- Add project – Add project with banner
- Add experience – Add work experience
- Add education – Add education record
- List portfolio – Get all user portfolio items
- Delete portfolio item – Remove from portfolio
Integration Points
With Orders Domain
Order.customerIdreferencesUser.idOrder.sellerIdreferencesUser.id- Users can view their orders (as customer or seller)
With Services Domain
Service.ownerIdreferencesUser.id- Only KYC verified users can create services (sellers)
With Accounts Domain
- Each user has one
Accountfor balance management - Accounts reference
User.id
With Notifications
- Users receive email notifications
- Notifications reference
User.id
Key Workflows
User Registration Flow
1. User submits registration form
↓
2. Validate email/username uniqueness
↓
3. Hash password
↓
4. Create User entity (isActive = false)
↓
5. Assign CUSTOMER role by default
↓
6. Send activation email
↓
7. User clicks activation link
↓
8. User.activate()
↓
9. User can log in
KYC Verification Flow
1. User creates Identity (status = draft)
↓
2. User uploads ID documents
↓
3. User fills all required fields
↓
4. User submits Identity (status = pending)
↓
5. Admin reviews submission
↓
6. Admin approves Identity (status = approved)
↓
7. User.approveKyc()
↓
8. User can create services (if seller role)
Permission Check Flow
1. Request arrives at endpoint
↓
2. AuthGuard extracts JWT token
↓
3. Load User from database
↓
4. Load User roles and permissions
↓
5. Check user.hasPermission(requiredPermission)
↓
6. Allow or deny request
Data Model
┌─────────────┐
│ User │
├─────────────┤
│ id │◄────┐
│ email │ │
│ username │ │
│ passwordHash│ │
│ isActive │ │
│ isKYCVerified│ │
└─────────────┘ │
│
┌─────────────┐ │
│ Identity │ │
├─────────────┤ │
│ id │ │
│ userId │─────┘
│ firstName │
│ lastName │
│ status │
└─────────────┘
┌─────────────┐ ┌─────────────┐
│ UserRole │────►│ Role │
├─────────────┤ ├─────────────┤
│ userId │ │ id │
│ roleId │ │ name │
└─────────────┘ │ permissions │
└─────────────┘
┌─────────────┐
│ Portfolio │
├─────────────┤
│ Skill │
│ Project │
│ Experience │
│ Education │
└─────────────┘
Best Practices
✅ Do
- Hash passwords – Use bcrypt, never store plain text
- Validate uniqueness – Email and username must be unique
- Check permissions – Always validate authorization
- Use KYC status – Restrict sensitive operations to verified users
- Audit changes – Track who modified user data
❌ Don't
- Don't expose passwordHash – Never include in DTOs
- Don't bypass activation – Users must verify email
- Don't skip permission checks – Always validate authorization
- Don't allow self-promotion – Users can't make themselves staff/superuser
- Don't delete users – Deactivate instead to preserve history
Summary
The Users domain provides:
- User account management with email verification
- Role-based access control with fine-grained permissions
- KYC verification for identity validation
- User portfolios for seller profiles
- Flexible authorization supporting multiple roles per user
This domain is foundational—all other domains depend on User for authentication and authorization.