Created
December 17, 2019 10:14
-
-
Save DimosthenisK/db21929a137d3e6c147f0bda3ecfbda6 to your computer and use it in GitHub Desktop.
NestJS Guard + Decorator that allows user access limit to his own resources
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
import { SetMetadata } from '@nestjs/common'; | |
export interface SelfDecoratorParams { | |
userIDParam: string; | |
allowAdmins?: boolean; | |
} | |
export const Self = (params: SelfDecoratorParams | string) => | |
SetMetadata( | |
'selfParams', | |
typeof params == 'string' ? { userIDParam: params } : params, | |
); |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
import { CanActivate, ExecutionContext, Injectable } from '@nestjs/common'; | |
import { Observable } from 'rxjs'; | |
import { Reflector } from '@nestjs/core'; | |
import { roles, User } from '../../user.dbentity'; | |
import { SelfDecoratorParams } from '../decorators/self.decorator'; | |
@Injectable() | |
export class SelfGuard implements CanActivate { | |
constructor(private readonly reflector: Reflector) {} | |
canActivate( | |
context: ExecutionContext, | |
): boolean | Promise<boolean> | Observable<boolean> { | |
const request = context.switchToHttp().getRequest(); | |
const user = request.user as User; //Use passport authentication strategy | |
//Priority on method meta | |
let selfParams = this.reflector.get<SelfDecoratorParams>( | |
'selfParams', | |
context.getHandler(), | |
); | |
if (!selfParams) | |
//Check for class meta | |
selfParams = this.reflector.get<SelfDecoratorParams>( | |
'selfParams', | |
context.getClass(), | |
); | |
//If still no meta, pass | |
if (!selfParams) return true; | |
let allowAdmins = selfParams.allowAdmins || true; | |
let userIDParam = selfParams.userIDParam; | |
if (!user) return false; | |
if (request.params[userIDParam] == user.id) return true; | |
if (allowAdmins && user.role == roles.SUPERUSER) return true; | |
} | |
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
import { | |
Controller, | |
Param, | |
Body, | |
UseInterceptors, | |
Patch, | |
UseGuards, | |
Req, | |
} from '@nestjs/common'; | |
import { SelfGuard } from '../authentication/guards/self.guard'; | |
import { Request } from 'express'; | |
import { User } from '../user.dbentity'; | |
import { Self } from '../authentication/decorators/self.decorator'; | |
@Self('id') //here "id" notes that the user id is on the "id" request parameter | |
@UseGuards(SelfGuard) | |
@Controller() | |
export class UserController { | |
constructor(service: UserService) {} | |
@Get('/sampleResource') | |
//You may also use the @Self decorator here for method-specific functionality | |
async getSampleResource() { | |
return "Sample resource"; | |
} | |
@Get('/sampleResource-adminCanAccess') | |
@Self({userIDParam: 'id', allowAdmins: true}) | |
async getAdminSampleResource() { | |
return "Sample resource"; | |
} | |
} |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment