171 lines
7.4 KiB
JavaScript
171 lines
7.4 KiB
JavaScript
const express = require('express');
|
|
const router = express.Router();
|
|
const { getDb } = require('../models/db');
|
|
const { authMiddleware, adminMiddleware } = require('../middleware/auth');
|
|
|
|
// Get all groups for current user
|
|
router.get('/', authMiddleware, (req, res) => {
|
|
const db = getDb();
|
|
const userId = req.user.id;
|
|
|
|
// Public groups (all users are members)
|
|
const publicGroups = db.prepare(`
|
|
SELECT g.*,
|
|
(SELECT COUNT(*) FROM messages m WHERE m.group_id = g.id AND m.is_deleted = 0) as message_count,
|
|
(SELECT m.content FROM messages m WHERE m.group_id = g.id AND m.is_deleted = 0 ORDER BY m.created_at DESC LIMIT 1) as last_message,
|
|
(SELECT m.created_at FROM messages m WHERE m.group_id = g.id AND m.is_deleted = 0 ORDER BY m.created_at DESC LIMIT 1) as last_message_at
|
|
FROM groups g
|
|
WHERE g.type = 'public'
|
|
ORDER BY g.is_default DESC, g.name ASC
|
|
`).all();
|
|
|
|
// Private groups (user is a member)
|
|
const privateGroups = db.prepare(`
|
|
SELECT g.*,
|
|
u.name as owner_name,
|
|
(SELECT COUNT(*) FROM messages m WHERE m.group_id = g.id AND m.is_deleted = 0) as message_count,
|
|
(SELECT m.content FROM messages m WHERE m.group_id = g.id AND m.is_deleted = 0 ORDER BY m.created_at DESC LIMIT 1) as last_message,
|
|
(SELECT m.created_at FROM messages m WHERE m.group_id = g.id AND m.is_deleted = 0 ORDER BY m.created_at DESC LIMIT 1) as last_message_at
|
|
FROM groups g
|
|
JOIN group_members gm ON g.id = gm.group_id AND gm.user_id = ?
|
|
LEFT JOIN users u ON g.owner_id = u.id
|
|
WHERE g.type = 'private'
|
|
ORDER BY last_message_at DESC NULLS LAST
|
|
`).all(userId);
|
|
|
|
res.json({ publicGroups, privateGroups });
|
|
});
|
|
|
|
// Create group
|
|
router.post('/', authMiddleware, (req, res) => {
|
|
const { name, type, memberIds, isReadonly } = req.body;
|
|
const db = getDb();
|
|
|
|
if (type === 'public' && req.user.role !== 'admin') {
|
|
return res.status(403).json({ error: 'Only admins can create public groups' });
|
|
}
|
|
|
|
const result = db.prepare(`
|
|
INSERT INTO groups (name, type, owner_id, is_readonly)
|
|
VALUES (?, ?, ?, ?)
|
|
`).run(name, type || 'private', req.user.id, isReadonly ? 1 : 0);
|
|
|
|
const groupId = result.lastInsertRowid;
|
|
|
|
if (type === 'public') {
|
|
// Add all users to public group
|
|
const allUsers = db.prepare("SELECT id FROM users WHERE status = 'active'").all();
|
|
const insert = db.prepare('INSERT OR IGNORE INTO group_members (group_id, user_id) VALUES (?, ?)');
|
|
for (const u of allUsers) insert.run(groupId, u.id);
|
|
} else {
|
|
// Add creator
|
|
db.prepare('INSERT OR IGNORE INTO group_members (group_id, user_id) VALUES (?, ?)').run(groupId, req.user.id);
|
|
// Add other members
|
|
if (memberIds && memberIds.length > 0) {
|
|
const insert = db.prepare('INSERT OR IGNORE INTO group_members (group_id, user_id) VALUES (?, ?)');
|
|
for (const uid of memberIds) insert.run(groupId, uid);
|
|
}
|
|
}
|
|
|
|
const group = db.prepare('SELECT * FROM groups WHERE id = ?').get(groupId);
|
|
res.json({ group });
|
|
});
|
|
|
|
// Rename group
|
|
router.patch('/:id/rename', authMiddleware, (req, res) => {
|
|
const { name } = req.body;
|
|
const db = getDb();
|
|
const group = db.prepare('SELECT * FROM groups WHERE id = ?').get(req.params.id);
|
|
if (!group) return res.status(404).json({ error: 'Group not found' });
|
|
|
|
if (group.is_default) return res.status(403).json({ error: 'Cannot rename default group' });
|
|
if (group.type === 'public' && req.user.role !== 'admin') return res.status(403).json({ error: 'Only admins can rename public groups' });
|
|
if (group.type === 'private' && group.owner_id !== req.user.id && req.user.role !== 'admin') {
|
|
return res.status(403).json({ error: 'Only owner can rename private group' });
|
|
}
|
|
|
|
db.prepare("UPDATE groups SET name = ?, updated_at = datetime('now') WHERE id = ?").run(name, group.id);
|
|
res.json({ success: true });
|
|
});
|
|
|
|
// Get group members
|
|
router.get('/:id/members', authMiddleware, (req, res) => {
|
|
const db = getDb();
|
|
const members = db.prepare(`
|
|
SELECT u.id, u.name, u.display_name, u.avatar, u.role, u.status
|
|
FROM group_members gm
|
|
JOIN users u ON gm.user_id = u.id
|
|
WHERE gm.group_id = ?
|
|
ORDER BY u.name ASC
|
|
`).all(req.params.id);
|
|
res.json({ members });
|
|
});
|
|
|
|
// Add member to private group
|
|
router.post('/:id/members', authMiddleware, (req, res) => {
|
|
const { userId } = req.body;
|
|
const db = getDb();
|
|
const group = db.prepare('SELECT * FROM groups WHERE id = ?').get(req.params.id);
|
|
if (!group) return res.status(404).json({ error: 'Group not found' });
|
|
if (group.type !== 'private') return res.status(400).json({ error: 'Cannot manually add members to public groups' });
|
|
if (group.owner_id !== req.user.id && req.user.role !== 'admin') {
|
|
return res.status(403).json({ error: 'Only owner can add members' });
|
|
}
|
|
|
|
db.prepare('INSERT OR IGNORE INTO group_members (group_id, user_id) VALUES (?, ?)').run(group.id, userId);
|
|
res.json({ success: true });
|
|
});
|
|
|
|
// Remove a member from a private group (owner or admin only)
|
|
router.delete('/:id/members/:userId', authMiddleware, (req, res) => {
|
|
const db = getDb();
|
|
const group = db.prepare('SELECT * FROM groups WHERE id = ?').get(req.params.id);
|
|
if (!group) return res.status(404).json({ error: 'Group not found' });
|
|
if (group.type !== 'private') return res.status(400).json({ error: 'Cannot remove members from public groups' });
|
|
if (group.owner_id !== req.user.id && req.user.role !== 'admin') {
|
|
return res.status(403).json({ error: 'Only owner or admin can remove members' });
|
|
}
|
|
const targetId = parseInt(req.params.userId);
|
|
if (targetId === group.owner_id) {
|
|
return res.status(400).json({ error: 'Cannot remove the group owner' });
|
|
}
|
|
db.prepare('DELETE FROM group_members WHERE group_id = ? AND user_id = ?').run(group.id, targetId);
|
|
res.json({ success: true });
|
|
});
|
|
|
|
// Leave private group
|
|
router.delete('/:id/leave', authMiddleware, (req, res) => {
|
|
const db = getDb();
|
|
const group = db.prepare('SELECT * FROM groups WHERE id = ?').get(req.params.id);
|
|
if (!group) return res.status(404).json({ error: 'Group not found' });
|
|
if (group.type === 'public') return res.status(400).json({ error: 'Cannot leave public groups' });
|
|
|
|
db.prepare('DELETE FROM group_members WHERE group_id = ? AND user_id = ?').run(group.id, req.user.id);
|
|
res.json({ success: true });
|
|
});
|
|
|
|
// Admin take ownership of private group
|
|
router.post('/:id/take-ownership', authMiddleware, adminMiddleware, (req, res) => {
|
|
const db = getDb();
|
|
db.prepare("UPDATE groups SET owner_id = ?, updated_at = datetime('now') WHERE id = ?").run(req.user.id, req.params.id);
|
|
db.prepare('INSERT OR IGNORE INTO group_members (group_id, user_id) VALUES (?, ?)').run(req.params.id, req.user.id);
|
|
res.json({ success: true });
|
|
});
|
|
|
|
// Delete group (admin or private group owner)
|
|
router.delete('/:id', authMiddleware, (req, res) => {
|
|
const db = getDb();
|
|
const group = db.prepare('SELECT * FROM groups WHERE id = ?').get(req.params.id);
|
|
if (!group) return res.status(404).json({ error: 'Group not found' });
|
|
if (group.is_default) return res.status(403).json({ error: 'Cannot delete default group' });
|
|
if (group.type === 'public' && req.user.role !== 'admin') return res.status(403).json({ error: 'Only admins can delete public groups' });
|
|
if (group.type === 'private' && group.owner_id !== req.user.id && req.user.role !== 'admin') {
|
|
return res.status(403).json({ error: 'Only owner or admin can delete private groups' });
|
|
}
|
|
|
|
db.prepare('DELETE FROM groups WHERE id = ?').run(group.id);
|
|
res.json({ success: true });
|
|
});
|
|
|
|
module.exports = router;
|