mirror of
https://github.com/bitwarden/browser.git
synced 2025-01-24 21:41:33 +01:00
Merge branch 'main' into auth/pm-8111/browser-refresh-login-component
This commit is contained in:
commit
0df9474f57
@ -2,6 +2,7 @@
|
||||
"devFlags": {},
|
||||
"flags": {
|
||||
"showPasswordless": true,
|
||||
"accountSwitching": false
|
||||
"accountSwitching": false,
|
||||
"sdk": true
|
||||
}
|
||||
}
|
||||
|
@ -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",
|
||||
|
@ -90,6 +90,7 @@ import { I18nService as I18nServiceAbstraction } from "@bitwarden/common/platfor
|
||||
import { KeyGenerationService as KeyGenerationServiceAbstraction } from "@bitwarden/common/platform/abstractions/key-generation.service";
|
||||
import { LogService as LogServiceAbstraction } from "@bitwarden/common/platform/abstractions/log.service";
|
||||
import { PlatformUtilsService as PlatformUtilsServiceAbstraction } from "@bitwarden/common/platform/abstractions/platform-utils.service";
|
||||
import { SdkService } from "@bitwarden/common/platform/abstractions/sdk/sdk.service";
|
||||
import { StateService as StateServiceAbstraction } from "@bitwarden/common/platform/abstractions/state.service";
|
||||
import {
|
||||
AbstractStorageService,
|
||||
@ -122,6 +123,8 @@ import { FileUploadService } from "@bitwarden/common/platform/services/file-uplo
|
||||
import { KeyGenerationService } from "@bitwarden/common/platform/services/key-generation.service";
|
||||
import { MigrationBuilderService } from "@bitwarden/common/platform/services/migration-builder.service";
|
||||
import { MigrationRunner } from "@bitwarden/common/platform/services/migration-runner";
|
||||
import { DefaultSdkService } from "@bitwarden/common/platform/services/sdk/default-sdk.service";
|
||||
import { NoopSdkClientFactory } from "@bitwarden/common/platform/services/sdk/noop-sdk-client-factory";
|
||||
import { StateService } from "@bitwarden/common/platform/services/state.service";
|
||||
import { SystemService } from "@bitwarden/common/platform/services/system.service";
|
||||
import { UserAutoUnlockKeyService } from "@bitwarden/common/platform/services/user-auto-unlock-key.service";
|
||||
@ -228,6 +231,7 @@ import AutofillService from "../autofill/services/autofill.service";
|
||||
import { SafariApp } from "../browser/safariApp";
|
||||
import { BackgroundBrowserBiometricsService } from "../key-management/biometrics/background-browser-biometrics.service";
|
||||
import { BrowserApi } from "../platform/browser/browser-api";
|
||||
import { flagEnabled } from "../platform/flags";
|
||||
import { UpdateBadge } from "../platform/listeners/update-badge";
|
||||
/* eslint-disable no-restricted-imports */
|
||||
import { ChromeMessageSender } from "../platform/messaging/chrome-message.sender";
|
||||
@ -245,6 +249,7 @@ import { LocalBackedSessionStorageService } from "../platform/services/local-bac
|
||||
import { BackgroundPlatformUtilsService } from "../platform/services/platform-utils/background-platform-utils.service";
|
||||
import { BrowserPlatformUtilsService } from "../platform/services/platform-utils/browser-platform-utils.service";
|
||||
import { PopupViewCacheBackgroundService } from "../platform/services/popup-view-cache-background.service";
|
||||
import { BrowserSdkClientFactory } from "../platform/services/sdk/browser-sdk-client-factory";
|
||||
import { BackgroundTaskSchedulerService } from "../platform/services/task-scheduler/background-task-scheduler.service";
|
||||
import { ForegroundTaskSchedulerService } from "../platform/services/task-scheduler/foreground-task-scheduler.service";
|
||||
import { BackgroundMemoryStorageService } from "../platform/storage/background-memory-storage.service";
|
||||
@ -364,6 +369,7 @@ export default class MainBackground {
|
||||
syncServiceListener: SyncServiceListener;
|
||||
themeStateService: DefaultThemeStateService;
|
||||
autoSubmitLoginBackground: AutoSubmitLoginBackground;
|
||||
sdkService: SdkService;
|
||||
|
||||
onUpdatedRan: boolean;
|
||||
onReplacedRan: boolean;
|
||||
@ -719,6 +725,16 @@ export default class MainBackground {
|
||||
this.stateProvider,
|
||||
);
|
||||
|
||||
const sdkClientFactory = flagEnabled("sdk")
|
||||
? new BrowserSdkClientFactory()
|
||||
: new NoopSdkClientFactory();
|
||||
this.sdkService = new DefaultSdkService(
|
||||
sdkClientFactory,
|
||||
this.environmentService,
|
||||
this.platformUtilsService,
|
||||
this.apiService,
|
||||
);
|
||||
|
||||
this.passwordStrengthService = new PasswordStrengthService();
|
||||
|
||||
this.passwordGenerationService = legacyPasswordGenerationServiceFactory(
|
||||
@ -1315,6 +1331,20 @@ export default class MainBackground {
|
||||
|
||||
await this.initOverlayAndTabsBackground();
|
||||
|
||||
if (flagEnabled("sdk")) {
|
||||
// Warn if the SDK for some reason can't be initialized
|
||||
let supported = false;
|
||||
try {
|
||||
supported = await firstValueFrom(this.sdkService.supported$);
|
||||
} catch (e) {
|
||||
// Do nothing.
|
||||
}
|
||||
|
||||
if (!supported) {
|
||||
this.sdkService.failedToInitialize().catch(this.logService.error);
|
||||
}
|
||||
}
|
||||
|
||||
return new Promise<void>((resolve) => {
|
||||
setTimeout(async () => {
|
||||
await this.refreshBadge();
|
||||
|
@ -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.",
|
||||
@ -39,8 +39,7 @@
|
||||
}
|
||||
],
|
||||
"background": {
|
||||
"service_worker": "background.js",
|
||||
"type": "module"
|
||||
"service_worker": "background.js"
|
||||
},
|
||||
"action": {
|
||||
"default_icon": {
|
||||
|
@ -0,0 +1,66 @@
|
||||
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 {
|
||||
if (typeof WebAssembly === "object" && typeof WebAssembly.instantiate === "function") {
|
||||
const module = new WebAssembly.Module(
|
||||
Uint8Array.of(0x0, 0x61, 0x73, 0x6d, 0x01, 0x00, 0x00, 0x00),
|
||||
);
|
||||
if (module instanceof WebAssembly.Module) {
|
||||
return new WebAssembly.Instance(module) instanceof WebAssembly.Instance;
|
||||
}
|
||||
}
|
||||
} catch (e) {
|
||||
// ignore
|
||||
}
|
||||
return false;
|
||||
})();
|
||||
|
||||
// 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");
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* SDK client factory with a js fallback for when WASM is not supported.
|
||||
*
|
||||
* Works both in popup and service worker.
|
||||
*/
|
||||
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
apps/browser/src/platform/services/sdk/fallback.ts
Normal file
8
apps/browser/src/platform/services/sdk/fallback.ts
Normal file
@ -0,0 +1,8 @@
|
||||
import * as sdk from "@bitwarden/sdk-internal";
|
||||
import * as wasm from "@bitwarden/sdk-internal/bitwarden_wasm_internal_bg.wasm.js";
|
||||
|
||||
(globalThis as any).init_sdk = (...args: ConstructorParameters<typeof sdk.BitwardenClient>) => {
|
||||
(sdk as any).init(wasm);
|
||||
|
||||
return new sdk.BitwardenClient(...args);
|
||||
};
|
8
apps/browser/src/platform/services/sdk/wasm.ts
Normal file
8
apps/browser/src/platform/services/sdk/wasm.ts
Normal file
@ -0,0 +1,8 @@
|
||||
import * as sdk from "@bitwarden/sdk-internal";
|
||||
import * as wasm from "@bitwarden/sdk-internal/bitwarden_wasm_internal_bg.wasm";
|
||||
|
||||
(globalThis as any).init_sdk = (...args: ConstructorParameters<typeof sdk.BitwardenClient>) => {
|
||||
(sdk as any).init(wasm);
|
||||
|
||||
return new sdk.BitwardenClient(...args);
|
||||
};
|
@ -1,6 +1,7 @@
|
||||
import { ChangeDetectorRef, Component, NgZone, OnDestroy, OnInit, inject } from "@angular/core";
|
||||
import { takeUntilDestroyed } from "@angular/core/rxjs-interop";
|
||||
import { NavigationEnd, Router, RouterOutlet } from "@angular/router";
|
||||
import { Subject, takeUntil, firstValueFrom, concatMap, filter, tap } from "rxjs";
|
||||
import { Subject, takeUntil, firstValueFrom, concatMap, filter, tap, catchError, of } from "rxjs";
|
||||
|
||||
import { LogoutReason } from "@bitwarden/auth/common";
|
||||
import { AccountService } from "@bitwarden/common/auth/abstractions/account.service";
|
||||
@ -8,7 +9,9 @@ import { AuthService } from "@bitwarden/common/auth/abstractions/auth.service";
|
||||
import { AuthenticationStatus } from "@bitwarden/common/auth/enums/authentication-status";
|
||||
import { AnimationControlService } from "@bitwarden/common/platform/abstractions/animation-control.service";
|
||||
import { I18nService } from "@bitwarden/common/platform/abstractions/i18n.service";
|
||||
import { LogService } from "@bitwarden/common/platform/abstractions/log.service";
|
||||
import { PlatformUtilsService } from "@bitwarden/common/platform/abstractions/platform-utils.service";
|
||||
import { SdkService } from "@bitwarden/common/platform/abstractions/sdk/sdk.service";
|
||||
import { StateService } from "@bitwarden/common/platform/abstractions/state.service";
|
||||
import { MessageListener } from "@bitwarden/common/platform/messaging";
|
||||
import { UserId } from "@bitwarden/common/types/guid";
|
||||
@ -20,6 +23,7 @@ import {
|
||||
ToastService,
|
||||
} from "@bitwarden/components";
|
||||
|
||||
import { flagEnabled } from "../platform/flags";
|
||||
import { PopupViewCacheService } from "../platform/popup/view-cache/popup-view-cache.service";
|
||||
import { initPopupClosedListener } from "../platform/services/popup-view-cache-background.service";
|
||||
import { BrowserSendStateService } from "../tools/popup/services/browser-send-state.service";
|
||||
@ -62,7 +66,28 @@ export class AppComponent implements OnInit, OnDestroy {
|
||||
private toastService: ToastService,
|
||||
private accountService: AccountService,
|
||||
private animationControlService: AnimationControlService,
|
||||
) {}
|
||||
private logService: LogService,
|
||||
private sdkService: SdkService,
|
||||
) {
|
||||
if (flagEnabled("sdk")) {
|
||||
// Warn if the SDK for some reason can't be initialized
|
||||
this.sdkService.supported$
|
||||
.pipe(
|
||||
takeUntilDestroyed(),
|
||||
catchError(() => {
|
||||
return of(false);
|
||||
}),
|
||||
)
|
||||
.subscribe((supported) => {
|
||||
if (!supported) {
|
||||
this.logService.debug("SDK is not supported");
|
||||
this.sdkService.failedToInitialize().catch(this.logService.error);
|
||||
} else {
|
||||
this.logService.debug("SDK is supported");
|
||||
}
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
async ngOnInit() {
|
||||
initPopupClosedListener();
|
||||
|
@ -72,6 +72,7 @@ import {
|
||||
PlatformUtilsService,
|
||||
PlatformUtilsService as PlatformUtilsServiceAbstraction,
|
||||
} from "@bitwarden/common/platform/abstractions/platform-utils.service";
|
||||
import { SdkClientFactory } from "@bitwarden/common/platform/abstractions/sdk/sdk-client-factory";
|
||||
import { StateService } from "@bitwarden/common/platform/abstractions/state.service";
|
||||
import {
|
||||
AbstractStorageService,
|
||||
@ -80,9 +81,11 @@ import {
|
||||
import { Message, MessageListener, MessageSender } from "@bitwarden/common/platform/messaging";
|
||||
// eslint-disable-next-line no-restricted-imports -- Used for dependency injection
|
||||
import { SubjectMessageSender } from "@bitwarden/common/platform/messaging/internal";
|
||||
import { flagEnabled } from "@bitwarden/common/platform/misc/flags";
|
||||
import { TaskSchedulerService } from "@bitwarden/common/platform/scheduling";
|
||||
import { ConsoleLogService } from "@bitwarden/common/platform/services/console-log.service";
|
||||
import { ContainerService } from "@bitwarden/common/platform/services/container.service";
|
||||
import { NoopSdkClientFactory } from "@bitwarden/common/platform/services/sdk/noop-sdk-client-factory";
|
||||
import { StorageServiceProvider } from "@bitwarden/common/platform/services/storage-service.provider";
|
||||
import { WebCryptoFunctionService } from "@bitwarden/common/platform/services/web-crypto-function.service";
|
||||
import {
|
||||
@ -130,6 +133,7 @@ import BrowserLocalStorageService from "../../platform/services/browser-local-st
|
||||
import { BrowserScriptInjectorService } from "../../platform/services/browser-script-injector.service";
|
||||
import I18nService from "../../platform/services/i18n.service";
|
||||
import { ForegroundPlatformUtilsService } from "../../platform/services/platform-utils/foreground-platform-utils.service";
|
||||
import { BrowserSdkClientFactory } from "../../platform/services/sdk/browser-sdk-client-factory";
|
||||
import { ForegroundTaskSchedulerService } from "../../platform/services/task-scheduler/foreground-task-scheduler.service";
|
||||
import { BrowserStorageServiceProvider } from "../../platform/storage/browser-storage-service.provider";
|
||||
import { ForegroundMemoryStorageService } from "../../platform/storage/foreground-memory-storage.service";
|
||||
@ -604,6 +608,11 @@ const safeProviders: SafeProvider[] = [
|
||||
useClass: LoginEmailService,
|
||||
deps: [AccountService, AuthService, StateProvider],
|
||||
}),
|
||||
safeProvider({
|
||||
provide: SdkClientFactory,
|
||||
useClass: flagEnabled("sdk") ? BrowserSdkClientFactory : NoopSdkClientFactory,
|
||||
deps: [],
|
||||
}),
|
||||
];
|
||||
|
||||
@NgModule({
|
||||
|
@ -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 */,
|
||||
|
@ -122,7 +122,7 @@ const moduleRules = [
|
||||
loader: "@ngtools/webpack",
|
||||
},
|
||||
{
|
||||
test: /\.wasm$/,
|
||||
test: /argon2(-simd)?\.wasm$/,
|
||||
loader: "base64-loader",
|
||||
type: "javascript/auto",
|
||||
},
|
||||
@ -316,13 +316,18 @@ const mainConfig = {
|
||||
},
|
||||
output: {
|
||||
filename: "[name].js",
|
||||
chunkFilename: "assets/[name].js",
|
||||
webassemblyModuleFilename: "assets/[modulehash].wasm",
|
||||
path: path.resolve(__dirname, "build"),
|
||||
clean: true,
|
||||
},
|
||||
module: {
|
||||
noParse: /\.wasm$/,
|
||||
noParse: /argon2(-simd)?\.wasm$/,
|
||||
rules: moduleRules,
|
||||
},
|
||||
experiments: {
|
||||
asyncWebAssembly: true,
|
||||
},
|
||||
plugins: plugins,
|
||||
};
|
||||
|
||||
@ -395,12 +400,15 @@ if (manifestVersion == 2) {
|
||||
loader: "ts-loader",
|
||||
},
|
||||
{
|
||||
test: /\.wasm$/,
|
||||
test: /argon2(-simd)?\.wasm$/,
|
||||
loader: "base64-loader",
|
||||
type: "javascript/auto",
|
||||
},
|
||||
],
|
||||
noParse: /\.wasm$/,
|
||||
noParse: /argon2(-simd)?\.wasm$/,
|
||||
},
|
||||
experiments: {
|
||||
asyncWebAssembly: true,
|
||||
},
|
||||
resolve: {
|
||||
extensions: [".ts", ".js"],
|
||||
|
5
apps/cli/config/base.json
Normal file
5
apps/cli/config/base.json
Normal file
@ -0,0 +1,5 @@
|
||||
{
|
||||
"flags": {
|
||||
"sdk": true
|
||||
}
|
||||
}
|
@ -1,7 +1,27 @@
|
||||
function load(envName) {
|
||||
const base = require("./base.json");
|
||||
const env = loadConfig(envName);
|
||||
const local = loadConfig("local");
|
||||
|
||||
return {
|
||||
...loadConfig(envName),
|
||||
...loadConfig("local"),
|
||||
...base,
|
||||
...env,
|
||||
...local,
|
||||
dev: {
|
||||
...base.dev,
|
||||
...env.dev,
|
||||
...local.dev,
|
||||
},
|
||||
flags: {
|
||||
...base.flags,
|
||||
...env.flags,
|
||||
...local.flags,
|
||||
},
|
||||
devFlags: {
|
||||
...base.devFlags,
|
||||
...env.devFlags,
|
||||
...local.devFlags,
|
||||
},
|
||||
};
|
||||
}
|
||||
|
||||
|
@ -10,7 +10,11 @@ module.exports = {
|
||||
preset: "ts-jest",
|
||||
testEnvironment: "node",
|
||||
setupFilesAfterEnv: ["<rootDir>/test.setup.ts"],
|
||||
moduleNameMapper: pathsToModuleNameMapper(compilerOptions?.paths || {}, {
|
||||
prefix: "<rootDir>/",
|
||||
}),
|
||||
moduleNameMapper: {
|
||||
"@bitwarden/common/platform/services/sdk/default-sdk-client-factory":
|
||||
"<rootDir>/../../libs/common/spec/jest-sdk-client-factory",
|
||||
...pathsToModuleNameMapper(compilerOptions?.paths || {}, {
|
||||
prefix: "<rootDir>/",
|
||||
}),
|
||||
},
|
||||
};
|
||||
|
@ -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",
|
||||
|
@ -64,6 +64,7 @@ import {
|
||||
RegionConfig,
|
||||
} from "@bitwarden/common/platform/abstractions/environment.service";
|
||||
import { KeyGenerationService as KeyGenerationServiceAbstraction } from "@bitwarden/common/platform/abstractions/key-generation.service";
|
||||
import { SdkService } from "@bitwarden/common/platform/abstractions/sdk/sdk.service";
|
||||
import { KeySuffixOptions, LogLevelType } from "@bitwarden/common/platform/enums";
|
||||
import { StateFactory } from "@bitwarden/common/platform/factories/state-factory";
|
||||
import { MessageSender } from "@bitwarden/common/platform/messaging";
|
||||
@ -86,6 +87,9 @@ import { KeyGenerationService } from "@bitwarden/common/platform/services/key-ge
|
||||
import { MemoryStorageService } from "@bitwarden/common/platform/services/memory-storage.service";
|
||||
import { MigrationBuilderService } from "@bitwarden/common/platform/services/migration-builder.service";
|
||||
import { MigrationRunner } from "@bitwarden/common/platform/services/migration-runner";
|
||||
import { DefaultSdkClientFactory } from "@bitwarden/common/platform/services/sdk/default-sdk-client-factory";
|
||||
import { DefaultSdkService } from "@bitwarden/common/platform/services/sdk/default-sdk.service";
|
||||
import { NoopSdkClientFactory } from "@bitwarden/common/platform/services/sdk/noop-sdk-client-factory";
|
||||
import { StateService } from "@bitwarden/common/platform/services/state.service";
|
||||
import { StorageServiceProvider } from "@bitwarden/common/platform/services/storage-service.provider";
|
||||
import { UserAutoUnlockKeyService } from "@bitwarden/common/platform/services/user-auto-unlock-key.service";
|
||||
@ -151,6 +155,7 @@ import {
|
||||
VaultExportServiceAbstraction,
|
||||
} from "@bitwarden/vault-export-core";
|
||||
|
||||
import { flagEnabled } from "../platform/flags";
|
||||
import { CliPlatformUtilsService } from "../platform/services/cli-platform-utils.service";
|
||||
import { ConsoleLogService } from "../platform/services/console-log.service";
|
||||
import { I18nService } from "../platform/services/i18n.service";
|
||||
@ -249,6 +254,7 @@ export class ServiceContainer {
|
||||
userAutoUnlockKeyService: UserAutoUnlockKeyService;
|
||||
kdfConfigService: KdfConfigServiceAbstraction;
|
||||
taskSchedulerService: TaskSchedulerService;
|
||||
sdkService: SdkService;
|
||||
|
||||
constructor() {
|
||||
let p = null;
|
||||
@ -522,6 +528,17 @@ export class ServiceContainer {
|
||||
this.globalStateProvider,
|
||||
);
|
||||
|
||||
const sdkClientFactory = flagEnabled("sdk")
|
||||
? new DefaultSdkClientFactory()
|
||||
: new NoopSdkClientFactory();
|
||||
this.sdkService = new DefaultSdkService(
|
||||
sdkClientFactory,
|
||||
this.environmentService,
|
||||
this.platformUtilsService,
|
||||
this.apiService,
|
||||
customUserAgent,
|
||||
);
|
||||
|
||||
this.passwordStrengthService = new PasswordStrengthService();
|
||||
|
||||
this.passwordGenerationService = legacyPasswordGenerationServiceFactory(
|
||||
@ -830,5 +847,19 @@ export class ServiceContainer {
|
||||
}
|
||||
|
||||
this.inited = true;
|
||||
|
||||
if (flagEnabled("sdk")) {
|
||||
// Warn if the SDK for some reason can't be initialized
|
||||
let supported = false;
|
||||
try {
|
||||
supported = await firstValueFrom(this.sdkService.supported$);
|
||||
} catch (e) {
|
||||
// Do nothing.
|
||||
}
|
||||
|
||||
if (!supported) {
|
||||
this.sdkService.failedToInitialize().catch(this.logService.error);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -3,7 +3,7 @@
|
||||
"pretty": true,
|
||||
"moduleResolution": "node",
|
||||
"target": "ES2016",
|
||||
"module": "es6",
|
||||
"module": "ES2020",
|
||||
"noImplicitAny": true,
|
||||
"allowSyntheticDefaultImports": true,
|
||||
"emitDecoratorMetadata": true,
|
||||
|
@ -37,8 +37,10 @@ const plugins = [
|
||||
contextRegExp: /node-fetch/,
|
||||
}),
|
||||
new webpack.EnvironmentPlugin({
|
||||
ENV: ENV,
|
||||
BWCLI_ENV: ENV,
|
||||
FLAGS: envConfig.flags,
|
||||
DEV_FLAGS: envConfig.devFlags,
|
||||
}),
|
||||
new webpack.IgnorePlugin({
|
||||
resourceRegExp: /canvas/,
|
||||
@ -79,6 +81,9 @@ const webpackConfig = {
|
||||
allowlist: [/@bitwarden/],
|
||||
}),
|
||||
],
|
||||
experiments: {
|
||||
asyncWebAssembly: true,
|
||||
},
|
||||
};
|
||||
|
||||
module.exports = webpackConfig;
|
||||
|
@ -1,4 +1,6 @@
|
||||
{
|
||||
"devFlags": {},
|
||||
"flags": {}
|
||||
"flags": {
|
||||
"sdk": true
|
||||
},
|
||||
"devFlags": {}
|
||||
}
|
||||
|
@ -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",
|
||||
|
@ -8,8 +8,9 @@ import {
|
||||
ViewChild,
|
||||
ViewContainerRef,
|
||||
} from "@angular/core";
|
||||
import { takeUntilDestroyed } from "@angular/core/rxjs-interop";
|
||||
import { Router } from "@angular/router";
|
||||
import { filter, firstValueFrom, map, Subject, takeUntil, timeout } from "rxjs";
|
||||
import { catchError, filter, firstValueFrom, map, of, Subject, takeUntil, timeout } from "rxjs";
|
||||
|
||||
import { ModalRef } from "@bitwarden/angular/components/modal/modal.ref";
|
||||
import { ModalService } from "@bitwarden/angular/services/modal.service";
|
||||
@ -21,7 +22,6 @@ import { SearchService } from "@bitwarden/common/abstractions/search.service";
|
||||
import { VaultTimeoutSettingsService } from "@bitwarden/common/abstractions/vault-timeout/vault-timeout-settings.service";
|
||||
import { VaultTimeoutService } from "@bitwarden/common/abstractions/vault-timeout/vault-timeout.service";
|
||||
import { InternalPolicyService } from "@bitwarden/common/admin-console/abstractions/policy/policy.service.abstraction";
|
||||
import { ProviderService } from "@bitwarden/common/admin-console/abstractions/provider.service";
|
||||
import { AccountService } from "@bitwarden/common/auth/abstractions/account.service";
|
||||
import { AuthService } from "@bitwarden/common/auth/abstractions/auth.service";
|
||||
import { KeyConnectorService } from "@bitwarden/common/auth/abstractions/key-connector.service";
|
||||
@ -38,6 +38,7 @@ import { I18nService } from "@bitwarden/common/platform/abstractions/i18n.servic
|
||||
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 { SdkService } from "@bitwarden/common/platform/abstractions/sdk/sdk.service";
|
||||
import { StateService } from "@bitwarden/common/platform/abstractions/state.service";
|
||||
import { SystemService } from "@bitwarden/common/platform/abstractions/system.service";
|
||||
import { clearCaches } from "@bitwarden/common/platform/misc/sequentialize";
|
||||
@ -56,6 +57,7 @@ import { BiometricStateService } from "@bitwarden/key-management";
|
||||
import { DeleteAccountComponent } from "../auth/delete-account.component";
|
||||
import { LoginApprovalComponent } from "../auth/login/login-approval.component";
|
||||
import { MenuAccount, MenuUpdateRequest } from "../main/menu/menu.updater";
|
||||
import { flagEnabled } from "../platform/flags";
|
||||
import { PremiumComponent } from "../vault/app/accounts/premium.component";
|
||||
import { FolderAddEditComponent } from "../vault/app/vault/folder-add-edit.component";
|
||||
|
||||
@ -150,9 +152,28 @@ export class AppComponent implements OnInit, OnDestroy {
|
||||
private dialogService: DialogService,
|
||||
private biometricStateService: BiometricStateService,
|
||||
private stateEventRunnerService: StateEventRunnerService,
|
||||
private providerService: ProviderService,
|
||||
private accountService: AccountService,
|
||||
) {}
|
||||
private sdkService: SdkService,
|
||||
) {
|
||||
if (flagEnabled("sdk")) {
|
||||
// Warn if the SDK for some reason can't be initialized
|
||||
this.sdkService.supported$
|
||||
.pipe(
|
||||
takeUntilDestroyed(),
|
||||
catchError(() => {
|
||||
return of(false);
|
||||
}),
|
||||
)
|
||||
.subscribe((supported) => {
|
||||
if (!supported) {
|
||||
this.logService.debug("SDK is not supported");
|
||||
this.sdkService.failedToInitialize().catch(this.logService.error);
|
||||
} else {
|
||||
this.logService.debug("SDK is supported");
|
||||
}
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
ngOnInit() {
|
||||
this.accountService.activeAccount$.pipe(takeUntil(this.destroy$)).subscribe((account) => {
|
||||
|
@ -65,6 +65,7 @@ import {
|
||||
} from "@bitwarden/common/platform/abstractions/log.service";
|
||||
import { MessagingService as MessagingServiceAbstraction } from "@bitwarden/common/platform/abstractions/messaging.service";
|
||||
import { PlatformUtilsService as PlatformUtilsServiceAbstraction } from "@bitwarden/common/platform/abstractions/platform-utils.service";
|
||||
import { SdkClientFactory } from "@bitwarden/common/platform/abstractions/sdk/sdk-client-factory";
|
||||
import { StateService as StateServiceAbstraction } from "@bitwarden/common/platform/abstractions/state.service";
|
||||
import { AbstractStorageService } from "@bitwarden/common/platform/abstractions/storage.service";
|
||||
import { SystemService as SystemServiceAbstraction } from "@bitwarden/common/platform/abstractions/system.service";
|
||||
@ -73,6 +74,8 @@ import { Message, MessageListener, MessageSender } from "@bitwarden/common/platf
|
||||
import { SubjectMessageSender } from "@bitwarden/common/platform/messaging/internal";
|
||||
import { TaskSchedulerService } from "@bitwarden/common/platform/scheduling";
|
||||
import { MemoryStorageService } from "@bitwarden/common/platform/services/memory-storage.service";
|
||||
import { DefaultSdkClientFactory } from "@bitwarden/common/platform/services/sdk/default-sdk-client-factory";
|
||||
import { NoopSdkClientFactory } from "@bitwarden/common/platform/services/sdk/noop-sdk-client-factory";
|
||||
import { SystemService } from "@bitwarden/common/platform/services/system.service";
|
||||
import { GlobalStateProvider, StateProvider } from "@bitwarden/common/platform/state";
|
||||
// eslint-disable-next-line import/no-restricted-paths -- Implementation for memory storage
|
||||
@ -87,6 +90,7 @@ import { BiometricStateService, BiometricsService } from "@bitwarden/key-managem
|
||||
import { DesktopLoginComponentService } from "../../auth/login/desktop-login-component.service";
|
||||
import { DesktopAutofillSettingsService } from "../../autofill/services/desktop-autofill-settings.service";
|
||||
import { ElectronBiometricsService } from "../../key-management/biometrics/electron-biometrics.service";
|
||||
import { flagEnabled } from "../../platform/flags";
|
||||
import { DesktopSettingsService } from "../../platform/services/desktop-settings.service";
|
||||
import { ElectronCryptoService } from "../../platform/services/electron-crypto.service";
|
||||
import { ElectronLogRendererService } from "../../platform/services/electron-log.renderer.service";
|
||||
@ -332,6 +336,11 @@ const safeProviders: SafeProvider[] = [
|
||||
useClass: LoginEmailService,
|
||||
deps: [AccountService, AuthService, StateProvider],
|
||||
}),
|
||||
safeProvider({
|
||||
provide: SdkClientFactory,
|
||||
useClass: flagEnabled("sdk") ? DefaultSdkClientFactory : NoopSdkClientFactory,
|
||||
deps: [],
|
||||
}),
|
||||
];
|
||||
|
||||
@NgModule({
|
||||
|
@ -4,7 +4,7 @@
|
||||
<meta charset="UTF-8" />
|
||||
<meta
|
||||
http-equiv="Content-Security-Policy"
|
||||
content="default-src 'self'; style-src 'self' 'unsafe-inline';
|
||||
content="default-src 'self'; script-src 'self' 'wasm-unsafe-eval'; style-src 'self' 'unsafe-inline';
|
||||
img-src 'self' data: *; child-src *; frame-src *; connect-src *;"
|
||||
/>
|
||||
<meta name="viewport" content="width=device-width, initial-scale=1" />
|
||||
|
@ -331,7 +331,7 @@ export class NativeMessagingMain {
|
||||
const ext = process.platform === "win32" ? ".exe" : "";
|
||||
|
||||
if (isDev()) {
|
||||
return path.join(
|
||||
const devPath = path.join(
|
||||
this.appPath,
|
||||
"..",
|
||||
"desktop_native",
|
||||
@ -339,6 +339,12 @@ export class NativeMessagingMain {
|
||||
"debug",
|
||||
`desktop_proxy${ext}`,
|
||||
);
|
||||
|
||||
// isDev() returns true when using a production build with ELECTRON_IS_DEV=1,
|
||||
// so we need to fall back to the prod binary if the dev binary doesn't exist.
|
||||
if (existsSync(devPath)) {
|
||||
return devPath;
|
||||
}
|
||||
}
|
||||
|
||||
return path.join(path.dirname(this.exePath), `desktop_proxy${ext}`);
|
||||
|
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",
|
||||
|
@ -42,7 +42,7 @@ const common = {
|
||||
type: "asset/resource",
|
||||
},
|
||||
{
|
||||
test: /\.wasm$/,
|
||||
test: /argon2(-simd)?\.wasm$/,
|
||||
loader: "base64-loader",
|
||||
type: "javascript/auto",
|
||||
},
|
||||
@ -143,11 +143,15 @@ const renderer = {
|
||||
parser: { system: true },
|
||||
},
|
||||
{
|
||||
test: /\.wasm$/,
|
||||
test: /argon2(-simd)?\.wasm$/,
|
||||
loader: "base64-loader",
|
||||
type: "javascript/auto",
|
||||
},
|
||||
],
|
||||
noParse: /argon2(-simd)?\.wasm$/,
|
||||
},
|
||||
experiments: {
|
||||
asyncWebAssembly: true,
|
||||
},
|
||||
plugins: [
|
||||
new AngularWebpackPlugin({
|
||||
|
@ -11,6 +11,8 @@
|
||||
"allowedHosts": "auto"
|
||||
},
|
||||
"flags": {
|
||||
"showPasswordless": false
|
||||
}
|
||||
"showPasswordless": false,
|
||||
"sdk": true
|
||||
},
|
||||
"devFlags": {}
|
||||
}
|
||||
|
@ -9,11 +9,19 @@ module.exports = {
|
||||
...sharedConfig,
|
||||
preset: "jest-preset-angular",
|
||||
setupFilesAfterEnv: ["<rootDir>/test.setup.ts"],
|
||||
moduleNameMapper: pathsToModuleNameMapper(
|
||||
// lets us use @bitwarden/common/spec in web tests
|
||||
{ "@bitwarden/common/spec": ["../../libs/common/spec"], ...(compilerOptions?.paths ?? {}) },
|
||||
{
|
||||
prefix: "<rootDir>/",
|
||||
},
|
||||
),
|
||||
moduleNameMapper: {
|
||||
// Replace ESM SDK with Node compatible SDK
|
||||
"@bitwarden/common/platform/services/sdk/default-sdk-client-factory":
|
||||
"<rootDir>/../../libs/common/spec/jest-sdk-client-factory",
|
||||
...pathsToModuleNameMapper(
|
||||
{
|
||||
// lets us use @bitwarden/common/spec in web tests
|
||||
"@bitwarden/common/spec": ["../../libs/common/spec"],
|
||||
...(compilerOptions?.paths ?? {}),
|
||||
},
|
||||
{
|
||||
prefix: "<rootDir>/",
|
||||
},
|
||||
),
|
||||
},
|
||||
};
|
||||
|
@ -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",
|
||||
|
@ -1,8 +1,9 @@
|
||||
import { DOCUMENT } from "@angular/common";
|
||||
import { Component, Inject, NgZone, OnDestroy, OnInit } from "@angular/core";
|
||||
import { takeUntilDestroyed } from "@angular/core/rxjs-interop";
|
||||
import { NavigationEnd, Router } from "@angular/router";
|
||||
import * as jq from "jquery";
|
||||
import { Subject, filter, firstValueFrom, map, takeUntil, timeout } from "rxjs";
|
||||
import { Subject, filter, firstValueFrom, map, takeUntil, timeout, catchError, of } from "rxjs";
|
||||
|
||||
import { LogoutReason } from "@bitwarden/auth/common";
|
||||
import { EventUploadService } from "@bitwarden/common/abstractions/event/event-upload.service";
|
||||
@ -19,7 +20,9 @@ import { BroadcasterService } from "@bitwarden/common/platform/abstractions/broa
|
||||
import { ConfigService } from "@bitwarden/common/platform/abstractions/config/config.service";
|
||||
import { CryptoService } from "@bitwarden/common/platform/abstractions/crypto.service";
|
||||
import { I18nService } from "@bitwarden/common/platform/abstractions/i18n.service";
|
||||
import { LogService } from "@bitwarden/common/platform/abstractions/log.service";
|
||||
import { PlatformUtilsService } from "@bitwarden/common/platform/abstractions/platform-utils.service";
|
||||
import { SdkService } from "@bitwarden/common/platform/abstractions/sdk/sdk.service";
|
||||
import { StateService } from "@bitwarden/common/platform/abstractions/state.service";
|
||||
import { StateEventRunnerService } from "@bitwarden/common/platform/state";
|
||||
import { SyncService } from "@bitwarden/common/platform/sync";
|
||||
@ -30,6 +33,8 @@ import { DialogService, ToastOptions, ToastService } from "@bitwarden/components
|
||||
import { PasswordGenerationServiceAbstraction } from "@bitwarden/generator-legacy";
|
||||
import { BiometricStateService } from "@bitwarden/key-management";
|
||||
|
||||
import { flagEnabled } from "../utils/flags";
|
||||
|
||||
import { PolicyListService } from "./admin-console/core/policy-list.service";
|
||||
import {
|
||||
DisableSendPolicy,
|
||||
@ -85,7 +90,28 @@ export class AppComponent implements OnDestroy, OnInit {
|
||||
private stateEventRunnerService: StateEventRunnerService,
|
||||
private organizationService: InternalOrganizationServiceAbstraction,
|
||||
private accountService: AccountService,
|
||||
) {}
|
||||
private logService: LogService,
|
||||
private sdkService: SdkService,
|
||||
) {
|
||||
if (flagEnabled("sdk")) {
|
||||
// Warn if the SDK for some reason can't be initialized
|
||||
this.sdkService.supported$
|
||||
.pipe(
|
||||
takeUntilDestroyed(),
|
||||
catchError(() => {
|
||||
return of(false);
|
||||
}),
|
||||
)
|
||||
.subscribe((supported) => {
|
||||
if (!supported) {
|
||||
this.logService.debug("SDK is not supported");
|
||||
this.sdkService.failedToInitialize().catch(this.logService.error);
|
||||
} else {
|
||||
this.logService.debug("SDK is supported");
|
||||
}
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
ngOnInit() {
|
||||
this.i18nService.locale$.pipe(takeUntil(this.destroy$)).subscribe((locale) => {
|
||||
|
@ -58,6 +58,7 @@ import { FileDownloadService } from "@bitwarden/common/platform/abstractions/fil
|
||||
import { I18nService as I18nServiceAbstraction } from "@bitwarden/common/platform/abstractions/i18n.service";
|
||||
import { LogService } from "@bitwarden/common/platform/abstractions/log.service";
|
||||
import { PlatformUtilsService as PlatformUtilsServiceAbstraction } from "@bitwarden/common/platform/abstractions/platform-utils.service";
|
||||
import { SdkClientFactory } from "@bitwarden/common/platform/abstractions/sdk/sdk-client-factory";
|
||||
import { AbstractStorageService } from "@bitwarden/common/platform/abstractions/storage.service";
|
||||
import { ThemeType } from "@bitwarden/common/platform/enums";
|
||||
import { AppIdService as DefaultAppIdService } from "@bitwarden/common/platform/services/app-id.service";
|
||||
@ -65,6 +66,7 @@ import { MemoryStorageService } from "@bitwarden/common/platform/services/memory
|
||||
// eslint-disable-next-line import/no-restricted-paths -- Implementation for memory storage
|
||||
import { MigrationBuilderService } from "@bitwarden/common/platform/services/migration-builder.service";
|
||||
import { MigrationRunner } from "@bitwarden/common/platform/services/migration-runner";
|
||||
import { NoopSdkClientFactory } from "@bitwarden/common/platform/services/sdk/noop-sdk-client-factory";
|
||||
import { StorageServiceProvider } from "@bitwarden/common/platform/services/storage-service.provider";
|
||||
/* eslint-disable import/no-restricted-paths -- Implementation for memory storage */
|
||||
import { GlobalStateProvider, StateProvider } from "@bitwarden/common/platform/state";
|
||||
@ -80,6 +82,7 @@ import { CollectionService } from "@bitwarden/common/vault/abstractions/collecti
|
||||
import { PasswordGenerationServiceAbstraction } from "@bitwarden/generator-legacy";
|
||||
import { BiometricsService } from "@bitwarden/key-management";
|
||||
|
||||
import { flagEnabled } from "../../utils/flags";
|
||||
import { PolicyListService } from "../admin-console/core/policy-list.service";
|
||||
import {
|
||||
WebSetPasswordJitService,
|
||||
@ -93,6 +96,7 @@ import { I18nService } from "../core/i18n.service";
|
||||
import { WebBiometricsService } from "../key-management/web-biometric.service";
|
||||
import { WebEnvironmentService } from "../platform/web-environment.service";
|
||||
import { WebMigrationRunner } from "../platform/web-migration-runner";
|
||||
import { WebSdkClientFactory } from "../platform/web-sdk-client-factory";
|
||||
import { WebStorageServiceProvider } from "../platform/web-storage-service.provider";
|
||||
|
||||
import { EventService } from "./event.service";
|
||||
@ -270,6 +274,11 @@ const safeProviders: SafeProvider[] = [
|
||||
useClass: DefaultCollectionAdminService,
|
||||
deps: [ApiService, CryptoServiceAbstraction, EncryptService, CollectionService],
|
||||
}),
|
||||
safeProvider({
|
||||
provide: SdkClientFactory,
|
||||
useClass: flagEnabled("sdk") ? WebSdkClientFactory : NoopSdkClientFactory,
|
||||
deps: [],
|
||||
}),
|
||||
];
|
||||
|
||||
@NgModule({
|
||||
|
42
apps/web/src/app/platform/web-sdk-client-factory.ts
Normal file
42
apps/web/src/app/platform/web-sdk-client-factory.ts
Normal file
@ -0,0 +1,42 @@
|
||||
import { SdkClientFactory } from "@bitwarden/common/platform/abstractions/sdk/sdk-client-factory";
|
||||
import * as sdk from "@bitwarden/sdk-internal";
|
||||
|
||||
/**
|
||||
* SDK client factory with a js fallback for when WASM is not supported.
|
||||
*/
|
||||
export class WebSdkClientFactory implements SdkClientFactory {
|
||||
async createSdkClient(
|
||||
...args: ConstructorParameters<typeof sdk.BitwardenClient>
|
||||
): Promise<sdk.BitwardenClient> {
|
||||
const module = await load();
|
||||
|
||||
(sdk as any).init(module);
|
||||
|
||||
return Promise.resolve(new sdk.BitwardenClient(...args));
|
||||
}
|
||||
}
|
||||
|
||||
// https://stackoverflow.com/a/47880734
|
||||
const supported = (() => {
|
||||
try {
|
||||
if (typeof WebAssembly === "object" && typeof WebAssembly.instantiate === "function") {
|
||||
const module = new WebAssembly.Module(
|
||||
Uint8Array.of(0x0, 0x61, 0x73, 0x6d, 0x01, 0x00, 0x00, 0x00),
|
||||
);
|
||||
if (module instanceof WebAssembly.Module) {
|
||||
return new WebAssembly.Instance(module) instanceof WebAssembly.Instance;
|
||||
}
|
||||
}
|
||||
} catch (e) {
|
||||
// ignore
|
||||
}
|
||||
return false;
|
||||
})();
|
||||
|
||||
async function load() {
|
||||
if (supported) {
|
||||
return await import("@bitwarden/sdk-internal/bitwarden_wasm_internal_bg.wasm");
|
||||
} else {
|
||||
return await import("@bitwarden/sdk-internal/bitwarden_wasm_internal_bg.wasm.js");
|
||||
}
|
||||
}
|
@ -65,7 +65,7 @@
|
||||
>
|
||||
{{ "cancel" | i18n }}
|
||||
</button>
|
||||
<div class="tw-ml-auto">
|
||||
<div class="tw-ml-auto" *ngIf="showDelete">
|
||||
<button
|
||||
bitIconButton="bwi-trash"
|
||||
type="button"
|
||||
@ -73,6 +73,7 @@
|
||||
[appA11yTitle]="'delete' | i18n"
|
||||
[bitAction]="delete"
|
||||
[disabled]="!canDelete"
|
||||
data-testid="delete-cipher-btn"
|
||||
></button>
|
||||
</div>
|
||||
</ng-container>
|
||||
|
@ -179,6 +179,15 @@ export class VaultItemDialogComponent implements OnInit, OnDestroy {
|
||||
return this.cipher?.edit ?? false;
|
||||
}
|
||||
|
||||
protected get showDelete() {
|
||||
// Don't show the delete button when cloning a cipher
|
||||
if (this.params.mode == "form" && this.formConfig.mode === "clone") {
|
||||
return false;
|
||||
}
|
||||
// Never show the delete button for new ciphers
|
||||
return this.cipher != null;
|
||||
}
|
||||
|
||||
protected get showCipherView() {
|
||||
return this.cipher != undefined && (this.params.mode === "view" || this.loadingForm);
|
||||
}
|
||||
@ -332,8 +341,8 @@ export class VaultItemDialogComponent implements OnInit, OnDestroy {
|
||||
};
|
||||
|
||||
cancel = async () => {
|
||||
// We're in View mode, or we don't have a cipher, close the dialog.
|
||||
if (this.params.mode === "view" || this.cipher == null) {
|
||||
// We're in View mode, we don't have a cipher, or we were cloning, close the dialog.
|
||||
if (this.params.mode === "view" || this.cipher == null || this.formConfig.mode === "clone") {
|
||||
this.dialogRef.close(this._cipherModified ? VaultItemDialogResult.Saved : undefined);
|
||||
return;
|
||||
}
|
||||
|
@ -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;
|
||||
|
@ -78,7 +78,7 @@ const moduleRules = [
|
||||
loader: "@ngtools/webpack",
|
||||
},
|
||||
{
|
||||
test: /\.wasm$/,
|
||||
test: /argon2(-simd)?\.wasm$/,
|
||||
loader: "base64-loader",
|
||||
type: "javascript/auto",
|
||||
},
|
||||
@ -324,6 +324,7 @@ const webpackConfig = {
|
||||
mode: NODE_ENV,
|
||||
devtool: "source-map",
|
||||
devServer: devServer,
|
||||
target: "web",
|
||||
entry: {
|
||||
"app/polyfills": "./src/polyfills.ts",
|
||||
"app/main": "./src/main.ts",
|
||||
@ -383,9 +384,12 @@ const webpackConfig = {
|
||||
clean: true,
|
||||
},
|
||||
module: {
|
||||
noParse: /\.wasm$/,
|
||||
noParse: /argon2(-simd)?\.wasm$/,
|
||||
rules: moduleRules,
|
||||
},
|
||||
experiments: {
|
||||
asyncWebAssembly: true,
|
||||
},
|
||||
plugins: plugins,
|
||||
};
|
||||
|
||||
|
@ -10,7 +10,11 @@ module.exports = {
|
||||
preset: "ts-jest",
|
||||
testEnvironment: "node",
|
||||
setupFilesAfterEnv: ["<rootDir>/../../apps/cli/test.setup.ts"],
|
||||
moduleNameMapper: pathsToModuleNameMapper(compilerOptions?.paths || {}, {
|
||||
prefix: "<rootDir>/",
|
||||
}),
|
||||
moduleNameMapper: {
|
||||
"@bitwarden/common/platform/services/sdk/default-sdk-client-factory":
|
||||
"<rootDir>/../../libs/common/spec/jest-sdk-client-factory",
|
||||
...pathsToModuleNameMapper(compilerOptions?.paths || {}, {
|
||||
prefix: "<rootDir>/",
|
||||
}),
|
||||
},
|
||||
};
|
||||
|
@ -3,7 +3,7 @@
|
||||
"pretty": true,
|
||||
"moduleResolution": "node",
|
||||
"target": "ES2016",
|
||||
"module": "es6",
|
||||
"module": "ES2020",
|
||||
"noImplicitAny": true,
|
||||
"allowSyntheticDefaultImports": true,
|
||||
"emitDecoratorMetadata": true,
|
||||
|
@ -153,6 +153,8 @@ import { KeyGenerationService as KeyGenerationServiceAbstraction } from "@bitwar
|
||||
import { LogService } from "@bitwarden/common/platform/abstractions/log.service";
|
||||
import { MessagingService as MessagingServiceAbstraction } from "@bitwarden/common/platform/abstractions/messaging.service";
|
||||
import { PlatformUtilsService as PlatformUtilsServiceAbstraction } from "@bitwarden/common/platform/abstractions/platform-utils.service";
|
||||
import { SdkClientFactory } from "@bitwarden/common/platform/abstractions/sdk/sdk-client-factory";
|
||||
import { SdkService } from "@bitwarden/common/platform/abstractions/sdk/sdk.service";
|
||||
import { StateService as StateServiceAbstraction } from "@bitwarden/common/platform/abstractions/state.service";
|
||||
import { AbstractStorageService } from "@bitwarden/common/platform/abstractions/storage.service";
|
||||
import { ValidationService as ValidationServiceAbstraction } from "@bitwarden/common/platform/abstractions/validation.service";
|
||||
@ -181,6 +183,7 @@ import { KeyGenerationService } from "@bitwarden/common/platform/services/key-ge
|
||||
import { MigrationBuilderService } from "@bitwarden/common/platform/services/migration-builder.service";
|
||||
import { MigrationRunner } from "@bitwarden/common/platform/services/migration-runner";
|
||||
import { NoopNotificationsService } from "@bitwarden/common/platform/services/noop-notifications.service";
|
||||
import { DefaultSdkService } from "@bitwarden/common/platform/services/sdk/default-sdk.service";
|
||||
import { StateService } from "@bitwarden/common/platform/services/state.service";
|
||||
import { StorageServiceProvider } from "@bitwarden/common/platform/services/storage-service.provider";
|
||||
import { UserAutoUnlockKeyService } from "@bitwarden/common/platform/services/user-auto-unlock-key.service";
|
||||
@ -1337,6 +1340,16 @@ const safeProviders: SafeProvider[] = [
|
||||
SsoLoginServiceAbstraction,
|
||||
],
|
||||
}),
|
||||
safeProvider({
|
||||
provide: SdkService,
|
||||
useClass: DefaultSdkService,
|
||||
deps: [
|
||||
SdkClientFactory,
|
||||
EnvironmentService,
|
||||
PlatformUtilsServiceAbstraction,
|
||||
ApiServiceAbstraction,
|
||||
],
|
||||
}),
|
||||
];
|
||||
|
||||
@NgModule({
|
||||
|
@ -605,6 +605,10 @@ export class AddEditComponent implements OnInit, OnDestroy {
|
||||
this.collections = this.writeableCollections?.filter(
|
||||
(c) => c.organizationId === this.cipher.organizationId,
|
||||
);
|
||||
// If there's only one collection, check it by default
|
||||
if (this.collections.length === 1) {
|
||||
(this.collections[0] as any).checked = true;
|
||||
}
|
||||
const org = await this.organizationService.get(this.cipher.organizationId);
|
||||
if (org != null) {
|
||||
this.cipher.organizationUseTotp = org.useTotp;
|
||||
|
9
libs/common/spec/jest-sdk-client-factory.ts
Normal file
9
libs/common/spec/jest-sdk-client-factory.ts
Normal file
@ -0,0 +1,9 @@
|
||||
import { ClientSettings, LogLevel, BitwardenClient } from "@bitwarden/sdk-internal";
|
||||
|
||||
import { SdkClientFactory } from "../src/platform/abstractions/sdk/sdk-client-factory";
|
||||
|
||||
export class DefaultSdkClientFactory implements SdkClientFactory {
|
||||
createSdkClient(settings?: ClientSettings, log_level?: LogLevel): Promise<BitwardenClient> {
|
||||
throw new Error("Method not implemented.");
|
||||
}
|
||||
}
|
@ -0,0 +1,10 @@
|
||||
import type { BitwardenClient } from "@bitwarden/sdk-internal";
|
||||
|
||||
/**
|
||||
* Factory for creating SDK clients.
|
||||
*/
|
||||
export abstract class SdkClientFactory {
|
||||
abstract createSdkClient(
|
||||
...args: ConstructorParameters<typeof BitwardenClient>
|
||||
): Promise<BitwardenClient>;
|
||||
}
|
10
libs/common/src/platform/abstractions/sdk/sdk.service.ts
Normal file
10
libs/common/src/platform/abstractions/sdk/sdk.service.ts
Normal file
@ -0,0 +1,10 @@
|
||||
import { Observable } from "rxjs";
|
||||
|
||||
import { BitwardenClient } from "@bitwarden/sdk-internal";
|
||||
|
||||
export abstract class SdkService {
|
||||
client$: Observable<BitwardenClient>;
|
||||
supported$: Observable<boolean>;
|
||||
|
||||
abstract failedToInitialize(): Promise<void>;
|
||||
}
|
@ -2,6 +2,7 @@
|
||||
// eslint-disable-next-line @typescript-eslint/ban-types
|
||||
export type SharedFlags = {
|
||||
showPasswordless?: boolean;
|
||||
sdk?: boolean;
|
||||
};
|
||||
|
||||
// required to avoid linting errors when there are no flags
|
||||
@ -28,7 +29,7 @@ function getFlags<T>(envFlags: string | T): T {
|
||||
* @returns The value of the flag
|
||||
*/
|
||||
export function flagEnabled<Flags extends SharedFlags>(flag: keyof Flags): boolean {
|
||||
const flags = getFlags<Flags>(process.env.FLAGS);
|
||||
const flags = getFlags<Flags>(process.env.FLAGS) ?? ({} as Flags);
|
||||
return flags[flag] == null || !!flags[flag];
|
||||
}
|
||||
|
||||
|
@ -0,0 +1,19 @@
|
||||
import * as sdk from "@bitwarden/sdk-internal";
|
||||
import * as module from "@bitwarden/sdk-internal/bitwarden_wasm_internal_bg.wasm";
|
||||
|
||||
import { SdkClientFactory } from "../../abstractions/sdk/sdk-client-factory";
|
||||
|
||||
/**
|
||||
* Directly imports the Bitwarden SDK and initializes it.
|
||||
*
|
||||
* **Warning**: This requires WASM support and will fail if the environment does not support it.
|
||||
*/
|
||||
export class DefaultSdkClientFactory implements SdkClientFactory {
|
||||
async createSdkClient(
|
||||
...args: ConstructorParameters<typeof sdk.BitwardenClient>
|
||||
): Promise<sdk.BitwardenClient> {
|
||||
(sdk as any).init(module);
|
||||
|
||||
return Promise.resolve(new sdk.BitwardenClient(...args));
|
||||
}
|
||||
}
|
111
libs/common/src/platform/services/sdk/default-sdk.service.ts
Normal file
111
libs/common/src/platform/services/sdk/default-sdk.service.ts
Normal file
@ -0,0 +1,111 @@
|
||||
import { concatMap, firstValueFrom, shareReplay } from "rxjs";
|
||||
|
||||
import { LogLevel, DeviceType as SdkDeviceType } from "@bitwarden/sdk-internal";
|
||||
|
||||
import { ApiService } from "../../../abstractions/api.service";
|
||||
import { DeviceType } from "../../../enums/device-type.enum";
|
||||
import { EnvironmentService } from "../../abstractions/environment.service";
|
||||
import { PlatformUtilsService } from "../../abstractions/platform-utils.service";
|
||||
import { SdkClientFactory } from "../../abstractions/sdk/sdk-client-factory";
|
||||
import { SdkService } from "../../abstractions/sdk/sdk.service";
|
||||
|
||||
export class DefaultSdkService implements SdkService {
|
||||
client$ = this.environmentService.environment$.pipe(
|
||||
concatMap(async (env) => {
|
||||
const settings = {
|
||||
apiUrl: env.getApiUrl(),
|
||||
identityUrl: env.getIdentityUrl(),
|
||||
deviceType: this.toDevice(this.platformUtilsService.getDevice()),
|
||||
userAgent: this.userAgent ?? navigator.userAgent,
|
||||
};
|
||||
|
||||
return await this.sdkClientFactory.createSdkClient(settings, LogLevel.Info);
|
||||
}),
|
||||
shareReplay({ refCount: true, bufferSize: 1 }),
|
||||
);
|
||||
|
||||
supported$ = this.client$.pipe(
|
||||
concatMap(async (client) => {
|
||||
return client.echo("bitwarden wasm!") === "bitwarden wasm!";
|
||||
}),
|
||||
);
|
||||
|
||||
constructor(
|
||||
private sdkClientFactory: SdkClientFactory,
|
||||
private environmentService: EnvironmentService,
|
||||
private platformUtilsService: PlatformUtilsService,
|
||||
private apiService: ApiService, // Yes we shouldn't import ApiService, but it's temporary
|
||||
private userAgent: string = null,
|
||||
) {}
|
||||
|
||||
async failedToInitialize(): Promise<void> {
|
||||
// Only log on cloud instances
|
||||
if (
|
||||
this.platformUtilsService.isDev() ||
|
||||
!(await firstValueFrom(this.environmentService.environment$)).isCloud
|
||||
) {
|
||||
return;
|
||||
}
|
||||
|
||||
return this.apiService.send("POST", "/wasm-debug", null, false, false, null, (headers) => {
|
||||
headers.append("SDK-Version", "1.0.0");
|
||||
});
|
||||
}
|
||||
|
||||
private toDevice(device: DeviceType): SdkDeviceType {
|
||||
switch (device) {
|
||||
case DeviceType.Android:
|
||||
return "Android";
|
||||
case DeviceType.iOS:
|
||||
return "iOS";
|
||||
case DeviceType.ChromeExtension:
|
||||
return "ChromeExtension";
|
||||
case DeviceType.FirefoxExtension:
|
||||
return "FirefoxExtension";
|
||||
case DeviceType.OperaExtension:
|
||||
return "OperaExtension";
|
||||
case DeviceType.EdgeExtension:
|
||||
return "EdgeExtension";
|
||||
case DeviceType.WindowsDesktop:
|
||||
return "WindowsDesktop";
|
||||
case DeviceType.MacOsDesktop:
|
||||
return "MacOsDesktop";
|
||||
case DeviceType.LinuxDesktop:
|
||||
return "LinuxDesktop";
|
||||
case DeviceType.ChromeBrowser:
|
||||
return "ChromeBrowser";
|
||||
case DeviceType.FirefoxBrowser:
|
||||
return "FirefoxBrowser";
|
||||
case DeviceType.OperaBrowser:
|
||||
return "OperaBrowser";
|
||||
case DeviceType.EdgeBrowser:
|
||||
return "EdgeBrowser";
|
||||
case DeviceType.IEBrowser:
|
||||
return "IEBrowser";
|
||||
case DeviceType.UnknownBrowser:
|
||||
return "UnknownBrowser";
|
||||
case DeviceType.AndroidAmazon:
|
||||
return "AndroidAmazon";
|
||||
case DeviceType.UWP:
|
||||
return "UWP";
|
||||
case DeviceType.SafariBrowser:
|
||||
return "SafariBrowser";
|
||||
case DeviceType.VivaldiBrowser:
|
||||
return "VivaldiBrowser";
|
||||
case DeviceType.VivaldiExtension:
|
||||
return "VivaldiExtension";
|
||||
case DeviceType.SafariExtension:
|
||||
return "SafariExtension";
|
||||
case DeviceType.Server:
|
||||
return "Server";
|
||||
case DeviceType.WindowsCLI:
|
||||
return "WindowsCLI";
|
||||
case DeviceType.MacOsCLI:
|
||||
return "MacOsCLI";
|
||||
case DeviceType.LinuxCLI:
|
||||
return "LinuxCLI";
|
||||
default:
|
||||
return "SDK";
|
||||
}
|
||||
}
|
||||
}
|
@ -0,0 +1,16 @@
|
||||
import type { BitwardenClient } from "@bitwarden/sdk-internal";
|
||||
|
||||
import { SdkClientFactory } from "../../abstractions/sdk/sdk-client-factory";
|
||||
|
||||
/**
|
||||
* Noop SDK client factory.
|
||||
*
|
||||
* Used during SDK rollout to prevent bundling the SDK with some applications.
|
||||
*/
|
||||
export class NoopSdkClientFactory implements SdkClientFactory {
|
||||
createSdkClient(
|
||||
...args: ConstructorParameters<typeof BitwardenClient>
|
||||
): Promise<BitwardenClient> {
|
||||
return Promise.reject(new Error("SDK not available"));
|
||||
}
|
||||
}
|
@ -8,6 +8,7 @@ import { TreeNode } from "../models/domain/tree-node";
|
||||
import { CollectionView } from "../models/view/collection.view";
|
||||
|
||||
export abstract class CollectionService {
|
||||
encryptedCollections$: Observable<Collection[]>;
|
||||
decryptedCollections$: Observable<CollectionView[]>;
|
||||
|
||||
clearActiveUserCache: () => Promise<void>;
|
||||
|
@ -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;
|
||||
|
@ -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">
|
||||
|
@ -1,5 +1,5 @@
|
||||
import { inject, Injectable } from "@angular/core";
|
||||
import { combineLatest, firstValueFrom, map } from "rxjs";
|
||||
import { combineLatest, filter, firstValueFrom, map, switchMap } from "rxjs";
|
||||
|
||||
import { OrganizationService } from "@bitwarden/common/admin-console/abstractions/organization/organization.service.abstraction";
|
||||
import { PolicyService } from "@bitwarden/common/admin-console/abstractions/policy/policy.service.abstraction";
|
||||
@ -39,9 +39,21 @@ export class DefaultCipherFormConfigService implements CipherFormConfigService {
|
||||
await firstValueFrom(
|
||||
combineLatest([
|
||||
this.organizations$,
|
||||
this.collectionService.decryptedCollections$,
|
||||
this.collectionService.encryptedCollections$.pipe(
|
||||
switchMap((c) =>
|
||||
this.collectionService.decryptedCollections$.pipe(
|
||||
filter((d) => d.length === c.length), // Ensure all collections have been decrypted
|
||||
),
|
||||
),
|
||||
),
|
||||
this.allowPersonalOwnership$,
|
||||
this.folderService.folderViews$,
|
||||
this.folderService.folders$.pipe(
|
||||
switchMap((f) =>
|
||||
this.folderService.folderViews$.pipe(
|
||||
filter((d) => d.length - 1 === f.length), // -1 for "No Folder" in folderViews$
|
||||
),
|
||||
),
|
||||
),
|
||||
this.getCipher(cipherId),
|
||||
]),
|
||||
);
|
||||
|
14
package-lock.json
generated
14
package-lock.json
generated
@ -24,6 +24,7 @@
|
||||
"@angular/platform-browser": "16.2.12",
|
||||
"@angular/platform-browser-dynamic": "16.2.12",
|
||||
"@angular/router": "16.2.12",
|
||||
"@bitwarden/sdk-internal": "0.1.3",
|
||||
"@electron/fuses": "1.8.0",
|
||||
"@koa/multer": "3.0.2",
|
||||
"@koa/router": "12.0.1",
|
||||
@ -193,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",
|
||||
@ -233,7 +234,7 @@
|
||||
},
|
||||
"apps/desktop": {
|
||||
"name": "@bitwarden/desktop",
|
||||
"version": "2024.9.2",
|
||||
"version": "2024.10.0",
|
||||
"hasInstallScript": true,
|
||||
"license": "GPL-3.0"
|
||||
},
|
||||
@ -247,7 +248,7 @@
|
||||
},
|
||||
"apps/web": {
|
||||
"name": "@bitwarden/web-vault",
|
||||
"version": "2024.10.0"
|
||||
"version": "2024.10.1"
|
||||
},
|
||||
"libs/admin-console": {
|
||||
"name": "@bitwarden/admin-console",
|
||||
@ -4625,6 +4626,11 @@
|
||||
"resolved": "libs/platform",
|
||||
"link": true
|
||||
},
|
||||
"node_modules/@bitwarden/sdk-internal": {
|
||||
"version": "0.1.3",
|
||||
"resolved": "https://registry.npmjs.org/@bitwarden/sdk-internal/-/sdk-internal-0.1.3.tgz",
|
||||
"integrity": "sha512-zk9DyYMjylVLdljeLn3OLBcD939Hg/qMNJ2FxbyjiSKtcOcgglXgYmbcS01NRFFfM9REbn+j+2fWbQo6N+8SHw=="
|
||||
},
|
||||
"node_modules/@bitwarden/vault": {
|
||||
"resolved": "libs/vault",
|
||||
"link": true
|
||||
|
@ -157,6 +157,7 @@
|
||||
"@angular/platform-browser": "16.2.12",
|
||||
"@angular/platform-browser-dynamic": "16.2.12",
|
||||
"@angular/router": "16.2.12",
|
||||
"@bitwarden/sdk-internal": "0.1.3",
|
||||
"@electron/fuses": "1.8.0",
|
||||
"@koa/multer": "3.0.2",
|
||||
"@koa/router": "12.0.1",
|
||||
|
Loading…
Reference in New Issue
Block a user