# 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 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/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 apps/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.