Update language, add LICENSE and README
All checks were successful
Build & Push Docker Image / build (push) Successful in 1m9s

This commit is contained in:
2026-02-24 21:04:19 +01:00
parent 2ef6a9f30b
commit 7426ae8088
8 changed files with 668 additions and 106 deletions

View File

@@ -46,7 +46,7 @@ router.get('/', authenticateToken, async (req, res) => {
res.json({ rooms: [...ownRooms, ...sharedRooms] });
} catch (err) {
console.error('List rooms error:', err);
res.status(500).json({ error: 'Räume konnten nicht geladen werden' });
res.status(500).json({ error: 'Rooms could not be loaded' });
}
});
@@ -68,7 +68,7 @@ router.get('/users/search', authenticateToken, async (req, res) => {
res.json({ users });
} catch (err) {
console.error('Search users error:', err);
res.status(500).json({ error: 'Benutzersuche fehlgeschlagen' });
res.status(500).json({ error: 'User search failed' });
}
});
@@ -84,14 +84,14 @@ router.get('/:uid', authenticateToken, async (req, res) => {
`, [req.params.uid]);
if (!room) {
return res.status(404).json({ error: 'Raum nicht gefunden' });
return res.status(404).json({ error: 'Room not found' });
}
// Check access: owner, admin, or shared
if (room.user_id !== req.user.id && req.user.role !== 'admin') {
const share = await db.get('SELECT id FROM room_shares WHERE room_id = ? AND user_id = ?', [room.id, req.user.id]);
if (!share) {
return res.status(403).json({ error: 'Keine Berechtigung' });
return res.status(403).json({ error: 'No permission' });
}
room.shared = 1;
}
@@ -107,7 +107,7 @@ router.get('/:uid', authenticateToken, async (req, res) => {
res.json({ room, sharedUsers });
} catch (err) {
console.error('Get room error:', err);
res.status(500).json({ error: 'Raum konnte nicht geladen werden' });
res.status(500).json({ error: 'Room could not be loaded' });
}
});
@@ -129,7 +129,7 @@ router.post('/', authenticateToken, async (req, res) => {
} = req.body;
if (!name || name.trim().length === 0) {
return res.status(400).json({ error: 'Raumname ist erforderlich' });
return res.status(400).json({ error: 'Room name is required' });
}
const uid = crypto.randomBytes(8).toString('hex');
@@ -158,7 +158,7 @@ router.post('/', authenticateToken, async (req, res) => {
res.status(201).json({ room });
} catch (err) {
console.error('Create room error:', err);
res.status(500).json({ error: 'Raum konnte nicht erstellt werden' });
res.status(500).json({ error: 'Room could not be created' });
}
});
@@ -169,7 +169,7 @@ router.put('/:uid', authenticateToken, async (req, res) => {
const room = await db.get('SELECT * FROM rooms WHERE uid = ? AND user_id = ?', [req.params.uid, req.user.id]);
if (!room) {
return res.status(404).json({ error: 'Raum nicht gefunden oder keine Berechtigung' });
return res.status(404).json({ error: 'Room not found or no permission' });
}
const {
@@ -220,7 +220,7 @@ router.put('/:uid', authenticateToken, async (req, res) => {
res.json({ room: updated });
} catch (err) {
console.error('Update room error:', err);
res.status(500).json({ error: 'Raum konnte nicht aktualisiert werden' });
res.status(500).json({ error: 'Room could not be updated' });
}
});
@@ -231,18 +231,18 @@ router.delete('/:uid', authenticateToken, async (req, res) => {
const room = await db.get('SELECT * FROM rooms WHERE uid = ?', [req.params.uid]);
if (!room) {
return res.status(404).json({ error: 'Raum nicht gefunden' });
return res.status(404).json({ error: 'Room not found' });
}
if (room.user_id !== req.user.id && req.user.role !== 'admin') {
return res.status(403).json({ error: 'Keine Berechtigung' });
return res.status(403).json({ error: 'No permission' });
}
await db.run('DELETE FROM rooms WHERE uid = ?', [req.params.uid]);
res.json({ message: 'Raum erfolgreich gelöscht' });
res.json({ message: 'Room deleted successfully' });
} catch (err) {
console.error('Delete room error:', err);
res.status(500).json({ error: 'Raum konnte nicht gelöscht werden' });
res.status(500).json({ error: 'Room could not be deleted' });
}
});
// GET /api/rooms/:uid/shares - Get shared users for a room
@@ -251,7 +251,7 @@ router.get('/:uid/shares', authenticateToken, async (req, res) => {
const db = getDb();
const room = await db.get('SELECT * FROM rooms WHERE uid = ? AND user_id = ?', [req.params.uid, req.user.id]);
if (!room) {
return res.status(404).json({ error: 'Raum nicht gefunden oder keine Berechtigung' });
return res.status(404).json({ error: 'Room not found or no permission' });
}
const shares = await db.all(`
SELECT u.id, u.name, u.email, u.avatar_color, u.avatar_image
@@ -262,7 +262,7 @@ router.get('/:uid/shares', authenticateToken, async (req, res) => {
res.json({ shares });
} catch (err) {
console.error('Get shares error:', err);
res.status(500).json({ error: 'Fehler beim Laden der Freigaben' });
res.status(500).json({ error: 'Error loading shares' });
}
});
@@ -271,20 +271,20 @@ router.post('/:uid/shares', authenticateToken, async (req, res) => {
try {
const { user_id } = req.body;
if (!user_id) {
return res.status(400).json({ error: 'Benutzer-ID erforderlich' });
return res.status(400).json({ error: 'User ID is required' });
}
const db = getDb();
const room = await db.get('SELECT * FROM rooms WHERE uid = ? AND user_id = ?', [req.params.uid, req.user.id]);
if (!room) {
return res.status(404).json({ error: 'Raum nicht gefunden oder keine Berechtigung' });
return res.status(404).json({ error: 'Room not found or no permission' });
}
if (user_id === req.user.id) {
return res.status(400).json({ error: 'Du kannst den Raum nicht mit dir selbst teilen' });
return res.status(400).json({ error: 'You cannot share the room with yourself' });
}
// Check if already shared
const existing = await db.get('SELECT id FROM room_shares WHERE room_id = ? AND user_id = ?', [room.id, user_id]);
if (existing) {
return res.status(400).json({ error: 'Raum ist bereits mit diesem Benutzer geteilt' });
return res.status(400).json({ error: 'Room is already shared with this user' });
}
await db.run('INSERT INTO room_shares (room_id, user_id) VALUES (?, ?)', [room.id, user_id]);
const shares = await db.all(`
@@ -296,7 +296,7 @@ router.post('/:uid/shares', authenticateToken, async (req, res) => {
res.json({ shares });
} catch (err) {
console.error('Share room error:', err);
res.status(500).json({ error: 'Fehler beim Teilen des Raums' });
res.status(500).json({ error: 'Error sharing room' });
}
});
@@ -306,7 +306,7 @@ router.delete('/:uid/shares/:userId', authenticateToken, async (req, res) => {
const db = getDb();
const room = await db.get('SELECT * FROM rooms WHERE uid = ? AND user_id = ?', [req.params.uid, req.user.id]);
if (!room) {
return res.status(404).json({ error: 'Raum nicht gefunden oder keine Berechtigung' });
return res.status(404).json({ error: 'Room not found or no permission' });
}
await db.run('DELETE FROM room_shares WHERE room_id = ? AND user_id = ?', [room.id, parseInt(req.params.userId)]);
const shares = await db.all(`
@@ -318,7 +318,7 @@ router.delete('/:uid/shares/:userId', authenticateToken, async (req, res) => {
res.json({ shares });
} catch (err) {
console.error('Remove share error:', err);
res.status(500).json({ error: 'Fehler beim Entfernen der Freigabe' });
res.status(500).json({ error: 'Error removing share' });
}
});
@@ -329,15 +329,15 @@ router.post('/:uid/start', authenticateToken, async (req, res) => {
const room = await db.get('SELECT * FROM rooms WHERE uid = ?', [req.params.uid]);
if (!room) {
return res.status(404).json({ error: 'Raum nicht gefunden' });
return res.status(404).json({ error: 'Room not found' });
}
// Check access: owner or shared user
// Check access: owner or shared
const isOwner = room.user_id === req.user.id;
if (!isOwner) {
const share = await db.get('SELECT id FROM room_shares WHERE room_id = ? AND user_id = ?', [room.id, req.user.id]);
if (!share) {
return res.status(403).json({ error: 'Keine Berechtigung' });
return res.status(403).json({ error: 'No permission' });
}
}
@@ -347,7 +347,7 @@ router.post('/:uid/start', authenticateToken, async (req, res) => {
res.json({ joinUrl });
} catch (err) {
console.error('Start meeting error:', err);
res.status(500).json({ error: 'Meeting konnte nicht gestartet werden' });
res.status(500).json({ error: 'Meeting could not be started' });
}
});
@@ -358,18 +358,18 @@ router.post('/:uid/join', authenticateToken, async (req, res) => {
const room = await db.get('SELECT * FROM rooms WHERE uid = ?', [req.params.uid]);
if (!room) {
return res.status(404).json({ error: 'Raum nicht gefunden' });
return res.status(404).json({ error: 'Room not found' });
}
// Check access code if set
if (room.access_code && req.body.access_code !== room.access_code) {
return res.status(403).json({ error: 'Falscher Zugangscode' });
return res.status(403).json({ error: 'Wrong access code' });
}
// Check if meeting is running
const running = await isMeetingRunning(room.uid);
if (!running) {
return res.status(400).json({ error: 'Meeting läuft nicht. Bitte warten Sie, bis der Moderator das Meeting gestartet hat.' });
return res.status(400).json({ error: 'Meeting is not running. Please wait for the moderator to start the meeting.' });
}
// Owner and shared users join as moderator
@@ -381,7 +381,7 @@ router.post('/:uid/join', authenticateToken, async (req, res) => {
res.json({ joinUrl });
} catch (err) {
console.error('Join meeting error:', err);
res.status(500).json({ error: 'Meeting konnte nicht beigetreten werden' });
res.status(500).json({ error: 'Could not join meeting' });
}
});
@@ -392,7 +392,7 @@ router.post('/:uid/end', authenticateToken, async (req, res) => {
const room = await db.get('SELECT * FROM rooms WHERE uid = ?', [req.params.uid]);
if (!room) {
return res.status(404).json({ error: 'Raum nicht gefunden' });
return res.status(404).json({ error: 'Room not found' });
}
// Check access: owner or shared user
@@ -400,15 +400,15 @@ router.post('/:uid/end', authenticateToken, async (req, res) => {
if (!isOwner) {
const share = await db.get('SELECT id FROM room_shares WHERE room_id = ? AND user_id = ?', [room.id, req.user.id]);
if (!share) {
return res.status(403).json({ error: 'Keine Berechtigung' });
return res.status(403).json({ error: 'No permission' });
}
}
await endMeeting(room.uid);
res.json({ message: 'Meeting beendet' });
res.json({ message: 'Meeting ended' });
} catch (err) {
console.error('End meeting error:', err);
res.status(500).json({ error: 'Meeting konnte nicht beendet werden' });
res.status(500).json({ error: 'Meeting could not be ended' });
}
});
@@ -425,7 +425,7 @@ router.get('/:uid/public', async (req, res) => {
`, [req.params.uid]);
if (!room) {
return res.status(404).json({ error: 'Raum nicht gefunden' });
return res.status(404).json({ error: 'Room not found' });
}
const running = await isMeetingRunning(room.uid);
@@ -442,7 +442,7 @@ router.get('/:uid/public', async (req, res) => {
});
} catch (err) {
console.error('Public room info error:', err);
res.status(500).json({ error: 'Rauminfos konnten nicht geladen werden' });
res.status(500).json({ error: 'Room info could not be loaded' });
}
});
@@ -452,25 +452,25 @@ router.post('/:uid/guest-join', async (req, res) => {
const { name, access_code, moderator_code } = req.body;
if (!name || name.trim().length === 0) {
return res.status(400).json({ error: 'Name ist erforderlich' });
return res.status(400).json({ error: 'Name is required' });
}
const db = getDb();
const room = await db.get('SELECT * FROM rooms WHERE uid = ?', [req.params.uid]);
if (!room) {
return res.status(404).json({ error: 'Raum nicht gefunden' });
return res.status(404).json({ error: 'Room not found' });
}
// Check access code if set
if (room.access_code && access_code !== room.access_code) {
return res.status(403).json({ error: 'Falscher Zugangscode' });
return res.status(403).json({ error: 'Wrong access code' });
}
// Check if meeting is running (or if anyone_can_start is enabled)
const running = await isMeetingRunning(room.uid);
if (!running && !room.anyone_can_start) {
return res.status(400).json({ error: 'Meeting läuft nicht. Bitte warten Sie, bis der Moderator das Meeting gestartet hat.' });
return res.status(400).json({ error: 'Meeting is not running. Please wait for the moderator to start the meeting.' });
}
// If meeting not running but anyone_can_start, create it
@@ -490,7 +490,7 @@ router.post('/:uid/guest-join', async (req, res) => {
res.json({ joinUrl });
} catch (err) {
console.error('Guest join error:', err);
res.status(500).json({ error: 'Beitritt als Gast fehlgeschlagen' });
res.status(500).json({ error: 'Guest join failed' });
}
});