1
0
mirror of https://github.com/bitwarden/browser synced 2025-12-19 09:43:23 +00:00

[AC-1139] Reverted change that introduced ConfigService as a parameter to canAccessVaultTab

This commit is contained in:
Rui Tome
2023-11-27 13:13:35 +00:00
parent ed9e03570c
commit 975d38ba27
12 changed files with 37 additions and 109 deletions

View File

@@ -1,12 +1,11 @@
import { Component, Input, OnInit } from "@angular/core"; import { Component, Input, OnInit } from "@angular/core";
import { Observable, switchMap } from "rxjs"; import { 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 { 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";
@@ -15,11 +14,7 @@ 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( constructor(private organizationService: OrganizationService, private i18nService: I18nService) {}
private organizationService: OrganizationService,
private i18nService: I18nService,
private configService: ConfigServiceAbstraction
) {}
@Input() activeOrganization: Organization = null; @Input() activeOrganization: Organization = null;
organizations$: Observable<Organization[]>; organizations$: Observable<Organization[]>;
@@ -28,10 +23,8 @@ export class OrganizationSwitcherComponent implements OnInit {
async ngOnInit() { async ngOnInit() {
this.organizations$ = this.organizationService.memberOrganizations$.pipe( this.organizations$ = this.organizationService.memberOrganizations$.pipe(
switchMap(async (orgs) => { canAccessAdmin(this.i18nService),
const canAccess = await canAccessAdmin(this.i18nService, this.configService); map((orgs) => orgs.sort(Utils.getSortFunction(this.i18nService, "name")))
return canAccess ? orgs.sort(Utils.getSortFunction(this.i18nService, "name")) : orgs;
})
); );
this.loaded = true; this.loaded = true;

View File

@@ -9,7 +9,6 @@ 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";
@@ -53,8 +52,7 @@ describe("Organization Permissions Guard", () => {
organizationService, organizationService,
mock<PlatformUtilsService>(), mock<PlatformUtilsService>(),
mock<I18nService>(), mock<I18nService>(),
mock<SyncService>(), mock<SyncService>()
mock<ConfigServiceAbstraction>()
); );
}); });

View File

@@ -6,7 +6,6 @@ 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 { 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";
@@ -20,8 +19,7 @@ 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) {
@@ -44,12 +42,9 @@ export class OrganizationPermissionsGuard implements CanActivate {
return this.router.createUrlTree(["/"]); return this.router.createUrlTree(["/"]);
} }
const permissionsCallback: ( const permissionsCallback: (organization: Organization) => boolean =
organization: Organization, route.data?.organizationPermissions;
configService: ConfigServiceAbstraction const hasPermissions = permissionsCallback == null || permissionsCallback(org);
) => Promise<boolean> = route.data?.organizationPermissions;
const hasPermissions =
permissionsCallback == null || (await permissionsCallback(org, this.configService));
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
@@ -65,7 +60,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 (await canAccessOrgAdmin(org, this.configService)) return canAccessOrgAdmin(org)
? this.router.createUrlTree(["/organizations", org.id]) ? this.router.createUrlTree(["/organizations", org.id])
: this.router.createUrlTree(["/"]); : this.router.createUrlTree(["/"]);
} }

View File

