feat: Group chat and push notifications
- Add group chat tables (chat_groups, chat_group_members, group_messages) - Add push subscriptions table for web push notifications - Add group service, controller, routes - Add push service, controller, routes - Integrate push notifications with todos, messages, group messages Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
This commit is contained in:
88
src/routes/group.routes.js
Normal file
88
src/routes/group.routes.js
Normal file
@@ -0,0 +1,88 @@
|
||||
import express from 'express';
|
||||
import * as groupController from '../controllers/group.controller.js';
|
||||
import { authenticate } from '../middlewares/auth/authMiddleware.js';
|
||||
import { validateBody, validateParams } from '../middlewares/security/validateInput.js';
|
||||
import { z } from 'zod';
|
||||
|
||||
const router = express.Router();
|
||||
|
||||
// All group routes require authentication
|
||||
router.use(authenticate);
|
||||
|
||||
// Create a new group
|
||||
router.post(
|
||||
'/',
|
||||
validateBody(
|
||||
z.object({
|
||||
name: z.string().min(1, 'Názov skupiny je povinný').max(100, 'Názov je príliš dlhý'),
|
||||
memberIds: z.array(z.string().uuid()).min(1, 'Vyberte aspoň jedného člena'),
|
||||
})
|
||||
),
|
||||
groupController.createGroup
|
||||
);
|
||||
|
||||
// Get all groups for current user
|
||||
router.get('/', groupController.getUserGroups);
|
||||
|
||||
// Get group details
|
||||
router.get(
|
||||
'/:groupId',
|
||||
validateParams(z.object({ groupId: z.string().uuid() })),
|
||||
groupController.getGroupDetails
|
||||
);
|
||||
|
||||
// Update group name
|
||||
router.patch(
|
||||
'/:groupId',
|
||||
validateParams(z.object({ groupId: z.string().uuid() })),
|
||||
validateBody(z.object({ name: z.string().min(1).max(100) })),
|
||||
groupController.updateGroupName
|
||||
);
|
||||
|
||||
// Delete group
|
||||
router.delete(
|
||||
'/:groupId',
|
||||
validateParams(z.object({ groupId: z.string().uuid() })),
|
||||
groupController.deleteGroup
|
||||
);
|
||||
|
||||
// Get group messages
|
||||
router.get(
|
||||
'/:groupId/messages',
|
||||
validateParams(z.object({ groupId: z.string().uuid() })),
|
||||
groupController.getGroupMessages
|
||||
);
|
||||
|
||||
// Send message to group
|
||||
router.post(
|
||||
'/:groupId/messages',
|
||||
validateParams(z.object({ groupId: z.string().uuid() })),
|
||||
validateBody(
|
||||
z.object({
|
||||
content: z.string().min(1, 'Správa nemôže byť prázdna').max(5000, 'Správa je príliš dlhá'),
|
||||
})
|
||||
),
|
||||
groupController.sendGroupMessage
|
||||
);
|
||||
|
||||
// Add member to group
|
||||
router.post(
|
||||
'/:groupId/members',
|
||||
validateParams(z.object({ groupId: z.string().uuid() })),
|
||||
validateBody(z.object({ userId: z.string().uuid() })),
|
||||
groupController.addGroupMember
|
||||
);
|
||||
|
||||
// Remove member from group
|
||||
router.delete(
|
||||
'/:groupId/members/:userId',
|
||||
validateParams(
|
||||
z.object({
|
||||
groupId: z.string().uuid(),
|
||||
userId: z.string().uuid(),
|
||||
})
|
||||
),
|
||||
groupController.removeGroupMember
|
||||
);
|
||||
|
||||
export default router;
|
||||
49
src/routes/push.routes.js
Normal file
49
src/routes/push.routes.js
Normal file
@@ -0,0 +1,49 @@
|
||||
import express from 'express';
|
||||
import * as pushController from '../controllers/push.controller.js';
|
||||
import { authenticate } from '../middlewares/auth/authMiddleware.js';
|
||||
import { validateBody } from '../middlewares/security/validateInput.js';
|
||||
import { z } from 'zod';
|
||||
|
||||
const router = express.Router();
|
||||
|
||||
// Get VAPID public key (no auth required)
|
||||
router.get('/vapid-public-key', pushController.getVapidPublicKey);
|
||||
|
||||
// All other routes require authentication
|
||||
router.use(authenticate);
|
||||
|
||||
// Subscribe to push notifications
|
||||
router.post(
|
||||
'/subscribe',
|
||||
validateBody(
|
||||
z.object({
|
||||
subscription: z.object({
|
||||
endpoint: z.string().url(),
|
||||
keys: z.object({
|
||||
p256dh: z.string(),
|
||||
auth: z.string(),
|
||||
}),
|
||||
}),
|
||||
})
|
||||
),
|
||||
pushController.subscribe
|
||||
);
|
||||
|
||||
// Unsubscribe from push notifications
|
||||
router.post(
|
||||
'/unsubscribe',
|
||||
validateBody(
|
||||
z.object({
|
||||
endpoint: z.string().url().optional(),
|
||||
}).optional()
|
||||
),
|
||||
pushController.unsubscribe
|
||||
);
|
||||
|
||||
// Get subscription status
|
||||
router.get('/status', pushController.getStatus);
|
||||
|
||||
// Test push notification
|
||||
router.post('/test', pushController.testPush);
|
||||
|
||||
export default router;
|
||||
Reference in New Issue
Block a user