1
0
mirror of https://github.com/bitwarden/browser.git synced 2024-11-25 12:15:18 +01:00

[PM-5500] Implement StateProvider in RouterService (#8119)

* implement StateProvider in RouterService

* Remove 'export'

Co-authored-by: Andreas Coroiu <acoroiu@bitwarden.com>

* Skip parameter

Co-authored-by: Andreas Coroiu <acoroiu@bitwarden.com>

---------

Co-authored-by: Andreas Coroiu <acoroiu@bitwarden.com>
This commit is contained in:
rr-bw 2024-04-02 10:16:42 -07:00 committed by GitHub
parent a6e178f1e6
commit f79d159277
No known key found for this signature in database
GPG Key ID: B5690EEEBB952194
5 changed files with 25 additions and 36 deletions

View File

@ -1,14 +1,31 @@
import { Injectable } from "@angular/core"; import { Injectable } from "@angular/core";
import { Title } from "@angular/platform-browser"; import { Title } from "@angular/platform-browser";
import { ActivatedRoute, NavigationEnd, Router } from "@angular/router"; import { ActivatedRoute, NavigationEnd, Router } from "@angular/router";
import { filter } from "rxjs"; import { filter, firstValueFrom } from "rxjs";
import { I18nService } from "@bitwarden/common/platform/abstractions/i18n.service"; import { I18nService } from "@bitwarden/common/platform/abstractions/i18n.service";
import { StateService } from "@bitwarden/common/platform/abstractions/state.service";
import { Utils } from "@bitwarden/common/platform/misc/utils"; import { Utils } from "@bitwarden/common/platform/misc/utils";
import {
KeyDefinition,
ROUTER_DISK,
StateProvider,
GlobalState,
} from "@bitwarden/common/platform/state";
const DEEP_LINK_REDIRECT_URL = new KeyDefinition(ROUTER_DISK, "deepLinkRedirectUrl", {
deserializer: (value: string) => value,
});
@Injectable() @Injectable()
export class RouterService { export class RouterService {
/**
* The string value of the URL the user tried to navigate to while unauthenticated.
*
* Developed to allow users to deep link even when the navigation gets interrupted
* by the authentication process.
*/
private deepLinkRedirectUrlState: GlobalState<string>;
private previousUrl: string = undefined; private previousUrl: string = undefined;
private currentUrl: string = undefined; private currentUrl: string = undefined;
@ -16,9 +33,11 @@ export class RouterService {
private router: Router, private router: Router,
private activatedRoute: ActivatedRoute, private activatedRoute: ActivatedRoute,
private titleService: Title, private titleService: Title,
private stateService: StateService, private stateProvider: StateProvider,
i18nService: I18nService, i18nService: I18nService,
) { ) {
this.deepLinkRedirectUrlState = this.stateProvider.getGlobal(DEEP_LINK_REDIRECT_URL);
this.currentUrl = this.router.url; this.currentUrl = this.router.url;
router.events router.events
@ -67,14 +86,14 @@ export class RouterService {
* @param url URL being saved to the Global State * @param url URL being saved to the Global State
*/ */
async persistLoginRedirectUrl(url: string): Promise<void> { async persistLoginRedirectUrl(url: string): Promise<void> {
await this.stateService.setDeepLinkRedirectUrl(url); await this.deepLinkRedirectUrlState.update(() => url);
} }
/** /**
* Fetch and clear persisted LoginRedirectUrl if present in state * Fetch and clear persisted LoginRedirectUrl if present in state
*/ */
async getAndClearLoginRedirectUrl(): Promise<string> | undefined { async getAndClearLoginRedirectUrl(): Promise<string> | undefined {
const persistedPreLoginUrl = await this.stateService.getDeepLinkRedirectUrl(); const persistedPreLoginUrl = await firstValueFrom(this.deepLinkRedirectUrlState.state$);
if (!Utils.isNullOrEmpty(persistedPreLoginUrl)) { if (!Utils.isNullOrEmpty(persistedPreLoginUrl)) {
await this.persistLoginRedirectUrl(null); await this.persistLoginRedirectUrl(null);

View File

@ -243,18 +243,5 @@ export abstract class StateService<T extends Account = Account> {
setVaultTimeoutAction: (value: string, options?: StorageOptions) => Promise<void>; setVaultTimeoutAction: (value: string, options?: StorageOptions) => Promise<void>;
getApproveLoginRequests: (options?: StorageOptions) => Promise<boolean>; getApproveLoginRequests: (options?: StorageOptions) => Promise<boolean>;
setApproveLoginRequests: (value: boolean, options?: StorageOptions) => Promise<void>; setApproveLoginRequests: (value: boolean, options?: StorageOptions) => Promise<void>;
/**
* fetches string value of URL user tried to navigate to while unauthenticated.
* @param options Defines the storage options for the URL; Defaults to session Storage.
* @returns route called prior to successful login.
*/
getDeepLinkRedirectUrl: (options?: StorageOptions) => Promise<string>;
/**
* Store URL in session storage by default, but can be configured. Developed to handle
* unauthN interrupted navigation.
* @param url URL of route
* @param options Defines the storage options for the URL; Defaults to session Storage.
*/
setDeepLinkRedirectUrl: (url: string, options?: StorageOptions) => Promise<void>;
nextUpActiveUser: () => Promise<UserId>; nextUpActiveUser: () => Promise<UserId>;
} }

View File

@ -4,5 +4,4 @@ export class GlobalState {
vaultTimeoutAction?: string; vaultTimeoutAction?: string;
enableBrowserIntegration?: boolean; enableBrowserIntegration?: boolean;
enableBrowserIntegrationFingerprint?: boolean; enableBrowserIntegrationFingerprint?: boolean;
deepLinkRedirectUrl?: string;
} }

View File

@ -1173,23 +1173,6 @@ export class StateService<
); );
} }
async getDeepLinkRedirectUrl(options?: StorageOptions): Promise<string> {
return (
await this.getGlobals(this.reconcileOptions(options, await this.defaultOnDiskOptions()))
)?.deepLinkRedirectUrl;
}
async setDeepLinkRedirectUrl(url: string, options?: StorageOptions): Promise<void> {
const globals = await this.getGlobals(
this.reconcileOptions(options, await this.defaultOnDiskOptions()),
);
globals.deepLinkRedirectUrl = url;
await this.saveGlobals(
globals,
this.reconcileOptions(options, await this.defaultOnDiskOptions()),
);
}
protected async getGlobals(options: StorageOptions): Promise<TGlobalState> { protected async getGlobals(options: StorageOptions): Promise<TGlobalState> {
let globals: TGlobalState; let globals: TGlobalState;
if (this.useMemory(options.storageLocation)) { if (this.useMemory(options.storageLocation)) {

View File

@ -38,6 +38,7 @@ export const BILLING_DISK = new StateDefinition("billing", "disk");
export const KEY_CONNECTOR_DISK = new StateDefinition("keyConnector", "disk"); export const KEY_CONNECTOR_DISK = new StateDefinition("keyConnector", "disk");
export const ACCOUNT_MEMORY = new StateDefinition("account", "memory"); export const ACCOUNT_MEMORY = new StateDefinition("account", "memory");
export const AVATAR_DISK = new StateDefinition("avatar", "disk", { web: "disk-local" }); export const AVATAR_DISK = new StateDefinition("avatar", "disk", { web: "disk-local" });
export const ROUTER_DISK = new StateDefinition("router", "disk");
export const LOGIN_EMAIL_DISK = new StateDefinition("loginEmail", "disk", { export const LOGIN_EMAIL_DISK = new StateDefinition("loginEmail", "disk", {
web: "disk-local", web: "disk-local",
}); });