From 2bf734bd433701d8eeeedf60ca9328ef31d1deb3 Mon Sep 17 00:00:00 2001 From: "renovate[bot]" <29139614+renovate[bot]@users.noreply.github.com> Date: Tue, 18 Nov 2025 08:48:29 -0600 Subject: [PATCH 01/52] [deps] Platform: Update @types/node to v22.19.1 (#17448) Co-authored-by: renovate[bot] <29139614+renovate[bot]@users.noreply.github.com> --- .../native-messaging-test-runner/package-lock.json | 8 ++++---- apps/desktop/native-messaging-test-runner/package.json | 2 +- package-lock.json | 8 ++++---- package.json | 2 +- 4 files changed, 10 insertions(+), 10 deletions(-) diff --git a/apps/desktop/native-messaging-test-runner/package-lock.json b/apps/desktop/native-messaging-test-runner/package-lock.json index a4286aabed..9ad1ffb3ec 100644 --- a/apps/desktop/native-messaging-test-runner/package-lock.json +++ b/apps/desktop/native-messaging-test-runner/package-lock.json @@ -19,7 +19,7 @@ "yargs": "18.0.0" }, "devDependencies": { - "@types/node": "22.19.0", + "@types/node": "22.19.1", "typescript": "5.4.2" } }, @@ -117,9 +117,9 @@ "license": "MIT" }, "node_modules/@types/node": { - "version": "22.19.0", - "resolved": "https://registry.npmjs.org/@types/node/-/node-22.19.0.tgz", - "integrity": "sha512-xpr/lmLPQEj+TUnHmR+Ab91/glhJvsqcjB+yY0Ix9GO70H6Lb4FHH5GeqdOE5btAx7eIMwuHkp4H2MSkLcqWbA==", + "version": "22.19.1", + "resolved": "https://registry.npmjs.org/@types/node/-/node-22.19.1.tgz", + "integrity": "sha512-LCCV0HdSZZZb34qifBsyWlUmok6W7ouER+oQIGBScS8EsZsQbrtFTUrDX4hOl+CS6p7cnNC4td+qrSVGSCTUfQ==", "license": "MIT", "peer": true, "dependencies": { diff --git a/apps/desktop/native-messaging-test-runner/package.json b/apps/desktop/native-messaging-test-runner/package.json index 55699af47d..21a6ba3626 100644 --- a/apps/desktop/native-messaging-test-runner/package.json +++ b/apps/desktop/native-messaging-test-runner/package.json @@ -24,7 +24,7 @@ "yargs": "18.0.0" }, "devDependencies": { - "@types/node": "22.19.0", + "@types/node": "22.19.1", "typescript": "5.4.2" }, "_moduleAliases": { diff --git a/package-lock.json b/package-lock.json index bb8355dc63..82d05df83d 100644 --- a/package-lock.json +++ b/package-lock.json @@ -112,7 +112,7 @@ "@types/koa-json": "2.0.23", "@types/lowdb": "1.0.15", "@types/lunr": "2.3.7", - "@types/node": "22.19.0", + "@types/node": "22.19.1", "@types/node-fetch": "2.6.4", "@types/node-forge": "1.3.11", "@types/papaparse": "5.3.16", @@ -14391,9 +14391,9 @@ "license": "MIT" }, "node_modules/@types/node": { - "version": "22.19.0", - "resolved": "https://registry.npmjs.org/@types/node/-/node-22.19.0.tgz", - "integrity": "sha512-xpr/lmLPQEj+TUnHmR+Ab91/glhJvsqcjB+yY0Ix9GO70H6Lb4FHH5GeqdOE5btAx7eIMwuHkp4H2MSkLcqWbA==", + "version": "22.19.1", + "resolved": "https://registry.npmjs.org/@types/node/-/node-22.19.1.tgz", + "integrity": "sha512-LCCV0HdSZZZb34qifBsyWlUmok6W7ouER+oQIGBScS8EsZsQbrtFTUrDX4hOl+CS6p7cnNC4td+qrSVGSCTUfQ==", "license": "MIT", "dependencies": { "undici-types": "~6.21.0" diff --git a/package.json b/package.json index f9757aa1e6..53fcb74ce8 100644 --- a/package.json +++ b/package.json @@ -75,7 +75,7 @@ "@types/koa-json": "2.0.23", "@types/lowdb": "1.0.15", "@types/lunr": "2.3.7", - "@types/node": "22.19.0", + "@types/node": "22.19.1", "@types/node-fetch": "2.6.4", "@types/node-forge": "1.3.11", "@types/papaparse": "5.3.16", From bd2f6e75666f1604fbb3554d14c13496e4cb0de4 Mon Sep 17 00:00:00 2001 From: "renovate[bot]" <29139614+renovate[bot]@users.noreply.github.com> Date: Tue, 18 Nov 2025 15:49:45 +0100 Subject: [PATCH 02/52] [deps]: Update anchore/scan-action action to v7 (#16635) Co-authored-by: renovate[bot] <29139614+renovate[bot]@users.noreply.github.com> --- .github/workflows/build-web.yml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.github/workflows/build-web.yml b/.github/workflows/build-web.yml index 719063958f..89dd684c5f 100644 --- a/.github/workflows/build-web.yml +++ b/.github/workflows/build-web.yml @@ -334,7 +334,7 @@ jobs: - name: Scan Docker image if: ${{ needs.setup.outputs.has_secrets == 'true' }} id: container-scan - uses: anchore/scan-action@1638637db639e0ade3258b51db49a9a137574c3e # v6.5.1 + uses: anchore/scan-action@568b89d27fc18c60e56937bff480c91c772cd993 # v7.1.0 with: image: ${{ steps.image-name.outputs.name }} fail-build: false From 20d44b5136f20d061bb3756b9f114757e74fad03 Mon Sep 17 00:00:00 2001 From: Leslie Tilton <23057410+Banrion@users.noreply.github.com> Date: Tue, 18 Nov 2025 09:03:05 -0600 Subject: [PATCH 03/52] [PM-27739] Fix bug for icons not showing on application tables (#17373) * Added function to get a cipher icon for application tables. Update all application component to use signal properties * Fix type * Handle no ciphers on application --- .../risk-insights-orchestrator.service.ts | 18 ++++ .../view/risk-insights-data.service.ts | 4 +- .../all-applications.component.html | 16 ++-- .../all-applications.component.ts | 87 ++++++++++++------- .../critical-applications.component.ts | 34 ++++++-- .../app-table-row-scrollable.component.html | 5 +- .../app-table-row-scrollable.component.ts | 7 +- 7 files changed, 117 insertions(+), 54 deletions(-) diff --git a/bitwarden_license/bit-common/src/dirt/reports/risk-insights/services/domain/risk-insights-orchestrator.service.ts b/bitwarden_license/bit-common/src/dirt/reports/risk-insights/services/domain/risk-insights-orchestrator.service.ts index 38e1237318..51d35570cd 100644 --- a/bitwarden_license/bit-common/src/dirt/reports/risk-insights/services/domain/risk-insights-orchestrator.service.ts +++ b/bitwarden_license/bit-common/src/dirt/reports/risk-insights/services/domain/risk-insights-orchestrator.service.ts @@ -35,6 +35,7 @@ import { getUserId } from "@bitwarden/common/auth/services/account.service"; import { CipherId, OrganizationId, UserId } from "@bitwarden/common/types/guid"; import { CipherService } from "@bitwarden/common/vault/abstractions/cipher.service"; import { CipherView } from "@bitwarden/common/vault/models/view/cipher.view"; +import { CipherViewLike } from "@bitwarden/common/vault/utils/cipher-view-like-utils"; import { LogService } from "@bitwarden/logging"; import { @@ -191,6 +192,23 @@ export class RiskInsightsOrchestratorService { this._generateReportTriggerSubject.next(true); } + /** + * Gets the cipher icon for a given cipher ID + * + * @param cipherId The ID of the cipher to get the icon for + * @returns A CipherViewLike if found, otherwise undefined + */ + getCipherIcon(cipherId: string): CipherViewLike | undefined { + const currentCiphers = this._ciphersSubject.value; + if (!currentCiphers) { + return undefined; + } + + const foundCipher = currentCiphers.find((c) => c.id === cipherId); + + return foundCipher; + } + /** * Initializes the service context for a specific organization * diff --git a/bitwarden_license/bit-common/src/dirt/reports/risk-insights/services/view/risk-insights-data.service.ts b/bitwarden_license/bit-common/src/dirt/reports/risk-insights/services/view/risk-insights-data.service.ts index 7b9255ca82..d426a6b09c 100644 --- a/bitwarden_license/bit-common/src/dirt/reports/risk-insights/services/view/risk-insights-data.service.ts +++ b/bitwarden_license/bit-common/src/dirt/reports/risk-insights/services/view/risk-insights-data.service.ts @@ -87,7 +87,9 @@ export class RiskInsightsDataService { this._destroy$.complete(); } - // ----- UI-triggered methods (delegate to orchestrator) ----- + getCipherIcon(cipherId: string) { + return this.orchestrator.getCipherIcon(cipherId); + } initializeForOrganization(organizationId: OrganizationId) { this.orchestrator.initializeForOrganization(organizationId); } diff --git a/bitwarden_license/bit-web/src/app/dirt/access-intelligence/all-applications/all-applications.component.html b/bitwarden_license/bit-web/src/app/dirt/access-intelligence/all-applications/all-applications.component.html index b1c2faa4f0..73ded40388 100644 --- a/bitwarden_license/bit-web/src/app/dirt/access-intelligence/all-applications/all-applications.component.html +++ b/bitwarden_license/bit-web/src/app/dirt/access-intelligence/all-applications/all-applications.component.html @@ -22,10 +22,10 @@ bitTypography="h3" class="!tw-mb-0" aria-describedby="allAppsOrgAtRiskMembersLabel" - >{{ applicationSummary.totalAtRiskMemberCount }}{{ applicationSummary().totalAtRiskMemberCount }} {{ - "cardMetrics" | i18n: applicationSummary.totalMemberCount + "cardMetrics" | i18n: applicationSummary().totalMemberCount }}
@@ -62,10 +62,10 @@ bitTypography="h3" class="!tw-mb-0" aria-describedby="allAppsOrgAtRiskApplicationsLabel" - >{{ applicationSummary.totalAtRiskApplicationCount }}{{ applicationSummary().totalAtRiskApplicationCount }} {{ - "cardMetrics" | i18n: applicationSummary.totalApplicationCount + "cardMetrics" | i18n: applicationSummary().totalApplicationCount }}
@@ -95,11 +95,11 @@ type="button" [buttonType]="'primary'" bitButton - [disabled]="!selectedUrls.size" - [loading]="markingAsCritical" + [disabled]="!selectedUrls().size" + [loading]="markingAsCritical()" (click)="markAppsAsCritical()" > - + {{ "markAppAsCritical" | i18n }}
@@ -108,7 +108,7 @@ [dataSource]="dataSource" [showRowCheckBox]="true" [showRowMenuForCriticalApps]="false" - [selectedUrls]="selectedUrls" + [selectedUrls]="selectedUrls()" [openApplication]="drawerDetails.invokerId || ''" [checkboxChange]="onCheckboxChange" [showAppAtRiskMembers]="showAppAtRiskMembers" diff --git a/bitwarden_license/bit-web/src/app/dirt/access-intelligence/all-applications/all-applications.component.ts b/bitwarden_license/bit-web/src/app/dirt/access-intelligence/all-applications/all-applications.component.ts index acad2901ba..3a9159ad68 100644 --- a/bitwarden_license/bit-web/src/app/dirt/access-intelligence/all-applications/all-applications.component.ts +++ b/bitwarden_license/bit-web/src/app/dirt/access-intelligence/all-applications/all-applications.component.ts @@ -1,20 +1,23 @@ -import { Component, DestroyRef, inject, OnInit } from "@angular/core"; +import { + Component, + DestroyRef, + inject, + OnInit, + ChangeDetectionStrategy, + signal, +} from "@angular/core"; import { takeUntilDestroyed } from "@angular/core/rxjs-interop"; import { FormControl } from "@angular/forms"; -import { ActivatedRoute, Router } from "@angular/router"; +import { ActivatedRoute } from "@angular/router"; import { debounceTime } from "rxjs"; import { Security } from "@bitwarden/assets/svg"; -import { - ApplicationHealthReportDetailEnriched, - RiskInsightsDataService, -} from "@bitwarden/bit-common/dirt/reports/risk-insights"; +import { RiskInsightsDataService } from "@bitwarden/bit-common/dirt/reports/risk-insights"; import { createNewSummaryData } from "@bitwarden/bit-common/dirt/reports/risk-insights/helpers"; import { OrganizationReportSummary, ReportStatus, } from "@bitwarden/bit-common/dirt/reports/risk-insights/models/report-models"; -import { Organization } from "@bitwarden/common/admin-console/models/domain/organization"; import { I18nService } from "@bitwarden/common/platform/abstractions/i18n.service"; import { IconButtonModule, @@ -29,12 +32,14 @@ import { HeaderModule } from "@bitwarden/web-vault/app/layouts/header/header.mod import { SharedModule } from "@bitwarden/web-vault/app/shared"; import { PipesModule } from "@bitwarden/web-vault/app/vault/individual-vault/pipes/pipes.module"; -import { AppTableRowScrollableComponent } from "../shared/app-table-row-scrollable.component"; +import { + ApplicationTableDataSource, + AppTableRowScrollableComponent, +} from "../shared/app-table-row-scrollable.component"; import { ApplicationsLoadingComponent } from "../shared/risk-insights-loading.component"; -// FIXME(https://bitwarden.atlassian.net/browse/CL-764): Migrate to OnPush -// eslint-disable-next-line @angular-eslint/prefer-on-push-component-change-detection @Component({ + changeDetection: ChangeDetectionStrategy.OnPush, selector: "dirt-all-applications", templateUrl: "./all-applications.component.html", imports: [ @@ -51,24 +56,25 @@ import { ApplicationsLoadingComponent } from "../shared/risk-insights-loading.co ], }) export class AllApplicationsComponent implements OnInit { - protected dataSource = new TableDataSource(); - protected selectedUrls: Set = new Set(); - protected searchControl = new FormControl("", { nonNullable: true }); - protected organization = new Organization(); - noItemsIcon = Security; - protected markingAsCritical = false; - protected applicationSummary: OrganizationReportSummary = createNewSummaryData(); - protected ReportStatusEnum = ReportStatus; - destroyRef = inject(DestroyRef); + protected ReportStatusEnum = ReportStatus; + protected noItemsIcon = Security; + + // Standard properties + protected readonly dataSource = new TableDataSource(); + protected readonly searchControl = new FormControl("", { nonNullable: true }); + + // Template driven properties + protected readonly selectedUrls = signal(new Set()); + protected readonly markingAsCritical = signal(false); + protected readonly applicationSummary = signal(createNewSummaryData()); + constructor( protected i18nService: I18nService, protected activatedRoute: ActivatedRoute, protected toastService: ToastService, protected dataService: RiskInsightsDataService, - private router: Router, - // protected allActivitiesService: AllActivitiesService, ) { this.searchControl.valueChanges .pipe(debounceTime(200), takeUntilDestroyed()) @@ -78,8 +84,21 @@ export class AllApplicationsComponent implements OnInit { async ngOnInit() { this.dataService.enrichedReportData$.pipe(takeUntilDestroyed(this.destroyRef)).subscribe({ next: (report) => { - this.applicationSummary = report?.summaryData ?? createNewSummaryData(); - this.dataSource.data = report?.reportData ?? []; + if (report != null) { + this.applicationSummary.set(report.summaryData); + + // Map the report data to include the iconCipher for each application + const tableDataWithIcon = report.reportData.map((app) => ({ + ...app, + iconCipher: + app.cipherIds.length > 0 + ? this.dataService.getCipherIcon(app.cipherIds[0]) + : undefined, + })); + this.dataSource.data = tableDataWithIcon; + } else { + this.dataSource.data = []; + } }, error: () => { this.dataSource.data = []; @@ -88,15 +107,15 @@ export class AllApplicationsComponent implements OnInit { } isMarkedAsCriticalItem(applicationName: string) { - return this.selectedUrls.has(applicationName); + return this.selectedUrls().has(applicationName); } markAppsAsCritical = async () => { - this.markingAsCritical = true; - const count = this.selectedUrls.size; + this.markingAsCritical.set(true); + const count = this.selectedUrls().size; this.dataService - .saveCriticalApplications(Array.from(this.selectedUrls)) + .saveCriticalApplications(Array.from(this.selectedUrls())) .pipe(takeUntilDestroyed(this.destroyRef)) .subscribe({ next: () => { @@ -105,8 +124,8 @@ export class AllApplicationsComponent implements OnInit { title: "", message: this.i18nService.t("criticalApplicationsMarkedSuccess", count.toString()), }); - this.selectedUrls.clear(); - this.markingAsCritical = false; + this.selectedUrls.set(new Set()); + this.markingAsCritical.set(false); }, error: () => { this.toastService.showToast({ @@ -125,9 +144,15 @@ export class AllApplicationsComponent implements OnInit { onCheckboxChange = (applicationName: string, event: Event) => { const isChecked = (event.target as HTMLInputElement).checked; if (isChecked) { - this.selectedUrls.add(applicationName); + this.selectedUrls.update((selectedUrls) => { + selectedUrls.add(applicationName); + return selectedUrls; + }); } else { - this.selectedUrls.delete(applicationName); + this.selectedUrls.update((selectedUrls) => { + selectedUrls.delete(applicationName); + return selectedUrls; + }); } }; } diff --git a/bitwarden_license/bit-web/src/app/dirt/access-intelligence/critical-applications/critical-applications.component.ts b/bitwarden_license/bit-web/src/app/dirt/access-intelligence/critical-applications/critical-applications.component.ts index 1ea745929d..b61190df66 100644 --- a/bitwarden_license/bit-web/src/app/dirt/access-intelligence/critical-applications/critical-applications.component.ts +++ b/bitwarden_license/bit-web/src/app/dirt/access-intelligence/critical-applications/critical-applications.component.ts @@ -1,6 +1,6 @@ // FIXME: Update this file to be type safe and remove this and next line // @ts-strict-ignore -import { Component, DestroyRef, inject, OnInit } from "@angular/core"; +import { Component, DestroyRef, inject, OnInit, ChangeDetectionStrategy } from "@angular/core"; import { takeUntilDestroyed } from "@angular/core/rxjs-interop"; import { FormControl } from "@angular/forms"; import { ActivatedRoute, Router } from "@angular/router"; @@ -8,7 +8,6 @@ import { debounceTime, EMPTY, from, map, switchMap, take } from "rxjs"; import { Security } from "@bitwarden/assets/svg"; import { - ApplicationHealthReportDetailEnriched, CriticalAppsService, RiskInsightsDataService, RiskInsightsReportService, @@ -30,12 +29,14 @@ import { SharedModule } from "@bitwarden/web-vault/app/shared"; import { PipesModule } from "@bitwarden/web-vault/app/vault/individual-vault/pipes/pipes.module"; import { RiskInsightsTabType } from "../models/risk-insights.models"; -import { AppTableRowScrollableComponent } from "../shared/app-table-row-scrollable.component"; +import { + ApplicationTableDataSource, + AppTableRowScrollableComponent, +} from "../shared/app-table-row-scrollable.component"; import { AccessIntelligenceSecurityTasksService } from "../shared/security-tasks.service"; -// FIXME(https://bitwarden.atlassian.net/browse/CL-764): Migrate to OnPush -// eslint-disable-next-line @angular-eslint/prefer-on-push-component-change-detection @Component({ + changeDetection: ChangeDetectionStrategy.OnPush, selector: "dirt-critical-applications", templateUrl: "./critical-applications.component.html", imports: [ @@ -55,7 +56,7 @@ export class CriticalApplicationsComponent implements OnInit { protected organizationId: OrganizationId; noItemsIcon = Security; - protected dataSource = new TableDataSource(); + protected dataSource = new TableDataSource(); protected applicationSummary = {} as OrganizationReportSummary; protected selectedIds: Set = new Set(); @@ -79,9 +80,24 @@ export class CriticalApplicationsComponent implements OnInit { async ngOnInit() { this.dataService.criticalReportResults$.pipe(takeUntilDestroyed(this.destroyRef)).subscribe({ next: (criticalReport) => { - this.dataSource.data = criticalReport?.reportData ?? []; - this.applicationSummary = criticalReport?.summaryData ?? createNewSummaryData(); - this.enableRequestPasswordChange = criticalReport?.summaryData?.totalAtRiskMemberCount > 0; + if (criticalReport != null) { + // Map the report data to include the iconCipher for each application + const tableDataWithIcon = criticalReport.reportData.map((app) => ({ + ...app, + iconCipher: + app.cipherIds.length > 0 + ? this.dataService.getCipherIcon(app.cipherIds[0]) + : undefined, + })); + this.dataSource.data = tableDataWithIcon; + + this.applicationSummary = criticalReport.summaryData; + this.enableRequestPasswordChange = criticalReport.summaryData.totalAtRiskMemberCount > 0; + } else { + this.dataSource.data = []; + this.applicationSummary = createNewSummaryData(); + this.enableRequestPasswordChange = false; + } }, error: () => { this.dataSource.data = []; diff --git a/bitwarden_license/bit-web/src/app/dirt/access-intelligence/shared/app-table-row-scrollable.component.html b/bitwarden_license/bit-web/src/app/dirt/access-intelligence/shared/app-table-row-scrollable.component.html index 79af3869d9..edd90eaf97 100644 --- a/bitwarden_license/bit-web/src/app/dirt/access-intelligence/shared/app-table-row-scrollable.component.html +++ b/bitwarden_license/bit-web/src/app/dirt/access-intelligence/shared/app-table-row-scrollable.component.html @@ -46,10 +46,7 @@ [attr.aria-label]="'viewItem' | i18n" > - + ; + dataSource!: TableDataSource; // FIXME(https://bitwarden.atlassian.net/browse/CL-903): Migrate to Signals // eslint-disable-next-line @angular-eslint/prefer-signals @Input() showRowMenuForCriticalApps: boolean = false; From 96ffb567711f8f5cdab41e4d3a6d9bc36f1af971 Mon Sep 17 00:00:00 2001 From: Vicki League Date: Tue, 18 Nov 2025 11:25:48 -0500 Subject: [PATCH 04/52] [CL-928] Set link component to semibold weight (#17395) --- libs/components/src/link/link.directive.ts | 2 +- libs/components/src/typography/typography.stories.ts | 12 ++++++------ 2 files changed, 7 insertions(+), 7 deletions(-) diff --git a/libs/components/src/link/link.directive.ts b/libs/components/src/link/link.directive.ts index df124a6811..e6de8ac840 100644 --- a/libs/components/src/link/link.directive.ts +++ b/libs/components/src/link/link.directive.ts @@ -25,7 +25,7 @@ const commonStyles = [ "tw-leading-none", "tw-px-0", "tw-py-0.5", - "tw-font-medium", + "tw-font-semibold", "tw-bg-transparent", "tw-border-0", "tw-border-none", diff --git a/libs/components/src/typography/typography.stories.ts b/libs/components/src/typography/typography.stories.ts index bb055be79a..f9c57ae263 100644 --- a/libs/components/src/typography/typography.stories.ts +++ b/libs/components/src/typography/typography.stories.ts @@ -27,42 +27,42 @@ const typographyProps: TypographyData[] = [ { id: "h1", typography: "h1", - weight: "Regular", + weight: "Medium", size: 30, lineHeight: "150%", }, { id: "h2", typography: "h2", - weight: "Regular", + weight: "Medium", size: 24, lineHeight: "150%", }, { id: "h3", typography: "h3", - weight: "Regular", + weight: "Medium", size: 20, lineHeight: "150%", }, { id: "h4", typography: "h4", - weight: "Regular", + weight: "Medium", size: 18, lineHeight: "150%", }, { id: "h5", typography: "h5", - weight: "Regular", + weight: "Medium", size: 16, lineHeight: "150%", }, { id: "h6", typography: "h6", - weight: "Regular", + weight: "Medium", size: 14, lineHeight: "150%", }, From 9d15ae80ca4910e60406b3252e2cb8c28bcc6619 Mon Sep 17 00:00:00 2001 From: "renovate[bot]" <29139614+renovate[bot]@users.noreply.github.com> Date: Tue, 18 Nov 2025 10:30:27 -0600 Subject: [PATCH 05/52] [deps] Tools: Update @types/papaparse to v5.5.0 (#17454) Co-authored-by: renovate[bot] <29139614+renovate[bot]@users.noreply.github.com> --- package-lock.json | 8 ++++---- package.json | 2 +- 2 files changed, 5 insertions(+), 5 deletions(-) diff --git a/package-lock.json b/package-lock.json index 82d05df83d..5d9d43419f 100644 --- a/package-lock.json +++ b/package-lock.json @@ -115,7 +115,7 @@ "@types/node": "22.19.1", "@types/node-fetch": "2.6.4", "@types/node-forge": "1.3.11", - "@types/papaparse": "5.3.16", + "@types/papaparse": "5.5.0", "@types/proper-lockfile": "4.1.4", "@types/retry": "0.12.5", "@types/zxcvbn": "4.4.5", @@ -14459,9 +14459,9 @@ } }, "node_modules/@types/papaparse": { - "version": "5.3.16", - "resolved": "https://registry.npmjs.org/@types/papaparse/-/papaparse-5.3.16.tgz", - "integrity": "sha512-T3VuKMC2H0lgsjI9buTB3uuKj3EMD2eap1MOuEQuBQ44EnDx/IkGhU6EwiTf9zG3za4SKlmwKAImdDKdNnCsXg==", + "version": "5.5.0", + "resolved": "https://registry.npmjs.org/@types/papaparse/-/papaparse-5.5.0.tgz", + "integrity": "sha512-GVs5iMQmUr54BAZYYkByv8zPofFxmyxUpISPb2oh8sayR3+1zbxasrOvoKiHJ/nnoq/uULuPsu1Lze1EkagVFg==", "dev": true, "license": "MIT", "dependencies": { diff --git a/package.json b/package.json index 53fcb74ce8..3e5a2581e8 100644 --- a/package.json +++ b/package.json @@ -78,7 +78,7 @@ "@types/node": "22.19.1", "@types/node-fetch": "2.6.4", "@types/node-forge": "1.3.11", - "@types/papaparse": "5.3.16", + "@types/papaparse": "5.5.0", "@types/proper-lockfile": "4.1.4", "@types/retry": "0.12.5", "@types/zxcvbn": "4.4.5", From 60977b02771c4393699be8ae3ef59b85db8e12c5 Mon Sep 17 00:00:00 2001 From: "renovate[bot]" <29139614+renovate[bot]@users.noreply.github.com> Date: Tue, 18 Nov 2025 17:46:55 +0100 Subject: [PATCH 06/52] [deps] Platform: Update electron-log to v5.4.3 (#17455) Co-authored-by: renovate[bot] <29139614+renovate[bot]@users.noreply.github.com> --- package-lock.json | 8 ++++---- package.json | 2 +- 2 files changed, 5 insertions(+), 5 deletions(-) diff --git a/package-lock.json b/package-lock.json index 5d9d43419f..9c3c7e2226 100644 --- a/package-lock.json +++ b/package-lock.json @@ -136,7 +136,7 @@ "css-loader": "7.1.2", "electron": "37.7.0", "electron-builder": "26.0.12", - "electron-log": "5.4.0", + "electron-log": "5.4.3", "electron-reload": "2.0.0-alpha.1", "electron-store": "8.2.0", "electron-updater": "6.6.4", @@ -20938,9 +20938,9 @@ } }, "node_modules/electron-log": { - "version": "5.4.0", - "resolved": "https://registry.npmjs.org/electron-log/-/electron-log-5.4.0.tgz", - "integrity": "sha512-AXI5OVppskrWxEAmCxuv8ovX+s2Br39CpCAgkGMNHQtjYT3IiVbSQTncEjFVGPgoH35ZygRm/mvUMBDWwhRxgg==", + "version": "5.4.3", + "resolved": "https://registry.npmjs.org/electron-log/-/electron-log-5.4.3.tgz", + "integrity": "sha512-sOUsM3LjZdugatazSQ/XTyNcw8dfvH1SYhXWiJyfYodAAKOZdHs0txPiLDXFzOZbhXgAgshQkshH2ccq0feyLQ==", "dev": true, "license": "MIT", "engines": { diff --git a/package.json b/package.json index 3e5a2581e8..d97b7755de 100644 --- a/package.json +++ b/package.json @@ -99,7 +99,7 @@ "css-loader": "7.1.2", "electron": "37.7.0", "electron-builder": "26.0.12", - "electron-log": "5.4.0", + "electron-log": "5.4.3", "electron-reload": "2.0.0-alpha.1", "electron-store": "8.2.0", "electron-updater": "6.6.4", From 82a0b3aa70be774cd48e938d00cddfb400256e2f Mon Sep 17 00:00:00 2001 From: "renovate[bot]" <29139614+renovate[bot]@users.noreply.github.com> Date: Tue, 18 Nov 2025 17:48:52 +0100 Subject: [PATCH 07/52] [deps] Platform: Update semver to v7.7.3 (#17457) Co-authored-by: renovate[bot] <29139614+renovate[bot]@users.noreply.github.com> Co-authored-by: Daniel James Smith <2670567+djsmith85@users.noreply.github.com> --- apps/cli/package.json | 2 +- package-lock.json | 36 ++++++++++++++++++------------------ package.json | 2 +- 3 files changed, 20 insertions(+), 20 deletions(-) diff --git a/apps/cli/package.json b/apps/cli/package.json index 26e1183004..00686959ef 100644 --- a/apps/cli/package.json +++ b/apps/cli/package.json @@ -87,7 +87,7 @@ "papaparse": "5.5.3", "proper-lockfile": "4.1.2", "rxjs": "7.8.1", - "semver": "7.7.2", + "semver": "7.7.3", "tldts": "7.0.1", "zxcvbn": "4.4.2" } diff --git a/package-lock.json b/package-lock.json index 9c3c7e2226..f673947be9 100644 --- a/package-lock.json +++ b/package-lock.json @@ -66,7 +66,7 @@ "qrcode-parser": "2.1.3", "qrious": "4.0.2", "rxjs": "7.8.1", - "semver": "7.7.2", + "semver": "7.7.3", "tabbable": "6.3.0", "tldts": "7.0.1", "ts-node": "10.9.2", @@ -225,7 +225,7 @@ "papaparse": "5.5.3", "proper-lockfile": "4.1.2", "rxjs": "7.8.1", - "semver": "7.7.2", + "semver": "7.7.3", "tldts": "7.0.1", "zxcvbn": "4.4.2" }, @@ -1936,6 +1936,19 @@ "strip-json-comments": "3.1.1" } }, + "node_modules/@angular-eslint/schematics/node_modules/semver": { + "version": "7.7.2", + "resolved": "https://registry.npmjs.org/semver/-/semver-7.7.2.tgz", + "integrity": "sha512-RF0Fw+rO5AMf9MAyaRXI4AV0Ulj5lMHqVxxdSgiVbixSCXoEmmX/jk0CuJw4+3SqroYO9VoUh+HcuJivvtJemA==", + "dev": true, + "license": "ISC", + "bin": { + "semver": "bin/semver.js" + }, + "engines": { + "node": ">=10" + } + }, "node_modules/@angular-eslint/template-parser": { "version": "19.6.0", "resolved": "https://registry.npmjs.org/@angular-eslint/template-parser/-/template-parser-19.6.0.tgz", @@ -36903,9 +36916,9 @@ } }, "node_modules/semver": { - "version": "7.7.2", - "resolved": "https://registry.npmjs.org/semver/-/semver-7.7.2.tgz", - "integrity": "sha512-RF0Fw+rO5AMf9MAyaRXI4AV0Ulj5lMHqVxxdSgiVbixSCXoEmmX/jk0CuJw4+3SqroYO9VoUh+HcuJivvtJemA==", + "version": "7.7.3", + "resolved": "https://registry.npmjs.org/semver/-/semver-7.7.3.tgz", + "integrity": "sha512-SdsKMrI9TdgjdweUSR9MweHA4EJ8YxHn8DFaDisvhVlUOe4BF1tLD7GAj0lIqWVl+dPb/rExr0Btby5loQm20Q==", "license": "ISC", "bin": { "semver": "bin/semver.js" @@ -39354,19 +39367,6 @@ } } }, - "node_modules/ts-jest/node_modules/semver": { - "version": "7.7.3", - "resolved": "https://registry.npmjs.org/semver/-/semver-7.7.3.tgz", - "integrity": "sha512-SdsKMrI9TdgjdweUSR9MweHA4EJ8YxHn8DFaDisvhVlUOe4BF1tLD7GAj0lIqWVl+dPb/rExr0Btby5loQm20Q==", - "dev": true, - "license": "ISC", - "bin": { - "semver": "bin/semver.js" - }, - "engines": { - "node": ">=10" - } - }, "node_modules/ts-jest/node_modules/type-fest": { "version": "4.41.0", "resolved": "https://registry.npmjs.org/type-fest/-/type-fest-4.41.0.tgz", diff --git a/package.json b/package.json index d97b7755de..42162a6189 100644 --- a/package.json +++ b/package.json @@ -203,7 +203,7 @@ "qrcode-parser": "2.1.3", "qrious": "4.0.2", "rxjs": "7.8.1", - "semver": "7.7.2", + "semver": "7.7.3", "tabbable": "6.3.0", "tldts": "7.0.1", "ts-node": "10.9.2", From 3b84da60cafa79820d5ff89cf7c5336e9aa3775b Mon Sep 17 00:00:00 2001 From: "renovate[bot]" <29139614+renovate[bot]@users.noreply.github.com> Date: Tue, 18 Nov 2025 17:01:53 +0000 Subject: [PATCH 08/52] [deps] Platform: Update @types/chrome to v0.1.27 (#17453) Co-authored-by: renovate[bot] <29139614+renovate[bot]@users.noreply.github.com> --- package-lock.json | 8 ++++---- package.json | 2 +- 2 files changed, 5 insertions(+), 5 deletions(-) diff --git a/package-lock.json b/package-lock.json index f673947be9..b7b625fdde 100644 --- a/package-lock.json +++ b/package-lock.json @@ -100,7 +100,7 @@ "@storybook/theming": "8.6.12", "@storybook/web-components-webpack5": "8.6.12", "@tailwindcss/container-queries": "0.1.1", - "@types/chrome": "0.1.12", + "@types/chrome": "0.1.27", "@types/firefox-webext-browser": "120.0.4", "@types/inquirer": "8.2.10", "@types/jest": "29.5.14", @@ -13957,9 +13957,9 @@ } }, "node_modules/@types/chrome": { - "version": "0.1.12", - "resolved": "https://registry.npmjs.org/@types/chrome/-/chrome-0.1.12.tgz", - "integrity": "sha512-jEkxs9GPQHx7g49WjkA8QDNcqODbMGDuBbWQOtjiS/Wf9AiEcDmQMIAgJvC/Xi36WoCVNx584g0Dd9ThJQCAiw==", + "version": "0.1.27", + "resolved": "https://registry.npmjs.org/@types/chrome/-/chrome-0.1.27.tgz", + "integrity": "sha512-pkkCb0Ft8X+Igi751POzT+YqchSxUCtB6s4Gs6ttgSj8qzJga/qlJMgSW1mKxuQTW4i0sTqQbqVtzXDS5AU+4A==", "dev": true, "license": "MIT", "dependencies": { diff --git a/package.json b/package.json index 42162a6189..52a7d1c60a 100644 --- a/package.json +++ b/package.json @@ -63,7 +63,7 @@ "@storybook/theming": "8.6.12", "@storybook/web-components-webpack5": "8.6.12", "@tailwindcss/container-queries": "0.1.1", - "@types/chrome": "0.1.12", + "@types/chrome": "0.1.27", "@types/firefox-webext-browser": "120.0.4", "@types/inquirer": "8.2.10", "@types/jest": "29.5.14", From b1acff7f5c09a82b919a40544b413824242f7fa6 Mon Sep 17 00:00:00 2001 From: Daniel Riera Date: Tue, 18 Nov 2025 12:22:13 -0500 Subject: [PATCH 09/52] Pm 27900 add additional hardening in extension frame validation (#17265) * PM-27900 harden iframe, origin route tightening and test updates * reduce comments to make more legible * Removes referrer check in favor of PM-27822 #17313 bitwarden/clients@4206447cfece36766ed413791821ac6156e12ba8 * nake token optional since it is later set * whitelist -> allowlist * improve notes on unsafe * improve content handler notes * order allowlist * improve jsdoc on ismessagefromextension method * cover additional test cases * rename verifytoken and document more clear, update referrer --------- Co-authored-by: Miles Blackwood --- .../content/content-message-handler.ts | 19 ++- .../autofill-inline-menu-container.ts | 1 + .../autofill-inline-menu-container.spec.ts | 71 +++++++- .../autofill-inline-menu-container.ts | 156 +++++++++++++++--- .../autofill-inline-menu-page-element.ts | 20 ++- 5 files changed, 233 insertions(+), 34 deletions(-) diff --git a/apps/browser/src/autofill/content/content-message-handler.ts b/apps/browser/src/autofill/content/content-message-handler.ts index c57b2d959f..63afc21592 100644 --- a/apps/browser/src/autofill/content/content-message-handler.ts +++ b/apps/browser/src/autofill/content/content-message-handler.ts @@ -86,17 +86,30 @@ function handleOpenBrowserExtensionToUrlMessage({ url }: { url?: ExtensionPageUr } /** - * Handles the window message event. + * Handles window message events, validating source and extracting referrer for security. * * @param event - The window message event */ function handleWindowMessageEvent(event: MessageEvent) { - const { source, data } = event; + const { source, data, origin } = event; if (source !== window || !data?.command) { return; } - const referrer = source.location.hostname; + // Extract hostname from event.origin for secure referrer validation in background script + let referrer: string; + // Sandboxed iframe or opaque origin support + if (origin === "null") { + referrer = "null"; + } else { + try { + const originUrl = new URL(origin); + referrer = originUrl.hostname; + } catch { + return; + } + } + const handler = windowMessageHandlers[data.command]; if (handler) { handler({ data, referrer }); diff --git a/apps/browser/src/autofill/overlay/inline-menu/abstractions/autofill-inline-menu-container.ts b/apps/browser/src/autofill/overlay/inline-menu/abstractions/autofill-inline-menu-container.ts index a147e0ba16..af60d1de77 100644 --- a/apps/browser/src/autofill/overlay/inline-menu/abstractions/autofill-inline-menu-container.ts +++ b/apps/browser/src/autofill/overlay/inline-menu/abstractions/autofill-inline-menu-container.ts @@ -5,6 +5,7 @@ import { InlineMenuCipherData } from "../../../background/abstractions/overlay.b export type AutofillInlineMenuContainerMessage = { command: string; portKey: string; + token?: string; }; export type InitAutofillInlineMenuElementMessage = AutofillInlineMenuContainerMessage & { diff --git a/apps/browser/src/autofill/overlay/inline-menu/pages/menu-container/autofill-inline-menu-container.spec.ts b/apps/browser/src/autofill/overlay/inline-menu/pages/menu-container/autofill-inline-menu-container.spec.ts index f7a5727e47..d7a61bec61 100644 --- a/apps/browser/src/autofill/overlay/inline-menu/pages/menu-container/autofill-inline-menu-container.spec.ts +++ b/apps/browser/src/autofill/overlay/inline-menu/pages/menu-container/autofill-inline-menu-container.spec.ts @@ -6,11 +6,13 @@ import { AutofillInlineMenuContainer } from "./autofill-inline-menu-container"; describe("AutofillInlineMenuContainer", () => { const portKey = "testPortKey"; - const iframeUrl = "https://example.com"; + const extensionOrigin = "chrome-extension://test-extension-id"; + const iframeUrl = `${extensionOrigin}/overlay/menu-list.html`; const pageTitle = "Example"; let autofillInlineMenuContainer: AutofillInlineMenuContainer; beforeEach(() => { + jest.spyOn(chrome.runtime, "getURL").mockReturnValue(`${extensionOrigin}/`); autofillInlineMenuContainer = new AutofillInlineMenuContainer(); }); @@ -28,7 +30,7 @@ describe("AutofillInlineMenuContainer", () => { portName: AutofillOverlayPort.List, }; - postWindowMessage(message); + postWindowMessage(message, extensionOrigin); expect(autofillInlineMenuContainer["defaultIframeAttributes"].src).toBe(message.iframeUrl); expect(autofillInlineMenuContainer["defaultIframeAttributes"].title).toBe(message.pageTitle); @@ -44,15 +46,48 @@ describe("AutofillInlineMenuContainer", () => { portName: AutofillOverlayPort.Button, }; - postWindowMessage(message); + postWindowMessage(message, extensionOrigin); jest.spyOn(autofillInlineMenuContainer["inlineMenuPageIframe"].contentWindow, "postMessage"); autofillInlineMenuContainer["inlineMenuPageIframe"].dispatchEvent(new Event("load")); expect(chrome.runtime.connect).toHaveBeenCalledWith({ name: message.portName }); + const expectedMessage = expect.objectContaining({ + ...message, + token: expect.any(String), + }); expect( autofillInlineMenuContainer["inlineMenuPageIframe"].contentWindow.postMessage, - ).toHaveBeenCalledWith(message, "*"); + ).toHaveBeenCalledWith(expectedMessage, "*"); + }); + + it("ignores initialization when URLs are not from extension origin", () => { + const invalidIframeUrlMessage = { + command: "initAutofillInlineMenuList", + iframeUrl: "https://malicious.com/overlay/menu-list.html", + pageTitle, + portKey, + portName: AutofillOverlayPort.List, + }; + + postWindowMessage(invalidIframeUrlMessage, extensionOrigin); + expect(autofillInlineMenuContainer["inlineMenuPageIframe"]).toBeUndefined(); + expect(autofillInlineMenuContainer["isInitialized"]).toBe(false); + + autofillInlineMenuContainer = new AutofillInlineMenuContainer(); + + const invalidStyleSheetUrlMessage = { + command: "initAutofillInlineMenuList", + iframeUrl, + pageTitle, + portKey, + portName: AutofillOverlayPort.List, + styleSheetUrl: "https://malicious.com/styles.css", + }; + + postWindowMessage(invalidStyleSheetUrlMessage, extensionOrigin); + expect(autofillInlineMenuContainer["inlineMenuPageIframe"]).toBeUndefined(); + expect(autofillInlineMenuContainer["isInitialized"]).toBe(false); }); }); @@ -69,7 +104,7 @@ describe("AutofillInlineMenuContainer", () => { portName: AutofillOverlayPort.Button, }; - postWindowMessage(message); + postWindowMessage(message, extensionOrigin); iframe = autofillInlineMenuContainer["inlineMenuPageIframe"]; jest.spyOn(iframe.contentWindow, "postMessage"); @@ -112,7 +147,8 @@ describe("AutofillInlineMenuContainer", () => { }); it("posts a message to the background from the inline menu iframe", () => { - const message = { command: "checkInlineMenuButtonFocused", portKey }; + const token = autofillInlineMenuContainer["token"]; + const message = { command: "checkInlineMenuButtonFocused", portKey, token }; postWindowMessage(message, "null", iframe.contentWindow as any); @@ -124,7 +160,28 @@ describe("AutofillInlineMenuContainer", () => { postWindowMessage(message); - expect(iframe.contentWindow.postMessage).toHaveBeenCalledWith(message, "*"); + const expectedMessage = expect.objectContaining({ + ...message, + token: expect.any(String), + }); + expect(iframe.contentWindow.postMessage).toHaveBeenCalledWith(expectedMessage, "*"); + }); + + it("ignores messages from iframe with invalid token", () => { + const message = { command: "checkInlineMenuButtonFocused", portKey, token: "invalid-token" }; + + postWindowMessage(message, "null", iframe.contentWindow as any); + + expect(port.postMessage).not.toHaveBeenCalled(); + }); + + it("ignores messages from iframe with commands not in the allowlist", () => { + const token = autofillInlineMenuContainer["token"]; + const message = { command: "maliciousCommand", portKey, token }; + + postWindowMessage(message, "null", iframe.contentWindow as any); + + expect(port.postMessage).not.toHaveBeenCalled(); }); }); }); diff --git a/apps/browser/src/autofill/overlay/inline-menu/pages/menu-container/autofill-inline-menu-container.ts b/apps/browser/src/autofill/overlay/inline-menu/pages/menu-container/autofill-inline-menu-container.ts index 6d85982a1a..ad0b11f0bc 100644 --- a/apps/browser/src/autofill/overlay/inline-menu/pages/menu-container/autofill-inline-menu-container.ts +++ b/apps/browser/src/autofill/overlay/inline-menu/pages/menu-container/autofill-inline-menu-container.ts @@ -1,6 +1,6 @@ import { EVENTS } from "@bitwarden/common/autofill/constants"; -import { setElementStyles } from "../../../../utils"; +import { generateRandomChars, setElementStyles } from "../../../../utils"; import { InitAutofillInlineMenuElementMessage, AutofillInlineMenuContainerWindowMessageHandlers, @@ -8,14 +8,37 @@ import { AutofillInlineMenuContainerPortMessage, } from "../../abstractions/autofill-inline-menu-container"; +/** + * Allowlist of commands that can be sent to the background script. + */ +const ALLOWED_BG_COMMANDS = new Set([ + "addNewVaultItem", + "autofillInlineMenuBlurred", + "autofillInlineMenuButtonClicked", + "checkAutofillInlineMenuButtonFocused", + "checkInlineMenuButtonFocused", + "fillAutofillInlineMenuCipher", + "fillGeneratedPassword", + "redirectAutofillInlineMenuFocusOut", + "refreshGeneratedPassword", + "refreshOverlayCiphers", + "triggerDelayedAutofillInlineMenuClosure", + "updateAutofillInlineMenuColorScheme", + "updateAutofillInlineMenuListHeight", + "unlockVault", + "viewSelectedCipher", +]); + export class AutofillInlineMenuContainer { private readonly setElementStyles = setElementStyles; - private readonly extensionOriginsSet: Set; private port: chrome.runtime.Port | null = null; /** Non-null asserted. */ private portName!: string; /** Non-null asserted. */ private inlineMenuPageIframe!: HTMLIFrameElement; + private token: string; + private isInitialized: boolean = false; + private readonly extensionOrigin: string; private readonly iframeStyles: Partial = { all: "initial", position: "fixed", @@ -49,11 +72,8 @@ export class AutofillInlineMenuContainer { }; constructor() { - this.extensionOriginsSet = new Set([ - chrome.runtime.getURL("").slice(0, -1).toLowerCase(), // Remove the trailing slash and normalize the extension url to lowercase - "null", - ]); - + this.token = generateRandomChars(32); + this.extensionOrigin = chrome.runtime.getURL("").slice(0, -1); globalThis.addEventListener("message", this.handleWindowMessage); } @@ -63,9 +83,22 @@ export class AutofillInlineMenuContainer { * @param message - The message containing the iframe url and page title. */ private handleInitInlineMenuIframe(message: InitAutofillInlineMenuElementMessage) { + if (this.isInitialized) { + return; + } + + if (!this.isExtensionUrl(message.iframeUrl)) { + return; + } + + if (message.styleSheetUrl && !this.isExtensionUrl(message.styleSheetUrl)) { + return; + } + this.defaultIframeAttributes.src = message.iframeUrl; this.defaultIframeAttributes.title = message.pageTitle; this.portName = message.portName; + this.isInitialized = true; this.inlineMenuPageIframe = globalThis.document.createElement("iframe"); this.setElementStyles(this.inlineMenuPageIframe, this.iframeStyles, true); @@ -81,6 +114,26 @@ export class AutofillInlineMenuContainer { globalThis.document.body.appendChild(this.inlineMenuPageIframe); } + /** + * validates that a URL is from the extension origin. + * prevents loading arbitrary URLs in the iframe. + * + * @param url - The URL to validate. + */ + private isExtensionUrl(url: string): boolean { + if (!url) { + return false; + } + try { + const urlObj = new URL(url); + return ( + urlObj.origin === this.extensionOrigin || urlObj.href.startsWith(this.extensionOrigin + "/") + ); + } catch { + return false; + } + } + /** * Sets up the port message listener for the inline menu page. * @@ -88,7 +141,8 @@ export class AutofillInlineMenuContainer { */ private setupPortMessageListener = (message: InitAutofillInlineMenuElementMessage) => { this.port = chrome.runtime.connect({ name: this.portName }); - this.postMessageToInlineMenuPage(message); + const initMessage = { ...message, token: this.token }; + this.postMessageToInlineMenuPageUnsafe(initMessage); }; /** @@ -97,6 +151,22 @@ export class AutofillInlineMenuContainer { * @param message - The message to post. */ private postMessageToInlineMenuPage(message: AutofillInlineMenuContainerWindowMessage) { + if (this.inlineMenuPageIframe?.contentWindow) { + const messageWithToken = { ...message, token: this.token }; + this.postMessageToInlineMenuPageUnsafe(messageWithToken); + } + } + + /** + * Posts a message to the inline menu page iframe without token validation. + * + * UNSAFE: Bypasses token authentication and sends raw messages. Only use internally + * when sending trusted messages (e.g., initialization) or when token validation + * would create circular dependencies. External callers should use postMessageToInlineMenuPage(). + * + * @param message - The message to post. + */ + private postMessageToInlineMenuPageUnsafe(message: Record) { if (this.inlineMenuPageIframe?.contentWindow) { this.inlineMenuPageIframe.contentWindow.postMessage(message, "*"); } @@ -108,9 +178,15 @@ export class AutofillInlineMenuContainer { * @param message - The message to post. */ private postMessageToBackground(message: AutofillInlineMenuContainerPortMessage) { - if (this.port) { - this.port.postMessage(message); + if (!this.port) { + return; } + + if (message.command && !ALLOWED_BG_COMMANDS.has(message.command)) { + return; + } + + this.port.postMessage(message); } /** @@ -124,23 +200,33 @@ export class AutofillInlineMenuContainer { return; } - if ( - this.windowMessageHandlers[ - message.command as keyof AutofillInlineMenuContainerWindowMessageHandlers - ] - ) { - this.windowMessageHandlers[ - message.command as keyof AutofillInlineMenuContainerWindowMessageHandlers - ](message); + if (this.windowMessageHandlers[message.command]) { + // only accept init messages from extension origin or parent window + if ( + (message.command === "initAutofillInlineMenuButton" || + message.command === "initAutofillInlineMenuList") && + !this.isMessageFromExtensionOrigin(event) && + !this.isMessageFromParentWindow(event) + ) { + return; + } + this.windowMessageHandlers[message.command](message); return; } if (this.isMessageFromParentWindow(event)) { + // messages from parent window are trusted and forwarded to iframe this.postMessageToInlineMenuPage(message); return; } - this.postMessageToBackground(message); + // messages from iframe to background require object identity verification with a contentWindow check and token auth + if (this.isMessageFromInlineMenuPageIframe(event)) { + if (this.isValidSessionToken(message)) { + this.postMessageToBackground(message); + } + return; + } }; /** @@ -184,10 +270,34 @@ export class AutofillInlineMenuContainer { if (!this.inlineMenuPageIframe) { return false; } + // only trust the specific iframe we created + return this.inlineMenuPageIframe.contentWindow === event.source; + } - return ( - this.inlineMenuPageIframe.contentWindow === event.source && - this.extensionOriginsSet.has(event.origin.toLowerCase()) - ); + /** + * Validates that the message contains a valid session token. + * The session token is generated when the container is created and is refreshed + * every time the inline menu container is recreated. + * + */ + private isValidSessionToken(message: { token?: string }): boolean { + return message.token === this.token; + } + + /** + * Validates that a message event originates from the extension. + * + * @param event - The message event to validate. + * @returns True if the message is from the extension origin. + */ + private isMessageFromExtensionOrigin(event: MessageEvent): boolean { + try { + if (event.origin === "null") { + return false; + } + return event.origin === this.extensionOrigin; + } catch { + return false; + } } } diff --git a/apps/browser/src/autofill/overlay/inline-menu/pages/shared/autofill-inline-menu-page-element.ts b/apps/browser/src/autofill/overlay/inline-menu/pages/shared/autofill-inline-menu-page-element.ts index 89f44a6a80..ea77e3e434 100644 --- a/apps/browser/src/autofill/overlay/inline-menu/pages/shared/autofill-inline-menu-page-element.ts +++ b/apps/browser/src/autofill/overlay/inline-menu/pages/shared/autofill-inline-menu-page-element.ts @@ -16,6 +16,7 @@ export class AutofillInlineMenuPageElement extends HTMLElement { private portKey!: string; /** Non-null asserted. */ protected windowMessageHandlers!: AutofillInlineMenuPageElementWindowMessageHandlers; + private token?: string; constructor() { super(); @@ -37,8 +38,12 @@ export class AutofillInlineMenuPageElement extends HTMLElement { styleSheetUrl: string, translations: Record, portKey: string, + token?: string, ): Promise { this.portKey = portKey; + if (token) { + this.token = token; + } this.translations = translations; globalThis.document.documentElement.setAttribute("lang", this.getTranslation("locale")); @@ -58,7 +63,11 @@ export class AutofillInlineMenuPageElement extends HTMLElement { * @param message - The message to post */ protected postMessageToParent(message: AutofillInlineMenuPageElementWindowMessage) { - globalThis.parent.postMessage({ portKey: this.portKey, ...message }, "*"); + const messageWithAuth: Record = { portKey: this.portKey, ...message }; + if (this.token) { + messageWithAuth.token = this.token; + } + globalThis.parent.postMessage(messageWithAuth, "*"); } /** @@ -105,6 +114,15 @@ export class AutofillInlineMenuPageElement extends HTMLElement { } const message = event?.data; + + if ( + message?.token && + (message?.command === "initAutofillInlineMenuButton" || + message?.command === "initAutofillInlineMenuList") + ) { + this.token = message.token; + } + const handler = this.windowMessageHandlers[message?.command]; if (!handler) { return; From fa563641b20bb0f66ac039d140510e1b6f2850b5 Mon Sep 17 00:00:00 2001 From: Vince Grassia <593223+vgrassia@users.noreply.github.com> Date: Tue, 18 Nov 2025 12:23:39 -0500 Subject: [PATCH 10/52] BRE-1355 - Rename Bitwarden Unified to Bitwarden Lite (#17456) --- .github/workflows/publish-web.yml | 11 +++++------ 1 file changed, 5 insertions(+), 6 deletions(-) diff --git a/.github/workflows/publish-web.yml b/.github/workflows/publish-web.yml index 6bf2b282b3..4f41898a9b 100644 --- a/.github/workflows/publish-web.yml +++ b/.github/workflows/publish-web.yml @@ -157,11 +157,10 @@ jobs: - name: Log out of Docker run: docker logout - self-host-unified-build: - name: Trigger self-host unified build + bitwarden-lite-build: + name: Trigger Bitwarden Lite build runs-on: ubuntu-22.04 - needs: - - setup + needs: setup permissions: id-token: write steps: @@ -182,7 +181,7 @@ jobs: - name: Log out from Azure uses: bitwarden/gh-actions/azure-logout@main - - name: Trigger self-host build + - name: Trigger Bitwarden Lite build uses: actions/github-script@ed597411d8f924073f98dfc5c65a23a2325f34cd # v8.0.0 with: github-token: ${{ steps.retrieve-secret-pat.outputs.github-pat-bitwarden-devops-bot-repo-scope }} @@ -190,7 +189,7 @@ jobs: await github.rest.actions.createWorkflowDispatch({ owner: 'bitwarden', repo: 'self-host', - workflow_id: 'build-unified.yml', + workflow_id: 'build-bitwarden-lite.yml', ref: 'main', inputs: { use_latest_core_version: true From 0d14060e9d2cd317aee2a4b07a93f16e742352ec Mon Sep 17 00:00:00 2001 From: "bw-ghapp[bot]" <178206702+bw-ghapp[bot]@users.noreply.github.com> Date: Tue, 18 Nov 2025 18:33:12 +0100 Subject: [PATCH 11/52] Autosync the updated translations (#17460) Co-authored-by: bitwarden-devops-bot <106330231+bitwarden-devops-bot@users.noreply.github.com> --- apps/desktop/src/locales/he/messages.json | 20 ++++++++++---------- apps/desktop/src/locales/sk/messages.json | 18 +++++++++--------- apps/desktop/src/locales/zh_CN/messages.json | 4 ++-- 3 files changed, 21 insertions(+), 21 deletions(-) diff --git a/apps/desktop/src/locales/he/messages.json b/apps/desktop/src/locales/he/messages.json index 87fac938a3..868cd9ccbc 100644 --- a/apps/desktop/src/locales/he/messages.json +++ b/apps/desktop/src/locales/he/messages.json @@ -4195,33 +4195,33 @@ "message": "מספר כרטיס" }, "upgradeNow": { - "message": "Upgrade now" + "message": "שדרג עכשיו" }, "builtInAuthenticator": { - "message": "Built-in authenticator" + "message": "מאמת מובנה" }, "secureFileStorage": { - "message": "Secure file storage" + "message": "אחסון קבצים מאובטח" }, "emergencyAccess": { - "message": "Emergency access" + "message": "גישת חירום" }, "breachMonitoring": { - "message": "Breach monitoring" + "message": "ניטור פרצות" }, "andMoreFeatures": { - "message": "And more!" + "message": "ועוד!" }, "planDescPremium": { - "message": "Complete online security" + "message": "השלם אבטחה מקוונת" }, "upgradeToPremium": { - "message": "Upgrade to Premium" + "message": "שדרג לפרימיום" }, "sessionTimeoutSettingsAction": { - "message": "Timeout action" + "message": "פעולת פסק זמן" }, "sessionTimeoutHeader": { - "message": "Session timeout" + "message": "פסק זמן להפעלה" } } diff --git a/apps/desktop/src/locales/sk/messages.json b/apps/desktop/src/locales/sk/messages.json index e5763d78b9..0b14b961bb 100644 --- a/apps/desktop/src/locales/sk/messages.json +++ b/apps/desktop/src/locales/sk/messages.json @@ -1692,7 +1692,7 @@ "description": "Default URI match detection for auto-fill." }, "toggleOptions": { - "message": "Voľby prepínača" + "message": "Zobraziť/skryť možnosti" }, "organization": { "message": "Organizácia", @@ -2425,7 +2425,7 @@ "message": "Hlavné heslo bolo úspešne nastavené" }, "updatedMasterPassword": { - "message": "Hlavné heslo aktualizované" + "message": "Hlavné heslo bolo aktualizované" }, "updateMasterPassword": { "message": "Aktualizovať hlavné heslo" @@ -2476,7 +2476,7 @@ "message": "Použiť PIN kód" }, "useBiometrics": { - "message": "Použiť biometrické údaje" + "message": "Použiť biometriu" }, "enterVerificationCodeSentToEmail": { "message": "Zadajte overovací kód, ktorý vám bol zaslaný na e-mail." @@ -2574,7 +2574,7 @@ "message": "Táto organizácia má podnikovú politiku, ktorá vás automaticky zaregistruje na obnovenie hesla. Registrácia umožní správcom organizácie zmeniť vaše hlavné heslo." }, "vaultExportDisabled": { - "message": "Export trezoru je zakázaný" + "message": "Export trezoru bol odstránený" }, "personalVaultExportPolicyInEffect": { "message": "Jedna alebo viacero zásad organizácie vám bráni exportovať váš osobný trezor." @@ -2619,7 +2619,7 @@ "message": "Predvoľby" }, "appPreferences": { - "message": "Nastavenia aplikácie (Všetky účty)" + "message": "Nastavenia aplikácie (všetky účty)" }, "accountSwitcherLimitReached": { "message": "Dosiahnutý limit počtu účtov. Odhláste sa z účtu aby ste mohli pridať ďalší." @@ -2790,7 +2790,7 @@ "message": "Použiť možnosti subadresovania svojho poskytovateľa e-mailu." }, "catchallEmail": { - "message": "Catch-all Email" + "message": "E-mail Catch-all" }, "catchallEmailDesc": { "message": "Použiť doručenú poštu typu catch-all nastavenú na doméne." @@ -2843,7 +2843,7 @@ "description": "Guidance provided for email forwarding services that support multiple email domains." }, "forwarderError": { - "message": "$SERVICENAME$ chyba: $ERRORMESSAGE$", + "message": "Chyba $SERVICENAME$: $ERRORMESSAGE$", "description": "Reports an error returned by a forwarding service to the user.", "placeholders": { "servicename": { @@ -2959,7 +2959,7 @@ } }, "forwarderUnknownForwarder": { - "message": "Nepodporovaná služba: '$SERVICENAME$'.", + "message": "Neznáme presmerovanie: '$SERVICENAME$'.", "description": "Displayed when the forwarding service is not supported.", "placeholders": { "servicename": { @@ -2976,7 +2976,7 @@ "message": "Prístupový token API" }, "apiKey": { - "message": "API kľúč" + "message": "Kľúč API" }, "premiumSubcriptionRequired": { "message": "Vyžaduje sa predplatné Prémium" diff --git a/apps/desktop/src/locales/zh_CN/messages.json b/apps/desktop/src/locales/zh_CN/messages.json index 353fc036f6..b5e68b83bd 100644 --- a/apps/desktop/src/locales/zh_CN/messages.json +++ b/apps/desktop/src/locales/zh_CN/messages.json @@ -1503,7 +1503,7 @@ "message": "优先客户支持。" }, "premiumSignUpFuture": { - "message": "所有未来的高级功能。即将推出!" + "message": "未来的更多高级版功能。敬请期待!" }, "premiumPurchase": { "message": "购买高级版" @@ -2029,7 +2029,7 @@ "message": "Bitwarden 可以存储并填充两步验证码。选择相机图标来拍摄此网站的验证器二维码,或将密钥复制并粘贴到此字段。" }, "premium": { - "message": "高级会员", + "message": "高级版", "description": "Premium membership" }, "freeOrgsCannotUseAttachments": { From bbb42d9b17a3fd4666b2b887993687b59c8a90da Mon Sep 17 00:00:00 2001 From: "bw-ghapp[bot]" <178206702+bw-ghapp[bot]@users.noreply.github.com> Date: Tue, 18 Nov 2025 18:36:24 +0100 Subject: [PATCH 12/52] Autosync the updated translations (#17461) Co-authored-by: bitwarden-devops-bot <106330231+bitwarden-devops-bot@users.noreply.github.com> --- apps/browser/src/_locales/ar/messages.json | 9 +++++ apps/browser/src/_locales/az/messages.json | 11 +++++- apps/browser/src/_locales/be/messages.json | 9 +++++ apps/browser/src/_locales/bg/messages.json | 11 +++++- apps/browser/src/_locales/bn/messages.json | 9 +++++ apps/browser/src/_locales/bs/messages.json | 9 +++++ apps/browser/src/_locales/ca/messages.json | 9 +++++ apps/browser/src/_locales/cs/messages.json | 9 +++++ apps/browser/src/_locales/cy/messages.json | 9 +++++ apps/browser/src/_locales/da/messages.json | 9 +++++ apps/browser/src/_locales/de/messages.json | 11 +++++- apps/browser/src/_locales/el/messages.json | 9 +++++ apps/browser/src/_locales/en_GB/messages.json | 9 +++++ apps/browser/src/_locales/en_IN/messages.json | 9 +++++ apps/browser/src/_locales/es/messages.json | 9 +++++ apps/browser/src/_locales/et/messages.json | 9 +++++ apps/browser/src/_locales/eu/messages.json | 9 +++++ apps/browser/src/_locales/fa/messages.json | 9 +++++ apps/browser/src/_locales/fi/messages.json | 9 +++++ apps/browser/src/_locales/fil/messages.json | 9 +++++ apps/browser/src/_locales/fr/messages.json | 9 +++++ apps/browser/src/_locales/gl/messages.json | 9 +++++ apps/browser/src/_locales/he/messages.json | 39 ++++++++++++------- apps/browser/src/_locales/hi/messages.json | 9 +++++ apps/browser/src/_locales/hr/messages.json | 9 +++++ apps/browser/src/_locales/hu/messages.json | 9 +++++ apps/browser/src/_locales/id/messages.json | 9 +++++ apps/browser/src/_locales/it/messages.json | 9 +++++ apps/browser/src/_locales/ja/messages.json | 9 +++++ apps/browser/src/_locales/ka/messages.json | 9 +++++ apps/browser/src/_locales/km/messages.json | 9 +++++ apps/browser/src/_locales/kn/messages.json | 9 +++++ apps/browser/src/_locales/ko/messages.json | 9 +++++ apps/browser/src/_locales/lt/messages.json | 9 +++++ apps/browser/src/_locales/lv/messages.json | 9 +++++ apps/browser/src/_locales/ml/messages.json | 9 +++++ apps/browser/src/_locales/mr/messages.json | 9 +++++ apps/browser/src/_locales/my/messages.json | 9 +++++ apps/browser/src/_locales/nb/messages.json | 9 +++++ apps/browser/src/_locales/ne/messages.json | 9 +++++ apps/browser/src/_locales/nl/messages.json | 9 +++++ apps/browser/src/_locales/nn/messages.json | 9 +++++ apps/browser/src/_locales/or/messages.json | 9 +++++ apps/browser/src/_locales/pl/messages.json | 9 +++++ apps/browser/src/_locales/pt_BR/messages.json | 9 +++++ apps/browser/src/_locales/pt_PT/messages.json | 9 +++++ apps/browser/src/_locales/ro/messages.json | 9 +++++ apps/browser/src/_locales/ru/messages.json | 9 +++++ apps/browser/src/_locales/si/messages.json | 9 +++++ apps/browser/src/_locales/sk/messages.json | 11 +++++- apps/browser/src/_locales/sl/messages.json | 9 +++++ apps/browser/src/_locales/sr/messages.json | 9 +++++ apps/browser/src/_locales/sv/messages.json | 11 +++++- apps/browser/src/_locales/ta/messages.json | 9 +++++ apps/browser/src/_locales/te/messages.json | 9 +++++ apps/browser/src/_locales/th/messages.json | 9 +++++ apps/browser/src/_locales/tr/messages.json | 11 +++++- apps/browser/src/_locales/uk/messages.json | 9 +++++ apps/browser/src/_locales/vi/messages.json | 9 +++++ apps/browser/src/_locales/zh_CN/messages.json | 15 +++++-- apps/browser/src/_locales/zh_TW/messages.json | 11 +++++- 61 files changed, 574 insertions(+), 25 deletions(-) diff --git a/apps/browser/src/_locales/ar/messages.json b/apps/browser/src/_locales/ar/messages.json index 79d54193b5..20eb31a545 100644 --- a/apps/browser/src/_locales/ar/messages.json +++ b/apps/browser/src/_locales/ar/messages.json @@ -5809,6 +5809,15 @@ "upgradeToPremium": { "message": "Upgrade to Premium" }, + "upgradeCompleteSecurity": { + "message": "Upgrade for complete security" + }, + "premiumGivesMoreTools": { + "message": "Premium gives you more tools to stay secure, work efficiently, and stay in control." + }, + "explorePremium": { + "message": "Explore Premium" + }, "loadingVault": { "message": "Loading vault" }, diff --git a/apps/browser/src/_locales/az/messages.json b/apps/browser/src/_locales/az/messages.json index b67d5ace0d..d8d8589f47 100644 --- a/apps/browser/src/_locales/az/messages.json +++ b/apps/browser/src/_locales/az/messages.json @@ -595,7 +595,7 @@ "message": "Hamısına bax" }, "viewLess": { - "message": "View less" + "message": "Daha azına bax" }, "viewLogin": { "message": "Girişə bax" @@ -5809,6 +5809,15 @@ "upgradeToPremium": { "message": "\"Premium\"a yüksəlt" }, + "upgradeCompleteSecurity": { + "message": "Upgrade for complete security" + }, + "premiumGivesMoreTools": { + "message": "Premium gives you more tools to stay secure, work efficiently, and stay in control." + }, + "explorePremium": { + "message": "Explore Premium" + }, "loadingVault": { "message": "Seyf yüklənir" }, diff --git a/apps/browser/src/_locales/be/messages.json b/apps/browser/src/_locales/be/messages.json index 450fb6e3df..47bafb7efe 100644 --- a/apps/browser/src/_locales/be/messages.json +++ b/apps/browser/src/_locales/be/messages.json @@ -5809,6 +5809,15 @@ "upgradeToPremium": { "message": "Upgrade to Premium" }, + "upgradeCompleteSecurity": { + "message": "Upgrade for complete security" + }, + "premiumGivesMoreTools": { + "message": "Premium gives you more tools to stay secure, work efficiently, and stay in control." + }, + "explorePremium": { + "message": "Explore Premium" + }, "loadingVault": { "message": "Loading vault" }, diff --git a/apps/browser/src/_locales/bg/messages.json b/apps/browser/src/_locales/bg/messages.json index 0a71e453c2..98da9bf033 100644 --- a/apps/browser/src/_locales/bg/messages.json +++ b/apps/browser/src/_locales/bg/messages.json @@ -595,7 +595,7 @@ "message": "Показване на всички" }, "viewLess": { - "message": "View less" + "message": "Преглед на по-малко" }, "viewLogin": { "message": "Преглед на елемента за вписване" @@ -5809,6 +5809,15 @@ "upgradeToPremium": { "message": "Надградете до Платения план" }, + "upgradeCompleteSecurity": { + "message": "Надградете, за да се възползвате от пълна защита" + }, + "premiumGivesMoreTools": { + "message": "Платеният план предоставя повече инструменти за защита, ефективна работа и контрол." + }, + "explorePremium": { + "message": "Разгледайте платения план" + }, "loadingVault": { "message": "Зареждане на трезора" }, diff --git a/apps/browser/src/_locales/bn/messages.json b/apps/browser/src/_locales/bn/messages.json index f43e3fdad2..794e380d01 100644 --- a/apps/browser/src/_locales/bn/messages.json +++ b/apps/browser/src/_locales/bn/messages.json @@ -5809,6 +5809,15 @@ "upgradeToPremium": { "message": "Upgrade to Premium" }, + "upgradeCompleteSecurity": { + "message": "Upgrade for complete security" + }, + "premiumGivesMoreTools": { + "message": "Premium gives you more tools to stay secure, work efficiently, and stay in control." + }, + "explorePremium": { + "message": "Explore Premium" + }, "loadingVault": { "message": "Loading vault" }, diff --git a/apps/browser/src/_locales/bs/messages.json b/apps/browser/src/_locales/bs/messages.json index 4fbcccd9aa..611cb4f5f5 100644 --- a/apps/browser/src/_locales/bs/messages.json +++ b/apps/browser/src/_locales/bs/messages.json @@ -5809,6 +5809,15 @@ "upgradeToPremium": { "message": "Upgrade to Premium" }, + "upgradeCompleteSecurity": { + "message": "Upgrade for complete security" + }, + "premiumGivesMoreTools": { + "message": "Premium gives you more tools to stay secure, work efficiently, and stay in control." + }, + "explorePremium": { + "message": "Explore Premium" + }, "loadingVault": { "message": "Loading vault" }, diff --git a/apps/browser/src/_locales/ca/messages.json b/apps/browser/src/_locales/ca/messages.json index 15a309fa8f..01611cc076 100644 --- a/apps/browser/src/_locales/ca/messages.json +++ b/apps/browser/src/_locales/ca/messages.json @@ -5809,6 +5809,15 @@ "upgradeToPremium": { "message": "Upgrade to Premium" }, + "upgradeCompleteSecurity": { + "message": "Upgrade for complete security" + }, + "premiumGivesMoreTools": { + "message": "Premium gives you more tools to stay secure, work efficiently, and stay in control." + }, + "explorePremium": { + "message": "Explore Premium" + }, "loadingVault": { "message": "Loading vault" }, diff --git a/apps/browser/src/_locales/cs/messages.json b/apps/browser/src/_locales/cs/messages.json index f9f572d87d..5c0c8fbf52 100644 --- a/apps/browser/src/_locales/cs/messages.json +++ b/apps/browser/src/_locales/cs/messages.json @@ -5809,6 +5809,15 @@ "upgradeToPremium": { "message": "Aktualizovat na Premium" }, + "upgradeCompleteSecurity": { + "message": "Aktualizujte pro úplné zabezpečení" + }, + "premiumGivesMoreTools": { + "message": "Verze Premium Vám poskytne více nástrojů k zabezpečení, efektivní práci a udržení kontroly." + }, + "explorePremium": { + "message": "Objevit Premium" + }, "loadingVault": { "message": "Načítání trezoru" }, diff --git a/apps/browser/src/_locales/cy/messages.json b/apps/browser/src/_locales/cy/messages.json index 33c68b338a..3bd81cc803 100644 --- a/apps/browser/src/_locales/cy/messages.json +++ b/apps/browser/src/_locales/cy/messages.json @@ -5809,6 +5809,15 @@ "upgradeToPremium": { "message": "Upgrade to Premium" }, + "upgradeCompleteSecurity": { + "message": "Upgrade for complete security" + }, + "premiumGivesMoreTools": { + "message": "Premium gives you more tools to stay secure, work efficiently, and stay in control." + }, + "explorePremium": { + "message": "Explore Premium" + }, "loadingVault": { "message": "Loading vault" }, diff --git a/apps/browser/src/_locales/da/messages.json b/apps/browser/src/_locales/da/messages.json index a599994569..9a12f808f2 100644 --- a/apps/browser/src/_locales/da/messages.json +++ b/apps/browser/src/_locales/da/messages.json @@ -5809,6 +5809,15 @@ "upgradeToPremium": { "message": "Upgrade to Premium" }, + "upgradeCompleteSecurity": { + "message": "Upgrade for complete security" + }, + "premiumGivesMoreTools": { + "message": "Premium gives you more tools to stay secure, work efficiently, and stay in control." + }, + "explorePremium": { + "message": "Explore Premium" + }, "loadingVault": { "message": "Loading vault" }, diff --git a/apps/browser/src/_locales/de/messages.json b/apps/browser/src/_locales/de/messages.json index b72cc2decb..517dc638af 100644 --- a/apps/browser/src/_locales/de/messages.json +++ b/apps/browser/src/_locales/de/messages.json @@ -595,7 +595,7 @@ "message": "Alles anzeigen" }, "viewLess": { - "message": "View less" + "message": "Weniger anzeigen" }, "viewLogin": { "message": "Zugangsdaten anzeigen" @@ -5809,6 +5809,15 @@ "upgradeToPremium": { "message": "Upgrade auf Premium" }, + "upgradeCompleteSecurity": { + "message": "Upgrade für umfassende Sicherheit" + }, + "premiumGivesMoreTools": { + "message": "Premium gives you more tools to stay secure, work efficiently, and stay in control." + }, + "explorePremium": { + "message": "Explore Premium" + }, "loadingVault": { "message": "Tresor wird geladen" }, diff --git a/apps/browser/src/_locales/el/messages.json b/apps/browser/src/_locales/el/messages.json index e0de7e5e9e..ae685fff65 100644 --- a/apps/browser/src/_locales/el/messages.json +++ b/apps/browser/src/_locales/el/messages.json @@ -5809,6 +5809,15 @@ "upgradeToPremium": { "message": "Upgrade to Premium" }, + "upgradeCompleteSecurity": { + "message": "Upgrade for complete security" + }, + "premiumGivesMoreTools": { + "message": "Premium gives you more tools to stay secure, work efficiently, and stay in control." + }, + "explorePremium": { + "message": "Explore Premium" + }, "loadingVault": { "message": "Loading vault" }, diff --git a/apps/browser/src/_locales/en_GB/messages.json b/apps/browser/src/_locales/en_GB/messages.json index a9c57e157e..5079e1e668 100644 --- a/apps/browser/src/_locales/en_GB/messages.json +++ b/apps/browser/src/_locales/en_GB/messages.json @@ -5809,6 +5809,15 @@ "upgradeToPremium": { "message": "Upgrade to Premium" }, + "upgradeCompleteSecurity": { + "message": "Upgrade for complete security" + }, + "premiumGivesMoreTools": { + "message": "Premium gives you more tools to stay secure, work efficiently, and stay in control." + }, + "explorePremium": { + "message": "Explore Premium" + }, "loadingVault": { "message": "Loading vault" }, diff --git a/apps/browser/src/_locales/en_IN/messages.json b/apps/browser/src/_locales/en_IN/messages.json index cd8c91f843..2a34400ea5 100644 --- a/apps/browser/src/_locales/en_IN/messages.json +++ b/apps/browser/src/_locales/en_IN/messages.json @@ -5809,6 +5809,15 @@ "upgradeToPremium": { "message": "Upgrade to Premium" }, + "upgradeCompleteSecurity": { + "message": "Upgrade for complete security" + }, + "premiumGivesMoreTools": { + "message": "Premium gives you more tools to stay secure, work efficiently, and stay in control." + }, + "explorePremium": { + "message": "Explore Premium" + }, "loadingVault": { "message": "Loading vault" }, diff --git a/apps/browser/src/_locales/es/messages.json b/apps/browser/src/_locales/es/messages.json index 470cf2ab35..8100fa8043 100644 --- a/apps/browser/src/_locales/es/messages.json +++ b/apps/browser/src/_locales/es/messages.json @@ -5809,6 +5809,15 @@ "upgradeToPremium": { "message": "Upgrade to Premium" }, + "upgradeCompleteSecurity": { + "message": "Upgrade for complete security" + }, + "premiumGivesMoreTools": { + "message": "Premium gives you more tools to stay secure, work efficiently, and stay in control." + }, + "explorePremium": { + "message": "Explore Premium" + }, "loadingVault": { "message": "Loading vault" }, diff --git a/apps/browser/src/_locales/et/messages.json b/apps/browser/src/_locales/et/messages.json index 9220d61e46..0f69561df5 100644 --- a/apps/browser/src/_locales/et/messages.json +++ b/apps/browser/src/_locales/et/messages.json @@ -5809,6 +5809,15 @@ "upgradeToPremium": { "message": "Upgrade to Premium" }, + "upgradeCompleteSecurity": { + "message": "Upgrade for complete security" + }, + "premiumGivesMoreTools": { + "message": "Premium gives you more tools to stay secure, work efficiently, and stay in control." + }, + "explorePremium": { + "message": "Explore Premium" + }, "loadingVault": { "message": "Loading vault" }, diff --git a/apps/browser/src/_locales/eu/messages.json b/apps/browser/src/_locales/eu/messages.json index c360bed28e..c60ce5e4da 100644 --- a/apps/browser/src/_locales/eu/messages.json +++ b/apps/browser/src/_locales/eu/messages.json @@ -5809,6 +5809,15 @@ "upgradeToPremium": { "message": "Upgrade to Premium" }, + "upgradeCompleteSecurity": { + "message": "Upgrade for complete security" + }, + "premiumGivesMoreTools": { + "message": "Premium gives you more tools to stay secure, work efficiently, and stay in control." + }, + "explorePremium": { + "message": "Explore Premium" + }, "loadingVault": { "message": "Loading vault" }, diff --git a/apps/browser/src/_locales/fa/messages.json b/apps/browser/src/_locales/fa/messages.json index 774a02f50d..5a03f8427f 100644 --- a/apps/browser/src/_locales/fa/messages.json +++ b/apps/browser/src/_locales/fa/messages.json @@ -5809,6 +5809,15 @@ "upgradeToPremium": { "message": "Upgrade to Premium" }, + "upgradeCompleteSecurity": { + "message": "Upgrade for complete security" + }, + "premiumGivesMoreTools": { + "message": "Premium gives you more tools to stay secure, work efficiently, and stay in control." + }, + "explorePremium": { + "message": "Explore Premium" + }, "loadingVault": { "message": "Loading vault" }, diff --git a/apps/browser/src/_locales/fi/messages.json b/apps/browser/src/_locales/fi/messages.json index 8766632a91..db4649c33a 100644 --- a/apps/browser/src/_locales/fi/messages.json +++ b/apps/browser/src/_locales/fi/messages.json @@ -5809,6 +5809,15 @@ "upgradeToPremium": { "message": "Upgrade to Premium" }, + "upgradeCompleteSecurity": { + "message": "Upgrade for complete security" + }, + "premiumGivesMoreTools": { + "message": "Premium gives you more tools to stay secure, work efficiently, and stay in control." + }, + "explorePremium": { + "message": "Explore Premium" + }, "loadingVault": { "message": "Loading vault" }, diff --git a/apps/browser/src/_locales/fil/messages.json b/apps/browser/src/_locales/fil/messages.json index 6c7154a1ba..6239e9d4f9 100644 --- a/apps/browser/src/_locales/fil/messages.json +++ b/apps/browser/src/_locales/fil/messages.json @@ -5809,6 +5809,15 @@ "upgradeToPremium": { "message": "Upgrade to Premium" }, + "upgradeCompleteSecurity": { + "message": "Upgrade for complete security" + }, + "premiumGivesMoreTools": { + "message": "Premium gives you more tools to stay secure, work efficiently, and stay in control." + }, + "explorePremium": { + "message": "Explore Premium" + }, "loadingVault": { "message": "Loading vault" }, diff --git a/apps/browser/src/_locales/fr/messages.json b/apps/browser/src/_locales/fr/messages.json index 0e701750c5..1cc04809a1 100644 --- a/apps/browser/src/_locales/fr/messages.json +++ b/apps/browser/src/_locales/fr/messages.json @@ -5809,6 +5809,15 @@ "upgradeToPremium": { "message": "Upgrade to Premium" }, + "upgradeCompleteSecurity": { + "message": "Upgrade for complete security" + }, + "premiumGivesMoreTools": { + "message": "Premium gives you more tools to stay secure, work efficiently, and stay in control." + }, + "explorePremium": { + "message": "Explore Premium" + }, "loadingVault": { "message": "Loading vault" }, diff --git a/apps/browser/src/_locales/gl/messages.json b/apps/browser/src/_locales/gl/messages.json index c61325ef8d..090bc6b149 100644 --- a/apps/browser/src/_locales/gl/messages.json +++ b/apps/browser/src/_locales/gl/messages.json @@ -5809,6 +5809,15 @@ "upgradeToPremium": { "message": "Upgrade to Premium" }, + "upgradeCompleteSecurity": { + "message": "Upgrade for complete security" + }, + "premiumGivesMoreTools": { + "message": "Premium gives you more tools to stay secure, work efficiently, and stay in control." + }, + "explorePremium": { + "message": "Explore Premium" + }, "loadingVault": { "message": "Loading vault" }, diff --git a/apps/browser/src/_locales/he/messages.json b/apps/browser/src/_locales/he/messages.json index 81ac1e176f..2934d34560 100644 --- a/apps/browser/src/_locales/he/messages.json +++ b/apps/browser/src/_locales/he/messages.json @@ -595,7 +595,7 @@ "message": "הצג הכל" }, "viewLess": { - "message": "View less" + "message": "הצג פחות" }, "viewLogin": { "message": "הצג כניסה" @@ -800,10 +800,10 @@ "message": "בנעילת המערכת" }, "onIdle": { - "message": "On system idle" + "message": "כשהמערכת מזהה חוסר פעילות" }, "onSleep": { - "message": "On system sleep" + "message": "כשהמערכת נכנסת למצב שינה" }, "onRestart": { "message": "בהפעלת הדפדפן מחדש" @@ -4984,7 +4984,7 @@ } }, "defaultLabelWithValue": { - "message": "Default ( $VALUE$ )", + "message": "ברירת מחדל ( $VALUE$ )", "description": "A label that indicates the default value for a field with the current default value in parentheses.", "placeholders": { "value": { @@ -5786,34 +5786,43 @@ "message": "עבודה נהדרת באבטחת הכניסות בסיכון שלך!" }, "upgradeNow": { - "message": "Upgrade now" + "message": "שדרג עכשיו" }, "builtInAuthenticator": { - "message": "Built-in authenticator" + "message": "מאמת מובנה" }, "secureFileStorage": { - "message": "Secure file storage" + "message": "אחסון קבצים מאובטח" }, "emergencyAccess": { - "message": "Emergency access" + "message": "גישת חירום" }, "breachMonitoring": { - "message": "Breach monitoring" + "message": "ניטור פרצות" }, "andMoreFeatures": { - "message": "And more!" + "message": "ועוד!" }, "planDescPremium": { - "message": "Complete online security" + "message": "השלם אבטחה מקוונת" }, "upgradeToPremium": { - "message": "Upgrade to Premium" + "message": "שדרג לפרימיום" + }, + "upgradeCompleteSecurity": { + "message": "Upgrade for complete security" + }, + "premiumGivesMoreTools": { + "message": "Premium gives you more tools to stay secure, work efficiently, and stay in control." + }, + "explorePremium": { + "message": "Explore Premium" }, "loadingVault": { - "message": "Loading vault" + "message": "טוען כספת" }, "vaultLoaded": { - "message": "Vault loaded" + "message": "הכספת נטענה" }, "settingDisabledByPolicy": { "message": "הגדרה זו מושבתת על ידי מדיניות של הארגון שלך.", @@ -5826,6 +5835,6 @@ "message": "מספר כרטיס" }, "sessionTimeoutSettingsAction": { - "message": "Timeout action" + "message": "פעולת פסק זמן" } } diff --git a/apps/browser/src/_locales/hi/messages.json b/apps/browser/src/_locales/hi/messages.json index ff24818f82..75011ebf8e 100644 --- a/apps/browser/src/_locales/hi/messages.json +++ b/apps/browser/src/_locales/hi/messages.json @@ -5809,6 +5809,15 @@ "upgradeToPremium": { "message": "Upgrade to Premium" }, + "upgradeCompleteSecurity": { + "message": "Upgrade for complete security" + }, + "premiumGivesMoreTools": { + "message": "Premium gives you more tools to stay secure, work efficiently, and stay in control." + }, + "explorePremium": { + "message": "Explore Premium" + }, "loadingVault": { "message": "Loading vault" }, diff --git a/apps/browser/src/_locales/hr/messages.json b/apps/browser/src/_locales/hr/messages.json index 052fae3368..fb89e8940e 100644 --- a/apps/browser/src/_locales/hr/messages.json +++ b/apps/browser/src/_locales/hr/messages.json @@ -5809,6 +5809,15 @@ "upgradeToPremium": { "message": " Nadogradi na Premium" }, + "upgradeCompleteSecurity": { + "message": "Upgrade for complete security" + }, + "premiumGivesMoreTools": { + "message": "Premium gives you more tools to stay secure, work efficiently, and stay in control." + }, + "explorePremium": { + "message": "Explore Premium" + }, "loadingVault": { "message": "Učitavanje trezora" }, diff --git a/apps/browser/src/_locales/hu/messages.json b/apps/browser/src/_locales/hu/messages.json index fb94c4f466..f9a2f9ff00 100644 --- a/apps/browser/src/_locales/hu/messages.json +++ b/apps/browser/src/_locales/hu/messages.json @@ -5809,6 +5809,15 @@ "upgradeToPremium": { "message": "Áttérés Prémium csomagra" }, + "upgradeCompleteSecurity": { + "message": "Áttérés a teljes biztonságért" + }, + "premiumGivesMoreTools": { + "message": "A Premium több eszközt ad a biztonság megőrzéséhez, a hatékony munkavégzéshez és az irányítás megőrzéséhez." + }, + "explorePremium": { + "message": "Premium felfedezése" + }, "loadingVault": { "message": "Széf betöltése" }, diff --git a/apps/browser/src/_locales/id/messages.json b/apps/browser/src/_locales/id/messages.json index 1cb7980492..a88e3cc2d3 100644 --- a/apps/browser/src/_locales/id/messages.json +++ b/apps/browser/src/_locales/id/messages.json @@ -5809,6 +5809,15 @@ "upgradeToPremium": { "message": "Upgrade to Premium" }, + "upgradeCompleteSecurity": { + "message": "Upgrade for complete security" + }, + "premiumGivesMoreTools": { + "message": "Premium gives you more tools to stay secure, work efficiently, and stay in control." + }, + "explorePremium": { + "message": "Explore Premium" + }, "loadingVault": { "message": "Loading vault" }, diff --git a/apps/browser/src/_locales/it/messages.json b/apps/browser/src/_locales/it/messages.json index dc69cb13cb..f0e63d99ec 100644 --- a/apps/browser/src/_locales/it/messages.json +++ b/apps/browser/src/_locales/it/messages.json @@ -5809,6 +5809,15 @@ "upgradeToPremium": { "message": "Upgrade to Premium" }, + "upgradeCompleteSecurity": { + "message": "Upgrade for complete security" + }, + "premiumGivesMoreTools": { + "message": "Premium gives you more tools to stay secure, work efficiently, and stay in control." + }, + "explorePremium": { + "message": "Explore Premium" + }, "loadingVault": { "message": "Loading vault" }, diff --git a/apps/browser/src/_locales/ja/messages.json b/apps/browser/src/_locales/ja/messages.json index 8b3b0e2cc6..98ac152a08 100644 --- a/apps/browser/src/_locales/ja/messages.json +++ b/apps/browser/src/_locales/ja/messages.json @@ -5809,6 +5809,15 @@ "upgradeToPremium": { "message": "プレミアムにアップグレード" }, + "upgradeCompleteSecurity": { + "message": "Upgrade for complete security" + }, + "premiumGivesMoreTools": { + "message": "Premium gives you more tools to stay secure, work efficiently, and stay in control." + }, + "explorePremium": { + "message": "Explore Premium" + }, "loadingVault": { "message": "Loading vault" }, diff --git a/apps/browser/src/_locales/ka/messages.json b/apps/browser/src/_locales/ka/messages.json index 5c7a8da23a..e6e8becd50 100644 --- a/apps/browser/src/_locales/ka/messages.json +++ b/apps/browser/src/_locales/ka/messages.json @@ -5809,6 +5809,15 @@ "upgradeToPremium": { "message": "Upgrade to Premium" }, + "upgradeCompleteSecurity": { + "message": "Upgrade for complete security" + }, + "premiumGivesMoreTools": { + "message": "Premium gives you more tools to stay secure, work efficiently, and stay in control." + }, + "explorePremium": { + "message": "Explore Premium" + }, "loadingVault": { "message": "Loading vault" }, diff --git a/apps/browser/src/_locales/km/messages.json b/apps/browser/src/_locales/km/messages.json index 13e74f8d80..cb1a5c089f 100644 --- a/apps/browser/src/_locales/km/messages.json +++ b/apps/browser/src/_locales/km/messages.json @@ -5809,6 +5809,15 @@ "upgradeToPremium": { "message": "Upgrade to Premium" }, + "upgradeCompleteSecurity": { + "message": "Upgrade for complete security" + }, + "premiumGivesMoreTools": { + "message": "Premium gives you more tools to stay secure, work efficiently, and stay in control." + }, + "explorePremium": { + "message": "Explore Premium" + }, "loadingVault": { "message": "Loading vault" }, diff --git a/apps/browser/src/_locales/kn/messages.json b/apps/browser/src/_locales/kn/messages.json index 3e929bc653..c83d63762d 100644 --- a/apps/browser/src/_locales/kn/messages.json +++ b/apps/browser/src/_locales/kn/messages.json @@ -5809,6 +5809,15 @@ "upgradeToPremium": { "message": "Upgrade to Premium" }, + "upgradeCompleteSecurity": { + "message": "Upgrade for complete security" + }, + "premiumGivesMoreTools": { + "message": "Premium gives you more tools to stay secure, work efficiently, and stay in control." + }, + "explorePremium": { + "message": "Explore Premium" + }, "loadingVault": { "message": "Loading vault" }, diff --git a/apps/browser/src/_locales/ko/messages.json b/apps/browser/src/_locales/ko/messages.json index 5a21928c23..50f49833d5 100644 --- a/apps/browser/src/_locales/ko/messages.json +++ b/apps/browser/src/_locales/ko/messages.json @@ -5809,6 +5809,15 @@ "upgradeToPremium": { "message": "Upgrade to Premium" }, + "upgradeCompleteSecurity": { + "message": "Upgrade for complete security" + }, + "premiumGivesMoreTools": { + "message": "Premium gives you more tools to stay secure, work efficiently, and stay in control." + }, + "explorePremium": { + "message": "Explore Premium" + }, "loadingVault": { "message": "Loading vault" }, diff --git a/apps/browser/src/_locales/lt/messages.json b/apps/browser/src/_locales/lt/messages.json index ac598394a8..21cd9ca401 100644 --- a/apps/browser/src/_locales/lt/messages.json +++ b/apps/browser/src/_locales/lt/messages.json @@ -5809,6 +5809,15 @@ "upgradeToPremium": { "message": "Upgrade to Premium" }, + "upgradeCompleteSecurity": { + "message": "Upgrade for complete security" + }, + "premiumGivesMoreTools": { + "message": "Premium gives you more tools to stay secure, work efficiently, and stay in control." + }, + "explorePremium": { + "message": "Explore Premium" + }, "loadingVault": { "message": "Loading vault" }, diff --git a/apps/browser/src/_locales/lv/messages.json b/apps/browser/src/_locales/lv/messages.json index 70f46e0f06..088d671a2b 100644 --- a/apps/browser/src/_locales/lv/messages.json +++ b/apps/browser/src/_locales/lv/messages.json @@ -5809,6 +5809,15 @@ "upgradeToPremium": { "message": "Uzlabot uz Premium" }, + "upgradeCompleteSecurity": { + "message": "Upgrade for complete security" + }, + "premiumGivesMoreTools": { + "message": "Premium gives you more tools to stay secure, work efficiently, and stay in control." + }, + "explorePremium": { + "message": "Explore Premium" + }, "loadingVault": { "message": "Ielādē glabātavu" }, diff --git a/apps/browser/src/_locales/ml/messages.json b/apps/browser/src/_locales/ml/messages.json index d139531315..d76f579fac 100644 --- a/apps/browser/src/_locales/ml/messages.json +++ b/apps/browser/src/_locales/ml/messages.json @@ -5809,6 +5809,15 @@ "upgradeToPremium": { "message": "Upgrade to Premium" }, + "upgradeCompleteSecurity": { + "message": "Upgrade for complete security" + }, + "premiumGivesMoreTools": { + "message": "Premium gives you more tools to stay secure, work efficiently, and stay in control." + }, + "explorePremium": { + "message": "Explore Premium" + }, "loadingVault": { "message": "Loading vault" }, diff --git a/apps/browser/src/_locales/mr/messages.json b/apps/browser/src/_locales/mr/messages.json index 438cc75055..acbbc97cea 100644 --- a/apps/browser/src/_locales/mr/messages.json +++ b/apps/browser/src/_locales/mr/messages.json @@ -5809,6 +5809,15 @@ "upgradeToPremium": { "message": "Upgrade to Premium" }, + "upgradeCompleteSecurity": { + "message": "Upgrade for complete security" + }, + "premiumGivesMoreTools": { + "message": "Premium gives you more tools to stay secure, work efficiently, and stay in control." + }, + "explorePremium": { + "message": "Explore Premium" + }, "loadingVault": { "message": "Loading vault" }, diff --git a/apps/browser/src/_locales/my/messages.json b/apps/browser/src/_locales/my/messages.json index 13e74f8d80..cb1a5c089f 100644 --- a/apps/browser/src/_locales/my/messages.json +++ b/apps/browser/src/_locales/my/messages.json @@ -5809,6 +5809,15 @@ "upgradeToPremium": { "message": "Upgrade to Premium" }, + "upgradeCompleteSecurity": { + "message": "Upgrade for complete security" + }, + "premiumGivesMoreTools": { + "message": "Premium gives you more tools to stay secure, work efficiently, and stay in control." + }, + "explorePremium": { + "message": "Explore Premium" + }, "loadingVault": { "message": "Loading vault" }, diff --git a/apps/browser/src/_locales/nb/messages.json b/apps/browser/src/_locales/nb/messages.json index 4ae8a01a12..3933f66c54 100644 --- a/apps/browser/src/_locales/nb/messages.json +++ b/apps/browser/src/_locales/nb/messages.json @@ -5809,6 +5809,15 @@ "upgradeToPremium": { "message": "Upgrade to Premium" }, + "upgradeCompleteSecurity": { + "message": "Upgrade for complete security" + }, + "premiumGivesMoreTools": { + "message": "Premium gives you more tools to stay secure, work efficiently, and stay in control." + }, + "explorePremium": { + "message": "Explore Premium" + }, "loadingVault": { "message": "Loading vault" }, diff --git a/apps/browser/src/_locales/ne/messages.json b/apps/browser/src/_locales/ne/messages.json index 13e74f8d80..cb1a5c089f 100644 --- a/apps/browser/src/_locales/ne/messages.json +++ b/apps/browser/src/_locales/ne/messages.json @@ -5809,6 +5809,15 @@ "upgradeToPremium": { "message": "Upgrade to Premium" }, + "upgradeCompleteSecurity": { + "message": "Upgrade for complete security" + }, + "premiumGivesMoreTools": { + "message": "Premium gives you more tools to stay secure, work efficiently, and stay in control." + }, + "explorePremium": { + "message": "Explore Premium" + }, "loadingVault": { "message": "Loading vault" }, diff --git a/apps/browser/src/_locales/nl/messages.json b/apps/browser/src/_locales/nl/messages.json index b3463c9f1b..a4d38f6c9b 100644 --- a/apps/browser/src/_locales/nl/messages.json +++ b/apps/browser/src/_locales/nl/messages.json @@ -5809,6 +5809,15 @@ "upgradeToPremium": { "message": "Opwaarderen naar Premium" }, + "upgradeCompleteSecurity": { + "message": "Upgrade voor volledige beveiliging" + }, + "premiumGivesMoreTools": { + "message": "Premium geeft je meer tools om veilig te blijven, efficiënt te werken en in controle te blijven." + }, + "explorePremium": { + "message": "Premium verkennen" + }, "loadingVault": { "message": "Kluis laden" }, diff --git a/apps/browser/src/_locales/nn/messages.json b/apps/browser/src/_locales/nn/messages.json index 13e74f8d80..cb1a5c089f 100644 --- a/apps/browser/src/_locales/nn/messages.json +++ b/apps/browser/src/_locales/nn/messages.json @@ -5809,6 +5809,15 @@ "upgradeToPremium": { "message": "Upgrade to Premium" }, + "upgradeCompleteSecurity": { + "message": "Upgrade for complete security" + }, + "premiumGivesMoreTools": { + "message": "Premium gives you more tools to stay secure, work efficiently, and stay in control." + }, + "explorePremium": { + "message": "Explore Premium" + }, "loadingVault": { "message": "Loading vault" }, diff --git a/apps/browser/src/_locales/or/messages.json b/apps/browser/src/_locales/or/messages.json index 13e74f8d80..cb1a5c089f 100644 --- a/apps/browser/src/_locales/or/messages.json +++ b/apps/browser/src/_locales/or/messages.json @@ -5809,6 +5809,15 @@ "upgradeToPremium": { "message": "Upgrade to Premium" }, + "upgradeCompleteSecurity": { + "message": "Upgrade for complete security" + }, + "premiumGivesMoreTools": { + "message": "Premium gives you more tools to stay secure, work efficiently, and stay in control." + }, + "explorePremium": { + "message": "Explore Premium" + }, "loadingVault": { "message": "Loading vault" }, diff --git a/apps/browser/src/_locales/pl/messages.json b/apps/browser/src/_locales/pl/messages.json index 77b6cc436d..0847126f33 100644 --- a/apps/browser/src/_locales/pl/messages.json +++ b/apps/browser/src/_locales/pl/messages.json @@ -5809,6 +5809,15 @@ "upgradeToPremium": { "message": "Upgrade to Premium" }, + "upgradeCompleteSecurity": { + "message": "Upgrade for complete security" + }, + "premiumGivesMoreTools": { + "message": "Premium gives you more tools to stay secure, work efficiently, and stay in control." + }, + "explorePremium": { + "message": "Explore Premium" + }, "loadingVault": { "message": "Loading vault" }, diff --git a/apps/browser/src/_locales/pt_BR/messages.json b/apps/browser/src/_locales/pt_BR/messages.json index c3d9614594..dbd7229db2 100644 --- a/apps/browser/src/_locales/pt_BR/messages.json +++ b/apps/browser/src/_locales/pt_BR/messages.json @@ -5809,6 +5809,15 @@ "upgradeToPremium": { "message": "Faça upgrade para o Premium" }, + "upgradeCompleteSecurity": { + "message": "Faça upgrade para segurança completa" + }, + "premiumGivesMoreTools": { + "message": "O Premium te oferece mais ferramentas para se permanecer seguro, trabalhar eficientemente, e manter o controle." + }, + "explorePremium": { + "message": "Explorar o Premium" + }, "loadingVault": { "message": "Carregando cofre" }, diff --git a/apps/browser/src/_locales/pt_PT/messages.json b/apps/browser/src/_locales/pt_PT/messages.json index 10fbc3db00..55065838ec 100644 --- a/apps/browser/src/_locales/pt_PT/messages.json +++ b/apps/browser/src/_locales/pt_PT/messages.json @@ -5809,6 +5809,15 @@ "upgradeToPremium": { "message": "Atualizar para o Premium" }, + "upgradeCompleteSecurity": { + "message": "Atualize para obter segurança total" + }, + "premiumGivesMoreTools": { + "message": "O Premium oferece mais ferramentas para manter a segurança, trabalhar com eficiência e manter o controlo." + }, + "explorePremium": { + "message": "Explorar o Premium" + }, "loadingVault": { "message": "A carregar o cofre" }, diff --git a/apps/browser/src/_locales/ro/messages.json b/apps/browser/src/_locales/ro/messages.json index 5fe7c61f9c..84a1937bf1 100644 --- a/apps/browser/src/_locales/ro/messages.json +++ b/apps/browser/src/_locales/ro/messages.json @@ -5809,6 +5809,15 @@ "upgradeToPremium": { "message": "Upgrade to Premium" }, + "upgradeCompleteSecurity": { + "message": "Upgrade for complete security" + }, + "premiumGivesMoreTools": { + "message": "Premium gives you more tools to stay secure, work efficiently, and stay in control." + }, + "explorePremium": { + "message": "Explore Premium" + }, "loadingVault": { "message": "Loading vault" }, diff --git a/apps/browser/src/_locales/ru/messages.json b/apps/browser/src/_locales/ru/messages.json index 349e68c519..22e9052fe4 100644 --- a/apps/browser/src/_locales/ru/messages.json +++ b/apps/browser/src/_locales/ru/messages.json @@ -5809,6 +5809,15 @@ "upgradeToPremium": { "message": "Обновить до Премиум" }, + "upgradeCompleteSecurity": { + "message": "Перейти для полной защищенности" + }, + "premiumGivesMoreTools": { + "message": "Премиум предоставит вам больше инструментов для обеспечения безопасности, эффективной работы и контроля над ситуацией." + }, + "explorePremium": { + "message": "Познакомиться с Премиум" + }, "loadingVault": { "message": "Загрузка хранилища" }, diff --git a/apps/browser/src/_locales/si/messages.json b/apps/browser/src/_locales/si/messages.json index 9b36684dc5..f4c00449a2 100644 --- a/apps/browser/src/_locales/si/messages.json +++ b/apps/browser/src/_locales/si/messages.json @@ -5809,6 +5809,15 @@ "upgradeToPremium": { "message": "Upgrade to Premium" }, + "upgradeCompleteSecurity": { + "message": "Upgrade for complete security" + }, + "premiumGivesMoreTools": { + "message": "Premium gives you more tools to stay secure, work efficiently, and stay in control." + }, + "explorePremium": { + "message": "Explore Premium" + }, "loadingVault": { "message": "Loading vault" }, diff --git a/apps/browser/src/_locales/sk/messages.json b/apps/browser/src/_locales/sk/messages.json index a269756a41..b8b820def3 100644 --- a/apps/browser/src/_locales/sk/messages.json +++ b/apps/browser/src/_locales/sk/messages.json @@ -2195,7 +2195,7 @@ "description": "Default URI match detection for autofill." }, "toggleOptions": { - "message": "Voľby prepínača" + "message": "Zobraziť/skryť možnosti" }, "toggleCurrentUris": { "message": "Prepnúť zobrazenie aktuálnej URI", @@ -5809,6 +5809,15 @@ "upgradeToPremium": { "message": "Upgradovať na Prémium" }, + "upgradeCompleteSecurity": { + "message": "Upgradovať pre úplné zabezpečenie" + }, + "premiumGivesMoreTools": { + "message": "Predplatné Prémium vám poskytuje viac nástrojov na zabezpečenie, efektívnu prácu a kontrolu." + }, + "explorePremium": { + "message": "Preskúmať Prémium" + }, "loadingVault": { "message": "Načítava sa trezor" }, diff --git a/apps/browser/src/_locales/sl/messages.json b/apps/browser/src/_locales/sl/messages.json index 3cbd9a1134..70d9c5f70c 100644 --- a/apps/browser/src/_locales/sl/messages.json +++ b/apps/browser/src/_locales/sl/messages.json @@ -5809,6 +5809,15 @@ "upgradeToPremium": { "message": "Upgrade to Premium" }, + "upgradeCompleteSecurity": { + "message": "Upgrade for complete security" + }, + "premiumGivesMoreTools": { + "message": "Premium gives you more tools to stay secure, work efficiently, and stay in control." + }, + "explorePremium": { + "message": "Explore Premium" + }, "loadingVault": { "message": "Loading vault" }, diff --git a/apps/browser/src/_locales/sr/messages.json b/apps/browser/src/_locales/sr/messages.json index d13939f865..97fcb37fb5 100644 --- a/apps/browser/src/_locales/sr/messages.json +++ b/apps/browser/src/_locales/sr/messages.json @@ -5809,6 +5809,15 @@ "upgradeToPremium": { "message": "Надоградите на Premium" }, + "upgradeCompleteSecurity": { + "message": "Upgrade for complete security" + }, + "premiumGivesMoreTools": { + "message": "Premium gives you more tools to stay secure, work efficiently, and stay in control." + }, + "explorePremium": { + "message": "Explore Premium" + }, "loadingVault": { "message": "Loading vault" }, diff --git a/apps/browser/src/_locales/sv/messages.json b/apps/browser/src/_locales/sv/messages.json index 9f84e9d714..ea7a4d8035 100644 --- a/apps/browser/src/_locales/sv/messages.json +++ b/apps/browser/src/_locales/sv/messages.json @@ -595,7 +595,7 @@ "message": "Visa alla" }, "viewLess": { - "message": "View less" + "message": "Visa mindre" }, "viewLogin": { "message": "Visa inloggning" @@ -5809,6 +5809,15 @@ "upgradeToPremium": { "message": "Uppgradera till Premium" }, + "upgradeCompleteSecurity": { + "message": "Uppgradera för fullständig säkerhet" + }, + "premiumGivesMoreTools": { + "message": "Premium ger dig fler verktyg för att hålla dig säker, arbeta effektivt och ha kontroll." + }, + "explorePremium": { + "message": "Utforska Premium" + }, "loadingVault": { "message": "Läser in valv" }, diff --git a/apps/browser/src/_locales/ta/messages.json b/apps/browser/src/_locales/ta/messages.json index cbefd26424..a95da4d205 100644 --- a/apps/browser/src/_locales/ta/messages.json +++ b/apps/browser/src/_locales/ta/messages.json @@ -5809,6 +5809,15 @@ "upgradeToPremium": { "message": "Upgrade to Premium" }, + "upgradeCompleteSecurity": { + "message": "Upgrade for complete security" + }, + "premiumGivesMoreTools": { + "message": "Premium gives you more tools to stay secure, work efficiently, and stay in control." + }, + "explorePremium": { + "message": "Explore Premium" + }, "loadingVault": { "message": "Loading vault" }, diff --git a/apps/browser/src/_locales/te/messages.json b/apps/browser/src/_locales/te/messages.json index 13e74f8d80..cb1a5c089f 100644 --- a/apps/browser/src/_locales/te/messages.json +++ b/apps/browser/src/_locales/te/messages.json @@ -5809,6 +5809,15 @@ "upgradeToPremium": { "message": "Upgrade to Premium" }, + "upgradeCompleteSecurity": { + "message": "Upgrade for complete security" + }, + "premiumGivesMoreTools": { + "message": "Premium gives you more tools to stay secure, work efficiently, and stay in control." + }, + "explorePremium": { + "message": "Explore Premium" + }, "loadingVault": { "message": "Loading vault" }, diff --git a/apps/browser/src/_locales/th/messages.json b/apps/browser/src/_locales/th/messages.json index 594bc6d7a9..9096067ce3 100644 --- a/apps/browser/src/_locales/th/messages.json +++ b/apps/browser/src/_locales/th/messages.json @@ -5809,6 +5809,15 @@ "upgradeToPremium": { "message": "Upgrade to Premium" }, + "upgradeCompleteSecurity": { + "message": "Upgrade for complete security" + }, + "premiumGivesMoreTools": { + "message": "Premium gives you more tools to stay secure, work efficiently, and stay in control." + }, + "explorePremium": { + "message": "Explore Premium" + }, "loadingVault": { "message": "Loading vault" }, diff --git a/apps/browser/src/_locales/tr/messages.json b/apps/browser/src/_locales/tr/messages.json index 7f234b8750..4c7ca6937a 100644 --- a/apps/browser/src/_locales/tr/messages.json +++ b/apps/browser/src/_locales/tr/messages.json @@ -595,7 +595,7 @@ "message": "Tümünü göster" }, "viewLess": { - "message": "View less" + "message": "Daha az göster" }, "viewLogin": { "message": "Hesabı göster" @@ -5809,6 +5809,15 @@ "upgradeToPremium": { "message": "Premium'a yükselt" }, + "upgradeCompleteSecurity": { + "message": "Upgrade for complete security" + }, + "premiumGivesMoreTools": { + "message": "Premium gives you more tools to stay secure, work efficiently, and stay in control." + }, + "explorePremium": { + "message": "Explore Premium" + }, "loadingVault": { "message": "Kasa yükleniyor" }, diff --git a/apps/browser/src/_locales/uk/messages.json b/apps/browser/src/_locales/uk/messages.json index a17033ee6e..7f8b0f8b13 100644 --- a/apps/browser/src/_locales/uk/messages.json +++ b/apps/browser/src/_locales/uk/messages.json @@ -5809,6 +5809,15 @@ "upgradeToPremium": { "message": "Покращити до Premium" }, + "upgradeCompleteSecurity": { + "message": "Upgrade for complete security" + }, + "premiumGivesMoreTools": { + "message": "Premium gives you more tools to stay secure, work efficiently, and stay in control." + }, + "explorePremium": { + "message": "Explore Premium" + }, "loadingVault": { "message": "Loading vault" }, diff --git a/apps/browser/src/_locales/vi/messages.json b/apps/browser/src/_locales/vi/messages.json index 2fdba62ade..414b4cc2ca 100644 --- a/apps/browser/src/_locales/vi/messages.json +++ b/apps/browser/src/_locales/vi/messages.json @@ -5809,6 +5809,15 @@ "upgradeToPremium": { "message": "Nâng cấp lên gói Cao cấp" }, + "upgradeCompleteSecurity": { + "message": "Upgrade for complete security" + }, + "premiumGivesMoreTools": { + "message": "Premium gives you more tools to stay secure, work efficiently, and stay in control." + }, + "explorePremium": { + "message": "Explore Premium" + }, "loadingVault": { "message": "Loading vault" }, diff --git a/apps/browser/src/_locales/zh_CN/messages.json b/apps/browser/src/_locales/zh_CN/messages.json index 52d8a03b76..548bdd9e17 100644 --- a/apps/browser/src/_locales/zh_CN/messages.json +++ b/apps/browser/src/_locales/zh_CN/messages.json @@ -595,7 +595,7 @@ "message": "查看全部" }, "viewLess": { - "message": "View less" + "message": "查看更少" }, "viewLogin": { "message": "查看登录" @@ -1485,7 +1485,7 @@ "message": "优先客户支持。" }, "ppremiumSignUpFuture": { - "message": "未来的更多高级功能。敬请期待!" + "message": "未来的更多高级版功能。敬请期待!" }, "premiumPurchase": { "message": "购买高级版" @@ -4897,7 +4897,7 @@ "message": "确定要永久删除此附件吗?" }, "premium": { - "message": "高级会员" + "message": "高级版" }, "freeOrgsCannotUseAttachments": { "message": "免费组织无法使用附件" @@ -5809,6 +5809,15 @@ "upgradeToPremium": { "message": "升级为高级版" }, + "upgradeCompleteSecurity": { + "message": "升级以获得全面的安全防护" + }, + "premiumGivesMoreTools": { + "message": "高级版为您提供更多工具,助您保障安全、高效工作并掌控一切。" + }, + "explorePremium": { + "message": "探索高级版" + }, "loadingVault": { "message": "正在加载密码库" }, diff --git a/apps/browser/src/_locales/zh_TW/messages.json b/apps/browser/src/_locales/zh_TW/messages.json index 370c147871..600447a29f 100644 --- a/apps/browser/src/_locales/zh_TW/messages.json +++ b/apps/browser/src/_locales/zh_TW/messages.json @@ -595,7 +595,7 @@ "message": "檢視全部" }, "viewLess": { - "message": "View less" + "message": "顯示較少" }, "viewLogin": { "message": "檢視登入" @@ -5809,6 +5809,15 @@ "upgradeToPremium": { "message": "升級到 Premium" }, + "upgradeCompleteSecurity": { + "message": "Upgrade for complete security" + }, + "premiumGivesMoreTools": { + "message": "Premium gives you more tools to stay secure, work efficiently, and stay in control." + }, + "explorePremium": { + "message": "Explore Premium" + }, "loadingVault": { "message": "正在載入密碼庫" }, From fd1155ae581b046fc0e300ef9b04cf7b6d43f426 Mon Sep 17 00:00:00 2001 From: Jason Ng Date: Tue, 18 Nov 2025 12:38:18 -0500 Subject: [PATCH 13/52] [PM-27103] Add URL Check to Send (#17056) * add dangerousPatters check to api service --- libs/common/src/platform/misc/utils.spec.ts | 26 +++++++++++ libs/common/src/platform/misc/utils.ts | 49 +++++++++++++++++++++ libs/common/src/services/api.service.ts | 10 ++++- 3 files changed, 84 insertions(+), 1 deletion(-) diff --git a/libs/common/src/platform/misc/utils.spec.ts b/libs/common/src/platform/misc/utils.spec.ts index 9f01db61fa..664c6e22b3 100644 --- a/libs/common/src/platform/misc/utils.spec.ts +++ b/libs/common/src/platform/misc/utils.spec.ts @@ -689,6 +689,32 @@ describe("Utils Service", () => { }); }); + describe("invalidUrlPatterns", () => { + it("should return false if no invalid patterns are found", () => { + const urlString = "https://www.example.com/api/my/account/status"; + + const actual = Utils.invalidUrlPatterns(urlString); + + expect(actual).toBe(false); + }); + + it("should return true if an invalid pattern is found", () => { + const urlString = "https://www.example.com/api/%2e%2e/secret"; + + const actual = Utils.invalidUrlPatterns(urlString); + + expect(actual).toBe(true); + }); + + it("should return true if an invalid pattern is found in a param", () => { + const urlString = "https://www.example.com/api/history?someToken=../secret"; + + const actual = Utils.invalidUrlPatterns(urlString); + + expect(actual).toBe(true); + }); + }); + describe("getUrl", () => { it("assumes a http protocol if no protocol is specified", () => { const urlString = "www.exampleapp.com.au:4000"; diff --git a/libs/common/src/platform/misc/utils.ts b/libs/common/src/platform/misc/utils.ts index 5f977da397..136b0ac394 100644 --- a/libs/common/src/platform/misc/utils.ts +++ b/libs/common/src/platform/misc/utils.ts @@ -612,6 +612,55 @@ export class Utils { return path.normalize(decodeURIComponent(denormalizedPath)).replace(/^(\.\.(\/|\\|$))+/, ""); } + /** + * Validates an url checking against invalid patterns + * @param url + * @returns true if invalid patterns found, false if safe + */ + static invalidUrlPatterns(url: string): boolean { + const invalidUrlPatterns = ["..", "%2e", "\\", "%5c"]; + + const decodedUrl = decodeURIComponent(url.toLocaleLowerCase()); + + // Check URL for invalidUrl patterns across entire URL + if (invalidUrlPatterns.some((p) => decodedUrl.includes(p))) { + return true; + } + + // Check for additional invalid patterns inside URL params + if (decodedUrl.includes("?")) { + const hasInvalidParams = this.validateQueryParameters(decodedUrl); + if (hasInvalidParams) { + return true; + } + } + + return false; + } + + /** + * Validates query parameters for additional invalid patterns + * @param url - The URL containing query parameters + * @returns true if invalid patterns found, false if safe + */ + private static validateQueryParameters(url: string): boolean { + try { + let queryString: string; + + if (url.includes("?")) { + queryString = url.split("?")[1]; + } else { + return false; + } + + const paramInvalidPatterns = ["/", "%2f", "#", "%23"]; + + return paramInvalidPatterns.some((p) => queryString.includes(p)); + } catch (error) { + throw new Error(`Error validating query parameters: ${error}`); + } + } + private static isMobile(win: Window) { let mobile = false; ((a) => { diff --git a/libs/common/src/services/api.service.ts b/libs/common/src/services/api.service.ts index 8314e44e75..633c7eedcc 100644 --- a/libs/common/src/services/api.service.ts +++ b/libs/common/src/services/api.service.ts @@ -1588,8 +1588,16 @@ export class ApiService implements ApiServiceAbstraction { ); apiUrl = Utils.isNullOrWhitespace(apiUrl) ? env.getApiUrl() : apiUrl; - // Prevent directory traversal from malicious paths const pathParts = path.split("?"); + // Check for path traversal patterns from any URL. + const fullUrlPath = apiUrl + pathParts[0] + (pathParts.length > 1 ? `?${pathParts[1]}` : ""); + + const isInvalidUrl = Utils.invalidUrlPatterns(fullUrlPath); + if (isInvalidUrl) { + throw new Error("The request URL contains dangerous patterns."); + } + + // Prevent directory traversal from malicious paths const requestUrl = apiUrl + Utils.normalizePath(pathParts[0]) + (pathParts.length > 1 ? `?${pathParts[1]}` : ""); From 02ef4e72de615ca6fff7319398e69e244bb3a9be Mon Sep 17 00:00:00 2001 From: Github Actions Date: Tue, 18 Nov 2025 17:54:35 +0000 Subject: [PATCH 14/52] Bumped Desktop client to 2025.11.2 --- apps/desktop/package.json | 2 +- apps/desktop/src/package-lock.json | 4 ++-- apps/desktop/src/package.json | 2 +- package-lock.json | 2 +- 4 files changed, 5 insertions(+), 5 deletions(-) diff --git a/apps/desktop/package.json b/apps/desktop/package.json index 4639a0b636..2633f3d590 100644 --- a/apps/desktop/package.json +++ b/apps/desktop/package.json @@ -1,7 +1,7 @@ { "name": "@bitwarden/desktop", "description": "A secure and free password manager for all of your devices.", - "version": "2025.11.1", + "version": "2025.11.2", "keywords": [ "bitwarden", "password", diff --git a/apps/desktop/src/package-lock.json b/apps/desktop/src/package-lock.json index c11c8f08cd..0a4204bf23 100644 --- a/apps/desktop/src/package-lock.json +++ b/apps/desktop/src/package-lock.json @@ -1,12 +1,12 @@ { "name": "@bitwarden/desktop", - "version": "2025.11.1", + "version": "2025.11.2", "lockfileVersion": 3, "requires": true, "packages": { "": { "name": "@bitwarden/desktop", - "version": "2025.11.1", + "version": "2025.11.2", "license": "GPL-3.0", "dependencies": { "@bitwarden/desktop-napi": "file:../desktop_native/napi" diff --git a/apps/desktop/src/package.json b/apps/desktop/src/package.json index d4800009de..765bc771b9 100644 --- a/apps/desktop/src/package.json +++ b/apps/desktop/src/package.json @@ -2,7 +2,7 @@ "name": "@bitwarden/desktop", "productName": "Bitwarden", "description": "A secure and free password manager for all of your devices.", - "version": "2025.11.1", + "version": "2025.11.2", "author": "Bitwarden Inc. (https://bitwarden.com)", "homepage": "https://bitwarden.com", "license": "GPL-3.0", diff --git a/package-lock.json b/package-lock.json index b7b625fdde..67d3b68786 100644 --- a/package-lock.json +++ b/package-lock.json @@ -280,7 +280,7 @@ }, "apps/desktop": { "name": "@bitwarden/desktop", - "version": "2025.11.1", + "version": "2025.11.2", "hasInstallScript": true, "license": "GPL-3.0" }, From b952e6ea445314323f9342dcee96e3c9c7576fcc Mon Sep 17 00:00:00 2001 From: Will Martin Date: Tue, 18 Nov 2025 13:08:21 -0500 Subject: [PATCH 15/52] [PM-28071] add prod test domain for phishing detection (#17450) --- .../dirt/phishing-detection/services/phishing-data.service.ts | 1 + 1 file changed, 1 insertion(+) diff --git a/apps/browser/src/dirt/phishing-detection/services/phishing-data.service.ts b/apps/browser/src/dirt/phishing-detection/services/phishing-data.service.ts index cb76a1cc35..6e1bf07c64 100644 --- a/apps/browser/src/dirt/phishing-detection/services/phishing-data.service.ts +++ b/apps/browser/src/dirt/phishing-detection/services/phishing-data.service.ts @@ -58,6 +58,7 @@ export class PhishingDataService { new Set( (state?.domains?.filter((line) => line.trim().length > 0) ?? []).concat( this._testDomains, + "phishing.testcategory.com", // Included for QA to test in prod ), ), ), From df03664827c3f77c3d0eff8b7c6cd2efd83721b8 Mon Sep 17 00:00:00 2001 From: Jonathan Prusik Date: Tue, 18 Nov 2025 14:49:12 -0500 Subject: [PATCH 16/52] [PM-27915] Add additional global styling collision defenses for pseudo-elements (#17340) * add additional global styling collision defenses for pseudo-elements * move internal stylesheet into closed shadow root --- .../autofill-inline-menu-content.service.ts | 26 ---------- .../autofill-inline-menu-iframe-element.ts | 49 +++++++++++++++++++ 2 files changed, 49 insertions(+), 26 deletions(-) diff --git a/apps/browser/src/autofill/overlay/inline-menu/content/autofill-inline-menu-content.service.ts b/apps/browser/src/autofill/overlay/inline-menu/content/autofill-inline-menu-content.service.ts index b550ae203d..be93e86327 100644 --- a/apps/browser/src/autofill/overlay/inline-menu/content/autofill-inline-menu-content.service.ts +++ b/apps/browser/src/autofill/overlay/inline-menu/content/autofill-inline-menu-content.service.ts @@ -240,8 +240,6 @@ export class AutofillInlineMenuContentService implements AutofillInlineMenuConte this.buttonElement = globalThis.document.createElement(customElementName); this.buttonElement.setAttribute("popover", "manual"); - - this.createInternalStyleNode(this.buttonElement); } /** @@ -270,30 +268,6 @@ export class AutofillInlineMenuContentService implements AutofillInlineMenuConte this.listElement = globalThis.document.createElement(customElementName); this.listElement.setAttribute("popover", "manual"); - - this.createInternalStyleNode(this.listElement); - } - - /** - * Builds and prepends an internal stylesheet to the container node with rules - * to prevent targeting by the host's global styling rules. This should only be - * used for pseudo elements such as `::backdrop` or `::before`. All other - * styles should be applied inline upon the parent container itself. - */ - private createInternalStyleNode(parent: HTMLElement) { - const css = document.createTextNode(` - ${parent.tagName}::backdrop { - background: none !important; - pointer-events: none !important; - } - ${parent.tagName}::before, ${parent.tagName}::after { - content:"" !important; - } - `); - const style = globalThis.document.createElement("style"); - style.setAttribute("type", "text/css"); - style.appendChild(css); - parent.prepend(style); } /** diff --git a/apps/browser/src/autofill/overlay/inline-menu/iframe-content/autofill-inline-menu-iframe-element.ts b/apps/browser/src/autofill/overlay/inline-menu/iframe-content/autofill-inline-menu-iframe-element.ts index 2fea65a7f0..3e2b364b17 100644 --- a/apps/browser/src/autofill/overlay/inline-menu/iframe-content/autofill-inline-menu-iframe-element.ts +++ b/apps/browser/src/autofill/overlay/inline-menu/iframe-content/autofill-inline-menu-iframe-element.ts @@ -8,7 +8,10 @@ export class AutofillInlineMenuIframeElement { iframeTitle: string, ariaAlert?: string, ) { + const style = this.createInternalStyleNode(); const shadow: ShadowRoot = element.attachShadow({ mode: "closed" }); + shadow.prepend(style); + const autofillInlineMenuIframeService = new AutofillInlineMenuIframeService( shadow, portName, @@ -18,4 +21,50 @@ export class AutofillInlineMenuIframeElement { ); autofillInlineMenuIframeService.initMenuIframe(); } + + /** + * Builds and prepends an internal stylesheet to the container node with rules + * to prevent targeting by the host's global styling rules. This should only be + * used for pseudo elements such as `::backdrop` or `::before`. All other + * styles should be applied inline upon the parent container itself for improved + * specificity priority. + */ + private createInternalStyleNode() { + const css = document.createTextNode(` + :host::backdrop, + :host::before, + :host::after { + all: initial !important; + backdrop-filter: none !important; + filter: none !important; + inset: auto !important; + touch-action: auto !important; + user-select: text !important; + display: none !important; + position: relative !important; + top: auto !important; + right: auto !important; + bottom: auto !important; + left: auto !important; + transform: none !important; + transform-origin: 50% 50% !important; + opacity: 1 !important; + mix-blend-mode: normal !important; + isolation: isolate !important; + z-index: 0 !important; + background: none !important; + background-color: transparent !important; + background-image: none !important; + width: 0 !important; + height: 0 !important; + content: "" !important; + pointer-events: all !important; + } + `); + const style = globalThis.document.createElement("style"); + style.setAttribute("type", "text/css"); + style.appendChild(css); + + return style; + } } From bf8976ca66af75f6132b962b6b43b6734442e5bf Mon Sep 17 00:00:00 2001 From: gitclonebrian <235774926+gitclonebrian@users.noreply.github.com> Date: Tue, 18 Nov 2025 15:27:21 -0500 Subject: [PATCH 17/52] [BRE-1333] Added permissions to token generation (#17471) --- .github/workflows/crowdin-pull.yml | 2 ++ .github/workflows/sdk-breaking-change-check.yml | 2 ++ .github/workflows/version-auto-bump.yml | 1 + 3 files changed, 5 insertions(+) diff --git a/.github/workflows/crowdin-pull.yml b/.github/workflows/crowdin-pull.yml index 1953249307..311737a2c0 100644 --- a/.github/workflows/crowdin-pull.yml +++ b/.github/workflows/crowdin-pull.yml @@ -54,6 +54,8 @@ jobs: with: app-id: ${{ steps.get-kv-secrets.outputs.BW-GHAPP-ID }} private-key: ${{ steps.get-kv-secrets.outputs.BW-GHAPP-KEY }} + permission-contents: write # for creating, committing to, and pushing new branches + permission-pull-requests: write # for generating pull requests - name: Checkout repo uses: actions/checkout@08c6903cd8c0fde910a37f88322edcfb5dd907a8 # v5.0.0 diff --git a/.github/workflows/sdk-breaking-change-check.yml b/.github/workflows/sdk-breaking-change-check.yml index 759f2292d2..1b9653417f 100644 --- a/.github/workflows/sdk-breaking-change-check.yml +++ b/.github/workflows/sdk-breaking-change-check.yml @@ -58,6 +58,8 @@ jobs: with: app-id: ${{ steps.get-kv-secrets.outputs.BW-GHAPP-ID }} private-key: ${{ steps.get-kv-secrets.outputs.BW-GHAPP-KEY }} + permission-actions: read # for reading and downloading the artifacts for a workflow run + - name: Log out from Azure uses: bitwarden/gh-actions/azure-logout@main diff --git a/.github/workflows/version-auto-bump.yml b/.github/workflows/version-auto-bump.yml index 9ff252d2fe..d807dd046d 100644 --- a/.github/workflows/version-auto-bump.yml +++ b/.github/workflows/version-auto-bump.yml @@ -36,6 +36,7 @@ jobs: with: app-id: ${{ steps.get-kv-secrets.outputs.BW-GHAPP-ID }} private-key: ${{ steps.get-kv-secrets.outputs.BW-GHAPP-KEY }} + permission-contents: write # for committing and pushing to the current branch - name: Check out target ref uses: actions/checkout@08c6903cd8c0fde910a37f88322edcfb5dd907a8 # v5.0.0 From fde1e26ad9d26bca7fd925fb863c4fea32012b6f Mon Sep 17 00:00:00 2001 From: Kyle Denney <4227399+kdenney@users.noreply.github.com> Date: Tue, 18 Nov 2025 15:24:36 -0600 Subject: [PATCH 18/52] [PM-28370] fix defect for self-hosted metadata (#17464) --- .../src/services/jslib-services.module.ts | 2 +- .../billing-api.service.abstraction.ts | 4 +++ .../billing/services/billing-api.service.ts | 14 ++++++++++ .../organization-metadata.service.spec.ts | 28 ++++++++++++++++++- .../organization-metadata.service.ts | 6 +++- 5 files changed, 51 insertions(+), 3 deletions(-) diff --git a/libs/angular/src/services/jslib-services.module.ts b/libs/angular/src/services/jslib-services.module.ts index 9dbc667996..b1215654cf 100644 --- a/libs/angular/src/services/jslib-services.module.ts +++ b/libs/angular/src/services/jslib-services.module.ts @@ -1451,7 +1451,7 @@ const safeProviders: SafeProvider[] = [ safeProvider({ provide: OrganizationMetadataServiceAbstraction, useClass: DefaultOrganizationMetadataService, - deps: [BillingApiServiceAbstraction, ConfigService], + deps: [BillingApiServiceAbstraction, ConfigService, PlatformUtilsServiceAbstraction], }), safeProvider({ provide: BillingAccountProfileStateService, diff --git a/libs/common/src/billing/abstractions/billing-api.service.abstraction.ts b/libs/common/src/billing/abstractions/billing-api.service.abstraction.ts index ef01c98ecb..dcb395ef85 100644 --- a/libs/common/src/billing/abstractions/billing-api.service.abstraction.ts +++ b/libs/common/src/billing/abstractions/billing-api.service.abstraction.ts @@ -25,6 +25,10 @@ export abstract class BillingApiServiceAbstraction { organizationId: OrganizationId, ): Promise; + abstract getOrganizationBillingMetadataVNextSelfHost( + organizationId: OrganizationId, + ): Promise; + abstract getPlans(): Promise>; abstract getPremiumPlan(): Promise; diff --git a/libs/common/src/billing/services/billing-api.service.ts b/libs/common/src/billing/services/billing-api.service.ts index 673d4a9784..ae6913e545 100644 --- a/libs/common/src/billing/services/billing-api.service.ts +++ b/libs/common/src/billing/services/billing-api.service.ts @@ -62,6 +62,20 @@ export class BillingApiService implements BillingApiServiceAbstraction { return new OrganizationBillingMetadataResponse(r); } + async getOrganizationBillingMetadataVNextSelfHost( + organizationId: OrganizationId, + ): Promise { + const r = await this.apiService.send( + "GET", + "/organizations/" + organizationId + "/billing/vnext/self-host/metadata", + null, + true, + true, + ); + + return new OrganizationBillingMetadataResponse(r); + } + async getPlans(): Promise> { const r = await this.apiService.send("GET", "/plans", null, true, true); return new ListResponse(r, PlanResponse); diff --git a/libs/common/src/billing/services/organization/organization-metadata.service.spec.ts b/libs/common/src/billing/services/organization/organization-metadata.service.spec.ts index c67f4aed17..a2b012eb16 100644 --- a/libs/common/src/billing/services/organization/organization-metadata.service.spec.ts +++ b/libs/common/src/billing/services/organization/organization-metadata.service.spec.ts @@ -4,6 +4,7 @@ import { BehaviorSubject, firstValueFrom } from "rxjs"; import { BillingApiServiceAbstraction } from "@bitwarden/common/billing/abstractions"; import { OrganizationBillingMetadataResponse } from "@bitwarden/common/billing/models/response/organization-billing-metadata.response"; import { ConfigService } from "@bitwarden/common/platform/abstractions/config/config.service"; +import { PlatformUtilsService } from "@bitwarden/common/platform/abstractions/platform-utils.service"; import { newGuid } from "@bitwarden/guid"; import { FeatureFlag } from "../../../enums/feature-flag.enum"; @@ -15,6 +16,7 @@ describe("DefaultOrganizationMetadataService", () => { let service: DefaultOrganizationMetadataService; let billingApiService: jest.Mocked; let configService: jest.Mocked; + let platformUtilsService: jest.Mocked; let featureFlagSubject: BehaviorSubject; const mockOrganizationId = newGuid() as OrganizationId; @@ -33,11 +35,17 @@ describe("DefaultOrganizationMetadataService", () => { beforeEach(() => { billingApiService = mock(); configService = mock(); + platformUtilsService = mock(); featureFlagSubject = new BehaviorSubject(false); configService.getFeatureFlag$.mockReturnValue(featureFlagSubject.asObservable()); + platformUtilsService.isSelfHost.mockReturnValue(false); - service = new DefaultOrganizationMetadataService(billingApiService, configService); + service = new DefaultOrganizationMetadataService( + billingApiService, + configService, + platformUtilsService, + ); }); afterEach(() => { @@ -142,6 +150,24 @@ describe("DefaultOrganizationMetadataService", () => { expect(result3).toEqual(mockResponse1); expect(result4).toEqual(mockResponse2); }); + + it("calls getOrganizationBillingMetadataVNextSelfHost when feature flag is on and isSelfHost is true", async () => { + platformUtilsService.isSelfHost.mockReturnValue(true); + const mockResponse = createMockMetadataResponse(true, 25); + billingApiService.getOrganizationBillingMetadataVNextSelfHost.mockResolvedValue( + mockResponse, + ); + + const result = await firstValueFrom(service.getOrganizationMetadata$(mockOrganizationId)); + + expect(platformUtilsService.isSelfHost).toHaveBeenCalled(); + expect(billingApiService.getOrganizationBillingMetadataVNextSelfHost).toHaveBeenCalledWith( + mockOrganizationId, + ); + expect(billingApiService.getOrganizationBillingMetadataVNext).not.toHaveBeenCalled(); + expect(billingApiService.getOrganizationBillingMetadata).not.toHaveBeenCalled(); + expect(result).toEqual(mockResponse); + }); }); describe("shareReplay behavior", () => { diff --git a/libs/common/src/billing/services/organization/organization-metadata.service.ts b/libs/common/src/billing/services/organization/organization-metadata.service.ts index fe96f0d984..5ce87262c4 100644 --- a/libs/common/src/billing/services/organization/organization-metadata.service.ts +++ b/libs/common/src/billing/services/organization/organization-metadata.service.ts @@ -1,6 +1,7 @@ import { BehaviorSubject, combineLatest, from, Observable, shareReplay, switchMap } from "rxjs"; import { BillingApiServiceAbstraction } from "@bitwarden/common/billing/abstractions"; +import { PlatformUtilsService } from "@bitwarden/common/platform/abstractions/platform-utils.service"; import { FeatureFlag } from "../../../enums/feature-flag.enum"; import { ConfigService } from "../../../platform/abstractions/config/config.service"; @@ -17,6 +18,7 @@ export class DefaultOrganizationMetadataService implements OrganizationMetadataS constructor( private billingApiService: BillingApiServiceAbstraction, private configService: ConfigService, + private platformUtilsService: PlatformUtilsService, ) {} private refreshMetadataTrigger = new BehaviorSubject(undefined); @@ -67,7 +69,9 @@ export class DefaultOrganizationMetadataService implements OrganizationMetadataS featureFlagEnabled: boolean, ): Promise { return featureFlagEnabled - ? await this.billingApiService.getOrganizationBillingMetadataVNext(organizationId) + ? this.platformUtilsService.isSelfHost() + ? await this.billingApiService.getOrganizationBillingMetadataVNextSelfHost(organizationId) + : await this.billingApiService.getOrganizationBillingMetadataVNext(organizationId) : await this.billingApiService.getOrganizationBillingMetadata(organizationId); } } From 84ce21643dc3789f36b773012768e854a08d7530 Mon Sep 17 00:00:00 2001 From: Alex <55413326+AlexRubik@users.noreply.github.com> Date: Tue, 18 Nov 2025 17:27:40 -0500 Subject: [PATCH 19/52] text and style (#17439) --- .../access-intelligence/activity/all-activity.component.html | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/bitwarden_license/bit-web/src/app/dirt/access-intelligence/activity/all-activity.component.html b/bitwarden_license/bit-web/src/app/dirt/access-intelligence/activity/all-activity.component.html index ffc67028b7..c9b930b3b5 100644 --- a/bitwarden_license/bit-web/src/app/dirt/access-intelligence/activity/all-activity.component.html +++ b/bitwarden_license/bit-web/src/app/dirt/access-intelligence/activity/all-activity.component.html @@ -80,11 +80,11 @@ @else {
  • Date: Wed, 19 Nov 2025 00:18:10 +0000 Subject: [PATCH 20/52] Bumped client version(s) --- apps/browser/package.json | 2 +- apps/browser/src/manifest.json | 2 +- apps/browser/src/manifest.v3.json | 2 +- package-lock.json | 2 +- 4 files changed, 4 insertions(+), 4 deletions(-) diff --git a/apps/browser/package.json b/apps/browser/package.json index 82d2ad7ab7..72e112e62f 100644 --- a/apps/browser/package.json +++ b/apps/browser/package.json @@ -1,6 +1,6 @@ { "name": "@bitwarden/browser", - "version": "2025.11.0", + "version": "2025.11.1", "scripts": { "build": "npm run build:chrome", "build:bit": "npm run build:bit:chrome", diff --git a/apps/browser/src/manifest.json b/apps/browser/src/manifest.json index d44a3d2a2e..3d8f648dac 100644 --- a/apps/browser/src/manifest.json +++ b/apps/browser/src/manifest.json @@ -2,7 +2,7 @@ "manifest_version": 2, "name": "__MSG_extName__", "short_name": "Bitwarden", - "version": "2025.11.0", + "version": "2025.11.1", "description": "__MSG_extDesc__", "default_locale": "en", "author": "Bitwarden Inc.", diff --git a/apps/browser/src/manifest.v3.json b/apps/browser/src/manifest.v3.json index b6381201c7..73403d2321 100644 --- a/apps/browser/src/manifest.v3.json +++ b/apps/browser/src/manifest.v3.json @@ -3,7 +3,7 @@ "minimum_chrome_version": "102.0", "name": "__MSG_extName__", "short_name": "Bitwarden", - "version": "2025.11.0", + "version": "2025.11.1", "description": "__MSG_extDesc__", "default_locale": "en", "author": "Bitwarden Inc.", diff --git a/package-lock.json b/package-lock.json index 67d3b68786..44e46a5d41 100644 --- a/package-lock.json +++ b/package-lock.json @@ -194,7 +194,7 @@ }, "apps/browser": { "name": "@bitwarden/browser", - "version": "2025.11.0" + "version": "2025.11.1" }, "apps/cli": { "name": "@bitwarden/cli", From e32309260cf85ac2c3fc7530aa2d4866d862be08 Mon Sep 17 00:00:00 2001 From: "renovate[bot]" <29139614+renovate[bot]@users.noreply.github.com> Date: Wed, 19 Nov 2025 05:39:11 -0600 Subject: [PATCH 21/52] [deps] Platform: Update @types/node-forge to v1.3.14 (#17490) Co-authored-by: renovate[bot] <29139614+renovate[bot]@users.noreply.github.com> --- package-lock.json | 8 ++++---- package.json | 2 +- 2 files changed, 5 insertions(+), 5 deletions(-) diff --git a/package-lock.json b/package-lock.json index 44e46a5d41..ccfad167c8 100644 --- a/package-lock.json +++ b/package-lock.json @@ -114,7 +114,7 @@ "@types/lunr": "2.3.7", "@types/node": "22.19.1", "@types/node-fetch": "2.6.4", - "@types/node-forge": "1.3.11", + "@types/node-forge": "1.3.14", "@types/papaparse": "5.5.0", "@types/proper-lockfile": "4.1.4", "@types/retry": "0.12.5", @@ -14463,9 +14463,9 @@ } }, "node_modules/@types/node-forge": { - "version": "1.3.11", - "resolved": "https://registry.npmjs.org/@types/node-forge/-/node-forge-1.3.11.tgz", - "integrity": "sha512-FQx220y22OKNTqaByeBGqHWYz4cl94tpcxeFdvBo3wjG6XPBuZ0BNgNZRV5J5TFmmcsJ4IzsLkmGRiQbnYsBEQ==", + "version": "1.3.14", + "resolved": "https://registry.npmjs.org/@types/node-forge/-/node-forge-1.3.14.tgz", + "integrity": "sha512-mhVF2BnD4BO+jtOp7z1CdzaK4mbuK0LLQYAvdOLqHTavxFNq4zA1EmYkpnFjP8HOUzedfQkRnp0E2ulSAYSzAw==", "license": "MIT", "dependencies": { "@types/node": "*" diff --git a/package.json b/package.json index 52a7d1c60a..757b7fec62 100644 --- a/package.json +++ b/package.json @@ -77,7 +77,7 @@ "@types/lunr": "2.3.7", "@types/node": "22.19.1", "@types/node-fetch": "2.6.4", - "@types/node-forge": "1.3.11", + "@types/node-forge": "1.3.14", "@types/papaparse": "5.5.0", "@types/proper-lockfile": "4.1.4", "@types/retry": "0.12.5", From 58727e884302feb8b835b7aca2b2b019870f870f Mon Sep 17 00:00:00 2001 From: "renovate[bot]" <29139614+renovate[bot]@users.noreply.github.com> Date: Wed, 19 Nov 2025 05:39:33 -0600 Subject: [PATCH 22/52] [deps] Platform: Update @types/chrome to v0.1.28 (#17489) Co-authored-by: renovate[bot] <29139614+renovate[bot]@users.noreply.github.com> --- package-lock.json | 8 ++++---- package.json | 2 +- 2 files changed, 5 insertions(+), 5 deletions(-) diff --git a/package-lock.json b/package-lock.json index ccfad167c8..674dcabf12 100644 --- a/package-lock.json +++ b/package-lock.json @@ -100,7 +100,7 @@ "@storybook/theming": "8.6.12", "@storybook/web-components-webpack5": "8.6.12", "@tailwindcss/container-queries": "0.1.1", - "@types/chrome": "0.1.27", + "@types/chrome": "0.1.28", "@types/firefox-webext-browser": "120.0.4", "@types/inquirer": "8.2.10", "@types/jest": "29.5.14", @@ -13957,9 +13957,9 @@ } }, "node_modules/@types/chrome": { - "version": "0.1.27", - "resolved": "https://registry.npmjs.org/@types/chrome/-/chrome-0.1.27.tgz", - "integrity": "sha512-pkkCb0Ft8X+Igi751POzT+YqchSxUCtB6s4Gs6ttgSj8qzJga/qlJMgSW1mKxuQTW4i0sTqQbqVtzXDS5AU+4A==", + "version": "0.1.28", + "resolved": "https://registry.npmjs.org/@types/chrome/-/chrome-0.1.28.tgz", + "integrity": "sha512-wANMmVt9H8UJeRsk4vlk5IVTTUIdk0J6CJC2ER60fGHTJOFVMuXpGhCqs6fUGw3m9pF1eXEvi+6ejlQZrtGA4A==", "dev": true, "license": "MIT", "dependencies": { diff --git a/package.json b/package.json index 757b7fec62..8322d065eb 100644 --- a/package.json +++ b/package.json @@ -63,7 +63,7 @@ "@storybook/theming": "8.6.12", "@storybook/web-components-webpack5": "8.6.12", "@tailwindcss/container-queries": "0.1.1", - "@types/chrome": "0.1.27", + "@types/chrome": "0.1.28", "@types/firefox-webext-browser": "120.0.4", "@types/inquirer": "8.2.10", "@types/jest": "29.5.14", From 90ca6bf2cd769934ca778fb5a124939e9897823c Mon Sep 17 00:00:00 2001 From: "renovate[bot]" <29139614+renovate[bot]@users.noreply.github.com> Date: Wed, 19 Nov 2025 12:00:49 +0000 Subject: [PATCH 23/52] [deps]: Update codecov/test-results-action action to v1.1.1 (#17493) Co-authored-by: renovate[bot] <29139614+renovate[bot]@users.noreply.github.com> --- .github/workflows/test.yml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.github/workflows/test.yml b/.github/workflows/test.yml index 71f8e7c915..ed967e63b5 100644 --- a/.github/workflows/test.yml +++ b/.github/workflows/test.yml @@ -71,7 +71,7 @@ jobs: fail-on-error: true - name: Upload results to codecov.io - uses: codecov/test-results-action@f2dba722c67b86c6caa034178c6e4d35335f6706 # v1.1.0 + uses: codecov/test-results-action@47f89e9acb64b76debcd5ea40642d25a4adced9f # v1.1.1 - name: Upload test coverage uses: actions/upload-artifact@65c4c4a1ddee5b72f698fdd19549f0f0fb45cf08 # v4.6.0 From db16c201b879c8aa4c1a52a79cc2aa229a808cb2 Mon Sep 17 00:00:00 2001 From: neuronull <9162534+neuronull@users.noreply.github.com> Date: Wed, 19 Nov 2025 08:07:57 -0700 Subject: [PATCH 24/52] Align Desktop Native's Rust CI checks with SDK (#17261) * clean crate deps * update lint workflow * add rustfmt.toml * apply rust fmt * missed one * fix lint of lint lol * more deps platform fixes * fix macos_provider * some more deps clean * more cleanup * add --all-targets * remove another unused dep * generate index.d.ts * fix whitespace * fix split comment in biometric * formatting comment in biometric_v2 * apply fmt --- .github/workflows/lint.yml | 24 ++- apps/desktop/desktop_native/Cargo.lock | 200 ------------------ apps/desktop/desktop_native/Cargo.toml | 2 - .../autotype/src/windows/type_input.rs | 15 +- .../autotype/src/windows/window_title.rs | 16 +- .../src/windows/crypto.rs | 3 +- .../src/windows/impersonate.rs | 3 +- .../src/windows/log.rs | 6 +- .../src/windows/main.rs | 10 +- .../chromium_importer/Cargo.toml | 17 +- .../chromium_importer/src/chromium/mod.rs | 20 +- .../src/chromium/platform/linux.rs | 10 +- .../src/chromium/platform/macos.rs | 7 +- .../src/chromium/platform/windows/abe.rs | 6 +- .../src/chromium/platform/windows/mod.rs | 16 +- .../chromium/platform/windows/signature.rs | 3 +- .../chromium_importer/src/metadata.rs | 2 +- .../chromium_importer/src/util.rs | 43 ++-- apps/desktop/desktop_native/core/Cargo.toml | 29 +-- .../desktop_native/core/src/biometric/mod.rs | 10 +- .../desktop_native/core/src/biometric/unix.rs | 10 +- .../core/src/biometric/windows.rs | 7 +- .../core/src/biometric_v2/linux.rs | 27 +-- .../core/src/biometric_v2/mod.rs | 7 +- .../core/src/biometric_v2/windows.rs | 69 +++--- .../core/src/biometric_v2/windows_focus.rs | 32 +-- .../desktop_native/core/src/crypto/crypto.rs | 6 +- apps/desktop/desktop_native/core/src/error.rs | 11 - .../desktop_native/core/src/ipc/mod.rs | 8 +- .../desktop_native/core/src/ipc/server.rs | 19 +- .../desktop_native/core/src/password/macos.rs | 3 +- .../desktop_native/core/src/password/unix.rs | 6 +- .../core/src/password/windows.rs | 3 +- .../core/src/process_isolation/linux.rs | 8 +- .../core/src/secure_memory/dpapi.rs | 5 +- .../secure_memory/encrypted_memory_store.rs | 4 +- .../src/secure_memory/secure_key/crypto.rs | 6 +- .../src/secure_memory/secure_key/dpapi.rs | 7 +- .../src/secure_memory/secure_key/keyctl.rs | 13 +- .../secure_memory/secure_key/memfd_secret.rs | 11 +- .../src/secure_memory/secure_key/mlock.rs | 7 +- .../core/src/secure_memory/secure_key/mod.rs | 27 ++- .../desktop_native/core/src/ssh_agent/mod.rs | 8 +- .../ssh_agent/named_pipe_listener_stream.rs | 5 +- .../peercred_unix_listener_stream.rs | 12 +- .../core/src/ssh_agent/peerinfo/models.rs | 7 +- .../desktop_native/core/src/ssh_agent/unix.rs | 3 +- .../core/src/ssh_agent/windows.rs | 1 + .../desktop_native/macos_provider/Cargo.toml | 7 +- apps/desktop/desktop_native/napi/Cargo.toml | 4 - apps/desktop/desktop_native/napi/index.d.ts | 23 +- apps/desktop/desktop_native/napi/src/lib.rs | 37 ++-- apps/desktop/desktop_native/objc/Cargo.toml | 8 +- .../process_isolation/Cargo.toml | 2 +- .../process_isolation/src/lib.rs | 3 +- apps/desktop/desktop_native/proxy/Cargo.toml | 1 - apps/desktop/desktop_native/proxy/src/main.rs | 10 +- apps/desktop/desktop_native/rustfmt.toml | 7 + .../windows_plugin_authenticator/src/lib.rs | 11 +- 59 files changed, 382 insertions(+), 505 deletions(-) create mode 100644 apps/desktop/desktop_native/rustfmt.toml diff --git a/.github/workflows/lint.yml b/.github/workflows/lint.yml index c14abd7cd8..6718690539 100644 --- a/.github/workflows/lint.yml +++ b/.github/workflows/lint.yml @@ -98,12 +98,27 @@ jobs: with: persist-credentials: false + - name: Install Rust + uses: dtolnay/rust-toolchain@6d653acede28d24f02e3cd41383119e8b1b35921 # stable + with: + toolchain: stable + components: rustfmt, clippy + + - name: Install Rust nightly + uses: dtolnay/rust-toolchain@6d653acede28d24f02e3cd41383119e8b1b35921 # stable + with: + toolchain: nightly + components: rustfmt + - name: Check Rust version run: rustup --version + - name: Cache cargo registry + uses: Swatinem/rust-cache@f0deed1e0edfc6a9be95417288c0e1099b1eeec3 # v2.7.7 + - name: Run cargo fmt working-directory: ./apps/desktop/desktop_native - run: cargo fmt --check + run: cargo +nightly fmt --check - name: Run Clippy working-directory: ./apps/desktop/desktop_native @@ -118,6 +133,13 @@ jobs: working-directory: ./apps/desktop/desktop_native run: cargo sort --workspace --check + - name: Install cargo-udeps + run: cargo install cargo-udeps --version 0.1.57 --locked + + - name: Cargo udeps + working-directory: ./apps/desktop/desktop_native + run: cargo +nightly udeps --workspace --all-features --all-targets + - name: Install cargo-deny uses: taiki-e/install-action@81ee1d48d9194cdcab880cbdc7d36e87d39874cb # v2.62.45 with: diff --git a/apps/desktop/desktop_native/Cargo.lock b/apps/desktop/desktop_native/Cargo.lock index 4da8214430..e8cc9385bb 100644 --- a/apps/desktop/desktop_native/Cargo.lock +++ b/apps/desktop/desktop_native/Cargo.lock @@ -684,17 +684,6 @@ dependencies = [ "error-code", ] -[[package]] -name = "codespan-reporting" -version = "0.12.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "fe6d2e5af09e8c8ad56c969f2157a3d4238cebc7c55f0a517728c38f7b200f81" -dependencies = [ - "serde", - "termcolor", - "unicode-width", -] - [[package]] name = "colorchoice" version = "1.0.3" @@ -841,65 +830,6 @@ dependencies = [ "syn", ] -[[package]] -name = "cxx" -version = "1.0.158" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "a71ea7f29c73f7ffa64c50b83c9fe4d3a6d4be89a86b009eb80d5a6d3429d741" -dependencies = [ - "cc", - "cxxbridge-cmd", - "cxxbridge-flags", - "cxxbridge-macro", - "foldhash", - "link-cplusplus", -] - -[[package]] -name = "cxx-build" -version = "1.0.158" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "36a8232661d66dcf713394726157d3cfe0a89bfc85f52d6e9f9bbc2306797fe7" -dependencies = [ - "cc", - "codespan-reporting", - "proc-macro2", - "quote", - "scratch", - "syn", -] - -[[package]] -name = "cxxbridge-cmd" -version = "1.0.158" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "4f44296c8693e9ea226a48f6a122727f77aa9e9e338380cb021accaeeb7ee279" -dependencies = [ - "clap", - "codespan-reporting", - "proc-macro2", - "quote", - "syn", -] - -[[package]] -name = "cxxbridge-flags" -version = "1.0.158" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "c42f69c181c176981ae44ba9876e2ea41ce8e574c296b38d06925ce9214fb8e4" - -[[package]] -name = "cxxbridge-macro" -version = "1.0.158" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "8faff5d4467e0709448187df29ccbf3b0982cc426ee444a193f87b11afb565a8" -dependencies = [ - "proc-macro2", - "quote", - "rustversion", - "syn", -] - [[package]] name = "der" version = "0.7.10" @@ -921,27 +851,21 @@ dependencies = [ "ashpd", "base64", "bitwarden-russh", - "byteorder", "bytes", "cbc", "chacha20poly1305", "core-foundation", "desktop_objc", "dirs", - "ed25519", "futures", "homedir", "interprocess", - "keytar", "libc", "linux-keyutils", "memsec", "oo7", "pin-project", - "pkcs8", "rand 0.9.1", - "rsa", - "russh-cryptovec", "scopeguard", "secmem-proc", "security-framework", @@ -949,12 +873,10 @@ dependencies = [ "serde", "serde_json", "sha2", - "ssh-encoding", "ssh-key", "sysinfo", "thiserror 2.0.12", "tokio", - "tokio-stream", "tokio-util", "tracing", "typenum", @@ -972,18 +894,14 @@ version = "0.0.0" dependencies = [ "anyhow", "autotype", - "base64", "chromium_importer", "desktop_core", - "hex", "napi", "napi-build", "napi-derive", "serde", "serde_json", "tokio", - "tokio-stream", - "tokio-util", "tracing", "tracing-subscriber", "windows-registry", @@ -996,9 +914,7 @@ version = "0.0.0" dependencies = [ "anyhow", "cc", - "core-foundation", "glob", - "thiserror 2.0.12", "tokio", "tracing", ] @@ -1007,7 +923,6 @@ dependencies = [ name = "desktop_proxy" version = "0.0.0" dependencies = [ - "anyhow", "desktop_core", "embed_plist", "futures", @@ -1740,27 +1655,6 @@ version = "1.0.15" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "4a5f13b858c8d314ee3e8f639011f7ccefe71f97f96e50151fb991f267928e2c" -[[package]] -name = "keytar" -version = "0.1.6" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "d361c55fba09829ac620b040f5425bf239b1030c3d6820a84acac8da867dca4d" -dependencies = [ - "keytar-sys", -] - -[[package]] -name = "keytar-sys" -version = "0.1.6" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "fe908c6896705a1cb516cd6a5d956c63f08d95ace81b93253a98cd93e1e6a65a" -dependencies = [ - "cc", - "cxx", - "cxx-build", - "pkg-config", -] - [[package]] name = "lazy_static" version = "1.5.0" @@ -1813,15 +1707,6 @@ dependencies = [ "vcpkg", ] -[[package]] -name = "link-cplusplus" -version = "1.0.10" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "4a6f6da007f968f9def0d65a05b187e2960183de70c160204ecfccf0ee330212" -dependencies = [ - "cc", -] - [[package]] name = "linux-keyutils" version = "0.2.4" @@ -1875,7 +1760,6 @@ dependencies = [ "serde", "serde_json", "tokio", - "tokio-util", "tracing", "tracing-oslog", "tracing-subscriber", @@ -2521,21 +2405,6 @@ dependencies = [ "spki", ] -[[package]] -name = "pkcs5" -version = "0.7.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "e847e2c91a18bfa887dd028ec33f2fe6f25db77db3619024764914affe8b69a6" -dependencies = [ - "aes", - "cbc", - "der", - "pbkdf2", - "scrypt", - "sha2", - "spki", -] - [[package]] name = "pkcs8" version = "0.10.2" @@ -2543,8 +2412,6 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "f950b2377845cebe5cf8b5165cb3cc1a5e0fa5cfa3e1f7f55707d8fd82e0a7b7" dependencies = [ "der", - "pkcs5", - "rand_core 0.6.4", "spki", ] @@ -2923,27 +2790,12 @@ dependencies = [ "rustix 1.0.7", ] -[[package]] -name = "rustversion" -version = "1.0.20" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "eded382c5f5f786b989652c49544c4877d9f015cc22e145a5ea8ea66c2921cd2" - [[package]] name = "ryu" version = "1.0.20" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "28d3b2b1366ec20994f1fd18c3c594f05c5dd4bc44d8bb0c1c632c8d6829481f" -[[package]] -name = "salsa20" -version = "0.10.2" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "97a22f5af31f73a954c10289c93e8a50cc23d971e80ee446f1f6f7137a088213" -dependencies = [ - "cipher", -] - [[package]] name = "scc" version = "2.4.0" @@ -2959,12 +2811,6 @@ version = "1.2.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "94143f37725109f92c262ed2cf5e59bce7498c01bcc1502d7b9afe439a4e9f49" -[[package]] -name = "scratch" -version = "1.0.8" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "9f6280af86e5f559536da57a45ebc84948833b3bee313a7dd25232e09c878a52" - [[package]] name = "scroll" version = "0.12.0" @@ -2985,17 +2831,6 @@ dependencies = [ "syn", ] -[[package]] -name = "scrypt" -version = "0.11.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "0516a385866c09368f0b5bcd1caff3366aace790fcd46e2bb032697bb172fd1f" -dependencies = [ - "pbkdf2", - "salsa20", - "sha2", -] - [[package]] name = "sdd" version = "3.0.10" @@ -3370,15 +3205,6 @@ dependencies = [ "windows-sys 0.59.0", ] -[[package]] -name = "termcolor" -version = "1.4.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "06794f8f6c5c898b3275aebefa6b8a1cb24cd2c6c79397ab15774837a0bc5755" -dependencies = [ - "winapi-util", -] - [[package]] name = "termtree" version = "0.5.1" @@ -3483,17 +3309,6 @@ dependencies = [ "syn", ] -[[package]] -name = "tokio-stream" -version = "0.1.15" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "267ac89e0bec6e691e5813911606935d77c476ff49024f98abcea3e7b15e37af" -dependencies = [ - "futures-core", - "pin-project-lite", - "tokio", -] - [[package]] name = "tokio-util" version = "0.7.13" @@ -3693,12 +3508,6 @@ version = "1.12.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "f6ccf251212114b54433ec949fd6a7841275f9ada20dddd2f29e9ceea4501493" -[[package]] -name = "unicode-width" -version = "0.2.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "1fc81956842c57dac11422a97c3b8195a1ff727f06e85c84ed2e8aa277c9a0fd" - [[package]] name = "uniffi" version = "0.28.3" @@ -4029,15 +3838,6 @@ version = "0.4.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "ac3b87c63620426dd9b991e5ce0329eff545bccbbb34f3be09ff6fb6ab51b7b6" -[[package]] -name = "winapi-util" -version = "0.1.9" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "cf221c93e13a30d793f7645a0e7762c55d169dbb0a49671918a2319d289b10bb" -dependencies = [ - "windows-sys 0.59.0", -] - [[package]] name = "winapi-x86_64-pc-windows-gnu" version = "0.4.0" diff --git a/apps/desktop/desktop_native/Cargo.toml b/apps/desktop/desktop_native/Cargo.toml index ccf7c1f379..d7afd44e9c 100644 --- a/apps/desktop/desktop_native/Cargo.toml +++ b/apps/desktop/desktop_native/Cargo.toml @@ -39,7 +39,6 @@ futures = "=0.3.31" hex = "=0.4.3" homedir = "=0.3.4" interprocess = "=2.2.1" -keytar = "=0.1.6" libc = "=0.2.172" linux-keyutils = "=0.2.4" memsec = "=0.7.0" @@ -64,7 +63,6 @@ ssh-key = { version = "=0.6.7", default-features = false } sysinfo = "=0.35.0" thiserror = "=2.0.12" tokio = "=1.45.0" -tokio-stream = "=0.1.15" tokio-util = "=0.7.13" tracing = "=0.1.41" tracing-subscriber = { version = "=0.3.20", features = [ diff --git a/apps/desktop/desktop_native/autotype/src/windows/type_input.rs b/apps/desktop/desktop_native/autotype/src/windows/type_input.rs index b757cf7752..10f30f5ee4 100644 --- a/apps/desktop/desktop_native/autotype/src/windows/type_input.rs +++ b/apps/desktop/desktop_native/autotype/src/windows/type_input.rs @@ -33,7 +33,8 @@ impl InputOperations for Win32InputOperations { /// Attempts to type the input text wherever the user's cursor is. /// /// `input` must be a vector of utf-16 encoded characters to insert. -/// `keyboard_shortcut` must be a vector of Strings, where valid shortcut keys: Control, Alt, Super, Shift, letters a - Z +/// `keyboard_shortcut` must be a vector of Strings, where valid shortcut keys: Control, Alt, Super, +/// Shift, letters a - Z /// /// https://learn.microsoft.com/en-in/windows/win32/api/winuser/nf-winuser-sendinput pub(super) fn type_input(input: Vec, keyboard_shortcut: Vec) -> Result<()> { @@ -234,16 +235,16 @@ where #[cfg(test)] mod tests { - //! For the mocking of the traits that are static methods, we need to use the `serial_test` crate - //! in order to mock those, since the mock expectations set have to be global in absence of a `self`. - //! More info: https://docs.rs/mockall/latest/mockall/#static-methods + //! For the mocking of the traits that are static methods, we need to use the `serial_test` + //! crate in order to mock those, since the mock expectations set have to be global in + //! absence of a `self`. More info: https://docs.rs/mockall/latest/mockall/#static-methods - use super::*; - - use crate::windowing::MockErrorOperations; use serial_test::serial; use windows::Win32::Foundation::WIN32_ERROR; + use super::*; + use crate::windowing::MockErrorOperations; + #[test] fn get_alphabetic_hot_key_succeeds() { for c in ('a'..='z').chain('A'..='Z') { diff --git a/apps/desktop/desktop_native/autotype/src/windows/window_title.rs b/apps/desktop/desktop_native/autotype/src/windows/window_title.rs index 58f06eb54c..d56a811ab5 100644 --- a/apps/desktop/desktop_native/autotype/src/windows/window_title.rs +++ b/apps/desktop/desktop_native/autotype/src/windows/window_title.rs @@ -127,8 +127,8 @@ where /// /// # Errors /// -/// - If the actual window title length (what the win32 API declares was written into the -/// buffer), is length zero and GetLastError() != 0 , return the GetLastError() message. +/// - If the actual window title length (what the win32 API declares was written into the buffer), +/// is length zero and GetLastError() != 0 , return the GetLastError() message. fn get_window_title(window_handle: &H, expected_title_length: usize) -> Result where H: WindowHandleOperations, @@ -169,17 +169,17 @@ where #[cfg(test)] mod tests { - //! For the mocking of the traits that are static methods, we need to use the `serial_test` crate - //! in order to mock those, since the mock expectations set have to be global in absence of a `self`. - //! More info: https://docs.rs/mockall/latest/mockall/#static-methods + //! For the mocking of the traits that are static methods, we need to use the `serial_test` + //! crate in order to mock those, since the mock expectations set have to be global in + //! absence of a `self`. More info: https://docs.rs/mockall/latest/mockall/#static-methods - use super::*; - - use crate::windowing::MockErrorOperations; use mockall::predicate; use serial_test::serial; use windows::Win32::Foundation::WIN32_ERROR; + use super::*; + use crate::windowing::MockErrorOperations; + #[test] #[serial] fn get_window_title_length_can_be_zero() { diff --git a/apps/desktop/desktop_native/bitwarden_chromium_import_helper/src/windows/crypto.rs b/apps/desktop/desktop_native/bitwarden_chromium_import_helper/src/windows/crypto.rs index 094dbf94a6..c335a4b296 100644 --- a/apps/desktop/desktop_native/bitwarden_chromium_import_helper/src/windows/crypto.rs +++ b/apps/desktop/desktop_native/bitwarden_chromium_import_helper/src/windows/crypto.rs @@ -95,7 +95,8 @@ pub(crate) fn decode_abe_key_blob(blob_data: &[u8]) -> Result> { let content_offset = content_len_offset + 4; let content = get_safe(blob_data, content_offset, content_len)?; - // When the size is exactly 32 bytes, it's a plain key. It's used in unbranded Chromium builds, Brave, possibly Edge + // When the size is exactly 32 bytes, it's a plain key. It's used in unbranded Chromium builds, + // Brave, possibly Edge if content_len == 32 { return Ok(content.to_vec()); } diff --git a/apps/desktop/desktop_native/bitwarden_chromium_import_helper/src/windows/impersonate.rs b/apps/desktop/desktop_native/bitwarden_chromium_import_helper/src/windows/impersonate.rs index 5a5109b9d3..22006b8db1 100644 --- a/apps/desktop/desktop_native/bitwarden_chromium_import_helper/src/windows/impersonate.rs +++ b/apps/desktop/desktop_native/bitwarden_chromium_import_helper/src/windows/impersonate.rs @@ -30,7 +30,8 @@ pub(crate) fn start_impersonating() -> Result { // Need to enable SE_DEBUG_PRIVILEGE to enumerate and open SYSTEM processes enable_debug_privilege()?; - // Find a SYSTEM process and get its token. Not every SYSTEM process allows token duplication, so try several. + // Find a SYSTEM process and get its token. Not every SYSTEM process allows token duplication, + // so try several. let (token, pid, name) = find_system_process_with_token(get_system_pid_list())?; // Impersonate the SYSTEM process diff --git a/apps/desktop/desktop_native/bitwarden_chromium_import_helper/src/windows/log.rs b/apps/desktop/desktop_native/bitwarden_chromium_import_helper/src/windows/log.rs index 7ee34a4160..aa00a2f61b 100644 --- a/apps/desktop/desktop_native/bitwarden_chromium_import_helper/src/windows/log.rs +++ b/apps/desktop/desktop_native/bitwarden_chromium_import_helper/src/windows/log.rs @@ -1,13 +1,13 @@ +use chromium_importer::config::{ENABLE_DEVELOPER_LOGGING, LOG_FILENAME}; use tracing::{error, level_filters::LevelFilter}; use tracing_subscriber::{ fmt, layer::SubscriberExt as _, util::SubscriberInitExt as _, EnvFilter, Layer as _, }; -use chromium_importer::config::{ENABLE_DEVELOPER_LOGGING, LOG_FILENAME}; - pub(crate) fn init_logging() { if ENABLE_DEVELOPER_LOGGING { - // We only log to a file. It's impossible to see stdout/stderr when this exe is launched from ShellExecuteW. + // We only log to a file. It's impossible to see stdout/stderr when this exe is launched + // from ShellExecuteW. match std::fs::File::create(LOG_FILENAME) { Ok(file) => { let file_filter = EnvFilter::builder() diff --git a/apps/desktop/desktop_native/bitwarden_chromium_import_helper/src/windows/main.rs b/apps/desktop/desktop_native/bitwarden_chromium_import_helper/src/windows/main.rs index e178a8accf..560135b8ce 100644 --- a/apps/desktop/desktop_native/bitwarden_chromium_import_helper/src/windows/main.rs +++ b/apps/desktop/desktop_native/bitwarden_chromium_import_helper/src/windows/main.rs @@ -1,12 +1,14 @@ -use anyhow::{anyhow, Result}; -use clap::Parser; -use scopeguard::defer; use std::{ ffi::OsString, os::windows::{ffi::OsStringExt as _, io::AsRawHandle}, path::PathBuf, time::Duration, }; + +use anyhow::{anyhow, Result}; +use chromium_importer::chromium::{verify_signature, ADMIN_TO_USER_PIPE_NAME}; +use clap::Parser; +use scopeguard::defer; use tokio::{ io::{AsyncReadExt, AsyncWriteExt}, net::windows::named_pipe::{ClientOptions, NamedPipeClient}, @@ -25,8 +27,6 @@ use windows::Win32::{ UI::Shell::IsUserAnAdmin, }; -use chromium_importer::chromium::{verify_signature, ADMIN_TO_USER_PIPE_NAME}; - use super::{ crypto::{ decode_abe_key_blob, decode_base64, decrypt_with_dpapi_as_system, diff --git a/apps/desktop/desktop_native/chromium_importer/Cargo.toml b/apps/desktop/desktop_native/chromium_importer/Cargo.toml index 933b0a8dac..4b02079bfd 100644 --- a/apps/desktop/desktop_native/chromium_importer/Cargo.toml +++ b/apps/desktop/desktop_native/chromium_importer/Cargo.toml @@ -7,35 +7,38 @@ publish = { workspace = true } [dependencies] aes = { workspace = true } -aes-gcm = { workspace = true } anyhow = { workspace = true } async-trait = "=0.1.88" -base64 = { workspace = true } -cbc = { workspace = true, features = ["alloc"] } dirs = { workspace = true } hex = { workspace = true } -pbkdf2 = "=0.12.2" rand = { workspace = true } rusqlite = { version = "=0.37.0", features = ["bundled"] } serde = { workspace = true, features = ["derive"] } serde_json = { workspace = true } -sha1 = "=0.10.6" -tokio = { workspace = true, features = ["full"] } -tracing = { workspace = true } [target.'cfg(target_os = "macos")'.dependencies] +cbc = { workspace = true, features = ["alloc"] } +pbkdf2 = "=0.12.2" security-framework = { workspace = true } +sha1 = "=0.10.6" [target.'cfg(target_os = "windows")'.dependencies] +aes-gcm = { workspace = true } +base64 = { workspace = true } windows = { workspace = true, features = [ "Win32_Security_Cryptography", "Win32_UI_Shell", "Win32_UI_WindowsAndMessaging", ] } verifysign = "=0.2.4" +tokio = { workspace = true, features = ["full"] } +tracing = { workspace = true } [target.'cfg(target_os = "linux")'.dependencies] +cbc = { workspace = true, features = ["alloc"] } oo7 = { workspace = true } +pbkdf2 = "=0.12.2" +sha1 = "=0.10.6" [lints] workspace = true diff --git a/apps/desktop/desktop_native/chromium_importer/src/chromium/mod.rs b/apps/desktop/desktop_native/chromium_importer/src/chromium/mod.rs index 369e63e0ad..e57b40b577 100644 --- a/apps/desktop/desktop_native/chromium_importer/src/chromium/mod.rs +++ b/apps/desktop/desktop_native/chromium_importer/src/chromium/mod.rs @@ -1,6 +1,8 @@ -use std::collections::HashMap; -use std::path::{Path, PathBuf}; -use std::sync::LazyLock; +use std::{ + collections::HashMap, + path::{Path, PathBuf}, + sync::LazyLock, +}; use anyhow::{anyhow, Result}; use async_trait::async_trait; @@ -10,11 +12,10 @@ use rusqlite::{params, Connection}; mod platform; +pub(crate) use platform::SUPPORTED_BROWSERS as PLATFORM_SUPPORTED_BROWSERS; #[cfg(target_os = "windows")] pub use platform::*; -pub(crate) use platform::SUPPORTED_BROWSERS as PLATFORM_SUPPORTED_BROWSERS; - // // Public API // @@ -87,14 +88,15 @@ pub async fn import_logins( let local_logins = get_logins(&data_dir, profile_id, "Login Data") .map_err(|e| anyhow!("Failed to query logins: {}", e))?; - // This is not available in all browsers, but there's no harm in trying. If the file doesn't exist we just get an empty vector. + // This is not available in all browsers, but there's no harm in trying. If the file doesn't + // exist we just get an empty vector. let account_logins = get_logins(&data_dir, profile_id, "Login Data For Account") .map_err(|e| anyhow!("Failed to query logins: {}", e))?; // TODO: Do we need a better merge strategy? Maybe ignore duplicates at least? - // TODO: Should we also ignore an error from one of the two imports? If one is successful and the other fails, - // should we still return the successful ones? At the moment it doesn't fail for a missing file, only when - // something goes really wrong. + // TODO: Should we also ignore an error from one of the two imports? If one is successful and + // the other fails, should we still return the successful ones? At the moment it + // doesn't fail for a missing file, only when something goes really wrong. let all_logins = local_logins .into_iter() .chain(account_logins.into_iter()) diff --git a/apps/desktop/desktop_native/chromium_importer/src/chromium/platform/linux.rs b/apps/desktop/desktop_native/chromium_importer/src/chromium/platform/linux.rs index 227dffdcca..14e3879764 100644 --- a/apps/desktop/desktop_native/chromium_importer/src/chromium/platform/linux.rs +++ b/apps/desktop/desktop_native/chromium_importer/src/chromium/platform/linux.rs @@ -4,15 +4,17 @@ use anyhow::{anyhow, Result}; use async_trait::async_trait; use oo7::XDG_SCHEMA_ATTRIBUTE; -use crate::chromium::{BrowserConfig, CryptoService, LocalState}; - -use crate::util; +use crate::{ + chromium::{BrowserConfig, CryptoService, LocalState}, + util, +}; // // Public API // -// TODO: It's possible that there might be multiple possible data directories, depending on the installation method (e.g., snap, flatpak, etc.). +// TODO: It's possible that there might be multiple possible data directories, depending on the +// installation method (e.g., snap, flatpak, etc.). pub(crate) const SUPPORTED_BROWSERS: &[BrowserConfig] = &[ BrowserConfig { name: "Chrome", diff --git a/apps/desktop/desktop_native/chromium_importer/src/chromium/platform/macos.rs b/apps/desktop/desktop_native/chromium_importer/src/chromium/platform/macos.rs index c0e770c161..5d0b4f0c75 100644 --- a/apps/desktop/desktop_native/chromium_importer/src/chromium/platform/macos.rs +++ b/apps/desktop/desktop_native/chromium_importer/src/chromium/platform/macos.rs @@ -2,9 +2,10 @@ use anyhow::{anyhow, Result}; use async_trait::async_trait; use security_framework::passwords::get_generic_password; -use crate::chromium::{BrowserConfig, CryptoService, LocalState}; - -use crate::util; +use crate::{ + chromium::{BrowserConfig, CryptoService, LocalState}, + util, +}; // // Public API diff --git a/apps/desktop/desktop_native/chromium_importer/src/chromium/platform/windows/abe.rs b/apps/desktop/desktop_native/chromium_importer/src/chromium/platform/windows/abe.rs index 943727690f..a76f7b95e5 100644 --- a/apps/desktop/desktop_native/chromium_importer/src/chromium/platform/windows/abe.rs +++ b/apps/desktop/desktop_native/chromium_importer/src/chromium/platform/windows/abe.rs @@ -1,6 +1,6 @@ -use super::abe_config; -use anyhow::{anyhow, Result}; use std::{ffi::OsStr, os::windows::ffi::OsStrExt}; + +use anyhow::{anyhow, Result}; use tokio::{ io::{self, AsyncReadExt, AsyncWriteExt}, net::windows::named_pipe::{NamedPipeServer, ServerOptions}, @@ -14,6 +14,8 @@ use windows::{ Win32::UI::{Shell::ShellExecuteW, WindowsAndMessaging::SW_HIDE}, }; +use super::abe_config; + const WAIT_FOR_ADMIN_MESSAGE_TIMEOUT_SECS: u64 = 30; fn start_tokio_named_pipe_server( diff --git a/apps/desktop/desktop_native/chromium_importer/src/chromium/platform/windows/mod.rs b/apps/desktop/desktop_native/chromium_importer/src/chromium/platform/windows/mod.rs index 867104d9bf..9cc89ed216 100644 --- a/apps/desktop/desktop_native/chromium_importer/src/chromium/platform/windows/mod.rs +++ b/apps/desktop/desktop_native/chromium_importer/src/chromium/platform/windows/mod.rs @@ -1,11 +1,14 @@ +use std::path::{Path, PathBuf}; + use aes_gcm::{aead::Aead, Aes256Gcm, Key, KeyInit, Nonce}; use anyhow::{anyhow, Result}; use async_trait::async_trait; use base64::{engine::general_purpose::STANDARD as BASE64_STANDARD, Engine as _}; -use std::path::{Path, PathBuf}; -use crate::chromium::{BrowserConfig, CryptoService, LocalState}; -use crate::util; +use crate::{ + chromium::{BrowserConfig, CryptoService, LocalState}, + util, +}; mod abe; mod abe_config; mod crypto; @@ -95,7 +98,8 @@ impl CryptoService for WindowsCryptoService { let (version, no_prefix) = util::split_encrypted_string_and_validate(encrypted, &["v10", "v20"])?; - // v10 is already stripped; Windows Chrome uses AES-GCM: [12 bytes IV][ciphertext][16 bytes auth tag] + // v10 is already stripped; Windows Chrome uses AES-GCM: [12 bytes IV][ciphertext][16 bytes + // auth tag] const IV_SIZE: usize = 12; const TAG_SIZE: usize = 16; const MIN_LENGTH: usize = IV_SIZE + TAG_SIZE; @@ -242,8 +246,8 @@ fn get_dist_admin_exe_path(current_exe_full_path: &Path) -> Result { Ok(admin_exe) } -// Try to find bitwarden_chromium_import_helper.exe in debug build folders. This might not cover all the cases. -// Tested on `npm run electron` from apps/desktop and apps/desktop/desktop_native. +// Try to find bitwarden_chromium_import_helper.exe in debug build folders. This might not cover all +// the cases. Tested on `npm run electron` from apps/desktop and apps/desktop/desktop_native. fn get_debug_admin_exe_path() -> Result { let current_dir = std::env::current_dir()?; let folder_name = current_dir diff --git a/apps/desktop/desktop_native/chromium_importer/src/chromium/platform/windows/signature.rs b/apps/desktop/desktop_native/chromium_importer/src/chromium/platform/windows/signature.rs index d5d6c5d6d1..97cf57935b 100644 --- a/apps/desktop/desktop_native/chromium_importer/src/chromium/platform/windows/signature.rs +++ b/apps/desktop/desktop_native/chromium_importer/src/chromium/platform/windows/signature.rs @@ -1,5 +1,6 @@ -use anyhow::{anyhow, Result}; use std::path::Path; + +use anyhow::{anyhow, Result}; use tracing::{debug, info}; use verifysign::CodeSignVerifier; diff --git a/apps/desktop/desktop_native/chromium_importer/src/metadata.rs b/apps/desktop/desktop_native/chromium_importer/src/metadata.rs index bfd7f18462..114c9f8df8 100644 --- a/apps/desktop/desktop_native/chromium_importer/src/metadata.rs +++ b/apps/desktop/desktop_native/chromium_importer/src/metadata.rs @@ -59,9 +59,9 @@ pub fn get_supported_importers( // Tests are cfg-gated based upon OS, and must be compiled/run on each OS for full coverage #[cfg(test)] mod tests { - use super::*; use std::collections::HashSet; + use super::*; use crate::chromium::{InstalledBrowserRetriever, SUPPORTED_BROWSER_MAP}; pub struct MockInstalledBrowserRetriever {} diff --git a/apps/desktop/desktop_native/chromium_importer/src/util.rs b/apps/desktop/desktop_native/chromium_importer/src/util.rs index f346d7e6dd..2dbc6ed005 100644 --- a/apps/desktop/desktop_native/chromium_importer/src/util.rs +++ b/apps/desktop/desktop_native/chromium_importer/src/util.rs @@ -32,7 +32,7 @@ pub(crate) fn split_encrypted_string_and_validate<'a>( } /// Decrypt using AES-128 in CBC mode. -#[cfg(any(target_os = "linux", target_os = "macos", test))] +#[cfg(any(target_os = "linux", target_os = "macos"))] pub(crate) fn decrypt_aes_128_cbc(key: &[u8], iv: &[u8], ciphertext: &[u8]) -> Result> { use aes::cipher::{block_padding::Pkcs7, BlockDecryptMut, KeyIvInit}; @@ -41,7 +41,8 @@ pub(crate) fn decrypt_aes_128_cbc(key: &[u8], iv: &[u8], ciphertext: &[u8]) -> R .map_err(|e| anyhow!("Failed to decrypt: {}", e)) } -/// Derives a PBKDF2 key from the static "saltysalt" salt with the given password and iteration count. +/// Derives a PBKDF2 key from the static "saltysalt" salt with the given password and iteration +/// count. #[cfg(any(target_os = "linux", target_os = "macos"))] pub(crate) fn derive_saltysalt(password: &[u8], iterations: u32) -> Result> { use pbkdf2::{hmac::Hmac, pbkdf2}; @@ -55,27 +56,9 @@ pub(crate) fn derive_saltysalt(password: &[u8], iterations: u32) -> Result Vec { - (0..length).map(|i| offset + i as u8 * increment).collect() - } - - fn generate_generic_array>( - offset: u8, - increment: u8, - ) -> GenericArray { - GenericArray::generate(|i| offset + i as u8 * increment) - } - fn run_split_encrypted_string_test<'a, const N: usize>( successfully_split: bool, plaintext_to_encrypt: &'a str, @@ -144,8 +127,28 @@ mod tests { run_split_encrypted_string_and_validate_test(false, "v10EncryptMe!", &[]); } + #[cfg(any(target_os = "linux", target_os = "macos"))] #[test] fn test_decrypt_aes_128_cbc() { + use aes::cipher::{ + block_padding::Pkcs7, + generic_array::{sequence::GenericSequence, GenericArray}, + ArrayLength, BlockEncryptMut, KeyIvInit, + }; + + const LENGTH16: usize = 16; + + fn generate_generic_array>( + offset: u8, + increment: u8, + ) -> GenericArray { + GenericArray::generate(|i| offset + i as u8 * increment) + } + + fn generate_vec(length: usize, offset: u8, increment: u8) -> Vec { + (0..length).map(|i| offset + i as u8 * increment).collect() + } + let offset = 0; let increment = 1; diff --git a/apps/desktop/desktop_native/core/Cargo.toml b/apps/desktop/desktop_native/core/Cargo.toml index f6c9d669df..dc9246f55c 100644 --- a/apps/desktop/desktop_native/core/Cargo.toml +++ b/apps/desktop/desktop_native/core/Cargo.toml @@ -23,27 +23,15 @@ anyhow = { workspace = true } arboard = { workspace = true, features = ["wayland-data-control"] } base64 = { workspace = true } bitwarden-russh = { workspace = true } -byteorder = { workspace = true } bytes = { workspace = true } cbc = { workspace = true, features = ["alloc"] } chacha20poly1305 = { workspace = true } dirs = { workspace = true } -ed25519 = { workspace = true, features = ["pkcs8"] } futures = { workspace = true } -homedir = { workspace = true } interprocess = { workspace = true, features = ["tokio"] } memsec = { workspace = true, features = ["alloc_ext"] } -pin-project = { workspace = true } -pkcs8 = { workspace = true, features = ["alloc", "encryption", "pem"] } rand = { workspace = true } -rsa = { workspace = true } -russh-cryptovec = { workspace = true } -scopeguard = { workspace = true } -secmem-proc = { workspace = true } -serde = { workspace = true, features = ["derive"] } -serde_json = { workspace = true } sha2 = { workspace = true } -ssh-encoding = { workspace = true } ssh-key = { workspace = true, features = [ "encryption", "ed25519", @@ -53,13 +41,17 @@ ssh-key = { workspace = true, features = [ sysinfo = { workspace = true, features = ["windows"] } thiserror = { workspace = true } tokio = { workspace = true, features = ["io-util", "sync", "macros", "net"] } -tokio-stream = { workspace = true, features = ["net"] } tokio-util = { workspace = true, features = ["codec"] } tracing = { workspace = true } typenum = { workspace = true } zeroizing-alloc = { workspace = true } [target.'cfg(windows)'.dependencies] +pin-project = { workspace = true } +scopeguard = { workspace = true } +secmem-proc = { workspace = true } +serde = { workspace = true, features = ["derive"] } +serde_json = { workspace = true } widestring = { workspace = true, optional = true } windows = { workspace = true, features = [ "Foundation", @@ -76,21 +68,20 @@ windows = { workspace = true, features = [ ], optional = true } windows-future = { workspace = true } -[target.'cfg(windows)'.dev-dependencies] -keytar = { workspace = true } - [target.'cfg(target_os = "macos")'.dependencies] core-foundation = { workspace = true, optional = true } +homedir = { workspace = true } +secmem-proc = { workspace = true } security-framework = { workspace = true, optional = true } security-framework-sys = { workspace = true, optional = true } desktop_objc = { path = "../objc" } [target.'cfg(target_os = "linux")'.dependencies] -oo7 = { workspace = true } +ashpd = { workspace = true } +homedir = { workspace = true } libc = { workspace = true } linux-keyutils = { workspace = true } -ashpd = { workspace = true } - +oo7 = { workspace = true } zbus = { workspace = true, optional = true } zbus_polkit = { workspace = true, optional = true } diff --git a/apps/desktop/desktop_native/core/src/biometric/mod.rs b/apps/desktop/desktop_native/core/src/biometric/mod.rs index e4d51f5da9..937c67ff30 100644 --- a/apps/desktop/desktop_native/core/src/biometric/mod.rs +++ b/apps/desktop/desktop_native/core/src/biometric/mod.rs @@ -86,11 +86,15 @@ impl KeyMaterial { #[cfg(test)] mod tests { - use crate::biometric::{decrypt, encrypt, KeyMaterial}; - use crate::crypto::CipherString; - use base64::{engine::general_purpose::STANDARD as base64_engine, Engine}; use std::str::FromStr; + use base64::{engine::general_purpose::STANDARD as base64_engine, Engine}; + + use crate::{ + biometric::{decrypt, encrypt, KeyMaterial}, + crypto::CipherString, + }; + fn key_material() -> KeyMaterial { KeyMaterial { os_key_part_b64: "AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA=".to_owned(), diff --git a/apps/desktop/desktop_native/core/src/biometric/unix.rs b/apps/desktop/desktop_native/core/src/biometric/unix.rs index 0f6ff8f33d..3f4f10a1fc 100644 --- a/apps/desktop/desktop_native/core/src/biometric/unix.rs +++ b/apps/desktop/desktop_native/core/src/biometric/unix.rs @@ -1,18 +1,18 @@ use std::str::FromStr; -use anyhow::Result; +use anyhow::{anyhow, Result}; use base64::Engine; use rand::RngCore; use sha2::{Digest, Sha256}; use tracing::error; - -use crate::biometric::{base64_engine, KeyMaterial, OsDerivedKey}; use zbus::Connection; use zbus_polkit::policykit1::*; use super::{decrypt, encrypt}; -use crate::crypto::CipherString; -use anyhow::anyhow; +use crate::{ + biometric::{base64_engine, KeyMaterial, OsDerivedKey}, + crypto::CipherString, +}; /// The Unix implementation of the biometric trait. pub struct Biometric {} diff --git a/apps/desktop/desktop_native/core/src/biometric/windows.rs b/apps/desktop/desktop_native/core/src/biometric/windows.rs index 8013c21bf9..f72282d928 100644 --- a/apps/desktop/desktop_native/core/src/biometric/windows.rs +++ b/apps/desktop/desktop_native/core/src/biometric/windows.rs @@ -16,13 +16,12 @@ use windows::{ }; use windows_future::IAsyncOperation; +use super::{decrypt, encrypt, windows_focus::set_focus}; use crate::{ biometric::{KeyMaterial, OsDerivedKey}, crypto::CipherString, }; -use super::{decrypt, encrypt, windows_focus::set_focus}; - /// The Windows OS implementation of the biometric trait. pub struct Biometric {} @@ -61,7 +60,8 @@ impl super::BiometricTrait for Biometric { match ucv_available { UserConsentVerifierAvailability::Available => Ok(true), - UserConsentVerifierAvailability::DeviceBusy => Ok(true), // TODO: Look into removing this and making the check more ad-hoc + // TODO: look into removing this and making the check more ad-hoc + UserConsentVerifierAvailability::DeviceBusy => Ok(true), _ => Ok(false), } } @@ -133,7 +133,6 @@ fn random_challenge() -> [u8; 16] { #[cfg(test)] mod tests { use super::*; - use crate::biometric::BiometricTrait; #[test] diff --git a/apps/desktop/desktop_native/core/src/biometric_v2/linux.rs b/apps/desktop/desktop_native/core/src/biometric_v2/linux.rs index 44cba4a9e5..ff2abc0686 100644 --- a/apps/desktop/desktop_native/core/src/biometric_v2/linux.rs +++ b/apps/desktop/desktop_native/core/src/biometric_v2/linux.rs @@ -1,17 +1,19 @@ //! This file implements Polkit based system unlock. //! //! # Security -//! This section describes the assumed security model and security guarantees achieved. In the required security -//! guarantee is that a locked vault - a running app - cannot be unlocked when the device (user-space) -//! is compromised in this state. +//! This section describes the assumed security model and security guarantees achieved. In the +//! required security guarantee is that a locked vault - a running app - cannot be unlocked when the +//! device (user-space) is compromised in this state. //! -//! When first unlocking the app, the app sends the user-key to this module, which holds it in secure memory, -//! protected by memfd_secret. This makes it inaccessible to other processes, even if they compromise root, a kernel compromise -//! has circumventable best-effort protections. While the app is running this key is held in memory, even if locked. -//! When unlocking, the app will prompt the user via `polkit` to get a yes/no decision on whether to release the key to the app. +//! When first unlocking the app, the app sends the user-key to this module, which holds it in +//! secure memory, protected by memfd_secret. This makes it inaccessible to other processes, even if +//! they compromise root, a kernel compromise has circumventable best-effort protections. While the +//! app is running this key is held in memory, even if locked. When unlocking, the app will prompt +//! the user via `polkit` to get a yes/no decision on whether to release the key to the app. + +use std::sync::Arc; use anyhow::{anyhow, Result}; -use std::sync::Arc; use tokio::sync::Mutex; use tracing::{debug, warn}; use zbus::Connection; @@ -20,8 +22,8 @@ use zbus_polkit::policykit1::{AuthorityProxy, CheckAuthorizationFlags, Subject}; use crate::secure_memory::*; pub struct BiometricLockSystem { - // The userkeys that are held in memory MUST be protected from memory dumping attacks, to ensure - // locked vaults cannot be unlocked + // The userkeys that are held in memory MUST be protected from memory dumping attacks, to + // ensure locked vaults cannot be unlocked secure_memory: Arc>, } @@ -88,8 +90,9 @@ impl super::BiometricTrait for BiometricLockSystem { } } -/// Perform a polkit authorization against the bitwarden unlock policy. Note: This relies on no custom -/// rules in the system skipping the authorization check, in which case this counts as UV / authentication. +/// Perform a polkit authorization against the bitwarden unlock policy. Note: This relies on no +/// custom rules in the system skipping the authorization check, in which case this counts as UV / +/// authentication. async fn polkit_authenticate_bitwarden_policy() -> Result { debug!("[Polkit] Authenticating / performing UV"); diff --git a/apps/desktop/desktop_native/core/src/biometric_v2/mod.rs b/apps/desktop/desktop_native/core/src/biometric_v2/mod.rs index 669267b782..55aee27dd3 100644 --- a/apps/desktop/desktop_native/core/src/biometric_v2/mod.rs +++ b/apps/desktop/desktop_native/core/src/biometric_v2/mod.rs @@ -17,8 +17,8 @@ pub trait BiometricTrait: Send + Sync { async fn authenticate(&self, hwnd: Vec, message: String) -> Result; /// Check if biometric authentication is available async fn authenticate_available(&self) -> Result; - /// Enroll a key for persistent unlock. If the implementation does not support persistent enrollment, - /// this function should do nothing. + /// Enroll a key for persistent unlock. If the implementation does not support persistent + /// enrollment, this function should do nothing. async fn enroll_persistent(&self, user_id: &str, key: &[u8]) -> Result<()>; /// Clear the persistent and ephemeral keys async fn unenroll(&self, user_id: &str) -> Result<()>; @@ -28,6 +28,7 @@ pub trait BiometricTrait: Send + Sync { async fn provide_key(&self, user_id: &str, key: &[u8]); /// Perform biometric unlock and return the key async fn unlock(&self, user_id: &str, hwnd: Vec) -> Result>; - /// Check if biometric unlock is available based on whether a key is present and whether authentication is possible + /// Check if biometric unlock is available based on whether a key is present and whether + /// authentication is possible async fn unlock_available(&self, user_id: &str) -> Result; } diff --git a/apps/desktop/desktop_native/core/src/biometric_v2/windows.rs b/apps/desktop/desktop_native/core/src/biometric_v2/windows.rs index 043c2453cd..32d2eb7e6e 100644 --- a/apps/desktop/desktop_native/core/src/biometric_v2/windows.rs +++ b/apps/desktop/desktop_native/core/src/biometric_v2/windows.rs @@ -2,38 +2,40 @@ //! //! There are two paths implemented here. //! The former via UV + ephemerally (but protected) keys. This only works after first unlock. -//! The latter via a signing API, that deterministically signs a challenge, from which a windows hello key is derived. This key -//! is used to encrypt the protected key. +//! The latter via a signing API, that deterministically signs a challenge, from which a windows +//! hello key is derived. This key is used to encrypt the protected key. //! //! # Security -//! The security goal is that a locked vault - a running app - cannot be unlocked when the device (user-space) -//! is compromised in this state. +//! The security goal is that a locked vault - a running app - cannot be unlocked when the device +//! (user-space) is compromised in this state. //! //! ## UV path -//! When first unlocking the app, the app sends the user-key to this module, which holds it in secure memory, -//! protected by DPAPI. This makes it inaccessible to other processes, unless they compromise the system administrator, or kernel. -//! While the app is running this key is held in memory, even if locked. When unlocking, the app will prompt the user via +//! When first unlocking the app, the app sends the user-key to this module, which holds it in +//! secure memory, protected by DPAPI. This makes it inaccessible to other processes, unless they +//! compromise the system administrator, or kernel. While the app is running this key is held in +//! memory, even if locked. When unlocking, the app will prompt the user via //! `windows_hello_authenticate` to get a yes/no decision on whether to release the key to the app. -//! Note: Further process isolation is needed here so that code cannot be injected into the running process, which may -//! circumvent DPAPI. +//! Note: Further process isolation is needed here so that code cannot be injected into the running +//! process, which may circumvent DPAPI. //! //! ## Sign path -//! In this scenario, when enrolling, the app sends the user-key to this module, which derives the windows hello key -//! with the Windows Hello prompt. This is done by signing a per-user challenge, which produces a deterministic -//! signature which is hashed to obtain a key. This key is used to encrypt and persist the vault unlock key (user key). +//! In this scenario, when enrolling, the app sends the user-key to this module, which derives the +//! windows hello key with the Windows Hello prompt. This is done by signing a per-user challenge, +//! which produces a deterministic signature which is hashed to obtain a key. This key is used to +//! encrypt and persist the vault unlock key (user key). //! -//! Since the keychain can be accessed by all user-space processes, the challenge is known to all userspace processes. -//! Therefore, to circumvent the security measure, the attacker would need to create a fake Windows-Hello prompt, and -//! get the user to confirm it. +//! Since the keychain can be accessed by all user-space processes, the challenge is known to all +//! userspace processes. Therefore, to circumvent the security measure, the attacker would need to +//! create a fake Windows-Hello prompt, and get the user to confirm it. use std::sync::{atomic::AtomicBool, Arc}; -use tracing::{debug, warn}; use aes::cipher::KeyInit; use anyhow::{anyhow, Result}; use chacha20poly1305::{aead::Aead, XChaCha20Poly1305, XNonce}; use sha2::{Digest, Sha256}; use tokio::sync::Mutex; +use tracing::{debug, warn}; use windows::{ core::{factory, h, Interface, HSTRING}, Security::{ @@ -74,8 +76,8 @@ struct WindowsHelloKeychainEntry { /// The Windows OS implementation of the biometric trait. pub struct BiometricLockSystem { - // The userkeys that are held in memory MUST be protected from memory dumping attacks, to ensure - // locked vaults cannot be unlocked + // The userkeys that are held in memory MUST be protected from memory dumping attacks, to + // ensure locked vaults cannot be unlocked secure_memory: Arc>, } @@ -114,12 +116,14 @@ impl super::BiometricTrait for BiometricLockSystem { } async fn enroll_persistent(&self, user_id: &str, key: &[u8]) -> Result<()> { - // Enrollment works by first generating a random challenge unique to the user / enrollment. Then, - // with the challenge and a Windows-Hello prompt, the "windows hello key" is derived. The windows - // hello key is used to encrypt the key to store with XChaCha20Poly1305. The bundle of nonce, - // challenge and wrapped-key are stored to the keychain + // Enrollment works by first generating a random challenge unique to the user / enrollment. + // Then, with the challenge and a Windows-Hello prompt, the "windows hello key" is + // derived. The windows hello key is used to encrypt the key to store with + // XChaCha20Poly1305. The bundle of nonce, challenge and wrapped-key are stored to + // the keychain - // Each enrollment (per user) has a unique challenge, so that the windows-hello key is unique + // Each enrollment (per user) has a unique challenge, so that the windows-hello key is + // unique let challenge: [u8; CHALLENGE_LENGTH] = rand::random(); // This key is unique to the challenge @@ -155,8 +159,8 @@ impl super::BiometricTrait for BiometricLockSystem { }); let mut secure_memory = self.secure_memory.lock().await; - // If the key is held ephemerally, always use UV API. Only use signing API if the key is not held - // ephemerally but the keychain holds it persistently. + // If the key is held ephemerally, always use UV API. Only use signing API if the key is not + // held ephemerally but the keychain holds it persistently. if secure_memory.has(user_id) { if windows_hello_authenticate("Unlock your vault".to_string()).await? { secure_memory @@ -175,7 +179,8 @@ impl super::BiometricTrait for BiometricLockSystem { &keychain_entry.wrapped_key, &keychain_entry.nonce, )?; - // The first unlock already sets the key for subsequent unlocks. The key may again be set externally after unlock finishes. + // The first unlock already sets the key for subsequent unlocks. The key may again be + // set externally after unlock finishes. secure_memory.put(user_id.to_string(), &decrypted_key.clone()); Ok(decrypted_key) } @@ -231,8 +236,8 @@ async fn windows_hello_authenticate_with_crypto( ) -> Result<[u8; XCHACHA20POLY1305_KEY_LENGTH]> { debug!("[Windows Hello] Authenticating to sign challenge"); - // Ugly hack: We need to focus the window via window focusing APIs until Microsoft releases a new API. - // This is unreliable, and if it does not work, the operation may fail + // Ugly hack: We need to focus the window via window focusing APIs until Microsoft releases a + // new API. This is unreliable, and if it does not work, the operation may fail let stop_focusing = Arc::new(AtomicBool::new(false)); let stop_focusing_clone = stop_focusing.clone(); let _ = std::thread::spawn(move || loop { @@ -243,8 +248,8 @@ async fn windows_hello_authenticate_with_crypto( break; } }); - // Only stop focusing once this function exits. The focus MUST run both during the initial creation - // with RequestCreateAsync, and also with the subsequent use with RequestSignAsync. + // Only stop focusing once this function exits. The focus MUST run both during the initial + // creation with RequestCreateAsync, and also with the subsequent use with RequestSignAsync. let _guard = scopeguard::guard((), |_| { stop_focusing.store(true, std::sync::atomic::Ordering::Relaxed); }); @@ -283,8 +288,8 @@ async fn windows_hello_authenticate_with_crypto( let signature_buffer = signature.Result()?; let signature_value = unsafe { as_mut_bytes(&signature_buffer)? }; - // The signature is deterministic based on the challenge and keychain key. Thus, it can be hashed to a key. - // It is unclear what entropy this key provides. + // The signature is deterministic based on the challenge and keychain key. Thus, it can be + // hashed to a key. It is unclear what entropy this key provides. let windows_hello_key = Sha256::digest(signature_value).into(); Ok(windows_hello_key) } diff --git a/apps/desktop/desktop_native/core/src/biometric_v2/windows_focus.rs b/apps/desktop/desktop_native/core/src/biometric_v2/windows_focus.rs index f3ffb6e4eb..bf303c88e0 100644 --- a/apps/desktop/desktop_native/core/src/biometric_v2/windows_focus.rs +++ b/apps/desktop/desktop_native/core/src/biometric_v2/windows_focus.rs @@ -34,23 +34,25 @@ pub fn focus_security_prompt() { /// Sets focus to a window using a few unstable methods fn set_focus(hwnd: HWND) { unsafe { - // Windows REALLY does not like apps stealing focus, even if it is for fixing Windows-Hello bugs. - // The windows hello signing prompt NEEDS to be focused instantly, or it will error, but it does - // not focus itself. + // Windows REALLY does not like apps stealing focus, even if it is for fixing Windows-Hello + // bugs. The windows hello signing prompt NEEDS to be focused instantly, or it will + // error, but it does not focus itself. // This function implements forced focusing of windows using a few hacks. // The conditions to successfully foreground a window are: // All of the following conditions are true: - // The calling process belongs to a desktop application, not a UWP app or a Windows Store app designed for Windows 8 or 8.1. - // The foreground process has not disabled calls to SetForegroundWindow by a previous call to the LockSetForegroundWindow function. - // The foreground lock time-out has expired (see SPI_GETFOREGROUNDLOCKTIMEOUT in SystemParametersInfo). - // No menus are active. + // - The calling process belongs to a desktop application, not a UWP app or a Windows + // Store app designed for Windows 8 or 8.1. + // - The foreground process has not disabled calls to SetForegroundWindow by a previous + // call to the LockSetForegroundWindow function. + // - The foreground lock time-out has expired (see SPI_GETFOREGROUNDLOCKTIMEOUT in + // SystemParametersInfo). No menus are active. // Additionally, at least one of the following conditions is true: - // The calling process is the foreground process. - // The calling process was started by the foreground process. - // There is currently no foreground window, and thus no foreground process. - // The calling process received the last input event. - // Either the foreground process or the calling process is being debugged. + // - The calling process is the foreground process. + // - The calling process was started by the foreground process. + // - There is currently no foreground window, and thus no foreground process. + // - The calling process received the last input event. + // - Either the foreground process or the calling process is being debugged. // Update the foreground lock timeout temporarily let mut old_timeout = 0; @@ -75,7 +77,8 @@ fn set_focus(hwnd: HWND) { ); }); - // Attach to the foreground thread once attached, we can foreground, even if in the background + // Attach to the foreground thread once attached, we can foreground, even if in the + // background let dw_current_thread = GetCurrentThreadId(); let dw_fg_thread = GetWindowThreadProcessId(GetForegroundWindow(), None); @@ -91,7 +94,8 @@ fn set_focus(hwnd: HWND) { } } -/// When restoring focus to the application window, we need a less aggressive method so the electron window doesn't get frozen. +/// When restoring focus to the application window, we need a less aggressive method so the electron +/// window doesn't get frozen. pub(crate) fn restore_focus(hwnd: HWND) { unsafe { let _ = SetForegroundWindow(hwnd); diff --git a/apps/desktop/desktop_native/core/src/crypto/crypto.rs b/apps/desktop/desktop_native/core/src/crypto/crypto.rs index d9e2aec304..7991c87ca2 100644 --- a/apps/desktop/desktop_native/core/src/crypto/crypto.rs +++ b/apps/desktop/desktop_native/core/src/crypto/crypto.rs @@ -5,9 +5,8 @@ use aes::cipher::{ BlockEncryptMut, KeyIvInit, }; -use crate::error::{CryptoError, Result}; - use super::CipherString; +use crate::error::{CryptoError, Result}; pub fn decrypt_aes256(iv: &[u8; 16], data: &[u8], key: GenericArray) -> Result> { let iv = GenericArray::from_slice(iv); @@ -16,7 +15,8 @@ pub fn decrypt_aes256(iv: &[u8; 16], data: &[u8], key: GenericArray) -> .decrypt_padded_mut::(&mut data) .map_err(|_| CryptoError::KeyDecrypt)?; - // Data is decrypted in place and returns a subslice of the original Vec, to avoid cloning it, we truncate to the subslice length + // Data is decrypted in place and returns a subslice of the original Vec, to avoid cloning it, + // we truncate to the subslice length let decrypted_len = decrypted_key_slice.len(); data.truncate(decrypted_len); diff --git a/apps/desktop/desktop_native/core/src/error.rs b/apps/desktop/desktop_native/core/src/error.rs index d70d862401..c8d3ec0233 100644 --- a/apps/desktop/desktop_native/core/src/error.rs +++ b/apps/desktop/desktop_native/core/src/error.rs @@ -35,15 +35,4 @@ pub enum KdfParamError { InvalidParams(String), } -// Ensure that the error messages implement Send and Sync -#[cfg(test)] -const _: () = { - fn assert_send() {} - fn assert_sync() {} - fn assert_all() { - assert_send::(); - assert_sync::(); - } -}; - pub type Result = std::result::Result; diff --git a/apps/desktop/desktop_native/core/src/ipc/mod.rs b/apps/desktop/desktop_native/core/src/ipc/mod.rs index 5d4cc9e27f..f806e395d1 100644 --- a/apps/desktop/desktop_native/core/src/ipc/mod.rs +++ b/apps/desktop/desktop_native/core/src/ipc/mod.rs @@ -49,7 +49,8 @@ pub fn path(name: &str) -> std::path::PathBuf { #[cfg(target_os = "macos")] { // When running in an unsandboxed environment, path is: /Users// - // While running sandboxed, it's different: /Users//Library/Containers/com.bitwarden.desktop/Data + // While running sandboxed, it's different: + // /Users//Library/Containers/com.bitwarden.desktop/Data let mut home = dirs::home_dir().unwrap(); // Check if the app is sandboxed by looking for the Containers directory @@ -59,8 +60,9 @@ pub fn path(name: &str) -> std::path::PathBuf { // If the app is sanboxed, we need to use the App Group directory if let Some(position) = containers_position { - // We want to use App Groups in /Users//Library/Group Containers/LTZ2PFU5D6.com.bitwarden.desktop, - // so we need to remove all the components after the user. We can use the previous position to do this. + // We want to use App Groups in /Users//Library/Group + // Containers/LTZ2PFU5D6.com.bitwarden.desktop, so we need to remove all the + // components after the user. We can use the previous position to do this. while home.components().count() > position - 1 { home.pop(); } diff --git a/apps/desktop/desktop_native/core/src/ipc/server.rs b/apps/desktop/desktop_native/core/src/ipc/server.rs index 2762a832ac..a65638303f 100644 --- a/apps/desktop/desktop_native/core/src/ipc/server.rs +++ b/apps/desktop/desktop_native/core/src/ipc/server.rs @@ -3,9 +3,8 @@ use std::{ path::{Path, PathBuf}, }; -use futures::{SinkExt, StreamExt, TryFutureExt}; - use anyhow::Result; +use futures::{SinkExt, StreamExt, TryFutureExt}; use interprocess::local_socket::{tokio::prelude::*, GenericFilePath, ListenerOptions}; use tokio::{ io::{AsyncRead, AsyncWrite}, @@ -42,14 +41,17 @@ impl Server { /// /// # Parameters /// - /// - `name`: The endpoint name to listen on. This name uniquely identifies the IPC connection and must be the same for both the server and client. - /// - `client_to_server_send`: This [`mpsc::Sender`] will receive all the [`Message`]'s that the clients send to this server. + /// - `name`: The endpoint name to listen on. This name uniquely identifies the IPC connection + /// and must be the same for both the server and client. + /// - `client_to_server_send`: This [`mpsc::Sender`] will receive all the [`Message`]'s + /// that the clients send to this server. pub fn start( path: &Path, client_to_server_send: mpsc::Sender, ) -> Result> { - // If the unix socket file already exists, we get an error when trying to bind to it. So we remove it first. - // Any processes that were using the old socket should remain connected to it but any new connections will use the new socket. + // If the unix socket file already exists, we get an error when trying to bind to it. So we + // remove it first. Any processes that were using the old socket should remain + // connected to it but any new connections will use the new socket. if !cfg!(windows) { let _ = std::fs::remove_file(path); } @@ -58,8 +60,9 @@ impl Server { let opts = ListenerOptions::new().name(name); let listener = opts.create_tokio()?; - // This broadcast channel is used for sending messages to all connected clients, and so the sender - // will be stored in the server while the receiver will be cloned and passed to each client handler. + // This broadcast channel is used for sending messages to all connected clients, and so the + // sender will be stored in the server while the receiver will be cloned and passed + // to each client handler. let (server_to_clients_send, server_to_clients_recv) = broadcast::channel::(MESSAGE_CHANNEL_BUFFER); diff --git a/apps/desktop/desktop_native/core/src/password/macos.rs b/apps/desktop/desktop_native/core/src/password/macos.rs index 4f3a16ba4b..72d8ebeb42 100644 --- a/apps/desktop/desktop_native/core/src/password/macos.rs +++ b/apps/desktop/desktop_native/core/src/password/macos.rs @@ -1,9 +1,10 @@ -use crate::password::PASSWORD_NOT_FOUND; use anyhow::Result; use security_framework::passwords::{ delete_generic_password, get_generic_password, set_generic_password, }; +use crate::password::PASSWORD_NOT_FOUND; + #[allow(clippy::unused_async)] pub async fn get_password(service: &str, account: &str) -> Result { let password = get_generic_password(service, account).map_err(convert_error)?; diff --git a/apps/desktop/desktop_native/core/src/password/unix.rs b/apps/desktop/desktop_native/core/src/password/unix.rs index b7595dca28..57b71adefe 100644 --- a/apps/desktop/desktop_native/core/src/password/unix.rs +++ b/apps/desktop/desktop_native/core/src/password/unix.rs @@ -1,9 +1,11 @@ -use crate::password::PASSWORD_NOT_FOUND; +use std::collections::HashMap; + use anyhow::{anyhow, Result}; use oo7::dbus::{self}; -use std::collections::HashMap; use tracing::info; +use crate::password::PASSWORD_NOT_FOUND; + pub async fn get_password(service: &str, account: &str) -> Result { match get_password_new(service, account).await { Ok(res) => Ok(res), diff --git a/apps/desktop/desktop_native/core/src/password/windows.rs b/apps/desktop/desktop_native/core/src/password/windows.rs index ad09019f01..645620b444 100644 --- a/apps/desktop/desktop_native/core/src/password/windows.rs +++ b/apps/desktop/desktop_native/core/src/password/windows.rs @@ -1,4 +1,3 @@ -use crate::password::PASSWORD_NOT_FOUND; use anyhow::{anyhow, Result}; use widestring::{U16CString, U16String}; use windows::{ @@ -12,6 +11,8 @@ use windows::{ }, }; +use crate::password::PASSWORD_NOT_FOUND; + const CRED_FLAGS_NONE: u32 = 0; #[allow(clippy::unused_async)] diff --git a/apps/desktop/desktop_native/core/src/process_isolation/linux.rs b/apps/desktop/desktop_native/core/src/process_isolation/linux.rs index bad348c93e..263cc10b71 100644 --- a/apps/desktop/desktop_native/core/src/process_isolation/linux.rs +++ b/apps/desktop/desktop_native/core/src/process_isolation/linux.rs @@ -4,15 +4,15 @@ use libc::c_uint; use libc::{self, c_int}; use tracing::info; -// RLIMIT_CORE is the maximum size of a core dump file. Setting both to 0 disables core dumps, on crashes -// https://github.com/torvalds/linux/blob/1613e604df0cd359cf2a7fbd9be7a0bcfacfabd0/include/uapi/asm-generic/resource.h#L20 +// RLIMIT_CORE is the maximum size of a core dump file. Setting both to 0 disables core dumps, on +// crashes https://github.com/torvalds/linux/blob/1613e604df0cd359cf2a7fbd9be7a0bcfacfabd0/include/uapi/asm-generic/resource.h#L20 #[cfg(target_env = "musl")] const RLIMIT_CORE: c_int = 4; #[cfg(target_env = "gnu")] const RLIMIT_CORE: c_uint = 4; -// PR_SET_DUMPABLE makes it so no other running process (root or same user) can dump the memory of this process -// or attach a debugger to it. +// PR_SET_DUMPABLE makes it so no other running process (root or same user) can dump the memory of +// this process or attach a debugger to it. // https://github.com/torvalds/linux/blob/a38297e3fb012ddfa7ce0321a7e5a8daeb1872b6/include/uapi/linux/prctl.h#L14 const PR_SET_DUMPABLE: c_int = 4; diff --git a/apps/desktop/desktop_native/core/src/secure_memory/dpapi.rs b/apps/desktop/desktop_native/core/src/secure_memory/dpapi.rs index 3ff8a6d3d8..8d8e10d92c 100644 --- a/apps/desktop/desktop_native/core/src/secure_memory/dpapi.rs +++ b/apps/desktop/desktop_native/core/src/secure_memory/dpapi.rs @@ -29,8 +29,9 @@ impl SecureMemoryStore for DpapiSecretKVStore { fn put(&mut self, key: String, value: &[u8]) { let length_header_len = std::mem::size_of::(); - // The allocated data has to be a multiple of CRYPTPROTECTMEMORY_BLOCK_SIZE, so we pad it and write the length in front - // We are storing LENGTH|DATA|00..00, where LENGTH is the length of DATA, the total length is a multiple + // The allocated data has to be a multiple of CRYPTPROTECTMEMORY_BLOCK_SIZE, so we pad it + // and write the length in front We are storing LENGTH|DATA|00..00, where LENGTH is + // the length of DATA, the total length is a multiple // of CRYPTPROTECTMEMORY_BLOCK_SIZE, and the padding is filled with zeros. let data_len = value.len(); diff --git a/apps/desktop/desktop_native/core/src/secure_memory/encrypted_memory_store.rs b/apps/desktop/desktop_native/core/src/secure_memory/encrypted_memory_store.rs index a8952d8f55..d116e564bc 100644 --- a/apps/desktop/desktop_native/core/src/secure_memory/encrypted_memory_store.rs +++ b/apps/desktop/desktop_native/core/src/secure_memory/encrypted_memory_store.rs @@ -10,8 +10,8 @@ use crate::secure_memory::{ /// allows circumventing length and amount limitations on platform specific secure memory APIs since /// only a single short item needs to be protected. /// -/// The key is briefly in process memory during encryption and decryption, in memory that is protected -/// from swapping to disk via mlock, and then zeroed out immediately after use. +/// The key is briefly in process memory during encryption and decryption, in memory that is +/// protected from swapping to disk via mlock, and then zeroed out immediately after use. #[allow(unused)] pub(crate) struct EncryptedMemoryStore { map: std::collections::HashMap, diff --git a/apps/desktop/desktop_native/core/src/secure_memory/secure_key/crypto.rs b/apps/desktop/desktop_native/core/src/secure_memory/secure_key/crypto.rs index 1ee6c4cdf4..7e2917ade6 100644 --- a/apps/desktop/desktop_native/core/src/secure_memory/secure_key/crypto.rs +++ b/apps/desktop/desktop_native/core/src/secure_memory/secure_key/crypto.rs @@ -6,9 +6,9 @@ use rand::{rng, Rng}; pub(super) const KEY_SIZE: usize = 32; pub(super) const NONCE_SIZE: usize = 24; -/// The encryption performed here is xchacha-poly1305. Any tampering with the key or the ciphertexts will result -/// in a decryption failure and panic. The key's memory contents are protected from being swapped to disk -/// via mlock. +/// The encryption performed here is xchacha-poly1305. Any tampering with the key or the ciphertexts +/// will result in a decryption failure and panic. The key's memory contents are protected from +/// being swapped to disk via mlock. pub(super) struct MemoryEncryptionKey(NonNull<[u8]>); /// An encrypted memory blob that must be decrypted using the same key that it was encrypted with. diff --git a/apps/desktop/desktop_native/core/src/secure_memory/secure_key/dpapi.rs b/apps/desktop/desktop_native/core/src/secure_memory/secure_key/dpapi.rs index 0975b54287..52b75d94a0 100644 --- a/apps/desktop/desktop_native/core/src/secure_memory/secure_key/dpapi.rs +++ b/apps/desktop/desktop_native/core/src/secure_memory/secure_key/dpapi.rs @@ -1,10 +1,13 @@ -use super::crypto::{MemoryEncryptionKey, KEY_SIZE}; -use super::SecureKeyContainer; use windows::Win32::Security::Cryptography::{ CryptProtectMemory, CryptUnprotectMemory, CRYPTPROTECTMEMORY_BLOCK_SIZE, CRYPTPROTECTMEMORY_SAME_PROCESS, }; +use super::{ + crypto::{MemoryEncryptionKey, KEY_SIZE}, + SecureKeyContainer, +}; + /// https://learn.microsoft.com/en-us/windows/win32/api/dpapi/nf-dpapi-cryptprotectdata /// The DPAPI store encrypts data using the Windows Data Protection API (DPAPI). The key is bound /// to the current process, and cannot be decrypted by other user-mode processes. diff --git a/apps/desktop/desktop_native/core/src/secure_memory/secure_key/keyctl.rs b/apps/desktop/desktop_native/core/src/secure_memory/secure_key/keyctl.rs index a738d96467..29c6275974 100644 --- a/apps/desktop/desktop_native/core/src/secure_memory/secure_key/keyctl.rs +++ b/apps/desktop/desktop_native/core/src/secure_memory/secure_key/keyctl.rs @@ -1,9 +1,8 @@ -use crate::secure_memory::secure_key::crypto::MemoryEncryptionKey; - -use super::crypto::KEY_SIZE; -use super::SecureKeyContainer; use linux_keyutils::{KeyRing, KeyRingIdentifier}; +use super::{crypto::KEY_SIZE, SecureKeyContainer}; +use crate::secure_memory::secure_key::crypto::MemoryEncryptionKey; + /// The keys are bound to the process keyring. const KEY_RING_IDENTIFIER: KeyRingIdentifier = KeyRingIdentifier::Process; /// This is an atomic global counter used to help generate unique key IDs @@ -26,9 +25,9 @@ pub(super) struct KeyctlSecureKeyContainer { id: String, } -// SAFETY: The key id is fully owned by this struct and not exposed or cloned, and cleaned up on drop. -// Further, since we use `KeyRingIdentifier::Process` and not `KeyRingIdentifier::Thread`, the key -// is accessible across threads within the same process bound. +// SAFETY: The key id is fully owned by this struct and not exposed or cloned, and cleaned up on +// drop. Further, since we use `KeyRingIdentifier::Process` and not `KeyRingIdentifier::Thread`, the +// key is accessible across threads within the same process bound. unsafe impl Send for KeyctlSecureKeyContainer {} // SAFETY: The container is non-mutable and thus safe to share between threads. unsafe impl Sync for KeyctlSecureKeyContainer {} diff --git a/apps/desktop/desktop_native/core/src/secure_memory/secure_key/memfd_secret.rs b/apps/desktop/desktop_native/core/src/secure_memory/secure_key/memfd_secret.rs index 4e6a2c4d7a..e9f96db314 100644 --- a/apps/desktop/desktop_native/core/src/secure_memory/secure_key/memfd_secret.rs +++ b/apps/desktop/desktop_native/core/src/secure_memory/secure_key/memfd_secret.rs @@ -1,8 +1,9 @@ use std::{ptr::NonNull, sync::LazyLock}; -use super::crypto::MemoryEncryptionKey; -use super::crypto::KEY_SIZE; -use super::SecureKeyContainer; +use super::{ + crypto::{MemoryEncryptionKey, KEY_SIZE}, + SecureKeyContainer, +}; /// https://man.archlinux.org/man/memfd_secret.2.en /// The memfd_secret store protects the data using the `memfd_secret` syscall. The @@ -15,8 +16,8 @@ pub(super) struct MemfdSecretSecureKeyContainer { // SAFETY: The pointers in this struct are allocated by `memfd_secret`, and we have full ownership. // They are never exposed outside or cloned, and are cleaned up by drop. unsafe impl Send for MemfdSecretSecureKeyContainer {} -// SAFETY: The container is non-mutable and thus safe to share between threads. Further, memfd-secret -// is accessible across threads within the same process bound. +// SAFETY: The container is non-mutable and thus safe to share between threads. Further, +// memfd-secret is accessible across threads within the same process bound. unsafe impl Sync for MemfdSecretSecureKeyContainer {} impl SecureKeyContainer for MemfdSecretSecureKeyContainer { diff --git a/apps/desktop/desktop_native/core/src/secure_memory/secure_key/mlock.rs b/apps/desktop/desktop_native/core/src/secure_memory/secure_key/mlock.rs index db21cd7fed..961988c1d4 100644 --- a/apps/desktop/desktop_native/core/src/secure_memory/secure_key/mlock.rs +++ b/apps/desktop/desktop_native/core/src/secure_memory/secure_key/mlock.rs @@ -1,8 +1,9 @@ use std::ptr::NonNull; -use super::crypto::MemoryEncryptionKey; -use super::crypto::KEY_SIZE; -use super::SecureKeyContainer; +use super::{ + crypto::{MemoryEncryptionKey, KEY_SIZE}, + SecureKeyContainer, +}; /// A SecureKeyContainer that uses mlock to prevent the memory from being swapped to disk. /// This does not provide as strong protections as other methods, but is always supported. diff --git a/apps/desktop/desktop_native/core/src/secure_memory/secure_key/mod.rs b/apps/desktop/desktop_native/core/src/secure_memory/secure_key/mod.rs index 6c3b53117a..26e72f7d58 100644 --- a/apps/desktop/desktop_native/core/src/secure_memory/secure_key/mod.rs +++ b/apps/desktop/desktop_native/core/src/secure_memory/secure_key/mod.rs @@ -1,9 +1,12 @@ -//! This module provides hardened storage for single cryptographic keys. These are meant for encrypting large amounts of memory. -//! Some platforms restrict how many keys can be protected by their APIs, which necessitates this layer of indirection. This significantly -//! reduces the complexity of each platform specific implementation, since all that's needed is implementing protecting a single fixed sized key -//! instead of protecting many arbitrarily sized secrets. This significantly lowers the effort to maintain each implementation. +//! This module provides hardened storage for single cryptographic keys. These are meant for +//! encrypting large amounts of memory. Some platforms restrict how many keys can be protected by +//! their APIs, which necessitates this layer of indirection. This significantly reduces the +//! complexity of each platform specific implementation, since all that's needed is implementing +//! protecting a single fixed sized key instead of protecting many arbitrarily sized secrets. This +//! significantly lowers the effort to maintain each implementation. //! -//! The implementations include DPAPI on Windows, `keyctl` on Linux, and `memfd_secret` on Linux, and a fallback implementation using mlock. +//! The implementations include DPAPI on Windows, `keyctl` on Linux, and `memfd_secret` on Linux, +//! and a fallback implementation using mlock. use tracing::info; @@ -20,12 +23,13 @@ pub use crypto::EncryptedMemory; use crate::secure_memory::secure_key::crypto::DecryptionError; -/// An ephemeral key that is protected using a platform mechanism. It is generated on construction freshly, and can be used -/// to encrypt and decrypt segments of memory. Since the key is ephemeral, persistent data cannot be encrypted with this key. -/// On Linux and Windows, in most cases the protection mechanisms prevent memory dumps/debuggers from reading the key. +/// An ephemeral key that is protected using a platform mechanism. It is generated on construction +/// freshly, and can be used to encrypt and decrypt segments of memory. Since the key is ephemeral, +/// persistent data cannot be encrypted with this key. On Linux and Windows, in most cases the +/// protection mechanisms prevent memory dumps/debuggers from reading the key. /// -/// Note: This can be circumvented if code can be injected into the process and is only effective in combination with the -/// memory isolation provided in `process_isolation`. +/// Note: This can be circumvented if code can be injected into the process and is only effective in +/// combination with the memory isolation provided in `process_isolation`. /// - https://github.com/zer1t0/keydump #[allow(unused)] pub(crate) struct SecureMemoryEncryptionKey(CrossPlatformSecureKeyContainer); @@ -55,7 +59,8 @@ impl SecureMemoryEncryptionKey { /// from memory attacks. #[allow(unused)] trait SecureKeyContainer: Sync + Send { - /// Returns the key as a byte slice. This slice does not have additional memory protections applied. + /// Returns the key as a byte slice. This slice does not have additional memory protections + /// applied. fn as_key(&self) -> crypto::MemoryEncryptionKey; /// Creates a new SecureKeyContainer from the provided key. fn from_key(key: crypto::MemoryEncryptionKey) -> Self; diff --git a/apps/desktop/desktop_native/core/src/ssh_agent/mod.rs b/apps/desktop/desktop_native/core/src/ssh_agent/mod.rs index 61cb8fc187..8ba64618ff 100644 --- a/apps/desktop/desktop_native/core/src/ssh_agent/mod.rs +++ b/apps/desktop/desktop_native/core/src/ssh_agent/mod.rs @@ -7,13 +7,12 @@ use std::{ }; use base64::{engine::general_purpose::STANDARD, Engine as _}; -use tokio::sync::Mutex; -use tokio_util::sync::CancellationToken; - use bitwarden_russh::{ session_bind::SessionBindResult, ssh_agent::{self, SshKey}, }; +use tokio::sync::Mutex; +use tokio_util::sync::CancellationToken; use tracing::{error, info}; #[cfg_attr(target_os = "windows", path = "windows.rs")] @@ -34,7 +33,8 @@ pub struct BitwardenDesktopAgent { show_ui_request_tx: tokio::sync::mpsc::Sender, get_ui_response_rx: Arc>>, request_id: Arc, - /// before first unlock, or after account switching, listing keys should require an unlock to get a list of public keys + /// before first unlock, or after account switching, listing keys should require an unlock to + /// get a list of public keys needs_unlock: Arc, is_running: Arc, } diff --git a/apps/desktop/desktop_native/core/src/ssh_agent/named_pipe_listener_stream.rs b/apps/desktop/desktop_native/core/src/ssh_agent/named_pipe_listener_stream.rs index cb10e873a3..38b2193faf 100644 --- a/apps/desktop/desktop_native/core/src/ssh_agent/named_pipe_listener_stream.rs +++ b/apps/desktop/desktop_native/core/src/ssh_agent/named_pipe_listener_stream.rs @@ -1,7 +1,6 @@ -use futures::Stream; -use std::os::windows::prelude::AsRawHandle as _; use std::{ io, + os::windows::prelude::AsRawHandle as _, pin::Pin, sync::{ atomic::{AtomicBool, Ordering}, @@ -9,6 +8,8 @@ use std::{ }, task::{Context, Poll}, }; + +use futures::Stream; use tokio::{ net::windows::named_pipe::{NamedPipeServer, ServerOptions}, select, diff --git a/apps/desktop/desktop_native/core/src/ssh_agent/peercred_unix_listener_stream.rs b/apps/desktop/desktop_native/core/src/ssh_agent/peercred_unix_listener_stream.rs index 77eec5e35c..5b6b1d8f36 100644 --- a/apps/desktop/desktop_native/core/src/ssh_agent/peercred_unix_listener_stream.rs +++ b/apps/desktop/desktop_native/core/src/ssh_agent/peercred_unix_listener_stream.rs @@ -1,11 +1,13 @@ +use std::{ + io, + pin::Pin, + task::{Context, Poll}, +}; + use futures::Stream; -use std::io; -use std::pin::Pin; -use std::task::{Context, Poll}; use tokio::net::{UnixListener, UnixStream}; -use super::peerinfo; -use super::peerinfo::models::PeerInfo; +use super::{peerinfo, peerinfo::models::PeerInfo}; #[derive(Debug)] pub struct PeercredUnixListenerStream { diff --git a/apps/desktop/desktop_native/core/src/ssh_agent/peerinfo/models.rs b/apps/desktop/desktop_native/core/src/ssh_agent/peerinfo/models.rs index fad535cb80..74b909f5ce 100644 --- a/apps/desktop/desktop_native/core/src/ssh_agent/peerinfo/models.rs +++ b/apps/desktop/desktop_native/core/src/ssh_agent/peerinfo/models.rs @@ -1,9 +1,10 @@ use std::sync::{atomic::AtomicBool, Arc, Mutex}; /** -* Peerinfo represents the information of a peer process connecting over a socket. -* This can be later extended to include more information (icon, app name) for the corresponding application. -*/ + * Peerinfo represents the information of a peer process connecting over a socket. + * This can be later extended to include more information (icon, app name) for the corresponding + * application. + */ #[derive(Debug, Clone)] pub struct PeerInfo { uid: u32, diff --git a/apps/desktop/desktop_native/core/src/ssh_agent/unix.rs b/apps/desktop/desktop_native/core/src/ssh_agent/unix.rs index a45c2f6c0b..8623df1377 100644 --- a/apps/desktop/desktop_native/core/src/ssh_agent/unix.rs +++ b/apps/desktop/desktop_native/core/src/ssh_agent/unix.rs @@ -6,9 +6,8 @@ use homedir::my_home; use tokio::{net::UnixListener, sync::Mutex}; use tracing::{error, info}; -use crate::ssh_agent::peercred_unix_listener_stream::PeercredUnixListenerStream; - use super::{BitwardenDesktopAgent, SshAgentUIRequest}; +use crate::ssh_agent::peercred_unix_listener_stream::PeercredUnixListenerStream; /// User can override the default socket path with this env var const ENV_BITWARDEN_SSH_AUTH_SOCK: &str = "BITWARDEN_SSH_AUTH_SOCK"; diff --git a/apps/desktop/desktop_native/core/src/ssh_agent/windows.rs b/apps/desktop/desktop_native/core/src/ssh_agent/windows.rs index 662a4658ed..2012dab2d7 100644 --- a/apps/desktop/desktop_native/core/src/ssh_agent/windows.rs +++ b/apps/desktop/desktop_native/core/src/ssh_agent/windows.rs @@ -2,6 +2,7 @@ use bitwarden_russh::ssh_agent; pub mod named_pipe_listener_stream; use std::sync::Arc; + use tokio::sync::Mutex; use super::{BitwardenDesktopAgent, SshAgentUIRequest}; diff --git a/apps/desktop/desktop_native/macos_provider/Cargo.toml b/apps/desktop/desktop_native/macos_provider/Cargo.toml index ea44f3d9a2..50f1834851 100644 --- a/apps/desktop/desktop_native/macos_provider/Cargo.toml +++ b/apps/desktop/desktop_native/macos_provider/Cargo.toml @@ -14,17 +14,16 @@ crate-type = ["staticlib", "cdylib"] bench = false [dependencies] +uniffi = { workspace = true, features = ["cli"] } + +[target.'cfg(target_os = "macos")'.dependencies] desktop_core = { path = "../core" } futures = { workspace = true } serde = { workspace = true, features = ["derive"] } serde_json = { workspace = true } tokio = { workspace = true, features = ["sync"] } -tokio-util = { workspace = true } tracing = { workspace = true } tracing-subscriber = { workspace = true } -uniffi = { workspace = true, features = ["cli"] } - -[target.'cfg(target_os = "macos")'.dependencies] tracing-oslog = "0.3.0" [build-dependencies] diff --git a/apps/desktop/desktop_native/napi/Cargo.toml b/apps/desktop/desktop_native/napi/Cargo.toml index 4198baa4b5..b5847a602d 100644 --- a/apps/desktop/desktop_native/napi/Cargo.toml +++ b/apps/desktop/desktop_native/napi/Cargo.toml @@ -16,17 +16,13 @@ manual_test = [] [dependencies] anyhow = { workspace = true } autotype = { path = "../autotype" } -base64 = { workspace = true } chromium_importer = { path = "../chromium_importer" } desktop_core = { path = "../core" } -hex = { workspace = true } napi = { workspace = true, features = ["async"] } napi-derive = { workspace = true } serde = { workspace = true, features = ["derive"] } serde_json = { workspace = true } tokio = { workspace = true } -tokio-stream = { workspace = true } -tokio-util = { workspace = true } tracing = { workspace = true } tracing-subscriber = { workspace = true } diff --git a/apps/desktop/desktop_native/napi/index.d.ts b/apps/desktop/desktop_native/napi/index.d.ts index 0a8beb8c42..01bfa65d57 100644 --- a/apps/desktop/desktop_native/napi/index.d.ts +++ b/apps/desktop/desktop_native/napi/index.d.ts @@ -11,7 +11,10 @@ export declare namespace passwords { * Throws {@link Error} with message {@link PASSWORD_NOT_FOUND} if the password does not exist. */ export function getPassword(service: string, account: string): Promise - /** Save the password to the keychain. Adds an entry if none exists otherwise updates the existing entry. */ + /** + * Save the password to the keychain. Adds an entry if none exists otherwise updates the + * existing entry. + */ export function setPassword(service: string, account: string, password: string): Promise /** * Delete the stored password from the keychain. @@ -35,7 +38,8 @@ export declare namespace biometrics { * base64 encoded key and the base64 encoded challenge used to create it * separated by a `|` character. * - * If the iv is provided, it will be used as the challenge. Otherwise a random challenge will be generated. + * If the iv is provided, it will be used as the challenge. Otherwise a random challenge will + * be generated. * * `format!("|")` */ @@ -119,8 +123,9 @@ export declare namespace ipc { /** * Create and start the IPC server without blocking. * - * @param name The endpoint name to listen on. This name uniquely identifies the IPC connection and must be the same for both the server and client. - * @param callback This function will be called whenever a message is received from a client. + * @param name The endpoint name to listen on. This name uniquely identifies the IPC + * connection and must be the same for both the server and client. @param callback + * This function will be called whenever a message is received from a client. */ static listen(name: string, callback: (error: null | Error, message: IpcMessage) => void): Promise /** Return the path to the IPC server. */ @@ -130,8 +135,9 @@ export declare namespace ipc { /** * Send a message over the IPC server to all the connected clients * - * @return The number of clients that the message was sent to. Note that the number of messages - * actually received may be less, as some clients could disconnect before receiving the message. + * @return The number of clients that the message was sent to. Note that the number of + * messages actually received may be less, as some clients could disconnect before + * receiving the message. */ send(message: string): number } @@ -194,8 +200,9 @@ export declare namespace autofill { /** * Create and start the IPC server without blocking. * - * @param name The endpoint name to listen on. This name uniquely identifies the IPC connection and must be the same for both the server and client. - * @param callback This function will be called whenever a message is received from a client. + * @param name The endpoint name to listen on. This name uniquely identifies the IPC + * connection and must be the same for both the server and client. @param callback + * This function will be called whenever a message is received from a client. */ static listen(name: string, registrationCallback: (error: null | Error, clientId: number, sequenceNumber: number, message: PasskeyRegistrationRequest) => void, assertionCallback: (error: null | Error, clientId: number, sequenceNumber: number, message: PasskeyAssertionRequest) => void, assertionWithoutUserInterfaceCallback: (error: null | Error, clientId: number, sequenceNumber: number, message: PasskeyAssertionWithoutUserInterfaceRequest) => void): Promise /** Return the path to the IPC server. */ diff --git a/apps/desktop/desktop_native/napi/src/lib.rs b/apps/desktop/desktop_native/napi/src/lib.rs index 01d60ff5f5..c34e7574f6 100644 --- a/apps/desktop/desktop_native/napi/src/lib.rs +++ b/apps/desktop/desktop_native/napi/src/lib.rs @@ -19,7 +19,8 @@ pub mod passwords { .map_err(|e| napi::Error::from_reason(e.to_string())) } - /// Save the password to the keychain. Adds an entry if none exists otherwise updates the existing entry. + /// Save the password to the keychain. Adds an entry if none exists otherwise updates the + /// existing entry. #[napi] pub async fn set_password( service: String, @@ -107,7 +108,8 @@ pub mod biometrics { /// base64 encoded key and the base64 encoded challenge used to create it /// separated by a `|` character. /// - /// If the iv is provided, it will be used as the challenge. Otherwise a random challenge will be generated. + /// If the iv is provided, it will be used as the challenge. Otherwise a random challenge will + /// be generated. /// /// `format!("|")` #[allow(clippy::unused_async)] // FIXME: Remove unused async! @@ -556,8 +558,9 @@ pub mod ipc { impl IpcServer { /// Create and start the IPC server without blocking. /// - /// @param name The endpoint name to listen on. This name uniquely identifies the IPC connection and must be the same for both the server and client. - /// @param callback This function will be called whenever a message is received from a client. + /// @param name The endpoint name to listen on. This name uniquely identifies the IPC + /// connection and must be the same for both the server and client. @param callback + /// This function will be called whenever a message is received from a client. #[allow(clippy::unused_async)] // FIXME: Remove unused async! #[napi(factory)] pub async fn listen( @@ -598,8 +601,9 @@ pub mod ipc { /// Send a message over the IPC server to all the connected clients /// - /// @return The number of clients that the message was sent to. Note that the number of messages - /// actually received may be less, as some clients could disconnect before receiving the message. + /// @return The number of clients that the message was sent to. Note that the number of + /// messages actually received may be less, as some clients could disconnect before + /// receiving the message. #[napi] pub fn send(&self, message: String) -> napi::Result { self.server @@ -743,8 +747,9 @@ pub mod autofill { impl IpcServer { /// Create and start the IPC server without blocking. /// - /// @param name The endpoint name to listen on. This name uniquely identifies the IPC connection and must be the same for both the server and client. - /// @param callback This function will be called whenever a message is received from a client. + /// @param name The endpoint name to listen on. This name uniquely identifies the IPC + /// connection and must be the same for both the server and client. @param callback + /// This function will be called whenever a message is received from a client. #[allow(clippy::unused_async)] // FIXME: Remove unused async! #[napi(factory)] pub async fn listen( @@ -946,18 +951,21 @@ pub mod logging { //! //! # Example //! - //! [Elec] 14:34:03.517 › [NAPI] [INFO] desktop_core::ssh_agent::platform_ssh_agent: Starting SSH Agent server {socket=/Users/foo/.bitwarden-ssh-agent.sock} + //! [Elec] 14:34:03.517 › [NAPI] [INFO] desktop_core::ssh_agent::platform_ssh_agent: Starting + //! SSH Agent server {socket=/Users/foo/.bitwarden-ssh-agent.sock} - use std::fmt::Write; - use std::sync::OnceLock; + use std::{fmt::Write, sync::OnceLock}; use napi::threadsafe_function::{ ErrorStrategy::CalleeHandled, ThreadsafeFunction, ThreadsafeFunctionCallMode, }; use tracing::Level; - use tracing_subscriber::fmt::format::{DefaultVisitor, Writer}; use tracing_subscriber::{ - filter::EnvFilter, layer::SubscriberExt, util::SubscriberInitExt, Layer, + filter::EnvFilter, + fmt::format::{DefaultVisitor, Writer}, + layer::SubscriberExt, + util::SubscriberInitExt, + Layer, }; struct JsLogger(OnceLock>); @@ -1069,6 +1077,8 @@ pub mod logging { #[napi] pub mod chromium_importer { + use std::collections::HashMap; + use chromium_importer::{ chromium::{ DefaultInstalledBrowserRetriever, LoginImportResult as _LoginImportResult, @@ -1076,7 +1086,6 @@ pub mod chromium_importer { }, metadata::NativeImporterMetadata as _NativeImporterMetadata, }; - use std::collections::HashMap; #[napi(object)] pub struct ProfileInfo { diff --git a/apps/desktop/desktop_native/objc/Cargo.toml b/apps/desktop/desktop_native/objc/Cargo.toml index fc8910bddd..c161b8226b 100644 --- a/apps/desktop/desktop_native/objc/Cargo.toml +++ b/apps/desktop/desktop_native/objc/Cargo.toml @@ -8,16 +8,12 @@ publish = { workspace = true } [features] default = [] -[dependencies] +[target.'cfg(target_os = "macos")'.dependencies] anyhow = { workspace = true } -thiserror = { workspace = true } tokio = { workspace = true } tracing = { workspace = true } -[target.'cfg(target_os = "macos")'.dependencies] -core-foundation = "=0.10.1" - -[build-dependencies] +[target.'cfg(target_os = "macos")'.build-dependencies] cc = "=1.2.4" glob = "=0.3.2" diff --git a/apps/desktop/desktop_native/process_isolation/Cargo.toml b/apps/desktop/desktop_native/process_isolation/Cargo.toml index 170832c2fd..d8c6c7a618 100644 --- a/apps/desktop/desktop_native/process_isolation/Cargo.toml +++ b/apps/desktop/desktop_native/process_isolation/Cargo.toml @@ -8,7 +8,7 @@ publish = { workspace = true } [lib] crate-type = ["cdylib"] -[dependencies] +[target.'cfg(target_os = "linux")'.dependencies] ctor = { workspace = true } desktop_core = { path = "../core" } libc = { workspace = true } diff --git a/apps/desktop/desktop_native/process_isolation/src/lib.rs b/apps/desktop/desktop_native/process_isolation/src/lib.rs index 850ffac841..55c5d7fafa 100644 --- a/apps/desktop/desktop_native/process_isolation/src/lib.rs +++ b/apps/desktop/desktop_native/process_isolation/src/lib.rs @@ -5,8 +5,9 @@ //! On Linux, this is PR_SET_DUMPABLE to prevent debuggers from attaching, the env //! from being read and the memory from being stolen. -use desktop_core::process_isolation; use std::{ffi::c_char, sync::LazyLock}; + +use desktop_core::process_isolation; use tracing::info; static ORIGINAL_UNSETENV: LazyLock i32> = diff --git a/apps/desktop/desktop_native/proxy/Cargo.toml b/apps/desktop/desktop_native/proxy/Cargo.toml index c672f57543..25682fe2aa 100644 --- a/apps/desktop/desktop_native/proxy/Cargo.toml +++ b/apps/desktop/desktop_native/proxy/Cargo.toml @@ -6,7 +6,6 @@ version = { workspace = true } publish = { workspace = true } [dependencies] -anyhow = { workspace = true } desktop_core = { path = "../core" } futures = { workspace = true } tokio = { workspace = true, features = ["io-std", "io-util", "macros", "rt"] } diff --git a/apps/desktop/desktop_native/proxy/src/main.rs b/apps/desktop/desktop_native/proxy/src/main.rs index c2c525b865..21957d8ba3 100644 --- a/apps/desktop/desktop_native/proxy/src/main.rs +++ b/apps/desktop/desktop_native/proxy/src/main.rs @@ -60,7 +60,6 @@ fn init_logging(log_path: &Path, console_level: LevelFilter, file_level: LevelFi /// a stable communication channel between the proxy and the running desktop application. /// /// Browser extension <-[native messaging]-> proxy <-[ipc]-> desktop -/// // FIXME: Remove unwraps! They panic and terminate the whole application. #[allow(clippy::unwrap_used)] #[tokio::main(flavor = "current_thread")] @@ -83,8 +82,10 @@ async fn main() { // Different browsers send different arguments when the app starts: // // Firefox: - // - The complete path to the app manifest. (in the form `/Users//Library/.../Mozilla/NativeMessagingHosts/com.8bit.bitwarden.json`) - // - (in Firefox 55+) the ID (as given in the manifest.json) of the add-on that started it (in the form `{[UUID]}`). + // - The complete path to the app manifest. (in the form + // `/Users//Library/.../Mozilla/NativeMessagingHosts/com.8bit.bitwarden.json`) + // - (in Firefox 55+) the ID (as given in the manifest.json) of the add-on that started it (in + // the form `{[UUID]}`). // // Chrome on Windows: // - Origin of the extension that started it (in the form `chrome-extension://[ID]`). @@ -96,7 +97,8 @@ async fn main() { let args: Vec<_> = std::env::args().skip(1).collect(); info!(?args, "Process args"); - // Setup two channels, one for sending messages to the desktop application (`out`) and one for receiving messages from the desktop application (`in`) + // Setup two channels, one for sending messages to the desktop application (`out`) and one for + // receiving messages from the desktop application (`in`) let (in_send, in_recv) = tokio::sync::mpsc::channel(MESSAGE_CHANNEL_BUFFER); let (out_send, mut out_recv) = tokio::sync::mpsc::channel(MESSAGE_CHANNEL_BUFFER); diff --git a/apps/desktop/desktop_native/rustfmt.toml b/apps/desktop/desktop_native/rustfmt.toml new file mode 100644 index 0000000000..bb3baeccd7 --- /dev/null +++ b/apps/desktop/desktop_native/rustfmt.toml @@ -0,0 +1,7 @@ +# Wrap comments and increase the width of comments to 100 +comment_width = 100 +wrap_comments = true + +# Sort and group imports +group_imports = "StdExternalCrate" +imports_granularity = "Crate" diff --git a/apps/desktop/desktop_native/windows_plugin_authenticator/src/lib.rs b/apps/desktop/desktop_native/windows_plugin_authenticator/src/lib.rs index 2e4f453d8f..893fdf765f 100644 --- a/apps/desktop/desktop_native/windows_plugin_authenticator/src/lib.rs +++ b/apps/desktop/desktop_native/windows_plugin_authenticator/src/lib.rs @@ -2,11 +2,12 @@ #![allow(non_snake_case)] #![allow(non_camel_case_types)] -use std::ffi::c_uchar; -use std::ptr; -use windows::Win32::Foundation::*; -use windows::Win32::System::Com::*; -use windows::Win32::System::LibraryLoader::*; +use std::{ffi::c_uchar, ptr}; + +use windows::Win32::{ + Foundation::*, + System::{Com::*, LibraryLoader::*}, +}; use windows_core::*; mod pluginauthenticator; From 0912d1abe8f280be48f6c28cb932d6407bb22341 Mon Sep 17 00:00:00 2001 From: "bw-ghapp[bot]" <178206702+bw-ghapp[bot]@users.noreply.github.com> Date: Wed, 19 Nov 2025 18:31:02 +0100 Subject: [PATCH 25/52] Autosync the updated translations (#17462) Co-authored-by: bitwarden-devops-bot <106330231+bitwarden-devops-bot@users.noreply.github.com> --- apps/web/src/locales/af/messages.json | 72 ++++++------- apps/web/src/locales/ar/messages.json | 72 ++++++------- apps/web/src/locales/az/messages.json | 82 +++++++-------- apps/web/src/locales/be/messages.json | 72 ++++++------- apps/web/src/locales/bg/messages.json | 78 +++++++------- apps/web/src/locales/bn/messages.json | 72 ++++++------- apps/web/src/locales/bs/messages.json | 72 ++++++------- apps/web/src/locales/ca/messages.json | 72 ++++++------- apps/web/src/locales/cs/messages.json | 70 ++++++------- apps/web/src/locales/cy/messages.json | 72 ++++++------- apps/web/src/locales/da/messages.json | 72 ++++++------- apps/web/src/locales/de/messages.json | 84 +++++++-------- apps/web/src/locales/el/messages.json | 72 ++++++------- apps/web/src/locales/en_GB/messages.json | 72 ++++++------- apps/web/src/locales/en_IN/messages.json | 72 ++++++------- apps/web/src/locales/eo/messages.json | 72 ++++++------- apps/web/src/locales/es/messages.json | 72 ++++++------- apps/web/src/locales/et/messages.json | 72 ++++++------- apps/web/src/locales/eu/messages.json | 72 ++++++------- apps/web/src/locales/fa/messages.json | 72 ++++++------- apps/web/src/locales/fi/messages.json | 72 ++++++------- apps/web/src/locales/fil/messages.json | 72 ++++++------- apps/web/src/locales/fr/messages.json | 78 +++++++------- apps/web/src/locales/gl/messages.json | 72 ++++++------- apps/web/src/locales/he/messages.json | 128 +++++++++++------------ apps/web/src/locales/hi/messages.json | 72 ++++++------- apps/web/src/locales/hr/messages.json | 74 ++++++------- apps/web/src/locales/hu/messages.json | 74 ++++++------- apps/web/src/locales/id/messages.json | 74 ++++++------- apps/web/src/locales/it/messages.json | 72 ++++++------- apps/web/src/locales/ja/messages.json | 72 ++++++------- apps/web/src/locales/ka/messages.json | 72 ++++++------- apps/web/src/locales/km/messages.json | 72 ++++++------- apps/web/src/locales/kn/messages.json | 72 ++++++------- apps/web/src/locales/ko/messages.json | 72 ++++++------- apps/web/src/locales/lv/messages.json | 74 ++++++------- apps/web/src/locales/ml/messages.json | 72 ++++++------- apps/web/src/locales/mr/messages.json | 72 ++++++------- apps/web/src/locales/my/messages.json | 72 ++++++------- apps/web/src/locales/nb/messages.json | 72 ++++++------- apps/web/src/locales/ne/messages.json | 72 ++++++------- apps/web/src/locales/nl/messages.json | 74 ++++++------- apps/web/src/locales/nn/messages.json | 72 ++++++------- apps/web/src/locales/or/messages.json | 72 ++++++------- apps/web/src/locales/pl/messages.json | 72 ++++++------- apps/web/src/locales/pt_BR/messages.json | 72 ++++++------- apps/web/src/locales/pt_PT/messages.json | 76 +++++++------- apps/web/src/locales/ro/messages.json | 72 ++++++------- apps/web/src/locales/ru/messages.json | 72 ++++++------- apps/web/src/locales/si/messages.json | 72 ++++++------- apps/web/src/locales/sk/messages.json | 102 +++++++++--------- apps/web/src/locales/sl/messages.json | 72 ++++++------- apps/web/src/locales/sr_CS/messages.json | 72 ++++++------- apps/web/src/locales/sr_CY/messages.json | 74 ++++++------- apps/web/src/locales/sv/messages.json | 80 +++++++------- apps/web/src/locales/ta/messages.json | 72 ++++++------- apps/web/src/locales/te/messages.json | 72 ++++++------- apps/web/src/locales/th/messages.json | 72 ++++++------- apps/web/src/locales/tr/messages.json | 74 ++++++------- apps/web/src/locales/uk/messages.json | 72 ++++++------- apps/web/src/locales/vi/messages.json | 74 ++++++------- apps/web/src/locales/zh_CN/messages.json | 104 +++++++++--------- apps/web/src/locales/zh_TW/messages.json | 78 +++++++------- 63 files changed, 2171 insertions(+), 2549 deletions(-) diff --git a/apps/web/src/locales/af/messages.json b/apps/web/src/locales/af/messages.json index 684e107cd5..2fee7410e9 100644 --- a/apps/web/src/locales/af/messages.json +++ b/apps/web/src/locales/af/messages.json @@ -93,8 +93,8 @@ "assignMembersTasksToMonitorProgress": { "message": "Assign members tasks to monitor progress" }, - "onceYouReviewApps": { - "message": "Once you review applications and mark them as critical, you can assign tasks to members to resolve at-risk items and monitor progress here" + "onceYouReviewApplications": { + "message": "Once you review applications and mark them as critical, assign tasks to your members to change their passwords." }, "sendReminders": { "message": "Send reminders" @@ -178,41 +178,35 @@ } } }, - "noApplicationsInOrgTitle": { - "message": "No applications found for $ORG NAME$", - "placeholders": { - "org name": { - "content": "$1", - "example": "Company Name" - } - } + "noDataInOrgTitle": { + "message": "No data found" }, - "noApplicationsInOrgDescription": { - "message": "Import your organization's login data to start monitoring credential security risks. Once imported you get to:" + "noDataInOrgDescription": { + "message": "Import your organization's login data to get started with Access Intelligence. Once you do that, you'll be able to:" }, - "benefit1Title": { - "message": "Prioritize risks" + "feature1Title": { + "message": "Mark applications as critical" }, - "benefit1Description": { - "message": "Focus on applications that matter the most" + "feature1Description": { + "message": "This will help you remove risks to your most important applications first." }, - "benefit2Title": { - "message": "Guide remediation" + "feature2Title": { + "message": "Help members improve their security" }, - "benefit2Description": { - "message": "Assign at-risk members guided tasks to rotate at-risk credentials" + "feature2Description": { + "message": "Assign at-risk members guided security tasks to update credentials." }, - "benefit3Title": { + "feature3Title": { "message": "Monitor progress" }, - "benefit3Description": { - "message": "Track changes over time to show security improvements" + "feature3Description": { + "message": "Track changes over time to show security improvements." }, - "noReportRunTitle": { - "message": "Run your first report to see applications" + "noReportsRunTitle": { + "message": "Generate report" }, - "noReportRunDescription": { - "message": "Generate a risk insights report to analyze your organization's applications and identify at-risk passwords that need attention. Running your first report will:" + "noReportsRunDescription": { + "message": "You’re ready to start generating reports. Once you generate, you’ll be able to:" }, "noCriticalApplicationsTitle": { "message": "You haven’t marked any applications as critical" @@ -271,14 +265,14 @@ "atRiskMembers": { "message": "At-risk members" }, - "membersWithAccessToAtRiskItemsForCriticalApps": { - "message": "Members with access to at-risk items for critical applications" + "membersWithAccessToAtRiskItemsForCriticalApplications": { + "message": "These members have access to vulnerable items for critical applications." }, "membersWithAtRiskPasswords": { "message": "Members with at-risk passwords" }, - "membersWillReceiveNotification": { - "message": "Members will receive a notification to resolve at-risk logins through the browser extension." + "membersWillReceiveSecurityTask": { + "message": "Members of your organization will be assigned a task to change vulnerable passwords. They’ll receive a notification within their Bitwarden browser extension." }, "membersAtRiskCount": { "message": "$COUNT$ members at-risk", @@ -307,8 +301,8 @@ } } }, - "atRiskMembersDescription": { - "message": "These members are logging into applications with weak, exposed, or reused passwords." + "atRiskMemberDescription": { + "message": "These members are logging into critical applications with weak, exposed, or reused passwords." }, "atRiskMembersDescriptionNone": { "message": "These are no members logging into applications with weak, exposed, or reused passwords." @@ -391,14 +385,14 @@ "prioritizeCriticalApplications": { "message": "Prioritize critical applications" }, - "selectCriticalApplicationsDescription": { - "message": "Select which applications are most critical to your organization, then assign security tasks to members to resolve risks." + "selectCriticalAppsDescription": { + "message": "Select which applications are most critical to your organization. Then, you’ll be able to assign security tasks to members to remove risks." }, "reviewNewApplications": { "message": "Review new applications" }, - "reviewNewApplicationsDescription": { - "message": "We've highlighted at-risk items for new applications stored in Admin console that have weak, exposed, or reused passwords." + "reviewNewAppsDescription": { + "message": "Review new applications with vulnerable items and mark those you’d like to monitor closely as critical. Then, you’ll be able to assign security tasks to members to remove risks." }, "clickIconToMarkAppAsCritical": { "message": "Click the star icon to mark an app as critical" @@ -9856,8 +9850,8 @@ "assignTasks": { "message": "Assign tasks" }, - "assignTasksToMembers": { - "message": "Assign tasks to members for guided resolution" + "assignSecurityTasksToMembers": { + "message": "Send notifications to change passwords" }, "assignToCollections": { "message": "Assign to collections" diff --git a/apps/web/src/locales/ar/messages.json b/apps/web/src/locales/ar/messages.json index fb42b2b5fa..7dbfa67074 100644 --- a/apps/web/src/locales/ar/messages.json +++ b/apps/web/src/locales/ar/messages.json @@ -93,8 +93,8 @@ "assignMembersTasksToMonitorProgress": { "message": "Assign members tasks to monitor progress" }, - "onceYouReviewApps": { - "message": "Once you review applications and mark them as critical, you can assign tasks to members to resolve at-risk items and monitor progress here" + "onceYouReviewApplications": { + "message": "Once you review applications and mark them as critical, assign tasks to your members to change their passwords." }, "sendReminders": { "message": "Send reminders" @@ -178,41 +178,35 @@ } } }, - "noApplicationsInOrgTitle": { - "message": "No applications found for $ORG NAME$", - "placeholders": { - "org name": { - "content": "$1", - "example": "Company Name" - } - } + "noDataInOrgTitle": { + "message": "No data found" }, - "noApplicationsInOrgDescription": { - "message": "Import your organization's login data to start monitoring credential security risks. Once imported you get to:" + "noDataInOrgDescription": { + "message": "Import your organization's login data to get started with Access Intelligence. Once you do that, you'll be able to:" }, - "benefit1Title": { - "message": "Prioritize risks" + "feature1Title": { + "message": "Mark applications as critical" }, - "benefit1Description": { - "message": "Focus on applications that matter the most" + "feature1Description": { + "message": "This will help you remove risks to your most important applications first." }, - "benefit2Title": { - "message": "Guide remediation" + "feature2Title": { + "message": "Help members improve their security" }, - "benefit2Description": { - "message": "Assign at-risk members guided tasks to rotate at-risk credentials" + "feature2Description": { + "message": "Assign at-risk members guided security tasks to update credentials." }, - "benefit3Title": { + "feature3Title": { "message": "Monitor progress" }, - "benefit3Description": { - "message": "Track changes over time to show security improvements" + "feature3Description": { + "message": "Track changes over time to show security improvements." }, - "noReportRunTitle": { - "message": "Run your first report to see applications" + "noReportsRunTitle": { + "message": "Generate report" }, - "noReportRunDescription": { - "message": "Generate a risk insights report to analyze your organization's applications and identify at-risk passwords that need attention. Running your first report will:" + "noReportsRunDescription": { + "message": "You’re ready to start generating reports. Once you generate, you’ll be able to:" }, "noCriticalApplicationsTitle": { "message": "You haven’t marked any applications as critical" @@ -271,14 +265,14 @@ "atRiskMembers": { "message": "الأعضاء المعرضون للخطر" }, - "membersWithAccessToAtRiskItemsForCriticalApps": { - "message": "Members with access to at-risk items for critical applications" + "membersWithAccessToAtRiskItemsForCriticalApplications": { + "message": "These members have access to vulnerable items for critical applications." }, "membersWithAtRiskPasswords": { "message": "Members with at-risk passwords" }, - "membersWillReceiveNotification": { - "message": "Members will receive a notification to resolve at-risk logins through the browser extension." + "membersWillReceiveSecurityTask": { + "message": "Members of your organization will be assigned a task to change vulnerable passwords. They’ll receive a notification within their Bitwarden browser extension." }, "membersAtRiskCount": { "message": "$COUNT$ members at-risk", @@ -307,8 +301,8 @@ } } }, - "atRiskMembersDescription": { - "message": "يقوم هؤلاء الأعضاء بتسجيل الدخول إلى التطبيقات باستخدام كلمات مرور ضعيفة أو مكشوفة أو مُعادة الاستخدام." + "atRiskMemberDescription": { + "message": "These members are logging into critical applications with weak, exposed, or reused passwords." }, "atRiskMembersDescriptionNone": { "message": "يقوم هؤلاء الأعضاء بتسجيل الدخول إلى التطبيقات باستخدام كلمات مرور ضعيفة أو مكشوفة أو مُعادة الاستخدام." @@ -391,14 +385,14 @@ "prioritizeCriticalApplications": { "message": "Prioritize critical applications" }, - "selectCriticalApplicationsDescription": { - "message": "Select which applications are most critical to your organization, then assign security tasks to members to resolve risks." + "selectCriticalAppsDescription": { + "message": "Select which applications are most critical to your organization. Then, you’ll be able to assign security tasks to members to remove risks." }, "reviewNewApplications": { "message": "Review new applications" }, - "reviewNewApplicationsDescription": { - "message": "We've highlighted at-risk items for new applications stored in Admin console that have weak, exposed, or reused passwords." + "reviewNewAppsDescription": { + "message": "Review new applications with vulnerable items and mark those you’d like to monitor closely as critical. Then, you’ll be able to assign security tasks to members to remove risks." }, "clickIconToMarkAppAsCritical": { "message": "Click the star icon to mark an app as critical" @@ -9856,8 +9850,8 @@ "assignTasks": { "message": "Assign tasks" }, - "assignTasksToMembers": { - "message": "Assign tasks to members for guided resolution" + "assignSecurityTasksToMembers": { + "message": "Send notifications to change passwords" }, "assignToCollections": { "message": "Assign to collections" diff --git a/apps/web/src/locales/az/messages.json b/apps/web/src/locales/az/messages.json index 8dcfa862f0..9ff3fc4604 100644 --- a/apps/web/src/locales/az/messages.json +++ b/apps/web/src/locales/az/messages.json @@ -93,8 +93,8 @@ "assignMembersTasksToMonitorProgress": { "message": "İrəliləyişi izləmək üçün üzvlərə tapşırıqlar təyin edin" }, - "onceYouReviewApps": { - "message": "Tətbiqləri incələyib kritik olaraq işarələdikdən sonra, riskli elementləri həll etməsi üçün üzvlərə tapşırıqlar verə və irəliləyişi burada izləyə bilərsiniz" + "onceYouReviewApplications": { + "message": "Once you review applications and mark them as critical, assign tasks to your members to change their passwords." }, "sendReminders": { "message": "Xatırlatma göndər" @@ -178,41 +178,35 @@ } } }, - "noApplicationsInOrgTitle": { - "message": "$ORG NAME$ üçün heç bir tətbiq tapılmadı", - "placeholders": { - "org name": { - "content": "$1", - "example": "Company Name" - } - } + "noDataInOrgTitle": { + "message": "No data found" }, - "noApplicationsInOrgDescription": { - "message": "Kimlik məlumatı təhlükəsizlik risklərini monitorinq etməyə başlamaq üçün təşkilatınızın giriş verilərini daxilə köçürün. Daxilə köçürdükdən sonra əldə edəcəkləriniz:" + "noDataInOrgDescription": { + "message": "Import your organization's login data to get started with Access Intelligence. Once you do that, you'll be able to:" }, - "benefit1Title": { - "message": "Riskləri prioritetləşdirmə" + "feature1Title": { + "message": "Mark applications as critical" }, - "benefit1Description": { - "message": "Ən vacib tətbiqlərə fokuslanma" + "feature1Description": { + "message": "This will help you remove risks to your most important applications first." }, - "benefit2Title": { - "message": "Riskləri azaltma bələdçisi" + "feature2Title": { + "message": "Help members improve their security" }, - "benefit2Description": { - "message": "Risk altındakı üzvlərə, riskli kimlik məlumatlarını dəyişmək üçün rəhbər tapşırıqlar təyin edin" + "feature2Description": { + "message": "Assign at-risk members guided security tasks to update credentials." }, - "benefit3Title": { - "message": "İrəliləyişin monitorinqi" + "feature3Title": { + "message": "Monitor progress" }, - "benefit3Description": { - "message": "Təhlükəsizlik təkmilləşdirmələrini göstərmək üçün zamanla dəyişiklikləri izləyin" + "feature3Description": { + "message": "Track changes over time to show security improvements." }, - "noReportRunTitle": { - "message": "Tətbiqləri görmək üçün ilk hesabatınızı çalışdırın" + "noReportsRunTitle": { + "message": "Generate report" }, - "noReportRunDescription": { - "message": "Təşkilatınızın tətbiqlərini təhlil etmək və diqqət edilməli riskli parolları müəyyənləşdirmək üçün risk təhlili hesabatını yaradın. İlk hesabatınızı çalışdırdıqda:" + "noReportsRunDescription": { + "message": "You’re ready to start generating reports. Once you generate, you’ll be able to:" }, "noCriticalApplicationsTitle": { "message": "Heç bir tətbiqi kritik olaraq işarələməmisiniz" @@ -271,14 +265,14 @@ "atRiskMembers": { "message": "Riskli üzvlər" }, - "membersWithAccessToAtRiskItemsForCriticalApps": { - "message": "Kritik tətbiqlər üçün risk altındakı elementlərə erişimi olan üzvlər" + "membersWithAccessToAtRiskItemsForCriticalApplications": { + "message": "These members have access to vulnerable items for critical applications." }, "membersWithAtRiskPasswords": { "message": "Riskli parollara sahib üzvlər" }, - "membersWillReceiveNotification": { - "message": "Üzvlər, riskli girişləri həll etmək üçün brauzer uzantısı üzərindən bildiriş alacaqlar." + "membersWillReceiveSecurityTask": { + "message": "Members of your organization will be assigned a task to change vulnerable passwords. They’ll receive a notification within their Bitwarden browser extension." }, "membersAtRiskCount": { "message": "$COUNT$ üzv risk altındadır", @@ -307,8 +301,8 @@ } } }, - "atRiskMembersDescription": { - "message": "Bu üzvlər, tətbiqlərə zəif, ifşa olunmuş və ya təkrar istifadə olunan parollarla giriş edir." + "atRiskMemberDescription": { + "message": "These members are logging into critical applications with weak, exposed, or reused passwords." }, "atRiskMembersDescriptionNone": { "message": "Tətbiqlərə zəif, ifşa olunmuş və ya təkrar istifadə olunan parollarla giriş edən üzv yoxdur." @@ -391,14 +385,14 @@ "prioritizeCriticalApplications": { "message": "Kritik tətbiqləri prioritetləşdir" }, - "selectCriticalApplicationsDescription": { - "message": "Təşkilatınız üçün ən kritik sayılan tətbiqləri seçin, daha sonra riskləri həll etmələri üçün üzvlərə təhlükəsizlik tapşırıqları təyin edin." + "selectCriticalAppsDescription": { + "message": "Select which applications are most critical to your organization. Then, you’ll be able to assign security tasks to members to remove risks." }, "reviewNewApplications": { "message": "Yeni tətbiqlər incələ" }, - "reviewNewApplicationsDescription": { - "message": "Admin konsolunda saxlanılmış və zəif, ifşa olunmuş və ya təkrar istifadə olunmuş parollara sahib yeni tətbiqlər üçün riskli elementləri vurğulamışıq." + "reviewNewAppsDescription": { + "message": "Review new applications with vulnerable items and mark those you’d like to monitor closely as critical. Then, you’ll be able to assign security tasks to members to remove risks." }, "clickIconToMarkAppAsCritical": { "message": "Bir tətbiqi kritik olaraq işarələmək üçün ulduz ikonuna klikləyin" @@ -3251,7 +3245,7 @@ "message": "Növbəti ödəniş" }, "nextChargeHeader": { - "message": "Next Charge" + "message": "Növbəti ödəniş" }, "plan": { "message": "Plan" @@ -3260,7 +3254,7 @@ "message": "Təfsilatlar" }, "discount": { - "message": "discount" + "message": "endirim" }, "downloadLicense": { "message": "Lisenziyanı endir" @@ -9856,8 +9850,8 @@ "assignTasks": { "message": "Tapşırıq təyin et" }, - "assignTasksToMembers": { - "message": "Üzvlərə rəhbər həll üçün tapşırıqlar təyin edin" + "assignSecurityTasksToMembers": { + "message": "Send notifications to change passwords" }, "assignToCollections": { "message": "Kolleksiyalara təyin et" @@ -12159,9 +12153,9 @@ } }, "confirmNoSelectedCriticalApplicationsTitle": { - "message": "No critical applications are selected" + "message": "Heç bir kritik tətbiq seçilməyib" }, "confirmNoSelectedCriticalApplicationsDesc": { - "message": "Are you sure you want to continue?" + "message": "Davam etmək istədiyinizə əminsiniz?" } } diff --git a/apps/web/src/locales/be/messages.json b/apps/web/src/locales/be/messages.json index 9fd22d0ccd..e562c39ea7 100644 --- a/apps/web/src/locales/be/messages.json +++ b/apps/web/src/locales/be/messages.json @@ -93,8 +93,8 @@ "assignMembersTasksToMonitorProgress": { "message": "Assign members tasks to monitor progress" }, - "onceYouReviewApps": { - "message": "Once you review applications and mark them as critical, you can assign tasks to members to resolve at-risk items and monitor progress here" + "onceYouReviewApplications": { + "message": "Once you review applications and mark them as critical, assign tasks to your members to change their passwords." }, "sendReminders": { "message": "Send reminders" @@ -178,41 +178,35 @@ } } }, - "noApplicationsInOrgTitle": { - "message": "No applications found for $ORG NAME$", - "placeholders": { - "org name": { - "content": "$1", - "example": "Company Name" - } - } + "noDataInOrgTitle": { + "message": "No data found" }, - "noApplicationsInOrgDescription": { - "message": "Import your organization's login data to start monitoring credential security risks. Once imported you get to:" + "noDataInOrgDescription": { + "message": "Import your organization's login data to get started with Access Intelligence. Once you do that, you'll be able to:" }, - "benefit1Title": { - "message": "Prioritize risks" + "feature1Title": { + "message": "Mark applications as critical" }, - "benefit1Description": { - "message": "Focus on applications that matter the most" + "feature1Description": { + "message": "This will help you remove risks to your most important applications first." }, - "benefit2Title": { - "message": "Guide remediation" + "feature2Title": { + "message": "Help members improve their security" }, - "benefit2Description": { - "message": "Assign at-risk members guided tasks to rotate at-risk credentials" + "feature2Description": { + "message": "Assign at-risk members guided security tasks to update credentials." }, - "benefit3Title": { + "feature3Title": { "message": "Monitor progress" }, - "benefit3Description": { - "message": "Track changes over time to show security improvements" + "feature3Description": { + "message": "Track changes over time to show security improvements." }, - "noReportRunTitle": { - "message": "Run your first report to see applications" + "noReportsRunTitle": { + "message": "Generate report" }, - "noReportRunDescription": { - "message": "Generate a risk insights report to analyze your organization's applications and identify at-risk passwords that need attention. Running your first report will:" + "noReportsRunDescription": { + "message": "You’re ready to start generating reports. Once you generate, you’ll be able to:" }, "noCriticalApplicationsTitle": { "message": "You haven’t marked any applications as critical" @@ -271,14 +265,14 @@ "atRiskMembers": { "message": "Удзельнікі ў зоне рызыкі" }, - "membersWithAccessToAtRiskItemsForCriticalApps": { - "message": "Members with access to at-risk items for critical applications" + "membersWithAccessToAtRiskItemsForCriticalApplications": { + "message": "These members have access to vulnerable items for critical applications." }, "membersWithAtRiskPasswords": { "message": "Members with at-risk passwords" }, - "membersWillReceiveNotification": { - "message": "Members will receive a notification to resolve at-risk logins through the browser extension." + "membersWillReceiveSecurityTask": { + "message": "Members of your organization will be assigned a task to change vulnerable passwords. They’ll receive a notification within their Bitwarden browser extension." }, "membersAtRiskCount": { "message": "$COUNT$ members at-risk", @@ -307,8 +301,8 @@ } } }, - "atRiskMembersDescription": { - "message": "Гэтыя ўдзельнікі ўваходзяць у праграму з ненадзейнымі, скампраметаванымі або паўторна выкарыстанымі паролямі." + "atRiskMemberDescription": { + "message": "These members are logging into critical applications with weak, exposed, or reused passwords." }, "atRiskMembersDescriptionNone": { "message": "These are no members logging into applications with weak, exposed, or reused passwords." @@ -391,14 +385,14 @@ "prioritizeCriticalApplications": { "message": "Prioritize critical applications" }, - "selectCriticalApplicationsDescription": { - "message": "Select which applications are most critical to your organization, then assign security tasks to members to resolve risks." + "selectCriticalAppsDescription": { + "message": "Select which applications are most critical to your organization. Then, you’ll be able to assign security tasks to members to remove risks." }, "reviewNewApplications": { "message": "Review new applications" }, - "reviewNewApplicationsDescription": { - "message": "We've highlighted at-risk items for new applications stored in Admin console that have weak, exposed, or reused passwords." + "reviewNewAppsDescription": { + "message": "Review new applications with vulnerable items and mark those you’d like to monitor closely as critical. Then, you’ll be able to assign security tasks to members to remove risks." }, "clickIconToMarkAppAsCritical": { "message": "Click the star icon to mark an app as critical" @@ -9856,8 +9850,8 @@ "assignTasks": { "message": "Assign tasks" }, - "assignTasksToMembers": { - "message": "Assign tasks to members for guided resolution" + "assignSecurityTasksToMembers": { + "message": "Send notifications to change passwords" }, "assignToCollections": { "message": "Assign to collections" diff --git a/apps/web/src/locales/bg/messages.json b/apps/web/src/locales/bg/messages.json index 6f17d4b264..1f897b5d74 100644 --- a/apps/web/src/locales/bg/messages.json +++ b/apps/web/src/locales/bg/messages.json @@ -93,8 +93,8 @@ "assignMembersTasksToMonitorProgress": { "message": "Назначете задачи на членовете, за да следите напредъка" }, - "onceYouReviewApps": { - "message": "След като прегледате приложенията и отбележите някои като важни, можете да зададете задачи на членовете, така че те да се занимаят с нещата в риск, а Вие да следите напредъка тук" + "onceYouReviewApplications": { + "message": "След като прегледате приложенията и ги отбележите като важни, можете да зададете задачи на членовете си, за да сменят паролите си." }, "sendReminders": { "message": "Изпращане на напомняния" @@ -178,41 +178,35 @@ } } }, - "noApplicationsInOrgTitle": { - "message": "Няма намерени приложения за $ORG NAME$", - "placeholders": { - "org name": { - "content": "$1", - "example": "Company Name" - } - } + "noDataInOrgTitle": { + "message": "Няма намерени данни" }, - "noApplicationsInOrgDescription": { - "message": "Внесете данните за вписване на организацията си, за да започнете да следите рисковете по сигурността им. След внасянето ще можете:" + "noDataInOrgDescription": { + "message": "Внесете данните за вписване на организацията си, за да започнете да използвате Анализа на достъпа. След като направите това, ще можете да:" }, - "benefit1Title": { - "message": "Да приоритизирате рисковете" + "feature1Title": { + "message": "Отбелязвате приложения като важни" }, - "benefit1Description": { - "message": "Фокусирайте се върху приложенията, които са най-важни" + "feature1Description": { + "message": "Това ще Ви помогне да отстранявате рисковете първо в най-важните си приложения." }, - "benefit2Title": { - "message": "Да давате насоки за подобряване" + "feature2Title": { + "message": "Помагате на членовете да подобряват сигурността си" }, - "benefit2Description": { - "message": "Давайте задачи на членовете в риск, така че те да не забравят да променят данните си" + "feature2Description": { + "message": "Задавайте на членовете в риск задачи по сигурността, които да ги насочват в промяната на данните им." }, - "benefit3Title": { - "message": "Да следите напредъка" + "feature3Title": { + "message": "Следите напредъка" }, - "benefit3Description": { - "message": "Следете промените във времето, за да виждате как сигурността се подобрява" + "feature3Description": { + "message": "Следете промените във времето, за да виждате как сигурността се подобрява." }, - "noReportRunTitle": { - "message": "Създайте първия си доклад, за да видите приложенията" + "noReportsRunTitle": { + "message": "Създаване на доклад" }, - "noReportRunDescription": { - "message": "Създайте доклад с подробности за рисковете, за да анализирате приложенията в организацията си и да установите кои пароли са в риск и имат нужда от внимание. Създаването на първия доклад ще:" + "noReportsRunDescription": { + "message": "Всичко е готово и можете да започнете да създавате доклади. След като го направите, ще можете да:" }, "noCriticalApplicationsTitle": { "message": "Не сте отбелязали нито едно приложение като важно" @@ -271,14 +265,14 @@ "atRiskMembers": { "message": "Членове в риск" }, - "membersWithAccessToAtRiskItemsForCriticalApps": { - "message": "Членове с достъп до елементи в риск за важни приложения" + "membersWithAccessToAtRiskItemsForCriticalApplications": { + "message": "Тези членове имат достъп до рисковите елементи за важните приложения." }, "membersWithAtRiskPasswords": { "message": "Членове с пароли в риск" }, - "membersWillReceiveNotification": { - "message": "Членовете ще получат известие, за да отстранят проблема с данните си за вписване в риск, чрез добавката за браузъра." + "membersWillReceiveSecurityTask": { + "message": "Членовете на организацията ще получат задача за промяна на рисковите пароли. Те ще получат известие в разширението за браузър на Битуорден." }, "membersAtRiskCount": { "message": "$COUNT$ членове в риск", @@ -307,8 +301,8 @@ } } }, - "atRiskMembersDescription": { - "message": "Тези членове се вписват в приложенията със слаби, преизползвани или разобличени пароли." + "atRiskMemberDescription": { + "message": "Тези членове се вписват във важните приложения със слаби, преизползвани или разкрити пароли." }, "atRiskMembersDescriptionNone": { "message": "Няма членове, които се вписват в приложенията със слаби, преизползвани или разобличени пароли." @@ -391,14 +385,14 @@ "prioritizeCriticalApplications": { "message": "Даване на приоритет на важните приложения" }, - "selectCriticalApplicationsDescription": { - "message": "Изберете кои приложения са най-важни за организацията Ви, а след това раздайте задачи на членовете, за да отстраните рисковете." + "selectCriticalAppsDescription": { + "message": "Изберете кои приложения са най-важни за организацията Ви. След това ще можете да зададете задачи на членовете, за да отстраните рисковете." }, "reviewNewApplications": { "message": "Преглед на новите приложения" }, - "reviewNewApplicationsDescription": { - "message": "Отбелязахме елементите в риск за новите приложения съхранявани в Административната конзола, които имат слаби, преизползвани или разкрити пароли." + "reviewNewAppsDescription": { + "message": "Прегледайте новите приложения с рискови елементи и ги отбележете, ако искате да ги следите внимателно като важни. След това ще можете да задавате задачи на членовете, за да отстраните рисковете." }, "clickIconToMarkAppAsCritical": { "message": "Щракнете върху иконката със звезда, за да отбележите приложение като важно" @@ -9856,8 +9850,8 @@ "assignTasks": { "message": "Назначаване на задачи" }, - "assignTasksToMembers": { - "message": "Задавайте задачи на членовете, за да отстраняват проблемите" + "assignSecurityTasksToMembers": { + "message": "Изпращане на известия за промяна на пароли" }, "assignToCollections": { "message": "Свързване с колекции" @@ -12159,9 +12153,9 @@ } }, "confirmNoSelectedCriticalApplicationsTitle": { - "message": "No critical applications are selected" + "message": "Няма избрани важни приложения" }, "confirmNoSelectedCriticalApplicationsDesc": { - "message": "Are you sure you want to continue?" + "message": "Наистина ли искате да продължите?" } } diff --git a/apps/web/src/locales/bn/messages.json b/apps/web/src/locales/bn/messages.json index 4baf480b51..67fddc7d6e 100644 --- a/apps/web/src/locales/bn/messages.json +++ b/apps/web/src/locales/bn/messages.json @@ -93,8 +93,8 @@ "assignMembersTasksToMonitorProgress": { "message": "Assign members tasks to monitor progress" }, - "onceYouReviewApps": { - "message": "Once you review applications and mark them as critical, you can assign tasks to members to resolve at-risk items and monitor progress here" + "onceYouReviewApplications": { + "message": "Once you review applications and mark them as critical, assign tasks to your members to change their passwords." }, "sendReminders": { "message": "Send reminders" @@ -178,41 +178,35 @@ } } }, - "noApplicationsInOrgTitle": { - "message": "No applications found for $ORG NAME$", - "placeholders": { - "org name": { - "content": "$1", - "example": "Company Name" - } - } + "noDataInOrgTitle": { + "message": "No data found" }, - "noApplicationsInOrgDescription": { - "message": "Import your organization's login data to start monitoring credential security risks. Once imported you get to:" + "noDataInOrgDescription": { + "message": "Import your organization's login data to get started with Access Intelligence. Once you do that, you'll be able to:" }, - "benefit1Title": { - "message": "Prioritize risks" + "feature1Title": { + "message": "Mark applications as critical" }, - "benefit1Description": { - "message": "Focus on applications that matter the most" + "feature1Description": { + "message": "This will help you remove risks to your most important applications first." }, - "benefit2Title": { - "message": "Guide remediation" + "feature2Title": { + "message": "Help members improve their security" }, - "benefit2Description": { - "message": "Assign at-risk members guided tasks to rotate at-risk credentials" + "feature2Description": { + "message": "Assign at-risk members guided security tasks to update credentials." }, - "benefit3Title": { + "feature3Title": { "message": "Monitor progress" }, - "benefit3Description": { - "message": "Track changes over time to show security improvements" + "feature3Description": { + "message": "Track changes over time to show security improvements." }, - "noReportRunTitle": { - "message": "Run your first report to see applications" + "noReportsRunTitle": { + "message": "Generate report" }, - "noReportRunDescription": { - "message": "Generate a risk insights report to analyze your organization's applications and identify at-risk passwords that need attention. Running your first report will:" + "noReportsRunDescription": { + "message": "You’re ready to start generating reports. Once you generate, you’ll be able to:" }, "noCriticalApplicationsTitle": { "message": "You haven’t marked any applications as critical" @@ -271,14 +265,14 @@ "atRiskMembers": { "message": "At-risk members" }, - "membersWithAccessToAtRiskItemsForCriticalApps": { - "message": "Members with access to at-risk items for critical applications" + "membersWithAccessToAtRiskItemsForCriticalApplications": { + "message": "These members have access to vulnerable items for critical applications." }, "membersWithAtRiskPasswords": { "message": "Members with at-risk passwords" }, - "membersWillReceiveNotification": { - "message": "Members will receive a notification to resolve at-risk logins through the browser extension." + "membersWillReceiveSecurityTask": { + "message": "Members of your organization will be assigned a task to change vulnerable passwords. They’ll receive a notification within their Bitwarden browser extension." }, "membersAtRiskCount": { "message": "$COUNT$ members at-risk", @@ -307,8 +301,8 @@ } } }, - "atRiskMembersDescription": { - "message": "These members are logging into applications with weak, exposed, or reused passwords." + "atRiskMemberDescription": { + "message": "These members are logging into critical applications with weak, exposed, or reused passwords." }, "atRiskMembersDescriptionNone": { "message": "These are no members logging into applications with weak, exposed, or reused passwords." @@ -391,14 +385,14 @@ "prioritizeCriticalApplications": { "message": "Prioritize critical applications" }, - "selectCriticalApplicationsDescription": { - "message": "Select which applications are most critical to your organization, then assign security tasks to members to resolve risks." + "selectCriticalAppsDescription": { + "message": "Select which applications are most critical to your organization. Then, you’ll be able to assign security tasks to members to remove risks." }, "reviewNewApplications": { "message": "Review new applications" }, - "reviewNewApplicationsDescription": { - "message": "We've highlighted at-risk items for new applications stored in Admin console that have weak, exposed, or reused passwords." + "reviewNewAppsDescription": { + "message": "Review new applications with vulnerable items and mark those you’d like to monitor closely as critical. Then, you’ll be able to assign security tasks to members to remove risks." }, "clickIconToMarkAppAsCritical": { "message": "Click the star icon to mark an app as critical" @@ -9856,8 +9850,8 @@ "assignTasks": { "message": "Assign tasks" }, - "assignTasksToMembers": { - "message": "Assign tasks to members for guided resolution" + "assignSecurityTasksToMembers": { + "message": "Send notifications to change passwords" }, "assignToCollections": { "message": "Assign to collections" diff --git a/apps/web/src/locales/bs/messages.json b/apps/web/src/locales/bs/messages.json index f9b5481cd2..cae2a248d0 100644 --- a/apps/web/src/locales/bs/messages.json +++ b/apps/web/src/locales/bs/messages.json @@ -93,8 +93,8 @@ "assignMembersTasksToMonitorProgress": { "message": "Assign members tasks to monitor progress" }, - "onceYouReviewApps": { - "message": "Once you review applications and mark them as critical, you can assign tasks to members to resolve at-risk items and monitor progress here" + "onceYouReviewApplications": { + "message": "Once you review applications and mark them as critical, assign tasks to your members to change their passwords." }, "sendReminders": { "message": "Send reminders" @@ -178,41 +178,35 @@ } } }, - "noApplicationsInOrgTitle": { - "message": "No applications found for $ORG NAME$", - "placeholders": { - "org name": { - "content": "$1", - "example": "Company Name" - } - } + "noDataInOrgTitle": { + "message": "No data found" }, - "noApplicationsInOrgDescription": { - "message": "Import your organization's login data to start monitoring credential security risks. Once imported you get to:" + "noDataInOrgDescription": { + "message": "Import your organization's login data to get started with Access Intelligence. Once you do that, you'll be able to:" }, - "benefit1Title": { - "message": "Prioritize risks" + "feature1Title": { + "message": "Mark applications as critical" }, - "benefit1Description": { - "message": "Focus on applications that matter the most" + "feature1Description": { + "message": "This will help you remove risks to your most important applications first." }, - "benefit2Title": { - "message": "Guide remediation" + "feature2Title": { + "message": "Help members improve their security" }, - "benefit2Description": { - "message": "Assign at-risk members guided tasks to rotate at-risk credentials" + "feature2Description": { + "message": "Assign at-risk members guided security tasks to update credentials." }, - "benefit3Title": { + "feature3Title": { "message": "Monitor progress" }, - "benefit3Description": { - "message": "Track changes over time to show security improvements" + "feature3Description": { + "message": "Track changes over time to show security improvements." }, - "noReportRunTitle": { - "message": "Run your first report to see applications" + "noReportsRunTitle": { + "message": "Generate report" }, - "noReportRunDescription": { - "message": "Generate a risk insights report to analyze your organization's applications and identify at-risk passwords that need attention. Running your first report will:" + "noReportsRunDescription": { + "message": "You’re ready to start generating reports. Once you generate, you’ll be able to:" }, "noCriticalApplicationsTitle": { "message": "You haven’t marked any applications as critical" @@ -271,14 +265,14 @@ "atRiskMembers": { "message": "At-risk members" }, - "membersWithAccessToAtRiskItemsForCriticalApps": { - "message": "Members with access to at-risk items for critical applications" + "membersWithAccessToAtRiskItemsForCriticalApplications": { + "message": "These members have access to vulnerable items for critical applications." }, "membersWithAtRiskPasswords": { "message": "Members with at-risk passwords" }, - "membersWillReceiveNotification": { - "message": "Members will receive a notification to resolve at-risk logins through the browser extension." + "membersWillReceiveSecurityTask": { + "message": "Members of your organization will be assigned a task to change vulnerable passwords. They’ll receive a notification within their Bitwarden browser extension." }, "membersAtRiskCount": { "message": "$COUNT$ members at-risk", @@ -307,8 +301,8 @@ } } }, - "atRiskMembersDescription": { - "message": "These members are logging into applications with weak, exposed, or reused passwords." + "atRiskMemberDescription": { + "message": "These members are logging into critical applications with weak, exposed, or reused passwords." }, "atRiskMembersDescriptionNone": { "message": "These are no members logging into applications with weak, exposed, or reused passwords." @@ -391,14 +385,14 @@ "prioritizeCriticalApplications": { "message": "Prioritize critical applications" }, - "selectCriticalApplicationsDescription": { - "message": "Select which applications are most critical to your organization, then assign security tasks to members to resolve risks." + "selectCriticalAppsDescription": { + "message": "Select which applications are most critical to your organization. Then, you’ll be able to assign security tasks to members to remove risks." }, "reviewNewApplications": { "message": "Review new applications" }, - "reviewNewApplicationsDescription": { - "message": "We've highlighted at-risk items for new applications stored in Admin console that have weak, exposed, or reused passwords." + "reviewNewAppsDescription": { + "message": "Review new applications with vulnerable items and mark those you’d like to monitor closely as critical. Then, you’ll be able to assign security tasks to members to remove risks." }, "clickIconToMarkAppAsCritical": { "message": "Click the star icon to mark an app as critical" @@ -9856,8 +9850,8 @@ "assignTasks": { "message": "Assign tasks" }, - "assignTasksToMembers": { - "message": "Assign tasks to members for guided resolution" + "assignSecurityTasksToMembers": { + "message": "Send notifications to change passwords" }, "assignToCollections": { "message": "Assign to collections" diff --git a/apps/web/src/locales/ca/messages.json b/apps/web/src/locales/ca/messages.json index 2994137855..77204835db 100644 --- a/apps/web/src/locales/ca/messages.json +++ b/apps/web/src/locales/ca/messages.json @@ -93,8 +93,8 @@ "assignMembersTasksToMonitorProgress": { "message": "Assign members tasks to monitor progress" }, - "onceYouReviewApps": { - "message": "Once you review applications and mark them as critical, you can assign tasks to members to resolve at-risk items and monitor progress here" + "onceYouReviewApplications": { + "message": "Once you review applications and mark them as critical, assign tasks to your members to change their passwords." }, "sendReminders": { "message": "Send reminders" @@ -178,41 +178,35 @@ } } }, - "noApplicationsInOrgTitle": { - "message": "No applications found for $ORG NAME$", - "placeholders": { - "org name": { - "content": "$1", - "example": "Company Name" - } - } + "noDataInOrgTitle": { + "message": "No data found" }, - "noApplicationsInOrgDescription": { - "message": "Import your organization's login data to start monitoring credential security risks. Once imported you get to:" + "noDataInOrgDescription": { + "message": "Import your organization's login data to get started with Access Intelligence. Once you do that, you'll be able to:" }, - "benefit1Title": { - "message": "Prioritize risks" + "feature1Title": { + "message": "Mark applications as critical" }, - "benefit1Description": { - "message": "Focus on applications that matter the most" + "feature1Description": { + "message": "This will help you remove risks to your most important applications first." }, - "benefit2Title": { - "message": "Guide remediation" + "feature2Title": { + "message": "Help members improve their security" }, - "benefit2Description": { - "message": "Assign at-risk members guided tasks to rotate at-risk credentials" + "feature2Description": { + "message": "Assign at-risk members guided security tasks to update credentials." }, - "benefit3Title": { + "feature3Title": { "message": "Monitor progress" }, - "benefit3Description": { - "message": "Track changes over time to show security improvements" + "feature3Description": { + "message": "Track changes over time to show security improvements." }, - "noReportRunTitle": { - "message": "Run your first report to see applications" + "noReportsRunTitle": { + "message": "Generate report" }, - "noReportRunDescription": { - "message": "Generate a risk insights report to analyze your organization's applications and identify at-risk passwords that need attention. Running your first report will:" + "noReportsRunDescription": { + "message": "You’re ready to start generating reports. Once you generate, you’ll be able to:" }, "noCriticalApplicationsTitle": { "message": "You haven’t marked any applications as critical" @@ -271,14 +265,14 @@ "atRiskMembers": { "message": "At-risk members" }, - "membersWithAccessToAtRiskItemsForCriticalApps": { - "message": "Members with access to at-risk items for critical applications" + "membersWithAccessToAtRiskItemsForCriticalApplications": { + "message": "These members have access to vulnerable items for critical applications." }, "membersWithAtRiskPasswords": { "message": "Members with at-risk passwords" }, - "membersWillReceiveNotification": { - "message": "Members will receive a notification to resolve at-risk logins through the browser extension." + "membersWillReceiveSecurityTask": { + "message": "Members of your organization will be assigned a task to change vulnerable passwords. They’ll receive a notification within their Bitwarden browser extension." }, "membersAtRiskCount": { "message": "$COUNT$ members at-risk", @@ -307,8 +301,8 @@ } } }, - "atRiskMembersDescription": { - "message": "These members are logging into applications with weak, exposed, or reused passwords." + "atRiskMemberDescription": { + "message": "These members are logging into critical applications with weak, exposed, or reused passwords." }, "atRiskMembersDescriptionNone": { "message": "These are no members logging into applications with weak, exposed, or reused passwords." @@ -391,14 +385,14 @@ "prioritizeCriticalApplications": { "message": "Prioritize critical applications" }, - "selectCriticalApplicationsDescription": { - "message": "Select which applications are most critical to your organization, then assign security tasks to members to resolve risks." + "selectCriticalAppsDescription": { + "message": "Select which applications are most critical to your organization. Then, you’ll be able to assign security tasks to members to remove risks." }, "reviewNewApplications": { "message": "Review new applications" }, - "reviewNewApplicationsDescription": { - "message": "We've highlighted at-risk items for new applications stored in Admin console that have weak, exposed, or reused passwords." + "reviewNewAppsDescription": { + "message": "Review new applications with vulnerable items and mark those you’d like to monitor closely as critical. Then, you’ll be able to assign security tasks to members to remove risks." }, "clickIconToMarkAppAsCritical": { "message": "Click the star icon to mark an app as critical" @@ -9856,8 +9850,8 @@ "assignTasks": { "message": "Assign tasks" }, - "assignTasksToMembers": { - "message": "Assign tasks to members for guided resolution" + "assignSecurityTasksToMembers": { + "message": "Send notifications to change passwords" }, "assignToCollections": { "message": "Assigna a col·leccions" diff --git a/apps/web/src/locales/cs/messages.json b/apps/web/src/locales/cs/messages.json index ed82a38c39..ccb2172dbf 100644 --- a/apps/web/src/locales/cs/messages.json +++ b/apps/web/src/locales/cs/messages.json @@ -93,8 +93,8 @@ "assignMembersTasksToMonitorProgress": { "message": "Přiřadit úkoly členů ke sledování průběhu" }, - "onceYouReviewApps": { - "message": "Jakmile zkontrolujete aplikace a označíte je jako kritické, můžete přidělit členům úkoly k řešení ohrožených položek a sledovat průběh zde" + "onceYouReviewApplications": { + "message": "Jakmile zkontrolujete aplikace a označíte je jako kritické, přiřaďte svým členům úkoly ke změně jejich hesel." }, "sendReminders": { "message": "Odeslat připomenutí" @@ -178,41 +178,35 @@ } } }, - "noApplicationsInOrgTitle": { - "message": "Pro $ORG NAME$ nebyly nalezeny žádné aplikace", - "placeholders": { - "org name": { - "content": "$1", - "example": "Company Name" - } - } + "noDataInOrgTitle": { + "message": "Nebyla nalezena žádná data" }, - "noApplicationsInOrgDescription": { - "message": "Importujte přihlašovací údaje Vaší organizace a začněte sledovat bezpečnostní rizika spojená s přihlašovacími údaji. Po importu získáte přístup k:" + "noDataInOrgDescription": { + "message": "Importujte přihlašovací údaje Vaší organizace a začněte s Access Intelligence. Jakmile to uděláte, budete moci:" }, - "benefit1Title": { - "message": "Upřednostnit rizika" + "feature1Title": { + "message": "Označit aplikace jako kritické" }, - "benefit1Description": { - "message": "Zaměřit se na aplikace, na které záleží nejvíce" + "feature1Description": { + "message": "To Vám pomůže nejprve odebrat rizika pro Vaše nejdůležitější aplikace." }, - "benefit2Title": { - "message": "Průvodce nápravou" + "feature2Title": { + "message": "Pomoci členům zlepšit jejich zabezpečení" }, - "benefit2Description": { - "message": "Přiřadit ohroženým členům řízené úkoly, aby střídali používání ohrožených přihlašovacích údajů" + "feature2Description": { + "message": "Přiřaďte ohroženým členům řízené bezpečnostní úkoly k aktualizaci přihlašovacích údajů." }, - "benefit3Title": { + "feature3Title": { "message": "Sledovat průběh" }, - "benefit3Description": { + "feature3Description": { "message": "Sleduje změny v průběhu času pro zobrazení zlepšení zabezpečení." }, - "noReportRunTitle": { - "message": "Spustit první hlášení pro zobrazení aplikací" + "noReportsRunTitle": { + "message": "Vygenerovat přehled" }, - "noReportRunDescription": { - "message": "Vygenerujte zprávu o rizicích, abyste mohli analyzovat aplikace Vaší organizace a identifikovat riziková hesla, která vyžadují pozornost. Spuštěním první zprávy:" + "noReportsRunDescription": { + "message": "Jste připraveni začít generovat přehledy. Jakmile je vytvoříte, budete moci:" }, "noCriticalApplicationsTitle": { "message": "Neoznačili jste žádné aplikace jako kritické" @@ -271,14 +265,14 @@ "atRiskMembers": { "message": "Ohrožení členové" }, - "membersWithAccessToAtRiskItemsForCriticalApps": { - "message": "Členové s přístupem k rizikovým položkám pro kritické aplikace" + "membersWithAccessToAtRiskItemsForCriticalApplications": { + "message": "Tito členové mají přístup k zranitelným položkám pro kritické aplikace." }, "membersWithAtRiskPasswords": { "message": "Členové s ohroženými hesly" }, - "membersWillReceiveNotification": { - "message": "Členové obdrží oznámení, aby vyřešili ohrožená přihlášení prostřednictvím rozšíření prohlížeče." + "membersWillReceiveSecurityTask": { + "message": "Členům Vaší organizace bude přiřazen úkol ke změně zranitelných hesel. Obdrželi oznámení v rámci jejich rozšíření prohlížeče Bitwarden." }, "membersAtRiskCount": { "message": "$COUNT$ členů v ohrožení", @@ -307,8 +301,8 @@ } } }, - "atRiskMembersDescription": { - "message": "Tito členové se přihlašují do aplikací se slabými, odhalenými nebo znovu použitými hesly." + "atRiskMemberDescription": { + "message": "Tito členové se přihlašují do kritických aplikací s odhalenými nebo znovu použitými hesly." }, "atRiskMembersDescriptionNone": { "message": "Žádní členové se nepřihlašují do aplikací se slabými, odhalenými nebo znovu použitými hesly." @@ -391,14 +385,14 @@ "prioritizeCriticalApplications": { "message": "Upřednostnit kritické aplikace" }, - "selectCriticalApplicationsDescription": { - "message": "Vybere, které aplikace jsou pro Vaši organizaci nejkritičtější, a pro řešení rizik přiřaďte členům bezpečnostní úkoly." + "selectCriticalAppsDescription": { + "message": "Vyberte, které aplikace jsou pro Vaši organizaci nejkritičtější. Potom budete moci přidělit členům bezpečnostní úkoly pro odebrání rizik." }, "reviewNewApplications": { "message": "Zkontrolovat nové aplikace" }, - "reviewNewApplicationsDescription": { - "message": "Zvýraznili jsme rizikové položky pro nové aplikace uložené v administrátorské konzoli, které mají slabá, exponovaná nebo znovu použitá hesla." + "reviewNewAppsDescription": { + "message": "Zkontrolujte nové aplikace s citlivými položkami a označte ty, které chcete pečlivě sledovat jako kritické. Potom budete moci přidělit členům bezpečnostní úkoly, abyste odebrali rizika." }, "clickIconToMarkAppAsCritical": { "message": "Klepnutím na ikonu hvězdičky označte aplikaci jako kritickou" @@ -9856,8 +9850,8 @@ "assignTasks": { "message": "Přiřadit úkoly" }, - "assignTasksToMembers": { - "message": "Přiřadit úkoly členům k řízenému řešení" + "assignSecurityTasksToMembers": { + "message": "Odeslat oznámení pro změnu hesla" }, "assignToCollections": { "message": "Přiřadit ke sbírkám" diff --git a/apps/web/src/locales/cy/messages.json b/apps/web/src/locales/cy/messages.json index 8c62a789fb..c140204619 100644 --- a/apps/web/src/locales/cy/messages.json +++ b/apps/web/src/locales/cy/messages.json @@ -93,8 +93,8 @@ "assignMembersTasksToMonitorProgress": { "message": "Assign members tasks to monitor progress" }, - "onceYouReviewApps": { - "message": "Once you review applications and mark them as critical, you can assign tasks to members to resolve at-risk items and monitor progress here" + "onceYouReviewApplications": { + "message": "Once you review applications and mark them as critical, assign tasks to your members to change their passwords." }, "sendReminders": { "message": "Send reminders" @@ -178,41 +178,35 @@ } } }, - "noApplicationsInOrgTitle": { - "message": "No applications found for $ORG NAME$", - "placeholders": { - "org name": { - "content": "$1", - "example": "Company Name" - } - } + "noDataInOrgTitle": { + "message": "No data found" }, - "noApplicationsInOrgDescription": { - "message": "Import your organization's login data to start monitoring credential security risks. Once imported you get to:" + "noDataInOrgDescription": { + "message": "Import your organization's login data to get started with Access Intelligence. Once you do that, you'll be able to:" }, - "benefit1Title": { - "message": "Prioritize risks" + "feature1Title": { + "message": "Mark applications as critical" }, - "benefit1Description": { - "message": "Focus on applications that matter the most" + "feature1Description": { + "message": "This will help you remove risks to your most important applications first." }, - "benefit2Title": { - "message": "Guide remediation" + "feature2Title": { + "message": "Help members improve their security" }, - "benefit2Description": { - "message": "Assign at-risk members guided tasks to rotate at-risk credentials" + "feature2Description": { + "message": "Assign at-risk members guided security tasks to update credentials." }, - "benefit3Title": { + "feature3Title": { "message": "Monitor progress" }, - "benefit3Description": { - "message": "Track changes over time to show security improvements" + "feature3Description": { + "message": "Track changes over time to show security improvements." }, - "noReportRunTitle": { - "message": "Run your first report to see applications" + "noReportsRunTitle": { + "message": "Generate report" }, - "noReportRunDescription": { - "message": "Generate a risk insights report to analyze your organization's applications and identify at-risk passwords that need attention. Running your first report will:" + "noReportsRunDescription": { + "message": "You’re ready to start generating reports. Once you generate, you’ll be able to:" }, "noCriticalApplicationsTitle": { "message": "You haven’t marked any applications as critical" @@ -271,14 +265,14 @@ "atRiskMembers": { "message": "At-risk members" }, - "membersWithAccessToAtRiskItemsForCriticalApps": { - "message": "Members with access to at-risk items for critical applications" + "membersWithAccessToAtRiskItemsForCriticalApplications": { + "message": "These members have access to vulnerable items for critical applications." }, "membersWithAtRiskPasswords": { "message": "Members with at-risk passwords" }, - "membersWillReceiveNotification": { - "message": "Members will receive a notification to resolve at-risk logins through the browser extension." + "membersWillReceiveSecurityTask": { + "message": "Members of your organization will be assigned a task to change vulnerable passwords. They’ll receive a notification within their Bitwarden browser extension." }, "membersAtRiskCount": { "message": "$COUNT$ members at-risk", @@ -307,8 +301,8 @@ } } }, - "atRiskMembersDescription": { - "message": "These members are logging into applications with weak, exposed, or reused passwords." + "atRiskMemberDescription": { + "message": "These members are logging into critical applications with weak, exposed, or reused passwords." }, "atRiskMembersDescriptionNone": { "message": "These are no members logging into applications with weak, exposed, or reused passwords." @@ -391,14 +385,14 @@ "prioritizeCriticalApplications": { "message": "Prioritize critical applications" }, - "selectCriticalApplicationsDescription": { - "message": "Select which applications are most critical to your organization, then assign security tasks to members to resolve risks." + "selectCriticalAppsDescription": { + "message": "Select which applications are most critical to your organization. Then, you’ll be able to assign security tasks to members to remove risks." }, "reviewNewApplications": { "message": "Review new applications" }, - "reviewNewApplicationsDescription": { - "message": "We've highlighted at-risk items for new applications stored in Admin console that have weak, exposed, or reused passwords." + "reviewNewAppsDescription": { + "message": "Review new applications with vulnerable items and mark those you’d like to monitor closely as critical. Then, you’ll be able to assign security tasks to members to remove risks." }, "clickIconToMarkAppAsCritical": { "message": "Click the star icon to mark an app as critical" @@ -9856,8 +9850,8 @@ "assignTasks": { "message": "Assign tasks" }, - "assignTasksToMembers": { - "message": "Assign tasks to members for guided resolution" + "assignSecurityTasksToMembers": { + "message": "Send notifications to change passwords" }, "assignToCollections": { "message": "Assign to collections" diff --git a/apps/web/src/locales/da/messages.json b/apps/web/src/locales/da/messages.json index 7ddd60a2b7..cc2a58aa27 100644 --- a/apps/web/src/locales/da/messages.json +++ b/apps/web/src/locales/da/messages.json @@ -93,8 +93,8 @@ "assignMembersTasksToMonitorProgress": { "message": "Assign members tasks to monitor progress" }, - "onceYouReviewApps": { - "message": "Once you review applications and mark them as critical, you can assign tasks to members to resolve at-risk items and monitor progress here" + "onceYouReviewApplications": { + "message": "Once you review applications and mark them as critical, assign tasks to your members to change their passwords." }, "sendReminders": { "message": "Send reminders" @@ -178,41 +178,35 @@ } } }, - "noApplicationsInOrgTitle": { - "message": "No applications found for $ORG NAME$", - "placeholders": { - "org name": { - "content": "$1", - "example": "Company Name" - } - } + "noDataInOrgTitle": { + "message": "No data found" }, - "noApplicationsInOrgDescription": { - "message": "Import your organization's login data to start monitoring credential security risks. Once imported you get to:" + "noDataInOrgDescription": { + "message": "Import your organization's login data to get started with Access Intelligence. Once you do that, you'll be able to:" }, - "benefit1Title": { - "message": "Prioritize risks" + "feature1Title": { + "message": "Mark applications as critical" }, - "benefit1Description": { - "message": "Focus on applications that matter the most" + "feature1Description": { + "message": "This will help you remove risks to your most important applications first." }, - "benefit2Title": { - "message": "Guide remediation" + "feature2Title": { + "message": "Help members improve their security" }, - "benefit2Description": { - "message": "Assign at-risk members guided tasks to rotate at-risk credentials" + "feature2Description": { + "message": "Assign at-risk members guided security tasks to update credentials." }, - "benefit3Title": { + "feature3Title": { "message": "Monitor progress" }, - "benefit3Description": { - "message": "Track changes over time to show security improvements" + "feature3Description": { + "message": "Track changes over time to show security improvements." }, - "noReportRunTitle": { - "message": "Run your first report to see applications" + "noReportsRunTitle": { + "message": "Generate report" }, - "noReportRunDescription": { - "message": "Generate a risk insights report to analyze your organization's applications and identify at-risk passwords that need attention. Running your first report will:" + "noReportsRunDescription": { + "message": "You’re ready to start generating reports. Once you generate, you’ll be able to:" }, "noCriticalApplicationsTitle": { "message": "You haven’t marked any applications as critical" @@ -271,14 +265,14 @@ "atRiskMembers": { "message": "Udsatte medlemmer" }, - "membersWithAccessToAtRiskItemsForCriticalApps": { - "message": "Members with access to at-risk items for critical applications" + "membersWithAccessToAtRiskItemsForCriticalApplications": { + "message": "These members have access to vulnerable items for critical applications." }, "membersWithAtRiskPasswords": { "message": "Members with at-risk passwords" }, - "membersWillReceiveNotification": { - "message": "Members will receive a notification to resolve at-risk logins through the browser extension." + "membersWillReceiveSecurityTask": { + "message": "Members of your organization will be assigned a task to change vulnerable passwords. They’ll receive a notification within their Bitwarden browser extension." }, "membersAtRiskCount": { "message": "$COUNT$ members at-risk", @@ -307,8 +301,8 @@ } } }, - "atRiskMembersDescription": { - "message": "Disse medlemmer logger ind på programmer med svage, udsatte eller genbrugte adgangskoder." + "atRiskMemberDescription": { + "message": "These members are logging into critical applications with weak, exposed, or reused passwords." }, "atRiskMembersDescriptionNone": { "message": "These are no members logging into applications with weak, exposed, or reused passwords." @@ -391,14 +385,14 @@ "prioritizeCriticalApplications": { "message": "Prioritize critical applications" }, - "selectCriticalApplicationsDescription": { - "message": "Select which applications are most critical to your organization, then assign security tasks to members to resolve risks." + "selectCriticalAppsDescription": { + "message": "Select which applications are most critical to your organization. Then, you’ll be able to assign security tasks to members to remove risks." }, "reviewNewApplications": { "message": "Review new applications" }, - "reviewNewApplicationsDescription": { - "message": "We've highlighted at-risk items for new applications stored in Admin console that have weak, exposed, or reused passwords." + "reviewNewAppsDescription": { + "message": "Review new applications with vulnerable items and mark those you’d like to monitor closely as critical. Then, you’ll be able to assign security tasks to members to remove risks." }, "clickIconToMarkAppAsCritical": { "message": "Click the star icon to mark an app as critical" @@ -9856,8 +9850,8 @@ "assignTasks": { "message": "Assign tasks" }, - "assignTasksToMembers": { - "message": "Assign tasks to members for guided resolution" + "assignSecurityTasksToMembers": { + "message": "Send notifications to change passwords" }, "assignToCollections": { "message": "Tildel til samlinger" diff --git a/apps/web/src/locales/de/messages.json b/apps/web/src/locales/de/messages.json index 162eefe992..073126da44 100644 --- a/apps/web/src/locales/de/messages.json +++ b/apps/web/src/locales/de/messages.json @@ -93,8 +93,8 @@ "assignMembersTasksToMonitorProgress": { "message": "Mitglieder Aufgaben zuweisen, um den Fortschritt zu überwachen" }, - "onceYouReviewApps": { - "message": "Sobald du die Anwendungen überprüft und als kritisch markiert hast, kannst du Mitgliedern Aufgaben zuweisen, um gefährdete Einträge zu beheben und den Fortschritt hier überwachen" + "onceYouReviewApplications": { + "message": "Once you review applications and mark them as critical, assign tasks to your members to change their passwords." }, "sendReminders": { "message": "Erinnerungen senden" @@ -178,41 +178,35 @@ } } }, - "noApplicationsInOrgTitle": { - "message": "Keine Anwendungen für $ORG NAME$ gefunden", - "placeholders": { - "org name": { - "content": "$1", - "example": "Company Name" - } - } + "noDataInOrgTitle": { + "message": "No data found" }, - "noApplicationsInOrgDescription": { - "message": "Importiere die Zugangsdaten deiner Organisation, um mit der Überwachung von Sicherheitsrisiken für Zugangsdaten zu starten. Nach dem Import kannst du:" + "noDataInOrgDescription": { + "message": "Import your organization's login data to get started with Access Intelligence. Once you do that, you'll be able to:" }, - "benefit1Title": { - "message": "Risiken priorisieren" + "feature1Title": { + "message": "Mark applications as critical" }, - "benefit1Description": { - "message": "Auf Anwendungen konzentrieren, die am wichtigsten sind" + "feature1Description": { + "message": "This will help you remove risks to your most important applications first." }, - "benefit2Title": { - "message": "Anleitung zur Behebung" + "feature2Title": { + "message": "Help members improve their security" }, - "benefit2Description": { - "message": "Gefährdeten Mitgliedern gezielte Aufgaben zuweisen, um gefährdete Zugangsdaten zu erneuern" + "feature2Description": { + "message": "Assign at-risk members guided security tasks to update credentials." }, - "benefit3Title": { + "feature3Title": { "message": "Fortschritt überwachen" }, - "benefit3Description": { - "message": "Änderungen im Laufe der Zeit verfolgen, um Sicherheitsverbesserungen anzuzeigen" + "feature3Description": { + "message": "Track changes over time to show security improvements." }, - "noReportRunTitle": { - "message": "Erstelle deinen ersten Bericht, um Anwendungen zu sehen" + "noReportsRunTitle": { + "message": "Generate report" }, - "noReportRunDescription": { - "message": "Erstelle einen Risikoanalysebericht, um die Anwendungen deines Unternehmens zu analysieren und gefährdete Passwörter zu identifizieren, die Aufmerksamkeit erfordern. Die Erstellung deines ersten Berichts wird:" + "noReportsRunDescription": { + "message": "You’re ready to start generating reports. Once you generate, you’ll be able to:" }, "noCriticalApplicationsTitle": { "message": "Du hast keine Anwendung als kritisch markiert" @@ -271,14 +265,14 @@ "atRiskMembers": { "message": "Gefährdete Mitglieder" }, - "membersWithAccessToAtRiskItemsForCriticalApps": { - "message": "Mitglieder mit Zugriff auf gefährdete Einträge für kritische Anwendungen" + "membersWithAccessToAtRiskItemsForCriticalApplications": { + "message": "These members have access to vulnerable items for critical applications." }, "membersWithAtRiskPasswords": { "message": "Mitglieder mit gefährdeten Passwörtern" }, - "membersWillReceiveNotification": { - "message": "Mitglieder erhalten über die Browser-Erweiterung eine Benachrichtigung, um gefährdete Zugangsdaten zu ändern." + "membersWillReceiveSecurityTask": { + "message": "Members of your organization will be assigned a task to change vulnerable passwords. They’ll receive a notification within their Bitwarden browser extension." }, "membersAtRiskCount": { "message": "$COUNT$ gefährdete Mitglieder", @@ -307,8 +301,8 @@ } } }, - "atRiskMembersDescription": { - "message": "Diese Mitglieder melden sich bei Anwendungen mit schwachen, kompromittierten oder wiederverwendeten Passwörtern an." + "atRiskMemberDescription": { + "message": "These members are logging into critical applications with weak, exposed, or reused passwords." }, "atRiskMembersDescriptionNone": { "message": "Dies sind keine Mitglieder, die sich in Anwendungen mit schwachen, kompromittierten oder wiederverwendeten Passwörtern anmelden." @@ -391,14 +385,14 @@ "prioritizeCriticalApplications": { "message": "Kritische Anwendungen priorisieren" }, - "selectCriticalApplicationsDescription": { - "message": "Wähle die für deine Organisation kritischsten Anwendungen aus und weise den Mitgliedern Sicherheitsaufgaben zu, um Risiken zu beseitigen." + "selectCriticalAppsDescription": { + "message": "Select which applications are most critical to your organization. Then, you’ll be able to assign security tasks to members to remove risks." }, "reviewNewApplications": { "message": "Neue Anwendungen überprüfen" }, - "reviewNewApplicationsDescription": { - "message": "Wir haben gefährdete Einträge für neue Anwendungen hervorgehoben, die in der Administrator-Konsole gespeichert sind und schwache, kompromittierte oder wiederverwendete Passwörter beinhalten." + "reviewNewAppsDescription": { + "message": "Review new applications with vulnerable items and mark those you’d like to monitor closely as critical. Then, you’ll be able to assign security tasks to members to remove risks." }, "clickIconToMarkAppAsCritical": { "message": "Klicke auf das Sternsymbol, um eine App als kritisch zu markieren" @@ -3251,16 +3245,16 @@ "message": "Nächste Abbuchung" }, "nextChargeHeader": { - "message": "Next Charge" + "message": "Nächste Abbuchung" }, "plan": { - "message": "Plan" + "message": "Tarif" }, "details": { "message": "Details" }, "discount": { - "message": "discount" + "message": "Rabatt" }, "downloadLicense": { "message": "Lizenz herunterladen" @@ -9856,8 +9850,8 @@ "assignTasks": { "message": "Aufgaben zuweisen" }, - "assignTasksToMembers": { - "message": "Mitgliedern Aufgaben für eine gezielte Lösung zuweisen" + "assignSecurityTasksToMembers": { + "message": "Sende Benachrichtigungen, um Passwörter zu ändern" }, "assignToCollections": { "message": "Sammlungen zuweisen" @@ -10369,7 +10363,7 @@ "message": "Index" }, "selectAPlan": { - "message": "Ein Abo auswählen" + "message": "Einen Tarif auswählen" }, "thirtyFivePercentDiscount": { "message": "35% Rabatt" @@ -12159,9 +12153,9 @@ } }, "confirmNoSelectedCriticalApplicationsTitle": { - "message": "No critical applications are selected" + "message": "Es sind keine kritischen Anwendungen ausgewählt" }, "confirmNoSelectedCriticalApplicationsDesc": { - "message": "Are you sure you want to continue?" + "message": "Bist du sicher, dass du fortfahren möchtest?" } } diff --git a/apps/web/src/locales/el/messages.json b/apps/web/src/locales/el/messages.json index fb06612043..606d10fa60 100644 --- a/apps/web/src/locales/el/messages.json +++ b/apps/web/src/locales/el/messages.json @@ -93,8 +93,8 @@ "assignMembersTasksToMonitorProgress": { "message": "Assign members tasks to monitor progress" }, - "onceYouReviewApps": { - "message": "Once you review applications and mark them as critical, you can assign tasks to members to resolve at-risk items and monitor progress here" + "onceYouReviewApplications": { + "message": "Once you review applications and mark them as critical, assign tasks to your members to change their passwords." }, "sendReminders": { "message": "Send reminders" @@ -178,41 +178,35 @@ } } }, - "noApplicationsInOrgTitle": { - "message": "No applications found for $ORG NAME$", - "placeholders": { - "org name": { - "content": "$1", - "example": "Company Name" - } - } + "noDataInOrgTitle": { + "message": "No data found" }, - "noApplicationsInOrgDescription": { - "message": "Import your organization's login data to start monitoring credential security risks. Once imported you get to:" + "noDataInOrgDescription": { + "message": "Import your organization's login data to get started with Access Intelligence. Once you do that, you'll be able to:" }, - "benefit1Title": { - "message": "Prioritize risks" + "feature1Title": { + "message": "Mark applications as critical" }, - "benefit1Description": { - "message": "Focus on applications that matter the most" + "feature1Description": { + "message": "This will help you remove risks to your most important applications first." }, - "benefit2Title": { - "message": "Guide remediation" + "feature2Title": { + "message": "Help members improve their security" }, - "benefit2Description": { - "message": "Assign at-risk members guided tasks to rotate at-risk credentials" + "feature2Description": { + "message": "Assign at-risk members guided security tasks to update credentials." }, - "benefit3Title": { + "feature3Title": { "message": "Monitor progress" }, - "benefit3Description": { - "message": "Track changes over time to show security improvements" + "feature3Description": { + "message": "Track changes over time to show security improvements." }, - "noReportRunTitle": { - "message": "Run your first report to see applications" + "noReportsRunTitle": { + "message": "Generate report" }, - "noReportRunDescription": { - "message": "Generate a risk insights report to analyze your organization's applications and identify at-risk passwords that need attention. Running your first report will:" + "noReportsRunDescription": { + "message": "You’re ready to start generating reports. Once you generate, you’ll be able to:" }, "noCriticalApplicationsTitle": { "message": "You haven’t marked any applications as critical" @@ -271,14 +265,14 @@ "atRiskMembers": { "message": "At-risk members" }, - "membersWithAccessToAtRiskItemsForCriticalApps": { - "message": "Members with access to at-risk items for critical applications" + "membersWithAccessToAtRiskItemsForCriticalApplications": { + "message": "These members have access to vulnerable items for critical applications." }, "membersWithAtRiskPasswords": { "message": "Members with at-risk passwords" }, - "membersWillReceiveNotification": { - "message": "Members will receive a notification to resolve at-risk logins through the browser extension." + "membersWillReceiveSecurityTask": { + "message": "Members of your organization will be assigned a task to change vulnerable passwords. They’ll receive a notification within their Bitwarden browser extension." }, "membersAtRiskCount": { "message": "$COUNT$ members at-risk", @@ -307,8 +301,8 @@ } } }, - "atRiskMembersDescription": { - "message": "These members are logging into applications with weak, exposed, or reused passwords." + "atRiskMemberDescription": { + "message": "These members are logging into critical applications with weak, exposed, or reused passwords." }, "atRiskMembersDescriptionNone": { "message": "These are no members logging into applications with weak, exposed, or reused passwords." @@ -391,14 +385,14 @@ "prioritizeCriticalApplications": { "message": "Prioritize critical applications" }, - "selectCriticalApplicationsDescription": { - "message": "Select which applications are most critical to your organization, then assign security tasks to members to resolve risks." + "selectCriticalAppsDescription": { + "message": "Select which applications are most critical to your organization. Then, you’ll be able to assign security tasks to members to remove risks." }, "reviewNewApplications": { "message": "Review new applications" }, - "reviewNewApplicationsDescription": { - "message": "We've highlighted at-risk items for new applications stored in Admin console that have weak, exposed, or reused passwords." + "reviewNewAppsDescription": { + "message": "Review new applications with vulnerable items and mark those you’d like to monitor closely as critical. Then, you’ll be able to assign security tasks to members to remove risks." }, "clickIconToMarkAppAsCritical": { "message": "Click the star icon to mark an app as critical" @@ -9856,8 +9850,8 @@ "assignTasks": { "message": "Assign tasks" }, - "assignTasksToMembers": { - "message": "Assign tasks to members for guided resolution" + "assignSecurityTasksToMembers": { + "message": "Send notifications to change passwords" }, "assignToCollections": { "message": "Ανάθεση σε συλλογές" diff --git a/apps/web/src/locales/en_GB/messages.json b/apps/web/src/locales/en_GB/messages.json index 2270d95056..2f40b6fa13 100644 --- a/apps/web/src/locales/en_GB/messages.json +++ b/apps/web/src/locales/en_GB/messages.json @@ -93,8 +93,8 @@ "assignMembersTasksToMonitorProgress": { "message": "Assign members tasks to monitor progress" }, - "onceYouReviewApps": { - "message": "Once you review applications and mark them as critical, you can assign tasks to members to resolve at-risk items and monitor progress here" + "onceYouReviewApplications": { + "message": "Once you review applications and mark them as critical, assign tasks to your members to change their passwords." }, "sendReminders": { "message": "Send reminders" @@ -178,41 +178,35 @@ } } }, - "noApplicationsInOrgTitle": { - "message": "No applications found for $ORG NAME$", - "placeholders": { - "org name": { - "content": "$1", - "example": "Company Name" - } - } + "noDataInOrgTitle": { + "message": "No data found" }, - "noApplicationsInOrgDescription": { - "message": "Import your organisation's login data to start monitoring credential security risks. Once imported you get to:" + "noDataInOrgDescription": { + "message": "Import your organization's login data to get started with Access Intelligence. Once you do that, you'll be able to:" }, - "benefit1Title": { - "message": "Prioritise risks" + "feature1Title": { + "message": "Mark applications as critical" }, - "benefit1Description": { - "message": "Focus on applications that matter the most" + "feature1Description": { + "message": "This will help you remove risks to your most important applications first." }, - "benefit2Title": { - "message": "Guide remediation" + "feature2Title": { + "message": "Help members improve their security" }, - "benefit2Description": { - "message": "Assign at-risk members guided tasks to rotate at-risk credentials" + "feature2Description": { + "message": "Assign at-risk members guided security tasks to update credentials." }, - "benefit3Title": { + "feature3Title": { "message": "Monitor progress" }, - "benefit3Description": { - "message": "Track changes over time to show security improvements" + "feature3Description": { + "message": "Track changes over time to show security improvements." }, - "noReportRunTitle": { - "message": "Run your first report to see applications" + "noReportsRunTitle": { + "message": "Generate report" }, - "noReportRunDescription": { - "message": "Generate a risk insights report to analyse your organisation's applications and identify at-risk passwords that need attention. Running your first report will:" + "noReportsRunDescription": { + "message": "You’re ready to start generating reports. Once you generate, you’ll be able to:" }, "noCriticalApplicationsTitle": { "message": "You haven’t marked any applications as critical" @@ -271,14 +265,14 @@ "atRiskMembers": { "message": "At-risk members" }, - "membersWithAccessToAtRiskItemsForCriticalApps": { - "message": "Members with access to at-risk items for critical applications" + "membersWithAccessToAtRiskItemsForCriticalApplications": { + "message": "These members have access to vulnerable items for critical applications." }, "membersWithAtRiskPasswords": { "message": "Members with at-risk passwords" }, - "membersWillReceiveNotification": { - "message": "Members will receive a notification to resolve at-risk logins through the browser extension." + "membersWillReceiveSecurityTask": { + "message": "Members of your organization will be assigned a task to change vulnerable passwords. They’ll receive a notification within their Bitwarden browser extension." }, "membersAtRiskCount": { "message": "$COUNT$ members at-risk", @@ -307,8 +301,8 @@ } } }, - "atRiskMembersDescription": { - "message": "These members are logging into applications with weak, exposed, or reused passwords." + "atRiskMemberDescription": { + "message": "These members are logging into critical applications with weak, exposed, or reused passwords." }, "atRiskMembersDescriptionNone": { "message": "These are no members logging into applications with weak, exposed, or reused passwords." @@ -391,14 +385,14 @@ "prioritizeCriticalApplications": { "message": "Prioritise critical applications" }, - "selectCriticalApplicationsDescription": { - "message": "Select which applications are most critical to your organisation, then assign security tasks to members to resolve risks." + "selectCriticalAppsDescription": { + "message": "Select which applications are most critical to your organization. Then, you’ll be able to assign security tasks to members to remove risks." }, "reviewNewApplications": { "message": "Review new applications" }, - "reviewNewApplicationsDescription": { - "message": "We've highlighted at-risk items for new applications stored in Admin console that have weak, exposed, or reused passwords." + "reviewNewAppsDescription": { + "message": "Review new applications with vulnerable items and mark those you’d like to monitor closely as critical. Then, you’ll be able to assign security tasks to members to remove risks." }, "clickIconToMarkAppAsCritical": { "message": "Click the star icon to mark an app as critical" @@ -9856,8 +9850,8 @@ "assignTasks": { "message": "Assign tasks" }, - "assignTasksToMembers": { - "message": "Assign tasks to members for guided resolution" + "assignSecurityTasksToMembers": { + "message": "Send notifications to change passwords" }, "assignToCollections": { "message": "Assign to collections" diff --git a/apps/web/src/locales/en_IN/messages.json b/apps/web/src/locales/en_IN/messages.json index 99ebcf2241..180b90cf87 100644 --- a/apps/web/src/locales/en_IN/messages.json +++ b/apps/web/src/locales/en_IN/messages.json @@ -93,8 +93,8 @@ "assignMembersTasksToMonitorProgress": { "message": "Assign members tasks to monitor progress" }, - "onceYouReviewApps": { - "message": "Once you review applications and mark them as critical, you can assign tasks to members to resolve at-risk items and monitor progress here" + "onceYouReviewApplications": { + "message": "Once you review applications and mark them as critical, assign tasks to your members to change their passwords." }, "sendReminders": { "message": "Send reminders" @@ -178,41 +178,35 @@ } } }, - "noApplicationsInOrgTitle": { - "message": "No applications found for $ORG NAME$", - "placeholders": { - "org name": { - "content": "$1", - "example": "Company Name" - } - } + "noDataInOrgTitle": { + "message": "No data found" }, - "noApplicationsInOrgDescription": { - "message": "Import your organisation's login data to start monitoring credential security risks. Once imported you get to:" + "noDataInOrgDescription": { + "message": "Import your organization's login data to get started with Access Intelligence. Once you do that, you'll be able to:" }, - "benefit1Title": { - "message": "Prioritise risks" + "feature1Title": { + "message": "Mark applications as critical" }, - "benefit1Description": { - "message": "Focus on applications that matter the most" + "feature1Description": { + "message": "This will help you remove risks to your most important applications first." }, - "benefit2Title": { - "message": "Guide remediation" + "feature2Title": { + "message": "Help members improve their security" }, - "benefit2Description": { - "message": "Assign at-risk members guided tasks to rotate at-risk credentials" + "feature2Description": { + "message": "Assign at-risk members guided security tasks to update credentials." }, - "benefit3Title": { + "feature3Title": { "message": "Monitor progress" }, - "benefit3Description": { - "message": "Track changes over time to show security improvements" + "feature3Description": { + "message": "Track changes over time to show security improvements." }, - "noReportRunTitle": { - "message": "Run your first report to see applications" + "noReportsRunTitle": { + "message": "Generate report" }, - "noReportRunDescription": { - "message": "Generate a risk insights report to analyse your organisation's applications and identify at-risk passwords that need attention. Running your first report will:" + "noReportsRunDescription": { + "message": "You’re ready to start generating reports. Once you generate, you’ll be able to:" }, "noCriticalApplicationsTitle": { "message": "You haven’t marked any applications as critical" @@ -271,14 +265,14 @@ "atRiskMembers": { "message": "At-risk members" }, - "membersWithAccessToAtRiskItemsForCriticalApps": { - "message": "Members with access to at-risk items for critical applications" + "membersWithAccessToAtRiskItemsForCriticalApplications": { + "message": "These members have access to vulnerable items for critical applications." }, "membersWithAtRiskPasswords": { "message": "Members with at-risk passwords" }, - "membersWillReceiveNotification": { - "message": "Members will receive a notification to resolve at-risk logins through the browser extension." + "membersWillReceiveSecurityTask": { + "message": "Members of your organization will be assigned a task to change vulnerable passwords. They’ll receive a notification within their Bitwarden browser extension." }, "membersAtRiskCount": { "message": "$COUNT$ members at-risk", @@ -307,8 +301,8 @@ } } }, - "atRiskMembersDescription": { - "message": "These members are logging into applications with weak, exposed, or reused passwords." + "atRiskMemberDescription": { + "message": "These members are logging into critical applications with weak, exposed, or reused passwords." }, "atRiskMembersDescriptionNone": { "message": "These are no members logging into applications with weak, exposed, or reused passwords." @@ -391,14 +385,14 @@ "prioritizeCriticalApplications": { "message": "Prioritise critical applications" }, - "selectCriticalApplicationsDescription": { - "message": "Select which applications are most critical to your organisation, then assign security tasks to members to resolve risks." + "selectCriticalAppsDescription": { + "message": "Select which applications are most critical to your organization. Then, you’ll be able to assign security tasks to members to remove risks." }, "reviewNewApplications": { "message": "Review new applications" }, - "reviewNewApplicationsDescription": { - "message": "We've highlighted at-risk items for new applications stored in Admin console that have weak, exposed, or reused passwords." + "reviewNewAppsDescription": { + "message": "Review new applications with vulnerable items and mark those you’d like to monitor closely as critical. Then, you’ll be able to assign security tasks to members to remove risks." }, "clickIconToMarkAppAsCritical": { "message": "Click the star icon to mark an app as critical" @@ -9856,8 +9850,8 @@ "assignTasks": { "message": "Assign tasks" }, - "assignTasksToMembers": { - "message": "Assign tasks to members for guided resolution" + "assignSecurityTasksToMembers": { + "message": "Send notifications to change passwords" }, "assignToCollections": { "message": "Assign to collections" diff --git a/apps/web/src/locales/eo/messages.json b/apps/web/src/locales/eo/messages.json index b1acc78487..94fd92f45c 100644 --- a/apps/web/src/locales/eo/messages.json +++ b/apps/web/src/locales/eo/messages.json @@ -93,8 +93,8 @@ "assignMembersTasksToMonitorProgress": { "message": "Assign members tasks to monitor progress" }, - "onceYouReviewApps": { - "message": "Once you review applications and mark them as critical, you can assign tasks to members to resolve at-risk items and monitor progress here" + "onceYouReviewApplications": { + "message": "Once you review applications and mark them as critical, assign tasks to your members to change their passwords." }, "sendReminders": { "message": "Send reminders" @@ -178,41 +178,35 @@ } } }, - "noApplicationsInOrgTitle": { - "message": "No applications found for $ORG NAME$", - "placeholders": { - "org name": { - "content": "$1", - "example": "Company Name" - } - } + "noDataInOrgTitle": { + "message": "No data found" }, - "noApplicationsInOrgDescription": { - "message": "Import your organization's login data to start monitoring credential security risks. Once imported you get to:" + "noDataInOrgDescription": { + "message": "Import your organization's login data to get started with Access Intelligence. Once you do that, you'll be able to:" }, - "benefit1Title": { - "message": "Prioritize risks" + "feature1Title": { + "message": "Mark applications as critical" }, - "benefit1Description": { - "message": "Focus on applications that matter the most" + "feature1Description": { + "message": "This will help you remove risks to your most important applications first." }, - "benefit2Title": { - "message": "Guide remediation" + "feature2Title": { + "message": "Help members improve their security" }, - "benefit2Description": { - "message": "Assign at-risk members guided tasks to rotate at-risk credentials" + "feature2Description": { + "message": "Assign at-risk members guided security tasks to update credentials." }, - "benefit3Title": { + "feature3Title": { "message": "Monitor progress" }, - "benefit3Description": { - "message": "Track changes over time to show security improvements" + "feature3Description": { + "message": "Track changes over time to show security improvements." }, - "noReportRunTitle": { - "message": "Run your first report to see applications" + "noReportsRunTitle": { + "message": "Generate report" }, - "noReportRunDescription": { - "message": "Generate a risk insights report to analyze your organization's applications and identify at-risk passwords that need attention. Running your first report will:" + "noReportsRunDescription": { + "message": "You’re ready to start generating reports. Once you generate, you’ll be able to:" }, "noCriticalApplicationsTitle": { "message": "You haven’t marked any applications as critical" @@ -271,14 +265,14 @@ "atRiskMembers": { "message": "At-risk members" }, - "membersWithAccessToAtRiskItemsForCriticalApps": { - "message": "Members with access to at-risk items for critical applications" + "membersWithAccessToAtRiskItemsForCriticalApplications": { + "message": "These members have access to vulnerable items for critical applications." }, "membersWithAtRiskPasswords": { "message": "Members with at-risk passwords" }, - "membersWillReceiveNotification": { - "message": "Members will receive a notification to resolve at-risk logins through the browser extension." + "membersWillReceiveSecurityTask": { + "message": "Members of your organization will be assigned a task to change vulnerable passwords. They’ll receive a notification within their Bitwarden browser extension." }, "membersAtRiskCount": { "message": "$COUNT$ members at-risk", @@ -307,8 +301,8 @@ } } }, - "atRiskMembersDescription": { - "message": "These members are logging into applications with weak, exposed, or reused passwords." + "atRiskMemberDescription": { + "message": "These members are logging into critical applications with weak, exposed, or reused passwords." }, "atRiskMembersDescriptionNone": { "message": "These are no members logging into applications with weak, exposed, or reused passwords." @@ -391,14 +385,14 @@ "prioritizeCriticalApplications": { "message": "Prioritize critical applications" }, - "selectCriticalApplicationsDescription": { - "message": "Select which applications are most critical to your organization, then assign security tasks to members to resolve risks." + "selectCriticalAppsDescription": { + "message": "Select which applications are most critical to your organization. Then, you’ll be able to assign security tasks to members to remove risks." }, "reviewNewApplications": { "message": "Review new applications" }, - "reviewNewApplicationsDescription": { - "message": "We've highlighted at-risk items for new applications stored in Admin console that have weak, exposed, or reused passwords." + "reviewNewAppsDescription": { + "message": "Review new applications with vulnerable items and mark those you’d like to monitor closely as critical. Then, you’ll be able to assign security tasks to members to remove risks." }, "clickIconToMarkAppAsCritical": { "message": "Click the star icon to mark an app as critical" @@ -9856,8 +9850,8 @@ "assignTasks": { "message": "Assign tasks" }, - "assignTasksToMembers": { - "message": "Assign tasks to members for guided resolution" + "assignSecurityTasksToMembers": { + "message": "Send notifications to change passwords" }, "assignToCollections": { "message": "Assign to collections" diff --git a/apps/web/src/locales/es/messages.json b/apps/web/src/locales/es/messages.json index 80767d520e..be77b07592 100644 --- a/apps/web/src/locales/es/messages.json +++ b/apps/web/src/locales/es/messages.json @@ -93,8 +93,8 @@ "assignMembersTasksToMonitorProgress": { "message": "Assign members tasks to monitor progress" }, - "onceYouReviewApps": { - "message": "Once you review applications and mark them as critical, you can assign tasks to members to resolve at-risk items and monitor progress here" + "onceYouReviewApplications": { + "message": "Once you review applications and mark them as critical, assign tasks to your members to change their passwords." }, "sendReminders": { "message": "Send reminders" @@ -178,41 +178,35 @@ } } }, - "noApplicationsInOrgTitle": { - "message": "No applications found for $ORG NAME$", - "placeholders": { - "org name": { - "content": "$1", - "example": "Company Name" - } - } + "noDataInOrgTitle": { + "message": "No data found" }, - "noApplicationsInOrgDescription": { - "message": "Import your organization's login data to start monitoring credential security risks. Once imported you get to:" + "noDataInOrgDescription": { + "message": "Import your organization's login data to get started with Access Intelligence. Once you do that, you'll be able to:" }, - "benefit1Title": { - "message": "Prioritize risks" + "feature1Title": { + "message": "Mark applications as critical" }, - "benefit1Description": { - "message": "Focus on applications that matter the most" + "feature1Description": { + "message": "This will help you remove risks to your most important applications first." }, - "benefit2Title": { - "message": "Guide remediation" + "feature2Title": { + "message": "Help members improve their security" }, - "benefit2Description": { - "message": "Assign at-risk members guided tasks to rotate at-risk credentials" + "feature2Description": { + "message": "Assign at-risk members guided security tasks to update credentials." }, - "benefit3Title": { + "feature3Title": { "message": "Monitor progress" }, - "benefit3Description": { - "message": "Track changes over time to show security improvements" + "feature3Description": { + "message": "Track changes over time to show security improvements." }, - "noReportRunTitle": { - "message": "Run your first report to see applications" + "noReportsRunTitle": { + "message": "Generate report" }, - "noReportRunDescription": { - "message": "Generate a risk insights report to analyze your organization's applications and identify at-risk passwords that need attention. Running your first report will:" + "noReportsRunDescription": { + "message": "You’re ready to start generating reports. Once you generate, you’ll be able to:" }, "noCriticalApplicationsTitle": { "message": "You haven’t marked any applications as critical" @@ -271,14 +265,14 @@ "atRiskMembers": { "message": "At-risk members" }, - "membersWithAccessToAtRiskItemsForCriticalApps": { - "message": "Members with access to at-risk items for critical applications" + "membersWithAccessToAtRiskItemsForCriticalApplications": { + "message": "These members have access to vulnerable items for critical applications." }, "membersWithAtRiskPasswords": { "message": "Members with at-risk passwords" }, - "membersWillReceiveNotification": { - "message": "Members will receive a notification to resolve at-risk logins through the browser extension." + "membersWillReceiveSecurityTask": { + "message": "Members of your organization will be assigned a task to change vulnerable passwords. They’ll receive a notification within their Bitwarden browser extension." }, "membersAtRiskCount": { "message": "$COUNT$ members at-risk", @@ -307,8 +301,8 @@ } } }, - "atRiskMembersDescription": { - "message": "These members are logging into applications with weak, exposed, or reused passwords." + "atRiskMemberDescription": { + "message": "These members are logging into critical applications with weak, exposed, or reused passwords." }, "atRiskMembersDescriptionNone": { "message": "These are no members logging into applications with weak, exposed, or reused passwords." @@ -391,14 +385,14 @@ "prioritizeCriticalApplications": { "message": "Prioritize critical applications" }, - "selectCriticalApplicationsDescription": { - "message": "Select which applications are most critical to your organization, then assign security tasks to members to resolve risks." + "selectCriticalAppsDescription": { + "message": "Select which applications are most critical to your organization. Then, you’ll be able to assign security tasks to members to remove risks." }, "reviewNewApplications": { "message": "Review new applications" }, - "reviewNewApplicationsDescription": { - "message": "We've highlighted at-risk items for new applications stored in Admin console that have weak, exposed, or reused passwords." + "reviewNewAppsDescription": { + "message": "Review new applications with vulnerable items and mark those you’d like to monitor closely as critical. Then, you’ll be able to assign security tasks to members to remove risks." }, "clickIconToMarkAppAsCritical": { "message": "Click the star icon to mark an app as critical" @@ -9856,8 +9850,8 @@ "assignTasks": { "message": "Assign tasks" }, - "assignTasksToMembers": { - "message": "Assign tasks to members for guided resolution" + "assignSecurityTasksToMembers": { + "message": "Send notifications to change passwords" }, "assignToCollections": { "message": "Asignar a colecciones" diff --git a/apps/web/src/locales/et/messages.json b/apps/web/src/locales/et/messages.json index 0e47bce83f..2dddfda1bb 100644 --- a/apps/web/src/locales/et/messages.json +++ b/apps/web/src/locales/et/messages.json @@ -93,8 +93,8 @@ "assignMembersTasksToMonitorProgress": { "message": "Assign members tasks to monitor progress" }, - "onceYouReviewApps": { - "message": "Once you review applications and mark them as critical, you can assign tasks to members to resolve at-risk items and monitor progress here" + "onceYouReviewApplications": { + "message": "Once you review applications and mark them as critical, assign tasks to your members to change their passwords." }, "sendReminders": { "message": "Send reminders" @@ -178,41 +178,35 @@ } } }, - "noApplicationsInOrgTitle": { - "message": "No applications found for $ORG NAME$", - "placeholders": { - "org name": { - "content": "$1", - "example": "Company Name" - } - } + "noDataInOrgTitle": { + "message": "No data found" }, - "noApplicationsInOrgDescription": { - "message": "Import your organization's login data to start monitoring credential security risks. Once imported you get to:" + "noDataInOrgDescription": { + "message": "Import your organization's login data to get started with Access Intelligence. Once you do that, you'll be able to:" }, - "benefit1Title": { - "message": "Prioritize risks" + "feature1Title": { + "message": "Mark applications as critical" }, - "benefit1Description": { - "message": "Focus on applications that matter the most" + "feature1Description": { + "message": "This will help you remove risks to your most important applications first." }, - "benefit2Title": { - "message": "Guide remediation" + "feature2Title": { + "message": "Help members improve their security" }, - "benefit2Description": { - "message": "Assign at-risk members guided tasks to rotate at-risk credentials" + "feature2Description": { + "message": "Assign at-risk members guided security tasks to update credentials." }, - "benefit3Title": { + "feature3Title": { "message": "Monitor progress" }, - "benefit3Description": { - "message": "Track changes over time to show security improvements" + "feature3Description": { + "message": "Track changes over time to show security improvements." }, - "noReportRunTitle": { - "message": "Run your first report to see applications" + "noReportsRunTitle": { + "message": "Generate report" }, - "noReportRunDescription": { - "message": "Generate a risk insights report to analyze your organization's applications and identify at-risk passwords that need attention. Running your first report will:" + "noReportsRunDescription": { + "message": "You’re ready to start generating reports. Once you generate, you’ll be able to:" }, "noCriticalApplicationsTitle": { "message": "You haven’t marked any applications as critical" @@ -271,14 +265,14 @@ "atRiskMembers": { "message": "At-risk members" }, - "membersWithAccessToAtRiskItemsForCriticalApps": { - "message": "Members with access to at-risk items for critical applications" + "membersWithAccessToAtRiskItemsForCriticalApplications": { + "message": "These members have access to vulnerable items for critical applications." }, "membersWithAtRiskPasswords": { "message": "Members with at-risk passwords" }, - "membersWillReceiveNotification": { - "message": "Members will receive a notification to resolve at-risk logins through the browser extension." + "membersWillReceiveSecurityTask": { + "message": "Members of your organization will be assigned a task to change vulnerable passwords. They’ll receive a notification within their Bitwarden browser extension." }, "membersAtRiskCount": { "message": "$COUNT$ members at-risk", @@ -307,8 +301,8 @@ } } }, - "atRiskMembersDescription": { - "message": "These members are logging into applications with weak, exposed, or reused passwords." + "atRiskMemberDescription": { + "message": "These members are logging into critical applications with weak, exposed, or reused passwords." }, "atRiskMembersDescriptionNone": { "message": "These are no members logging into applications with weak, exposed, or reused passwords." @@ -391,14 +385,14 @@ "prioritizeCriticalApplications": { "message": "Prioritize critical applications" }, - "selectCriticalApplicationsDescription": { - "message": "Select which applications are most critical to your organization, then assign security tasks to members to resolve risks." + "selectCriticalAppsDescription": { + "message": "Select which applications are most critical to your organization. Then, you’ll be able to assign security tasks to members to remove risks." }, "reviewNewApplications": { "message": "Review new applications" }, - "reviewNewApplicationsDescription": { - "message": "We've highlighted at-risk items for new applications stored in Admin console that have weak, exposed, or reused passwords." + "reviewNewAppsDescription": { + "message": "Review new applications with vulnerable items and mark those you’d like to monitor closely as critical. Then, you’ll be able to assign security tasks to members to remove risks." }, "clickIconToMarkAppAsCritical": { "message": "Click the star icon to mark an app as critical" @@ -9856,8 +9850,8 @@ "assignTasks": { "message": "Assign tasks" }, - "assignTasksToMembers": { - "message": "Assign tasks to members for guided resolution" + "assignSecurityTasksToMembers": { + "message": "Send notifications to change passwords" }, "assignToCollections": { "message": "Assign to collections" diff --git a/apps/web/src/locales/eu/messages.json b/apps/web/src/locales/eu/messages.json index 95281e381c..785ba6e2e0 100644 --- a/apps/web/src/locales/eu/messages.json +++ b/apps/web/src/locales/eu/messages.json @@ -93,8 +93,8 @@ "assignMembersTasksToMonitorProgress": { "message": "Assign members tasks to monitor progress" }, - "onceYouReviewApps": { - "message": "Once you review applications and mark them as critical, you can assign tasks to members to resolve at-risk items and monitor progress here" + "onceYouReviewApplications": { + "message": "Once you review applications and mark them as critical, assign tasks to your members to change their passwords." }, "sendReminders": { "message": "Send reminders" @@ -178,41 +178,35 @@ } } }, - "noApplicationsInOrgTitle": { - "message": "No applications found for $ORG NAME$", - "placeholders": { - "org name": { - "content": "$1", - "example": "Company Name" - } - } + "noDataInOrgTitle": { + "message": "No data found" }, - "noApplicationsInOrgDescription": { - "message": "Import your organization's login data to start monitoring credential security risks. Once imported you get to:" + "noDataInOrgDescription": { + "message": "Import your organization's login data to get started with Access Intelligence. Once you do that, you'll be able to:" }, - "benefit1Title": { - "message": "Prioritize risks" + "feature1Title": { + "message": "Mark applications as critical" }, - "benefit1Description": { - "message": "Focus on applications that matter the most" + "feature1Description": { + "message": "This will help you remove risks to your most important applications first." }, - "benefit2Title": { - "message": "Guide remediation" + "feature2Title": { + "message": "Help members improve their security" }, - "benefit2Description": { - "message": "Assign at-risk members guided tasks to rotate at-risk credentials" + "feature2Description": { + "message": "Assign at-risk members guided security tasks to update credentials." }, - "benefit3Title": { + "feature3Title": { "message": "Monitor progress" }, - "benefit3Description": { - "message": "Track changes over time to show security improvements" + "feature3Description": { + "message": "Track changes over time to show security improvements." }, - "noReportRunTitle": { - "message": "Run your first report to see applications" + "noReportsRunTitle": { + "message": "Generate report" }, - "noReportRunDescription": { - "message": "Generate a risk insights report to analyze your organization's applications and identify at-risk passwords that need attention. Running your first report will:" + "noReportsRunDescription": { + "message": "You’re ready to start generating reports. Once you generate, you’ll be able to:" }, "noCriticalApplicationsTitle": { "message": "You haven’t marked any applications as critical" @@ -271,14 +265,14 @@ "atRiskMembers": { "message": "At-risk members" }, - "membersWithAccessToAtRiskItemsForCriticalApps": { - "message": "Members with access to at-risk items for critical applications" + "membersWithAccessToAtRiskItemsForCriticalApplications": { + "message": "These members have access to vulnerable items for critical applications." }, "membersWithAtRiskPasswords": { "message": "Members with at-risk passwords" }, - "membersWillReceiveNotification": { - "message": "Members will receive a notification to resolve at-risk logins through the browser extension." + "membersWillReceiveSecurityTask": { + "message": "Members of your organization will be assigned a task to change vulnerable passwords. They’ll receive a notification within their Bitwarden browser extension." }, "membersAtRiskCount": { "message": "$COUNT$ members at-risk", @@ -307,8 +301,8 @@ } } }, - "atRiskMembersDescription": { - "message": "These members are logging into applications with weak, exposed, or reused passwords." + "atRiskMemberDescription": { + "message": "These members are logging into critical applications with weak, exposed, or reused passwords." }, "atRiskMembersDescriptionNone": { "message": "These are no members logging into applications with weak, exposed, or reused passwords." @@ -391,14 +385,14 @@ "prioritizeCriticalApplications": { "message": "Prioritize critical applications" }, - "selectCriticalApplicationsDescription": { - "message": "Select which applications are most critical to your organization, then assign security tasks to members to resolve risks." + "selectCriticalAppsDescription": { + "message": "Select which applications are most critical to your organization. Then, you’ll be able to assign security tasks to members to remove risks." }, "reviewNewApplications": { "message": "Review new applications" }, - "reviewNewApplicationsDescription": { - "message": "We've highlighted at-risk items for new applications stored in Admin console that have weak, exposed, or reused passwords." + "reviewNewAppsDescription": { + "message": "Review new applications with vulnerable items and mark those you’d like to monitor closely as critical. Then, you’ll be able to assign security tasks to members to remove risks." }, "clickIconToMarkAppAsCritical": { "message": "Click the star icon to mark an app as critical" @@ -9856,8 +9850,8 @@ "assignTasks": { "message": "Assign tasks" }, - "assignTasksToMembers": { - "message": "Assign tasks to members for guided resolution" + "assignSecurityTasksToMembers": { + "message": "Send notifications to change passwords" }, "assignToCollections": { "message": "Assign to collections" diff --git a/apps/web/src/locales/fa/messages.json b/apps/web/src/locales/fa/messages.json index aec55daad5..71da2a1b8b 100644 --- a/apps/web/src/locales/fa/messages.json +++ b/apps/web/src/locales/fa/messages.json @@ -93,8 +93,8 @@ "assignMembersTasksToMonitorProgress": { "message": "Assign members tasks to monitor progress" }, - "onceYouReviewApps": { - "message": "Once you review applications and mark them as critical, you can assign tasks to members to resolve at-risk items and monitor progress here" + "onceYouReviewApplications": { + "message": "Once you review applications and mark them as critical, assign tasks to your members to change their passwords." }, "sendReminders": { "message": "Send reminders" @@ -178,41 +178,35 @@ } } }, - "noApplicationsInOrgTitle": { - "message": "No applications found for $ORG NAME$", - "placeholders": { - "org name": { - "content": "$1", - "example": "Company Name" - } - } + "noDataInOrgTitle": { + "message": "No data found" }, - "noApplicationsInOrgDescription": { - "message": "Import your organization's login data to start monitoring credential security risks. Once imported you get to:" + "noDataInOrgDescription": { + "message": "Import your organization's login data to get started with Access Intelligence. Once you do that, you'll be able to:" }, - "benefit1Title": { - "message": "Prioritize risks" + "feature1Title": { + "message": "Mark applications as critical" }, - "benefit1Description": { - "message": "Focus on applications that matter the most" + "feature1Description": { + "message": "This will help you remove risks to your most important applications first." }, - "benefit2Title": { - "message": "Guide remediation" + "feature2Title": { + "message": "Help members improve their security" }, - "benefit2Description": { - "message": "Assign at-risk members guided tasks to rotate at-risk credentials" + "feature2Description": { + "message": "Assign at-risk members guided security tasks to update credentials." }, - "benefit3Title": { + "feature3Title": { "message": "Monitor progress" }, - "benefit3Description": { - "message": "Track changes over time to show security improvements" + "feature3Description": { + "message": "Track changes over time to show security improvements." }, - "noReportRunTitle": { - "message": "Run your first report to see applications" + "noReportsRunTitle": { + "message": "Generate report" }, - "noReportRunDescription": { - "message": "Generate a risk insights report to analyze your organization's applications and identify at-risk passwords that need attention. Running your first report will:" + "noReportsRunDescription": { + "message": "You’re ready to start generating reports. Once you generate, you’ll be able to:" }, "noCriticalApplicationsTitle": { "message": "You haven’t marked any applications as critical" @@ -271,14 +265,14 @@ "atRiskMembers": { "message": "اعضای در معرض خطر" }, - "membersWithAccessToAtRiskItemsForCriticalApps": { - "message": "Members with access to at-risk items for critical applications" + "membersWithAccessToAtRiskItemsForCriticalApplications": { + "message": "These members have access to vulnerable items for critical applications." }, "membersWithAtRiskPasswords": { "message": "Members with at-risk passwords" }, - "membersWillReceiveNotification": { - "message": "Members will receive a notification to resolve at-risk logins through the browser extension." + "membersWillReceiveSecurityTask": { + "message": "Members of your organization will be assigned a task to change vulnerable passwords. They’ll receive a notification within their Bitwarden browser extension." }, "membersAtRiskCount": { "message": "$COUNT$ members at-risk", @@ -307,8 +301,8 @@ } } }, - "atRiskMembersDescription": { - "message": "این اعضا با کلمات عبور ضعیف، افشا شده یا تکراری وارد برنامه‌ها می‌شوند." + "atRiskMemberDescription": { + "message": "These members are logging into critical applications with weak, exposed, or reused passwords." }, "atRiskMembersDescriptionNone": { "message": "هیچ عضوی با کلمات عبور ضعیف، افشا شده یا تکراری وارد برنامه‌ها نمی‌شود." @@ -391,14 +385,14 @@ "prioritizeCriticalApplications": { "message": "Prioritize critical applications" }, - "selectCriticalApplicationsDescription": { - "message": "Select which applications are most critical to your organization, then assign security tasks to members to resolve risks." + "selectCriticalAppsDescription": { + "message": "Select which applications are most critical to your organization. Then, you’ll be able to assign security tasks to members to remove risks." }, "reviewNewApplications": { "message": "Review new applications" }, - "reviewNewApplicationsDescription": { - "message": "We've highlighted at-risk items for new applications stored in Admin console that have weak, exposed, or reused passwords." + "reviewNewAppsDescription": { + "message": "Review new applications with vulnerable items and mark those you’d like to monitor closely as critical. Then, you’ll be able to assign security tasks to members to remove risks." }, "clickIconToMarkAppAsCritical": { "message": "Click the star icon to mark an app as critical" @@ -9856,8 +9850,8 @@ "assignTasks": { "message": "Assign tasks" }, - "assignTasksToMembers": { - "message": "Assign tasks to members for guided resolution" + "assignSecurityTasksToMembers": { + "message": "Send notifications to change passwords" }, "assignToCollections": { "message": "اختصاص به مجموعه‌ها" diff --git a/apps/web/src/locales/fi/messages.json b/apps/web/src/locales/fi/messages.json index 8a1c7550d4..b735280c31 100644 --- a/apps/web/src/locales/fi/messages.json +++ b/apps/web/src/locales/fi/messages.json @@ -93,8 +93,8 @@ "assignMembersTasksToMonitorProgress": { "message": "Assign members tasks to monitor progress" }, - "onceYouReviewApps": { - "message": "Once you review applications and mark them as critical, you can assign tasks to members to resolve at-risk items and monitor progress here" + "onceYouReviewApplications": { + "message": "Once you review applications and mark them as critical, assign tasks to your members to change their passwords." }, "sendReminders": { "message": "Send reminders" @@ -178,41 +178,35 @@ } } }, - "noApplicationsInOrgTitle": { - "message": "No applications found for $ORG NAME$", - "placeholders": { - "org name": { - "content": "$1", - "example": "Company Name" - } - } + "noDataInOrgTitle": { + "message": "No data found" }, - "noApplicationsInOrgDescription": { - "message": "Import your organization's login data to start monitoring credential security risks. Once imported you get to:" + "noDataInOrgDescription": { + "message": "Import your organization's login data to get started with Access Intelligence. Once you do that, you'll be able to:" }, - "benefit1Title": { - "message": "Prioritize risks" + "feature1Title": { + "message": "Mark applications as critical" }, - "benefit1Description": { - "message": "Focus on applications that matter the most" + "feature1Description": { + "message": "This will help you remove risks to your most important applications first." }, - "benefit2Title": { - "message": "Guide remediation" + "feature2Title": { + "message": "Help members improve their security" }, - "benefit2Description": { - "message": "Assign at-risk members guided tasks to rotate at-risk credentials" + "feature2Description": { + "message": "Assign at-risk members guided security tasks to update credentials." }, - "benefit3Title": { + "feature3Title": { "message": "Monitor progress" }, - "benefit3Description": { - "message": "Track changes over time to show security improvements" + "feature3Description": { + "message": "Track changes over time to show security improvements." }, - "noReportRunTitle": { - "message": "Run your first report to see applications" + "noReportsRunTitle": { + "message": "Generate report" }, - "noReportRunDescription": { - "message": "Generate a risk insights report to analyze your organization's applications and identify at-risk passwords that need attention. Running your first report will:" + "noReportsRunDescription": { + "message": "You’re ready to start generating reports. Once you generate, you’ll be able to:" }, "noCriticalApplicationsTitle": { "message": "You haven’t marked any applications as critical" @@ -271,14 +265,14 @@ "atRiskMembers": { "message": "Riskialttiit jäsenet" }, - "membersWithAccessToAtRiskItemsForCriticalApps": { - "message": "Members with access to at-risk items for critical applications" + "membersWithAccessToAtRiskItemsForCriticalApplications": { + "message": "These members have access to vulnerable items for critical applications." }, "membersWithAtRiskPasswords": { "message": "Members with at-risk passwords" }, - "membersWillReceiveNotification": { - "message": "Members will receive a notification to resolve at-risk logins through the browser extension." + "membersWillReceiveSecurityTask": { + "message": "Members of your organization will be assigned a task to change vulnerable passwords. They’ll receive a notification within their Bitwarden browser extension." }, "membersAtRiskCount": { "message": "$COUNT$ members at-risk", @@ -307,8 +301,8 @@ } } }, - "atRiskMembersDescription": { - "message": "These members are logging into applications with weak, exposed, or reused passwords." + "atRiskMemberDescription": { + "message": "These members are logging into critical applications with weak, exposed, or reused passwords." }, "atRiskMembersDescriptionNone": { "message": "These are no members logging into applications with weak, exposed, or reused passwords." @@ -391,14 +385,14 @@ "prioritizeCriticalApplications": { "message": "Prioritize critical applications" }, - "selectCriticalApplicationsDescription": { - "message": "Select which applications are most critical to your organization, then assign security tasks to members to resolve risks." + "selectCriticalAppsDescription": { + "message": "Select which applications are most critical to your organization. Then, you’ll be able to assign security tasks to members to remove risks." }, "reviewNewApplications": { "message": "Review new applications" }, - "reviewNewApplicationsDescription": { - "message": "We've highlighted at-risk items for new applications stored in Admin console that have weak, exposed, or reused passwords." + "reviewNewAppsDescription": { + "message": "Review new applications with vulnerable items and mark those you’d like to monitor closely as critical. Then, you’ll be able to assign security tasks to members to remove risks." }, "clickIconToMarkAppAsCritical": { "message": "Click the star icon to mark an app as critical" @@ -9856,8 +9850,8 @@ "assignTasks": { "message": "Assign tasks" }, - "assignTasksToMembers": { - "message": "Assign tasks to members for guided resolution" + "assignSecurityTasksToMembers": { + "message": "Send notifications to change passwords" }, "assignToCollections": { "message": "Määritä kokoelmiin" diff --git a/apps/web/src/locales/fil/messages.json b/apps/web/src/locales/fil/messages.json index 6b0d5e3e8a..f91cf0d9bf 100644 --- a/apps/web/src/locales/fil/messages.json +++ b/apps/web/src/locales/fil/messages.json @@ -93,8 +93,8 @@ "assignMembersTasksToMonitorProgress": { "message": "Assign members tasks to monitor progress" }, - "onceYouReviewApps": { - "message": "Once you review applications and mark them as critical, you can assign tasks to members to resolve at-risk items and monitor progress here" + "onceYouReviewApplications": { + "message": "Once you review applications and mark them as critical, assign tasks to your members to change their passwords." }, "sendReminders": { "message": "Send reminders" @@ -178,41 +178,35 @@ } } }, - "noApplicationsInOrgTitle": { - "message": "No applications found for $ORG NAME$", - "placeholders": { - "org name": { - "content": "$1", - "example": "Company Name" - } - } + "noDataInOrgTitle": { + "message": "No data found" }, - "noApplicationsInOrgDescription": { - "message": "Import your organization's login data to start monitoring credential security risks. Once imported you get to:" + "noDataInOrgDescription": { + "message": "Import your organization's login data to get started with Access Intelligence. Once you do that, you'll be able to:" }, - "benefit1Title": { - "message": "Prioritize risks" + "feature1Title": { + "message": "Mark applications as critical" }, - "benefit1Description": { - "message": "Focus on applications that matter the most" + "feature1Description": { + "message": "This will help you remove risks to your most important applications first." }, - "benefit2Title": { - "message": "Guide remediation" + "feature2Title": { + "message": "Help members improve their security" }, - "benefit2Description": { - "message": "Assign at-risk members guided tasks to rotate at-risk credentials" + "feature2Description": { + "message": "Assign at-risk members guided security tasks to update credentials." }, - "benefit3Title": { + "feature3Title": { "message": "Monitor progress" }, - "benefit3Description": { - "message": "Track changes over time to show security improvements" + "feature3Description": { + "message": "Track changes over time to show security improvements." }, - "noReportRunTitle": { - "message": "Run your first report to see applications" + "noReportsRunTitle": { + "message": "Generate report" }, - "noReportRunDescription": { - "message": "Generate a risk insights report to analyze your organization's applications and identify at-risk passwords that need attention. Running your first report will:" + "noReportsRunDescription": { + "message": "You’re ready to start generating reports. Once you generate, you’ll be able to:" }, "noCriticalApplicationsTitle": { "message": "You haven’t marked any applications as critical" @@ -271,14 +265,14 @@ "atRiskMembers": { "message": "At-risk members" }, - "membersWithAccessToAtRiskItemsForCriticalApps": { - "message": "Members with access to at-risk items for critical applications" + "membersWithAccessToAtRiskItemsForCriticalApplications": { + "message": "These members have access to vulnerable items for critical applications." }, "membersWithAtRiskPasswords": { "message": "Members with at-risk passwords" }, - "membersWillReceiveNotification": { - "message": "Members will receive a notification to resolve at-risk logins through the browser extension." + "membersWillReceiveSecurityTask": { + "message": "Members of your organization will be assigned a task to change vulnerable passwords. They’ll receive a notification within their Bitwarden browser extension." }, "membersAtRiskCount": { "message": "$COUNT$ members at-risk", @@ -307,8 +301,8 @@ } } }, - "atRiskMembersDescription": { - "message": "These members are logging into applications with weak, exposed, or reused passwords." + "atRiskMemberDescription": { + "message": "These members are logging into critical applications with weak, exposed, or reused passwords." }, "atRiskMembersDescriptionNone": { "message": "These are no members logging into applications with weak, exposed, or reused passwords." @@ -391,14 +385,14 @@ "prioritizeCriticalApplications": { "message": "Prioritize critical applications" }, - "selectCriticalApplicationsDescription": { - "message": "Select which applications are most critical to your organization, then assign security tasks to members to resolve risks." + "selectCriticalAppsDescription": { + "message": "Select which applications are most critical to your organization. Then, you’ll be able to assign security tasks to members to remove risks." }, "reviewNewApplications": { "message": "Review new applications" }, - "reviewNewApplicationsDescription": { - "message": "We've highlighted at-risk items for new applications stored in Admin console that have weak, exposed, or reused passwords." + "reviewNewAppsDescription": { + "message": "Review new applications with vulnerable items and mark those you’d like to monitor closely as critical. Then, you’ll be able to assign security tasks to members to remove risks." }, "clickIconToMarkAppAsCritical": { "message": "Click the star icon to mark an app as critical" @@ -9856,8 +9850,8 @@ "assignTasks": { "message": "Assign tasks" }, - "assignTasksToMembers": { - "message": "Assign tasks to members for guided resolution" + "assignSecurityTasksToMembers": { + "message": "Send notifications to change passwords" }, "assignToCollections": { "message": "Assign to collections" diff --git a/apps/web/src/locales/fr/messages.json b/apps/web/src/locales/fr/messages.json index 8d51d685d7..d97fca90d5 100644 --- a/apps/web/src/locales/fr/messages.json +++ b/apps/web/src/locales/fr/messages.json @@ -93,8 +93,8 @@ "assignMembersTasksToMonitorProgress": { "message": "Affecter des tâches aux membres pour surveiller la progression" }, - "onceYouReviewApps": { - "message": "Une fois que vous examinez les applications et marquez comme critiques, vous pouvez assigner des tâches aux membres pour résoudre les éléments à risque et suivre les progrès ici" + "onceYouReviewApplications": { + "message": "Once you review applications and mark them as critical, assign tasks to your members to change their passwords." }, "sendReminders": { "message": "Envoyer des rappels" @@ -178,41 +178,35 @@ } } }, - "noApplicationsInOrgTitle": { - "message": "Aucune application trouvée pour $ORG NOM$", - "placeholders": { - "org name": { - "content": "$1", - "example": "Company Name" - } - } + "noDataInOrgTitle": { + "message": "No data found" }, - "noApplicationsInOrgDescription": { - "message": "Importez les données de connexion de votre organisation pour commencer à surveiller les risques de sécurité des identifiants. Une fois importé, vous pouvez :" + "noDataInOrgDescription": { + "message": "Import your organization's login data to get started with Access Intelligence. Once you do that, you'll be able to:" }, - "benefit1Title": { - "message": "Prioriser les risques" + "feature1Title": { + "message": "Mark applications as critical" }, - "benefit1Description": { - "message": "Vous concentrer sur les applications qui comptent le plus" + "feature1Description": { + "message": "This will help you remove risks to your most important applications first." }, - "benefit2Title": { - "message": "Guider la remédiation" + "feature2Title": { + "message": "Help members improve their security" }, - "benefit2Description": { - "message": "Assignez aux membres à risque des tâches guidées pour faire pivoter les identifiants à risque." + "feature2Description": { + "message": "Assign at-risk members guided security tasks to update credentials." }, - "benefit3Title": { - "message": "Suivre la progression" + "feature3Title": { + "message": "Monitor progress" }, - "benefit3Description": { - "message": "Suivre les changements au fil du temps pour afficher les améliorations de sécurité" + "feature3Description": { + "message": "Track changes over time to show security improvements." }, - "noReportRunTitle": { - "message": "Exécutez votre premier rapport pour voir les applications" + "noReportsRunTitle": { + "message": "Generate report" }, - "noReportRunDescription": { - "message": "Générer un rapport de connaissance des risques pour analyser les applications de votre organisation et identifier les mots de passe à risque qui nécessitent une attention. Exécuter votre premier rapport fera :" + "noReportsRunDescription": { + "message": "You’re ready to start generating reports. Once you generate, you’ll be able to:" }, "noCriticalApplicationsTitle": { "message": "Vous n'avez marqué aucune application comme critique" @@ -271,14 +265,14 @@ "atRiskMembers": { "message": "Membres à risque" }, - "membersWithAccessToAtRiskItemsForCriticalApps": { - "message": "Les membres ayant accès aux éléments à risque pour les applications critiques" + "membersWithAccessToAtRiskItemsForCriticalApplications": { + "message": "These members have access to vulnerable items for critical applications." }, "membersWithAtRiskPasswords": { "message": "Membres avec des mots de passe à risque" }, - "membersWillReceiveNotification": { - "message": "Les membres recevront une notification pour résoudre les identifiants à risque via l'extension du navigateur." + "membersWillReceiveSecurityTask": { + "message": "Members of your organization will be assigned a task to change vulnerable passwords. They’ll receive a notification within their Bitwarden browser extension." }, "membersAtRiskCount": { "message": "$COUNT$ membres à risque", @@ -307,8 +301,8 @@ } } }, - "atRiskMembersDescription": { - "message": "Ces membres se connectent à des applications avec des mots de passe faibles, exposés ou réutilisés." + "atRiskMemberDescription": { + "message": "These members are logging into critical applications with weak, exposed, or reused passwords." }, "atRiskMembersDescriptionNone": { "message": "Aucun membre ne se connecte dans des applications avec des mots de passe faibles, exposés ou réutilisés." @@ -391,14 +385,14 @@ "prioritizeCriticalApplications": { "message": "Prioriser les applications critiques" }, - "selectCriticalApplicationsDescription": { - "message": "Sélectionnez les applications les plus critiques pour votre organisation, puis attribuez des tâches de sécurité aux membres pour résoudre les risques." + "selectCriticalAppsDescription": { + "message": "Select which applications are most critical to your organization. Then, you’ll be able to assign security tasks to members to remove risks." }, "reviewNewApplications": { "message": "Examiner les nouvelles applications" }, - "reviewNewApplicationsDescription": { - "message": "Nous avons mis en évidence des éléments à risque pour les nouvelles applications stockées dans la console Admin qui ont des mots de passe faibles, exposés ou réutilisés." + "reviewNewAppsDescription": { + "message": "Review new applications with vulnerable items and mark those you’d like to monitor closely as critical. Then, you’ll be able to assign security tasks to members to remove risks." }, "clickIconToMarkAppAsCritical": { "message": "Cliquez sur l'icône étoile pour marquer une application comme critique" @@ -9856,8 +9850,8 @@ "assignTasks": { "message": "Assigner des tâches" }, - "assignTasksToMembers": { - "message": "Assigner des tâches aux membres pour une résolution guidée" + "assignSecurityTasksToMembers": { + "message": "Send notifications to change passwords" }, "assignToCollections": { "message": "Assigner aux collections" @@ -12159,9 +12153,9 @@ } }, "confirmNoSelectedCriticalApplicationsTitle": { - "message": "No critical applications are selected" + "message": "Aucune application critique n'est sélectionnée" }, "confirmNoSelectedCriticalApplicationsDesc": { - "message": "Are you sure you want to continue?" + "message": "Êtes-vous sûr de vouloir continuer ?" } } diff --git a/apps/web/src/locales/gl/messages.json b/apps/web/src/locales/gl/messages.json index e5c8ce9b49..c9fc10749d 100644 --- a/apps/web/src/locales/gl/messages.json +++ b/apps/web/src/locales/gl/messages.json @@ -93,8 +93,8 @@ "assignMembersTasksToMonitorProgress": { "message": "Assign members tasks to monitor progress" }, - "onceYouReviewApps": { - "message": "Once you review applications and mark them as critical, you can assign tasks to members to resolve at-risk items and monitor progress here" + "onceYouReviewApplications": { + "message": "Once you review applications and mark them as critical, assign tasks to your members to change their passwords." }, "sendReminders": { "message": "Send reminders" @@ -178,41 +178,35 @@ } } }, - "noApplicationsInOrgTitle": { - "message": "No applications found for $ORG NAME$", - "placeholders": { - "org name": { - "content": "$1", - "example": "Company Name" - } - } + "noDataInOrgTitle": { + "message": "No data found" }, - "noApplicationsInOrgDescription": { - "message": "Import your organization's login data to start monitoring credential security risks. Once imported you get to:" + "noDataInOrgDescription": { + "message": "Import your organization's login data to get started with Access Intelligence. Once you do that, you'll be able to:" }, - "benefit1Title": { - "message": "Prioritize risks" + "feature1Title": { + "message": "Mark applications as critical" }, - "benefit1Description": { - "message": "Focus on applications that matter the most" + "feature1Description": { + "message": "This will help you remove risks to your most important applications first." }, - "benefit2Title": { - "message": "Guide remediation" + "feature2Title": { + "message": "Help members improve their security" }, - "benefit2Description": { - "message": "Assign at-risk members guided tasks to rotate at-risk credentials" + "feature2Description": { + "message": "Assign at-risk members guided security tasks to update credentials." }, - "benefit3Title": { + "feature3Title": { "message": "Monitor progress" }, - "benefit3Description": { - "message": "Track changes over time to show security improvements" + "feature3Description": { + "message": "Track changes over time to show security improvements." }, - "noReportRunTitle": { - "message": "Run your first report to see applications" + "noReportsRunTitle": { + "message": "Generate report" }, - "noReportRunDescription": { - "message": "Generate a risk insights report to analyze your organization's applications and identify at-risk passwords that need attention. Running your first report will:" + "noReportsRunDescription": { + "message": "You’re ready to start generating reports. Once you generate, you’ll be able to:" }, "noCriticalApplicationsTitle": { "message": "You haven’t marked any applications as critical" @@ -271,14 +265,14 @@ "atRiskMembers": { "message": "At-risk members" }, - "membersWithAccessToAtRiskItemsForCriticalApps": { - "message": "Members with access to at-risk items for critical applications" + "membersWithAccessToAtRiskItemsForCriticalApplications": { + "message": "These members have access to vulnerable items for critical applications." }, "membersWithAtRiskPasswords": { "message": "Members with at-risk passwords" }, - "membersWillReceiveNotification": { - "message": "Members will receive a notification to resolve at-risk logins through the browser extension." + "membersWillReceiveSecurityTask": { + "message": "Members of your organization will be assigned a task to change vulnerable passwords. They’ll receive a notification within their Bitwarden browser extension." }, "membersAtRiskCount": { "message": "$COUNT$ members at-risk", @@ -307,8 +301,8 @@ } } }, - "atRiskMembersDescription": { - "message": "These members are logging into applications with weak, exposed, or reused passwords." + "atRiskMemberDescription": { + "message": "These members are logging into critical applications with weak, exposed, or reused passwords." }, "atRiskMembersDescriptionNone": { "message": "These are no members logging into applications with weak, exposed, or reused passwords." @@ -391,14 +385,14 @@ "prioritizeCriticalApplications": { "message": "Prioritize critical applications" }, - "selectCriticalApplicationsDescription": { - "message": "Select which applications are most critical to your organization, then assign security tasks to members to resolve risks." + "selectCriticalAppsDescription": { + "message": "Select which applications are most critical to your organization. Then, you’ll be able to assign security tasks to members to remove risks." }, "reviewNewApplications": { "message": "Review new applications" }, - "reviewNewApplicationsDescription": { - "message": "We've highlighted at-risk items for new applications stored in Admin console that have weak, exposed, or reused passwords." + "reviewNewAppsDescription": { + "message": "Review new applications with vulnerable items and mark those you’d like to monitor closely as critical. Then, you’ll be able to assign security tasks to members to remove risks." }, "clickIconToMarkAppAsCritical": { "message": "Click the star icon to mark an app as critical" @@ -9856,8 +9850,8 @@ "assignTasks": { "message": "Assign tasks" }, - "assignTasksToMembers": { - "message": "Assign tasks to members for guided resolution" + "assignSecurityTasksToMembers": { + "message": "Send notifications to change passwords" }, "assignToCollections": { "message": "Assign to collections" diff --git a/apps/web/src/locales/he/messages.json b/apps/web/src/locales/he/messages.json index b60e76f6a7..5eb5c7969e 100644 --- a/apps/web/src/locales/he/messages.json +++ b/apps/web/src/locales/he/messages.json @@ -21,13 +21,13 @@ "message": "סיכון סיסמה" }, "noEditPermissions": { - "message": "You don't have permission to edit this item" + "message": "אין לך הרשאות לערוך את הפריט הזה" }, "reviewAtRiskPasswords": { "message": "סקור סיסמאות בסיכון (חלשות, חשופות, או משומשות) בין יישומים. בחר את היישומים הכי קריטיים שלך על מנת לתעדף פעולות אבטחה עבור המשתמשים שלך כדי לטפל בסיסמאות בסיכון." }, "reviewAtRiskLoginsPrompt": { - "message": "Review at-risk logins" + "message": "סקור כניסות בסיכון" }, "dataLastUpdated": { "message": "הנתונים עודכנו לאחרונה: $DATE$", @@ -93,8 +93,8 @@ "assignMembersTasksToMonitorProgress": { "message": "הקצה משימות לחברים כדי לנטר התקדמות" }, - "onceYouReviewApps": { - "message": "לאחר שתסקור יישומים ותסמן אותם כקריטיים, באפשרותך להקצות משימות לחברים כדי לפתור פריטים בסיכון ולנטר התקדמות כאן" + "onceYouReviewApplications": { + "message": "Once you review applications and mark them as critical, assign tasks to your members to change their passwords." }, "sendReminders": { "message": "שלח תזכורות" @@ -131,7 +131,7 @@ } }, "criticalApplicationsMarked": { - "message": "critical applications marked" + "message": "יישומים קריטיים סומנו" }, "countOfCriticalApplications": { "message": "$COUNT$ יישומים קריטיים", @@ -178,41 +178,35 @@ } } }, - "noApplicationsInOrgTitle": { - "message": "לא נמצאו יישומים עבור $ORG NAME", - "placeholders": { - "org name": { - "content": "$1", - "example": "Company Name" - } - } + "noDataInOrgTitle": { + "message": "No data found" }, - "noApplicationsInOrgDescription": { - "message": "ייבא את נתוני הכניסה של הארגון שלך כדי להתחיל בניטור סיכוני אבטחה של אישורים. לאחר הייבוא תוכל:" + "noDataInOrgDescription": { + "message": "Import your organization's login data to get started with Access Intelligence. Once you do that, you'll be able to:" }, - "benefit1Title": { - "message": "לתעדף סיכונים" + "feature1Title": { + "message": "Mark applications as critical" }, - "benefit1Description": { - "message": "התמקדות ביישומים החשובים ביותר" + "feature1Description": { + "message": "This will help you remove risks to your most important applications first." }, - "benefit2Title": { - "message": "להדריך תיקון" + "feature2Title": { + "message": "Help members improve their security" }, - "benefit2Description": { - "message": "הקצה משימות מודרכות לחברים בסיכון כדי להחליף אישורים בסיכון" + "feature2Description": { + "message": "Assign at-risk members guided security tasks to update credentials." }, - "benefit3Title": { - "message": "לנטר התקדמות" + "feature3Title": { + "message": "Monitor progress" }, - "benefit3Description": { - "message": "עקוב אחר שינויים לאורך זמן כדי להציג שיפורי אבטחה" + "feature3Description": { + "message": "Track changes over time to show security improvements." }, - "noReportRunTitle": { - "message": "הרץ את הדוח הראשון שלך כדי לראות יישומים" + "noReportsRunTitle": { + "message": "Generate report" }, - "noReportRunDescription": { - "message": "ייצר דוח תובנות סיכון כדי לנתח את היישומים של הארגון שלך ולזהות סיסמאות בסיכון שצריכות תשומת לב. הרצת הדוח הראשון שלך תגרום ל:" + "noReportsRunDescription": { + "message": "You’re ready to start generating reports. Once you generate, you’ll be able to:" }, "noCriticalApplicationsTitle": { "message": "לא סימנת אף יישום כקריטי" @@ -242,7 +236,7 @@ "message": "יישומים המסומנים כקריטיים" }, "criticalApplicationsMarkedSuccess": { - "message": "$COUNT$ applications marked as critical", + "message": "$COUNT$ יישומים סומנו כקריטיים", "placeholders": { "count": { "content": "$1", @@ -271,14 +265,14 @@ "atRiskMembers": { "message": "חברים בסיכון" }, - "membersWithAccessToAtRiskItemsForCriticalApps": { - "message": "חברים עם גישה לפריטים בסיכון עבור יישומים קריטיים" + "membersWithAccessToAtRiskItemsForCriticalApplications": { + "message": "These members have access to vulnerable items for critical applications." }, "membersWithAtRiskPasswords": { - "message": "Members with at-risk passwords" + "message": "חברים עם סיסמאות בסיכון" }, - "membersWillReceiveNotification": { - "message": "Members will receive a notification to resolve at-risk logins through the browser extension." + "membersWillReceiveSecurityTask": { + "message": "Members of your organization will be assigned a task to change vulnerable passwords. They’ll receive a notification within their Bitwarden browser extension." }, "membersAtRiskCount": { "message": "$COUNT$ חברים בסיכון", @@ -307,8 +301,8 @@ } } }, - "atRiskMembersDescription": { - "message": "חברים אלה נכנסו אל יישומים עם סיסמאות חלשות, חשופות, או משומשות." + "atRiskMemberDescription": { + "message": "These members are logging into critical applications with weak, exposed, or reused passwords." }, "atRiskMembersDescriptionNone": { "message": "אין חברים שנכנסו אל יישומים עם סיסמאות חלשות, חשופות, או משומשות." @@ -350,7 +344,7 @@ "message": "יישומים צריכים סקירה" }, "newApplicationsCardTitle": { - "message": "Review new applications" + "message": "סקור יישומים חדשים" }, "newApplicationsWithCount": { "message": "$COUNT$ יישומים חדשים", @@ -368,7 +362,7 @@ "message": "סקור עכשיו" }, "allCaughtUp": { - "message": "All caught up!" + "message": "הכל טופל!" }, "noNewApplicationsToReviewAtThisTime": { "message": "No new applications to review at this time" @@ -386,19 +380,19 @@ "message": "Review applications to secure the items most critical to your organization's security" }, "reviewApplications": { - "message": "Review applications" + "message": "סקור יישומים" }, "prioritizeCriticalApplications": { "message": "תעדוף יישומים קריטיים" }, - "selectCriticalApplicationsDescription": { - "message": "Select which applications are most critical to your organization, then assign security tasks to members to resolve risks." + "selectCriticalAppsDescription": { + "message": "Select which applications are most critical to your organization. Then, you’ll be able to assign security tasks to members to remove risks." }, "reviewNewApplications": { - "message": "Review new applications" + "message": "סקור יישומים חדשים" }, - "reviewNewApplicationsDescription": { - "message": "We've highlighted at-risk items for new applications stored in Admin console that have weak, exposed, or reused passwords." + "reviewNewAppsDescription": { + "message": "Review new applications with vulnerable items and mark those you’d like to monitor closely as critical. Then, you’ll be able to assign security tasks to members to remove risks." }, "clickIconToMarkAppAsCritical": { "message": "Click the star icon to mark an app as critical" @@ -881,7 +875,7 @@ "message": "מועדפים" }, "taskSummary": { - "message": "Task summary" + "message": "סיכום משימה" }, "types": { "message": "סוגים" @@ -3251,16 +3245,16 @@ "message": "החיוב הבא" }, "nextChargeHeader": { - "message": "Next Charge" + "message": "החיוב הבא" }, "plan": { - "message": "Plan" + "message": "תוכנית" }, "details": { "message": "פרטים" }, "discount": { - "message": "discount" + "message": "הנחה" }, "downloadLicense": { "message": "הורד רישיון" @@ -5856,14 +5850,14 @@ "message": "איך להפעיל אישור משתמש אוטומטי" }, "autoConfirmExtension1": { - "message": "Open your Bitwarden extension" + "message": "פתח את הרחבת Bitwarden שלך" }, "autoConfirmExtension2": { - "message": "Select", + "message": "בחר", "description": "This is a fragment of a larger sencence. The whole sentence will read: 'Select Turn on'" }, "autoConfirmExtension3": { - "message": " Turn on", + "message": " הפעל", "description": "This is a fragment of a larger sencence. The whole sentence will read: 'Select Turn on'" }, "autoConfirmExtensionOpened": { @@ -5954,13 +5948,13 @@ "description": "'Send' is a noun and the name of a feature called 'Bitwarden Send'. It should not be translated." }, "uriMatchDetectionPolicy": { - "message": "Default URI match detection" + "message": "ברירת מחדל לזיהוי התאמת URI" }, "uriMatchDetectionPolicyDesc": { "message": "Determine when logins are suggested for autofill. Admins and owners are exempt from this policy." }, "uriMatchDetectionOptionsLabel": { - "message": "Default URI match detection" + "message": "ברירת מחדל לזיהוי התאמת URI" }, "invalidUriMatchDefaultPolicySetting": { "message": "Please select a valid URI match detection option.", @@ -9856,8 +9850,8 @@ "assignTasks": { "message": "הקצה משימות" }, - "assignTasksToMembers": { - "message": "Assign tasks to members for guided resolution" + "assignSecurityTasksToMembers": { + "message": "Send notifications to change passwords" }, "assignToCollections": { "message": "הקצה לאוספים" @@ -12125,28 +12119,28 @@ "message": "התחל ניסיון משפחות בחינם" }, "unlockMethodNeededToChangeTimeoutActionDesc": { - "message": "Set up an unlock method to change your vault timeout action." + "message": "הגדר שיטת ביטול נעילה כדי לשנות את פעולת פסק הזמן לכספת שלך." }, "vaultTimeoutPolicyAffectingOptions": { - "message": "Enterprise policy requirements have been applied to your timeout options" + "message": "דרישות מדיניות ארגונית הוחלו על אפשרויות פסק הזמן שלך" }, "vaultTimeoutTooLarge": { - "message": "Your vault timeout exceeds the restrictions set by your organization." + "message": "פסק הזמן לכספת שלך חורג מהמגבלות שנקבעו על ידי הארגון שלך." }, "neverLockWarning": { - "message": "Are you sure you want to use the \"Never\" option? Setting your lock options to \"Never\" stores your vault's encryption key on your device. If you use this option you should ensure that you keep your device properly protected." + "message": "האם אתה בטוח שברצונך להשתמש באפשרות \"אף פעם לא\"? במצב זה הסיסמה לכספת שלך תשמר על המכשיר שלך. אם תשתמש באפשרות זו עליך לוודא כי המכשיר מאובטח כראוי." }, "sessionTimeoutSettingsAction": { - "message": "Timeout action" + "message": "פעולת פסק זמן" }, "sessionTimeoutHeader": { - "message": "Session timeout" + "message": "פסק זמן להפעלה" }, "appearance": { - "message": "Appearance" + "message": "מראה" }, "vaultTimeoutPolicyMaximumError": { - "message": "Timeout exceeds the restriction set by your organization: $HOURS$ hour(s) and $MINUTES$ minute(s) maximum", + "message": "פסק זמן חורג את ההגבלה שהוגדרה על ידי הארגון שלך: $HOURS$ שעות ו־$MINUTES$ דקות לכל היותר", "placeholders": { "hours": { "content": "$1", @@ -12159,7 +12153,7 @@ } }, "confirmNoSelectedCriticalApplicationsTitle": { - "message": "No critical applications are selected" + "message": "לא סומנו יישומים קריטים" }, "confirmNoSelectedCriticalApplicationsDesc": { "message": "Are you sure you want to continue?" diff --git a/apps/web/src/locales/hi/messages.json b/apps/web/src/locales/hi/messages.json index 01cf40c3c0..766c6c3e8b 100644 --- a/apps/web/src/locales/hi/messages.json +++ b/apps/web/src/locales/hi/messages.json @@ -93,8 +93,8 @@ "assignMembersTasksToMonitorProgress": { "message": "Assign members tasks to monitor progress" }, - "onceYouReviewApps": { - "message": "Once you review applications and mark them as critical, you can assign tasks to members to resolve at-risk items and monitor progress here" + "onceYouReviewApplications": { + "message": "Once you review applications and mark them as critical, assign tasks to your members to change their passwords." }, "sendReminders": { "message": "Send reminders" @@ -178,41 +178,35 @@ } } }, - "noApplicationsInOrgTitle": { - "message": "No applications found for $ORG NAME$", - "placeholders": { - "org name": { - "content": "$1", - "example": "Company Name" - } - } + "noDataInOrgTitle": { + "message": "No data found" }, - "noApplicationsInOrgDescription": { - "message": "Import your organization's login data to start monitoring credential security risks. Once imported you get to:" + "noDataInOrgDescription": { + "message": "Import your organization's login data to get started with Access Intelligence. Once you do that, you'll be able to:" }, - "benefit1Title": { - "message": "Prioritize risks" + "feature1Title": { + "message": "Mark applications as critical" }, - "benefit1Description": { - "message": "Focus on applications that matter the most" + "feature1Description": { + "message": "This will help you remove risks to your most important applications first." }, - "benefit2Title": { - "message": "Guide remediation" + "feature2Title": { + "message": "Help members improve their security" }, - "benefit2Description": { - "message": "Assign at-risk members guided tasks to rotate at-risk credentials" + "feature2Description": { + "message": "Assign at-risk members guided security tasks to update credentials." }, - "benefit3Title": { + "feature3Title": { "message": "Monitor progress" }, - "benefit3Description": { - "message": "Track changes over time to show security improvements" + "feature3Description": { + "message": "Track changes over time to show security improvements." }, - "noReportRunTitle": { - "message": "Run your first report to see applications" + "noReportsRunTitle": { + "message": "Generate report" }, - "noReportRunDescription": { - "message": "Generate a risk insights report to analyze your organization's applications and identify at-risk passwords that need attention. Running your first report will:" + "noReportsRunDescription": { + "message": "You’re ready to start generating reports. Once you generate, you’ll be able to:" }, "noCriticalApplicationsTitle": { "message": "You haven’t marked any applications as critical" @@ -271,14 +265,14 @@ "atRiskMembers": { "message": "At-risk members" }, - "membersWithAccessToAtRiskItemsForCriticalApps": { - "message": "Members with access to at-risk items for critical applications" + "membersWithAccessToAtRiskItemsForCriticalApplications": { + "message": "These members have access to vulnerable items for critical applications." }, "membersWithAtRiskPasswords": { "message": "Members with at-risk passwords" }, - "membersWillReceiveNotification": { - "message": "Members will receive a notification to resolve at-risk logins through the browser extension." + "membersWillReceiveSecurityTask": { + "message": "Members of your organization will be assigned a task to change vulnerable passwords. They’ll receive a notification within their Bitwarden browser extension." }, "membersAtRiskCount": { "message": "$COUNT$ members at-risk", @@ -307,8 +301,8 @@ } } }, - "atRiskMembersDescription": { - "message": "These members are logging into applications with weak, exposed, or reused passwords." + "atRiskMemberDescription": { + "message": "These members are logging into critical applications with weak, exposed, or reused passwords." }, "atRiskMembersDescriptionNone": { "message": "These are no members logging into applications with weak, exposed, or reused passwords." @@ -391,14 +385,14 @@ "prioritizeCriticalApplications": { "message": "Prioritize critical applications" }, - "selectCriticalApplicationsDescription": { - "message": "Select which applications are most critical to your organization, then assign security tasks to members to resolve risks." + "selectCriticalAppsDescription": { + "message": "Select which applications are most critical to your organization. Then, you’ll be able to assign security tasks to members to remove risks." }, "reviewNewApplications": { "message": "Review new applications" }, - "reviewNewApplicationsDescription": { - "message": "We've highlighted at-risk items for new applications stored in Admin console that have weak, exposed, or reused passwords." + "reviewNewAppsDescription": { + "message": "Review new applications with vulnerable items and mark those you’d like to monitor closely as critical. Then, you’ll be able to assign security tasks to members to remove risks." }, "clickIconToMarkAppAsCritical": { "message": "Click the star icon to mark an app as critical" @@ -9856,8 +9850,8 @@ "assignTasks": { "message": "Assign tasks" }, - "assignTasksToMembers": { - "message": "Assign tasks to members for guided resolution" + "assignSecurityTasksToMembers": { + "message": "Send notifications to change passwords" }, "assignToCollections": { "message": "Assign to collections" diff --git a/apps/web/src/locales/hr/messages.json b/apps/web/src/locales/hr/messages.json index e0f0ce0b28..a0dbd290ab 100644 --- a/apps/web/src/locales/hr/messages.json +++ b/apps/web/src/locales/hr/messages.json @@ -93,8 +93,8 @@ "assignMembersTasksToMonitorProgress": { "message": "Dodijeli članovima zadatke za praćenje napretka" }, - "onceYouReviewApps": { - "message": "Nakon što pregledaš prijave i označiš kritične, možeš dodijeliti zadatke članovima za rješavanje rizičnih stavki i ovdje pratiti napredak" + "onceYouReviewApplications": { + "message": "Once you review applications and mark them as critical, assign tasks to your members to change their passwords." }, "sendReminders": { "message": "Pošalji podsjetnike" @@ -178,41 +178,35 @@ } } }, - "noApplicationsInOrgTitle": { - "message": "Nisu nađene aplikacije u $ORG NAME$", - "placeholders": { - "org name": { - "content": "$1", - "example": "Company Name" - } - } + "noDataInOrgTitle": { + "message": "No data found" }, - "noApplicationsInOrgDescription": { - "message": "Uvezi podatke za prijavu svoje organizacije za početak praćenja sigurnosnih rizika vjerodajnica. Nakon uvoza možeš:" + "noDataInOrgDescription": { + "message": "Import your organization's login data to get started with Access Intelligence. Once you do that, you'll be able to:" }, - "benefit1Title": { - "message": "Prioritizirajte rizike" + "feature1Title": { + "message": "Mark applications as critical" }, - "benefit1Description": { - "message": "Usredotoči se na najvažnije aplikacije" + "feature1Description": { + "message": "This will help you remove risks to your most important applications first." }, - "benefit2Title": { - "message": "Vodič za sanaciju" + "feature2Title": { + "message": "Help members improve their security" }, - "benefit2Description": { - "message": "Dodijeli vođene zadatke rizičnim članovima za rotaciju rizičnih vjerodajnica" + "feature2Description": { + "message": "Assign at-risk members guided security tasks to update credentials." }, - "benefit3Title": { - "message": "Prati napredak" + "feature3Title": { + "message": "Monitor progress" }, - "benefit3Description": { - "message": "Prati promjene tijekom vremena za prikaz sigurnosnih poboljšanja" + "feature3Description": { + "message": "Track changes over time to show security improvements." }, - "noReportRunTitle": { - "message": "Za pregled aplikacija, pokreni svoje prvo izvješće" + "noReportsRunTitle": { + "message": "Generate report" }, - "noReportRunDescription": { - "message": "Generiraj izvješće o uvidima u rizike za analizu aplikacije svoje organizacije i identifikaciju lozinki koje su u riziku i kojima je potrebna pozornost. Pokretanje tvojeg prvog izvješća će:" + "noReportsRunDescription": { + "message": "You’re ready to start generating reports. Once you generate, you’ll be able to:" }, "noCriticalApplicationsTitle": { "message": "Niti jedna aplikacija nije označena kao kritična" @@ -271,14 +265,14 @@ "atRiskMembers": { "message": "Rizični korisnici" }, - "membersWithAccessToAtRiskItemsForCriticalApps": { - "message": "Članovi koji imaju pristup stavkama za aplikacije označene kao kritične" + "membersWithAccessToAtRiskItemsForCriticalApplications": { + "message": "These members have access to vulnerable items for critical applications." }, "membersWithAtRiskPasswords": { "message": "Članovi s rizičnim lozinkama" }, - "membersWillReceiveNotification": { - "message": "Članovi će dobiti obavijest o rješavanju rizičnih prijava putem proširenja preglednika." + "membersWillReceiveSecurityTask": { + "message": "Members of your organization will be assigned a task to change vulnerable passwords. They’ll receive a notification within their Bitwarden browser extension." }, "membersAtRiskCount": { "message": "Rizičnih članova: $COUNT$", @@ -307,8 +301,8 @@ } } }, - "atRiskMembersDescription": { - "message": "Ovi članovi se prijavljuju u aplikacije slabim, izloženim ili ponovno korištenim lozinkama." + "atRiskMemberDescription": { + "message": "These members are logging into critical applications with weak, exposed, or reused passwords." }, "atRiskMembersDescriptionNone": { "message": "Nema članova koji se prijavljuju slabim, izloženim ili ponovno korištenim lozinkama." @@ -391,14 +385,14 @@ "prioritizeCriticalApplications": { "message": "Daj prioritet kritičnim aplikacijama" }, - "selectCriticalApplicationsDescription": { - "message": "Odaberi koje su aplikacije najvažnije za tvoju organizaciju, a zatim dodijeli sigurnosne zadatke članovima kako bi se riješili rizici." + "selectCriticalAppsDescription": { + "message": "Select which applications are most critical to your organization. Then, you’ll be able to assign security tasks to members to remove risks." }, "reviewNewApplications": { "message": "Pregledaj nove prijave" }, - "reviewNewApplicationsDescription": { - "message": "Istaknuli smo rizične stavke za nove aplikacije pohranjene u administratorskoj konzoli koje imaju slabe, otkrivene ili ponovno korištene lozinke." + "reviewNewAppsDescription": { + "message": "Review new applications with vulnerable items and mark those you’d like to monitor closely as critical. Then, you’ll be able to assign security tasks to members to remove risks." }, "clickIconToMarkAppAsCritical": { "message": "Klikni ikonu zvjezdice za označavanje aplikacije kao kritične" @@ -9856,8 +9850,8 @@ "assignTasks": { "message": "Dodijeli zadatke" }, - "assignTasksToMembers": { - "message": "Dodijeli zadatke članovima za vođeno rješavanje" + "assignSecurityTasksToMembers": { + "message": "Send notifications to change passwords" }, "assignToCollections": { "message": "Dodijeli zbirkama" diff --git a/apps/web/src/locales/hu/messages.json b/apps/web/src/locales/hu/messages.json index d9bbd09b0f..df292a29c0 100644 --- a/apps/web/src/locales/hu/messages.json +++ b/apps/web/src/locales/hu/messages.json @@ -93,8 +93,8 @@ "assignMembersTasksToMonitorProgress": { "message": "Rendeljünk a tagokhoz feladatokat az előrehaladás monitorozására." }, - "onceYouReviewApps": { - "message": "Miután az alkalmazásokat áttekintettük és kritikusként jelöltük meg azokat, feladatokat rendelhetünk a tagokhoz a kockázatos elemek megoldására és itt nyomon követhetjük a feldolgozást." + "onceYouReviewApplications": { + "message": "Az alkalmazások áttekintése és azok kritikusként megjelölése után rendeljünk feladatokat a tagoknak a jelszavak megváltoztatásához." }, "sendReminders": { "message": "Emlékeztető küldés" @@ -178,41 +178,35 @@ } } }, - "noApplicationsInOrgTitle": { - "message": "Nem találhatók alkalmazások: $ORG NAME$", - "placeholders": { - "org name": { - "content": "$1", - "example": "Company Name" - } - } + "noDataInOrgTitle": { + "message": "Nem található adat." }, - "noApplicationsInOrgDescription": { - "message": "A szervezet bejelentkezési adatainak importálása a hitelesítő adatok biztonsági kockázat figyelésének megkezdéséhez. Az importálás után a következőkhöz jutunk el:" + "noDataInOrgDescription": { + "message": "Importáljuk a szervezet bejelentkezési adatait az Access Intelligence használatának megkezdéséhez. Ezután a következőket tehetjük:" }, - "benefit1Title": { - "message": "Kockázatok rangsorolása" + "feature1Title": { + "message": "Alkalmazások megjelölése kritikusként" }, - "benefit1Description": { - "message": "Összpontosítás a legfontosabb alkalmazásokra" + "feature1Description": { + "message": "Ez először is segít eltávolítani a legfontosabb alkalmazások kockázatait." }, - "benefit2Title": { - "message": "Kármentési útmutató" + "feature2Title": { + "message": "Segítsünk a tagoknak biztonságuk javításában." }, - "benefit2Description": { - "message": "Irányított feladatok hozzárendelése a veszélyeztetett tagokhoz a veszélyeztetett jogosultságok rotálásához." + "feature2Description": { + "message": "Rendeljünk a veszélyeztetett tagoknak irányított biztonsági feladatokat a hitelesítő adatok frissítéséhez." }, - "benefit3Title": { - "message": "Folyamatok nyomonkövetése" + "feature3Title": { + "message": "Folyamat nyomonkövetése" }, - "benefit3Description": { - "message": "Kövessük az idő múlásával bekövetkező változásokat a biztonsági fejlesztések megjelenítéséhez." + "feature3Description": { + "message": "Kövessük nyomon az időbeli változásokat a biztonsági fejlesztések megjelenítéséhez." }, - "noReportRunTitle": { - "message": "Futtassuk le az első jelentést az alkalmazások megtekintéséhez" + "noReportsRunTitle": { + "message": "Jelentés generálása" }, - "noReportRunDescription": { - "message": "Készítsünk kockázati betekintés jelentést a szervezet alkalmazásainak elemzéséhez és azonosítsuk azokat a veszélyeztetett jelszavakat, amelyekre figyelmet kell fordítani. Az első jelentés futtatása:" + "noReportsRunDescription": { + "message": "Készen állunk a jelentések generálására. A generálás után a következőket teheti meg:" }, "noCriticalApplicationsTitle": { "message": "Egyetlen alkalmazás sem lett megjelölve kritikusként." @@ -271,14 +265,14 @@ "atRiskMembers": { "message": "Veszélyes tagok" }, - "membersWithAccessToAtRiskItemsForCriticalApps": { - "message": "Members with access to at-risk items for critical applications" + "membersWithAccessToAtRiskItemsForCriticalApplications": { + "message": "Ezek a tagok hozzáférhetnek a kritikus alkalmazásoknál a sebezhető elemekhez." }, "membersWithAtRiskPasswords": { "message": "Kockázatos jelszavú tagok" }, - "membersWillReceiveNotification": { - "message": "A tagok értesítést kapnak a kockázatos bejelentkezések megoldásáról a böngésző bővítményen keresztül." + "membersWillReceiveSecurityTask": { + "message": "A szervezet tagjaira feladat hárul a sebezhető jelszavak megváltoztatására. Értesítést kapnak a Bitwarden böngésző bővítményen belül." }, "membersAtRiskCount": { "message": "$COUNT$ kockázatos tag", @@ -307,8 +301,8 @@ } } }, - "atRiskMembersDescription": { - "message": "Ezek a tagok gyenge, nyílt vagy újrafelhasznált jelszavakkal jelentkeznek be az alkalmazásokba." + "atRiskMemberDescription": { + "message": "Ezek a tagok gyenge, kitett vagy újrafelhasznált jelszavakkal jelentkeznek be az alkalmazásokba." }, "atRiskMembersDescriptionNone": { "message": "Ezek nem olyan tagok, akik gyenge, kitett vagy újrafelhasznált jelszavakkal jelentkeznek be az alkalmazásokba." @@ -391,14 +385,14 @@ "prioritizeCriticalApplications": { "message": "Kritikus alkalmazások rangsorolása" }, - "selectCriticalApplicationsDescription": { - "message": "Válasszuk ki, hogy mely alkalmazások a legkritikusabbak a szervezet számára, majd rendeljünk biztonsági feladatokat a tagokhoz a kockázatok megoldása érdekében." + "selectCriticalAppsDescription": { + "message": "Válasszuk ki, hogy mely alkalmazások a legkritikusabbak a szervezet számára. Ezután rendeljünk biztonsági feladatokat a tagokhoz a kockázatok eltávolítása érdekében." }, "reviewNewApplications": { "message": "Új alkalmazások felülvizsgálata" }, - "reviewNewApplicationsDescription": { - "message": "Kiemelésre került az Admin konzolban tárolt új alkalmazások veszélyeztetett elemei, amelyek gyenge, kitett vagy újrafelhasznált jelszavakkal rendelkeznek." + "reviewNewAppsDescription": { + "message": "Tekintsük át a sebezhető elemeket tartalmazó új alkalmazásokat és jelöljük meg kritikusnak azokat, amelyeket szorosan figyelemmel szeretnénk kísérni. Ezután biztonsági feladatokat rendelhetünk a tagokhoz a kockázatok eltávolítása érdekében." }, "clickIconToMarkAppAsCritical": { "message": "Kattintsunk a csillag ikonra egy alkalmazás kritikusként megjelöléséhez." @@ -9856,8 +9850,8 @@ "assignTasks": { "message": "Feladatok hozzárendelése" }, - "assignTasksToMembers": { - "message": "Feladatok hozzárendelése a tagokhoz irányított megoldáshoz." + "assignSecurityTasksToMembers": { + "message": "Értesítések küldése a jelszavak megváltoztatásához" }, "assignToCollections": { "message": "Hozzárendelés gyűjteményekhez" diff --git a/apps/web/src/locales/id/messages.json b/apps/web/src/locales/id/messages.json index ad9d2405ad..388ca3ba9c 100644 --- a/apps/web/src/locales/id/messages.json +++ b/apps/web/src/locales/id/messages.json @@ -93,8 +93,8 @@ "assignMembersTasksToMonitorProgress": { "message": "Tetapkan tugas ke anggota untuk memantau progres" }, - "onceYouReviewApps": { - "message": "Setelah meninjau aplikasi dan menandainya sebagai penting, Anda dapat menetapkan tugas kepada anggota untuk menyelesaikan item berisiko dan memantau kemajuan di sini" + "onceYouReviewApplications": { + "message": "Once you review applications and mark them as critical, assign tasks to your members to change their passwords." }, "sendReminders": { "message": "Kirim pengingat" @@ -178,41 +178,35 @@ } } }, - "noApplicationsInOrgTitle": { - "message": "Tidak ada aplikasi ditemukan untuk $ORG NAME$", - "placeholders": { - "org name": { - "content": "$1", - "example": "Company Name" - } - } + "noDataInOrgTitle": { + "message": "No data found" }, - "noApplicationsInOrgDescription": { - "message": "Impor data login organisasi Anda untuk mulai memantau risiko keamanan kredensial. Setelah diimpor, Anda akan mendapatkan:" + "noDataInOrgDescription": { + "message": "Import your organization's login data to get started with Access Intelligence. Once you do that, you'll be able to:" }, - "benefit1Title": { - "message": "Prioritaskan risiko" + "feature1Title": { + "message": "Mark applications as critical" }, - "benefit1Description": { - "message": "Fokus pada aplikasi yang paling penting" + "feature1Description": { + "message": "This will help you remove risks to your most important applications first." }, - "benefit2Title": { - "message": "Guide remediation" + "feature2Title": { + "message": "Help members improve their security" }, - "benefit2Description": { - "message": "Assign at-risk members guided tasks to rotate at-risk credentials" + "feature2Description": { + "message": "Assign at-risk members guided security tasks to update credentials." }, - "benefit3Title": { - "message": "Memantau kemajuan" + "feature3Title": { + "message": "Monitor progress" }, - "benefit3Description": { - "message": "Lacak perubahan dari waktu ke waktu untuk menunjukkan peningkatan keamanan" + "feature3Description": { + "message": "Track changes over time to show security improvements." }, - "noReportRunTitle": { - "message": "Jalankan laporan pertama Anda untuk melihat aplikasi" + "noReportsRunTitle": { + "message": "Generate report" }, - "noReportRunDescription": { - "message": "Generate a risk insights report to analyze your organization's applications and identify at-risk passwords that need attention. Running your first report will:" + "noReportsRunDescription": { + "message": "You’re ready to start generating reports. Once you generate, you’ll be able to:" }, "noCriticalApplicationsTitle": { "message": "Anda belum menandai aplikasi apa pun sebagai penting" @@ -271,14 +265,14 @@ "atRiskMembers": { "message": "Anggota berisiko" }, - "membersWithAccessToAtRiskItemsForCriticalApps": { - "message": "Anggota dengan akses ke item berisiko untuk apl penting" + "membersWithAccessToAtRiskItemsForCriticalApplications": { + "message": "These members have access to vulnerable items for critical applications." }, "membersWithAtRiskPasswords": { "message": "Members with at-risk passwords" }, - "membersWillReceiveNotification": { - "message": "Members will receive a notification to resolve at-risk logins through the browser extension." + "membersWillReceiveSecurityTask": { + "message": "Members of your organization will be assigned a task to change vulnerable passwords. They’ll receive a notification within their Bitwarden browser extension." }, "membersAtRiskCount": { "message": "$COUNT$ anggota berisiko", @@ -307,8 +301,8 @@ } } }, - "atRiskMembersDescription": { - "message": "Anggota ini masuk ke aplikasi dengan sandi yang lemah, terekspos, atau sama." + "atRiskMemberDescription": { + "message": "These members are logging into critical applications with weak, exposed, or reused passwords." }, "atRiskMembersDescriptionNone": { "message": "Anggota ini masuk ke aplikasi dengan sandi yang lemah, terekspos, atau sama." @@ -391,14 +385,14 @@ "prioritizeCriticalApplications": { "message": "Prioritaskan aplikasi penting" }, - "selectCriticalApplicationsDescription": { - "message": "Select which applications are most critical to your organization, then assign security tasks to members to resolve risks." + "selectCriticalAppsDescription": { + "message": "Select which applications are most critical to your organization. Then, you’ll be able to assign security tasks to members to remove risks." }, "reviewNewApplications": { "message": "Review new applications" }, - "reviewNewApplicationsDescription": { - "message": "We've highlighted at-risk items for new applications stored in Admin console that have weak, exposed, or reused passwords." + "reviewNewAppsDescription": { + "message": "Review new applications with vulnerable items and mark those you’d like to monitor closely as critical. Then, you’ll be able to assign security tasks to members to remove risks." }, "clickIconToMarkAppAsCritical": { "message": "Click the star icon to mark an app as critical" @@ -9856,8 +9850,8 @@ "assignTasks": { "message": "Assign tasks" }, - "assignTasksToMembers": { - "message": "Assign tasks to members for guided resolution" + "assignSecurityTasksToMembers": { + "message": "Send notifications to change passwords" }, "assignToCollections": { "message": "Assign to collections" diff --git a/apps/web/src/locales/it/messages.json b/apps/web/src/locales/it/messages.json index fa3146996d..b60e8f4584 100644 --- a/apps/web/src/locales/it/messages.json +++ b/apps/web/src/locales/it/messages.json @@ -93,8 +93,8 @@ "assignMembersTasksToMonitorProgress": { "message": "Assegna compiti ai membri per monitorarne i progressi" }, - "onceYouReviewApps": { - "message": "Dopo aver esaminato le applicazioni e contrassegnato quelle critiche, puoi assegnare attività ai membri per risolvere gli elementi a rischio e monitorare qui lo stato di avanzamento" + "onceYouReviewApplications": { + "message": "Once you review applications and mark them as critical, assign tasks to your members to change their passwords." }, "sendReminders": { "message": "Invia promemoria" @@ -178,41 +178,35 @@ } } }, - "noApplicationsInOrgTitle": { - "message": "Nessuna applicazione trovata per $ORG NAME$", - "placeholders": { - "org name": { - "content": "$1", - "example": "Company Name" - } - } + "noDataInOrgTitle": { + "message": "No data found" }, - "noApplicationsInOrgDescription": { - "message": "Importa i dati di accesso della tua organizzazione per iniziare a monitorare i rischi per la sicurezza delle credenziali. Una volta importati, potrai:" + "noDataInOrgDescription": { + "message": "Import your organization's login data to get started with Access Intelligence. Once you do that, you'll be able to:" }, - "benefit1Title": { - "message": "Priorità dei rischi" + "feature1Title": { + "message": "Mark applications as critical" }, - "benefit1Description": { - "message": "Concentrati sulle applicazioni più importanti" + "feature1Description": { + "message": "This will help you remove risks to your most important applications first." }, - "benefit2Title": { - "message": "Guide remediation" + "feature2Title": { + "message": "Help members improve their security" }, - "benefit2Description": { - "message": "Assign at-risk members guided tasks to rotate at-risk credentials" + "feature2Description": { + "message": "Assign at-risk members guided security tasks to update credentials." }, - "benefit3Title": { + "feature3Title": { "message": "Monitor progress" }, - "benefit3Description": { - "message": "Track changes over time to show security improvements" + "feature3Description": { + "message": "Track changes over time to show security improvements." }, - "noReportRunTitle": { - "message": "Run your first report to see applications" + "noReportsRunTitle": { + "message": "Generate report" }, - "noReportRunDescription": { - "message": "Generate a risk insights report to analyze your organization's applications and identify at-risk passwords that need attention. Running your first report will:" + "noReportsRunDescription": { + "message": "You’re ready to start generating reports. Once you generate, you’ll be able to:" }, "noCriticalApplicationsTitle": { "message": "Non hai contrassegnato nessuna applicazione come critica" @@ -271,14 +265,14 @@ "atRiskMembers": { "message": "Membri a rischio" }, - "membersWithAccessToAtRiskItemsForCriticalApps": { - "message": "Membri con accesso agli elementi a rischio per applicazioni critiche" + "membersWithAccessToAtRiskItemsForCriticalApplications": { + "message": "These members have access to vulnerable items for critical applications." }, "membersWithAtRiskPasswords": { "message": "Members with at-risk passwords" }, - "membersWillReceiveNotification": { - "message": "Members will receive a notification to resolve at-risk logins through the browser extension." + "membersWillReceiveSecurityTask": { + "message": "Members of your organization will be assigned a task to change vulnerable passwords. They’ll receive a notification within their Bitwarden browser extension." }, "membersAtRiskCount": { "message": "$COUNT$ membri a rischio", @@ -307,8 +301,8 @@ } } }, - "atRiskMembersDescription": { - "message": "Questi membri accedono ad applicazioni con password deboli, esposte, o riutilizzate." + "atRiskMemberDescription": { + "message": "These members are logging into critical applications with weak, exposed, or reused passwords." }, "atRiskMembersDescriptionNone": { "message": "Non ci sono utenti connessi con password deboli, esposte o riutilizzate." @@ -391,14 +385,14 @@ "prioritizeCriticalApplications": { "message": "Priorità alle applicazioni critiche" }, - "selectCriticalApplicationsDescription": { - "message": "Select which applications are most critical to your organization, then assign security tasks to members to resolve risks." + "selectCriticalAppsDescription": { + "message": "Select which applications are most critical to your organization. Then, you’ll be able to assign security tasks to members to remove risks." }, "reviewNewApplications": { "message": "Review new applications" }, - "reviewNewApplicationsDescription": { - "message": "We've highlighted at-risk items for new applications stored in Admin console that have weak, exposed, or reused passwords." + "reviewNewAppsDescription": { + "message": "Review new applications with vulnerable items and mark those you’d like to monitor closely as critical. Then, you’ll be able to assign security tasks to members to remove risks." }, "clickIconToMarkAppAsCritical": { "message": "Click the star icon to mark an app as critical" @@ -9856,8 +9850,8 @@ "assignTasks": { "message": "Assegna attività" }, - "assignTasksToMembers": { - "message": "Assign tasks to members for guided resolution" + "assignSecurityTasksToMembers": { + "message": "Send notifications to change passwords" }, "assignToCollections": { "message": "Assegna alle raccolte" diff --git a/apps/web/src/locales/ja/messages.json b/apps/web/src/locales/ja/messages.json index a70b821a1f..eed4085320 100644 --- a/apps/web/src/locales/ja/messages.json +++ b/apps/web/src/locales/ja/messages.json @@ -93,8 +93,8 @@ "assignMembersTasksToMonitorProgress": { "message": "Assign members tasks to monitor progress" }, - "onceYouReviewApps": { - "message": "Once you review applications and mark them as critical, you can assign tasks to members to resolve at-risk items and monitor progress here" + "onceYouReviewApplications": { + "message": "Once you review applications and mark them as critical, assign tasks to your members to change their passwords." }, "sendReminders": { "message": "Send reminders" @@ -178,41 +178,35 @@ } } }, - "noApplicationsInOrgTitle": { - "message": "No applications found for $ORG NAME$", - "placeholders": { - "org name": { - "content": "$1", - "example": "Company Name" - } - } + "noDataInOrgTitle": { + "message": "No data found" }, - "noApplicationsInOrgDescription": { - "message": "Import your organization's login data to start monitoring credential security risks. Once imported you get to:" + "noDataInOrgDescription": { + "message": "Import your organization's login data to get started with Access Intelligence. Once you do that, you'll be able to:" }, - "benefit1Title": { - "message": "Prioritize risks" + "feature1Title": { + "message": "Mark applications as critical" }, - "benefit1Description": { - "message": "Focus on applications that matter the most" + "feature1Description": { + "message": "This will help you remove risks to your most important applications first." }, - "benefit2Title": { - "message": "Guide remediation" + "feature2Title": { + "message": "Help members improve their security" }, - "benefit2Description": { - "message": "Assign at-risk members guided tasks to rotate at-risk credentials" + "feature2Description": { + "message": "Assign at-risk members guided security tasks to update credentials." }, - "benefit3Title": { + "feature3Title": { "message": "Monitor progress" }, - "benefit3Description": { - "message": "Track changes over time to show security improvements" + "feature3Description": { + "message": "Track changes over time to show security improvements." }, - "noReportRunTitle": { - "message": "Run your first report to see applications" + "noReportsRunTitle": { + "message": "Generate report" }, - "noReportRunDescription": { - "message": "Generate a risk insights report to analyze your organization's applications and identify at-risk passwords that need attention. Running your first report will:" + "noReportsRunDescription": { + "message": "You’re ready to start generating reports. Once you generate, you’ll be able to:" }, "noCriticalApplicationsTitle": { "message": "You haven’t marked any applications as critical" @@ -271,14 +265,14 @@ "atRiskMembers": { "message": "リスクがあるメンバー" }, - "membersWithAccessToAtRiskItemsForCriticalApps": { - "message": "Members with access to at-risk items for critical applications" + "membersWithAccessToAtRiskItemsForCriticalApplications": { + "message": "These members have access to vulnerable items for critical applications." }, "membersWithAtRiskPasswords": { "message": "Members with at-risk passwords" }, - "membersWillReceiveNotification": { - "message": "Members will receive a notification to resolve at-risk logins through the browser extension." + "membersWillReceiveSecurityTask": { + "message": "Members of your organization will be assigned a task to change vulnerable passwords. They’ll receive a notification within their Bitwarden browser extension." }, "membersAtRiskCount": { "message": "$COUNT$ members at-risk", @@ -307,8 +301,8 @@ } } }, - "atRiskMembersDescription": { - "message": "これらのメンバーは、脆弱な、または流出したか再利用されたパスワードでアプリにログインしています。" + "atRiskMemberDescription": { + "message": "These members are logging into critical applications with weak, exposed, or reused passwords." }, "atRiskMembersDescriptionNone": { "message": "These are no members logging into applications with weak, exposed, or reused passwords." @@ -391,14 +385,14 @@ "prioritizeCriticalApplications": { "message": "Prioritize critical applications" }, - "selectCriticalApplicationsDescription": { - "message": "Select which applications are most critical to your organization, then assign security tasks to members to resolve risks." + "selectCriticalAppsDescription": { + "message": "Select which applications are most critical to your organization. Then, you’ll be able to assign security tasks to members to remove risks." }, "reviewNewApplications": { "message": "Review new applications" }, - "reviewNewApplicationsDescription": { - "message": "We've highlighted at-risk items for new applications stored in Admin console that have weak, exposed, or reused passwords." + "reviewNewAppsDescription": { + "message": "Review new applications with vulnerable items and mark those you’d like to monitor closely as critical. Then, you’ll be able to assign security tasks to members to remove risks." }, "clickIconToMarkAppAsCritical": { "message": "Click the star icon to mark an app as critical" @@ -9856,8 +9850,8 @@ "assignTasks": { "message": "Assign tasks" }, - "assignTasksToMembers": { - "message": "Assign tasks to members for guided resolution" + "assignSecurityTasksToMembers": { + "message": "Send notifications to change passwords" }, "assignToCollections": { "message": "コレクションに割り当てる" diff --git a/apps/web/src/locales/ka/messages.json b/apps/web/src/locales/ka/messages.json index 973dcc2951..b64d882bb0 100644 --- a/apps/web/src/locales/ka/messages.json +++ b/apps/web/src/locales/ka/messages.json @@ -93,8 +93,8 @@ "assignMembersTasksToMonitorProgress": { "message": "Assign members tasks to monitor progress" }, - "onceYouReviewApps": { - "message": "Once you review applications and mark them as critical, you can assign tasks to members to resolve at-risk items and monitor progress here" + "onceYouReviewApplications": { + "message": "Once you review applications and mark them as critical, assign tasks to your members to change their passwords." }, "sendReminders": { "message": "Send reminders" @@ -178,41 +178,35 @@ } } }, - "noApplicationsInOrgTitle": { - "message": "No applications found for $ORG NAME$", - "placeholders": { - "org name": { - "content": "$1", - "example": "Company Name" - } - } + "noDataInOrgTitle": { + "message": "No data found" }, - "noApplicationsInOrgDescription": { - "message": "Import your organization's login data to start monitoring credential security risks. Once imported you get to:" + "noDataInOrgDescription": { + "message": "Import your organization's login data to get started with Access Intelligence. Once you do that, you'll be able to:" }, - "benefit1Title": { - "message": "Prioritize risks" + "feature1Title": { + "message": "Mark applications as critical" }, - "benefit1Description": { - "message": "Focus on applications that matter the most" + "feature1Description": { + "message": "This will help you remove risks to your most important applications first." }, - "benefit2Title": { - "message": "Guide remediation" + "feature2Title": { + "message": "Help members improve their security" }, - "benefit2Description": { - "message": "Assign at-risk members guided tasks to rotate at-risk credentials" + "feature2Description": { + "message": "Assign at-risk members guided security tasks to update credentials." }, - "benefit3Title": { + "feature3Title": { "message": "Monitor progress" }, - "benefit3Description": { - "message": "Track changes over time to show security improvements" + "feature3Description": { + "message": "Track changes over time to show security improvements." }, - "noReportRunTitle": { - "message": "Run your first report to see applications" + "noReportsRunTitle": { + "message": "Generate report" }, - "noReportRunDescription": { - "message": "Generate a risk insights report to analyze your organization's applications and identify at-risk passwords that need attention. Running your first report will:" + "noReportsRunDescription": { + "message": "You’re ready to start generating reports. Once you generate, you’ll be able to:" }, "noCriticalApplicationsTitle": { "message": "You haven’t marked any applications as critical" @@ -271,14 +265,14 @@ "atRiskMembers": { "message": "At-risk members" }, - "membersWithAccessToAtRiskItemsForCriticalApps": { - "message": "Members with access to at-risk items for critical applications" + "membersWithAccessToAtRiskItemsForCriticalApplications": { + "message": "These members have access to vulnerable items for critical applications." }, "membersWithAtRiskPasswords": { "message": "Members with at-risk passwords" }, - "membersWillReceiveNotification": { - "message": "Members will receive a notification to resolve at-risk logins through the browser extension." + "membersWillReceiveSecurityTask": { + "message": "Members of your organization will be assigned a task to change vulnerable passwords. They’ll receive a notification within their Bitwarden browser extension." }, "membersAtRiskCount": { "message": "$COUNT$ members at-risk", @@ -307,8 +301,8 @@ } } }, - "atRiskMembersDescription": { - "message": "These members are logging into applications with weak, exposed, or reused passwords." + "atRiskMemberDescription": { + "message": "These members are logging into critical applications with weak, exposed, or reused passwords." }, "atRiskMembersDescriptionNone": { "message": "These are no members logging into applications with weak, exposed, or reused passwords." @@ -391,14 +385,14 @@ "prioritizeCriticalApplications": { "message": "Prioritize critical applications" }, - "selectCriticalApplicationsDescription": { - "message": "Select which applications are most critical to your organization, then assign security tasks to members to resolve risks." + "selectCriticalAppsDescription": { + "message": "Select which applications are most critical to your organization. Then, you’ll be able to assign security tasks to members to remove risks." }, "reviewNewApplications": { "message": "Review new applications" }, - "reviewNewApplicationsDescription": { - "message": "We've highlighted at-risk items for new applications stored in Admin console that have weak, exposed, or reused passwords." + "reviewNewAppsDescription": { + "message": "Review new applications with vulnerable items and mark those you’d like to monitor closely as critical. Then, you’ll be able to assign security tasks to members to remove risks." }, "clickIconToMarkAppAsCritical": { "message": "Click the star icon to mark an app as critical" @@ -9856,8 +9850,8 @@ "assignTasks": { "message": "Assign tasks" }, - "assignTasksToMembers": { - "message": "Assign tasks to members for guided resolution" + "assignSecurityTasksToMembers": { + "message": "Send notifications to change passwords" }, "assignToCollections": { "message": "Assign to collections" diff --git a/apps/web/src/locales/km/messages.json b/apps/web/src/locales/km/messages.json index 47df482685..9f57ed8c6c 100644 --- a/apps/web/src/locales/km/messages.json +++ b/apps/web/src/locales/km/messages.json @@ -93,8 +93,8 @@ "assignMembersTasksToMonitorProgress": { "message": "Assign members tasks to monitor progress" }, - "onceYouReviewApps": { - "message": "Once you review applications and mark them as critical, you can assign tasks to members to resolve at-risk items and monitor progress here" + "onceYouReviewApplications": { + "message": "Once you review applications and mark them as critical, assign tasks to your members to change their passwords." }, "sendReminders": { "message": "Send reminders" @@ -178,41 +178,35 @@ } } }, - "noApplicationsInOrgTitle": { - "message": "No applications found for $ORG NAME$", - "placeholders": { - "org name": { - "content": "$1", - "example": "Company Name" - } - } + "noDataInOrgTitle": { + "message": "No data found" }, - "noApplicationsInOrgDescription": { - "message": "Import your organization's login data to start monitoring credential security risks. Once imported you get to:" + "noDataInOrgDescription": { + "message": "Import your organization's login data to get started with Access Intelligence. Once you do that, you'll be able to:" }, - "benefit1Title": { - "message": "Prioritize risks" + "feature1Title": { + "message": "Mark applications as critical" }, - "benefit1Description": { - "message": "Focus on applications that matter the most" + "feature1Description": { + "message": "This will help you remove risks to your most important applications first." }, - "benefit2Title": { - "message": "Guide remediation" + "feature2Title": { + "message": "Help members improve their security" }, - "benefit2Description": { - "message": "Assign at-risk members guided tasks to rotate at-risk credentials" + "feature2Description": { + "message": "Assign at-risk members guided security tasks to update credentials." }, - "benefit3Title": { + "feature3Title": { "message": "Monitor progress" }, - "benefit3Description": { - "message": "Track changes over time to show security improvements" + "feature3Description": { + "message": "Track changes over time to show security improvements." }, - "noReportRunTitle": { - "message": "Run your first report to see applications" + "noReportsRunTitle": { + "message": "Generate report" }, - "noReportRunDescription": { - "message": "Generate a risk insights report to analyze your organization's applications and identify at-risk passwords that need attention. Running your first report will:" + "noReportsRunDescription": { + "message": "You’re ready to start generating reports. Once you generate, you’ll be able to:" }, "noCriticalApplicationsTitle": { "message": "You haven’t marked any applications as critical" @@ -271,14 +265,14 @@ "atRiskMembers": { "message": "At-risk members" }, - "membersWithAccessToAtRiskItemsForCriticalApps": { - "message": "Members with access to at-risk items for critical applications" + "membersWithAccessToAtRiskItemsForCriticalApplications": { + "message": "These members have access to vulnerable items for critical applications." }, "membersWithAtRiskPasswords": { "message": "Members with at-risk passwords" }, - "membersWillReceiveNotification": { - "message": "Members will receive a notification to resolve at-risk logins through the browser extension." + "membersWillReceiveSecurityTask": { + "message": "Members of your organization will be assigned a task to change vulnerable passwords. They’ll receive a notification within their Bitwarden browser extension." }, "membersAtRiskCount": { "message": "$COUNT$ members at-risk", @@ -307,8 +301,8 @@ } } }, - "atRiskMembersDescription": { - "message": "These members are logging into applications with weak, exposed, or reused passwords." + "atRiskMemberDescription": { + "message": "These members are logging into critical applications with weak, exposed, or reused passwords." }, "atRiskMembersDescriptionNone": { "message": "These are no members logging into applications with weak, exposed, or reused passwords." @@ -391,14 +385,14 @@ "prioritizeCriticalApplications": { "message": "Prioritize critical applications" }, - "selectCriticalApplicationsDescription": { - "message": "Select which applications are most critical to your organization, then assign security tasks to members to resolve risks." + "selectCriticalAppsDescription": { + "message": "Select which applications are most critical to your organization. Then, you’ll be able to assign security tasks to members to remove risks." }, "reviewNewApplications": { "message": "Review new applications" }, - "reviewNewApplicationsDescription": { - "message": "We've highlighted at-risk items for new applications stored in Admin console that have weak, exposed, or reused passwords." + "reviewNewAppsDescription": { + "message": "Review new applications with vulnerable items and mark those you’d like to monitor closely as critical. Then, you’ll be able to assign security tasks to members to remove risks." }, "clickIconToMarkAppAsCritical": { "message": "Click the star icon to mark an app as critical" @@ -9856,8 +9850,8 @@ "assignTasks": { "message": "Assign tasks" }, - "assignTasksToMembers": { - "message": "Assign tasks to members for guided resolution" + "assignSecurityTasksToMembers": { + "message": "Send notifications to change passwords" }, "assignToCollections": { "message": "Assign to collections" diff --git a/apps/web/src/locales/kn/messages.json b/apps/web/src/locales/kn/messages.json index 17aaa51f26..4101793385 100644 --- a/apps/web/src/locales/kn/messages.json +++ b/apps/web/src/locales/kn/messages.json @@ -93,8 +93,8 @@ "assignMembersTasksToMonitorProgress": { "message": "Assign members tasks to monitor progress" }, - "onceYouReviewApps": { - "message": "Once you review applications and mark them as critical, you can assign tasks to members to resolve at-risk items and monitor progress here" + "onceYouReviewApplications": { + "message": "Once you review applications and mark them as critical, assign tasks to your members to change their passwords." }, "sendReminders": { "message": "Send reminders" @@ -178,41 +178,35 @@ } } }, - "noApplicationsInOrgTitle": { - "message": "No applications found for $ORG NAME$", - "placeholders": { - "org name": { - "content": "$1", - "example": "Company Name" - } - } + "noDataInOrgTitle": { + "message": "No data found" }, - "noApplicationsInOrgDescription": { - "message": "Import your organization's login data to start monitoring credential security risks. Once imported you get to:" + "noDataInOrgDescription": { + "message": "Import your organization's login data to get started with Access Intelligence. Once you do that, you'll be able to:" }, - "benefit1Title": { - "message": "Prioritize risks" + "feature1Title": { + "message": "Mark applications as critical" }, - "benefit1Description": { - "message": "Focus on applications that matter the most" + "feature1Description": { + "message": "This will help you remove risks to your most important applications first." }, - "benefit2Title": { - "message": "Guide remediation" + "feature2Title": { + "message": "Help members improve their security" }, - "benefit2Description": { - "message": "Assign at-risk members guided tasks to rotate at-risk credentials" + "feature2Description": { + "message": "Assign at-risk members guided security tasks to update credentials." }, - "benefit3Title": { + "feature3Title": { "message": "Monitor progress" }, - "benefit3Description": { - "message": "Track changes over time to show security improvements" + "feature3Description": { + "message": "Track changes over time to show security improvements." }, - "noReportRunTitle": { - "message": "Run your first report to see applications" + "noReportsRunTitle": { + "message": "Generate report" }, - "noReportRunDescription": { - "message": "Generate a risk insights report to analyze your organization's applications and identify at-risk passwords that need attention. Running your first report will:" + "noReportsRunDescription": { + "message": "You’re ready to start generating reports. Once you generate, you’ll be able to:" }, "noCriticalApplicationsTitle": { "message": "You haven’t marked any applications as critical" @@ -271,14 +265,14 @@ "atRiskMembers": { "message": "At-risk members" }, - "membersWithAccessToAtRiskItemsForCriticalApps": { - "message": "Members with access to at-risk items for critical applications" + "membersWithAccessToAtRiskItemsForCriticalApplications": { + "message": "These members have access to vulnerable items for critical applications." }, "membersWithAtRiskPasswords": { "message": "Members with at-risk passwords" }, - "membersWillReceiveNotification": { - "message": "Members will receive a notification to resolve at-risk logins through the browser extension." + "membersWillReceiveSecurityTask": { + "message": "Members of your organization will be assigned a task to change vulnerable passwords. They’ll receive a notification within their Bitwarden browser extension." }, "membersAtRiskCount": { "message": "$COUNT$ members at-risk", @@ -307,8 +301,8 @@ } } }, - "atRiskMembersDescription": { - "message": "These members are logging into applications with weak, exposed, or reused passwords." + "atRiskMemberDescription": { + "message": "These members are logging into critical applications with weak, exposed, or reused passwords." }, "atRiskMembersDescriptionNone": { "message": "These are no members logging into applications with weak, exposed, or reused passwords." @@ -391,14 +385,14 @@ "prioritizeCriticalApplications": { "message": "Prioritize critical applications" }, - "selectCriticalApplicationsDescription": { - "message": "Select which applications are most critical to your organization, then assign security tasks to members to resolve risks." + "selectCriticalAppsDescription": { + "message": "Select which applications are most critical to your organization. Then, you’ll be able to assign security tasks to members to remove risks." }, "reviewNewApplications": { "message": "Review new applications" }, - "reviewNewApplicationsDescription": { - "message": "We've highlighted at-risk items for new applications stored in Admin console that have weak, exposed, or reused passwords." + "reviewNewAppsDescription": { + "message": "Review new applications with vulnerable items and mark those you’d like to monitor closely as critical. Then, you’ll be able to assign security tasks to members to remove risks." }, "clickIconToMarkAppAsCritical": { "message": "Click the star icon to mark an app as critical" @@ -9856,8 +9850,8 @@ "assignTasks": { "message": "Assign tasks" }, - "assignTasksToMembers": { - "message": "Assign tasks to members for guided resolution" + "assignSecurityTasksToMembers": { + "message": "Send notifications to change passwords" }, "assignToCollections": { "message": "Assign to collections" diff --git a/apps/web/src/locales/ko/messages.json b/apps/web/src/locales/ko/messages.json index f831e76b1e..971a2ee59a 100644 --- a/apps/web/src/locales/ko/messages.json +++ b/apps/web/src/locales/ko/messages.json @@ -93,8 +93,8 @@ "assignMembersTasksToMonitorProgress": { "message": "Assign members tasks to monitor progress" }, - "onceYouReviewApps": { - "message": "Once you review applications and mark them as critical, you can assign tasks to members to resolve at-risk items and monitor progress here" + "onceYouReviewApplications": { + "message": "Once you review applications and mark them as critical, assign tasks to your members to change their passwords." }, "sendReminders": { "message": "Send reminders" @@ -178,41 +178,35 @@ } } }, - "noApplicationsInOrgTitle": { - "message": "No applications found for $ORG NAME$", - "placeholders": { - "org name": { - "content": "$1", - "example": "Company Name" - } - } + "noDataInOrgTitle": { + "message": "No data found" }, - "noApplicationsInOrgDescription": { - "message": "Import your organization's login data to start monitoring credential security risks. Once imported you get to:" + "noDataInOrgDescription": { + "message": "Import your organization's login data to get started with Access Intelligence. Once you do that, you'll be able to:" }, - "benefit1Title": { - "message": "Prioritize risks" + "feature1Title": { + "message": "Mark applications as critical" }, - "benefit1Description": { - "message": "Focus on applications that matter the most" + "feature1Description": { + "message": "This will help you remove risks to your most important applications first." }, - "benefit2Title": { - "message": "Guide remediation" + "feature2Title": { + "message": "Help members improve their security" }, - "benefit2Description": { - "message": "Assign at-risk members guided tasks to rotate at-risk credentials" + "feature2Description": { + "message": "Assign at-risk members guided security tasks to update credentials." }, - "benefit3Title": { + "feature3Title": { "message": "Monitor progress" }, - "benefit3Description": { - "message": "Track changes over time to show security improvements" + "feature3Description": { + "message": "Track changes over time to show security improvements." }, - "noReportRunTitle": { - "message": "Run your first report to see applications" + "noReportsRunTitle": { + "message": "Generate report" }, - "noReportRunDescription": { - "message": "Generate a risk insights report to analyze your organization's applications and identify at-risk passwords that need attention. Running your first report will:" + "noReportsRunDescription": { + "message": "You’re ready to start generating reports. Once you generate, you’ll be able to:" }, "noCriticalApplicationsTitle": { "message": "You haven’t marked any applications as critical" @@ -271,14 +265,14 @@ "atRiskMembers": { "message": "At-risk members" }, - "membersWithAccessToAtRiskItemsForCriticalApps": { - "message": "Members with access to at-risk items for critical applications" + "membersWithAccessToAtRiskItemsForCriticalApplications": { + "message": "These members have access to vulnerable items for critical applications." }, "membersWithAtRiskPasswords": { "message": "Members with at-risk passwords" }, - "membersWillReceiveNotification": { - "message": "Members will receive a notification to resolve at-risk logins through the browser extension." + "membersWillReceiveSecurityTask": { + "message": "Members of your organization will be assigned a task to change vulnerable passwords. They’ll receive a notification within their Bitwarden browser extension." }, "membersAtRiskCount": { "message": "$COUNT$ members at-risk", @@ -307,8 +301,8 @@ } } }, - "atRiskMembersDescription": { - "message": "These members are logging into applications with weak, exposed, or reused passwords." + "atRiskMemberDescription": { + "message": "These members are logging into critical applications with weak, exposed, or reused passwords." }, "atRiskMembersDescriptionNone": { "message": "These are no members logging into applications with weak, exposed, or reused passwords." @@ -391,14 +385,14 @@ "prioritizeCriticalApplications": { "message": "Prioritize critical applications" }, - "selectCriticalApplicationsDescription": { - "message": "Select which applications are most critical to your organization, then assign security tasks to members to resolve risks." + "selectCriticalAppsDescription": { + "message": "Select which applications are most critical to your organization. Then, you’ll be able to assign security tasks to members to remove risks." }, "reviewNewApplications": { "message": "Review new applications" }, - "reviewNewApplicationsDescription": { - "message": "We've highlighted at-risk items for new applications stored in Admin console that have weak, exposed, or reused passwords." + "reviewNewAppsDescription": { + "message": "Review new applications with vulnerable items and mark those you’d like to monitor closely as critical. Then, you’ll be able to assign security tasks to members to remove risks." }, "clickIconToMarkAppAsCritical": { "message": "Click the star icon to mark an app as critical" @@ -9856,8 +9850,8 @@ "assignTasks": { "message": "Assign tasks" }, - "assignTasksToMembers": { - "message": "Assign tasks to members for guided resolution" + "assignSecurityTasksToMembers": { + "message": "Send notifications to change passwords" }, "assignToCollections": { "message": "Assign to collections" diff --git a/apps/web/src/locales/lv/messages.json b/apps/web/src/locales/lv/messages.json index b35e704eb2..ba97873047 100644 --- a/apps/web/src/locales/lv/messages.json +++ b/apps/web/src/locales/lv/messages.json @@ -93,8 +93,8 @@ "assignMembersTasksToMonitorProgress": { "message": "Piešķirt dalībniekiem uzdevumus, lai pārraudzītu virzību" }, - "onceYouReviewApps": { - "message": "Tiklīdz lietotnes būs pārskatītas un atzīmētas kā būtiskas, dalībniekiem varēs piešķirt uzdevumus atrisināt riskam pakļautos vienumus un šeit pārskatīt virzību" + "onceYouReviewApplications": { + "message": "Once you review applications and mark them as critical, assign tasks to your members to change their passwords." }, "sendReminders": { "message": "Nosūtīt atgādinājumus" @@ -178,41 +178,35 @@ } } }, - "noApplicationsInOrgTitle": { - "message": "$ORG NAME$ netika atrasta neviena lietotne", - "placeholders": { - "org name": { - "content": "$1", - "example": "Company Name" - } - } + "noDataInOrgTitle": { + "message": "No data found" }, - "noApplicationsInOrgDescription": { - "message": "Ievieto savas apvienības pieteikšanās datus, lai uzsāktu to drošības risku uzraudzīšanu. Tiklīdz dati ir ievietoti, Tu vari:" + "noDataInOrgDescription": { + "message": "Import your organization's login data to get started with Access Intelligence. Once you do that, you'll be able to:" }, - "benefit1Title": { - "message": "Noteikt risku svarīgumu" + "feature1Title": { + "message": "Mark applications as critical" }, - "benefit1Description": { - "message": "Pievērst uzmanību visbūtiskākajām lietotnēm" + "feature1Description": { + "message": "This will help you remove risks to your most important applications first." }, - "benefit2Title": { - "message": "Virzīt nepilnību novēršanu" + "feature2Title": { + "message": "Help members improve their security" }, - "benefit2Description": { - "message": "Piešķirt riskam pakļautajiem dalībniekiem uzdevumus riskam pakļauto pieteikšanās datu nomaiņai" + "feature2Description": { + "message": "Assign at-risk members guided security tasks to update credentials." }, - "benefit3Title": { - "message": "Pārraudzīt virzību" + "feature3Title": { + "message": "Monitor progress" }, - "benefit3Description": { - "message": "Sekot izmaiņām, lai uzrādītu drošības uzlabojumus" + "feature3Description": { + "message": "Track changes over time to show security improvements." }, - "noReportRunTitle": { - "message": "Izveidot savu pirmo atskaiti, lai redzētu lietotnes" + "noReportsRunTitle": { + "message": "Generate report" }, - "noReportRunDescription": { - "message": "Izveidot riska ieskatu atskaiti, lai izvērtētu savas apvienības lietotnes un noteiktu riskam pakļautas paroles, kurēm jāpievērš uzmanība. Pirmās atskaites izveidošana:" + "noReportsRunDescription": { + "message": "You’re ready to start generating reports. Once you generate, you’ll be able to:" }, "noCriticalApplicationsTitle": { "message": "Neviena lietotne nav atzīmēta kā kritiska" @@ -271,14 +265,14 @@ "atRiskMembers": { "message": "Riskam pakļautie dalībnieki" }, - "membersWithAccessToAtRiskItemsForCriticalApps": { - "message": "Dalībnieki ar piekluvi riskam pakļautajiem vienumiem būtiskajām lietotnēm" + "membersWithAccessToAtRiskItemsForCriticalApplications": { + "message": "These members have access to vulnerable items for critical applications." }, "membersWithAtRiskPasswords": { "message": "Dalībnieki ar riskam pakļautām parolēm" }, - "membersWillReceiveNotification": { - "message": "Dalībnieki pārlūka paplašinājumā saņems paziņojumu, ka jānomaina riskam pakļautās paroles." + "membersWillReceiveSecurityTask": { + "message": "Members of your organization will be assigned a task to change vulnerable passwords. They’ll receive a notification within their Bitwarden browser extension." }, "membersAtRiskCount": { "message": "$COUNT$ dalībnieki ir pakļauti riskam", @@ -307,8 +301,8 @@ } } }, - "atRiskMembersDescription": { - "message": "Šie dalībnieki piesakās lietotnēs ar vājām, atklātām vai atkārtoti izmantotām parolēm." + "atRiskMemberDescription": { + "message": "These members are logging into critical applications with weak, exposed, or reused passwords." }, "atRiskMembersDescriptionNone": { "message": "Nav dalībnieku, kas piesakās lietotnēs ar vājām, atklātām vai atkārtoti izmantotām parolēm." @@ -391,14 +385,14 @@ "prioritizeCriticalApplications": { "message": "Paaugstināt būtisko lietotņu svarīgumu" }, - "selectCriticalApplicationsDescription": { - "message": "Jāatlasa, kuras lietontes apvienībai ir visbūtiskākās, tad jāpiešķir drošības uzdevumi dalībniekiem risku novēršanai." + "selectCriticalAppsDescription": { + "message": "Select which applications are most critical to your organization. Then, you’ll be able to assign security tasks to members to remove risks." }, "reviewNewApplications": { "message": "Pārskatīt jaunās lietotnes" }, - "reviewNewApplicationsDescription": { - "message": "Mēs izcēlām riskam pakļautos vienumus jaunām lietotnēm, kas tiek glabātas pārvaldības konsolē un kurās ir vājas, atklātas vai atkārtoti izmantotas paroles." + "reviewNewAppsDescription": { + "message": "Review new applications with vulnerable items and mark those you’d like to monitor closely as critical. Then, you’ll be able to assign security tasks to members to remove risks." }, "clickIconToMarkAppAsCritical": { "message": "Jāklikšķina uz zvaigznes, lai atzīmētu lietotni kā būtisku" @@ -9856,8 +9850,8 @@ "assignTasks": { "message": "Piešķirt uzdevumus" }, - "assignTasksToMembers": { - "message": "Piešķirt uzdevumus dalībniekiem risinājumam ar norādēm" + "assignSecurityTasksToMembers": { + "message": "Send notifications to change passwords" }, "assignToCollections": { "message": "Piešķirt krājumiem" diff --git a/apps/web/src/locales/ml/messages.json b/apps/web/src/locales/ml/messages.json index 624121be5d..14f5b921ce 100644 --- a/apps/web/src/locales/ml/messages.json +++ b/apps/web/src/locales/ml/messages.json @@ -93,8 +93,8 @@ "assignMembersTasksToMonitorProgress": { "message": "Assign members tasks to monitor progress" }, - "onceYouReviewApps": { - "message": "Once you review applications and mark them as critical, you can assign tasks to members to resolve at-risk items and monitor progress here" + "onceYouReviewApplications": { + "message": "Once you review applications and mark them as critical, assign tasks to your members to change their passwords." }, "sendReminders": { "message": "Send reminders" @@ -178,41 +178,35 @@ } } }, - "noApplicationsInOrgTitle": { - "message": "No applications found for $ORG NAME$", - "placeholders": { - "org name": { - "content": "$1", - "example": "Company Name" - } - } + "noDataInOrgTitle": { + "message": "No data found" }, - "noApplicationsInOrgDescription": { - "message": "Import your organization's login data to start monitoring credential security risks. Once imported you get to:" + "noDataInOrgDescription": { + "message": "Import your organization's login data to get started with Access Intelligence. Once you do that, you'll be able to:" }, - "benefit1Title": { - "message": "Prioritize risks" + "feature1Title": { + "message": "Mark applications as critical" }, - "benefit1Description": { - "message": "Focus on applications that matter the most" + "feature1Description": { + "message": "This will help you remove risks to your most important applications first." }, - "benefit2Title": { - "message": "Guide remediation" + "feature2Title": { + "message": "Help members improve their security" }, - "benefit2Description": { - "message": "Assign at-risk members guided tasks to rotate at-risk credentials" + "feature2Description": { + "message": "Assign at-risk members guided security tasks to update credentials." }, - "benefit3Title": { + "feature3Title": { "message": "Monitor progress" }, - "benefit3Description": { - "message": "Track changes over time to show security improvements" + "feature3Description": { + "message": "Track changes over time to show security improvements." }, - "noReportRunTitle": { - "message": "Run your first report to see applications" + "noReportsRunTitle": { + "message": "Generate report" }, - "noReportRunDescription": { - "message": "Generate a risk insights report to analyze your organization's applications and identify at-risk passwords that need attention. Running your first report will:" + "noReportsRunDescription": { + "message": "You’re ready to start generating reports. Once you generate, you’ll be able to:" }, "noCriticalApplicationsTitle": { "message": "You haven’t marked any applications as critical" @@ -271,14 +265,14 @@ "atRiskMembers": { "message": "At-risk members" }, - "membersWithAccessToAtRiskItemsForCriticalApps": { - "message": "Members with access to at-risk items for critical applications" + "membersWithAccessToAtRiskItemsForCriticalApplications": { + "message": "These members have access to vulnerable items for critical applications." }, "membersWithAtRiskPasswords": { "message": "Members with at-risk passwords" }, - "membersWillReceiveNotification": { - "message": "Members will receive a notification to resolve at-risk logins through the browser extension." + "membersWillReceiveSecurityTask": { + "message": "Members of your organization will be assigned a task to change vulnerable passwords. They’ll receive a notification within their Bitwarden browser extension." }, "membersAtRiskCount": { "message": "$COUNT$ members at-risk", @@ -307,8 +301,8 @@ } } }, - "atRiskMembersDescription": { - "message": "These members are logging into applications with weak, exposed, or reused passwords." + "atRiskMemberDescription": { + "message": "These members are logging into critical applications with weak, exposed, or reused passwords." }, "atRiskMembersDescriptionNone": { "message": "These are no members logging into applications with weak, exposed, or reused passwords." @@ -391,14 +385,14 @@ "prioritizeCriticalApplications": { "message": "Prioritize critical applications" }, - "selectCriticalApplicationsDescription": { - "message": "Select which applications are most critical to your organization, then assign security tasks to members to resolve risks." + "selectCriticalAppsDescription": { + "message": "Select which applications are most critical to your organization. Then, you’ll be able to assign security tasks to members to remove risks." }, "reviewNewApplications": { "message": "Review new applications" }, - "reviewNewApplicationsDescription": { - "message": "We've highlighted at-risk items for new applications stored in Admin console that have weak, exposed, or reused passwords." + "reviewNewAppsDescription": { + "message": "Review new applications with vulnerable items and mark those you’d like to monitor closely as critical. Then, you’ll be able to assign security tasks to members to remove risks." }, "clickIconToMarkAppAsCritical": { "message": "Click the star icon to mark an app as critical" @@ -9856,8 +9850,8 @@ "assignTasks": { "message": "Assign tasks" }, - "assignTasksToMembers": { - "message": "Assign tasks to members for guided resolution" + "assignSecurityTasksToMembers": { + "message": "Send notifications to change passwords" }, "assignToCollections": { "message": "Assign to collections" diff --git a/apps/web/src/locales/mr/messages.json b/apps/web/src/locales/mr/messages.json index 612ff8b876..a7a1e405ed 100644 --- a/apps/web/src/locales/mr/messages.json +++ b/apps/web/src/locales/mr/messages.json @@ -93,8 +93,8 @@ "assignMembersTasksToMonitorProgress": { "message": "Assign members tasks to monitor progress" }, - "onceYouReviewApps": { - "message": "Once you review applications and mark them as critical, you can assign tasks to members to resolve at-risk items and monitor progress here" + "onceYouReviewApplications": { + "message": "Once you review applications and mark them as critical, assign tasks to your members to change their passwords." }, "sendReminders": { "message": "Send reminders" @@ -178,41 +178,35 @@ } } }, - "noApplicationsInOrgTitle": { - "message": "No applications found for $ORG NAME$", - "placeholders": { - "org name": { - "content": "$1", - "example": "Company Name" - } - } + "noDataInOrgTitle": { + "message": "No data found" }, - "noApplicationsInOrgDescription": { - "message": "Import your organization's login data to start monitoring credential security risks. Once imported you get to:" + "noDataInOrgDescription": { + "message": "Import your organization's login data to get started with Access Intelligence. Once you do that, you'll be able to:" }, - "benefit1Title": { - "message": "Prioritize risks" + "feature1Title": { + "message": "Mark applications as critical" }, - "benefit1Description": { - "message": "Focus on applications that matter the most" + "feature1Description": { + "message": "This will help you remove risks to your most important applications first." }, - "benefit2Title": { - "message": "Guide remediation" + "feature2Title": { + "message": "Help members improve their security" }, - "benefit2Description": { - "message": "Assign at-risk members guided tasks to rotate at-risk credentials" + "feature2Description": { + "message": "Assign at-risk members guided security tasks to update credentials." }, - "benefit3Title": { + "feature3Title": { "message": "Monitor progress" }, - "benefit3Description": { - "message": "Track changes over time to show security improvements" + "feature3Description": { + "message": "Track changes over time to show security improvements." }, - "noReportRunTitle": { - "message": "Run your first report to see applications" + "noReportsRunTitle": { + "message": "Generate report" }, - "noReportRunDescription": { - "message": "Generate a risk insights report to analyze your organization's applications and identify at-risk passwords that need attention. Running your first report will:" + "noReportsRunDescription": { + "message": "You’re ready to start generating reports. Once you generate, you’ll be able to:" }, "noCriticalApplicationsTitle": { "message": "You haven’t marked any applications as critical" @@ -271,14 +265,14 @@ "atRiskMembers": { "message": "At-risk members" }, - "membersWithAccessToAtRiskItemsForCriticalApps": { - "message": "Members with access to at-risk items for critical applications" + "membersWithAccessToAtRiskItemsForCriticalApplications": { + "message": "These members have access to vulnerable items for critical applications." }, "membersWithAtRiskPasswords": { "message": "Members with at-risk passwords" }, - "membersWillReceiveNotification": { - "message": "Members will receive a notification to resolve at-risk logins through the browser extension." + "membersWillReceiveSecurityTask": { + "message": "Members of your organization will be assigned a task to change vulnerable passwords. They’ll receive a notification within their Bitwarden browser extension." }, "membersAtRiskCount": { "message": "$COUNT$ members at-risk", @@ -307,8 +301,8 @@ } } }, - "atRiskMembersDescription": { - "message": "These members are logging into applications with weak, exposed, or reused passwords." + "atRiskMemberDescription": { + "message": "These members are logging into critical applications with weak, exposed, or reused passwords." }, "atRiskMembersDescriptionNone": { "message": "These are no members logging into applications with weak, exposed, or reused passwords." @@ -391,14 +385,14 @@ "prioritizeCriticalApplications": { "message": "Prioritize critical applications" }, - "selectCriticalApplicationsDescription": { - "message": "Select which applications are most critical to your organization, then assign security tasks to members to resolve risks." + "selectCriticalAppsDescription": { + "message": "Select which applications are most critical to your organization. Then, you’ll be able to assign security tasks to members to remove risks." }, "reviewNewApplications": { "message": "Review new applications" }, - "reviewNewApplicationsDescription": { - "message": "We've highlighted at-risk items for new applications stored in Admin console that have weak, exposed, or reused passwords." + "reviewNewAppsDescription": { + "message": "Review new applications with vulnerable items and mark those you’d like to monitor closely as critical. Then, you’ll be able to assign security tasks to members to remove risks." }, "clickIconToMarkAppAsCritical": { "message": "Click the star icon to mark an app as critical" @@ -9856,8 +9850,8 @@ "assignTasks": { "message": "Assign tasks" }, - "assignTasksToMembers": { - "message": "Assign tasks to members for guided resolution" + "assignSecurityTasksToMembers": { + "message": "Send notifications to change passwords" }, "assignToCollections": { "message": "Assign to collections" diff --git a/apps/web/src/locales/my/messages.json b/apps/web/src/locales/my/messages.json index 47df482685..9f57ed8c6c 100644 --- a/apps/web/src/locales/my/messages.json +++ b/apps/web/src/locales/my/messages.json @@ -93,8 +93,8 @@ "assignMembersTasksToMonitorProgress": { "message": "Assign members tasks to monitor progress" }, - "onceYouReviewApps": { - "message": "Once you review applications and mark them as critical, you can assign tasks to members to resolve at-risk items and monitor progress here" + "onceYouReviewApplications": { + "message": "Once you review applications and mark them as critical, assign tasks to your members to change their passwords." }, "sendReminders": { "message": "Send reminders" @@ -178,41 +178,35 @@ } } }, - "noApplicationsInOrgTitle": { - "message": "No applications found for $ORG NAME$", - "placeholders": { - "org name": { - "content": "$1", - "example": "Company Name" - } - } + "noDataInOrgTitle": { + "message": "No data found" }, - "noApplicationsInOrgDescription": { - "message": "Import your organization's login data to start monitoring credential security risks. Once imported you get to:" + "noDataInOrgDescription": { + "message": "Import your organization's login data to get started with Access Intelligence. Once you do that, you'll be able to:" }, - "benefit1Title": { - "message": "Prioritize risks" + "feature1Title": { + "message": "Mark applications as critical" }, - "benefit1Description": { - "message": "Focus on applications that matter the most" + "feature1Description": { + "message": "This will help you remove risks to your most important applications first." }, - "benefit2Title": { - "message": "Guide remediation" + "feature2Title": { + "message": "Help members improve their security" }, - "benefit2Description": { - "message": "Assign at-risk members guided tasks to rotate at-risk credentials" + "feature2Description": { + "message": "Assign at-risk members guided security tasks to update credentials." }, - "benefit3Title": { + "feature3Title": { "message": "Monitor progress" }, - "benefit3Description": { - "message": "Track changes over time to show security improvements" + "feature3Description": { + "message": "Track changes over time to show security improvements." }, - "noReportRunTitle": { - "message": "Run your first report to see applications" + "noReportsRunTitle": { + "message": "Generate report" }, - "noReportRunDescription": { - "message": "Generate a risk insights report to analyze your organization's applications and identify at-risk passwords that need attention. Running your first report will:" + "noReportsRunDescription": { + "message": "You’re ready to start generating reports. Once you generate, you’ll be able to:" }, "noCriticalApplicationsTitle": { "message": "You haven’t marked any applications as critical" @@ -271,14 +265,14 @@ "atRiskMembers": { "message": "At-risk members" }, - "membersWithAccessToAtRiskItemsForCriticalApps": { - "message": "Members with access to at-risk items for critical applications" + "membersWithAccessToAtRiskItemsForCriticalApplications": { + "message": "These members have access to vulnerable items for critical applications." }, "membersWithAtRiskPasswords": { "message": "Members with at-risk passwords" }, - "membersWillReceiveNotification": { - "message": "Members will receive a notification to resolve at-risk logins through the browser extension." + "membersWillReceiveSecurityTask": { + "message": "Members of your organization will be assigned a task to change vulnerable passwords. They’ll receive a notification within their Bitwarden browser extension." }, "membersAtRiskCount": { "message": "$COUNT$ members at-risk", @@ -307,8 +301,8 @@ } } }, - "atRiskMembersDescription": { - "message": "These members are logging into applications with weak, exposed, or reused passwords." + "atRiskMemberDescription": { + "message": "These members are logging into critical applications with weak, exposed, or reused passwords." }, "atRiskMembersDescriptionNone": { "message": "These are no members logging into applications with weak, exposed, or reused passwords." @@ -391,14 +385,14 @@ "prioritizeCriticalApplications": { "message": "Prioritize critical applications" }, - "selectCriticalApplicationsDescription": { - "message": "Select which applications are most critical to your organization, then assign security tasks to members to resolve risks." + "selectCriticalAppsDescription": { + "message": "Select which applications are most critical to your organization. Then, you’ll be able to assign security tasks to members to remove risks." }, "reviewNewApplications": { "message": "Review new applications" }, - "reviewNewApplicationsDescription": { - "message": "We've highlighted at-risk items for new applications stored in Admin console that have weak, exposed, or reused passwords." + "reviewNewAppsDescription": { + "message": "Review new applications with vulnerable items and mark those you’d like to monitor closely as critical. Then, you’ll be able to assign security tasks to members to remove risks." }, "clickIconToMarkAppAsCritical": { "message": "Click the star icon to mark an app as critical" @@ -9856,8 +9850,8 @@ "assignTasks": { "message": "Assign tasks" }, - "assignTasksToMembers": { - "message": "Assign tasks to members for guided resolution" + "assignSecurityTasksToMembers": { + "message": "Send notifications to change passwords" }, "assignToCollections": { "message": "Assign to collections" diff --git a/apps/web/src/locales/nb/messages.json b/apps/web/src/locales/nb/messages.json index b2fb413be8..345d875875 100644 --- a/apps/web/src/locales/nb/messages.json +++ b/apps/web/src/locales/nb/messages.json @@ -93,8 +93,8 @@ "assignMembersTasksToMonitorProgress": { "message": "Assign members tasks to monitor progress" }, - "onceYouReviewApps": { - "message": "Once you review applications and mark them as critical, you can assign tasks to members to resolve at-risk items and monitor progress here" + "onceYouReviewApplications": { + "message": "Once you review applications and mark them as critical, assign tasks to your members to change their passwords." }, "sendReminders": { "message": "Send reminders" @@ -178,41 +178,35 @@ } } }, - "noApplicationsInOrgTitle": { - "message": "No applications found for $ORG NAME$", - "placeholders": { - "org name": { - "content": "$1", - "example": "Company Name" - } - } + "noDataInOrgTitle": { + "message": "No data found" }, - "noApplicationsInOrgDescription": { - "message": "Import your organization's login data to start monitoring credential security risks. Once imported you get to:" + "noDataInOrgDescription": { + "message": "Import your organization's login data to get started with Access Intelligence. Once you do that, you'll be able to:" }, - "benefit1Title": { - "message": "Prioritize risks" + "feature1Title": { + "message": "Mark applications as critical" }, - "benefit1Description": { - "message": "Focus on applications that matter the most" + "feature1Description": { + "message": "This will help you remove risks to your most important applications first." }, - "benefit2Title": { - "message": "Guide remediation" + "feature2Title": { + "message": "Help members improve their security" }, - "benefit2Description": { - "message": "Assign at-risk members guided tasks to rotate at-risk credentials" + "feature2Description": { + "message": "Assign at-risk members guided security tasks to update credentials." }, - "benefit3Title": { + "feature3Title": { "message": "Monitor progress" }, - "benefit3Description": { - "message": "Track changes over time to show security improvements" + "feature3Description": { + "message": "Track changes over time to show security improvements." }, - "noReportRunTitle": { - "message": "Run your first report to see applications" + "noReportsRunTitle": { + "message": "Generate report" }, - "noReportRunDescription": { - "message": "Generate a risk insights report to analyze your organization's applications and identify at-risk passwords that need attention. Running your first report will:" + "noReportsRunDescription": { + "message": "You’re ready to start generating reports. Once you generate, you’ll be able to:" }, "noCriticalApplicationsTitle": { "message": "You haven’t marked any applications as critical" @@ -271,14 +265,14 @@ "atRiskMembers": { "message": "At-risk members" }, - "membersWithAccessToAtRiskItemsForCriticalApps": { - "message": "Members with access to at-risk items for critical applications" + "membersWithAccessToAtRiskItemsForCriticalApplications": { + "message": "These members have access to vulnerable items for critical applications." }, "membersWithAtRiskPasswords": { "message": "Members with at-risk passwords" }, - "membersWillReceiveNotification": { - "message": "Members will receive a notification to resolve at-risk logins through the browser extension." + "membersWillReceiveSecurityTask": { + "message": "Members of your organization will be assigned a task to change vulnerable passwords. They’ll receive a notification within their Bitwarden browser extension." }, "membersAtRiskCount": { "message": "$COUNT$ members at-risk", @@ -307,8 +301,8 @@ } } }, - "atRiskMembersDescription": { - "message": "These members are logging into applications with weak, exposed, or reused passwords." + "atRiskMemberDescription": { + "message": "These members are logging into critical applications with weak, exposed, or reused passwords." }, "atRiskMembersDescriptionNone": { "message": "These are no members logging into applications with weak, exposed, or reused passwords." @@ -391,14 +385,14 @@ "prioritizeCriticalApplications": { "message": "Prioritize critical applications" }, - "selectCriticalApplicationsDescription": { - "message": "Select which applications are most critical to your organization, then assign security tasks to members to resolve risks." + "selectCriticalAppsDescription": { + "message": "Select which applications are most critical to your organization. Then, you’ll be able to assign security tasks to members to remove risks." }, "reviewNewApplications": { "message": "Review new applications" }, - "reviewNewApplicationsDescription": { - "message": "We've highlighted at-risk items for new applications stored in Admin console that have weak, exposed, or reused passwords." + "reviewNewAppsDescription": { + "message": "Review new applications with vulnerable items and mark those you’d like to monitor closely as critical. Then, you’ll be able to assign security tasks to members to remove risks." }, "clickIconToMarkAppAsCritical": { "message": "Click the star icon to mark an app as critical" @@ -9856,8 +9850,8 @@ "assignTasks": { "message": "Assign tasks" }, - "assignTasksToMembers": { - "message": "Assign tasks to members for guided resolution" + "assignSecurityTasksToMembers": { + "message": "Send notifications to change passwords" }, "assignToCollections": { "message": "Legg til i samlinger" diff --git a/apps/web/src/locales/ne/messages.json b/apps/web/src/locales/ne/messages.json index 8bd88ef4a5..8387c568e9 100644 --- a/apps/web/src/locales/ne/messages.json +++ b/apps/web/src/locales/ne/messages.json @@ -93,8 +93,8 @@ "assignMembersTasksToMonitorProgress": { "message": "Assign members tasks to monitor progress" }, - "onceYouReviewApps": { - "message": "Once you review applications and mark them as critical, you can assign tasks to members to resolve at-risk items and monitor progress here" + "onceYouReviewApplications": { + "message": "Once you review applications and mark them as critical, assign tasks to your members to change their passwords." }, "sendReminders": { "message": "Send reminders" @@ -178,41 +178,35 @@ } } }, - "noApplicationsInOrgTitle": { - "message": "No applications found for $ORG NAME$", - "placeholders": { - "org name": { - "content": "$1", - "example": "Company Name" - } - } + "noDataInOrgTitle": { + "message": "No data found" }, - "noApplicationsInOrgDescription": { - "message": "Import your organization's login data to start monitoring credential security risks. Once imported you get to:" + "noDataInOrgDescription": { + "message": "Import your organization's login data to get started with Access Intelligence. Once you do that, you'll be able to:" }, - "benefit1Title": { - "message": "Prioritize risks" + "feature1Title": { + "message": "Mark applications as critical" }, - "benefit1Description": { - "message": "Focus on applications that matter the most" + "feature1Description": { + "message": "This will help you remove risks to your most important applications first." }, - "benefit2Title": { - "message": "Guide remediation" + "feature2Title": { + "message": "Help members improve their security" }, - "benefit2Description": { - "message": "Assign at-risk members guided tasks to rotate at-risk credentials" + "feature2Description": { + "message": "Assign at-risk members guided security tasks to update credentials." }, - "benefit3Title": { + "feature3Title": { "message": "Monitor progress" }, - "benefit3Description": { - "message": "Track changes over time to show security improvements" + "feature3Description": { + "message": "Track changes over time to show security improvements." }, - "noReportRunTitle": { - "message": "Run your first report to see applications" + "noReportsRunTitle": { + "message": "Generate report" }, - "noReportRunDescription": { - "message": "Generate a risk insights report to analyze your organization's applications and identify at-risk passwords that need attention. Running your first report will:" + "noReportsRunDescription": { + "message": "You’re ready to start generating reports. Once you generate, you’ll be able to:" }, "noCriticalApplicationsTitle": { "message": "You haven’t marked any applications as critical" @@ -271,14 +265,14 @@ "atRiskMembers": { "message": "At-risk members" }, - "membersWithAccessToAtRiskItemsForCriticalApps": { - "message": "Members with access to at-risk items for critical applications" + "membersWithAccessToAtRiskItemsForCriticalApplications": { + "message": "These members have access to vulnerable items for critical applications." }, "membersWithAtRiskPasswords": { "message": "Members with at-risk passwords" }, - "membersWillReceiveNotification": { - "message": "Members will receive a notification to resolve at-risk logins through the browser extension." + "membersWillReceiveSecurityTask": { + "message": "Members of your organization will be assigned a task to change vulnerable passwords. They’ll receive a notification within their Bitwarden browser extension." }, "membersAtRiskCount": { "message": "$COUNT$ members at-risk", @@ -307,8 +301,8 @@ } } }, - "atRiskMembersDescription": { - "message": "These members are logging into applications with weak, exposed, or reused passwords." + "atRiskMemberDescription": { + "message": "These members are logging into critical applications with weak, exposed, or reused passwords." }, "atRiskMembersDescriptionNone": { "message": "These are no members logging into applications with weak, exposed, or reused passwords." @@ -391,14 +385,14 @@ "prioritizeCriticalApplications": { "message": "Prioritize critical applications" }, - "selectCriticalApplicationsDescription": { - "message": "Select which applications are most critical to your organization, then assign security tasks to members to resolve risks." + "selectCriticalAppsDescription": { + "message": "Select which applications are most critical to your organization. Then, you’ll be able to assign security tasks to members to remove risks." }, "reviewNewApplications": { "message": "Review new applications" }, - "reviewNewApplicationsDescription": { - "message": "We've highlighted at-risk items for new applications stored in Admin console that have weak, exposed, or reused passwords." + "reviewNewAppsDescription": { + "message": "Review new applications with vulnerable items and mark those you’d like to monitor closely as critical. Then, you’ll be able to assign security tasks to members to remove risks." }, "clickIconToMarkAppAsCritical": { "message": "Click the star icon to mark an app as critical" @@ -9856,8 +9850,8 @@ "assignTasks": { "message": "Assign tasks" }, - "assignTasksToMembers": { - "message": "Assign tasks to members for guided resolution" + "assignSecurityTasksToMembers": { + "message": "Send notifications to change passwords" }, "assignToCollections": { "message": "Assign to collections" diff --git a/apps/web/src/locales/nl/messages.json b/apps/web/src/locales/nl/messages.json index 8ac8cf24ca..35d61fc7ce 100644 --- a/apps/web/src/locales/nl/messages.json +++ b/apps/web/src/locales/nl/messages.json @@ -93,8 +93,8 @@ "assignMembersTasksToMonitorProgress": { "message": "Leden taken toewijzen om de voortgang te controleren" }, - "onceYouReviewApps": { - "message": "Zodra je applicaties beoordeelt en ze als kritiek markeert, kun je leden taken toewijzen om risico-items op te lossen en de voortgang hier te controleren" + "onceYouReviewApplications": { + "message": "Zodra je applicaties beoordeelt en als belangrijk markeert, wijs je taken toe aan je leden om hun wachtwoorden te wijzigen." }, "sendReminders": { "message": "Herinneringen versturen" @@ -178,41 +178,35 @@ } } }, - "noApplicationsInOrgTitle": { - "message": "No applications found for $ORG NAME$", - "placeholders": { - "org name": { - "content": "$1", - "example": "Company Name" - } - } + "noDataInOrgTitle": { + "message": "Geen gegevens gevonden" }, - "noApplicationsInOrgDescription": { - "message": "Import your organization's login data to start monitoring credential security risks. Once imported you get to:" + "noDataInOrgDescription": { + "message": "Importeer de inloggegevens van je organisatie om aan de slag te gaan met Access Intelligence. Zodra je dat doet, kun je:" }, - "benefit1Title": { - "message": "Prioritize risks" + "feature1Title": { + "message": "Applicaties als belangrijk markeren" }, - "benefit1Description": { - "message": "Focus on applications that matter the most" + "feature1Description": { + "message": "Hiermee kun je eerst risico's voor je belangrijkste applicaties weghalen." }, - "benefit2Title": { - "message": "Guide remediation" + "feature2Title": { + "message": "Help leden hun beveiliging te verbeteren" }, - "benefit2Description": { - "message": "Assign at-risk members guided tasks to rotate at-risk credentials" + "feature2Description": { + "message": "Risicovolle leden begeleide beveiligingstaken toewijzien om inloggegevens bij te werken." }, - "benefit3Title": { - "message": "Monitor progress" + "feature3Title": { + "message": "Voortgang monitoren" }, - "benefit3Description": { - "message": "Track changes over time to show security improvements" + "feature3Description": { + "message": "Bijhouden van wijzigingen over tijd voor het weergeven van beveiligingsverbeteringen." }, - "noReportRunTitle": { - "message": "Run your first report to see applications" + "noReportsRunTitle": { + "message": "Rapport genereren" }, - "noReportRunDescription": { - "message": "Generate a risk insights report to analyze your organization's applications and identify at-risk passwords that need attention. Running your first report will:" + "noReportsRunDescription": { + "message": "Je bent klaar om rapporten te genereren. Zodra je rapporten maakt, kun je:" }, "noCriticalApplicationsTitle": { "message": "Je hebt nog geen applicaties als belangrijk aangewezen" @@ -271,14 +265,14 @@ "atRiskMembers": { "message": "Leden in gevaar" }, - "membersWithAccessToAtRiskItemsForCriticalApps": { - "message": "Leden met toegang tot risico-items voor belangrijke applicaties" + "membersWithAccessToAtRiskItemsForCriticalApplications": { + "message": "Deze leden hebben toegang tot kwetsbare items voor belangrijke applicaties." }, "membersWithAtRiskPasswords": { "message": "Leden met risicovolle wachtwoorden" }, - "membersWillReceiveNotification": { - "message": "Leden ontvangen een melding via de browserextensie om risico-logins op te lossen." + "membersWillReceiveSecurityTask": { + "message": "Leden van jew organisatie krijgen een taak om kwetsbare wachtwoorden te wijzigen. Ze ontvangen een melding binnen hun Bitwarden-browserextensie." }, "membersAtRiskCount": { "message": "$COUNT$ leden lopen risico", @@ -307,8 +301,8 @@ } } }, - "atRiskMembersDescription": { - "message": "Deze leden loggen in op toepassingen met zwakke, blootgestelde of hergebruikte wachtwoorden." + "atRiskMemberDescription": { + "message": "Deze leden loggen in op applicaties met zwakke, blootgestelde of hergebruikte wachtwoorden." }, "atRiskMembersDescriptionNone": { "message": "Deze niet-leden loggen in op toepassingen met zwakke, blootgestelde of hergebruikte wachtwoorden." @@ -391,14 +385,14 @@ "prioritizeCriticalApplications": { "message": "Belangrijke applicaties prioriteren" }, - "selectCriticalApplicationsDescription": { - "message": "Selecteer welke toepassingen het meest belangrijk zijn voor je organisatie en wijs de leden dan beveiligingstaken toe om risico's op te lossen." + "selectCriticalAppsDescription": { + "message": "Selecteer welke toepassingen het meest belangrijk zijn voor je organisatie. Vervolgens kun je leden beveiligingstaken toewijzen om risico's weg te halen." }, "reviewNewApplications": { "message": "Nieuwe toepassingen beoordelen" }, - "reviewNewApplicationsDescription": { - "message": "We hebben items met risico gemarkeerd voor nieuwe toepassingen die zijn opgeslagen in Admin-console die zwakke, onthulde of hergebruikte wachtwoorden hebben." + "reviewNewAppsDescription": { + "message": "Bekijk nieuwe applicaties met kwetsbare items en markeer degenen die je wilt monitoren als belangrijk. Vervolgens kun je beveiligingstaken toewijzen aan leden om risico's weg te halen." }, "clickIconToMarkAppAsCritical": { "message": "Klik op het sterpictogram om een app als belangrijk te markeren" @@ -9856,8 +9850,8 @@ "assignTasks": { "message": "Taken toewijzen" }, - "assignTasksToMembers": { - "message": "Taken aan leden toewijzen voor een begeleide oplossing" + "assignSecurityTasksToMembers": { + "message": "Meldingen verzenden om wachtwoorden te wijzigen" }, "assignToCollections": { "message": "Toewijzen aan collecties" diff --git a/apps/web/src/locales/nn/messages.json b/apps/web/src/locales/nn/messages.json index b6ec66bf69..4979a3eb72 100644 --- a/apps/web/src/locales/nn/messages.json +++ b/apps/web/src/locales/nn/messages.json @@ -93,8 +93,8 @@ "assignMembersTasksToMonitorProgress": { "message": "Assign members tasks to monitor progress" }, - "onceYouReviewApps": { - "message": "Once you review applications and mark them as critical, you can assign tasks to members to resolve at-risk items and monitor progress here" + "onceYouReviewApplications": { + "message": "Once you review applications and mark them as critical, assign tasks to your members to change their passwords." }, "sendReminders": { "message": "Send reminders" @@ -178,41 +178,35 @@ } } }, - "noApplicationsInOrgTitle": { - "message": "No applications found for $ORG NAME$", - "placeholders": { - "org name": { - "content": "$1", - "example": "Company Name" - } - } + "noDataInOrgTitle": { + "message": "No data found" }, - "noApplicationsInOrgDescription": { - "message": "Import your organization's login data to start monitoring credential security risks. Once imported you get to:" + "noDataInOrgDescription": { + "message": "Import your organization's login data to get started with Access Intelligence. Once you do that, you'll be able to:" }, - "benefit1Title": { - "message": "Prioritize risks" + "feature1Title": { + "message": "Mark applications as critical" }, - "benefit1Description": { - "message": "Focus on applications that matter the most" + "feature1Description": { + "message": "This will help you remove risks to your most important applications first." }, - "benefit2Title": { - "message": "Guide remediation" + "feature2Title": { + "message": "Help members improve their security" }, - "benefit2Description": { - "message": "Assign at-risk members guided tasks to rotate at-risk credentials" + "feature2Description": { + "message": "Assign at-risk members guided security tasks to update credentials." }, - "benefit3Title": { + "feature3Title": { "message": "Monitor progress" }, - "benefit3Description": { - "message": "Track changes over time to show security improvements" + "feature3Description": { + "message": "Track changes over time to show security improvements." }, - "noReportRunTitle": { - "message": "Run your first report to see applications" + "noReportsRunTitle": { + "message": "Generate report" }, - "noReportRunDescription": { - "message": "Generate a risk insights report to analyze your organization's applications and identify at-risk passwords that need attention. Running your first report will:" + "noReportsRunDescription": { + "message": "You’re ready to start generating reports. Once you generate, you’ll be able to:" }, "noCriticalApplicationsTitle": { "message": "You haven’t marked any applications as critical" @@ -271,14 +265,14 @@ "atRiskMembers": { "message": "At-risk members" }, - "membersWithAccessToAtRiskItemsForCriticalApps": { - "message": "Members with access to at-risk items for critical applications" + "membersWithAccessToAtRiskItemsForCriticalApplications": { + "message": "These members have access to vulnerable items for critical applications." }, "membersWithAtRiskPasswords": { "message": "Members with at-risk passwords" }, - "membersWillReceiveNotification": { - "message": "Members will receive a notification to resolve at-risk logins through the browser extension." + "membersWillReceiveSecurityTask": { + "message": "Members of your organization will be assigned a task to change vulnerable passwords. They’ll receive a notification within their Bitwarden browser extension." }, "membersAtRiskCount": { "message": "$COUNT$ members at-risk", @@ -307,8 +301,8 @@ } } }, - "atRiskMembersDescription": { - "message": "These members are logging into applications with weak, exposed, or reused passwords." + "atRiskMemberDescription": { + "message": "These members are logging into critical applications with weak, exposed, or reused passwords." }, "atRiskMembersDescriptionNone": { "message": "These are no members logging into applications with weak, exposed, or reused passwords." @@ -391,14 +385,14 @@ "prioritizeCriticalApplications": { "message": "Prioritize critical applications" }, - "selectCriticalApplicationsDescription": { - "message": "Select which applications are most critical to your organization, then assign security tasks to members to resolve risks." + "selectCriticalAppsDescription": { + "message": "Select which applications are most critical to your organization. Then, you’ll be able to assign security tasks to members to remove risks." }, "reviewNewApplications": { "message": "Review new applications" }, - "reviewNewApplicationsDescription": { - "message": "We've highlighted at-risk items for new applications stored in Admin console that have weak, exposed, or reused passwords." + "reviewNewAppsDescription": { + "message": "Review new applications with vulnerable items and mark those you’d like to monitor closely as critical. Then, you’ll be able to assign security tasks to members to remove risks." }, "clickIconToMarkAppAsCritical": { "message": "Click the star icon to mark an app as critical" @@ -9856,8 +9850,8 @@ "assignTasks": { "message": "Assign tasks" }, - "assignTasksToMembers": { - "message": "Assign tasks to members for guided resolution" + "assignSecurityTasksToMembers": { + "message": "Send notifications to change passwords" }, "assignToCollections": { "message": "Assign to collections" diff --git a/apps/web/src/locales/or/messages.json b/apps/web/src/locales/or/messages.json index 47df482685..9f57ed8c6c 100644 --- a/apps/web/src/locales/or/messages.json +++ b/apps/web/src/locales/or/messages.json @@ -93,8 +93,8 @@ "assignMembersTasksToMonitorProgress": { "message": "Assign members tasks to monitor progress" }, - "onceYouReviewApps": { - "message": "Once you review applications and mark them as critical, you can assign tasks to members to resolve at-risk items and monitor progress here" + "onceYouReviewApplications": { + "message": "Once you review applications and mark them as critical, assign tasks to your members to change their passwords." }, "sendReminders": { "message": "Send reminders" @@ -178,41 +178,35 @@ } } }, - "noApplicationsInOrgTitle": { - "message": "No applications found for $ORG NAME$", - "placeholders": { - "org name": { - "content": "$1", - "example": "Company Name" - } - } + "noDataInOrgTitle": { + "message": "No data found" }, - "noApplicationsInOrgDescription": { - "message": "Import your organization's login data to start monitoring credential security risks. Once imported you get to:" + "noDataInOrgDescription": { + "message": "Import your organization's login data to get started with Access Intelligence. Once you do that, you'll be able to:" }, - "benefit1Title": { - "message": "Prioritize risks" + "feature1Title": { + "message": "Mark applications as critical" }, - "benefit1Description": { - "message": "Focus on applications that matter the most" + "feature1Description": { + "message": "This will help you remove risks to your most important applications first." }, - "benefit2Title": { - "message": "Guide remediation" + "feature2Title": { + "message": "Help members improve their security" }, - "benefit2Description": { - "message": "Assign at-risk members guided tasks to rotate at-risk credentials" + "feature2Description": { + "message": "Assign at-risk members guided security tasks to update credentials." }, - "benefit3Title": { + "feature3Title": { "message": "Monitor progress" }, - "benefit3Description": { - "message": "Track changes over time to show security improvements" + "feature3Description": { + "message": "Track changes over time to show security improvements." }, - "noReportRunTitle": { - "message": "Run your first report to see applications" + "noReportsRunTitle": { + "message": "Generate report" }, - "noReportRunDescription": { - "message": "Generate a risk insights report to analyze your organization's applications and identify at-risk passwords that need attention. Running your first report will:" + "noReportsRunDescription": { + "message": "You’re ready to start generating reports. Once you generate, you’ll be able to:" }, "noCriticalApplicationsTitle": { "message": "You haven’t marked any applications as critical" @@ -271,14 +265,14 @@ "atRiskMembers": { "message": "At-risk members" }, - "membersWithAccessToAtRiskItemsForCriticalApps": { - "message": "Members with access to at-risk items for critical applications" + "membersWithAccessToAtRiskItemsForCriticalApplications": { + "message": "These members have access to vulnerable items for critical applications." }, "membersWithAtRiskPasswords": { "message": "Members with at-risk passwords" }, - "membersWillReceiveNotification": { - "message": "Members will receive a notification to resolve at-risk logins through the browser extension." + "membersWillReceiveSecurityTask": { + "message": "Members of your organization will be assigned a task to change vulnerable passwords. They’ll receive a notification within their Bitwarden browser extension." }, "membersAtRiskCount": { "message": "$COUNT$ members at-risk", @@ -307,8 +301,8 @@ } } }, - "atRiskMembersDescription": { - "message": "These members are logging into applications with weak, exposed, or reused passwords." + "atRiskMemberDescription": { + "message": "These members are logging into critical applications with weak, exposed, or reused passwords." }, "atRiskMembersDescriptionNone": { "message": "These are no members logging into applications with weak, exposed, or reused passwords." @@ -391,14 +385,14 @@ "prioritizeCriticalApplications": { "message": "Prioritize critical applications" }, - "selectCriticalApplicationsDescription": { - "message": "Select which applications are most critical to your organization, then assign security tasks to members to resolve risks." + "selectCriticalAppsDescription": { + "message": "Select which applications are most critical to your organization. Then, you’ll be able to assign security tasks to members to remove risks." }, "reviewNewApplications": { "message": "Review new applications" }, - "reviewNewApplicationsDescription": { - "message": "We've highlighted at-risk items for new applications stored in Admin console that have weak, exposed, or reused passwords." + "reviewNewAppsDescription": { + "message": "Review new applications with vulnerable items and mark those you’d like to monitor closely as critical. Then, you’ll be able to assign security tasks to members to remove risks." }, "clickIconToMarkAppAsCritical": { "message": "Click the star icon to mark an app as critical" @@ -9856,8 +9850,8 @@ "assignTasks": { "message": "Assign tasks" }, - "assignTasksToMembers": { - "message": "Assign tasks to members for guided resolution" + "assignSecurityTasksToMembers": { + "message": "Send notifications to change passwords" }, "assignToCollections": { "message": "Assign to collections" diff --git a/apps/web/src/locales/pl/messages.json b/apps/web/src/locales/pl/messages.json index 9750a2a7df..48f25c451a 100644 --- a/apps/web/src/locales/pl/messages.json +++ b/apps/web/src/locales/pl/messages.json @@ -93,8 +93,8 @@ "assignMembersTasksToMonitorProgress": { "message": "Assign members tasks to monitor progress" }, - "onceYouReviewApps": { - "message": "Once you review applications and mark them as critical, you can assign tasks to members to resolve at-risk items and monitor progress here" + "onceYouReviewApplications": { + "message": "Once you review applications and mark them as critical, assign tasks to your members to change their passwords." }, "sendReminders": { "message": "Send reminders" @@ -178,41 +178,35 @@ } } }, - "noApplicationsInOrgTitle": { - "message": "No applications found for $ORG NAME$", - "placeholders": { - "org name": { - "content": "$1", - "example": "Company Name" - } - } + "noDataInOrgTitle": { + "message": "No data found" }, - "noApplicationsInOrgDescription": { - "message": "Import your organization's login data to start monitoring credential security risks. Once imported you get to:" + "noDataInOrgDescription": { + "message": "Import your organization's login data to get started with Access Intelligence. Once you do that, you'll be able to:" }, - "benefit1Title": { - "message": "Prioritize risks" + "feature1Title": { + "message": "Mark applications as critical" }, - "benefit1Description": { - "message": "Focus on applications that matter the most" + "feature1Description": { + "message": "This will help you remove risks to your most important applications first." }, - "benefit2Title": { - "message": "Guide remediation" + "feature2Title": { + "message": "Help members improve their security" }, - "benefit2Description": { - "message": "Assign at-risk members guided tasks to rotate at-risk credentials" + "feature2Description": { + "message": "Assign at-risk members guided security tasks to update credentials." }, - "benefit3Title": { + "feature3Title": { "message": "Monitor progress" }, - "benefit3Description": { - "message": "Track changes over time to show security improvements" + "feature3Description": { + "message": "Track changes over time to show security improvements." }, - "noReportRunTitle": { - "message": "Run your first report to see applications" + "noReportsRunTitle": { + "message": "Generate report" }, - "noReportRunDescription": { - "message": "Generate a risk insights report to analyze your organization's applications and identify at-risk passwords that need attention. Running your first report will:" + "noReportsRunDescription": { + "message": "You’re ready to start generating reports. Once you generate, you’ll be able to:" }, "noCriticalApplicationsTitle": { "message": "You haven’t marked any applications as critical" @@ -271,14 +265,14 @@ "atRiskMembers": { "message": "Zagrożeni użytkownicy" }, - "membersWithAccessToAtRiskItemsForCriticalApps": { - "message": "Members with access to at-risk items for critical applications" + "membersWithAccessToAtRiskItemsForCriticalApplications": { + "message": "These members have access to vulnerable items for critical applications." }, "membersWithAtRiskPasswords": { "message": "Members with at-risk passwords" }, - "membersWillReceiveNotification": { - "message": "Members will receive a notification to resolve at-risk logins through the browser extension." + "membersWillReceiveSecurityTask": { + "message": "Members of your organization will be assigned a task to change vulnerable passwords. They’ll receive a notification within their Bitwarden browser extension." }, "membersAtRiskCount": { "message": "$COUNT$ members at-risk", @@ -307,8 +301,8 @@ } } }, - "atRiskMembersDescription": { - "message": "Ci członkowie logują się do aplikacji ze słabymi, ujawnionymi lub ponownie używanymi hasłami." + "atRiskMemberDescription": { + "message": "These members are logging into critical applications with weak, exposed, or reused passwords." }, "atRiskMembersDescriptionNone": { "message": "Ci członkowie nie logują się do aplikacji ze słabymi, ujawnionymi lub ponownie używanymi hasłami." @@ -391,14 +385,14 @@ "prioritizeCriticalApplications": { "message": "Prioritize critical applications" }, - "selectCriticalApplicationsDescription": { - "message": "Select which applications are most critical to your organization, then assign security tasks to members to resolve risks." + "selectCriticalAppsDescription": { + "message": "Select which applications are most critical to your organization. Then, you’ll be able to assign security tasks to members to remove risks." }, "reviewNewApplications": { "message": "Review new applications" }, - "reviewNewApplicationsDescription": { - "message": "We've highlighted at-risk items for new applications stored in Admin console that have weak, exposed, or reused passwords." + "reviewNewAppsDescription": { + "message": "Review new applications with vulnerable items and mark those you’d like to monitor closely as critical. Then, you’ll be able to assign security tasks to members to remove risks." }, "clickIconToMarkAppAsCritical": { "message": "Click the star icon to mark an app as critical" @@ -9856,8 +9850,8 @@ "assignTasks": { "message": "Assign tasks" }, - "assignTasksToMembers": { - "message": "Assign tasks to members for guided resolution" + "assignSecurityTasksToMembers": { + "message": "Send notifications to change passwords" }, "assignToCollections": { "message": "Przypisz do kolekcji" diff --git a/apps/web/src/locales/pt_BR/messages.json b/apps/web/src/locales/pt_BR/messages.json index 4ef989dcd7..4520e190b5 100644 --- a/apps/web/src/locales/pt_BR/messages.json +++ b/apps/web/src/locales/pt_BR/messages.json @@ -93,8 +93,8 @@ "assignMembersTasksToMonitorProgress": { "message": "Atribuir tarefas a membros para monitorar progresso" }, - "onceYouReviewApps": { - "message": "Ao revisar aplicativos e marcá-los como críticos, você pode atribuir traferas a membros para resolver itens em risco e monitorar o progresso aqui" + "onceYouReviewApplications": { + "message": "Once you review applications and mark them as critical, assign tasks to your members to change their passwords." }, "sendReminders": { "message": "Enviar lembretes" @@ -178,41 +178,35 @@ } } }, - "noApplicationsInOrgTitle": { - "message": "No applications found for $ORG NAME$", - "placeholders": { - "org name": { - "content": "$1", - "example": "Company Name" - } - } + "noDataInOrgTitle": { + "message": "No data found" }, - "noApplicationsInOrgDescription": { - "message": "Import your organization's login data to start monitoring credential security risks. Once imported you get to:" + "noDataInOrgDescription": { + "message": "Import your organization's login data to get started with Access Intelligence. Once you do that, you'll be able to:" }, - "benefit1Title": { - "message": "Prioritize risks" + "feature1Title": { + "message": "Mark applications as critical" }, - "benefit1Description": { - "message": "Focus on applications that matter the most" + "feature1Description": { + "message": "This will help you remove risks to your most important applications first." }, - "benefit2Title": { - "message": "Guide remediation" + "feature2Title": { + "message": "Help members improve their security" }, - "benefit2Description": { - "message": "Assign at-risk members guided tasks to rotate at-risk credentials" + "feature2Description": { + "message": "Assign at-risk members guided security tasks to update credentials." }, - "benefit3Title": { + "feature3Title": { "message": "Monitor progress" }, - "benefit3Description": { - "message": "Track changes over time to show security improvements" + "feature3Description": { + "message": "Track changes over time to show security improvements." }, - "noReportRunTitle": { - "message": "Run your first report to see applications" + "noReportsRunTitle": { + "message": "Generate report" }, - "noReportRunDescription": { - "message": "Generate a risk insights report to analyze your organization's applications and identify at-risk passwords that need attention. Running your first report will:" + "noReportsRunDescription": { + "message": "You’re ready to start generating reports. Once you generate, you’ll be able to:" }, "noCriticalApplicationsTitle": { "message": "Você não marcou nenhum aplicativo como crítico" @@ -271,14 +265,14 @@ "atRiskMembers": { "message": "Membros em risco" }, - "membersWithAccessToAtRiskItemsForCriticalApps": { - "message": "Membros com acesso a itens em risco de aplicativos críticos" + "membersWithAccessToAtRiskItemsForCriticalApplications": { + "message": "These members have access to vulnerable items for critical applications." }, "membersWithAtRiskPasswords": { "message": "Members with at-risk passwords" }, - "membersWillReceiveNotification": { - "message": "Members will receive a notification to resolve at-risk logins through the browser extension." + "membersWillReceiveSecurityTask": { + "message": "Members of your organization will be assigned a task to change vulnerable passwords. They’ll receive a notification within their Bitwarden browser extension." }, "membersAtRiskCount": { "message": "$COUNT$ membros em risco", @@ -307,8 +301,8 @@ } } }, - "atRiskMembersDescription": { - "message": "Esses membros estão conectando-se em aplicativos com senhas fracas, expostas, ou reutilizadas." + "atRiskMemberDescription": { + "message": "These members are logging into critical applications with weak, exposed, or reused passwords." }, "atRiskMembersDescriptionNone": { "message": "Não há nenhum membro se conectando em aplicativos com senhas fracas, expostas, ou reutilizadas." @@ -391,14 +385,14 @@ "prioritizeCriticalApplications": { "message": "Priorizar aplicativos críticos" }, - "selectCriticalApplicationsDescription": { - "message": "Select which applications are most critical to your organization, then assign security tasks to members to resolve risks." + "selectCriticalAppsDescription": { + "message": "Select which applications are most critical to your organization. Then, you’ll be able to assign security tasks to members to remove risks." }, "reviewNewApplications": { "message": "Review new applications" }, - "reviewNewApplicationsDescription": { - "message": "We've highlighted at-risk items for new applications stored in Admin console that have weak, exposed, or reused passwords." + "reviewNewAppsDescription": { + "message": "Review new applications with vulnerable items and mark those you’d like to monitor closely as critical. Then, you’ll be able to assign security tasks to members to remove risks." }, "clickIconToMarkAppAsCritical": { "message": "Click the star icon to mark an app as critical" @@ -9856,8 +9850,8 @@ "assignTasks": { "message": "Assign tasks" }, - "assignTasksToMembers": { - "message": "Assign tasks to members for guided resolution" + "assignSecurityTasksToMembers": { + "message": "Send notifications to change passwords" }, "assignToCollections": { "message": "Atribuir à coleções" diff --git a/apps/web/src/locales/pt_PT/messages.json b/apps/web/src/locales/pt_PT/messages.json index 45b511a857..4831f14d69 100644 --- a/apps/web/src/locales/pt_PT/messages.json +++ b/apps/web/src/locales/pt_PT/messages.json @@ -93,8 +93,8 @@ "assignMembersTasksToMonitorProgress": { "message": "Atribuir tarefas aos membros para monitorizar o progresso" }, - "onceYouReviewApps": { - "message": "Depois de analisar as aplicações e marcá-las como críticas, pode atribuir tarefas aos membros para resolver itens em risco e monitorizar o progresso aqui" + "onceYouReviewApplications": { + "message": "Depois de rever as aplicações e marcá-las como críticas, atribua tarefas aos seus membros para que alterem as respetivas palavras-passe." }, "sendReminders": { "message": "Enviar lembretes" @@ -178,41 +178,35 @@ } } }, - "noApplicationsInOrgTitle": { - "message": "Não foram encontradas aplicações para $ORG NAME$", - "placeholders": { - "org name": { - "content": "$1", - "example": "Company Name" - } - } + "noDataInOrgTitle": { + "message": "Não foram encontrados dados" }, - "noApplicationsInOrgDescription": { - "message": "Importe as credenciais da sua organização para começar a monitorizar os riscos de segurança das credenciais. Após a importação, poderá:" + "noDataInOrgDescription": { + "message": "Import your organization's login data to get started with Access Intelligence. Once you do that, you'll be able to:" }, - "benefit1Title": { - "message": "Priorizar os riscos" + "feature1Title": { + "message": "Mark applications as critical" }, - "benefit1Description": { - "message": "Com foco nas aplicações mais importantes" + "feature1Description": { + "message": "This will help you remove risks to your most important applications first." }, - "benefit2Title": { - "message": "Remediação de guias" + "feature2Title": { + "message": "Help members improve their security" }, - "benefit2Description": { - "message": "Atribuir tarefas orientadas aos membros em risco para alterar as credenciais em risco" + "feature2Description": { + "message": "Assign at-risk members guided security tasks to update credentials." }, - "benefit3Title": { - "message": "Monitorizar o progresso" + "feature3Title": { + "message": "Monitor progress" }, - "benefit3Description": { - "message": "Acompanhe as alterações ao longo do tempo para mostrar as melhorias na segurança" + "feature3Description": { + "message": "Track changes over time to show security improvements." }, - "noReportRunTitle": { - "message": "Execute o seu primeiro relatório para ver as aplicações" + "noReportsRunTitle": { + "message": "Generate report" }, - "noReportRunDescription": { - "message": "Gere um relatório de insights de risco para analisar as aplicações da sua organização e identificar palavras-passe em risco que precisam de atenção. A execução do seu primeiro relatório irá:" + "noReportsRunDescription": { + "message": "You’re ready to start generating reports. Once you generate, you’ll be able to:" }, "noCriticalApplicationsTitle": { "message": "Não marcou nenhuma aplicação como crítica" @@ -271,14 +265,14 @@ "atRiskMembers": { "message": "Membros em risco" }, - "membersWithAccessToAtRiskItemsForCriticalApps": { - "message": "Membros com acesso a itens em risco para aplicações críticas" + "membersWithAccessToAtRiskItemsForCriticalApplications": { + "message": "These members have access to vulnerable items for critical applications." }, "membersWithAtRiskPasswords": { "message": "Membros com palavras-passe em risco" }, - "membersWillReceiveNotification": { - "message": "Os membros receberão uma notificação para resolver as credenciais em risco através da extensão do navegador." + "membersWillReceiveSecurityTask": { + "message": "Members of your organization will be assigned a task to change vulnerable passwords. They’ll receive a notification within their Bitwarden browser extension." }, "membersAtRiskCount": { "message": "$COUNT$ membros em risco", @@ -307,8 +301,8 @@ } } }, - "atRiskMembersDescription": { - "message": "Estes membros estão a iniciar sessão em aplicações com palavras-passe fracas, expostas ou reutilizadas." + "atRiskMemberDescription": { + "message": "These members are logging into critical applications with weak, exposed, or reused passwords." }, "atRiskMembersDescriptionNone": { "message": "Estes não são membros que iniciam sessão em aplicações com palavras-passe fracas, expostas ou reutilizadas." @@ -391,14 +385,14 @@ "prioritizeCriticalApplications": { "message": "Dê prioridade a aplicações críticas" }, - "selectCriticalApplicationsDescription": { - "message": "Selecione quais aplicações são mais críticas para a sua organização e, em seguida, atribua tarefas de segurança aos membros para resolver os riscos." + "selectCriticalAppsDescription": { + "message": "Select which applications are most critical to your organization. Then, you’ll be able to assign security tasks to members to remove risks." }, "reviewNewApplications": { "message": "Rever novas aplicações" }, - "reviewNewApplicationsDescription": { - "message": "Destacámos os itens em risco para novas aplicações armazenadas na consola de administração que têm palavras-passe fracas, expostas ou reutilizadas." + "reviewNewAppsDescription": { + "message": "Review new applications with vulnerable items and mark those you’d like to monitor closely as critical. Then, you’ll be able to assign security tasks to members to remove risks." }, "clickIconToMarkAppAsCritical": { "message": "Clique no ícone de estrela para marcar uma app como crítica" @@ -9856,8 +9850,8 @@ "assignTasks": { "message": "Atribuir tarefas" }, - "assignTasksToMembers": { - "message": "Atribuir tarefas aos membros para resolução guiada" + "assignSecurityTasksToMembers": { + "message": "Send notifications to change passwords" }, "assignToCollections": { "message": "Atribuir às coleções" @@ -12083,7 +12077,7 @@ "message": "Tem o plano gratuito do Bitwarden" }, "upgradeCompleteSecurity": { - "message": "Atualize para segurança total" + "message": "Atualize para obter segurança total" }, "viewbusinessplans": { "message": "Ver planos empresariais" diff --git a/apps/web/src/locales/ro/messages.json b/apps/web/src/locales/ro/messages.json index e683e0a5f1..0c3eaa3ea0 100644 --- a/apps/web/src/locales/ro/messages.json +++ b/apps/web/src/locales/ro/messages.json @@ -93,8 +93,8 @@ "assignMembersTasksToMonitorProgress": { "message": "Assign members tasks to monitor progress" }, - "onceYouReviewApps": { - "message": "Once you review applications and mark them as critical, you can assign tasks to members to resolve at-risk items and monitor progress here" + "onceYouReviewApplications": { + "message": "Once you review applications and mark them as critical, assign tasks to your members to change their passwords." }, "sendReminders": { "message": "Send reminders" @@ -178,41 +178,35 @@ } } }, - "noApplicationsInOrgTitle": { - "message": "No applications found for $ORG NAME$", - "placeholders": { - "org name": { - "content": "$1", - "example": "Company Name" - } - } + "noDataInOrgTitle": { + "message": "No data found" }, - "noApplicationsInOrgDescription": { - "message": "Import your organization's login data to start monitoring credential security risks. Once imported you get to:" + "noDataInOrgDescription": { + "message": "Import your organization's login data to get started with Access Intelligence. Once you do that, you'll be able to:" }, - "benefit1Title": { - "message": "Prioritize risks" + "feature1Title": { + "message": "Mark applications as critical" }, - "benefit1Description": { - "message": "Focus on applications that matter the most" + "feature1Description": { + "message": "This will help you remove risks to your most important applications first." }, - "benefit2Title": { - "message": "Guide remediation" + "feature2Title": { + "message": "Help members improve their security" }, - "benefit2Description": { - "message": "Assign at-risk members guided tasks to rotate at-risk credentials" + "feature2Description": { + "message": "Assign at-risk members guided security tasks to update credentials." }, - "benefit3Title": { + "feature3Title": { "message": "Monitor progress" }, - "benefit3Description": { - "message": "Track changes over time to show security improvements" + "feature3Description": { + "message": "Track changes over time to show security improvements." }, - "noReportRunTitle": { - "message": "Run your first report to see applications" + "noReportsRunTitle": { + "message": "Generate report" }, - "noReportRunDescription": { - "message": "Generate a risk insights report to analyze your organization's applications and identify at-risk passwords that need attention. Running your first report will:" + "noReportsRunDescription": { + "message": "You’re ready to start generating reports. Once you generate, you’ll be able to:" }, "noCriticalApplicationsTitle": { "message": "You haven’t marked any applications as critical" @@ -271,14 +265,14 @@ "atRiskMembers": { "message": "At-risk members" }, - "membersWithAccessToAtRiskItemsForCriticalApps": { - "message": "Members with access to at-risk items for critical applications" + "membersWithAccessToAtRiskItemsForCriticalApplications": { + "message": "These members have access to vulnerable items for critical applications." }, "membersWithAtRiskPasswords": { "message": "Members with at-risk passwords" }, - "membersWillReceiveNotification": { - "message": "Members will receive a notification to resolve at-risk logins through the browser extension." + "membersWillReceiveSecurityTask": { + "message": "Members of your organization will be assigned a task to change vulnerable passwords. They’ll receive a notification within their Bitwarden browser extension." }, "membersAtRiskCount": { "message": "$COUNT$ members at-risk", @@ -307,8 +301,8 @@ } } }, - "atRiskMembersDescription": { - "message": "These members are logging into applications with weak, exposed, or reused passwords." + "atRiskMemberDescription": { + "message": "These members are logging into critical applications with weak, exposed, or reused passwords." }, "atRiskMembersDescriptionNone": { "message": "These are no members logging into applications with weak, exposed, or reused passwords." @@ -391,14 +385,14 @@ "prioritizeCriticalApplications": { "message": "Prioritize critical applications" }, - "selectCriticalApplicationsDescription": { - "message": "Select which applications are most critical to your organization, then assign security tasks to members to resolve risks." + "selectCriticalAppsDescription": { + "message": "Select which applications are most critical to your organization. Then, you’ll be able to assign security tasks to members to remove risks." }, "reviewNewApplications": { "message": "Review new applications" }, - "reviewNewApplicationsDescription": { - "message": "We've highlighted at-risk items for new applications stored in Admin console that have weak, exposed, or reused passwords." + "reviewNewAppsDescription": { + "message": "Review new applications with vulnerable items and mark those you’d like to monitor closely as critical. Then, you’ll be able to assign security tasks to members to remove risks." }, "clickIconToMarkAppAsCritical": { "message": "Click the star icon to mark an app as critical" @@ -9856,8 +9850,8 @@ "assignTasks": { "message": "Assign tasks" }, - "assignTasksToMembers": { - "message": "Assign tasks to members for guided resolution" + "assignSecurityTasksToMembers": { + "message": "Send notifications to change passwords" }, "assignToCollections": { "message": "Assign to collections" diff --git a/apps/web/src/locales/ru/messages.json b/apps/web/src/locales/ru/messages.json index 9b5a939949..205e953c0e 100644 --- a/apps/web/src/locales/ru/messages.json +++ b/apps/web/src/locales/ru/messages.json @@ -93,8 +93,8 @@ "assignMembersTasksToMonitorProgress": { "message": "Назначайте членам команды задачи по мониторингу прогресса" }, - "onceYouReviewApps": { - "message": "Как только вы оцените приложения и пометите их как критичные, вы можете назначить задачи участникам касающиеся элементов, подверженных риску, и следить за прогрессом здесь" + "onceYouReviewApplications": { + "message": "После того как вы просмотрите приложения и отметите их как критичные, назначьте своим пользователям задачи по смене паролей." }, "sendReminders": { "message": "Отправить напоминания" @@ -178,41 +178,35 @@ } } }, - "noApplicationsInOrgTitle": { - "message": "Не найдено приложений для $ORG NAME$", - "placeholders": { - "org name": { - "content": "$1", - "example": "Company Name" - } - } + "noDataInOrgTitle": { + "message": "Данные не найдены" }, - "noApplicationsInOrgDescription": { - "message": "Импортируйте логины вашей организации, чтобы начать мониторинг угроз безопасности учетных данных. После импорта вы получите доступ к:" + "noDataInOrgDescription": { + "message": "Импортируйте данные логинов вашей организации, чтобы начать работу с Access Intelligence. Как только вы это сделаете, вы сможете:" }, - "benefit1Title": { - "message": "Приоритет рисков" + "feature1Title": { + "message": "Пометить приложения как критичные" }, - "benefit1Description": { - "message": "Сосредоточьтесь на наиболее важных приложениях" + "feature1Description": { + "message": "Это поможет вам в первую очередь устранить риски для ваших наиболее важных приложений." }, - "benefit2Title": { - "message": "Руководство по восстановлению" + "feature2Title": { + "message": "Помогите пользователями повысить безопасность" }, - "benefit2Description": { - "message": "Назначайте участникам, подверженным риску, управляемые задания для ротации учетных данных" + "feature2Description": { + "message": "Назначайте участникам, находящимся в группе риска, управляемые задачи по обеспечению безопасности для обновления учетных данных." }, - "benefit3Title": { + "feature3Title": { "message": "Отслеживать прогресс" }, - "benefit3Description": { - "message": "Отслеживать изменения с течением времени, чтобы показать улучшения безопасности" + "feature3Description": { + "message": "Отслеживать изменения с течением времени, чтобы показать улучшения безопасности." }, - "noReportRunTitle": { - "message": "Запустите ваш первый отчет для просмотра приложений" + "noReportsRunTitle": { + "message": "Создать отчет" }, - "noReportRunDescription": { - "message": "Создайте аналитический отчет о рисках для анализа приложений вашей организации и выявления паролей, подверженных риску, которые требуют внимания. Запуск первого отчета позволит:" + "noReportsRunDescription": { + "message": "Вы готовы приступить к созданию отчетов. После создания вы сможете:" }, "noCriticalApplicationsTitle": { "message": "Вы не отметили ни одного приложения в качестве критичного" @@ -271,14 +265,14 @@ "atRiskMembers": { "message": "Участники, подверженные риску" }, - "membersWithAccessToAtRiskItemsForCriticalApps": { - "message": "Участники, имеющие доступ к элементам, подверженным риску, для критичных приложений" + "membersWithAccessToAtRiskItemsForCriticalApplications": { + "message": "Эти пользователи имеют доступ к уязвимым элементам критичных приложений." }, "membersWithAtRiskPasswords": { "message": "Пользователи, пароли которых подверженны риску" }, - "membersWillReceiveNotification": { - "message": "Пользователи получат уведомление о разрешении подверженных риску логинов с помощью расширения браузера." + "membersWillReceiveSecurityTask": { + "message": "Сотрудникам вашей организации будет поручено изменить уязвимые пароли. Они получат уведомление в своем расширении Bitwarden для браузера." }, "membersAtRiskCount": { "message": "$COUNT$ участников, подверженных риску", @@ -307,8 +301,8 @@ } } }, - "atRiskMembersDescription": { - "message": "Эти пользователи входят в приложения со слабыми, скомпрометированными или повторно используемыми паролями." + "atRiskMemberDescription": { + "message": "Эти пользователи входят в критичные приложения со слабыми, скомпрометированными или повторно используемыми паролями." }, "atRiskMembersDescriptionNone": { "message": "Нет пользователей, входящих в приложения со слабыми, скомпрометированными или повторно используемыми паролями." @@ -391,14 +385,14 @@ "prioritizeCriticalApplications": { "message": "Приоритет критичных приложений" }, - "selectCriticalApplicationsDescription": { - "message": "Выберите, какие приложения наиболее критичны для вашей организации, а затем назначьте пользователям задачи по обеспечению безопасности для устранения рисков." + "selectCriticalAppsDescription": { + "message": "Выберите, какие приложения наиболее критичны для вашей организации. Затем вы сможете назначить пользователям задачи по обеспечению безопасности по устранению рисков." }, "reviewNewApplications": { "message": "Обзор новых приложений" }, - "reviewNewApplicationsDescription": { - "message": "Мы выделили элементы, подверженные риску, для новых приложений, хранящихся в консоли администратора, которые имеют слабые, незащищенные или повторно используемые пароли." + "reviewNewAppsDescription": { + "message": "Просмотрите новые приложения, содержащие уязвимые элементы, и отметьте те, за которыми вы хотели бы внимательно следить, как критичные. После этого вы сможете назначать пользователям задачи по обеспечению безопасности для устранения рисков." }, "clickIconToMarkAppAsCritical": { "message": "Нажмите на значок звездочки, чтобы отметить приложение как критичное" @@ -9856,8 +9850,8 @@ "assignTasks": { "message": "Назначить задачи" }, - "assignTasksToMembers": { - "message": "Назначайте задачи пользователям для управляемого решения" + "assignSecurityTasksToMembers": { + "message": "Отправляйте уведомления о смене паролей" }, "assignToCollections": { "message": "Назначить коллекциям" diff --git a/apps/web/src/locales/si/messages.json b/apps/web/src/locales/si/messages.json index 0fdc35fb8d..aeb1a4b4e0 100644 --- a/apps/web/src/locales/si/messages.json +++ b/apps/web/src/locales/si/messages.json @@ -93,8 +93,8 @@ "assignMembersTasksToMonitorProgress": { "message": "Assign members tasks to monitor progress" }, - "onceYouReviewApps": { - "message": "Once you review applications and mark them as critical, you can assign tasks to members to resolve at-risk items and monitor progress here" + "onceYouReviewApplications": { + "message": "Once you review applications and mark them as critical, assign tasks to your members to change their passwords." }, "sendReminders": { "message": "Send reminders" @@ -178,41 +178,35 @@ } } }, - "noApplicationsInOrgTitle": { - "message": "No applications found for $ORG NAME$", - "placeholders": { - "org name": { - "content": "$1", - "example": "Company Name" - } - } + "noDataInOrgTitle": { + "message": "No data found" }, - "noApplicationsInOrgDescription": { - "message": "Import your organization's login data to start monitoring credential security risks. Once imported you get to:" + "noDataInOrgDescription": { + "message": "Import your organization's login data to get started with Access Intelligence. Once you do that, you'll be able to:" }, - "benefit1Title": { - "message": "Prioritize risks" + "feature1Title": { + "message": "Mark applications as critical" }, - "benefit1Description": { - "message": "Focus on applications that matter the most" + "feature1Description": { + "message": "This will help you remove risks to your most important applications first." }, - "benefit2Title": { - "message": "Guide remediation" + "feature2Title": { + "message": "Help members improve their security" }, - "benefit2Description": { - "message": "Assign at-risk members guided tasks to rotate at-risk credentials" + "feature2Description": { + "message": "Assign at-risk members guided security tasks to update credentials." }, - "benefit3Title": { + "feature3Title": { "message": "Monitor progress" }, - "benefit3Description": { - "message": "Track changes over time to show security improvements" + "feature3Description": { + "message": "Track changes over time to show security improvements." }, - "noReportRunTitle": { - "message": "Run your first report to see applications" + "noReportsRunTitle": { + "message": "Generate report" }, - "noReportRunDescription": { - "message": "Generate a risk insights report to analyze your organization's applications and identify at-risk passwords that need attention. Running your first report will:" + "noReportsRunDescription": { + "message": "You’re ready to start generating reports. Once you generate, you’ll be able to:" }, "noCriticalApplicationsTitle": { "message": "You haven’t marked any applications as critical" @@ -271,14 +265,14 @@ "atRiskMembers": { "message": "At-risk members" }, - "membersWithAccessToAtRiskItemsForCriticalApps": { - "message": "Members with access to at-risk items for critical applications" + "membersWithAccessToAtRiskItemsForCriticalApplications": { + "message": "These members have access to vulnerable items for critical applications." }, "membersWithAtRiskPasswords": { "message": "Members with at-risk passwords" }, - "membersWillReceiveNotification": { - "message": "Members will receive a notification to resolve at-risk logins through the browser extension." + "membersWillReceiveSecurityTask": { + "message": "Members of your organization will be assigned a task to change vulnerable passwords. They’ll receive a notification within their Bitwarden browser extension." }, "membersAtRiskCount": { "message": "$COUNT$ members at-risk", @@ -307,8 +301,8 @@ } } }, - "atRiskMembersDescription": { - "message": "These members are logging into applications with weak, exposed, or reused passwords." + "atRiskMemberDescription": { + "message": "These members are logging into critical applications with weak, exposed, or reused passwords." }, "atRiskMembersDescriptionNone": { "message": "These are no members logging into applications with weak, exposed, or reused passwords." @@ -391,14 +385,14 @@ "prioritizeCriticalApplications": { "message": "Prioritize critical applications" }, - "selectCriticalApplicationsDescription": { - "message": "Select which applications are most critical to your organization, then assign security tasks to members to resolve risks." + "selectCriticalAppsDescription": { + "message": "Select which applications are most critical to your organization. Then, you’ll be able to assign security tasks to members to remove risks." }, "reviewNewApplications": { "message": "Review new applications" }, - "reviewNewApplicationsDescription": { - "message": "We've highlighted at-risk items for new applications stored in Admin console that have weak, exposed, or reused passwords." + "reviewNewAppsDescription": { + "message": "Review new applications with vulnerable items and mark those you’d like to monitor closely as critical. Then, you’ll be able to assign security tasks to members to remove risks." }, "clickIconToMarkAppAsCritical": { "message": "Click the star icon to mark an app as critical" @@ -9856,8 +9850,8 @@ "assignTasks": { "message": "Assign tasks" }, - "assignTasksToMembers": { - "message": "Assign tasks to members for guided resolution" + "assignSecurityTasksToMembers": { + "message": "Send notifications to change passwords" }, "assignToCollections": { "message": "Assign to collections" diff --git a/apps/web/src/locales/sk/messages.json b/apps/web/src/locales/sk/messages.json index fdcaa412db..30afb3afcc 100644 --- a/apps/web/src/locales/sk/messages.json +++ b/apps/web/src/locales/sk/messages.json @@ -93,8 +93,8 @@ "assignMembersTasksToMonitorProgress": { "message": "Pre sledovanie progresu, priraďte členom úlohy" }, - "onceYouReviewApps": { - "message": "Keď skontrolujete a označíte kritické aplikácie, môžete na tomto mieste prideliť členom úlohy pre ohrozené položky a sledovať progres" + "onceYouReviewApplications": { + "message": "Once you review applications and mark them as critical, assign tasks to your members to change their passwords." }, "sendReminders": { "message": "Poslať upomienky" @@ -178,41 +178,35 @@ } } }, - "noApplicationsInOrgTitle": { - "message": "Neboli nájdené žiadne aplikácie v $ORG NAME$", - "placeholders": { - "org name": { - "content": "$1", - "example": "Company Name" - } - } + "noDataInOrgTitle": { + "message": "No data found" }, - "noApplicationsInOrgDescription": { - "message": "Pre začatie monitorovania bezpečnostných problémov importujte prihlasovacie údaje vašej organizácie. Po importe budete mať k dispozícii:" + "noDataInOrgDescription": { + "message": "Import your organization's login data to get started with Access Intelligence. Once you do that, you'll be able to:" }, - "benefit1Title": { - "message": "Prioritizácia bezpečnostných problémov" + "feature1Title": { + "message": "Mark applications as critical" }, - "benefit1Description": { - "message": "Zamerajte sa na najdôležitejšie aplikácie" + "feature1Description": { + "message": "This will help you remove risks to your most important applications first." }, - "benefit2Title": { - "message": "Sprievodca nápravou" + "feature2Title": { + "message": "Help members improve their security" }, - "benefit2Description": { - "message": "Prideľte ohrozeným členom úlohy pre obnovu ohrozených prihlasovacích údajov" + "feature2Description": { + "message": "Assign at-risk members guided security tasks to update credentials." }, - "benefit3Title": { - "message": "Monitorovanie progresu" + "feature3Title": { + "message": "Monitor progress" }, - "benefit3Description": { - "message": "Zobrazte zlepšenie zabezpečenia sledovaním zmien v priebehu času" + "feature3Description": { + "message": "Track changes over time to show security improvements." }, - "noReportRunTitle": { - "message": "Pre prehľad aplikácií generujte váš prvý report" + "noReportsRunTitle": { + "message": "Generate report" }, - "noReportRunDescription": { - "message": "Generujte prehľad rizík pre analýzu aplikácií vo vašej organizácii a identifikujte ohrozene heslá ktoré vyžadujú vašu pozornosť. Spustením vášho prvého reportu:" + "noReportsRunDescription": { + "message": "You’re ready to start generating reports. Once you generate, you’ll be able to:" }, "noCriticalApplicationsTitle": { "message": "Neoznačili ste žiadne aplikácie ako kritické" @@ -271,14 +265,14 @@ "atRiskMembers": { "message": "Ohrozených členov" }, - "membersWithAccessToAtRiskItemsForCriticalApps": { - "message": "Členovia s prístupom k ohrozeným položkám kritických aplikácii" + "membersWithAccessToAtRiskItemsForCriticalApplications": { + "message": "These members have access to vulnerable items for critical applications." }, "membersWithAtRiskPasswords": { "message": "Členovia s ohrozenými heslami" }, - "membersWillReceiveNotification": { - "message": "Členovia dostanú notifikáciu aby vyriešili problémy s ohrozeným heslom prostredníctvom rozšírenia pre prehliadače." + "membersWillReceiveSecurityTask": { + "message": "Members of your organization will be assigned a task to change vulnerable passwords. They’ll receive a notification within their Bitwarden browser extension." }, "membersAtRiskCount": { "message": "$COUNT$ ohrozených členov", @@ -307,8 +301,8 @@ } } }, - "atRiskMembersDescription": { - "message": "Títo členovia sa prihlasujú do aplikácií so slabým, uniknutým alebo viacnásobne použitým heslom." + "atRiskMemberDescription": { + "message": "These members are logging into critical applications with weak, exposed, or reused passwords." }, "atRiskMembersDescriptionNone": { "message": "These are no members logging into applications with weak, exposed, or reused passwords." @@ -368,13 +362,13 @@ "message": "Skontrolovať teraz" }, "allCaughtUp": { - "message": "All caught up!" + "message": "Všetko hotové!" }, "noNewApplicationsToReviewAtThisTime": { - "message": "No new applications to review at this time" + "message": "Žiadne nové aplikácie na kontrolu" }, "organizationHasItemsSavedForApplications": { - "message": "Your organization has items saved for $COUNT$ applications", + "message": "Vaša organizácia ma uložené položky pre $COUNT$ aplikácii", "placeholders": { "count": { "content": "$1", @@ -383,22 +377,22 @@ } }, "reviewApplicationsToSecureItems": { - "message": "Review applications to secure the items most critical to your organization's security" + "message": "Pre zabezpečenie položiek najkritickejších pre bezpečnosť vašej organizácie, skontrolujte aplikácie" }, "reviewApplications": { - "message": "Review applications" + "message": "Skontrolovať aplikácie" }, "prioritizeCriticalApplications": { "message": "Uprednostniť kritické aplikácie" }, - "selectCriticalApplicationsDescription": { - "message": "Vyberte ktoré aplikácie sú pre vašu organizáciu najkritickejšie, potom prideľte členom bezpečnostné úlohy pre vyriešenie ohrozených hesiel." + "selectCriticalAppsDescription": { + "message": "Select which applications are most critical to your organization. Then, you’ll be able to assign security tasks to members to remove risks." }, "reviewNewApplications": { "message": "Review new applications" }, - "reviewNewApplicationsDescription": { - "message": "We've highlighted at-risk items for new applications stored in Admin console that have weak, exposed, or reused passwords." + "reviewNewAppsDescription": { + "message": "Review new applications with vulnerable items and mark those you’d like to monitor closely as critical. Then, you’ll be able to assign security tasks to members to remove risks." }, "clickIconToMarkAppAsCritical": { "message": "Aplikáciu označíte za kritickú kliknutím na ikonu hviezdičky" @@ -3251,16 +3245,16 @@ "message": "Ďalšia platba" }, "nextChargeHeader": { - "message": "Next Charge" + "message": "Ďalšia platba" }, "plan": { - "message": "Plan" + "message": "Plán" }, "details": { "message": "Podrobnosti" }, "discount": { - "message": "discount" + "message": "zľava" }, "downloadLicense": { "message": "Stiahnuť licenciu" @@ -5954,16 +5948,16 @@ "description": "'Send' is a noun and the name of a feature called 'Bitwarden Send'. It should not be translated." }, "uriMatchDetectionPolicy": { - "message": "Default URI match detection" + "message": "Predvolené zisťovanie zhody URI" }, "uriMatchDetectionPolicyDesc": { - "message": "Determine when logins are suggested for autofill. Admins and owners are exempt from this policy." + "message": "Určite kedy budú ponúknuté položky pre automatické vypĺňanie. Správcovia a majitelia majú pre toto pravidlo výnimku." }, "uriMatchDetectionOptionsLabel": { - "message": "Default URI match detection" + "message": "Predvolené zisťovanie zhody URI" }, "invalidUriMatchDefaultPolicySetting": { - "message": "Please select a valid URI match detection option.", + "message": "Prosím vyberte platnú predvoľbu zisťovania zhody URI.", "description": "Error message displayed when a user attempts to save URI match detection policy settings with an invalid selection." }, "modifiedPolicyId": { @@ -9856,8 +9850,8 @@ "assignTasks": { "message": "Priradiť úlohy" }, - "assignTasksToMembers": { - "message": "Pre riadené riešenie problémov prideľte úlohy členom" + "assignSecurityTasksToMembers": { + "message": "Send notifications to change passwords" }, "assignToCollections": { "message": "Prideliť k zbierkam" @@ -12159,9 +12153,9 @@ } }, "confirmNoSelectedCriticalApplicationsTitle": { - "message": "No critical applications are selected" + "message": "Nie sú vybrané žiadne kritické aplikácie" }, "confirmNoSelectedCriticalApplicationsDesc": { - "message": "Are you sure you want to continue?" + "message": "Ste si istí, že chcete pokračovať?" } } diff --git a/apps/web/src/locales/sl/messages.json b/apps/web/src/locales/sl/messages.json index 709baa2e36..2f14c42dd9 100644 --- a/apps/web/src/locales/sl/messages.json +++ b/apps/web/src/locales/sl/messages.json @@ -93,8 +93,8 @@ "assignMembersTasksToMonitorProgress": { "message": "Assign members tasks to monitor progress" }, - "onceYouReviewApps": { - "message": "Once you review applications and mark them as critical, you can assign tasks to members to resolve at-risk items and monitor progress here" + "onceYouReviewApplications": { + "message": "Once you review applications and mark them as critical, assign tasks to your members to change their passwords." }, "sendReminders": { "message": "Send reminders" @@ -178,41 +178,35 @@ } } }, - "noApplicationsInOrgTitle": { - "message": "No applications found for $ORG NAME$", - "placeholders": { - "org name": { - "content": "$1", - "example": "Company Name" - } - } + "noDataInOrgTitle": { + "message": "No data found" }, - "noApplicationsInOrgDescription": { - "message": "Import your organization's login data to start monitoring credential security risks. Once imported you get to:" + "noDataInOrgDescription": { + "message": "Import your organization's login data to get started with Access Intelligence. Once you do that, you'll be able to:" }, - "benefit1Title": { - "message": "Prioritize risks" + "feature1Title": { + "message": "Mark applications as critical" }, - "benefit1Description": { - "message": "Focus on applications that matter the most" + "feature1Description": { + "message": "This will help you remove risks to your most important applications first." }, - "benefit2Title": { - "message": "Guide remediation" + "feature2Title": { + "message": "Help members improve their security" }, - "benefit2Description": { - "message": "Assign at-risk members guided tasks to rotate at-risk credentials" + "feature2Description": { + "message": "Assign at-risk members guided security tasks to update credentials." }, - "benefit3Title": { + "feature3Title": { "message": "Monitor progress" }, - "benefit3Description": { - "message": "Track changes over time to show security improvements" + "feature3Description": { + "message": "Track changes over time to show security improvements." }, - "noReportRunTitle": { - "message": "Run your first report to see applications" + "noReportsRunTitle": { + "message": "Generate report" }, - "noReportRunDescription": { - "message": "Generate a risk insights report to analyze your organization's applications and identify at-risk passwords that need attention. Running your first report will:" + "noReportsRunDescription": { + "message": "You’re ready to start generating reports. Once you generate, you’ll be able to:" }, "noCriticalApplicationsTitle": { "message": "You haven’t marked any applications as critical" @@ -271,14 +265,14 @@ "atRiskMembers": { "message": "At-risk members" }, - "membersWithAccessToAtRiskItemsForCriticalApps": { - "message": "Members with access to at-risk items for critical applications" + "membersWithAccessToAtRiskItemsForCriticalApplications": { + "message": "These members have access to vulnerable items for critical applications." }, "membersWithAtRiskPasswords": { "message": "Members with at-risk passwords" }, - "membersWillReceiveNotification": { - "message": "Members will receive a notification to resolve at-risk logins through the browser extension." + "membersWillReceiveSecurityTask": { + "message": "Members of your organization will be assigned a task to change vulnerable passwords. They’ll receive a notification within their Bitwarden browser extension." }, "membersAtRiskCount": { "message": "$COUNT$ members at-risk", @@ -307,8 +301,8 @@ } } }, - "atRiskMembersDescription": { - "message": "These members are logging into applications with weak, exposed, or reused passwords." + "atRiskMemberDescription": { + "message": "These members are logging into critical applications with weak, exposed, or reused passwords." }, "atRiskMembersDescriptionNone": { "message": "These are no members logging into applications with weak, exposed, or reused passwords." @@ -391,14 +385,14 @@ "prioritizeCriticalApplications": { "message": "Prioritize critical applications" }, - "selectCriticalApplicationsDescription": { - "message": "Select which applications are most critical to your organization, then assign security tasks to members to resolve risks." + "selectCriticalAppsDescription": { + "message": "Select which applications are most critical to your organization. Then, you’ll be able to assign security tasks to members to remove risks." }, "reviewNewApplications": { "message": "Review new applications" }, - "reviewNewApplicationsDescription": { - "message": "We've highlighted at-risk items for new applications stored in Admin console that have weak, exposed, or reused passwords." + "reviewNewAppsDescription": { + "message": "Review new applications with vulnerable items and mark those you’d like to monitor closely as critical. Then, you’ll be able to assign security tasks to members to remove risks." }, "clickIconToMarkAppAsCritical": { "message": "Click the star icon to mark an app as critical" @@ -9856,8 +9850,8 @@ "assignTasks": { "message": "Assign tasks" }, - "assignTasksToMembers": { - "message": "Assign tasks to members for guided resolution" + "assignSecurityTasksToMembers": { + "message": "Send notifications to change passwords" }, "assignToCollections": { "message": "Assign to collections" diff --git a/apps/web/src/locales/sr_CS/messages.json b/apps/web/src/locales/sr_CS/messages.json index 876669827c..6201f3a7e4 100644 --- a/apps/web/src/locales/sr_CS/messages.json +++ b/apps/web/src/locales/sr_CS/messages.json @@ -93,8 +93,8 @@ "assignMembersTasksToMonitorProgress": { "message": "Assign members tasks to monitor progress" }, - "onceYouReviewApps": { - "message": "Once you review applications and mark them as critical, you can assign tasks to members to resolve at-risk items and monitor progress here" + "onceYouReviewApplications": { + "message": "Once you review applications and mark them as critical, assign tasks to your members to change their passwords." }, "sendReminders": { "message": "Send reminders" @@ -178,41 +178,35 @@ } } }, - "noApplicationsInOrgTitle": { - "message": "No applications found for $ORG NAME$", - "placeholders": { - "org name": { - "content": "$1", - "example": "Company Name" - } - } + "noDataInOrgTitle": { + "message": "No data found" }, - "noApplicationsInOrgDescription": { - "message": "Import your organization's login data to start monitoring credential security risks. Once imported you get to:" + "noDataInOrgDescription": { + "message": "Import your organization's login data to get started with Access Intelligence. Once you do that, you'll be able to:" }, - "benefit1Title": { - "message": "Prioritize risks" + "feature1Title": { + "message": "Mark applications as critical" }, - "benefit1Description": { - "message": "Focus on applications that matter the most" + "feature1Description": { + "message": "This will help you remove risks to your most important applications first." }, - "benefit2Title": { - "message": "Guide remediation" + "feature2Title": { + "message": "Help members improve their security" }, - "benefit2Description": { - "message": "Assign at-risk members guided tasks to rotate at-risk credentials" + "feature2Description": { + "message": "Assign at-risk members guided security tasks to update credentials." }, - "benefit3Title": { + "feature3Title": { "message": "Monitor progress" }, - "benefit3Description": { - "message": "Track changes over time to show security improvements" + "feature3Description": { + "message": "Track changes over time to show security improvements." }, - "noReportRunTitle": { - "message": "Run your first report to see applications" + "noReportsRunTitle": { + "message": "Generate report" }, - "noReportRunDescription": { - "message": "Generate a risk insights report to analyze your organization's applications and identify at-risk passwords that need attention. Running your first report will:" + "noReportsRunDescription": { + "message": "You’re ready to start generating reports. Once you generate, you’ll be able to:" }, "noCriticalApplicationsTitle": { "message": "You haven’t marked any applications as critical" @@ -271,14 +265,14 @@ "atRiskMembers": { "message": "At-risk members" }, - "membersWithAccessToAtRiskItemsForCriticalApps": { - "message": "Members with access to at-risk items for critical applications" + "membersWithAccessToAtRiskItemsForCriticalApplications": { + "message": "These members have access to vulnerable items for critical applications." }, "membersWithAtRiskPasswords": { "message": "Members with at-risk passwords" }, - "membersWillReceiveNotification": { - "message": "Members will receive a notification to resolve at-risk logins through the browser extension." + "membersWillReceiveSecurityTask": { + "message": "Members of your organization will be assigned a task to change vulnerable passwords. They’ll receive a notification within their Bitwarden browser extension." }, "membersAtRiskCount": { "message": "$COUNT$ members at-risk", @@ -307,8 +301,8 @@ } } }, - "atRiskMembersDescription": { - "message": "These members are logging into applications with weak, exposed, or reused passwords." + "atRiskMemberDescription": { + "message": "These members are logging into critical applications with weak, exposed, or reused passwords." }, "atRiskMembersDescriptionNone": { "message": "These are no members logging into applications with weak, exposed, or reused passwords." @@ -391,14 +385,14 @@ "prioritizeCriticalApplications": { "message": "Prioritize critical applications" }, - "selectCriticalApplicationsDescription": { - "message": "Select which applications are most critical to your organization, then assign security tasks to members to resolve risks." + "selectCriticalAppsDescription": { + "message": "Select which applications are most critical to your organization. Then, you’ll be able to assign security tasks to members to remove risks." }, "reviewNewApplications": { "message": "Review new applications" }, - "reviewNewApplicationsDescription": { - "message": "We've highlighted at-risk items for new applications stored in Admin console that have weak, exposed, or reused passwords." + "reviewNewAppsDescription": { + "message": "Review new applications with vulnerable items and mark those you’d like to monitor closely as critical. Then, you’ll be able to assign security tasks to members to remove risks." }, "clickIconToMarkAppAsCritical": { "message": "Click the star icon to mark an app as critical" @@ -9856,8 +9850,8 @@ "assignTasks": { "message": "Assign tasks" }, - "assignTasksToMembers": { - "message": "Assign tasks to members for guided resolution" + "assignSecurityTasksToMembers": { + "message": "Send notifications to change passwords" }, "assignToCollections": { "message": "Assign to collections" diff --git a/apps/web/src/locales/sr_CY/messages.json b/apps/web/src/locales/sr_CY/messages.json index dd41032a03..1d0ae7b089 100644 --- a/apps/web/src/locales/sr_CY/messages.json +++ b/apps/web/src/locales/sr_CY/messages.json @@ -93,8 +93,8 @@ "assignMembersTasksToMonitorProgress": { "message": "Доделите задатке чланова да прате напредак" }, - "onceYouReviewApps": { - "message": "Када прегледате апликације и означите их као критичне, можете доделити задатке члановима за решавање ризичних ставки и пратити напредак овде" + "onceYouReviewApplications": { + "message": "Once you review applications and mark them as critical, assign tasks to your members to change their passwords." }, "sendReminders": { "message": "Пошаљи подсетнике" @@ -178,41 +178,35 @@ } } }, - "noApplicationsInOrgTitle": { - "message": "Није пронађена ниједна апликација за $ORG NAME$", - "placeholders": { - "org name": { - "content": "$1", - "example": "Company Name" - } - } + "noDataInOrgTitle": { + "message": "No data found" }, - "noApplicationsInOrgDescription": { - "message": "Увезите податке за пријаву своје организације да бисте почели да надгледате безбедносне ризике акредитива. Када увезете, добијате:" + "noDataInOrgDescription": { + "message": "Import your organization's login data to get started with Access Intelligence. Once you do that, you'll be able to:" }, - "benefit1Title": { - "message": "Одредите приоритете ризика" + "feature1Title": { + "message": "Mark applications as critical" }, - "benefit1Description": { - "message": "Фокусирајте се на апликације које су најважније" + "feature1Description": { + "message": "This will help you remove risks to your most important applications first." }, - "benefit2Title": { - "message": "Водич за санацију" + "feature2Title": { + "message": "Help members improve their security" }, - "benefit2Description": { - "message": "Доделите вођене задатке члановима изложеним ризику да ротирају акредитиве у ризику" + "feature2Description": { + "message": "Assign at-risk members guided security tasks to update credentials." }, - "benefit3Title": { - "message": "Праћење напретка" + "feature3Title": { + "message": "Monitor progress" }, - "benefit3Description": { - "message": "Пратите промене током времена да бисте показали безбедносна побољшања" + "feature3Description": { + "message": "Track changes over time to show security improvements." }, - "noReportRunTitle": { - "message": "Покрените свој први извештај да бисте видели апликације" + "noReportsRunTitle": { + "message": "Generate report" }, - "noReportRunDescription": { - "message": "Направите извештај о увиду у ризик да бисте анализирали апликације ваше организације и идентификовали ризичне лозинке на које треба обратити пажњу. Покретање вашег првог извештаја ће:" + "noReportsRunDescription": { + "message": "You’re ready to start generating reports. Once you generate, you’ll be able to:" }, "noCriticalApplicationsTitle": { "message": "Нисте означили ниједну апликацију као критичну" @@ -271,14 +265,14 @@ "atRiskMembers": { "message": "Чланови под ризиком" }, - "membersWithAccessToAtRiskItemsForCriticalApps": { - "message": "Чланови са приступом за угрожене ставке критичних апликација" + "membersWithAccessToAtRiskItemsForCriticalApplications": { + "message": "These members have access to vulnerable items for critical applications." }, "membersWithAtRiskPasswords": { "message": "Чланови са ризичним лозинкама" }, - "membersWillReceiveNotification": { - "message": "Чланови ће добити обавештење за решавање ризичних пријава путем екстензије претраживача." + "membersWillReceiveSecurityTask": { + "message": "Members of your organization will be assigned a task to change vulnerable passwords. They’ll receive a notification within their Bitwarden browser extension." }, "membersAtRiskCount": { "message": "Угрожени чланови: $COUNT$", @@ -307,8 +301,8 @@ } } }, - "atRiskMembersDescription": { - "message": "Ови чланови се пријављују у апликације са слабим, откривеним или поново коришћеним лозинкама." + "atRiskMemberDescription": { + "message": "These members are logging into critical applications with weak, exposed, or reused passwords." }, "atRiskMembersDescriptionNone": { "message": "Нема чланова пријављена у апликације са слабим, откривеним или поново коришћеним лозинкама." @@ -391,14 +385,14 @@ "prioritizeCriticalApplications": { "message": "Дајте приоритет критичним апликацијама" }, - "selectCriticalApplicationsDescription": { - "message": "Изаберите које су апликације најкритичније за вашу организацију, а затим доделите безбедносне задатке члановима да бисте решили ризике." + "selectCriticalAppsDescription": { + "message": "Select which applications are most critical to your organization. Then, you’ll be able to assign security tasks to members to remove risks." }, "reviewNewApplications": { "message": "Прегледајте нове апликације" }, - "reviewNewApplicationsDescription": { - "message": "Истакли смо ризичне ставке за нове апликације ускладиштене у Админ конзоли које имају слабе, откривене или поново коришћене лозинке." + "reviewNewAppsDescription": { + "message": "Review new applications with vulnerable items and mark those you’d like to monitor closely as critical. Then, you’ll be able to assign security tasks to members to remove risks." }, "clickIconToMarkAppAsCritical": { "message": "Кликните на икону звездице да бисте означили апликацију као критичну" @@ -9856,8 +9850,8 @@ "assignTasks": { "message": "Додели задатке" }, - "assignTasksToMembers": { - "message": "Доделите задатке члановима за вођено решавање" + "assignSecurityTasksToMembers": { + "message": "Send notifications to change passwords" }, "assignToCollections": { "message": "Додели колекцијама" diff --git a/apps/web/src/locales/sv/messages.json b/apps/web/src/locales/sv/messages.json index ca0547d7d9..3ebe049942 100644 --- a/apps/web/src/locales/sv/messages.json +++ b/apps/web/src/locales/sv/messages.json @@ -93,8 +93,8 @@ "assignMembersTasksToMonitorProgress": { "message": "Tilldela medlemmar uppgifter för att övervaka framsteg" }, - "onceYouReviewApps": { - "message": "När du har granskat applikationer och markerat dem som kritiska kan du tilldela uppgifter till medlemmar för att åtgärda riskutsatta objekt och övervaka framsteg här" + "onceYouReviewApplications": { + "message": "Once you review applications and mark them as critical, assign tasks to your members to change their passwords." }, "sendReminders": { "message": "Skicka påminnelser" @@ -178,41 +178,35 @@ } } }, - "noApplicationsInOrgTitle": { - "message": "Inga applikationer hittades för $ORG NAME$", - "placeholders": { - "org name": { - "content": "$1", - "example": "Company Name" - } - } + "noDataInOrgTitle": { + "message": "Ingen data hittades" }, - "noApplicationsInOrgDescription": { - "message": "Importera din organisations inloggningsdata för att börja övervaka säkerhetsrisker för autentiseringsuppgifter. När de har importerats kan du:" + "noDataInOrgDescription": { + "message": "Import your organization's login data to get started with Access Intelligence. Once you do that, you'll be able to:" }, - "benefit1Title": { - "message": "Prioritera risker" + "feature1Title": { + "message": "Markera applikationer som kritiska" }, - "benefit1Description": { - "message": "Fokusera på applikationer som betyder mest" + "feature1Description": { + "message": "This will help you remove risks to your most important applications first." }, - "benefit2Title": { - "message": "Guide åtgärder" + "feature2Title": { + "message": "Hjälp medlemmar att förbättra sin säkerhet" }, - "benefit2Description": { - "message": "Tilldela riskutsatta medlemmar vägledda uppgifter för att byta ut riskutsatta autentiseringsuppgifter" + "feature2Description": { + "message": "Assign at-risk members guided security tasks to update credentials." }, - "benefit3Title": { + "feature3Title": { "message": "Övervaka framsteg" }, - "benefit3Description": { - "message": "Spåra förändringar över tid för att visa säkerhetsförbättringar" + "feature3Description": { + "message": "Track changes over time to show security improvements." }, - "noReportRunTitle": { - "message": "Kör din första rapport för att se applikationer" + "noReportsRunTitle": { + "message": "Generera rapport" }, - "noReportRunDescription": { - "message": "Generate a risk insights report to analyze your organization's applications and identify at-risk passwords that need attention. Running your first report will:" + "noReportsRunDescription": { + "message": "You’re ready to start generating reports. Once you generate, you’ll be able to:" }, "noCriticalApplicationsTitle": { "message": "Du har inte markerat några applikationer som kritiska" @@ -271,14 +265,14 @@ "atRiskMembers": { "message": "Riskutsatta medlemmar" }, - "membersWithAccessToAtRiskItemsForCriticalApps": { - "message": "Members with access to at-risk items for critical applications" + "membersWithAccessToAtRiskItemsForCriticalApplications": { + "message": "These members have access to vulnerable items for critical applications." }, "membersWithAtRiskPasswords": { "message": "Members with at-risk passwords" }, - "membersWillReceiveNotification": { - "message": "Members will receive a notification to resolve at-risk logins through the browser extension." + "membersWillReceiveSecurityTask": { + "message": "Members of your organization will be assigned a task to change vulnerable passwords. They’ll receive a notification within their Bitwarden browser extension." }, "membersAtRiskCount": { "message": "$COUNT$ medlemmar i riskzonen", @@ -307,8 +301,8 @@ } } }, - "atRiskMembersDescription": { - "message": "Dessa medlemmar loggar in i applikationer med svaga, exponerade eller återanvända lösenord." + "atRiskMemberDescription": { + "message": "These members are logging into critical applications with weak, exposed, or reused passwords." }, "atRiskMembersDescriptionNone": { "message": "Det finns inga medlemmar som loggar in i applikationer med svaga, exponerade eller återanvända lösenord." @@ -386,19 +380,19 @@ "message": "Review applications to secure the items most critical to your organization's security" }, "reviewApplications": { - "message": "Review applications" + "message": "Granska applikationer" }, "prioritizeCriticalApplications": { "message": "Prioritera kritiska applikationer" }, - "selectCriticalApplicationsDescription": { - "message": "Select which applications are most critical to your organization, then assign security tasks to members to resolve risks." + "selectCriticalAppsDescription": { + "message": "Select which applications are most critical to your organization. Then, you’ll be able to assign security tasks to members to remove risks." }, "reviewNewApplications": { "message": "Granska nya applikationer" }, - "reviewNewApplicationsDescription": { - "message": "Vi har markerat objekt i riskzonen för nya applikationer som lagras i administratörskonsolen och som har svaga, exponerade eller återanvända lösenord." + "reviewNewAppsDescription": { + "message": "Review new applications with vulnerable items and mark those you’d like to monitor closely as critical. Then, you’ll be able to assign security tasks to members to remove risks." }, "clickIconToMarkAppAsCritical": { "message": "Click the star icon to mark an app as critical" @@ -3251,7 +3245,7 @@ "message": "Nästa debitering" }, "nextChargeHeader": { - "message": "Next Charge" + "message": "Nästa betalning" }, "plan": { "message": "Plan" @@ -3260,7 +3254,7 @@ "message": "Detaljer" }, "discount": { - "message": "discount" + "message": "rabatt" }, "downloadLicense": { "message": "Hämta licens" @@ -9856,8 +9850,8 @@ "assignTasks": { "message": "Tilldela uppgifter" }, - "assignTasksToMembers": { - "message": "Assign tasks to members for guided resolution" + "assignSecurityTasksToMembers": { + "message": "Skicka aviseringar om att ändra lösenord" }, "assignToCollections": { "message": "Tilldela till samlingar" @@ -12162,6 +12156,6 @@ "message": "No critical applications are selected" }, "confirmNoSelectedCriticalApplicationsDesc": { - "message": "Are you sure you want to continue?" + "message": "Är du säker på att du vill fortsätta?" } } diff --git a/apps/web/src/locales/ta/messages.json b/apps/web/src/locales/ta/messages.json index bea4f3365b..64ce03adb1 100644 --- a/apps/web/src/locales/ta/messages.json +++ b/apps/web/src/locales/ta/messages.json @@ -93,8 +93,8 @@ "assignMembersTasksToMonitorProgress": { "message": "Assign members tasks to monitor progress" }, - "onceYouReviewApps": { - "message": "Once you review applications and mark them as critical, you can assign tasks to members to resolve at-risk items and monitor progress here" + "onceYouReviewApplications": { + "message": "Once you review applications and mark them as critical, assign tasks to your members to change their passwords." }, "sendReminders": { "message": "Send reminders" @@ -178,41 +178,35 @@ } } }, - "noApplicationsInOrgTitle": { - "message": "No applications found for $ORG NAME$", - "placeholders": { - "org name": { - "content": "$1", - "example": "Company Name" - } - } + "noDataInOrgTitle": { + "message": "No data found" }, - "noApplicationsInOrgDescription": { - "message": "Import your organization's login data to start monitoring credential security risks. Once imported you get to:" + "noDataInOrgDescription": { + "message": "Import your organization's login data to get started with Access Intelligence. Once you do that, you'll be able to:" }, - "benefit1Title": { - "message": "Prioritize risks" + "feature1Title": { + "message": "Mark applications as critical" }, - "benefit1Description": { - "message": "Focus on applications that matter the most" + "feature1Description": { + "message": "This will help you remove risks to your most important applications first." }, - "benefit2Title": { - "message": "Guide remediation" + "feature2Title": { + "message": "Help members improve their security" }, - "benefit2Description": { - "message": "Assign at-risk members guided tasks to rotate at-risk credentials" + "feature2Description": { + "message": "Assign at-risk members guided security tasks to update credentials." }, - "benefit3Title": { + "feature3Title": { "message": "Monitor progress" }, - "benefit3Description": { - "message": "Track changes over time to show security improvements" + "feature3Description": { + "message": "Track changes over time to show security improvements." }, - "noReportRunTitle": { - "message": "Run your first report to see applications" + "noReportsRunTitle": { + "message": "Generate report" }, - "noReportRunDescription": { - "message": "Generate a risk insights report to analyze your organization's applications and identify at-risk passwords that need attention. Running your first report will:" + "noReportsRunDescription": { + "message": "You’re ready to start generating reports. Once you generate, you’ll be able to:" }, "noCriticalApplicationsTitle": { "message": "You haven’t marked any applications as critical" @@ -271,14 +265,14 @@ "atRiskMembers": { "message": "ஆபத்தில் உள்ள உறுப்பினர்கள்" }, - "membersWithAccessToAtRiskItemsForCriticalApps": { - "message": "Members with access to at-risk items for critical applications" + "membersWithAccessToAtRiskItemsForCriticalApplications": { + "message": "These members have access to vulnerable items for critical applications." }, "membersWithAtRiskPasswords": { "message": "Members with at-risk passwords" }, - "membersWillReceiveNotification": { - "message": "Members will receive a notification to resolve at-risk logins through the browser extension." + "membersWillReceiveSecurityTask": { + "message": "Members of your organization will be assigned a task to change vulnerable passwords. They’ll receive a notification within their Bitwarden browser extension." }, "membersAtRiskCount": { "message": "$COUNT$ members at-risk", @@ -307,8 +301,8 @@ } } }, - "atRiskMembersDescription": { - "message": "இந்த உறுப்பினர்கள் பலவீனமான, அம்பலப்படுத்தப்பட்ட அல்லது மீண்டும் பயன்படுத்தப்பட்ட கடவுச்சொற்களுடன் பயன்பாடுகளில் உள்நுழைகிறார்கள்." + "atRiskMemberDescription": { + "message": "These members are logging into critical applications with weak, exposed, or reused passwords." }, "atRiskMembersDescriptionNone": { "message": "பலவீனமான, அம்பலப்படுத்தப்பட்ட அல்லது மீண்டும் பயன்படுத்தப்பட்ட கடவுச்சொற்களுடன் பயன்பாடுகளில் உள்நுழையும் உறுப்பினர்கள் யாரும் இல்லை." @@ -391,14 +385,14 @@ "prioritizeCriticalApplications": { "message": "Prioritize critical applications" }, - "selectCriticalApplicationsDescription": { - "message": "Select which applications are most critical to your organization, then assign security tasks to members to resolve risks." + "selectCriticalAppsDescription": { + "message": "Select which applications are most critical to your organization. Then, you’ll be able to assign security tasks to members to remove risks." }, "reviewNewApplications": { "message": "Review new applications" }, - "reviewNewApplicationsDescription": { - "message": "We've highlighted at-risk items for new applications stored in Admin console that have weak, exposed, or reused passwords." + "reviewNewAppsDescription": { + "message": "Review new applications with vulnerable items and mark those you’d like to monitor closely as critical. Then, you’ll be able to assign security tasks to members to remove risks." }, "clickIconToMarkAppAsCritical": { "message": "Click the star icon to mark an app as critical" @@ -9856,8 +9850,8 @@ "assignTasks": { "message": "Assign tasks" }, - "assignTasksToMembers": { - "message": "Assign tasks to members for guided resolution" + "assignSecurityTasksToMembers": { + "message": "Send notifications to change passwords" }, "assignToCollections": { "message": "சேகரிப்புகளுக்கு ஒதுக்கு" diff --git a/apps/web/src/locales/te/messages.json b/apps/web/src/locales/te/messages.json index 47df482685..9f57ed8c6c 100644 --- a/apps/web/src/locales/te/messages.json +++ b/apps/web/src/locales/te/messages.json @@ -93,8 +93,8 @@ "assignMembersTasksToMonitorProgress": { "message": "Assign members tasks to monitor progress" }, - "onceYouReviewApps": { - "message": "Once you review applications and mark them as critical, you can assign tasks to members to resolve at-risk items and monitor progress here" + "onceYouReviewApplications": { + "message": "Once you review applications and mark them as critical, assign tasks to your members to change their passwords." }, "sendReminders": { "message": "Send reminders" @@ -178,41 +178,35 @@ } } }, - "noApplicationsInOrgTitle": { - "message": "No applications found for $ORG NAME$", - "placeholders": { - "org name": { - "content": "$1", - "example": "Company Name" - } - } + "noDataInOrgTitle": { + "message": "No data found" }, - "noApplicationsInOrgDescription": { - "message": "Import your organization's login data to start monitoring credential security risks. Once imported you get to:" + "noDataInOrgDescription": { + "message": "Import your organization's login data to get started with Access Intelligence. Once you do that, you'll be able to:" }, - "benefit1Title": { - "message": "Prioritize risks" + "feature1Title": { + "message": "Mark applications as critical" }, - "benefit1Description": { - "message": "Focus on applications that matter the most" + "feature1Description": { + "message": "This will help you remove risks to your most important applications first." }, - "benefit2Title": { - "message": "Guide remediation" + "feature2Title": { + "message": "Help members improve their security" }, - "benefit2Description": { - "message": "Assign at-risk members guided tasks to rotate at-risk credentials" + "feature2Description": { + "message": "Assign at-risk members guided security tasks to update credentials." }, - "benefit3Title": { + "feature3Title": { "message": "Monitor progress" }, - "benefit3Description": { - "message": "Track changes over time to show security improvements" + "feature3Description": { + "message": "Track changes over time to show security improvements." }, - "noReportRunTitle": { - "message": "Run your first report to see applications" + "noReportsRunTitle": { + "message": "Generate report" }, - "noReportRunDescription": { - "message": "Generate a risk insights report to analyze your organization's applications and identify at-risk passwords that need attention. Running your first report will:" + "noReportsRunDescription": { + "message": "You’re ready to start generating reports. Once you generate, you’ll be able to:" }, "noCriticalApplicationsTitle": { "message": "You haven’t marked any applications as critical" @@ -271,14 +265,14 @@ "atRiskMembers": { "message": "At-risk members" }, - "membersWithAccessToAtRiskItemsForCriticalApps": { - "message": "Members with access to at-risk items for critical applications" + "membersWithAccessToAtRiskItemsForCriticalApplications": { + "message": "These members have access to vulnerable items for critical applications." }, "membersWithAtRiskPasswords": { "message": "Members with at-risk passwords" }, - "membersWillReceiveNotification": { - "message": "Members will receive a notification to resolve at-risk logins through the browser extension." + "membersWillReceiveSecurityTask": { + "message": "Members of your organization will be assigned a task to change vulnerable passwords. They’ll receive a notification within their Bitwarden browser extension." }, "membersAtRiskCount": { "message": "$COUNT$ members at-risk", @@ -307,8 +301,8 @@ } } }, - "atRiskMembersDescription": { - "message": "These members are logging into applications with weak, exposed, or reused passwords." + "atRiskMemberDescription": { + "message": "These members are logging into critical applications with weak, exposed, or reused passwords." }, "atRiskMembersDescriptionNone": { "message": "These are no members logging into applications with weak, exposed, or reused passwords." @@ -391,14 +385,14 @@ "prioritizeCriticalApplications": { "message": "Prioritize critical applications" }, - "selectCriticalApplicationsDescription": { - "message": "Select which applications are most critical to your organization, then assign security tasks to members to resolve risks." + "selectCriticalAppsDescription": { + "message": "Select which applications are most critical to your organization. Then, you’ll be able to assign security tasks to members to remove risks." }, "reviewNewApplications": { "message": "Review new applications" }, - "reviewNewApplicationsDescription": { - "message": "We've highlighted at-risk items for new applications stored in Admin console that have weak, exposed, or reused passwords." + "reviewNewAppsDescription": { + "message": "Review new applications with vulnerable items and mark those you’d like to monitor closely as critical. Then, you’ll be able to assign security tasks to members to remove risks." }, "clickIconToMarkAppAsCritical": { "message": "Click the star icon to mark an app as critical" @@ -9856,8 +9850,8 @@ "assignTasks": { "message": "Assign tasks" }, - "assignTasksToMembers": { - "message": "Assign tasks to members for guided resolution" + "assignSecurityTasksToMembers": { + "message": "Send notifications to change passwords" }, "assignToCollections": { "message": "Assign to collections" diff --git a/apps/web/src/locales/th/messages.json b/apps/web/src/locales/th/messages.json index 3e4797eb03..30a75f4d4d 100644 --- a/apps/web/src/locales/th/messages.json +++ b/apps/web/src/locales/th/messages.json @@ -93,8 +93,8 @@ "assignMembersTasksToMonitorProgress": { "message": "Assign members tasks to monitor progress" }, - "onceYouReviewApps": { - "message": "Once you review applications and mark them as critical, you can assign tasks to members to resolve at-risk items and monitor progress here" + "onceYouReviewApplications": { + "message": "Once you review applications and mark them as critical, assign tasks to your members to change their passwords." }, "sendReminders": { "message": "Send reminders" @@ -178,41 +178,35 @@ } } }, - "noApplicationsInOrgTitle": { - "message": "No applications found for $ORG NAME$", - "placeholders": { - "org name": { - "content": "$1", - "example": "Company Name" - } - } + "noDataInOrgTitle": { + "message": "No data found" }, - "noApplicationsInOrgDescription": { - "message": "Import your organization's login data to start monitoring credential security risks. Once imported you get to:" + "noDataInOrgDescription": { + "message": "Import your organization's login data to get started with Access Intelligence. Once you do that, you'll be able to:" }, - "benefit1Title": { - "message": "Prioritize risks" + "feature1Title": { + "message": "Mark applications as critical" }, - "benefit1Description": { - "message": "Focus on applications that matter the most" + "feature1Description": { + "message": "This will help you remove risks to your most important applications first." }, - "benefit2Title": { - "message": "Guide remediation" + "feature2Title": { + "message": "Help members improve their security" }, - "benefit2Description": { - "message": "Assign at-risk members guided tasks to rotate at-risk credentials" + "feature2Description": { + "message": "Assign at-risk members guided security tasks to update credentials." }, - "benefit3Title": { + "feature3Title": { "message": "Monitor progress" }, - "benefit3Description": { - "message": "Track changes over time to show security improvements" + "feature3Description": { + "message": "Track changes over time to show security improvements." }, - "noReportRunTitle": { - "message": "Run your first report to see applications" + "noReportsRunTitle": { + "message": "Generate report" }, - "noReportRunDescription": { - "message": "Generate a risk insights report to analyze your organization's applications and identify at-risk passwords that need attention. Running your first report will:" + "noReportsRunDescription": { + "message": "You’re ready to start generating reports. Once you generate, you’ll be able to:" }, "noCriticalApplicationsTitle": { "message": "You haven’t marked any applications as critical" @@ -271,14 +265,14 @@ "atRiskMembers": { "message": "At-risk members" }, - "membersWithAccessToAtRiskItemsForCriticalApps": { - "message": "Members with access to at-risk items for critical applications" + "membersWithAccessToAtRiskItemsForCriticalApplications": { + "message": "These members have access to vulnerable items for critical applications." }, "membersWithAtRiskPasswords": { "message": "Members with at-risk passwords" }, - "membersWillReceiveNotification": { - "message": "Members will receive a notification to resolve at-risk logins through the browser extension." + "membersWillReceiveSecurityTask": { + "message": "Members of your organization will be assigned a task to change vulnerable passwords. They’ll receive a notification within their Bitwarden browser extension." }, "membersAtRiskCount": { "message": "$COUNT$ members at-risk", @@ -307,8 +301,8 @@ } } }, - "atRiskMembersDescription": { - "message": "These members are logging into applications with weak, exposed, or reused passwords." + "atRiskMemberDescription": { + "message": "These members are logging into critical applications with weak, exposed, or reused passwords." }, "atRiskMembersDescriptionNone": { "message": "These are no members logging into applications with weak, exposed, or reused passwords." @@ -391,14 +385,14 @@ "prioritizeCriticalApplications": { "message": "Prioritize critical applications" }, - "selectCriticalApplicationsDescription": { - "message": "Select which applications are most critical to your organization, then assign security tasks to members to resolve risks." + "selectCriticalAppsDescription": { + "message": "Select which applications are most critical to your organization. Then, you’ll be able to assign security tasks to members to remove risks." }, "reviewNewApplications": { "message": "Review new applications" }, - "reviewNewApplicationsDescription": { - "message": "We've highlighted at-risk items for new applications stored in Admin console that have weak, exposed, or reused passwords." + "reviewNewAppsDescription": { + "message": "Review new applications with vulnerable items and mark those you’d like to monitor closely as critical. Then, you’ll be able to assign security tasks to members to remove risks." }, "clickIconToMarkAppAsCritical": { "message": "Click the star icon to mark an app as critical" @@ -9856,8 +9850,8 @@ "assignTasks": { "message": "Assign tasks" }, - "assignTasksToMembers": { - "message": "Assign tasks to members for guided resolution" + "assignSecurityTasksToMembers": { + "message": "Send notifications to change passwords" }, "assignToCollections": { "message": "Assign to collections" diff --git a/apps/web/src/locales/tr/messages.json b/apps/web/src/locales/tr/messages.json index bb52d98e1e..448172f3c4 100644 --- a/apps/web/src/locales/tr/messages.json +++ b/apps/web/src/locales/tr/messages.json @@ -93,8 +93,8 @@ "assignMembersTasksToMonitorProgress": { "message": "Assign members tasks to monitor progress" }, - "onceYouReviewApps": { - "message": "Once you review applications and mark them as critical, you can assign tasks to members to resolve at-risk items and monitor progress here" + "onceYouReviewApplications": { + "message": "Once you review applications and mark them as critical, assign tasks to your members to change their passwords." }, "sendReminders": { "message": "Send reminders" @@ -178,41 +178,35 @@ } } }, - "noApplicationsInOrgTitle": { - "message": "$ORG NAME$ kuruluşu için hiçbir uygulama bulunmadı", - "placeholders": { - "org name": { - "content": "$1", - "example": "Company Name" - } - } + "noDataInOrgTitle": { + "message": "No data found" }, - "noApplicationsInOrgDescription": { - "message": "Import your organization's login data to start monitoring credential security risks. Once imported you get to:" + "noDataInOrgDescription": { + "message": "Import your organization's login data to get started with Access Intelligence. Once you do that, you'll be able to:" }, - "benefit1Title": { - "message": "Prioritize risks" + "feature1Title": { + "message": "Mark applications as critical" }, - "benefit1Description": { - "message": "Focus on applications that matter the most" + "feature1Description": { + "message": "This will help you remove risks to your most important applications first." }, - "benefit2Title": { - "message": "Guide remediation" + "feature2Title": { + "message": "Help members improve their security" }, - "benefit2Description": { - "message": "Assign at-risk members guided tasks to rotate at-risk credentials" + "feature2Description": { + "message": "Assign at-risk members guided security tasks to update credentials." }, - "benefit3Title": { + "feature3Title": { "message": "Monitor progress" }, - "benefit3Description": { - "message": "Track changes over time to show security improvements" + "feature3Description": { + "message": "Track changes over time to show security improvements." }, - "noReportRunTitle": { - "message": "Run your first report to see applications" + "noReportsRunTitle": { + "message": "Generate report" }, - "noReportRunDescription": { - "message": "Generate a risk insights report to analyze your organization's applications and identify at-risk passwords that need attention. Running your first report will:" + "noReportsRunDescription": { + "message": "You’re ready to start generating reports. Once you generate, you’ll be able to:" }, "noCriticalApplicationsTitle": { "message": "Hiçbir uygulamayı kritik olarak işaretlemediniz" @@ -271,14 +265,14 @@ "atRiskMembers": { "message": "Riskli üyeler" }, - "membersWithAccessToAtRiskItemsForCriticalApps": { - "message": "Kritik uygulamalar için risk altındaki kayıtlara erişimi olan üyeler" + "membersWithAccessToAtRiskItemsForCriticalApplications": { + "message": "These members have access to vulnerable items for critical applications." }, "membersWithAtRiskPasswords": { "message": "Members with at-risk passwords" }, - "membersWillReceiveNotification": { - "message": "Members will receive a notification to resolve at-risk logins through the browser extension." + "membersWillReceiveSecurityTask": { + "message": "Members of your organization will be assigned a task to change vulnerable passwords. They’ll receive a notification within their Bitwarden browser extension." }, "membersAtRiskCount": { "message": "$COUNT$ üye risk altında", @@ -307,8 +301,8 @@ } } }, - "atRiskMembersDescription": { - "message": "Bu üyeler uygulamalara zayıf, ele geçirilmiş veya tekrar kullanılan parolalarla giriş yapmaktadır." + "atRiskMemberDescription": { + "message": "These members are logging into critical applications with weak, exposed, or reused passwords." }, "atRiskMembersDescriptionNone": { "message": "Zayıf, ele geçirilmiş veya tekrar kullanılan parolayla uygulamalara giriş yapan üye yok." @@ -391,14 +385,14 @@ "prioritizeCriticalApplications": { "message": "Prioritize critical applications" }, - "selectCriticalApplicationsDescription": { - "message": "Select which applications are most critical to your organization, then assign security tasks to members to resolve risks." + "selectCriticalAppsDescription": { + "message": "Select which applications are most critical to your organization. Then, you’ll be able to assign security tasks to members to remove risks." }, "reviewNewApplications": { "message": "Review new applications" }, - "reviewNewApplicationsDescription": { - "message": "We've highlighted at-risk items for new applications stored in Admin console that have weak, exposed, or reused passwords." + "reviewNewAppsDescription": { + "message": "Review new applications with vulnerable items and mark those you’d like to monitor closely as critical. Then, you’ll be able to assign security tasks to members to remove risks." }, "clickIconToMarkAppAsCritical": { "message": "Click the star icon to mark an app as critical" @@ -9856,8 +9850,8 @@ "assignTasks": { "message": "Assign tasks" }, - "assignTasksToMembers": { - "message": "Assign tasks to members for guided resolution" + "assignSecurityTasksToMembers": { + "message": "Send notifications to change passwords" }, "assignToCollections": { "message": "Koleksiyonlara ata" @@ -12162,6 +12156,6 @@ "message": "No critical applications are selected" }, "confirmNoSelectedCriticalApplicationsDesc": { - "message": "Are you sure you want to continue?" + "message": "Devam etmek istediğinizden emin misiniz?" } } diff --git a/apps/web/src/locales/uk/messages.json b/apps/web/src/locales/uk/messages.json index 6fa971b98a..f1f7d6530b 100644 --- a/apps/web/src/locales/uk/messages.json +++ b/apps/web/src/locales/uk/messages.json @@ -93,8 +93,8 @@ "assignMembersTasksToMonitorProgress": { "message": "Assign members tasks to monitor progress" }, - "onceYouReviewApps": { - "message": "Once you review applications and mark them as critical, you can assign tasks to members to resolve at-risk items and monitor progress here" + "onceYouReviewApplications": { + "message": "Once you review applications and mark them as critical, assign tasks to your members to change their passwords." }, "sendReminders": { "message": "Send reminders" @@ -178,41 +178,35 @@ } } }, - "noApplicationsInOrgTitle": { - "message": "No applications found for $ORG NAME$", - "placeholders": { - "org name": { - "content": "$1", - "example": "Company Name" - } - } + "noDataInOrgTitle": { + "message": "No data found" }, - "noApplicationsInOrgDescription": { - "message": "Import your organization's login data to start monitoring credential security risks. Once imported you get to:" + "noDataInOrgDescription": { + "message": "Import your organization's login data to get started with Access Intelligence. Once you do that, you'll be able to:" }, - "benefit1Title": { - "message": "Prioritize risks" + "feature1Title": { + "message": "Mark applications as critical" }, - "benefit1Description": { - "message": "Focus on applications that matter the most" + "feature1Description": { + "message": "This will help you remove risks to your most important applications first." }, - "benefit2Title": { - "message": "Guide remediation" + "feature2Title": { + "message": "Help members improve their security" }, - "benefit2Description": { - "message": "Assign at-risk members guided tasks to rotate at-risk credentials" + "feature2Description": { + "message": "Assign at-risk members guided security tasks to update credentials." }, - "benefit3Title": { + "feature3Title": { "message": "Monitor progress" }, - "benefit3Description": { - "message": "Track changes over time to show security improvements" + "feature3Description": { + "message": "Track changes over time to show security improvements." }, - "noReportRunTitle": { - "message": "Run your first report to see applications" + "noReportsRunTitle": { + "message": "Generate report" }, - "noReportRunDescription": { - "message": "Generate a risk insights report to analyze your organization's applications and identify at-risk passwords that need attention. Running your first report will:" + "noReportsRunDescription": { + "message": "You’re ready to start generating reports. Once you generate, you’ll be able to:" }, "noCriticalApplicationsTitle": { "message": "Ви не відмітили жодного додатку в якості критичного" @@ -271,14 +265,14 @@ "atRiskMembers": { "message": "Ризиковані учасники" }, - "membersWithAccessToAtRiskItemsForCriticalApps": { - "message": "Members with access to at-risk items for critical applications" + "membersWithAccessToAtRiskItemsForCriticalApplications": { + "message": "These members have access to vulnerable items for critical applications." }, "membersWithAtRiskPasswords": { "message": "Members with at-risk passwords" }, - "membersWillReceiveNotification": { - "message": "Members will receive a notification to resolve at-risk logins through the browser extension." + "membersWillReceiveSecurityTask": { + "message": "Members of your organization will be assigned a task to change vulnerable passwords. They’ll receive a notification within their Bitwarden browser extension." }, "membersAtRiskCount": { "message": "$COUNT$ members at-risk", @@ -307,8 +301,8 @@ } } }, - "atRiskMembersDescription": { - "message": "Ці учасники використовують у програмах слабкі, викриті, або повторювані паролі." + "atRiskMemberDescription": { + "message": "These members are logging into critical applications with weak, exposed, or reused passwords." }, "atRiskMembersDescriptionNone": { "message": "Немає учасників, які використовують у програмах слабкі, викриті, або повторювані паролі." @@ -391,14 +385,14 @@ "prioritizeCriticalApplications": { "message": "Prioritize critical applications" }, - "selectCriticalApplicationsDescription": { - "message": "Select which applications are most critical to your organization, then assign security tasks to members to resolve risks." + "selectCriticalAppsDescription": { + "message": "Select which applications are most critical to your organization. Then, you’ll be able to assign security tasks to members to remove risks." }, "reviewNewApplications": { "message": "Review new applications" }, - "reviewNewApplicationsDescription": { - "message": "We've highlighted at-risk items for new applications stored in Admin console that have weak, exposed, or reused passwords." + "reviewNewAppsDescription": { + "message": "Review new applications with vulnerable items and mark those you’d like to monitor closely as critical. Then, you’ll be able to assign security tasks to members to remove risks." }, "clickIconToMarkAppAsCritical": { "message": "Click the star icon to mark an app as critical" @@ -9856,8 +9850,8 @@ "assignTasks": { "message": "Assign tasks" }, - "assignTasksToMembers": { - "message": "Assign tasks to members for guided resolution" + "assignSecurityTasksToMembers": { + "message": "Send notifications to change passwords" }, "assignToCollections": { "message": "Призначити до збірок" diff --git a/apps/web/src/locales/vi/messages.json b/apps/web/src/locales/vi/messages.json index 6e6ba52daa..f05004b46d 100644 --- a/apps/web/src/locales/vi/messages.json +++ b/apps/web/src/locales/vi/messages.json @@ -93,8 +93,8 @@ "assignMembersTasksToMonitorProgress": { "message": "Giao tác vụ cho thành viên để theo dõi tiến trình" }, - "onceYouReviewApps": { - "message": "Sau khi bạn xem xét các ứng dụng và đánh dấu chúng là nghiêm trọng, bạn có thể giao nhiệm vụ cho các thành viên để xử lý các mục có rủi ro và theo dõi tiến độ tại đây" + "onceYouReviewApplications": { + "message": "Once you review applications and mark them as critical, assign tasks to your members to change their passwords." }, "sendReminders": { "message": "Gửi lời nhắc" @@ -178,41 +178,35 @@ } } }, - "noApplicationsInOrgTitle": { - "message": "Không tìm thấy ứng dụng nào cho $ORG NAME$", - "placeholders": { - "org name": { - "content": "$1", - "example": "Company Name" - } - } + "noDataInOrgTitle": { + "message": "No data found" }, - "noApplicationsInOrgDescription": { - "message": "Nhập dữ liệu đăng nhập của tổ chức bạn để bắt đầu giám sát các rủi ro bảo mật thông tin xác thực. Sau khi nhập, bạn có thể:" + "noDataInOrgDescription": { + "message": "Import your organization's login data to get started with Access Intelligence. Once you do that, you'll be able to:" }, - "benefit1Title": { - "message": "Ưu tiên các rủi ro" + "feature1Title": { + "message": "Mark applications as critical" }, - "benefit1Description": { - "message": "Tập trung vào các ứng dụng quan trọng nhất" + "feature1Description": { + "message": "This will help you remove risks to your most important applications first." }, - "benefit2Title": { - "message": "Hướng dẫn khắc phục" + "feature2Title": { + "message": "Help members improve their security" }, - "benefit2Description": { - "message": "Giao nhiệm vụ được hướng dẫn cho các thành viên có rủi ro để xoay vòng thông tin xác thực có rủi ro" + "feature2Description": { + "message": "Assign at-risk members guided security tasks to update credentials." }, - "benefit3Title": { - "message": "Theo dõi tiến độ" + "feature3Title": { + "message": "Monitor progress" }, - "benefit3Description": { - "message": "Theo dõi thay đổi theo thời gian để hiển thị cải tiến bảo mật" + "feature3Description": { + "message": "Track changes over time to show security improvements." }, - "noReportRunTitle": { - "message": "Chạy báo cáo đầu tiên của bạn để xem các ứng dụng" + "noReportsRunTitle": { + "message": "Generate report" }, - "noReportRunDescription": { - "message": "Tạo báo cáo thông tin chi tiết về rủi ro để phân tích các ứng dụng của tổ chức bạn và xác định các mật khẩu có rủi ro cần chú ý. Khi chạy báo cáo đầu tiên, bạn sẽ:" + "noReportsRunDescription": { + "message": "You’re ready to start generating reports. Once you generate, you’ll be able to:" }, "noCriticalApplicationsTitle": { "message": "Bạn chưa đánh dấu ứng dụng nào là quan trọng" @@ -271,14 +265,14 @@ "atRiskMembers": { "message": "Các thành viên có rủi ro" }, - "membersWithAccessToAtRiskItemsForCriticalApps": { - "message": "Thành viên có quyền truy cập vào các mục có nguy cơ dành cho các ứng dụng quan trọng" + "membersWithAccessToAtRiskItemsForCriticalApplications": { + "message": "These members have access to vulnerable items for critical applications." }, "membersWithAtRiskPasswords": { "message": "Thành viên có mật khẩu rủi ro" }, - "membersWillReceiveNotification": { - "message": "Các thành viên sẽ nhận được thông báo để giải quyết các đăng nhập có rủi ro thông qua tiện ích mở rộng trình duyệt." + "membersWillReceiveSecurityTask": { + "message": "Members of your organization will be assigned a task to change vulnerable passwords. They’ll receive a notification within their Bitwarden browser extension." }, "membersAtRiskCount": { "message": "$COUNT$ thành viên gặp rủi ro", @@ -307,8 +301,8 @@ } } }, - "atRiskMembersDescription": { - "message": "Các thành viên này đang đăng nhập vào các ứng dụng bằng mật khẩu yếu, dễ bị lộ hoặc được sử dụng lại." + "atRiskMemberDescription": { + "message": "These members are logging into critical applications with weak, exposed, or reused passwords." }, "atRiskMembersDescriptionNone": { "message": "Không có thành viên nào đăng nhập vào ứng dụng bằng mật khẩu yếu, dễ bị lộ hoặc được sử dụng lại." @@ -391,14 +385,14 @@ "prioritizeCriticalApplications": { "message": "Ưu tiên các ứng dụng quan trọng" }, - "selectCriticalApplicationsDescription": { - "message": "Chọn những ứng dụng quan trọng nhất đối với tổ chức của bạn, sau đó giao nhiệm vụ bảo mật cho các thành viên để giải quyết rủi ro." + "selectCriticalAppsDescription": { + "message": "Select which applications are most critical to your organization. Then, you’ll be able to assign security tasks to members to remove risks." }, "reviewNewApplications": { "message": "Review new applications" }, - "reviewNewApplicationsDescription": { - "message": "We've highlighted at-risk items for new applications stored in Admin console that have weak, exposed, or reused passwords." + "reviewNewAppsDescription": { + "message": "Review new applications with vulnerable items and mark those you’d like to monitor closely as critical. Then, you’ll be able to assign security tasks to members to remove risks." }, "clickIconToMarkAppAsCritical": { "message": "Nhấp vào biểu tượng ngôi sao để đánh dấu một ứng dụng là quan trọng" @@ -9856,8 +9850,8 @@ "assignTasks": { "message": "Giao tác vụ" }, - "assignTasksToMembers": { - "message": "Giao nhiệm vụ cho các thành viên để hướng dẫn giải quyết" + "assignSecurityTasksToMembers": { + "message": "Send notifications to change passwords" }, "assignToCollections": { "message": "Gán vào bộ sưu tập" diff --git a/apps/web/src/locales/zh_CN/messages.json b/apps/web/src/locales/zh_CN/messages.json index cce4544ac7..05534b3a8b 100644 --- a/apps/web/src/locales/zh_CN/messages.json +++ b/apps/web/src/locales/zh_CN/messages.json @@ -93,8 +93,8 @@ "assignMembersTasksToMonitorProgress": { "message": "分配成员任务以监测进度" }, - "onceYouReviewApps": { - "message": "审查新应用程序并将其标记为关键后,您可以在这里将任务分配给成员以解决存在风险的项目并监测进度" + "onceYouReviewApplications": { + "message": "审查应用程序并将其标记为关键后,将任务分配给您的成员以更改他们的密码。" }, "sendReminders": { "message": "发送提醒" @@ -178,41 +178,35 @@ } } }, - "noApplicationsInOrgTitle": { - "message": "未找到与 $ORG NAME$ 相关的应用程序", - "placeholders": { - "org name": { - "content": "$1", - "example": "Company Name" - } - } + "noDataInOrgTitle": { + "message": "未找到任何数据" }, - "noApplicationsInOrgDescription": { - "message": "导入您组织的登录数据,以开始监测凭据安全风险。导入后您将能够:" + "noDataInOrgDescription": { + "message": "导入您组织的登录数据以开始使用 Access Intelligence。导入完成后,您将能够:" }, - "benefit1Title": { - "message": "优先处理风险" + "feature1Title": { + "message": "将应用程序标记为关键" }, - "benefit1Description": { - "message": "重点关注最重要的应用程序" + "feature1Description": { + "message": "这将帮助您优先消除您最重要的应用程序的风险。" }, - "benefit2Title": { - "message": "指导补救措施" + "feature2Title": { + "message": "帮助成员提升他们的安全性" }, - "benefit2Description": { - "message": "为存在风险的成员分配引导式任务,以轮换存在风险的凭据" + "feature2Description": { + "message": "为存在风险的成员分配引导式安全任务,以更新凭证。" }, - "benefit3Title": { + "feature3Title": { "message": "监测进度" }, - "benefit3Description": { - "message": "追踪变化趋势,展示安全改进成效" + "feature3Description": { + "message": "追踪一段时间内的变化,以展示安全性的改进。" }, - "noReportRunTitle": { - "message": "运行您的第一份报告以查看应用程序" + "noReportsRunTitle": { + "message": "生成报告" }, - "noReportRunDescription": { - "message": "生成风险洞察报告,以分析您组织的应用程序并识别需要关注的风险密码。运行您的第一份报告将:" + "noReportsRunDescription": { + "message": "您已准备好开始生成报告。生成报告后,您将能够:" }, "noCriticalApplicationsTitle": { "message": "您还没有将任何应用程序标记为关键" @@ -224,7 +218,7 @@ "message": "选择关键应用程序" }, "markAppAsCritical": { - "message": "标记应用程序为关键" + "message": "将 App 标记为关键" }, "markAsCritical": { "message": "标记为关键" @@ -271,14 +265,14 @@ "atRiskMembers": { "message": "存在风险的成员" }, - "membersWithAccessToAtRiskItemsForCriticalApps": { - "message": "对关键应用程序中存在风险的项目具有访问权限的成员" + "membersWithAccessToAtRiskItemsForCriticalApplications": { + "message": "这些成员拥有关键应用程序中易受攻击项目的访问权限。" }, "membersWithAtRiskPasswords": { "message": "密码存在风险的成员" }, - "membersWillReceiveNotification": { - "message": "成员将通过浏览器扩展收到通知,以解决存在风险的登录。" + "membersWillReceiveSecurityTask": { + "message": "您的组织成员将被分配更改易受攻击的密码的任务。他们将在 Bitwarden 浏览器扩展中收到通知。" }, "membersAtRiskCount": { "message": "$COUNT$ 个成员存在风险", @@ -307,8 +301,8 @@ } } }, - "atRiskMembersDescription": { - "message": "这些成员正登录到具有弱的、暴露的或重复使用的密码的应用程序。" + "atRiskMemberDescription": { + "message": "这些成员正在登录到具有弱的、暴露的或重复使用的密码的关键应用程序。" }, "atRiskMembersDescriptionNone": { "message": "没有成员登录到具有弱的、暴露的或重复使用的密码的应用程序。" @@ -391,14 +385,14 @@ "prioritizeCriticalApplications": { "message": "优先处理关键应用程序" }, - "selectCriticalApplicationsDescription": { - "message": "选择对您的组织最关键的应用程序,然后将安全任务分配给成员以解决风险。" + "selectCriticalAppsDescription": { + "message": "选择对您的组织最关键的应用程序。然后,您可以将安全任务分配给成员以消除风险。" }, "reviewNewApplications": { "message": "审查新应用程序" }, - "reviewNewApplicationsDescription": { - "message": "我们突出显示了存储在管理控制台中的新应用程序的风险项目,这些项目使用了弱、暴露或重复使用的密码。" + "reviewNewAppsDescription": { + "message": "审查具有易受攻击项目的新应用程序然后将需要密切监测的应用程序标记为关键。然后,您可以将安全任务分配给成员以消除风险。" }, "clickIconToMarkAppAsCritical": { "message": "点击星形图标以将 App 标记为关键" @@ -2543,23 +2537,23 @@ "message": "恢复访问权限" }, "premium": { - "message": "高级会员", + "message": "高级版", "description": "Premium membership" }, "premiumMembership": { "message": "高级会员" }, "premiumRequired": { - "message": "需要高级会员" + "message": "需要高级版" }, "premiumRequiredDesc": { "message": "使用此功能需要高级会员资格。" }, "youHavePremiumAccess": { - "message": "您拥有高级访问权限" + "message": "您拥有高级版访问权限" }, "alreadyPremiumFromOrg": { - "message": "由于您是拥有高级会员功能的组织的成员,您已经拥有此功能。" + "message": "由于您是组织的成员,您已经拥有高级版功能访问权限。" }, "manage": { "message": "管理" @@ -3056,7 +3050,7 @@ "message": "您账户的信用额度可用于进行消费。任何可用的信用额度将用于自动抵扣此账户的账单。" }, "goPremium": { - "message": "升级高级会员", + "message": "升级高级版", "description": "Another way of saying \"Get a Premium membership\"" }, "premiumUpdated": { @@ -3084,7 +3078,7 @@ "message": "优先客户支持。" }, "premiumSignUpFuture": { - "message": "未来的更多高级功能。敬请期待!" + "message": "未来的更多高级版功能。敬请期待!" }, "premiumPrice": { "message": "所有功能仅需 $PRICE$ /年!", @@ -3096,7 +3090,7 @@ } }, "premiumPriceWithFamilyPlan": { - "message": "升级高级会员仅需 $PRICE$ /年,或成为具有 $FAMILYPLANUSERCOUNT$ 位用户以及无限制的家庭共享的高级账户,通过 ", + "message": "升级高级版仅需 $PRICE$ /年,或成为具有 $FAMILYPLANUSERCOUNT$ 位用户以及无限制的家庭共享的高级账户,通过 ", "placeholders": { "price": { "content": "$1", @@ -3115,10 +3109,10 @@ "message": "附加项目" }, "premiumAccess": { - "message": "高级会员" + "message": "高级版访问权限" }, "premiumAccessDesc": { - "message": "您可以为您的组织所有成员添加高级访问权限,只需 $PRICE$ /$INTERVAL$ 。", + "message": "您可以为您的组织所有成员添加高级版访问权限,只需 $PRICE$ /$INTERVAL$ 。", "placeholders": { "price": { "content": "$1", @@ -3559,7 +3553,7 @@ "message": "本地托管(可选)" }, "usersGetPremium": { - "message": "用户拥有高级会员功能权限" + "message": "用户拥有高级版功能访问权限" }, "controlAccessWithGroups": { "message": "使用群组控制用户访问权限" @@ -6915,7 +6909,7 @@ "message": "Bitwarden 家庭方案包含" }, "sponsoredFamiliesPremiumAccess": { - "message": "最多 6 个用户的高级访问权限" + "message": "最多 6 个高级版访问权限的用户" }, "sponsoredFamiliesSharedCollectionsForFamilyMembers": { "message": "为家庭成员提供共享集合" @@ -9856,8 +9850,8 @@ "assignTasks": { "message": "分配任务" }, - "assignTasksToMembers": { - "message": "将任务分配给成员以引导式解决" + "assignSecurityTasksToMembers": { + "message": "发送通知以更改密码" }, "assignToCollections": { "message": "分配到集合" @@ -10877,7 +10871,7 @@ "message": "保护您的家庭登录" }, "accessToPremiumFeatures": { - "message": "访问高级会员功能" + "message": "高级版功能访问权限" }, "additionalStorageGbMessage": { "message": "GB 附加存储" @@ -10916,7 +10910,7 @@ "message": "RSA 4096-Bit" }, "premiumAccounts": { - "message": "6 个高级账户" + "message": "6 个高级版账户" }, "unlimitedSharing": { "message": "不限数量的共享" @@ -12159,9 +12153,9 @@ } }, "confirmNoSelectedCriticalApplicationsTitle": { - "message": "No critical applications are selected" + "message": "未选择任何关键应用程序" }, "confirmNoSelectedCriticalApplicationsDesc": { - "message": "Are you sure you want to continue?" + "message": "确定要继续吗?" } } diff --git a/apps/web/src/locales/zh_TW/messages.json b/apps/web/src/locales/zh_TW/messages.json index 784027a735..3036366816 100644 --- a/apps/web/src/locales/zh_TW/messages.json +++ b/apps/web/src/locales/zh_TW/messages.json @@ -93,8 +93,8 @@ "assignMembersTasksToMonitorProgress": { "message": "指派成員任務以監控進度" }, - "onceYouReviewApps": { - "message": "在您檢視應用程式並將其標記為關鍵後,您可以指派任務給成員,以解決有風險的項目,並在此監控進度" + "onceYouReviewApplications": { + "message": "Once you review applications and mark them as critical, assign tasks to your members to change their passwords." }, "sendReminders": { "message": "傳送提醒" @@ -178,41 +178,35 @@ } } }, - "noApplicationsInOrgTitle": { - "message": "未找到 $ORG NAME$ 的應用程式", - "placeholders": { - "org name": { - "content": "$1", - "example": "Company Name" - } - } + "noDataInOrgTitle": { + "message": "No data found" }, - "noApplicationsInOrgDescription": { - "message": "匯入您組織的登入資料以開始監控憑證安全風險。匯入後您可以:" + "noDataInOrgDescription": { + "message": "Import your organization's login data to get started with Access Intelligence. Once you do that, you'll be able to:" }, - "benefit1Title": { - "message": "風險優先排序" + "feature1Title": { + "message": "Mark applications as critical" }, - "benefit1Description": { - "message": "專注於最重要的應用程式" + "feature1Description": { + "message": "This will help you remove risks to your most important applications first." }, - "benefit2Title": { - "message": "指導補救措施" + "feature2Title": { + "message": "Help members improve their security" }, - "benefit2Description": { - "message": "指派有風險的成員執行指導任務以輪換有風險的憑證" + "feature2Description": { + "message": "Assign at-risk members guided security tasks to update credentials." }, - "benefit3Title": { - "message": "監控進展" + "feature3Title": { + "message": "Monitor progress" }, - "benefit3Description": { - "message": "追蹤隨時間變化的狀況以顯示安全性改善" + "feature3Description": { + "message": "Track changes over time to show security improvements." }, - "noReportRunTitle": { - "message": "執行您的第一份報告以查看應用程式" + "noReportsRunTitle": { + "message": "Generate report" }, - "noReportRunDescription": { - "message": "產生風險洞察報告以分析組織的應用程式並找出需要注意的高風險密碼。執行第一份報告將會:" + "noReportsRunDescription": { + "message": "You’re ready to start generating reports. Once you generate, you’ll be able to:" }, "noCriticalApplicationsTitle": { "message": "您尚未將任何應用程式標記為關鍵" @@ -271,14 +265,14 @@ "atRiskMembers": { "message": "具有風險的成員" }, - "membersWithAccessToAtRiskItemsForCriticalApps": { - "message": "擁有關鍵應用程式中有風險項目存取權的成員" + "membersWithAccessToAtRiskItemsForCriticalApplications": { + "message": "These members have access to vulnerable items for critical applications." }, "membersWithAtRiskPasswords": { "message": "使用有風險密碼的成員" }, - "membersWillReceiveNotification": { - "message": "成員會透過瀏覽器擴充套件接收到有風險登入的通知。" + "membersWillReceiveSecurityTask": { + "message": "Members of your organization will be assigned a task to change vulnerable passwords. They’ll receive a notification within their Bitwarden browser extension." }, "membersAtRiskCount": { "message": "$COUNT$ 位有風險的成員", @@ -307,8 +301,8 @@ } } }, - "atRiskMembersDescription": { - "message": "這些成員正在使用弱密碼、外洩密碼或重複密碼登入應用程式。" + "atRiskMemberDescription": { + "message": "These members are logging into critical applications with weak, exposed, or reused passwords." }, "atRiskMembersDescriptionNone": { "message": "目前沒有成員使用弱密碼、外洩密碼或重複密碼登入應用程式。" @@ -391,14 +385,14 @@ "prioritizeCriticalApplications": { "message": "優先處理關鍵應用程式" }, - "selectCriticalApplicationsDescription": { - "message": "選擇對組織最關鍵的應用程式,然後將安全任務指派給成員以供解決。" + "selectCriticalAppsDescription": { + "message": "Select which applications are most critical to your organization. Then, you’ll be able to assign security tasks to members to remove risks." }, "reviewNewApplications": { "message": "審查新應用程式" }, - "reviewNewApplicationsDescription": { - "message": "我們已在管理主控台中標示出新應用程式中密碼薄弱、已外洩或重複使用的高風險項目。" + "reviewNewAppsDescription": { + "message": "Review new applications with vulnerable items and mark those you’d like to monitor closely as critical. Then, you’ll be able to assign security tasks to members to remove risks." }, "clickIconToMarkAppAsCritical": { "message": "點擊星形圖示以將應用程式標記為關鍵" @@ -9856,8 +9850,8 @@ "assignTasks": { "message": "指派任務" }, - "assignTasksToMembers": { - "message": "指派任務給成員並引導解決" + "assignSecurityTasksToMembers": { + "message": "Send notifications to change passwords" }, "assignToCollections": { "message": "指派至集合" @@ -12159,9 +12153,9 @@ } }, "confirmNoSelectedCriticalApplicationsTitle": { - "message": "No critical applications are selected" + "message": "未選取任何關鍵應用程式" }, "confirmNoSelectedCriticalApplicationsDesc": { - "message": "Are you sure you want to continue?" + "message": "您確定要繼續嗎?" } } From 28dc244fd3bc272fd2e36c8727df76b27f75ede4 Mon Sep 17 00:00:00 2001 From: Brandon Treston Date: Wed, 19 Nov 2025 13:32:50 -0500 Subject: [PATCH 26/52] fix error in console (#17468) --- .../group-name-badge.component.html | 2 +- .../group-badge/group-name-badge.component.ts | 39 +++++++++---------- 2 files changed, 19 insertions(+), 22 deletions(-) diff --git a/apps/web/src/app/admin-console/organizations/collections/group-badge/group-name-badge.component.html b/apps/web/src/app/admin-console/organizations/collections/group-badge/group-name-badge.component.html index 9ddc9897a3..a8021e82c3 100644 --- a/apps/web/src/app/admin-console/organizations/collections/group-badge/group-name-badge.component.html +++ b/apps/web/src/app/admin-console/organizations/collections/group-badge/group-name-badge.component.html @@ -1 +1 @@ - + diff --git a/apps/web/src/app/admin-console/organizations/collections/group-badge/group-name-badge.component.ts b/apps/web/src/app/admin-console/organizations/collections/group-badge/group-name-badge.component.ts index 8a58f5b92d..3c1d0d2b69 100644 --- a/apps/web/src/app/admin-console/organizations/collections/group-badge/group-name-badge.component.ts +++ b/apps/web/src/app/admin-console/organizations/collections/group-badge/group-name-badge.component.ts @@ -1,36 +1,33 @@ -// FIXME: Update this file to be type safe and remove this and next line -// @ts-strict-ignore -import { Component, Input, OnChanges } from "@angular/core"; +import { ChangeDetectionStrategy, Component, computed, input } from "@angular/core"; import { SelectionReadOnlyRequest } from "@bitwarden/common/admin-console/models/request/selection-read-only.request"; import { I18nService } from "@bitwarden/common/platform/abstractions/i18n.service"; import { GroupView } from "../../core"; -// FIXME(https://bitwarden.atlassian.net/browse/CL-764): Migrate to OnPush -// eslint-disable-next-line @angular-eslint/prefer-on-push-component-change-detection @Component({ selector: "app-group-badge", templateUrl: "group-name-badge.component.html", standalone: false, + changeDetection: ChangeDetectionStrategy.OnPush, }) -export class GroupNameBadgeComponent implements OnChanges { - // FIXME(https://bitwarden.atlassian.net/browse/CL-903): Migrate to Signals - // eslint-disable-next-line @angular-eslint/prefer-signals - @Input() selectedGroups: SelectionReadOnlyRequest[]; - // FIXME(https://bitwarden.atlassian.net/browse/CL-903): Migrate to Signals - // eslint-disable-next-line @angular-eslint/prefer-signals - @Input() allGroups: GroupView[]; +export class GroupNameBadgeComponent { + readonly selectedGroups = input([]); + readonly allGroups = input([]); - protected groupNames: string[] = []; + protected readonly groupNames = computed(() => { + const allGroups = this.allGroups(); + if (!allGroups) { + return []; + } + + return this.selectedGroups() + .map((g) => { + return allGroups.find((o) => o.id === g.id)?.name; + }) + .filter((name): name is string => name !== undefined) + .sort(this.i18nService.collator.compare); + }); constructor(private i18nService: I18nService) {} - - ngOnChanges() { - this.groupNames = this.selectedGroups - .map((g) => { - return this.allGroups.find((o) => o.id === g.id)?.name; - }) - .sort(this.i18nService.collator.compare); - } } From 9ec05a96b9f14331f8c2dfde5513115cf238940f Mon Sep 17 00:00:00 2001 From: "renovate[bot]" <29139614+renovate[bot]@users.noreply.github.com> Date: Wed, 19 Nov 2025 18:44:01 +0000 Subject: [PATCH 27/52] [deps]: Update GitHub Artifact Actions (#17305) Co-authored-by: renovate[bot] <29139614+renovate[bot]@users.noreply.github.com> Co-authored-by: Daniel James Smith <2670567+djsmith85@users.noreply.github.com> --- .github/workflows/build-browser.yml | 8 +-- .github/workflows/build-cli.yml | 12 ++--- .github/workflows/build-desktop.yml | 84 ++++++++++++++--------------- .github/workflows/build-web.yml | 2 +- .github/workflows/test.yml | 8 +-- 5 files changed, 57 insertions(+), 57 deletions(-) diff --git a/.github/workflows/build-browser.yml b/.github/workflows/build-browser.yml index 83e6c2d696..dc71d33d60 100644 --- a/.github/workflows/build-browser.yml +++ b/.github/workflows/build-browser.yml @@ -193,7 +193,7 @@ jobs: zip -r browser-source.zip browser-source - name: Upload browser source - uses: actions/upload-artifact@65c4c4a1ddee5b72f698fdd19549f0f0fb45cf08 # v4.6.0 + uses: actions/upload-artifact@330a01c490aca151604b8cf639adc76d48f6c5d4 # v5.0.0 with: name: ${{matrix.license_type.archive_name_prefix}}browser-source-${{ env._BUILD_NUMBER }}.zip path: browser-source.zip @@ -268,7 +268,7 @@ jobs: npm --version - name: Download browser source - uses: actions/download-artifact@634f93cb2916e3fdff6788551b99b062d0335ce0 # v5.0.0 + uses: actions/download-artifact@018cc2cf5baa6db3ef3c5f8a56943fffe632ef53 # v6.0.0 with: name: ${{matrix.license_type.source_archive_name_prefix}}browser-source-${{ env._BUILD_NUMBER }}.zip @@ -332,7 +332,7 @@ jobs: working-directory: browser-source/apps/browser - name: Upload extension artifact - uses: actions/upload-artifact@65c4c4a1ddee5b72f698fdd19549f0f0fb45cf08 # v4.6.0 + uses: actions/upload-artifact@330a01c490aca151604b8cf639adc76d48f6c5d4 # v5.0.0 with: name: ${{ matrix.license_type.artifact_prefix }}${{ matrix.browser.artifact_name }}-${{ env._BUILD_NUMBER }}.zip path: browser-source/apps/browser/dist/${{matrix.license_type.archive_name_prefix}}${{ matrix.browser.archive_name }} @@ -506,7 +506,7 @@ jobs: ls -la - name: Upload Safari artifact - uses: actions/upload-artifact@65c4c4a1ddee5b72f698fdd19549f0f0fb45cf08 # v4.6.0 + uses: actions/upload-artifact@330a01c490aca151604b8cf639adc76d48f6c5d4 # v5.0.0 with: name: ${{matrix.license_type.archive_name_prefix}}dist-safari-${{ env._BUILD_NUMBER }}.zip path: apps/browser/dist/${{matrix.license_type.archive_name_prefix}}dist-safari.zip diff --git a/.github/workflows/build-cli.yml b/.github/workflows/build-cli.yml index 414c043b89..babd00a323 100644 --- a/.github/workflows/build-cli.yml +++ b/.github/workflows/build-cli.yml @@ -268,7 +268,7 @@ jobs: fi - name: Upload unix zip asset - uses: actions/upload-artifact@65c4c4a1ddee5b72f698fdd19549f0f0fb45cf08 # v4.6.0 + uses: actions/upload-artifact@330a01c490aca151604b8cf639adc76d48f6c5d4 # v5.0.0 with: name: bw${{ matrix.license_type.artifact_prefix }}-${{ env.LOWER_RUNNER_OS }}${{ matrix.os.target_suffix }}-${{ env._PACKAGE_VERSION }}.zip path: apps/cli/dist/bw${{ matrix.license_type.artifact_prefix }}-${{ env.LOWER_RUNNER_OS }}${{ matrix.os.target_suffix }}-${{ env._PACKAGE_VERSION }}.zip @@ -482,7 +482,7 @@ jobs: } - name: Upload windows zip asset - uses: actions/upload-artifact@65c4c4a1ddee5b72f698fdd19549f0f0fb45cf08 # v4.6.0 + uses: actions/upload-artifact@330a01c490aca151604b8cf639adc76d48f6c5d4 # v5.0.0 with: name: bw${{ matrix.license_type.artifact_prefix }}-windows-${{ env._PACKAGE_VERSION }}.zip path: apps/cli/dist/bw${{ matrix.license_type.artifact_prefix }}-windows-${{ env._PACKAGE_VERSION }}.zip @@ -490,7 +490,7 @@ jobs: - name: Upload Chocolatey asset if: matrix.license_type.build_prefix == 'bit' - uses: actions/upload-artifact@65c4c4a1ddee5b72f698fdd19549f0f0fb45cf08 # v4.6.0 + uses: actions/upload-artifact@330a01c490aca151604b8cf639adc76d48f6c5d4 # v5.0.0 with: name: bitwarden-cli.${{ env._PACKAGE_VERSION }}.nupkg path: apps/cli/dist/chocolatey/bitwarden-cli.${{ env._PACKAGE_VERSION }}.nupkg @@ -503,7 +503,7 @@ jobs: - name: Upload NPM Build Directory asset if: matrix.license_type.build_prefix == 'bit' - uses: actions/upload-artifact@65c4c4a1ddee5b72f698fdd19549f0f0fb45cf08 # v4.6.0 + uses: actions/upload-artifact@330a01c490aca151604b8cf639adc76d48f6c5d4 # v5.0.0 with: name: bitwarden-cli-${{ env._PACKAGE_VERSION }}-npm-build.zip path: apps/cli/bitwarden-cli-${{ env._PACKAGE_VERSION }}-npm-build.zip @@ -535,7 +535,7 @@ jobs: echo "BW Package Version: $_PACKAGE_VERSION" - name: Get bw linux cli - uses: actions/download-artifact@634f93cb2916e3fdff6788551b99b062d0335ce0 # v5.0.0 + uses: actions/download-artifact@018cc2cf5baa6db3ef3c5f8a56943fffe632ef53 # v6.0.0 with: name: bw-linux-${{ env._PACKAGE_VERSION }}.zip path: apps/cli/dist/snap @@ -572,7 +572,7 @@ jobs: run: sudo snap remove bw - name: Upload snap asset - uses: actions/upload-artifact@65c4c4a1ddee5b72f698fdd19549f0f0fb45cf08 # v4.6.0 + uses: actions/upload-artifact@330a01c490aca151604b8cf639adc76d48f6c5d4 # v5.0.0 with: name: bw_${{ env._PACKAGE_VERSION }}_amd64.snap path: apps/cli/dist/snap/bw_${{ env._PACKAGE_VERSION }}_amd64.snap diff --git a/.github/workflows/build-desktop.yml b/.github/workflows/build-desktop.yml index 27a7bfe412..1877374a52 100644 --- a/.github/workflows/build-desktop.yml +++ b/.github/workflows/build-desktop.yml @@ -257,35 +257,35 @@ jobs: run: npm run dist:lin - name: Upload .deb artifact - uses: actions/upload-artifact@65c4c4a1ddee5b72f698fdd19549f0f0fb45cf08 # v4.6.0 + uses: actions/upload-artifact@330a01c490aca151604b8cf639adc76d48f6c5d4 # v5.0.0 with: name: Bitwarden-${{ env._PACKAGE_VERSION }}-amd64.deb path: apps/desktop/dist/Bitwarden-${{ env._PACKAGE_VERSION }}-amd64.deb if-no-files-found: error - name: Upload .rpm artifact - uses: actions/upload-artifact@65c4c4a1ddee5b72f698fdd19549f0f0fb45cf08 # v4.6.0 + uses: actions/upload-artifact@330a01c490aca151604b8cf639adc76d48f6c5d4 # v5.0.0 with: name: Bitwarden-${{ env._PACKAGE_VERSION }}-x86_64.rpm path: apps/desktop/dist/Bitwarden-${{ env._PACKAGE_VERSION }}-x86_64.rpm if-no-files-found: error - name: Upload .snap artifact - uses: actions/upload-artifact@65c4c4a1ddee5b72f698fdd19549f0f0fb45cf08 # v4.6.0 + uses: actions/upload-artifact@330a01c490aca151604b8cf639adc76d48f6c5d4 # v5.0.0 with: name: bitwarden_${{ env._PACKAGE_VERSION }}_amd64.snap path: apps/desktop/dist/bitwarden_${{ env._PACKAGE_VERSION }}_amd64.snap if-no-files-found: error - name: Upload .AppImage artifact - uses: actions/upload-artifact@65c4c4a1ddee5b72f698fdd19549f0f0fb45cf08 # v4.6.0 + uses: actions/upload-artifact@330a01c490aca151604b8cf639adc76d48f6c5d4 # v5.0.0 with: name: Bitwarden-${{ env._PACKAGE_VERSION }}-x86_64.AppImage path: apps/desktop/dist/Bitwarden-${{ env._PACKAGE_VERSION }}-x86_64.AppImage if-no-files-found: error - name: Upload auto-update artifact - uses: actions/upload-artifact@65c4c4a1ddee5b72f698fdd19549f0f0fb45cf08 # v4.6.0 + uses: actions/upload-artifact@330a01c490aca151604b8cf639adc76d48f6c5d4 # v5.0.0 with: name: ${{ needs.setup.outputs.release_channel }}-linux.yml path: apps/desktop/dist/${{ needs.setup.outputs.release_channel }}-linux.yml @@ -298,7 +298,7 @@ jobs: sudo npm run pack:lin:flatpak - name: Upload flatpak artifact - uses: actions/upload-artifact@65c4c4a1ddee5b72f698fdd19549f0f0fb45cf08 # v4.6.0 + uses: actions/upload-artifact@330a01c490aca151604b8cf639adc76d48f6c5d4 # v5.0.0 with: name: com.bitwarden.desktop.flatpak path: apps/desktop/dist/com.bitwarden.desktop.flatpak @@ -426,14 +426,14 @@ jobs: run: npm run dist:lin:arm64 - name: Upload .snap artifact - uses: actions/upload-artifact@65c4c4a1ddee5b72f698fdd19549f0f0fb45cf08 # v4.6.0 + uses: actions/upload-artifact@330a01c490aca151604b8cf639adc76d48f6c5d4 # v5.0.0 with: name: bitwarden_${{ env._PACKAGE_VERSION }}_arm64.snap path: apps/desktop/dist/bitwarden_${{ env._PACKAGE_VERSION }}_arm64.snap if-no-files-found: error - name: Upload tar.gz artifact - uses: actions/upload-artifact@ea165f8d65b6e75b540449e92b4886f43607fa02 # v4.6.2 + uses: actions/upload-artifact@330a01c490aca151604b8cf639adc76d48f6c5d4 # v5.0.0 with: name: bitwarden_${{ env._PACKAGE_VERSION }}_arm64.tar.gz path: apps/desktop/dist/bitwarden_desktop_arm64.tar.gz @@ -446,7 +446,7 @@ jobs: sudo npm run pack:lin:flatpak - name: Upload flatpak artifact - uses: actions/upload-artifact@65c4c4a1ddee5b72f698fdd19549f0f0fb45cf08 # v4.6.0 + uses: actions/upload-artifact@330a01c490aca151604b8cf639adc76d48f6c5d4 # v5.0.0 with: name: com.bitwarden.desktop-arm64.flatpak path: apps/desktop/dist/com.bitwarden.desktop.flatpak @@ -617,7 +617,7 @@ jobs: -NewName bitwarden-$env:_PACKAGE_VERSION-arm64.nsis.7z - name: Upload portable exe artifact - uses: actions/upload-artifact@65c4c4a1ddee5b72f698fdd19549f0f0fb45cf08 # v4.6.0 + uses: actions/upload-artifact@330a01c490aca151604b8cf639adc76d48f6c5d4 # v5.0.0 with: name: Bitwarden-Portable-${{ env._PACKAGE_VERSION }}.exe path: apps/desktop/dist/Bitwarden-Portable-${{ env._PACKAGE_VERSION }}.exe @@ -625,7 +625,7 @@ jobs: - name: Upload installer exe artifact if: ${{ needs.setup.outputs.has_secrets == 'true' }} - uses: actions/upload-artifact@65c4c4a1ddee5b72f698fdd19549f0f0fb45cf08 # v4.6.0 + uses: actions/upload-artifact@330a01c490aca151604b8cf639adc76d48f6c5d4 # v5.0.0 with: name: Bitwarden-Installer-${{ env._PACKAGE_VERSION }}..exe path: apps/desktop/dist/nsis-web/Bitwarden-Installer-${{ env._PACKAGE_VERSION }}.exe @@ -633,7 +633,7 @@ jobs: - name: Upload appx ia32 artifact if: ${{ needs.setup.outputs.has_secrets == 'true' }} - uses: actions/upload-artifact@65c4c4a1ddee5b72f698fdd19549f0f0fb45cf08 # v4.6.0 + uses: actions/upload-artifact@330a01c490aca151604b8cf639adc76d48f6c5d4 # v5.0.0 with: name: Bitwarden-${{ env._PACKAGE_VERSION }}-ia32.appx path: apps/desktop/dist/Bitwarden-${{ env._PACKAGE_VERSION }}-ia32.appx @@ -641,7 +641,7 @@ jobs: - name: Upload store appx ia32 artifact if: ${{ needs.setup.outputs.has_secrets == 'true' }} - uses: actions/upload-artifact@65c4c4a1ddee5b72f698fdd19549f0f0fb45cf08 # v4.6.0 + uses: actions/upload-artifact@330a01c490aca151604b8cf639adc76d48f6c5d4 # v5.0.0 with: name: Bitwarden-${{ env._PACKAGE_VERSION }}-ia32-store.appx path: apps/desktop/dist/Bitwarden-${{ env._PACKAGE_VERSION }}-ia32-store.appx @@ -649,7 +649,7 @@ jobs: - name: Upload NSIS ia32 artifact if: ${{ needs.setup.outputs.has_secrets == 'true' }} - uses: actions/upload-artifact@65c4c4a1ddee5b72f698fdd19549f0f0fb45cf08 # v4.6.0 + uses: actions/upload-artifact@330a01c490aca151604b8cf639adc76d48f6c5d4 # v5.0.0 with: name: bitwarden-${{ env._PACKAGE_VERSION }}-ia32.nsis.7z path: apps/desktop/dist/nsis-web/bitwarden-${{ env._PACKAGE_VERSION }}-ia32.nsis.7z @@ -657,7 +657,7 @@ jobs: - name: Upload appx x64 artifact if: ${{ needs.setup.outputs.has_secrets == 'true' }} - uses: actions/upload-artifact@65c4c4a1ddee5b72f698fdd19549f0f0fb45cf08 # v4.6.0 + uses: actions/upload-artifact@330a01c490aca151604b8cf639adc76d48f6c5d4 # v5.0.0 with: name: Bitwarden-${{ env._PACKAGE_VERSION }}-x64.appx path: apps/desktop/dist/Bitwarden-${{ env._PACKAGE_VERSION }}-x64.appx @@ -665,7 +665,7 @@ jobs: - name: Upload store appx x64 artifact if: ${{ needs.setup.outputs.has_secrets == 'true' }} - uses: actions/upload-artifact@65c4c4a1ddee5b72f698fdd19549f0f0fb45cf08 # v4.6.0 + uses: actions/upload-artifact@330a01c490aca151604b8cf639adc76d48f6c5d4 # v5.0.0 with: name: Bitwarden-${{ env._PACKAGE_VERSION }}-x64-store.appx path: apps/desktop/dist/Bitwarden-${{ env._PACKAGE_VERSION }}-x64-store.appx @@ -673,7 +673,7 @@ jobs: - name: Upload NSIS x64 artifact if: ${{ needs.setup.outputs.has_secrets == 'true' }} - uses: actions/upload-artifact@65c4c4a1ddee5b72f698fdd19549f0f0fb45cf08 # v4.6.0 + uses: actions/upload-artifact@330a01c490aca151604b8cf639adc76d48f6c5d4 # v5.0.0 with: name: bitwarden-${{ env._PACKAGE_VERSION }}-x64.nsis.7z path: apps/desktop/dist/nsis-web/bitwarden-${{ env._PACKAGE_VERSION }}-x64.nsis.7z @@ -681,7 +681,7 @@ jobs: - name: Upload appx ARM64 artifact if: ${{ needs.setup.outputs.has_secrets == 'true' }} - uses: actions/upload-artifact@65c4c4a1ddee5b72f698fdd19549f0f0fb45cf08 # v4.6.0 + uses: actions/upload-artifact@330a01c490aca151604b8cf639adc76d48f6c5d4 # v5.0.0 with: name: Bitwarden-${{ env._PACKAGE_VERSION }}-arm64.appx path: apps/desktop/dist/Bitwarden-${{ env._PACKAGE_VERSION }}-arm64.appx @@ -689,7 +689,7 @@ jobs: - name: Upload store appx ARM64 artifact if: ${{ needs.setup.outputs.has_secrets == 'true' }} - uses: actions/upload-artifact@65c4c4a1ddee5b72f698fdd19549f0f0fb45cf08 # v4.6.0 + uses: actions/upload-artifact@330a01c490aca151604b8cf639adc76d48f6c5d4 # v5.0.0 with: name: Bitwarden-${{ env._PACKAGE_VERSION }}-arm64-store.appx path: apps/desktop/dist/Bitwarden-${{ env._PACKAGE_VERSION }}-arm64-store.appx @@ -697,7 +697,7 @@ jobs: - name: Upload NSIS ARM64 artifact if: ${{ needs.setup.outputs.has_secrets == 'true' }} - uses: actions/upload-artifact@65c4c4a1ddee5b72f698fdd19549f0f0fb45cf08 # v4.6.0 + uses: actions/upload-artifact@330a01c490aca151604b8cf639adc76d48f6c5d4 # v5.0.0 with: name: bitwarden-${{ env._PACKAGE_VERSION }}-arm64.nsis.7z path: apps/desktop/dist/nsis-web/bitwarden-${{ env._PACKAGE_VERSION }}-arm64.nsis.7z @@ -705,7 +705,7 @@ jobs: - name: Upload nupkg artifact if: ${{ needs.setup.outputs.has_secrets == 'true' }} - uses: actions/upload-artifact@65c4c4a1ddee5b72f698fdd19549f0f0fb45cf08 # v4.6.0 + uses: actions/upload-artifact@330a01c490aca151604b8cf639adc76d48f6c5d4 # v5.0.0 with: name: bitwarden.${{ env._PACKAGE_VERSION }}.nupkg path: apps/desktop/dist/chocolatey/bitwarden.${{ env._PACKAGE_VERSION }}.nupkg @@ -713,7 +713,7 @@ jobs: - name: Upload auto-update artifact if: ${{ needs.setup.outputs.has_secrets == 'true' }} - uses: actions/upload-artifact@65c4c4a1ddee5b72f698fdd19549f0f0fb45cf08 # v4.6.0 + uses: actions/upload-artifact@330a01c490aca151604b8cf639adc76d48f6c5d4 # v5.0.0 with: name: ${{ needs.setup.outputs.release_channel }}.yml path: apps/desktop/dist/nsis-web/${{ needs.setup.outputs.release_channel }}.yml @@ -868,7 +868,7 @@ jobs: -NewName latest-beta.yml - name: Upload portable exe artifact - uses: actions/upload-artifact@65c4c4a1ddee5b72f698fdd19549f0f0fb45cf08 # v4.6.0 + uses: actions/upload-artifact@330a01c490aca151604b8cf639adc76d48f6c5d4 # v5.0.0 with: name: Bitwarden-Beta-Portable-${{ env._PACKAGE_VERSION }}.exe path: apps/desktop/dist/Bitwarden-Beta-Portable-${{ env._PACKAGE_VERSION }}.exe @@ -876,7 +876,7 @@ jobs: - name: Upload installer exe artifact if: ${{ needs.setup.outputs.has_secrets == 'true' }} - uses: actions/upload-artifact@65c4c4a1ddee5b72f698fdd19549f0f0fb45cf08 # v4.6.0 + uses: actions/upload-artifact@330a01c490aca151604b8cf639adc76d48f6c5d4 # v5.0.0 with: name: Bitwarden-Beta-Installer-${{ env._PACKAGE_VERSION }}.exe path: apps/desktop/dist/nsis-web/Bitwarden-Beta-Installer-${{ env._PACKAGE_VERSION }}.exe @@ -884,7 +884,7 @@ jobs: - name: Upload appx ia32 artifact if: ${{ needs.setup.outputs.has_secrets == 'true' }} - uses: actions/upload-artifact@65c4c4a1ddee5b72f698fdd19549f0f0fb45cf08 # v4.6.0 + uses: actions/upload-artifact@330a01c490aca151604b8cf639adc76d48f6c5d4 # v5.0.0 with: name: Bitwarden-Beta-${{ env._PACKAGE_VERSION }}-ia32.appx path: apps/desktop/dist/Bitwarden-Beta-${{ env._PACKAGE_VERSION }}-ia32.appx @@ -892,7 +892,7 @@ jobs: - name: Upload store appx ia32 artifact if: ${{ needs.setup.outputs.has_secrets == 'true' }} - uses: actions/upload-artifact@65c4c4a1ddee5b72f698fdd19549f0f0fb45cf08 # v4.6.0 + uses: actions/upload-artifact@330a01c490aca151604b8cf639adc76d48f6c5d4 # v5.0.0 with: name: Bitwarden-Beta-${{ env._PACKAGE_VERSION }}-ia32-store.appx path: apps/desktop/dist/Bitwarden-Beta-${{ env._PACKAGE_VERSION }}-ia32-store.appx @@ -900,7 +900,7 @@ jobs: - name: Upload NSIS ia32 artifact if: ${{ needs.setup.outputs.has_secrets == 'true' }} - uses: actions/upload-artifact@65c4c4a1ddee5b72f698fdd19549f0f0fb45cf08 # v4.6.0 + uses: actions/upload-artifact@330a01c490aca151604b8cf639adc76d48f6c5d4 # v5.0.0 with: name: bitwarden-beta-${{ env._PACKAGE_VERSION }}-ia32.nsis.7z path: apps/desktop/dist/nsis-web/bitwarden-beta-${{ env._PACKAGE_VERSION }}-ia32.nsis.7z @@ -908,7 +908,7 @@ jobs: - name: Upload appx x64 artifact if: ${{ needs.setup.outputs.has_secrets == 'true' }} - uses: actions/upload-artifact@65c4c4a1ddee5b72f698fdd19549f0f0fb45cf08 # v4.6.0 + uses: actions/upload-artifact@330a01c490aca151604b8cf639adc76d48f6c5d4 # v5.0.0 with: name: Bitwarden-Beta-${{ env._PACKAGE_VERSION }}-x64.appx path: apps/desktop/dist/Bitwarden-Beta-${{ env._PACKAGE_VERSION }}-x64.appx @@ -916,7 +916,7 @@ jobs: - name: Upload store appx x64 artifact if: ${{ needs.setup.outputs.has_secrets == 'true' }} - uses: actions/upload-artifact@65c4c4a1ddee5b72f698fdd19549f0f0fb45cf08 # v4.6.0 + uses: actions/upload-artifact@330a01c490aca151604b8cf639adc76d48f6c5d4 # v5.0.0 with: name: Bitwarden-Beta-${{ env._PACKAGE_VERSION }}-x64-store.appx path: apps/desktop/dist/Bitwarden-Beta-${{ env._PACKAGE_VERSION }}-x64-store.appx @@ -924,7 +924,7 @@ jobs: - name: Upload NSIS x64 artifact if: ${{ needs.setup.outputs.has_secrets == 'true' }} - uses: actions/upload-artifact@65c4c4a1ddee5b72f698fdd19549f0f0fb45cf08 # v4.6.0 + uses: actions/upload-artifact@330a01c490aca151604b8cf639adc76d48f6c5d4 # v5.0.0 with: name: bitwarden-beta-${{ env._PACKAGE_VERSION }}-x64.nsis.7z path: apps/desktop/dist/nsis-web/bitwarden-beta-${{ env._PACKAGE_VERSION }}-x64.nsis.7z @@ -932,7 +932,7 @@ jobs: - name: Upload appx ARM64 artifact if: ${{ needs.setup.outputs.has_secrets == 'true' }} - uses: actions/upload-artifact@65c4c4a1ddee5b72f698fdd19549f0f0fb45cf08 # v4.6.0 + uses: actions/upload-artifact@330a01c490aca151604b8cf639adc76d48f6c5d4 # v5.0.0 with: name: Bitwarden-Beta-${{ env._PACKAGE_VERSION }}-arm64.appx path: apps/desktop/dist/Bitwarden-Beta-${{ env._PACKAGE_VERSION }}-arm64.appx @@ -940,7 +940,7 @@ jobs: - name: Upload store appx ARM64 artifact if: ${{ needs.setup.outputs.has_secrets == 'true' }} - uses: actions/upload-artifact@65c4c4a1ddee5b72f698fdd19549f0f0fb45cf08 # v4.6.0 + uses: actions/upload-artifact@330a01c490aca151604b8cf639adc76d48f6c5d4 # v5.0.0 with: name: Bitwarden-Beta-${{ env._PACKAGE_VERSION }}-arm64-store.appx path: apps/desktop/dist/Bitwarden-Beta-${{ env._PACKAGE_VERSION }}-arm64-store.appx @@ -948,7 +948,7 @@ jobs: - name: Upload NSIS ARM64 artifact if: ${{ needs.setup.outputs.has_secrets == 'true' }} - uses: actions/upload-artifact@65c4c4a1ddee5b72f698fdd19549f0f0fb45cf08 # v4.6.0 + uses: actions/upload-artifact@330a01c490aca151604b8cf639adc76d48f6c5d4 # v5.0.0 with: name: bitwarden-beta-${{ env._PACKAGE_VERSION }}-arm64.nsis.7z path: apps/desktop/dist/nsis-web/bitwarden-beta-${{ env._PACKAGE_VERSION }}-arm64.nsis.7z @@ -956,7 +956,7 @@ jobs: - name: Upload auto-update artifact if: ${{ needs.setup.outputs.has_secrets == 'true' }} - uses: actions/upload-artifact@65c4c4a1ddee5b72f698fdd19549f0f0fb45cf08 # v4.6.0 + uses: actions/upload-artifact@330a01c490aca151604b8cf639adc76d48f6c5d4 # v5.0.0 with: name: latest-beta.yml path: apps/desktop/dist/nsis-web/latest-beta.yml @@ -1408,7 +1408,7 @@ jobs: run: npm run build - name: Download Browser artifact - uses: actions/download-artifact@634f93cb2916e3fdff6788551b99b062d0335ce0 # v5.0.0 + uses: actions/download-artifact@018cc2cf5baa6db3ef3c5f8a56943fffe632ef53 # v6.0.0 with: path: ${{ github.workspace }}/browser-build-artifacts @@ -1441,28 +1441,28 @@ jobs: run: npm run pack:mac - name: Upload .zip artifact - uses: actions/upload-artifact@65c4c4a1ddee5b72f698fdd19549f0f0fb45cf08 # v4.6.0 + uses: actions/upload-artifact@330a01c490aca151604b8cf639adc76d48f6c5d4 # v5.0.0 with: name: Bitwarden-${{ env._PACKAGE_VERSION }}-universal-mac.zip path: apps/desktop/dist/Bitwarden-${{ env._PACKAGE_VERSION }}-universal-mac.zip if-no-files-found: error - name: Upload .dmg artifact - uses: actions/upload-artifact@65c4c4a1ddee5b72f698fdd19549f0f0fb45cf08 # v4.6.0 + uses: actions/upload-artifact@330a01c490aca151604b8cf639adc76d48f6c5d4 # v5.0.0 with: name: Bitwarden-${{ env._PACKAGE_VERSION }}-universal.dmg path: apps/desktop/dist/Bitwarden-${{ env._PACKAGE_VERSION }}-universal.dmg if-no-files-found: error - name: Upload .dmg blockmap artifact - uses: actions/upload-artifact@65c4c4a1ddee5b72f698fdd19549f0f0fb45cf08 # v4.6.0 + uses: actions/upload-artifact@330a01c490aca151604b8cf639adc76d48f6c5d4 # v5.0.0 with: name: Bitwarden-${{ env._PACKAGE_VERSION }}-universal.dmg.blockmap path: apps/desktop/dist/Bitwarden-${{ env._PACKAGE_VERSION }}-universal.dmg.blockmap if-no-files-found: error - name: Upload auto-update artifact - uses: actions/upload-artifact@65c4c4a1ddee5b72f698fdd19549f0f0fb45cf08 # v4.6.0 + uses: actions/upload-artifact@330a01c490aca151604b8cf639adc76d48f6c5d4 # v5.0.0 with: name: ${{ needs.setup.outputs.release_channel }}-mac.yml path: apps/desktop/dist/${{ needs.setup.outputs.release_channel }}-mac.yml @@ -1688,7 +1688,7 @@ jobs: run: npm run build - name: Download Browser artifact - uses: actions/download-artifact@634f93cb2916e3fdff6788551b99b062d0335ce0 # v5.0.0 + uses: actions/download-artifact@018cc2cf5baa6db3ef3c5f8a56943fffe632ef53 # v6.0.0 with: path: ${{ github.workspace }}/browser-build-artifacts @@ -1731,14 +1731,14 @@ jobs: $buildInfo | ConvertTo-Json | Set-Content -Path dist/macos-build-number.json - name: Upload MacOS App Store build number artifact - uses: actions/upload-artifact@65c4c4a1ddee5b72f698fdd19549f0f0fb45cf08 # v4.6.0 + uses: actions/upload-artifact@330a01c490aca151604b8cf639adc76d48f6c5d4 # v5.0.0 with: name: macos-build-number.json path: apps/desktop/dist/macos-build-number.json if-no-files-found: error - name: Upload .pkg artifact - uses: actions/upload-artifact@65c4c4a1ddee5b72f698fdd19549f0f0fb45cf08 # v4.6.0 + uses: actions/upload-artifact@330a01c490aca151604b8cf639adc76d48f6c5d4 # v5.0.0 with: name: Bitwarden-${{ env._PACKAGE_VERSION }}-universal.pkg path: apps/desktop/dist/mas-universal/Bitwarden-${{ env._PACKAGE_VERSION }}-universal.pkg diff --git a/.github/workflows/build-web.yml b/.github/workflows/build-web.yml index 89dd684c5f..caf806af9f 100644 --- a/.github/workflows/build-web.yml +++ b/.github/workflows/build-web.yml @@ -307,7 +307,7 @@ jobs: zip -r web-$_VERSION-${{ matrix.artifact_name }}.zip build - name: Upload ${{ matrix.artifact_name }} artifact - uses: actions/upload-artifact@65c4c4a1ddee5b72f698fdd19549f0f0fb45cf08 # v4.6.0 + uses: actions/upload-artifact@330a01c490aca151604b8cf639adc76d48f6c5d4 # v5.0.0 with: name: web-${{ env._VERSION }}-${{ matrix.artifact_name }}.zip path: apps/web/web-${{ env._VERSION }}-${{ matrix.artifact_name }}.zip diff --git a/.github/workflows/test.yml b/.github/workflows/test.yml index ed967e63b5..f471826355 100644 --- a/.github/workflows/test.yml +++ b/.github/workflows/test.yml @@ -74,7 +74,7 @@ jobs: uses: codecov/test-results-action@47f89e9acb64b76debcd5ea40642d25a4adced9f # v1.1.1 - name: Upload test coverage - uses: actions/upload-artifact@65c4c4a1ddee5b72f698fdd19549f0f0fb45cf08 # v4.6.0 + uses: actions/upload-artifact@330a01c490aca151604b8cf639adc76d48f6c5d4 # v5.0.0 with: name: jest-coverage path: ./coverage/lcov.info @@ -160,7 +160,7 @@ jobs: run: cargo llvm-cov --all-features --lcov --output-path lcov.info --workspace --no-cfg-coverage - name: Upload test coverage - uses: actions/upload-artifact@65c4c4a1ddee5b72f698fdd19549f0f0fb45cf08 # v4.6.0 + uses: actions/upload-artifact@330a01c490aca151604b8cf639adc76d48f6c5d4 # v5.0.0 with: name: rust-coverage path: ./apps/desktop/desktop_native/lcov.info @@ -178,13 +178,13 @@ jobs: persist-credentials: false - name: Download jest coverage - uses: actions/download-artifact@634f93cb2916e3fdff6788551b99b062d0335ce0 # v5.0.0 + uses: actions/download-artifact@018cc2cf5baa6db3ef3c5f8a56943fffe632ef53 # v6.0.0 with: name: jest-coverage path: ./ - name: Download rust coverage - uses: actions/download-artifact@634f93cb2916e3fdff6788551b99b062d0335ce0 # v5.0.0 + uses: actions/download-artifact@018cc2cf5baa6db3ef3c5f8a56943fffe632ef53 # v6.0.0 with: name: rust-coverage path: ./apps/desktop/desktop_native From de42cf303fd3a567463e474996a9917b57594805 Mon Sep 17 00:00:00 2001 From: Alex Morask <144709477+amorask-bitwarden@users.noreply.github.com> Date: Wed, 19 Nov 2025 12:57:00 -0600 Subject: [PATCH 28/52] [PM-27925] Refactor `StripeService` to allow more than one instance (#17467) * Refactor StripeService to allow more than one instance per scope * Fix linting issue * Claude's feedback --- .../settings/create-organization.component.ts | 15 +- .../enter-payment-method.component.ts | 154 ++-- .../billing/services/stripe.service.spec.ts | 797 ++++++++++++++++++ .../app/billing/services/stripe.service.ts | 259 ++++-- 4 files changed, 1088 insertions(+), 137 deletions(-) create mode 100644 apps/web/src/app/billing/services/stripe.service.spec.ts diff --git a/apps/web/src/app/admin-console/settings/create-organization.component.ts b/apps/web/src/app/admin-console/settings/create-organization.component.ts index 45ce89c0e3..78398fd889 100644 --- a/apps/web/src/app/admin-console/settings/create-organization.component.ts +++ b/apps/web/src/app/admin-console/settings/create-organization.component.ts @@ -1,8 +1,8 @@ // FIXME: Update this file to be type safe and remove this and next line // @ts-strict-ignore -import { Component, OnInit } from "@angular/core"; -import { takeUntilDestroyed } from "@angular/core/rxjs-interop"; +import { Component, OnDestroy, OnInit } from "@angular/core"; import { ActivatedRoute } from "@angular/router"; +import { Subject, takeUntil } from "rxjs"; import { first } from "rxjs/operators"; import { PlanType, ProductTierType, ProductType } from "@bitwarden/common/billing/enums"; @@ -19,7 +19,7 @@ import { SharedModule } from "../../shared"; templateUrl: "create-organization.component.html", imports: [SharedModule, OrganizationPlansComponent, HeaderModule], }) -export class CreateOrganizationComponent implements OnInit { +export class CreateOrganizationComponent implements OnInit, OnDestroy { protected secretsManager = false; protected plan: PlanType = PlanType.Free; protected productTier: ProductTierType = ProductTierType.Free; @@ -29,6 +29,8 @@ export class CreateOrganizationComponent implements OnInit { private configService: ConfigService, ) {} + private destroy$ = new Subject(); + async ngOnInit(): Promise { const milestone3FeatureEnabled = await this.configService.getFeatureFlag( FeatureFlag.PM26462_Milestone_3, @@ -37,7 +39,7 @@ export class CreateOrganizationComponent implements OnInit { ? PlanType.FamiliesAnnually : PlanType.FamiliesAnnually2025; - this.route.queryParams.pipe(first(), takeUntilDestroyed()).subscribe((qParams) => { + this.route.queryParams.pipe(first(), takeUntil(this.destroy$)).subscribe((qParams) => { if (qParams.plan === "families" || qParams.productTier == ProductTierType.Families) { this.plan = familyPlan; this.productTier = ProductTierType.Families; @@ -61,4 +63,9 @@ export class CreateOrganizationComponent implements OnInit { this.secretsManager = qParams.product == ProductType.SecretsManager; }); } + + ngOnDestroy() { + this.destroy$.next(); + this.destroy$.complete(); + } } diff --git a/apps/web/src/app/billing/payment/components/enter-payment-method.component.ts b/apps/web/src/app/billing/payment/components/enter-payment-method.component.ts index 5448f03aa5..9e7b870579 100644 --- a/apps/web/src/app/billing/payment/components/enter-payment-method.component.ts +++ b/apps/web/src/app/billing/payment/components/enter-payment-method.component.ts @@ -1,9 +1,10 @@ -import { Component, Input, OnInit } from "@angular/core"; +import { ChangeDetectionStrategy, Component, input, OnDestroy, OnInit } from "@angular/core"; import { FormControl, FormGroup, Validators } from "@angular/forms"; import { map, Observable, of, startWith, Subject, takeUntil } from "rxjs"; import { I18nService } from "@bitwarden/common/platform/abstractions/i18n.service"; import { LogService } from "@bitwarden/common/platform/abstractions/log.service"; +import { Utils } from "@bitwarden/common/platform/misc/utils"; import { PopoverModule, ToastService } from "@bitwarden/components"; import { SharedModule } from "../../../shared"; @@ -34,18 +35,17 @@ type PaymentMethodFormGroup = FormGroup<{ }>; }>; -// FIXME(https://bitwarden.atlassian.net/browse/CL-764): Migrate to OnPush -// eslint-disable-next-line @angular-eslint/prefer-on-push-component-change-detection @Component({ selector: "app-enter-payment-method", + changeDetection: ChangeDetectionStrategy.OnPush, template: ` - @let showBillingDetails = includeBillingAddress && selected !== "payPal"; -
    + @let showBillingDetails = includeBillingAddress() && selected !== "payPal"; + @if (showBillingDetails) {
    {{ "paymentMethod" | i18n }}
    }
    - + @@ -60,7 +60,7 @@ type PaymentMethodFormGroup = FormGroup<{ } - @if (showPayPal) { + @if (showPayPal()) { @@ -68,7 +68,7 @@ type PaymentMethodFormGroup = FormGroup<{ } - @if (showAccountCredit) { + @if (showAccountCredit()) { @@ -82,10 +82,10 @@ type PaymentMethodFormGroup = FormGroup<{ @case ("card") {
    - + {{ "cardNumberLabel" | i18n }} -
    +
    - + {{ "expiration" | i18n }} -
    +
    - + {{ "securityCodeSlashCVV" | i18n }}
    } @@ -131,7 +131,7 @@ type PaymentMethodFormGroup = FormGroup<{ bitInput id="routingNumber" type="text" - [formControl]="group.controls.bankAccount.controls.routingNumber" + [formControl]="group().controls.bankAccount.controls.routingNumber" required /> @@ -141,7 +141,7 @@ type PaymentMethodFormGroup = FormGroup<{ bitInput id="accountNumber" type="text" - [formControl]="group.controls.bankAccount.controls.accountNumber" + [formControl]="group().controls.bankAccount.controls.accountNumber" required /> @@ -151,7 +151,7 @@ type PaymentMethodFormGroup = FormGroup<{ id="accountHolderName" bitInput type="text" - [formControl]="group.controls.bankAccount.controls.accountHolderName" + [formControl]="group().controls.bankAccount.controls.accountHolderName" required /> @@ -159,7 +159,7 @@ type PaymentMethodFormGroup = FormGroup<{ {{ "bankAccountType" | i18n }} @@ -186,7 +186,7 @@ type PaymentMethodFormGroup = FormGroup<{ } @case ("accountCredit") { - @if (hasEnoughAccountCredit) { + @if (hasEnoughAccountCredit()) { {{ "makeSureEnoughCredit" | i18n }} @@ -204,7 +204,7 @@ type PaymentMethodFormGroup = FormGroup<{
    {{ "country" | i18n }} - + @for (selectableCountry of selectableCountries; track selectableCountry.value) { @@ -233,26 +233,15 @@ type PaymentMethodFormGroup = FormGroup<{ standalone: true, imports: [BillingServicesModule, PaymentLabelComponent, PopoverModule, SharedModule], }) -export class EnterPaymentMethodComponent implements OnInit { - // FIXME(https://bitwarden.atlassian.net/browse/CL-903): Migrate to Signals - // eslint-disable-next-line @angular-eslint/prefer-signals - @Input({ required: true }) group!: PaymentMethodFormGroup; +export class EnterPaymentMethodComponent implements OnInit, OnDestroy { + protected readonly instanceId = Utils.newGuid(); - // FIXME(https://bitwarden.atlassian.net/browse/CL-903): Migrate to Signals - // eslint-disable-next-line @angular-eslint/prefer-signals - @Input() private showBankAccount = true; - // FIXME(https://bitwarden.atlassian.net/browse/CL-903): Migrate to Signals - // eslint-disable-next-line @angular-eslint/prefer-signals - @Input() showPayPal = true; - // FIXME(https://bitwarden.atlassian.net/browse/CL-903): Migrate to Signals - // eslint-disable-next-line @angular-eslint/prefer-signals - @Input() showAccountCredit = false; - // FIXME(https://bitwarden.atlassian.net/browse/CL-903): Migrate to Signals - // eslint-disable-next-line @angular-eslint/prefer-signals - @Input() hasEnoughAccountCredit = true; - // FIXME(https://bitwarden.atlassian.net/browse/CL-903): Migrate to Signals - // eslint-disable-next-line @angular-eslint/prefer-signals - @Input() includeBillingAddress = false; + readonly group = input.required(); + protected readonly showBankAccount = input(true); + readonly showPayPal = input(true); + readonly showAccountCredit = input(false); + readonly hasEnoughAccountCredit = input(true); + readonly includeBillingAddress = input(false); protected showBankAccount$!: Observable; protected selectableCountries = selectableCountries; @@ -269,57 +258,62 @@ export class EnterPaymentMethodComponent implements OnInit { ngOnInit() { this.stripeService.loadStripe( + this.instanceId, { - cardNumber: "#stripe-card-number", - cardExpiry: "#stripe-card-expiry", - cardCvc: "#stripe-card-cvc", + cardNumber: `#stripe-card-number-${this.instanceId}`, + cardExpiry: `#stripe-card-expiry-${this.instanceId}`, + cardCvc: `#stripe-card-cvc-${this.instanceId}`, }, true, ); - if (this.showPayPal) { + if (this.showPayPal()) { this.braintreeService.loadBraintree("#braintree-container", false); } - if (!this.includeBillingAddress) { - this.showBankAccount$ = of(this.showBankAccount); - this.group.controls.billingAddress.disable(); + if (!this.includeBillingAddress()) { + this.showBankAccount$ = of(this.showBankAccount()); + this.group().controls.billingAddress.disable(); } else { - this.group.controls.billingAddress.patchValue({ + this.group().controls.billingAddress.patchValue({ country: "US", }); - this.showBankAccount$ = this.group.controls.billingAddress.controls.country.valueChanges.pipe( - startWith(this.group.controls.billingAddress.controls.country.value), - map((country) => this.showBankAccount && country === "US"), - ); + this.showBankAccount$ = + this.group().controls.billingAddress.controls.country.valueChanges.pipe( + startWith(this.group().controls.billingAddress.controls.country.value), + map((country) => this.showBankAccount() && country === "US"), + ); } - this.group.controls.type.valueChanges - .pipe(startWith(this.group.controls.type.value), takeUntil(this.destroy$)) + this.group() + .controls.type.valueChanges.pipe( + startWith(this.group().controls.type.value), + takeUntil(this.destroy$), + ) .subscribe((selected) => { if (selected === "bankAccount") { - this.group.controls.bankAccount.enable(); - if (this.includeBillingAddress) { - this.group.controls.billingAddress.enable(); + this.group().controls.bankAccount.enable(); + if (this.includeBillingAddress()) { + this.group().controls.billingAddress.enable(); } } else { switch (selected) { case "card": { - this.stripeService.mountElements(); - if (this.includeBillingAddress) { - this.group.controls.billingAddress.enable(); + this.stripeService.mountElements(this.instanceId); + if (this.includeBillingAddress()) { + this.group().controls.billingAddress.enable(); } break; } case "payPal": { this.braintreeService.createDropin(); - if (this.includeBillingAddress) { - this.group.controls.billingAddress.disable(); + if (this.includeBillingAddress()) { + this.group().controls.billingAddress.disable(); } break; } } - this.group.controls.bankAccount.disable(); + this.group().controls.bankAccount.disable(); } }); @@ -330,22 +324,28 @@ export class EnterPaymentMethodComponent implements OnInit { }); } + ngOnDestroy() { + this.stripeService.unloadStripe(this.instanceId); + this.destroy$.next(); + this.destroy$.complete(); + } + select = (paymentMethod: PaymentMethodOption) => - this.group.controls.type.patchValue(paymentMethod); + this.group().controls.type.patchValue(paymentMethod); tokenize = async (): Promise => { const exchange = async (paymentMethod: TokenizablePaymentMethod) => { switch (paymentMethod) { case "bankAccount": { - this.group.controls.bankAccount.markAllAsTouched(); - if (!this.group.controls.bankAccount.valid) { + this.group().controls.bankAccount.markAllAsTouched(); + if (!this.group().controls.bankAccount.valid) { throw new Error("Attempted to tokenize invalid bank account information."); } - const bankAccount = this.group.controls.bankAccount.getRawValue(); + const bankAccount = this.group().controls.bankAccount.getRawValue(); const clientSecret = await this.stripeService.createSetupIntent("bankAccount"); - const billingDetails = this.group.controls.billingAddress.enabled - ? this.group.controls.billingAddress.getRawValue() + const billingDetails = this.group().controls.billingAddress.enabled + ? this.group().controls.billingAddress.getRawValue() : undefined; return await this.stripeService.setupBankAccountPaymentMethod( clientSecret, @@ -355,10 +355,14 @@ export class EnterPaymentMethodComponent implements OnInit { } case "card": { const clientSecret = await this.stripeService.createSetupIntent("card"); - const billingDetails = this.group.controls.billingAddress.enabled - ? this.group.controls.billingAddress.getRawValue() + const billingDetails = this.group().controls.billingAddress.enabled + ? this.group().controls.billingAddress.getRawValue() : undefined; - return this.stripeService.setupCardPaymentMethod(clientSecret, billingDetails); + return this.stripeService.setupCardPaymentMethod( + this.instanceId, + clientSecret, + billingDetails, + ); } case "payPal": { return this.braintreeService.requestPaymentMethod(); @@ -410,15 +414,15 @@ export class EnterPaymentMethodComponent implements OnInit { validate = (): boolean => { if (this.selected === "bankAccount") { - this.group.controls.bankAccount.markAllAsTouched(); - return this.group.controls.bankAccount.valid; + this.group().controls.bankAccount.markAllAsTouched(); + return this.group().controls.bankAccount.valid; } return true; }; get selected(): PaymentMethodOption { - return this.group.value.type!; + return this.group().value.type!; } static getFormGroup = (): PaymentMethodFormGroup => diff --git a/apps/web/src/app/billing/services/stripe.service.spec.ts b/apps/web/src/app/billing/services/stripe.service.spec.ts new file mode 100644 index 0000000000..983aeb266a --- /dev/null +++ b/apps/web/src/app/billing/services/stripe.service.spec.ts @@ -0,0 +1,797 @@ +import { mock, MockProxy } from "jest-mock-extended"; + +import { ApiService } from "@bitwarden/common/abstractions/api.service"; +import { BankAccount } from "@bitwarden/common/billing/models/domain"; +import { LogService } from "@bitwarden/common/platform/abstractions/log.service"; + +import { StripeService } from "./stripe.service"; + +// Extend Window interface to include Stripe +declare global { + interface Window { + Stripe: any; + } +} + +describe("StripeService", () => { + let service: StripeService; + let apiService: MockProxy; + let logService: MockProxy; + + // Stripe SDK mocks + let mockStripeInstance: any; + let mockElements: any; + let mockCardNumber: any; + let mockCardExpiry: any; + let mockCardCvc: any; + + // DOM mocks + let mockScript: HTMLScriptElement; + let mockIframe: HTMLIFrameElement; + + beforeEach(() => { + jest.useFakeTimers(); + + // Setup service dependency mocks + apiService = mock(); + logService = mock(); + + // Setup Stripe element mocks + mockCardNumber = { + mount: jest.fn(), + unmount: jest.fn(), + }; + mockCardExpiry = { + mount: jest.fn(), + unmount: jest.fn(), + }; + mockCardCvc = { + mount: jest.fn(), + unmount: jest.fn(), + }; + + // Setup Stripe Elements mock + mockElements = { + create: jest.fn((type: string) => { + switch (type) { + case "cardNumber": + return mockCardNumber; + case "cardExpiry": + return mockCardExpiry; + case "cardCvc": + return mockCardCvc; + default: + return null; + } + }), + getElement: jest.fn((type: string) => { + switch (type) { + case "cardNumber": + return mockCardNumber; + case "cardExpiry": + return mockCardExpiry; + case "cardCvc": + return mockCardCvc; + default: + return null; + } + }), + }; + + // Setup Stripe instance mock + mockStripeInstance = { + elements: jest.fn(() => mockElements), + confirmCardSetup: jest.fn(), + confirmUsBankAccountSetup: jest.fn(), + }; + + // Setup window.Stripe mock + window.Stripe = jest.fn(() => mockStripeInstance); + + // Setup DOM mocks + mockScript = { + id: "", + src: "", + onload: null, + onerror: null, + } as any; + + mockIframe = { + src: "https://js.stripe.com/v3/", + remove: jest.fn(), + } as any; + + jest.spyOn(window.document, "createElement").mockReturnValue(mockScript); + jest.spyOn(window.document, "getElementById").mockReturnValue(null); + jest.spyOn(window.document.head, "appendChild").mockReturnValue(mockScript); + jest.spyOn(window.document.head, "removeChild").mockImplementation(() => mockScript); + jest.spyOn(window.document, "querySelectorAll").mockReturnValue([mockIframe] as any); + + // Mock getComputedStyle + jest.spyOn(window, "getComputedStyle").mockReturnValue({ + getPropertyValue: (prop: string) => { + const props: Record = { + "--color-text-main": "0, 0, 0", + "--color-text-muted": "128, 128, 128", + "--color-danger-600": "220, 38, 38", + }; + return props[prop] || ""; + }, + } as any); + + // Create service instance + service = new StripeService(apiService, logService); + }); + + afterEach(() => { + jest.clearAllTimers(); + jest.useRealTimers(); + jest.restoreAllMocks(); + }); + + // Helper function to trigger script load + const triggerScriptLoad = () => { + if (mockScript.onload) { + mockScript.onload(new Event("load")); + } + }; + + // Helper function to advance timers and flush promises + const advanceTimersAndFlush = async (ms: number) => { + jest.advanceTimersByTime(ms); + await Promise.resolve(); + }; + + describe("createSetupIntent", () => { + it("should call API with correct path for card payment", async () => { + apiService.send.mockResolvedValue("client_secret_card_123"); + + const result = await service.createSetupIntent("card"); + + expect(apiService.send).toHaveBeenCalledWith("POST", "/setup-intent/card", null, true, true); + expect(result).toBe("client_secret_card_123"); + }); + + it("should call API with correct path for bank account payment", async () => { + apiService.send.mockResolvedValue("client_secret_bank_456"); + + const result = await service.createSetupIntent("bankAccount"); + + expect(apiService.send).toHaveBeenCalledWith( + "POST", + "/setup-intent/bank-account", + null, + true, + true, + ); + expect(result).toBe("client_secret_bank_456"); + }); + + it("should return client secret from API response", async () => { + const expectedSecret = "seti_1234567890_secret_abcdefg"; + apiService.send.mockResolvedValue(expectedSecret); + + const result = await service.createSetupIntent("card"); + + expect(result).toBe(expectedSecret); + }); + + it("should propagate API errors", async () => { + const error = new Error("API error"); + apiService.send.mockRejectedValue(error); + + await expect(service.createSetupIntent("card")).rejects.toThrow("API error"); + }); + }); + + describe("loadStripe - initial load", () => { + const instanceId = "test-instance-1"; + const elementIds = { + cardNumber: "#card-number", + cardExpiry: "#card-expiry", + cardCvc: "#card-cvc", + }; + + it("should create script element with correct attributes", () => { + service.loadStripe(instanceId, elementIds, false); + + expect(window.document.createElement).toHaveBeenCalledWith("script"); + expect(mockScript.id).toBe("stripe-script"); + expect(mockScript.src).toBe("https://js.stripe.com/v3?advancedFraudSignals=false"); + }); + + it("should append script to document head", () => { + service.loadStripe(instanceId, elementIds, false); + + expect(window.document.head.appendChild).toHaveBeenCalledWith(mockScript); + }); + + it("should initialize Stripe client on script load", async () => { + service.loadStripe(instanceId, elementIds, false); + + triggerScriptLoad(); + await advanceTimersAndFlush(0); + + expect(window.Stripe).toHaveBeenCalledWith(process.env.STRIPE_KEY); + }); + + it("should create Elements instance and store in Map", async () => { + service.loadStripe(instanceId, elementIds, false); + + triggerScriptLoad(); + await advanceTimersAndFlush(50); + + expect(mockStripeInstance.elements).toHaveBeenCalled(); + expect(service["instances"].size).toBe(1); + expect(service["instances"].get(instanceId)).toBeDefined(); + }); + + it("should increment instanceCount", async () => { + service.loadStripe(instanceId, elementIds, false); + + triggerScriptLoad(); + await advanceTimersAndFlush(50); + + expect(service["instanceCount"]).toBe(1); + }); + }); + + describe("loadStripe - already loaded", () => { + const instanceId1 = "instance-1"; + const instanceId2 = "instance-2"; + const elementIds = { + cardNumber: "#card-number", + cardExpiry: "#card-expiry", + cardCvc: "#card-cvc", + }; + + beforeEach(async () => { + // Load first instance to initialize Stripe + service.loadStripe(instanceId1, elementIds, false); + triggerScriptLoad(); + await advanceTimersAndFlush(100); + }); + + it("should not create new script if already loaded", () => { + jest.clearAllMocks(); + + service.loadStripe(instanceId2, elementIds, false); + + expect(window.document.createElement).not.toHaveBeenCalled(); + expect(window.document.head.appendChild).not.toHaveBeenCalled(); + }); + + it("should immediately initialize instance when script loaded", async () => { + service.loadStripe(instanceId2, elementIds, false); + await advanceTimersAndFlush(50); + + expect(service["instances"].size).toBe(2); + expect(service["instances"].get(instanceId2)).toBeDefined(); + }); + + it("should increment instanceCount correctly", async () => { + expect(service["instanceCount"]).toBe(1); + + service.loadStripe(instanceId2, elementIds, false); + await advanceTimersAndFlush(50); + + expect(service["instanceCount"]).toBe(2); + }); + }); + + describe("loadStripe - concurrent calls", () => { + const elementIds = { + cardNumber: "#card-number", + cardExpiry: "#card-expiry", + cardCvc: "#card-cvc", + }; + + it("should handle multiple loadStripe calls sequentially", async () => { + // Test practical scenario: load instances one after another + service.loadStripe("instance-1", elementIds, false); + triggerScriptLoad(); + await advanceTimersAndFlush(100); + + service.loadStripe("instance-2", elementIds, false); + await advanceTimersAndFlush(100); + + service.loadStripe("instance-3", elementIds, false); + await advanceTimersAndFlush(100); + + // All instances should be initialized + expect(service["instances"].size).toBe(3); + expect(service["instanceCount"]).toBe(3); + expect(service["instances"].get("instance-1")).toBeDefined(); + expect(service["instances"].get("instance-2")).toBeDefined(); + expect(service["instances"].get("instance-3")).toBeDefined(); + }); + + it("should share Stripe client across instances", async () => { + // Load first instance + service.loadStripe("instance-1", elementIds, false); + triggerScriptLoad(); + await advanceTimersAndFlush(100); + + const stripeClientAfterFirst = service["stripe"]; + expect(stripeClientAfterFirst).toBeDefined(); + + // Load second instance + service.loadStripe("instance-2", elementIds, false); + await advanceTimersAndFlush(100); + + // Should reuse the same Stripe client + expect(service["stripe"]).toBe(stripeClientAfterFirst); + expect(service["instances"].size).toBe(2); + }); + }); + + describe("mountElements - success path", () => { + const instanceId = "mount-test-instance"; + const elementIds = { + cardNumber: "#card-number-mount", + cardExpiry: "#card-expiry-mount", + cardCvc: "#card-cvc-mount", + }; + + beforeEach(async () => { + service.loadStripe(instanceId, elementIds, false); + triggerScriptLoad(); + await advanceTimersAndFlush(100); + }); + + it("should mount all three card elements to DOM", async () => { + service.mountElements(instanceId); + await advanceTimersAndFlush(100); + + expect(mockCardNumber.mount).toHaveBeenCalledWith("#card-number-mount"); + expect(mockCardExpiry.mount).toHaveBeenCalledWith("#card-expiry-mount"); + expect(mockCardCvc.mount).toHaveBeenCalledWith("#card-cvc-mount"); + }); + + it("should use correct element IDs from instance", async () => { + const customIds = { + cardNumber: "#custom-card", + cardExpiry: "#custom-expiry", + cardCvc: "#custom-cvc", + }; + + service.loadStripe("custom-instance", customIds, false); + await advanceTimersAndFlush(100); + + service.mountElements("custom-instance"); + await advanceTimersAndFlush(100); + + expect(mockCardNumber.mount).toHaveBeenCalledWith("#custom-card"); + expect(mockCardExpiry.mount).toHaveBeenCalledWith("#custom-expiry"); + expect(mockCardCvc.mount).toHaveBeenCalledWith("#custom-cvc"); + }); + + it("should handle autoMount flag correctly", async () => { + const autoMountId = "auto-mount-instance"; + jest.clearAllMocks(); + + service.loadStripe(autoMountId, elementIds, true); + triggerScriptLoad(); + await advanceTimersAndFlush(150); + + // Should auto-mount without explicit call + expect(mockCardNumber.mount).toHaveBeenCalled(); + expect(mockCardExpiry.mount).toHaveBeenCalled(); + expect(mockCardCvc.mount).toHaveBeenCalled(); + }); + }); + + describe("mountElements - retry logic", () => { + const elementIds = { + cardNumber: "#card-number", + cardExpiry: "#card-expiry", + cardCvc: "#card-cvc", + }; + + it("should retry if instance not found", async () => { + service.mountElements("non-existent-instance"); + await advanceTimersAndFlush(100); + + expect(logService.warning).toHaveBeenCalledWith( + expect.stringContaining("Stripe instance non-existent-instance not found"), + ); + }); + + it("should log error after 10 failed attempts", async () => { + service.mountElements("non-existent-instance"); + + for (let i = 0; i < 10; i++) { + await advanceTimersAndFlush(100); + } + + expect(logService.error).toHaveBeenCalledWith( + expect.stringContaining("not found after 10 attempts"), + ); + }); + + it("should retry if elements not ready", async () => { + const instanceId = "retry-elements-instance"; + service.loadStripe(instanceId, elementIds, false); + triggerScriptLoad(); + await advanceTimersAndFlush(100); + + // Make elements temporarily unavailable + mockElements.getElement.mockReturnValueOnce(null); + mockElements.getElement.mockReturnValueOnce(null); + mockElements.getElement.mockReturnValueOnce(null); + + service.mountElements(instanceId); + await advanceTimersAndFlush(100); + + expect(logService.warning).toHaveBeenCalledWith( + expect.stringContaining("Some Stripe card elements"), + ); + }); + }); + + describe("setupCardPaymentMethod", () => { + const instanceId = "card-setup-instance"; + const clientSecret = "seti_card_secret_123"; + const elementIds = { + cardNumber: "#card-number", + cardExpiry: "#card-expiry", + cardCvc: "#card-cvc", + }; + + beforeEach(async () => { + service.loadStripe(instanceId, elementIds, false); + triggerScriptLoad(); + await advanceTimersAndFlush(100); + }); + + it("should call Stripe confirmCardSetup with correct parameters", async () => { + mockStripeInstance.confirmCardSetup.mockResolvedValue({ + setupIntent: { status: "succeeded", payment_method: "pm_card_123" }, + }); + + await service.setupCardPaymentMethod(instanceId, clientSecret); + + expect(mockStripeInstance.confirmCardSetup).toHaveBeenCalledWith(clientSecret, { + payment_method: { + card: mockCardNumber, + }, + }); + }); + + it("should include billing details when provided", async () => { + mockStripeInstance.confirmCardSetup.mockResolvedValue({ + setupIntent: { status: "succeeded", payment_method: "pm_card_123" }, + }); + + const billingDetails = { country: "US", postalCode: "12345" }; + await service.setupCardPaymentMethod(instanceId, clientSecret, billingDetails); + + expect(mockStripeInstance.confirmCardSetup).toHaveBeenCalledWith(clientSecret, { + payment_method: { + card: mockCardNumber, + billing_details: { + address: { + country: "US", + postal_code: "12345", + }, + }, + }, + }); + }); + + it("should throw error if instance not found", async () => { + await expect(service.setupCardPaymentMethod("non-existent", clientSecret)).rejects.toThrow( + "Payment method initialization failed. Please try again.", + ); + expect(logService.error).toHaveBeenCalledWith( + expect.stringContaining("Stripe instance non-existent not found"), + ); + }); + + it("should throw error if setup fails", async () => { + const error = { message: "Card declined" }; + mockStripeInstance.confirmCardSetup.mockResolvedValue({ error }); + + await expect(service.setupCardPaymentMethod(instanceId, clientSecret)).rejects.toEqual(error); + expect(logService.error).toHaveBeenCalledWith(error); + }); + + it("should throw error if status is not succeeded", async () => { + const error = { message: "Invalid status" }; + mockStripeInstance.confirmCardSetup.mockResolvedValue({ + setupIntent: { status: "requires_action" }, + error, + }); + + await expect(service.setupCardPaymentMethod(instanceId, clientSecret)).rejects.toEqual(error); + }); + + it("should return payment method ID on success", async () => { + mockStripeInstance.confirmCardSetup.mockResolvedValue({ + setupIntent: { status: "succeeded", payment_method: "pm_card_success_123" }, + }); + + const result = await service.setupCardPaymentMethod(instanceId, clientSecret); + + expect(result).toBe("pm_card_success_123"); + }); + }); + + describe("setupBankAccountPaymentMethod", () => { + const clientSecret = "seti_bank_secret_456"; + const bankAccount: BankAccount = { + accountHolderName: "John Doe", + routingNumber: "110000000", + accountNumber: "000123456789", + accountHolderType: "individual", + }; + + beforeEach(async () => { + // Initialize Stripe instance for bank account tests + service.loadStripe( + "bank-test-instance", + { + cardNumber: "#card", + cardExpiry: "#expiry", + cardCvc: "#cvc", + }, + false, + ); + triggerScriptLoad(); + await advanceTimersAndFlush(100); + }); + + it("should call Stripe confirmUsBankAccountSetup with bank details", async () => { + mockStripeInstance.confirmUsBankAccountSetup.mockResolvedValue({ + setupIntent: { status: "requires_action", payment_method: "pm_bank_123" }, + }); + + await service.setupBankAccountPaymentMethod(clientSecret, bankAccount); + + expect(mockStripeInstance.confirmUsBankAccountSetup).toHaveBeenCalledWith(clientSecret, { + payment_method: { + us_bank_account: { + routing_number: "110000000", + account_number: "000123456789", + account_holder_type: "individual", + }, + billing_details: { + name: "John Doe", + }, + }, + }); + }); + + it("should include billing address when provided", async () => { + mockStripeInstance.confirmUsBankAccountSetup.mockResolvedValue({ + setupIntent: { status: "requires_action", payment_method: "pm_bank_123" }, + }); + + const billingDetails = { country: "US", postalCode: "90210" }; + await service.setupBankAccountPaymentMethod(clientSecret, bankAccount, billingDetails); + + expect(mockStripeInstance.confirmUsBankAccountSetup).toHaveBeenCalledWith(clientSecret, { + payment_method: { + us_bank_account: { + routing_number: "110000000", + account_number: "000123456789", + account_holder_type: "individual", + }, + billing_details: { + name: "John Doe", + address: { + country: "US", + postal_code: "90210", + }, + }, + }, + }); + }); + + it("should omit billing address when not provided", async () => { + mockStripeInstance.confirmUsBankAccountSetup.mockResolvedValue({ + setupIntent: { status: "requires_action", payment_method: "pm_bank_123" }, + }); + + await service.setupBankAccountPaymentMethod(clientSecret, bankAccount); + + const call = mockStripeInstance.confirmUsBankAccountSetup.mock.calls[0][1]; + expect(call.payment_method.billing_details.address).toBeUndefined(); + }); + + it("should validate status is requires_action", async () => { + const error = { message: "Invalid status" }; + mockStripeInstance.confirmUsBankAccountSetup.mockResolvedValue({ + setupIntent: { status: "succeeded" }, + error, + }); + + await expect( + service.setupBankAccountPaymentMethod(clientSecret, bankAccount), + ).rejects.toEqual(error); + }); + + it("should return payment method ID on success", async () => { + mockStripeInstance.confirmUsBankAccountSetup.mockResolvedValue({ + setupIntent: { status: "requires_action", payment_method: "pm_bank_success_456" }, + }); + + const result = await service.setupBankAccountPaymentMethod(clientSecret, bankAccount); + + expect(result).toBe("pm_bank_success_456"); + }); + }); + + describe("unloadStripe - single instance", () => { + const instanceId = "unload-test-instance"; + const elementIds = { + cardNumber: "#card-number", + cardExpiry: "#card-expiry", + cardCvc: "#card-cvc", + }; + + beforeEach(async () => { + service.loadStripe(instanceId, elementIds, false); + triggerScriptLoad(); + await advanceTimersAndFlush(100); + }); + + it("should unmount all card elements", () => { + service.unloadStripe(instanceId); + + expect(mockCardNumber.unmount).toHaveBeenCalled(); + expect(mockCardExpiry.unmount).toHaveBeenCalled(); + expect(mockCardCvc.unmount).toHaveBeenCalled(); + }); + + it("should remove instance from Map", () => { + expect(service["instances"].has(instanceId)).toBe(true); + + service.unloadStripe(instanceId); + + expect(service["instances"].has(instanceId)).toBe(false); + }); + + it("should decrement instanceCount", () => { + expect(service["instanceCount"]).toBe(1); + + service.unloadStripe(instanceId); + + expect(service["instanceCount"]).toBe(0); + }); + + it("should remove script when last instance unloaded", () => { + jest.spyOn(window.document, "getElementById").mockReturnValue(mockScript); + + service.unloadStripe(instanceId); + + expect(window.document.head.removeChild).toHaveBeenCalledWith(mockScript); + }); + + it("should remove Stripe iframes after cleanup delay", async () => { + service.unloadStripe(instanceId); + + await advanceTimersAndFlush(500); + + expect(window.document.querySelectorAll).toHaveBeenCalledWith("iframe"); + expect(mockIframe.remove).toHaveBeenCalled(); + }); + }); + + describe("unloadStripe - multiple instances", () => { + const elementIds = { + cardNumber: "#card-number", + cardExpiry: "#card-expiry", + cardCvc: "#card-cvc", + }; + + beforeEach(async () => { + // Load first instance + service.loadStripe("instance-1", elementIds, false); + triggerScriptLoad(); + await advanceTimersAndFlush(100); + + // Load second instance (script already loaded) + service.loadStripe("instance-2", elementIds, false); + await advanceTimersAndFlush(100); + }); + + it("should not remove script when other instances exist", () => { + expect(service["instanceCount"]).toBe(2); + + service.unloadStripe("instance-1"); + + expect(service["instanceCount"]).toBe(1); + expect(window.document.head.removeChild).not.toHaveBeenCalled(); + }); + + it("should only cleanup specific instance", () => { + service.unloadStripe("instance-1"); + + expect(service["instances"].has("instance-1")).toBe(false); + expect(service["instances"].has("instance-2")).toBe(true); + }); + + it("should handle reference counting correctly", () => { + expect(service["instanceCount"]).toBe(2); + + service.unloadStripe("instance-1"); + expect(service["instanceCount"]).toBe(1); + + service.unloadStripe("instance-2"); + expect(service["instanceCount"]).toBe(0); + }); + }); + + describe("unloadStripe - edge cases", () => { + it("should handle unload of non-existent instance gracefully", () => { + expect(() => service.unloadStripe("non-existent")).not.toThrow(); + expect(service["instanceCount"]).toBe(0); + }); + + it("should handle duplicate unload calls", async () => { + const instanceId = "duplicate-unload"; + const elementIds = { + cardNumber: "#card-number", + cardExpiry: "#card-expiry", + cardCvc: "#card-cvc", + }; + + service.loadStripe(instanceId, elementIds, false); + triggerScriptLoad(); + await advanceTimersAndFlush(100); + + service.unloadStripe(instanceId); + expect(service["instanceCount"]).toBe(0); + + service.unloadStripe(instanceId); + expect(service["instanceCount"]).toBe(0); // Should not go negative + }); + + it("should catch and log element unmount errors", async () => { + const instanceId = "error-unmount"; + const elementIds = { + cardNumber: "#card-number", + cardExpiry: "#card-expiry", + cardCvc: "#card-cvc", + }; + + service.loadStripe(instanceId, elementIds, false); + triggerScriptLoad(); + await advanceTimersAndFlush(100); + + const unmountError = new Error("Unmount failed"); + mockCardNumber.unmount.mockImplementation(() => { + throw unmountError; + }); + + service.unloadStripe(instanceId); + + expect(logService.error).toHaveBeenCalledWith( + expect.stringContaining("Error unmounting Stripe elements"), + unmountError, + ); + }); + }); + + describe("element styling", () => { + it("should apply correct CSS custom properties", () => { + const options = service["getElementOptions"]("cardNumber"); + + expect(options.style.base.color).toBe("rgb(0, 0, 0)"); + expect(options.style.base["::placeholder"].color).toBe("rgb(128, 128, 128)"); + expect(options.style.invalid.color).toBe("rgb(0, 0, 0)"); + expect(options.style.invalid.borderColor).toBe("rgb(220, 38, 38)"); + }); + + it("should remove placeholder for cardNumber and cardCvc", () => { + const cardNumberOptions = service["getElementOptions"]("cardNumber"); + const cardCvcOptions = service["getElementOptions"]("cardCvc"); + const cardExpiryOptions = service["getElementOptions"]("cardExpiry"); + + expect(cardNumberOptions.placeholder).toBe(""); + expect(cardCvcOptions.placeholder).toBe(""); + expect(cardExpiryOptions.placeholder).toBeUndefined(); + }); + }); +}); diff --git a/apps/web/src/app/billing/services/stripe.service.ts b/apps/web/src/app/billing/services/stripe.service.ts index a2eb7cd98f..9aabab9beb 100644 --- a/apps/web/src/app/billing/services/stripe.service.ts +++ b/apps/web/src/app/billing/services/stripe.service.ts @@ -8,8 +8,6 @@ import { LogService } from "@bitwarden/common/platform/abstractions/log.service" import { BankAccountPaymentMethod, CardPaymentMethod } from "../payment/types"; -import { BillingServicesModule } from "./billing-services.module"; - type SetupBankAccountRequest = { payment_method: { us_bank_account: { @@ -39,15 +37,21 @@ type SetupCardRequest = { }; }; -@Injectable({ providedIn: BillingServicesModule }) +@Injectable({ providedIn: "root" }) export class StripeService { - private stripe: any; - private elements: any; - private elementIds: { - cardNumber: string; - cardExpiry: string; - cardCvc: string; - }; + // Shared/Global - One Stripe client for entire application + private stripe: any = null; + private stripeScriptLoaded = false; + private instanceCount = 0; + + // Per-Instance - Isolated Elements for each component + private instances = new Map< + string, + { + elements: any; + elementIds: { cardNumber: string; cardExpiry: string; cardCvc: string }; + } + >(); constructor( private apiService: ApiService, @@ -76,53 +80,121 @@ export class StripeService { * Loads [Stripe JS]{@link https://docs.stripe.com/js} in the element of the current page and mounts * Stripe credit card [elements]{@link https://docs.stripe.com/js/elements_object/create} into the HTML elements with the provided element IDS. * We do this to avoid having to load the Stripe JS SDK on every page of the Web Vault given many pages contain sensitive information. + * @param instanceId - Unique identifier for this component instance. * @param elementIds - The ID attributes of the HTML elements used to load the Stripe JS credit card elements. * @param autoMount - A flag indicating whether you want to immediately mount the Stripe credit card elements. */ loadStripe( + instanceId: string, elementIds: { cardNumber: string; cardExpiry: string; cardCvc: string }, autoMount: boolean, ) { - this.elementIds = elementIds; - const script = window.document.createElement("script"); - script.id = "stripe-script"; - script.src = "https://js.stripe.com/v3?advancedFraudSignals=false"; - script.onload = async () => { - const window$ = window as any; - this.stripe = window$.Stripe(process.env.STRIPE_KEY); - this.elements = this.stripe.elements(); - setTimeout(() => { - this.elements.create("cardNumber", this.getElementOptions("cardNumber")); - this.elements.create("cardExpiry", this.getElementOptions("cardExpiry")); - this.elements.create("cardCvc", this.getElementOptions("cardCvc")); - if (autoMount) { - this.mountElements(); - } - }, 50); - }; + // Check if script is already loaded + if (this.stripeScriptLoaded) { + // Script already loaded, initialize this instance immediately + this.initializeInstance(instanceId, elementIds, autoMount); + } else if (!window.document.getElementById("stripe-script")) { + // Script not loaded and not loading, start loading it + const script = window.document.createElement("script"); + script.id = "stripe-script"; + script.src = "https://js.stripe.com/v3?advancedFraudSignals=false"; + script.onload = async () => { + const window$ = window as any; + this.stripe = window$.Stripe(process.env.STRIPE_KEY); + this.stripeScriptLoaded = true; // Mark as loaded after script loads - window.document.head.appendChild(script); + // Initialize this instance after script loads + this.initializeInstance(instanceId, elementIds, autoMount); + }; + window.document.head.appendChild(script); + } else { + // Script is currently loading, wait for it + this.initializeInstance(instanceId, elementIds, autoMount); + } } - mountElements(attempt: number = 1) { - setTimeout(() => { - if (!this.elements) { - this.logService.warning(`Stripe elements are missing, retrying for attempt ${attempt}...`); - this.mountElements(attempt + 1); + private initializeInstance( + instanceId: string, + elementIds: { cardNumber: string; cardExpiry: string; cardCvc: string }, + autoMount: boolean, + attempt: number = 1, + ) { + // Wait for stripe to be available if script just loaded + if (!this.stripe) { + if (attempt < 10) { + this.logService.warning( + `Stripe not yet loaded for instance ${instanceId}, retrying attempt ${attempt}...`, + ); + setTimeout( + () => this.initializeInstance(instanceId, elementIds, autoMount, attempt + 1), + 50, + ); } else { - const cardNumber = this.elements.getElement("cardNumber"); - const cardExpiry = this.elements.getElement("cardExpiry"); - const cardCVC = this.elements.getElement("cardCvc"); + this.logService.error( + `Stripe failed to load for instance ${instanceId} after ${attempt} attempts`, + ); + } + return; + } + + // Create a new Elements instance for this component + const elements = this.stripe.elements(); + + // Store instance data + this.instances.set(instanceId, { elements, elementIds }); + + // Increment instance count now that instance is successfully initialized + this.instanceCount++; + + // Create the card elements + setTimeout(() => { + elements.create("cardNumber", this.getElementOptions("cardNumber")); + elements.create("cardExpiry", this.getElementOptions("cardExpiry")); + elements.create("cardCvc", this.getElementOptions("cardCvc")); + + if (autoMount) { + this.mountElements(instanceId); + } + }, 50); + } + + mountElements(instanceId: string, attempt: number = 1) { + setTimeout(() => { + const instance = this.instances.get(instanceId); + + if (!instance) { + if (attempt < 10) { + this.logService.warning( + `Stripe instance ${instanceId} not found, retrying for attempt ${attempt}...`, + ); + this.mountElements(instanceId, attempt + 1); + } else { + this.logService.error( + `Stripe instance ${instanceId} not found after ${attempt} attempts`, + ); + } + return; + } + + if (!instance.elements) { + this.logService.warning( + `Stripe elements for instance ${instanceId} are missing, retrying for attempt ${attempt}...`, + ); + this.mountElements(instanceId, attempt + 1); + } else { + const cardNumber = instance.elements.getElement("cardNumber"); + const cardExpiry = instance.elements.getElement("cardExpiry"); + const cardCVC = instance.elements.getElement("cardCvc"); if ([cardNumber, cardExpiry, cardCVC].some((element) => !element)) { this.logService.warning( - `Some Stripe card elements are missing, retrying for attempt ${attempt}...`, + `Some Stripe card elements for instance ${instanceId} are missing, retrying for attempt ${attempt}...`, ); - this.mountElements(attempt + 1); + this.mountElements(instanceId, attempt + 1); } else { - cardNumber.mount(this.elementIds.cardNumber); - cardExpiry.mount(this.elementIds.cardExpiry); - cardCVC.mount(this.elementIds.cardCvc); + cardNumber.mount(instance.elementIds.cardNumber); + cardExpiry.mount(instance.elementIds.cardExpiry); + cardCVC.mount(instance.elementIds.cardCvc); } } }, 100); @@ -132,6 +204,9 @@ export class StripeService { * Creates a Stripe [SetupIntent]{@link https://docs.stripe.com/api/setup_intents} and uses the resulting client secret * to invoke the Stripe JS [confirmUsBankAccountSetup]{@link https://docs.stripe.com/js/setup_intents/confirm_us_bank_account_setup} method, * thereby creating and storing a Stripe [PaymentMethod]{@link https://docs.stripe.com/api/payment_methods}. + * @param clientSecret - The client secret from the SetupIntent. + * @param bankAccount - The bank account details. + * @param billingDetails - Optional billing details. * @returns The ID of the newly created PaymentMethod. */ async setupBankAccountPaymentMethod( @@ -171,13 +246,28 @@ export class StripeService { * Creates a Stripe [SetupIntent]{@link https://docs.stripe.com/api/setup_intents} and uses the resulting client secret * to invoke the Stripe JS [confirmCardSetup]{@link https://docs.stripe.com/js/setup_intents/confirm_card_setup} method, * thereby creating and storing a Stripe [PaymentMethod]{@link https://docs.stripe.com/api/payment_methods}. + * @param instanceId - Unique identifier for the component instance. + * @param clientSecret - The client secret from the SetupIntent. + * @param billingDetails - Optional billing details. * @returns The ID of the newly created PaymentMethod. */ async setupCardPaymentMethod( + instanceId: string, clientSecret: string, billingDetails?: { country: string; postalCode: string }, ): Promise { - const cardNumber = this.elements.getElement("cardNumber"); + const instance = this.instances.get(instanceId); + if (!instance) { + const availableInstances = Array.from(this.instances.keys()); + this.logService.error( + `Stripe instance ${instanceId} not found. ` + + `Available instances: [${availableInstances.join(", ")}]. ` + + `This may occur if the component was destroyed during the payment flow.`, + ); + throw new Error("Payment method initialization failed. Please try again."); + } + + const cardNumber = instance.elements.getElement("cardNumber"); const request: SetupCardRequest = { payment_method: { card: cardNumber, @@ -200,24 +290,77 @@ export class StripeService { } /** - * Removes {@link https://docs.stripe.com/js} from the element of the current page as well as all - * Stripe-managed