@sambath999/localize-token 19.0.2 → 19.0.4
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.
- package/fesm2022/sambath999-localize-token.mjs +709 -289
- package/fesm2022/sambath999-localize-token.mjs.map +1 -1
- package/localize-api-token/localize-api-token.module.d.ts +9 -0
- package/localize-api-token/localize-api-token.service.d.ts +15 -0
- package/localize-logindlg/localize-logindlg.component.d.ts +7 -2
- package/localize-logindlg/localize-logindlg.module.d.ts +1 -4
- package/localize-logindlg/localize-logindlg.service.d.ts +44 -0
- package/localize-token/helpers/interfaces.d.ts +92 -0
- package/localize-token/helpers/localize.api.assets.d.ts +5 -0
- package/localize-token/helpers/loccalize.api.helper.d.ts +33 -0
- package/localize-token/localize.api.service.d.ts +29 -45
- package/localize-token/localize.token.d.ts +8 -10
- package/localize-token/localize.token.service.d.ts +12 -5
- package/package.json +1 -1
- package/public-api.d.ts +13 -2
- package/localize-logindlg/public-api.d.ts +0 -3
- package/localize-token/public-api.d.ts +0 -5
|
@@ -1,28 +1,25 @@
|
|
|
1
1
|
import * as i0 from '@angular/core';
|
|
2
|
-
import { Injectable,
|
|
3
|
-
import
|
|
4
|
-
import * as jwt_decode from 'jwt-decode';
|
|
5
|
-
import * as i1 from '@angular/common/http';
|
|
6
|
-
import { HttpHeaders } from '@angular/common/http';
|
|
7
|
-
import * as i1$1 from 'primeng/api';
|
|
2
|
+
import { Injectable, Component, ViewEncapsulation, NgModule, CUSTOM_ELEMENTS_SCHEMA } from '@angular/core';
|
|
3
|
+
import * as i1 from 'primeng/api';
|
|
8
4
|
import { MessageService } from 'primeng/api';
|
|
9
5
|
import * as i2 from 'primeng/dynamicdialog';
|
|
10
|
-
import { DialogService
|
|
11
|
-
import
|
|
6
|
+
import { DialogService } from 'primeng/dynamicdialog';
|
|
7
|
+
import { BehaviorSubject, takeUntil, catchError, throwError, Subject } from 'rxjs';
|
|
8
|
+
import * as jwt_decode from 'jwt-decode';
|
|
9
|
+
import * as i4 from '@angular/common/http';
|
|
10
|
+
import { HttpErrorResponse, HttpHeaders } from '@angular/common/http';
|
|
11
|
+
import * as i5 from '@angular/platform-browser';
|
|
12
|
+
import { BrowserModule } from '@angular/platform-browser';
|
|
13
|
+
import * as i6 from '@angular/common';
|
|
12
14
|
import { CommonModule } from '@angular/common';
|
|
13
|
-
import * as
|
|
15
|
+
import * as i7 from 'primeng/toast';
|
|
14
16
|
import { ToastModule } from 'primeng/toast';
|
|
15
|
-
import * as
|
|
17
|
+
import * as i8 from 'primeng/inputtext';
|
|
16
18
|
import { InputTextModule } from 'primeng/inputtext';
|
|
17
|
-
import * as
|
|
19
|
+
import * as i9 from '@angular/forms';
|
|
18
20
|
import { FormsModule } from '@angular/forms';
|
|
19
|
-
import * as
|
|
21
|
+
import * as i10 from 'primeng/button';
|
|
20
22
|
import { ButtonModule } from 'primeng/button';
|
|
21
|
-
import * as i10 from 'primeng/inputgroup';
|
|
22
|
-
import { InputGroupModule } from 'primeng/inputgroup';
|
|
23
|
-
import * as i11 from 'primeng/inputgroupaddon';
|
|
24
|
-
import { InputGroupAddonModule } from 'primeng/inputgroupaddon';
|
|
25
|
-
import { BrowserModule } from '@angular/platform-browser';
|
|
26
23
|
|
|
27
24
|
/**
|
|
28
25
|
* Assembly of @package ng2-cookies @see https://www.npmjs.com/package/ng2-cookies
|
|
@@ -132,18 +129,6 @@ class LocalizeTokenStorage {
|
|
|
132
129
|
}
|
|
133
130
|
|
|
134
131
|
class LocalizeToken {
|
|
135
|
-
static init(config) {
|
|
136
|
-
LocalizeToken.config = { ...LocalizeToken.config, ...config };
|
|
137
|
-
}
|
|
138
|
-
static config = {
|
|
139
|
-
mainDomain: extractMainDomain(),
|
|
140
|
-
authTokenName: 'auth-token',
|
|
141
|
-
tenantTokenName: '_lze_tnt_01',
|
|
142
|
-
refreshTokenName: '_lze_rftkp_',
|
|
143
|
-
needTenant: false,
|
|
144
|
-
isProduction: false,
|
|
145
|
-
revokeTokenUrl: ''
|
|
146
|
-
};
|
|
147
132
|
static storage = new LocalizeTokenStorage();
|
|
148
133
|
static httpHeaders = {
|
|
149
134
|
AUTHORIZATION: 'Authorization',
|
|
@@ -187,38 +172,52 @@ function extractMainDomain(subdomain) {
|
|
|
187
172
|
}
|
|
188
173
|
|
|
189
174
|
class LocalizeTokenService {
|
|
175
|
+
configSubject = new BehaviorSubject({});
|
|
190
176
|
isRevokingTokenSubject = new BehaviorSubject(false);
|
|
191
|
-
|
|
192
|
-
|
|
193
|
-
|
|
194
|
-
|
|
195
|
-
}
|
|
196
|
-
|
|
177
|
+
defaultConfig = {
|
|
178
|
+
mainDomain: extractMainDomain(),
|
|
179
|
+
authToken: {
|
|
180
|
+
name: 'auth-token',
|
|
181
|
+
},
|
|
182
|
+
refreshToken: {
|
|
183
|
+
name: 'refresh-token',
|
|
184
|
+
requestUrl: '/api/token/revoke'
|
|
185
|
+
},
|
|
186
|
+
};
|
|
187
|
+
get config() {
|
|
188
|
+
this.throwIfNotInitialized();
|
|
189
|
+
return this.configSubject.value;
|
|
190
|
+
}
|
|
191
|
+
isInitialized = false;
|
|
192
|
+
init(config) {
|
|
193
|
+
console.log('LocalizeTokenService is initialized.');
|
|
194
|
+
this.configSubject.next({ ...this.defaultConfig, ...config });
|
|
195
|
+
this.isInitialized = true;
|
|
196
|
+
}
|
|
197
|
+
ngOnDestroy() {
|
|
198
|
+
// this.configSubject.complete();
|
|
199
|
+
// this.isRevokingTokenSubject.complete();
|
|
197
200
|
}
|
|
198
201
|
get authToken() { return this.storageGet(); }
|
|
199
202
|
set authToken(value) {
|
|
200
203
|
value
|
|
201
204
|
? this.storageSet(value)
|
|
202
|
-
: LocalizeToken.storage.delete(this.config.
|
|
205
|
+
: LocalizeToken.storage.delete(this.config.authToken?.name);
|
|
203
206
|
}
|
|
204
|
-
get
|
|
207
|
+
get tenantToken() { return LocalizeToken.storage.get(this.config.tenantToken?.name || ''); }
|
|
208
|
+
get refreshToken() { return LocalizeToken.storage.get(this.config.refreshToken?.name || ''); }
|
|
205
209
|
get accessToken() { return this.authToken?.token; }
|
|
206
210
|
set accessToken(value) {
|
|
207
|
-
|
|
208
|
-
this.authToken = { token: value, revoke: false };
|
|
209
|
-
}
|
|
211
|
+
value && (this.authToken = { token: value, revoke: false });
|
|
210
212
|
}
|
|
211
213
|
get isRevokingToken() { return this.isRevokingTokenSubject.value; /* this.authToken?.revoke ?? false */ }
|
|
212
214
|
set isRevokingToken(value) {
|
|
213
215
|
this.isRevokingTokenSubject.next(value);
|
|
214
|
-
|
|
215
|
-
this.authToken = { ...this.authToken, revoke: value };
|
|
216
|
-
}
|
|
216
|
+
this.authToken && (this.authToken = { ...this.authToken, revoke: value });
|
|
217
217
|
}
|
|
218
|
-
get tenantToken() { return LocalizeToken.storage.get(this.config.tenantTokenName); }
|
|
219
218
|
storageGet() {
|
|
220
219
|
try {
|
|
221
|
-
const encoded = LocalizeToken.storage.get(this.config.
|
|
220
|
+
const encoded = LocalizeToken.storage.get(this.config.authToken?.name || '');
|
|
222
221
|
const decoded = atob(encoded || '');
|
|
223
222
|
return JSON.parse(decoded);
|
|
224
223
|
}
|
|
@@ -228,17 +227,21 @@ class LocalizeTokenService {
|
|
|
228
227
|
}
|
|
229
228
|
storageSet(value) {
|
|
230
229
|
const base64 = btoa(JSON.stringify(value));
|
|
231
|
-
LocalizeToken.storage.set(this.config.
|
|
230
|
+
LocalizeToken.storage.set(this.config.authToken?.name || '', base64);
|
|
232
231
|
}
|
|
233
232
|
tokensValid() {
|
|
234
|
-
return this.refreshToken?.length
|
|
233
|
+
return !!this.refreshToken?.length
|
|
234
|
+
&& (!this.config.tenantToken || !!this.tenantToken?.length);
|
|
235
235
|
}
|
|
236
236
|
decodeToken = (token) => jwt_decode.jwtDecode(token);
|
|
237
237
|
get decodeRefreshToken() {
|
|
238
|
-
const token =
|
|
239
|
-
|
|
240
|
-
|
|
241
|
-
|
|
238
|
+
const token = this.refreshToken;
|
|
239
|
+
return !token ? null : this.decodeToken(token);
|
|
240
|
+
}
|
|
241
|
+
throwIfNotInitialized() {
|
|
242
|
+
if (!this.isInitialized) {
|
|
243
|
+
throw new Error('LocalizeTokenService is not initialized. Call init() method before using it.');
|
|
244
|
+
}
|
|
242
245
|
}
|
|
243
246
|
static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "19.0.5", ngImport: i0, type: LocalizeTokenService, deps: [], target: i0.ɵɵFactoryTarget.Injectable });
|
|
244
247
|
static ɵprov = i0.ɵɵngDeclareInjectable({ minVersion: "12.0.0", version: "19.0.5", ngImport: i0, type: LocalizeTokenService, providedIn: 'root' });
|
|
@@ -246,161 +249,6 @@ class LocalizeTokenService {
|
|
|
246
249
|
i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "19.0.5", ngImport: i0, type: LocalizeTokenService, decorators: [{
|
|
247
250
|
type: Injectable,
|
|
248
251
|
args: [{ providedIn: 'root' }]
|
|
249
|
-
}], ctorParameters: () => [] });
|
|
250
|
-
|
|
251
|
-
/**
|
|
252
|
-
* Http method options
|
|
253
|
-
*/
|
|
254
|
-
var EMethod;
|
|
255
|
-
(function (EMethod) {
|
|
256
|
-
EMethod[EMethod["POST"] = 1] = "POST";
|
|
257
|
-
EMethod[EMethod["GET"] = 2] = "GET";
|
|
258
|
-
EMethod[EMethod["PUT"] = 3] = "PUT";
|
|
259
|
-
EMethod[EMethod["DELETE"] = 4] = "DELETE";
|
|
260
|
-
EMethod[EMethod["PATCH"] = 5] = "PATCH";
|
|
261
|
-
})(EMethod || (EMethod = {}));
|
|
262
|
-
class LocalizeApiService {
|
|
263
|
-
httpClient;
|
|
264
|
-
localizeTokenService;
|
|
265
|
-
isRequestingSubject = new BehaviorSubject(false);
|
|
266
|
-
isResolvedStartupSubject = new BehaviorSubject(false);
|
|
267
|
-
get isRequesting() { return this.isRequestingSubject.value; }
|
|
268
|
-
get isResolvedStartup() { return this.isResolvedStartupSubject.value; }
|
|
269
|
-
apiConfigs = {};
|
|
270
|
-
isInitialized = false;
|
|
271
|
-
constructor(httpClient, localizeTokenService) {
|
|
272
|
-
this.httpClient = httpClient;
|
|
273
|
-
this.localizeTokenService = localizeTokenService;
|
|
274
|
-
}
|
|
275
|
-
/**
|
|
276
|
-
* Initialize the API service.
|
|
277
|
-
* @param apiConfigs - The API configurations.
|
|
278
|
-
*/
|
|
279
|
-
init(apiConfigs) {
|
|
280
|
-
if (this.isInitialized)
|
|
281
|
-
return;
|
|
282
|
-
this.isInitialized = true;
|
|
283
|
-
this.apiConfigs = apiConfigs;
|
|
284
|
-
}
|
|
285
|
-
/**
|
|
286
|
-
* A higher-order function that returns a curried function for making API requests.
|
|
287
|
-
*
|
|
288
|
-
* @param baseUrl - The base URL of the API.
|
|
289
|
-
* @returns A curried function that can be used to make API requests.
|
|
290
|
-
*/
|
|
291
|
-
func = (baseUrl) => (path, method = EMethod.GET, value = null, isFormData = false, headers) => this.base(baseUrl, path, method, value, isFormData, headers);
|
|
292
|
-
async base(baseUrl, path, method = EMethod.GET, value = null, isFormData = false, headers) {
|
|
293
|
-
await this.ifPromise(this.apiConfigs.onPrepareRequest);
|
|
294
|
-
const url = `${baseUrl.trim().replace(/\/?$/, '/')}${path.trim().replace(/^\//, '')}`;
|
|
295
|
-
const httpMethod = EMethod[method].toLowerCase();
|
|
296
|
-
const request = () => { return { body: value, headers: this.options(isFormData, headers) }; };
|
|
297
|
-
// Wait for previous request to complete
|
|
298
|
-
await this.toWaitForPreviousRequest();
|
|
299
|
-
// Process request
|
|
300
|
-
try {
|
|
301
|
-
return await this.processRequest(httpMethod, url, request());
|
|
302
|
-
}
|
|
303
|
-
// Handle unauthorized error if any
|
|
304
|
-
catch (error) {
|
|
305
|
-
if (error.status !== 401) {
|
|
306
|
-
throw error;
|
|
307
|
-
}
|
|
308
|
-
return await this.onUnauthorizedError(httpMethod, url, request);
|
|
309
|
-
}
|
|
310
|
-
}
|
|
311
|
-
async onUnauthorizedError(httpMethod, url, request) {
|
|
312
|
-
await this.revokeToken();
|
|
313
|
-
if (!this.isResolvedStartup) {
|
|
314
|
-
return await this.processRequest(httpMethod, url, request());
|
|
315
|
-
}
|
|
316
|
-
}
|
|
317
|
-
async toWaitForPreviousRequest() {
|
|
318
|
-
if (this.localizeTokenService.isRevokingToken) {
|
|
319
|
-
await waitUntil(() => !this.localizeTokenService.isRevokingToken);
|
|
320
|
-
}
|
|
321
|
-
// to wait for each request in 50ms, even if the request is not completed
|
|
322
|
-
if (this.apiConfigs.waitEachRequest?.milliseconds) {
|
|
323
|
-
await waitFor(this.apiConfigs.waitEachRequest.milliseconds, this.isRequesting);
|
|
324
|
-
}
|
|
325
|
-
}
|
|
326
|
-
async processRequest(method, url, options) {
|
|
327
|
-
this.isRequestingSubject.next(true);
|
|
328
|
-
const result = await new Promise((resolve, reject) => this.httpClient.request(method, url, options).subscribe({ next: resolve, error: reject }));
|
|
329
|
-
this.isRequestingSubject.next(false);
|
|
330
|
-
return result;
|
|
331
|
-
}
|
|
332
|
-
async revokeToken() {
|
|
333
|
-
if (this.localizeTokenService.isRevokingToken) {
|
|
334
|
-
await waitUntil(() => !this.localizeTokenService.isRevokingToken);
|
|
335
|
-
return;
|
|
336
|
-
}
|
|
337
|
-
try {
|
|
338
|
-
this.localizeTokenService.isRevokingToken = true;
|
|
339
|
-
const reqUrl = LocalizeToken.config.revokeTokenUrl;
|
|
340
|
-
const reqHeaders = this.options().append(LocalizeToken.httpHeaders.X_REFRESH_TOKEN, `${this.localizeTokenService.refreshToken}`);
|
|
341
|
-
const revokeToken = await new Promise((resolve, reject) => this.httpClient.get(reqUrl, { headers: reqHeaders }).subscribe({ next: resolve, error: reject }));
|
|
342
|
-
if (revokeToken?.status) {
|
|
343
|
-
this.localizeTokenService.accessToken = revokeToken.message;
|
|
344
|
-
}
|
|
345
|
-
else if (!this.localizeTokenService.refreshToken) {
|
|
346
|
-
await this.ifPromise(this.apiConfigs.onAutoLogout);
|
|
347
|
-
}
|
|
348
|
-
else {
|
|
349
|
-
if (this.apiConfigs.onRevokeUnauthorized) {
|
|
350
|
-
await this.ifPromise(this.apiConfigs.onRevokeUnauthorized);
|
|
351
|
-
// await this.revokeToken();
|
|
352
|
-
}
|
|
353
|
-
}
|
|
354
|
-
}
|
|
355
|
-
finally {
|
|
356
|
-
this.localizeTokenService.isRevokingToken = false;
|
|
357
|
-
}
|
|
358
|
-
}
|
|
359
|
-
/** default http request options */
|
|
360
|
-
options(isFormData = false, headers = {}) {
|
|
361
|
-
const defaultHeaders = { [LocalizeToken.httpHeaders.AUTHORIZATION]: `Bearer ${this.localizeTokenService.accessToken}`, };
|
|
362
|
-
if (LocalizeToken.config.needTenant) {
|
|
363
|
-
defaultHeaders[LocalizeToken.httpHeaders.X_TENANT] = `${this.localizeTokenService.tenantToken}`;
|
|
364
|
-
}
|
|
365
|
-
if (!isFormData) {
|
|
366
|
-
defaultHeaders[LocalizeToken.httpHeaders.CONTENT_TYPE] = 'application/json';
|
|
367
|
-
}
|
|
368
|
-
const filteredHeaders = Object.keys(defaultHeaders).filter(key => !Object.keys(headers).includes(key))
|
|
369
|
-
.reduce((acc, key) => ({ ...acc, [key]: defaultHeaders[key] }), {});
|
|
370
|
-
const mergedHeaders = { ...filteredHeaders, ...headers };
|
|
371
|
-
return new HttpHeaders(mergedHeaders);
|
|
372
|
-
}
|
|
373
|
-
async ifPromise(fn) {
|
|
374
|
-
if (!fn)
|
|
375
|
-
return;
|
|
376
|
-
return fn instanceof Promise ? await fn() : fn();
|
|
377
|
-
}
|
|
378
|
-
static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "19.0.5", ngImport: i0, type: LocalizeApiService, deps: [{ token: i1.HttpClient }, { token: LocalizeTokenService }], target: i0.ɵɵFactoryTarget.Injectable });
|
|
379
|
-
static ɵprov = i0.ɵɵngDeclareInjectable({ minVersion: "12.0.0", version: "19.0.5", ngImport: i0, type: LocalizeApiService, providedIn: 'root' });
|
|
380
|
-
} //class
|
|
381
|
-
i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "19.0.5", ngImport: i0, type: LocalizeApiService, decorators: [{
|
|
382
|
-
type: Injectable,
|
|
383
|
-
args: [{
|
|
384
|
-
providedIn: 'root'
|
|
385
|
-
}]
|
|
386
|
-
}], ctorParameters: () => [{ type: i1.HttpClient }, { type: LocalizeTokenService }] });
|
|
387
|
-
|
|
388
|
-
class LocalizeTokenModule {
|
|
389
|
-
static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "19.0.5", ngImport: i0, type: LocalizeTokenModule, deps: [], target: i0.ɵɵFactoryTarget.NgModule });
|
|
390
|
-
static ɵmod = i0.ɵɵngDeclareNgModule({ minVersion: "14.0.0", version: "19.0.5", ngImport: i0, type: LocalizeTokenModule });
|
|
391
|
-
static ɵinj = i0.ɵɵngDeclareInjector({ minVersion: "12.0.0", version: "19.0.5", ngImport: i0, type: LocalizeTokenModule, providers: [
|
|
392
|
-
LocalizeTokenService,
|
|
393
|
-
LocalizeApiService
|
|
394
|
-
] });
|
|
395
|
-
}
|
|
396
|
-
i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "19.0.5", ngImport: i0, type: LocalizeTokenModule, decorators: [{
|
|
397
|
-
type: NgModule,
|
|
398
|
-
args: [{
|
|
399
|
-
providers: [
|
|
400
|
-
LocalizeTokenService,
|
|
401
|
-
LocalizeApiService
|
|
402
|
-
],
|
|
403
|
-
}]
|
|
404
252
|
}] });
|
|
405
253
|
|
|
406
254
|
class LocalizeLogindlgComponent {
|
|
@@ -410,24 +258,28 @@ class LocalizeLogindlgComponent {
|
|
|
410
258
|
dlgConfig;
|
|
411
259
|
tokenService;
|
|
412
260
|
httpClient;
|
|
261
|
+
sanitizer;
|
|
413
262
|
messageKey = "$login-dlg";
|
|
414
263
|
password;
|
|
415
264
|
decodeToken;
|
|
416
265
|
loading = false;
|
|
417
266
|
success = false;
|
|
418
|
-
config
|
|
267
|
+
get config() { return this.tokenService.config; }
|
|
419
268
|
loginConfig;
|
|
420
269
|
logout;
|
|
421
270
|
loginUrl;
|
|
422
|
-
|
|
271
|
+
properties;
|
|
272
|
+
constructor(messageService, cdt, dlgRef, dlgConfig, tokenService, httpClient, sanitizer) {
|
|
423
273
|
this.messageService = messageService;
|
|
424
274
|
this.cdt = cdt;
|
|
425
275
|
this.dlgRef = dlgRef;
|
|
426
276
|
this.dlgConfig = dlgConfig;
|
|
427
277
|
this.tokenService = tokenService;
|
|
428
278
|
this.httpClient = httpClient;
|
|
279
|
+
this.sanitizer = sanitizer;
|
|
429
280
|
this.decodeToken = this.tokenService.decodeRefreshToken;
|
|
430
281
|
this.loginConfig = this.dlgConfig.data.loginConfig;
|
|
282
|
+
this.properties = this.loginConfig.properties;
|
|
431
283
|
}
|
|
432
284
|
ngOnInit() {
|
|
433
285
|
this.dlgConfig.closable = false;
|
|
@@ -443,29 +295,34 @@ class LocalizeLogindlgComponent {
|
|
|
443
295
|
}
|
|
444
296
|
async clickLogin() {
|
|
445
297
|
if (!this.isValidPassword) {
|
|
446
|
-
this.showMessage("error", "Password is required and must be at least 6 characters");
|
|
447
|
-
return;
|
|
298
|
+
return this.showMessage("error", "Password is required and must be at least 6 characters");
|
|
448
299
|
}
|
|
449
300
|
this.loading = true;
|
|
450
301
|
const loginRes = await this.login();
|
|
451
302
|
if (!loginRes?.status) {
|
|
452
|
-
this.showMessage("error", loginRes.message ?? "An error occurred");
|
|
453
|
-
return;
|
|
303
|
+
return this.showMessage("error", loginRes.message ?? "An error occurred");
|
|
454
304
|
}
|
|
455
305
|
this.tokenService.accessToken = loginRes.tokens.accessToken;
|
|
456
|
-
const cookieOptions = { expires: this.loginConfig.expire ??
|
|
457
|
-
LocalizeToken.storage.set(this.config.
|
|
306
|
+
const cookieOptions = { expires: this.loginConfig.expire ?? 365 };
|
|
307
|
+
LocalizeToken.storage.set(this.config.refreshToken?.name || '', loginRes.tokens.refreshToken, cookieOptions);
|
|
458
308
|
this.success = true;
|
|
459
|
-
setTimeout(() =>
|
|
309
|
+
setTimeout(() => {
|
|
310
|
+
this.dlgConfig.dismissableMask = true;
|
|
311
|
+
this.dlgConfig.modal = false;
|
|
312
|
+
this.dlgRef.close(true);
|
|
313
|
+
}, 2000);
|
|
460
314
|
}
|
|
461
315
|
async login() {
|
|
462
|
-
if (!this.loginUrl
|
|
316
|
+
if (!this.loginUrl?.trim().length) {
|
|
463
317
|
this.showMessage("error", "Login url is required");
|
|
464
318
|
throw new Error("Login url is required");
|
|
465
319
|
}
|
|
466
320
|
try {
|
|
467
|
-
|
|
468
|
-
.
|
|
321
|
+
if (this.loginConfig.loginFunction) {
|
|
322
|
+
console.log("Using custom login function");
|
|
323
|
+
return await this.loginConfig.loginFunction(this.decodeToken?.email ?? '', this.password.trim(), this.getHeaders());
|
|
324
|
+
}
|
|
325
|
+
return await new Promise((resolve, reject) => this.httpClient.post(this.loginUrl, { password: this.password.trim() }, { headers: this.getHeaders() }).subscribe({ next: resolve, error: reject }));
|
|
469
326
|
}
|
|
470
327
|
catch (e) {
|
|
471
328
|
this.showMessage("error", e.message);
|
|
@@ -474,26 +331,31 @@ class LocalizeLogindlgComponent {
|
|
|
474
331
|
}
|
|
475
332
|
getHeaders() {
|
|
476
333
|
return {
|
|
477
|
-
[LocalizeToken.httpHeaders.X_REFRESH_TOKEN]:
|
|
478
|
-
[LocalizeToken.httpHeaders.X_TENANT]:
|
|
334
|
+
[LocalizeToken.httpHeaders.X_REFRESH_TOKEN]: this.tokenService.refreshToken ?? "",
|
|
335
|
+
[LocalizeToken.httpHeaders.X_TENANT]: this.tokenService.tenantToken ?? "",
|
|
479
336
|
};
|
|
480
337
|
}
|
|
481
338
|
get isValidPassword() {
|
|
482
339
|
this.loading = false;
|
|
483
|
-
return this.
|
|
340
|
+
return this.properties.passwordValidator
|
|
341
|
+
? this.properties.passwordValidator(this.password)
|
|
342
|
+
: this.password && this.password.trim().length >= 6 && this.password.trim().length <= 50;
|
|
484
343
|
}
|
|
485
344
|
clickLogout = () => this.logout?.();
|
|
486
345
|
showMessage(severity, summary) {
|
|
487
346
|
this.messageService.add({ key: this.messageKey, severity, summary });
|
|
488
347
|
this.loading = false;
|
|
489
348
|
}
|
|
490
|
-
|
|
349
|
+
get sanitizedTitle() {
|
|
350
|
+
return this.sanitizer.bypassSecurityTrustHtml(this.properties.title ?? '');
|
|
351
|
+
}
|
|
352
|
+
static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "19.0.5", ngImport: i0, type: LocalizeLogindlgComponent, deps: [{ token: i1.MessageService }, { token: i0.ChangeDetectorRef }, { token: i2.DynamicDialogRef }, { token: i2.DynamicDialogConfig }, { token: LocalizeTokenService }, { token: i4.HttpClient }, { token: i5.DomSanitizer }], target: i0.ɵɵFactoryTarget.Component });
|
|
491
353
|
static ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "14.0.0", version: "19.0.5", type: LocalizeLogindlgComponent, isStandalone: false, selector: "app-localize-logindlg", providers: [MessageService], ngImport: i0, template: `<p-toast key="$login-dlg" position="top-center"></p-toast>
|
|
492
354
|
<div id="login-dlg-wrap">
|
|
493
355
|
<div id="login-dlg-header">
|
|
494
|
-
<div id="login-logo" class="p-mb-2"></div>
|
|
495
|
-
<h3 *ngIf="!success"
|
|
496
|
-
<h3 *ngIf="success" style="color:green !important;">
|
|
356
|
+
<div id="login-logo" class="p-mb-2" style="background: url('{{properties.logoImage}}') no-repeat"></div>
|
|
357
|
+
<h3 *ngIf="!success" [innerHTML]="sanitizedTitle"></h3>
|
|
358
|
+
<h3 *ngIf="success" style="color:green !important;">{{properties.loginSuccessMessage}}</h3>
|
|
497
359
|
</div>
|
|
498
360
|
<div id="login-dlg-content">
|
|
499
361
|
<ng-container *ngIf="!success">
|
|
@@ -501,35 +363,33 @@ class LocalizeLogindlgComponent {
|
|
|
501
363
|
<div class="login-dlg-loader"></div>
|
|
502
364
|
</div>
|
|
503
365
|
<div class="login-dlg-elm">
|
|
504
|
-
<p-inputgroup>
|
|
505
|
-
<
|
|
506
|
-
<
|
|
507
|
-
|
|
508
|
-
|
|
509
|
-
|
|
510
|
-
<input disabled pInputText type="text" placeholder="Username" [value]="decodeToken?.email" />
|
|
511
|
-
</p-inputgroup>
|
|
366
|
+
<div class="p-inputgroup">
|
|
367
|
+
<span class="p-inputgroup-addon">
|
|
368
|
+
<i class="material-icons-round">person</i>
|
|
369
|
+
</span>
|
|
370
|
+
<input disabled pInputText type="text" placeholder="{{properties.username?.placeHolder}}" [value]="decodeToken?.email" />
|
|
371
|
+
</div>
|
|
512
372
|
</div>
|
|
513
373
|
|
|
514
374
|
<div class="login-dlg-elm">
|
|
515
|
-
<p-inputgroup>
|
|
516
|
-
<p-inputgroup-addon>
|
|
517
|
-
<
|
|
518
|
-
|
|
519
|
-
|
|
520
|
-
|
|
521
|
-
<input [disabled]="loading" (keydown.enter)="clickLogin()" pInputText type="password" placeholder="Password" [(ngModel)]="password"
|
|
375
|
+
<div class="p-inputgroup">
|
|
376
|
+
<span class="p-inputgroup-addon">
|
|
377
|
+
<i class="material-icons-round">lock</i>
|
|
378
|
+
</span>
|
|
379
|
+
<input [disabled]="loading" (keydown.enter)="clickLogin()" pInputText type="password"
|
|
380
|
+
placeholder="{{properties.password?.placeHolder}}" [(ngModel)]="password"
|
|
522
381
|
autofocus />
|
|
523
|
-
</
|
|
382
|
+
</div>
|
|
524
383
|
</div>
|
|
525
384
|
<div class="login-dlg-elm">
|
|
526
|
-
<button style="width: 100%;" pButton type="button" label="
|
|
385
|
+
<button style="width: 100%;" pButton type="button" label="{{properties.loginButton?.placeHolder}}" (click)="clickLogin()"
|
|
527
386
|
[disabled]="!password || loading"></button>
|
|
528
387
|
</div>
|
|
529
388
|
|
|
530
|
-
<div class="login-dlg-elm" style="display:flex;align-items: center;user-select: none;">
|
|
531
|
-
<span>
|
|
532
|
-
<button class="p-button-text" pButton type="button" label="
|
|
389
|
+
<div class="login-dlg-elm login-dlg-suggest" style="display:flex;align-items: center;user-select: none;">
|
|
390
|
+
<span>{{properties.logoutButton?.message}}</span>
|
|
391
|
+
<button class="p-button-text" pButton type="button" label="{{properties.logoutButton?.placeHolder}}"
|
|
392
|
+
(click)="clickLogout()"></button>
|
|
533
393
|
</div>
|
|
534
394
|
</ng-container>
|
|
535
395
|
|
|
@@ -549,16 +409,16 @@ class LocalizeLogindlgComponent {
|
|
|
549
409
|
</div>
|
|
550
410
|
</ng-container>
|
|
551
411
|
</div>
|
|
552
|
-
</div>`, isInline: true, styles: ["#login-dlg-wrap{width:100%;max-width:400px;margin:0 auto;padding:30px}.login-dlg-elm{margin-top:1rem}#login-dlg-header{display:flex;flex-direction:column;align-items:center;justify-content:center}#login-dlg-header h3{font-weight:700;font-size:.9rem;color:orange;text-align:center}#login-logo{height:
|
|
412
|
+
</div>`, isInline: true, styles: ["#login-dlg-wrap{width:100%;max-width:400px;margin:0 auto;padding:30px;height:100%}.login-dlg-elm{margin-top:1rem}.login-dlg-elm.login-dlg-suggest{display:flex;align-items:center;-webkit-user-select:none;user-select:none;border-bottom:solid 1px #ddd;border-radius:5px;padding:5px 10px;background:#f9f9f9;box-shadow:1px 5px 10px -12px #000}#login-dlg-header{display:flex;flex-direction:column;align-items:center;justify-content:center}#login-dlg-header h3{font-weight:700;font-size:.9rem;color:orange;text-align:center}#login-logo{height:55px;width:55px;background-size:contain!important}#login-dlg-content .p-inputgroup{height:45px}#login-dlg-content .p-inputgroup .p-inputgroup-addon{height:45px;border-radius:15px 0 0 15px;width:50px}#login-dlg-content *{font-size:.9rem}#login-dlg-content .p-inputgroup .p-inputgroup-addon *{font-size:1rem}#login-dlg-content .p-inputgroup input{height:45px;border-radius:0 15px 15px 0}#login-dlg-content button{height:45px;border-radius:15px}.check-animation-wrap{top:0;left:0;position:absolute;display:flex;flex-direction:column;align-items:center;justify-content:center;width:100%;height:calc(100% - 200px);min-height:400px}.check-main-container{width:100%;height:100vh;display:flex;flex-flow:column;justify-content:center;align-items:center}.check-container{width:6.25rem;height:7.5rem;display:flex;flex-flow:column;align-items:center;justify-content:space-between}.check-container .check-background{width:100%;height:calc(100% - 1.25rem);background:linear-gradient(to bottom right,#5de593,#41d67c);box-shadow:0 0 0 65px #ffffff40 inset,0 0 0 65px #ffffff40 inset;transform:scale(.84);border-radius:50%;animation:animateContainer .75s ease-out forwards .75s;display:flex;align-items:center;justify-content:center;opacity:0}.check-container .check-background svg{width:65%;transform:translateY(.25rem);stroke-dasharray:80;stroke-dashoffset:80;animation:animateCheck .35s forwards 1.25s ease-out;min-width:auto!important}.check-container .check-shadow{bottom:calc(-15% - 5px);left:0;border-radius:50%;background:radial-gradient(closest-side,rgba(73,218,131,1),transparent);animation:animateShadow .75s ease-out forwards .75s}@keyframes animateContainer{0%{opacity:0;transform:scale(0);box-shadow:0 0 0 65px #ffffff40 inset,0 0 0 65px #ffffff40 inset}25%{opacity:1;transform:scale(.9);box-shadow:0 0 0 65px #ffffff40 inset,0 0 0 65px #ffffff40 inset}43.75%{transform:scale(1.15);box-shadow:0 0 0 43.334px #ffffff40 inset,0 0 0 65px #ffffff40 inset}62.5%{transform:scale(1);box-shadow:0 0 #ffffff40 inset,0 0 0 21.667px #ffffff40 inset}81.25%{box-shadow:0 0 #ffffff40 inset,0 0 #ffffff40 inset}to{opacity:1;box-shadow:0 0 #ffffff40 inset,0 0 #ffffff40 inset}}@keyframes animateCheck{0%{stroke-dashoffset:80}to{stroke-dashoffset:0}}@keyframes animateShadow{0%{opacity:0;width:100%;height:15%}25%{opacity:.25}43.75%{width:40%;height:7%;opacity:.35}to{width:85%;height:15%;opacity:.25}}#login-dlg-wrap .loader-wrap{display:flex;justify-content:center;align-items:center;height:100%;width:100%;position:absolute;top:0;left:0;z-index:100;background:#ffffff42;-webkit-backdrop-filter:blur(1px);backdrop-filter:blur(1px)}#login-dlg-wrap .login-dlg-loader{border:15px solid #e7e7e7;border-top:15px solid #52dba1;border-radius:50%;width:100px;height:100px;animation:spinloader 2s linear infinite}#login-dlg-wrap .loader-wrap:before{content:\"\";position:absolute;width:70px;height:70px;transform:translate(-50%,-50%);z-index:1;border:15px solid #e7e7e700;border-top:15px solid #52dba1c9;border-radius:50%;animation:spinloader .75s linear infinite}@keyframes spinloader{0%{transform:rotate(0)}to{transform:rotate(360deg)}}\n"], dependencies: [{ kind: "directive", type: i6.NgIf, selector: "[ngIf]", inputs: ["ngIf", "ngIfThen", "ngIfElse"] }, { kind: "component", type: i7.Toast, selector: "p-toast", inputs: ["key", "autoZIndex", "baseZIndex", "life", "style", "styleClass", "position", "preventOpenDuplicates", "preventDuplicates", "showTransformOptions", "hideTransformOptions", "showTransitionOptions", "hideTransitionOptions", "breakpoints"], outputs: ["onClose"] }, { kind: "directive", type: i8.InputText, selector: "[pInputText]", inputs: ["variant", "fluid", "pSize"] }, { kind: "directive", type: i9.DefaultValueAccessor, selector: "input:not([type=checkbox])[formControlName],textarea[formControlName],input:not([type=checkbox])[formControl],textarea[formControl],input:not([type=checkbox])[ngModel],textarea[ngModel],[ngDefaultControl]" }, { kind: "directive", type: i9.NgControlStatus, selector: "[formControlName],[ngModel],[formControl]" }, { kind: "directive", type: i9.NgModel, selector: "[ngModel]:not([formControlName]):not([formControl])", inputs: ["name", "disabled", "ngModel", "ngModelOptions"], outputs: ["ngModelChange"], exportAs: ["ngModel"] }, { kind: "directive", type: i10.ButtonDirective, selector: "[pButton]", inputs: ["iconPos", "loadingIcon", "loading", "severity", "raised", "rounded", "text", "outlined", "size", "plain", "fluid", "label", "icon", "buttonProps"] }], encapsulation: i0.ViewEncapsulation.None });
|
|
553
413
|
}
|
|
554
414
|
i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "19.0.5", ngImport: i0, type: LocalizeLogindlgComponent, decorators: [{
|
|
555
415
|
type: Component,
|
|
556
416
|
args: [{ standalone: false, template: `<p-toast key="$login-dlg" position="top-center"></p-toast>
|
|
557
417
|
<div id="login-dlg-wrap">
|
|
558
418
|
<div id="login-dlg-header">
|
|
559
|
-
<div id="login-logo" class="p-mb-2"></div>
|
|
560
|
-
<h3 *ngIf="!success"
|
|
561
|
-
<h3 *ngIf="success" style="color:green !important;">
|
|
419
|
+
<div id="login-logo" class="p-mb-2" style="background: url('{{properties.logoImage}}') no-repeat"></div>
|
|
420
|
+
<h3 *ngIf="!success" [innerHTML]="sanitizedTitle"></h3>
|
|
421
|
+
<h3 *ngIf="success" style="color:green !important;">{{properties.loginSuccessMessage}}</h3>
|
|
562
422
|
</div>
|
|
563
423
|
<div id="login-dlg-content">
|
|
564
424
|
<ng-container *ngIf="!success">
|
|
@@ -566,35 +426,33 @@ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "19.0.5", ngImpor
|
|
|
566
426
|
<div class="login-dlg-loader"></div>
|
|
567
427
|
</div>
|
|
568
428
|
<div class="login-dlg-elm">
|
|
569
|
-
<p-inputgroup>
|
|
570
|
-
<
|
|
571
|
-
<
|
|
572
|
-
|
|
573
|
-
|
|
574
|
-
|
|
575
|
-
<input disabled pInputText type="text" placeholder="Username" [value]="decodeToken?.email" />
|
|
576
|
-
</p-inputgroup>
|
|
429
|
+
<div class="p-inputgroup">
|
|
430
|
+
<span class="p-inputgroup-addon">
|
|
431
|
+
<i class="material-icons-round">person</i>
|
|
432
|
+
</span>
|
|
433
|
+
<input disabled pInputText type="text" placeholder="{{properties.username?.placeHolder}}" [value]="decodeToken?.email" />
|
|
434
|
+
</div>
|
|
577
435
|
</div>
|
|
578
436
|
|
|
579
437
|
<div class="login-dlg-elm">
|
|
580
|
-
<p-inputgroup>
|
|
581
|
-
<p-inputgroup-addon>
|
|
582
|
-
<
|
|
583
|
-
|
|
584
|
-
|
|
585
|
-
|
|
586
|
-
<input [disabled]="loading" (keydown.enter)="clickLogin()" pInputText type="password" placeholder="Password" [(ngModel)]="password"
|
|
438
|
+
<div class="p-inputgroup">
|
|
439
|
+
<span class="p-inputgroup-addon">
|
|
440
|
+
<i class="material-icons-round">lock</i>
|
|
441
|
+
</span>
|
|
442
|
+
<input [disabled]="loading" (keydown.enter)="clickLogin()" pInputText type="password"
|
|
443
|
+
placeholder="{{properties.password?.placeHolder}}" [(ngModel)]="password"
|
|
587
444
|
autofocus />
|
|
588
|
-
</
|
|
445
|
+
</div>
|
|
589
446
|
</div>
|
|
590
447
|
<div class="login-dlg-elm">
|
|
591
|
-
<button style="width: 100%;" pButton type="button" label="
|
|
448
|
+
<button style="width: 100%;" pButton type="button" label="{{properties.loginButton?.placeHolder}}" (click)="clickLogin()"
|
|
592
449
|
[disabled]="!password || loading"></button>
|
|
593
450
|
</div>
|
|
594
451
|
|
|
595
|
-
<div class="login-dlg-elm" style="display:flex;align-items: center;user-select: none;">
|
|
596
|
-
<span>
|
|
597
|
-
<button class="p-button-text" pButton type="button" label="
|
|
452
|
+
<div class="login-dlg-elm login-dlg-suggest" style="display:flex;align-items: center;user-select: none;">
|
|
453
|
+
<span>{{properties.logoutButton?.message}}</span>
|
|
454
|
+
<button class="p-button-text" pButton type="button" label="{{properties.logoutButton?.placeHolder}}"
|
|
455
|
+
(click)="clickLogout()"></button>
|
|
598
456
|
</div>
|
|
599
457
|
</ng-container>
|
|
600
458
|
|
|
@@ -614,8 +472,8 @@ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "19.0.5", ngImpor
|
|
|
614
472
|
</div>
|
|
615
473
|
</ng-container>
|
|
616
474
|
</div>
|
|
617
|
-
</div>`, selector: "app-localize-logindlg", providers: [MessageService], encapsulation: ViewEncapsulation.None, styles: ["#login-dlg-wrap{width:100%;max-width:400px;margin:0 auto;padding:30px}.login-dlg-elm{margin-top:1rem}#login-dlg-header{display:flex;flex-direction:column;align-items:center;justify-content:center}#login-dlg-header h3{font-weight:700;font-size:.9rem;color:orange;text-align:center}#login-logo{height:
|
|
618
|
-
}], ctorParameters: () => [{ type: i1
|
|
475
|
+
</div>`, selector: "app-localize-logindlg", providers: [MessageService], encapsulation: ViewEncapsulation.None, styles: ["#login-dlg-wrap{width:100%;max-width:400px;margin:0 auto;padding:30px;height:100%}.login-dlg-elm{margin-top:1rem}.login-dlg-elm.login-dlg-suggest{display:flex;align-items:center;-webkit-user-select:none;user-select:none;border-bottom:solid 1px #ddd;border-radius:5px;padding:5px 10px;background:#f9f9f9;box-shadow:1px 5px 10px -12px #000}#login-dlg-header{display:flex;flex-direction:column;align-items:center;justify-content:center}#login-dlg-header h3{font-weight:700;font-size:.9rem;color:orange;text-align:center}#login-logo{height:55px;width:55px;background-size:contain!important}#login-dlg-content .p-inputgroup{height:45px}#login-dlg-content .p-inputgroup .p-inputgroup-addon{height:45px;border-radius:15px 0 0 15px;width:50px}#login-dlg-content *{font-size:.9rem}#login-dlg-content .p-inputgroup .p-inputgroup-addon *{font-size:1rem}#login-dlg-content .p-inputgroup input{height:45px;border-radius:0 15px 15px 0}#login-dlg-content button{height:45px;border-radius:15px}.check-animation-wrap{top:0;left:0;position:absolute;display:flex;flex-direction:column;align-items:center;justify-content:center;width:100%;height:calc(100% - 200px);min-height:400px}.check-main-container{width:100%;height:100vh;display:flex;flex-flow:column;justify-content:center;align-items:center}.check-container{width:6.25rem;height:7.5rem;display:flex;flex-flow:column;align-items:center;justify-content:space-between}.check-container .check-background{width:100%;height:calc(100% - 1.25rem);background:linear-gradient(to bottom right,#5de593,#41d67c);box-shadow:0 0 0 65px #ffffff40 inset,0 0 0 65px #ffffff40 inset;transform:scale(.84);border-radius:50%;animation:animateContainer .75s ease-out forwards .75s;display:flex;align-items:center;justify-content:center;opacity:0}.check-container .check-background svg{width:65%;transform:translateY(.25rem);stroke-dasharray:80;stroke-dashoffset:80;animation:animateCheck .35s forwards 1.25s ease-out;min-width:auto!important}.check-container .check-shadow{bottom:calc(-15% - 5px);left:0;border-radius:50%;background:radial-gradient(closest-side,rgba(73,218,131,1),transparent);animation:animateShadow .75s ease-out forwards .75s}@keyframes animateContainer{0%{opacity:0;transform:scale(0);box-shadow:0 0 0 65px #ffffff40 inset,0 0 0 65px #ffffff40 inset}25%{opacity:1;transform:scale(.9);box-shadow:0 0 0 65px #ffffff40 inset,0 0 0 65px #ffffff40 inset}43.75%{transform:scale(1.15);box-shadow:0 0 0 43.334px #ffffff40 inset,0 0 0 65px #ffffff40 inset}62.5%{transform:scale(1);box-shadow:0 0 #ffffff40 inset,0 0 0 21.667px #ffffff40 inset}81.25%{box-shadow:0 0 #ffffff40 inset,0 0 #ffffff40 inset}to{opacity:1;box-shadow:0 0 #ffffff40 inset,0 0 #ffffff40 inset}}@keyframes animateCheck{0%{stroke-dashoffset:80}to{stroke-dashoffset:0}}@keyframes animateShadow{0%{opacity:0;width:100%;height:15%}25%{opacity:.25}43.75%{width:40%;height:7%;opacity:.35}to{width:85%;height:15%;opacity:.25}}#login-dlg-wrap .loader-wrap{display:flex;justify-content:center;align-items:center;height:100%;width:100%;position:absolute;top:0;left:0;z-index:100;background:#ffffff42;-webkit-backdrop-filter:blur(1px);backdrop-filter:blur(1px)}#login-dlg-wrap .login-dlg-loader{border:15px solid #e7e7e7;border-top:15px solid #52dba1;border-radius:50%;width:100px;height:100px;animation:spinloader 2s linear infinite}#login-dlg-wrap .loader-wrap:before{content:\"\";position:absolute;width:70px;height:70px;transform:translate(-50%,-50%);z-index:1;border:15px solid #e7e7e700;border-top:15px solid #52dba1c9;border-radius:50%;animation:spinloader .75s linear infinite}@keyframes spinloader{0%{transform:rotate(0)}to{transform:rotate(360deg)}}\n"] }]
|
|
476
|
+
}], ctorParameters: () => [{ type: i1.MessageService }, { type: i0.ChangeDetectorRef }, { type: i2.DynamicDialogRef }, { type: i2.DynamicDialogConfig }, { type: LocalizeTokenService }, { type: i4.HttpClient }, { type: i5.DomSanitizer }] });
|
|
619
477
|
|
|
620
478
|
class LocalizeLogindlgService {
|
|
621
479
|
injector;
|
|
@@ -623,12 +481,9 @@ class LocalizeLogindlgService {
|
|
|
623
481
|
this.injector = injector;
|
|
624
482
|
}
|
|
625
483
|
async openLoginDialog(loginConfig, config) {
|
|
626
|
-
config
|
|
627
|
-
|
|
628
|
-
|
|
629
|
-
style: { 'max-width': '400px', width: '100%', 'height': '650px' },
|
|
630
|
-
};
|
|
631
|
-
config.data = { ...config.data || {}, ...{ loginConfig } };
|
|
484
|
+
config = this.intercepDialogConfig(config);
|
|
485
|
+
this.initConfig(loginConfig);
|
|
486
|
+
config.data = { ...(config.data || {}), ...{ loginConfig } };
|
|
632
487
|
const dialogService = this.injector.get(DialogService);
|
|
633
488
|
const dialog = dialogService.open(LocalizeLogindlgComponent, config);
|
|
634
489
|
await new Promise((resolve) => dialog.onClose.subscribe(res => {
|
|
@@ -637,6 +492,37 @@ class LocalizeLogindlgService {
|
|
|
637
492
|
}
|
|
638
493
|
}));
|
|
639
494
|
}
|
|
495
|
+
intercepDialogConfig(config) {
|
|
496
|
+
config ??= {
|
|
497
|
+
header: 'Login',
|
|
498
|
+
style: { 'max-width': '400px', width: '100%', 'height': '650px' },
|
|
499
|
+
modal: true,
|
|
500
|
+
closable: false,
|
|
501
|
+
showHeader: false,
|
|
502
|
+
};
|
|
503
|
+
config = {
|
|
504
|
+
...config, ...{
|
|
505
|
+
contentStyle: { 'height': '100%', 'border-radius': '20px' }
|
|
506
|
+
}
|
|
507
|
+
};
|
|
508
|
+
config.style = { ...config.style, ...{ 'border-radius': '20px' } };
|
|
509
|
+
return config;
|
|
510
|
+
}
|
|
511
|
+
initConfig(loginConfig) {
|
|
512
|
+
loginConfig ??= {};
|
|
513
|
+
loginConfig.properties ??= {
|
|
514
|
+
title: 'Your session is expired!<br/> Please login again to continue.',
|
|
515
|
+
loginSuccessMessage: 'You have successfully logged in.',
|
|
516
|
+
logoImage: '/assets/images/logo-300px.png',
|
|
517
|
+
username: { placeHolder: 'Username' },
|
|
518
|
+
password: { placeHolder: 'Password' },
|
|
519
|
+
loginButton: { placeHolder: 'Login' },
|
|
520
|
+
logoutButton: {
|
|
521
|
+
message: 'No, I want to login with another user.',
|
|
522
|
+
placeHolder: 'Logout'
|
|
523
|
+
}
|
|
524
|
+
};
|
|
525
|
+
}
|
|
640
526
|
static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "19.0.5", ngImport: i0, type: LocalizeLogindlgService, deps: [{ token: i0.Injector }], target: i0.ɵɵFactoryTarget.Injectable });
|
|
641
527
|
static ɵprov = i0.ɵɵngDeclareInjectable({ minVersion: "12.0.0", version: "19.0.5", ngImport: i0, type: LocalizeLogindlgService, providedIn: 'root' });
|
|
642
528
|
}
|
|
@@ -654,19 +540,13 @@ class LocalizeLogindlgModule {
|
|
|
654
540
|
InputTextModule,
|
|
655
541
|
BrowserModule,
|
|
656
542
|
FormsModule,
|
|
657
|
-
ButtonModule,
|
|
658
|
-
DynamicDialogModule,
|
|
659
|
-
InputGroupModule,
|
|
660
|
-
InputGroupAddonModule], exports: [LocalizeLogindlgComponent] });
|
|
543
|
+
ButtonModule], exports: [LocalizeLogindlgComponent] });
|
|
661
544
|
static ɵinj = i0.ɵɵngDeclareInjector({ minVersion: "12.0.0", version: "19.0.5", ngImport: i0, type: LocalizeLogindlgModule, providers: [LocalizeLogindlgService], imports: [CommonModule,
|
|
662
545
|
ToastModule,
|
|
663
546
|
InputTextModule,
|
|
664
547
|
BrowserModule,
|
|
665
548
|
FormsModule,
|
|
666
|
-
ButtonModule
|
|
667
|
-
DynamicDialogModule,
|
|
668
|
-
InputGroupModule,
|
|
669
|
-
InputGroupAddonModule] });
|
|
549
|
+
ButtonModule] });
|
|
670
550
|
}
|
|
671
551
|
i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "19.0.5", ngImport: i0, type: LocalizeLogindlgModule, decorators: [{
|
|
672
552
|
type: NgModule,
|
|
@@ -680,18 +560,558 @@ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "19.0.5", ngImpor
|
|
|
680
560
|
BrowserModule,
|
|
681
561
|
FormsModule,
|
|
682
562
|
ButtonModule,
|
|
683
|
-
DynamicDialogModule,
|
|
684
|
-
InputGroupModule,
|
|
685
|
-
InputGroupAddonModule
|
|
686
563
|
],
|
|
687
564
|
providers: [LocalizeLogindlgService],
|
|
688
565
|
schemas: [CUSTOM_ELEMENTS_SCHEMA],
|
|
689
566
|
}]
|
|
690
567
|
}] });
|
|
691
568
|
|
|
569
|
+
const LOCALIZE_API_ASSETS = {
|
|
570
|
+
network: {
|
|
571
|
+
noConnection: `<?xml version="1.0" encoding="UTF-8"?>
|
|
572
|
+
<svg id="lze-no-connection" data-name="Layer 2" xmlns="http://www.w3.org/2000/svg" viewBox="0 0 77.29 70.98">
|
|
573
|
+
<defs>
|
|
574
|
+
<style> .cls-1 { fill: #fff; } .cls-2, .cls-3 { fill: #e30613; } .cls-3 { stroke: #e30613; stroke-miterlimit: 10; stroke-width: .25px; } </style>
|
|
575
|
+
</defs>
|
|
576
|
+
<g id="Layer_3" data-name="Layer 3">
|
|
577
|
+
<g>
|
|
578
|
+
<path class="cls-1" d="m73.29,35c-1.2,0-2.33-.53-3.09-1.46-.48-.57-11.23-13.2-31.55-13.2s-31.11,12.66-31.56,13.2c-1.4,1.71-3.92,1.95-5.63.55-1.71-1.4-1.95-3.92-.55-5.63.54-.66,13.47-16.12,37.74-16.12s37.2,15.46,37.74,16.12c1.4,1.71,1.15,4.23-.56,5.62-.71.58-1.61.9-2.53.9Z"/>
|
|
579
|
+
<path class="cls-1" d="m63.96,45.66c-1.19,0-2.32-.53-3.08-1.44-5.79-6.05-13.86-9.39-22.24-9.21-8.38-.18-16.45,3.16-22.24,9.22-1.46,1.65-3.99,1.81-5.64.35-1.57-1.39-1.8-3.77-.52-5.43,7.32-7.89,17.64-12.29,28.4-12.12,10.76-.17,21.08,4.24,28.4,12.12,1.4,1.71,1.15,4.23-.56,5.62-.71.58-1.6.9-2.53.9Z"/>
|
|
580
|
+
<path class="cls-1" d="m53.3,56.32c-1.24,0-2.41-.57-3.16-1.55-5.73-6.35-15.52-6.85-21.87-1.13-.4.36-.77.73-1.13,1.13-1.36,1.73-3.88,2.03-5.61.67-1.71-1.34-2.03-3.8-.73-5.54,8.39-9.85,23.18-11.04,33.03-2.65.95.81,1.84,1.69,2.65,2.65,1.34,1.75,1,4.26-.75,5.6-.7.53-1.55.82-2.43.82Z"/>
|
|
581
|
+
</g>
|
|
582
|
+
<path class="cls-2" d="m47.21,9.45l-4.06,41.36c-.64,5.42-8.39,5.39-9.01,0,0,0-4.06-41.36-4.06-41.36-.46-4.73,2.99-8.94,7.72-9.4,5.33-.58,9.97,4.09,9.4,9.4h0Z"/>
|
|
583
|
+
<circle class="cls-3" cx="38.64" cy="64.79" r="6.07"/>
|
|
584
|
+
</g>
|
|
585
|
+
</svg>`
|
|
586
|
+
}
|
|
587
|
+
};
|
|
588
|
+
|
|
589
|
+
/**
|
|
590
|
+
* Http method options
|
|
591
|
+
*/
|
|
592
|
+
var EMethod;
|
|
593
|
+
(function (EMethod) {
|
|
594
|
+
EMethod["POST"] = "post";
|
|
595
|
+
EMethod["GET"] = "get";
|
|
596
|
+
EMethod["PUT"] = "put";
|
|
597
|
+
EMethod["DELETE"] = "delete";
|
|
598
|
+
EMethod["PATCH"] = "patch";
|
|
599
|
+
})(EMethod || (EMethod = {}));
|
|
600
|
+
|
|
601
|
+
class LocalizeApiHelper {
|
|
602
|
+
defaultRetryOptions = {
|
|
603
|
+
connectionError: {
|
|
604
|
+
message: 'Connection error occurred. Please wait',
|
|
605
|
+
blockScreen: true,
|
|
606
|
+
blockScreenZIndex: 10000
|
|
607
|
+
}
|
|
608
|
+
};
|
|
609
|
+
async performRetry(options) {
|
|
610
|
+
let attempts = 0;
|
|
611
|
+
let lastError;
|
|
612
|
+
let consoleCount = 0;
|
|
613
|
+
// Merge default retry options with provided options
|
|
614
|
+
options = { ...this.defaultRetryOptions, ...options };
|
|
615
|
+
let styleElement;
|
|
616
|
+
while (attempts < options.maxRetries()) {
|
|
617
|
+
try {
|
|
618
|
+
const result = await options.callback();
|
|
619
|
+
this.removeBlocker(styleElement);
|
|
620
|
+
return result;
|
|
621
|
+
}
|
|
622
|
+
catch (error) {
|
|
623
|
+
lastError = error;
|
|
624
|
+
if (consoleCount >= 7) {
|
|
625
|
+
console.clear();
|
|
626
|
+
consoleCount = 0;
|
|
627
|
+
}
|
|
628
|
+
if (options.retryUnless && !options.retryUnless(error))
|
|
629
|
+
throw error; // If the error should not be retried, rethrow it
|
|
630
|
+
// Handle connection error
|
|
631
|
+
styleElement = await this.onConnectionError(options, error);
|
|
632
|
+
if (options.onError)
|
|
633
|
+
await this.invokeHook(options.onError.bind(this, error));
|
|
634
|
+
if (attempts >= options.maxRetries() - 1)
|
|
635
|
+
throw error;
|
|
636
|
+
attempts++;
|
|
637
|
+
consoleCount++;
|
|
638
|
+
console.warn(`Attempt ${attempts} failed. Retrying...`, error);
|
|
639
|
+
await waitFor(options.delay);
|
|
640
|
+
}
|
|
641
|
+
}
|
|
642
|
+
console.warn(`Failed after ${options.maxRetries} attempts`);
|
|
643
|
+
throw lastError;
|
|
644
|
+
}
|
|
645
|
+
async performRequestWithRetry(options, config, performRequest) {
|
|
646
|
+
const retryUnless = config.retryOptions?.retryFunction
|
|
647
|
+
|| this.isConnectionError;
|
|
648
|
+
return await this.performRetry({
|
|
649
|
+
connectionError: config.retryOptions?.onConnectionError,
|
|
650
|
+
maxRetries: () => config.retryOptions?.maxRetries ?? 1000,
|
|
651
|
+
delay: config.retryOptions?.delay ?? 500,
|
|
652
|
+
callback: () => performRequest(options),
|
|
653
|
+
retryUnless: retryUnless,
|
|
654
|
+
});
|
|
655
|
+
}
|
|
656
|
+
buildUrl(baseUrl, path) {
|
|
657
|
+
const normalizedUrl = `${baseUrl.trim().replace(/\/?$/, '/')}${path.trim().replace(/^\//, '')}`;
|
|
658
|
+
return normalizedUrl.endsWith('/')
|
|
659
|
+
? normalizedUrl.slice(0, -1)
|
|
660
|
+
: normalizedUrl;
|
|
661
|
+
}
|
|
662
|
+
normalizeError(error) {
|
|
663
|
+
return {
|
|
664
|
+
code: error.error?.code || `HTTP_${error.status}`,
|
|
665
|
+
message: error.error?.message || error.message,
|
|
666
|
+
details: error.error?.details,
|
|
667
|
+
status: error.status
|
|
668
|
+
};
|
|
669
|
+
}
|
|
670
|
+
async invokeHook(callback) {
|
|
671
|
+
if (!callback)
|
|
672
|
+
return;
|
|
673
|
+
const result = callback();
|
|
674
|
+
if (result instanceof Promise) {
|
|
675
|
+
await result;
|
|
676
|
+
}
|
|
677
|
+
}
|
|
678
|
+
createRequest(instance, method, url, body, options) {
|
|
679
|
+
const request$ = instance.client.request(method, url, {
|
|
680
|
+
...options,
|
|
681
|
+
body,
|
|
682
|
+
observe: 'response',
|
|
683
|
+
}).pipe(takeUntil(instance.destroy$()), catchError((error) => {
|
|
684
|
+
// Convert to a non-observable error to handle in the promise
|
|
685
|
+
return throwError(() => this.normalizeError(error));
|
|
686
|
+
}));
|
|
687
|
+
return request$;
|
|
688
|
+
}
|
|
689
|
+
defaultRetryFunction(error) {
|
|
690
|
+
// Don't retry for other errors (like 400, 401, 403, etc.)
|
|
691
|
+
if (!this.isConnectionError(error))
|
|
692
|
+
throw error;
|
|
693
|
+
return true;
|
|
694
|
+
}
|
|
695
|
+
isConnectionError(error) {
|
|
696
|
+
const isNetworkError = error.status === 0;
|
|
697
|
+
const isServerError = error.status >= 1000 && error.status < 600;
|
|
698
|
+
return isNetworkError || isServerError;
|
|
699
|
+
}
|
|
700
|
+
async onConnectionError(options, error) {
|
|
701
|
+
if (!options.connectionError)
|
|
702
|
+
return;
|
|
703
|
+
let styleElement;
|
|
704
|
+
if (this.isConnectionError(error)) {
|
|
705
|
+
styleElement = this.screenBlocker(options, error, true);
|
|
706
|
+
await this.invokeHook(options.connectionError.callback?.bind(this, error));
|
|
707
|
+
return styleElement;
|
|
708
|
+
}
|
|
709
|
+
else {
|
|
710
|
+
this.screenBlocker(options, error, false);
|
|
711
|
+
styleElement?.remove();
|
|
712
|
+
}
|
|
713
|
+
}
|
|
714
|
+
screenBlocker(optons, error, add = true) {
|
|
715
|
+
if (!optons.connectionError?.blockScreen)
|
|
716
|
+
return;
|
|
717
|
+
if (error instanceof HttpErrorResponse)
|
|
718
|
+
error = this.normalizeError(error);
|
|
719
|
+
const message = optons.connectionError?.message
|
|
720
|
+
|| 'Connection error occurred. Please wait';
|
|
721
|
+
const errorMessage = error?.message || 'An error occurred';
|
|
722
|
+
const suggestinMessage = optons.connectionError?.suggestionMessage
|
|
723
|
+
|| 'Please check your internet connection or the server status.';
|
|
724
|
+
const zIndex = optons.connectionError?.blockScreenZIndex || 10000;
|
|
725
|
+
const body = document.body;
|
|
726
|
+
const blcokerHtml = `
|
|
727
|
+
<div class="lze-blocker">
|
|
728
|
+
${LOCALIZE_API_ASSETS.network.noConnection}
|
|
729
|
+
<div class="lze-blocker__message">
|
|
730
|
+
${message}
|
|
731
|
+
<span class="lze-blocker__dotting">
|
|
732
|
+
<span class="lze-blocker__dot"></span>
|
|
733
|
+
<span class="lze-blocker__dot"></span>
|
|
734
|
+
<span class="lze-blocker__dot"></span>
|
|
735
|
+
</span>
|
|
736
|
+
</div>
|
|
737
|
+
<div class="lze-blocker__error">${errorMessage}</div>
|
|
738
|
+
<div class="lze-blocker__error_suggestion">${suggestinMessage}</div>
|
|
739
|
+
</div>
|
|
740
|
+
`;
|
|
741
|
+
const style = `
|
|
742
|
+
div.lze-blocker {
|
|
743
|
+
position: fixed;
|
|
744
|
+
top: 0;
|
|
745
|
+
left: 0;
|
|
746
|
+
width: 100%;
|
|
747
|
+
height: 100%;
|
|
748
|
+
background: rgba(0, 0, 0, 0.85) !important;
|
|
749
|
+
z-index: ${zIndex};
|
|
750
|
+
display: flex;
|
|
751
|
+
align-items: center;
|
|
752
|
+
justify-content: center;
|
|
753
|
+
flex-direction: column;
|
|
754
|
+
color: #fff !important;
|
|
755
|
+
font-family: Arial, sans-serif;
|
|
756
|
+
text-align: center;
|
|
757
|
+
padding: 20px;
|
|
758
|
+
box-sizing: border-box;
|
|
759
|
+
overflow: hidden;
|
|
760
|
+
user-select: none;
|
|
761
|
+
}
|
|
762
|
+
|
|
763
|
+
svg#lze-no-connection {
|
|
764
|
+
width: 75px;
|
|
765
|
+
height: 75px;
|
|
766
|
+
margin-bottom: 20px;
|
|
767
|
+
}
|
|
768
|
+
|
|
769
|
+
div.lze-blocker__message {
|
|
770
|
+
color: #fff !important;
|
|
771
|
+
font-size: 18px !important;
|
|
772
|
+
margin-bottom: 10px;
|
|
773
|
+
}
|
|
774
|
+
|
|
775
|
+
.lze-blocker__dotting {
|
|
776
|
+
display: inline-block;
|
|
777
|
+
vertical-align: middle;
|
|
778
|
+
}
|
|
779
|
+
span.lze-blocker__dot {
|
|
780
|
+
display: inline-block;
|
|
781
|
+
width: 7px;
|
|
782
|
+
height: 7px;
|
|
783
|
+
background-color: #ffffff !important;
|
|
784
|
+
border-radius: 50%;
|
|
785
|
+
margin-left: 3px;
|
|
786
|
+
opacity: 0.3;
|
|
787
|
+
animation: dotting 1s infinite;
|
|
788
|
+
}
|
|
789
|
+
.lze-blocker__dot:nth-child(1) {
|
|
790
|
+
animation-delay: 0s;
|
|
791
|
+
opacity: 1;
|
|
792
|
+
}
|
|
793
|
+
.lze-blocker__dot:nth-child(2) {
|
|
794
|
+
animation-delay: 0.2s;
|
|
795
|
+
}
|
|
796
|
+
.lze-blocker__dot:nth-child(3) {
|
|
797
|
+
animation-delay: 0.4s;
|
|
798
|
+
}
|
|
799
|
+
|
|
800
|
+
@keyframes dotting {
|
|
801
|
+
0%, 80%, 100% { opacity: 0.3; }
|
|
802
|
+
40% { opacity: 1; }
|
|
803
|
+
}
|
|
804
|
+
|
|
805
|
+
div.lze-blocker__error {
|
|
806
|
+
color: #f00;
|
|
807
|
+
font-size: 14px !important;
|
|
808
|
+
margin-bottom: 10px;
|
|
809
|
+
text-shadow: 0 0 1px #ff5f5f !important;
|
|
810
|
+
}
|
|
811
|
+
|
|
812
|
+
div.lze-blocker__error_suggestion {
|
|
813
|
+
color: #ccc !important;
|
|
814
|
+
font-size: 14px !important;
|
|
815
|
+
margin-top: 10px;
|
|
816
|
+
}
|
|
817
|
+
|
|
818
|
+
@keyframes spin {
|
|
819
|
+
0% { transform: rotate(0deg); }
|
|
820
|
+
100% { transform: rotate(360deg); }
|
|
821
|
+
}
|
|
822
|
+
`;
|
|
823
|
+
const styleElement = document.createElement('style');
|
|
824
|
+
if (add) {
|
|
825
|
+
if (!document.querySelector('.lze-blocker')) {
|
|
826
|
+
styleElement.innerHTML = style;
|
|
827
|
+
document.head.appendChild(styleElement);
|
|
828
|
+
body.insertAdjacentHTML('beforeend', blcokerHtml);
|
|
829
|
+
}
|
|
830
|
+
}
|
|
831
|
+
else {
|
|
832
|
+
this.removeBlocker(styleElement);
|
|
833
|
+
}
|
|
834
|
+
return styleElement;
|
|
835
|
+
}
|
|
836
|
+
removeBlocker(styleElement) {
|
|
837
|
+
const blocker = document.querySelector('.lze-blocker');
|
|
838
|
+
blocker?.remove();
|
|
839
|
+
styleElement?.remove();
|
|
840
|
+
}
|
|
841
|
+
}
|
|
842
|
+
const ApiHelper = new LocalizeApiHelper();
|
|
843
|
+
|
|
844
|
+
const SCHEMES = LocalizeToken.httpHeaders;
|
|
845
|
+
class LocalizeApiService {
|
|
846
|
+
httpClient;
|
|
847
|
+
localizeTokenService;
|
|
848
|
+
destroy$ = new Subject();
|
|
849
|
+
configSubject = new BehaviorSubject({});
|
|
850
|
+
isRequestingSubject = new BehaviorSubject(false);
|
|
851
|
+
isResolvingStartupSubject = new BehaviorSubject(false);
|
|
852
|
+
get isResolvingStartup() { return this.isResolvingStartupSubject.value; }
|
|
853
|
+
get needTenant() { return this.localizeTokenService.config.tenantToken !== undefined; }
|
|
854
|
+
get isRequesting() { return this.isRequestingSubject.value; }
|
|
855
|
+
get isRevokingToken() { return this.localizeTokenService.isRevokingToken; }
|
|
856
|
+
set isRevokingToken(value) { this.localizeTokenService.isRevokingToken = value; }
|
|
857
|
+
get accessToken() { return this.localizeTokenService.accessToken; }
|
|
858
|
+
set accessToken(value) { this.localizeTokenService.accessToken = value; }
|
|
859
|
+
get refreshToken() { return this.localizeTokenService.refreshToken; }
|
|
860
|
+
get tenantToken() { return this.localizeTokenService.tenantToken; }
|
|
861
|
+
defaultConfig = {
|
|
862
|
+
waitEachRequest: { milliseconds: 0 },
|
|
863
|
+
enableRequestCancellation: true,
|
|
864
|
+
retryOptions: {
|
|
865
|
+
maxRetries: 1000,
|
|
866
|
+
delay: 1000,
|
|
867
|
+
retryFunction: ApiHelper.defaultRetryFunction.bind(this),
|
|
868
|
+
},
|
|
869
|
+
};
|
|
870
|
+
get config() {
|
|
871
|
+
this.validateConfig();
|
|
872
|
+
return this.configSubject.value;
|
|
873
|
+
}
|
|
874
|
+
apiOptions = {
|
|
875
|
+
method: EMethod.GET,
|
|
876
|
+
requestBody: null,
|
|
877
|
+
};
|
|
878
|
+
constructor(httpClient, localizeTokenService) {
|
|
879
|
+
this.httpClient = httpClient;
|
|
880
|
+
this.localizeTokenService = localizeTokenService;
|
|
881
|
+
}
|
|
882
|
+
/**
|
|
883
|
+
* Initialize the API service.
|
|
884
|
+
* @param apiConfigs - The API configurations.
|
|
885
|
+
*/
|
|
886
|
+
init(apiConfigs) {
|
|
887
|
+
console.log('LocalizeApiService is initialized.');
|
|
888
|
+
this.configSubject.next({ ...this.defaultConfig, ...apiConfigs });
|
|
889
|
+
}
|
|
890
|
+
cancelPendingRequests() {
|
|
891
|
+
this.config.enableRequestCancellation
|
|
892
|
+
&& this.destroy$.next();
|
|
893
|
+
}
|
|
894
|
+
ngOnDestroy() {
|
|
895
|
+
this.destroy$.next();
|
|
896
|
+
this.destroy$.complete();
|
|
897
|
+
// this.isResolvingStartupSubject.complete();
|
|
898
|
+
// this.isRequestingSubject.complete();
|
|
899
|
+
// this.configSubject.complete();
|
|
900
|
+
}
|
|
901
|
+
/**
|
|
902
|
+
* A higher-order function that returns a curried function for making API requests.
|
|
903
|
+
*
|
|
904
|
+
* @param baseUrl - The base URL of the API.
|
|
905
|
+
* @returns A curried function that can be used to make API requests.
|
|
906
|
+
*/
|
|
907
|
+
func = (baseUrl) => (path, method = EMethod.GET, reqBody = null, reqHeaders) => this.request(baseUrl, path, method, reqBody, reqHeaders);
|
|
908
|
+
async request(baseUrl, path, method = EMethod.GET, reqBody = null, reqHeaders) {
|
|
909
|
+
await waitUntil(() => !this.isResolvingStartup, 500);
|
|
910
|
+
await ApiHelper.invokeHook(this.config.onPrepareRequest);
|
|
911
|
+
const apiOptions = this.buildApiOptions(baseUrl, path, method, reqBody, reqHeaders);
|
|
912
|
+
try {
|
|
913
|
+
await this.toWaitForPreviousRequest();
|
|
914
|
+
return await ApiHelper.performRequestWithRetry(apiOptions, this.config, this.performRequest.bind(this));
|
|
915
|
+
}
|
|
916
|
+
catch (error) {
|
|
917
|
+
return await this.handleOnRequestError(error, apiOptions);
|
|
918
|
+
}
|
|
919
|
+
}
|
|
920
|
+
async handleOnRequestError(error, options) {
|
|
921
|
+
if (error.status !== 401)
|
|
922
|
+
throw error;
|
|
923
|
+
await waitUntil(() => !this.isResolvingStartup, 500);
|
|
924
|
+
return await ApiHelper.performRetry({
|
|
925
|
+
maxRetries: () => 1000,
|
|
926
|
+
delay: 500,
|
|
927
|
+
retryUnless: (error) => error.status === 401 || ApiHelper.isConnectionError(error),
|
|
928
|
+
callback: async () => {
|
|
929
|
+
// Only handle 401 Unauthorized errors
|
|
930
|
+
await this.revokeToken();
|
|
931
|
+
// Retry the request with the new access token
|
|
932
|
+
return await this.performRequest(options);
|
|
933
|
+
}
|
|
934
|
+
});
|
|
935
|
+
}
|
|
936
|
+
async performRequest(options) {
|
|
937
|
+
// Build the request options
|
|
938
|
+
const buildOptions = { headers: this.buildHeaderOptions(options) };
|
|
939
|
+
// Create the request observable
|
|
940
|
+
const request$ = ApiHelper.createRequest({
|
|
941
|
+
client: this.httpClient,
|
|
942
|
+
destroy$: () => this.destroy$
|
|
943
|
+
}, options.method, options.requestUrl, options.requestBody, buildOptions);
|
|
944
|
+
// Set the isRequesting state to true before making the request
|
|
945
|
+
this.isRequestingSubject.next(true);
|
|
946
|
+
const response = await new Promise((resolve, reject) => request$.subscribe({ next: (res) => resolve(res.body), error: reject }));
|
|
947
|
+
// Reset the isRequesting state after the request completes
|
|
948
|
+
this.isRequestingSubject.next(false);
|
|
949
|
+
return response;
|
|
950
|
+
}
|
|
951
|
+
async revokeToken() {
|
|
952
|
+
try {
|
|
953
|
+
if (await this.interceptRevokeToken())
|
|
954
|
+
return;
|
|
955
|
+
this.isRevokingToken = true;
|
|
956
|
+
const apiOptions = {
|
|
957
|
+
...this.buildApiOptions(this.localizeTokenService.config.refreshToken?.requestUrl || ''),
|
|
958
|
+
refreshToken: true,
|
|
959
|
+
};
|
|
960
|
+
// const revokeToken = await this.performRequest(apiOptions);
|
|
961
|
+
const revokeToken = await ApiHelper.performRequestWithRetry(apiOptions, this.config, this.performRequest.bind(this));
|
|
962
|
+
await this.handleOnTokenRevoked(revokeToken);
|
|
963
|
+
}
|
|
964
|
+
catch (error) {
|
|
965
|
+
// Handle the error, log it
|
|
966
|
+
await ApiHelper.invokeHook(this.config.onAutoLogout);
|
|
967
|
+
}
|
|
968
|
+
finally {
|
|
969
|
+
// Reset the revoking token state
|
|
970
|
+
this.isRevokingToken = false;
|
|
971
|
+
}
|
|
972
|
+
}
|
|
973
|
+
/** default http request options */
|
|
974
|
+
buildHeaderOptions(options) {
|
|
975
|
+
const headers = {
|
|
976
|
+
...(options.refreshToken && { [SCHEMES.X_REFRESH_TOKEN]: `${this.refreshToken}` }),
|
|
977
|
+
...(!options.isFormData && { [SCHEMES.CONTENT_TYPE]: 'application/json' }),
|
|
978
|
+
[SCHEMES.AUTHORIZATION]: `Bearer ${this.accessToken}`,
|
|
979
|
+
...(this.needTenant && { [SCHEMES.X_TENANT]: `${this.tenantToken}` })
|
|
980
|
+
};
|
|
981
|
+
return new HttpHeaders({ ...headers, ...options.headers });
|
|
982
|
+
}
|
|
983
|
+
buildApiOptions(baseUrl, path = '', method = EMethod.GET, requestBody = null, headers) {
|
|
984
|
+
const requestUrl = ApiHelper.buildUrl(baseUrl, path);
|
|
985
|
+
const isFormData = requestBody && requestBody instanceof FormData;
|
|
986
|
+
return {
|
|
987
|
+
...this.apiOptions,
|
|
988
|
+
...{ headers, method, requestUrl, requestBody, isFormData }
|
|
989
|
+
};
|
|
990
|
+
}
|
|
991
|
+
async toWaitForPreviousRequest() {
|
|
992
|
+
this.isRevokingToken &&
|
|
993
|
+
(await waitUntil(() => !this.isRevokingToken));
|
|
994
|
+
// to wait for each request in 50ms, even if the request is not completed
|
|
995
|
+
this.config.waitEachRequest?.milliseconds &&
|
|
996
|
+
(await waitFor(this.config.waitEachRequest.milliseconds, this.isRequesting));
|
|
997
|
+
}
|
|
998
|
+
async handleOnTokenRevoked(response) {
|
|
999
|
+
if (response?.status) {
|
|
1000
|
+
// If the response is successful, update the access token
|
|
1001
|
+
this.accessToken = response.message;
|
|
1002
|
+
}
|
|
1003
|
+
else {
|
|
1004
|
+
// If the response indicates an error, invoke the onRevokeUnauthorized hook
|
|
1005
|
+
console.warn('Token revocation failed, refresh token is expired.', response.message);
|
|
1006
|
+
await ApiHelper.invokeHook(this.config.onRevokeUnauthorized);
|
|
1007
|
+
}
|
|
1008
|
+
}
|
|
1009
|
+
async interceptRevokeToken() {
|
|
1010
|
+
if (this.isRevokingToken) {
|
|
1011
|
+
console.warn('Token is already being revoked. Waiting for the current operation to complete...');
|
|
1012
|
+
await waitUntil(() => !this.isRevokingToken);
|
|
1013
|
+
return true;
|
|
1014
|
+
}
|
|
1015
|
+
if (!this.refreshToken) {
|
|
1016
|
+
// await ApiHelper.invokeHook(this.apiConfigs.onAutoLogout);
|
|
1017
|
+
throw new Error('Refresh token is missing. Please login again.');
|
|
1018
|
+
}
|
|
1019
|
+
return false;
|
|
1020
|
+
}
|
|
1021
|
+
validateConfig() {
|
|
1022
|
+
if (this.localizeTokenService.config.tenantToken
|
|
1023
|
+
&& !this.localizeTokenService.config.tenantToken?.name?.trim().length) {
|
|
1024
|
+
throw Error('Tenant token is required but tenantTokenName is not configured');
|
|
1025
|
+
}
|
|
1026
|
+
if (!this.localizeTokenService.config.refreshToken?.requestUrl?.trim().length) {
|
|
1027
|
+
throw Error('Revoke token URL is not configured - token refresh will not work');
|
|
1028
|
+
}
|
|
1029
|
+
}
|
|
1030
|
+
static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "19.0.5", ngImport: i0, type: LocalizeApiService, deps: [{ token: i4.HttpClient }, { token: LocalizeTokenService }], target: i0.ɵɵFactoryTarget.Injectable });
|
|
1031
|
+
static ɵprov = i0.ɵɵngDeclareInjectable({ minVersion: "12.0.0", version: "19.0.5", ngImport: i0, type: LocalizeApiService, providedIn: 'root' });
|
|
1032
|
+
}
|
|
1033
|
+
i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "19.0.5", ngImport: i0, type: LocalizeApiService, decorators: [{
|
|
1034
|
+
type: Injectable,
|
|
1035
|
+
args: [{
|
|
1036
|
+
providedIn: 'root'
|
|
1037
|
+
}]
|
|
1038
|
+
}], ctorParameters: () => [{ type: i4.HttpClient }, { type: LocalizeTokenService }] });
|
|
1039
|
+
|
|
1040
|
+
class LocalizeTokenModule {
|
|
1041
|
+
static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "19.0.5", ngImport: i0, type: LocalizeTokenModule, deps: [], target: i0.ɵɵFactoryTarget.NgModule });
|
|
1042
|
+
static ɵmod = i0.ɵɵngDeclareNgModule({ minVersion: "14.0.0", version: "19.0.5", ngImport: i0, type: LocalizeTokenModule });
|
|
1043
|
+
static ɵinj = i0.ɵɵngDeclareInjector({ minVersion: "12.0.0", version: "19.0.5", ngImport: i0, type: LocalizeTokenModule, providers: [
|
|
1044
|
+
LocalizeTokenService,
|
|
1045
|
+
LocalizeApiService
|
|
1046
|
+
] });
|
|
1047
|
+
}
|
|
1048
|
+
i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "19.0.5", ngImport: i0, type: LocalizeTokenModule, decorators: [{
|
|
1049
|
+
type: NgModule,
|
|
1050
|
+
args: [{
|
|
1051
|
+
providers: [
|
|
1052
|
+
LocalizeTokenService,
|
|
1053
|
+
LocalizeApiService
|
|
1054
|
+
]
|
|
1055
|
+
}]
|
|
1056
|
+
}] });
|
|
1057
|
+
|
|
1058
|
+
class LocalizeApiTokenService {
|
|
1059
|
+
api;
|
|
1060
|
+
token;
|
|
1061
|
+
loginDialog;
|
|
1062
|
+
constructor(tokenService, apiService, loginDialogService) {
|
|
1063
|
+
this.api = apiService;
|
|
1064
|
+
this.token = tokenService;
|
|
1065
|
+
this.loginDialog = loginDialogService;
|
|
1066
|
+
}
|
|
1067
|
+
initialize(tokenConfig, apiConfig) {
|
|
1068
|
+
// Initialize the LocalizeTokenService with the provided token configuration
|
|
1069
|
+
this.token.init(tokenConfig);
|
|
1070
|
+
// Initialize the LocalizeApiService with the provided API configuration
|
|
1071
|
+
this.api.init(apiConfig);
|
|
1072
|
+
console.log('LocalizeApiTokenService initialized with token and API configurations.');
|
|
1073
|
+
}
|
|
1074
|
+
static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "19.0.5", ngImport: i0, type: LocalizeApiTokenService, deps: [{ token: LocalizeTokenService }, { token: LocalizeApiService }, { token: LocalizeLogindlgService }], target: i0.ɵɵFactoryTarget.Injectable });
|
|
1075
|
+
static ɵprov = i0.ɵɵngDeclareInjectable({ minVersion: "12.0.0", version: "19.0.5", ngImport: i0, type: LocalizeApiTokenService, providedIn: 'root' });
|
|
1076
|
+
}
|
|
1077
|
+
i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "19.0.5", ngImport: i0, type: LocalizeApiTokenService, decorators: [{
|
|
1078
|
+
type: Injectable,
|
|
1079
|
+
args: [{
|
|
1080
|
+
providedIn: 'root'
|
|
1081
|
+
}]
|
|
1082
|
+
}], ctorParameters: () => [{ type: LocalizeTokenService }, { type: LocalizeApiService }, { type: LocalizeLogindlgService }] });
|
|
1083
|
+
|
|
1084
|
+
class LocalizeApiTokenModule {
|
|
1085
|
+
static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "19.0.5", ngImport: i0, type: LocalizeApiTokenModule, deps: [], target: i0.ɵɵFactoryTarget.NgModule });
|
|
1086
|
+
static ɵmod = i0.ɵɵngDeclareNgModule({ minVersion: "14.0.0", version: "19.0.5", ngImport: i0, type: LocalizeApiTokenModule, imports: [CommonModule,
|
|
1087
|
+
LocalizeTokenModule,
|
|
1088
|
+
LocalizeLogindlgModule] });
|
|
1089
|
+
static ɵinj = i0.ɵɵngDeclareInjector({ minVersion: "12.0.0", version: "19.0.5", ngImport: i0, type: LocalizeApiTokenModule, providers: [
|
|
1090
|
+
LocalizeApiTokenService
|
|
1091
|
+
], imports: [CommonModule,
|
|
1092
|
+
LocalizeTokenModule,
|
|
1093
|
+
LocalizeLogindlgModule] });
|
|
1094
|
+
}
|
|
1095
|
+
i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "19.0.5", ngImport: i0, type: LocalizeApiTokenModule, decorators: [{
|
|
1096
|
+
type: NgModule,
|
|
1097
|
+
args: [{
|
|
1098
|
+
declarations: [],
|
|
1099
|
+
imports: [
|
|
1100
|
+
CommonModule,
|
|
1101
|
+
LocalizeTokenModule,
|
|
1102
|
+
LocalizeLogindlgModule
|
|
1103
|
+
],
|
|
1104
|
+
providers: [
|
|
1105
|
+
LocalizeApiTokenService
|
|
1106
|
+
]
|
|
1107
|
+
}]
|
|
1108
|
+
}] });
|
|
1109
|
+
|
|
1110
|
+
//#region login dialog
|
|
1111
|
+
|
|
692
1112
|
/**
|
|
693
1113
|
* Generated bundle index. Do not edit.
|
|
694
1114
|
*/
|
|
695
1115
|
|
|
696
|
-
export { EMethod, LocalizeApiService, LocalizeLogindlgComponent, LocalizeLogindlgModule, LocalizeLogindlgService, LocalizeToken, LocalizeTokenModule, LocalizeTokenService, LocalizeTokenStorage, extractMainDomain, waitFor, waitUntil };
|
|
1116
|
+
export { ApiHelper, EMethod, LOCALIZE_API_ASSETS, LocalizeApiService, LocalizeApiTokenModule, LocalizeApiTokenService, LocalizeLogindlgComponent, LocalizeLogindlgModule, LocalizeLogindlgService, LocalizeToken, LocalizeTokenModule, LocalizeTokenService, LocalizeTokenStorage, extractMainDomain, waitFor, waitUntil };
|
|
697
1117
|
//# sourceMappingURL=sambath999-localize-token.mjs.map
|