@@ -5,31 +5,26 @@ 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 { 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( constructor(private router: Router, private organizationService: OrganizationService) {}
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 customRedirect = route.data?.autoRedirectCallback; const customRedirect = route.data?.autoRedirectCallback;
if (customRedirect) { if (customRedirect) {
let redirectPath = await customRedirect(org, this.configService); let redirectPath = customRedirect(org);
if (typeof redirectPath === "string") { if (typeof redirectPath === "string") {
redirectPath = [redirectPath]; redirectPath = [redirectPath];
} }
return this.router.createUrlTree([state.url, ...redirectPath]); return this.router.createUrlTree([state.url, ...redirectPath]);
} }
if (await canAccessOrgAdmin(org, this.configService)) { if (canAccessOrgAdmin(org)) {
return this.router.createUrlTree(["/organizations", org.id]); return this.router.createUrlTree(["/organizations", org.id]);
} }
return this.router.createUrlTree(["/"]); return this.router.createUrlTree(["/"]);

View File

@@ -7,7 +7,7 @@
[activeOrganization]="organization" [activeOrganization]="organization"
></app-organization-switcher> ></app-organization-switcher>
<bit-tab-nav-bar class="-tw-mb-px"> <bit-tab-nav-bar class="-tw-mb-px">
<bit-tab-link *ngIf="canShowVaultTab(organization) | async" route="vault">{{ <bit-tab-link *ngIf="canShowVaultTab(organization)" route="vault">{{
"vault" | i18n "vault" | i18n
}}</bit-tab-link> }}</bit-tab-link>
<bit-tab-link *ngIf="canShowMembersTab(organization)" route="members">{{ <bit-tab-link *ngIf="canShowMembersTab(organization)" route="members">{{

View File

@@ -13,8 +13,6 @@ 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",
@@ -24,21 +22,12 @@ 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( constructor(private route: ActivatedRoute, private organizationService: OrganizationService) {}
private route: ActivatedRoute,
private organizationService: OrganizationService,
private configService: ConfigServiceAbstraction
) {}
async ngOnInit() { 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))
@@ -56,8 +45,8 @@ export class OrganizationLayoutComponent implements OnInit, OnDestroy {
this._destroy.complete(); this._destroy.complete();
} }
async canShowVaultTab(organization: Organization): Promise<boolean> { canShowVaultTab(organization: Organization): boolean {
return await canAccessVaultTab(organization, this.configService); return canAccessVaultTab(organization);
} }
canShowSettingsTab(organization: Organization): boolean { canShowSettingsTab(organization: Organization): boolean {

View File

@@ -11,7 +11,6 @@ import {
canAccessSettingsTab, canAccessSettingsTab,
} 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 { ConfigServiceAbstraction } from "@bitwarden/common/platform/abstractions/config/config.service.abstraction";
import { OrganizationPermissionsGuard } from "../../admin-console/organizations/guards/org-permissions.guard"; import { OrganizationPermissionsGuard } from "../../admin-console/organizations/guards/org-permissions.guard";
import { OrganizationRedirectGuard } from "../../admin-console/organizations/guards/org-redirect.guard"; import { OrganizationRedirectGuard } from "../../admin-console/organizations/guards/org-redirect.guard";
@@ -80,11 +79,8 @@ const routes: Routes = [
}, },
]; ];
async function getOrganizationRoute( function getOrganizationRoute(organization: Organization): string {
organization: Organization, if (canAccessVaultTab(organization)) {
configService: ConfigServiceAbstraction
): Promise<string> {
if (await canAccessVaultTab(organization, configService)) {
return "vault"; return "vault";
} }
if (canAccessMembersTab(organization)) { if (canAccessMembersTab(organization)) {

View File

@@ -22,15 +22,9 @@
class="nav-item" class="nav-item"
routerLinkActive="active" routerLinkActive="active"
> >
<ng-container *ngIf="{ orgs: organizations$ | async } as data"> <a class="nav-link" [routerLink]="['/organizations', (organizations$ | async)[0].id]">{{
<a "organizations" | i18n
*ngIf="data.orgs?.length > 0" }}</a>
class="nav-link"
[routerLink]="['/organizations', data.orgs[0].id]"
>
{{ "organizations" | i18n }}
</a>
</ng-container>
</li> </li>
<ng-container *ngIf="providers.length >= 1"> <ng-container *ngIf="providers.length >= 1">
<li class="nav-item" routerLinkActive="active" *ngIf="providers.length == 1"> <li class="nav-item" routerLinkActive="active" *ngIf="providers.length == 1">

View File

@@ -1,5 +1,5 @@
import { Component, OnInit } from "@angular/core"; import { Component, OnInit } from "@angular/core";
import { map, Observable, switchMap } from "rxjs"; import { 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 {
@@ -11,7 +11,6 @@ import { Organization } from "@bitwarden/common/admin-console/models/domain/orga
import { TokenService } from "@bitwarden/common/auth/abstractions/token.service"; import { TokenService } from "@bitwarden/common/auth/abstractions/token.service";
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";
@@ -39,8 +38,7 @@ 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();
} }
@@ -60,10 +58,7 @@ 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$ = this.organizationService.memberOrganizations$.pipe(
switchMap(async (orgs) => { canAccessAdmin(this.i18nService)
const isAdmin = await canAccessAdmin(this.i18nService, this.configService);
return isAdmin ? orgs : [];
})
); );
this.canLock$ = this.vaultTimeoutSettingsService this.canLock$ = this.vaultTimeoutSettingsService
.availableVaultTimeoutActions$() .availableVaultTimeoutActions$()

View File

@@ -6,7 +6,6 @@ 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 { 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";
@@ -24,8 +23,7 @@ export class ImportWebComponent implements OnInit {
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 { ngOnInit(): void {
@@ -46,7 +44,7 @@ export class ImportWebComponent implements OnInit {
return; return;
} }
if (await canAccessVaultTab(organization, this.configService)) { if (canAccessVaultTab(organization)) {
await this.router.navigate(["organizations", organizationId, "vault"]); await this.router.navigate(["organizations", organizationId, "vault"]);
} }
} }

View File

@@ -33,7 +33,7 @@ export class CollectionAdminView extends CollectionView {
override canEdit(org: Organization, flexibleCollectionsEnabled: boolean): boolean { override canEdit(org: Organization, flexibleCollectionsEnabled: boolean): boolean {
if (flexibleCollectionsEnabled) { if (flexibleCollectionsEnabled) {
return org?.canEditAnyCollection || this.assigned; return org?.canEditAnyCollection;
} else { } else {
return org?.canEditAnyCollection || (org?.canEditAssignedCollections && this.assigned); return org?.canEditAnyCollection || (org?.canEditAssignedCollections && this.assigned);
} }

View File

@@ -1,26 +1,12 @@
import { map, Observable } from "rxjs"; import { map, Observable } from "rxjs";
import { FeatureFlag } from "../../../enums/feature-flag.enum";
import { ConfigServiceAbstraction } from "../../../platform/abstractions/config/config.service.abstraction";
import { I18nService } from "../../../platform/abstractions/i18n.service"; import { I18nService } from "../../../platform/abstractions/i18n.service";
import { Utils } from "../../../platform/misc/utils"; 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 async function canAccessVaultTab( export function canAccessVaultTab(org: Organization): boolean {
org: Organization, return org.canViewAssignedCollections || org.canViewAllCollections;
configService: ConfigServiceAbstraction
): Promise<boolean> {
const flexibleCollectionsEnabled = await configService.getFeatureFlag(
FeatureFlag.FlexibleCollections,
false
);
if (flexibleCollectionsEnabled) {
return org.canViewAllCollections;
} else {
return org.canViewAssignedCollections || org.canViewAllCollections;
}
} }
export function canAccessSettingsTab(org: Organization): boolean { export function canAccessSettingsTab(org: Organization): boolean {
@@ -50,17 +36,14 @@ export function canAccessBillingTab(org: Organization): boolean {
return org.isOwner; return org.isOwner;
} }
export async function canAccessOrgAdmin( export function canAccessOrgAdmin(org: Organization): boolean {
org: Organization,
configService: ConfigServiceAbstraction
): Promise<boolean> {
return ( return (
canAccessMembersTab(org) || canAccessMembersTab(org) ||
canAccessGroupsTab(org) || canAccessGroupsTab(org) ||
canAccessReportingTab(org) || canAccessReportingTab(org) ||
canAccessBillingTab(org) || canAccessBillingTab(org) ||
canAccessSettingsTab(org) || canAccessSettingsTab(org) ||
(await canAccessVaultTab(org, configService)) canAccessVaultTab(org)
); );
} }
@@ -68,18 +51,10 @@ 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 async function canAccessAdmin( export function canAccessAdmin(i18nService: I18nService) {
i18nService: I18nService, return map<Organization[], Organization[]>((orgs) =>
configService: ConfigServiceAbstraction orgs.filter(canAccessOrgAdmin).sort(Utils.getSortFunction(i18nService, "name"))
) { );
return async (orgs: Organization[]): Promise<Organization[]> => {
const orgsPromises = orgs.map(async (org) => {
const canAccess = await canAccessOrgAdmin(org, configService);
return canAccess ? org : null;
});
const results = (await Promise.all(orgsPromises)).filter((org) => org !== null);
return results.sort(Utils.getSortFunction(i18nService, "name"));
};
} }
export function canAccessImportExport(i18nService: I18nService) { export function canAccessImportExport(i18nService: I18nService) {