Initial Push to GIT
This commit is contained in:
153
backend/src/routes/groups.js
Normal file
153
backend/src/routes/groups.js
Normal file
@@ -0,0 +1,153 @@
|
||||
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 });
|
||||
});
|
||||
|
||||
// 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;
|
||||
Reference in New Issue
Block a user