1
0
mirror of https://github.com/bitwarden/browser synced 2025-12-19 09:43:23 +00:00

[PM-5189] Merging main into current branch

This commit is contained in:
Cesar Gonzalez
2024-03-21 11:18:00 -05:00
141 changed files with 1900 additions and 469 deletions

View File

@@ -15,8 +15,8 @@ import {
factory,
} from "../../../platform/background/service-factories/factory-options";
import {
messagingServiceFactory,
MessagingServiceInitOptions,
messagingServiceFactory,
} from "../../../platform/background/service-factories/messaging-service.factory";
import {
StateServiceInitOptions,

View File

@@ -43,6 +43,11 @@ import {
stateServiceFactory,
} from "../../../platform/background/service-factories/state-service.factory";
import {
UserDecryptionOptionsServiceInitOptions,
userDecryptionOptionsServiceFactory,
} from "./user-decryption-options-service.factory";
type DeviceTrustCryptoServiceFactoryOptions = FactoryOptions;
export type DeviceTrustCryptoServiceInitOptions = DeviceTrustCryptoServiceFactoryOptions &
@@ -54,7 +59,8 @@ export type DeviceTrustCryptoServiceInitOptions = DeviceTrustCryptoServiceFactor
AppIdServiceInitOptions &
DevicesApiServiceInitOptions &
I18nServiceInitOptions &
PlatformUtilsServiceInitOptions;
PlatformUtilsServiceInitOptions &
UserDecryptionOptionsServiceInitOptions;
export function deviceTrustCryptoServiceFactory(
cache: { deviceTrustCryptoService?: DeviceTrustCryptoServiceAbstraction } & CachedServices,
@@ -75,6 +81,7 @@ export function deviceTrustCryptoServiceFactory(
await devicesApiServiceFactory(cache, opts),
await i18nServiceFactory(cache, opts),
await platformUtilsServiceFactory(cache, opts),
await userDecryptionOptionsServiceFactory(cache, opts),
),
);
}

View File

