diff --git a/apps/web/src/app/admin-console/organizations/members/components/member-dialog/member-dialog.component.html b/apps/web/src/app/admin-console/organizations/members/components/member-dialog/member-dialog.component.html index 46d8c6a867..95febbd3c5 100644 --- a/apps/web/src/app/admin-console/organizations/members/components/member-dialog/member-dialog.component.html +++ b/apps/web/src/app/admin-console/organizations/members/components/member-dialog/member-dialog.component.html @@ -399,7 +399,11 @@
- {{ "groupAccessUserDesc" | i18n }} + {{ + (restrictedAccess$ | async) + ? ("restrictedGroupAccess" | i18n) + : ("groupAccessUserDesc" | i18n) + }}
-
+
+ {{ "restrictedCollectionAccess" | i18n }} +
+
{{ "userPermissionOverrideHelper" | i18n }}
@@ -441,6 +449,7 @@ [selectorLabelText]="'selectCollections' | i18n" [emptySelectionText]="'noCollectionsAdded' | i18n" [flexibleCollectionsEnabled]="organization.flexibleCollections" + [hideMultiSelect]="restrictedAccess$ | async" > diff --git a/apps/web/src/app/admin-console/organizations/members/components/member-dialog/member-dialog.component.ts b/apps/web/src/app/admin-console/organizations/members/components/member-dialog/member-dialog.component.ts index 4d6442e898..38ddf013c0 100644 --- a/apps/web/src/app/admin-console/organizations/members/components/member-dialog/member-dialog.component.ts +++ b/apps/web/src/app/admin-console/organizations/members/components/member-dialog/member-dialog.component.ts @@ -4,6 +4,7 @@ import { FormBuilder, Validators } from "@angular/forms"; import { combineLatest, firstValueFrom, + map, Observable, of, shareReplay, @@ -20,7 +21,9 @@ 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 { AccountService } from "@bitwarden/common/auth/abstractions/account.service"; import { ProductType } from "@bitwarden/common/enums"; +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"; @@ -99,6 +102,8 @@ export class MemberDialogComponent implements OnDestroy { groups: [[] as AccessItemValue[]], }); + protected restrictedAccess$: Observable; + protected permissionsGroup = this.formBuilder.group({ manageAssignedCollectionsGroup: this.formBuilder.group>({ manageAssignedCollections: false, @@ -144,6 +149,7 @@ export class MemberDialogComponent implements OnDestroy { private organizationUserService: OrganizationUserService, private dialogService: DialogService, private configService: ConfigServiceAbstraction, + private accountService: AccountService, organizationService: OrganizationService, ) { this.organization$ = organizationService @@ -162,12 +168,42 @@ export class MemberDialogComponent implements OnDestroy { ), ); + const userDetails$ = this.params.organizationUserId + ? this.userService.get(this.params.organizationId, this.params.organizationUserId) + : of(null); + + // The orgUser cannot manage their own Group assignments if collection access is restricted + // TODO: fix disabled state of access-selector rows so that any controls are hidden + this.restrictedAccess$ = combineLatest([ + this.organization$, + userDetails$, + this.accountService.activeAccount$, + this.configService.getFeatureFlag$(FeatureFlag.FlexibleCollectionsV1), + ]).pipe( + map( + ([organization, userDetails, activeAccount, flexibleCollectionsV1Enabled]) => + // Feature flag conditionals + flexibleCollectionsV1Enabled && + organization.flexibleCollections && + // Business logic conditionals + userDetails.userId == activeAccount.id && + !organization.allowAdminAccessToAllCollectionItems, + ), + shareReplay({ refCount: true, bufferSize: 1 }), + ); + + this.restrictedAccess$.pipe(takeUntil(this.destroy$)).subscribe((restrictedAccess) => { + if (restrictedAccess) { + this.formGroup.controls.groups.disable(); + } else { + this.formGroup.controls.groups.enable(); + } + }); + combineLatest({ organization: this.organization$, collections: this.collectionAdminService.getAll(this.params.organizationId), - userDetails: this.params.organizationUserId - ? this.userService.get(this.params.organizationId, this.params.organizationUserId) - : of(null), + userDetails: userDetails$, groups: groups$, }) .pipe(takeUntil(this.destroy$)) @@ -369,7 +405,11 @@ export class MemberDialogComponent implements OnDestroy { userView.collections = this.formGroup.value.access .filter((v) => v.type === AccessItemType.Collection) .map(convertToSelectionView); - userView.groups = this.formGroup.value.groups.map((m) => m.id); + + userView.groups = (await firstValueFrom(this.restrictedAccess$)) + ? null + : this.formGroup.value.groups.map((m) => m.id); + userView.accessSecretsManager = this.formGroup.value.accessSecretsManager; if (this.editMode) { diff --git a/apps/web/src/app/admin-console/organizations/shared/components/access-selector/access-selector.component.html b/apps/web/src/app/admin-console/organizations/shared/components/access-selector/access-selector.component.html index 5a22b7b228..16a24781df 100644 --- a/apps/web/src/app/admin-console/organizations/shared/components/access-selector/access-selector.component.html +++ b/apps/web/src/app/admin-console/organizations/shared/components/access-selector/access-selector.component.html @@ -1,6 +1,6 @@ -
+
{{ "permission" | i18n }}