{"record":{"id":"259c7bef31f4cd06","repo":"RocketChat/Rocket.Chat","slug":"not-allowed","errorCode":"Not allowed","errorMessage":"Not allowed","messagePattern":"Not allowed","errorType":"error_code","errorClass":"Meteor.Error","httpStatus":null,"severity":"error","filePath":"apps/meteor/ee/server/lib/audit/functions.ts","lineNumber":59,"sourceCode":"\t}\n\n\tif (type === 'l') {\n\t\tconst extraQuery = await callbacks.run('livechat.applyRoomRestrictions', {}, { userId });\n\t\tconst rooms = await LivechatRooms.findByVisitorIdAndAgentId(\n\t\t\tvisitor,\n\t\t\tagent,\n\t\t\t{\n\t\t\t\tprojection: { _id: 1 },\n\t\t\t},\n\t\t\textraQuery,\n\t\t).toArray();\n\t\treturn rooms?.length ? { rids: rooms.map(({ _id }) => _id), name: i18n.t('Omnichannel') } : undefined;\n\t}\n};\n\nconst requireAuditor = async (userId: string | null): Promise<IUser> => {\n\tif (!userId) {\n\t\tthrow new Meteor.Error('Not allowed');\n\t}\n\n\tconst user = await Users.findOneById(userId);\n\tif (!user || !(await hasPermissionAsync(user._id, 'can-audit'))) {\n\t\tthrow new Meteor.Error('Not allowed');\n\t}\n\treturn user;\n};\n\ntype AuditMessagesParams = {\n\trid?: IRoom['_id'];\n\tstartDate: Date;\n\tendDate: Date;\n\tusers: NonNullable<IUser['username']>[];\n\tmsg: IMessage['msg'];\n\ttype: string;\n\tvisitor?: ILivechatVisitor['_id'];\n\tagent?: ILivechatAgent['_id'];","sourceCodeStart":41,"sourceCodeEnd":77,"githubUrl":"https://github.com/RocketChat/Rocket.Chat/blob/2a7de457074cbb4d4373fbd9a4e5bea292c9c764/apps/meteor/ee/server/lib/audit/functions.ts#L41-L77","documentation":"Meteor.Error 'Not allowed' thrown by requireAuditor when the audit-message method is invoked with a null/absent userId — i.e. there is no authenticated user on the DDP method context at all. The audit API (auditGetMessagesMethod) refuses to run anonymously before any permission lookup happens.","triggerScenarios":"Calling the auditMessages meteor method from an unauthenticated connection; a method binding losing the user context (e.g. server-side invocation without this.userId); token expiry dropping the user between connect and method call.","commonSituations":"Scripts calling internal methods without login tokens; custom integrations using DDP without auth; session invalidated server-side mid-flight.","solutions":["Ensure the method call runs on an authenticated connection (valid login token / this.userId set)","For server-side code, pass an explicit userId or use an authenticated REST endpoint instead of a raw method call","Handle 401-style 'Not allowed' by re-authenticating rather than retrying blindly"],"exampleFix":"// before: invoking the audit method without a user context\nMeteor.call('auditMessages', params);\n\n// after: run it as an authenticated user (client) or bound server-side\n// client: ensure Meteor.userId() is set before calling\nif (!Meteor.userId()) {\n  throw new Error('Login required for auditing');\n}\nMeteor.call('auditMessages', params);\n// server: Meteor.call with a bound user or use promise with authenticated userId","handlingStrategy":"try-catch","validationCode":"// On the client, ensure an authenticated session before invoking audit methods\nif (!Meteor.userId()) {\n  throw new Error('Authentication required');\n}","typeGuard":null,"tryCatchPattern":"try {\n  const results = await auditGetMessagesMethod(this.userId, params);\n} catch (err: any) {\n  if (err?.error === 'Not allowed' && !userId) {\n    // re-authenticate; retrying with the same null userId will always fail\n  }\n  throw err;\n}","preventionTips":["Bind DDP method calls to authenticated connections with valid login tokens","Check Meteor.userId() before calling protected methods","Prefer authenticated REST endpoints for integration access to audit data"],"tags":["audit","authentication","enterprise","method-guard"],"backgroundTag":"authentication-required","analyzedSha":"2a7de457074cbb4d4373fbd9a4e5bea292c9c764","analyzedAt":"2026-08-18T15:26:39.429Z","contentChangedAt":"2026-08-18T15:26:39.429Z","schemaVersion":2},"datasetVersion":"2026-09-23T08:17:48.524Z"}