v0.12.22 User Manager updates

This commit is contained in:
2026-03-24 15:19:32 -04:00
parent 65e7cc4007
commit 72094d7d15
8 changed files with 372 additions and 64 deletions

View File

@@ -193,6 +193,14 @@ router.get('/', authMiddleware, teamManagerMiddleware, async (req, res) => {
} catch (e) { res.status(500).json({ error: e.message }); }
});
// GET /byuser/:userId — user group IDs for a specific user
router.get('/byuser/:userId', authMiddleware, teamManagerMiddleware, async (req, res) => {
try {
const rows = await query(req.schema, 'SELECT user_group_id FROM user_group_members WHERE user_id=$1', [req.params.userId]);
res.json({ groupIds: rows.map(r => r.user_group_id) });
} catch (e) { res.status(500).json({ error: e.message }); }
});
// GET /:id
router.get('/:id', authMiddleware, teamManagerMiddleware, async (req, res) => {
try {
@@ -364,6 +372,80 @@ router.delete('/:id', authMiddleware, teamManagerMiddleware, async (req, res) =>
});
// POST /:id/members/:userId — add a single user to a group (with DM + notifications)
router.post('/:id/members/:userId', authMiddleware, teamManagerMiddleware, async (req, res) => {
try {
const ug = await queryOne(req.schema, 'SELECT * FROM user_groups WHERE id=$1', [req.params.id]);
if (!ug) return res.status(404).json({ error: 'Not found' });
const userId = parseInt(req.params.userId);
const defaultAdmin = await queryOne(req.schema, 'SELECT id FROM users WHERE is_default_admin=TRUE');
if (defaultAdmin && userId === defaultAdmin.id) return res.status(400).json({ error: 'Cannot add default admin to user groups' });
await exec(req.schema, 'INSERT INTO user_group_members (user_group_id,user_id) VALUES ($1,$2) ON CONFLICT DO NOTHING', [ug.id, userId]);
if (ug.dm_group_id) {
await addUserSilent(req.schema, ug.dm_group_id, userId);
const u = await queryOne(req.schema, 'SELECT name,display_name FROM users WHERE id=$1', [userId]);
await postSysMsg(req.schema, ug.dm_group_id, req.user.id, `${u?.display_name||u?.name||'A user'} has joined the conversation.`);
}
// Propagate to multi-group DMs
const mgDms = await query(req.schema, `
SELECT mgd.id, mgd.dm_group_id FROM multi_group_dm_members mgdm
JOIN multi_group_dms mgd ON mgd.id=mgdm.multi_group_dm_id WHERE mgdm.user_group_id=$1
`, [ug.id]);
for (const mg of mgDms) {
if (!mg.dm_group_id) continue;
await addUserSilent(req.schema, mg.dm_group_id, userId);
const u = await queryOne(req.schema, 'SELECT name,display_name FROM users WHERE id=$1', [userId]);
await postSysMsg(req.schema, mg.dm_group_id, req.user.id, `${u?.display_name||u?.name||'A user'} has joined this conversation.`);
}
res.json({ success: true });
} catch (e) { res.status(500).json({ error: e.message }); }
});
// DELETE /:id/members/:userId — remove a single user from a group (with DM + notifications)
router.delete('/:id/members/:userId', authMiddleware, teamManagerMiddleware, async (req, res) => {
try {
const ug = await queryOne(req.schema, 'SELECT * FROM user_groups WHERE id=$1', [req.params.id]);
if (!ug) return res.status(404).json({ error: 'Not found' });
const userId = parseInt(req.params.userId);
await exec(req.schema, 'DELETE FROM user_group_members WHERE user_group_id=$1 AND user_id=$2', [ug.id, userId]);
if (ug.dm_group_id) {
await exec(req.schema, 'DELETE FROM group_members WHERE group_id=$1 AND user_id=$2', [ug.dm_group_id, userId]);
io.in(R(req.schema,'user',userId)).socketsLeave(R(req.schema,'group',ug.dm_group_id));
io.to(R(req.schema,'user',userId)).emit('group:deleted', { groupId: ug.dm_group_id });
const u = await queryOne(req.schema, 'SELECT name,display_name FROM users WHERE id=$1', [userId]);
await postSysMsg(req.schema, ug.dm_group_id, req.user.id, `${u?.display_name||u?.name||'A user'} has been removed from the conversation.`);
}
// Propagate to multi-group DMs
const mgDms = await query(req.schema, `
SELECT mgd.id, mgd.dm_group_id FROM multi_group_dm_members mgdm
JOIN multi_group_dms mgd ON mgd.id=mgdm.multi_group_dm_id WHERE mgdm.user_group_id=$1
`, [ug.id]);
for (const mg of mgDms) {
if (!mg.dm_group_id) continue;
const stillIn = await queryOne(req.schema, `
SELECT 1 FROM multi_group_dm_members mgdm JOIN user_group_members ugm ON ugm.user_group_id=mgdm.user_group_id
WHERE mgdm.multi_group_dm_id=$1 AND ugm.user_id=$2
`, [mg.id, userId]);
if (!stillIn) {
await exec(req.schema, 'DELETE FROM group_members WHERE group_id=$1 AND user_id=$2', [mg.dm_group_id, userId]);
io.in(R(req.schema,'user',userId)).socketsLeave(R(req.schema,'group',mg.dm_group_id));
io.to(R(req.schema,'user',userId)).emit('group:deleted', { groupId: mg.dm_group_id });
const u = await queryOne(req.schema, 'SELECT name,display_name FROM users WHERE id=$1', [userId]);
await postSysMsg(req.schema, mg.dm_group_id, req.user.id, `${u?.display_name||u?.name||'A user'} has been removed from this conversation.`);
}
}
res.json({ success: true });
} catch (e) { res.status(500).json({ error: e.message }); }
});
// ── U2U DM Restrictions ───────────────────────────────────────────────────────
// GET /:id/restrictions — get blocked group IDs for a user group