javascript - Ako pristupovať k databáze z ochranky nestjs
Momentálne sa snažím naučiť nestjs, na to som nasledoval oficiálny (mačací) tutoriál na vytvorenie základného systému autentifikácie používateľov.
Keď pristupujete k API, aby ste zmenili používateľské meno alebo heslo, požiadavka by mala skontrolovať, či je používateľ platný používateľ (čítanie používateľa z databázy). Na uloženie používateľa už mám pripojenie k MongoDB.
Momentálne bojujem s tým, ako môžem získať modul/databázový prístup v garde.
Strážca funguje, ale vracia iba hodnotu true, skúšal som injektovať môj databázový modul, ale bez úspechu.
@Injectable()
export class AuthGuard implements CanActivate {
canActivate(
context: ExecutionContext,
): boolean | Promise<boolean> | Observable<boolean> {
const request = context.switchToHttp().getRequest();
return this.validateRequest(request);
}
validateRequest(execContext: ExecutionContext): boolean | Promise<boolean> | Observable<boolean>{
const request = execContext.switchToHttp().getRequest();
const user = request.user;
return true;
}
}
Je správny prístup rozšíriť triedu UserService metódou findOne a vložiť ju do služby?
@Injectable()
export class UserService{
constructor(@Inject('USER_MODEL') private readonly userModel: Model<User>){}
async create(createUserDto: CreateUserDto): Promise<User>{
const createdUser = new this.userModel(createUserDto);
return await createdUser.save();
}
async update(updateUserDto: UpdateUserDto): Promise<User>{
const updateUser = new this.userModel(updateUserDto);
return await this.userModel.updateOne({loginname: updateUser.loginname}, this.getUpdateQueryFromUserModel(updateUser));
}
async delete(deleteUserDto: DeleteUserDto): Promise<User>{
const deleteUser = new this.userModel(deleteUserDto);
return await this.userModel.deleteAll({loginname:deleteUser.loginname}).exec();
}
async findAll(): Promise<User[]> {
return await this.userModel.find().exec();
}
getUpdateQueryFromUserModel(userModel: Model<User>): Object {
let query = {};
if(userModel.dispname !== undefined && userModel.dispname !== null){
query["dispname"] = userModel.dispname;
}
if(userModel.pw !== undefined && userModel.pw !== null){
query["pw"] = hash.sha256().update(userModel.pw).digest('hex');
}
return query;
}
}
Môžete mi prosím povedať, ako vyzerá správny prístup? Vopred ďakujem!
Odpoveď č. 1
Našiel som riešenie prístupu k databáze, môžeš ho vložiť priamo (skúšal som to predtým, ale zlyhalo to kvôli inému problému).
@Injectable()
export class AuthGuard implements CanActivate {
constructor(@Inject('UserService')private readonly userService:UserService){}
canActivate(context: ExecutionContext): boolean | Promise<boolean> | Observable<boolean> {
const request = context.switchToHttp().getRequest();
return this.validateRequest(request);
}
async validateRequest(execContext: ExecutionContext): Promise<boolean>{
const request = execContext.switchToHttp().getRequest();
const user = request.user;
console.log(await this.userService.findAll());
return new Promise<boolean>((resolve, reject) => {
return true;
});
}
}
Môj kód teraz vyzerá takto s injektovanou službou v konštruktore, ale stále úplne nefunguje, pretože keď sa pokúsim spustiť riadok execContext.switchToHttp().getRequest(), dostanem chybu switchToHttp nie je funkcia, môže mi niekto pomôcť?
Pozdravujem Pascal
Odpoveď č. 2
toto je moja implementácia a funguje to dobre
import { CanActivate, ExecutionContext, Injectable, UnauthorizedException } from '@nestjs/common'
import { Reflector } from '@nestjs/core'
import { IS_PUBLIC_KEY } from 'src/decorators'
import { IResourcePermission, RESOURCE_PERMISSION_KEY } from 'src/decorators/resource-permission.decorator'
import { RolesPermissionsLogicService } from 'src/modules/roles-permissions/services/roles-permissions-logic.service'
@Injectable()
export class AuthorizeGuard implements CanActivate {
constructor(
private readonly rolesPermissionsLogicService: RolesPermissionsLogicService,
private reflector: Reflector,
) {}
canActivate(context: ExecutionContext): Promise<boolean> {
return this.validateRequest(context)
}
async validateRequest(ctx: ExecutionContext): Promise<boolean> {
const isRoutePublic = this.reflector.get<string>(IS_PUBLIC_KEY, ctx.getHandler())
const resourcePermission = this.reflector.get<IResourcePermission>(RESOURCE_PERMISSION_KEY, ctx.getHandler())
if (isRoutePublic || !resourcePermission) {
return true
}
const { user } = ctx.switchToHttp().getRequest()
const rolePermissions = await this.rolesPermissionsLogicService.getOneRole({
name: user.userRole,
permissions: {
$elemMatch: {
name: resourcePermission.resource,
[`actions.${resourcePermission.scope}`]: true,
},
},
})
if (!rolePermissions) {
throw new UnauthorizedException('Not authorized to access this resource')
}
return true
}
}
