import { Directive } from "@angular/core" ; import { ActivatedRoute , Router } from "@angular/router" ; import { first } from "rxjs/operators" ; import { ApiService } from "jslib-common/abstractions/api.service" ; import { CryptoService } from "jslib-common/abstractions/crypto.service" ; import { I18nService } from "jslib-common/abstractions/i18n.service" ; import { MessagingService } from "jslib-common/abstractions/messaging.service" ; import { PasswordGenerationService } from "jslib-common/abstractions/passwordGeneration.service" ; import { PlatformUtilsService } from "jslib-common/abstractions/platformUtils.service" ; import { PolicyService } from "jslib-common/abstractions/policy.service" ; import { StateService } from "jslib-common/abstractions/state.service" ; import { SyncService } from "jslib-common/abstractions/sync.service" ; import { EncString } from "jslib-common/models/domain/encString" ; import { SymmetricCryptoKey } from "jslib-common/models/domain/symmetricCryptoKey" ; import { KeysRequest } from "jslib-common/models/request/keysRequest" ; import { OrganizationUserResetPasswordEnrollmentRequest } from "jslib-common/models/request/organizationUserResetPasswordEnrollmentRequest" ; import { SetPasswordRequest } from "jslib-common/models/request/setPasswordRequest" ; import { ChangePasswordComponent as BaseChangePasswordComponent } from "./change-password.component" ; import { HashPurpose } from "jslib-common/enums/hashPurpose" ; import { KdfType } from "jslib-common/enums/kdfType" ; import { Utils } from "jslib-common/misc/utils" ; @ Directive ( ) export class SetPasswordComponent extends BaseChangePasswordComponent { syncLoading : boolean = true ; showPassword : boolean = false ; hint : string = "" ; identifier : string = null ; orgId : string ; resetPasswordAutoEnroll = false ; onSuccessfulChangePassword : ( ) => Promise < any > ; successRoute = "vault" ; constructor ( i18nService , cryptoService , messagingService , passwordGenerationService , platformUtilsService , policyService , protected router , private apiService , private syncService , private route , stateService ) { super ( i18nService , cryptoService , messagingService , passwordGenerationService , platformUtilsService , policyService , stateService ) ; } async ngOnInit ( ) { await this . syncService . fullSync ( true ) ; this . syncLoading = false ; this . route . queryParams . pipe ( first ( ) ) . subscribe ( async ( qParams ) => { if ( qParams . identifier != null ) { this . identifier = qParams . identifier ; } } ) ; if ( this . identifier != null ) { try { const response = await this . apiService . getOrganizationAutoEnrollStatus ( this . identifier ) ; this . orgId = response . id ; this . resetPasswordAutoEnroll = response . resetPasswordEnabled ; this . enforcedPolicyOptions = await this . policyService . getMasterPasswordPoliciesForInvitedUsers ( this . orgId ) ; } catch { this . platformUtilsService . showToast ( "error" , null , this . i18nService . t ( "errorOccurred" ) ) ; } } super . ngOnInit ( ) ; } async setupSubmitActions ( ) { this . kdf = KdfType . PBKDF2_SHA256 ; const useLowerKdf = this . platformUtilsService . isIE ( ) ; this . kdfIterations = useLowerKdf ? 10000 : 100000 ; return true ; } async performSubmitActions ( masterPasswordHash , key , encKey ) { const keys = await this . cryptoService . makeKeyPair ( encKey [ 0 ] ) ; const request = new SetPasswordRequest ( masterPasswordHash , encKey [ 1 ] . encryptedString , this . hint , this . kdf , this . kdfIterations , this . identifier , new KeysRequest ( keys [ 0 ] , keys [ 1 ] . encryptedString ) ) ; try { if ( this . resetPasswordAutoEnroll ) { this . formPromise = this . apiService . setPassword ( request ) . then ( async ( ) => { await this . onSetPasswordSuccess ( key , encKey , keys ) ; return this . apiService . getOrganizationKeys ( this . orgId ) ; } ) . then ( async ( response ) => { if ( response == null ) { throw new Error ( this . i18nService . t ( "resetPasswordOrgKeysError" ) ) ; } const userId = await this . stateService . getUserId ( ) ; const publicKey = Utils . fromB64ToArray ( response . publicKey ) ; const userEncKey = await this . cryptoService . getEncKey ( ) ; const encryptedKey = await this . cryptoService . rsaEncrypt ( userEncKey . key , publicKey . buffer ) ; const resetRequest = new OrganizationUserResetPasswordEnrollmentRequest ( ) ; resetRequest . resetPasswordKey = encryptedKey . encryptedString ; return this . apiService . putOrganizationUserResetPasswordEnrollment ( this . orgId , userId , resetRequest ) ; } ) ; } else { this . formPromise = this . apiService . setPassword ( request ) . then ( async ( ) => { await this . onSetPasswordSuccess ( key , encKey , keys ) ; } ) ; } await this . formPromise ; if ( this . onSuccessfulChangePassword != null ) { this . onSuccessfulChangePassword ( ) ; } else { this . router . navigate ( [ this . successRoute ] ) ; } } catch { this . platformUtilsService . showToast ( "error" , null , this . i18nService . t ( "errorOccurred" ) ) ; } } togglePassword ( confirmField ) { this . showPassword = ! this . showPassword ; document . getElementById ( confirmField ? "masterPasswordRetype" : "masterPassword" ) . focus ( ) ; } private async onSetPasswordSuccess ( key , encKey , keys ) { await this . stateService . setKdfType ( this . kdf ) ; await this . stateService . setKdfIterations ( this . kdfIterations ) ; await this . cryptoService . setKey ( key ) ; await this . cryptoService . setEncKey ( encKey [ 1 ] . encryptedString ) ; await this . cryptoService . setEncPrivateKey ( keys [ 1 ] . encryptedString ) ; const localKeyHash = await this . cryptoService . hashPassword ( this . masterPassword , key , HashPurpose . LocalAuthorization ) ; await this . cryptoService . setKeyHash ( localKeyHash ) ; } }