Quitar acceso admin a no permitidos
parent
03accc5947
commit
4a86f36112
|
@ -18,6 +18,7 @@
|
|||
"@angular/platform-browser": "^18.0.0",
|
||||
"@angular/platform-browser-dynamic": "^18.0.0",
|
||||
"@angular/router": "^18.0.0",
|
||||
"jwt-decode": "^4.0.0",
|
||||
"rxjs": "~7.8.0",
|
||||
"tslib": "^2.3.0",
|
||||
"zone.js": "^0.14.6"
|
||||
|
@ -8754,6 +8755,14 @@
|
|||
"node >= 0.2.0"
|
||||
]
|
||||
},
|
||||
"node_modules/jwt-decode": {
|
||||
"version": "4.0.0",
|
||||
"resolved": "https://registry.npmjs.org/jwt-decode/-/jwt-decode-4.0.0.tgz",
|
||||
"integrity": "sha512-+KJGIyHgkGuIq3IEBNftfhW/LfWhXUIY6OmyVWjliu5KH1y0fw7VQ8YndE2O4qZdMSd9SqbnC8GOcZEy0Om7sA==",
|
||||
"engines": {
|
||||
"node": ">=18"
|
||||
}
|
||||
},
|
||||
"node_modules/karma": {
|
||||
"version": "6.4.3",
|
||||
"resolved": "https://registry.npmjs.org/karma/-/karma-6.4.3.tgz",
|
||||
|
|
|
@ -20,6 +20,7 @@
|
|||
"@angular/platform-browser": "^18.0.0",
|
||||
"@angular/platform-browser-dynamic": "^18.0.0",
|
||||
"@angular/router": "^18.0.0",
|
||||
"jwt-decode": "^4.0.0",
|
||||
"rxjs": "~7.8.0",
|
||||
"tslib": "^2.3.0",
|
||||
"zone.js": "^0.14.6"
|
||||
|
|
|
@ -17,7 +17,7 @@ const routes: Routes = [
|
|||
{ path: 'dashboard', component: DashboardComponent },
|
||||
{ path: 'admin', component: AdminComponent },
|
||||
{ path: 'users', component: UsersComponent },
|
||||
{ path: 'roles', component: RolesComponent },
|
||||
{ path: 'user-groups', component: RolesComponent },
|
||||
// otras rutas que usan el MainLayoutComponent
|
||||
],
|
||||
},
|
||||
|
|
|
@ -13,7 +13,7 @@
|
|||
<button mat-flat-button color="primary">Buscar</button>
|
||||
<button mat-flat-button color="primary">Calendario</button>
|
||||
<button mat-flat-button color="primary">Ayuda</button>
|
||||
<button mat-flat-button color="accent" routerLink="/admin">Admin</button>
|
||||
<button mat-flat-button color="accent" routerLink="/admin" *ngIf="isSuperAdmin">Admin</button>
|
||||
<button mat-flat-button color="warn" routerLink="/auth/login">Salir</button>
|
||||
</div>
|
||||
|
||||
|
|
|
@ -1,11 +1,26 @@
|
|||
import { Component } from '@angular/core';
|
||||
import {MatToolbarModule} from '@angular/material/toolbar';
|
||||
import { Component, OnInit } from '@angular/core';
|
||||
import {jwtDecode} from 'jwt-decode';
|
||||
|
||||
@Component({
|
||||
selector: 'app-header',
|
||||
templateUrl: './header.component.html',
|
||||
styleUrl: './header.component.css',
|
||||
styleUrls: ['./header.component.css'],
|
||||
})
|
||||
export class HeaderComponent {
|
||||
export class HeaderComponent implements OnInit {
|
||||
isSuperAdmin: boolean = false;
|
||||
|
||||
constructor() { }
|
||||
|
||||
ngOnInit(): void {
|
||||
const token = localStorage.getItem('loginToken');
|
||||
if (token) {
|
||||
try {
|
||||
const decodedToken: any = jwtDecode(token);
|
||||
console.log('Decoded JWT:', decodedToken);
|
||||
this.isSuperAdmin = decodedToken.roles.includes('ROLE_SUPER_ADMIN');
|
||||
} catch (error) {
|
||||
console.error('Error decoding JWT:', error);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
@ -1,10 +1,9 @@
|
|||
import { Component } from '@angular/core';
|
||||
|
||||
@Component({
|
||||
selector: 'app-main-layout',
|
||||
templateUrl: './main-layout.component.html',
|
||||
styleUrl: './main-layout.component.css'
|
||||
})
|
||||
export class MainLayoutComponent {
|
||||
|
||||
|
||||
}
|
||||
|
|
|
@ -3,7 +3,7 @@
|
|||
<mat-icon>group</mat-icon>
|
||||
<span>Usuarios</span>
|
||||
</button>
|
||||
<button mat-fab color="primary" class="fab-button" routerLink="/roles">
|
||||
<button mat-fab color="primary" class="fab-button" routerLink="/user-groups">
|
||||
<mat-icon>admin_panel_settings</mat-icon>
|
||||
<span>Roles</span>
|
||||
</button>
|
||||
|
|
|
@ -0,0 +1,10 @@
|
|||
.role-form .form-field {
|
||||
display: block;
|
||||
margin-bottom: 10px; /* Puedes ajustar el valor para cambiar la separación */
|
||||
}
|
||||
|
||||
.checkbox-group label {
|
||||
display: block;
|
||||
margin-bottom: 8px; /* Ajusta este valor según necesites */
|
||||
}
|
||||
|
|
@ -0,0 +1,25 @@
|
|||
<h1 mat-dialog-title>Añadir Rol (TBD)</h1>
|
||||
<div mat-dialog-content>
|
||||
<form class="role-form">
|
||||
<mat-form-field class="form-field">
|
||||
<mat-label>Nombre</mat-label>
|
||||
<input matInput formControlName="rolename" required>
|
||||
</mat-form-field>
|
||||
|
||||
<section class="example-section">
|
||||
<h4>Permisos:</h4>
|
||||
<p><mat-checkbox >Gestionar los usuarios</mat-checkbox></p>
|
||||
<p><mat-checkbox >Configuración PXE</mat-checkbox></p>
|
||||
<p><mat-checkbox >Imágenes de la consola web</mat-checkbox></p>
|
||||
<p><mat-checkbox >Gestionar los distintos componentes</mat-checkbox></p>
|
||||
<p><mat-checkbox >Crear imágenes</mat-checkbox></p>
|
||||
<p><mat-checkbox >script de configuración del servidor</mat-checkbox></p>
|
||||
<p><mat-checkbox >...</mat-checkbox></p>
|
||||
</section>
|
||||
|
||||
</form>
|
||||
</div>
|
||||
<div mat-dialog-actions>
|
||||
<button mat-button (click)="onNoClick()">Cancelar</button>
|
||||
<button mat-button>Añadir</button>
|
||||
</div>
|
|
@ -0,0 +1,23 @@
|
|||
import { ComponentFixture, TestBed } from '@angular/core/testing';
|
||||
|
||||
import { AddRoleModalComponent } from './add-role-modal.component';
|
||||
|
||||
describe('AddRoleModalComponent', () => {
|
||||
let component: AddRoleModalComponent;
|
||||
let fixture: ComponentFixture<AddRoleModalComponent>;
|
||||
|
||||
beforeEach(async () => {
|
||||
await TestBed.configureTestingModule({
|
||||
declarations: [AddRoleModalComponent]
|
||||
})
|
||||
.compileComponents();
|
||||
|
||||
fixture = TestBed.createComponent(AddRoleModalComponent);
|
||||
component = fixture.componentInstance;
|
||||
fixture.detectChanges();
|
||||
});
|
||||
|
||||
it('should create', () => {
|
||||
expect(component).toBeTruthy();
|
||||
});
|
||||
});
|
|
@ -0,0 +1,19 @@
|
|||
import { HttpClient } from '@angular/common/http';
|
||||
import { Component, Inject } from '@angular/core';
|
||||
import { MatDialogRef, MAT_DIALOG_DATA } from '@angular/material/dialog';
|
||||
|
||||
@Component({
|
||||
selector: 'app-add-role-modal',
|
||||
templateUrl: './add-role-modal.component.html',
|
||||
styleUrl: './add-role-modal.component.css'
|
||||
})
|
||||
export class AddRoleModalComponent {
|
||||
constructor(
|
||||
public dialogRef: MatDialogRef<AddRoleModalComponent>,
|
||||
@Inject(MAT_DIALOG_DATA) public data: any,
|
||||
private http: HttpClient
|
||||
) {}
|
||||
onNoClick(): void {
|
||||
this.dialogRef.close();
|
||||
}
|
||||
}
|
|
@ -0,0 +1,8 @@
|
|||
<h1 mat-dialog-title>Eliminar Rol</h1>
|
||||
<div mat-dialog-content>
|
||||
<p>¿Estás seguro que deseas eliminar el rol {{ data.name }}?</p>
|
||||
</div>
|
||||
<div mat-dialog-actions>
|
||||
<button mat-button (click)="onNoClick()">Cancelar</button>
|
||||
<button mat-button (click)="onYesClick()">Eliminar</button>
|
||||
</div>
|
|
@ -0,0 +1,23 @@
|
|||
import { ComponentFixture, TestBed } from '@angular/core/testing';
|
||||
|
||||
import { DeleteRoleModalComponent } from './delete-role-modal.component';
|
||||
|
||||
describe('DeleteRoleModalComponent', () => {
|
||||
let component: DeleteRoleModalComponent;
|
||||
let fixture: ComponentFixture<DeleteRoleModalComponent>;
|
||||
|
||||
beforeEach(async () => {
|
||||
await TestBed.configureTestingModule({
|
||||
declarations: [DeleteRoleModalComponent]
|
||||
})
|
||||
.compileComponents();
|
||||
|
||||
fixture = TestBed.createComponent(DeleteRoleModalComponent);
|
||||
component = fixture.componentInstance;
|
||||
fixture.detectChanges();
|
||||
});
|
||||
|
||||
it('should create', () => {
|
||||
expect(component).toBeTruthy();
|
||||
});
|
||||
});
|
|
@ -0,0 +1,40 @@
|
|||
import { HttpClient, HttpHeaders } from '@angular/common/http';
|
||||
import { Component, EventEmitter, Inject, Output } from '@angular/core';
|
||||
import { MatDialogRef, MAT_DIALOG_DATA } from '@angular/material/dialog';
|
||||
|
||||
@Component({
|
||||
selector: 'app-delete-role-modal',
|
||||
templateUrl: './delete-role-modal.component.html',
|
||||
styleUrl: './delete-role-modal.component.css'
|
||||
})
|
||||
export class DeleteRoleModalComponent {
|
||||
@Output() roleDeleted = new EventEmitter<void>();
|
||||
constructor(
|
||||
public dialogRef: MatDialogRef<DeleteRoleModalComponent>,
|
||||
@Inject(MAT_DIALOG_DATA) public data: any,
|
||||
private http: HttpClient
|
||||
) {}
|
||||
|
||||
onNoClick(): void {
|
||||
this.dialogRef.close();
|
||||
}
|
||||
|
||||
onYesClick(): void {
|
||||
const apiUrl = `http://127.0.0.1:8080/user-groups/${this.data.uuid}`;
|
||||
const headers = new HttpHeaders({
|
||||
'Content-Type': 'application/ld+json'
|
||||
});
|
||||
|
||||
this.http.delete(apiUrl, { headers: headers }).subscribe(
|
||||
() => {
|
||||
console.log('Role deleted successfully');
|
||||
this.roleDeleted.emit();
|
||||
this.dialogRef.close(true);
|
||||
},
|
||||
( error: any) => {
|
||||
console.error('Error deleting role:', error);
|
||||
// Agregar alguna lógica para manejar el error en la interfaz de usuario
|
||||
}
|
||||
);
|
||||
}
|
||||
}
|
|
@ -7,9 +7,10 @@
|
|||
</mat-form-field>
|
||||
<mat-form-field class="form-field">
|
||||
<mat-label>Contraseña</mat-label>
|
||||
<input matInput formControlName="password" required>
|
||||
<input matInput formControlName="password" type="password" required>
|
||||
</mat-form-field>
|
||||
<mat-form-field appearance="fill">
|
||||
|
||||
<mat-form-field class="form-field">
|
||||
<mat-label>Rol</mat-label>
|
||||
<mat-select formControlName="role">
|
||||
<mat-option *ngFor="let group of userGroups" [value]="group['@id']">
|
||||
|
@ -17,6 +18,16 @@
|
|||
</mat-option>
|
||||
</mat-select>
|
||||
</mat-form-field>
|
||||
|
||||
<mat-form-field class="form-field">
|
||||
<mat-label>Organizational Units</mat-label>
|
||||
<mat-select multiple formControlName="organizationalUnit">
|
||||
<mat-option *ngFor="let unit of organizationalUnits" [value]="unit['@id']">
|
||||
{{unit.name}}
|
||||
</mat-option>
|
||||
</mat-select>
|
||||
</mat-form-field>
|
||||
|
||||
|
||||
</form>
|
||||
</div>
|
||||
|
|
|
@ -18,6 +18,7 @@ export class AddUserModalComponent implements OnInit {
|
|||
@Output() userAdded = new EventEmitter<void>();
|
||||
userForm: FormGroup;
|
||||
userGroups: UserGroup[] = [];
|
||||
organizationalUnits: any[] = [];
|
||||
|
||||
constructor(
|
||||
public dialogRef: MatDialogRef<AddUserModalComponent>,
|
||||
|
@ -28,7 +29,8 @@ export class AddUserModalComponent implements OnInit {
|
|||
this.userForm = this.fb.group({
|
||||
username: ['', Validators.required],
|
||||
password: ['', Validators.required],
|
||||
role: ['', Validators.required], // Control para el permiso seleccionado
|
||||
role: ['', Validators.required],
|
||||
organizationalUnit: [[], Validators.required]
|
||||
});
|
||||
}
|
||||
|
||||
|
@ -36,6 +38,10 @@ export class AddUserModalComponent implements OnInit {
|
|||
this.userService.getUserGroups().subscribe((data) => {
|
||||
this.userGroups = data['hydra:member'];
|
||||
});
|
||||
this.userService.getOrganizationalUnits().subscribe((data) => {
|
||||
this.organizationalUnits = data['hydra:member'];
|
||||
});
|
||||
|
||||
}
|
||||
|
||||
onNoClick(): void {
|
||||
|
@ -46,7 +52,7 @@ export class AddUserModalComponent implements OnInit {
|
|||
if (this.userForm.valid) {
|
||||
const userPayload = {
|
||||
username: this.userForm.value.username,
|
||||
allowedOrganizationalUnits: [],
|
||||
allowedOrganizationalUnits: this.userForm.value.organizationalUnit,
|
||||
password: this.userForm.value.password,
|
||||
enabled: true,
|
||||
userGroups: [this.userForm.value.role ]
|
||||
|
|
|
@ -7,7 +7,7 @@
|
|||
</mat-form-field>
|
||||
<mat-form-field class="form-field">
|
||||
<mat-label>Contraseña</mat-label>
|
||||
<input matInput formControlName="password" >
|
||||
<input matInput formControlName="password" type="password">
|
||||
</mat-form-field>
|
||||
<mat-form-field appearance="fill">
|
||||
<mat-label>Rol</mat-label>
|
||||
|
|
|
@ -27,7 +27,7 @@ export class UsersComponent implements OnInit {
|
|||
{
|
||||
columnDef: 'allowedOrganizationalUnits',
|
||||
header: 'Unidades Organizacionales Permitidas',
|
||||
cell: (user: any) => `${user.allowedOrganizationalUnits.join(', ')}`
|
||||
cell: (user: any) => `${user.allowedOrganizationalUnits.map((unit: { name: any; }) => unit.name).join(', ')}`
|
||||
},
|
||||
{
|
||||
columnDef: 'roles',
|
||||
|
@ -46,6 +46,7 @@ export class UsersComponent implements OnInit {
|
|||
loadUsers() {
|
||||
this.userService.getUsers().subscribe(response => {
|
||||
this.dataSource.data = response['hydra:member'];
|
||||
console.log(this.dataSource.data);
|
||||
});
|
||||
}
|
||||
|
||||
|
|
|
@ -45,4 +45,9 @@ export class UserService {
|
|||
getUsers(): Observable<any> {
|
||||
return this.http.get<any>(`${this.apiUrl}/users?page=1&itemsPerPage=30`);
|
||||
}
|
||||
|
||||
getOrganizationalUnits(): Observable<any> {
|
||||
return this.http.get<any>(`${this.apiUrl}/organizational-units?page=1&itemsPerPage=30`);
|
||||
|
||||
}
|
||||
}
|
||||
|
|
Loading…
Reference in New Issue