mirror of
https://github.com/bitwarden/browser
synced 2025-12-22 11:13:46 +00:00
[AC-1373] Flexible Collections (#6336)
* [AC-1117] Add manage permission (#5910) * Add 'manage' option to collection access permissions * Add 'manage' to collection permissions * remove service accidentally committed from another branch * Update CLI commands * update message casing to be consistent * access selector model updates * [AC-1374] Limit collection create/delete (#5963) * feat: udate request/response/data/domain models for new column, refs AC-1374 * feat: create collection management ui, refs AC-1374 * fix: remove limitCollectionCdOwnerAdmin boolean from org update request, refs AC-1374 * fix: moved collection management UI, removed comments, refs AC-1374 * fix: observable chaining now properly calls API when local org updated, refs AC-1374 * fix: remove unused form template variables, refs AC-1374 * fix: clean up observable chain, refs AC-1374 * fix: remove parent.parent route, refs AC-1374 * fix: add cd explaination, refs AC-1374 * [AC-1649] Remove organizationId from collection-bulk-delete.request (#6343) * refactor: remove organizationId from collection-bulk-delete-request, refs AC-1649 * refactor: remove request model from dialog component, refs AC-1649 * [AC-1174] Bulk collection management (#6133) * [AC-1174] Add bulk edit collection access event type * [AC-1174] Add bulk edit collection access menu option * [AC-1174] Add initial bulk collections access dialog * [AC-1174] Add logic to open bulk edit collections dialog * [AC-1174] Move AccessItemView helper methods to access selector model to be shared * [AC-1174] Add access selector to bulk collections dialog * [AC-1174] Add bulk assign access method to collection-admin service * [AC-1174] Introduce strongly typed BulkCollectionAccessRequest model * [AC-1174] Update vault item event type name * Update DialogService dependency --------- Co-authored-by: Thomas Rittson <trittson@bitwarden.com> * Rename LimitCollectionCdOwnerAdmin -> LimitCollectionCreationDeletion (#6409) * Add manage property to synced Collection data * Revert "Add manage property to synced Collection data" Pushed to feature branch instead of a new one This reverts commit65cd39589c. * Add manage property to synced Collection data * Revert "Add manage property to synced Collection data" This reverts commitf7fa30b79a. * [AC-1680] Add manage property to collection view and response models (#6417) * Add manage property to synced Collection data * Update tests * feat: add LimitCollectionCreationDeletion conditional to canCreateNewCollections logic, refs AC-1659 (#6429) * [AC-1669] Enforce Can Manage permission on Collection dialog (#6493) * [AC-1669] Cleanup unhandled promise warnings * [AC-1669] Force change detection to ensure AccessSelector has the most recent items * [AC-1669] Initially select acting member when creating a new collection * [AC-1669] Add validator to ensure manage permission is selected * [AC-1669] Update error toast logic to support access tab errors * [AC-1669] Add error icon * [AC-1713] [Flexible collections] Add feature flags to clients (#6486) * Add FlexibleCollections and BulkCollectionAccess flags * Flag Collection Management settings * Flag bulk collection access dialog * Flag collection access modal changes * [AC-1662] Add LimitCollecitonCreationDeletion conditional to CanDelete logic (#6526) * feat: implement limitCollectionCreationDeletion into canDelete logic, refs AC-1662 * feat: make canDelete functions backwards compatible with feature flag, refs AC-1662 * feat: update vault-items.component for async getter, refs AC-1662 * feat: update configService injection, refs AC-1662 * feat: add config service to canDelete reference, refs AC-1662 * fix: remove configservice dependency from views, refs AC-1757 (#6686) * Add missing provider to vault-items.stories (#6690) * Fix imports after update from master --------- Co-authored-by: Robyn MacCallum <robyntmaccallum@gmail.com> Co-authored-by: Vincent Salucci <26154748+vincentsalucci@users.noreply.github.com> Co-authored-by: Vincent Salucci <vincesalucci21@gmail.com> Co-authored-by: Shane Melton <smelton@bitwarden.com>
This commit is contained in:
@@ -76,7 +76,7 @@ export class InternalGroupService extends GroupService {
|
||||
request.accessAll = group.accessAll;
|
||||
request.users = group.members;
|
||||
request.collections = group.collections.map(
|
||||
(c) => new SelectionReadOnlyRequest(c.id, c.readOnly, c.hidePasswords)
|
||||
(c) => new SelectionReadOnlyRequest(c.id, c.readOnly, c.hidePasswords, c.manage)
|
||||
);
|
||||
|
||||
if (group.id == undefined) {
|
||||
|
||||
@@ -80,6 +80,7 @@ export class UserAdminService {
|
||||
id: c.id,
|
||||
hidePasswords: c.hidePasswords,
|
||||
readOnly: c.readOnly,
|
||||
manage: c.manage,
|
||||
}));
|
||||
view.groups = u.groups;
|
||||
view.accessSecretsManager = u.accessSecretsManager;
|
||||
|
||||
@@ -4,12 +4,14 @@ interface SelectionResponseLike {
|
||||
id: string;
|
||||
readOnly: boolean;
|
||||
hidePasswords: boolean;
|
||||
manage: boolean;
|
||||
}
|
||||
|
||||
export class CollectionAccessSelectionView extends View {
|
||||
readonly id: string;
|
||||
readonly readOnly: boolean;
|
||||
readonly hidePasswords: boolean;
|
||||
readonly manage: boolean;
|
||||
|
||||
constructor(response?: SelectionResponseLike) {
|
||||
super();
|
||||
@@ -21,5 +23,6 @@ export class CollectionAccessSelectionView extends View {
|
||||
this.id = response.id;
|
||||
this.readOnly = response.readOnly;
|
||||
this.hidePasswords = response.hidePasswords;
|
||||
this.manage = response.manage;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -40,6 +40,7 @@
|
||||
[columnHeader]="'member' | i18n"
|
||||
[selectorLabelText]="'selectMembers' | i18n"
|
||||
[emptySelectionText]="'noMembersAdded' | i18n"
|
||||
[flexibleCollectionsEnabled]="flexibleCollectionsEnabled$ | async"
|
||||
></bit-access-selector>
|
||||
</bit-tab>
|
||||
|
||||
@@ -60,6 +61,7 @@
|
||||
[columnHeader]="'collection' | i18n"
|
||||
[selectorLabelText]="'selectCollections' | i18n"
|
||||
[emptySelectionText]="'noCollectionsAdded' | i18n"
|
||||
[flexibleCollectionsEnabled]="flexibleCollectionsEnabled$ | async"
|
||||
></bit-access-selector>
|
||||
</ng-container>
|
||||
</bit-tab>
|
||||
|
||||
@@ -5,7 +5,9 @@ import { catchError, combineLatest, from, map, of, Subject, switchMap, takeUntil
|
||||
|
||||
import { ApiService } from "@bitwarden/common/abstractions/api.service";
|
||||
import { OrganizationUserService } from "@bitwarden/common/admin-console/abstractions/organization-user/organization-user.service";
|
||||
import { FeatureFlag } from "@bitwarden/common/enums/feature-flag.enum";
|
||||
import { ErrorResponse } from "@bitwarden/common/models/response/error.response";
|
||||
import { ConfigServiceAbstraction } from "@bitwarden/common/platform/abstractions/config/config.service.abstraction";
|
||||
import { I18nService } from "@bitwarden/common/platform/abstractions/i18n.service";
|
||||
import { LogService } from "@bitwarden/common/platform/abstractions/log.service";
|
||||
import { PlatformUtilsService } from "@bitwarden/common/platform/abstractions/platform-utils.service";
|
||||
@@ -78,6 +80,11 @@ export const openGroupAddEditDialog = (
|
||||
templateUrl: "group-add-edit.component.html",
|
||||
})
|
||||
export class GroupAddEditComponent implements OnInit, OnDestroy {
|
||||
protected flexibleCollectionsEnabled$ = this.configService.getFeatureFlag$(
|
||||
FeatureFlag.FlexibleCollections,
|
||||
false
|
||||
);
|
||||
|
||||
protected PermissionMode = PermissionMode;
|
||||
protected ResultType = GroupAddEditDialogResultType;
|
||||
|
||||
@@ -181,7 +188,8 @@ export class GroupAddEditComponent implements OnInit, OnDestroy {
|
||||
private logService: LogService,
|
||||
private formBuilder: FormBuilder,
|
||||
private changeDetectorRef: ChangeDetectorRef,
|
||||
private dialogService: DialogService
|
||||
private dialogService: DialogService,
|
||||
private configService: ConfigServiceAbstraction
|
||||
) {
|
||||
this.tabIndex = params.initialTab ?? GroupAddEditTabType.Info;
|
||||
}
|
||||
|
||||
@@ -289,6 +289,7 @@
|
||||
[columnHeader]="'groups' | i18n"
|
||||
[selectorLabelText]="'selectGroups' | i18n"
|
||||
[emptySelectionText]="'noGroupsAdded' | i18n"
|
||||
[flexibleCollectionsEnabled]="flexibleCollectionsEnabled$ | async"
|
||||
></bit-access-selector>
|
||||
</bit-tab>
|
||||
<bit-tab [label]="'collections' | i18n">
|
||||
@@ -321,6 +322,7 @@
|
||||
[columnHeader]="'collection' | i18n"
|
||||
[selectorLabelText]="'selectCollections' | i18n"
|
||||
[emptySelectionText]="'noCollectionsAdded' | i18n"
|
||||
[flexibleCollectionsEnabled]="flexibleCollectionsEnabled$ | async"
|
||||
></bit-access-selector
|
||||
></bit-tab>
|
||||
</bit-tab-group>
|
||||
|
||||
@@ -11,6 +11,8 @@ import {
|
||||
} from "@bitwarden/common/admin-console/enums";
|
||||
import { PermissionsApi } from "@bitwarden/common/admin-console/models/api/permissions.api";
|
||||
import { Organization } from "@bitwarden/common/admin-console/models/domain/organization";
|
||||
import { FeatureFlag } from "@bitwarden/common/enums/feature-flag.enum";
|
||||
import { ConfigServiceAbstraction } from "@bitwarden/common/platform/abstractions/config/config.service.abstraction";
|
||||
import { I18nService } from "@bitwarden/common/platform/abstractions/i18n.service";
|
||||
import { PlatformUtilsService } from "@bitwarden/common/platform/abstractions/platform-utils.service";
|
||||
import { CollectionView } from "@bitwarden/common/vault/models/view/collection.view";
|
||||
@@ -64,6 +66,11 @@ export enum MemberDialogResult {
|
||||
templateUrl: "member-dialog.component.html",
|
||||
})
|
||||
export class MemberDialogComponent implements OnInit, OnDestroy {
|
||||
protected flexibleCollectionsEnabled$ = this.configService.getFeatureFlag$(
|
||||
FeatureFlag.FlexibleCollections,
|
||||
false
|
||||
);
|
||||
|
||||
loading = true;
|
||||
editMode = false;
|
||||
isRevoked = false;
|
||||
@@ -134,7 +141,8 @@ export class MemberDialogComponent implements OnInit, OnDestroy {
|
||||
private groupService: GroupService,
|
||||
private userService: UserAdminService,
|
||||
private organizationUserService: OrganizationUserService,
|
||||
private dialogService: DialogService
|
||||
private dialogService: DialogService,
|
||||
private configService: ConfigServiceAbstraction
|
||||
) {}
|
||||
|
||||
async ngOnInit() {
|
||||
|
||||
@@ -7,7 +7,7 @@
|
||||
></i>
|
||||
<span class="tw-sr-only">{{ "loading" | i18n }}</span>
|
||||
</div>
|
||||
<form *ngIf="org && !loading" #form [bitSubmit]="submit" [formGroup]="formGroup">
|
||||
<form *ngIf="org && !loading" [bitSubmit]="submit" [formGroup]="formGroup">
|
||||
<div class="tw-grid tw-grid-cols-2 tw-gap-5">
|
||||
<div>
|
||||
<bit-form-field>
|
||||
@@ -52,6 +52,27 @@
|
||||
{{ "rotateApiKey" | i18n }}
|
||||
</button>
|
||||
</ng-container>
|
||||
<form
|
||||
*ngIf="org && !loading && (showCollectionManagementSettings$ | async)"
|
||||
[bitSubmit]="submitCollectionManagement"
|
||||
[formGroup]="collectionManagementFormGroup"
|
||||
>
|
||||
<h1 bitTypography="h1" class="tw-mt-16 tw-pb-2.5">{{ "collectionManagement" | i18n }}</h1>
|
||||
<p>{{ "collectionManagementDesc" | i18n }}</p>
|
||||
<bit-form-control>
|
||||
<bit-label>{{ "limitCollectionCreationDeletionDesc" | i18n }}</bit-label>
|
||||
<input type="checkbox" bitCheckbox formControlName="limitCollectionCreationDeletion" />
|
||||
</bit-form-control>
|
||||
<button
|
||||
type="submit"
|
||||
bitButton
|
||||
bitFormButton
|
||||
buttonType="primary"
|
||||
id="collectionManagementSubmitButton"
|
||||
>
|
||||
{{ "save" | i18n }}
|
||||
</button>
|
||||
</form>
|
||||
<h1 bitTypography="h1" class="tw-mt-16 tw-pb-2.5 !tw-text-danger">{{ "dangerZone" | i18n }}</h1>
|
||||
<div class="tw-rounded tw-border tw-border-solid tw-border-danger-500 tw-bg-background tw-p-5">
|
||||
<p>{{ "dangerZoneDesc" | i18n }}</p>
|
||||
|
||||
@@ -1,17 +1,19 @@
|
||||
import { Component, ViewChild, ViewContainerRef } from "@angular/core";
|
||||
import { FormBuilder, Validators } from "@angular/forms";
|
||||
import { ActivatedRoute, Router } from "@angular/router";
|
||||
import { combineLatest, lastValueFrom, Subject, switchMap, takeUntil, from } from "rxjs";
|
||||
import { combineLatest, lastValueFrom, Subject, switchMap, takeUntil, from, of } from "rxjs";
|
||||
|
||||
import { ModalService } from "@bitwarden/angular/services/modal.service";
|
||||
import { OrganizationApiServiceAbstraction } from "@bitwarden/common/admin-console/abstractions/organization/organization-api.service.abstraction";
|
||||
import { OrganizationService } from "@bitwarden/common/admin-console/abstractions/organization/organization.service.abstraction";
|
||||
import { OrganizationCollectionManagementUpdateRequest } from "@bitwarden/common/admin-console/models/request/organization-collection-management-update.request";
|
||||
import { OrganizationKeysRequest } from "@bitwarden/common/admin-console/models/request/organization-keys.request";
|
||||
import { OrganizationUpdateRequest } from "@bitwarden/common/admin-console/models/request/organization-update.request";
|
||||
import { OrganizationResponse } from "@bitwarden/common/admin-console/models/response/organization.response";
|
||||
import { FeatureFlag } from "@bitwarden/common/enums/feature-flag.enum";
|
||||
import { ConfigServiceAbstraction } from "@bitwarden/common/platform/abstractions/config/config.service.abstraction";
|
||||
import { CryptoService } from "@bitwarden/common/platform/abstractions/crypto.service";
|
||||
import { I18nService } from "@bitwarden/common/platform/abstractions/i18n.service";
|
||||
import { LogService } from "@bitwarden/common/platform/abstractions/log.service";
|
||||
import { PlatformUtilsService } from "@bitwarden/common/platform/abstractions/platform-utils.service";
|
||||
import { Utils } from "@bitwarden/common/platform/misc/utils";
|
||||
import { DialogService } from "@bitwarden/components";
|
||||
@@ -38,8 +40,11 @@ export class AccountComponent {
|
||||
loading = true;
|
||||
canUseApi = false;
|
||||
org: OrganizationResponse;
|
||||
formPromise: Promise<OrganizationResponse>;
|
||||
taxFormPromise: Promise<unknown>;
|
||||
showCollectionManagementSettings$ = this.configService.getFeatureFlag$(
|
||||
FeatureFlag.FlexibleCollections,
|
||||
false
|
||||
);
|
||||
|
||||
// FormGroup validators taken from server Organization domain object
|
||||
protected formGroup = this.formBuilder.group({
|
||||
@@ -60,6 +65,10 @@ export class AccountComponent {
|
||||
),
|
||||
});
|
||||
|
||||
protected collectionManagementFormGroup = this.formBuilder.group({
|
||||
limitCollectionCreationDeletion: [false],
|
||||
});
|
||||
|
||||
protected organizationId: string;
|
||||
protected publicKeyBuffer: Uint8Array;
|
||||
|
||||
@@ -71,27 +80,27 @@ export class AccountComponent {
|
||||
private route: ActivatedRoute,
|
||||
private platformUtilsService: PlatformUtilsService,
|
||||
private cryptoService: CryptoService,
|
||||
private logService: LogService,
|
||||
private router: Router,
|
||||
private organizationService: OrganizationService,
|
||||
private organizationApiService: OrganizationApiServiceAbstraction,
|
||||
private dialogService: DialogService,
|
||||
private formBuilder: FormBuilder
|
||||
private formBuilder: FormBuilder,
|
||||
private configService: ConfigServiceAbstraction
|
||||
) {}
|
||||
|
||||
async ngOnInit() {
|
||||
this.selfHosted = this.platformUtilsService.isSelfHost();
|
||||
|
||||
this.route.parent.parent.params
|
||||
this.route.params
|
||||
.pipe(
|
||||
switchMap((params) => {
|
||||
switchMap((params) => this.organizationService.get$(params.organizationId)),
|
||||
switchMap((organization) => {
|
||||
return combineLatest([
|
||||
// Organization domain
|
||||
this.organizationService.get$(params.organizationId),
|
||||
of(organization),
|
||||
// OrganizationResponse for form population
|
||||
from(this.organizationApiService.get(params.organizationId)),
|
||||
from(this.organizationApiService.get(organization.id)),
|
||||
// Organization Public Key
|
||||
from(this.organizationApiService.getKeys(params.organizationId)),
|
||||
from(this.organizationApiService.getKeys(organization.id)),
|
||||
]);
|
||||
}),
|
||||
takeUntil(this.destroy$)
|
||||
@@ -102,6 +111,16 @@ export class AccountComponent {
|
||||
this.canEditSubscription = organization.canEditSubscription;
|
||||
this.canUseApi = organization.useApi;
|
||||
|
||||
// Update disabled states - reactive forms prefers not using disabled attribute
|
||||
if (!this.selfHosted) {
|
||||
this.formGroup.get("orgName").enable();
|
||||
}
|
||||
|
||||
if (!this.selfHosted || this.canEditSubscription) {
|
||||
this.formGroup.get("billingEmail").enable();
|
||||
this.formGroup.get("businessName").enable();
|
||||
}
|
||||
|
||||
// Org Response
|
||||
this.org = orgResponse;
|
||||
|
||||
@@ -114,16 +133,9 @@ export class AccountComponent {
|
||||
billingEmail: this.org.billingEmail,
|
||||
businessName: this.org.businessName,
|
||||
});
|
||||
|
||||
// Update disabled states - reactive forms prefers not using disabled attribute
|
||||
if (!this.selfHosted) {
|
||||
this.formGroup.get("orgName").enable();
|
||||
}
|
||||
|
||||
if (!this.selfHosted || this.canEditSubscription) {
|
||||
this.formGroup.get("billingEmail").enable();
|
||||
this.formGroup.get("businessName").enable();
|
||||
}
|
||||
this.collectionManagementFormGroup.patchValue({
|
||||
limitCollectionCreationDeletion: this.org.limitCollectionCreationDeletion,
|
||||
});
|
||||
|
||||
this.loading = false;
|
||||
});
|
||||
@@ -153,11 +165,25 @@ export class AccountComponent {
|
||||
request.keys = new OrganizationKeysRequest(orgKeys[0], orgKeys[1].encryptedString);
|
||||
}
|
||||
|
||||
this.formPromise = this.organizationApiService.save(this.organizationId, request);
|
||||
await this.formPromise;
|
||||
await this.organizationApiService.save(this.organizationId, request);
|
||||
|
||||
this.platformUtilsService.showToast("success", null, this.i18nService.t("organizationUpdated"));
|
||||
};
|
||||
|
||||
submitCollectionManagement = async () => {
|
||||
const request = new OrganizationCollectionManagementUpdateRequest();
|
||||
request.limitCreateDeleteOwnerAdmin =
|
||||
this.collectionManagementFormGroup.value.limitCollectionCreationDeletion;
|
||||
|
||||
await this.organizationApiService.updateCollectionManagement(this.organizationId, request);
|
||||
|
||||
this.platformUtilsService.showToast(
|
||||
"success",
|
||||
null,
|
||||
this.i18nService.t("collectionManagementUpdated")
|
||||
);
|
||||
};
|
||||
|
||||
async deleteOrganization() {
|
||||
const dialog = openDeleteOrganizationDialog(this.dialogService, {
|
||||
data: {
|
||||
|
||||
@@ -122,6 +122,10 @@ export class AccessSelectorComponent implements ControlValueAccessor, OnInit, On
|
||||
{ perm: CollectionPermission.Edit, labelId: "canEdit" },
|
||||
{ perm: CollectionPermission.EditExceptPass, labelId: "canEditExceptPass" },
|
||||
];
|
||||
private canManagePermissionListItem = {
|
||||
perm: CollectionPermission.Manage,
|
||||
labelId: "canManage",
|
||||
};
|
||||
protected initialPermission = CollectionPermission.View;
|
||||
|
||||
disabled: boolean;
|
||||
@@ -192,6 +196,11 @@ export class AccessSelectorComponent implements ControlValueAccessor, OnInit, On
|
||||
*/
|
||||
@Input() showGroupColumn: boolean;
|
||||
|
||||
/**
|
||||
* Enable Flexible Collections changes (feature flag)
|
||||
*/
|
||||
@Input() flexibleCollectionsEnabled: boolean;
|
||||
|
||||
constructor(
|
||||
private readonly formBuilder: FormBuilder,
|
||||
private readonly i18nService: I18nService
|
||||
@@ -254,7 +263,7 @@ export class AccessSelectorComponent implements ControlValueAccessor, OnInit, On
|
||||
this.pauseChangeNotification = false;
|
||||
}
|
||||
|
||||
ngOnInit() {
|
||||
async ngOnInit() {
|
||||
// Watch the internal formArray for changes and propagate them
|
||||
this.selectionList.formArray.valueChanges.pipe(takeUntil(this.destroy$)).subscribe((v) => {
|
||||
if (!this.notifyOnChange || this.pauseChangeNotification) {
|
||||
@@ -268,6 +277,10 @@ export class AccessSelectorComponent implements ControlValueAccessor, OnInit, On
|
||||
}
|
||||
this.notifyOnChange(v);
|
||||
});
|
||||
|
||||
if (this.flexibleCollectionsEnabled) {
|
||||
this.permissionList.push(this.canManagePermissionListItem);
|
||||
}
|
||||
}
|
||||
|
||||
ngOnDestroy() {
|
||||
|
||||
@@ -1,19 +1,21 @@
|
||||
import { OrganizationUserUserDetailsResponse } from "@bitwarden/common/admin-console/abstractions/organization-user/responses";
|
||||
import {
|
||||
OrganizationUserStatusType,
|
||||
OrganizationUserType,
|
||||
} from "@bitwarden/common/admin-console/enums";
|
||||
import { SelectItemView } from "@bitwarden/components";
|
||||
|
||||
import { CollectionAccessSelectionView } from "../../../core";
|
||||
import { CollectionAccessSelectionView, GroupView } from "../../../core";
|
||||
|
||||
/**
|
||||
* Permission options that replace/correspond with readOnly and hidePassword server fields.
|
||||
* Permission options that replace/correspond with manage, readOnly, and hidePassword server fields.
|
||||
*/
|
||||
export enum CollectionPermission {
|
||||
View = "view",
|
||||
ViewExceptPass = "viewExceptPass",
|
||||
Edit = "edit",
|
||||
EditExceptPass = "editExceptPass",
|
||||
Manage = "manage",
|
||||
}
|
||||
|
||||
export enum AccessItemType {
|
||||
@@ -82,7 +84,9 @@ export type AccessItemValue = {
|
||||
* @param value
|
||||
*/
|
||||
export const convertToPermission = (value: CollectionAccessSelectionView) => {
|
||||
if (value.readOnly) {
|
||||
if (value.manage) {
|
||||
return CollectionPermission.Manage;
|
||||
} else if (value.readOnly) {
|
||||
return value.hidePasswords ? CollectionPermission.ViewExceptPass : CollectionPermission.View;
|
||||
} else {
|
||||
return value.hidePasswords ? CollectionPermission.EditExceptPass : CollectionPermission.Edit;
|
||||
@@ -91,7 +95,7 @@ export const convertToPermission = (value: CollectionAccessSelectionView) => {
|
||||
|
||||
/**
|
||||
* Converts an AccessItemValue back into a CollectionAccessView class using the CollectionPermission
|
||||
* to determine the values for `readOnly` and `hidePassword`
|
||||
* to determine the values for `manage`, `readOnly`, and `hidePassword`
|
||||
* @param value
|
||||
*/
|
||||
export const convertToSelectionView = (value: AccessItemValue) => {
|
||||
@@ -99,6 +103,7 @@ export const convertToSelectionView = (value: AccessItemValue) => {
|
||||
id: value.id,
|
||||
readOnly: readOnly(value.permission),
|
||||
hidePasswords: hidePassword(value.permission),
|
||||
manage: value.permission === CollectionPermission.Manage,
|
||||
});
|
||||
};
|
||||
|
||||
@@ -107,3 +112,29 @@ const readOnly = (perm: CollectionPermission) =>
|
||||
|
||||
const hidePassword = (perm: CollectionPermission) =>
|
||||
[CollectionPermission.ViewExceptPass, CollectionPermission.EditExceptPass].includes(perm);
|
||||
|
||||
export function mapGroupToAccessItemView(group: GroupView): AccessItemView {
|
||||
return {
|
||||
id: group.id,
|
||||
type: AccessItemType.Group,
|
||||
listName: group.name,
|
||||
labelName: group.name,
|
||||
accessAllItems: group.accessAll,
|
||||
readonly: group.accessAll,
|
||||
};
|
||||
}
|
||||
|
||||
// TODO: Use view when user apis are migrated to a service
|
||||
export function mapUserToAccessItemView(user: OrganizationUserUserDetailsResponse): AccessItemView {
|
||||
return {
|
||||
id: user.id,
|
||||
type: AccessItemType.Member,
|
||||
email: user.email,
|
||||
role: user.type,
|
||||
listName: user.name?.length > 0 ? `${user.name} (${user.email})` : user.email,
|
||||
labelName: user.name ?? user.email,
|
||||
status: user.status,
|
||||
accessAllItems: user.accessAll,
|
||||
readonly: user.accessAll,
|
||||
};
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user