Browse Source

Create RolesGuard

Michael Bromley 7 years ago
parent
commit
a013bad94d
2 changed files with 49 additions and 3 deletions
  1. 2 3
      modules/core/api/customer/customer.resolver.ts
  2. 47 0
      modules/core/auth/roles-guard.ts

+ 2 - 3
modules/core/api/customer/customer.resolver.ts

@@ -1,10 +1,10 @@
 import { Query, ResolveProperty, Resolver } from '@nestjs/graphql';
-import { AuthGuard } from '@nestjs/passport';
 import { CustomerService } from './customer.service';
 import { Address } from '../../entity/address/address.interface';
 import { CustomerEntity } from "../../entity/customer/customer.entity";
 import { Customer } from "../../entity/customer/customer.interface";
-import { UseGuards } from "@nestjs/common";
+import { RolesGuard } from "../../auth/roles-guard";
+import { Role } from "../../auth/role";
 
 @Resolver('Customer')
 export class CustomerResolver {
@@ -15,7 +15,6 @@ export class CustomerResolver {
         return this.customerService.findAll();
     }
 
-    @UseGuards(AuthGuard('jwt'))
     @Query('customer')
     customer(obj, args): Promise<Customer> {
         return this.customerService.findOne(args.id);

+ 47 - 0
modules/core/auth/roles-guard.ts

@@ -0,0 +1,47 @@
+import { CanActivate, ExecutionContext, UseGuards } from "@nestjs/common";
+import { AuthGuard } from "@nestjs/passport";
+import { Role } from "./role";
+import { UserEntity } from "../entity/user/user.entity";
+import { ExtractJwt, Strategy } from 'passport-jwt';
+
+/**
+ * A guard which combines the JWT passport auth method with restrictions based on
+ * the authenticated user's roles.
+ *
+ * @example
+ * ```
+ *  @RolesGuard([Role.Superadmin])
+ *  @Query('administrators')
+ *  getAdministrators() {
+ *      // ...
+ *  }
+ * ```
+ */
+export function RolesGuard(roles: Role[]) {
+    return UseGuards(AuthGuard('jwt'), forRoles(roles));
+}
+
+/**
+ * A guard which specifies which roles are authorized to access a given
+ * route or property in a Controller / Resolver.
+ */
+function forRoles(roles: Role[]) {
+    return {
+        canActivate(context: ExecutionContext) {
+            const user: UserEntity = context.switchToHttp().getRequest().user;
+            if (!user) {
+                return false;
+            }
+            return arraysIntersect(roles, user.roles);
+        }
+    } as CanActivate;
+}
+
+/**
+ * Returns true if any element of arr1 appears in arr2.
+ */
+function arraysIntersect(arr1, arr2): boolean {
+    return arr1.reduce((intersects, role) => {
+        return intersects || arr2.includes(role);
+    }, false);
+}