mirror of
https://github.com/bitwarden/web
synced 2025-12-23 19:53:16 +00:00
[End User Vault Refresh] Organizations - updated nav and route permissions (#1551)
* Add Organizations link to navbar * Update route permissions and guards * Use NavigationPermissionsService to unify route permissions
This commit is contained in:
@@ -19,17 +19,17 @@ import { MaximumVaultTimeoutPolicyComponent } from "./policies/maximum-vault-tim
|
||||
|
||||
@NgModule({
|
||||
imports: [
|
||||
AppRoutingModule,
|
||||
BrowserAnimationsModule,
|
||||
DragDropModule,
|
||||
FormsModule,
|
||||
InfiniteScrollModule,
|
||||
JslibModule,
|
||||
OrganizationsModule,
|
||||
OssRoutingModule,
|
||||
BrowserAnimationsModule,
|
||||
FormsModule,
|
||||
ReactiveFormsModule,
|
||||
RouterModule,
|
||||
ServicesModule,
|
||||
InfiniteScrollModule,
|
||||
DragDropModule,
|
||||
AppRoutingModule,
|
||||
OssRoutingModule,
|
||||
OrganizationsModule, // Must be after OssRoutingModule for competing routes to resolve properly
|
||||
RouterModule,
|
||||
WildcardRoutingModule, // Needs to be last to catch all non-existing routes
|
||||
],
|
||||
declarations: [
|
||||
|
||||
@@ -4,10 +4,10 @@ import { RouterModule, Routes } from "@angular/router";
|
||||
import { AuthGuard } from "jslib-angular/guards/auth.guard";
|
||||
import { Permissions } from "jslib-common/enums/permissions";
|
||||
|
||||
import { OrganizationLayoutComponent } from "src/app/layouts/organization-layout.component";
|
||||
import { PermissionsGuard } from "src/app/organizations/guards/permissions.guard";
|
||||
import { OrganizationLayoutComponent } from "src/app/organizations/layouts/organization-layout.component";
|
||||
import { ManageComponent } from "src/app/organizations/manage/manage.component";
|
||||
import { OrganizationGuardService } from "src/app/services/organization-guard.service";
|
||||
import { OrganizationTypeGuardService } from "src/app/services/organization-type-guard.service";
|
||||
import { NavigationPermissionsService } from "src/app/organizations/services/navigation-permissions.service";
|
||||
|
||||
import { SsoComponent } from "./manage/sso.component";
|
||||
|
||||
@@ -15,24 +15,15 @@ const routes: Routes = [
|
||||
{
|
||||
path: "organizations/:organizationId",
|
||||
component: OrganizationLayoutComponent,
|
||||
canActivate: [AuthGuard, OrganizationGuardService],
|
||||
canActivate: [AuthGuard, PermissionsGuard],
|
||||
children: [
|
||||
{
|
||||
path: "manage",
|
||||
component: ManageComponent,
|
||||
canActivate: [OrganizationTypeGuardService],
|
||||
canActivate: [PermissionsGuard],
|
||||
data: {
|
||||
permissions: [
|
||||
Permissions.CreateNewCollections,
|
||||
Permissions.EditAnyCollection,
|
||||
Permissions.DeleteAnyCollection,
|
||||
Permissions.EditAssignedCollections,
|
||||
Permissions.DeleteAssignedCollections,
|
||||
Permissions.AccessEventLogs,
|
||||
Permissions.ManageGroups,
|
||||
Permissions.ManageUsers,
|
||||
Permissions.ManagePolicies,
|
||||
Permissions.ManageSso,
|
||||
NavigationPermissionsService.getPermissions("manage").concat(Permissions.ManageSso),
|
||||
],
|
||||
},
|
||||
children: [
|
||||
|
||||
@@ -5,7 +5,7 @@ import { ProviderService } from "jslib-common/abstractions/provider.service";
|
||||
import { Permissions } from "jslib-common/enums/permissions";
|
||||
|
||||
@Injectable()
|
||||
export class ProviderTypeGuardService implements CanActivate {
|
||||
export class PermissionsGuard implements CanActivate {
|
||||
constructor(private providerService: ProviderService, private router: Router) {}
|
||||
|
||||
async canActivate(route: ActivatedRouteSnapshot) {
|
||||
@@ -6,7 +6,7 @@ import { PlatformUtilsService } from "jslib-common/abstractions/platformUtils.se
|
||||
import { ProviderService } from "jslib-common/abstractions/provider.service";
|
||||
|
||||
@Injectable()
|
||||
export class ProviderGuardService implements CanActivate {
|
||||
export class ProviderGuard implements CanActivate {
|
||||
constructor(
|
||||
private router: Router,
|
||||
private platformUtilsService: PlatformUtilsService,
|
||||
@@ -9,13 +9,13 @@ import { ProvidersComponent } from "src/app/providers/providers.component";
|
||||
|
||||
import { ClientsComponent } from "./clients/clients.component";
|
||||
import { CreateOrganizationComponent } from "./clients/create-organization.component";
|
||||
import { PermissionsGuard } from "./guards/provider-type.guard";
|
||||
import { ProviderGuard } from "./guards/provider.guard";
|
||||
import { AcceptProviderComponent } from "./manage/accept-provider.component";
|
||||
import { EventsComponent } from "./manage/events.component";
|
||||
import { ManageComponent } from "./manage/manage.component";
|
||||
import { PeopleComponent } from "./manage/people.component";
|
||||
import { ProvidersLayoutComponent } from "./providers-layout.component";
|
||||
import { ProviderGuardService } from "./services/provider-guard.service";
|
||||
import { ProviderTypeGuardService } from "./services/provider-type-guard.service";
|
||||
import { AccountComponent } from "./settings/account.component";
|
||||
import { SettingsComponent } from "./settings/settings.component";
|
||||
import { SetupProviderComponent } from "./setup/setup-provider.component";
|
||||
@@ -54,7 +54,7 @@ const routes: Routes = [
|
||||
{
|
||||
path: ":providerId",
|
||||
component: ProvidersLayoutComponent,
|
||||
canActivate: [ProviderGuardService],
|
||||
canActivate: [ProviderGuard],
|
||||
children: [
|
||||
{ path: "", pathMatch: "full", redirectTo: "clients" },
|
||||
{ path: "clients/create", component: CreateOrganizationComponent },
|
||||
@@ -71,7 +71,7 @@ const routes: Routes = [
|
||||
{
|
||||
path: "people",
|
||||
component: PeopleComponent,
|
||||
canActivate: [ProviderTypeGuardService],
|
||||
canActivate: [PermissionsGuard],
|
||||
data: {
|
||||
titleId: "people",
|
||||
permissions: [Permissions.ManageUsers],
|
||||
@@ -80,7 +80,7 @@ const routes: Routes = [
|
||||
{
|
||||
path: "events",
|
||||
component: EventsComponent,
|
||||
canActivate: [ProviderTypeGuardService],
|
||||
canActivate: [PermissionsGuard],
|
||||
data: {
|
||||
titleId: "eventLogs",
|
||||
permissions: [Permissions.AccessEventLogs],
|
||||
@@ -100,7 +100,7 @@ const routes: Routes = [
|
||||
{
|
||||
path: "account",
|
||||
component: AccountComponent,
|
||||
canActivate: [ProviderTypeGuardService],
|
||||
canActivate: [PermissionsGuard],
|
||||
data: {
|
||||
titleId: "myProvider",
|
||||
permissions: [Permissions.ManageProvider],
|
||||
|
||||
@@ -10,6 +10,8 @@ import { OssModule } from "src/app/oss.module";
|
||||
import { AddOrganizationComponent } from "./clients/add-organization.component";
|
||||
import { ClientsComponent } from "./clients/clients.component";
|
||||
import { CreateOrganizationComponent } from "./clients/create-organization.component";
|
||||
import { PermissionsGuard } from "./guards/provider-type.guard";
|
||||
import { ProviderGuard } from "./guards/provider.guard";
|
||||
import { AcceptProviderComponent } from "./manage/accept-provider.component";
|
||||
import { BulkConfirmComponent } from "./manage/bulk/bulk-confirm.component";
|
||||
import { BulkRemoveComponent } from "./manage/bulk/bulk-remove.component";
|
||||
@@ -19,8 +21,6 @@ import { PeopleComponent } from "./manage/people.component";
|
||||
import { UserAddEditComponent } from "./manage/user-add-edit.component";
|
||||
import { ProvidersLayoutComponent } from "./providers-layout.component";
|
||||
import { ProvidersRoutingModule } from "./providers-routing.module";
|
||||
import { ProviderGuardService } from "./services/provider-guard.service";
|
||||
import { ProviderTypeGuardService } from "./services/provider-type-guard.service";
|
||||
import { WebProviderService } from "./services/webProvider.service";
|
||||
import { AccountComponent } from "./settings/account.component";
|
||||
import { SettingsComponent } from "./settings/settings.component";
|
||||
@@ -46,7 +46,7 @@ import { SetupComponent } from "./setup/setup.component";
|
||||
SetupProviderComponent,
|
||||
UserAddEditComponent,
|
||||
],
|
||||
providers: [WebProviderService, ProviderGuardService, ProviderTypeGuardService],
|
||||
providers: [WebProviderService, ProviderGuard, PermissionsGuard],
|
||||
})
|
||||
export class ProvidersModule {
|
||||
constructor(modalService: ModalService, componentFactoryResolver: ComponentFactoryResolver) {
|
||||
|
||||
@@ -27,6 +27,11 @@
|
||||
<li class="nav-item" routerLinkActive="active">
|
||||
<a class="nav-link" routerLink="/reports">{{ "reports" | i18n }}</a>
|
||||
</li>
|
||||
<li *ngIf="organizations.length >= 1" class="nav-item" routerLinkActive="active">
|
||||
<a class="nav-link" [routerLink]="['/organizations', organizations[0].id]">{{
|
||||
"organizations" | i18n
|
||||
}}</a>
|
||||
</li>
|
||||
</ul>
|
||||
</div>
|
||||
<ul class="navbar-nav flex-row ml-md-auto d-none d-md-flex">
|
||||
|
||||
@@ -1,12 +1,18 @@
|
||||
import { Component, OnInit } from "@angular/core";
|
||||
|
||||
import { I18nService } from "jslib-common/abstractions/i18n.service";
|
||||
import { MessagingService } from "jslib-common/abstractions/messaging.service";
|
||||
import { OrganizationService } from "jslib-common/abstractions/organization.service";
|
||||
import { PlatformUtilsService } from "jslib-common/abstractions/platformUtils.service";
|
||||
import { ProviderService } from "jslib-common/abstractions/provider.service";
|
||||
import { SyncService } from "jslib-common/abstractions/sync.service";
|
||||
import { TokenService } from "jslib-common/abstractions/token.service";
|
||||
import { Utils } from "jslib-common/misc/utils";
|
||||
import { Organization } from "jslib-common/models/domain/organization";
|
||||
import { Provider } from "jslib-common/models/domain/provider";
|
||||
|
||||
import { NavigationPermissionsService as OrgNavigationPermissionsService } from "../organizations/services/navigation-permissions.service";
|
||||
|
||||
@Component({
|
||||
selector: "app-navbar",
|
||||
templateUrl: "navbar.component.html",
|
||||
@@ -16,13 +22,16 @@ export class NavbarComponent implements OnInit {
|
||||
name: string;
|
||||
email: string;
|
||||
providers: Provider[] = [];
|
||||
organizations: Organization[] = [];
|
||||
|
||||
constructor(
|
||||
private messagingService: MessagingService,
|
||||
private platformUtilsService: PlatformUtilsService,
|
||||
private tokenService: TokenService,
|
||||
private providerService: ProviderService,
|
||||
private syncService: SyncService
|
||||
private syncService: SyncService,
|
||||
private organizationService: OrganizationService,
|
||||
private i18nService: I18nService
|
||||
) {
|
||||
this.selfHosted = this.platformUtilsService.isSelfHost();
|
||||
}
|
||||
@@ -34,11 +43,16 @@ export class NavbarComponent implements OnInit {
|
||||
this.name = this.email;
|
||||
}
|
||||
|
||||
// Ensure provides are loaded
|
||||
// Ensure providers and organizations are loaded
|
||||
if ((await this.syncService.getLastSync()) == null) {
|
||||
await this.syncService.fullSync(false);
|
||||
}
|
||||
this.providers = await this.providerService.getAll();
|
||||
|
||||
const allOrgs = await this.organizationService.getAll();
|
||||
this.organizations = allOrgs
|
||||
.filter((org) => OrgNavigationPermissionsService.canAccessAdmin(org))
|
||||
.sort(Utils.getSortFunction(this.i18nService, "name"));
|
||||
}
|
||||
|
||||
lock() {
|
||||
|
||||
@@ -1,33 +1,42 @@
|
||||
import { Injectable } from "@angular/core";
|
||||
import { ActivatedRouteSnapshot, CanActivate, Router } from "@angular/router";
|
||||
|
||||
import { BaseGuard } from "jslib-angular/guards/base.guard";
|
||||
import { I18nService } from "jslib-common/abstractions/i18n.service";
|
||||
import { OrganizationService } from "jslib-common/abstractions/organization.service";
|
||||
import { PlatformUtilsService } from "jslib-common/abstractions/platformUtils.service";
|
||||
import { Permissions } from "jslib-common/enums/permissions";
|
||||
|
||||
@Injectable()
|
||||
export class OrganizationGuardService implements CanActivate {
|
||||
export class PermissionsGuard extends BaseGuard implements CanActivate {
|
||||
constructor(
|
||||
private router: Router,
|
||||
router: Router,
|
||||
private organizationService: OrganizationService,
|
||||
private platformUtilsService: PlatformUtilsService,
|
||||
private i18nService: I18nService,
|
||||
private organizationService: OrganizationService
|
||||
) {}
|
||||
private i18nService: I18nService
|
||||
) {
|
||||
super(router);
|
||||
}
|
||||
|
||||
async canActivate(route: ActivatedRouteSnapshot) {
|
||||
const org = await this.organizationService.get(route.params.organizationId);
|
||||
if (org == null) {
|
||||
this.router.navigate(["/"]);
|
||||
return false;
|
||||
return this.redirect();
|
||||
}
|
||||
|
||||
if (!org.isOwner && !org.enabled) {
|
||||
this.platformUtilsService.showToast(
|
||||
"error",
|
||||
null,
|
||||
this.i18nService.t("organizationIsDisabled")
|
||||
);
|
||||
this.router.navigate(["/"]);
|
||||
return false;
|
||||
return this.redirect();
|
||||
}
|
||||
|
||||
const permissions = route.data == null ? [] : (route.data.permissions as Permissions[]);
|
||||
if (permissions != null && !org.hasAnyPermission(permissions)) {
|
||||
this.platformUtilsService.showToast("error", null, this.i18nService.t("accessDenied"));
|
||||
return this.redirect();
|
||||
}
|
||||
|
||||
return true;
|
||||
@@ -1,4 +1,3 @@
|
||||
<app-navbar></app-navbar>
|
||||
<div class="org-nav" *ngIf="organization">
|
||||
<div class="container d-flex">
|
||||
<div class="d-flex flex-column">
|
||||
@@ -27,7 +26,7 @@
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
<ul class="nav nav-tabs" *ngIf="showMenuBar">
|
||||
<ul class="nav nav-tabs">
|
||||
<li class="nav-item">
|
||||
<a class="nav-link" routerLink="vault" routerLinkActive="active">
|
||||
<i class="bwi bwi-lock" aria-hidden="true"></i>
|
||||
@@ -46,7 +45,7 @@
|
||||
{{ "tools" | i18n }}
|
||||
</a>
|
||||
</li>
|
||||
<li class="nav-item" *ngIf="organization.isOwner">
|
||||
<li class="nav-item" *ngIf="showSettingsTab">
|
||||
<a class="nav-link" routerLink="settings" routerLinkActive="active">
|
||||
<i class="bwi bwi-cogs" aria-hidden="true"></i>
|
||||
{{ "settings" | i18n }}
|
||||
@@ -57,4 +56,3 @@
|
||||
</div>
|
||||
</div>
|
||||
<router-outlet></router-outlet>
|
||||
<app-footer></app-footer>
|
||||
@@ -5,6 +5,8 @@ import { BroadcasterService } from "jslib-common/abstractions/broadcaster.servic
|
||||
import { OrganizationService } from "jslib-common/abstractions/organization.service";
|
||||
import { Organization } from "jslib-common/models/domain/organization";
|
||||
|
||||
import { NavigationPermissionsService } from "../services/navigation-permissions.service";
|
||||
|
||||
const BroadcasterSubscriptionId = "OrganizationLayoutComponent";
|
||||
|
||||
@Component({
|
||||
@@ -25,7 +27,7 @@ export class OrganizationLayoutComponent implements OnInit, OnDestroy {
|
||||
|
||||
ngOnInit() {
|
||||
document.body.classList.remove("layout_frontend");
|
||||
this.route.params.subscribe(async (params) => {
|
||||
this.route.params.subscribe(async (params: any) => {
|
||||
this.organizationId = params.organizationId;
|
||||
await this.load();
|
||||
});
|
||||
@@ -48,23 +50,16 @@ export class OrganizationLayoutComponent implements OnInit, OnDestroy {
|
||||
this.organization = await this.organizationService.get(this.organizationId);
|
||||
}
|
||||
|
||||
get showMenuBar() {
|
||||
return this.showManageTab || this.showToolsTab || this.organization.isOwner;
|
||||
}
|
||||
|
||||
get showManageTab(): boolean {
|
||||
return (
|
||||
this.organization.canManageUsers ||
|
||||
this.organization.canViewAllCollections ||
|
||||
this.organization.canViewAssignedCollections ||
|
||||
this.organization.canManageGroups ||
|
||||
this.organization.canManagePolicies ||
|
||||
this.organization.canAccessEventLogs
|
||||
);
|
||||
return NavigationPermissionsService.canAccessManage(this.organization);
|
||||
}
|
||||
|
||||
get showToolsTab(): boolean {
|
||||
return this.organization.canAccessImportExport || this.organization.canAccessReports;
|
||||
return NavigationPermissionsService.canAccessTools(this.organization);
|
||||
}
|
||||
|
||||
get showSettingsTab(): boolean {
|
||||
return NavigationPermissionsService.canAccessSettings(this.organization);
|
||||
}
|
||||
|
||||
get toolsRoute(): string {
|
||||
217
src/app/organizations/organization-routing.module.ts
Normal file
217
src/app/organizations/organization-routing.module.ts
Normal file
@@ -0,0 +1,217 @@
|
||||
import { NgModule } from "@angular/core";
|
||||
import { RouterModule, Routes } from "@angular/router";
|
||||
|
||||
import { AuthGuard } from "jslib-angular/guards/auth.guard";
|
||||
import { Permissions } from "jslib-common/enums/permissions";
|
||||
|
||||
import { PermissionsGuard } from "./guards/permissions.guard";
|
||||
import { OrganizationLayoutComponent } from "./layouts/organization-layout.component";
|
||||
import { CollectionsComponent } from "./manage/collections.component";
|
||||
import { EventsComponent } from "./manage/events.component";
|
||||
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 { AccountComponent } from "./settings/account.component";
|
||||
import { OrganizationBillingComponent } from "./settings/organization-billing.component";
|
||||
import { OrganizationSubscriptionComponent } from "./settings/organization-subscription.component";
|
||||
import { SettingsComponent } from "./settings/settings.component";
|
||||
import { TwoFactorSetupComponent } from "./settings/two-factor-setup.component";
|
||||
import { ExportComponent } from "./tools/export.component";
|
||||
import { ExposedPasswordsReportComponent } from "./tools/exposed-passwords-report.component";
|
||||
import { ImportComponent } from "./tools/import.component";
|
||||
import { InactiveTwoFactorReportComponent } from "./tools/inactive-two-factor-report.component";
|
||||
import { ReusedPasswordsReportComponent } from "./tools/reused-passwords-report.component";
|
||||
import { ToolsComponent } from "./tools/tools.component";
|
||||
import { UnsecuredWebsitesReportComponent } from "./tools/unsecured-websites-report.component";
|
||||
import { WeakPasswordsReportComponent } from "./tools/weak-passwords-report.component";
|
||||
import { VaultComponent } from "./vault/vault.component";
|
||||
|
||||
const routes: Routes = [
|
||||
{
|
||||
path: ":organizationId",
|
||||
component: OrganizationLayoutComponent,
|
||||
canActivate: [AuthGuard, PermissionsGuard],
|
||||
data: {
|
||||
permissions: NavigationPermissionsService.getPermissions("admin"),
|
||||
},
|
||||
children: [
|
||||
{ path: "", pathMatch: "full", redirectTo: "vault" },
|
||||
{ path: "vault", component: VaultComponent, data: { titleId: "vault" } },
|
||||
{
|
||||
path: "tools",
|
||||
component: ToolsComponent,
|
||||
canActivate: [PermissionsGuard],
|
||||
data: { permissions: NavigationPermissionsService.getPermissions("tools") },
|
||||
children: [
|
||||
{
|
||||
path: "",
|
||||
pathMatch: "full",
|
||||
redirectTo: "import",
|
||||
},
|
||||
{
|
||||
path: "import",
|
||||
component: ImportComponent,
|
||||
canActivate: [PermissionsGuard],
|
||||
data: {
|
||||
titleId: "importData",
|
||||
permissions: [Permissions.AccessImportExport],
|
||||
},
|
||||
},
|
||||
{
|
||||
path: "export",
|
||||
component: ExportComponent,
|
||||
canActivate: [PermissionsGuard],
|
||||
data: {
|
||||
titleId: "exportVault",
|
||||
permissions: [Permissions.AccessImportExport],
|
||||
},
|
||||
},
|
||||
{
|
||||
path: "exposed-passwords-report",
|
||||
component: ExposedPasswordsReportComponent,
|
||||
canActivate: [PermissionsGuard],
|
||||
data: {
|
||||
titleId: "exposedPasswordsReport",
|
||||
permissions: [Permissions.AccessReports],
|
||||
},
|
||||
},
|
||||
{
|
||||
path: "inactive-two-factor-report",
|
||||
component: InactiveTwoFactorReportComponent,
|
||||
canActivate: [PermissionsGuard],
|
||||
data: {
|
||||
titleId: "inactive2faReport",
|
||||
permissions: [Permissions.AccessReports],
|
||||
},
|
||||
},
|
||||
{
|
||||
path: "reused-passwords-report",
|
||||
component: ReusedPasswordsReportComponent,
|
||||
canActivate: [PermissionsGuard],
|
||||
data: {
|
||||
titleId: "reusedPasswordsReport",
|
||||
permissions: [Permissions.AccessReports],
|
||||
},
|
||||
},
|
||||
{
|
||||
path: "unsecured-websites-report",
|
||||
component: UnsecuredWebsitesReportComponent,
|
||||
canActivate: [PermissionsGuard],
|
||||
data: {
|
||||
titleId: "unsecuredWebsitesReport",
|
||||
permissions: [Permissions.AccessReports],
|
||||
},
|
||||
},
|
||||
{
|
||||
path: "weak-passwords-report",
|
||||
component: WeakPasswordsReportComponent,
|
||||
canActivate: [PermissionsGuard],
|
||||
data: {
|
||||
titleId: "weakPasswordsReport",
|
||||
permissions: [Permissions.AccessReports],
|
||||
},
|
||||
},
|
||||
],
|
||||
},
|
||||
{
|
||||
path: "manage",
|
||||
component: ManageComponent,
|
||||
canActivate: [PermissionsGuard],
|
||||
data: {
|
||||
permissions: NavigationPermissionsService.getPermissions("manage"),
|
||||
},
|
||||
children: [
|
||||
{
|
||||
path: "",
|
||||
pathMatch: "full",
|
||||
redirectTo: "people",
|
||||
},
|
||||
{
|
||||
path: "collections",
|
||||
component: CollectionsComponent,
|
||||
canActivate: [PermissionsGuard],
|
||||
data: {
|
||||
titleId: "collections",
|
||||
permissions: [
|
||||
Permissions.CreateNewCollections,
|
||||
Permissions.EditAnyCollection,
|
||||
Permissions.DeleteAnyCollection,
|
||||
Permissions.EditAssignedCollections,
|
||||
Permissions.DeleteAssignedCollections,
|
||||
],
|
||||
},
|
||||
},
|
||||
{
|
||||
path: "events",
|
||||
component: EventsComponent,
|
||||
canActivate: [PermissionsGuard],
|
||||
data: {
|
||||
titleId: "eventLogs",
|
||||
permissions: [Permissions.AccessEventLogs],
|
||||
},
|
||||
},
|
||||
{
|
||||
path: "groups",
|
||||
component: GroupsComponent,
|
||||
canActivate: [PermissionsGuard],
|
||||
data: {
|
||||
titleId: "groups",
|
||||
permissions: [Permissions.ManageGroups],
|
||||
},
|
||||
},
|
||||
{
|
||||
path: "people",
|
||||
component: PeopleComponent,
|
||||
canActivate: [PermissionsGuard],
|
||||
data: {
|
||||
titleId: "people",
|
||||
permissions: [Permissions.ManageUsers, Permissions.ManageUsersPassword],
|
||||
},
|
||||
},
|
||||
{
|
||||
path: "policies",
|
||||
component: PoliciesComponent,
|
||||
canActivate: [PermissionsGuard],
|
||||
data: {
|
||||
titleId: "policies",
|
||||
permissions: [Permissions.ManagePolicies],
|
||||
},
|
||||
},
|
||||
],
|
||||
},
|
||||
{
|
||||
path: "settings",
|
||||
component: SettingsComponent,
|
||||
canActivate: [PermissionsGuard],
|
||||
data: { permissions: NavigationPermissionsService.getPermissions("settings") },
|
||||
children: [
|
||||
{ path: "", pathMatch: "full", redirectTo: "account" },
|
||||
{ path: "account", component: AccountComponent, data: { titleId: "myOrganization" } },
|
||||
{
|
||||
path: "two-factor",
|
||||
component: TwoFactorSetupComponent,
|
||||
data: { titleId: "twoStepLogin" },
|
||||
},
|
||||
{
|
||||
path: "billing",
|
||||
component: OrganizationBillingComponent,
|
||||
data: { titleId: "billing" },
|
||||
},
|
||||
{
|
||||
path: "subscription",
|
||||
component: OrganizationSubscriptionComponent,
|
||||
data: { titleId: "subscription" },
|
||||
},
|
||||
],
|
||||
},
|
||||
],
|
||||
},
|
||||
];
|
||||
|
||||
@NgModule({
|
||||
imports: [RouterModule.forChild(routes)],
|
||||
exports: [RouterModule],
|
||||
})
|
||||
export class OrganizationsRoutingModule {}
|
||||
@@ -0,0 +1,48 @@
|
||||
import { Permissions } from "jslib-common/enums/permissions";
|
||||
import { Organization } from "jslib-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,
|
||||
],
|
||||
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"));
|
||||
}
|
||||
}
|
||||
@@ -4,7 +4,6 @@ import { RouterModule, Routes } from "@angular/router";
|
||||
import { AuthGuard } from "jslib-angular/guards/auth.guard";
|
||||
import { LockGuard } from "jslib-angular/guards/lock.guard";
|
||||
import { UnauthGuard } from "jslib-angular/guards/unauth.guard";
|
||||
import { Permissions } from "jslib-common/enums/permissions";
|
||||
|
||||
import { AcceptEmergencyComponent } from "./accounts/accept-emergency.component";
|
||||
import { AcceptOrganizationComponent } from "./accounts/accept-organization.component";
|
||||
@@ -23,33 +22,10 @@ import { UpdateTempPasswordComponent } from "./accounts/update-temp-password.com
|
||||
import { VerifyEmailTokenComponent } from "./accounts/verify-email-token.component";
|
||||
import { VerifyRecoverDeleteComponent } from "./accounts/verify-recover-delete.component";
|
||||
import { FrontendLayoutComponent } from "./layouts/frontend-layout.component";
|
||||
import { OrganizationLayoutComponent } from "./layouts/organization-layout.component";
|
||||
import { UserLayoutComponent } from "./layouts/user-layout.component";
|
||||
import { CollectionsComponent as OrgManageCollectionsComponent } from "./organizations/manage/collections.component";
|
||||
import { EventsComponent as OrgEventsComponent } from "./organizations/manage/events.component";
|
||||
import { GroupsComponent as OrgGroupsComponent } from "./organizations/manage/groups.component";
|
||||
import { ManageComponent as OrgManageComponent } from "./organizations/manage/manage.component";
|
||||
import { PeopleComponent as OrgPeopleComponent } from "./organizations/manage/people.component";
|
||||
import { PoliciesComponent as OrgPoliciesComponent } from "./organizations/manage/policies.component";
|
||||
import { AccountComponent as OrgAccountComponent } from "./organizations/settings/account.component";
|
||||
import { OrganizationBillingComponent } from "./organizations/settings/organization-billing.component";
|
||||
import { OrganizationSubscriptionComponent } from "./organizations/settings/organization-subscription.component";
|
||||
import { SettingsComponent as OrgSettingsComponent } from "./organizations/settings/settings.component";
|
||||
import { TwoFactorSetupComponent as OrgTwoFactorSetupComponent } from "./organizations/settings/two-factor-setup.component";
|
||||
import { FamiliesForEnterpriseSetupComponent } from "./organizations/sponsorships/families-for-enterprise-setup.component";
|
||||
import { ExportComponent as OrgExportComponent } from "./organizations/tools/export.component";
|
||||
import { ExposedPasswordsReportComponent as OrgExposedPasswordsReportComponent } from "./organizations/tools/exposed-passwords-report.component";
|
||||
import { ImportComponent as OrgImportComponent } from "./organizations/tools/import.component";
|
||||
import { InactiveTwoFactorReportComponent as OrgInactiveTwoFactorReportComponent } from "./organizations/tools/inactive-two-factor-report.component";
|
||||
import { ReusedPasswordsReportComponent as OrgReusedPasswordsReportComponent } from "./organizations/tools/reused-passwords-report.component";
|
||||
import { ToolsComponent as OrgToolsComponent } from "./organizations/tools/tools.component";
|
||||
import { UnsecuredWebsitesReportComponent as OrgUnsecuredWebsitesReportComponent } from "./organizations/tools/unsecured-websites-report.component";
|
||||
import { WeakPasswordsReportComponent as OrgWeakPasswordsReportComponent } from "./organizations/tools/weak-passwords-report.component";
|
||||
import { VaultComponent as OrgVaultComponent } from "./organizations/vault/vault.component";
|
||||
import { AccessComponent } from "./send/access.component";
|
||||
import { SendComponent } from "./send/send.component";
|
||||
import { OrganizationGuardService } from "./services/organization-guard.service";
|
||||
import { OrganizationTypeGuardService } from "./services/organization-type-guard.service";
|
||||
import { AccountComponent } from "./settings/account.component";
|
||||
import { CreateOrganizationComponent } from "./settings/create-organization.component";
|
||||
import { DomainRulesComponent } from "./settings/domain-rules.component";
|
||||
@@ -245,191 +221,12 @@ const routes: Routes = [
|
||||
loadChildren: async () => (await import("./reports/reports.module")).ReportsModule,
|
||||
},
|
||||
{ path: "setup/families-for-enterprise", component: FamiliesForEnterpriseSetupComponent },
|
||||
],
|
||||
},
|
||||
{
|
||||
path: "organizations/:organizationId",
|
||||
component: OrganizationLayoutComponent,
|
||||
canActivate: [AuthGuard, OrganizationGuardService],
|
||||
children: [
|
||||
{ path: "", pathMatch: "full", redirectTo: "vault" },
|
||||
{ path: "vault", component: OrgVaultComponent, data: { titleId: "vault" } },
|
||||
{
|
||||
path: "tools",
|
||||
component: OrgToolsComponent,
|
||||
canActivate: [OrganizationTypeGuardService],
|
||||
data: { permissions: [Permissions.AccessImportExport, Permissions.AccessReports] },
|
||||
children: [
|
||||
{
|
||||
path: "",
|
||||
pathMatch: "full",
|
||||
redirectTo: "import",
|
||||
},
|
||||
{
|
||||
path: "import",
|
||||
component: OrgImportComponent,
|
||||
canActivate: [OrganizationTypeGuardService],
|
||||
data: {
|
||||
titleId: "importData",
|
||||
permissions: [Permissions.AccessImportExport],
|
||||
},
|
||||
},
|
||||
{
|
||||
path: "export",
|
||||
component: OrgExportComponent,
|
||||
canActivate: [OrganizationTypeGuardService],
|
||||
data: {
|
||||
titleId: "exportVault",
|
||||
permissions: [Permissions.AccessImportExport],
|
||||
},
|
||||
},
|
||||
{
|
||||
path: "exposed-passwords-report",
|
||||
component: OrgExposedPasswordsReportComponent,
|
||||
canActivate: [OrganizationTypeGuardService],
|
||||
data: {
|
||||
titleId: "exposedPasswordsReport",
|
||||
permissions: [Permissions.AccessReports],
|
||||
},
|
||||
},
|
||||
{
|
||||
path: "inactive-two-factor-report",
|
||||
component: OrgInactiveTwoFactorReportComponent,
|
||||
canActivate: [OrganizationTypeGuardService],
|
||||
data: {
|
||||
titleId: "inactive2faReport",
|
||||
permissions: [Permissions.AccessReports],
|
||||
},
|
||||
},
|
||||
{
|
||||
path: "reused-passwords-report",
|
||||
component: OrgReusedPasswordsReportComponent,
|
||||
canActivate: [OrganizationTypeGuardService],
|
||||
data: {
|
||||
titleId: "reusedPasswordsReport",
|
||||
permissions: [Permissions.AccessReports],
|
||||
},
|
||||
},
|
||||
{
|
||||
path: "unsecured-websites-report",
|
||||
component: OrgUnsecuredWebsitesReportComponent,
|
||||
canActivate: [OrganizationTypeGuardService],
|
||||
data: {
|
||||
titleId: "unsecuredWebsitesReport",
|
||||
permissions: [Permissions.AccessReports],
|
||||
},
|
||||
},
|
||||
{
|
||||
path: "weak-passwords-report",
|
||||
component: OrgWeakPasswordsReportComponent,
|
||||
canActivate: [OrganizationTypeGuardService],
|
||||
data: {
|
||||
titleId: "weakPasswordsReport",
|
||||
permissions: [Permissions.AccessReports],
|
||||
},
|
||||
},
|
||||
],
|
||||
},
|
||||
{
|
||||
path: "manage",
|
||||
component: OrgManageComponent,
|
||||
canActivate: [OrganizationTypeGuardService],
|
||||
data: {
|
||||
permissions: [
|
||||
Permissions.CreateNewCollections,
|
||||
Permissions.EditAnyCollection,
|
||||
Permissions.DeleteAnyCollection,
|
||||
Permissions.EditAssignedCollections,
|
||||
Permissions.DeleteAssignedCollections,
|
||||
Permissions.AccessEventLogs,
|
||||
Permissions.ManageGroups,
|
||||
Permissions.ManageUsers,
|
||||
Permissions.ManagePolicies,
|
||||
],
|
||||
},
|
||||
children: [
|
||||
{
|
||||
path: "",
|
||||
pathMatch: "full",
|
||||
redirectTo: "people",
|
||||
},
|
||||
{
|
||||
path: "collections",
|
||||
component: OrgManageCollectionsComponent,
|
||||
canActivate: [OrganizationTypeGuardService],
|
||||
data: {
|
||||
titleId: "collections",
|
||||
permissions: [
|
||||
Permissions.CreateNewCollections,
|
||||
Permissions.EditAnyCollection,
|
||||
Permissions.DeleteAnyCollection,
|
||||
Permissions.EditAssignedCollections,
|
||||
Permissions.DeleteAssignedCollections,
|
||||
],
|
||||
},
|
||||
},
|
||||
{
|
||||
path: "events",
|
||||
component: OrgEventsComponent,
|
||||
canActivate: [OrganizationTypeGuardService],
|
||||
data: {
|
||||
titleId: "eventLogs",
|
||||
permissions: [Permissions.AccessEventLogs],
|
||||
},
|
||||
},
|
||||
{
|
||||
path: "groups",
|
||||
component: OrgGroupsComponent,
|
||||
canActivate: [OrganizationTypeGuardService],
|
||||
data: {
|
||||
titleId: "groups",
|
||||
permissions: [Permissions.ManageGroups],
|
||||
},
|
||||
},
|
||||
{
|
||||
path: "people",
|
||||
component: OrgPeopleComponent,
|
||||
canActivate: [OrganizationTypeGuardService],
|
||||
data: {
|
||||
titleId: "people",
|
||||
permissions: [Permissions.ManageUsers, Permissions.ManageUsersPassword],
|
||||
},
|
||||
},
|
||||
{
|
||||
path: "policies",
|
||||
component: OrgPoliciesComponent,
|
||||
canActivate: [OrganizationTypeGuardService],
|
||||
data: {
|
||||
titleId: "policies",
|
||||
permissions: [Permissions.ManagePolicies],
|
||||
},
|
||||
},
|
||||
],
|
||||
},
|
||||
{
|
||||
path: "settings",
|
||||
component: OrgSettingsComponent,
|
||||
canActivate: [OrganizationTypeGuardService],
|
||||
data: { permissions: [Permissions.ManageOrganization] },
|
||||
children: [
|
||||
{ path: "", pathMatch: "full", redirectTo: "account" },
|
||||
{ path: "account", component: OrgAccountComponent, data: { titleId: "myOrganization" } },
|
||||
{
|
||||
path: "two-factor",
|
||||
component: OrgTwoFactorSetupComponent,
|
||||
data: { titleId: "twoStepLogin" },
|
||||
},
|
||||
{
|
||||
path: "billing",
|
||||
component: OrganizationBillingComponent,
|
||||
data: { titleId: "billing" },
|
||||
},
|
||||
{
|
||||
path: "subscription",
|
||||
component: OrganizationSubscriptionComponent,
|
||||
data: { titleId: "subscription" },
|
||||
},
|
||||
],
|
||||
path: "organizations",
|
||||
loadChildren: () =>
|
||||
import("./organizations/organization-routing.module").then(
|
||||
(m) => m.OrganizationsRoutingModule
|
||||
),
|
||||
},
|
||||
],
|
||||
},
|
||||
@@ -440,7 +237,7 @@ const routes: Routes = [
|
||||
RouterModule.forRoot(routes, {
|
||||
useHash: true,
|
||||
paramsInheritanceStrategy: "always",
|
||||
/*enableTracing: true,*/
|
||||
// enableTracing: true,
|
||||
}),
|
||||
],
|
||||
exports: [RouterModule],
|
||||
|
||||
@@ -83,8 +83,8 @@ import { PremiumBadgeComponent } from "./components/premium-badge.component";
|
||||
import { FooterComponent } from "./layouts/footer.component";
|
||||
import { FrontendLayoutComponent } from "./layouts/frontend-layout.component";
|
||||
import { NavbarComponent } from "./layouts/navbar.component";
|
||||
import { OrganizationLayoutComponent } from "./layouts/organization-layout.component";
|
||||
import { UserLayoutComponent } from "./layouts/user-layout.component";
|
||||
import { OrganizationLayoutComponent } from "./organizations/layouts/organization-layout.component";
|
||||
import { BulkConfirmComponent as OrgBulkConfirmComponent } from "./organizations/manage/bulk/bulk-confirm.component";
|
||||
import { BulkRemoveComponent as OrgBulkRemoveComponent } from "./organizations/manage/bulk/bulk-remove.component";
|
||||
import { BulkStatusComponent as OrgBulkStatusComponent } from "./organizations/manage/bulk/bulk-status.component";
|
||||
|
||||
@@ -1,40 +0,0 @@
|
||||
import { Injectable } from "@angular/core";
|
||||
import { ActivatedRouteSnapshot, CanActivate, Router } from "@angular/router";
|
||||
|
||||
import { OrganizationService } from "jslib-common/abstractions/organization.service";
|
||||
import { Permissions } from "jslib-common/enums/permissions";
|
||||
|
||||
@Injectable()
|
||||
export class OrganizationTypeGuardService implements CanActivate {
|
||||
constructor(private organizationService: OrganizationService, private router: Router) {}
|
||||
|
||||
async canActivate(route: ActivatedRouteSnapshot) {
|
||||
const org = await this.organizationService.get(route.params.organizationId);
|
||||
const permissions = route.data == null ? null : (route.data.permissions as Permissions[]);
|
||||
|
||||
if (
|
||||
(permissions.indexOf(Permissions.AccessEventLogs) !== -1 && org.canAccessEventLogs) ||
|
||||
(permissions.indexOf(Permissions.AccessImportExport) !== -1 && org.canAccessImportExport) ||
|
||||
(permissions.indexOf(Permissions.AccessReports) !== -1 && org.canAccessReports) ||
|
||||
(permissions.indexOf(Permissions.CreateNewCollections) !== -1 &&
|
||||
org.canCreateNewCollections) ||
|
||||
(permissions.indexOf(Permissions.EditAnyCollection) !== -1 && org.canEditAnyCollection) ||
|
||||
(permissions.indexOf(Permissions.DeleteAnyCollection) !== -1 && org.canDeleteAnyCollection) ||
|
||||
(permissions.indexOf(Permissions.EditAssignedCollections) !== -1 &&
|
||||
org.canEditAssignedCollections) ||
|
||||
(permissions.indexOf(Permissions.DeleteAssignedCollections) !== -1 &&
|
||||
org.canDeleteAssignedCollections) ||
|
||||
(permissions.indexOf(Permissions.ManageGroups) !== -1 && org.canManageGroups) ||
|
||||
(permissions.indexOf(Permissions.ManageOrganization) !== -1 && org.isOwner) ||
|
||||
(permissions.indexOf(Permissions.ManagePolicies) !== -1 && org.canManagePolicies) ||
|
||||
(permissions.indexOf(Permissions.ManageUsers) !== -1 && org.canManageUsers) ||
|
||||
(permissions.indexOf(Permissions.ManageUsersPassword) !== -1 && org.canManageUsersPassword) ||
|
||||
(permissions.indexOf(Permissions.ManageSso) !== -1 && org.canManageSso)
|
||||
) {
|
||||
return true;
|
||||
}
|
||||
|
||||
this.router.navigate(["/organizations", org.id]);
|
||||
return false;
|
||||
}
|
||||
}
|
||||
@@ -45,11 +45,11 @@ import { PasswordRepromptService } from "../../services/passwordReprompt.service
|
||||
import { StateService } from "../../services/state.service";
|
||||
import { StateMigrationService } from "../../services/stateMigration.service";
|
||||
import { WebPlatformUtilsService } from "../../services/webPlatformUtils.service";
|
||||
import { PermissionsGuard as OrgPermissionsGuard } from "../organizations/guards/permissions.guard";
|
||||
import { NavigationPermissionsService as OrgPermissionsService } from "../organizations/services/navigation-permissions.service";
|
||||
|
||||
import { EventService } from "./event.service";
|
||||
import { ModalService } from "./modal.service";
|
||||
import { OrganizationGuardService } from "./organization-guard.service";
|
||||
import { OrganizationTypeGuardService } from "./organization-type-guard.service";
|
||||
import { PolicyListService } from "./policy-list.service";
|
||||
import { RouterService } from "./router.service";
|
||||
|
||||
@@ -100,6 +100,7 @@ export function initFactory(
|
||||
imports: [ToastrModule, JslibServicesModule],
|
||||
declarations: [],
|
||||
providers: [
|
||||
OrgPermissionsService,
|
||||
{
|
||||
provide: APP_INITIALIZER,
|
||||
useFactory: initFactory,
|
||||
@@ -117,8 +118,7 @@ export function initFactory(
|
||||
],
|
||||
multi: true,
|
||||
},
|
||||
OrganizationGuardService,
|
||||
OrganizationTypeGuardService,
|
||||
OrgPermissionsGuard,
|
||||
RouterService,
|
||||
EventService,
|
||||
PolicyListService,
|
||||
|
||||
@@ -4833,6 +4833,9 @@
|
||||
}
|
||||
}
|
||||
},
|
||||
"accessDenied": {
|
||||
"message": "Access Denied. You do not have permission to view this page."
|
||||
},
|
||||
"backToReports": {
|
||||
"message": "Back to Reports"
|
||||
},
|
||||
|
||||
Reference in New Issue
Block a user