feat: Add a large collection of emoji and other frontend assets, including a sound file, and a backend package.json.
This commit is contained in:
213
Backend/routes/roles.js
Normal file
213
Backend/routes/roles.js
Normal file
@@ -0,0 +1,213 @@
|
||||
const express = require('express');
|
||||
const router = express.Router();
|
||||
const db = require('../db');
|
||||
|
||||
// Middleware to check for permissions (simplified for now)
|
||||
// In a real app, you'd check if req.user has the permission
|
||||
// Middleware to check for permissions
|
||||
const checkPermission = (requiredPerm) => {
|
||||
return async (req, res, next) => {
|
||||
const userId = req.headers['x-user-id'];
|
||||
|
||||
if (!userId) {
|
||||
return res.status(401).json({ error: 'Unauthorized: No User ID' });
|
||||
}
|
||||
|
||||
try {
|
||||
// Fetch all roles for user and aggregate permissions
|
||||
const result = await db.query(`
|
||||
SELECT r.permissions
|
||||
FROM user_roles ur
|
||||
JOIN roles r ON ur.role_id = r.id
|
||||
WHERE ur.user_id = $1
|
||||
`, [userId]);
|
||||
|
||||
let hasPermission = false;
|
||||
|
||||
// Check if ANY of the user's roles has the permission
|
||||
for (const row of result.rows) {
|
||||
const perms = row.permissions || {};
|
||||
// If Manage Roles is true, or if checking for something else and they have it
|
||||
if (perms[requiredPerm] === true) {
|
||||
hasPermission = true;
|
||||
break;
|
||||
}
|
||||
// Implicit Admin/Owner check: if they have 'manage_roles' and we are checking something lower?
|
||||
// For "Owner" role, we seeded it with specific true values.
|
||||
// But let's check for 'administrator' equivalent if we had it.
|
||||
// For now, implicit check: if we need 'manage_roles', look for it.
|
||||
}
|
||||
|
||||
if (!hasPermission) {
|
||||
return res.status(403).json({ error: `Forbidden: Missing ${requiredPerm}` });
|
||||
}
|
||||
|
||||
next();
|
||||
} catch (err) {
|
||||
console.error('Permission check failed:', err);
|
||||
return res.status(500).json({ error: 'Internal Server Error' });
|
||||
}
|
||||
};
|
||||
};
|
||||
|
||||
// GET /api/roles/permissions - Get current user's permissions
|
||||
router.get('/permissions', async (req, res) => {
|
||||
const userId = req.headers['x-user-id'];
|
||||
if (!userId) return res.json({}); // No perms if no ID
|
||||
|
||||
try {
|
||||
const result = await db.query(`
|
||||
SELECT r.permissions
|
||||
FROM user_roles ur
|
||||
JOIN roles r ON ur.role_id = r.id
|
||||
WHERE ur.user_id = $1
|
||||
`, [userId]);
|
||||
|
||||
const finalPerms = {
|
||||
manage_channels: false,
|
||||
manage_roles: false,
|
||||
create_invite: false,
|
||||
embed_links: false,
|
||||
attach_files: false
|
||||
};
|
||||
|
||||
for (const row of result.rows) {
|
||||
const p = row.permissions || {};
|
||||
if (p.manage_channels) finalPerms.manage_channels = true;
|
||||
if (p.manage_roles) finalPerms.manage_roles = true;
|
||||
if (p.create_invite) finalPerms.create_invite = true;
|
||||
if (p.embed_links) finalPerms.embed_links = true;
|
||||
if (p.attach_files) finalPerms.attach_files = true;
|
||||
}
|
||||
res.json(finalPerms);
|
||||
} catch (err) {
|
||||
console.error(err);
|
||||
res.status(500).json({ error: 'Server error' });
|
||||
}
|
||||
});
|
||||
|
||||
// GET /api/roles - List all roles
|
||||
router.get('/', async (req, res) => {
|
||||
try {
|
||||
const result = await db.query('SELECT * FROM roles ORDER BY position DESC, id ASC');
|
||||
res.json(result.rows);
|
||||
} catch (err) {
|
||||
console.error(err);
|
||||
res.status(500).json({ error: 'Server error' });
|
||||
}
|
||||
});
|
||||
|
||||
// POST /api/roles - Create new role
|
||||
router.post('/', checkPermission('manage_roles'), async (req, res) => {
|
||||
const { name, color, permissions, position, is_hoist } = req.body;
|
||||
try {
|
||||
const result = await db.query(
|
||||
'INSERT INTO roles (name, color, permissions, position, is_hoist) VALUES ($1, $2, $3, $4, $5) RETURNING *',
|
||||
[name || 'new role', color || '#99aab5', permissions || {}, position || 0, is_hoist || false]
|
||||
);
|
||||
res.json(result.rows[0]);
|
||||
} catch (err) {
|
||||
console.error(err);
|
||||
res.status(500).json({ error: 'Server error' });
|
||||
}
|
||||
});
|
||||
|
||||
// PUT /api/roles/:id - Update role
|
||||
router.put('/:id', checkPermission('manage_roles'), async (req, res) => {
|
||||
const { id } = req.params;
|
||||
const { name, color, permissions, position, is_hoist } = req.body;
|
||||
|
||||
// Dynamic update query
|
||||
const fields = [];
|
||||
const values = [];
|
||||
let idx = 1;
|
||||
|
||||
if (name !== undefined) { fields.push(`name = $${idx++}`); values.push(name); }
|
||||
if (color !== undefined) { fields.push(`color = $${idx++}`); values.push(color); }
|
||||
if (permissions !== undefined) { fields.push(`permissions = $${idx++}`); values.push(permissions); }
|
||||
if (position !== undefined) { fields.push(`position = $${idx++}`); values.push(position); }
|
||||
if (is_hoist !== undefined) { fields.push(`is_hoist = $${idx++}`); values.push(is_hoist); }
|
||||
|
||||
if (fields.length === 0) return res.json({ success: true }); // Nothing to update
|
||||
|
||||
values.push(id);
|
||||
const query = `UPDATE roles SET ${fields.join(', ')} WHERE id = $${idx} RETURNING *`;
|
||||
|
||||
try {
|
||||
const result = await db.query(query, values);
|
||||
if (result.rows.length === 0) return res.status(404).json({ error: 'Role not found' });
|
||||
res.json(result.rows[0]);
|
||||
} catch (err) {
|
||||
console.error(err);
|
||||
res.status(500).json({ error: 'Server error' });
|
||||
}
|
||||
});
|
||||
|
||||
// DELETE /api/roles/:id - Delete role
|
||||
router.delete('/:id', checkPermission('manage_roles'), async (req, res) => {
|
||||
const { id } = req.params;
|
||||
try {
|
||||
// user_roles cascade handled by DB
|
||||
const result = await db.query('DELETE FROM roles WHERE id = $1 RETURNING *', [id]);
|
||||
if (result.rows.length === 0) return res.status(404).json({ error: 'Role not found' });
|
||||
res.json({ success: true, deletedId: id });
|
||||
} catch (err) {
|
||||
console.error(err);
|
||||
res.status(500).json({ error: 'Server error' });
|
||||
}
|
||||
});
|
||||
|
||||
// GET /api/roles/members - List members with roles
|
||||
// (This is effectively GET /api/users but enriched with roles)
|
||||
router.get('/members', async (req, res) => {
|
||||
try {
|
||||
const result = await db.query(`
|
||||
SELECT u.id, u.username, u.public_identity_key,
|
||||
json_agg(r.*) FILTER (WHERE r.id IS NOT NULL) as roles
|
||||
FROM users u
|
||||
LEFT JOIN user_roles ur ON u.id = ur.user_id
|
||||
LEFT JOIN roles r ON ur.role_id = r.id
|
||||
GROUP BY u.id
|
||||
`);
|
||||
res.json(result.rows);
|
||||
} catch (err) {
|
||||
console.error(err);
|
||||
res.status(500).json({ error: 'Server error' });
|
||||
}
|
||||
});
|
||||
|
||||
// POST /api/roles/:id/assign - Assign role to user
|
||||
router.post('/:id/assign', checkPermission('manage_roles'), async (req, res) => {
|
||||
const { id } = req.params; // role id
|
||||
const { userId } = req.body;
|
||||
|
||||
try {
|
||||
await db.query(
|
||||
'INSERT INTO user_roles (user_id, role_id) VALUES ($1, $2) ON CONFLICT DO NOTHING',
|
||||
[userId, id]
|
||||
);
|
||||
res.json({ success: true });
|
||||
} catch (err) {
|
||||
console.error(err);
|
||||
res.status(500).json({ error: 'Server error' });
|
||||
}
|
||||
});
|
||||
|
||||
// POST /api/roles/:id/remove - Remove role from user
|
||||
router.post('/:id/remove', checkPermission('manage_roles'), async (req, res) => {
|
||||
const { id } = req.params; // role id
|
||||
const { userId } = req.body;
|
||||
|
||||
try {
|
||||
await db.query(
|
||||
'DELETE FROM user_roles WHERE user_id = $1 AND role_id = $2',
|
||||
[userId, id]
|
||||
);
|
||||
res.json({ success: true });
|
||||
} catch (err) {
|
||||
console.error(err);
|
||||
res.status(500).json({ error: 'Server error' });
|
||||
}
|
||||
});
|
||||
|
||||
module.exports = router;
|
||||
Reference in New Issue
Block a user