mirror of
https://github.com/bitwarden/browser
synced 2025-12-10 13:23:34 +00:00
Import: Migrate input to handle and validate organization (#16920)
* Verify route and input to be a valid organizationId * Optimize canImport check Instead of loading the user and organization again, used the previously loaded organization and check the permission directly * Reset organization in case organizationId is set to undefined --------- Co-authored-by: Daniel James Smith <djsmith85@users.noreply.github.com>
This commit is contained in:
committed by
GitHub
parent
a860f218bd
commit
b8d55c4db1
@@ -1,5 +1,3 @@
|
|||||||
// FIXME: Update this file to be type safe and remove this and next line
|
|
||||||
// @ts-strict-ignore
|
|
||||||
import { Component, OnInit } from "@angular/core";
|
import { Component, OnInit } from "@angular/core";
|
||||||
import { ActivatedRoute, Router } from "@angular/router";
|
import { ActivatedRoute, Router } from "@angular/router";
|
||||||
import { firstValueFrom, map } from "rxjs";
|
import { firstValueFrom, map } from "rxjs";
|
||||||
@@ -11,6 +9,7 @@ import {
|
|||||||
} from "@bitwarden/common/admin-console/abstractions/organization/organization.service.abstraction";
|
} from "@bitwarden/common/admin-console/abstractions/organization/organization.service.abstraction";
|
||||||
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 { isId, OrganizationId } from "@bitwarden/common/types/guid";
|
||||||
import { ImportCollectionServiceAbstraction } from "@bitwarden/importer-core";
|
import { ImportCollectionServiceAbstraction } from "@bitwarden/importer-core";
|
||||||
import { ImportComponent } from "@bitwarden/importer-ui";
|
import { ImportComponent } from "@bitwarden/importer-ui";
|
||||||
|
|
||||||
@@ -31,7 +30,7 @@ import { ImportCollectionAdminService } from "./import-collection-admin.service"
|
|||||||
],
|
],
|
||||||
})
|
})
|
||||||
export class OrgImportComponent implements OnInit {
|
export class OrgImportComponent implements OnInit {
|
||||||
protected routeOrgId: string = null;
|
protected routeOrgId: OrganizationId | undefined = undefined;
|
||||||
protected loading = false;
|
protected loading = false;
|
||||||
protected disabled = false;
|
protected disabled = false;
|
||||||
|
|
||||||
@@ -43,7 +42,16 @@ export class OrgImportComponent implements OnInit {
|
|||||||
) {}
|
) {}
|
||||||
|
|
||||||
ngOnInit(): void {
|
ngOnInit(): void {
|
||||||
this.routeOrgId = this.route.snapshot.paramMap.get("organizationId");
|
const orgIdParam = this.route.snapshot.paramMap.get("organizationId");
|
||||||
|
if (orgIdParam === undefined) {
|
||||||
|
throw new Error("`organizationId` is a required route parameter");
|
||||||
|
}
|
||||||
|
|
||||||
|
if (!isId<OrganizationId>(orgIdParam)) {
|
||||||
|
throw new Error("Invalid OrganizationId provided in route parameter `organizationId`");
|
||||||
|
}
|
||||||
|
|
||||||
|
this.routeOrgId = orgIdParam;
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
|||||||
@@ -35,10 +35,7 @@ import {
|
|||||||
CollectionView,
|
CollectionView,
|
||||||
} from "@bitwarden/admin-console/common";
|
} from "@bitwarden/admin-console/common";
|
||||||
import { JslibModule } from "@bitwarden/angular/jslib.module";
|
import { JslibModule } from "@bitwarden/angular/jslib.module";
|
||||||
import {
|
import { OrganizationService } from "@bitwarden/common/admin-console/abstractions/organization/organization.service.abstraction";
|
||||||
getOrganizationById,
|
|
||||||
OrganizationService,
|
|
||||||
} from "@bitwarden/common/admin-console/abstractions/organization/organization.service.abstraction";
|
|
||||||
import { PolicyService } from "@bitwarden/common/admin-console/abstractions/policy/policy.service.abstraction";
|
import { PolicyService } from "@bitwarden/common/admin-console/abstractions/policy/policy.service.abstraction";
|
||||||
import { PolicyType } from "@bitwarden/common/admin-console/enums";
|
import { PolicyType } from "@bitwarden/common/admin-console/enums";
|
||||||
import { Organization } from "@bitwarden/common/admin-console/models/domain/organization";
|
import { Organization } from "@bitwarden/common/admin-console/models/domain/organization";
|
||||||
@@ -48,7 +45,9 @@ import { ClientType } from "@bitwarden/common/enums";
|
|||||||
import { I18nService } from "@bitwarden/common/platform/abstractions/i18n.service";
|
import { I18nService } from "@bitwarden/common/platform/abstractions/i18n.service";
|
||||||
import { LogService } from "@bitwarden/common/platform/abstractions/log.service";
|
import { LogService } from "@bitwarden/common/platform/abstractions/log.service";
|
||||||
import { PlatformUtilsService } from "@bitwarden/common/platform/abstractions/platform-utils.service";
|
import { PlatformUtilsService } from "@bitwarden/common/platform/abstractions/platform-utils.service";
|
||||||
|
import { getById } from "@bitwarden/common/platform/misc";
|
||||||
import { Utils } from "@bitwarden/common/platform/misc/utils";
|
import { Utils } from "@bitwarden/common/platform/misc/utils";
|
||||||
|
import { isId, OrganizationId } from "@bitwarden/common/types/guid";
|
||||||
import { FolderService } from "@bitwarden/common/vault/abstractions/folder/folder.service.abstraction";
|
import { FolderService } from "@bitwarden/common/vault/abstractions/folder/folder.service.abstraction";
|
||||||
import { SyncService } from "@bitwarden/common/vault/abstractions/sync/sync.service.abstraction";
|
import { SyncService } from "@bitwarden/common/vault/abstractions/sync/sync.service.abstraction";
|
||||||
import { FolderView } from "@bitwarden/common/vault/models/view/folder.view";
|
import { FolderView } from "@bitwarden/common/vault/models/view/folder.view";
|
||||||
@@ -122,21 +121,34 @@ export class ImportComponent implements OnInit, OnDestroy, AfterViewInit {
|
|||||||
collections$: Observable<CollectionView[]>;
|
collections$: Observable<CollectionView[]>;
|
||||||
organizations$: Observable<Organization[]>;
|
organizations$: Observable<Organization[]>;
|
||||||
|
|
||||||
private _organizationId: string;
|
private _organizationId: OrganizationId | undefined;
|
||||||
|
|
||||||
get organizationId(): string {
|
get organizationId(): OrganizationId | undefined {
|
||||||
return this._organizationId;
|
return this._organizationId;
|
||||||
}
|
}
|
||||||
|
|
||||||
@Input() set organizationId(value: string) {
|
/**
|
||||||
|
* Enables the hosting control to pass in an organizationId
|
||||||
|
* If a organizationId is provided, the organization selection is disabled.
|
||||||
|
*/
|
||||||
|
@Input() set organizationId(value: OrganizationId | string | undefined) {
|
||||||
|
if (Utils.isNullOrEmpty(value)) {
|
||||||
|
this._organizationId = undefined;
|
||||||
|
this.organization = undefined;
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (!isId<OrganizationId>(value)) {
|
||||||
|
this._organizationId = undefined;
|
||||||
|
this.organization = undefined;
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
this._organizationId = value;
|
this._organizationId = value;
|
||||||
|
|
||||||
getUserId(this.accountService.activeAccount$)
|
getUserId(this.accountService.activeAccount$)
|
||||||
.pipe(
|
.pipe(
|
||||||
switchMap((userId) =>
|
switchMap((userId) => this.organizationService.organizations$(userId).pipe(getById(value))),
|
||||||
this.organizationService
|
|
||||||
.organizations$(userId)
|
|
||||||
.pipe(getOrganizationById(this._organizationId)),
|
|
||||||
),
|
|
||||||
)
|
)
|
||||||
.pipe(takeUntil(this.destroy$))
|
.pipe(takeUntil(this.destroy$))
|
||||||
.subscribe((organization) => {
|
.subscribe((organization) => {
|
||||||
@@ -151,7 +163,7 @@ export class ImportComponent implements OnInit, OnDestroy, AfterViewInit {
|
|||||||
@Input()
|
@Input()
|
||||||
onImportFromBrowser: (browser: string, profile: string) => Promise<any[]>;
|
onImportFromBrowser: (browser: string, profile: string) => Promise<any[]>;
|
||||||
|
|
||||||
protected organization: Organization;
|
protected organization: Organization | undefined = undefined;
|
||||||
protected destroy$ = new Subject<void>();
|
protected destroy$ = new Subject<void>();
|
||||||
|
|
||||||
protected readonly isCardTypeRestricted$: Observable<boolean> =
|
protected readonly isCardTypeRestricted$: Observable<boolean> =
|
||||||
@@ -451,7 +463,7 @@ export class ImportComponent implements OnInit, OnDestroy, AfterViewInit {
|
|||||||
importContents,
|
importContents,
|
||||||
this.organizationId,
|
this.organizationId,
|
||||||
this.formGroup.controls.targetSelector.value,
|
this.formGroup.controls.targetSelector.value,
|
||||||
(await this.canAccessImport(this.organizationId)) && this.isFromAC,
|
this.organization?.canAccessImport && this.isFromAC,
|
||||||
);
|
);
|
||||||
|
|
||||||
//No errors, display success message
|
//No errors, display success message
|
||||||
@@ -471,20 +483,6 @@ export class ImportComponent implements OnInit, OnDestroy, AfterViewInit {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
private async canAccessImport(organizationId?: string): Promise<boolean> {
|
|
||||||
if (!organizationId) {
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
const userId = await firstValueFrom(getUserId(this.accountService.activeAccount$));
|
|
||||||
return (
|
|
||||||
await firstValueFrom(
|
|
||||||
this.organizationService
|
|
||||||
.organizations$(userId)
|
|
||||||
.pipe(getOrganizationById(this.organizationId)),
|
|
||||||
)
|
|
||||||
)?.canAccessImport;
|
|
||||||
}
|
|
||||||
|
|
||||||
getFormatInstructionTitle() {
|
getFormatInstructionTitle() {
|
||||||
if (this.format == null) {
|
if (this.format == null) {
|
||||||
return null;
|
return null;
|
||||||
|
|||||||
Reference in New Issue
Block a user