javascript - Cara mengakses basis data dari guard nestjs


Saat ini saya mencoba belajar nestjs, untuk itu saya mengikuti tutorial resmi (kucing-) untuk membangun sistem autentikasi pengguna dasar.

Ketika Anda mengakses API untuk mengubah nama pengguna atau kata sandi, permintaan harus memeriksa apakah pengguna adalah pengguna yang valid (membaca pengguna dari database). Untuk menyimpan pengguna, saya sudah memiliki koneksi mongodb.

Saat ini saya sedang berjuang bagaimana saya bisa mendapatkan modul/akses database di guard.

Penjaga sedang bekerja tetapi hanya mengembalikan true, saya sudah mencoba menyuntikkan modul database saya tetapi tidak berhasil.

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

Apakah pendekatan yang tepat untuk memperluas kelas UserService dengan metode findOne dan menyuntikkannya ke dalam layanan?

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

Dapatkah Anda memberi tahu saya bagaimana seharusnya pendekatan yang benar? Terima kasih sebelumnya!

Jawaban #1

Saya menemukan solusi untuk akses basis data, Anda bisa menyuntikkannya langsung (pernah mencoba itu sebelumnya tapi gagal karena masalah lain).

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

Kode saya sekarang terlihat seperti ini dengan layanan yang disuntikkan di konstruktor, tetapi masih belum sepenuhnya bekerja, karena ketika saya mencoba menjalankan baris execContext.switchToHttp().getRequest(), saya mendapat kesalahan switchToHttp bukan fungsi, apakah ada yang bisa membantu?

Salam Pascal

Jawaban #2

ini adalah implementasi saya dan itu bekerja dengan baik

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