mirror of
https://github.com/bitwarden/browser
synced 2026-02-13 15:03:26 +00:00
Merge branch 'main' into ps/extension-refresh
This commit is contained in:
@@ -272,6 +272,7 @@ export class BaseLoginDecryptionOptionsComponent implements OnInit, OnDestroy {
|
||||
|
||||
// this.loading to support clients without async-actions-support
|
||||
this.loading = true;
|
||||
// errors must be caught in child components to prevent navigation
|
||||
try {
|
||||
const { publicKey, privateKey } = await this.cryptoService.initAccount();
|
||||
const keysRequest = new KeysRequest(publicKey, privateKey.encryptedString);
|
||||
@@ -288,8 +289,6 @@ export class BaseLoginDecryptionOptionsComponent implements OnInit, OnDestroy {
|
||||
if (this.rememberDeviceForm.value.rememberDevice) {
|
||||
await this.deviceTrustService.trustDevice(this.activeAccountId);
|
||||
}
|
||||
} catch (error) {
|
||||
this.validationService.showError(error);
|
||||
} finally {
|
||||
this.loading = false;
|
||||
}
|
||||
|
||||
@@ -244,7 +244,7 @@ export class SetPasswordComponent extends BaseChangePasswordComponent {
|
||||
await this.userDecryptionOptionsService.setUserDecryptionOptions(userDecryptionOpts);
|
||||
await this.kdfConfigService.setKdfConfig(this.userId, this.kdfConfig);
|
||||
await this.masterPasswordService.setMasterKey(masterKey, this.userId);
|
||||
await this.cryptoService.setUserKey(userKey[0]);
|
||||
await this.cryptoService.setUserKey(userKey[0], this.userId);
|
||||
|
||||
// Set private key only for new JIT provisioned users in MP encryption orgs
|
||||
// Existing TDE users will have private key set on sync or on login
|
||||
@@ -253,7 +253,7 @@ export class SetPasswordComponent extends BaseChangePasswordComponent {
|
||||
this.forceSetPasswordReason !=
|
||||
ForceSetPasswordReason.TdeUserWithoutPasswordHasPasswordResetPermission
|
||||
) {
|
||||
await this.cryptoService.setPrivateKey(keyPair[1].encryptedString);
|
||||
await this.cryptoService.setPrivateKey(keyPair[1].encryptedString, this.userId);
|
||||
}
|
||||
|
||||
const localMasterKeyHash = await this.cryptoService.hashMasterKey(
|
||||
|
||||
@@ -14,7 +14,7 @@ export class LoggingErrorHandler extends ErrorHandler {
|
||||
override handleError(error: any): void {
|
||||
try {
|
||||
const logService = this.injector.get(LogService, null);
|
||||
logService.error(error);
|
||||
logService.error("Unhandled error in angular", error);
|
||||
} catch {
|
||||
super.handleError(error);
|
||||
}
|
||||
|
||||
@@ -656,7 +656,6 @@ const safeProviders: SafeProvider[] = [
|
||||
CipherServiceAbstraction,
|
||||
FolderServiceAbstraction,
|
||||
CollectionServiceAbstraction,
|
||||
CryptoServiceAbstraction,
|
||||
PlatformUtilsServiceAbstraction,
|
||||
MessagingServiceAbstraction,
|
||||
SearchServiceAbstraction,
|
||||
@@ -968,6 +967,7 @@ const safeProviders: SafeProvider[] = [
|
||||
StateProvider,
|
||||
SECURE_STORAGE,
|
||||
UserDecryptionOptionsServiceAbstraction,
|
||||
LogService,
|
||||
],
|
||||
}),
|
||||
safeProvider({
|
||||
|
||||
55
libs/angular/src/utils/component-route-swap.ts
Normal file
55
libs/angular/src/utils/component-route-swap.ts
Normal file
@@ -0,0 +1,55 @@
|
||||
import { Type } from "@angular/core";
|
||||
import { Route, Routes } from "@angular/router";
|
||||
|
||||
/**
|
||||
* Helper function to swap between two components based on an async condition. The async condition is evaluated
|
||||
* as an `CanMatchFn` and supports Angular dependency injection via `inject()`.
|
||||
*
|
||||
* @example
|
||||
* ```ts
|
||||
* const routes = [
|
||||
* ...componentRouteSwap(
|
||||
* defaultComponent,
|
||||
* altComponent,
|
||||
* async () => {
|
||||
* const configService = inject(ConfigService);
|
||||
* return configService.getFeatureFlag(FeatureFlag.SomeFlag);
|
||||
* },
|
||||
* {
|
||||
* path: 'some-path'
|
||||
* }
|
||||
* ),
|
||||
* // Other routes...
|
||||
* ];
|
||||
* ```
|
||||
*
|
||||
* @param defaultComponent - The default component to render.
|
||||
* @param altComponent - The alternate component to render when the condition is met.
|
||||
* @param shouldSwapFn - The async function to determine if the alternate component should be rendered.
|
||||
* @param options - The shared route options to apply to both components.
|
||||
*/
|
||||
export function componentRouteSwap(
|
||||
defaultComponent: Type<any>,
|
||||
altComponent: Type<any>,
|
||||
shouldSwapFn: () => Promise<boolean>,
|
||||
options: Route,
|
||||
): Routes {
|
||||
const defaultRoute = {
|
||||
...options,
|
||||
component: defaultComponent,
|
||||
};
|
||||
|
||||
const altRoute: Route = {
|
||||
...options,
|
||||
component: altComponent,
|
||||
canMatch: [
|
||||
async () => {
|
||||
return await shouldSwapFn();
|
||||
},
|
||||
...(options.canMatch ?? []),
|
||||
],
|
||||
};
|
||||
|
||||
// Return the alternate route first, so it is evaluated first.
|
||||
return [altRoute, defaultRoute];
|
||||
}
|
||||
@@ -289,6 +289,16 @@ export class AddEditComponent implements OnInit, OnDestroy {
|
||||
});
|
||||
}
|
||||
}
|
||||
// Only Admins can clone a cipher to different owner
|
||||
if (this.cloneMode && this.cipher.organizationId != null) {
|
||||
const cipherOrg = (await firstValueFrom(this.organizationService.memberOrganizations$)).find(
|
||||
(o) => o.id === this.cipher.organizationId,
|
||||
);
|
||||
|
||||
if (cipherOrg != null && !cipherOrg.isAdmin && !cipherOrg.permissions.editAnyCollection) {
|
||||
this.ownershipOptions = [{ name: cipherOrg.name, value: cipherOrg.id }];
|
||||
}
|
||||
}
|
||||
|
||||
// We don't want to copy passkeys when we clone a cipher
|
||||
if (this.cloneMode && this.cipher?.login?.hasFido2Credentials) {
|
||||
|
||||
Reference in New Issue
Block a user