mirror of
https://github.com/bitwarden/browser
synced 2026-02-05 11:13:44 +00:00
Merge branch 'main' of https://github.com/bitwarden/clients into PM-24304
This commit is contained in:
2
.github/CODEOWNERS
vendored
2
.github/CODEOWNERS
vendored
@@ -131,6 +131,7 @@ apps/web/src/translation-constants.ts @bitwarden/team-platform-dev
|
||||
.github/workflows/version-auto-bump.yml @bitwarden/team-platform-dev
|
||||
# ESLint custom rules
|
||||
libs/eslint @bitwarden/team-platform-dev
|
||||
libs/eslint/components @bitwarden/team-ui-foundation
|
||||
# Typescript tooling
|
||||
tsconfig.base.json @bitwarden/team-platform-dev
|
||||
nx.json @bitwarden/team-platform-dev
|
||||
@@ -155,6 +156,7 @@ apps/desktop/desktop_native/core/src/ssh_agent @bitwarden/team-autofill-dev @bit
|
||||
## UI Foundation ##
|
||||
.storybook @bitwarden/team-ui-foundation
|
||||
libs/components @bitwarden/team-ui-foundation
|
||||
libs/assets @bitwarden/team-ui-foundation
|
||||
libs/ui @bitwarden/team-ui-foundation
|
||||
apps/browser/src/platform/popup/layout @bitwarden/team-ui-foundation
|
||||
apps/browser/src/popup/app-routing.animations.ts @bitwarden/team-ui-foundation
|
||||
|
||||
1
.github/renovate.json5
vendored
1
.github/renovate.json5
vendored
@@ -197,6 +197,7 @@
|
||||
"nx",
|
||||
"oo7",
|
||||
"oslog",
|
||||
"parse5",
|
||||
"pin-project",
|
||||
"pkg",
|
||||
"postcss",
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
{
|
||||
"name": "@bitwarden/browser",
|
||||
"version": "2025.8.0",
|
||||
"version": "2025.8.1",
|
||||
"scripts": {
|
||||
"build": "npm run build:chrome",
|
||||
"build:chrome": "cross-env BROWSER=chrome MANIFEST_VERSION=3 NODE_OPTIONS=\"--max-old-space-size=8192\" webpack",
|
||||
|
||||
@@ -4131,15 +4131,11 @@
|
||||
"selectImportCollection": {
|
||||
"message": "Select a collection"
|
||||
},
|
||||
"importTargetHint": {
|
||||
"message": "Select this option if you want the imported file contents moved to a $DESTINATION$",
|
||||
"description": "Located as a hint under the import target. Will be appended by either folder or collection, depending if the user is importing into an individual or an organizational vault.",
|
||||
"placeholders": {
|
||||
"destination": {
|
||||
"content": "$1",
|
||||
"example": "folder or collection"
|
||||
}
|
||||
}
|
||||
"importTargetHintCollection": {
|
||||
"message": "Select this option if you want the imported file contents moved to a collection"
|
||||
},
|
||||
"importTargetHintFolder": {
|
||||
"message": "Select this option if you want the imported file contents moved to a folder"
|
||||
},
|
||||
"importUnassignedItemsError": {
|
||||
"message": "File contains unassigned items."
|
||||
@@ -5579,5 +5575,9 @@
|
||||
},
|
||||
"showLess": {
|
||||
"message": "Show less"
|
||||
},
|
||||
"moreBreadcrumbs": {
|
||||
"message": "More breadcrumbs",
|
||||
"description": "This is used in the context of a breadcrumb navigation, indicating that there are more items in the breadcrumb trail that are not currently displayed."
|
||||
}
|
||||
}
|
||||
|
||||
@@ -24,7 +24,6 @@ import { EnvironmentService } from "@bitwarden/common/platform/abstractions/envi
|
||||
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 { MessageSender } from "@bitwarden/common/platform/messaging";
|
||||
import { Utils } from "@bitwarden/common/platform/misc/utils";
|
||||
@@ -79,7 +78,6 @@ describe("AccountSecurityComponent", () => {
|
||||
{ provide: PlatformUtilsService, useValue: platformUtilsService },
|
||||
{ provide: PolicyService, useValue: policyService },
|
||||
{ provide: PopupRouterCacheService, useValue: mock<PopupRouterCacheService>() },
|
||||
{ provide: StateService, useValue: mock<StateService>() },
|
||||
{ provide: ToastService, useValue: mock<ToastService>() },
|
||||
{ provide: UserVerificationService, useValue: mock<UserVerificationService>() },
|
||||
{ provide: VaultTimeoutService, useValue: mock<VaultTimeoutService>() },
|
||||
|
||||
@@ -44,9 +44,9 @@ import {
|
||||
import { ConfigService } from "@bitwarden/common/platform/abstractions/config/config.service";
|
||||
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";
|
||||
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 { ValidationService } from "@bitwarden/common/platform/abstractions/validation.service";
|
||||
import {
|
||||
DialogRef,
|
||||
@@ -149,7 +149,6 @@ export class AccountSecurityComponent implements OnInit, OnDestroy {
|
||||
public messagingService: MessagingService,
|
||||
private environmentService: EnvironmentService,
|
||||
private keyService: KeyService,
|
||||
private stateService: StateService,
|
||||
private userVerificationService: UserVerificationService,
|
||||
private dialogService: DialogService,
|
||||
private changeDetectorRef: ChangeDetectorRef,
|
||||
@@ -159,6 +158,7 @@ export class AccountSecurityComponent implements OnInit, OnDestroy {
|
||||
private vaultNudgesService: NudgesService,
|
||||
private validationService: ValidationService,
|
||||
private configService: ConfigService,
|
||||
private logService: LogService,
|
||||
) {}
|
||||
|
||||
async ngOnInit() {
|
||||
@@ -683,10 +683,16 @@ export class AccountSecurityComponent implements OnInit, OnDestroy {
|
||||
}
|
||||
|
||||
async openAcctFingerprintDialog() {
|
||||
const activeUserId = await firstValueFrom(
|
||||
this.accountService.activeAccount$.pipe(map((a) => a?.id)),
|
||||
);
|
||||
const activeUserId = await firstValueFrom(getUserId(this.accountService.activeAccount$));
|
||||
const publicKey = await firstValueFrom(this.keyService.userPublicKey$(activeUserId));
|
||||
if (publicKey == null) {
|
||||
this.logService.error(
|
||||
"[AccountSecurityComponent] No public key available for the user: " +
|
||||
activeUserId +
|
||||
" fingerprint can't be displayed.",
|
||||
);
|
||||
return;
|
||||
}
|
||||
const fingerprint = await this.keyService.getFingerprint(activeUserId, publicKey);
|
||||
|
||||
const dialogRef = FingerprintDialogComponent.open(this.dialogService, {
|
||||
|
||||
@@ -41,6 +41,10 @@ describe("AutofillInlineMenuContentService", () => {
|
||||
autofillInlineMenuContentService as any,
|
||||
"sendExtensionMessage",
|
||||
);
|
||||
jest.spyOn(autofillInlineMenuContentService as any, "getPageIsOpaque");
|
||||
jest
|
||||
.spyOn(autofillInlineMenuContentService as any, "getPageTopLayerInUse")
|
||||
.mockResolvedValue(false);
|
||||
});
|
||||
|
||||
afterEach(() => {
|
||||
@@ -386,30 +390,45 @@ describe("AutofillInlineMenuContentService", () => {
|
||||
expect(globalThis.document.body.insertBefore).not.toHaveBeenCalled();
|
||||
});
|
||||
|
||||
it("closes the inline menu if the page has content in the top layer", async () => {
|
||||
document.querySelector("html").style.opacity = "1";
|
||||
document.body.style.opacity = "1";
|
||||
|
||||
jest
|
||||
.spyOn(autofillInlineMenuContentService as any, "getPageTopLayerInUse")
|
||||
.mockResolvedValue(true);
|
||||
|
||||
await autofillInlineMenuContentService["handlePageMutations"]([mockBodyMutationRecord]);
|
||||
|
||||
expect(autofillInlineMenuContentService["getPageIsOpaque"]).toHaveReturnedWith(true);
|
||||
expect(autofillInlineMenuContentService["closeInlineMenu"]).toHaveBeenCalled();
|
||||
});
|
||||
|
||||
it("closes the inline menu if the page body is not sufficiently opaque", async () => {
|
||||
document.querySelector("html").style.opacity = "0.9";
|
||||
document.body.style.opacity = "0";
|
||||
autofillInlineMenuContentService["handlePageMutations"]([mockBodyMutationRecord]);
|
||||
await autofillInlineMenuContentService["handlePageMutations"]([mockBodyMutationRecord]);
|
||||
|
||||
expect(autofillInlineMenuContentService["pageIsOpaque"]).toBe(false);
|
||||
expect(autofillInlineMenuContentService["getPageIsOpaque"]).toHaveReturnedWith(false);
|
||||
expect(autofillInlineMenuContentService["closeInlineMenu"]).toHaveBeenCalled();
|
||||
});
|
||||
|
||||
it("closes the inline menu if the page html is not sufficiently opaque", async () => {
|
||||
document.querySelector("html").style.opacity = "0.3";
|
||||
document.body.style.opacity = "0.7";
|
||||
autofillInlineMenuContentService["handlePageMutations"]([mockHTMLMutationRecord]);
|
||||
await autofillInlineMenuContentService["handlePageMutations"]([mockHTMLMutationRecord]);
|
||||
|
||||
expect(autofillInlineMenuContentService["pageIsOpaque"]).toBe(false);
|
||||
expect(autofillInlineMenuContentService["getPageIsOpaque"]).toHaveReturnedWith(false);
|
||||
expect(autofillInlineMenuContentService["closeInlineMenu"]).toHaveBeenCalled();
|
||||
});
|
||||
|
||||
it("does not close the inline menu if the page html and body is sufficiently opaque", async () => {
|
||||
document.querySelector("html").style.opacity = "0.9";
|
||||
document.body.style.opacity = "1";
|
||||
autofillInlineMenuContentService["handlePageMutations"]([mockBodyMutationRecord]);
|
||||
await autofillInlineMenuContentService["handlePageMutations"]([mockBodyMutationRecord]);
|
||||
await waitForIdleCallback();
|
||||
|
||||
expect(autofillInlineMenuContentService["pageIsOpaque"]).toBe(true);
|
||||
expect(autofillInlineMenuContentService["getPageIsOpaque"]).toHaveReturnedWith(true);
|
||||
expect(autofillInlineMenuContentService["closeInlineMenu"]).not.toHaveBeenCalled();
|
||||
});
|
||||
|
||||
|
||||
@@ -33,7 +33,6 @@ export class AutofillInlineMenuContentService implements AutofillInlineMenuConte
|
||||
private listElement?: HTMLElement;
|
||||
private htmlMutationObserver: MutationObserver;
|
||||
private bodyMutationObserver: MutationObserver;
|
||||
private pageIsOpaque = true;
|
||||
private inlineMenuElementsMutationObserver: MutationObserver;
|
||||
private containerElementMutationObserver: MutationObserver;
|
||||
private mutationObserverIterations = 0;
|
||||
@@ -52,7 +51,6 @@ export class AutofillInlineMenuContentService implements AutofillInlineMenuConte
|
||||
};
|
||||
|
||||
constructor() {
|
||||
this.checkPageOpacity();
|
||||
this.setupMutationObserver();
|
||||
}
|
||||
|
||||
@@ -405,20 +403,35 @@ export class AutofillInlineMenuContentService implements AutofillInlineMenuConte
|
||||
});
|
||||
};
|
||||
|
||||
private checkPageOpacity = () => {
|
||||
this.pageIsOpaque = this.getPageIsOpaque();
|
||||
private checkPageRisks = async () => {
|
||||
const pageIsOpaque = await this.getPageIsOpaque();
|
||||
const pageTopLayerInUse = await this.getPageTopLayerInUse();
|
||||
|
||||
if (!this.pageIsOpaque) {
|
||||
const risksFound = !pageIsOpaque || pageTopLayerInUse;
|
||||
|
||||
if (risksFound) {
|
||||
this.closeInlineMenu();
|
||||
}
|
||||
|
||||
return risksFound;
|
||||
};
|
||||
|
||||
/*
|
||||
* Checks for known risks at the page level
|
||||
*/
|
||||
private handlePageMutations = async (mutations: MutationRecord[]) => {
|
||||
if (mutations.some(({ type }) => type === "attributes")) {
|
||||
await this.checkPageRisks();
|
||||
}
|
||||
};
|
||||
|
||||
private handlePageMutations = (mutations: MutationRecord[]) => {
|
||||
for (const mutation of mutations) {
|
||||
if (mutation.type === "attributes") {
|
||||
this.checkPageOpacity();
|
||||
}
|
||||
}
|
||||
/**
|
||||
* Checks if the page top layer has content (will obscure/overlap the inline menu)
|
||||
*/
|
||||
private getPageTopLayerInUse = () => {
|
||||
const pageHasOpenPopover = !!globalThis.document.querySelector(":popover-open");
|
||||
|
||||
return pageHasOpenPopover;
|
||||
};
|
||||
|
||||
/**
|
||||
@@ -427,7 +440,7 @@ export class AutofillInlineMenuContentService implements AutofillInlineMenuConte
|
||||
* of parents below the body. Assumes the target element will be a direct child of the page
|
||||
* `body` (enforced elsewhere).
|
||||
*/
|
||||
private getPageIsOpaque() {
|
||||
private getPageIsOpaque = () => {
|
||||
// These are computed style values, so we don't need to worry about non-float values
|
||||
// for `opacity`, here
|
||||
const htmlOpacity = globalThis.window.getComputedStyle(
|
||||
@@ -441,17 +454,16 @@ export class AutofillInlineMenuContentService implements AutofillInlineMenuConte
|
||||
const opacityThreshold = 0.6;
|
||||
|
||||
return parseFloat(htmlOpacity) > opacityThreshold && parseFloat(bodyOpacity) > opacityThreshold;
|
||||
}
|
||||
};
|
||||
|
||||
/**
|
||||
* Processes the mutation of the element that contains the inline menu. Will trigger when an
|
||||
* idle moment in the execution of the main thread is detected.
|
||||
*/
|
||||
private processContainerElementMutation = async (containerElement: HTMLElement) => {
|
||||
// If the computed opacity of the body and parent is not sufficiently opaque, tear
|
||||
// down and prevent building the inline menu experience.
|
||||
this.checkPageOpacity();
|
||||
if (!this.pageIsOpaque) {
|
||||
// If the page contains risks, tear down and prevent building the inline menu experience.
|
||||
const pageRisksFound = await this.checkPageRisks();
|
||||
if (pageRisksFound) {
|
||||
return;
|
||||
}
|
||||
|
||||
|
||||
@@ -18,6 +18,7 @@ import {
|
||||
} from "rxjs";
|
||||
|
||||
import { JslibModule } from "@bitwarden/angular/jslib.module";
|
||||
import { NoResults } from "@bitwarden/assets/svg";
|
||||
import { AccountService } from "@bitwarden/common/auth/abstractions/account.service";
|
||||
import { getUserId } from "@bitwarden/common/auth/services/account.service";
|
||||
import { DomainSettingsService } from "@bitwarden/common/autofill/services/domain-settings.service";
|
||||
@@ -36,7 +37,6 @@ import { SecureNoteView } from "@bitwarden/common/vault/models/view/secure-note.
|
||||
import {
|
||||
ButtonModule,
|
||||
DialogService,
|
||||
Icons,
|
||||
ItemModule,
|
||||
NoItemsModule,
|
||||
SearchModule,
|
||||
@@ -102,7 +102,7 @@ export class Fido2Component implements OnInit, OnDestroy {
|
||||
protected equivalentDomainsURL: string;
|
||||
protected hostname: string;
|
||||
protected loading = false;
|
||||
protected noResultsIcon = Icons.NoResults;
|
||||
protected noResultsIcon = NoResults;
|
||||
protected passkeyAction: PasskeyActionValue = PasskeyActions.Register;
|
||||
protected PasskeyActions = PasskeyActions;
|
||||
protected hasSearched = false;
|
||||
|
||||
@@ -30,7 +30,7 @@
|
||||
</bit-item-content>
|
||||
<button
|
||||
*ngIf="i < fieldsEditThreshold"
|
||||
appA11yTitle="{{ 'remove' | i18n }}"
|
||||
label="{{ 'remove' | i18n }}"
|
||||
bitIconButton="bwi-minus-circle"
|
||||
buttonType="danger"
|
||||
size="small"
|
||||
|
||||
@@ -26,7 +26,7 @@
|
||||
</bit-item-content>
|
||||
<button
|
||||
*ngIf="i < fieldsEditThreshold"
|
||||
appA11yTitle="{{ 'remove' | i18n }}"
|
||||
label="{{ 'remove' | i18n }}"
|
||||
bitIconButton="bwi-minus-circle"
|
||||
buttonType="danger"
|
||||
size="small"
|
||||
|
||||
@@ -7,7 +7,7 @@ import {
|
||||
VaultTimeoutSettingsService,
|
||||
VaultTimeoutStringType,
|
||||
} from "@bitwarden/common/key-management/vault-timeout";
|
||||
import { NotificationsService } from "@bitwarden/common/platform/notifications";
|
||||
import { ServerNotificationsService } from "@bitwarden/common/platform/server-notifications";
|
||||
|
||||
const IdleInterval = 60 * 5; // 5 minutes
|
||||
|
||||
@@ -18,7 +18,7 @@ export default class IdleBackground {
|
||||
|
||||
constructor(
|
||||
private vaultTimeoutService: VaultTimeoutService,
|
||||
private notificationsService: NotificationsService,
|
||||
private serverNotificationsService: ServerNotificationsService,
|
||||
private accountService: AccountService,
|
||||
private vaultTimeoutSettingsService: VaultTimeoutSettingsService,
|
||||
) {
|
||||
@@ -32,9 +32,9 @@ export default class IdleBackground {
|
||||
|
||||
const idleHandler = (newState: string) => {
|
||||
if (newState === "active") {
|
||||
this.notificationsService.reconnectFromActivity();
|
||||
this.serverNotificationsService.reconnectFromActivity();
|
||||
} else {
|
||||
this.notificationsService.disconnectFromInactivity();
|
||||
this.serverNotificationsService.disconnectFromInactivity();
|
||||
}
|
||||
};
|
||||
if (this.idle.onStateChanged && this.idle.setDetectionInterval) {
|
||||
|
||||
@@ -111,21 +111,22 @@ import {
|
||||
ObservableStorageService,
|
||||
} from "@bitwarden/common/platform/abstractions/storage.service";
|
||||
import { SystemService as SystemServiceAbstraction } from "@bitwarden/common/platform/abstractions/system.service";
|
||||
import { ActionsService } from "@bitwarden/common/platform/actions/actions-service";
|
||||
import { IpcService } from "@bitwarden/common/platform/ipc";
|
||||
import { Message, MessageListener, MessageSender } from "@bitwarden/common/platform/messaging";
|
||||
// eslint-disable-next-line no-restricted-imports -- Used for dependency creation
|
||||
import { SubjectMessageSender } from "@bitwarden/common/platform/messaging/internal";
|
||||
import { Lazy } from "@bitwarden/common/platform/misc/lazy";
|
||||
import { SymmetricCryptoKey } from "@bitwarden/common/platform/models/domain/symmetric-crypto-key";
|
||||
import { NotificationsService } from "@bitwarden/common/platform/notifications";
|
||||
import { ServerNotificationsService } from "@bitwarden/common/platform/server-notifications";
|
||||
// eslint-disable-next-line no-restricted-imports -- Needed for service creation
|
||||
import {
|
||||
DefaultNotificationsService,
|
||||
DefaultServerNotificationsService,
|
||||
SignalRConnectionService,
|
||||
UnsupportedWebPushConnectionService,
|
||||
WebPushNotificationsApiService,
|
||||
WorkerWebPushConnectionService,
|
||||
} from "@bitwarden/common/platform/notifications/internal";
|
||||
} from "@bitwarden/common/platform/server-notifications/internal";
|
||||
import { AppIdService } from "@bitwarden/common/platform/services/app-id.service";
|
||||
import { ConfigApiService } from "@bitwarden/common/platform/services/config/config-api.service";
|
||||
import { DefaultConfigService } from "@bitwarden/common/platform/services/config/default-config.service";
|
||||
@@ -164,6 +165,8 @@ import { WindowStorageService } from "@bitwarden/common/platform/storage/window-
|
||||
import { SyncService } from "@bitwarden/common/platform/sync";
|
||||
// eslint-disable-next-line no-restricted-imports -- Needed for service creation
|
||||
import { DefaultSyncService } from "@bitwarden/common/platform/sync/internal";
|
||||
import { SystemNotificationsService } from "@bitwarden/common/platform/system-notifications/";
|
||||
import { UnsupportedSystemNotificationsService } from "@bitwarden/common/platform/system-notifications/unsupported-system-notifications.service";
|
||||
import { DefaultThemeStateService } from "@bitwarden/common/platform/theming/theme-state.service";
|
||||
import { ApiService } from "@bitwarden/common/services/api.service";
|
||||
import { AuditService } from "@bitwarden/common/services/audit.service";
|
||||
@@ -264,6 +267,7 @@ import { InlineMenuFieldQualificationService } from "../autofill/services/inline
|
||||
import { SafariApp } from "../browser/safariApp";
|
||||
import { BackgroundBrowserBiometricsService } from "../key-management/biometrics/background-browser-biometrics.service";
|
||||
import VaultTimeoutService from "../key-management/vault-timeout/vault-timeout.service";
|
||||
import { BrowserActionsService } from "../platform/actions/browser-actions.service";
|
||||
import { DefaultBadgeBrowserApi } from "../platform/badge/badge-browser-api";
|
||||
import { BadgeService } from "../platform/badge/badge.service";
|
||||
import { BrowserApi } from "../platform/browser/browser-api";
|
||||
@@ -292,6 +296,7 @@ import { BackgroundMemoryStorageService } from "../platform/storage/background-m
|
||||
import { BrowserStorageServiceProvider } from "../platform/storage/browser-storage-service.provider";
|
||||
import { OffscreenStorageService } from "../platform/storage/offscreen-storage.service";
|
||||
import { SyncServiceListener } from "../platform/sync/sync-service.listener";
|
||||
import { BrowserSystemNotificationService } from "../platform/system-notifications/browser-system-notification.service";
|
||||
import { fromChromeRuntimeMessaging } from "../platform/utils/from-chrome-runtime-messaging";
|
||||
import { VaultFilterService } from "../vault/services/vault-filter.service";
|
||||
|
||||
@@ -337,7 +342,9 @@ export default class MainBackground {
|
||||
importService: ImportServiceAbstraction;
|
||||
exportService: VaultExportServiceAbstraction;
|
||||
searchService: SearchServiceAbstraction;
|
||||
notificationsService: NotificationsService;
|
||||
serverNotificationsService: ServerNotificationsService;
|
||||
systemNotificationService: SystemNotificationsService;
|
||||
actionsService: ActionsService;
|
||||
stateService: StateServiceAbstraction;
|
||||
userNotificationSettingsService: UserNotificationSettingsServiceAbstraction;
|
||||
autofillSettingsService: AutofillSettingsServiceAbstraction;
|
||||
@@ -439,7 +446,6 @@ export default class MainBackground {
|
||||
private webRequestBackground: WebRequestBackground;
|
||||
|
||||
private syncTimeout: any;
|
||||
private isSafari: boolean;
|
||||
private nativeMessagingBackground: NativeMessagingBackground;
|
||||
|
||||
private popupViewCacheBackgroundService: PopupViewCacheBackgroundService;
|
||||
@@ -773,6 +779,7 @@ export default class MainBackground {
|
||||
this.accountService,
|
||||
this.kdfConfigService,
|
||||
this.keyService,
|
||||
this.stateProvider,
|
||||
);
|
||||
|
||||
this.passwordStrengthService = new PasswordStrengthService();
|
||||
@@ -1109,7 +1116,18 @@ export default class MainBackground {
|
||||
this.webPushConnectionService = new UnsupportedWebPushConnectionService();
|
||||
}
|
||||
|
||||
this.notificationsService = new DefaultNotificationsService(
|
||||
this.actionsService = new BrowserActionsService(this.logService, this.platformUtilsService);
|
||||
|
||||
if ("notifications" in chrome) {
|
||||
this.systemNotificationService = new BrowserSystemNotificationService(
|
||||
this.logService,
|
||||
this.platformUtilsService,
|
||||
);
|
||||
} else {
|
||||
this.systemNotificationService = new UnsupportedSystemNotificationsService();
|
||||
}
|
||||
|
||||
this.serverNotificationsService = new DefaultServerNotificationsService(
|
||||
this.logService,
|
||||
this.syncService,
|
||||
this.appIdService,
|
||||
@@ -1163,9 +1181,6 @@ export default class MainBackground {
|
||||
this.logService,
|
||||
);
|
||||
|
||||
// Other fields
|
||||
this.isSafari = this.platformUtilsService.isSafari();
|
||||
|
||||
// Background
|
||||
|
||||
this.fido2Background = new Fido2Background(
|
||||
@@ -1183,7 +1198,6 @@ export default class MainBackground {
|
||||
this,
|
||||
this.autofillService,
|
||||
this.platformUtilsService as BrowserPlatformUtilsService,
|
||||
this.notificationsService,
|
||||
this.autofillSettingsService,
|
||||
this.processReloadService,
|
||||
this.environmentService,
|
||||
@@ -1222,7 +1236,7 @@ export default class MainBackground {
|
||||
this.apiService,
|
||||
this.organizationService,
|
||||
this.authService,
|
||||
this.notificationsService,
|
||||
this.serverNotificationsService,
|
||||
messageListener,
|
||||
);
|
||||
|
||||
@@ -1296,7 +1310,7 @@ export default class MainBackground {
|
||||
|
||||
this.idleBackground = new IdleBackground(
|
||||
this.vaultTimeoutService,
|
||||
this.notificationsService,
|
||||
this.serverNotificationsService,
|
||||
this.accountService,
|
||||
this.vaultTimeoutSettingsService,
|
||||
);
|
||||
@@ -1354,7 +1368,7 @@ export default class MainBackground {
|
||||
this.endUserNotificationService = new DefaultEndUserNotificationService(
|
||||
this.stateProvider,
|
||||
this.apiService,
|
||||
this.notificationsService,
|
||||
this.serverNotificationsService,
|
||||
this.authService,
|
||||
this.logService,
|
||||
);
|
||||
@@ -1433,7 +1447,7 @@ export default class MainBackground {
|
||||
setTimeout(async () => {
|
||||
await this.fullSync(false);
|
||||
this.backgroundSyncService.init();
|
||||
this.notificationsService.startListening();
|
||||
this.serverNotificationsService.startListening();
|
||||
|
||||
this.taskService.listenForTaskNotifications();
|
||||
this.endUserNotificationService.listenForEndUserNotifications();
|
||||
@@ -1656,6 +1670,11 @@ export default class MainBackground {
|
||||
);
|
||||
}
|
||||
|
||||
/**
|
||||
* Opens the popup.
|
||||
*
|
||||
* @deprecated Migrating to the browser actions service.
|
||||
*/
|
||||
async openPopup() {
|
||||
const browserAction = BrowserApi.getBrowserAction();
|
||||
|
||||
@@ -1664,7 +1683,7 @@ export default class MainBackground {
|
||||
return;
|
||||
}
|
||||
|
||||
if (this.isSafari) {
|
||||
if (this.platformUtilsService.isSafari()) {
|
||||
await SafariApp.sendMessageToApp("showPopover", null, true);
|
||||
}
|
||||
}
|
||||
@@ -1691,7 +1710,9 @@ export default class MainBackground {
|
||||
|
||||
/**
|
||||
* Opens the popup to the given page
|
||||
*
|
||||
* @default ExtensionPageUrls.Index
|
||||
* @deprecated Migrating to the browser actions service.
|
||||
*/
|
||||
async openTheExtensionToPage(url: ExtensionPageUrls = ExtensionPageUrls.Index) {
|
||||
const isValidUrl = Object.values(ExtensionPageUrls).includes(url);
|
||||
|
||||
@@ -15,7 +15,6 @@ import { MessagingService } from "@bitwarden/common/platform/abstractions/messag
|
||||
import { MessageListener, isExternalMessage } from "@bitwarden/common/platform/messaging";
|
||||
import { devFlagEnabled } from "@bitwarden/common/platform/misc/flags";
|
||||
import { Utils } from "@bitwarden/common/platform/misc/utils";
|
||||
import { NotificationsService } from "@bitwarden/common/platform/notifications";
|
||||
import { CipherType } from "@bitwarden/common/vault/enums";
|
||||
import { VaultMessages } from "@bitwarden/common/vault/enums/vault-messages.enum";
|
||||
import { BiometricsCommands } from "@bitwarden/key-management";
|
||||
@@ -46,7 +45,6 @@ export default class RuntimeBackground {
|
||||
private main: MainBackground,
|
||||
private autofillService: AutofillService,
|
||||
private platformUtilsService: BrowserPlatformUtilsService,
|
||||
private notificationsService: NotificationsService,
|
||||
private autofillSettingsService: AutofillSettingsServiceAbstraction,
|
||||
private processReloadService: ProcessReloadServiceAbstraction,
|
||||
private environmentService: BrowserEnvironmentService,
|
||||
@@ -424,6 +422,11 @@ export default class RuntimeBackground {
|
||||
return await BrowserApi.tabsQuery({ url: `${urlObj.href}*` });
|
||||
}
|
||||
|
||||
/**
|
||||
* Opens the popup.
|
||||
*
|
||||
* @deprecated Migrating to the browser actions service.
|
||||
*/
|
||||
private async openPopup() {
|
||||
await this.main.openPopup();
|
||||
}
|
||||
@@ -450,7 +453,7 @@ export default class RuntimeBackground {
|
||||
/** Sends a message to each tab that the popup was opened */
|
||||
private announcePopupOpen() {
|
||||
const announceToAllTabs = async () => {
|
||||
const isOpen = await this.platformUtilsService.isViewOpen();
|
||||
const isOpen = await this.platformUtilsService.isPopupOpen();
|
||||
const tabs = await this.getBwTabs();
|
||||
|
||||
if (isOpen && tabs.length > 0) {
|
||||
|
||||
@@ -2,7 +2,7 @@
|
||||
"manifest_version": 2,
|
||||
"name": "__MSG_extName__",
|
||||
"short_name": "Bitwarden",
|
||||
"version": "2025.8.0",
|
||||
"version": "2025.8.1",
|
||||
"description": "__MSG_extDesc__",
|
||||
"default_locale": "en",
|
||||
"author": "Bitwarden Inc.",
|
||||
|
||||
@@ -3,7 +3,7 @@
|
||||
"minimum_chrome_version": "102.0",
|
||||
"name": "__MSG_extName__",
|
||||
"short_name": "Bitwarden",
|
||||
"version": "2025.8.0",
|
||||
"version": "2025.8.1",
|
||||
"description": "__MSG_extDesc__",
|
||||
"default_locale": "en",
|
||||
"author": "Bitwarden Inc.",
|
||||
|
||||
48
apps/browser/src/platform/actions/browser-actions.service.ts
Normal file
48
apps/browser/src/platform/actions/browser-actions.service.ts
Normal file
@@ -0,0 +1,48 @@
|
||||
import { DeviceType } from "@bitwarden/common/enums";
|
||||
import { PlatformUtilsService } from "@bitwarden/common/platform/abstractions/platform-utils.service";
|
||||
import { ActionsService } from "@bitwarden/common/platform/actions/actions-service";
|
||||
import { LogService } from "@bitwarden/logging";
|
||||
|
||||
import { SafariApp } from "../../browser/safariApp";
|
||||
import { BrowserApi } from "../browser/browser-api";
|
||||
|
||||
export class BrowserActionsService implements ActionsService {
|
||||
constructor(
|
||||
private logService: LogService,
|
||||
private platformUtilsService: PlatformUtilsService,
|
||||
) {}
|
||||
|
||||
async openPopup(): Promise<void> {
|
||||
const deviceType = this.platformUtilsService.getDevice();
|
||||
|
||||
try {
|
||||
switch (deviceType) {
|
||||
case DeviceType.FirefoxExtension:
|
||||
case DeviceType.ChromeExtension: {
|
||||
const browserAction = BrowserApi.getBrowserAction();
|
||||
|
||||
if ("openPopup" in browserAction && typeof browserAction.openPopup === "function") {
|
||||
await browserAction.openPopup();
|
||||
return;
|
||||
} else {
|
||||
this.logService.warning(
|
||||
`No openPopup function found on browser actions. On browser: ${deviceType} and manifest version: ${BrowserApi.manifestVersion}`,
|
||||
);
|
||||
}
|
||||
break;
|
||||
}
|
||||
case DeviceType.SafariExtension:
|
||||
await SafariApp.sendMessageToApp("showPopover", null, true);
|
||||
return;
|
||||
default:
|
||||
this.logService.warning(
|
||||
`Tried to open the popup from an unsupported device type: ${deviceType}`,
|
||||
);
|
||||
}
|
||||
} catch (e) {
|
||||
this.logService.error(
|
||||
`Failed to open the popup on ${DeviceType[deviceType]} with manifest ${BrowserApi.manifestVersion} and error: ${e}`,
|
||||
);
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -1,5 +1,3 @@
|
||||
// FIXME: Update this file to be type safe and remove this and next line
|
||||
// @ts-strict-ignore
|
||||
import { Observable } from "rxjs";
|
||||
|
||||
import { BrowserApi } from "./browser-api";
|
||||
@@ -26,13 +24,13 @@ export function fromChromeEvent<T extends unknown[]>(
|
||||
event: chrome.events.Event<(...args: T) => void>,
|
||||
): Observable<T> {
|
||||
return new Observable<T>((subscriber) => {
|
||||
const handler = (...args: T) => {
|
||||
const handler = (...args: readonly unknown[]) => {
|
||||
if (chrome.runtime.lastError) {
|
||||
subscriber.error(chrome.runtime.lastError);
|
||||
return;
|
||||
}
|
||||
|
||||
subscriber.next(args);
|
||||
subscriber.next(args as T);
|
||||
};
|
||||
|
||||
BrowserApi.addListener(event, handler);
|
||||
|
||||
@@ -2,12 +2,12 @@ import { Observable, Subscription } from "rxjs";
|
||||
|
||||
import { NotificationResponse } from "@bitwarden/common/models/response/notification.response";
|
||||
import { LogService } from "@bitwarden/common/platform/abstractions/log.service";
|
||||
import { NotificationsService } from "@bitwarden/common/platform/notifications";
|
||||
import { ServerNotificationsService } from "@bitwarden/common/platform/server-notifications";
|
||||
import { UserId } from "@bitwarden/common/types/guid";
|
||||
|
||||
// Eventually if we want to support listening to notifications from browser foreground we
|
||||
// Eventually if we want to support listening to server notifications from browser foreground we
|
||||
// will only ever create a single SignalR connection, likely messaging to the background to reuse its connection.
|
||||
export class ForegroundNotificationsService implements NotificationsService {
|
||||
export class ForegroundServerNotificationsService implements ServerNotificationsService {
|
||||
notifications$: Observable<readonly [NotificationResponse, UserId]>;
|
||||
|
||||
constructor(private readonly logService: LogService) {
|
||||
@@ -3,7 +3,7 @@
|
||||
bitIconButton="bwi-popout"
|
||||
size="small"
|
||||
type="button"
|
||||
appA11yTitle="{{ 'popOutNewWindow' | i18n }}"
|
||||
label="{{ 'popOutNewWindow' | i18n }}"
|
||||
[title]="'popOutNewWindow' | i18n"
|
||||
(click)="expand()"
|
||||
></button>
|
||||
|
||||
@@ -19,8 +19,7 @@
|
||||
bitIconButton="bwi-angle-left"
|
||||
type="button"
|
||||
*ngIf="showBackButton"
|
||||
[title]="'back' | i18n"
|
||||
[attr.aria-label]="'back' | i18n"
|
||||
[label]="'back' | i18n"
|
||||
[bitAction]="backAction"
|
||||
></button>
|
||||
<h1 *ngIf="pageTitle" bitTypography="h3" class="!tw-mb-0.5">
|
||||
|
||||
@@ -4,6 +4,16 @@ import { Component, importProvidersFrom } from "@angular/core";
|
||||
import { RouterModule } from "@angular/router";
|
||||
import { Meta, StoryObj, applicationConfig, moduleMetadata } from "@storybook/angular";
|
||||
|
||||
import {
|
||||
GeneratorActive,
|
||||
GeneratorInactive,
|
||||
SendActive,
|
||||
SendInactive,
|
||||
SettingsActive,
|
||||
SettingsInactive,
|
||||
VaultActive,
|
||||
VaultInactive,
|
||||
} from "@bitwarden/assets/svg";
|
||||
import { PolicyService } from "@bitwarden/common/admin-console/abstractions/policy/policy.service.abstraction";
|
||||
import { I18nService } from "@bitwarden/common/platform/abstractions/i18n.service";
|
||||
import { SendService } from "@bitwarden/common/tools/send/services/send.service.abstraction";
|
||||
@@ -13,7 +23,6 @@ import {
|
||||
BannerModule,
|
||||
ButtonModule,
|
||||
I18nMockService,
|
||||
Icons,
|
||||
IconButtonModule,
|
||||
ItemModule,
|
||||
NoItemsModule,
|
||||
@@ -67,14 +76,10 @@ class ExtensionPoppedContainerComponent {}
|
||||
<button type="button" bitBadge variant="primary">Fill</button>
|
||||
</bit-item-action>
|
||||
<bit-item-action>
|
||||
<button type="button" bitIconButton="bwi-clone" aria-label="Copy item"></button>
|
||||
<button type="button" bitIconButton="bwi-clone" label="Copy item"></button>
|
||||
</bit-item-action>
|
||||
<bit-item-action>
|
||||
<button
|
||||
type="button"
|
||||
bitIconButton="bwi-ellipsis-v"
|
||||
aria-label="More options"
|
||||
></button>
|
||||
<button type="button" bitIconButton="bwi-ellipsis-v" label="More options"></button>
|
||||
</bit-item-action>
|
||||
</ng-container>
|
||||
</bit-item>
|
||||
@@ -102,13 +107,7 @@ class MockAddButtonComponent {}
|
||||
@Component({
|
||||
selector: "mock-popout-button",
|
||||
template: `
|
||||
<button
|
||||
bitIconButton="bwi-popout"
|
||||
size="small"
|
||||
type="button"
|
||||
title="Pop out"
|
||||
aria-label="Pop out"
|
||||
></button>
|
||||
<button bitIconButton="bwi-popout" size="small" type="button" label="Pop out"></button>
|
||||
`,
|
||||
imports: [IconButtonModule],
|
||||
})
|
||||
@@ -278,7 +277,13 @@ class MockSettingsPageComponent {}
|
||||
<popup-footer slot="footer">
|
||||
<button type="button" bitButton buttonType="primary">Save</button>
|
||||
<button type="button" bitButton buttonType="secondary">Cancel</button>
|
||||
<button slot="end" type="button" buttonType="danger" bitIconButton="bwi-trash"></button>
|
||||
<button
|
||||
slot="end"
|
||||
type="button"
|
||||
buttonType="danger"
|
||||
bitIconButton="bwi-trash"
|
||||
label="Delete"
|
||||
></button>
|
||||
</popup-footer>
|
||||
</popup-page>
|
||||
`,
|
||||
@@ -408,26 +413,26 @@ const navButtons = (showBerry = false) => [
|
||||
{
|
||||
label: "vault",
|
||||
page: "/tabs/vault",
|
||||
icon: Icons.VaultInactive,
|
||||
iconActive: Icons.VaultActive,
|
||||
icon: VaultInactive,
|
||||
iconActive: VaultActive,
|
||||
},
|
||||
{
|
||||
label: "generator",
|
||||
page: "/tabs/generator",
|
||||
icon: Icons.GeneratorInactive,
|
||||
iconActive: Icons.GeneratorActive,
|
||||
icon: GeneratorInactive,
|
||||
iconActive: GeneratorActive,
|
||||
},
|
||||
{
|
||||
label: "send",
|
||||
page: "/tabs/send",
|
||||
icon: Icons.SendInactive,
|
||||
iconActive: Icons.SendActive,
|
||||
icon: SendInactive,
|
||||
iconActive: SendActive,
|
||||
},
|
||||
{
|
||||
label: "settings",
|
||||
page: "/tabs/settings",
|
||||
icon: Icons.SettingsInactive,
|
||||
iconActive: Icons.SettingsActive,
|
||||
icon: SettingsInactive,
|
||||
iconActive: SettingsActive,
|
||||
showBerry: showBerry,
|
||||
},
|
||||
];
|
||||
@@ -671,17 +676,13 @@ export const WithVirtualScrollChild: Story = {
|
||||
<button type="button" bitBadge variant="primary">Fill</button>
|
||||
</bit-item-action>
|
||||
<bit-item-action>
|
||||
<button
|
||||
type="button"
|
||||
bitIconButton="bwi-clone"
|
||||
aria-label="Copy item"
|
||||
></button>
|
||||
<button type="button" bitIconButton="bwi-clone" label="Copy item"></button>
|
||||
</bit-item-action>
|
||||
<bit-item-action>
|
||||
<button
|
||||
type="button"
|
||||
bitIconButton="bwi-ellipsis-v"
|
||||
aria-label="More options"
|
||||
label="More options"
|
||||
></button>
|
||||
</bit-item-action>
|
||||
</ng-container>
|
||||
|
||||
@@ -3,8 +3,9 @@ import { Component, Input } from "@angular/core";
|
||||
import { RouterModule } from "@angular/router";
|
||||
|
||||
import { JslibModule } from "@bitwarden/angular/jslib.module";
|
||||
import { Icon } from "@bitwarden/assets/svg";
|
||||
import { I18nService } from "@bitwarden/common/platform/abstractions/i18n.service";
|
||||
import { Icon, IconModule, LinkModule } from "@bitwarden/components";
|
||||
import { IconModule, LinkModule } from "@bitwarden/components";
|
||||
|
||||
export type NavButton = {
|
||||
label: string;
|
||||
|
||||
@@ -150,7 +150,7 @@ describe("Browser Utils Service", () => {
|
||||
callback(undefined);
|
||||
});
|
||||
|
||||
const isViewOpen = await browserPlatformUtilsService.isViewOpen();
|
||||
const isViewOpen = await browserPlatformUtilsService.isPopupOpen();
|
||||
|
||||
expect(isViewOpen).toBe(false);
|
||||
});
|
||||
@@ -160,7 +160,7 @@ describe("Browser Utils Service", () => {
|
||||
callback(message.command === "checkVaultPopupHeartbeat");
|
||||
});
|
||||
|
||||
const isViewOpen = await browserPlatformUtilsService.isViewOpen();
|
||||
const isViewOpen = await browserPlatformUtilsService.isPopupOpen();
|
||||
|
||||
expect(isViewOpen).toBe(true);
|
||||
});
|
||||
@@ -173,7 +173,7 @@ describe("Browser Utils Service", () => {
|
||||
callback(undefined);
|
||||
});
|
||||
|
||||
const isViewOpen = await browserPlatformUtilsService.isViewOpen();
|
||||
const isViewOpen = await browserPlatformUtilsService.isPopupOpen();
|
||||
|
||||
expect(isViewOpen).toBe(false);
|
||||
|
||||
|
||||
@@ -150,7 +150,7 @@ export abstract class BrowserPlatformUtilsService implements PlatformUtilsServic
|
||||
* message to the popup and waiting for a response. If a response is received,
|
||||
* the view is open.
|
||||
*/
|
||||
async isViewOpen(): Promise<boolean> {
|
||||
async isPopupOpen(): Promise<boolean> {
|
||||
if (this.isSafari()) {
|
||||
// Query views on safari since chrome.runtime.sendMessage does not timeout and will hang.
|
||||
return BrowserApi.isPopupOpen();
|
||||
|
||||
@@ -0,0 +1,60 @@
|
||||
import { map, merge, Observable } from "rxjs";
|
||||
|
||||
import { LogService } from "@bitwarden/common/platform/abstractions/log.service";
|
||||
import { PlatformUtilsService } from "@bitwarden/common/platform/abstractions/platform-utils.service";
|
||||
import {
|
||||
ButtonLocation,
|
||||
SystemNotificationClearInfo,
|
||||
SystemNotificationCreateInfo,
|
||||
SystemNotificationEvent,
|
||||
SystemNotificationsService,
|
||||
} from "@bitwarden/common/platform/system-notifications/system-notifications.service";
|
||||
|
||||
import { fromChromeEvent } from "../browser/from-chrome-event";
|
||||
|
||||
export class BrowserSystemNotificationService implements SystemNotificationsService {
|
||||
notificationClicked$: Observable<SystemNotificationEvent>;
|
||||
|
||||
constructor(
|
||||
private logService: LogService,
|
||||
private platformUtilsService: PlatformUtilsService,
|
||||
) {
|
||||
this.notificationClicked$ = merge(
|
||||
fromChromeEvent(chrome.notifications.onButtonClicked).pipe(
|
||||
map(([notificationId, buttonIndex]) => ({
|
||||
id: notificationId,
|
||||
buttonIdentifier: buttonIndex,
|
||||
})),
|
||||
),
|
||||
fromChromeEvent(chrome.notifications.onClicked).pipe(
|
||||
map(([notificationId]: [string]) => ({
|
||||
id: notificationId,
|
||||
buttonIdentifier: ButtonLocation.NotificationButton,
|
||||
})),
|
||||
),
|
||||
);
|
||||
}
|
||||
|
||||
async create(createInfo: SystemNotificationCreateInfo): Promise<string> {
|
||||
return new Promise<string>((resolve) => {
|
||||
chrome.notifications.create(
|
||||
{
|
||||
iconUrl: chrome.runtime.getURL("images/icon128.png"),
|
||||
message: createInfo.body,
|
||||
type: "basic",
|
||||
title: createInfo.title,
|
||||
buttons: createInfo.buttons.map((value) => ({ title: value.title })),
|
||||
},
|
||||
(notificationId) => resolve(notificationId),
|
||||
);
|
||||
});
|
||||
}
|
||||
|
||||
async clear(clearInfo: SystemNotificationClearInfo): Promise<undefined> {
|
||||
chrome.notifications.clear(clearInfo.id);
|
||||
}
|
||||
|
||||
isSupported(): boolean {
|
||||
return "notifications" in chrome;
|
||||
}
|
||||
}
|
||||
@@ -17,28 +17,31 @@ import { SetInitialPasswordComponent } from "@bitwarden/angular/auth/password-ma
|
||||
import { canAccessFeature } from "@bitwarden/angular/platform/guard/feature-flag.guard";
|
||||
import {
|
||||
DevicesIcon,
|
||||
RegistrationLockAltIcon,
|
||||
RegistrationUserAddIcon,
|
||||
TwoFactorTimeoutIcon,
|
||||
DeviceVerificationIcon,
|
||||
UserLockIcon,
|
||||
VaultIcon,
|
||||
LockIcon,
|
||||
} from "@bitwarden/assets/svg";
|
||||
import {
|
||||
LoginComponent,
|
||||
LoginDecryptionOptionsComponent,
|
||||
LoginSecondaryContentComponent,
|
||||
LoginViaAuthRequestComponent,
|
||||
PasswordHintComponent,
|
||||
RegistrationFinishComponent,
|
||||
RegistrationLockAltIcon,
|
||||
RegistrationStartComponent,
|
||||
RegistrationStartSecondaryComponent,
|
||||
RegistrationStartSecondaryComponentData,
|
||||
RegistrationUserAddIcon,
|
||||
SsoComponent,
|
||||
TwoFactorTimeoutIcon,
|
||||
TwoFactorAuthComponent,
|
||||
TwoFactorAuthGuard,
|
||||
NewDeviceVerificationComponent,
|
||||
DeviceVerificationIcon,
|
||||
UserLockIcon,
|
||||
VaultIcon,
|
||||
} from "@bitwarden/auth/angular";
|
||||
import { FeatureFlag } from "@bitwarden/common/enums/feature-flag.enum";
|
||||
import { AnonLayoutWrapperData, Icons } from "@bitwarden/components";
|
||||
import { AnonLayoutWrapperData } from "@bitwarden/components";
|
||||
import { LockComponent } from "@bitwarden/key-management-ui";
|
||||
|
||||
import { AccountSwitcherComponent } from "../auth/popup/account-switching/account-switcher.component";
|
||||
@@ -497,7 +500,7 @@ const routes: Routes = [
|
||||
path: "lock",
|
||||
canActivate: [lockGuard()],
|
||||
data: {
|
||||
pageIcon: Icons.LockIcon,
|
||||
pageIcon: LockIcon,
|
||||
pageTitle: {
|
||||
key: "yourVaultIsLockedV2",
|
||||
},
|
||||
|
||||
@@ -321,6 +321,9 @@ export class AppComponent implements OnInit, OnDestroy {
|
||||
}
|
||||
|
||||
private async clearComponentStates() {
|
||||
if (this.activeUserId == null) {
|
||||
return;
|
||||
}
|
||||
if (!(await firstValueFrom(this.tokenService.hasAccessToken$(this.activeUserId)))) {
|
||||
return;
|
||||
}
|
||||
|
||||
@@ -5,10 +5,9 @@ import { Component, OnDestroy, OnInit } from "@angular/core";
|
||||
import { ActivatedRoute, Data, NavigationEnd, Router, RouterModule } from "@angular/router";
|
||||
import { Subject, filter, switchMap, takeUntil, tap } from "rxjs";
|
||||
|
||||
import { ExtensionBitwardenLogo, Icon } from "@bitwarden/assets/svg";
|
||||
import { I18nService } from "@bitwarden/common/platform/abstractions/i18n.service";
|
||||
import {
|
||||
Icon,
|
||||
Icons,
|
||||
IconModule,
|
||||
Translation,
|
||||
AnonLayoutComponent,
|
||||
@@ -63,7 +62,7 @@ export class ExtensionAnonLayoutWrapperComponent implements OnInit, OnDestroy {
|
||||
protected hideCardWrapper: boolean = false;
|
||||
|
||||
protected theme: string;
|
||||
protected logo = Icons.ExtensionBitwardenLogo;
|
||||
protected logo = ExtensionBitwardenLogo;
|
||||
|
||||
constructor(
|
||||
private router: Router,
|
||||
|
||||
@@ -9,6 +9,7 @@ import {
|
||||
} from "@storybook/angular";
|
||||
import { of } from "rxjs";
|
||||
|
||||
import { LockIcon, RegistrationCheckEmailIcon } from "@bitwarden/assets/svg";
|
||||
import { AccountService } from "@bitwarden/common/auth/abstractions/account.service";
|
||||
import { AuthService } from "@bitwarden/common/auth/abstractions/auth.service";
|
||||
import { AvatarService } from "@bitwarden/common/auth/abstractions/avatar.service";
|
||||
@@ -22,12 +23,7 @@ import {
|
||||
import { I18nService } from "@bitwarden/common/platform/abstractions/i18n.service";
|
||||
import { PlatformUtilsService } from "@bitwarden/common/platform/abstractions/platform-utils.service";
|
||||
import { UserId } from "@bitwarden/common/types/guid";
|
||||
import {
|
||||
AnonLayoutWrapperDataService,
|
||||
ButtonModule,
|
||||
Icons,
|
||||
I18nMockService,
|
||||
} from "@bitwarden/components";
|
||||
import { AnonLayoutWrapperDataService, ButtonModule, I18nMockService } from "@bitwarden/components";
|
||||
|
||||
import { AccountSwitcherService } from "../../../auth/popup/account-switching/services/account-switcher.service";
|
||||
import { PopupRouterCacheService } from "../../../platform/popup/view-cache/popup-router-cache.service";
|
||||
@@ -244,7 +240,7 @@ const initialData: ExtensionAnonLayoutWrapperData = {
|
||||
pageSubtitle: {
|
||||
key: "finishCreatingYourAccountBySettingAPassword",
|
||||
},
|
||||
pageIcon: Icons.LockIcon,
|
||||
pageIcon: LockIcon,
|
||||
showAcctSwitcher: true,
|
||||
showBackButton: true,
|
||||
showLogo: true,
|
||||
@@ -258,7 +254,7 @@ const changedData: ExtensionAnonLayoutWrapperData = {
|
||||
pageSubtitle: {
|
||||
key: "checkYourEmail",
|
||||
},
|
||||
pageIcon: Icons.RegistrationCheckEmailIcon,
|
||||
pageIcon: RegistrationCheckEmailIcon,
|
||||
showAcctSwitcher: false,
|
||||
showBackButton: false,
|
||||
showLogo: false,
|
||||
|
||||
@@ -92,12 +92,13 @@ import {
|
||||
AbstractStorageService,
|
||||
ObservableStorageService,
|
||||
} from "@bitwarden/common/platform/abstractions/storage.service";
|
||||
import { ActionsService } from "@bitwarden/common/platform/actions";
|
||||
import { Message, MessageListener, MessageSender } from "@bitwarden/common/platform/messaging";
|
||||
// eslint-disable-next-line no-restricted-imports -- Used for dependency injection
|
||||
import { SubjectMessageSender } from "@bitwarden/common/platform/messaging/internal";
|
||||
import { flagEnabled } from "@bitwarden/common/platform/misc/flags";
|
||||
import { NotificationsService } from "@bitwarden/common/platform/notifications";
|
||||
import { TaskSchedulerService } from "@bitwarden/common/platform/scheduling";
|
||||
import { ServerNotificationsService } from "@bitwarden/common/platform/server-notifications";
|
||||
import { ConsoleLogService } from "@bitwarden/common/platform/services/console-log.service";
|
||||
import { ContainerService } from "@bitwarden/common/platform/services/container.service";
|
||||
import { DefaultSdkClientFactory } from "@bitwarden/common/platform/services/sdk/default-sdk-client-factory";
|
||||
@@ -113,6 +114,7 @@ import { InlineDerivedStateProvider } from "@bitwarden/common/platform/state/imp
|
||||
import { PrimarySecondaryStorageService } from "@bitwarden/common/platform/storage/primary-secondary-storage.service";
|
||||
import { WindowStorageService } from "@bitwarden/common/platform/storage/window-storage.service";
|
||||
import { SyncService } from "@bitwarden/common/platform/sync";
|
||||
import { SystemNotificationsService } from "@bitwarden/common/platform/system-notifications/system-notifications.service";
|
||||
import { SendApiService } from "@bitwarden/common/tools/send/services/send-api.service.abstraction";
|
||||
import { InternalSendService } from "@bitwarden/common/tools/send/services/send.service.abstraction";
|
||||
import { CipherService } from "@bitwarden/common/vault/abstractions/cipher.service";
|
||||
@@ -160,13 +162,14 @@ import { InlineMenuFieldQualificationService } from "../../autofill/services/inl
|
||||
import { ForegroundBrowserBiometricsService } from "../../key-management/biometrics/foreground-browser-biometrics";
|
||||
import { ExtensionLockComponentService } from "../../key-management/lock/services/extension-lock-component.service";
|
||||
import { ForegroundVaultTimeoutService } from "../../key-management/vault-timeout/foreground-vault-timeout.service";
|
||||
import { BrowserActionsService } from "../../platform/actions/browser-actions.service";
|
||||
import { BrowserApi } from "../../platform/browser/browser-api";
|
||||
import { runInsideAngular } from "../../platform/browser/run-inside-angular.operator";
|
||||
/* eslint-disable no-restricted-imports */
|
||||
import { ZonedMessageListenerService } from "../../platform/browser/zoned-message-listener.service";
|
||||
import { ChromeMessageSender } from "../../platform/messaging/chrome-message.sender";
|
||||
/* eslint-enable no-restricted-imports */
|
||||
import { ForegroundNotificationsService } from "../../platform/notifications/foreground-notifications.service";
|
||||
import { ForegroundServerNotificationsService } from "../../platform/notifications/foreground-server-notifications.service";
|
||||
import { OffscreenDocumentService } from "../../platform/offscreen-document/abstractions/offscreen-document";
|
||||
import { DefaultOffscreenDocumentService } from "../../platform/offscreen-document/offscreen-document.service";
|
||||
import { PopupCompactModeService } from "../../platform/popup/layout/popup-compact-mode.service";
|
||||
@@ -184,6 +187,7 @@ import { ForegroundTaskSchedulerService } from "../../platform/services/task-sch
|
||||
import { BrowserStorageServiceProvider } from "../../platform/storage/browser-storage-service.provider";
|
||||
import { ForegroundMemoryStorageService } from "../../platform/storage/foreground-memory-storage.service";
|
||||
import { ForegroundSyncService } from "../../platform/sync/foreground-sync.service";
|
||||
import { BrowserSystemNotificationService } from "../../platform/system-notifications/browser-system-notification.service";
|
||||
import { fromChromeRuntimeMessaging } from "../../platform/utils/from-chrome-runtime-messaging";
|
||||
import { FilePopoutUtilsService } from "../../tools/popup/services/file-popout-utils.service";
|
||||
import { Fido2UserVerificationService } from "../../vault/services/fido2-user-verification.service";
|
||||
@@ -253,6 +257,11 @@ const safeProviders: SafeProvider[] = [
|
||||
},
|
||||
deps: [GlobalStateProvider],
|
||||
}),
|
||||
safeProvider({
|
||||
provide: ActionsService,
|
||||
useClass: BrowserActionsService,
|
||||
deps: [LogService, PlatformUtilsService],
|
||||
}),
|
||||
safeProvider({
|
||||
provide: KeyService,
|
||||
useFactory: (
|
||||
@@ -609,6 +618,11 @@ const safeProviders: SafeProvider[] = [
|
||||
useClass: SsoUrlService,
|
||||
deps: [],
|
||||
}),
|
||||
safeProvider({
|
||||
provide: SystemNotificationsService,
|
||||
useClass: BrowserSystemNotificationService,
|
||||
deps: [LogService, PlatformUtilsService],
|
||||
}),
|
||||
safeProvider({
|
||||
provide: LoginComponentService,
|
||||
useClass: ExtensionLoginComponentService,
|
||||
@@ -674,8 +688,8 @@ const safeProviders: SafeProvider[] = [
|
||||
deps: [KeyService, MasterPasswordApiService, InternalMasterPasswordServiceAbstraction, WINDOW],
|
||||
}),
|
||||
safeProvider({
|
||||
provide: NotificationsService,
|
||||
useClass: ForegroundNotificationsService,
|
||||
provide: ServerNotificationsService,
|
||||
useClass: ForegroundServerNotificationsService,
|
||||
deps: [LogService],
|
||||
}),
|
||||
safeProvider({
|
||||
|
||||
@@ -2,9 +2,18 @@ import { Component } from "@angular/core";
|
||||
import { map, Observable, startWith, switchMap } from "rxjs";
|
||||
|
||||
import { NudgesService } from "@bitwarden/angular/vault";
|
||||
import {
|
||||
VaultInactive,
|
||||
VaultActive,
|
||||
GeneratorInactive,
|
||||
GeneratorActive,
|
||||
SendInactive,
|
||||
SendActive,
|
||||
SettingsInactive,
|
||||
SettingsActive,
|
||||
} from "@bitwarden/assets/svg";
|
||||
import { AccountService } from "@bitwarden/common/auth/abstractions/account.service";
|
||||
import { getUserId } from "@bitwarden/common/auth/services/account.service";
|
||||
import { Icons } from "@bitwarden/components";
|
||||
|
||||
import { NavButton } from "../platform/popup/layout/popup-tab-navigation.component";
|
||||
|
||||
@@ -24,26 +33,26 @@ export class TabsV2Component {
|
||||
{
|
||||
label: "vault",
|
||||
page: "/tabs/vault",
|
||||
icon: Icons.VaultInactive,
|
||||
iconActive: Icons.VaultActive,
|
||||
icon: VaultInactive,
|
||||
iconActive: VaultActive,
|
||||
},
|
||||
{
|
||||
label: "generator",
|
||||
page: "/tabs/generator",
|
||||
icon: Icons.GeneratorInactive,
|
||||
iconActive: Icons.GeneratorActive,
|
||||
icon: GeneratorInactive,
|
||||
iconActive: GeneratorActive,
|
||||
},
|
||||
{
|
||||
label: "send",
|
||||
page: "/tabs/send",
|
||||
icon: Icons.SendInactive,
|
||||
iconActive: Icons.SendActive,
|
||||
icon: SendInactive,
|
||||
iconActive: SendActive,
|
||||
},
|
||||
{
|
||||
label: "settings",
|
||||
page: "/tabs/settings",
|
||||
icon: Icons.SettingsInactive,
|
||||
iconActive: Icons.SettingsActive,
|
||||
icon: SettingsInactive,
|
||||
iconActive: SettingsActive,
|
||||
showBerry: hasBadges,
|
||||
},
|
||||
];
|
||||
|
||||
@@ -26,7 +26,7 @@
|
||||
slot="end"
|
||||
bitIconButton="bwi-trash"
|
||||
[bitAction]="deleteSend"
|
||||
appA11yTitle="{{ 'delete' | i18n }}"
|
||||
label="{{ 'delete' | i18n }}"
|
||||
></button>
|
||||
</popup-footer>
|
||||
</popup-page>
|
||||
|
||||
@@ -7,13 +7,13 @@ import { ActivatedRoute, Router, RouterModule } from "@angular/router";
|
||||
import { firstValueFrom } from "rxjs";
|
||||
|
||||
import { JslibModule } from "@bitwarden/angular/jslib.module";
|
||||
import { ActiveSendIcon } from "@bitwarden/assets/svg";
|
||||
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";
|
||||
import { SendView } from "@bitwarden/common/tools/send/models/view/send.view";
|
||||
import { SendService } from "@bitwarden/common/tools/send/services/send.service.abstraction";
|
||||
import { ButtonModule, IconModule, ToastService } from "@bitwarden/components";
|
||||
import { ActiveSendIcon } from "@bitwarden/send-ui";
|
||||
|
||||
import { PopOutComponent } from "../../../../platform/popup/components/pop-out.component";
|
||||
import { PopupFooterComponent } from "../../../../platform/popup/layout/popup-footer.component";
|
||||
|
||||
@@ -4,15 +4,15 @@ import { takeUntilDestroyed } from "@angular/core/rxjs-interop";
|
||||
import { combineLatest, switchMap } from "rxjs";
|
||||
|
||||
import { JslibModule } from "@bitwarden/angular/jslib.module";
|
||||
import { NoResults, NoSendsIcon } from "@bitwarden/assets/svg";
|
||||
import { PolicyService } from "@bitwarden/common/admin-console/abstractions/policy/policy.service.abstraction";
|
||||
import { PolicyType } from "@bitwarden/common/admin-console/enums";
|
||||
import { AccountService } from "@bitwarden/common/auth/abstractions/account.service";
|
||||
import { getUserId } from "@bitwarden/common/auth/services/account.service";
|
||||
import { SendType } from "@bitwarden/common/tools/send/enums/send-type";
|
||||
import { ButtonModule, CalloutModule, Icons, NoItemsModule } from "@bitwarden/components";
|
||||
import { ButtonModule, CalloutModule, NoItemsModule } from "@bitwarden/components";
|
||||
import {
|
||||
NewSendDropdownComponent,
|
||||
NoSendsIcon,
|
||||
SendItemsService,
|
||||
SendListFiltersComponent,
|
||||
SendListFiltersService,
|
||||
@@ -59,7 +59,7 @@ export class SendV2Component implements OnDestroy {
|
||||
protected sendsLoading$ = this.sendItemsService.loading$;
|
||||
protected title: string = "allSends";
|
||||
protected noItemIcon = NoSendsIcon;
|
||||
protected noResultsIcon = Icons.NoResults;
|
||||
protected noResultsIcon = NoResults;
|
||||
|
||||
protected sendsDisabled = false;
|
||||
|
||||
|
||||
@@ -38,7 +38,7 @@
|
||||
type="button"
|
||||
buttonType="danger"
|
||||
bitIconButton="bwi-trash"
|
||||
[appA11yTitle]="'delete' | i18n"
|
||||
[label]="'delete' | i18n"
|
||||
></button>
|
||||
</popup-footer>
|
||||
</popup-page>
|
||||
|
||||
@@ -2,9 +2,10 @@ import { Component } from "@angular/core";
|
||||
import { Router } from "@angular/router";
|
||||
|
||||
import { JslibModule } from "@bitwarden/angular/jslib.module";
|
||||
import { SecurityHandshake, LoginCards, SecureUser, SecureDevices } from "@bitwarden/assets/svg";
|
||||
import { ButtonModule, DialogModule, IconModule, TypographyModule } from "@bitwarden/components";
|
||||
import { I18nPipe } from "@bitwarden/ui-common";
|
||||
import { VaultCarouselModule, VaultIcons } from "@bitwarden/vault";
|
||||
import { VaultCarouselModule } from "@bitwarden/vault";
|
||||
|
||||
import { IntroCarouselService } from "../../../services/intro-carousel.service";
|
||||
|
||||
@@ -22,10 +23,10 @@ import { IntroCarouselService } from "../../../services/intro-carousel.service";
|
||||
],
|
||||
})
|
||||
export class IntroCarouselComponent {
|
||||
protected securityHandshake = VaultIcons.SecurityHandshake;
|
||||
protected loginCards = VaultIcons.LoginCards;
|
||||
protected secureUser = VaultIcons.SecureUser;
|
||||
protected secureDevices = VaultIcons.SecureDevices;
|
||||
protected securityHandshake = SecurityHandshake;
|
||||
protected loginCards = LoginCards;
|
||||
protected secureUser = SecureUser;
|
||||
protected secureDevices = SecureDevices;
|
||||
|
||||
constructor(
|
||||
private router: Router,
|
||||
|
||||
@@ -7,7 +7,7 @@
|
||||
size="small"
|
||||
appCopyField="username"
|
||||
[cipher]="cipher"
|
||||
[appA11yTitle]="'copyUsername' | i18n"
|
||||
[label]="'copyUsername' | i18n"
|
||||
></button>
|
||||
</bit-item-action>
|
||||
<bit-item-action>
|
||||
@@ -18,7 +18,7 @@
|
||||
size="small"
|
||||
appCopyField="password"
|
||||
[cipher]="cipher"
|
||||
[appA11yTitle]="'copyPassword' | i18n"
|
||||
[label]="'copyPassword' | i18n"
|
||||
></button>
|
||||
</bit-item-action>
|
||||
<bit-item-action>
|
||||
@@ -28,7 +28,7 @@
|
||||
size="small"
|
||||
appCopyField="totp"
|
||||
[cipher]="cipher"
|
||||
[appA11yTitle]="'copyVerificationCode' | i18n"
|
||||
[label]="'copyVerificationCode' | i18n"
|
||||
></button>
|
||||
</bit-item-action>
|
||||
</ng-container>
|
||||
@@ -40,7 +40,7 @@
|
||||
type="button"
|
||||
bitIconButton="bwi-clone"
|
||||
size="small"
|
||||
[appA11yTitle]="'copyFieldCipherName' | i18n: singleCopyableLogin.key : cipher.name"
|
||||
[label]="'copyFieldCipherName' | i18n: singleCopyableLogin.key : cipher.name"
|
||||
[appCopyField]="singleCopyableLogin.field"
|
||||
[cipher]="cipher"
|
||||
></button>
|
||||
@@ -49,7 +49,7 @@
|
||||
type="button"
|
||||
bitIconButton="bwi-clone"
|
||||
size="small"
|
||||
[appA11yTitle]="
|
||||
[label]="
|
||||
hasLoginValues ? ('copyInfoTitle' | i18n: cipher.name) : ('noValuesToCopy' | i18n)
|
||||
"
|
||||
[disabled]="!hasLoginValues"
|
||||
@@ -86,7 +86,7 @@
|
||||
size="small"
|
||||
appCopyField="cardNumber"
|
||||
[cipher]="cipher"
|
||||
[appA11yTitle]="'copyNumber' | i18n"
|
||||
[label]="'copyNumber' | i18n"
|
||||
></button>
|
||||
</bit-item-action>
|
||||
<bit-item-action>
|
||||
@@ -96,7 +96,7 @@
|
||||
size="small"
|
||||
appCopyField="securityCode"
|
||||
[cipher]="cipher"
|
||||
[appA11yTitle]="'copySecurityCode' | i18n"
|
||||
[label]="'copySecurityCode' | i18n"
|
||||
></button>
|
||||
</bit-item-action>
|
||||
</ng-container>
|
||||
@@ -107,7 +107,7 @@
|
||||
type="button"
|
||||
bitIconButton="bwi-clone"
|
||||
size="small"
|
||||
[appA11yTitle]="'copyFieldCipherName' | i18n: singleCopyableCard.key : cipher.name"
|
||||
[label]="'copyFieldCipherName' | i18n: singleCopyableCard.key : cipher.name"
|
||||
[appCopyField]="singleCopyableCard.field"
|
||||
[cipher]="cipher"
|
||||
showToast
|
||||
@@ -117,7 +117,7 @@
|
||||
type="button"
|
||||
bitIconButton="bwi-clone"
|
||||
size="small"
|
||||
[appA11yTitle]="
|
||||
[label]="
|
||||
hasCardValues ? ('copyInfoTitle' | i18n: cipher.name) : ('noValuesToCopy' | i18n)
|
||||
"
|
||||
[disabled]="!hasCardValues"
|
||||
@@ -142,7 +142,7 @@
|
||||
type="button"
|
||||
bitIconButton="bwi-clone"
|
||||
size="small"
|
||||
[appA11yTitle]="'copyFieldCipherName' | i18n: singleCopyableIdentity.key : cipher.name"
|
||||
[label]="'copyFieldCipherName' | i18n: singleCopyableIdentity.key : cipher.name"
|
||||
[appCopyField]="singleCopyableIdentity.field"
|
||||
[cipher]="cipher"
|
||||
showToast
|
||||
@@ -152,7 +152,7 @@
|
||||
type="button"
|
||||
bitIconButton="bwi-clone"
|
||||
size="small"
|
||||
[appA11yTitle]="
|
||||
[label]="
|
||||
hasIdentityValues ? ('copyInfoTitle' | i18n: cipher.name) : ('noValuesToCopy' | i18n)
|
||||
"
|
||||
[disabled]="!hasIdentityValues"
|
||||
@@ -180,9 +180,7 @@
|
||||
type="button"
|
||||
bitIconButton="bwi-clone"
|
||||
size="small"
|
||||
[appA11yTitle]="
|
||||
hasSecureNoteValue ? ('copyNoteTitle' | i18n: cipher.name) : ('noValuesToCopy' | i18n)
|
||||
"
|
||||
[label]="hasSecureNoteValue ? ('copyNoteTitle' | i18n: cipher.name) : ('noValuesToCopy' | i18n)"
|
||||
appCopyField="secureNote"
|
||||
[cipher]="cipher"
|
||||
></button>
|
||||
@@ -193,9 +191,7 @@
|
||||
type="button"
|
||||
bitIconButton="bwi-clone"
|
||||
size="small"
|
||||
[appA11yTitle]="
|
||||
hasSshKeyValues ? ('copyInfoTitle' | i18n: cipher.name) : ('noValuesToCopy' | i18n)
|
||||
"
|
||||
[label]="hasSshKeyValues ? ('copyInfoTitle' | i18n: cipher.name) : ('noValuesToCopy' | i18n)"
|
||||
[disabled]="!hasSshKeyValues"
|
||||
[bitMenuTriggerFor]="sshKeyOptions"
|
||||
></button>
|
||||
|
||||
@@ -3,8 +3,7 @@
|
||||
type="button"
|
||||
bitIconButton="bwi-ellipsis-v"
|
||||
size="small"
|
||||
[attr.aria-label]="'moreOptionsLabel' | i18n: cipher.name"
|
||||
[title]="'moreOptionsTitle' | i18n: cipher.name"
|
||||
[label]="'moreOptionsLabel' | i18n: cipher.name"
|
||||
[disabled]="decryptionFailure"
|
||||
[bitMenuTriggerFor]="moreOptions"
|
||||
></button>
|
||||
|
||||
@@ -76,10 +76,8 @@ describe("VaultGeneratorDialogComponent", () => {
|
||||
component.onValueGenerated("test-password");
|
||||
fixture.detectChanges();
|
||||
|
||||
const button = fixture.debugElement.query(
|
||||
By.css("[data-testid='select-button']"),
|
||||
).nativeElement;
|
||||
expect(button.disabled).toBe(false);
|
||||
const button = fixture.debugElement.query(By.css("[data-testid='select-button']"));
|
||||
expect(button.attributes["aria-disabled"]).toBe(undefined);
|
||||
});
|
||||
|
||||
it("should disable the button if no value has been generated", () => {
|
||||
@@ -90,10 +88,8 @@ describe("VaultGeneratorDialogComponent", () => {
|
||||
generator.algorithmSelected.emit({ useGeneratedValue: "Use Password" } as any);
|
||||
fixture.detectChanges();
|
||||
|
||||
const button = fixture.debugElement.query(
|
||||
By.css("[data-testid='select-button']"),
|
||||
).nativeElement;
|
||||
expect(button.disabled).toBe(true);
|
||||
const button = fixture.debugElement.query(By.css("[data-testid='select-button']"));
|
||||
expect(button.attributes["aria-disabled"]).toBe("true");
|
||||
});
|
||||
|
||||
it("should disable the button if no algorithm is selected", () => {
|
||||
@@ -104,10 +100,8 @@ describe("VaultGeneratorDialogComponent", () => {
|
||||
generator.valueGenerated.emit("test-password");
|
||||
fixture.detectChanges();
|
||||
|
||||
const button = fixture.debugElement.query(
|
||||
By.css("[data-testid='select-button']"),
|
||||
).nativeElement;
|
||||
expect(button.disabled).toBe(true);
|
||||
const button = fixture.debugElement.query(By.css("[data-testid='select-button']"));
|
||||
expect(button.attributes["aria-disabled"]).toBe("true");
|
||||
});
|
||||
|
||||
it("should update button text when algorithm is selected", () => {
|
||||
|
||||
@@ -8,7 +8,7 @@
|
||||
bitIconButton="bwi-sliders"
|
||||
[buttonType]="'muted'"
|
||||
[bitDisclosureTriggerFor]="disclosureRef"
|
||||
[appA11yTitle]="'filterVault' | i18n"
|
||||
[label]="'filterVault' | i18n"
|
||||
aria-describedby="filters-applied"
|
||||
></button>
|
||||
<p
|
||||
|
||||
@@ -42,7 +42,7 @@
|
||||
type="button"
|
||||
size="small"
|
||||
(click)="onRefresh.emit()"
|
||||
[appA11yTitle]="'refresh' | i18n"
|
||||
[label]="'refresh' | i18n"
|
||||
></button>
|
||||
<span bitTypography="body2" slot="end">
|
||||
<span
|
||||
@@ -141,8 +141,7 @@
|
||||
bitIconButton="bwi-external-link"
|
||||
size="small"
|
||||
(click)="launchCipher(cipher)"
|
||||
[attr.aria-label]="'launchWebsiteName' | i18n: cipher.name"
|
||||
[title]="'launchWebsiteName' | i18n: cipher.name"
|
||||
[label]="'launchWebsiteName' | i18n: cipher.name"
|
||||
></button>
|
||||
</bit-item-action>
|
||||
<app-item-copy-actions [cipher]="cipher"></app-item-copy-actions>
|
||||
|
||||
@@ -5,12 +5,11 @@ import { FormsModule } from "@angular/forms";
|
||||
import { Subject, Subscription, debounceTime, distinctUntilChanged, filter } from "rxjs";
|
||||
|
||||
import { JslibModule } from "@bitwarden/angular/jslib.module";
|
||||
import { SearchTextDebounceInterval } from "@bitwarden/common/vault/services/search.service";
|
||||
import { SearchModule } from "@bitwarden/components";
|
||||
|
||||
import { VaultPopupItemsService } from "../../../services/vault-popup-items.service";
|
||||
|
||||
const SearchTextDebounceInterval = 200;
|
||||
|
||||
@Component({
|
||||
imports: [CommonModule, SearchModule, JslibModule, FormsModule],
|
||||
selector: "app-vault-v2-search",
|
||||
|
||||
@@ -18,6 +18,7 @@ import {
|
||||
import { JslibModule } from "@bitwarden/angular/jslib.module";
|
||||
import { NudgesService, NudgeType } from "@bitwarden/angular/vault";
|
||||
import { SpotlightComponent } from "@bitwarden/angular/vault/components/spotlight/spotlight.component";
|
||||
import { DeactivatedOrg, NoResults, VaultOpen } from "@bitwarden/assets/svg";
|
||||
import { AccountService } from "@bitwarden/common/auth/abstractions/account.service";
|
||||
import { getUserId } from "@bitwarden/common/auth/services/account.service";
|
||||
import { FeatureFlag } from "@bitwarden/common/enums/feature-flag.enum";
|
||||
@@ -28,11 +29,10 @@ import { UnionOfValues } from "@bitwarden/common/vault/types/union-of-values";
|
||||
import {
|
||||
ButtonModule,
|
||||
DialogService,
|
||||
Icons,
|
||||
NoItemsModule,
|
||||
TypographyModule,
|
||||
} from "@bitwarden/components";
|
||||
import { DecryptionFailureDialogComponent, VaultIcons } from "@bitwarden/vault";
|
||||
import { DecryptionFailureDialogComponent } from "@bitwarden/vault";
|
||||
|
||||
import { CurrentAccountComponent } from "../../../../auth/popup/account-switching/current-account.component";
|
||||
import { BrowserApi } from "../../../../platform/browser/browser-api";
|
||||
@@ -136,9 +136,9 @@ export class VaultV2Component implements OnInit, AfterViewInit, OnDestroy {
|
||||
/** Visual state of the vault */
|
||||
protected vaultState: VaultState | null = null;
|
||||
|
||||
protected vaultIcon = VaultIcons.Vault;
|
||||
protected deactivatedIcon = VaultIcons.DeactivatedOrg;
|
||||
protected noResultsIcon = Icons.NoResults;
|
||||
protected vaultIcon = VaultOpen;
|
||||
protected deactivatedIcon = DeactivatedOrg;
|
||||
protected noResultsIcon = NoResults;
|
||||
|
||||
protected VaultStateEnum = VaultState;
|
||||
|
||||
|
||||
@@ -33,7 +33,7 @@
|
||||
type="button"
|
||||
buttonType="danger"
|
||||
bitIconButton="bwi-trash"
|
||||
[appA11yTitle]="(cipher.isDeleted ? 'deleteForever' : 'delete') | i18n"
|
||||
[label]="(cipher.isDeleted ? 'deleteForever' : 'delete') | i18n"
|
||||
></button>
|
||||
</popup-footer>
|
||||
</popup-page>
|
||||
|
||||
@@ -25,7 +25,7 @@
|
||||
slot="end"
|
||||
type="button"
|
||||
(click)="openAddEditFolderDialog(folder)"
|
||||
[appA11yTitle]="'editFolderWithName' | i18n: folder.name"
|
||||
[label]="'editFolderWithName' | i18n: folder.name"
|
||||
bitIconButton="bwi-pencil-square"
|
||||
class="tw-self-end"
|
||||
data-testid="edit-folder-button"
|
||||
|
||||
@@ -3,6 +3,7 @@ import { Component } from "@angular/core";
|
||||
import { filter, map, Observable, switchMap } from "rxjs";
|
||||
|
||||
import { JslibModule } from "@bitwarden/angular/jslib.module";
|
||||
import { NoFolders } from "@bitwarden/assets/svg";
|
||||
import { AccountService } from "@bitwarden/common/auth/abstractions/account.service";
|
||||
import { UserId } from "@bitwarden/common/types/guid";
|
||||
import { FolderService } from "@bitwarden/common/vault/abstractions/folder/folder.service.abstraction";
|
||||
@@ -15,7 +16,7 @@ import {
|
||||
ItemModule,
|
||||
NoItemsModule,
|
||||
} from "@bitwarden/components";
|
||||
import { AddEditFolderDialogComponent, VaultIcons } from "@bitwarden/vault";
|
||||
import { AddEditFolderDialogComponent } from "@bitwarden/vault";
|
||||
|
||||
import { PopOutComponent } from "../../../platform/popup/components/pop-out.component";
|
||||
import { PopupHeaderComponent } from "../../../platform/popup/layout/popup-header.component";
|
||||
@@ -39,7 +40,7 @@ import { PopupPageComponent } from "../../../platform/popup/layout/popup-page.co
|
||||
export class FoldersV2Component {
|
||||
folders$: Observable<FolderView[]>;
|
||||
|
||||
NoFoldersIcon = VaultIcons.NoFolders;
|
||||
NoFoldersIcon = NoFolders;
|
||||
private activeUserId$ = this.accountService.activeAccount$.pipe(map((a) => a?.id));
|
||||
|
||||
constructor(
|
||||
|
||||
@@ -37,8 +37,7 @@
|
||||
type="button"
|
||||
bitIconButton="bwi-ellipsis-v"
|
||||
size="small"
|
||||
[attr.aria-label]="'moreOptionsLabel' | i18n: cipher.name"
|
||||
[title]="'moreOptionsTitle' | i18n: cipher.name"
|
||||
[label]="'moreOptionsLabel' | i18n: cipher.name"
|
||||
[bitMenuTriggerFor]="moreOptions"
|
||||
></button>
|
||||
<bit-menu #moreOptions>
|
||||
|
||||
@@ -2,8 +2,8 @@ import { CommonModule } from "@angular/common";
|
||||
import { ChangeDetectionStrategy, Component } from "@angular/core";
|
||||
|
||||
import { JslibModule } from "@bitwarden/angular/jslib.module";
|
||||
import { EmptyTrash } from "@bitwarden/assets/svg";
|
||||
import { CalloutModule, NoItemsModule } from "@bitwarden/components";
|
||||
import { VaultIcons } from "@bitwarden/vault";
|
||||
|
||||
import { PopOutComponent } from "../../../platform/popup/components/pop-out.component";
|
||||
import { PopupHeaderComponent } from "../../../platform/popup/layout/popup-header.component";
|
||||
@@ -29,7 +29,7 @@ import { TrashListItemsContainerComponent } from "./trash-list-items-container/t
|
||||
export class TrashComponent {
|
||||
protected deletedCiphers$ = this.vaultPopupItemsService.deletedCiphers$;
|
||||
|
||||
protected emptyTrashIcon = VaultIcons.EmptyTrash;
|
||||
protected emptyTrashIcon = EmptyTrash;
|
||||
|
||||
constructor(private vaultPopupItemsService: VaultPopupItemsService) {}
|
||||
}
|
||||
|
||||
@@ -4,6 +4,7 @@ const config = require("../../libs/components/tailwind.config.base");
|
||||
config.content = [
|
||||
"./src/**/*.{html,ts}",
|
||||
"../../libs/components/src/**/*.{html,ts}",
|
||||
"../../libs/assets/src/**/*.{html,ts}",
|
||||
"../../libs/auth/src/**/*.{html,ts}",
|
||||
"../../libs/key-management-ui/src/**/*.{html,ts}",
|
||||
"../../libs/vault/src/**/*.{html,ts}",
|
||||
|
||||
@@ -606,6 +606,9 @@ export class GetCommand extends DownloadCommand {
|
||||
if (id === "me") {
|
||||
const activeUserId = await firstValueFrom(this.accountService.activeAccount$.pipe(getUserId));
|
||||
const publicKey = await firstValueFrom(this.keyService.userPublicKey$(activeUserId));
|
||||
if (publicKey == null) {
|
||||
return Response.error("No public key available for the active user.");
|
||||
}
|
||||
fingerprint = await this.keyService.getFingerprint(activeUserId, publicKey);
|
||||
} else if (Utils.isGuid(id)) {
|
||||
try {
|
||||
|
||||
@@ -75,7 +75,7 @@ export class CliPlatformUtilsService implements PlatformUtilsService {
|
||||
return false;
|
||||
}
|
||||
|
||||
isViewOpen() {
|
||||
isPopupOpen() {
|
||||
return Promise.resolve(false);
|
||||
}
|
||||
|
||||
|
||||
@@ -599,6 +599,7 @@ export class ServiceContainer {
|
||||
this.accountService,
|
||||
this.kdfConfigService,
|
||||
this.keyService,
|
||||
this.stateProvider,
|
||||
customUserAgent,
|
||||
);
|
||||
|
||||
|
||||
@@ -1,7 +1,7 @@
|
||||
{
|
||||
"name": "@bitwarden/desktop",
|
||||
"description": "A secure and free password manager for all of your devices.",
|
||||
"version": "2025.8.0",
|
||||
"version": "2025.8.1",
|
||||
"keywords": [
|
||||
"bitwarden",
|
||||
"password",
|
||||
|
||||
@@ -12,29 +12,32 @@ import {
|
||||
unauthGuardFn,
|
||||
} from "@bitwarden/angular/auth/guards";
|
||||
import { ChangePasswordComponent } from "@bitwarden/angular/auth/password-management/change-password";
|
||||
import {
|
||||
DevicesIcon,
|
||||
RegistrationLockAltIcon,
|
||||
RegistrationUserAddIcon,
|
||||
TwoFactorTimeoutIcon,
|
||||
DeviceVerificationIcon,
|
||||
UserLockIcon,
|
||||
VaultIcon,
|
||||
LockIcon,
|
||||
} from "@bitwarden/assets/svg";
|
||||
import {
|
||||
LoginComponent,
|
||||
LoginSecondaryContentComponent,
|
||||
LoginViaAuthRequestComponent,
|
||||
PasswordHintComponent,
|
||||
RegistrationFinishComponent,
|
||||
RegistrationLockAltIcon,
|
||||
RegistrationStartComponent,
|
||||
RegistrationStartSecondaryComponent,
|
||||
RegistrationStartSecondaryComponentData,
|
||||
RegistrationUserAddIcon,
|
||||
UserLockIcon,
|
||||
VaultIcon,
|
||||
LoginDecryptionOptionsComponent,
|
||||
DevicesIcon,
|
||||
SsoComponent,
|
||||
TwoFactorTimeoutIcon,
|
||||
TwoFactorAuthComponent,
|
||||
TwoFactorAuthGuard,
|
||||
NewDeviceVerificationComponent,
|
||||
DeviceVerificationIcon,
|
||||
} from "@bitwarden/auth/angular";
|
||||
import { AnonLayoutWrapperComponent, AnonLayoutWrapperData, Icons } from "@bitwarden/components";
|
||||
import { AnonLayoutWrapperComponent, AnonLayoutWrapperData } from "@bitwarden/components";
|
||||
import { LockComponent } from "@bitwarden/key-management-ui";
|
||||
|
||||
import { maxAccountsGuardFn } from "../auth/guards/max-accounts.guard";
|
||||
@@ -260,7 +263,7 @@ const routes: Routes = [
|
||||
path: "lock",
|
||||
canActivate: [lockGuard()],
|
||||
data: {
|
||||
pageIcon: Icons.LockIcon,
|
||||
pageIcon: LockIcon,
|
||||
pageTitle: {
|
||||
key: "yourVaultIsLockedV2",
|
||||
},
|
||||
|
||||
@@ -62,7 +62,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 { SystemService } from "@bitwarden/common/platform/abstractions/system.service";
|
||||
import { NotificationsService } from "@bitwarden/common/platform/notifications";
|
||||
import { ServerNotificationsService } from "@bitwarden/common/platform/server-notifications";
|
||||
import { StateEventRunnerService } from "@bitwarden/common/platform/state";
|
||||
import { SyncService } from "@bitwarden/common/platform/sync";
|
||||
import { UserId } from "@bitwarden/common/types/guid";
|
||||
@@ -155,7 +155,7 @@ export class AppComponent implements OnInit, OnDestroy {
|
||||
private messagingService: MessagingService,
|
||||
private collectionService: CollectionService,
|
||||
private searchService: SearchService,
|
||||
private notificationsService: NotificationsService,
|
||||
private notificationsService: ServerNotificationsService,
|
||||
private platformUtilsService: PlatformUtilsService,
|
||||
private systemService: SystemService,
|
||||
private processReloadService: ProcessReloadServiceAbstraction,
|
||||
@@ -299,12 +299,22 @@ export class AppComponent implements OnInit, OnDestroy {
|
||||
break;
|
||||
case "showFingerprintPhrase": {
|
||||
const activeUserId = await firstValueFrom(
|
||||
this.accountService.activeAccount$.pipe(map((a) => a?.id)),
|
||||
getUserId(this.accountService.activeAccount$),
|
||||
);
|
||||
const publicKey = await firstValueFrom(this.keyService.userPublicKey$(activeUserId));
|
||||
const fingerprint = await this.keyService.getFingerprint(activeUserId, publicKey);
|
||||
const dialogRef = FingerprintDialogComponent.open(this.dialogService, { fingerprint });
|
||||
await firstValueFrom(dialogRef.closed);
|
||||
if (publicKey == null) {
|
||||
this.logService.error(
|
||||
"[AppComponent] No public key available for the user: " +
|
||||
activeUserId +
|
||||
" fingerprint can't be displayed.",
|
||||
);
|
||||
} else {
|
||||
const fingerprint = await this.keyService.getFingerprint(activeUserId, publicKey);
|
||||
const dialogRef = FingerprintDialogComponent.open(this.dialogService, {
|
||||
fingerprint,
|
||||
});
|
||||
await firstValueFrom(dialogRef.closed);
|
||||
}
|
||||
break;
|
||||
}
|
||||
case "deleteAccount":
|
||||
|
||||
@@ -13,7 +13,7 @@ import { I18nService as I18nServiceAbstraction } from "@bitwarden/common/platfor
|
||||
import { PlatformUtilsService as PlatformUtilsServiceAbstraction } from "@bitwarden/common/platform/abstractions/platform-utils.service";
|
||||
import { SdkLoadService } from "@bitwarden/common/platform/abstractions/sdk/sdk-load.service";
|
||||
import { StateService as StateServiceAbstraction } from "@bitwarden/common/platform/abstractions/state.service";
|
||||
import { NotificationsService } from "@bitwarden/common/platform/notifications";
|
||||
import { ServerNotificationsService } from "@bitwarden/common/platform/server-notifications";
|
||||
import { ContainerService } from "@bitwarden/common/platform/services/container.service";
|
||||
import { MigrationRunner } from "@bitwarden/common/platform/services/migration-runner";
|
||||
import { UserAutoUnlockKeyService } from "@bitwarden/common/platform/services/user-auto-unlock-key.service";
|
||||
@@ -38,7 +38,7 @@ export class InitService {
|
||||
private i18nService: I18nServiceAbstraction,
|
||||
private eventUploadService: EventUploadServiceAbstraction,
|
||||
private twoFactorService: TwoFactorServiceAbstraction,
|
||||
private notificationsService: NotificationsService,
|
||||
private notificationsService: ServerNotificationsService,
|
||||
private platformUtilsService: PlatformUtilsServiceAbstraction,
|
||||
private stateService: StateServiceAbstraction,
|
||||
private keyService: KeyServiceAbstraction,
|
||||
|
||||
@@ -702,6 +702,12 @@
|
||||
"attachmentSaved": {
|
||||
"message": "Attachment saved"
|
||||
},
|
||||
"addAttachment": {
|
||||
"message": "Add attachment"
|
||||
},
|
||||
"maxFileSizeSansPunctuation": {
|
||||
"message": "Maximum file size is 500 MB"
|
||||
},
|
||||
"file": {
|
||||
"message": "File"
|
||||
},
|
||||
@@ -3491,15 +3497,11 @@
|
||||
"selectImportCollection": {
|
||||
"message": "Select a collection"
|
||||
},
|
||||
"importTargetHint": {
|
||||
"message": "Select this option if you want the imported file contents moved to a $DESTINATION$",
|
||||
"description": "Located as a hint under the import target. Will be appended by either folder or collection, depending if the user is importing into an individual or an organizational vault.",
|
||||
"placeholders": {
|
||||
"destination": {
|
||||
"content": "$1",
|
||||
"example": "folder or collection"
|
||||
}
|
||||
}
|
||||
"importTargetHintCollection": {
|
||||
"message": "Select this option if you want the imported file contents moved to a collection"
|
||||
},
|
||||
"importTargetHintFolder": {
|
||||
"message": "Select this option if you want the imported file contents moved to a folder"
|
||||
},
|
||||
"importUnassignedItemsError": {
|
||||
"message": "File contains unassigned items."
|
||||
@@ -4077,5 +4079,9 @@
|
||||
},
|
||||
"enableAutotypeDescription": {
|
||||
"message": "Bitwarden does not validate input locations, be sure you are in the right window and field before using the shortcut."
|
||||
},
|
||||
"moreBreadcrumbs": {
|
||||
"message": "More breadcrumbs",
|
||||
"description": "This is used in the context of a breadcrumb navigation, indicating that there are more items in the breadcrumb trail that are not currently displayed."
|
||||
}
|
||||
}
|
||||
|
||||
4
apps/desktop/src/package-lock.json
generated
4
apps/desktop/src/package-lock.json
generated
@@ -1,12 +1,12 @@
|
||||
{
|
||||
"name": "@bitwarden/desktop",
|
||||
"version": "2025.8.0",
|
||||
"version": "2025.8.1",
|
||||
"lockfileVersion": 3,
|
||||
"requires": true,
|
||||
"packages": {
|
||||
"": {
|
||||
"name": "@bitwarden/desktop",
|
||||
"version": "2025.8.0",
|
||||
"version": "2025.8.1",
|
||||
"license": "GPL-3.0",
|
||||
"dependencies": {
|
||||
"@bitwarden/desktop-napi": "file:../desktop_native/napi"
|
||||
|
||||
@@ -2,7 +2,7 @@
|
||||
"name": "@bitwarden/desktop",
|
||||
"productName": "Bitwarden",
|
||||
"description": "A secure and free password manager for all of your devices.",
|
||||
"version": "2025.8.0",
|
||||
"version": "2025.8.1",
|
||||
"author": "Bitwarden Inc. <hello@bitwarden.com> (https://bitwarden.com)",
|
||||
"homepage": "https://bitwarden.com",
|
||||
"license": "GPL-3.0",
|
||||
|
||||
@@ -59,7 +59,7 @@ export class ElectronPlatformUtilsService implements PlatformUtilsService {
|
||||
return ipc.platform.isMacAppStore;
|
||||
}
|
||||
|
||||
isViewOpen(): Promise<boolean> {
|
||||
isPopupOpen(): Promise<boolean> {
|
||||
return Promise.resolve(false);
|
||||
}
|
||||
|
||||
|
||||
@@ -2,7 +2,7 @@ import { ScrollingModule } from "@angular/cdk/scrolling";
|
||||
import { CommonModule } from "@angular/common";
|
||||
import { Component } from "@angular/core";
|
||||
import { takeUntilDestroyed } from "@angular/core/rxjs-interop";
|
||||
import { distinctUntilChanged } from "rxjs";
|
||||
import { distinctUntilChanged, debounceTime } from "rxjs";
|
||||
|
||||
import { JslibModule } from "@bitwarden/angular/jslib.module";
|
||||
import { VaultItemsComponent as BaseVaultItemsComponent } from "@bitwarden/angular/vault/components/vault-items.component";
|
||||
@@ -10,6 +10,7 @@ import { AccountService } from "@bitwarden/common/auth/abstractions/account.serv
|
||||
import { CipherService } from "@bitwarden/common/vault/abstractions/cipher.service";
|
||||
import { SearchService } from "@bitwarden/common/vault/abstractions/search.service";
|
||||
import { RestrictedItemTypesService } from "@bitwarden/common/vault/services/restricted-item-types.service";
|
||||
import { SearchTextDebounceInterval } from "@bitwarden/common/vault/services/search.service";
|
||||
import {
|
||||
CipherViewLike,
|
||||
CipherViewLikeUtils,
|
||||
@@ -35,7 +36,7 @@ export class VaultItemsV2Component<C extends CipherViewLike> extends BaseVaultIt
|
||||
super(searchService, cipherService, accountService, restrictedItemTypesService);
|
||||
|
||||
this.searchBarService.searchText$
|
||||
.pipe(distinctUntilChanged(), takeUntilDestroyed())
|
||||
.pipe(debounceTime(SearchTextDebounceInterval), distinctUntilChanged(), takeUntilDestroyed())
|
||||
.subscribe((searchText) => {
|
||||
this.searchText = searchText!;
|
||||
});
|
||||
|
||||
@@ -4,6 +4,7 @@ const config = require("../../libs/components/tailwind.config.base");
|
||||
config.content = [
|
||||
"./src/**/*.{html,ts}",
|
||||
"../../libs/components/src/**/*.{html,ts}",
|
||||
"../../libs/assets/src/**/*.{html,ts}",
|
||||
"../../libs/auth/src/**/*.{html,ts}",
|
||||
"../../libs/key-management-ui/src/**/*.{html,ts}",
|
||||
"../../libs/angular/src/**/*.{html,ts}",
|
||||
|
||||
@@ -15,23 +15,206 @@
|
||||
<link rel="manifest" href="manifest.json" />
|
||||
</head>
|
||||
|
||||
<body class="tw-min-h-screen !tw-min-w-0 tw-text-center tw-bg-background-alt tw-flex tw-flex-col">
|
||||
<img class="new-logo-themed tw-m-8" alt="Bitwarden" />
|
||||
<body
|
||||
class="tw-relative tw-min-h-screen !tw-min-w-0 tw-text-center tw-bg-background-alt tw-flex tw-flex-col"
|
||||
>
|
||||
<img class="new-logo-themed !tw-w-[200px] tw-ms-5 tw-my-5" alt="Bitwarden" />
|
||||
<div class="tw-relative tw-grow">
|
||||
<main class="tw-max-w-3xl tw-mx-auto tw-px-2 tw-my-8">
|
||||
<h1 class="tw-mb-0 tw-h1">Sorry, this page isn't available.</h1>
|
||||
|
||||
<main class="tw-max-w-3xl tw-mx-auto tw-px-2 tw-my-4">
|
||||
<h1 class="tw-mb-0 tw-h1">Sorry, this page isn't available.</h1>
|
||||
<p class="tw-py-9 tw-mb-0">
|
||||
The link you followed may be broken, or the page may have been removed. Try going back to
|
||||
the previous page or see our
|
||||
<a href="https://bitwarden.com/help/" target="_blank" rel="noreferrer" class="tw-link"
|
||||
>Help Center</a
|
||||
>
|
||||
for more information.
|
||||
</p>
|
||||
<a href="/" class="tw-btn-secondary tw-inline-block">Go to your web vault</a>
|
||||
</main>
|
||||
<div
|
||||
class="tw-hidden md:tw-block [&_svg]:tw-absolute [&_svg]:tw-z-[1] tw-opacity-[.11] [&_svg]:tw-bottom-0 [&_svg]:tw-start-0 [&_svg]:tw-w-[35%] [&_svg]:tw-max-w-[450px]"
|
||||
>
|
||||
<svg xmlns="http://www.w3.org/2000/svg" fill="none" viewBox="0 0 501 226">
|
||||
<g clip-path="url(#left-a)">
|
||||
<path
|
||||
class="tw-fill-illustration-bg-primary"
|
||||
d="M-71.691 6.821a4 4 0 0 1 4-4h296.5a4 4 0 0 1 4 4v188a4 4 0 0 1-4 4h-296.5a4 4 0 0 1-4-4v-188Z"
|
||||
/>
|
||||
<path
|
||||
class="tw-fill-illustration-bg-primary"
|
||||
d="M-48.941 25.821a2 2 0 0 1 2-2h127.5v154h-127.5a2 2 0 0 1-2-2v-150Z"
|
||||
/>
|
||||
<path
|
||||
class="tw-fill-illustration-bg-tertiary"
|
||||
d="M80.559 25.82a2 2 0 0 1 2-2h125.5a2 2 0 0 1 2 2v150.001a2 2 0 0 1-2 2h-125.5a2 2 0 0 1-2-2v-150ZM45.871 89.854c0 17.155-13.96 31.062-31.182 31.062-17.221 0-31.182-13.907-31.182-31.062s13.96-31.062 31.182-31.062c17.221 0 31.182 13.907 31.182 31.062Z"
|
||||
/>
|
||||
<path
|
||||
class="tw-fill-illustration-bg-tertiary"
|
||||
d="M72.396 153.443a57.243 57.243 0 0 1 4.663 22.604v1.222a2 2 0 0 1-2 2h-118.5a2 2 0 0 1-2-2v-1.222a57.243 57.243 0 0 1 4.662-22.604c3.078-7.167 7.59-13.678 13.277-19.163 5.688-5.485 12.44-9.836 19.871-12.805a63.228 63.228 0 0 1 23.44-4.496 63.227 63.227 0 0 1 23.439 4.496c7.431 2.969 14.183 7.32 19.87 12.805 5.688 5.485 10.2 11.996 13.278 19.163Z"
|
||||
/>
|
||||
<path
|
||||
class="tw-fill-illustration-bg-secondary"
|
||||
d="M161.629 57.193c0 9.182-7.579 16.625-16.927 16.625-9.349 0-16.928-7.443-16.928-16.625 0-9.181 7.579-16.625 16.928-16.625 9.348 0 16.927 7.444 16.927 16.625Z"
|
||||
/>
|
||||
<path
|
||||
class="tw-fill-illustration-bg-secondary"
|
||||
d="M176.028 89.071a29.33 29.33 0 0 1 2.531 11.894c0 .937-.759 1.696-1.696 1.696h-63.109a1.695 1.695 0 0 1-1.695-1.696c0-4.081.86-8.123 2.531-11.894 1.671-3.77 4.12-7.197 7.207-10.083 3.088-2.886 6.753-5.176 10.787-6.738a35.275 35.275 0 0 1 12.725-2.366c4.366 0 8.69.804 12.724 2.366 4.034 1.562 7.699 3.852 10.787 6.738 3.087 2.886 5.537 6.312 7.208 10.083ZM161.629 134.193c0 9.182-7.579 16.625-16.927 16.625-9.349 0-16.928-7.443-16.928-16.625s7.579-16.625 16.928-16.625c9.348 0 16.927 7.443 16.927 16.625Z"
|
||||
/>
|
||||
<path
|
||||
class="tw-fill-illustration-bg-secondary"
|
||||
d="M176.028 165.953a28.993 28.993 0 0 1 2.531 11.821c0 .93-.755 1.684-1.685 1.684h-63.131c-.93 0-1.684-.754-1.684-1.684 0-4.057.86-8.074 2.531-11.821 1.671-3.748 4.12-7.153 7.207-10.021 3.088-2.869 6.753-5.144 10.787-6.696a35.456 35.456 0 0 1 12.725-2.352c4.366 0 8.69.799 12.724 2.352 4.034 1.552 7.699 3.827 10.787 6.696 3.087 2.868 5.537 6.273 7.208 10.021ZM-87.441 199.521h332.5v14.5c0 5.523-4.478 10-10 10h-312.5c-5.523 0-10-4.477-10-10v-14.5Z"
|
||||
/>
|
||||
<path
|
||||
class="tw-fill-illustration-outline"
|
||||
fill-rule="evenodd"
|
||||
d="M208.059 21.82a4 4 0 0 1 4 4v150.001a4 4 0 0 1-4 4l-255 .001a4 4 0 0 1-4-4v-150a4 4 0 0 1 4-4l255-.001Zm-255 154.002h1.5a57.23 57.23 0 0 1 4.378-21.706l.284-.673c2.982-6.943 7.31-13.27 12.748-18.646l.529-.517c5.688-5.485 12.44-9.836 19.871-12.805a62.937 62.937 0 0 1 10.036-3.065c-11.113-4.751-18.897-15.747-18.897-28.556 0-17.155 13.96-31.061 31.182-31.062 17.22 0 31.18 13.907 31.181 31.062 0 12.537-7.457 23.338-18.192 28.245a62.952 62.952 0 0 1 11.569 3.376c7.431 2.969 14.184 7.32 19.871 12.805 5.688 5.485 10.2 11.996 13.278 19.163a57.251 57.251 0 0 1 4.66 22.379h1.502v-150h-125.5v150Zm129.5-.001h29.568a29.02 29.02 0 0 1 2.159-9.161l.304-.706c1.671-3.748 4.12-7.154 7.207-10.022 2.894-2.689 6.297-4.857 10.035-6.396l.752-.299c.996-.383 2.01-.721 3.037-1.012-4.602-2.879-7.693-7.881-7.841-13.602l-.006-.429c0-9.182 7.579-16.625 16.928-16.625l.437.006c9.146.227 16.49 7.581 16.49 16.619l-.006.429c-.144 5.571-3.08 10.461-7.484 13.372 1.321.338 2.622.752 3.894 1.242 4.034 1.552 7.7 3.827 10.787 6.695 3.088 2.868 5.536 6.274 7.207 10.022a29.066 29.066 0 0 1 2.462 9.867h29.57v-73h-125.5v73Zm62.75-24.936c-3.881 0-7.718.71-11.288 2.084-3.571 1.374-6.797 3.382-9.501 5.894-2.704 2.511-4.831 5.478-6.277 8.72a25.125 25.125 0 0 0-2.074 7.876h58.279a25.125 25.125 0 0 0-2.074-7.876c-1.445-3.242-3.573-6.209-6.276-8.72-2.705-2.512-5.931-4.52-9.501-5.894a31.473 31.473 0 0 0-11.288-2.084Zm-129.5-29.906a59.215 59.215 0 0 0-21.955 4.211c-6.957 2.779-13.269 6.848-18.579 11.969-5.31 5.12-9.513 11.191-12.378 17.862a53.266 53.266 0 0 0-4.332 20.248H73.053a53.266 53.266 0 0 0-4.332-20.248c-2.866-6.671-7.07-12.742-12.38-17.862-5.31-5.121-11.621-9.19-18.577-11.969a59.215 59.215 0 0 0-21.955-4.211Zm128.893.59c-7.208 0-12.928 5.72-12.928 12.625.001 6.904 5.721 12.624 12.928 12.624 7.208 0 12.926-5.72 12.927-12.624 0-6.905-5.719-12.625-12.927-12.625ZM14.69 62.792c-15.027 0-27.182 12.13-27.182 27.062 0 14.931 12.155 27.062 27.181 27.063 15.027-.001 27.182-12.132 27.182-27.063S29.716 62.793 14.69 62.792Zm67.869 36.029h29.579c.229-3.094.952-6.141 2.148-9.04l.304-.71a30.936 30.936 0 0 1 6.636-9.536l.571-.547a33.416 33.416 0 0 1 10.035-6.437l.752-.3a34.78 34.78 0 0 1 3.047-1.021c-4.607-2.878-7.703-7.883-7.851-13.607l-.006-.43c0-9.18 7.579-16.624 16.928-16.624l.437.006c9.146.227 16.49 7.58 16.49 16.619l-.006.429c-.144 5.574-3.082 10.465-7.49 13.376 1.324.34 2.626.758 3.9 1.252 4.034 1.561 7.7 3.85 10.787 6.737 3.088 2.886 5.536 6.312 7.207 10.083a29.407 29.407 0 0 1 2.451 9.75h29.581v-73h-125.5v73Zm62.75-24.937c-3.878 0-7.712.714-11.281 2.096-3.568 1.382-6.795 3.401-9.5 5.93-2.704 2.528-4.833 5.515-6.281 8.782a25.432 25.432 0 0 0-2.08 7.969h58.283a25.432 25.432 0 0 0-2.08-7.97c-1.447-3.266-3.577-6.253-6.281-8.781-2.705-2.529-5.931-4.548-9.5-5.93a31.275 31.275 0 0 0-11.28-2.096Zm-.607-29.315c-7.208 0-12.928 5.72-12.928 12.625.001 6.904 5.721 12.624 12.928 12.624 7.208 0 12.926-5.72 12.927-12.624 0-6.905-5.719-12.625-12.927-12.625Z"
|
||||
clip-rule="evenodd"
|
||||
/>
|
||||
<path
|
||||
class="tw-fill-illustration-outline"
|
||||
fill-rule="evenodd"
|
||||
d="M228.809.822a6 6 0 0 1 6 6v188a5.97 5.97 0 0 1-.643 2.699h12.893v16.5c0 6.627-5.373 12-12 12h-312.5c-6.628 0-12-5.373-12-12v-16.5h16.391a5.966 5.966 0 0 1-.634-2.391l-.007-.308v-188a6 6 0 0 1 6-6h296.5ZM-85.441 214.02a8 8 0 0 0 8 8h312.5a8 8 0 0 0 8-8v-12.5h-328.5v12.5Zm17.75-209.2a2 2 0 0 0-2 2v188.001l.01.204a2 2 0 0 0 1.99 1.796h296.5a2.001 2.001 0 0 0 2-2v-188a2 2 0 0 0-2-2h-296.5Z"
|
||||
clip-rule="evenodd"
|
||||
/>
|
||||
<path
|
||||
class="tw-fill-illustration-bg-primary"
|
||||
d="M378.821 114.003a1.997 1.997 0 0 0-.675 1.497v8.396c0 .583.254 1.136.697 1.515l11.455 9.825a2 2 0 0 1 .543 2.286l-4.203 10.056a1.998 1.998 0 0 1-1.936 1.224l-15.288-.717a1.997 1.997 0 0 0-1.501.579l-6.014 5.979a1.995 1.995 0 0 0-.583 1.569l1.145 14.942a1.997 1.997 0 0 1-1.22 1.995l-9.958 4.169a1.997 1.997 0 0 1-2.252-.503l-10.221-11.309a1.998 1.998 0 0 0-1.482-.658h-8.474c-.579 0-1.129.252-1.508.689l-9.889 11.4a1.998 1.998 0 0 1-2.28.534l-9.969-4.174a1.998 1.998 0 0 1-1.224-1.937l.721-15.182a2 2 0 0 0-.587-1.51l-6.014-5.98a1.996 1.996 0 0 0-1.559-.575l-15.049 1.14a1.997 1.997 0 0 1-1.993-1.221l-4.198-10.045a1.997 1.997 0 0 1 .512-2.258l11.363-10.155c.424-.379.666-.92.666-1.489v-8.403c0-.583-.254-1.136-.696-1.516l-11.456-9.824a1.997 1.997 0 0 1-.542-2.286L279.354 92a1.998 1.998 0 0 1 1.936-1.224l15.288.717a1.998 1.998 0 0 0 1.502-.579l6.007-5.974c.418-.415.631-.995.582-1.582l-1.292-15.419a1.995 1.995 0 0 1 1.218-2.008l9.942-4.163a1.996 1.996 0 0 1 2.258.51l10.552 11.786c.379.423.92.665 1.488.665h8.469c.579 0 1.129-.25 1.508-.688l9.889-11.4a1.996 1.996 0 0 1 2.279-.534l9.97 4.174a1.999 1.999 0 0 1 1.224 1.937l-.721 15.181a2 2 0 0 0 .587 1.51l6.014 5.98c.411.41.98.62 1.558.576l15.049-1.14a1.996 1.996 0 0 1 1.993 1.22l4.195 10.036c.33.79.12 1.702-.521 2.268l-11.507 10.154Z"
|
||||
/>
|
||||
<path
|
||||
class="tw-fill-illustration-outline"
|
||||
fill-rule="evenodd"
|
||||
d="M313.765 59.926a3.994 3.994 0 0 1 4.518 1.02l10.552 11.786h8.469l9.888-11.4a3.994 3.994 0 0 1 4.559-1.067l9.97 4.174a3.994 3.994 0 0 1 2.447 3.873l-.72 15.182 6.013 5.98 15.049-1.14a3.995 3.995 0 0 1 3.987 2.442l4.194 10.035a3.992 3.992 0 0 1-1.042 4.534L380.142 115.5v8.396l11.456 9.824a3.995 3.995 0 0 1 1.085 4.571l-4.203 10.056a3.993 3.993 0 0 1-3.872 2.449l-15.288-.717-6.013 5.98 1.145 14.943a3.994 3.994 0 0 1-2.44 3.988l-9.958 4.169a3.992 3.992 0 0 1-4.505-1.005l-10.221-11.309h-8.474l-9.889 11.4a3.993 3.993 0 0 1-4.559 1.067l-9.97-4.174a3.993 3.993 0 0 1-2.446-3.873l.72-15.181-6.014-5.98-15.049 1.14a3.993 3.993 0 0 1-3.986-2.442l-4.198-10.045a3.993 3.993 0 0 1 1.023-4.517l11.363-10.155v-8.403l-11.455-9.825a3.992 3.992 0 0 1-1.085-4.571l4.203-10.056a3.993 3.993 0 0 1 3.872-2.45l15.287.718 6.008-5.974-1.292-15.418a3.992 3.992 0 0 1 2.437-4.017l9.941-4.163Zm1.543 3.684-9.942 4.162 1.292 15.419a3.992 3.992 0 0 1-1.163 3.165l-6.008 5.974a3.994 3.994 0 0 1-3.003 1.157l-15.288-.717-4.202 10.056 11.455 9.824a3.993 3.993 0 0 1 1.394 3.032v8.403c0 1.137-.485 2.22-1.332 2.978l-11.364 10.154 4.198 10.045 15.049-1.14a3.994 3.994 0 0 1 3.118 1.15l6.014 5.98a3.996 3.996 0 0 1 1.173 3.021l-.72 15.181 9.969 4.175 9.889-11.401a3.994 3.994 0 0 1 3.017-1.377h8.474c1.129 0 2.206.478 2.963 1.316l10.221 11.309 9.958-4.169-1.145-14.943a3.996 3.996 0 0 1 1.166-3.137l6.013-5.979a3.997 3.997 0 0 1 3.003-1.158l15.288.717 4.203-10.056-11.456-9.824a3.995 3.995 0 0 1-1.393-3.031V115.5c0-1.146.492-2.236 1.351-2.994l11.506-10.155-4.194-10.035-15.049 1.14a3.991 3.991 0 0 1-3.117-1.15l-6.014-5.98a3.99 3.99 0 0 1-1.173-3.022l.72-15.181-9.97-4.174-9.889 11.4a3.992 3.992 0 0 1-3.016 1.377h-8.469a3.992 3.992 0 0 1-2.975-1.33L315.308 63.61Z"
|
||||
clip-rule="evenodd"
|
||||
/>
|
||||
<path
|
||||
class="tw-fill-illustration-logo"
|
||||
d="M353.438 119.624c0 11.289-9.152 20.441-20.442 20.441-11.289 0-20.441-9.152-20.441-20.441 0-11.29 9.152-20.442 20.441-20.442 11.29 0 20.442 9.152 20.442 20.442Z"
|
||||
/>
|
||||
<path
|
||||
class="tw-fill-illustration-outline"
|
||||
fill-rule="evenodd"
|
||||
d="M332.996 101.179c-10.186 0-18.444 8.258-18.444 18.444 0 10.187 8.258 18.445 18.444 18.445 10.187 0 18.445-8.258 18.445-18.445 0-10.186-8.258-18.444-18.445-18.444Zm-22.438 18.444c0-12.392 10.046-22.438 22.438-22.438 12.393 0 22.439 10.046 22.439 22.438 0 12.393-10.046 22.439-22.439 22.439-12.392 0-22.438-10.046-22.438-22.439Z"
|
||||
clip-rule="evenodd"
|
||||
/>
|
||||
<path
|
||||
class="tw-fill-illustration-bg-tertiary"
|
||||
d="m497.152 164.106-7.588-7.587a3.004 3.004 0 0 0-4.245-.003l-4.055 4.047 11.83 11.83 4.055-4.047a2.996 2.996 0 0 0 .003-4.24Z"
|
||||
/>
|
||||
<path
|
||||
class="tw-fill-illustration-bg-secondary"
|
||||
d="M500.922 194.274c0 22.644-18.356 41-41 41s-41-18.356-41-41 18.356-41 41-41 41 18.356 41 41Z"
|
||||
/>
|
||||
<path
|
||||
class="tw-fill-illustration-outline"
|
||||
d="M459.03 177.416a2 2 0 1 1 4 0v18.469c0 .613-.282 1.192-.763 1.571l-12.032 9.48a2.001 2.001 0 0 1-2.809-.333 2.002 2.002 0 0 1 .334-2.809l11.27-8.881v-17.497Z"
|
||||
/>
|
||||
<path
|
||||
class="tw-fill-illustration-bg-tertiary"
|
||||
d="M450.936 144.041a2 2 0 0 1 2-2h13.972a2 2 0 0 1 2 2v3.863a2 2 0 0 1-2 2h-13.972a2 2 0 0 1-2-2v-3.863Z"
|
||||
/>
|
||||
<path
|
||||
class="tw-fill-illustration-outline"
|
||||
fill-rule="evenodd"
|
||||
d="M467.114 140.046a4 4 0 0 1 3.794 3.995v3.863a3.999 3.999 0 0 1-3.931 3.998v1.978a40.72 40.72 0 0 1 13.484 4.903l3.69-3.68a5.008 5.008 0 0 1 7.076.003l7.587 7.588.177.186a4.994 4.994 0 0 1-.181 6.881l-3.615 3.606a40.801 40.801 0 0 1 5.727 20.907c0 22.644-18.357 41-41 41-22.644 0-41-18.356-41-41 0-20.434 14.949-37.375 34.507-40.487v-1.883h-.493a4 4 0 0 1-4-4v-3.863a4 4 0 0 1 4-4h13.972l.206.005Zm-7.192 17.228c-20.435 0-37 16.566-37 37 0 20.435 16.565 37 37 37 20.434 0 37-16.565 37-37 0-20.434-16.566-37-37-37Zm28.473.658a1.002 1.002 0 0 0-1.416-.001l-2.638 2.633 9.001 9.002 2.639-2.633a1 1 0 0 0 .07-1.338l-.069-.075-7.587-7.588Zm-30.966-6.028v1.447a41.171 41.171 0 0 1 5.548.036v-1.483h-5.548Zm-4.493-4h13.972v-3.863h-13.972v3.863Z"
|
||||
clip-rule="evenodd"
|
||||
/>
|
||||
</g>
|
||||
<defs>
|
||||
<clipPath id="left-a">
|
||||
<path class="tw-fill-illustration-bg-tertiary" d="M0 0h501v226H0z" />
|
||||
</clipPath>
|
||||
</defs>
|
||||
</svg>
|
||||
`;
|
||||
</div>
|
||||
|
||||
<p class="tw-py-9 tw-mb-0">
|
||||
The link you followed may be broken, or the page may have been removed. Try going back to
|
||||
the previous page or see our
|
||||
<a href="https://bitwarden.com/help/" target="_blank" rel="noreferrer">Help Center</a> for
|
||||
more information.
|
||||
</p>
|
||||
|
||||
<a href="/" class="tw-btn-secondary tw-inline-block">Go to your web vault</a>
|
||||
</main>
|
||||
<footer class="tw-mt-auto tw-h-40 tw-bg-primary-600 tw-flex tw-justify-center tw-items-center">
|
||||
<i class="bwi bwi-shield tw-text-contrast tw-text-4xl"></i>
|
||||
</footer>
|
||||
<div
|
||||
class="tw-hidden md:tw-block [&_svg]:tw-absolute tw-z-[1] tw-opacity-[.11] [&_svg]:tw-bottom-0 [&_svg]:tw-end-0 [&_svg]:tw-w-[35%] [&_svg]:tw-max-w-[450px]"
|
||||
>
|
||||
<svg xmlns="http://www.w3.org/2000/svg" fill="none" viewBox="0 0 506 297">
|
||||
<g clip-path="url(#right-a)">
|
||||
<path
|
||||
class="tw-fill-illustration-bg-primary"
|
||||
d="M45.673 294.742v-29.124l22.323 16.198-15.395 15.75a4.04 4.04 0 0 1-6.928-2.824Z"
|
||||
/>
|
||||
<path
|
||||
class="tw-fill-illustration-bg-tertiary"
|
||||
d="m4.978 240.865 95.568-44.738c3.52-1.648 7.492 1.175 7.093 5.041l-9.608 93.173c-.395 3.823-4.774 5.79-7.893 3.547l-43.43-31.233-41.47-16.621c-4.06-1.627-4.221-7.315-.26-9.169Z"
|
||||
/>
|
||||
<path
|
||||
class="tw-fill-illustration-outline"
|
||||
d="M99.698 194.315c4.929-2.306 10.489 1.645 9.931 7.058l-9.608 93.174c-.552 5.351-6.683 8.105-11.05 4.965l-20.832-14.983-14.107 14.435a6.04 6.04 0 0 1-10.359-4.222v-27.151l-39.178-15.7c-5.684-2.278-5.91-10.242-.364-12.838l95.567-44.738Zm5.953 6.648c.239-2.32-2.144-4.013-4.256-3.025L5.827 242.676c-2.376 1.112-2.28 4.525.156 5.502l40.159 16.093 26.703-30.327a2.001 2.001 0 0 1 3.002 2.644l-26.178 29.731 41.637 29.945c1.872 1.346 4.5.165 4.736-2.128l9.609-93.173Zm-57.978 93.779a2.04 2.04 0 0 0 3.498 1.426l13.684-14.001-17.182-12.357v24.932Z"
|
||||
/>
|
||||
<circle
|
||||
cx="86.719"
|
||||
cy="86.719"
|
||||
r="84.719"
|
||||
class="tw-fill-illustration-bg-tertiary"
|
||||
stroke="#020F66"
|
||||
stroke-linecap="round"
|
||||
stroke-linejoin="round"
|
||||
stroke-width="4"
|
||||
transform="scale(-1 1) rotate(45.035 -184.565 -565.488)"
|
||||
/>
|
||||
<circle
|
||||
cx="69.752"
|
||||
cy="69.752"
|
||||
r="69.752"
|
||||
class="tw-fill-illustration-bg-secondary"
|
||||
transform="scale(-1 1) rotate(45.035 -213.255 -553.709)"
|
||||
/>
|
||||
<path
|
||||
class="tw-fill-illustration-outline"
|
||||
d="m445.838 353.214 2.95-180.467 12.372-.007 3.078 180.465a4.64 4.64 0 0 1-4.637 4.72l-9.12.005a4.64 4.64 0 0 1-4.643-4.716ZM453.82 52.947a2 2 0 0 1 1.998-2.001l35.638-.023a2 2 0 0 1 2.001 2.015l-.268 35.637a2 2 0 1 1-4-.03l.252-33.62-33.62.02a1.999 1.999 0 0 1-2.001-1.998ZM415.689 86.49a2 2 0 0 1 4.001.03l-.254 33.62 33.622-.021a2 2 0 0 1 .003 4l-35.637.022a2 2 0 0 1-2.001-2.015l.266-35.636Zm25.457-19.997a2 2 0 0 1 3.461-2.006l23.124 39.885a2 2 0 0 1-3.461 2.006l-23.124-39.885Z"
|
||||
/>
|
||||
<path
|
||||
class="tw-fill-illustration-bg-primary"
|
||||
d="M259.264 277.271c21.107-4.293 34.791-24.62 30.565-45.402-4.227-20.782-24.764-34.15-45.871-29.857-21.107 4.293-34.791 24.62-30.565 45.402 4.227 20.783 24.764 34.15 45.871 29.857ZM299.993 173.472c7.793-1.585 12.826-9.188 11.241-16.981-1.585-7.793-9.187-12.826-16.981-11.241-7.793 1.585-12.826 9.187-11.241 16.981 1.585 7.793 9.188 12.826 16.981 11.241Z"
|
||||
/>
|
||||
<path
|
||||
class="tw-fill-illustration-bg-secondary"
|
||||
d="M329.869 242.094c7.793-1.585 12.826-9.187 11.241-16.981-1.585-7.793-9.188-12.826-16.981-11.241-7.794 1.585-12.827 9.188-11.241 16.981 1.585 7.794 9.187 12.827 16.981 11.241Z"
|
||||
/>
|
||||
<path
|
||||
class="tw-fill-illustration-bg-tertiary"
|
||||
d="M330.088 309.401c7.794-1.585 12.826-9.188 11.241-16.981-1.585-7.794-9.187-12.827-16.981-11.242-7.793 1.585-12.826 9.188-11.241 16.981 1.585 7.794 9.188 12.827 16.981 11.242Z"
|
||||
/>
|
||||
<path
|
||||
class="tw-fill-illustration-bg-primary"
|
||||
d="M234.598 327.597c7.793-1.585 12.826-9.187 11.241-16.981-1.585-7.793-9.187-12.826-16.981-11.241-7.793 1.585-12.826 9.188-11.241 16.981 1.585 7.794 9.188 12.826 16.981 11.241Z"
|
||||
/>
|
||||
<path
|
||||
class="tw-fill-illustration-bg-secondary"
|
||||
d="M176.919 248.71c7.794-1.585 12.827-9.188 11.242-16.981-1.586-7.794-9.188-12.827-16.982-11.242-7.793 1.586-12.826 9.188-11.241 16.982 1.585 7.793 9.188 12.826 16.981 11.241Z"
|
||||
/>
|
||||
<path
|
||||
class="tw-fill-illustration-bg-tertiary"
|
||||
d="M206.836 185.071c7.794-1.585 12.827-9.188 11.242-16.981-1.586-7.793-9.188-12.826-16.982-11.241-7.793 1.585-12.826 9.188-11.241 16.981 1.585 7.793 9.188 12.826 16.981 11.241Z"
|
||||
/>
|
||||
<path
|
||||
class="tw-fill-illustration-outline"
|
||||
fill-rule="evenodd"
|
||||
d="M200.699 154.89c8.875-1.805 17.533 3.927 19.339 12.803 1.165 5.732-.814 11.372-4.752 15.135.131.223.29.502.489.845l14.805 21.386a41.483 41.483 0 0 1 12.979-5.007c9.276-1.886 18.455-.523 26.321 3.303.038-.221.111-.441.227-.648l17.035-30.333a16.337 16.337 0 0 1-6.09-9.744c-1.805-8.876 3.928-17.535 12.803-19.34 8.876-1.805 17.534 3.928 19.339 12.803 1.805 8.876-3.926 17.534-12.802 19.339-3.427.697-6.822.27-9.803-1.028l-16.994 30.262a1.98 1.98 0 0 1-.397.497c8.774 5.316 15.487 13.883 18.16 24.43l19.238-1.61c-.007-7.642 5.356-14.488 13.135-16.07 8.875-1.805 17.534 3.927 19.339 12.803 1.805 8.875-3.927 17.533-12.802 19.339-8.639 1.757-17.072-3.627-19.18-12.099l-18.935 1.585c1.474 9.839-.81 19.465-5.834 27.387l29.108 22.962a16.324 16.324 0 0 1 8.523-4.671c8.876-1.804 17.534 3.928 19.339 12.803 1.805 8.876-3.927 17.534-12.802 19.339-8.875 1.805-17.534-3.926-19.34-12.802a16.338 16.338 0 0 1 1.872-11.474l-29.007-22.882c-5.828 7.464-14.29 12.983-24.349 15.028a41.442 41.442 0 0 1-14.045.441l-6.224 19.317a16.365 16.365 0 0 1 8.405 11.229c1.805 8.876-3.927 17.534-12.802 19.339-8.876 1.805-17.535-3.926-19.34-12.802-1.805-8.875 3.927-17.534 12.803-19.34 2.461-.5 4.906-.42 7.192.145l6.007-18.641c-14.851-3.594-27.011-15.301-30.225-31.105a40.043 40.043 0 0 1-.808-8.184l-20.473-1.442c-.032-.002-.064-.008-.096-.011-1.37 6.114-6.201 11.162-12.739 12.492-8.875 1.805-17.534-3.926-19.339-12.802-1.805-8.875 3.927-17.534 12.802-19.34 8.876-1.804 17.534 3.928 19.339 12.803.196.962.302 1.921.327 2.869l20.401 1.436c1.206-11.333 7.247-21.627 16.399-28.363l-14.76-21.321a20.41 20.41 0 0 0-.435-.719 16.428 16.428 0 0 1-4.816 1.8c-8.876 1.805-17.535-3.927-19.34-12.802-1.805-8.876 3.927-17.535 12.803-19.34Zm124.048 128.249c-6.711 1.365-11.045 7.912-9.68 14.623 1.365 6.711 7.912 11.044 14.623 9.679 6.71-1.365 11.044-7.911 9.679-14.622-1.364-6.71-7.911-11.044-14.622-9.68Zm-95.49 18.196c-6.711 1.365-11.045 7.912-9.68 14.623 1.365 6.711 7.912 11.044 14.623 9.679 6.71-1.365 11.044-7.911 9.679-14.621-1.365-6.711-7.911-11.045-14.622-9.681Zm15.1-97.363c-20.054 4.079-33.004 23.373-29.004 43.044 4.001 19.672 23.459 32.374 43.513 28.296 9.593-1.951 17.558-7.386 22.822-14.676a1.986 1.986 0 0 1 .612-.873c5.306-7.813 7.58-17.606 5.569-27.495-4.001-19.671-23.459-32.374-43.512-28.296Zm80.171 11.861c-6.711 1.364-11.045 7.912-9.68 14.623 1.365 6.71 7.912 11.044 14.623 9.679 6.71-1.365 11.044-7.911 9.679-14.622-1.365-6.711-7.911-11.045-14.622-9.68Zm-152.949 6.614c-6.711 1.365-11.045 7.912-9.681 14.623 1.365 6.711 7.912 11.044 14.623 9.679 6.711-1.365 11.044-7.911 9.68-14.621-1.365-6.711-7.912-11.045-14.622-9.681Zm123.073-75.237c-6.71 1.365-11.044 7.912-9.68 14.623 1.365 6.711 7.912 11.044 14.623 9.679 6.711-1.365 11.044-7.911 9.68-14.622-1.365-6.71-7.912-11.045-14.623-9.68Zm-93.156 11.6c-6.711 1.364-11.045 7.912-9.68 14.623 1.365 6.71 7.912 11.044 14.622 9.679 6.711-1.365 11.044-7.912 9.68-14.622-1.365-6.711-7.911-11.045-14.622-9.68Z"
|
||||
clip-rule="evenodd"
|
||||
/>
|
||||
<path
|
||||
class="tw-fill-illustration-logo"
|
||||
d="M272.266 232.544a1.998 1.998 0 0 0-.353 1.589l.554 2.725a2.002 2.002 0 0 0 1.002 1.357l4.786 2.611a2 2 0 0 1 1.003 2.15l-.667 3.313a1.998 1.998 0 0 1-1.647 1.58l-5.641.896a1.998 1.998 0 0 0-1.352.867l-1.524 2.291a2 2 0 0 0-.252 1.678l1.555 5.227a2 2 0 0 1-.794 2.224l-2.799 1.902a2 2 0 0 1-2.309-.043l-4.524-3.327a2 2 0 0 0-1.583-.348l-2.754.56a1.997 1.997 0 0 0-1.352.994l-2.638 4.785a2 2 0 0 1-2.14.996l-3.339-.661a2 2 0 0 1-1.587-1.649l-.886-5.597a2.003 2.003 0 0 0-.875-1.358l-2.298-1.514a2 2 0 0 0-1.669-.247l-5.272 1.563a2 2 0 0 1-2.22-.788l-1.897-2.774a2.001 2.001 0 0 1 .045-2.321l3.339-4.498a2.004 2.004 0 0 0 .354-1.591l-.557-2.736a2.001 2.001 0 0 0-.983-1.347l-4.848-2.715a2 2 0 0 1-.983-2.14l.669-3.329a2.001 2.001 0 0 1 1.648-1.581l5.641-.895a1.999 1.999 0 0 0 1.352-.868l1.526-2.293c.327-.493.42-1.105.253-1.673l-1.608-5.457a2 2 0 0 1 .794-2.22l2.793-1.897a2 2 0 0 1 2.322.053l4.676 3.5a1.999 1.999 0 0 0 1.597.359l2.744-.558a2.002 2.002 0 0 0 1.353-.995l2.637-4.784a1.997 1.997 0 0 1 2.14-.996l3.339.661a2 2 0 0 1 1.587 1.649l.886 5.597c.088.555.406 1.048.875 1.357l2.298 1.514a2.002 2.002 0 0 0 1.669.248l5.272-1.564a2 2 0 0 1 2.22.789l1.898 2.775a2 2 0 0 1-.044 2.319l-3.432 4.635Zm-24.977-.064c-4.049 2.702-5.078 8.076-2.395 11.991 2.705 4.028 8.1 5.044 12.035 2.365 3.936-2.678 5.078-8.076 2.395-11.991-2.592-4.051-7.986-5.067-12.035-2.365Z"
|
||||
/>
|
||||
<path
|
||||
class="tw-fill-illustration-outline"
|
||||
d="m270.507 237.256-.554-2.724a4.004 4.004 0 0 1 .705-3.178l3.433-4.636-1.897-2.775-5.273 1.564a4 4 0 0 1-3.337-.494l-2.298-1.515a4 4 0 0 1-1.751-2.714l-.886-5.597-3.339-.661-2.637 4.784a4.001 4.001 0 0 1-2.706 1.989l-2.744.558a4 4 0 0 1-3.194-.718l-4.676-3.5-2.792 1.898 1.608 5.457a3.998 3.998 0 0 1-.507 3.345l-1.525 2.294c-.62.931-1.6 1.56-2.704 1.736l-5.642.895-.669 3.329 4.848 2.715a4 4 0 0 1 1.965 2.693l.557 2.737a3.999 3.999 0 0 1-.708 3.18l-3.338 4.499 1.897 2.774 5.272-1.563a3.998 3.998 0 0 1 3.338.494l2.298 1.514a4.001 4.001 0 0 1 1.75 2.715l.886 5.597 3.339.661 2.638-4.785a4 4 0 0 1 2.706-1.988l2.753-.56a4 4 0 0 1 3.166.697l4.524 3.327 2.8-1.902-1.555-5.227a4.002 4.002 0 0 1 .504-3.355l1.524-2.291a3.998 3.998 0 0 1 2.703-1.736l5.642-.895.667-3.313-4.787-2.611a4.004 4.004 0 0 1-2.004-2.714Zm-24.328-6.439c4.915-3.28 11.556-2.099 14.795 2.898h.001v.001l.034.051h-.001c3.294 4.868 1.835 11.464-2.953 14.723-4.855 3.304-11.499 2.043-14.821-2.903l.001-.001c-3.308-4.845-2.013-11.461 2.944-14.769Zm11.461 5.106c-1.959-3.06-6.075-3.891-9.24-1.779-3.036 2.026-3.85 5.957-2.039 8.913l.183.284.01.015c2.089 3.109 6.234 3.879 9.25 1.827 3.066-2.087 3.897-6.25 1.871-9.207a.97.97 0 0 1-.035-.053Zm16.787.536 4.787 2.611a4 4 0 0 1 2.005 4.3l-.666 3.313a4.001 4.001 0 0 1-3.295 3.161l-5.641.896-1.525 2.291 1.555 5.227a4.002 4.002 0 0 1-1.586 4.449l-2.8 1.901a4 4 0 0 1-4.618-.086l-4.523-3.326-2.753.56-2.638 4.784a4 4 0 0 1-4.279 1.993l-3.34-.661a4.002 4.002 0 0 1-3.174-3.298l-.886-5.598-2.298-1.514-5.273 1.564a3.999 3.999 0 0 1-4.438-1.577l-1.897-2.774a3.998 3.998 0 0 1 .09-4.641l3.338-4.499-.557-2.737-4.848-2.715a3.998 3.998 0 0 1-1.966-4.279l.669-3.329a4.002 4.002 0 0 1 3.294-3.162l5.642-.895 1.526-2.294-1.609-5.457a4.001 4.001 0 0 1 1.59-4.439l2.792-1.897a4 4 0 0 1 4.645.106l4.676 3.5 2.744-.558 2.636-4.785a4 4 0 0 1 4.281-1.992l3.339.661a4 4 0 0 1 3.174 3.298l.886 5.597 2.298 1.514 5.272-1.563a4 4 0 0 1 4.439 1.576l1.898 2.775a4.001 4.001 0 0 1-.087 4.639l-3.433 4.636.554 2.724Z"
|
||||
/>
|
||||
</g>
|
||||
<defs>
|
||||
<clipPath id="right-a">
|
||||
<path class="tw-fill-illustration-bg-tertiary" d="M0 0h506v297H0z" />
|
||||
</clipPath>
|
||||
</defs>
|
||||
</svg>
|
||||
</div>
|
||||
</div>
|
||||
</body>
|
||||
</html>
|
||||
|
||||
@@ -1,8 +1,13 @@
|
||||
// FIXME: Update this file to be type safe and remove this and next line
|
||||
// @ts-strict-ignore
|
||||
import { Directive } from "@angular/core";
|
||||
import { Directive, OnDestroy } from "@angular/core";
|
||||
import { FormControl, FormGroup } from "@angular/forms";
|
||||
import { ActivatedRoute } from "@angular/router";
|
||||
import { combineLatest, filter, map, Observable, Subject, switchMap, takeUntil } from "rxjs";
|
||||
|
||||
import { OrganizationService } from "@bitwarden/common/admin-console/abstractions/organization/organization.service.abstraction";
|
||||
import { Organization } from "@bitwarden/common/admin-console/models/domain/organization";
|
||||
import { Account, AccountService } from "@bitwarden/common/auth/abstractions/account.service";
|
||||
import { EventResponse } from "@bitwarden/common/models/response/event.response";
|
||||
import { ListResponse } from "@bitwarden/common/models/response/list.response";
|
||||
import { EventView } from "@bitwarden/common/models/view/event.view";
|
||||
@@ -12,16 +17,17 @@ import { LogService } from "@bitwarden/common/platform/abstractions/log.service"
|
||||
import { PlatformUtilsService } from "@bitwarden/common/platform/abstractions/platform-utils.service";
|
||||
import { ToastService } from "@bitwarden/components";
|
||||
|
||||
import { EventService } from "../../core";
|
||||
import { EventOptions, EventService } from "../../core";
|
||||
import { EventExportService } from "../../tools/event-export";
|
||||
|
||||
@Directive()
|
||||
export abstract class BaseEventsComponent {
|
||||
export abstract class BaseEventsComponent implements OnDestroy {
|
||||
loading = true;
|
||||
loaded = false;
|
||||
events: EventView[];
|
||||
dirtyDates = true;
|
||||
continuationToken: string;
|
||||
canUseSM = false;
|
||||
|
||||
abstract readonly exportFileName: string;
|
||||
|
||||
@@ -30,6 +36,15 @@ export abstract class BaseEventsComponent {
|
||||
end: new FormControl(null),
|
||||
});
|
||||
|
||||
protected canUseSM$: Observable<boolean>;
|
||||
protected activeOrganization$: Observable<Organization | undefined>;
|
||||
protected organizations$: Observable<Organization[]>;
|
||||
private destroySubject$ = new Subject<void>();
|
||||
|
||||
protected get destroy$(): Observable<void> {
|
||||
return this.destroySubject$.asObservable();
|
||||
}
|
||||
|
||||
constructor(
|
||||
protected eventService: EventService,
|
||||
protected i18nService: I18nService,
|
||||
@@ -38,12 +53,39 @@ export abstract class BaseEventsComponent {
|
||||
protected logService: LogService,
|
||||
protected fileDownloadService: FileDownloadService,
|
||||
private toastService: ToastService,
|
||||
protected activeRoute: ActivatedRoute,
|
||||
protected accountService: AccountService,
|
||||
protected organizationService: OrganizationService,
|
||||
) {
|
||||
const defaultDates = this.eventService.getDefaultDateFilters();
|
||||
this.start = defaultDates[0];
|
||||
this.end = defaultDates[1];
|
||||
}
|
||||
|
||||
protected initBase(): void {
|
||||
this.organizations$ = this.accountService.activeAccount$.pipe(
|
||||
filter((account): account is Account => !!account?.id),
|
||||
switchMap((account) => this.organizationService.organizations$(account.id)),
|
||||
);
|
||||
|
||||
this.activeOrganization$ = combineLatest([this.activeRoute.paramMap, this.organizations$]).pipe(
|
||||
map(([params, orgs]) => orgs.find((org) => org.id === params.get("organizationId"))),
|
||||
);
|
||||
|
||||
this.canUseSM$ = this.activeOrganization$.pipe(
|
||||
map((org) => org?.canAccessSecretsManager ?? false),
|
||||
);
|
||||
|
||||
this.canUseSM$.pipe(takeUntil(this.destroy$)).subscribe((value) => {
|
||||
this.canUseSM = value;
|
||||
});
|
||||
}
|
||||
|
||||
ngOnDestroy(): void {
|
||||
this.destroySubject$.next();
|
||||
this.destroySubject$.complete();
|
||||
}
|
||||
|
||||
get start(): string {
|
||||
return this.eventsForm.value.start;
|
||||
}
|
||||
@@ -139,7 +181,10 @@ export abstract class BaseEventsComponent {
|
||||
const events = await Promise.all(
|
||||
response.data.map(async (r) => {
|
||||
const userId = r.actingUserId == null ? r.userId : r.actingUserId;
|
||||
const eventInfo = await this.eventService.getEventInfo(r);
|
||||
const options = new EventOptions();
|
||||
options.disableLink = !this.canUseSM;
|
||||
|
||||
const eventInfo = await this.eventService.getEventInfo(r, options);
|
||||
const user = this.getUserName(r, userId);
|
||||
const userName = user != null ? user.name : this.i18nService.t("unknown");
|
||||
|
||||
|
||||
@@ -1 +0,0 @@
|
||||
export * from "./devices";
|
||||
@@ -1,15 +1,11 @@
|
||||
import { Component, EventEmitter, Input, Output } from "@angular/core";
|
||||
|
||||
import { ButtonModule, NoItemsModule, svgIcon } from "@bitwarden/components";
|
||||
import { RestrictedView } from "@bitwarden/assets/svg";
|
||||
import { ButtonModule, NoItemsModule } from "@bitwarden/components";
|
||||
|
||||
import { SharedModule } from "../../../shared";
|
||||
import { CollectionDialogTabType } from "../shared/components/collection-dialog";
|
||||
|
||||
const icon = svgIcon`<svg xmlns="http://www.w3.org/2000/svg" width="120" height="120" viewBox="10 -10 120 140" fill="none">
|
||||
<rect class="tw-stroke-secondary-600" width="134" height="86" x="3" y="31.485" stroke-width="6" rx="11"/>
|
||||
<path class="tw-fill-secondary-600" d="M123.987 20.15H14.779a3.114 3.114 0 0 1-2.083-.95 3.036 3.036 0 0 1 0-4.208 3.125 3.125 0 0 1 2.083-.951h109.208c.792.043 1.536.38 2.083.95a3.035 3.035 0 0 1 0 4.208 3.115 3.115 0 0 1-2.083.95Zm-6.649-14.041h-95.91a3.114 3.114 0 0 1-2.082-.95 3.036 3.036 0 0 1-.848-2.105c0-.782.306-1.538.848-2.104A3.125 3.125 0 0 1 21.43 0h95.909c.791.043 1.535.38 2.082.95.547.57.849 1.322.849 2.104a3.05 3.05 0 0 1-.849 2.104 3.115 3.115 0 0 1-2.082.95ZM95.132 74.407A42.317 42.317 0 0 0 83.59 65.43l8.799-8.657a1.59 1.59 0 0 0 .004-2.27 1.641 1.641 0 0 0-2.298-.004l-9.64 9.479a28.017 28.017 0 0 0-10.483-2.13c-14.323 0-24.814 12.342-25.298 12.89a2.431 2.431 0 0 0-.675 1.64c-.01.612.215 1.203.626 1.66a43.981 43.981 0 0 0 11.873 9.485l-8.806 8.658a1.601 1.601 0 0 0-.499 1.138 1.602 1.602 0 0 0 1.008 1.5 1.651 1.651 0 0 0 1.255-.009c.199-.085.379-.205.528-.359l9.634-9.443a27.16 27.16 0 0 0 10.359 2.158c14.323 0 24.753-12.086 25.23-12.63a2.983 2.983 0 0 0-.078-4.128h.002ZM49.204 77.82a1.82 1.82 0 0 1-.43-.6 1.767 1.767 0 0 1-.152-.72 1.778 1.778 0 0 1 .582-1.32c3.857-3.564 11.782-9.686 20.77-9.676 2.564.037 5.105.508 7.508 1.395l-3.291 3.235a7.793 7.793 0 0 0-5.02-1.226 7.746 7.746 0 0 0-4.676 2.18 7.528 7.528 0 0 0-1 9.563l-4.199 4.143a43.135 43.135 0 0 1-10.092-6.974Zm26.059-1.318a5.19 5.19 0 0 1-1.557 3.68 5.326 5.326 0 0 1-3.733 1.521c-.82-.005-1.63-.2-2.359-.57l7.067-6.952c.377.718.575 1.513.582 2.321Zm-10.58 0a5.136 5.136 0 0 1 .673-2.555 5.204 5.204 0 0 1 1.862-1.897 5.302 5.302 0 0 1 5.172-.146l-7.096 6.977a5.06 5.06 0 0 1-.61-2.379Zm26.053 1.331c-3.857 3.56-11.779 9.677-20.763 9.677a22.723 22.723 0 0 1-7.454-1.369l3.292-3.226a7.793 7.793 0 0 0 4.995 1.192 7.734 7.734 0 0 0 4.642-2.176 7.524 7.524 0 0 0 1.033-9.506l4.224-4.168a43.258 43.258 0 0 1 10.02 6.945 1.788 1.788 0 0 1 .585 1.313 1.788 1.788 0 0 1-.577 1.318h.003Z"/>
|
||||
</svg>`;
|
||||
|
||||
@Component({
|
||||
selector: "collection-access-restricted",
|
||||
imports: [SharedModule, ButtonModule, NoItemsModule],
|
||||
@@ -38,7 +34,7 @@ const icon = svgIcon`<svg xmlns="http://www.w3.org/2000/svg" width="120" height=
|
||||
</bit-no-items>`,
|
||||
})
|
||||
export class CollectionAccessRestrictedComponent {
|
||||
protected icon = icon;
|
||||
protected icon = RestrictedView;
|
||||
protected collectionDialogTabType = CollectionDialogTabType;
|
||||
|
||||
@Input() canEditCollection = false;
|
||||
|
||||
@@ -34,6 +34,7 @@
|
||||
[bitMenuTriggerFor]="editCollectionMenu"
|
||||
size="small"
|
||||
type="button"
|
||||
[label]="'editCollection' | i18n"
|
||||
></button>
|
||||
<bit-menu #editCollectionMenu>
|
||||
<ng-container *ngIf="canEditCollection">
|
||||
|
||||
@@ -34,6 +34,7 @@ import {
|
||||
Unassigned,
|
||||
} from "@bitwarden/admin-console/common";
|
||||
import { SearchPipe } from "@bitwarden/angular/pipes/search.pipe";
|
||||
import { Search } from "@bitwarden/assets/svg";
|
||||
import { ApiService } from "@bitwarden/common/abstractions/api.service";
|
||||
import { EventCollectionService } from "@bitwarden/common/abstractions/event/event-collection.service";
|
||||
import { OrganizationApiServiceAbstraction } from "@bitwarden/common/admin-console/abstractions/organization/organization-api.service.abstraction";
|
||||
@@ -66,7 +67,6 @@ import {
|
||||
BannerModule,
|
||||
DialogRef,
|
||||
DialogService,
|
||||
Icons,
|
||||
NoItemsModule,
|
||||
ToastService,
|
||||
} from "@bitwarden/components";
|
||||
@@ -170,7 +170,7 @@ export class VaultComponent implements OnInit, OnDestroy {
|
||||
activeFilter: VaultFilter = new VaultFilter();
|
||||
|
||||
protected showAddAccessToggle = false;
|
||||
protected noItemIcon = Icons.Search;
|
||||
protected noItemIcon = Search;
|
||||
protected performingInitialLoad = true;
|
||||
protected refreshing = false;
|
||||
protected processingEvent = false;
|
||||
|
||||
@@ -6,6 +6,7 @@ import { ActivatedRoute, RouterModule } from "@angular/router";
|
||||
import { combineLatest, filter, map, Observable, switchMap, withLatestFrom } from "rxjs";
|
||||
|
||||
import { JslibModule } from "@bitwarden/angular/jslib.module";
|
||||
import { AdminConsoleLogo } from "@bitwarden/assets/svg";
|
||||
import {
|
||||
canAccessBillingTab,
|
||||
canAccessGroupsTab,
|
||||
@@ -27,7 +28,7 @@ import { FeatureFlag } from "@bitwarden/common/enums/feature-flag.enum";
|
||||
import { ConfigService } from "@bitwarden/common/platform/abstractions/config/config.service";
|
||||
import { PlatformUtilsService } from "@bitwarden/common/platform/abstractions/platform-utils.service";
|
||||
import { getById } from "@bitwarden/common/platform/misc";
|
||||
import { BannerModule, IconModule, AdminConsoleLogo } from "@bitwarden/components";
|
||||
import { BannerModule, IconModule } from "@bitwarden/components";
|
||||
import { OrganizationWarningsModule } from "@bitwarden/web-vault/app/billing/organizations/warnings/organization-warnings.module";
|
||||
import { OrganizationWarningsService } from "@bitwarden/web-vault/app/billing/organizations/warnings/services";
|
||||
import { NonIndividualSubscriber } from "@bitwarden/web-vault/app/billing/types";
|
||||
|
||||
@@ -8,6 +8,8 @@ import { firstValueFrom, switchMap } from "rxjs";
|
||||
import { OrganizationUserApiService } from "@bitwarden/admin-console/common";
|
||||
import { UserNamePipe } from "@bitwarden/angular/pipes/user-name.pipe";
|
||||
import { ApiService } from "@bitwarden/common/abstractions/api.service";
|
||||
import { OrganizationService } from "@bitwarden/common/admin-console/abstractions/organization/organization.service.abstraction";
|
||||
import { AccountService } from "@bitwarden/common/auth/abstractions/account.service";
|
||||
import { EventResponse } from "@bitwarden/common/models/response/event.response";
|
||||
import { ListResponse } from "@bitwarden/common/models/response/list.response";
|
||||
import { EventView } from "@bitwarden/common/models/view/event.view";
|
||||
@@ -26,7 +28,7 @@ import { EventService } from "../../../core";
|
||||
import { SharedModule } from "../../../shared";
|
||||
|
||||
export interface EntityEventsDialogParams {
|
||||
entity: "user" | "cipher";
|
||||
entity: "user" | "cipher" | "secret" | "project";
|
||||
entityId: string;
|
||||
|
||||
organizationId?: string;
|
||||
@@ -72,6 +74,8 @@ export class EntityEventsComponent implements OnInit, OnDestroy {
|
||||
private toastService: ToastService,
|
||||
private router: Router,
|
||||
private activeRoute: ActivatedRoute,
|
||||
private accountService: AccountService,
|
||||
protected organizationService: OrganizationService,
|
||||
) {}
|
||||
|
||||
async ngOnInit() {
|
||||
@@ -162,6 +166,22 @@ export class EntityEventsComponent implements OnInit, OnDestroy {
|
||||
dates[1],
|
||||
clearExisting ? null : this.continuationToken,
|
||||
);
|
||||
} else if (this.params.entity === "secret") {
|
||||
response = await this.apiService.getEventsSecret(
|
||||
this.params.organizationId,
|
||||
this.params.entityId,
|
||||
dates[0],
|
||||
dates[1],
|
||||
clearExisting ? null : this.continuationToken,
|
||||
);
|
||||
} else if (this.params.entity === "project") {
|
||||
response = await this.apiService.getEventsProject(
|
||||
this.params.organizationId,
|
||||
this.params.entityId,
|
||||
dates[0],
|
||||
dates[1],
|
||||
clearExisting ? null : this.continuationToken,
|
||||
);
|
||||
} else {
|
||||
response = await this.apiService.getEventsCipher(
|
||||
this.params.entityId,
|
||||
|
||||
@@ -1,8 +1,8 @@
|
||||
// FIXME: Update this file to be type safe and remove this and next line
|
||||
// @ts-strict-ignore
|
||||
import { Component, OnDestroy, OnInit } from "@angular/core";
|
||||
import { ActivatedRoute, Router } from "@angular/router";
|
||||
import { concatMap, firstValueFrom, lastValueFrom, Subject, takeUntil } from "rxjs";
|
||||
import { ActivatedRoute } from "@angular/router";
|
||||
import { concatMap, firstValueFrom, lastValueFrom, takeUntil } from "rxjs";
|
||||
|
||||
import { OrganizationUserApiService } from "@bitwarden/admin-console/common";
|
||||
import { UserNamePipe } from "@bitwarden/angular/pipes/user-name.pipe";
|
||||
@@ -60,8 +60,6 @@ export class EventsComponent extends BaseEventsComponent implements OnInit, OnDe
|
||||
placeholderEvents = placeholderEvents as EventView[];
|
||||
|
||||
private orgUsersUserIdMap = new Map<string, any>();
|
||||
private destroy$ = new Subject<void>();
|
||||
|
||||
readonly ProductTierType = ProductTierType;
|
||||
|
||||
protected isBreadcrumbEventLogsEnabled$ = this.configService.getFeatureFlag$(
|
||||
@@ -75,18 +73,18 @@ export class EventsComponent extends BaseEventsComponent implements OnInit, OnDe
|
||||
i18nService: I18nService,
|
||||
exportService: EventExportService,
|
||||
platformUtilsService: PlatformUtilsService,
|
||||
private router: Router,
|
||||
logService: LogService,
|
||||
private userNamePipe: UserNamePipe,
|
||||
private organizationService: OrganizationService,
|
||||
protected organizationService: OrganizationService,
|
||||
private organizationUserApiService: OrganizationUserApiService,
|
||||
private organizationApiService: OrganizationApiServiceAbstraction,
|
||||
private providerService: ProviderService,
|
||||
fileDownloadService: FileDownloadService,
|
||||
toastService: ToastService,
|
||||
private accountService: AccountService,
|
||||
protected accountService: AccountService,
|
||||
private dialogService: DialogService,
|
||||
private configService: ConfigService,
|
||||
protected activeRoute: ActivatedRoute,
|
||||
) {
|
||||
super(
|
||||
eventService,
|
||||
@@ -96,10 +94,15 @@ export class EventsComponent extends BaseEventsComponent implements OnInit, OnDe
|
||||
logService,
|
||||
fileDownloadService,
|
||||
toastService,
|
||||
activeRoute,
|
||||
accountService,
|
||||
organizationService,
|
||||
);
|
||||
}
|
||||
|
||||
async ngOnInit() {
|
||||
this.initBase();
|
||||
|
||||
const userId = await firstValueFrom(getUserId(this.accountService.activeAccount$));
|
||||
this.route.params
|
||||
.pipe(
|
||||
@@ -233,9 +236,4 @@ export class EventsComponent extends BaseEventsComponent implements OnInit, OnDe
|
||||
}
|
||||
await this.load();
|
||||
}
|
||||
|
||||
ngOnDestroy() {
|
||||
this.destroy$.next();
|
||||
this.destroy$.complete();
|
||||
}
|
||||
}
|
||||
|
||||
@@ -80,7 +80,7 @@
|
||||
bitIconButton="bwi-trash"
|
||||
bitFormButton
|
||||
[bitAction]="delete"
|
||||
[appA11yTitle]="'delete' | i18n"
|
||||
[label]="'delete' | i18n"
|
||||
></button>
|
||||
</ng-container>
|
||||
</bit-dialog>
|
||||
|
||||
@@ -46,7 +46,7 @@
|
||||
type="button"
|
||||
bitIconButton="bwi-ellipsis-v"
|
||||
size="small"
|
||||
appA11yTitle="{{ 'options' | i18n }}"
|
||||
label="{{ 'options' | i18n }}"
|
||||
></button>
|
||||
|
||||
<bit-menu #headerMenu>
|
||||
@@ -82,7 +82,7 @@
|
||||
type="button"
|
||||
bitIconButton="bwi-ellipsis-v"
|
||||
size="small"
|
||||
appA11yTitle="{{ 'options' | i18n }}"
|
||||
label="{{ 'options' | i18n }}"
|
||||
></button>
|
||||
|
||||
<bit-menu #rowMenu>
|
||||
|
||||
@@ -106,7 +106,7 @@
|
||||
type="button"
|
||||
bitIconButton="bwi-ellipsis-v"
|
||||
size="small"
|
||||
appA11yTitle="{{ 'options' | i18n }}"
|
||||
label="{{ 'options' | i18n }}"
|
||||
*ngIf="showUserManagementControls$ | async"
|
||||
></button>
|
||||
|
||||
@@ -350,7 +350,7 @@
|
||||
type="button"
|
||||
bitIconButton="bwi-ellipsis-v"
|
||||
size="small"
|
||||
appA11yTitle="{{ 'options' | i18n }}"
|
||||
label="{{ 'options' | i18n }}"
|
||||
></button>
|
||||
|
||||
<bit-menu #rowMenu>
|
||||
|
||||
@@ -51,7 +51,7 @@ const render: Story["render"] = (args) => ({
|
||||
buttonType="danger"
|
||||
size="default"
|
||||
title="Delete"
|
||||
aria-label="Delete"></button>
|
||||
label="Delete"></button>
|
||||
</ng-container>
|
||||
</bit-dialog>
|
||||
`,
|
||||
|
||||
@@ -122,7 +122,7 @@
|
||||
type="button"
|
||||
bitIconButton="bwi-close"
|
||||
buttonType="muted"
|
||||
appA11yTitle="{{ 'remove' | i18n }} {{ item.labelName }}"
|
||||
label="{{ 'remove' | i18n }} {{ item.labelName }}"
|
||||
[disabled]="disabled"
|
||||
(click)="selectionList.deselectItem(item.id); handleBlur()"
|
||||
></button>
|
||||
|
||||
@@ -143,7 +143,7 @@
|
||||
buttonType="danger"
|
||||
class="tw-ml-auto"
|
||||
bitFormButton
|
||||
[appA11yTitle]="'delete' | i18n"
|
||||
[label]="'delete' | i18n"
|
||||
[bitAction]="delete"
|
||||
[disabled]="loading"
|
||||
></button>
|
||||
|
||||
@@ -4,10 +4,11 @@ import { CommonModule } from "@angular/common";
|
||||
import { Component, inject } from "@angular/core";
|
||||
import { Params } from "@angular/router";
|
||||
|
||||
import { BitwardenLogo } from "@bitwarden/assets/svg";
|
||||
import { PolicyApiServiceAbstraction } from "@bitwarden/common/admin-console/abstractions/policy/policy-api.service.abstraction";
|
||||
import { OrganizationSponsorshipResponse } from "@bitwarden/common/admin-console/models/response/organization-sponsorship.response";
|
||||
import { ConfigService } from "@bitwarden/common/platform/abstractions/config/config.service";
|
||||
import { IconModule, Icons, ToastService } from "@bitwarden/components";
|
||||
import { IconModule, ToastService } from "@bitwarden/components";
|
||||
import { I18nPipe } from "@bitwarden/ui-common";
|
||||
|
||||
import { BaseAcceptComponent } from "../../../common/base.accept.component";
|
||||
@@ -22,7 +23,7 @@ import { BaseAcceptComponent } from "../../../common/base.accept.component";
|
||||
imports: [CommonModule, I18nPipe, IconModule],
|
||||
})
|
||||
export class AcceptFamilySponsorshipComponent extends BaseAcceptComponent {
|
||||
protected logo = Icons.BitwardenLogo;
|
||||
protected logo = BitwardenLogo;
|
||||
failedShortMessage = "inviteAcceptFailedShort";
|
||||
failedMessage = "inviteAcceptFailed";
|
||||
|
||||
|
||||
@@ -2,8 +2,10 @@
|
||||
<!-- This is the same html from index.html which presents the bitwarden logo and loading spinny properly
|
||||
when the body has the layout_frontend class. Having this match the index allows for a duplicative yet seamless
|
||||
loading state here for process reloading. -->
|
||||
<div class="tw-p-8 tw-flex">
|
||||
<img class="new-logo-themed" alt="Bitwarden" />
|
||||
<div class="tw-flex tw-flex-col tw-min-h-[100vh]">
|
||||
<div class="tw-pt-5 tw-px-5 tw-fixed">
|
||||
<img class="new-logo-themed !tw-w-[200px]" alt="Bitwarden" />
|
||||
</div>
|
||||
<div class="spinner-container tw-justify-center">
|
||||
<i
|
||||
class="bwi bwi-spinner bwi-spin bwi-3x tw-text-muted"
|
||||
@@ -11,6 +13,190 @@
|
||||
aria-hidden="true"
|
||||
></i>
|
||||
</div>
|
||||
<div class="tw-relative tw-grow">
|
||||
<div
|
||||
class="tw-hidden md:tw-block [&_svg]:tw-absolute [&_svg]:tw-z-[1] tw-opacity-[.11] [&_svg]:tw-bottom-0 [&_svg]:tw-start-0 [&_svg]:tw-w-[35%] [&_svg]:tw-max-w-[450px]"
|
||||
>
|
||||
<svg xmlns="http://www.w3.org/2000/svg" fill="none" viewBox="0 0 501 226">
|
||||
<g clip-path="url(#left-a)">
|
||||
<path
|
||||
class="tw-fill-illustration-bg-primary"
|
||||
d="M-71.691 6.821a4 4 0 0 1 4-4h296.5a4 4 0 0 1 4 4v188a4 4 0 0 1-4 4h-296.5a4 4 0 0 1-4-4v-188Z"
|
||||
/>
|
||||
<path
|
||||
class="tw-fill-illustration-bg-primary"
|
||||
d="M-48.941 25.821a2 2 0 0 1 2-2h127.5v154h-127.5a2 2 0 0 1-2-2v-150Z"
|
||||
/>
|
||||
<path
|
||||
class="tw-fill-illustration-bg-tertiary"
|
||||
d="M80.559 25.82a2 2 0 0 1 2-2h125.5a2 2 0 0 1 2 2v150.001a2 2 0 0 1-2 2h-125.5a2 2 0 0 1-2-2v-150ZM45.871 89.854c0 17.155-13.96 31.062-31.182 31.062-17.221 0-31.182-13.907-31.182-31.062s13.96-31.062 31.182-31.062c17.221 0 31.182 13.907 31.182 31.062Z"
|
||||
/>
|
||||
<path
|
||||
class="tw-fill-illustration-bg-tertiary"
|
||||
d="M72.396 153.443a57.243 57.243 0 0 1 4.663 22.604v1.222a2 2 0 0 1-2 2h-118.5a2 2 0 0 1-2-2v-1.222a57.243 57.243 0 0 1 4.662-22.604c3.078-7.167 7.59-13.678 13.277-19.163 5.688-5.485 12.44-9.836 19.871-12.805a63.228 63.228 0 0 1 23.44-4.496 63.227 63.227 0 0 1 23.439 4.496c7.431 2.969 14.183 7.32 19.87 12.805 5.688 5.485 10.2 11.996 13.278 19.163Z"
|
||||
/>
|
||||
<path
|
||||
class="tw-fill-illustration-bg-secondary"
|
||||
d="M161.629 57.193c0 9.182-7.579 16.625-16.927 16.625-9.349 0-16.928-7.443-16.928-16.625 0-9.181 7.579-16.625 16.928-16.625 9.348 0 16.927 7.444 16.927 16.625Z"
|
||||
/>
|
||||
<path
|
||||
class="tw-fill-illustration-bg-secondary"
|
||||
d="M176.028 89.071a29.33 29.33 0 0 1 2.531 11.894c0 .937-.759 1.696-1.696 1.696h-63.109a1.695 1.695 0 0 1-1.695-1.696c0-4.081.86-8.123 2.531-11.894 1.671-3.77 4.12-7.197 7.207-10.083 3.088-2.886 6.753-5.176 10.787-6.738a35.275 35.275 0 0 1 12.725-2.366c4.366 0 8.69.804 12.724 2.366 4.034 1.562 7.699 3.852 10.787 6.738 3.087 2.886 5.537 6.312 7.208 10.083ZM161.629 134.193c0 9.182-7.579 16.625-16.927 16.625-9.349 0-16.928-7.443-16.928-16.625s7.579-16.625 16.928-16.625c9.348 0 16.927 7.443 16.927 16.625Z"
|
||||
/>
|
||||
<path
|
||||
class="tw-fill-illustration-bg-secondary"
|
||||
d="M176.028 165.953a28.993 28.993 0 0 1 2.531 11.821c0 .93-.755 1.684-1.685 1.684h-63.131c-.93 0-1.684-.754-1.684-1.684 0-4.057.86-8.074 2.531-11.821 1.671-3.748 4.12-7.153 7.207-10.021 3.088-2.869 6.753-5.144 10.787-6.696a35.456 35.456 0 0 1 12.725-2.352c4.366 0 8.69.799 12.724 2.352 4.034 1.552 7.699 3.827 10.787 6.696 3.087 2.868 5.537 6.273 7.208 10.021ZM-87.441 199.521h332.5v14.5c0 5.523-4.478 10-10 10h-312.5c-5.523 0-10-4.477-10-10v-14.5Z"
|
||||
/>
|
||||
<path
|
||||
class="tw-fill-illustration-outline"
|
||||
fill-rule="evenodd"
|
||||
d="M208.059 21.82a4 4 0 0 1 4 4v150.001a4 4 0 0 1-4 4l-255 .001a4 4 0 0 1-4-4v-150a4 4 0 0 1 4-4l255-.001Zm-255 154.002h1.5a57.23 57.23 0 0 1 4.378-21.706l.284-.673c2.982-6.943 7.31-13.27 12.748-18.646l.529-.517c5.688-5.485 12.44-9.836 19.871-12.805a62.937 62.937 0 0 1 10.036-3.065c-11.113-4.751-18.897-15.747-18.897-28.556 0-17.155 13.96-31.061 31.182-31.062 17.22 0 31.18 13.907 31.181 31.062 0 12.537-7.457 23.338-18.192 28.245a62.952 62.952 0 0 1 11.569 3.376c7.431 2.969 14.184 7.32 19.871 12.805 5.688 5.485 10.2 11.996 13.278 19.163a57.251 57.251 0 0 1 4.66 22.379h1.502v-150h-125.5v150Zm129.5-.001h29.568a29.02 29.02 0 0 1 2.159-9.161l.304-.706c1.671-3.748 4.12-7.154 7.207-10.022 2.894-2.689 6.297-4.857 10.035-6.396l.752-.299c.996-.383 2.01-.721 3.037-1.012-4.602-2.879-7.693-7.881-7.841-13.602l-.006-.429c0-9.182 7.579-16.625 16.928-16.625l.437.006c9.146.227 16.49 7.581 16.49 16.619l-.006.429c-.144 5.571-3.08 10.461-7.484 13.372 1.321.338 2.622.752 3.894 1.242 4.034 1.552 7.7 3.827 10.787 6.695 3.088 2.868 5.536 6.274 7.207 10.022a29.066 29.066 0 0 1 2.462 9.867h29.57v-73h-125.5v73Zm62.75-24.936c-3.881 0-7.718.71-11.288 2.084-3.571 1.374-6.797 3.382-9.501 5.894-2.704 2.511-4.831 5.478-6.277 8.72a25.125 25.125 0 0 0-2.074 7.876h58.279a25.125 25.125 0 0 0-2.074-7.876c-1.445-3.242-3.573-6.209-6.276-8.72-2.705-2.512-5.931-4.52-9.501-5.894a31.473 31.473 0 0 0-11.288-2.084Zm-129.5-29.906a59.215 59.215 0 0 0-21.955 4.211c-6.957 2.779-13.269 6.848-18.579 11.969-5.31 5.12-9.513 11.191-12.378 17.862a53.266 53.266 0 0 0-4.332 20.248H73.053a53.266 53.266 0 0 0-4.332-20.248c-2.866-6.671-7.07-12.742-12.38-17.862-5.31-5.121-11.621-9.19-18.577-11.969a59.215 59.215 0 0 0-21.955-4.211Zm128.893.59c-7.208 0-12.928 5.72-12.928 12.625.001 6.904 5.721 12.624 12.928 12.624 7.208 0 12.926-5.72 12.927-12.624 0-6.905-5.719-12.625-12.927-12.625ZM14.69 62.792c-15.027 0-27.182 12.13-27.182 27.062 0 14.931 12.155 27.062 27.181 27.063 15.027-.001 27.182-12.132 27.182-27.063S29.716 62.793 14.69 62.792Zm67.869 36.029h29.579c.229-3.094.952-6.141 2.148-9.04l.304-.71a30.936 30.936 0 0 1 6.636-9.536l.571-.547a33.416 33.416 0 0 1 10.035-6.437l.752-.3a34.78 34.78 0 0 1 3.047-1.021c-4.607-2.878-7.703-7.883-7.851-13.607l-.006-.43c0-9.18 7.579-16.624 16.928-16.624l.437.006c9.146.227 16.49 7.58 16.49 16.619l-.006.429c-.144 5.574-3.082 10.465-7.49 13.376 1.324.34 2.626.758 3.9 1.252 4.034 1.561 7.7 3.85 10.787 6.737 3.088 2.886 5.536 6.312 7.207 10.083a29.407 29.407 0 0 1 2.451 9.75h29.581v-73h-125.5v73Zm62.75-24.937c-3.878 0-7.712.714-11.281 2.096-3.568 1.382-6.795 3.401-9.5 5.93-2.704 2.528-4.833 5.515-6.281 8.782a25.432 25.432 0 0 0-2.08 7.969h58.283a25.432 25.432 0 0 0-2.08-7.97c-1.447-3.266-3.577-6.253-6.281-8.781-2.705-2.529-5.931-4.548-9.5-5.93a31.275 31.275 0 0 0-11.28-2.096Zm-.607-29.315c-7.208 0-12.928 5.72-12.928 12.625.001 6.904 5.721 12.624 12.928 12.624 7.208 0 12.926-5.72 12.927-12.624 0-6.905-5.719-12.625-12.927-12.625Z"
|
||||
clip-rule="evenodd"
|
||||
/>
|
||||
<path
|
||||
class="tw-fill-illustration-outline"
|
||||
fill-rule="evenodd"
|
||||
d="M228.809.822a6 6 0 0 1 6 6v188a5.97 5.97 0 0 1-.643 2.699h12.893v16.5c0 6.627-5.373 12-12 12h-312.5c-6.628 0-12-5.373-12-12v-16.5h16.391a5.966 5.966 0 0 1-.634-2.391l-.007-.308v-188a6 6 0 0 1 6-6h296.5ZM-85.441 214.02a8 8 0 0 0 8 8h312.5a8 8 0 0 0 8-8v-12.5h-328.5v12.5Zm17.75-209.2a2 2 0 0 0-2 2v188.001l.01.204a2 2 0 0 0 1.99 1.796h296.5a2.001 2.001 0 0 0 2-2v-188a2 2 0 0 0-2-2h-296.5Z"
|
||||
clip-rule="evenodd"
|
||||
/>
|
||||
<path
|
||||
class="tw-fill-illustration-bg-primary"
|
||||
d="M378.821 114.003a1.997 1.997 0 0 0-.675 1.497v8.396c0 .583.254 1.136.697 1.515l11.455 9.825a2 2 0 0 1 .543 2.286l-4.203 10.056a1.998 1.998 0 0 1-1.936 1.224l-15.288-.717a1.997 1.997 0 0 0-1.501.579l-6.014 5.979a1.995 1.995 0 0 0-.583 1.569l1.145 14.942a1.997 1.997 0 0 1-1.22 1.995l-9.958 4.169a1.997 1.997 0 0 1-2.252-.503l-10.221-11.309a1.998 1.998 0 0 0-1.482-.658h-8.474c-.579 0-1.129.252-1.508.689l-9.889 11.4a1.998 1.998 0 0 1-2.28.534l-9.969-4.174a1.998 1.998 0 0 1-1.224-1.937l.721-15.182a2 2 0 0 0-.587-1.51l-6.014-5.98a1.996 1.996 0 0 0-1.559-.575l-15.049 1.14a1.997 1.997 0 0 1-1.993-1.221l-4.198-10.045a1.997 1.997 0 0 1 .512-2.258l11.363-10.155c.424-.379.666-.92.666-1.489v-8.403c0-.583-.254-1.136-.696-1.516l-11.456-9.824a1.997 1.997 0 0 1-.542-2.286L279.354 92a1.998 1.998 0 0 1 1.936-1.224l15.288.717a1.998 1.998 0 0 0 1.502-.579l6.007-5.974c.418-.415.631-.995.582-1.582l-1.292-15.419a1.995 1.995 0 0 1 1.218-2.008l9.942-4.163a1.996 1.996 0 0 1 2.258.51l10.552 11.786c.379.423.92.665 1.488.665h8.469c.579 0 1.129-.25 1.508-.688l9.889-11.4a1.996 1.996 0 0 1 2.279-.534l9.97 4.174a1.999 1.999 0 0 1 1.224 1.937l-.721 15.181a2 2 0 0 0 .587 1.51l6.014 5.98c.411.41.98.62 1.558.576l15.049-1.14a1.996 1.996 0 0 1 1.993 1.22l4.195 10.036c.33.79.12 1.702-.521 2.268l-11.507 10.154Z"
|
||||
/>
|
||||
<path
|
||||
class="tw-fill-illustration-outline"
|
||||
fill-rule="evenodd"
|
||||
d="M313.765 59.926a3.994 3.994 0 0 1 4.518 1.02l10.552 11.786h8.469l9.888-11.4a3.994 3.994 0 0 1 4.559-1.067l9.97 4.174a3.994 3.994 0 0 1 2.447 3.873l-.72 15.182 6.013 5.98 15.049-1.14a3.995 3.995 0 0 1 3.987 2.442l4.194 10.035a3.992 3.992 0 0 1-1.042 4.534L380.142 115.5v8.396l11.456 9.824a3.995 3.995 0 0 1 1.085 4.571l-4.203 10.056a3.993 3.993 0 0 1-3.872 2.449l-15.288-.717-6.013 5.98 1.145 14.943a3.994 3.994 0 0 1-2.44 3.988l-9.958 4.169a3.992 3.992 0 0 1-4.505-1.005l-10.221-11.309h-8.474l-9.889 11.4a3.993 3.993 0 0 1-4.559 1.067l-9.97-4.174a3.993 3.993 0 0 1-2.446-3.873l.72-15.181-6.014-5.98-15.049 1.14a3.993 3.993 0 0 1-3.986-2.442l-4.198-10.045a3.993 3.993 0 0 1 1.023-4.517l11.363-10.155v-8.403l-11.455-9.825a3.992 3.992 0 0 1-1.085-4.571l4.203-10.056a3.993 3.993 0 0 1 3.872-2.45l15.287.718 6.008-5.974-1.292-15.418a3.992 3.992 0 0 1 2.437-4.017l9.941-4.163Zm1.543 3.684-9.942 4.162 1.292 15.419a3.992 3.992 0 0 1-1.163 3.165l-6.008 5.974a3.994 3.994 0 0 1-3.003 1.157l-15.288-.717-4.202 10.056 11.455 9.824a3.993 3.993 0 0 1 1.394 3.032v8.403c0 1.137-.485 2.22-1.332 2.978l-11.364 10.154 4.198 10.045 15.049-1.14a3.994 3.994 0 0 1 3.118 1.15l6.014 5.98a3.996 3.996 0 0 1 1.173 3.021l-.72 15.181 9.969 4.175 9.889-11.401a3.994 3.994 0 0 1 3.017-1.377h8.474c1.129 0 2.206.478 2.963 1.316l10.221 11.309 9.958-4.169-1.145-14.943a3.996 3.996 0 0 1 1.166-3.137l6.013-5.979a3.997 3.997 0 0 1 3.003-1.158l15.288.717 4.203-10.056-11.456-9.824a3.995 3.995 0 0 1-1.393-3.031V115.5c0-1.146.492-2.236 1.351-2.994l11.506-10.155-4.194-10.035-15.049 1.14a3.991 3.991 0 0 1-3.117-1.15l-6.014-5.98a3.99 3.99 0 0 1-1.173-3.022l.72-15.181-9.97-4.174-9.889 11.4a3.992 3.992 0 0 1-3.016 1.377h-8.469a3.992 3.992 0 0 1-2.975-1.33L315.308 63.61Z"
|
||||
clip-rule="evenodd"
|
||||
/>
|
||||
<path
|
||||
class="tw-fill-illustration-logo"
|
||||
d="M353.438 119.624c0 11.289-9.152 20.441-20.442 20.441-11.289 0-20.441-9.152-20.441-20.441 0-11.29 9.152-20.442 20.441-20.442 11.29 0 20.442 9.152 20.442 20.442Z"
|
||||
/>
|
||||
<path
|
||||
class="tw-fill-illustration-outline"
|
||||
fill-rule="evenodd"
|
||||
d="M332.996 101.179c-10.186 0-18.444 8.258-18.444 18.444 0 10.187 8.258 18.445 18.444 18.445 10.187 0 18.445-8.258 18.445-18.445 0-10.186-8.258-18.444-18.445-18.444Zm-22.438 18.444c0-12.392 10.046-22.438 22.438-22.438 12.393 0 22.439 10.046 22.439 22.438 0 12.393-10.046 22.439-22.439 22.439-12.392 0-22.438-10.046-22.438-22.439Z"
|
||||
clip-rule="evenodd"
|
||||
/>
|
||||
<path
|
||||
class="tw-fill-illustration-bg-tertiary"
|
||||
d="m497.152 164.106-7.588-7.587a3.004 3.004 0 0 0-4.245-.003l-4.055 4.047 11.83 11.83 4.055-4.047a2.996 2.996 0 0 0 .003-4.24Z"
|
||||
/>
|
||||
<path
|
||||
class="tw-fill-illustration-bg-secondary"
|
||||
d="M500.922 194.274c0 22.644-18.356 41-41 41s-41-18.356-41-41 18.356-41 41-41 41 18.356 41 41Z"
|
||||
/>
|
||||
<path
|
||||
class="tw-fill-illustration-outline"
|
||||
d="M459.03 177.416a2 2 0 1 1 4 0v18.469c0 .613-.282 1.192-.763 1.571l-12.032 9.48a2.001 2.001 0 0 1-2.809-.333 2.002 2.002 0 0 1 .334-2.809l11.27-8.881v-17.497Z"
|
||||
/>
|
||||
<path
|
||||
class="tw-fill-illustration-bg-tertiary"
|
||||
d="M450.936 144.041a2 2 0 0 1 2-2h13.972a2 2 0 0 1 2 2v3.863a2 2 0 0 1-2 2h-13.972a2 2 0 0 1-2-2v-3.863Z"
|
||||
/>
|
||||
<path
|
||||
class="tw-fill-illustration-outline"
|
||||
fill-rule="evenodd"
|
||||
d="M467.114 140.046a4 4 0 0 1 3.794 3.995v3.863a3.999 3.999 0 0 1-3.931 3.998v1.978a40.72 40.72 0 0 1 13.484 4.903l3.69-3.68a5.008 5.008 0 0 1 7.076.003l7.587 7.588.177.186a4.994 4.994 0 0 1-.181 6.881l-3.615 3.606a40.801 40.801 0 0 1 5.727 20.907c0 22.644-18.357 41-41 41-22.644 0-41-18.356-41-41 0-20.434 14.949-37.375 34.507-40.487v-1.883h-.493a4 4 0 0 1-4-4v-3.863a4 4 0 0 1 4-4h13.972l.206.005Zm-7.192 17.228c-20.435 0-37 16.566-37 37 0 20.435 16.565 37 37 37 20.434 0 37-16.565 37-37 0-20.434-16.566-37-37-37Zm28.473.658a1.002 1.002 0 0 0-1.416-.001l-2.638 2.633 9.001 9.002 2.639-2.633a1 1 0 0 0 .07-1.338l-.069-.075-7.587-7.588Zm-30.966-6.028v1.447a41.171 41.171 0 0 1 5.548.036v-1.483h-5.548Zm-4.493-4h13.972v-3.863h-13.972v3.863Z"
|
||||
clip-rule="evenodd"
|
||||
/>
|
||||
</g>
|
||||
<defs>
|
||||
<clipPath id="left-a">
|
||||
<path class="tw-fill-illustration-bg-tertiary" d="M0 0h501v226H0z" />
|
||||
</clipPath>
|
||||
</defs>
|
||||
</svg>
|
||||
`;
|
||||
</div>
|
||||
|
||||
<div
|
||||
class="tw-hidden md:tw-block [&_svg]:tw-absolute tw-z-[1] tw-opacity-[.11] [&_svg]:tw-bottom-0 [&_svg]:tw-end-0 [&_svg]:tw-w-[35%] [&_svg]:tw-max-w-[450px]"
|
||||
>
|
||||
<svg xmlns="http://www.w3.org/2000/svg" fill="none" viewBox="0 0 506 297">
|
||||
<g clip-path="url(#right-a)">
|
||||
<path
|
||||
class="tw-fill-illustration-bg-primary"
|
||||
d="M45.673 294.742v-29.124l22.323 16.198-15.395 15.75a4.04 4.04 0 0 1-6.928-2.824Z"
|
||||
/>
|
||||
<path
|
||||
class="tw-fill-illustration-bg-tertiary"
|
||||
d="m4.978 240.865 95.568-44.738c3.52-1.648 7.492 1.175 7.093 5.041l-9.608 93.173c-.395 3.823-4.774 5.79-7.893 3.547l-43.43-31.233-41.47-16.621c-4.06-1.627-4.221-7.315-.26-9.169Z"
|
||||
/>
|
||||
<path
|
||||
class="tw-fill-illustration-outline"
|
||||
d="M99.698 194.315c4.929-2.306 10.489 1.645 9.931 7.058l-9.608 93.174c-.552 5.351-6.683 8.105-11.05 4.965l-20.832-14.983-14.107 14.435a6.04 6.04 0 0 1-10.359-4.222v-27.151l-39.178-15.7c-5.684-2.278-5.91-10.242-.364-12.838l95.567-44.738Zm5.953 6.648c.239-2.32-2.144-4.013-4.256-3.025L5.827 242.676c-2.376 1.112-2.28 4.525.156 5.502l40.159 16.093 26.703-30.327a2.001 2.001 0 0 1 3.002 2.644l-26.178 29.731 41.637 29.945c1.872 1.346 4.5.165 4.736-2.128l9.609-93.173Zm-57.978 93.779a2.04 2.04 0 0 0 3.498 1.426l13.684-14.001-17.182-12.357v24.932Z"
|
||||
/>
|
||||
<circle
|
||||
cx="86.719"
|
||||
cy="86.719"
|
||||
r="84.719"
|
||||
class="tw-fill-illustration-bg-tertiary"
|
||||
stroke="#020F66"
|
||||
stroke-linecap="round"
|
||||
stroke-linejoin="round"
|
||||
stroke-width="4"
|
||||
transform="scale(-1 1) rotate(45.035 -184.565 -565.488)"
|
||||
/>
|
||||
<circle
|
||||
cx="69.752"
|
||||
cy="69.752"
|
||||
r="69.752"
|
||||
class="tw-fill-illustration-bg-secondary"
|
||||
transform="scale(-1 1) rotate(45.035 -213.255 -553.709)"
|
||||
/>
|
||||
<path
|
||||
class="tw-fill-illustration-outline"
|
||||
d="m445.838 353.214 2.95-180.467 12.372-.007 3.078 180.465a4.64 4.64 0 0 1-4.637 4.72l-9.12.005a4.64 4.64 0 0 1-4.643-4.716ZM453.82 52.947a2 2 0 0 1 1.998-2.001l35.638-.023a2 2 0 0 1 2.001 2.015l-.268 35.637a2 2 0 1 1-4-.03l.252-33.62-33.62.02a1.999 1.999 0 0 1-2.001-1.998ZM415.689 86.49a2 2 0 0 1 4.001.03l-.254 33.62 33.622-.021a2 2 0 0 1 .003 4l-35.637.022a2 2 0 0 1-2.001-2.015l.266-35.636Zm25.457-19.997a2 2 0 0 1 3.461-2.006l23.124 39.885a2 2 0 0 1-3.461 2.006l-23.124-39.885Z"
|
||||
/>
|
||||
<path
|
||||
class="tw-fill-illustration-bg-primary"
|
||||
d="M259.264 277.271c21.107-4.293 34.791-24.62 30.565-45.402-4.227-20.782-24.764-34.15-45.871-29.857-21.107 4.293-34.791 24.62-30.565 45.402 4.227 20.783 24.764 34.15 45.871 29.857ZM299.993 173.472c7.793-1.585 12.826-9.188 11.241-16.981-1.585-7.793-9.187-12.826-16.981-11.241-7.793 1.585-12.826 9.187-11.241 16.981 1.585 7.793 9.188 12.826 16.981 11.241Z"
|
||||
/>
|
||||
<path
|
||||
class="tw-fill-illustration-bg-secondary"
|
||||
d="M329.869 242.094c7.793-1.585 12.826-9.187 11.241-16.981-1.585-7.793-9.188-12.826-16.981-11.241-7.794 1.585-12.827 9.188-11.241 16.981 1.585 7.794 9.187 12.827 16.981 11.241Z"
|
||||
/>
|
||||
<path
|
||||
class="tw-fill-illustration-bg-tertiary"
|
||||
d="M330.088 309.401c7.794-1.585 12.826-9.188 11.241-16.981-1.585-7.794-9.187-12.827-16.981-11.242-7.793 1.585-12.826 9.188-11.241 16.981 1.585 7.794 9.188 12.827 16.981 11.242Z"
|
||||
/>
|
||||
<path
|
||||
class="tw-fill-illustration-bg-primary"
|
||||
d="M234.598 327.597c7.793-1.585 12.826-9.187 11.241-16.981-1.585-7.793-9.187-12.826-16.981-11.241-7.793 1.585-12.826 9.188-11.241 16.981 1.585 7.794 9.188 12.826 16.981 11.241Z"
|
||||
/>
|
||||
<path
|
||||
class="tw-fill-illustration-bg-secondary"
|
||||
d="M176.919 248.71c7.794-1.585 12.827-9.188 11.242-16.981-1.586-7.794-9.188-12.827-16.982-11.242-7.793 1.586-12.826 9.188-11.241 16.982 1.585 7.793 9.188 12.826 16.981 11.241Z"
|
||||
/>
|
||||
<path
|
||||
class="tw-fill-illustration-bg-tertiary"
|
||||
d="M206.836 185.071c7.794-1.585 12.827-9.188 11.242-16.981-1.586-7.793-9.188-12.826-16.982-11.241-7.793 1.585-12.826 9.188-11.241 16.981 1.585 7.793 9.188 12.826 16.981 11.241Z"
|
||||
/>
|
||||
<path
|
||||
class="tw-fill-illustration-outline"
|
||||
fill-rule="evenodd"
|
||||
d="M200.699 154.89c8.875-1.805 17.533 3.927 19.339 12.803 1.165 5.732-.814 11.372-4.752 15.135.131.223.29.502.489.845l14.805 21.386a41.483 41.483 0 0 1 12.979-5.007c9.276-1.886 18.455-.523 26.321 3.303.038-.221.111-.441.227-.648l17.035-30.333a16.337 16.337 0 0 1-6.09-9.744c-1.805-8.876 3.928-17.535 12.803-19.34 8.876-1.805 17.534 3.928 19.339 12.803 1.805 8.876-3.926 17.534-12.802 19.339-3.427.697-6.822.27-9.803-1.028l-16.994 30.262a1.98 1.98 0 0 1-.397.497c8.774 5.316 15.487 13.883 18.16 24.43l19.238-1.61c-.007-7.642 5.356-14.488 13.135-16.07 8.875-1.805 17.534 3.927 19.339 12.803 1.805 8.875-3.927 17.533-12.802 19.339-8.639 1.757-17.072-3.627-19.18-12.099l-18.935 1.585c1.474 9.839-.81 19.465-5.834 27.387l29.108 22.962a16.324 16.324 0 0 1 8.523-4.671c8.876-1.804 17.534 3.928 19.339 12.803 1.805 8.876-3.927 17.534-12.802 19.339-8.875 1.805-17.534-3.926-19.34-12.802a16.338 16.338 0 0 1 1.872-11.474l-29.007-22.882c-5.828 7.464-14.29 12.983-24.349 15.028a41.442 41.442 0 0 1-14.045.441l-6.224 19.317a16.365 16.365 0 0 1 8.405 11.229c1.805 8.876-3.927 17.534-12.802 19.339-8.876 1.805-17.535-3.926-19.34-12.802-1.805-8.875 3.927-17.534 12.803-19.34 2.461-.5 4.906-.42 7.192.145l6.007-18.641c-14.851-3.594-27.011-15.301-30.225-31.105a40.043 40.043 0 0 1-.808-8.184l-20.473-1.442c-.032-.002-.064-.008-.096-.011-1.37 6.114-6.201 11.162-12.739 12.492-8.875 1.805-17.534-3.926-19.339-12.802-1.805-8.875 3.927-17.534 12.802-19.34 8.876-1.804 17.534 3.928 19.339 12.803.196.962.302 1.921.327 2.869l20.401 1.436c1.206-11.333 7.247-21.627 16.399-28.363l-14.76-21.321a20.41 20.41 0 0 0-.435-.719 16.428 16.428 0 0 1-4.816 1.8c-8.876 1.805-17.535-3.927-19.34-12.802-1.805-8.876 3.927-17.535 12.803-19.34Zm124.048 128.249c-6.711 1.365-11.045 7.912-9.68 14.623 1.365 6.711 7.912 11.044 14.623 9.679 6.71-1.365 11.044-7.911 9.679-14.622-1.364-6.71-7.911-11.044-14.622-9.68Zm-95.49 18.196c-6.711 1.365-11.045 7.912-9.68 14.623 1.365 6.711 7.912 11.044 14.623 9.679 6.71-1.365 11.044-7.911 9.679-14.621-1.365-6.711-7.911-11.045-14.622-9.681Zm15.1-97.363c-20.054 4.079-33.004 23.373-29.004 43.044 4.001 19.672 23.459 32.374 43.513 28.296 9.593-1.951 17.558-7.386 22.822-14.676a1.986 1.986 0 0 1 .612-.873c5.306-7.813 7.58-17.606 5.569-27.495-4.001-19.671-23.459-32.374-43.512-28.296Zm80.171 11.861c-6.711 1.364-11.045 7.912-9.68 14.623 1.365 6.71 7.912 11.044 14.623 9.679 6.71-1.365 11.044-7.911 9.679-14.622-1.365-6.711-7.911-11.045-14.622-9.68Zm-152.949 6.614c-6.711 1.365-11.045 7.912-9.681 14.623 1.365 6.711 7.912 11.044 14.623 9.679 6.711-1.365 11.044-7.911 9.68-14.621-1.365-6.711-7.912-11.045-14.622-9.681Zm123.073-75.237c-6.71 1.365-11.044 7.912-9.68 14.623 1.365 6.711 7.912 11.044 14.623 9.679 6.711-1.365 11.044-7.911 9.68-14.622-1.365-6.71-7.912-11.045-14.623-9.68Zm-93.156 11.6c-6.711 1.364-11.045 7.912-9.68 14.623 1.365 6.71 7.912 11.044 14.622 9.679 6.711-1.365 11.044-7.912 9.68-14.622-1.365-6.711-7.911-11.045-14.622-9.68Z"
|
||||
clip-rule="evenodd"
|
||||
/>
|
||||
<path
|
||||
class="tw-fill-illustration-logo"
|
||||
d="M272.266 232.544a1.998 1.998 0 0 0-.353 1.589l.554 2.725a2.002 2.002 0 0 0 1.002 1.357l4.786 2.611a2 2 0 0 1 1.003 2.15l-.667 3.313a1.998 1.998 0 0 1-1.647 1.58l-5.641.896a1.998 1.998 0 0 0-1.352.867l-1.524 2.291a2 2 0 0 0-.252 1.678l1.555 5.227a2 2 0 0 1-.794 2.224l-2.799 1.902a2 2 0 0 1-2.309-.043l-4.524-3.327a2 2 0 0 0-1.583-.348l-2.754.56a1.997 1.997 0 0 0-1.352.994l-2.638 4.785a2 2 0 0 1-2.14.996l-3.339-.661a2 2 0 0 1-1.587-1.649l-.886-5.597a2.003 2.003 0 0 0-.875-1.358l-2.298-1.514a2 2 0 0 0-1.669-.247l-5.272 1.563a2 2 0 0 1-2.22-.788l-1.897-2.774a2.001 2.001 0 0 1 .045-2.321l3.339-4.498a2.004 2.004 0 0 0 .354-1.591l-.557-2.736a2.001 2.001 0 0 0-.983-1.347l-4.848-2.715a2 2 0 0 1-.983-2.14l.669-3.329a2.001 2.001 0 0 1 1.648-1.581l5.641-.895a1.999 1.999 0 0 0 1.352-.868l1.526-2.293c.327-.493.42-1.105.253-1.673l-1.608-5.457a2 2 0 0 1 .794-2.22l2.793-1.897a2 2 0 0 1 2.322.053l4.676 3.5a1.999 1.999 0 0 0 1.597.359l2.744-.558a2.002 2.002 0 0 0 1.353-.995l2.637-4.784a1.997 1.997 0 0 1 2.14-.996l3.339.661a2 2 0 0 1 1.587 1.649l.886 5.597c.088.555.406 1.048.875 1.357l2.298 1.514a2.002 2.002 0 0 0 1.669.248l5.272-1.564a2 2 0 0 1 2.22.789l1.898 2.775a2 2 0 0 1-.044 2.319l-3.432 4.635Zm-24.977-.064c-4.049 2.702-5.078 8.076-2.395 11.991 2.705 4.028 8.1 5.044 12.035 2.365 3.936-2.678 5.078-8.076 2.395-11.991-2.592-4.051-7.986-5.067-12.035-2.365Z"
|
||||
/>
|
||||
<path
|
||||
class="tw-fill-illustration-outline"
|
||||
d="m270.507 237.256-.554-2.724a4.004 4.004 0 0 1 .705-3.178l3.433-4.636-1.897-2.775-5.273 1.564a4 4 0 0 1-3.337-.494l-2.298-1.515a4 4 0 0 1-1.751-2.714l-.886-5.597-3.339-.661-2.637 4.784a4.001 4.001 0 0 1-2.706 1.989l-2.744.558a4 4 0 0 1-3.194-.718l-4.676-3.5-2.792 1.898 1.608 5.457a3.998 3.998 0 0 1-.507 3.345l-1.525 2.294c-.62.931-1.6 1.56-2.704 1.736l-5.642.895-.669 3.329 4.848 2.715a4 4 0 0 1 1.965 2.693l.557 2.737a3.999 3.999 0 0 1-.708 3.18l-3.338 4.499 1.897 2.774 5.272-1.563a3.998 3.998 0 0 1 3.338.494l2.298 1.514a4.001 4.001 0 0 1 1.75 2.715l.886 5.597 3.339.661 2.638-4.785a4 4 0 0 1 2.706-1.988l2.753-.56a4 4 0 0 1 3.166.697l4.524 3.327 2.8-1.902-1.555-5.227a4.002 4.002 0 0 1 .504-3.355l1.524-2.291a3.998 3.998 0 0 1 2.703-1.736l5.642-.895.667-3.313-4.787-2.611a4.004 4.004 0 0 1-2.004-2.714Zm-24.328-6.439c4.915-3.28 11.556-2.099 14.795 2.898h.001v.001l.034.051h-.001c3.294 4.868 1.835 11.464-2.953 14.723-4.855 3.304-11.499 2.043-14.821-2.903l.001-.001c-3.308-4.845-2.013-11.461 2.944-14.769Zm11.461 5.106c-1.959-3.06-6.075-3.891-9.24-1.779-3.036 2.026-3.85 5.957-2.039 8.913l.183.284.01.015c2.089 3.109 6.234 3.879 9.25 1.827 3.066-2.087 3.897-6.25 1.871-9.207a.97.97 0 0 1-.035-.053Zm16.787.536 4.787 2.611a4 4 0 0 1 2.005 4.3l-.666 3.313a4.001 4.001 0 0 1-3.295 3.161l-5.641.896-1.525 2.291 1.555 5.227a4.002 4.002 0 0 1-1.586 4.449l-2.8 1.901a4 4 0 0 1-4.618-.086l-4.523-3.326-2.753.56-2.638 4.784a4 4 0 0 1-4.279 1.993l-3.34-.661a4.002 4.002 0 0 1-3.174-3.298l-.886-5.598-2.298-1.514-5.273 1.564a3.999 3.999 0 0 1-4.438-1.577l-1.897-2.774a3.998 3.998 0 0 1 .09-4.641l3.338-4.499-.557-2.737-4.848-2.715a3.998 3.998 0 0 1-1.966-4.279l.669-3.329a4.002 4.002 0 0 1 3.294-3.162l5.642-.895 1.526-2.294-1.609-5.457a4.001 4.001 0 0 1 1.59-4.439l2.792-1.897a4 4 0 0 1 4.645.106l4.676 3.5 2.744-.558 2.636-4.785a4 4 0 0 1 4.281-1.992l3.339.661a4 4 0 0 1 3.174 3.298l.886 5.597 2.298 1.514 5.272-1.563a4 4 0 0 1 4.439 1.576l1.898 2.775a4.001 4.001 0 0 1-.087 4.639l-3.433 4.636.554 2.724Z"
|
||||
/>
|
||||
</g>
|
||||
<defs>
|
||||
<clipPath id="right-a">
|
||||
<path class="tw-fill-illustration-bg-tertiary" d="M0 0h506v297H0z" />
|
||||
</clipPath>
|
||||
</defs>
|
||||
</svg>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</ng-template>
|
||||
|
||||
|
||||
@@ -22,7 +22,7 @@ import { ConfigService } from "@bitwarden/common/platform/abstractions/config/co
|
||||
import { I18nService } from "@bitwarden/common/platform/abstractions/i18n.service";
|
||||
import { PlatformUtilsService } from "@bitwarden/common/platform/abstractions/platform-utils.service";
|
||||
import { StateService } from "@bitwarden/common/platform/abstractions/state.service";
|
||||
import { NotificationsService } from "@bitwarden/common/platform/notifications";
|
||||
import { ServerNotificationsService } from "@bitwarden/common/platform/server-notifications";
|
||||
import { StateEventRunnerService } from "@bitwarden/common/platform/state";
|
||||
import { CipherService } from "@bitwarden/common/vault/abstractions/cipher.service";
|
||||
import { InternalFolderService } from "@bitwarden/common/vault/abstractions/folder/folder.service.abstraction";
|
||||
@@ -76,7 +76,7 @@ export class AppComponent implements OnDestroy, OnInit {
|
||||
private keyService: KeyService,
|
||||
private collectionService: CollectionService,
|
||||
private searchService: SearchService,
|
||||
private notificationsService: NotificationsService,
|
||||
private serverNotificationsService: ServerNotificationsService,
|
||||
private stateService: StateService,
|
||||
private eventUploadService: EventUploadService,
|
||||
protected policyListService: PolicyListService,
|
||||
@@ -88,14 +88,14 @@ export class AppComponent implements OnDestroy, OnInit {
|
||||
private accountService: AccountService,
|
||||
private processReloadService: ProcessReloadServiceAbstraction,
|
||||
private deviceTrustToastService: DeviceTrustToastService,
|
||||
private readonly destoryRef: DestroyRef,
|
||||
private readonly destroy: DestroyRef,
|
||||
private readonly documentLangSetter: DocumentLangSetter,
|
||||
private readonly tokenService: TokenService,
|
||||
) {
|
||||
this.deviceTrustToastService.setupListeners$.pipe(takeUntilDestroyed()).subscribe();
|
||||
|
||||
const langSubscription = this.documentLangSetter.start();
|
||||
this.destoryRef.onDestroy(() => langSubscription.unsubscribe());
|
||||
this.destroy.onDestroy(() => langSubscription.unsubscribe());
|
||||
}
|
||||
|
||||
ngOnInit() {
|
||||
@@ -347,9 +347,9 @@ export class AppComponent implements OnDestroy, OnInit {
|
||||
|
||||
private idleStateChanged() {
|
||||
if (this.isIdle) {
|
||||
this.notificationsService.disconnectFromInactivity();
|
||||
this.serverNotificationsService.disconnectFromInactivity();
|
||||
} else {
|
||||
this.notificationsService.reconnectFromActivity();
|
||||
this.serverNotificationsService.reconnectFromActivity();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1,8 +1,7 @@
|
||||
import { Component } from "@angular/core";
|
||||
|
||||
import { BaseLoginViaWebAuthnComponent } from "@bitwarden/angular/auth/components/base-login-via-webauthn.component";
|
||||
import { CreatePasskeyFailedIcon } from "@bitwarden/angular/auth/icons/create-passkey-failed.icon";
|
||||
import { CreatePasskeyIcon } from "@bitwarden/angular/auth/icons/create-passkey.icon";
|
||||
import { CreatePasskeyIcon, CreatePasskeyFailedIcon } from "@bitwarden/assets/svg";
|
||||
|
||||
@Component({
|
||||
selector: "app-login-via-webauthn",
|
||||
@@ -10,5 +9,8 @@ import { CreatePasskeyIcon } from "@bitwarden/angular/auth/icons/create-passkey.
|
||||
standalone: false,
|
||||
})
|
||||
export class LoginViaWebAuthnComponent extends BaseLoginViaWebAuthnComponent {
|
||||
protected readonly Icons = { CreatePasskeyIcon, CreatePasskeyFailedIcon };
|
||||
protected readonly Icons = {
|
||||
CreatePasskeyIcon,
|
||||
CreatePasskeyFailedIcon,
|
||||
};
|
||||
}
|
||||
|
||||
@@ -46,11 +46,14 @@
|
||||
<i class="bwi bwi-question-circle" aria-hidden="true"></i>
|
||||
</a>
|
||||
</div>
|
||||
<app-account-fingerprint
|
||||
[fingerprintMaterial]="fingerprintMaterial"
|
||||
fingerprintLabel="{{ 'yourAccountsFingerprint' | i18n }}"
|
||||
>
|
||||
</app-account-fingerprint>
|
||||
@if (fingerprintMaterial && userPublicKey) {
|
||||
<app-account-fingerprint
|
||||
[fingerprintMaterial]="fingerprintMaterial"
|
||||
[publicKeyBuffer]="userPublicKey"
|
||||
fingerprintLabel="{{ 'yourAccountsFingerprint' | i18n }}"
|
||||
>
|
||||
</app-account-fingerprint>
|
||||
}
|
||||
</div>
|
||||
</div>
|
||||
<button bitButton bitFormButton type="submit" buttonType="primary">{{ "save" | i18n }}</button>
|
||||
|
||||
@@ -12,7 +12,10 @@ import { UpdateProfileRequest } from "@bitwarden/common/auth/models/request/upda
|
||||
import { getUserId } from "@bitwarden/common/auth/services/account.service";
|
||||
import { ProfileResponse } from "@bitwarden/common/models/response/profile.response";
|
||||
import { I18nService } from "@bitwarden/common/platform/abstractions/i18n.service";
|
||||
import { LogService } from "@bitwarden/common/platform/abstractions/log.service";
|
||||
import { UserPublicKey } from "@bitwarden/common/types/key";
|
||||
import { DialogService, ToastService } from "@bitwarden/components";
|
||||
import { KeyService } from "@bitwarden/key-management";
|
||||
|
||||
import { DynamicAvatarComponent } from "../../../components/dynamic-avatar.component";
|
||||
import { SharedModule } from "../../../shared";
|
||||
@@ -29,6 +32,7 @@ export class ProfileComponent implements OnInit, OnDestroy {
|
||||
loading = true;
|
||||
profile: ProfileResponse;
|
||||
fingerprintMaterial: string;
|
||||
userPublicKey: UserPublicKey;
|
||||
managingOrganization$: Observable<Organization>;
|
||||
private destroy$ = new Subject<void>();
|
||||
|
||||
@@ -44,16 +48,24 @@ export class ProfileComponent implements OnInit, OnDestroy {
|
||||
private dialogService: DialogService,
|
||||
private toastService: ToastService,
|
||||
private organizationService: OrganizationService,
|
||||
private keyService: KeyService,
|
||||
private logService: LogService,
|
||||
) {}
|
||||
|
||||
async ngOnInit() {
|
||||
this.profile = await this.apiService.getProfile();
|
||||
this.loading = false;
|
||||
this.fingerprintMaterial = await firstValueFrom(
|
||||
this.accountService.activeAccount$.pipe(map((a) => a?.id)),
|
||||
);
|
||||
|
||||
const userId = await firstValueFrom(getUserId(this.accountService.activeAccount$));
|
||||
this.fingerprintMaterial = userId;
|
||||
const publicKey = await firstValueFrom(this.keyService.userPublicKey$(userId));
|
||||
if (publicKey == null) {
|
||||
this.logService.error(
|
||||
"[ProfileComponent] No public key available for the user: " +
|
||||
userId +
|
||||
" fingerprint can't be displayed.",
|
||||
);
|
||||
} else {
|
||||
this.userPublicKey = publicKey;
|
||||
}
|
||||
|
||||
this.managingOrganization$ = this.organizationService
|
||||
.organizations$(userId)
|
||||
@@ -70,6 +82,8 @@ export class ProfileComponent implements OnInit, OnDestroy {
|
||||
.subscribe((name) => {
|
||||
this.profile.name = name;
|
||||
});
|
||||
|
||||
this.loading = false;
|
||||
}
|
||||
|
||||
openChangeAvatar = async () => {
|
||||
|
||||
@@ -62,7 +62,7 @@
|
||||
buttonType="danger"
|
||||
[bitAction]="delete"
|
||||
*ngIf="editMode"
|
||||
appA11yTitle="{{ 'delete' | i18n }}"
|
||||
label="{{ 'delete' | i18n }}"
|
||||
></button>
|
||||
</ng-container>
|
||||
</bit-dialog>
|
||||
|
||||
@@ -89,7 +89,7 @@
|
||||
<button
|
||||
[bitMenuTriggerFor]="trustedContactOptions"
|
||||
type="button"
|
||||
appA11yTitle="{{ 'options' | i18n }}"
|
||||
label="{{ 'options' | i18n }}"
|
||||
bitIconButton="bwi-ellipsis-v"
|
||||
buttonType="main"
|
||||
></button>
|
||||
@@ -212,7 +212,7 @@
|
||||
<button
|
||||
[bitMenuTriggerFor]="grantedContactOptions"
|
||||
type="button"
|
||||
appA11yTitle="{{ 'options' | i18n }}"
|
||||
label="{{ 'options' | i18n }}"
|
||||
bitIconButton="bwi-ellipsis-v"
|
||||
buttonType="main"
|
||||
></button>
|
||||
|
||||
@@ -13,9 +13,6 @@
|
||||
>
|
||||
{{ "twoStepLoginProviderEnabled" | i18n }}
|
||||
</bit-callout>
|
||||
<bit-callout type="warning">
|
||||
<p bitTypography="body1">{{ "twoFactorWebAuthnWarning1" | i18n }}</p>
|
||||
</bit-callout>
|
||||
<img class="tw-float-right tw-ml-5 mfaType7" alt="FIDO2 WebAuthn logo" />
|
||||
<ul class="bwi-ul">
|
||||
<li *ngFor="let k of keys; let i = index" #removeKeyBtn [appApiAction]="k.removePromise">
|
||||
|
||||
@@ -39,7 +39,7 @@
|
||||
type="button"
|
||||
buttonType="danger"
|
||||
(click)="remove(i)"
|
||||
appA11yTitle="{{ 'remove' | i18n }}"
|
||||
label="{{ 'remove' | i18n }}"
|
||||
></button>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
@@ -4,10 +4,9 @@
|
||||
id="sendBtn"
|
||||
bitLink
|
||||
linkType="secondary"
|
||||
bitButton
|
||||
type="button"
|
||||
buttonType="unstyled"
|
||||
[bitAction]="send"
|
||||
(click)="send()"
|
||||
>
|
||||
{{ "sendEmail" | i18n }}
|
||||
</button>
|
||||
|
||||
@@ -4,6 +4,7 @@ import { Component, OnInit } from "@angular/core";
|
||||
import { FormBuilder, Validators } from "@angular/forms";
|
||||
import { firstValueFrom, map, Observable } from "rxjs";
|
||||
|
||||
import { CreatePasskeyFailedIcon, CreatePasskeyIcon } from "@bitwarden/assets/svg";
|
||||
import { PrfKeySet } from "@bitwarden/auth/common";
|
||||
import { Verification } from "@bitwarden/common/auth/types/verification";
|
||||
import { ErrorResponse } from "@bitwarden/common/models/response/error.response";
|
||||
@@ -16,9 +17,6 @@ import { WebauthnLoginAdminService } from "../../../core";
|
||||
import { CredentialCreateOptionsView } from "../../../core/views/credential-create-options.view";
|
||||
import { PendingWebauthnLoginCredentialView } from "../../../core/views/pending-webauthn-login-credential.view";
|
||||
|
||||
import { CreatePasskeyFailedIcon } from "./create-passkey-failed.icon";
|
||||
import { CreatePasskeyIcon } from "./create-passkey.icon";
|
||||
|
||||
// FIXME: update to use a const object instead of a typescript enum
|
||||
// eslint-disable-next-line @bitwarden/platform/no-enums
|
||||
export enum CreateCredentialDialogResult {
|
||||
@@ -38,7 +36,10 @@ type Step =
|
||||
export class CreateCredentialDialogComponent implements OnInit {
|
||||
protected readonly NameMaxCharacters = 50;
|
||||
protected readonly CreateCredentialDialogResult = CreateCredentialDialogResult;
|
||||
protected readonly Icons = { CreatePasskeyIcon, CreatePasskeyFailedIcon };
|
||||
protected readonly Icons = {
|
||||
CreatePasskeyIcon,
|
||||
CreatePasskeyFailedIcon,
|
||||
};
|
||||
|
||||
protected currentStep: Step = "userVerification";
|
||||
protected invalidSecret = false;
|
||||
|
||||
@@ -1,28 +0,0 @@
|
||||
import { svgIcon } from "@bitwarden/components";
|
||||
|
||||
export const CreatePasskeyFailedIcon = svgIcon`
|
||||
<svg xmlns="http://www.w3.org/2000/svg" width="163" height="115" fill="none">
|
||||
<path class="tw-fill-secondary-600" fill-rule="evenodd" d="M31 19.46H9v22h22v-22Zm-24-2v26h26v-26H7Z"
|
||||
clip-rule="evenodd" />
|
||||
<path class="tw-fill-secondary-600" fill-rule="evenodd"
|
||||
d="M0 43.46a4 4 0 0 1 4-4h32a4 4 0 0 1 4 4v7h-4v-7H4v16.747l1.705 2.149a4 4 0 0 1 .866 2.486v22.205a4 4 0 0 1-1 2.645L4 91.475v17.985h32V91.475l-1.572-1.783a4 4 0 0 1-1-2.645V64.842a4 4 0 0 1 .867-2.486L36 60.207V56.46h4v3.747a4 4 0 0 1-.867 2.487l-1.704 2.148v22.205L39 88.83a4 4 0 0 1 1 2.645v17.985a4 4 0 0 1-4 4H4a4 4 0 0 1-4-4V91.475a4 4 0 0 1 1-2.645l1.571-1.783V64.842L.867 62.694A4 4 0 0 1 0 60.207V43.46Z"
|
||||
clip-rule="evenodd" />
|
||||
<path class="tw-fill-secondary-600" fill-rule="evenodd"
|
||||
d="M19.74 63.96a.5.5 0 0 1 .355.147l2.852 2.866a.5.5 0 0 1 .146.353V77.56c2.585 1.188 4.407 3.814 4.407 6.865 0 4.183-3.357 7.534-7.5 7.534-4.144 0-7.5-3.376-7.5-7.534a7.546 7.546 0 0 1 4.478-6.894v-1.443a.5.5 0 0 1 .146-.353l1.275-1.281-1.322-1.33a.5.5 0 0 1 0-.705l.332-.334-.262-.263a.5.5 0 0 1-.005-.7l1.332-1.377-1.445-1.452a.5.5 0 0 1-.145-.352v-1.114a.5.5 0 0 1 .145-.352l2.357-2.369a.5.5 0 0 1 .355-.147Zm-1.856 3.075v.7l1.645 1.654a.5.5 0 0 1 .005.7l-1.332 1.377.267.268a.5.5 0 0 1 0 .705l-.333.334 1.323 1.329a.5.5 0 0 1 0 .705l-1.48 1.488v1.57a.5.5 0 0 1-.32.466 6.545 6.545 0 0 0-4.159 6.095c0 3.61 2.913 6.534 6.5 6.534 3.588 0 6.5-2.901 6.5-6.534 0-2.749-1.707-5.105-4.095-6.074a.5.5 0 0 1-.312-.463V67.532L19.74 65.17l-1.857 1.866ZM20 85.623a1.27 1.27 0 0 0-1.268 1.276c0 .702.56 1.276 1.268 1.276.712 0 1.268-.555 1.268-1.276A1.27 1.27 0 0 0 20 85.623Zm-2.268 1.276A2.27 2.27 0 0 1 20 84.623a2.27 2.27 0 0 1 2.268 2.276c0 1.269-1 2.276-2.268 2.276a2.27 2.27 0 0 1-2.268-2.276ZM57.623 114a1 1 0 0 1 1-1h63.048a1 1 0 0 1 0 2H58.623a1 1 0 0 1-1-1Z"
|
||||
clip-rule="evenodd" />
|
||||
<path class="tw-fill-secondary-600" fill-rule="evenodd"
|
||||
d="M78.022 114V95.654h2V114h-2ZM98.418 114V95.654h2V114h-2Z" clip-rule="evenodd" />
|
||||
<path class="tw-fill-secondary-600" fill-rule="evenodd"
|
||||
d="M16 14.46c0-7.732 6.268-14 14-14h119c7.732 0 14 6.268 14 14v68c0 7.732-6.268 14-14 14H39.5v-4H149c5.523 0 10-4.477 10-10v-68c0-5.523-4.477-10-10-10H30c-5.523 0-10 4.477-10 10v5h-4v-5Z"
|
||||
clip-rule="evenodd" />
|
||||
<path class="tw-fill-secondary-600" fill-rule="evenodd"
|
||||
d="M25 15.46a6 6 0 0 1 6-6h117a6 6 0 0 1 6 6v66a6 6 0 0 1-6 6H36.5v-2H148a4 4 0 0 0 4-4v-66a4 4 0 0 0-4-4H31a4 4 0 0 0-4 4v3h-2v-3Z"
|
||||
clip-rule="evenodd" />
|
||||
<path class="tw-fill-secondary-600"
|
||||
d="M104.269 32.86a1.42 1.42 0 0 0-1.007-.4h-25.83c-.39 0-.722.132-1.007.4a1.26 1.26 0 0 0-.425.947v16.199c0 1.207.25 2.407.75 3.597a13.22 13.22 0 0 0 1.861 3.165c.74.919 1.62 1.817 2.646 2.69a30.93 30.93 0 0 0 2.834 2.172c.868.577 1.77 1.121 2.712 1.636.942.516 1.612.862 2.007 1.043.394.181.714.326.95.42.18.083.373.128.583.128.21 0 .403-.041.582-.128.241-.099.557-.239.956-.42.394-.181 1.064-.532 2.006-1.043a36.595 36.595 0 0 0 2.712-1.636c.867-.576 1.813-1.302 2.838-2.171a19.943 19.943 0 0 0 2.646-2.69 13.24 13.24 0 0 0 1.862-3.166 9.19 9.19 0 0 0 .749-3.597V33.812c.005-.367-.14-.684-.425-.952Zm-3.329 17.298c0 5.864-10.593 10.916-10.593 10.916V35.93h10.593v14.228Z" />
|
||||
<path class="tw-fill-secondary-600" fill-rule="evenodd" d="M18 24.46h-5v-2h5v2ZM27 24.46h-5v-2h5v2Z"
|
||||
clip-rule="evenodd" />
|
||||
<path class="tw-fill-danger-600"
|
||||
d="M51.066 66.894a2.303 2.303 0 0 1-2.455-.5l-10.108-9.797L28.375 66.4l-.002.002a2.294 2.294 0 0 1-3.185.005 2.24 2.24 0 0 1-.506-2.496c.117-.27.286-.518.503-.728l10.062-9.737-9.945-9.623a2.258 2.258 0 0 1-.698-1.6c-.004-.314.06-.619.176-.894a2.254 2.254 0 0 1 1.257-1.222 2.305 2.305 0 0 1 1.723.014c.267.11.518.274.732.486l10.01 9.682 9.995-9.688.009-.008a2.292 2.292 0 0 1 3.159.026c.425.411.68.98.684 1.59a2.242 2.242 0 0 1-.655 1.6l-.01.01-9.926 9.627 10.008 9.7.029.027a2.237 2.237 0 0 1 .53 2.496l-.002.004a2.258 2.258 0 0 1-1.257 1.222Z" />
|
||||
</svg>
|
||||
`;
|
||||
@@ -1,26 +0,0 @@
|
||||
import { svgIcon } from "@bitwarden/components";
|
||||
|
||||
export const CreatePasskeyIcon = svgIcon`
|
||||
<svg xmlns="http://www.w3.org/2000/svg" width="163" height="116" fill="none">
|
||||
<path class="tw-fill-secondary-600" fill-rule="evenodd" d="M31 19.58H9v22h22v-22Zm-24-2v26h26v-26H7Z"
|
||||
clip-rule="evenodd" />
|
||||
<path class="tw-fill-secondary-600" fill-rule="evenodd"
|
||||
d="M0 43.58a4 4 0 0 1 4-4h32a4 4 0 0 1 4 4v7h-4v-7H4v16.747l1.705 2.149a4 4 0 0 1 .866 2.486v22.204a4 4 0 0 1-1 2.646L4 91.595v17.985h32V91.595l-1.572-1.783a4 4 0 0 1-1-2.646V64.962a4 4 0 0 1 .867-2.486L36 60.327V56.58h4v3.747a4 4 0 0 1-.867 2.486l-1.704 2.149v22.204L39 88.95a4 4 0 0 1 1 2.646v17.985a4 4 0 0 1-4 4H4a4 4 0 0 1-4-4V91.595a4 4 0 0 1 1-2.646l1.571-1.783V64.962L.867 62.813A4 4 0 0 1 0 60.327V43.58Z"
|
||||
clip-rule="evenodd" />
|
||||
<path class="tw-fill-secondary-600" fill-rule="evenodd"
|
||||
d="M19.74 64.08a.5.5 0 0 1 .355.147l2.852 2.866a.5.5 0 0 1 .146.352V77.68c2.585 1.189 4.407 3.814 4.407 6.865 0 4.183-3.357 7.535-7.5 7.535-4.144 0-7.5-3.377-7.5-7.535a7.546 7.546 0 0 1 4.478-6.894V76.21a.5.5 0 0 1 .146-.353l1.275-1.282-1.322-1.329a.5.5 0 0 1 0-.705l.332-.334-.262-.263a.5.5 0 0 1-.005-.7l1.332-1.377-1.445-1.452a.5.5 0 0 1-.145-.353v-1.113a.5.5 0 0 1 .145-.353l2.357-2.368a.5.5 0 0 1 .355-.147Zm-1.856 3.074v.7l1.645 1.654a.5.5 0 0 1 .005.7l-1.332 1.377.267.268a.5.5 0 0 1 0 .706l-.333.334 1.323 1.329a.5.5 0 0 1 0 .705l-1.48 1.488v1.57a.5.5 0 0 1-.32.466 6.545 6.545 0 0 0-4.159 6.094c0 3.61 2.913 6.535 6.5 6.535 3.588 0 6.5-2.902 6.5-6.535 0-2.748-1.707-5.104-4.095-6.073a.5.5 0 0 1-.312-.463V67.651l-2.352-2.364-1.857 1.866ZM20 85.742a1.27 1.27 0 0 0-1.268 1.277c0 .701.56 1.276 1.268 1.276.712 0 1.268-.555 1.268-1.276A1.27 1.27 0 0 0 20 85.742Zm-2.268 1.277A2.27 2.27 0 0 1 20 84.742a2.27 2.27 0 0 1 2.268 2.277c0 1.268-1 2.276-2.268 2.276a2.27 2.27 0 0 1-2.268-2.276ZM41.796 42.844a1 1 0 0 1 1.413.058l5.526 6A1 1 0 0 1 48 50.58H27a1 1 0 1 1 0-2h18.72l-3.982-4.323a1 1 0 0 1 .058-1.413ZM33.315 62.315a1 1 0 0 1-1.413-.058l-5.526-6a1 1 0 0 1 .735-1.677h21a1 1 0 1 1 0 2h-18.72l3.982 4.322a1 1 0 0 1-.058 1.413ZM57.623 114.12a1 1 0 0 1 1-1h63.048a1 1 0 1 1 0 2H58.623a1 1 0 0 1-1-1Z"
|
||||
clip-rule="evenodd" />
|
||||
<path class="tw-fill-secondary-600" fill-rule="evenodd"
|
||||
d="M78.022 114.12V95.774h2v18.346h-2ZM98.418 114.12V95.774h2v18.346h-2Z" clip-rule="evenodd" />
|
||||
<path class="tw-fill-secondary-600" fill-rule="evenodd"
|
||||
d="M16 14.58c0-7.732 6.268-14 14-14h119c7.732 0 14 6.268 14 14v68c0 7.732-6.268 14-14 14H39.5v-4H149c5.523 0 10-4.478 10-10v-68c0-5.523-4.477-10-10-10H30c-5.523 0-10 4.477-10 10v5h-4v-5Z"
|
||||
clip-rule="evenodd" />
|
||||
<path class="tw-fill-secondary-600" fill-rule="evenodd"
|
||||
d="M25 15.58a6 6 0 0 1 6-6h117a6 6 0 0 1 6 6v66a6 6 0 0 1-6 6H36.5v-2H148a4 4 0 0 0 4-4v-66a4 4 0 0 0-4-4H31a4 4 0 0 0-4 4v3h-2v-3Z"
|
||||
clip-rule="evenodd" />
|
||||
<path class="tw-fill-secondary-600"
|
||||
d="M104.269 32.98a1.42 1.42 0 0 0-1.007-.4h-25.83c-.39 0-.722.132-1.007.4a1.26 1.26 0 0 0-.425.947v16.199c0 1.207.25 2.406.75 3.597a13.222 13.222 0 0 0 1.861 3.165c.74.919 1.62 1.817 2.646 2.69a30.93 30.93 0 0 0 2.834 2.172c.868.577 1.77 1.121 2.712 1.636.942.515 1.612.861 2.007 1.043.394.18.714.325.95.42.18.082.373.128.583.128.21 0 .403-.042.582-.128.241-.099.557-.24.956-.42.394-.182 1.064-.532 2.006-1.043a36.56 36.56 0 0 0 2.712-1.636c.867-.577 1.813-1.302 2.838-2.172a19.943 19.943 0 0 0 2.646-2.69 13.24 13.24 0 0 0 1.862-3.165c.5-1.187.749-2.386.749-3.597V33.93c.005-.367-.14-.684-.425-.952Zm-3.329 17.298c0 5.864-10.593 10.916-10.593 10.916V36.049h10.593v14.23Z" />
|
||||
<path class="tw-fill-secondary-600" fill-rule="evenodd" d="M18 24.58h-5v-2h5v2ZM27 24.58h-5v-2h5v2Z"
|
||||
clip-rule="evenodd" />
|
||||
</svg>
|
||||
`;
|
||||
@@ -51,6 +51,7 @@
|
||||
<h2 class="tw-mb-3 tw-text-base tw-font-semibold">{{ "paymentType" | i18n }}</h2>
|
||||
<app-payment [showAccountCredit]="false"></app-payment>
|
||||
<app-manage-tax-information
|
||||
[showTaxIdField]="showTaxIdField"
|
||||
(taxInformationChanged)="onTaxInformationChanged()"
|
||||
></app-manage-tax-information>
|
||||
|
||||
|
||||
@@ -259,6 +259,15 @@ export class TrialBillingStepComponent implements OnInit, OnDestroy {
|
||||
return planType ? this.applicablePlans.find((plan) => plan.type === planType) : null;
|
||||
}
|
||||
|
||||
protected get showTaxIdField(): boolean {
|
||||
switch (this.organizationInfo.type) {
|
||||
case ProductTierType.Families:
|
||||
return false;
|
||||
default:
|
||||
return true;
|
||||
}
|
||||
}
|
||||
|
||||
private getBillingInformationFromTaxInfoComponent(): BillingInformation {
|
||||
return {
|
||||
postalCode: this.taxInfoComponent.getTaxInformation()?.postalCode,
|
||||
|
||||
@@ -53,7 +53,7 @@
|
||||
bitIconButton="bwi-ellipsis-v"
|
||||
buttonType="main"
|
||||
[bitMenuTriggerFor]="appListDropdown"
|
||||
appA11yTitle="{{ 'options' | i18n }}"
|
||||
label="{{ 'options' | i18n }}"
|
||||
></button>
|
||||
<bit-menu #appListDropdown>
|
||||
@if (!isSelfHosted && !sponsoredFamily.validUntil) {
|
||||
|
||||
@@ -33,7 +33,7 @@
|
||||
showToast
|
||||
[valueLabel]="'billingSyncKey' | i18n"
|
||||
[appCopyClick]="clientSecret"
|
||||
[appA11yTitle]="'copyValue' | i18n"
|
||||
[label]="'copyValue' | i18n"
|
||||
></button>
|
||||
</bit-form-field>
|
||||
<div class="tw-mt-2 tw-text-sm tw-text-muted" *ngIf="showLastSyncText">
|
||||
|
||||
@@ -33,7 +33,7 @@
|
||||
bitIconButton="bwi-trash"
|
||||
bitFormButton
|
||||
[bitAction]="deleteConnection"
|
||||
appA11yTitle="{{ 'delete' | i18n }}"
|
||||
label="{{ 'delete' | i18n }}"
|
||||
></button>
|
||||
</ng-container>
|
||||
</bit-dialog>
|
||||
|
||||
@@ -359,7 +359,7 @@
|
||||
type="button"
|
||||
[bitIconButton]="totalOpened ? 'bwi-angle-down' : 'bwi-angle-up'"
|
||||
size="small"
|
||||
aria-hidden="true"
|
||||
[label]="totalOpened ? ('hidePricingSummary' | i18n) : ('showPricingSummary' | i18n)"
|
||||
></button>
|
||||
</p>
|
||||
</div>
|
||||
|
||||
@@ -8,7 +8,7 @@
|
||||
type="button"
|
||||
size="small"
|
||||
class="tw-float-right"
|
||||
appA11yTitle="{{ 'cancel' | i18n }}"
|
||||
label="{{ 'cancel' | i18n }}"
|
||||
(click)="cancel()"
|
||||
></button>
|
||||
<h2 bitTypography="h2">{{ "changeBillingPlan" | i18n }}</h2>
|
||||
|
||||
@@ -5,6 +5,7 @@ import { ActivatedRoute } from "@angular/router";
|
||||
import { firstValueFrom, lastValueFrom, Subject } from "rxjs";
|
||||
|
||||
import { OrganizationUserApiService } from "@bitwarden/admin-console/common";
|
||||
import { SubscriptionHiddenIcon } from "@bitwarden/assets/svg";
|
||||
import { ApiService } from "@bitwarden/common/abstractions/api.service";
|
||||
import { OrganizationApiServiceAbstraction } from "@bitwarden/common/admin-console/abstractions/organization/organization-api.service.abstraction";
|
||||
import {
|
||||
@@ -39,7 +40,6 @@ import {
|
||||
import { BillingSyncApiKeyComponent } from "./billing-sync-api-key.component";
|
||||
import { ChangePlanDialogResultType, openChangePlanDialog } from "./change-plan-dialog.component";
|
||||
import { DownloadLicenceDialogComponent } from "./download-license.component";
|
||||
import { SubscriptionHiddenIcon } from "./icons/subscription-hidden.icon";
|
||||
import { SecretsManagerSubscriptionOptions } from "./sm-adjust-subscription.component";
|
||||
|
||||
@Component({
|
||||
|
||||
Some files were not shown because too many files have changed in this diff Show More
Reference in New Issue
Block a user