valtech-components 2.0.463 → 2.0.465

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
@@ -13,7 +13,7 @@ import * as i1$2 from '@angular/platform-browser';
13
13
  import QRCodeStyling from 'qr-code-styling';
14
14
  import * as i1$3 from '@angular/forms';
15
15
  import { ReactiveFormsModule, FormsModule, FormControl, Validators } from '@angular/forms';
16
- import { BehaviorSubject, filter, map, distinctUntilChanged, Subject, firstValueFrom, throwError, of } from 'rxjs';
16
+ import { BehaviorSubject, filter, map, distinctUntilChanged, Subject, firstValueFrom, throwError, of, from } from 'rxjs';
17
17
  import * as i1$4 from 'ng-otp-input';
18
18
  import { NgOtpInputComponent, NgOtpInputModule } from 'ng-otp-input';
19
19
  import * as i2 from '@ionic/angular';
@@ -38,7 +38,7 @@ import * as i1$7 from '@angular/fire/storage';
38
38
  import { provideStorage, getStorage, connectStorageEmulator, ref, uploadBytesResumable, getDownloadURL, getMetadata, deleteObject, listAll } from '@angular/fire/storage';
39
39
  import * as i1$9 from '@angular/common/http';
40
40
  import { provideHttpClient, withInterceptors } from '@angular/common/http';
41
- import { tap, catchError, switchMap, finalize, filter as filter$1, take } from 'rxjs/operators';
41
+ import { tap, catchError, switchMap, map as map$1, finalize, filter as filter$1, take } from 'rxjs/operators';
42
42
 
43
43
  /**
44
44
  * val-avatar
@@ -21480,6 +21480,11 @@ class FirebaseService {
21480
21480
  async signInWithCustomToken(token) {
21481
21481
  try {
21482
21482
  const credential = await signInWithCustomToken(this.auth, token);
21483
+ // Forzar refresh del token para asegurar que los claims estén actualizados
21484
+ // Esto es necesario porque getIdTokenResult() cachea el resultado
21485
+ if (credential.user) {
21486
+ await credential.user.getIdToken(true);
21487
+ }
21483
21488
  return credential;
21484
21489
  }
21485
21490
  catch (error) {
@@ -21557,14 +21562,15 @@ class FirebaseService {
21557
21562
  * Obtiene los claims personalizados del token del usuario.
21558
21563
  * Los claims son establecidos por tu backend al crear el Custom Token.
21559
21564
  *
21565
+ * @param forceRefresh - Si true, fuerza la renovación del token para obtener claims actualizados
21560
21566
  * @returns Objeto con los claims o vacío si no hay usuario
21561
21567
  */
