v0.3.0
This commit is contained in:
@@ -32,9 +32,10 @@ app.use('/uploads', express.static('/app/uploads'));
|
||||
// API Routes
|
||||
app.use('/api/auth', require('./routes/auth'));
|
||||
app.use('/api/users', require('./routes/users'));
|
||||
app.use('/api/groups', require('./routes/groups'));
|
||||
app.use('/api/groups', require('./routes/groups')(io));
|
||||
app.use('/api/messages', require('./routes/messages'));
|
||||
app.use('/api/settings', require('./routes/settings'));
|
||||
app.use('/api/about', require('./routes/about'));
|
||||
app.use('/api/push', pushRouter);
|
||||
|
||||
// Link preview proxy
|
||||
@@ -128,14 +129,27 @@ io.on('connection', (socket) => {
|
||||
// Broadcast online status
|
||||
io.emit('user:online', { userId });
|
||||
|
||||
// Join personal room for direct notifications
|
||||
socket.join(`user:${userId}`);
|
||||
|
||||
// Join rooms for all user's groups
|
||||
const db = getDb();
|
||||
const publicGroups = db.prepare("SELECT id FROM groups WHERE type = 'public'").all();
|
||||
for (const g of publicGroups) socket.join(`group:${g.id}`);
|
||||
|
||||
|
||||
const privateGroups = db.prepare("SELECT group_id FROM group_members WHERE user_id = ?").all(userId);
|
||||
for (const g of privateGroups) socket.join(`group:${g.group_id}`);
|
||||
|
||||
// When a new group is created and pushed to this socket, join its room
|
||||
socket.on('group:join-room', ({ groupId }) => {
|
||||
socket.join(`group:${groupId}`);
|
||||
});
|
||||
|
||||
// When a user leaves a group, remove them from the socket room
|
||||
socket.on('group:leave-room', ({ groupId }) => {
|
||||
socket.leave(`group:${groupId}`);
|
||||
});
|
||||
|
||||
// Handle new message
|
||||
socket.on('message:send', async (data) => {
|
||||
const { groupId, content, replyToId, imageUrl, linkPreview } = data;
|
||||
@@ -271,12 +285,31 @@ io.on('connection', (socket) => {
|
||||
socket.on('message:delete', (data) => {
|
||||
const { messageId } = data;
|
||||
const db = getDb();
|
||||
const message = db.prepare('SELECT m.*, g.type as group_type, g.owner_id as group_owner_id FROM messages m JOIN groups g ON m.group_id = g.id WHERE m.id = ?').get(messageId);
|
||||
const message = db.prepare(`
|
||||
SELECT m.*, g.type as group_type, g.owner_id as group_owner_id, g.is_direct
|
||||
FROM messages m JOIN groups g ON m.group_id = g.id WHERE m.id = ?
|
||||
`).get(messageId);
|
||||
if (!message) return;
|
||||
|
||||
const canDelete = message.user_id === userId ||
|
||||
(socket.user.role === 'admin' && message.group_type === 'public') ||
|
||||
(message.group_type === 'private' && message.group_owner_id === userId);
|
||||
const isAdmin = socket.user.role === 'admin';
|
||||
const isOwner = message.group_owner_id === userId;
|
||||
const isAuthor = message.user_id === userId;
|
||||
|
||||
// Rules:
|
||||
// 1. Author can always delete their own message
|
||||
// 2. Admin can delete in any public group or any group they're a member of
|
||||
// 3. Group owner can delete any message in their group
|
||||
// 4. In direct messages: author + owner rules apply (no blanket block)
|
||||
let canDelete = isAuthor || isOwner;
|
||||
if (!canDelete && isAdmin) {
|
||||
if (message.group_type === 'public') {
|
||||
canDelete = true;
|
||||
} else {
|
||||
// Admin can delete in private/direct groups they're a member of
|
||||
const membership = db.prepare('SELECT id FROM group_members WHERE group_id = ? AND user_id = ?').get(message.group_id, userId);
|
||||
if (membership) canDelete = true;
|
||||
}
|
||||
}
|
||||
|
||||
if (!canDelete) return;
|
||||
|
||||
|
||||
Reference in New Issue
Block a user