ekyc

Electronic KYC process with uploading ID document using OAuth 2.1 (experimental)
Log | Files | Refs | README | LICENSE

user_info.ts (3138B)


      1 import { CustomerInfoUseCase } from "#core/application/customer_info.ts";
      2 import { OAuth2FlowRepository } from "#core/application/oauth2/flow_repository.ts";
      3 import { InvalidOAuth2Flow } from "#core/domain/oauth2flow.ts";
      4 import { InvalidToken, Token } from "#core/domain/token.ts";
      5 import { EntityNotFound } from "../repository_error.ts";
      6 
      7 export type OAuth2FlowUserInfoRequest = {
      8   accessToken: string;
      9 };
     10 
     11 export type OAuth2FlowUserInfoResponse = {
     12   exists: boolean;
     13   uuid: string | null;
     14   email: string | null;
     15   emailVerified: boolean;
     16   phoneNumber: string | null;
     17   phoneNumberVerified: boolean;
     18   firstName: string | null;
     19   lastName: string | null;
     20   birthDate: Date | null;
     21   sex: string | null;
     22   nationality: string | null;
     23   country: string | null;
     24   idDocumentVerified: boolean;
     25   idDocumentRegistered: boolean;
     26 };
     27 
     28 export class OAuth2FlowUserInfoUseCase {
     29   constructor(
     30     private readonly flowRepo: OAuth2FlowRepository,
     31     private readonly customerInfo: CustomerInfoUseCase,
     32   ) {
     33   }
     34 
     35   async execute(
     36     { accessToken }: OAuth2FlowUserInfoRequest,
     37   ): Promise<OAuth2FlowUserInfoResponse> {
     38     try {
     39       const token = new Token(accessToken);
     40       const flow = await this.flowRepo.findByToken(token);
     41       flow.authenticate(token);
     42       const uuid = flow.resourceOwner!;
     43       const scope = flow.scope;
     44       const { exists, ...info } = await this.customerInfo.execute({
     45         uuid: uuid.toString(),
     46       });
     47       return {
     48         exists,
     49         uuid: info.uuid,
     50         email: scope.contains("email") ? info.email : null,
     51         emailVerified: scope.contains("email") ? info.emailVerified : false,
     52         phoneNumber: scope.contains("phone-number") ? info.phoneNumber : null,
     53         phoneNumberVerified: scope.contains("phone-number")
     54           ? info.phoneNumberVerified
     55           : false,
     56         firstName: scope.contains("id-document") ? info.firstName : null,
     57         lastName: scope.contains("id-document") ? info.lastName : null,
     58         birthDate: scope.contains("id-document") ? info.birthDate : null,
     59         sex: scope.contains("id-document") ? info.sex : null,
     60         nationality: scope.contains("id-document") ? info.nationality : null,
     61         country: scope.contains("id-document") ? info.country : null,
     62         idDocumentVerified: scope.contains("id-document")
     63           ? info.idDocumentVerified
     64           : false,
     65         idDocumentRegistered: scope.contains("id-document")
     66           ? info.idDocumentRegistered
     67           : false,
     68       };
     69     } catch (error) {
     70       if (
     71         error instanceof InvalidToken ||
     72         error instanceof EntityNotFound ||
     73         error instanceof InvalidOAuth2Flow
     74       ) {
     75         return {
     76           exists: false,
     77           uuid: null,
     78           email: null,
     79           emailVerified: false,
     80           phoneNumber: null,
     81           phoneNumberVerified: false,
     82           firstName: null,
     83           lastName: null,
     84           birthDate: null,
     85           sex: null,
     86           nationality: null,
     87           country: null,
     88           idDocumentVerified: false,
     89           idDocumentRegistered: false,
     90         };
     91       }
     92       throw error;
     93     }
     94   }
     95 }