@propmix/profet-common-header 3.2.0-beta.1 → 3.2.0-beta.2

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.
@@ -223,6 +223,8 @@ class Utilities {
223
223
  class CommonHeaderService {
224
224
  constructor(config) {
225
225
  this.config = config;
226
+ this.SESSION_EXPIRED_KEY = 'session_expired';
227
+ this.LAST_ACTIVE_SESSION_KEY = 'lastActiveSessionTime';
226
228
  this.baseUrl = '';
227
229
  this.isSessionExpiryDialogOpen = false;
228
230
  this._apiGatewayService = inject(ApiGatewayService);
@@ -318,6 +320,63 @@ class CommonHeaderService {
318
320
  let url = `${this.baseUrl + EndPoints.API_URLS.updateLastAccessedApplication}`;
319
321
  return this._apiGatewayService.doPost(url, reqBody);
320
322
  }
323
+ /**
324
+ * Helper to get the root domain (e.g. .profet.ai) to share cookies across subdomains/ports.
325
+ * If on localhost or an IP, it falls back to the hostname.
326
+ */
327
+ getRootDomain() {
328
+ const hostname = window.location.hostname;
329
+ const parts = hostname.split('.');
330
+ if (parts.length > 2 && !/^\d{1,3}\.\d{1,3}\.\d{1,3}\.\d{1,3}$/.test(hostname)) {
331
+ // If we have 4+ parts (e.g. app1.local.profet.ai), we want to include the environment (local.profet.ai)
332
+ // to avoid sharing cookies with app1.dev.profet.ai or app1.profet.ai.
333
+ if (parts.length > 3) {
334
+ return '.' + parts.slice(-3).join('.');
335
+ }
336
+ // For standard 3 parts (app1.profet.ai), share on .profet.ai
337
+ return '.' + parts.slice(-2).join('.');
338
+ }
339
+ return hostname;
340
+ }
341
+ /**
342
+ * Generates a unique cookie name based on the environment root domain.
343
+ * e.g. 'lastActive' on .qa.profet.ai -> 'lastActive_qa_profet_ai'
344
+ * @param name Base cookie name
345
+ */
346
+ getSuffixedCookieName(name) {
347
+ const rootDomain = this.getRootDomain();
348
+ // Replace dots with underscores to create a clean suffix
349
+ const suffix = rootDomain.replace(/\./g, '_');
350
+ return `${name}${suffix}`;
351
+ }
352
+ setCookie(name, value, days) {
353
+ const uniqueName = this.getSuffixedCookieName(name);
354
+ let expires = "";
355
+ if (days) {
356
+ const date = new Date();
357
+ date.setTime(date.getTime() + (days * 24 * 60 * 60 * 1000));
358
+ expires = "; expires=" + date.toUTCString();
359
+ }
360
+ // Important: set domain to allow sharing across subdomains
361
+ const domain = "; domain=" + this.getRootDomain();
362
+ document.cookie = uniqueName + "=" + (value || "") + expires + domain + "; path=/";
363
+ }
364
+ getCookie(name) {
365
+ const uniqueName = this.getSuffixedCookieName(name);
366
+ const nameEQ = uniqueName + "=";
367
+ const ca = document.cookie.split(';');
368
+ for (let i = 0; i < ca.length; i++) {
369
+ let c = ca[i];
370
+ while (c.charAt(0) == ' ')
371
+ c = c.substring(1, c.length);
372
+ if (c.indexOf(nameEQ) == 0)
373
+ return c.substring(nameEQ.length, c.length);
374
+ }
375
+ return null;
376
+ }
377
+ deleteCookie(name) {
378
+ this.setCookie(name, '', -1);
379
+ }
321
380
  }
322
381
  CommonHeaderService.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "15.2.10", ngImport: i0, type: CommonHeaderService, deps: [{ token: 'headerConfig' }], target: i0.ɵɵFactoryTarget.Injectable });
323
382
  CommonHeaderService.ɵprov = i0.ɵɵngDeclareInjectable({ minVersion: "12.0.0", version: "15.2.10", ngImport: i0, type: CommonHeaderService, providedIn: 'root' });
