[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:
Oleksandr Bezdieniezhnykh
2026-04-16 06:25:36 +03:00
parent 1b38e888e1
commit d320d6dd59
98 changed files with 6883 additions and 1 deletions
@@ -0,0 +1,62 @@
# Module: Azaion.Services.UserService
## Purpose
Core business logic for user management: registration, authentication, hardware binding, role management, and account lifecycle.
## Public Interface
### IUserService
| Method | Signature | Description |
|--------|-----------|-------------|
| `RegisterUser` | `Task RegisterUser(RegisterUserRequest request, CancellationToken ct)` | Creates a new user with hashed password |
| `ValidateUser` | `Task<User> ValidateUser(LoginRequest request, CancellationToken ct)` | Validates email + password, returns user |
| `GetByEmail` | `Task<User?> GetByEmail(string? email, CancellationToken ct)` | Cached user lookup by email |
| `UpdateHardware` | `Task UpdateHardware(string email, string? hardware, CancellationToken ct)` | Sets/clears user's hardware fingerprint |
| `UpdateQueueOffsets` | `Task UpdateQueueOffsets(string email, UserQueueOffsets offsets, CancellationToken ct)` | Updates user's annotation queue offsets |
| `GetUsers` | `Task<IEnumerable<User>> GetUsers(string? searchEmail, RoleEnum? searchRole, CancellationToken ct)` | Lists users with optional email/role filters |
| `CheckHardwareHash` | `Task<string> CheckHardwareHash(User user, string hardware, CancellationToken ct)` | Validates or initializes hardware binding |
| `ChangeRole` | `Task ChangeRole(string email, RoleEnum newRole, CancellationToken ct)` | Changes a user's role |
| `SetEnableStatus` | `Task SetEnableStatus(string email, bool isEnabled, CancellationToken ct)` | Enables or disables a user account |
| `RemoveUser` | `Task RemoveUser(string email, CancellationToken ct)` | Permanently deletes a user |
## Internal Logic
- **RegisterUser**: checks for duplicate email, hashes password via `Security.ToHash`, inserts via `RunAdmin`.
- **ValidateUser**: finds user by email, compares password hash. Throws `NoEmailFound` or `WrongPassword`.
- **GetByEmail**: uses `ICache.GetFromCacheAsync` with key `User.{email}`.
- **CheckHardwareHash**: on first access (null hardware), stores the raw hardware string and returns the hash. On subsequent access, compares hashes. Throws `HardwareIdMismatch` on mismatch. Also updates `LastLogin` timestamp.
- **UpdateHardware/UpdateQueueOffsets**: use `RunAdmin` for writes, then invalidate cache.
- **GetUsers**: uses `WhereIf` for optional filter predicates.
Private method:
- `UpdateLastLoginDate` — updates `LastLogin` to `DateTime.UtcNow`.
## Dependencies
- `IDbFactory` (database access)
- `ICache` (user caching)
- `Security` (hashing)
- `BusinessException` (domain errors)
- `QueryableExtensions.WhereIf`
- `User`, `UserConfig`, `UserQueueOffsets`, `RoleEnum`
- `RegisterUserRequest`, `LoginRequest`
## Consumers
- `Program.cs` — all `/users/*` endpoints delegate to `IUserService`
- `AuthService.GetCurrentUser` — calls `GetByEmail`
- `Program.cs` `/resources/get` — calls `CheckHardwareHash`
## Data Models
Operates on `User` entity via `AzaionDb.Users` table.
## Configuration
None.
## External Integrations
PostgreSQL via `IDbFactory`.
## Security
- Passwords hashed with SHA-384 (via `Security.ToHash`) before storage
- Hardware binding prevents resource access from unauthorized devices
- Read operations use read-only DB connection; writes use admin connection
## Tests
- `UserServiceTest.CheckHardwareHashTest` — integration test against live database