/** * Consent Management API Routes * * Handles social media platform listings and consent management */ const express = require('express'); const router = express.Router(); const GroupRepository = require('../repositories/GroupRepository'); const SocialMediaRepository = require('../repositories/SocialMediaRepository'); const dbManager = require('../database/DatabaseManager'); // ============================================================================ // Social Media Platforms // ============================================================================ /** * GET /api/social-media/platforms * Liste aller aktiven Social Media Plattformen */ router.get('/social-media/platforms', async (req, res) => { try { const socialMediaRepo = new SocialMediaRepository(dbManager); const platforms = await socialMediaRepo.getActivePlatforms(); res.json(platforms); } catch (error) { console.error('Error fetching platforms:', error); res.status(500).json({ error: 'Failed to fetch social media platforms', message: error.message }); } }); // ============================================================================ // Group Consents // ============================================================================ /** * POST /api/groups/:groupId/consents * Speichere oder aktualisiere Consents für eine Gruppe * * Body: { * workshopConsent: boolean, * socialMediaConsents: [{ platformId: number, consented: boolean }] * } */ router.post('/groups/:groupId/consents', async (req, res) => { try { const { groupId } = req.params; const { workshopConsent, socialMediaConsents } = req.body; // Validierung if (typeof workshopConsent !== 'boolean') { return res.status(400).json({ error: 'Invalid request', message: 'workshopConsent must be a boolean' }); } if (!Array.isArray(socialMediaConsents)) { return res.status(400).json({ error: 'Invalid request', message: 'socialMediaConsents must be an array' }); } // Prüfe ob Gruppe existiert const group = await GroupRepository.getGroupById(groupId); if (!group) { return res.status(404).json({ error: 'Group not found', message: `No group found with ID: ${groupId}` }); } // Aktualisiere Consents await GroupRepository.updateConsents( groupId, workshopConsent, socialMediaConsents ); res.json({ success: true, message: 'Consents updated successfully', groupId }); } catch (error) { console.error('Error updating consents:', error); res.status(500).json({ error: 'Failed to update consents', message: error.message }); } }); /** * GET /api/groups/:groupId/consents * Lade alle Consents für eine Gruppe */ router.get('/groups/:groupId/consents', async (req, res) => { try { const { groupId } = req.params; // Hole Gruppe mit Consents const group = await GroupRepository.getGroupWithConsents(groupId); if (!group) { return res.status(404).json({ error: 'Group not found', message: `No group found with ID: ${groupId}` }); } // Formatiere Response const response = { groupId: group.group_id, workshopConsent: group.display_in_workshop === 1, consentTimestamp: group.consent_timestamp, socialMediaConsents: group.consents.map(c => ({ platformId: c.platform_id, platformName: c.platform_name, displayName: c.display_name, iconName: c.icon_name, consented: c.consented === 1, consentTimestamp: c.consent_timestamp, revoked: c.revoked === 1, revokedTimestamp: c.revoked_timestamp })) }; res.json(response); } catch (error) { console.error('Error fetching consents:', error); res.status(500).json({ error: 'Failed to fetch consents', message: error.message }); } }); // ============================================================================ // Admin - Filtering & Export // ============================================================================ /** * GET /api/admin/groups/by-consent * Filtere Gruppen nach Consent-Status * * Query params: * - displayInWorkshop: boolean * - platformId: number * - platformConsent: boolean */ router.get('/admin/groups/by-consent', async (req, res) => { try { const filters = {}; // Parse query parameters if (req.query.displayInWorkshop !== undefined) { filters.displayInWorkshop = req.query.displayInWorkshop === 'true'; } if (req.query.platformId !== undefined) { filters.platformId = parseInt(req.query.platformId, 10); if (isNaN(filters.platformId)) { return res.status(400).json({ error: 'Invalid platformId', message: 'platformId must be a number' }); } } if (req.query.platformConsent !== undefined) { filters.platformConsent = req.query.platformConsent === 'true'; } // Hole gefilterte Gruppen const groups = await GroupRepository.getGroupsByConsentStatus(filters); res.json({ count: groups.length, filters, groups }); } catch (error) { console.error('Error filtering groups by consent:', error); res.status(500).json({ error: 'Failed to filter groups', message: error.message }); } }); /** * GET /api/admin/consents/export * Export Consent-Daten für rechtliche Dokumentation * * Query params: * - format: 'json' | 'csv' (default: json) * - year: number (optional filter) * - approved: boolean (optional filter) */ router.get('/admin/consents/export', async (req, res) => { try { const format = req.query.format || 'json'; const filters = {}; // Parse filters if (req.query.year) { filters.year = parseInt(req.query.year, 10); } if (req.query.approved !== undefined) { filters.approved = req.query.approved === 'true'; } // Export Daten holen const exportData = await GroupRepository.exportConsentData(filters); // Format: JSON if (format === 'json') { res.json({ exportDate: new Date().toISOString(), filters, count: exportData.length, data: exportData }); return; } // Format: CSV if (format === 'csv') { // CSV Header let csv = 'group_id,year,title,name,upload_date,workshop_consent,consent_timestamp,approved'; // Sammle alle möglichen Plattformen const allPlatforms = new Set(); exportData.forEach(group => { group.socialMediaConsents.forEach(consent => { allPlatforms.add(consent.platform_name); }); }); // Füge Platform-Spalten hinzu const platformNames = Array.from(allPlatforms).sort(); platformNames.forEach(platform => { csv += `,${platform}`; }); csv += '\n'; // CSV Daten exportData.forEach(group => { const row = [ group.group_id, group.year, `"${(group.title || '').replace(/"/g, '""')}"`, `"${(group.name || '').replace(/"/g, '""')}"`, group.upload_date, group.display_in_workshop === 1 ? 'true' : 'false', group.consent_timestamp || '', group.approved === 1 ? 'true' : 'false' ]; // Platform-Consents const consentMap = {}; group.socialMediaConsents.forEach(consent => { consentMap[consent.platform_name] = consent.consented === 1; }); platformNames.forEach(platform => { row.push(consentMap[platform] ? 'true' : 'false'); }); csv += row.join(',') + '\n'; }); res.setHeader('Content-Type', 'text/csv'); res.setHeader('Content-Disposition', `attachment; filename=consent-export-${Date.now()}.csv`); res.send(csv); return; } res.status(400).json({ error: 'Invalid format', message: 'Format must be "json" or "csv"' }); } catch (error) { console.error('Error exporting consent data:', error); res.status(500).json({ error: 'Failed to export consent data', message: error.message }); } }); module.exports = router;