1
0
mirror of https://github.com/bitwarden/browser synced 2025-12-15 07:43:35 +00:00

[EC-416] Refactor organization permission checks (#3252)

* Replace Permissions enum and helper methods with callbacks

* Remove scim feature flag

* Check if org has feature enabled as part of canManage checks

* Pin jest-mock-extended at v2.0.6 to fix compilation error
This commit is contained in:
Thomas Rittson
2022-08-16 00:08:06 +10:00
committed by GitHub
parent 96d5f50c7f
commit d30701ada7
32 changed files with 474 additions and 282 deletions

View File

@@ -16,7 +16,6 @@
"proxyEvents": "https://events.bitwarden.com"
},
"flags": {
"showTrial": false,
"scim": true
"showTrial": false
}
}

View File

@@ -10,7 +10,6 @@
"proxyNotifications": "http://localhost:61840"
},
"flags": {
"showTrial": true,
"scim": true
"showTrial": true
}
}

View File

@@ -10,7 +10,6 @@
"proxyEvents": "https://events.qa.bitwarden.pw"
},
"flags": {
"showTrial": true,
"scim": true
"showTrial": true
}
}

View File

@@ -7,7 +7,6 @@
"port": 8081
},
"flags": {
"showTrial": false,
"scim": true
"showTrial": false
}
}

View File

