Browse Source

Integración de las políticas de seguridad al sistema

Jose Brito 1 year ago
parent
commit
0c99787cda

+ 188 - 188
sistema-mantenimiento-front/src/app/components/system-admin/security-politics/security-politics.component.html

@@ -1,194 +1,194 @@
 <div class="items-container animated fadeIn">
-    <div id="navigation" class="mb-8">
-        <div class="prev-page prevent-select indigo_primary_background mat-elevation-z8" (click)="goBack(1)" matRipple>
-            <mat-icon style="color: white;">arrow_back</mat-icon>
-            <div class="page-name ml-4">Administrador del sistema</div>
-        </div>
+  <div id="navigation" class="mb-8">
+    <div class="prev-page prevent-select indigo_primary_background mat-elevation-z8" (click)="goBack(1)" matRipple>
+      <mat-icon style="color: white;">arrow_back</mat-icon>
+      <div class="page-name ml-4">Administrador del sistema</div>
     </div>
-    <mat-card class="override-elevation-z8" style="width: 100%; height: calc(100% - 48px);">
-        <mat-card-title style="text-align: center;" class="prevent-select pv-16">Políticas de seguridad</mat-card-title>
-        <mat-card-content>
-            <div class="loader-container prevent-select" *ngIf="isLoading">
-                <mat-spinner></mat-spinner>
-                <h2 class="loader-label">Cargando...</h2>
+  </div>
+  <mat-card class="override-elevation-z8" style="width: 100%; height: calc(100% - 48px);">
+    <mat-card-title style="text-align: center;" class="prevent-select pv-16">Políticas de seguridad</mat-card-title>
+    <mat-card-content>
+      <div class="loader-container prevent-select" *ngIf="isLoading">
+        <mat-spinner></mat-spinner>
+        <h2 class="loader-label">Cargando...</h2>
+      </div>
+      <div class="error-container prevent-select" *ngIf="!isLoading && hasError">
+        <mat-icon style="color: #e53935; transform: scale(5); margin: 48px;">error</mat-icon>
+        <h1 style="color: #e53935;">¡Error!</h1>
+        <p style="font-style: italic; font-size: 16px; overflow-wrap: anywhere; text-align: center;">{{ errorStr }}</p>
+      </div>
+      <div class="table-container" [hidden]="!(!isLoading && !hasError)" style="overflow: hidden;" class="animated fadeIn">
+        <mat-tab-group class="prevent-select">
+          <mat-tab label="Patrón de contraseñas" >
+            <div class="form-pass-container animated fadeIn" style="height: calc(100vh - 304px);" [formGroup]="politicsForm" *ngIf="passwordPatternEnabled">
+              <div class="element">
+                <mat-checkbox [disabled]="true" checked>Longitud mínima</mat-checkbox>
+                <mat-form-field appearance="outline" style="width: 100%;">
+                  <input matInput style="text-align: center;" readonly formControlName="minLength">
+                  <button mat-icon-button matPrefix (click)="editMinLength(0)">
+                    <mat-icon>remove</mat-icon>
+                  </button>
+                  <button mat-icon-button matSuffix (click)="editMinLength(1)">
+                    <mat-icon>add</mat-icon>
+                  </button>
+                </mat-form-field>
+              </div>
+              <div class="element">
+                <mat-checkbox formControlName="enableUpperCase" (change)="disableMinUpper()">Letras mayúsculas</mat-checkbox>
+                <mat-form-field appearance="outline" style="width: 100%;">
+                  <input matInput style="text-align: center;" readonly formControlName="minUpper">
+                  <button mat-icon-button matPrefix (click)="editMinUpper(0)">
+                    <mat-icon>remove</mat-icon>
+                  </button>
+                  <button mat-icon-button matSuffix (click)="editMinUpper(1)">
+                    <mat-icon>add</mat-icon>
+                  </button>
+                </mat-form-field>
+              </div>
+              <div class="element">
+                <mat-checkbox formControlName="enableNumbers" (change)="disableMinNumber()">Números</mat-checkbox>
+                <mat-form-field appearance="outline" style="width: 100%;">
+                  <input matInput style="text-align: center;" readonly formControlName="minNumber">
+                  <button mat-icon-button matPrefix (click)="editMinNumber(0)">
+                    <mat-icon>remove</mat-icon>
+                  </button>
+                  <button mat-icon-button matSuffix (click)="editMinNumber(1)">
+                    <mat-icon>add</mat-icon>
+                  </button>
+                </mat-form-field>
+              </div>
+              <div class="element">
+                <mat-checkbox formControlName="enableCharacters" (change)="disableMinCharacters()">Caracteres especiales</mat-checkbox>
+                <mat-form-field appearance="outline" style="width: 100%;">
+                  <input matInput style="text-align: center;" readonly formControlName="minCharacters">
+                  <button mat-icon-button matPrefix (click)="editMinCharacters(0)">
+                    <mat-icon>remove</mat-icon>
+                  </button>
+                  <button mat-icon-button matSuffix (click)="editMinCharacters(1)">
+                    <mat-icon>add</mat-icon>
+                  </button>
+                </mat-form-field>
+              </div>
+              <div class="save-politics-container">
+                <button mat-flat-button class="indigo_primary_background white_font" (click)="savePaswordFormat()">Guardar configuración</button>
+              </div>
             </div>
-            <div class="error-container prevent-select" *ngIf="!isLoading && hasError">
-                <mat-icon style="color: #e53935; transform: scale(5); margin: 48px;">error</mat-icon>
-                <h1 style="color: #e53935;">¡Error!</h1>
-                <p style="font-style: italic; font-size: 16px; overflow-wrap: anywhere; text-align: center;">{{ errorStr }}</p>
+            <div class="animated fadeIn" *ngIf="!passwordPatternEnabled">
+              <h3 class="ml-20 mt-16"><b>Su perfil no cuenta con los permisos necesarios para visualizar la información de esta sección.</b></h3>
             </div>
