[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,100 @@
# Resource Management
## 1. High-Level Overview
**Purpose**: Server-side file storage management — upload, list, download (with per-user AES encryption), folder clearing, and installer distribution.
**Architectural Pattern**: Service layer — filesystem operations with encryption applied at the service boundary.
**Upstream dependencies**: Data Layer (ResourcesConfig), Authentication & Security (encryption via Security.EncryptTo).
**Downstream consumers**: Admin API (resource endpoints).
## 2. Internal Interfaces
### Interface: IResourcesService
| Method | Input | Output | Async | Error Types |
|--------|-------|--------|-------|-------------|
| `GetInstaller` | `bool isStage` | `(string?, Stream?)` | No | None (returns nulls if not found) |
| `GetEncryptedResource` | `string? dataFolder, string fileName, string key, CancellationToken` | `Stream` | Yes | `FileNotFoundException` |
| `SaveResource` | `string? dataFolder, IFormFile data, CancellationToken` | void | Yes | `BusinessException(NoFileProvided)` |
| `ListResources` | `string? dataFolder, string? search, CancellationToken` | `IEnumerable<string>` | Yes | `DirectoryNotFoundException` |
| `ClearFolder` | `string? dataFolder` | void | No | None |
**Input DTOs**:
```
GetResourceRequest:
Password: string (required, min 8 chars)
Hardware: string (required, not empty)
FileName: string (required, not empty)
CheckResourceRequest:
Hardware: string (required)
```
## 3. External API Specification
N/A — exposed through Admin API.
## 4. Data Access Patterns
No database access. All operations are filesystem-based.
### Storage Estimates
Resources are stored as flat files in configured directories. Size depends on uploaded content (AI models, DLLs, installers — potentially hundreds of MB per file).
## 5. Implementation Details
**State Management**: Stateless — reads/writes directly to filesystem.
**Key Dependencies**: None beyond BCL (System.IO).
**Error Handling Strategy**:
- `SaveResource` throws `BusinessException(NoFileProvided)` for null uploads.
- Missing files/directories throw standard .NET I/O exceptions.
- `ClearFolder` silently returns if directory doesn't exist.
- `GetInstaller` returns `(null, null)` tuple if installer file is not found.
## 6. Extensions and Helpers
| Helper | Purpose | Used By |
|--------|---------|---------|
| `Security.EncryptTo` | AES stream encryption | GetEncryptedResource |
| `Security.GetApiEncryptionKey` | Key derivation | Admin API (before calling GetEncryptedResource) |
## 7. Caveats & Edge Cases
**Known limitations**:
- No path traversal protection: `dataFolder` parameter is concatenated directly with `ResourcesFolder`. A malicious `dataFolder` like `../../etc` could access arbitrary filesystem paths.
- `SaveResource` deletes existing file before writing — no versioning or backup.
- `GetEncryptedResource` loads the entire encrypted file into a `MemoryStream` — memory-intensive for large files.
- `ListResources` wraps a synchronous `DirectoryInfo.GetFiles` in `Task.FromResult` — not truly async.
**Performance bottlenecks**:
- Full file encryption to memory before streaming response: memory usage scales with file size.
- `ClearFolder` iterates and deletes files synchronously.
## 8. Dependency Graph
**Must be implemented after**: Data Layer (ResourcesConfig), Authentication & Security (encryption).
**Can be implemented in parallel with**: User Management.
**Blocks**: Admin API.
## 9. Logging Strategy
| Log Level | When | Example |
|-----------|------|---------|
| INFO | Successful file save | `Resource {data.FileName} Saved Successfully` |
**Log format**: String interpolation via Serilog.
**Log storage**: Console + rolling file (via Serilog configured in Program.cs).
## Modules Covered
- `Services/ResourcesService`
- `Common/Requests/GetResourceRequest` (includes CheckResourceRequest)
- `Common/Configs/ResourcesConfig`