mirror of
https://github.com/azaion/admin.git
synced 2026-04-22 08:46:34 +00:00
[AZ-189] [AZ-190] [AZ-191] [AZ-192] [AZ-193] [AZ-194] [AZ-195] Add e2e blackbox test suite
Made-with: Cursor
This commit is contained in:
@@ -0,0 +1,127 @@
|
||||
# User Management
|
||||
|
||||
## 1. High-Level Overview
|
||||
|
||||
**Purpose**: Full user lifecycle management — registration, credential validation, hardware binding, role changes, account enable/disable, and deletion.
|
||||
|
||||
**Architectural Pattern**: Service layer — stateless business logic operating on the Data Layer through `IDbFactory`.
|
||||
|
||||
**Upstream dependencies**: Data Layer (IDbFactory, ICache, User entity), Security & Cryptography (hashing).
|
||||
|
||||
**Downstream consumers**: Admin API (endpoint handlers), Authentication (GetByEmail).
|
||||
|
||||
## 2. Internal Interfaces
|
||||
|
||||
### Interface: IUserService
|
||||
|
||||
| Method | Input | Output | Async | Error Types |
|
||||
|--------|-------|--------|-------|-------------|
|
||||
| `RegisterUser` | `RegisterUserRequest, CancellationToken` | void | Yes | `BusinessException(EmailExists)` |
|
||||
| `ValidateUser` | `LoginRequest, CancellationToken` | `User` | Yes | `BusinessException(NoEmailFound, WrongPassword)` |
|
||||
| `GetByEmail` | `string? email, CancellationToken` | `User?` | Yes | `ArgumentNullException` |
|
||||
| `UpdateHardware` | `string email, string? hardware, CancellationToken` | void | Yes | None |
|
||||
| `UpdateQueueOffsets` | `string email, UserQueueOffsets, CancellationToken` | void | Yes | None |
|
||||
| `GetUsers` | `string? searchEmail, RoleEnum? searchRole, CancellationToken` | `IEnumerable<User>` | Yes | None |
|
||||
| `CheckHardwareHash` | `User, string hardware, CancellationToken` | `string` (hash) | Yes | `BusinessException(HardwareIdMismatch)` |
|
||||
| `ChangeRole` | `string email, RoleEnum, CancellationToken` | void | Yes | None |
|
||||
| `SetEnableStatus` | `string email, bool, CancellationToken` | void | Yes | None |
|
||||
| `RemoveUser` | `string email, CancellationToken` | void | Yes | None |
|
||||
|
||||
**Input DTOs**:
|
||||
```
|
||||
RegisterUserRequest:
|
||||
Email: string (required) — validated: min 8 chars, valid email format
|
||||
Password: string (required) — validated: min 8 chars
|
||||
Role: RoleEnum (required)
|
||||
|
||||
LoginRequest:
|
||||
Email: string (required)
|
||||
Password: string (required)
|
||||
|
||||
SetHWRequest:
|
||||
Email: string (required, validated: not empty)
|
||||
Hardware: string? (optional — null clears hardware)
|
||||
|
||||
SetUserQueueOffsetsRequest:
|
||||
Email: string (required)
|
||||
Offsets: UserQueueOffsets (required)
|
||||
```
|
||||
|
||||
## 3. External API Specification
|
||||
|
||||
N/A — exposed through Admin API component.
|
||||
|
||||
## 4. Data Access Patterns
|
||||
|
||||
### Queries
|
||||
|
||||
| Query | Frequency | Hot Path | Index Needed |
|
||||
|-------|-----------|----------|--------------|
|
||||
| User by email (cached) | High | Yes | Yes |
|
||||
| User list with filters | Medium | No | No |
|
||||
| User insert (registration) | Low | No | No |
|
||||
| User update (hardware, role, config, status) | Medium | No | No |
|
||||
| User delete | Low | No | No |
|
||||
|
||||
### Caching Strategy
|
||||
|
||||
| Data | Cache Type | TTL | Invalidation |
|
||||
|------|-----------|-----|-------------|
|
||||
| User by email | In-memory (via ICache) | 4 hours | After UpdateHardware, UpdateQueueOffsets, CheckHardwareHash (first login) |
|
||||
|
||||
## 5. Implementation Details
|
||||
|
||||
**State Management**: Stateless — all state in PostgreSQL + in-memory cache.
|
||||
|
||||
**Key Dependencies**:
|
||||
|
||||
| Library | Version | Purpose |
|
||||
|---------|---------|---------|
|
||||
| FluentValidation | 11.10.0 | Request validation (auto-discovered) |
|
||||
|
||||
**Error Handling Strategy**:
|
||||
- Domain errors thrown as `BusinessException` with specific `ExceptionEnum` codes.
|
||||
- `GetByEmail` throws `ArgumentNullException` for null/whitespace email.
|
||||
- Database errors propagate from `IDbFactory`.
|
||||
- Write operations use `RunAdmin` (admin connection); reads use `Run` (reader connection).
|
||||
|
||||
## 6. Extensions and Helpers
|
||||
|
||||
| Helper | Purpose | Used By |
|
||||
|--------|---------|---------|
|
||||
| `Security.ToHash` | Password hashing (SHA-384) | RegisterUser, ValidateUser |
|
||||
| `Security.GetHWHash` | Hardware fingerprint hashing | CheckHardwareHash |
|
||||
| `QueryableExtensions.WhereIf` | Conditional LINQ filters | GetUsers |
|
||||
|
||||
## 7. Caveats & Edge Cases
|
||||
|
||||
**Known limitations**:
|
||||
- No pagination on `GetUsers` — returns all matching users.
|
||||
- `CheckHardwareHash` auto-stores hardware on first access (no explicit admin approval step).
|
||||
- `RemoveUser` is a hard delete, not soft delete.
|
||||
|
||||
**Potential race conditions**:
|
||||
- Concurrent `RegisterUser` calls with the same email: both could pass the existence check before insert. Mitigated by database unique constraint on email (if one exists).
|
||||
- `CheckHardwareHash` first-login path: concurrent requests could trigger multiple hardware updates.
|
||||
|
||||
**Performance bottlenecks**:
|
||||
- `GetUsers` loads full user objects including `UserConfig` JSON; for large user bases, projection would be more efficient.
|
||||
|
||||
## 8. Dependency Graph
|
||||
|
||||
**Must be implemented after**: Data Layer, Security & Cryptography.
|
||||
|
||||
**Can be implemented in parallel with**: Resource Management.
|
||||
|
||||
**Blocks**: Authentication (uses `GetByEmail`), Admin API.
|
||||
|
||||
## 9. Logging Strategy
|
||||
|
||||
No explicit logging in UserService.
|
||||
|
||||
## Modules Covered
|
||||
- `Services/UserService`
|
||||
- `Common/Requests/LoginRequest`
|
||||
- `Common/Requests/RegisterUserRequest`
|
||||
- `Common/Requests/SetHWRequest`
|
||||
- `Common/Requests/SetUserQueueOffsetsRequest`
|
||||
Reference in New Issue
Block a user