mirror of
https://github.com/bitwarden/browser
synced 2025-12-17 16:53:34 +00:00
Merge branch 'master' of https://github.com/bitwarden/clients into tools/pm-147/import-error-states-usability-improvements
This commit is contained in:
@@ -1,6 +1,6 @@
|
||||
{
|
||||
"name": "@bitwarden/web-vault",
|
||||
"version": "2023.7.0",
|
||||
"version": "2023.8.2",
|
||||
"scripts": {
|
||||
"build:oss": "webpack",
|
||||
"build:bit": "webpack -c ../../bitwarden_license/bit-web/webpack.config.js",
|
||||
|
||||
@@ -1,9 +1,9 @@
|
||||
import { Injectable } from "@angular/core";
|
||||
import { ActivatedRouteSnapshot, CanActivate, Router, RouterStateSnapshot } from "@angular/router";
|
||||
|
||||
import { DialogServiceAbstraction, SimpleDialogType } from "@bitwarden/angular/services/dialog";
|
||||
import { OrganizationService } from "@bitwarden/common/admin-console/abstractions/organization/organization.service.abstraction";
|
||||
import { MessagingService } from "@bitwarden/common/platform/abstractions/messaging.service";
|
||||
import { DialogService } from "@bitwarden/components";
|
||||
|
||||
@Injectable({
|
||||
providedIn: "root",
|
||||
@@ -13,7 +13,7 @@ export class IsPaidOrgGuard implements CanActivate {
|
||||
private router: Router,
|
||||
private organizationService: OrganizationService,
|
||||
private messagingService: MessagingService,
|
||||
private dialogService: DialogServiceAbstraction
|
||||
private dialogService: DialogService
|
||||
) {}
|
||||
|
||||
async canActivate(route: ActivatedRouteSnapshot, state: RouterStateSnapshot) {
|
||||
@@ -31,7 +31,7 @@ export class IsPaidOrgGuard implements CanActivate {
|
||||
content: { key: "notAvailableForFreeOrganization" },
|
||||
acceptButtonText: { key: "ok" },
|
||||
cancelButtonText: null,
|
||||
type: SimpleDialogType.INFO,
|
||||
type: "info",
|
||||
});
|
||||
return false;
|
||||
} else {
|
||||
|
||||
@@ -3,7 +3,6 @@ import { Component, Inject, OnInit } from "@angular/core";
|
||||
import { FormBuilder } from "@angular/forms";
|
||||
|
||||
import { UserNamePipe } from "@bitwarden/angular/pipes/user-name.pipe";
|
||||
import { DialogServiceAbstraction } from "@bitwarden/angular/services/dialog";
|
||||
import { ApiService } from "@bitwarden/common/abstractions/api.service";
|
||||
import { OrganizationUserService } from "@bitwarden/common/abstractions/organization-user/organization-user.service";
|
||||
import { EventResponse } from "@bitwarden/common/models/response/event.response";
|
||||
@@ -13,7 +12,7 @@ import { I18nService } from "@bitwarden/common/platform/abstractions/i18n.servic
|
||||
import { LogService } from "@bitwarden/common/platform/abstractions/log.service";
|
||||
import { PlatformUtilsService } from "@bitwarden/common/platform/abstractions/platform-utils.service";
|
||||
import { ValidationService } from "@bitwarden/common/platform/abstractions/validation.service";
|
||||
import { TableDataSource } from "@bitwarden/components";
|
||||
import { DialogService, TableDataSource } from "@bitwarden/components";
|
||||
|
||||
import { EventService } from "../../../core";
|
||||
import { SharedModule } from "../../../shared";
|
||||
@@ -186,7 +185,7 @@ export class EntityEventsComponent implements OnInit {
|
||||
* @param config Configuration for the dialog
|
||||
*/
|
||||
export const openEntityEventsDialog = (
|
||||
dialogService: DialogServiceAbstraction,
|
||||
dialogService: DialogService,
|
||||
config: DialogConfig<EntityEventsDialogParams>
|
||||
) => {
|
||||
return dialogService.open<void, EntityEventsDialogParams>(EntityEventsComponent, config);
|
||||
|
||||
@@ -3,7 +3,6 @@ import { ChangeDetectorRef, Component, Inject, OnDestroy, OnInit } from "@angula
|
||||
import { FormBuilder, Validators } from "@angular/forms";
|
||||
import { catchError, combineLatest, from, map, of, Subject, switchMap, takeUntil } from "rxjs";
|
||||
|
||||
import { DialogServiceAbstraction, SimpleDialogType } from "@bitwarden/angular/services/dialog";
|
||||
import { ApiService } from "@bitwarden/common/abstractions/api.service";
|
||||
import { OrganizationUserService } from "@bitwarden/common/abstractions/organization-user/organization-user.service";
|
||||
import { ErrorResponse } from "@bitwarden/common/models/response/error.response";
|
||||
@@ -14,6 +13,7 @@ import { CollectionService } from "@bitwarden/common/vault/abstractions/collecti
|
||||
import { CollectionData } from "@bitwarden/common/vault/models/data/collection.data";
|
||||
import { Collection } from "@bitwarden/common/vault/models/domain/collection";
|
||||
import { CollectionDetailsResponse } from "@bitwarden/common/vault/models/response/collection.response";
|
||||
import { DialogService } from "@bitwarden/components";
|
||||
|
||||
import { InternalGroupService as GroupService, GroupView } from "../core";
|
||||
import {
|
||||
@@ -64,7 +64,7 @@ export enum GroupAddEditDialogResultType {
|
||||
* @param config Configuration for the dialog
|
||||
*/
|
||||
export const openGroupAddEditDialog = (
|
||||
dialogService: DialogServiceAbstraction,
|
||||
dialogService: DialogService,
|
||||
config: DialogConfig<GroupAddEditDialogParams>
|
||||
) => {
|
||||
return dialogService.open<GroupAddEditDialogResultType, GroupAddEditDialogParams>(
|
||||
@@ -181,7 +181,7 @@ export class GroupAddEditComponent implements OnInit, OnDestroy {
|
||||
private logService: LogService,
|
||||
private formBuilder: FormBuilder,
|
||||
private changeDetectorRef: ChangeDetectorRef,
|
||||
private dialogService: DialogServiceAbstraction
|
||||
private dialogService: DialogService
|
||||
) {
|
||||
this.tabIndex = params.initialTab ?? GroupAddEditTabType.Info;
|
||||
}
|
||||
@@ -273,7 +273,7 @@ export class GroupAddEditComponent implements OnInit, OnDestroy {
|
||||
const confirmed = await this.dialogService.openSimpleDialog({
|
||||
title: this.group.name,
|
||||
content: { key: "deleteGroupConfirmation" },
|
||||
type: SimpleDialogType.WARNING,
|
||||
type: "warning",
|
||||
});
|
||||
if (!confirmed) {
|
||||
return false;
|
||||
|
||||
@@ -15,7 +15,6 @@ import {
|
||||
import { first } from "rxjs/operators";
|
||||
|
||||
import { SearchPipe } from "@bitwarden/angular/pipes/search.pipe";
|
||||
import { DialogServiceAbstraction, SimpleDialogType } from "@bitwarden/angular/services/dialog";
|
||||
import { ModalService } from "@bitwarden/angular/services/modal.service";
|
||||
import { ApiService } from "@bitwarden/common/abstractions/api.service";
|
||||
import { SearchService } from "@bitwarden/common/abstractions/search.service";
|
||||
@@ -32,6 +31,7 @@ import {
|
||||
CollectionResponse,
|
||||
} from "@bitwarden/common/vault/models/response/collection.response";
|
||||
import { CollectionView } from "@bitwarden/common/vault/models/view/collection.view";
|
||||
import { DialogService } from "@bitwarden/components";
|
||||
|
||||
import { InternalGroupService as GroupService, GroupView } from "../core";
|
||||
|
||||
@@ -127,7 +127,7 @@ export class GroupsComponent implements OnInit, OnDestroy {
|
||||
private route: ActivatedRoute,
|
||||
private i18nService: I18nService,
|
||||
private modalService: ModalService,
|
||||
private dialogService: DialogServiceAbstraction,
|
||||
private dialogService: DialogService,
|
||||
private platformUtilsService: PlatformUtilsService,
|
||||
private searchService: SearchService,
|
||||
private logService: LogService,
|
||||
@@ -236,7 +236,7 @@ export class GroupsComponent implements OnInit, OnDestroy {
|
||||
const confirmed = await this.dialogService.openSimpleDialog({
|
||||
title: groupRow.details.name,
|
||||
content: { key: "deleteGroupConfirmation" },
|
||||
type: SimpleDialogType.WARNING,
|
||||
type: "warning",
|
||||
});
|
||||
if (!confirmed) {
|
||||
return false;
|
||||
@@ -269,7 +269,7 @@ export class GroupsComponent implements OnInit, OnDestroy {
|
||||
placeholders: [groupsToDelete.length.toString()],
|
||||
},
|
||||
content: deleteMessage,
|
||||
type: SimpleDialogType.WARNING,
|
||||
type: "warning",
|
||||
});
|
||||
if (!confirmed) {
|
||||
return false;
|
||||
|
||||
@@ -28,10 +28,7 @@ export class UserConfirmComponent implements OnInit {
|
||||
async ngOnInit() {
|
||||
try {
|
||||
if (this.publicKey != null) {
|
||||
const fingerprint = await this.cryptoService.getFingerprint(
|
||||
this.userId,
|
||||
this.publicKey.buffer
|
||||
);
|
||||
const fingerprint = await this.cryptoService.getFingerprint(this.userId, this.publicKey);
|
||||
if (fingerprint != null) {
|
||||
this.fingerprint = fingerprint.join("-");
|
||||
}
|
||||
|
||||
@@ -7,6 +7,7 @@ import { OrganizationUserStatusType } from "@bitwarden/common/admin-console/enum
|
||||
import { CryptoService } from "@bitwarden/common/platform/abstractions/crypto.service";
|
||||
import { I18nService } from "@bitwarden/common/platform/abstractions/i18n.service";
|
||||
import { Utils } from "@bitwarden/common/platform/misc/utils";
|
||||
import { SymmetricCryptoKey } from "@bitwarden/common/platform/models/domain/symmetric-crypto-key";
|
||||
|
||||
import { BulkUserDetails } from "./bulk-status.component";
|
||||
|
||||
@@ -47,7 +48,7 @@ export class BulkConfirmComponent implements OnInit {
|
||||
|
||||
for (const entry of response.data) {
|
||||
const publicKey = Utils.fromB64ToArray(entry.key);
|
||||
const fingerprint = await this.cryptoService.getFingerprint(entry.userId, publicKey.buffer);
|
||||
const fingerprint = await this.cryptoService.getFingerprint(entry.userId, publicKey);
|
||||
if (fingerprint != null) {
|
||||
this.publicKeys.set(entry.id, publicKey);
|
||||
this.fingerprints.set(entry.id, fingerprint.join("-"));
|
||||
@@ -67,7 +68,7 @@ export class BulkConfirmComponent implements OnInit {
|
||||
if (publicKey == null) {
|
||||
continue;
|
||||
}
|
||||
const encryptedKey = await this.cryptoService.rsaEncrypt(key.key, publicKey.buffer);
|
||||
const encryptedKey = await this.cryptoService.rsaEncrypt(key.key, publicKey);
|
||||
userIdsWithKeys.push({
|
||||
id: user.id,
|
||||
key: encryptedKey.encryptedString,
|
||||
@@ -98,7 +99,7 @@ export class BulkConfirmComponent implements OnInit {
|
||||
);
|
||||
}
|
||||
|
||||
protected getCryptoKey() {
|
||||
protected getCryptoKey(): Promise<SymmetricCryptoKey> {
|
||||
return this.cryptoService.getOrgKey(this.organizationId);
|
||||
}
|
||||
|
||||
|
||||
@@ -1,11 +1,10 @@
|
||||
import { DialogRef, DIALOG_DATA } from "@angular/cdk/dialog";
|
||||
import { Component, Inject, OnInit } from "@angular/core";
|
||||
|
||||
import { DialogServiceAbstraction } from "@bitwarden/angular/services/dialog";
|
||||
import { OrganizationUserService } from "@bitwarden/common/abstractions/organization-user/organization-user.service";
|
||||
import { I18nService } from "@bitwarden/common/platform/abstractions/i18n.service";
|
||||
import { PlatformUtilsService } from "@bitwarden/common/platform/abstractions/platform-utils.service";
|
||||
import { TableDataSource } from "@bitwarden/components";
|
||||
import { DialogService, TableDataSource } from "@bitwarden/components";
|
||||
|
||||
import { OrganizationUserView } from "../../../core";
|
||||
|
||||
@@ -44,7 +43,7 @@ export class BulkEnableSecretsManagerDialogComponent implements OnInit {
|
||||
this.dialogRef.close();
|
||||
};
|
||||
|
||||
static open(dialogService: DialogServiceAbstraction, data: BulkEnableSecretsManagerDialogData) {
|
||||
static open(dialogService: DialogService, data: BulkEnableSecretsManagerDialogData) {
|
||||
return dialogService.open<unknown, BulkEnableSecretsManagerDialogData>(
|
||||
BulkEnableSecretsManagerDialogComponent,
|
||||
{ data }
|
||||
|
||||
@@ -246,7 +246,7 @@
|
||||
(change)="handleDependentPermissions()"
|
||||
/>
|
||||
<label class="!tw-font-normal" for="manageResetPassword">
|
||||
{{ "manageResetPassword" | i18n }}
|
||||
{{ "manageAccountRecovery" | i18n }}
|
||||
</label>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
@@ -3,7 +3,6 @@ import { Component, Inject, OnDestroy, OnInit } from "@angular/core";
|
||||
import { FormBuilder, Validators } from "@angular/forms";
|
||||
import { combineLatest, of, shareReplay, Subject, switchMap, takeUntil } from "rxjs";
|
||||
|
||||
import { DialogServiceAbstraction, SimpleDialogType } from "@bitwarden/angular/services/dialog";
|
||||
import { OrganizationUserService } from "@bitwarden/common/abstractions/organization-user/organization-user.service";
|
||||
import { OrganizationService } from "@bitwarden/common/admin-console/abstractions/organization/organization.service.abstraction";
|
||||
import {
|
||||
@@ -15,6 +14,7 @@ import { Organization } from "@bitwarden/common/admin-console/models/domain/orga
|
||||
import { I18nService } from "@bitwarden/common/platform/abstractions/i18n.service";
|
||||
import { PlatformUtilsService } from "@bitwarden/common/platform/abstractions/platform-utils.service";
|
||||
import { CollectionView } from "@bitwarden/common/vault/models/view/collection.view";
|
||||
import { DialogService } from "@bitwarden/components";
|
||||
|
||||
import { flagEnabled } from "../../../../../../utils/flags";
|
||||
import { CollectionAdminService } from "../../../../../vault/core/collection-admin.service";
|
||||
@@ -134,7 +134,7 @@ export class MemberDialogComponent implements OnInit, OnDestroy {
|
||||
private groupService: GroupService,
|
||||
private userService: UserAdminService,
|
||||
private organizationUserService: OrganizationUserService,
|
||||
private dialogService: DialogServiceAbstraction
|
||||
private dialogService: DialogService
|
||||
) {}
|
||||
|
||||
async ngOnInit() {
|
||||
@@ -302,7 +302,7 @@ export class MemberDialogComponent implements OnInit, OnDestroy {
|
||||
}
|
||||
|
||||
handleDependentPermissions() {
|
||||
// Manage Password Reset must have Manage Users enabled
|
||||
// Manage Password Reset (Account Recovery) must have Manage Users enabled
|
||||
if (
|
||||
this.permissionsGroup.value.manageResetPassword &&
|
||||
!this.permissionsGroup.value.manageUsers
|
||||
@@ -312,7 +312,7 @@ export class MemberDialogComponent implements OnInit, OnDestroy {
|
||||
this.platformUtilsService.showToast(
|
||||
"info",
|
||||
null,
|
||||
this.i18nService.t("resetPasswordManageUsers")
|
||||
this.i18nService.t("accountRecoveryManageUsers")
|
||||
);
|
||||
}
|
||||
}
|
||||
@@ -389,7 +389,7 @@ export class MemberDialogComponent implements OnInit, OnDestroy {
|
||||
let confirmed = await this.dialogService.openSimpleDialog({
|
||||
title: { key: "removeUserIdAccess", placeholders: [this.params.name] },
|
||||
content: { key: message },
|
||||
type: SimpleDialogType.WARNING,
|
||||
type: "warning",
|
||||
});
|
||||
|
||||
if (!confirmed) {
|
||||
@@ -426,7 +426,7 @@ export class MemberDialogComponent implements OnInit, OnDestroy {
|
||||
title: { key: "revokeUserId", placeholders: [this.params.name] },
|
||||
content: { key: "revokeUserConfirmation" },
|
||||
acceptButtonText: { key: "revokeAccess" },
|
||||
type: SimpleDialogType.WARNING,
|
||||
type: "warning",
|
||||
});
|
||||
|
||||
if (!confirmed) {
|
||||
@@ -496,7 +496,7 @@ export class MemberDialogComponent implements OnInit, OnDestroy {
|
||||
key: "removeOrgUserNoMasterPasswordDesc",
|
||||
placeholders: [this.params.name],
|
||||
},
|
||||
type: SimpleDialogType.WARNING,
|
||||
type: "warning",
|
||||
});
|
||||
}
|
||||
}
|
||||
@@ -557,7 +557,7 @@ function mapToGroupAccessSelections(groups: string[]): AccessItemValue[] {
|
||||
* @param config Configuration for the dialog
|
||||
*/
|
||||
export function openUserAddEditDialog(
|
||||
dialogService: DialogServiceAbstraction,
|
||||
dialogService: DialogService,
|
||||
config: DialogConfig<MemberDialogParams>
|
||||
) {
|
||||
return dialogService.open<MemberDialogResult, MemberDialogParams>(MemberDialogComponent, config);
|
||||
|
||||
@@ -10,7 +10,6 @@ import {
|
||||
import { Subject, takeUntil } from "rxjs";
|
||||
import zxcvbn from "zxcvbn";
|
||||
|
||||
import { DialogServiceAbstraction, SimpleDialogType } from "@bitwarden/angular/services/dialog";
|
||||
import { PasswordStrengthComponent } from "@bitwarden/angular/shared/components/password-strength/password-strength.component";
|
||||
import { OrganizationUserService } from "@bitwarden/common/abstractions/organization-user/organization-user.service";
|
||||
import { OrganizationUserResetPasswordRequest } from "@bitwarden/common/abstractions/organization-user/requests";
|
||||
@@ -23,8 +22,12 @@ import { LogService } from "@bitwarden/common/platform/abstractions/log.service"
|
||||
import { PlatformUtilsService } from "@bitwarden/common/platform/abstractions/platform-utils.service";
|
||||
import { Utils } from "@bitwarden/common/platform/misc/utils";
|
||||
import { EncString } from "@bitwarden/common/platform/models/domain/enc-string";
|
||||
import { SymmetricCryptoKey } from "@bitwarden/common/platform/models/domain/symmetric-crypto-key";
|
||||
import {
|
||||
SymmetricCryptoKey,
|
||||
UserKey,
|
||||
} from "@bitwarden/common/platform/models/domain/symmetric-crypto-key";
|
||||
import { PasswordGenerationServiceAbstraction } from "@bitwarden/common/tools/generator/password";
|
||||
import { DialogService } from "@bitwarden/components";
|
||||
|
||||
@Component({
|
||||
selector: "app-reset-password",
|
||||
@@ -54,7 +57,7 @@ export class ResetPasswordComponent implements OnInit, OnDestroy {
|
||||
private cryptoService: CryptoService,
|
||||
private logService: LogService,
|
||||
private organizationUserService: OrganizationUserService,
|
||||
private dialogService: DialogServiceAbstraction
|
||||
private dialogService: DialogService
|
||||
) {}
|
||||
|
||||
async ngOnInit() {
|
||||
@@ -140,7 +143,7 @@ export class ResetPasswordComponent implements OnInit, OnDestroy {
|
||||
const result = await this.dialogService.openSimpleDialog({
|
||||
title: { key: "weakMasterPassword" },
|
||||
content: { key: "weakMasterPasswordDesc" },
|
||||
type: SimpleDialogType.WARNING,
|
||||
type: "warning",
|
||||
});
|
||||
|
||||
if (!result) {
|
||||
@@ -171,26 +174,32 @@ export class ResetPasswordComponent implements OnInit, OnDestroy {
|
||||
orgSymKey
|
||||
);
|
||||
|
||||
// Decrypt User's Reset Password Key to get EncKey
|
||||
// Decrypt User's Reset Password Key to get UserKey
|
||||
const decValue = await this.cryptoService.rsaDecrypt(resetPasswordKey, decPrivateKey);
|
||||
const userEncKey = new SymmetricCryptoKey(decValue);
|
||||
const existingUserKey = new SymmetricCryptoKey(decValue) as UserKey;
|
||||
|
||||
// Create new key and hash new password
|
||||
const newKey = await this.cryptoService.makeKey(
|
||||
// Create new master key and hash new password
|
||||
const newMasterKey = await this.cryptoService.makeMasterKey(
|
||||
this.newPassword,
|
||||
this.email.trim().toLowerCase(),
|
||||
kdfType,
|
||||
new KdfConfig(kdfIterations, kdfMemory, kdfParallelism)
|
||||
);
|
||||
const newPasswordHash = await this.cryptoService.hashPassword(this.newPassword, newKey);
|
||||
const newMasterKeyHash = await this.cryptoService.hashMasterKey(
|
||||
this.newPassword,
|
||||
newMasterKey
|
||||
);
|
||||
|
||||
// Create new encKey for the User
|
||||
const newEncKey = await this.cryptoService.remakeEncKey(newKey, userEncKey);
|
||||
// Create new encrypted user key for the User
|
||||
const newUserKey = await this.cryptoService.encryptUserKeyWithMasterKey(
|
||||
newMasterKey,
|
||||
existingUserKey
|
||||
);
|
||||
|
||||
// Create request
|
||||
const request = new OrganizationUserResetPasswordRequest();
|
||||
request.key = newEncKey[1].encryptedString;
|
||||
request.newMasterPasswordHash = newPasswordHash;
|
||||
request.key = newUserKey[1].encryptedString;
|
||||
request.newMasterPasswordHash = newMasterKeyHash;
|
||||
|
||||
// Change user's password
|
||||
return this.organizationUserService.putOrganizationUserResetPassword(
|
||||
|
||||
@@ -16,12 +16,6 @@ import {
|
||||
|
||||
import { SearchPipe } from "@bitwarden/angular/pipes/search.pipe";
|
||||
import { UserNamePipe } from "@bitwarden/angular/pipes/user-name.pipe";
|
||||
import {
|
||||
DialogServiceAbstraction,
|
||||
SimpleDialogCloseType,
|
||||
SimpleDialogOptions,
|
||||
SimpleDialogType,
|
||||
} from "@bitwarden/angular/services/dialog";
|
||||
import { ModalService } from "@bitwarden/angular/services/modal.service";
|
||||
import { ApiService } from "@bitwarden/common/abstractions/api.service";
|
||||
import { OrganizationUserService } from "@bitwarden/common/abstractions/organization-user/organization-user.service";
|
||||
@@ -55,6 +49,7 @@ import { SyncService } from "@bitwarden/common/vault/abstractions/sync/sync.serv
|
||||
import { CollectionData } from "@bitwarden/common/vault/models/data/collection.data";
|
||||
import { Collection } from "@bitwarden/common/vault/models/domain/collection";
|
||||
import { CollectionDetailsResponse } from "@bitwarden/common/vault/models/response/collection.response";
|
||||
import { DialogService, SimpleDialogOptions } from "@bitwarden/components";
|
||||
|
||||
import { flagEnabled } from "../../../../utils/flags";
|
||||
import { openEntityEventsDialog } from "../../../admin-console/organizations/manage/entity-events.component";
|
||||
@@ -125,7 +120,7 @@ export class PeopleComponent
|
||||
private organizationService: OrganizationService,
|
||||
private organizationApiService: OrganizationApiServiceAbstraction,
|
||||
private organizationUserService: OrganizationUserService,
|
||||
dialogService: DialogServiceAbstraction,
|
||||
dialogService: DialogService,
|
||||
private router: Router,
|
||||
private groupService: GroupService,
|
||||
private collectionService: CollectionService
|
||||
@@ -302,7 +297,7 @@ export class PeopleComponent
|
||||
|
||||
async confirmUser(user: OrganizationUserView, publicKey: Uint8Array): Promise<void> {
|
||||
const orgKey = await this.cryptoService.getOrgKey(this.organization.id);
|
||||
const key = await this.cryptoService.rsaEncrypt(orgKey.key, publicKey.buffer);
|
||||
const key = await this.cryptoService.rsaEncrypt(orgKey.key, publicKey);
|
||||
const request = new OrganizationUserConfirmRequest();
|
||||
request.key = key.encryptedString;
|
||||
await this.organizationUserService.postOrganizationUserConfirm(
|
||||
@@ -359,7 +354,7 @@ export class PeopleComponent
|
||||
: "freeOrgInvLimitReachedNoManageBilling",
|
||||
this.organization.seats
|
||||
),
|
||||
type: SimpleDialogType.PRIMARY,
|
||||
type: "primary",
|
||||
};
|
||||
|
||||
if (this.organization.canEditSubscription) {
|
||||
@@ -371,12 +366,12 @@ export class PeopleComponent
|
||||
|
||||
const simpleDialog = this.dialogService.openSimpleDialogRef(orgUpgradeSimpleDialogOpts);
|
||||
|
||||
firstValueFrom(simpleDialog.closed).then((result: SimpleDialogCloseType | undefined) => {
|
||||
firstValueFrom(simpleDialog.closed).then((result: boolean | undefined) => {
|
||||
if (!result) {
|
||||
return;
|
||||
}
|
||||
|
||||
if (result == SimpleDialogCloseType.ACCEPT && this.organization.canEditSubscription) {
|
||||
if (result && this.organization.canEditSubscription) {
|
||||
this.router.navigate(["/organizations", this.organization.id, "billing", "subscription"], {
|
||||
queryParams: { upgrade: true },
|
||||
});
|
||||
@@ -581,7 +576,7 @@ export class PeopleComponent
|
||||
placeholders: [this.userNamePipe.transform(user)],
|
||||
},
|
||||
content: { key: content },
|
||||
type: SimpleDialogType.WARNING,
|
||||
type: "warning",
|
||||
});
|
||||
|
||||
if (!confirmed) {
|
||||
@@ -600,7 +595,7 @@ export class PeopleComponent
|
||||
title: { key: "revokeAccess", placeholders: [this.userNamePipe.transform(user)] },
|
||||
content: this.revokeWarningMessage(),
|
||||
acceptButtonText: { key: "revokeAccess" },
|
||||
type: SimpleDialogType.WARNING,
|
||||
type: "warning",
|
||||
});
|
||||
|
||||
if (!confirmed) {
|
||||
@@ -676,7 +671,7 @@ export class PeopleComponent
|
||||
key: "removeOrgUserNoMasterPasswordDesc",
|
||||
placeholders: [this.userNamePipe.transform(user)],
|
||||
},
|
||||
type: SimpleDialogType.WARNING,
|
||||
type: "warning",
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1,7 +1,7 @@
|
||||
import { NgModule } from "@angular/core";
|
||||
import { RouterModule, Routes } from "@angular/router";
|
||||
|
||||
import { AuthGuard } from "@bitwarden/angular/auth/guards/auth.guard";
|
||||
import { AuthGuard } from "@bitwarden/angular/auth/guards";
|
||||
import {
|
||||
canAccessOrgAdmin,
|
||||
canAccessGroupsTab,
|
||||
|
||||
@@ -3,7 +3,6 @@ import { FormBuilder, Validators } from "@angular/forms";
|
||||
import { ActivatedRoute, Router } from "@angular/router";
|
||||
import { combineLatest, lastValueFrom, Subject, switchMap, takeUntil, from } from "rxjs";
|
||||
|
||||
import { DialogServiceAbstraction } from "@bitwarden/angular/services/dialog";
|
||||
import { ModalService } from "@bitwarden/angular/services/modal.service";
|
||||
import { OrganizationApiServiceAbstraction } from "@bitwarden/common/admin-console/abstractions/organization/organization-api.service.abstraction";
|
||||
import { OrganizationService } from "@bitwarden/common/admin-console/abstractions/organization/organization.service.abstraction";
|
||||
@@ -15,6 +14,7 @@ import { I18nService } from "@bitwarden/common/platform/abstractions/i18n.servic
|
||||
import { LogService } from "@bitwarden/common/platform/abstractions/log.service";
|
||||
import { PlatformUtilsService } from "@bitwarden/common/platform/abstractions/platform-utils.service";
|
||||
import { Utils } from "@bitwarden/common/platform/misc/utils";
|
||||
import { DialogService } from "@bitwarden/components";
|
||||
|
||||
import { ApiKeyComponent } from "../../../settings/api-key.component";
|
||||
import { PurgeVaultComponent } from "../../../settings/purge-vault.component";
|
||||
@@ -61,7 +61,7 @@ export class AccountComponent {
|
||||
});
|
||||
|
||||
protected organizationId: string;
|
||||
protected publicKeyBuffer: ArrayBuffer;
|
||||
protected publicKeyBuffer: Uint8Array;
|
||||
|
||||
private destroy$ = new Subject<void>();
|
||||
|
||||
@@ -75,7 +75,7 @@ export class AccountComponent {
|
||||
private router: Router,
|
||||
private organizationService: OrganizationService,
|
||||
private organizationApiService: OrganizationApiServiceAbstraction,
|
||||
private dialogService: DialogServiceAbstraction,
|
||||
private dialogService: DialogService,
|
||||
private formBuilder: FormBuilder
|
||||
) {}
|
||||
|
||||
@@ -106,7 +106,7 @@ export class AccountComponent {
|
||||
this.org = orgResponse;
|
||||
|
||||
// Public Key Buffer for Org Fingerprint Generation
|
||||
this.publicKeyBuffer = Utils.fromB64ToArray(orgKeys?.publicKey)?.buffer;
|
||||
this.publicKeyBuffer = Utils.fromB64ToArray(orgKeys?.publicKey);
|
||||
|
||||
// Patch existing values
|
||||
this.formGroup.patchValue({
|
||||
|
||||
@@ -3,7 +3,6 @@ import { Component, Inject, OnDestroy, OnInit } from "@angular/core";
|
||||
import { FormBuilder, FormControl, Validators } from "@angular/forms";
|
||||
import { combineLatest, Subject, takeUntil } from "rxjs";
|
||||
|
||||
import { DialogServiceAbstraction } from "@bitwarden/angular/services/dialog";
|
||||
import { OrganizationApiServiceAbstraction } from "@bitwarden/common/admin-console/abstractions/organization/organization-api.service.abstraction";
|
||||
import { OrganizationService } from "@bitwarden/common/admin-console/abstractions/organization/organization.service.abstraction";
|
||||
import { Organization } from "@bitwarden/common/admin-console/models/domain/organization";
|
||||
@@ -15,6 +14,7 @@ import { Verification } from "@bitwarden/common/types/verification";
|
||||
import { CipherService } from "@bitwarden/common/vault/abstractions/cipher.service";
|
||||
import { CipherType } from "@bitwarden/common/vault/enums/cipher-type";
|
||||
import { CipherView } from "@bitwarden/common/vault/models/view/cipher.view";
|
||||
import { DialogService } from "@bitwarden/components";
|
||||
|
||||
import { UserVerificationModule } from "../../../../auth/shared/components/user-verification";
|
||||
import { SharedModule } from "../../../../shared/shared.module";
|
||||
@@ -168,7 +168,7 @@ export class DeleteOrganizationDialogComponent implements OnInit, OnDestroy {
|
||||
* @param config Configuration for the dialog
|
||||
*/
|
||||
export function openDeleteOrganizationDialog(
|
||||
dialogService: DialogServiceAbstraction,
|
||||
dialogService: DialogService,
|
||||
config: DialogConfig<DeleteOrganizationDialogParams>
|
||||
) {
|
||||
return dialogService.open<DeleteOrganizationDialogResult, DeleteOrganizationDialogParams>(
|
||||
|
||||
@@ -70,6 +70,9 @@ function getSettingsRoute(organization: Organization) {
|
||||
if (organization.canManageScim) {
|
||||
return "scim";
|
||||
}
|
||||
if (organization.canManageDeviceApprovals) {
|
||||
return "device-approvals";
|
||||
}
|
||||
return undefined;
|
||||
}
|
||||
|
||||
|
||||
@@ -65,7 +65,7 @@
|
||||
routerLink="device-approvals"
|
||||
class="list-group-item"
|
||||
routerLinkActive="active"
|
||||
*ngIf="org.canManageUsersPassword"
|
||||
*ngIf="org.canManageDeviceApprovals"
|
||||
>
|
||||
{{ "deviceApprovals" | i18n }}
|
||||
</a>
|
||||
|
||||
@@ -3,7 +3,6 @@ import { ActivatedRoute, Router } from "@angular/router";
|
||||
import { lastValueFrom, Observable, Subject } from "rxjs";
|
||||
import { first, map, takeUntil } from "rxjs/operators";
|
||||
|
||||
import { DialogServiceAbstraction } from "@bitwarden/angular/services/dialog";
|
||||
import { ApiService } from "@bitwarden/common/abstractions/api.service";
|
||||
import { OrganizationService } from "@bitwarden/common/admin-console/abstractions/organization/organization.service.abstraction";
|
||||
import { Organization } from "@bitwarden/common/admin-console/models/domain/organization";
|
||||
@@ -14,6 +13,7 @@ import { I18nService } from "@bitwarden/common/platform/abstractions/i18n.servic
|
||||
import { PlatformUtilsService } from "@bitwarden/common/platform/abstractions/platform-utils.service";
|
||||
import { ValidationService } from "@bitwarden/common/platform/abstractions/validation.service";
|
||||
import { SyncService } from "@bitwarden/common/vault/abstractions/sync/sync.service.abstraction";
|
||||
import { DialogService } from "@bitwarden/components";
|
||||
|
||||
import { OrganizationPlansComponent } from "../../../billing/settings/organization-plans.component";
|
||||
import {
|
||||
@@ -62,7 +62,7 @@ export class FamiliesForEnterpriseSetupComponent implements OnInit, OnDestroy {
|
||||
private syncService: SyncService,
|
||||
private validationService: ValidationService,
|
||||
private organizationService: OrganizationService,
|
||||
private dialogService: DialogServiceAbstraction
|
||||
private dialogService: DialogService
|
||||
) {}
|
||||
|
||||
async ngOnInit() {
|
||||
|
||||
@@ -2,7 +2,6 @@ import { Component } from "@angular/core";
|
||||
import { UntypedFormBuilder } from "@angular/forms";
|
||||
import { ActivatedRoute } from "@angular/router";
|
||||
|
||||
import { DialogServiceAbstraction } from "@bitwarden/angular/services/dialog";
|
||||
import { EventCollectionService } from "@bitwarden/common/abstractions/event/event-collection.service";
|
||||
import { PolicyService } from "@bitwarden/common/admin-console/abstractions/policy/policy.service.abstraction";
|
||||
import { UserVerificationService } from "@bitwarden/common/auth/abstractions/user-verification/user-verification.service.abstraction";
|
||||
@@ -12,6 +11,7 @@ import { FileDownloadService } from "@bitwarden/common/platform/abstractions/fil
|
||||
import { I18nService } from "@bitwarden/common/platform/abstractions/i18n.service";
|
||||
import { LogService } from "@bitwarden/common/platform/abstractions/log.service";
|
||||
import { PlatformUtilsService } from "@bitwarden/common/platform/abstractions/platform-utils.service";
|
||||
import { DialogService } from "@bitwarden/components";
|
||||
import { VaultExportServiceAbstraction } from "@bitwarden/exporter/vault-export";
|
||||
|
||||
import { ExportComponent } from "../../../../tools/import-export/export.component";
|
||||
@@ -34,7 +34,7 @@ export class OrganizationExportComponent extends ExportComponent {
|
||||
userVerificationService: UserVerificationService,
|
||||
formBuilder: UntypedFormBuilder,
|
||||
fileDownloadService: FileDownloadService,
|
||||
dialogService: DialogServiceAbstraction
|
||||
dialogService: DialogService
|
||||
) {
|
||||
super(
|
||||
cryptoService,
|
||||
|
||||
@@ -1,8 +1,8 @@
|
||||
import { Component } from "@angular/core";
|
||||
import { FormBuilder } from "@angular/forms";
|
||||
import { ActivatedRoute, Router } from "@angular/router";
|
||||
import { switchMap, takeUntil } from "rxjs/operators";
|
||||
|
||||
import { DialogServiceAbstraction, SimpleDialogType } from "@bitwarden/angular/services/dialog";
|
||||
import { ModalService } from "@bitwarden/angular/services/modal.service";
|
||||
import {
|
||||
canAccessVaultTab,
|
||||
@@ -13,7 +13,10 @@ import { Organization } from "@bitwarden/common/admin-console/models/domain/orga
|
||||
import { I18nService } from "@bitwarden/common/platform/abstractions/i18n.service";
|
||||
import { LogService } from "@bitwarden/common/platform/abstractions/log.service";
|
||||
import { PlatformUtilsService } from "@bitwarden/common/platform/abstractions/platform-utils.service";
|
||||
import { CollectionService } from "@bitwarden/common/vault/abstractions/collection.service";
|
||||
import { FolderService } from "@bitwarden/common/vault/abstractions/folder/folder.service.abstraction";
|
||||
import { SyncService } from "@bitwarden/common/vault/abstractions/sync/sync.service.abstraction";
|
||||
import { DialogService } from "@bitwarden/components";
|
||||
import { ImportServiceAbstraction } from "@bitwarden/importer";
|
||||
|
||||
import { ImportComponent } from "../../../../tools/import-export/import.component";
|
||||
@@ -37,11 +40,14 @@ export class OrganizationImportComponent extends ImportComponent {
|
||||
private route: ActivatedRoute,
|
||||
platformUtilsService: PlatformUtilsService,
|
||||
policyService: PolicyService,
|
||||
private organizationService: OrganizationService,
|
||||
organizationService: OrganizationService,
|
||||
logService: LogService,
|
||||
modalService: ModalService,
|
||||
syncService: SyncService,
|
||||
dialogService: DialogServiceAbstraction
|
||||
dialogService: DialogService,
|
||||
folderService: FolderService,
|
||||
collectionService: CollectionService,
|
||||
formBuilder: FormBuilder
|
||||
) {
|
||||
super(
|
||||
i18nService,
|
||||
@@ -52,7 +58,11 @@ export class OrganizationImportComponent extends ImportComponent {
|
||||
logService,
|
||||
modalService,
|
||||
syncService,
|
||||
dialogService
|
||||
dialogService,
|
||||
folderService,
|
||||
collectionService,
|
||||
organizationService,
|
||||
formBuilder
|
||||
);
|
||||
}
|
||||
|
||||
@@ -74,20 +84,19 @@ export class OrganizationImportComponent extends ImportComponent {
|
||||
await this.router.navigate(["organizations", this.organizationId, "vault"]);
|
||||
} else {
|
||||
this.fileSelected = null;
|
||||
this.fileContents = "";
|
||||
}
|
||||
}
|
||||
|
||||
async submit() {
|
||||
protected async performImport() {
|
||||
const confirmed = await this.dialogService.openSimpleDialog({
|
||||
title: { key: "warning" },
|
||||
content: { key: "importWarning", placeholders: [this.organization.name] },
|
||||
type: SimpleDialogType.WARNING,
|
||||
type: "warning",
|
||||
});
|
||||
|
||||
if (!confirmed) {
|
||||
return;
|
||||
}
|
||||
super.submit();
|
||||
await super.performImport();
|
||||
}
|
||||
}
|
||||
|
||||
@@ -58,8 +58,8 @@ export class EnrollMasterPasswordReset {
|
||||
const publicKey = Utils.fromB64ToArray(orgKeys.publicKey);
|
||||
|
||||
// RSA Encrypt user's encKey.key with organization public key
|
||||
const encKey = await this.cryptoService.getEncKey();
|
||||
const encryptedKey = await this.cryptoService.rsaEncrypt(encKey.key, publicKey.buffer);
|
||||
const userKey = await this.cryptoService.getUserKey();
|
||||
const encryptedKey = await this.cryptoService.rsaEncrypt(userKey.key, publicKey);
|
||||
keyString = encryptedKey.encryptedString;
|
||||
toastStringRef = "enrollPasswordResetSuccess";
|
||||
|
||||
|
||||
@@ -2,12 +2,12 @@ import { formatDate } from "@angular/common";
|
||||
import { Component, EventEmitter, Input, Output, OnInit } from "@angular/core";
|
||||
import { firstValueFrom } from "rxjs";
|
||||
|
||||
import { DialogServiceAbstraction, SimpleDialogType } from "@bitwarden/angular/services/dialog";
|
||||
import { ApiService } from "@bitwarden/common/abstractions/api.service";
|
||||
import { Organization } from "@bitwarden/common/admin-console/models/domain/organization";
|
||||
import { I18nService } from "@bitwarden/common/platform/abstractions/i18n.service";
|
||||
import { LogService } from "@bitwarden/common/platform/abstractions/log.service";
|
||||
import { PlatformUtilsService } from "@bitwarden/common/platform/abstractions/platform-utils.service";
|
||||
import { DialogService } from "@bitwarden/components";
|
||||
|
||||
@Component({
|
||||
selector: "[sponsoring-org-row]",
|
||||
@@ -32,7 +32,7 @@ export class SponsoringOrgRowComponent implements OnInit {
|
||||
private i18nService: I18nService,
|
||||
private logService: LogService,
|
||||
private platformUtilsService: PlatformUtilsService,
|
||||
private dialogService: DialogServiceAbstraction
|
||||
private dialogService: DialogService
|
||||
) {}
|
||||
|
||||
async ngOnInit() {
|
||||
@@ -73,7 +73,7 @@ export class SponsoringOrgRowComponent implements OnInit {
|
||||
title: `${this.i18nService.t("remove")} ${this.sponsoringOrg.familySponsorshipFriendlyName}?`,
|
||||
content: { key: "revokeSponsorshipConfirmation" },
|
||||
acceptButtonText: { key: "remove" },
|
||||
type: SimpleDialogType.WARNING,
|
||||
type: "warning",
|
||||
});
|
||||
|
||||
if (!confirmed) {
|
||||
|
||||
@@ -7,12 +7,11 @@ import { IndividualConfig, ToastrService } from "ngx-toastr";
|
||||
import { Subject, takeUntil } from "rxjs";
|
||||
import Swal from "sweetalert2";
|
||||
|
||||
import { DialogServiceAbstraction, SimpleDialogType } from "@bitwarden/angular/services/dialog";
|
||||
import { EventUploadService } from "@bitwarden/common/abstractions/event/event-upload.service";
|
||||
import { NotificationsService } from "@bitwarden/common/abstractions/notifications.service";
|
||||
import { SearchService } from "@bitwarden/common/abstractions/search.service";
|
||||
import { SettingsService } from "@bitwarden/common/abstractions/settings.service";
|
||||
import { VaultTimeoutService } from "@bitwarden/common/abstractions/vaultTimeout/vaultTimeout.service";
|
||||
import { VaultTimeoutService } from "@bitwarden/common/abstractions/vault-timeout/vault-timeout.service";
|
||||
import { InternalPolicyService } from "@bitwarden/common/admin-console/abstractions/policy/policy.service.abstraction";
|
||||
import { AuthService } from "@bitwarden/common/auth/abstractions/auth.service";
|
||||
import { KeyConnectorService } from "@bitwarden/common/auth/abstractions/key-connector.service";
|
||||
@@ -27,6 +26,7 @@ import { CipherService } from "@bitwarden/common/vault/abstractions/cipher.servi
|
||||
import { CollectionService } from "@bitwarden/common/vault/abstractions/collection.service";
|
||||
import { InternalFolderService } from "@bitwarden/common/vault/abstractions/folder/folder.service.abstraction";
|
||||
import { SyncService } from "@bitwarden/common/vault/abstractions/sync/sync.service.abstraction";
|
||||
import { DialogService } from "@bitwarden/components";
|
||||
|
||||
import { PolicyListService } from "./admin-console/core/policy-list.service";
|
||||
import {
|
||||
@@ -82,7 +82,7 @@ export class AppComponent implements OnDestroy, OnInit {
|
||||
protected policyListService: PolicyListService,
|
||||
private keyConnectorService: KeyConnectorService,
|
||||
private configService: ConfigServiceAbstraction,
|
||||
private dialogService: DialogServiceAbstraction
|
||||
private dialogService: DialogService
|
||||
) {}
|
||||
|
||||
ngOnInit() {
|
||||
@@ -145,7 +145,7 @@ export class AppComponent implements OnDestroy, OnInit {
|
||||
title: { key: "upgradeOrganization" },
|
||||
content: { key: "upgradeOrganizationDesc" },
|
||||
acceptButtonText: { key: "upgradeOrganization" },
|
||||
type: SimpleDialogType.INFO,
|
||||
type: "info",
|
||||
});
|
||||
if (upgradeConfirmed) {
|
||||
this.router.navigate([
|
||||
@@ -162,7 +162,7 @@ export class AppComponent implements OnDestroy, OnInit {
|
||||
title: { key: "premiumRequired" },
|
||||
content: { key: "premiumRequiredDesc" },
|
||||
acceptButtonText: { key: "upgrade" },
|
||||
type: SimpleDialogType.SUCCESS,
|
||||
type: "success",
|
||||
});
|
||||
if (premiumConfirmed) {
|
||||
this.router.navigate(["settings/subscription/premium"]);
|
||||
@@ -174,7 +174,7 @@ export class AppComponent implements OnDestroy, OnInit {
|
||||
title: { key: "emailVerificationRequired" },
|
||||
content: { key: "emailVerificationRequiredDesc" },
|
||||
acceptButtonText: { key: "learnMore" },
|
||||
type: SimpleDialogType.INFO,
|
||||
type: "info",
|
||||
});
|
||||
if (emailVerificationConfirmed) {
|
||||
this.platformUtilsService.launchUri(
|
||||
|
||||
@@ -9,6 +9,7 @@ import { AppComponent } from "./app.component";
|
||||
import { CoreModule } from "./core";
|
||||
import { OssRoutingModule } from "./oss-routing.module";
|
||||
import { OssModule } from "./oss.module";
|
||||
import { SendComponent } from "./tools/send/send.component";
|
||||
import { WildcardRoutingModule } from "./wildcard-routing.module";
|
||||
|
||||
@NgModule({
|
||||
@@ -21,6 +22,7 @@ import { WildcardRoutingModule } from "./wildcard-routing.module";
|
||||
DragDropModule,
|
||||
LayoutModule,
|
||||
OssRoutingModule,
|
||||
SendComponent,
|
||||
WildcardRoutingModule, // Needs to be last to catch all non-existing routes
|
||||
],
|
||||
declarations: [AppComponent],
|
||||
|
||||
@@ -18,6 +18,7 @@ import { MessagingService } from "@bitwarden/common/platform/abstractions/messag
|
||||
import { PlatformUtilsService } from "@bitwarden/common/platform/abstractions/platform-utils.service";
|
||||
import { StateService } from "@bitwarden/common/platform/abstractions/state.service";
|
||||
import { Utils } from "@bitwarden/common/platform/misc/utils";
|
||||
import { OrgKey } from "@bitwarden/common/platform/models/domain/symmetric-crypto-key";
|
||||
|
||||
import { BaseAcceptComponent } from "../common/base.accept.component";
|
||||
|
||||
@@ -108,16 +109,14 @@ export class AcceptOrganizationComponent extends BaseAcceptComponent {
|
||||
const request = new OrganizationUserAcceptInitRequest();
|
||||
request.token = qParams.token;
|
||||
|
||||
const [encryptedOrgShareKey, orgShareKey] = await this.cryptoService.makeShareKey();
|
||||
const [orgPublicKey, encryptedOrgPrivateKey] = await this.cryptoService.makeKeyPair(
|
||||
orgShareKey
|
||||
);
|
||||
const [encryptedOrgKey, orgKey] = await this.cryptoService.makeOrgKey<OrgKey>();
|
||||
const [orgPublicKey, encryptedOrgPrivateKey] = await this.cryptoService.makeKeyPair(orgKey);
|
||||
const collection = await this.cryptoService.encrypt(
|
||||
this.i18nService.t("defaultCollection"),
|
||||
orgShareKey
|
||||
orgKey
|
||||
);
|
||||
|
||||
request.key = encryptedOrgShareKey.encryptedString;
|
||||
request.key = encryptedOrgKey.encryptedString;
|
||||
request.keys = new OrganizationKeysRequest(
|
||||
orgPublicKey,
|
||||
encryptedOrgPrivateKey.encryptedString
|
||||
@@ -141,8 +140,8 @@ export class AcceptOrganizationComponent extends BaseAcceptComponent {
|
||||
const publicKey = Utils.fromB64ToArray(response.publicKey);
|
||||
|
||||
// RSA Encrypt user's encKey.key with organization public key
|
||||
const encKey = await this.cryptoService.getEncKey();
|
||||
const encryptedKey = await this.cryptoService.rsaEncrypt(encKey.key, publicKey.buffer);
|
||||
const userKey = await this.cryptoService.getUserKey();
|
||||
const encryptedKey = await this.cryptoService.rsaEncrypt(userKey.key, publicKey);
|
||||
|
||||
// Add reset password key to accept request
|
||||
request.resetPasswordKey = encryptedKey.encryptedString;
|
||||
|
||||
@@ -2,13 +2,13 @@ import { Component, NgZone } from "@angular/core";
|
||||
import { Router } from "@angular/router";
|
||||
|
||||
import { LockComponent as BaseLockComponent } from "@bitwarden/angular/auth/components/lock.component";
|
||||
import { DialogServiceAbstraction } from "@bitwarden/angular/services/dialog";
|
||||
import { ApiService } from "@bitwarden/common/abstractions/api.service";
|
||||
import { VaultTimeoutService } from "@bitwarden/common/abstractions/vaultTimeout/vaultTimeout.service";
|
||||
import { VaultTimeoutSettingsService } from "@bitwarden/common/abstractions/vaultTimeout/vaultTimeoutSettings.service";
|
||||
import { VaultTimeoutSettingsService } from "@bitwarden/common/abstractions/vault-timeout/vault-timeout-settings.service";
|
||||
import { VaultTimeoutService } from "@bitwarden/common/abstractions/vault-timeout/vault-timeout.service";
|
||||
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 { KeyConnectorService } from "@bitwarden/common/auth/abstractions/key-connector.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 { CryptoService } from "@bitwarden/common/platform/abstractions/crypto.service";
|
||||
import { EnvironmentService } from "@bitwarden/common/platform/abstractions/environment.service";
|
||||
import { I18nService } from "@bitwarden/common/platform/abstractions/i18n.service";
|
||||
@@ -17,6 +17,7 @@ import { MessagingService } from "@bitwarden/common/platform/abstractions/messag
|
||||
import { PlatformUtilsService } from "@bitwarden/common/platform/abstractions/platform-utils.service";
|
||||
import { StateService } from "@bitwarden/common/platform/abstractions/state.service";
|
||||
import { PasswordStrengthServiceAbstraction } from "@bitwarden/common/tools/password-strength";
|
||||
import { DialogService } from "@bitwarden/components";
|
||||
|
||||
import { RouterService } from "../core";
|
||||
|
||||
@@ -38,12 +39,13 @@ export class LockComponent extends BaseLockComponent {
|
||||
stateService: StateService,
|
||||
apiService: ApiService,
|
||||
logService: LogService,
|
||||
keyConnectorService: KeyConnectorService,
|
||||
ngZone: NgZone,
|
||||
policyApiService: PolicyApiServiceAbstraction,
|
||||
policyService: InternalPolicyService,
|
||||
passwordStrengthService: PasswordStrengthServiceAbstraction,
|
||||
dialogService: DialogServiceAbstraction
|
||||
dialogService: DialogService,
|
||||
deviceTrustCryptoService: DeviceTrustCryptoServiceAbstraction,
|
||||
userVerificationService: UserVerificationService
|
||||
) {
|
||||
super(
|
||||
router,
|
||||
@@ -57,12 +59,13 @@ export class LockComponent extends BaseLockComponent {
|
||||
stateService,
|
||||
apiService,
|
||||
logService,
|
||||
keyConnectorService,
|
||||
ngZone,
|
||||
policyApiService,
|
||||
policyService,
|
||||
passwordStrengthService,
|
||||
dialogService
|
||||
dialogService,
|
||||
deviceTrustCryptoService,
|
||||
userVerificationService
|
||||
);
|
||||
}
|
||||
|
||||
|
||||
@@ -0,0 +1,105 @@
|
||||
<div class="tw-container tw-mx-auto">
|
||||
<div
|
||||
class="tw-mx-auto tw-mt-5 tw-flex tw-max-w-lg tw-flex-col tw-items-center tw-justify-center tw-p-8"
|
||||
>
|
||||
<div class="tw-mb-6">
|
||||
<img class="logo logo-themed" alt="Bitwarden" />
|
||||
</div>
|
||||
|
||||
<ng-container *ngIf="loading">
|
||||
<p class="text-center">
|
||||
<i
|
||||
class="bwi bwi-spinner bwi-spin bwi-2x text-muted"
|
||||
title="{{ 'loading' | i18n }}"
|
||||
aria-hidden="true"
|
||||
></i>
|
||||
<span class="sr-only">{{ "loading" | i18n }}</span>
|
||||
</p>
|
||||
</ng-container>
|
||||
|
||||
<div
|
||||
*ngIf="!loading"
|
||||
class="tw-w-full tw-rounded-md tw-border tw-border-solid tw-border-secondary-300 tw-bg-background tw-p-6"
|
||||
>
|
||||
<ng-container *ngIf="data.state == State.ExistingUserUntrustedDevice">
|
||||
<h2 bitTypography="h2" class="tw-mb-6">{{ "loginInitiated" | i18n }}</h2>
|
||||
|
||||
<p bitTypography="body1" class="tw-mb-6">
|
||||
{{ "deviceApprovalRequired" | i18n }}
|
||||
</p>
|
||||
|
||||
<form [formGroup]="rememberDeviceForm">
|
||||
<bit-form-control>
|
||||
<input type="checkbox" bitCheckbox formControlName="rememberDevice" />
|
||||
<bit-label>{{ "rememberThisDevice" | i18n }} </bit-label>
|
||||
<bit-hint bitTypography="body2">{{ "uncheckIfPublicDevice" | i18n }}</bit-hint>
|
||||
</bit-form-control>
|
||||
</form>
|
||||
|
||||
<div class="tw-mb-6 tw-flex tw-flex-col tw-space-y-3">
|
||||
<button
|
||||
*ngIf="data.showApproveFromOtherDeviceBtn"
|
||||
(click)="approveFromOtherDevice()"
|
||||
bitButton
|
||||
type="button"
|
||||
buttonType="primary"
|
||||
block
|
||||
>
|
||||
{{ "approveFromYourOtherDevice" | i18n }}
|
||||
</button>
|
||||
|
||||
<button
|
||||
*ngIf="data.showReqAdminApprovalBtn"
|
||||
(click)="requestAdminApproval()"
|
||||
bitButton
|
||||
type="button"
|
||||
buttonType="secondary"
|
||||
>
|
||||
{{ "requestAdminApproval" | i18n }}
|
||||
</button>
|
||||
|
||||
<button
|
||||
*ngIf="data.showApproveWithMasterPasswordBtn"
|
||||
(click)="approveWithMasterPassword()"
|
||||
bitButton
|
||||
type="button"
|
||||
buttonType="secondary"
|
||||
block
|
||||
>
|
||||
{{ "approveWithMasterPassword" | i18n }}
|
||||
</button>
|
||||
</div>
|
||||
</ng-container>
|
||||
|
||||
<ng-container *ngIf="data.state == State.NewUser">
|
||||
<h2 bitTypography="h2" class="tw-mb-6">{{ "loggedInExclamation" | i18n }}</h2>
|
||||
|
||||
<form [formGroup]="rememberDeviceForm">
|
||||
<bit-form-control>
|
||||
<input type="checkbox" bitCheckbox formControlName="rememberDevice" />
|
||||
<bit-label>{{ "rememberThisDevice" | i18n }} </bit-label>
|
||||
<bit-hint bitTypography="body2">{{ "uncheckIfPublicDevice" | i18n }}</bit-hint>
|
||||
</bit-form-control>
|
||||
</form>
|
||||
|
||||
<button
|
||||
bitButton
|
||||
type="button"
|
||||
buttonType="primary"
|
||||
block
|
||||
class="tw-mb-6"
|
||||
[bitAction]="createUserAction"
|
||||
>
|
||||
{{ "continue" | i18n }}
|
||||
</button>
|
||||
</ng-container>
|
||||
|
||||
<hr class="tw-mb-6 tw-mt-0" />
|
||||
|
||||
<div class="tw-m-0 tw-text-sm">
|
||||
<p class="tw-mb-1">{{ "loggingInAs" | i18n }} {{ data.userEmail }}</p>
|
||||
<a [routerLink]="[]" (click)="logOut()">{{ "notYou" | i18n }}</a>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
@@ -0,0 +1,21 @@
|
||||
import { Component } from "@angular/core";
|
||||
|
||||
import { BaseLoginDecryptionOptionsComponent } from "@bitwarden/angular/auth/components/base-login-decryption-options.component";
|
||||
@Component({
|
||||
selector: "web-login-decryption-options",
|
||||
templateUrl: "login-decryption-options.component.html",
|
||||
})
|
||||
export class LoginDecryptionOptionsComponent extends BaseLoginDecryptionOptionsComponent {
|
||||
override async createUser(): Promise<void> {
|
||||
try {
|
||||
await super.createUser();
|
||||
await this.router.navigate(["/vault"]);
|
||||
} catch (error) {
|
||||
this.validationService.showError(error);
|
||||
}
|
||||
}
|
||||
|
||||
createUserAction = async (): Promise<void> => {
|
||||
return this.createUser();
|
||||
};
|
||||
}
|
||||
@@ -5,42 +5,71 @@
|
||||
>
|
||||
<div>
|
||||
<img class="logo logo-themed" alt="Bitwarden" />
|
||||
<p class="tw-mx-4 tw-mb-4 tw-mt-3 tw-text-center tw-text-xl">
|
||||
{{ "loginOrCreateNewAccount" | i18n }}
|
||||
</p>
|
||||
|
||||
<div
|
||||
class="tw-mt-3 tw-rounded-md tw-border tw-border-solid tw-border-secondary-300 tw-bg-background tw-p-6"
|
||||
>
|
||||
<h2 class="tw-mb-6 tw-text-xl tw-font-semibold">{{ "logInInitiated" | i18n }}</h2>
|
||||
<ng-container *ngIf="state == StateEnum.StandardAuthRequest">
|
||||
<p class="tw-mx-4 tw-mb-4 tw-mt-3 tw-text-center tw-text-xl">
|
||||
{{ "loginOrCreateNewAccount" | i18n }}
|
||||
</p>
|
||||
|
||||
<div class="tw-text-light">
|
||||
<p class="tw-mb-6">{{ "notificationSentDevice" | i18n }}</p>
|
||||
<div
|
||||
class="tw-mt-3 tw-rounded-md tw-border tw-border-solid tw-border-secondary-300 tw-bg-background tw-p-6"
|
||||
>
|
||||
<h2 class="tw-mb-6 tw-text-xl tw-font-semibold">{{ "loginInitiated" | i18n }}</h2>
|
||||
|
||||
<p class="tw-mb-6">
|
||||
{{ "fingerprintMatchInfo" | i18n }}
|
||||
</p>
|
||||
<div class="tw-text-light">
|
||||
<p class="tw-mb-6">{{ "notificationSentDevice" | i18n }}</p>
|
||||
|
||||
<p class="tw-mb-6">
|
||||
{{ "fingerprintMatchInfo" | i18n }}
|
||||
</p>
|
||||
</div>
|
||||
|
||||
<div class="tw-mb-6">
|
||||
<h4 class="tw-font-semibold">{{ "fingerprintPhraseHeader" | i18n }}</h4>
|
||||
<p>
|
||||
<code>{{ fingerprintPhrase }}</code>
|
||||
</p>
|
||||
</div>
|
||||
|
||||
<div class="tw-my-10" *ngIf="showResendNotification">
|
||||
<a [routerLink]="[]" disabled="true" (click)="startPasswordlessLogin()">{{
|
||||
"resendNotification" | i18n
|
||||
}}</a>
|
||||
</div>
|
||||
|
||||
<hr />
|
||||
|
||||
<div class="tw-text-light tw-mt-3">
|
||||
{{ "loginWithDeviceEnabledNote" | i18n }}
|
||||
<a routerLink="/login">{{ "viewAllLoginOptions" | i18n }}</a>
|
||||
</div>
|
||||
</div>
|
||||
</ng-container>
|
||||
<ng-container *ngIf="state == StateEnum.AdminAuthRequest">
|
||||
<div
|
||||
class="tw-mt-3 tw-rounded-md tw-border tw-border-solid tw-border-secondary-300 tw-bg-background tw-p-6"
|
||||
>
|
||||
<h2 class="tw-mb-6 tw-text-xl tw-font-semibold">{{ "adminApprovalRequested" | i18n }}</h2>
|
||||
|
||||
<div class="tw-mb-6">
|
||||
<h4 class="tw-font-semibold">{{ "fingerprintPhraseHeader" | i18n }}</h4>
|
||||
<p>
|
||||
<code>{{ fingerprintPhrase }}</code>
|
||||
</p>
|
||||
<div class="tw-text-light">
|
||||
<p class="tw-mb-6">{{ "adminApprovalRequestSentToAdmins" | i18n }}</p>
|
||||
<p class="tw-mb-6">{{ "youWillBeNotifiedOnceApproved" | i18n }}</p>
|
||||
</div>
|
||||
|
||||
<div class="tw-mb-6">
|
||||
<h4 class="tw-font-semibold">{{ "fingerprintPhraseHeader" | i18n }}</h4>
|
||||
<p>
|
||||
<code>{{ fingerprintPhrase }}</code>
|
||||
</p>
|
||||
</div>
|
||||
|
||||
<hr />
|
||||
|
||||
<div class="tw-text-light tw-mt-3">
|
||||
{{ "troubleLoggingIn" | i18n }}
|
||||
<a routerLink="/login-initiated">{{ "viewAllLoginOptions" | i18n }}</a>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div class="tw-my-10" *ngIf="showResendNotification">
|
||||
<a [routerLink]="[]" disabled="true" (click)="startPasswordlessLogin()">{{
|
||||
"resendNotification" | i18n
|
||||
}}</a>
|
||||
</div>
|
||||
|
||||
<hr />
|
||||
|
||||
<div class="tw-text-light tw-mt-3">
|
||||
{{ "loginWithDeviceEnabledNote" | i18n }}
|
||||
<a routerLink="/login">{{ "viewAllLoginOptions" | i18n }}</a>
|
||||
</div>
|
||||
</div>
|
||||
</ng-container>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
@@ -4,7 +4,9 @@ import { Router } from "@angular/router";
|
||||
import { LoginWithDeviceComponent as BaseLoginWithDeviceComponent } from "@bitwarden/angular/auth/components/login-with-device.component";
|
||||
import { AnonymousHubService } from "@bitwarden/common/abstractions/anonymousHub.service";
|
||||
import { ApiService } from "@bitwarden/common/abstractions/api.service";
|
||||
import { AuthRequestCryptoServiceAbstraction } from "@bitwarden/common/auth/abstractions/auth-request-crypto.service.abstraction";
|
||||
import { AuthService } from "@bitwarden/common/auth/abstractions/auth.service";
|
||||
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 { CryptoFunctionService } from "@bitwarden/common/platform/abstractions/crypto-function.service";
|
||||
@@ -41,7 +43,9 @@ export class LoginWithDeviceComponent
|
||||
anonymousHubService: AnonymousHubService,
|
||||
validationService: ValidationService,
|
||||
stateService: StateService,
|
||||
loginService: LoginService
|
||||
loginService: LoginService,
|
||||
deviceTrustCryptoService: DeviceTrustCryptoServiceAbstraction,
|
||||
authReqCryptoService: AuthRequestCryptoServiceAbstraction
|
||||
) {
|
||||
super(
|
||||
router,
|
||||
@@ -58,7 +62,9 @@ export class LoginWithDeviceComponent
|
||||
anonymousHubService,
|
||||
validationService,
|
||||
stateService,
|
||||
loginService
|
||||
loginService,
|
||||
deviceTrustCryptoService,
|
||||
authReqCryptoService
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -6,7 +6,6 @@ import { first } from "rxjs/operators";
|
||||
|
||||
import { LoginComponent as BaseLoginComponent } from "@bitwarden/angular/auth/components/login.component";
|
||||
import { FormValidationErrorsService } from "@bitwarden/angular/platform/abstractions/form-validation-errors.service";
|
||||
import { DevicesApiServiceAbstraction } from "@bitwarden/common/abstractions/devices/devices-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 { PolicyData } from "@bitwarden/common/admin-console/models/data/policy.data";
|
||||
@@ -14,6 +13,7 @@ import { MasterPasswordPolicyOptions } from "@bitwarden/common/admin-console/mod
|
||||
import { Policy } from "@bitwarden/common/admin-console/models/domain/policy";
|
||||
import { PolicyResponse } from "@bitwarden/common/admin-console/models/response/policy.response";
|
||||
import { AuthService } from "@bitwarden/common/auth/abstractions/auth.service";
|
||||
import { DevicesApiServiceAbstraction } from "@bitwarden/common/auth/abstractions/devices-api.service.abstraction";
|
||||
import { LoginService } from "@bitwarden/common/auth/abstractions/login.service";
|
||||
import { ListResponse } from "@bitwarden/common/models/response/list.response";
|
||||
import { AppIdService } from "@bitwarden/common/platform/abstractions/app-id.service";
|
||||
|
||||
@@ -4,12 +4,13 @@ import { CheckboxModule } from "@bitwarden/components";
|
||||
|
||||
import { SharedModule } from "../../../app/shared";
|
||||
|
||||
import { LoginDecryptionOptionsComponent } from "./login-decryption-options/login-decryption-options.component";
|
||||
import { LoginWithDeviceComponent } from "./login-with-device.component";
|
||||
import { LoginComponent } from "./login.component";
|
||||
|
||||
@NgModule({
|
||||
imports: [SharedModule, CheckboxModule],
|
||||
declarations: [LoginComponent, LoginWithDeviceComponent],
|
||||
exports: [LoginComponent, LoginWithDeviceComponent],
|
||||
declarations: [LoginComponent, LoginWithDeviceComponent, LoginDecryptionOptionsComponent],
|
||||
exports: [LoginComponent, LoginWithDeviceComponent, LoginDecryptionOptionsComponent],
|
||||
})
|
||||
export class LoginModule {}
|
||||
|
||||
@@ -35,7 +35,7 @@ export class RecoverTwoFactorComponent {
|
||||
request.recoveryCode = this.recoveryCode.replace(/\s/g, "").toLowerCase();
|
||||
request.email = this.email.trim().toLowerCase();
|
||||
const key = await this.authService.makePreloginKey(this.masterPassword, request.email);
|
||||
request.masterPasswordHash = await this.cryptoService.hashPassword(this.masterPassword, key);
|
||||
request.masterPasswordHash = await this.cryptoService.hashMasterKey(this.masterPassword, key);
|
||||
this.formPromise = this.apiService.postTwoFactorRecover(request);
|
||||
await this.formPromise;
|
||||
this.platformUtilsService.showToast(
|
||||
|
||||
@@ -123,8 +123,7 @@
|
||||
</bit-label>
|
||||
</div>
|
||||
|
||||
<hr />
|
||||
<div class="tw-flex tw-space-x-2 tw-pt-2">
|
||||
<div class="tw-space-x-2 tw-pt-2">
|
||||
<ng-container *ngIf="!accountCreated">
|
||||
<button
|
||||
[block]="true"
|
||||
@@ -135,10 +134,6 @@
|
||||
>
|
||||
{{ "createAccount" | i18n }}
|
||||
</button>
|
||||
<a bitButton [block]="true" buttonType="secondary" routerLink="/login">
|
||||
<i class="bwi bwi-sign-in tw-mr-2"></i>
|
||||
{{ "logIn" | i18n }}
|
||||
</a>
|
||||
</ng-container>
|
||||
<ng-container *ngIf="accountCreated">
|
||||
<button
|
||||
@@ -152,6 +147,10 @@
|
||||
</button>
|
||||
</ng-container>
|
||||
</div>
|
||||
<p class="tw-m-0 tw-mt-5 tw-text-sm">
|
||||
{{ "alreadyHaveAccount" | i18n }}
|
||||
<a routerLink="/login">{{ "logIn" | i18n }}</a>
|
||||
</p>
|
||||
<bit-error-summary *ngIf="showErrorSummary" [formGroup]="formGroup"></bit-error-summary>
|
||||
</div>
|
||||
</form>
|
||||
|
||||
@@ -4,7 +4,6 @@ import { Router } from "@angular/router";
|
||||
|
||||
import { RegisterComponent as BaseRegisterComponent } from "@bitwarden/angular/components/register.component";
|
||||
import { FormValidationErrorsService } from "@bitwarden/angular/platform/abstractions/form-validation-errors.service";
|
||||
import { DialogServiceAbstraction } from "@bitwarden/angular/services/dialog";
|
||||
import { ApiService } from "@bitwarden/common/abstractions/api.service";
|
||||
import { AuditService } from "@bitwarden/common/abstractions/audit.service";
|
||||
import { PolicyService } from "@bitwarden/common/admin-console/abstractions/policy/policy.service.abstraction";
|
||||
@@ -18,6 +17,7 @@ import { LogService } from "@bitwarden/common/platform/abstractions/log.service"
|
||||
import { PlatformUtilsService } from "@bitwarden/common/platform/abstractions/platform-utils.service";
|
||||
import { StateService } from "@bitwarden/common/platform/abstractions/state.service";
|
||||
import { PasswordGenerationServiceAbstraction } from "@bitwarden/common/tools/generator/password";
|
||||
import { DialogService } from "@bitwarden/components";
|
||||
|
||||
@Component({
|
||||
selector: "app-register-form",
|
||||
@@ -46,7 +46,7 @@ export class RegisterFormComponent extends BaseRegisterComponent {
|
||||
environmentService: EnvironmentService,
|
||||
logService: LogService,
|
||||
auditService: AuditService,
|
||||
dialogService: DialogServiceAbstraction
|
||||
dialogService: DialogService
|
||||
) {
|
||||
super(
|
||||
formValidationErrorService,
|
||||
|
||||
@@ -2,7 +2,6 @@ import { Component } from "@angular/core";
|
||||
import { ActivatedRoute, Router } from "@angular/router";
|
||||
|
||||
import { SetPasswordComponent as BaseSetPasswordComponent } from "@bitwarden/angular/components/set-password.component";
|
||||
import { DialogServiceAbstraction } from "@bitwarden/angular/services/dialog";
|
||||
import { ApiService } from "@bitwarden/common/abstractions/api.service";
|
||||
import { OrganizationUserService } from "@bitwarden/common/abstractions/organization-user/organization-user.service";
|
||||
import { OrganizationApiServiceAbstraction } from "@bitwarden/common/admin-console/abstractions/organization/organization-api.service.abstraction";
|
||||
@@ -15,6 +14,7 @@ import { PlatformUtilsService } from "@bitwarden/common/platform/abstractions/pl
|
||||
import { StateService } from "@bitwarden/common/platform/abstractions/state.service";
|
||||
import { PasswordGenerationServiceAbstraction } from "@bitwarden/common/tools/generator/password";
|
||||
import { SyncService } from "@bitwarden/common/vault/abstractions/sync/sync.service.abstraction";
|
||||
import { DialogService } from "@bitwarden/components";
|
||||
|
||||
@Component({
|
||||
selector: "app-set-password",
|
||||
@@ -36,7 +36,7 @@ export class SetPasswordComponent extends BaseSetPasswordComponent {
|
||||
stateService: StateService,
|
||||
organizationApiService: OrganizationApiServiceAbstraction,
|
||||
organizationUserService: OrganizationUserService,
|
||||
dialogService: DialogServiceAbstraction
|
||||
dialogService: DialogService
|
||||
) {
|
||||
super(
|
||||
i18nService,
|
||||
|
||||
@@ -89,12 +89,12 @@
|
||||
<input
|
||||
class="form-check-input"
|
||||
type="checkbox"
|
||||
id="rotateEncKey"
|
||||
name="RotateEncKey"
|
||||
[(ngModel)]="rotateEncKey"
|
||||
(change)="rotateEncKeyClicked()"
|
||||
id="rotateUserKey"
|
||||
name="RotateUserKey"
|
||||
[(ngModel)]="rotateUserKey"
|
||||
(change)="rotateUserKeyClicked()"
|
||||
/>
|
||||
<label class="form-check-label" for="rotateEncKey">
|
||||
<label class="form-check-label" for="rotateUserKey">
|
||||
{{ "rotateAccountEncKey" | i18n }}
|
||||
</label>
|
||||
<a
|
||||
@@ -3,7 +3,6 @@ import { Router } from "@angular/router";
|
||||
import { firstValueFrom } from "rxjs";
|
||||
|
||||
import { ChangePasswordComponent as BaseChangePasswordComponent } from "@bitwarden/angular/auth/components/change-password.component";
|
||||
import { DialogServiceAbstraction, SimpleDialogType } from "@bitwarden/angular/services/dialog";
|
||||
import { ApiService } from "@bitwarden/common/abstractions/api.service";
|
||||
import { AuditService } from "@bitwarden/common/abstractions/audit.service";
|
||||
import { OrganizationUserService } from "@bitwarden/common/abstractions/organization-user/organization-user.service";
|
||||
@@ -11,7 +10,9 @@ import { OrganizationUserResetPasswordEnrollmentRequest } from "@bitwarden/commo
|
||||
import { OrganizationApiServiceAbstraction } from "@bitwarden/common/admin-console/abstractions/organization/organization-api.service.abstraction";
|
||||
import { OrganizationService } from "@bitwarden/common/admin-console/abstractions/organization/organization.service.abstraction";
|
||||
import { PolicyService } from "@bitwarden/common/admin-console/abstractions/policy/policy.service.abstraction";
|
||||
import { DeviceTrustCryptoServiceAbstraction } from "@bitwarden/common/auth/abstractions/device-trust-crypto.service.abstraction";
|
||||
import { KeyConnectorService } from "@bitwarden/common/auth/abstractions/key-connector.service";
|
||||
import { UserVerificationService } from "@bitwarden/common/auth/abstractions/user-verification/user-verification.service.abstraction";
|
||||
import { EmergencyAccessStatusType } from "@bitwarden/common/auth/enums/emergency-access-status-type";
|
||||
import { EmergencyAccessUpdateRequest } from "@bitwarden/common/auth/models/request/emergency-access-update.request";
|
||||
import { PasswordRequest } from "@bitwarden/common/auth/models/request/password.request";
|
||||
@@ -23,7 +24,11 @@ import { PlatformUtilsService } from "@bitwarden/common/platform/abstractions/pl
|
||||
import { StateService } from "@bitwarden/common/platform/abstractions/state.service";
|
||||
import { Utils } from "@bitwarden/common/platform/misc/utils";
|
||||
import { EncString } from "@bitwarden/common/platform/models/domain/enc-string";
|
||||
import { SymmetricCryptoKey } from "@bitwarden/common/platform/models/domain/symmetric-crypto-key";
|
||||
import {
|
||||
MasterKey,
|
||||
SymmetricCryptoKey,
|
||||
UserKey,
|
||||
} from "@bitwarden/common/platform/models/domain/symmetric-crypto-key";
|
||||
import { PasswordGenerationServiceAbstraction } from "@bitwarden/common/tools/generator/password";
|
||||
import { SendWithIdRequest } from "@bitwarden/common/tools/send/models/request/send-with-id.request";
|
||||
import { SendService } from "@bitwarden/common/tools/send/services/send.service.abstraction";
|
||||
@@ -32,13 +37,14 @@ import { FolderService } from "@bitwarden/common/vault/abstractions/folder/folde
|
||||
import { SyncService } from "@bitwarden/common/vault/abstractions/sync/sync.service.abstraction";
|
||||
import { CipherWithIdRequest } from "@bitwarden/common/vault/models/request/cipher-with-id.request";
|
||||
import { FolderWithIdRequest } from "@bitwarden/common/vault/models/request/folder-with-id.request";
|
||||
import { DialogService } from "@bitwarden/components";
|
||||
|
||||
@Component({
|
||||
selector: "app-change-password",
|
||||
templateUrl: "change-password.component.html",
|
||||
})
|
||||
export class ChangePasswordComponent extends BaseChangePasswordComponent {
|
||||
rotateEncKey = false;
|
||||
rotateUserKey = false;
|
||||
currentMasterPassword: string;
|
||||
masterPasswordHint: string;
|
||||
checkForBreaches = true;
|
||||
@@ -63,7 +69,9 @@ export class ChangePasswordComponent extends BaseChangePasswordComponent {
|
||||
private router: Router,
|
||||
private organizationApiService: OrganizationApiServiceAbstraction,
|
||||
private organizationUserService: OrganizationUserService,
|
||||
dialogService: DialogServiceAbstraction
|
||||
dialogService: DialogService,
|
||||
private userVerificationService: UserVerificationService,
|
||||
private deviceTrustCryptoService: DeviceTrustCryptoServiceAbstraction
|
||||
) {
|
||||
super(
|
||||
i18nService,
|
||||
@@ -78,7 +86,7 @@ export class ChangePasswordComponent extends BaseChangePasswordComponent {
|
||||
}
|
||||
|
||||
async ngOnInit() {
|
||||
if (await this.keyConnectorService.getUsesKeyConnector()) {
|
||||
if (!(await this.userVerificationService.hasMasterPassword())) {
|
||||
this.router.navigate(["/settings/security/two-factor"]);
|
||||
}
|
||||
|
||||
@@ -88,8 +96,8 @@ export class ChangePasswordComponent extends BaseChangePasswordComponent {
|
||||
this.characterMinimumMessage = this.i18nService.t("characterMinimum", this.minimumLength);
|
||||
}
|
||||
|
||||
async rotateEncKeyClicked() {
|
||||
if (this.rotateEncKey) {
|
||||
async rotateUserKeyClicked() {
|
||||
if (this.rotateUserKey) {
|
||||
const ciphers = await this.cipherService.getAllDecrypted();
|
||||
let hasOldAttachments = false;
|
||||
if (ciphers != null) {
|
||||
@@ -107,7 +115,7 @@ export class ChangePasswordComponent extends BaseChangePasswordComponent {
|
||||
content: { key: "oldAttachmentsNeedFixDesc" },
|
||||
acceptButtonText: { key: "learnMore" },
|
||||
cancelButtonText: { key: "close" },
|
||||
type: SimpleDialogType.WARNING,
|
||||
type: "warning",
|
||||
});
|
||||
|
||||
if (learnMore) {
|
||||
@@ -115,7 +123,7 @@ export class ChangePasswordComponent extends BaseChangePasswordComponent {
|
||||
"https://bitwarden.com/help/attachments/#add-storage-space"
|
||||
);
|
||||
}
|
||||
this.rotateEncKey = false;
|
||||
this.rotateUserKey = false;
|
||||
return;
|
||||
}
|
||||
|
||||
@@ -127,18 +135,18 @@ export class ChangePasswordComponent extends BaseChangePasswordComponent {
|
||||
this.i18nService.t("updateEncryptionKeyExportWarning") +
|
||||
" " +
|
||||
this.i18nService.t("rotateEncKeyConfirmation"),
|
||||
type: SimpleDialogType.WARNING,
|
||||
type: "warning",
|
||||
});
|
||||
|
||||
if (!result) {
|
||||
this.rotateEncKey = false;
|
||||
this.rotateUserKey = false;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
async submit() {
|
||||
const hasEncKey = await this.cryptoService.hasEncKey();
|
||||
if (!hasEncKey) {
|
||||
const hasUserKey = await this.cryptoService.hasUserKey();
|
||||
if (!hasUserKey) {
|
||||
this.platformUtilsService.showToast("error", null, this.i18nService.t("updateKey"));
|
||||
return;
|
||||
}
|
||||
@@ -170,7 +178,7 @@ export class ChangePasswordComponent extends BaseChangePasswordComponent {
|
||||
return false;
|
||||
}
|
||||
|
||||
if (this.rotateEncKey) {
|
||||
if (this.rotateUserKey) {
|
||||
await this.syncService.fullSync(true);
|
||||
}
|
||||
|
||||
@@ -179,22 +187,23 @@ export class ChangePasswordComponent extends BaseChangePasswordComponent {
|
||||
|
||||
async performSubmitActions(
|
||||
newMasterPasswordHash: string,
|
||||
newKey: SymmetricCryptoKey,
|
||||
newEncKey: [SymmetricCryptoKey, EncString]
|
||||
newMasterKey: MasterKey,
|
||||
newUserKey: [UserKey, EncString]
|
||||
) {
|
||||
const masterKey = await this.cryptoService.getOrDeriveMasterKey(this.currentMasterPassword);
|
||||
const request = new PasswordRequest();
|
||||
request.masterPasswordHash = await this.cryptoService.hashPassword(
|
||||
request.masterPasswordHash = await this.cryptoService.hashMasterKey(
|
||||
this.currentMasterPassword,
|
||||
null
|
||||
masterKey
|
||||
);
|
||||
request.masterPasswordHint = this.masterPasswordHint;
|
||||
request.newMasterPasswordHash = newMasterPasswordHash;
|
||||
request.key = newEncKey[1].encryptedString;
|
||||
request.key = newUserKey[1].encryptedString;
|
||||
|
||||
try {
|
||||
if (this.rotateEncKey) {
|
||||
if (this.rotateUserKey) {
|
||||
this.formPromise = this.apiService.postPassword(request).then(() => {
|
||||
return this.updateKey(newKey, request.newMasterPasswordHash);
|
||||
return this.updateKey(newMasterKey, request.newMasterPasswordHash);
|
||||
});
|
||||
} else {
|
||||
this.formPromise = this.apiService.postPassword(request);
|
||||
@@ -213,16 +222,16 @@ export class ChangePasswordComponent extends BaseChangePasswordComponent {
|
||||
}
|
||||
}
|
||||
|
||||
private async updateKey(key: SymmetricCryptoKey, masterPasswordHash: string) {
|
||||
const encKey = await this.cryptoService.makeEncKey(key);
|
||||
const privateKey = await this.cryptoService.getPrivateKey();
|
||||
private async updateKey(masterKey: MasterKey, masterPasswordHash: string) {
|
||||
const [newUserKey, masterKeyEncUserKey] = await this.cryptoService.makeUserKey(masterKey);
|
||||
const userPrivateKey = await this.cryptoService.getPrivateKey();
|
||||
let encPrivateKey: EncString = null;
|
||||
if (privateKey != null) {
|
||||
encPrivateKey = await this.cryptoService.encrypt(privateKey, encKey[0]);
|
||||
if (userPrivateKey != null) {
|
||||
encPrivateKey = await this.cryptoService.encrypt(userPrivateKey, newUserKey);
|
||||
}
|
||||
const request = new UpdateKeyRequest();
|
||||
request.privateKey = encPrivateKey != null ? encPrivateKey.encryptedString : null;
|
||||
request.key = encKey[1].encryptedString;
|
||||
request.key = masterKeyEncUserKey.encryptedString;
|
||||
request.masterPasswordHash = masterPasswordHash;
|
||||
|
||||
const folders = await firstValueFrom(this.folderService.folderViews$);
|
||||
@@ -230,7 +239,7 @@ export class ChangePasswordComponent extends BaseChangePasswordComponent {
|
||||
if (folders[i].id == null) {
|
||||
continue;
|
||||
}
|
||||
const folder = await this.folderService.encrypt(folders[i], encKey[0]);
|
||||
const folder = await this.folderService.encrypt(folders[i], newUserKey);
|
||||
request.folders.push(new FolderWithIdRequest(folder));
|
||||
}
|
||||
|
||||
@@ -240,24 +249,26 @@ export class ChangePasswordComponent extends BaseChangePasswordComponent {
|
||||
continue;
|
||||
}
|
||||
|
||||
const cipher = await this.cipherService.encrypt(ciphers[i], encKey[0]);
|
||||
const cipher = await this.cipherService.encrypt(ciphers[i], newUserKey);
|
||||
request.ciphers.push(new CipherWithIdRequest(cipher));
|
||||
}
|
||||
|
||||
const sends = await firstValueFrom(this.sendService.sends$);
|
||||
await Promise.all(
|
||||
sends.map(async (send) => {
|
||||
const cryptoKey = await this.cryptoService.decryptToBytes(send.key, null);
|
||||
send.key = (await this.cryptoService.encrypt(cryptoKey, encKey[0])) ?? send.key;
|
||||
const sendKey = await this.cryptoService.decryptToBytes(send.key, null);
|
||||
send.key = (await this.cryptoService.encrypt(sendKey, newUserKey)) ?? send.key;
|
||||
request.sends.push(new SendWithIdRequest(send));
|
||||
})
|
||||
);
|
||||
|
||||
await this.deviceTrustCryptoService.rotateDevicesTrust(newUserKey, masterPasswordHash);
|
||||
|
||||
await this.apiService.postAccountKey(request);
|
||||
|
||||
await this.updateEmergencyAccesses(encKey[0]);
|
||||
await this.updateEmergencyAccesses(newUserKey);
|
||||
|
||||
await this.updateAllResetPasswordKeys(encKey[0], masterPasswordHash);
|
||||
await this.updateAllResetPasswordKeys(newUserKey, masterPasswordHash);
|
||||
}
|
||||
|
||||
private async updateEmergencyAccesses(encKey: SymmetricCryptoKey) {
|
||||
@@ -274,7 +285,7 @@ export class ChangePasswordComponent extends BaseChangePasswordComponent {
|
||||
const publicKeyResponse = await this.apiService.getUserPublicKey(details.granteeId);
|
||||
const publicKey = Utils.fromB64ToArray(publicKeyResponse.publicKey);
|
||||
|
||||
const encryptedKey = await this.cryptoService.rsaEncrypt(encKey.key, publicKey.buffer);
|
||||
const encryptedKey = await this.cryptoService.rsaEncrypt(encKey.key, publicKey);
|
||||
|
||||
const updateRequest = new EmergencyAccessUpdateRequest();
|
||||
updateRequest.type = details.type;
|
||||
@@ -285,7 +296,7 @@ export class ChangePasswordComponent extends BaseChangePasswordComponent {
|
||||
}
|
||||
}
|
||||
|
||||
private async updateAllResetPasswordKeys(encKey: SymmetricCryptoKey, masterPasswordHash: string) {
|
||||
private async updateAllResetPasswordKeys(userKey: UserKey, masterPasswordHash: string) {
|
||||
const orgs = await this.organizationService.getAll();
|
||||
|
||||
for (const org of orgs) {
|
||||
@@ -299,7 +310,7 @@ export class ChangePasswordComponent extends BaseChangePasswordComponent {
|
||||
const publicKey = Utils.fromB64ToArray(response?.publicKey);
|
||||
|
||||
// Re-enroll - encrypt user's encKey.key with organization public key
|
||||
const encryptedKey = await this.cryptoService.rsaEncrypt(encKey.key, publicKey.buffer);
|
||||
const encryptedKey = await this.cryptoService.rsaEncrypt(userKey.key, publicKey);
|
||||
|
||||
// Create/Execute request
|
||||
const request = new OrganizationUserResetPasswordEnrollmentRequest();
|
||||
@@ -1,6 +1,5 @@
|
||||
import { Component } from "@angular/core";
|
||||
|
||||
import { DialogServiceAbstraction } from "@bitwarden/angular/services/dialog";
|
||||
import { AttachmentsComponent as BaseAttachmentsComponent } from "@bitwarden/angular/vault/components/attachments.component";
|
||||
import { ApiService } from "@bitwarden/common/abstractions/api.service";
|
||||
import { CryptoService } from "@bitwarden/common/platform/abstractions/crypto.service";
|
||||
@@ -11,6 +10,7 @@ import { PlatformUtilsService } from "@bitwarden/common/platform/abstractions/pl
|
||||
import { StateService } from "@bitwarden/common/platform/abstractions/state.service";
|
||||
import { CipherService } from "@bitwarden/common/vault/abstractions/cipher.service";
|
||||
import { AttachmentView } from "@bitwarden/common/vault/models/view/attachment.view";
|
||||
import { DialogService } from "@bitwarden/components";
|
||||
|
||||
@Component({
|
||||
selector: "emergency-access-attachments",
|
||||
@@ -29,7 +29,7 @@ export class EmergencyAccessAttachmentsComponent extends BaseAttachmentsComponen
|
||||
apiService: ApiService,
|
||||
logService: LogService,
|
||||
fileDownloadService: FileDownloadService,
|
||||
dialogService: DialogServiceAbstraction
|
||||
dialogService: DialogService
|
||||
) {
|
||||
super(
|
||||
cipherService,
|
||||
|
||||
@@ -33,7 +33,7 @@ export class EmergencyAccessConfirmComponent implements OnInit {
|
||||
const publicKeyResponse = await this.apiService.getUserPublicKey(this.userId);
|
||||
if (publicKeyResponse != null) {
|
||||
const publicKey = Utils.fromB64ToArray(publicKeyResponse.publicKey);
|
||||
const fingerprint = await this.cryptoService.getFingerprint(this.userId, publicKey.buffer);
|
||||
const fingerprint = await this.cryptoService.getFingerprint(this.userId, publicKey);
|
||||
if (fingerprint != null) {
|
||||
this.fingerprint = fingerprint.join("-");
|
||||
}
|
||||
|
||||
@@ -2,7 +2,6 @@ import { Component, EventEmitter, Input, OnDestroy, OnInit, Output } from "@angu
|
||||
import { takeUntil } from "rxjs";
|
||||
|
||||
import { ChangePasswordComponent } from "@bitwarden/angular/auth/components/change-password.component";
|
||||
import { DialogServiceAbstraction } from "@bitwarden/angular/services/dialog";
|
||||
import { ApiService } from "@bitwarden/common/abstractions/api.service";
|
||||
import { PolicyService } from "@bitwarden/common/admin-console/abstractions/policy/policy.service.abstraction";
|
||||
import { PolicyData } from "@bitwarden/common/admin-console/models/data/policy.data";
|
||||
@@ -17,8 +16,12 @@ import { LogService } from "@bitwarden/common/platform/abstractions/log.service"
|
||||
import { MessagingService } from "@bitwarden/common/platform/abstractions/messaging.service";
|
||||
import { PlatformUtilsService } from "@bitwarden/common/platform/abstractions/platform-utils.service";
|
||||
import { StateService } from "@bitwarden/common/platform/abstractions/state.service";
|
||||
import { SymmetricCryptoKey } from "@bitwarden/common/platform/models/domain/symmetric-crypto-key";
|
||||
import {
|
||||
SymmetricCryptoKey,
|
||||
UserKey,
|
||||
} from "@bitwarden/common/platform/models/domain/symmetric-crypto-key";
|
||||
import { PasswordGenerationServiceAbstraction } from "@bitwarden/common/tools/generator/password";
|
||||
import { DialogService } from "@bitwarden/components";
|
||||
|
||||
@Component({
|
||||
selector: "emergency-access-takeover",
|
||||
@@ -48,7 +51,7 @@ export class EmergencyAccessTakeoverComponent
|
||||
policyService: PolicyService,
|
||||
private apiService: ApiService,
|
||||
private logService: LogService,
|
||||
dialogService: DialogServiceAbstraction
|
||||
dialogService: DialogService
|
||||
) {
|
||||
super(
|
||||
i18nService,
|
||||
@@ -91,9 +94,9 @@ export class EmergencyAccessTakeoverComponent
|
||||
);
|
||||
|
||||
const oldKeyBuffer = await this.cryptoService.rsaDecrypt(takeoverResponse.keyEncrypted);
|
||||
const oldEncKey = new SymmetricCryptoKey(oldKeyBuffer);
|
||||
const oldUserKey = new SymmetricCryptoKey(oldKeyBuffer) as UserKey;
|
||||
|
||||
if (oldEncKey == null) {
|
||||
if (oldUserKey == null) {
|
||||
this.platformUtilsService.showToast(
|
||||
"error",
|
||||
this.i18nService.t("errorOccurred"),
|
||||
@@ -102,7 +105,7 @@ export class EmergencyAccessTakeoverComponent
|
||||
return;
|
||||
}
|
||||
|
||||
const key = await this.cryptoService.makeKey(
|
||||
const masterKey = await this.cryptoService.makeMasterKey(
|
||||
this.masterPassword,
|
||||
this.email,
|
||||
takeoverResponse.kdf,
|
||||
@@ -112,12 +115,12 @@ export class EmergencyAccessTakeoverComponent
|
||||
takeoverResponse.kdfParallelism
|
||||
)
|
||||
);
|
||||
const masterPasswordHash = await this.cryptoService.hashPassword(this.masterPassword, key);
|
||||
const masterKeyHash = await this.cryptoService.hashMasterKey(this.masterPassword, masterKey);
|
||||
|
||||
const encKey = await this.cryptoService.remakeEncKey(key, oldEncKey);
|
||||
const encKey = await this.cryptoService.encryptUserKeyWithMasterKey(masterKey, oldUserKey);
|
||||
|
||||
const request = new EmergencyAccessPasswordRequest();
|
||||
request.newMasterPasswordHash = masterPasswordHash;
|
||||
request.newMasterPasswordHash = masterKeyHash;
|
||||
request.key = encKey[1].encryptedString;
|
||||
|
||||
this.apiService.postEmergencyAccessPassword(this.emergencyAccessId, request);
|
||||
|
||||
@@ -5,7 +5,10 @@ import { ModalService } from "@bitwarden/angular/services/modal.service";
|
||||
import { ApiService } from "@bitwarden/common/abstractions/api.service";
|
||||
import { EmergencyAccessViewResponse } from "@bitwarden/common/auth/models/response/emergency-access.response";
|
||||
import { CryptoService } from "@bitwarden/common/platform/abstractions/crypto.service";
|
||||
import { SymmetricCryptoKey } from "@bitwarden/common/platform/models/domain/symmetric-crypto-key";
|
||||
import {
|
||||
SymmetricCryptoKey,
|
||||
UserKey,
|
||||
} from "@bitwarden/common/platform/models/domain/symmetric-crypto-key";
|
||||
import { CipherService } from "@bitwarden/common/vault/abstractions/cipher.service";
|
||||
import { CipherData } from "@bitwarden/common/vault/models/data/cipher.data";
|
||||
import { Cipher } from "@bitwarden/common/vault/models/domain/cipher";
|
||||
@@ -87,13 +90,13 @@ export class EmergencyAccessViewComponent implements OnInit {
|
||||
|
||||
const decCiphers: CipherView[] = [];
|
||||
const oldKeyBuffer = await this.cryptoService.rsaDecrypt(response.keyEncrypted);
|
||||
const oldEncKey = new SymmetricCryptoKey(oldKeyBuffer);
|
||||
const oldUserKey = new SymmetricCryptoKey(oldKeyBuffer) as UserKey;
|
||||
|
||||
const promises: any[] = [];
|
||||
ciphers.forEach((cipherResponse) => {
|
||||
const cipherData = new CipherData(cipherResponse);
|
||||
const cipher = new Cipher(cipherData);
|
||||
promises.push(cipher.decrypt(oldEncKey).then((c) => decCiphers.push(c)));
|
||||
promises.push(cipher.decrypt(oldUserKey).then((c) => decCiphers.push(c)));
|
||||
});
|
||||
|
||||
await Promise.all(promises);
|
||||
|
||||
@@ -1,7 +1,6 @@
|
||||
import { Component, OnInit, ViewChild, ViewContainerRef } from "@angular/core";
|
||||
|
||||
import { UserNamePipe } from "@bitwarden/angular/pipes/user-name.pipe";
|
||||
import { DialogServiceAbstraction, SimpleDialogType } from "@bitwarden/angular/services/dialog";
|
||||
import { ModalService } from "@bitwarden/angular/services/modal.service";
|
||||
import { ApiService } from "@bitwarden/common/abstractions/api.service";
|
||||
import { OrganizationService } from "@bitwarden/common/admin-console/abstractions/organization/organization.service.abstraction";
|
||||
@@ -19,6 +18,7 @@ import { MessagingService } from "@bitwarden/common/platform/abstractions/messag
|
||||
import { PlatformUtilsService } from "@bitwarden/common/platform/abstractions/platform-utils.service";
|
||||
import { StateService } from "@bitwarden/common/platform/abstractions/state.service";
|
||||
import { Utils } from "@bitwarden/common/platform/misc/utils";
|
||||
import { DialogService } from "@bitwarden/components";
|
||||
|
||||
import { EmergencyAccessAddEditComponent } from "./emergency-access-add-edit.component";
|
||||
import { EmergencyAccessConfirmComponent } from "./emergency-access-confirm.component";
|
||||
@@ -56,7 +56,7 @@ export class EmergencyAccessComponent implements OnInit {
|
||||
private logService: LogService,
|
||||
private stateService: StateService,
|
||||
private organizationService: OrganizationService,
|
||||
protected dialogService: DialogServiceAbstraction
|
||||
protected dialogService: DialogService
|
||||
) {}
|
||||
|
||||
async ngOnInit() {
|
||||
@@ -174,7 +174,7 @@ export class EmergencyAccessComponent implements OnInit {
|
||||
const confirmed = await this.dialogService.openSimpleDialog({
|
||||
title: this.userNamePipe.transform(details),
|
||||
content: { key: "removeUserConfirmation" },
|
||||
type: SimpleDialogType.WARNING,
|
||||
type: "warning",
|
||||
});
|
||||
|
||||
if (!confirmed) {
|
||||
@@ -207,7 +207,7 @@ export class EmergencyAccessComponent implements OnInit {
|
||||
placeholders: [details.waitTimeDays.toString()],
|
||||
},
|
||||
acceptButtonText: { key: "requestAccess" },
|
||||
type: SimpleDialogType.WARNING,
|
||||
type: "warning",
|
||||
});
|
||||
|
||||
if (!confirmed) {
|
||||
@@ -236,7 +236,7 @@ export class EmergencyAccessComponent implements OnInit {
|
||||
placeholders: [this.userNamePipe.transform(details), type],
|
||||
},
|
||||
acceptButtonText: { key: "approve" },
|
||||
type: SimpleDialogType.WARNING,
|
||||
type: "warning",
|
||||
});
|
||||
|
||||
if (!confirmed) {
|
||||
@@ -300,22 +300,25 @@ export class EmergencyAccessComponent implements OnInit {
|
||||
}
|
||||
}
|
||||
|
||||
// Encrypt the master password hash using the grantees public key, and send it to bitwarden for escrow.
|
||||
// Encrypt the user key with the grantees public key, and send it to bitwarden for escrow.
|
||||
private async doConfirmation(details: EmergencyAccessGranteeDetailsResponse) {
|
||||
const encKey = await this.cryptoService.getEncKey();
|
||||
const userKey = await this.cryptoService.getUserKey();
|
||||
if (!userKey) {
|
||||
throw new Error("No user key found");
|
||||
}
|
||||
const publicKeyResponse = await this.apiService.getUserPublicKey(details.granteeId);
|
||||
const publicKey = Utils.fromB64ToArray(publicKeyResponse.publicKey);
|
||||
|
||||
try {
|
||||
this.logService.debug(
|
||||
"User's fingerprint: " +
|
||||
(await this.cryptoService.getFingerprint(details.granteeId, publicKey.buffer)).join("-")
|
||||
(await this.cryptoService.getFingerprint(details.granteeId, publicKey)).join("-")
|
||||
);
|
||||
} catch {
|
||||
// Ignore errors since it's just a debug message
|
||||
}
|
||||
|
||||
const encryptedKey = await this.cryptoService.rsaEncrypt(encKey.key, publicKey.buffer);
|
||||
const encryptedKey = await this.cryptoService.rsaEncrypt(userKey.key, publicKey);
|
||||
const request = new EmergencyAccessConfirmRequest();
|
||||
request.key = encryptedKey.encryptedString;
|
||||
await this.apiService.postEmergencyAccessConfirm(details.id, request);
|
||||
|
||||
@@ -1,6 +1,5 @@
|
||||
import { Component } from "@angular/core";
|
||||
|
||||
import { DialogServiceAbstraction } from "@bitwarden/angular/services/dialog";
|
||||
import { AuditService } from "@bitwarden/common/abstractions/audit.service";
|
||||
import { EventCollectionService } from "@bitwarden/common/abstractions/event/event-collection.service";
|
||||
import { TotpService } from "@bitwarden/common/abstractions/totp.service";
|
||||
@@ -18,6 +17,7 @@ import { CollectionService } from "@bitwarden/common/vault/abstractions/collecti
|
||||
import { FolderService } from "@bitwarden/common/vault/abstractions/folder/folder.service.abstraction";
|
||||
import { PasswordRepromptService } from "@bitwarden/common/vault/abstractions/password-reprompt.service";
|
||||
import { Cipher } from "@bitwarden/common/vault/models/domain/cipher";
|
||||
import { DialogService } from "@bitwarden/components";
|
||||
|
||||
import { AddEditComponent as BaseAddEditComponent } from "../../../vault/individual-vault/add-edit.component";
|
||||
|
||||
@@ -47,7 +47,7 @@ export class EmergencyAddEditComponent extends BaseAddEditComponent {
|
||||
organizationService: OrganizationService,
|
||||
logService: LogService,
|
||||
sendApiService: SendApiService,
|
||||
dialogService: DialogServiceAbstraction
|
||||
dialogService: DialogService
|
||||
) {
|
||||
super(
|
||||
cipherService,
|
||||
|
||||
@@ -1,6 +1,5 @@
|
||||
import { Component, OnDestroy, OnInit } from "@angular/core";
|
||||
|
||||
import { DialogServiceAbstraction } from "@bitwarden/angular/services/dialog";
|
||||
import { ApiService } from "@bitwarden/common/abstractions/api.service";
|
||||
import { UserVerificationService } from "@bitwarden/common/auth/abstractions/user-verification/user-verification.service.abstraction";
|
||||
import { TwoFactorProviderType } from "@bitwarden/common/auth/enums/two-factor-provider-type";
|
||||
@@ -12,6 +11,7 @@ import { LogService } from "@bitwarden/common/platform/abstractions/log.service"
|
||||
import { PlatformUtilsService } from "@bitwarden/common/platform/abstractions/platform-utils.service";
|
||||
import { StateService } from "@bitwarden/common/platform/abstractions/state.service";
|
||||
import { Utils } from "@bitwarden/common/platform/misc/utils";
|
||||
import { DialogService } from "@bitwarden/components";
|
||||
|
||||
import { TwoFactorBaseComponent } from "./two-factor-base.component";
|
||||
|
||||
@@ -52,7 +52,7 @@ export class TwoFactorAuthenticatorComponent
|
||||
platformUtilsService: PlatformUtilsService,
|
||||
logService: LogService,
|
||||
private stateService: StateService,
|
||||
dialogService: DialogServiceAbstraction
|
||||
dialogService: DialogService
|
||||
) {
|
||||
super(
|
||||
apiService,
|
||||
|
||||
@@ -1,6 +1,5 @@
|
||||
import { Directive, EventEmitter, Output } from "@angular/core";
|
||||
|
||||
import { DialogServiceAbstraction, SimpleDialogType } from "@bitwarden/angular/services/dialog";
|
||||
import { ApiService } from "@bitwarden/common/abstractions/api.service";
|
||||
import { UserVerificationService } from "@bitwarden/common/auth/abstractions/user-verification/user-verification.service.abstraction";
|
||||
import { TwoFactorProviderType } from "@bitwarden/common/auth/enums/two-factor-provider-type";
|
||||
@@ -11,6 +10,7 @@ import { AuthResponseBase } from "@bitwarden/common/auth/types/auth-response";
|
||||
import { I18nService } from "@bitwarden/common/platform/abstractions/i18n.service";
|
||||
import { LogService } from "@bitwarden/common/platform/abstractions/log.service";
|
||||
import { PlatformUtilsService } from "@bitwarden/common/platform/abstractions/platform-utils.service";
|
||||
import { DialogService } from "@bitwarden/components";
|
||||
|
||||
@Directive()
|
||||
export abstract class TwoFactorBaseComponent {
|
||||
@@ -32,7 +32,7 @@ export abstract class TwoFactorBaseComponent {
|
||||
protected platformUtilsService: PlatformUtilsService,
|
||||
protected logService: LogService,
|
||||
protected userVerificationService: UserVerificationService,
|
||||
protected dialogService: DialogServiceAbstraction
|
||||
protected dialogService: DialogService
|
||||
) {}
|
||||
|
||||
protected auth(authResponse: AuthResponseBase) {
|
||||
@@ -54,7 +54,7 @@ export abstract class TwoFactorBaseComponent {
|
||||
const confirmed = await this.dialogService.openSimpleDialog({
|
||||
title: { key: "disable" },
|
||||
content: { key: "twoStepDisableDesc" },
|
||||
type: SimpleDialogType.WARNING,
|
||||
type: "warning",
|
||||
});
|
||||
|
||||
if (!confirmed) {
|
||||
|
||||
@@ -1,6 +1,5 @@
|
||||
import { Component } from "@angular/core";
|
||||
|
||||
import { DialogServiceAbstraction } from "@bitwarden/angular/services/dialog";
|
||||
import { ApiService } from "@bitwarden/common/abstractions/api.service";
|
||||
import { UserVerificationService } from "@bitwarden/common/auth/abstractions/user-verification/user-verification.service.abstraction";
|
||||
import { TwoFactorProviderType } from "@bitwarden/common/auth/enums/two-factor-provider-type";
|
||||
@@ -10,6 +9,7 @@ import { AuthResponse } from "@bitwarden/common/auth/types/auth-response";
|
||||
import { I18nService } from "@bitwarden/common/platform/abstractions/i18n.service";
|
||||
import { LogService } from "@bitwarden/common/platform/abstractions/log.service";
|
||||
import { PlatformUtilsService } from "@bitwarden/common/platform/abstractions/platform-utils.service";
|
||||
import { DialogService } from "@bitwarden/components";
|
||||
|
||||
import { TwoFactorBaseComponent } from "./two-factor-base.component";
|
||||
|
||||
@@ -32,7 +32,7 @@ export class TwoFactorDuoComponent extends TwoFactorBaseComponent {
|
||||
platformUtilsService: PlatformUtilsService,
|
||||
logService: LogService,
|
||||
userVerificationService: UserVerificationService,
|
||||
dialogService: DialogServiceAbstraction
|
||||
dialogService: DialogService
|
||||
) {
|
||||
super(
|
||||
apiService,
|
||||
|
||||
@@ -1,6 +1,5 @@
|
||||
import { Component } from "@angular/core";
|
||||
|
||||
import { DialogServiceAbstraction } from "@bitwarden/angular/services/dialog";
|
||||
import { ApiService } from "@bitwarden/common/abstractions/api.service";
|
||||
import { UserVerificationService } from "@bitwarden/common/auth/abstractions/user-verification/user-verification.service.abstraction";
|
||||
import { TwoFactorProviderType } from "@bitwarden/common/auth/enums/two-factor-provider-type";
|
||||
@@ -12,6 +11,7 @@ import { I18nService } from "@bitwarden/common/platform/abstractions/i18n.servic
|
||||
import { LogService } from "@bitwarden/common/platform/abstractions/log.service";
|
||||
import { PlatformUtilsService } from "@bitwarden/common/platform/abstractions/platform-utils.service";
|
||||
import { StateService } from "@bitwarden/common/platform/abstractions/state.service";
|
||||
import { DialogService } from "@bitwarden/components";
|
||||
|
||||
import { TwoFactorBaseComponent } from "./two-factor-base.component";
|
||||
|
||||
@@ -36,7 +36,7 @@ export class TwoFactorEmailComponent extends TwoFactorBaseComponent {
|
||||
logService: LogService,
|
||||
userVerificationService: UserVerificationService,
|
||||
private stateService: StateService,
|
||||
dialogService: DialogServiceAbstraction
|
||||
dialogService: DialogService
|
||||
) {
|
||||
super(
|
||||
apiService,
|
||||
|
||||
@@ -1,6 +1,5 @@
|
||||
<form #form (ngSubmit)="submit()" [appApiAction]="formPromise" ngNativeValidate>
|
||||
<div class="modal-body">
|
||||
<p>{{ "twoStepLoginAuthDesc" | i18n }}</p>
|
||||
<app-user-verification [(ngModel)]="secret" ngDefaultControl name="secret">
|
||||
</app-user-verification>
|
||||
</div>
|
||||
|
||||
@@ -1,6 +1,5 @@
|
||||
import { Component, NgZone } from "@angular/core";
|
||||
|
||||
import { DialogServiceAbstraction, SimpleDialogType } from "@bitwarden/angular/services/dialog";
|
||||
import { ApiService } from "@bitwarden/common/abstractions/api.service";
|
||||
import { UserVerificationService } from "@bitwarden/common/auth/abstractions/user-verification/user-verification.service.abstraction";
|
||||
import { TwoFactorProviderType } from "@bitwarden/common/auth/enums/two-factor-provider-type";
|
||||
@@ -15,6 +14,7 @@ import { AuthResponse } from "@bitwarden/common/auth/types/auth-response";
|
||||
import { I18nService } from "@bitwarden/common/platform/abstractions/i18n.service";
|
||||
import { LogService } from "@bitwarden/common/platform/abstractions/log.service";
|
||||
import { PlatformUtilsService } from "@bitwarden/common/platform/abstractions/platform-utils.service";
|
||||
import { DialogService } from "@bitwarden/components";
|
||||
|
||||
import { TwoFactorBaseComponent } from "./two-factor-base.component";
|
||||
|
||||
@@ -51,7 +51,7 @@ export class TwoFactorWebAuthnComponent extends TwoFactorBaseComponent {
|
||||
private ngZone: NgZone,
|
||||
logService: LogService,
|
||||
userVerificationService: UserVerificationService,
|
||||
dialogService: DialogServiceAbstraction
|
||||
dialogService: DialogService
|
||||
) {
|
||||
super(
|
||||
apiService,
|
||||
@@ -98,7 +98,7 @@ export class TwoFactorWebAuthnComponent extends TwoFactorBaseComponent {
|
||||
const confirmed = await this.dialogService.openSimpleDialog({
|
||||
title: name,
|
||||
content: { key: "removeU2fConfirmation" },
|
||||
type: SimpleDialogType.WARNING,
|
||||
type: "warning",
|
||||
});
|
||||
|
||||
if (!confirmed) {
|
||||
|
||||
@@ -1,6 +1,5 @@
|
||||
import { Component } from "@angular/core";
|
||||
|
||||
import { DialogServiceAbstraction } from "@bitwarden/angular/services/dialog";
|
||||
import { ApiService } from "@bitwarden/common/abstractions/api.service";
|
||||
import { UserVerificationService } from "@bitwarden/common/auth/abstractions/user-verification/user-verification.service.abstraction";
|
||||
import { TwoFactorProviderType } from "@bitwarden/common/auth/enums/two-factor-provider-type";
|
||||
@@ -10,6 +9,7 @@ import { AuthResponse } from "@bitwarden/common/auth/types/auth-response";
|
||||
import { I18nService } from "@bitwarden/common/platform/abstractions/i18n.service";
|
||||
import { LogService } from "@bitwarden/common/platform/abstractions/log.service";
|
||||
import { PlatformUtilsService } from "@bitwarden/common/platform/abstractions/platform-utils.service";
|
||||
import { DialogService } from "@bitwarden/components";
|
||||
|
||||
import { TwoFactorBaseComponent } from "./two-factor-base.component";
|
||||
|
||||
@@ -38,7 +38,7 @@ export class TwoFactorYubiKeyComponent extends TwoFactorBaseComponent {
|
||||
platformUtilsService: PlatformUtilsService,
|
||||
logService: LogService,
|
||||
userVerificationService: UserVerificationService,
|
||||
dialogService: DialogServiceAbstraction
|
||||
dialogService: DialogService
|
||||
) {
|
||||
super(
|
||||
apiService,
|
||||
|
||||
@@ -3,11 +3,11 @@ import { Component, Inject } from "@angular/core";
|
||||
import { FormBuilder } from "@angular/forms";
|
||||
|
||||
import { UserVerificationPromptComponent as BaseUserVerificationPrompt } from "@bitwarden/angular/auth/components/user-verification-prompt.component";
|
||||
import { DialogServiceAbstraction } from "@bitwarden/angular/services/dialog";
|
||||
import { ModalConfig } from "@bitwarden/angular/services/modal.service";
|
||||
import { UserVerificationService } from "@bitwarden/common/auth/abstractions/user-verification/user-verification.service.abstraction";
|
||||
import { I18nService } from "@bitwarden/common/platform/abstractions/i18n.service";
|
||||
import { PlatformUtilsService } from "@bitwarden/common/platform/abstractions/platform-utils.service";
|
||||
import { DialogService } from "@bitwarden/components";
|
||||
|
||||
export interface UserVerificationPromptParams {
|
||||
confirmDescription: string;
|
||||
@@ -50,7 +50,7 @@ export class UserVerificationPromptComponent extends BaseUserVerificationPrompt
|
||||
* @param config Configuration for the dialog
|
||||
*/
|
||||
export const openUserVerificationPrompt = (
|
||||
dialogService: DialogServiceAbstraction,
|
||||
dialogService: DialogService,
|
||||
config: DialogConfig<UserVerificationPromptParams>
|
||||
) => {
|
||||
return dialogService.open<boolean, UserVerificationPromptParams>(
|
||||
|
||||
@@ -1,4 +1,4 @@
|
||||
<ng-container *ngIf="!usesKeyConnector">
|
||||
<ng-container *ngIf="hasMasterPassword">
|
||||
<bit-form-field disableMargin>
|
||||
<bit-label>{{ "masterPass" | i18n }}</bit-label>
|
||||
<input
|
||||
@@ -14,7 +14,7 @@
|
||||
<bit-hint>{{ "confirmIdentity" | i18n }}</bit-hint>
|
||||
</bit-form-field>
|
||||
</ng-container>
|
||||
<ng-container *ngIf="usesKeyConnector">
|
||||
<ng-container *ngIf="!hasMasterPassword">
|
||||
<div class="tw-mb-6">
|
||||
<label class="tw-block">{{ "sendVerificationCode" | i18n }}</label>
|
||||
<button type="button" bitButton buttonType="secondary" [bitAction]="requestOTP" appAutofocus>
|
||||
|
||||
@@ -10,6 +10,7 @@ import { AuthService } from "@bitwarden/common/auth/abstractions/auth.service";
|
||||
import { LoginService } from "@bitwarden/common/auth/abstractions/login.service";
|
||||
import { HttpStatusCode } from "@bitwarden/common/enums";
|
||||
import { ErrorResponse } from "@bitwarden/common/models/response/error.response";
|
||||
import { ConfigServiceAbstraction } from "@bitwarden/common/platform/abstractions/config/config.service.abstraction";
|
||||
import { CryptoFunctionService } from "@bitwarden/common/platform/abstractions/crypto-function.service";
|
||||
import { EnvironmentService } from "@bitwarden/common/platform/abstractions/environment.service";
|
||||
import { I18nService } from "@bitwarden/common/platform/abstractions/i18n.service";
|
||||
@@ -39,7 +40,8 @@ export class SsoComponent extends BaseSsoComponent {
|
||||
logService: LogService,
|
||||
private orgDomainApiService: OrgDomainApiServiceAbstraction,
|
||||
private loginService: LoginService,
|
||||
private validationService: ValidationService
|
||||
private validationService: ValidationService,
|
||||
configService: ConfigServiceAbstraction
|
||||
) {
|
||||
super(
|
||||
authService,
|
||||
@@ -52,7 +54,8 @@ export class SsoComponent extends BaseSsoComponent {
|
||||
cryptoFunctionService,
|
||||
environmentService,
|
||||
passwordGenerationService,
|
||||
logService
|
||||
logService,
|
||||
configService
|
||||
);
|
||||
this.redirectUri = window.location.origin + "/sso-connector.html";
|
||||
this.clientId = "web";
|
||||
|
||||
@@ -58,13 +58,13 @@
|
||||
</div>
|
||||
<div class="tw-pt-44" *ngIf="useTrialStepper">
|
||||
<div class="tw-rounded tw-border tw-border-solid tw-border-secondary-300 tw-bg-background">
|
||||
<div class="tw-flex tw-h-auto tw-w-full tw-rounded-t tw-bg-secondary-100">
|
||||
<div class="tw-flex tw-h-auto tw-w-full tw-gap-5 tw-rounded-t tw-bg-secondary-100">
|
||||
<h2 class="tw-pb-4 tw-pl-4 tw-pt-5 tw-text-base tw-font-bold tw-uppercase">
|
||||
{{ "startYour7DayFreeTrialOfBitwardenFor" | i18n : org }}
|
||||
</h2>
|
||||
<environment-selector
|
||||
[hasFlags]="true"
|
||||
class="tw-mr-4 tw-mt-6 tw-text-end"
|
||||
class="tw-mr-4 tw-mt-6 tw-flex-shrink-0 tw-text-end"
|
||||
></environment-selector>
|
||||
</div>
|
||||
<app-vertical-stepper #stepper linear (selectionChange)="stepSelectionChange($event)">
|
||||
|
||||
@@ -94,6 +94,13 @@ export class TrialInitiationComponent implements OnInit, OnDestroy {
|
||||
|
||||
if (this.referenceData.id === "") {
|
||||
this.referenceData.id = null;
|
||||
} else {
|
||||
// Matches "_ga_QBRN562QQQ=value1.value2.session" and captures values and session.
|
||||
const regex = /_ga_QBRN562QQQ=([^.]+)\.([^.]+)\.(\d+)/;
|
||||
const match = document.cookie.match(regex);
|
||||
if (match) {
|
||||
this.referenceData.session = match[3];
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -1,7 +1,8 @@
|
||||
import { Component, ViewChild, ViewContainerRef } from "@angular/core";
|
||||
import { Component, Inject, ViewChild, ViewContainerRef } from "@angular/core";
|
||||
import { ActivatedRoute, Router } from "@angular/router";
|
||||
|
||||
import { TwoFactorComponent as BaseTwoFactorComponent } from "@bitwarden/angular/auth/components/two-factor.component";
|
||||
import { WINDOW } from "@bitwarden/angular/services/injection-tokens";
|
||||
import { ModalService } from "@bitwarden/angular/services/modal.service";
|
||||
import { ApiService } from "@bitwarden/common/abstractions/api.service";
|
||||
import { AuthService } from "@bitwarden/common/auth/abstractions/auth.service";
|
||||
@@ -9,6 +10,7 @@ import { LoginService } from "@bitwarden/common/auth/abstractions/login.service"
|
||||
import { TwoFactorService } from "@bitwarden/common/auth/abstractions/two-factor.service";
|
||||
import { TwoFactorProviderType } from "@bitwarden/common/auth/enums/two-factor-provider-type";
|
||||
import { AppIdService } from "@bitwarden/common/platform/abstractions/app-id.service";
|
||||
import { ConfigServiceAbstraction } from "@bitwarden/common/platform/abstractions/config/config.service.abstraction";
|
||||
import { EnvironmentService } from "@bitwarden/common/platform/abstractions/environment.service";
|
||||
import { I18nService } from "@bitwarden/common/platform/abstractions/i18n.service";
|
||||
import { LogService } from "@bitwarden/common/platform/abstractions/log.service";
|
||||
@@ -42,7 +44,9 @@ export class TwoFactorComponent extends BaseTwoFactorComponent {
|
||||
twoFactorService: TwoFactorService,
|
||||
appIdService: AppIdService,
|
||||
private routerService: RouterService,
|
||||
loginService: LoginService
|
||||
loginService: LoginService,
|
||||
configService: ConfigServiceAbstraction,
|
||||
@Inject(WINDOW) protected win: Window
|
||||
) {
|
||||
super(
|
||||
authService,
|
||||
@@ -50,14 +54,15 @@ export class TwoFactorComponent extends BaseTwoFactorComponent {
|
||||
i18nService,
|
||||
apiService,
|
||||
platformUtilsService,
|
||||
window,
|
||||
win,
|
||||
environmentService,
|
||||
stateService,
|
||||
route,
|
||||
logService,
|
||||
twoFactorService,
|
||||
appIdService,
|
||||
loginService
|
||||
loginService,
|
||||
configService
|
||||
);
|
||||
this.onSuccessfulLoginNavigate = this.goAfterLogIn;
|
||||
}
|
||||
@@ -81,7 +86,7 @@ export class TwoFactorComponent extends BaseTwoFactorComponent {
|
||||
);
|
||||
}
|
||||
|
||||
async goAfterLogIn() {
|
||||
goAfterLogIn = async () => {
|
||||
this.loginService.clearValues();
|
||||
const previousUrl = this.routerService.getPreviousUrl();
|
||||
if (previousUrl) {
|
||||
@@ -103,9 +108,9 @@ export class TwoFactorComponent extends BaseTwoFactorComponent {
|
||||
|
||||
this.router.navigate([this.successRoute], {
|
||||
queryParams: {
|
||||
identifier: this.identifier,
|
||||
identifier: this.orgIdentifier,
|
||||
},
|
||||
});
|
||||
}
|
||||
}
|
||||
};
|
||||
}
|
||||
|
||||
@@ -2,7 +2,6 @@ import { Component } from "@angular/core";
|
||||
import { Router } from "@angular/router";
|
||||
|
||||
import { UpdatePasswordComponent as BaseUpdatePasswordComponent } from "@bitwarden/angular/auth/components/update-password.component";
|
||||
import { DialogServiceAbstraction } from "@bitwarden/angular/services/dialog";
|
||||
import { ApiService } from "@bitwarden/common/abstractions/api.service";
|
||||
import { PolicyService } from "@bitwarden/common/admin-console/abstractions/policy/policy.service.abstraction";
|
||||
import { UserVerificationService } from "@bitwarden/common/auth/abstractions/user-verification/user-verification.service.abstraction";
|
||||
@@ -13,6 +12,7 @@ import { MessagingService } from "@bitwarden/common/platform/abstractions/messag
|
||||
import { PlatformUtilsService } from "@bitwarden/common/platform/abstractions/platform-utils.service";
|
||||
import { StateService } from "@bitwarden/common/platform/abstractions/state.service";
|
||||
import { PasswordGenerationServiceAbstraction } from "@bitwarden/common/tools/generator/password";
|
||||
import { DialogService } from "@bitwarden/components";
|
||||
|
||||
@Component({
|
||||
selector: "app-update-password",
|
||||
@@ -31,7 +31,7 @@ export class UpdatePasswordComponent extends BaseUpdatePasswordComponent {
|
||||
logService: LogService,
|
||||
stateService: StateService,
|
||||
userVerificationService: UserVerificationService,
|
||||
dialogService: DialogServiceAbstraction
|
||||
dialogService: DialogService
|
||||
) {
|
||||
super(
|
||||
router,
|
||||
|
||||
@@ -87,13 +87,32 @@
|
||||
<td bitCell>{{ "passwordManager" | i18n }} - {{ "freeOrganization" | i18n }}</td>
|
||||
<td bitCell class="tw-text-right">{{ "free" | i18n }}</td>
|
||||
</tr>
|
||||
<tr bitRow *ngIf="userOrg.useSecretsManager">
|
||||
<tr bitRow *ngIf="userOrg.useSecretsManager && !sub.secretsManagerBeta">
|
||||
<td bitCell>{{ "secretsManager" | i18n }} - {{ "freeOrganization" | i18n }}</td>
|
||||
<td bitCell class="tw-text-right">{{ "free" | i18n }}</td>
|
||||
</tr>
|
||||
</ng-container>
|
||||
<tr bitRow *ngIf="sub.secretsManagerBeta">
|
||||
<td bitCell>
|
||||
{{ "secretsManager" | i18n }} -
|
||||
{{ "beta" | i18n }}
|
||||
({{ "annually" | i18n }}) @
|
||||
{{ 0 | currency : "$" }}
|
||||
<span bitBadge badgeType="warning" class="tw-ml-2">{{
|
||||
"betaEnding" | i18n | uppercase
|
||||
}}</span>
|
||||
</td>
|
||||
<td bitCell class="tw-text-right">{{ 0 | currency : "$" }} /{{ "year" | i18n }}</td>
|
||||
</tr>
|
||||
</ng-template>
|
||||
</bit-table>
|
||||
<bit-callout
|
||||
*ngIf="sub.secretsManagerBeta && !userOrg.isFreeOrg"
|
||||
type="warning"
|
||||
class="tw-mt-4 tw-block"
|
||||
>
|
||||
{{ smBetaEndedDesc }}
|
||||
</bit-callout>
|
||||
</div>
|
||||
</ng-container>
|
||||
|
||||
|
||||
@@ -1,8 +1,8 @@
|
||||
import { DatePipe } from "@angular/common";
|
||||
import { Component, OnDestroy, OnInit } from "@angular/core";
|
||||
import { ActivatedRoute } from "@angular/router";
|
||||
import { concatMap, Subject, takeUntil } from "rxjs";
|
||||
|
||||
import { DialogServiceAbstraction, SimpleDialogType } from "@bitwarden/angular/services/dialog";
|
||||
import { ModalConfig, ModalService } from "@bitwarden/angular/services/modal.service";
|
||||
import { ApiService } from "@bitwarden/common/abstractions/api.service";
|
||||
import { OrganizationApiServiceAbstraction } from "@bitwarden/common/admin-console/abstractions/organization/organization-api.service.abstraction";
|
||||
@@ -17,6 +17,8 @@ import { ConfigServiceAbstraction } from "@bitwarden/common/platform/abstraction
|
||||
import { I18nService } from "@bitwarden/common/platform/abstractions/i18n.service";
|
||||
import { LogService } from "@bitwarden/common/platform/abstractions/log.service";
|
||||
import { PlatformUtilsService } from "@bitwarden/common/platform/abstractions/platform-utils.service";
|
||||
import { Utils } from "@bitwarden/common/platform/misc/utils";
|
||||
import { DialogService } from "@bitwarden/components";
|
||||
|
||||
import {
|
||||
BillingSyncApiKeyComponent,
|
||||
@@ -45,6 +47,9 @@ export class OrganizationSubscriptionCloudComponent implements OnInit, OnDestroy
|
||||
firstLoaded = false;
|
||||
loading: boolean;
|
||||
|
||||
private readonly _smBetaEndingDate = new Date(2023, 7, 15);
|
||||
private readonly _smGracePeriodEndingDate = new Date(2023, 10, 14);
|
||||
|
||||
private destroy$ = new Subject<void>();
|
||||
|
||||
constructor(
|
||||
@@ -56,8 +61,9 @@ export class OrganizationSubscriptionCloudComponent implements OnInit, OnDestroy
|
||||
private organizationService: OrganizationService,
|
||||
private organizationApiService: OrganizationApiServiceAbstraction,
|
||||
private route: ActivatedRoute,
|
||||
private dialogService: DialogServiceAbstraction,
|
||||
private configService: ConfigServiceAbstraction
|
||||
private dialogService: DialogService,
|
||||
private configService: ConfigServiceAbstraction,
|
||||
private datePipe: DatePipe
|
||||
) {}
|
||||
|
||||
async ngOnInit() {
|
||||
@@ -122,6 +128,7 @@ export class OrganizationSubscriptionCloudComponent implements OnInit, OnDestroy
|
||||
this.userOrg.useSecretsManager &&
|
||||
this.subscription != null &&
|
||||
this.sub.secretsManagerPlan?.hasAdditionalSeatsOption &&
|
||||
!this.sub.secretsManagerBeta &&
|
||||
!this.subscription.cancelled &&
|
||||
!this.subscriptionMarkedForCancel;
|
||||
|
||||
@@ -256,6 +263,14 @@ export class OrganizationSubscriptionCloudComponent implements OnInit, OnDestroy
|
||||
);
|
||||
}
|
||||
|
||||
get smBetaEndedDesc() {
|
||||
return this.i18nService.translate(
|
||||
"smBetaEndedDesc",
|
||||
this.datePipe.transform(this._smBetaEndingDate),
|
||||
Utils.daysRemaining(this._smGracePeriodEndingDate).toString()
|
||||
);
|
||||
}
|
||||
|
||||
cancel = async () => {
|
||||
if (this.loading) {
|
||||
return;
|
||||
@@ -264,7 +279,7 @@ export class OrganizationSubscriptionCloudComponent implements OnInit, OnDestroy
|
||||
const confirmed = await this.dialogService.openSimpleDialog({
|
||||
title: { key: "cancelSubscription" },
|
||||
content: { key: "cancelConfirmation" },
|
||||
type: SimpleDialogType.WARNING,
|
||||
type: "warning",
|
||||
});
|
||||
|
||||
if (!confirmed) {
|
||||
@@ -292,7 +307,7 @@ export class OrganizationSubscriptionCloudComponent implements OnInit, OnDestroy
|
||||
const confirmed = await this.dialogService.openSimpleDialog({
|
||||
title: { key: "reinstateSubscription" },
|
||||
content: { key: "reinstateConfirmation" },
|
||||
type: SimpleDialogType.WARNING,
|
||||
type: "warning",
|
||||
});
|
||||
|
||||
if (!confirmed) {
|
||||
@@ -364,7 +379,7 @@ export class OrganizationSubscriptionCloudComponent implements OnInit, OnDestroy
|
||||
title: { key: "removeSponsorship" },
|
||||
content: { key: "removeSponsorshipConfirmation" },
|
||||
acceptButtonText: { key: "remove" },
|
||||
type: SimpleDialogType.WARNING,
|
||||
type: "warning",
|
||||
});
|
||||
|
||||
if (!confirmed) {
|
||||
|
||||
@@ -5,7 +5,7 @@
|
||||
<bit-hint>
|
||||
<strong>{{ "total" | i18n }}:</strong>
|
||||
{{ formGroup.value.seatCount || 0 }} × {{ options.seatPrice | currency : "$" }} =
|
||||
{{ seatTotal | currency : "$" }} / {{ options.interval | i18n }}
|
||||
{{ seatTotalCost | currency : "$" }} / {{ options.interval | i18n }}
|
||||
</bit-hint>
|
||||
</bit-form-field>
|
||||
<bit-form-control>
|
||||
@@ -28,7 +28,7 @@
|
||||
<bit-hint>
|
||||
<strong>{{ "maxSeatCost" | i18n }}:</strong>
|
||||
{{ formGroup.value.maxAutoscaleSeats || 0 }} ×
|
||||
{{ options.seatPrice | currency : "$" }} = {{ maxSeatTotal | currency : "$" }} /
|
||||
{{ options.seatPrice | currency : "$" }} = {{ maxSeatTotalCost | currency : "$" }} /
|
||||
{{ options.interval | i18n }}
|
||||
</bit-hint>
|
||||
</bit-form-field>
|
||||
@@ -44,16 +44,14 @@
|
||||
/>
|
||||
<bit-hint>
|
||||
<div>
|
||||
{{
|
||||
"additionalServiceAccountsDesc"
|
||||
| i18n : options.baseServiceAccountCount : (monthlyServiceAccountPrice | currency : "$")
|
||||
}}
|
||||
{{ "includedServiceAccounts" | i18n : options.baseServiceAccountCount }}
|
||||
{{ "addAdditionalServiceAccounts" | i18n : (monthlyServiceAccountPrice | currency : "$") }}
|
||||
</div>
|
||||
<div>
|
||||
<strong>{{ "total" | i18n }}:</strong>
|
||||
{{ formGroup.value.additionalServiceAccounts || 0 }} ×
|
||||
{{ options.additionalServiceAccountPrice | currency : "$" }} =
|
||||
{{ serviceAccountTotal | currency : "$" }} / {{ options.interval | i18n }}
|
||||
{{ serviceAccountTotalCost | currency : "$" }} / {{ options.interval | i18n }}
|
||||
</div>
|
||||
</bit-hint>
|
||||
</bit-form-field>
|
||||
@@ -80,10 +78,13 @@
|
||||
[min]="formGroup.value.additionalServiceAccounts"
|
||||
/>
|
||||
<bit-hint>
|
||||
<div>
|
||||
{{ "includedServiceAccounts" | i18n : options.baseServiceAccountCount }}
|
||||
</div>
|
||||
<strong>{{ "maxServiceAccountCost" | i18n }}:</strong>
|
||||
{{ formGroup.value.maxAutoscaleServiceAccounts || 0 }} ×
|
||||
{{ maxAdditionalServiceAccounts }} ×
|
||||
{{ options.additionalServiceAccountPrice | currency : "$" }} =
|
||||
{{ maxServiceAccountTotal | currency : "$" }} / {{ options.interval | i18n }}
|
||||
{{ maxServiceAccountTotalCost | currency : "$" }} / {{ options.interval | i18n }}
|
||||
</bit-hint>
|
||||
</bit-form-field>
|
||||
<button type="submit" bitButton buttonType="primary" bitFormButton>
|
||||
|
||||
@@ -72,24 +72,26 @@ export class SecretsManagerAdjustSubscriptionComponent implements OnInit, OnDest
|
||||
: this.options.additionalServiceAccountPrice / 12;
|
||||
}
|
||||
|
||||
get serviceAccountTotal(): number {
|
||||
get serviceAccountTotalCost(): number {
|
||||
return Math.abs(
|
||||
this.formGroup.value.additionalServiceAccounts * this.options.additionalServiceAccountPrice
|
||||
);
|
||||
}
|
||||
|
||||
get seatTotal(): number {
|
||||
get seatTotalCost(): number {
|
||||
return Math.abs(this.formGroup.value.seatCount * this.options.seatPrice);
|
||||
}
|
||||
|
||||
get maxServiceAccountTotal(): number {
|
||||
return Math.abs(
|
||||
(this.formGroup.value.maxAutoscaleServiceAccounts ?? 0) *
|
||||
this.options.additionalServiceAccountPrice
|
||||
);
|
||||
get maxAdditionalServiceAccounts(): number {
|
||||
const maxTotalServiceAccounts = this.formGroup.value.maxAutoscaleServiceAccounts ?? 0;
|
||||
return Math.max(0, maxTotalServiceAccounts - this.options.baseServiceAccountCount);
|
||||
}
|
||||
|
||||
get maxSeatTotal(): number {
|
||||
get maxServiceAccountTotalCost(): number {
|
||||
return this.maxAdditionalServiceAccounts * this.options.additionalServiceAccountPrice;
|
||||
}
|
||||
|
||||
get maxSeatTotalCost(): number {
|
||||
return Math.abs((this.formGroup.value.maxAutoscaleSeats ?? 0) * this.options.seatPrice);
|
||||
}
|
||||
|
||||
@@ -115,7 +117,7 @@ export class SecretsManagerAdjustSubscriptionComponent implements OnInit, OnDest
|
||||
|
||||
if (value.limitServiceAccounts) {
|
||||
maxAutoscaleServiceAccountsControl.setValidators([
|
||||
Validators.min(value.additionalServiceAccounts),
|
||||
Validators.min(value.additionalServiceAccounts + this.options.baseServiceAccountCount),
|
||||
]);
|
||||
maxAutoscaleServiceAccountsControl.enable({ emitEvent: false });
|
||||
} else {
|
||||
|
||||
@@ -2,6 +2,8 @@ import { Component, EventEmitter, Input, Output } from "@angular/core";
|
||||
import { FormBuilder } from "@angular/forms";
|
||||
|
||||
import { OrganizationApiServiceAbstraction } from "@bitwarden/common/admin-console/abstractions/organization/organization-api.service.abstraction";
|
||||
import { InternalOrganizationServiceAbstraction } from "@bitwarden/common/admin-console/abstractions/organization/organization.service.abstraction";
|
||||
import { OrganizationData } from "@bitwarden/common/admin-console/models/data/organization.data";
|
||||
import { Organization } from "@bitwarden/common/admin-console/models/domain/organization";
|
||||
import { SecretsManagerSubscribeRequest } from "@bitwarden/common/billing/models/request/sm-subscribe.request";
|
||||
import { PlanResponse } from "@bitwarden/common/billing/models/response/plan.response";
|
||||
@@ -25,7 +27,8 @@ export class SecretsManagerSubscribeStandaloneComponent {
|
||||
private formBuilder: FormBuilder,
|
||||
private platformUtilsService: PlatformUtilsService,
|
||||
private i18nService: I18nService,
|
||||
private organizationApiService: OrganizationApiServiceAbstraction
|
||||
private organizationApiService: OrganizationApiServiceAbstraction,
|
||||
private organizationService: InternalOrganizationServiceAbstraction
|
||||
) {}
|
||||
|
||||
submit = async () => {
|
||||
@@ -37,7 +40,15 @@ export class SecretsManagerSubscribeStandaloneComponent {
|
||||
? this.formGroup.value.additionalServiceAccounts
|
||||
: 0;
|
||||
|
||||
await this.organizationApiService.subscribeToSecretsManager(this.organization.id, request);
|
||||
const profileOrganization = await this.organizationApiService.subscribeToSecretsManager(
|
||||
this.organization.id,
|
||||
request
|
||||
);
|
||||
const organizationData = new OrganizationData(profileOrganization, {
|
||||
isMember: this.organization.isMember,
|
||||
isProviderUser: this.organization.isProviderUser,
|
||||
});
|
||||
await this.organizationService.upsert(organizationData);
|
||||
|
||||
this.platformUtilsService.showToast("success", null, this.i18nService.t("subscriptionUpdated"));
|
||||
|
||||
|
||||
@@ -56,10 +56,13 @@
|
||||
<bit-form-field>
|
||||
<bit-label>{{ "additionalServiceAccounts" | i18n }}</bit-label>
|
||||
<input bitInput formControlName="additionalServiceAccounts" type="number" />
|
||||
<bit-hint>{{
|
||||
"additionalServiceAccountsDesc"
|
||||
| i18n : serviceAccountsIncluded : (monthlyCostPerServiceAccount | currency : "$")
|
||||
}}</bit-hint>
|
||||
<bit-hint>
|
||||
{{ "includedServiceAccounts" | i18n : serviceAccountsIncluded }}
|
||||
{{
|
||||
"addAdditionalServiceAccounts"
|
||||
| i18n : (monthlyCostPerServiceAccount | currency : "$")
|
||||
}}
|
||||
</bit-hint>
|
||||
</bit-form-field>
|
||||
</div>
|
||||
|
||||
|
||||
@@ -12,6 +12,7 @@ import { ApiService } from "@bitwarden/common/abstractions/api.service";
|
||||
import { OrganizationService } from "@bitwarden/common/admin-console/abstractions/organization/organization.service.abstraction";
|
||||
import { PaymentMethodType } from "@bitwarden/common/billing/enums";
|
||||
import { BitPayInvoiceRequest } from "@bitwarden/common/billing/models/request/bit-pay-invoice.request";
|
||||
import { ConfigServiceAbstraction } from "@bitwarden/common/platform/abstractions/config/config.service.abstraction";
|
||||
import { PayPalConfig } from "@bitwarden/common/platform/abstractions/environment.service";
|
||||
import { LogService } from "@bitwarden/common/platform/abstractions/log.service";
|
||||
import { PlatformUtilsService } from "@bitwarden/common/platform/abstractions/platform-utils.service";
|
||||
@@ -43,13 +44,15 @@ export class AddCreditComponent implements OnInit {
|
||||
private userId: string;
|
||||
private name: string;
|
||||
private email: string;
|
||||
private region: string;
|
||||
|
||||
constructor(
|
||||
private stateService: StateService,
|
||||
private apiService: ApiService,
|
||||
private platformUtilsService: PlatformUtilsService,
|
||||
private organizationService: OrganizationService,
|
||||
private logService: LogService
|
||||
private logService: LogService,
|
||||
private configService: ConfigServiceAbstraction
|
||||
) {
|
||||
const payPalConfig = process.env.PAYPAL_CONFIG as PayPalConfig;
|
||||
this.ppButtonFormAction = payPalConfig.buttonAction;
|
||||
@@ -76,7 +79,9 @@ export class AddCreditComponent implements OnInit {
|
||||
this.email = this.subject;
|
||||
this.ppButtonCustomField = "user_id:" + this.userId;
|
||||
}
|
||||
this.region = await this.configService.getCloudRegion();
|
||||
this.ppButtonCustomField += ",account_credit:1";
|
||||
this.ppButtonCustomField += `,region:${this.region}`;
|
||||
this.returnUrl = window.location.href;
|
||||
}
|
||||
|
||||
|
||||
@@ -329,7 +329,7 @@
|
||||
>
|
||||
{{ "submit" | i18n }}
|
||||
</button>
|
||||
<button type="button" class="btn btn-outline-secondary" (click)="cancel()" *ngIf="showCancel">
|
||||
<button type="button" buttonType="secondary" bitButton (click)="cancel()" *ngIf="showCancel">
|
||||
{{ "cancel" | i18n }}
|
||||
</button>
|
||||
</div>
|
||||
|
||||
@@ -31,7 +31,10 @@ import { LogService } from "@bitwarden/common/platform/abstractions/log.service"
|
||||
import { MessagingService } from "@bitwarden/common/platform/abstractions/messaging.service";
|
||||
import { PlatformUtilsService } from "@bitwarden/common/platform/abstractions/platform-utils.service";
|
||||
import { EncString } from "@bitwarden/common/platform/models/domain/enc-string";
|
||||
import { SymmetricCryptoKey } from "@bitwarden/common/platform/models/domain/symmetric-crypto-key";
|
||||
import {
|
||||
OrgKey,
|
||||
SymmetricCryptoKey,
|
||||
} from "@bitwarden/common/platform/models/domain/symmetric-crypto-key";
|
||||
import { SyncService } from "@bitwarden/common/vault/abstractions/sync/sync.service.abstraction";
|
||||
|
||||
import { secretsManagerSubscribeFormFactory } from "../organizations/secrets-manager/sm-subscribe.component";
|
||||
@@ -314,16 +317,11 @@ export class OrganizationPlansComponent implements OnInit, OnDestroy {
|
||||
return 0;
|
||||
}
|
||||
|
||||
let subTotal = plan.basePrice;
|
||||
if (plan.hasAdditionalSeatsOption && formValues.userSeats) {
|
||||
subTotal += this.seatTotal(plan, formValues.userSeats);
|
||||
}
|
||||
|
||||
if (plan.hasAdditionalStorageOption && formValues.additionalServiceAccounts) {
|
||||
subTotal += this.additionalServiceAccountTotal(this.selectedPlan);
|
||||
}
|
||||
|
||||
return subTotal;
|
||||
return (
|
||||
plan.basePrice +
|
||||
this.seatTotal(plan, formValues.userSeats) +
|
||||
this.additionalServiceAccountTotal(plan)
|
||||
);
|
||||
}
|
||||
|
||||
get freeTrial() {
|
||||
@@ -420,19 +418,19 @@ export class OrganizationPlansComponent implements OnInit, OnDestroy {
|
||||
const doSubmit = async (): Promise<string> => {
|
||||
let orgId: string = null;
|
||||
if (this.createOrganization) {
|
||||
const shareKey = await this.cryptoService.makeShareKey();
|
||||
const key = shareKey[0].encryptedString;
|
||||
const orgKey = await this.cryptoService.makeOrgKey<OrgKey>();
|
||||
const key = orgKey[0].encryptedString;
|
||||
const collection = await this.cryptoService.encrypt(
|
||||
this.i18nService.t("defaultCollection"),
|
||||
shareKey[1]
|
||||
orgKey[1]
|
||||
);
|
||||
const collectionCt = collection.encryptedString;
|
||||
const orgKeys = await this.cryptoService.makeKeyPair(shareKey[1]);
|
||||
const orgKeys = await this.cryptoService.makeKeyPair(orgKey[1]);
|
||||
|
||||
if (this.selfHosted) {
|
||||
orgId = await this.createSelfHosted(key, collectionCt, orgKeys);
|
||||
} else {
|
||||
orgId = await this.createCloudHosted(key, collectionCt, orgKeys, shareKey[1]);
|
||||
orgId = await this.createCloudHosted(key, collectionCt, orgKeys, orgKey[1]);
|
||||
}
|
||||
|
||||
this.platformUtilsService.showToast(
|
||||
|
||||
@@ -112,6 +112,7 @@
|
||||
*ngIf="showAdjustPayment"
|
||||
>
|
||||
</app-adjust-payment>
|
||||
<p *ngIf="isUnpaid">{{ "paymentChargedWithUnpaidSubscription" | i18n }}</p>
|
||||
<ng-container *ngIf="forOrganization">
|
||||
<h2 class="spaced-header">{{ "taxInformation" | i18n }}</h2>
|
||||
<p>{{ "taxInformationDesc" | i18n }}</p>
|
||||
|
||||
@@ -2,16 +2,17 @@ import { Component, OnInit, ViewChild } from "@angular/core";
|
||||
import { FormBuilder, FormControl, Validators } from "@angular/forms";
|
||||
import { ActivatedRoute, Router } from "@angular/router";
|
||||
|
||||
import { DialogServiceAbstraction, SimpleDialogType } from "@bitwarden/angular/services/dialog";
|
||||
import { ApiService } from "@bitwarden/common/abstractions/api.service";
|
||||
import { OrganizationApiServiceAbstraction } from "@bitwarden/common/admin-console/abstractions/organization/organization-api.service.abstraction";
|
||||
import { OrganizationResponse } from "@bitwarden/common/admin-console/models/response/organization.response";
|
||||
import { PaymentMethodType } from "@bitwarden/common/billing/enums";
|
||||
import { BillingPaymentResponse } from "@bitwarden/common/billing/models/response/billing-payment.response";
|
||||
import { OrganizationSubscriptionResponse } from "@bitwarden/common/billing/models/response/organization-subscription.response";
|
||||
import { SubscriptionResponse } from "@bitwarden/common/billing/models/response/subscription.response";
|
||||
import { VerifyBankRequest } from "@bitwarden/common/models/request/verify-bank.request";
|
||||
import { I18nService } from "@bitwarden/common/platform/abstractions/i18n.service";
|
||||
import { LogService } from "@bitwarden/common/platform/abstractions/log.service";
|
||||
import { PlatformUtilsService } from "@bitwarden/common/platform/abstractions/platform-utils.service";
|
||||
import { DialogService } from "@bitwarden/components";
|
||||
|
||||
import { TaxInfoComponent } from "./tax-info.component";
|
||||
|
||||
@@ -28,9 +29,11 @@ export class PaymentMethodComponent implements OnInit {
|
||||
showAdjustPayment = false;
|
||||
showAddCredit = false;
|
||||
billing: BillingPaymentResponse;
|
||||
org: OrganizationResponse;
|
||||
org: OrganizationSubscriptionResponse;
|
||||
sub: SubscriptionResponse;
|
||||
paymentMethodType = PaymentMethodType;
|
||||
organizationId: string;
|
||||
isUnpaid = false;
|
||||
|
||||
verifyBankPromise: Promise<any>;
|
||||
taxFormPromise: Promise<any>;
|
||||
@@ -57,7 +60,7 @@ export class PaymentMethodComponent implements OnInit {
|
||||
private logService: LogService,
|
||||
private route: ActivatedRoute,
|
||||
private formBuilder: FormBuilder,
|
||||
private dialogService: DialogServiceAbstraction
|
||||
private dialogService: DialogService
|
||||
) {}
|
||||
|
||||
async ngOnInit() {
|
||||
@@ -83,13 +86,23 @@ export class PaymentMethodComponent implements OnInit {
|
||||
|
||||
if (this.forOrganization) {
|
||||
const billingPromise = this.organizationApiService.getBilling(this.organizationId);
|
||||
const orgPromise = this.organizationApiService.get(this.organizationId);
|
||||
const organizationSubscriptionPromise = this.organizationApiService.getSubscription(
|
||||
this.organizationId
|
||||
);
|
||||
|
||||
[this.billing, this.org] = await Promise.all([billingPromise, orgPromise]);
|
||||
[this.billing, this.org] = await Promise.all([
|
||||
billingPromise,
|
||||
organizationSubscriptionPromise,
|
||||
]);
|
||||
} else {
|
||||
this.billing = await this.apiService.getUserBillingPayment();
|
||||
const billingPromise = this.apiService.getUserBillingPayment();
|
||||
const subPromise = this.apiService.getUserSubscription();
|
||||
|
||||
[this.billing, this.sub] = await Promise.all([billingPromise, subPromise]);
|
||||
}
|
||||
|
||||
this.isUnpaid = this.subscription?.status === "unpaid" ?? false;
|
||||
|
||||
this.loading = false;
|
||||
}
|
||||
|
||||
@@ -100,7 +113,7 @@ export class PaymentMethodComponent implements OnInit {
|
||||
content: { key: "cannotPerformInAppPurchase" },
|
||||
acceptButtonText: { key: "ok" },
|
||||
cancelButtonText: null,
|
||||
type: SimpleDialogType.WARNING,
|
||||
type: "warning",
|
||||
});
|
||||
|
||||
return;
|
||||
@@ -122,11 +135,12 @@ export class PaymentMethodComponent implements OnInit {
|
||||
content: { key: "cannotPerformInAppPurchase" },
|
||||
acceptButtonText: { key: "ok" },
|
||||
cancelButtonText: null,
|
||||
type: SimpleDialogType.WARNING,
|
||||
type: "warning",
|
||||
});
|
||||
|
||||
return;
|
||||
}
|
||||
|
||||
this.showAdjustPayment = true;
|
||||
}
|
||||
|
||||
@@ -214,4 +228,8 @@ export class PaymentMethodComponent implements OnInit {
|
||||
this.paymentSource.type === PaymentMethodType.GoogleInApp)
|
||||
);
|
||||
}
|
||||
|
||||
get subscription() {
|
||||
return this.sub?.subscription ?? this.org?.subscription ?? null;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -4,7 +4,7 @@ import { RouterModule, Routes } from "@angular/router";
|
||||
import { BillingHistoryViewComponent } from "../../billing/settings/billing-history-view.component";
|
||||
import { PaymentMethodComponent } from "../../billing/settings/payment-method.component";
|
||||
import { UserSubscriptionComponent } from "../../billing/settings/user-subscription.component";
|
||||
import { PremiumComponent } from "../../settings/premium.component";
|
||||
import { PremiumComponent } from "../../vault/settings/premium.component";
|
||||
|
||||
import { SubscriptionComponent } from "./subscription.component";
|
||||
|
||||
|
||||
@@ -1,7 +1,6 @@
|
||||
import { Component, OnInit } from "@angular/core";
|
||||
import { Router } from "@angular/router";
|
||||
|
||||
import { DialogServiceAbstraction, SimpleDialogType } from "@bitwarden/angular/services/dialog";
|
||||
import { ApiService } from "@bitwarden/common/abstractions/api.service";
|
||||
import { SubscriptionResponse } from "@bitwarden/common/billing/models/response/subscription.response";
|
||||
import { EnvironmentService } from "@bitwarden/common/platform/abstractions/environment.service";
|
||||
@@ -10,6 +9,7 @@ import { I18nService } from "@bitwarden/common/platform/abstractions/i18n.servic
|
||||
import { LogService } from "@bitwarden/common/platform/abstractions/log.service";
|
||||
import { PlatformUtilsService } from "@bitwarden/common/platform/abstractions/platform-utils.service";
|
||||
import { StateService } from "@bitwarden/common/platform/abstractions/state.service";
|
||||
import { DialogService } from "@bitwarden/components";
|
||||
|
||||
@Component({
|
||||
selector: "app-user-subscription",
|
||||
@@ -36,7 +36,7 @@ export class UserSubscriptionComponent implements OnInit {
|
||||
private router: Router,
|
||||
private logService: LogService,
|
||||
private fileDownloadService: FileDownloadService,
|
||||
private dialogService: DialogServiceAbstraction,
|
||||
private dialogService: DialogService,
|
||||
private environmentService: EnvironmentService
|
||||
) {
|
||||
this.selfHosted = platformUtilsService.isSelfHost();
|
||||
@@ -75,7 +75,7 @@ export class UserSubscriptionComponent implements OnInit {
|
||||
content: { key: "manageSubscriptionFromStore" },
|
||||
acceptButtonText: { key: "ok" },
|
||||
cancelButtonText: null,
|
||||
type: SimpleDialogType.WARNING,
|
||||
type: "warning",
|
||||
});
|
||||
|
||||
return;
|
||||
@@ -84,7 +84,7 @@ export class UserSubscriptionComponent implements OnInit {
|
||||
const confirmed = await this.dialogService.openSimpleDialog({
|
||||
title: { key: "reinstateSubscription" },
|
||||
content: { key: "reinstateConfirmation" },
|
||||
type: SimpleDialogType.WARNING,
|
||||
type: "warning",
|
||||
});
|
||||
|
||||
if (!confirmed) {
|
||||
@@ -112,7 +112,7 @@ export class UserSubscriptionComponent implements OnInit {
|
||||
content: { key: "manageSubscriptionFromStore" },
|
||||
acceptButtonText: { key: "ok" },
|
||||
cancelButtonText: null,
|
||||
type: SimpleDialogType.WARNING,
|
||||
type: "warning",
|
||||
});
|
||||
|
||||
return;
|
||||
@@ -121,7 +121,7 @@ export class UserSubscriptionComponent implements OnInit {
|
||||
const confirmed = await this.dialogService.openSimpleDialog({
|
||||
title: { key: "cancelSubscription" },
|
||||
content: { key: "cancelConfirmation" },
|
||||
type: SimpleDialogType.WARNING,
|
||||
type: "warning",
|
||||
});
|
||||
|
||||
if (!confirmed) {
|
||||
@@ -175,7 +175,7 @@ export class UserSubscriptionComponent implements OnInit {
|
||||
content: { key: "cannotPerformInAppPurchase" },
|
||||
acceptButtonText: { key: "ok" },
|
||||
cancelButtonText: null,
|
||||
type: SimpleDialogType.WARNING,
|
||||
type: "warning",
|
||||
});
|
||||
|
||||
return;
|
||||
|
||||
@@ -2,7 +2,6 @@ import { Directive, ViewChild, ViewContainerRef } from "@angular/core";
|
||||
|
||||
import { SearchPipe } from "@bitwarden/angular/pipes/search.pipe";
|
||||
import { UserNamePipe } from "@bitwarden/angular/pipes/user-name.pipe";
|
||||
import { DialogServiceAbstraction, SimpleDialogType } from "@bitwarden/angular/services/dialog";
|
||||
import { ModalService } from "@bitwarden/angular/services/modal.service";
|
||||
import { ApiService } from "@bitwarden/common/abstractions/api.service";
|
||||
import { SearchService } from "@bitwarden/common/abstractions/search.service";
|
||||
@@ -21,6 +20,7 @@ import { PlatformUtilsService } from "@bitwarden/common/platform/abstractions/pl
|
||||
import { StateService } from "@bitwarden/common/platform/abstractions/state.service";
|
||||
import { ValidationService } from "@bitwarden/common/platform/abstractions/validation.service";
|
||||
import { Utils } from "@bitwarden/common/platform/misc/utils";
|
||||
import { DialogService } from "@bitwarden/components";
|
||||
|
||||
import { OrganizationUserView } from "../admin-console/organizations/core/views/organization-user.view";
|
||||
import { UserConfirmComponent } from "../admin-console/organizations/manage/user-confirm.component";
|
||||
@@ -110,7 +110,7 @@ export abstract class BasePeopleComponent<
|
||||
private searchPipe: SearchPipe,
|
||||
protected userNamePipe: UserNamePipe,
|
||||
protected stateService: StateService,
|
||||
protected dialogService: DialogServiceAbstraction
|
||||
protected dialogService: DialogService
|
||||
) {}
|
||||
|
||||
abstract edit(user: UserType): void;
|
||||
@@ -222,7 +222,7 @@ export abstract class BasePeopleComponent<
|
||||
return this.dialogService.openSimpleDialog({
|
||||
title: this.userNamePipe.transform(user),
|
||||
content: { key: "removeUserConfirmation" },
|
||||
type: SimpleDialogType.WARNING,
|
||||
type: "warning",
|
||||
});
|
||||
}
|
||||
|
||||
@@ -252,7 +252,7 @@ export abstract class BasePeopleComponent<
|
||||
title: { key: "revokeAccess", placeholders: [this.userNamePipe.transform(user)] },
|
||||
content: this.revokeWarningMessage(),
|
||||
acceptButtonText: { key: "revokeAccess" },
|
||||
type: SimpleDialogType.WARNING,
|
||||
type: "warning",
|
||||
});
|
||||
}
|
||||
|
||||
@@ -374,7 +374,7 @@ export abstract class BasePeopleComponent<
|
||||
}
|
||||
|
||||
try {
|
||||
const fingerprint = await this.cryptoService.getFingerprint(user.userId, publicKey.buffer);
|
||||
const fingerprint = await this.cryptoService.getFingerprint(user.userId, publicKey);
|
||||
this.logService.info(`User's fingerprint: ${fingerprint.join("-")}`);
|
||||
} catch (e) {
|
||||
this.logService.error(e);
|
||||
|
||||
@@ -10,8 +10,12 @@
|
||||
aria-hidden="true"
|
||||
[style.visibility]="isUsServer ? 'visible' : 'hidden'"
|
||||
></i>
|
||||
<img src="../../images/us_flag.png" alt="{{ 'usFlag' | i18n }}" class="pb-1 mr-1" />
|
||||
{{ "us" | i18n }}
|
||||
<img
|
||||
src="../../images/flag-us.svg"
|
||||
alt="{{ 'usFlag' | i18n }}"
|
||||
class="tw-mr-1 tw-w-6 tw-pb-1"
|
||||
/>
|
||||
{{ "usDomain" | i18n }}
|
||||
</a>
|
||||
<a
|
||||
bitMenuItem
|
||||
@@ -24,31 +28,35 @@
|
||||
aria-hidden="true"
|
||||
[style.visibility]="isEuServer ? 'visible' : 'hidden'"
|
||||
></i>
|
||||
<img src="../../images/eu_flag.png" alt="{{ 'euFlag' | i18n }}" class="pb-1 mr-1" />
|
||||
{{ "eu" | i18n }}
|
||||
<img
|
||||
src="../../images/flag-eu.svg"
|
||||
alt="{{ 'euFlag' | i18n }}"
|
||||
class="tw-mr-1 tw-w-6 tw-pb-1"
|
||||
/>
|
||||
{{ "euDomain" | i18n }}
|
||||
</a>
|
||||
</bit-menu>
|
||||
<span *ngIf="hasFlags" class="!tw-inline-block !tw-w-52 !tw-min-w-52">
|
||||
<label>{{ "region" | i18n }}:</label>
|
||||
<span *ngIf="hasFlags" class="!tw-inline-block !tw-min-w-52">
|
||||
<label>{{ "server" | i18n }}:</label>
|
||||
<a
|
||||
[routerLink]="[]"
|
||||
[bitMenuTriggerFor]="environmentOptions"
|
||||
class="tw-rounded-md tw-border tw-border-solid tw-border-secondary-300 tw-bg-background tw-p-2"
|
||||
>
|
||||
<img
|
||||
[src]="'../../images/' + selectedRegionImageName + '.png'"
|
||||
[src]="'../../images/' + selectedRegionImageName + '.svg'"
|
||||
alt="{{ 'selectedRegionFlag' | i18n }}"
|
||||
class="pb-1 mr-1 tw-ml-1"
|
||||
class="tw-mx-1 tw-pb-1"
|
||||
/><label class="tw-cursor-pointer !tw-font-normal"
|
||||
>{{ isEuServer ? ("eu" | i18n) : ("us" | i18n) }}
|
||||
>{{ isEuServer ? ("euDomain" | i18n) : ("usDomain" | i18n) }}
|
||||
<i class="bwi bwi-fw bwi-sm bwi-angle-down" aria-hidden="true"></i
|
||||
></label>
|
||||
</a>
|
||||
</span>
|
||||
<div *ngIf="!hasFlags">
|
||||
{{ "region" | i18n }}:
|
||||
{{ "server" | i18n }}:
|
||||
<a [routerLink]="[]" [bitMenuTriggerFor]="environmentOptions">
|
||||
<b>{{ isEuServer ? ("eu" | i18n) : ("us" | i18n) }}</b
|
||||
<b>{{ isEuServer ? ("euDomain" | i18n) : ("usDomain" | i18n) }}</b
|
||||
><i class="bwi bwi-fw bwi-sm bwi-angle-down" aria-hidden="true"></i>
|
||||
</a>
|
||||
</div>
|
||||
|
||||
@@ -35,9 +35,9 @@ export class EnvironmentSelectorComponent implements OnInit {
|
||||
|
||||
getRegionImage(): string {
|
||||
if (this.isEuServer) {
|
||||
return "eu_flag";
|
||||
return "flag-eu";
|
||||
} else {
|
||||
return "us_flag";
|
||||
return "flag-us";
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -17,7 +17,6 @@ import { FileDownloadService } from "@bitwarden/common/platform/abstractions/fil
|
||||
import { I18nService as I18nServiceAbstraction } from "@bitwarden/common/platform/abstractions/i18n.service";
|
||||
import { MessagingService as MessagingServiceAbstraction } from "@bitwarden/common/platform/abstractions/messaging.service";
|
||||
import { PlatformUtilsService as PlatformUtilsServiceAbstraction } from "@bitwarden/common/platform/abstractions/platform-utils.service";
|
||||
import { StateMigrationService as StateMigrationServiceAbstraction } from "@bitwarden/common/platform/abstractions/state-migration.service";
|
||||
import { StateService as BaseStateServiceAbstraction } from "@bitwarden/common/platform/abstractions/state.service";
|
||||
import { AbstractStorageService } from "@bitwarden/common/platform/abstractions/storage.service";
|
||||
import { StateFactory } from "@bitwarden/common/platform/factories/state-factory";
|
||||
@@ -27,7 +26,6 @@ import { PasswordRepromptService as PasswordRepromptServiceAbstraction } from "@
|
||||
import { PolicyListService } from "../admin-console/core/policy-list.service";
|
||||
import { HtmlStorageService } from "../core/html-storage.service";
|
||||
import { I18nService } from "../core/i18n.service";
|
||||
import { StateMigrationService } from "../core/state-migration.service";
|
||||
import { CollectionAdminService } from "../vault/core/collection-admin.service";
|
||||
import { PasswordRepromptService } from "../vault/core/password-reprompt.service";
|
||||
|
||||
@@ -84,11 +82,6 @@ import { WebPlatformUtilsService } from "./web-platform-utils.service";
|
||||
},
|
||||
{ provide: MessagingServiceAbstraction, useClass: BroadcasterMessagingService },
|
||||
{ provide: ModalServiceAbstraction, useClass: ModalService },
|
||||
{
|
||||
provide: StateMigrationServiceAbstraction,
|
||||
useClass: StateMigrationService,
|
||||
deps: [AbstractStorageService, SECURE_STORAGE, STATE_FACTORY],
|
||||
},
|
||||
StateService,
|
||||
{
|
||||
provide: BaseStateServiceAbstraction,
|
||||
|
||||
@@ -80,6 +80,9 @@ export class EventService {
|
||||
case EventType.User_MigratedKeyToKeyConnector:
|
||||
msg = humanReadableMsg = this.i18nService.t("migratedKeyConnector");
|
||||
break;
|
||||
case EventType.User_RequestedDeviceApproval:
|
||||
msg = humanReadableMsg = this.i18nService.t("requestedDeviceApproval");
|
||||
break;
|
||||
// Cipher
|
||||
case EventType.Cipher_Created:
|
||||
msg = this.i18nService.t("createdItemId", this.formatCipherId(ev, options));
|
||||
@@ -307,6 +310,20 @@ export class EventService {
|
||||
this.getShortId(ev.organizationUserId)
|
||||
);
|
||||
break;
|
||||
case EventType.OrganizationUser_ApprovedAuthRequest:
|
||||
msg = this.i18nService.t("approvedAuthRequest", this.formatOrgUserId(ev));
|
||||
humanReadableMsg = this.i18nService.t(
|
||||
"approvedAuthRequest",
|
||||
this.getShortId(ev.organizationUserId)
|
||||
);
|
||||
break;
|
||||
case EventType.OrganizationUser_RejectedAuthRequest:
|
||||
msg = this.i18nService.t("rejectedAuthRequest", this.formatOrgUserId(ev));
|
||||
humanReadableMsg = this.i18nService.t(
|
||||
"rejectedAuthRequest",
|
||||
this.getShortId(ev.organizationUserId)
|
||||
);
|
||||
break;
|
||||
// Org
|
||||
case EventType.Organization_Updated:
|
||||
msg = humanReadableMsg = this.i18nService.t("editedOrgSettings");
|
||||
|
||||
@@ -4,7 +4,6 @@ import { WINDOW } from "@bitwarden/angular/services/injection-tokens";
|
||||
import { AbstractThemingService } from "@bitwarden/angular/services/theming/theming.service.abstraction";
|
||||
import { EventUploadService as EventUploadServiceAbstraction } from "@bitwarden/common/abstractions/event/event-upload.service";
|
||||
import { NotificationsService as NotificationsServiceAbstraction } from "@bitwarden/common/abstractions/notifications.service";
|
||||
import { VaultTimeoutService as VaultTimeoutServiceAbstraction } from "@bitwarden/common/abstractions/vaultTimeout/vaultTimeout.service";
|
||||
import { TwoFactorService as TwoFactorServiceAbstraction } from "@bitwarden/common/auth/abstractions/two-factor.service";
|
||||
import { CryptoService as CryptoServiceAbstraction } from "@bitwarden/common/platform/abstractions/crypto.service";
|
||||
import { EncryptService } from "@bitwarden/common/platform/abstractions/encrypt.service";
|
||||
@@ -16,7 +15,7 @@ import { I18nService as I18nServiceAbstraction } from "@bitwarden/common/platfor
|
||||
import { StateService as StateServiceAbstraction } from "@bitwarden/common/platform/abstractions/state.service";
|
||||
import { ContainerService } from "@bitwarden/common/platform/services/container.service";
|
||||
import { EventUploadService } from "@bitwarden/common/services/event/event-upload.service";
|
||||
import { VaultTimeoutService as VaultTimeoutService } from "@bitwarden/common/services/vaultTimeout/vaultTimeout.service";
|
||||
import { VaultTimeoutService } from "@bitwarden/common/services/vault-timeout/vault-timeout.service";
|
||||
|
||||
import { I18nService } from "../core/i18n.service";
|
||||
|
||||
@@ -26,7 +25,7 @@ export class InitService {
|
||||
@Inject(WINDOW) private win: Window,
|
||||
private environmentService: EnvironmentServiceAbstraction,
|
||||
private notificationsService: NotificationsServiceAbstraction,
|
||||
private vaultTimeoutService: VaultTimeoutServiceAbstraction,
|
||||
private vaultTimeoutService: VaultTimeoutService,
|
||||
private i18nService: I18nServiceAbstraction,
|
||||
private eventUploadService: EventUploadServiceAbstraction,
|
||||
private twoFactorService: TwoFactorServiceAbstraction,
|
||||
@@ -48,7 +47,7 @@ export class InitService {
|
||||
this.environmentService.initialized = true;
|
||||
|
||||
setTimeout(() => this.notificationsService.init(), 3000);
|
||||
(this.vaultTimeoutService as VaultTimeoutService).init(true);
|
||||
await this.vaultTimeoutService.init(true);
|
||||
const locale = await this.stateService.getLocale();
|
||||
await (this.i18nService as I18nService).init(locale);
|
||||
(this.eventUploadService as EventUploadService).init(true);
|
||||
|
||||
@@ -23,7 +23,12 @@ export class RouterService {
|
||||
.subscribe((event: NavigationEnd) => {
|
||||
this.currentUrl = event.url;
|
||||
|
||||
let title = i18nService.t("pageTitle", "Bitwarden");
|
||||
let title = i18nService.t("bitWebVault");
|
||||
|
||||
if (this.currentUrl.includes("/sm/")) {
|
||||
title = i18nService.t("bitSecretsManager");
|
||||
}
|
||||
|
||||
let child = this.activatedRoute.firstChild;
|
||||
while (child.firstChild) {
|
||||
child = child.firstChild;
|
||||
|
||||
@@ -1,13 +0,0 @@
|
||||
import { StateMigrationService as BaseStateMigrationService } from "@bitwarden/common/platform/services/state-migration.service";
|
||||
|
||||
import { Account } from "./state/account";
|
||||
import { GlobalState } from "./state/global-state";
|
||||
|
||||
export class StateMigrationService extends BaseStateMigrationService<GlobalState, Account> {
|
||||
protected async migrationStateFrom1To2(): Promise<void> {
|
||||
await super.migrateStateFrom1To2();
|
||||
const globals = (await this.get<GlobalState>("global")) ?? this.stateFactory.createGlobal(null);
|
||||
globals.rememberEmail = (await this.get<boolean>("rememberEmail")) ?? globals.rememberEmail;
|
||||
await this.set("global", globals);
|
||||
}
|
||||
}
|
||||
@@ -7,7 +7,6 @@ import {
|
||||
STATE_SERVICE_USE_CACHE,
|
||||
} from "@bitwarden/angular/services/injection-tokens";
|
||||
import { LogService } from "@bitwarden/common/platform/abstractions/log.service";
|
||||
import { StateMigrationService } from "@bitwarden/common/platform/abstractions/state-migration.service";
|
||||
import {
|
||||
AbstractMemoryStorageService,
|
||||
AbstractStorageService,
|
||||
@@ -30,7 +29,6 @@ export class StateService extends BaseStateService<GlobalState, Account> {
|
||||
@Inject(SECURE_STORAGE) secureStorageService: AbstractStorageService,
|
||||
@Inject(MEMORY_STORAGE) memoryStorageService: AbstractMemoryStorageService,
|
||||
logService: LogService,
|
||||
stateMigrationService: StateMigrationService,
|
||||
@Inject(STATE_FACTORY) stateFactory: StateFactory<GlobalState, Account>,
|
||||
@Inject(STATE_SERVICE_USE_CACHE) useAccountCache = true
|
||||
) {
|
||||
@@ -39,7 +37,6 @@ export class StateService extends BaseStateService<GlobalState, Account> {
|
||||
secureStorageService,
|
||||
memoryStorageService,
|
||||
logService,
|
||||
stateMigrationService,
|
||||
stateFactory,
|
||||
useAccountCache
|
||||
);
|
||||
|
||||
@@ -1,24 +0,0 @@
|
||||
import { Injectable } from "@angular/core";
|
||||
import { ActivatedRouteSnapshot, CanActivate, Router } from "@angular/router";
|
||||
|
||||
import { AuthService } from "@bitwarden/common/auth/abstractions/auth.service";
|
||||
import { AuthenticationStatus } from "@bitwarden/common/auth/enums/authentication-status";
|
||||
|
||||
@Injectable({
|
||||
providedIn: "root",
|
||||
})
|
||||
export class HomeGuard implements CanActivate {
|
||||
constructor(private router: Router, private authService: AuthService) {}
|
||||
|
||||
async canActivate(route: ActivatedRouteSnapshot) {
|
||||
const authStatus = await this.authService.getAuthStatus();
|
||||
|
||||
if (authStatus === AuthenticationStatus.LoggedOut) {
|
||||
return this.router.createUrlTree(["/login"], { queryParams: route.queryParams });
|
||||
}
|
||||
if (authStatus === AuthenticationStatus.Locked) {
|
||||
return this.router.createUrlTree(["/lock"], { queryParams: route.queryParams });
|
||||
}
|
||||
return this.router.createUrlTree(["/vault"], { queryParams: route.queryParams });
|
||||
}
|
||||
}
|
||||
@@ -1,6 +1,6 @@
|
||||
<nav class="navbar navbar-expand navbar-dark" [ngClass]="{ 'nav-background-alt': selfHosted }">
|
||||
<div class="container">
|
||||
<a class="navbar-brand" routerLink="/" appA11yTitle="{{ 'pageTitle' | i18n : 'Bitwarden' }}">
|
||||
<a class="navbar-brand" routerLink="/" appA11yTitle="{{ 'bitWebVault' | i18n }}">
|
||||
<i class="bwi bwi-shield" aria-hidden="true"></i>
|
||||
</a>
|
||||
<div class="collapse navbar-collapse">
|
||||
@@ -84,7 +84,7 @@
|
||||
{{ "getApps" | i18n }}
|
||||
</a>
|
||||
<bit-menu-divider></bit-menu-divider>
|
||||
<button bitMenuItem type="button" (click)="lock()">
|
||||
<button *ngIf="canLock$ | async" bitMenuItem type="button" (click)="lock()">
|
||||
<i class="bwi bwi-fw bwi-lock" aria-hidden="true"></i>
|
||||
{{ "lockNow" | i18n }}
|
||||
</button>
|
||||
|
||||
@@ -1,6 +1,7 @@
|
||||
import { Component, OnInit } from "@angular/core";
|
||||
import { Observable } from "rxjs";
|
||||
import { map, Observable } from "rxjs";
|
||||
|
||||
import { VaultTimeoutSettingsService } from "@bitwarden/common/abstractions/vault-timeout/vault-timeout-settings.service";
|
||||
import {
|
||||
canAccessAdmin,
|
||||
OrganizationService,
|
||||
@@ -8,6 +9,7 @@ import {
|
||||
import { ProviderService } from "@bitwarden/common/admin-console/abstractions/provider.service";
|
||||
import { Organization } from "@bitwarden/common/admin-console/models/domain/organization";
|
||||
import { TokenService } from "@bitwarden/common/auth/abstractions/token.service";
|
||||
import { VaultTimeoutAction } from "@bitwarden/common/enums/vault-timeout-action.enum";
|
||||
import { Provider } from "@bitwarden/common/models/domain/provider";
|
||||
import { I18nService } from "@bitwarden/common/platform/abstractions/i18n.service";
|
||||
import { MessagingService } from "@bitwarden/common/platform/abstractions/messaging.service";
|
||||
@@ -26,6 +28,7 @@ export class NavbarComponent implements OnInit {
|
||||
providers: Provider[] = [];
|
||||
userId: string;
|
||||
organizations$: Observable<Organization[]>;
|
||||
canLock$: Observable<boolean>;
|
||||
|
||||
constructor(
|
||||
private messagingService: MessagingService,
|
||||
@@ -34,6 +37,7 @@ export class NavbarComponent implements OnInit {
|
||||
private providerService: ProviderService,
|
||||
private syncService: SyncService,
|
||||
private organizationService: OrganizationService,
|
||||
private vaultTimeoutSettingsService: VaultTimeoutSettingsService,
|
||||
private i18nService: I18nService
|
||||
) {
|
||||
this.selfHosted = this.platformUtilsService.isSelfHost();
|
||||
@@ -56,6 +60,9 @@ export class NavbarComponent implements OnInit {
|
||||
this.organizations$ = this.organizationService.memberOrganizations$.pipe(
|
||||
canAccessAdmin(this.i18nService)
|
||||
);
|
||||
this.canLock$ = this.vaultTimeoutSettingsService
|
||||
.availableVaultTimeoutActions$()
|
||||
.pipe(map((actions) => actions.includes(VaultTimeoutAction.Lock)));
|
||||
}
|
||||
|
||||
lock() {
|
||||
|
||||
@@ -64,7 +64,7 @@ export class ProductSwitcherContentComponent {
|
||||
isActive: !this.router.url.includes("/sm/"),
|
||||
},
|
||||
sm: {
|
||||
name: "Secrets Manager Beta",
|
||||
name: "Secrets Manager",
|
||||
icon: "bwi-cli",
|
||||
appRoute: ["/sm", smOrg?.id],
|
||||
marketingRoute: "https://bitwarden.com/products/secrets-manager/",
|
||||
|
||||
@@ -1,9 +1,15 @@
|
||||
import { NgModule } from "@angular/core";
|
||||
import { Route, RouterModule, Routes } from "@angular/router";
|
||||
|
||||
import { AuthGuard } from "@bitwarden/angular/auth/guards/auth.guard";
|
||||
import { LockGuard } from "@bitwarden/angular/auth/guards/lock.guard";
|
||||
import { UnauthGuard } from "@bitwarden/angular/auth/guards/unauth.guard";
|
||||
import {
|
||||
AuthGuard,
|
||||
lockGuard,
|
||||
redirectGuard,
|
||||
tdeDecryptionRequiredGuard,
|
||||
UnauthGuard,
|
||||
} from "@bitwarden/angular/auth/guards";
|
||||
import { canAccessFeature } from "@bitwarden/angular/guard/feature-flag.guard";
|
||||
import { FeatureFlag } from "@bitwarden/common/enums/feature-flag.enum";
|
||||
|
||||
import { SubscriptionRoutingModule } from "../app/billing/settings/subscription-routing.module";
|
||||
import { flagEnabled, Flags } from "../utils/flags";
|
||||
@@ -16,6 +22,7 @@ import { AcceptEmergencyComponent } from "./auth/accept-emergency.component";
|
||||
import { AcceptOrganizationComponent } from "./auth/accept-organization.component";
|
||||
import { HintComponent } from "./auth/hint.component";
|
||||
import { LockComponent } from "./auth/lock.component";
|
||||
import { LoginDecryptionOptionsComponent } from "./auth/login/login-decryption-options/login-decryption-options.component";
|
||||
import { LoginWithDeviceComponent } from "./auth/login/login-with-device.component";
|
||||
import { LoginComponent } from "./auth/login/login.component";
|
||||
import { RecoverDeleteComponent } from "./auth/recover-delete.component";
|
||||
@@ -31,7 +38,6 @@ import { UpdatePasswordComponent } from "./auth/update-password.component";
|
||||
import { UpdateTempPasswordComponent } from "./auth/update-temp-password.component";
|
||||
import { VerifyEmailTokenComponent } from "./auth/verify-email-token.component";
|
||||
import { VerifyRecoverDeleteComponent } from "./auth/verify-recover-delete.component";
|
||||
import { HomeGuard } from "./guards/home.guard";
|
||||
import { FrontendLayoutComponent } from "./layouts/frontend-layout.component";
|
||||
import { UserLayoutComponent } from "./layouts/user-layout.component";
|
||||
import { ReportsModule } from "./reports";
|
||||
@@ -56,7 +62,7 @@ const routes: Routes = [
|
||||
path: "",
|
||||
pathMatch: "full",
|
||||
children: [], // Children lets us have an empty component.
|
||||
canActivate: [HomeGuard], // Redirects either to vault, login or lock page.
|
||||
canActivate: [redirectGuard()], // Redirects either to vault, login, or lock page.
|
||||
},
|
||||
{ path: "login", component: LoginComponent, canActivate: [UnauthGuard] },
|
||||
{
|
||||
@@ -64,7 +70,20 @@ const routes: Routes = [
|
||||
component: LoginWithDeviceComponent,
|
||||
data: { titleId: "loginWithDevice" },
|
||||
},
|
||||
{
|
||||
path: "admin-approval-requested",
|
||||
component: LoginWithDeviceComponent,
|
||||
data: { titleId: "loginWithDevice" },
|
||||
},
|
||||
{ path: "2fa", component: TwoFactorComponent, canActivate: [UnauthGuard] },
|
||||
{
|
||||
path: "login-initiated",
|
||||
component: LoginDecryptionOptionsComponent,
|
||||
canActivate: [
|
||||
tdeDecryptionRequiredGuard(),
|
||||
canAccessFeature(FeatureFlag.TrustedDeviceEncryption),
|
||||
],
|
||||
},
|
||||
{
|
||||
path: "register",
|
||||
component: TrialInitiationComponent,
|
||||
@@ -96,7 +115,7 @@ const routes: Routes = [
|
||||
{
|
||||
path: "lock",
|
||||
component: LockComponent,
|
||||
canActivate: [LockGuard],
|
||||
canActivate: [lockGuard()],
|
||||
},
|
||||
{ path: "verify-email", component: VerifyEmailTokenComponent },
|
||||
{
|
||||
|
||||
@@ -1,7 +1,7 @@
|
||||
import { NgModule } from "@angular/core";
|
||||
import { RouterModule, Routes } from "@angular/router";
|
||||
|
||||
import { AuthGuard } from "@bitwarden/angular/auth/guards/auth.guard";
|
||||
import { AuthGuard } from "@bitwarden/angular/auth/guards";
|
||||
|
||||
import { HasPremiumGuard } from "../core/guards/has-premium.guard";
|
||||
|
||||
|
||||
@@ -1,9 +1,7 @@
|
||||
import { Component, ViewChild, ViewContainerRef } from "@angular/core";
|
||||
|
||||
import { ModalService } from "@bitwarden/angular/services/modal.service";
|
||||
import { ApiService } from "@bitwarden/common/abstractions/api.service";
|
||||
import { KeyConnectorService } from "@bitwarden/common/auth/abstractions/key-connector.service";
|
||||
import { StateService } from "@bitwarden/common/platform/abstractions/state.service";
|
||||
import { UserVerificationService } from "@bitwarden/common/auth/abstractions/user-verification/user-verification.service.abstraction";
|
||||
|
||||
import { DeauthorizeSessionsComponent } from "../auth/settings/deauthorize-sessions.component";
|
||||
|
||||
@@ -26,13 +24,11 @@ export class AccountComponent {
|
||||
|
||||
constructor(
|
||||
private modalService: ModalService,
|
||||
private apiService: ApiService,
|
||||
private keyConnectorService: KeyConnectorService,
|
||||
private stateService: StateService
|
||||
private userVerificationService: UserVerificationService
|
||||
) {}
|
||||
|
||||
async ngOnInit() {
|
||||
this.showChangeEmail = !(await this.keyConnectorService.getUsesKeyConnector());
|
||||
this.showChangeEmail = await this.userVerificationService.hasMasterPassword();
|
||||
}
|
||||
|
||||
async deauthorizeSessions() {
|
||||
|
||||
@@ -42,8 +42,8 @@ export class ChangeEmailComponent implements OnInit {
|
||||
}
|
||||
|
||||
async submit() {
|
||||
const hasEncKey = await this.cryptoService.hasEncKey();
|
||||
if (!hasEncKey) {
|
||||
const hasUserKey = await this.cryptoService.hasUserKey();
|
||||
if (!hasUserKey) {
|
||||
this.platformUtilsService.showToast("error", null, this.i18nService.t("updateKey"));
|
||||
return;
|
||||
}
|
||||
@@ -52,7 +52,10 @@ export class ChangeEmailComponent implements OnInit {
|
||||
if (!this.tokenSent) {
|
||||
const request = new EmailTokenRequest();
|
||||
request.newEmail = this.newEmail;
|
||||
request.masterPasswordHash = await this.cryptoService.hashPassword(this.masterPassword, null);
|
||||
request.masterPasswordHash = await this.cryptoService.hashMasterKey(
|
||||
this.masterPassword,
|
||||
await this.cryptoService.getOrDeriveMasterKey(this.masterPassword)
|
||||
);
|
||||
try {
|
||||
this.formPromise = this.apiService.postEmailToken(request);
|
||||
await this.formPromise;
|
||||
@@ -64,21 +67,24 @@ export class ChangeEmailComponent implements OnInit {
|
||||
const request = new EmailRequest();
|
||||
request.token = this.token;
|
||||
request.newEmail = this.newEmail;
|
||||
request.masterPasswordHash = await this.cryptoService.hashPassword(this.masterPassword, null);
|
||||
request.masterPasswordHash = await this.cryptoService.hashMasterKey(
|
||||
this.masterPassword,
|
||||
await this.cryptoService.getOrDeriveMasterKey(this.masterPassword)
|
||||
);
|
||||
const kdf = await this.stateService.getKdfType();
|
||||
const kdfConfig = await this.stateService.getKdfConfig();
|
||||
const newKey = await this.cryptoService.makeKey(
|
||||
const newMasterKey = await this.cryptoService.makeMasterKey(
|
||||
this.masterPassword,
|
||||
this.newEmail,
|
||||
kdf,
|
||||
kdfConfig
|
||||
);
|
||||
request.newMasterPasswordHash = await this.cryptoService.hashPassword(
|
||||
request.newMasterPasswordHash = await this.cryptoService.hashMasterKey(
|
||||
this.masterPassword,
|
||||
newKey
|
||||
newMasterKey
|
||||
);
|
||||
const newEncKey = await this.cryptoService.remakeEncKey(newKey);
|
||||
request.key = newEncKey[1].encryptedString;
|
||||
const newUserKey = await this.cryptoService.encryptUserKeyWithMasterKey(newMasterKey);
|
||||
request.key = newUserKey[1].encryptedString;
|
||||
try {
|
||||
this.formPromise = this.apiService.postEmail(request);
|
||||
await this.formPromise;
|
||||
|
||||
@@ -46,8 +46,8 @@ export class ChangeKdfConfirmationComponent {
|
||||
|
||||
async submit() {
|
||||
this.loading = true;
|
||||
const hasEncKey = await this.cryptoService.hasEncKey();
|
||||
if (!hasEncKey) {
|
||||
const hasUserKey = await this.cryptoService.hasUserKey();
|
||||
if (!hasUserKey) {
|
||||
this.platformUtilsService.showToast("error", null, this.i18nService.t("updateKey"));
|
||||
return;
|
||||
}
|
||||
@@ -75,17 +75,21 @@ export class ChangeKdfConfirmationComponent {
|
||||
request.kdfIterations = this.kdfConfig.iterations;
|
||||
request.kdfMemory = this.kdfConfig.memory;
|
||||
request.kdfParallelism = this.kdfConfig.parallelism;
|
||||
request.masterPasswordHash = await this.cryptoService.hashPassword(masterPassword, null);
|
||||
const masterKey = await this.cryptoService.getOrDeriveMasterKey(masterPassword);
|
||||
request.masterPasswordHash = await this.cryptoService.hashMasterKey(masterPassword, masterKey);
|
||||
const email = await this.stateService.getEmail();
|
||||
const newKey = await this.cryptoService.makeKey(
|
||||
const newMasterKey = await this.cryptoService.makeMasterKey(
|
||||
masterPassword,
|
||||
email,
|
||||
this.kdf,
|
||||
this.kdfConfig
|
||||
);
|
||||
request.newMasterPasswordHash = await this.cryptoService.hashPassword(masterPassword, newKey);
|
||||
const newEncKey = await this.cryptoService.remakeEncKey(newKey);
|
||||
request.key = newEncKey[1].encryptedString;
|
||||
request.newMasterPasswordHash = await this.cryptoService.hashMasterKey(
|
||||
masterPassword,
|
||||
newMasterKey
|
||||
);
|
||||
const newUserKey = await this.cryptoService.encryptUserKeyWithMasterKey(newMasterKey);
|
||||
request.key = newUserKey[1].encryptedString;
|
||||
|
||||
await this.apiService.postAccountKdf(request);
|
||||
}
|
||||
|
||||
@@ -1,6 +1,5 @@
|
||||
import { Component, OnInit } from "@angular/core";
|
||||
|
||||
import { DialogServiceAbstraction } from "@bitwarden/angular/services/dialog";
|
||||
import { KdfConfig } from "@bitwarden/common/auth/models/domain/kdf-config";
|
||||
import {
|
||||
DEFAULT_KDF_CONFIG,
|
||||
@@ -11,6 +10,7 @@ import {
|
||||
KdfType,
|
||||
} from "@bitwarden/common/enums";
|
||||
import { StateService } from "@bitwarden/common/platform/abstractions/state.service";
|
||||
import { DialogService } from "@bitwarden/components";
|
||||
|
||||
import { ChangeKdfConfirmationComponent } from "./change-kdf-confirmation.component";
|
||||
|
||||
@@ -25,7 +25,7 @@ export class ChangeKdfComponent implements OnInit {
|
||||
kdfOptions: any[] = [];
|
||||
recommendedPbkdf2Iterations = DEFAULT_PBKDF2_ITERATIONS;
|
||||
|
||||
constructor(private stateService: StateService, private dialogService: DialogServiceAbstraction) {
|
||||
constructor(private stateService: StateService, private dialogService: DialogService) {
|
||||
this.kdfOptions = [
|
||||
{ name: "PBKDF2 SHA-256", value: KdfType.PBKDF2_SHA256 },
|
||||
{ name: "Argon2id", value: KdfType.Argon2id },
|
||||
|
||||
@@ -27,37 +27,45 @@
|
||||
</app-vault-timeout-input>
|
||||
</div>
|
||||
</div>
|
||||
<div class="form-group">
|
||||
<label>{{ "vaultTimeoutAction" | i18n }}</label>
|
||||
<div class="form-check form-check-block">
|
||||
<input
|
||||
class="form-check-input"
|
||||
type="radio"
|
||||
name="vaultTimeoutAction"
|
||||
id="vaultTimeoutActionLock"
|
||||
value="{{ VaultTimeoutAction.Lock }}"
|
||||
formControlName="vaultTimeoutAction"
|
||||
/>
|
||||
<label class="form-check-label" for="vaultTimeoutActionLock">
|
||||
{{ "lock" | i18n }}
|
||||
<small>{{ "vaultTimeoutActionLockDesc" | i18n }}</small>
|
||||
</label>
|
||||
<ng-container *ngIf="availableVaultTimeoutActions$ | async as availableVaultTimeoutActions">
|
||||
<div *ngIf="availableVaultTimeoutActions.length > 1" class="form-group">
|
||||
<label>{{ "vaultTimeoutAction" | i18n }}</label>
|
||||
<div
|
||||
*ngIf="availableVaultTimeoutActions.includes(VaultTimeoutAction.Lock)"
|
||||
class="form-check form-check-block"
|
||||
>
|
||||
<input
|
||||
class="form-check-input"
|
||||
type="radio"
|
||||
name="vaultTimeoutAction"
|
||||
id="vaultTimeoutActionLock"
|
||||
value="{{ VaultTimeoutAction.Lock }}"
|
||||
formControlName="vaultTimeoutAction"
|
||||
/>
|
||||
<label class="form-check-label" for="vaultTimeoutActionLock">
|
||||
{{ "lock" | i18n }}
|
||||
<small>{{ "vaultTimeoutActionLockDesc" | i18n }}</small>
|
||||
</label>
|
||||
</div>
|
||||
<div
|
||||
*ngIf="availableVaultTimeoutActions.includes(VaultTimeoutAction.LogOut)"
|
||||
class="form-check mt-2 form-check-block"
|
||||
>
|
||||
<input
|
||||
class="form-check-input"
|
||||
type="radio"
|
||||
name="vaultTimeoutAction"
|
||||
id="vaultTimeoutActionLogOut"
|
||||
value="{{ VaultTimeoutAction.LogOut }}"
|
||||
formControlName="vaultTimeoutAction"
|
||||
/>
|
||||
<label class="form-check-label" for="vaultTimeoutActionLogOut">
|
||||
{{ "logOut" | i18n }}
|
||||
<small>{{ "vaultTimeoutActionLogOutDesc" | i18n }}</small>
|
||||
</label>
|
||||
</div>
|
||||
</div>
|
||||
<div class="form-check mt-2 form-check-block">
|
||||
<input
|
||||
class="form-check-input"
|
||||
type="radio"
|
||||
name="vaultTimeoutAction"
|
||||
id="vaultTimeoutActionLogOut"
|
||||
value="{{ VaultTimeoutAction.LogOut }}"
|
||||
formControlName="vaultTimeoutAction"
|
||||
/>
|
||||
<label class="form-check-label" for="vaultTimeoutActionLogOut">
|
||||
{{ "logOut" | i18n }}
|
||||
<small>{{ "vaultTimeoutActionLogOutDesc" | i18n }}</small>
|
||||
</label>
|
||||
</div>
|
||||
</div>
|
||||
</ng-container>
|
||||
<div class="row">
|
||||
<div class="col-6">
|
||||
<div class="form-group">
|
||||
|
||||
@@ -1,11 +1,10 @@
|
||||
import { Component, OnInit } from "@angular/core";
|
||||
import { FormBuilder } from "@angular/forms";
|
||||
import { concatMap, filter, map, Observable, Subject, takeUntil, tap } from "rxjs";
|
||||
import { concatMap, filter, firstValueFrom, map, Observable, Subject, takeUntil, tap } from "rxjs";
|
||||
|
||||
import { DialogServiceAbstraction, SimpleDialogType } from "@bitwarden/angular/services/dialog";
|
||||
import { AbstractThemingService } from "@bitwarden/angular/services/theming/theming.service.abstraction";
|
||||
import { SettingsService } from "@bitwarden/common/abstractions/settings.service";
|
||||
import { VaultTimeoutSettingsService } from "@bitwarden/common/abstractions/vaultTimeout/vaultTimeoutSettings.service";
|
||||
import { VaultTimeoutSettingsService } from "@bitwarden/common/abstractions/vault-timeout/vault-timeout-settings.service";
|
||||
import { PolicyService } from "@bitwarden/common/admin-console/abstractions/policy/policy.service.abstraction";
|
||||
import { PolicyType } from "@bitwarden/common/admin-console/enums";
|
||||
import { ThemeType } from "@bitwarden/common/enums";
|
||||
@@ -15,6 +14,7 @@ import { MessagingService } from "@bitwarden/common/platform/abstractions/messag
|
||||
import { PlatformUtilsService } from "@bitwarden/common/platform/abstractions/platform-utils.service";
|
||||
import { StateService } from "@bitwarden/common/platform/abstractions/state.service";
|
||||
import { Utils } from "@bitwarden/common/platform/misc/utils";
|
||||
import { DialogService } from "@bitwarden/components";
|
||||
|
||||
@Component({
|
||||
selector: "app-preferences",
|
||||
@@ -24,6 +24,8 @@ export class PreferencesComponent implements OnInit {
|
||||
// For use in template
|
||||
protected readonly VaultTimeoutAction = VaultTimeoutAction;
|
||||
|
||||
protected availableVaultTimeoutActions$: Observable<VaultTimeoutAction[]>;
|
||||
|
||||
vaultTimeoutPolicyCallout: Observable<{
|
||||
timeout: { hours: number; minutes: number };
|
||||
action: VaultTimeoutAction;
|
||||
@@ -55,7 +57,7 @@ export class PreferencesComponent implements OnInit {
|
||||
private messagingService: MessagingService,
|
||||
private themingService: AbstractThemingService,
|
||||
private settingsService: SettingsService,
|
||||
private dialogService: DialogServiceAbstraction
|
||||
private dialogService: DialogService
|
||||
) {
|
||||
this.vaultTimeoutOptions = [
|
||||
{ name: i18nService.t("oneMinute"), value: 1 },
|
||||
@@ -89,6 +91,9 @@ export class PreferencesComponent implements OnInit {
|
||||
}
|
||||
|
||||
async ngOnInit() {
|
||||
this.availableVaultTimeoutActions$ =
|
||||
this.vaultTimeoutSettingsService.availableVaultTimeoutActions$();
|
||||
|
||||
this.vaultTimeoutPolicyCallout = this.policyService.get$(PolicyType.MaximumVaultTimeout).pipe(
|
||||
filter((policy) => policy != null),
|
||||
map((policy) => {
|
||||
@@ -117,7 +122,7 @@ export class PreferencesComponent implements OnInit {
|
||||
const confirmed = await this.dialogService.openSimpleDialog({
|
||||
title: { key: "vaultTimeoutLogOutConfirmationTitle" },
|
||||
content: { key: "vaultTimeoutLogOutConfirmation" },
|
||||
type: SimpleDialogType.WARNING,
|
||||
type: "warning",
|
||||
});
|
||||
|
||||
if (!confirmed) {
|
||||
@@ -133,7 +138,9 @@ export class PreferencesComponent implements OnInit {
|
||||
.subscribe();
|
||||
const initialFormValues = {
|
||||
vaultTimeout: await this.vaultTimeoutSettingsService.getVaultTimeout(),
|
||||
vaultTimeoutAction: await this.vaultTimeoutSettingsService.getVaultTimeoutAction(),
|
||||
vaultTimeoutAction: await firstValueFrom(
|
||||
this.vaultTimeoutSettingsService.vaultTimeoutAction$()
|
||||
),
|
||||
enableFavicons: !(await this.settingsService.getDisableFavicon()),
|
||||
enableFullWidth: await this.stateService.getEnableFullWidth(),
|
||||
theme: await this.stateService.getTheme(),
|
||||
|
||||
@@ -2,7 +2,7 @@ import { Component, OnInit, ViewChild, ViewContainerRef } from "@angular/core";
|
||||
|
||||
import { ModalService } from "@bitwarden/angular/services/modal.service";
|
||||
import { ApiService } from "@bitwarden/common/abstractions/api.service";
|
||||
import { KeyConnectorService } from "@bitwarden/common/auth/abstractions/key-connector.service";
|
||||
import { UserVerificationService } from "@bitwarden/common/auth/abstractions/user-verification/user-verification.service.abstraction";
|
||||
import { StateService } from "@bitwarden/common/platform/abstractions/state.service";
|
||||
|
||||
import { ApiKeyComponent } from "./api-key.component";
|
||||
@@ -20,14 +20,14 @@ export class SecurityKeysComponent implements OnInit {
|
||||
showChangeKdf = true;
|
||||
|
||||
constructor(
|
||||
private keyConnectorService: KeyConnectorService,
|
||||
private userVerificationService: UserVerificationService,
|
||||
private stateService: StateService,
|
||||
private modalService: ModalService,
|
||||
private apiService: ApiService
|
||||
) {}
|
||||
|
||||
async ngOnInit() {
|
||||
this.showChangeKdf = !(await this.keyConnectorService.getUsesKeyConnector());
|
||||
this.showChangeKdf = await this.userVerificationService.hasMasterPassword();
|
||||
}
|
||||
|
||||
async viewUserApiKey() {
|
||||
|
||||
@@ -1,9 +1,9 @@
|
||||
import { NgModule } from "@angular/core";
|
||||
import { RouterModule, Routes } from "@angular/router";
|
||||
|
||||
import { ChangePasswordComponent } from "../auth/settings/change-password.component";
|
||||
import { TwoFactorSetupComponent } from "../auth/settings/two-factor-setup.component";
|
||||
|
||||
import { ChangePasswordComponent } from "./change-password.component";
|
||||
import { SecurityKeysComponent } from "./security-keys.component";
|
||||
import { SecurityComponent } from "./security.component";
|
||||
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
import { Component } from "@angular/core";
|
||||
|
||||
import { KeyConnectorService } from "@bitwarden/common/auth/abstractions/key-connector.service";
|
||||
import { UserVerificationService } from "@bitwarden/common/auth/abstractions/user-verification/user-verification.service.abstraction";
|
||||
|
||||
@Component({
|
||||
selector: "app-security",
|
||||
@@ -9,9 +9,9 @@ import { KeyConnectorService } from "@bitwarden/common/auth/abstractions/key-con
|
||||
export class SecurityComponent {
|
||||
showChangePassword = true;
|
||||
|
||||
constructor(private keyConnectorService: KeyConnectorService) {}
|
||||
constructor(private userVerificationService: UserVerificationService) {}
|
||||
|
||||
async ngOnInit() {
|
||||
this.showChangePassword = !(await this.keyConnectorService.getUsesKeyConnector());
|
||||
this.showChangePassword = await this.userVerificationService.hasMasterPassword();
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1,4 +1,4 @@
|
||||
<div class="modal fade" role="dialog" aria-modal="true" aria-labelledby="updateEncKeyTitle">
|
||||
<div class="modal fade" role="dialog" aria-modal="true" aria-labelledby="updateUserKeyTitle">
|
||||
<div class="modal-dialog modal-dialog-scrollable" role="document">
|
||||
<form
|
||||
class="modal-content"
|
||||
@@ -8,7 +8,7 @@
|
||||
ngNativeValidate
|
||||
>
|
||||
<div class="modal-header">
|
||||
<h1 class="modal-title" id="updateEncKeyTitle">{{ "updateEncryptionKey" | i18n }}</h1>
|
||||
<h1 class="modal-title" id="updateUserKeyTitle">{{ "updateEncryptionKey" | i18n }}</h1>
|
||||
<button
|
||||
type="button"
|
||||
class="close"
|
||||
|
||||
@@ -36,8 +36,8 @@ export class UpdateKeyComponent {
|
||||
) {}
|
||||
|
||||
async submit() {
|
||||
const hasEncKey = await this.cryptoService.hasEncKey();
|
||||
if (hasEncKey) {
|
||||
const hasUserKey = await this.cryptoService.hasUserKey();
|
||||
if (hasUserKey) {
|
||||
return;
|
||||
}
|
||||
|
||||
@@ -68,17 +68,20 @@ export class UpdateKeyComponent {
|
||||
}
|
||||
|
||||
private async makeRequest(): Promise<UpdateKeyRequest> {
|
||||
const key = await this.cryptoService.getKey();
|
||||
const encKey = await this.cryptoService.makeEncKey(key);
|
||||
const masterKey = await this.cryptoService.getMasterKey();
|
||||
const newUserKey = await this.cryptoService.makeUserKey(masterKey);
|
||||
const privateKey = await this.cryptoService.getPrivateKey();
|
||||
let encPrivateKey: EncString = null;
|
||||
if (privateKey != null) {
|
||||
encPrivateKey = await this.cryptoService.encrypt(privateKey, encKey[0]);
|
||||
encPrivateKey = await this.cryptoService.encrypt(privateKey, newUserKey[0]);
|
||||
}
|
||||
const request = new UpdateKeyRequest();
|
||||
request.privateKey = encPrivateKey != null ? encPrivateKey.encryptedString : null;
|
||||
request.key = encKey[1].encryptedString;
|
||||
request.masterPasswordHash = await this.cryptoService.hashPassword(this.masterPassword, null);
|
||||
request.key = newUserKey[1].encryptedString;
|
||||
request.masterPasswordHash = await this.cryptoService.hashMasterKey(
|
||||
this.masterPassword,
|
||||
await this.cryptoService.getOrDeriveMasterKey(this.masterPassword)
|
||||
);
|
||||
|
||||
await this.syncService.fullSync(true);
|
||||
|
||||
@@ -87,7 +90,7 @@ export class UpdateKeyComponent {
|
||||
if (folders[i].id == null) {
|
||||
continue;
|
||||
}
|
||||
const folder = await this.folderService.encrypt(folders[i], encKey[0]);
|
||||
const folder = await this.folderService.encrypt(folders[i], newUserKey[0]);
|
||||
request.folders.push(new FolderWithIdRequest(folder));
|
||||
}
|
||||
|
||||
@@ -96,7 +99,7 @@ export class UpdateKeyComponent {
|
||||
if (ciphers[i].organizationId != null) {
|
||||
continue;
|
||||
}
|
||||
const cipher = await this.cipherService.encrypt(ciphers[i], encKey[0]);
|
||||
const cipher = await this.cipherService.encrypt(ciphers[i], newUserKey[0]);
|
||||
request.ciphers.push(new CipherWithIdRequest(cipher));
|
||||
}
|
||||
|
||||
|
||||
@@ -9,7 +9,9 @@
|
||||
>
|
||||
<option *ngFor="let o of vaultTimeoutOptions" [ngValue]="o.value">{{ o.name }}</option>
|
||||
</select>
|
||||
<small class="form-text text-muted">{{ "vaultTimeoutDesc" | i18n }}</small>
|
||||
<small class="form-text text-muted">{{
|
||||
((canLockVault$ | async) ? "vaultTimeoutDesc" : "vaultTimeoutLogoutDesc") | i18n
|
||||
}}</small>
|
||||
</div>
|
||||
<div class="form-group" *ngIf="showCustom" formGroupName="custom">
|
||||
<label for="customVaultTimeout">{{ "customVaultTimeout" | i18n }}</label>
|
||||
|
||||
@@ -12,7 +12,7 @@ import { SharedModule } from "../../shared.module";
|
||||
})
|
||||
export class AccountFingerprintComponent implements OnInit {
|
||||
@Input() fingerprintMaterial: string;
|
||||
@Input() publicKeyBuffer: ArrayBuffer;
|
||||
@Input() publicKeyBuffer: Uint8Array;
|
||||
@Input() fingerprintLabel: string;
|
||||
|
||||
protected fingerprint: string;
|
||||
|
||||
@@ -26,6 +26,7 @@ import { RecoverTwoFactorComponent } from "../auth/recover-two-factor.component"
|
||||
import { RegisterFormModule } from "../auth/register-form/register-form.module";
|
||||
import { RemovePasswordComponent } from "../auth/remove-password.component";
|
||||
import { SetPasswordComponent } from "../auth/set-password.component";
|
||||
import { ChangePasswordComponent } from "../auth/settings/change-password.component";
|
||||
import { DeauthorizeSessionsComponent } from "../auth/settings/deauthorize-sessions.component";
|
||||
import { EmergencyAccessAddEditComponent } from "../auth/settings/emergency-access/emergency-access-add-edit.component";
|
||||
import { EmergencyAccessAttachmentsComponent } from "../auth/settings/emergency-access/emergency-access-attachments.component";
|
||||
@@ -76,12 +77,10 @@ import { ApiKeyComponent } from "../settings/api-key.component";
|
||||
import { ChangeAvatarComponent } from "../settings/change-avatar.component";
|
||||
import { ChangeEmailComponent } from "../settings/change-email.component";
|
||||
import { ChangeKdfModule } from "../settings/change-kdf/change-kdf.module";
|
||||
import { ChangePasswordComponent } from "../settings/change-password.component";
|
||||
import { DeleteAccountComponent } from "../settings/delete-account.component";
|
||||
import { DomainRulesComponent } from "../settings/domain-rules.component";
|
||||
import { LowKdfComponent } from "../settings/low-kdf.component";
|
||||
import { PreferencesComponent } from "../settings/preferences.component";
|
||||
import { PremiumComponent } from "../settings/premium.component";
|
||||
import { ProfileComponent } from "../settings/profile.component";
|
||||
import { PurgeVaultComponent } from "../settings/purge-vault.component";
|
||||
import { SecurityKeysComponent } from "../settings/security-keys.component";
|
||||
@@ -95,7 +94,6 @@ import { PasswordGeneratorHistoryComponent } from "../tools/password-generator-h
|
||||
import { AccessComponent } from "../tools/send/access.component";
|
||||
import { AddEditComponent as SendAddEditComponent } from "../tools/send/add-edit.component";
|
||||
import { EffluxDatesComponent as SendEffluxDatesComponent } from "../tools/send/efflux-dates.component";
|
||||
import { SendComponent } from "../tools/send/send.component";
|
||||
import { ToolsComponent } from "../tools/tools.component";
|
||||
import { PasswordRepromptComponent } from "../vault/components/password-reprompt.component";
|
||||
import { PremiumBadgeComponent } from "../vault/components/premium-badge.component";
|
||||
@@ -108,6 +106,7 @@ import { ShareComponent } from "../vault/individual-vault/share.component";
|
||||
import { AddEditComponent as OrgAddEditComponent } from "../vault/org-vault/add-edit.component";
|
||||
import { AttachmentsComponent as OrgAttachmentsComponent } from "../vault/org-vault/attachments.component";
|
||||
import { CollectionsComponent as OrgCollectionsComponent } from "../vault/org-vault/collections.component";
|
||||
import { PremiumComponent } from "../vault/settings/premium.component";
|
||||
|
||||
import { EnvironmentSelectorModule } from "./../components/environment-selector/environment-selector.module";
|
||||
import { AccountFingerprintComponent } from "./components/account-fingerprint/account-fingerprint.component";
|
||||
@@ -199,7 +198,6 @@ import { SharedModule } from "./shared.module";
|
||||
SecurityKeysComponent,
|
||||
SelectableAvatarComponent,
|
||||
SendAddEditComponent,
|
||||
SendComponent,
|
||||
SendEffluxDatesComponent,
|
||||
SetPasswordComponent,
|
||||
SettingsComponent,
|
||||
@@ -304,7 +302,6 @@ import { SharedModule } from "./shared.module";
|
||||
SecurityKeysComponent,
|
||||
SelectableAvatarComponent,
|
||||
SendAddEditComponent,
|
||||
SendComponent,
|
||||
SendEffluxDatesComponent,
|
||||
SetPasswordComponent,
|
||||
SettingsComponent,
|
||||
|
||||
Some files were not shown because too many files have changed in this diff Show More
Reference in New Issue
Block a user