@acorex/connectivity 20.2.0-next.1 → 20.2.0-next.2
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/api/index.d.ts +23 -13
- package/fesm2022/acorex-connectivity-api.mjs +694 -586
- package/fesm2022/acorex-connectivity-api.mjs.map +1 -1
- package/fesm2022/acorex-connectivity-mock.mjs +4959 -4647
- package/fesm2022/acorex-connectivity-mock.mjs.map +1 -1
- package/fesm2022/acorex-connectivity-utils.mjs +64 -0
- package/fesm2022/acorex-connectivity-utils.mjs.map +1 -0
- package/mock/index.d.ts +75 -12
- package/package.json +9 -5
- package/utils/README.md +3 -0
- package/utils/index.d.ts +17 -0
|
@@ -1,19 +1,20 @@
|
|
|
1
|
-
import { AXP_ROOT_CONFIG_TOKEN, AXPFilterOperatorMiddlewareService, AXPFileStorageService, AXPFileStorageStatus
|
|
1
|
+
import { AXP_ROOT_CONFIG_TOKEN, AXPFilterOperatorMiddlewareService, AXPRegionalService, AXPFileStorageService, AXPFileStorageStatus } from '@acorex/platform/common';
|
|
2
2
|
import { AXPEntityResolver, AXPEntityStorageService } from '@acorex/platform/layout/entity';
|
|
3
3
|
import * as i1 from '@angular/common/http';
|
|
4
4
|
import { HttpParams, HttpClient, HttpHeaders } from '@angular/common/http';
|
|
5
5
|
import * as i0 from '@angular/core';
|
|
6
6
|
import { inject, Injectable, NgModule } from '@angular/core';
|
|
7
7
|
import { kebabCase } from 'lodash-es';
|
|
8
|
-
import { firstValueFrom, map, BehaviorSubject, tap, filter, take,
|
|
8
|
+
import { firstValueFrom, catchError, of, map, BehaviorSubject, tap, filter, take, switchMap, delay } from 'rxjs';
|
|
9
9
|
import * as i2 from '@acorex/platform/auth';
|
|
10
|
-
import { AXPSessionService, AXPAuthModule, AXP_APPLICATION_LOADER, AXP_PERMISSION_LOADER, AXP_FEATURE_LOADER } from '@acorex/platform/auth';
|
|
10
|
+
import { AXPAuthStrategy, AXPSessionService, JwtUtil, TimeUtil, PkceUtil, AXPAuthModule, AXP_TENANT_LOADER, AXP_APPLICATION_LOADER, AXP_PERMISSION_LOADER, AXP_FEATURE_LOADER } from '@acorex/platform/auth';
|
|
11
11
|
import { STRATEGY_CONFIG_TOKEN } from '@acorex/platform/widgets';
|
|
12
12
|
import * as i1$1 from 'angular-oauth2-oidc';
|
|
13
13
|
import { OAuthService, OAuthModule } from 'angular-oauth2-oidc';
|
|
14
|
-
import { AXM_AUTH_CONFIG_TOKEN } from '@acorex/modules/auth';
|
|
15
14
|
import { AXUSLocaleProfile, AXIRLocaleProfile } from '@acorex/core/locale';
|
|
16
15
|
import { AXTranslationService } from '@acorex/core/translation';
|
|
16
|
+
import { AXM_AUTH_CONFIG_TOKEN } from '@acorex/modules/auth';
|
|
17
|
+
import { Router } from '@angular/router';
|
|
17
18
|
|
|
18
19
|
class AXCApiEntityStorageService {
|
|
19
20
|
constructor(http) {
|
|
@@ -138,386 +139,252 @@ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "20.1.3", ngImpor
|
|
|
138
139
|
type: Injectable
|
|
139
140
|
}], ctorParameters: () => [{ type: i1.HttpClient }] });
|
|
140
141
|
|
|
141
|
-
class
|
|
142
|
-
constructor(http) {
|
|
143
|
-
this.http = http;
|
|
144
|
-
this.configs = inject(AXP_ROOT_CONFIG_TOKEN);
|
|
145
|
-
this.apiGetApps = `${this.configs.baseUrl}/applications/applications-for-current-tenant`;
|
|
146
|
-
this.apiSetApp = `${this.configs.baseUrl}/SetApplication`;
|
|
147
|
-
}
|
|
148
|
-
getList() {
|
|
149
|
-
return this.http.get(this.apiGetApps).pipe(map((response) => {
|
|
150
|
-
return response.items.map((item) => this.mapToAXPApplication(item));
|
|
151
|
-
}));
|
|
152
|
-
}
|
|
153
|
-
set(application) {
|
|
154
|
-
return Promise.resolve();
|
|
155
|
-
}
|
|
156
|
-
// //TODO: shoud be removed
|
|
157
|
-
// set(application: AXPApplication): Observable<AXPRefreshTokenResult> {
|
|
158
|
-
// return this.http.post<any>(this.apiSetApp, { applicationId: application.id }).pipe(
|
|
159
|
-
// map((response) => {
|
|
160
|
-
// return {
|
|
161
|
-
// succeed: true,
|
|
162
|
-
// data: {
|
|
163
|
-
// accessToken: response.token,
|
|
164
|
-
// refreshToken: response.token,
|
|
165
|
-
// }
|
|
166
|
-
// };
|
|
167
|
-
// })
|
|
168
|
-
// );
|
|
169
|
-
// }
|
|
170
|
-
mapToAXPApplication(item) {
|
|
171
|
-
return {
|
|
172
|
-
id: item.id,
|
|
173
|
-
name: item.name || 'defaultName',
|
|
174
|
-
title: item.title || 'defaultTitle',
|
|
175
|
-
version: item.version || '1.0.0',
|
|
176
|
-
description: item.description,
|
|
177
|
-
logo: item.logo, // Assuming logo is of type AXPLogoConfig or undefined
|
|
178
|
-
editionName: item.editionName,
|
|
179
|
-
// features: item.features || [],
|
|
180
|
-
};
|
|
181
|
-
}
|
|
182
|
-
static { this.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "20.1.3", ngImport: i0, type: AXMOidcApplicationLoader, deps: [{ token: i1.HttpClient }], target: i0.ɵɵFactoryTarget.Injectable }); }
|
|
183
|
-
static { this.ɵprov = i0.ɵɵngDeclareInjectable({ minVersion: "12.0.0", version: "20.1.3", ngImport: i0, type: AXMOidcApplicationLoader }); }
|
|
184
|
-
}
|
|
185
|
-
i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "20.1.3", ngImport: i0, type: AXMOidcApplicationLoader, decorators: [{
|
|
186
|
-
type: Injectable
|
|
187
|
-
}], ctorParameters: () => [{ type: i1.HttpClient }] });
|
|
188
|
-
|
|
189
|
-
class AXMConfigurationService {
|
|
190
|
-
constructor(http) {
|
|
191
|
-
this.http = http;
|
|
192
|
-
this.configs = inject(AXP_ROOT_CONFIG_TOKEN);
|
|
193
|
-
this.applicationConfig = null;
|
|
194
|
-
this.apiGetConfig = `${this.configs.baseUrl}/abp/application-configuration`;
|
|
195
|
-
this.fetchInProgress = false;
|
|
196
|
-
this.configSubject = new BehaviorSubject(null);
|
|
197
|
-
this.init().subscribe(); // Automatically trigger configuration load on service instantiation
|
|
198
|
-
}
|
|
199
|
-
init() {
|
|
200
|
-
if (!this.fetchInProgress) {
|
|
201
|
-
this.fetchInProgress = true;
|
|
202
|
-
return this.http.get(this.apiGetConfig).pipe(tap((response) => {
|
|
203
|
-
this.applicationConfig = response;
|
|
204
|
-
this.configSubject.next(this.applicationConfig);
|
|
205
|
-
this.fetchInProgress = false;
|
|
206
|
-
}));
|
|
207
|
-
}
|
|
208
|
-
else {
|
|
209
|
-
// Adjusted approach to handle TypeScript's type safety requirements
|
|
210
|
-
return this.configSubject.asObservable().pipe(filter((config) => config !== null), take(1) // Ensures it completes after emitting the first non-null value
|
|
211
|
-
);
|
|
212
|
-
}
|
|
213
|
-
}
|
|
214
|
-
getConfig() {
|
|
215
|
-
if (this.applicationConfig) {
|
|
216
|
-
// If the config is already loaded, return it immediately
|
|
217
|
-
return of(this.applicationConfig);
|
|
218
|
-
}
|
|
219
|
-
else {
|
|
220
|
-
// If the config is not loaded, initiate loading
|
|
221
|
-
return this.configSubject.asObservable().pipe(filter((config) => config !== null), take(1), // Ensure it only emits the first non-null value and completes
|
|
222
|
-
switchMap(() => of(this.applicationConfig)));
|
|
223
|
-
}
|
|
224
|
-
}
|
|
225
|
-
static { this.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "20.1.3", ngImport: i0, type: AXMConfigurationService, deps: [{ token: i1.HttpClient }], target: i0.ɵɵFactoryTarget.Injectable }); }
|
|
226
|
-
static { this.ɵprov = i0.ɵɵngDeclareInjectable({ minVersion: "12.0.0", version: "20.1.3", ngImport: i0, type: AXMConfigurationService, providedIn: 'root' }); }
|
|
227
|
-
}
|
|
228
|
-
i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "20.1.3", ngImport: i0, type: AXMConfigurationService, decorators: [{
|
|
229
|
-
type: Injectable,
|
|
230
|
-
args: [{
|
|
231
|
-
providedIn: 'root',
|
|
232
|
-
}]
|
|
233
|
-
}], ctorParameters: () => [{ type: i1.HttpClient }] });
|
|
234
|
-
|
|
235
|
-
class AXMOidcFeatureLoader {
|
|
142
|
+
class AXCRegionalApiService extends AXPRegionalService {
|
|
236
143
|
constructor() {
|
|
237
|
-
|
|
144
|
+
super(...arguments);
|
|
145
|
+
this.http = inject(HttpClient);
|
|
146
|
+
this.languageService = inject(AXTranslationService);
|
|
147
|
+
//#region ---- API Endpoints ----
|
|
148
|
+
this.baseUrl = '/api/regional';
|
|
149
|
+
//#endregion
|
|
150
|
+
//#region ---- Fallback Data ----
|
|
151
|
+
this.fallbackCountries = [
|
|
238
152
|
{
|
|
239
|
-
|
|
240
|
-
title: '
|
|
241
|
-
|
|
153
|
+
code: 'US',
|
|
154
|
+
title: 'United States',
|
|
155
|
+
native: 'United States',
|
|
156
|
+
regional: 'en',
|
|
157
|
+
timezone: 'America/New_York'
|
|
242
158
|
},
|
|
243
159
|
{
|
|
244
|
-
|
|
245
|
-
title: '
|
|
246
|
-
|
|
160
|
+
code: 'CA',
|
|
161
|
+
title: 'Canada',
|
|
162
|
+
native: 'Canada',
|
|
163
|
+
regional: 'en',
|
|
164
|
+
timezone: 'America/Toronto'
|
|
165
|
+
},
|
|
166
|
+
{
|
|
167
|
+
code: 'GB',
|
|
168
|
+
title: 'United Kingdom',
|
|
169
|
+
native: 'United Kingdom',
|
|
170
|
+
regional: 'en',
|
|
171
|
+
timezone: 'Europe/London'
|
|
247
172
|
}
|
|
248
173
|
];
|
|
249
|
-
|
|
250
|
-
|
|
251
|
-
|
|
252
|
-
|
|
253
|
-
|
|
254
|
-
|
|
255
|
-
|
|
256
|
-
|
|
257
|
-
|
|
258
|
-
|
|
259
|
-
|
|
260
|
-
|
|
261
|
-
|
|
262
|
-
|
|
263
|
-
|
|
264
|
-
|
|
265
|
-
|
|
266
|
-
|
|
267
|
-
}
|
|
268
|
-
this.authConfig = this.aXMAuthConfigs.authConfig;
|
|
269
|
-
}
|
|
270
|
-
this.oauthService.configure(this.authConfig);
|
|
271
|
-
this.oauthService.setStorage(localStorage);
|
|
272
|
-
this.openidConfigurationInfo = await this.oauthService.loadDiscoveryDocument();
|
|
273
|
-
if (!this.openidConfigurationInfo) {
|
|
274
|
-
throw new Error('openidConfigurationInfo is missing');
|
|
275
|
-
}
|
|
276
|
-
this.oauthService.events.subscribe(async (event) => {
|
|
277
|
-
// console.log('event', event);
|
|
278
|
-
// if (event.type === 'token_received') {
|
|
279
|
-
// console.log('Token has been refreshed');
|
|
280
|
-
// }
|
|
281
|
-
// if (event.type === 'token_expires') {
|
|
282
|
-
// console.log('Token is about to expire. Triggering silent refresh...');
|
|
283
|
-
// }
|
|
284
|
-
});
|
|
285
|
-
const oidcJson = localStorage.getItem(AXPSessionService.SESSION_KEY);
|
|
286
|
-
if (oidcJson) {
|
|
287
|
-
const authData = JSON.parse(oidcJson);
|
|
288
|
-
if (authData) {
|
|
289
|
-
this.setServiceProps(authData);
|
|
290
|
-
if (authData.expiresIn && new Date(authData.expiresIn) < new Date()) {
|
|
291
|
-
if (authData.expiresIn) {
|
|
292
|
-
// this.refresh();
|
|
293
|
-
}
|
|
294
|
-
else {
|
|
295
|
-
this.logout();
|
|
296
|
-
}
|
|
297
|
-
}
|
|
298
|
-
}
|
|
299
|
-
}
|
|
300
|
-
}
|
|
301
|
-
async signin(credentials) {
|
|
302
|
-
await this.configureOAuth();
|
|
303
|
-
try {
|
|
304
|
-
const body = new HttpParams()
|
|
305
|
-
.set('grant_type', 'password')
|
|
306
|
-
.set('client_id', this.authConfig.clientId)
|
|
307
|
-
.set('client_secret', this.authConfig.dummyClientSecret)
|
|
308
|
-
.set('username', credentials.username)
|
|
309
|
-
.set('password', credentials.password)
|
|
310
|
-
.set('scope', this.authConfig.scope);
|
|
311
|
-
const headers = new HttpHeaders().set('Content-Type', 'application/x-www-form-urlencoded');
|
|
312
|
-
const response = await firstValueFrom(this.http.post(this.openidConfigurationInfo.info.discoveryDocument.token_endpoint, body.toString(), { headers }));
|
|
313
|
-
// const authData = new AuthenticationData(response);
|
|
314
|
-
this.setServiceProps({
|
|
315
|
-
accessToken: response.access_token,
|
|
316
|
-
refreshToken: response.refresh_token,
|
|
317
|
-
idToken: response.id_token,
|
|
318
|
-
expiresIn: this.calculateExpireInDate(response.expires_in ?? 0),
|
|
319
|
-
});
|
|
320
|
-
return {
|
|
321
|
-
succeed: true,
|
|
322
|
-
data: {
|
|
323
|
-
accessToken: response.access_token,
|
|
324
|
-
expiresIn: this.calculateExpireInDate(response.expires_in ?? 0),
|
|
325
|
-
idToken: response.id_token,
|
|
326
|
-
refreshToken: response.refresh_token,
|
|
327
|
-
user: {
|
|
328
|
-
id: response.sub,
|
|
329
|
-
title: response.fullname,
|
|
330
|
-
name: response.sub,
|
|
331
|
-
avatar: response.picture,
|
|
332
|
-
},
|
|
333
|
-
tenant: {
|
|
334
|
-
id: response.tenantid,
|
|
335
|
-
name: response.tenantname,
|
|
336
|
-
title: response.tenanttitle,
|
|
337
|
-
},
|
|
338
|
-
application: {
|
|
339
|
-
id: response.applicationid,
|
|
340
|
-
name: response.applicationname,
|
|
341
|
-
title: response.applicationtitle,
|
|
342
|
-
},
|
|
343
|
-
},
|
|
344
|
-
};
|
|
345
|
-
}
|
|
346
|
-
catch (error) {
|
|
347
|
-
this.handleError(error);
|
|
348
|
-
}
|
|
349
|
-
}
|
|
350
|
-
async signout() {
|
|
351
|
-
//this.logout();
|
|
352
|
-
}
|
|
353
|
-
async refreshToken(context) {
|
|
354
|
-
try {
|
|
355
|
-
await this.configureOAuth();
|
|
356
|
-
const refreshResult = await this.refresh(context.tenant?.id, context.application?.id);
|
|
357
|
-
if (refreshResult) {
|
|
358
|
-
return {
|
|
359
|
-
succeed: true,
|
|
360
|
-
data: {
|
|
361
|
-
accessToken: this.oauthService.getAccessToken(),
|
|
362
|
-
refreshToken: this.oauthService.getRefreshToken(),
|
|
363
|
-
},
|
|
364
|
-
};
|
|
174
|
+
this.fallbackProvinces = [
|
|
175
|
+
{
|
|
176
|
+
code: 'CA',
|
|
177
|
+
title: 'California',
|
|
178
|
+
native: 'California',
|
|
179
|
+
timezone: 'America/Los_Angeles'
|
|
180
|
+
},
|
|
181
|
+
{
|
|
182
|
+
code: 'NY',
|
|
183
|
+
title: 'New York',
|
|
184
|
+
native: 'New York',
|
|
185
|
+
timezone: 'America/New_York'
|
|
186
|
+
},
|
|
187
|
+
{
|
|
188
|
+
code: 'ON',
|
|
189
|
+
title: 'Ontario',
|
|
190
|
+
native: 'Ontario',
|
|
191
|
+
timezone: 'America/Toronto'
|
|
365
192
|
}
|
|
366
|
-
|
|
367
|
-
|
|
193
|
+
];
|
|
194
|
+
this.fallbackCities = [
|
|
195
|
+
{
|
|
196
|
+
code: 'NYC',
|
|
197
|
+
title: 'New York City',
|
|
198
|
+
native: 'New York City',
|
|
199
|
+
timezone: 'America/New_York'
|
|
200
|
+
},
|
|
201
|
+
{
|
|
202
|
+
code: 'LA',
|
|
203
|
+
title: 'Los Angeles',
|
|
204
|
+
native: 'Los Angeles',
|
|
205
|
+
timezone: 'America/Los_Angeles'
|
|
206
|
+
},
|
|
207
|
+
{
|
|
208
|
+
code: 'TOR',
|
|
209
|
+
title: 'Toronto',
|
|
210
|
+
native: 'Toronto',
|
|
211
|
+
timezone: 'America/Toronto'
|
|
368
212
|
}
|
|
369
|
-
|
|
370
|
-
|
|
371
|
-
|
|
372
|
-
|
|
373
|
-
|
|
213
|
+
];
|
|
214
|
+
this.fallbackCurrencies = [
|
|
215
|
+
{
|
|
216
|
+
code: 'USD',
|
|
217
|
+
title: 'United States Dollar',
|
|
218
|
+
symbol: '$',
|
|
219
|
+
format: '${amount}'
|
|
220
|
+
},
|
|
221
|
+
{
|
|
222
|
+
code: 'CAD',
|
|
223
|
+
title: 'Canadian Dollar',
|
|
224
|
+
symbol: 'CA$',
|
|
225
|
+
format: 'CA${amount}'
|
|
226
|
+
},
|
|
227
|
+
{
|
|
228
|
+
code: 'GBP',
|
|
229
|
+
title: 'British Pound',
|
|
230
|
+
symbol: '£',
|
|
231
|
+
format: '£{amount}'
|
|
232
|
+
}
|
|
233
|
+
];
|
|
234
|
+
this.fallbackLocaleProfiles = [
|
|
235
|
+
{
|
|
236
|
+
...AXUSLocaleProfile,
|
|
237
|
+
code: 'en-US',
|
|
238
|
+
title: 'English (United States)',
|
|
239
|
+
nativeTitle: 'English (United States)',
|
|
240
|
+
},
|
|
241
|
+
{
|
|
242
|
+
...AXIRLocaleProfile,
|
|
243
|
+
code: 'fa-IR',
|
|
244
|
+
title: 'Persian (Iran)',
|
|
245
|
+
nativeTitle: 'فارسی (ایران)',
|
|
246
|
+
}
|
|
247
|
+
];
|
|
248
|
+
this.fallbackLanguages = [
|
|
249
|
+
{
|
|
250
|
+
code: 'en',
|
|
251
|
+
title: 'English'
|
|
252
|
+
},
|
|
253
|
+
{
|
|
254
|
+
code: 'fa',
|
|
255
|
+
title: 'Persian'
|
|
256
|
+
},
|
|
257
|
+
{
|
|
258
|
+
code: 'es',
|
|
259
|
+
title: 'Spanish'
|
|
260
|
+
}
|
|
261
|
+
];
|
|
262
|
+
this.fallbackTimeZones = [
|
|
263
|
+
{
|
|
264
|
+
code: 'America/New_York',
|
|
265
|
+
title: 'Eastern Time (US & Canada)',
|
|
266
|
+
offset: '-05:00',
|
|
267
|
+
iana: 'America/New_York',
|
|
268
|
+
abbr: 'EST'
|
|
269
|
+
},
|
|
270
|
+
{
|
|
271
|
+
code: 'America/Los_Angeles',
|
|
272
|
+
title: 'Pacific Time (US & Canada)',
|
|
273
|
+
offset: '-08:00',
|
|
274
|
+
iana: 'America/Los_Angeles',
|
|
275
|
+
abbr: 'PST'
|
|
276
|
+
},
|
|
277
|
+
{
|
|
278
|
+
code: 'Europe/London',
|
|
279
|
+
title: 'Greenwich Mean Time',
|
|
280
|
+
offset: '+00:00',
|
|
281
|
+
iana: 'Europe/London',
|
|
282
|
+
abbr: 'GMT'
|
|
283
|
+
}
|
|
284
|
+
];
|
|
374
285
|
}
|
|
375
|
-
|
|
376
|
-
|
|
377
|
-
const
|
|
378
|
-
if (!authData)
|
|
379
|
-
return false;
|
|
380
|
-
const refreshToken = this.oauthService.getRefreshToken();
|
|
381
|
-
if (!refreshToken)
|
|
382
|
-
return false;
|
|
383
|
-
const body = new HttpParams()
|
|
384
|
-
.set('grant_type', 'refresh_token')
|
|
385
|
-
.set('client_id', this.authConfig.clientId)
|
|
386
|
-
.set('client_secret', this.authConfig.dummyClientSecret)
|
|
387
|
-
.set('refresh_token', refreshToken)
|
|
388
|
-
.set('tenantId', tenantId ?? '')
|
|
389
|
-
.set('applicationId', applicationId ?? '');
|
|
390
|
-
const headers = new HttpHeaders().set('Content-Type', 'application/x-www-form-urlencoded');
|
|
286
|
+
//#endregion
|
|
287
|
+
async getCountries() {
|
|
288
|
+
const lang = await firstValueFrom(this.languageService.langChanges$);
|
|
391
289
|
try {
|
|
392
|
-
const
|
|
393
|
-
|
|
394
|
-
|
|
395
|
-
|
|
396
|
-
|
|
397
|
-
|
|
290
|
+
const countries = await firstValueFrom(this.http.get(`${this.baseUrl}/countries`).pipe(catchError(() => of(this.fallbackCountries))));
|
|
291
|
+
return countries.map((country) => {
|
|
292
|
+
if (lang == country.regional) {
|
|
293
|
+
return {
|
|
294
|
+
...country,
|
|
295
|
+
title: country.native,
|
|
296
|
+
};
|
|
297
|
+
}
|
|
298
|
+
else {
|
|
299
|
+
return country;
|
|
300
|
+
}
|
|
398
301
|
});
|
|
399
|
-
return true;
|
|
400
302
|
}
|
|
401
|
-
catch
|
|
402
|
-
|
|
403
|
-
|
|
404
|
-
|
|
405
|
-
|
|
406
|
-
|
|
407
|
-
|
|
408
|
-
|
|
409
|
-
|
|
410
|
-
|
|
411
|
-
|
|
412
|
-
|
|
413
|
-
this.oauthService.getIdToken = () => authData.idToken ?? '';
|
|
414
|
-
this.oauthService.getRefreshToken = () => authData.refreshToken;
|
|
415
|
-
if (authData.expiresIn) {
|
|
416
|
-
const refreshTime = this.expires_in_milisecound(authData.expiresIn);
|
|
417
|
-
this.oauthService.getAccessTokenExpiration = () => refreshTime;
|
|
418
|
-
// if (refreshTime < 0) {
|
|
419
|
-
// this.refresh();
|
|
420
|
-
// }else{
|
|
421
|
-
// }
|
|
303
|
+
catch {
|
|
304
|
+
return this.fallbackCountries.map((country) => {
|
|
305
|
+
if (lang == country.regional) {
|
|
306
|
+
return {
|
|
307
|
+
...country,
|
|
308
|
+
title: country.native,
|
|
309
|
+
};
|
|
310
|
+
}
|
|
311
|
+
else {
|
|
312
|
+
return country;
|
|
313
|
+
}
|
|
314
|
+
});
|
|
422
315
|
}
|
|
423
316
|
}
|
|
424
|
-
|
|
425
|
-
|
|
426
|
-
if (
|
|
427
|
-
|
|
428
|
-
const authData = JSON.parse(authDataJson);
|
|
429
|
-
// return authData ? new AuthenticationData(authData) : undefined;
|
|
430
|
-
return authData;
|
|
431
|
-
}
|
|
432
|
-
async loadUserInfo() {
|
|
433
|
-
return this.oauthService.loadUserProfile();
|
|
434
|
-
}
|
|
435
|
-
calculateExpireInDate(expireInMilisecound) {
|
|
436
|
-
return new Date(Date.now() + expireInMilisecound * 1000).toISOString();
|
|
437
|
-
}
|
|
438
|
-
logout() {
|
|
439
|
-
this.oauthService.logOut({
|
|
440
|
-
noRedirectToLogoutUrl: true,
|
|
441
|
-
});
|
|
442
|
-
}
|
|
443
|
-
handleError(error) {
|
|
444
|
-
if (error?.reason) {
|
|
445
|
-
throw new Error(JSON.stringify(error.reason));
|
|
317
|
+
async getProvinces(countryId) {
|
|
318
|
+
let params = new HttpParams();
|
|
319
|
+
if (countryId) {
|
|
320
|
+
params = params.set('countryId', countryId);
|
|
446
321
|
}
|
|
447
|
-
|
|
448
|
-
|
|
322
|
+
try {
|
|
323
|
+
return await firstValueFrom(this.http.get(`${this.baseUrl}/provinces`, { params }).pipe(catchError(() => of(this.fallbackProvinces))));
|
|
449
324
|
}
|
|
450
|
-
|
|
451
|
-
|
|
325
|
+
catch {
|
|
326
|
+
return this.fallbackProvinces;
|
|
452
327
|
}
|
|
453
328
|
}
|
|
454
|
-
|
|
455
|
-
|
|
456
|
-
|
|
457
|
-
|
|
458
|
-
|
|
459
|
-
|
|
460
|
-
|
|
461
|
-
|
|
462
|
-
|
|
463
|
-
|
|
464
|
-
|
|
465
|
-
|
|
466
|
-
|
|
467
|
-
|
|
468
|
-
this.configs = inject(AXP_ROOT_CONFIG_TOKEN);
|
|
469
|
-
this.apiGetConfig = `${this.configs.baseUrl}/abp/application-configuration`;
|
|
329
|
+
async getCities(filter) {
|
|
330
|
+
let params = new HttpParams();
|
|
331
|
+
if (filter?.countryId) {
|
|
332
|
+
params = params.set('countryId', filter.countryId);
|
|
333
|
+
}
|
|
334
|
+
if (filter?.provinceId) {
|
|
335
|
+
params = params.set('provinceId', filter.provinceId);
|
|
336
|
+
}
|
|
337
|
+
try {
|
|
338
|
+
return await firstValueFrom(this.http.get(`${this.baseUrl}/cities`, { params }).pipe(catchError(() => of(this.fallbackCities))));
|
|
339
|
+
}
|
|
340
|
+
catch {
|
|
341
|
+
return this.fallbackCities;
|
|
342
|
+
}
|
|
470
343
|
}
|
|
471
|
-
|
|
472
|
-
|
|
473
|
-
|
|
474
|
-
|
|
475
|
-
|
|
476
|
-
|
|
477
|
-
|
|
478
|
-
// return of(['asc.user.gliding']);
|
|
479
|
-
// return of(['axp.admin.console', 'asc.admin.message', 'asc.admin.settings', 'asc.admin.gliding', 'asc.user.gliding']);
|
|
344
|
+
async getCurrencies() {
|
|
345
|
+
try {
|
|
346
|
+
return await firstValueFrom(this.http.get(`${this.baseUrl}/currencies`).pipe(catchError(() => of(this.fallbackCurrencies))));
|
|
347
|
+
}
|
|
348
|
+
catch {
|
|
349
|
+
return this.fallbackCurrencies;
|
|
350
|
+
}
|
|
480
351
|
}
|
|
481
|
-
|
|
482
|
-
|
|
483
|
-
|
|
484
|
-
|
|
352
|
+
async getLocaleProfiles() {
|
|
353
|
+
try {
|
|
354
|
+
return await firstValueFrom(this.http.get(`${this.baseUrl}/locale-profiles`).pipe(catchError(() => of(this.fallbackLocaleProfiles))));
|
|
355
|
+
}
|
|
356
|
+
catch {
|
|
357
|
+
return this.fallbackLocaleProfiles;
|
|
358
|
+
}
|
|
485
359
|
}
|
|
486
|
-
|
|
487
|
-
|
|
488
|
-
}
|
|
489
|
-
|
|
490
|
-
|
|
491
|
-
|
|
492
|
-
|
|
493
|
-
class AXMOidcTenantLoader {
|
|
494
|
-
constructor(http) {
|
|
495
|
-
this.http = http;
|
|
496
|
-
this.configs = inject(AXP_ROOT_CONFIG_TOKEN);
|
|
497
|
-
this.apiGetTenants = `${this.configs.baseUrl}/tenants/available-for-user`;
|
|
360
|
+
async getLanguages() {
|
|
361
|
+
try {
|
|
362
|
+
return await firstValueFrom(this.http.get(`${this.baseUrl}/languages`).pipe(catchError(() => of(this.fallbackLanguages))));
|
|
363
|
+
}
|
|
364
|
+
catch {
|
|
365
|
+
return this.fallbackLanguages;
|
|
366
|
+
}
|
|
498
367
|
}
|
|
499
|
-
|
|
500
|
-
|
|
501
|
-
return this.
|
|
502
|
-
}
|
|
368
|
+
async getAvailableLanguages() {
|
|
369
|
+
try {
|
|
370
|
+
return await firstValueFrom(this.http.get(`${this.baseUrl}/available-languages`).pipe(catchError(() => of(this.fallbackLanguages))));
|
|
371
|
+
}
|
|
372
|
+
catch {
|
|
373
|
+
return this.fallbackLanguages;
|
|
374
|
+
}
|
|
503
375
|
}
|
|
504
|
-
async
|
|
505
|
-
return
|
|
376
|
+
async getBrowserTimeZoneCode() {
|
|
377
|
+
return Intl.DateTimeFormat().resolvedOptions().timeZone;
|
|
506
378
|
}
|
|
507
|
-
|
|
508
|
-
|
|
509
|
-
|
|
510
|
-
|
|
511
|
-
|
|
512
|
-
|
|
513
|
-
}
|
|
379
|
+
async getTimeZones() {
|
|
380
|
+
try {
|
|
381
|
+
return await firstValueFrom(this.http.get(`${this.baseUrl}/timezones`).pipe(catchError(() => of(this.fallbackTimeZones))));
|
|
382
|
+
}
|
|
383
|
+
catch {
|
|
384
|
+
return this.fallbackTimeZones;
|
|
385
|
+
}
|
|
514
386
|
}
|
|
515
|
-
static { this.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "20.1.3", ngImport: i0, type: AXMOidcTenantLoader, deps: [{ token: i1.HttpClient }], target: i0.ɵɵFactoryTarget.Injectable }); }
|
|
516
|
-
static { this.ɵprov = i0.ɵɵngDeclareInjectable({ minVersion: "12.0.0", version: "20.1.3", ngImport: i0, type: AXMOidcTenantLoader }); }
|
|
517
387
|
}
|
|
518
|
-
i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "20.1.3", ngImport: i0, type: AXMOidcTenantLoader, decorators: [{
|
|
519
|
-
type: Injectable
|
|
520
|
-
}], ctorParameters: () => [{ type: i1.HttpClient }] });
|
|
521
388
|
|
|
522
389
|
class AXCFileStorageApiService extends AXPFileStorageService {
|
|
523
390
|
constructor() {
|
|
@@ -658,252 +525,493 @@ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "20.1.3", ngImpor
|
|
|
658
525
|
type: Injectable
|
|
659
526
|
}] });
|
|
660
527
|
|
|
661
|
-
class
|
|
662
|
-
constructor() {
|
|
663
|
-
|
|
664
|
-
this.
|
|
665
|
-
this.
|
|
666
|
-
|
|
667
|
-
|
|
668
|
-
|
|
669
|
-
|
|
670
|
-
|
|
671
|
-
|
|
672
|
-
|
|
673
|
-
|
|
674
|
-
|
|
675
|
-
|
|
676
|
-
|
|
677
|
-
|
|
678
|
-
|
|
679
|
-
|
|
680
|
-
|
|
681
|
-
|
|
682
|
-
|
|
683
|
-
|
|
684
|
-
|
|
685
|
-
|
|
686
|
-
|
|
687
|
-
|
|
688
|
-
|
|
689
|
-
|
|
690
|
-
|
|
691
|
-
|
|
692
|
-
|
|
693
|
-
|
|
694
|
-
|
|
695
|
-
|
|
696
|
-
|
|
697
|
-
|
|
698
|
-
|
|
699
|
-
|
|
700
|
-
|
|
701
|
-
|
|
702
|
-
|
|
703
|
-
|
|
704
|
-
|
|
705
|
-
|
|
706
|
-
|
|
707
|
-
|
|
708
|
-
|
|
709
|
-
|
|
710
|
-
|
|
711
|
-
|
|
712
|
-
|
|
713
|
-
this.
|
|
714
|
-
|
|
715
|
-
|
|
716
|
-
|
|
717
|
-
|
|
718
|
-
|
|
719
|
-
|
|
720
|
-
|
|
721
|
-
|
|
722
|
-
|
|
723
|
-
|
|
724
|
-
|
|
725
|
-
|
|
726
|
-
|
|
727
|
-
|
|
728
|
-
|
|
729
|
-
|
|
730
|
-
|
|
731
|
-
|
|
732
|
-
|
|
733
|
-
|
|
734
|
-
|
|
735
|
-
|
|
736
|
-
|
|
737
|
-
|
|
738
|
-
|
|
739
|
-
|
|
740
|
-
|
|
741
|
-
|
|
742
|
-
|
|
743
|
-
|
|
744
|
-
|
|
745
|
-
|
|
746
|
-
|
|
747
|
-
|
|
748
|
-
|
|
749
|
-
|
|
750
|
-
|
|
751
|
-
|
|
752
|
-
|
|
753
|
-
|
|
754
|
-
|
|
755
|
-
|
|
756
|
-
|
|
757
|
-
|
|
758
|
-
nativeTitle: 'English (United States)',
|
|
759
|
-
},
|
|
760
|
-
{
|
|
761
|
-
...AXIRLocaleProfile,
|
|
762
|
-
code: 'fa-IR',
|
|
763
|
-
title: 'Persian (Iran)',
|
|
764
|
-
nativeTitle: 'فارسی (ایران)',
|
|
765
|
-
}
|
|
766
|
-
];
|
|
767
|
-
this.fallbackLanguages = [
|
|
768
|
-
{
|
|
769
|
-
code: 'en',
|
|
770
|
-
title: 'English'
|
|
771
|
-
},
|
|
772
|
-
{
|
|
773
|
-
code: 'fa',
|
|
774
|
-
title: 'Persian'
|
|
775
|
-
},
|
|
776
|
-
{
|
|
777
|
-
code: 'es',
|
|
778
|
-
title: 'Spanish'
|
|
779
|
-
}
|
|
780
|
-
];
|
|
781
|
-
this.fallbackTimeZones = [
|
|
782
|
-
{
|
|
783
|
-
code: 'America/New_York',
|
|
784
|
-
title: 'Eastern Time (US & Canada)',
|
|
785
|
-
offset: '-05:00',
|
|
786
|
-
iana: 'America/New_York',
|
|
787
|
-
abbr: 'EST'
|
|
788
|
-
},
|
|
528
|
+
class AXMOidcApplicationLoader {
|
|
529
|
+
constructor(http) {
|
|
530
|
+
this.http = http;
|
|
531
|
+
this.configs = inject(AXP_ROOT_CONFIG_TOKEN);
|
|
532
|
+
this.apiGetApps = `${this.configs.baseUrl}/applications/applications-for-current-tenant`;
|
|
533
|
+
this.apiSetApp = `${this.configs.baseUrl}/SetApplication`;
|
|
534
|
+
}
|
|
535
|
+
getList() {
|
|
536
|
+
return this.http.get(this.apiGetApps).pipe(map((response) => {
|
|
537
|
+
return response.items.map((item) => this.mapToAXPApplication(item));
|
|
538
|
+
}));
|
|
539
|
+
}
|
|
540
|
+
set(application) {
|
|
541
|
+
return Promise.resolve();
|
|
542
|
+
}
|
|
543
|
+
// //TODO: shoud be removed
|
|
544
|
+
// set(application: AXPApplication): Observable<AXPRefreshTokenResult> {
|
|
545
|
+
// return this.http.post<any>(this.apiSetApp, { applicationId: application.id }).pipe(
|
|
546
|
+
// map((response) => {
|
|
547
|
+
// return {
|
|
548
|
+
// succeed: true,
|
|
549
|
+
// data: {
|
|
550
|
+
// accessToken: response.token,
|
|
551
|
+
// refreshToken: response.token,
|
|
552
|
+
// }
|
|
553
|
+
// };
|
|
554
|
+
// })
|
|
555
|
+
// );
|
|
556
|
+
// }
|
|
557
|
+
mapToAXPApplication(item) {
|
|
558
|
+
return {
|
|
559
|
+
id: item.id,
|
|
560
|
+
name: item.name || 'defaultName',
|
|
561
|
+
title: item.title || 'defaultTitle',
|
|
562
|
+
version: item.version || '1.0.0',
|
|
563
|
+
description: item.description,
|
|
564
|
+
logo: item.logo, // Assuming logo is of type AXPLogoConfig or undefined
|
|
565
|
+
editionName: item.editionName,
|
|
566
|
+
// features: item.features || [],
|
|
567
|
+
};
|
|
568
|
+
}
|
|
569
|
+
static { this.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "20.1.3", ngImport: i0, type: AXMOidcApplicationLoader, deps: [{ token: i1.HttpClient }], target: i0.ɵɵFactoryTarget.Injectable }); }
|
|
570
|
+
static { this.ɵprov = i0.ɵɵngDeclareInjectable({ minVersion: "12.0.0", version: "20.1.3", ngImport: i0, type: AXMOidcApplicationLoader }); }
|
|
571
|
+
}
|
|
572
|
+
i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "20.1.3", ngImport: i0, type: AXMOidcApplicationLoader, decorators: [{
|
|
573
|
+
type: Injectable
|
|
574
|
+
}], ctorParameters: () => [{ type: i1.HttpClient }] });
|
|
575
|
+
|
|
576
|
+
class AXMConfigurationService {
|
|
577
|
+
constructor(http) {
|
|
578
|
+
this.http = http;
|
|
579
|
+
this.configs = inject(AXP_ROOT_CONFIG_TOKEN);
|
|
580
|
+
this.applicationConfig = null;
|
|
581
|
+
this.apiGetConfig = `${this.configs.baseUrl}/abp/application-configuration`;
|
|
582
|
+
this.fetchInProgress = false;
|
|
583
|
+
this.configSubject = new BehaviorSubject(null);
|
|
584
|
+
this.init().subscribe(); // Automatically trigger configuration load on service instantiation
|
|
585
|
+
}
|
|
586
|
+
init() {
|
|
587
|
+
if (!this.fetchInProgress) {
|
|
588
|
+
this.fetchInProgress = true;
|
|
589
|
+
return this.http.get(this.apiGetConfig).pipe(tap((response) => {
|
|
590
|
+
this.applicationConfig = response;
|
|
591
|
+
this.configSubject.next(this.applicationConfig);
|
|
592
|
+
this.fetchInProgress = false;
|
|
593
|
+
}));
|
|
594
|
+
}
|
|
595
|
+
else {
|
|
596
|
+
// Adjusted approach to handle TypeScript's type safety requirements
|
|
597
|
+
return this.configSubject.asObservable().pipe(filter((config) => config !== null), take(1) // Ensures it completes after emitting the first non-null value
|
|
598
|
+
);
|
|
599
|
+
}
|
|
600
|
+
}
|
|
601
|
+
getConfig() {
|
|
602
|
+
if (this.applicationConfig) {
|
|
603
|
+
// If the config is already loaded, return it immediately
|
|
604
|
+
return of(this.applicationConfig);
|
|
605
|
+
}
|
|
606
|
+
else {
|
|
607
|
+
// If the config is not loaded, initiate loading
|
|
608
|
+
return this.configSubject.asObservable().pipe(filter((config) => config !== null), take(1), // Ensure it only emits the first non-null value and completes
|
|
609
|
+
switchMap(() => of(this.applicationConfig)));
|
|
610
|
+
}
|
|
611
|
+
}
|
|
612
|
+
static { this.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "20.1.3", ngImport: i0, type: AXMConfigurationService, deps: [{ token: i1.HttpClient }], target: i0.ɵɵFactoryTarget.Injectable }); }
|
|
613
|
+
static { this.ɵprov = i0.ɵɵngDeclareInjectable({ minVersion: "12.0.0", version: "20.1.3", ngImport: i0, type: AXMConfigurationService, providedIn: 'root' }); }
|
|
614
|
+
}
|
|
615
|
+
i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "20.1.3", ngImport: i0, type: AXMConfigurationService, decorators: [{
|
|
616
|
+
type: Injectable,
|
|
617
|
+
args: [{
|
|
618
|
+
providedIn: 'root',
|
|
619
|
+
}]
|
|
620
|
+
}], ctorParameters: () => [{ type: i1.HttpClient }] });
|
|
621
|
+
|
|
622
|
+
class AXMOidcFeatureLoader {
|
|
623
|
+
constructor() {
|
|
624
|
+
this.list = [
|
|
789
625
|
{
|
|
790
|
-
|
|
791
|
-
title: '
|
|
792
|
-
|
|
793
|
-
iana: 'America/Los_Angeles',
|
|
794
|
-
abbr: 'PST'
|
|
626
|
+
name: 'axp-entity-list-custom-view',
|
|
627
|
+
title: 'Custom View',
|
|
628
|
+
value: false
|
|
795
629
|
},
|
|
796
630
|
{
|
|
797
|
-
|
|
798
|
-
title: '
|
|
799
|
-
|
|
800
|
-
iana: 'Europe/London',
|
|
801
|
-
abbr: 'GMT'
|
|
631
|
+
name: 'axp-entity-list-quick-search',
|
|
632
|
+
title: 'Custom View',
|
|
633
|
+
value: false
|
|
802
634
|
}
|
|
803
635
|
];
|
|
804
636
|
}
|
|
805
|
-
|
|
806
|
-
|
|
807
|
-
const lang = await firstValueFrom(this.languageService.langChanges$);
|
|
808
|
-
try {
|
|
809
|
-
const countries = await firstValueFrom(this.http.get(`${this.baseUrl}/countries`).pipe(catchError(() => of(this.fallbackCountries))));
|
|
810
|
-
return countries.map((country) => {
|
|
811
|
-
if (lang == country.regional) {
|
|
812
|
-
return {
|
|
813
|
-
...country,
|
|
814
|
-
title: country.native,
|
|
815
|
-
};
|
|
816
|
-
}
|
|
817
|
-
else {
|
|
818
|
-
return country;
|
|
819
|
-
}
|
|
820
|
-
});
|
|
821
|
-
}
|
|
822
|
-
catch {
|
|
823
|
-
return this.fallbackCountries.map((country) => {
|
|
824
|
-
if (lang == country.regional) {
|
|
825
|
-
return {
|
|
826
|
-
...country,
|
|
827
|
-
title: country.native,
|
|
828
|
-
};
|
|
829
|
-
}
|
|
830
|
-
else {
|
|
831
|
-
return country;
|
|
832
|
-
}
|
|
833
|
-
});
|
|
834
|
-
}
|
|
637
|
+
getList() {
|
|
638
|
+
return of(this.list).pipe(delay(0));
|
|
835
639
|
}
|
|
836
|
-
|
|
837
|
-
|
|
838
|
-
|
|
839
|
-
|
|
640
|
+
}
|
|
641
|
+
|
|
642
|
+
//#endregion
|
|
643
|
+
class AXCAPIOidcStrategy extends AXPAuthStrategy {
|
|
644
|
+
constructor() {
|
|
645
|
+
super(...arguments);
|
|
646
|
+
this.aXMAuthConfigs = inject(AXM_AUTH_CONFIG_TOKEN);
|
|
647
|
+
this.oauthService = inject(OAuthService);
|
|
648
|
+
this.http = inject(HttpClient);
|
|
649
|
+
this.sessionService = inject(AXPSessionService);
|
|
650
|
+
this.router = inject(Router);
|
|
651
|
+
}
|
|
652
|
+
async configureOAuth() {
|
|
653
|
+
if (this.openidConfigurationInfo)
|
|
654
|
+
return;
|
|
655
|
+
if (!this.authConfig) {
|
|
656
|
+
if (!this.aXMAuthConfigs.authConfig) {
|
|
657
|
+
throw new Error('authConfig is missing');
|
|
658
|
+
}
|
|
659
|
+
this.authConfig = this.aXMAuthConfigs.authConfig;
|
|
840
660
|
}
|
|
841
|
-
|
|
842
|
-
|
|
661
|
+
this.oauthService.configure(this.authConfig);
|
|
662
|
+
this.oauthService.setStorage(localStorage);
|
|
663
|
+
this.openidConfigurationInfo = await this.oauthService.loadDiscoveryDocument();
|
|
664
|
+
if (!this.openidConfigurationInfo) {
|
|
665
|
+
throw new Error('openidConfigurationInfo is missing');
|
|
843
666
|
}
|
|
844
|
-
|
|
845
|
-
|
|
667
|
+
this.oauthService.events.subscribe(async (event) => {
|
|
668
|
+
// console.log('event', event);
|
|
669
|
+
// if (event.type === 'token_received') {
|
|
670
|
+
// console.log('Token has been refreshed');
|
|
671
|
+
// }
|
|
672
|
+
// if (event.type === 'token_expires') {
|
|
673
|
+
// console.log('Token is about to expire. Triggering silent refresh...');
|
|
674
|
+
// }
|
|
675
|
+
});
|
|
676
|
+
const oidcJson = localStorage.getItem(AXPSessionService.SESSION_KEY);
|
|
677
|
+
if (oidcJson) {
|
|
678
|
+
const authData = JSON.parse(oidcJson);
|
|
679
|
+
if (authData) {
|
|
680
|
+
this.sessionService.setSession(authData);
|
|
681
|
+
if (authData.expiresIn && new Date(authData.expiresIn) < new Date()) {
|
|
682
|
+
if (authData.expiresIn) {
|
|
683
|
+
this.sessionService.refreshToken();
|
|
684
|
+
}
|
|
685
|
+
else {
|
|
686
|
+
this.signout();
|
|
687
|
+
}
|
|
688
|
+
}
|
|
689
|
+
}
|
|
846
690
|
}
|
|
847
691
|
}
|
|
848
|
-
async
|
|
849
|
-
|
|
850
|
-
if (
|
|
851
|
-
|
|
692
|
+
async signin(credentials) {
|
|
693
|
+
// If OIDC with username/password
|
|
694
|
+
if (credentials.strategy === 'oidc' && credentials.username && credentials.password) {
|
|
695
|
+
await this.handleOidcPasswordSignin(credentials);
|
|
696
|
+
await new Promise(() => { }); // Keeps the promise pending until another flow (e.g., OAuth callback) completes
|
|
852
697
|
}
|
|
853
|
-
|
|
854
|
-
|
|
698
|
+
throw new Error(`Authentication method or credentials not supported: ${credentials.strategy}`);
|
|
699
|
+
}
|
|
700
|
+
async handleOidcPasswordSignin(credentials) {
|
|
701
|
+
await this.configureOAuth();
|
|
702
|
+
const loginRes = await fetch(this.authConfig.issuer + '/api/auth/manual-login', {
|
|
703
|
+
method: 'POST',
|
|
704
|
+
headers: { 'Content-Type': 'application/json' },
|
|
705
|
+
body: JSON.stringify({ username: credentials.username, password: credentials.password }),
|
|
706
|
+
credentials: 'include',
|
|
707
|
+
});
|
|
708
|
+
if (!loginRes.ok) {
|
|
709
|
+
let errorText = 'Login failed';
|
|
710
|
+
try {
|
|
711
|
+
const errorJson = await loginRes.json();
|
|
712
|
+
if (errorJson && errorJson.error && errorJson.error.description) {
|
|
713
|
+
errorText = errorJson.error.description;
|
|
714
|
+
}
|
|
715
|
+
}
|
|
716
|
+
catch {
|
|
717
|
+
try {
|
|
718
|
+
const text = await loginRes.text();
|
|
719
|
+
if (text) {
|
|
720
|
+
errorText = text;
|
|
721
|
+
}
|
|
722
|
+
}
|
|
723
|
+
catch { }
|
|
724
|
+
}
|
|
725
|
+
throw new Error(errorText);
|
|
855
726
|
}
|
|
856
|
-
|
|
857
|
-
|
|
727
|
+
// Check if response is JSON or text
|
|
728
|
+
const contentType = loginRes.headers.get('content-type');
|
|
729
|
+
let result;
|
|
730
|
+
if (contentType && contentType.includes('application/json')) {
|
|
731
|
+
result = await loginRes.json();
|
|
858
732
|
}
|
|
859
|
-
|
|
860
|
-
|
|
733
|
+
else {
|
|
734
|
+
// Handle text response (like "Login successful")
|
|
735
|
+
const responseText = await loginRes.text();
|
|
736
|
+
console.log('Server response:', responseText);
|
|
861
737
|
}
|
|
738
|
+
await this.updateToken({});
|
|
862
739
|
}
|
|
863
|
-
async
|
|
740
|
+
async updateToken(params) {
|
|
864
741
|
try {
|
|
865
|
-
|
|
742
|
+
// Ensure OAuth is configured first
|
|
743
|
+
if (!this.openidConfigurationInfo) {
|
|
744
|
+
await this.configureOAuth();
|
|
745
|
+
}
|
|
746
|
+
// get Token Code
|
|
747
|
+
if (params['code']) {
|
|
748
|
+
// If params contains 'code', exchange it for tokens using the OpenIddict token endpoint
|
|
749
|
+
const code = params['code'];
|
|
750
|
+
const redirectUri = params['redirectUri'] || this.authConfig.redirectUri;
|
|
751
|
+
const clientId = params['clientId'] || this.authConfig.clientId;
|
|
752
|
+
const tokenEndpoint = params['tokenEndpoint'] ||
|
|
753
|
+
this.openidConfigurationInfo?.info?.discoveryDocument?.token_endpoint ||
|
|
754
|
+
`${this.aXMAuthConfigs?.authConfig?.issuer}/connect/token`;
|
|
755
|
+
// Get code_verifier from localStorage (PKCE)
|
|
756
|
+
const codeVerifier = localStorage.getItem('pkce_code_verifier');
|
|
757
|
+
localStorage.removeItem('pkce_code_verifier');
|
|
758
|
+
if (!codeVerifier) {
|
|
759
|
+
throw new Error('Code verifier not found. Please try signing in again.');
|
|
760
|
+
}
|
|
761
|
+
// Prepare body for token request
|
|
762
|
+
const body = new URLSearchParams({
|
|
763
|
+
grant_type: 'authorization_code',
|
|
764
|
+
client_id: clientId,
|
|
765
|
+
code_verifier: codeVerifier,
|
|
766
|
+
code: code,
|
|
767
|
+
redirect_uri: redirectUri,
|
|
768
|
+
});
|
|
769
|
+
// Call the token endpoint (OpenIddict)
|
|
770
|
+
const response = await fetch(tokenEndpoint, {
|
|
771
|
+
method: 'POST',
|
|
772
|
+
headers: { 'Content-Type': 'application/x-www-form-urlencoded' },
|
|
773
|
+
body: body.toString(),
|
|
774
|
+
});
|
|
775
|
+
if (!response.ok) {
|
|
776
|
+
throw new Error(`Token exchange failed: ${response.status} ${response.statusText}`);
|
|
777
|
+
}
|
|
778
|
+
const tokenData = await response.json();
|
|
779
|
+
if (!tokenData) {
|
|
780
|
+
throw new Error('Token data not found');
|
|
781
|
+
}
|
|
782
|
+
const payload = JwtUtil.parseJwt(tokenData.id_token);
|
|
783
|
+
if (!payload) {
|
|
784
|
+
throw new Error('Payload not found');
|
|
785
|
+
}
|
|
786
|
+
const user = {
|
|
787
|
+
id: payload['sub'] || payload['http://schemas.xmlsoap.org/ws/2005/05/identity/claims/nameidentifier'] || '',
|
|
788
|
+
title: payload['name'] || payload['email'] || '',
|
|
789
|
+
name: payload['name'] || payload['email'] || '',
|
|
790
|
+
avatar: payload['picture'] || '',
|
|
791
|
+
};
|
|
792
|
+
const tenant = payload['tenantid'] || payload['tenant']
|
|
793
|
+
? {
|
|
794
|
+
id: payload['tenantid'] || payload['tenant'] || '',
|
|
795
|
+
name: payload['tenantname'] || '',
|
|
796
|
+
title: payload['tenanttitle'] || '',
|
|
797
|
+
}
|
|
798
|
+
: undefined;
|
|
799
|
+
const application = payload['applicationid'] || payload['application']
|
|
800
|
+
? {
|
|
801
|
+
id: payload['applicationid'] || payload['application'] || '',
|
|
802
|
+
name: payload['applicationname'] || '',
|
|
803
|
+
title: payload['applicationtitle'] || '',
|
|
804
|
+
}
|
|
805
|
+
: undefined;
|
|
806
|
+
console.log('payload', payload);
|
|
807
|
+
return {
|
|
808
|
+
succeed: true,
|
|
809
|
+
data: {
|
|
810
|
+
accessToken: tokenData.access_token,
|
|
811
|
+
refreshToken: tokenData.refresh_token,
|
|
812
|
+
idToken: tokenData.id_token,
|
|
813
|
+
expiresIn: TimeUtil.calculateExpireInDate(tokenData.expires_in || 0),
|
|
814
|
+
user,
|
|
815
|
+
tenant,
|
|
816
|
+
application,
|
|
817
|
+
},
|
|
818
|
+
};
|
|
819
|
+
}
|
|
820
|
+
// get Authorizeation Code
|
|
821
|
+
else {
|
|
822
|
+
// Extract parameters
|
|
823
|
+
// Support both direct id fields and nested tenant/application objects
|
|
824
|
+
const tenantId = params['tenantId'] ?? params['tenant']?.id ?? null;
|
|
825
|
+
const applicationId = params['applicationId'] ?? params['application']?.id ?? null;
|
|
826
|
+
const redirectUri = params['redirectUri'] || this.authConfig.redirectUri;
|
|
827
|
+
const scope = params['scope'] || this.authConfig.scope;
|
|
828
|
+
// Generate PKCE code verifier and challenge
|
|
829
|
+
const codeVerifier = PkceUtil.generateRandomString(128);
|
|
830
|
+
localStorage.setItem('pkce_code_verifier', codeVerifier);
|
|
831
|
+
const codeChallenge = await PkceUtil.generateCodeChallenge(codeVerifier);
|
|
832
|
+
// Build authorization URL
|
|
833
|
+
const authorizeEndpoint = this.openidConfigurationInfo.info.discoveryDocument.authorization_endpoint;
|
|
834
|
+
const clientId = this.authConfig.clientId;
|
|
835
|
+
const responseType = 'code';
|
|
836
|
+
const state = Math.random().toString(36).substring(2);
|
|
837
|
+
// const authorizeUrl = `${authorizeEndpoint}?response_type=${encodeURIComponent(responseType)}&client_id=${encodeURIComponent(clientId)}&redirect_uri=${encodeURIComponent(redirectUri)}&scope=${encodeURIComponent(scope)}&state=${encodeURIComponent(state)}&tenant_id=${encodeURIComponent(tenantId)}&application_id=${encodeURIComponent(applicationId)}&code_challenge=${encodeURIComponent(codeChallenge)}&code_challenge_method=S256`;
|
|
838
|
+
// Build query params dynamically, only add tenant_id and application_id if they have values
|
|
839
|
+
const queryParams = [
|
|
840
|
+
`response_type=${encodeURIComponent(responseType)}`,
|
|
841
|
+
`client_id=${encodeURIComponent(clientId)}`,
|
|
842
|
+
`redirect_uri=${encodeURIComponent(redirectUri)}`,
|
|
843
|
+
`scope=${encodeURIComponent(scope)}`,
|
|
844
|
+
`state=${encodeURIComponent(state)}`,
|
|
845
|
+
tenantId ? `tenant_id=${encodeURIComponent(tenantId)}` : null,
|
|
846
|
+
applicationId ? `application_id=${encodeURIComponent(applicationId)}` : null,
|
|
847
|
+
`code_challenge=${encodeURIComponent(codeChallenge)}`,
|
|
848
|
+
`code_challenge_method=S256`,
|
|
849
|
+
]
|
|
850
|
+
.filter(Boolean)
|
|
851
|
+
.join('&');
|
|
852
|
+
const authorizeUrl = `${authorizeEndpoint}?${queryParams}`;
|
|
853
|
+
// Step 1: Redirect to authorization endpoint
|
|
854
|
+
window.location.href = authorizeUrl;
|
|
855
|
+
}
|
|
866
856
|
}
|
|
867
|
-
catch {
|
|
868
|
-
|
|
857
|
+
catch (error) {
|
|
858
|
+
this.handleError(error);
|
|
869
859
|
}
|
|
870
860
|
}
|
|
871
|
-
async
|
|
872
|
-
|
|
873
|
-
|
|
874
|
-
|
|
875
|
-
|
|
876
|
-
|
|
877
|
-
}
|
|
861
|
+
async signout() {
|
|
862
|
+
debugger;
|
|
863
|
+
localStorage.removeItem('pkce_code_verifier');
|
|
864
|
+
localStorage.removeItem('oauth_provider');
|
|
865
|
+
debugger;
|
|
866
|
+
console.log(this.openidConfigurationInfo?.info?.discoveryDocument);
|
|
867
|
+
const logoutUrl = `${this.aXMAuthConfigs?.authConfig?.issuer}/connect/logout`;
|
|
868
|
+
// Use GET instead of POST to avoid Content-Type header issues
|
|
869
|
+
await firstValueFrom(this.http.get(logoutUrl, { withCredentials: true }));
|
|
878
870
|
}
|
|
879
|
-
async
|
|
871
|
+
async refreshToken(context) {
|
|
880
872
|
try {
|
|
881
|
-
|
|
873
|
+
await this.configureOAuth();
|
|
874
|
+
if (!this.authConfig || !this.authConfig.clientId) {
|
|
875
|
+
throw new Error('authConfig or clientId is missing');
|
|
876
|
+
}
|
|
877
|
+
const authData = this.loadAuthData();
|
|
878
|
+
if (!authData) {
|
|
879
|
+
return { succeed: false };
|
|
880
|
+
}
|
|
881
|
+
const refreshToken = authData.refreshToken;
|
|
882
|
+
if (!refreshToken) {
|
|
883
|
+
return { succeed: false };
|
|
884
|
+
}
|
|
885
|
+
const body = new HttpParams()
|
|
886
|
+
.set('grant_type', 'refresh_token')
|
|
887
|
+
.set('client_id', this.authConfig.clientId)
|
|
888
|
+
.set('refresh_token', refreshToken);
|
|
889
|
+
const headers = new HttpHeaders().set('Content-Type', 'application/x-www-form-urlencoded');
|
|
890
|
+
const response = await firstValueFrom(this.http.post(this.openidConfigurationInfo.info.discoveryDocument.token_endpoint, body.toString(), { headers }));
|
|
891
|
+
// Extract user, tenant, and application from id_token
|
|
892
|
+
const payload = JwtUtil.parseJwt(response.id_token);
|
|
893
|
+
const user = {
|
|
894
|
+
id: payload['sub'] || payload['http://schemas.xmlsoap.org/ws/2005/05/identity/claims/nameidentifier'] || '',
|
|
895
|
+
title: payload['name'] || payload['email'] || '',
|
|
896
|
+
name: payload['name'] || payload['email'] || '',
|
|
897
|
+
avatar: payload['picture'] || '',
|
|
898
|
+
};
|
|
899
|
+
const tenant = payload['tenantid'] || payload['tenant']
|
|
900
|
+
? {
|
|
901
|
+
id: payload['tenantid'] || payload['tenant'] || '',
|
|
902
|
+
name: payload['tenantname'] || '',
|
|
903
|
+
title: payload['tenanttitle'] || '',
|
|
904
|
+
}
|
|
905
|
+
: undefined;
|
|
906
|
+
const application = payload['applicationid'] || payload['application']
|
|
907
|
+
? {
|
|
908
|
+
id: payload['applicationid'] || payload['application'] || '',
|
|
909
|
+
name: payload['applicationname'] || '',
|
|
910
|
+
title: payload['applicationtitle'] || '',
|
|
911
|
+
}
|
|
912
|
+
: undefined;
|
|
913
|
+
const sessionData = {
|
|
914
|
+
accessToken: response.access_token,
|
|
915
|
+
refreshToken: response.refresh_token,
|
|
916
|
+
idToken: response.id_token,
|
|
917
|
+
strategy: 'oidc',
|
|
918
|
+
expiresIn: TimeUtil.calculateExpireInDate(response.expires_in ?? 0),
|
|
919
|
+
user,
|
|
920
|
+
tenant,
|
|
921
|
+
application,
|
|
922
|
+
};
|
|
923
|
+
// this.setServiceProps(sessionData);
|
|
924
|
+
return {
|
|
925
|
+
succeed: true,
|
|
926
|
+
data: {
|
|
927
|
+
...sessionData,
|
|
928
|
+
user: sessionData.user, // Ensure user is not undefined
|
|
929
|
+
},
|
|
930
|
+
};
|
|
882
931
|
}
|
|
883
|
-
catch {
|
|
884
|
-
|
|
932
|
+
catch (error) {
|
|
933
|
+
console.error('Error refreshing token', error);
|
|
934
|
+
return { succeed: false };
|
|
885
935
|
}
|
|
886
936
|
}
|
|
887
|
-
|
|
888
|
-
|
|
889
|
-
|
|
890
|
-
}
|
|
891
|
-
catch {
|
|
892
|
-
return this.fallbackLanguages;
|
|
893
|
-
}
|
|
937
|
+
loadAuthData() {
|
|
938
|
+
const sessionData = this.sessionService.getSessionData();
|
|
939
|
+
return sessionData || undefined;
|
|
894
940
|
}
|
|
895
|
-
async
|
|
896
|
-
return
|
|
941
|
+
async loadUserInfo() {
|
|
942
|
+
return this.oauthService.loadUserProfile();
|
|
897
943
|
}
|
|
898
|
-
|
|
899
|
-
|
|
900
|
-
|
|
901
|
-
|
|
902
|
-
|
|
903
|
-
|
|
904
|
-
|
|
944
|
+
handleError(error) {
|
|
945
|
+
console.error('Authentication error:', error);
|
|
946
|
+
throw error;
|
|
947
|
+
}
|
|
948
|
+
//#region getter
|
|
949
|
+
get name() {
|
|
950
|
+
return 'oidc';
|
|
905
951
|
}
|
|
952
|
+
static { this.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "20.1.3", ngImport: i0, type: AXCAPIOidcStrategy, deps: null, target: i0.ɵɵFactoryTarget.Injectable }); }
|
|
953
|
+
static { this.ɵprov = i0.ɵɵngDeclareInjectable({ minVersion: "12.0.0", version: "20.1.3", ngImport: i0, type: AXCAPIOidcStrategy }); }
|
|
906
954
|
}
|
|
955
|
+
i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "20.1.3", ngImport: i0, type: AXCAPIOidcStrategy, decorators: [{
|
|
956
|
+
type: Injectable
|
|
957
|
+
}] });
|
|
958
|
+
|
|
959
|
+
class AXMOidcPermissionLoader {
|
|
960
|
+
constructor(http) {
|
|
961
|
+
this.http = http;
|
|
962
|
+
this.configs = inject(AXP_ROOT_CONFIG_TOKEN);
|
|
963
|
+
this.apiGetConfig = `${this.configs.baseUrl}/abp/application-configuration`;
|
|
964
|
+
}
|
|
965
|
+
getList(context) {
|
|
966
|
+
return this.http.get(this.apiGetConfig).pipe(map((response) => this.mapTo(response)));
|
|
967
|
+
// if (context.user == null)
|
|
968
|
+
// return of([]);
|
|
969
|
+
// else if (context.user.name.toLowerCase() == 'admin')
|
|
970
|
+
// return of(['axp.admin.console', 'asc.admin.message', 'asc.admin.settings', 'asc.admin.gliding', 'asc.user.gliding']);
|
|
971
|
+
// else
|
|
972
|
+
// return of(['asc.user.gliding']);
|
|
973
|
+
// return of(['axp.admin.console', 'asc.admin.message', 'asc.admin.settings', 'asc.admin.gliding', 'asc.user.gliding']);
|
|
974
|
+
}
|
|
975
|
+
mapTo(jsonObj) {
|
|
976
|
+
const policies = jsonObj.auth.grantedPolicies;
|
|
977
|
+
const truePolicies = Object.keys(policies).filter((key) => policies[key] === true);
|
|
978
|
+
return truePolicies;
|
|
979
|
+
}
|
|
980
|
+
static { this.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "20.1.3", ngImport: i0, type: AXMOidcPermissionLoader, deps: [{ token: i1.HttpClient }], target: i0.ɵɵFactoryTarget.Injectable }); }
|
|
981
|
+
static { this.ɵprov = i0.ɵɵngDeclareInjectable({ minVersion: "12.0.0", version: "20.1.3", ngImport: i0, type: AXMOidcPermissionLoader }); }
|
|
982
|
+
}
|
|
983
|
+
i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "20.1.3", ngImport: i0, type: AXMOidcPermissionLoader, decorators: [{
|
|
984
|
+
type: Injectable
|
|
985
|
+
}], ctorParameters: () => [{ type: i1.HttpClient }] });
|
|
986
|
+
|
|
987
|
+
class AXMOidcTenantLoader {
|
|
988
|
+
constructor(http) {
|
|
989
|
+
this.http = http;
|
|
990
|
+
this.configs = inject(AXP_ROOT_CONFIG_TOKEN);
|
|
991
|
+
this.apiGetTenants = `${this.configs.baseUrl}/tenants/available-for-user`;
|
|
992
|
+
}
|
|
993
|
+
getList() {
|
|
994
|
+
return this.http.get(this.apiGetTenants).pipe(map((response) => response.items.map((item) => {
|
|
995
|
+
return this.mapToAXPTenant(item);
|
|
996
|
+
})));
|
|
997
|
+
}
|
|
998
|
+
async set(tenant) {
|
|
999
|
+
return Promise.resolve();
|
|
1000
|
+
}
|
|
1001
|
+
mapToAXPTenant(item) {
|
|
1002
|
+
return {
|
|
1003
|
+
id: item.id,
|
|
1004
|
+
name: item.name || 'defaultName',
|
|
1005
|
+
title: item.title || 'defaultTitle',
|
|
1006
|
+
// Add other fields and defaults as needed, and handle the logo if applicable
|
|
1007
|
+
};
|
|
1008
|
+
}
|
|
1009
|
+
static { this.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "20.1.3", ngImport: i0, type: AXMOidcTenantLoader, deps: [{ token: i1.HttpClient }], target: i0.ɵɵFactoryTarget.Injectable }); }
|
|
1010
|
+
static { this.ɵprov = i0.ɵɵngDeclareInjectable({ minVersion: "12.0.0", version: "20.1.3", ngImport: i0, type: AXMOidcTenantLoader }); }
|
|
1011
|
+
}
|
|
1012
|
+
i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "20.1.3", ngImport: i0, type: AXMOidcTenantLoader, decorators: [{
|
|
1013
|
+
type: Injectable
|
|
1014
|
+
}], ctorParameters: () => [{ type: i1.HttpClient }] });
|
|
907
1015
|
|
|
908
1016
|
class AXCApiModule {
|
|
909
1017
|
static { this.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "20.1.3", ngImport: i0, type: AXCApiModule, deps: [], target: i0.ɵɵFactoryTarget.NgModule }); }
|
|
@@ -921,10 +1029,10 @@ class AXCApiModule {
|
|
|
921
1029
|
provide: AXPFileStorageService,
|
|
922
1030
|
useClass: AXCFileStorageApiService,
|
|
923
1031
|
},
|
|
924
|
-
|
|
925
|
-
|
|
926
|
-
|
|
927
|
-
|
|
1032
|
+
{
|
|
1033
|
+
provide: AXP_TENANT_LOADER,
|
|
1034
|
+
useClass: AXMOidcTenantLoader,
|
|
1035
|
+
},
|
|
928
1036
|
{
|
|
929
1037
|
provide: AXP_APPLICATION_LOADER,
|
|
930
1038
|
useClass: AXMOidcApplicationLoader,
|
|
@@ -946,7 +1054,7 @@ class AXCApiModule {
|
|
|
946
1054
|
},
|
|
947
1055
|
], imports: [OAuthModule.forRoot(),
|
|
948
1056
|
AXPAuthModule.forRoot({
|
|
949
|
-
strategies: [],
|
|
1057
|
+
strategies: [AXCAPIOidcStrategy],
|
|
950
1058
|
})] }); }
|
|
951
1059
|
}
|
|
952
1060
|
i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "20.1.3", ngImport: i0, type: AXCApiModule, decorators: [{
|
|
@@ -955,7 +1063,7 @@ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "20.1.3", ngImpor
|
|
|
955
1063
|
imports: [
|
|
956
1064
|
OAuthModule.forRoot(),
|
|
957
1065
|
AXPAuthModule.forRoot({
|
|
958
|
-
strategies: [],
|
|
1066
|
+
strategies: [AXCAPIOidcStrategy],
|
|
959
1067
|
}),
|
|
960
1068
|
],
|
|
961
1069
|
providers: [
|
|
@@ -971,10 +1079,10 @@ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "20.1.3", ngImpor
|
|
|
971
1079
|
provide: AXPFileStorageService,
|
|
972
1080
|
useClass: AXCFileStorageApiService,
|
|
973
1081
|
},
|
|
974
|
-
|
|
975
|
-
|
|
976
|
-
|
|
977
|
-
|
|
1082
|
+
{
|
|
1083
|
+
provide: AXP_TENANT_LOADER,
|
|
1084
|
+
useClass: AXMOidcTenantLoader,
|
|
1085
|
+
},
|
|
978
1086
|
{
|
|
979
1087
|
provide: AXP_APPLICATION_LOADER,
|
|
980
1088
|
useClass: AXMOidcApplicationLoader,
|
|
@@ -1002,5 +1110,5 @@ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "20.1.3", ngImpor
|
|
|
1002
1110
|
* Generated bundle index. Do not edit.
|
|
1003
1111
|
*/
|
|
1004
1112
|
|
|
1005
|
-
export { AXCApiEntityStorageService, AXCApiModule, AXMConfigurationService, AXMOidcApplicationLoader, AXMOidcFeatureLoader, AXMOidcPermissionLoader,
|
|
1113
|
+
export { AXCAPIOidcStrategy, AXCApiEntityStorageService, AXCApiModule, AXMConfigurationService, AXMOidcApplicationLoader, AXMOidcFeatureLoader, AXMOidcPermissionLoader, AXMOidcTenantLoader };
|
|
1006
1114
|
//# sourceMappingURL=acorex-connectivity-api.mjs.map
|