1
0
mirror of https://github.com/bitwarden/browser synced 2026-02-22 04:14:04 +00:00

RegistrationFinishComponent - read param on init and set state upon successful login

This commit is contained in:
rr-bw
2025-10-25 22:16:16 -07:00
parent bcc92387b2
commit 07258f1803
7 changed files with 79 additions and 0 deletions

View File

@@ -20,6 +20,9 @@ import {
} from "@bitwarden/common/key-management/crypto/models/enc-string";
import { LogService } from "@bitwarden/common/platform/abstractions/log.service";
import { KeyService } from "@bitwarden/key-management";
import { UserId } from "@bitwarden/user-core";
import { SetupPremiumService } from "../../../../billing/individual/premium/setup-premium.service";
export class WebRegistrationFinishService
extends DefaultRegistrationFinishService
@@ -32,6 +35,7 @@ export class WebRegistrationFinishService
private policyApiService: PolicyApiServiceAbstraction,
private logService: LogService,
private policyService: PolicyService,
private setupPremiumService: SetupPremiumService,
) {
super(keyService, accountApiService);
}
@@ -123,4 +127,8 @@ export class WebRegistrationFinishService
return registerRequest;
}
async establishIntentToSetupPremium(userId: UserId) {
await this.setupPremiumService.setIntentToSetupPremium(true, userId);
}
}

View File

@@ -0,0 +1,33 @@
import { Injectable } from "@angular/core";
import { firstValueFrom } from "rxjs";
import { BILLING_DISK_LOCAL, StateProvider, UserKeyDefinition } from "@bitwarden/state";
import { UserId } from "@bitwarden/user-core";
export const INTENT_TO_SETUP_PREMIUM_KEY = new UserKeyDefinition<boolean>(
BILLING_DISK_LOCAL,
"intentToSetupPremium",
{
deserializer: (value) => value,
clearOn: [],
},
);
@Injectable({
providedIn: "root",
})
export class SetupPremiumService {
constructor(private stateProvider: StateProvider) {}
async setIntentToSetupPremium(intent: boolean, userId: UserId) {
await this.stateProvider.setUserState(INTENT_TO_SETUP_PREMIUM_KEY, intent, userId);
}
async getIntentToSetupPremium(userId: UserId) {
await firstValueFrom(this.stateProvider.getUserState$(INTENT_TO_SETUP_PREMIUM_KEY, userId));
}
async clearIntentToSetupPremium(userId: UserId) {
await this.stateProvider.setUserState(INTENT_TO_SETUP_PREMIUM_KEY, null, userId);
}
}

View File

@@ -127,6 +127,7 @@ import {
WebSetInitialPasswordService,
} from "../auth";
import { WebSsoComponentService } from "../auth/core/services/login/web-sso-component.service";
import { SetupPremiumService } from "../billing/individual/premium/setup-premium.service";
import { HtmlStorageService } from "../core/html-storage.service";
import { I18nService } from "../core/i18n.service";
import { WebFileDownloadService } from "../core/web-file-download.service";
@@ -266,6 +267,7 @@ const safeProviders: SafeProvider[] = [
PolicyApiServiceAbstraction,
LogService,
PolicyService,
SetupPremiumService,
],
}),
safeProvider({

View File

@@ -9,6 +9,7 @@ import {
} from "@bitwarden/common/key-management/crypto/models/enc-string";
import { KeysRequest } from "@bitwarden/common/models/request/keys.request";
import { KeyService } from "@bitwarden/key-management";
import { UserId } from "@bitwarden/user-core";
import { PasswordInputResult } from "../../input-password/password-input-result";
@@ -96,4 +97,8 @@ export class DefaultRegistrationFinishService implements RegistrationFinishServi
return registerFinishRequest;
}
async establishIntentToSetupPremium(userId: UserId) {
// no-op
}
}

View File

@@ -67,6 +67,8 @@ export class RegistrationFinishComponent implements OnInit, OnDestroy {
masterPasswordPolicyOptions: MasterPasswordPolicyOptions | null = null;
intendsToSetupPremium = false;
constructor(
private activatedRoute: ActivatedRoute,
private router: Router,
@@ -126,6 +128,25 @@ export class RegistrationFinishComponent implements OnInit, OnDestroy {
this.providerInviteToken = qParams.providerInviteToken;
this.providerUserId = qParams.providerUserId;
}
// -- Proof of Concept (start) --
const mockParams = {
fromMarketing: "premium", // `&fromMarketing=premium`
};
if (mockParams.fromMarketing && mockParams.fromMarketing === "premium") {
this.intendsToSetupPremium = true;
}
// Note: To avoid magic strings, we can create an enum-like type and use it above:
// ```
// export const MarketingInitiative = Object.freeze({
// Premium: "premium",
// Families: "families",
// // Other variants in the future
// } as const);
// -- Proof of Concept (end) --
}
private async initOrgInviteFlowIfPresent(): Promise<boolean> {
@@ -190,6 +211,12 @@ export class RegistrationFinishComponent implements OnInit, OnDestroy {
await this.loginSuccessHandlerService.run(authenticationResult.userId);
if (this.intendsToSetupPremium) {
await this.registrationFinishService.establishIntentToSetupPremium(
authenticationResult.userId,
);
}
await this.router.navigate(["/vault"]);
} catch (e) {
// If login errors, redirect to login page per product. Don't show error

View File

@@ -1,4 +1,5 @@
import { MasterPasswordPolicyOptions } from "@bitwarden/common/admin-console/models/domain/master-password-policy-options";
import { UserId } from "@bitwarden/user-core";
import { PasswordInputResult } from "../../input-password/password-input-result";
@@ -39,4 +40,6 @@ export abstract class RegistrationFinishService {
providerInviteToken?: string,
providerUserId?: string,
): Promise<void>;
abstract establishIntentToSetupPremium(userId: UserId): Promise<void>;
}

View File

@@ -40,6 +40,7 @@ export const AUTO_CONFIRM = new StateDefinition("autoConfirm", "disk");
// Billing
export const BILLING_DISK = new StateDefinition("billing", "disk");
export const BILLING_DISK_LOCAL = new StateDefinition("billing", "disk", { web: "disk-local" });
// Auth