# 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 ValidateUser(LoginRequest request, CancellationToken ct)` | Validates email + password, returns user | | `GetByEmail` | `Task 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> GetUsers(string? searchEmail, RoleEnum? searchRole, CancellationToken ct)` | Lists users with optional email/role filters | | `CheckHardwareHash` | `Task 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