-            <div class="table-container" [hidden]="!(!isLoading && !hasError)" style="overflow: hidden;" class="animated fadeIn">
-                <mat-tab-group class="prevent-select">
-                    <mat-tab label="Patrón de contraseñas" >
-                        <div class="form-pass-container animated fadeIn" style="height: calc(100vh - 304px);" [formGroup]="politicsForm" *ngIf="passwordPatternEnabled">
-                            <div class="element">
-                                <mat-checkbox [disabled]="true" checked>Longitud mínima</mat-checkbox>
-                                <mat-form-field appearance="outline" style="width: 100%;">
-                                    <input matInput style="text-align: center;" readonly formControlName="minLength">
-                                    <button mat-icon-button matPrefix (click)="editMinLength(0)">
-                                        <mat-icon>remove</mat-icon>
-                                    </button>
-                                    <button mat-icon-button matSuffix (click)="editMinLength(1)">
-                                        <mat-icon>add</mat-icon>
-                                    </button>
-                                </mat-form-field>
-                            </div>
-                            <div class="element">
-                                <mat-checkbox formControlName="enableUpperCase" (change)="disableMinUpper()">Letras mayúsculas</mat-checkbox>
-                                <mat-form-field appearance="outline" style="width: 100%;">
-                                    <input matInput style="text-align: center;" readonly formControlName="minUpper">
-                                    <button mat-icon-button matPrefix (click)="editMinUpper(0)">
-                                        <mat-icon>remove</mat-icon>
-                                    </button>
-                                    <button mat-icon-button matSuffix (click)="editMinUpper(1)">
-                                        <mat-icon>add</mat-icon>
-                                    </button>
-                                </mat-form-field>
-                            </div>
-                            <div class="element">
-                                <mat-checkbox formControlName="enableNumbers" (change)="disableMinNumber()">Números</mat-checkbox>
-                                <mat-form-field appearance="outline" style="width: 100%;">
-                                    <input matInput style="text-align: center;" readonly formControlName="minNumber">
-                                    <button mat-icon-button matPrefix (click)="editMinNumber(0)">
-                                        <mat-icon>remove</mat-icon>
-                                    </button>
-                                    <button mat-icon-button matSuffix (click)="editMinNumber(1)">
-                                        <mat-icon>add</mat-icon>
-                                    </button>
-                                </mat-form-field>
-                            </div>
-                            <div class="element">
-                                <mat-checkbox formControlName="enableCharacters" (change)="disableMinCharacters()">Caracteres especiales</mat-checkbox>
-                                <mat-form-field appearance="outline" style="width: 100%;">
-                                    <input matInput style="text-align: center;" readonly formControlName="minCharacters">
-                                    <button mat-icon-button matPrefix (click)="editMinCharacters(0)">
-                                        <mat-icon>remove</mat-icon>
-                                    </button>
-                                    <button mat-icon-button matSuffix (click)="editMinCharacters(1)">
-                                        <mat-icon>add</mat-icon>
-                                    </button>
-                                </mat-form-field>
-                            </div>
-                            <div class="save-politics-container">
-                                <button mat-flat-button class="indigo_primary_background white_font" (click)="savePaswordFormat()">Guardar configuración</button>
-                            </div>
-                        </div>
-                        <div class="animated fadeIn" *ngIf="!passwordPatternEnabled">
-                            <h3 class="ml-20 mt-16"><b>Su perfil no cuenta con los permisos necesarios para visualizar la información de esta sección.</b></h3>
-                        </div>
-                    </mat-tab>
-                    <mat-tab label="Duración de sesiones">
-                        <div class="form-pass-container animated fadeIn" style="height: calc(100vh - 304px);" [formGroup]="sessionsForm" *ngIf="sessionsDurationEnabled">
-                            <div class="element">
-                                <mat-label>Días</mat-label>
-                                <mat-form-field appearance="outline" style="width: 100%;">
-                                    <input matInput style="text-align: center;" readonly formControlName="days">
-                                    <button mat-icon-button matPrefix (click)="editDays(0)">
-                                        <mat-icon>remove</mat-icon>
-                                    </button>
-                                    <button mat-icon-button matSuffix (click)="editDays(1)">
-                                        <mat-icon>add</mat-icon>
-                                    </button>
-                                </mat-form-field>
-                            </div>
-                            <div class="element">
-                                <mat-label>Horas</mat-label>
-                                <mat-form-field appearance="outline" style="width: 100%;">
-                                    <input matInput style="text-align: center;" readonly formControlName="hours">
-                                    <button mat-icon-button matPrefix (click)="editHours(0)">
-                                        <mat-icon>remove</mat-icon>
-                                    </button>
-                                    <button mat-icon-button matSuffix (click)="editHours(1)">
-                                        <mat-icon>add</mat-icon>
-                                    </button>
-                                </mat-form-field>
-                            </div>
-                            <div class="element">
-                                <mat-label>Minutos</mat-label>
-                                <mat-form-field appearance="outline" style="width: 100%;">
-                                    <input matInput style="text-align: center;" readonly formControlName="minutes">
-                                    <button mat-icon-button matPrefix (click)="editMinutes(0)">
-                                        <mat-icon>remove</mat-icon>
-                                    </button>
-                                    <button mat-icon-button matSuffix (click)="editMinutes(1)">
-                                        <mat-icon>add</mat-icon>
-                                    </button>
-                                </mat-form-field>
-                            </div>
-                            <div class="element">
-                                <mat-label>Segundos</mat-label>
-                                <mat-form-field appearance="outline" style="width: 100%;">
-                                    <input matInput style="text-align: center;" readonly formControlName="seconds">
-                                    <button mat-icon-button matPrefix (click)="editSeconds(0)">
-                                        <mat-icon>remove</mat-icon>
-                                    </button>
-                                    <button mat-icon-button matSuffix (click)="editSeconds(1)">
-                                        <mat-icon>add</mat-icon>
-                                    </button>
-                                </mat-form-field>
-                            </div>
-                            <div class="save-politics-container">
-                                <button mat-flat-button class="indigo_primary_background white_font" (click)="saveSessionsDuration()">Guardar configuración</button>
-                            </div>
-                        </div>
-                        <div class="animated fadeIn" *ngIf="!sessionsDurationEnabled">
-                            <h3 class="ml-20 mt-16"><b>Su perfil no cuenta con los permisos necesarios para visualizar la información de esta sección.</b></h3>
-                        </div>
-                    </mat-tab>
-                    <mat-tab label="Autenticación en dos pasos">
-                        <div class="auth-table-container animated fadeIn" style="height: calc(100vh - 304px);" *ngIf="twoFactorAuthEnabled">
-                            <table mat-table [dataSource]="dataSourceAuth!">
-                                <ng-container matColumnDef="ID">
-                                    <th mat-header-cell *matHeaderCellDef>ID</th>
-                                    <td mat-cell *matCellDef="let row"> {{row.IDUSUARIO}} </td>
-                                </ng-container>
-                                
-                                <ng-container matColumnDef="NAME">
-                                    <th mat-header-cell *matHeaderCellDef>Usuario</th>
-                                    <td mat-cell *matCellDef="let row"> {{row.NOMBREUSUARIO}} </td>
-                                </ng-container>
-                                
-                                <ng-container matColumnDef="AUTH">
-                                    <th mat-header-cell *matHeaderCellDef>Usar autorización</th>
-                                    <td mat-cell *matCellDef="let row; let i = index">
-                                        <mat-slide-toggle (change)="changeStatus(i)" [checked]="row.AUTHENABLED">
-                                            {{ row.AUTHENABLED ? 'Activado' : 'Desactivado' }}
-                                        </mat-slide-toggle>
-                                    </td>
-                                </ng-container>
-    
-                                <tr mat-header-row *matHeaderRowDef="displayedColumnsAuth"></tr>
-                                <tr mat-row *matRowDef="let row; columns: displayedColumnsAuth;"></tr>
-                            </table>
-                        </div>
-                        <div class="animated fadeIn" *ngIf="!twoFactorAuthEnabled">
-                            <h3 class="ml-20 mt-16"><b>Su perfil no cuenta con los permisos necesarios para visualizar la información de esta sección.</b></h3>
-                        </div>
-                    </mat-tab>
-                    <mat-tab label="Número de sesiones activas">
-                        <div class="form-pass-container animated fadeIn" style="height: calc(100vh - 304px);" [formGroup]="sessionsNumberForm" *ngIf="activeSessionsNumberEnabled">
-                            <div class="element">
-                                <mat-label>Sesiones configuradas</mat-label>
-                                <mat-form-field appearance="outline" style="width: 100%;">
-                                    <input matInput style="text-align: center;" readonly formControlName="number">
-                                    <button mat-icon-button matPrefix (click)="editNumber(0)">
-                                        <mat-icon>remove</mat-icon>
-                                    </button>
-                                    <button mat-icon-button matSuffix (click)="editNumber(1)">
-                                        <mat-icon>add</mat-icon>
-                                    </button>
-                                </mat-form-field>
-                            </div>
-                            <div class="save-politics-container">
-                                <button mat-flat-button class="indigo_primary_background white_font" (click)="saveActiveSessionsNumber()">Guardar configuración</button>
-                            </div>
-                        </div>
-                        <div class="animated fadeIn" *ngIf="!activeSessionsNumberEnabled">
-                            <h3 class="ml-20 mt-16"><b>Su perfil no cuenta con los permisos necesarios para visualizar la información de esta sección.</b></h3>
-                        </div>
-                    </mat-tab>
-                </mat-tab-group>
+          </mat-tab>
+          <mat-tab label="Duración de sesiones">
+            <div class="form-pass-container animated fadeIn" style="height: calc(100vh - 304px);" [formGroup]="sessionsForm" *ngIf="sessionsDurationEnabled">
+              <div class="element">
+                <mat-label>Días</mat-label>
+                <mat-form-field appearance="outline" style="width: 100%;">
+                  <input matInput style="text-align: center;" readonly formControlName="days">
+                  <button mat-icon-button matPrefix (click)="editDays(0)">
+                    <mat-icon>remove</mat-icon>
+                  </button>
+                  <button mat-icon-button matSuffix (click)="editDays(1)">
+                    <mat-icon>add</mat-icon>
+                  </button>
+                </mat-form-field>
+              </div>
+              <div class="element">
+                <mat-label>Horas</mat-label>
+                <mat-form-field appearance="outline" style="width: 100%;">
+                  <input matInput style="text-align: center;" readonly formControlName="hours">
+                  <button mat-icon-button matPrefix (click)="editHours(0)">
+                    <mat-icon>remove</mat-icon>
+                  </button>
+                  <button mat-icon-button matSuffix (click)="editHours(1)">
+                    <mat-icon>add</mat-icon>
+                  </button>
+                </mat-form-field>
+              </div>
+              <div class="element">
+                <mat-label>Minutos</mat-label>
+                <mat-form-field appearance="outline" style="width: 100%;">
+                  <input matInput style="text-align: center;" readonly formControlName="minutes">
+                  <button mat-icon-button matPrefix (click)="editMinutes(0)">
+                    <mat-icon>remove</mat-icon>
+                  </button>
+                  <button mat-icon-button matSuffix (click)="editMinutes(1)">
+                    <mat-icon>add</mat-icon>
+                  </button>
+                </mat-form-field>
+              </div>
+              <div class="element">
+                <mat-label>Segundos</mat-label>
+                <mat-form-field appearance="outline" style="width: 100%;">
+                  <input matInput style="text-align: center;" readonly formControlName="seconds">
+                  <button mat-icon-button matPrefix (click)="editSeconds(0)">
+                    <mat-icon>remove</mat-icon>
+                  </button>
+                  <button mat-icon-button matSuffix (click)="editSeconds(1)">
+                    <mat-icon>add</mat-icon>
+                  </button>
+                </mat-form-field>
+              </div>
+              <div class="save-politics-container">
+                <button mat-flat-button class="indigo_primary_background white_font" (click)="saveSessionsDuration()">Guardar configuración</button>
+              </div>
             </div>
