mirror of
https://github.com/bitwarden/browser.git
synced 2024-12-22 16:29:09 +01:00
parent
6c21223466
commit
cf74870779
@ -42,32 +42,3 @@ export class ServiceAccountProjectAccessPolicyView extends BaseAccessPolicyView
|
||||
grantedProjectId: 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[];
|
||||
}
|
@ -0,0 +1,6 @@
|
||||
import { GroupProjectAccessPolicyView, UserProjectAccessPolicyView } from "./access-policy.view";
|
||||
|
||||
export class ProjectPeopleAccessPoliciesView {
|
||||
userAccessPolicies: UserProjectAccessPolicyView[];
|
||||
groupAccessPolicies: GroupProjectAccessPolicyView[];
|
||||
}
|
@ -0,0 +1,5 @@
|
||||
import { ServiceAccountProjectAccessPolicyView } from "./access-policy.view";
|
||||
|
||||
export class ProjectServiceAccountsAccessPoliciesView {
|
||||
serviceAccountAccessPolicies: ServiceAccountProjectAccessPolicyView[];
|
||||
}
|
@ -0,0 +1,10 @@
|
||||
import { ServiceAccountProjectAccessPolicyView } from "./access-policy.view";
|
||||
|
||||
export class ServiceAccountGrantedPoliciesView {
|
||||
grantedProjectPolicies: ServiceAccountProjectPolicyPermissionDetailsView[];
|
||||
}
|
||||
|
||||
export class ServiceAccountProjectPolicyPermissionDetailsView {
|
||||
accessPolicy: ServiceAccountProjectAccessPolicyView;
|
||||
hasPermission: boolean;
|
||||
}
|
@ -0,0 +1,9 @@
|
||||
import {
|
||||
GroupServiceAccountAccessPolicyView,
|
||||
UserServiceAccountAccessPolicyView,
|
||||
} from "./access-policy.view";
|
||||
|
||||
export class ServiceAccountPeopleAccessPoliciesView {
|
||||
userAccessPolicies: UserServiceAccountAccessPolicyView[];
|
||||
groupAccessPolicies: GroupServiceAccountAccessPolicyView[];
|
||||
}
|
@ -7,7 +7,7 @@ import { I18nService } from "@bitwarden/common/platform/abstractions/i18n.servic
|
||||
import { PlatformUtilsService } from "@bitwarden/common/platform/abstractions/platform-utils.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 {
|
||||
ApItemValueType,
|
||||
convertToProjectServiceAccountsAccessPoliciesView,
|
||||
|
@ -6,7 +6,6 @@ import { OrganizationService } from "@bitwarden/common/admin-console/abstraction
|
||||
import { DialogService } from "@bitwarden/components";
|
||||
|
||||
import { ProjectListView } from "../../models/view/project-list.view";
|
||||
import { AccessPolicyService } from "../../shared/access-policies/access-policy.service";
|
||||
import {
|
||||
BulkConfirmationDetails,
|
||||
BulkConfirmationDialogComponent,
|
||||
@ -38,7 +37,6 @@ export class ProjectsComponent implements OnInit {
|
||||
constructor(
|
||||
private route: ActivatedRoute,
|
||||
private projectService: ProjectService,
|
||||
private accessPolicyService: AccessPolicyService,
|
||||
private dialogService: DialogService,
|
||||
private organizationService: OrganizationService,
|
||||
) {}
|
||||
@ -47,7 +45,6 @@ export class ProjectsComponent implements OnInit {
|
||||
this.projects$ = combineLatest([
|
||||
this.route.params,
|
||||
this.projectService.project$.pipe(startWith(null)),
|
||||
this.accessPolicyService.projectAccessPolicyChanges$.pipe(startWith(null)),
|
||||
]).pipe(
|
||||
switchMap(async ([params]) => {
|
||||
this.organizationId = params.organizationId;
|
||||
|
@ -7,7 +7,7 @@ import { I18nService } from "@bitwarden/common/platform/abstractions/i18n.servic
|
||||
import { PlatformUtilsService } from "@bitwarden/common/platform/abstractions/platform-utils.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 {
|
||||
ApItemValueType,
|
||||
convertToServiceAccountGrantedPoliciesView,
|
||||
|
@ -1,15 +1,17 @@
|
||||
import {
|
||||
ProjectPeopleAccessPoliciesView,
|
||||
UserProjectAccessPolicyView,
|
||||
GroupProjectAccessPolicyView,
|
||||
ServiceAccountPeopleAccessPoliciesView,
|
||||
UserServiceAccountAccessPolicyView,
|
||||
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,
|
||||
ServiceAccountProjectPolicyPermissionDetailsView,
|
||||
ServiceAccountProjectAccessPolicyView,
|
||||
ProjectServiceAccountsAccessPoliciesView,
|
||||
} from "../../../../models/view/access-policy.view";
|
||||
} from "../../../../models/view/access-policies/service-account-granted-policies.view";
|
||||
import { ServiceAccountPeopleAccessPoliciesView } from "../../../../models/view/access-policies/service-account-people-access-policies.view";
|
||||
|
||||
import { ApItemEnum } from "./enums/ap-item.enum";
|
||||
import { ApPermissionEnum, ApPermissionEnumUtil } from "./enums/ap-permission.enum";
|
||||
|
@ -1,13 +1,11 @@
|
||||
import { Utils } from "@bitwarden/common/platform/misc/utils";
|
||||
import { SelectItemView } from "@bitwarden/components";
|
||||
|
||||
import {
|
||||
ProjectPeopleAccessPoliciesView,
|
||||
ServiceAccountGrantedPoliciesView,
|
||||
ProjectServiceAccountsAccessPoliciesView,
|
||||
ServiceAccountPeopleAccessPoliciesView,
|
||||
} from "../../../../models/view/access-policy.view";
|
||||
import { PotentialGranteeView } from "../../../../models/view/potential-grantee.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 } from "../../../../models/view/access-policies/service-account-granted-policies.view";
|
||||
import { ServiceAccountPeopleAccessPoliciesView } from "../../../../models/view/access-policies/service-account-people-access-policies.view";
|
||||
|
||||
import { ApItemEnum, ApItemEnumUtil } from "./enums/ap-item.enum";
|
||||
import { ApPermissionEnum, ApPermissionEnumUtil } from "./enums/ap-permission.enum";
|
||||
|
@ -1,5 +1,4 @@
|
||||
import { Injectable } from "@angular/core";
|
||||
import { Subject } from "rxjs";
|
||||
|
||||
import { ApiService } from "@bitwarden/common/abstractions/api.service";
|
||||
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 {
|
||||
BaseAccessPolicyView,
|
||||
GroupProjectAccessPolicyView,
|
||||
GroupServiceAccountAccessPolicyView,
|
||||
ProjectAccessPoliciesView,
|
||||
ProjectPeopleAccessPoliciesView,
|
||||
ServiceAccountProjectAccessPolicyView,
|
||||
UserProjectAccessPolicyView,
|
||||
GroupProjectAccessPolicyView,
|
||||
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,
|
||||
ProjectServiceAccountsAccessPoliciesView,
|
||||
ServiceAccountProjectPolicyPermissionDetailsView,
|
||||
} 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";
|
||||
} from "../../models/view/access-policies/service-account-granted-policies.view";
|
||||
import { ServiceAccountPeopleAccessPoliciesView } from "../../models/view/access-policies/service-account-people-access-policies.view";
|
||||
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 { AccessPolicyUpdateRequest } from "./models/requests/access-policy-update.request";
|
||||
import { AccessPolicyRequest } from "./models/requests/access-policy.request";
|
||||
import { ProjectServiceAccountsAccessPoliciesRequest } from "./models/requests/project-service-accounts-access-policies.request";
|
||||
import {
|
||||
@ -49,39 +45,12 @@ import { ServiceAccountProjectPolicyPermissionDetailsResponse } from "./models/r
|
||||
providedIn: "root",
|
||||
})
|
||||
export class AccessPolicyService {
|
||||
private _projectAccessPolicyChanges$ = new Subject<ProjectAccessPoliciesView>();
|
||||
|
||||
/**
|
||||
* Emits when a project access policy is created or deleted.
|
||||
*/
|
||||
readonly projectAccessPolicyChanges$ = this._projectAccessPolicyChanges$.asObservable();
|
||||
|
||||
constructor(
|
||||
private cryptoService: CryptoService,
|
||||
protected apiService: ApiService,
|
||||
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(
|
||||
projectId: string,
|
||||
): Promise<ProjectPeopleAccessPoliciesView> {
|
||||
@ -212,43 +181,6 @@ export class AccessPolicyService {
|
||||
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) {
|
||||
const r = await this.apiService.send(
|
||||
"GET",
|
||||
@ -285,11 +217,11 @@ export class AccessPolicyService {
|
||||
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);
|
||||
}
|
||||
|
||||
protected getAccessPolicyRequest(
|
||||
private getAccessPolicyRequest(
|
||||
granteeId: string,
|
||||
view:
|
||||
| UserProjectAccessPolicyView
|
||||
@ -305,7 +237,53 @@ export class AccessPolicyService {
|
||||
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:
|
||||
| UserProjectAccessPolicyResponse
|
||||
| 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(
|
||||
response: ServiceAccountGrantedPoliciesPermissionDetailsResponse,
|
||||
organizationId: string,
|
||||
@ -413,27 +365,6 @@ export class AccessPolicyService {
|
||||
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(
|
||||
peopleAccessPoliciesResponse: ProjectPeopleAccessPoliciesResponse,
|
||||
): ProjectPeopleAccessPoliciesView {
|
||||
@ -462,56 +393,6 @@ export class AccessPolicyService {
|
||||
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(
|
||||
response: UserProjectAccessPolicyResponse,
|
||||
): UserProjectAccessPolicyView {
|
||||
|
@ -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>
|
@ -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;
|
||||
}
|
||||
}
|
@ -1,7 +0,0 @@
|
||||
import { AccessPolicyRequest } from "./access-policy.request";
|
||||
|
||||
export class AccessPoliciesCreateRequest {
|
||||
userAccessPolicyRequests?: AccessPolicyRequest[];
|
||||
groupAccessPolicyRequests?: AccessPolicyRequest[];
|
||||
serviceAccountAccessPolicyRequests?: AccessPolicyRequest[];
|
||||
}
|
@ -1,4 +0,0 @@
|
||||
export class AccessPolicyUpdateRequest {
|
||||
read: boolean;
|
||||
write: boolean;
|
||||
}
|
@ -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),
|
||||
);
|
||||
}
|
||||
}
|
@ -13,7 +13,6 @@ import { ProductSwitcherModule } from "@bitwarden/web-vault/app/layouts/product-
|
||||
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 { BulkConfirmationDialogComponent } from "./dialogs/bulk-confirmation-dialog.component";
|
||||
import { BulkStatusDialogComponent } from "./dialogs/bulk-status-dialog.component";
|
||||
import { NewMenuComponent } from "./new-menu.component";
|
||||
@ -35,7 +34,6 @@ import { SecretsListComponent } from "./secrets-list.component";
|
||||
],
|
||||
exports: [
|
||||
AccessPolicySelectorComponent,
|
||||
AccessSelectorComponent,
|
||||
BulkConfirmationDialogComponent,
|
||||
BulkStatusDialogComponent,
|
||||
HeaderModule,
|
||||
@ -49,7 +47,6 @@ import { SecretsListComponent } from "./secrets-list.component";
|
||||
],
|
||||
declarations: [
|
||||
AccessPolicySelectorComponent,
|
||||
AccessSelectorComponent,
|
||||
BulkConfirmationDialogComponent,
|
||||
BulkStatusDialogComponent,
|
||||
BulkStatusDialogComponent,
|
||||
|
Loading…
Reference in New Issue
Block a user