feat(feedback): add validation for feedback creation and update (#4260)

* feat(feedback): add validation for feedback creation and update

Introduced validation functions for feedback creation and update in the new validation service.
Updated feedback controller to utilize these validation functions before processing requests.

* refactor(feedback): update validation to return feedback object

- Modified validateFeedbackExists to return the ChatMessageFeedback object instead of a boolean.
- Updated validateFeedbackForUpdate to utilize the returned feedback object for setting default values.
This commit is contained in:
Mehdi 2025-04-14 19:38:02 +01:00 committed by GitHub
parent 9d9b40a326
commit 54d1b5e3bb
No known key found for this signature in database
GPG Key ID: B5690EEEBB952194
2 changed files with 130 additions and 0 deletions

View File

@ -1,5 +1,6 @@
import { Request, Response, NextFunction } from 'express' import { Request, Response, NextFunction } from 'express'
import feedbackService from '../../services/feedback' import feedbackService from '../../services/feedback'
import { validateFeedbackForCreation, validateFeedbackForUpdate } from '../../services/feedback/validation'
import { InternalFlowiseError } from '../../errors/internalFlowiseError' import { InternalFlowiseError } from '../../errors/internalFlowiseError'
import { StatusCodes } from 'http-status-codes' import { StatusCodes } from 'http-status-codes'
@ -31,6 +32,7 @@ const createChatMessageFeedbackForChatflow = async (req: Request, res: Response,
`Error: feedbackController.createChatMessageFeedbackForChatflow - body not provided!` `Error: feedbackController.createChatMessageFeedbackForChatflow - body not provided!`
) )
} }
await validateFeedbackForCreation(req.body)
const apiResponse = await feedbackService.createChatMessageFeedbackForChatflow(req.body) const apiResponse = await feedbackService.createChatMessageFeedbackForChatflow(req.body)
return res.json(apiResponse) return res.json(apiResponse)
} catch (error) { } catch (error) {
@ -52,6 +54,7 @@ const updateChatMessageFeedbackForChatflow = async (req: Request, res: Response,
`Error: feedbackController.updateChatMessageFeedbackForChatflow - id not provided!` `Error: feedbackController.updateChatMessageFeedbackForChatflow - id not provided!`
) )
} }
await validateFeedbackForUpdate(req.params.id, req.body)
const apiResponse = await feedbackService.updateChatMessageFeedbackForChatflow(req.params.id, req.body) const apiResponse = await feedbackService.updateChatMessageFeedbackForChatflow(req.params.id, req.body)
return res.json(apiResponse) return res.json(apiResponse)
} catch (error) { } catch (error) {

View File

@ -0,0 +1,127 @@
import { StatusCodes } from 'http-status-codes'
import { IChatMessageFeedback } from '../../Interface'
import { InternalFlowiseError } from '../../errors/internalFlowiseError'
import { getRunningExpressApp } from '../../utils/getRunningExpressApp'
import { ChatMessage } from '../../database/entities/ChatMessage'
import { ChatMessageFeedback } from '../../database/entities/ChatMessageFeedback'
/**
* Validates that the message ID exists
* @param {string} messageId
*/
export const validateMessageExists = async (messageId: string): Promise<ChatMessage> => {
const appServer = getRunningExpressApp()
const message = await appServer.AppDataSource.getRepository(ChatMessage).findOne({
where: { id: messageId }
})
if (!message) {
throw new InternalFlowiseError(StatusCodes.NOT_FOUND, `Message with ID ${messageId} not found`)
}
return message
}
/**
* Validates that the feedback ID exists
* @param {string} feedbackId
*/
export const validateFeedbackExists = async (feedbackId: string): Promise<ChatMessageFeedback> => {
const appServer = getRunningExpressApp()
const feedbackExists = await appServer.AppDataSource.getRepository(ChatMessageFeedback).findOne({
where: { id: feedbackId }
})
if (!feedbackExists) {
throw new InternalFlowiseError(StatusCodes.NOT_FOUND, `Feedback with ID ${feedbackId} not found`)
}
return feedbackExists
}
/**
* Validates a feedback object for creation
* @param {Partial<IChatMessageFeedback>} feedback
*/
export const validateFeedbackForCreation = async (feedback: Partial<IChatMessageFeedback>): Promise<Partial<IChatMessageFeedback>> => {
// If messageId is provided, validate it exists and get the message
let message: ChatMessage | null = null
if (feedback.messageId) {
message = await validateMessageExists(feedback.messageId)
} else {
throw new InternalFlowiseError(StatusCodes.BAD_REQUEST, 'Message ID is required')
}
// If chatId is provided, validate it matches the message's chatId
if (feedback.chatId) {
if (message.chatId !== feedback.chatId) {
throw new InternalFlowiseError(
StatusCodes.BAD_REQUEST,
`Inconsistent chat ID: message with ID ${message.id} does not belong to chat with ID ${feedback.chatId}`
)
}
} else {
// If not provided, use the message's chatId
feedback.chatId = message.chatId
}
// If chatflowid is provided, validate it matches the message's chatflowid
if (feedback.chatflowid) {
if (message.chatflowid !== feedback.chatflowid) {
throw new InternalFlowiseError(
StatusCodes.BAD_REQUEST,
`Inconsistent chatflow ID: message with ID ${message.id} does not belong to chatflow with ID ${feedback.chatflowid}`
)
}
} else {
// If not provided, use the message's chatflowid
feedback.chatflowid = message.chatflowid
}
return feedback
}
/**
* Validates a feedback object for update
* @param {string} feedbackId
* @param {Partial<IChatMessageFeedback>} feedback
*/
export const validateFeedbackForUpdate = async (
feedbackId: string,
feedback: Partial<IChatMessageFeedback>
): Promise<Partial<IChatMessageFeedback>> => {
// First validate the feedback exists
const existingFeedback = await validateFeedbackExists(feedbackId)
feedback.messageId = feedback.messageId ?? existingFeedback.messageId
feedback.chatId = feedback.chatId ?? existingFeedback.chatId
feedback.chatflowid = feedback.chatflowid ?? existingFeedback.chatflowid
// If messageId is provided, validate it exists and get the message
let message: ChatMessage | null = null
if (feedback.messageId) {
message = await validateMessageExists(feedback.messageId)
}
// If chatId is provided and we have a message, validate it matches the message's chatId
if (feedback.chatId) {
if (message?.chatId !== feedback.chatId) {
throw new InternalFlowiseError(
StatusCodes.BAD_REQUEST,
`Inconsistent chat ID: message with ID ${message?.id} does not belong to chat with ID ${feedback.chatId}`
)
}
}
// If chatflowid is provided and we have a message, validate it matches the message's chatflowid
if (feedback.chatflowid && message) {
if (message?.chatflowid !== feedback.chatflowid) {
throw new InternalFlowiseError(
StatusCodes.BAD_REQUEST,
`Inconsistent chatflow ID: message with ID ${message?.id} does not belong to chatflow with ID ${feedback.chatflowid}`
)
}
}
return feedback
}