-        </mat-card-content>
-    </mat-card>
+            <div class="animated fadeIn" *ngIf="!sessionsDurationEnabled">
+              <h3 class="ml-20 mt-16"><b>Su perfil no cuenta con los permisos necesarios para visualizar la información de esta sección.</b></h3>
+            </div>
+          </mat-tab>
+          <mat-tab label="Autenticación en dos pasos">
+            <div class="auth-table-container animated fadeIn" style="height: calc(100vh - 304px);" *ngIf="twoFactorAuthEnabled">
+              <table mat-table [dataSource]="dataSourceAuth!">
+                <ng-container matColumnDef="ID">
+                  <th mat-header-cell *matHeaderCellDef>ID</th>
+                  <td mat-cell *matCellDef="let row"> {{row.IDUSUARIO}} </td>
+                </ng-container>
+                
+                <ng-container matColumnDef="NAME">
+                  <th mat-header-cell *matHeaderCellDef>Usuario</th>
+                  <td mat-cell *matCellDef="let row"> {{row.NOMBREUSUARIO}} </td>
+                </ng-container>
+                
+                <ng-container matColumnDef="AUTH">
+                  <th mat-header-cell *matHeaderCellDef>Usar autorización</th>
+                  <td mat-cell *matCellDef="let row; let i = index">
+                    <mat-slide-toggle (change)="changeStatus(i)" [checked]="row.AUTHENABLED">
+                      {{ row.AUTHENABLED ? 'Activado' : 'Desactivado' }}
+                    </mat-slide-toggle>
+                  </td>
+                </ng-container>
+
+                <tr mat-header-row *matHeaderRowDef="displayedColumnsAuth"></tr>
+                <tr mat-row *matRowDef="let row; columns: displayedColumnsAuth;"></tr>
+              </table>
+            </div>
+            <div class="animated fadeIn" *ngIf="!twoFactorAuthEnabled">
+              <h3 class="ml-20 mt-16"><b>Su perfil no cuenta con los permisos necesarios para visualizar la información de esta sección.</b></h3>
+            </div>
+          </mat-tab>
+          <mat-tab label="Número de sesiones activas">
+            <div class="form-pass-container animated fadeIn" style="height: calc(100vh - 304px);" [formGroup]="sessionsNumberForm" *ngIf="activeSessionsNumberEnabled">
+              <div class="element">
+                <mat-label>Sesiones configuradas</mat-label>
+                <mat-form-field appearance="outline" style="width: 100%;">
+                  <input matInput style="text-align: center;" readonly formControlName="number">
+                  <button mat-icon-button matPrefix (click)="editNumber(0)">
+                    <mat-icon>remove</mat-icon>
+                  </button>
+                  <button mat-icon-button matSuffix (click)="editNumber(1)">
+                    <mat-icon>add</mat-icon>
+                  </button>
+                </mat-form-field>
+              </div>
+              <div class="save-politics-container">
+                <button mat-flat-button class="indigo_primary_background white_font" (click)="saveActiveSessionsNumber()">Guardar configuración</button>
+              </div>
+            </div>
+            <div class="animated fadeIn" *ngIf="!activeSessionsNumberEnabled">
+              <h3 class="ml-20 mt-16"><b>Su perfil no cuenta con los permisos necesarios para visualizar la información de esta sección.</b></h3>
+            </div>
+          </mat-tab>
+        </mat-tab-group>
+      </div>
+    </mat-card-content>
+  </mat-card>
 </div>

