1
0
mirror of https://github.com/bitwarden/browser.git synced 2024-12-22 16:29:09 +01:00

[SM-1030] Remove access selector (#8909)

* remove access selector
This commit is contained in:
Thomas Avery 2024-05-06 14:56:24 -05:00 committed by GitHub
parent 6c21223466
commit cf74870779
No known key found for this signature in database
GPG Key ID: B5690EEEBB952194
18 changed files with 103 additions and 541 deletions

View File

@ -42,32 +42,3 @@ export class ServiceAccountProjectAccessPolicyView extends BaseAccessPolicyView
grantedProjectId: string; grantedProjectId: string;
grantedProjectName: string; grantedProjectName: string;
} }
export class ProjectAccessPoliciesView {
userAccessPolicies: UserProjectAccessPolicyView[];
groupAccessPolicies: GroupProjectAccessPolicyView[];
serviceAccountAccessPolicies: ServiceAccountProjectAccessPolicyView[];
}
export class ProjectPeopleAccessPoliciesView {
userAccessPolicies: UserProjectAccessPolicyView[];
groupAccessPolicies: GroupProjectAccessPolicyView[];
}
export class ServiceAccountPeopleAccessPoliciesView {
userAccessPolicies: UserServiceAccountAccessPolicyView[];
groupAccessPolicies: GroupServiceAccountAccessPolicyView[];
}
export class ServiceAccountProjectPolicyPermissionDetailsView {
accessPolicy: ServiceAccountProjectAccessPolicyView;
hasPermission: boolean;
}
export class ServiceAccountGrantedPoliciesView {
grantedProjectPolicies: ServiceAccountProjectPolicyPermissionDetailsView[];
}
export class ProjectServiceAccountsAccessPoliciesView {
serviceAccountAccessPolicies: ServiceAccountProjectAccessPolicyView[];
}

View File

@ -0,0 +1,6 @@
import { GroupProjectAccessPolicyView, UserProjectAccessPolicyView } from "./access-policy.view";
export class ProjectPeopleAccessPoliciesView {
userAccessPolicies: UserProjectAccessPolicyView[];
groupAccessPolicies: GroupProjectAccessPolicyView[];
}

View File

@ -0,0 +1,5 @@
import { ServiceAccountProjectAccessPolicyView } from "./access-policy.view";
export class ProjectServiceAccountsAccessPoliciesView {
serviceAccountAccessPolicies: ServiceAccountProjectAccessPolicyView[];
}

View File

@ -0,0 +1,10 @@
import { ServiceAccountProjectAccessPolicyView } from "./access-policy.view";
export class ServiceAccountGrantedPoliciesView {
grantedProjectPolicies: ServiceAccountProjectPolicyPermissionDetailsView[];
}
export class ServiceAccountProjectPolicyPermissionDetailsView {
accessPolicy: ServiceAccountProjectAccessPolicyView;
hasPermission: boolean;
}

View File

@ -0,0 +1,9 @@
import {
GroupServiceAccountAccessPolicyView,
UserServiceAccountAccessPolicyView,
} from "./access-policy.view";
export class ServiceAccountPeopleAccessPoliciesView {
userAccessPolicies: UserServiceAccountAccessPolicyView[];
groupAccessPolicies: GroupServiceAccountAccessPolicyView[];
}

View File

