جافاسكريبت - كيفية الوصول إلى قاعدة البيانات من حارس NestJS
حالياً أحاول تعلم NestJS، ولأجل ذلك اتبعت الدليل الرسمي (القط-) لبناء نظام مصادقة مستخدم أساسي.
عندما تصل إلى واجهة برمجة التطبيقات لتغيير اسم المستخدم أو كلمة المرور، يجب على الطلب التحقق مما إذا كان المستخدم مستخدمًا صالحًا (قراءة المستخدم من قاعدة البيانات). لتخزين المستخدم، لدي بالفعل اتصال بـ MongoDB.
أنا حالياً أجد صعوبة في كيفية الحصول على وحدة/وصول قاعدة البيانات في الحارس.
الحارس يعمل لكنه يرجع true فقط، حاولت حقن وحدة قاعدة البيانات الخاصة بي لكن دون جدوى.
@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;
}
}
هل هذه هي الطريقة الصحيحة لتوسيع فئة UserService بإضافة طريقة findOne وحقنها في الخدمة؟
@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;
}
}
هل يمكنك من فضلك أن تخبرني كيف يبدو النهج الصحيح؟ شكراً مقدماً!
الإجابة رقم 1
لقد وجدت حلاً للوصول إلى قاعدة البيانات، يمكنك حقنه مباشرة (جربت ذلك من قبل لكن فشلت بسبب مشكلة أخرى).
@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;
});
}
}
كدّي الآن يبدو هكذا مع حقن الخدمة في المنشئ، لكنه لا يزال لا يعمل بالكامل، لأنه عندما أحاول تشغيل السطر execContext.switchToHttp().getRequest()، أحصل على خطأ switchToHttp ليست دالة، هل يمكن لأي أحد المساعدة؟
تحياتي يا باسكال
الإجابة رقم 2
هذا هو تنفيذي وهو يعمل بشكل جيد
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
}
}
