mirror of
https://github.com/bitwarden/browser
synced 2025-12-17 16:53:34 +00:00
Merge branch 'master' into PM-2135-beeep-refactor-and-refresh-web-user-verification-components
This commit is contained in:
@@ -0,0 +1,87 @@
|
||||
<label class="environment-selector-btn">
|
||||
{{ "region" | i18n }}:
|
||||
<a
|
||||
(click)="toggle(null)"
|
||||
cdkOverlayOrigin
|
||||
#trigger="cdkOverlayOrigin"
|
||||
aria-haspopup="menu"
|
||||
aria-controls="cdk-overlay-container"
|
||||
[ngSwitch]="selectedEnvironment"
|
||||
>
|
||||
<label *ngSwitchCase="ServerEnvironmentType.US" class="text-primary">{{ "us" | i18n }}</label>
|
||||
<label *ngSwitchCase="ServerEnvironmentType.EU" class="text-primary">{{ "eu" | i18n }}</label>
|
||||
<label *ngSwitchCase="ServerEnvironmentType.SelfHosted" class="text-primary">{{
|
||||
"selfHosted" | i18n
|
||||
}}</label>
|
||||
<i class="bwi bwi-fw bwi-sm bwi-angle-down" aria-hidden="true"></i>
|
||||
</a>
|
||||
</label>
|
||||
|
||||
<ng-template
|
||||
cdkConnectedOverlay
|
||||
[cdkConnectedOverlayOrigin]="trigger"
|
||||
(backdropClick)="close()"
|
||||
(detach)="close()"
|
||||
[cdkConnectedOverlayOpen]="isOpen"
|
||||
[cdkConnectedOverlayPositions]="overlayPostition"
|
||||
>
|
||||
<div class="box-content">
|
||||
<div class="environment-selector-dialog" [@transformPanel]="'open'" role="dialog">
|
||||
<button
|
||||
type="button"
|
||||
class="environment-selector-dialog-item"
|
||||
(click)="toggle(ServerEnvironmentType.US)"
|
||||
>
|
||||
<i
|
||||
class="bwi bwi-fw bwi-sm bwi-check"
|
||||
style="padding-bottom: 1px"
|
||||
aria-hidden="true"
|
||||
[style.visibility]="
|
||||
selectedEnvironment === ServerEnvironmentType.US ? 'visible' : 'hidden'
|
||||
"
|
||||
></i>
|
||||
<img class="img-us" alt="" />
|
||||
<span>{{ "us" | i18n }}</span>
|
||||
</button>
|
||||
<br />
|
||||
<button
|
||||
type="button"
|
||||
class="environment-selector-dialog-item"
|
||||
(click)="toggle(ServerEnvironmentType.EU)"
|
||||
*ngIf="euServerFlagEnabled"
|
||||
>
|
||||
<i
|
||||
class="bwi bwi-fw bwi-sm bwi-check"
|
||||
style="padding-bottom: 1px"
|
||||
aria-hidden="true"
|
||||
[style.visibility]="
|
||||
selectedEnvironment === ServerEnvironmentType.EU ? 'visible' : 'hidden'
|
||||
"
|
||||
></i>
|
||||
<img class="img-eu" alt="" />
|
||||
<span>{{ "eu" | i18n }}</span>
|
||||
</button>
|
||||
<br *ngIf="euServerFlagEnabled" />
|
||||
<button
|
||||
type="button"
|
||||
class="environment-selector-dialog-item"
|
||||
(click)="toggle(ServerEnvironmentType.SelfHosted)"
|
||||
>
|
||||
<i
|
||||
class="bwi bwi-fw bwi-sm bwi-check"
|
||||
style="padding-bottom: 1px"
|
||||
aria-hidden="true"
|
||||
[style.visibility]="
|
||||
selectedEnvironment === ServerEnvironmentType.SelfHosted ? 'visible' : 'hidden'
|
||||
"
|
||||
></i>
|
||||
<i
|
||||
class="bwi bwi-fw bwi-sm bwi-pencil-square"
|
||||
style="padding-bottom: 1px"
|
||||
aria-hidden="true"
|
||||
></i>
|
||||
<span>{{ "selfHosted" | i18n }}</span>
|
||||
</button>
|
||||
</div>
|
||||
</div>
|
||||
</ng-template>
|
||||
@@ -0,0 +1,109 @@
|
||||
import { animate, state, style, transition, trigger } from "@angular/animations";
|
||||
import { ConnectedPosition } from "@angular/cdk/overlay";
|
||||
import { Component, EventEmitter, OnDestroy, OnInit, Output } from "@angular/core";
|
||||
import { Router } from "@angular/router";
|
||||
import { Subject, takeUntil } from "rxjs";
|
||||
|
||||
import { ConfigServiceAbstraction } from "@bitwarden/common/abstractions/config/config.service.abstraction";
|
||||
import { EnvironmentService } from "@bitwarden/common/abstractions/environment.service";
|
||||
import { FeatureFlag } from "@bitwarden/common/enums/feature-flag.enum";
|
||||
|
||||
@Component({
|
||||
selector: "environment-selector",
|
||||
templateUrl: "environment-selector.component.html",
|
||||
animations: [
|
||||
trigger("transformPanel", [
|
||||
state(
|
||||
"void",
|
||||
style({
|
||||
opacity: 0,
|
||||
})
|
||||
),
|
||||
transition(
|
||||
"void => open",
|
||||
animate(
|
||||
"100ms linear",
|
||||
style({
|
||||
opacity: 1,
|
||||
})
|
||||
)
|
||||
),
|
||||
transition("* => void", animate("100ms linear", style({ opacity: 0 }))),
|
||||
]),
|
||||
],
|
||||
})
|
||||
export class EnvironmentSelectorComponent implements OnInit, OnDestroy {
|
||||
@Output() onOpenSelfHostedSettings = new EventEmitter();
|
||||
euServerFlagEnabled: boolean;
|
||||
isOpen = false;
|
||||
showingModal = false;
|
||||
selectedEnvironment: ServerEnvironment;
|
||||
ServerEnvironmentType = ServerEnvironment;
|
||||
overlayPostition: ConnectedPosition[] = [
|
||||
{
|
||||
originX: "start",
|
||||
originY: "bottom",
|
||||
overlayX: "start",
|
||||
overlayY: "top",
|
||||
},
|
||||
];
|
||||
protected componentDestroyed$: Subject<void> = new Subject();
|
||||
|
||||
constructor(
|
||||
protected environmentService: EnvironmentService,
|
||||
protected configService: ConfigServiceAbstraction,
|
||||
protected router: Router
|
||||
) {}
|
||||
|
||||
async ngOnInit() {
|
||||
this.configService.serverConfig$.pipe(takeUntil(this.componentDestroyed$)).subscribe(() => {
|
||||
this.updateEnvironmentInfo();
|
||||
});
|
||||
this.updateEnvironmentInfo();
|
||||
}
|
||||
|
||||
ngOnDestroy(): void {
|
||||
this.componentDestroyed$.next();
|
||||
this.componentDestroyed$.complete();
|
||||
}
|
||||
|
||||
async toggle(option: ServerEnvironment) {
|
||||
this.isOpen = !this.isOpen;
|
||||
if (option === null) {
|
||||
return;
|
||||
}
|
||||
if (option === ServerEnvironment.EU) {
|
||||
await this.environmentService.setUrls({ base: "https://vault.bitwarden.eu" });
|
||||
} else if (option === ServerEnvironment.US) {
|
||||
await this.environmentService.setUrls({ base: "https://vault.bitwarden.com" });
|
||||
} else if (option === ServerEnvironment.SelfHosted) {
|
||||
this.onOpenSelfHostedSettings.emit();
|
||||
}
|
||||
this.updateEnvironmentInfo();
|
||||
}
|
||||
|
||||
async updateEnvironmentInfo() {
|
||||
this.euServerFlagEnabled = await this.configService.getFeatureFlagBool(
|
||||
FeatureFlag.DisplayEuEnvironmentFlag
|
||||
);
|
||||
const webvaultUrl = this.environmentService.getWebVaultUrl();
|
||||
if (this.environmentService.isSelfHosted()) {
|
||||
this.selectedEnvironment = ServerEnvironment.SelfHosted;
|
||||
} else if (webvaultUrl != null && webvaultUrl.includes("bitwarden.eu")) {
|
||||
this.selectedEnvironment = ServerEnvironment.EU;
|
||||
} else {
|
||||
this.selectedEnvironment = ServerEnvironment.US;
|
||||
}
|
||||
}
|
||||
|
||||
close() {
|
||||
this.isOpen = false;
|
||||
this.updateEnvironmentInfo();
|
||||
}
|
||||
}
|
||||
|
||||
enum ServerEnvironment {
|
||||
US = "US",
|
||||
EU = "EU",
|
||||
SelfHosted = "Self-hosted",
|
||||
}
|
||||
@@ -3,9 +3,9 @@ import { FormBuilder, Validators } from "@angular/forms";
|
||||
import { ActivatedRoute, Router } from "@angular/router";
|
||||
import { take } from "rxjs/operators";
|
||||
|
||||
import { ApiService } from "@bitwarden/common/abstractions/api.service";
|
||||
import { AppIdService } from "@bitwarden/common/abstractions/appId.service";
|
||||
import { CryptoFunctionService } from "@bitwarden/common/abstractions/cryptoFunction.service";
|
||||
import { DevicesApiServiceAbstraction } from "@bitwarden/common/abstractions/devices/devices-api.service.abstraction";
|
||||
import { EnvironmentService } from "@bitwarden/common/abstractions/environment.service";
|
||||
import {
|
||||
AllValidationErrors,
|
||||
@@ -55,7 +55,7 @@ export class LoginComponent extends CaptchaProtectedComponent implements OnInit
|
||||
}
|
||||
|
||||
constructor(
|
||||
protected apiService: ApiService,
|
||||
protected devicesApiService: DevicesApiServiceAbstraction,
|
||||
protected appIdService: AppIdService,
|
||||
protected authService: AuthService,
|
||||
protected router: Router,
|
||||
@@ -295,7 +295,7 @@ export class LoginComponent extends CaptchaProtectedComponent implements OnInit
|
||||
async getLoginWithDevice(email: string) {
|
||||
try {
|
||||
const deviceIdentifier = await this.appIdService.getAppId();
|
||||
const res = await this.apiService.getKnownDevice(email, deviceIdentifier);
|
||||
const res = await this.devicesApiService.getKnownDevice(email, deviceIdentifier);
|
||||
//ensure the application is not self-hosted
|
||||
this.showLoginWithDevice = res && !this.selfHosted;
|
||||
} catch (e) {
|
||||
|
||||
@@ -202,7 +202,9 @@ export class TwoFactorComponent extends CaptchaProtectedComponent implements OnI
|
||||
}
|
||||
if (this.onSuccessfulLogin != null) {
|
||||
this.loginService.clearValues();
|
||||
await this.onSuccessfulLogin();
|
||||
// Note: awaiting this will currently cause a hang on desktop & browser as they will wait for a full sync to complete
|
||||
// before nagivating to the success route.
|
||||
this.onSuccessfulLogin();
|
||||
}
|
||||
if (response.resetMasterPassword) {
|
||||
this.successRoute = "set-password";
|
||||
|
||||
Reference in New Issue
Block a user