mirror of
https://github.com/bitwarden/browser
synced 2025-12-13 14:53:33 +00:00
[PM-5264] Implement StateProvider in LoginEmailService (#7662)
* setup StateProvider in LoginService * replace implementations * replace implementation * remove stateService * change storage location for web to 'disk-local' * implement migrate() method of Migrator * add RememberedEmailMigrator to migrate.ts * add rollback * add tests * replace implementation * replace implementation * add StateProvider to Desktop services * rename LoginService to RememberEmailService * update state definition * rename file * rename to storedEmail * rename service to EmailService to avoid confusion * add jsdocs * refactor login.component.ts * fix typos * fix test * rename to LoginEmailService * update factory * more renaming * remove duplicate logic and rename method * convert storedEmail to observable * refactor to remove setStoredEmail() method * move service to libs/auth/common * address floating promises * remove comment * remove unnecessary deps in service registration
This commit is contained in:
@@ -0,0 +1,28 @@
|
|||||||
|
import { LoginEmailServiceAbstraction, LoginEmailService } from "@bitwarden/auth/common";
|
||||||
|
|
||||||
|
import {
|
||||||
|
CachedServices,
|
||||||
|
factory,
|
||||||
|
FactoryOptions,
|
||||||
|
} from "../../../platform/background/service-factories/factory-options";
|
||||||
|
import {
|
||||||
|
stateProviderFactory,
|
||||||
|
StateProviderInitOptions,
|
||||||
|
} from "../../../platform/background/service-factories/state-provider.factory";
|
||||||
|
|
||||||
|
type LoginEmailServiceFactoryOptions = FactoryOptions;
|
||||||
|
|
||||||
|
export type LoginEmailServiceInitOptions = LoginEmailServiceFactoryOptions &
|
||||||
|
StateProviderInitOptions;
|
||||||
|
|
||||||
|
export function loginEmailServiceFactory(
|
||||||
|
cache: { loginEmailService?: LoginEmailServiceAbstraction } & CachedServices,
|
||||||
|
opts: LoginEmailServiceInitOptions,
|
||||||
|
): Promise<LoginEmailServiceAbstraction> {
|
||||||
|
return factory(
|
||||||
|
cache,
|
||||||
|
"loginEmailService",
|
||||||
|
opts,
|
||||||
|
async () => new LoginEmailService(await stateProviderFactory(cache, opts)),
|
||||||
|
);
|
||||||
|
}
|
||||||
@@ -2,8 +2,8 @@ import { Component } from "@angular/core";
|
|||||||
import { ActivatedRoute, Router } from "@angular/router";
|
import { ActivatedRoute, Router } from "@angular/router";
|
||||||
|
|
||||||
import { HintComponent as BaseHintComponent } from "@bitwarden/angular/auth/components/hint.component";
|
import { HintComponent as BaseHintComponent } from "@bitwarden/angular/auth/components/hint.component";
|
||||||
|
import { LoginEmailServiceAbstraction } from "@bitwarden/auth/common";
|
||||||
import { ApiService } from "@bitwarden/common/abstractions/api.service";
|
import { ApiService } from "@bitwarden/common/abstractions/api.service";
|
||||||
import { LoginService } from "@bitwarden/common/auth/abstractions/login.service";
|
|
||||||
import { I18nService } from "@bitwarden/common/platform/abstractions/i18n.service";
|
import { I18nService } from "@bitwarden/common/platform/abstractions/i18n.service";
|
||||||
import { LogService } from "@bitwarden/common/platform/abstractions/log.service";
|
import { LogService } from "@bitwarden/common/platform/abstractions/log.service";
|
||||||
import { PlatformUtilsService } from "@bitwarden/common/platform/abstractions/platform-utils.service";
|
import { PlatformUtilsService } from "@bitwarden/common/platform/abstractions/platform-utils.service";
|
||||||
@@ -20,9 +20,9 @@ export class HintComponent extends BaseHintComponent {
|
|||||||
apiService: ApiService,
|
apiService: ApiService,
|
||||||
logService: LogService,
|
logService: LogService,
|
||||||
private route: ActivatedRoute,
|
private route: ActivatedRoute,
|
||||||
loginService: LoginService,
|
loginEmailService: LoginEmailServiceAbstraction,
|
||||||
) {
|
) {
|
||||||
super(router, i18nService, apiService, platformUtilsService, logService, loginService);
|
super(router, i18nService, apiService, platformUtilsService, logService, loginEmailService);
|
||||||
|
|
||||||
super.onSuccessfulSubmit = async () => {
|
super.onSuccessfulSubmit = async () => {
|
||||||
// FIXME: Verify that this floating promise is intentional. If it is, add an explanatory comment and ensure there is proper error handling.
|
// FIXME: Verify that this floating promise is intentional. If it is, add an explanatory comment and ensure there is proper error handling.
|
||||||
|
|||||||
@@ -30,7 +30,7 @@
|
|||||||
</form>
|
</form>
|
||||||
<p class="createAccountLink">
|
<p class="createAccountLink">
|
||||||
{{ "newAroundHere" | i18n }}
|
{{ "newAroundHere" | i18n }}
|
||||||
<a routerLink="/register" (click)="setFormValues()">{{ "createAccount" | i18n }}</a>
|
<a routerLink="/register" (click)="setLoginEmailValues()">{{ "createAccount" | i18n }}</a>
|
||||||
</p>
|
</p>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
|
|||||||
@@ -1,14 +1,13 @@
|
|||||||
import { Component, OnDestroy, OnInit, ViewChild } from "@angular/core";
|
import { Component, OnDestroy, OnInit, ViewChild } from "@angular/core";
|
||||||
import { FormBuilder, Validators } from "@angular/forms";
|
import { FormBuilder, Validators } from "@angular/forms";
|
||||||
import { Router } from "@angular/router";
|
import { Router } from "@angular/router";
|
||||||
import { Subject, takeUntil } from "rxjs";
|
import { Subject, firstValueFrom, takeUntil } from "rxjs";
|
||||||
|
|
||||||
import { EnvironmentSelectorComponent } from "@bitwarden/angular/auth/components/environment-selector.component";
|
import { EnvironmentSelectorComponent } from "@bitwarden/angular/auth/components/environment-selector.component";
|
||||||
import { LoginService } from "@bitwarden/common/auth/abstractions/login.service";
|
import { LoginEmailServiceAbstraction } from "@bitwarden/auth/common";
|
||||||
import { EnvironmentService } from "@bitwarden/common/platform/abstractions/environment.service";
|
import { EnvironmentService } from "@bitwarden/common/platform/abstractions/environment.service";
|
||||||
import { I18nService } from "@bitwarden/common/platform/abstractions/i18n.service";
|
import { I18nService } from "@bitwarden/common/platform/abstractions/i18n.service";
|
||||||
import { PlatformUtilsService } from "@bitwarden/common/platform/abstractions/platform-utils.service";
|
import { PlatformUtilsService } from "@bitwarden/common/platform/abstractions/platform-utils.service";
|
||||||
import { StateService } from "@bitwarden/common/platform/abstractions/state.service";
|
|
||||||
|
|
||||||
import { AccountSwitcherService } from "./account-switching/services/account-switcher.service";
|
import { AccountSwitcherService } from "./account-switching/services/account-switcher.service";
|
||||||
|
|
||||||
@@ -29,38 +28,32 @@ export class HomeComponent implements OnInit, OnDestroy {
|
|||||||
|
|
||||||
constructor(
|
constructor(
|
||||||
protected platformUtilsService: PlatformUtilsService,
|
protected platformUtilsService: PlatformUtilsService,
|
||||||
private stateService: StateService,
|
|
||||||
private formBuilder: FormBuilder,
|
private formBuilder: FormBuilder,
|
||||||
private router: Router,
|
private router: Router,
|
||||||
private i18nService: I18nService,
|
private i18nService: I18nService,
|
||||||
private environmentService: EnvironmentService,
|
private environmentService: EnvironmentService,
|
||||||
private loginService: LoginService,
|
private loginEmailService: LoginEmailServiceAbstraction,
|
||||||
private accountSwitcherService: AccountSwitcherService,
|
private accountSwitcherService: AccountSwitcherService,
|
||||||
) {}
|
) {}
|
||||||
|
|
||||||
async ngOnInit(): Promise<void> {
|
async ngOnInit(): Promise<void> {
|
||||||
let savedEmail = this.loginService.getEmail();
|
const email = this.loginEmailService.getEmail();
|
||||||
const rememberEmail = this.loginService.getRememberEmail();
|
const rememberEmail = this.loginEmailService.getRememberEmail();
|
||||||
|
|
||||||
if (savedEmail != null) {
|
if (email != null) {
|
||||||
this.formGroup.patchValue({
|
this.formGroup.patchValue({ email, rememberEmail });
|
||||||
email: savedEmail,
|
|
||||||
rememberEmail: rememberEmail,
|
|
||||||
});
|
|
||||||
} else {
|
} else {
|
||||||
savedEmail = await this.stateService.getRememberedEmail();
|
const storedEmail = await firstValueFrom(this.loginEmailService.storedEmail$);
|
||||||
if (savedEmail != null) {
|
|
||||||
this.formGroup.patchValue({
|
if (storedEmail != null) {
|
||||||
email: savedEmail,
|
this.formGroup.patchValue({ email: storedEmail, rememberEmail: true });
|
||||||
rememberEmail: true,
|
|
||||||
});
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
this.environmentSelector.onOpenSelfHostedSettings
|
this.environmentSelector.onOpenSelfHostedSettings
|
||||||
.pipe(takeUntil(this.destroyed$))
|
.pipe(takeUntil(this.destroyed$))
|
||||||
.subscribe(() => {
|
.subscribe(() => {
|
||||||
this.setFormValues();
|
this.setLoginEmailValues();
|
||||||
// FIXME: Verify that this floating promise is intentional. If it is, add an explanatory comment and ensure there is proper error handling.
|
// FIXME: Verify that this floating promise is intentional. If it is, add an explanatory comment and ensure there is proper error handling.
|
||||||
// eslint-disable-next-line @typescript-eslint/no-floating-promises
|
// eslint-disable-next-line @typescript-eslint/no-floating-promises
|
||||||
this.router.navigate(["environment"]);
|
this.router.navigate(["environment"]);
|
||||||
@@ -76,8 +69,9 @@ export class HomeComponent implements OnInit, OnDestroy {
|
|||||||
return this.accountSwitcherService.availableAccounts$;
|
return this.accountSwitcherService.availableAccounts$;
|
||||||
}
|
}
|
||||||
|
|
||||||
submit() {
|
async submit() {
|
||||||
this.formGroup.markAllAsTouched();
|
this.formGroup.markAllAsTouched();
|
||||||
|
|
||||||
if (this.formGroup.invalid) {
|
if (this.formGroup.invalid) {
|
||||||
this.platformUtilsService.showToast(
|
this.platformUtilsService.showToast(
|
||||||
"error",
|
"error",
|
||||||
@@ -87,15 +81,12 @@ export class HomeComponent implements OnInit, OnDestroy {
|
|||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
this.loginService.setEmail(this.formGroup.value.email);
|
this.setLoginEmailValues();
|
||||||
this.loginService.setRememberEmail(this.formGroup.value.rememberEmail);
|
await this.router.navigate(["login"], { queryParams: { email: this.formGroup.value.email } });
|
||||||
// FIXME: Verify that this floating promise is intentional. If it is, add an explanatory comment and ensure there is proper error handling.
|
|
||||||
// eslint-disable-next-line @typescript-eslint/no-floating-promises
|
|
||||||
this.router.navigate(["login"], { queryParams: { email: this.formGroup.value.email } });
|
|
||||||
}
|
}
|
||||||
|
|
||||||
setFormValues() {
|
setLoginEmailValues() {
|
||||||
this.loginService.setEmail(this.formGroup.value.email);
|
this.loginEmailService.setEmail(this.formGroup.value.email);
|
||||||
this.loginService.setRememberEmail(this.formGroup.value.rememberEmail);
|
this.loginEmailService.setRememberEmail(this.formGroup.value.rememberEmail);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -6,12 +6,12 @@ import { LoginViaAuthRequestComponent as BaseLoginWithDeviceComponent } from "@b
|
|||||||
import {
|
import {
|
||||||
AuthRequestServiceAbstraction,
|
AuthRequestServiceAbstraction,
|
||||||
LoginStrategyServiceAbstraction,
|
LoginStrategyServiceAbstraction,
|
||||||
|
LoginEmailServiceAbstraction,
|
||||||
} from "@bitwarden/auth/common";
|
} from "@bitwarden/auth/common";
|
||||||
import { ApiService } from "@bitwarden/common/abstractions/api.service";
|
import { ApiService } from "@bitwarden/common/abstractions/api.service";
|
||||||
import { AnonymousHubService } from "@bitwarden/common/auth/abstractions/anonymous-hub.service";
|
import { AnonymousHubService } from "@bitwarden/common/auth/abstractions/anonymous-hub.service";
|
||||||
import { AuthService } from "@bitwarden/common/auth/abstractions/auth.service";
|
import { AuthService } from "@bitwarden/common/auth/abstractions/auth.service";
|
||||||
import { DeviceTrustCryptoServiceAbstraction } from "@bitwarden/common/auth/abstractions/device-trust-crypto.service.abstraction";
|
import { DeviceTrustCryptoServiceAbstraction } from "@bitwarden/common/auth/abstractions/device-trust-crypto.service.abstraction";
|
||||||
import { LoginService } from "@bitwarden/common/auth/abstractions/login.service";
|
|
||||||
import { AppIdService } from "@bitwarden/common/platform/abstractions/app-id.service";
|
import { AppIdService } from "@bitwarden/common/platform/abstractions/app-id.service";
|
||||||
import { CryptoFunctionService } from "@bitwarden/common/platform/abstractions/crypto-function.service";
|
import { CryptoFunctionService } from "@bitwarden/common/platform/abstractions/crypto-function.service";
|
||||||
import { CryptoService } from "@bitwarden/common/platform/abstractions/crypto.service";
|
import { CryptoService } from "@bitwarden/common/platform/abstractions/crypto.service";
|
||||||
@@ -44,7 +44,7 @@ export class LoginViaAuthRequestComponent extends BaseLoginWithDeviceComponent {
|
|||||||
anonymousHubService: AnonymousHubService,
|
anonymousHubService: AnonymousHubService,
|
||||||
validationService: ValidationService,
|
validationService: ValidationService,
|
||||||
stateService: StateService,
|
stateService: StateService,
|
||||||
loginService: LoginService,
|
loginEmailService: LoginEmailServiceAbstraction,
|
||||||
syncService: SyncService,
|
syncService: SyncService,
|
||||||
deviceTrustCryptoService: DeviceTrustCryptoServiceAbstraction,
|
deviceTrustCryptoService: DeviceTrustCryptoServiceAbstraction,
|
||||||
authRequestService: AuthRequestServiceAbstraction,
|
authRequestService: AuthRequestServiceAbstraction,
|
||||||
@@ -66,7 +66,7 @@ export class LoginViaAuthRequestComponent extends BaseLoginWithDeviceComponent {
|
|||||||
anonymousHubService,
|
anonymousHubService,
|
||||||
validationService,
|
validationService,
|
||||||
stateService,
|
stateService,
|
||||||
loginService,
|
loginEmailService,
|
||||||
deviceTrustCryptoService,
|
deviceTrustCryptoService,
|
||||||
authRequestService,
|
authRequestService,
|
||||||
loginStrategyService,
|
loginStrategyService,
|
||||||
|
|||||||
@@ -52,7 +52,7 @@
|
|||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
<div class="box-footer">
|
<div class="box-footer">
|
||||||
<button type="button" class="btn link" routerLink="/hint" (click)="setFormValues()">
|
<button type="button" class="btn link" routerLink="/hint" (click)="setLoginEmailValues()">
|
||||||
<b>{{ "getMasterPasswordHint" | i18n }}</b>
|
<b>{{ "getMasterPasswordHint" | i18n }}</b>
|
||||||
</button>
|
</button>
|
||||||
</div>
|
</div>
|
||||||
|
|||||||
@@ -5,9 +5,11 @@ import { firstValueFrom } from "rxjs";
|
|||||||
|
|
||||||
import { LoginComponent as BaseLoginComponent } from "@bitwarden/angular/auth/components/login.component";
|
import { LoginComponent as BaseLoginComponent } from "@bitwarden/angular/auth/components/login.component";
|
||||||
import { FormValidationErrorsService } from "@bitwarden/angular/platform/abstractions/form-validation-errors.service";
|
import { FormValidationErrorsService } from "@bitwarden/angular/platform/abstractions/form-validation-errors.service";
|
||||||
import { LoginStrategyServiceAbstraction } from "@bitwarden/auth/common";
|
import {
|
||||||
|
LoginStrategyServiceAbstraction,
|
||||||
|
LoginEmailServiceAbstraction,
|
||||||
|
} from "@bitwarden/auth/common";
|
||||||
import { DevicesApiServiceAbstraction } from "@bitwarden/common/auth/abstractions/devices-api.service.abstraction";
|
import { DevicesApiServiceAbstraction } from "@bitwarden/common/auth/abstractions/devices-api.service.abstraction";
|
||||||
import { LoginService } from "@bitwarden/common/auth/abstractions/login.service";
|
|
||||||
import { SsoLoginServiceAbstraction } from "@bitwarden/common/auth/abstractions/sso-login.service.abstraction";
|
import { SsoLoginServiceAbstraction } from "@bitwarden/common/auth/abstractions/sso-login.service.abstraction";
|
||||||
import { WebAuthnLoginServiceAbstraction } from "@bitwarden/common/auth/abstractions/webauthn/webauthn-login.service.abstraction";
|
import { WebAuthnLoginServiceAbstraction } from "@bitwarden/common/auth/abstractions/webauthn/webauthn-login.service.abstraction";
|
||||||
import { AppIdService } from "@bitwarden/common/platform/abstractions/app-id.service";
|
import { AppIdService } from "@bitwarden/common/platform/abstractions/app-id.service";
|
||||||
@@ -46,7 +48,7 @@ export class LoginComponent extends BaseLoginComponent {
|
|||||||
formBuilder: FormBuilder,
|
formBuilder: FormBuilder,
|
||||||
formValidationErrorService: FormValidationErrorsService,
|
formValidationErrorService: FormValidationErrorsService,
|
||||||
route: ActivatedRoute,
|
route: ActivatedRoute,
|
||||||
loginService: LoginService,
|
loginEmailService: LoginEmailServiceAbstraction,
|
||||||
ssoLoginService: SsoLoginServiceAbstraction,
|
ssoLoginService: SsoLoginServiceAbstraction,
|
||||||
webAuthnLoginService: WebAuthnLoginServiceAbstraction,
|
webAuthnLoginService: WebAuthnLoginServiceAbstraction,
|
||||||
) {
|
) {
|
||||||
@@ -66,7 +68,7 @@ export class LoginComponent extends BaseLoginComponent {
|
|||||||
formBuilder,
|
formBuilder,
|
||||||
formValidationErrorService,
|
formValidationErrorService,
|
||||||
route,
|
route,
|
||||||
loginService,
|
loginEmailService,
|
||||||
ssoLoginService,
|
ssoLoginService,
|
||||||
webAuthnLoginService,
|
webAuthnLoginService,
|
||||||
);
|
);
|
||||||
@@ -77,8 +79,8 @@ export class LoginComponent extends BaseLoginComponent {
|
|||||||
this.showPasswordless = flagEnabled("showPasswordless");
|
this.showPasswordless = flagEnabled("showPasswordless");
|
||||||
|
|
||||||
if (this.showPasswordless) {
|
if (this.showPasswordless) {
|
||||||
this.formGroup.controls.email.setValue(this.loginService.getEmail());
|
this.formGroup.controls.email.setValue(this.loginEmailService.getEmail());
|
||||||
this.formGroup.controls.rememberEmail.setValue(this.loginService.getRememberEmail());
|
this.formGroup.controls.rememberEmail.setValue(this.loginEmailService.getRememberEmail());
|
||||||
// FIXME: Verify that this floating promise is intentional. If it is, add an explanatory comment and ensure there is proper error handling.
|
// FIXME: Verify that this floating promise is intentional. If it is, add an explanatory comment and ensure there is proper error handling.
|
||||||
// eslint-disable-next-line @typescript-eslint/no-floating-promises
|
// eslint-disable-next-line @typescript-eslint/no-floating-promises
|
||||||
this.validateEmail();
|
this.validateEmail();
|
||||||
@@ -94,7 +96,7 @@ export class LoginComponent extends BaseLoginComponent {
|
|||||||
async launchSsoBrowser() {
|
async launchSsoBrowser() {
|
||||||
// Save off email for SSO
|
// Save off email for SSO
|
||||||
await this.ssoLoginService.setSsoEmail(this.formGroup.value.email);
|
await this.ssoLoginService.setSsoEmail(this.formGroup.value.email);
|
||||||
await this.loginService.saveEmailSettings();
|
await this.loginEmailService.saveEmailSettings();
|
||||||
// Generate necessary sso params
|
// Generate necessary sso params
|
||||||
const passwordOptions: any = {
|
const passwordOptions: any = {
|
||||||
type: "password",
|
type: "password",
|
||||||
|
|||||||
@@ -7,10 +7,10 @@ import { TwoFactorComponent as BaseTwoFactorComponent } from "@bitwarden/angular
|
|||||||
import { WINDOW } from "@bitwarden/angular/services/injection-tokens";
|
import { WINDOW } from "@bitwarden/angular/services/injection-tokens";
|
||||||
import {
|
import {
|
||||||
LoginStrategyServiceAbstraction,
|
LoginStrategyServiceAbstraction,
|
||||||
|
LoginEmailServiceAbstraction,
|
||||||
UserDecryptionOptionsServiceAbstraction,
|
UserDecryptionOptionsServiceAbstraction,
|
||||||
} from "@bitwarden/auth/common";
|
} from "@bitwarden/auth/common";
|
||||||
import { ApiService } from "@bitwarden/common/abstractions/api.service";
|
import { ApiService } from "@bitwarden/common/abstractions/api.service";
|
||||||
import { LoginService } from "@bitwarden/common/auth/abstractions/login.service";
|
|
||||||
import { SsoLoginServiceAbstraction } from "@bitwarden/common/auth/abstractions/sso-login.service.abstraction";
|
import { SsoLoginServiceAbstraction } from "@bitwarden/common/auth/abstractions/sso-login.service.abstraction";
|
||||||
import { TwoFactorService } from "@bitwarden/common/auth/abstractions/two-factor.service";
|
import { TwoFactorService } from "@bitwarden/common/auth/abstractions/two-factor.service";
|
||||||
import { TwoFactorProviderType } from "@bitwarden/common/auth/enums/two-factor-provider-type";
|
import { TwoFactorProviderType } from "@bitwarden/common/auth/enums/two-factor-provider-type";
|
||||||
@@ -57,7 +57,7 @@ export class TwoFactorComponent extends BaseTwoFactorComponent {
|
|||||||
logService: LogService,
|
logService: LogService,
|
||||||
twoFactorService: TwoFactorService,
|
twoFactorService: TwoFactorService,
|
||||||
appIdService: AppIdService,
|
appIdService: AppIdService,
|
||||||
loginService: LoginService,
|
loginEmailService: LoginEmailServiceAbstraction,
|
||||||
userDecryptionOptionsService: UserDecryptionOptionsServiceAbstraction,
|
userDecryptionOptionsService: UserDecryptionOptionsServiceAbstraction,
|
||||||
configService: ConfigService,
|
configService: ConfigService,
|
||||||
ssoLoginService: SsoLoginServiceAbstraction,
|
ssoLoginService: SsoLoginServiceAbstraction,
|
||||||
@@ -78,7 +78,7 @@ export class TwoFactorComponent extends BaseTwoFactorComponent {
|
|||||||
logService,
|
logService,
|
||||||
twoFactorService,
|
twoFactorService,
|
||||||
appIdService,
|
appIdService,
|
||||||
loginService,
|
loginEmailService,
|
||||||
userDecryptionOptionsService,
|
userDecryptionOptionsService,
|
||||||
ssoLoginService,
|
ssoLoginService,
|
||||||
configService,
|
configService,
|
||||||
|
|||||||
@@ -9,6 +9,7 @@ import {
|
|||||||
UserDecryptionOptionsService,
|
UserDecryptionOptionsService,
|
||||||
AuthRequestServiceAbstraction,
|
AuthRequestServiceAbstraction,
|
||||||
AuthRequestService,
|
AuthRequestService,
|
||||||
|
LoginEmailServiceAbstraction,
|
||||||
} from "@bitwarden/auth/common";
|
} from "@bitwarden/auth/common";
|
||||||
import { ApiService as ApiServiceAbstraction } from "@bitwarden/common/abstractions/api.service";
|
import { ApiService as ApiServiceAbstraction } from "@bitwarden/common/abstractions/api.service";
|
||||||
import { AuditService as AuditServiceAbstraction } from "@bitwarden/common/abstractions/audit.service";
|
import { AuditService as AuditServiceAbstraction } from "@bitwarden/common/abstractions/audit.service";
|
||||||
@@ -258,6 +259,7 @@ export default class MainBackground {
|
|||||||
auditService: AuditServiceAbstraction;
|
auditService: AuditServiceAbstraction;
|
||||||
authService: AuthServiceAbstraction;
|
authService: AuthServiceAbstraction;
|
||||||
loginStrategyService: LoginStrategyServiceAbstraction;
|
loginStrategyService: LoginStrategyServiceAbstraction;
|
||||||
|
loginEmailService: LoginEmailServiceAbstraction;
|
||||||
importApiService: ImportApiServiceAbstraction;
|
importApiService: ImportApiServiceAbstraction;
|
||||||
importService: ImportServiceAbstraction;
|
importService: ImportServiceAbstraction;
|
||||||
exportService: VaultExportServiceAbstraction;
|
exportService: VaultExportServiceAbstraction;
|
||||||
@@ -1080,7 +1082,9 @@ export default class MainBackground {
|
|||||||
await this.stateService.setActiveUser(userId);
|
await this.stateService.setActiveUser(userId);
|
||||||
|
|
||||||
if (userId == null) {
|
if (userId == null) {
|
||||||
await this.stateService.setRememberedEmail(null);
|
this.loginEmailService.setRememberEmail(false);
|
||||||
|
await this.loginEmailService.saveEmailSettings();
|
||||||
|
|
||||||
await this.refreshBadge();
|
await this.refreshBadge();
|
||||||
await this.refreshMenu();
|
await this.refreshMenu();
|
||||||
await this.overlayBackground.updateOverlayCiphers();
|
await this.overlayBackground.updateOverlayCiphers();
|
||||||
|
|||||||
@@ -30,13 +30,11 @@ import { AuthService as AuthServiceAbstraction } from "@bitwarden/common/auth/ab
|
|||||||
import { DeviceTrustCryptoServiceAbstraction } from "@bitwarden/common/auth/abstractions/device-trust-crypto.service.abstraction";
|
import { DeviceTrustCryptoServiceAbstraction } from "@bitwarden/common/auth/abstractions/device-trust-crypto.service.abstraction";
|
||||||
import { DevicesServiceAbstraction } from "@bitwarden/common/auth/abstractions/devices/devices.service.abstraction";
|
import { DevicesServiceAbstraction } from "@bitwarden/common/auth/abstractions/devices/devices.service.abstraction";
|
||||||
import { KeyConnectorService } from "@bitwarden/common/auth/abstractions/key-connector.service";
|
import { KeyConnectorService } from "@bitwarden/common/auth/abstractions/key-connector.service";
|
||||||
import { LoginService as LoginServiceAbstraction } from "@bitwarden/common/auth/abstractions/login.service";
|
|
||||||
import { SsoLoginServiceAbstraction } from "@bitwarden/common/auth/abstractions/sso-login.service.abstraction";
|
import { SsoLoginServiceAbstraction } from "@bitwarden/common/auth/abstractions/sso-login.service.abstraction";
|
||||||
import { TokenService } from "@bitwarden/common/auth/abstractions/token.service";
|
import { TokenService } from "@bitwarden/common/auth/abstractions/token.service";
|
||||||
import { TwoFactorService } from "@bitwarden/common/auth/abstractions/two-factor.service";
|
import { TwoFactorService } from "@bitwarden/common/auth/abstractions/two-factor.service";
|
||||||
import { UserVerificationService } from "@bitwarden/common/auth/abstractions/user-verification/user-verification.service.abstraction";
|
import { UserVerificationService } from "@bitwarden/common/auth/abstractions/user-verification/user-verification.service.abstraction";
|
||||||
import { AuthService } from "@bitwarden/common/auth/services/auth.service";
|
import { AuthService } from "@bitwarden/common/auth/services/auth.service";
|
||||||
import { LoginService } from "@bitwarden/common/auth/services/login.service";
|
|
||||||
import {
|
import {
|
||||||
AutofillSettingsService,
|
AutofillSettingsService,
|
||||||
AutofillSettingsServiceAbstraction,
|
AutofillSettingsServiceAbstraction,
|
||||||
@@ -429,11 +427,6 @@ const safeProviders: SafeProvider[] = [
|
|||||||
useClass: BrowserFileDownloadService,
|
useClass: BrowserFileDownloadService,
|
||||||
deps: [],
|
deps: [],
|
||||||
}),
|
}),
|
||||||
safeProvider({
|
|
||||||
provide: LoginServiceAbstraction,
|
|
||||||
useClass: LoginService,
|
|
||||||
deps: [StateServiceAbstraction],
|
|
||||||
}),
|
|
||||||
safeProvider({
|
safeProvider({
|
||||||
provide: SYSTEM_THEME_OBSERVABLE,
|
provide: SYSTEM_THEME_OBSERVABLE,
|
||||||
useFactory: (platformUtilsService: PlatformUtilsService) => {
|
useFactory: (platformUtilsService: PlatformUtilsService) => {
|
||||||
|
|||||||
@@ -4,6 +4,7 @@ import { Component, OnDestroy, OnInit } from "@angular/core";
|
|||||||
import { Router } from "@angular/router";
|
import { Router } from "@angular/router";
|
||||||
import { concatMap, firstValueFrom, Subject, takeUntil } from "rxjs";
|
import { concatMap, firstValueFrom, Subject, takeUntil } from "rxjs";
|
||||||
|
|
||||||
|
import { LoginEmailServiceAbstraction } from "@bitwarden/auth/common";
|
||||||
import { AuthService } from "@bitwarden/common/auth/abstractions/auth.service";
|
import { AuthService } from "@bitwarden/common/auth/abstractions/auth.service";
|
||||||
import { AvatarService } from "@bitwarden/common/auth/abstractions/avatar.service";
|
import { AvatarService } from "@bitwarden/common/auth/abstractions/avatar.service";
|
||||||
import { TokenService } from "@bitwarden/common/auth/abstractions/token.service";
|
import { TokenService } from "@bitwarden/common/auth/abstractions/token.service";
|
||||||
@@ -91,6 +92,7 @@ export class AccountSwitcherComponent implements OnInit, OnDestroy {
|
|||||||
private router: Router,
|
private router: Router,
|
||||||
private tokenService: TokenService,
|
private tokenService: TokenService,
|
||||||
private environmentService: EnvironmentService,
|
private environmentService: EnvironmentService,
|
||||||
|
private loginEmailService: LoginEmailServiceAbstraction,
|
||||||
) {}
|
) {}
|
||||||
|
|
||||||
async ngOnInit(): Promise<void> {
|
async ngOnInit(): Promise<void> {
|
||||||
@@ -137,7 +139,10 @@ export class AccountSwitcherComponent implements OnInit, OnDestroy {
|
|||||||
|
|
||||||
async addAccount() {
|
async addAccount() {
|
||||||
this.close();
|
this.close();
|
||||||
await this.stateService.setRememberedEmail(null);
|
|
||||||
|
this.loginEmailService.setRememberEmail(false);
|
||||||
|
await this.loginEmailService.saveEmailSettings();
|
||||||
|
|
||||||
await this.router.navigate(["/login"]);
|
await this.router.navigate(["/login"]);
|
||||||
await this.stateService.setActiveUser(null);
|
await this.stateService.setActiveUser(null);
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -20,9 +20,7 @@ import { VaultTimeoutSettingsService } from "@bitwarden/common/abstractions/vaul
|
|||||||
import { PolicyService as PolicyServiceAbstraction } from "@bitwarden/common/admin-console/abstractions/policy/policy.service.abstraction";
|
import { PolicyService as PolicyServiceAbstraction } from "@bitwarden/common/admin-console/abstractions/policy/policy.service.abstraction";
|
||||||
import { AccountService as AccountServiceAbstraction } from "@bitwarden/common/auth/abstractions/account.service";
|
import { AccountService as AccountServiceAbstraction } from "@bitwarden/common/auth/abstractions/account.service";
|
||||||
import { AuthService as AuthServiceAbstraction } from "@bitwarden/common/auth/abstractions/auth.service";
|
import { AuthService as AuthServiceAbstraction } from "@bitwarden/common/auth/abstractions/auth.service";
|
||||||
import { LoginService as LoginServiceAbstraction } from "@bitwarden/common/auth/abstractions/login.service";
|
|
||||||
import { TokenService } from "@bitwarden/common/auth/abstractions/token.service";
|
import { TokenService } from "@bitwarden/common/auth/abstractions/token.service";
|
||||||
import { LoginService } from "@bitwarden/common/auth/services/login.service";
|
|
||||||
import { AutofillSettingsServiceAbstraction } from "@bitwarden/common/autofill/services/autofill-settings.service";
|
import { AutofillSettingsServiceAbstraction } from "@bitwarden/common/autofill/services/autofill-settings.service";
|
||||||
import { BroadcasterService as BroadcasterServiceAbstraction } from "@bitwarden/common/platform/abstractions/broadcaster.service";
|
import { BroadcasterService as BroadcasterServiceAbstraction } from "@bitwarden/common/platform/abstractions/broadcaster.service";
|
||||||
import { CryptoFunctionService as CryptoFunctionServiceAbstraction } from "@bitwarden/common/platform/abstractions/crypto-function.service";
|
import { CryptoFunctionService as CryptoFunctionServiceAbstraction } from "@bitwarden/common/platform/abstractions/crypto-function.service";
|
||||||
@@ -221,11 +219,6 @@ const safeProviders: SafeProvider[] = [
|
|||||||
DesktopAutofillSettingsService,
|
DesktopAutofillSettingsService,
|
||||||
],
|
],
|
||||||
}),
|
}),
|
||||||
safeProvider({
|
|
||||||
provide: LoginServiceAbstraction,
|
|
||||||
useClass: LoginService,
|
|
||||||
deps: [StateServiceAbstraction],
|
|
||||||
}),
|
|
||||||
safeProvider({
|
safeProvider({
|
||||||
provide: CryptoFunctionServiceAbstraction,
|
provide: CryptoFunctionServiceAbstraction,
|
||||||
useClass: RendererCryptoFunctionService,
|
useClass: RendererCryptoFunctionService,
|
||||||
|
|||||||
@@ -2,8 +2,8 @@ import { Component } from "@angular/core";
|
|||||||
import { Router } from "@angular/router";
|
import { Router } from "@angular/router";
|
||||||
|
|
||||||
import { HintComponent as BaseHintComponent } from "@bitwarden/angular/auth/components/hint.component";
|
import { HintComponent as BaseHintComponent } from "@bitwarden/angular/auth/components/hint.component";
|
||||||
|
import { LoginEmailServiceAbstraction } from "@bitwarden/auth/common";
|
||||||
import { ApiService } from "@bitwarden/common/abstractions/api.service";
|
import { ApiService } from "@bitwarden/common/abstractions/api.service";
|
||||||
import { LoginService } from "@bitwarden/common/auth/abstractions/login.service";
|
|
||||||
import { I18nService } from "@bitwarden/common/platform/abstractions/i18n.service";
|
import { I18nService } from "@bitwarden/common/platform/abstractions/i18n.service";
|
||||||
import { LogService } from "@bitwarden/common/platform/abstractions/log.service";
|
import { LogService } from "@bitwarden/common/platform/abstractions/log.service";
|
||||||
import { PlatformUtilsService } from "@bitwarden/common/platform/abstractions/platform-utils.service";
|
import { PlatformUtilsService } from "@bitwarden/common/platform/abstractions/platform-utils.service";
|
||||||
@@ -19,8 +19,8 @@ export class HintComponent extends BaseHintComponent {
|
|||||||
i18nService: I18nService,
|
i18nService: I18nService,
|
||||||
apiService: ApiService,
|
apiService: ApiService,
|
||||||
logService: LogService,
|
logService: LogService,
|
||||||
loginService: LoginService,
|
loginEmailService: LoginEmailServiceAbstraction,
|
||||||
) {
|
) {
|
||||||
super(router, i18nService, apiService, platformUtilsService, logService, loginService);
|
super(router, i18nService, apiService, platformUtilsService, logService, loginEmailService);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -7,12 +7,12 @@ import { ModalService } from "@bitwarden/angular/services/modal.service";
|
|||||||
import {
|
import {
|
||||||
AuthRequestServiceAbstraction,
|
AuthRequestServiceAbstraction,
|
||||||
LoginStrategyServiceAbstraction,
|
LoginStrategyServiceAbstraction,
|
||||||
|
LoginEmailServiceAbstraction,
|
||||||
} from "@bitwarden/auth/common";
|
} from "@bitwarden/auth/common";
|
||||||
import { ApiService } from "@bitwarden/common/abstractions/api.service";
|
import { ApiService } from "@bitwarden/common/abstractions/api.service";
|
||||||
import { AnonymousHubService } from "@bitwarden/common/auth/abstractions/anonymous-hub.service";
|
import { AnonymousHubService } from "@bitwarden/common/auth/abstractions/anonymous-hub.service";
|
||||||
import { AuthService } from "@bitwarden/common/auth/abstractions/auth.service";
|
import { AuthService } from "@bitwarden/common/auth/abstractions/auth.service";
|
||||||
import { DeviceTrustCryptoServiceAbstraction } from "@bitwarden/common/auth/abstractions/device-trust-crypto.service.abstraction";
|
import { DeviceTrustCryptoServiceAbstraction } from "@bitwarden/common/auth/abstractions/device-trust-crypto.service.abstraction";
|
||||||
import { LoginService } from "@bitwarden/common/auth/abstractions/login.service";
|
|
||||||
import { AppIdService } from "@bitwarden/common/platform/abstractions/app-id.service";
|
import { AppIdService } from "@bitwarden/common/platform/abstractions/app-id.service";
|
||||||
import { CryptoFunctionService } from "@bitwarden/common/platform/abstractions/crypto-function.service";
|
import { CryptoFunctionService } from "@bitwarden/common/platform/abstractions/crypto-function.service";
|
||||||
import { CryptoService } from "@bitwarden/common/platform/abstractions/crypto.service";
|
import { CryptoService } from "@bitwarden/common/platform/abstractions/crypto.service";
|
||||||
@@ -53,7 +53,7 @@ export class LoginViaAuthRequestComponent extends BaseLoginWithDeviceComponent {
|
|||||||
private modalService: ModalService,
|
private modalService: ModalService,
|
||||||
syncService: SyncService,
|
syncService: SyncService,
|
||||||
stateService: StateService,
|
stateService: StateService,
|
||||||
loginService: LoginService,
|
loginEmailService: LoginEmailServiceAbstraction,
|
||||||
deviceTrustCryptoService: DeviceTrustCryptoServiceAbstraction,
|
deviceTrustCryptoService: DeviceTrustCryptoServiceAbstraction,
|
||||||
authRequestService: AuthRequestServiceAbstraction,
|
authRequestService: AuthRequestServiceAbstraction,
|
||||||
loginStrategyService: LoginStrategyServiceAbstraction,
|
loginStrategyService: LoginStrategyServiceAbstraction,
|
||||||
@@ -74,7 +74,7 @@ export class LoginViaAuthRequestComponent extends BaseLoginWithDeviceComponent {
|
|||||||
anonymousHubService,
|
anonymousHubService,
|
||||||
validationService,
|
validationService,
|
||||||
stateService,
|
stateService,
|
||||||
loginService,
|
loginEmailService,
|
||||||
deviceTrustCryptoService,
|
deviceTrustCryptoService,
|
||||||
authRequestService,
|
authRequestService,
|
||||||
loginStrategyService,
|
loginStrategyService,
|
||||||
|
|||||||
@@ -99,7 +99,7 @@
|
|||||||
class="btn block"
|
class="btn block"
|
||||||
type="button"
|
type="button"
|
||||||
routerLink="/accessibility-cookie"
|
routerLink="/accessibility-cookie"
|
||||||
(click)="setFormValues()"
|
(click)="setLoginEmailValues()"
|
||||||
>
|
>
|
||||||
<i class="bwi bwi-universal-access" aria-hidden="true"></i>
|
<i class="bwi bwi-universal-access" aria-hidden="true"></i>
|
||||||
{{ "loadAccessibilityCookie" | i18n }}
|
{{ "loadAccessibilityCookie" | i18n }}
|
||||||
@@ -139,7 +139,7 @@
|
|||||||
type="button"
|
type="button"
|
||||||
class="text text-primary password-hint-btn"
|
class="text text-primary password-hint-btn"
|
||||||
routerLink="/hint"
|
routerLink="/hint"
|
||||||
(click)="setFormValues()"
|
(click)="setLoginEmailValues()"
|
||||||
>
|
>
|
||||||
{{ "getMasterPasswordHint" | i18n }}
|
{{ "getMasterPasswordHint" | i18n }}
|
||||||
</button>
|
</button>
|
||||||
|
|||||||
@@ -7,9 +7,11 @@ import { EnvironmentSelectorComponent } from "@bitwarden/angular/auth/components
|
|||||||
import { LoginComponent as BaseLoginComponent } from "@bitwarden/angular/auth/components/login.component";
|
import { LoginComponent as BaseLoginComponent } from "@bitwarden/angular/auth/components/login.component";
|
||||||
import { FormValidationErrorsService } from "@bitwarden/angular/platform/abstractions/form-validation-errors.service";
|
import { FormValidationErrorsService } from "@bitwarden/angular/platform/abstractions/form-validation-errors.service";
|
||||||
import { ModalService } from "@bitwarden/angular/services/modal.service";
|
import { ModalService } from "@bitwarden/angular/services/modal.service";
|
||||||
import { LoginStrategyServiceAbstraction } from "@bitwarden/auth/common";
|
import {
|
||||||
|
LoginStrategyServiceAbstraction,
|
||||||
|
LoginEmailServiceAbstraction,
|
||||||
|
} from "@bitwarden/auth/common";
|
||||||
import { DevicesApiServiceAbstraction } from "@bitwarden/common/auth/abstractions/devices-api.service.abstraction";
|
import { DevicesApiServiceAbstraction } from "@bitwarden/common/auth/abstractions/devices-api.service.abstraction";
|
||||||
import { LoginService } from "@bitwarden/common/auth/abstractions/login.service";
|
|
||||||
import { SsoLoginServiceAbstraction } from "@bitwarden/common/auth/abstractions/sso-login.service.abstraction";
|
import { SsoLoginServiceAbstraction } from "@bitwarden/common/auth/abstractions/sso-login.service.abstraction";
|
||||||
import { WebAuthnLoginServiceAbstraction } from "@bitwarden/common/auth/abstractions/webauthn/webauthn-login.service.abstraction";
|
import { WebAuthnLoginServiceAbstraction } from "@bitwarden/common/auth/abstractions/webauthn/webauthn-login.service.abstraction";
|
||||||
import { AppIdService } from "@bitwarden/common/platform/abstractions/app-id.service";
|
import { AppIdService } from "@bitwarden/common/platform/abstractions/app-id.service";
|
||||||
@@ -69,7 +71,7 @@ export class LoginComponent extends BaseLoginComponent implements OnDestroy {
|
|||||||
formBuilder: FormBuilder,
|
formBuilder: FormBuilder,
|
||||||
formValidationErrorService: FormValidationErrorsService,
|
formValidationErrorService: FormValidationErrorsService,
|
||||||
route: ActivatedRoute,
|
route: ActivatedRoute,
|
||||||
loginService: LoginService,
|
loginEmailService: LoginEmailServiceAbstraction,
|
||||||
ssoLoginService: SsoLoginServiceAbstraction,
|
ssoLoginService: SsoLoginServiceAbstraction,
|
||||||
webAuthnLoginService: WebAuthnLoginServiceAbstraction,
|
webAuthnLoginService: WebAuthnLoginServiceAbstraction,
|
||||||
) {
|
) {
|
||||||
@@ -89,7 +91,7 @@ export class LoginComponent extends BaseLoginComponent implements OnDestroy {
|
|||||||
formBuilder,
|
formBuilder,
|
||||||
formValidationErrorService,
|
formValidationErrorService,
|
||||||
route,
|
route,
|
||||||
loginService,
|
loginEmailService,
|
||||||
ssoLoginService,
|
ssoLoginService,
|
||||||
webAuthnLoginService,
|
webAuthnLoginService,
|
||||||
);
|
);
|
||||||
|
|||||||
@@ -7,10 +7,10 @@ import { WINDOW } from "@bitwarden/angular/services/injection-tokens";
|
|||||||
import { ModalService } from "@bitwarden/angular/services/modal.service";
|
import { ModalService } from "@bitwarden/angular/services/modal.service";
|
||||||
import {
|
import {
|
||||||
LoginStrategyServiceAbstraction,
|
LoginStrategyServiceAbstraction,
|
||||||
|
LoginEmailServiceAbstraction,
|
||||||
UserDecryptionOptionsServiceAbstraction,
|
UserDecryptionOptionsServiceAbstraction,
|
||||||
} from "@bitwarden/auth/common";
|
} from "@bitwarden/auth/common";
|
||||||
import { ApiService } from "@bitwarden/common/abstractions/api.service";
|
import { ApiService } from "@bitwarden/common/abstractions/api.service";
|
||||||
import { LoginService } from "@bitwarden/common/auth/abstractions/login.service";
|
|
||||||
import { SsoLoginServiceAbstraction } from "@bitwarden/common/auth/abstractions/sso-login.service.abstraction";
|
import { SsoLoginServiceAbstraction } from "@bitwarden/common/auth/abstractions/sso-login.service.abstraction";
|
||||||
import { TwoFactorService } from "@bitwarden/common/auth/abstractions/two-factor.service";
|
import { TwoFactorService } from "@bitwarden/common/auth/abstractions/two-factor.service";
|
||||||
import { TwoFactorProviderType } from "@bitwarden/common/auth/enums/two-factor-provider-type";
|
import { TwoFactorProviderType } from "@bitwarden/common/auth/enums/two-factor-provider-type";
|
||||||
@@ -56,7 +56,7 @@ export class TwoFactorComponent extends BaseTwoFactorComponent {
|
|||||||
logService: LogService,
|
logService: LogService,
|
||||||
twoFactorService: TwoFactorService,
|
twoFactorService: TwoFactorService,
|
||||||
appIdService: AppIdService,
|
appIdService: AppIdService,
|
||||||
loginService: LoginService,
|
loginEmailService: LoginEmailServiceAbstraction,
|
||||||
userDecryptionOptionsService: UserDecryptionOptionsServiceAbstraction,
|
userDecryptionOptionsService: UserDecryptionOptionsServiceAbstraction,
|
||||||
ssoLoginService: SsoLoginServiceAbstraction,
|
ssoLoginService: SsoLoginServiceAbstraction,
|
||||||
configService: ConfigService,
|
configService: ConfigService,
|
||||||
@@ -75,7 +75,7 @@ export class TwoFactorComponent extends BaseTwoFactorComponent {
|
|||||||
logService,
|
logService,
|
||||||
twoFactorService,
|
twoFactorService,
|
||||||
appIdService,
|
appIdService,
|
||||||
loginService,
|
loginEmailService,
|
||||||
userDecryptionOptionsService,
|
userDecryptionOptionsService,
|
||||||
ssoLoginService,
|
ssoLoginService,
|
||||||
configService,
|
configService,
|
||||||
|
|||||||
@@ -2,8 +2,8 @@ import { Component } from "@angular/core";
|
|||||||
import { Router } from "@angular/router";
|
import { Router } from "@angular/router";
|
||||||
|
|
||||||
import { HintComponent as BaseHintComponent } from "@bitwarden/angular/auth/components/hint.component";
|
import { HintComponent as BaseHintComponent } from "@bitwarden/angular/auth/components/hint.component";
|
||||||
|
import { LoginEmailServiceAbstraction } from "@bitwarden/auth/common";
|
||||||
import { ApiService } from "@bitwarden/common/abstractions/api.service";
|
import { ApiService } from "@bitwarden/common/abstractions/api.service";
|
||||||
import { LoginService } from "@bitwarden/common/auth/abstractions/login.service";
|
|
||||||
import { I18nService } from "@bitwarden/common/platform/abstractions/i18n.service";
|
import { I18nService } from "@bitwarden/common/platform/abstractions/i18n.service";
|
||||||
import { LogService } from "@bitwarden/common/platform/abstractions/log.service";
|
import { LogService } from "@bitwarden/common/platform/abstractions/log.service";
|
||||||
import { PlatformUtilsService } from "@bitwarden/common/platform/abstractions/platform-utils.service";
|
import { PlatformUtilsService } from "@bitwarden/common/platform/abstractions/platform-utils.service";
|
||||||
@@ -19,8 +19,8 @@ export class HintComponent extends BaseHintComponent {
|
|||||||
apiService: ApiService,
|
apiService: ApiService,
|
||||||
platformUtilsService: PlatformUtilsService,
|
platformUtilsService: PlatformUtilsService,
|
||||||
logService: LogService,
|
logService: LogService,
|
||||||
loginService: LoginService,
|
loginEmailService: LoginEmailServiceAbstraction,
|
||||||
) {
|
) {
|
||||||
super(router, i18nService, apiService, platformUtilsService, logService, loginService);
|
super(router, i18nService, apiService, platformUtilsService, logService, loginEmailService);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -1,6 +1,6 @@
|
|||||||
<form
|
<form
|
||||||
#form
|
#form
|
||||||
(ngSubmit)="submit()"
|
(ngSubmit)="submit(false)"
|
||||||
[appApiAction]="formPromise"
|
[appApiAction]="formPromise"
|
||||||
class="tw-container tw-mx-auto"
|
class="tw-container tw-mx-auto"
|
||||||
[formGroup]="formGroup"
|
[formGroup]="formGroup"
|
||||||
@@ -91,7 +91,7 @@
|
|||||||
class="-tw-mt-2"
|
class="-tw-mt-2"
|
||||||
routerLink="/hint"
|
routerLink="/hint"
|
||||||
(mousedown)="goToHint()"
|
(mousedown)="goToHint()"
|
||||||
(click)="setFormValues()"
|
(click)="setLoginEmailValues()"
|
||||||
>{{ "getMasterPasswordHint" | i18n }}</a
|
>{{ "getMasterPasswordHint" | i18n }}</a
|
||||||
>
|
>
|
||||||
</div>
|
</div>
|
||||||
|
|||||||
@@ -6,7 +6,10 @@ import { first } from "rxjs/operators";
|
|||||||
|
|
||||||
import { LoginComponent as BaseLoginComponent } from "@bitwarden/angular/auth/components/login.component";
|
import { LoginComponent as BaseLoginComponent } from "@bitwarden/angular/auth/components/login.component";
|
||||||
import { FormValidationErrorsService } from "@bitwarden/angular/platform/abstractions/form-validation-errors.service";
|
import { FormValidationErrorsService } from "@bitwarden/angular/platform/abstractions/form-validation-errors.service";
|
||||||
import { LoginStrategyServiceAbstraction } from "@bitwarden/auth/common";
|
import {
|
||||||
|
LoginStrategyServiceAbstraction,
|
||||||
|
LoginEmailServiceAbstraction,
|
||||||
|
} from "@bitwarden/auth/common";
|
||||||
import { PolicyApiServiceAbstraction } from "@bitwarden/common/admin-console/abstractions/policy/policy-api.service.abstraction";
|
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 { InternalPolicyService } from "@bitwarden/common/admin-console/abstractions/policy/policy.service.abstraction";
|
||||||
import { PolicyData } from "@bitwarden/common/admin-console/models/data/policy.data";
|
import { PolicyData } from "@bitwarden/common/admin-console/models/data/policy.data";
|
||||||
@@ -14,7 +17,6 @@ import { MasterPasswordPolicyOptions } from "@bitwarden/common/admin-console/mod
|
|||||||
import { Policy } from "@bitwarden/common/admin-console/models/domain/policy";
|
import { Policy } from "@bitwarden/common/admin-console/models/domain/policy";
|
||||||
import { PolicyResponse } from "@bitwarden/common/admin-console/models/response/policy.response";
|
import { PolicyResponse } from "@bitwarden/common/admin-console/models/response/policy.response";
|
||||||
import { DevicesApiServiceAbstraction } from "@bitwarden/common/auth/abstractions/devices-api.service.abstraction";
|
import { DevicesApiServiceAbstraction } from "@bitwarden/common/auth/abstractions/devices-api.service.abstraction";
|
||||||
import { LoginService } from "@bitwarden/common/auth/abstractions/login.service";
|
|
||||||
import { SsoLoginServiceAbstraction } from "@bitwarden/common/auth/abstractions/sso-login.service.abstraction";
|
import { SsoLoginServiceAbstraction } from "@bitwarden/common/auth/abstractions/sso-login.service.abstraction";
|
||||||
import { WebAuthnLoginServiceAbstraction } from "@bitwarden/common/auth/abstractions/webauthn/webauthn-login.service.abstraction";
|
import { WebAuthnLoginServiceAbstraction } from "@bitwarden/common/auth/abstractions/webauthn/webauthn-login.service.abstraction";
|
||||||
import { AuthResult } from "@bitwarden/common/auth/models/domain/auth-result";
|
import { AuthResult } from "@bitwarden/common/auth/models/domain/auth-result";
|
||||||
@@ -62,7 +64,7 @@ export class LoginComponent extends BaseLoginComponent implements OnInit {
|
|||||||
private routerService: RouterService,
|
private routerService: RouterService,
|
||||||
formBuilder: FormBuilder,
|
formBuilder: FormBuilder,
|
||||||
formValidationErrorService: FormValidationErrorsService,
|
formValidationErrorService: FormValidationErrorsService,
|
||||||
loginService: LoginService,
|
loginEmailService: LoginEmailServiceAbstraction,
|
||||||
ssoLoginService: SsoLoginServiceAbstraction,
|
ssoLoginService: SsoLoginServiceAbstraction,
|
||||||
webAuthnLoginService: WebAuthnLoginServiceAbstraction,
|
webAuthnLoginService: WebAuthnLoginServiceAbstraction,
|
||||||
) {
|
) {
|
||||||
@@ -82,7 +84,7 @@ export class LoginComponent extends BaseLoginComponent implements OnInit {
|
|||||||
formBuilder,
|
formBuilder,
|
||||||
formValidationErrorService,
|
formValidationErrorService,
|
||||||
route,
|
route,
|
||||||
loginService,
|
loginEmailService,
|
||||||
ssoLoginService,
|
ssoLoginService,
|
||||||
webAuthnLoginService,
|
webAuthnLoginService,
|
||||||
);
|
);
|
||||||
@@ -173,14 +175,14 @@ export class LoginComponent extends BaseLoginComponent implements OnInit {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
this.loginService.clearValues();
|
this.loginEmailService.clearValues();
|
||||||
// FIXME: Verify that this floating promise is intentional. If it is, add an explanatory comment and ensure there is proper error handling.
|
// FIXME: Verify that this floating promise is intentional. If it is, add an explanatory comment and ensure there is proper error handling.
|
||||||
// eslint-disable-next-line @typescript-eslint/no-floating-promises
|
// eslint-disable-next-line @typescript-eslint/no-floating-promises
|
||||||
this.router.navigate([this.successRoute]);
|
this.router.navigate([this.successRoute]);
|
||||||
}
|
}
|
||||||
|
|
||||||
goToHint() {
|
goToHint() {
|
||||||
this.setFormValues();
|
this.setLoginEmailValues();
|
||||||
// FIXME: Verify that this floating promise is intentional. If it is, add an explanatory comment and ensure there is proper error handling.
|
// FIXME: Verify that this floating promise is intentional. If it is, add an explanatory comment and ensure there is proper error handling.
|
||||||
// eslint-disable-next-line @typescript-eslint/no-floating-promises
|
// eslint-disable-next-line @typescript-eslint/no-floating-promises
|
||||||
this.router.navigateByUrl("/hint");
|
this.router.navigateByUrl("/hint");
|
||||||
@@ -201,15 +203,6 @@ export class LoginComponent extends BaseLoginComponent implements OnInit {
|
|||||||
this.router.navigate(["/register"]);
|
this.router.navigate(["/register"]);
|
||||||
}
|
}
|
||||||
|
|
||||||
async submit() {
|
|
||||||
const rememberEmail = this.formGroup.value.rememberEmail;
|
|
||||||
|
|
||||||
if (!rememberEmail) {
|
|
||||||
await this.stateService.setRememberedEmail(null);
|
|
||||||
}
|
|
||||||
await super.submit(false);
|
|
||||||
}
|
|
||||||
|
|
||||||
protected override handleMigrateEncryptionKey(result: AuthResult): boolean {
|
protected override handleMigrateEncryptionKey(result: AuthResult): boolean {
|
||||||
if (!result.requiresEncryptionKeyMigration) {
|
if (!result.requiresEncryptionKeyMigration) {
|
||||||
return false;
|
return false;
|
||||||
|
|||||||
@@ -6,10 +6,10 @@ import { WINDOW } from "@bitwarden/angular/services/injection-tokens";
|
|||||||
import { ModalService } from "@bitwarden/angular/services/modal.service";
|
import { ModalService } from "@bitwarden/angular/services/modal.service";
|
||||||
import {
|
import {
|
||||||
LoginStrategyServiceAbstraction,
|
LoginStrategyServiceAbstraction,
|
||||||
|
LoginEmailServiceAbstraction,
|
||||||
UserDecryptionOptionsServiceAbstraction,
|
UserDecryptionOptionsServiceAbstraction,
|
||||||
} from "@bitwarden/auth/common";
|
} from "@bitwarden/auth/common";
|
||||||
import { ApiService } from "@bitwarden/common/abstractions/api.service";
|
import { ApiService } from "@bitwarden/common/abstractions/api.service";
|
||||||
import { LoginService } from "@bitwarden/common/auth/abstractions/login.service";
|
|
||||||
import { SsoLoginServiceAbstraction } from "@bitwarden/common/auth/abstractions/sso-login.service.abstraction";
|
import { SsoLoginServiceAbstraction } from "@bitwarden/common/auth/abstractions/sso-login.service.abstraction";
|
||||||
import { TwoFactorService } from "@bitwarden/common/auth/abstractions/two-factor.service";
|
import { TwoFactorService } from "@bitwarden/common/auth/abstractions/two-factor.service";
|
||||||
import { TwoFactorProviderType } from "@bitwarden/common/auth/enums/two-factor-provider-type";
|
import { TwoFactorProviderType } from "@bitwarden/common/auth/enums/two-factor-provider-type";
|
||||||
@@ -46,7 +46,7 @@ export class TwoFactorComponent extends BaseTwoFactorComponent implements OnDest
|
|||||||
logService: LogService,
|
logService: LogService,
|
||||||
twoFactorService: TwoFactorService,
|
twoFactorService: TwoFactorService,
|
||||||
appIdService: AppIdService,
|
appIdService: AppIdService,
|
||||||
loginService: LoginService,
|
loginEmailService: LoginEmailServiceAbstraction,
|
||||||
userDecryptionOptionsService: UserDecryptionOptionsServiceAbstraction,
|
userDecryptionOptionsService: UserDecryptionOptionsServiceAbstraction,
|
||||||
ssoLoginService: SsoLoginServiceAbstraction,
|
ssoLoginService: SsoLoginServiceAbstraction,
|
||||||
configService: ConfigService,
|
configService: ConfigService,
|
||||||
@@ -65,7 +65,7 @@ export class TwoFactorComponent extends BaseTwoFactorComponent implements OnDest
|
|||||||
logService,
|
logService,
|
||||||
twoFactorService,
|
twoFactorService,
|
||||||
appIdService,
|
appIdService,
|
||||||
loginService,
|
loginEmailService,
|
||||||
userDecryptionOptionsService,
|
userDecryptionOptionsService,
|
||||||
ssoLoginService,
|
ssoLoginService,
|
||||||
configService,
|
configService,
|
||||||
@@ -103,7 +103,7 @@ export class TwoFactorComponent extends BaseTwoFactorComponent implements OnDest
|
|||||||
}
|
}
|
||||||
|
|
||||||
goAfterLogIn = async () => {
|
goAfterLogIn = async () => {
|
||||||
this.loginService.clearValues();
|
this.loginEmailService.clearValues();
|
||||||
// FIXME: Verify that this floating promise is intentional. If it is, add an explanatory comment and ensure there is proper error handling.
|
// FIXME: Verify that this floating promise is intentional. If it is, add an explanatory comment and ensure there is proper error handling.
|
||||||
// eslint-disable-next-line @typescript-eslint/no-floating-promises
|
// eslint-disable-next-line @typescript-eslint/no-floating-promises
|
||||||
this.router.navigate([this.successRoute], {
|
this.router.navigate([this.successRoute], {
|
||||||
|
|||||||
@@ -16,8 +16,6 @@ import {
|
|||||||
import { JslibServicesModule } from "@bitwarden/angular/services/jslib-services.module";
|
import { JslibServicesModule } from "@bitwarden/angular/services/jslib-services.module";
|
||||||
import { ModalService as ModalServiceAbstraction } from "@bitwarden/angular/services/modal.service";
|
import { ModalService as ModalServiceAbstraction } from "@bitwarden/angular/services/modal.service";
|
||||||
import { AccountService } from "@bitwarden/common/auth/abstractions/account.service";
|
import { AccountService } from "@bitwarden/common/auth/abstractions/account.service";
|
||||||
import { LoginService as LoginServiceAbstraction } from "@bitwarden/common/auth/abstractions/login.service";
|
|
||||||
import { LoginService } from "@bitwarden/common/auth/services/login.service";
|
|
||||||
import { EnvironmentService } from "@bitwarden/common/platform/abstractions/environment.service";
|
import { EnvironmentService } from "@bitwarden/common/platform/abstractions/environment.service";
|
||||||
import { FileDownloadService } from "@bitwarden/common/platform/abstractions/file-download/file-download.service";
|
import { FileDownloadService } from "@bitwarden/common/platform/abstractions/file-download/file-download.service";
|
||||||
import { I18nService as I18nServiceAbstraction } from "@bitwarden/common/platform/abstractions/i18n.service";
|
import { I18nService as I18nServiceAbstraction } from "@bitwarden/common/platform/abstractions/i18n.service";
|
||||||
@@ -29,6 +27,7 @@ import { AbstractStorageService } from "@bitwarden/common/platform/abstractions/
|
|||||||
import { ThemeType } from "@bitwarden/common/platform/enums";
|
import { ThemeType } from "@bitwarden/common/platform/enums";
|
||||||
import { StateFactory } from "@bitwarden/common/platform/factories/state-factory";
|
import { StateFactory } from "@bitwarden/common/platform/factories/state-factory";
|
||||||
import { MemoryStorageService } from "@bitwarden/common/platform/services/memory-storage.service";
|
import { MemoryStorageService } from "@bitwarden/common/platform/services/memory-storage.service";
|
||||||
|
// eslint-disable-next-line import/no-restricted-paths -- Implementation for memory storage
|
||||||
import { MigrationBuilderService } from "@bitwarden/common/platform/services/migration-builder.service";
|
import { MigrationBuilderService } from "@bitwarden/common/platform/services/migration-builder.service";
|
||||||
import { MigrationRunner } from "@bitwarden/common/platform/services/migration-runner";
|
import { MigrationRunner } from "@bitwarden/common/platform/services/migration-runner";
|
||||||
import { StorageServiceProvider } from "@bitwarden/common/platform/services/storage-service.provider";
|
import { StorageServiceProvider } from "@bitwarden/common/platform/services/storage-service.provider";
|
||||||
@@ -117,11 +116,6 @@ import { WebPlatformUtilsService } from "./web-platform-utils.service";
|
|||||||
provide: FileDownloadService,
|
provide: FileDownloadService,
|
||||||
useClass: WebFileDownloadService,
|
useClass: WebFileDownloadService,
|
||||||
},
|
},
|
||||||
{
|
|
||||||
provide: LoginServiceAbstraction,
|
|
||||||
useClass: LoginService,
|
|
||||||
deps: [StateService],
|
|
||||||
},
|
|
||||||
CollectionAdminService,
|
CollectionAdminService,
|
||||||
{
|
{
|
||||||
provide: OBSERVABLE_DISK_LOCAL_STORAGE,
|
provide: OBSERVABLE_DISK_LOCAL_STORAGE,
|
||||||
|
|||||||
@@ -15,6 +15,7 @@ import {
|
|||||||
} from "rxjs";
|
} from "rxjs";
|
||||||
|
|
||||||
import {
|
import {
|
||||||
|
LoginEmailServiceAbstraction,
|
||||||
UserDecryptionOptions,
|
UserDecryptionOptions,
|
||||||
UserDecryptionOptionsServiceAbstraction,
|
UserDecryptionOptionsServiceAbstraction,
|
||||||
} from "@bitwarden/auth/common";
|
} from "@bitwarden/auth/common";
|
||||||
@@ -23,7 +24,6 @@ import { OrganizationApiServiceAbstraction } from "@bitwarden/common/admin-conso
|
|||||||
import { OrganizationUserService } from "@bitwarden/common/admin-console/abstractions/organization-user/organization-user.service";
|
import { OrganizationUserService } from "@bitwarden/common/admin-console/abstractions/organization-user/organization-user.service";
|
||||||
import { DeviceTrustCryptoServiceAbstraction } from "@bitwarden/common/auth/abstractions/device-trust-crypto.service.abstraction";
|
import { DeviceTrustCryptoServiceAbstraction } from "@bitwarden/common/auth/abstractions/device-trust-crypto.service.abstraction";
|
||||||
import { DevicesServiceAbstraction } from "@bitwarden/common/auth/abstractions/devices/devices.service.abstraction";
|
import { DevicesServiceAbstraction } from "@bitwarden/common/auth/abstractions/devices/devices.service.abstraction";
|
||||||
import { LoginService } from "@bitwarden/common/auth/abstractions/login.service";
|
|
||||||
import { PasswordResetEnrollmentServiceAbstraction } from "@bitwarden/common/auth/abstractions/password-reset-enrollment.service.abstraction";
|
import { PasswordResetEnrollmentServiceAbstraction } from "@bitwarden/common/auth/abstractions/password-reset-enrollment.service.abstraction";
|
||||||
import { SsoLoginServiceAbstraction } from "@bitwarden/common/auth/abstractions/sso-login.service.abstraction";
|
import { SsoLoginServiceAbstraction } from "@bitwarden/common/auth/abstractions/sso-login.service.abstraction";
|
||||||
import { TokenService } from "@bitwarden/common/auth/abstractions/token.service";
|
import { TokenService } from "@bitwarden/common/auth/abstractions/token.service";
|
||||||
@@ -82,7 +82,7 @@ export class BaseLoginDecryptionOptionsComponent implements OnInit, OnDestroy {
|
|||||||
protected activatedRoute: ActivatedRoute,
|
protected activatedRoute: ActivatedRoute,
|
||||||
protected messagingService: MessagingService,
|
protected messagingService: MessagingService,
|
||||||
protected tokenService: TokenService,
|
protected tokenService: TokenService,
|
||||||
protected loginService: LoginService,
|
protected loginEmailService: LoginEmailServiceAbstraction,
|
||||||
protected organizationApiService: OrganizationApiServiceAbstraction,
|
protected organizationApiService: OrganizationApiServiceAbstraction,
|
||||||
protected cryptoService: CryptoService,
|
protected cryptoService: CryptoService,
|
||||||
protected organizationUserService: OrganizationUserService,
|
protected organizationUserService: OrganizationUserService,
|
||||||
@@ -244,23 +244,17 @@ export class BaseLoginDecryptionOptionsComponent implements OnInit, OnDestroy {
|
|||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
this.loginService.setEmail(this.data.userEmail);
|
this.loginEmailService.setEmail(this.data.userEmail);
|
||||||
// FIXME: Verify that this floating promise is intentional. If it is, add an explanatory comment and ensure there is proper error handling.
|
await this.router.navigate(["/login-with-device"]);
|
||||||
// eslint-disable-next-line @typescript-eslint/no-floating-promises
|
|
||||||
this.router.navigate(["/login-with-device"]);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
async requestAdminApproval() {
|
async requestAdminApproval() {
|
||||||
this.loginService.setEmail(this.data.userEmail);
|
this.loginEmailService.setEmail(this.data.userEmail);
|
||||||
// FIXME: Verify that this floating promise is intentional. If it is, add an explanatory comment and ensure there is proper error handling.
|
await this.router.navigate(["/admin-approval-requested"]);
|
||||||
// eslint-disable-next-line @typescript-eslint/no-floating-promises
|
|
||||||
this.router.navigate(["/admin-approval-requested"]);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
async approveWithMasterPassword() {
|
async approveWithMasterPassword() {
|
||||||
// FIXME: Verify that this floating promise is intentional. If it is, add an explanatory comment and ensure there is proper error handling.
|
await this.router.navigate(["/lock"], { queryParams: { from: "login-initiated" } });
|
||||||
// eslint-disable-next-line @typescript-eslint/no-floating-promises
|
|
||||||
this.router.navigate(["/lock"], { queryParams: { from: "login-initiated" } });
|
|
||||||
}
|
}
|
||||||
|
|
||||||
async createUser() {
|
async createUser() {
|
||||||
|
|||||||
@@ -1,8 +1,8 @@
|
|||||||
import { Directive, OnInit } from "@angular/core";
|
import { Directive, OnInit } from "@angular/core";
|
||||||
import { Router } from "@angular/router";
|
import { Router } from "@angular/router";
|
||||||
|
|
||||||
|
import { LoginEmailServiceAbstraction } from "@bitwarden/auth/common";
|
||||||
import { ApiService } from "@bitwarden/common/abstractions/api.service";
|
import { ApiService } from "@bitwarden/common/abstractions/api.service";
|
||||||
import { LoginService } from "@bitwarden/common/auth/abstractions/login.service";
|
|
||||||
import { PasswordHintRequest } from "@bitwarden/common/auth/models/request/password-hint.request";
|
import { PasswordHintRequest } from "@bitwarden/common/auth/models/request/password-hint.request";
|
||||||
import { I18nService } from "@bitwarden/common/platform/abstractions/i18n.service";
|
import { I18nService } from "@bitwarden/common/platform/abstractions/i18n.service";
|
||||||
import { LogService } from "@bitwarden/common/platform/abstractions/log.service";
|
import { LogService } from "@bitwarden/common/platform/abstractions/log.service";
|
||||||
@@ -22,11 +22,11 @@ export class HintComponent implements OnInit {
|
|||||||
protected apiService: ApiService,
|
protected apiService: ApiService,
|
||||||
protected platformUtilsService: PlatformUtilsService,
|
protected platformUtilsService: PlatformUtilsService,
|
||||||
private logService: LogService,
|
private logService: LogService,
|
||||||
private loginService: LoginService,
|
private loginEmailService: LoginEmailServiceAbstraction,
|
||||||
) {}
|
) {}
|
||||||
|
|
||||||
ngOnInit(): void {
|
ngOnInit(): void {
|
||||||
this.email = this.loginService.getEmail() ?? "";
|
this.email = this.loginEmailService.getEmail() ?? "";
|
||||||
}
|
}
|
||||||
|
|
||||||
async submit() {
|
async submit() {
|
||||||
|
|||||||
@@ -6,12 +6,12 @@ import {
|
|||||||
AuthRequestLoginCredentials,
|
AuthRequestLoginCredentials,
|
||||||
AuthRequestServiceAbstraction,
|
AuthRequestServiceAbstraction,
|
||||||
LoginStrategyServiceAbstraction,
|
LoginStrategyServiceAbstraction,
|
||||||
|
LoginEmailServiceAbstraction,
|
||||||
} from "@bitwarden/auth/common";
|
} from "@bitwarden/auth/common";
|
||||||
import { ApiService } from "@bitwarden/common/abstractions/api.service";
|
import { ApiService } from "@bitwarden/common/abstractions/api.service";
|
||||||
import { AnonymousHubService } from "@bitwarden/common/auth/abstractions/anonymous-hub.service";
|
import { AnonymousHubService } from "@bitwarden/common/auth/abstractions/anonymous-hub.service";
|
||||||
import { AuthService } from "@bitwarden/common/auth/abstractions/auth.service";
|
import { AuthService } from "@bitwarden/common/auth/abstractions/auth.service";
|
||||||
import { DeviceTrustCryptoServiceAbstraction } from "@bitwarden/common/auth/abstractions/device-trust-crypto.service.abstraction";
|
import { DeviceTrustCryptoServiceAbstraction } from "@bitwarden/common/auth/abstractions/device-trust-crypto.service.abstraction";
|
||||||
import { LoginService } from "@bitwarden/common/auth/abstractions/login.service";
|
|
||||||
import { AuthRequestType } from "@bitwarden/common/auth/enums/auth-request-type";
|
import { AuthRequestType } from "@bitwarden/common/auth/enums/auth-request-type";
|
||||||
import { AuthenticationStatus } from "@bitwarden/common/auth/enums/authentication-status";
|
import { AuthenticationStatus } from "@bitwarden/common/auth/enums/authentication-status";
|
||||||
import { AdminAuthRequestStorable } from "@bitwarden/common/auth/models/domain/admin-auth-req-storable";
|
import { AdminAuthRequestStorable } from "@bitwarden/common/auth/models/domain/admin-auth-req-storable";
|
||||||
@@ -83,7 +83,7 @@ export class LoginViaAuthRequestComponent
|
|||||||
private anonymousHubService: AnonymousHubService,
|
private anonymousHubService: AnonymousHubService,
|
||||||
private validationService: ValidationService,
|
private validationService: ValidationService,
|
||||||
private stateService: StateService,
|
private stateService: StateService,
|
||||||
private loginService: LoginService,
|
private loginEmailService: LoginEmailServiceAbstraction,
|
||||||
private deviceTrustCryptoService: DeviceTrustCryptoServiceAbstraction,
|
private deviceTrustCryptoService: DeviceTrustCryptoServiceAbstraction,
|
||||||
private authRequestService: AuthRequestServiceAbstraction,
|
private authRequestService: AuthRequestServiceAbstraction,
|
||||||
private loginStrategyService: LoginStrategyServiceAbstraction,
|
private loginStrategyService: LoginStrategyServiceAbstraction,
|
||||||
@@ -94,7 +94,7 @@ export class LoginViaAuthRequestComponent
|
|||||||
// Why would the existence of the email depend on the navigation?
|
// Why would the existence of the email depend on the navigation?
|
||||||
const navigation = this.router.getCurrentNavigation();
|
const navigation = this.router.getCurrentNavigation();
|
||||||
if (navigation) {
|
if (navigation) {
|
||||||
this.email = this.loginService.getEmail();
|
this.email = this.loginEmailService.getEmail();
|
||||||
}
|
}
|
||||||
|
|
||||||
// Gets signalR push notification
|
// Gets signalR push notification
|
||||||
@@ -151,7 +151,7 @@ export class LoginViaAuthRequestComponent
|
|||||||
} else {
|
} else {
|
||||||
// Standard auth request
|
// Standard auth request
|
||||||
// TODO: evaluate if we can remove the setting of this.email in the constructor
|
// TODO: evaluate if we can remove the setting of this.email in the constructor
|
||||||
this.email = this.loginService.getEmail();
|
this.email = this.loginEmailService.getEmail();
|
||||||
|
|
||||||
if (!this.email) {
|
if (!this.email) {
|
||||||
this.platformUtilsService.showToast("error", null, this.i18nService.t("userEmailMissing"));
|
this.platformUtilsService.showToast("error", null, this.i18nService.t("userEmailMissing"));
|
||||||
@@ -472,17 +472,10 @@ export class LoginViaAuthRequestComponent
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
async setRememberEmailValues() {
|
|
||||||
const rememberEmail = this.loginService.getRememberEmail();
|
|
||||||
const rememberedEmail = this.loginService.getEmail();
|
|
||||||
await this.stateService.setRememberedEmail(rememberEmail ? rememberedEmail : null);
|
|
||||||
this.loginService.clearValues();
|
|
||||||
}
|
|
||||||
|
|
||||||
private async handleSuccessfulLoginNavigation() {
|
private async handleSuccessfulLoginNavigation() {
|
||||||
if (this.state === State.StandardAuthRequest) {
|
if (this.state === State.StandardAuthRequest) {
|
||||||
// Only need to set remembered email on standard login with auth req flow
|
// Only need to set remembered email on standard login with auth req flow
|
||||||
await this.setRememberEmailValues();
|
await this.loginEmailService.saveEmailSettings();
|
||||||
}
|
}
|
||||||
|
|
||||||
if (this.onSuccessfulLogin != null) {
|
if (this.onSuccessfulLogin != null) {
|
||||||
|
|||||||
@@ -4,9 +4,12 @@ import { ActivatedRoute, Router } from "@angular/router";
|
|||||||
import { Subject, firstValueFrom } from "rxjs";
|
import { Subject, firstValueFrom } from "rxjs";
|
||||||
import { take, takeUntil } from "rxjs/operators";
|
import { take, takeUntil } from "rxjs/operators";
|
||||||
|
|
||||||
import { LoginStrategyServiceAbstraction, PasswordLoginCredentials } from "@bitwarden/auth/common";
|
import {
|
||||||
|
LoginStrategyServiceAbstraction,
|
||||||
|
LoginEmailServiceAbstraction,
|
||||||
|
PasswordLoginCredentials,
|
||||||
|
} from "@bitwarden/auth/common";
|
||||||
import { DevicesApiServiceAbstraction } from "@bitwarden/common/auth/abstractions/devices-api.service.abstraction";
|
import { DevicesApiServiceAbstraction } from "@bitwarden/common/auth/abstractions/devices-api.service.abstraction";
|
||||||
import { LoginService } from "@bitwarden/common/auth/abstractions/login.service";
|
|
||||||
import { SsoLoginServiceAbstraction } from "@bitwarden/common/auth/abstractions/sso-login.service.abstraction";
|
import { SsoLoginServiceAbstraction } from "@bitwarden/common/auth/abstractions/sso-login.service.abstraction";
|
||||||
import { WebAuthnLoginServiceAbstraction } from "@bitwarden/common/auth/abstractions/webauthn/webauthn-login.service.abstraction";
|
import { WebAuthnLoginServiceAbstraction } from "@bitwarden/common/auth/abstractions/webauthn/webauthn-login.service.abstraction";
|
||||||
import { AuthResult } from "@bitwarden/common/auth/models/domain/auth-result";
|
import { AuthResult } from "@bitwarden/common/auth/models/domain/auth-result";
|
||||||
@@ -77,7 +80,7 @@ export class LoginComponent extends CaptchaProtectedComponent implements OnInit,
|
|||||||
protected formBuilder: FormBuilder,
|
protected formBuilder: FormBuilder,
|
||||||
protected formValidationErrorService: FormValidationErrorsService,
|
protected formValidationErrorService: FormValidationErrorsService,
|
||||||
protected route: ActivatedRoute,
|
protected route: ActivatedRoute,
|
||||||
protected loginService: LoginService,
|
protected loginEmailService: LoginEmailServiceAbstraction,
|
||||||
protected ssoLoginService: SsoLoginServiceAbstraction,
|
protected ssoLoginService: SsoLoginServiceAbstraction,
|
||||||
protected webAuthnLoginService: WebAuthnLoginServiceAbstraction,
|
protected webAuthnLoginService: WebAuthnLoginServiceAbstraction,
|
||||||
) {
|
) {
|
||||||
@@ -93,25 +96,23 @@ export class LoginComponent extends CaptchaProtectedComponent implements OnInit,
|
|||||||
const queryParamsEmail = params.email;
|
const queryParamsEmail = params.email;
|
||||||
|
|
||||||
if (queryParamsEmail != null && queryParamsEmail.indexOf("@") > -1) {
|
if (queryParamsEmail != null && queryParamsEmail.indexOf("@") > -1) {
|
||||||
this.formGroup.get("email").setValue(queryParamsEmail);
|
this.formGroup.controls.email.setValue(queryParamsEmail);
|
||||||
this.loginService.setEmail(queryParamsEmail);
|
|
||||||
this.paramEmailSet = true;
|
this.paramEmailSet = true;
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
let email = this.loginService.getEmail();
|
|
||||||
|
|
||||||
if (email == null || email === "") {
|
|
||||||
email = await this.stateService.getRememberedEmail();
|
|
||||||
}
|
|
||||||
|
|
||||||
if (!this.paramEmailSet) {
|
if (!this.paramEmailSet) {
|
||||||
this.formGroup.get("email")?.setValue(email ?? "");
|
const storedEmail = await firstValueFrom(this.loginEmailService.storedEmail$);
|
||||||
|
this.formGroup.controls.email.setValue(storedEmail ?? "");
|
||||||
}
|
}
|
||||||
let rememberEmail = this.loginService.getRememberEmail();
|
|
||||||
|
let rememberEmail = this.loginEmailService.getRememberEmail();
|
||||||
|
|
||||||
if (rememberEmail == null) {
|
if (rememberEmail == null) {
|
||||||
rememberEmail = (await this.stateService.getRememberedEmail()) != null;
|
rememberEmail = (await firstValueFrom(this.loginEmailService.storedEmail$)) != null;
|
||||||
}
|
}
|
||||||
this.formGroup.get("rememberEmail")?.setValue(rememberEmail);
|
|
||||||
|
this.formGroup.controls.rememberEmail.setValue(rememberEmail);
|
||||||
}
|
}
|
||||||
|
|
||||||
ngOnDestroy() {
|
ngOnDestroy() {
|
||||||
@@ -148,8 +149,10 @@ export class LoginComponent extends CaptchaProtectedComponent implements OnInit,
|
|||||||
|
|
||||||
this.formPromise = this.loginStrategyService.logIn(credentials);
|
this.formPromise = this.loginStrategyService.logIn(credentials);
|
||||||
const response = await this.formPromise;
|
const response = await this.formPromise;
|
||||||
this.setFormValues();
|
|
||||||
await this.loginService.saveEmailSettings();
|
this.setLoginEmailValues();
|
||||||
|
await this.loginEmailService.saveEmailSettings();
|
||||||
|
|
||||||
if (this.handleCaptchaRequired(response)) {
|
if (this.handleCaptchaRequired(response)) {
|
||||||
return;
|
return;
|
||||||
} else if (this.handleMigrateEncryptionKey(response)) {
|
} else if (this.handleMigrateEncryptionKey(response)) {
|
||||||
@@ -214,7 +217,7 @@ export class LoginComponent extends CaptchaProtectedComponent implements OnInit,
|
|||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
this.setFormValues();
|
this.setLoginEmailValues();
|
||||||
// FIXME: Verify that this floating promise is intentional. If it is, add an explanatory comment and ensure there is proper error handling.
|
// FIXME: Verify that this floating promise is intentional. If it is, add an explanatory comment and ensure there is proper error handling.
|
||||||
// eslint-disable-next-line @typescript-eslint/no-floating-promises
|
// eslint-disable-next-line @typescript-eslint/no-floating-promises
|
||||||
this.router.navigate(["/login-with-device"]);
|
this.router.navigate(["/login-with-device"]);
|
||||||
@@ -292,14 +295,14 @@ export class LoginComponent extends CaptchaProtectedComponent implements OnInit,
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
setFormValues() {
|
setLoginEmailValues() {
|
||||||
this.loginService.setEmail(this.formGroup.value.email);
|
this.loginEmailService.setEmail(this.formGroup.value.email);
|
||||||
this.loginService.setRememberEmail(this.formGroup.value.rememberEmail);
|
this.loginEmailService.setRememberEmail(this.formGroup.value.rememberEmail);
|
||||||
}
|
}
|
||||||
|
|
||||||
async saveEmailSettings() {
|
async saveEmailSettings() {
|
||||||
this.setFormValues();
|
this.setLoginEmailValues();
|
||||||
await this.loginService.saveEmailSettings();
|
await this.loginEmailService.saveEmailSettings();
|
||||||
|
|
||||||
// Save off email for SSO
|
// Save off email for SSO
|
||||||
await this.ssoLoginService.setSsoEmail(this.formGroup.value.email);
|
await this.ssoLoginService.setSsoEmail(this.formGroup.value.email);
|
||||||
|
|||||||
@@ -7,14 +7,14 @@ import { BehaviorSubject } from "rxjs";
|
|||||||
// eslint-disable-next-line no-restricted-imports
|
// eslint-disable-next-line no-restricted-imports
|
||||||
import { WINDOW } from "@bitwarden/angular/services/injection-tokens";
|
import { WINDOW } from "@bitwarden/angular/services/injection-tokens";
|
||||||
import {
|
import {
|
||||||
FakeKeyConnectorUserDecryptionOption as KeyConnectorUserDecryptionOption,
|
|
||||||
LoginStrategyServiceAbstraction,
|
LoginStrategyServiceAbstraction,
|
||||||
|
LoginEmailServiceAbstraction,
|
||||||
|
FakeKeyConnectorUserDecryptionOption as KeyConnectorUserDecryptionOption,
|
||||||
FakeTrustedDeviceUserDecryptionOption as TrustedDeviceUserDecryptionOption,
|
FakeTrustedDeviceUserDecryptionOption as TrustedDeviceUserDecryptionOption,
|
||||||
FakeUserDecryptionOptions as UserDecryptionOptions,
|
FakeUserDecryptionOptions as UserDecryptionOptions,
|
||||||
UserDecryptionOptionsServiceAbstraction,
|
UserDecryptionOptionsServiceAbstraction,
|
||||||
} from "@bitwarden/auth/common";
|
} from "@bitwarden/auth/common";
|
||||||
import { ApiService } from "@bitwarden/common/abstractions/api.service";
|
import { ApiService } from "@bitwarden/common/abstractions/api.service";
|
||||||
import { LoginService } from "@bitwarden/common/auth/abstractions/login.service";
|
|
||||||
import { SsoLoginServiceAbstraction } from "@bitwarden/common/auth/abstractions/sso-login.service.abstraction";
|
import { SsoLoginServiceAbstraction } from "@bitwarden/common/auth/abstractions/sso-login.service.abstraction";
|
||||||
import { TwoFactorService } from "@bitwarden/common/auth/abstractions/two-factor.service";
|
import { TwoFactorService } from "@bitwarden/common/auth/abstractions/two-factor.service";
|
||||||
import { AuthResult } from "@bitwarden/common/auth/models/domain/auth-result";
|
import { AuthResult } from "@bitwarden/common/auth/models/domain/auth-result";
|
||||||
@@ -59,7 +59,7 @@ describe("TwoFactorComponent", () => {
|
|||||||
let mockLogService: MockProxy<LogService>;
|
let mockLogService: MockProxy<LogService>;
|
||||||
let mockTwoFactorService: MockProxy<TwoFactorService>;
|
let mockTwoFactorService: MockProxy<TwoFactorService>;
|
||||||
let mockAppIdService: MockProxy<AppIdService>;
|
let mockAppIdService: MockProxy<AppIdService>;
|
||||||
let mockLoginService: MockProxy<LoginService>;
|
let mockLoginEmailService: MockProxy<LoginEmailServiceAbstraction>;
|
||||||
let mockUserDecryptionOptionsService: MockProxy<UserDecryptionOptionsServiceAbstraction>;
|
let mockUserDecryptionOptionsService: MockProxy<UserDecryptionOptionsServiceAbstraction>;
|
||||||
let mockSsoLoginService: MockProxy<SsoLoginServiceAbstraction>;
|
let mockSsoLoginService: MockProxy<SsoLoginServiceAbstraction>;
|
||||||
let mockConfigService: MockProxy<ConfigService>;
|
let mockConfigService: MockProxy<ConfigService>;
|
||||||
@@ -89,7 +89,7 @@ describe("TwoFactorComponent", () => {
|
|||||||
mockLogService = mock<LogService>();
|
mockLogService = mock<LogService>();
|
||||||
mockTwoFactorService = mock<TwoFactorService>();
|
mockTwoFactorService = mock<TwoFactorService>();
|
||||||
mockAppIdService = mock<AppIdService>();
|
mockAppIdService = mock<AppIdService>();
|
||||||
mockLoginService = mock<LoginService>();
|
mockLoginEmailService = mock<LoginEmailServiceAbstraction>();
|
||||||
mockUserDecryptionOptionsService = mock<UserDecryptionOptionsServiceAbstraction>();
|
mockUserDecryptionOptionsService = mock<UserDecryptionOptionsServiceAbstraction>();
|
||||||
mockSsoLoginService = mock<SsoLoginServiceAbstraction>();
|
mockSsoLoginService = mock<SsoLoginServiceAbstraction>();
|
||||||
mockConfigService = mock<ConfigService>();
|
mockConfigService = mock<ConfigService>();
|
||||||
@@ -163,7 +163,7 @@ describe("TwoFactorComponent", () => {
|
|||||||
{ provide: LogService, useValue: mockLogService },
|
{ provide: LogService, useValue: mockLogService },
|
||||||
{ provide: TwoFactorService, useValue: mockTwoFactorService },
|
{ provide: TwoFactorService, useValue: mockTwoFactorService },
|
||||||
{ provide: AppIdService, useValue: mockAppIdService },
|
{ provide: AppIdService, useValue: mockAppIdService },
|
||||||
{ provide: LoginService, useValue: mockLoginService },
|
{ provide: LoginEmailServiceAbstraction, useValue: mockLoginEmailService },
|
||||||
{
|
{
|
||||||
provide: UserDecryptionOptionsServiceAbstraction,
|
provide: UserDecryptionOptionsServiceAbstraction,
|
||||||
useValue: mockUserDecryptionOptionsService,
|
useValue: mockUserDecryptionOptionsService,
|
||||||
@@ -280,11 +280,11 @@ describe("TwoFactorComponent", () => {
|
|||||||
expect(component.onSuccessfulLogin).toHaveBeenCalled();
|
expect(component.onSuccessfulLogin).toHaveBeenCalled();
|
||||||
});
|
});
|
||||||
|
|
||||||
it("calls loginService.clearValues() when login is successful", async () => {
|
it("calls loginEmailService.clearValues() when login is successful", async () => {
|
||||||
// Arrange
|
// Arrange
|
||||||
mockLoginStrategyService.logInTwoFactor.mockResolvedValue(new AuthResult());
|
mockLoginStrategyService.logInTwoFactor.mockResolvedValue(new AuthResult());
|
||||||
// spy on loginService.clearValues
|
// spy on loginEmailService.clearValues
|
||||||
const clearValuesSpy = jest.spyOn(mockLoginService, "clearValues");
|
const clearValuesSpy = jest.spyOn(mockLoginEmailService, "clearValues");
|
||||||
|
|
||||||
// Act
|
// Act
|
||||||
await component.doSubmit();
|
await component.doSubmit();
|
||||||
|
|||||||
@@ -8,12 +8,12 @@ import { first } from "rxjs/operators";
|
|||||||
import { WINDOW } from "@bitwarden/angular/services/injection-tokens";
|
import { WINDOW } from "@bitwarden/angular/services/injection-tokens";
|
||||||
import {
|
import {
|
||||||
LoginStrategyServiceAbstraction,
|
LoginStrategyServiceAbstraction,
|
||||||
|
LoginEmailServiceAbstraction,
|
||||||
TrustedDeviceUserDecryptionOption,
|
TrustedDeviceUserDecryptionOption,
|
||||||
UserDecryptionOptions,
|
UserDecryptionOptions,
|
||||||
UserDecryptionOptionsServiceAbstraction,
|
UserDecryptionOptionsServiceAbstraction,
|
||||||
} from "@bitwarden/auth/common";
|
} from "@bitwarden/auth/common";
|
||||||
import { ApiService } from "@bitwarden/common/abstractions/api.service";
|
import { ApiService } from "@bitwarden/common/abstractions/api.service";
|
||||||
import { LoginService } from "@bitwarden/common/auth/abstractions/login.service";
|
|
||||||
import { SsoLoginServiceAbstraction } from "@bitwarden/common/auth/abstractions/sso-login.service.abstraction";
|
import { SsoLoginServiceAbstraction } from "@bitwarden/common/auth/abstractions/sso-login.service.abstraction";
|
||||||
import { TwoFactorService } from "@bitwarden/common/auth/abstractions/two-factor.service";
|
import { TwoFactorService } from "@bitwarden/common/auth/abstractions/two-factor.service";
|
||||||
import { AuthenticationType } from "@bitwarden/common/auth/enums/authentication-type";
|
import { AuthenticationType } from "@bitwarden/common/auth/enums/authentication-type";
|
||||||
@@ -88,7 +88,7 @@ export class TwoFactorComponent extends CaptchaProtectedComponent implements OnI
|
|||||||
protected logService: LogService,
|
protected logService: LogService,
|
||||||
protected twoFactorService: TwoFactorService,
|
protected twoFactorService: TwoFactorService,
|
||||||
protected appIdService: AppIdService,
|
protected appIdService: AppIdService,
|
||||||
protected loginService: LoginService,
|
protected loginEmailService: LoginEmailServiceAbstraction,
|
||||||
protected userDecryptionOptionsService: UserDecryptionOptionsServiceAbstraction,
|
protected userDecryptionOptionsService: UserDecryptionOptionsServiceAbstraction,
|
||||||
protected ssoLoginService: SsoLoginServiceAbstraction,
|
protected ssoLoginService: SsoLoginServiceAbstraction,
|
||||||
protected configService: ConfigService,
|
protected configService: ConfigService,
|
||||||
@@ -288,7 +288,7 @@ export class TwoFactorComponent extends CaptchaProtectedComponent implements OnI
|
|||||||
// - TDE login decryption options component
|
// - TDE login decryption options component
|
||||||
// - Browser SSO on extension open
|
// - Browser SSO on extension open
|
||||||
await this.ssoLoginService.setActiveUserOrganizationSsoIdentifier(this.orgIdentifier);
|
await this.ssoLoginService.setActiveUserOrganizationSsoIdentifier(this.orgIdentifier);
|
||||||
this.loginService.clearValues();
|
this.loginEmailService.clearValues();
|
||||||
|
|
||||||
// note: this flow affects both TDE & standard users
|
// note: this flow affects both TDE & standard users
|
||||||
if (this.isForcePasswordResetRequired(authResult)) {
|
if (this.isForcePasswordResetRequired(authResult)) {
|
||||||
|
|||||||
@@ -7,6 +7,8 @@ import {
|
|||||||
PinCryptoService,
|
PinCryptoService,
|
||||||
LoginStrategyServiceAbstraction,
|
LoginStrategyServiceAbstraction,
|
||||||
LoginStrategyService,
|
LoginStrategyService,
|
||||||
|
LoginEmailServiceAbstraction,
|
||||||
|
LoginEmailService,
|
||||||
InternalUserDecryptionOptionsServiceAbstraction,
|
InternalUserDecryptionOptionsServiceAbstraction,
|
||||||
UserDecryptionOptionsService,
|
UserDecryptionOptionsService,
|
||||||
UserDecryptionOptionsServiceAbstraction,
|
UserDecryptionOptionsServiceAbstraction,
|
||||||
@@ -58,7 +60,6 @@ import { DeviceTrustCryptoServiceAbstraction } from "@bitwarden/common/auth/abst
|
|||||||
import { DevicesServiceAbstraction } from "@bitwarden/common/auth/abstractions/devices/devices.service.abstraction";
|
import { DevicesServiceAbstraction } from "@bitwarden/common/auth/abstractions/devices/devices.service.abstraction";
|
||||||
import { DevicesApiServiceAbstraction } from "@bitwarden/common/auth/abstractions/devices-api.service.abstraction";
|
import { DevicesApiServiceAbstraction } from "@bitwarden/common/auth/abstractions/devices-api.service.abstraction";
|
||||||
import { KeyConnectorService as KeyConnectorServiceAbstraction } from "@bitwarden/common/auth/abstractions/key-connector.service";
|
import { KeyConnectorService as KeyConnectorServiceAbstraction } from "@bitwarden/common/auth/abstractions/key-connector.service";
|
||||||
import { LoginService as LoginServiceAbstraction } from "@bitwarden/common/auth/abstractions/login.service";
|
|
||||||
import { PasswordResetEnrollmentServiceAbstraction } from "@bitwarden/common/auth/abstractions/password-reset-enrollment.service.abstraction";
|
import { PasswordResetEnrollmentServiceAbstraction } from "@bitwarden/common/auth/abstractions/password-reset-enrollment.service.abstraction";
|
||||||
import { SsoLoginServiceAbstraction } from "@bitwarden/common/auth/abstractions/sso-login.service.abstraction";
|
import { SsoLoginServiceAbstraction } from "@bitwarden/common/auth/abstractions/sso-login.service.abstraction";
|
||||||
import { TokenService as TokenServiceAbstraction } from "@bitwarden/common/auth/abstractions/token.service";
|
import { TokenService as TokenServiceAbstraction } from "@bitwarden/common/auth/abstractions/token.service";
|
||||||
@@ -77,7 +78,6 @@ import { DeviceTrustCryptoService } from "@bitwarden/common/auth/services/device
|
|||||||
import { DevicesServiceImplementation } from "@bitwarden/common/auth/services/devices/devices.service.implementation";
|
import { DevicesServiceImplementation } from "@bitwarden/common/auth/services/devices/devices.service.implementation";
|
||||||
import { DevicesApiServiceImplementation } from "@bitwarden/common/auth/services/devices-api.service.implementation";
|
import { DevicesApiServiceImplementation } from "@bitwarden/common/auth/services/devices-api.service.implementation";
|
||||||
import { KeyConnectorService } from "@bitwarden/common/auth/services/key-connector.service";
|
import { KeyConnectorService } from "@bitwarden/common/auth/services/key-connector.service";
|
||||||
import { LoginService } from "@bitwarden/common/auth/services/login.service";
|
|
||||||
import { PasswordResetEnrollmentServiceImplementation } from "@bitwarden/common/auth/services/password-reset-enrollment.service.implementation";
|
import { PasswordResetEnrollmentServiceImplementation } from "@bitwarden/common/auth/services/password-reset-enrollment.service.implementation";
|
||||||
import { SsoLoginService } from "@bitwarden/common/auth/services/sso-login.service";
|
import { SsoLoginService } from "@bitwarden/common/auth/services/sso-login.service";
|
||||||
import { TokenService } from "@bitwarden/common/auth/services/token.service";
|
import { TokenService } from "@bitwarden/common/auth/services/token.service";
|
||||||
@@ -874,9 +874,9 @@ const safeProviders: SafeProvider[] = [
|
|||||||
deps: [I18nServiceAbstraction, PlatformUtilsServiceAbstraction],
|
deps: [I18nServiceAbstraction, PlatformUtilsServiceAbstraction],
|
||||||
}),
|
}),
|
||||||
safeProvider({
|
safeProvider({
|
||||||
provide: LoginServiceAbstraction,
|
provide: LoginEmailServiceAbstraction,
|
||||||
useClass: LoginService,
|
useClass: LoginEmailService,
|
||||||
deps: [StateServiceAbstraction],
|
deps: [StateProvider],
|
||||||
}),
|
}),
|
||||||
safeProvider({
|
safeProvider({
|
||||||
provide: OrgDomainInternalServiceAbstraction,
|
provide: OrgDomainInternalServiceAbstraction,
|
||||||
|
|||||||
@@ -1,4 +1,5 @@
|
|||||||
export * from "./pin-crypto.service.abstraction";
|
export * from "./pin-crypto.service.abstraction";
|
||||||
|
export * from "./login-email.service";
|
||||||
export * from "./login-strategy.service";
|
export * from "./login-strategy.service";
|
||||||
export * from "./user-decryption-options.service.abstraction";
|
export * from "./user-decryption-options.service.abstraction";
|
||||||
export * from "./auth-request.service.abstraction";
|
export * from "./auth-request.service.abstraction";
|
||||||
|
|||||||
38
libs/auth/src/common/abstractions/login-email.service.ts
Normal file
38
libs/auth/src/common/abstractions/login-email.service.ts
Normal file
@@ -0,0 +1,38 @@
|
|||||||
|
import { Observable } from "rxjs";
|
||||||
|
|
||||||
|
export abstract class LoginEmailServiceAbstraction {
|
||||||
|
/**
|
||||||
|
* An observable that monitors the storedEmail
|
||||||
|
*/
|
||||||
|
storedEmail$: Observable<string>;
|
||||||
|
/**
|
||||||
|
* Gets the current email being used in the login process.
|
||||||
|
* @returns A string of the email.
|
||||||
|
*/
|
||||||
|
getEmail: () => string;
|
||||||
|
/**
|
||||||
|
* Sets the current email being used in the login process.
|
||||||
|
* @param email The email to be set.
|
||||||
|
*/
|
||||||
|
setEmail: (email: string) => void;
|
||||||
|
/**
|
||||||
|
* Gets whether or not the email should be stored on disk.
|
||||||
|
* @returns A boolean stating whether or not the email should be stored on disk.
|
||||||
|
*/
|
||||||
|
getRememberEmail: () => boolean;
|
||||||
|
/**
|
||||||
|
* Sets whether or not the email should be stored on disk.
|
||||||
|
*/
|
||||||
|
setRememberEmail: (value: boolean) => void;
|
||||||
|
/**
|
||||||
|
* Sets the email and rememberEmail properties to null.
|
||||||
|
*/
|
||||||
|
clearValues: () => void;
|
||||||
|
/**
|
||||||
|
* - If rememberEmail is true, sets the storedEmail on disk to the current email.
|
||||||
|
* - If rememberEmail is false, sets the storedEmail on disk to null.
|
||||||
|
* - Then sets the email and rememberEmail properties to null.
|
||||||
|
* @returns A promise that resolves once the email settings are saved.
|
||||||
|
*/
|
||||||
|
saveEmailSettings: () => Promise<void>;
|
||||||
|
}
|
||||||
@@ -1,4 +1,5 @@
|
|||||||
export * from "./pin-crypto/pin-crypto.service.implementation";
|
export * from "./pin-crypto/pin-crypto.service.implementation";
|
||||||
|
export * from "./login-email/login-email.service";
|
||||||
export * from "./login-strategies/login-strategy.service";
|
export * from "./login-strategies/login-strategy.service";
|
||||||
export * from "./user-decryption-options/user-decryption-options.service";
|
export * from "./user-decryption-options/user-decryption-options.service";
|
||||||
export * from "./auth-request/auth-request.service";
|
export * from "./auth-request/auth-request.service";
|
||||||
|
|||||||
@@ -0,0 +1,52 @@
|
|||||||
|
import { Observable } from "rxjs";
|
||||||
|
|
||||||
|
import {
|
||||||
|
GlobalState,
|
||||||
|
KeyDefinition,
|
||||||
|
LOGIN_EMAIL_DISK,
|
||||||
|
StateProvider,
|
||||||
|
} from "../../../../../common/src/platform/state";
|
||||||
|
import { LoginEmailServiceAbstraction } from "../../abstractions/login-email.service";
|
||||||
|
|
||||||
|
const STORED_EMAIL = new KeyDefinition<string>(LOGIN_EMAIL_DISK, "storedEmail", {
|
||||||
|
deserializer: (value: string) => value,
|
||||||
|
});
|
||||||
|
|
||||||
|
export class LoginEmailService implements LoginEmailServiceAbstraction {
|
||||||
|
private email: string;
|
||||||
|
private rememberEmail: boolean;
|
||||||
|
|
||||||
|
private readonly storedEmailState: GlobalState<string>;
|
||||||
|
storedEmail$: Observable<string>;
|
||||||
|
|
||||||
|
constructor(private stateProvider: StateProvider) {
|
||||||
|
this.storedEmailState = this.stateProvider.getGlobal(STORED_EMAIL);
|
||||||
|
this.storedEmail$ = this.storedEmailState.state$;
|
||||||
|
}
|
||||||
|
|
||||||
|
getEmail() {
|
||||||
|
return this.email;
|
||||||
|
}
|
||||||
|
|
||||||
|
setEmail(email: string) {
|
||||||
|
this.email = email;
|
||||||
|
}
|
||||||
|
|
||||||
|
getRememberEmail() {
|
||||||
|
return this.rememberEmail;
|
||||||
|
}
|
||||||
|
|
||||||
|
setRememberEmail(value: boolean) {
|
||||||
|
this.rememberEmail = value;
|
||||||
|
}
|
||||||
|
|
||||||
|
clearValues() {
|
||||||
|
this.email = null;
|
||||||
|
this.rememberEmail = null;
|
||||||
|
}
|
||||||
|
|
||||||
|
async saveEmailSettings() {
|
||||||
|
await this.storedEmailState.update(() => (this.rememberEmail ? this.email : null));
|
||||||
|
this.clearValues();
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -1,8 +0,0 @@
|
|||||||
export abstract class LoginService {
|
|
||||||
getEmail: () => string;
|
|
||||||
getRememberEmail: () => boolean;
|
|
||||||
setEmail: (value: string) => void;
|
|
||||||
setRememberEmail: (value: boolean) => void;
|
|
||||||
clearValues: () => void;
|
|
||||||
saveEmailSettings: () => Promise<void>;
|
|
||||||
}
|
|
||||||
@@ -1,35 +0,0 @@
|
|||||||
import { StateService } from "../../platform/abstractions/state.service";
|
|
||||||
import { LoginService as LoginServiceAbstraction } from "../abstractions/login.service";
|
|
||||||
|
|
||||||
export class LoginService implements LoginServiceAbstraction {
|
|
||||||
private _email: string;
|
|
||||||
private _rememberEmail: boolean;
|
|
||||||
|
|
||||||
constructor(private stateService: StateService) {}
|
|
||||||
|
|
||||||
getEmail() {
|
|
||||||
return this._email;
|
|
||||||
}
|
|
||||||
|
|
||||||
getRememberEmail() {
|
|
||||||
return this._rememberEmail;
|
|
||||||
}
|
|
||||||
|
|
||||||
setEmail(value: string) {
|
|
||||||
this._email = value;
|
|
||||||
}
|
|
||||||
|
|
||||||
setRememberEmail(value: boolean) {
|
|
||||||
this._rememberEmail = value;
|
|
||||||
}
|
|
||||||
|
|
||||||
clearValues() {
|
|
||||||
this._email = null;
|
|
||||||
this._rememberEmail = null;
|
|
||||||
}
|
|
||||||
|
|
||||||
async saveEmailSettings() {
|
|
||||||
await this.stateService.setRememberedEmail(this._rememberEmail ? this._email : null);
|
|
||||||
this.clearValues();
|
|
||||||
}
|
|
||||||
}
|
|
||||||
@@ -262,8 +262,6 @@ export abstract class StateService<T extends Account = Account> {
|
|||||||
* Sets the user's Pin, encrypted by the user key
|
* Sets the user's Pin, encrypted by the user key
|
||||||
*/
|
*/
|
||||||
setProtectedPin: (value: string, options?: StorageOptions) => Promise<void>;
|
setProtectedPin: (value: string, options?: StorageOptions) => Promise<void>;
|
||||||
getRememberedEmail: (options?: StorageOptions) => Promise<string>;
|
|
||||||
setRememberedEmail: (value: string, options?: StorageOptions) => Promise<void>;
|
|
||||||
getSecurityStamp: (options?: StorageOptions) => Promise<string>;
|
getSecurityStamp: (options?: StorageOptions) => Promise<string>;
|
||||||
setSecurityStamp: (value: string, options?: StorageOptions) => Promise<void>;
|
setSecurityStamp: (value: string, options?: StorageOptions) => Promise<void>;
|
||||||
getUserId: (options?: StorageOptions) => Promise<string>;
|
getUserId: (options?: StorageOptions) => Promise<string>;
|
||||||
|
|||||||
@@ -3,7 +3,6 @@ import { ThemeType } from "../../enums";
|
|||||||
export class GlobalState {
|
export class GlobalState {
|
||||||
installedVersion?: string;
|
installedVersion?: string;
|
||||||
organizationInvitation?: any;
|
organizationInvitation?: any;
|
||||||
rememberedEmail?: string;
|
|
||||||
theme?: ThemeType = ThemeType.System;
|
theme?: ThemeType = ThemeType.System;
|
||||||
twoFactorToken?: string;
|
twoFactorToken?: string;
|
||||||
biometricFingerprintValidated?: boolean;
|
biometricFingerprintValidated?: boolean;
|
||||||
|
|||||||
@@ -1241,23 +1241,6 @@ export class StateService<
|
|||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
async getRememberedEmail(options?: StorageOptions): Promise<string> {
|
|
||||||
return (
|
|
||||||
await this.getGlobals(this.reconcileOptions(options, await this.defaultOnDiskLocalOptions()))
|
|
||||||
)?.rememberedEmail;
|
|
||||||
}
|
|
||||||
|
|
||||||
async setRememberedEmail(value: string, options?: StorageOptions): Promise<void> {
|
|
||||||
const globals = await this.getGlobals(
|
|
||||||
this.reconcileOptions(options, await this.defaultOnDiskLocalOptions()),
|
|
||||||
);
|
|
||||||
globals.rememberedEmail = value;
|
|
||||||
await this.saveGlobals(
|
|
||||||
globals,
|
|
||||||
this.reconcileOptions(options, await this.defaultOnDiskLocalOptions()),
|
|
||||||
);
|
|
||||||
}
|
|
||||||
|
|
||||||
async getSecurityStamp(options?: StorageOptions): Promise<string> {
|
async getSecurityStamp(options?: StorageOptions): Promise<string> {
|
||||||
return (
|
return (
|
||||||
await this.getAccount(this.reconcileOptions(options, await this.defaultInMemoryOptions()))
|
await this.getAccount(this.reconcileOptions(options, await this.defaultInMemoryOptions()))
|
||||||
|
|||||||
@@ -38,13 +38,16 @@ 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 LOGIN_EMAIL_DISK = new StateDefinition("loginEmail", "disk", {
|
||||||
|
web: "disk-local",
|
||||||
|
});
|
||||||
|
export const LOGIN_STRATEGY_MEMORY = new StateDefinition("loginStrategy", "memory");
|
||||||
export const SSO_DISK = new StateDefinition("ssoLogin", "disk");
|
export const SSO_DISK = new StateDefinition("ssoLogin", "disk");
|
||||||
export const TOKEN_DISK = new StateDefinition("token", "disk");
|
export const TOKEN_DISK = new StateDefinition("token", "disk");
|
||||||
export const TOKEN_DISK_LOCAL = new StateDefinition("tokenDiskLocal", "disk", {
|
export const TOKEN_DISK_LOCAL = new StateDefinition("tokenDiskLocal", "disk", {
|
||||||
web: "disk-local",
|
web: "disk-local",
|
||||||
});
|
});
|
||||||
export const TOKEN_MEMORY = new StateDefinition("token", "memory");
|
export const TOKEN_MEMORY = new StateDefinition("token", "memory");
|
||||||
export const LOGIN_STRATEGY_MEMORY = new StateDefinition("loginStrategy", "memory");
|
|
||||||
export const USER_DECRYPTION_OPTIONS_DISK = new StateDefinition("userDecryptionOptions", "disk");
|
export const USER_DECRYPTION_OPTIONS_DISK = new StateDefinition("userDecryptionOptions", "disk");
|
||||||
|
|
||||||
// Autofill
|
// Autofill
|
||||||
|
|||||||
@@ -47,6 +47,7 @@ import { MoveDdgToStateProviderMigrator } from "./migrations/48-move-ddg-to-stat
|
|||||||
import { AccountServerConfigMigrator } from "./migrations/49-move-account-server-configs";
|
import { AccountServerConfigMigrator } from "./migrations/49-move-account-server-configs";
|
||||||
import { AddKeyTypeToOrgKeysMigrator } from "./migrations/5-add-key-type-to-org-keys";
|
import { AddKeyTypeToOrgKeysMigrator } from "./migrations/5-add-key-type-to-org-keys";
|
||||||
import { KeyConnectorMigrator } from "./migrations/50-move-key-connector-to-state-provider";
|
import { KeyConnectorMigrator } from "./migrations/50-move-key-connector-to-state-provider";
|
||||||
|
import { RememberedEmailMigrator } from "./migrations/51-move-remembered-email-to-state-providers";
|
||||||
import { RemoveLegacyEtmKeyMigrator } from "./migrations/6-remove-legacy-etm-key";
|
import { RemoveLegacyEtmKeyMigrator } from "./migrations/6-remove-legacy-etm-key";
|
||||||
import { MoveBiometricAutoPromptToAccount } from "./migrations/7-move-biometric-auto-prompt-to-account";
|
import { MoveBiometricAutoPromptToAccount } from "./migrations/7-move-biometric-auto-prompt-to-account";
|
||||||
import { MoveStateVersionMigrator } from "./migrations/8-move-state-version";
|
import { MoveStateVersionMigrator } from "./migrations/8-move-state-version";
|
||||||
@@ -54,7 +55,7 @@ import { MoveBrowserSettingsToGlobal } from "./migrations/9-move-browser-setting
|
|||||||
import { MinVersionMigrator } from "./migrations/min-version";
|
import { MinVersionMigrator } from "./migrations/min-version";
|
||||||
|
|
||||||
export const MIN_VERSION = 3;
|
export const MIN_VERSION = 3;
|
||||||
export const CURRENT_VERSION = 50;
|
export const CURRENT_VERSION = 51;
|
||||||
|
|
||||||
export type MinVersion = typeof MIN_VERSION;
|
export type MinVersion = typeof MIN_VERSION;
|
||||||
|
|
||||||
@@ -107,7 +108,8 @@ export function createMigrationBuilder() {
|
|||||||
.with(MoveDesktopSettingsMigrator, 46, 47)
|
.with(MoveDesktopSettingsMigrator, 46, 47)
|
||||||
.with(MoveDdgToStateProviderMigrator, 47, 48)
|
.with(MoveDdgToStateProviderMigrator, 47, 48)
|
||||||
.with(AccountServerConfigMigrator, 48, 49)
|
.with(AccountServerConfigMigrator, 48, 49)
|
||||||
.with(KeyConnectorMigrator, 49, CURRENT_VERSION);
|
.with(KeyConnectorMigrator, 49, 50)
|
||||||
|
.with(RememberedEmailMigrator, 50, CURRENT_VERSION);
|
||||||
}
|
}
|
||||||
|
|
||||||
export async function currentVersion(
|
export async function currentVersion(
|
||||||
|
|||||||
@@ -0,0 +1,81 @@
|
|||||||
|
import { MockProxy } from "jest-mock-extended";
|
||||||
|
|
||||||
|
import { MigrationHelper } from "../migration-helper";
|
||||||
|
import { mockMigrationHelper, runMigrator } from "../migration-helper.spec";
|
||||||
|
|
||||||
|
import { RememberedEmailMigrator } from "./51-move-remembered-email-to-state-providers";
|
||||||
|
|
||||||
|
function rollbackJSON() {
|
||||||
|
return {
|
||||||
|
global: {
|
||||||
|
extra: "data",
|
||||||
|
},
|
||||||
|
global_loginEmail_storedEmail: "user@example.com",
|
||||||
|
};
|
||||||
|
}
|
||||||
|
|
||||||
|
describe("RememberedEmailMigrator", () => {
|
||||||
|
const migrator = new RememberedEmailMigrator(50, 51);
|
||||||
|
|
||||||
|
describe("migrate", () => {
|
||||||
|
it("should migrate the rememberedEmail property from the legacy global object to a global StorageKey as 'global_loginEmail_storedEmail'", async () => {
|
||||||
|
const output = await runMigrator(migrator, {
|
||||||
|
global: {
|
||||||
|
rememberedEmail: "user@example.com",
|
||||||
|
extra: "data", // Represents a global property that should persist after migration
|
||||||
|
},
|
||||||
|
});
|
||||||
|
|
||||||
|
expect(output).toEqual({
|
||||||
|
global: {
|
||||||
|
extra: "data",
|
||||||
|
},
|
||||||
|
global_loginEmail_storedEmail: "user@example.com",
|
||||||
|
});
|
||||||
|
});
|
||||||
|
|
||||||
|
it("should remove the rememberedEmail property from the legacy global object", async () => {
|
||||||
|
const output = await runMigrator(migrator, {
|
||||||
|
global: {
|
||||||
|
rememberedEmail: "user@example.com",
|
||||||
|
},
|
||||||
|
});
|
||||||
|
|
||||||
|
expect(output.global).not.toHaveProperty("rememberedEmail");
|
||||||
|
});
|
||||||
|
});
|
||||||
|
|
||||||
|
describe("rollback", () => {
|
||||||
|
let helper: MockProxy<MigrationHelper>;
|
||||||
|
let sut: RememberedEmailMigrator;
|
||||||
|
|
||||||
|
const keyDefinitionLike = {
|
||||||
|
key: "storedEmail",
|
||||||
|
stateDefinition: {
|
||||||
|
name: "loginEmail",
|
||||||
|
},
|
||||||
|
};
|
||||||
|
|
||||||
|
beforeEach(() => {
|
||||||
|
helper = mockMigrationHelper(rollbackJSON(), 51);
|
||||||
|
sut = new RememberedEmailMigrator(50, 51);
|
||||||
|
});
|
||||||
|
|
||||||
|
it("should null out the storedEmail global StorageKey", async () => {
|
||||||
|
await sut.rollback(helper);
|
||||||
|
|
||||||
|
expect(helper.setToGlobal).toHaveBeenCalledTimes(1);
|
||||||
|
expect(helper.setToGlobal).toHaveBeenCalledWith(keyDefinitionLike, null);
|
||||||
|
});
|
||||||
|
|
||||||
|
it("should add the rememberedEmail property back to legacy global object", async () => {
|
||||||
|
await sut.rollback(helper);
|
||||||
|
|
||||||
|
expect(helper.set).toHaveBeenCalledTimes(1);
|
||||||
|
expect(helper.set).toHaveBeenCalledWith("global", {
|
||||||
|
rememberedEmail: "user@example.com",
|
||||||
|
extra: "data",
|
||||||
|
});
|
||||||
|
});
|
||||||
|
});
|
||||||
|
});
|
||||||
@@ -0,0 +1,46 @@
|
|||||||
|
import { KeyDefinitionLike, MigrationHelper, StateDefinitionLike } from "../migration-helper";
|
||||||
|
import { Migrator } from "../migrator";
|
||||||
|
|
||||||
|
type ExpectedGlobalState = { rememberedEmail?: string };
|
||||||
|
|
||||||
|
const LOGIN_EMAIL_STATE: StateDefinitionLike = { name: "loginEmail" };
|
||||||
|
|
||||||
|
const STORED_EMAIL: KeyDefinitionLike = {
|
||||||
|
key: "storedEmail",
|
||||||
|
stateDefinition: LOGIN_EMAIL_STATE,
|
||||||
|
};
|
||||||
|
|
||||||
|
export class RememberedEmailMigrator extends Migrator<50, 51> {
|
||||||
|
async migrate(helper: MigrationHelper): Promise<void> {
|
||||||
|
const legacyGlobal = await helper.get<ExpectedGlobalState>("global");
|
||||||
|
|
||||||
|
// Move global data
|
||||||
|
if (legacyGlobal?.rememberedEmail != null) {
|
||||||
|
await helper.setToGlobal(STORED_EMAIL, legacyGlobal.rememberedEmail);
|
||||||
|
}
|
||||||
|
|
||||||
|
// Delete legacy global data
|
||||||
|
delete legacyGlobal?.rememberedEmail;
|
||||||
|
await helper.set("global", legacyGlobal);
|
||||||
|
}
|
||||||
|
|
||||||
|
async rollback(helper: MigrationHelper): Promise<void> {
|
||||||
|
let legacyGlobal = await helper.get<ExpectedGlobalState>("global");
|
||||||
|
let updatedLegacyGlobal = false;
|
||||||
|
const globalStoredEmail = await helper.getFromGlobal<string>(STORED_EMAIL);
|
||||||
|
|
||||||
|
if (globalStoredEmail) {
|
||||||
|
if (!legacyGlobal) {
|
||||||
|
legacyGlobal = {};
|
||||||
|
}
|
||||||
|
|
||||||
|
updatedLegacyGlobal = true;
|
||||||
|
legacyGlobal.rememberedEmail = globalStoredEmail;
|
||||||
|
await helper.setToGlobal(STORED_EMAIL, null);
|
||||||
|
}
|
||||||
|
|
||||||
|
if (updatedLegacyGlobal) {
|
||||||
|
await helper.set("global", legacyGlobal);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
Reference in New Issue
Block a user