@@ -455,75 +514,21 @@ class HeaderComponent {
455
514
  // }
456
515
  this.resetTimer();
457
516
  // Clear any stale logout signal on init
458
- this.setCookie('session_expired', '', -1);
517
+ this._headerSer.setCookie(this._headerSer.SESSION_EXPIRED_KEY, '', -1);
459
518
  this.startLogoutCheck();
460
519
  });
461
520
  }
462
- /**
463
- * Helper to get the root domain (e.g. .mycom.ai) to share cookies across subdomains/ports.
464
- * If on localhost or an IP, it falls back to the hostname.
465
- */
466
- getRootDomain() {
467
- const hostname = window.location.hostname;
468
- const parts = hostname.split('.');
469
- if (parts.length > 2 && !/^\d{1,3}\.\d{1,3}\.\d{1,3}\.\d{1,3}$/.test(hostname)) {
470
- // If we have 4+ parts (e.g. app1.local.profet.ai), we want to include the environment (local.profet.ai)
471
- // to avoid sharing cookies with app1.dev.profet.ai or app1.profet.ai.
472
- if (parts.length > 3) {
473
- return '.' + parts.slice(-3).join('.');
474
- }
475
- // For standard 3 parts (app1.profet.ai), share on .profet.ai
476
- return '.' + parts.slice(-2).join('.');
477
- }
478
- return hostname;
479
- }
480
- /**
481
- * Generates a unique cookie name based on the environment root domain.
482
- * e.g. 'lastActive' on .qa.profet.ai -> 'lastActive_qa_profet_ai'
483
- * @param name Base cookie name
484
- */
485
- getSuffixedCookieName(name) {
486
- const rootDomain = this.getRootDomain();
487
- // Replace dots with underscores to create a clean suffix
488
- const suffix = rootDomain.replace(/\./g, '_');
489
- return `${name}${suffix}`;
490
- }
491
- setCookie(name, value, days) {
492
- const uniqueName = this.getSuffixedCookieName(name);
493
- let expires = "";
494
- if (days) {
495
- const date = new Date();
496
- date.setTime(date.getTime() + (days * 24 * 60 * 60 * 1000));
497
- expires = "; expires=" + date.toUTCString();
498
- }
499
- // Important: set domain to allow sharing across subdomains
500
- const domain = "; domain=" + this.getRootDomain();
501
- document.cookie = uniqueName + "=" + (value || "") + expires + domain + "; path=/";
502
- }
503
- getCookie(name) {
504
- const uniqueName = this.getSuffixedCookieName(name);
505
- const nameEQ = uniqueName + "=";
506
- const ca = document.cookie.split(';');
507
- for (let i = 0; i < ca.length; i++) {
508
- let c = ca[i];
509
- while (c.charAt(0) == ' ')
510
- c = c.substring(1, c.length);
511
- if (c.indexOf(nameEQ) == 0)
512
- return c.substring(nameEQ.length, c.length);
513
- }
514
- return null;
515
- }
516
521
  resetTimer(isUserActivity = true) {
517
522
  clearTimeout(this.inactivityTimeout);
518
523
  // Update global activity timestamp in cookie ONLY if triggered by user activity
519
524
  if (isUserActivity) {
520
525
  // Use a short expiry (e.g. 1 day) or sync with session length
521
- this.setCookie('lastActiveSessionTime', Date.now().toString(), 1);
526
+ this._headerSer.setCookie(this._headerSer.LAST_ACTIVE_SESSION_KEY, Date.now().toString(), 1);
522
527
  }
523
528
  // if (!this._headerSer.isSessionExpiryDialogOpen) {
524
529
  this.inactivityTimeout = setTimeout(() => {
525
530
  // Check global activity before logging out
526
- const lastActive = this.getCookie('lastActiveSessionTime');
531
+ const lastActive = this._headerSer.getCookie(this._headerSer.LAST_ACTIVE_SESSION_KEY);
527
532
  const now = Date.now();
528
533
  const lastActiveTime = lastActive ? parseInt(lastActive, 10) : 0;
529
534
  const elapsed = now - lastActiveTime;
@@ -545,11 +550,11 @@ class HeaderComponent {
545
550
  startLogoutCheck() {
546
551
  // Poll for the logout signal cookie (works across ports/subdomains)
547
552
  this.logoutCheckInterval = setInterval(() => {
548
- if (this.getCookie('session_expired')) {
553
+ if (this._headerSer.getCookie(this._headerSer.SESSION_EXPIRED_KEY)) {
549
554
  // Check if tab still "active" according to the shared time
550
555
  // If tab is active but receiving a logout signal, it implies a MANUAL logout from another tab.
551
556
  // If tab is inactive and receiving a logout signal, it implies a TIMEOUT.
552
- const lastActive = this.getCookie('lastActiveSessionTime');
557
+ const lastActive = this._headerSer.getCookie(this._headerSer.LAST_ACTIVE_SESSION_KEY);
553
558
  const now = Date.now();
554
559
  const lastActiveTime = lastActive ? parseInt(lastActive, 10) : 0;
555
560
  const elapsed = now - lastActiveTime;
@@ -565,15 +570,18 @@ class HeaderComponent {
565
570
  // }
566
571
  if (broadcast) {
567
572
  // Set a cookie to signal other tabs/ports
568
- this.setCookie('session_expired', 'true', 1);
573
+ this._headerSer.setCookie(this._headerSer.SESSION_EXPIRED_KEY, 'true', 1);
569
574
  }
570
575
  this.logoutEvent.emit();
571
576
  let sessionUrl = this._headerSer.headerConfig.signOutUrl;
577
+ if (this._headerSer.headerConfig.enableLastUrlRedirection) {
578
+ const separator = sessionUrl.includes('?') ? '&' : '?';
579
+ sessionUrl = sessionUrl + separator + 'returnUrl=' + encodeURIComponent(window.location.href);
580
+ }
572
581
  // Only add sessionExpired params if it is NOT a manual logout
573
582
  if (!isManual) {
574
- let appUrl = this._headerSer.headerConfig.signOutUrl;
575
- let separator = appUrl.includes('?') ? '&' : '?';
576
- sessionUrl = appUrl + separator + 'sessionExpired=true&timeout=' + this.INACTIVITY_LIMIT;
583
+ const separator = sessionUrl.includes('?') ? '&' : '?';
584
+ sessionUrl = sessionUrl + separator + 'sessionExpired=true&timeout=' + this.INACTIVITY_LIMIT;
577
585
  }
578
586
  signOut({ global: true, oauth: { redirectUrl: sessionUrl } })
579
587
  .then(() => {
@@ -686,22 +694,27 @@ class HeaderComponent {
686
694
  onLogoutClick() {
687
695
  this.menuTrigger.closeMenu();
688
696
  // Sync with other tabs
689
- this.setCookie('session_expired', 'true', 1);
697
+ this._headerSer.setCookie(this._headerSer.SESSION_EXPIRED_KEY, 'true', 1);
690
698
  // Clear timers
691
699
  if (this.inactivityTimeout)
692
700
  clearTimeout(this.inactivityTimeout);
693
701
  if (this.logoutCheckInterval)
694
702
  clearInterval(this.logoutCheckInterval);
695
703
  this.logoutEvent.emit();
696
- signOut({ global: true, oauth: { redirectUrl: this._headerSer.headerConfig.signOutUrl } })
704
+ let sessionUrl = this._headerSer.headerConfig.signOutUrl;
705
+ if (this._headerSer.headerConfig.enableLastUrlRedirection) {
706
+ const separator = sessionUrl.includes('?') ? '&' : '?';
707
+ sessionUrl = sessionUrl + separator + 'returnUrl=' + encodeURIComponent(window.location.href);
708
+ }
709
+ signOut({ global: true, oauth: { redirectUrl: sessionUrl } })
697
710
  .then((data) => {
698
- window.open(this._headerSer.headerConfig.signOutUrl, '_self');
711
+ window.open(sessionUrl, '_self');
699
712
  })
700
713
  .catch((err) => {
701
714
  console.log(err);
702
- signOut({ global: true, oauth: { redirectUrl: this._headerSer.headerConfig.signOutUrl } })
715
+ signOut({ global: true, oauth: { redirectUrl: sessionUrl } })
703
716
  .then(() => {
704
- window.open(this._headerSer.headerConfig.signOutUrl, '_self');
717
+ window.open(sessionUrl, '_self');
705
718
  })
706
719
  .catch((error) => console.log(error));
707
720
  });