TASKS-1823 WebManager module
This commit is contained in:
@@ -0,0 +1,110 @@
|
||||
# File Manager Backend
|
||||
|
||||
Authenticated file operations under `/file-manager`: validation, authorization, path normalization, orchestration, with raw storage delegated to a storage adapter. Source: `apps/backend/app/base_modules/FileManager/`.
|
||||
|
||||
## Request Flow
|
||||
|
||||
```txt
|
||||
routes.ts
|
||||
-> controller/file_manager_controller.ts
|
||||
-> validator/*
|
||||
-> policy/file_manager_policy.ts
|
||||
-> services/file_manager_service.ts
|
||||
-> services/storage_service/ (interface -> factory -> fs | s3 adapter)
|
||||
-> Adonis Drive
|
||||
```
|
||||
|
||||
The controller stays thin (auth checks, validation, path extraction, status codes, response shape). `FileManagerService` owns orchestration; storage adapters own raw persistence.
|
||||
|
||||
## Routes
|
||||
|
||||
All prefixed with `/file-manager`, behind `middleware.auth()`; controller methods check policy abilities (`policy/file_manager_policy.ts`) before doing work. When adding an operation, add or reuse an explicit ability first.
|
||||
|
||||
| Method | Route | Controller Method | Ability | Purpose |
|
||||
| -------- | ------------------ | ----------------- | ---------- | ------------------------------------------------------- |
|
||||
| `GET` | `/` and `/*` | `index` | `viewList` | List entries for root or a nested directory. |
|
||||
| `GET` | `/files/details/*` | `show` | `view` | Return file metadata and optional text preview content. |
|
||||
| `GET` | `/files/raw/*` | `raw` | `view` | Stream raw file content. |
|
||||
| `GET` | `/search?q=value` | `search` | `viewList` | Search entries recursively. |
|
||||
| `POST` | `/folders` | `createFolder` | `create` | Create a folder. |
|
||||
| `POST` | `/files` | `upload` | `create` | Upload a file. |
|
||||
| `POST` | `/files/duplicate` | `duplicate` | `create` | Duplicate one or more **file** entries. |
|
||||
| `PUT` | `/entries/rename` | `rename` | `update` | Rename or move an entry within its parent path. |
|
||||
| `DELETE` | `/*` | `destroy` | `delete` | Delete an entry. |
|
||||
|
||||
## Validation
|
||||
|
||||
Validators in `validator/`: `list_validator.ts` (filter, sort, order, max results, pagination token), `create_directory_validator.ts`, `rename_entry_validator.ts`, `upload_file_validator.ts`, `duplicate_entries_validator.ts`, plus shared helpers in `schemas.ts`.
|
||||
|
||||
Path extraction from wildcard routes goes through `helpers/get_validated_path_from_request.ts` — never parse wildcard paths in controllers or storage adapters.
|
||||
|
||||
## Services
|
||||
|
||||
| Service | Owns |
|
||||
| ------------------------- | ------------------------------------------------------------------------------------------------------------------------------------------------------------------------------ |
|
||||
| `file_manager_service.ts` | Orchestration: listing with filter/sort/pagination, file detail + preview composition, moves, unique upload and copy names, search, storage calls. |
|
||||
| `path_service.ts` | Client↔storage path conversion, safe joins, dirname/basename, extension metadata, filename sanitizing, unique names. Use it instead of string manipulation. |
|
||||
| `entry_list_service.ts` | List behavior on raw storage entries: category filter, sort, folders-first, pagination + token encoding. Frontend list controls must stay compatible with its accepted values. |
|
||||
| `file_preview_service.ts` | Text preview content for previewable extensions (defined in the same file). For rich previews, keep the response small and stream via `/files/raw/*`. |
|
||||
| `entry_search_service.ts` | Path search including matching parent folders for context. Receives an abort signal from the controller — long searches should respect it. |
|
||||
|
||||
## Storage
|
||||
|
||||
Abstractions in `services/storage_service/`:
|
||||
|
||||
- `storage_service_interface.ts` — the adapter contract: list (flat and recursive), existence, metadata, read/stream/write, create directory, move, delete, copy. Services call the interface, never a concrete adapter.
|
||||
- `fs_storage_service.ts` — filesystem adapter over the Adonis Drive `fs` disk: maps filesystem objects to entries, handles streams and metadata, preserves directory marker behavior.
|
||||
- `s3_storage_service.ts` — S3-compatible adapter over the `s3` disk: maps objects and common prefixes to entries, uploads multipart files by streaming the temp file via `putStream`, creates folders with directory marker objects, moves folders by moving every object under the prefix, deletes files exactly and folders by prefix, copies file entries. S3 has no native directories, so it shares the `.keep` marker convention. **Folder operations must use slash-terminated prefixes** — deleting `test/` must not delete `test123.txt`.
|
||||
- `fs_directory_marker_service.ts` — encapsulates the `.keep` marker convention; never duplicate marker logic outside it.
|
||||
- `create_storage_service.ts` — factory; the active adapter (`fs` or `s3`) is selected by `DRIVE_DISK`.
|
||||
|
||||
## Drive Configuration
|
||||
|
||||
`apps/backend/config/drive.ts` configures two disks: `fs` (local development, filesystem storage) and `s3` (S3-compatible object storage, including local MinIO).
|
||||
|
||||
S3 environment variables:
|
||||
|
||||
| Variable | Local Docker Value | Purpose |
|
||||
| ----------------------- | --------------------------------------------------------------------- | --------------------------------------------- |
|
||||
| `AWS_ACCESS_KEY_ID` | `minioadmin` | S3 access key. |
|
||||
| `AWS_SECRET_ACCESS_KEY` | `minioadmin` | S3 secret key. |
|
||||
| `AWS_REGION` | `us-east-1` | S3 region. |
|
||||
| `S3_BUCKET` | `crux-drive` | Bucket used by the file manager. |
|
||||
| `S3_ENDPOINT` | `http://minio:9000` in Docker, `http://localhost:9000` outside Docker | S3 API endpoint. |
|
||||
| `S3_CDN_URL` | `http://localhost:9000/crux-drive/` | Browser-facing public URL base for file URLs. |
|
||||
|
||||
For MinIO the disk uses `forcePathStyle: true` and `supportsACL: false`; bucket public-read is handled by the Docker bucket setup container.
|
||||
|
||||
## Local S3 Simulation
|
||||
|
||||
`docker-compose.yml` runs `minio` (the S3 server) and `minio_create_bucket` (one-shot setup that creates the bucket and enables anonymous download — it exits after setup, which is normal). Console at `http://localhost:9001`, credentials `minioadmin` / `minioadmin`. After dependency or Dockerfile changes: `docker compose build --no-cache && docker compose up`.
|
||||
|
||||
## Response Shape
|
||||
|
||||
```ts
|
||||
interface EntryBase {
|
||||
name: string;
|
||||
path: string;
|
||||
updatedAt?: string;
|
||||
}
|
||||
|
||||
interface FileEntry extends EntryBase {
|
||||
type: "file";
|
||||
size?: number;
|
||||
url: string;
|
||||
}
|
||||
|
||||
interface FolderEntry extends EntryBase {
|
||||
type: "folder";
|
||||
}
|
||||
```
|
||||
|
||||
List responses: `{ data: Entry[]; meta: { nextPaginationToken: string | null } }`.
|
||||
|
||||
## Backend Change Checklist
|
||||
|
||||
1. Confirm the policy ability for the operation.
|
||||
2. Add or update a validator for all request input.
|
||||
3. Keep client paths and storage paths separated through `path_service.ts`.
|
||||
4. Update the frontend DTO or mapper if the response shape changes.
|
||||
5. Update this documentation when routes, permissions, storage contracts, or response shapes change.
|
||||
Reference in New Issue
Block a user