DTP Base provides a scalable and secure Node.js application development harness ready for production service.
You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
 
 
 
 

278 lines
7.8 KiB

// auth.js
// Copyright (C) 2024 DTP Technologies, LLC
// All Rights Reserved
'use strict';
import express from 'express';
import { SiteController, SiteError } from '../../lib/site-lib.js';
export default class ChatController extends SiteController {
static get name ( ) { return 'ChatController'; }
static get slug ( ) { return 'chat'; }
static get MESSAGES_PER_PAGE ( ) { return 20; }
constructor (dtp) {
super(dtp, ChatController);
}
async start ( ) {
const {
// csrfToken: csrfTokenService,
// limiter: limiterService,
session: sessionService,
} = this.dtp.services;
const authRequired = sessionService.authCheckMiddleware({ requireLogin: true });
const multer = this.createMulter(ChatController.slug);
async function requireRoomOwner (req, res, next) {
if (!req.user) {
return next(new SiteError(403, 'Must be logged in to proceed'));
}
if (!res.locals.room) {
return next(new SiteError(403, 'Room not found'));
}
if (!res.locals.room.owner._id.equals(req.user._id)) {
return next(new SiteError(403, 'This is not your room'));
}
return next();
}
const router = express.Router();
this.dtp.app.use('/chat', router);
router.use(
async (req, res, next) => {
res.locals.currentView = 'auth';
return next();
},
authRequired,
);
router.param('roomId', this.populateRoomId.bind(this));
router.param('messageId', this.populateMessageId.bind(this));
router.post(
'/room/:roomId/message',
// limiterService.create(limiterService.config.chat.postRoomMessage),
multer.fields([{ name: 'imageFiles', maxCount: 6 }, { name: 'videoFiles', maxCount: 1 }]),
this.postRoomMessage.bind(this),
);
router.post(
'/room/:roomId/settings',
requireRoomOwner,
// limiterService.create(limiterService.config.chat.postRoomSettings),
this.postRoomSettings.bind(this),
);
router.post(
'/room',
// limiterService.create(limiterService.config.chat.postCreateRoom),
this.postCreateRoom.bind(this),
);
router.post(
'/message/:messageId/reaction',
// limiterService.create(limiterService.config.chat.postMessageReaction),
multer.none(),
this.postMessageReaction.bind(this),
);
router.get(
'/room/create',
// limiterService.create(limiterService.config.chat.getRoomCreateView),
this.getRoomCreateView.bind(this),
);
router.get(
'/room/:roomId/join',
// limiterService.create(limiterService.config.chat.getRoomView),
this.getRoomJoin.bind(this),
);
router.get(
'/room/:roomId/messages',
// limiterService.create(limiterService.config.chat.getRoomMessages),
this.getRoomMessages.bind(this),
);
router.get(
'/room/:roomId/settings',
// limiterService.create(limiterService.config.chat.getRoomMessages),
requireRoomOwner,
this.getRoomSettingsView.bind(this),
);
router.get(
'/room/:roomId',
// limiterService.create(limiterService.config.chat.getRoomView),
this.getRoomView.bind(this),
);
router.delete(
'/room/:roomId',
// limiterService.create(limiterService.config.chat.deleteRoom),
this.deleteRoom.bind(this),
);
return router;
}
async populateRoomId (req, res, next, roomId) {
const { chat: chatService } = this.dtp.services;
try {
res.locals.room = await chatService.getRoomById(roomId);
if (!res.locals.room) {
throw new SiteError(404, "The chat room doesn't exist.");
}
return next();
} catch (error) {
return next(error);
}
}
async populateMessageId (req, res, next, messageId) {
const { chat: chatService } = this.dtp.services;
try {
res.locals.message = await chatService.getMessageById(messageId);
if (!res.locals.message) {
throw new SiteError(404, "The chat message doesn't exist.");
}
return next();
} catch (error) {
return next(error);
}
}
async postMessageReaction (req, res) {
const { chat: chatService } = this.dtp.services;
try {
await chatService.toggleMessageReaction(req.user, res.locals.message, req.body);
return res.status(200).json({ success: true });
} catch (error) {
this.log.error('failed to send chat room message', { error });
return res.status(error.statusCode || 500).json({
success: false,
message: error.message,
});
}
}
async postRoomMessage (req, res) {
const { chat: chatService } = this.dtp.services;
try {
this.log.debug('post attachments', {
imageFiles: req.files.imageFiles,
videoFiles: req.files.videoFiles,
});
await chatService.sendRoomMessage(
res.locals.room,
req.user,
req.body,
req.files.imageFiles,
req.files.videoFiles,
);
return res.status(200).json({ success: true });
} catch (error) {
this.log.error('failed to send chat room message', { error });
return res.status(error.statusCode || 500).json({
success: false,
message: error.message,
});
}
}
async postRoomSettings (req, res, next) {
const { chat: chatService } = this.dtp.services;
try {
await chatService.updateRoomSettings(res.locals.room, req.body);
res.redirect(`/chat/room/${res.locals.room._id}`);
} catch (error) {
this.log.error('failed to present the room settings view', { error });
return next(error);
}
}
async postCreateRoom (req, res, next) {
const { chat: chatService } = this.dtp.services;
try {
res.locals.room = await chatService.createRoom(req.user, req.body);
res.redirect(`/chat/room/${res.locals.room._id}`);
} catch (error) {
return next(error);
}
}
async getRoomCreateView (req, res) {
res.render('chat/room/create');
}
async getRoomJoin (req, res, next) {
const { chat: chatService } = this.dtp.services;
try {
await chatService.joinRoom(res.locals.room, req.user);
res.status(200).json({ success: true, room: res.locals.room });
} catch (error) {
this.log.error('failed to join chat room', { error });
return next(error);
}
}
async getRoomMessages (req, res, next) {
const { chat: chatService } = this.dtp.services;
try {
res.locals.pagination = this.getPaginationParameters(req, ChatController.MESSAGES_PER_PAGE);
res.locals.messages = await chatService.getRoomMessages(res.locals.room, res.locals.pagination);
res.render('chat/room/view');
} catch (error) {
this.log.error('failed to present the chat room view', { error });
return next(error);
}
}
async getRoomSettingsView (req, res) {
res.render('chat/room/settings');
}
async getRoomView (req, res, next) {
const { chat: chatService } = this.dtp.services;
try {
res.locals.currentView = 'chat-room';
res.locals.pagination = this.getPaginationParameters(req, ChatController.MESSAGES_PER_PAGE);
res.locals.messages = await chatService.getRoomMessages(res.locals.room, res.locals.pagination);
res.render('chat/room/view');
} catch (error) {
this.log.error('failed to present the chat room view', { error });
return next(error);
}
}
async deleteRoom (req, res) {
const { chat: chatService } = this.dtp.services;
try {
await chatService.destroyRoom(req.user, res.locals.room);
const displayList = this.createDisplayList('chat-room-delete');
displayList.navigateto('/');
res.status(200).json({ success: true, displayList });
} catch (error) {
this.log.error('failed to destroy chat room', { error });
res.status(error.statusCode || 500).json({
success: false,
message: error.message,
});
}
}
}