mirror of
https://github.com/bitwarden/browser
synced 2025-12-10 21:33:27 +00:00
[PM-23920] Admin Console - adopt strongly typed guids (#15814)
Update organization, collection and policy to use strongly typed IDs
This commit is contained in:
@@ -10,7 +10,7 @@ import { BillingAccountProfileStateService } from "@bitwarden/common/billing/abs
|
|||||||
import { ProductTierType } from "@bitwarden/common/billing/enums";
|
import { ProductTierType } from "@bitwarden/common/billing/enums";
|
||||||
import { I18nService } from "@bitwarden/common/platform/abstractions/i18n.service";
|
import { I18nService } from "@bitwarden/common/platform/abstractions/i18n.service";
|
||||||
import { Utils } from "@bitwarden/common/platform/misc/utils";
|
import { Utils } from "@bitwarden/common/platform/misc/utils";
|
||||||
import { CipherId, UserId } from "@bitwarden/common/types/guid";
|
import { CipherId, OrganizationId, UserId } from "@bitwarden/common/types/guid";
|
||||||
import { CipherService } from "@bitwarden/common/vault/abstractions/cipher.service";
|
import { CipherService } from "@bitwarden/common/vault/abstractions/cipher.service";
|
||||||
import { CipherType } from "@bitwarden/common/vault/enums";
|
import { CipherType } from "@bitwarden/common/vault/enums";
|
||||||
import { CipherView } from "@bitwarden/common/vault/models/view/cipher.view";
|
import { CipherView } from "@bitwarden/common/vault/models/view/cipher.view";
|
||||||
@@ -163,7 +163,7 @@ describe("OpenAttachmentsComponent", () => {
|
|||||||
it("sets `cipherIsAPartOfFreeOrg` to true when the cipher is a part of a free organization", async () => {
|
it("sets `cipherIsAPartOfFreeOrg` to true when the cipher is a part of a free organization", async () => {
|
||||||
cipherView.organizationId = "888-333-333";
|
cipherView.organizationId = "888-333-333";
|
||||||
org.productTierType = ProductTierType.Free;
|
org.productTierType = ProductTierType.Free;
|
||||||
org.id = cipherView.organizationId;
|
org.id = cipherView.organizationId as OrganizationId;
|
||||||
|
|
||||||
await component.ngOnInit();
|
await component.ngOnInit();
|
||||||
|
|
||||||
@@ -173,7 +173,7 @@ describe("OpenAttachmentsComponent", () => {
|
|||||||
it("sets `cipherIsAPartOfFreeOrg` to false when the organization is not free", async () => {
|
it("sets `cipherIsAPartOfFreeOrg` to false when the organization is not free", async () => {
|
||||||
cipherView.organizationId = "888-333-333";
|
cipherView.organizationId = "888-333-333";
|
||||||
org.productTierType = ProductTierType.Families;
|
org.productTierType = ProductTierType.Families;
|
||||||
org.id = cipherView.organizationId;
|
org.id = cipherView.organizationId as OrganizationId;
|
||||||
|
|
||||||
await component.ngOnInit();
|
await component.ngOnInit();
|
||||||
|
|
||||||
|
|||||||
@@ -1,13 +1,14 @@
|
|||||||
// FIXME: Update this file to be type safe and remove this and next line
|
// FIXME: Update this file to be type safe and remove this and next line
|
||||||
// @ts-strict-ignore
|
// @ts-strict-ignore
|
||||||
import { CollectionExport } from "@bitwarden/common/models/export/collection.export";
|
import { CollectionExport } from "@bitwarden/common/models/export/collection.export";
|
||||||
|
import { OrganizationId } from "@bitwarden/common/types/guid";
|
||||||
|
|
||||||
import { SelectionReadOnly } from "../selection-read-only";
|
import { SelectionReadOnly } from "../selection-read-only";
|
||||||
|
|
||||||
export class OrganizationCollectionRequest extends CollectionExport {
|
export class OrganizationCollectionRequest extends CollectionExport {
|
||||||
static template(): OrganizationCollectionRequest {
|
static template(): OrganizationCollectionRequest {
|
||||||
const req = new OrganizationCollectionRequest();
|
const req = new OrganizationCollectionRequest();
|
||||||
req.organizationId = "00000000-0000-0000-0000-000000000000";
|
req.organizationId = "00000000-0000-0000-0000-000000000000" as OrganizationId;
|
||||||
req.name = "Collection name";
|
req.name = "Collection name";
|
||||||
req.externalId = null;
|
req.externalId = null;
|
||||||
req.groups = [SelectionReadOnly.template(), SelectionReadOnly.template()];
|
req.groups = [SelectionReadOnly.template(), SelectionReadOnly.template()];
|
||||||
|
|||||||
@@ -278,9 +278,16 @@ export class VaultComponent implements OnInit, OnDestroy {
|
|||||||
);
|
);
|
||||||
|
|
||||||
const filter$ = this.routedVaultFilterService.filter$;
|
const filter$ = this.routedVaultFilterService.filter$;
|
||||||
|
|
||||||
|
// FIXME: The RoutedVaultFilterModel uses `organizationId: Unassigned` to represent the individual vault,
|
||||||
|
// but that is never used in Admin Console. This function narrows the type so it doesn't pollute our code here,
|
||||||
|
// but really we should change to using our own vault filter model that only represents valid states in AC.
|
||||||
|
const isOrganizationId = (value: OrganizationId | Unassigned): value is OrganizationId =>
|
||||||
|
value !== Unassigned;
|
||||||
const organizationId$ = filter$.pipe(
|
const organizationId$ = filter$.pipe(
|
||||||
map((filter) => filter.organizationId),
|
map((filter) => filter.organizationId),
|
||||||
filter((filter) => filter !== undefined),
|
filter((filter) => filter !== undefined),
|
||||||
|
filter(isOrganizationId),
|
||||||
distinctUntilChanged(),
|
distinctUntilChanged(),
|
||||||
);
|
);
|
||||||
|
|
||||||
@@ -373,9 +380,12 @@ export class VaultComponent implements OnInit, OnDestroy {
|
|||||||
this.allCollectionsWithoutUnassigned$,
|
this.allCollectionsWithoutUnassigned$,
|
||||||
]).pipe(
|
]).pipe(
|
||||||
map(([organizationId, allCollections]) => {
|
map(([organizationId, allCollections]) => {
|
||||||
|
// FIXME: We should not assert that the Unassigned type is a CollectionId.
|
||||||
|
// Instead we should consider representing the Unassigned collection as a different object, given that
|
||||||
|
// it is not actually a collection.
|
||||||
const noneCollection = new CollectionAdminView();
|
const noneCollection = new CollectionAdminView();
|
||||||
noneCollection.name = this.i18nService.t("unassigned");
|
noneCollection.name = this.i18nService.t("unassigned");
|
||||||
noneCollection.id = Unassigned;
|
noneCollection.id = Unassigned as CollectionId;
|
||||||
noneCollection.organizationId = organizationId;
|
noneCollection.organizationId = organizationId;
|
||||||
return allCollections.concat(noneCollection);
|
return allCollections.concat(noneCollection);
|
||||||
}),
|
}),
|
||||||
|
|||||||
@@ -39,6 +39,7 @@ import { ConfigService } from "@bitwarden/common/platform/abstractions/config/co
|
|||||||
import { I18nService } from "@bitwarden/common/platform/abstractions/i18n.service";
|
import { I18nService } from "@bitwarden/common/platform/abstractions/i18n.service";
|
||||||
import { getById } from "@bitwarden/common/platform/misc";
|
import { getById } from "@bitwarden/common/platform/misc";
|
||||||
import { Utils } from "@bitwarden/common/platform/misc/utils";
|
import { Utils } from "@bitwarden/common/platform/misc/utils";
|
||||||
|
import { CollectionId, OrganizationId } from "@bitwarden/common/types/guid";
|
||||||
import {
|
import {
|
||||||
DIALOG_DATA,
|
DIALOG_DATA,
|
||||||
DialogConfig,
|
DialogConfig,
|
||||||
@@ -87,8 +88,8 @@ enum ButtonType {
|
|||||||
}
|
}
|
||||||
|
|
||||||
export interface CollectionDialogParams {
|
export interface CollectionDialogParams {
|
||||||
collectionId?: string;
|
collectionId?: CollectionId;
|
||||||
organizationId: string;
|
organizationId: OrganizationId;
|
||||||
initialTab?: CollectionDialogTabType;
|
initialTab?: CollectionDialogTabType;
|
||||||
parentCollectionId?: string;
|
parentCollectionId?: string;
|
||||||
showOrgSelector?: boolean;
|
showOrgSelector?: boolean;
|
||||||
@@ -136,7 +137,7 @@ export class CollectionDialogComponent implements OnInit, OnDestroy {
|
|||||||
externalId: { value: "", disabled: true },
|
externalId: { value: "", disabled: true },
|
||||||
parent: undefined as string | undefined,
|
parent: undefined as string | undefined,
|
||||||
access: [[] as AccessItemValue[]],
|
access: [[] as AccessItemValue[]],
|
||||||
selectedOrg: "",
|
selectedOrg: "" as OrganizationId,
|
||||||
});
|
});
|
||||||
protected PermissionMode = PermissionMode;
|
protected PermissionMode = PermissionMode;
|
||||||
protected showDeleteButton = false;
|
protected showDeleteButton = false;
|
||||||
|
|||||||
@@ -1,8 +1,8 @@
|
|||||||
// FIXME: Update this file to be type safe and remove this and next line
|
// FIXME: Update this file to be type safe and remove this and next line
|
||||||
// @ts-strict-ignore
|
// @ts-strict-ignore
|
||||||
import { Guid } from "@bitwarden/common/types/guid";
|
import { OrganizationId } from "@bitwarden/common/types/guid";
|
||||||
|
|
||||||
export class RequestSMAccessRequest {
|
export class RequestSMAccessRequest {
|
||||||
OrganizationId: Guid;
|
OrganizationId: OrganizationId;
|
||||||
EmailContent: string;
|
EmailContent: string;
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -10,7 +10,6 @@ import { Organization } from "@bitwarden/common/admin-console/models/domain/orga
|
|||||||
import { AccountService } from "@bitwarden/common/auth/abstractions/account.service";
|
import { AccountService } from "@bitwarden/common/auth/abstractions/account.service";
|
||||||
import { getUserId } from "@bitwarden/common/auth/services/account.service";
|
import { getUserId } from "@bitwarden/common/auth/services/account.service";
|
||||||
import { I18nService } from "@bitwarden/common/platform/abstractions/i18n.service";
|
import { I18nService } from "@bitwarden/common/platform/abstractions/i18n.service";
|
||||||
import { Guid } from "@bitwarden/common/types/guid";
|
|
||||||
import { NoItemsModule, SearchModule, ToastService } from "@bitwarden/components";
|
import { NoItemsModule, SearchModule, ToastService } from "@bitwarden/components";
|
||||||
|
|
||||||
import { HeaderModule } from "../../layouts/header/header.module";
|
import { HeaderModule } from "../../layouts/header/header.module";
|
||||||
@@ -63,7 +62,7 @@ export class RequestSMAccessComponent implements OnInit {
|
|||||||
|
|
||||||
const formValue = this.requestAccessForm.value;
|
const formValue = this.requestAccessForm.value;
|
||||||
const request = new RequestSMAccessRequest();
|
const request = new RequestSMAccessRequest();
|
||||||
request.OrganizationId = formValue.selectedOrganization.id as Guid;
|
request.OrganizationId = formValue.selectedOrganization.id;
|
||||||
request.EmailContent = formValue.requestAccessEmailContents;
|
request.EmailContent = formValue.requestAccessEmailContents;
|
||||||
|
|
||||||
await this.smLandingApiService.requestSMAccessFromAdmins(request);
|
await this.smLandingApiService.requestSMAccessFromAdmins(request);
|
||||||
|
|||||||
@@ -29,6 +29,7 @@ import {
|
|||||||
} from "@bitwarden/common/platform/abstractions/environment.service";
|
} from "@bitwarden/common/platform/abstractions/environment.service";
|
||||||
import { StateService } from "@bitwarden/common/platform/abstractions/state.service";
|
import { StateService } from "@bitwarden/common/platform/abstractions/state.service";
|
||||||
import { SymmetricCryptoKey } from "@bitwarden/common/platform/models/domain/symmetric-crypto-key";
|
import { SymmetricCryptoKey } from "@bitwarden/common/platform/models/domain/symmetric-crypto-key";
|
||||||
|
import { CollectionId, OrganizationId } from "@bitwarden/common/types/guid";
|
||||||
import { CipherType } from "@bitwarden/common/vault/enums";
|
import { CipherType } from "@bitwarden/common/vault/enums";
|
||||||
import { AttachmentView } from "@bitwarden/common/vault/models/view/attachment.view";
|
import { AttachmentView } from "@bitwarden/common/vault/models/view/attachment.view";
|
||||||
import { CipherView } from "@bitwarden/common/vault/models/view/cipher.view";
|
import { CipherView } from "@bitwarden/common/vault/models/view/cipher.view";
|
||||||
@@ -262,7 +263,7 @@ export const OrganizationTrash: Story = {
|
|||||||
};
|
};
|
||||||
|
|
||||||
const unassignedCollection = new CollectionAdminView();
|
const unassignedCollection = new CollectionAdminView();
|
||||||
unassignedCollection.id = Unassigned;
|
unassignedCollection.id = Unassigned as CollectionId;
|
||||||
unassignedCollection.name = "Unassigned";
|
unassignedCollection.name = "Unassigned";
|
||||||
export const OrganizationTopLevelCollection: Story = {
|
export const OrganizationTopLevelCollection: Story = {
|
||||||
args: {
|
args: {
|
||||||
@@ -327,7 +328,7 @@ function createCollectionView(i: number): CollectionAdminView {
|
|||||||
const organization = organizations[i % (organizations.length + 1)];
|
const organization = organizations[i % (organizations.length + 1)];
|
||||||
const group = groups[i % (groups.length + 1)];
|
const group = groups[i % (groups.length + 1)];
|
||||||
const view = new CollectionAdminView();
|
const view = new CollectionAdminView();
|
||||||
view.id = `collection-${i}`;
|
view.id = `collection-${i}` as CollectionId;
|
||||||
view.name = `Collection ${i}`;
|
view.name = `Collection ${i}`;
|
||||||
view.organizationId = organization?.id;
|
view.organizationId = organization?.id;
|
||||||
view.manage = true;
|
view.manage = true;
|
||||||
@@ -357,7 +358,7 @@ function createGroupView(i: number): GroupView {
|
|||||||
|
|
||||||
function createOrganization(i: number): Organization {
|
function createOrganization(i: number): Organization {
|
||||||
const organization = new Organization();
|
const organization = new Organization();
|
||||||
organization.id = `organization-${i}`;
|
organization.id = `organization-${i}` as OrganizationId;
|
||||||
organization.name = `Organization ${i}`;
|
organization.name = `Organization ${i}`;
|
||||||
organization.type = OrganizationUserType.Owner;
|
organization.type = OrganizationUserType.Owner;
|
||||||
organization.permissions = new PermissionsApi();
|
organization.permissions = new PermissionsApi();
|
||||||
|
|||||||
@@ -2,6 +2,8 @@ import { Injectable, OnDestroy } from "@angular/core";
|
|||||||
import { ActivatedRoute, NavigationExtras } from "@angular/router";
|
import { ActivatedRoute, NavigationExtras } from "@angular/router";
|
||||||
import { combineLatest, map, Observable, Subject, takeUntil } from "rxjs";
|
import { combineLatest, map, Observable, Subject, takeUntil } from "rxjs";
|
||||||
|
|
||||||
|
import { CollectionId, OrganizationId } from "@bitwarden/common/types/guid";
|
||||||
|
|
||||||
import {
|
import {
|
||||||
isRoutedVaultFilterItemType,
|
isRoutedVaultFilterItemType,
|
||||||
RoutedVaultFilterModel,
|
RoutedVaultFilterModel,
|
||||||
@@ -31,10 +33,12 @@ export class RoutedVaultFilterService implements OnDestroy {
|
|||||||
const type = isRoutedVaultFilterItemType(unsafeType) ? unsafeType : undefined;
|
const type = isRoutedVaultFilterItemType(unsafeType) ? unsafeType : undefined;
|
||||||
|
|
||||||
return {
|
return {
|
||||||
collectionId: queryParams.get("collectionId") ?? undefined,
|
collectionId: (queryParams.get("collectionId") as CollectionId) ?? undefined,
|
||||||
folderId: queryParams.get("folderId") ?? undefined,
|
folderId: queryParams.get("folderId") ?? undefined,
|
||||||
organizationId:
|
organizationId:
|
||||||
params.get("organizationId") ?? queryParams.get("organizationId") ?? undefined,
|
(params.get("organizationId") as OrganizationId) ??
|
||||||
|
(queryParams.get("organizationId") as OrganizationId) ??
|
||||||
|
undefined,
|
||||||
organizationIdParamType:
|
organizationIdParamType:
|
||||||
params.get("organizationId") != undefined ? ("path" as const) : ("query" as const),
|
params.get("organizationId") != undefined ? ("path" as const) : ("query" as const),
|
||||||
type,
|
type,
|
||||||
|
|||||||
@@ -28,7 +28,7 @@ import { FeatureFlag } from "@bitwarden/common/enums/feature-flag.enum";
|
|||||||
import { ConfigService } from "@bitwarden/common/platform/abstractions/config/config.service";
|
import { ConfigService } from "@bitwarden/common/platform/abstractions/config/config.service";
|
||||||
import { I18nService } from "@bitwarden/common/platform/abstractions/i18n.service";
|
import { I18nService } from "@bitwarden/common/platform/abstractions/i18n.service";
|
||||||
import { SingleUserState, StateProvider } from "@bitwarden/common/platform/state";
|
import { SingleUserState, StateProvider } from "@bitwarden/common/platform/state";
|
||||||
import { UserId } from "@bitwarden/common/types/guid";
|
import { OrganizationId, UserId } from "@bitwarden/common/types/guid";
|
||||||
import { CipherService } from "@bitwarden/common/vault/abstractions/cipher.service";
|
import { CipherService } from "@bitwarden/common/vault/abstractions/cipher.service";
|
||||||
import { FolderService } from "@bitwarden/common/vault/abstractions/folder/folder.service.abstraction";
|
import { FolderService } from "@bitwarden/common/vault/abstractions/folder/folder.service.abstraction";
|
||||||
import { CipherType } from "@bitwarden/common/vault/enums";
|
import { CipherType } from "@bitwarden/common/vault/enums";
|
||||||
@@ -209,7 +209,7 @@ export class VaultFilterService implements VaultFilterServiceAbstraction {
|
|||||||
|
|
||||||
protected getOrganizationFilterMyVault(): TreeNode<OrganizationFilter> {
|
protected getOrganizationFilterMyVault(): TreeNode<OrganizationFilter> {
|
||||||
const myVault = new Organization() as OrganizationFilter;
|
const myVault = new Organization() as OrganizationFilter;
|
||||||
myVault.id = "MyVault";
|
myVault.id = "MyVault" as OrganizationId;
|
||||||
myVault.icon = "bwi-user";
|
myVault.icon = "bwi-user";
|
||||||
myVault.enabled = true;
|
myVault.enabled = true;
|
||||||
myVault.hideOptions = true;
|
myVault.hideOptions = true;
|
||||||
|
|||||||
@@ -1,4 +1,5 @@
|
|||||||
import { Unassigned } from "@bitwarden/admin-console/common";
|
import { Unassigned } from "@bitwarden/admin-console/common";
|
||||||
|
import { CollectionId } from "@bitwarden/common/types/guid";
|
||||||
import { CipherType } from "@bitwarden/common/vault/enums";
|
import { CipherType } from "@bitwarden/common/vault/enums";
|
||||||
import { TreeNode } from "@bitwarden/common/vault/models/domain/tree-node";
|
import { TreeNode } from "@bitwarden/common/vault/models/domain/tree-node";
|
||||||
|
|
||||||
@@ -65,7 +66,7 @@ export class RoutedVaultFilterBridge implements VaultFilter {
|
|||||||
let type: RoutedVaultFilterItemType | undefined;
|
let type: RoutedVaultFilterItemType | undefined;
|
||||||
|
|
||||||
if (value?.node.id === "AllItems" && this.routedFilter.organizationIdParamType === "path") {
|
if (value?.node.id === "AllItems" && this.routedFilter.organizationIdParamType === "path") {
|
||||||
type = "all";
|
type = All;
|
||||||
} else if (
|
} else if (
|
||||||
value?.node.id === "AllItems" &&
|
value?.node.id === "AllItems" &&
|
||||||
this.routedFilter.organizationIdParamType === "query"
|
this.routedFilter.organizationIdParamType === "query"
|
||||||
@@ -98,7 +99,7 @@ export class RoutedVaultFilterBridge implements VaultFilter {
|
|||||||
return this.legacyFilter.selectedCollectionNode;
|
return this.legacyFilter.selectedCollectionNode;
|
||||||
}
|
}
|
||||||
set selectedCollectionNode(value: TreeNode<CollectionFilter>) {
|
set selectedCollectionNode(value: TreeNode<CollectionFilter>) {
|
||||||
let collectionId: string | undefined;
|
let collectionId: CollectionId | All | Unassigned | undefined;
|
||||||
|
|
||||||
if (value != null && value.node.id === null) {
|
if (value != null && value.node.id === null) {
|
||||||
collectionId = Unassigned;
|
collectionId = Unassigned;
|
||||||
|
|||||||
@@ -1,4 +1,11 @@
|
|||||||
|
import { Unassigned } from "@bitwarden/admin-console/common";
|
||||||
|
import { CollectionId, OrganizationId } from "@bitwarden/common/types/guid";
|
||||||
|
|
||||||
|
/**
|
||||||
|
* A constant used to represent viewing "all" of a particular filter.
|
||||||
|
*/
|
||||||
export const All = "all";
|
export const All = "all";
|
||||||
|
export type All = typeof All;
|
||||||
|
|
||||||
// TODO: Remove `All` when moving to vertical navigation.
|
// TODO: Remove `All` when moving to vertical navigation.
|
||||||
const itemTypes = [
|
const itemTypes = [
|
||||||
@@ -19,9 +26,9 @@ export function isRoutedVaultFilterItemType(value: unknown): value is RoutedVaul
|
|||||||
}
|
}
|
||||||
|
|
||||||
export interface RoutedVaultFilterModel {
|
export interface RoutedVaultFilterModel {
|
||||||
collectionId?: string;
|
collectionId?: CollectionId | All | Unassigned;
|
||||||
folderId?: string;
|
folderId?: string;
|
||||||
organizationId?: string;
|
organizationId?: OrganizationId | Unassigned;
|
||||||
type?: RoutedVaultFilterItemType;
|
type?: RoutedVaultFilterItemType;
|
||||||
|
|
||||||
organizationIdParamType?: "path" | "query";
|
organizationIdParamType?: "path" | "query";
|
||||||
|
|||||||
@@ -4,7 +4,10 @@ import { CollectionAccessSelectionView } from "./collection-access-selection.vie
|
|||||||
import { CollectionAccessDetailsResponse } from "./collection.response";
|
import { CollectionAccessDetailsResponse } from "./collection.response";
|
||||||
import { CollectionView } from "./collection.view";
|
import { CollectionView } from "./collection.view";
|
||||||
|
|
||||||
|
// TODO: this is used to represent the pseudo "Unassigned" collection as well as
|
||||||
|
// the user's personal vault (as a pseudo organization). This should be separated out into different values.
|
||||||
export const Unassigned = "unassigned";
|
export const Unassigned = "unassigned";
|
||||||
|
export type Unassigned = typeof Unassigned;
|
||||||
|
|
||||||
export class CollectionAdminView extends CollectionView {
|
export class CollectionAdminView extends CollectionView {
|
||||||
groups: CollectionAccessSelectionView[] = [];
|
groups: CollectionAccessSelectionView[] = [];
|
||||||
|
|||||||
@@ -54,7 +54,7 @@ describe("Collection", () => {
|
|||||||
|
|
||||||
it("Decrypt", async () => {
|
it("Decrypt", async () => {
|
||||||
const collection = new Collection();
|
const collection = new Collection();
|
||||||
collection.id = "id";
|
collection.id = "id" as CollectionId;
|
||||||
collection.organizationId = "orgId" as OrganizationId;
|
collection.organizationId = "orgId" as OrganizationId;
|
||||||
collection.name = mockEnc("encName");
|
collection.name = mockEnc("encName");
|
||||||
collection.externalId = "extId";
|
collection.externalId = "extId";
|
||||||
|
|||||||
@@ -1,5 +1,6 @@
|
|||||||
import { EncString } from "@bitwarden/common/key-management/crypto/models/enc-string";
|
import { EncString } from "@bitwarden/common/key-management/crypto/models/enc-string";
|
||||||
import Domain, { EncryptableKeys } from "@bitwarden/common/platform/models/domain/domain-base";
|
import Domain, { EncryptableKeys } from "@bitwarden/common/platform/models/domain/domain-base";
|
||||||
|
import { CollectionId, OrganizationId } from "@bitwarden/common/types/guid";
|
||||||
import { OrgKey } from "@bitwarden/common/types/key";
|
import { OrgKey } from "@bitwarden/common/types/key";
|
||||||
|
|
||||||
import { CollectionData } from "./collection.data";
|
import { CollectionData } from "./collection.data";
|
||||||
@@ -13,8 +14,8 @@ export const CollectionTypes = {
|
|||||||
export type CollectionType = (typeof CollectionTypes)[keyof typeof CollectionTypes];
|
export type CollectionType = (typeof CollectionTypes)[keyof typeof CollectionTypes];
|
||||||
|
|
||||||
export class Collection extends Domain {
|
export class Collection extends Domain {
|
||||||
id: string | undefined;
|
id: CollectionId | undefined;
|
||||||
organizationId: string | undefined;
|
organizationId: OrganizationId | undefined;
|
||||||
name: EncString | undefined;
|
name: EncString | undefined;
|
||||||
externalId: string | undefined;
|
externalId: string | undefined;
|
||||||
readOnly: boolean = false;
|
readOnly: boolean = false;
|
||||||
|
|||||||
@@ -2,6 +2,7 @@ import { Jsonify } from "type-fest";
|
|||||||
|
|
||||||
import { Organization } from "@bitwarden/common/admin-console/models/domain/organization";
|
import { Organization } from "@bitwarden/common/admin-console/models/domain/organization";
|
||||||
import { View } from "@bitwarden/common/models/view/view";
|
import { View } from "@bitwarden/common/models/view/view";
|
||||||
|
import { CollectionId, OrganizationId } from "@bitwarden/common/types/guid";
|
||||||
import { ITreeNodeObject } from "@bitwarden/common/vault/models/domain/tree-node";
|
import { ITreeNodeObject } from "@bitwarden/common/vault/models/domain/tree-node";
|
||||||
|
|
||||||
import { Collection, CollectionType, CollectionTypes } from "./collection";
|
import { Collection, CollectionType, CollectionTypes } from "./collection";
|
||||||
@@ -10,8 +11,8 @@ import { CollectionAccessDetailsResponse } from "./collection.response";
|
|||||||
export const NestingDelimiter = "/";
|
export const NestingDelimiter = "/";
|
||||||
|
|
||||||
export class CollectionView implements View, ITreeNodeObject {
|
export class CollectionView implements View, ITreeNodeObject {
|
||||||
id: string | undefined;
|
id: CollectionId | undefined;
|
||||||
organizationId: string | undefined;
|
organizationId: OrganizationId | undefined;
|
||||||
name: string = "";
|
name: string = "";
|
||||||
externalId: string | undefined;
|
externalId: string | undefined;
|
||||||
// readOnly applies to the items within a collection
|
// readOnly applies to the items within a collection
|
||||||
|
|||||||
@@ -5,7 +5,7 @@ import { combineLatest, Observable, of, switchMap } from "rxjs";
|
|||||||
// eslint-disable-next-line no-restricted-imports
|
// eslint-disable-next-line no-restricted-imports
|
||||||
import { CollectionService } from "@bitwarden/admin-console/common";
|
import { CollectionService } from "@bitwarden/admin-console/common";
|
||||||
import { OrganizationService } from "@bitwarden/common/admin-console/abstractions/organization/organization.service.abstraction";
|
import { OrganizationService } from "@bitwarden/common/admin-console/abstractions/organization/organization.service.abstraction";
|
||||||
import { UserId } from "@bitwarden/common/types/guid";
|
import { OrganizationId, UserId } from "@bitwarden/common/types/guid";
|
||||||
import { CipherService } from "@bitwarden/common/vault/abstractions/cipher.service";
|
import { CipherService } from "@bitwarden/common/vault/abstractions/cipher.service";
|
||||||
|
|
||||||
import { DefaultSingleNudgeService } from "../default-single-nudge.service";
|
import { DefaultSingleNudgeService } from "../default-single-nudge.service";
|
||||||
@@ -42,7 +42,7 @@ export class EmptyVaultNudgeService extends DefaultSingleNudgeService {
|
|||||||
const orgIds = new Set(orgs.map((org) => org.id));
|
const orgIds = new Set(orgs.map((org) => org.id));
|
||||||
const canCreateCollections = orgs.some((org) => org.canCreateNewCollections);
|
const canCreateCollections = orgs.some((org) => org.canCreateNewCollections);
|
||||||
const hasManageCollections = collections.some(
|
const hasManageCollections = collections.some(
|
||||||
(c) => c.manage && orgIds.has(c.organizationId!),
|
(c) => c.manage && orgIds.has(c.organizationId! as OrganizationId),
|
||||||
);
|
);
|
||||||
|
|
||||||
// When the user has dismissed the nudge or spotlight, return the nudge status directly
|
// When the user has dismissed the nudge or spotlight, return the nudge status directly
|
||||||
|
|||||||
@@ -5,7 +5,7 @@ import { combineLatest, Observable, of, switchMap } from "rxjs";
|
|||||||
// eslint-disable-next-line no-restricted-imports
|
// eslint-disable-next-line no-restricted-imports
|
||||||
import { CollectionService } from "@bitwarden/admin-console/common";
|
import { CollectionService } from "@bitwarden/admin-console/common";
|
||||||
import { OrganizationService } from "@bitwarden/common/admin-console/abstractions/organization/organization.service.abstraction";
|
import { OrganizationService } from "@bitwarden/common/admin-console/abstractions/organization/organization.service.abstraction";
|
||||||
import { UserId } from "@bitwarden/common/types/guid";
|
import { OrganizationId, UserId } from "@bitwarden/common/types/guid";
|
||||||
import { CipherService } from "@bitwarden/common/vault/abstractions/cipher.service";
|
import { CipherService } from "@bitwarden/common/vault/abstractions/cipher.service";
|
||||||
|
|
||||||
import { DefaultSingleNudgeService } from "../default-single-nudge.service";
|
import { DefaultSingleNudgeService } from "../default-single-nudge.service";
|
||||||
@@ -46,7 +46,7 @@ export class VaultSettingsImportNudgeService extends DefaultSingleNudgeService {
|
|||||||
const orgIds = new Set(orgs.map((org) => org.id));
|
const orgIds = new Set(orgs.map((org) => org.id));
|
||||||
const canCreateCollections = orgs.some((org) => org.canCreateNewCollections);
|
const canCreateCollections = orgs.some((org) => org.canCreateNewCollections);
|
||||||
const hasManageCollections = collections.some(
|
const hasManageCollections = collections.some(
|
||||||
(c) => c.manage && orgIds.has(c.organizationId!),
|
(c) => c.manage && orgIds.has(c.organizationId! as OrganizationId),
|
||||||
);
|
);
|
||||||
|
|
||||||
// When the user has dismissed the nudge or spotlight, return the nudge status directly
|
// When the user has dismissed the nudge or spotlight, return the nudge status directly
|
||||||
|
|||||||
@@ -3,12 +3,13 @@
|
|||||||
import { Jsonify } from "type-fest";
|
import { Jsonify } from "type-fest";
|
||||||
|
|
||||||
import { ProductTierType } from "../../../billing/enums";
|
import { ProductTierType } from "../../../billing/enums";
|
||||||
|
import { OrganizationId } from "../../../types/guid";
|
||||||
import { OrganizationUserStatusType, OrganizationUserType, ProviderType } from "../../enums";
|
import { OrganizationUserStatusType, OrganizationUserType, ProviderType } from "../../enums";
|
||||||
import { PermissionsApi } from "../api/permissions.api";
|
import { PermissionsApi } from "../api/permissions.api";
|
||||||
import { OrganizationData } from "../data/organization.data";
|
import { OrganizationData } from "../data/organization.data";
|
||||||
|
|
||||||
export class Organization {
|
export class Organization {
|
||||||
id: string;
|
id: OrganizationId;
|
||||||
name: string;
|
name: string;
|
||||||
status: OrganizationUserStatusType;
|
status: OrganizationUserStatusType;
|
||||||
|
|
||||||
@@ -99,7 +100,7 @@ export class Organization {
|
|||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
this.id = obj.id;
|
this.id = obj.id as OrganizationId;
|
||||||
this.name = obj.name;
|
this.name = obj.name;
|
||||||
this.status = obj.status;
|
this.status = obj.status;
|
||||||
this.type = obj.type;
|
this.type = obj.type;
|
||||||
|
|||||||
@@ -2,14 +2,14 @@
|
|||||||
// @ts-strict-ignore
|
// @ts-strict-ignore
|
||||||
import { ListResponse } from "../../../models/response/list.response";
|
import { ListResponse } from "../../../models/response/list.response";
|
||||||
import Domain from "../../../platform/models/domain/domain-base";
|
import Domain from "../../../platform/models/domain/domain-base";
|
||||||
import { PolicyId } from "../../../types/guid";
|
import { OrganizationId, PolicyId } from "../../../types/guid";
|
||||||
import { PolicyType } from "../../enums";
|
import { PolicyType } from "../../enums";
|
||||||
import { PolicyData } from "../data/policy.data";
|
import { PolicyData } from "../data/policy.data";
|
||||||
import { PolicyResponse } from "../response/policy.response";
|
import { PolicyResponse } from "../response/policy.response";
|
||||||
|
|
||||||
export class Policy extends Domain {
|
export class Policy extends Domain {
|
||||||
id: PolicyId;
|
id: PolicyId;
|
||||||
organizationId: string;
|
organizationId: OrganizationId;
|
||||||
type: PolicyType;
|
type: PolicyType;
|
||||||
data: any;
|
data: any;
|
||||||
|
|
||||||
@@ -26,7 +26,7 @@ export class Policy extends Domain {
|
|||||||
}
|
}
|
||||||
|
|
||||||
this.id = obj.id;
|
this.id = obj.id;
|
||||||
this.organizationId = obj.organizationId;
|
this.organizationId = obj.organizationId as OrganizationId;
|
||||||
this.type = obj.type;
|
this.type = obj.type;
|
||||||
this.data = obj.data;
|
this.data = obj.data;
|
||||||
this.enabled = obj.enabled;
|
this.enabled = obj.enabled;
|
||||||
|
|||||||
@@ -4,10 +4,12 @@
|
|||||||
// eslint-disable-next-line no-restricted-imports
|
// eslint-disable-next-line no-restricted-imports
|
||||||
import { Collection as CollectionDomain, CollectionView } from "@bitwarden/admin-console/common";
|
import { Collection as CollectionDomain, CollectionView } from "@bitwarden/admin-console/common";
|
||||||
|
|
||||||
|
import { CollectionId } from "../../types/guid";
|
||||||
|
|
||||||
import { CollectionExport } from "./collection.export";
|
import { CollectionExport } from "./collection.export";
|
||||||
|
|
||||||
export class CollectionWithIdExport extends CollectionExport {
|
export class CollectionWithIdExport extends CollectionExport {
|
||||||
id: string;
|
id: CollectionId;
|
||||||
|
|
||||||
static toView(req: CollectionWithIdExport, view = new CollectionView()) {
|
static toView(req: CollectionWithIdExport, view = new CollectionView()) {
|
||||||
view.id = req.id;
|
view.id = req.id;
|
||||||
|
|||||||
@@ -5,13 +5,14 @@
|
|||||||
import { Collection as CollectionDomain, CollectionView } from "@bitwarden/admin-console/common";
|
import { Collection as CollectionDomain, CollectionView } from "@bitwarden/admin-console/common";
|
||||||
|
|
||||||
import { EncString } from "../../key-management/crypto/models/enc-string";
|
import { EncString } from "../../key-management/crypto/models/enc-string";
|
||||||
|
import { emptyGuid, OrganizationId } from "../../types/guid";
|
||||||
|
|
||||||
import { safeGetString } from "./utils";
|
import { safeGetString } from "./utils";
|
||||||
|
|
||||||
export class CollectionExport {
|
export class CollectionExport {
|
||||||
static template(): CollectionExport {
|
static template(): CollectionExport {
|
||||||
const req = new CollectionExport();
|
const req = new CollectionExport();
|
||||||
req.organizationId = "00000000-0000-0000-0000-000000000000";
|
req.organizationId = emptyGuid as OrganizationId;
|
||||||
req.name = "Collection name";
|
req.name = "Collection name";
|
||||||
req.externalId = null;
|
req.externalId = null;
|
||||||
return req;
|
return req;
|
||||||
@@ -35,7 +36,7 @@ export class CollectionExport {
|
|||||||
return domain;
|
return domain;
|
||||||
}
|
}
|
||||||
|
|
||||||
organizationId: string;
|
organizationId: OrganizationId;
|
||||||
name: string;
|
name: string;
|
||||||
externalId: string;
|
externalId: string;
|
||||||
|
|
||||||
|
|||||||
@@ -20,3 +20,8 @@ export type OrganizationIntegrationConfigurationId = Opaque<
|
|||||||
string,
|
string,
|
||||||
"OrganizationIntegrationConfigurationId"
|
"OrganizationIntegrationConfigurationId"
|
||||||
>;
|
>;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* A string representation of an empty guid.
|
||||||
|
*/
|
||||||
|
export const emptyGuid = "00000000-0000-0000-0000-000000000000";
|
||||||
|
|||||||
@@ -9,6 +9,7 @@ import { normalizeExpiryYearFormat } from "@bitwarden/common/autofill/utils";
|
|||||||
import { LogService } from "@bitwarden/common/platform/abstractions/log.service";
|
import { LogService } from "@bitwarden/common/platform/abstractions/log.service";
|
||||||
import { Utils } from "@bitwarden/common/platform/misc/utils";
|
import { Utils } from "@bitwarden/common/platform/misc/utils";
|
||||||
import { ConsoleLogService } from "@bitwarden/common/platform/services/console-log.service";
|
import { ConsoleLogService } from "@bitwarden/common/platform/services/console-log.service";
|
||||||
|
import { CollectionId, OrganizationId } from "@bitwarden/common/types/guid";
|
||||||
import { FieldType, SecureNoteType, CipherType } from "@bitwarden/common/vault/enums";
|
import { FieldType, SecureNoteType, CipherType } from "@bitwarden/common/vault/enums";
|
||||||
import { CipherView } from "@bitwarden/common/vault/models/view/cipher.view";
|
import { CipherView } from "@bitwarden/common/vault/models/view/cipher.view";
|
||||||
import { FieldView } from "@bitwarden/common/vault/models/view/field.view";
|
import { FieldView } from "@bitwarden/common/vault/models/view/field.view";
|
||||||
@@ -20,7 +21,7 @@ import { SecureNoteView } from "@bitwarden/common/vault/models/view/secure-note.
|
|||||||
import { ImportResult } from "../models/import-result";
|
import { ImportResult } from "../models/import-result";
|
||||||
|
|
||||||
export abstract class BaseImporter {
|
export abstract class BaseImporter {
|
||||||
organizationId: string = null;
|
organizationId: OrganizationId = null;
|
||||||
|
|
||||||
// FIXME: This should be replaced by injecting the log service.
|
// FIXME: This should be replaced by injecting the log service.
|
||||||
protected logService: LogService = new ConsoleLogService(false);
|
protected logService: LogService = new ConsoleLogService(false);
|
||||||
@@ -279,7 +280,7 @@ export abstract class BaseImporter {
|
|||||||
result.collections = result.folders.map((f) => {
|
result.collections = result.folders.map((f) => {
|
||||||
const collection = new CollectionView();
|
const collection = new CollectionView();
|
||||||
collection.name = f.name;
|
collection.name = f.name;
|
||||||
collection.id = f.id ?? undefined; // folder id may be null, which is not suitable for collections.
|
collection.id = (f.id as CollectionId) ?? undefined; // folder id may be null, which is not suitable for collections.
|
||||||
return collection;
|
return collection;
|
||||||
});
|
});
|
||||||
result.folderRelationships = [];
|
result.folderRelationships = [];
|
||||||
|
|||||||
@@ -1,4 +1,5 @@
|
|||||||
import { Utils } from "@bitwarden/common/platform/misc/utils";
|
import { Utils } from "@bitwarden/common/platform/misc/utils";
|
||||||
|
import { OrganizationId } from "@bitwarden/common/types/guid";
|
||||||
|
|
||||||
import {
|
import {
|
||||||
testData as TestData,
|
testData as TestData,
|
||||||
@@ -103,7 +104,7 @@ describe("Keeper CSV Importer", () => {
|
|||||||
});
|
});
|
||||||
|
|
||||||
it("should create collections, with subcollections and relationships", async () => {
|
it("should create collections, with subcollections and relationships", async () => {
|
||||||
importer.organizationId = Utils.newGuid();
|
importer.organizationId = Utils.newGuid() as OrganizationId;
|
||||||
const result = await importer.parse(TestData);
|
const result = await importer.parse(TestData);
|
||||||
expect(result != null).toBe(true);
|
expect(result != null).toBe(true);
|
||||||
|
|
||||||
@@ -126,7 +127,7 @@ describe("Keeper CSV Importer", () => {
|
|||||||
});
|
});
|
||||||
|
|
||||||
it("should create collections tree, with child collections and relationships", async () => {
|
it("should create collections tree, with child collections and relationships", async () => {
|
||||||
importer.organizationId = Utils.newGuid();
|
importer.organizationId = Utils.newGuid() as OrganizationId;
|
||||||
const result = await importer.parse(testDataMultiCollection);
|
const result = await importer.parse(testDataMultiCollection);
|
||||||
expect(result != null).toBe(true);
|
expect(result != null).toBe(true);
|
||||||
|
|
||||||
|
|||||||
@@ -1,4 +1,5 @@
|
|||||||
import { Utils } from "@bitwarden/common/platform/misc/utils";
|
import { Utils } from "@bitwarden/common/platform/misc/utils";
|
||||||
|
import { OrganizationId } from "@bitwarden/common/types/guid";
|
||||||
|
|
||||||
import { testData as TestData } from "../spec-data/keeper-json/testdata.json";
|
import { testData as TestData } from "../spec-data/keeper-json/testdata.json";
|
||||||
|
|
||||||
@@ -93,7 +94,7 @@ describe("Keeper Json Importer", () => {
|
|||||||
});
|
});
|
||||||
|
|
||||||
it("should create collections if part of an organization", async () => {
|
it("should create collections if part of an organization", async () => {
|
||||||
importer.organizationId = Utils.newGuid();
|
importer.organizationId = Utils.newGuid() as OrganizationId;
|
||||||
const result = await importer.parse(testDataJson);
|
const result = await importer.parse(testDataJson);
|
||||||
expect(result != null).toBe(true);
|
expect(result != null).toBe(true);
|
||||||
|
|
||||||
|
|||||||
@@ -1,4 +1,5 @@
|
|||||||
import { Utils } from "@bitwarden/common/platform/misc/utils";
|
import { Utils } from "@bitwarden/common/platform/misc/utils";
|
||||||
|
import { OrganizationId } from "@bitwarden/common/types/guid";
|
||||||
|
|
||||||
import {
|
import {
|
||||||
credentialsData,
|
credentialsData,
|
||||||
@@ -79,7 +80,7 @@ describe("Netwrix Password Secure CSV Importer", () => {
|
|||||||
});
|
});
|
||||||
|
|
||||||
it("should parse an item and create a collection when importing into an organization", async () => {
|
it("should parse an item and create a collection when importing into an organization", async () => {
|
||||||
importer.organizationId = Utils.newGuid();
|
importer.organizationId = Utils.newGuid() as OrganizationId;
|
||||||
const result = await importer.parse(credentialsData);
|
const result = await importer.parse(credentialsData);
|
||||||
|
|
||||||
expect(result).not.toBeNull();
|
expect(result).not.toBeNull();
|
||||||
@@ -93,7 +94,7 @@ describe("Netwrix Password Secure CSV Importer", () => {
|
|||||||
});
|
});
|
||||||
|
|
||||||
it("should parse multiple collections", async () => {
|
it("should parse multiple collections", async () => {
|
||||||
importer.organizationId = Utils.newGuid();
|
importer.organizationId = Utils.newGuid() as OrganizationId;
|
||||||
const result = await importer.parse(credentialsDataWithFolders);
|
const result = await importer.parse(credentialsDataWithFolders);
|
||||||
|
|
||||||
expect(result).not.toBeNull();
|
expect(result).not.toBeNull();
|
||||||
|
|||||||
@@ -1,4 +1,5 @@
|
|||||||
import { Utils } from "@bitwarden/common/platform/misc/utils";
|
import { Utils } from "@bitwarden/common/platform/misc/utils";
|
||||||
|
import { OrganizationId } from "@bitwarden/common/types/guid";
|
||||||
import { SecureNoteType, CipherType, FieldType } from "@bitwarden/common/vault/enums";
|
import { SecureNoteType, CipherType, FieldType } from "@bitwarden/common/vault/enums";
|
||||||
import { CipherView } from "@bitwarden/common/vault/models/view/cipher.view";
|
import { CipherView } from "@bitwarden/common/vault/models/view/cipher.view";
|
||||||
import { IdentityView } from "@bitwarden/common/vault/models/view/identity.view";
|
import { IdentityView } from "@bitwarden/common/vault/models/view/identity.view";
|
||||||
@@ -224,7 +225,7 @@ describe("NordPass CSV Importer", () => {
|
|||||||
});
|
});
|
||||||
|
|
||||||
it("should parse an item and create a collection if organizationId is set", async () => {
|
it("should parse an item and create a collection if organizationId is set", async () => {
|
||||||
importer.organizationId = Utils.newGuid();
|
importer.organizationId = Utils.newGuid() as OrganizationId;
|
||||||
const result = await importer.parse(secureNoteData);
|
const result = await importer.parse(secureNoteData);
|
||||||
|
|
||||||
expect(result).not.toBeNull();
|
expect(result).not.toBeNull();
|
||||||
|
|||||||
@@ -1,4 +1,5 @@
|
|||||||
import { Utils } from "@bitwarden/common/platform/misc/utils";
|
import { Utils } from "@bitwarden/common/platform/misc/utils";
|
||||||
|
import { OrganizationId } from "@bitwarden/common/types/guid";
|
||||||
import { FieldType, SecureNoteType, CipherType } from "@bitwarden/common/vault/enums";
|
import { FieldType, SecureNoteType, CipherType } from "@bitwarden/common/vault/enums";
|
||||||
import { FieldView } from "@bitwarden/common/vault/models/view/field.view";
|
import { FieldView } from "@bitwarden/common/vault/models/view/field.view";
|
||||||
|
|
||||||
@@ -691,7 +692,7 @@ describe("1Password 1Pux Importer", () => {
|
|||||||
|
|
||||||
it("should create collections if part of an organization", async () => {
|
it("should create collections if part of an organization", async () => {
|
||||||
const importer = new OnePassword1PuxImporter();
|
const importer = new OnePassword1PuxImporter();
|
||||||
importer.organizationId = Utils.newGuid();
|
importer.organizationId = Utils.newGuid() as OrganizationId;
|
||||||
const result = await importer.parse(SanitizedExportJson);
|
const result = await importer.parse(SanitizedExportJson);
|
||||||
expect(result != null).toBe(true);
|
expect(result != null).toBe(true);
|
||||||
|
|
||||||
|
|||||||
@@ -1,3 +1,4 @@
|
|||||||
|
import { OrganizationId } from "@bitwarden/common/types/guid";
|
||||||
import { CipherType } from "@bitwarden/common/vault/enums";
|
import { CipherType } from "@bitwarden/common/vault/enums";
|
||||||
|
|
||||||
import { ImportResult } from "../../models/import-result";
|
import { ImportResult } from "../../models/import-result";
|
||||||
@@ -146,7 +147,7 @@ describe("PasswordXPCsvImporter", () => {
|
|||||||
});
|
});
|
||||||
|
|
||||||
it("should convert folders to collections when importing into an organization", async () => {
|
it("should convert folders to collections when importing into an organization", async () => {
|
||||||
importer.organizationId = "someOrg";
|
importer.organizationId = "someOrg" as OrganizationId;
|
||||||
const result: ImportResult = await importer.parse(withFolders);
|
const result: ImportResult = await importer.parse(withFolders);
|
||||||
expect(result.success).toBe(true);
|
expect(result.success).toBe(true);
|
||||||
expect(result.ciphers.length).toBe(5);
|
expect(result.ciphers.length).toBe(5);
|
||||||
@@ -172,7 +173,7 @@ describe("PasswordXPCsvImporter", () => {
|
|||||||
});
|
});
|
||||||
|
|
||||||
it("should convert multi-level folders to collections when importing into an organization", async () => {
|
it("should convert multi-level folders to collections when importing into an organization", async () => {
|
||||||
importer.organizationId = "someOrg";
|
importer.organizationId = "someOrg" as OrganizationId;
|
||||||
const result: ImportResult = await importer.parse(withMultipleFolders);
|
const result: ImportResult = await importer.parse(withMultipleFolders);
|
||||||
expect(result.success).toBe(true);
|
expect(result.success).toBe(true);
|
||||||
expect(result.ciphers.length).toBe(5);
|
expect(result.ciphers.length).toBe(5);
|
||||||
|
|||||||
@@ -1,6 +1,7 @@
|
|||||||
// This import has been flagged as unallowed for this class. It may be involved in a circular dependency loop.
|
// This import has been flagged as unallowed for this class. It may be involved in a circular dependency loop.
|
||||||
// eslint-disable-next-line no-restricted-imports
|
// eslint-disable-next-line no-restricted-imports
|
||||||
import { CollectionView } from "@bitwarden/admin-console/common";
|
import { CollectionView } from "@bitwarden/admin-console/common";
|
||||||
|
import { OrganizationId } from "@bitwarden/common/types/guid";
|
||||||
import { FieldType, SecureNoteType } from "@bitwarden/common/vault/enums";
|
import { FieldType, SecureNoteType } from "@bitwarden/common/vault/enums";
|
||||||
import { FolderView } from "@bitwarden/common/vault/models/view/folder.view";
|
import { FolderView } from "@bitwarden/common/vault/models/view/folder.view";
|
||||||
import { CipherType } from "@bitwarden/sdk-internal";
|
import { CipherType } from "@bitwarden/sdk-internal";
|
||||||
@@ -485,7 +486,7 @@ describe("Password Depot 17 Xml Importer", () => {
|
|||||||
|
|
||||||
it("should parse groups nodes into collections when importing into an organization", async () => {
|
it("should parse groups nodes into collections when importing into an organization", async () => {
|
||||||
const importer = new PasswordDepot17XmlImporter();
|
const importer = new PasswordDepot17XmlImporter();
|
||||||
importer.organizationId = "someOrgId";
|
importer.organizationId = "someOrgId" as OrganizationId;
|
||||||
const collection = new CollectionView();
|
const collection = new CollectionView();
|
||||||
collection.name = "tempDB";
|
collection.name = "tempDB";
|
||||||
const actual = [collection];
|
const actual = [collection];
|
||||||
|
|||||||
@@ -2,6 +2,7 @@ import { MockProxy } from "jest-mock-extended";
|
|||||||
|
|
||||||
import { I18nService } from "@bitwarden/common/platform/abstractions/i18n.service";
|
import { I18nService } from "@bitwarden/common/platform/abstractions/i18n.service";
|
||||||
import { Utils } from "@bitwarden/common/platform/misc/utils";
|
import { Utils } from "@bitwarden/common/platform/misc/utils";
|
||||||
|
import { OrganizationId } from "@bitwarden/common/types/guid";
|
||||||
import { FieldType, CipherType } from "@bitwarden/common/vault/enums";
|
import { FieldType, CipherType } from "@bitwarden/common/vault/enums";
|
||||||
|
|
||||||
import { testData } from "../spec-data/protonpass-json/protonpass.json";
|
import { testData } from "../spec-data/protonpass-json/protonpass.json";
|
||||||
@@ -90,7 +91,7 @@ describe("Protonpass Json Importer", () => {
|
|||||||
|
|
||||||
it("should create collections if part of an organization", async () => {
|
it("should create collections if part of an organization", async () => {
|
||||||
const testDataJson = JSON.stringify(testData);
|
const testDataJson = JSON.stringify(testData);
|
||||||
importer.organizationId = Utils.newGuid();
|
importer.organizationId = Utils.newGuid() as OrganizationId;
|
||||||
const result = await importer.parse(testDataJson);
|
const result = await importer.parse(testDataJson);
|
||||||
expect(result != null).toBe(true);
|
expect(result != null).toBe(true);
|
||||||
|
|
||||||
|
|||||||
@@ -1,3 +1,4 @@
|
|||||||
|
import { OrganizationId } from "@bitwarden/common/types/guid";
|
||||||
import { FieldType, CipherType } from "@bitwarden/common/vault/enums";
|
import { FieldType, CipherType } from "@bitwarden/common/vault/enums";
|
||||||
import { FieldView } from "@bitwarden/common/vault/models/view/field.view";
|
import { FieldView } from "@bitwarden/common/vault/models/view/field.view";
|
||||||
|
|
||||||
@@ -236,7 +237,7 @@ describe("PSONO JSON Importer", () => {
|
|||||||
|
|
||||||
it("should create collections if part of an organization", async () => {
|
it("should create collections if part of an organization", async () => {
|
||||||
const importer = new PsonoJsonImporter();
|
const importer = new PsonoJsonImporter();
|
||||||
importer.organizationId = "someOrg";
|
importer.organizationId = "someOrg" as OrganizationId;
|
||||||
const result = await importer.parse(FoldersTestDataJson);
|
const result = await importer.parse(FoldersTestDataJson);
|
||||||
expect(result != null).toBe(true);
|
expect(result != null).toBe(true);
|
||||||
|
|
||||||
|
|||||||
@@ -1,3 +1,4 @@
|
|||||||
|
import { OrganizationId } from "@bitwarden/common/types/guid";
|
||||||
import { CipherView } from "@bitwarden/common/vault/models/view/cipher.view";
|
import { CipherView } from "@bitwarden/common/vault/models/view/cipher.view";
|
||||||
import { LoginUriView } from "@bitwarden/common/vault/models/view/login-uri.view";
|
import { LoginUriView } from "@bitwarden/common/vault/models/view/login-uri.view";
|
||||||
import { LoginView } from "@bitwarden/common/vault/models/view/login.view";
|
import { LoginView } from "@bitwarden/common/vault/models/view/login.view";
|
||||||
@@ -73,7 +74,7 @@ describe("Zoho Vault CSV Importer", () => {
|
|||||||
|
|
||||||
it("should create collection and assign ciphers when importing into an organization", async () => {
|
it("should create collection and assign ciphers when importing into an organization", async () => {
|
||||||
const importer = new ZohoVaultCsvImporter();
|
const importer = new ZohoVaultCsvImporter();
|
||||||
importer.organizationId = "someOrgId";
|
importer.organizationId = "someOrgId" as OrganizationId;
|
||||||
const result = await importer.parse(samplezohovaultcsvdata);
|
const result = await importer.parse(samplezohovaultcsvdata);
|
||||||
expect(result != null).toBe(true);
|
expect(result != null).toBe(true);
|
||||||
expect(result.success).toBe(true);
|
expect(result.success).toBe(true);
|
||||||
|
|||||||
@@ -9,6 +9,7 @@ import { PinServiceAbstraction } from "@bitwarden/common/key-management/pin/pin.
|
|||||||
import { I18nService } from "@bitwarden/common/platform/abstractions/i18n.service";
|
import { I18nService } from "@bitwarden/common/platform/abstractions/i18n.service";
|
||||||
import { Utils } from "@bitwarden/common/platform/misc/utils";
|
import { Utils } from "@bitwarden/common/platform/misc/utils";
|
||||||
import { MockSdkService } from "@bitwarden/common/platform/spec/mock-sdk.service";
|
import { MockSdkService } from "@bitwarden/common/platform/spec/mock-sdk.service";
|
||||||
|
import { CollectionId, OrganizationId } from "@bitwarden/common/types/guid";
|
||||||
import { CipherService } from "@bitwarden/common/vault/abstractions/cipher.service";
|
import { CipherService } from "@bitwarden/common/vault/abstractions/cipher.service";
|
||||||
import { FolderService } from "@bitwarden/common/vault/abstractions/folder/folder.service.abstraction";
|
import { FolderService } from "@bitwarden/common/vault/abstractions/folder/folder.service.abstraction";
|
||||||
import { CipherView } from "@bitwarden/common/vault/models/view/cipher.view";
|
import { CipherView } from "@bitwarden/common/vault/models/view/cipher.view";
|
||||||
@@ -67,7 +68,7 @@ describe("ImportService", () => {
|
|||||||
describe("getImporterInstance", () => {
|
describe("getImporterInstance", () => {
|
||||||
describe("Get bitPasswordProtected importer", () => {
|
describe("Get bitPasswordProtected importer", () => {
|
||||||
let importer: Importer;
|
let importer: Importer;
|
||||||
const organizationId = Utils.newGuid();
|
const organizationId = Utils.newGuid() as OrganizationId;
|
||||||
const password = Utils.newGuid();
|
const password = Utils.newGuid();
|
||||||
const promptForPassword_callback = async () => {
|
const promptForPassword_callback = async () => {
|
||||||
return password;
|
return password;
|
||||||
@@ -98,7 +99,7 @@ describe("ImportService", () => {
|
|||||||
});
|
});
|
||||||
|
|
||||||
describe("setImportTarget", () => {
|
describe("setImportTarget", () => {
|
||||||
const organizationId = Utils.newGuid();
|
const organizationId = Utils.newGuid() as OrganizationId;
|
||||||
|
|
||||||
let importResult: ImportResult;
|
let importResult: ImportResult;
|
||||||
|
|
||||||
@@ -145,19 +146,19 @@ describe("ImportService", () => {
|
|||||||
});
|
});
|
||||||
|
|
||||||
const mockImportTargetCollection = new CollectionView();
|
const mockImportTargetCollection = new CollectionView();
|
||||||
mockImportTargetCollection.id = "myImportTarget";
|
mockImportTargetCollection.id = "myImportTarget" as CollectionId;
|
||||||
mockImportTargetCollection.name = "myImportTarget";
|
mockImportTargetCollection.name = "myImportTarget";
|
||||||
mockImportTargetCollection.organizationId = organizationId;
|
mockImportTargetCollection.organizationId = organizationId;
|
||||||
|
|
||||||
const mockCollection1 = new CollectionView();
|
const mockCollection1 = new CollectionView();
|
||||||
mockCollection1.id = "collection1";
|
mockCollection1.id = "collection1" as CollectionId;
|
||||||
mockCollection1.name = "collection1";
|
mockCollection1.name = "collection1";
|
||||||
mockCollection1.organizationId = organizationId;
|
mockCollection1.organizationId = organizationId;
|
||||||
|
|
||||||
const mockCollection2 = new CollectionView();
|
const mockCollection2 = new CollectionView();
|
||||||
mockCollection1.id = "collection2";
|
mockCollection2.id = "collection2" as CollectionId;
|
||||||
mockCollection1.name = "collection2";
|
mockCollection2.name = "collection2";
|
||||||
mockCollection1.organizationId = organizationId;
|
mockCollection2.organizationId = organizationId;
|
||||||
|
|
||||||
it("passing importTarget adds it to collections", async () => {
|
it("passing importTarget adds it to collections", async () => {
|
||||||
await importService["setImportTarget"](
|
await importService["setImportTarget"](
|
||||||
|
|||||||
@@ -19,6 +19,7 @@ import { ErrorResponse } from "@bitwarden/common/models/response/error.response"
|
|||||||
import { I18nService } from "@bitwarden/common/platform/abstractions/i18n.service";
|
import { I18nService } from "@bitwarden/common/platform/abstractions/i18n.service";
|
||||||
import { SdkService } from "@bitwarden/common/platform/abstractions/sdk/sdk.service";
|
import { SdkService } from "@bitwarden/common/platform/abstractions/sdk/sdk.service";
|
||||||
import { Utils } from "@bitwarden/common/platform/misc/utils";
|
import { Utils } from "@bitwarden/common/platform/misc/utils";
|
||||||
|
import { OrganizationId } from "@bitwarden/common/types/guid";
|
||||||
import { CipherService } from "@bitwarden/common/vault/abstractions/cipher.service";
|
import { CipherService } from "@bitwarden/common/vault/abstractions/cipher.service";
|
||||||
import { FolderService } from "@bitwarden/common/vault/abstractions/folder/folder.service.abstraction";
|
import { FolderService } from "@bitwarden/common/vault/abstractions/folder/folder.service.abstraction";
|
||||||
import { CipherType, toCipherTypeName } from "@bitwarden/common/vault/enums";
|
import { CipherType, toCipherTypeName } from "@bitwarden/common/vault/enums";
|
||||||
@@ -130,7 +131,7 @@ export class ImportService implements ImportServiceAbstraction {
|
|||||||
async import(
|
async import(
|
||||||
importer: Importer,
|
importer: Importer,
|
||||||
fileContents: string,
|
fileContents: string,
|
||||||
organizationId: string = null,
|
organizationId: OrganizationId = null,
|
||||||
selectedImportTarget: FolderView | CollectionView = null,
|
selectedImportTarget: FolderView | CollectionView = null,
|
||||||
canAccessImportExport: boolean,
|
canAccessImportExport: boolean,
|
||||||
): Promise<ImportResult> {
|
): Promise<ImportResult> {
|
||||||
@@ -204,7 +205,7 @@ export class ImportService implements ImportServiceAbstraction {
|
|||||||
getImporter(
|
getImporter(
|
||||||
format: ImportType | "bitwardenpasswordprotected",
|
format: ImportType | "bitwardenpasswordprotected",
|
||||||
promptForPassword_callback: () => Promise<string>,
|
promptForPassword_callback: () => Promise<string>,
|
||||||
organizationId: string = null,
|
organizationId: OrganizationId = null,
|
||||||
): Importer {
|
): Importer {
|
||||||
if (promptForPassword_callback == null) {
|
if (promptForPassword_callback == null) {
|
||||||
return null;
|
return null;
|
||||||
@@ -393,7 +394,10 @@ export class ImportService implements ImportServiceAbstraction {
|
|||||||
return await this.importApiService.postImportCiphers(request);
|
return await this.importApiService.postImportCiphers(request);
|
||||||
}
|
}
|
||||||
|
|
||||||
private async handleOrganizationalImport(importResult: ImportResult, organizationId: string) {
|
private async handleOrganizationalImport(
|
||||||
|
importResult: ImportResult,
|
||||||
|
organizationId: OrganizationId,
|
||||||
|
) {
|
||||||
const request = new ImportOrganizationCiphersRequest();
|
const request = new ImportOrganizationCiphersRequest();
|
||||||
const activeUserId = await firstValueFrom(
|
const activeUserId = await firstValueFrom(
|
||||||
this.accountService.activeAccount$.pipe(map((a) => a?.id)),
|
this.accountService.activeAccount$.pipe(map((a) => a?.id)),
|
||||||
|
|||||||
@@ -14,6 +14,7 @@ import { Policy } from "@bitwarden/common/admin-console/models/domain/policy";
|
|||||||
import { AccountService } from "@bitwarden/common/auth/abstractions/account.service";
|
import { AccountService } from "@bitwarden/common/auth/abstractions/account.service";
|
||||||
import { ConfigService } from "@bitwarden/common/platform/abstractions/config/config.service";
|
import { ConfigService } from "@bitwarden/common/platform/abstractions/config/config.service";
|
||||||
import { I18nService } from "@bitwarden/common/platform/abstractions/i18n.service";
|
import { I18nService } from "@bitwarden/common/platform/abstractions/i18n.service";
|
||||||
|
import { CollectionId, OrganizationId } from "@bitwarden/common/types/guid";
|
||||||
import { CipherView } from "@bitwarden/common/vault/models/view/cipher.view";
|
import { CipherView } from "@bitwarden/common/vault/models/view/cipher.view";
|
||||||
import { SelectComponent } from "@bitwarden/components";
|
import { SelectComponent } from "@bitwarden/components";
|
||||||
|
|
||||||
@@ -33,9 +34,9 @@ const createMockCollection = (
|
|||||||
canEdit = true,
|
canEdit = true,
|
||||||
): CollectionView => {
|
): CollectionView => {
|
||||||
return {
|
return {
|
||||||
id,
|
id: id as CollectionId,
|
||||||
name,
|
name,
|
||||||
organizationId,
|
organizationId: organizationId as OrganizationId,
|
||||||
externalId: "",
|
externalId: "",
|
||||||
readOnly,
|
readOnly,
|
||||||
hidePasswords: false,
|
hidePasswords: false,
|
||||||
|
|||||||
Reference in New Issue
Block a user