Initial commit
This commit is contained in:
@@ -0,0 +1,368 @@
|
||||
# File Manager Backend
|
||||
|
||||
The backend module exposes authenticated file operations under `/file-manager`. It validates requests, authorizes actions, normalizes paths, orchestrates file-manager behavior, and delegates raw storage work to a storage adapter.
|
||||
|
||||
Source root:
|
||||
|
||||
```txt
|
||||
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/storage_service_interface.ts
|
||||
-> services/storage_service/create_storage_service.ts
|
||||
-> services/storage_service/fs_storage_service.ts | services/storage_service/s3_storage_service.ts
|
||||
-> Adonis Drive
|
||||
```
|
||||
|
||||
The controller should stay thin. It handles HTTP concerns: auth policy checks, request validation, path extraction, status codes, and response payload shape.
|
||||
|
||||
`FileManagerService` owns business orchestration. Storage adapters own raw persistence operations.
|
||||
|
||||
## Routes
|
||||
|
||||
All routes are prefixed with `/file-manager` and use `middleware.auth()`.
|
||||
|
||||
| Method | Route | Controller Method | Purpose |
|
||||
| -------- | ------------------ | ----------------- | ------------------------------------------------------- |
|
||||
| `GET` | `/` | `index` | List root directory entries. |
|
||||
| `GET` | `/*` | `index` | List entries for a nested directory. |
|
||||
| `GET` | `/files/details/*` | `show` | Return file metadata and optional text preview content. |
|
||||
| `GET` | `/files/raw/*` | `raw` | Stream raw file content. |
|
||||
| `GET` | `/search?q=value` | `search` | Search entries recursively. |
|
||||
| `POST` | `/folders` | `createFolder` | Create a folder. |
|
||||
| `POST` | `/files` | `upload` | Upload a file. |
|
||||
| `POST` | `/files/duplicate` | `duplicate` | Duplicate one or more **file** entries. |
|
||||
| `PUT` | `/entries/rename` | `rename` | Rename or move an entry within its parent path. |
|
||||
| `DELETE` | `/*` | `destroy` | Delete an entry. |
|
||||
|
||||
## Authorization
|
||||
|
||||
Policy file:
|
||||
|
||||
```txt
|
||||
policy/file_manager_policy.ts
|
||||
```
|
||||
|
||||
Controller methods call policy abilities before performing work:
|
||||
|
||||
| Ability | Used By |
|
||||
| ---------- | ---------------------------------------------- |
|
||||
| `viewList` | List entries, search entries. |
|
||||
| `view` | File details, raw file stream. |
|
||||
| `create` | Create folder, upload file, duplicate entries. |
|
||||
| `update` | Rename entry. |
|
||||
| `delete` | Delete entry. |
|
||||
|
||||
When adding a new operation, add or reuse an explicit policy ability before adding service logic.
|
||||
|
||||
## Validation
|
||||
|
||||
Validators live in:
|
||||
|
||||
```txt
|
||||
validator/
|
||||
```
|
||||
|
||||
Current validators:
|
||||
|
||||
| File | Purpose |
|
||||
| -------------------------------- | ----------------------------------------------------------------- |
|
||||
| `list_validator.ts` | Validates filter, sort, order, max results, and pagination token. |
|
||||
| `create_directory_validator.ts` | Validates parent path and folder name. |
|
||||
| `rename_entry_validator.ts` | Validates source path and new name. |
|
||||
| `upload_file_validator.ts` | Validates upload path and file payload. |
|
||||
| `duplicate_entries_validator.ts` | Validates duplicate source paths. |
|
||||
| `schemas.ts` | Shared validation schema helpers. |
|
||||
|
||||
Path extraction from wildcard routes goes through:
|
||||
|
||||
```txt
|
||||
helpers/get_validated_path_from_request.ts
|
||||
```
|
||||
|
||||
Keep path validation centralized. Avoid parsing wildcard paths directly in controllers or storage adapters.
|
||||
|
||||
## Services
|
||||
|
||||
### `file_manager_service.ts`
|
||||
|
||||
Main orchestration service.
|
||||
|
||||
Responsibilities:
|
||||
|
||||
- List directory entries with filtering, sorting, and pagination.
|
||||
- Compose file detail responses with preview content.
|
||||
- Create directory response entries.
|
||||
- Validate and move entries.
|
||||
- Generate unique upload names.
|
||||
- Generate duplicate copy names.
|
||||
- Search entries.
|
||||
- Coordinate storage adapter calls.
|
||||
|
||||
### `path_service.ts`
|
||||
|
||||
Shared path and filename utility service.
|
||||
|
||||
Responsibilities:
|
||||
|
||||
- Convert client paths to storage paths.
|
||||
- Convert storage paths to client paths.
|
||||
- Join paths safely.
|
||||
- Get dirname and basename.
|
||||
- Parse file extension metadata.
|
||||
- Sanitize filenames.
|
||||
- Generate unique names.
|
||||
|
||||
Use this service for path behavior instead of string manipulation in feature code.
|
||||
|
||||
### `entry_list_service.ts`
|
||||
|
||||
Applies list behavior to raw storage entries.
|
||||
|
||||
Responsibilities:
|
||||
|
||||
- Filter entries by category.
|
||||
- Sort entries.
|
||||
- Keep folders before files.
|
||||
- Paginate entries.
|
||||
- Encode and decode pagination tokens.
|
||||
|
||||
Frontend list controls must stay compatible with this service's accepted filter and sort values.
|
||||
|
||||
### `file_preview_service.ts`
|
||||
|
||||
Adds text preview content to previewable files.
|
||||
|
||||
Previewable text extensions are currently defined in:
|
||||
|
||||
```txt
|
||||
services/file_preview_service.ts
|
||||
```
|
||||
|
||||
If a file type needs rich frontend preview, keep the backend response small and stream raw content through `/files/raw/*` when possible.
|
||||
|
||||
### `entry_search_service.ts`
|
||||
|
||||
Searches entries by path and includes matching parent folders so the frontend can display useful context.
|
||||
|
||||
Search receives an abort signal from the controller. Long-running search implementations should respect that signal.
|
||||
|
||||
## Storage
|
||||
|
||||
Storage abstractions live in:
|
||||
|
||||
```txt
|
||||
services/storage_service/
|
||||
```
|
||||
|
||||
### `storage_service_interface.ts`
|
||||
|
||||
Defines the storage adapter contract. Adapters expose raw operations:
|
||||
|
||||
- List directory entries.
|
||||
- List recursive entries.
|
||||
- Check entry existence.
|
||||
- Get file metadata.
|
||||
- Read file content.
|
||||
- Stream file content.
|
||||
- Write file.
|
||||
- Create directory.
|
||||
- Move entry.
|
||||
- Delete entry.
|
||||
- Copy entry.
|
||||
|
||||
Services should call the interface, not a concrete adapter.
|
||||
|
||||
### `fs_storage_service.ts`
|
||||
|
||||
Filesystem storage adapter.
|
||||
|
||||
Responsibilities:
|
||||
|
||||
- Call the Adonis Drive filesystem disk.
|
||||
- Map filesystem objects to File Manager entries.
|
||||
- Handle file streams and metadata.
|
||||
- Create, move, copy, and delete filesystem entries.
|
||||
- Preserve filesystem directory marker behavior.
|
||||
|
||||
### `s3_storage_service.ts`
|
||||
|
||||
S3-compatible storage adapter.
|
||||
|
||||
Responsibilities:
|
||||
|
||||
- Call the Adonis Drive `s3` disk.
|
||||
- Map S3 objects and common prefixes to File Manager entries.
|
||||
- Upload multipart files by streaming the temporary upload file into S3 with `putStream`.
|
||||
- Read file content and streams from S3.
|
||||
- Create folders with directory marker objects.
|
||||
- Move folders by moving every object under the folder prefix.
|
||||
- Delete files with exact object deletion and folders with folder-prefix deletion.
|
||||
- Copy file entries.
|
||||
|
||||
S3 has no native directories. The adapter uses the same `.keep` marker convention as the filesystem adapter so empty folders can exist.
|
||||
|
||||
Folder operations must use slash-terminated prefixes. For example, deleting `test/` must not delete objects such as `test123.txt`.
|
||||
|
||||
### `fs_directory_marker_service.ts`
|
||||
|
||||
Encapsulates the filesystem directory marker convention.
|
||||
|
||||
Current marker:
|
||||
|
||||
```txt
|
||||
.keep
|
||||
```
|
||||
|
||||
Do not duplicate marker logic outside this service. Storage adapters that need virtual folders should use this marker service behind the storage interface.
|
||||
|
||||
### `create_storage_service.ts`
|
||||
|
||||
Storage service factory.
|
||||
|
||||
Current supported storage:
|
||||
|
||||
```txt
|
||||
fs
|
||||
s3
|
||||
```
|
||||
|
||||
The active adapter is selected by `DRIVE_DISK`.
|
||||
|
||||
```env
|
||||
DRIVE_DISK=fs
|
||||
```
|
||||
|
||||
or:
|
||||
|
||||
```env
|
||||
DRIVE_DISK=s3
|
||||
```
|
||||
|
||||
## Drive Configuration
|
||||
|
||||
Adonis Drive config lives in:
|
||||
|
||||
```txt
|
||||
backend/config/drive.ts
|
||||
```
|
||||
|
||||
Configured disks:
|
||||
|
||||
| Disk | Driver | Purpose |
|
||||
| ---- | ------------- | ---------------------------------------------------- |
|
||||
| `fs` | `services.fs` | Local development and filesystem-backed storage. |
|
||||
| `s3` | `services.s3` | S3-compatible object storage, including local MinIO. |
|
||||
|
||||
The S3 disk expects these 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 S3 disk uses path-style addressing:
|
||||
|
||||
```ts
|
||||
forcePathStyle: true;
|
||||
```
|
||||
|
||||
The adapter also disables ACL API calls:
|
||||
|
||||
```ts
|
||||
supportsACL: false;
|
||||
```
|
||||
|
||||
Bucket public-read behavior is handled by the Docker bucket setup container.
|
||||
|
||||
## Local S3 Simulation
|
||||
|
||||
Local S3 is simulated with MinIO in:
|
||||
|
||||
```txt
|
||||
docker-compose.yml
|
||||
```
|
||||
|
||||
Services:
|
||||
|
||||
| Service | Purpose |
|
||||
| --------------------- | --------------------------------------------------------------------------------------- |
|
||||
| `minio` | Runs the S3-compatible object storage server. |
|
||||
| `minio_create_bucket` | One-shot setup container that creates the bucket and enables anonymous download access. |
|
||||
|
||||
MinIO console:
|
||||
|
||||
```txt
|
||||
http://localhost:9001
|
||||
```
|
||||
|
||||
Default local credentials:
|
||||
|
||||
```txt
|
||||
user: minioadmin
|
||||
pass: minioadmin
|
||||
```
|
||||
|
||||
The `minio_create_bucket` container is expected to exit after setup. A stopped container with successful bucket logs is normal.
|
||||
|
||||
To rebuild after dependency or Dockerfile changes:
|
||||
|
||||
```sh
|
||||
docker compose build --no-cache
|
||||
docker compose up
|
||||
```
|
||||
|
||||
## Response Shape
|
||||
|
||||
Directory and file operations return `Entry` objects:
|
||||
|
||||
```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 include pagination metadata:
|
||||
|
||||
```ts
|
||||
{
|
||||
data: Entry[];
|
||||
meta: {
|
||||
nextPaginationToken: string | null;
|
||||
};
|
||||
}
|
||||
```
|
||||
|
||||
## Backend Change Checklist
|
||||
|
||||
Before changing backend behavior:
|
||||
|
||||
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 response shape changes.
|
||||
5. Update this documentation when routes, permissions, storage contracts, or response shapes change.
|
||||
Reference in New Issue
Block a user