🔐 fix: Enhance Message & Image Access Security (#3363)

* chore: slight refactor

* fix: prevent message updates unless explicitly owned

* refactor: rethrow errors, update deleteMessagesSince (not used), add basic tests

* fix: Add path normalization and validation to image request middleware

* fix: image validation path security
This commit is contained in:
Danny Avila 2024-07-17 09:51:03 -04:00 committed by GitHub
parent 0a1d38e318
commit d5d188eebf
No known key found for this signature in database
GPG key ID: B5690EEEBB952194
17 changed files with 595 additions and 229 deletions

View file

@ -1,46 +1,42 @@
const express = require('express');
const router = express.Router();
const {
getMessages,
updateMessage,
saveConvo,
saveMessage,
deleteMessages,
} = require('../../models');
const { countTokens } = require('../utils');
const { requireJwtAuth, validateMessageReq } = require('../middleware/');
const { saveConvo, saveMessage, getMessages, updateMessage, deleteMessages } = require('~/models');
const { requireJwtAuth, validateMessageReq } = require('~/server/middleware');
const { countTokens } = require('~/server/utils');
router.use(requireJwtAuth);
router.use(validateMessageReq);
router.get('/:conversationId', validateMessageReq, async (req, res) => {
router.get('/:conversationId', async (req, res) => {
const { conversationId } = req.params;
res.status(200).send(await getMessages({ conversationId }, '-_id -__v -user'));
});
// CREATE
router.post('/:conversationId', validateMessageReq, async (req, res) => {
router.post('/:conversationId', async (req, res) => {
const message = req.body;
const savedMessage = await saveMessage({ ...message, user: req.user.id });
const savedMessage = await saveMessage(req, { ...message, user: req.user.id });
await saveConvo(req.user.id, savedMessage);
res.status(201).send(savedMessage);
});
// READ
router.get('/:conversationId/:messageId', validateMessageReq, async (req, res) => {
router.get('/:conversationId/:messageId', async (req, res) => {
const { conversationId, messageId } = req.params;
res.status(200).send(await getMessages({ conversationId, messageId }, '-_id -__v -user'));
});
// UPDATE
router.put('/:conversationId/:messageId', validateMessageReq, async (req, res) => {
router.put('/:conversationId/:messageId', async (req, res) => {
const { messageId, model } = req.params;
const { text } = req.body;
const tokenCount = await countTokens(text, model);
res.status(201).json(await updateMessage({ messageId, text, tokenCount }));
const result = await updateMessage(req, { messageId, text, tokenCount });
res.status(201).json(result);
});
// DELETE
router.delete('/:conversationId/:messageId', validateMessageReq, async (req, res) => {
router.delete('/:conversationId/:messageId', async (req, res) => {
const { messageId } = req.params;
await deleteMessages({ messageId });
res.status(204).send();