AI Implementation feature(885): Admin Area General Settings and Categories 1.03 #25
+48
-11
@@ -1,33 +1,70 @@
|
||||
---
|
||||
type: api
|
||||
title: Uploads Endpoints
|
||||
description: Admin-only multipart upload endpoints for category icons and challenge files.
|
||||
description: Admin-only multipart upload endpoints for site logos, category icons, and challenge files.
|
||||
tags: [api, uploads, multipart, admin]
|
||||
timestamp: 2026-07-21T18:28:00Z
|
||||
timestamp: 2026-07-22T13:05:30Z
|
||||
---
|
||||
|
||||
# Endpoints
|
||||
|
||||
| Method | Path | Auth | Source |
|
||||
|--------|---------------------------------------|-------|---------------------------------------------------------|
|
||||
| `POST` | `/api/v1/uploads/category-icon` | Admin | `backend/src/modules/uploads/uploads.controller.ts` |
|
||||
| `POST` | `/api/v1/uploads/logo` | Admin | `backend/src/modules/uploads/uploads.controller.ts` |
|
||||
| `POST` | `/api/v1/uploads/category-icon` | Admin | Same. |
|
||||
| `POST` | `/api/v1/uploads/challenge-file` | Admin | Same. |
|
||||
|
||||
# Guard chain
|
||||
|
||||
Both handlers are gated by `JwtAuthGuard` + `AdminGuard`. CSRF is enforced
|
||||
(standard cookie + header pattern; nothing is added to the skip list).
|
||||
All handlers are gated by the controller-level `AdminGuard` and `admin` role.
|
||||
The global authentication and CSRF protections also apply; clients must send a
|
||||
valid admin session and the standard CSRF cookie/header pair.
|
||||
|
||||
# Behavior
|
||||
|
||||
* Each endpoint uses `FileInterceptor('file')` and parses a single
|
||||
multipart part named `file`.
|
||||
* File size is validated by `parseUploadSizeLimit()` in
|
||||
`backend/src/common/utils/upload.ts`.
|
||||
* Filenames are sanitized by the same helper before being persisted
|
||||
under `UPLOAD_DIR`.
|
||||
* Each endpoint uses `FileInterceptor('file')` and parses a single multipart
|
||||
part named `file`.
|
||||
* File size is validated against `UPLOAD_SIZE_LIMIT` through
|
||||
`parseUploadSizeLimit()` in `backend/src/common/utils/upload.ts`.
|
||||
* Category icons are written under `UPLOAD_DIR/icons`; when `categoryId` is
|
||||
supplied, the image is cropped to a 128-by-128 PNG and exposed at
|
||||
`/uploads/icons/{categoryId}.png`.
|
||||
* Challenge attachments are written under `UPLOAD_DIR/challenges` and exposed
|
||||
at `/uploads/challenges/{safeFilename}`.
|
||||
* Site logos are decoded with Sharp and accepted only when their actual format
|
||||
is PNG, JPEG, GIF, or WebP. The multipart MIME type and filename extension
|
||||
are not trusted for validation.
|
||||
* An accepted logo keeps its sanitized filename, is written directly under
|
||||
`UPLOAD_DIR`, and returns `{ publicUrl, originalFilename }`, with `publicUrl`
|
||||
in the form `/uploads/{safeFilename}`.
|
||||
* A missing `file` part, an oversized upload, a corrupt image, or a decoded logo
|
||||
in another format returns `400 Bad Request`. Invalid logo payloads use the
|
||||
message `Logo must be a valid PNG, JPEG, GIF, or WebP image.` and are not
|
||||
persisted.
|
||||
|
||||
# Examples
|
||||
|
||||
1. Sign in as an administrator and navigate to `/admin/general`.
|
||||
2. In the site-logo setting, choose a PNG, JPEG, GIF, or WebP image and save the
|
||||
general settings.
|
||||
3. The client uploads the selected file to `POST /api/v1/uploads/logo` before
|
||||
saving the returned `/uploads/...` URL as the configured logo.
|
||||
4. After a successful save, the uploaded image is available from its returned
|
||||
public URL and is used wherever the configured site logo is rendered.
|
||||
5. Choosing a corrupt file, or a valid image in an unsupported format, leaves
|
||||
the file unstored and surfaces the upload validation failure to the user.
|
||||
|
||||
# Key files
|
||||
|
||||
| File | Responsibility |
|
||||
|---|---|
|
||||
| `backend/src/modules/uploads/uploads.controller.ts` | Registers upload routes, validates payloads, and persists files. |
|
||||
| `backend/src/common/utils/upload.ts` | Parses size limits and sanitizes upload filenames. |
|
||||
| `frontend/src/app/features/admin/general/admin-general.component.ts` | Provides the administrator-facing logo selection and settings workflow. |
|
||||
| `tests/backend/uploads-logo.spec.ts` | Verifies accepted logo formats, spoofed/corrupt payload rejection, size limits, and persisted responses. |
|
||||
|
||||
# See also
|
||||
|
||||
- [Admin — General Settings](/guides/admin-general-settings.md)
|
||||
- [REST API Overview](/api/rest-overview.md)
|
||||
- [Backend Module Map](/architecture/backend-modules.md)
|
||||
|
||||
@@ -1,7 +1,7 @@
|
||||
---
|
||||
type: architecture
|
||||
title: Key Files Index
|
||||
description: One-line responsibility for important source files, including authenticated event streaming.
|
||||
description: One-line responsibility for important source files, including authenticated event streaming and validated site-logo uploads.
|
||||
tags: [architecture, index, key-files]
|
||||
timestamp: 2026-07-22T10:32:00Z
|
||||
---
|
||||
@@ -22,6 +22,7 @@ timestamp: 2026-07-22T10:32:00Z
|
||||
| `backend/src/modules/system/system.service.ts` | Builds the public bootstrap payload. |
|
||||
| `backend/src/modules/auth/auth.controller.ts` | Registers authentication and account endpoints. |
|
||||
| `backend/src/modules/auth/auth.service.ts` | Handles sessions, authentication, registration, and password changes. |
|
||||
| `backend/src/modules/uploads/uploads.controller.ts` | Registers admin-only multipart uploads, including Sharp-backed site-logo format validation. |
|
||||
|
||||
# Frontend
|
||||
|
||||
|
||||
+1
-1
@@ -49,7 +49,7 @@ they need. Last regenerated 2026-07-22T12:44:45Z.
|
||||
* [System Endpoints](/api/system.md) - Bootstrap, event status, public SSE
|
||||
streams, public event-window settings, and the authenticated
|
||||
`/events/status` SSE stream.
|
||||
* [Uploads Endpoints](/api/uploads.md) - Admin-only multipart uploads.
|
||||
* [Uploads Endpoints](/api/uploads.md) - Admin-only multipart uploads for category icons, challenge files, and validated site logos.
|
||||
|
||||
# Guides
|
||||
|
||||
|
||||
Reference in New Issue
Block a user