@sambath999/localize-token 19.0.3 → 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 -292
- 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 -46
- 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,41 +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
|
-
}
|
|
217
|
-
}
|
|
218
|
-
// get tenantToken() { return LocalizeToken.storage.get(this.config.tenantTokenName!) }
|
|
219
|
-
tenantToken(name) {
|
|
220
|
-
return LocalizeToken.storage.get(name ?? this.config.tenantTokenName);
|
|
216
|
+
this.authToken && (this.authToken = { ...this.authToken, revoke: value });
|
|
221
217
|
}
|
|
222
218
|
storageGet() {
|
|
223
219
|
try {
|
|
224
|
-
const encoded = LocalizeToken.storage.get(this.config.
|
|
220
|
+
const encoded = LocalizeToken.storage.get(this.config.authToken?.name || '');
|
|
225
221
|
const decoded = atob(encoded || '');
|
|
226
222
|
return JSON.parse(decoded);
|
|
227
223
|
}
|
|
@@ -231,17 +227,21 @@ class LocalizeTokenService {
|
|
|
231
227
|
}
|
|
232
228
|
storageSet(value) {
|
|
233
229
|
const base64 = btoa(JSON.stringify(value));
|
|
234
|
-
LocalizeToken.storage.set(this.config.
|
|
230
|
+
LocalizeToken.storage.set(this.config.authToken?.name || '', base64);
|
|
235
231
|
}
|
|
236
232
|
tokensValid() {
|
|
237
|
-
return this.refreshToken?.length
|
|
233
|
+
return !!this.refreshToken?.length
|
|
234
|
+
&& (!this.config.tenantToken || !!this.tenantToken?.length);
|
|
238
235
|
}
|
|
239
236
|
decodeToken = (token) => jwt_decode.jwtDecode(token);
|
|
240
237
|
get decodeRefreshToken() {
|
|
241
|
-
const token =
|
|
242
|
-
|
|
243
|
-
|
|
244
|
-
|
|
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
|
+
}
|
|
245
245
|
}
|
|
246
246
|
static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "19.0.5", ngImport: i0, type: LocalizeTokenService, deps: [], target: i0.ɵɵFactoryTarget.Injectable });
|
|
247
247
|
static ɵprov = i0.ɵɵngDeclareInjectable({ minVersion: "12.0.0", version: "19.0.5", ngImport: i0, type: LocalizeTokenService, providedIn: 'root' });
|
|
@@ -249,161 +249,6 @@ class LocalizeTokenService {
|
|
|
249
249
|
i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "19.0.5", ngImport: i0, type: LocalizeTokenService, decorators: [{
|
|
250
250
|
type: Injectable,
|
|
251
251
|
args: [{ providedIn: 'root' }]
|
|
252
|
-
}], ctorParameters: () => [] });
|
|
253
|
-
|
|
254
|
-
/**
|
|
255
|
-
* Http method options
|
|
256
|
-
*/
|
|
257
|
-
var EMethod;
|
|
258
|
-
(function (EMethod) {
|
|
259
|
-
EMethod[EMethod["POST"] = 1] = "POST";
|
|
260
|
-
EMethod[EMethod["GET"] = 2] = "GET";
|
|
261
|
-
EMethod[EMethod["PUT"] = 3] = "PUT";
|
|
262
|
-
EMethod[EMethod["DELETE"] = 4] = "DELETE";
|
|
263
|
-
EMethod[EMethod["PATCH"] = 5] = "PATCH";
|
|
264
|
-
})(EMethod || (EMethod = {}));
|
|
265
|
-
class LocalizeApiService {
|
|
266
|
-
httpClient;
|
|
267
|
-
localizeTokenService;
|
|
268
|
-
isRequestingSubject = new BehaviorSubject(false);
|
|
269
|
-
isResolvedStartupSubject = new BehaviorSubject(false);
|
|
270
|
-
get isRequesting() { return this.isRequestingSubject.value; }
|
|
271
|
-
get isResolvedStartup() { return this.isResolvedStartupSubject.value; }
|
|
272
|
-
apiConfigs = {};
|
|
273
|
-
isInitialized = false;
|
|
274
|
-
constructor(httpClient, localizeTokenService) {
|
|
275
|
-
this.httpClient = httpClient;
|
|
276
|
-
this.localizeTokenService = localizeTokenService;
|
|
277
|
-
}
|
|
278
|
-
/**
|
|
279
|
-
* Initialize the API service.
|
|
280
|
-
* @param apiConfigs - The API configurations.
|
|
281
|
-
*/
|
|
282
|
-
init(apiConfigs) {
|
|
283
|
-
if (this.isInitialized)
|
|
284
|
-
return;
|
|
285
|
-
this.isInitialized = true;
|
|
286
|
-
this.apiConfigs = apiConfigs;
|
|
287
|
-
}
|
|
288
|
-
/**
|
|
289
|
-
* A higher-order function that returns a curried function for making API requests.
|
|
290
|
-
*
|
|
291
|
-
* @param baseUrl - The base URL of the API.
|
|
292
|
-
* @returns A curried function that can be used to make API requests.
|
|
293
|
-
*/
|
|
294
|
-
func = (baseUrl) => (path, method = EMethod.GET, value = null, isFormData = false, headers) => this.base(baseUrl, path, method, value, isFormData, headers);
|
|
295
|
-
async base(baseUrl, path, method = EMethod.GET, value = null, isFormData = false, headers) {
|
|
296
|
-
await this.ifPromise(this.apiConfigs.onPrepareRequest);
|
|
297
|
-
const url = `${baseUrl.trim().replace(/\/?$/, '/')}${path.trim().replace(/^\//, '')}`;
|
|
298
|
-
const httpMethod = EMethod[method].toLowerCase();
|
|
299
|
-
const request = () => { return { body: value, headers: this.options(isFormData, headers) }; };
|
|
300
|
-
// Wait for previous request to complete
|
|
301
|
-
await this.toWaitForPreviousRequest();
|
|
302
|
-
// Process request
|
|
303
|
-
try {
|
|
304
|
-
return await this.processRequest(httpMethod, url, request());
|
|
305
|
-
}
|
|
306
|
-
// Handle unauthorized error if any
|
|
307
|
-
catch (error) {
|
|
308
|
-
if (error.status !== 401) {
|
|
309
|
-
throw error;
|
|
310
|
-
}
|
|
311
|
-
return await this.onUnauthorizedError(httpMethod, url, request);
|
|
312
|
-
}
|
|
313
|
-
}
|
|
314
|
-
async onUnauthorizedError(httpMethod, url, request) {
|
|
315
|
-
await this.revokeToken();
|
|
316
|
-
if (!this.isResolvedStartup) {
|
|
317
|
-
return await this.processRequest(httpMethod, url, request());
|
|
318
|
-
}
|
|
319
|
-
}
|
|
320
|
-
async toWaitForPreviousRequest() {
|
|
321
|
-
if (this.localizeTokenService.isRevokingToken) {
|
|
322
|
-
await waitUntil(() => !this.localizeTokenService.isRevokingToken);
|
|
323
|
-
}
|
|
324
|
-
// to wait for each request in 50ms, even if the request is not completed
|
|
325
|
-
if (this.apiConfigs.waitEachRequest?.milliseconds) {
|
|
326
|
-
await waitFor(this.apiConfigs.waitEachRequest.milliseconds, this.isRequesting);
|
|
327
|
-
}
|
|
328
|
-
}
|
|
329
|
-
async processRequest(method, url, options) {
|
|
330
|
-
this.isRequestingSubject.next(true);
|
|
331
|
-
const result = await new Promise((resolve, reject) => this.httpClient.request(method, url, options).subscribe({ next: resolve, error: reject }));
|
|
332
|
-
this.isRequestingSubject.next(false);
|
|
333
|
-
return result;
|
|
334
|
-
}
|
|
335
|
-
async revokeToken() {
|
|
336
|
-
if (this.localizeTokenService.isRevokingToken) {
|
|
337
|
-
await waitUntil(() => !this.localizeTokenService.isRevokingToken);
|
|
338
|
-
return;
|
|
339
|
-
}
|
|
340
|
-
try {
|
|
341
|
-
this.localizeTokenService.isRevokingToken = true;
|
|
342
|
-
const reqUrl = LocalizeToken.config.revokeTokenUrl;
|
|
343
|
-
const reqHeaders = this.options().append(LocalizeToken.httpHeaders.X_REFRESH_TOKEN, `${this.localizeTokenService.refreshToken}`);
|
|
344
|
-
const revokeToken = await new Promise((resolve, reject) => this.httpClient.get(reqUrl, { headers: reqHeaders }).subscribe({ next: resolve, error: reject }));
|
|
345
|
-
if (revokeToken?.status) {
|
|
346
|
-
this.localizeTokenService.accessToken = revokeToken.message;
|
|
347
|
-
}
|
|
348
|
-
else if (!this.localizeTokenService.refreshToken) {
|
|
349
|
-
await this.ifPromise(this.apiConfigs.onAutoLogout);
|
|
350
|
-
}
|
|
351
|
-
else {
|
|
352
|
-
if (this.apiConfigs.onRevokeUnauthorized) {
|
|
353
|
-
await this.ifPromise(this.apiConfigs.onRevokeUnauthorized);
|
|
354
|
-
// await this.revokeToken();
|
|
355
|
-
}
|
|
356
|
-
}
|
|
357
|
-
}
|
|
358
|
-
finally {
|
|
359
|
-
this.localizeTokenService.isRevokingToken = false;
|
|
360
|
-
}
|
|
361
|
-
}
|
|
362
|
-
/** default http request options */
|
|
363
|
-
options(isFormData = false, headers = {}) {
|
|
364
|
-
const defaultHeaders = { [LocalizeToken.httpHeaders.AUTHORIZATION]: `Bearer ${this.localizeTokenService.accessToken}`, };
|
|
365
|
-
if (LocalizeToken.config.needTenant) {
|
|
366
|
-
defaultHeaders[LocalizeToken.httpHeaders.X_TENANT] = `${this.localizeTokenService.tenantToken(this.apiConfigs.tenantTokenName)}`;
|
|
367
|
-
}
|
|
368
|
-
if (!isFormData) {
|
|
369
|
-
defaultHeaders[LocalizeToken.httpHeaders.CONTENT_TYPE] = 'application/json';
|
|
370
|
-
}
|
|
371
|
-
const filteredHeaders = Object.keys(defaultHeaders).filter(key => !Object.keys(headers).includes(key))
|
|
372
|
-
.reduce((acc, key) => ({ ...acc, [key]: defaultHeaders[key] }), {});
|
|
373
|
-
const mergedHeaders = { ...filteredHeaders, ...headers };
|
|
374
|
-
return new HttpHeaders(mergedHeaders);
|
|
375
|
-
}
|
|
376
|
-
async ifPromise(fn) {
|
|
377
|
-
if (!fn)
|
|
378
|
-
return;
|
|
379
|
-
return fn instanceof Promise ? await fn() : fn();
|
|
380
|
-
}
|
|
381
|
-
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 });
|
|
382
|
-
static ɵprov = i0.ɵɵngDeclareInjectable({ minVersion: "12.0.0", version: "19.0.5", ngImport: i0, type: LocalizeApiService, providedIn: 'root' });
|
|
383
|
-
} //class
|
|
384
|
-
i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "19.0.5", ngImport: i0, type: LocalizeApiService, decorators: [{
|
|
385
|
-
type: Injectable,
|
|
386
|
-
args: [{
|
|
387
|
-
providedIn: 'root'
|
|
388
|
-
}]
|
|
389
|
-
}], ctorParameters: () => [{ type: i1.HttpClient }, { type: LocalizeTokenService }] });
|
|
390
|
-
|
|
391
|
-
class LocalizeTokenModule {
|
|
392
|
-
static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "19.0.5", ngImport: i0, type: LocalizeTokenModule, deps: [], target: i0.ɵɵFactoryTarget.NgModule });
|
|
393
|
-
static ɵmod = i0.ɵɵngDeclareNgModule({ minVersion: "14.0.0", version: "19.0.5", ngImport: i0, type: LocalizeTokenModule });
|
|
394
|
-
static ɵinj = i0.ɵɵngDeclareInjector({ minVersion: "12.0.0", version: "19.0.5", ngImport: i0, type: LocalizeTokenModule, providers: [
|
|
395
|
-
LocalizeTokenService,
|
|
396
|
-
LocalizeApiService
|
|
397
|
-
] });
|
|
398
|
-
}
|
|
399
|
-
i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "19.0.5", ngImport: i0, type: LocalizeTokenModule, decorators: [{
|
|
400
|
-
type: NgModule,
|
|
401
|
-
args: [{
|
|
402
|
-
providers: [
|
|
403
|
-
LocalizeTokenService,
|
|
404
|
-
LocalizeApiService
|
|
405
|
-
],
|
|
406
|
-
}]
|
|
407
252
|
}] });
|
|
408
253
|
|
|
409
254
|
class LocalizeLogindlgComponent {
|
|
@@ -413,24 +258,28 @@ class LocalizeLogindlgComponent {
|
|
|
413
258
|
dlgConfig;
|
|
414
259
|
tokenService;
|
|
415
260
|
httpClient;
|
|
261
|
+
sanitizer;
|
|
416
262
|
messageKey = "$login-dlg";
|
|
417
263
|
password;
|
|
418
264
|
decodeToken;
|
|
419
265
|
loading = false;
|
|
420
266
|
success = false;
|
|
421
|
-
config
|
|
267
|
+
get config() { return this.tokenService.config; }
|
|
422
268
|
loginConfig;
|
|
423
269
|
logout;
|
|
424
270
|
loginUrl;
|
|
425
|
-
|
|
271
|
+
properties;
|
|
272
|
+
constructor(messageService, cdt, dlgRef, dlgConfig, tokenService, httpClient, sanitizer) {
|
|
426
273
|
this.messageService = messageService;
|
|
427
274
|
this.cdt = cdt;
|
|
428
275
|
this.dlgRef = dlgRef;
|
|
429
276
|
this.dlgConfig = dlgConfig;
|
|
430
277
|
this.tokenService = tokenService;
|
|
431
278
|
this.httpClient = httpClient;
|
|
279
|
+
this.sanitizer = sanitizer;
|
|
432
280
|
this.decodeToken = this.tokenService.decodeRefreshToken;
|
|
433
281
|
this.loginConfig = this.dlgConfig.data.loginConfig;
|
|
282
|
+
this.properties = this.loginConfig.properties;
|
|
434
283
|
}
|
|
435
284
|
ngOnInit() {
|
|
436
285
|
this.dlgConfig.closable = false;
|
|
@@ -446,29 +295,34 @@ class LocalizeLogindlgComponent {
|
|
|
446
295
|
}
|
|
447
296
|
async clickLogin() {
|
|
448
297
|
if (!this.isValidPassword) {
|
|
449
|
-
this.showMessage("error", "Password is required and must be at least 6 characters");
|
|
450
|
-
return;
|
|
298
|
+
return this.showMessage("error", "Password is required and must be at least 6 characters");
|
|
451
299
|
}
|
|
452
300
|
this.loading = true;
|
|
453
301
|
const loginRes = await this.login();
|
|
454
302
|
if (!loginRes?.status) {
|
|
455
|
-
this.showMessage("error", loginRes.message ?? "An error occurred");
|
|
456
|
-
return;
|
|
303
|
+
return this.showMessage("error", loginRes.message ?? "An error occurred");
|
|
457
304
|
}
|
|
458
305
|
this.tokenService.accessToken = loginRes.tokens.accessToken;
|
|
459
|
-
const cookieOptions = { expires: this.loginConfig.expire ??
|
|
460
|
-
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);
|
|
461
308
|
this.success = true;
|
|
462
|
-
setTimeout(() =>
|
|
309
|
+
setTimeout(() => {
|
|
310
|
+
this.dlgConfig.dismissableMask = true;
|
|
311
|
+
this.dlgConfig.modal = false;
|
|
312
|
+
this.dlgRef.close(true);
|
|
313
|
+
}, 2000);
|
|
463
314
|
}
|
|
464
315
|
async login() {
|
|
465
|
-
if (!this.loginUrl
|
|
316
|
+
if (!this.loginUrl?.trim().length) {
|
|
466
317
|
this.showMessage("error", "Login url is required");
|
|
467
318
|
throw new Error("Login url is required");
|
|
468
319
|
}
|
|
469
320
|
try {
|
|
470
|
-
|
|
471
|
-
.
|
|
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 }));
|
|
472
326
|
}
|
|
473
327
|
catch (e) {
|
|
474
328
|
this.showMessage("error", e.message);
|
|
@@ -477,26 +331,31 @@ class LocalizeLogindlgComponent {
|
|
|
477
331
|
}
|
|
478
332
|
getHeaders() {
|
|
479
333
|
return {
|
|
480
|
-
[LocalizeToken.httpHeaders.X_REFRESH_TOKEN]:
|
|
481
|
-
[LocalizeToken.httpHeaders.X_TENANT]:
|
|
334
|
+
[LocalizeToken.httpHeaders.X_REFRESH_TOKEN]: this.tokenService.refreshToken ?? "",
|
|
335
|
+
[LocalizeToken.httpHeaders.X_TENANT]: this.tokenService.tenantToken ?? "",
|
|
482
336
|
};
|
|
483
337
|
}
|
|
484
338
|
get isValidPassword() {
|
|
485
339
|
this.loading = false;
|
|
486
|
-
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;
|
|
487
343
|
}
|
|
488
344
|
clickLogout = () => this.logout?.();
|
|
489
345
|
showMessage(severity, summary) {
|
|
490
346
|
this.messageService.add({ key: this.messageKey, severity, summary });
|
|
491
347
|
this.loading = false;
|
|
492
348
|
}
|
|
493
|
-
|
|
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 });
|
|
494
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>
|
|
495
354
|
<div id="login-dlg-wrap">
|
|
496
355
|
<div id="login-dlg-header">
|
|
497
|
-
<div id="login-logo" class="p-mb-2"></div>
|
|
498
|
-
<h3 *ngIf="!success"
|
|
499
|
-
<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>
|
|
500
359
|
</div>
|
|
501
360
|
<div id="login-dlg-content">
|
|
502
361
|
<ng-container *ngIf="!success">
|
|
@@ -504,35 +363,33 @@ class LocalizeLogindlgComponent {
|
|
|
504
363
|
<div class="login-dlg-loader"></div>
|
|
505
364
|
</div>
|
|
506
365
|
<div class="login-dlg-elm">
|
|
507
|
-
<p-inputgroup>
|
|
508
|
-
<
|
|
509
|
-
<
|
|
510
|
-
|
|
511
|
-
|
|
512
|
-
|
|
513
|
-
<input disabled pInputText type="text" placeholder="Username" [value]="decodeToken?.email" />
|
|
514
|
-
</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>
|
|
515
372
|
</div>
|
|
516
373
|
|
|
517
374
|
<div class="login-dlg-elm">
|
|
518
|
-
<p-inputgroup>
|
|
519
|
-
<p-inputgroup-addon>
|
|
520
|
-
<
|
|
521
|
-
|
|
522
|
-
|
|
523
|
-
|
|
524
|
-
<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"
|
|
525
381
|
autofocus />
|
|
526
|
-
</
|
|
382
|
+
</div>
|
|
527
383
|
</div>
|
|
528
384
|
<div class="login-dlg-elm">
|
|
529
|
-
<button style="width: 100%;" pButton type="button" label="
|
|
385
|
+
<button style="width: 100%;" pButton type="button" label="{{properties.loginButton?.placeHolder}}" (click)="clickLogin()"
|
|
530
386
|
[disabled]="!password || loading"></button>
|
|
531
387
|
</div>
|
|
532
388
|
|
|
533
|
-
<div class="login-dlg-elm" style="display:flex;align-items: center;user-select: none;">
|
|
534
|
-
<span>
|
|
535
|
-
<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>
|
|
536
393
|
</div>
|
|
537
394
|
</ng-container>
|
|
538
395
|
|
|
@@ -552,16 +409,16 @@ class LocalizeLogindlgComponent {
|
|
|
552
409
|
</div>
|
|
553
410
|
</ng-container>
|
|
554
411
|
</div>
|
|
555
|
-
</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 });
|
|
556
413
|
}
|
|
557
414
|
i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "19.0.5", ngImport: i0, type: LocalizeLogindlgComponent, decorators: [{
|
|
558
415
|
type: Component,
|
|
559
416
|
args: [{ standalone: false, template: `<p-toast key="$login-dlg" position="top-center"></p-toast>
|
|
560
417
|
<div id="login-dlg-wrap">
|
|
561
418
|
<div id="login-dlg-header">
|
|
562
|
-
<div id="login-logo" class="p-mb-2"></div>
|
|
563
|
-
<h3 *ngIf="!success"
|
|
564
|
-
<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>
|
|
565
422
|
</div>
|
|
566
423
|
<div id="login-dlg-content">
|
|
567
424
|
<ng-container *ngIf="!success">
|
|
@@ -569,35 +426,33 @@ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "19.0.5", ngImpor
|
|
|
569
426
|
<div class="login-dlg-loader"></div>
|
|
570
427
|
</div>
|
|
571
428
|
<div class="login-dlg-elm">
|
|
572
|
-
<p-inputgroup>
|
|
573
|
-
<
|
|
574
|
-
<
|
|
575
|
-
|
|
576
|
-
|
|
577
|
-
|
|
578
|
-
<input disabled pInputText type="text" placeholder="Username" [value]="decodeToken?.email" />
|
|
579
|
-
</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>
|
|
580
435
|
</div>
|
|
581
436
|
|
|
582
437
|
<div class="login-dlg-elm">
|
|
583
|
-
<p-inputgroup>
|
|
584
|
-
<p-inputgroup-addon>
|
|
585
|
-
<
|
|
586
|
-
|
|
587
|
-
|
|
588
|
-
|
|
589
|
-
<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"
|
|
590
444
|
autofocus />
|
|
591
|
-
</
|
|
445
|
+
</div>
|
|
592
446
|
</div>
|
|
593
447
|
<div class="login-dlg-elm">
|
|
594
|
-
<button style="width: 100%;" pButton type="button" label="
|
|
448
|
+
<button style="width: 100%;" pButton type="button" label="{{properties.loginButton?.placeHolder}}" (click)="clickLogin()"
|
|
595
449
|
[disabled]="!password || loading"></button>
|
|
596
450
|
</div>
|
|
597
451
|
|
|
598
|
-
<div class="login-dlg-elm" style="display:flex;align-items: center;user-select: none;">
|
|
599
|
-
<span>
|
|
600
|
-
<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>
|
|
601
456
|
</div>
|
|
602
457
|
</ng-container>
|
|
603
458
|
|
|
@@ -617,8 +472,8 @@ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "19.0.5", ngImpor
|
|
|
617
472
|
</div>
|
|
618
473
|
</ng-container>
|
|
619
474
|
</div>
|
|
620
|
-
</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:
|
|
621
|
-
}], 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 }] });
|
|
622
477
|
|
|
623
478
|
class LocalizeLogindlgService {
|
|
624
479
|
injector;
|
|
@@ -626,12 +481,9 @@ class LocalizeLogindlgService {
|
|
|
626
481
|
this.injector = injector;
|
|
627
482
|
}
|
|
628
483
|
async openLoginDialog(loginConfig, config) {
|
|
629
|
-
config
|
|
630
|
-
|
|
631
|
-
|
|
632
|
-
style: { 'max-width': '400px', width: '100%', 'height': '650px' },
|
|
633
|
-
};
|
|
634
|
-
config.data = { ...config.data || {}, ...{ loginConfig } };
|
|
484
|
+
config = this.intercepDialogConfig(config);
|
|
485
|
+
this.initConfig(loginConfig);
|
|
486
|
+
config.data = { ...(config.data || {}), ...{ loginConfig } };
|
|
635
487
|
const dialogService = this.injector.get(DialogService);
|
|
636
488
|
const dialog = dialogService.open(LocalizeLogindlgComponent, config);
|
|
637
489
|
await new Promise((resolve) => dialog.onClose.subscribe(res => {
|
|
@@ -640,6 +492,37 @@ class LocalizeLogindlgService {
|
|
|
640
492
|
}
|
|
641
493
|
}));
|
|
642
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
|
+
}
|
|
643
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 });
|
|
644
527
|
static ɵprov = i0.ɵɵngDeclareInjectable({ minVersion: "12.0.0", version: "19.0.5", ngImport: i0, type: LocalizeLogindlgService, providedIn: 'root' });
|
|
645
528
|
}
|
|
@@ -657,19 +540,13 @@ class LocalizeLogindlgModule {
|
|
|
657
540
|
InputTextModule,
|
|
658
541
|
BrowserModule,
|
|
659
542
|
FormsModule,
|
|
660
|
-
ButtonModule,
|
|
661
|
-
DynamicDialogModule,
|
|
662
|
-
InputGroupModule,
|
|
663
|
-
InputGroupAddonModule], exports: [LocalizeLogindlgComponent] });
|
|
543
|
+
ButtonModule], exports: [LocalizeLogindlgComponent] });
|
|
664
544
|
static ɵinj = i0.ɵɵngDeclareInjector({ minVersion: "12.0.0", version: "19.0.5", ngImport: i0, type: LocalizeLogindlgModule, providers: [LocalizeLogindlgService], imports: [CommonModule,
|
|
665
545
|
ToastModule,
|
|
666
546
|
InputTextModule,
|
|
667
547
|
BrowserModule,
|
|
668
548
|
FormsModule,
|
|
669
|
-
ButtonModule
|
|
670
|
-
DynamicDialogModule,
|
|
671
|
-
InputGroupModule,
|
|
672
|
-
InputGroupAddonModule] });
|
|
549
|
+
ButtonModule] });
|
|
673
550
|
}
|
|
674
551
|
i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "19.0.5", ngImport: i0, type: LocalizeLogindlgModule, decorators: [{
|
|
675
552
|
type: NgModule,
|
|
@@ -683,18 +560,558 @@ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "19.0.5", ngImpor
|
|
|
683
560
|
BrowserModule,
|
|
684
561
|
FormsModule,
|
|
685
562
|
ButtonModule,
|
|
686
|
-
DynamicDialogModule,
|
|
687
|
-
InputGroupModule,
|
|
688
|
-
InputGroupAddonModule
|
|
689
563
|
],
|
|
690
564
|
providers: [LocalizeLogindlgService],
|
|
691
565
|
schemas: [CUSTOM_ELEMENTS_SCHEMA],
|
|
692
566
|
}]
|
|
693
567
|
}] });
|
|
694
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
|
+
|
|
695
1112
|
/**
|
|
696
1113
|
* Generated bundle index. Do not edit.
|
|
697
1114
|
*/
|
|
698
1115
|
|
|
699
|
-
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 };
|
|
700
1117
|
//# sourceMappingURL=sambath999-localize-token.mjs.map
|