@ -7,7 +7,7 @@ import { I18nService } from "@bitwarden/common/platform/abstractions/i18n.servic
import { PlatformUtilsService } from "@bitwarden/common/platform/abstractions/platform-utils.service"; import { PlatformUtilsService } from "@bitwarden/common/platform/abstractions/platform-utils.service";
import { ValidationService } from "@bitwarden/common/platform/abstractions/validation.service"; import { ValidationService } from "@bitwarden/common/platform/abstractions/validation.service";
import { ProjectServiceAccountsAccessPoliciesView } from "../../models/view/access-policy.view"; import { ProjectServiceAccountsAccessPoliciesView } from "../../models/view/access-policies/project-service-accounts-access-policies.view";
import { import {
ApItemValueType, ApItemValueType,
convertToProjectServiceAccountsAccessPoliciesView, convertToProjectServiceAccountsAccessPoliciesView,

View File

@ -6,7 +6,6 @@ import { OrganizationService } from "@bitwarden/common/admin-console/abstraction
import { DialogService } from "@bitwarden/components"; import { DialogService } from "@bitwarden/components";
import { ProjectListView } from "../../models/view/project-list.view"; import { ProjectListView } from "../../models/view/project-list.view";
import { AccessPolicyService } from "../../shared/access-policies/access-policy.service";
import { import {
BulkConfirmationDetails, BulkConfirmationDetails,
BulkConfirmationDialogComponent, BulkConfirmationDialogComponent,
@ -38,7 +37,6 @@ export class ProjectsComponent implements OnInit {
constructor( constructor(
private route: ActivatedRoute, private route: ActivatedRoute,
private projectService: ProjectService, private projectService: ProjectService,
private accessPolicyService: AccessPolicyService,
private dialogService: DialogService, private dialogService: DialogService,
private organizationService: OrganizationService, private organizationService: OrganizationService,
) {} ) {}
@ -47,7 +45,6 @@ export class ProjectsComponent implements OnInit {
this.projects$ = combineLatest([ this.projects$ = combineLatest([
this.route.params, this.route.params,
this.projectService.project$.pipe(startWith(null)), this.projectService.project$.pipe(startWith(null)),
this.accessPolicyService.projectAccessPolicyChanges$.pipe(startWith(null)),
]).pipe( ]).pipe(
switchMap(async ([params]) => { switchMap(async ([params]) => {
this.organizationId = params.organizationId; this.organizationId = params.organizationId;

View File

@ -7,7 +7,7 @@ import { I18nService } from "@bitwarden/common/platform/abstractions/i18n.servic
import { PlatformUtilsService } from "@bitwarden/common/platform/abstractions/platform-utils.service"; import { PlatformUtilsService } from "@bitwarden/common/platform/abstractions/platform-utils.service";
import { ValidationService } from "@bitwarden/common/platform/abstractions/validation.service"; import { ValidationService } from "@bitwarden/common/platform/abstractions/validation.service";
import { ServiceAccountGrantedPoliciesView } from "../../models/view/access-policy.view"; import { ServiceAccountGrantedPoliciesView } from "../../models/view/access-policies/service-account-granted-policies.view";
import { import {
ApItemValueType, ApItemValueType,
convertToServiceAccountGrantedPoliciesView, convertToServiceAccountGrantedPoliciesView,

View File

@ -1,15 +1,17 @@
import { import {
ProjectPeopleAccessPoliciesView,
UserProjectAccessPolicyView, UserProjectAccessPolicyView,
GroupProjectAccessPolicyView, GroupProjectAccessPolicyView,
ServiceAccountPeopleAccessPoliciesView,
UserServiceAccountAccessPolicyView, UserServiceAccountAccessPolicyView,
GroupServiceAccountAccessPolicyView, GroupServiceAccountAccessPolicyView,
ServiceAccountProjectAccessPolicyView,
} from "../../../../models/view/access-policies/access-policy.view";
import { ProjectPeopleAccessPoliciesView } from "../../../../models/view/access-policies/project-people-access-policies.view";
import { ProjectServiceAccountsAccessPoliciesView } from "../../../../models/view/access-policies/project-service-accounts-access-policies.view";
import {
ServiceAccountGrantedPoliciesView, ServiceAccountGrantedPoliciesView,
ServiceAccountProjectPolicyPermissionDetailsView, ServiceAccountProjectPolicyPermissionDetailsView,
ServiceAccountProjectAccessPolicyView, } from "../../../../models/view/access-policies/service-account-granted-policies.view";
ProjectServiceAccountsAccessPoliciesView, import { ServiceAccountPeopleAccessPoliciesView } from "../../../../models/view/access-policies/service-account-people-access-policies.view";
} from "../../../../models/view/access-policy.view";
import { ApItemEnum } from "./enums/ap-item.enum"; import { ApItemEnum } from "./enums/ap-item.enum";
import { ApPermissionEnum, ApPermissionEnumUtil } from "./enums/ap-permission.enum"; import { ApPermissionEnum, ApPermissionEnumUtil } from "./enums/ap-permission.enum";

View File

@ -1,13 +1,11 @@
import { Utils } from "@bitwarden/common/platform/misc/utils"; import { Utils } from "@bitwarden/common/platform/misc/utils";
import { SelectItemView } from "@bitwarden/components"; import { SelectItemView } from "@bitwarden/components";
import { import { PotentialGranteeView } from "../../../../models/view/access-policies/potential-grantee.view";
ProjectPeopleAccessPoliciesView, import { ProjectPeopleAccessPoliciesView } from "../../../../models/view/access-policies/project-people-access-policies.view";
ServiceAccountGrantedPoliciesView, import { ProjectServiceAccountsAccessPoliciesView } from "../../../../models/view/access-policies/project-service-accounts-access-policies.view";
ProjectServiceAccountsAccessPoliciesView, import { ServiceAccountGrantedPoliciesView } from "../../../../models/view/access-policies/service-account-granted-policies.view";
ServiceAccountPeopleAccessPoliciesView, import { ServiceAccountPeopleAccessPoliciesView } from "../../../../models/view/access-policies/service-account-people-access-policies.view";
} from "../../../../models/view/access-policy.view";
import { PotentialGranteeView } from "../../../../models/view/potential-grantee.view";
import { ApItemEnum, ApItemEnumUtil } from "./enums/ap-item.enum"; import { ApItemEnum, ApItemEnumUtil } from "./enums/ap-item.enum";
import { ApPermissionEnum, ApPermissionEnumUtil } from "./enums/ap-permission.enum"; import { ApPermissionEnum, ApPermissionEnumUtil } from "./enums/ap-permission.enum";

View File

@ -1,5 +1,4 @@
import { Injectable } from "@angular/core"; import { Injectable } from "@angular/core";
import { Subject } from "rxjs";
import { ApiService } from "@bitwarden/common/abstractions/api.service"; import { ApiService } from "@bitwarden/common/abstractions/api.service";
import { ListResponse } from "@bitwarden/common/models/response/list.response"; import { ListResponse } from "@bitwarden/common/models/response/list.response";
@ -9,26 +8,23 @@ import { EncString } from "@bitwarden/common/platform/models/domain/enc-string";
import { SymmetricCryptoKey } from "@bitwarden/common/platform/models/domain/symmetric-crypto-key"; import { SymmetricCryptoKey } from "@bitwarden/common/platform/models/domain/symmetric-crypto-key";
import { import {
BaseAccessPolicyView,
GroupProjectAccessPolicyView,
GroupServiceAccountAccessPolicyView,
ProjectAccessPoliciesView,
ProjectPeopleAccessPoliciesView,
ServiceAccountProjectAccessPolicyView,
UserProjectAccessPolicyView, UserProjectAccessPolicyView,
GroupProjectAccessPolicyView,
UserServiceAccountAccessPolicyView, UserServiceAccountAccessPolicyView,
ServiceAccountPeopleAccessPoliciesView, GroupServiceAccountAccessPolicyView,
ServiceAccountProjectAccessPolicyView,
} from "../../models/view/access-policies/access-policy.view";
import { PotentialGranteeView } from "../../models/view/access-policies/potential-grantee.view";
import { ProjectPeopleAccessPoliciesView } from "../../models/view/access-policies/project-people-access-policies.view";
import { ProjectServiceAccountsAccessPoliciesView } from "../../models/view/access-policies/project-service-accounts-access-policies.view";
import {
ServiceAccountGrantedPoliciesView, ServiceAccountGrantedPoliciesView,
ProjectServiceAccountsAccessPoliciesView,
ServiceAccountProjectPolicyPermissionDetailsView, ServiceAccountProjectPolicyPermissionDetailsView,
} from "../../models/view/access-policy.view"; } from "../../models/view/access-policies/service-account-granted-policies.view";
import { PotentialGranteeView } from "../../models/view/potential-grantee.view"; import { ServiceAccountPeopleAccessPoliciesView } from "../../models/view/access-policies/service-account-people-access-policies.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 { PeopleAccessPoliciesRequest } from "../../shared/access-policies/models/requests/people-access-policies.request";
import { ProjectAccessPoliciesResponse } from "../../shared/access-policies/models/responses/project-access-policies.response";
import { ServiceAccountGrantedPoliciesRequest } from "../access-policies/models/requests/service-account-granted-policies.request"; import { ServiceAccountGrantedPoliciesRequest } from "../access-policies/models/requests/service-account-granted-policies.request";
import { AccessPolicyUpdateRequest } from "./models/requests/access-policy-update.request";
import { AccessPolicyRequest } from "./models/requests/access-policy.request"; import { AccessPolicyRequest } from "./models/requests/access-policy.request";
import { ProjectServiceAccountsAccessPoliciesRequest } from "./models/requests/project-service-accounts-access-policies.request"; import { ProjectServiceAccountsAccessPoliciesRequest } from "./models/requests/project-service-accounts-access-policies.request";
import { import {
@ -49,39 +45,12 @@ import { ServiceAccountProjectPolicyPermissionDetailsResponse } from "./models/r
providedIn: "root", providedIn: "root",
}) })
export class AccessPolicyService { export class AccessPolicyService {
private _projectAccessPolicyChanges$ = new Subject<ProjectAccessPoliciesView>();
/**
* Emits when a project access policy is created or deleted.
*/
readonly projectAccessPolicyChanges$ = this._projectAccessPolicyChanges$.asObservable();
constructor( constructor(
private cryptoService: CryptoService, private cryptoService: CryptoService,
protected apiService: ApiService, protected apiService: ApiService,
protected encryptService: EncryptService, protected encryptService: EncryptService,
) {} ) {}
refreshProjectAccessPolicyChanges() {
this._projectAccessPolicyChanges$.next(null);
}
async getProjectAccessPolicies(
organizationId: string,
projectId: string,
): Promise<ProjectAccessPoliciesView> {
const r = await this.apiService.send(
"GET",
"/projects/" + projectId + "/access-policies",
null,
true,
true,
);
const results = new ProjectAccessPoliciesResponse(r);
return await this.createProjectAccessPoliciesView(organizationId, results);
}
async getProjectPeopleAccessPolicies( async getProjectPeopleAccessPolicies(
projectId: string, projectId: string,
): Promise<ProjectPeopleAccessPoliciesView> { ): Promise<ProjectPeopleAccessPoliciesView> {
@ -212,43 +181,6 @@ export class AccessPolicyService {
return await this.createProjectServiceAccountsAccessPoliciesView(result, organizationId); return await this.createProjectServiceAccountsAccessPoliciesView(result, organizationId);
} }
async createProjectAccessPolicies(
organizationId: string,
projectId: string,
projectAccessPoliciesView: ProjectAccessPoliciesView,
): Promise<ProjectAccessPoliciesView> {
const request = this.getAccessPoliciesCreateRequest(projectAccessPoliciesView);
const r = await this.apiService.send(
"POST",
"/projects/" + projectId + "/access-policies",
request,
true,
true,
);
const results = new ProjectAccessPoliciesResponse(r);
const view = await this.createProjectAccessPoliciesView(organizationId, results);
this._projectAccessPolicyChanges$.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);
}
async updateAccessPolicy(baseAccessPolicyView: BaseAccessPolicyView): Promise<void> {
const payload = new AccessPolicyUpdateRequest();
payload.read = baseAccessPolicyView.read;
payload.write = baseAccessPolicyView.write;
await this.apiService.send(
"PUT",
"/access-policies/" + baseAccessPolicyView.id,
payload,
true,
true,
);
}
async getPeoplePotentialGrantees(organizationId: string) { async getPeoplePotentialGrantees(organizationId: string) {
const r = await this.apiService.send( const r = await this.apiService.send(
"GET", "GET",
@ -285,11 +217,11 @@ export class AccessPolicyService {
return await this.createPotentialGranteeViews(organizationId, results.data); return await this.createPotentialGranteeViews(organizationId, results.data);
} }
protected async getOrganizationKey(organizationId: string): Promise<SymmetricCryptoKey> { private async getOrganizationKey(organizationId: string): Promise<SymmetricCryptoKey> {
return await this.cryptoService.getOrgKey(organizationId); return await this.cryptoService.getOrgKey(organizationId);
} }
protected getAccessPolicyRequest( private getAccessPolicyRequest(
granteeId: string, granteeId: string,
view: view:
| UserProjectAccessPolicyView | UserProjectAccessPolicyView
@ -305,7 +237,53 @@ export class AccessPolicyService {
return request; return request;
} }
protected createBaseAccessPolicyView( private getServiceAccountGrantedPoliciesRequest(
policies: ServiceAccountGrantedPoliciesView,
): ServiceAccountGrantedPoliciesRequest {
const request = new ServiceAccountGrantedPoliciesRequest();
request.projectGrantedPolicyRequests = policies.grantedProjectPolicies.map((detailView) => ({
grantedId: detailView.accessPolicy.grantedProjectId,
read: detailView.accessPolicy.read,
write: detailView.accessPolicy.write,
}));
return request;
}
private getProjectServiceAccountsAccessPoliciesRequest(
policies: ProjectServiceAccountsAccessPoliciesView,
): ProjectServiceAccountsAccessPoliciesRequest {
const request = new ProjectServiceAccountsAccessPoliciesRequest();
request.serviceAccountAccessPolicyRequests = policies.serviceAccountAccessPolicies.map((ap) => {
return this.getAccessPolicyRequest(ap.serviceAccountId, ap);
});
return request;
}
private getPeopleAccessPoliciesRequest(
view: ProjectPeopleAccessPoliciesView | ServiceAccountPeopleAccessPoliciesView,
): PeopleAccessPoliciesRequest {
const request = new PeopleAccessPoliciesRequest();
if (view.userAccessPolicies?.length > 0) {
request.userAccessPolicyRequests = view.userAccessPolicies.map((ap) => {
return this.getAccessPolicyRequest(ap.organizationUserId, ap);
});
}
if (view.groupAccessPolicies?.length > 0) {
request.groupAccessPolicyRequests = view.groupAccessPolicies.map((ap) => {
return this.getAccessPolicyRequest(ap.groupId, ap);
});
}
return request;
}
private createBaseAccessPolicyView(
response: response:
| UserProjectAccessPolicyResponse | UserProjectAccessPolicyResponse
| UserServiceAccountAccessPolicyResponse | UserServiceAccountAccessPolicyResponse
@ -348,32 +326,6 @@ export class AccessPolicyService {
); );
} }
private getServiceAccountGrantedPoliciesRequest(
policies: ServiceAccountGrantedPoliciesView,
): ServiceAccountGrantedPoliciesRequest {
const request = new ServiceAccountGrantedPoliciesRequest();
request.projectGrantedPolicyRequests = policies.grantedProjectPolicies.map((detailView) => ({
grantedId: detailView.accessPolicy.grantedProjectId,
read: detailView.accessPolicy.read,
write: detailView.accessPolicy.write,
}));
return request;
}
private getProjectServiceAccountsAccessPoliciesRequest(
policies: ProjectServiceAccountsAccessPoliciesView,
): ProjectServiceAccountsAccessPoliciesRequest {
const request = new ProjectServiceAccountsAccessPoliciesRequest();
request.serviceAccountAccessPolicyRequests = policies.serviceAccountAccessPolicies.map((ap) => {
return this.getAccessPolicyRequest(ap.serviceAccountId, ap);
});
return request;
}
private async createServiceAccountGrantedPoliciesView( private async createServiceAccountGrantedPoliciesView(
response: ServiceAccountGrantedPoliciesPermissionDetailsResponse, response: ServiceAccountGrantedPoliciesPermissionDetailsResponse,
organizationId: string, organizationId: string,
@ -413,27 +365,6 @@ export class AccessPolicyService {
return view; return view;
} }
private async createProjectAccessPoliciesView(
organizationId: string,
projectAccessPoliciesResponse: ProjectAccessPoliciesResponse,
): Promise<ProjectAccessPoliciesView> {
const orgKey = await this.getOrganizationKey(organizationId);
const view = new ProjectAccessPoliciesView();
view.userAccessPolicies = projectAccessPoliciesResponse.userAccessPolicies.map((ap) => {
return this.createUserProjectAccessPolicyView(ap);
});
view.groupAccessPolicies = projectAccessPoliciesResponse.groupAccessPolicies.map((ap) => {
return this.createGroupProjectAccessPolicyView(ap);
});
view.serviceAccountAccessPolicies = await Promise.all(
projectAccessPoliciesResponse.serviceAccountAccessPolicies.map(async (ap) => {
return await this.createServiceAccountProjectAccessPolicyView(orgKey, ap);
}),
);
return view;
}
private createProjectPeopleAccessPoliciesView( private createProjectPeopleAccessPoliciesView(
peopleAccessPoliciesResponse: ProjectPeopleAccessPoliciesResponse, peopleAccessPoliciesResponse: ProjectPeopleAccessPoliciesResponse,
): ProjectPeopleAccessPoliciesView { ): ProjectPeopleAccessPoliciesView {
@ -462,56 +393,6 @@ export class AccessPolicyService {
return view; return view;
} }
private getAccessPoliciesCreateRequest(
projectAccessPoliciesView: ProjectAccessPoliciesView,
): AccessPoliciesCreateRequest {
const createRequest = new AccessPoliciesCreateRequest();
if (projectAccessPoliciesView.userAccessPolicies?.length > 0) {
createRequest.userAccessPolicyRequests = projectAccessPoliciesView.userAccessPolicies.map(
(ap) => {
return this.getAccessPolicyRequest(ap.organizationUserId, ap);
},
);
}
if (projectAccessPoliciesView.groupAccessPolicies?.length > 0) {
createRequest.groupAccessPolicyRequests = projectAccessPoliciesView.groupAccessPolicies.map(
(ap) => {
return this.getAccessPolicyRequest(ap.groupId, ap);
},
);
}
if (projectAccessPoliciesView.serviceAccountAccessPolicies?.length > 0) {
createRequest.serviceAccountAccessPolicyRequests =
projectAccessPoliciesView.serviceAccountAccessPolicies.map((ap) => {
return this.getAccessPolicyRequest(ap.serviceAccountId, ap);
});
}
return createRequest;
}
private getPeopleAccessPoliciesRequest(
view: ProjectPeopleAccessPoliciesView | ServiceAccountPeopleAccessPoliciesView,
): PeopleAccessPoliciesRequest {
const request = new PeopleAccessPoliciesRequest();
if (view.userAccessPolicies?.length > 0) {
request.userAccessPolicyRequests = view.userAccessPolicies.map((ap) => {
return this.getAccessPolicyRequest(ap.organizationUserId, ap);
});
}
if (view.groupAccessPolicies?.length > 0) {
request.groupAccessPolicyRequests = view.groupAccessPolicies.map((ap) => {
return this.getAccessPolicyRequest(ap.groupId, ap);
});
}
return request;
}
private createUserProjectAccessPolicyView( private createUserProjectAccessPolicyView(
response: UserProjectAccessPolicyResponse, response: UserProjectAccessPolicyResponse,
): UserProjectAccessPolicyView { ): UserProjectAccessPolicyView {

View File

@ -1,80 +0,0 @@
<form [formGroup]="formGroup" [bitSubmit]="submit" class="tw-mt-5">
<bit-form-field>
<bit-label>{{ label }}</bit-label>
<bit-multi-select
class="tw-mr-4 tw-w-full"
formControlName="multiSelect"
[baseItems]="selectItems$ | async"
[loading]="loading"
></bit-multi-select>
<bit-hint>{{ hint }}</bit-hint>
<button type="submit" bitButton buttonType="primary" bitFormButton>
{{ "add" | i18n }}
</button>
</bit-form-field>
</form>
<ng-container>
<bit-table *ngIf="rows$ | async as rows; else spinner">
<ng-container header>
<tr>
<th bitCell colspan="2">{{ columnTitle }}</th>
<th bitCell>{{ "permissions" | i18n }}</th>
</tr>
</ng-container>
<ng-template body>
<ng-container *ngIf="rows.length > 0; else empty">
<tr bitRow *ngFor="let row of rows">
<td bitCell class="tw-w-0 tw-pr-0">
<i class="bwi {{ row.icon }} tw-text-muted" aria-hidden="true"></i>
</td>
<td bitCell class="tw-max-w-sm tw-truncate">{{ row.name }}</td>
<td bitCell>
<bit-form-field
*ngIf="!row.static; else staticPermissions"
class="tw-mb-auto tw-inline-block tw-w-auto"
>
<select bitInput (change)="update($event.target, row)" [disabled]="row.static">
<option value="canRead" [selected]="row.read && row.write != true">
{{ "canRead" | i18n }}
</option>
<option value="canReadWrite" [selected]="row.read && row.write">
{{ "canReadWrite" | i18n }}
</option>
</select>
</bit-form-field>
<ng-template #staticPermissions>
<span *ngIf="row.read && row.write != true">{{ "canRead" | i18n }}</span>
<span *ngIf="row.read != true && row.write">{{ "canWrite" | i18n }}</span>
<span *ngIf="row.read && row.write">{{ "canReadWrite" | i18n }}</span>
</ng-template>
</td>
<td bitCell class="tw-w-0">
<button
type="button"
bitIconButton="bwi-close"
buttonType="main"
size="default"
[attr.title]="'remove' | i18n"
[attr.aria-label]="'remove' | i18n"
[bitAction]="delete(row)"
></button>
</td>
</tr>
</ng-container>
</ng-template>
</bit-table>
</ng-container>
<ng-template #empty>
<div class="tw-mt-4 tw-text-center">
{{ emptyMessage }}
</div>
</ng-template>
<ng-template #spinner>
<div class="tw-items-center tw-justify-center tw-pt-10 tw-text-center">
<i class="bwi bwi-spinner bwi-spin bwi-3x"></i>
</div>
</ng-template>

View File

@ -1,194 +0,0 @@
import { Component, EventEmitter, Input, OnInit, Output } from "@angular/core";
import { FormControl, FormGroup, Validators } from "@angular/forms";
import { ActivatedRoute } from "@angular/router";
import {
combineLatest,
firstValueFrom,
map,
Observable,
share,
Subject,
switchMap,
tap,
} from "rxjs";
import { Utils } from "@bitwarden/common/platform/misc/utils";
import { SelectItemView } from "@bitwarden/components/src/multi-select/models/select-item-view";
import { BaseAccessPolicyView } from "../../models/view/access-policy.view";
import { AccessPolicyService } from "./access-policy.service";
export type AccessSelectorRowView = {
type: "user" | "group" | "serviceAccount" | "project";
name: string;
id: string;
accessPolicyId: string;
read: boolean;
write: boolean;
icon: string;
userId?: string;
currentUserInGroup?: boolean;
static?: boolean;
};
@Component({
selector: "sm-access-selector",
templateUrl: "./access-selector.component.html",
})
export class AccessSelectorComponent implements OnInit {
static readonly userIcon = "bwi-user";
static readonly groupIcon = "bwi-family";
static readonly serviceAccountIcon = "bwi-wrench";
static readonly projectIcon = "bwi-collection";
/**
* Emits the selected items on submit.
*/
@Output() onCreateAccessPolicies = new EventEmitter<SelectItemView[]>();
@Output() onDeleteAccessPolicy = new EventEmitter<AccessSelectorRowView>();
@Output() onUpdateAccessPolicy = new EventEmitter<AccessSelectorRowView>();
@Input() label: string;
@Input() hint: string;
@Input() columnTitle: string;
@Input() emptyMessage: string;
@Input() granteeType: "people" | "serviceAccounts" | "projects";
protected rows$ = new Subject<AccessSelectorRowView[]>();
@Input() private set rows(value: AccessSelectorRowView[]) {
const sorted = value.sort((a, b) => {
if (a.icon == b.icon) {
return a.name.localeCompare(b.name);
}
if (a.icon == AccessSelectorComponent.userIcon) {
return -1;
}
return 1;
});
this.rows$.next(sorted);
}
private maxLength = 15;
protected formGroup = new FormGroup({
multiSelect: new FormControl([], [Validators.required, Validators.maxLength(this.maxLength)]),
});
protected loading = true;
protected selectItems$: Observable<SelectItemView[]> = combineLatest([
this.rows$,
this.route.params,
]).pipe(
switchMap(([rows, params]) =>
this.getPotentialGrantees(params.organizationId).then((grantees) =>
grantees
.filter((g) => !rows.some((row) => row.id === g.id))
.map((granteeView) => {
let icon: string;
let listName = granteeView.name;
let labelName = granteeView.name;
if (granteeView.type === "user") {
icon = AccessSelectorComponent.userIcon;
if (Utils.isNullOrWhitespace(granteeView.name)) {
listName = granteeView.email;
labelName = granteeView.email;
} else {
listName = `${granteeView.name} (${granteeView.email})`;
}
} else if (granteeView.type === "group") {
icon = AccessSelectorComponent.groupIcon;
} else if (granteeView.type === "serviceAccount") {
icon = AccessSelectorComponent.serviceAccountIcon;
} else if (granteeView.type === "project") {
icon = AccessSelectorComponent.projectIcon;
}
return {
icon: icon,
id: granteeView.id,
labelName: labelName,
listName: listName,
};
}),
),
),
map((selectItems) => selectItems.sort((a, b) => a.listName.localeCompare(b.listName))),
tap(() => {
this.loading = false;
this.formGroup.reset();
this.formGroup.enable();
}),
share(),
);
constructor(
private accessPolicyService: AccessPolicyService,
private route: ActivatedRoute,
) {}
ngOnInit(): void {
this.formGroup.disable();
}
submit = async () => {
this.formGroup.markAllAsTouched();
if (this.formGroup.invalid) {
return;
}
this.formGroup.disable();
this.loading = true;
this.onCreateAccessPolicies.emit(this.formGroup.value.multiSelect);
return firstValueFrom(this.selectItems$);
};
async update(target: any, row: AccessSelectorRowView): Promise<void> {
if (target.value === "canRead") {
row.read = true;
row.write = false;
} else if (target.value === "canReadWrite") {
row.read = true;
row.write = true;
}
this.onUpdateAccessPolicy.emit(row);
}
delete = (row: AccessSelectorRowView) => async () => {
this.loading = true;
this.formGroup.disable();
this.onDeleteAccessPolicy.emit(row);
return firstValueFrom(this.selectItems$);
};
private getPotentialGrantees(organizationId: string) {
switch (this.granteeType) {
case "people":
return this.accessPolicyService.getPeoplePotentialGrantees(organizationId);
case "serviceAccounts":
return this.accessPolicyService.getServiceAccountsPotentialGrantees(organizationId);
case "projects":
return this.accessPolicyService.getProjectsPotentialGrantees(organizationId);
}
}
static getAccessItemType(item: SelectItemView) {
switch (item.icon) {
case AccessSelectorComponent.userIcon:
return "user";
case AccessSelectorComponent.groupIcon:
return "group";
case AccessSelectorComponent.serviceAccountIcon:
return "serviceAccount";
case AccessSelectorComponent.projectIcon:
return "project";
}
}
static getBaseAccessPolicyView(row: AccessSelectorRowView) {
const view = new BaseAccessPolicyView();
view.id = row.accessPolicyId;
view.read = row.read;
view.write = row.write;
return view;
}
}

View File

@ -1,7 +0,0 @@
import { AccessPolicyRequest } from "./access-policy.request";
export class AccessPoliciesCreateRequest {
userAccessPolicyRequests?: AccessPolicyRequest[];
groupAccessPolicyRequests?: AccessPolicyRequest[];
serviceAccountAccessPolicyRequests?: AccessPolicyRequest[];
}

View File

@ -1,4 +0,0 @@
export class AccessPolicyUpdateRequest {
read: boolean;
write: boolean;
}

View File

@ -1,29 +0,0 @@
import { BaseResponse } from "@bitwarden/common/models/response/base.response";
import {
GroupProjectAccessPolicyResponse,
ServiceAccountProjectAccessPolicyResponse,
UserProjectAccessPolicyResponse,
} from "./access-policy.response";
export class ProjectAccessPoliciesResponse extends BaseResponse {
userAccessPolicies: UserProjectAccessPolicyResponse[];
groupAccessPolicies: GroupProjectAccessPolicyResponse[];
serviceAccountAccessPolicies: ServiceAccountProjectAccessPolicyResponse[];
constructor(response: any) {
super(response);
const userAccessPolicies = this.getResponseProperty("UserAccessPolicies");
this.userAccessPolicies = userAccessPolicies.map(
(k: any) => new UserProjectAccessPolicyResponse(k),
);
const groupAccessPolicies = this.getResponseProperty("GroupAccessPolicies");
this.groupAccessPolicies = groupAccessPolicies.map(
(k: any) => new GroupProjectAccessPolicyResponse(k),
);
const serviceAccountAccessPolicies = this.getResponseProperty("ServiceAccountAccessPolicies");
this.serviceAccountAccessPolicies = serviceAccountAccessPolicies.map(
(k: any) => new ServiceAccountProjectAccessPolicyResponse(k),
);
}
}

View File

@ -13,7 +13,6 @@ import { ProductSwitcherModule } from "@bitwarden/web-vault/app/layouts/product-
import { SharedModule } from "@bitwarden/web-vault/app/shared"; import { SharedModule } from "@bitwarden/web-vault/app/shared";
import { AccessPolicySelectorComponent } from "./access-policies/access-policy-selector/access-policy-selector.component"; import { AccessPolicySelectorComponent } from "./access-policies/access-policy-selector/access-policy-selector.component";
import { AccessSelectorComponent } from "./access-policies/access-selector.component";
import { BulkConfirmationDialogComponent } from "./dialogs/bulk-confirmation-dialog.component"; import { BulkConfirmationDialogComponent } from "./dialogs/bulk-confirmation-dialog.component";
import { BulkStatusDialogComponent } from "./dialogs/bulk-status-dialog.component"; import { BulkStatusDialogComponent } from "./dialogs/bulk-status-dialog.component";
import { NewMenuComponent } from "./new-menu.component"; import { NewMenuComponent } from "./new-menu.component";
@ -35,7 +34,6 @@ import { SecretsListComponent } from "./secrets-list.component";
], ],
exports: [ exports: [
AccessPolicySelectorComponent, AccessPolicySelectorComponent,
AccessSelectorComponent,
BulkConfirmationDialogComponent, BulkConfirmationDialogComponent,
BulkStatusDialogComponent, BulkStatusDialogComponent,
HeaderModule, HeaderModule,
@ -49,7 +47,6 @@ import { SecretsListComponent } from "./secrets-list.component";
], ],
declarations: [ declarations: [
AccessPolicySelectorComponent, AccessPolicySelectorComponent,
AccessSelectorComponent,
BulkConfirmationDialogComponent, BulkConfirmationDialogComponent,
BulkStatusDialogComponent, BulkStatusDialogComponent,
BulkStatusDialogComponent, BulkStatusDialogComponent,