From 51c5e053f7f1c1112e0bce4e15b76304c3ad00f3 Mon Sep 17 00:00:00 2001
From: Thomas Avery <43214426+Thomas-Avery@users.noreply.github.com>
Date: Thu, 7 Dec 2023 15:33:45 -0600
Subject: [PATCH] [SM-909] Migrate service account people tab to new selector
(#6534)
* migrate sa -> people tab to new selector
* remove unused code
* Add access token still available warning
---
apps/web/src/locales/en/messages.json | 5 +-
.../models/view/access-policy.view.ts | 3 +-
.../service-account-people.component.html | 38 +-
.../service-account-people.component.ts | 326 ++++++++++--------
.../service-accounts.component.ts | 3 -
.../access-policy-selector.service.spec.ts | 118 +++++++
.../access-policy-selector.service.ts | 22 ++
.../models/ap-item-value.type.ts | 33 ++
.../models/ap-item-view.type.ts | 7 +-
.../access-policies/access-policy.service.ts | 183 +++-------
.../access-removal-dialog.component.html | 14 -
.../access-removal-dialog.component.ts | 69 ----
.../responses/access-policy.response.ts | 2 +
...ccount-people-access-policies.response.ts} | 2 +-
.../shared/sm-shared.module.ts | 3 -
15 files changed, 452 insertions(+), 376 deletions(-)
delete mode 100644 bitwarden_license/bit-web/src/app/secrets-manager/shared/access-policies/dialogs/access-removal-dialog.component.html
delete mode 100644 bitwarden_license/bit-web/src/app/secrets-manager/shared/access-policies/dialogs/access-removal-dialog.component.ts
rename bitwarden_license/bit-web/src/app/secrets-manager/shared/access-policies/models/responses/{service-accounts-access-policies.response.ts => service-account-people-access-policies.response.ts} (91%)
diff --git a/apps/web/src/locales/en/messages.json b/apps/web/src/locales/en/messages.json
index 0929019670..236ba76cfe 100644
--- a/apps/web/src/locales/en/messages.json
+++ b/apps/web/src/locales/en/messages.json
@@ -7415,7 +7415,7 @@
"example": "Unique ID"
}
}
- },
+ },
"seeDetailedInstructions": {
"message": "See detailed instructions on our help site at",
"description": "This is followed a by a hyperlink to the help website."
@@ -7437,5 +7437,8 @@
},
"collectionAccessRestricted": {
"message": "Collection access is restricted"
+ },
+ "serviceAccountAccessUpdated": {
+ "message": "Service account access updated"
}
}
diff --git a/bitwarden_license/bit-web/src/app/secrets-manager/models/view/access-policy.view.ts b/bitwarden_license/bit-web/src/app/secrets-manager/models/view/access-policy.view.ts
index 1b102acaa5..958fe0d48e 100644
--- a/bitwarden_license/bit-web/src/app/secrets-manager/models/view/access-policy.view.ts
+++ b/bitwarden_license/bit-web/src/app/secrets-manager/models/view/access-policy.view.ts
@@ -19,6 +19,7 @@ export class UserServiceAccountAccessPolicyView extends BaseAccessPolicyView {
organizationUserName: string;
grantedServiceAccountId: string;
userId: string;
+ currentUser: boolean;
}
export class GroupProjectAccessPolicyView extends BaseAccessPolicyView {
@@ -53,7 +54,7 @@ export class ProjectPeopleAccessPoliciesView {
groupAccessPolicies: GroupProjectAccessPolicyView[];
}
-export class ServiceAccountAccessPoliciesView {
+export class ServiceAccountPeopleAccessPoliciesView {
userAccessPolicies: UserServiceAccountAccessPolicyView[];
groupAccessPolicies: GroupServiceAccountAccessPolicyView[];
}
diff --git a/bitwarden_license/bit-web/src/app/secrets-manager/service-accounts/people/service-account-people.component.html b/bitwarden_license/bit-web/src/app/secrets-manager/service-accounts/people/service-account-people.component.html
index 2a490d7914..79c8132bbc 100644
--- a/bitwarden_license/bit-web/src/app/secrets-manager/service-accounts/people/service-account-people.component.html
+++ b/bitwarden_license/bit-web/src/app/secrets-manager/service-accounts/people/service-account-people.component.html
@@ -1,16 +1,22 @@
-
-
- {{ "serviceAccountPeopleDescription" | i18n }}
-
-
-
-
+
diff --git a/bitwarden_license/bit-web/src/app/secrets-manager/service-accounts/people/service-account-people.component.ts b/bitwarden_license/bit-web/src/app/secrets-manager/service-accounts/people/service-account-people.component.ts
index 4874605040..04e0617815 100644
--- a/bitwarden_license/bit-web/src/app/secrets-manager/service-accounts/people/service-account-people.component.ts
+++ b/bitwarden_license/bit-web/src/app/secrets-manager/service-accounts/people/service-account-people.component.ts
@@ -1,162 +1,93 @@
-import { Component } from "@angular/core";
-import { ActivatedRoute } from "@angular/router";
-import {
- combineLatestWith,
- map,
- Observable,
- share,
- startWith,
- Subject,
- switchMap,
- takeUntil,
-} from "rxjs";
+import { ChangeDetectorRef, Component, OnDestroy, OnInit } from "@angular/core";
+import { FormControl, FormGroup } from "@angular/forms";
+import { ActivatedRoute, Router } from "@angular/router";
+import { catchError, combineLatest, EMPTY, Subject, switchMap, takeUntil } from "rxjs";
import { I18nService } from "@bitwarden/common/platform/abstractions/i18n.service";
+import { PlatformUtilsService } from "@bitwarden/common/platform/abstractions/platform-utils.service";
import { ValidationService } from "@bitwarden/common/platform/abstractions/validation.service";
-import { DialogService, SimpleDialogOptions } from "@bitwarden/components";
-import { SelectItemView } from "@bitwarden/components/src/multi-select/models/select-item-view";
+import { DialogService } from "@bitwarden/components";
+import { AccessPolicySelectorService } from "../../shared/access-policies/access-policy-selector/access-policy-selector.service";
import {
- GroupServiceAccountAccessPolicyView,
- ServiceAccountAccessPoliciesView,
- UserServiceAccountAccessPolicyView,
-} from "../../models/view/access-policy.view";
+ ApItemValueType,
+ convertToServiceAccountPeopleAccessPoliciesView,
+} from "../../shared/access-policies/access-policy-selector/models/ap-item-value.type";
+import {
+ ApItemViewType,
+ convertPotentialGranteesToApItemViewType,
+ convertToAccessPolicyItemViews,
+} from "../../shared/access-policies/access-policy-selector/models/ap-item-view.type";
+import { ApItemEnum } from "../../shared/access-policies/access-policy-selector/models/enums/ap-item.enum";
+import { ApPermissionEnum } from "../../shared/access-policies/access-policy-selector/models/enums/ap-permission.enum";
import { AccessPolicyService } from "../../shared/access-policies/access-policy.service";
-import {
- AccessSelectorComponent,
- AccessSelectorRowView,
-} from "../../shared/access-policies/access-selector.component";
-import {
- AccessRemovalDetails,
- AccessRemovalDialogComponent,
-} from "../../shared/access-policies/dialogs/access-removal-dialog.component";
@Component({
selector: "sm-service-account-people",
templateUrl: "./service-account-people.component.html",
})
-export class ServiceAccountPeopleComponent {
+export class ServiceAccountPeopleComponent implements OnInit, OnDestroy {
+ private currentAccessPolicies: ApItemViewType[];
private destroy$ = new Subject();
- private serviceAccountId: string;
private organizationId: string;
- private rows: AccessSelectorRowView[];
+ private serviceAccountId: string;
- protected rows$: Observable =
- this.accessPolicyService.serviceAccountAccessPolicyChanges$.pipe(
- startWith(null),
- combineLatestWith(this.route.params),
- switchMap(([_, params]) =>
- this.accessPolicyService.getServiceAccountAccessPolicies(params.serviceAccountId),
- ),
- map((policies) => {
- const rows: AccessSelectorRowView[] = [];
- policies.userAccessPolicies.forEach((policy) => {
- rows.push({
- type: "user",
- name: policy.organizationUserName,
- id: policy.organizationUserId,
- accessPolicyId: policy.id,
- read: policy.read,
- write: policy.write,
- userId: policy.userId,
- icon: AccessSelectorComponent.userIcon,
- static: true,
- });
- });
+ private currentAccessPolicies$ = combineLatest([this.route.params]).pipe(
+ switchMap(([params]) =>
+ this.accessPolicyService
+ .getServiceAccountPeopleAccessPolicies(params.serviceAccountId)
+ .then((policies) => {
+ return convertToAccessPolicyItemViews(policies);
+ }),
+ ),
+ catchError(() => {
+ this.router.navigate(["/sm", this.organizationId, "service-accounts"]);
+ return EMPTY;
+ }),
+ );
- policies.groupAccessPolicies.forEach((policy) => {
- rows.push({
- type: "group",
- name: policy.groupName,
- id: policy.groupId,
- accessPolicyId: policy.id,
- read: policy.read,
- write: policy.write,
- currentUserInGroup: policy.currentUserInGroup,
- icon: AccessSelectorComponent.groupIcon,
- static: true,
- });
- });
+ private potentialGrantees$ = combineLatest([this.route.params]).pipe(
+ switchMap(([params]) =>
+ this.accessPolicyService
+ .getPeoplePotentialGrantees(params.organizationId)
+ .then((grantees) => {
+ return convertPotentialGranteesToApItemViewType(grantees);
+ }),
+ ),
+ );
- return rows;
- }),
- share(),
- );
+ protected formGroup = new FormGroup({
+ accessPolicies: new FormControl([] as ApItemValueType[]),
+ });
- protected handleCreateAccessPolicies(selected: SelectItemView[]) {
- const serviceAccountAccessPoliciesView = new ServiceAccountAccessPoliciesView();
- serviceAccountAccessPoliciesView.userAccessPolicies = selected
- .filter((selection) => AccessSelectorComponent.getAccessItemType(selection) === "user")
- .map((filtered) => {
- const view = new UserServiceAccountAccessPolicyView();
- view.grantedServiceAccountId = this.serviceAccountId;
- view.organizationUserId = filtered.id;
- view.read = true;
- view.write = true;
- return view;
- });
-
- serviceAccountAccessPoliciesView.groupAccessPolicies = selected
- .filter((selection) => AccessSelectorComponent.getAccessItemType(selection) === "group")
- .map((filtered) => {
- const view = new GroupServiceAccountAccessPolicyView();
- view.grantedServiceAccountId = this.serviceAccountId;
- view.groupId = filtered.id;
- view.read = true;
- view.write = true;
- return view;
- });
-
- return this.accessPolicyService.createServiceAccountAccessPolicies(
- this.serviceAccountId,
- serviceAccountAccessPoliciesView,
- );
- }
-
- protected async handleDeleteAccessPolicy(policy: AccessSelectorRowView) {
- if (
- await this.accessPolicyService.needToShowAccessRemovalWarning(
- this.organizationId,
- policy,
- this.rows,
- )
- ) {
- this.launchDeleteWarningDialog(policy);
- return;
- }
-
- try {
- await this.accessPolicyService.deleteAccessPolicy(policy.accessPolicyId);
- const simpleDialogOpts: SimpleDialogOptions = {
- title: this.i18nService.t("saPeopleWarningTitle"),
- content: this.i18nService.t("saPeopleWarningMessage"),
- type: "warning",
- acceptButtonText: { key: "close" },
- cancelButtonText: null,
- };
- this.dialogService.openSimpleDialogRef(simpleDialogOpts);
- } catch (e) {
- this.validationService.showError(e);
- }
- }
+ protected loading = true;
+ protected potentialGrantees: ApItemViewType[];
+ protected staticPermission = ApPermissionEnum.CanReadWrite;
constructor(
private route: ActivatedRoute,
private dialogService: DialogService,
- private i18nService: I18nService,
+ private changeDetectorRef: ChangeDetectorRef,
private validationService: ValidationService,
private accessPolicyService: AccessPolicyService,
+ private router: Router,
+ private platformUtilsService: PlatformUtilsService,
+ private i18nService: I18nService,
+ private accessPolicySelectorService: AccessPolicySelectorService,
) {}
ngOnInit(): void {
this.route.params.pipe(takeUntil(this.destroy$)).subscribe((params) => {
- this.serviceAccountId = params.serviceAccountId;
this.organizationId = params.organizationId;
+ this.serviceAccountId = params.serviceAccountId;
});
- this.rows$.pipe(takeUntil(this.destroy$)).subscribe((rows) => {
- this.rows = rows;
- });
+ combineLatest([this.potentialGrantees$, this.currentAccessPolicies$])
+ .pipe(takeUntil(this.destroy$))
+ .subscribe(([potentialGrantees, currentAccessPolicies]) => {
+ this.potentialGrantees = potentialGrantees;
+ this.setSelected(currentAccessPolicies);
+ });
}
ngOnDestroy(): void {
@@ -164,16 +95,133 @@ export class ServiceAccountPeopleComponent {
this.destroy$.complete();
}
- private launchDeleteWarningDialog(policy: AccessSelectorRowView) {
- this.dialogService.open(AccessRemovalDialogComponent, {
- data: {
- title: "smAccessRemovalWarningSaTitle",
- message: "smAccessRemovalWarningSaMessage",
- operation: "delete",
- type: "service-account",
- returnRoute: ["sm", this.organizationId, "service-accounts"],
- policy,
- },
+ submit = async () => {
+ if (this.isFormInvalid()) {
+ return;
+ }
+
+ const showAccessRemovalWarning =
+ await this.accessPolicySelectorService.showAccessRemovalWarning(
+ this.organizationId,
+ this.formGroup.value.accessPolicies,
+ );
+
+ if (
+ await this.handleAccessRemovalWarning(showAccessRemovalWarning, this.currentAccessPolicies)
+ ) {
+ return;
+ }
+
+ try {
+ const peoplePoliciesViews = await this.updateServiceAccountPeopleAccessPolicies(
+ this.serviceAccountId,
+ this.formGroup.value.accessPolicies,
+ );
+
+ await this.handleAccessTokenAvailableWarning(
+ showAccessRemovalWarning,
+ this.currentAccessPolicies,
+ this.formGroup.value.accessPolicies,
+ );
+
+ this.currentAccessPolicies = convertToAccessPolicyItemViews(peoplePoliciesViews);
+
+ this.platformUtilsService.showToast(
+ "success",
+ null,
+ this.i18nService.t("serviceAccountAccessUpdated"),
+ );
+ } catch (e) {
+ this.validationService.showError(e);
+ this.setSelected(this.currentAccessPolicies);
+ }
+ };
+
+ private setSelected(policiesToSelect: ApItemViewType[]) {
+ this.loading = true;
+ this.currentAccessPolicies = policiesToSelect;
+ if (policiesToSelect != undefined) {
+ // Must detect changes so that AccessSelector @Inputs() are aware of the latest
+ // potentialGrantees, otherwise no selected values will be patched below
+ this.changeDetectorRef.detectChanges();
+ this.formGroup.patchValue({
+ accessPolicies: policiesToSelect.map((m) => ({
+ type: m.type,
+ id: m.id,
+ permission: m.permission,
+ currentUser: m.type == ApItemEnum.User ? m.currentUser : null,
+ currentUserInGroup: m.type == ApItemEnum.Group ? m.currentUserInGroup : null,
+ })),
+ });
+ }
+ this.loading = false;
+ }
+
+ private isFormInvalid(): boolean {
+ this.formGroup.markAllAsTouched();
+ return this.formGroup.invalid;
+ }
+
+ private async handleAccessRemovalWarning(
+ showAccessRemovalWarning: boolean,
+ currentAccessPolicies: ApItemViewType[],
+ ): Promise {
+ if (showAccessRemovalWarning) {
+ const confirmed = await this.showWarning();
+ if (!confirmed) {
+ this.setSelected(currentAccessPolicies);
+ return true;
+ }
+ }
+ return false;
+ }
+
+ private async updateServiceAccountPeopleAccessPolicies(
+ serviceAccountId: string,
+ selectedPolicies: ApItemValueType[],
+ ) {
+ const serviceAccountPeopleView = convertToServiceAccountPeopleAccessPoliciesView(
+ serviceAccountId,
+ selectedPolicies,
+ );
+ return await this.accessPolicyService.putServiceAccountPeopleAccessPolicies(
+ serviceAccountId,
+ serviceAccountPeopleView,
+ );
+ }
+
+ private async handleAccessTokenAvailableWarning(
+ showAccessRemovalWarning: boolean,
+ currentAccessPolicies: ApItemViewType[],
+ selectedPolicies: ApItemValueType[],
+ ): Promise {
+ if (showAccessRemovalWarning) {
+ this.router.navigate(["sm", this.organizationId, "service-accounts"]);
+ } else if (
+ this.accessPolicySelectorService.isAccessRemoval(currentAccessPolicies, selectedPolicies)
+ ) {
+ await this.showAccessTokenStillAvailableWarning();
+ }
+ }
+
+ private async showWarning(): Promise {
+ const confirmed = await this.dialogService.openSimpleDialog({
+ title: { key: "smAccessRemovalWarningSaTitle" },
+ content: { key: "smAccessRemovalWarningSaMessage" },
+ acceptButtonText: { key: "removeAccess" },
+ cancelButtonText: { key: "cancel" },
+ type: "warning",
+ });
+ return confirmed;
+ }
+
+ private async showAccessTokenStillAvailableWarning(): Promise {
+ await this.dialogService.openSimpleDialog({
+ title: { key: "saPeopleWarningTitle" },
+ content: { key: "saPeopleWarningMessage" },
+ type: "warning",
+ acceptButtonText: { key: "close" },
+ cancelButtonText: null,
});
}
}
diff --git a/bitwarden_license/bit-web/src/app/secrets-manager/service-accounts/service-accounts.component.ts b/bitwarden_license/bit-web/src/app/secrets-manager/service-accounts/service-accounts.component.ts
index 70d4e0c9c3..a5e3cd29d2 100644
--- a/bitwarden_license/bit-web/src/app/secrets-manager/service-accounts/service-accounts.component.ts
+++ b/bitwarden_license/bit-web/src/app/secrets-manager/service-accounts/service-accounts.component.ts
@@ -9,7 +9,6 @@ import {
ServiceAccountSecretsDetailsView,
ServiceAccountView,
} from "../models/view/service-account.view";
-import { AccessPolicyService } from "../shared/access-policies/access-policy.service";
import {
ServiceAccountDeleteDialogComponent,
@@ -36,7 +35,6 @@ export class ServiceAccountsComponent implements OnInit {
constructor(
private route: ActivatedRoute,
private dialogService: DialogService,
- private accessPolicyService: AccessPolicyService,
private serviceAccountService: ServiceAccountService,
private organizationService: OrganizationService,
) {}
@@ -45,7 +43,6 @@ export class ServiceAccountsComponent implements OnInit {
this.serviceAccounts$ = combineLatest([
this.route.params,
this.serviceAccountService.serviceAccount$.pipe(startWith(null)),
- this.accessPolicyService.serviceAccountAccessPolicyChanges$.pipe(startWith(null)),
]).pipe(
switchMap(async ([params]) => {
this.organizationId = params.organizationId;
diff --git a/bitwarden_license/bit-web/src/app/secrets-manager/shared/access-policies/access-policy-selector/access-policy-selector.service.spec.ts b/bitwarden_license/bit-web/src/app/secrets-manager/shared/access-policies/access-policy-selector/access-policy-selector.service.spec.ts
index 9f200f2f56..482d2bb06b 100644
--- a/bitwarden_license/bit-web/src/app/secrets-manager/shared/access-policies/access-policy-selector/access-policy-selector.service.spec.ts
+++ b/bitwarden_license/bit-web/src/app/secrets-manager/shared/access-policies/access-policy-selector/access-policy-selector.service.spec.ts
@@ -6,6 +6,7 @@ import { Organization } from "@bitwarden/common/admin-console/models/domain/orga
import { AccessPolicySelectorService } from "./access-policy-selector.service";
import { ApItemValueType } from "./models/ap-item-value.type";
+import { ApItemViewType } from "./models/ap-item-view.type";
import { ApItemEnum } from "./models/enums/ap-item.enum";
import { ApPermissionEnum } from "./models/enums/ap-permission.enum";
@@ -207,6 +208,113 @@ describe("AccessPolicySelectorService", () => {
const result = await sut.showAccessRemovalWarning(org.id, selectedPolicyValues);
+ expect(result).toBe(true);
+ });
+ });
+ describe("isAccessRemoval", () => {
+ it("returns false when there are no previous policies and no selected policies", async () => {
+ const currentAccessPolicies: ApItemViewType[] = [];
+ const selectedPolicyValues: ApItemValueType[] = [];
+
+ const result = sut.isAccessRemoval(currentAccessPolicies, selectedPolicyValues);
+
+ expect(result).toBe(false);
+ });
+ it("returns false when there are no previous policies", async () => {
+ const currentAccessPolicies: ApItemViewType[] = [];
+ const selectedPolicyValues: ApItemValueType[] = [
+ createApItemValueType({
+ id: "example",
+ permission: ApPermissionEnum.CanRead,
+ currentUser: true,
+ }),
+ ];
+
+ const result = sut.isAccessRemoval(currentAccessPolicies, selectedPolicyValues);
+
+ expect(result).toBe(false);
+ });
+ it("returns false when previous policies and selected policies are the same", async () => {
+ const currentAccessPolicies: ApItemViewType[] = [
+ createApItemViewType({
+ id: "example",
+ permission: ApPermissionEnum.CanRead,
+ currentUser: true,
+ }),
+ ];
+ const selectedPolicyValues: ApItemValueType[] = [
+ createApItemValueType({
+ id: "example",
+ permission: ApPermissionEnum.CanRead,
+ currentUser: true,
+ }),
+ ];
+
+ const result = sut.isAccessRemoval(currentAccessPolicies, selectedPolicyValues);
+
+ expect(result).toBe(false);
+ });
+ it("returns false when previous policies are still selected", async () => {
+ const currentAccessPolicies: ApItemViewType[] = [
+ createApItemViewType({
+ id: "example",
+ permission: ApPermissionEnum.CanRead,
+ currentUser: true,
+ }),
+ ];
+ const selectedPolicyValues: ApItemValueType[] = [
+ createApItemValueType({
+ id: "example",
+ permission: ApPermissionEnum.CanRead,
+ currentUser: true,
+ }),
+ createApItemValueType({
+ id: "example-2",
+ permission: ApPermissionEnum.CanRead,
+ currentUser: true,
+ }),
+ ];
+
+ const result = sut.isAccessRemoval(currentAccessPolicies, selectedPolicyValues);
+
+ expect(result).toBe(false);
+ });
+ it("returns true when previous policies are not selected", async () => {
+ const currentAccessPolicies: ApItemViewType[] = [
+ createApItemViewType({
+ id: "example",
+ permission: ApPermissionEnum.CanRead,
+ currentUser: true,
+ }),
+ ];
+ const selectedPolicyValues: ApItemValueType[] = [
+ createApItemValueType({
+ id: "test",
+ permission: ApPermissionEnum.CanRead,
+ currentUser: true,
+ }),
+ createApItemValueType({
+ id: "example-2",
+ permission: ApPermissionEnum.CanRead,
+ currentUser: true,
+ }),
+ ];
+
+ const result = sut.isAccessRemoval(currentAccessPolicies, selectedPolicyValues);
+
+ expect(result).toBe(true);
+ });
+ it("returns true when there are previous policies and nothing was selected", async () => {
+ const currentAccessPolicies: ApItemViewType[] = [
+ createApItemViewType({
+ permission: ApPermissionEnum.CanRead,
+ currentUser: true,
+ }),
+ ];
+ const selectedPolicyValues: ApItemValueType[] = [];
+
+ const result = sut.isAccessRemoval(currentAccessPolicies, selectedPolicyValues);
+
expect(result).toBe(true);
});
});
@@ -232,6 +340,16 @@ function createApItemValueType(options: Partial = {}) {
};
}
+function createApItemViewType(options: Partial = {}) {
+ return {
+ id: options?.id ?? "test",
+ listName: options?.listName ?? "test",
+ labelName: options?.labelName ?? "test",
+ type: options?.type ?? ApItemEnum.User,
+ permission: options?.permission ?? ApPermissionEnum.CanRead,
+ };
+}
+
function setupUserOrg() {
const userId = "testUserId";
const org = orgFactory({ userId: userId });
diff --git a/bitwarden_license/bit-web/src/app/secrets-manager/shared/access-policies/access-policy-selector/access-policy-selector.service.ts b/bitwarden_license/bit-web/src/app/secrets-manager/shared/access-policies/access-policy-selector/access-policy-selector.service.ts
index 7923590ab4..4a90172d45 100644
--- a/bitwarden_license/bit-web/src/app/secrets-manager/shared/access-policies/access-policy-selector/access-policy-selector.service.ts
+++ b/bitwarden_license/bit-web/src/app/secrets-manager/shared/access-policies/access-policy-selector/access-policy-selector.service.ts
@@ -3,6 +3,7 @@ import { Injectable } from "@angular/core";
import { OrganizationService } from "@bitwarden/common/admin-console/abstractions/organization/organization.service.abstraction";
import { ApItemValueType } from "./models/ap-item-value.type";
+import { ApItemViewType } from "./models/ap-item-view.type";
import { ApItemEnum } from "./models/enums/ap-item.enum";
import { ApPermissionEnum } from "./models/enums/ap-permission.enum";
@@ -45,4 +46,25 @@ export class AccessPolicySelectorService {
return false;
}
+
+ isAccessRemoval(current: ApItemViewType[], selected: ApItemValueType[]): boolean {
+ if (current?.length === 0) {
+ return false;
+ }
+
+ if (selected?.length === 0) {
+ return true;
+ }
+
+ return this.isAnyCurrentIdNotInSelectedIds(current, selected);
+ }
+
+ private isAnyCurrentIdNotInSelectedIds(
+ current: ApItemViewType[],
+ selected: ApItemValueType[],
+ ): boolean {
+ const currentIds = current.map((x) => x.id);
+ const selectedIds = selected.map((x) => x.id);
+ return !currentIds.every((id) => selectedIds.includes(id));
+ }
}
diff --git a/bitwarden_license/bit-web/src/app/secrets-manager/shared/access-policies/access-policy-selector/models/ap-item-value.type.ts b/bitwarden_license/bit-web/src/app/secrets-manager/shared/access-policies/access-policy-selector/models/ap-item-value.type.ts
index 2e6180a97e..362f3c524a 100644
--- a/bitwarden_license/bit-web/src/app/secrets-manager/shared/access-policies/access-policy-selector/models/ap-item-value.type.ts
+++ b/bitwarden_license/bit-web/src/app/secrets-manager/shared/access-policies/access-policy-selector/models/ap-item-value.type.ts
@@ -2,6 +2,9 @@ import {
ProjectPeopleAccessPoliciesView,
UserProjectAccessPolicyView,
GroupProjectAccessPolicyView,
+ ServiceAccountPeopleAccessPoliciesView,
+ UserServiceAccountAccessPolicyView,
+ GroupServiceAccountAccessPolicyView,
} from "../../../../models/view/access-policy.view";
import { ApItemEnum } from "./enums/ap-item.enum";
@@ -43,3 +46,33 @@ export function convertToProjectPeopleAccessPoliciesView(
});
return view;
}
+
+export function convertToServiceAccountPeopleAccessPoliciesView(
+ serviceAccountId: string,
+ selectedPolicyValues: ApItemValueType[],
+): ServiceAccountPeopleAccessPoliciesView {
+ const view = new ServiceAccountPeopleAccessPoliciesView();
+ view.userAccessPolicies = selectedPolicyValues
+ .filter((x) => x.type == ApItemEnum.User)
+ .map((filtered) => {
+ const policyView = new UserServiceAccountAccessPolicyView();
+ policyView.grantedServiceAccountId = serviceAccountId;
+ policyView.organizationUserId = filtered.id;
+ policyView.read = ApPermissionEnumUtil.toRead(filtered.permission);
+ policyView.write = ApPermissionEnumUtil.toWrite(filtered.permission);
+ policyView.currentUser = filtered.currentUser;
+ return policyView;
+ });
+
+ view.groupAccessPolicies = selectedPolicyValues
+ .filter((x) => x.type == ApItemEnum.Group)
+ .map((filtered) => {
+ const policyView = new GroupServiceAccountAccessPolicyView();
+ policyView.grantedServiceAccountId = serviceAccountId;
+ policyView.groupId = filtered.id;
+ policyView.read = ApPermissionEnumUtil.toRead(filtered.permission);
+ policyView.write = ApPermissionEnumUtil.toWrite(filtered.permission);
+ return policyView;
+ });
+ return view;
+}
diff --git a/bitwarden_license/bit-web/src/app/secrets-manager/shared/access-policies/access-policy-selector/models/ap-item-view.type.ts b/bitwarden_license/bit-web/src/app/secrets-manager/shared/access-policies/access-policy-selector/models/ap-item-view.type.ts
index e0d87c0d85..1f494b8fbf 100644
--- a/bitwarden_license/bit-web/src/app/secrets-manager/shared/access-policies/access-policy-selector/models/ap-item-view.type.ts
+++ b/bitwarden_license/bit-web/src/app/secrets-manager/shared/access-policies/access-policy-selector/models/ap-item-view.type.ts
@@ -1,7 +1,10 @@
import { Utils } from "@bitwarden/common/platform/misc/utils";
import { SelectItemView } from "@bitwarden/components";
-import { ProjectPeopleAccessPoliciesView } from "../../../../models/view/access-policy.view";
+import {
+ ProjectPeopleAccessPoliciesView,
+ ServiceAccountPeopleAccessPoliciesView,
+} from "../../../../models/view/access-policy.view";
import { PotentialGranteeView } from "../../../../models/view/potential-grantee.view";
import { ApItemEnum, ApItemEnumUtil } from "./enums/ap-item.enum";
@@ -29,7 +32,7 @@ export type ApItemViewType = SelectItemView & {
);
export function convertToAccessPolicyItemViews(
- value: ProjectPeopleAccessPoliciesView,
+ value: ProjectPeopleAccessPoliciesView | ServiceAccountPeopleAccessPoliciesView,
): ApItemViewType[] {
const accessPolicies: ApItemViewType[] = [];
diff --git a/bitwarden_license/bit-web/src/app/secrets-manager/shared/access-policies/access-policy.service.ts b/bitwarden_license/bit-web/src/app/secrets-manager/shared/access-policies/access-policy.service.ts
index 9fc424c4f4..05b95e127d 100644
--- a/bitwarden_license/bit-web/src/app/secrets-manager/shared/access-policies/access-policy.service.ts
+++ b/bitwarden_license/bit-web/src/app/secrets-manager/shared/access-policies/access-policy.service.ts
@@ -2,7 +2,6 @@ import { Injectable } from "@angular/core";
import { Subject } from "rxjs";
import { ApiService } from "@bitwarden/common/abstractions/api.service";
-import { OrganizationService } from "@bitwarden/common/admin-console/abstractions/organization/organization.service.abstraction";
import { ListResponse } from "@bitwarden/common/models/response/list.response";
import { CryptoService } from "@bitwarden/common/platform/abstractions/crypto.service";
import { EncryptService } from "@bitwarden/common/platform/abstractions/encrypt.service";
@@ -15,18 +14,16 @@ import {
GroupServiceAccountAccessPolicyView,
ProjectAccessPoliciesView,
ProjectPeopleAccessPoliciesView,
- ServiceAccountAccessPoliciesView,
ServiceAccountProjectAccessPolicyView,
UserProjectAccessPolicyView,
UserServiceAccountAccessPolicyView,
+ ServiceAccountPeopleAccessPoliciesView,
} from "../../models/view/access-policy.view";
import { PotentialGranteeView } from "../../models/view/potential-grantee.view";
import { AccessPoliciesCreateRequest } from "../../shared/access-policies/models/requests/access-policies-create.request";
import { PeopleAccessPoliciesRequest } from "../../shared/access-policies/models/requests/people-access-policies.request";
import { ProjectAccessPoliciesResponse } from "../../shared/access-policies/models/responses/project-access-policies.response";
-import { ServiceAccountAccessPoliciesResponse } from "../../shared/access-policies/models/responses/service-accounts-access-policies.response";
-import { AccessSelectorRowView } from "./access-selector.component";
import { AccessPolicyUpdateRequest } from "./models/requests/access-policy-update.request";
import { AccessPolicyRequest } from "./models/requests/access-policy.request";
import { GrantedPolicyRequest } from "./models/requests/granted-policy.request";
@@ -39,13 +36,13 @@ import {
} from "./models/responses/access-policy.response";
import { PotentialGranteeResponse } from "./models/responses/potential-grantee.response";
import { ProjectPeopleAccessPoliciesResponse } from "./models/responses/project-people-access-policies.response";
+import { ServiceAccountPeopleAccessPoliciesResponse } from "./models/responses/service-account-people-access-policies.response";
@Injectable({
providedIn: "root",
})
export class AccessPolicyService {
private _projectAccessPolicyChanges$ = new Subject();
- private _serviceAccountAccessPolicyChanges$ = new Subject();
private _serviceAccountGrantedPolicyChanges$ = new Subject<
ServiceAccountProjectAccessPolicyView[]
>();
@@ -55,12 +52,6 @@ export class AccessPolicyService {
*/
readonly projectAccessPolicyChanges$ = this._projectAccessPolicyChanges$.asObservable();
- /**
- * Emits when a service account access policy is created or deleted.
- */
- readonly serviceAccountAccessPolicyChanges$ =
- this._serviceAccountAccessPolicyChanges$.asObservable();
-
/**
* Emits when a service account granted policy is created or deleted.
*/
@@ -69,7 +60,6 @@ export class AccessPolicyService {
constructor(
private cryptoService: CryptoService,
- private organizationService: OrganizationService,
protected apiService: ApiService,
protected encryptService: EncryptService,
) {}
@@ -78,10 +68,6 @@ export class AccessPolicyService {
this._projectAccessPolicyChanges$.next(null);
}
- refreshServiceAccountAccessPolicyChanges() {
- this._serviceAccountAccessPolicyChanges$.next(null);
- }
-
async getGrantedPolicies(
serviceAccountId: string,
organizationId: string,
@@ -167,19 +153,35 @@ export class AccessPolicyService {
return this.createProjectPeopleAccessPoliciesView(results);
}
- async getServiceAccountAccessPolicies(
+ async getServiceAccountPeopleAccessPolicies(
serviceAccountId: string,
- ): Promise {
+ ): Promise {
const r = await this.apiService.send(
"GET",
- "/service-accounts/" + serviceAccountId + "/access-policies",
+ "/service-accounts/" + serviceAccountId + "/access-policies/people",
null,
true,
true,
);
- const results = new ServiceAccountAccessPoliciesResponse(r);
- return await this.createServiceAccountAccessPoliciesView(results);
+ const results = new ServiceAccountPeopleAccessPoliciesResponse(r);
+ return this.createServiceAccountPeopleAccessPoliciesView(results);
+ }
+
+ async putServiceAccountPeopleAccessPolicies(
+ serviceAccountId: string,
+ peoplePoliciesView: ServiceAccountPeopleAccessPoliciesView,
+ ) {
+ const request = this.getPeopleAccessPoliciesRequest(peoplePoliciesView);
+ const r = await this.apiService.send(
+ "PUT",
+ "/service-accounts/" + serviceAccountId + "/access-policies/people",
+ request,
+ true,
+ true,
+ );
+ const results = new ServiceAccountPeopleAccessPoliciesResponse(r);
+ return this.createServiceAccountPeopleAccessPoliciesView(results);
}
async createProjectAccessPolicies(
@@ -201,30 +203,9 @@ export class AccessPolicyService {
return view;
}
- async createServiceAccountAccessPolicies(
- serviceAccountId: string,
- serviceAccountAccessPoliciesView: ServiceAccountAccessPoliciesView,
- ): Promise {
- const request = this.getServiceAccountAccessPoliciesCreateRequest(
- serviceAccountAccessPoliciesView,
- );
- const r = await this.apiService.send(
- "POST",
- "/service-accounts/" + serviceAccountId + "/access-policies",
- request,
- true,
- true,
- );
- const results = new ServiceAccountAccessPoliciesResponse(r);
- const view = await this.createServiceAccountAccessPoliciesView(results);
- this._serviceAccountAccessPolicyChanges$.next(view);
- return view;
- }
-
async deleteAccessPolicy(accessPolicyId: string): Promise {
await this.apiService.send("DELETE", "/access-policies/" + accessPolicyId, null, true, false);
this._projectAccessPolicyChanges$.next(null);
- this._serviceAccountAccessPolicyChanges$.next(null);
this._serviceAccountGrantedPolicyChanges$.next(null);
}
@@ -241,36 +222,6 @@ export class AccessPolicyService {
);
}
- async needToShowAccessRemovalWarning(
- organizationId: string,
- policy: AccessSelectorRowView,
- currentPolicies: AccessSelectorRowView[],
- ): Promise {
- const organization = this.organizationService.get(organizationId);
- if (organization.isOwner || organization.isAdmin) {
- return false;
- }
- const currentUserId = organization.userId;
- const readWriteGroupPolicies = currentPolicies
- .filter((x) => x.accessPolicyId != policy.accessPolicyId)
- .filter((x) => x.currentUserInGroup && x.read && x.write).length;
- const readWriteUserPolicies = currentPolicies
- .filter((x) => x.accessPolicyId != policy.accessPolicyId)
- .filter((x) => x.userId == currentUserId && x.read && x.write).length;
-
- if (policy.type === "user" && policy.userId == currentUserId && readWriteGroupPolicies == 0) {
- return true;
- } else if (
- policy.type === "group" &&
- policy.currentUserInGroup &&
- readWriteUserPolicies == 0 &&
- readWriteGroupPolicies == 0
- ) {
- return true;
- }
- return false;
- }
-
private async createProjectAccessPoliciesView(
organizationId: string,
projectAccessPoliciesResponse: ProjectAccessPoliciesResponse,
@@ -306,6 +257,20 @@ export class AccessPolicyService {
return view;
}
+ private createServiceAccountPeopleAccessPoliciesView(
+ response: ServiceAccountPeopleAccessPoliciesResponse,
+ ): ServiceAccountPeopleAccessPoliciesView {
+ const view = new ServiceAccountPeopleAccessPoliciesView();
+
+ view.userAccessPolicies = response.userAccessPolicies.map((ap) => {
+ return this.createUserServiceAccountAccessPolicyView(ap);
+ });
+ view.groupAccessPolicies = response.groupAccessPolicies.map((ap) => {
+ return this.createGroupServiceAccountAccessPolicyView(ap);
+ });
+ return view;
+ }
+
private getAccessPoliciesCreateRequest(
projectAccessPoliciesView: ProjectAccessPoliciesView,
): AccessPoliciesCreateRequest {
@@ -337,24 +302,20 @@ export class AccessPolicyService {
}
private getPeopleAccessPoliciesRequest(
- projectPeopleAccessPoliciesView: ProjectPeopleAccessPoliciesView,
+ view: ProjectPeopleAccessPoliciesView | ServiceAccountPeopleAccessPoliciesView,
): PeopleAccessPoliciesRequest {
const request = new PeopleAccessPoliciesRequest();
- if (projectPeopleAccessPoliciesView.userAccessPolicies?.length > 0) {
- request.userAccessPolicyRequests = projectPeopleAccessPoliciesView.userAccessPolicies.map(
- (ap) => {
- return this.getAccessPolicyRequest(ap.organizationUserId, ap);
- },
- );
+ if (view.userAccessPolicies?.length > 0) {
+ request.userAccessPolicyRequests = view.userAccessPolicies.map((ap) => {
+ return this.getAccessPolicyRequest(ap.organizationUserId, ap);
+ });
}
- if (projectPeopleAccessPoliciesView.groupAccessPolicies?.length > 0) {
- request.groupAccessPolicyRequests = projectPeopleAccessPoliciesView.groupAccessPolicies.map(
- (ap) => {
- return this.getAccessPolicyRequest(ap.groupId, ap);
- },
- );
+ if (view.groupAccessPolicies?.length > 0) {
+ request.groupAccessPolicyRequests = view.groupAccessPolicies.map((ap) => {
+ return this.getAccessPolicyRequest(ap.groupId, ap);
+ });
}
return request;
@@ -399,50 +360,15 @@ export class AccessPolicyService {
organizationKey,
)
: null,
- serviceAccountName: await this.encryptService.decryptToUtf8(
- new EncString(response.serviceAccountName),
- organizationKey,
- ),
+ serviceAccountName: response.serviceAccountName
+ ? await this.encryptService.decryptToUtf8(
+ new EncString(response.serviceAccountName),
+ organizationKey,
+ )
+ : null,
};
}
- private getServiceAccountAccessPoliciesCreateRequest(
- serviceAccountAccessPoliciesView: ServiceAccountAccessPoliciesView,
- ): AccessPoliciesCreateRequest {
- const createRequest = new AccessPoliciesCreateRequest();
-
- if (serviceAccountAccessPoliciesView.userAccessPolicies?.length > 0) {
- createRequest.userAccessPolicyRequests =
- serviceAccountAccessPoliciesView.userAccessPolicies.map((ap) => {
- return this.getAccessPolicyRequest(ap.organizationUserId, ap);
- });
- }
-
- if (serviceAccountAccessPoliciesView.groupAccessPolicies?.length > 0) {
- createRequest.groupAccessPolicyRequests =
- serviceAccountAccessPoliciesView.groupAccessPolicies.map((ap) => {
- return this.getAccessPolicyRequest(ap.groupId, ap);
- });
- }
-
- return createRequest;
- }
-
- private async createServiceAccountAccessPoliciesView(
- serviceAccountAccessPoliciesResponse: ServiceAccountAccessPoliciesResponse,
- ): Promise {
- const view = new ServiceAccountAccessPoliciesView();
- view.userAccessPolicies = serviceAccountAccessPoliciesResponse.userAccessPolicies.map((ap) => {
- return this.createUserServiceAccountAccessPolicyView(ap);
- });
- view.groupAccessPolicies = serviceAccountAccessPoliciesResponse.groupAccessPolicies.map(
- (ap) => {
- return this.createGroupServiceAccountAccessPolicyView(ap);
- },
- );
- return view;
- }
-
private createUserServiceAccountAccessPolicyView(
response: UserServiceAccountAccessPolicyResponse,
): UserServiceAccountAccessPolicyView {
@@ -452,6 +378,7 @@ export class AccessPolicyService {
organizationUserId: response.organizationUserId,
organizationUserName: response.organizationUserName,
userId: response.userId,
+ currentUser: response.currentUser,
};
}
@@ -555,7 +482,9 @@ export class AccessPolicyService {
view.currentUserInGroup = r.currentUserInGroup;
if (r.type === "serviceAccount" || r.type === "project") {
- view.name = await this.encryptService.decryptToUtf8(new EncString(r.name), orgKey);
+ view.name = r.name
+ ? await this.encryptService.decryptToUtf8(new EncString(r.name), orgKey)
+ : null;
} else {
view.name = r.name;
}
diff --git a/bitwarden_license/bit-web/src/app/secrets-manager/shared/access-policies/dialogs/access-removal-dialog.component.html b/bitwarden_license/bit-web/src/app/secrets-manager/shared/access-policies/dialogs/access-removal-dialog.component.html
deleted file mode 100644
index 66ca0ce72f..0000000000
--- a/bitwarden_license/bit-web/src/app/secrets-manager/shared/access-policies/dialogs/access-removal-dialog.component.html
+++ /dev/null
@@ -1,14 +0,0 @@
-
- {{ data.title | i18n }}
-
- {{ data.message | i18n }}
-
-
-
-
-
-
diff --git a/bitwarden_license/bit-web/src/app/secrets-manager/shared/access-policies/dialogs/access-removal-dialog.component.ts b/bitwarden_license/bit-web/src/app/secrets-manager/shared/access-policies/dialogs/access-removal-dialog.component.ts
deleted file mode 100644
index d6464421f1..0000000000
--- a/bitwarden_license/bit-web/src/app/secrets-manager/shared/access-policies/dialogs/access-removal-dialog.component.ts
+++ /dev/null
@@ -1,69 +0,0 @@
-import { DialogRef, DIALOG_DATA } from "@angular/cdk/dialog";
-import { Component, Inject, OnInit } from "@angular/core";
-import { Router } from "@angular/router";
-
-import { AccessPolicyService } from "../access-policy.service";
-import { AccessSelectorComponent, AccessSelectorRowView } from "../access-selector.component";
-
-export interface AccessRemovalDetails {
- title: string;
- message: string;
- operation: "update" | "delete";
- type: "project" | "service-account";
- returnRoute: string[];
- policy: AccessSelectorRowView;
-}
-
-@Component({
- templateUrl: "./access-removal-dialog.component.html",
-})
-export class AccessRemovalDialogComponent implements OnInit {
- constructor(
- public dialogRef: DialogRef,
- private router: Router,
- private accessPolicyService: AccessPolicyService,
- @Inject(DIALOG_DATA) public data: AccessRemovalDetails,
- ) {}
-
- ngOnInit(): void {
- // TODO remove null checks once strictNullChecks in TypeScript is turned on.
- if (
- !this.data.message ||
- !this.data.title ||
- !this.data.operation ||
- !this.data.returnRoute ||
- !this.data.policy
- ) {
- this.dialogRef.close();
- throw new Error(
- "The access removal dialog was not called with the appropriate operation values.",
- );
- }
- }
-
- removeAccess = async () => {
- await this.router.navigate(this.data.returnRoute);
- if (this.data.operation === "delete") {
- await this.accessPolicyService.deleteAccessPolicy(this.data.policy.accessPolicyId);
- } else if (this.data.operation == "update") {
- await this.accessPolicyService.updateAccessPolicy(
- AccessSelectorComponent.getBaseAccessPolicyView(this.data.policy),
- );
- this.refreshPolicyChanges();
- }
- this.dialogRef.close();
- };
-
- cancel = () => {
- this.refreshPolicyChanges();
- this.dialogRef.close();
- };
-
- private refreshPolicyChanges() {
- if (this.data.type == "project") {
- this.accessPolicyService.refreshProjectAccessPolicyChanges();
- } else if (this.data.type == "service-account") {
- this.accessPolicyService.refreshServiceAccountAccessPolicyChanges();
- }
- }
-}
diff --git a/bitwarden_license/bit-web/src/app/secrets-manager/shared/access-policies/models/responses/access-policy.response.ts b/bitwarden_license/bit-web/src/app/secrets-manager/shared/access-policies/models/responses/access-policy.response.ts
index 9aaa57a722..ef076f9b59 100644
--- a/bitwarden_license/bit-web/src/app/secrets-manager/shared/access-policies/models/responses/access-policy.response.ts
+++ b/bitwarden_license/bit-web/src/app/secrets-manager/shared/access-policies/models/responses/access-policy.response.ts
@@ -39,6 +39,7 @@ export class UserServiceAccountAccessPolicyResponse extends BaseAccessPolicyResp
organizationUserName: string;
grantedServiceAccountId: string;
userId: string;
+ currentUser: boolean;
constructor(response: any) {
super(response);
@@ -46,6 +47,7 @@ export class UserServiceAccountAccessPolicyResponse extends BaseAccessPolicyResp
this.organizationUserName = this.getResponseProperty("OrganizationUserName");
this.grantedServiceAccountId = this.getResponseProperty("GrantedServiceAccountId");
this.userId = this.getResponseProperty("UserId");
+ this.currentUser = this.getResponseProperty("CurrentUser");
}
}
diff --git a/bitwarden_license/bit-web/src/app/secrets-manager/shared/access-policies/models/responses/service-accounts-access-policies.response.ts b/bitwarden_license/bit-web/src/app/secrets-manager/shared/access-policies/models/responses/service-account-people-access-policies.response.ts
similarity index 91%
rename from bitwarden_license/bit-web/src/app/secrets-manager/shared/access-policies/models/responses/service-accounts-access-policies.response.ts
rename to bitwarden_license/bit-web/src/app/secrets-manager/shared/access-policies/models/responses/service-account-people-access-policies.response.ts
index a4d1cfc4c3..ca134d9012 100644
--- a/bitwarden_license/bit-web/src/app/secrets-manager/shared/access-policies/models/responses/service-accounts-access-policies.response.ts
+++ b/bitwarden_license/bit-web/src/app/secrets-manager/shared/access-policies/models/responses/service-account-people-access-policies.response.ts
@@ -5,7 +5,7 @@ import {
UserServiceAccountAccessPolicyResponse,
} from "./access-policy.response";
-export class ServiceAccountAccessPoliciesResponse extends BaseResponse {
+export class ServiceAccountPeopleAccessPoliciesResponse extends BaseResponse {
userAccessPolicies: UserServiceAccountAccessPolicyResponse[];
groupAccessPolicies: GroupServiceAccountAccessPolicyResponse[];
diff --git a/bitwarden_license/bit-web/src/app/secrets-manager/shared/sm-shared.module.ts b/bitwarden_license/bit-web/src/app/secrets-manager/shared/sm-shared.module.ts
index f9b8eed298..cf312f4a2f 100644
--- a/bitwarden_license/bit-web/src/app/secrets-manager/shared/sm-shared.module.ts
+++ b/bitwarden_license/bit-web/src/app/secrets-manager/shared/sm-shared.module.ts
@@ -13,7 +13,6 @@ import { SharedModule } from "@bitwarden/web-vault/app/shared";
import { AccessPolicySelectorComponent } from "./access-policies/access-policy-selector/access-policy-selector.component";
import { AccessSelectorComponent } from "./access-policies/access-selector.component";
-import { AccessRemovalDialogComponent } from "./access-policies/dialogs/access-removal-dialog.component";
import { BulkConfirmationDialogComponent } from "./dialogs/bulk-confirmation-dialog.component";
import { BulkStatusDialogComponent } from "./dialogs/bulk-status-dialog.component";
import { HeaderComponent } from "./header.component";
@@ -36,7 +35,6 @@ import { SecretsListComponent } from "./secrets-list.component";
exports: [
SharedModule,
NoItemsModule,
- AccessRemovalDialogComponent,
AccessSelectorComponent,
AccessPolicySelectorComponent,
BulkStatusDialogComponent,
@@ -50,7 +48,6 @@ import { SecretsListComponent } from "./secrets-list.component";
SharedModule,
],
declarations: [
- AccessRemovalDialogComponent,
BulkStatusDialogComponent,
BulkConfirmationDialogComponent,
HeaderComponent,