{"record":{"id":"888017246b2b88c3","repo":"wekan/wekan","slug":"not-authorized-888017","errorCode":"not-authorized","errorMessage":"You must be an admin.","messagePattern":"You must be an admin\\.","errorType":"error_code","errorClass":"Meteor.Error","httpStatus":null,"severity":"error","filePath":"server/methods/cleanupTemplateContainers.js","lineNumber":80,"sourceCode":"      board,\n      counts: { templateCount, listCount, swimlaneCount, cardCount },\n      options: { defaultTitles: DEFAULT_TITLES },\n    });\n  }\n  return entries;\n}\n\nMeteor.methods({\n  // options: { apply: false, limit: 0 }\n  async cleanupUnusedTemplateContainers(options = {}) {\n    check(options, Match.Optional(Object));\n    const apply = options.apply === true;\n    const limit = Number.isInteger(options.limit) && options.limit > 0\n      ? options.limit\n      : 0;\n\n    if (!this.userId || !(await ReactiveCache.getUser(this.userId))?.isAdmin) {\n      throw new Meteor.Error('not-authorized', 'You must be an admin.');\n    }\n\n    const entries = await collectContainers(limit);\n    const plan = planTemplateContainerCleanup(entries);\n\n    if (!apply) {\n      return {\n        applied: false,\n        scanned: entries.length,\n        wouldRemove: plan.remove.length,\n        kept: plan.keep.length,\n        // A sample rather than thirteen thousand rows, and the reasons the kept\n        // ones were kept - which is what tells an admin the rule is doing what\n        // they think it is.\n        removeSample: plan.remove.slice(0, 25),\n        keepSample: plan.keep.slice(0, 25),\n      };\n    }","sourceCodeStart":62,"sourceCodeEnd":98,"githubUrl":"https://github.com/wekan/wekan/blob/eb1433158b1804bcf3edaa5cb18f08ae2e04d6c2/server/methods/cleanupTemplateContainers.js#L62-L98","documentation":"The 'cleanupTemplateContainers' Meteor method (server/methods/cleanupTemplateContainers.js:80) throws Meteor.Error('not-authorized', 'You must be an admin.') when the caller either is not logged in (no this.userId) or is logged in but the user document lacks isAdmin. This method inspects/removes unused template container entries, an administrative maintenance operation, so it is deliberately restricted to admins. The error is the app's standard guard for admin-only server methods.","triggerScenarios":"Calling Meteor.call('cleanupUnusedTemplateContainers', options) from a client session with no authenticated user, or from a logged-in user whose Users document has isAdmin !== true. Also produced by REST/scripted calls that hit the public method with a non-admin account token.","commonSituations":"A developer tests the cleanup routine while logged in as a normal user; an ops script runs against the server without admin credentials; isAdmin was set via a direct DB edit that did not take effect (wrong field name or user cached), so the guard still fails.","solutions":["Log in as a user with isAdmin true in the users collection before invoking the method.","Promote the current user: in the mongo shell run db.users.updateOne({username:'<name>'},{$set:{isAdmin:true}}) (or use the WeKan Admin Panel) then re-login.","Ensure the client call is made over an authenticated DDP/REST session (this.userId present), not an anonymous connection.","If the intent is a dry run, note that even non-apply (dry-run) calls still require admin; wrap script calls in an admin login flow."],"exampleFix":"// before\ncall('cleanupUnusedTemplateContainers', { apply: true });\n// after\nconst me = await ReactiveCache.getUser(Meteor.userId());\nif (me?.isAdmin) {\n  await call('cleanupUnusedTemplateContainers', { apply: true });\n} else {\n  throw new Error('Admin account required for template container cleanup');\n}","handlingStrategy":"validation","validationCode":"const me = await ReactiveCache.getUser(Meteor.userId());\nif (!me?.isAdmin) {\n  throw new Error('Admin privileges required for template container cleanup');\n}\n// safe to call: Meteor.call('cleanupUnusedTemplateContainers', { apply: true })","typeGuard":"function isAdminUser(u) {\n  return !!u && typeof u === 'object' && u.isAdmin === true;\n}","tryCatchPattern":"try {\n  await call('cleanupUnusedTemplateContainers', options);\n} catch (e) {\n  if (e instanceof Meteor.Error && e.error === 'not-authorized') {\n    // route to admin login / show permission UI\n  } else throw e;\n}","preventionTips":["Check user.isAdmin before rendering any admin maintenance UI that calls this method","Use the Admin Panel to grant isAdmin instead of manual DB edits","Re-login after changing admin flags so the session picks up the new role","Document that even dry-run (apply:false) invocations require admin"],"tags":["meteor","authorization","admin-only","server-method"],"backgroundTag":"meteor-method-not-authorized","analyzedSha":"eb1433158b1804bcf3edaa5cb18f08ae2e04d6c2","analyzedAt":"2026-09-01T21:05:02.951Z","contentChangedAt":null,"schemaVersion":2},"datasetVersion":"2026-09-09T01:17:15.007Z"}