Chore/refractor (#4454)

* markdown files and env examples cleanup

* components update

* update jsonlines description

* server refractor

* update telemetry

* add execute custom node

* add ui refractor

* add username and password authenticate

* correctly retrieve past images in agentflowv2

* disable e2e temporarily

* add existing username and password authenticate

* update migration to default workspace

* update todo

* blob storage migrating

* throw error on agent tool call error

* add missing execution import

* add referral

* chore: add error message when importData is undefined

* migrate api keys to db

* fix: data too long for column executionData

* migrate api keys from json to db at init

* add info on account setup

* update docstore missing fields

---------

Co-authored-by: chungyau97 <chungyau97@gmail.com>
This commit is contained in:
Henry Heng
2025-05-27 14:29:42 +08:00
committed by GitHub
parent e35a126b46
commit 5a37227d14
560 changed files with 62127 additions and 4100 deletions
@@ -6,7 +6,8 @@ import apikeyService from '../../services/apikey'
// Get api keys
const getAllApiKeys = async (req: Request, res: Response, next: NextFunction) => {
try {
const apiResponse = await apikeyService.getAllApiKeys()
const autoCreateNewKey = true
const apiResponse = await apikeyService.getAllApiKeys(req.user?.activeWorkspaceId, autoCreateNewKey)
return res.json(apiResponse)
} catch (error) {
next(error)
@@ -18,7 +19,7 @@ const createApiKey = async (req: Request, res: Response, next: NextFunction) =>
if (typeof req.body === 'undefined' || !req.body.keyName) {
throw new InternalFlowiseError(StatusCodes.PRECONDITION_FAILED, `Error: apikeyController.createApiKey - keyName not provided!`)
}
const apiResponse = await apikeyService.createApiKey(req.body.keyName)
const apiResponse = await apikeyService.createApiKey(req.body.keyName, req.user?.activeWorkspaceId)
return res.json(apiResponse)
} catch (error) {
next(error)
@@ -34,7 +35,7 @@ const updateApiKey = async (req: Request, res: Response, next: NextFunction) =>
if (typeof req.body === 'undefined' || !req.body.keyName) {
throw new InternalFlowiseError(StatusCodes.PRECONDITION_FAILED, `Error: apikeyController.updateApiKey - keyName not provided!`)
}
const apiResponse = await apikeyService.updateApiKey(req.params.id, req.body.keyName)
const apiResponse = await apikeyService.updateApiKey(req.params.id, req.body.keyName, req.user?.activeWorkspaceId)
return res.json(apiResponse)
} catch (error) {
next(error)
@@ -47,6 +48,7 @@ const importKeys = async (req: Request, res: Response, next: NextFunction) => {
if (typeof req.body === 'undefined' || !req.body.jsonFile) {
throw new InternalFlowiseError(StatusCodes.PRECONDITION_FAILED, `Error: apikeyController.importKeys - body not provided!`)
}
req.body.workspaceId = req.user?.activeWorkspaceId
const apiResponse = await apikeyService.importKeys(req.body)
return res.json(apiResponse)
} catch (error) {
@@ -60,7 +62,7 @@ const deleteApiKey = async (req: Request, res: Response, next: NextFunction) =>
if (typeof req.params === 'undefined' || !req.params.id) {
throw new InternalFlowiseError(StatusCodes.PRECONDITION_FAILED, `Error: apikeyController.deleteApiKey - id not provided!`)
}
const apiResponse = await apikeyService.deleteApiKey(req.params.id)
const apiResponse = await apikeyService.deleteApiKey(req.params.id, req.user?.activeWorkspaceId)
return res.json(apiResponse)
} catch (error) {
next(error)
@@ -1,8 +1,10 @@
import { Request, Response, NextFunction } from 'express'
import assistantsService from '../../services/assistants'
import { InternalFlowiseError } from '../../errors/internalFlowiseError'
import { NextFunction, Request, Response } from 'express'
import { StatusCodes } from 'http-status-codes'
import { InternalFlowiseError } from '../../errors/internalFlowiseError'
import { AssistantType } from '../../Interface'
import assistantsService from '../../services/assistants'
import { getRunningExpressApp } from '../../utils/getRunningExpressApp'
import { checkUsageLimit } from '../../utils/quotaUsage'
const createAssistant = async (req: Request, res: Response, next: NextFunction) => {
try {
@@ -12,7 +14,30 @@ const createAssistant = async (req: Request, res: Response, next: NextFunction)
`Error: assistantsController.createAssistant - body not provided!`
)
}
const apiResponse = await assistantsService.createAssistant(req.body)
const body = req.body
const orgId = req.user?.activeOrganizationId
if (!orgId) {
throw new InternalFlowiseError(
StatusCodes.NOT_FOUND,
`Error: assistantsController.createAssistant - organization ${orgId} not found!`
)
}
const workspaceId = req.user?.activeWorkspaceId
if (!workspaceId) {
throw new InternalFlowiseError(
StatusCodes.NOT_FOUND,
`Error: assistantsController.createAssistant - workspace ${workspaceId} not found!`
)
}
const subscriptionId = req.user?.activeOrganizationSubscriptionId || ''
const existingAssistantCount = await assistantsService.getAssistantsCountByOrganization(body.type, orgId)
const newAssistantCount = 1
await checkUsageLimit('flows', subscriptionId, getRunningExpressApp().usageCacheManager, existingAssistantCount + newAssistantCount)
body.workspaceId = workspaceId
const apiResponse = await assistantsService.createAssistant(body, orgId)
return res.json(apiResponse)
} catch (error) {
next(error)
@@ -37,7 +62,7 @@ const deleteAssistant = async (req: Request, res: Response, next: NextFunction)
const getAllAssistants = async (req: Request, res: Response, next: NextFunction) => {
try {
const type = req.query.type as AssistantType
const apiResponse = await assistantsService.getAllAssistants(type)
const apiResponse = await assistantsService.getAllAssistants(type, req.user?.activeWorkspaceId)
return res.json(apiResponse)
} catch (error) {
next(error)
@@ -91,7 +116,7 @@ const getChatModels = async (req: Request, res: Response, next: NextFunction) =>
const getDocumentStores = async (req: Request, res: Response, next: NextFunction) => {
try {
const apiResponse = await assistantsService.getDocumentStores()
const apiResponse = await assistantsService.getDocumentStores(req.user?.activeWorkspaceId)
return res.json(apiResponse)
} catch (error) {
next(error)
@@ -62,6 +62,7 @@ const getAllChatMessages = async (req: Request, res: Response, next: NextFunctio
chatTypes = [_chatTypes as ChatType]
}
}
const activeWorkspaceId = req.user?.activeWorkspaceId
const sortOrder = req.query?.order as string | undefined
const chatId = req.query?.chatId as string | undefined
const memoryType = req.query?.memoryType as string | undefined
@@ -91,9 +92,9 @@ const getAllChatMessages = async (req: Request, res: Response, next: NextFunctio
endDate,
messageId,
feedback,
feedbackTypeFilters
feedbackTypeFilters,
activeWorkspaceId
)
return res.json(parseAPIResponse(apiResponse))
} catch (error) {
next(error)
@@ -102,6 +103,7 @@ const getAllChatMessages = async (req: Request, res: Response, next: NextFunctio
const getAllInternalChatMessages = async (req: Request, res: Response, next: NextFunction) => {
try {
const activeWorkspaceId = req.user?.activeWorkspaceId
const sortOrder = req.query?.order as string | undefined
const chatId = req.query?.chatId as string | undefined
const memoryType = req.query?.memoryType as string | undefined
@@ -125,7 +127,8 @@ const getAllInternalChatMessages = async (req: Request, res: Response, next: Nex
endDate,
messageId,
feedback,
feedbackTypeFilters
feedbackTypeFilters,
activeWorkspaceId
)
return res.json(parseAPIResponse(apiResponse))
} catch (error) {
@@ -142,6 +145,20 @@ const removeAllChatMessages = async (req: Request, res: Response, next: NextFunc
'Error: chatMessagesController.removeAllChatMessages - id not provided!'
)
}
const orgId = req.user?.activeOrganizationId
if (!orgId) {
throw new InternalFlowiseError(
StatusCodes.NOT_FOUND,
`Error: chatMessagesController.removeAllChatMessages - organization ${orgId} not found!`
)
}
const workspaceId = req.user?.activeWorkspaceId
if (!workspaceId) {
throw new InternalFlowiseError(
StatusCodes.NOT_FOUND,
`Error: chatMessagesController.removeAllChatMessages - workspace ${workspaceId} not found!`
)
}
const chatflowid = req.params.id
const chatflow = await chatflowsService.getChatflowById(req.params.id)
if (!chatflow) {
@@ -177,6 +194,7 @@ const removeAllChatMessages = async (req: Request, res: Response, next: NextFunc
if (!chatId) {
const isFeedback = feedbackTypeFilters?.length ? true : false
const hardDelete = req.query?.hardDelete as boolean | undefined
const messages = await utilGetChatMessage({
chatflowid,
chatTypes,
@@ -216,6 +234,7 @@ const removeAllChatMessages = async (req: Request, res: Response, next: NextFunc
appServer.nodesPool.componentNodes,
chatId,
appServer.AppDataSource,
orgId,
sessionId,
memoryType,
isClearFromViewMessageDialog
@@ -226,7 +245,14 @@ const removeAllChatMessages = async (req: Request, res: Response, next: NextFunc
}
}
const apiResponse = await chatMessagesService.removeChatMessagesByMessageIds(chatflowid, chatIdMap, messageIds)
const apiResponse = await chatMessagesService.removeChatMessagesByMessageIds(
chatflowid,
chatIdMap,
messageIds,
orgId,
workspaceId,
appServer.usageCacheManager
)
return res.json(apiResponse)
} else {
try {
@@ -235,6 +261,7 @@ const removeAllChatMessages = async (req: Request, res: Response, next: NextFunc
appServer.nodesPool.componentNodes,
chatId,
appServer.AppDataSource,
orgId,
sessionId,
memoryType,
isClearFromViewMessageDialog
@@ -255,7 +282,14 @@ const removeAllChatMessages = async (req: Request, res: Response, next: NextFunc
const toDate = new Date(endDate)
deleteOptions.createdDate = Between(fromDate ?? aMonthAgo(), toDate ?? new Date())
}
const apiResponse = await chatMessagesService.removeAllChatMessages(chatId, chatflowid, deleteOptions)
const apiResponse = await chatMessagesService.removeAllChatMessages(
chatId,
chatflowid,
deleteOptions,
orgId,
workspaceId,
appServer.usageCacheManager
)
return res.json(apiResponse)
}
} catch (error) {
@@ -282,26 +316,30 @@ const parseAPIResponse = (apiResponse: ChatMessage | ChatMessage[]): ChatMessage
const parseResponse = (response: ChatMessage): ChatMessage => {
const parsedResponse = { ...response }
if (parsedResponse.sourceDocuments) {
parsedResponse.sourceDocuments = JSON.parse(parsedResponse.sourceDocuments)
}
if (parsedResponse.usedTools) {
parsedResponse.usedTools = JSON.parse(parsedResponse.usedTools)
}
if (parsedResponse.fileAnnotations) {
parsedResponse.fileAnnotations = JSON.parse(parsedResponse.fileAnnotations)
}
if (parsedResponse.agentReasoning) {
parsedResponse.agentReasoning = JSON.parse(parsedResponse.agentReasoning)
}
if (parsedResponse.fileUploads) {
parsedResponse.fileUploads = JSON.parse(parsedResponse.fileUploads)
}
if (parsedResponse.action) {
parsedResponse.action = JSON.parse(parsedResponse.action)
}
if (parsedResponse.artifacts) {
parsedResponse.artifacts = JSON.parse(parsedResponse.artifacts)
try {
if (parsedResponse.sourceDocuments) {
parsedResponse.sourceDocuments = JSON.parse(parsedResponse.sourceDocuments)
}
if (parsedResponse.usedTools) {
parsedResponse.usedTools = JSON.parse(parsedResponse.usedTools)
}
if (parsedResponse.fileAnnotations) {
parsedResponse.fileAnnotations = JSON.parse(parsedResponse.fileAnnotations)
}
if (parsedResponse.agentReasoning) {
parsedResponse.agentReasoning = JSON.parse(parsedResponse.agentReasoning)
}
if (parsedResponse.fileUploads) {
parsedResponse.fileUploads = JSON.parse(parsedResponse.fileUploads)
}
if (parsedResponse.action) {
parsedResponse.action = JSON.parse(parsedResponse.action)
}
if (parsedResponse.artifacts) {
parsedResponse.artifacts = JSON.parse(parsedResponse.artifacts)
}
} catch (e) {
console.error('Error parsing chat message response', e)
}
return parsedResponse
@@ -1,18 +1,20 @@
import { NextFunction, Request, Response } from 'express'
import { StatusCodes } from 'http-status-codes'
import apiKeyService from '../../services/apikey'
import { ChatFlow } from '../../database/entities/ChatFlow'
import { RateLimiterManager } from '../../utils/rateLimit'
import { InternalFlowiseError } from '../../errors/internalFlowiseError'
import { ChatflowType } from '../../Interface'
import apiKeyService from '../../services/apikey'
import chatflowsService from '../../services/chatflows'
import { getRunningExpressApp } from '../../utils/getRunningExpressApp'
import { checkUsageLimit } from '../../utils/quotaUsage'
import { RateLimiterManager } from '../../utils/rateLimit'
const checkIfChatflowIsValidForStreaming = async (req: Request, res: Response, next: NextFunction) => {
try {
if (typeof req.params === 'undefined' || !req.params.id) {
throw new InternalFlowiseError(
StatusCodes.PRECONDITION_FAILED,
`Error: chatflowsRouter.checkIfChatflowIsValidForStreaming - id not provided!`
`Error: chatflowsController.checkIfChatflowIsValidForStreaming - id not provided!`
)
}
const apiResponse = await chatflowsService.checkIfChatflowIsValidForStreaming(req.params.id)
@@ -27,7 +29,7 @@ const checkIfChatflowIsValidForUploads = async (req: Request, res: Response, nex
if (typeof req.params === 'undefined' || !req.params.id) {
throw new InternalFlowiseError(
StatusCodes.PRECONDITION_FAILED,
`Error: chatflowsRouter.checkIfChatflowIsValidForUploads - id not provided!`
`Error: chatflowsController.checkIfChatflowIsValidForUploads - id not provided!`
)
}
const apiResponse = await chatflowsService.checkIfChatflowIsValidForUploads(req.params.id)
@@ -40,9 +42,23 @@ const checkIfChatflowIsValidForUploads = async (req: Request, res: Response, nex
const deleteChatflow = async (req: Request, res: Response, next: NextFunction) => {
try {
if (typeof req.params === 'undefined' || !req.params.id) {
throw new InternalFlowiseError(StatusCodes.PRECONDITION_FAILED, `Error: chatflowsRouter.deleteChatflow - id not provided!`)
throw new InternalFlowiseError(StatusCodes.PRECONDITION_FAILED, `Error: chatflowsController.deleteChatflow - id not provided!`)
}
const apiResponse = await chatflowsService.deleteChatflow(req.params.id)
const orgId = req.user?.activeOrganizationId
if (!orgId) {
throw new InternalFlowiseError(
StatusCodes.NOT_FOUND,
`Error: chatflowsController.deleteChatflow - organization ${orgId} not found!`
)
}
const workspaceId = req.user?.activeWorkspaceId
if (!workspaceId) {
throw new InternalFlowiseError(
StatusCodes.NOT_FOUND,
`Error: chatflowsController.deleteChatflow - workspace ${workspaceId} not found!`
)
}
const apiResponse = await chatflowsService.deleteChatflow(req.params.id, orgId, workspaceId)
return res.json(apiResponse)
} catch (error) {
next(error)
@@ -51,7 +67,7 @@ const deleteChatflow = async (req: Request, res: Response, next: NextFunction) =
const getAllChatflows = async (req: Request, res: Response, next: NextFunction) => {
try {
const apiResponse = await chatflowsService.getAllChatflows(req.query?.type as ChatflowType)
const apiResponse = await chatflowsService.getAllChatflows(req.query?.type as ChatflowType, req.user?.activeWorkspaceId)
return res.json(apiResponse)
} catch (error) {
next(error)
@@ -64,7 +80,7 @@ const getChatflowByApiKey = async (req: Request, res: Response, next: NextFuncti
if (typeof req.params === 'undefined' || !req.params.apikey) {
throw new InternalFlowiseError(
StatusCodes.PRECONDITION_FAILED,
`Error: chatflowsRouter.getChatflowByApiKey - apikey not provided!`
`Error: chatflowsController.getChatflowByApiKey - apikey not provided!`
)
}
const apikey = await apiKeyService.getApiKey(req.params.apikey)
@@ -81,7 +97,7 @@ const getChatflowByApiKey = async (req: Request, res: Response, next: NextFuncti
const getChatflowById = async (req: Request, res: Response, next: NextFunction) => {
try {
if (typeof req.params === 'undefined' || !req.params.id) {
throw new InternalFlowiseError(StatusCodes.PRECONDITION_FAILED, `Error: chatflowsRouter.getChatflowById - id not provided!`)
throw new InternalFlowiseError(StatusCodes.PRECONDITION_FAILED, `Error: chatflowsController.getChatflowById - id not provided!`)
}
const apiResponse = await chatflowsService.getChatflowById(req.params.id)
return res.json(apiResponse)
@@ -93,12 +109,40 @@ const getChatflowById = async (req: Request, res: Response, next: NextFunction)
const saveChatflow = async (req: Request, res: Response, next: NextFunction) => {
try {
if (!req.body) {
throw new InternalFlowiseError(StatusCodes.PRECONDITION_FAILED, `Error: chatflowsRouter.saveChatflow - body not provided!`)
throw new InternalFlowiseError(StatusCodes.PRECONDITION_FAILED, `Error: chatflowsController.saveChatflow - body not provided!`)
}
const orgId = req.user?.activeOrganizationId
if (!orgId) {
throw new InternalFlowiseError(
StatusCodes.NOT_FOUND,
`Error: chatflowsController.saveChatflow - organization ${orgId} not found!`
)
}
const workspaceId = req.user?.activeWorkspaceId
if (!workspaceId) {
throw new InternalFlowiseError(
StatusCodes.NOT_FOUND,
`Error: chatflowsController.saveChatflow - workspace ${workspaceId} not found!`
)
}
const subscriptionId = req.user?.activeOrganizationSubscriptionId || ''
const body = req.body
const existingChatflowCount = await chatflowsService.getAllChatflowsCountByOrganization(body.type, orgId)
const newChatflowCount = 1
await checkUsageLimit('flows', subscriptionId, getRunningExpressApp().usageCacheManager, existingChatflowCount + newChatflowCount)
const newChatFlow = new ChatFlow()
Object.assign(newChatFlow, body)
const apiResponse = await chatflowsService.saveChatflow(newChatFlow)
newChatFlow.workspaceId = workspaceId
const apiResponse = await chatflowsService.saveChatflow(
newChatFlow,
orgId,
workspaceId,
subscriptionId,
getRunningExpressApp().usageCacheManager
)
return res.json(apiResponse)
} catch (error) {
next(error)
@@ -108,7 +152,23 @@ const saveChatflow = async (req: Request, res: Response, next: NextFunction) =>
const importChatflows = async (req: Request, res: Response, next: NextFunction) => {
try {
const chatflows: Partial<ChatFlow>[] = req.body.Chatflows
const apiResponse = await chatflowsService.importChatflows(chatflows)
const orgId = req.user?.activeOrganizationId
if (!orgId) {
throw new InternalFlowiseError(
StatusCodes.NOT_FOUND,
`Error: chatflowsController.saveChatflow - organization ${orgId} not found!`
)
}
const workspaceId = req.user?.activeWorkspaceId
if (!workspaceId) {
throw new InternalFlowiseError(
StatusCodes.NOT_FOUND,
`Error: chatflowsController.saveChatflow - workspace ${workspaceId} not found!`
)
}
const subscriptionId = req.user?.activeOrganizationSubscriptionId || ''
req.body.workspaceId = req.user?.activeWorkspaceId
const apiResponse = await chatflowsService.importChatflows(chatflows, orgId, workspaceId, subscriptionId)
return res.json(apiResponse)
} catch (error) {
next(error)
@@ -118,13 +178,27 @@ const importChatflows = async (req: Request, res: Response, next: NextFunction)
const updateChatflow = async (req: Request, res: Response, next: NextFunction) => {
try {
if (typeof req.params === 'undefined' || !req.params.id) {
throw new InternalFlowiseError(StatusCodes.PRECONDITION_FAILED, `Error: chatflowsRouter.updateChatflow - id not provided!`)
throw new InternalFlowiseError(StatusCodes.PRECONDITION_FAILED, `Error: chatflowsController.updateChatflow - id not provided!`)
}
const chatflow = await chatflowsService.getChatflowById(req.params.id)
if (!chatflow) {
return res.status(404).send(`Chatflow ${req.params.id} not found`)
}
const orgId = req.user?.activeOrganizationId
if (!orgId) {
throw new InternalFlowiseError(
StatusCodes.NOT_FOUND,
`Error: chatflowsController.saveChatflow - organization ${orgId} not found!`
)
}
const workspaceId = req.user?.activeWorkspaceId
if (!workspaceId) {
throw new InternalFlowiseError(
StatusCodes.NOT_FOUND,
`Error: chatflowsController.saveChatflow - workspace ${workspaceId} not found!`
)
}
const subscriptionId = req.user?.activeOrganizationSubscriptionId || ''
const body = req.body
const updateChatFlow = new ChatFlow()
Object.assign(updateChatFlow, body)
@@ -133,7 +207,7 @@ const updateChatflow = async (req: Request, res: Response, next: NextFunction) =
const rateLimiterManager = RateLimiterManager.getInstance()
await rateLimiterManager.updateRateLimiter(updateChatFlow)
const apiResponse = await chatflowsService.updateChatflow(chatflow, updateChatFlow)
const apiResponse = await chatflowsService.updateChatflow(chatflow, updateChatFlow, orgId, workspaceId, subscriptionId)
return res.json(apiResponse)
} catch (error) {
next(error)
@@ -145,7 +219,7 @@ const getSinglePublicChatflow = async (req: Request, res: Response, next: NextFu
if (typeof req.params === 'undefined' || !req.params.id) {
throw new InternalFlowiseError(
StatusCodes.PRECONDITION_FAILED,
`Error: chatflowsRouter.getSinglePublicChatflow - id not provided!`
`Error: chatflowsController.getSinglePublicChatflow - id not provided!`
)
}
const apiResponse = await chatflowsService.getSinglePublicChatflow(req.params.id)
@@ -160,7 +234,7 @@ const getSinglePublicChatbotConfig = async (req: Request, res: Response, next: N
if (typeof req.params === 'undefined' || !req.params.id) {
throw new InternalFlowiseError(
StatusCodes.PRECONDITION_FAILED,
`Error: chatflowsRouter.getSinglePublicChatbotConfig - id not provided!`
`Error: chatflowsController.getSinglePublicChatbotConfig - id not provided!`
)
}
const apiResponse = await chatflowsService.getSinglePublicChatbotConfig(req.params.id)
@@ -170,6 +244,27 @@ const getSinglePublicChatbotConfig = async (req: Request, res: Response, next: N
}
}
const checkIfChatflowHasChanged = async (req: Request, res: Response, next: NextFunction) => {
try {
if (typeof req.params === 'undefined' || !req.params.id) {
throw new InternalFlowiseError(
StatusCodes.PRECONDITION_FAILED,
`Error: chatflowsController.checkIfChatflowHasChanged - id not provided!`
)
}
if (!req.params.lastUpdatedDateTime) {
throw new InternalFlowiseError(
StatusCodes.PRECONDITION_FAILED,
`Error: chatflowsController.checkIfChatflowHasChanged - lastUpdatedDateTime not provided!`
)
}
const apiResponse = await chatflowsService.checkIfChatflowHasChanged(req.params.id, req.params.lastUpdatedDateTime)
return res.json(apiResponse)
} catch (error) {
next(error)
}
}
export default {
checkIfChatflowIsValidForStreaming,
checkIfChatflowIsValidForUploads,
@@ -181,5 +276,6 @@ export default {
importChatflows,
updateChatflow,
getSinglePublicChatflow,
getSinglePublicChatbotConfig
getSinglePublicChatbotConfig,
checkIfChatflowHasChanged
}
@@ -11,7 +11,9 @@ const createCredential = async (req: Request, res: Response, next: NextFunction)
`Error: credentialsController.createCredential - body not provided!`
)
}
const apiResponse = await credentialsService.createCredential(req.body)
const body = req.body
body.workspaceId = req.user?.activeWorkspaceId
const apiResponse = await credentialsService.createCredential(body)
return res.json(apiResponse)
} catch (error) {
next(error)
@@ -35,7 +37,7 @@ const deleteCredentials = async (req: Request, res: Response, next: NextFunction
const getAllCredentials = async (req: Request, res: Response, next: NextFunction) => {
try {
const apiResponse = await credentialsService.getAllCredentials(req.query.credentialName)
const apiResponse = await credentialsService.getAllCredentials(req.query.credentialName, req.user?.activeWorkspaceId)
return res.json(apiResponse)
} catch (error) {
next(error)
@@ -50,7 +52,7 @@ const getCredentialById = async (req: Request, res: Response, next: NextFunction
`Error: credentialsController.getCredentialById - id not provided!`
)
}
const apiResponse = await credentialsService.getCredentialById(req.params.id)
const apiResponse = await credentialsService.getCredentialById(req.params.id, req.user?.activeWorkspaceId)
return res.json(apiResponse)
} catch (error) {
next(error)
@@ -0,0 +1,143 @@
import { Request, Response, NextFunction } from 'express'
import { InternalFlowiseError } from '../../errors/internalFlowiseError'
import datasetService from '../../services/dataset'
import { StatusCodes } from 'http-status-codes'
const getAllDatasets = async (req: Request, res: Response, next: NextFunction) => {
try {
const apiResponse = await datasetService.getAllDatasets(req.user?.activeWorkspaceId)
return res.json(apiResponse)
} catch (error) {
next(error)
}
}
const getDataset = async (req: Request, res: Response, next: NextFunction) => {
try {
if (typeof req.params === 'undefined' || !req.params.id) {
throw new InternalFlowiseError(StatusCodes.PRECONDITION_FAILED, `Error: datasetService.getDataset - id not provided!`)
}
const apiResponse = await datasetService.getDataset(req.params.id)
return res.json(apiResponse)
} catch (error) {
next(error)
}
}
const createDataset = async (req: Request, res: Response, next: NextFunction) => {
try {
if (!req.body) {
throw new InternalFlowiseError(StatusCodes.PRECONDITION_FAILED, `Error: datasetService.createDataset - body not provided!`)
}
const body = req.body
body.workspaceId = req.user?.activeWorkspaceId
const apiResponse = await datasetService.createDataset(body)
return res.json(apiResponse)
} catch (error) {
next(error)
}
}
const updateDataset = async (req: Request, res: Response, next: NextFunction) => {
try {
if (!req.body) {
throw new InternalFlowiseError(StatusCodes.PRECONDITION_FAILED, `Error: datasetService.updateDataset - body not provided!`)
}
if (typeof req.params === 'undefined' || !req.params.id) {
throw new InternalFlowiseError(StatusCodes.PRECONDITION_FAILED, `Error: datasetService.updateDataset - id not provided!`)
}
const apiResponse = await datasetService.updateDataset(req.params.id, req.body)
return res.json(apiResponse)
} catch (error) {
next(error)
}
}
const deleteDataset = async (req: Request, res: Response, next: NextFunction) => {
try {
if (typeof req.params === 'undefined' || !req.params.id) {
throw new InternalFlowiseError(StatusCodes.PRECONDITION_FAILED, `Error: datasetService.deleteDataset - id not provided!`)
}
const apiResponse = await datasetService.deleteDataset(req.params.id)
return res.json(apiResponse)
} catch (error) {
next(error)
}
}
const addDatasetRow = async (req: Request, res: Response, next: NextFunction) => {
try {
if (!req.body) {
throw new InternalFlowiseError(StatusCodes.PRECONDITION_FAILED, `Error: datasetService.addDatasetRow - body not provided!`)
}
if (!req.body.datasetId) {
throw new InternalFlowiseError(StatusCodes.PRECONDITION_FAILED, `Error: datasetService.addDatasetRow - datasetId not provided!`)
}
const apiResponse = await datasetService.addDatasetRow(req.body)
return res.json(apiResponse)
} catch (error) {
next(error)
}
}
const updateDatasetRow = async (req: Request, res: Response, next: NextFunction) => {
try {
if (!req.body) {
throw new InternalFlowiseError(StatusCodes.PRECONDITION_FAILED, `Error: datasetService.updateDatasetRow - body not provided!`)
}
if (typeof req.params === 'undefined' || !req.params.id) {
throw new InternalFlowiseError(StatusCodes.PRECONDITION_FAILED, `Error: datasetService.updateDatasetRow - id not provided!`)
}
const apiResponse = await datasetService.updateDatasetRow(req.params.id, req.body)
return res.json(apiResponse)
} catch (error) {
next(error)
}
}
const deleteDatasetRow = async (req: Request, res: Response, next: NextFunction) => {
try {
if (typeof req.params === 'undefined' || !req.params.id) {
throw new InternalFlowiseError(StatusCodes.PRECONDITION_FAILED, `Error: datasetService.deleteDatasetRow - id not provided!`)
}
const apiResponse = await datasetService.deleteDatasetRow(req.params.id)
return res.json(apiResponse)
} catch (error) {
next(error)
}
}
const patchDeleteRows = async (req: Request, res: Response, next: NextFunction) => {
try {
const ids = req.body.ids ?? []
const apiResponse = await datasetService.patchDeleteRows(ids)
return res.json(apiResponse)
} catch (error) {
next(error)
}
}
const reorderDatasetRow = async (req: Request, res: Response, next: NextFunction) => {
try {
if (!req.body) {
throw new InternalFlowiseError(StatusCodes.PRECONDITION_FAILED, `Error: datasetService.reorderDatasetRow - body not provided!`)
}
const apiResponse = await datasetService.reorderDatasetRow(req.body.datasetId, req.body.rows)
return res.json(apiResponse)
} catch (error) {
next(error)
}
}
export default {
getAllDatasets,
getDataset,
createDataset,
updateDataset,
deleteDataset,
addDatasetRow,
updateDatasetRow,
deleteDatasetRow,
patchDeleteRows,
reorderDatasetRow
}
@@ -15,9 +15,20 @@ const createDocumentStore = async (req: Request, res: Response, next: NextFuncti
`Error: documentStoreController.createDocumentStore - body not provided!`
)
}
const orgId = req.user?.activeOrganizationId
if (!orgId) {
throw new InternalFlowiseError(
StatusCodes.PRECONDITION_FAILED,
`Error: documentStoreController.createDocumentStore - organizationId not provided!`
)
}
const body = req.body
body.workspaceId = req.user?.activeWorkspaceId
const docStore = DocumentStoreDTO.toEntity(body)
const apiResponse = await documentStoreService.createDocumentStore(docStore)
const apiResponse = await documentStoreService.createDocumentStore(docStore, orgId)
return res.json(apiResponse)
} catch (error) {
next(error)
@@ -26,7 +37,7 @@ const createDocumentStore = async (req: Request, res: Response, next: NextFuncti
const getAllDocumentStores = async (req: Request, res: Response, next: NextFunction) => {
try {
const apiResponse = await documentStoreService.getAllDocumentStores()
const apiResponse = await documentStoreService.getAllDocumentStores(req.user?.activeWorkspaceId)
return res.json(DocumentStoreDTO.fromEntities(apiResponse))
} catch (error) {
next(error)
@@ -44,7 +55,29 @@ const deleteLoaderFromDocumentStore = async (req: Request, res: Response, next:
`Error: documentStoreController.deleteLoaderFromDocumentStore - missing storeId or loaderId.`
)
}
const apiResponse = await documentStoreService.deleteLoaderFromDocumentStore(storeId, loaderId)
const orgId = req.user?.activeOrganizationId
if (!orgId) {
throw new InternalFlowiseError(
StatusCodes.PRECONDITION_FAILED,
`Error: documentStoreController.createDocumentStore - organizationId not provided!`
)
}
const workspaceId = req.user?.activeWorkspaceId
if (!workspaceId) {
throw new InternalFlowiseError(
StatusCodes.PRECONDITION_FAILED,
`Error: documentStoreController.createDocumentStore - workspaceId not provided!`
)
}
const apiResponse = await documentStoreService.deleteLoaderFromDocumentStore(
storeId,
loaderId,
orgId,
workspaceId,
getRunningExpressApp().usageCacheManager
)
return res.json(DocumentStoreDTO.fromEntity(apiResponse))
} catch (error) {
next(error)
@@ -199,10 +232,33 @@ const processLoader = async (req: Request, res: Response, next: NextFunction) =>
`Error: documentStoreController.processLoader - body not provided!`
)
}
const orgId = req.user?.activeOrganizationId
if (!orgId) {
throw new InternalFlowiseError(
StatusCodes.PRECONDITION_FAILED,
`Error: documentStoreController.createDocumentStore - organizationId not provided!`
)
}
const workspaceId = req.user?.activeWorkspaceId
if (!workspaceId) {
throw new InternalFlowiseError(
StatusCodes.PRECONDITION_FAILED,
`Error: documentStoreController.createDocumentStore - workspaceId not provided!`
)
}
const subscriptionId = req.user?.activeOrganizationSubscriptionId || ''
const docLoaderId = req.params.loaderId
const body = req.body
const isInternalRequest = req.headers['x-request-from'] === 'internal'
const apiResponse = await documentStoreService.processLoaderMiddleware(body, docLoaderId, isInternalRequest)
const apiResponse = await documentStoreService.processLoaderMiddleware(
body,
docLoaderId,
orgId,
workspaceId,
subscriptionId,
getRunningExpressApp().usageCacheManager,
isInternalRequest
)
return res.json(apiResponse)
} catch (error) {
next(error)
@@ -248,7 +304,26 @@ const deleteDocumentStore = async (req: Request, res: Response, next: NextFuncti
`Error: documentStoreController.deleteDocumentStore - storeId not provided!`
)
}
const apiResponse = await documentStoreService.deleteDocumentStore(req.params.id)
const orgId = req.user?.activeOrganizationId
if (!orgId) {
throw new InternalFlowiseError(
StatusCodes.PRECONDITION_FAILED,
`Error: documentStoreController.createDocumentStore - organizationId not provided!`
)
}
const workspaceId = req.user?.activeWorkspaceId
if (!workspaceId) {
throw new InternalFlowiseError(
StatusCodes.PRECONDITION_FAILED,
`Error: documentStoreController.createDocumentStore - workspaceId not provided!`
)
}
const apiResponse = await documentStoreService.deleteDocumentStore(
req.params.id,
orgId,
workspaceId,
getRunningExpressApp().usageCacheManager
)
return res.json(apiResponse)
} catch (error) {
next(error)
@@ -263,9 +338,30 @@ const previewFileChunks = async (req: Request, res: Response, next: NextFunction
`Error: documentStoreController.previewFileChunks - body not provided!`
)
}
const orgId = req.user?.activeOrganizationId
if (!orgId) {
throw new InternalFlowiseError(
StatusCodes.PRECONDITION_FAILED,
`Error: documentStoreController.createDocumentStore - organizationId not provided!`
)
}
const workspaceId = req.user?.activeWorkspaceId
if (!workspaceId) {
throw new InternalFlowiseError(
StatusCodes.PRECONDITION_FAILED,
`Error: documentStoreController.createDocumentStore - workspaceId not provided!`
)
}
const subscriptionId = req.user?.activeOrganizationSubscriptionId || ''
const body = req.body
body.preview = true
const apiResponse = await documentStoreService.previewChunksMiddleware(body)
const apiResponse = await documentStoreService.previewChunksMiddleware(
body,
orgId,
workspaceId,
subscriptionId,
getRunningExpressApp().usageCacheManager
)
return res.json(apiResponse)
} catch (error) {
next(error)
@@ -286,8 +382,30 @@ const insertIntoVectorStore = async (req: Request, res: Response, next: NextFunc
if (typeof req.body === 'undefined') {
throw new Error('Error: documentStoreController.insertIntoVectorStore - body not provided!')
}
const orgId = req.user?.activeOrganizationId
if (!orgId) {
throw new InternalFlowiseError(
StatusCodes.PRECONDITION_FAILED,
`Error: documentStoreController.createDocumentStore - organizationId not provided!`
)
}
const workspaceId = req.user?.activeWorkspaceId
if (!workspaceId) {
throw new InternalFlowiseError(
StatusCodes.PRECONDITION_FAILED,
`Error: documentStoreController.createDocumentStore - workspaceId not provided!`
)
}
const subscriptionId = req.user?.activeOrganizationSubscriptionId || ''
const body = req.body
const apiResponse = await documentStoreService.insertIntoVectorStoreMiddleware(body)
const apiResponse = await documentStoreService.insertIntoVectorStoreMiddleware(
body,
false,
orgId,
workspaceId,
subscriptionId,
getRunningExpressApp().usageCacheManager
)
getRunningExpressApp().metricsProvider?.incrementCounter(FLOWISE_METRIC_COUNTERS.VECTORSTORE_UPSERT, {
status: FLOWISE_COUNTER_STATUS.SUCCESS
})
@@ -393,9 +511,32 @@ const upsertDocStoreMiddleware = async (req: Request, res: Response, next: NextF
if (typeof req.body === 'undefined') {
throw new Error('Error: documentStoreController.upsertDocStoreMiddleware - body not provided!')
}
const orgId = req.user?.activeOrganizationId
if (!orgId) {
throw new InternalFlowiseError(
StatusCodes.PRECONDITION_FAILED,
`Error: documentStoreController.createDocumentStore - organizationId not provided!`
)
}
const workspaceId = req.user?.activeWorkspaceId
if (!workspaceId) {
throw new InternalFlowiseError(
StatusCodes.PRECONDITION_FAILED,
`Error: documentStoreController.createDocumentStore - workspaceId not provided!`
)
}
const subscriptionId = req.user?.activeOrganizationSubscriptionId || ''
const body = req.body
const files = (req.files as Express.Multer.File[]) || []
const apiResponse = await documentStoreService.upsertDocStoreMiddleware(req.params.id, body, files)
const apiResponse = await documentStoreService.upsertDocStoreMiddleware(
req.params.id,
body,
files,
orgId,
workspaceId,
subscriptionId,
getRunningExpressApp().usageCacheManager
)
getRunningExpressApp().metricsProvider?.incrementCounter(FLOWISE_METRIC_COUNTERS.VECTORSTORE_UPSERT, {
status: FLOWISE_COUNTER_STATUS.SUCCESS
})
@@ -416,8 +557,30 @@ const refreshDocStoreMiddleware = async (req: Request, res: Response, next: Next
`Error: documentStoreController.refreshDocStoreMiddleware - storeId not provided!`
)
}
const orgId = req.user?.activeOrganizationId
if (!orgId) {
throw new InternalFlowiseError(
StatusCodes.PRECONDITION_FAILED,
`Error: documentStoreController.createDocumentStore - organizationId not provided!`
)
}
const workspaceId = req.user?.activeWorkspaceId
if (!workspaceId) {
throw new InternalFlowiseError(
StatusCodes.PRECONDITION_FAILED,
`Error: documentStoreController.createDocumentStore - workspaceId not provided!`
)
}
const subscriptionId = req.user?.activeOrganizationSubscriptionId || ''
const body = req.body
const apiResponse = await documentStoreService.refreshDocStoreMiddleware(req.params.id, body)
const apiResponse = await documentStoreService.refreshDocStoreMiddleware(
req.params.id,
body,
orgId,
workspaceId,
subscriptionId,
getRunningExpressApp().usageCacheManager
)
getRunningExpressApp().metricsProvider?.incrementCounter(FLOWISE_METRIC_COUNTERS.VECTORSTORE_UPSERT, {
status: FLOWISE_COUNTER_STATUS.SUCCESS
})
@@ -0,0 +1,135 @@
import { Request, Response, NextFunction } from 'express'
import { InternalFlowiseError } from '../../errors/internalFlowiseError'
import { StatusCodes } from 'http-status-codes'
import evaluationsService from '../../services/evaluations'
const createEvaluation = async (req: Request, res: Response, next: NextFunction) => {
try {
if (!req.body) {
throw new InternalFlowiseError(
StatusCodes.PRECONDITION_FAILED,
`Error: evaluationsService.createEvaluation - body not provided!`
)
}
const orgId = req.user?.activeOrganizationId
if (!orgId) {
throw new InternalFlowiseError(
StatusCodes.NOT_FOUND,
`Error: evaluationsService.createEvaluation - organization ${orgId} not found!`
)
}
const workspaceId = req.user?.activeWorkspaceId
if (!workspaceId) {
throw new InternalFlowiseError(
StatusCodes.NOT_FOUND,
`Error: evaluationsService.createEvaluation - workspace ${workspaceId} not found!`
)
}
const body = req.body
body.workspaceId = workspaceId
const httpProtocol = req.get('x-forwarded-proto') || req.get('X-Forwarded-Proto') || req.protocol
const baseURL = `${httpProtocol}://${req.get('host')}`
const apiResponse = await evaluationsService.createEvaluation(body, baseURL, orgId)
return res.json(apiResponse)
} catch (error) {
next(error)
}
}
const runAgain = async (req: Request, res: Response, next: NextFunction) => {
try {
if (typeof req.params === 'undefined' || !req.params.id) {
throw new InternalFlowiseError(StatusCodes.PRECONDITION_FAILED, `Error: evaluationsService.runAgain - id not provided!`)
}
const orgId = req.user?.activeOrganizationId
if (!orgId) {
throw new InternalFlowiseError(StatusCodes.NOT_FOUND, `Error: evaluationsService.runAgain - organization ${orgId} not found!`)
}
const httpProtocol = req.get('x-forwarded-proto') || req.get('X-Forwarded-Proto') || req.protocol
const baseURL = `${httpProtocol}://${req.get('host')}`
const apiResponse = await evaluationsService.runAgain(req.params.id, baseURL, orgId)
return res.json(apiResponse)
} catch (error) {
next(error)
}
}
const getEvaluation = async (req: Request, res: Response, next: NextFunction) => {
try {
if (typeof req.params === 'undefined' || !req.params.id) {
throw new InternalFlowiseError(StatusCodes.PRECONDITION_FAILED, `Error: evaluationsService.getEvaluation - id not provided!`)
}
const apiResponse = await evaluationsService.getEvaluation(req.params.id)
return res.json(apiResponse)
} catch (error) {
next(error)
}
}
const deleteEvaluation = async (req: Request, res: Response, next: NextFunction) => {
try {
if (typeof req.params === 'undefined' || !req.params.id) {
throw new InternalFlowiseError(StatusCodes.PRECONDITION_FAILED, `Error: evaluationsService.deleteEvaluation - id not provided!`)
}
const apiResponse = await evaluationsService.deleteEvaluation(req.params.id, req.user?.activeWorkspaceId)
return res.json(apiResponse)
} catch (error) {
next(error)
}
}
const getAllEvaluations = async (req: Request, res: Response, next: NextFunction) => {
try {
const apiResponse = await evaluationsService.getAllEvaluations(req.user?.activeWorkspaceId)
return res.json(apiResponse)
} catch (error) {
next(error)
}
}
const isOutdated = async (req: Request, res: Response, next: NextFunction) => {
try {
if (typeof req.params === 'undefined' || !req.params.id) {
throw new InternalFlowiseError(StatusCodes.PRECONDITION_FAILED, `Error: evaluationsService.isOutdated - id not provided!`)
}
const apiResponse = await evaluationsService.isOutdated(req.params.id)
return res.json(apiResponse)
} catch (error) {
next(error)
}
}
const getVersions = async (req: Request, res: Response, next: NextFunction) => {
try {
if (typeof req.params === 'undefined' || !req.params.id) {
throw new InternalFlowiseError(StatusCodes.PRECONDITION_FAILED, `Error: evaluationsService.getVersions - id not provided!`)
}
const apiResponse = await evaluationsService.getVersions(req.params.id)
return res.json(apiResponse)
} catch (error) {
next(error)
}
}
const patchDeleteEvaluations = async (req: Request, res: Response, next: NextFunction) => {
try {
const ids = req.body.ids ?? []
const isDeleteAllVersion = req.body.isDeleteAllVersion ?? false
const apiResponse = await evaluationsService.patchDeleteEvaluations(ids, isDeleteAllVersion, req.user?.activeWorkspaceId)
return res.json(apiResponse)
} catch (error) {
next(error)
}
}
export default {
createEvaluation,
getEvaluation,
deleteEvaluation,
getAllEvaluations,
isOutdated,
runAgain,
getVersions,
patchDeleteEvaluations
}
@@ -0,0 +1,74 @@
import { Request, Response, NextFunction } from 'express'
import { InternalFlowiseError } from '../../errors/internalFlowiseError'
import { StatusCodes } from 'http-status-codes'
import evaluatorService from '../../services/evaluator'
const getAllEvaluators = async (req: Request, res: Response, next: NextFunction) => {
try {
const apiResponse = await evaluatorService.getAllEvaluators(req.user?.activeWorkspaceId)
return res.json(apiResponse)
} catch (error) {
next(error)
}
}
const getEvaluator = async (req: Request, res: Response, next: NextFunction) => {
try {
if (typeof req.params === 'undefined' || !req.params.id) {
throw new InternalFlowiseError(StatusCodes.PRECONDITION_FAILED, `Error: evaluatorService.getEvaluator - id not provided!`)
}
const apiResponse = await evaluatorService.getEvaluator(req.params.id)
return res.json(apiResponse)
} catch (error) {
next(error)
}
}
const createEvaluator = async (req: Request, res: Response, next: NextFunction) => {
try {
if (!req.body) {
throw new InternalFlowiseError(StatusCodes.PRECONDITION_FAILED, `Error: evaluatorService.createEvaluator - body not provided!`)
}
const body = req.body
body.workspaceId = req.user?.activeWorkspaceId
const apiResponse = await evaluatorService.createEvaluator(body)
return res.json(apiResponse)
} catch (error) {
next(error)
}
}
const updateEvaluator = async (req: Request, res: Response, next: NextFunction) => {
try {
if (!req.body) {
throw new InternalFlowiseError(StatusCodes.PRECONDITION_FAILED, `Error: evaluatorService.updateEvaluator - body not provided!`)
}
if (typeof req.params === 'undefined' || !req.params.id) {
throw new InternalFlowiseError(StatusCodes.PRECONDITION_FAILED, `Error: evaluatorService.updateEvaluator - id not provided!`)
}
const apiResponse = await evaluatorService.updateEvaluator(req.params.id, req.body)
return res.json(apiResponse)
} catch (error) {
next(error)
}
}
const deleteEvaluator = async (req: Request, res: Response, next: NextFunction) => {
try {
if (typeof req.params === 'undefined' || !req.params.id) {
throw new InternalFlowiseError(StatusCodes.PRECONDITION_FAILED, `Error: evaluatorService.deleteEvaluator - id not provided!`)
}
const apiResponse = await evaluatorService.deleteEvaluator(req.params.id)
return res.json(apiResponse)
} catch (error) {
next(error)
}
}
export default {
getAllEvaluators,
getEvaluator,
createEvaluator,
updateEvaluator,
deleteEvaluator
}
@@ -5,7 +5,8 @@ import { ExecutionState } from '../../Interface'
const getExecutionById = async (req: Request, res: Response, next: NextFunction) => {
try {
const executionId = req.params.id
const execution = await executionsService.getExecutionById(executionId)
const workspaceId = req.user?.activeWorkspaceId
const execution = await executionsService.getExecutionById(executionId, workspaceId)
return res.json(execution)
} catch (error) {
next(error)
@@ -25,7 +26,8 @@ const getPublicExecutionById = async (req: Request, res: Response, next: NextFun
const updateExecution = async (req: Request, res: Response, next: NextFunction) => {
try {
const executionId = req.params.id
const execution = await executionsService.updateExecution(executionId, req.body)
const workspaceId = req.user?.activeWorkspaceId
const execution = await executionsService.updateExecution(executionId, req.body, workspaceId)
return res.json(execution)
} catch (error) {
next(error)
@@ -37,6 +39,9 @@ const getAllExecutions = async (req: Request, res: Response, next: NextFunction)
// Extract all possible filters from query params
const filters: any = {}
// Add workspace ID filter
filters.workspaceId = req.user?.activeWorkspaceId
// ID filter
if (req.query.id) filters.id = req.query.id as string
@@ -86,6 +91,7 @@ const getAllExecutions = async (req: Request, res: Response, next: NextFunction)
const deleteExecutions = async (req: Request, res: Response, next: NextFunction) => {
try {
let executionIds: string[] = []
const workspaceId = req.user?.activeWorkspaceId
// Check if we're deleting a single execution from URL param
if (req.params.id) {
@@ -98,7 +104,7 @@ const deleteExecutions = async (req: Request, res: Response, next: NextFunction)
return res.status(400).json({ success: false, message: 'No execution IDs provided' })
}
const result = await executionsService.deleteExecutions(executionIds)
const result = await executionsService.deleteExecutions(executionIds, workspaceId)
return res.json(result)
} catch (error) {
next(error)
@@ -1,9 +1,14 @@
import { NextFunction, Request, Response } from 'express'
import { StatusCodes } from 'http-status-codes'
import { InternalFlowiseError } from '../../errors/internalFlowiseError'
import exportImportService from '../../services/export-import'
const exportData = async (req: Request, res: Response, next: NextFunction) => {
try {
const apiResponse = await exportImportService.exportData(exportImportService.convertExportInput(req.body))
const apiResponse = await exportImportService.exportData(
exportImportService.convertExportInput(req.body),
req.user?.activeWorkspaceId
)
return res.json(apiResponse)
} catch (error) {
next(error)
@@ -12,8 +17,28 @@ const exportData = async (req: Request, res: Response, next: NextFunction) => {
const importData = async (req: Request, res: Response, next: NextFunction) => {
try {
const orgId = req.user?.activeOrganizationId
if (!orgId) {
throw new InternalFlowiseError(
StatusCodes.NOT_FOUND,
`Error: exportImportController.importData - organization ${orgId} not found!`
)
}
const workspaceId = req.user?.activeWorkspaceId
if (!workspaceId) {
throw new InternalFlowiseError(
StatusCodes.NOT_FOUND,
`Error: exportImportController.importData - workspace ${workspaceId} not found!`
)
}
const subscriptionId = req.user?.activeOrganizationSubscriptionId || ''
const importData = req.body
await exportImportService.importData(importData)
if (!importData) {
throw new InternalFlowiseError(StatusCodes.BAD_REQUEST, 'Error: exportImportController.importData - importData is required!')
}
await exportImportService.importData(importData, orgId, workspaceId, subscriptionId)
return res.json({ message: 'success' })
} catch (error) {
next(error)
@@ -0,0 +1,59 @@
import path from 'path'
import { NextFunction, Request, Response } from 'express'
import { getFilesListFromStorage, getStoragePath, removeSpecificFileFromStorage } from 'flowise-components'
import { updateStorageUsage } from '../../utils/quotaUsage'
import { InternalFlowiseError } from '../../errors/internalFlowiseError'
import { StatusCodes } from 'http-status-codes'
import { getRunningExpressApp } from '../../utils/getRunningExpressApp'
const getAllFiles = async (req: Request, res: Response, next: NextFunction) => {
try {
const activeOrganizationId = req.user?.activeOrganizationId
if (!activeOrganizationId) {
throw new InternalFlowiseError(
StatusCodes.NOT_FOUND,
`Error: filesController.getAllFiles - organization ${activeOrganizationId} not found!`
)
}
const apiResponse = await getFilesListFromStorage(activeOrganizationId)
const filesList = apiResponse.map((file: any) => ({
...file,
// replace org id because we don't want to expose it
path: file.path.replace(getStoragePath(), '').replace(`${path.sep}${activeOrganizationId}${path.sep}`, '')
}))
return res.json(filesList)
} catch (error) {
next(error)
}
}
const deleteFile = async (req: Request, res: Response, next: NextFunction) => {
try {
const activeOrganizationId = req.user?.activeOrganizationId
if (!activeOrganizationId) {
throw new InternalFlowiseError(
StatusCodes.NOT_FOUND,
`Error: filesController.deleteFile - organization ${activeOrganizationId} not found!`
)
}
const activeWorkspaceId = req.user?.activeWorkspaceId
if (!activeWorkspaceId) {
throw new InternalFlowiseError(
StatusCodes.NOT_FOUND,
`Error: filesController.deleteFile - workspace ${activeWorkspaceId} not found!`
)
}
const filePath = req.query.path as string
const paths = filePath.split(path.sep).filter((path) => path !== '')
const { totalSize } = await removeSpecificFileFromStorage(activeOrganizationId, ...paths)
await updateStorageUsage(activeOrganizationId, activeWorkspaceId, totalSize, getRunningExpressApp().usageCacheManager)
return res.json({ message: 'file_deleted' })
} catch (error) {
next(error)
}
}
export default {
getAllFiles,
deleteFile
}
@@ -4,6 +4,9 @@ import contentDisposition from 'content-disposition'
import { streamStorageFile } from 'flowise-components'
import { StatusCodes } from 'http-status-codes'
import { InternalFlowiseError } from '../../errors/internalFlowiseError'
import { getRunningExpressApp } from '../../utils/getRunningExpressApp'
import { ChatFlow } from '../../database/entities/ChatFlow'
import { Workspace } from '../../enterprise/database/entities/workspace.entity'
const streamUploadedFile = async (req: Request, res: Response, next: NextFunction) => {
try {
@@ -13,8 +16,27 @@ const streamUploadedFile = async (req: Request, res: Response, next: NextFunctio
const chatflowId = req.query.chatflowId as string
const chatId = req.query.chatId as string
const fileName = req.query.fileName as string
const appServer = getRunningExpressApp()
// This can be public API, so we can only get orgId from the chatflow
const chatflow = await appServer.AppDataSource.getRepository(ChatFlow).findOneBy({
id: chatflowId
})
if (!chatflow) {
throw new InternalFlowiseError(StatusCodes.NOT_FOUND, `Chatflow ${chatflowId} not found`)
}
const chatflowWorkspaceId = chatflow.workspaceId
const workspace = await appServer.AppDataSource.getRepository(Workspace).findOneBy({
id: chatflowWorkspaceId
})
if (!workspace) {
throw new InternalFlowiseError(StatusCodes.NOT_FOUND, `Workspace ${chatflowWorkspaceId} not found`)
}
const orgId = workspace.organizationId as string
res.setHeader('Content-Disposition', contentDisposition(fileName))
const fileStream = await streamStorageFile(chatflowId, chatId, fileName)
const fileStream = await streamStorageFile(chatflowId, chatId, fileName, orgId)
if (!fileStream) throw new InternalFlowiseError(StatusCodes.INTERNAL_SERVER_ERROR, `Error: streamStorageFile`)
@@ -0,0 +1,16 @@
import { Request, Response, NextFunction } from 'express'
import logService from '../../services/log'
// Get logs
const getLogs = async (req: Request, res: Response, next: NextFunction) => {
try {
const apiResponse = await logService.getLogs(req.query?.startDate as string, req.query?.endDate as string)
res.send(apiResponse)
} catch (error) {
next(error)
}
}
export default {
getLogs
}
@@ -30,7 +30,7 @@ const deleteCustomTemplate = async (req: Request, res: Response, next: NextFunct
const getAllCustomTemplates = async (req: Request, res: Response, next: NextFunction) => {
try {
const apiResponse = await marketplacesService.getAllCustomTemplates()
const apiResponse = await marketplacesService.getAllCustomTemplates(req.user?.activeWorkspaceId)
return res.json(apiResponse)
} catch (error) {
next(error)
@@ -45,7 +45,9 @@ const saveCustomTemplate = async (req: Request, res: Response, next: NextFunctio
`Error: marketplacesService.saveCustomTemplate - body not provided!`
)
}
const apiResponse = await marketplacesService.saveCustomTemplate(req.body)
const body = req.body
body.workspaceId = req.user?.activeWorkspaceId
const apiResponse = await marketplacesService.saveCustomTemplate(body)
return res.json(apiResponse)
} catch (error) {
next(error)
@@ -3,6 +3,7 @@ import _ from 'lodash'
import nodesService from '../../services/nodes'
import { InternalFlowiseError } from '../../errors/internalFlowiseError'
import { StatusCodes } from 'http-status-codes'
import { getWorkspaceSearchOptionsFromReq } from '../../enterprise/utils/ControllerServiceUtils'
const getAllNodes = async (req: Request, res: Response, next: NextFunction) => {
try {
@@ -67,7 +68,9 @@ const getSingleNodeAsyncOptions = async (req: Request, res: Response, next: Next
`Error: nodesController.getSingleNodeAsyncOptions - name not provided!`
)
}
const apiResponse = await nodesService.getSingleNodeAsyncOptions(req.params.name, req.body)
const body = req.body
body.searchOptions = getWorkspaceSearchOptionsFromReq(req)
const apiResponse = await nodesService.getSingleNodeAsyncOptions(req.params.name, body)
return res.json(apiResponse)
} catch (error) {
next(error)
@@ -82,7 +85,8 @@ const executeCustomFunction = async (req: Request, res: Response, next: NextFunc
`Error: nodesController.executeCustomFunction - body not provided!`
)
}
const apiResponse = await nodesService.executeCustomFunction(req.body)
const orgId = req.user?.activeOrganizationId
const apiResponse = await nodesService.executeCustomFunction(req.body, orgId)
return res.json(apiResponse)
} catch (error) {
next(error)
@@ -5,6 +5,9 @@ import contentDisposition from 'content-disposition'
import { InternalFlowiseError } from '../../errors/internalFlowiseError'
import { StatusCodes } from 'http-status-codes'
import { streamStorageFile } from 'flowise-components'
import { getRunningExpressApp } from '../../utils/getRunningExpressApp'
import { ChatFlow } from '../../database/entities/ChatFlow'
import { Workspace } from '../../enterprise/database/entities/workspace.entity'
// List available assistants
const getAllOpenaiAssistants = async (req: Request, res: Response, next: NextFunction) => {
@@ -50,11 +53,29 @@ const getFileFromAssistant = async (req: Request, res: Response, next: NextFunct
if (!req.body.chatflowId || !req.body.chatId || !req.body.fileName) {
return res.status(500).send(`Invalid file path`)
}
const appServer = getRunningExpressApp()
const chatflowId = req.body.chatflowId as string
const chatId = req.body.chatId as string
const fileName = req.body.fileName as string
// This can be public API, so we can only get orgId from the chatflow
const chatflow = await appServer.AppDataSource.getRepository(ChatFlow).findOneBy({
id: chatflowId
})
if (!chatflow) {
throw new InternalFlowiseError(StatusCodes.NOT_FOUND, `Chatflow ${chatflowId} not found`)
}
const chatflowWorkspaceId = chatflow.workspaceId
const workspace = await appServer.AppDataSource.getRepository(Workspace).findOneBy({
id: chatflowWorkspaceId
})
if (!workspace) {
throw new InternalFlowiseError(StatusCodes.NOT_FOUND, `Workspace ${chatflowWorkspaceId} not found`)
}
const orgId = workspace.organizationId as string
res.setHeader('Content-Disposition', contentDisposition(fileName))
const fileStream = await streamStorageFile(chatflowId, chatId, fileName)
const fileStream = await streamStorageFile(chatflowId, chatId, fileName, orgId)
if (!fileStream) throw new InternalFlowiseError(StatusCodes.INTERNAL_SERVER_ERROR, `Error: getFileFromAssistant`)
@@ -0,0 +1,81 @@
import { Request, Response, NextFunction } from 'express'
const getPricing = async (req: Request, res: Response, next: NextFunction) => {
try {
const PRODUCT_IDS = {
FREE: process.env.CLOUD_FREE_ID,
STARTER: process.env.CLOUD_STARTER_ID,
PRO: process.env.CLOUD_PRO_ID
}
const pricingPlans = [
{
prodId: PRODUCT_IDS.FREE,
title: 'Free',
subtitle: 'For trying out the platform',
price: '$0',
period: '/month',
features: [
{ text: '2 Flows & Assistants' },
{ text: '100 Predictions / month' },
{ text: '5MB Storage' },
{ text: 'Evaluations & Metrics' },
{ text: 'Custom Embedded Chatbot Branding' },
{ text: 'Community Support' }
]
},
{
prodId: PRODUCT_IDS.STARTER,
title: 'Starter',
subtitle: 'For individuals & small teams',
mostPopular: true,
price: '$35',
period: '/month',
features: [
{ text: 'Everything in Free plan, plus' },
{ text: 'Unlimited Flows & Assistants' },
{ text: '10,000 Predictions / month' },
{ text: '1GB Storage' },
{ text: 'Email Support' }
]
},
{
prodId: PRODUCT_IDS.PRO,
title: 'Pro',
subtitle: 'For medium-sized businesses',
price: '$65',
period: '/month',
features: [
{ text: 'Everything in Starter plan, plus' },
{ text: '50,000 Predictions / month' },
{ text: '10GB Storage' },
{ text: 'Unlimited Workspaces' },
{ text: '5 users', subtext: '+ $15/user/month' },
{ text: 'Admin Roles & Permissions' },
{ text: 'Priority Support' }
]
},
{
title: 'Enterprise',
subtitle: 'For large organizations',
price: 'Contact Us',
features: [
{ text: 'On-Premise Deployment' },
{ text: 'Air-gapped Environments' },
{ text: 'SSO & SAML' },
{ text: 'LDAP & RBAC' },
{ text: 'Versioning' },
{ text: 'Audit Logs' },
{ text: '99.99% Uptime SLA' },
{ text: 'Personalized Support' }
]
}
]
return res.status(200).json(pricingPlans)
} catch (error) {
next(error)
}
}
export default {
getPricing
}
@@ -0,0 +1,15 @@
import { Request, Response, NextFunction } from 'express'
import settingsService from '../../services/settings'
const getSettingsList = async (req: Request, res: Response, next: NextFunction) => {
try {
const apiResponse = await settingsService.getSettings()
return res.json(apiResponse)
} catch (error) {
next(error)
}
}
export default {
getSettingsList
}
+14 -3
View File
@@ -1,4 +1,4 @@
import { Request, Response, NextFunction } from 'express'
import { NextFunction, Request, Response } from 'express'
import toolsService from '../../services/tools'
import { InternalFlowiseError } from '../../errors/internalFlowiseError'
import { StatusCodes } from 'http-status-codes'
@@ -8,7 +8,18 @@ const createTool = async (req: Request, res: Response, next: NextFunction) => {
if (!req.body) {
throw new InternalFlowiseError(StatusCodes.PRECONDITION_FAILED, `Error: toolsController.createTool - body not provided!`)
}
const apiResponse = await toolsService.createTool(req.body)
const orgId = req.user?.activeOrganizationId
if (!orgId) {
throw new InternalFlowiseError(StatusCodes.NOT_FOUND, `Error: toolsController.createTool - organization ${orgId} not found!`)
}
const workspaceId = req.user?.activeWorkspaceId
if (!workspaceId) {
throw new InternalFlowiseError(StatusCodes.NOT_FOUND, `Error: toolsController.createTool - workspace ${workspaceId} not found!`)
}
const body = req.body
body.workspaceId = workspaceId
const apiResponse = await toolsService.createTool(body, orgId)
return res.json(apiResponse)
} catch (error) {
next(error)
@@ -29,7 +40,7 @@ const deleteTool = async (req: Request, res: Response, next: NextFunction) => {
const getAllTools = async (req: Request, res: Response, next: NextFunction) => {
try {
const apiResponse = await toolsService.getAllTools()
const apiResponse = await toolsService.getAllTools(req.user?.activeWorkspaceId)
return res.json(apiResponse)
} catch (error) {
next(error)
@@ -12,7 +12,8 @@ const checkFlowValidation = async (req: Request, res: Response, next: NextFuncti
`Error: validationController.checkFlowValidation - id not provided!`
)
}
const apiResponse = await validationService.checkFlowValidation(flowId)
const workspaceId = req.user?.activeWorkspaceId
const apiResponse = await validationService.checkFlowValidation(flowId, workspaceId)
return res.json(apiResponse)
} catch (error) {
next(error)
@@ -12,10 +12,19 @@ const createVariable = async (req: Request, res: Response, next: NextFunction) =
`Error: variablesController.createVariable - body not provided!`
)
}
const orgId = req.user?.activeOrganizationId
if (!orgId) {
throw new InternalFlowiseError(StatusCodes.NOT_FOUND, `Error: toolsController.createTool - organization ${orgId} not found!`)
}
const workspaceId = req.user?.activeWorkspaceId
if (!workspaceId) {
throw new InternalFlowiseError(StatusCodes.NOT_FOUND, `Error: toolsController.createTool - workspace ${workspaceId} not found!`)
}
const body = req.body
body.workspaceId = workspaceId
const newVariable = new Variable()
Object.assign(newVariable, body)
const apiResponse = await variablesService.createVariable(newVariable)
const apiResponse = await variablesService.createVariable(newVariable, orgId)
return res.json(apiResponse)
} catch (error) {
next(error)
@@ -36,7 +45,7 @@ const deleteVariable = async (req: Request, res: Response, next: NextFunction) =
const getAllVariables = async (req: Request, res: Response, next: NextFunction) => {
try {
const apiResponse = await variablesService.getAllVariables()
const apiResponse = await variablesService.getAllVariables(req.user?.activeWorkspaceId)
return res.json(apiResponse)
} catch (error) {
next(error)