Weboldal keresés

javascript - Hogyan lehet hozzáférni az adatbázishoz NestJS guardból


Jelenleg próbálok megtanulni nestjs-t, ehhez követtem a hivatalos (macska-)oktatóanyagot egy alap felhasználói hitelesítési rendszer létrehozásához.

Amikor hozzáférsz az API-hoz a felhasználónév vagy jelszó megváltoztatásához, a kérésnek ellenőriznie kell, hogy a felhasználó érvényes-e (a felhasználó adatbázisból való lekérésével). A felhasználó tárolásához már van egy MongoDB kapcsolat.

Jelenleg azzal küszködöm, hogyan tudnám hozzáférni az adatbázis modulhoz/a guard-ban.

Az őr működik, de csak igazzal tér vissza, megpróbáltam befecskendezni az adatbázis modulomat, de sikertelenül.

@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;
  }
}

Helyes megközelítés a UserService osztály kiterjesztése egy findOne metódussal, és ennek injektálása a szolgáltatásba?

@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;
    }
}

Meg tudnád mondani, hogyan néz ki a helyes megközelítés? Előre is köszönöm!

Válasz #1

Találtam egy megoldást az adatbázis-hozzáférésre, közvetlenül be lehet injektálni (korábban próbáltam, de egy másik probléma miatt sikertelen volt).

@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;
    });
  }
}

A kódom most így néz ki, miután a szolgáltatást a konstruktorba injektáltam, de még mindig nem működik teljesen, mert amikor megpróbálom futtatni a execContext.switchToHttp().getRequest() sort, hibát kapok: switchToHttp nem egy függvény, tudna valaki segíteni?

Üdvözlet Pascal

Válasz #2

ez az én megvalósításom és jól működik

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
  }
}