fix: Update Swagger Grouping
This commit is contained in:
parent
6332b82c6a
commit
7a14c239d4
|
|
@ -15,7 +15,6 @@ Im Rahmen der OpenAPI-Auto-Generation wurden **massive Änderungen** an der API-
|
|||
- **`backend/src/routes/README.md`** - Vollständige API-Route-Dokumentation
|
||||
- **`AUTHENTICATION.md`** - Auth-System-Setup und Verwendung
|
||||
|
||||
**Geschätzter Migrations-Aufwand**: 2-3 Stunden
|
||||
|
||||
---
|
||||
|
||||
|
|
@ -34,7 +33,7 @@ docker compose -f docker/dev/docker-compose.yml up -d
|
|||
### Zugriff
|
||||
- **Frontend**: http://localhost:3000 (Hot Module Reloading aktiv)
|
||||
- **Backend**: http://localhost:5001 (API)
|
||||
- **API Documentation**: http://localhost:5001/api/docs (Swagger UI)
|
||||
- **API Documentation**: http://localhost:5001/api/docs/ (Swagger UI)
|
||||
- **Slideshow**: http://localhost:3000/slideshow
|
||||
- **Moderation**: http://localhost:3000/moderation (Login über Admin Session)
|
||||
|
||||
|
|
@ -116,6 +115,8 @@ Router mit spezifischen Routes **vor** generischen Routes mounten!
|
|||
```
|
||||
|
||||
2. **Management Portal (UUID Token)**:
|
||||
User, die Bilder hochladen, erhalten automatisch einen UUID-Token für das Self-Service Management Portal.
|
||||
Über diesen Token / Link können sie ihre hochgeladenen Gruppen verwalten:
|
||||
```bash
|
||||
# Automatisch beim Upload generiert
|
||||
GET /api/manage/550e8400-e29b-41d4-a716-446655440000
|
||||
|
|
@ -125,12 +126,8 @@ Router mit spezifischen Routes **vor** generischen Routes mounten!
|
|||
|
||||
#### Admin-Hinweise: Logout & neue Nutzer
|
||||
|
||||
- **Logout:** Bis ein eigener Button im UI existiert, kann die Session jederzeit über den vorhandenen Endpoint beendet werden, z. B. in der Browser-Konsole:
|
||||
```js
|
||||
await fetch('/auth/logout', { method: 'POST', credentials: 'include' });
|
||||
```
|
||||
Alternativ per CLI: `curl -b cookies.txt -X POST http://localhost:5001/auth/logout`. Danach ist das `sid`-Cookie entfernt und die Moderationsseite zeigt wieder den Login.
|
||||
- **Weiterer Admin:** `npm run create-admin -- --username zweiteradmin --password 'SuperPasswort123!' [--role admin --require-password-change]` oder alternativ `./scripts/create_admin_user.sh --username zweiteradmin --password 'SuperPasswort123!' [...]` ruft das Skript (`backend/src/scripts/createAdminUser.js`) auf und legt einen weiteren User an. Das Skript prüft Duplikate, nutzt dieselben Bcrypt-Runden wie das Backend und kann bei Bedarf weiterhin über die DB nachvollzogen werden. Falls du lieber manuell arbeitest, kannst du wie bisher einen Hash erzeugen und direkt in `admin_users` einfügen.
|
||||
- **Logout:** Der Moderationsbereich enthält jetzt einen Logout-Button (Icon in der Kopfzeile). Klick → `POST /auth/logout` → Session beendet, Login erscheint erneut. Für Skripte kannst du weiterhin `curl -b cookies.txt -X POST http://localhost:5001/auth/logout` verwenden.
|
||||
- **Weiterer Admin:** Verwende das neue API-basierte Skript `./scripts/create_admin_user.sh --server http://localhost:5001 --username zweiteradmin --password 'SuperPasswort123!' [--admin-user bestehend --admin-password ... --role ... --require-password-change]`. Das Skript erledigt Login, CSRF, Duplikats-Check und legt zusätzliche Admins über `/api/admin/users` an (Fallback: `backend/src/scripts/createAdminUser.js`).
|
||||
|
||||
### OpenAPI-Spezifikation
|
||||
|
||||
|
|
|
|||
|
|
@ -12,15 +12,24 @@
|
|||
}
|
||||
],
|
||||
"tags": [
|
||||
{
|
||||
"name": "Admin Authentication"
|
||||
},
|
||||
{
|
||||
"name": "Upload"
|
||||
},
|
||||
{
|
||||
"name": "Management Portal"
|
||||
"name": "Download"
|
||||
},
|
||||
{
|
||||
"name": "Public Groups"
|
||||
},
|
||||
{
|
||||
"name": "Consent Management"
|
||||
},
|
||||
{
|
||||
"name": "Management Portal"
|
||||
},
|
||||
{
|
||||
"name": "Admin - Users"
|
||||
},
|
||||
|
|
@ -43,7 +52,11 @@
|
|||
"paths": {
|
||||
"/auth/setup/status": {
|
||||
"get": {
|
||||
"description": "",
|
||||
"tags": [
|
||||
"Admin Authentication"
|
||||
],
|
||||
"summary": "Check onboarding status",
|
||||
"description": "Returns whether the initial admin setup is still pending and if a session already exists.",
|
||||
"responses": {
|
||||
"200": {
|
||||
"description": "OK"
|
||||
|
|
@ -56,7 +69,11 @@
|
|||
},
|
||||
"/auth/setup/initial-admin": {
|
||||
"post": {
|
||||
"description": "",
|
||||
"tags": [
|
||||
"Admin Authentication"
|
||||
],
|
||||
"summary": "Complete initial admin setup",
|
||||
"description": "Creates the very first admin account and immediately starts a session.",
|
||||
"parameters": [
|
||||
{
|
||||
"name": "body",
|
||||
|
|
@ -92,7 +109,11 @@
|
|||
},
|
||||
"/auth/login": {
|
||||
"post": {
|
||||
"description": "",
|
||||
"tags": [
|
||||
"Admin Authentication"
|
||||
],
|
||||
"summary": "Admin login",
|
||||
"description": "Starts a server-side admin session and returns a CSRF token.",
|
||||
"parameters": [
|
||||
{
|
||||
"name": "body",
|
||||
|
|
@ -131,7 +152,11 @@
|
|||
},
|
||||
"/auth/logout": {
|
||||
"post": {
|
||||
"description": "",
|
||||
"tags": [
|
||||
"Admin Authentication"
|
||||
],
|
||||
"summary": "Terminate admin session",
|
||||
"description": "Destroys the current session and clears the sid cookie.",
|
||||
"responses": {
|
||||
"204": {
|
||||
"description": "No Content"
|
||||
|
|
@ -144,7 +169,11 @@
|
|||
},
|
||||
"/auth/csrf-token": {
|
||||
"get": {
|
||||
"description": "",
|
||||
"tags": [
|
||||
"Admin Authentication"
|
||||
],
|
||||
"summary": "Fetch CSRF token",
|
||||
"description": "Returns a CSRF token for the active admin session (session required).",
|
||||
"responses": {
|
||||
"200": {
|
||||
"description": "OK"
|
||||
|
|
@ -157,7 +186,11 @@
|
|||
},
|
||||
"/auth/change-password": {
|
||||
"post": {
|
||||
"description": "",
|
||||
"tags": [
|
||||
"Admin Authentication"
|
||||
],
|
||||
"summary": "Change admin password",
|
||||
"description": "Allows a logged-in admin to rotate their password (CSRF protected).",
|
||||
"parameters": [
|
||||
{
|
||||
"name": "x-csrf-token",
|
||||
|
|
@ -297,25 +330,40 @@
|
|||
},
|
||||
"/api/download/{id}": {
|
||||
"get": {
|
||||
"tags": [
|
||||
"Download"
|
||||
],
|
||||
"summary": "Download original image",
|
||||
"description": "",
|
||||
"parameters": [
|
||||
{
|
||||
"name": "id",
|
||||
"in": "path",
|
||||
"required": true,
|
||||
"type": "string"
|
||||
"type": "string",
|
||||
"description": "Filename of the uploaded image"
|
||||
}
|
||||
],
|
||||
"responses": {
|
||||
"default": {
|
||||
"description": ""
|
||||
"200": {
|
||||
"description": "Binary image response"
|
||||
},
|
||||
"404": {
|
||||
"description": "File not found"
|
||||
}
|
||||
}
|
||||
}
|
||||
},
|
||||
"/api/upload/batch": {
|
||||
"post": {
|
||||
"description": "",
|
||||
"tags": [
|
||||
"Upload"
|
||||
],
|
||||
"summary": "Batch upload multiple images",
|
||||
"description": "Accepts multiple images + metadata/consents and creates a managed group with management token.",
|
||||
"consumes": [
|
||||
"multipart/form-data"
|
||||
],
|
||||
"parameters": [
|
||||
{
|
||||
"name": "body",
|
||||
|
|
@ -341,57 +389,98 @@
|
|||
],
|
||||
"responses": {
|
||||
"200": {
|
||||
"description": "OK"
|
||||
"description": "Batch upload successful (returns management token)"
|
||||
},
|
||||
"400": {
|
||||
"description": "Bad Request"
|
||||
"description": "Missing files or workshop consent"
|
||||
},
|
||||
"500": {
|
||||
"description": "Internal Server Error"
|
||||
"description": "Unexpected server error"
|
||||
}
|
||||
}
|
||||
}
|
||||
},
|
||||
"/api/groups": {
|
||||
"get": {
|
||||
"description": "",
|
||||
"tags": [
|
||||
"Public Groups"
|
||||
],
|
||||
"summary": "Get approved groups with images",
|
||||
"description": "Returns all approved groups (slideshow feed). Automatically triggers JSON→SQLite migration if required.",
|
||||
"responses": {
|
||||
"200": {
|
||||
"description": "OK"
|
||||
"description": "List of approved groups",
|
||||
"schema": {
|
||||
"type": "object",
|
||||
"properties": {
|
||||
"groups": {
|
||||
"type": "array",
|
||||
"items": {
|
||||
"type": "object",
|
||||
"properties": {
|
||||
"groupId": {
|
||||
"type": "string",
|
||||
"example": "cTV24Yn-a"
|
||||
},
|
||||
"title": {
|
||||
"type": "string",
|
||||
"example": "Familie Mueller"
|
||||
}
|
||||
}
|
||||
}
|
||||
},
|
||||
"totalCount": {
|
||||
"type": "number",
|
||||
"example": 73
|
||||
}
|
||||
},
|
||||
"xml": {
|
||||
"name": "main"
|
||||
}
|
||||
}
|
||||
},
|
||||
"500": {
|
||||
"description": "Internal Server Error"
|
||||
"description": "Server error"
|
||||
}
|
||||
}
|
||||
}
|
||||
},
|
||||
"/api/groups/{groupId}": {
|
||||
"get": {
|
||||
"tags": [
|
||||
"Public Groups"
|
||||
],
|
||||
"summary": "Get approved group by ID",
|
||||
"description": "",
|
||||
"parameters": [
|
||||
{
|
||||
"name": "groupId",
|
||||
"in": "path",
|
||||
"required": true,
|
||||
"type": "string"
|
||||
"type": "string",
|
||||
"description": "Public groupId (e.g. cTV24Yn-a)"
|
||||
}
|
||||
],
|
||||
"responses": {
|
||||
"200": {
|
||||
"description": "OK"
|
||||
"description": "Group payload (images + metadata)"
|
||||
},
|
||||
"404": {
|
||||
"description": "Not Found"
|
||||
"description": "Group not found or not approved"
|
||||
},
|
||||
"500": {
|
||||
"description": "Internal Server Error"
|
||||
"description": "Server error"
|
||||
}
|
||||
}
|
||||
}
|
||||
},
|
||||
"/api/social-media/platforms": {
|
||||
"get": {
|
||||
"description": "",
|
||||
"tags": [
|
||||
"Consent Management"
|
||||
],
|
||||
"summary": "List active social media platforms",
|
||||
"description": "Public endpoint that exposes the available platforms for consent selection on the upload form.",
|
||||
"responses": {
|
||||
"200": {
|
||||
"description": "OK"
|
||||
|
|
@ -2483,13 +2572,18 @@
|
|||
},
|
||||
"/api/admin/{groupId}/reorder": {
|
||||
"put": {
|
||||
"tags": [
|
||||
"Admin - Groups Moderation"
|
||||
],
|
||||
"summary": "Reorder images within a group",
|
||||
"description": "",
|
||||
"parameters": [
|
||||
{
|
||||
"name": "groupId",
|
||||
"in": "path",
|
||||
"required": true,
|
||||
"type": "string"
|
||||
"type": "string",
|
||||
"description": "Admin groupId"
|
||||
},
|
||||
{
|
||||
"name": "body",
|
||||
|
|
@ -2506,19 +2600,19 @@
|
|||
],
|
||||
"responses": {
|
||||
"200": {
|
||||
"description": "OK"
|
||||
"description": "Order updated successfully"
|
||||
},
|
||||
"400": {
|
||||
"description": "Bad Request"
|
||||
"description": "Validation error"
|
||||
},
|
||||
"403": {
|
||||
"description": "Forbidden"
|
||||
},
|
||||
"404": {
|
||||
"description": "Not Found"
|
||||
"description": "Group not found"
|
||||
},
|
||||
"500": {
|
||||
"description": "Internal Server Error"
|
||||
"description": "Internal server error"
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -5,6 +5,11 @@ const { requireAdminAuth } = require('../middlewares/auth');
|
|||
const { requireCsrf } = require('../middlewares/csrf');
|
||||
|
||||
router.get('/setup/status', async (req, res) => {
|
||||
/*
|
||||
#swagger.tags = ['Admin Authentication']
|
||||
#swagger.summary = 'Check onboarding status'
|
||||
#swagger.description = 'Returns whether the initial admin setup is still pending and if a session already exists.'
|
||||
*/
|
||||
try {
|
||||
const needsSetup = await AdminAuthService.needsInitialSetup();
|
||||
const sessionUser = req.session && req.session.user
|
||||
|
|
@ -27,6 +32,11 @@ router.get('/setup/status', async (req, res) => {
|
|||
});
|
||||
|
||||
router.post('/setup/initial-admin', async (req, res) => {
|
||||
/*
|
||||
#swagger.tags = ['Admin Authentication']
|
||||
#swagger.summary = 'Complete initial admin setup'
|
||||
#swagger.description = 'Creates the very first admin account and immediately starts a session.'
|
||||
*/
|
||||
try {
|
||||
const { username, password } = req.body || {};
|
||||
if (!username || !password) {
|
||||
|
|
@ -67,6 +77,11 @@ router.post('/setup/initial-admin', async (req, res) => {
|
|||
});
|
||||
|
||||
router.post('/login', async (req, res) => {
|
||||
/*
|
||||
#swagger.tags = ['Admin Authentication']
|
||||
#swagger.summary = 'Admin login'
|
||||
#swagger.description = 'Starts a server-side admin session and returns a CSRF token.'
|
||||
*/
|
||||
try {
|
||||
const { username, password } = req.body || {};
|
||||
if (!username || !password) {
|
||||
|
|
@ -100,6 +115,11 @@ router.post('/login', async (req, res) => {
|
|||
});
|
||||
|
||||
router.post('/logout', async (req, res) => {
|
||||
/*
|
||||
#swagger.tags = ['Admin Authentication']
|
||||
#swagger.summary = 'Terminate admin session'
|
||||
#swagger.description = 'Destroys the current session and clears the sid cookie.'
|
||||
*/
|
||||
try {
|
||||
await AdminAuthService.destroySession(req);
|
||||
res.clearCookie('sid');
|
||||
|
|
@ -111,6 +131,11 @@ router.post('/logout', async (req, res) => {
|
|||
});
|
||||
|
||||
router.get('/csrf-token', requireAdminAuth, (req, res) => {
|
||||
/*
|
||||
#swagger.tags = ['Admin Authentication']
|
||||
#swagger.summary = 'Fetch CSRF token'
|
||||
#swagger.description = 'Returns a CSRF token for the active admin session (session required).'
|
||||
*/
|
||||
if (!req.session.csrfToken) {
|
||||
req.session.csrfToken = AdminAuthService.generateCsrfToken();
|
||||
}
|
||||
|
|
@ -119,6 +144,11 @@ router.get('/csrf-token', requireAdminAuth, (req, res) => {
|
|||
});
|
||||
|
||||
router.post('/change-password', requireAdminAuth, requireCsrf, async (req, res) => {
|
||||
/*
|
||||
#swagger.tags = ['Admin Authentication']
|
||||
#swagger.summary = 'Change admin password'
|
||||
#swagger.description = 'Allows a logged-in admin to rotate their password (CSRF protected).'
|
||||
*/
|
||||
try {
|
||||
const { currentPassword, newPassword } = req.body || {};
|
||||
if (!currentPassword || !newPassword) {
|
||||
|
|
|
|||
|
|
@ -84,6 +84,15 @@ const router = Router();
|
|||
*/
|
||||
// Batch-Upload für mehrere Bilder
|
||||
router.post('/upload/batch', async (req, res) => {
|
||||
/*
|
||||
#swagger.tags = ['Upload']
|
||||
#swagger.summary = 'Batch upload multiple images'
|
||||
#swagger.description = 'Accepts multiple images + metadata/consents and creates a managed group with management token.'
|
||||
#swagger.consumes = ['multipart/form-data']
|
||||
#swagger.responses[200] = { description: 'Batch upload successful (returns management token)' }
|
||||
#swagger.responses[400] = { description: 'Missing files or workshop consent' }
|
||||
#swagger.responses[500] = { description: 'Unexpected server error' }
|
||||
*/
|
||||
try {
|
||||
// Überprüfe ob Dateien hochgeladen wurden
|
||||
if (!req.files || !req.files.images) {
|
||||
|
|
|
|||
|
|
@ -31,6 +31,18 @@ const router = Router();
|
|||
* description: File not found
|
||||
*/
|
||||
router.get('/download/:id', (req, res) => {
|
||||
/*
|
||||
#swagger.tags = ['Download']
|
||||
#swagger.summary = 'Download original image'
|
||||
#swagger.parameters['id'] = {
|
||||
in: 'path',
|
||||
required: true,
|
||||
type: 'string',
|
||||
description: 'Filename of the uploaded image'
|
||||
}
|
||||
#swagger.responses[200] = { description: 'Binary image response' }
|
||||
#swagger.responses[404] = { description: 'File not found' }
|
||||
*/
|
||||
const filePath = path.join(__dirname, '..', UPLOAD_FS_DIR, req.params.id);
|
||||
res.download(filePath);
|
||||
});
|
||||
|
|
|
|||
|
|
@ -4,54 +4,21 @@ const MigrationService = require('../services/MigrationService');
|
|||
|
||||
const router = Router();
|
||||
|
||||
/**
|
||||
* @swagger
|
||||
* /groups:
|
||||
* get:
|
||||
* tags: [Groups]
|
||||
* summary: Get all approved groups with images
|
||||
* description: Returns all approved groups with their images for public slideshow display. Automatically triggers migration if needed.
|
||||
* responses:
|
||||
* 200:
|
||||
* description: List of approved groups
|
||||
* content:
|
||||
* application/json:
|
||||
* schema:
|
||||
* type: object
|
||||
* properties:
|
||||
* groups:
|
||||
* type: array
|
||||
* items:
|
||||
* type: object
|
||||
* properties:
|
||||
* groupId:
|
||||
* type: string
|
||||
* example: "cTV24Yn-a"
|
||||
* year:
|
||||
* type: integer
|
||||
* example: 2024
|
||||
* title:
|
||||
* type: string
|
||||
* example: "Familie Mueller"
|
||||
* description:
|
||||
* type: string
|
||||
* name:
|
||||
* type: string
|
||||
* approved:
|
||||
* type: boolean
|
||||
* example: true
|
||||
* images:
|
||||
* type: array
|
||||
* items:
|
||||
* type: object
|
||||
* totalCount:
|
||||
* type: integer
|
||||
* example: 73
|
||||
* 500:
|
||||
* description: Server error
|
||||
*/
|
||||
// Alle Gruppen abrufen (für Slideshow mit vollständigen Bilddaten)
|
||||
router.get('/groups', async (req, res) => {
|
||||
/*
|
||||
#swagger.tags = ['Public Groups']
|
||||
#swagger.summary = 'Get approved groups with images'
|
||||
#swagger.description = 'Returns all approved groups (slideshow feed). Automatically triggers JSON→SQLite migration if required.'
|
||||
#swagger.responses[200] = {
|
||||
description: 'List of approved groups',
|
||||
schema: {
|
||||
groups: [{ groupId: 'cTV24Yn-a', title: 'Familie Mueller' }],
|
||||
totalCount: 73
|
||||
}
|
||||
}
|
||||
#swagger.responses[500] = { description: 'Server error' }
|
||||
*/
|
||||
try {
|
||||
// Auto-Migration beim ersten Zugriff
|
||||
const migrationStatus = await MigrationService.getMigrationStatus();
|
||||
|
|
@ -75,52 +42,21 @@ router.get('/groups', async (req, res) => {
|
|||
}
|
||||
});
|
||||
|
||||
/**
|
||||
* @swagger
|
||||
* /groups/{groupId}:
|
||||
* get:
|
||||
* tags: [Groups]
|
||||
* summary: Get a specific approved group by ID
|
||||
* description: Returns details of a single approved group with all its images
|
||||
* parameters:
|
||||
* - in: path
|
||||
* name: groupId
|
||||
* required: true
|
||||
* schema:
|
||||
* type: string
|
||||
* example: "cTV24Yn-a"
|
||||
* description: Unique identifier of the group
|
||||
* responses:
|
||||
* 200:
|
||||
* description: Group details
|
||||
* content:
|
||||
* application/json:
|
||||
* schema:
|
||||
* type: object
|
||||
* properties:
|
||||
* groupId:
|
||||
* type: string
|
||||
* year:
|
||||
* type: integer
|
||||
* title:
|
||||
* type: string
|
||||
* description:
|
||||
* type: string
|
||||
* name:
|
||||
* type: string
|
||||
* approved:
|
||||
* type: boolean
|
||||
* images:
|
||||
* type: array
|
||||
* items:
|
||||
* type: object
|
||||
* 404:
|
||||
* description: Group not found
|
||||
* 500:
|
||||
* description: Server error
|
||||
*/
|
||||
// Einzelne Gruppe abrufen (nur freigegebene)
|
||||
router.get('/groups/:groupId', async (req, res) => {
|
||||
/*
|
||||
#swagger.tags = ['Public Groups']
|
||||
#swagger.summary = 'Get approved group by ID'
|
||||
#swagger.parameters['groupId'] = {
|
||||
in: 'path',
|
||||
required: true,
|
||||
type: 'string',
|
||||
description: 'Public groupId (e.g. cTV24Yn-a)'
|
||||
}
|
||||
#swagger.responses[200] = { description: 'Group payload (images + metadata)' }
|
||||
#swagger.responses[404] = { description: 'Group not found or not approved' }
|
||||
#swagger.responses[500] = { description: 'Server error' }
|
||||
*/
|
||||
try {
|
||||
const { groupId } = req.params;
|
||||
const group = await GroupRepository.getGroupById(groupId);
|
||||
|
|
|
|||
|
|
@ -70,6 +70,20 @@ router.use(requireCsrf);
|
|||
* description: Server error during reordering
|
||||
*/
|
||||
router.put('/:groupId/reorder', async (req, res) => {
|
||||
/*
|
||||
#swagger.tags = ['Admin - Groups Moderation']
|
||||
#swagger.summary = 'Reorder images within a group'
|
||||
#swagger.parameters['groupId'] = {
|
||||
in: 'path',
|
||||
required: true,
|
||||
type: 'string',
|
||||
description: 'Admin groupId'
|
||||
}
|
||||
#swagger.responses[200] = { description: 'Order updated successfully' }
|
||||
#swagger.responses[400] = { description: 'Validation error' }
|
||||
#swagger.responses[404] = { description: 'Group not found' }
|
||||
#swagger.responses[500] = { description: 'Internal server error' }
|
||||
*/
|
||||
try {
|
||||
const { groupId } = req.params;
|
||||
const { imageIds } = req.body;
|
||||
|
|
|
|||
|
|
@ -8,6 +8,11 @@ const router = express.Router();
|
|||
* Public endpoint: list active social media platforms for consent selection
|
||||
*/
|
||||
router.get('/social-media/platforms', async (req, res) => {
|
||||
/*
|
||||
#swagger.tags = ['Consent Management']
|
||||
#swagger.summary = 'List active social media platforms'
|
||||
#swagger.description = 'Public endpoint that exposes the available platforms for consent selection on the upload form.'
|
||||
*/
|
||||
try {
|
||||
const socialMediaRepo = new SocialMediaRepository(dbManager);
|
||||
const platforms = await socialMediaRepo.getActivePlatforms();
|
||||
|
|
|
|||
|
|
@ -15,7 +15,7 @@ RUN npm install --production
|
|||
COPY backend/src ./src
|
||||
|
||||
# Copy production environment configuration
|
||||
COPY docker/prod/backend/config/.env ./.env
|
||||
#COPY docker/prod/backend/config/.env ./.env
|
||||
|
||||
# Create data directories for file storage
|
||||
RUN mkdir -p src/data/images src/data/previews src/data/groups
|
||||
|
|
|
|||
|
|
@ -34,8 +34,9 @@ services:
|
|||
networks:
|
||||
- prod-internal
|
||||
environment:
|
||||
- REMOVE_IMAGES=false
|
||||
- NODE_ENV=production
|
||||
- ADMIN_SESSION_SECRET=${ADMIN_SESSION_SECRET}
|
||||
- ADMIN_SESSION_SECRET=MvFhivVIPIXvSGvWGfGOiQCkUJrmUsjWQTNGUgnSmtpsGHQlKruTBEBZgbVvOHHr
|
||||
- ADMIN_SESSION_DIR=/usr/src/app/src/data/sessions
|
||||
|
||||
networks:
|
||||
|
|
|
|||
Loading…
Reference in New Issue
Block a user