+ 97 - 69
sistema-mantenimiento-front/src/app/components/system-admin/security-politics/security-politics.component.ts

@@ -2,7 +2,6 @@ import { Permissions } from './../../../interfaces/permissions.interface';
 import { ActiveSessionsNumberResponse } from './../../../interfaces/active-sessions-number.interface';
 import { SessionsDurationsInterface } from './../../../interfaces/sessions-duration.interface';
 import { PasswordFormatResponse } from './../../../interfaces/password-format.interface';
-import { MatSnackBar } from '@angular/material/snack-bar';
 import { MatTableDataSource } from '@angular/material/table';
 import { UsersAuth, UserAuth } from './../../../interfaces/user-auths.interface';
 import { lastValueFrom } from 'rxjs';
@@ -63,7 +62,6 @@ export class SecurityPoliticsComponent implements OnInit {
     private _formBuilder: FormBuilder,
     private _systemAdminService: SystemAdminService,
     private _encService: EncService,
-    private _snackBar: MatSnackBar,
     private _socketService: SocketService,
     private _usersProfilesService: UsersProfilesService,
     private _router: Router,
@@ -146,39 +144,37 @@ export class SecurityPoliticsComponent implements OnInit {
     });
   }
 
-  openSnackBar(msg: string){
-    this._snackBar.open(msg, undefined, {
-      duration: 2500
-    })
-  }
-
   async getAuthData(){
     try{
       let idUser = localStorage.getItem('idusuario')!;
       let userAuths: UsersAuth = await lastValueFrom(this._systemAdminService.getTwoStepsAuth(idUser, 1));
-      this.users = [];
 
-      let cont = 0;
-      userAuths.response.forEach(async (item: UserAuth) => {
-        let idDec = await this._encService.decrypt(item.IDUSUARIO);
-        let id = await this._encService.decrypt(idUser!);
+      this.hasError = userAuths.error;
+      this.errorStr = userAuths.msg;
 
-        if(idDec != id){
-          let usr: UserAuth = {
-            IDUSUARIO: idDec,
-            NOMBREUSUARIO: item.NOMBREUSUARIO,
-            AUTHENABLED: item.AUTHENABLED
-          };
-
-          this.users.push(usr);
+      if(this.hasError){
+        this.isLoading = false;
+      }else{
+        let idUserDec = await this._encService.decrypt(idUser);
+        let userAuthsArr: UserAuth[] = [];
+
+        for(const user of userAuths.response){
+          let idDec = await this._encService.decrypt(user.IDUSUARIO);
+          if(idDec != idUserDec){
+            let usr: UserAuth = {
+              IDUSUARIO: idDec,
+              NOMBREUSUARIO: user.NOMBREUSUARIO,
+              AUTHENABLED: user.AUTHENABLED
+            };
+
+            userAuthsArr.push(usr);
+          }
         }
         
-        cont++;
-        if(cont == userAuths.response.length){
-          this.dataSourceAuth = new MatTableDataSource(this.users);
-          this.getPwdData();
-        }
-      });
+        this.users = userAuthsArr;
+        this.dataSourceAuth = new MatTableDataSource(userAuthsArr);
+        this.getPwdData();
+      }
     }catch(error: any){
       if(error.error == undefined){
         this.errorStr = 'Ocurrió un error inesperado.';
@@ -226,7 +222,7 @@ export class SecurityPoliticsComponent implements OnInit {
         msg = error.error.msg;
       }
 
-      this.openSnackBar(msg);
+      this._resourcesService.openSnackBar(msg);
     }
   }
 
@@ -260,7 +256,7 @@ export class SecurityPoliticsComponent implements OnInit {
         msg = error.error.msg;
       }
 
-      this.openSnackBar(msg);
+      this._resourcesService.openSnackBar(msg);
     }
   }
 
@@ -291,7 +287,7 @@ export class SecurityPoliticsComponent implements OnInit {
         msg = error.error.msg;
       }
 
-      this.openSnackBar(msg);
+      this._resourcesService.openSnackBar(msg);
     }
   }
 
