11 KiB
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:
backend/app/base_modules/FileManager/
Request Flow
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:
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:
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:
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:
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:
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
s3disk. - 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:
.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:
fs
s3
The active adapter is selected by DRIVE_DISK.
DRIVE_DISK=fs
or:
DRIVE_DISK=s3
Drive Configuration
Adonis Drive config lives in:
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:
forcePathStyle: true;
The adapter also disables ACL API calls:
supportsACL: false;
Bucket public-read behavior is handled by the Docker bucket setup container.
Local S3 Simulation
Local S3 is simulated with MinIO in:
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:
http://localhost:9001
Default local credentials:
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:
docker compose build --no-cache
docker compose up
Response Shape
Directory and file operations return Entry objects:
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:
{
data: Entry[];
meta: {
nextPaginationToken: string | null;
};
}
Backend Change Checklist
Before changing backend behavior:
- Confirm the policy ability for the operation.
- Add or update a validator for all request input.
- Keep client paths and storage paths separated through
path_service.ts. - Update the frontend DTO or mapper if response shape changes.
- Update this documentation when routes, permissions, storage contracts, or response shapes change.