@arsedizioni/ars-utils 18.2.338 → 18.2.339

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.
@@ -1,10 +1,11 @@
1
1
  import * as i0 from '@angular/core';
2
2
  import { signal, computed, inject, Injectable, NgModule } from '@angular/core';
3
+ import { HttpClient, HttpHeaders, HttpErrorResponse } from '@angular/common/http';
4
+ import { Router } from '@angular/router';
3
5
  import { DialogService } from '@arsedizioni/ars-utils/ui';
4
- import { timer, EMPTY, throwError, of, catchError as catchError$1 } from 'rxjs';
5
- import { HttpClient, HttpHeaders } from '@angular/common/http';
6
+ import { throwError, of, catchError as catchError$1, switchMap } from 'rxjs';
6
7
  import { BroadcastService, SystemUtils } from '@arsedizioni/ars-utils/core';
7
- import { switchMap, shareReplay, catchError, map } from 'rxjs/operators';
8
+ import { catchError, map } from 'rxjs/operators';
8
9
 
9
10
  const ClipperMessages = {
10
11
  /**
@@ -1851,30 +1852,14 @@ class ClipperSearchUtils {
1851
1852
  }
1852
1853
 
1853
1854
  class ClipperService {
1854
- get loginInfo() {
1855
- if (!this._loginInfo) {
1856
- const loginInfo = localStorage.getItem('clipper_login');
1857
- if (loginInfo) {
1858
- try {
1859
- this._loginInfo = JSON.parse(loginInfo);
1860
- }
1861
- catch { }
1862
- }
1863
- }
1864
- return this._loginInfo;
1865
- }
1866
- get serviceUri() {
1867
- return this._serviceUri;
1868
- }
1869
1855
  constructor() {
1870
- this.REFRESH_INTERVAL = 60000 * 50; //50 min
1871
1856
  this.httpClient = inject(HttpClient);
1872
1857
  this.broadcastService = inject(BroadcastService);
1873
1858
  this.dialogService = inject(DialogService);
1874
- this.tokenRefreshInterval = this.REFRESH_INTERVAL;
1875
- this.refreshing = false;
1859
+ this._serviceUri = null;
1860
+ this._accessRoute = null;
1861
+ this._errorRoute = null;
1876
1862
  this._loginInfo = null;
1877
- this._serviceUri = "https://clipper.arsedizioni.it";
1878
1863
  this.loggedIn = signal(false);
1879
1864
  this.loggingIn = signal(false);
1880
1865
  this.snapshot = signal(null);
@@ -1886,13 +1871,29 @@ class ClipperService {
1886
1871
  });
1887
1872
  this.visible = signal(false);
1888
1873
  this.supportsRS = signal(false);
1889
- this.initialize();
1890
1874
  }
1891
- ngOnDestroy() {
1892
- // Clean-up
1893
- if (this.tokenRefreshTimerSubscription) {
1894
- this.tokenRefreshTimerSubscription.unsubscribe();
1875
+ get serviceUri() {
1876
+ return this._serviceUri;
1877
+ }
1878
+ get accessRoute() {
1879
+ return this._accessRoute;
1880
+ }
1881
+ get errorRoute() {
1882
+ return this._errorRoute;
1883
+ }
1884
+ get loginInfo() {
1885
+ if (!this._loginInfo) {
1886
+ const loginInfo = localStorage.getItem('clipper_login');
1887
+ if (loginInfo) {
1888
+ try {
1889
+ this._loginInfo = JSON.parse(loginInfo);
1890
+ }
1891
+ catch { }
1892
+ }
1895
1893
  }
1894
+ return this._loginInfo;
1895
+ }
1896
+ ngOnDestroy() {
1896
1897
  if (this.broadcastServiceSubscription) {
1897
1898
  this.broadcastServiceSubscription.unsubscribe();
1898
1899
  }
@@ -1900,16 +1901,18 @@ class ClipperService {
1900
1901
  /**
1901
1902
  * Initialize service
1902
1903
  * @param serviceUri : the service uri
1903
- * @param tokenRefreshInterval : the token refresh interval
1904
+ * @param accessRoute : the login route
1905
+ * @param errorRoute : the optional route to navigate in case of 403 error
1904
1906
  */
1905
- initialize(serviceUri = null, tokenRefreshInterval = this.REFRESH_INTERVAL) {
1907
+ initialize(serviceUri, accessRoute = "/login", errorRoute = null) {
1906
1908
  // Create unique client id
1907
1909
  if (!localStorage.getItem('clipper_client_id')) {
1908
1910
  localStorage.setItem('clipper_client_id', SystemUtils.generateUUID());
1909
1911
  }
1910
1912
  // Initialize
1911
1913
  this._serviceUri = serviceUri;
1912
- this.tokenRefreshInterval = tokenRefreshInterval;
1914
+ this._accessRoute = accessRoute;
1915
+ this._errorRoute = errorRoute;
1913
1916
  // React to message broadcasting
1914
1917
  if (!this.broadcastServiceSubscription) {
1915
1918
  this.broadcastServiceSubscription = this.broadcastService.getMessage().subscribe(message => {
@@ -1947,49 +1950,16 @@ class ClipperService {
1947
1950
  if (!this.loggedIn() && this.getToken()) {
1948
1951
  // Auto login
1949
1952
  this.loggedIn.set(true);
1950
- // Start refresh timer
1951
- this.enableTokenRefresh();
1952
- }
1953
- }
1954
- /**
1955
- * Set JWT token
1956
- * @param token : token
1957
- */
1958
- setToken(token) {
1959
- //console.log(new Date().toString() + " - token:" + token.substring(token.length - 15));
1960
- sessionStorage.setItem('clipper_jwt', token);
1961
- if (token) {
1962
- this.enableTokenRefresh();
1963
1953
  }
1964
1954
  }
1965
1955
  /**
1966
1956
  * Set JWT tokens
1967
- * @param valur : token
1957
+ * @param value : the login result
1968
1958
  */
1969
- setToken2(value) {
1959
+ setToken(value) {
1970
1960
  sessionStorage.setItem('clipper_jwt', value.token);
1971
1961
  sessionStorage.setItem('clipper_jwt_refresh', value.refreshToken);
1972
1962
  }
1973
- /**
1974
- * Enable JWT token auto refresh
1975
- */
1976
- enableTokenRefresh() {
1977
- if (!this.tokenRefreshTimerSubscription) {
1978
- this.tokenRefreshTimer =
1979
- timer(this.tokenRefreshInterval, this.tokenRefreshInterval)
1980
- .pipe(switchMap(() => {
1981
- if (this.refreshing || !this.loggedIn())
1982
- return EMPTY;
1983
- this.refreshing = true;
1984
- this.refresh().subscribe({
1985
- error: () => { this.refreshing = false; },
1986
- complete: () => { this.refreshing = false; }
1987
- });
1988
- return EMPTY;
1989
- }), shareReplay(1));
1990
- this.tokenRefreshTimerSubscription = this.tokenRefreshTimer.subscribe();
1991
- }
1992
- }
1993
1963
  /**
1994
1964
  * Return current JWT token
1995
1965
  * @param refresh: true to get the refresh token. Default is false.
@@ -2011,60 +1981,6 @@ class ClipperService {
2011
1981
  * @returns: the login result
2012
1982
  */
2013
1983
  login(email = null, password = null, remember = false, oauth = null, oauthAccessToken = null) {
2014
- this.clear();
2015
- this.loggingIn.set(true);
2016
- return this.httpClient
2017
- .post(this._serviceUri + '/login', {
2018
- user: oauth ? null : email,
2019
- password: oauth ? null : password,
2020
- clientId: localStorage.getItem("clipper_client_id"),
2021
- OAUTH: oauth
2022
- }, {
2023
- headers: !oauth
2024
- ? new HttpHeaders()
2025
- : new HttpHeaders()
2026
- .set("Authorization", oauthAccessToken)
2027
- })
2028
- .pipe(catchError(err => {
2029
- this.loggingIn.set(false);
2030
- localStorage.removeItem('clipper_login');
2031
- return throwError(() => err);
2032
- }), map(r => {
2033
- this.loggingIn.set(false);
2034
- if (r.success) {
2035
- // Store access token
2036
- this.setToken(r.value.token);
2037
- const loginInfo = {
2038
- context: r.value.context,
2039
- userSettings: r.value.settings,
2040
- OAUTH: oauth
2041
- };
2042
- if (!oauth) {
2043
- loginInfo.userCredentials =
2044
- SystemUtils.cipher(JSON.stringify({
2045
- email: email,
2046
- password: password,
2047
- remember: remember,
2048
- }), loginInfo.context.userId.toString());
2049
- }
2050
- // Update info
2051
- localStorage.setItem('clipper_login', JSON.stringify(loginInfo));
2052
- this._loginInfo = loginInfo;
2053
- this.loggedIn.set(true);
2054
- }
2055
- return r;
2056
- }));
2057
- }
2058
- /**
2059
- * Perform login
2060
- * @param email: the optioanl email if using OAuth2
2061
- * @parma password: the optional password if using OAuth2
2062
- * @param remember: remember credentials
2063
- * @param oauth: the optional open authentication supported
2064
- * @param oauthAccessToken: the optional OAuth2 access token
2065
- * @returns: the login result
2066
- */
2067
- login2(email = null, password = null, remember = false, oauth = null, oauthAccessToken = null) {
2068
1984
  this.clear();
2069
1985
  this.loggingIn.set(true);
2070
1986
  return this.httpClient
@@ -2087,7 +2003,7 @@ class ClipperService {
2087
2003
  this.loggingIn.set(false);
2088
2004
  if (r.success) {
2089
2005
  // Store access token
2090
- this.setToken2(r.value);
2006
+ this.setToken(r.value);
2091
2007
  const loginInfo = {
2092
2008
  context: r.value.context,
2093
2009
  userSettings: r.value.settings,
@@ -2125,12 +2041,6 @@ class ClipperService {
2125
2041
  * Reset login refresh timer and login state
2126
2042
  */
2127
2043
  reset() {
2128
- // Clear subscriptions
2129
- if (this.tokenRefreshTimerSubscription) {
2130
- this.tokenRefreshTimerSubscription.unsubscribe();
2131
- this.tokenRefreshTimerSubscription = null;
2132
- }
2133
- this.tokenRefreshTimer = null;
2134
2044
  // Clear login info
2135
2045
  this._loginInfo = null;
2136
2046
  // Logged out
@@ -2148,22 +2058,13 @@ class ClipperService {
2148
2058
  // Reset login
2149
2059
  this.reset();
2150
2060
  }
2151
- /**
2152
- * Perform token refresh
2153
- */
2154
- refresh() {
2155
- return this.httpClient.post(this._serviceUri + '/refresh', {}).pipe(map(r => {
2156
- // Update token
2157
- this.setToken(r.value.token);
2158
- }));
2159
- }
2160
2061
  /**
2161
2062
  * Perform token refresh
2162
2063
  */
2163
- refresh2() {
2064
+ refresh() {
2164
2065
  return this.httpClient.get(this._serviceUri + '/refresh2/?token=' + this.getToken(true)).pipe(map(r => {
2165
2066
  // Update token
2166
- this.setToken2(r.value);
2067
+ this.setToken(r.value);
2167
2068
  }));
2168
2069
  }
2169
2070
  /**
@@ -2189,7 +2090,10 @@ class ClipperService {
2189
2090
  * Get facets for a query
2190
2091
  */
2191
2092
  queryFacets(params) {
2192
- return this.httpClient.post(this._serviceUri + '/documents/facets', params);
2093
+ return this.httpClient.post(params.model === ClipperModel.Coordinamento ||
2094
+ (params.models?.length === 1 && params.models[0] === ClipperModel.Coordinamento)
2095
+ ? this._serviceUri + '/documents/changes/facets'
2096
+ : this._serviceUri + '/documents/facets', params);
2193
2097
  }
2194
2098
  /**
2195
2099
  * Update document state
@@ -2501,49 +2405,49 @@ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "18.1.3", ngImpor
2501
2405
  args: [{
2502
2406
  providedIn: 'root',
2503
2407
  }]
2504
- }], ctorParameters: () => [] });
2408
+ }] });
2505
2409
 
2506
2410
  class ClipperAuthInterceptor {
2507
2411
  constructor() {
2508
2412
  this.clipperService = inject(ClipperService);
2509
2413
  this.dialogService = inject(DialogService);
2414
+ this.router = inject(Router);
2510
2415
  }
2511
2416
  intercept(request, next) {
2512
2417
  if (request.url.startsWith(this.clipperService.serviceUri)) {
2513
2418
  request = request.clone({ withCredentials: true });
2514
2419
  return next.handle(this.addTokenToRequest(request))
2515
- .pipe(catchError$1((err) => {
2516
- // Get the message
2517
- let message = err.error?.message || err.message || "Impossibile eseguire l'operazione richiesta.";
2518
- let invalidSession = err.status === 401;
2519
- switch (err.status) {
2520
- case 0:
2521
- case 500:
2522
- case 502:
2523
- case 503:
2524
- case 504:
2525
- message = null; // No messages
2526
- break;
2527
- case 403:
2528
- message = "<p>Non hai i permessi necessari per eseguire l'operazione richiesta.</p>";
2529
- break;
2530
- default:
2531
- message = '<p>' + message.replaceAll('\r\n', '</p><p>') + '</p>';
2532
- break;
2420
+ .pipe(catchError$1(error => {
2421
+ if (error instanceof HttpErrorResponse &&
2422
+ !request.url.includes(this.clipperService.accessRoute) &&
2423
+ error.status === 401) {
2424
+ return this.handle401Error(request, next);
2533
2425
  }
2534
- // Display message
2535
- if (message) {
2536
- setTimeout(() => {
2537
- this.dialogService.error(message, null, 'Errore in Clipper', 'Ok', 500, invalidSession ? 5000 : null).afterClosed().subscribe(() => {
2538
- if (invalidSession) {
2539
- if (this.clipperService.loggedIn()) {
2540
- this.clipperService.reset();
2541
- }
2542
- }
2543
- });
2544
- }, 250);
2426
+ // Show a message
2427
+ this.dialogService.clearBusy();
2428
+ this.dialogService.error('<p>' + (error.error?.message ?? error.message ?? "Impossibile eseguire l'operazione richiesta.").replaceAll('\r\n', '</p><p>') + '</p>', null, 'Errore in Clipper');
2429
+ return throwError(() => error);
2430
+ }));
2431
+ }
2432
+ return next.handle(request);
2433
+ }
2434
+ /**
2435
+ * Handle 401 error
2436
+ * @param request : the request
2437
+ * @param next : the http handler
2438
+ */
2439
+ handle401Error(request, next) {
2440
+ if (this.clipperService.loggedIn()) {
2441
+ return this.clipperService.refresh().pipe(switchMap(() => {
2442
+ return next.handle(this.addTokenToRequest(request));
2443
+ }), catchError$1(error => {
2444
+ if (error instanceof HttpErrorResponse && error.status === 403) {
2445
+ this.clipperService.clear();
2446
+ if (this.clipperService.errorRoute) {
2447
+ this.router.navigateByUrl(this.clipperService.errorRoute);
2448
+ }
2545
2449
  }
2546
- return throwError(() => err);
2450
+ return throwError(() => error);
2547
2451
  }));
2548
2452
  }
2549
2453
  return next.handle(request);