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 @@
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 };
+ }
}