import type { INewOutgoingIntegration, IOutgoingIntegration } from '@rocket.chat/core-typings'; import type { ServerMethods } from '@rocket.chat/ddp-client'; import { Integrations } from '@rocket.chat/models'; import { removeEmpty } from '@rocket.chat/tools'; import { Match, check } from 'meteor/check'; import { Meteor } from 'meteor/meteor'; import { hasPermissionAsync } from '../../../lib/authorization/hasPermission'; import { methodDeprecationLogger } from '../../../lib/deprecationWarningLogger'; import { validateOutgoingIntegration } from '../../../lib/integrations/lib/validateOutgoingIntegration'; import { validateScriptEngine } from '../../../lib/integrations/lib/validateScriptEngine'; import { notifyOnIntegrationChanged } from '../../../lib/notifyListener'; declare module '@rocket.chat/ddp-client' { // eslint-disable-next-line @typescript-eslint/naming-convention interface ServerMethods { addOutgoingIntegration(integration: INewOutgoingIntegration): Promise; } } export const addOutgoingIntegration = async (userId: string, integration: INewOutgoingIntegration): Promise => { check( integration, Match.ObjectIncluding({ type: String, name: String, enabled: Boolean, username: String, channel: String, alias: Match.Maybe(String), emoji: Match.Maybe(String), scriptEnabled: Boolean, script: Match.Maybe(String), scriptEngine: Match.Maybe(String), urls: Match.Maybe([String]), event: Match.Maybe(String), triggerWords: Match.Maybe([String]), avatar: Match.Maybe(String), token: Match.Maybe(String), impersonateUser: Match.Maybe(Boolean), retryCount: Match.Maybe(Number), retryDelay: Match.Maybe(String), retryFailedCalls: Match.Maybe(Boolean), runOnEdits: Match.Maybe(Boolean), targetRoom: Match.Maybe(String), triggerWordAnywhere: Match.Maybe(Boolean), }), ); if ( !userId || (!(await hasPermissionAsync(userId, 'manage-outgoing-integrations')) && !(await hasPermissionAsync(userId, 'manage-own-outgoing-integrations'))) ) { throw new Meteor.Error('not_authorized'); } if (integration.script?.trim()) { validateScriptEngine(integration.scriptEngine ?? 'isolated-vm'); } const integrationData = await validateOutgoingIntegration(integration, userId); const { insertedId } = await Integrations.insertOne(removeEmpty(integrationData)); const integrationStored = await Integrations.findOne({ _id: insertedId }); if (!integrationStored) { throw new Error('Error inserting integration'); } void notifyOnIntegrationChanged({ ...integrationStored, _id: insertedId }, 'inserted'); return integrationStored as IOutgoingIntegration; }; Meteor.methods({ async addOutgoingIntegration(integration: INewOutgoingIntegration): Promise { methodDeprecationLogger.method('addOutgoingIntegration', '9.0.0', '/v1/integrations.create'); const { userId } = this; if (!userId) { throw new Meteor.Error('Invalid User'); } return addOutgoingIntegration(userId, integration); }, });