1
0
mirror of https://github.com/bitwarden/browser synced 2025-12-19 01:33:33 +00:00

[AC-1139] Checking if FC feature flag is enabled when using canDeleteAssignedCollections or canViewAssignedCollections

This commit is contained in:
Rui Tome
2023-11-17 11:22:06 +00:00
parent 7ce712aa7c
commit 8e5dc600df
13 changed files with 133 additions and 37 deletions

View File

@@ -1,11 +1,13 @@
import { Component, Input, OnInit } from "@angular/core"; import { Component, Input, OnInit } from "@angular/core";
import { map, Observable } from "rxjs"; import { combineLatest, map, Observable } from "rxjs";
import { import {
canAccessAdmin, canAccessAdmin,
OrganizationService, OrganizationService,
} from "@bitwarden/common/admin-console/abstractions/organization/organization.service.abstraction"; } from "@bitwarden/common/admin-console/abstractions/organization/organization.service.abstraction";
import { Organization } from "@bitwarden/common/admin-console/models/domain/organization"; 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 { I18nService } from "@bitwarden/common/platform/abstractions/i18n.service";
import { Utils } from "@bitwarden/common/platform/misc/utils"; import { Utils } from "@bitwarden/common/platform/misc/utils";
@@ -14,7 +16,11 @@ import { Utils } from "@bitwarden/common/platform/misc/utils";
templateUrl: "organization-switcher.component.html", templateUrl: "organization-switcher.component.html",
}) })
export class OrganizationSwitcherComponent implements OnInit { export class OrganizationSwitcherComponent implements OnInit {
constructor(private organizationService: OrganizationService, private i18nService: I18nService) {} constructor(
private organizationService: OrganizationService,
private i18nService: I18nService,
private configService: ConfigServiceAbstraction
) {}
@Input() activeOrganization: Organization = null; @Input() activeOrganization: Organization = null;
organizations$: Observable<Organization[]>; organizations$: Observable<Organization[]>;
@@ -22,9 +28,14 @@ export class OrganizationSwitcherComponent implements OnInit {
loaded = false; loaded = false;
async ngOnInit() { async ngOnInit() {
this.organizations$ = this.organizationService.memberOrganizations$.pipe( this.organizations$ = combineLatest([
canAccessAdmin(this.i18nService), this.organizationService.memberOrganizations$,
map((orgs) => orgs.sort(Utils.getSortFunction(this.i18nService, "name"))) this.configService.getFeatureFlag$(FeatureFlag.FlexibleCollections, false),
]).pipe(
map(([orgs, flexibleCollectionsEnabled]) => {
const canAccess = canAccessAdmin(this.i18nService, flexibleCollectionsEnabled);
return canAccess ? orgs.sort(Utils.getSortFunction(this.i18nService, "name")) : [];
})
); );
this.loaded = true; this.loaded = true;

View File

@@ -9,6 +9,7 @@ import { mock, MockProxy } from "jest-mock-extended";
import { OrganizationService } from "@bitwarden/common/admin-console/abstractions/organization/organization.service.abstraction"; import { OrganizationService } from "@bitwarden/common/admin-console/abstractions/organization/organization.service.abstraction";
import { OrganizationUserType } from "@bitwarden/common/admin-console/enums"; import { OrganizationUserType } from "@bitwarden/common/admin-console/enums";
import { Organization } from "@bitwarden/common/admin-console/models/domain/organization"; import { Organization } from "@bitwarden/common/admin-console/models/domain/organization";
import { ConfigServiceAbstraction } from "@bitwarden/common/platform/abstractions/config/config.service.abstraction";
import { I18nService } from "@bitwarden/common/platform/abstractions/i18n.service"; import { I18nService } from "@bitwarden/common/platform/abstractions/i18n.service";
import { PlatformUtilsService } from "@bitwarden/common/platform/abstractions/platform-utils.service"; import { PlatformUtilsService } from "@bitwarden/common/platform/abstractions/platform-utils.service";
import { SyncService } from "@bitwarden/common/vault/abstractions/sync/sync.service.abstraction"; import { SyncService } from "@bitwarden/common/vault/abstractions/sync/sync.service.abstraction";
@@ -52,7 +53,8 @@ describe("Organization Permissions Guard", () => {
organizationService, organizationService,
mock<PlatformUtilsService>(), mock<PlatformUtilsService>(),
mock<I18nService>(), mock<I18nService>(),
mock<SyncService>() mock<SyncService>(),
mock<ConfigServiceAbstraction>()
); );
}); });

View File

@@ -6,6 +6,8 @@ import {
OrganizationService, OrganizationService,
} from "@bitwarden/common/admin-console/abstractions/organization/organization.service.abstraction"; } from "@bitwarden/common/admin-console/abstractions/organization/organization.service.abstraction";
import { Organization } from "@bitwarden/common/admin-console/models/domain/organization"; 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 { I18nService } from "@bitwarden/common/platform/abstractions/i18n.service";
import { PlatformUtilsService } from "@bitwarden/common/platform/abstractions/platform-utils.service"; import { PlatformUtilsService } from "@bitwarden/common/platform/abstractions/platform-utils.service";
import { SyncService } from "@bitwarden/common/vault/abstractions/sync/sync.service.abstraction"; import { SyncService } from "@bitwarden/common/vault/abstractions/sync/sync.service.abstraction";
@@ -19,7 +21,8 @@ export class OrganizationPermissionsGuard implements CanActivate {
private organizationService: OrganizationService, private organizationService: OrganizationService,
private platformUtilsService: PlatformUtilsService, private platformUtilsService: PlatformUtilsService,
private i18nService: I18nService, private i18nService: I18nService,
private syncService: SyncService private syncService: SyncService,
private configService: ConfigServiceAbstraction
) {} ) {}
async canActivate(route: ActivatedRouteSnapshot, state: RouterStateSnapshot) { async canActivate(route: ActivatedRouteSnapshot, state: RouterStateSnapshot) {
@@ -42,9 +45,17 @@ export class OrganizationPermissionsGuard implements CanActivate {
return this.router.createUrlTree(["/"]); return this.router.createUrlTree(["/"]);
} }
const permissionsCallback: (organization: Organization) => boolean = const flexibleCollectionsEnabled = await this.configService.getFeatureFlag(
route.data?.organizationPermissions; FeatureFlag.FlexibleCollections,
const hasPermissions = permissionsCallback == null || permissionsCallback(org); false
);
const permissionsCallback: (
organization: Organization,
flexibleCollectionsEnabled: boolean
) => boolean = route.data?.organizationPermissions;
const hasPermissions =
permissionsCallback == null || permissionsCallback(org, flexibleCollectionsEnabled);
if (!hasPermissions) { if (!hasPermissions) {
// Handle linkable ciphers for organizations the user only has view access to // Handle linkable ciphers for organizations the user only has view access to
@@ -60,7 +71,7 @@ export class OrganizationPermissionsGuard implements CanActivate {
} }
this.platformUtilsService.showToast("error", null, this.i18nService.t("accessDenied")); this.platformUtilsService.showToast("error", null, this.i18nService.t("accessDenied"));
return canAccessOrgAdmin(org) return canAccessOrgAdmin(org, flexibleCollectionsEnabled)
? this.router.createUrlTree(["/organizations", org.id]) ? this.router.createUrlTree(["/organizations", org.id])
: this.router.createUrlTree(["/"]); : this.router.createUrlTree(["/"]);
} }

