{"record":{"id":"144516f659bf61e0","repo":"RocketChat/Rocket.Chat","slug":"not-authorized-144516","errorCode":"not_authorized","errorMessage":"Unauthorized","messagePattern":"Unauthorized","errorType":"exception","errorClass":"Meteor.Error","httpStatus":null,"severity":"error","filePath":"apps/meteor/server/meteor-methods/integrations/outgoing/deleteOutgoingIntegration.ts","lineNumber":18,"sourceCode":"import type { ServerMethods } from '@rocket.chat/ddp-client';\nimport { Integrations, IntegrationHistory } from '@rocket.chat/models';\nimport { Meteor } from 'meteor/meteor';\n\nimport { hasPermissionAsync } from '../../../lib/authorization/hasPermission';\nimport { methodDeprecationLogger } from '../../../lib/deprecationWarningLogger';\nimport { notifyOnIntegrationChanged } from '../../../lib/notifyListener';\n\ndeclare module '@rocket.chat/ddp-client' {\n\t// eslint-disable-next-line @typescript-eslint/naming-convention\n\tinterface ServerMethods {\n\t\tdeleteOutgoingIntegration(integrationId: string): Promise<boolean>;\n\t}\n}\n\nexport const deleteOutgoingIntegration = async (integrationId: string, userId: string): Promise<void> => {\n\tif (!userId) {\n\t\tthrow new Meteor.Error('not_authorized', 'Unauthorized', {\n\t\t\tmethod: 'deleteOutgoingIntegration',\n\t\t});\n\t}\n\n\tconst canManageAllIntegrations = await hasPermissionAsync(userId, 'manage-outgoing-integrations');\n\tconst canManageOwnIntegrations = !canManageAllIntegrations && (await hasPermissionAsync(userId, 'manage-own-outgoing-integrations'));\n\n\tif (!canManageAllIntegrations && !canManageOwnIntegrations) {\n\t\tthrow new Meteor.Error('not_authorized', 'Unauthorized', {\n\t\t\tmethod: 'deleteOutgoingIntegration',\n\t\t});\n\t}\n\n\tconst integration = await Integrations.removeByIdAndCreatedByIfExists({\n\t\t_id: integrationId,\n\t\t...(canManageOwnIntegrations && { createdBy: userId }),\n\t});\n","sourceCodeStart":1,"sourceCodeEnd":36,"githubUrl":"https://github.com/RocketChat/Rocket.Chat/blob/b2c16d5842cbe6b69b59bdf6fc5e5f1afcd1f0b0/apps/meteor/server/meteor-methods/integrations/outgoing/deleteOutgoingIntegration.ts#L1-L36","documentation":"The exported helper deleteOutgoingIntegration(integrationId, userId) throws not_authorized 'Unauthorized' as its first guard when the passed userId is falsy. Server-side callers (REST endpoints, other methods) supply userId explicitly, so a falsy value means the calling layer never resolved an authenticated user.","triggerScenarios":"Calling the exported helper with undefined/empty userId — e.g. a custom wrapper forwarding Meteor.userId() while logged out, or a REST-style handler reading a missing X-User-Id.","commonSituations":"Custom server code reusing the helper without an auth check; method wrappers that forward this.userId unconditionally.","solutions":["Resolve and assert an authenticated userId before invoking the helper","Prefer the shipped method wrapper or POST /v1/integrations.remove, which perform auth themselves","Throw early with a clear error when Meteor.userId() returns null instead of forwarding it"],"exampleFix":"// before\nawait deleteOutgoingIntegration(integrationId, Meteor.userId() ?? '');\n\n// after\nconst uid = Meteor.userId();\nif (!uid) {\n  throw new Meteor.Error('not_authorized', 'Unauthorized');\n}\nawait deleteOutgoingIntegration(integrationId, uid);","handlingStrategy":"validation","validationCode":"const uid = Meteor.userId();\nif (!uid) {\n  throw new Meteor.Error('not_authorized', 'Unauthorized');\n}\nawait deleteOutgoingIntegration(integrationId, uid);","typeGuard":null,"tryCatchPattern":"try {\n  await deleteOutgoingIntegration(integrationId, uid);\n} catch (err) {\n  if (err instanceof Meteor.Error && err.error === 'not_authorized') {\n    // resolve a valid authenticated userId before retrying\n    return;\n  }\n  throw err;\n}","preventionTips":["Never forward Meteor.userId() unconditionally — assert it first","Prefer the shipped wrappers and REST endpoints that handle auth","Type the helper parameter as string (not string | null) so falsy ids fail at compile time"],"tags":["authentication","integrations","meteor-methods"],"backgroundTag":"authentication-required","analyzedSha":"b2c16d5842cbe6b69b59bdf6fc5e5f1afcd1f0b0","analyzedAt":"2026-08-18T15:26:39.429Z","contentChangedAt":"2026-08-18T15:26:39.429Z","schemaVersion":2},"datasetVersion":"2026-09-14T05:17:10.506Z"}