1
0
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:
gbubemismith
2023-09-21 15:10:54 -04:00
100 changed files with 1300 additions and 906 deletions

View File

@@ -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"

View File

@@ -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)

View File

@@ -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];

View File

@@ -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);
}

View File

@@ -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);
}

View File

@@ -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(["/"]);

View File

@@ -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();
}
});

View File

@@ -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"
);
}
}
}