mirror of
https://github.com/bitwarden/browser.git
synced 2024-12-22 16:29:09 +01:00
[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
This commit is contained in:
parent
e5b8fd4388
commit
51c5e053f7
@ -7437,5 +7437,8 @@
|
||||
},
|
||||
"collectionAccessRestricted": {
|
||||
"message": "Collection access is restricted"
|
||||
},
|
||||
"serviceAccountAccessUpdated": {
|
||||
"message": "Service account access updated"
|
||||
}
|
||||
}
|
||||
|
@ -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[];
|
||||
}
|
||||
|
@ -1,16 +1,22 @@
|
||||
<div class="tw-mt-4 tw-w-2/5">
|
||||
<p class="tw-mt-6">
|
||||
<form [formGroup]="formGroup" [bitSubmit]="submit">
|
||||
<div class="tw-w-2/5">
|
||||
<p class="tw-mt-8" *ngIf="!loading">
|
||||
{{ "serviceAccountPeopleDescription" | i18n }}
|
||||
</p>
|
||||
<sm-access-selector
|
||||
[rows]="rows$ | async"
|
||||
granteeType="people"
|
||||
<sm-access-policy-selector
|
||||
[loading]="loading"
|
||||
formControlName="accessPolicies"
|
||||
[addButtonMode]="true"
|
||||
[items]="potentialGrantees"
|
||||
[label]="'people' | i18n"
|
||||
[hint]="'projectPeopleSelectHint' | i18n"
|
||||
[columnTitle]="'name' | i18n"
|
||||
[emptyMessage]="'projectEmptyPeopleAccessPolicies' | i18n"
|
||||
(onCreateAccessPolicies)="handleCreateAccessPolicies($event)"
|
||||
(onDeleteAccessPolicy)="handleDeleteAccessPolicy($event)"
|
||||
[staticPermission]="staticPermission"
|
||||
>
|
||||
</sm-access-selector>
|
||||
</sm-access-policy-selector>
|
||||
<button bitButton buttonType="primary" bitFormButton type="submit" class="tw-mt-7">
|
||||
{{ "save" | i18n }}
|
||||
</button>
|
||||
</div>
|
||||
</form>
|
||||
|
@ -1,161 +1,92 @@
|
||||
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<void>();
|
||||
private serviceAccountId: string;
|
||||
private organizationId: string;
|
||||
private rows: AccessSelectorRowView[];
|
||||
private serviceAccountId: string;
|
||||
|
||||
protected rows$: Observable<AccessSelectorRowView[]> =
|
||||
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,
|
||||
});
|
||||
});
|
||||
|
||||
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,
|
||||
});
|
||||
});
|
||||
|
||||
return rows;
|
||||
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;
|
||||
}),
|
||||
share(),
|
||||
);
|
||||
|
||||
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,
|
||||
private potentialGrantees$ = combineLatest([this.route.params]).pipe(
|
||||
switchMap(([params]) =>
|
||||
this.accessPolicyService
|
||||
.getPeoplePotentialGrantees(params.organizationId)
|
||||
.then((grantees) => {
|
||||
return convertPotentialGranteesToApItemViewType(grantees);
|
||||
}),
|
||||
),
|
||||
);
|
||||
}
|
||||
|
||||
protected async handleDeleteAccessPolicy(policy: AccessSelectorRowView) {
|
||||
if (
|
||||
await this.accessPolicyService.needToShowAccessRemovalWarning(
|
||||
this.organizationId,
|
||||
policy,
|
||||
this.rows,
|
||||
)
|
||||
) {
|
||||
this.launchDeleteWarningDialog(policy);
|
||||
return;
|
||||
}
|
||||
protected formGroup = new FormGroup({
|
||||
accessPolicies: new FormControl([] as ApItemValueType[]),
|
||||
});
|
||||
|
||||
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);
|
||||
});
|
||||
}
|
||||
|
||||
@ -164,16 +95,133 @@ export class ServiceAccountPeopleComponent {
|
||||
this.destroy$.complete();
|
||||
}
|
||||
|
||||
private launchDeleteWarningDialog(policy: AccessSelectorRowView) {
|
||||
this.dialogService.open<unknown, AccessRemovalDetails>(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<boolean> {
|
||||
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<void> {
|
||||
if (showAccessRemovalWarning) {
|
||||
this.router.navigate(["sm", this.organizationId, "service-accounts"]);
|
||||
} else if (
|
||||
this.accessPolicySelectorService.isAccessRemoval(currentAccessPolicies, selectedPolicies)
|
||||
) {
|
||||
await this.showAccessTokenStillAvailableWarning();
|
||||
}
|
||||
}
|
||||
|
||||
private async showWarning(): Promise<boolean> {
|
||||
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<void> {
|
||||
await this.dialogService.openSimpleDialog({
|
||||
title: { key: "saPeopleWarningTitle" },
|
||||
content: { key: "saPeopleWarningMessage" },
|
||||
type: "warning",
|
||||
acceptButtonText: { key: "close" },
|
||||
cancelButtonText: null,
|
||||
});
|
||||
}
|
||||
}
|
||||
|
@ -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;
|
||||
|
@ -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<ApItemValueType> = {}) {
|
||||
};
|
||||
}
|
||||
|
||||
function createApItemViewType(options: Partial<ApItemViewType> = {}) {
|
||||
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 });
|
||||
|
@ -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));
|
||||
}
|
||||
}
|
||||
|
@ -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;
|
||||
}
|
||||
|
@ -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[] = [];
|
||||
|
||||
|
@ -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<ProjectAccessPoliciesView>();
|
||||
private _serviceAccountAccessPolicyChanges$ = new Subject<ServiceAccountAccessPoliciesView>();
|
||||
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<ServiceAccountAccessPoliciesView> {
|
||||
): Promise<ServiceAccountPeopleAccessPoliciesView> {
|
||||
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<ServiceAccountAccessPoliciesView> {
|
||||
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<void> {
|
||||
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<boolean> {
|
||||
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) => {
|
||||
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) => {
|
||||
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(
|
||||
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<ServiceAccountAccessPoliciesView> {
|
||||
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;
|
||||
}
|
||||
|
@ -1,14 +0,0 @@
|
||||
<bit-simple-dialog>
|
||||
<span bitDialogTitle>{{ data.title | i18n }}</span>
|
||||
<span bitDialogContent>
|
||||
{{ data.message | i18n }}
|
||||
</span>
|
||||
<ng-container bitDialogFooter>
|
||||
<button type="button" bitButton buttonType="danger" [bitAction]="removeAccess">
|
||||
{{ "removeAccess" | i18n }}
|
||||
</button>
|
||||
<button type="button" bitButton buttonType="secondary" [bitAction]="cancel">
|
||||
{{ "cancel" | i18n }}
|
||||
</button>
|
||||
</ng-container>
|
||||
</bit-simple-dialog>
|
@ -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();
|
||||
}
|
||||
}
|
||||
}
|
@ -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");
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -5,7 +5,7 @@ import {
|
||||
UserServiceAccountAccessPolicyResponse,
|
||||
} from "./access-policy.response";
|
||||
|
||||
export class ServiceAccountAccessPoliciesResponse extends BaseResponse {
|
||||
export class ServiceAccountPeopleAccessPoliciesResponse extends BaseResponse {
|
||||
userAccessPolicies: UserServiceAccountAccessPolicyResponse[];
|
||||
groupAccessPolicies: GroupServiceAccountAccessPolicyResponse[];
|
||||
|
@ -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,
|
||||
|
Loading…
Reference in New Issue
Block a user