mirror of
https://github.com/bitwarden/browser
synced 2026-02-21 20:04:02 +00:00
Merged with master and fixed conflicts
This commit is contained in:
@@ -1,40 +1,51 @@
|
||||
<label class="environment-selector-btn">
|
||||
<div class="environment-selector-btn">
|
||||
{{ "loggingInOn" | i18n }}:
|
||||
<a
|
||||
<button
|
||||
type="button"
|
||||
(click)="toggle(null)"
|
||||
cdkOverlayOrigin
|
||||
#trigger="cdkOverlayOrigin"
|
||||
aria-haspopup="menu"
|
||||
aria-haspopup="dialog"
|
||||
aria-controls="cdk-overlay-container"
|
||||
[ngSwitch]="selectedEnvironment"
|
||||
>
|
||||
<label *ngSwitchCase="ServerEnvironmentType.US" class="text-primary">{{
|
||||
<span *ngSwitchCase="ServerEnvironmentType.US" class="text-primary">{{
|
||||
"usDomain" | i18n
|
||||
}}</label>
|
||||
<label *ngSwitchCase="ServerEnvironmentType.EU" class="text-primary">{{
|
||||
}}</span>
|
||||
<span *ngSwitchCase="ServerEnvironmentType.EU" class="text-primary">{{
|
||||
"euDomain" | i18n
|
||||
}}</label>
|
||||
<label *ngSwitchCase="ServerEnvironmentType.SelfHosted" class="text-primary">{{
|
||||
}}</span>
|
||||
<span *ngSwitchCase="ServerEnvironmentType.SelfHosted" class="text-primary">{{
|
||||
"selfHostedServer" | i18n
|
||||
}}</label>
|
||||
}}</span>
|
||||
<i class="bwi bwi-fw bwi-sm bwi-angle-down" aria-hidden="true"></i>
|
||||
</a>
|
||||
</label>
|
||||
</button>
|
||||
</div>
|
||||
|
||||
<ng-template
|
||||
cdkConnectedOverlay
|
||||
[cdkConnectedOverlayOrigin]="trigger"
|
||||
(backdropClick)="close()"
|
||||
(detach)="close()"
|
||||
[cdkConnectedOverlayOpen]="isOpen"
|
||||
[cdkConnectedOverlayPositions]="overlayPosition"
|
||||
[cdkConnectedOverlayHasBackdrop]="true"
|
||||
[cdkConnectedOverlayBackdropClass]="'cdk-overlay-transparent-backdrop'"
|
||||
(backdropClick)="isOpen = false"
|
||||
(detach)="close()"
|
||||
>
|
||||
<div class="box-content">
|
||||
<div class="environment-selector-dialog" [@transformPanel]="'open'" role="dialog">
|
||||
<div
|
||||
class="environment-selector-dialog"
|
||||
[@transformPanel]="'open'"
|
||||
cdkTrapFocus
|
||||
cdkTrapFocusAutoCapture
|
||||
role="dialog"
|
||||
aria-modal="true"
|
||||
>
|
||||
<button
|
||||
type="button"
|
||||
class="environment-selector-dialog-item"
|
||||
(click)="toggle(ServerEnvironmentType.US)"
|
||||
[attr.aria-pressed]="selectedEnvironment === ServerEnvironmentType.US ? 'true' : 'false'"
|
||||
>
|
||||
<i
|
||||
class="bwi bwi-fw bwi-sm bwi-check"
|
||||
@@ -51,6 +62,7 @@
|
||||
type="button"
|
||||
class="environment-selector-dialog-item"
|
||||
(click)="toggle(ServerEnvironmentType.EU)"
|
||||
[attr.aria-pressed]="selectedEnvironment === ServerEnvironmentType.EU ? 'true' : 'false'"
|
||||
*ngIf="euServerFlagEnabled"
|
||||
>
|
||||
<i
|
||||
@@ -68,6 +80,9 @@
|
||||
type="button"
|
||||
class="environment-selector-dialog-item"
|
||||
(click)="toggle(ServerEnvironmentType.SelfHosted)"
|
||||
[attr.aria-pressed]="
|
||||
selectedEnvironment === ServerEnvironmentType.SelfHosted ? 'true' : 'false'
|
||||
"
|
||||
>
|
||||
<i
|
||||
class="bwi bwi-fw bwi-sm bwi-check"
|
||||
|
||||
@@ -152,6 +152,8 @@ export class LoginComponent extends CaptchaProtectedComponent implements OnInit,
|
||||
await this.loginService.saveEmailSettings();
|
||||
if (this.handleCaptchaRequired(response)) {
|
||||
return;
|
||||
} else if (this.handleMigrateEncryptionKey(response)) {
|
||||
return;
|
||||
} else if (response.requiresTwoFactor) {
|
||||
if (this.onSuccessfulLoginTwoFactorNavigate != null) {
|
||||
this.onSuccessfulLoginTwoFactorNavigate();
|
||||
@@ -283,6 +285,21 @@ export class LoginComponent extends CaptchaProtectedComponent implements OnInit,
|
||||
await this.loginService.saveEmailSettings();
|
||||
}
|
||||
|
||||
// Legacy accounts used the master key to encrypt data. Migration is required
|
||||
// but only performed on web
|
||||
protected handleMigrateEncryptionKey(result: AuthResult): boolean {
|
||||
if (!result.requiresEncryptionKeyMigration) {
|
||||
return false;
|
||||
}
|
||||
|
||||
this.platformUtilsService.showToast(
|
||||
"error",
|
||||
this.i18nService.t("errorOccured"),
|
||||
this.i18nService.t("encryptionKeyMigrationRequired")
|
||||
);
|
||||
return true;
|
||||
}
|
||||
|
||||
private getErrorToastMessage() {
|
||||
const error: AllValidationErrors = this.formValidationErrorService
|
||||
.getFormValidationErrors(this.formGroup.controls)
|
||||
|
||||
@@ -352,7 +352,7 @@ describe("SsoComponent", () => {
|
||||
describe("Given Trusted Device Encryption is enabled, user doesn't need to set a MP, and forcePasswordReset is required", () => {
|
||||
[
|
||||
ForceResetPasswordReason.AdminForcePasswordReset,
|
||||
ForceResetPasswordReason.WeakMasterPassword,
|
||||
// ForceResetPasswordReason.WeakMasterPassword, -- not possible in SSO flow as set client side
|
||||
].forEach((forceResetPasswordReason) => {
|
||||
const reasonString = ForceResetPasswordReason[forceResetPasswordReason];
|
||||
let authResult;
|
||||
@@ -449,7 +449,7 @@ describe("SsoComponent", () => {
|
||||
describe("Force Master Password Reset scenarios", () => {
|
||||
[
|
||||
ForceResetPasswordReason.AdminForcePasswordReset,
|
||||
ForceResetPasswordReason.WeakMasterPassword,
|
||||
// ForceResetPasswordReason.WeakMasterPassword, -- not possible in SSO flow as set client side
|
||||
].forEach((forceResetPasswordReason) => {
|
||||
const reasonString = ForceResetPasswordReason[forceResetPasswordReason];
|
||||
|
||||
|
||||
@@ -226,9 +226,9 @@ export class SsoComponent {
|
||||
return await this.handleChangePasswordRequired(orgIdentifier);
|
||||
}
|
||||
|
||||
// Users can be forced to reset their password via an admin or org policy
|
||||
// disallowing weak passwords
|
||||
if (authResult.forcePasswordReset !== ForceResetPasswordReason.None) {
|
||||
// Users enrolled in admin acct recovery can be forced to set a new password after
|
||||
// having the admin set a temp password for them
|
||||
if (authResult.forcePasswordReset == ForceResetPasswordReason.AdminForcePasswordReset) {
|
||||
return await this.handleForcePasswordReset(orgIdentifier);
|
||||
}
|
||||
|
||||
|
||||
@@ -215,9 +215,24 @@ export class TwoFactorComponent extends CaptchaProtectedComponent implements OnI
|
||||
await this.handleLoginResponse(authResult);
|
||||
}
|
||||
|
||||
protected handleMigrateEncryptionKey(result: AuthResult): boolean {
|
||||
if (!result.requiresEncryptionKeyMigration) {
|
||||
return false;
|
||||
}
|
||||
|
||||
this.platformUtilsService.showToast(
|
||||
"error",
|
||||
this.i18nService.t("errorOccured"),
|
||||
this.i18nService.t("encryptionKeyMigrationRequired")
|
||||
);
|
||||
return true;
|
||||
}
|
||||
|
||||
private async handleLoginResponse(authResult: AuthResult) {
|
||||
if (this.handleCaptchaRequired(authResult)) {
|
||||
return;
|
||||
} else if (this.handleMigrateEncryptionKey(authResult)) {
|
||||
return;
|
||||
}
|
||||
|
||||
this.loginService.clearValues();
|
||||
@@ -282,8 +297,10 @@ export class TwoFactorComponent extends CaptchaProtectedComponent implements OnI
|
||||
return await this.handleChangePasswordRequired(orgIdentifier);
|
||||
}
|
||||
|
||||
// Users can be forced to reset their password via an admin or org policy
|
||||
// disallowing weak passwords
|
||||
// Users can be forced to reset their password via an admin or org policy disallowing weak passwords
|
||||
// Note: this is different from SSO component login flow as a user can
|
||||
// login with MP and then have to pass 2FA to finish login and we can actually
|
||||
// evaluate if they have a weak password at this time.
|
||||
if (authResult.forcePasswordReset !== ForceResetPasswordReason.None) {
|
||||
return await this.handleForcePasswordReset(orgIdentifier);
|
||||
}
|
||||
|
||||
@@ -10,7 +10,10 @@ import { AuthService } from "@bitwarden/common/auth/abstractions/auth.service";
|
||||
import { DeviceTrustCryptoServiceAbstraction } from "@bitwarden/common/auth/abstractions/device-trust-crypto.service.abstraction";
|
||||
import { UserVerificationService } from "@bitwarden/common/auth/abstractions/user-verification/user-verification.service.abstraction";
|
||||
import { AuthenticationStatus } from "@bitwarden/common/auth/enums/authentication-status";
|
||||
import { ClientType } from "@bitwarden/common/enums";
|
||||
import { CryptoService } from "@bitwarden/common/platform/abstractions/crypto.service";
|
||||
import { MessagingService } from "@bitwarden/common/platform/abstractions/messaging.service";
|
||||
import { PlatformUtilsService } from "@bitwarden/common/platform/abstractions/platform-utils.service";
|
||||
|
||||
/**
|
||||
* Only allow access to this route if the vault is locked.
|
||||
@@ -25,9 +28,21 @@ export function lockGuard(): CanActivateFn {
|
||||
const authService = inject(AuthService);
|
||||
const cryptoService = inject(CryptoService);
|
||||
const deviceTrustCryptoService = inject(DeviceTrustCryptoServiceAbstraction);
|
||||
const platformUtilService = inject(PlatformUtilsService);
|
||||
const messagingService = inject(MessagingService);
|
||||
const router = inject(Router);
|
||||
const userVerificationService = inject(UserVerificationService);
|
||||
|
||||
// If legacy user on web, redirect to migration page
|
||||
if (await cryptoService.isLegacyUser()) {
|
||||
if (platformUtilService.getClientType() === ClientType.Web) {
|
||||
return router.createUrlTree(["migrate-legacy-encryption"]);
|
||||
}
|
||||
// Log out legacy users on other clients
|
||||
messagingService.send("logout");
|
||||
return false;
|
||||
}
|
||||
|
||||
const authStatus = await authService.getAuthStatus();
|
||||
if (authStatus !== AuthenticationStatus.Locked) {
|
||||
return router.createUrlTree(["/"]);
|
||||
|
||||
@@ -154,8 +154,13 @@ export class AddEditComponent implements OnInit, OnDestroy {
|
||||
.policyAppliesToActiveUser$(PolicyType.SendOptions, (p) => p.data.disableHideEmail)
|
||||
.pipe(takeUntil(this.destroy$))
|
||||
.subscribe((policyAppliesToActiveUser) => {
|
||||
if ((this.disableHideEmail = policyAppliesToActiveUser)) {
|
||||
if (
|
||||
(this.disableHideEmail = policyAppliesToActiveUser) &&
|
||||
!this.formGroup.controls.hideEmail.value
|
||||
) {
|
||||
this.formGroup.controls.hideEmail.disable();
|
||||
} else {
|
||||
this.formGroup.controls.hideEmail.enable();
|
||||
}
|
||||
});
|
||||
|
||||
|
||||
@@ -24,7 +24,6 @@ export class AttachmentsComponent implements OnInit {
|
||||
|
||||
cipher: CipherView;
|
||||
cipherDomain: Cipher;
|
||||
hasUpdatedKey: boolean;
|
||||
canAccessAttachments: boolean;
|
||||
formPromise: Promise<any>;
|
||||
deletePromises: { [id: string]: Promise<any> } = {};
|
||||
@@ -50,15 +49,6 @@ export class AttachmentsComponent implements OnInit {
|
||||
}
|
||||
|
||||
async submit() {
|
||||
if (!this.hasUpdatedKey) {
|
||||
this.platformUtilsService.showToast(
|
||||
"error",
|
||||
this.i18nService.t("errorOccurred"),
|
||||
this.i18nService.t("updateKey")
|
||||
);
|
||||
return;
|
||||
}
|
||||
|
||||
const fileEl = document.getElementById("file") as HTMLInputElement;
|
||||
const files = fileEl.files;
|
||||
if (files == null || files.length === 0) {
|
||||
@@ -191,7 +181,6 @@ export class AttachmentsComponent implements OnInit {
|
||||
this.cipherDomain = await this.loadCipher();
|
||||
this.cipher = await this.cipherDomain.decrypt();
|
||||
|
||||
this.hasUpdatedKey = await this.cryptoService.hasUserKey();
|
||||
const canAccessPremium = await this.stateService.getCanAccessPremium();
|
||||
this.canAccessAttachments = canAccessPremium || this.cipher.organizationId != null;
|
||||
|
||||
@@ -206,19 +195,6 @@ export class AttachmentsComponent implements OnInit {
|
||||
if (confirmed) {
|
||||
this.platformUtilsService.launchUri("https://vault.bitwarden.com/#/?premium=purchase");
|
||||
}
|
||||
} else if (!this.hasUpdatedKey) {
|
||||
const confirmed = await this.dialogService.openSimpleDialog({
|
||||
title: { key: "featureUnavailable" },
|
||||
content: { key: "updateKey" },
|
||||
acceptButtonText: { key: "learnMore" },
|
||||
type: "warning",
|
||||
});
|
||||
|
||||
if (confirmed) {
|
||||
this.platformUtilsService.launchUri(
|
||||
"https://bitwarden.com/help/account-encryption-key/#rotate-your-encryption-key"
|
||||
);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
Reference in New Issue
Block a user