mirror of
https://github.com/bitwarden/browser
synced 2026-02-13 15:03:26 +00:00
Merge branch 'main' into ps/extension-refresh
This commit is contained in:
34
.github/workflows/locales-lint.yml
vendored
Normal file
34
.github/workflows/locales-lint.yml
vendored
Normal file
@@ -0,0 +1,34 @@
|
||||
---
|
||||
name: Locales lint for Crowdin
|
||||
|
||||
on:
|
||||
pull_request:
|
||||
branches-ignore:
|
||||
- 'l10n_master'
|
||||
- 'cf-pages'
|
||||
paths:
|
||||
- '**/messages.json'
|
||||
|
||||
jobs:
|
||||
lint:
|
||||
name: Lint
|
||||
runs-on: ubuntu-22.04
|
||||
steps:
|
||||
- name: Checkout repo
|
||||
uses: actions/checkout@d632683dd7b4114ad314bca15554477dd762a938 # v4.2.0
|
||||
- name: Checkout base branch repo
|
||||
uses: actions/checkout@d632683dd7b4114ad314bca15554477dd762a938 # v4.2.0
|
||||
with:
|
||||
ref: ${{ github.event.pull_request.base.sha }}
|
||||
path: base
|
||||
- name: Install dependencies
|
||||
run: npm ci
|
||||
- name: Compare
|
||||
run: |
|
||||
npm run test:locales
|
||||
if [ $? -eq 0 ]; then
|
||||
echo "Lint check successful."
|
||||
else
|
||||
echo "Lint check failed."
|
||||
exit 1
|
||||
fi
|
||||
@@ -1,6 +1,6 @@
|
||||
{
|
||||
"name": "@bitwarden/browser",
|
||||
"version": "2024.10.0",
|
||||
"version": "2024.10.1",
|
||||
"scripts": {
|
||||
"build": "cross-env MANIFEST_VERSION=3 webpack",
|
||||
"build:mv2": "webpack",
|
||||
|
||||
@@ -42,7 +42,7 @@ describe("AutoSubmitLoginBackground", () => {
|
||||
const validIpdUrl1 = "https://example.com";
|
||||
const validIpdUrl2 = "https://subdomain.example3.com";
|
||||
const validAutoSubmitHost = "some-valid-url.com";
|
||||
const validAutoSubmitUrl = `https://${validAutoSubmitHost}/?autofill=1`;
|
||||
const validAutoSubmitUrl = `https://${validAutoSubmitHost}/#autosubmit=1`;
|
||||
|
||||
beforeEach(() => {
|
||||
logService = mock<LogService>();
|
||||
@@ -122,7 +122,7 @@ describe("AutoSubmitLoginBackground", () => {
|
||||
await autoSubmitLoginBackground.init();
|
||||
});
|
||||
|
||||
it("sets up the auto-submit workflow when the web request occurs in the main frame and the destination URL contains a valid auto-fill param", () => {
|
||||
it("sets up the auto-submit workflow when the web request occurs in the main frame and the destination URL contains a valid auto-fill hash", () => {
|
||||
triggerWebRequestOnBeforeRequestEvent(webRequestDetails);
|
||||
|
||||
expect(autoSubmitLoginBackground["currentAutoSubmitHostData"]).toStrictEqual({
|
||||
@@ -226,7 +226,7 @@ describe("AutoSubmitLoginBackground", () => {
|
||||
|
||||
it("disables the auto-submit workflow if a web request is initiated after the auto-submit route has been visited", () => {
|
||||
webRequestDetails.url = `https://${validAutoSubmitHost}`;
|
||||
webRequestDetails.initiator = `https://${validAutoSubmitHost}?autofill=1`;
|
||||
webRequestDetails.initiator = `https://${validAutoSubmitHost}#autosubmit=1`;
|
||||
|
||||
triggerWebRequestOnBeforeRequestEvent(webRequestDetails);
|
||||
|
||||
|
||||
@@ -234,7 +234,7 @@ export class AutoSubmitLoginBackground implements AutoSubmitLoginBackgroundAbstr
|
||||
) => {
|
||||
if (
|
||||
details.tabId === this.currentAutoSubmitHostData.tabId &&
|
||||
this.urlContainsAutoFillParam(details.url)
|
||||
this.urlContainsAutoSubmitHash(details.url)
|
||||
) {
|
||||
this.injectAutoSubmitLoginScript(details.tabId).catch((error) =>
|
||||
this.logService.error(error),
|
||||
@@ -277,7 +277,7 @@ export class AutoSubmitLoginBackground implements AutoSubmitLoginBackgroundAbstr
|
||||
private handleWebRequestOnBeforeRedirect = (
|
||||
details: chrome.webRequest.WebRedirectionResponseDetails,
|
||||
) => {
|
||||
if (this.isRequestInMainFrame(details) && this.urlContainsAutoFillParam(details.redirectUrl)) {
|
||||
if (this.isRequestInMainFrame(details) && this.urlContainsAutoSubmitHash(details.redirectUrl)) {
|
||||
this.validAutoSubmitHosts.add(this.getUrlHost(details.redirectUrl));
|
||||
this.validAutoSubmitHosts.add(this.getUrlHost(details.url));
|
||||
}
|
||||
@@ -369,7 +369,7 @@ export class AutoSubmitLoginBackground implements AutoSubmitLoginBackgroundAbstr
|
||||
|
||||
/**
|
||||
* Determines if the provided URL is a valid auto-submit host. If the request is occurring
|
||||
* in the main frame, we will check for the presence of the `autofill=1` query parameter.
|
||||
* in the main frame, we will check for the presence of the `autosubmit=1` uri hash.
|
||||
* If the request is occurring in a sub frame, the main frame URL should be set as a
|
||||
* valid auto-submit host and can be used to validate the request.
|
||||
*
|
||||
@@ -382,7 +382,7 @@ export class AutoSubmitLoginBackground implements AutoSubmitLoginBackgroundAbstr
|
||||
) => {
|
||||
if (this.isRequestInMainFrame(details)) {
|
||||
return !!(
|
||||
this.urlContainsAutoFillParam(details.url) ||
|
||||
this.urlContainsAutoSubmitHash(details.url) ||
|
||||
this.triggerAutoSubmitAfterRedirectOnSafari(details.url)
|
||||
);
|
||||
}
|
||||
@@ -391,14 +391,14 @@ export class AutoSubmitLoginBackground implements AutoSubmitLoginBackgroundAbstr
|
||||
};
|
||||
|
||||
/**
|
||||
* Determines if the provided URL contains the `autofill=1` query parameter.
|
||||
* Determines if the provided URL contains the `autosubmit=1` uri hash.
|
||||
*
|
||||
* @param url - The URL to check for the `autofill=1` query parameter.
|
||||
* @param url - The URL to check for the `autosubmit=1` uri hash.
|
||||
*/
|
||||
private urlContainsAutoFillParam = (url: string) => {
|
||||
private urlContainsAutoSubmitHash = (url: string) => {
|
||||
try {
|
||||
const urlObj = new URL(url);
|
||||
return urlObj.search.indexOf("autofill=1") !== -1;
|
||||
return urlObj.hash.indexOf("autosubmit=1") !== -1;
|
||||
} catch {
|
||||
return false;
|
||||
}
|
||||
|
||||
@@ -2,7 +2,7 @@
|
||||
"manifest_version": 2,
|
||||
"name": "__MSG_extName__",
|
||||
"short_name": "__MSG_appName__",
|
||||
"version": "2024.10.0",
|
||||
"version": "2024.10.1",
|
||||
"description": "__MSG_extDesc__",
|
||||
"default_locale": "en",
|
||||
"author": "Bitwarden Inc.",
|
||||
|
||||
@@ -3,7 +3,7 @@
|
||||
"minimum_chrome_version": "102.0",
|
||||
"name": "__MSG_extName__",
|
||||
"short_name": "__MSG_appName__",
|
||||
"version": "2024.10.0",
|
||||
"version": "2024.10.1",
|
||||
"description": "__MSG_extDesc__",
|
||||
"default_locale": "en",
|
||||
"author": "Bitwarden Inc.",
|
||||
|
||||
@@ -1,6 +1,8 @@
|
||||
import { SdkClientFactory } from "@bitwarden/common/platform/abstractions/sdk/sdk-client-factory";
|
||||
import type { BitwardenClient } from "@bitwarden/sdk-internal";
|
||||
|
||||
import { BrowserApi } from "../../browser/browser-api";
|
||||
|
||||
// https://stackoverflow.com/a/47880734
|
||||
const supported = (() => {
|
||||
try {
|
||||
@@ -18,14 +20,34 @@ const supported = (() => {
|
||||
return false;
|
||||
})();
|
||||
|
||||
if (supported) {
|
||||
// eslint-disable-next-line no-console
|
||||
console.debug("WebAssembly is supported in this environment");
|
||||
import("./wasm");
|
||||
} else {
|
||||
// eslint-disable-next-line no-console
|
||||
console.debug("WebAssembly is not supported in this environment");
|
||||
import("./fallback");
|
||||
// Manifest v3 does not support dynamic imports in the service worker.
|
||||
if (BrowserApi.isManifestVersion(3)) {
|
||||
if (supported) {
|
||||
// eslint-disable-next-line no-console
|
||||
console.debug("WebAssembly is supported in this environment");
|
||||
import("./wasm");
|
||||
} else {
|
||||
// eslint-disable-next-line no-console
|
||||
console.debug("WebAssembly is not supported in this environment");
|
||||
import("./fallback");
|
||||
}
|
||||
}
|
||||
|
||||
// Manifest v2 expects dynamic imports to prevent timing issues.
|
||||
async function load() {
|
||||
if (BrowserApi.isManifestVersion(3)) {
|
||||
return;
|
||||
}
|
||||
|
||||
if (supported) {
|
||||
// eslint-disable-next-line no-console
|
||||
console.debug("WebAssembly is supported in this environment");
|
||||
await import("./wasm");
|
||||
} else {
|
||||
// eslint-disable-next-line no-console
|
||||
console.debug("WebAssembly is not supported in this environment");
|
||||
await import("./fallback");
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -37,6 +59,8 @@ export class BrowserSdkClientFactory implements SdkClientFactory {
|
||||
async createSdkClient(
|
||||
...args: ConstructorParameters<typeof BitwardenClient>
|
||||
): Promise<BitwardenClient> {
|
||||
await load();
|
||||
|
||||
return Promise.resolve((globalThis as any).init_sdk(...args));
|
||||
}
|
||||
}
|
||||
|
||||
@@ -8,6 +8,7 @@
|
||||
|
||||
/* Begin PBXBuildFile section */
|
||||
03100CAF291891F4008E14EF /* encrypt-worker.js in Resources */ = {isa = PBXBuildFile; fileRef = 03100CAE291891F4008E14EF /* encrypt-worker.js */; };
|
||||
55BC93932CB4268A008CA4C6 /* assets in Resources */ = {isa = PBXBuildFile; fileRef = 55BC93922CB4268A008CA4C6 /* assets */; };
|
||||
55E0374D2577FA6B00979016 /* AppDelegate.swift in Sources */ = {isa = PBXBuildFile; fileRef = 55E0374C2577FA6B00979016 /* AppDelegate.swift */; };
|
||||
55E037502577FA6B00979016 /* Main.storyboard in Resources */ = {isa = PBXBuildFile; fileRef = 55E0374E2577FA6B00979016 /* Main.storyboard */; };
|
||||
55E037522577FA6B00979016 /* ViewController.swift in Sources */ = {isa = PBXBuildFile; fileRef = 55E037512577FA6B00979016 /* ViewController.swift */; };
|
||||
@@ -54,6 +55,7 @@
|
||||
/* Begin PBXFileReference section */
|
||||
03100CAE291891F4008E14EF /* encrypt-worker.js */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.javascript; name = "encrypt-worker.js"; path = "../../../build/encrypt-worker.js"; sourceTree = "<group>"; };
|
||||
5508DD7926051B5900A85C58 /* libswiftAppKit.tbd */ = {isa = PBXFileReference; lastKnownFileType = "sourcecode.text-based-dylib-definition"; name = libswiftAppKit.tbd; path = usr/lib/swift/libswiftAppKit.tbd; sourceTree = SDKROOT; };
|
||||
55BC93922CB4268A008CA4C6 /* assets */ = {isa = PBXFileReference; lastKnownFileType = folder; name = assets; path = ../../../build/assets; sourceTree = "<group>"; };
|
||||
55E037482577FA6B00979016 /* desktop.app */ = {isa = PBXFileReference; explicitFileType = wrapper.application; includeInIndex = 0; path = desktop.app; sourceTree = BUILT_PRODUCTS_DIR; };
|
||||
55E0374B2577FA6B00979016 /* desktop.entitlements */ = {isa = PBXFileReference; lastKnownFileType = text.plist.entitlements; path = desktop.entitlements; sourceTree = "<group>"; };
|
||||
55E0374C2577FA6B00979016 /* AppDelegate.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = AppDelegate.swift; sourceTree = "<group>"; };
|
||||
@@ -152,6 +154,7 @@
|
||||
55E0376F2577FA6F00979016 /* Resources */ = {
|
||||
isa = PBXGroup;
|
||||
children = (
|
||||
55BC93922CB4268A008CA4C6 /* assets */,
|
||||
03100CAE291891F4008E14EF /* encrypt-worker.js */,
|
||||
55E037702577FA6F00979016 /* popup */,
|
||||
55E037712577FA6F00979016 /* background.js */,
|
||||
@@ -270,6 +273,7 @@
|
||||
55E0377A2577FA6F00979016 /* background.js in Resources */,
|
||||
55E037792577FA6F00979016 /* popup in Resources */,
|
||||
03100CAF291891F4008E14EF /* encrypt-worker.js in Resources */,
|
||||
55BC93932CB4268A008CA4C6 /* assets in Resources */,
|
||||
55E0377C2577FA6F00979016 /* notification in Resources */,
|
||||
55E0377E2577FA6F00979016 /* vendor.js in Resources */,
|
||||
55E0377D2577FA6F00979016 /* content in Resources */,
|
||||
|
||||
@@ -316,6 +316,8 @@ const mainConfig = {
|
||||
},
|
||||
output: {
|
||||
filename: "[name].js",
|
||||
chunkFilename: "assets/[name].js",
|
||||
webassemblyModuleFilename: "assets/[modulehash].wasm",
|
||||
path: path.resolve(__dirname, "build"),
|
||||
clean: true,
|
||||
},
|
||||
|
||||
@@ -1,7 +1,7 @@
|
||||
{
|
||||
"name": "@bitwarden/cli",
|
||||
"description": "A secure and free password manager for all of your devices.",
|
||||
"version": "2024.9.1",
|
||||
"version": "2024.10.0",
|
||||
"keywords": [
|
||||
"bitwarden",
|
||||
"password",
|
||||
|
||||
@@ -1,7 +1,7 @@
|
||||
{
|
||||
"name": "@bitwarden/desktop",
|
||||
"description": "A secure and free password manager for all of your devices.",
|
||||
"version": "2024.9.2",
|
||||
"version": "2024.10.0",
|
||||
"keywords": [
|
||||
"bitwarden",
|
||||
"password",
|
||||
|
||||
12
apps/desktop/src/package-lock.json
generated
12
apps/desktop/src/package-lock.json
generated
@@ -1,26 +1,18 @@
|
||||
{
|
||||
"name": "@bitwarden/desktop",
|
||||
"version": "2024.9.2",
|
||||
"version": "2024.10.0",
|
||||
"lockfileVersion": 3,
|
||||
"requires": true,
|
||||
"packages": {
|
||||
"": {
|
||||
"name": "@bitwarden/desktop",
|
||||
"version": "2024.9.2",
|
||||
"version": "2024.10.0",
|
||||
"license": "GPL-3.0",
|
||||
"dependencies": {
|
||||
"@bitwarden/desktop-napi": "file:../desktop_native/napi",
|
||||
"argon2": "0.40.1"
|
||||
}
|
||||
},
|
||||
"../desktop_native/napi": {
|
||||
"name": "@bitwarden/desktop-napi",
|
||||
"version": "0.1.0",
|
||||
"license": "GPL-3.0",
|
||||
"devDependencies": {
|
||||
"@napi-rs/cli": "2.16.2"
|
||||
}
|
||||
},
|
||||
"../desktop_native/napi": {
|
||||
"version": "0.1.0",
|
||||
"license": "GPL-3.0",
|
||||
|
||||
@@ -2,7 +2,7 @@
|
||||
"name": "@bitwarden/desktop",
|
||||
"productName": "Bitwarden",
|
||||
"description": "A secure and free password manager for all of your devices.",
|
||||
"version": "2024.9.2",
|
||||
"version": "2024.10.0",
|
||||
"author": "Bitwarden Inc. <hello@bitwarden.com> (https://bitwarden.com)",
|
||||
"homepage": "https://bitwarden.com",
|
||||
"license": "GPL-3.0",
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
{
|
||||
"name": "@bitwarden/web-vault",
|
||||
"version": "2024.10.0",
|
||||
"version": "2024.10.1",
|
||||
"scripts": {
|
||||
"build:oss": "webpack",
|
||||
"build:bit": "webpack -c ../../bitwarden_license/bit-web/webpack.config.js",
|
||||
|
||||
@@ -16,38 +16,13 @@
|
||||
"all" | i18n
|
||||
}}</label>
|
||||
</th>
|
||||
<!-- Organization vault -->
|
||||
<th
|
||||
*ngIf="showAdminActions"
|
||||
bitCell
|
||||
bitSortable="name"
|
||||
[fn]="sortByName"
|
||||
[class]="showExtraColumn ? 'lg:tw-w-3/5' : 'tw-w-full'"
|
||||
>
|
||||
{{ "name" | i18n }}
|
||||
</th>
|
||||
<!-- Individual vault -->
|
||||
<th
|
||||
*ngIf="!showAdminActions"
|
||||
bitCell
|
||||
[class]="showExtraColumn ? 'lg:tw-w-3/5' : 'tw-w-full'"
|
||||
>
|
||||
{{ "name" | i18n }}
|
||||
</th>
|
||||
<th bitCell [class]="showExtraColumn ? 'lg:tw-w-3/5' : 'tw-w-full'">{{ "name" | i18n }}</th>
|
||||
<th bitCell *ngIf="showOwner" class="tw-hidden tw-w-2/5 lg:tw-table-cell">
|
||||
{{ "owner" | i18n }}
|
||||
</th>
|
||||
<th bitCell class="tw-w-2/5" *ngIf="showCollections">{{ "collections" | i18n }}</th>
|
||||
<th bitCell bitSortable="groups" [fn]="sortByGroups" class="tw-w-2/5" *ngIf="showGroups">
|
||||
{{ "groups" | i18n }}
|
||||
</th>
|
||||
<th
|
||||
bitCell
|
||||
bitSortable="permissions"
|
||||
[fn]="sortByPermissions"
|
||||
class="tw-w-2/5"
|
||||
*ngIf="showPermissionsColumn"
|
||||
>
|
||||
<th bitCell class="tw-w-2/5" *ngIf="showGroups">{{ "groups" | i18n }}</th>
|
||||
<th bitCell class="tw-w-2/5" *ngIf="showPermissionsColumn">
|
||||
{{ "permission" | i18n }}
|
||||
</th>
|
||||
<th bitCell class="tw-w-12 tw-text-right">
|
||||
|
||||
@@ -1,19 +1,14 @@
|
||||
import { SelectionModel } from "@angular/cdk/collections";
|
||||
import { Component, EventEmitter, inject, Input, Output } from "@angular/core";
|
||||
import { Component, EventEmitter, Input, Output } from "@angular/core";
|
||||
|
||||
import { CollectionAdminView, Unassigned } from "@bitwarden/admin-console/common";
|
||||
import { Unassigned } from "@bitwarden/admin-console/common";
|
||||
import { Organization } from "@bitwarden/common/admin-console/models/domain/organization";
|
||||
import { I18nService } from "@bitwarden/common/platform/abstractions/i18n.service";
|
||||
import { CipherView } from "@bitwarden/common/vault/models/view/cipher.view";
|
||||
import { CollectionView } from "@bitwarden/common/vault/models/view/collection.view";
|
||||
import { TableDataSource } from "@bitwarden/components";
|
||||
|
||||
import { GroupView } from "../../../admin-console/organizations/core";
|
||||
|
||||
import {
|
||||
CollectionPermission,
|
||||
convertToPermission,
|
||||
} from "./../../../admin-console/organizations/shared/components/access-selector/access-selector.models";
|
||||
import { VaultItem } from "./vault-item";
|
||||
import { VaultItemEvent } from "./vault-item-event";
|
||||
|
||||
@@ -30,7 +25,6 @@ const MaxSelectionCount = 500;
|
||||
// changeDetection: ChangeDetectionStrategy.OnPush,
|
||||
})
|
||||
export class VaultItemsComponent {
|
||||
protected i18nService = inject(I18nService);
|
||||
protected RowHeight = RowHeight;
|
||||
|
||||
@Input() disabled: boolean;
|
||||
@@ -203,7 +197,7 @@ export class VaultItemsComponent {
|
||||
private refreshItems() {
|
||||
const collections: VaultItem[] = this.collections.map((collection) => ({ collection }));
|
||||
const ciphers: VaultItem[] = this.ciphers.map((cipher) => ({ cipher }));
|
||||
let items: VaultItem[] = [].concat(collections).concat(ciphers);
|
||||
const items: VaultItem[] = [].concat(collections).concat(ciphers);
|
||||
|
||||
this.selection.clear();
|
||||
|
||||
@@ -214,11 +208,6 @@ export class VaultItemsComponent {
|
||||
(item.collection !== undefined && item.collection.id !== Unassigned),
|
||||
);
|
||||
|
||||
// Apply sorting only for organization vault
|
||||
if (this.showAdminActions) {
|
||||
items = items.sort(this.sortByGroups);
|
||||
}
|
||||
|
||||
this.dataSource.data = items;
|
||||
}
|
||||
|
||||
@@ -304,112 +293,6 @@ export class VaultItemsComponent {
|
||||
return false;
|
||||
}
|
||||
|
||||
/**
|
||||
* Sorts VaultItems, grouping collections before ciphers, and sorting each group alphabetically by name.
|
||||
*/
|
||||
protected sortByName = (a: VaultItem, b: VaultItem) => {
|
||||
const getName = (item: VaultItem) => item.collection?.name || item.cipher?.name;
|
||||
|
||||
// First, sort collections before ciphers
|
||||
if (a.collection && !b.collection) {
|
||||
return -1;
|
||||
}
|
||||
if (!a.collection && b.collection) {
|
||||
return 1;
|
||||
}
|
||||
|
||||
return getName(a).localeCompare(getName(b));
|
||||
};
|
||||
|
||||
/**
|
||||
* Sorts VaultItems based on group names
|
||||
*/
|
||||
protected sortByGroups = (a: VaultItem, b: VaultItem): number => {
|
||||
const getGroupNames = (item: VaultItem): string => {
|
||||
if (item.collection instanceof CollectionAdminView) {
|
||||
return item.collection.groups
|
||||
.map((group) => this.getGroupName(group.id))
|
||||
.filter(Boolean)
|
||||
.join(",");
|
||||
}
|
||||
|
||||
return "";
|
||||
};
|
||||
|
||||
const aGroupNames = getGroupNames(a);
|
||||
const bGroupNames = getGroupNames(b);
|
||||
|
||||
if (aGroupNames.length !== bGroupNames.length) {
|
||||
return bGroupNames.length - aGroupNames.length;
|
||||
}
|
||||
|
||||
return aGroupNames.localeCompare(bGroupNames);
|
||||
};
|
||||
|
||||
/**
|
||||
* Sorts VaultItems based on their permissions, with higher permissions taking precedence.
|
||||
* If permissions are equal, it falls back to sorting by name.
|
||||
*/
|
||||
protected sortByPermissions = (a: VaultItem, b: VaultItem): number => {
|
||||
const getPermissionPriority = (item: VaultItem): number => {
|
||||
if (item.collection instanceof CollectionAdminView) {
|
||||
const permission = this.getCollectionPermission(item.collection);
|
||||
|
||||
switch (permission) {
|
||||
case CollectionPermission.Manage:
|
||||
return 5;
|
||||
case CollectionPermission.Edit:
|
||||
return 4;
|
||||
case CollectionPermission.EditExceptPass:
|
||||
return 3;
|
||||
case CollectionPermission.View:
|
||||
return 2;
|
||||
case CollectionPermission.ViewExceptPass:
|
||||
return 1;
|
||||
case "NoAccess":
|
||||
return 0;
|
||||
}
|
||||
}
|
||||
|
||||
return -1;
|
||||
};
|
||||
|
||||
const priorityA = getPermissionPriority(a);
|
||||
const priorityB = getPermissionPriority(b);
|
||||
|
||||
// Higher priority first
|
||||
if (priorityA !== priorityB) {
|
||||
return priorityB - priorityA;
|
||||
}
|
||||
|
||||
return this.sortByName(a, b);
|
||||
};
|
||||
|
||||
/**
|
||||
* Default sorting function for vault items.
|
||||
* Sorts by: 1. Collections before ciphers
|
||||
* 2. Highest permission first
|
||||
* 3. Alphabetical order of collections and ciphers
|
||||
*/
|
||||
private defaultSort = (a: VaultItem, b: VaultItem) => {
|
||||
// First, sort collections before ciphers
|
||||
if (a.collection && !b.collection) {
|
||||
return -1;
|
||||
}
|
||||
if (!a.collection && b.collection) {
|
||||
return 1;
|
||||
}
|
||||
|
||||
// Next, sort by permissions
|
||||
const permissionSort = this.sortByPermissions(a, b);
|
||||
if (permissionSort !== 0) {
|
||||
return permissionSort;
|
||||
}
|
||||
|
||||
// Finally, sort by name
|
||||
return this.sortByName(a, b);
|
||||
};
|
||||
|
||||
private hasPersonalItems(): boolean {
|
||||
return this.selection.selected.some(({ cipher }) => cipher?.organizationId === null);
|
||||
}
|
||||
@@ -423,24 +306,4 @@ export class VaultItemsComponent {
|
||||
private getUniqueOrganizationIds(): Set<string> {
|
||||
return new Set(this.selection.selected.flatMap((i) => i.cipher?.organizationId ?? []));
|
||||
}
|
||||
|
||||
private getGroupName(groupId: string): string | undefined {
|
||||
return this.allGroups.find((g) => g.id === groupId)?.name;
|
||||
}
|
||||
|
||||
private getCollectionPermission(
|
||||
collection: CollectionAdminView,
|
||||
): CollectionPermission | "NoAccess" {
|
||||
const organization = this.allOrganizations.find((o) => o.id === collection.organizationId);
|
||||
|
||||
if (collection.id == Unassigned && organization?.canEditUnassignedCiphers) {
|
||||
return CollectionPermission.Edit;
|
||||
}
|
||||
|
||||
if (collection.assigned) {
|
||||
return convertToPermission(collection);
|
||||
}
|
||||
|
||||
return "NoAccess";
|
||||
}
|
||||
}
|
||||
|
||||
@@ -0,0 +1,119 @@
|
||||
import { TestBed } from "@angular/core/testing";
|
||||
import { BehaviorSubject } from "rxjs";
|
||||
|
||||
import { CollectionAdminService } from "@bitwarden/admin-console/common";
|
||||
import { ApiService } from "@bitwarden/common/abstractions/api.service";
|
||||
import { OrganizationService } from "@bitwarden/common/admin-console/abstractions/organization/organization.service.abstraction";
|
||||
import { Organization } from "@bitwarden/common/admin-console/models/domain/organization";
|
||||
import { CipherId } from "@bitwarden/common/types/guid";
|
||||
import { CipherService } from "@bitwarden/common/vault/abstractions/cipher.service";
|
||||
|
||||
import { RoutedVaultFilterService } from "../../individual-vault/vault-filter/services/routed-vault-filter.service";
|
||||
|
||||
import { AdminConsoleCipherFormConfigService } from "./admin-console-cipher-form-config.service";
|
||||
|
||||
describe("AdminConsoleCipherFormConfigService", () => {
|
||||
let adminConsoleConfigService: AdminConsoleCipherFormConfigService;
|
||||
|
||||
const cipherId = "333-444-555" as CipherId;
|
||||
const testOrg = { id: "333-44-55", name: "Test Org", canEditAllCiphers: false };
|
||||
const organization$ = new BehaviorSubject<Organization>(testOrg as Organization);
|
||||
const getCipherAdmin = jest.fn().mockResolvedValue(null);
|
||||
const getCipher = jest.fn().mockResolvedValue(null);
|
||||
|
||||
beforeEach(async () => {
|
||||
getCipherAdmin.mockClear();
|
||||
getCipher.mockClear();
|
||||
getCipher.mockResolvedValue({ id: cipherId, name: "Test Cipher - (non-admin)" });
|
||||
getCipherAdmin.mockResolvedValue({ id: cipherId, name: "Test Cipher - (admin)" });
|
||||
|
||||
await TestBed.configureTestingModule({
|
||||
providers: [
|
||||
AdminConsoleCipherFormConfigService,
|
||||
{ provide: OrganizationService, useValue: { get$: () => organization$ } },
|
||||
{ provide: CipherService, useValue: { get: getCipher } },
|
||||
{ provide: CollectionAdminService, useValue: { getAll: () => Promise.resolve([]) } },
|
||||
{
|
||||
provide: RoutedVaultFilterService,
|
||||
useValue: { filter$: new BehaviorSubject({ organizationId: testOrg.id }) },
|
||||
},
|
||||
{ provide: ApiService, useValue: { getCipherAdmin } },
|
||||
],
|
||||
});
|
||||
});
|
||||
|
||||
describe("buildConfig", () => {
|
||||
it("sets individual attributes", async () => {
|
||||
adminConsoleConfigService = TestBed.inject(AdminConsoleCipherFormConfigService);
|
||||
|
||||
const { folders, hideIndividualVaultFields } = await adminConsoleConfigService.buildConfig(
|
||||
"add",
|
||||
cipherId,
|
||||
);
|
||||
|
||||
expect(folders).toEqual([]);
|
||||
expect(hideIndividualVaultFields).toBe(true);
|
||||
});
|
||||
|
||||
it("sets mode based on passed mode", async () => {
|
||||
adminConsoleConfigService = TestBed.inject(AdminConsoleCipherFormConfigService);
|
||||
|
||||
const { mode } = await adminConsoleConfigService.buildConfig("edit", cipherId);
|
||||
|
||||
expect(mode).toBe("edit");
|
||||
});
|
||||
|
||||
it("sets admin flag based on `canEditAllCiphers`", async () => {
|
||||
// Disable edit all ciphers on org
|
||||
testOrg.canEditAllCiphers = false;
|
||||
adminConsoleConfigService = TestBed.inject(AdminConsoleCipherFormConfigService);
|
||||
|
||||
let result = await adminConsoleConfigService.buildConfig("add", cipherId);
|
||||
|
||||
expect(result.admin).toBe(false);
|
||||
|
||||
// Enable edit all ciphers on org
|
||||
testOrg.canEditAllCiphers = true;
|
||||
result = await adminConsoleConfigService.buildConfig("add", cipherId);
|
||||
|
||||
expect(result.admin).toBe(true);
|
||||
});
|
||||
|
||||
it("sets `allowPersonalOwnership` to false", async () => {
|
||||
adminConsoleConfigService = TestBed.inject(AdminConsoleCipherFormConfigService);
|
||||
|
||||
const result = await adminConsoleConfigService.buildConfig("clone", cipherId);
|
||||
|
||||
expect(result.allowPersonalOwnership).toBe(false);
|
||||
});
|
||||
|
||||
describe("getCipher", () => {
|
||||
it("retrieves the cipher from the cipher service", async () => {
|
||||
testOrg.canEditAllCiphers = false;
|
||||
|
||||
adminConsoleConfigService = TestBed.inject(AdminConsoleCipherFormConfigService);
|
||||
|
||||
const result = await adminConsoleConfigService.buildConfig("clone", cipherId);
|
||||
|
||||
expect(getCipher).toHaveBeenCalledWith(cipherId);
|
||||
expect(result.originalCipher.name).toBe("Test Cipher - (non-admin)");
|
||||
|
||||
// Admin service not needed when cipher service can return the cipher
|
||||
expect(getCipherAdmin).not.toHaveBeenCalled();
|
||||
});
|
||||
|
||||
it("retrieves the cipher from the admin service", async () => {
|
||||
getCipher.mockResolvedValueOnce(null);
|
||||
getCipherAdmin.mockResolvedValue({ id: cipherId, name: "Test Cipher - (admin)" });
|
||||
|
||||
adminConsoleConfigService = TestBed.inject(AdminConsoleCipherFormConfigService);
|
||||
|
||||
await adminConsoleConfigService.buildConfig("add", cipherId);
|
||||
|
||||
expect(getCipherAdmin).toHaveBeenCalledWith(cipherId);
|
||||
|
||||
expect(getCipher).toHaveBeenCalledWith(cipherId);
|
||||
});
|
||||
});
|
||||
});
|
||||
});
|
||||
@@ -0,0 +1,99 @@
|
||||
import { inject, Injectable } from "@angular/core";
|
||||
import { combineLatest, filter, firstValueFrom, map, switchMap } from "rxjs";
|
||||
|
||||
import { CollectionAdminService } from "@bitwarden/admin-console/common";
|
||||
import { ApiService } from "@bitwarden/common/abstractions/api.service";
|
||||
import { OrganizationService } from "@bitwarden/common/admin-console/abstractions/organization/organization.service.abstraction";
|
||||
import { Organization } from "@bitwarden/common/admin-console/models/domain/organization";
|
||||
import { CipherId } from "@bitwarden/common/types/guid";
|
||||
import { CipherService } from "@bitwarden/common/vault/abstractions/cipher.service";
|
||||
import { CipherType } from "@bitwarden/common/vault/enums";
|
||||
import { CipherData } from "@bitwarden/common/vault/models/data/cipher.data";
|
||||
import { Cipher } from "@bitwarden/common/vault/models/domain/cipher";
|
||||
|
||||
import {
|
||||
CipherFormConfig,
|
||||
CipherFormConfigService,
|
||||
CipherFormMode,
|
||||
} from "../../../../../../../libs/vault/src/cipher-form/abstractions/cipher-form-config.service";
|
||||
import { RoutedVaultFilterService } from "../../individual-vault/vault-filter/services/routed-vault-filter.service";
|
||||
|
||||
/** Admin Console implementation of the `CipherFormConfigService`. */
|
||||
@Injectable()
|
||||
export class AdminConsoleCipherFormConfigService implements CipherFormConfigService {
|
||||
private organizationService: OrganizationService = inject(OrganizationService);
|
||||
private cipherService: CipherService = inject(CipherService);
|
||||
private routedVaultFilterService: RoutedVaultFilterService = inject(RoutedVaultFilterService);
|
||||
private collectionAdminService: CollectionAdminService = inject(CollectionAdminService);
|
||||
private apiService: ApiService = inject(ApiService);
|
||||
|
||||
private organizationId$ = this.routedVaultFilterService.filter$.pipe(
|
||||
map((filter) => filter.organizationId),
|
||||
filter((filter) => filter !== undefined),
|
||||
);
|
||||
|
||||
private organization$ = this.organizationId$.pipe(
|
||||
switchMap((organizationId) => this.organizationService.get$(organizationId)),
|
||||
);
|
||||
|
||||
private editableCollections$ = this.organization$.pipe(
|
||||
switchMap(async (org) => {
|
||||
const collections = await this.collectionAdminService.getAll(org.id);
|
||||
// Users that can edit all ciphers can implicitly add to / edit within any collection
|
||||
if (org.canEditAllCiphers) {
|
||||
return collections;
|
||||
}
|
||||
// The user is only allowed to add/edit items to assigned collections that are not readonly
|
||||
return collections.filter((c) => c.assigned && !c.readOnly);
|
||||
}),
|
||||
);
|
||||
|
||||
async buildConfig(
|
||||
mode: CipherFormMode,
|
||||
cipherId?: CipherId,
|
||||
cipherType?: CipherType,
|
||||
): Promise<CipherFormConfig> {
|
||||
const [organization, allCollections] = await firstValueFrom(
|
||||
combineLatest([this.organization$, this.editableCollections$]),
|
||||
);
|
||||
|
||||
const cipher = await this.getCipher(organization, cipherId);
|
||||
|
||||
const collections = allCollections.filter(
|
||||
(c) => c.organizationId === organization.id && c.assigned && !c.readOnly,
|
||||
);
|
||||
|
||||
return {
|
||||
mode,
|
||||
cipherType: cipher?.type ?? cipherType ?? CipherType.Login,
|
||||
admin: organization.canEditAllCiphers ?? false,
|
||||
allowPersonalOwnership: false,
|
||||
originalCipher: cipher,
|
||||
collections,
|
||||
organizations: [organization], // only a single org is in context at a time
|
||||
folders: [], // folders not applicable in the admin console
|
||||
hideIndividualVaultFields: true,
|
||||
};
|
||||
}
|
||||
|
||||
private async getCipher(organization: Organization, id?: CipherId): Promise<Cipher | null> {
|
||||
if (id == null) {
|
||||
return Promise.resolve(null);
|
||||
}
|
||||
|
||||
// Check to see if the user has direct access to the cipher
|
||||
const cipherFromCipherService = await this.cipherService.get(id);
|
||||
|
||||
// If the organization doesn't allow admin/owners to edit all ciphers return the cipher
|
||||
if (!organization.canEditAllCiphers && cipherFromCipherService != null) {
|
||||
return cipherFromCipherService;
|
||||
}
|
||||
|
||||
// Retrieve the cipher through the means of an admin
|
||||
const cipherResponse = await this.apiService.getCipherAdmin(id);
|
||||
cipherResponse.edit = true;
|
||||
|
||||
const cipherData = new CipherData(cipherResponse);
|
||||
return new Cipher(cipherData);
|
||||
}
|
||||
}
|
||||
@@ -1,3 +1,4 @@
|
||||
import { DialogRef } from "@angular/cdk/dialog";
|
||||
import {
|
||||
ChangeDetectorRef,
|
||||
Component,
|
||||
@@ -42,16 +43,17 @@ import { EventCollectionService } from "@bitwarden/common/abstractions/event/eve
|
||||
import { SearchService } from "@bitwarden/common/abstractions/search.service";
|
||||
import { OrganizationService } from "@bitwarden/common/admin-console/abstractions/organization/organization.service.abstraction";
|
||||
import { Organization } from "@bitwarden/common/admin-console/models/domain/organization";
|
||||
import { AccountService } from "@bitwarden/common/auth/abstractions/account.service";
|
||||
import { EventType } from "@bitwarden/common/enums";
|
||||
import { FeatureFlag } from "@bitwarden/common/enums/feature-flag.enum";
|
||||
import { BroadcasterService } from "@bitwarden/common/platform/abstractions/broadcaster.service";
|
||||
import { ConfigService } from "@bitwarden/common/platform/abstractions/config/config.service";
|
||||
import { I18nService } from "@bitwarden/common/platform/abstractions/i18n.service";
|
||||
import { LogService } from "@bitwarden/common/platform/abstractions/log.service";
|
||||
import { MessagingService } from "@bitwarden/common/platform/abstractions/messaging.service";
|
||||
import { PlatformUtilsService } from "@bitwarden/common/platform/abstractions/platform-utils.service";
|
||||
import { Utils } from "@bitwarden/common/platform/misc/utils";
|
||||
import { SyncService } from "@bitwarden/common/platform/sync";
|
||||
import { OrganizationId } from "@bitwarden/common/types/guid";
|
||||
import { CipherId, CollectionId, OrganizationId } from "@bitwarden/common/types/guid";
|
||||
import { CipherService } from "@bitwarden/common/vault/abstractions/cipher.service";
|
||||
import { CollectionService } from "@bitwarden/common/vault/abstractions/collection.service";
|
||||
import { TotpService } from "@bitwarden/common/vault/abstractions/totp.service";
|
||||
@@ -62,7 +64,12 @@ import { CipherView } from "@bitwarden/common/vault/models/view/cipher.view";
|
||||
import { CollectionView } from "@bitwarden/common/vault/models/view/collection.view";
|
||||
import { ServiceUtils } from "@bitwarden/common/vault/service-utils";
|
||||
import { DialogService, Icons, NoItemsModule, ToastService } from "@bitwarden/components";
|
||||
import { CollectionAssignmentResult, PasswordRepromptService } from "@bitwarden/vault";
|
||||
import {
|
||||
CipherFormConfig,
|
||||
CipherFormConfigService,
|
||||
CollectionAssignmentResult,
|
||||
PasswordRepromptService,
|
||||
} from "@bitwarden/vault";
|
||||
|
||||
import { GroupService, GroupView } from "../../admin-console/organizations/core";
|
||||
import { openEntityEventsDialog } from "../../admin-console/organizations/manage/entity-events.component";
|
||||
@@ -75,6 +82,11 @@ import {
|
||||
CollectionDialogTabType,
|
||||
openCollectionDialog,
|
||||
} from "../components/collection-dialog";
|
||||
import {
|
||||
VaultItemDialogComponent,
|
||||
VaultItemDialogMode,
|
||||
VaultItemDialogResult,
|
||||
} from "../components/vault-item-dialog/vault-item-dialog.component";
|
||||
import { VaultItemEvent } from "../components/vault-items/vault-item-event";
|
||||
import { VaultItemsModule } from "../components/vault-items/vault-items.module";
|
||||
import {
|
||||
@@ -89,12 +101,6 @@ import {
|
||||
All,
|
||||
RoutedVaultFilterModel,
|
||||
} from "../individual-vault/vault-filter/shared/models/routed-vault-filter.model";
|
||||
import {
|
||||
openViewCipherDialog,
|
||||
ViewCipherDialogCloseResult,
|
||||
ViewCipherDialogResult,
|
||||
ViewComponent,
|
||||
} from "../individual-vault/view.component";
|
||||
import { VaultHeaderComponent } from "../org-vault/vault-header/vault-header.component";
|
||||
import { getNestedCollectionTree } from "../utils/collection-utils";
|
||||
|
||||
@@ -106,8 +112,8 @@ import {
|
||||
} from "./bulk-collections-dialog";
|
||||
import { CollectionAccessRestrictedComponent } from "./collection-access-restricted.component";
|
||||
import { openOrgVaultCollectionsDialog } from "./collections.component";
|
||||
import { AdminConsoleCipherFormConfigService } from "./services/admin-console-cipher-form-config.service";
|
||||
import { VaultFilterModule } from "./vault-filter/vault-filter.module";
|
||||
|
||||
const BroadcasterSubscriptionId = "OrgVaultComponent";
|
||||
const SearchTextDebounceInterval = 200;
|
||||
|
||||
@@ -127,9 +133,12 @@ enum AddAccessStatusType {
|
||||
VaultItemsModule,
|
||||
SharedModule,
|
||||
NoItemsModule,
|
||||
ViewComponent,
|
||||
],
|
||||
providers: [RoutedVaultFilterService, RoutedVaultFilterBridgeService],
|
||||
providers: [
|
||||
RoutedVaultFilterService,
|
||||
RoutedVaultFilterBridgeService,
|
||||
{ provide: CipherFormConfigService, useClass: AdminConsoleCipherFormConfigService },
|
||||
],
|
||||
})
|
||||
export class VaultComponent implements OnInit, OnDestroy {
|
||||
protected Unassigned = Unassigned;
|
||||
@@ -174,6 +183,8 @@ export class VaultComponent implements OnInit, OnDestroy {
|
||||
private refresh$ = new BehaviorSubject<void>(null);
|
||||
private destroy$ = new Subject<void>();
|
||||
protected addAccessStatus$ = new BehaviorSubject<AddAccessStatusType>(0);
|
||||
private extensionRefreshEnabled: boolean;
|
||||
private vaultItemDialogRef?: DialogRef<VaultItemDialogResult> | undefined;
|
||||
|
||||
constructor(
|
||||
private route: ActivatedRoute,
|
||||
@@ -203,10 +214,15 @@ export class VaultComponent implements OnInit, OnDestroy {
|
||||
private apiService: ApiService,
|
||||
private collectionService: CollectionService,
|
||||
private toastService: ToastService,
|
||||
private accountService: AccountService,
|
||||
private configService: ConfigService,
|
||||
private cipherFormConfigService: CipherFormConfigService,
|
||||
) {}
|
||||
|
||||
async ngOnInit() {
|
||||
this.extensionRefreshEnabled = await this.configService.getFeatureFlag(
|
||||
FeatureFlag.ExtensionRefresh,
|
||||
);
|
||||
|
||||
this.trashCleanupWarning = this.i18nService.t(
|
||||
this.platformUtilsService.isSelfHost()
|
||||
? "trashCleanupWarningSelfHosted"
|
||||
@@ -466,22 +482,27 @@ export class VaultComponent implements OnInit, OnDestroy {
|
||||
firstSetup$
|
||||
.pipe(
|
||||
switchMap(() => this.route.queryParams),
|
||||
// Only process the queryParams if the dialog is not open (only when extension refresh is enabled)
|
||||
filter(() => this.vaultItemDialogRef == undefined || !this.extensionRefreshEnabled),
|
||||
withLatestFrom(allCipherMap$, allCollections$, organization$),
|
||||
switchMap(async ([qParams, allCiphersMap, allCollections]) => {
|
||||
switchMap(async ([qParams, allCiphersMap]) => {
|
||||
const cipherId = getCipherIdFromParams(qParams);
|
||||
if (!cipherId) {
|
||||
return;
|
||||
}
|
||||
const cipher = allCiphersMap[cipherId];
|
||||
const cipherCollections = allCollections.filter((c) =>
|
||||
cipher.collectionIds.includes(c.id),
|
||||
);
|
||||
|
||||
if (cipher) {
|
||||
if (qParams.action === "view") {
|
||||
await this.viewCipher(cipher, cipherCollections);
|
||||
let action = qParams.action;
|
||||
// Default to "view" if extension refresh is enabled
|
||||
if (action == null && this.extensionRefreshEnabled) {
|
||||
action = "view";
|
||||
}
|
||||
|
||||
if (action === "view") {
|
||||
await this.viewCipherById(cipher);
|
||||
} else {
|
||||
await this.editCipherId(cipherId);
|
||||
await this.editCipherId(cipher, false);
|
||||
}
|
||||
} else {
|
||||
this.toastService.showToast({
|
||||
@@ -730,12 +751,16 @@ export class VaultComponent implements OnInit, OnDestroy {
|
||||
}
|
||||
|
||||
async addCipher(cipherType?: CipherType) {
|
||||
if (this.extensionRefreshEnabled) {
|
||||
return this.addCipherV2(cipherType);
|
||||
}
|
||||
|
||||
let collections: CollectionView[] = [];
|
||||
|
||||
// Admins limited to only adding items to collections they have access to.
|
||||
collections = await firstValueFrom(this.editableCollections$);
|
||||
|
||||
await this.editCipher(null, (comp) => {
|
||||
await this.editCipher(null, false, (comp) => {
|
||||
comp.type = cipherType || this.activeFilter.cipherType;
|
||||
comp.collections = collections;
|
||||
if (this.activeFilter.collectionId) {
|
||||
@@ -744,20 +769,46 @@ export class VaultComponent implements OnInit, OnDestroy {
|
||||
});
|
||||
}
|
||||
|
||||
/** Opens the Add/Edit Dialog. Only to be used when the BrowserExtension feature flag is active */
|
||||
async addCipherV2(cipherType?: CipherType) {
|
||||
const cipherFormConfig = await this.cipherFormConfigService.buildConfig(
|
||||
"add",
|
||||
null,
|
||||
cipherType,
|
||||
);
|
||||
|
||||
const collectionId: CollectionId | undefined = this.activeFilter.collectionId as CollectionId;
|
||||
|
||||
cipherFormConfig.initialValues = {
|
||||
organizationId: this.organization.id as OrganizationId,
|
||||
collectionIds: collectionId ? [collectionId] : [],
|
||||
};
|
||||
|
||||
await this.openVaultItemDialog("form", cipherFormConfig);
|
||||
}
|
||||
|
||||
/**
|
||||
* Edit the given cipher
|
||||
* @param cipherView - The cipher to be edited
|
||||
* @param cloneCipher - `true` when the cipher should be cloned.
|
||||
* Used in place of the `additionalComponentParameters`, as
|
||||
* the `editCipherIdV2` method has a differing implementation.
|
||||
* @param defaultComponentParameters - A method that takes in an instance of
|
||||
* the `AddEditComponent` to edit methods directly.
|
||||
*/
|
||||
async editCipher(
|
||||
cipher: CipherView,
|
||||
cloneCipher: boolean,
|
||||
additionalComponentParameters?: (comp: AddEditComponent) => void,
|
||||
) {
|
||||
return this.editCipherId(cipher?.id, additionalComponentParameters);
|
||||
return this.editCipherId(cipher, cloneCipher, additionalComponentParameters);
|
||||
}
|
||||
|
||||
async editCipherId(
|
||||
cipherId: string,
|
||||
cipher: CipherView,
|
||||
cloneCipher: boolean,
|
||||
additionalComponentParameters?: (comp: AddEditComponent) => void,
|
||||
) {
|
||||
const cipher = await this.cipherService.get(cipherId);
|
||||
// if cipher exists (cipher is null when new) and MP reprompt
|
||||
// is on for this cipher, then show password reprompt
|
||||
if (
|
||||
cipher &&
|
||||
cipher.reprompt !== 0 &&
|
||||
@@ -768,10 +819,15 @@ export class VaultComponent implements OnInit, OnDestroy {
|
||||
return;
|
||||
}
|
||||
|
||||
if (this.extensionRefreshEnabled) {
|
||||
await this.editCipherIdV2(cipher, cloneCipher);
|
||||
return;
|
||||
}
|
||||
|
||||
const defaultComponentParameters = (comp: AddEditComponent) => {
|
||||
comp.organization = this.organization;
|
||||
comp.organizationId = this.organization.id;
|
||||
comp.cipherId = cipherId;
|
||||
comp.cipherId = cipher.id;
|
||||
comp.onSavedCipher.pipe(takeUntil(this.destroy$)).subscribe(() => {
|
||||
modal.close();
|
||||
this.refresh();
|
||||
@@ -807,46 +863,70 @@ export class VaultComponent implements OnInit, OnDestroy {
|
||||
}
|
||||
|
||||
/**
|
||||
* Takes a cipher and its assigned collections to opens dialog where it can be viewed.
|
||||
* @param cipher - the cipher to view
|
||||
* @param collections - the collections the cipher is assigned to
|
||||
* Edit a cipher using the new AddEditCipherDialogV2 component.
|
||||
* Only to be used behind the ExtensionRefresh feature flag.
|
||||
*/
|
||||
async viewCipher(cipher: CipherView, collections: CollectionView[] = []) {
|
||||
private async editCipherIdV2(cipher: CipherView, cloneCipher: boolean) {
|
||||
const cipherFormConfig = await this.cipherFormConfigService.buildConfig(
|
||||
cloneCipher ? "clone" : "edit",
|
||||
cipher.id as CipherId,
|
||||
);
|
||||
|
||||
await this.openVaultItemDialog("form", cipherFormConfig, cipher);
|
||||
}
|
||||
|
||||
/** Opens the view dialog for the given cipher unless password reprompt fails */
|
||||
async viewCipherById(cipher: CipherView) {
|
||||
if (!cipher) {
|
||||
this.go({ cipherId: null, itemId: null });
|
||||
return;
|
||||
}
|
||||
|
||||
if (cipher.reprompt !== 0 && !(await this.passwordRepromptService.showPasswordPrompt())) {
|
||||
// didn't pass password prompt, so don't open the dialog
|
||||
this.go({ cipherId: null, itemId: null });
|
||||
if (
|
||||
cipher &&
|
||||
cipher.reprompt !== 0 &&
|
||||
!(await this.passwordRepromptService.showPasswordPrompt())
|
||||
) {
|
||||
// Didn't pass password prompt, so don't open add / edit modal.
|
||||
await this.go({ cipherId: null, itemId: null, action: null });
|
||||
return;
|
||||
}
|
||||
|
||||
const dialogRef = openViewCipherDialog(this.dialogService, {
|
||||
data: {
|
||||
cipher: cipher,
|
||||
collections: collections,
|
||||
disableEdit: !cipher.edit && !this.organization.canEditAllCiphers,
|
||||
},
|
||||
const cipherFormConfig = await this.cipherFormConfigService.buildConfig(
|
||||
"edit",
|
||||
cipher.id as CipherId,
|
||||
cipher.type,
|
||||
);
|
||||
|
||||
await this.openVaultItemDialog("view", cipherFormConfig, cipher);
|
||||
}
|
||||
|
||||
/**
|
||||
* Open the combined view / edit dialog for a cipher.
|
||||
*/
|
||||
async openVaultItemDialog(
|
||||
mode: VaultItemDialogMode,
|
||||
formConfig: CipherFormConfig,
|
||||
cipher?: CipherView,
|
||||
) {
|
||||
const disableForm = cipher ? !cipher.edit && !this.organization.canEditAllCiphers : false;
|
||||
// If the form is disabled, force the mode into `view`
|
||||
const dialogMode = disableForm ? "view" : mode;
|
||||
this.vaultItemDialogRef = VaultItemDialogComponent.open(this.dialogService, {
|
||||
mode: dialogMode,
|
||||
formConfig,
|
||||
disableForm,
|
||||
});
|
||||
|
||||
// Wait for the dialog to close.
|
||||
const result: ViewCipherDialogCloseResult = await lastValueFrom(dialogRef.closed);
|
||||
|
||||
// If the dialog was closed by clicking the edit button, navigate to open the edit dialog.
|
||||
if (result?.action === ViewCipherDialogResult.Edited) {
|
||||
this.go({ itemId: cipher.id, action: "edit" });
|
||||
return;
|
||||
}
|
||||
const result = await lastValueFrom(this.vaultItemDialogRef.closed);
|
||||
this.vaultItemDialogRef = undefined;
|
||||
|
||||
// If the dialog was closed by deleting the cipher, refresh the vault.
|
||||
if (result?.action === ViewCipherDialogResult.Deleted) {
|
||||
if (result === VaultItemDialogResult.Deleted || result === VaultItemDialogResult.Saved) {
|
||||
this.refresh();
|
||||
}
|
||||
|
||||
// Clear the query params when the view dialog closes
|
||||
this.go({ cipherId: null, itemId: null, action: null });
|
||||
// Clear the query params when the dialog closes
|
||||
await this.go({ cipherId: null, itemId: null, action: null });
|
||||
}
|
||||
|
||||
async cloneCipher(cipher: CipherView) {
|
||||
@@ -867,7 +947,7 @@ export class VaultComponent implements OnInit, OnDestroy {
|
||||
// Admins limited to only adding items to collections they have access to.
|
||||
collections = await firstValueFrom(this.editableCollections$);
|
||||
|
||||
await this.editCipher(cipher, (comp) => {
|
||||
await this.editCipher(cipher, true, (comp) => {
|
||||
comp.cloneMode = true;
|
||||
comp.collections = collections;
|
||||
comp.collectionIds = cipher.collectionIds;
|
||||
|
||||
@@ -673,6 +673,8 @@ export class CipherService implements CipherServiceAbstraction {
|
||||
if (orgAdmin && cipher.organizationId != null) {
|
||||
const request = new CipherCreateRequest(cipher);
|
||||
response = await this.apiService.postCipherAdmin(request);
|
||||
const data = new CipherData(response, cipher.collectionIds);
|
||||
return new Cipher(data);
|
||||
} else if (cipher.collectionIds != null) {
|
||||
const request = new CipherCreateRequest(cipher);
|
||||
response = await this.apiService.postCipherCreate(request);
|
||||
@@ -697,6 +699,8 @@ export class CipherService implements CipherServiceAbstraction {
|
||||
if (orgAdmin && isNotClone) {
|
||||
const request = new CipherRequest(cipher);
|
||||
response = await this.apiService.putCipherAdmin(cipher.id, request);
|
||||
const data = new CipherData(response, cipher.collectionIds);
|
||||
return new Cipher(data, cipher.localData);
|
||||
} else if (cipher.edit) {
|
||||
const request = new CipherRequest(cipher);
|
||||
response = await this.apiService.putCipher(cipher.id, request);
|
||||
|
||||
@@ -56,6 +56,16 @@ describe("1Password 1Pux Importer", () => {
|
||||
const SecureNoteDataJson = JSON.stringify(SecureNoteData);
|
||||
const SanitizedExportJson = JSON.stringify(SanitizedExport);
|
||||
|
||||
it("should not import items with state 'archived'", async () => {
|
||||
const importer = new OnePassword1PuxImporter();
|
||||
const archivedLoginData = LoginData;
|
||||
archivedLoginData["accounts"][0]["vaults"][0]["items"][0]["state"] = "archived";
|
||||
const archivedDataJson = JSON.stringify(archivedLoginData);
|
||||
const result = await importer.parse(archivedDataJson);
|
||||
expect(result != null).toBe(true);
|
||||
expect(result.ciphers.length).toBe(0);
|
||||
});
|
||||
|
||||
it("should parse login data", async () => {
|
||||
const importer = new OnePassword1PuxImporter();
|
||||
const result = await importer.parse(LoginDataJson);
|
||||
|
||||
@@ -26,7 +26,7 @@ export const APICredentialsData: ExportData = {
|
||||
favIndex: 0,
|
||||
createdAt: 1619465969,
|
||||
updatedAt: 1619466052,
|
||||
trashed: false,
|
||||
state: "active",
|
||||
categoryUuid: "112",
|
||||
details: {
|
||||
loginFields: [],
|
||||
@@ -41,7 +41,6 @@ export const APICredentialsData: ExportData = {
|
||||
value: {
|
||||
string: "apiuser@nullvalue.test",
|
||||
},
|
||||
indexAtSource: 0,
|
||||
guarded: true,
|
||||
multiline: false,
|
||||
dontGenerate: false,
|
||||
@@ -57,7 +56,6 @@ export const APICredentialsData: ExportData = {
|
||||
value: {
|
||||
concealed: "apiapiapiapiapiapiappy",
|
||||
},
|
||||
indexAtSource: 1,
|
||||
guarded: true,
|
||||
multiline: false,
|
||||
dontGenerate: true,
|
||||
@@ -73,7 +71,6 @@ export const APICredentialsData: ExportData = {
|
||||
value: {
|
||||
menu: "jwt",
|
||||
},
|
||||
indexAtSource: 2,
|
||||
guarded: false,
|
||||
multiline: false,
|
||||
dontGenerate: false,
|
||||
@@ -89,7 +86,6 @@ export const APICredentialsData: ExportData = {
|
||||
value: {
|
||||
string: "filename.jwt",
|
||||
},
|
||||
indexAtSource: 3,
|
||||
guarded: false,
|
||||
multiline: false,
|
||||
dontGenerate: false,
|
||||
@@ -105,7 +101,6 @@ export const APICredentialsData: ExportData = {
|
||||
value: {
|
||||
date: 1301918460,
|
||||
},
|
||||
indexAtSource: 4,
|
||||
guarded: false,
|
||||
multiline: false,
|
||||
dontGenerate: false,
|
||||
@@ -121,7 +116,6 @@ export const APICredentialsData: ExportData = {
|
||||
value: {
|
||||
date: 1932811260,
|
||||
},
|
||||
indexAtSource: 5,
|
||||
guarded: false,
|
||||
multiline: false,
|
||||
dontGenerate: false,
|
||||
@@ -137,7 +131,6 @@ export const APICredentialsData: ExportData = {
|
||||
value: {
|
||||
string: "not.your.everyday.hostname",
|
||||
},
|
||||
indexAtSource: 6,
|
||||
guarded: false,
|
||||
multiline: false,
|
||||
dontGenerate: false,
|
||||
|
||||
@@ -26,7 +26,7 @@ export const BankAccountData: ExportData = {
|
||||
favIndex: 0,
|
||||
createdAt: 1619466056,
|
||||
updatedAt: 1619466187,
|
||||
trashed: false,
|
||||
state: "active",
|
||||
categoryUuid: "101",
|
||||
details: {
|
||||
loginFields: [],
|
||||
@@ -41,7 +41,6 @@ export const BankAccountData: ExportData = {
|
||||
value: {
|
||||
string: "Super Credit Union",
|
||||
},
|
||||
indexAtSource: 0,
|
||||
guarded: false,
|
||||
multiline: false,
|
||||
dontGenerate: false,
|
||||
@@ -57,7 +56,6 @@ export const BankAccountData: ExportData = {
|
||||
value: {
|
||||
string: "Cool Guy",
|
||||
},
|
||||
indexAtSource: 1,
|
||||
guarded: false,
|
||||
multiline: false,
|
||||
dontGenerate: false,
|
||||
@@ -73,7 +71,6 @@ export const BankAccountData: ExportData = {
|
||||
value: {
|
||||
menu: "checking",
|
||||
},
|
||||
indexAtSource: 2,
|
||||
guarded: false,
|
||||
multiline: false,
|
||||
dontGenerate: false,
|
||||
@@ -89,7 +86,6 @@ export const BankAccountData: ExportData = {
|
||||
value: {
|
||||
string: "111000999",
|
||||
},
|
||||
indexAtSource: 3,
|
||||
guarded: false,
|
||||
multiline: false,
|
||||
dontGenerate: false,
|
||||
@@ -105,7 +101,6 @@ export const BankAccountData: ExportData = {
|
||||
value: {
|
||||
string: "192837465918273645",
|
||||
},
|
||||
indexAtSource: 4,
|
||||
guarded: false,
|
||||
multiline: false,
|
||||
dontGenerate: false,
|
||||
@@ -121,7 +116,6 @@ export const BankAccountData: ExportData = {
|
||||
value: {
|
||||
string: "123456",
|
||||
},
|
||||
indexAtSource: 5,
|
||||
guarded: false,
|
||||
multiline: false,
|
||||
dontGenerate: false,
|
||||
@@ -137,7 +131,6 @@ export const BankAccountData: ExportData = {
|
||||
value: {
|
||||
string: "DE12 123456",
|
||||
},
|
||||
indexAtSource: 6,
|
||||
guarded: false,
|
||||
multiline: false,
|
||||
dontGenerate: false,
|
||||
@@ -153,7 +146,6 @@ export const BankAccountData: ExportData = {
|
||||
value: {
|
||||
concealed: "5555",
|
||||
},
|
||||
indexAtSource: 7,
|
||||
guarded: false,
|
||||
multiline: false,
|
||||
dontGenerate: true,
|
||||
@@ -175,7 +167,6 @@ export const BankAccountData: ExportData = {
|
||||
value: {
|
||||
phone: "9399399933",
|
||||
},
|
||||
indexAtSource: 0,
|
||||
guarded: false,
|
||||
multiline: false,
|
||||
dontGenerate: false,
|
||||
@@ -191,7 +182,6 @@ export const BankAccountData: ExportData = {
|
||||
value: {
|
||||
string: "1 Fifth Avenue",
|
||||
},
|
||||
indexAtSource: 1,
|
||||
guarded: false,
|
||||
multiline: false,
|
||||
dontGenerate: false,
|
||||
|
||||
@@ -26,7 +26,7 @@ export const CreditCardData: ExportData = {
|
||||
favIndex: 0,
|
||||
createdAt: 1619465282,
|
||||
updatedAt: 1619465447,
|
||||
trashed: false,
|
||||
state: "active",
|
||||
categoryUuid: "002",
|
||||
details: {
|
||||
loginFields: [],
|
||||
@@ -41,7 +41,6 @@ export const CreditCardData: ExportData = {
|
||||
value: {
|
||||
string: "Fred Engels",
|
||||
},
|
||||
indexAtSource: 0,
|
||||
guarded: true,
|
||||
multiline: false,
|
||||
dontGenerate: false,
|
||||
@@ -57,7 +56,6 @@ export const CreditCardData: ExportData = {
|
||||
value: {
|
||||
creditCardType: "discover",
|
||||
},
|
||||
indexAtSource: 1,
|
||||
guarded: true,
|
||||
multiline: false,
|
||||
dontGenerate: false,
|
||||
@@ -73,7 +71,6 @@ export const CreditCardData: ExportData = {
|
||||
value: {
|
||||
creditCardNumber: "6011111111111117",
|
||||
},
|
||||
indexAtSource: 2,
|
||||
guarded: true,
|
||||
clipboardFilter: "0123456789",
|
||||
multiline: false,
|
||||
@@ -90,7 +87,6 @@ export const CreditCardData: ExportData = {
|
||||
value: {
|
||||
concealed: "1312",
|
||||
},
|
||||
indexAtSource: 3,
|
||||
guarded: true,
|
||||
multiline: false,
|
||||
dontGenerate: true,
|
||||
@@ -106,7 +102,6 @@ export const CreditCardData: ExportData = {
|
||||
value: {
|
||||
monthYear: 209912,
|
||||
},
|
||||
indexAtSource: 4,
|
||||
guarded: true,
|
||||
multiline: false,
|
||||
dontGenerate: false,
|
||||
@@ -122,7 +117,6 @@ export const CreditCardData: ExportData = {
|
||||
value: {
|
||||
monthYear: 200101,
|
||||
},
|
||||
indexAtSource: 5,
|
||||
guarded: true,
|
||||
multiline: false,
|
||||
dontGenerate: false,
|
||||
@@ -138,7 +132,6 @@ export const CreditCardData: ExportData = {
|
||||
value: {
|
||||
string: "card",
|
||||
},
|
||||
indexAtSource: 6,
|
||||
guarded: false,
|
||||
multiline: false,
|
||||
dontGenerate: false,
|
||||
@@ -160,7 +153,6 @@ export const CreditCardData: ExportData = {
|
||||
value: {
|
||||
string: "Some bank",
|
||||
},
|
||||
indexAtSource: 0,
|
||||
guarded: false,
|
||||
multiline: false,
|
||||
dontGenerate: false,
|
||||
@@ -176,7 +168,6 @@ export const CreditCardData: ExportData = {
|
||||
value: {
|
||||
phone: "123456",
|
||||
},
|
||||
indexAtSource: 1,
|
||||
guarded: false,
|
||||
multiline: false,
|
||||
dontGenerate: false,
|
||||
@@ -192,7 +183,6 @@ export const CreditCardData: ExportData = {
|
||||
value: {
|
||||
phone: "0800123456",
|
||||
},
|
||||
indexAtSource: 2,
|
||||
guarded: false,
|
||||
multiline: false,
|
||||
dontGenerate: false,
|
||||
@@ -208,7 +198,6 @@ export const CreditCardData: ExportData = {
|
||||
value: {
|
||||
phone: "+49123456",
|
||||
},
|
||||
indexAtSource: 3,
|
||||
guarded: false,
|
||||
multiline: false,
|
||||
dontGenerate: false,
|
||||
@@ -224,7 +213,6 @@ export const CreditCardData: ExportData = {
|
||||
value: {
|
||||
url: "somebank.com",
|
||||
},
|
||||
indexAtSource: 4,
|
||||
guarded: false,
|
||||
multiline: false,
|
||||
dontGenerate: false,
|
||||
@@ -246,7 +234,6 @@ export const CreditCardData: ExportData = {
|
||||
value: {
|
||||
concealed: "1234",
|
||||
},
|
||||
indexAtSource: 0,
|
||||
guarded: false,
|
||||
multiline: false,
|
||||
dontGenerate: true,
|
||||
@@ -262,7 +249,6 @@ export const CreditCardData: ExportData = {
|
||||
value: {
|
||||
string: "$1312",
|
||||
},
|
||||
indexAtSource: 1,
|
||||
guarded: false,
|
||||
multiline: false,
|
||||
dontGenerate: false,
|
||||
@@ -278,7 +264,6 @@ export const CreditCardData: ExportData = {
|
||||
value: {
|
||||
string: "$500",
|
||||
},
|
||||
indexAtSource: 2,
|
||||
guarded: false,
|
||||
multiline: false,
|
||||
dontGenerate: false,
|
||||
@@ -294,7 +279,6 @@ export const CreditCardData: ExportData = {
|
||||
value: {
|
||||
string: "1%",
|
||||
},
|
||||
indexAtSource: 3,
|
||||
guarded: false,
|
||||
multiline: false,
|
||||
dontGenerate: false,
|
||||
@@ -310,7 +294,6 @@ export const CreditCardData: ExportData = {
|
||||
value: {
|
||||
string: "123456",
|
||||
},
|
||||
indexAtSource: 4,
|
||||
guarded: false,
|
||||
multiline: false,
|
||||
dontGenerate: false,
|
||||
|
||||
@@ -26,7 +26,7 @@ export const DatabaseData: ExportData = {
|
||||
favIndex: 0,
|
||||
createdAt: 1619466193,
|
||||
updatedAt: 1619466276,
|
||||
trashed: false,
|
||||
state: "active",
|
||||
categoryUuid: "102",
|
||||
details: {
|
||||
loginFields: [],
|
||||
@@ -41,7 +41,6 @@ export const DatabaseData: ExportData = {
|
||||
value: {
|
||||
menu: "postgresql",
|
||||
},
|
||||
indexAtSource: 0,
|
||||
guarded: false,
|
||||
multiline: false,
|
||||
dontGenerate: false,
|
||||
@@ -57,7 +56,6 @@ export const DatabaseData: ExportData = {
|
||||
value: {
|
||||
string: "my.secret.db.server",
|
||||
},
|
||||
indexAtSource: 1,
|
||||
guarded: false,
|
||||
multiline: false,
|
||||
dontGenerate: false,
|
||||
@@ -73,7 +71,6 @@ export const DatabaseData: ExportData = {
|
||||
value: {
|
||||
string: "1337",
|
||||
},
|
||||
indexAtSource: 2,
|
||||
guarded: false,
|
||||
multiline: false,
|
||||
dontGenerate: false,
|
||||
@@ -89,7 +86,6 @@ export const DatabaseData: ExportData = {
|
||||
value: {
|
||||
string: "user_database",
|
||||
},
|
||||
indexAtSource: 3,
|
||||
guarded: false,
|
||||
multiline: false,
|
||||
dontGenerate: false,
|
||||
@@ -105,7 +101,6 @@ export const DatabaseData: ExportData = {
|
||||
value: {
|
||||
string: "cooldbuser",
|
||||
},
|
||||
indexAtSource: 4,
|
||||
guarded: false,
|
||||
multiline: false,
|
||||
dontGenerate: false,
|
||||
@@ -121,7 +116,6 @@ export const DatabaseData: ExportData = {
|
||||
value: {
|
||||
concealed: "^+kTjhLaN7wVPAhGU)*J",
|
||||
},
|
||||
indexAtSource: 5,
|
||||
guarded: false,
|
||||
multiline: false,
|
||||
dontGenerate: false,
|
||||
@@ -137,7 +131,6 @@ export const DatabaseData: ExportData = {
|
||||
value: {
|
||||
string: "ASDIUFU-283234",
|
||||
},
|
||||
indexAtSource: 6,
|
||||
guarded: false,
|
||||
multiline: false,
|
||||
dontGenerate: false,
|
||||
@@ -153,7 +146,6 @@ export const DatabaseData: ExportData = {
|
||||
value: {
|
||||
string: "cdbu",
|
||||
},
|
||||
indexAtSource: 7,
|
||||
guarded: false,
|
||||
multiline: false,
|
||||
dontGenerate: false,
|
||||
@@ -169,7 +161,6 @@ export const DatabaseData: ExportData = {
|
||||
value: {
|
||||
string: "ssh",
|
||||
},
|
||||
indexAtSource: 8,
|
||||
guarded: false,
|
||||
multiline: false,
|
||||
dontGenerate: false,
|
||||
|
||||
@@ -26,7 +26,7 @@ export const DriversLicenseData: ExportData = {
|
||||
favIndex: 0,
|
||||
createdAt: 1619466279,
|
||||
updatedAt: 1619466425,
|
||||
trashed: false,
|
||||
state: "active",
|
||||
categoryUuid: "103",
|
||||
details: {
|
||||
loginFields: [],
|
||||
@@ -41,7 +41,6 @@ export const DriversLicenseData: ExportData = {
|
||||
value: {
|
||||
string: "Michael Scarn",
|
||||
},
|
||||
indexAtSource: 0,
|
||||
guarded: false,
|
||||
multiline: false,
|
||||
dontGenerate: false,
|
||||
@@ -57,7 +56,6 @@ export const DriversLicenseData: ExportData = {
|
||||
value: {
|
||||
string: "2120 Mifflin Rd.",
|
||||
},
|
||||
indexAtSource: 1,
|
||||
guarded: false,
|
||||
multiline: false,
|
||||
dontGenerate: false,
|
||||
@@ -73,7 +71,6 @@ export const DriversLicenseData: ExportData = {
|
||||
value: {
|
||||
date: 252504060,
|
||||
},
|
||||
indexAtSource: 2,
|
||||
guarded: false,
|
||||
multiline: false,
|
||||
dontGenerate: false,
|
||||
@@ -89,7 +86,6 @@ export const DriversLicenseData: ExportData = {
|
||||
value: {
|
||||
gender: "male",
|
||||
},
|
||||
indexAtSource: 3,
|
||||
guarded: false,
|
||||
multiline: false,
|
||||
dontGenerate: false,
|
||||
@@ -105,7 +101,6 @@ export const DriversLicenseData: ExportData = {
|
||||
value: {
|
||||
string: "5'11\"",
|
||||
},
|
||||
indexAtSource: 4,
|
||||
guarded: false,
|
||||
multiline: false,
|
||||
dontGenerate: false,
|
||||
@@ -121,7 +116,6 @@ export const DriversLicenseData: ExportData = {
|
||||
value: {
|
||||
string: "12345678901",
|
||||
},
|
||||
indexAtSource: 5,
|
||||
guarded: false,
|
||||
multiline: false,
|
||||
dontGenerate: false,
|
||||
@@ -137,7 +131,6 @@ export const DriversLicenseData: ExportData = {
|
||||
value: {
|
||||
string: "C",
|
||||
},
|
||||
indexAtSource: 6,
|
||||
guarded: false,
|
||||
multiline: false,
|
||||
dontGenerate: false,
|
||||
@@ -153,7 +146,6 @@ export const DriversLicenseData: ExportData = {
|
||||
value: {
|
||||
string: "B",
|
||||
},
|
||||
indexAtSource: 7,
|
||||
guarded: false,
|
||||
multiline: false,
|
||||
dontGenerate: false,
|
||||
@@ -169,7 +161,6 @@ export const DriversLicenseData: ExportData = {
|
||||
value: {
|
||||
string: "Pennsylvania",
|
||||
},
|
||||
indexAtSource: 8,
|
||||
guarded: false,
|
||||
multiline: false,
|
||||
dontGenerate: false,
|
||||
@@ -185,7 +176,6 @@ export const DriversLicenseData: ExportData = {
|
||||
value: {
|
||||
string: "United States",
|
||||
},
|
||||
indexAtSource: 9,
|
||||
guarded: false,
|
||||
multiline: false,
|
||||
dontGenerate: false,
|
||||
@@ -201,7 +191,6 @@ export const DriversLicenseData: ExportData = {
|
||||
value: {
|
||||
monthYear: 203012,
|
||||
},
|
||||
indexAtSource: 10,
|
||||
guarded: false,
|
||||
multiline: false,
|
||||
dontGenerate: false,
|
||||
|
||||
@@ -26,7 +26,7 @@ export const EmailAccountData: ExportData = {
|
||||
favIndex: 0,
|
||||
createdAt: 1619466428,
|
||||
updatedAt: 1619466585,
|
||||
trashed: false,
|
||||
state: "active",
|
||||
categoryUuid: "111",
|
||||
details: {
|
||||
loginFields: [],
|
||||
@@ -41,7 +41,6 @@ export const EmailAccountData: ExportData = {
|
||||
value: {
|
||||
menu: "either",
|
||||
},
|
||||
indexAtSource: 0,
|
||||
guarded: false,
|
||||
multiline: false,
|
||||
dontGenerate: false,
|
||||
@@ -57,7 +56,6 @@ export const EmailAccountData: ExportData = {
|
||||
value: {
|
||||
string: "someuser@nullvalue.test",
|
||||
},
|
||||
indexAtSource: 1,
|
||||
guarded: false,
|
||||
multiline: false,
|
||||
dontGenerate: false,
|
||||
@@ -73,7 +71,6 @@ export const EmailAccountData: ExportData = {
|
||||
value: {
|
||||
string: "mailserver.nullvalue.test",
|
||||
},
|
||||
indexAtSource: 2,
|
||||
guarded: false,
|
||||
multiline: false,
|
||||
dontGenerate: false,
|
||||
@@ -89,7 +86,6 @@ export const EmailAccountData: ExportData = {
|
||||
value: {
|
||||
string: "587",
|
||||
},
|
||||
indexAtSource: 3,
|
||||
guarded: false,
|
||||
multiline: false,
|
||||
dontGenerate: false,
|
||||
@@ -105,7 +101,6 @@ export const EmailAccountData: ExportData = {
|
||||
value: {
|
||||
concealed: "u1jsf<UI*&YU&^T",
|
||||
},
|
||||
indexAtSource: 4,
|
||||
guarded: false,
|
||||
multiline: false,
|
||||
dontGenerate: false,
|
||||
@@ -121,7 +116,6 @@ export const EmailAccountData: ExportData = {
|
||||
value: {
|
||||
menu: "TLS",
|
||||
},
|
||||
indexAtSource: 5,
|
||||
guarded: false,
|
||||
multiline: false,
|
||||
dontGenerate: false,
|
||||
@@ -137,7 +131,6 @@ export const EmailAccountData: ExportData = {
|
||||
value: {
|
||||
menu: "kerberos_v5",
|
||||
},
|
||||
indexAtSource: 6,
|
||||
guarded: false,
|
||||
multiline: false,
|
||||
dontGenerate: false,
|
||||
@@ -159,7 +152,6 @@ export const EmailAccountData: ExportData = {
|
||||
value: {
|
||||
string: "mailserver.nullvalue.test",
|
||||
},
|
||||
indexAtSource: 0,
|
||||
guarded: false,
|
||||
multiline: false,
|
||||
dontGenerate: false,
|
||||
@@ -175,7 +167,6 @@ export const EmailAccountData: ExportData = {
|
||||
value: {
|
||||
string: "589",
|
||||
},
|
||||
indexAtSource: 1,
|
||||
guarded: false,
|
||||
multiline: false,
|
||||
dontGenerate: false,
|
||||
@@ -191,7 +182,6 @@ export const EmailAccountData: ExportData = {
|
||||
value: {
|
||||
string: "someuser@nullvalue.test",
|
||||
},
|
||||
indexAtSource: 2,
|
||||
guarded: false,
|
||||
multiline: false,
|
||||
dontGenerate: false,
|
||||
@@ -207,7 +197,6 @@ export const EmailAccountData: ExportData = {
|
||||
value: {
|
||||
concealed: "(*1674%^UIUJ*UI(IUI8u98uyy",
|
||||
},
|
||||
indexAtSource: 3,
|
||||
guarded: false,
|
||||
multiline: false,
|
||||
dontGenerate: false,
|
||||
@@ -223,7 +212,6 @@ export const EmailAccountData: ExportData = {
|
||||
value: {
|
||||
menu: "TLS",
|
||||
},
|
||||
indexAtSource: 4,
|
||||
guarded: false,
|
||||
multiline: false,
|
||||
dontGenerate: false,
|
||||
@@ -239,7 +227,6 @@ export const EmailAccountData: ExportData = {
|
||||
value: {
|
||||
menu: "password",
|
||||
},
|
||||
indexAtSource: 5,
|
||||
guarded: false,
|
||||
multiline: false,
|
||||
dontGenerate: false,
|
||||
@@ -261,7 +248,6 @@ export const EmailAccountData: ExportData = {
|
||||
value: {
|
||||
string: "Telum",
|
||||
},
|
||||
indexAtSource: 0,
|
||||
guarded: false,
|
||||
multiline: false,
|
||||
dontGenerate: false,
|
||||
@@ -277,7 +263,6 @@ export const EmailAccountData: ExportData = {
|
||||
value: {
|
||||
string: "https://telum.nullvalue.test",
|
||||
},
|
||||
indexAtSource: 1,
|
||||
guarded: false,
|
||||
multiline: false,
|
||||
dontGenerate: false,
|
||||
@@ -293,7 +278,6 @@ export const EmailAccountData: ExportData = {
|
||||
value: {
|
||||
string: "2346666666",
|
||||
},
|
||||
indexAtSource: 2,
|
||||
guarded: false,
|
||||
multiline: false,
|
||||
dontGenerate: false,
|
||||
@@ -309,7 +293,6 @@ export const EmailAccountData: ExportData = {
|
||||
value: {
|
||||
string: "18005557777",
|
||||
},
|
||||
indexAtSource: 3,
|
||||
guarded: false,
|
||||
multiline: false,
|
||||
dontGenerate: false,
|
||||
|
||||
@@ -26,7 +26,7 @@ export const EmailFieldOnIdentityData: ExportData = {
|
||||
favIndex: 0,
|
||||
createdAt: 1619465450,
|
||||
updatedAt: 1619465789,
|
||||
trashed: false,
|
||||
state: "active",
|
||||
categoryUuid: "004",
|
||||
details: {
|
||||
loginFields: [],
|
||||
@@ -55,7 +55,6 @@ export const EmailFieldOnIdentityData: ExportData = {
|
||||
provider: "myEmailProvider",
|
||||
},
|
||||
},
|
||||
indexAtSource: 4,
|
||||
guarded: false,
|
||||
multiline: false,
|
||||
dontGenerate: false,
|
||||
|
||||
@@ -26,7 +26,7 @@ export const EmailFieldOnIdentityPrefilledData: ExportData = {
|
||||
favIndex: 0,
|
||||
createdAt: 1619465450,
|
||||
updatedAt: 1619465789,
|
||||
trashed: false,
|
||||
state: "active",
|
||||
categoryUuid: "004",
|
||||
details: {
|
||||
loginFields: [],
|
||||
@@ -52,7 +52,6 @@ export const EmailFieldOnIdentityPrefilledData: ExportData = {
|
||||
value: {
|
||||
string: "gengels@nullvalue.test",
|
||||
},
|
||||
indexAtSource: 4,
|
||||
guarded: false,
|
||||
multiline: false,
|
||||
dontGenerate: false,
|
||||
@@ -71,7 +70,6 @@ export const EmailFieldOnIdentityPrefilledData: ExportData = {
|
||||
provider: "myEmailProvider",
|
||||
},
|
||||
},
|
||||
indexAtSource: 1,
|
||||
guarded: false,
|
||||
multiline: false,
|
||||
dontGenerate: false,
|
||||
|
||||
@@ -26,7 +26,7 @@ export const EmailFieldData: ExportData = {
|
||||
favIndex: 1,
|
||||
createdAt: 1619467985,
|
||||
updatedAt: 1619468230,
|
||||
trashed: false,
|
||||
state: "active",
|
||||
categoryUuid: "100",
|
||||
details: {
|
||||
loginFields: [],
|
||||
@@ -49,7 +49,6 @@ export const EmailFieldData: ExportData = {
|
||||
provider: "myEmailProvider",
|
||||
},
|
||||
},
|
||||
indexAtSource: 1,
|
||||
guarded: false,
|
||||
multiline: false,
|
||||
dontGenerate: false,
|
||||
|
||||
@@ -26,7 +26,7 @@ export const IdentityData: ExportData = {
|
||||
favIndex: 0,
|
||||
createdAt: 1619465450,
|
||||
updatedAt: 1619465789,
|
||||
trashed: false,
|
||||
state: "active",
|
||||
categoryUuid: "004",
|
||||
details: {
|
||||
loginFields: [],
|
||||
@@ -42,7 +42,6 @@ export const IdentityData: ExportData = {
|
||||
value: {
|
||||
string: "George",
|
||||
},
|
||||
indexAtSource: 0,
|
||||
guarded: true,
|
||||
multiline: false,
|
||||
dontGenerate: false,
|
||||
@@ -58,7 +57,6 @@ export const IdentityData: ExportData = {
|
||||
value: {
|
||||
string: "S",
|
||||
},
|
||||
indexAtSource: 1,
|
||||
guarded: true,
|
||||
multiline: false,
|
||||
dontGenerate: false,
|
||||
@@ -74,7 +72,6 @@ export const IdentityData: ExportData = {
|
||||
value: {
|
||||
string: "Engels",
|
||||
},
|
||||
indexAtSource: 2,
|
||||
guarded: true,
|
||||
multiline: false,
|
||||
dontGenerate: false,
|
||||
@@ -90,7 +87,6 @@ export const IdentityData: ExportData = {
|
||||
value: {
|
||||
menu: "male",
|
||||
},
|
||||
indexAtSource: 3,
|
||||
guarded: true,
|
||||
multiline: false,
|
||||
dontGenerate: false,
|
||||
@@ -106,7 +102,6 @@ export const IdentityData: ExportData = {
|
||||
value: {
|
||||
date: 347198460,
|
||||
},
|
||||
indexAtSource: 4,
|
||||
guarded: true,
|
||||
multiline: false,
|
||||
dontGenerate: false,
|
||||
@@ -122,7 +117,6 @@ export const IdentityData: ExportData = {
|
||||
value: {
|
||||
string: "Steel Worker",
|
||||
},
|
||||
indexAtSource: 5,
|
||||
guarded: true,
|
||||
multiline: false,
|
||||
dontGenerate: false,
|
||||
@@ -138,7 +132,6 @@ export const IdentityData: ExportData = {
|
||||
value: {
|
||||
string: "Acme Inc.",
|
||||
},
|
||||
indexAtSource: 6,
|
||||
guarded: true,
|
||||
multiline: false,
|
||||
dontGenerate: false,
|
||||
@@ -154,7 +147,6 @@ export const IdentityData: ExportData = {
|
||||
value: {
|
||||
string: "QA",
|
||||
},
|
||||
indexAtSource: 7,
|
||||
guarded: true,
|
||||
multiline: false,
|
||||
dontGenerate: false,
|
||||
@@ -170,7 +162,6 @@ export const IdentityData: ExportData = {
|
||||
value: {
|
||||
string: "Quality Assurance Manager",
|
||||
},
|
||||
indexAtSource: 8,
|
||||
guarded: true,
|
||||
multiline: false,
|
||||
dontGenerate: false,
|
||||
@@ -198,7 +189,6 @@ export const IdentityData: ExportData = {
|
||||
state: "California",
|
||||
},
|
||||
},
|
||||
indexAtSource: 0,
|
||||
guarded: true,
|
||||
multiline: false,
|
||||
dontGenerate: false,
|
||||
@@ -214,7 +204,6 @@ export const IdentityData: ExportData = {
|
||||
value: {
|
||||
phone: "4565555555",
|
||||
},
|
||||
indexAtSource: 1,
|
||||
guarded: true,
|
||||
multiline: false,
|
||||
dontGenerate: false,
|
||||
@@ -230,7 +219,6 @@ export const IdentityData: ExportData = {
|
||||
value: {
|
||||
phone: "4575555555",
|
||||
},
|
||||
indexAtSource: 2,
|
||||
guarded: true,
|
||||
multiline: false,
|
||||
dontGenerate: false,
|
||||
@@ -246,7 +234,6 @@ export const IdentityData: ExportData = {
|
||||
value: {
|
||||
phone: "4585555555",
|
||||
},
|
||||
indexAtSource: 3,
|
||||
guarded: true,
|
||||
multiline: false,
|
||||
dontGenerate: false,
|
||||
@@ -262,7 +249,6 @@ export const IdentityData: ExportData = {
|
||||
value: {
|
||||
phone: "4595555555",
|
||||
},
|
||||
indexAtSource: 4,
|
||||
guarded: true,
|
||||
multiline: false,
|
||||
dontGenerate: false,
|
||||
@@ -284,7 +270,6 @@ export const IdentityData: ExportData = {
|
||||
value: {
|
||||
string: "gengels",
|
||||
},
|
||||
indexAtSource: 0,
|
||||
guarded: true,
|
||||
multiline: false,
|
||||
dontGenerate: false,
|
||||
@@ -300,7 +285,6 @@ export const IdentityData: ExportData = {
|
||||
value: {
|
||||
string: "Who's a super cool guy?",
|
||||
},
|
||||
indexAtSource: 1,
|
||||
guarded: false,
|
||||
multiline: false,
|
||||
dontGenerate: false,
|
||||
@@ -316,7 +300,6 @@ export const IdentityData: ExportData = {
|
||||
value: {
|
||||
string: "Me, buddy.",
|
||||
},
|
||||
indexAtSource: 2,
|
||||
guarded: false,
|
||||
multiline: false,
|
||||
dontGenerate: false,
|
||||
@@ -332,7 +315,6 @@ export const IdentityData: ExportData = {
|
||||
value: {
|
||||
string: "gengels@nullvalue.test",
|
||||
},
|
||||
indexAtSource: 3,
|
||||
guarded: true,
|
||||
multiline: false,
|
||||
dontGenerate: false,
|
||||
@@ -348,7 +330,6 @@ export const IdentityData: ExportData = {
|
||||
value: {
|
||||
string: "cv.gengels.nullvalue.test",
|
||||
},
|
||||
indexAtSource: 4,
|
||||
guarded: false,
|
||||
multiline: false,
|
||||
dontGenerate: false,
|
||||
@@ -364,7 +345,6 @@ export const IdentityData: ExportData = {
|
||||
value: {
|
||||
string: "12345678",
|
||||
},
|
||||
indexAtSource: 5,
|
||||
guarded: false,
|
||||
multiline: false,
|
||||
dontGenerate: false,
|
||||
@@ -380,7 +360,6 @@ export const IdentityData: ExportData = {
|
||||
value: {
|
||||
string: "skypeisbad1619",
|
||||
},
|
||||
indexAtSource: 6,
|
||||
guarded: false,
|
||||
multiline: false,
|
||||
dontGenerate: false,
|
||||
@@ -396,7 +375,6 @@ export const IdentityData: ExportData = {
|
||||
value: {
|
||||
string: "aollol@lololol.aol.com",
|
||||
},
|
||||
indexAtSource: 7,
|
||||
guarded: false,
|
||||
multiline: false,
|
||||
dontGenerate: false,
|
||||
@@ -412,7 +390,6 @@ export const IdentityData: ExportData = {
|
||||
value: {
|
||||
string: "sk8rboi13@yah00.com",
|
||||
},
|
||||
indexAtSource: 8,
|
||||
guarded: false,
|
||||
multiline: false,
|
||||
dontGenerate: false,
|
||||
@@ -428,7 +405,6 @@ export const IdentityData: ExportData = {
|
||||
value: {
|
||||
string: "msnothankyou@msn&m&m.com",
|
||||
},
|
||||
indexAtSource: 9,
|
||||
guarded: false,
|
||||
multiline: false,
|
||||
dontGenerate: false,
|
||||
@@ -444,7 +420,6 @@ export const IdentityData: ExportData = {
|
||||
value: {
|
||||
string: "super cool guy",
|
||||
},
|
||||
indexAtSource: 10,
|
||||
guarded: false,
|
||||
multiline: false,
|
||||
dontGenerate: false,
|
||||
|
||||
@@ -26,7 +26,7 @@ export const LoginData: ExportData = {
|
||||
favIndex: 0,
|
||||
createdAt: 1635522833,
|
||||
updatedAt: 1635522872,
|
||||
trashed: false,
|
||||
state: "active",
|
||||
categoryUuid: "001",
|
||||
details: {
|
||||
loginFields: [
|
||||
@@ -68,7 +68,6 @@ export const LoginData: ExportData = {
|
||||
value: {
|
||||
string: "username123123",
|
||||
},
|
||||
indexAtSource: 0,
|
||||
guarded: false,
|
||||
multiline: false,
|
||||
dontGenerate: false,
|
||||
@@ -84,7 +83,6 @@ export const LoginData: ExportData = {
|
||||
value: {
|
||||
totp: "otpseed777",
|
||||
},
|
||||
indexAtSource: 0,
|
||||
guarded: false,
|
||||
multiline: false,
|
||||
dontGenerate: false,
|
||||
|
||||
@@ -26,7 +26,7 @@ export const MedicalRecordData: ExportData = {
|
||||
favIndex: 0,
|
||||
createdAt: 1641220207,
|
||||
updatedAt: 1641220326,
|
||||
trashed: false,
|
||||
state: "active",
|
||||
categoryUuid: "113",
|
||||
details: {
|
||||
loginFields: [],
|
||||
@@ -41,7 +41,6 @@ export const MedicalRecordData: ExportData = {
|
||||
value: {
|
||||
date: 1641038460,
|
||||
},
|
||||
indexAtSource: 0,
|
||||
guarded: true,
|
||||
multiline: false,
|
||||
dontGenerate: false,
|
||||
@@ -57,7 +56,6 @@ export const MedicalRecordData: ExportData = {
|
||||
value: {
|
||||
string: "some hospital/clinic",
|
||||
},
|
||||
indexAtSource: 1,
|
||||
guarded: true,
|
||||
multiline: false,
|
||||
dontGenerate: false,
|
||||
@@ -74,7 +72,6 @@ export const MedicalRecordData: ExportData = {
|
||||
value: {
|
||||
string: "Some Doctor",
|
||||
},
|
||||
indexAtSource: 2,
|
||||
guarded: true,
|
||||
multiline: false,
|
||||
dontGenerate: false,
|
||||
@@ -91,7 +88,6 @@ export const MedicalRecordData: ExportData = {
|
||||
value: {
|
||||
string: "Me",
|
||||
},
|
||||
indexAtSource: 3,
|
||||
guarded: true,
|
||||
multiline: false,
|
||||
dontGenerate: false,
|
||||
@@ -108,7 +104,6 @@ export const MedicalRecordData: ExportData = {
|
||||
value: {
|
||||
string: "unwell",
|
||||
},
|
||||
indexAtSource: 4,
|
||||
guarded: true,
|
||||
multiline: true,
|
||||
dontGenerate: false,
|
||||
@@ -131,7 +126,6 @@ export const MedicalRecordData: ExportData = {
|
||||
value: {
|
||||
string: "Insuline",
|
||||
},
|
||||
indexAtSource: 0,
|
||||
guarded: true,
|
||||
multiline: false,
|
||||
dontGenerate: false,
|
||||
@@ -148,7 +142,6 @@ export const MedicalRecordData: ExportData = {
|
||||
value: {
|
||||
string: "1",
|
||||
},
|
||||
indexAtSource: 1,
|
||||
guarded: true,
|
||||
multiline: false,
|
||||
dontGenerate: false,
|
||||
@@ -165,7 +158,6 @@ export const MedicalRecordData: ExportData = {
|
||||
value: {
|
||||
string: "multiple times a day",
|
||||
},
|
||||
indexAtSource: 2,
|
||||
guarded: true,
|
||||
multiline: true,
|
||||
dontGenerate: false,
|
||||
|
||||
@@ -26,7 +26,7 @@ export const MembershipData: ExportData = {
|
||||
favIndex: 1,
|
||||
createdAt: 1619467269,
|
||||
updatedAt: 1619467368,
|
||||
trashed: false,
|
||||
state: "active",
|
||||
categoryUuid: "105",
|
||||
details: {
|
||||
loginFields: [],
|
||||
@@ -41,7 +41,6 @@ export const MembershipData: ExportData = {
|
||||
value: {
|
||||
string: "National Public Library",
|
||||
},
|
||||
indexAtSource: 0,
|
||||
guarded: false,
|
||||
multiline: false,
|
||||
dontGenerate: false,
|
||||
@@ -57,7 +56,6 @@ export const MembershipData: ExportData = {
|
||||
value: {
|
||||
url: "https://npl.nullvalue.gov.test",
|
||||
},
|
||||
indexAtSource: 1,
|
||||
guarded: false,
|
||||
multiline: false,
|
||||
dontGenerate: false,
|
||||
@@ -73,7 +71,6 @@ export const MembershipData: ExportData = {
|
||||
value: {
|
||||
phone: "9995555555",
|
||||
},
|
||||
indexAtSource: 2,
|
||||
guarded: false,
|
||||
multiline: false,
|
||||
dontGenerate: false,
|
||||
@@ -89,7 +86,6 @@ export const MembershipData: ExportData = {
|
||||
value: {
|
||||
string: "George Engels",
|
||||
},
|
||||
indexAtSource: 3,
|
||||
guarded: false,
|
||||
multiline: false,
|
||||
dontGenerate: false,
|
||||
@@ -105,7 +101,6 @@ export const MembershipData: ExportData = {
|
||||
value: {
|
||||
monthYear: 199901,
|
||||
},
|
||||
indexAtSource: 4,
|
||||
guarded: false,
|
||||
multiline: false,
|
||||
dontGenerate: false,
|
||||
@@ -121,7 +116,6 @@ export const MembershipData: ExportData = {
|
||||
value: {
|
||||
monthYear: 203412,
|
||||
},
|
||||
indexAtSource: 5,
|
||||
guarded: false,
|
||||
multiline: false,
|
||||
dontGenerate: false,
|
||||
@@ -137,7 +131,6 @@ export const MembershipData: ExportData = {
|
||||
value: {
|
||||
string: "64783862",
|
||||
},
|
||||
indexAtSource: 6,
|
||||
guarded: false,
|
||||
multiline: false,
|
||||
dontGenerate: false,
|
||||
@@ -153,7 +146,6 @@ export const MembershipData: ExportData = {
|
||||
value: {
|
||||
concealed: "19191",
|
||||
},
|
||||
indexAtSource: 7,
|
||||
guarded: false,
|
||||
multiline: false,
|
||||
dontGenerate: false,
|
||||
|
||||
@@ -26,7 +26,7 @@ export const OnePuxExampleFile: ExportData = {
|
||||
favIndex: 1,
|
||||
createdAt: 1614298956,
|
||||
updatedAt: 1635346445,
|
||||
trashed: false,
|
||||
state: "active",
|
||||
categoryUuid: "001",
|
||||
details: {
|
||||
loginFields: [
|
||||
@@ -50,7 +50,6 @@ export const OnePuxExampleFile: ExportData = {
|
||||
value: {
|
||||
concealed: "12345",
|
||||
},
|
||||
indexAtSource: 0,
|
||||
guarded: false,
|
||||
multiline: false,
|
||||
dontGenerate: false,
|
||||
|
||||
@@ -26,7 +26,7 @@ export const OutdoorLicenseData: ExportData = {
|
||||
favIndex: 0,
|
||||
createdAt: 1619467374,
|
||||
updatedAt: 1619467492,
|
||||
trashed: false,
|
||||
state: "active",
|
||||
categoryUuid: "104",
|
||||
details: {
|
||||
loginFields: [],
|
||||
@@ -41,7 +41,6 @@ export const OutdoorLicenseData: ExportData = {
|
||||
value: {
|
||||
string: "Cash Bandit",
|
||||
},
|
||||
indexAtSource: 0,
|
||||
guarded: false,
|
||||
multiline: false,
|
||||
dontGenerate: false,
|
||||
@@ -57,7 +56,6 @@ export const OutdoorLicenseData: ExportData = {
|
||||
value: {
|
||||
date: 1617278460,
|
||||
},
|
||||
indexAtSource: 1,
|
||||
guarded: false,
|
||||
multiline: false,
|
||||
dontGenerate: false,
|
||||
@@ -73,7 +71,6 @@ export const OutdoorLicenseData: ExportData = {
|
||||
value: {
|
||||
date: 2343124860,
|
||||
},
|
||||
indexAtSource: 2,
|
||||
guarded: false,
|
||||
multiline: false,
|
||||
dontGenerate: false,
|
||||
@@ -89,7 +86,6 @@ export const OutdoorLicenseData: ExportData = {
|
||||
value: {
|
||||
string: "Bananas,blueberries,corn",
|
||||
},
|
||||
indexAtSource: 3,
|
||||
guarded: false,
|
||||
multiline: false,
|
||||
dontGenerate: false,
|
||||
@@ -105,7 +101,6 @@ export const OutdoorLicenseData: ExportData = {
|
||||
value: {
|
||||
string: "100/each",
|
||||
},
|
||||
indexAtSource: 4,
|
||||
guarded: false,
|
||||
multiline: false,
|
||||
dontGenerate: false,
|
||||
@@ -121,7 +116,6 @@ export const OutdoorLicenseData: ExportData = {
|
||||
value: {
|
||||
string: "Washington",
|
||||
},
|
||||
indexAtSource: 5,
|
||||
guarded: false,
|
||||
multiline: false,
|
||||
dontGenerate: false,
|
||||
@@ -137,7 +131,6 @@ export const OutdoorLicenseData: ExportData = {
|
||||
value: {
|
||||
string: "United States of America",
|
||||
},
|
||||
indexAtSource: 6,
|
||||
guarded: false,
|
||||
multiline: false,
|
||||
dontGenerate: false,
|
||||
|
||||
@@ -26,7 +26,7 @@ export const PassportData: ExportData = {
|
||||
favIndex: 0,
|
||||
createdAt: 1619467498,
|
||||
updatedAt: 1619467655,
|
||||
trashed: false,
|
||||
state: "active",
|
||||
categoryUuid: "106",
|
||||
details: {
|
||||
loginFields: [],
|
||||
@@ -41,7 +41,6 @@ export const PassportData: ExportData = {
|
||||
value: {
|
||||
string: "US Passport",
|
||||
},
|
||||
indexAtSource: 0,
|
||||
guarded: false,
|
||||
multiline: false,
|
||||
dontGenerate: false,
|
||||
@@ -57,7 +56,6 @@ export const PassportData: ExportData = {
|
||||
value: {
|
||||
string: "United States of America",
|
||||
},
|
||||
indexAtSource: 1,
|
||||
guarded: false,
|
||||
multiline: false,
|
||||
dontGenerate: false,
|
||||
@@ -73,7 +71,6 @@ export const PassportData: ExportData = {
|
||||
value: {
|
||||
string: "76436847",
|
||||
},
|
||||
indexAtSource: 2,
|
||||
guarded: false,
|
||||
multiline: false,
|
||||
dontGenerate: false,
|
||||
@@ -89,7 +86,6 @@ export const PassportData: ExportData = {
|
||||
value: {
|
||||
string: "David Global",
|
||||
},
|
||||
indexAtSource: 3,
|
||||
guarded: false,
|
||||
multiline: false,
|
||||
dontGenerate: false,
|
||||
@@ -105,7 +101,6 @@ export const PassportData: ExportData = {
|
||||
value: {
|
||||
gender: "female",
|
||||
},
|
||||
indexAtSource: 4,
|
||||
guarded: false,
|
||||
multiline: false,
|
||||
dontGenerate: false,
|
||||
@@ -121,7 +116,6 @@ export const PassportData: ExportData = {
|
||||
value: {
|
||||
string: "International",
|
||||
},
|
||||
indexAtSource: 5,
|
||||
guarded: false,
|
||||
multiline: false,
|
||||
dontGenerate: false,
|
||||
@@ -137,7 +131,6 @@ export const PassportData: ExportData = {
|
||||
value: {
|
||||
string: "Department of State",
|
||||
},
|
||||
indexAtSource: 6,
|
||||
guarded: false,
|
||||
multiline: false,
|
||||
dontGenerate: false,
|
||||
@@ -153,7 +146,6 @@ export const PassportData: ExportData = {
|
||||
value: {
|
||||
date: 418046460,
|
||||
},
|
||||
indexAtSource: 7,
|
||||
guarded: false,
|
||||
multiline: false,
|
||||
dontGenerate: false,
|
||||
@@ -169,7 +161,6 @@ export const PassportData: ExportData = {
|
||||
value: {
|
||||
string: "A cave somewhere in Maine",
|
||||
},
|
||||
indexAtSource: 8,
|
||||
guarded: false,
|
||||
multiline: false,
|
||||
dontGenerate: false,
|
||||
@@ -185,7 +176,6 @@ export const PassportData: ExportData = {
|
||||
value: {
|
||||
date: 1577880060,
|
||||
},
|
||||
indexAtSource: 9,
|
||||
guarded: false,
|
||||
multiline: false,
|
||||
dontGenerate: false,
|
||||
@@ -201,7 +191,6 @@ export const PassportData: ExportData = {
|
||||
value: {
|
||||
date: 2524651260,
|
||||
},
|
||||
indexAtSource: 10,
|
||||
guarded: false,
|
||||
multiline: false,
|
||||
dontGenerate: false,
|
||||
|
||||
@@ -26,7 +26,7 @@ export const PasswordData: ExportData = {
|
||||
favIndex: 0,
|
||||
createdAt: 1619465796,
|
||||
updatedAt: 1619465869,
|
||||
trashed: false,
|
||||
state: "active",
|
||||
categoryUuid: "005",
|
||||
details: {
|
||||
loginFields: [],
|
||||
|
||||
@@ -26,7 +26,7 @@ export const RewardsProgramData: ExportData = {
|
||||
favIndex: 0,
|
||||
createdAt: 1619467659,
|
||||
updatedAt: 1619467765,
|
||||
trashed: false,
|
||||
state: "active",
|
||||
categoryUuid: "107",
|
||||
details: {
|
||||
loginFields: [],
|
||||
@@ -41,7 +41,6 @@ export const RewardsProgramData: ExportData = {
|
||||
value: {
|
||||
string: "Super Cool Store Co.",
|
||||
},
|
||||
indexAtSource: 0,
|
||||
guarded: false,
|
||||
multiline: false,
|
||||
dontGenerate: false,
|
||||
@@ -57,7 +56,6 @@ export const RewardsProgramData: ExportData = {
|
||||
value: {
|
||||
string: "Chef Coldroom",
|
||||
},
|
||||
indexAtSource: 1,
|
||||
guarded: false,
|
||||
multiline: false,
|
||||
dontGenerate: false,
|
||||
@@ -73,7 +71,6 @@ export const RewardsProgramData: ExportData = {
|
||||
value: {
|
||||
string: "member-29813569",
|
||||
},
|
||||
indexAtSource: 2,
|
||||
guarded: false,
|
||||
clipboardFilter:
|
||||
"0123456789ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz",
|
||||
@@ -91,7 +88,6 @@ export const RewardsProgramData: ExportData = {
|
||||
value: {
|
||||
concealed: "99913",
|
||||
},
|
||||
indexAtSource: 3,
|
||||
guarded: false,
|
||||
multiline: false,
|
||||
dontGenerate: false,
|
||||
@@ -113,7 +109,6 @@ export const RewardsProgramData: ExportData = {
|
||||
value: {
|
||||
string: "additional member id",
|
||||
},
|
||||
indexAtSource: 0,
|
||||
guarded: false,
|
||||
multiline: false,
|
||||
dontGenerate: false,
|
||||
@@ -129,7 +124,6 @@ export const RewardsProgramData: ExportData = {
|
||||
value: {
|
||||
monthYear: 202101,
|
||||
},
|
||||
indexAtSource: 1,
|
||||
guarded: false,
|
||||
multiline: false,
|
||||
dontGenerate: false,
|
||||
@@ -145,7 +139,6 @@ export const RewardsProgramData: ExportData = {
|
||||
value: {
|
||||
phone: "123456",
|
||||
},
|
||||
indexAtSource: 2,
|
||||
guarded: false,
|
||||
multiline: false,
|
||||
dontGenerate: false,
|
||||
@@ -161,7 +154,6 @@ export const RewardsProgramData: ExportData = {
|
||||
value: {
|
||||
phone: "123456",
|
||||
},
|
||||
indexAtSource: 3,
|
||||
guarded: false,
|
||||
multiline: false,
|
||||
dontGenerate: false,
|
||||
@@ -177,7 +169,6 @@ export const RewardsProgramData: ExportData = {
|
||||
value: {
|
||||
url: "supercoolstore.com",
|
||||
},
|
||||
indexAtSource: 4,
|
||||
guarded: false,
|
||||
multiline: false,
|
||||
dontGenerate: false,
|
||||
|
||||
File diff suppressed because it is too large
Load Diff
@@ -26,7 +26,7 @@ export const SecureNoteData: ExportData = {
|
||||
favIndex: 0,
|
||||
createdAt: 1619465226,
|
||||
updatedAt: 1619465278,
|
||||
trashed: false,
|
||||
state: "active",
|
||||
categoryUuid: "003",
|
||||
details: {
|
||||
loginFields: [],
|
||||
|
||||
@@ -26,7 +26,7 @@ export const ServerData: ExportData = {
|
||||
favIndex: 0,
|
||||
createdAt: 1619467769,
|
||||
updatedAt: 1619467906,
|
||||
trashed: false,
|
||||
state: "active",
|
||||
categoryUuid: "110",
|
||||
details: {
|
||||
loginFields: [],
|
||||
@@ -41,7 +41,6 @@ export const ServerData: ExportData = {
|
||||
value: {
|
||||
string: "https://coolserver.nullvalue.test",
|
||||
},
|
||||
indexAtSource: 0,
|
||||
guarded: false,
|
||||
multiline: false,
|
||||
dontGenerate: false,
|
||||
@@ -57,7 +56,6 @@ export const ServerData: ExportData = {
|
||||
value: {
|
||||
string: "frankly-notsure",
|
||||
},
|
||||
indexAtSource: 1,
|
||||
guarded: false,
|
||||
multiline: false,
|
||||
dontGenerate: false,
|
||||
@@ -73,7 +71,6 @@ export const ServerData: ExportData = {
|
||||
value: {
|
||||
concealed: "*&YHJI87yjy78u",
|
||||
},
|
||||
indexAtSource: 2,
|
||||
guarded: false,
|
||||
multiline: false,
|
||||
dontGenerate: false,
|
||||
@@ -95,7 +92,6 @@ export const ServerData: ExportData = {
|
||||
value: {
|
||||
string: "https://coolserver.nullvalue.test/admin",
|
||||
},
|
||||
indexAtSource: 0,
|
||||
guarded: false,
|
||||
multiline: false,
|
||||
dontGenerate: false,
|
||||
@@ -111,7 +107,6 @@ export const ServerData: ExportData = {
|
||||
value: {
|
||||
string: "frankly-idontknowwhatimdoing",
|
||||
},
|
||||
indexAtSource: 1,
|
||||
guarded: false,
|
||||
multiline: false,
|
||||
dontGenerate: false,
|
||||
@@ -127,7 +122,6 @@ export const ServerData: ExportData = {
|
||||
value: {
|
||||
concealed: "^%RY&^YUiju8iUYHJI(U",
|
||||
},
|
||||
indexAtSource: 2,
|
||||
guarded: false,
|
||||
multiline: false,
|
||||
dontGenerate: false,
|
||||
@@ -149,7 +143,6 @@ export const ServerData: ExportData = {
|
||||
value: {
|
||||
string: "Private Hosting Provider Inc.",
|
||||
},
|
||||
indexAtSource: 0,
|
||||
guarded: false,
|
||||
multiline: false,
|
||||
dontGenerate: false,
|
||||
@@ -165,7 +158,6 @@ export const ServerData: ExportData = {
|
||||
value: {
|
||||
string: "https://phpi.nullvalue.test",
|
||||
},
|
||||
indexAtSource: 1,
|
||||
guarded: false,
|
||||
multiline: false,
|
||||
dontGenerate: false,
|
||||
@@ -181,7 +173,6 @@ export const ServerData: ExportData = {
|
||||
value: {
|
||||
string: "https://phpi.nullvalue.test/support",
|
||||
},
|
||||
indexAtSource: 2,
|
||||
guarded: false,
|
||||
multiline: false,
|
||||
dontGenerate: false,
|
||||
@@ -197,7 +188,6 @@ export const ServerData: ExportData = {
|
||||
value: {
|
||||
string: "8882569382",
|
||||
},
|
||||
indexAtSource: 3,
|
||||
guarded: false,
|
||||
multiline: false,
|
||||
dontGenerate: false,
|
||||
|
||||
@@ -26,7 +26,7 @@ export const SoftwareLicenseData: ExportData = {
|
||||
favIndex: 1,
|
||||
createdAt: 1619467985,
|
||||
updatedAt: 1619468230,
|
||||
trashed: false,
|
||||
state: "active",
|
||||
categoryUuid: "100",
|
||||
details: {
|
||||
loginFields: [],
|
||||
@@ -41,7 +41,6 @@ export const SoftwareLicenseData: ExportData = {
|
||||
value: {
|
||||
string: "5.10.1000",
|
||||
},
|
||||
indexAtSource: 0,
|
||||
guarded: false,
|
||||
multiline: false,
|
||||
dontGenerate: false,
|
||||
@@ -57,7 +56,6 @@ export const SoftwareLicenseData: ExportData = {
|
||||
value: {
|
||||
string: "265453-13457355-847327",
|
||||
},
|
||||
indexAtSource: 1,
|
||||
guarded: true,
|
||||
multiline: true,
|
||||
dontGenerate: false,
|
||||
@@ -79,7 +77,6 @@ export const SoftwareLicenseData: ExportData = {
|
||||
value: {
|
||||
string: "Kay Riddler",
|
||||
},
|
||||
indexAtSource: 0,
|
||||
guarded: false,
|
||||
multiline: false,
|
||||
dontGenerate: false,
|
||||
@@ -98,7 +95,6 @@ export const SoftwareLicenseData: ExportData = {
|
||||
provider: null,
|
||||
},
|
||||
},
|
||||
indexAtSource: 1,
|
||||
guarded: false,
|
||||
multiline: false,
|
||||
dontGenerate: false,
|
||||
@@ -114,7 +110,6 @@ export const SoftwareLicenseData: ExportData = {
|
||||
value: {
|
||||
string: "Riddles and Jigsaw Puzzles GmbH",
|
||||
},
|
||||
indexAtSource: 2,
|
||||
guarded: false,
|
||||
multiline: false,
|
||||
dontGenerate: false,
|
||||
@@ -136,7 +131,6 @@ export const SoftwareLicenseData: ExportData = {
|
||||
value: {
|
||||
url: "https://limuxcompany.nullvalue.test/5.10.1000/isos",
|
||||
},
|
||||
indexAtSource: 0,
|
||||
guarded: false,
|
||||
multiline: false,
|
||||
dontGenerate: false,
|
||||
@@ -152,7 +146,6 @@ export const SoftwareLicenseData: ExportData = {
|
||||
value: {
|
||||
string: "Limux Software and Hardware",
|
||||
},
|
||||
indexAtSource: 1,
|
||||
guarded: false,
|
||||
multiline: false,
|
||||
dontGenerate: false,
|
||||
@@ -168,7 +161,6 @@ export const SoftwareLicenseData: ExportData = {
|
||||
value: {
|
||||
url: "https://limuxcompany.nullvalue.test/",
|
||||
},
|
||||
indexAtSource: 2,
|
||||
guarded: false,
|
||||
multiline: false,
|
||||
dontGenerate: false,
|
||||
@@ -184,7 +176,6 @@ export const SoftwareLicenseData: ExportData = {
|
||||
value: {
|
||||
string: "$999",
|
||||
},
|
||||
indexAtSource: 3,
|
||||
guarded: false,
|
||||
multiline: false,
|
||||
dontGenerate: false,
|
||||
@@ -203,7 +194,6 @@ export const SoftwareLicenseData: ExportData = {
|
||||
provider: null,
|
||||
},
|
||||
},
|
||||
indexAtSource: 4,
|
||||
guarded: false,
|
||||
multiline: false,
|
||||
dontGenerate: false,
|
||||
@@ -225,7 +215,6 @@ export const SoftwareLicenseData: ExportData = {
|
||||
value: {
|
||||
date: 1617278460,
|
||||
},
|
||||
indexAtSource: 0,
|
||||
guarded: false,
|
||||
multiline: false,
|
||||
dontGenerate: false,
|
||||
@@ -241,7 +230,6 @@ export const SoftwareLicenseData: ExportData = {
|
||||
value: {
|
||||
string: "594839",
|
||||
},
|
||||
indexAtSource: 1,
|
||||
guarded: false,
|
||||
multiline: false,
|
||||
dontGenerate: false,
|
||||
@@ -257,7 +245,6 @@ export const SoftwareLicenseData: ExportData = {
|
||||
value: {
|
||||
string: "$1086.59",
|
||||
},
|
||||
indexAtSource: 2,
|
||||
guarded: false,
|
||||
multiline: false,
|
||||
dontGenerate: false,
|
||||
|
||||
@@ -26,7 +26,7 @@ export const SSNData: ExportData = {
|
||||
favIndex: 1,
|
||||
createdAt: 1619467910,
|
||||
updatedAt: 1619467982,
|
||||
trashed: false,
|
||||
state: "active",
|
||||
categoryUuid: "108",
|
||||
details: {
|
||||
loginFields: [],
|
||||
@@ -41,7 +41,6 @@ export const SSNData: ExportData = {
|
||||
value: {
|
||||
string: "Jack Judd",
|
||||
},
|
||||
indexAtSource: 0,
|
||||
guarded: false,
|
||||
multiline: false,
|
||||
dontGenerate: false,
|
||||
@@ -57,7 +56,6 @@ export const SSNData: ExportData = {
|
||||
value: {
|
||||
concealed: "131-216-1900",
|
||||
},
|
||||
indexAtSource: 1,
|
||||
guarded: false,
|
||||
multiline: false,
|
||||
dontGenerate: true,
|
||||
|
||||
@@ -26,7 +26,7 @@ export const WirelessRouterData: ExportData = {
|
||||
favIndex: 0,
|
||||
createdAt: 1577652307,
|
||||
updatedAt: 1577652307,
|
||||
trashed: false,
|
||||
state: "active",
|
||||
categoryUuid: "109",
|
||||
details: {
|
||||
loginFields: [],
|
||||
@@ -41,7 +41,6 @@ export const WirelessRouterData: ExportData = {
|
||||
value: {
|
||||
string: "pixel 2Xl",
|
||||
},
|
||||
indexAtSource: 0,
|
||||
guarded: false,
|
||||
multiline: false,
|
||||
dontGenerate: false,
|
||||
@@ -57,7 +56,6 @@ export const WirelessRouterData: ExportData = {
|
||||
value: {
|
||||
concealed: "BqatGTVQ9TCN72tLbjrsHqkb",
|
||||
},
|
||||
indexAtSource: 1,
|
||||
guarded: false,
|
||||
multiline: false,
|
||||
dontGenerate: false,
|
||||
@@ -73,7 +71,6 @@ export const WirelessRouterData: ExportData = {
|
||||
value: {
|
||||
string: "127.0.0.1",
|
||||
},
|
||||
indexAtSource: 2,
|
||||
guarded: false,
|
||||
multiline: false,
|
||||
dontGenerate: false,
|
||||
@@ -89,7 +86,6 @@ export const WirelessRouterData: ExportData = {
|
||||
value: {
|
||||
string: "some airportId",
|
||||
},
|
||||
indexAtSource: 3,
|
||||
guarded: false,
|
||||
multiline: false,
|
||||
dontGenerate: false,
|
||||
@@ -105,7 +101,6 @@ export const WirelessRouterData: ExportData = {
|
||||
value: {
|
||||
string: "some network name",
|
||||
},
|
||||
indexAtSource: 4,
|
||||
guarded: false,
|
||||
multiline: false,
|
||||
dontGenerate: false,
|
||||
@@ -121,7 +116,6 @@ export const WirelessRouterData: ExportData = {
|
||||
value: {
|
||||
menu: "WPA",
|
||||
},
|
||||
indexAtSource: 5,
|
||||
guarded: false,
|
||||
multiline: false,
|
||||
dontGenerate: false,
|
||||
@@ -137,7 +131,6 @@ export const WirelessRouterData: ExportData = {
|
||||
value: {
|
||||
concealed: "wifipassword",
|
||||
},
|
||||
indexAtSource: 6,
|
||||
guarded: false,
|
||||
multiline: false,
|
||||
dontGenerate: false,
|
||||
@@ -153,7 +146,6 @@ export const WirelessRouterData: ExportData = {
|
||||
value: {
|
||||
concealed: "diskpassword",
|
||||
},
|
||||
indexAtSource: 7,
|
||||
guarded: false,
|
||||
multiline: false,
|
||||
dontGenerate: false,
|
||||
|
||||
@@ -22,7 +22,7 @@ export class Parser {
|
||||
/*
|
||||
May return null when the chunk does not represent an account.
|
||||
All secure notes are ACCTs but not all of them store account information.
|
||||
|
||||
|
||||
TODO: Add a test for the folder case!
|
||||
TODO: Add a test case that covers secure note account!
|
||||
*/
|
||||
@@ -60,9 +60,17 @@ export class Parser {
|
||||
|
||||
// 3: url
|
||||
step = 3;
|
||||
let url = Utils.fromBufferToUtf8(
|
||||
this.decodeHexLoose(Utils.fromBufferToUtf8(this.readItem(reader))),
|
||||
);
|
||||
const urlEncoded = this.readItem(reader);
|
||||
let url =
|
||||
urlEncoded.length > 0 && urlEncoded[0] === 33 // 33 = '!'
|
||||
? // URL is encrypted
|
||||
await this.cryptoUtils.decryptAes256PlainWithDefault(
|
||||
urlEncoded,
|
||||
encryptionKey,
|
||||
placeholder,
|
||||
)
|
||||
: // URL is not encrypted
|
||||
Utils.fromBufferToUtf8(this.decodeHexLoose(Utils.fromBufferToUtf8(urlEncoded)));
|
||||
|
||||
// Ignore "group" accounts. They have no credentials.
|
||||
if (url == "http://group") {
|
||||
|
||||
@@ -37,7 +37,7 @@ export class OnePassword1PuxImporter extends BaseImporter implements Importer {
|
||||
// const personalVaults = account.vaults[0].filter((v) => v.attrs.type === VaultAttributeTypeEnum.Personal);
|
||||
account.vaults.forEach((vault: VaultsEntity) => {
|
||||
vault.items.forEach((item: Item) => {
|
||||
if (item.trashed === true) {
|
||||
if (item.state === "archived") {
|
||||
return;
|
||||
}
|
||||
|
||||
|
||||
@@ -53,7 +53,7 @@ export interface Item {
|
||||
favIndex: number;
|
||||
createdAt: number;
|
||||
updatedAt: number;
|
||||
trashed?: boolean;
|
||||
state: "active" | "archived";
|
||||
categoryUuid: string;
|
||||
details: Details;
|
||||
overview: Overview;
|
||||
@@ -88,12 +88,12 @@ export interface SectionsEntity {
|
||||
title: string;
|
||||
name?: string | null;
|
||||
fields?: FieldsEntity[] | null;
|
||||
hideAddAnotherField?: boolean | null;
|
||||
}
|
||||
export interface FieldsEntity {
|
||||
title: string;
|
||||
id: string;
|
||||
value: Value;
|
||||
indexAtSource: number;
|
||||
guarded: boolean;
|
||||
multiline: boolean;
|
||||
dontGenerate: boolean;
|
||||
@@ -153,6 +153,8 @@ export interface Overview {
|
||||
pbe?: number | null;
|
||||
pgrng?: boolean | null;
|
||||
tags?: string[] | null;
|
||||
icons?: string | null;
|
||||
watchtowerExclusions?: string | null;
|
||||
}
|
||||
export interface UrlsEntity {
|
||||
label: string;
|
||||
|
||||
@@ -27,6 +27,7 @@
|
||||
bitIconButton="bwi-generate"
|
||||
bitSuffix
|
||||
[appA11yTitle]="'generatePassword' | i18n"
|
||||
[disabled]="!config.areSendsAllowed"
|
||||
(click)="generatePassword()"
|
||||
data-testid="generate-password"
|
||||
></button>
|
||||
@@ -35,7 +36,7 @@
|
||||
bitIconButton="bwi-clone"
|
||||
bitSuffix
|
||||
[appA11yTitle]="'copyPassword' | i18n"
|
||||
[disabled]="!sendOptionsForm.get('password').value"
|
||||
[disabled]="!config.areSendsAllowed || !sendOptionsForm.get('password').value"
|
||||
[valueLabel]="'password' | i18n"
|
||||
[appCopyClick]="sendOptionsForm.get('password').value"
|
||||
showToast
|
||||
|
||||
@@ -79,6 +79,9 @@ type BaseCipherFormConfig = {
|
||||
* List of organizations that the user can create ciphers for.
|
||||
*/
|
||||
organizations?: Organization[];
|
||||
|
||||
/** Hides the fields that are only applicable to individuals, useful in the Admin Console where folders aren't applicable */
|
||||
hideIndividualVaultFields?: true;
|
||||
};
|
||||
|
||||
/**
|
||||
|
||||
@@ -2,6 +2,7 @@
|
||||
<bit-section-header>
|
||||
<h2 bitTypography="h6">{{ "itemDetails" | i18n }}</h2>
|
||||
<button
|
||||
*ngIf="!config.hideIndividualVaultFields"
|
||||
slot="end"
|
||||
type="button"
|
||||
size="small"
|
||||
@@ -18,7 +19,11 @@
|
||||
<input bitInput formControlName="name" />
|
||||
</bit-form-field>
|
||||
<div class="tw-grid tw-grid-cols-2 tw-gap-1">
|
||||
<bit-form-field *ngIf="showOwnership" [disableMargin]="!showCollectionsControl">
|
||||
<bit-form-field
|
||||
*ngIf="showOwnership"
|
||||
[disableMargin]="!showCollectionsControl"
|
||||
[class.tw-col-span-2]="config.hideIndividualVaultFields"
|
||||
>
|
||||
<bit-label>{{ "owner" | i18n }}</bit-label>
|
||||
<bit-select formControlName="organizationId">
|
||||
<bit-option
|
||||
@@ -36,6 +41,7 @@
|
||||
<bit-form-field
|
||||
[class.tw-col-span-2]="!showOwnership"
|
||||
[disableMargin]="!showCollectionsControl"
|
||||
*ngIf="!config.hideIndividualVaultFields"
|
||||
>
|
||||
<bit-label>{{ "folder" | i18n }}</bit-label>
|
||||
<bit-select formControlName="folderId">
|
||||
|
||||
8
package-lock.json
generated
8
package-lock.json
generated
@@ -194,11 +194,11 @@
|
||||
},
|
||||
"apps/browser": {
|
||||
"name": "@bitwarden/browser",
|
||||
"version": "2024.10.0"
|
||||
"version": "2024.10.1"
|
||||
},
|
||||
"apps/cli": {
|
||||
"name": "@bitwarden/cli",
|
||||
"version": "2024.9.1",
|
||||
"version": "2024.10.0",
|
||||
"license": "SEE LICENSE IN LICENSE.txt",
|
||||
"dependencies": {
|
||||
"@koa/multer": "3.0.2",
|
||||
@@ -234,7 +234,7 @@
|
||||
},
|
||||
"apps/desktop": {
|
||||
"name": "@bitwarden/desktop",
|
||||
"version": "2024.9.2",
|
||||
"version": "2024.10.0",
|
||||
"hasInstallScript": true,
|
||||
"license": "GPL-3.0"
|
||||
},
|
||||
@@ -248,7 +248,7 @@
|
||||
},
|
||||
"apps/web": {
|
||||
"name": "@bitwarden/web-vault",
|
||||
"version": "2024.10.0"
|
||||
"version": "2024.10.1"
|
||||
},
|
||||
"libs/admin-console": {
|
||||
"name": "@bitwarden/admin-console",
|
||||
|
||||
@@ -22,6 +22,7 @@
|
||||
"test:watch": "jest --clearCache && jest --watch",
|
||||
"test:watch:all": "jest --watchAll",
|
||||
"test:types": "node ./scripts/test-types.js",
|
||||
"test:locales": "tsc --project ./scripts/tsconfig.json && node ./scripts/dist/test-locales.js",
|
||||
"docs:json": "compodoc -p ./tsconfig.json -e json -d . --disableRoutesGraph",
|
||||
"storybook": "ng run components:storybook",
|
||||
"build-storybook": "ng run components:build-storybook",
|
||||
|
||||
5
scripts/.eslintrc.json
Normal file
5
scripts/.eslintrc.json
Normal file
@@ -0,0 +1,5 @@
|
||||
{
|
||||
"env": {
|
||||
"node": true
|
||||
}
|
||||
}
|
||||
105
scripts/test-locales.ts
Normal file
105
scripts/test-locales.ts
Normal file
@@ -0,0 +1,105 @@
|
||||
/* eslint no-console:0 */
|
||||
import fs from "fs";
|
||||
import path from "path";
|
||||
|
||||
type Messages = {
|
||||
[id: string]: {
|
||||
message: string;
|
||||
};
|
||||
};
|
||||
|
||||
function findLocaleFiles(dir: string): string[] {
|
||||
return fs
|
||||
.readdirSync(dir, { encoding: null, recursive: true })
|
||||
.filter((file) => path.basename(file) === "messages.json")
|
||||
.filter((file) => path.dirname(file).endsWith("en"))
|
||||
.map((file) => path.join(dir, file));
|
||||
}
|
||||
|
||||
function findAllLocaleFiles(rootDir: string): string[] {
|
||||
return [
|
||||
...findLocaleFiles(path.join(rootDir, "apps", "browser", "src")),
|
||||
...findLocaleFiles(path.join(rootDir, "apps", "cli", "src")),
|
||||
...findLocaleFiles(path.join(rootDir, "apps", "desktop", "src")),
|
||||
...findLocaleFiles(path.join(rootDir, "apps", "web", "src")),
|
||||
].map((file) => path.relative(rootDir, file));
|
||||
}
|
||||
|
||||
function readMessagesJson(file: string): Messages {
|
||||
let content = fs.readFileSync(file, { encoding: "utf-8" });
|
||||
// Strip BOM
|
||||
content = content.replace(/^\uFEFF/, "");
|
||||
try {
|
||||
return JSON.parse(content);
|
||||
} catch (e: unknown) {
|
||||
console.error(`ERROR: Invalid JSON file ${file}`, e);
|
||||
throw e;
|
||||
}
|
||||
}
|
||||
|
||||
function compareMessagesJson(beforeFile: string, afterFile: string): boolean {
|
||||
try {
|
||||
console.log("Comparing locale files:", beforeFile, afterFile);
|
||||
|
||||
const messagesBeforeJson = readMessagesJson(beforeFile);
|
||||
const messagesAfterJson = readMessagesJson(afterFile);
|
||||
|
||||
const messagesIdMapBefore = toMessageIdMap(messagesBeforeJson);
|
||||
const messagesIdMapAfter = toMessageIdMap(messagesAfterJson);
|
||||
|
||||
let changed = false;
|
||||
|
||||
for (const [id, message] of messagesIdMapAfter.entries()) {
|
||||
if (!messagesIdMapBefore.has(id)) {
|
||||
console.log("New message:", id);
|
||||
continue;
|
||||
}
|
||||
|
||||
if (messagesIdMapBefore.get(id) !== message) {
|
||||
console.error("ERROR: Message changed:", id);
|
||||
changed = true;
|
||||
}
|
||||
}
|
||||
|
||||
return changed;
|
||||
} catch (e: unknown) {
|
||||
console.error(`ERROR: Unable to compare files ${beforeFile} and ${afterFile}`, e);
|
||||
throw e;
|
||||
}
|
||||
}
|
||||
|
||||
function toMessageIdMap(messagesJson: Messages): Map<string, string> {
|
||||
return Object.entries(messagesJson).reduce((map, [id, value]) => {
|
||||
map.set(id, value.message);
|
||||
return map;
|
||||
}, new Map<string, string>());
|
||||
}
|
||||
|
||||
const rootDir = path.join(__dirname, "..", "..");
|
||||
const baseBranchRootDir = path.join(rootDir, "base");
|
||||
|
||||
const files = findAllLocaleFiles(rootDir);
|
||||
|
||||
console.log("Detected valid English locale files:", files);
|
||||
|
||||
let changedFiles = false;
|
||||
|
||||
for (const file of files) {
|
||||
const baseBranchFile = path.join(baseBranchRootDir, file);
|
||||
if (!fs.existsSync(baseBranchFile)) {
|
||||
console.error("ERROR: File not found in base branch:", file);
|
||||
continue;
|
||||
}
|
||||
|
||||
const changed = compareMessagesJson(baseBranchFile, path.join(rootDir, file));
|
||||
changedFiles ||= changed;
|
||||
}
|
||||
|
||||
if (changedFiles) {
|
||||
console.error(
|
||||
"ERROR: Incompatible Crowdin locale files. " +
|
||||
"All messages in messages.json locale files needs to be immutable and cannot be updated. " +
|
||||
"If a message needs to be changed, create a new message id and update your code to use it instead.",
|
||||
);
|
||||
process.exit(1);
|
||||
}
|
||||
9
scripts/tsconfig.json
Normal file
9
scripts/tsconfig.json
Normal file
@@ -0,0 +1,9 @@
|
||||
{
|
||||
"extends": "../libs/shared/tsconfig",
|
||||
"compilerOptions": {
|
||||
"outDir": "dist",
|
||||
"module": "NodeNext",
|
||||
"target": "ESNext"
|
||||
},
|
||||
"include": ["*.ts"]
|
||||
}
|
||||
@@ -42,6 +42,6 @@
|
||||
}
|
||||
]
|
||||
},
|
||||
"include": ["apps/**/*", "libs/**/*", "bitwarden_license/**/*"],
|
||||
"exclude": ["**/build"]
|
||||
"include": ["apps/**/*", "libs/**/*", "bitwarden_license/**/*", "scripts/**/*"],
|
||||
"exclude": ["**/build", "**/dist"]
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user