[{"data":1,"prerenderedAt":-1},["ShallowReactive",2],{"verticals":3,"search-suggestions":44,"article-nestjs-weekly-guards-canactivate-reflector":92,"related-nestjs-weekly-guards-canactivate-reflector":501,"code:ts:true:2zlzhx":576,"code:ts:true:1cl2fdl":577,"code:ts:true:15b5uda":578,"code:ts:true:1fgy1g6":579,"code:ts:true:10j4wrv":580,"code:ts:true:1gmdpgz":581,"code:ts:true:1cxidk1":582,"code:ts:true:1x4gqkd":583,"code:ts:true:1r61l34":584,"code:ts:true:car0hy":585,"code:ts:true:lz7n67":586,"comments-01a0ddae-48ac-73c6-bdee-1420cdfb17c2":587},[4,20,32],{"id":5,"slug":6,"name":7,"tagline":8,"description":9,"accentFrom":10,"accentTo":11,"icon":12,"defaultLocale":13,"locales":14,"features":16,"position":19},"019fe637-3d33-714b-b57f-23e163ffca0c","dev","Web Development","Read it. Run it. Prove it.","A post a day on modern web development — most with an editable playground and a quiz that explains every answer. Free, no account needed.","violet-500","cyan-400","◇","en",[13,15],"fa",{"courses":17,"paths":17,"articles":17,"exams":18,"flashcards":18,"packages":17,"community":17,"certificates":17,"teams":17,"commerce":17},true,false,0,{"id":21,"slug":22,"name":23,"tagline":24,"description":25,"accentFrom":26,"accentTo":10,"icon":27,"defaultLocale":13,"locales":28,"features":30,"position":31},"019fe637-3dc2-754c-8657-0f175bfee7c6","lang","Languages","Learn a language the way you learn a codebase.","Grammar explained the way good documentation explains an API — one idea at a time, each with a quiz.","amber-400","⌘",[13,15,29],"es",{"courses":18,"paths":18,"articles":17,"exams":18,"flashcards":17,"packages":18,"community":17,"certificates":17,"teams":18,"commerce":18},2,{"id":33,"slug":34,"name":35,"tagline":36,"description":37,"accentFrom":38,"accentTo":39,"icon":40,"defaultLocale":13,"locales":41,"features":42,"position":43},"7b3c16f2-931d-410e-802e-e1fa4edab7de","soft","Soft Skills","The half of the job nobody wrote documentation for.","Weekly, on the parts of working life that decide more than your code does — first weeks, meetings, interviews, promotions, and the people around you. Written from what actually happens, and recorded as a podcast you can listen to on the walk.","emerald-400","teal-300","◉",[13],{"courses":18,"paths":18,"articles":17,"exams":18,"flashcards":18,"packages":18,"community":17,"certificates":18,"teams":18,"commerce":18},3,[45,49,53,57,61,65,69,73,77,81,84,88],{"slug":46,"name":47,"articles":48},"webdev","Webdev",111,{"slug":50,"name":51,"articles":52},"javascript","Javascript",93,{"slug":54,"name":55,"articles":56},"frontend","Frontend",73,{"slug":58,"name":59,"articles":60},"tutorial","Tutorial",39,{"slug":62,"name":63,"articles":64},"css","Css",36,{"slug":66,"name":67,"articles":68},"typescript","Typescript",16,{"slug":70,"name":71,"articles":72},"performance","Performance",14,{"slug":74,"name":75,"articles":76},"react","React",13,{"slug":78,"name":79,"articles":80},"browser","Browser",10,{"slug":82,"name":83,"articles":80},"node","Node",{"slug":85,"name":86,"articles":87},"html","Html",8,{"slug":89,"name":90,"articles":91},"accessibility","Accessibility",7,{"id":93,"slug":94,"title":95,"subtitle":96,"excerpt":97,"coverUrl":98,"locale":13,"readingMinutes":72,"publishedAt":99,"viewCount":100,"likeCount":19,"commentCount":19,"author":101,"vertical":106,"topic":107,"tags":110,"_count":115,"playground":117,"body":119,"bodyMd":466,"seo":467,"translationGroupId":469,"series":470,"podcastUrl":96,"verticalId":5,"thread":491,"assessments":493,"translations":497,"quiz":499},"01a0ddae-48ac-73c6-bdee-1420cdfb17c2","nestjs-weekly-guards-canactivate-reflector","NestJS Guards: CanActivate, ExecutionContext & Reflector",null,"A complete guide to NestJS guards: how CanActivate, ExecutionContext, and the Reflector decide who reaches your route handler, with a cheat sheet.","\u002Fmedia\u002Fcovers\u002Fnestjs-weekly-guards-canactivate-reflector.png","2026-09-26T12:25:39.001Z",46,{"id":102,"name":103,"username":104,"avatarUrl":96,"headline":105},"019fe637-3c25-7088-9034-39c9f15dc3c8","Parsa Jiravand","parsa","Frontend engineer · building bestpractic",{"slug":6,"name":7,"accentFrom":10,"accentTo":11},{"slug":108,"name":109},"nestjs","Nestjs",[111,112,113,114],{"slug":108,"name":109,"color":96},{"slug":82,"name":83,"color":96},{"slug":66,"name":67,"color":96},{"slug":58,"name":59,"color":96},{"assessments":116},1,{"slug":94,"title":118},"NestJS guards — CanActivate & Reflector playground",{"blocks":120,"version":116},[121,125,128,131,136,139,148,151,154,157,172,176,179,185,188,192,195,198,201,204,207,213,216,219,223,226,230,233,236,239,242,245,249,252,256,259,263,267,271,274,277,280,284,287,290,294,297,300,304,307,310,318,321,329,332,335,338,341,344,348,351,355,358,362,365,368,372,398,401,404,412,415,418,421,424,427,430,433,436,439,442,445,448,451,454,457,460],{"id":122,"html":123,"type":124},"b1","\u003Cp>A code review flags a &quot;protected&quot; admin endpoint. The controller has \u003Ccode>@UseGuards(RolesGuard)\u003C\u002Fcode> on the class, \u003Ccode>RolesGuard\u003C\u002Fcode> injects a \u003Ccode>UserService\u003C\u002Fcode> to check role hierarchy, and it&#39;s registered application-wide with \u003Ccode>app.useGlobalGuards(new RolesGuard(reflector, userService))\u003C\u002Fcode> in \u003Ccode>main.ts\u003C\u002Fcode>. It looks careful. It is also broken: \u003Ccode>userService\u003C\u002Fcode> is \u003Ccode>undefined\u003C\u002Fcode> inside the guard, on every single request, and no test would have caught it because the app never crashed — it just let every request through the branch that assumes a user has no elevated role.\u003C\u002Fp>","paragraph",{"id":126,"html":127,"type":124},"b2","\u003Cp>Nothing here is a typo. The guard class is correct. The decorator is correct. The one thing wrong is \u003Cem>how\u003C\u002Fem> the guard was registered — and until you know what a guard actually is to Nest&#39;s container, that line looks completely reasonable.\u003C\u002Fp>",{"id":129,"html":130,"type":124},"b3","\u003Cp>This is written against \u003Cstrong>NestJS 12.0.x\u003C\u002Fstrong> (verified September 2026, current \u003Ccode>@nestjs\u002Fcore\u003C\u002Fcode> release, \u003Ca href=\"https:\u002F\u002Fgithub.com\u002Fnestjs\u002Fnest\u002Freleases\">v12.0.4\u003C\u002Fa>). The \u003Ccode>CanActivate\u003C\u002Fcode> interface, \u003Ccode>ExecutionContext\u003C\u002Fcode>, and \u003Ccode>Reflector\u003C\u002Fcode> covered here have been stable since well before v9 and are untouched by v12&#39;s ESM and Standard Schema changes — nothing in this article is version-fragile.\u003C\u002Fp>",{"id":132,"html":133,"text":134,"type":135,"level":31},"b4","What you&#39;ll learn","What you'll learn","heading",{"id":137,"html":138,"type":124},"b5","\u003Cp>By the end of this article you&#39;ll be able to:\u003C\u002Fp>",{"id":140,"type":141,"items":142,"ordered":18},"b6","list",[143,144,145,146,147],"Explain what a guard actually is — a DI-instantiated class, not a function you happen to call \u003Ccode>canActivate\u003C\u002Fcode>","Read and use \u003Ccode>ExecutionContext\u003C\u002Fcode> to get at the request, the handler, and the controller class from inside a guard","Build a \u003Ccode>Reflector\u003C\u002Fcode>-backed \u003Ccode>@Roles()\u003C\u002Fcode> decorator and understand exactly why the method&#39;s metadata overrides the class&#39;s","Register a global guard the \u003Cem>right\u003C\u002Fem> way (\u003Ccode>APP_GUARD\u003C\u002Fcode>) so it keeps its dependency injection","Predict, for any combination of global\u002Fcontroller\u002Fmethod guards, the exact order they run in and what &quot;all must pass&quot; means",{"id":149,"html":150,"text":150,"type":135,"level":31},"b7","Who this is for",{"id":152,"html":153,"type":124},"b8","\u003Cp>You&#39;ve written a NestJS controller, used \u003Ccode>@UseGuards()\u003C\u002Fcode> at least once, and you know what \u003Ccode>@Injectable()\u003C\u002Fcode> does. If you haven&#39;t read the \u003Ca href=\"https:\u002F\u002Fdev.to\u002Fparsajiravand\u002Fnestjs-request-lifecycle-explained-with-cheat-sheet-227l\">NestJS request lifecycle\u003C\u002Fa> episode of this series, it&#39;s a useful map of where guards sit relative to middleware, interceptors, and pipes — but this article is self-contained.\u003C\u002Fp>",{"id":155,"html":156,"text":156,"type":135,"level":31},"b9","Table of contents",{"id":158,"type":141,"items":159,"ordered":18},"b10",[160,161,162,163,164,165,166,167,168,169,170,171],"\u003Ca href=\"#the-problem-a-guard-that-quietly-cant-do-its-job\">The problem: a guard that quietly can&#39;t do its job\u003C\u002Fa>","\u003Ca href=\"#the-mental-model-a-guard-is-a-provider-not-a-function\">The mental model: a guard is a provider, not a function\u003C\u002Fa>","\u003Ca href=\"#stage-1-the-smallest-correct-guard\">Stage 1: the smallest correct guard\u003C\u002Fa>","\u003Ca href=\"#stage-2-executioncontext-properly\">Stage 2: ExecutionContext, properly\u003C\u002Fa>","\u003Ca href=\"#stage-3-reflector-and-a-real-roles-decorator\">Stage 3: Reflector and a real \u003Ccode>@Roles()\u003C\u002Fcode> decorator\u003C\u002Fa>","\u003Ca href=\"#stage-4-registering-a-global-guard-without-losing-di\">Stage 4: registering a global guard without losing DI\u003C\u002Fa>","\u003Ca href=\"#stage-5-composing-guards--order-and-all-must-pass\">Stage 5: composing guards — order and &quot;all must pass&quot;\u003C\u002Fa>","\u003Ca href=\"#edge-cases-and-gotchas\">Edge cases and gotchas\u003C\u002Fa>","\u003Ca href=\"#best-practices\">Best practices\u003C\u002Fa>","\u003Ca href=\"#faq\">FAQ\u003C\u002Fa>","\u003Ca href=\"#cheat-sheet\">Cheat sheet\u003C\u002Fa>","\u003Ca href=\"#key-takeaways\">Key takeaways\u003C\u002Fa>",{"id":173,"html":174,"text":175,"type":135,"level":31},"b11","The problem: a guard that quietly can&#39;t do its job","The problem: a guard that quietly can't do its job",{"id":177,"html":178,"type":124},"b12","\u003Cp>Here&#39;s the guard from the intro, in full:\u003C\u002Fp>",{"id":180,"code":181,"type":182,"language":183,"highlight":184},"b13","@Injectable()\nexport class RolesGuard implements CanActivate {\n  constructor(\n    private reflector: Reflector,\n    private userService: UserService, \u002F\u002F meant to check role hierarchy\n  ) {}\n\n  canActivate(context: ExecutionContext): boolean {\n    const required = this.reflector.get\u003Cstring[]>(\"roles\", context.getHandler());\n    if (!required) return true;\n    const { user } = context.switchToHttp().getRequest();\n    \u002F\u002F userService is undefined here — this branch always throws or always no-ops\n    return this.userService.hasAnyRole(user, required);\n  }\n}","code","ts",[],{"id":186,"html":187,"type":124},"b14","\u003Cp>And here&#39;s how it was wired up, because &quot;global&quot; sounded like the right word for &quot;runs on every route&quot;:\u003C\u002Fp>",{"id":189,"code":190,"type":182,"language":183,"highlight":191},"b15","\u002F\u002F main.ts — looks reasonable, is quietly broken\nconst app = await NestFactory.create(AppModule);\napp.useGlobalGuards(new RolesGuard(new Reflector(), \u002F* userService? *\u002F undefined));",[],{"id":193,"html":194,"type":124},"b16","\u003Cp>\u003Ccode>app.useGlobalGuards()\u003C\u002Fcode> takes an \u003Cem>instance\u003C\u002Fem>. Nothing about that instance goes through Nest&#39;s dependency injection — you constructed it yourself, with \u003Ccode>new\u003C\u002Fcode>, outside any module, before the application&#39;s providers even exist to hand it a real \u003Ccode>UserService\u003C\u002Fcode>. Nest will happily call \u003Ccode>canActivate()\u003C\u002Fcode> on this object for every request. It just can&#39;t give it the dependency the guard was written to use.\u003C\u002Fp>",{"id":196,"html":197,"type":124},"b17","\u003Cp>The fix isn&#39;t a different guard. It&#39;s a different \u003Cem>registration\u003C\u002Fem>, covered in \u003Ca href=\"#stage-4-registering-a-global-guard-without-losing-di\">Stage 4\u003C\u002Fa>. But to see why that fix works, you need the actual mental model of what a guard is.\u003C\u002Fp>",{"id":199,"html":200,"text":200,"type":135,"level":31},"b18","The mental model: a guard is a provider, not a function",{"id":202,"html":203,"type":124},"b19","\u003Cp>\u003Cstrong>The mental model:\u003C\u002Fstrong> a NestJS guard is an ordinary DI provider — the same kind of class as a service — that additionally implements one method, \u003Ccode>canActivate(context: ExecutionContext)\u003C\u002Fcode>, which Nest calls immediately before it would otherwise invoke your route handler. If \u003Ccode>canActivate\u003C\u002Fcode> resolves to \u003Ccode>true\u003C\u002Fcode>, the request keeps moving toward interceptors, pipes, and the handler. If it resolves to \u003Ccode>false\u003C\u002Fcode>, or throws, the handler never runs and Nest hands the request straight to the exception-filter layer.\u003C\u002Fp>",{"id":205,"html":206,"type":124},"b20","\u003Cp>Three consequences fall out of that one sentence, and they&#39;re the three things the intro&#39;s bug got wrong:\u003C\u002Fp>",{"id":208,"type":141,"items":209,"ordered":17},"b21",[210,211,212],"\u003Cstrong>A guard only gets real dependency injection if Nest constructs it.\u003C\u002Fstrong> \u003Ccode>@UseGuards(RolesGuard)\u003C\u002Fcode> (passing the \u003Cem>class\u003C\u002Fem>) lets Nest instantiate it through the container, resolving its constructor arguments normally. \u003Ccode>new RolesGuard(...)\u003C\u002Fcode> (passing an \u003Cem>instance\u003C\u002Fem> you built) does not — you&#39;re on your own for every dependency.","\u003Cstrong>A guard doesn&#39;t see &quot;a request&quot; in the abstract — it sees an \u003Ccode>ExecutionContext\u003C\u002Fcode>.\u003C\u002Fstrong> That&#39;s a wrapper Nest builds fresh for every incoming call, giving the guard a uniform way to reach the underlying request \u003Cem>and\u003C\u002Fem> to ask &quot;what handler and class is Nest about to invoke?&quot; — which is exactly what a guard needs to look up route-specific metadata.","\u003Cstrong>A guard&#39;s decision is binary, not additive.\u003C\u002Fstrong> It either lets a request through or it doesn&#39;t. Anything more nuanced than &quot;yes\u002Fno&quot; — attaching data, transforming the body — is an interceptor&#39;s or a pipe&#39;s job, not a guard&#39;s.",{"id":214,"html":215,"text":215,"type":135,"level":31},"b22","Stage 1: the smallest correct guard",{"id":217,"html":218,"type":124},"b23","\u003Cp>The simplest guard that compiles and does something real:\u003C\u002Fp>",{"id":220,"code":221,"type":182,"language":183,"highlight":222},"b24","import { CanActivate, ExecutionContext, Injectable } from \"@nestjs\u002Fcommon\";\n\n@Injectable()\nexport class AuthGuard implements CanActivate {\n  canActivate(context: ExecutionContext): boolean {\n    const request = context.switchToHttp().getRequest();\n    return Boolean(request.headers.authorization);\n  }\n}",[],{"id":224,"html":225,"type":124},"b25","\u003Cp>Apply it to one route:\u003C\u002Fp>",{"id":227,"code":228,"type":182,"language":183,"highlight":229},"b26","@UseGuards(AuthGuard)\n@Get(\"profile\")\ngetProfile(@Req() req: Request) {\n  return req.user;\n}",[],{"id":231,"html":232,"type":124},"b27","\u003Cp>\u003Cstrong>Key concept:\u003C\u002Fstrong> \u003Ccode>canActivate\u003C\u002Fcode> can return \u003Ccode>boolean\u003C\u002Fcode>, \u003Ccode>Promise&lt;boolean&gt;\u003C\u002Fcode>, or \u003Ccode>Observable&lt;boolean&gt;\u003C\u002Fcode> — Nest awaits or subscribes to whichever you give it. A guard that calls a database or an external identity provider to check a session is completely normal; just make it \u003Ccode>async canActivate(...): Promise&lt;boolean&gt;\u003C\u002Fcode> and Nest will wait for it before deciding.\u003C\u002Fp>",{"id":234,"html":235,"text":235,"type":135,"level":31},"b28","Stage 2: ExecutionContext, properly",{"id":237,"html":238,"type":124},"b29","\u003Cp>\u003Ccode>ExecutionContext\u003C\u002Fcode> is the single argument every guard, interceptor, and exception filter receives, and it answers two different questions:\u003C\u002Fp>",{"id":240,"html":241,"type":124},"b30","\u003Cp>\u003Cstrong>&quot;What kind of call is this, and what&#39;s the underlying request object?&quot;\u003C\u002Fstrong> — via \u003Ccode>switchToHttp()\u003C\u002Fcode>, \u003Ccode>switchToRpc()\u003C\u002Fcode>, or \u003Ccode>switchToWs()\u003C\u002Fcode>. Most guards only ever call \u003Ccode>context.switchToHttp().getRequest()\u003C\u002Fcode>, but the same guard class \u003Cem>can\u003C\u002Fem> run in front of a WebSocket gateway or a microservice handler if you check \u003Ccode>context.getType()\u003C\u002Fcode> first and branch — that&#39;s what makes \u003Ccode>ExecutionContext\u003C\u002Fcode> a context, not just an HTTP request wrapper.\u003C\u002Fp>",{"id":243,"html":244,"type":124},"b31","\u003Cp>\u003Cstrong>&quot;Which handler and which class is Nest about to call?&quot;\u003C\u002Fstrong> — via \u003Ccode>context.getHandler()\u003C\u002Fcode> (the specific route method, as a function reference) and \u003Ccode>context.getClass()\u003C\u002Fcode> (the controller class). This half is what makes metadata-driven guards possible, because it&#39;s the \u003Cem>only\u003C\u002Fem> way a guard can ask &quot;does this specific route carry a \u003Ccode>@Roles(...)\u003C\u002Fcode> decorator?&quot; — the guard runs once per registration, but \u003Ccode>getHandler()\u003C\u002Fcode>\u002F\u003Ccode>getClass()\u003C\u002Fcode> tell it which route it&#39;s currently deciding for.\u003C\u002Fp>",{"id":246,"code":247,"type":182,"language":183,"highlight":248},"b32","canActivate(context: ExecutionContext): boolean {\n  const handlerName = context.getHandler().name;      \u002F\u002F e.g. \"getProfile\"\n  const controllerName = context.getClass().name;     \u002F\u002F e.g. \"UsersController\"\n  const request = context.switchToHttp().getRequest();\n  \u002F\u002F ...\n}",[],{"id":250,"html":251,"type":124},"b33","\u003Cp>\u003Cstrong>Key concept:\u003C\u002Fstrong> \u003Ccode>getHandler()\u003C\u002Fcode> and \u003Ccode>getClass()\u003C\u002Fcode> return the raw function\u002Fclass references, not strings — they exist so you can hand them to \u003Ccode>Reflector\u003C\u002Fcode>, which looks up metadata \u003Cem>attached to those exact references\u003C\u002Fem>. That&#39;s the bridge to Stage 3.\u003C\u002Fp>",{"id":253,"html":254,"text":255,"type":135,"level":31},"b34","Stage 3: Reflector and a real \u003Ccode>@Roles()\u003C\u002Fcode> decorator","Stage 3: Reflector and a real @Roles() decorator",{"id":257,"html":258,"type":124},"b35","\u003Cp>Hardcoding a role check per route doesn&#39;t scale, and neither does branching on \u003Ccode>handler.name\u003C\u002Fcode> — a rename breaks it silently. The idiomatic pattern is a custom decorator that attaches metadata, and a \u003Ccode>Reflector\u003C\u002Fcode> that reads it back inside a guard.\u003C\u002Fp>",{"id":260,"code":261,"type":182,"language":183,"highlight":262},"b36","\u002F\u002F roles.decorator.ts\nimport { SetMetadata } from \"@nestjs\u002Fcommon\";\n\nexport const ROLES_KEY = \"roles\";\nexport const Roles = (...roles: string[]) => SetMetadata(ROLES_KEY, roles);",[],{"id":264,"code":265,"type":182,"language":183,"highlight":266},"b37","\u002F\u002F roles.guard.ts\nimport { CanActivate, ExecutionContext, Injectable } from \"@nestjs\u002Fcommon\";\nimport { Reflector } from \"@nestjs\u002Fcore\";\nimport { ROLES_KEY } from \".\u002Froles.decorator\";\n\n@Injectable()\nexport class RolesGuard implements CanActivate {\n  constructor(private reflector: Reflector) {}\n\n  canActivate(context: ExecutionContext): boolean {\n    const required = this.reflector.getAllAndOverride\u003Cstring[]>(ROLES_KEY, [\n      context.getHandler(),\n      context.getClass(),\n    ]);\n    if (!required || required.length === 0) return true; \u002F\u002F no @Roles() = open route\n\n    const { user } = context.switchToHttp().getRequest();\n    return required.some((role) => user?.roles?.includes(role));\n  }\n}",[],{"id":268,"code":269,"type":182,"language":183,"highlight":270},"b38","@Controller(\"orders\")\n@Roles(\"editor\") \u002F\u002F class-level default\nexport class OrdersController {\n  @Get()\n  list() { \u002F* requires \"editor\" — inherits the class default *\u002F }\n\n  @Delete(\":id\")\n  @Roles(\"admin\") \u002F\u002F method-level override\n  remove() { \u002F* requires \"admin\" — this wins over the class's \"editor\" *\u002F }\n}",[],{"id":272,"html":273,"type":124},"b39","\u003Cp>\u003Cstrong>Key concept:\u003C\u002Fstrong> \u003Ccode>getAllAndOverride(key, [handler, class])\u003C\u002Fcode> checks the handler first, then the class, and returns the \u003Cstrong>first one it finds\u003C\u002Fstrong> — it does not merge arrays. That order in the array is why a method-level \u003Ccode>@Roles(&quot;admin&quot;)\u003C\u002Fcode> completely replaces the class-level \u003Ccode>@Roles(&quot;editor&quot;)\u003C\u002Fcode> rather than requiring both. If you actually want both handler and class metadata combined, \u003Ccode>Reflector\u003C\u002Fcode> also has \u003Ccode>getAllAndMerge()\u003C\u002Fcode>, which concatenates arrays instead of short-circuiting — reach for it explicitly when &quot;either level can add a role&quot; is the behavior you want.\u003C\u002Fp>",{"id":275,"html":276,"text":276,"type":135,"level":31},"b40","Stage 4: registering a global guard without losing DI",{"id":278,"html":279,"type":124},"b41","\u003Cp>Back to the intro&#39;s bug. \u003Ccode>app.useGlobalGuards(new RolesGuard(...))\u003C\u002Fcode> builds the guard outside the container, so any constructor dependency has to be supplied by hand — which is exactly what went wrong. The fix is to register the guard as a provider, using the \u003Ccode>APP_GUARD\u003C\u002Fcode> injection token from \u003Ccode>@nestjs\u002Fcore\u003C\u002Fcode>:\u003C\u002Fp>",{"id":281,"code":282,"type":182,"language":183,"highlight":283},"b42","import { APP_GUARD } from \"@nestjs\u002Fcore\";\n\n@Module({\n  providers: [\n    RolesGuard,\n    { provide: APP_GUARD, useClass: RolesGuard },\n  ],\n})\nexport class AppModule {}",[],{"id":285,"html":286,"type":124},"b43","\u003Cp>Because \u003Ccode>RolesGuard\u003C\u002Fcode> is now a normal provider, Nest resolves its constructor the usual way — \u003Ccode>Reflector\u003C\u002Fcode> (and, in the intro&#39;s case, a real \u003Ccode>UserService\u003C\u002Fcode>) get injected correctly, module-scoped providers work, and \u003Ccode>Test.createTestingModule\u003C\u002Fcode> can \u003Ccode>overrideProvider(RolesGuard)\u003C\u002Fcode> in tests the same way it overrides any other dependency, as covered in this series&#39; \u003Ca href=\"https:\u002F\u002Fdev.to\u002Fparsajiravand\u002Fnestjs-testing-module-provider-overrides-with-cheat-sheet-1o79\">testing module episode\u003C\u002Fa>. None of that is available to a guard built with \u003Ccode>new\u003C\u002Fcode> in \u003Ccode>main.ts\u003C\u002Fcode>.\u003C\u002Fp>",{"id":288,"html":289,"type":124},"b44","\u003Cp>\u003Cstrong>Key concept:\u003C\u002Fstrong> \u003Ccode>app.useGlobalGuards()\u003C\u002Fcode> still exists and still works for a guard with zero dependencies — it&#39;s not deprecated. The rule is narrower and easy to remember: the moment a guard&#39;s constructor needs anything Nest would normally inject, register it through \u003Ccode>APP_GUARD\u003C\u002Fcode>, not \u003Ccode>useGlobalGuards()\u003C\u002Fcode>.\u003C\u002Fp>",{"id":291,"html":292,"text":293,"type":135,"level":31},"b45","Stage 5: composing guards — order and &quot;all must pass&quot;","Stage 5: composing guards — order and \"all must pass\"",{"id":295,"html":296,"type":124},"b46","\u003Cp>A single request can pass through guards registered at three different scopes at once: global (\u003Ccode>APP_GUARD\u003C\u002Fcode>, or \u003Ccode>useGlobalGuards()\u003C\u002Fcode>), controller (\u003Ccode>@UseGuards()\u003C\u002Fcode> on the class), and method (\u003Ccode>@UseGuards()\u003C\u002Fcode> on the handler). Nest runs them in that exact order — global, then controller, then method — and within one \u003Ccode>@UseGuards(A, B)\u003C\u002Fcode> call, in the order listed.\u003C\u002Fp>",{"id":298,"html":299,"type":124},"b47","\u003Cp>This composition is a logical \u003Cstrong>AND\u003C\u002Fstrong>, not a fallback chain: every guard in the sequence must return (or resolve to) \u003Ccode>true\u003C\u002Fcode>, or the request is rejected at the first one that doesn&#39;t. There&#39;s no &quot;guard B can override guard A&#39;s denial&quot; — a single \u003Ccode>false\u003C\u002Fcode> anywhere in the chain ends the request immediately, and every guard after it, plus every interceptor and pipe, is skipped entirely.\u003C\u002Fp>",{"id":301,"code":302,"type":182,"language":183,"highlight":303},"b48","@UseGuards(ThrottleGuard, RolesGuard) \u002F\u002F ThrottleGuard runs first\n@Controller(\"orders\")\nexport class OrdersController {}",[],{"id":305,"html":306,"type":124},"b49","\u003Cp>If a global \u003Ccode>AuthGuard\u003C\u002Fcode> is also registered via \u003Ccode>APP_GUARD\u003C\u002Fcode>, the real order for any route on this controller is: \u003Ccode>AuthGuard\u003C\u002Fcode> → \u003Ccode>ThrottleGuard\u003C\u002Fcode> → \u003Ccode>RolesGuard\u003C\u002Fcode> → (method-level guards, if any) → interceptors → pipes → the handler.\u003C\u002Fp>",{"id":308,"html":309,"text":309,"type":135,"level":31},"b50","Edge cases and gotchas",{"id":311,"type":141,"items":312,"ordered":18},"b51",[313,314,315,316,317],"\u003Cstrong>A guard that throws vs. a guard that returns \u003Ccode>false\u003C\u002Fcode>.\u003C\u002Fstrong> Returning \u003Ccode>false\u003C\u002Fcode> produces a generic \u003Ccode>403 Forbidden\u003C\u002Fcode>. Throwing a specific exception — \u003Ccode>throw new UnauthorizedException(&quot;Session expired&quot;)\u003C\u002Fcode> — gives the client (and your logs) a far more useful signal, and is the idiomatic choice for anything beyond &quot;just deny it.&quot;","\u003Cstrong>\u003Ccode>Reflector\u003C\u002Fcode> needs the exact same metadata key everywhere.\u003C\u002Fstrong> \u003Ccode>SetMetadata(ROLES_KEY, ...)\u003C\u002Fcode> and \u003Ccode>reflector.getAllAndOverride(ROLES_KEY, ...)\u003C\u002Fcode> must use the identical string (or, better, the same exported constant). A typo in one spot means the guard silently sees \u003Ccode>undefined\u003C\u002Fcode> and treats the route as unrestricted — this fails open, which is the worst direction for an auth check to fail.","\u003Cstrong>\u003Ccode>getAllAndOverride\u003C\u002Fcode> vs \u003Ccode>getAllAndMerge\u003C\u002Fcode>.\u003C\u002Fstrong> Covered in Stage 3, but worth repeating because it&#39;s the single most common \u003Ccode>Reflector\u003C\u002Fcode> mistake: reach for \u003Ccode>getAllAndOverride\u003C\u002Fcode> when a method should be able to fully replace a class default, and \u003Ccode>getAllAndMerge\u003C\u002Fcode> when both levels should contribute.","\u003Cstrong>WebSocket and microservice guards need a type check.\u003C\u002Fstrong> \u003Ccode>context.switchToHttp()\u003C\u002Fcode> throws if the current call isn&#39;t actually HTTP. A guard meant to run across transports should branch on \u003Ccode>context.getType()\u003C\u002Fcode> (\u003Ccode>&quot;http&quot;\u003C\u002Fcode>, \u003Ccode>&quot;ws&quot;\u003C\u002Fcode>, \u003Ccode>&quot;rpc&quot;\u003C\u002Fcode>) before picking which \u003Ccode>switchTo*()\u003C\u002Fcode> to call.","\u003Cstrong>A denied guard skips the &quot;before&quot; half of interceptors too.\u003C\u002Fstrong> Interceptors run after guards, so a rejected request never reaches even the setup code in an interceptor — only the exception-filter layer sees it.",{"id":319,"html":320,"text":320,"type":135,"level":31},"b52","Best practices",{"id":322,"type":141,"items":323,"ordered":18},"b53",[324,325,326,327,328],"\u003Cstrong>Keep guards to yes\u002Fno authorization decisions.\u003C\u002Fstrong> If you find yourself mutating the request object inside a guard, that logic usually belongs in middleware (before routing) or an interceptor (after the handler is chosen) instead.","\u003Cstrong>Prefer metadata-driven guards over hardcoded checks.\u003C\u002Fstrong> A \u003Ccode>@Roles()\u003C\u002Fcode>\u002F\u003Ccode>Reflector\u003C\u002Fcode> pair scales to new routes with zero changes to the guard itself; an \u003Ccode>if (handler.name === &quot;remove&quot;)\u003C\u002Fcode> branch doesn&#39;t.","\u003Cstrong>Register anything with a dependency via \u003Ccode>APP_GUARD\u003C\u002Fcode>, never \u003Ccode>new Guard()\u003C\u002Fcode>.\u003C\u002Fstrong> It&#39;s the difference between a guard that&#39;s testable and overridable, and one that silently can&#39;t be either.","\u003Cstrong>Fail closed, not open.\u003C\u002Fstrong> If a metadata lookup comes back \u003Ccode>undefined\u003C\u002Fcode> because of a wiring mistake, decide what that \u003Cem>should\u003C\u002Fem> mean deliberately (usually: deny), rather than letting \u003Ccode>!required\u003C\u002Fcode> accidentally mean &quot;allow everyone.&quot;","\u003Cstrong>One guard, one concern.\u003C\u002Fstrong> A \u003Ccode>ThrottleGuard\u003C\u002Fcode> and a \u003Ccode>RolesGuard\u003C\u002Fcode> composed via \u003Ccode>@UseGuards(ThrottleGuard, RolesGuard)\u003C\u002Fcode> are each easier to test and reuse than one guard doing both jobs.",{"id":330,"html":331,"text":331,"type":135,"level":31},"b54","FAQ",{"id":333,"html":334,"text":334,"type":135,"level":43},"b55","Do guards run before or after middleware?",{"id":336,"html":337,"type":124},"b56","\u003Cp>After. Middleware runs first and doesn&#39;t know which controller or handler will end up serving the request; guards run once routing has resolved to a specific handler, which is what lets a guard call \u003Ccode>context.getHandler()\u003C\u002Fcode>.\u003C\u002Fp>",{"id":339,"html":340,"text":340,"type":135,"level":43},"b57","Can a guard inject a service?",{"id":342,"html":343,"type":124},"b58","\u003Cp>Yes, as long as Nest constructs the guard — via \u003Ccode>@UseGuards(SomeGuard)\u003C\u002Fcode> (the class) or an \u003Ccode>APP_GUARD\u003C\u002Fcode> provider. A guard instance you build yourself with \u003Ccode>new\u003C\u002Fcode> gets none of Nest&#39;s dependency injection.\u003C\u002Fp>",{"id":345,"html":346,"text":347,"type":135,"level":43},"b59","Can I use \u003Ccode>@UseGuards()\u003C\u002Fcode> more than once on the same controller?","Can I use @UseGuards() more than once on the same controller?",{"id":349,"html":350,"type":124},"b60","\u003Cp>Yes — \u003Ccode>@UseGuards(A, B, C)\u003C\u002Fcode> runs them in that order, and you can also stack a class-level \u003Ccode>@UseGuards()\u003C\u002Fcode> with a method-level one; both apply, in the global → controller → method order described in Stage 5.\u003C\u002Fp>",{"id":352,"html":353,"text":354,"type":135,"level":43},"b61","What does a guard returning \u003Ccode>false\u003C\u002Fcode> actually send to the client?","What does a guard returning false actually send to the client?",{"id":356,"html":357,"type":124},"b62","\u003Cp>A \u003Ccode>403 Forbidden\u003C\u002Fcode> by default, handled by Nest&#39;s built-in exception layer. Throw a specific \u003Ccode>HttpException\u003C\u002Fcode> subclass from inside the guard if you need a different status code or a custom error body.\u003C\u002Fp>",{"id":359,"html":360,"text":361,"type":135,"level":43},"b63","Is \u003Ccode>Reflector\u003C\u002Fcode> only for guards?","Is Reflector only for guards?",{"id":363,"html":364,"type":124},"b64","\u003Cp>No — interceptors and custom decorators use it too, for the same reason: reading metadata attached to a handler or class via \u003Ccode>SetMetadata\u003C\u002Fcode>. Guards are just its most common consumer, because &quot;does this route require X&quot; is the canonical authorization question.\u003C\u002Fp>",{"id":366,"html":367,"text":367,"type":135,"level":31},"b65","Cheat sheet",{"id":369,"code":370,"type":182,"language":183,"highlight":371},"b66","\u002F\u002F A guard is a provider that implements CanActivate.\n@Injectable()\nexport class MyGuard implements CanActivate {\n  constructor(private reflector: Reflector) {} \u002F\u002F real DI, if registered correctly\n\n  canActivate(ctx: ExecutionContext): boolean | Promise\u003Cboolean> {\n    const req = ctx.switchToHttp().getRequest();       \u002F\u002F the underlying request\n    const handler = ctx.getHandler();                  \u002F\u002F the exact route method\n    const controller = ctx.getClass();                 \u002F\u002F the controller class\n    return true; \u002F\u002F or false, or throw a specific HttpException\n  }\n}\n\n\u002F\u002F Metadata decorator + read-back\nexport const ROLES_KEY = \"roles\";\nexport const Roles = (...roles: string[]) => SetMetadata(ROLES_KEY, roles);\n\u002F\u002F method metadata wins over class metadata:\nreflector.getAllAndOverride\u003Cstring[]>(ROLES_KEY, [ctx.getHandler(), ctx.getClass()]);\n\u002F\u002F both levels contribute instead:\nreflector.getAllAndMerge\u003Cstring[]>(ROLES_KEY, [ctx.getHandler(), ctx.getClass()]);\n\n\u002F\u002F Registration — pick based on whether the guard has dependencies\n@UseGuards(MyGuard)              \u002F\u002F per-route or per-controller, always through DI\napp.useGlobalGuards(new MyGuard()); \u002F\u002F global, but NO dependency injection\n{ provide: APP_GUARD, useClass: MyGuard } \u002F\u002F global, WITH dependency injection",[],{"id":373,"head":374,"rows":379,"type":397},"b67",[375,376,377,378],"Scope","Registration","Runs when","Gets DI?",[380,385,389,393],[381,382,383,384],"Method","\u003Ccode>@UseGuards(G)\u003C\u002Fcode> on a handler","Only that route","Yes",[386,387,388,384],"Controller","\u003Ccode>@UseGuards(G)\u003C\u002Fcode> on a class","Every route in that controller",[390,391,392,384],"Global (correct)","\u003Ccode>APP_GUARD\u003C\u002Fcode> provider","Every route in the app",[394,395,392,396],"Global (limited)","\u003Ccode>app.useGlobalGuards(new G())\u003C\u002Fcode>","No","table",{"id":399,"html":400,"type":124},"b68","\u003Cp>Execution order for one request: \u003Cstrong>global → controller → method\u003C\u002Fstrong>, each one an AND — the first \u003Ccode>false\u003C\u002Fcode> (or thrown exception) stops the chain immediately.\u003C\u002Fp>",{"id":402,"html":403,"text":403,"type":135,"level":31},"b69","Key takeaways",{"id":405,"type":141,"items":406,"ordered":18},"b70",[407,408,409,410,411],"A guard is a DI provider with a \u003Ccode>canActivate(context: ExecutionContext)\u003C\u002Fcode> method — not a bare function, and not free of the container&#39;s rules.","\u003Ccode>ExecutionContext\u003C\u002Fcode> gives a guard the underlying request (via \u003Ccode>switchToHttp()\u003C\u002Fcode>\u002F\u003Ccode>switchToWs()\u003C\u002Fcode>\u002F\u003Ccode>switchToRpc()\u003C\u002Fcode>) and the exact handler\u002Fclass Nest is about to invoke (via \u003Ccode>getHandler()\u003C\u002Fcode>\u002F\u003Ccode>getClass()\u003C\u002Fcode>).","\u003Ccode>Reflector.getAllAndOverride()\u003C\u002Fcode> reads metadata attached with a custom decorator, checking the method before the class, and returns the first match — use \u003Ccode>getAllAndMerge()\u003C\u002Fcode> when you want both to contribute instead.","\u003Ccode>app.useGlobalGuards(new G())\u003C\u002Fcode> skips dependency injection entirely; use the \u003Ccode>APP_GUARD\u003C\u002Fcode> provider token for any global guard with constructor dependencies.","Guards compose as global → controller → method, and it&#39;s a strict AND: any single \u003Ccode>false\u003C\u002Fcode> or thrown exception stops the request before it reaches the next guard, any interceptor, or the handler.",{"id":413,"html":414,"text":414,"type":135,"level":31},"b71","Ending",{"id":416,"html":417,"type":124},"b72","\u003Cp>The guard from the intro wasn&#39;t wrong about \u003Cem>what\u003C\u002Fem> it wanted to check — it was wrong about \u003Cem>how it was born\u003C\u002Fem>. \u003Ccode>new RolesGuard(...)\u003C\u002Fcode> and \u003Ccode>{ provide: APP_GUARD, useClass: RolesGuard }\u003C\u002Fcode> compile to the same class doing the same check, and only one of them lets Nest&#39;s container do its job. That&#39;s the whole lesson of guards: they look like plain functions with a \u003Ccode>canActivate\u003C\u002Fcode> name, but every guarantee they can offer — real dependencies, testability, metadata lookups through \u003Ccode>ExecutionContext\u003C\u002Fcode> — depends on Nest actually building them. Next time a &quot;protected&quot; route turns out not to be, check the registration line before you touch the guard&#39;s logic.\u003C\u002Fp>",{"id":419,"html":420,"type":124},"b73","\u003Cp>What&#39;s the strangest guard bug you&#39;ve chased down — a missing dependency, a metadata key typo, or something else? Drop it in the comments.\u003C\u002Fp>",{"id":422,"html":423,"type":124},"b74","\u003C!-- playground:start -->",{"id":425,"html":426,"text":426,"type":135,"level":31},"b75","🎮 Try it yourself",{"id":428,"html":429,"type":124},"b76","\u003Cp>\u003Cstrong>\u003Ca href=\"https:\u002F\u002Fbestpractic.org\u002Fblog\u002Fnestjs-weekly-guards-canactivate-reflector\u002Fplayground\">▶️ Open the interactive playground →\u003C\u002Fa>\u003C\u002Fstrong>\u003C\u002Fp>",{"id":431,"html":432,"type":124},"b77","\u003Cp>\u003Cem>Runs right in your browser — poke at it and watch the concept react live.\u003C\u002Fem>\u003C\u002Fp>",{"id":434,"html":435,"type":124},"b78","\u003C!-- playground:end -->",{"id":437,"html":438,"type":124},"b79","\u003C!-- quiz:start -->",{"id":440,"html":441,"text":441,"type":135,"level":31},"b80","🧠 Test yourself",{"id":443,"html":444,"type":124},"b81","\u003Cp>Think it clicked? \u003Cstrong>\u003Ca href=\"https:\u002F\u002Fbestpractic.org\u002Fblog\u002Fnestjs-weekly-guards-canactivate-reflector\u002Fquiz\">Take the 7-question quiz →\u003C\u002Fa>\u003C\u002Fstrong>\u003C\u002Fp>",{"id":446,"html":447,"type":124},"b82","\u003Cp>\u003Cem>Instant feedback, a hint on every question, and an explanation for each answer — right or wrong.\u003C\u002Fem>\u003C\u002Fp>",{"id":449,"html":450,"type":124},"b83","\u003C!-- quiz:end -->",{"id":452,"type":453},"b84","divider",{"id":455,"html":456,"type":124},"b85","\u003Cp>🚀 \u003Cstrong>Want more like this?\u003C\u002Fstrong> Every guide, playground, and quiz lives on \u003Cstrong>\u003Ca href=\"https:\u002F\u002Fbestpractic.org\u002F\">bestpractic.org\u003C\u002Fa>\u003C\u002Fstrong> — open it and \u003Cstrong>\u003Ca href=\"https:\u002F\u002Fbestpractic.org\u002F\">sign up free\u003C\u002Fa>\u003C\u002Fstrong> so the next one finds you.\u003C\u002Fp>",{"id":458,"html":459,"type":124},"b86","\u003Cp>\u003Cem>Thanks for reading! Let&#39;s stay connected:\u003C\u002Fem>\u003C\u002Fp>",{"id":461,"type":141,"items":462,"ordered":18},"b87",[463,464,465],"⭐ \u003Cstrong>GitHub\u003C\u002Fstrong> — follow me and star the projects: \u003Ca href=\"https:\u002F\u002Fgithub.com\u002Fparsajiravand\">github.com\u002Fparsajiravand\u003C\u002Fa>","💬 \u003Cstrong>Discord\u003C\u002Fstrong> — join the frontend best-practices community: \u003Ca href=\"https:\u002F\u002Fdiscord.gg\u002Fd9KRhuAwQ\">discord.gg\u002Fd9KRhuAwQ\u003C\u002Fa>","📸 \u003Cstrong>Instagram\u003C\u002Fstrong> — frontend best practices, daily: \u003Ca href=\"https:\u002F\u002Fwww.instagram.com\u002Fbestpractice___\u002F\">@bestpractice___\u003C\u002Fa>","A code review flags a \"protected\" admin endpoint. The controller has `@UseGuards(RolesGuard)` on the class, `RolesGuard` injects a `UserService` to check role hierarchy, and it's registered application-wide with `app.useGlobalGuards(new RolesGuard(reflector, userService))` in `main.ts`. It looks careful. It is also broken: `userService` is `undefined` inside the guard, on every single request, and no test would have caught it because the app never crashed — it just let every request through the branch that assumes a user has no elevated role.\n\nNothing here is a typo. The guard class is correct. The decorator is correct. The one thing wrong is *how* the guard was registered — and until you know what a guard actually is to Nest's container, that line looks completely reasonable.\n\nThis is written against **NestJS 12.0.x** (verified September 2026, current `@nestjs\u002Fcore` release, [v12.0.4](https:\u002F\u002Fgithub.com\u002Fnestjs\u002Fnest\u002Freleases)). The `CanActivate` interface, `ExecutionContext`, and `Reflector` covered here have been stable since well before v9 and are untouched by v12's ESM and Standard Schema changes — nothing in this article is version-fragile.\n\n## What you'll learn\n\nBy the end of this article you'll be able to:\n\n- Explain what a guard actually is — a DI-instantiated class, not a function you happen to call `canActivate`\n- Read and use `ExecutionContext` to get at the request, the handler, and the controller class from inside a guard\n- Build a `Reflector`-backed `@Roles()` decorator and understand exactly why the method's metadata overrides the class's\n- Register a global guard the *right* way (`APP_GUARD`) so it keeps its dependency injection\n- Predict, for any combination of global\u002Fcontroller\u002Fmethod guards, the exact order they run in and what \"all must pass\" means\n\n## Who this is for\n\nYou've written a NestJS controller, used `@UseGuards()` at least once, and you know what `@Injectable()` does. If you haven't read the [NestJS request lifecycle](https:\u002F\u002Fdev.to\u002Fparsajiravand\u002Fnestjs-request-lifecycle-explained-with-cheat-sheet-227l) episode of this series, it's a useful map of where guards sit relative to middleware, interceptors, and pipes — but this article is self-contained.\n\n## Table of contents\n\n- [The problem: a guard that quietly can't do its job](#the-problem-a-guard-that-quietly-cant-do-its-job)\n- [The mental model: a guard is a provider, not a function](#the-mental-model-a-guard-is-a-provider-not-a-function)\n- [Stage 1: the smallest correct guard](#stage-1-the-smallest-correct-guard)\n- [Stage 2: ExecutionContext, properly](#stage-2-executioncontext-properly)\n- [Stage 3: Reflector and a real `@Roles()` decorator](#stage-3-reflector-and-a-real-roles-decorator)\n- [Stage 4: registering a global guard without losing DI](#stage-4-registering-a-global-guard-without-losing-di)\n- [Stage 5: composing guards — order and \"all must pass\"](#stage-5-composing-guards--order-and-all-must-pass)\n- [Edge cases and gotchas](#edge-cases-and-gotchas)\n- [Best practices](#best-practices)\n- [FAQ](#faq)\n- [Cheat sheet](#cheat-sheet)\n- [Key takeaways](#key-takeaways)\n\n## The problem: a guard that quietly can't do its job\n\nHere's the guard from the intro, in full:\n\n```typescript\n@Injectable()\nexport class RolesGuard implements CanActivate {\n  constructor(\n    private reflector: Reflector,\n    private userService: UserService, \u002F\u002F meant to check role hierarchy\n  ) {}\n\n  canActivate(context: ExecutionContext): boolean {\n    const required = this.reflector.get\u003Cstring[]>(\"roles\", context.getHandler());\n    if (!required) return true;\n    const { user } = context.switchToHttp().getRequest();\n    \u002F\u002F userService is undefined here — this branch always throws or always no-ops\n    return this.userService.hasAnyRole(user, required);\n  }\n}\n```\n\nAnd here's how it was wired up, because \"global\" sounded like the right word for \"runs on every route\":\n\n```typescript\n\u002F\u002F main.ts — looks reasonable, is quietly broken\nconst app = await NestFactory.create(AppModule);\napp.useGlobalGuards(new RolesGuard(new Reflector(), \u002F* userService? *\u002F undefined));\n```\n\n`app.useGlobalGuards()` takes an *instance*. Nothing about that instance goes through Nest's dependency injection — you constructed it yourself, with `new`, outside any module, before the application's providers even exist to hand it a real `UserService`. Nest will happily call `canActivate()` on this object for every request. It just can't give it the dependency the guard was written to use.\n\nThe fix isn't a different guard. It's a different *registration*, covered in [Stage 4](#stage-4-registering-a-global-guard-without-losing-di). But to see why that fix works, you need the actual mental model of what a guard is.\n\n## The mental model: a guard is a provider, not a function\n\n**The mental model:** a NestJS guard is an ordinary DI provider — the same kind of class as a service — that additionally implements one method, `canActivate(context: ExecutionContext)`, which Nest calls immediately before it would otherwise invoke your route handler. If `canActivate` resolves to `true`, the request keeps moving toward interceptors, pipes, and the handler. If it resolves to `false`, or throws, the handler never runs and Nest hands the request straight to the exception-filter layer.\n\nThree consequences fall out of that one sentence, and they're the three things the intro's bug got wrong:\n\n1. **A guard only gets real dependency injection if Nest constructs it.** `@UseGuards(RolesGuard)` (passing the *class*) lets Nest instantiate it through the container, resolving its constructor arguments normally. `new RolesGuard(...)` (passing an *instance* you built) does not — you're on your own for every dependency.\n2. **A guard doesn't see \"a request\" in the abstract — it sees an `ExecutionContext`.** That's a wrapper Nest builds fresh for every incoming call, giving the guard a uniform way to reach the underlying request *and* to ask \"what handler and class is Nest about to invoke?\" — which is exactly what a guard needs to look up route-specific metadata.\n3. **A guard's decision is binary, not additive.** It either lets a request through or it doesn't. Anything more nuanced than \"yes\u002Fno\" — attaching data, transforming the body — is an interceptor's or a pipe's job, not a guard's.\n\n## Stage 1: the smallest correct guard\n\nThe simplest guard that compiles and does something real:\n\n```typescript\nimport { CanActivate, ExecutionContext, Injectable } from \"@nestjs\u002Fcommon\";\n\n@Injectable()\nexport class AuthGuard implements CanActivate {\n  canActivate(context: ExecutionContext): boolean {\n    const request = context.switchToHttp().getRequest();\n    return Boolean(request.headers.authorization);\n  }\n}\n```\n\nApply it to one route:\n\n```typescript\n@UseGuards(AuthGuard)\n@Get(\"profile\")\ngetProfile(@Req() req: Request) {\n  return req.user;\n}\n```\n\n**Key concept:** `canActivate` can return `boolean`, `Promise\u003Cboolean>`, or `Observable\u003Cboolean>` — Nest awaits or subscribes to whichever you give it. A guard that calls a database or an external identity provider to check a session is completely normal; just make it `async canActivate(...): Promise\u003Cboolean>` and Nest will wait for it before deciding.\n\n## Stage 2: ExecutionContext, properly\n\n`ExecutionContext` is the single argument every guard, interceptor, and exception filter receives, and it answers two different questions:\n\n**\"What kind of call is this, and what's the underlying request object?\"** — via `switchToHttp()`, `switchToRpc()`, or `switchToWs()`. Most guards only ever call `context.switchToHttp().getRequest()`, but the same guard class *can* run in front of a WebSocket gateway or a microservice handler if you check `context.getType()` first and branch — that's what makes `ExecutionContext` a context, not just an HTTP request wrapper.\n\n**\"Which handler and which class is Nest about to call?\"** — via `context.getHandler()` (the specific route method, as a function reference) and `context.getClass()` (the controller class). This half is what makes metadata-driven guards possible, because it's the *only* way a guard can ask \"does this specific route carry a `@Roles(...)` decorator?\" — the guard runs once per registration, but `getHandler()`\u002F`getClass()` tell it which route it's currently deciding for.\n\n```typescript\ncanActivate(context: ExecutionContext): boolean {\n  const handlerName = context.getHandler().name;      \u002F\u002F e.g. \"getProfile\"\n  const controllerName = context.getClass().name;     \u002F\u002F e.g. \"UsersController\"\n  const request = context.switchToHttp().getRequest();\n  \u002F\u002F ...\n}\n```\n\n**Key concept:** `getHandler()` and `getClass()` return the raw function\u002Fclass references, not strings — they exist so you can hand them to `Reflector`, which looks up metadata *attached to those exact references*. That's the bridge to Stage 3.\n\n## Stage 3: Reflector and a real `@Roles()` decorator\n\nHardcoding a role check per route doesn't scale, and neither does branching on `handler.name` — a rename breaks it silently. The idiomatic pattern is a custom decorator that attaches metadata, and a `Reflector` that reads it back inside a guard.\n\n```typescript\n\u002F\u002F roles.decorator.ts\nimport { SetMetadata } from \"@nestjs\u002Fcommon\";\n\nexport const ROLES_KEY = \"roles\";\nexport const Roles = (...roles: string[]) => SetMetadata(ROLES_KEY, roles);\n```\n\n```typescript\n\u002F\u002F roles.guard.ts\nimport { CanActivate, ExecutionContext, Injectable } from \"@nestjs\u002Fcommon\";\nimport { Reflector } from \"@nestjs\u002Fcore\";\nimport { ROLES_KEY } from \".\u002Froles.decorator\";\n\n@Injectable()\nexport class RolesGuard implements CanActivate {\n  constructor(private reflector: Reflector) {}\n\n  canActivate(context: ExecutionContext): boolean {\n    const required = this.reflector.getAllAndOverride\u003Cstring[]>(ROLES_KEY, [\n      context.getHandler(),\n      context.getClass(),\n    ]);\n    if (!required || required.length === 0) return true; \u002F\u002F no @Roles() = open route\n\n    const { user } = context.switchToHttp().getRequest();\n    return required.some((role) => user?.roles?.includes(role));\n  }\n}\n```\n\n```typescript\n@Controller(\"orders\")\n@Roles(\"editor\") \u002F\u002F class-level default\nexport class OrdersController {\n  @Get()\n  list() { \u002F* requires \"editor\" — inherits the class default *\u002F }\n\n  @Delete(\":id\")\n  @Roles(\"admin\") \u002F\u002F method-level override\n  remove() { \u002F* requires \"admin\" — this wins over the class's \"editor\" *\u002F }\n}\n```\n\n**Key concept:** `getAllAndOverride(key, [handler, class])` checks the handler first, then the class, and returns the **first one it finds** — it does not merge arrays. That order in the array is why a method-level `@Roles(\"admin\")` completely replaces the class-level `@Roles(\"editor\")` rather than requiring both. If you actually want both handler and class metadata combined, `Reflector` also has `getAllAndMerge()`, which concatenates arrays instead of short-circuiting — reach for it explicitly when \"either level can add a role\" is the behavior you want.\n\n## Stage 4: registering a global guard without losing DI\n\nBack to the intro's bug. `app.useGlobalGuards(new RolesGuard(...))` builds the guard outside the container, so any constructor dependency has to be supplied by hand — which is exactly what went wrong. The fix is to register the guard as a provider, using the `APP_GUARD` injection token from `@nestjs\u002Fcore`:\n\n```typescript\nimport { APP_GUARD } from \"@nestjs\u002Fcore\";\n\n@Module({\n  providers: [\n    RolesGuard,\n    { provide: APP_GUARD, useClass: RolesGuard },\n  ],\n})\nexport class AppModule {}\n```\n\nBecause `RolesGuard` is now a normal provider, Nest resolves its constructor the usual way — `Reflector` (and, in the intro's case, a real `UserService`) get injected correctly, module-scoped providers work, and `Test.createTestingModule` can `overrideProvider(RolesGuard)` in tests the same way it overrides any other dependency, as covered in this series' [testing module episode](https:\u002F\u002Fdev.to\u002Fparsajiravand\u002Fnestjs-testing-module-provider-overrides-with-cheat-sheet-1o79). None of that is available to a guard built with `new` in `main.ts`.\n\n**Key concept:** `app.useGlobalGuards()` still exists and still works for a guard with zero dependencies — it's not deprecated. The rule is narrower and easy to remember: the moment a guard's constructor needs anything Nest would normally inject, register it through `APP_GUARD`, not `useGlobalGuards()`.\n\n## Stage 5: composing guards — order and \"all must pass\"\n\nA single request can pass through guards registered at three different scopes at once: global (`APP_GUARD`, or `useGlobalGuards()`), controller (`@UseGuards()` on the class), and method (`@UseGuards()` on the handler). Nest runs them in that exact order — global, then controller, then method — and within one `@UseGuards(A, B)` call, in the order listed.\n\nThis composition is a logical **AND**, not a fallback chain: every guard in the sequence must return (or resolve to) `true`, or the request is rejected at the first one that doesn't. There's no \"guard B can override guard A's denial\" — a single `false` anywhere in the chain ends the request immediately, and every guard after it, plus every interceptor and pipe, is skipped entirely.\n\n```typescript\n@UseGuards(ThrottleGuard, RolesGuard) \u002F\u002F ThrottleGuard runs first\n@Controller(\"orders\")\nexport class OrdersController {}\n```\n\nIf a global `AuthGuard` is also registered via `APP_GUARD`, the real order for any route on this controller is: `AuthGuard` → `ThrottleGuard` → `RolesGuard` → (method-level guards, if any) → interceptors → pipes → the handler.\n\n## Edge cases and gotchas\n\n- **A guard that throws vs. a guard that returns `false`.** Returning `false` produces a generic `403 Forbidden`. Throwing a specific exception — `throw new UnauthorizedException(\"Session expired\")` — gives the client (and your logs) a far more useful signal, and is the idiomatic choice for anything beyond \"just deny it.\"\n- **`Reflector` needs the exact same metadata key everywhere.** `SetMetadata(ROLES_KEY, ...)` and `reflector.getAllAndOverride(ROLES_KEY, ...)` must use the identical string (or, better, the same exported constant). A typo in one spot means the guard silently sees `undefined` and treats the route as unrestricted — this fails open, which is the worst direction for an auth check to fail.\n- **`getAllAndOverride` vs `getAllAndMerge`.** Covered in Stage 3, but worth repeating because it's the single most common `Reflector` mistake: reach for `getAllAndOverride` when a method should be able to fully replace a class default, and `getAllAndMerge` when both levels should contribute.\n- **WebSocket and microservice guards need a type check.** `context.switchToHttp()` throws if the current call isn't actually HTTP. A guard meant to run across transports should branch on `context.getType()` (`\"http\"`, `\"ws\"`, `\"rpc\"`) before picking which `switchTo*()` to call.\n- **A denied guard skips the \"before\" half of interceptors too.** Interceptors run after guards, so a rejected request never reaches even the setup code in an interceptor — only the exception-filter layer sees it.\n\n## Best practices\n\n- **Keep guards to yes\u002Fno authorization decisions.** If you find yourself mutating the request object inside a guard, that logic usually belongs in middleware (before routing) or an interceptor (after the handler is chosen) instead.\n- **Prefer metadata-driven guards over hardcoded checks.** A `@Roles()`\u002F`Reflector` pair scales to new routes with zero changes to the guard itself; an `if (handler.name === \"remove\")` branch doesn't.\n- **Register anything with a dependency via `APP_GUARD`, never `new Guard()`.** It's the difference between a guard that's testable and overridable, and one that silently can't be either.\n- **Fail closed, not open.** If a metadata lookup comes back `undefined` because of a wiring mistake, decide what that *should* mean deliberately (usually: deny), rather than letting `!required` accidentally mean \"allow everyone.\"\n- **One guard, one concern.** A `ThrottleGuard` and a `RolesGuard` composed via `@UseGuards(ThrottleGuard, RolesGuard)` are each easier to test and reuse than one guard doing both jobs.\n\n## FAQ\n\n### Do guards run before or after middleware?\n\nAfter. Middleware runs first and doesn't know which controller or handler will end up serving the request; guards run once routing has resolved to a specific handler, which is what lets a guard call `context.getHandler()`.\n\n### Can a guard inject a service?\n\nYes, as long as Nest constructs the guard — via `@UseGuards(SomeGuard)` (the class) or an `APP_GUARD` provider. A guard instance you build yourself with `new` gets none of Nest's dependency injection.\n\n### Can I use `@UseGuards()` more than once on the same controller?\n\nYes — `@UseGuards(A, B, C)` runs them in that order, and you can also stack a class-level `@UseGuards()` with a method-level one; both apply, in the global → controller → method order described in Stage 5.\n\n### What does a guard returning `false` actually send to the client?\n\nA `403 Forbidden` by default, handled by Nest's built-in exception layer. Throw a specific `HttpException` subclass from inside the guard if you need a different status code or a custom error body.\n\n### Is `Reflector` only for guards?\n\nNo — interceptors and custom decorators use it too, for the same reason: reading metadata attached to a handler or class via `SetMetadata`. Guards are just its most common consumer, because \"does this route require X\" is the canonical authorization question.\n\n## Cheat sheet\n\n```typescript\n\u002F\u002F A guard is a provider that implements CanActivate.\n@Injectable()\nexport class MyGuard implements CanActivate {\n  constructor(private reflector: Reflector) {} \u002F\u002F real DI, if registered correctly\n\n  canActivate(ctx: ExecutionContext): boolean | Promise\u003Cboolean> {\n    const req = ctx.switchToHttp().getRequest();       \u002F\u002F the underlying request\n    const handler = ctx.getHandler();                  \u002F\u002F the exact route method\n    const controller = ctx.getClass();                 \u002F\u002F the controller class\n    return true; \u002F\u002F or false, or throw a specific HttpException\n  }\n}\n\n\u002F\u002F Metadata decorator + read-back\nexport const ROLES_KEY = \"roles\";\nexport const Roles = (...roles: string[]) => SetMetadata(ROLES_KEY, roles);\n\u002F\u002F method metadata wins over class metadata:\nreflector.getAllAndOverride\u003Cstring[]>(ROLES_KEY, [ctx.getHandler(), ctx.getClass()]);\n\u002F\u002F both levels contribute instead:\nreflector.getAllAndMerge\u003Cstring[]>(ROLES_KEY, [ctx.getHandler(), ctx.getClass()]);\n\n\u002F\u002F Registration — pick based on whether the guard has dependencies\n@UseGuards(MyGuard)              \u002F\u002F per-route or per-controller, always through DI\napp.useGlobalGuards(new MyGuard()); \u002F\u002F global, but NO dependency injection\n{ provide: APP_GUARD, useClass: MyGuard } \u002F\u002F global, WITH dependency injection\n```\n\n| Scope | Registration | Runs when | Gets DI? |\n| --- | --- | --- | --- |\n| Method | `@UseGuards(G)` on a handler | Only that route | Yes |\n| Controller | `@UseGuards(G)` on a class | Every route in that controller | Yes |\n| Global (correct) | `APP_GUARD` provider | Every route in the app | Yes |\n| Global (limited) | `app.useGlobalGuards(new G())` | Every route in the app | No |\n\nExecution order for one request: **global → controller → method**, each one an AND — the first `false` (or thrown exception) stops the chain immediately.\n\n## Key takeaways\n\n- A guard is a DI provider with a `canActivate(context: ExecutionContext)` method — not a bare function, and not free of the container's rules.\n- `ExecutionContext` gives a guard the underlying request (via `switchToHttp()`\u002F`switchToWs()`\u002F`switchToRpc()`) and the exact handler\u002Fclass Nest is about to invoke (via `getHandler()`\u002F`getClass()`).\n- `Reflector.getAllAndOverride()` reads metadata attached with a custom decorator, checking the method before the class, and returns the first match — use `getAllAndMerge()` when you want both to contribute instead.\n- `app.useGlobalGuards(new G())` skips dependency injection entirely; use the `APP_GUARD` provider token for any global guard with constructor dependencies.\n- Guards compose as global → controller → method, and it's a strict AND: any single `false` or thrown exception stops the request before it reaches the next guard, any interceptor, or the handler.\n\n## Ending\n\nThe guard from the intro wasn't wrong about *what* it wanted to check — it was wrong about *how it was born*. `new RolesGuard(...)` and `{ provide: APP_GUARD, useClass: RolesGuard }` compile to the same class doing the same check, and only one of them lets Nest's container do its job. That's the whole lesson of guards: they look like plain functions with a `canActivate` name, but every guarantee they can offer — real dependencies, testability, metadata lookups through `ExecutionContext` — depends on Nest actually building them. Next time a \"protected\" route turns out not to be, check the registration line before you touch the guard's logic.\n\nWhat's the strangest guard bug you've chased down — a missing dependency, a metadata key typo, or something else? Drop it in the comments.\n\n\u003C!-- playground:start -->\n\n## 🎮 Try it yourself\n\n**[▶️ Open the interactive playground →](https:\u002F\u002Fbestpractic.org\u002Fblog\u002Fnestjs-weekly-guards-canactivate-reflector\u002Fplayground)**\n\n_Runs right in your browser — poke at it and watch the concept react live._\n\n\u003C!-- playground:end -->\n\n\u003C!-- quiz:start -->\n\n## 🧠 Test yourself\n\nThink it clicked? **[Take the 7-question quiz →](https:\u002F\u002Fbestpractic.org\u002Fblog\u002Fnestjs-weekly-guards-canactivate-reflector\u002Fquiz)**\n\n_Instant feedback, a hint on every question, and an explanation for each answer — right or wrong._\n\n\u003C!-- quiz:end -->\n\n---\n\n🚀 **Want more like this?** Every guide, playground, and quiz lives on **[bestpractic.org](https:\u002F\u002Fbestpractic.org\u002F)** — open it and **[sign up free](https:\u002F\u002Fbestpractic.org\u002F)** so the next one finds you.\n\n*Thanks for reading! Let's stay connected:*\n\n- ⭐ **GitHub** — follow me and star the projects: [github.com\u002Fparsajiravand](https:\u002F\u002Fgithub.com\u002Fparsajiravand)\n- 💬 **Discord** — join the frontend best-practices community: [discord.gg\u002Fd9KRhuAwQ](https:\u002F\u002Fdiscord.gg\u002Fd9KRhuAwQ)\n- 📸 **Instagram** — frontend best practices, daily: [@bestpractice___](https:\u002F\u002Fwww.instagram.com\u002Fbestpractice___\u002F)",{"title":95,"canonical":468,"description":97},"https:\u002F\u002Fbestpractic.org\u002Fblog\u002Fnestjs-weekly-guards-canactivate-reflector","01a0ddae-48ad-75a7-9839-4b6d112301dd",{"name":471,"part":472,"total":472,"items":473},"NestJS Deep Dive",5,[474,478,482,486,490],{"slug":475,"title":476,"publishedAt":477,"readingMinutes":76},"nestjs-weekly-request-lifecycle","NestJS Request Lifecycle Explained (with Cheat Sheet)","2026-08-28T17:01:41.941Z",{"slug":479,"title":480,"publishedAt":481,"readingMinutes":72},"nestjs-weekly-dependency-injection-providers-scopes","NestJS Dependency Injection Explained (with Cheat Sheet)","2026-09-13T08:40:18.434Z",{"slug":483,"title":484,"publishedAt":485,"readingMinutes":72},"nestjs-weekly-module-encapsulation-exports","NestJS Module Encapsulation Explained (with Cheat Sheet)","2026-09-13T08:40:50.070Z",{"slug":487,"title":488,"publishedAt":489,"readingMinutes":76},"nestjs-weekly-testing-provider-overrides","NestJS Testing Module: Provider Overrides (with Cheat Sheet)","2026-09-18T17:23:03.842Z",{"slug":94,"title":95,"publishedAt":99,"readingMinutes":72},{"id":492,"locked":18},"01a0ddae-48e5-719c-b789-ed0a33c4bf65",[494],{"id":495,"slug":94,"title":95,"_count":496},"01a0ddae-48fd-75e3-89c9-d4789d07f556",{"questions":91},[498],{"locale":13,"slug":94},{"id":495,"slug":94,"title":95,"_count":500,"questionCount":91},{"questions":91},{"items":502,"meta":575},[503,515,530,545,560],{"id":93,"slug":94,"title":95,"subtitle":96,"excerpt":97,"coverUrl":98,"locale":13,"readingMinutes":72,"publishedAt":99,"viewCount":504,"likeCount":19,"commentCount":19,"author":505,"vertical":506,"topic":507,"tags":508,"_count":513,"playground":514,"hasQuiz":17,"hasPlayground":17},47,{"id":102,"name":103,"username":104,"avatarUrl":96,"headline":105},{"slug":6,"name":7,"accentFrom":10,"accentTo":11},{"slug":108,"name":109},[509,510,511,512],{"slug":108,"name":109,"color":96},{"slug":82,"name":83,"color":96},{"slug":66,"name":67,"color":96},{"slug":58,"name":59,"color":96},{"assessments":116},{"slug":94},{"id":516,"slug":487,"title":488,"subtitle":96,"excerpt":517,"coverUrl":518,"locale":13,"readingMinutes":76,"publishedAt":489,"viewCount":519,"likeCount":19,"commentCount":19,"author":520,"vertical":521,"topic":522,"tags":523,"_count":528,"playground":529,"hasQuiz":17,"hasPlayground":17},"01a0a630-c856-72d3-bae5-3339e38a8564","A complete guide to NestJS's testing module: how overrideProvider really wires mocks, why get() fails on scoped providers, and using useMocker.","\u002Fmedia\u002Fcovers\u002Fnestjs-weekly-testing-provider-overrides.png",275,{"id":102,"name":103,"username":104,"avatarUrl":96,"headline":105},{"slug":6,"name":7,"accentFrom":10,"accentTo":11},{"slug":108,"name":109},[524,525,526,527],{"slug":108,"name":109,"color":96},{"slug":82,"name":83,"color":96},{"slug":66,"name":67,"color":96},{"slug":58,"name":59,"color":96},{"assessments":116},{"slug":487},{"id":531,"slug":483,"title":484,"subtitle":96,"excerpt":532,"coverUrl":533,"locale":13,"readingMinutes":72,"publishedAt":485,"viewCount":534,"likeCount":19,"commentCount":19,"author":535,"vertical":536,"topic":537,"tags":538,"_count":543,"playground":544,"hasQuiz":17,"hasPlayground":17},"01a0821b-4733-762d-bf96-b68c7eb140c0","How NestJS module boundaries actually work: what exports really cross, why @Global() isn't a shortcut, and how forwardRef breaks circular module dependencies.","\u002Fmedia\u002Fcovers\u002Fnestjs-weekly-module-encapsulation-exports.png",262,{"id":102,"name":103,"username":104,"avatarUrl":96,"headline":105},{"slug":6,"name":7,"accentFrom":10,"accentTo":11},{"slug":108,"name":109},[539,540,541,542],{"slug":108,"name":109,"color":96},{"slug":82,"name":83,"color":96},{"slug":66,"name":67,"color":96},{"slug":58,"name":59,"color":96},{"assessments":116},{"slug":483},{"id":546,"slug":479,"title":480,"subtitle":96,"excerpt":547,"coverUrl":548,"locale":13,"readingMinutes":72,"publishedAt":481,"viewCount":549,"likeCount":19,"commentCount":19,"author":550,"vertical":551,"topic":552,"tags":553,"_count":558,"playground":559,"hasQuiz":17,"hasPlayground":17},"01a05e06-53b7-7415-9cd3-05504882514b","How the NestJS DI container resolves providers: tokens, module scope, singleton vs request vs transient, and why 'singleton' can still mean two instances.","\u002Fmedia\u002Fcovers\u002Fnestjs-weekly-dependency-injection-providers-scopes.png",258,{"id":102,"name":103,"username":104,"avatarUrl":96,"headline":105},{"slug":6,"name":7,"accentFrom":10,"accentTo":11},{"slug":108,"name":109},[554,555,556,557],{"slug":108,"name":109,"color":96},{"slug":82,"name":83,"color":96},{"slug":66,"name":67,"color":96},{"slug":58,"name":59,"color":96},{"assessments":116},{"slug":479},{"id":561,"slug":475,"title":476,"subtitle":96,"excerpt":562,"coverUrl":563,"locale":13,"readingMinutes":76,"publishedAt":477,"viewCount":564,"likeCount":19,"commentCount":19,"author":565,"vertical":566,"topic":567,"tags":568,"_count":573,"playground":574,"hasQuiz":17,"hasPlayground":17},"01a03cdb-22ef-748a-b555-8071c7a905e6","A complete guide to the NestJS request lifecycle: the exact order middleware, guards, interceptors, pipes, and filters run, and why it matters.","\u002Fmedia\u002Fcovers\u002Fnestjs-weekly-request-lifecycle.png",449,{"id":102,"name":103,"username":104,"avatarUrl":96,"headline":105},{"slug":6,"name":7,"accentFrom":10,"accentTo":11},{"slug":108,"name":109},[569,570,571,572],{"slug":108,"name":109,"color":96},{"slug":82,"name":83,"color":96},{"slug":66,"name":67,"color":96},{"slug":58,"name":59,"color":96},{"assessments":116},{"slug":475},{"page":116,"perPage":91,"total":472,"totalPages":116},"\u003Cdiv class=\"shj shj-lang-ts shj-multiline\" data-lang=\"ts\">\u003Cdiv class=\"shj-scroll\">\u003Cdiv class=\"shj-numbers\">\u003Cdiv>1\u003C\u002Fdiv>\u003Cdiv>2\u003C\u002Fdiv>\u003Cdiv>3\u003C\u002Fdiv>\u003Cdiv>4\u003C\u002Fdiv>\u003Cdiv>5\u003C\u002Fdiv>\u003Cdiv>6\u003C\u002Fdiv>\u003Cdiv>7\u003C\u002Fdiv>\u003Cdiv>8\u003C\u002Fdiv>\u003Cdiv>9\u003C\u002Fdiv>\u003Cdiv>10\u003C\u002Fdiv>\u003Cdiv>11\u003C\u002Fdiv>\u003Cdiv>12\u003C\u002Fdiv>\u003Cdiv>13\u003C\u002Fdiv>\u003Cdiv>14\u003C\u002Fdiv>\u003Cdiv>15\u003C\u002Fdiv>\u003C\u002Fdiv>\u003Cdiv class=\"shj-code\">@\u003Cspan class=\"shj-class\">Injectable\u003C\u002Fspan>\u003Cspan class=\"shj-bracket\">(\u003C\u002Fspan>\u003Cspan class=\"shj-bracket\">)\u003C\u002Fspan>\n\u003Cspan class=\"shj-kwd\">export\u003C\u002Fspan> \u003Cspan class=\"shj-kwd\">class\u003C\u002Fspan> \u003Cspan class=\"shj-class\">RolesGuard\u003C\u002Fspan> \u003Cspan class=\"shj-kwd\">implements\u003C\u002Fspan> \u003Cspan class=\"shj-class\">CanActivate\u003C\u002Fspan> \u003Cspan class=\"shj-bracket\">{\u003C\u002Fspan>\n  \u003Cspan class=\"shj-kwd\">constructor\u003C\u002Fspan>\u003Cspan class=\"shj-bracket\">(\u003C\u002Fspan>\n    \u003Cspan class=\"shj-kwd\">private\u003C\u002Fspan> reflector\u003Cspan class=\"shj-oper\">:\u003C\u002Fspan> \u003Cspan class=\"shj-class\">Reflector\u003C\u002Fspan>\u003Cspan class=\"shj-oper\">,\u003C\u002Fspan>\n    \u003Cspan class=\"shj-kwd\">private\u003C\u002Fspan> userService\u003Cspan class=\"shj-oper\">:\u003C\u002Fspan> \u003Cspan class=\"shj-class\">UserService\u003C\u002Fspan>\u003Cspan class=\"shj-oper\">,\u003C\u002Fspan> \u003Cspan class=\"shj-cmnt\">\u002F\u002F meant to check role hierarchy\n\u003C\u002Fspan>  \u003Cspan class=\"shj-bracket\">)\u003C\u002Fspan> \u003Cspan class=\"shj-bracket\">{\u003C\u002Fspan>\u003Cspan class=\"shj-bracket\">}\u003C\u002Fspan>\n\n  \u003Cspan class=\"shj-func\">canActivate\u003C\u002Fspan>\u003Cspan class=\"shj-bracket\">(\u003C\u002Fspan>context\u003Cspan class=\"shj-oper\">:\u003C\u002Fspan> \u003Cspan class=\"shj-class\">ExecutionContext\u003C\u002Fspan>\u003Cspan class=\"shj-bracket\">)\u003C\u002Fspan>\u003Cspan class=\"shj-type\">: boolean\u003C\u002Fspan> \u003Cspan class=\"shj-bracket\">{\u003C\u002Fspan>\n    \u003Cspan class=\"shj-kwd\">const\u003C\u002Fspan> required \u003Cspan class=\"shj-oper\">=\u003C\u002Fspan> \u003Cspan class=\"shj-kwd\">this\u003C\u002Fspan>\u003Cspan class=\"shj-oper\">.\u003C\u002Fspan>reflector\u003Cspan class=\"shj-oper\">.\u003C\u002Fspan>\u003Cspan class=\"shj-kwd\">get\u003C\u002Fspan>\u003Cspan class=\"shj-oper\">&lt;\u003C\u002Fspan>string\u003Cspan class=\"shj-bracket\">[\u003C\u002Fspan>\u003Cspan class=\"shj-bracket\">]\u003C\u002Fspan>\u003Cspan class=\"shj-oper\">&gt;\u003C\u002Fspan>\u003Cspan class=\"shj-bracket\">(\u003C\u002Fspan>\u003Cspan class=\"shj-str\">\"roles\"\u003C\u002Fspan>\u003Cspan class=\"shj-oper\">,\u003C\u002Fspan> context\u003Cspan class=\"shj-oper\">.\u003C\u002Fspan>\u003Cspan class=\"shj-func\">getHandler\u003C\u002Fspan>\u003Cspan class=\"shj-bracket\">(\u003C\u002Fspan>\u003Cspan class=\"shj-bracket\">)\u003C\u002Fspan>\u003Cspan class=\"shj-bracket\">)\u003C\u002Fspan>;\n    \u003Cspan class=\"shj-kwd\">if\u003C\u002Fspan> \u003Cspan class=\"shj-bracket\">(\u003C\u002Fspan>\u003Cspan class=\"shj-oper\">!\u003C\u002Fspan>required\u003Cspan class=\"shj-bracket\">)\u003C\u002Fspan> \u003Cspan class=\"shj-kwd\">return\u003C\u002Fspan> \u003Cspan class=\"shj-bool\">true\u003C\u002Fspan>;\n    \u003Cspan class=\"shj-kwd\">const\u003C\u002Fspan> \u003Cspan class=\"shj-bracket\">{\u003C\u002Fspan> user \u003Cspan class=\"shj-bracket\">}\u003C\u002Fspan> \u003Cspan class=\"shj-oper\">=\u003C\u002Fspan> context\u003Cspan class=\"shj-oper\">.\u003C\u002Fspan>\u003Cspan class=\"shj-func\">switchToHttp\u003C\u002Fspan>\u003Cspan class=\"shj-bracket\">(\u003C\u002Fspan>\u003Cspan class=\"shj-bracket\">)\u003C\u002Fspan>\u003Cspan class=\"shj-oper\">.\u003C\u002Fspan>\u003Cspan class=\"shj-func\">getRequest\u003C\u002Fspan>\u003Cspan class=\"shj-bracket\">(\u003C\u002Fspan>\u003Cspan class=\"shj-bracket\">)\u003C\u002Fspan>;\n    \u003Cspan class=\"shj-cmnt\">\u002F\u002F userService is undefined here — this branch always throws or always no-ops\n\u003C\u002Fspan>    \u003Cspan class=\"shj-kwd\">return\u003C\u002Fspan> \u003Cspan class=\"shj-kwd\">this\u003C\u002Fspan>\u003Cspan class=\"shj-oper\">.\u003C\u002Fspan>userService\u003Cspan class=\"shj-oper\">.\u003C\u002Fspan>\u003Cspan class=\"shj-func\">hasAnyRole\u003C\u002Fspan>\u003Cspan class=\"shj-bracket\">(\u003C\u002Fspan>user\u003Cspan class=\"shj-oper\">,\u003C\u002Fspan> required\u003Cspan class=\"shj-bracket\">)\u003C\u002Fspan>;\n  \u003Cspan class=\"shj-bracket\">}\u003C\u002Fspan>\n\u003Cspan class=\"shj-bracket\">}\u003C\u002Fspan>\u003C\u002Fdiv>\u003C\u002Fdiv>\u003C\u002Fdiv>","\u003Cdiv class=\"shj shj-lang-ts shj-multiline\" data-lang=\"ts\">\u003Cdiv class=\"shj-scroll\">\u003Cdiv class=\"shj-numbers\">\u003Cdiv>1\u003C\u002Fdiv>\u003Cdiv>2\u003C\u002Fdiv>\u003Cdiv>3\u003C\u002Fdiv>\u003C\u002Fdiv>\u003Cdiv class=\"shj-code\">\u003Cspan class=\"shj-cmnt\">\u002F\u002F main.ts — looks reasonable, is quietly broken\n\u003C\u002Fspan>\u003Cspan class=\"shj-kwd\">const\u003C\u002Fspan> app \u003Cspan class=\"shj-oper\">=\u003C\u002Fspan> \u003Cspan class=\"shj-kwd\">await\u003C\u002Fspan> \u003Cspan class=\"shj-class\">NestFactory\u003C\u002Fspan>\u003Cspan class=\"shj-oper\">.\u003C\u002Fspan>\u003Cspan class=\"shj-func\">create\u003C\u002Fspan>\u003Cspan class=\"shj-bracket\">(\u003C\u002Fspan>\u003Cspan class=\"shj-class\">AppModule\u003C\u002Fspan>\u003Cspan class=\"shj-bracket\">)\u003C\u002Fspan>;\napp\u003Cspan class=\"shj-oper\">.\u003C\u002Fspan>\u003Cspan class=\"shj-func\">useGlobalGuards\u003C\u002Fspan>\u003Cspan class=\"shj-bracket\">(\u003C\u002Fspan>\u003Cspan class=\"shj-kwd\">new\u003C\u002Fspan> \u003Cspan class=\"shj-class\">RolesGuard\u003C\u002Fspan>\u003Cspan class=\"shj-bracket\">(\u003C\u002Fspan>\u003Cspan class=\"shj-kwd\">new\u003C\u002Fspan> \u003Cspan class=\"shj-class\">Reflector\u003C\u002Fspan>\u003Cspan class=\"shj-bracket\">(\u003C\u002Fspan>\u003Cspan class=\"shj-bracket\">)\u003C\u002Fspan>\u003Cspan class=\"shj-oper\">,\u003C\u002Fspan> \u003Cspan class=\"shj-cmnt\">\u002F* userService? *\u002F\u003C\u002Fspan> \u003Cspan class=\"shj-num\">undefined\u003C\u002Fspan>\u003Cspan class=\"shj-bracket\">)\u003C\u002Fspan>\u003Cspan class=\"shj-bracket\">)\u003C\u002Fspan>;\u003C\u002Fdiv>\u003C\u002Fdiv>\u003C\u002Fdiv>","\u003Cdiv class=\"shj shj-lang-ts shj-multiline\" data-lang=\"ts\">\u003Cdiv class=\"shj-scroll\">\u003Cdiv class=\"shj-numbers\">\u003Cdiv>1\u003C\u002Fdiv>\u003Cdiv>2\u003C\u002Fdiv>\u003Cdiv>3\u003C\u002Fdiv>\u003Cdiv>4\u003C\u002Fdiv>\u003Cdiv>5\u003C\u002Fdiv>\u003Cdiv>6\u003C\u002Fdiv>\u003Cdiv>7\u003C\u002Fdiv>\u003Cdiv>8\u003C\u002Fdiv>\u003Cdiv>9\u003C\u002Fdiv>\u003C\u002Fdiv>\u003Cdiv class=\"shj-code\">\u003Cspan class=\"shj-kwd\">import\u003C\u002Fspan> \u003Cspan class=\"shj-bracket\">{\u003C\u002Fspan> \u003Cspan class=\"shj-class\">CanActivate\u003C\u002Fspan>\u003Cspan class=\"shj-oper\">,\u003C\u002Fspan> \u003Cspan class=\"shj-class\">ExecutionContext\u003C\u002Fspan>\u003Cspan class=\"shj-oper\">,\u003C\u002Fspan> \u003Cspan class=\"shj-class\">Injectable\u003C\u002Fspan> \u003Cspan class=\"shj-bracket\">}\u003C\u002Fspan> \u003Cspan class=\"shj-kwd\">from\u003C\u002Fspan> \u003Cspan class=\"shj-str\">\"@nestjs\u002Fcommon\"\u003C\u002Fspan>;\n\n@\u003Cspan class=\"shj-class\">Injectable\u003C\u002Fspan>\u003Cspan class=\"shj-bracket\">(\u003C\u002Fspan>\u003Cspan class=\"shj-bracket\">)\u003C\u002Fspan>\n\u003Cspan class=\"shj-kwd\">export\u003C\u002Fspan> \u003Cspan class=\"shj-kwd\">class\u003C\u002Fspan> \u003Cspan class=\"shj-class\">AuthGuard\u003C\u002Fspan> \u003Cspan class=\"shj-kwd\">implements\u003C\u002Fspan> \u003Cspan class=\"shj-class\">CanActivate\u003C\u002Fspan> \u003Cspan class=\"shj-bracket\">{\u003C\u002Fspan>\n  \u003Cspan class=\"shj-func\">canActivate\u003C\u002Fspan>\u003Cspan class=\"shj-bracket\">(\u003C\u002Fspan>context\u003Cspan class=\"shj-oper\">:\u003C\u002Fspan> \u003Cspan class=\"shj-class\">ExecutionContext\u003C\u002Fspan>\u003Cspan class=\"shj-bracket\">)\u003C\u002Fspan>\u003Cspan class=\"shj-type\">: boolean\u003C\u002Fspan> \u003Cspan class=\"shj-bracket\">{\u003C\u002Fspan>\n    \u003Cspan class=\"shj-kwd\">const\u003C\u002Fspan> request \u003Cspan class=\"shj-oper\">=\u003C\u002Fspan> context\u003Cspan class=\"shj-oper\">.\u003C\u002Fspan>\u003Cspan class=\"shj-func\">switchToHttp\u003C\u002Fspan>\u003Cspan class=\"shj-bracket\">(\u003C\u002Fspan>\u003Cspan class=\"shj-bracket\">)\u003C\u002Fspan>\u003Cspan class=\"shj-oper\">.\u003C\u002Fspan>\u003Cspan class=\"shj-func\">getRequest\u003C\u002Fspan>\u003Cspan class=\"shj-bracket\">(\u003C\u002Fspan>\u003Cspan class=\"shj-bracket\">)\u003C\u002Fspan>;\n    \u003Cspan class=\"shj-kwd\">return\u003C\u002Fspan> \u003Cspan class=\"shj-class\">Boolean\u003C\u002Fspan>\u003Cspan class=\"shj-bracket\">(\u003C\u002Fspan>request\u003Cspan class=\"shj-oper\">.\u003C\u002Fspan>headers\u003Cspan class=\"shj-oper\">.\u003C\u002Fspan>authorization\u003Cspan class=\"shj-bracket\">)\u003C\u002Fspan>;\n  \u003Cspan class=\"shj-bracket\">}\u003C\u002Fspan>\n\u003Cspan class=\"shj-bracket\">}\u003C\u002Fspan>\u003C\u002Fdiv>\u003C\u002Fdiv>\u003C\u002Fdiv>","\u003Cdiv class=\"shj shj-lang-ts shj-multiline\" data-lang=\"ts\">\u003Cdiv class=\"shj-scroll\">\u003Cdiv class=\"shj-numbers\">\u003Cdiv>1\u003C\u002Fdiv>\u003Cdiv>2\u003C\u002Fdiv>\u003Cdiv>3\u003C\u002Fdiv>\u003Cdiv>4\u003C\u002Fdiv>\u003Cdiv>5\u003C\u002Fdiv>\u003C\u002Fdiv>\u003Cdiv class=\"shj-code\">@\u003Cspan class=\"shj-class\">UseGuards\u003C\u002Fspan>\u003Cspan class=\"shj-bracket\">(\u003C\u002Fspan>\u003Cspan class=\"shj-class\">AuthGuard\u003C\u002Fspan>\u003Cspan class=\"shj-bracket\">)\u003C\u002Fspan>\n@\u003Cspan class=\"shj-class\">Get\u003C\u002Fspan>\u003Cspan class=\"shj-bracket\">(\u003C\u002Fspan>\u003Cspan class=\"shj-str\">\"profile\"\u003C\u002Fspan>\u003Cspan class=\"shj-bracket\">)\u003C\u002Fspan>\n\u003Cspan class=\"shj-func\">getProfile\u003C\u002Fspan>\u003Cspan class=\"shj-bracket\">(\u003C\u002Fspan>@\u003Cspan class=\"shj-class\">Req\u003C\u002Fspan>\u003Cspan class=\"shj-bracket\">(\u003C\u002Fspan>\u003Cspan class=\"shj-bracket\">)\u003C\u002Fspan> req\u003Cspan class=\"shj-oper\">:\u003C\u002Fspan> \u003Cspan class=\"shj-class\">Request\u003C\u002Fspan>\u003Cspan class=\"shj-bracket\">)\u003C\u002Fspan> \u003Cspan class=\"shj-bracket\">{\u003C\u002Fspan>\n  \u003Cspan class=\"shj-kwd\">return\u003C\u002Fspan> req\u003Cspan class=\"shj-oper\">.\u003C\u002Fspan>user;\n\u003Cspan class=\"shj-bracket\">}\u003C\u002Fspan>\u003C\u002Fdiv>\u003C\u002Fdiv>\u003C\u002Fdiv>","\u003Cdiv class=\"shj shj-lang-ts shj-multiline\" data-lang=\"ts\">\u003Cdiv class=\"shj-scroll\">\u003Cdiv class=\"shj-numbers\">\u003Cdiv>1\u003C\u002Fdiv>\u003Cdiv>2\u003C\u002Fdiv>\u003Cdiv>3\u003C\u002Fdiv>\u003Cdiv>4\u003C\u002Fdiv>\u003Cdiv>5\u003C\u002Fdiv>\u003Cdiv>6\u003C\u002Fdiv>\u003C\u002Fdiv>\u003Cdiv class=\"shj-code\">\u003Cspan class=\"shj-func\">canActivate\u003C\u002Fspan>\u003Cspan class=\"shj-bracket\">(\u003C\u002Fspan>context\u003Cspan class=\"shj-oper\">:\u003C\u002Fspan> \u003Cspan class=\"shj-class\">ExecutionContext\u003C\u002Fspan>\u003Cspan class=\"shj-bracket\">)\u003C\u002Fspan>\u003Cspan class=\"shj-type\">: boolean\u003C\u002Fspan> \u003Cspan class=\"shj-bracket\">{\u003C\u002Fspan>\n  \u003Cspan class=\"shj-kwd\">const\u003C\u002Fspan> handlerName \u003Cspan class=\"shj-oper\">=\u003C\u002Fspan> context\u003Cspan class=\"shj-oper\">.\u003C\u002Fspan>\u003Cspan class=\"shj-func\">getHandler\u003C\u002Fspan>\u003Cspan class=\"shj-bracket\">(\u003C\u002Fspan>\u003Cspan class=\"shj-bracket\">)\u003C\u002Fspan>\u003Cspan class=\"shj-oper\">.\u003C\u002Fspan>name;      \u003Cspan class=\"shj-cmnt\">\u002F\u002F e.g. \"getProfile\"\n\u003C\u002Fspan>  \u003Cspan class=\"shj-kwd\">const\u003C\u002Fspan> controllerName \u003Cspan class=\"shj-oper\">=\u003C\u002Fspan> context\u003Cspan class=\"shj-oper\">.\u003C\u002Fspan>\u003Cspan class=\"shj-func\">getClass\u003C\u002Fspan>\u003Cspan class=\"shj-bracket\">(\u003C\u002Fspan>\u003Cspan class=\"shj-bracket\">)\u003C\u002Fspan>\u003Cspan class=\"shj-oper\">.\u003C\u002Fspan>name;     \u003Cspan class=\"shj-cmnt\">\u002F\u002F e.g. \"UsersController\"\n\u003C\u002Fspan>  \u003Cspan class=\"shj-kwd\">const\u003C\u002Fspan> request \u003Cspan class=\"shj-oper\">=\u003C\u002Fspan> context\u003Cspan class=\"shj-oper\">.\u003C\u002Fspan>\u003Cspan class=\"shj-func\">switchToHttp\u003C\u002Fspan>\u003Cspan class=\"shj-bracket\">(\u003C\u002Fspan>\u003Cspan class=\"shj-bracket\">)\u003C\u002Fspan>\u003Cspan class=\"shj-oper\">.\u003C\u002Fspan>\u003Cspan class=\"shj-func\">getRequest\u003C\u002Fspan>\u003Cspan class=\"shj-bracket\">(\u003C\u002Fspan>\u003Cspan class=\"shj-bracket\">)\u003C\u002Fspan>;\n  \u003Cspan class=\"shj-cmnt\">\u002F\u002F ...\n\u003C\u002Fspan>\u003Cspan class=\"shj-bracket\">}\u003C\u002Fspan>\u003C\u002Fdiv>\u003C\u002Fdiv>\u003C\u002Fdiv>","\u003Cdiv class=\"shj shj-lang-ts shj-multiline\" data-lang=\"ts\">\u003Cdiv class=\"shj-scroll\">\u003Cdiv class=\"shj-numbers\">\u003Cdiv>1\u003C\u002Fdiv>\u003Cdiv>2\u003C\u002Fdiv>\u003Cdiv>3\u003C\u002Fdiv>\u003Cdiv>4\u003C\u002Fdiv>\u003Cdiv>5\u003C\u002Fdiv>\u003C\u002Fdiv>\u003Cdiv class=\"shj-code\">\u003Cspan class=\"shj-cmnt\">\u002F\u002F roles.decorator.ts\n\u003C\u002Fspan>\u003Cspan class=\"shj-kwd\">import\u003C\u002Fspan> \u003Cspan class=\"shj-bracket\">{\u003C\u002Fspan> \u003Cspan class=\"shj-class\">SetMetadata\u003C\u002Fspan> \u003Cspan class=\"shj-bracket\">}\u003C\u002Fspan> \u003Cspan class=\"shj-kwd\">from\u003C\u002Fspan> \u003Cspan class=\"shj-str\">\"@nestjs\u002Fcommon\"\u003C\u002Fspan>;\n\n\u003Cspan class=\"shj-kwd\">export\u003C\u002Fspan> \u003Cspan class=\"shj-kwd\">const\u003C\u002Fspan> \u003Cspan class=\"shj-num\">ROLES_KEY\u003C\u002Fspan> \u003Cspan class=\"shj-oper\">=\u003C\u002Fspan> \u003Cspan class=\"shj-str\">\"roles\"\u003C\u002Fspan>;\n\u003Cspan class=\"shj-kwd\">export\u003C\u002Fspan> \u003Cspan class=\"shj-kwd\">const\u003C\u002Fspan> \u003Cspan class=\"shj-class\">Roles\u003C\u002Fspan> \u003Cspan class=\"shj-oper\">=\u003C\u002Fspan> \u003Cspan class=\"shj-bracket\">(\u003C\u002Fspan>\u003Cspan class=\"shj-oper\">...\u003C\u002Fspan>roles\u003Cspan class=\"shj-type\">: string\u003C\u002Fspan>\u003Cspan class=\"shj-bracket\">[\u003C\u002Fspan>\u003Cspan class=\"shj-bracket\">]\u003C\u002Fspan>\u003Cspan class=\"shj-bracket\">)\u003C\u002Fspan> \u003Cspan class=\"shj-kwd\">=&gt;\u003C\u002Fspan> \u003Cspan class=\"shj-class\">SetMetadata\u003C\u002Fspan>\u003Cspan class=\"shj-bracket\">(\u003C\u002Fspan>\u003Cspan class=\"shj-num\">ROLES_KEY\u003C\u002Fspan>\u003Cspan class=\"shj-oper\">,\u003C\u002Fspan> roles\u003Cspan class=\"shj-bracket\">)\u003C\u002Fspan>;\u003C\u002Fdiv>\u003C\u002Fdiv>\u003C\u002Fdiv>","\u003Cdiv class=\"shj shj-lang-ts shj-multiline\" data-lang=\"ts\">\u003Cdiv class=\"shj-scroll\">\u003Cdiv class=\"shj-numbers\">\u003Cdiv>1\u003C\u002Fdiv>\u003Cdiv>2\u003C\u002Fdiv>\u003Cdiv>3\u003C\u002Fdiv>\u003Cdiv>4\u003C\u002Fdiv>\u003Cdiv>5\u003C\u002Fdiv>\u003Cdiv>6\u003C\u002Fdiv>\u003Cdiv>7\u003C\u002Fdiv>\u003Cdiv>8\u003C\u002Fdiv>\u003Cdiv>9\u003C\u002Fdiv>\u003Cdiv>10\u003C\u002Fdiv>\u003Cdiv>11\u003C\u002Fdiv>\u003Cdiv>12\u003C\u002Fdiv>\u003Cdiv>13\u003C\u002Fdiv>\u003Cdiv>14\u003C\u002Fdiv>\u003Cdiv>15\u003C\u002Fdiv>\u003Cdiv>16\u003C\u002Fdiv>\u003Cdiv>17\u003C\u002Fdiv>\u003Cdiv>18\u003C\u002Fdiv>\u003Cdiv>19\u003C\u002Fdiv>\u003Cdiv>20\u003C\u002Fdiv>\u003C\u002Fdiv>\u003Cdiv class=\"shj-code\">\u003Cspan class=\"shj-cmnt\">\u002F\u002F roles.guard.ts\n\u003C\u002Fspan>\u003Cspan class=\"shj-kwd\">import\u003C\u002Fspan> \u003Cspan class=\"shj-bracket\">{\u003C\u002Fspan> \u003Cspan class=\"shj-class\">CanActivate\u003C\u002Fspan>\u003Cspan class=\"shj-oper\">,\u003C\u002Fspan> \u003Cspan class=\"shj-class\">ExecutionContext\u003C\u002Fspan>\u003Cspan class=\"shj-oper\">,\u003C\u002Fspan> \u003Cspan class=\"shj-class\">Injectable\u003C\u002Fspan> \u003Cspan class=\"shj-bracket\">}\u003C\u002Fspan> \u003Cspan class=\"shj-kwd\">from\u003C\u002Fspan> \u003Cspan class=\"shj-str\">\"@nestjs\u002Fcommon\"\u003C\u002Fspan>;\n\u003Cspan class=\"shj-kwd\">import\u003C\u002Fspan> \u003Cspan class=\"shj-bracket\">{\u003C\u002Fspan> \u003Cspan class=\"shj-class\">Reflector\u003C\u002Fspan> \u003Cspan class=\"shj-bracket\">}\u003C\u002Fspan> \u003Cspan class=\"shj-kwd\">from\u003C\u002Fspan> \u003Cspan class=\"shj-str\">\"@nestjs\u002Fcore\"\u003C\u002Fspan>;\n\u003Cspan class=\"shj-kwd\">import\u003C\u002Fspan> \u003Cspan class=\"shj-bracket\">{\u003C\u002Fspan> \u003Cspan class=\"shj-num\">ROLES_KEY\u003C\u002Fspan> \u003Cspan class=\"shj-bracket\">}\u003C\u002Fspan> \u003Cspan class=\"shj-kwd\">from\u003C\u002Fspan> \u003Cspan class=\"shj-str\">\".\u002Froles.decorator\"\u003C\u002Fspan>;\n\n@\u003Cspan class=\"shj-class\">Injectable\u003C\u002Fspan>\u003Cspan class=\"shj-bracket\">(\u003C\u002Fspan>\u003Cspan class=\"shj-bracket\">)\u003C\u002Fspan>\n\u003Cspan class=\"shj-kwd\">export\u003C\u002Fspan> \u003Cspan class=\"shj-kwd\">class\u003C\u002Fspan> \u003Cspan class=\"shj-class\">RolesGuard\u003C\u002Fspan> \u003Cspan class=\"shj-kwd\">implements\u003C\u002Fspan> \u003Cspan class=\"shj-class\">CanActivate\u003C\u002Fspan> \u003Cspan class=\"shj-bracket\">{\u003C\u002Fspan>\n  \u003Cspan class=\"shj-kwd\">constructor\u003C\u002Fspan>\u003Cspan class=\"shj-bracket\">(\u003C\u002Fspan>\u003Cspan class=\"shj-kwd\">private\u003C\u002Fspan> reflector\u003Cspan class=\"shj-oper\">:\u003C\u002Fspan> \u003Cspan class=\"shj-class\">Reflector\u003C\u002Fspan>\u003Cspan class=\"shj-bracket\">)\u003C\u002Fspan> \u003Cspan class=\"shj-bracket\">{\u003C\u002Fspan>\u003Cspan class=\"shj-bracket\">}\u003C\u002Fspan>\n\n  \u003Cspan class=\"shj-func\">canActivate\u003C\u002Fspan>\u003Cspan class=\"shj-bracket\">(\u003C\u002Fspan>context\u003Cspan class=\"shj-oper\">:\u003C\u002Fspan> \u003Cspan class=\"shj-class\">ExecutionContext\u003C\u002Fspan>\u003Cspan class=\"shj-bracket\">)\u003C\u002Fspan>\u003Cspan class=\"shj-type\">: boolean\u003C\u002Fspan> \u003Cspan class=\"shj-bracket\">{\u003C\u002Fspan>\n    \u003Cspan class=\"shj-kwd\">const\u003C\u002Fspan> required \u003Cspan class=\"shj-oper\">=\u003C\u002Fspan> \u003Cspan class=\"shj-kwd\">this\u003C\u002Fspan>\u003Cspan class=\"shj-oper\">.\u003C\u002Fspan>reflector\u003Cspan class=\"shj-oper\">.\u003C\u002Fspan>getAllAndOverride\u003Cspan class=\"shj-oper\">&lt;\u003C\u002Fspan>string\u003Cspan class=\"shj-bracket\">[\u003C\u002Fspan>\u003Cspan class=\"shj-bracket\">]\u003C\u002Fspan>\u003Cspan class=\"shj-oper\">&gt;\u003C\u002Fspan>\u003Cspan class=\"shj-bracket\">(\u003C\u002Fspan>\u003Cspan class=\"shj-num\">ROLES_KEY\u003C\u002Fspan>\u003Cspan class=\"shj-oper\">,\u003C\u002Fspan> \u003Cspan class=\"shj-bracket\">[\u003C\u002Fspan>\n      context\u003Cspan class=\"shj-oper\">.\u003C\u002Fspan>\u003Cspan class=\"shj-func\">getHandler\u003C\u002Fspan>\u003Cspan class=\"shj-bracket\">(\u003C\u002Fspan>\u003Cspan class=\"shj-bracket\">)\u003C\u002Fspan>\u003Cspan class=\"shj-oper\">,\u003C\u002Fspan>\n      context\u003Cspan class=\"shj-oper\">.\u003C\u002Fspan>\u003Cspan class=\"shj-func\">getClass\u003C\u002Fspan>\u003Cspan class=\"shj-bracket\">(\u003C\u002Fspan>\u003Cspan class=\"shj-bracket\">)\u003C\u002Fspan>\u003Cspan class=\"shj-oper\">,\u003C\u002Fspan>\n    \u003Cspan class=\"shj-bracket\">]\u003C\u002Fspan>\u003Cspan class=\"shj-bracket\">)\u003C\u002Fspan>;\n    \u003Cspan class=\"shj-kwd\">if\u003C\u002Fspan> \u003Cspan class=\"shj-bracket\">(\u003C\u002Fspan>\u003Cspan class=\"shj-oper\">!\u003C\u002Fspan>required \u003Cspan class=\"shj-oper\">||\u003C\u002Fspan> required\u003Cspan class=\"shj-oper\">.\u003C\u002Fspan>length \u003Cspan class=\"shj-oper\">===\u003C\u002Fspan> \u003Cspan class=\"shj-num\">0\u003C\u002Fspan>\u003Cspan class=\"shj-bracket\">)\u003C\u002Fspan> \u003Cspan class=\"shj-kwd\">return\u003C\u002Fspan> \u003Cspan class=\"shj-bool\">true\u003C\u002Fspan>; \u003Cspan class=\"shj-cmnt\">\u002F\u002F no @Roles() = open route\n\u003C\u002Fspan>\n    \u003Cspan class=\"shj-kwd\">const\u003C\u002Fspan> \u003Cspan class=\"shj-bracket\">{\u003C\u002Fspan> user \u003Cspan class=\"shj-bracket\">}\u003C\u002Fspan> \u003Cspan class=\"shj-oper\">=\u003C\u002Fspan> context\u003Cspan class=\"shj-oper\">.\u003C\u002Fspan>\u003Cspan class=\"shj-func\">switchToHttp\u003C\u002Fspan>\u003Cspan class=\"shj-bracket\">(\u003C\u002Fspan>\u003Cspan class=\"shj-bracket\">)\u003C\u002Fspan>\u003Cspan class=\"shj-oper\">.\u003C\u002Fspan>\u003Cspan class=\"shj-func\">getRequest\u003C\u002Fspan>\u003Cspan class=\"shj-bracket\">(\u003C\u002Fspan>\u003Cspan class=\"shj-bracket\">)\u003C\u002Fspan>;\n    \u003Cspan class=\"shj-kwd\">return\u003C\u002Fspan> required\u003Cspan class=\"shj-oper\">.\u003C\u002Fspan>\u003Cspan class=\"shj-func\">some\u003C\u002Fspan>\u003Cspan class=\"shj-bracket\">(\u003C\u002Fspan>\u003Cspan class=\"shj-bracket\">(\u003C\u002Fspan>role\u003Cspan class=\"shj-bracket\">)\u003C\u002Fspan> \u003Cspan class=\"shj-kwd\">=&gt;\u003C\u002Fspan> user\u003Cspan class=\"shj-oper\">?.\u003C\u002Fspan>roles\u003Cspan class=\"shj-oper\">?.\u003C\u002Fspan>\u003Cspan class=\"shj-func\">includes\u003C\u002Fspan>\u003Cspan class=\"shj-bracket\">(\u003C\u002Fspan>role\u003Cspan class=\"shj-bracket\">)\u003C\u002Fspan>\u003Cspan class=\"shj-bracket\">)\u003C\u002Fspan>;\n  \u003Cspan class=\"shj-bracket\">}\u003C\u002Fspan>\n\u003Cspan class=\"shj-bracket\">}\u003C\u002Fspan>\u003C\u002Fdiv>\u003C\u002Fdiv>\u003C\u002Fdiv>","\u003Cdiv class=\"shj shj-lang-ts shj-multiline\" data-lang=\"ts\">\u003Cdiv class=\"shj-scroll\">\u003Cdiv class=\"shj-numbers\">\u003Cdiv>1\u003C\u002Fdiv>\u003Cdiv>2\u003C\u002Fdiv>\u003Cdiv>3\u003C\u002Fdiv>\u003Cdiv>4\u003C\u002Fdiv>\u003Cdiv>5\u003C\u002Fdiv>\u003Cdiv>6\u003C\u002Fdiv>\u003Cdiv>7\u003C\u002Fdiv>\u003Cdiv>8\u003C\u002Fdiv>\u003Cdiv>9\u003C\u002Fdiv>\u003Cdiv>10\u003C\u002Fdiv>\u003C\u002Fdiv>\u003Cdiv class=\"shj-code\">@\u003Cspan class=\"shj-class\">Controller\u003C\u002Fspan>\u003Cspan class=\"shj-bracket\">(\u003C\u002Fspan>\u003Cspan class=\"shj-str\">\"orders\"\u003C\u002Fspan>\u003Cspan class=\"shj-bracket\">)\u003C\u002Fspan>\n@\u003Cspan class=\"shj-class\">Roles\u003C\u002Fspan>\u003Cspan class=\"shj-bracket\">(\u003C\u002Fspan>\u003Cspan class=\"shj-str\">\"editor\"\u003C\u002Fspan>\u003Cspan class=\"shj-bracket\">)\u003C\u002Fspan> \u003Cspan class=\"shj-cmnt\">\u002F\u002F class-level default\n\u003C\u002Fspan>\u003Cspan class=\"shj-kwd\">export\u003C\u002Fspan> \u003Cspan class=\"shj-kwd\">class\u003C\u002Fspan> \u003Cspan class=\"shj-class\">OrdersController\u003C\u002Fspan> \u003Cspan class=\"shj-bracket\">{\u003C\u002Fspan>\n  @\u003Cspan class=\"shj-class\">Get\u003C\u002Fspan>\u003Cspan class=\"shj-bracket\">(\u003C\u002Fspan>\u003Cspan class=\"shj-bracket\">)\u003C\u002Fspan>\n  \u003Cspan class=\"shj-func\">list\u003C\u002Fspan>\u003Cspan class=\"shj-bracket\">(\u003C\u002Fspan>\u003Cspan class=\"shj-bracket\">)\u003C\u002Fspan> \u003Cspan class=\"shj-bracket\">{\u003C\u002Fspan> \u003Cspan class=\"shj-cmnt\">\u002F* requires \"editor\" — inherits the class default *\u002F\u003C\u002Fspan> \u003Cspan class=\"shj-bracket\">}\u003C\u002Fspan>\n\n  @\u003Cspan class=\"shj-class\">Delete\u003C\u002Fspan>\u003Cspan class=\"shj-bracket\">(\u003C\u002Fspan>\u003Cspan class=\"shj-str\">\":id\"\u003C\u002Fspan>\u003Cspan class=\"shj-bracket\">)\u003C\u002Fspan>\n  @\u003Cspan class=\"shj-class\">Roles\u003C\u002Fspan>\u003Cspan class=\"shj-bracket\">(\u003C\u002Fspan>\u003Cspan class=\"shj-str\">\"admin\"\u003C\u002Fspan>\u003Cspan class=\"shj-bracket\">)\u003C\u002Fspan> \u003Cspan class=\"shj-cmnt\">\u002F\u002F method-level override\n\u003C\u002Fspan>  \u003Cspan class=\"shj-func\">remove\u003C\u002Fspan>\u003Cspan class=\"shj-bracket\">(\u003C\u002Fspan>\u003Cspan class=\"shj-bracket\">)\u003C\u002Fspan> \u003Cspan class=\"shj-bracket\">{\u003C\u002Fspan> \u003Cspan class=\"shj-cmnt\">\u002F* requires \"admin\" — this wins over the class's \"editor\" *\u002F\u003C\u002Fspan> \u003Cspan class=\"shj-bracket\">}\u003C\u002Fspan>\n\u003Cspan class=\"shj-bracket\">}\u003C\u002Fspan>\u003C\u002Fdiv>\u003C\u002Fdiv>\u003C\u002Fdiv>","\u003Cdiv class=\"shj shj-lang-ts shj-multiline\" data-lang=\"ts\">\u003Cdiv class=\"shj-scroll\">\u003Cdiv class=\"shj-numbers\">\u003Cdiv>1\u003C\u002Fdiv>\u003Cdiv>2\u003C\u002Fdiv>\u003Cdiv>3\u003C\u002Fdiv>\u003Cdiv>4\u003C\u002Fdiv>\u003Cdiv>5\u003C\u002Fdiv>\u003Cdiv>6\u003C\u002Fdiv>\u003Cdiv>7\u003C\u002Fdiv>\u003Cdiv>8\u003C\u002Fdiv>\u003Cdiv>9\u003C\u002Fdiv>\u003C\u002Fdiv>\u003Cdiv class=\"shj-code\">\u003Cspan class=\"shj-kwd\">import\u003C\u002Fspan> \u003Cspan class=\"shj-bracket\">{\u003C\u002Fspan> \u003Cspan class=\"shj-num\">APP_GUARD\u003C\u002Fspan> \u003Cspan class=\"shj-bracket\">}\u003C\u002Fspan> \u003Cspan class=\"shj-kwd\">from\u003C\u002Fspan> \u003Cspan class=\"shj-str\">\"@nestjs\u002Fcore\"\u003C\u002Fspan>;\n\n@\u003Cspan class=\"shj-class\">Module\u003C\u002Fspan>\u003Cspan class=\"shj-bracket\">(\u003C\u002Fspan>\u003Cspan class=\"shj-bracket\">{\u003C\u002Fspan>\n  providers\u003Cspan class=\"shj-oper\">:\u003C\u002Fspan> \u003Cspan class=\"shj-bracket\">[\u003C\u002Fspan>\n    \u003Cspan class=\"shj-class\">RolesGuard\u003C\u002Fspan>\u003Cspan class=\"shj-oper\">,\u003C\u002Fspan>\n    \u003Cspan class=\"shj-bracket\">{\u003C\u002Fspan> provide\u003Cspan class=\"shj-oper\">:\u003C\u002Fspan> \u003Cspan class=\"shj-num\">APP_GUARD\u003C\u002Fspan>\u003Cspan class=\"shj-oper\">,\u003C\u002Fspan> useClass\u003Cspan class=\"shj-oper\">:\u003C\u002Fspan> \u003Cspan class=\"shj-class\">RolesGuard\u003C\u002Fspan> \u003Cspan class=\"shj-bracket\">}\u003C\u002Fspan>\u003Cspan class=\"shj-oper\">,\u003C\u002Fspan>\n  \u003Cspan class=\"shj-bracket\">]\u003C\u002Fspan>\u003Cspan class=\"shj-oper\">,\u003C\u002Fspan>\n\u003Cspan class=\"shj-bracket\">}\u003C\u002Fspan>\u003Cspan class=\"shj-bracket\">)\u003C\u002Fspan>\n\u003Cspan class=\"shj-kwd\">export\u003C\u002Fspan> \u003Cspan class=\"shj-kwd\">class\u003C\u002Fspan> \u003Cspan class=\"shj-class\">AppModule\u003C\u002Fspan> \u003Cspan class=\"shj-bracket\">{\u003C\u002Fspan>\u003Cspan class=\"shj-bracket\">}\u003C\u002Fspan>\u003C\u002Fdiv>\u003C\u002Fdiv>\u003C\u002Fdiv>","\u003Cdiv class=\"shj shj-lang-ts shj-multiline\" data-lang=\"ts\">\u003Cdiv class=\"shj-scroll\">\u003Cdiv class=\"shj-numbers\">\u003Cdiv>1\u003C\u002Fdiv>\u003Cdiv>2\u003C\u002Fdiv>\u003Cdiv>3\u003C\u002Fdiv>\u003C\u002Fdiv>\u003Cdiv class=\"shj-code\">@\u003Cspan class=\"shj-class\">UseGuards\u003C\u002Fspan>\u003Cspan class=\"shj-bracket\">(\u003C\u002Fspan>\u003Cspan class=\"shj-class\">ThrottleGuard\u003C\u002Fspan>\u003Cspan class=\"shj-oper\">,\u003C\u002Fspan> \u003Cspan class=\"shj-class\">RolesGuard\u003C\u002Fspan>\u003Cspan class=\"shj-bracket\">)\u003C\u002Fspan> \u003Cspan class=\"shj-cmnt\">\u002F\u002F ThrottleGuard runs first\n\u003C\u002Fspan>@\u003Cspan class=\"shj-class\">Controller\u003C\u002Fspan>\u003Cspan class=\"shj-bracket\">(\u003C\u002Fspan>\u003Cspan class=\"shj-str\">\"orders\"\u003C\u002Fspan>\u003Cspan class=\"shj-bracket\">)\u003C\u002Fspan>\n\u003Cspan class=\"shj-kwd\">export\u003C\u002Fspan> \u003Cspan class=\"shj-kwd\">class\u003C\u002Fspan> \u003Cspan class=\"shj-class\">OrdersController\u003C\u002Fspan> \u003Cspan class=\"shj-bracket\">{\u003C\u002Fspan>\u003Cspan class=\"shj-bracket\">}\u003C\u002Fspan>\u003C\u002Fdiv>\u003C\u002Fdiv>\u003C\u002Fdiv>","\u003Cdiv class=\"shj shj-lang-ts shj-multiline\" data-lang=\"ts\">\u003Cdiv class=\"shj-scroll\">\u003Cdiv class=\"shj-numbers\">\u003Cdiv>1\u003C\u002Fdiv>\u003Cdiv>2\u003C\u002Fdiv>\u003Cdiv>3\u003C\u002Fdiv>\u003Cdiv>4\u003C\u002Fdiv>\u003Cdiv>5\u003C\u002Fdiv>\u003Cdiv>6\u003C\u002Fdiv>\u003Cdiv>7\u003C\u002Fdiv>\u003Cdiv>8\u003C\u002Fdiv>\u003Cdiv>9\u003C\u002Fdiv>\u003Cdiv>10\u003C\u002Fdiv>\u003Cdiv>11\u003C\u002Fdiv>\u003Cdiv>12\u003C\u002Fdiv>\u003Cdiv>13\u003C\u002Fdiv>\u003Cdiv>14\u003C\u002Fdiv>\u003Cdiv>15\u003C\u002Fdiv>\u003Cdiv>16\u003C\u002Fdiv>\u003Cdiv>17\u003C\u002Fdiv>\u003Cdiv>18\u003C\u002Fdiv>\u003Cdiv>19\u003C\u002Fdiv>\u003Cdiv>20\u003C\u002Fdiv>\u003Cdiv>21\u003C\u002Fdiv>\u003Cdiv>22\u003C\u002Fdiv>\u003Cdiv>23\u003C\u002Fdiv>\u003Cdiv>24\u003C\u002Fdiv>\u003Cdiv>25\u003C\u002Fdiv>\u003C\u002Fdiv>\u003Cdiv class=\"shj-code\">\u003Cspan class=\"shj-cmnt\">\u002F\u002F A guard is a provider that implements CanActivate.\n\u003C\u002Fspan>@\u003Cspan class=\"shj-class\">Injectable\u003C\u002Fspan>\u003Cspan class=\"shj-bracket\">(\u003C\u002Fspan>\u003Cspan class=\"shj-bracket\">)\u003C\u002Fspan>\n\u003Cspan class=\"shj-kwd\">export\u003C\u002Fspan> \u003Cspan class=\"shj-kwd\">class\u003C\u002Fspan> \u003Cspan class=\"shj-class\">MyGuard\u003C\u002Fspan> \u003Cspan class=\"shj-kwd\">implements\u003C\u002Fspan> \u003Cspan class=\"shj-class\">CanActivate\u003C\u002Fspan> \u003Cspan class=\"shj-bracket\">{\u003C\u002Fspan>\n  \u003Cspan class=\"shj-kwd\">constructor\u003C\u002Fspan>\u003Cspan class=\"shj-bracket\">(\u003C\u002Fspan>\u003Cspan class=\"shj-kwd\">private\u003C\u002Fspan> reflector\u003Cspan class=\"shj-oper\">:\u003C\u002Fspan> \u003Cspan class=\"shj-class\">Reflector\u003C\u002Fspan>\u003Cspan class=\"shj-bracket\">)\u003C\u002Fspan> \u003Cspan class=\"shj-bracket\">{\u003C\u002Fspan>\u003Cspan class=\"shj-bracket\">}\u003C\u002Fspan> \u003Cspan class=\"shj-cmnt\">\u002F\u002F real DI, if registered correctly\n\u003C\u002Fspan>\n  \u003Cspan class=\"shj-func\">canActivate\u003C\u002Fspan>\u003Cspan class=\"shj-bracket\">(\u003C\u002Fspan>ctx\u003Cspan class=\"shj-oper\">:\u003C\u002Fspan> \u003Cspan class=\"shj-class\">ExecutionContext\u003C\u002Fspan>\u003Cspan class=\"shj-bracket\">)\u003C\u002Fspan>\u003Cspan class=\"shj-type\">: boolean\u003C\u002Fspan> \u003Cspan class=\"shj-oper\">|\u003C\u002Fspan> \u003Cspan class=\"shj-class\">Promise\u003C\u002Fspan>\u003Cspan class=\"shj-oper\">&lt;\u003C\u002Fspan>boolean\u003Cspan class=\"shj-oper\">&gt;\u003C\u002Fspan> \u003Cspan class=\"shj-bracket\">{\u003C\u002Fspan>\n    \u003Cspan class=\"shj-kwd\">const\u003C\u002Fspan> req \u003Cspan class=\"shj-oper\">=\u003C\u002Fspan> ctx\u003Cspan class=\"shj-oper\">.\u003C\u002Fspan>\u003Cspan class=\"shj-func\">switchToHttp\u003C\u002Fspan>\u003Cspan class=\"shj-bracket\">(\u003C\u002Fspan>\u003Cspan class=\"shj-bracket\">)\u003C\u002Fspan>\u003Cspan class=\"shj-oper\">.\u003C\u002Fspan>\u003Cspan class=\"shj-func\">getRequest\u003C\u002Fspan>\u003Cspan class=\"shj-bracket\">(\u003C\u002Fspan>\u003Cspan class=\"shj-bracket\">)\u003C\u002Fspan>;       \u003Cspan class=\"shj-cmnt\">\u002F\u002F the underlying request\n\u003C\u002Fspan>    \u003Cspan class=\"shj-kwd\">const\u003C\u002Fspan> handler \u003Cspan class=\"shj-oper\">=\u003C\u002Fspan> ctx\u003Cspan class=\"shj-oper\">.\u003C\u002Fspan>\u003Cspan class=\"shj-func\">getHandler\u003C\u002Fspan>\u003Cspan class=\"shj-bracket\">(\u003C\u002Fspan>\u003Cspan class=\"shj-bracket\">)\u003C\u002Fspan>;                  \u003Cspan class=\"shj-cmnt\">\u002F\u002F the exact route method\n\u003C\u002Fspan>    \u003Cspan class=\"shj-kwd\">const\u003C\u002Fspan> controller \u003Cspan class=\"shj-oper\">=\u003C\u002Fspan> ctx\u003Cspan class=\"shj-oper\">.\u003C\u002Fspan>\u003Cspan class=\"shj-func\">getClass\u003C\u002Fspan>\u003Cspan class=\"shj-bracket\">(\u003C\u002Fspan>\u003Cspan class=\"shj-bracket\">)\u003C\u002Fspan>;                 \u003Cspan class=\"shj-cmnt\">\u002F\u002F the controller class\n\u003C\u002Fspan>    \u003Cspan class=\"shj-kwd\">return\u003C\u002Fspan> \u003Cspan class=\"shj-bool\">true\u003C\u002Fspan>; \u003Cspan class=\"shj-cmnt\">\u002F\u002F or false, or throw a specific HttpException\n\u003C\u002Fspan>  \u003Cspan class=\"shj-bracket\">}\u003C\u002Fspan>\n\u003Cspan class=\"shj-bracket\">}\u003C\u002Fspan>\n\n\u003Cspan class=\"shj-cmnt\">\u002F\u002F Metadata decorator + read-back\n\u003C\u002Fspan>\u003Cspan class=\"shj-kwd\">export\u003C\u002Fspan> \u003Cspan class=\"shj-kwd\">const\u003C\u002Fspan> \u003Cspan class=\"shj-num\">ROLES_KEY\u003C\u002Fspan> \u003Cspan class=\"shj-oper\">=\u003C\u002Fspan> \u003Cspan class=\"shj-str\">\"roles\"\u003C\u002Fspan>;\n\u003Cspan class=\"shj-kwd\">export\u003C\u002Fspan> \u003Cspan class=\"shj-kwd\">const\u003C\u002Fspan> \u003Cspan class=\"shj-class\">Roles\u003C\u002Fspan> \u003Cspan class=\"shj-oper\">=\u003C\u002Fspan> \u003Cspan class=\"shj-bracket\">(\u003C\u002Fspan>\u003Cspan class=\"shj-oper\">...\u003C\u002Fspan>roles\u003Cspan class=\"shj-type\">: string\u003C\u002Fspan>\u003Cspan class=\"shj-bracket\">[\u003C\u002Fspan>\u003Cspan class=\"shj-bracket\">]\u003C\u002Fspan>\u003Cspan class=\"shj-bracket\">)\u003C\u002Fspan> \u003Cspan class=\"shj-kwd\">=&gt;\u003C\u002Fspan> \u003Cspan class=\"shj-class\">SetMetadata\u003C\u002Fspan>\u003Cspan class=\"shj-bracket\">(\u003C\u002Fspan>\u003Cspan class=\"shj-num\">ROLES_KEY\u003C\u002Fspan>\u003Cspan class=\"shj-oper\">,\u003C\u002Fspan> roles\u003Cspan class=\"shj-bracket\">)\u003C\u002Fspan>;\n\u003Cspan class=\"shj-cmnt\">\u002F\u002F method metadata wins over class metadata:\n\u003C\u002Fspan>reflector\u003Cspan class=\"shj-oper\">.\u003C\u002Fspan>getAllAndOverride\u003Cspan class=\"shj-oper\">&lt;\u003C\u002Fspan>string\u003Cspan class=\"shj-bracket\">[\u003C\u002Fspan>\u003Cspan class=\"shj-bracket\">]\u003C\u002Fspan>\u003Cspan class=\"shj-oper\">&gt;\u003C\u002Fspan>\u003Cspan class=\"shj-bracket\">(\u003C\u002Fspan>\u003Cspan class=\"shj-num\">ROLES_KEY\u003C\u002Fspan>\u003Cspan class=\"shj-oper\">,\u003C\u002Fspan> \u003Cspan class=\"shj-bracket\">[\u003C\u002Fspan>ctx\u003Cspan class=\"shj-oper\">.\u003C\u002Fspan>\u003Cspan class=\"shj-func\">getHandler\u003C\u002Fspan>\u003Cspan class=\"shj-bracket\">(\u003C\u002Fspan>\u003Cspan class=\"shj-bracket\">)\u003C\u002Fspan>\u003Cspan class=\"shj-oper\">,\u003C\u002Fspan> ctx\u003Cspan class=\"shj-oper\">.\u003C\u002Fspan>\u003Cspan class=\"shj-func\">getClass\u003C\u002Fspan>\u003Cspan class=\"shj-bracket\">(\u003C\u002Fspan>\u003Cspan class=\"shj-bracket\">)\u003C\u002Fspan>\u003Cspan class=\"shj-bracket\">]\u003C\u002Fspan>\u003Cspan class=\"shj-bracket\">)\u003C\u002Fspan>;\n\u003Cspan class=\"shj-cmnt\">\u002F\u002F both levels contribute instead:\n\u003C\u002Fspan>reflector\u003Cspan class=\"shj-oper\">.\u003C\u002Fspan>getAllAndMerge\u003Cspan class=\"shj-oper\">&lt;\u003C\u002Fspan>string\u003Cspan class=\"shj-bracket\">[\u003C\u002Fspan>\u003Cspan class=\"shj-bracket\">]\u003C\u002Fspan>\u003Cspan class=\"shj-oper\">&gt;\u003C\u002Fspan>\u003Cspan class=\"shj-bracket\">(\u003C\u002Fspan>\u003Cspan class=\"shj-num\">ROLES_KEY\u003C\u002Fspan>\u003Cspan class=\"shj-oper\">,\u003C\u002Fspan> \u003Cspan class=\"shj-bracket\">[\u003C\u002Fspan>ctx\u003Cspan class=\"shj-oper\">.\u003C\u002Fspan>\u003Cspan class=\"shj-func\">getHandler\u003C\u002Fspan>\u003Cspan class=\"shj-bracket\">(\u003C\u002Fspan>\u003Cspan class=\"shj-bracket\">)\u003C\u002Fspan>\u003Cspan class=\"shj-oper\">,\u003C\u002Fspan> ctx\u003Cspan class=\"shj-oper\">.\u003C\u002Fspan>\u003Cspan class=\"shj-func\">getClass\u003C\u002Fspan>\u003Cspan class=\"shj-bracket\">(\u003C\u002Fspan>\u003Cspan class=\"shj-bracket\">)\u003C\u002Fspan>\u003Cspan class=\"shj-bracket\">]\u003C\u002Fspan>\u003Cspan class=\"shj-bracket\">)\u003C\u002Fspan>;\n\n\u003Cspan class=\"shj-cmnt\">\u002F\u002F Registration — pick based on whether the guard has dependencies\n\u003C\u002Fspan>@\u003Cspan class=\"shj-class\">UseGuards\u003C\u002Fspan>\u003Cspan class=\"shj-bracket\">(\u003C\u002Fspan>\u003Cspan class=\"shj-class\">MyGuard\u003C\u002Fspan>\u003Cspan class=\"shj-bracket\">)\u003C\u002Fspan>              \u003Cspan class=\"shj-cmnt\">\u002F\u002F per-route or per-controller, always through DI\n\u003C\u002Fspan>app\u003Cspan class=\"shj-oper\">.\u003C\u002Fspan>\u003Cspan class=\"shj-func\">useGlobalGuards\u003C\u002Fspan>\u003Cspan class=\"shj-bracket\">(\u003C\u002Fspan>\u003Cspan class=\"shj-kwd\">new\u003C\u002Fspan> \u003Cspan class=\"shj-class\">MyGuard\u003C\u002Fspan>\u003Cspan class=\"shj-bracket\">(\u003C\u002Fspan>\u003Cspan class=\"shj-bracket\">)\u003C\u002Fspan>\u003Cspan class=\"shj-bracket\">)\u003C\u002Fspan>; \u003Cspan class=\"shj-cmnt\">\u002F\u002F global, but NO dependency injection\n\u003C\u002Fspan>\u003Cspan class=\"shj-bracket\">{\u003C\u002Fspan> provide\u003Cspan class=\"shj-oper\">:\u003C\u002Fspan> \u003Cspan class=\"shj-num\">APP_GUARD\u003C\u002Fspan>\u003Cspan class=\"shj-oper\">,\u003C\u002Fspan> useClass\u003Cspan class=\"shj-oper\">:\u003C\u002Fspan> \u003Cspan class=\"shj-class\">MyGuard\u003C\u002Fspan> \u003Cspan class=\"shj-bracket\">}\u003C\u002Fspan> \u003Cspan class=\"shj-cmnt\">\u002F\u002F global, WITH dependency injection\u003C\u002Fspan>\u003C\u002Fdiv>\u003C\u002Fdiv>\u003C\u002Fdiv>",{"locked":18,"total":19,"comments":588},[]]