@@ -300,29 +296,36 @@ export class SecurityPoliticsComponent implements OnInit {
       let idUser = localStorage.getItem('idusuario')!;
       let pwdFormat: PasswordFormatResponse = await lastValueFrom(this._systemAdminService.getPasswordFormat(idUser, 1));
 
-      this.politicsForm.controls.minLength.setValue(`${pwdFormat.response.password_format.min_length}`);
-      this.politicsForm.controls.enableUpperCase.setValue(pwdFormat.response.password_format.upper_enabled);
-      this.politicsForm.controls.minUpper.setValue(`${pwdFormat.response.password_format.min_upper}`);
-
-      if(!pwdFormat.response.password_format.upper_enabled){
-        this.politicsForm.controls.minUpper.disable();
-      }
-
-      this.politicsForm.controls.enableNumbers.setValue(pwdFormat.response.password_format.number_enabled);
-      this.politicsForm.controls.minNumber.setValue(`${pwdFormat.response.password_format.min_number}`);
-
-      if(!pwdFormat.response.password_format.number_enabled){
-        this.politicsForm.controls.minNumber.disable();
-      }
-
-      this.politicsForm.controls.enableCharacters.setValue(pwdFormat.response.password_format.chars_enabled);
-      this.politicsForm.controls.minCharacters.setValue(`${pwdFormat.response.password_format.min_chars}`);
+      this.hasError = pwdFormat.error;
+      this.errorStr = pwdFormat.msg;
 
-      if(!pwdFormat.response.password_format.chars_enabled){
-        this.politicsForm.controls.minCharacters.disable();
+      if(this.hasError){
+        this.isLoading = false;
+      }else{
+        this.politicsForm.controls.minLength.setValue(`${pwdFormat.response.password_format.min_length}`);
+        this.politicsForm.controls.enableUpperCase.setValue(pwdFormat.response.password_format.upper_enabled);
+        this.politicsForm.controls.minUpper.setValue(`${pwdFormat.response.password_format.min_upper}`);
+  
+        if(!pwdFormat.response.password_format.upper_enabled){
+          this.politicsForm.controls.minUpper.disable();
+        }
+  
+        this.politicsForm.controls.enableNumbers.setValue(pwdFormat.response.password_format.number_enabled);
+        this.politicsForm.controls.minNumber.setValue(`${pwdFormat.response.password_format.min_number}`);
+  
+        if(!pwdFormat.response.password_format.number_enabled){
+          this.politicsForm.controls.minNumber.disable();
+        }
+  
+        this.politicsForm.controls.enableCharacters.setValue(pwdFormat.response.password_format.chars_enabled);
+        this.politicsForm.controls.minCharacters.setValue(`${pwdFormat.response.password_format.min_chars}`);
+  
+        if(!pwdFormat.response.password_format.chars_enabled){
+          this.politicsForm.controls.minCharacters.disable();
+        }
+        
+        this.getSessionsData();
       }
-      
-      this.getSessionsData();
     }catch(error: any){
       if(error.error == undefined){
         this.errorStr = 'Ocurrió un error inesperado.';
@@ -342,12 +345,19 @@ export class SecurityPoliticsComponent implements OnInit {
       let idUser = localStorage.getItem('idusuario')!;
       let sessionsDuration: SessionsDurationsInterface = await lastValueFrom(this._systemAdminService.getSessionsDuration(idUser, 1));
 
-      this.sessionsForm.controls.days.setValue(`${sessionsDuration.response.sessions_duration.days}`);
-      this.sessionsForm.controls.hours.setValue(`${sessionsDuration.response.sessions_duration.hours}`);
-      this.sessionsForm.controls.minutes.setValue(`${sessionsDuration.response.sessions_duration.minutes}`);
-      this.sessionsForm.controls.seconds.setValue(`${sessionsDuration.response.sessions_duration.seconds}`);
+      this.hasError = sessionsDuration.error;
+      this.errorStr = sessionsDuration.msg;
+
+      if(this.hasError){
+        this.isLoading = false;
+      }else{
+        this.sessionsForm.controls.days.setValue(`${sessionsDuration.response.sessions_duration.days}`);
+        this.sessionsForm.controls.hours.setValue(`${sessionsDuration.response.sessions_duration.hours}`);
+        this.sessionsForm.controls.minutes.setValue(`${sessionsDuration.response.sessions_duration.minutes}`);
+        this.sessionsForm.controls.seconds.setValue(`${sessionsDuration.response.sessions_duration.seconds}`);
       
-      this.getActiveSessionsNumber();
+        this.getActiveSessionsNumber();
+      }
     }catch(error: any){
       if(error.error == undefined){
         this.errorStr = 'Ocurrió un error inesperado.';
@@ -367,22 +377,25 @@ export class SecurityPoliticsComponent implements OnInit {
       let idUser = localStorage.getItem('idusuario')!;
       let activeSessionsNumber: ActiveSessionsNumberResponse = await lastValueFrom(this._systemAdminService.getActiveSessionsNumber(idUser, 1));
 
-      this.sessionsNumberForm.controls.number.setValue(`${activeSessionsNumber.response.active_sessions_number}`);
+      this.hasError = activeSessionsNumber.error;
+      this.errorStr = activeSessionsNumber.msg;
+
+      if(!this.hasError){
+        this.sessionsNumberForm.controls.number.setValue(`${activeSessionsNumber.response.active_sessions_number}`);
 
-      let permissionsEnc = localStorage.getItem('permisos');
-      let permissionsDec = await this._encService.decrypt(permissionsEnc!);
-      let permissionsArr: Permissions = JSON.parse(permissionsDec);
+        let permissionsEnc = localStorage.getItem('permisos');
+        let permissionsDec = await this._encService.decrypt(permissionsEnc!);
+        let permissionsArr: Permissions = JSON.parse(permissionsDec);
 
-      let modPerm = permissionsArr.permissions.filter(item => item.id == 'S002V01M01ADSI')[0];
-      let funPerm = modPerm.children.filter(item => item.id == 'S002V01F04POSE')[0];
+        let modPerm = permissionsArr.permissions.filter(item => item.id == 'S002V01M01ADSI')[0];
+        let funPerm = modPerm.children.filter(item => item.id == 'S002V01F04POSE')[0];
 
-      this.passwordPatternEnabled = funPerm.children.filter(item => item.id == 'S002V01P01PACO')[0].access > 0;
-      this.sessionsDurationEnabled = funPerm.children.filter(item => item.id == 'S002V01P02DUSE')[0].access > 0;
-      this.twoFactorAuthEnabled = funPerm.children.filter(item => item.id == 'S002V01P03ADPA')[0].access > 0;
-      this.activeSessionsNumberEnabled = funPerm.children.filter(item => item.id == 'S002V01P04NSAC')[0].access > 0;
+        this.passwordPatternEnabled = funPerm.children.filter(item => item.id == 'S002V01P01PACO')[0].access > 0;
+        this.sessionsDurationEnabled = funPerm.children.filter(item => item.id == 'S002V01P02DUSE')[0].access > 0;
+        this.twoFactorAuthEnabled = funPerm.children.filter(item => item.id == 'S002V01P03ADPA')[0].access > 0;
+        this.activeSessionsNumberEnabled = funPerm.children.filter(item => item.id == 'S002V01P04NSAC')[0].access > 0;
+      }
 
-      this.hasError = activeSessionsNumber.error;
-      this.errorStr = activeSessionsNumber.msg;
       this.isLoading = false;
     }catch(error: any){
       if(error.error == undefined){
@@ -434,7 +447,7 @@ export class SecurityPoliticsComponent implements OnInit {
         msg = error.error.msg;
       }
 
-      this.openSnackBar(msg);
+      this._resourcesService.openSnackBar(msg);
     }
   }
 
@@ -540,6 +553,14 @@ export class SecurityPoliticsComponent implements OnInit {
       if(days > 0){
         days--;
         this.sessionsForm.controls.days.setValue(`${days}`);
+
+        let hoursStr = this.sessionsForm.getRawValue().hours!;
+        let hours = parseInt(hoursStr);
+
+        if(days == 0 && hours == 0){
+          this.sessionsForm.controls['hours'].setValue('1');
+          this._resourcesService.openSnackBar('La duración mínima de las sesiones debe ser de 1 hora.');
+        }
       }
     }else{
       if(days < 30){
@@ -554,6 +575,13 @@ export class SecurityPoliticsComponent implements OnInit {
     let hours = parseInt(hoursStr!);
     if(action == 0){
       if(hours > 0){
+        let daysStr = this.sessionsForm.getRawValue().days;
+        let days = parseInt(daysStr!);
+        if(days == 0 && hours == 1){
+          this._resourcesService.openSnackBar('La duración mínima de las sesiones debe ser de 1 hora.');
+          return;
+        }
+
         hours--;
         this.sessionsForm.controls.hours.setValue(`${hours}`);
       }

+ 49 - 50
sistema-mantenimiento-front/src/app/components/template/template.component.html

@@ -1,55 +1,54 @@
 <mat-toolbar class="toolbar prevent-select" (window:resize)="onResize()">
-    <mat-toolbar-row class="p-0">
-        <div class="toolbar-row">
-            <div class="menu-items">
-                <h1 class="main-title" [routerLink]="['/sam/home']">{{ title }}</h1>
-                <div class="example-spacer">
-                    <div *ngIf="maintenanceActivated" class="time-counter">
-                        {{ timeLeft }}
-                    </div>
-                </div>
-                <button mat-button class="white_font animated fadeIn" *ngIf="!isLoading && !maintenanceMode"
-                    (click)="modulesActivated = !modulesActivated">
-                    <mat-icon style="margin-bottom: 4px;">arrow_drop_down</mat-icon> MÓDULOS
-                </button>
-                <mat-progress-bar style="background-color: #FFFFFF; color: #FFFFFF; width: 550px;" mode="indeterminate" *ngIf="isLoading"></mat-progress-bar>
-
-                <button mat-button [matMenuTriggerFor]="menuA" class="white_font animated fadeIn" *ngIf="!isLoading && !maintenanceMode" 
-                    [matBadge]="unreadNotifications" [matBadgeHidden]="unreadNotifications <= 0" matBadgeColor="warn">
-                    <mat-icon style="margin-bottom: 4px;">arrow_drop_down</mat-icon> {{ userName }}
-                </button>
-                <mat-menu #menuA="matMenu">
-                    <button mat-menu-item (click)="openMyProfile()"><mat-icon>person</mat-icon> Mi perfil</button>
-                    <button mat-menu-item (click)="rightDrawer.toggle()">
-                        <mat-icon>notifications</mat-icon>
-                        <span>Notificaciones <span class="red_primary_font" style="font-weight: 500;" *ngIf="unreadNotifications > 0">
-                            ({{ unreadNotifications }})
-                        </span></span>
-                    </button>
-                    <button mat-menu-item [routerLink]="['/sam/vacation']"><mat-icon>houseboat</mat-icon> Gestión de Vacaciones </button>
-                    <button mat-menu-item><mat-icon>help</mat-icon> Ayuda</button>
-                    <button mat-menu-item><mat-icon>key</mat-icon> Cambiar contraseña</button>
-                    <button mat-menu-item (click)="logout()"><mat-icon>logout</mat-icon> Cerrar sesión</button>
-                </mat-menu>
-                <span class="m-8"></span>
-                <div class="search-mat-form-field animated fadeIn" *ngIf="!isLoading && !maintenanceMode">
-                    <mat-icon class="prefix">search</mat-icon>
-                    <input type="text" class="input" placeholder="Buscar ubicaciones, archivos, etc..." #input>
-                    <button mat-icon-button [disabled]="input.value === ''">
-                        <mat-icon class="suffix">close</mat-icon>
-                    </button>
-                </div>
-            </div>
-            <div class="icon-modules-container" [ngClass]="{ hidden: !modulesActivated, animate_hide: modulesActivated }">
-                <div class="row-container">
-                    <div class="row-item" *ngFor="let item of menuItems" (click)="navigate(item.IDMODULO)">
-                        <mat-icon>{{ item.ICONOMODULO }}</mat-icon>
-                        <p>{{ item.NOMBREMODULO }}</p>
-                    </div>
-                </div>
-            </div>
+  <mat-toolbar-row class="p-0">
+    <div class="toolbar-row">
+      <div class="menu-items">
+        <h1 class="main-title" [routerLink]="['/sam/home']">{{ title }}</h1>
+        <div class="example-spacer">
+          <div *ngIf="maintenanceActivated" class="time-counter">
+            {{ timeLeft }}
+          </div>
+        </div>
+        <button mat-button class="white_font animated fadeIn" *ngIf="!isLoading && !maintenanceMode"
+        (click)="modulesActivated = !modulesActivated">
+          <mat-icon style="margin-bottom: 4px;">arrow_drop_down</mat-icon> MÓDULOS
+        </button>
+        <mat-progress-bar style="background-color: #FFFFFF; color: #FFFFFF; width: 550px;" mode="indeterminate" *ngIf="isLoading"></mat-progress-bar>
+        <button mat-button [matMenuTriggerFor]="menuA" class="white_font animated fadeIn" *ngIf="!isLoading && !maintenanceMode" 
+        [matBadge]="unreadNotifications" [matBadgeHidden]="unreadNotifications <= 0" matBadgeColor="warn">
+          <mat-icon style="margin-bottom: 4px;">arrow_drop_down</mat-icon> {{ userName }} ({{ usedSessions }}/{{ enabledSessions }})
+        </button>
+        <mat-menu #menuA="matMenu">
+            <button mat-menu-item (click)="openMyProfile()"><mat-icon>person</mat-icon> Mi perfil</button>
+            <button mat-menu-item (click)="rightDrawer.toggle()">
+                <mat-icon>notifications</mat-icon>
+                <span>Notificaciones <span class="red_primary_font" style="font-weight: 500;" *ngIf="unreadNotifications > 0">
+                    ({{ unreadNotifications }})
+                </span></span>
+            </button>
+            <button mat-menu-item [routerLink]="['/sam/vacation']"><mat-icon>houseboat</mat-icon> Gestión de Vacaciones </button>
+            <button mat-menu-item><mat-icon>help</mat-icon> Ayuda</button>
+            <button mat-menu-item><mat-icon>key</mat-icon> Cambiar contraseña</button>
+            <button mat-menu-item (click)="logout()"><mat-icon>logout</mat-icon> Cerrar sesión</button>
+        </mat-menu>
+        <span class="m-8"></span>
+        <div class="search-mat-form-field animated fadeIn" *ngIf="!isLoading && !maintenanceMode">
+            <mat-icon class="prefix">search</mat-icon>
+            <input type="text" class="input" placeholder="Buscar ubicaciones, archivos, etc..." #input>
+            <button mat-icon-button [disabled]="input.value === ''">
+                <mat-icon class="suffix">close</mat-icon>
+            </button>
         </div>
-    </mat-toolbar-row>
+      </div>
+      <div class="icon-modules-container" [ngClass]="{ hidden: !modulesActivated, animate_hide: modulesActivated }">
+          <div class="row-container">
+              <div class="row-item" *ngFor="let item of menuItems" (click)="navigate(item.IDMODULO)">
+                  <mat-icon>{{ item.ICONOMODULO }}</mat-icon>
+                  <p>{{ item.NOMBREMODULO }}</p>
+              </div>
+          </div>
+      </div>
+    </div>
+  </mat-toolbar-row>
 </mat-toolbar>
 
 <mat-drawer-container class="example-container" autosize>

+ 42 - 0
sistema-mantenimiento-front/src/app/components/template/template.component.ts

@@ -45,6 +45,7 @@ import { NotificationDialogComponent } from './notification-dialog/notification-
 import { MatSidenav } from '@angular/material/sidenav';
 import { CorrectiveMaintenanceService } from 'src/app/services/corrective-maintenance.service';
 import { CorrectiveWorkOrderDetailsResponse } from 'src/app/interfaces/corrective-maintenance.interface';
+import { ActiveSessionsNumberResponse } from 'src/app/interfaces/active-sessions-number.interface';
 
 @Component({
   selector: 'app-template',
@@ -67,6 +68,8 @@ export class TemplateComponent implements OnInit {
   secondsLeft = 0;
   errorsCont = 0;
   timeLeft = "5:00";
+  enabledSessions: number;
+  usedSessions: number;
 
   userName = "";
 
@@ -96,6 +99,7 @@ export class TemplateComponent implements OnInit {
     private _notificationsService: NotificationsService,
     private _functionsService: FunctionsService,
     private _correctiveMaintenanceService: CorrectiveMaintenanceService,
+    private _systemAdminService: SystemAdminService,
   ) {
     this.navItems = [];
     this.menuItems = [];
@@ -103,6 +107,8 @@ export class TemplateComponent implements OnInit {
     this.notificationsForPanel = [];
     this.unreadNotifications = 0;
     this.totalNotifications = [];
+    this.enabledSessions = 0;
+    this.usedSessions = 0;
   }
 
   ngOnInit(): void {
@@ -562,6 +568,42 @@ export class TemplateComponent implements OnInit {
         }
       });
 
+      this._socketService.newSessionSaved().subscribe(async (sessionsStr) => {
+        try{
+          let idUser = localStorage.getItem('idusuario');
+          if(idUser != null && idUser != undefined && idUser != ''){
+            let sessionsArr = JSON.parse(sessionsStr);
+            let sessionsCount = 0;
+            let idUserDec = await this._encService.decrypt(idUser);
+    
+            for(const session of sessionsArr){
+              let sessionUsr = await this._encService.decrypt(session.user);
+              if(sessionUsr == idUserDec){
+                sessionsCount++;
+              }
+            }
+            
+            let activeSessionsNumber: ActiveSessionsNumberResponse = await lastValueFrom(this._systemAdminService.getActiveSessionsNumber(idUser, 1));
+            if(activeSessionsNumber.error){
+              this._resourcesService.openSnackBar(activeSessionsNumber.msg);
+            }else{
+              this.enabledSessions = activeSessionsNumber.response.active_sessions_number;
+              this.usedSessions = sessionsCount;
+            }
+          }
+        }catch(error: any){
+          if(error.error == undefined){
+            this._resourcesService.openSnackBar('Ocurrió un error inesperado.');
+          }else if(error.error.msg == undefined){
+            this._resourcesService.openSnackBar('Ocurrió un error inesperado.');
+          }else{
+            this._resourcesService.openSnackBar(error.error.msg);
+          }
+        }
+      });
+
+      this._socketService.getSessions();
+
       let userName = localStorage.getItem('nombre_usuario');
       let name = await this._encService.decrypt(userName!);
 

+ 9 - 7
sistema-mantenimiento-front/src/app/components/users-profiles/users-admin/new-user/new-user.component.ts

@@ -144,9 +144,9 @@ export class NewUserComponent implements OnInit {
       }
     }catch(error: any){
       if(error.error == undefined){
-        this.errorStr = 'Ocurrió un error inesperado.';
+        this.errorStr = 'Ocurrió un error inesperado (1).';
       }else if(error.error.msg == undefined){
-        this.errorStr = 'Ocurrió un error inesperado.';
+        this.errorStr = 'Ocurrió un error inesperado (2).';
       }else{
         this.errorStr = error.error.msg;
       }
@@ -185,9 +185,9 @@ export class NewUserComponent implements OnInit {
       }
     }catch(error: any){
       if(error.error.msg == undefined){
-        this.errorStr = "Ocurrió un error inesperado.";
+        this.errorStr = "Ocurrió un error inesperado (3).";
       }else if(error.error.msg == undefined){
-        this.errorStr = "Ocurrió un error inesperado.";
+        this.errorStr = "Ocurrió un error inesperado (4).";
       }else{
         this.errorStr = error.error.msg;
       }
@@ -205,7 +205,7 @@ export class NewUserComponent implements OnInit {
       this.hasError = passwordPattern.error;
       this.errorStr = passwordPattern.msg;
 
-      if(!this.hasError){
+      if(!this.hasError && this.isNew){
         this.userForm.controls['password'].setValidators(Validators.minLength(passwordPattern.response.password_format.min_length));
         this.userForm.controls['password_confirmation'].setValidators(Validators.minLength(passwordPattern.response.password_format.min_length));
         this.passMinLength = passwordPattern.response.password_format.min_length;
@@ -228,10 +228,12 @@ export class NewUserComponent implements OnInit {
 
       this.isLoading = false;
     }catch(error: any){
+      console.log(error);
+      
       if(error.error == undefined){
-        this.errorStr = 'Ocurrió un error inesperado.';
+        this.errorStr = 'Ocurrió un error inesperado (5).';
       }else if(error.error.msg == undefined){
-        this.errorStr = 'Ocurrió un error inesperado.';
+        this.errorStr = 'Ocurrió un error inesperado (6).';
       }else{
         this.errorStr = error.error.msg;
       }

+ 2 - 2
sistema-mantenimiento-front/src/app/components/users-profiles/users-admin/users-admin.component.ts

@@ -263,9 +263,9 @@ export class UsersAdminComponent implements OnInit {
       this.getData();
     }catch(error: any){
       if(error.error == undefined){
-        this._resourcesService.openSnackBar('Ocurrió un error inesperado.');
+        this._resourcesService.openSnackBar('Ocurrió un error inesperado (3).');
       }else if(error.error.msg == undefined){
-        this._resourcesService.openSnackBar('Ocurrió un error inesperado.');
+        this._resourcesService.openSnackBar('Ocurrió un error inesperado (4).');
       }else{
         this._resourcesService.openSnackBar(error.error.msg);
       }

+ 26 - 12
sistema-mantenimiento-front/src/app/services/login/login-data.service.ts

@@ -42,6 +42,14 @@ export class LoginDataService {
     if(panel != null){
       this.localStorageLogin.setItem('panel', panel)
     }
+
+    let socketInfoObj = {
+      token: token,
+      user: idusuario
+    };
+
+    let socketInfoStr = JSON.stringify(socketInfoObj);
+    this._socketService.saveSession(socketInfoStr);
   }
 
   async verifyToken(token: string): Promise<boolean>{
@@ -104,18 +112,15 @@ export class LoginDataService {
       let ciud = location.locality;
       let esta = location.city;
       let pais = location.countryName;
-
-      await lastValueFrom(this._connectionsServiece.setLastConnection({
-        id: id,
-        linea: 1,
-        latitude: lati,
-        longitude: long,
-        accuracy: prec,
-        city: ciud,
-        state: esta,
-        country: pais,
-      }));
   
+      let sessionData = {
+        token: localStorage.getItem('token'),
+        user: localStorage.getItem('idusuario')
+      }
+
+      let sessionDataStr = JSON.stringify(sessionData);
+      this._socketService.deleteSession(sessionDataStr);
+
       this._socketService.unregister(id!);
       // this.localStorageLogin.clear()
       this.localStorageLogin.removeItem('correo');
@@ -127,7 +132,16 @@ export class LoginDataService {
       this.localStorageLogin.removeItem('token');
 
       this.router.navigate(['login']);
-
+      await lastValueFrom(this._connectionsServiece.setLastConnection({
+        id: id,
+        linea: 1,
+        latitude: lati,
+        longitude: long,
+        accuracy: prec,
+        city: ciud,
+        state: esta,
+        country: pais,
+      }));
     }catch(error: any){
       this._socketService.unregister(id!);
       // this.localStorageLogin.clear()

+ 16 - 0
sistema-mantenimiento-front/src/app/services/socket.service.ts

@@ -110,4 +110,20 @@ export class SocketService{
   panelAssociationsChanged(){
     return this.socket.fromEvent('panel_associations_changed').pipe(map((data: any) => data));
   }
+
+  saveSession(msg: string){
+    this.socket.emit('save_session', msg);
+  }
+
+  newSessionSaved(){
+    return this.socket.fromEvent('new_session_saved').pipe(map((data: any) => data));
+  }
+
+  deleteSession(msg: string){
+    this.socket.emit('delete_session', msg);
+  }
+
+  getSessions(){
+    this.socket.emit('get_sessions');
+  }
 }

+ 4 - 4
sistema-mantenimiento-front/src/environments/environment.prod.ts

@@ -119,10 +119,10 @@ export const supportedFiles = [
 ];
 
 export const validateRFC = "/^([A-ZÑ&]{3,4}) ?(?:- ?)?(\d{2}(?:0[1-9]|1[0-2])(?:0[1-9]|[12]\d|3[01])) ?(?:- ?)?([A-Z\d]{2})([A\d])$/";
-export const socket = 'http://localhost:3200';
-// export const socket = 'https://a9cf-209-50-56-224.ngrok-free.app';
-export const apiTemp = `http://192.168.100.105:8000/api/`;
-// export const apiTemp = 'http://git.ittec.mx/sam/public/api/';
+// export const socket = 'http://localhost:3200';
+export const socket = 'https://a9cf-209-50-56-224.ngrok-free.app';
+// export const apiTemp = `http://192.168.100.105:8000/api/`;
+export const apiTemp = 'http://git.ittec.mx/sam/public/api/';
 
 
 /*******************************************************************************/