मेरे पास एक सेवा विधि है जो निम्न कार्य करती है:

  1. डेटाबेस से उपयोगकर्ता को उनकी आईडी द्वारा ढूँढता है
  2. जाँचता है कि क्या कोई उपयोगकर्ता पाया गया है
  3. पैरामीटर के रूप में प्रदान किए गए पासवर्ड के विरुद्ध डीबी में संग्रहीत पासवर्ड की तुलना करने के लिए bcrypt का उपयोग करता है
  4. यदि पासवर्ड गलत था, तो एक अनधिकृत अपवाद फेंकता है, सही होने पर उपयोगकर्ता को लौटाता है।

मैं सिर्फ यह पता लगाने की कोशिश कर रहा हूं कि ऐसा करने के लिए आरएक्सजेएस ऑपरेटरों का उपयोग करने का कोई बेहतर तरीका है क्योंकि मुझे bcrypt.compare से पाइप करना पसंद नहीं है:

public validateUser(email: string, pass: string): Promise<UserDto> {
    return this.userService
      .findOne({ email })
      .pipe(
        map((user: UserDto) => {
          if (!user || !user.password) {
            return throwError(new UnauthorizedException());
          }
          return user;
        }),
        switchMap((user: UserDto) => {
          return from(
            bcrypt.compare(pass, user.password) as Promise<boolean>
          ).pipe(
            map((passwordIsCorrect) => ({
              passwordIsCorrect,
              user
            }))
          );
        }),
        switchMap((res) => {
          if (!res.passwordIsCorrect) {
            return throwError(new UnauthorizedException());
          }
          return of(res.user);
        })
      )
      .toPromise();
  }
2
Rob Bailey 9 फरवरी 2021, 23:36

2 जवाब

सबसे बढ़िया उत्तर

मुझे नहीं लगता कि उपयोग करने के लिए कोई बेहतर ऑपरेटर है, लेकिन आप कोड को सरल बनाकर switchMap इस तरह कर सकते हैं:

  public validateUser(email: string, pass: string): Promise<UserDto> {
    return this.userService.findOne({ email }).pipe(
      switchMap(user => {
        if (!user?.password) {
          return throwError(new UnauthorizedException());
        }

        return from(bcrypt.compare(pass, user.password)).pipe(
          switchMap(passwordIsCorrect => passwordIsCorrect ? of(user) : throwError(new UnauthorizedException()))
        )
      })
    ).toPromise();
  }

हालांकि, इस मामले में, ऐसा लगता है कि आप वेधशालाओं का उपयोग करने के लिए लड़ रहे हैं, (वादे को देखने योग्य में बदलें, बस वापस वादे में बदलने के लिए)।

यहां तक ​​​​कि अगर userSerivce देखने योग्य है, तो क्यों न इसे सीधे एक वादे में बदल दिया जाए? ऐसा लगता है कि कोड बहुत आसान होगा:

  public async validateUser(email: string, pass: string): Promise<UserDto> {
    const user = await this.userService.findOne({ email }).toPromise();
    
    if (!user?.password || !await bcrypt.compare(pass, user.password)) {
      throw new UnauthorizedException();
    }
    
    return user;
  }
2
BizzyBob 10 फरवरी 2021, 05:10

यदि आप वास्तव में आंतरिक पाइप को पसंद नहीं करते हैं, तो आप combineLatest का उपयोग user के मान के साथ-साथ passwordIsCorrect करने के लिए भी कर सकते हैं:

public validateUser(email: string, pass: string): Promise<UserDto> {
    return this.userService
      .findOne({ email })
      .pipe(
        map((user: UserDto) => {
          if (!user || !user.password) {
            return throwError(new UnauthorizedException());
          }
          return user;
        }),
        switchMap((user: UserDto) => {
          return combineLatest([
            from(bcrypt.compare(pass, user.password)),
            of(user)
          ])
        }),
        map(([passwordIsCorrect, user]) => ({
          passwordIsCorrect,
          user
        })),
        switchMap((res) => {
          if (!res.passwordIsCorrect) {
            return throwError(new UnauthorizedException());
          }
          return of(res.user);
        })
      )
      .toPromise();
  }
0
Steve Holgado 10 फरवरी 2021, 00:31