diff --git a/apps/web/src/app/accounts/register-form/register-form.component.html b/apps/web/src/app/accounts/register-form/register-form.component.html index e147f463cb..56364086ff 100644 --- a/apps/web/src/app/accounts/register-form/register-form.component.html +++ b/apps/web/src/app/accounts/register-form/register-form.component.html @@ -113,16 +113,21 @@
- {{ "createAccount" | i18n }} - - - {{ "logIn" | i18n }} - + + {{ "createAccount" | i18n }} + + + {{ "logIn" | i18n }} + + + + {{ "logIn" | i18n }} +
diff --git a/libs/angular/src/components/register.component.ts b/libs/angular/src/components/register.component.ts index 1dd1b77931..66bf205352 100644 --- a/libs/angular/src/components/register.component.ts +++ b/libs/angular/src/components/register.component.ts @@ -68,6 +68,8 @@ export class RegisterComponent extends CaptchaProtectedComponent implements OnIn protected successRoute = "login"; + protected accountCreated = false; + constructor( protected formValidationErrorService: FormValidationErrorsService, protected formBuilder: UntypedFormBuilder, @@ -92,100 +94,33 @@ export class RegisterComponent extends CaptchaProtectedComponent implements OnIn async submit(showToast = true) { let email = this.formGroup.get("email")?.value; - let name = this.formGroup.get("name")?.value; - const masterPassword = this.formGroup.get("masterPassword")?.value; - const hint = this.formGroup.get("hint")?.value; - - this.formGroup.markAllAsTouched(); - this.showErrorSummary = true; - - if (this.formGroup.get("acceptPolicies").hasError("required")) { - this.platformUtilsService.showToast( - "error", - this.i18nService.t("errorOccurred"), - this.i18nService.t("acceptPoliciesRequired") - ); - return; - } - - //web - if (this.formGroup.invalid && !showToast) { - return; - } - - //desktop, browser - if (this.formGroup.invalid && showToast) { - const errorText = this.getErrorToastMessage(); - this.platformUtilsService.showToast("error", this.i18nService.t("errorOccurred"), errorText); - return; - } - - if (this.passwordStrengthResult != null && this.passwordStrengthResult.score < 3) { - const result = await this.platformUtilsService.showDialog( - this.i18nService.t("weakMasterPasswordDesc"), - this.i18nService.t("weakMasterPassword"), - this.i18nService.t("yes"), - this.i18nService.t("no"), - "warning" - ); - if (!result) { - return; - } - } - - name = name === "" ? null : name; email = email.trim().toLowerCase(); - const kdf = DEFAULT_KDF_TYPE; - const kdfIterations = DEFAULT_KDF_ITERATIONS; - const key = await this.cryptoService.makeKey(masterPassword, email, kdf, kdfIterations); - const encKey = await this.cryptoService.makeEncKey(key); - const hashedPassword = await this.cryptoService.hashPassword(masterPassword, key); - const keys = await this.cryptoService.makeKeyPair(encKey[0]); - const request = new RegisterRequest( - email, - name, - hashedPassword, - hint, - encKey[1].encryptedString, - kdf, - kdfIterations, - this.referenceData, - this.captchaToken - ); - request.keys = new KeysRequest(keys[0], keys[1].encryptedString); - const orgInvite = await this.stateService.getOrganizationInvitation(); - if (orgInvite != null && orgInvite.token != null && orgInvite.organizationUserId != null) { - request.token = orgInvite.token; - request.organizationUserId = orgInvite.organizationUserId; - } - + let name = this.formGroup.get("name")?.value; + name = name === "" ? null : name; // Why do we do this? + const masterPassword = this.formGroup.get("masterPassword")?.value; try { - this.formPromise = this.apiService.postRegister(request); - try { - await this.formPromise; - } catch (e) { - if (this.handleCaptchaRequired(e)) { + if (!this.accountCreated) { + const registerResponse = await this.registerAccount( + await this.buildRegisterRequest(email, masterPassword, name), + showToast + ); + if (registerResponse.captchaRequired) { return; - } else { - throw e; } + this.accountCreated = true; } - if (this.isInTrialFlow) { - this.platformUtilsService.showToast( - "success", - null, - this.i18nService.t("trialAccountCreated") - ); - //login user here - const credentials = new PasswordLogInCredentials( - email, - masterPassword, - this.captchaToken, - null - ); - await this.authService.logIn(credentials); - + if (!this.accountCreated) { + this.platformUtilsService.showToast( + "success", + null, + this.i18nService.t("trialAccountCreated") + ); + } + const loginResponse = await this.logIn(email, masterPassword, this.captchaToken); + if (loginResponse.captchaRequired) { + return; + } this.createdAccount.emit(this.formGroup.get("email")?.value); } else { this.platformUtilsService.showToast( @@ -247,4 +182,111 @@ export class RegisterComponent extends CaptchaProtectedComponent implements OnIn return !ctrlValue && this.showTerms ? { required: true } : null; }; } + + private async validateRegistration(showToast: boolean) { + this.formGroup.markAllAsTouched(); + this.showErrorSummary = true; + + if (this.formGroup.get("acceptPolicies").hasError("required")) { + this.platformUtilsService.showToast( + "error", + this.i18nService.t("errorOccurred"), + this.i18nService.t("acceptPoliciesRequired") + ); + return; + } + + //web + if (this.formGroup.invalid && !showToast) { + return; + } + + //desktop, browser + if (this.formGroup.invalid && showToast) { + const errorText = this.getErrorToastMessage(); + this.platformUtilsService.showToast("error", this.i18nService.t("errorOccurred"), errorText); + return; + } + + if (this.passwordStrengthResult != null && this.passwordStrengthResult.score < 3) { + const result = await this.platformUtilsService.showDialog( + this.i18nService.t("weakMasterPasswordDesc"), + this.i18nService.t("weakMasterPassword"), + this.i18nService.t("yes"), + this.i18nService.t("no"), + "warning" + ); + if (!result) { + return; + } + } + } + + private async buildRegisterRequest( + email: string, + masterPassword: string, + name: string + ): Promise { + const hint = this.formGroup.get("hint")?.value; + const kdf = DEFAULT_KDF_TYPE; + const kdfIterations = DEFAULT_KDF_ITERATIONS; + const key = await this.cryptoService.makeKey(masterPassword, email, kdf, kdfIterations); + const encKey = await this.cryptoService.makeEncKey(key); + const hashedPassword = await this.cryptoService.hashPassword(masterPassword, key); + const keys = await this.cryptoService.makeKeyPair(encKey[0]); + const request = new RegisterRequest( + email, + name, + hashedPassword, + hint, + encKey[1].encryptedString, + kdf, + kdfIterations, + this.referenceData, + this.captchaToken + ); + request.keys = new KeysRequest(keys[0], keys[1].encryptedString); + const orgInvite = await this.stateService.getOrganizationInvitation(); + if (orgInvite != null && orgInvite.token != null && orgInvite.organizationUserId != null) { + request.token = orgInvite.token; + request.organizationUserId = orgInvite.organizationUserId; + } + return request; + } + + private async registerAccount( + request: RegisterRequest, + showToast: boolean + ): Promise<{ captchaRequired: boolean }> { + await this.validateRegistration(showToast); + this.formPromise = this.apiService.postRegister(request); + try { + await this.formPromise; + return { captchaRequired: false }; + } catch (e) { + if (this.handleCaptchaRequired(e)) { + return { captchaRequired: true }; + } else { + throw e; + } + } + } + + private async logIn( + email: string, + masterPassword: string, + captchaBypassToken: string + ): Promise<{ captchaRequired: boolean }> { + const credentials = new PasswordLogInCredentials( + email, + masterPassword, + captchaBypassToken, + null + ); + const loginResponse = await this.authService.logIn(credentials); + if (this.handleCaptchaRequired(loginResponse)) { + return { captchaRequired: true }; + } + return { captchaRequired: false }; + } }