369 lines
11 KiB
Markdown
369 lines
11 KiB
Markdown
# 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.
|