refs #2098. Move clients to different OU
testing/ogGui-multibranch/pipeline/head There was a failure building this commit
Details
testing/ogGui-multibranch/pipeline/head There was a failure building this commit
Details
commit
4e23723717
|
@ -3,28 +3,26 @@ import { RouterModule, Routes } from '@angular/router';
|
||||||
import { MainLayoutComponent } from './layout/main-layout/main-layout.component';
|
import { MainLayoutComponent } from './layout/main-layout/main-layout.component';
|
||||||
import { AuthLayoutComponent } from './layout/auth-layout/auth-layout.component';
|
import { AuthLayoutComponent } from './layout/auth-layout/auth-layout.component';
|
||||||
import { LoginComponent } from './components/login/login.component';
|
import { LoginComponent } from './components/login/login.component';
|
||||||
import { DashboardComponent } from './components/dashboard/dashboard.component';
|
|
||||||
import { PageNotFoundComponent } from './shared/page-not-found/page-not-found.component';
|
import { PageNotFoundComponent } from './shared/page-not-found/page-not-found.component';
|
||||||
import { AdminComponent } from './components/admin/admin.component';
|
|
||||||
import { UsersComponent } from './components/admin/users/users/users.component';
|
import { UsersComponent } from './components/admin/users/users/users.component';
|
||||||
import { RolesComponent } from './components/admin/roles/roles/roles.component';
|
import { RolesComponent } from './components/admin/roles/roles/roles.component';
|
||||||
import { GroupsComponent } from './components/groups/groups.component';
|
import { GroupsComponent } from './components/groups/groups.component';
|
||||||
import { PXEimagesComponent } from './components/ogboot/pxe-images/pxe-images.component';
|
import { PXEimagesComponent } from './components/ogboot/pxe-images/pxe-images.component';
|
||||||
import { PxeComponent } from './components/ogboot/pxe/pxe.component';
|
import { PxeComponent } from './components/ogboot/pxe/pxe.component';
|
||||||
import { PxeBootFilesComponent } from './components/ogboot/pxe-boot-files/pxe-boot-files.component';
|
import { PxeBootFilesComponent } from './components/ogboot/pxe-boot-files/pxe-boot-files.component';
|
||||||
import {OgbootStatusComponent} from "./components/ogboot/ogboot-status/ogboot-status.component";
|
import { OgbootStatusComponent } from "./components/ogboot/ogboot-status/ogboot-status.component";
|
||||||
import { CalendarComponent } from "./components/calendar/calendar.component";
|
import { CalendarComponent } from "./components/calendar/calendar.component";
|
||||||
import { CommandsComponent } from './components/commands/main-commands/commands.component';
|
import { CommandsComponent } from './components/commands/main-commands/commands.component';
|
||||||
import { CommandsGroupsComponent } from './components/commands/commands-groups/commands-groups.component';
|
import { CommandsGroupsComponent } from './components/commands/commands-groups/commands-groups.component';
|
||||||
import { CommandsTaskComponent } from './components/commands/commands-task/commands-task.component';
|
import { CommandsTaskComponent } from './components/commands/commands-task/commands-task.component';
|
||||||
import { TaskLogsComponent } from './components/task-logs/task-logs.component';
|
import { TaskLogsComponent } from './components/task-logs/task-logs.component';
|
||||||
import {SoftwareComponent} from "./components/software/software.component";
|
import { SoftwareComponent } from "./components/software/software.component";
|
||||||
import {SoftwareProfileComponent} from "./components/software-profile/software-profile.component";
|
import { SoftwareProfileComponent } from "./components/software-profile/software-profile.component";
|
||||||
import {OperativeSystemComponent} from "./components/operative-system/operative-system.component";
|
import { OperativeSystemComponent } from "./components/operative-system/operative-system.component";
|
||||||
import {
|
import {
|
||||||
PartitionAssistantComponent
|
PartitionAssistantComponent
|
||||||
} from "./components/groups/components/client-main-view/partition-assistant/partition-assistant.component";
|
} from "./components/groups/components/client-main-view/partition-assistant/partition-assistant.component";
|
||||||
import {RepositoriesComponent} from "./components/repositories/repositories.component";
|
import { RepositoriesComponent } from "./components/repositories/repositories.component";
|
||||||
import {
|
import {
|
||||||
CreateClientImageComponent
|
CreateClientImageComponent
|
||||||
} from "./components/groups/components/client-main-view/create-image/create-image.component";
|
} from "./components/groups/components/client-main-view/create-image/create-image.component";
|
||||||
|
@ -34,44 +32,44 @@ import {
|
||||||
import {
|
import {
|
||||||
MainRepositoryViewComponent
|
MainRepositoryViewComponent
|
||||||
} from "./components/repositories/main-repository-view/main-repository-view.component";
|
} from "./components/repositories/main-repository-view/main-repository-view.component";
|
||||||
import {EnvVarsComponent} from "./components/admin/env-vars/env-vars.component";
|
import { EnvVarsComponent } from "./components/admin/env-vars/env-vars.component";
|
||||||
import {MenusComponent} from "./components/menus/menus.component";
|
import { MenusComponent } from "./components/menus/menus.component";
|
||||||
import {OgDhcpSubnetsComponent} from "./components/ogdhcp/og-dhcp-subnets.component";
|
import { OgDhcpSubnetsComponent } from "./components/ogdhcp/og-dhcp-subnets.component";
|
||||||
import {StatusComponent} from "./components/ogdhcp/status/status.component";
|
import { StatusComponent } from "./components/ogdhcp/status/status.component";
|
||||||
import {
|
import {
|
||||||
RunScriptAssistantComponent
|
RunScriptAssistantComponent
|
||||||
} from "./components/groups/components/client-main-view/run-script-assistant/run-script-assistant.component";
|
} from "./components/groups/components/client-main-view/run-script-assistant/run-script-assistant.component";
|
||||||
|
import { roleGuard } from './guards/role.guard';
|
||||||
const routes: Routes = [
|
const routes: Routes = [
|
||||||
{ path: '', redirectTo: 'auth/login', pathMatch: 'full' },
|
{ path: '', redirectTo: 'auth/login', pathMatch: 'full' },
|
||||||
{ path: '', component: MainLayoutComponent,
|
{
|
||||||
|
path: '', component: MainLayoutComponent,
|
||||||
children: [
|
children: [
|
||||||
{ path: 'dashboard', component: DashboardComponent },
|
{ path: 'users', component: UsersComponent, canActivate: [roleGuard], data: { allowedRoles: ['super-admin'] } },
|
||||||
{ path: 'admin', component: AdminComponent },
|
{ path: 'env-vars', component: EnvVarsComponent, canActivate: [roleGuard], data: { allowedRoles: ['super-admin'] } },
|
||||||
{ path: 'users', component: UsersComponent },
|
{ path: 'roles', component: RolesComponent, canActivate: [roleGuard], data: { allowedRoles: ['super-admin'] } },
|
||||||
{ path: 'env-vars', component: EnvVarsComponent },
|
|
||||||
{ path: 'user-groups', component: RolesComponent },
|
|
||||||
{ path: 'groups', component: GroupsComponent },
|
{ path: 'groups', component: GroupsComponent },
|
||||||
{ path: 'pxe-images', component: PXEimagesComponent },
|
{ path: 'pxe-images', component: PXEimagesComponent, canActivate: [roleGuard], data: { allowedRoles: ['super-admin', 'ou-admin'] } },
|
||||||
{ path: 'pxe', component: PxeComponent },
|
{ path: 'pxe', component: PxeComponent, canActivate: [roleGuard], data: { allowedRoles: ['super-admin', 'ou-admin'] } },
|
||||||
{ path: 'pxe-boot-file', component: PxeBootFilesComponent },
|
{ path: 'pxe-boot-file', component: PxeBootFilesComponent, canActivate: [roleGuard], data: { allowedRoles: ['super-admin', 'ou-admin'] } },
|
||||||
{ path: 'ogboot-status', component: OgbootStatusComponent },
|
{ path: 'ogboot-status', component: OgbootStatusComponent, canActivate: [roleGuard], data: { allowedRoles: ['super-admin', 'ou-admin'] } },
|
||||||
{ path: 'subnets', component: OgDhcpSubnetsComponent },
|
{ path: 'subnets', component: OgDhcpSubnetsComponent, canActivate: [roleGuard], data: { allowedRoles: ['super-admin', 'ou-admin'] } },
|
||||||
{ path: 'ogdhcp-status', component: StatusComponent },
|
{ path: 'ogdhcp-status', component: StatusComponent, canActivate: [roleGuard], data: { allowedRoles: ['super-admin', 'ou-admin'] } },
|
||||||
{ path: 'commands', component: CommandsComponent },
|
{ path: 'commands', component: CommandsComponent, canActivate: [roleGuard], data: { allowedRoles: ['super-admin', 'ou-admin'] } },
|
||||||
{ path: 'commands-groups', component: CommandsGroupsComponent },
|
{ path: 'commands-groups', component: CommandsGroupsComponent, canActivate: [roleGuard], data: { allowedRoles: ['super-admin', 'ou-admin'] } },
|
||||||
{ path: 'commands-task', component: CommandsTaskComponent },
|
{ path: 'commands-task', component: CommandsTaskComponent, canActivate: [roleGuard], data: { allowedRoles: ['super-admin', 'ou-admin'] } },
|
||||||
{ path: 'commands-logs', component: TaskLogsComponent },
|
{ path: 'commands-logs', component: TaskLogsComponent, canActivate: [roleGuard], data: { allowedRoles: ['super-admin', 'ou-admin'] } },
|
||||||
{ path: 'calendars', component: CalendarComponent },
|
{ path: 'calendars', component: CalendarComponent, canActivate: [roleGuard], data: { allowedRoles: ['super-admin', 'ou-admin'] } },
|
||||||
{ path: 'clients/deploy-image', component: DeployImageComponent },
|
{ path: 'clients/deploy-image', component: DeployImageComponent, canActivate: [roleGuard], data: { allowedRoles: ['super-admin', 'ou-admin'] } },
|
||||||
{ path: 'clients/partition-assistant', component: PartitionAssistantComponent },
|
{ path: 'clients/partition-assistant', component: PartitionAssistantComponent, canActivate: [roleGuard], data: { allowedRoles: ['super-admin', 'ou-admin'] } },
|
||||||
{ path: 'clients/run-script', component: RunScriptAssistantComponent },
|
{ path: 'clients/run-script', component: RunScriptAssistantComponent, canActivate: [roleGuard], data: { allowedRoles: ['super-admin', 'ou-admin'] } },
|
||||||
{ path: 'clients/:id/create-image', component: CreateClientImageComponent },
|
{ path: 'clients/:id/create-image', component: CreateClientImageComponent, canActivate: [roleGuard], data: { allowedRoles: ['super-admin', 'ou-admin'] } },
|
||||||
{ path: 'repositories', component: RepositoriesComponent },
|
{ path: 'repositories', component: RepositoriesComponent, canActivate: [roleGuard], data: { allowedRoles: ['super-admin', 'ou-admin'] } },
|
||||||
{ path: 'repository/:id', component: MainRepositoryViewComponent },
|
{ path: 'repository/:id', component: MainRepositoryViewComponent, canActivate: [roleGuard], data: { allowedRoles: ['super-admin', 'ou-admin'] } },
|
||||||
{ path: 'software', component: SoftwareComponent },
|
{ path: 'software', component: SoftwareComponent, canActivate: [roleGuard], data: { allowedRoles: ['super-admin', 'ou-admin'] } },
|
||||||
{ path: 'software-profiles', component: SoftwareProfileComponent },
|
{ path: 'software-profiles', component: SoftwareProfileComponent, canActivate: [roleGuard], data: { allowedRoles: ['super-admin', 'ou-admin'] } },
|
||||||
{ path: 'operative-systems', component: OperativeSystemComponent },
|
{ path: 'operative-systems', component: OperativeSystemComponent, canActivate: [roleGuard], data: { allowedRoles: ['super-admin', 'ou-admin'] } },
|
||||||
{ path: 'menus', component: MenusComponent },
|
{ path: 'menus', component: MenusComponent, canActivate: [roleGuard], data: { allowedRoles: ['super-admin', 'ou-admin'] } },
|
||||||
],
|
],
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
|
|
|
@ -17,7 +17,6 @@ import { MatIconModule } from '@angular/material/icon';
|
||||||
import { MatButtonModule } from '@angular/material/button';
|
import { MatButtonModule } from '@angular/material/button';
|
||||||
import { MatSidenavModule } from '@angular/material/sidenav';
|
import { MatSidenavModule } from '@angular/material/sidenav';
|
||||||
import { NoopAnimationsModule } from '@angular/platform-browser/animations';
|
import { NoopAnimationsModule } from '@angular/platform-browser/animations';
|
||||||
import { AdminComponent } from './components/admin/admin.component';
|
|
||||||
import { MatCardModule } from '@angular/material/card';
|
import { MatCardModule } from '@angular/material/card';
|
||||||
import { MatCheckboxModule } from '@angular/material/checkbox';
|
import { MatCheckboxModule } from '@angular/material/checkbox';
|
||||||
import { MatFormFieldModule } from '@angular/material/form-field';
|
import { MatFormFieldModule } from '@angular/material/form-field';
|
||||||
|
@ -173,7 +172,6 @@ registerLocaleData(localeEs, 'es-ES');
|
||||||
HeaderComponent,
|
HeaderComponent,
|
||||||
SidebarComponent,
|
SidebarComponent,
|
||||||
LoginComponent,
|
LoginComponent,
|
||||||
AdminComponent,
|
|
||||||
MainLayoutComponent,
|
MainLayoutComponent,
|
||||||
UsersComponent,
|
UsersComponent,
|
||||||
RolesComponent,
|
RolesComponent,
|
||||||
|
|
|
@ -1,48 +0,0 @@
|
||||||
/* Estilos del contenedor para centrar los botones */
|
|
||||||
.container {
|
|
||||||
display: flex;
|
|
||||||
justify-content: center;
|
|
||||||
align-items: center;
|
|
||||||
height: 100vh;
|
|
||||||
}
|
|
||||||
|
|
||||||
/* Estilos del contenedor de cada botón y texto */
|
|
||||||
.button-container {
|
|
||||||
display: flex;
|
|
||||||
flex-direction: column;
|
|
||||||
align-items: center;
|
|
||||||
margin: 0 10px;
|
|
||||||
}
|
|
||||||
|
|
||||||
/* Estilos del texto debajo de los botones */
|
|
||||||
span{
|
|
||||||
margin: 0;
|
|
||||||
font-size: 20px;
|
|
||||||
text-align: center;
|
|
||||||
}
|
|
||||||
|
|
||||||
/* Media query para hacer los botones responsive */
|
|
||||||
@media (max-width: 900px) {
|
|
||||||
button {
|
|
||||||
height: 120px;
|
|
||||||
width: 120px;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
@media (max-width: 600px) {
|
|
||||||
button {
|
|
||||||
height: 90px;
|
|
||||||
width: 90px;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
@media (max-width: 400px) {
|
|
||||||
button {
|
|
||||||
height: 70px;
|
|
||||||
width: 70px;
|
|
||||||
}
|
|
||||||
|
|
||||||
span{
|
|
||||||
font-size: 14px;
|
|
||||||
}
|
|
||||||
}
|
|
|
@ -1,10 +0,0 @@
|
||||||
<div class="container">
|
|
||||||
<button class="action-button" routerLink="/users">
|
|
||||||
<mat-icon>group</mat-icon>
|
|
||||||
<span>{{ 'labelUsers' | translate }}</span>
|
|
||||||
</button>
|
|
||||||
<button class="action-button" routerLink="/user-groups">
|
|
||||||
<mat-icon>admin_panel_settings</mat-icon>
|
|
||||||
<span>{{ 'labelRoles' | translate }}</span>
|
|
||||||
</button>
|
|
||||||
</div>
|
|
|
@ -1,48 +0,0 @@
|
||||||
import { ComponentFixture, TestBed } from '@angular/core/testing';
|
|
||||||
import { RouterTestingModule } from '@angular/router/testing';
|
|
||||||
import { AdminComponent } from './admin.component';
|
|
||||||
import { MatButtonModule } from '@angular/material/button';
|
|
||||||
import { MatIconModule } from '@angular/material/icon';
|
|
||||||
import { TranslateModule } from '@ngx-translate/core';
|
|
||||||
import { Router } from '@angular/router';
|
|
||||||
|
|
||||||
describe('AdminComponent', () => {
|
|
||||||
let component: AdminComponent;
|
|
||||||
let fixture: ComponentFixture<AdminComponent>;
|
|
||||||
let router: Router;
|
|
||||||
|
|
||||||
beforeEach(async () => {
|
|
||||||
await TestBed.configureTestingModule({
|
|
||||||
declarations: [AdminComponent],
|
|
||||||
imports: [
|
|
||||||
RouterTestingModule,
|
|
||||||
MatButtonModule,
|
|
||||||
MatIconModule,
|
|
||||||
TranslateModule.forRoot()
|
|
||||||
]
|
|
||||||
}).compileComponents();
|
|
||||||
|
|
||||||
router = TestBed.inject(Router);
|
|
||||||
});
|
|
||||||
|
|
||||||
beforeEach(() => {
|
|
||||||
fixture = TestBed.createComponent(AdminComponent);
|
|
||||||
component = fixture.componentInstance;
|
|
||||||
fixture.detectChanges();
|
|
||||||
});
|
|
||||||
|
|
||||||
it('debería crear el componente', () => {
|
|
||||||
expect(component).toBeTruthy();
|
|
||||||
});
|
|
||||||
|
|
||||||
it('debería renderizar dos botones', () => {
|
|
||||||
const buttons = fixture.nativeElement.querySelectorAll('button');
|
|
||||||
expect(buttons.length).toBe(2);
|
|
||||||
});
|
|
||||||
|
|
||||||
it('debería tener un botón con routerLink a "/users"', () => {
|
|
||||||
const button = fixture.nativeElement.querySelector('button[routerLink="/users"]');
|
|
||||||
expect(button).toBeTruthy();
|
|
||||||
expect(button.querySelector('mat-icon').textContent.trim()).toBe('group');
|
|
||||||
});
|
|
||||||
});
|
|
|
@ -1,13 +0,0 @@
|
||||||
import { Component } from '@angular/core';
|
|
||||||
|
|
||||||
|
|
||||||
@Component({
|
|
||||||
selector: 'app-admin',
|
|
||||||
templateUrl: './admin.component.html',
|
|
||||||
styleUrl: './admin.component.css'
|
|
||||||
})
|
|
||||||
|
|
||||||
export class AdminComponent {
|
|
||||||
|
|
||||||
}
|
|
||||||
|
|
|
@ -1,24 +1,24 @@
|
||||||
import { ComponentFixture, TestBed } from '@angular/core/testing';
|
import { ComponentFixture, TestBed } from '@angular/core/testing';
|
||||||
|
|
||||||
import { BootSoPartitionComponent } from './boot-so-partition.component';
|
import { BootSoPartitionComponent } from './boot-so-partition.component';
|
||||||
import {ExecuteCommandComponent} from "../execute-command.component";
|
import { FormBuilder, FormsModule, ReactiveFormsModule } from "@angular/forms";
|
||||||
import {FormBuilder, FormsModule, ReactiveFormsModule} from "@angular/forms";
|
import { MAT_DIALOG_DATA, MatDialogModule, MatDialogRef } from "@angular/material/dialog";
|
||||||
import {MAT_DIALOG_DATA, MatDialogModule, MatDialogRef} from "@angular/material/dialog";
|
import { MatFormFieldModule } from "@angular/material/form-field";
|
||||||
import {MatFormFieldModule} from "@angular/material/form-field";
|
import { MatInputModule } from "@angular/material/input";
|
||||||
import {MatInputModule} from "@angular/material/input";
|
import { MatCheckboxModule } from "@angular/material/checkbox";
|
||||||
import {MatCheckboxModule} from "@angular/material/checkbox";
|
import { MatButtonModule } from "@angular/material/button";
|
||||||
import {MatButtonModule} from "@angular/material/button";
|
import { MatMenuModule } from "@angular/material/menu";
|
||||||
import {MatMenuModule} from "@angular/material/menu";
|
import { BrowserAnimationsModule } from "@angular/platform-browser/animations";
|
||||||
import {BrowserAnimationsModule} from "@angular/platform-browser/animations";
|
import { MatTableModule } from "@angular/material/table";
|
||||||
import {MatTableModule} from "@angular/material/table";
|
import { MatSelectModule } from "@angular/material/select";
|
||||||
import {MatSelectModule} from "@angular/material/select";
|
import { MatIconModule } from "@angular/material/icon";
|
||||||
import {MatIconModule} from "@angular/material/icon";
|
import { ToastrModule, ToastrService } from "ngx-toastr";
|
||||||
import {ToastrModule, ToastrService} from "ngx-toastr";
|
import { TranslateModule } from "@ngx-translate/core";
|
||||||
import {TranslateModule} from "@ngx-translate/core";
|
import { DataService } from "../../data.service";
|
||||||
import {DataService} from "../../data.service";
|
import { provideHttpClient } from "@angular/common/http";
|
||||||
import {provideHttpClient} from "@angular/common/http";
|
import { provideHttpClientTesting } from "@angular/common/http/testing";
|
||||||
import {provideHttpClientTesting} from "@angular/common/http/testing";
|
import { ConfigService } from "@services/config.service";
|
||||||
import {ConfigService} from "@services/config.service";
|
import { MatExpansionModule } from '@angular/material/expansion';
|
||||||
|
import { MatDividerModule } from '@angular/material/divider';
|
||||||
|
|
||||||
describe('BootSoPartitionComponent', () => {
|
describe('BootSoPartitionComponent', () => {
|
||||||
let component: BootSoPartitionComponent;
|
let component: BootSoPartitionComponent;
|
||||||
|
@ -40,9 +40,11 @@ describe('BootSoPartitionComponent', () => {
|
||||||
MatInputModule,
|
MatInputModule,
|
||||||
MatCheckboxModule,
|
MatCheckboxModule,
|
||||||
MatButtonModule,
|
MatButtonModule,
|
||||||
|
MatExpansionModule,
|
||||||
MatMenuModule,
|
MatMenuModule,
|
||||||
BrowserAnimationsModule,
|
BrowserAnimationsModule,
|
||||||
MatTableModule,
|
MatTableModule,
|
||||||
|
MatDividerModule,
|
||||||
MatSelectModule,
|
MatSelectModule,
|
||||||
MatIconModule,
|
MatIconModule,
|
||||||
ToastrModule.forRoot(),
|
ToastrModule.forRoot(),
|
||||||
|
@ -60,7 +62,9 @@ describe('BootSoPartitionComponent', () => {
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
provide: MAT_DIALOG_DATA,
|
provide: MAT_DIALOG_DATA,
|
||||||
useValue: {}
|
useValue: {
|
||||||
|
clients: []
|
||||||
|
}
|
||||||
},
|
},
|
||||||
{ provide: ConfigService, useValue: mockConfigService }
|
{ provide: ConfigService, useValue: mockConfigService }
|
||||||
]
|
]
|
||||||
|
|
|
@ -1,16 +1,16 @@
|
||||||
import {Component, Inject, OnInit} from '@angular/core';
|
import { Component, Inject, OnInit } from '@angular/core';
|
||||||
import {MAT_DIALOG_DATA, MatDialogRef} from "@angular/material/dialog";
|
import { MAT_DIALOG_DATA, MatDialogRef } from "@angular/material/dialog";
|
||||||
import {MatTableDataSource} from "@angular/material/table";
|
import { MatTableDataSource } from "@angular/material/table";
|
||||||
import {ConfigService} from "@services/config.service";
|
import { ConfigService } from "@services/config.service";
|
||||||
import {HttpClient} from "@angular/common/http";
|
import { HttpClient } from "@angular/common/http";
|
||||||
import {ToastrService} from "ngx-toastr";
|
import { ToastrService } from "ngx-toastr";
|
||||||
|
|
||||||
@Component({
|
@Component({
|
||||||
selector: 'app-boot-so-partition',
|
selector: 'app-boot-so-partition',
|
||||||
templateUrl: './boot-so-partition.component.html',
|
templateUrl: './boot-so-partition.component.html',
|
||||||
styleUrl: './boot-so-partition.component.css'
|
styleUrl: './boot-so-partition.component.css'
|
||||||
})
|
})
|
||||||
export class BootSoPartitionComponent implements OnInit{
|
export class BootSoPartitionComponent implements OnInit {
|
||||||
baseUrl: string;
|
baseUrl: string;
|
||||||
selectedPartition: any = null;
|
selectedPartition: any = null;
|
||||||
dataSource = new MatTableDataSource<any>();
|
dataSource = new MatTableDataSource<any>();
|
||||||
|
|
|
@ -3,9 +3,10 @@ import { HttpClient } from '@angular/common/http';
|
||||||
import { Router } from "@angular/router";
|
import { Router } from "@angular/router";
|
||||||
import { ToastrService } from "ngx-toastr";
|
import { ToastrService } from "ngx-toastr";
|
||||||
import { ConfigService } from '@services/config.service';
|
import { ConfigService } from '@services/config.service';
|
||||||
import {BootSoPartitionComponent} from "./boot-so-partition/boot-so-partition.component";
|
import { BootSoPartitionComponent } from "./boot-so-partition/boot-so-partition.component";
|
||||||
import {MatDialog} from "@angular/material/dialog";
|
import { MatDialog } from "@angular/material/dialog";
|
||||||
import {RemoveCacheImageComponent} from "./remove-cache-image/remove-cache-image.component";
|
import { RemoveCacheImageComponent } from "./remove-cache-image/remove-cache-image.component";
|
||||||
|
import { AuthService } from '@services/auth.service';
|
||||||
|
|
||||||
@Component({
|
@Component({
|
||||||
selector: 'app-execute-command',
|
selector: 'app-execute-command',
|
||||||
|
@ -44,6 +45,7 @@ export class ExecuteCommandComponent implements OnInit {
|
||||||
private router: Router,
|
private router: Router,
|
||||||
private configService: ConfigService,
|
private configService: ConfigService,
|
||||||
private toastService: ToastrService,
|
private toastService: ToastrService,
|
||||||
|
public auth: AuthService,
|
||||||
private dialog: MatDialog,
|
private dialog: MatDialog,
|
||||||
) {
|
) {
|
||||||
this.baseUrl = this.configService.apiUrl;
|
this.baseUrl = this.configService.apiUrl;
|
||||||
|
@ -51,6 +53,9 @@ export class ExecuteCommandComponent implements OnInit {
|
||||||
|
|
||||||
ngOnInit(): void {
|
ngOnInit(): void {
|
||||||
this.clientData = this.clientData || [];
|
this.clientData = this.clientData || [];
|
||||||
|
const allowed = this.getAllowedCommandsByRole();
|
||||||
|
this.arrayCommands = this.arrayCommands.filter(c => allowed.includes(c.slug));
|
||||||
|
|
||||||
this.updateCommandStates();
|
this.updateCommandStates();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -58,6 +63,34 @@ export class ExecuteCommandComponent implements OnInit {
|
||||||
this.updateCommandStates();
|
this.updateCommandStates();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
private getAllowedCommandsByRole(): string[] {
|
||||||
|
const role = this.auth.userCategory;
|
||||||
|
|
||||||
|
const permissions: Record<string, string[]> = {
|
||||||
|
'super-admin': ['*'],
|
||||||
|
'ou-admin': ['*'],
|
||||||
|
'ou-operator': [
|
||||||
|
'power-on',
|
||||||
|
'power-off',
|
||||||
|
'reboot',
|
||||||
|
'login',
|
||||||
|
'deploy-image',
|
||||||
|
'software-inventory',
|
||||||
|
'hardware-inventory',
|
||||||
|
'remove-cache-image',
|
||||||
|
'partition'
|
||||||
|
],
|
||||||
|
'ou-minimal': [
|
||||||
|
'power-on',
|
||||||
|
'power-off'
|
||||||
|
]
|
||||||
|
};
|
||||||
|
|
||||||
|
const allowed = permissions[role] || [];
|
||||||
|
return allowed.includes('*') ? this.arrayCommands.map(c => c.slug) : allowed;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
private updateCommandStates(): void {
|
private updateCommandStates(): void {
|
||||||
let states: string[] = [];
|
let states: string[] = [];
|
||||||
|
|
||||||
|
|
|
@ -1,24 +1,25 @@
|
||||||
import { ComponentFixture, TestBed } from '@angular/core/testing';
|
import { ComponentFixture, TestBed } from '@angular/core/testing';
|
||||||
|
|
||||||
import { RemoveCacheImageComponent } from './remove-cache-image.component';
|
import { RemoveCacheImageComponent } from './remove-cache-image.component';
|
||||||
import {BootSoPartitionComponent} from "../boot-so-partition/boot-so-partition.component";
|
import { FormBuilder, FormsModule, ReactiveFormsModule } from "@angular/forms";
|
||||||
import {FormBuilder, FormsModule, ReactiveFormsModule} from "@angular/forms";
|
import { MAT_DIALOG_DATA, MatDialogModule, MatDialogRef } from "@angular/material/dialog";
|
||||||
import {MAT_DIALOG_DATA, MatDialogModule, MatDialogRef} from "@angular/material/dialog";
|
import { MatFormFieldModule } from "@angular/material/form-field";
|
||||||
import {MatFormFieldModule} from "@angular/material/form-field";
|
import { MatInputModule } from "@angular/material/input";
|
||||||
import {MatInputModule} from "@angular/material/input";
|
import { MatCheckboxModule } from "@angular/material/checkbox";
|
||||||
import {MatCheckboxModule} from "@angular/material/checkbox";
|
import { MatButtonModule } from "@angular/material/button";
|
||||||
import {MatButtonModule} from "@angular/material/button";
|
import { MatMenuModule } from "@angular/material/menu";
|
||||||
import {MatMenuModule} from "@angular/material/menu";
|
import { BrowserAnimationsModule } from "@angular/platform-browser/animations";
|
||||||
import {BrowserAnimationsModule} from "@angular/platform-browser/animations";
|
import { MatTableModule } from "@angular/material/table";
|
||||||
import {MatTableModule} from "@angular/material/table";
|
import { MatSelectModule } from "@angular/material/select";
|
||||||
import {MatSelectModule} from "@angular/material/select";
|
import { MatIconModule } from "@angular/material/icon";
|
||||||
import {MatIconModule} from "@angular/material/icon";
|
import { ToastrModule, ToastrService } from "ngx-toastr";
|
||||||
import {ToastrModule, ToastrService} from "ngx-toastr";
|
import { TranslateModule } from "@ngx-translate/core";
|
||||||
import {TranslateModule} from "@ngx-translate/core";
|
import { DataService } from "../../data.service";
|
||||||
import {DataService} from "../../data.service";
|
import { provideHttpClient } from "@angular/common/http";
|
||||||
import {provideHttpClient} from "@angular/common/http";
|
import { provideHttpClientTesting } from "@angular/common/http/testing";
|
||||||
import {provideHttpClientTesting} from "@angular/common/http/testing";
|
import { ConfigService } from "@services/config.service";
|
||||||
import {ConfigService} from "@services/config.service";
|
import { MatExpansionModule } from '@angular/material/expansion';
|
||||||
|
import { MatDividerModule } from '@angular/material/divider';
|
||||||
|
import { MatRadioModule } from '@angular/material/radio';
|
||||||
|
|
||||||
describe('RemoveCacheImageComponent', () => {
|
describe('RemoveCacheImageComponent', () => {
|
||||||
let component: RemoveCacheImageComponent;
|
let component: RemoveCacheImageComponent;
|
||||||
|
@ -41,9 +42,12 @@ describe('RemoveCacheImageComponent', () => {
|
||||||
MatCheckboxModule,
|
MatCheckboxModule,
|
||||||
MatButtonModule,
|
MatButtonModule,
|
||||||
MatMenuModule,
|
MatMenuModule,
|
||||||
|
MatExpansionModule,
|
||||||
BrowserAnimationsModule,
|
BrowserAnimationsModule,
|
||||||
MatTableModule,
|
MatTableModule,
|
||||||
|
MatDividerModule,
|
||||||
MatSelectModule,
|
MatSelectModule,
|
||||||
|
MatRadioModule,
|
||||||
MatIconModule,
|
MatIconModule,
|
||||||
ToastrModule.forRoot(),
|
ToastrModule.forRoot(),
|
||||||
TranslateModule.forRoot()
|
TranslateModule.forRoot()
|
||||||
|
@ -60,7 +64,17 @@ describe('RemoveCacheImageComponent', () => {
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
provide: MAT_DIALOG_DATA,
|
provide: MAT_DIALOG_DATA,
|
||||||
useValue: {}
|
useValue: {
|
||||||
|
clients: [
|
||||||
|
{
|
||||||
|
'@id': '/clients/1',
|
||||||
|
uuid: 'client-uuid-1',
|
||||||
|
selected: false,
|
||||||
|
status: 'og-live',
|
||||||
|
state: 'og-live'
|
||||||
|
}
|
||||||
|
]
|
||||||
|
}
|
||||||
},
|
},
|
||||||
{ provide: ConfigService, useValue: mockConfigService }
|
{ provide: ConfigService, useValue: mockConfigService }
|
||||||
]
|
]
|
||||||
|
|
|
@ -1 +0,0 @@
|
||||||
<p>dashboard works!</p>
|
|
|
@ -1,23 +0,0 @@
|
||||||
import { ComponentFixture, TestBed } from '@angular/core/testing';
|
|
||||||
import { DashboardComponent } from './dashboard.component';
|
|
||||||
|
|
||||||
describe('DashboardComponent', () => {
|
|
||||||
let component: DashboardComponent;
|
|
||||||
let fixture: ComponentFixture<DashboardComponent>;
|
|
||||||
|
|
||||||
beforeEach(async () => {
|
|
||||||
await TestBed.configureTestingModule({
|
|
||||||
declarations: [DashboardComponent]
|
|
||||||
}).compileComponents();
|
|
||||||
});
|
|
||||||
|
|
||||||
beforeEach(() => {
|
|
||||||
fixture = TestBed.createComponent(DashboardComponent);
|
|
||||||
component = fixture.componentInstance;
|
|
||||||
fixture.detectChanges();
|
|
||||||
});
|
|
||||||
|
|
||||||
it('should create the component', () => {
|
|
||||||
expect(component).toBeTruthy();
|
|
||||||
});
|
|
||||||
});
|
|
|
@ -1,10 +0,0 @@
|
||||||
import { Component } from '@angular/core';
|
|
||||||
|
|
||||||
@Component({
|
|
||||||
selector: 'app-dashboard',
|
|
||||||
templateUrl: './dashboard.component.html',
|
|
||||||
styleUrl: './dashboard.component.css'
|
|
||||||
})
|
|
||||||
export class DashboardComponent {
|
|
||||||
|
|
||||||
}
|
|
|
@ -11,11 +11,12 @@
|
||||||
</div>
|
</div>
|
||||||
<div class="groups-button-row">
|
<div class="groups-button-row">
|
||||||
<div joyrideStep="addStep" text="{{ 'groupsAddStepText' | translate }}" style="display: flex; gap: 15px;">
|
<div joyrideStep="addStep" text="{{ 'groupsAddStepText' | translate }}" style="display: flex; gap: 15px;">
|
||||||
<button class="action-button" (click)="addOU($event)"
|
<button class="action-button" (click)="addOU($event)" *ngIf="auth.userCategory !== 'ou-minimal'"
|
||||||
matTooltip="{{ 'newOrganizationalUnitTooltip' | translate }}" matTooltipShowDelay="1000">
|
matTooltip="{{ 'newOrganizationalUnitTooltip' | translate }}" matTooltipShowDelay="1000">
|
||||||
{{ 'newOrganizationalUnitButton' | translate }}
|
{{ 'newOrganizationalUnitButton' | translate }}
|
||||||
</button>
|
</button>
|
||||||
<button class="action-button" [matMenuTriggerFor]="menuClients">{{ 'newClientButton' | translate }}</button>
|
<button class="action-button" [matMenuTriggerFor]="menuClients" *ngIf="auth.userCategory !== 'ou-minimal'">{{
|
||||||
|
'newClientButton' | translate }}</button>
|
||||||
<mat-menu #menuClients="matMenu">
|
<mat-menu #menuClients="matMenu">
|
||||||
<button mat-menu-item (click)="addClient($event)">{{ 'newSingleClientButton' | translate }}</button>
|
<button mat-menu-item (click)="addClient($event)">{{ 'newSingleClientButton' | translate }}</button>
|
||||||
<button mat-menu-item (click)="addMultipleClients($event)">{{ 'newMultipleClientButton' | translate
|
<button mat-menu-item (click)="addMultipleClients($event)">{{ 'newMultipleClientButton' | translate
|
||||||
|
@ -180,23 +181,23 @@
|
||||||
<mat-icon>map</mat-icon>
|
<mat-icon>map</mat-icon>
|
||||||
<span>{{ 'roomMap' | translate }}</span>
|
<span>{{ 'roomMap' | translate }}</span>
|
||||||
</button>
|
</button>
|
||||||
<button mat-menu-item (click)="addClient($event, selectedNode)">
|
<button mat-menu-item (click)="addClient($event, selectedNode)" *ngIf="auth.userCategory !== 'ou-minimal'">
|
||||||
<mat-icon>add</mat-icon>
|
<mat-icon>add</mat-icon>
|
||||||
<span>{{ 'newSingleClientButton' | translate }}</span>
|
<span>{{ 'newSingleClientButton' | translate }}</span>
|
||||||
</button>
|
</button>
|
||||||
<button mat-menu-item (click)="addMultipleClients($event, selectedNode)">
|
<button mat-menu-item (click)="addMultipleClients($event, selectedNode)" *ngIf="auth.userCategory !== 'ou-minimal'">
|
||||||
<mat-icon>playlist_add</mat-icon>
|
<mat-icon>playlist_add</mat-icon>
|
||||||
<span>{{ 'newMultipleClientButton' | translate }}</span>
|
<span>{{ 'newMultipleClientButton' | translate }}</span>
|
||||||
</button>
|
</button>
|
||||||
<button mat-menu-item (click)="addOU($event, selectedNode)">
|
<button mat-menu-item (click)="addOU($event, selectedNode)" *ngIf="auth.userCategory !== 'ou-minimal'">
|
||||||
<mat-icon>account_tree</mat-icon>
|
<mat-icon>account_tree</mat-icon>
|
||||||
<span>{{ 'addOrganizationalUnit' | translate }}</span>
|
<span>{{ 'addOrganizationalUnit' | translate }}</span>
|
||||||
</button>
|
</button>
|
||||||
<button mat-menu-item (click)="onEditNode($event, selectedNode)">
|
<button mat-menu-item (click)="onEditNode($event, selectedNode)" *ngIf="auth.userCategory !== 'ou-minimal'">
|
||||||
<mat-icon>edit</mat-icon>
|
<mat-icon>edit</mat-icon>
|
||||||
<span>{{ 'edit' | translate }}</span>
|
<span>{{ 'edit' | translate }}</span>
|
||||||
</button>
|
</button>
|
||||||
<button mat-menu-item (click)="onDeleteClick($event, selectedNode)">
|
<button mat-menu-item (click)="onDeleteClick($event, selectedNode)" *ngIf="auth.userCategory !== 'ou-minimal'">
|
||||||
<mat-icon>delete</mat-icon>
|
<mat-icon>delete</mat-icon>
|
||||||
<span>{{ 'delete' | translate }}</span>
|
<span>{{ 'delete' | translate }}</span>
|
||||||
</button>
|
</button>
|
||||||
|
@ -292,7 +293,7 @@
|
||||||
</span>
|
</span>
|
||||||
|
|
||||||
<mat-menu #clientMenu="matMenu">
|
<mat-menu #clientMenu="matMenu">
|
||||||
<button mat-menu-item (click)="onEditClick($event, client.type, client.uuid)">
|
<button mat-menu-item (click)="onEditClick($event, client.type, client.uuid)" *ngIf="auth.userCategory !== 'ou-minimal'">
|
||||||
<mat-icon>edit</mat-icon>
|
<mat-icon>edit</mat-icon>
|
||||||
<span>{{ 'edit' | translate }}</span>
|
<span>{{ 'edit' | translate }}</span>
|
||||||
</button>
|
</button>
|
||||||
|
@ -309,7 +310,7 @@
|
||||||
<mat-icon>list_alt</mat-icon>
|
<mat-icon>list_alt</mat-icon>
|
||||||
<span>{{ 'procedimientosCliente' | translate }}</span>
|
<span>{{ 'procedimientosCliente' | translate }}</span>
|
||||||
</button>
|
</button>
|
||||||
<button mat-menu-item (click)="onDeleteClick($event, client)">
|
<button mat-menu-item (click)="onDeleteClick($event, client)" *ngIf="auth.userCategory !== 'ou-minimal'">
|
||||||
<mat-icon>delete</mat-icon>
|
<mat-icon>delete</mat-icon>
|
||||||
<span>{{ 'delete' | translate }}</span>
|
<span>{{ 'delete' | translate }}</span>
|
||||||
</button>
|
</button>
|
||||||
|
@ -427,7 +428,7 @@
|
||||||
[runScriptContext]="getRunScriptContext([client])">
|
[runScriptContext]="getRunScriptContext([client])">
|
||||||
</app-execute-command>
|
</app-execute-command>
|
||||||
<mat-menu #clientMenu="matMenu">
|
<mat-menu #clientMenu="matMenu">
|
||||||
<button mat-menu-item (click)="onEditClick($event, client.type, client.uuid)">
|
<button mat-menu-item (click)="onEditClick($event, client.type, client.uuid)" *ngIf="auth.userCategory !== 'ou-minimal'">
|
||||||
<mat-icon>edit</mat-icon>
|
<mat-icon>edit</mat-icon>
|
||||||
<span>{{ 'edit' | translate }}</span>
|
<span>{{ 'edit' | translate }}</span>
|
||||||
</button>
|
</button>
|
||||||
|
@ -443,7 +444,7 @@
|
||||||
<mat-icon>list_alt</mat-icon>
|
<mat-icon>list_alt</mat-icon>
|
||||||
<span>{{ 'procedimientosCliente' | translate }}</span>
|
<span>{{ 'procedimientosCliente' | translate }}</span>
|
||||||
</button>
|
</button>
|
||||||
<button mat-menu-item (click)="onDeleteClick($event, client)">
|
<button mat-menu-item (click)="onDeleteClick($event, client)" *ngIf="auth.userCategory !== 'ou-minimal'">
|
||||||
<mat-icon>delete</mat-icon>
|
<mat-icon>delete</mat-icon>
|
||||||
<span>{{ 'delete' | translate }}</span>
|
<span>{{ 'delete' | translate }}</span>
|
||||||
</button>
|
</button>
|
||||||
|
|
|
@ -30,6 +30,7 @@ import { ClientDetailsComponent } from './shared/client-details/client-details.c
|
||||||
import { PartitionTypeOrganizatorComponent } from './shared/partition-type-organizator/partition-type-organizator.component';
|
import { PartitionTypeOrganizatorComponent } from './shared/partition-type-organizator/partition-type-organizator.component';
|
||||||
import { ClientTaskLogsComponent } from '../task-logs/client-task-logs/client-task-logs.component';
|
import { ClientTaskLogsComponent } from '../task-logs/client-task-logs/client-task-logs.component';
|
||||||
import {ChangeParentComponent} from "./shared/change-parent/change-parent.component";
|
import {ChangeParentComponent} from "./shared/change-parent/change-parent.component";
|
||||||
|
import { AuthService } from '@services/auth.service';
|
||||||
|
|
||||||
enum NodeType {
|
enum NodeType {
|
||||||
OrganizationalUnit = 'organizational-unit',
|
OrganizationalUnit = 'organizational-unit',
|
||||||
|
@ -115,6 +116,7 @@ export class GroupsComponent implements OnInit, OnDestroy {
|
||||||
private joyrideService: JoyrideService,
|
private joyrideService: JoyrideService,
|
||||||
private breakpointObserver: BreakpointObserver,
|
private breakpointObserver: BreakpointObserver,
|
||||||
private toastr: ToastrService,
|
private toastr: ToastrService,
|
||||||
|
public auth: AuthService,
|
||||||
private configService: ConfigService,
|
private configService: ConfigService,
|
||||||
private cd: ChangeDetectorRef,
|
private cd: ChangeDetectorRef,
|
||||||
) {
|
) {
|
||||||
|
@ -133,7 +135,7 @@ export class GroupsComponent implements OnInit, OnDestroy {
|
||||||
);
|
);
|
||||||
|
|
||||||
this.treeDataSource = new MatTreeFlatDataSource(this.treeControl, this.treeFlattener);
|
this.treeDataSource = new MatTreeFlatDataSource(this.treeControl, this.treeFlattener);
|
||||||
this.currentView = localStorage.getItem('groupsView') || 'list';
|
this.currentView = this.auth.groupsView || 'list';
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
@ -885,7 +887,7 @@ export class GroupsComponent implements OnInit, OnDestroy {
|
||||||
|
|
||||||
this.dialog.open(ClientTaskLogsComponent, {
|
this.dialog.open(ClientTaskLogsComponent, {
|
||||||
width: '1200px',
|
width: '1200px',
|
||||||
data: {client}
|
data: { client }
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -3,10 +3,10 @@ import { Component, signal } from '@angular/core';
|
||||||
import { Router } from '@angular/router';
|
import { Router } from '@angular/router';
|
||||||
import { TranslateService } from '@ngx-translate/core';
|
import { TranslateService } from '@ngx-translate/core';
|
||||||
import { ToastrService } from "ngx-toastr";
|
import { ToastrService } from "ngx-toastr";
|
||||||
import { jwtDecode } from "jwt-decode";
|
|
||||||
import { ConfigService } from '@services/config.service';
|
import { ConfigService } from '@services/config.service';
|
||||||
import { MatDialog } from '@angular/material/dialog';
|
import { MatDialog } from '@angular/material/dialog';
|
||||||
import { GlobalStatusComponent } from '../global-status/global-status.component'
|
import { GlobalStatusComponent } from '../global-status/global-status.component'
|
||||||
|
import { AuthService } from '@services/auth.service';
|
||||||
|
|
||||||
@Component({
|
@Component({
|
||||||
selector: 'app-login',
|
selector: 'app-login',
|
||||||
|
@ -20,8 +20,6 @@ export class LoginComponent {
|
||||||
};
|
};
|
||||||
errorMessage: string = '';
|
errorMessage: string = '';
|
||||||
isLoading: boolean = false;
|
isLoading: boolean = false;
|
||||||
decodedToken: any;
|
|
||||||
|
|
||||||
baseUrl: string;
|
baseUrl: string;
|
||||||
|
|
||||||
constructor(
|
constructor(
|
||||||
|
@ -29,6 +27,7 @@ export class LoginComponent {
|
||||||
private router: Router,
|
private router: Router,
|
||||||
private configService: ConfigService,
|
private configService: ConfigService,
|
||||||
private toastService: ToastrService,
|
private toastService: ToastrService,
|
||||||
|
private auth: AuthService,
|
||||||
private translateService: TranslateService,
|
private translateService: TranslateService,
|
||||||
private dialog: MatDialog
|
private dialog: MatDialog
|
||||||
) {
|
) {
|
||||||
|
@ -62,13 +61,8 @@ export class LoginComponent {
|
||||||
next: (res: any) => {
|
next: (res: any) => {
|
||||||
if (res.token) {
|
if (res.token) {
|
||||||
localStorage.setItem('loginToken', res.token);
|
localStorage.setItem('loginToken', res.token);
|
||||||
localStorage.setItem('refreshToken', res.refreshToken);
|
this.auth.refresh();
|
||||||
localStorage.setItem('username', this.loginObj.username);
|
this.openSnackBar(false, 'Bienvenido ' + this.auth.username);
|
||||||
|
|
||||||
this.decodedToken = jwtDecode(res.token);
|
|
||||||
localStorage.setItem('groupsView', this.decodedToken.groupsView);
|
|
||||||
|
|
||||||
this.openSnackBar(false, 'Bienvenido ' + this.loginObj.username);
|
|
||||||
this.router.navigateByUrl('/groups');
|
this.router.navigateByUrl('/groups');
|
||||||
this.dialog.open(GlobalStatusComponent, {
|
this.dialog.open(GlobalStatusComponent, {
|
||||||
width: '45vw',
|
width: '45vw',
|
||||||
|
|
|
@ -0,0 +1,17 @@
|
||||||
|
import { TestBed } from '@angular/core/testing';
|
||||||
|
import { CanActivateFn } from '@angular/router';
|
||||||
|
|
||||||
|
import { roleGuard } from './role.guard';
|
||||||
|
|
||||||
|
describe('roleGuard', () => {
|
||||||
|
const executeGuard: CanActivateFn = (...guardParameters) =>
|
||||||
|
TestBed.runInInjectionContext(() => roleGuard(...guardParameters));
|
||||||
|
|
||||||
|
beforeEach(() => {
|
||||||
|
TestBed.configureTestingModule({});
|
||||||
|
});
|
||||||
|
|
||||||
|
it('should be created', () => {
|
||||||
|
expect(executeGuard).toBeTruthy();
|
||||||
|
});
|
||||||
|
});
|
|
@ -0,0 +1,19 @@
|
||||||
|
import { inject } from '@angular/core';
|
||||||
|
import { CanActivateFn, Router } from '@angular/router';
|
||||||
|
import { AuthService } from '@services/auth.service';
|
||||||
|
|
||||||
|
export const roleGuard: CanActivateFn = (route, state) => {
|
||||||
|
const auth = inject(AuthService);
|
||||||
|
const router = inject(Router);
|
||||||
|
|
||||||
|
const currentRole = auth.getCurrentRole();
|
||||||
|
|
||||||
|
const allowedRoles = route.data?.['allowedRoles'] as string[];
|
||||||
|
|
||||||
|
if (allowedRoles?.includes(currentRole)) {
|
||||||
|
return true;
|
||||||
|
} else {
|
||||||
|
router.navigate(['/groups']);
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
};
|
|
@ -18,17 +18,17 @@
|
||||||
{{ 'GlobalStatus' | translate }}
|
{{ 'GlobalStatus' | translate }}
|
||||||
</button>
|
</button>
|
||||||
|
|
||||||
<button class="ordinary-button" *ngIf="isSuperAdmin" [matMenuTriggerFor]="menu"
|
<button class="ordinary-button" *ngIf="auth.userCategory === 'super-admin'" [matMenuTriggerFor]="menu"
|
||||||
matTooltip="Gestión de usuarios y roles de la aplicación" matTooltipShowDelay="1000">
|
matTooltip="Gestión de usuarios y roles de la aplicación" matTooltipShowDelay="1000">
|
||||||
{{ 'Administration' | translate }}
|
{{ 'Administration' | translate }}
|
||||||
</button>
|
</button>
|
||||||
|
|
||||||
<button class="ordinary-button" *ngIf="!isSuperAdmin" (click)="editUser()"
|
<button class="ordinary-button" (click)="editUser()"
|
||||||
matTooltip="Editar tu información de usuario" matTooltipShowDelay="1000">
|
matTooltip="Editar tu información de usuario" matTooltipShowDelay="1000">
|
||||||
{{ 'changePassword' | translate }}
|
{{ 'changePassword' | translate }}
|
||||||
</button>
|
</button>
|
||||||
|
|
||||||
<button class="logout-button" routerLink="/auth/login" matTooltip="Cerrar sesión y salir de la aplicación"
|
<button class="logout-button" (click)="logOut()" matTooltip="Cerrar sesión y salir de la aplicación"
|
||||||
matTooltipShowDelay="1000">
|
matTooltipShowDelay="1000">
|
||||||
{{ 'logout' | translate }}
|
{{ 'logout' | translate }}
|
||||||
</button>
|
</button>
|
||||||
|
@ -47,10 +47,10 @@
|
||||||
<button mat-menu-item (click)="showGlobalStatus()">
|
<button mat-menu-item (click)="showGlobalStatus()">
|
||||||
{{ 'GlobalStatus' | translate }}
|
{{ 'GlobalStatus' | translate }}
|
||||||
</button>
|
</button>
|
||||||
<button mat-menu-item *ngIf="isSuperAdmin" [matMenuTriggerFor]="menu">
|
<button mat-menu-item *ngIf="auth.userCategory === 'super-admin'" [matMenuTriggerFor]="menu">
|
||||||
{{ 'Administration' | translate }}
|
{{ 'Administration' | translate }}
|
||||||
</button>
|
</button>
|
||||||
<button mat-menu-item *ngIf="!isSuperAdmin" (click)="editUser()">
|
<button mat-menu-item *ngIf="auth.userCategory === 'super-admin'" (click)="editUser()">
|
||||||
{{ 'changePassword' | translate }}
|
{{ 'changePassword' | translate }}
|
||||||
</button>
|
</button>
|
||||||
</mat-menu>
|
</mat-menu>
|
||||||
|
@ -65,7 +65,7 @@
|
||||||
matTooltipShowDelay="1000">
|
matTooltipShowDelay="1000">
|
||||||
{{ 'labelUsers' | translate }}
|
{{ 'labelUsers' | translate }}
|
||||||
</button>
|
</button>
|
||||||
<button mat-menu-item routerLink="/user-groups" matTooltip="Gestionar roles de usuario" matTooltipShowDelay="1000">
|
<button mat-menu-item routerLink="/roles" matTooltip="Gestionar roles de usuario" matTooltipShowDelay="1000">
|
||||||
{{ 'labelRoles' | translate }}
|
{{ 'labelRoles' | translate }}
|
||||||
</button>
|
</button>
|
||||||
<button mat-menu-item routerLink="/env-vars" matTooltip="Gestionar variables de entorno" matTooltipShowDelay="1000">
|
<button mat-menu-item routerLink="/env-vars" matTooltip="Gestionar variables de entorno" matTooltipShowDelay="1000">
|
||||||
|
|
|
@ -1,9 +1,9 @@
|
||||||
import { Component, EventEmitter, OnInit, Output } from '@angular/core';
|
import { Component, EventEmitter, OnInit, Output } from '@angular/core';
|
||||||
import { jwtDecode } from 'jwt-decode';
|
|
||||||
import { ChangePasswordModalComponent } from '../../components/admin/users/users/change-password-modal/change-password-modal.component';
|
import { ChangePasswordModalComponent } from '../../components/admin/users/users/change-password-modal/change-password-modal.component';
|
||||||
import { MatDialog } from "@angular/material/dialog";
|
import { MatDialog } from "@angular/material/dialog";
|
||||||
import { GlobalStatusComponent } from 'src/app/components/global-status/global-status.component';
|
import { GlobalStatusComponent } from 'src/app/components/global-status/global-status.component';
|
||||||
import { BreakpointObserver, Breakpoints } from '@angular/cdk/layout';
|
import { BreakpointObserver } from '@angular/cdk/layout';
|
||||||
|
import { AuthService } from '@services/auth.service';
|
||||||
|
|
||||||
@Component({
|
@Component({
|
||||||
selector: 'app-header',
|
selector: 'app-header',
|
||||||
|
@ -16,39 +16,26 @@ export class HeaderComponent implements OnInit {
|
||||||
isSmallScreen: boolean = false;
|
isSmallScreen: boolean = false;
|
||||||
|
|
||||||
@Output() toggleSidebar = new EventEmitter<void>();
|
@Output() toggleSidebar = new EventEmitter<void>();
|
||||||
private decodedToken: any;
|
|
||||||
private username: any;
|
|
||||||
|
|
||||||
onToggleSidebar() {
|
onToggleSidebar() {
|
||||||
this.toggleSidebar.emit();
|
this.toggleSidebar.emit();
|
||||||
}
|
}
|
||||||
|
|
||||||
constructor(public dialog: MatDialog, private breakpointObserver: BreakpointObserver) { }
|
constructor(
|
||||||
|
public dialog: MatDialog,
|
||||||
|
public auth: AuthService,
|
||||||
|
private breakpointObserver: BreakpointObserver
|
||||||
|
) { }
|
||||||
|
|
||||||
ngOnInit(): void {
|
ngOnInit(): void {
|
||||||
const token = localStorage.getItem('loginToken');
|
|
||||||
if (token) {
|
|
||||||
try {
|
|
||||||
this.decodedToken = jwtDecode(token);
|
|
||||||
this.isSuperAdmin = this.decodedToken.roles.includes('ROLE_SUPER_ADMIN');
|
|
||||||
localStorage.setItem('isSuperAdmin', String(this.isSuperAdmin));
|
|
||||||
this.username = this.decodedToken.username;
|
|
||||||
} catch (error) {
|
|
||||||
console.error('Error decoding JWT:', error);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
this.breakpointObserver.observe(['(max-width: 576px)']).subscribe((result) => {
|
this.breakpointObserver.observe(['(max-width: 576px)']).subscribe((result) => {
|
||||||
this.isSmallScreen = result.matches;
|
this.isSmallScreen = result.matches;
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
|
|
||||||
ngDoCheck(): void {
|
|
||||||
this.isSuperAdmin = localStorage.getItem('isSuperAdmin') === 'true';
|
|
||||||
}
|
|
||||||
|
|
||||||
editUser() {
|
editUser() {
|
||||||
const dialogRef = this.dialog.open(ChangePasswordModalComponent, {
|
const dialogRef = this.dialog.open(ChangePasswordModalComponent, {
|
||||||
data: { user: this.decodedToken.username, uuid: this.decodedToken.uuid },
|
data: { user: this.auth.username, uuid: this.auth.uuid },
|
||||||
width: '400px',
|
width: '400px',
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
@ -56,7 +43,11 @@ export class HeaderComponent implements OnInit {
|
||||||
showGlobalStatus() {
|
showGlobalStatus() {
|
||||||
this.dialog.open(GlobalStatusComponent, {
|
this.dialog.open(GlobalStatusComponent, {
|
||||||
width: '45vw',
|
width: '45vw',
|
||||||
height: '80vh',
|
height: '80vh',
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
|
|
||||||
|
logOut() {
|
||||||
|
this.auth.logout();
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -1,9 +1,9 @@
|
||||||
<mat-nav-list class="sidebar-content">
|
<mat-nav-list class="sidebar-content">
|
||||||
<div disabled class="user-info">
|
<div disabled class="user-info">
|
||||||
<div class="user-info-wrapper" matTooltipShowDelay="1000">
|
<div class="user-info-wrapper" matTooltipShowDelay="1000">
|
||||||
<img ngSrc="assets/images/logo.png" alt="Logo" class="user-logo" height="500" width="500"/>
|
<img ngSrc="assets/images/logo.png" alt="Logo" class="user-logo" height="500" width="500" />
|
||||||
<span class="user-logged">
|
<span class="user-logged">
|
||||||
{{ 'welcomeUser' | translate:{username: username} }}
|
{{ 'welcomeUser' | translate:{username: username} }}
|
||||||
</span>
|
</span>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
|
@ -18,7 +18,7 @@
|
||||||
</mat-list-item>
|
</mat-list-item>
|
||||||
|
|
||||||
<mat-list-item (click)="toggleCommandSub()" matTooltip="{{ 'TOOLTIP_ACTIONS' | translate }}"
|
<mat-list-item (click)="toggleCommandSub()" matTooltip="{{ 'TOOLTIP_ACTIONS' | translate }}"
|
||||||
matTooltipShowDelay="1000">
|
matTooltipShowDelay="1000" *ngIf="auth.userCategory !== 'ou-operator' && auth.userCategory !== 'ou-minimal'">
|
||||||
<span class="entry">
|
<span class="entry">
|
||||||
<mat-icon class="icon">playlist_play</mat-icon>
|
<mat-icon class="icon">playlist_play</mat-icon>
|
||||||
<span>{{ 'actions' | translate }}</span>
|
<span>{{ 'actions' | translate }}</span>
|
||||||
|
@ -28,7 +28,7 @@
|
||||||
<!-- Submenu items for commands -->
|
<!-- Submenu items for commands -->
|
||||||
<mat-nav-list *ngIf="showCommandSub" style="padding-left: 20px;">
|
<mat-nav-list *ngIf="showCommandSub" style="padding-left: 20px;">
|
||||||
<mat-list-item routerLink="/commands" (click)="onItemClick()" matTooltip="{{ 'TOOLTIP_COMMANDS' | translate }}"
|
<mat-list-item routerLink="/commands" (click)="onItemClick()" matTooltip="{{ 'TOOLTIP_COMMANDS' | translate }}"
|
||||||
matTooltipShowDelay="1000">
|
matTooltipShowDelay="1000" *ngIf="auth.userCategory !== 'ou-operator' && auth.userCategory !== 'ou-minimal'">
|
||||||
<span class="entry">
|
<span class="entry">
|
||||||
<mat-icon class="icon">chevron_right</mat-icon>
|
<mat-icon class="icon">chevron_right</mat-icon>
|
||||||
<span>{{ 'commands' | translate }}</span>
|
<span>{{ 'commands' | translate }}</span>
|
||||||
|
@ -44,7 +44,7 @@
|
||||||
</mat-list-item>
|
</mat-list-item>
|
||||||
-->
|
-->
|
||||||
<mat-list-item routerLink="/commands-task" (click)="onItemClick()" matTooltip="{{ 'TOOLTIP_TASKS' | translate }}"
|
<mat-list-item routerLink="/commands-task" (click)="onItemClick()" matTooltip="{{ 'TOOLTIP_TASKS' | translate }}"
|
||||||
matTooltipShowDelay="1000">
|
matTooltipShowDelay="1000" *ngIf="auth.userCategory !== 'ou-operator' && auth.userCategory !== 'ou-minimal'">
|
||||||
<span class="entry">
|
<span class="entry">
|
||||||
<mat-icon class="icon">chevron_right</mat-icon>
|
<mat-icon class="icon">chevron_right</mat-icon>
|
||||||
<span>{{ 'tasks' | translate }}</span>
|
<span>{{ 'tasks' | translate }}</span>
|
||||||
|
@ -53,15 +53,15 @@
|
||||||
</mat-nav-list>
|
</mat-nav-list>
|
||||||
|
|
||||||
<mat-list-item routerLink="/subnets" (click)="onItemClick()" matTooltip="{{ 'TOOLTIP_SUBNETS' | translate }}"
|
<mat-list-item routerLink="/subnets" (click)="onItemClick()" matTooltip="{{ 'TOOLTIP_SUBNETS' | translate }}"
|
||||||
matTooltipShowDelay="1000">
|
matTooltipShowDelay="1000" *ngIf="auth.userCategory !== 'ou-operator' && auth.userCategory !== 'ou-minimal'">
|
||||||
<span class="entry">
|
<span class="entry">
|
||||||
<mat-icon class="icon">lan</mat-icon>
|
<mat-icon class="icon">lan</mat-icon>
|
||||||
<span> {{ 'subnets' | translate }}</span>
|
<span> {{ 'subnets' | translate }}</span>
|
||||||
</span>
|
</span>
|
||||||
</mat-list-item>
|
</mat-list-item>
|
||||||
|
|
||||||
<mat-list-item (click)="toggleOgBootSub()" matTooltip="{{ 'TOOLTIP_BOOT' | translate }}"
|
<mat-list-item (click)="toggleOgBootSub()" matTooltip="{{ 'TOOLTIP_BOOT' | translate }}" matTooltipShowDelay="1000"
|
||||||
matTooltipShowDelay="1000">
|
*ngIf="auth.userCategory !== 'ou-operator' && auth.userCategory !== 'ou-minimal'">
|
||||||
<span class="entry">
|
<span class="entry">
|
||||||
<mat-icon class="icon">desktop_windows</mat-icon>
|
<mat-icon class="icon">desktop_windows</mat-icon>
|
||||||
<span>{{ 'boot' | translate }}</span>
|
<span>{{ 'boot' | translate }}</span>
|
||||||
|
@ -94,7 +94,7 @@
|
||||||
</mat-nav-list>
|
</mat-nav-list>
|
||||||
|
|
||||||
<mat-list-item routerLink="/calendars" (click)="onItemClick()" matTooltip="{{ 'TOOLTIP_CALENDARS' | translate }}"
|
<mat-list-item routerLink="/calendars" (click)="onItemClick()" matTooltip="{{ 'TOOLTIP_CALENDARS' | translate }}"
|
||||||
matTooltipShowDelay="1000">
|
matTooltipShowDelay="1000" *ngIf="auth.userCategory !== 'ou-operator' && auth.userCategory !== 'ou-minimal'">
|
||||||
<span class="entry">
|
<span class="entry">
|
||||||
<mat-icon class="icon">calendar_month</mat-icon>
|
<mat-icon class="icon">calendar_month</mat-icon>
|
||||||
<span>{{ 'calendars' | translate }}</span>
|
<span>{{ 'calendars' | translate }}</span>
|
||||||
|
@ -102,7 +102,7 @@
|
||||||
</mat-list-item>
|
</mat-list-item>
|
||||||
|
|
||||||
<mat-list-item (click)="toggleSoftwareSub()" matTooltip="{{ 'TOOLTIP_SOFTWARE' | translate }}"
|
<mat-list-item (click)="toggleSoftwareSub()" matTooltip="{{ 'TOOLTIP_SOFTWARE' | translate }}"
|
||||||
matTooltipShowDelay="1000">
|
matTooltipShowDelay="1000" *ngIf="auth.userCategory !== 'ou-operator' && auth.userCategory !== 'ou-minimal'">
|
||||||
<span class="entry">
|
<span class="entry">
|
||||||
<mat-icon class="icon">terminal</mat-icon>
|
<mat-icon class="icon">terminal</mat-icon>
|
||||||
<span>{{ 'software' | translate }}</span>
|
<span>{{ 'software' | translate }}</span>
|
||||||
|
@ -135,7 +135,8 @@
|
||||||
</mat-nav-list>
|
</mat-nav-list>
|
||||||
|
|
||||||
<mat-list-item routerLink="/repositories" (click)="onItemClick()"
|
<mat-list-item routerLink="/repositories" (click)="onItemClick()"
|
||||||
matTooltip="{{ 'TOOLTIP_REPOSITORIES' | translate }}" matTooltipShowDelay="1000">
|
matTooltip="{{ 'TOOLTIP_REPOSITORIES' | translate }}" matTooltipShowDelay="1000"
|
||||||
|
*ngIf="auth.userCategory !== 'ou-operator' && auth.userCategory !== 'ou-minimal'">
|
||||||
<span class="entry">
|
<span class="entry">
|
||||||
<mat-icon class="icon">warehouse</mat-icon>
|
<mat-icon class="icon">warehouse</mat-icon>
|
||||||
<span>{{ 'repositories' | translate }}</span>
|
<span>{{ 'repositories' | translate }}</span>
|
||||||
|
@ -143,10 +144,10 @@
|
||||||
</mat-list-item>
|
</mat-list-item>
|
||||||
|
|
||||||
<mat-list-item routerLink="/menus" (click)="onItemClick()" matTooltip="{{ 'TOOLTIP_MENUS' | translate }}"
|
<mat-list-item routerLink="/menus" (click)="onItemClick()" matTooltip="{{ 'TOOLTIP_MENUS' | translate }}"
|
||||||
matTooltipShowDelay="1000">
|
matTooltipShowDelay="1000" *ngIf="auth.userCategory !== 'ou-operator' && auth.userCategory !== 'ou-minimal'">
|
||||||
<span class="entry">
|
<span class="entry">
|
||||||
<mat-icon class="icon">list</mat-icon>
|
<mat-icon class="icon">list</mat-icon>
|
||||||
<span>{{ 'menus' | translate }}</span>
|
<span>{{ 'menus' | translate }}</span>
|
||||||
</span>
|
</span>
|
||||||
</mat-list-item>
|
</mat-list-item>
|
||||||
</mat-nav-list>
|
</mat-nav-list>
|
|
@ -1,6 +1,6 @@
|
||||||
import { Component, Input, Output, EventEmitter } from '@angular/core';
|
import { Component, Input, Output, EventEmitter } from '@angular/core';
|
||||||
import { jwtDecode } from 'jwt-decode';
|
|
||||||
import { MatDialog } from '@angular/material/dialog';
|
import { MatDialog } from '@angular/material/dialog';
|
||||||
|
import { AuthService } from '@services/auth.service';
|
||||||
|
|
||||||
@Component({
|
@Component({
|
||||||
selector: 'app-sidebar',
|
selector: 'app-sidebar',
|
||||||
|
@ -12,9 +12,7 @@ export class SidebarComponent {
|
||||||
@Input() sidebarMode: 'side' | 'over' = 'side';
|
@Input() sidebarMode: 'side' | 'over' = 'side';
|
||||||
@Output() closeSidebar: EventEmitter<void> = new EventEmitter<void>();
|
@Output() closeSidebar: EventEmitter<void> = new EventEmitter<void>();
|
||||||
|
|
||||||
isSuperAdmin: boolean = false;
|
username: string | null = "";
|
||||||
username: string = "";
|
|
||||||
decodedToken: any = "";
|
|
||||||
showOgBootSub: boolean = false;
|
showOgBootSub: boolean = false;
|
||||||
showOgDhcpSub: boolean = false;
|
showOgDhcpSub: boolean = false;
|
||||||
showCommandSub: boolean = false;
|
showCommandSub: boolean = false;
|
||||||
|
@ -39,19 +37,9 @@ export class SidebarComponent {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
constructor(public dialog: MatDialog) {}
|
constructor(public dialog: MatDialog, public auth: AuthService,) {}
|
||||||
|
|
||||||
ngOnInit(): void {
|
ngOnInit(): void {
|
||||||
const token = localStorage.getItem('loginToken');
|
this.username = this.auth.username
|
||||||
if (token) {
|
|
||||||
try {
|
|
||||||
this.decodedToken = jwtDecode(token);
|
|
||||||
this.isSuperAdmin = this.decodedToken.roles.includes('ROLE_SUPER_ADMIN');
|
|
||||||
localStorage.setItem('isSuperAdmin', String(this.isSuperAdmin));
|
|
||||||
this.username = this.decodedToken.username;
|
|
||||||
} catch (error) {
|
|
||||||
console.error('Error decoding JWT:', error);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
}
|
}
|
|
@ -0,0 +1,119 @@
|
||||||
|
import { Injectable } from '@angular/core';
|
||||||
|
import { Router } from '@angular/router';
|
||||||
|
import { jwtDecode } from 'jwt-decode';
|
||||||
|
|
||||||
|
export type UserCategory =
|
||||||
|
| 'super-admin'
|
||||||
|
| 'ou-admin'
|
||||||
|
| 'ou-operator'
|
||||||
|
| 'ou-minimal'
|
||||||
|
| 'user';
|
||||||
|
|
||||||
|
interface JwtPayload {
|
||||||
|
roles: string[];
|
||||||
|
username: string;
|
||||||
|
id: number;
|
||||||
|
uuid: string;
|
||||||
|
groupsView: string;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Injectable({ providedIn: 'root' })
|
||||||
|
export class AuthService {
|
||||||
|
private tokenPayload: JwtPayload | null = null;
|
||||||
|
|
||||||
|
constructor(private router: Router) {
|
||||||
|
this.loadToken();
|
||||||
|
}
|
||||||
|
|
||||||
|
/** Intenta leer y decodificar el token de localStorage */
|
||||||
|
private loadToken() {
|
||||||
|
const token = localStorage.getItem('loginToken');
|
||||||
|
if (!token) return;
|
||||||
|
try {
|
||||||
|
this.tokenPayload = jwtDecode<JwtPayload>(token);
|
||||||
|
} catch (e) {
|
||||||
|
console.error('Error decoding JWT', e);
|
||||||
|
this.tokenPayload = null;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/** Fuerza recarga del token (por si cambió en localStorage) */
|
||||||
|
public refresh() {
|
||||||
|
this.loadToken();
|
||||||
|
}
|
||||||
|
|
||||||
|
/** Roles básicos que aparecen en el token */
|
||||||
|
private get roles(): string[] {
|
||||||
|
return this.tokenPayload?.roles || [];
|
||||||
|
}
|
||||||
|
|
||||||
|
get isSuperAdmin(): boolean {
|
||||||
|
return this.roles.includes('ROLE_SUPER_ADMIN');
|
||||||
|
}
|
||||||
|
|
||||||
|
get isOUAdmin(): boolean {
|
||||||
|
return this.roles.includes('ROLE_ORGANIZATIONAL_UNIT_ADMIN');
|
||||||
|
}
|
||||||
|
|
||||||
|
get isOUOperator(): boolean {
|
||||||
|
return this.roles.includes('ROLE_ORGANIZATIONAL_UNIT_OPERATOR');
|
||||||
|
}
|
||||||
|
|
||||||
|
get isOUMinimal(): boolean {
|
||||||
|
return this.roles.includes('ROLE_ORGANIZATIONAL_UNIT_MINIMAL');
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Categoría única de usuario, según prioridades:
|
||||||
|
* - super-admin
|
||||||
|
* - ou-admin
|
||||||
|
* - ou-operator
|
||||||
|
* - ou-minimal
|
||||||
|
* - user (fallback)
|
||||||
|
*/
|
||||||
|
get userCategory(): UserCategory {
|
||||||
|
if (this.isSuperAdmin) return 'super-admin';
|
||||||
|
if (this.isOUAdmin) return 'ou-admin';
|
||||||
|
if (this.isOUOperator) return 'ou-operator';
|
||||||
|
if (this.isOUMinimal) return 'ou-minimal';
|
||||||
|
return 'user';
|
||||||
|
}
|
||||||
|
|
||||||
|
/** Nombre de usuario */
|
||||||
|
get username(): string | null {
|
||||||
|
return this.tokenPayload?.username || null;
|
||||||
|
}
|
||||||
|
|
||||||
|
/** Uuid del usuario*/
|
||||||
|
get uuid(): any | null {
|
||||||
|
return this.tokenPayload?.uuid || null;
|
||||||
|
}
|
||||||
|
|
||||||
|
/** groupsView del usuario */
|
||||||
|
get groupsView(): string | null {
|
||||||
|
return this.tokenPayload?.groupsView || null;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Devuelve el rol principal del usuario según prioridad.
|
||||||
|
*/
|
||||||
|
getCurrentRole(): string {
|
||||||
|
if (this.isSuperAdmin) return 'super-admin';
|
||||||
|
if (this.isOUAdmin) return 'ou-admin';
|
||||||
|
if (this.isOUOperator) return 'ou-operator';
|
||||||
|
if (this.isOUMinimal) return 'ou-minimal';
|
||||||
|
return 'user';
|
||||||
|
}
|
||||||
|
|
||||||
|
/** Logout: limpia tokens y redirige al login */
|
||||||
|
logout(): void {
|
||||||
|
localStorage.removeItem('loginToken');
|
||||||
|
localStorage.removeItem('refreshToken');
|
||||||
|
localStorage.removeItem('isSuperAdmin');
|
||||||
|
localStorage.removeItem('username');
|
||||||
|
localStorage.removeItem('groupsView');
|
||||||
|
localStorage.removeItem('language');
|
||||||
|
this.tokenPayload = null;
|
||||||
|
this.router.navigate(['/auth/login']);
|
||||||
|
}
|
||||||
|
}
|
|
@ -0,0 +1,16 @@
|
||||||
|
.main-container {
|
||||||
|
height: 100dvh;
|
||||||
|
display: grid;
|
||||||
|
place-content: center;
|
||||||
|
}
|
||||||
|
|
||||||
|
.content-container {
|
||||||
|
padding: 4em;
|
||||||
|
border: 1px solid #3f51b5;
|
||||||
|
border-radius: 30px;
|
||||||
|
}
|
||||||
|
|
||||||
|
.message {
|
||||||
|
font-size: 25px;
|
||||||
|
font-weight: 500;
|
||||||
|
}
|
|
@ -1 +1,7 @@
|
||||||
<p>page-not-found works!</p>
|
<main>
|
||||||
|
<article class="main-container">
|
||||||
|
<div class="content-container">
|
||||||
|
<span class="message">Page not found</span>
|
||||||
|
</div>
|
||||||
|
</article>
|
||||||
|
</main>
|
Loading…
Reference in New Issue