mirror of
https://github.com/GNS3/gns3-web-ui.git
synced 2024-12-18 20:47:51 +00:00
Add role management
This commit is contained in:
parent
36e39f908b
commit
920154e7b9
@ -1,107 +1,112 @@
|
||||
import { NgModule } from '@angular/core';
|
||||
import { RouterModule, Routes } from '@angular/router';
|
||||
import { BundledServerFinderComponent } from './components/bundled-server-finder/bundled-server-finder.component';
|
||||
import { DirectLinkComponent } from './components/direct-link/direct-link.component';
|
||||
import { HelpComponent } from './components/help/help.component';
|
||||
import { InstalledSoftwareComponent } from './components/installed-software/installed-software.component';
|
||||
import { LoginComponent } from './components/login/login.component';
|
||||
import { PageNotFoundComponent } from './components/page-not-found/page-not-found.component';
|
||||
import { BuiltInPreferencesComponent } from './components/preferences/built-in/built-in-preferences.component';
|
||||
import { CloudNodesAddTemplateComponent } from './components/preferences/built-in/cloud-nodes/cloud-nodes-add-template/cloud-nodes-add-template.component';
|
||||
import { CloudNodesTemplateDetailsComponent } from './components/preferences/built-in/cloud-nodes/cloud-nodes-template-details/cloud-nodes-template-details.component';
|
||||
import { CloudNodesTemplatesComponent } from './components/preferences/built-in/cloud-nodes/cloud-nodes-templates/cloud-nodes-templates.component';
|
||||
import { EthernetHubsAddTemplateComponent } from './components/preferences/built-in/ethernet-hubs/ethernet-hubs-add-template/ethernet-hubs-add-template.component';
|
||||
import { EthernetHubsTemplateDetailsComponent } from './components/preferences/built-in/ethernet-hubs/ethernet-hubs-template-details/ethernet-hubs-template-details.component';
|
||||
import { EthernetHubsTemplatesComponent } from './components/preferences/built-in/ethernet-hubs/ethernet-hubs-templates/ethernet-hubs-templates.component';
|
||||
import { EthernetSwitchesAddTemplateComponent } from './components/preferences/built-in/ethernet-switches/ethernet-switches-add-template/ethernet-switches-add-template.component';
|
||||
import { EthernetSwitchesTemplateDetailsComponent } from './components/preferences/built-in/ethernet-switches/ethernet-switches-template-details/ethernet-switches-template-details.component';
|
||||
import { EthernetSwitchesTemplatesComponent } from './components/preferences/built-in/ethernet-switches/ethernet-switches-templates/ethernet-switches-templates.component';
|
||||
import { AddDockerTemplateComponent } from './components/preferences/docker/add-docker-template/add-docker-template.component';
|
||||
import { CopyDockerTemplateComponent } from './components/preferences/docker/copy-docker-template/copy-docker-template.component';
|
||||
import { DockerTemplateDetailsComponent } from './components/preferences/docker/docker-template-details/docker-template-details.component';
|
||||
import { DockerTemplatesComponent } from './components/preferences/docker/docker-templates/docker-templates.component';
|
||||
import { AddIosTemplateComponent } from './components/preferences/dynamips/add-ios-template/add-ios-template.component';
|
||||
import { CopyIosTemplateComponent } from './components/preferences/dynamips/copy-ios-template/copy-ios-template.component';
|
||||
import { IosTemplateDetailsComponent } from './components/preferences/dynamips/ios-template-details/ios-template-details.component';
|
||||
import { IosTemplatesComponent } from './components/preferences/dynamips/ios-templates/ios-templates.component';
|
||||
import { AddIouTemplateComponent } from './components/preferences/ios-on-unix/add-iou-template/add-iou-template.component';
|
||||
import { CopyIouTemplateComponent } from './components/preferences/ios-on-unix/copy-iou-template/copy-iou-template.component';
|
||||
import { IouTemplateDetailsComponent } from './components/preferences/ios-on-unix/iou-template-details/iou-template-details.component';
|
||||
import { IouTemplatesComponent } from './components/preferences/ios-on-unix/iou-templates/iou-templates.component';
|
||||
import { PreferencesComponent } from './components/preferences/preferences.component';
|
||||
import { AddQemuVmTemplateComponent } from './components/preferences/qemu/add-qemu-vm-template/add-qemu-vm-template.component';
|
||||
import { CopyQemuVmTemplateComponent } from './components/preferences/qemu/copy-qemu-vm-template/copy-qemu-vm-template.component';
|
||||
import { QemuVmTemplateDetailsComponent } from './components/preferences/qemu/qemu-vm-template-details/qemu-vm-template-details.component';
|
||||
import { QemuVmTemplatesComponent } from './components/preferences/qemu/qemu-vm-templates/qemu-vm-templates.component';
|
||||
import { AddVirtualBoxTemplateComponent } from './components/preferences/virtual-box/add-virtual-box-template/add-virtual-box-template.component';
|
||||
import { VirtualBoxTemplateDetailsComponent } from './components/preferences/virtual-box/virtual-box-template-details/virtual-box-template-details.component';
|
||||
import { VirtualBoxTemplatesComponent } from './components/preferences/virtual-box/virtual-box-templates/virtual-box-templates.component';
|
||||
import { AddVmwareTemplateComponent } from './components/preferences/vmware/add-vmware-template/add-vmware-template.component';
|
||||
import { VmwareTemplateDetailsComponent } from './components/preferences/vmware/vmware-template-details/vmware-template-details.component';
|
||||
import { VmwareTemplatesComponent } from './components/preferences/vmware/vmware-templates/vmware-templates.component';
|
||||
import { AddVpcsTemplateComponent } from './components/preferences/vpcs/add-vpcs-template/add-vpcs-template.component';
|
||||
import { VpcsTemplateDetailsComponent } from './components/preferences/vpcs/vpcs-template-details/vpcs-template-details.component';
|
||||
import { VpcsTemplatesComponent } from './components/preferences/vpcs/vpcs-templates/vpcs-templates.component';
|
||||
import { ProjectMapComponent } from './components/project-map/project-map.component';
|
||||
import { ProjectsComponent } from './components/projects/projects.component';
|
||||
import { ServersComponent } from './components/servers/servers.component';
|
||||
import { ConsoleComponent } from './components/settings/console/console.component';
|
||||
import { SettingsComponent } from './components/settings/settings.component';
|
||||
import { ListOfSnapshotsComponent } from './components/snapshots/list-of-snapshots/list-of-snapshots.component';
|
||||
import { SystemStatusComponent } from './components/system-status/system-status.component';
|
||||
import { WebConsoleFullWindowComponent } from './components/web-console-full-window/web-console-full-window.component';
|
||||
import { ConsoleGuard } from './guards/console-guard';
|
||||
import { LoginGuard } from './guards/login-guard';
|
||||
import { DefaultLayoutComponent } from './layouts/default-layout/default-layout.component';
|
||||
import { ServerResolve } from './resolvers/server-resolve';
|
||||
import { UserManagementComponent } from './components/user-management/user-management.component';
|
||||
import { LoggedUserComponent } from './components/users/logged-user/logged-user.component';
|
||||
import {NgModule} from '@angular/core';
|
||||
import {RouterModule, Routes} from '@angular/router';
|
||||
import {BundledServerFinderComponent} from './components/bundled-server-finder/bundled-server-finder.component';
|
||||
import {DirectLinkComponent} from './components/direct-link/direct-link.component';
|
||||
import {HelpComponent} from './components/help/help.component';
|
||||
import {InstalledSoftwareComponent} from './components/installed-software/installed-software.component';
|
||||
import {LoginComponent} from './components/login/login.component';
|
||||
import {PageNotFoundComponent} from './components/page-not-found/page-not-found.component';
|
||||
import {BuiltInPreferencesComponent} from './components/preferences/built-in/built-in-preferences.component';
|
||||
import {CloudNodesAddTemplateComponent} from './components/preferences/built-in/cloud-nodes/cloud-nodes-add-template/cloud-nodes-add-template.component';
|
||||
import {CloudNodesTemplateDetailsComponent} from './components/preferences/built-in/cloud-nodes/cloud-nodes-template-details/cloud-nodes-template-details.component';
|
||||
import {CloudNodesTemplatesComponent} from './components/preferences/built-in/cloud-nodes/cloud-nodes-templates/cloud-nodes-templates.component';
|
||||
import {EthernetHubsAddTemplateComponent} from './components/preferences/built-in/ethernet-hubs/ethernet-hubs-add-template/ethernet-hubs-add-template.component';
|
||||
import {EthernetHubsTemplateDetailsComponent} from './components/preferences/built-in/ethernet-hubs/ethernet-hubs-template-details/ethernet-hubs-template-details.component';
|
||||
import {EthernetHubsTemplatesComponent} from './components/preferences/built-in/ethernet-hubs/ethernet-hubs-templates/ethernet-hubs-templates.component';
|
||||
import {EthernetSwitchesAddTemplateComponent} from './components/preferences/built-in/ethernet-switches/ethernet-switches-add-template/ethernet-switches-add-template.component';
|
||||
import {EthernetSwitchesTemplateDetailsComponent} from './components/preferences/built-in/ethernet-switches/ethernet-switches-template-details/ethernet-switches-template-details.component';
|
||||
import {EthernetSwitchesTemplatesComponent} from './components/preferences/built-in/ethernet-switches/ethernet-switches-templates/ethernet-switches-templates.component';
|
||||
import {AddDockerTemplateComponent} from './components/preferences/docker/add-docker-template/add-docker-template.component';
|
||||
import {CopyDockerTemplateComponent} from './components/preferences/docker/copy-docker-template/copy-docker-template.component';
|
||||
import {DockerTemplateDetailsComponent} from './components/preferences/docker/docker-template-details/docker-template-details.component';
|
||||
import {DockerTemplatesComponent} from './components/preferences/docker/docker-templates/docker-templates.component';
|
||||
import {AddIosTemplateComponent} from './components/preferences/dynamips/add-ios-template/add-ios-template.component';
|
||||
import {CopyIosTemplateComponent} from './components/preferences/dynamips/copy-ios-template/copy-ios-template.component';
|
||||
import {IosTemplateDetailsComponent} from './components/preferences/dynamips/ios-template-details/ios-template-details.component';
|
||||
import {IosTemplatesComponent} from './components/preferences/dynamips/ios-templates/ios-templates.component';
|
||||
import {AddIouTemplateComponent} from './components/preferences/ios-on-unix/add-iou-template/add-iou-template.component';
|
||||
import {CopyIouTemplateComponent} from './components/preferences/ios-on-unix/copy-iou-template/copy-iou-template.component';
|
||||
import {IouTemplateDetailsComponent} from './components/preferences/ios-on-unix/iou-template-details/iou-template-details.component';
|
||||
import {IouTemplatesComponent} from './components/preferences/ios-on-unix/iou-templates/iou-templates.component';
|
||||
import {PreferencesComponent} from './components/preferences/preferences.component';
|
||||
import {AddQemuVmTemplateComponent} from './components/preferences/qemu/add-qemu-vm-template/add-qemu-vm-template.component';
|
||||
import {CopyQemuVmTemplateComponent} from './components/preferences/qemu/copy-qemu-vm-template/copy-qemu-vm-template.component';
|
||||
import {QemuVmTemplateDetailsComponent} from './components/preferences/qemu/qemu-vm-template-details/qemu-vm-template-details.component';
|
||||
import {QemuVmTemplatesComponent} from './components/preferences/qemu/qemu-vm-templates/qemu-vm-templates.component';
|
||||
import {AddVirtualBoxTemplateComponent} from './components/preferences/virtual-box/add-virtual-box-template/add-virtual-box-template.component';
|
||||
import {VirtualBoxTemplateDetailsComponent} from './components/preferences/virtual-box/virtual-box-template-details/virtual-box-template-details.component';
|
||||
import {VirtualBoxTemplatesComponent} from './components/preferences/virtual-box/virtual-box-templates/virtual-box-templates.component';
|
||||
import {AddVmwareTemplateComponent} from './components/preferences/vmware/add-vmware-template/add-vmware-template.component';
|
||||
import {VmwareTemplateDetailsComponent} from './components/preferences/vmware/vmware-template-details/vmware-template-details.component';
|
||||
import {VmwareTemplatesComponent} from './components/preferences/vmware/vmware-templates/vmware-templates.component';
|
||||
import {AddVpcsTemplateComponent} from './components/preferences/vpcs/add-vpcs-template/add-vpcs-template.component';
|
||||
import {VpcsTemplateDetailsComponent} from './components/preferences/vpcs/vpcs-template-details/vpcs-template-details.component';
|
||||
import {VpcsTemplatesComponent} from './components/preferences/vpcs/vpcs-templates/vpcs-templates.component';
|
||||
import {ProjectMapComponent} from './components/project-map/project-map.component';
|
||||
import {ProjectsComponent} from './components/projects/projects.component';
|
||||
import {ServersComponent} from './components/servers/servers.component';
|
||||
import {ConsoleComponent} from './components/settings/console/console.component';
|
||||
import {SettingsComponent} from './components/settings/settings.component';
|
||||
import {ListOfSnapshotsComponent} from './components/snapshots/list-of-snapshots/list-of-snapshots.component';
|
||||
import {SystemStatusComponent} from './components/system-status/system-status.component';
|
||||
import {WebConsoleFullWindowComponent} from './components/web-console-full-window/web-console-full-window.component';
|
||||
import {ConsoleGuard} from './guards/console-guard';
|
||||
import {LoginGuard} from './guards/login-guard';
|
||||
import {DefaultLayoutComponent} from './layouts/default-layout/default-layout.component';
|
||||
import {ServerResolve} from './resolvers/server-resolve';
|
||||
import {UserManagementComponent} from './components/user-management/user-management.component';
|
||||
import {LoggedUserComponent} from './components/users/logged-user/logged-user.component';
|
||||
import {GroupManagementComponent} from "./components/group-management/group-management.component";
|
||||
import {GroupDetailsComponent} from "@components/group-details/group-details.component";
|
||||
import {UserDetailComponent} from "@components/user-management/user-detail/user-detail.component";
|
||||
import {GroupDetailsResolver} from "@resolvers/group-details.resolver";
|
||||
import {ManagementComponent} from "@components/management/management.component";
|
||||
import {RoleManagementComponent} from "@components/role-management/role-management.component";
|
||||
import {RoleDetailComponent} from "@components/role-management/role-detail/role-detail.component";
|
||||
import {RoleDetailResolver} from "@resolvers/role-detail.resolver";
|
||||
import {PermissionEditorComponent} from "@components/role-management/role-detail/permission-editor/permission-editor.component";
|
||||
import {PermissionResolver} from "@resolvers/permission.resolver";
|
||||
|
||||
const routes: Routes = [
|
||||
{
|
||||
path: '',
|
||||
component: DefaultLayoutComponent,
|
||||
children: [
|
||||
{ path: '', redirectTo: 'servers', pathMatch: 'full' },
|
||||
{ path: 'servers', component: ServersComponent },
|
||||
{ path: 'bundled', component: BundledServerFinderComponent },
|
||||
{ path: 'server/:server_id/login', component: LoginComponent },
|
||||
{ path: 'server/:server_id/loggeduser', component: LoggedUserComponent },
|
||||
{path: '', redirectTo: 'servers', pathMatch: 'full'},
|
||||
{path: 'servers', component: ServersComponent},
|
||||
{path: 'bundled', component: BundledServerFinderComponent},
|
||||
{path: 'server/:server_id/login', component: LoginComponent},
|
||||
{path: 'server/:server_id/loggeduser', component: LoggedUserComponent},
|
||||
{
|
||||
path: 'server/:server_id/projects',
|
||||
component: ProjectsComponent,
|
||||
canActivate: [LoginGuard],
|
||||
resolve: { server: ServerResolve },
|
||||
resolve: {server: ServerResolve},
|
||||
},
|
||||
{ path: 'help', component: HelpComponent },
|
||||
{ path: 'settings', component: SettingsComponent },
|
||||
{ path: 'settings/console', component: ConsoleComponent },
|
||||
{path: 'help', component: HelpComponent},
|
||||
{path: 'settings', component: SettingsComponent},
|
||||
{path: 'settings/console', component: ConsoleComponent},
|
||||
{
|
||||
path: 'server/:server_id/management/users/:user_id',
|
||||
component: UserDetailComponent,
|
||||
canActivate: [LoginGuard],
|
||||
resolve: { server: ServerResolve },
|
||||
resolve: {server: ServerResolve},
|
||||
},
|
||||
{ path: 'installed-software', component: InstalledSoftwareComponent },
|
||||
{ path: 'server/:server_id/systemstatus', component: SystemStatusComponent, canActivate: [LoginGuard] },
|
||||
{path: 'installed-software', component: InstalledSoftwareComponent},
|
||||
{path: 'server/:server_id/systemstatus', component: SystemStatusComponent, canActivate: [LoginGuard]},
|
||||
|
||||
{ path: 'server/:server_ip/:server_port/project/:project_id', component: DirectLinkComponent, canActivate: [LoginGuard] },
|
||||
{path: 'server/:server_ip/:server_port/project/:project_id', component: DirectLinkComponent, canActivate: [LoginGuard]},
|
||||
{
|
||||
path: 'server/:server_id/project/:project_id/snapshots',
|
||||
component: ListOfSnapshotsComponent,
|
||||
canActivate: [LoginGuard],
|
||||
resolve: { server: ServerResolve },
|
||||
resolve: {server: ServerResolve},
|
||||
},
|
||||
{ path: 'server/:server_id/preferences', component: PreferencesComponent, canActivate: [LoginGuard] },
|
||||
{path: 'server/:server_id/preferences', component: PreferencesComponent, canActivate: [LoginGuard]},
|
||||
// { path: 'server/:server_id/preferences/general', component: GeneralPreferencesComponent },
|
||||
{ path: 'server/:server_id/preferences/builtin', component: BuiltInPreferencesComponent, canActivate: [LoginGuard] },
|
||||
{path: 'server/:server_id/preferences/builtin', component: BuiltInPreferencesComponent, canActivate: [LoginGuard]},
|
||||
|
||||
{ path: 'server/:server_id/preferences/builtin/ethernet-hubs', component: EthernetHubsTemplatesComponent, canActivate: [LoginGuard] },
|
||||
{path: 'server/:server_id/preferences/builtin/ethernet-hubs', component: EthernetHubsTemplatesComponent, canActivate: [LoginGuard]},
|
||||
{
|
||||
path: 'server/:server_id/preferences/builtin/ethernet-hubs/addtemplate',
|
||||
component: EthernetHubsAddTemplateComponent,
|
||||
@ -129,7 +134,7 @@ const routes: Routes = [
|
||||
canActivate: [LoginGuard]
|
||||
},
|
||||
|
||||
{ path: 'server/:server_id/preferences/builtin/cloud-nodes', component: CloudNodesTemplatesComponent, canActivate: [LoginGuard] },
|
||||
{path: 'server/:server_id/preferences/builtin/cloud-nodes', component: CloudNodesTemplatesComponent, canActivate: [LoginGuard]},
|
||||
{
|
||||
path: 'server/:server_id/preferences/builtin/cloud-nodes/addtemplate',
|
||||
component: CloudNodesAddTemplateComponent,
|
||||
@ -142,9 +147,13 @@ const routes: Routes = [
|
||||
},
|
||||
|
||||
//{ path: 'server/:server_id/preferences/dynamips', component: DynamipsPreferencesComponent },
|
||||
{ path: 'server/:server_id/preferences/dynamips/templates', component: IosTemplatesComponent, canActivate: [LoginGuard] },
|
||||
{ path: 'server/:server_id/preferences/dynamips/templates/addtemplate', component: AddIosTemplateComponent, canActivate: [LoginGuard] },
|
||||
{ path: 'server/:server_id/preferences/dynamips/templates/:template_id', component: IosTemplateDetailsComponent, canActivate: [LoginGuard] },
|
||||
{path: 'server/:server_id/preferences/dynamips/templates', component: IosTemplatesComponent, canActivate: [LoginGuard]},
|
||||
{path: 'server/:server_id/preferences/dynamips/templates/addtemplate', component: AddIosTemplateComponent, canActivate: [LoginGuard]},
|
||||
{
|
||||
path: 'server/:server_id/preferences/dynamips/templates/:template_id',
|
||||
component: IosTemplateDetailsComponent,
|
||||
canActivate: [LoginGuard]
|
||||
},
|
||||
{
|
||||
path: 'server/:server_id/preferences/dynamips/templates/:template_id/copy',
|
||||
component: CopyIosTemplateComponent,
|
||||
@ -152,39 +161,47 @@ const routes: Routes = [
|
||||
},
|
||||
|
||||
// { path: 'server/:server_id/preferences/qemu', component: QemuPreferencesComponent },
|
||||
{ path: 'server/:server_id/preferences/qemu/templates', component: QemuVmTemplatesComponent, canActivate: [LoginGuard] },
|
||||
{path: 'server/:server_id/preferences/qemu/templates', component: QemuVmTemplatesComponent, canActivate: [LoginGuard]},
|
||||
{
|
||||
path: 'server/:server_id/preferences/qemu/templates/:template_id/copy',
|
||||
component: CopyQemuVmTemplateComponent,
|
||||
canActivate: [LoginGuard]
|
||||
},
|
||||
{ path: 'server/:server_id/preferences/qemu/templates/:template_id', component: QemuVmTemplateDetailsComponent, canActivate: [LoginGuard] },
|
||||
{ path: 'server/:server_id/preferences/qemu/addtemplate', component: AddQemuVmTemplateComponent, canActivate: [LoginGuard] },
|
||||
{
|
||||
path: 'server/:server_id/preferences/qemu/templates/:template_id',
|
||||
component: QemuVmTemplateDetailsComponent,
|
||||
canActivate: [LoginGuard]
|
||||
},
|
||||
{path: 'server/:server_id/preferences/qemu/addtemplate', component: AddQemuVmTemplateComponent, canActivate: [LoginGuard]},
|
||||
|
||||
// { path: 'server/:server_id/preferences/vpcs', component: VpcsPreferencesComponent },
|
||||
{ path: 'server/:server_id/preferences/vpcs/templates', component: VpcsTemplatesComponent, canActivate: [LoginGuard] },
|
||||
{ path: 'server/:server_id/preferences/vpcs/templates/:template_id', component: VpcsTemplateDetailsComponent, canActivate: [LoginGuard] },
|
||||
{ path: 'server/:server_id/preferences/vpcs/addtemplate', component: AddVpcsTemplateComponent, canActivate: [LoginGuard] },
|
||||
{path: 'server/:server_id/preferences/vpcs/templates', component: VpcsTemplatesComponent, canActivate: [LoginGuard]},
|
||||
{
|
||||
path: 'server/:server_id/preferences/vpcs/templates/:template_id',
|
||||
component: VpcsTemplateDetailsComponent,
|
||||
canActivate: [LoginGuard]
|
||||
},
|
||||
{path: 'server/:server_id/preferences/vpcs/addtemplate', component: AddVpcsTemplateComponent, canActivate: [LoginGuard]},
|
||||
|
||||
// { path: 'server/:server_id/preferences/virtualbox', component: VirtualBoxPreferencesComponent },
|
||||
{ path: 'server/:server_id/preferences/virtualbox/templates', component: VirtualBoxTemplatesComponent, canActivate: [LoginGuard] },
|
||||
{path: 'server/:server_id/preferences/virtualbox/templates', component: VirtualBoxTemplatesComponent, canActivate: [LoginGuard]},
|
||||
{
|
||||
path: 'server/:server_id/preferences/virtualbox/templates/:template_id',
|
||||
component: VirtualBoxTemplateDetailsComponent,
|
||||
canActivate: [LoginGuard]
|
||||
},
|
||||
{ path: 'server/:server_id/preferences/virtualbox/addtemplate', component: AddVirtualBoxTemplateComponent, canActivate: [LoginGuard] },
|
||||
{path: 'server/:server_id/preferences/virtualbox/addtemplate', component: AddVirtualBoxTemplateComponent, canActivate: [LoginGuard]},
|
||||
|
||||
// { path: 'server/:server_id/preferences/vmware', component: VmwarePreferencesComponent },
|
||||
{ path: 'server/:server_id/preferences/vmware/templates', component: VmwareTemplatesComponent, canActivate: [LoginGuard] },
|
||||
{path: 'server/:server_id/preferences/vmware/templates', component: VmwareTemplatesComponent, canActivate: [LoginGuard]},
|
||||
{
|
||||
path: 'server/:server_id/preferences/vmware/templates/:template_id',
|
||||
component: VmwareTemplateDetailsComponent,
|
||||
canActivate: [LoginGuard]
|
||||
},
|
||||
{ path: 'server/:server_id/preferences/vmware/addtemplate', component: AddVmwareTemplateComponent, canActivate: [LoginGuard] },
|
||||
{path: 'server/:server_id/preferences/vmware/addtemplate', component: AddVmwareTemplateComponent, canActivate: [LoginGuard]},
|
||||
|
||||
{ path: 'server/:server_id/preferences/docker/templates', component: DockerTemplatesComponent, canActivate: [LoginGuard] },
|
||||
{path: 'server/:server_id/preferences/docker/templates', component: DockerTemplatesComponent, canActivate: [LoginGuard]},
|
||||
{
|
||||
path: 'server/:server_id/preferences/docker/templates/:template_id',
|
||||
component: DockerTemplateDetailsComponent,
|
||||
@ -195,27 +212,58 @@ const routes: Routes = [
|
||||
component: CopyDockerTemplateComponent,
|
||||
canActivate: [LoginGuard]
|
||||
},
|
||||
{ path: 'server/:server_id/preferences/docker/addtemplate', component: AddDockerTemplateComponent, canActivate: [LoginGuard] },
|
||||
{path: 'server/:server_id/preferences/docker/addtemplate', component: AddDockerTemplateComponent, canActivate: [LoginGuard]},
|
||||
|
||||
{ path: 'server/:server_id/preferences/iou/templates', component: IouTemplatesComponent, canActivate: [LoginGuard] },
|
||||
{ path: 'server/:server_id/preferences/iou/templates/:template_id', component: IouTemplateDetailsComponent, canActivate: [LoginGuard] },
|
||||
{ path: 'server/:server_id/preferences/iou/templates/:template_id/copy', component: CopyIouTemplateComponent, canActivate: [LoginGuard] },
|
||||
{ path: 'server/:server_id/preferences/iou/addtemplate', component: AddIouTemplateComponent, canActivate: [LoginGuard] },
|
||||
{path: 'server/:server_id/preferences/iou/templates', component: IouTemplatesComponent, canActivate: [LoginGuard]},
|
||||
{path: 'server/:server_id/preferences/iou/templates/:template_id', component: IouTemplateDetailsComponent, canActivate: [LoginGuard]},
|
||||
{
|
||||
path: 'server/:server_id/preferences/iou/templates/:template_id/copy',
|
||||
component: CopyIouTemplateComponent,
|
||||
canActivate: [LoginGuard]
|
||||
},
|
||||
{path: 'server/:server_id/preferences/iou/addtemplate', component: AddIouTemplateComponent, canActivate: [LoginGuard]},
|
||||
{
|
||||
path: 'server/:server_id/management',
|
||||
component: ManagementComponent,
|
||||
children: [
|
||||
{
|
||||
path: 'users',
|
||||
component: UserManagementComponent
|
||||
},
|
||||
{
|
||||
path: 'groups',
|
||||
component: GroupManagementComponent
|
||||
children: [
|
||||
{
|
||||
path: 'users',
|
||||
component: UserManagementComponent
|
||||
},
|
||||
{
|
||||
path: 'groups',
|
||||
component: GroupManagementComponent
|
||||
},
|
||||
{
|
||||
path: 'roles',
|
||||
component: RoleManagementComponent
|
||||
}
|
||||
]
|
||||
},
|
||||
{
|
||||
path: 'server/:server_id/management/groups/:user_group_id',
|
||||
component: GroupDetailsComponent,
|
||||
resolve: {
|
||||
group: GroupDetailsResolver
|
||||
}
|
||||
]},
|
||||
{ path: 'server/:server_id/management/groups/:user_group_id', component: GroupDetailsComponent, resolve: {group: GroupDetailsResolver}},
|
||||
|
||||
},
|
||||
{
|
||||
path: 'server/:server_id/management/roles/:role_id',
|
||||
component: RoleDetailComponent,
|
||||
resolve: {
|
||||
role: RoleDetailResolver,
|
||||
server: ServerResolve
|
||||
}
|
||||
},
|
||||
{
|
||||
path: 'server/:server_id/management/roles/:role_id/permissions',
|
||||
component: PermissionEditorComponent,
|
||||
resolve: {
|
||||
role: RoleDetailResolver,
|
||||
server: ServerResolve,
|
||||
permissions: PermissionResolver
|
||||
}
|
||||
},
|
||||
],
|
||||
},
|
||||
{
|
||||
@ -251,4 +299,5 @@ const routes: Routes = [
|
||||
],
|
||||
exports: [RouterModule],
|
||||
})
|
||||
export class AppRoutingModule {}
|
||||
export class AppRoutingModule {
|
||||
}
|
||||
|
@ -287,6 +287,14 @@ import { RemoveUserToGroupDialogComponent } from './components/group-details/rem
|
||||
import { PaginatorPipe } from './components/group-details/paginator.pipe';
|
||||
import { MembersFilterPipe } from './components/group-details/members-filter.pipe';
|
||||
import { ManagementComponent } from './components/management/management.component';
|
||||
import { RoleManagementComponent } from './components/role-management/role-management.component';
|
||||
import { RoleFilterPipe } from './components/role-management/role-filter.pipe';
|
||||
import { AddRoleDialogComponent } from './components/role-management/add-role-dialog/add-role-dialog.component';
|
||||
import { DeleteRoleDialogComponent } from './components/role-management/delete-role-dialog/delete-role-dialog.component';
|
||||
import { RoleDetailComponent } from './components/role-management/role-detail/role-detail.component';
|
||||
import { PermissionEditorComponent } from './components/role-management/role-detail/permission-editor/permission-editor.component';
|
||||
import { EditablePermissionComponent } from './components/role-management/role-detail/permission-editor/editable-permission/editable-permission.component';
|
||||
import { PermissionEditorValidateDialogComponent } from './components/role-management/role-detail/permission-editor/permission-editor-validate-dialog/permission-editor-validate-dialog.component';
|
||||
|
||||
@NgModule({
|
||||
declarations: [
|
||||
@ -488,7 +496,15 @@ import { ManagementComponent } from './components/management/management.componen
|
||||
RemoveUserToGroupDialogComponent,
|
||||
PaginatorPipe,
|
||||
MembersFilterPipe,
|
||||
ManagementComponent
|
||||
ManagementComponent,
|
||||
RoleManagementComponent,
|
||||
RoleFilterPipe,
|
||||
AddRoleDialogComponent,
|
||||
DeleteRoleDialogComponent,
|
||||
RoleDetailComponent,
|
||||
PermissionEditorComponent,
|
||||
EditablePermissionComponent,
|
||||
PermissionEditorValidateDialogComponent,
|
||||
],
|
||||
imports: [
|
||||
BrowserModule,
|
||||
|
@ -23,7 +23,7 @@ import {ServerService} from "@services/server.service";
|
||||
export class ManagementComponent implements OnInit {
|
||||
|
||||
server: Server;
|
||||
links = ['users', 'groups'];
|
||||
links = ['users', 'groups', 'roles'];
|
||||
activeLink: string = this.links[0];
|
||||
|
||||
constructor(
|
||||
|
@ -0,0 +1,30 @@
|
||||
<h1 mat-dialog-title>Create new role</h1>
|
||||
<form [formGroup]="roleNameForm" class="file-name-form">
|
||||
<mat-form-field>
|
||||
<input
|
||||
matInput
|
||||
type="text"
|
||||
formControlName="name"
|
||||
[ngClass]="{ 'is-invalid': form.name?.errors }"
|
||||
placeholder="Please enter role name"/>
|
||||
<mat-error *ngIf="form.name?.touched && form.name?.errors && form.name?.errors.required">
|
||||
role name is required
|
||||
</mat-error>
|
||||
<mat-error *ngIf="form.name?.errors && form.name?.errors.invalidName">
|
||||
Role name is incorrect
|
||||
</mat-error>
|
||||
</mat-form-field>
|
||||
<mat-form-field>
|
||||
<input
|
||||
matInput
|
||||
type="text"
|
||||
formControlName="description"
|
||||
placeholder="Please enter a description"/>
|
||||
</mat-form-field>
|
||||
<div mat-dialog-actions>
|
||||
<button mat-button (click)="onNoClick()" color="accent">Cancel</button>
|
||||
<button mat-button (click)="onAddClick()" tabindex="2" class="add-project-button" mat-raised-button color="primary">
|
||||
Add Role
|
||||
</button>
|
||||
</div>
|
||||
</form>
|
@ -0,0 +1,7 @@
|
||||
mat-form-field {
|
||||
width: 100%;
|
||||
}
|
||||
|
||||
.project-snackbar {
|
||||
background: #2196f3;
|
||||
}
|
@ -0,0 +1,25 @@
|
||||
import { ComponentFixture, TestBed } from '@angular/core/testing';
|
||||
|
||||
import { AddRoleDialogComponent } from './add-role-dialog.component';
|
||||
|
||||
describe('AddRoleDialogComponent', () => {
|
||||
let component: AddRoleDialogComponent;
|
||||
let fixture: ComponentFixture<AddRoleDialogComponent>;
|
||||
|
||||
beforeEach(async () => {
|
||||
await TestBed.configureTestingModule({
|
||||
declarations: [ AddRoleDialogComponent ]
|
||||
})
|
||||
.compileComponents();
|
||||
});
|
||||
|
||||
beforeEach(() => {
|
||||
fixture = TestBed.createComponent(AddRoleDialogComponent);
|
||||
component = fixture.componentInstance;
|
||||
fixture.detectChanges();
|
||||
});
|
||||
|
||||
it('should create', () => {
|
||||
expect(component).toBeTruthy();
|
||||
});
|
||||
});
|
@ -0,0 +1,48 @@
|
||||
import {Component, Inject, OnInit} from '@angular/core';
|
||||
import {FormBuilder, FormControl, FormGroup, Validators} from "@angular/forms";
|
||||
import {MAT_DIALOG_DATA, MatDialogRef} from "@angular/material/dialog";
|
||||
import {Server} from "@models/server";
|
||||
import {GroupNameValidator} from "@components/group-management/add-group-dialog/GroupNameValidator";
|
||||
import {GroupService} from "@services/group.service";
|
||||
import {groupNameAsyncValidator} from "@components/group-management/add-group-dialog/groupNameAsyncValidator";
|
||||
|
||||
@Component({
|
||||
selector: 'app-add-role-dialog',
|
||||
templateUrl: './add-role-dialog.component.html',
|
||||
styleUrls: ['./add-role-dialog.component.scss']
|
||||
})
|
||||
export class AddRoleDialogComponent implements OnInit {
|
||||
|
||||
roleNameForm: FormGroup;
|
||||
|
||||
constructor(private dialogRef: MatDialogRef<AddRoleDialogComponent>,
|
||||
@Inject(MAT_DIALOG_DATA) public data: { server: Server },
|
||||
private formBuilder: FormBuilder) {
|
||||
}
|
||||
|
||||
ngOnInit(): void {
|
||||
this.roleNameForm = this.formBuilder.group({
|
||||
name: new FormControl(),
|
||||
description: new FormControl()
|
||||
});
|
||||
}
|
||||
|
||||
get form() {
|
||||
return this.roleNameForm.controls;
|
||||
}
|
||||
|
||||
onAddClick() {
|
||||
if (this.roleNameForm.invalid) {
|
||||
return;
|
||||
}
|
||||
const roleName = this.roleNameForm.controls['name'].value;
|
||||
const description = this.roleNameForm.controls['description'].value;
|
||||
this.dialogRef.close({name: roleName, description});
|
||||
}
|
||||
|
||||
onNoClick() {
|
||||
this.dialogRef.close();
|
||||
}
|
||||
|
||||
|
||||
}
|
@ -0,0 +1,8 @@
|
||||
<h1 mat-dialog-title>Are you sure to delete role named: </h1>
|
||||
<p *ngFor="let role of data.roles">{{role.name}}</p>
|
||||
<div mat-dialog-actions>
|
||||
<button mat-button (click)="onCancel()" color="accent">No, cancel</button>
|
||||
<button mat-button (click)="onDelete()" tabindex="2" class="add-project-button" mat-raised-button color="primary">
|
||||
Yes, delete!
|
||||
</button>
|
||||
</div>
|
@ -0,0 +1,6 @@
|
||||
:host {
|
||||
display: flex;
|
||||
flex-direction: column;
|
||||
align-items: center;
|
||||
justify-content: center;
|
||||
}
|
@ -0,0 +1,25 @@
|
||||
import { ComponentFixture, TestBed } from '@angular/core/testing';
|
||||
|
||||
import { DeleteRoleDialogComponent } from './delete-role-dialog.component';
|
||||
|
||||
describe('DeleteRoleDialogComponent', () => {
|
||||
let component: DeleteRoleDialogComponent;
|
||||
let fixture: ComponentFixture<DeleteRoleDialogComponent>;
|
||||
|
||||
beforeEach(async () => {
|
||||
await TestBed.configureTestingModule({
|
||||
declarations: [ DeleteRoleDialogComponent ]
|
||||
})
|
||||
.compileComponents();
|
||||
});
|
||||
|
||||
beforeEach(() => {
|
||||
fixture = TestBed.createComponent(DeleteRoleDialogComponent);
|
||||
component = fixture.componentInstance;
|
||||
fixture.detectChanges();
|
||||
});
|
||||
|
||||
it('should create', () => {
|
||||
expect(component).toBeTruthy();
|
||||
});
|
||||
});
|
@ -0,0 +1,27 @@
|
||||
import {Component, Inject, OnInit} from '@angular/core';
|
||||
import {MAT_DIALOG_DATA, MatDialogRef} from "@angular/material/dialog";
|
||||
import {Role} from "@models/api/role";
|
||||
|
||||
@Component({
|
||||
selector: 'app-delete-role-dialog',
|
||||
templateUrl: './delete-role-dialog.component.html',
|
||||
styleUrls: ['./delete-role-dialog.component.scss']
|
||||
})
|
||||
export class DeleteRoleDialogComponent implements OnInit {
|
||||
|
||||
constructor(private dialogRef: MatDialogRef<DeleteRoleDialogComponent>,
|
||||
@Inject(MAT_DIALOG_DATA) public data: { roles: Role[] }) { }
|
||||
|
||||
ngOnInit(): void {
|
||||
}
|
||||
|
||||
onCancel() {
|
||||
this.dialogRef.close();
|
||||
}
|
||||
|
||||
onDelete() {
|
||||
this.dialogRef.close(true);
|
||||
}
|
||||
|
||||
|
||||
}
|
@ -0,0 +1,14 @@
|
||||
<div [matTooltip]="getToolTip()"
|
||||
matTooltipClass="permission-tooltip"
|
||||
class="box" [ngClass]="{allow: permission.action === 'ALLOW', left: side === 'LEFT'}">
|
||||
<button *ngIf="side === 'RIGHT'" mat-button (click)="onClick()">
|
||||
<mat-icon>keyboard_arrow_left</mat-icon>
|
||||
</button>
|
||||
<div class="content">
|
||||
<div class="center">{{permission.methods.join(",")}}</div>
|
||||
<div class="center">{{permission.path}}</div>
|
||||
</div>
|
||||
<button *ngIf="side === 'LEFT'" mat-button (click)="onClick()">
|
||||
<mat-icon>keyboard_arrow_right</mat-icon>
|
||||
</button>
|
||||
</div>
|
@ -0,0 +1,42 @@
|
||||
.box {
|
||||
display: flex;
|
||||
flex-direction: row;
|
||||
border: 1px solid;
|
||||
border-radius: 20px;
|
||||
margin: 10px;
|
||||
font-size: 12px;
|
||||
font-family: monospace;
|
||||
justify-items: center;
|
||||
background-color: rgba(130, 8, 8, 0.36);
|
||||
justify-content: flex-start;
|
||||
}
|
||||
|
||||
|
||||
|
||||
.left {
|
||||
justify-content: flex-end;
|
||||
}
|
||||
|
||||
.allow {
|
||||
background-color: rgba(5, 76, 5, 0.38);
|
||||
}
|
||||
|
||||
.content {
|
||||
width: 100%;
|
||||
display: flex;
|
||||
flex-direction: row;
|
||||
justify-content: space-around;
|
||||
}
|
||||
|
||||
.content > div {
|
||||
padding-right: 20px;
|
||||
}
|
||||
|
||||
.center {
|
||||
display: flex;
|
||||
align-items: center;
|
||||
justify-content: center;
|
||||
}
|
||||
button {
|
||||
border-radius: 20px;
|
||||
}
|
@ -0,0 +1,25 @@
|
||||
import { ComponentFixture, TestBed } from '@angular/core/testing';
|
||||
|
||||
import { EditablePermissionComponent } from './editable-permission.component';
|
||||
|
||||
describe('EditablePermissionComponent', () => {
|
||||
let component: EditablePermissionComponent;
|
||||
let fixture: ComponentFixture<EditablePermissionComponent>;
|
||||
|
||||
beforeEach(async () => {
|
||||
await TestBed.configureTestingModule({
|
||||
declarations: [ EditablePermissionComponent ]
|
||||
})
|
||||
.compileComponents();
|
||||
});
|
||||
|
||||
beforeEach(() => {
|
||||
fixture = TestBed.createComponent(EditablePermissionComponent);
|
||||
component = fixture.componentInstance;
|
||||
fixture.detectChanges();
|
||||
});
|
||||
|
||||
it('should create', () => {
|
||||
expect(component).toBeTruthy();
|
||||
});
|
||||
});
|
@ -0,0 +1,32 @@
|
||||
import {Component, EventEmitter, Input, OnInit, Output} from '@angular/core';
|
||||
import {Permission} from "@models/api/permission";
|
||||
|
||||
@Component({
|
||||
selector: 'app-editable-permission',
|
||||
templateUrl: './editable-permission.component.html',
|
||||
styleUrls: ['./editable-permission.component.scss']
|
||||
})
|
||||
export class EditablePermissionComponent implements OnInit {
|
||||
|
||||
@Input() permission: Permission;
|
||||
@Input() side: 'LEFT' | 'RIGHT';
|
||||
@Output() click = new EventEmitter();
|
||||
|
||||
constructor() { }
|
||||
|
||||
ngOnInit(): void {
|
||||
}
|
||||
|
||||
|
||||
onClick() {
|
||||
this.click.emit();
|
||||
}
|
||||
|
||||
getToolTip() {
|
||||
return `
|
||||
action: ${this.permission.action}
|
||||
methods: ${this.permission.methods.join(',')}
|
||||
path: ${this.permission.path}
|
||||
`;
|
||||
}
|
||||
}
|
@ -0,0 +1,33 @@
|
||||
<div>
|
||||
<div class="button">
|
||||
<button
|
||||
mat-button
|
||||
mat-raised-button
|
||||
(click)="close()">
|
||||
Cancel
|
||||
</button>
|
||||
<button *ngIf="data.add.length > 0 || data.remove.length > 0"
|
||||
mat-button
|
||||
mat-raised-button
|
||||
color="primary"
|
||||
(click)="update()">
|
||||
Apply
|
||||
</button>
|
||||
</div>
|
||||
<div class="change" *ngIf="data.add.length > 0 || data.remove.length > 0; else nothingTodo">
|
||||
<p></p>
|
||||
<div class="title" *ngIf="data.add.length > 0">Permission to Add:</div>
|
||||
<div *ngFor="let permission of data.add">
|
||||
<app-editable-permission [permission]="permission"></app-editable-permission>
|
||||
</div>
|
||||
<div class="title" *ngIf="data.remove.length > 0">Permission to Remove:</div>
|
||||
<div *ngFor="let permission of data.remove">
|
||||
<app-editable-permission [permission]="permission"></app-editable-permission>
|
||||
</div>
|
||||
</div>
|
||||
<ng-template #nothingTodo>
|
||||
<div class="noChange">
|
||||
No change
|
||||
</div>
|
||||
</ng-template>
|
||||
</div>
|
@ -0,0 +1,33 @@
|
||||
.change {
|
||||
height: 350px;
|
||||
display: flex;
|
||||
flex-direction: column;
|
||||
justify-content: center;
|
||||
overflow-y: auto;
|
||||
}
|
||||
|
||||
.change div {
|
||||
justify-content: center;
|
||||
justify-items: center;
|
||||
text-align: center;
|
||||
}
|
||||
|
||||
.title {
|
||||
font-size: 20px;
|
||||
}
|
||||
|
||||
.button {
|
||||
position: relative;
|
||||
top: 400px;
|
||||
z-index: 1;
|
||||
}
|
||||
|
||||
.button button {
|
||||
margin-right: 50px;
|
||||
}
|
||||
|
||||
.noChange {
|
||||
display: flex;
|
||||
justify-content: center;
|
||||
justify-items: center;
|
||||
}
|
@ -0,0 +1,25 @@
|
||||
import { ComponentFixture, TestBed } from '@angular/core/testing';
|
||||
|
||||
import { PermissionEditorValidateDialogComponent } from './permission-editor-validate-dialog.component';
|
||||
|
||||
describe('PermissionEditorValidateDialogComponent', () => {
|
||||
let component: PermissionEditorValidateDialogComponent;
|
||||
let fixture: ComponentFixture<PermissionEditorValidateDialogComponent>;
|
||||
|
||||
beforeEach(async () => {
|
||||
await TestBed.configureTestingModule({
|
||||
declarations: [ PermissionEditorValidateDialogComponent ]
|
||||
})
|
||||
.compileComponents();
|
||||
});
|
||||
|
||||
beforeEach(() => {
|
||||
fixture = TestBed.createComponent(PermissionEditorValidateDialogComponent);
|
||||
component = fixture.componentInstance;
|
||||
fixture.detectChanges();
|
||||
});
|
||||
|
||||
it('should create', () => {
|
||||
expect(component).toBeTruthy();
|
||||
});
|
||||
});
|
@ -0,0 +1,26 @@
|
||||
import {Component, Inject, OnInit} from '@angular/core';
|
||||
import {MAT_DIALOG_DATA, MatDialogRef} from "@angular/material/dialog";
|
||||
import {Group} from "@models/groups/group";
|
||||
import {Permission} from "@models/api/permission";
|
||||
|
||||
@Component({
|
||||
selector: 'app-permission-editor-validate-dialog',
|
||||
templateUrl: './permission-editor-validate-dialog.component.html',
|
||||
styleUrls: ['./permission-editor-validate-dialog.component.scss']
|
||||
})
|
||||
export class PermissionEditorValidateDialogComponent implements OnInit {
|
||||
|
||||
constructor(private dialogRef: MatDialogRef<PermissionEditorValidateDialogComponent>,
|
||||
@Inject(MAT_DIALOG_DATA) public data: { add: Permission[], remove: Permission[] }) { }
|
||||
|
||||
ngOnInit(): void {
|
||||
}
|
||||
|
||||
close() {
|
||||
this.dialogRef.close(false);
|
||||
}
|
||||
|
||||
update() {
|
||||
this.dialogRef.close(true);
|
||||
}
|
||||
}
|
@ -0,0 +1,62 @@
|
||||
<div class="header">
|
||||
<div>
|
||||
<div>
|
||||
<a
|
||||
mat-icon-button
|
||||
matTooltip="Back to role detail"
|
||||
matTooltipClass="custom-tooltip"
|
||||
[routerLink]="['/server', server.id, 'management', 'roles', role.role_id]">
|
||||
<mat-icon aria-label="Back to role detail">keyboard_arrow_left</mat-icon>
|
||||
</a>
|
||||
</div>
|
||||
<div>
|
||||
Edit {{role.name}} role permissions
|
||||
</div>
|
||||
</div>
|
||||
<div>
|
||||
<div>
|
||||
Allow:
|
||||
</div>
|
||||
<div class="box allow"></div>
|
||||
<div>
|
||||
Deny:
|
||||
</div>
|
||||
<div class="box deny"></div>
|
||||
</div>
|
||||
<div>
|
||||
<button
|
||||
mat-button
|
||||
mat-raised-button
|
||||
(click)="reset()">Reset
|
||||
</button>
|
||||
<button
|
||||
mat-button
|
||||
mat-raised-button
|
||||
(click)="update()"
|
||||
color="primary">Update
|
||||
</button>
|
||||
</div>
|
||||
</div>
|
||||
<div class="editor">
|
||||
<div class="column">
|
||||
<div class="title">Owned</div>
|
||||
<app-editable-permission
|
||||
[side]="'LEFT'"
|
||||
[permission]="permission"
|
||||
(click)="remove(permission)"
|
||||
*ngFor="let permission of owned">
|
||||
|
||||
</app-editable-permission>
|
||||
</div>
|
||||
<mat-divider [vertical]="true"></mat-divider>
|
||||
<div class="column">
|
||||
<div class="title">available</div>
|
||||
<app-editable-permission
|
||||
[side]="'RIGHT'"
|
||||
[permission]="permission"
|
||||
(click)="add(permission)"
|
||||
*ngFor="let permission of available">
|
||||
|
||||
</app-editable-permission>
|
||||
</div>
|
||||
</div>
|
@ -0,0 +1,47 @@
|
||||
.editor {
|
||||
display: flex;
|
||||
justify-content: stretch;
|
||||
}
|
||||
.column {
|
||||
width: 50vw;
|
||||
}
|
||||
|
||||
.header {
|
||||
margin-top: 5px;
|
||||
display: flex;
|
||||
flex-direction: row;
|
||||
justify-content: space-between;
|
||||
font-size: 20px;
|
||||
}
|
||||
|
||||
.header > div > button {
|
||||
margin-right: 30px;
|
||||
}
|
||||
|
||||
.header > div {
|
||||
display: flex;
|
||||
align-items: center;
|
||||
justify-content: center;
|
||||
margin-bottom: 20px;
|
||||
|
||||
}
|
||||
|
||||
.title {
|
||||
font-size: 20px;
|
||||
margin-left: 20px;
|
||||
}
|
||||
.box {
|
||||
width: 50px;
|
||||
height: 25px;
|
||||
border: 1px solid;
|
||||
margin-right: 20px;
|
||||
margin-left: 10px;
|
||||
}
|
||||
|
||||
.allow {
|
||||
background-color: rgba(5, 76, 5, 0.38);
|
||||
}
|
||||
|
||||
.deny {
|
||||
background-color: rgba(130, 8, 8, 0.36);
|
||||
}
|
@ -0,0 +1,25 @@
|
||||
import { ComponentFixture, TestBed } from '@angular/core/testing';
|
||||
|
||||
import { PermissionEditorComponent } from './permission-editor.component';
|
||||
|
||||
describe('PermissionEditorComponent', () => {
|
||||
let component: PermissionEditorComponent;
|
||||
let fixture: ComponentFixture<PermissionEditorComponent>;
|
||||
|
||||
beforeEach(async () => {
|
||||
await TestBed.configureTestingModule({
|
||||
declarations: [ PermissionEditorComponent ]
|
||||
})
|
||||
.compileComponents();
|
||||
});
|
||||
|
||||
beforeEach(() => {
|
||||
fixture = TestBed.createComponent(PermissionEditorComponent);
|
||||
component = fixture.componentInstance;
|
||||
fixture.detectChanges();
|
||||
});
|
||||
|
||||
it('should create', () => {
|
||||
expect(component).toBeTruthy();
|
||||
});
|
||||
});
|
@ -0,0 +1,104 @@
|
||||
import {Component, OnInit} from '@angular/core';
|
||||
import {ActivatedRoute, Router} from "@angular/router";
|
||||
import {Role} from "@models/api/role";
|
||||
import {Server} from "@models/server";
|
||||
import {Permission} from "@models/api/permission";
|
||||
import {MatDialog} from "@angular/material/dialog";
|
||||
import {PermissionEditorValidateDialogComponent} from "@components/role-management/role-detail/permission-editor/permission-editor-validate-dialog/permission-editor-validate-dialog.component";
|
||||
import {forkJoin, Observable} from "rxjs";
|
||||
import {RoleService} from "@services/role.service";
|
||||
import {ToasterService} from "@services/toaster.service";
|
||||
|
||||
@Component({
|
||||
selector: 'app-permission-editor',
|
||||
templateUrl: './permission-editor.component.html',
|
||||
styleUrls: ['./permission-editor.component.scss']
|
||||
})
|
||||
export class PermissionEditorComponent implements OnInit {
|
||||
server: Server;
|
||||
role: Role;
|
||||
private permissions: Permission[];
|
||||
owned: Set<Permission>;
|
||||
available: Set<Permission>;
|
||||
|
||||
constructor(private route: ActivatedRoute,
|
||||
private dialog: MatDialog,
|
||||
private toastService: ToasterService,
|
||||
private router: Router,
|
||||
private roleService: RoleService) {
|
||||
this.route.data.subscribe((data: { server: Server, role: Role, permissions: Permission[] }) => {
|
||||
this.server = data.server;
|
||||
this.role = data.role;
|
||||
this.permissions = data.permissions;
|
||||
this.reset();
|
||||
});
|
||||
}
|
||||
|
||||
ngOnInit(): void {
|
||||
}
|
||||
|
||||
add(permission: Permission) {
|
||||
this.available.delete(permission);
|
||||
this.owned.add(permission);
|
||||
}
|
||||
|
||||
remove(permission: Permission) {
|
||||
this.owned.delete(permission);
|
||||
this.available.add(permission);
|
||||
}
|
||||
|
||||
reset() {
|
||||
const ownedPermissionId = this.role.permissions.map(p => p.permission_id);
|
||||
this.owned = new Set(this.role.permissions);
|
||||
this.available = new Set(this.permissions.filter(p => !ownedPermissionId.includes(p.permission_id)));
|
||||
}
|
||||
|
||||
update() {
|
||||
const {add, remove} = this.diff();
|
||||
this.dialog
|
||||
.open(PermissionEditorValidateDialogComponent,
|
||||
{width: '700px', height: '500px', data: {add, remove}})
|
||||
.afterClosed()
|
||||
.subscribe((confirmed: boolean) => {
|
||||
if (confirmed) {
|
||||
const obs: Observable<any>[] = [];
|
||||
add.forEach((permission: Permission) => {
|
||||
obs.push(this.roleService.addPermission(this.server, this.role, permission));
|
||||
});
|
||||
remove.forEach((permission: Permission) => {
|
||||
obs.push(this.roleService.removePermission(this.server, this.role, permission));
|
||||
});
|
||||
|
||||
forkJoin(obs)
|
||||
.subscribe(() => {
|
||||
this.toastService.success(`permissions updated`);
|
||||
this.router.navigate(['/server', this.server.id, 'management', 'roles', this.role.role_id]);
|
||||
},
|
||||
(error) => {
|
||||
this.toastService.error(error);
|
||||
});
|
||||
}
|
||||
|
||||
});
|
||||
}
|
||||
|
||||
private diff() {
|
||||
const add: Permission[] = [];
|
||||
|
||||
const currentRolePermissionId = this.role.permissions.map(p => p.permission_id);
|
||||
this.owned.forEach((permission: Permission) => {
|
||||
if (!currentRolePermissionId.includes(permission.permission_id)) {
|
||||
add.push(permission);
|
||||
}
|
||||
});
|
||||
|
||||
const remove: Permission[] = [];
|
||||
this.role.permissions.forEach((permission: Permission) => {
|
||||
if (!this.owned.has(permission)) {
|
||||
remove.push(permission);
|
||||
}
|
||||
});
|
||||
|
||||
return {add, remove};
|
||||
}
|
||||
}
|
@ -0,0 +1,59 @@
|
||||
<div class="content">
|
||||
<div class="default-header">
|
||||
<div class="row align-items-center">
|
||||
<a
|
||||
mat-icon-button
|
||||
matTooltip="Back to role management"
|
||||
matTooltipClass="custom-tooltip"
|
||||
[routerLink]="['/server', server.id, 'management', 'roles']">
|
||||
<mat-icon aria-label="Back to role management">keyboard_arrow_left</mat-icon>
|
||||
</a>
|
||||
<h1 class="col">Role {{role.name}} details</h1>
|
||||
</div>
|
||||
<div class="main">
|
||||
<div class="details">
|
||||
<div>
|
||||
<mat-form-field>
|
||||
<mat-label>Role name:</mat-label>
|
||||
<input matInput type="text" [ngModel]="role.name">
|
||||
</mat-form-field>
|
||||
</div>
|
||||
<div>
|
||||
<mat-form-field>
|
||||
<mat-label>Description:</mat-label>
|
||||
<input matInput type="text" [ngModel]="role.description">
|
||||
</mat-form-field>
|
||||
</div>
|
||||
<div>Creation date: {{role.created_at}}</div>
|
||||
<div>Last update Date: {{role.updated_at}}</div>
|
||||
<div>UUID: {{role.role_id}}</div>
|
||||
<div>
|
||||
<mat-checkbox [checked]="role.is_builtin" disabled>Is build in</mat-checkbox>
|
||||
</div>
|
||||
<div mat-dialog-actions class="button-div">
|
||||
<button mat-button (click)="onUpdate()" tabindex="2" mat-raised-button color="primary"
|
||||
[disabled]="!editRoleForm.valid">
|
||||
Update Role
|
||||
</button>
|
||||
</div>
|
||||
</div>
|
||||
<mat-divider [vertical]="true"></mat-divider>
|
||||
<div class="permissions">
|
||||
<div class="header">
|
||||
<div>Permissions</div>
|
||||
<div>
|
||||
<button
|
||||
mat-button
|
||||
[routerLink]="['/server', server.id, 'management', 'roles', role.role_id, 'permissions']">
|
||||
<mat-icon>edit</mat-icon>
|
||||
</button>
|
||||
</div>
|
||||
</div>
|
||||
<app-editable-permission
|
||||
[permission]="permission"
|
||||
*ngFor="let permission of role.permissions">
|
||||
</app-editable-permission>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
@ -0,0 +1,40 @@
|
||||
.main {
|
||||
display: flex;
|
||||
justify-content: space-around;
|
||||
}
|
||||
|
||||
.details {
|
||||
width: 30vw;
|
||||
display: flex;
|
||||
flex-direction: column;
|
||||
justify-content: center;
|
||||
}
|
||||
|
||||
.permissions {
|
||||
width: 35vw;
|
||||
display: flex;
|
||||
flex-direction: column;
|
||||
justify-content: stretch;
|
||||
}
|
||||
|
||||
.permission {
|
||||
display: flex;
|
||||
flex-direction: row;
|
||||
justify-content: space-between;
|
||||
margin-bottom: 10px;
|
||||
border: 1px solid;
|
||||
padding: 5px;
|
||||
border-radius: 5px;
|
||||
font-family: monospace;
|
||||
}
|
||||
|
||||
.header {
|
||||
display: flex;
|
||||
flex-direction: row;
|
||||
justify-content: space-between;
|
||||
padding-bottom: 20px;
|
||||
|
||||
}
|
||||
.header > div {
|
||||
font-size: 2em;
|
||||
}
|
@ -0,0 +1,25 @@
|
||||
import { ComponentFixture, TestBed } from '@angular/core/testing';
|
||||
|
||||
import { RoleDetailComponent } from './role-detail.component';
|
||||
|
||||
describe('RoleDetailComponent', () => {
|
||||
let component: RoleDetailComponent;
|
||||
let fixture: ComponentFixture<RoleDetailComponent>;
|
||||
|
||||
beforeEach(async () => {
|
||||
await TestBed.configureTestingModule({
|
||||
declarations: [ RoleDetailComponent ]
|
||||
})
|
||||
.compileComponents();
|
||||
});
|
||||
|
||||
beforeEach(() => {
|
||||
fixture = TestBed.createComponent(RoleDetailComponent);
|
||||
component = fixture.componentInstance;
|
||||
fixture.detectChanges();
|
||||
});
|
||||
|
||||
it('should create', () => {
|
||||
expect(component).toBeTruthy();
|
||||
});
|
||||
});
|
@ -0,0 +1,47 @@
|
||||
import {Component, OnInit} from '@angular/core';
|
||||
import {RoleService} from "@services/role.service";
|
||||
import {ActivatedRoute} from "@angular/router";
|
||||
import {Server} from "@models/server";
|
||||
import {ServerService} from "@services/server.service";
|
||||
import {Role} from "@models/api/role";
|
||||
import {FormControl, FormGroup} from "@angular/forms";
|
||||
import {ToasterService} from "@services/toaster.service";
|
||||
|
||||
@Component({
|
||||
selector: 'app-role-detail',
|
||||
templateUrl: './role-detail.component.html',
|
||||
styleUrls: ['./role-detail.component.scss']
|
||||
})
|
||||
export class RoleDetailComponent implements OnInit {
|
||||
server: Server;
|
||||
role: Role;
|
||||
editRoleForm: FormGroup;
|
||||
|
||||
constructor(private roleService: RoleService,
|
||||
private serverService: ServerService,
|
||||
private toastService: ToasterService,
|
||||
private route: ActivatedRoute) {
|
||||
|
||||
this.editRoleForm = new FormGroup({
|
||||
rolename: new FormControl(),
|
||||
description: new FormControl(),
|
||||
});
|
||||
}
|
||||
|
||||
ngOnInit(): void {
|
||||
this.route.data.subscribe((d: { server: Server; role: Role }) => {
|
||||
this.server = d.server;
|
||||
this.role = d.role;
|
||||
});
|
||||
}
|
||||
|
||||
onUpdate() {
|
||||
this.roleService.update(this.server, this.role)
|
||||
.subscribe(() => {
|
||||
this.toastService.success(`role: ${this.role.name} was updated`);
|
||||
},
|
||||
(error) => {
|
||||
this.toastService.error(error);
|
||||
});
|
||||
}
|
||||
}
|
@ -0,0 +1,8 @@
|
||||
import { RoleFilterPipe } from './role-filter.pipe';
|
||||
|
||||
describe('RoleFilterPipe', () => {
|
||||
it('create an instance', () => {
|
||||
const pipe = new RoleFilterPipe();
|
||||
expect(pipe).toBeTruthy();
|
||||
});
|
||||
});
|
22
src/app/components/role-management/role-filter.pipe.ts
Normal file
22
src/app/components/role-management/role-filter.pipe.ts
Normal file
@ -0,0 +1,22 @@
|
||||
import { Pipe, PipeTransform } from '@angular/core';
|
||||
import {Role} from "@models/api/role";
|
||||
import {User} from "@models/users/user";
|
||||
import {MatTableDataSource} from "@angular/material/table";
|
||||
|
||||
@Pipe({
|
||||
name: 'roleFilter'
|
||||
})
|
||||
export class RoleFilterPipe implements PipeTransform {
|
||||
|
||||
transform(roles: MatTableDataSource<Role[]>, searchText: string): MatTableDataSource<Role[]> {
|
||||
if (!searchText) {
|
||||
return roles;
|
||||
}
|
||||
searchText = searchText.trim().toLowerCase();
|
||||
roles.filter = searchText;
|
||||
return roles;
|
||||
|
||||
|
||||
}
|
||||
|
||||
}
|
@ -0,0 +1,90 @@
|
||||
<div class="content" *ngIf="isReady; else loading">
|
||||
<div class="default-header">
|
||||
<div class="row">
|
||||
<h1 class="col">Roles Management</h1>
|
||||
<button class="col" mat-raised-button color="primary" (click)="onDelete(selection.selected)" class="add-button"
|
||||
[disabled]="selection.selected.length == 0">
|
||||
Delete roles
|
||||
</button>
|
||||
<button class="col" mat-raised-button color="primary" (click)="addRole()" class="add-button">
|
||||
Add role
|
||||
</button>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<form>
|
||||
<mat-form-field class="full-width">
|
||||
<input matInput placeholder="Search role by name" [(ngModel)]="searchText"
|
||||
[ngModelOptions]="{ standalone: true }"/>
|
||||
</mat-form-field>
|
||||
</form>
|
||||
|
||||
<div class="default-content">
|
||||
<div class="mat-elevation-z8">
|
||||
<mat-table #table [dataSource]="dataSource | roleFilter: searchText" matSort>
|
||||
<ng-container matColumnDef="select">
|
||||
<mat-header-cell *matHeaderCellDef class="small-col">
|
||||
<mat-checkbox (change)="$event ? masterToggle() : null"
|
||||
[checked]="selection.hasValue() && isAllSelected()"
|
||||
[indeterminate]="selection.hasValue() && !isAllSelected()">
|
||||
</mat-checkbox>
|
||||
</mat-header-cell>
|
||||
<mat-cell *matCellDef="let row" class="small-col">
|
||||
<mat-checkbox (click)="$event.stopPropagation()"
|
||||
(change)="$event ? selection.toggle(row) : null"
|
||||
[checked]="selection.isSelected(row)">
|
||||
</mat-checkbox>
|
||||
</mat-cell>
|
||||
</ng-container>
|
||||
|
||||
<ng-container matColumnDef="name">
|
||||
<mat-header-cell *matHeaderCellDef mat-sort-header>Name</mat-header-cell>
|
||||
<mat-cell *matCellDef="let row">
|
||||
<a [routerLink]="['/server', server.id, 'management','roles', row.role_id]"
|
||||
class="table-link" [matTooltip]="row.name">{{ row.name }}</a>
|
||||
</mat-cell>
|
||||
</ng-container>
|
||||
<ng-container matColumnDef="description">
|
||||
<mat-header-cell *matHeaderCellDef mat-sort-header>Description</mat-header-cell>
|
||||
<mat-cell *matCellDef="let row">
|
||||
<div [matTooltip]="row.description" matTooltipClass="custom-tooltip"
|
||||
class="overflow-col">{{ row.description }}</div>
|
||||
</mat-cell>
|
||||
</ng-container>
|
||||
<ng-container matColumnDef="permissions">
|
||||
<mat-header-cell *matHeaderCellDef mat-sort-header>Permissions (Allow)</mat-header-cell>
|
||||
<mat-cell *matCellDef="let row">
|
||||
<div class="permissions-list">
|
||||
<div class="overflow-col permission" *ngFor="let permission of row.permissions">
|
||||
<div>{{permission.action}}</div>
|
||||
<div>{{permission.methods.join(',')}}</div>
|
||||
<div>{{permission.path}}</div>
|
||||
</div>
|
||||
</div>
|
||||
</mat-cell>
|
||||
</ng-container>
|
||||
<ng-container matColumnDef="delete">
|
||||
<mat-header-cell *matHeaderCellDef class="small-col"></mat-header-cell>
|
||||
<mat-cell *matCellDef="let row" class="small-col">
|
||||
<button mat-button (click)="onDelete([row])">
|
||||
<mat-icon>delete</mat-icon>
|
||||
</button>
|
||||
</mat-cell>
|
||||
</ng-container>
|
||||
|
||||
<mat-header-row *matHeaderRowDef="displayedColumns"></mat-header-row>
|
||||
<mat-row *matRowDef="let row; columns: displayedColumns"></mat-row>
|
||||
</mat-table>
|
||||
|
||||
<mat-paginator [pageSizeOptions]="[5, 10, 20]"
|
||||
showFirstLastButtons
|
||||
aria-label="Select page">
|
||||
</mat-paginator>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
<ng-template #loading>
|
||||
<div>
|
||||
<mat-spinner class="loader"></mat-spinner>
|
||||
</div>
|
||||
</ng-template>
|
@ -0,0 +1,56 @@
|
||||
.add-button {
|
||||
height: 40px;
|
||||
width: 160px;
|
||||
margin: 20px;
|
||||
}
|
||||
|
||||
.full-width {
|
||||
width: 940px;
|
||||
margin-left: -470px;
|
||||
left: 50%;
|
||||
}
|
||||
|
||||
.small-col {
|
||||
flex-grow: 0.3;
|
||||
}
|
||||
|
||||
.active-col {
|
||||
flex-grow: 0.5;
|
||||
}
|
||||
|
||||
.overflow-col {
|
||||
text-overflow: ellipsis;
|
||||
overflow: hidden;
|
||||
white-space: nowrap;
|
||||
padding-right: 5px;
|
||||
}
|
||||
|
||||
.permission {
|
||||
display: flex;
|
||||
flex-direction: row;
|
||||
justify-content: space-between;
|
||||
}
|
||||
.permission > div {
|
||||
margin-right: 20px;
|
||||
font-size: 10px;
|
||||
}
|
||||
.custom-tooltip {
|
||||
font-size:100px;
|
||||
}
|
||||
|
||||
.loader {
|
||||
position: absolute;
|
||||
margin: auto;
|
||||
height: 175px;
|
||||
bottom: 0;
|
||||
left: 0;
|
||||
right: 0;
|
||||
top: 0;
|
||||
width: 175px;
|
||||
}
|
||||
|
||||
.permissions-list {
|
||||
display: flex;
|
||||
flex-direction: column;
|
||||
justify-content: stretch;
|
||||
}
|
@ -0,0 +1,25 @@
|
||||
import { ComponentFixture, TestBed } from '@angular/core/testing';
|
||||
|
||||
import { RoleManagementComponent } from './role-management.component';
|
||||
|
||||
describe('RoleManagementComponent', () => {
|
||||
let component: RoleManagementComponent;
|
||||
let fixture: ComponentFixture<RoleManagementComponent>;
|
||||
|
||||
beforeEach(async () => {
|
||||
await TestBed.configureTestingModule({
|
||||
declarations: [ RoleManagementComponent ]
|
||||
})
|
||||
.compileComponents();
|
||||
});
|
||||
|
||||
beforeEach(() => {
|
||||
fixture = TestBed.createComponent(RoleManagementComponent);
|
||||
component = fixture.componentInstance;
|
||||
fixture.detectChanges();
|
||||
});
|
||||
|
||||
it('should create', () => {
|
||||
expect(component).toBeTruthy();
|
||||
});
|
||||
});
|
120
src/app/components/role-management/role-management.component.ts
Normal file
120
src/app/components/role-management/role-management.component.ts
Normal file
@ -0,0 +1,120 @@
|
||||
import {Component, OnInit, ViewChild} from '@angular/core';
|
||||
import {Server} from "@models/server";
|
||||
import {MatTableDataSource} from "@angular/material/table";
|
||||
import {SelectionModel} from "@angular/cdk/collections";
|
||||
import {MatPaginator} from "@angular/material/paginator";
|
||||
import {MatSort} from "@angular/material/sort";
|
||||
import {ActivatedRoute, Router} from "@angular/router";
|
||||
import {ProgressService} from "../../common/progress/progress.service";
|
||||
import {ServerService} from "@services/server.service";
|
||||
import {MatDialog} from "@angular/material/dialog";
|
||||
import {ToasterService} from "@services/toaster.service";
|
||||
import {Role} from "@models/api/role";
|
||||
import {RoleService} from "@services/role.service";
|
||||
import {AddRoleDialogComponent} from "@components/role-management/add-role-dialog/add-role-dialog.component";
|
||||
import {DeleteRoleDialogComponent} from "@components/role-management/delete-role-dialog/delete-role-dialog.component";
|
||||
import {forkJoin} from "rxjs";
|
||||
|
||||
|
||||
@Component({
|
||||
selector: 'app-role-management',
|
||||
templateUrl: './role-management.component.html',
|
||||
styleUrls: ['./role-management.component.scss']
|
||||
})
|
||||
export class RoleManagementComponent implements OnInit {
|
||||
server: Server;
|
||||
dataSource = new MatTableDataSource<Role>();
|
||||
displayedColumns = ['select', 'name', 'description', 'permissions', 'delete'];
|
||||
selection = new SelectionModel<Role>(true, []);
|
||||
searchText = '';
|
||||
|
||||
@ViewChild(MatPaginator) paginator: MatPaginator;
|
||||
@ViewChild(MatSort, {static: true}) sort: MatSort;
|
||||
isReady = false;
|
||||
|
||||
constructor(
|
||||
private route: ActivatedRoute,
|
||||
private router: Router,
|
||||
private roleService: RoleService,
|
||||
private progressService: ProgressService,
|
||||
private serverService: ServerService,
|
||||
public dialog: MatDialog,
|
||||
private toasterService: ToasterService) {
|
||||
}
|
||||
|
||||
ngOnInit() {
|
||||
const serverId = this.route.parent.snapshot.paramMap.get('server_id');
|
||||
this.serverService.get(+serverId).then((server: Server) => {
|
||||
this.server = server;
|
||||
this.refresh();
|
||||
});
|
||||
}
|
||||
|
||||
ngAfterViewInit() {
|
||||
this.dataSource.paginator = this.paginator;
|
||||
this.dataSource.sort = this.sort;
|
||||
|
||||
}
|
||||
|
||||
refresh() {
|
||||
this.roleService.get(this.server).subscribe(
|
||||
(roles: Role[]) => {
|
||||
this.isReady = true;
|
||||
this.dataSource.data = roles;
|
||||
},
|
||||
(error) => {
|
||||
this.progressService.setError(error);
|
||||
}
|
||||
);
|
||||
}
|
||||
|
||||
addRole() {
|
||||
const dialogRef = this.dialog.open(AddRoleDialogComponent, {
|
||||
width: '400px',
|
||||
autoFocus: false,
|
||||
disableClose: true,
|
||||
data: {server: this.server},
|
||||
})
|
||||
.afterClosed()
|
||||
.subscribe((role: { name: string; description: string }) => {
|
||||
if (role) {
|
||||
this.roleService.create(this.server, role)
|
||||
.subscribe(() => {
|
||||
this.toasterService.success(`${role.name} role created`);
|
||||
this.refresh();
|
||||
},
|
||||
(error) => this.toasterService.error(error));
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
isAllSelected() {
|
||||
const numSelected = this.selection.selected.length;
|
||||
const numRows = this.dataSource.data.length;
|
||||
return numSelected === numRows;
|
||||
}
|
||||
|
||||
masterToggle() {
|
||||
this.isAllSelected() ?
|
||||
this.selection.clear() :
|
||||
this.dataSource.data.forEach(row => this.selection.select(row));
|
||||
}
|
||||
|
||||
onDelete(rolesToDelete: Role[]) {
|
||||
this.dialog
|
||||
.open(DeleteRoleDialogComponent, {width: '500px', height: '250px', data: {roles: rolesToDelete}})
|
||||
.afterClosed()
|
||||
.subscribe((isDeletedConfirm) => {
|
||||
if (isDeletedConfirm) {
|
||||
const observables = rolesToDelete.map((role: Role) => this.roleService.delete(this.server, role.role_id));
|
||||
forkJoin(observables)
|
||||
.subscribe(() => {
|
||||
this.refresh();
|
||||
},
|
||||
(error) => {
|
||||
this.toasterService.error(`An error occur while trying to delete role`);
|
||||
});
|
||||
}
|
||||
});
|
||||
}
|
||||
}
|
@ -27,6 +27,7 @@
|
||||
|
||||
.custom-tooltip {
|
||||
font-size:100px;
|
||||
white-space: pre-line;
|
||||
}
|
||||
|
||||
.loader {
|
||||
|
0
src/app/models/LocalStorage.ts
Normal file
0
src/app/models/LocalStorage.ts
Normal file
@ -25,11 +25,11 @@ export enum PermissionActions {
|
||||
}
|
||||
|
||||
export interface Permission {
|
||||
methods: Methods[],
|
||||
path: string,
|
||||
action: PermissionActions,
|
||||
description: string,
|
||||
created_at: string,
|
||||
updated_at: string,
|
||||
permission_id: string
|
||||
methods: Methods[];
|
||||
path: string;
|
||||
action: PermissionActions;
|
||||
description: string;
|
||||
created_at: string;
|
||||
updated_at: string;
|
||||
permission_id: string;
|
||||
}
|
11
src/app/models/api/role.ts
Normal file
11
src/app/models/api/role.ts
Normal file
@ -0,0 +1,11 @@
|
||||
import {Permission} from "./permission";
|
||||
|
||||
export interface Role {
|
||||
name: string;
|
||||
description: string;
|
||||
created_at: string;
|
||||
updated_at: string;
|
||||
role_id: string;
|
||||
is_builtin: boolean;
|
||||
permissions: Permission[];
|
||||
}
|
16
src/app/resolvers/permission.resolver.spec.ts
Normal file
16
src/app/resolvers/permission.resolver.spec.ts
Normal file
@ -0,0 +1,16 @@
|
||||
import { TestBed } from '@angular/core/testing';
|
||||
|
||||
import { PermissionResolver } from './permission.resolver';
|
||||
|
||||
describe('PermissionResolver', () => {
|
||||
let resolver: PermissionResolver;
|
||||
|
||||
beforeEach(() => {
|
||||
TestBed.configureTestingModule({});
|
||||
resolver = TestBed.inject(PermissionResolver);
|
||||
});
|
||||
|
||||
it('should be created', () => {
|
||||
expect(resolver).toBeTruthy();
|
||||
});
|
||||
});
|
35
src/app/resolvers/permission.resolver.ts
Normal file
35
src/app/resolvers/permission.resolver.ts
Normal file
@ -0,0 +1,35 @@
|
||||
import { Injectable } from '@angular/core';
|
||||
import {
|
||||
Router, Resolve,
|
||||
RouterStateSnapshot,
|
||||
ActivatedRouteSnapshot
|
||||
} from '@angular/router';
|
||||
import {Observable, of, Subscriber} from 'rxjs';
|
||||
import {Permission} from "@models/api/permission";
|
||||
import {PermissionsService} from "@services/permissions.service";
|
||||
import {ServerService} from "@services/server.service";
|
||||
import {Server} from "@models/server";
|
||||
|
||||
@Injectable({
|
||||
providedIn: 'root'
|
||||
})
|
||||
export class PermissionResolver implements Resolve<Permission[]> {
|
||||
|
||||
constructor(private permissionService: PermissionsService,
|
||||
private serverService: ServerService) {
|
||||
}
|
||||
|
||||
resolve(route: ActivatedRouteSnapshot, state: RouterStateSnapshot): Observable<Permission[]> {
|
||||
return new Observable<Permission[]>((observer: Subscriber<Permission[]>) => {
|
||||
const serverId = route.paramMap.get('server_id');
|
||||
this.serverService.get(+serverId).then((server: Server) => {
|
||||
this.permissionService.list(server).subscribe((permission: Permission[]) => {
|
||||
observer.next(permission);
|
||||
observer.complete();
|
||||
});
|
||||
});
|
||||
});
|
||||
|
||||
|
||||
}
|
||||
}
|
16
src/app/resolvers/role-detail.resolver.spec.ts
Normal file
16
src/app/resolvers/role-detail.resolver.spec.ts
Normal file
@ -0,0 +1,16 @@
|
||||
import { TestBed } from '@angular/core/testing';
|
||||
|
||||
import { RoleDetailResolver } from './role-detail.resolver';
|
||||
|
||||
describe('RoleDetailResolver', () => {
|
||||
let resolver: RoleDetailResolver;
|
||||
|
||||
beforeEach(() => {
|
||||
TestBed.configureTestingModule({});
|
||||
resolver = TestBed.inject(RoleDetailResolver);
|
||||
});
|
||||
|
||||
it('should be created', () => {
|
||||
expect(resolver).toBeTruthy();
|
||||
});
|
||||
});
|
36
src/app/resolvers/role-detail.resolver.ts
Normal file
36
src/app/resolvers/role-detail.resolver.ts
Normal file
@ -0,0 +1,36 @@
|
||||
import {Injectable} from '@angular/core';
|
||||
import {
|
||||
Router, Resolve,
|
||||
RouterStateSnapshot,
|
||||
ActivatedRouteSnapshot
|
||||
} from '@angular/router';
|
||||
import {Observable, of, Subscriber} from 'rxjs';
|
||||
import {Server} from "../models/server";
|
||||
import {Role} from "../models/api/role";
|
||||
import {ServerService} from "../services/server.service";
|
||||
import {RoleService} from "../services/role.service";
|
||||
|
||||
@Injectable({
|
||||
providedIn: 'root'
|
||||
})
|
||||
export class RoleDetailResolver implements Resolve<Role> {
|
||||
|
||||
constructor(private serverService: ServerService,
|
||||
private roleService: RoleService) {
|
||||
}
|
||||
|
||||
resolve(route: ActivatedRouteSnapshot, state: RouterStateSnapshot): Observable<Role> {
|
||||
return new Observable<Role>((observer: Subscriber<Role>) => {
|
||||
const serverId = route.paramMap.get('server_id');
|
||||
const roleId = route.paramMap.get('role_id');
|
||||
|
||||
this.serverService.get(+serverId).then((server: Server) => {
|
||||
this.roleService.getById(server, roleId).subscribe((role: Role) => {
|
||||
observer.next( role);
|
||||
observer.complete();
|
||||
});
|
||||
});
|
||||
});
|
||||
|
||||
}
|
||||
}
|
@ -13,7 +13,7 @@
|
||||
import { Injectable } from '@angular/core';
|
||||
import {HttpServer} from "./http-server.service";
|
||||
import {Server} from "../models/server";
|
||||
import {Permission} from "../models/permission";
|
||||
import {Permission} from "../models/api/permission";
|
||||
import {Observable} from "rxjs/Rx";
|
||||
|
||||
@Injectable({
|
||||
|
16
src/app/services/role.service.spec.ts
Normal file
16
src/app/services/role.service.spec.ts
Normal file
@ -0,0 +1,16 @@
|
||||
import { TestBed } from '@angular/core/testing';
|
||||
|
||||
import { RoleService } from './role.service';
|
||||
|
||||
describe('RoleService', () => {
|
||||
let service: RoleService;
|
||||
|
||||
beforeEach(() => {
|
||||
TestBed.configureTestingModule({});
|
||||
service = TestBed.inject(RoleService);
|
||||
});
|
||||
|
||||
it('should be created', () => {
|
||||
expect(service).toBeTruthy();
|
||||
});
|
||||
});
|
43
src/app/services/role.service.ts
Normal file
43
src/app/services/role.service.ts
Normal file
@ -0,0 +1,43 @@
|
||||
import { Injectable } from '@angular/core';
|
||||
import {HttpServer} from "./http-server.service";
|
||||
import {Server} from "../models/server";
|
||||
import {Group} from "../models/groups/group";
|
||||
import {Role} from "../models/api/role";
|
||||
import {Permission} from "@models/api/permission";
|
||||
|
||||
@Injectable({
|
||||
providedIn: 'root'
|
||||
})
|
||||
export class RoleService {
|
||||
|
||||
constructor(private httpServer: HttpServer) { }
|
||||
|
||||
get(server: Server) {
|
||||
return this.httpServer.get<Role[]>(server, '/roles');
|
||||
}
|
||||
|
||||
delete(server: Server, role_id: string) {
|
||||
return this.httpServer.delete(server, `/roles/${role_id}`);
|
||||
}
|
||||
|
||||
create(server: Server, newRole: { name: string; description: string }) {
|
||||
return this.httpServer.post(server, `/roles`, newRole);
|
||||
}
|
||||
|
||||
getById(server: Server, roleId: string) {
|
||||
return this.httpServer.get<Role>(server, `/roles/${roleId}`);
|
||||
}
|
||||
|
||||
update(server: Server, role: Role) {
|
||||
return this.httpServer.put(server, `/roles/${role.role_id}`, {name: role.name, description: role.description});
|
||||
}
|
||||
|
||||
addPermission(server: Server, role: Role, permission: Permission) {
|
||||
return this.httpServer.put(server, `/roles/${role.role_id}/permissions/${permission.permission_id}`, {});
|
||||
|
||||
}
|
||||
|
||||
removePermission(server: Server, role: Role, permission: Permission) {
|
||||
return this.httpServer.delete(server, `/roles/${role.role_id}/permissions/${permission.permission_id}`);
|
||||
}
|
||||
}
|
29
src/app/services/server-version.service.ts
Normal file
29
src/app/services/server-version.service.ts
Normal file
@ -0,0 +1,29 @@
|
||||
/*
|
||||
* Software Name : GNS3 Web UI
|
||||
* Version: 3
|
||||
* SPDX-FileCopyrightText: Copyright (c) 2022 Orange Business Services
|
||||
* SPDX-License-Identifier: GPL-3.0-or-later
|
||||
*
|
||||
* This software is distributed under the GPL-3.0 or any later version,
|
||||
* the text of which is available at https://www.gnu.org/licenses/gpl-3.0.txt
|
||||
* or see the "LICENSE" file for more details.
|
||||
*
|
||||
* Author: Sylvain MATHIEU, Elise LEBEAU
|
||||
*/
|
||||
import { Injectable } from '@angular/core';
|
||||
import {HttpServer} from "./http-server.service";
|
||||
import {Server} from "../models/server";
|
||||
import {Observable} from "rxjs";
|
||||
|
||||
@Injectable({
|
||||
providedIn: 'root'
|
||||
})
|
||||
export class ServerVersionService {
|
||||
|
||||
constructor(private httpServer: HttpServer) { }
|
||||
|
||||
|
||||
public checkServerVersion(server: Server): Observable<any> {
|
||||
return this.httpServer.get(server, '/version');
|
||||
}
|
||||
}
|
@ -51,3 +51,14 @@ mat-menu-panel {
|
||||
background-color: grey;
|
||||
color: #ffffff;
|
||||
}
|
||||
|
||||
.permission-tooltip {
|
||||
max-width: unset !important;
|
||||
background-color: grey;
|
||||
color: #ffffff;
|
||||
background-color: grey;
|
||||
color: #ffffff;
|
||||
white-space: pre-line;
|
||||
font-size: 12px !important;
|
||||
font-family: monospace;
|
||||
}
|
||||
|
@ -4,6 +4,8 @@
|
||||
],
|
||||
"rules": {
|
||||
"arrow-return-shorthand": true,
|
||||
"no-implicit-dependencies": false,
|
||||
"no-submodule-imports": false,
|
||||
"callable-types": true,
|
||||
"class-name": true,
|
||||
"comment-format": [
|
||||
|
Loading…
Reference in New Issue
Block a user