@@ -9,7 +9,10 @@ import {
ApiServiceInitOptions,
} from "../../../platform/background/service-factories/api-service.factory";
import { appIdServiceFactory } from "../../../platform/background/service-factories/app-id-service.factory";
import { billingAccountProfileStateServiceFactory } from "../../../platform/background/service-factories/billing-account-profile-state-service.factory";
import {
billingAccountProfileStateServiceFactory,
BillingAccountProfileStateServiceInitOptions,
} from "../../../platform/background/service-factories/billing-account-profile-state-service.factory";
import {
CryptoServiceInitOptions,
cryptoServiceFactory,
@@ -70,6 +73,10 @@ import {
} from "./key-connector-service.factory";
import { tokenServiceFactory, TokenServiceInitOptions } from "./token-service.factory";
import { twoFactorServiceFactory, TwoFactorServiceInitOptions } from "./two-factor-service.factory";
import {
internalUserDecryptionOptionServiceFactory,
UserDecryptionOptionsServiceInitOptions,
} from "./user-decryption-options-service.factory";
type LoginStrategyServiceFactoryOptions = FactoryOptions;
@@ -90,7 +97,9 @@ export type LoginStrategyServiceInitOptions = LoginStrategyServiceFactoryOptions
PasswordStrengthServiceInitOptions &
DeviceTrustCryptoServiceInitOptions &
AuthRequestServiceInitOptions &
GlobalStateProviderInitOptions;
UserDecryptionOptionsServiceInitOptions &
GlobalStateProviderInitOptions &
BillingAccountProfileStateServiceInitOptions;
export function loginStrategyServiceFactory(
cache: { loginStrategyService?: LoginStrategyServiceAbstraction } & CachedServices,
@@ -119,6 +128,7 @@ export function loginStrategyServiceFactory(
await policyServiceFactory(cache, opts),
await deviceTrustCryptoServiceFactory(cache, opts),
await authRequestServiceFactory(cache, opts),
await internalUserDecryptionOptionServiceFactory(cache, opts),
await globalStateProviderFactory(cache, opts),
await billingAccountProfileStateServiceFactory(cache, opts),
),

View File

@@ -0,0 +1,46 @@
import {
InternalUserDecryptionOptionsServiceAbstraction,
UserDecryptionOptionsService,
UserDecryptionOptionsServiceAbstraction,
} from "@bitwarden/auth/common";
import {
CachedServices,
factory,
FactoryOptions,
} from "../../../platform/background/service-factories/factory-options";
import {
stateProviderFactory,
StateProviderInitOptions,
} from "../../../platform/background/service-factories/state-provider.factory";
type UserDecryptionOptionsServiceFactoryOptions = FactoryOptions;
export type UserDecryptionOptionsServiceInitOptions = UserDecryptionOptionsServiceFactoryOptions &
StateProviderInitOptions;
export function userDecryptionOptionsServiceFactory(
cache: {
userDecryptionOptionsService?: InternalUserDecryptionOptionsServiceAbstraction;
} & CachedServices,
opts: UserDecryptionOptionsServiceInitOptions,
): Promise<UserDecryptionOptionsServiceAbstraction> {
return factory(
cache,
"userDecryptionOptionsService",
opts,
async () => new UserDecryptionOptionsService(await stateProviderFactory(cache, opts)),
);
}
export async function internalUserDecryptionOptionServiceFactory(
cache: {
userDecryptionOptionsService?: InternalUserDecryptionOptionsServiceAbstraction;
} & CachedServices,
opts: UserDecryptionOptionsServiceInitOptions,
): Promise<InternalUserDecryptionOptionsServiceAbstraction> {
return (await userDecryptionOptionsServiceFactory(
cache,
opts,
)) as InternalUserDecryptionOptionsServiceAbstraction;
}

View File

@@ -32,6 +32,10 @@ import {
} from "../../../platform/background/service-factories/state-service.factory";
import { PinCryptoServiceInitOptions, pinCryptoServiceFactory } from "./pin-crypto-service.factory";
import {
userDecryptionOptionsServiceFactory,
UserDecryptionOptionsServiceInitOptions,
} from "./user-decryption-options-service.factory";
import {
UserVerificationApiServiceInitOptions,
userVerificationApiServiceFactory,
@@ -44,6 +48,7 @@ export type UserVerificationServiceInitOptions = UserVerificationServiceFactoryO
CryptoServiceInitOptions &
I18nServiceInitOptions &
UserVerificationApiServiceInitOptions &
UserDecryptionOptionsServiceInitOptions &
PinCryptoServiceInitOptions &
LogServiceInitOptions &
VaultTimeoutSettingsServiceInitOptions &
@@ -63,6 +68,7 @@ export function userVerificationServiceFactory(
await cryptoServiceFactory(cache, opts),
await i18nServiceFactory(cache, opts),
await userVerificationApiServiceFactory(cache, opts),
await userDecryptionOptionsServiceFactory(cache, opts),
await pinCryptoServiceFactory(cache, opts),
await logServiceFactory(cache, opts),
await vaultTimeoutSettingsServiceFactory(cache, opts),

View File

@@ -2,6 +2,7 @@ import { Component } from "@angular/core";
import { ActivatedRoute, Router } from "@angular/router";
import { SetPasswordComponent as BaseSetPasswordComponent } from "@bitwarden/angular/auth/components/set-password.component";
import { InternalUserDecryptionOptionsServiceAbstraction } from "@bitwarden/auth/common";
import { ApiService } from "@bitwarden/common/abstractions/api.service";
import { OrganizationApiServiceAbstraction } from "@bitwarden/common/admin-console/abstractions/organization/organization-api.service.abstraction";
import { OrganizationUserService } from "@bitwarden/common/admin-console/abstractions/organization-user/organization-user.service";
@@ -37,6 +38,7 @@ export class SetPasswordComponent extends BaseSetPasswordComponent {
route: ActivatedRoute,
organizationApiService: OrganizationApiServiceAbstraction,
organizationUserService: OrganizationUserService,
userDecryptionOptionsService: InternalUserDecryptionOptionsServiceAbstraction,
ssoLoginService: SsoLoginServiceAbstraction,
dialogService: DialogService,
) {
@@ -55,6 +57,7 @@ export class SetPasswordComponent extends BaseSetPasswordComponent {
stateService,
organizationApiService,
organizationUserService,
userDecryptionOptionsService,
ssoLoginService,
dialogService,
);

View File

@@ -3,7 +3,10 @@ import { ActivatedRoute, Router } from "@angular/router";
import { SsoComponent as BaseSsoComponent } from "@bitwarden/angular/auth/components/sso.component";
import { WINDOW } from "@bitwarden/angular/services/injection-tokens";
import { LoginStrategyServiceAbstraction } from "@bitwarden/auth/common";
import {
LoginStrategyServiceAbstraction,
UserDecryptionOptionsServiceAbstraction,
} from "@bitwarden/auth/common";
import { ApiService } from "@bitwarden/common/abstractions/api.service";
import { AuthService } from "@bitwarden/common/auth/abstractions/auth.service";
import { SsoLoginServiceAbstraction } from "@bitwarden/common/auth/abstractions/sso-login.service.abstraction";
@@ -39,6 +42,7 @@ export class SsoComponent extends BaseSsoComponent {
syncService: SyncService,
environmentService: EnvironmentService,
logService: LogService,
userDecryptionOptionsService: UserDecryptionOptionsServiceAbstraction,
configService: ConfigServiceAbstraction,
protected authService: AuthService,
@Inject(WINDOW) private win: Window,
@@ -56,6 +60,7 @@ export class SsoComponent extends BaseSsoComponent {
environmentService,
passwordGenerationService,
logService,
userDecryptionOptionsService,
configService,
);

View File

@@ -3,6 +3,7 @@ import { ActivatedRoute, Router } from "@angular/router";
import { TwoFactorOptionsComponent as BaseTwoFactorOptionsComponent } from "@bitwarden/angular/auth/components/two-factor-options.component";
import { TwoFactorService } from "@bitwarden/common/auth/abstractions/two-factor.service";
import { EnvironmentService } from "@bitwarden/common/platform/abstractions/environment.service";
import { I18nService } from "@bitwarden/common/platform/abstractions/i18n.service";
import { PlatformUtilsService } from "@bitwarden/common/platform/abstractions/platform-utils.service";
@@ -16,9 +17,10 @@ export class TwoFactorOptionsComponent extends BaseTwoFactorOptionsComponent {
router: Router,
i18nService: I18nService,
platformUtilsService: PlatformUtilsService,
environmentService: EnvironmentService,
private activatedRoute: ActivatedRoute,
) {
super(twoFactorService, router, i18nService, platformUtilsService, window);
super(twoFactorService, router, i18nService, platformUtilsService, window, environmentService);
}
close() {

View File

@@ -5,7 +5,10 @@ import { filter, first, takeUntil } from "rxjs/operators";
import { TwoFactorComponent as BaseTwoFactorComponent } from "@bitwarden/angular/auth/components/two-factor.component";
import { WINDOW } from "@bitwarden/angular/services/injection-tokens";
import { LoginStrategyServiceAbstraction } from "@bitwarden/auth/common";
import {
LoginStrategyServiceAbstraction,
UserDecryptionOptionsServiceAbstraction,
} from "@bitwarden/auth/common";
import { ApiService } from "@bitwarden/common/abstractions/api.service";
import { LoginService } from "@bitwarden/common/auth/abstractions/login.service";
import { SsoLoginServiceAbstraction } from "@bitwarden/common/auth/abstractions/sso-login.service.abstraction";
@@ -55,6 +58,7 @@ export class TwoFactorComponent extends BaseTwoFactorComponent {
twoFactorService: TwoFactorService,
appIdService: AppIdService,
loginService: LoginService,
userDecryptionOptionsService: UserDecryptionOptionsServiceAbstraction,
configService: ConfigServiceAbstraction,
ssoLoginService: SsoLoginServiceAbstraction,
private dialogService: DialogService,
@@ -75,6 +79,7 @@ export class TwoFactorComponent extends BaseTwoFactorComponent {
twoFactorService,
appIdService,
loginService,
userDecryptionOptionsService,
ssoLoginService,
configService,
);

View File

@@ -625,6 +625,22 @@ class AutofillOverlayContentService implements AutofillOverlayContentServiceInte
* Updates the position of the overlay button.
*/
private updateOverlayButtonPosition() {
// if (!this.overlayButtonElement) {
// this.createAutofillOverlayButton();
// this.updateCustomElementDefaultStyles(this.overlayButtonElement);
// }
//
// if (!this.isOverlayButtonVisible) {
// this.appendOverlayElementToBody(this.overlayButtonElement);
// this.isOverlayButtonVisible = true;
// this.setOverlayRepositionEventListeners();
// }
// // FIXME: Verify that this floating promise is intentional. If it is, add an explanatory comment and ensure there is proper error handling.
// // eslint-disable-next-line @typescript-eslint/no-floating-promises
// this.sendExtensionMessage("updateAutofillOverlayPosition", {
// overlayElement: AutofillOverlayElement.Button,
// });
void this.sendExtensionMessage("updateAutofillOverlayPosition", {
overlayElement: AutofillOverlayElement.Button,
});
@@ -634,6 +650,22 @@ class AutofillOverlayContentService implements AutofillOverlayContentServiceInte
* Updates the position of the overlay list.
*/
private updateOverlayListPosition() {
// if (!this.overlayListElement) {
// this.createAutofillOverlayList();
// this.updateCustomElementDefaultStyles(this.overlayListElement);
// }
//
// if (!this.isOverlayListVisible) {
// this.appendOverlayElementToBody(this.overlayListElement);
// this.isOverlayListVisible = true;
// }
//
// // FIXME: Verify that this floating promise is intentional. If it is, add an explanatory comment and ensure there is proper error handling.
// // eslint-disable-next-line @typescript-eslint/no-floating-promises
// this.sendExtensionMessage("updateAutofillOverlayPosition", {
// overlayElement: AutofillOverlayElement.List,
// });
void this.sendExtensionMessage("updateAutofillOverlayPosition", {
overlayElement: AutofillOverlayElement.List,
});

View File

@@ -5,6 +5,8 @@ import {
PinCryptoService,
LoginStrategyServiceAbstraction,
LoginStrategyService,
InternalUserDecryptionOptionsServiceAbstraction,
UserDecryptionOptionsService,
AuthRequestServiceAbstraction,
AuthRequestService,
} from "@bitwarden/auth/common";
@@ -242,6 +244,7 @@ export default class MainBackground {
environmentService: BrowserEnvironmentService;
cipherService: CipherServiceAbstraction;
folderService: InternalFolderServiceAbstraction;
userDecryptionOptionsService: InternalUserDecryptionOptionsServiceAbstraction;
collectionService: CollectionServiceAbstraction;
vaultTimeoutService: VaultTimeoutService;
vaultTimeoutSettingsService: VaultTimeoutSettingsServiceAbstraction;
@@ -539,6 +542,8 @@ export default class MainBackground {
};
})();
this.userDecryptionOptionsService = new UserDecryptionOptionsService(this.stateProvider);
this.devicesApiService = new DevicesApiServiceImplementation(this.apiService);
this.deviceTrustCryptoService = new DeviceTrustCryptoService(
this.keyGenerationService,
@@ -550,6 +555,7 @@ export default class MainBackground {
this.devicesApiService,
this.i18nService,
this.platformUtilsService,
this.userDecryptionOptionsService,
);
this.devicesService = new DevicesServiceImplementation(this.devicesApiService);
@@ -590,6 +596,7 @@ export default class MainBackground {
this.policyService,
this.deviceTrustCryptoService,
this.authRequestService,
this.userDecryptionOptionsService,
this.globalStateProvider,
this.billingAccountProfileStateService,
);
@@ -631,6 +638,7 @@ export default class MainBackground {
this.folderApiService = new FolderApiService(this.folderService, this.apiService);
this.vaultTimeoutSettingsService = new VaultTimeoutSettingsService(
this.userDecryptionOptionsService,
this.cryptoService,
this.tokenService,
this.policyService,
@@ -650,6 +658,7 @@ export default class MainBackground {
this.cryptoService,
this.i18nService,
this.userVerificationApiService,
this.userDecryptionOptionsService,
this.pinCryptoService,
this.logService,
this.vaultTimeoutSettingsService,
@@ -717,6 +726,7 @@ export default class MainBackground {
this.folderApiService,
this.organizationService,
this.sendApiService,
this.userDecryptionOptionsService,
this.avatarService,
logoutCallback,
this.billingAccountProfileStateService,

View File

@@ -9,6 +9,10 @@ import {
tokenServiceFactory,
TokenServiceInitOptions,
} from "../../auth/background/service-factories/token-service.factory";
import {
userDecryptionOptionsServiceFactory,
UserDecryptionOptionsServiceInitOptions,
} from "../../auth/background/service-factories/user-decryption-options-service.factory";
import {
biometricStateServiceFactory,
BiometricStateServiceInitOptions,
@@ -30,6 +34,7 @@ import {
type VaultTimeoutSettingsServiceFactoryOptions = FactoryOptions;
export type VaultTimeoutSettingsServiceInitOptions = VaultTimeoutSettingsServiceFactoryOptions &
UserDecryptionOptionsServiceInitOptions &
CryptoServiceInitOptions &
TokenServiceInitOptions &
PolicyServiceInitOptions &
@@ -46,6 +51,7 @@ export function vaultTimeoutSettingsServiceFactory(
opts,
async () =>
new VaultTimeoutSettingsService(
await userDecryptionOptionsServiceFactory(cache, opts),
await cryptoServiceFactory(cache, opts),
await tokenServiceFactory(cache, opts),
await policyServiceFactory(cache, opts),

View File

@@ -16,6 +16,7 @@ import { JslibModule } from "@bitwarden/angular/jslib.module";
import { ColorPasswordCountPipe } from "@bitwarden/angular/pipes/color-password-count.pipe";
import { ColorPasswordPipe } from "@bitwarden/angular/pipes/color-password.pipe";
import { AvatarModule, ButtonModule } from "@bitwarden/components";
import { ExportScopeCalloutComponent } from "@bitwarden/vault-export-ui";
import { AccountSwitcherComponent } from "../auth/popup/account-switching/account-switcher.component";
import { AccountComponent } from "../auth/popup/account-switching/account.component";
@@ -107,6 +108,7 @@ import "../platform/popup/locales";
AvatarModule,
AccountComponent,
ButtonModule,
ExportScopeCalloutComponent,
],
declarations: [
ActionButtonsComponent,

View File

@@ -82,7 +82,6 @@ import {
import { SearchService } from "@bitwarden/common/services/search.service";
import { PasswordGenerationServiceAbstraction } from "@bitwarden/common/tools/generator/password";
import { UsernameGenerationServiceAbstraction } from "@bitwarden/common/tools/generator/username";
import { PasswordStrengthServiceAbstraction } from "@bitwarden/common/tools/password-strength";
import { SendApiService } from "@bitwarden/common/tools/send/services/send-api.service";
import { SendApiService as SendApiServiceAbstraction } from "@bitwarden/common/tools/send/services/send-api.service.abstraction";
import {
@@ -96,7 +95,6 @@ import { FolderService as FolderServiceAbstraction } from "@bitwarden/common/vau
import { SyncService } from "@bitwarden/common/vault/abstractions/sync/sync.service.abstraction";
import { TotpService } from "@bitwarden/common/vault/abstractions/totp.service";
import { DialogService } from "@bitwarden/components";
import { ImportServiceAbstraction } from "@bitwarden/importer/core";
import { VaultExportServiceAbstraction } from "@bitwarden/vault-export-core";
import { UnauthGuardService } from "../../auth/popup/services";
@@ -292,11 +290,6 @@ function getBgService<T>(service: keyof MainBackground) {
},
deps: [DomSanitizer, ToastrService],
},
{
provide: PasswordStrengthServiceAbstraction,
useFactory: getBgService<PasswordStrengthServiceAbstraction>("passwordStrengthService"),
deps: [],
},
{
provide: PasswordGenerationServiceAbstraction,
useFactory: getBgService<PasswordGenerationServiceAbstraction>("passwordGenerationService"),
@@ -350,11 +343,6 @@ function getBgService<T>(service: keyof MainBackground) {
useFactory: getBgService<AutofillService>("autofillService"),
deps: [],
},
{
provide: ImportServiceAbstraction,
useFactory: getBgService<ImportServiceAbstraction>("importService"),
deps: [],
},
{
provide: VaultExportServiceAbstraction,
useFactory: getBgService<VaultExportServiceAbstraction>("exportService"),

View File

@@ -19,7 +19,7 @@
<app-callout type="warning" title="{{ 'vaultExportDisabled' | i18n }}" *ngIf="disabledByPolicy">
{{ "personalVaultExportPolicyInEffect" | i18n }}
</app-callout>
<app-export-scope-callout *ngIf="!disabledByPolicy"></app-export-scope-callout>
<tools-export-scope-callout *ngIf="!disabledByPolicy"></tools-export-scope-callout>
<div class="box">
<div class="box-content">

View File

@@ -4,6 +4,7 @@ import { ActivatedRoute } from "@angular/router";
import { first } from "rxjs/operators";
import { CollectionsComponent as BaseCollectionsComponent } from "@bitwarden/angular/admin-console/components/collections.component";
import { OrganizationService } from "@bitwarden/common/admin-console/abstractions/organization/organization.service.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";
@@ -21,11 +22,19 @@ export class CollectionsComponent extends BaseCollectionsComponent {
platformUtilsService: PlatformUtilsService,
i18nService: I18nService,
cipherService: CipherService,
organizationService: OrganizationService,
private route: ActivatedRoute,
private location: Location,
logService: LogService,
) {
super(collectionService, platformUtilsService, i18nService, cipherService, logService);
super(
collectionService,
platformUtilsService,
i18nService,
cipherService,
organizationService,
logService,
);
}
async ngOnInit() {

View File

@@ -20,6 +20,7 @@
"@bitwarden/vault-export-core": [
"../../libs/tools/export/vault-export/vault-export-core/src"
],
"@bitwarden/vault-export-ui": ["../../libs/tools/export/vault-export/vault-export-ui/src"],
"@bitwarden/importer/core": ["../../libs/importer/src"],
"@bitwarden/importer/ui": ["../../libs/importer/src/components"],
"@bitwarden/platform": ["../../libs/platform/src"],

View File

@@ -5,11 +5,13 @@ import { program } from "commander";
import * as jsdom from "jsdom";
import {
InternalUserDecryptionOptionsServiceAbstraction,
AuthRequestService,
LoginStrategyService,
LoginStrategyServiceAbstraction,
PinCryptoService,
PinCryptoServiceAbstraction,
UserDecryptionOptionsService,
} from "@bitwarden/auth/common";
import { EventCollectionService as EventCollectionServiceAbstraction } from "@bitwarden/common/abstractions/event/event-collection.service";
import { EventUploadService as EventUploadServiceAbstraction } from "@bitwarden/common/abstractions/event/event-upload.service";
@@ -169,6 +171,7 @@ export class Main {
eventUploadService: EventUploadServiceAbstraction;
passwordGenerationService: PasswordGenerationServiceAbstraction;
passwordStrengthService: PasswordStrengthServiceAbstraction;
userDecryptionOptionsService: InternalUserDecryptionOptionsServiceAbstraction;
totpService: TotpService;
containerService: ContainerService;
auditService: AuditService;
@@ -436,6 +439,8 @@ export class Main {
this.stateService,
);
this.userDecryptionOptionsService = new UserDecryptionOptionsService(this.stateProvider);
this.devicesApiService = new DevicesApiServiceImplementation(this.apiService);
this.deviceTrustCryptoService = new DeviceTrustCryptoService(
this.keyGenerationService,
@@ -447,6 +452,7 @@ export class Main {
this.devicesApiService,
this.i18nService,
this.platformUtilsService,
this.userDecryptionOptionsService,
);
this.authRequestService = new AuthRequestService(
@@ -478,6 +484,7 @@ export class Main {
this.policyService,
this.deviceTrustCryptoService,
this.authRequestService,
this.userDecryptionOptionsService,
this.globalStateProvider,
this.billingAccountProfileStateService,
);
@@ -529,6 +536,7 @@ export class Main {
this.biometricStateService = new DefaultBiometricStateService(this.stateProvider);
this.vaultTimeoutSettingsService = new VaultTimeoutSettingsService(
this.userDecryptionOptionsService,
this.cryptoService,
this.tokenService,
this.policyService,
@@ -548,6 +556,7 @@ export class Main {
this.cryptoService,
this.i18nService,
this.userVerificationApiService,
this.userDecryptionOptionsService,
this.pinCryptoService,
this.logService,
this.vaultTimeoutSettingsService,
@@ -589,6 +598,7 @@ export class Main {
this.folderApiService,
this.organizationService,
this.sendApiService,
this.userDecryptionOptionsService,
this.avatarService,
async (expired: boolean) => await this.logout(),
this.billingAccountProfileStateService,

View File

@@ -84,9 +84,9 @@ dependencies = [
[[package]]
name = "base64"
version = "0.21.5"
version = "0.22.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "35636a1494ede3b646cc98f74f8e62c773a38a659ebc777a2cf26b9b74171df9"
checksum = "9475866fec1451be56a3c2400fd081ff546538961565ccb5b7142cbd22bc7a51"
[[package]]
name = "bitflags"

View File

@@ -16,7 +16,7 @@ manual_test = []
aes = "=0.8.4"
anyhow = "=1.0.80"
arboard = { version = "=3.3.0", default-features = false, features = ["wayland-data-control"] }
base64 = "=0.21.5"
base64 = "=0.22.0"
cbc = { version = "=0.1.2", features = ["alloc"] }
napi = { version = "=2.13.3", features = ["async"] }
napi-derive = "=2.13.0"

View File

@@ -412,6 +412,23 @@
"enableBrowserIntegrationFingerprintDesc" | i18n
}}</small>
</div>
<div class="form-group">
<div class="checkbox">
<label for="enableHardwareAcceleration">
<input
id="enableHardwareAcceleration"
type="checkbox"
aria-describedby="enableHardwareAccelerationHelp"
formControlName="enableHardwareAcceleration"
(change)="saveHardwareAcceleration()"
/>
{{ "enableHardwareAcceleration" | i18n }}
</label>
</div>
<small id="enableHardwareAccelerationHelp" class="help-block">{{
"enableHardwareAccelerationDesc" | i18n
}}</small>
</div>
<div class="form-group" *ngIf="showDuckDuckGoIntegrationOption">
<div class="checkbox">
<label for="enableDuckDuckGoBrowserIntegration">

View File

@@ -24,6 +24,7 @@ import { DialogService } from "@bitwarden/components";
import { SetPinComponent } from "../../auth/components/set-pin.component";
import { flagEnabled } from "../../platform/flags";
import { DesktopSettingsService } from "../../platform/services/desktop-settings.service";
@Component({
selector: "app-settings",
@@ -96,6 +97,7 @@ export class SettingsComponent implements OnInit {
value: false,
disabled: true,
}),
enableHardwareAcceleration: true,
enableDuckDuckGoBrowserIntegration: false,
theme: [null as ThemeType | null],
locale: [null as string | null],
@@ -119,6 +121,7 @@ export class SettingsComponent implements OnInit {
private dialogService: DialogService,
private userVerificationService: UserVerificationServiceAbstraction,
private biometricStateService: BiometricStateService,
private desktopSettingsService: DesktopSettingsService,
) {
const isMac = this.platformUtilsService.getDevice() === DeviceType.MacOsDesktop;
@@ -259,6 +262,9 @@ export class SettingsComponent implements OnInit {
enableBrowserIntegration: await this.stateService.getEnableBrowserIntegration(),
enableBrowserIntegrationFingerprint:
await this.stateService.getEnableBrowserIntegrationFingerprint(),
enableHardwareAcceleration: await firstValueFrom(
this.desktopSettingsService.hardwareAcceleration$,
),
enableDuckDuckGoBrowserIntegration:
await this.stateService.getEnableDuckDuckGoBrowserIntegration(),
theme: await firstValueFrom(this.themeStateService.selectedTheme$),
@@ -655,6 +661,12 @@ export class SettingsComponent implements OnInit {
);
}
async saveHardwareAcceleration() {
await this.desktopSettingsService.setHardwareAcceleration(
this.form.value.enableHardwareAcceleration,
);
}
async updateApproveLoginRequests() {
await this.stateService.setApproveLoginRequests(this.form.value.approveLoginRequests);
}

View File

@@ -8,6 +8,7 @@ import { NgModule } from "@angular/core";
import { ColorPasswordCountPipe } from "@bitwarden/angular/pipes/color-password-count.pipe";
import { ColorPasswordPipe } from "@bitwarden/angular/pipes/color-password.pipe";
import { DialogModule } from "@bitwarden/components";
import { ExportScopeCalloutComponent } from "@bitwarden/vault-export-ui";
import { AccessibilityCookieComponent } from "../auth/accessibility-cookie.component";
import { DeleteAccountComponent } from "../auth/delete-account.component";
@@ -61,6 +62,7 @@ import { SendComponent } from "./tools/send/send.component";
DialogModule,
DeleteAccountComponent,
UserVerificationComponent,
ExportScopeCalloutComponent,
],
declarations: [
AccessibilityCookieComponent,

View File

@@ -54,6 +54,7 @@ import { DialogService } from "@bitwarden/components";
import { LoginGuard } from "../../auth/guards/login.guard";
import { Account } from "../../models/account";
import { DesktopSettingsService } from "../../platform/services/desktop-settings.service";
import { ElectronCryptoService } from "../../platform/services/electron-crypto.service";
import { ElectronLogRendererService } from "../../platform/services/electron-log.renderer.service";
import {
@@ -212,6 +213,11 @@ const RELOAD_CALLBACK = new InjectionToken<() => any>("RELOAD_CALLBACK");
BiometricStateService,
],
},
{
provide: DesktopSettingsService,
useClass: DesktopSettingsService,
deps: [StateProvider],
},
],
})
export class ServicesModule {}

View File

@@ -9,7 +9,7 @@
>
{{ "personalVaultExportPolicyInEffect" | i18n }}
</app-callout>
<app-export-scope-callout *ngIf="!disabledByPolicy"></app-export-scope-callout>
<tools-export-scope-callout *ngIf="!disabledByPolicy"></tools-export-scope-callout>
<div class="box">
<h1 class="box-header" id="exportTitle">
{{ "exportVault" | i18n }}

View File

@@ -2,6 +2,7 @@ import { Component, NgZone, OnDestroy } from "@angular/core";
import { ActivatedRoute, Router } from "@angular/router";
import { SetPasswordComponent as BaseSetPasswordComponent } from "@bitwarden/angular/auth/components/set-password.component";
import { InternalUserDecryptionOptionsServiceAbstraction } from "@bitwarden/auth/common";
import { ApiService } from "@bitwarden/common/abstractions/api.service";
import { OrganizationApiServiceAbstraction } from "@bitwarden/common/admin-console/abstractions/organization/organization-api.service.abstraction";
import { OrganizationUserService } from "@bitwarden/common/admin-console/abstractions/organization-user/organization-user.service";
@@ -44,6 +45,7 @@ export class SetPasswordComponent extends BaseSetPasswordComponent implements On
stateService: StateService,
organizationApiService: OrganizationApiServiceAbstraction,
organizationUserService: OrganizationUserService,
userDecryptionOptionsService: InternalUserDecryptionOptionsServiceAbstraction,
ssoLoginService: SsoLoginServiceAbstraction,
dialogService: DialogService,
) {
@@ -62,6 +64,7 @@ export class SetPasswordComponent extends BaseSetPasswordComponent implements On
stateService,
organizationApiService,
organizationUserService,
userDecryptionOptionsService,
ssoLoginService,
dialogService,
);

View File

@@ -2,7 +2,10 @@ import { Component } from "@angular/core";
import { ActivatedRoute, Router } from "@angular/router";
import { SsoComponent as BaseSsoComponent } from "@bitwarden/angular/auth/components/sso.component";
import { LoginStrategyServiceAbstraction } from "@bitwarden/auth/common";
import {
LoginStrategyServiceAbstraction,
UserDecryptionOptionsServiceAbstraction,
} from "@bitwarden/auth/common";
import { ApiService } from "@bitwarden/common/abstractions/api.service";
import { SsoLoginServiceAbstraction } from "@bitwarden/common/auth/abstractions/sso-login.service.abstraction";
import { ConfigServiceAbstraction } from "@bitwarden/common/platform/abstractions/config/config.service.abstraction";
@@ -34,6 +37,7 @@ export class SsoComponent extends BaseSsoComponent {
environmentService: EnvironmentService,
passwordGenerationService: PasswordGenerationServiceAbstraction,
logService: LogService,
userDecryptionOptionsService: UserDecryptionOptionsServiceAbstraction,
configService: ConfigServiceAbstraction,
) {
super(
@@ -49,6 +53,7 @@ export class SsoComponent extends BaseSsoComponent {
environmentService,
passwordGenerationService,
logService,
userDecryptionOptionsService,
configService,
);
super.onSuccessfulLogin = async () => {

View File

@@ -3,6 +3,7 @@ import { Router } from "@angular/router";
import { TwoFactorOptionsComponent as BaseTwoFactorOptionsComponent } from "@bitwarden/angular/auth/components/two-factor-options.component";
import { TwoFactorService } from "@bitwarden/common/auth/abstractions/two-factor.service";
import { EnvironmentService } from "@bitwarden/common/platform/abstractions/environment.service";
import { I18nService } from "@bitwarden/common/platform/abstractions/i18n.service";
import { PlatformUtilsService } from "@bitwarden/common/platform/abstractions/platform-utils.service";
@@ -16,7 +17,8 @@ export class TwoFactorOptionsComponent extends BaseTwoFactorOptionsComponent {
router: Router,
i18nService: I18nService,
platformUtilsService: PlatformUtilsService,
environmentService: EnvironmentService,
) {
super(twoFactorService, router, i18nService, platformUtilsService, window);
super(twoFactorService, router, i18nService, platformUtilsService, window, environmentService);
}
}

View File

@@ -4,7 +4,10 @@ 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 { LoginStrategyServiceAbstraction } from "@bitwarden/auth/common";
import {
LoginStrategyServiceAbstraction,
UserDecryptionOptionsServiceAbstraction,
} from "@bitwarden/auth/common";
import { ApiService } from "@bitwarden/common/abstractions/api.service";
import { LoginService } from "@bitwarden/common/auth/abstractions/login.service";
import { SsoLoginServiceAbstraction } from "@bitwarden/common/auth/abstractions/sso-login.service.abstraction";
@@ -53,6 +56,7 @@ export class TwoFactorComponent extends BaseTwoFactorComponent {
twoFactorService: TwoFactorService,
appIdService: AppIdService,
loginService: LoginService,
userDecryptionOptionsService: UserDecryptionOptionsServiceAbstraction,
ssoLoginService: SsoLoginServiceAbstraction,
configService: ConfigServiceAbstraction,
@Inject(WINDOW) protected win: Window,
@@ -71,6 +75,7 @@ export class TwoFactorComponent extends BaseTwoFactorComponent {
twoFactorService,
appIdService,
loginService,
userDecryptionOptionsService,
ssoLoginService,
configService,
);

View File

@@ -1644,6 +1644,12 @@
"enableBrowserIntegrationFingerprintDesc": {
"message": "Add an additional layer of security by requiring fingerprint phrase confirmation when establishing a link between your desktop and browser. This requires user action and verification each time a connection is created."
},
"enableHardwareAcceleration": {
"message": "Use hardware acceleration"
},
"enableHardwareAccelerationDesc": {
"message": "By default this setting is ON. Turn OFF only if you experience graphical issues. Restart is required."
},
"approve": {
"message": "Approve"
},

View File

@@ -1,6 +1,7 @@
import * as path from "path";
import { app } from "electron";
import { firstValueFrom } from "rxjs";
import { TokenService as TokenServiceAbstraction } from "@bitwarden/common/auth/abstractions/token.service";
import { AccountServiceImplementation } from "@bitwarden/common/auth/services/account.service";
@@ -37,6 +38,7 @@ import { BiometricsService, BiometricsServiceAbstraction } from "./platform/main
import { ClipboardMain } from "./platform/main/clipboard.main";
import { DesktopCredentialStorageListener } from "./platform/main/desktop-credential-storage-listener";
import { MainCryptoFunctionService } from "./platform/main/main-crypto-function.service";
import { DesktopSettingsService } from "./platform/services/desktop-settings.service";
import { ElectronLogMainService } from "./platform/services/electron-log.main.service";
import { ELECTRON_SUPPORTS_SECURE_STORAGE } from "./platform/services/electron-platform-utils.service";
import { ElectronStateService } from "./platform/services/electron-state.service";
@@ -56,6 +58,7 @@ export class Main {
mainCryptoFunctionService: MainCryptoFunctionService;
desktopCredentialStorageListener: DesktopCredentialStorageListener;
migrationRunner: MigrationRunner;
desktopSettingsService: DesktopSettingsService;
tokenService: TokenServiceAbstraction;
windowMain: WindowMain;
@@ -189,6 +192,7 @@ export class Main {
this.messagingMain = new MessagingMain(this, this.stateService);
this.updaterMain = new UpdaterMain(this.i18nService, this.windowMain);
this.trayMain = new TrayMain(this.windowMain, this.i18nService, this.stateService);
this.desktopSettingsService = new DesktopSettingsService(stateProvider);
this.messagingService = new ElectronMainMessagingService(this.windowMain, (message) => {
this.messagingMain.onMessage(message);
@@ -237,6 +241,7 @@ export class Main {
// Run migrations first, then other things
this.migrationRunner.run().then(
async () => {
await this.toggleHardwareAcceleration();
await this.windowMain.init();
await this.i18nService.init();
this.messagingMain.init();
@@ -307,4 +312,15 @@ export class Main {
this.messagingService.send("deepLink", { urlString: s });
});
}
private async toggleHardwareAcceleration(): Promise<void> {
const hardwareAcceleration = await firstValueFrom(
this.desktopSettingsService.hardwareAcceleration$,
);
if (!hardwareAcceleration) {
this.logService.warning("Hardware acceleration is disabled");
app.disableHardwareAcceleration();
}
}
}

View File

@@ -0,0 +1,26 @@
import { map } from "rxjs";
import {
DESKTOP_SETTINGS_DISK,
KeyDefinition,
StateProvider,
} from "@bitwarden/common/platform/state";
export const HARDWARE_ACCELERATION = new KeyDefinition<boolean>(
DESKTOP_SETTINGS_DISK,
"hardwareAcceleration",
{
deserializer: (v: boolean) => v,
},
);
export class DesktopSettingsService {
private hwState = this.stateProvider.getGlobal(HARDWARE_ACCELERATION);
hardwareAcceleration$ = this.hwState.state$.pipe(map((v) => v ?? true));
constructor(private stateProvider: StateProvider) {}
async setHardwareAcceleration(enabled: boolean) {
await this.hwState.update(() => enabled);
}
}

View File

@@ -1,6 +1,7 @@
import { Component } from "@angular/core";
import { CollectionsComponent as BaseCollectionsComponent } from "@bitwarden/angular/admin-console/components/collections.component";
import { OrganizationService } from "@bitwarden/common/admin-console/abstractions/organization/organization.service.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";
@@ -17,8 +18,16 @@ export class CollectionsComponent extends BaseCollectionsComponent {
i18nService: I18nService,
collectionService: CollectionService,
platformUtilsService: PlatformUtilsService,
organizationService: OrganizationService,
logService: LogService,
) {
super(collectionService, platformUtilsService, i18nService, cipherService, logService);
super(
collectionService,
platformUtilsService,
i18nService,
cipherService,
organizationService,
logService,
);
}
}

View File

@@ -20,6 +20,7 @@
"@bitwarden/vault-export-core": [
"../../libs/tools/export/vault-export/vault-export-core/src"
],
"@bitwarden/vault-export-ui": ["../../libs/tools/export/vault-export/vault-export-ui/src"],
"@bitwarden/importer/core": ["../../libs/importer/src"],
"@bitwarden/importer/ui": ["../../libs/importer/src/components"],
"@bitwarden/node/*": ["../../libs/node/src/*"],

View File

@@ -1,10 +1,12 @@
import { Directive, ViewChild, ViewContainerRef } from "@angular/core";
import { firstValueFrom } from "rxjs";
import { SearchPipe } from "@bitwarden/angular/pipes/search.pipe";
import { UserNamePipe } from "@bitwarden/angular/pipes/user-name.pipe";
import { ModalService } from "@bitwarden/angular/services/modal.service";
import { ApiService } from "@bitwarden/common/abstractions/api.service";
import { SearchService } from "@bitwarden/common/abstractions/search.service";
import { OrganizationManagementPreferencesService } from "@bitwarden/common/admin-console/abstractions/organization-management-preferences/organization-management-preferences.service";
import {
OrganizationUserStatusType,
OrganizationUserType,
@@ -17,7 +19,6 @@ import { CryptoService } from "@bitwarden/common/platform/abstractions/crypto.se
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 { 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";
@@ -109,8 +110,8 @@ export abstract class BasePeopleComponent<
private logService: LogService,
private searchPipe: SearchPipe,
protected userNamePipe: UserNamePipe,
protected stateService: StateService,
protected dialogService: DialogService,
protected organizationManagementPreferencesService: OrganizationManagementPreferencesService,
) {}
abstract edit(user: UserType): void;
@@ -351,7 +352,9 @@ export abstract class BasePeopleComponent<
const publicKeyResponse = await this.apiService.getUserPublicKey(user.userId);
const publicKey = Utils.fromB64ToArray(publicKeyResponse.publicKey);
const autoConfirm = await this.stateService.getAutoConfirmFingerPrints();
const autoConfirm = await firstValueFrom(
this.organizationManagementPreferencesService.autoConfirmFingerPrints.state$,
);
if (autoConfirm == null || !autoConfirm) {
const [modal] = await this.modalService.openViewRef(
UserConfirmComponent,

View File

@@ -1,8 +1,8 @@
import { Component, EventEmitter, Input, OnInit, Output } from "@angular/core";
import { OrganizationManagementPreferencesService } from "@bitwarden/common/admin-console/abstractions/organization-management-preferences/organization-management-preferences.service";
import { CryptoService } from "@bitwarden/common/platform/abstractions/crypto.service";
import { LogService } from "@bitwarden/common/platform/abstractions/log.service";
import { StateService } from "@bitwarden/common/platform/abstractions/state.service";
@Component({
selector: "app-user-confirm",
@@ -22,7 +22,7 @@ export class UserConfirmComponent implements OnInit {
constructor(
private cryptoService: CryptoService,
private logService: LogService,
private stateService: StateService,
private organizationManagementPreferencesService: OrganizationManagementPreferencesService,
) {}
async ngOnInit() {
@@ -45,7 +45,7 @@ export class UserConfirmComponent implements OnInit {
}
if (this.dontAskAgain) {
await this.stateService.setAutoConfirmFingerprints(true);
await this.organizationManagementPreferencesService.autoConfirmFingerPrints.set(true);
}
this.onConfirmedUser.emit();

View File

@@ -21,6 +21,7 @@ import { ApiService } from "@bitwarden/common/abstractions/api.service";
import { SearchService } from "@bitwarden/common/abstractions/search.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";
import { OrganizationManagementPreferencesService } from "@bitwarden/common/admin-console/abstractions/organization-management-preferences/organization-management-preferences.service";
import { OrganizationUserService } from "@bitwarden/common/admin-console/abstractions/organization-user/organization-user.service";
import { OrganizationUserConfirmRequest } from "@bitwarden/common/admin-console/abstractions/organization-user/requests";
import {
@@ -43,7 +44,6 @@ import { CryptoService } from "@bitwarden/common/platform/abstractions/crypto.se
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 { StateService } from "@bitwarden/common/platform/abstractions/state.service";
import { ValidationService } from "@bitwarden/common/platform/abstractions/validation.service";
import { CollectionService } from "@bitwarden/common/vault/abstractions/collection.service";
import { SyncService } from "@bitwarden/common/vault/abstractions/sync/sync.service.abstraction";
@@ -117,7 +117,6 @@ export class PeopleComponent
searchPipe: SearchPipe,
userNamePipe: UserNamePipe,
private syncService: SyncService,
stateService: StateService,
private organizationService: OrganizationService,
private organizationApiService: OrganizationApiServiceAbstraction,
private organizationUserService: OrganizationUserService,
@@ -125,6 +124,7 @@ export class PeopleComponent
private router: Router,
private groupService: GroupService,
private collectionService: CollectionService,
organizationManagementPreferencesService: OrganizationManagementPreferencesService,
) {
super(
apiService,
@@ -137,8 +137,8 @@ export class PeopleComponent
logService,
searchPipe,
userNamePipe,
stateService,
dialogService,
organizationManagementPreferencesService,
);
}

View File

@@ -1,12 +1,19 @@
import { NgModule } from "@angular/core";
import { ExportScopeCalloutComponent } from "@bitwarden/vault-export-ui";
import { LooseComponentsModule, SharedModule } from "../../../../shared";
import { OrganizationVaultExportRoutingModule } from "./org-vault-export-routing.module";
import { OrganizationVaultExportComponent } from "./org-vault-export.component";
@NgModule({
imports: [SharedModule, LooseComponentsModule, OrganizationVaultExportRoutingModule],
imports: [
SharedModule,
LooseComponentsModule,
OrganizationVaultExportRoutingModule,
ExportScopeCalloutComponent,
],
declarations: [OrganizationVaultExportComponent],
})
export class OrganizationVaultExportModule {}

View File

@@ -3,9 +3,9 @@ import { Component, OnInit, Inject } from "@angular/core";
import { FormBuilder } from "@angular/forms";
import { ApiService } from "@bitwarden/common/abstractions/api.service";
import { OrganizationManagementPreferencesService } from "@bitwarden/common/admin-console/abstractions/organization-management-preferences/organization-management-preferences.service";
import { CryptoService } from "@bitwarden/common/platform/abstractions/crypto.service";
import { LogService } from "@bitwarden/common/platform/abstractions/log.service";
import { StateService } from "@bitwarden/common/platform/abstractions/state.service";
import { Utils } from "@bitwarden/common/platform/misc/utils";
import { DialogService } from "@bitwarden/components";
@@ -36,7 +36,7 @@ export class EmergencyAccessConfirmComponent implements OnInit {
private formBuilder: FormBuilder,
private apiService: ApiService,
private cryptoService: CryptoService,
private stateService: StateService,
protected organizationManagementPreferencesService: OrganizationManagementPreferencesService,
private logService: LogService,
private dialogRef: DialogRef<EmergencyAccessConfirmDialogResult>,
) {}
@@ -63,7 +63,7 @@ export class EmergencyAccessConfirmComponent implements OnInit {
}
if (this.confirmForm.get("dontAskAgain").value) {
await this.stateService.setAutoConfirmFingerprints(true);
await this.organizationManagementPreferencesService.autoConfirmFingerPrints.set(true);
}
try {

View File

@@ -3,6 +3,7 @@ import { lastValueFrom, Observable, firstValueFrom } from "rxjs";
import { UserNamePipe } from "@bitwarden/angular/pipes/user-name.pipe";
import { OrganizationService } from "@bitwarden/common/admin-console/abstractions/organization/organization.service.abstraction";
import { OrganizationManagementPreferencesService } from "@bitwarden/common/admin-console/abstractions/organization-management-preferences/organization-management-preferences.service";
import { BillingAccountProfileStateService } from "@bitwarden/common/billing/abstractions/account/billing-account-profile-state.service";
import { I18nService } from "@bitwarden/common/platform/abstractions/i18n.service";
import { LogService } from "@bitwarden/common/platform/abstractions/log.service";
@@ -64,6 +65,7 @@ export class EmergencyAccessComponent implements OnInit {
private organizationService: OrganizationService,
protected dialogService: DialogService,
billingAccountProfileStateService: BillingAccountProfileStateService,
protected organizationManagementPreferencesService: OrganizationManagementPreferencesService,
) {
this.canAccessPremium$ = billingAccountProfileStateService.hasPremiumFromAnySource$;
}
@@ -136,7 +138,9 @@ export class EmergencyAccessComponent implements OnInit {
return;
}
const autoConfirm = await this.stateService.getAutoConfirmFingerPrints();
const autoConfirm = await firstValueFrom(
this.organizationManagementPreferencesService.autoConfirmFingerPrints.state$,
);
if (autoConfirm == null || !autoConfirm) {
const dialogRef = EmergencyAccessConfirmComponent.open(this.dialogService, {
data: {

View File

@@ -3,7 +3,10 @@ import { ActivatedRoute, Router } from "@angular/router";
import { first } from "rxjs/operators";
import { SsoComponent as BaseSsoComponent } from "@bitwarden/angular/auth/components/sso.component";
import { LoginStrategyServiceAbstraction } from "@bitwarden/auth/common";
import {
LoginStrategyServiceAbstraction,
UserDecryptionOptionsServiceAbstraction,
} from "@bitwarden/auth/common";
import { ApiService } from "@bitwarden/common/abstractions/api.service";
import { OrgDomainApiServiceAbstraction } from "@bitwarden/common/admin-console/abstractions/organization-domain/org-domain-api.service.abstraction";
import { OrganizationDomainSsoDetailsResponse } from "@bitwarden/common/admin-console/abstractions/organization-domain/responses/organization-domain-sso-details.response";
@@ -41,6 +44,7 @@ export class SsoComponent extends BaseSsoComponent {
logService: LogService,
private orgDomainApiService: OrgDomainApiServiceAbstraction,
private validationService: ValidationService,
userDecryptionOptionsService: UserDecryptionOptionsServiceAbstraction,
configService: ConfigServiceAbstraction,
) {
super(
@@ -56,6 +60,7 @@ export class SsoComponent extends BaseSsoComponent {
environmentService,
passwordGenerationService,
logService,
userDecryptionOptionsService,
configService,
);
this.redirectUri = window.location.origin + "/sso-connector.html";

View File

@@ -3,6 +3,7 @@ import { Router } from "@angular/router";
import { TwoFactorOptionsComponent as BaseTwoFactorOptionsComponent } from "@bitwarden/angular/auth/components/two-factor-options.component";
import { TwoFactorService } from "@bitwarden/common/auth/abstractions/two-factor.service";
import { EnvironmentService } from "@bitwarden/common/platform/abstractions/environment.service";
import { I18nService } from "@bitwarden/common/platform/abstractions/i18n.service";
import { PlatformUtilsService } from "@bitwarden/common/platform/abstractions/platform-utils.service";
@@ -16,7 +17,8 @@ export class TwoFactorOptionsComponent extends BaseTwoFactorOptionsComponent {
router: Router,
i18nService: I18nService,
platformUtilsService: PlatformUtilsService,
environmentService: EnvironmentService,
) {
super(twoFactorService, router, i18nService, platformUtilsService, window);
super(twoFactorService, router, i18nService, platformUtilsService, window, environmentService);
}
}

View File

@@ -4,7 +4,10 @@ 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 { LoginStrategyServiceAbstraction } from "@bitwarden/auth/common";
import {
LoginStrategyServiceAbstraction,
UserDecryptionOptionsServiceAbstraction,
} from "@bitwarden/auth/common";
import { ApiService } from "@bitwarden/common/abstractions/api.service";
import { LoginService } from "@bitwarden/common/auth/abstractions/login.service";
import { SsoLoginServiceAbstraction } from "@bitwarden/common/auth/abstractions/sso-login.service.abstraction";
@@ -44,6 +47,7 @@ export class TwoFactorComponent extends BaseTwoFactorComponent implements OnDest
twoFactorService: TwoFactorService,
appIdService: AppIdService,
loginService: LoginService,
userDecryptionOptionsService: UserDecryptionOptionsServiceAbstraction,
ssoLoginService: SsoLoginServiceAbstraction,
configService: ConfigServiceAbstraction,
@Inject(WINDOW) protected win: Window,
@@ -62,6 +66,7 @@ export class TwoFactorComponent extends BaseTwoFactorComponent implements OnDest
twoFactorService,
appIdService,
loginService,
userDecryptionOptionsService,
ssoLoginService,
configService,
);

View File

@@ -5,10 +5,10 @@
<bit-callout type="danger" title="{{ 'vaultExportDisabled' | i18n }}" *ngIf="disabledByPolicy">
{{ "personalVaultExportPolicyInEffect" | i18n }}
</bit-callout>
<app-export-scope-callout
<tools-export-scope-callout
[organizationId]="organizationId"
*ngIf="!disabledByPolicy"
></app-export-scope-callout>
></tools-export-scope-callout>
<ng-container *ngIf="organizations$ | async as organizations">
<bit-form-field *ngIf="organizations.length > 0">

View File

@@ -1,12 +1,14 @@
import { NgModule } from "@angular/core";
import { ExportScopeCalloutComponent } from "@bitwarden/vault-export-ui";
import { LooseComponentsModule, SharedModule } from "../../shared";
import { ExportRoutingModule } from "./export-routing.module";
import { ExportComponent } from "./export.component";
@NgModule({
imports: [SharedModule, LooseComponentsModule, ExportRoutingModule],
imports: [SharedModule, LooseComponentsModule, ExportRoutingModule, ExportScopeCalloutComponent],
declarations: [ExportComponent],
})
export class ExportModule {}

View File

@@ -40,6 +40,7 @@
[(ngModel)]="$any(c).checked"
name="Collection[{{ i }}].Checked"
appStopProp
[disabled]="!c.canEditItems(this.organization, this.flexibleCollectionsV1Enabled)"
/>
</td>
<td>

View File

@@ -1,6 +1,7 @@
import { Component, OnDestroy } from "@angular/core";
import { CollectionsComponent as BaseCollectionsComponent } from "@bitwarden/angular/admin-console/components/collections.component";
import { OrganizationService } from "@bitwarden/common/admin-console/abstractions/organization/organization.service.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";
@@ -18,9 +19,17 @@ export class CollectionsComponent extends BaseCollectionsComponent implements On
platformUtilsService: PlatformUtilsService,
i18nService: I18nService,
cipherService: CipherService,
organizationSerivce: OrganizationService,
logService: LogService,
) {
super(collectionService, platformUtilsService, i18nService, cipherService, logService);
super(
collectionService,
platformUtilsService,
i18nService,
cipherService,
organizationSerivce,
logService,
);
}
ngOnDestroy() {
@@ -28,6 +37,9 @@ export class CollectionsComponent extends BaseCollectionsComponent implements On
}
check(c: CollectionView, select?: boolean) {
if (!c.canEditItems(this.organization, this.flexibleCollectionsV1Enabled)) {
return;
}
(c as any).checked = select == null ? !(c as any).checked : select;
}

View File

@@ -1,6 +1,7 @@
import { Component, Inject, OnDestroy, OnInit } from "@angular/core";
import { combineLatest, map, Observable, Subject, takeUntil } from "rxjs";
import { UserDecryptionOptionsServiceAbstraction } from "@bitwarden/auth/common";
import { ApiService } from "@bitwarden/common/abstractions/api.service";
import { OrganizationApiServiceAbstraction } from "@bitwarden/common/admin-console/abstractions/organization/organization-api.service.abstraction";
import { OrganizationUserService } from "@bitwarden/common/admin-console/abstractions/organization-user/organization-user.service";
@@ -12,7 +13,6 @@ import { Policy } from "@bitwarden/common/admin-console/models/domain/policy";
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 { StateService } from "@bitwarden/common/platform/abstractions/state.service";
import { SyncService } from "@bitwarden/common/vault/abstractions/sync/sync.service.abstraction";
import { DialogService } from "@bitwarden/components";
@@ -44,8 +44,8 @@ export class OrganizationOptionsComponent implements OnInit, OnDestroy {
private logService: LogService,
private organizationApiService: OrganizationApiServiceAbstraction,
private organizationUserService: OrganizationUserService,
private userDecryptionOptionsService: UserDecryptionOptionsServiceAbstraction,
private dialogService: DialogService,
private stateService: StateService,
) {}
async ngOnInit() {
@@ -56,7 +56,7 @@ export class OrganizationOptionsComponent implements OnInit, OnDestroy {
combineLatest([
this.organization$,
resetPasswordPolicies$,
this.stateService.getAccountDecryptionOptions(),
this.userDecryptionOptionsService.userDecryptionOptions$,
])
.pipe(takeUntil(this.destroy$))
.subscribe(([organization, resetPasswordPolicies, decryptionOptions]) => {

View File

@@ -1,6 +1,7 @@
import { Component } from "@angular/core";
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";
import { I18nService } from "@bitwarden/common/platform/abstractions/i18n.service";
import { LogService } from "@bitwarden/common/platform/abstractions/log.service";
@@ -25,15 +26,27 @@ export class CollectionsComponent extends BaseCollectionsComponent {
platformUtilsService: PlatformUtilsService,
i18nService: I18nService,
cipherService: CipherService,
organizationService: OrganizationService,
private apiService: ApiService,
logService: LogService,
) {
super(collectionService, platformUtilsService, i18nService, cipherService, logService);
super(
collectionService,
platformUtilsService,
i18nService,
cipherService,
organizationService,
logService,
);
this.allowSelectNone = true;
}
protected async loadCipher() {
if (!this.organization.canViewAllCollections) {
// if cipher is unassigned use apiService. We can see this by looking at this.collectionIds
if (
!this.organization.canEditAllCiphers(this.flexibleCollectionsV1Enabled) &&
this.collectionIds.length !== 0
) {
return await super.loadCipher();
}
const response = await this.apiService.getCipherAdmin(this.cipherId);
@@ -55,7 +68,10 @@ export class CollectionsComponent extends BaseCollectionsComponent {
}
protected saveCollections() {
if (this.organization.canEditAnyCollection) {
if (
this.organization.canEditAllCiphers(this.flexibleCollectionsV1Enabled) ||
this.collectionIds.length === 0
) {
const request = new CipherCollectionsRequest(this.cipherDomain.collectionIds);
return this.apiService.putCipherCollectionsAdmin(this.cipherId, request);
} else {

View File

@@ -137,6 +137,7 @@ export class VaultComponent implements OnInit, OnDestroy {
protected showCollectionAccessRestricted: boolean;
protected currentSearchText$: Observable<string>;
protected editableCollections$: Observable<CollectionView[]>;
protected allCollectionsWithoutUnassigned$: Observable<CollectionAdminView[]>;
protected showBulkEditCollectionAccess$ = this.configService.getFeatureFlag$(
FeatureFlag.BulkCollectionAccess,
false,
@@ -253,7 +254,7 @@ export class VaultComponent implements OnInit, OnDestroy {
this.currentSearchText$ = this.route.queryParams.pipe(map((queryParams) => queryParams.search));
const allCollectionsWithoutUnassigned$ = combineLatest([
this.allCollectionsWithoutUnassigned$ = combineLatest([
organizationId$.pipe(switchMap((orgId) => this.collectionAdminService.getAll(orgId))),
defer(() => this.collectionService.getAllDecrypted()),
]).pipe(
@@ -276,7 +277,7 @@ export class VaultComponent implements OnInit, OnDestroy {
shareReplay({ refCount: true, bufferSize: 1 }),
);
this.editableCollections$ = allCollectionsWithoutUnassigned$.pipe(
this.editableCollections$ = this.allCollectionsWithoutUnassigned$.pipe(
map((collections) => {
// Users that can edit all ciphers can implicitly edit all collections
if (this.organization.canEditAllCiphers(this.flexibleCollectionsV1Enabled)) {
@@ -287,7 +288,10 @@ export class VaultComponent implements OnInit, OnDestroy {
shareReplay({ refCount: true, bufferSize: 1 }),
);
const allCollections$ = combineLatest([organizationId$, allCollectionsWithoutUnassigned$]).pipe(
const allCollections$ = combineLatest([
organizationId$,
this.allCollectionsWithoutUnassigned$,
]).pipe(
map(([organizationId, allCollections]) => {
const noneCollection = new CollectionAdminView();
noneCollection.name = this.i18nService.t("unassigned");
@@ -680,16 +684,35 @@ export class VaultComponent implements OnInit, OnDestroy {
if (this.flexibleCollectionsV1Enabled) {
// V1 limits admins to only adding items to collections they have access to.
collections = await firstValueFrom(this.editableCollections$);
} else {
collections = (await firstValueFrom(this.vaultFilterService.filteredCollections$)).filter(
(c) => !c.readOnly && c.id != Unassigned,
collections = await firstValueFrom(
this.allCollectionsWithoutUnassigned$.pipe(
map((c) => {
return c.sort((a, b) => {
if (
a.canEditItems(this.organization, true) &&
!b.canEditItems(this.organization, true)
) {
return -1;
} else if (
!a.canEditItems(this.organization, true) &&
b.canEditItems(this.organization, true)
) {
return 1;
} else {
return a.name.localeCompare(b.name);
}
});
}),
),
);
} else {
collections = await firstValueFrom(this.allCollectionsWithoutUnassigned$);
}
const [modal] = await this.modalService.openViewRef(
CollectionsComponent,
this.collectionsModalRef,
(comp) => {
comp.flexibleCollectionsV1Enabled = this.flexibleCollectionsV1Enabled;
comp.collectionIds = cipher.collectionIds;
comp.collections = collections;
comp.organization = this.organization;

View File

@@ -15,6 +15,7 @@
"@bitwarden/vault-export-core": [
"../../libs/tools/export/vault-export/vault-export-core/src"
],
"@bitwarden/vault-export-ui": ["../../libs/tools/export/vault-export/vault-export-ui/src"],
"@bitwarden/importer/core": ["../../libs/importer/src"],
"@bitwarden/importer/ui": ["../../libs/importer/src/components"],
"@bitwarden/platform": ["../../libs/platform/src"],