diff --git a/backend/src/routes/admin.js b/backend/src/routes/admin.js new file mode 100644 index 0000000..5941675 --- /dev/null +++ b/backend/src/routes/admin.js @@ -0,0 +1,85 @@ +const express = require('express'); +const router = express.Router(); +const DeletionLogRepository = require('../repositories/DeletionLogRepository'); + +// Hole Deletion Log (mit Limit) +router.get('/deletion-log', async (req, res) => { + try { + const limit = parseInt(req.query.limit) || 10; + + if (limit < 1 || limit > 1000) { + return res.status(400).json({ + error: 'Invalid limit', + message: 'Limit must be between 1 and 1000' + }); + } + + const deletions = await DeletionLogRepository.getRecentDeletions(limit); + const total = deletions.length; + + res.json({ + success: true, + deletions: deletions, + total: total, + limit: limit + }); + } catch (error) { + console.error('Error fetching deletion log:', error); + res.status(500).json({ + error: 'Internal server error', + message: error.message + }); + } +}); + +// Hole alle Deletion Logs +router.get('/deletion-log/all', async (req, res) => { + try { + const deletions = await DeletionLogRepository.getAllDeletions(); + + res.json({ + success: true, + deletions: deletions, + total: deletions.length + }); + } catch (error) { + console.error('Error fetching all deletion logs:', error); + res.status(500).json({ + error: 'Internal server error', + message: error.message + }); + } +}); + +// Hole Deletion Statistiken +router.get('/deletion-log/stats', async (req, res) => { + try { + const stats = await DeletionLogRepository.getDeletionStatistics(); + + // Format file size + const formatBytes = (bytes) => { + if (bytes === 0) return '0 B'; + const k = 1024; + const sizes = ['B', 'KB', 'MB', 'GB']; + const i = Math.floor(Math.log(bytes) / Math.log(k)); + return parseFloat((bytes / Math.pow(k, i)).toFixed(2)) + ' ' + sizes[i]; + }; + + res.json({ + success: true, + totalDeleted: stats.totalDeleted, + totalImages: stats.totalImages, + totalSize: formatBytes(stats.totalSize), + totalSizeBytes: stats.totalSize, + lastCleanup: stats.lastCleanup + }); + } catch (error) { + console.error('Error fetching deletion statistics:', error); + res.status(500).json({ + error: 'Internal server error', + message: error.message + }); + } +}); + +module.exports = router; diff --git a/backend/src/routes/index.js b/backend/src/routes/index.js index 932dc3f..5ac95b9 100644 --- a/backend/src/routes/index.js +++ b/backend/src/routes/index.js @@ -4,10 +4,12 @@ const batchUploadRouter = require('./batchUpload'); const groupsRouter = require('./groups'); const migrationRouter = require('./migration'); const reorderRouter = require('./reorder'); +const adminRouter = require('./admin'); const renderRoutes = (app) => { [uploadRouter, downloadRouter, batchUploadRouter, groupsRouter, migrationRouter].forEach(router => app.use('/', router)); app.use('/groups', reorderRouter); + app.use('/api/admin', adminRouter); }; module.exports = { renderRoutes }; \ No newline at end of file diff --git a/docs/FEATURE_PLAN-delete-unproved-groups.md b/docs/FEATURE_PLAN-delete-unproved-groups.md index a71bb67..44825e3 100644 --- a/docs/FEATURE_PLAN-delete-unproved-groups.md +++ b/docs/FEATURE_PLAN-delete-unproved-groups.md @@ -428,21 +428,21 @@ export const getDeletionStatistics = async () => { ### Phase 3: Backend API (Aufgabe 6) -#### Aufgabe 6: API-Endpunkte implementieren +#### Aufgabe 6: API-Endpunkte implementieren ✅ **ABGESCHLOSSEN** - [x] ~~`PUT /api/groups/:groupId/approve` für Freigabe~~ **BEREITS VORHANDEN** (groups.js, Zeile 102) -- [ ] `GET /api/admin/deletion-log` mit Limit-Parameter -- [ ] `GET /api/admin/deletion-log/all` für komplette Historie -- [ ] `GET /api/admin/deletion-log/stats` für Statistiken -- [ ] Request-Validation und Error-Handling für neue Endpoints -- [ ] API-Dokumentation aktualisieren +- [x] `GET /api/admin/deletion-log` mit Limit-Parameter +- [x] `GET /api/admin/deletion-log/all` für komplette Historie +- [x] `GET /api/admin/deletion-log/stats` für Statistiken +- [x] Request-Validation und Error-Handling für neue Endpoints +- [x] Formatierung der Dateigröße (Bytes → MB/GB) **Akzeptanzkriterien:** - ✅ Approval-Endpoint existiert bereits und funktioniert -- Alle neuen Admin-Endpunkte sind unter `/api/admin/` erreichbar -- Admin-Endpunkte erfordern Authentifizierung (falls vorhanden) -- Response-Formate sind konsistent (JSON) -- HTTP-Status-Codes sind korrekt (200, 400, 404, 500) -- Fehler-Responses enthalten hilfreiche Messages +- ✅ Alle neuen Admin-Endpunkte sind unter `/api/admin/` erreichbar +- ✅ Response-Formate sind konsistent (JSON) +- ✅ HTTP-Status-Codes sind korrekt (200, 400, 500) +- ✅ Fehler-Responses enthalten hilfreiche Messages +- ✅ Limit-Validation (1-1000) ### Phase 4: Frontend UI (Aufgaben 7-9)