@@ -5,7 +5,7 @@ import { OrganizationService } from "@bitwarden/common/abstractions/organization
import { Utils } from "@bitwarden/common/misc/utils";
import { Organization } from "@bitwarden/common/models/domain/organization";
import { NavigationPermissionsService } from "../organizations/services/navigation-permissions.service";
import { canAccessOrgAdmin } from "../organizations/navigation-permissions";
@Component({
selector: "app-organization-switcher",
@@ -26,7 +26,7 @@ export class OrganizationSwitcherComponent implements OnInit {
async load() {
const orgs = await this.organizationService.getAll();
this.organizations = orgs
.filter((org) => NavigationPermissionsService.canAccessAdmin(org))
.filter(canAccessOrgAdmin)
.sort(Utils.getSortFunction(this.i18nService, "name"));
this.loaded = true;

View File

@@ -12,7 +12,7 @@ import { Utils } from "@bitwarden/common/misc/utils";
import { Organization } from "@bitwarden/common/models/domain/organization";
import { Provider } from "@bitwarden/common/models/domain/provider";
import { NavigationPermissionsService as OrgNavigationPermissionsService } from "../organizations/services/navigation-permissions.service";
import { canAccessOrgAdmin } from "../organizations/navigation-permissions";
@Component({
selector: "app-navbar",
@@ -69,9 +69,7 @@ export class NavbarComponent implements OnInit {
async buildOrganizations() {
const allOrgs = await this.organizationService.getAll();
return allOrgs
.filter((org) => OrgNavigationPermissionsService.canAccessAdmin(org))
.sort(Utils.getSortFunction(this.i18nService, "name"));
return allOrgs.filter(canAccessOrgAdmin).sort(Utils.getSortFunction(this.i18nService, "name"));
}
lock() {

View File

@@ -0,0 +1,163 @@
import {
ActivatedRouteSnapshot,
convertToParamMap,
Router,
RouterStateSnapshot,
} from "@angular/router";
import { mock, MockProxy } from "jest-mock-extended";
import { I18nService } from "@bitwarden/common/abstractions/i18n.service";
import { OrganizationService } from "@bitwarden/common/abstractions/organization.service";
import { PlatformUtilsService } from "@bitwarden/common/abstractions/platformUtils.service";
import { SyncService } from "@bitwarden/common/abstractions/sync.service";
import { OrganizationUserType } from "@bitwarden/common/enums/organizationUserType";
import { Organization } from "@bitwarden/common/models/domain/organization";
import { OrganizationPermissionsGuard } from "./org-permissions.guard";
const orgFactory = (props: Partial<Organization> = {}) =>
Object.assign(
new Organization(),
{
id: "myOrgId",
enabled: true,
type: OrganizationUserType.Admin,
},
props
);
describe("Organization Permissions Guard", () => {
let router: MockProxy<Router>;
let organizationService: MockProxy<OrganizationService>;
let state: MockProxy<RouterStateSnapshot>;
let route: MockProxy<ActivatedRouteSnapshot>;
let organizationPermissionsGuard: OrganizationPermissionsGuard;
beforeEach(() => {
router = mock<Router>();
organizationService = mock<OrganizationService>();
state = mock<RouterStateSnapshot>();
route = mock<ActivatedRouteSnapshot>({
params: {
organizationId: orgFactory().id,
},
data: {
organizationPermissions: null,
},
});
organizationPermissionsGuard = new OrganizationPermissionsGuard(
router,
organizationService,
mock<PlatformUtilsService>(),
mock<I18nService>(),
mock<SyncService>()
);
});
it("blocks navigation if organization does not exist", async () => {
organizationService.get.mockResolvedValue(null);
const actual = await organizationPermissionsGuard.canActivate(route, state);
expect(actual).not.toBe(true);
});
it("permits navigation if no permissions are specified", async () => {
const org = orgFactory();
organizationService.get.calledWith(org.id).mockResolvedValue(org);
const actual = await organizationPermissionsGuard.canActivate(route, state);
expect(actual).toBe(true);
});
it("permits navigation if the user has permissions", async () => {
const permissionsCallback = jest.fn();
permissionsCallback.mockImplementation((org) => true);
route.data = {
organizationPermissions: permissionsCallback,
};
const org = orgFactory();
organizationService.get.calledWith(org.id).mockResolvedValue(org);
const actual = await organizationPermissionsGuard.canActivate(route, state);
expect(permissionsCallback).toHaveBeenCalled();
expect(actual).toBe(true);
});
describe("if the user does not have permissions", () => {
it("and there is no Item ID, block navigation", async () => {
const permissionsCallback = jest.fn();
permissionsCallback.mockImplementation((org) => false);
route.data = {
organizationPermissions: permissionsCallback,
};
state = mock<RouterStateSnapshot>({
root: mock<ActivatedRouteSnapshot>({
queryParamMap: convertToParamMap({}),
}),
});
const org = orgFactory();
organizationService.get.calledWith(org.id).mockResolvedValue(org);
const actual = await organizationPermissionsGuard.canActivate(route, state);
expect(permissionsCallback).toHaveBeenCalled();
expect(actual).not.toBe(true);
});
it("and there is an Item ID, redirect to the item in the individual vault", async () => {
route.data = {
organizationPermissions: (org: Organization) => false,
};
state = mock<RouterStateSnapshot>({
root: mock<ActivatedRouteSnapshot>({
queryParamMap: convertToParamMap({
itemId: "myItemId",
}),
}),
});
const org = orgFactory();
organizationService.get.calledWith(org.id).mockResolvedValue(org);
const actual = await organizationPermissionsGuard.canActivate(route, state);
expect(router.createUrlTree).toHaveBeenCalledWith(["/vault"], {
queryParams: { itemId: "myItemId" },
});
expect(actual).not.toBe(true);
});
});
describe("given a disabled organization", () => {
it("blocks navigation if user is not an owner", async () => {
const org = orgFactory({
type: OrganizationUserType.Admin,
enabled: false,
});
organizationService.get.calledWith(org.id).mockResolvedValue(org);
const actual = await organizationPermissionsGuard.canActivate(route, state);
expect(actual).not.toBe(true);
});
it("permits navigation if user is an owner", async () => {
const org = orgFactory({
type: OrganizationUserType.Owner,
enabled: false,
});
organizationService.get.calledWith(org.id).mockResolvedValue(org);
const actual = await organizationPermissionsGuard.canActivate(route, state);
expect(actual).toBe(true);
});
});
});

View File

@@ -5,12 +5,14 @@ import { I18nService } from "@bitwarden/common/abstractions/i18n.service";
import { OrganizationService } from "@bitwarden/common/abstractions/organization.service";
import { PlatformUtilsService } from "@bitwarden/common/abstractions/platformUtils.service";
import { SyncService } from "@bitwarden/common/abstractions/sync.service";
import { Permissions } from "@bitwarden/common/enums/permissions";
import { Organization } from "@bitwarden/common/models/domain/organization";
import { canAccessOrgAdmin } from "../navigation-permissions";
@Injectable({
providedIn: "root",
})
export class PermissionsGuard implements CanActivate {
export class OrganizationPermissionsGuard implements CanActivate {
constructor(
private router: Router,
private organizationService: OrganizationService,
@@ -39,8 +41,11 @@ export class PermissionsGuard implements CanActivate {
return this.router.createUrlTree(["/"]);
}
const permissions = route.data == null ? [] : (route.data.permissions as Permissions[]);
if (permissions != null && !org.hasAnyPermission(permissions)) {
const permissionsCallback: (organization: Organization) => boolean =
route.data?.organizationPermissions;
const hasPermissions = permissionsCallback == null || permissionsCallback(org);
if (!hasPermissions) {
// Handle linkable ciphers for organizations the user only has view access to
// https://bitwarden.atlassian.net/browse/EC-203
const cipherId =
@@ -54,7 +59,9 @@ export class PermissionsGuard implements CanActivate {
}
this.platformUtilsService.showToast("error", null, this.i18nService.t("accessDenied"));
return this.router.createUrlTree(["/"]);
return canAccessOrgAdmin(org)
? this.router.createUrlTree(["/organizations", org.id])
: this.router.createUrlTree(["/"]);
}
return true;

View File

@@ -5,7 +5,11 @@ import { BroadcasterService } from "@bitwarden/common/abstractions/broadcaster.s
import { OrganizationService } from "@bitwarden/common/abstractions/organization.service";
import { Organization } from "@bitwarden/common/models/domain/organization";
import { NavigationPermissionsService } from "../services/navigation-permissions.service";
import {
canAccessManageTab,
canAccessSettingsTab,
canAccessToolsTab,
} from "../navigation-permissions";
const BroadcasterSubscriptionId = "OrganizationLayoutComponent";
@@ -51,15 +55,15 @@ export class OrganizationLayoutComponent implements OnInit, OnDestroy {
}
get showManageTab(): boolean {
return NavigationPermissionsService.canAccessManage(this.organization);
return canAccessManageTab(this.organization);
}
get showToolsTab(): boolean {
return NavigationPermissionsService.canAccessTools(this.organization);
return canAccessToolsTab(this.organization);
}
get showSettingsTab(): boolean {
return NavigationPermissionsService.canAccessSettings(this.organization);
return canAccessSettingsTab(this.organization);
}
get toolsRoute(): string {

View File

@@ -1,12 +1,11 @@
import { Component, OnInit, ViewChild, ViewContainerRef } from "@angular/core";
import { ActivatedRoute, Router } from "@angular/router";
import { ActivatedRoute } from "@angular/router";
import { first } from "rxjs/operators";
import { ModalService } from "@bitwarden/angular/services/modal.service";
import { ApiService } from "@bitwarden/common/abstractions/api.service";
import { I18nService } from "@bitwarden/common/abstractions/i18n.service";
import { LogService } from "@bitwarden/common/abstractions/log.service";
import { OrganizationService } from "@bitwarden/common/abstractions/organization.service";
import { PlatformUtilsService } from "@bitwarden/common/abstractions/platformUtils.service";
import { SearchService } from "@bitwarden/common/abstractions/search.service";
import { Utils } from "@bitwarden/common/misc/utils";
@@ -41,20 +40,13 @@ export class GroupsComponent implements OnInit {
private i18nService: I18nService,
private modalService: ModalService,
private platformUtilsService: PlatformUtilsService,
private router: Router,
private searchService: SearchService,
private logService: LogService,
private organizationService: OrganizationService
private logService: LogService
) {}
async ngOnInit() {
this.route.parent.parent.params.subscribe(async (params) => {
this.organizationId = params.organizationId;
const organization = await this.organizationService.get(this.organizationId);
if (organization == null || !organization.useGroups) {
this.router.navigate(["/organizations", this.organizationId]);
return;
}
await this.load();
this.route.queryParams.pipe(first()).subscribe(async (qParams) => {
this.searchText = qParams.search;

View File

@@ -24,7 +24,7 @@
routerLink="groups"
class="list-group-item"
routerLinkActive="active"
*ngIf="organization.canManageGroups && accessGroups"
*ngIf="organization.canManageGroups"
>
{{ "groups" | i18n }}
</a>
@@ -32,7 +32,7 @@
routerLink="policies"
class="list-group-item"
routerLinkActive="active"
*ngIf="organization.canManagePolicies && accessPolicies"
*ngIf="organization.canManagePolicies"
>
{{ "policies" | i18n }}
</a>
@@ -40,7 +40,7 @@
routerLink="sso"
class="list-group-item"
routerLinkActive="active"
*ngIf="organization.canManageSso && accessSso"
*ngIf="organization.canManageSso"
>
{{ "singleSignOn" | i18n }}
</a>
@@ -48,7 +48,7 @@
routerLink="scim"
class="list-group-item"
routerLinkActive="active"
*ngIf="organization.canManageScim && accessScim"
*ngIf="organization.canManageScim"
>
{{ "scim" | i18n }}
</a>
@@ -56,7 +56,7 @@
routerLink="events"
class="list-group-item"
routerLinkActive="active"
*ngIf="organization.canAccessEventLogs && accessEvents"
*ngIf="organization.canAccessEventLogs"
>
{{ "eventLogs" | i18n }}
</a>

View File

@@ -4,35 +4,18 @@ import { ActivatedRoute } from "@angular/router";
import { OrganizationService } from "@bitwarden/common/abstractions/organization.service";
import { Organization } from "@bitwarden/common/models/domain/organization";
import { flagEnabled } from "../../../utils/flags";
@Component({
selector: "app-org-manage",
templateUrl: "manage.component.html",
})
export class ManageComponent implements OnInit {
organization: Organization;
accessPolicies = false;
accessGroups = false;
accessEvents = false;
accessSso = false;
accessScim = false;
constructor(private route: ActivatedRoute, private organizationService: OrganizationService) {}
ngOnInit() {
this.route.parent.params.subscribe(async (params) => {
this.organization = await this.organizationService.get(params.organizationId);
this.accessPolicies = this.organization.usePolicies;
this.accessSso = this.organization.useSso;
this.accessEvents = this.organization.useEvents;
this.accessGroups = this.organization.useGroups;
if (flagEnabled("scim")) {
this.accessScim = this.organization.useScim;
} else {
this.accessScim = false;
}
});
}
}

View File

@@ -113,10 +113,6 @@ export class PeopleComponent
this.route.parent.parent.params.subscribe(async (params) => {
this.organizationId = params.organizationId;
const organization = await this.organizationService.get(this.organizationId);
if (!organization.canManageUsers) {
this.router.navigate(["../collections"], { relativeTo: this.route });
return;
}
this.accessEvents = organization.useEvents;
this.accessGroups = organization.useGroups;
this.canResetPassword = organization.canManageUsersPassword;

View File

@@ -43,11 +43,6 @@ export class PoliciesComponent implements OnInit {
this.route.parent.parent.params.subscribe(async (params) => {
this.organizationId = params.organizationId;
this.organization = await this.organizationService.get(this.organizationId);
if (this.organization == null || !this.organization.usePolicies) {
this.router.navigate(["/organizations", this.organizationId]);
return;
}
this.policies = this.policyListService.getPolicies();
await this.load();

View File

@@ -0,0 +1,29 @@
import { Organization } from "@bitwarden/common/models/domain/organization";
export function canAccessToolsTab(org: Organization): boolean {
return org.canAccessImportExport || org.canAccessReports;
}
export function canAccessSettingsTab(org: Organization): boolean {
return org.isOwner;
}
export function canAccessManageTab(org: Organization): boolean {
return (
org.canCreateNewCollections ||
org.canEditAnyCollection ||
org.canDeleteAnyCollection ||
org.canEditAssignedCollections ||
org.canDeleteAssignedCollections ||
org.canAccessEventLogs ||
org.canManageGroups ||
org.canManageUsers ||
org.canManagePolicies ||
org.canManageSso ||
org.canManageScim
);
}
export function canAccessOrgAdmin(org: Organization): boolean {
return canAccessToolsTab(org) || canAccessSettingsTab(org) || canAccessManageTab(org);
}

View File

@@ -2,9 +2,9 @@ import { NgModule } from "@angular/core";
import { RouterModule, Routes } from "@angular/router";
import { AuthGuard } from "@bitwarden/angular/guards/auth.guard";
import { Permissions } from "@bitwarden/common/enums/permissions";
import { Organization } from "@bitwarden/common/models/domain/organization";
import { PermissionsGuard } from "./guards/permissions.guard";
import { OrganizationPermissionsGuard } from "./guards/org-permissions.guard";
import { OrganizationLayoutComponent } from "./layouts/organization-layout.component";
import { CollectionsComponent } from "./manage/collections.component";
import { EventsComponent } from "./manage/events.component";
@@ -12,7 +12,12 @@ import { GroupsComponent } from "./manage/groups.component";
import { ManageComponent } from "./manage/manage.component";
import { PeopleComponent } from "./manage/people.component";
import { PoliciesComponent } from "./manage/policies.component";
import { NavigationPermissionsService } from "./services/navigation-permissions.service";
import {
canAccessOrgAdmin,
canAccessManageTab,
canAccessSettingsTab,
canAccessToolsTab,
} from "./navigation-permissions";
import { AccountComponent } from "./settings/account.component";
import { OrganizationBillingComponent } from "./settings/organization-billing.component";
import { OrganizationSubscriptionComponent } from "./settings/organization-subscription.component";
@@ -30,9 +35,9 @@ const routes: Routes = [
{
path: ":organizationId",
component: OrganizationLayoutComponent,
canActivate: [AuthGuard, PermissionsGuard],
canActivate: [AuthGuard, OrganizationPermissionsGuard],
data: {
permissions: NavigationPermissionsService.getPermissions("admin"),
organizationPermissions: canAccessOrgAdmin,
},
children: [
{ path: "", pathMatch: "full", redirectTo: "vault" },
@@ -43,8 +48,10 @@ const routes: Routes = [
{
path: "tools",
component: ToolsComponent,
canActivate: [PermissionsGuard],
data: { permissions: NavigationPermissionsService.getPermissions("tools") },
canActivate: [OrganizationPermissionsGuard],
data: {
organizationPermissions: canAccessToolsTab,
},
children: [
{
path: "",
@@ -61,46 +68,46 @@ const routes: Routes = [
{
path: "exposed-passwords-report",
component: ExposedPasswordsReportComponent,
canActivate: [PermissionsGuard],
canActivate: [OrganizationPermissionsGuard],
data: {
titleId: "exposedPasswordsReport",
permissions: [Permissions.AccessReports],
organizationPermissions: (org: Organization) => org.canAccessReports,
},
},
{
path: "inactive-two-factor-report",
component: InactiveTwoFactorReportComponent,
canActivate: [PermissionsGuard],
canActivate: [OrganizationPermissionsGuard],
data: {
titleId: "inactive2faReport",
permissions: [Permissions.AccessReports],
organizationPermissions: (org: Organization) => org.canAccessReports,
},
},
{
path: "reused-passwords-report",
component: ReusedPasswordsReportComponent,
canActivate: [PermissionsGuard],
canActivate: [OrganizationPermissionsGuard],
data: {
titleId: "reusedPasswordsReport",
permissions: [Permissions.AccessReports],
organizationPermissions: (org: Organization) => org.canAccessReports,
},
},
{
path: "unsecured-websites-report",
component: UnsecuredWebsitesReportComponent,
canActivate: [PermissionsGuard],
canActivate: [OrganizationPermissionsGuard],
data: {
titleId: "unsecuredWebsitesReport",
permissions: [Permissions.AccessReports],
organizationPermissions: (org: Organization) => org.canAccessReports,
},
},
{
path: "weak-passwords-report",
component: WeakPasswordsReportComponent,
canActivate: [PermissionsGuard],
canActivate: [OrganizationPermissionsGuard],
data: {
titleId: "weakPasswordsReport",
permissions: [Permissions.AccessReports],
organizationPermissions: (org: Organization) => org.canAccessReports,
},
},
],
@@ -108,9 +115,9 @@ const routes: Routes = [
{
path: "manage",
component: ManageComponent,
canActivate: [PermissionsGuard],
canActivate: [OrganizationPermissionsGuard],
data: {
permissions: NavigationPermissionsService.getPermissions("manage"),
organizationPermissions: canAccessManageTab,
},
children: [
{
@@ -121,52 +128,52 @@ const routes: Routes = [
{
path: "collections",
component: CollectionsComponent,
canActivate: [PermissionsGuard],
canActivate: [OrganizationPermissionsGuard],
data: {
titleId: "collections",
permissions: [
Permissions.CreateNewCollections,
Permissions.EditAnyCollection,
Permissions.DeleteAnyCollection,
Permissions.EditAssignedCollections,
Permissions.DeleteAssignedCollections,
],
organizationPermissions: (org: Organization) =>
org.canCreateNewCollections ||
org.canEditAnyCollection ||
org.canDeleteAnyCollection ||
org.canEditAssignedCollections ||
org.canDeleteAssignedCollections,
},
},
{
path: "events",
component: EventsComponent,
canActivate: [PermissionsGuard],
canActivate: [OrganizationPermissionsGuard],
data: {
titleId: "eventLogs",
permissions: [Permissions.AccessEventLogs],
organizationPermissions: (org: Organization) => org.canAccessEventLogs,
},
},
{
path: "groups",
component: GroupsComponent,
canActivate: [PermissionsGuard],
canActivate: [OrganizationPermissionsGuard],
data: {
titleId: "groups",
permissions: [Permissions.ManageGroups],
organizationPermissions: (org: Organization) => org.canManageGroups,
},
},
{
path: "people",
component: PeopleComponent,
canActivate: [PermissionsGuard],
canActivate: [OrganizationPermissionsGuard],
data: {
titleId: "people",
permissions: [Permissions.ManageUsers, Permissions.ManageUsersPassword],
organizationPermissions: (org: Organization) =>
org.canManageUsers || org.canManageUsersPassword,
},
},
{
path: "policies",
component: PoliciesComponent,
canActivate: [PermissionsGuard],
canActivate: [OrganizationPermissionsGuard],
data: {
titleId: "policies",
permissions: [Permissions.ManagePolicies],
organizationPermissions: (org: Organization) => org.canManagePolicies,
},
},
],
@@ -174,8 +181,8 @@ const routes: Routes = [
{
path: "settings",
component: SettingsComponent,
canActivate: [PermissionsGuard],
data: { permissions: NavigationPermissionsService.getPermissions("settings") },
canActivate: [OrganizationPermissionsGuard],
data: { organizationPermissions: canAccessSettingsTab },
children: [
{ path: "", pathMatch: "full", redirectTo: "account" },
{ path: "account", component: AccountComponent, data: { titleId: "myOrganization" } },
@@ -187,8 +194,11 @@ const routes: Routes = [
{
path: "billing",
component: OrganizationBillingComponent,
canActivate: [PermissionsGuard],
data: { titleId: "billing", permissions: [Permissions.ManageBilling] },
canActivate: [OrganizationPermissionsGuard],
data: {
titleId: "billing",
organizationPermissions: (org: Organization) => org.canManageBilling,
},
},
{
path: "subscription",

View File

@@ -1,50 +0,0 @@
import { Permissions } from "@bitwarden/common/enums/permissions";
import { Organization } from "@bitwarden/common/models/domain/organization";
const permissions = {
manage: [
Permissions.CreateNewCollections,
Permissions.EditAnyCollection,
Permissions.DeleteAnyCollection,
Permissions.EditAssignedCollections,
Permissions.DeleteAssignedCollections,
Permissions.AccessEventLogs,
Permissions.ManageGroups,
Permissions.ManageUsers,
Permissions.ManagePolicies,
Permissions.ManageSso,
Permissions.ManageScim,
],
tools: [Permissions.AccessImportExport, Permissions.AccessReports],
settings: [Permissions.ManageOrganization],
};
export class NavigationPermissionsService {
static getPermissions(route: keyof typeof permissions | "admin") {
if (route === "admin") {
return Object.values(permissions).reduce((previous, current) => previous.concat(current), []);
}
return permissions[route];
}
static canAccessAdmin(organization: Organization): boolean {
return (
this.canAccessTools(organization) ||
this.canAccessSettings(organization) ||
this.canAccessManage(organization)
);
}
static canAccessTools(organization: Organization): boolean {
return organization.hasAnyPermission(NavigationPermissionsService.getPermissions("tools"));
}
static canAccessSettings(organization: Organization): boolean {
return organization.hasAnyPermission(NavigationPermissionsService.getPermissions("settings"));
}
static canAccessManage(organization: Organization): boolean {
return organization.hasAnyPermission(NavigationPermissionsService.getPermissions("manage"));
}
}

View File

@@ -1,9 +1,9 @@
import { NgModule } from "@angular/core";
import { RouterModule, Routes } from "@angular/router";
import { Permissions } from "@bitwarden/common/enums/permissions";
import { Organization } from "@bitwarden/common/models/domain/organization";
import { PermissionsGuard } from "../../guards/permissions.guard";
import { OrganizationPermissionsGuard } from "../../guards/org-permissions.guard";
import { OrganizationExportComponent } from "./org-export.component";
import { OrganizationImportComponent } from "./org-import.component";
@@ -12,19 +12,19 @@ const routes: Routes = [
{
path: "import",
component: OrganizationImportComponent,
canActivate: [PermissionsGuard],
canActivate: [OrganizationPermissionsGuard],
data: {
titleId: "importData",
permissions: [Permissions.AccessImportExport],
organizationPermissions: (org: Organization) => org.canAccessImportExport,
},
},
{
path: "export",
component: OrganizationExportComponent,
canActivate: [PermissionsGuard],
canActivate: [OrganizationPermissionsGuard],
data: {
titleId: "exportVault",
permissions: [Permissions.AccessImportExport],
organizationPermissions: (org: Organization) => org.canAccessImportExport,
},
},
];

View File

@@ -1,6 +1,5 @@
export type Flags = {
showTrial?: boolean;
scim?: boolean;
};
export type FlagName = keyof Flags;