View File

@@ -5,15 +5,25 @@ import {
canAccessOrgAdmin, canAccessOrgAdmin,
OrganizationService, OrganizationService,
} from "@bitwarden/common/admin-console/abstractions/organization/organization.service.abstraction"; } from "@bitwarden/common/admin-console/abstractions/organization/organization.service.abstraction";
import { FeatureFlag } from "@bitwarden/common/enums/feature-flag.enum";
import { ConfigServiceAbstraction } from "@bitwarden/common/platform/abstractions/config/config.service.abstraction";
@Injectable({ @Injectable({
providedIn: "root", providedIn: "root",
}) })
export class OrganizationRedirectGuard implements CanActivate { export class OrganizationRedirectGuard implements CanActivate {
constructor(private router: Router, private organizationService: OrganizationService) {} constructor(
private router: Router,
private organizationService: OrganizationService,
private configService: ConfigServiceAbstraction
) {}
async canActivate(route: ActivatedRouteSnapshot, state: RouterStateSnapshot) { async canActivate(route: ActivatedRouteSnapshot, state: RouterStateSnapshot) {
const org = this.organizationService.get(route.params.organizationId); const org = this.organizationService.get(route.params.organizationId);
const flexibleCollectionsEnabled = await this.configService.getFeatureFlag(
FeatureFlag.FlexibleCollections,
false
);
const customRedirect = route.data?.autoRedirectCallback; const customRedirect = route.data?.autoRedirectCallback;
if (customRedirect) { if (customRedirect) {
@@ -24,7 +34,7 @@ export class OrganizationRedirectGuard implements CanActivate {
return this.router.createUrlTree([state.url, ...redirectPath]); return this.router.createUrlTree([state.url, ...redirectPath]);
} }
if (canAccessOrgAdmin(org)) { if (canAccessOrgAdmin(org, flexibleCollectionsEnabled)) {
return this.router.createUrlTree(["/organizations", org.id]); return this.router.createUrlTree(["/organizations", org.id]);
} }
return this.router.createUrlTree(["/"]); return this.router.createUrlTree(["/"]);

View File

@@ -13,6 +13,8 @@ import {
OrganizationService, OrganizationService,
} from "@bitwarden/common/admin-console/abstractions/organization/organization.service.abstraction"; } from "@bitwarden/common/admin-console/abstractions/organization/organization.service.abstraction";
import { Organization } from "@bitwarden/common/admin-console/models/domain/organization"; 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";
@Component({ @Component({
selector: "app-organization-layout", selector: "app-organization-layout",
@@ -22,12 +24,21 @@ export class OrganizationLayoutComponent implements OnInit, OnDestroy {
organization$: Observable<Organization>; organization$: Observable<Organization>;
private _destroy = new Subject<void>(); private _destroy = new Subject<void>();
private flexibleCollectionsEnabled: boolean;
constructor(private route: ActivatedRoute, private organizationService: OrganizationService) {} constructor(
private route: ActivatedRoute,
private organizationService: OrganizationService,
private configService: ConfigServiceAbstraction
) {}
ngOnInit() { async ngOnInit() {
document.body.classList.remove("layout_frontend"); document.body.classList.remove("layout_frontend");
this.flexibleCollectionsEnabled = await this.configService.getFeatureFlag(
FeatureFlag.FlexibleCollections
);
this.organization$ = this.route.params this.organization$ = this.route.params
.pipe(takeUntil(this._destroy)) .pipe(takeUntil(this._destroy))
.pipe<string>(map((p) => p.organizationId)) .pipe<string>(map((p) => p.organizationId))
@@ -46,7 +57,7 @@ export class OrganizationLayoutComponent implements OnInit, OnDestroy {
} }
canShowVaultTab(organization: Organization): boolean { canShowVaultTab(organization: Organization): boolean {
return canAccessVaultTab(organization); return canAccessVaultTab(organization, this.flexibleCollectionsEnabled);
} }
canShowSettingsTab(organization: Organization): boolean { canShowSettingsTab(organization: Organization): boolean {

View File

@@ -78,8 +78,11 @@ const routes: Routes = [
}, },
]; ];
function getOrganizationRoute(organization: Organization): string { function getOrganizationRoute(
if (canAccessVaultTab(organization)) { organization: Organization,
flexibleCollectionsEnabled: boolean
): string {
if (canAccessVaultTab(organization, flexibleCollectionsEnabled)) {
return "vault"; return "vault";
} }
if (canAccessMembersTab(organization)) { if (canAccessMembersTab(organization)) {

View File

@@ -1,5 +1,5 @@
import { Component, OnInit } from "@angular/core"; import { Component, OnInit } from "@angular/core";
import { map, Observable } from "rxjs"; import { combineLatest, map, Observable } from "rxjs";
import { VaultTimeoutSettingsService } from "@bitwarden/common/abstractions/vault-timeout/vault-timeout-settings.service"; import { VaultTimeoutSettingsService } from "@bitwarden/common/abstractions/vault-timeout/vault-timeout-settings.service";
import { import {
@@ -9,8 +9,10 @@ import {
import { ProviderService } from "@bitwarden/common/admin-console/abstractions/provider.service"; import { ProviderService } from "@bitwarden/common/admin-console/abstractions/provider.service";
import { Organization } from "@bitwarden/common/admin-console/models/domain/organization"; import { Organization } from "@bitwarden/common/admin-console/models/domain/organization";
import { TokenService } from "@bitwarden/common/auth/abstractions/token.service"; import { TokenService } from "@bitwarden/common/auth/abstractions/token.service";
import { FeatureFlag } from "@bitwarden/common/enums/feature-flag.enum";
import { VaultTimeoutAction } from "@bitwarden/common/enums/vault-timeout-action.enum"; import { VaultTimeoutAction } from "@bitwarden/common/enums/vault-timeout-action.enum";
import { Provider } from "@bitwarden/common/models/domain/provider"; import { Provider } from "@bitwarden/common/models/domain/provider";
import { ConfigServiceAbstraction } from "@bitwarden/common/platform/abstractions/config/config.service.abstraction";
import { I18nService } from "@bitwarden/common/platform/abstractions/i18n.service"; import { I18nService } from "@bitwarden/common/platform/abstractions/i18n.service";
import { MessagingService } from "@bitwarden/common/platform/abstractions/messaging.service"; import { MessagingService } from "@bitwarden/common/platform/abstractions/messaging.service";
import { PlatformUtilsService } from "@bitwarden/common/platform/abstractions/platform-utils.service"; import { PlatformUtilsService } from "@bitwarden/common/platform/abstractions/platform-utils.service";
@@ -38,7 +40,8 @@ export class NavbarComponent implements OnInit {
private syncService: SyncService, private syncService: SyncService,
private organizationService: OrganizationService, private organizationService: OrganizationService,
private vaultTimeoutSettingsService: VaultTimeoutSettingsService, private vaultTimeoutSettingsService: VaultTimeoutSettingsService,
private i18nService: I18nService private i18nService: I18nService,
private configService: ConfigServiceAbstraction
) { ) {
this.selfHosted = this.platformUtilsService.isSelfHost(); this.selfHosted = this.platformUtilsService.isSelfHost();
} }
@@ -57,8 +60,14 @@ export class NavbarComponent implements OnInit {
} }
this.providers = await this.providerService.getAll(); this.providers = await this.providerService.getAll();
this.organizations$ = this.organizationService.memberOrganizations$.pipe( this.organizations$ = combineLatest([
canAccessAdmin(this.i18nService) this.organizationService.memberOrganizations$,
this.configService.getFeatureFlag$(FeatureFlag.FlexibleCollections, false),
]).pipe(
map(([organizations, featureFlag]) => {
const canAccess = canAccessAdmin(this.i18nService, featureFlag);
return canAccess ? organizations : [];
})
); );
this.canLock$ = this.vaultTimeoutSettingsService this.canLock$ = this.vaultTimeoutSettingsService
.availableVaultTimeoutActions$() .availableVaultTimeoutActions$()

View File

@@ -6,6 +6,8 @@ import {
OrganizationService, OrganizationService,
canAccessVaultTab, canAccessVaultTab,
} from "@bitwarden/common/admin-console/abstractions/organization/organization.service.abstraction"; } from "@bitwarden/common/admin-console/abstractions/organization/organization.service.abstraction";
import { FeatureFlag } from "@bitwarden/common/enums/feature-flag.enum";
import { ConfigServiceAbstraction } from "@bitwarden/common/platform/abstractions/config/config.service.abstraction";
import { ImportComponent } from "@bitwarden/importer/ui"; import { ImportComponent } from "@bitwarden/importer/ui";
import { SharedModule } from "../../shared"; import { SharedModule } from "../../shared";
@@ -20,14 +22,20 @@ export class ImportWebComponent implements OnInit {
protected loading = false; protected loading = false;
protected disabled = false; protected disabled = false;
private flexibleCollectionsEnabled: boolean;
constructor( constructor(
private route: ActivatedRoute, private route: ActivatedRoute,
private organizationService: OrganizationService, private organizationService: OrganizationService,
private router: Router private router: Router,
private configService: ConfigServiceAbstraction
) {} ) {}
ngOnInit(): void { async ngOnInit() {
this.routeOrgId = this.route.snapshot.paramMap.get("organizationId"); this.routeOrgId = this.route.snapshot.paramMap.get("organizationId");
this.flexibleCollectionsEnabled = await this.configService.getFeatureFlag(
FeatureFlag.FlexibleCollections
);
} }
/** /**
@@ -44,7 +52,7 @@ export class ImportWebComponent implements OnInit {
return; return;
} }
if (canAccessVaultTab(organization)) { if (canAccessVaultTab(organization, this.flexibleCollectionsEnabled)) {
await this.router.navigate(["organizations", organizationId, "vault"]); await this.router.navigate(["organizations", organizationId, "vault"]);
} }
} }

View File

@@ -109,7 +109,10 @@
{{ "cancel" | i18n }} {{ "cancel" | i18n }}
</button> </button>
<button <button
*ngIf="editMode && organization?.canDeleteAssignedCollections" *ngIf="
editMode &&
((flexibleCollectionsEnabled$ | async) || organization?.canDeleteAssignedCollections)
"
type="button" type="button"
bitIconButton="bwi-trash" bitIconButton="bwi-trash"
buttonType="danger" buttonType="danger"

View File

@@ -3,6 +3,8 @@ import { Component, Inject } from "@angular/core";
import { ApiService } from "@bitwarden/common/abstractions/api.service"; import { ApiService } from "@bitwarden/common/abstractions/api.service";
import { Organization } from "@bitwarden/common/admin-console/models/domain/organization"; 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 { I18nService } from "@bitwarden/common/platform/abstractions/i18n.service";
import { PlatformUtilsService } from "@bitwarden/common/platform/abstractions/platform-utils.service"; import { PlatformUtilsService } from "@bitwarden/common/platform/abstractions/platform-utils.service";
import { CipherService } from "@bitwarden/common/vault/abstractions/cipher.service"; import { CipherService } from "@bitwarden/common/vault/abstractions/cipher.service";
@@ -58,7 +60,8 @@ export class BulkDeleteDialogComponent {
private platformUtilsService: PlatformUtilsService, private platformUtilsService: PlatformUtilsService,
private i18nService: I18nService, private i18nService: I18nService,
private apiService: ApiService, private apiService: ApiService,
private collectionService: CollectionService private collectionService: CollectionService,
private configService: ConfigServiceAbstraction
) { ) {
this.cipherIds = params.cipherIds ?? []; this.cipherIds = params.cipherIds ?? [];
this.collectionIds = params.collectionIds ?? []; this.collectionIds = params.collectionIds ?? [];
@@ -125,10 +128,14 @@ export class BulkDeleteDialogComponent {
} }
private async deleteCollections(): Promise<any> { private async deleteCollections(): Promise<any> {
const flexibleCollectionsEnabled = await this.configService.getFeatureFlag(
FeatureFlag.FlexibleCollections,
false
);
// From org vault // From org vault
if (this.organization) { if (this.organization) {
if ( if (
!this.organization.canDeleteAssignedCollections && (flexibleCollectionsEnabled || !this.organization.canDeleteAssignedCollections) &&
!this.organization.canDeleteAnyCollection !this.organization.canDeleteAnyCollection
) { ) {
this.platformUtilsService.showToast( this.platformUtilsService.showToast(
@@ -143,7 +150,10 @@ export class BulkDeleteDialogComponent {
} else if (this.organizations && this.collections) { } else if (this.organizations && this.collections) {
const deletePromises: Promise<any>[] = []; const deletePromises: Promise<any>[] = [];
for (const organization of this.organizations) { for (const organization of this.organizations) {
if (!organization.canDeleteAssignedCollections && !organization.canDeleteAnyCollection) { if (
(flexibleCollectionsEnabled || !this.organization.canDeleteAssignedCollections) &&
!organization.canDeleteAnyCollection
) {
this.platformUtilsService.showToast( this.platformUtilsService.showToast(
"error", "error",
this.i18nService.t("errorOccurred"), this.i18nService.t("errorOccurred"),

View File

@@ -687,7 +687,14 @@ export class VaultComponent implements OnInit, OnDestroy {
async deleteCollection(collection: CollectionView): Promise<void> { async deleteCollection(collection: CollectionView): Promise<void> {
const organization = this.organizationService.get(collection.organizationId); const organization = this.organizationService.get(collection.organizationId);
if (!organization.canDeleteAssignedCollections && !organization.canDeleteAnyCollection) { const flexibleCollectionsEnabled = await this.configService.getFeatureFlag(
FeatureFlag.FlexibleCollections,
false
);
if (
(flexibleCollectionsEnabled || !organization.canDeleteAssignedCollections) &&
!organization.canDeleteAnyCollection
) {
this.platformUtilsService.showToast( this.platformUtilsService.showToast(
"error", "error",
this.i18nService.t("errorOccurred"), this.i18nService.t("errorOccurred"),

View File

@@ -132,6 +132,7 @@ export class VaultComponent implements OnInit, OnDestroy {
FeatureFlag.BulkCollectionAccess, FeatureFlag.BulkCollectionAccess,
false false
); );
protected flexibleCollectionsEnabled: boolean;
private searchText$ = new Subject<string>(); private searchText$ = new Subject<string>();
private refresh$ = new BehaviorSubject<void>(null); private refresh$ = new BehaviorSubject<void>(null);
@@ -750,8 +751,12 @@ export class VaultComponent implements OnInit, OnDestroy {
} }
async deleteCollection(collection: CollectionView): Promise<void> { async deleteCollection(collection: CollectionView): Promise<void> {
const flexibleCollectionsEnabled = await this.configService.getFeatureFlag(
FeatureFlag.FlexibleCollections,
false
);
if ( if (
!this.organization.canDeleteAssignedCollections && (flexibleCollectionsEnabled || !this.organization.canDeleteAssignedCollections) &&
!this.organization.canDeleteAnyCollection !this.organization.canDeleteAnyCollection
) { ) {
this.platformUtilsService.showToast( this.platformUtilsService.showToast(

View File

@@ -5,8 +5,12 @@ import { Utils } from "../../../platform/misc/utils";
import { OrganizationData } from "../../models/data/organization.data"; import { OrganizationData } from "../../models/data/organization.data";
import { Organization } from "../../models/domain/organization"; import { Organization } from "../../models/domain/organization";
export function canAccessVaultTab(org: Organization): boolean { export function canAccessVaultTab(org: Organization, flexibleCollectionsEnabled: boolean): boolean {
return org.canViewAssignedCollections || org.canViewAllCollections; if (flexibleCollectionsEnabled) {
return org.canViewAllCollections;
} else {
return org.canViewAssignedCollections || org.canViewAllCollections;
}
} }
export function canAccessSettingsTab(org: Organization): boolean { export function canAccessSettingsTab(org: Organization): boolean {
@@ -36,14 +40,14 @@ export function canAccessBillingTab(org: Organization): boolean {
return org.isOwner; return org.isOwner;
} }
export function canAccessOrgAdmin(org: Organization): boolean { export function canAccessOrgAdmin(org: Organization, flexibleCollectionsEnabled: boolean): boolean {
return ( return (
canAccessMembersTab(org) || canAccessMembersTab(org) ||
canAccessGroupsTab(org) || canAccessGroupsTab(org) ||
canAccessReportingTab(org) || canAccessReportingTab(org) ||
canAccessBillingTab(org) || canAccessBillingTab(org) ||
canAccessSettingsTab(org) || canAccessSettingsTab(org) ||
canAccessVaultTab(org) canAccessVaultTab(org, flexibleCollectionsEnabled)
); );
} }
@@ -51,9 +55,11 @@ export function getOrganizationById(id: string) {
return map<Organization[], Organization | undefined>((orgs) => orgs.find((o) => o.id === id)); return map<Organization[], Organization | undefined>((orgs) => orgs.find((o) => o.id === id));
} }
export function canAccessAdmin(i18nService: I18nService) { export function canAccessAdmin(i18nService: I18nService, flexibleCollectionsEnabled: boolean) {
return map<Organization[], Organization[]>((orgs) => return map<Organization[], Organization[]>((orgs) =>
orgs.filter(canAccessOrgAdmin).sort(Utils.getSortFunction(i18nService, "name")) orgs
.filter((org) => canAccessOrgAdmin(org, flexibleCollectionsEnabled))
.sort(Utils.getSortFunction(i18nService, "name"))
); );
} }