21562
- async getClaims() {
21568
+ async getClaims(forceRefresh = false) {
21563
21569
  const user = this.auth.currentUser;
21564
21570
  if (!user)
21565
21571
  return {};
21566
21572
  try {
21567
- const result = await user.getIdTokenResult();
21573
+ const result = await user.getIdTokenResult(forceRefresh);
21568
21574
  return result.claims;
21569
21575
  }
21570
21576
  catch {
@@ -21589,6 +21595,7 @@ class FirebaseService {
21589
21595
  * Obtiene las memberships (organizaciones) del usuario.
21590
21596
  * Cada membership contiene el rol y permisos en esa organización.
21591
21597
  *
21598
+ * @param forceRefresh - Si true, fuerza la renovación del token
21592
21599
  * @returns Mapa de orgId → MembershipInfo
21593
21600
  *
21594
21601
  * @example
@@ -21597,27 +21604,29 @@ class FirebaseService {
21597
21604
  * // { 'org_abc': { roleId: 'admin', roleName: 'admin', permissions: ['users:*', ...] } }
21598
21605
  * ```
21599
21606
  */
21600
- async getMemberships() {
21601
- const claims = await this.getClaims();
21607
+ async getMemberships(forceRefresh = false) {
21608
+ const claims = await this.getClaims(forceRefresh);
21602
21609
  return claims['memberships'] || {};
21603
21610
  }
21604
21611
  /**
21605
21612
  * Obtiene la organización activa del usuario.
21606
21613
  * La organización activa se establece al hacer login o al cambiar de org.
21607
21614
  *
21615
+ * @param forceRefresh - Si true, fuerza la renovación del token
21608
21616
  * @returns ID de la organización activa o null si no hay ninguna
21609
21617
  */
21610
- async getActiveOrg() {
21611
- const claims = await this.getClaims();
21618
+ async getActiveOrg(forceRefresh = false) {
21619
+ const claims = await this.getClaims(forceRefresh);
21612
21620
  return claims['activeOrg'] || null;
21613
21621
  }
21614
21622
  /**
21615
21623
  * Obtiene información de todas las organizaciones del usuario.
21616
21624
  *
21625
+ * @param forceRefresh - Si true, fuerza la renovación del token
21617
21626
  * @returns Array con información de cada organización
21618
21627
  */
21619
- async getOrganizations() {
21620
- const memberships = await this.getMemberships();
21628
+ async getOrganizations(forceRefresh = false) {
21629
+ const memberships = await this.getMemberships(forceRefresh);
21621
21630
  return Object.entries(memberships).map(([id, info]) => ({
21622
21631
  id,
21623
21632
  roleId: info.roleId,
@@ -24938,16 +24947,21 @@ class AuthService {
24938
24947
  switchOrg(organizationId) {
24939
24948
  return this.http
24940
24949
  .post(`${this.baseUrl}/switch-org`, { organizationId })
24941
- .pipe(tap(async (response) => {
24950
+ .pipe(switchMap(response => {
24942
24951
  // Re-autenticar en Firebase con el nuevo token
24943
- if (response.firebaseToken) {
24944
- await this.signInWithFirebase(response.firebaseToken);
24945
- }
24946
- // Notificar cambio a otras pestañas
24947
- this.syncService.broadcast({
24948
- type: 'ORG_SWITCH',
24949
- payload: { activeOrg: response.activeOrg },
24950
- });
24952
+ // Usar switchMap + from para esperar a que Firebase complete
24953
+ const firebaseAuth$ = response.firebaseToken
24954
+ ? from(this.signInWithFirebase(response.firebaseToken))
24955
+ : of(undefined);
24956
+ return firebaseAuth$.pipe(tap(() => {
24957
+ // Notificar cambio a otras pestañas
24958
+ this.syncService.broadcast({
24959
+ type: 'ORG_SWITCH',
24960
+ payload: { activeOrg: response.activeOrg },
24961
+ });
24962
+ }),
24963
+ // Retornar response original después de que Firebase complete
24964
+ map$1(() => response));
24951
24965
  }), catchError(error => this.handleAuthError(error)));
24952
24966
  }
24953
24967
  // =============================================
@@ -25216,8 +25230,8 @@ const authInterceptor = (request, next) => {
25216
25230
  if (!isApiRequest(request, config.apiUrl)) {
25217
25231
  return next(request);
25218
25232
  }
25219
- // Omitir endpoints de auth que no necesitan token
25220
- if (isAuthEndpoint(request, config.authPrefix)) {
25233
+ // Omitir endpoints públicos que no necesitan token
25234
+ if (isPublicEndpoint(request, config.authPrefix)) {
25221
25235
  return next(request);
25222
25236
  }
25223
25237
  const accessToken = authService.accessToken();
@@ -25226,7 +25240,7 @@ const authInterceptor = (request, next) => {
25226
25240
  request = addAuthHeader(request, accessToken);
25227
25241
  }
25228
25242
  return next(request).pipe(catchError((error) => {
25229
- if (error.status === 401 && !isAuthEndpoint(request, config.authPrefix)) {
25243
+ if (error.status === 401 && !isNoRefreshEndpoint(request, config.authPrefix)) {
25230
25244
  return handle401Error(request, next, authService);
25231
25245
  }
25232
25246
  if (error.status === 403) {
@@ -25252,22 +25266,35 @@ function isApiRequest(request, apiUrl) {
25252
25266
  return request.url.startsWith(apiUrl) || request.url.includes('/v2/auth');
25253
25267
  }
25254
25268
  /**
25255
- * Verifica si la request es a un endpoint de auth que no debe reintentar.
25269
+ * Verifica si la request es a un endpoint público que NO requiere token.
25256
25270
  */
25257
- function isAuthEndpoint(request, authPrefix) {
25258
- // Endpoints que no deben intentar refresh en 401
25271
+ function isPublicEndpoint(request, authPrefix) {
25272
+ const publicEndpoints = [
25273
+ '/signin',
25274
+ '/signup',
25275
+ '/refresh',
25276
+ '/logout',
25277
+ '/mfa/verify', // Solo durante login
25278
+ ];
25279
+ return publicEndpoints.some((endpoint) => request.url.includes(`${authPrefix}${endpoint}`));
25280
+ }
25281
+ /**
25282
+ * Verifica si la request es a un endpoint que NO debe reintentar refresh en 401.
25283
+ */
25284
+ function isNoRefreshEndpoint(request, authPrefix) {
25285
+ // Endpoints que no deben intentar refresh en 401:
25259
25286
  // - Públicos: signin, signup, refresh, logout
25260
- // - MFA: verify (durante login), disable (401 = contraseña incorrecta), confirm (401 = código incorrecto)
25261
- const authEndpoints = [
25287
+ // - MFA: verify (durante login), confirm (401 = código incorrecto), disable (401 = contraseña incorrecta)
25288
+ const noRefreshEndpoints = [
25262
25289
  '/signin',
25263
25290
  '/signup',
25264
25291
  '/refresh',
25265
25292
  '/logout',
25266
25293
  '/mfa/verify',
25267
- '/mfa/disable',
25268
25294
  '/mfa/confirm',
25295
+ '/mfa/disable',
25269
25296
  ];
25270
- return authEndpoints.some((endpoint) => request.url.includes(`${authPrefix}${endpoint}`));
25297
+ return noRefreshEndpoints.some((endpoint) => request.url.includes(`${authPrefix}${endpoint}`));
25271
25298
  }
25272
25299
  /**
25273
25300
  * Maneja errores 401 refrescando el token.