From 3868dcbc601861ae2fbeeffa0802fec2e7bad506 Mon Sep 17 00:00:00 2001 From: Alec Rippberger Date: Wed, 9 Oct 2024 22:31:43 -0500 Subject: [PATCH] Get clientType via service. --- .../extension-login-component.service.spec.ts | 37 ++++++++- .../extension-login-component.service.ts | 27 ++++++- .../src/app/services/services.module.ts | 4 +- .../desktop-login-component.service.spec.ts | 46 ++++++++--- .../login/desktop-login-component.service.ts | 30 ++++++-- .../login/web-login-component.service.spec.ts | 76 ++++++++++--------- .../login/web-login-component.service.ts | 39 +++++++--- apps/web/src/app/core/core.module.ts | 10 ++- 8 files changed, 205 insertions(+), 64 deletions(-) diff --git a/apps/browser/src/auth/popup/login/extension-login-component.service.spec.ts b/apps/browser/src/auth/popup/login/extension-login-component.service.spec.ts index 54137fd5c6d..a2d703cb031 100644 --- a/apps/browser/src/auth/popup/login/extension-login-component.service.spec.ts +++ b/apps/browser/src/auth/popup/login/extension-login-component.service.spec.ts @@ -1,8 +1,15 @@ import { TestBed } from "@angular/core/testing"; +import { MockProxy, mock } from "jest-mock-extended"; import { DefaultLoginComponentService } from "@bitwarden/auth/angular"; +import { SsoLoginServiceAbstraction } from "@bitwarden/common/auth/abstractions/sso-login.service.abstraction"; +import { CryptoFunctionService } from "@bitwarden/common/platform/abstractions/crypto-function.service"; +import { EnvironmentService } from "@bitwarden/common/platform/abstractions/environment.service"; +import { PlatformUtilsService } from "@bitwarden/common/platform/abstractions/platform-utils.service"; +import { PasswordGenerationServiceAbstraction } from "@bitwarden/generator-legacy"; import { flagEnabled } from "../../../platform/flags"; +import { BrowserPlatformUtilsService } from "../../../platform/services/platform-utils/browser-platform-utils.service"; import { ExtensionLoginComponentService } from "./extension-login-component.service"; @@ -12,12 +19,38 @@ jest.mock("../../../platform/flags", () => ({ describe("ExtensionLoginComponentService", () => { let service: ExtensionLoginComponentService; + let cryptoFunctionService: MockProxy; + let environmentService: MockProxy; + let passwordGenerationService: MockProxy; + let platformUtilsService: MockProxy; + let ssoLoginService: MockProxy; beforeEach(() => { + cryptoFunctionService = mock(); + environmentService = mock(); + passwordGenerationService = mock(); + platformUtilsService = mock(); + ssoLoginService = mock(); + TestBed.configureTestingModule({ providers: [ - ExtensionLoginComponentService, - { provide: DefaultLoginComponentService, useClass: ExtensionLoginComponentService }, + { + provide: ExtensionLoginComponentService, + useFactory: () => + new ExtensionLoginComponentService( + cryptoFunctionService, + environmentService, + passwordGenerationService, + platformUtilsService, + ssoLoginService, + ), + }, + { provide: DefaultLoginComponentService, useExisting: ExtensionLoginComponentService }, + { provide: CryptoFunctionService, useValue: cryptoFunctionService }, + { provide: EnvironmentService, useValue: environmentService }, + { provide: PasswordGenerationServiceAbstraction, useValue: passwordGenerationService }, + { provide: PlatformUtilsService, useValue: platformUtilsService }, + { provide: SsoLoginServiceAbstraction, useValue: ssoLoginService }, ], }); service = TestBed.inject(ExtensionLoginComponentService); diff --git a/apps/browser/src/auth/popup/login/extension-login-component.service.ts b/apps/browser/src/auth/popup/login/extension-login-component.service.ts index d3dc9ec771e..a050bf131d8 100644 --- a/apps/browser/src/auth/popup/login/extension-login-component.service.ts +++ b/apps/browser/src/auth/popup/login/extension-login-component.service.ts @@ -1,13 +1,36 @@ +import { Injectable } from "@angular/core"; + import { DefaultLoginComponentService, LoginComponentService } from "@bitwarden/auth/angular"; -import { ClientType } from "@bitwarden/common/enums"; +import { SsoLoginServiceAbstraction } from "@bitwarden/common/auth/abstractions/sso-login.service.abstraction"; +import { CryptoFunctionService } from "@bitwarden/common/platform/abstractions/crypto-function.service"; +import { EnvironmentService } from "@bitwarden/common/platform/abstractions/environment.service"; +import { PlatformUtilsService } from "@bitwarden/common/platform/abstractions/platform-utils.service"; +import { PasswordGenerationServiceAbstraction } from "@bitwarden/generator-legacy"; import { flagEnabled } from "../../../platform/flags"; +@Injectable() export class ExtensionLoginComponentService extends DefaultLoginComponentService implements LoginComponentService { - clientType = ClientType.Browser; + constructor( + cryptoFunctionService: CryptoFunctionService, + environmentService: EnvironmentService, + passwordGenerationService: PasswordGenerationServiceAbstraction, + platformUtilsService: PlatformUtilsService, + ssoLoginService: SsoLoginServiceAbstraction, + ) { + super( + cryptoFunctionService, + environmentService, + passwordGenerationService, + platformUtilsService, + ssoLoginService, + ); + this.clientType = this.platformUtilsService.getClientType(); + } + isLoginViaAuthRequestSupported(): boolean { return flagEnabled("showPasswordless"); } diff --git a/apps/desktop/src/app/services/services.module.ts b/apps/desktop/src/app/services/services.module.ts index e6ca38e3384..5bceb41056b 100644 --- a/apps/desktop/src/app/services/services.module.ts +++ b/apps/desktop/src/app/services/services.module.ts @@ -83,7 +83,7 @@ import { MemoryStorageService as MemoryStorageServiceForStateProviders } from "@ import { ThemeStateService } from "@bitwarden/common/platform/theming/theme-state.service"; import { VaultTimeoutStringType } from "@bitwarden/common/types/vault-timeout.type"; import { CipherService as CipherServiceAbstraction } from "@bitwarden/common/vault/abstractions/cipher.service"; -import { DialogService } from "@bitwarden/components"; +import { DialogService, ToastService } from "@bitwarden/components"; import { PasswordGenerationServiceAbstraction } from "@bitwarden/generator-legacy"; import { BiometricStateService, BiometricsService } from "@bitwarden/key-management"; @@ -329,6 +329,8 @@ const safeProviders: SafeProvider[] = [ PasswordGenerationServiceAbstraction, PlatformUtilsServiceAbstraction, SsoLoginServiceAbstraction, + I18nServiceAbstraction, + ToastService, ], }), safeProvider({ diff --git a/apps/desktop/src/auth/login/desktop-login-component.service.spec.ts b/apps/desktop/src/auth/login/desktop-login-component.service.spec.ts index e2c93165465..053397f130c 100644 --- a/apps/desktop/src/auth/login/desktop-login-component.service.spec.ts +++ b/apps/desktop/src/auth/login/desktop-login-component.service.spec.ts @@ -1,13 +1,17 @@ import { TestBed } from "@angular/core/testing"; -import { MockProxy } from "jest-mock-extended"; +import { MockProxy, mock } from "jest-mock-extended"; import { DefaultLoginComponentService } from "@bitwarden/auth/angular"; import { SsoLoginServiceAbstraction } from "@bitwarden/common/auth/abstractions/sso-login.service.abstraction"; import { CryptoFunctionService } from "@bitwarden/common/platform/abstractions/crypto-function.service"; +import { EnvironmentService } from "@bitwarden/common/platform/abstractions/environment.service"; import { I18nService } from "@bitwarden/common/platform/abstractions/i18n.service"; +import { PlatformUtilsService } from "@bitwarden/common/platform/abstractions/platform-utils.service"; import { ToastService } from "@bitwarden/components"; import { PasswordGenerationServiceAbstraction } from "@bitwarden/generator-legacy"; +import { ElectronPlatformUtilsService } from "../../platform/services/electron-platform-utils.service"; + import { DesktopLoginComponentService } from "./desktop-login-component.service"; (global as any).ipc = { @@ -23,22 +27,46 @@ import { DesktopLoginComponentService } from "./desktop-login-component.service" describe("DesktopLoginComponentService", () => { let service: DesktopLoginComponentService; + let cryptoFunctionService: MockProxy; + let environmentService: MockProxy; + let passwordGenerationService: MockProxy; + let platformUtilsService: MockProxy; + let ssoLoginService: MockProxy; let i18nService: MockProxy; let toastService: MockProxy; - let ssoLoginService: MockProxy; - let passwordGenerationService: MockProxy; - let cryptoFunctionService: MockProxy; beforeEach(() => { + cryptoFunctionService = mock(); + environmentService = mock(); + passwordGenerationService = mock(); + platformUtilsService = mock(); + ssoLoginService = mock(); + i18nService = mock(); + toastService = mock(); + TestBed.configureTestingModule({ providers: [ - DesktopLoginComponentService, - { provide: DefaultLoginComponentService, useClass: DesktopLoginComponentService }, + { + provide: DesktopLoginComponentService, + useFactory: () => + new DesktopLoginComponentService( + cryptoFunctionService, + environmentService, + passwordGenerationService, + platformUtilsService, + ssoLoginService, + i18nService, + toastService, + ), + }, + { provide: DefaultLoginComponentService, useExisting: DesktopLoginComponentService }, + { provide: CryptoFunctionService, useValue: cryptoFunctionService }, + { provide: EnvironmentService, useValue: environmentService }, + { provide: PasswordGenerationServiceAbstraction, useValue: passwordGenerationService }, + { provide: PlatformUtilsService, useValue: platformUtilsService }, + { provide: SsoLoginServiceAbstraction, useValue: ssoLoginService }, { provide: I18nService, useValue: i18nService }, { provide: ToastService, useValue: toastService }, - { provide: SsoLoginServiceAbstraction, useValue: ssoLoginService }, - { provide: PasswordGenerationServiceAbstraction, useValue: passwordGenerationService }, - { provide: CryptoFunctionService, useValue: cryptoFunctionService }, ], }); diff --git a/apps/desktop/src/auth/login/desktop-login-component.service.ts b/apps/desktop/src/auth/login/desktop-login-component.service.ts index 3f3296b24f8..ef0faaee1c6 100644 --- a/apps/desktop/src/auth/login/desktop-login-component.service.ts +++ b/apps/desktop/src/auth/login/desktop-login-component.service.ts @@ -1,18 +1,38 @@ -import { inject } from "@angular/core"; +import { Injectable } from "@angular/core"; import { DefaultLoginComponentService, LoginComponentService } from "@bitwarden/auth/angular"; -import { ClientType } from "@bitwarden/common/enums"; +import { SsoLoginServiceAbstraction } from "@bitwarden/common/auth/abstractions/sso-login.service.abstraction"; +import { CryptoFunctionService } from "@bitwarden/common/platform/abstractions/crypto-function.service"; +import { EnvironmentService } from "@bitwarden/common/platform/abstractions/environment.service"; import { I18nService } from "@bitwarden/common/platform/abstractions/i18n.service"; +import { PlatformUtilsService } from "@bitwarden/common/platform/abstractions/platform-utils.service"; import { Utils } from "@bitwarden/common/platform/misc/utils"; import { ToastService } from "@bitwarden/components"; +import { PasswordGenerationServiceAbstraction } from "@bitwarden/generator-legacy"; +@Injectable() export class DesktopLoginComponentService extends DefaultLoginComponentService implements LoginComponentService { - i18nService = inject(I18nService); - toastService = inject(ToastService); - clientType = ClientType.Desktop; + constructor( + protected cryptoFunctionService: CryptoFunctionService, + protected environmentService: EnvironmentService, + protected passwordGenerationService: PasswordGenerationServiceAbstraction, + protected platformUtilsService: PlatformUtilsService, + protected ssoLoginService: SsoLoginServiceAbstraction, + protected i18nService: I18nService, + protected toastService: ToastService, + ) { + super( + cryptoFunctionService, + environmentService, + passwordGenerationService, + platformUtilsService, + ssoLoginService, + ); + this.clientType = this.platformUtilsService.getClientType(); + } override async launchSsoBrowserWindow(email: string, clientId: "desktop"): Promise { if (!ipc.platform.isAppImage && !ipc.platform.isSnapStore && !ipc.platform.isDev) { diff --git a/apps/web/src/app/auth/core/services/login/web-login-component.service.spec.ts b/apps/web/src/app/auth/core/services/login/web-login-component.service.spec.ts index 3dbbe1471c5..41af877e06e 100644 --- a/apps/web/src/app/auth/core/services/login/web-login-component.service.spec.ts +++ b/apps/web/src/app/auth/core/services/login/web-login-component.service.spec.ts @@ -1,10 +1,16 @@ import { TestBed } from "@angular/core/testing"; import { UrlTree } from "@angular/router"; +import { MockProxy, mock } from "jest-mock-extended"; import { DefaultLoginComponentService } from "@bitwarden/auth/angular"; import { PolicyApiServiceAbstraction } from "@bitwarden/common/admin-console/abstractions/policy/policy-api.service.abstraction"; import { InternalPolicyService } from "@bitwarden/common/admin-console/abstractions/policy/policy.service.abstraction"; +import { SsoLoginServiceAbstraction } from "@bitwarden/common/auth/abstractions/sso-login.service.abstraction"; +import { CryptoFunctionService } from "@bitwarden/common/platform/abstractions/crypto-function.service"; +import { EnvironmentService } from "@bitwarden/common/platform/abstractions/environment.service"; import { LogService } from "@bitwarden/common/platform/abstractions/log.service"; +import { PlatformUtilsService } from "@bitwarden/common/platform/abstractions/platform-utils.service"; +import { PasswordGenerationServiceAbstraction } from "@bitwarden/generator-legacy"; import { RouterService } from "../../../../../../../../apps/web/src/app/core"; import { flagEnabled } from "../../../../../utils/flags"; @@ -18,37 +24,43 @@ jest.mock("../../../../../utils/flags", () => ({ describe("WebLoginComponentService", () => { let service: WebLoginComponentService; + let acceptOrganizationInviteService: MockProxy; + let logService: MockProxy; + let policyApiService: MockProxy; + let internalPolicyService: MockProxy; + let routerService: MockProxy; + let cryptoFunctionService: MockProxy; + let environmentService: MockProxy; + let passwordGenerationService: MockProxy; + let platformUtilsService: MockProxy; + let ssoLoginService: MockProxy; beforeEach(() => { + acceptOrganizationInviteService = mock(); + logService = mock(); + policyApiService = mock(); + internalPolicyService = mock(); + routerService = mock(); + cryptoFunctionService = mock(); + environmentService = mock(); + passwordGenerationService = mock(); + platformUtilsService = mock(); + ssoLoginService = mock(); + TestBed.configureTestingModule({ providers: [ WebLoginComponentService, { provide: DefaultLoginComponentService, useClass: WebLoginComponentService }, - { - provide: AcceptOrganizationInviteService, - useValue: { - getOrganizationInvite: jest.fn(), - }, - }, - { - provide: LogService, - useValue: { - error: jest.fn(), - }, - }, - { - provide: PolicyApiServiceAbstraction, - useValue: { - getPoliciesByToken: jest.fn(), - }, - }, - { provide: InternalPolicyService, useValue: {} }, - { - provide: RouterService, - useValue: { - setPreviousUrl: jest.fn(), - }, - }, + { provide: AcceptOrganizationInviteService, useValue: acceptOrganizationInviteService }, + { provide: LogService, useValue: logService }, + { provide: PolicyApiServiceAbstraction, useValue: policyApiService }, + { provide: InternalPolicyService, useValue: internalPolicyService }, + { provide: RouterService, useValue: routerService }, + { provide: CryptoFunctionService, useValue: cryptoFunctionService }, + { provide: EnvironmentService, useValue: environmentService }, + { provide: PasswordGenerationServiceAbstraction, useValue: passwordGenerationService }, + { provide: PlatformUtilsService, useValue: platformUtilsService }, + { provide: SsoLoginServiceAbstraction, useValue: ssoLoginService }, ], }); service = TestBed.inject(WebLoginComponentService); @@ -72,22 +84,19 @@ describe("WebLoginComponentService", () => { it("sets the previous URL", () => { const route = { toString: () => "test-url" } as UrlTree; - const routerServiceSpy = jest.spyOn(service.routerService, "setPreviousUrl"); service.setPreviousUrl(route); - expect(routerServiceSpy).toHaveBeenCalledWith("test-url"); + expect(routerService.setPreviousUrl).toHaveBeenCalledWith("test-url"); }); it("returns undefined if organization invite is null", async () => { - jest - .spyOn(service.acceptOrganizationInviteService, "getOrganizationInvite") - .mockResolvedValue(null); + acceptOrganizationInviteService.getOrganizationInvite.mockResolvedValue(null); const result = await service.getOrgPolicies(); expect(result).toBeUndefined(); }); it("logs an error if getPoliciesByToken throws an error", async () => { const error = new Error("Test error"); - jest.spyOn(service.acceptOrganizationInviteService, "getOrganizationInvite").mockResolvedValue({ + acceptOrganizationInviteService.getOrganizationInvite.mockResolvedValue({ organizationId: "org-id", token: "token", email: "email", @@ -97,9 +106,8 @@ describe("WebLoginComponentService", () => { orgUserHasExistingUser: false, organizationName: "org-name", }); - jest.spyOn(service.policyApiService, "getPoliciesByToken").mockRejectedValue(error); - const logServiceSpy = jest.spyOn(service.logService, "error"); + policyApiService.getPoliciesByToken.mockRejectedValue(error); await service.getOrgPolicies(); - expect(logServiceSpy).toHaveBeenCalledWith(error); + expect(logService.error).toHaveBeenCalledWith(error); }); }); diff --git a/apps/web/src/app/auth/core/services/login/web-login-component.service.ts b/apps/web/src/app/auth/core/services/login/web-login-component.service.ts index 8ad2a297bd4..7d90935a8f1 100644 --- a/apps/web/src/app/auth/core/services/login/web-login-component.service.ts +++ b/apps/web/src/app/auth/core/services/login/web-login-component.service.ts @@ -1,5 +1,5 @@ -import { inject } from "@angular/core"; -import { Router, UrlTree } from "@angular/router"; +import { Injectable } from "@angular/core"; +import { UrlTree } from "@angular/router"; import { firstValueFrom } from "rxjs"; import { @@ -10,24 +10,43 @@ import { import { PolicyApiServiceAbstraction } from "@bitwarden/common/admin-console/abstractions/policy/policy-api.service.abstraction"; import { InternalPolicyService } from "@bitwarden/common/admin-console/abstractions/policy/policy.service.abstraction"; import { Policy } from "@bitwarden/common/admin-console/models/domain/policy"; -import { ClientType } from "@bitwarden/common/enums"; +import { SsoLoginServiceAbstraction } from "@bitwarden/common/auth/abstractions/sso-login.service.abstraction"; +import { CryptoFunctionService } from "@bitwarden/common/platform/abstractions/crypto-function.service"; +import { EnvironmentService } from "@bitwarden/common/platform/abstractions/environment.service"; import { LogService } from "@bitwarden/common/platform/abstractions/log.service"; +import { PlatformUtilsService } from "@bitwarden/common/platform/abstractions/platform-utils.service"; +import { PasswordGenerationServiceAbstraction } from "@bitwarden/generator-legacy"; import { flagEnabled } from "../../../../../utils/flags"; import { RouterService } from "../../../../core/router.service"; import { AcceptOrganizationInviteService } from "../../../organization-invite/accept-organization.service"; +@Injectable() export class WebLoginComponentService extends DefaultLoginComponentService implements LoginComponentService { - acceptOrganizationInviteService = inject(AcceptOrganizationInviteService); - logService = inject(LogService); - policyApiService = inject(PolicyApiServiceAbstraction); - policyService = inject(InternalPolicyService); - router = inject(Router); - routerService = inject(RouterService); - clientType = ClientType.Web; + constructor( + protected acceptOrganizationInviteService: AcceptOrganizationInviteService, + protected logService: LogService, + protected policyApiService: PolicyApiServiceAbstraction, + protected policyService: InternalPolicyService, + protected routerService: RouterService, + cryptoFunctionService: CryptoFunctionService, + environmentService: EnvironmentService, + passwordGenerationService: PasswordGenerationServiceAbstraction, + platformUtilsService: PlatformUtilsService, + ssoLoginService: SsoLoginServiceAbstraction, + ) { + super( + cryptoFunctionService, + environmentService, + passwordGenerationService, + platformUtilsService, + ssoLoginService, + ); + this.clientType = this.platformUtilsService.getClientType(); + } isLoginViaAuthRequestSupported(): boolean { return flagEnabled("showPasswordless"); diff --git a/apps/web/src/app/core/core.module.ts b/apps/web/src/app/core/core.module.ts index 7072f43b770..57140bcc55d 100644 --- a/apps/web/src/app/core/core.module.ts +++ b/apps/web/src/app/core/core.module.ts @@ -38,7 +38,10 @@ import { import { ApiService } from "@bitwarden/common/abstractions/api.service"; import { OrganizationApiServiceAbstraction } from "@bitwarden/common/admin-console/abstractions/organization/organization-api.service.abstraction"; import { PolicyApiServiceAbstraction } from "@bitwarden/common/admin-console/abstractions/policy/policy-api.service.abstraction"; -import { PolicyService } from "@bitwarden/common/admin-console/abstractions/policy/policy.service.abstraction"; +import { + InternalPolicyService, + PolicyService, +} from "@bitwarden/common/admin-console/abstractions/policy/policy.service.abstraction"; import { AccountApiService as AccountApiServiceAbstraction } from "@bitwarden/common/auth/abstractions/account-api.service"; import { AccountService } from "@bitwarden/common/auth/abstractions/account.service"; import { AuthService } from "@bitwarden/common/auth/abstractions/auth.service"; @@ -257,6 +260,11 @@ const safeProviders: SafeProvider[] = [ provide: LoginComponentService, useClass: WebLoginComponentService, deps: [ + AcceptOrganizationInviteService, + LogService, + PolicyApiServiceAbstraction, + InternalPolicyService, + RouterService, CryptoFunctionServiceAbstraction, EnvironmentService, PasswordGenerationServiceAbstraction,