Setting up an OR guard in NestJS is a crucial step in managing

I need to secure a controller route using Guards, including IsAuthentifiedGuard, HasRoleGuard, and IsSafeGuard. I want the route to be accessible if at least one of these conditions is met:

  • IsAuthentifiedGuard and HasRoleGuard pass
  • IsSafeGuard passes

For example, the user should have access if authenticated AND has the necessary role, or if the call is considered "safe."

This is my OrGuard implementation:

@Injectable()
export class OrGuard implements CanActivate {
  constructor(private readonly orGuards: CanActivate[][]) {}

  async canActivate(context: ExecutionContext): Promise<boolean> {
    const orGuardsPromises = await Promise.all(
      this.orGuards.map(async andGuards => {
        const andGuardPromises = await Promise.all(
          andGuards.map(async guard => {
            return guard.canActivate(context)
          }),
        )
        return andGuardPromises.every(canActivate => canActivate === true)
      }),
    )

    return orGuardsPromises.some(canActivate => canActivate === true)
  }
}

And here's how it is applied in my controller:

@Controller('my_route')
export class MyController {
  @Post('/')
  @UseGuards(new OrGuard([[new IsAuthentifiedGuard(), new HasRoleGuard()], [new IsSafeGuard()]]))
  async myRoute() {}
}

The issue arises when guards require dependencies like ConfigService.

Another approach could be:

@UseGuards(OrGuard)
@SetMetadata('orGuards', [[IsAuthentifiedGuard, HasRoleGuard], [IsSafeGuard]])

But I am struggling to instantiate these guards within OrGuard with all their required dependencies. Any suggestions?

Answer №1

To achieve your desired outcome, you can utilize the @nest-lab/or-guard library. Make sure to register your guards as providers and create a custom provider for the AndGuard. Here's an example setup:

@Module({
  providers: [
    IsAuthentifiedGuard,
    HasRoleGuard,
    IsSafeGuard,
    {
      provide: 'AndGuard',
      useClass: AndGuard([IsAuthenticatedGuard, HasRoleGuard]),
    },
    ...
  ]
})

Once set up, you can use

@UseGuards(OrGuard(['AndGuard', IsSafeGuard]))
to implement the logic effectively. Feel free to check out the tests for more insight on its functionality.

Similar questions

If you have not found the answer to your question or you are interested in this topic, then look at other similar questions below or use the search

Jest - managing parent class methods during unit tests

The code snippet provided demonstrates a class called First extending TelemetryFramework with specific props and states, containing a method named getData. This method retrieves confidential data and logs telemetry information. However, running unit tests ...

Understanding a compound data type in TypeScript

Hey there, I'm new to TypeScript and I'm facing a challenge in defining the type for an object that might have the following structure at runtime: { "animals" : [ { name: "kittie", color: "blue" }, { name: ...

Setting values for TypeScript objects

I am currently working on developing a custom visual using Power BI. Within my interfaces file, I have a TypeScript interface called BiHiSankey. declare module 'd3' { interface BiHiSankey { nodeSpacing: () => number; ...

Dealing with Scoping Problems in a Typescript d3 Update Tutorial

I'm facing challenges trying to implement the provided bl.ocks example in Typescript (using Angular). This is my implementation in TypeScript: StackBlitz Could anyone offer insights on what might be causing the issues I'm encountering? My initi ...

The Angular overlay panel remains open consistently

I recently developed an Angular component similar to p-overlaypanel, but I'm facing an issue where it remains open for every item I click. What I actually want is for only one overlay panel to be clicked and shown at a time - if I click on another ove ...

Typescript: Transforming generic types into concrete types

I am utilizing a Generic type type GenericType = { [key: string]: { prop1: string, prop2?: string, prop3?: number, }, }; The purpose of the Generic type is to assist in constructing / validating a new object that I have created. const NewO ...

using lodash to convert objects into arrays while maintaining parent-child relationships

Is there a way to achieve this transformation in lodash or any other JavaScript/TypeScript method? var obj = { a: [ {id:1},{id:2},{id:3}] b: [ {id:4},{id:5},{id:6}] c: [ {id:7},{id:8},{id:9}] } // Need to transform into var arr = [ {title:a ...

Converting an existing array into a TypeScript string literal type: A step-by-step guide

Converting TypeScript Arrays to String Literal Types delves into the creation of a string literal type from an array. The question raised is whether it's feasible to derive a string literal from an existing array. Using the same example: const furnit ...

How can I pass a service method as a parameter in an Angular 2 component?

Within the component: myFunction(): void { this.myOtherFunctoin(this._myService.serviceMethod); } private myOtherFunction(func : Function){ func(); } Regarding service calls: serviceMethod(){ this.somethingMethod(); // "this" is coming as ...

Is a package I overlooked? The 'findOne' property is not found within the 'Schema<Document<any, {}>, Model<any, any>, undefined>'

I have taken over the responsibility of maintaining the websites at my company, and I am encountering the error message (Property 'findOne' does not exist on type 'Schema<Document<any, {}>, Model<any, any>, undefined>' ...

Developing a dynamic web application using Asp.Net Core integrated with React and material

After setting up an Asp.Net Core project using the react template, I decided to incorporate material-ui by following the steps outlined on this page. However, encountered some dependency issues along the way. To resolve them, I had to update the react and ...

A guide to accessing an ngModel element within a reusable component

I have a specific ngModel component inside a reusable component that is not part of a form. I need to access it in order to make some changes, but when I try to do so using the code below, it returns undefined during OnInit. Can you advise me on how to pro ...

Singleton constructor running repeatedly in NextJS 13 middleware

I'm encountering an issue with a simple singleton called Paths: export default class Paths { private static _instance: Paths; private constructor() { console.log('paths constructor'); } public static get Instance() { consol ...

Angular 4 prohibits certain special characters and the number zero

Currently, I am a beginner in Angular 4 and I am working on learning how to search for data from a text box. However, whenever I input special characters like "%" in my code, it triggers an error leading to a crash in my application. Is there any effectiv ...

define a variable within a v-for loop

Example of Code <div v-for="item in dataItems"> <div v-if="enableEdit"> <input type="text" v-model="name"> </div> <div v-else> {{name}} </div> <button @click="enableEdit = true">click</button> This ...

Create a unique custom design for your Mapbox GL control

When developing the website, we utilized Angular 8, Typescript, and SCSS. We are using mgl-map to display a map, and I wanted to create a custom control for it with unique styles. I added the custom control to the map using: const centerOnCoordinatesC ...

Launch the Image-Infused Modal

I am completely new to the world of Ionic development. Currently, I am working on a simple Ionic application that comprises a list of users with their respective usernames and images stored in an array. Typescript: users = [ { "name": "First ...

Retrieve the visibility and data type of an object's property in Javascript or Typescript

Issue at hand: I am currently facing a challenge in distinguishing between the private, public, and getter (get X()) properties within a TypeScript class. Current Project Scenario: Within my Angular project, I have implemented a model design pattern. Fo ...

Get detailed coverage reports using Istanbul JS, Vue JS, Vue CLI, Cypress end-to-end tests, and Typescript, focusing on specific files for analysis

I have a VueJS app written in Typescript that I am testing with Cypress e2e tests. I wanted to set up coverage reports using Istanbul JS to track how much of my code is covered by the tests. The integration process seemed straightforward based on the docum ...

"Encountering a module not found issue while trying to

Attempting to test out 3 node modules locally by updating their source locations in the package.json files. The modules in question are sdk, ng-widget-lib, and frontend. ng-widget-lib relies on sdk, while frontend depends on ng-widget-lib. To locally build ...