@acorex/connectivity 20.2.0-next.1 → 20.2.0-next.3
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 +52 -15
- package/fesm2022/acorex-connectivity-api.mjs +694 -563
- package/fesm2022/acorex-connectivity-api.mjs.map +1 -1
- package/fesm2022/acorex-connectivity-mock.mjs +9121 -4742
- 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 +265 -17
- package/package.json +5 -1
- package/utils/README.md +3 -0
- package/utils/index.d.ts +17 -0
- package/fesm2022/acorex-connectivity-mock-countries-DHRrtbwM.mjs +0 -591
- package/fesm2022/acorex-connectivity-mock-countries-DHRrtbwM.mjs.map +0 -1
- package/fesm2022/acorex-connectivity-mock-currencies-B-x3Mxql.mjs +0 -13
- package/fesm2022/acorex-connectivity-mock-currencies-B-x3Mxql.mjs.map +0 -1
- package/fesm2022/acorex-connectivity-mock-profiles-MJ9xFTtp.mjs +0 -19
- package/fesm2022/acorex-connectivity-mock-profiles-MJ9xFTtp.mjs.map +0 -1
- package/fesm2022/acorex-connectivity-mock-timezones-CnNQ6EXw.mjs +0 -44
- package/fesm2022/acorex-connectivity-mock-timezones-CnNQ6EXw.mjs.map +0 -1
|
@@ -1,19 +1,19 @@
|
|
|
1
|
-
import { AXP_ROOT_CONFIG_TOKEN, AXPFilterOperatorMiddlewareService, AXPFileStorageService, AXPFileStorageStatus
|
|
1
|
+
import { AXP_ROOT_CONFIG_TOKEN, AXPFilterOperatorMiddlewareService, 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
14
|
import { AXM_AUTH_CONFIG_TOKEN } from '@acorex/modules/auth';
|
|
15
|
-
import {
|
|
16
|
-
import {
|
|
15
|
+
import { Router } from '@angular/router';
|
|
16
|
+
import { AXCUtilsModule, AXCExternalAuthorizationService } from '@acorex/connectivity/utils';
|
|
17
17
|
|
|
18
18
|
class AXCApiEntityStorageService {
|
|
19
19
|
constructor(http) {
|
|
@@ -131,13 +131,152 @@ class AXCApiEntityStorageService {
|
|
|
131
131
|
};
|
|
132
132
|
});
|
|
133
133
|
}
|
|
134
|
-
static { this.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "20.1.
|
|
135
|
-
static { this.ɵprov = i0.ɵɵngDeclareInjectable({ minVersion: "12.0.0", version: "20.1.
|
|
134
|
+
static { this.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "20.1.4", ngImport: i0, type: AXCApiEntityStorageService, deps: [{ token: i1.HttpClient }], target: i0.ɵɵFactoryTarget.Injectable }); }
|
|
135
|
+
static { this.ɵprov = i0.ɵɵngDeclareInjectable({ minVersion: "12.0.0", version: "20.1.4", ngImport: i0, type: AXCApiEntityStorageService }); }
|
|
136
136
|
}
|
|
137
|
-
i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "20.1.
|
|
137
|
+
i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "20.1.4", ngImport: i0, type: AXCApiEntityStorageService, decorators: [{
|
|
138
138
|
type: Injectable
|
|
139
139
|
}], ctorParameters: () => [{ type: i1.HttpClient }] });
|
|
140
140
|
|
|
141
|
+
class AXCFileStorageApiService extends AXPFileStorageService {
|
|
142
|
+
constructor() {
|
|
143
|
+
super(...arguments);
|
|
144
|
+
this.http = inject(HttpClient);
|
|
145
|
+
//#region ---- API Endpoints ----
|
|
146
|
+
this.baseUrl = '/api/file-storage';
|
|
147
|
+
//#endregion
|
|
148
|
+
//#region ---- Fallback Data ----
|
|
149
|
+
this.fallbackFileInfo = {
|
|
150
|
+
fileId: 'fallback-file-id',
|
|
151
|
+
refId: 'fallback-ref-id',
|
|
152
|
+
refType: 'fallback-ref-type',
|
|
153
|
+
category: 'fallback-category',
|
|
154
|
+
size: 0,
|
|
155
|
+
mimeType: 'application/octet-stream',
|
|
156
|
+
uploadedAt: new Date(),
|
|
157
|
+
isPublic: true,
|
|
158
|
+
isPrimary: false,
|
|
159
|
+
status: AXPFileStorageStatus.Temporary,
|
|
160
|
+
name: 'fallback-file',
|
|
161
|
+
binary: new File([''], 'fallback-file'),
|
|
162
|
+
};
|
|
163
|
+
}
|
|
164
|
+
//#endregion
|
|
165
|
+
async save(request) {
|
|
166
|
+
try {
|
|
167
|
+
const formData = new FormData();
|
|
168
|
+
formData.append('file', request.file);
|
|
169
|
+
formData.append('refId', request.refId);
|
|
170
|
+
formData.append('refType', request.refType);
|
|
171
|
+
formData.append('category', request.category);
|
|
172
|
+
if (request.name) {
|
|
173
|
+
formData.append('name', request.name);
|
|
174
|
+
}
|
|
175
|
+
if (request.path) {
|
|
176
|
+
formData.append('path', request.path);
|
|
177
|
+
}
|
|
178
|
+
if (request.isPrimary !== undefined) {
|
|
179
|
+
formData.append('isPrimary', request.isPrimary.toString());
|
|
180
|
+
}
|
|
181
|
+
if (request.status) {
|
|
182
|
+
formData.append('status', request.status);
|
|
183
|
+
}
|
|
184
|
+
if (request.metadata) {
|
|
185
|
+
formData.append('metadata', JSON.stringify(request.metadata));
|
|
186
|
+
}
|
|
187
|
+
return await firstValueFrom(this.http.post(`${this.baseUrl}/save`, formData).pipe(catchError(() => of(this.fallbackFileInfo))));
|
|
188
|
+
}
|
|
189
|
+
catch {
|
|
190
|
+
return this.fallbackFileInfo;
|
|
191
|
+
}
|
|
192
|
+
}
|
|
193
|
+
async update(request) {
|
|
194
|
+
try {
|
|
195
|
+
const updateData = {
|
|
196
|
+
metadata: request.metadata,
|
|
197
|
+
};
|
|
198
|
+
if (request.path !== undefined) {
|
|
199
|
+
updateData.path = request.path;
|
|
200
|
+
}
|
|
201
|
+
if (request.isPrimary !== undefined) {
|
|
202
|
+
updateData.isPrimary = request.isPrimary;
|
|
203
|
+
}
|
|
204
|
+
return await firstValueFrom(this.http.put(`${this.baseUrl}/update/${request.fileId}`, updateData).pipe(catchError(() => of(this.fallbackFileInfo))));
|
|
205
|
+
}
|
|
206
|
+
catch {
|
|
207
|
+
return this.fallbackFileInfo;
|
|
208
|
+
}
|
|
209
|
+
}
|
|
210
|
+
async find(request) {
|
|
211
|
+
try {
|
|
212
|
+
let params = new HttpParams();
|
|
213
|
+
if (request.refId) {
|
|
214
|
+
params = params.set('refId', request.refId);
|
|
215
|
+
}
|
|
216
|
+
if (request.refType) {
|
|
217
|
+
params = params.set('refType', request.refType);
|
|
218
|
+
}
|
|
219
|
+
if (request.category) {
|
|
220
|
+
params = params.set('category', request.category);
|
|
221
|
+
}
|
|
222
|
+
if (request.mimeType) {
|
|
223
|
+
params = params.set('mimeType', request.mimeType);
|
|
224
|
+
}
|
|
225
|
+
if (request.isPublic !== undefined) {
|
|
226
|
+
params = params.set('isPublic', request.isPublic.toString());
|
|
227
|
+
}
|
|
228
|
+
if (request.isPrimary !== undefined) {
|
|
229
|
+
params = params.set('isPrimary', request.isPrimary.toString());
|
|
230
|
+
}
|
|
231
|
+
if (request.uploadedAtRange) {
|
|
232
|
+
params = params.set('uploadedAtFrom', request.uploadedAtRange.from.toISOString());
|
|
233
|
+
params = params.set('uploadedAtTo', request.uploadedAtRange.to.toISOString());
|
|
234
|
+
}
|
|
235
|
+
return await firstValueFrom(this.http.get(`${this.baseUrl}/find`, { params }).pipe(catchError(() => of([]))));
|
|
236
|
+
}
|
|
237
|
+
catch {
|
|
238
|
+
return [];
|
|
239
|
+
}
|
|
240
|
+
}
|
|
241
|
+
async getInfo(fileId) {
|
|
242
|
+
try {
|
|
243
|
+
return await firstValueFrom(this.http.get(`${this.baseUrl}/info/${fileId}`).pipe(catchError(() => of(this.fallbackFileInfo))));
|
|
244
|
+
}
|
|
245
|
+
catch {
|
|
246
|
+
return this.fallbackFileInfo;
|
|
247
|
+
}
|
|
248
|
+
}
|
|
249
|
+
async remove(fileId) {
|
|
250
|
+
try {
|
|
251
|
+
await firstValueFrom(this.http.delete(`${this.baseUrl}/remove/${fileId}`).pipe(catchError(() => of(void 0))));
|
|
252
|
+
}
|
|
253
|
+
catch {
|
|
254
|
+
// Silently fail in fallback mode
|
|
255
|
+
}
|
|
256
|
+
}
|
|
257
|
+
async commit(fileId) {
|
|
258
|
+
try {
|
|
259
|
+
await firstValueFrom(this.http.post(`${this.baseUrl}/commit/${fileId}`, {}).pipe(catchError(() => of(void 0))));
|
|
260
|
+
}
|
|
261
|
+
catch {
|
|
262
|
+
// Silently fail in fallback mode
|
|
263
|
+
}
|
|
264
|
+
}
|
|
265
|
+
async markForDeletion(fileId) {
|
|
266
|
+
try {
|
|
267
|
+
await firstValueFrom(this.http.post(`${this.baseUrl}/mark-for-deletion/${fileId}`, {}).pipe(catchError(() => of(void 0))));
|
|
268
|
+
}
|
|
269
|
+
catch {
|
|
270
|
+
// Silently fail in fallback mode
|
|
271
|
+
}
|
|
272
|
+
}
|
|
273
|
+
static { this.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "20.1.4", ngImport: i0, type: AXCFileStorageApiService, deps: null, target: i0.ɵɵFactoryTarget.Injectable }); }
|
|
274
|
+
static { this.ɵprov = i0.ɵɵngDeclareInjectable({ minVersion: "12.0.0", version: "20.1.4", ngImport: i0, type: AXCFileStorageApiService }); }
|
|
275
|
+
}
|
|
276
|
+
i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "20.1.4", ngImport: i0, type: AXCFileStorageApiService, decorators: [{
|
|
277
|
+
type: Injectable
|
|
278
|
+
}] });
|
|
279
|
+
|
|
141
280
|
class AXMOidcApplicationLoader {
|
|
142
281
|
constructor(http) {
|
|
143
282
|
this.http = http;
|
|
@@ -179,10 +318,10 @@ class AXMOidcApplicationLoader {
|
|
|
179
318
|
// features: item.features || [],
|
|
180
319
|
};
|
|
181
320
|
}
|
|
182
|
-
static { this.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "20.1.
|
|
183
|
-
static { this.ɵprov = i0.ɵɵngDeclareInjectable({ minVersion: "12.0.0", version: "20.1.
|
|
321
|
+
static { this.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "20.1.4", ngImport: i0, type: AXMOidcApplicationLoader, deps: [{ token: i1.HttpClient }], target: i0.ɵɵFactoryTarget.Injectable }); }
|
|
322
|
+
static { this.ɵprov = i0.ɵɵngDeclareInjectable({ minVersion: "12.0.0", version: "20.1.4", ngImport: i0, type: AXMOidcApplicationLoader }); }
|
|
184
323
|
}
|
|
185
|
-
i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "20.1.
|
|
324
|
+
i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "20.1.4", ngImport: i0, type: AXMOidcApplicationLoader, decorators: [{
|
|
186
325
|
type: Injectable
|
|
187
326
|
}], ctorParameters: () => [{ type: i1.HttpClient }] });
|
|
188
327
|
|
|
@@ -222,10 +361,10 @@ class AXMConfigurationService {
|
|
|
222
361
|
switchMap(() => of(this.applicationConfig)));
|
|
223
362
|
}
|
|
224
363
|
}
|
|
225
|
-
static { this.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "20.1.
|
|
226
|
-
static { this.ɵprov = i0.ɵɵngDeclareInjectable({ minVersion: "12.0.0", version: "20.1.
|
|
364
|
+
static { this.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "20.1.4", ngImport: i0, type: AXMConfigurationService, deps: [{ token: i1.HttpClient }], target: i0.ɵɵFactoryTarget.Injectable }); }
|
|
365
|
+
static { this.ɵprov = i0.ɵɵngDeclareInjectable({ minVersion: "12.0.0", version: "20.1.4", ngImport: i0, type: AXMConfigurationService, providedIn: 'root' }); }
|
|
227
366
|
}
|
|
228
|
-
i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "20.1.
|
|
367
|
+
i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "20.1.4", ngImport: i0, type: AXMConfigurationService, decorators: [{
|
|
229
368
|
type: Injectable,
|
|
230
369
|
args: [{
|
|
231
370
|
providedIn: 'root',
|
|
@@ -252,22 +391,24 @@ class AXMOidcFeatureLoader {
|
|
|
252
391
|
}
|
|
253
392
|
}
|
|
254
393
|
|
|
255
|
-
|
|
394
|
+
//#endregion
|
|
395
|
+
class AXCAPIOidcStrategy extends AXPAuthStrategy {
|
|
256
396
|
constructor() {
|
|
397
|
+
super(...arguments);
|
|
257
398
|
this.aXMAuthConfigs = inject(AXM_AUTH_CONFIG_TOKEN);
|
|
258
399
|
this.oauthService = inject(OAuthService);
|
|
259
400
|
this.http = inject(HttpClient);
|
|
401
|
+
this.sessionService = inject(AXPSessionService);
|
|
402
|
+
this.router = inject(Router);
|
|
260
403
|
}
|
|
261
404
|
async configureOAuth() {
|
|
262
405
|
if (this.openidConfigurationInfo)
|
|
263
406
|
return;
|
|
264
|
-
|
|
265
|
-
|
|
266
|
-
|
|
267
|
-
}
|
|
268
|
-
this.authConfig = this.aXMAuthConfigs.authConfig;
|
|
407
|
+
// Validation: اطمینان از وجود authConfig
|
|
408
|
+
if (!this.aXMAuthConfigs.authConfig) {
|
|
409
|
+
throw new Error('authConfig is missing. Please check your environment configuration.');
|
|
269
410
|
}
|
|
270
|
-
this.oauthService.configure(this.authConfig);
|
|
411
|
+
this.oauthService.configure(this.aXMAuthConfigs.authConfig);
|
|
271
412
|
this.oauthService.setStorage(localStorage);
|
|
272
413
|
this.openidConfigurationInfo = await this.oauthService.loadDiscoveryDocument();
|
|
273
414
|
if (!this.openidConfigurationInfo) {
|
|
@@ -286,179 +427,290 @@ class AXMOidcStrategy {
|
|
|
286
427
|
if (oidcJson) {
|
|
287
428
|
const authData = JSON.parse(oidcJson);
|
|
288
429
|
if (authData) {
|
|
289
|
-
this.
|
|
430
|
+
this.sessionService.setSession(authData);
|
|
290
431
|
if (authData.expiresIn && new Date(authData.expiresIn) < new Date()) {
|
|
291
432
|
if (authData.expiresIn) {
|
|
292
|
-
|
|
433
|
+
this.sessionService.refreshToken();
|
|
293
434
|
}
|
|
294
435
|
else {
|
|
295
|
-
this.
|
|
436
|
+
this.signout();
|
|
296
437
|
}
|
|
297
438
|
}
|
|
298
439
|
}
|
|
299
440
|
}
|
|
300
441
|
}
|
|
301
442
|
async signin(credentials) {
|
|
443
|
+
// If OIDC with username/password
|
|
444
|
+
if (credentials.strategy === 'oidc' && credentials.username && credentials.password) {
|
|
445
|
+
await this.handleOidcPasswordSignin(credentials);
|
|
446
|
+
await new Promise(() => { }); // Keeps the promise pending until another flow (e.g., OAuth callback) completes
|
|
447
|
+
}
|
|
448
|
+
throw new Error(`Authentication method or credentials not supported: ${credentials.strategy}`);
|
|
449
|
+
}
|
|
450
|
+
async handleOidcPasswordSignin(credentials) {
|
|
302
451
|
await this.configureOAuth();
|
|
303
|
-
|
|
304
|
-
|
|
305
|
-
|
|
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
|
-
};
|
|
452
|
+
// Validation: اطمینان از وجود baseUrl
|
|
453
|
+
if (!this.aXMAuthConfigs.baseUrl) {
|
|
454
|
+
throw new Error('baseUrl is missing. Please check your environment configuration.');
|
|
345
455
|
}
|
|
346
|
-
|
|
347
|
-
|
|
456
|
+
// استفاده از baseUrl از configuration
|
|
457
|
+
const baseUrl = this.aXMAuthConfigs.baseUrl;
|
|
458
|
+
const loginRes = await fetch(baseUrl + '/auth/manual-login', {
|
|
459
|
+
method: 'POST',
|
|
460
|
+
headers: { 'Content-Type': 'application/json' },
|
|
461
|
+
body: JSON.stringify({ username: credentials.username, password: credentials.password }),
|
|
462
|
+
credentials: 'include',
|
|
463
|
+
});
|
|
464
|
+
if (!loginRes.ok) {
|
|
465
|
+
let errorText = 'Login failed';
|
|
466
|
+
try {
|
|
467
|
+
const errorJson = await loginRes.json();
|
|
468
|
+
if (errorJson && errorJson.error && errorJson.error.description) {
|
|
469
|
+
errorText = errorJson.error.description;
|
|
470
|
+
}
|
|
471
|
+
}
|
|
472
|
+
catch {
|
|
473
|
+
try {
|
|
474
|
+
const text = await loginRes.text();
|
|
475
|
+
if (text) {
|
|
476
|
+
errorText = text;
|
|
477
|
+
}
|
|
478
|
+
}
|
|
479
|
+
catch { }
|
|
480
|
+
}
|
|
481
|
+
throw new Error(errorText);
|
|
348
482
|
}
|
|
483
|
+
// Check if response is JSON or text
|
|
484
|
+
const contentType = loginRes.headers.get('content-type');
|
|
485
|
+
let result;
|
|
486
|
+
if (contentType && contentType.includes('application/json')) {
|
|
487
|
+
result = await loginRes.json();
|
|
488
|
+
}
|
|
489
|
+
else {
|
|
490
|
+
// Handle text response (like "Login successful")
|
|
491
|
+
const responseText = await loginRes.text();
|
|
492
|
+
console.log('Server response:', responseText);
|
|
493
|
+
}
|
|
494
|
+
await this.updateToken({});
|
|
349
495
|
}
|
|
350
|
-
async
|
|
351
|
-
//this.logout();
|
|
352
|
-
}
|
|
353
|
-
async refreshToken(context) {
|
|
496
|
+
async updateToken(params) {
|
|
354
497
|
try {
|
|
355
|
-
|
|
356
|
-
|
|
357
|
-
|
|
498
|
+
// Ensure OAuth is configured first
|
|
499
|
+
if (!this.openidConfigurationInfo) {
|
|
500
|
+
await this.configureOAuth();
|
|
501
|
+
}
|
|
502
|
+
// Validation: اطمینان از وجود authConfig
|
|
503
|
+
if (!this.aXMAuthConfigs.authConfig) {
|
|
504
|
+
throw new Error('authConfig is missing. Please check your environment configuration.');
|
|
505
|
+
}
|
|
506
|
+
// get Token Code
|
|
507
|
+
if (params['code']) {
|
|
508
|
+
// If params contains 'code', exchange it for tokens using the OpenIddict token endpoint
|
|
509
|
+
const code = params['code'];
|
|
510
|
+
const redirectUri = params['redirectUri'] || this.aXMAuthConfigs.authConfig.redirectUri;
|
|
511
|
+
const clientId = params['clientId'] || this.aXMAuthConfigs.authConfig.clientId;
|
|
512
|
+
const tokenEndpoint = params['tokenEndpoint'] ||
|
|
513
|
+
this.openidConfigurationInfo?.info?.discoveryDocument?.token_endpoint ||
|
|
514
|
+
`${this.aXMAuthConfigs?.authConfig?.issuer}/connect/token`;
|
|
515
|
+
// Get code_verifier from localStorage (PKCE)
|
|
516
|
+
const codeVerifier = localStorage.getItem('pkce_code_verifier');
|
|
517
|
+
localStorage.removeItem('pkce_code_verifier');
|
|
518
|
+
if (!codeVerifier) {
|
|
519
|
+
throw new Error('Code verifier not found. Please try signing in again.');
|
|
520
|
+
}
|
|
521
|
+
// Prepare body for token request
|
|
522
|
+
const body = new URLSearchParams({
|
|
523
|
+
grant_type: 'authorization_code',
|
|
524
|
+
client_id: clientId,
|
|
525
|
+
code_verifier: codeVerifier,
|
|
526
|
+
code: code,
|
|
527
|
+
redirect_uri: redirectUri,
|
|
528
|
+
});
|
|
529
|
+
// Call the token endpoint (OpenIddict)
|
|
530
|
+
const response = await fetch(tokenEndpoint, {
|
|
531
|
+
method: 'POST',
|
|
532
|
+
headers: { 'Content-Type': 'application/x-www-form-urlencoded' },
|
|
533
|
+
body: body.toString(),
|
|
534
|
+
});
|
|
535
|
+
if (!response.ok) {
|
|
536
|
+
throw new Error(`Token exchange failed: ${response.status} ${response.statusText}`);
|
|
537
|
+
}
|
|
538
|
+
const tokenData = await response.json();
|
|
539
|
+
if (!tokenData) {
|
|
540
|
+
throw new Error('Token data not found');
|
|
541
|
+
}
|
|
542
|
+
const payload = JwtUtil.parseJwt(tokenData.id_token);
|
|
543
|
+
if (!payload) {
|
|
544
|
+
throw new Error('Payload not found');
|
|
545
|
+
}
|
|
546
|
+
const user = {
|
|
547
|
+
id: payload['sub'] || payload['http://schemas.xmlsoap.org/ws/2005/05/identity/claims/nameidentifier'] || '',
|
|
548
|
+
title: payload['name'] || payload['email'] || '',
|
|
549
|
+
name: payload['name'] || payload['email'] || '',
|
|
550
|
+
avatar: payload['picture'] || '',
|
|
551
|
+
};
|
|
552
|
+
const tenant = payload['tenantid'] || payload['tenant']
|
|
553
|
+
? {
|
|
554
|
+
id: payload['tenantid'] || payload['tenant'] || '',
|
|
555
|
+
name: payload['tenantname'] || '',
|
|
556
|
+
title: payload['tenanttitle'] || '',
|
|
557
|
+
}
|
|
558
|
+
: undefined;
|
|
559
|
+
const application = payload['applicationid'] || payload['application']
|
|
560
|
+
? {
|
|
561
|
+
id: payload['applicationid'] || payload['application'] || '',
|
|
562
|
+
name: payload['applicationname'] || '',
|
|
563
|
+
title: payload['applicationtitle'] || '',
|
|
564
|
+
}
|
|
565
|
+
: undefined;
|
|
566
|
+
console.log('payload', payload);
|
|
358
567
|
return {
|
|
359
568
|
succeed: true,
|
|
360
569
|
data: {
|
|
361
|
-
accessToken:
|
|
362
|
-
refreshToken:
|
|
570
|
+
accessToken: tokenData.access_token,
|
|
571
|
+
refreshToken: tokenData.refresh_token,
|
|
572
|
+
idToken: tokenData.id_token,
|
|
573
|
+
expiresIn: TimeUtil.calculateExpireInDate(tokenData.expires_in || 0),
|
|
574
|
+
user,
|
|
575
|
+
tenant,
|
|
576
|
+
application,
|
|
363
577
|
},
|
|
364
578
|
};
|
|
365
579
|
}
|
|
580
|
+
// get Authorizeation Code
|
|
366
581
|
else {
|
|
367
|
-
|
|
582
|
+
// Validation: اطمینان از وجود authConfig
|
|
583
|
+
if (!this.aXMAuthConfigs.authConfig) {
|
|
584
|
+
throw new Error('authConfig is missing. Please check your environment configuration.');
|
|
585
|
+
}
|
|
586
|
+
// Extract parameters
|
|
587
|
+
// Support both direct id fields and nested tenant/application objects
|
|
588
|
+
const tenantId = params['tenantId'] ?? params['tenant']?.id ?? null;
|
|
589
|
+
const applicationId = params['applicationId'] ?? params['application']?.id ?? null;
|
|
590
|
+
const redirectUri = params['redirectUri'] || this.aXMAuthConfigs.authConfig.redirectUri;
|
|
591
|
+
const scope = params['scope'] || this.aXMAuthConfigs.authConfig.scope;
|
|
592
|
+
// Generate PKCE code verifier and challenge
|
|
593
|
+
const codeVerifier = PkceUtil.generateRandomString(128);
|
|
594
|
+
localStorage.setItem('pkce_code_verifier', codeVerifier);
|
|
595
|
+
const codeChallenge = await PkceUtil.generateCodeChallenge(codeVerifier);
|
|
596
|
+
// Build authorization URL
|
|
597
|
+
const authorizeEndpoint = this.openidConfigurationInfo.info.discoveryDocument.authorization_endpoint;
|
|
598
|
+
const clientId = this.aXMAuthConfigs.authConfig.clientId;
|
|
599
|
+
const responseType = 'code';
|
|
600
|
+
const state = Math.random().toString(36).substring(2);
|
|
601
|
+
const queryParams = [
|
|
602
|
+
`response_type=${encodeURIComponent(responseType)}`,
|
|
603
|
+
`client_id=${encodeURIComponent(clientId)}`,
|
|
604
|
+
`redirect_uri=${encodeURIComponent(redirectUri)}`,
|
|
605
|
+
`scope=${encodeURIComponent(scope)}`,
|
|
606
|
+
`state=${encodeURIComponent(state)}`,
|
|
607
|
+
tenantId ? `tenant_id=${encodeURIComponent(tenantId)}` : null,
|
|
608
|
+
applicationId ? `application_id=${encodeURIComponent(applicationId)}` : null,
|
|
609
|
+
`code_challenge=${encodeURIComponent(codeChallenge)}`,
|
|
610
|
+
`code_challenge_method=S256`,
|
|
611
|
+
]
|
|
612
|
+
.filter(Boolean)
|
|
613
|
+
.join('&');
|
|
614
|
+
const authorizeUrl = `${authorizeEndpoint}?${queryParams}`;
|
|
615
|
+
window.location.href = authorizeUrl;
|
|
368
616
|
}
|
|
369
617
|
}
|
|
370
618
|
catch (error) {
|
|
371
|
-
|
|
372
|
-
return { succeed: false };
|
|
619
|
+
this.handleError(error);
|
|
373
620
|
}
|
|
374
621
|
}
|
|
375
|
-
async
|
|
376
|
-
|
|
377
|
-
|
|
378
|
-
|
|
379
|
-
|
|
380
|
-
|
|
381
|
-
|
|
382
|
-
|
|
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');
|
|
622
|
+
async signout() {
|
|
623
|
+
localStorage.removeItem('pkce_code_verifier');
|
|
624
|
+
localStorage.removeItem('oauth_provider');
|
|
625
|
+
console.log(this.openidConfigurationInfo?.info?.discoveryDocument);
|
|
626
|
+
const logoutUrl = `${this.aXMAuthConfigs?.authConfig?.issuer}/connect/logout`;
|
|
627
|
+
window.location.href = logoutUrl;
|
|
628
|
+
}
|
|
629
|
+
async refreshToken(context) {
|
|
391
630
|
try {
|
|
631
|
+
await this.configureOAuth();
|
|
632
|
+
if (!this.aXMAuthConfigs.authConfig || !this.aXMAuthConfigs.authConfig.clientId) {
|
|
633
|
+
throw new Error('authConfig or clientId is missing');
|
|
634
|
+
}
|
|
635
|
+
const authData = this.loadAuthData();
|
|
636
|
+
if (!authData) {
|
|
637
|
+
return { succeed: false };
|
|
638
|
+
}
|
|
639
|
+
const refreshToken = authData.refreshToken;
|
|
640
|
+
if (!refreshToken) {
|
|
641
|
+
return { succeed: false };
|
|
642
|
+
}
|
|
643
|
+
const body = new HttpParams()
|
|
644
|
+
.set('grant_type', 'refresh_token')
|
|
645
|
+
.set('client_id', this.aXMAuthConfigs.authConfig.clientId)
|
|
646
|
+
.set('refresh_token', refreshToken);
|
|
647
|
+
const headers = new HttpHeaders().set('Content-Type', 'application/x-www-form-urlencoded');
|
|
392
648
|
const response = await firstValueFrom(this.http.post(this.openidConfigurationInfo.info.discoveryDocument.token_endpoint, body.toString(), { headers }));
|
|
393
|
-
|
|
649
|
+
// Extract user, tenant, and application from id_token
|
|
650
|
+
const payload = JwtUtil.parseJwt(response.id_token);
|
|
651
|
+
const user = {
|
|
652
|
+
id: payload['sub'] || payload['http://schemas.xmlsoap.org/ws/2005/05/identity/claims/nameidentifier'] || '',
|
|
653
|
+
title: payload['name'] || payload['email'] || '',
|
|
654
|
+
name: payload['name'] || payload['email'] || '',
|
|
655
|
+
avatar: payload['picture'] || '',
|
|
656
|
+
};
|
|
657
|
+
const tenant = payload['tenantid'] || payload['tenant']
|
|
658
|
+
? {
|
|
659
|
+
id: payload['tenantid'] || payload['tenant'] || '',
|
|
660
|
+
name: payload['tenantname'] || '',
|
|
661
|
+
title: payload['tenanttitle'] || '',
|
|
662
|
+
}
|
|
663
|
+
: undefined;
|
|
664
|
+
const application = payload['applicationid'] || payload['application']
|
|
665
|
+
? {
|
|
666
|
+
id: payload['applicationid'] || payload['application'] || '',
|
|
667
|
+
name: payload['applicationname'] || '',
|
|
668
|
+
title: payload['applicationtitle'] || '',
|
|
669
|
+
}
|
|
670
|
+
: undefined;
|
|
671
|
+
const sessionData = {
|
|
394
672
|
accessToken: response.access_token,
|
|
395
673
|
refreshToken: response.refresh_token,
|
|
396
674
|
idToken: response.id_token,
|
|
397
|
-
|
|
398
|
-
|
|
399
|
-
|
|
675
|
+
strategy: 'oidc',
|
|
676
|
+
expiresIn: TimeUtil.calculateExpireInDate(response.expires_in ?? 0),
|
|
677
|
+
user,
|
|
678
|
+
tenant,
|
|
679
|
+
application,
|
|
680
|
+
};
|
|
681
|
+
// this.setServiceProps(sessionData);
|
|
682
|
+
return {
|
|
683
|
+
succeed: true,
|
|
684
|
+
data: {
|
|
685
|
+
...sessionData,
|
|
686
|
+
user: sessionData.user, // Ensure user is not undefined
|
|
687
|
+
},
|
|
688
|
+
};
|
|
400
689
|
}
|
|
401
690
|
catch (error) {
|
|
402
|
-
console.error('
|
|
403
|
-
return false;
|
|
404
|
-
}
|
|
405
|
-
}
|
|
406
|
-
expires_in_milisecound(expires_in_date) {
|
|
407
|
-
const now = new Date();
|
|
408
|
-
const expire = new Date(expires_in_date);
|
|
409
|
-
return expire.getTime() - now.getTime();
|
|
410
|
-
}
|
|
411
|
-
setServiceProps(authData) {
|
|
412
|
-
this.oauthService.getAccessToken = () => authData.accessToken;
|
|
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
|
-
// }
|
|
691
|
+
console.error('Error refreshing token', error);
|
|
692
|
+
return { succeed: false };
|
|
422
693
|
}
|
|
423
694
|
}
|
|
424
695
|
loadAuthData() {
|
|
425
|
-
const
|
|
426
|
-
|
|
427
|
-
return undefined;
|
|
428
|
-
const authData = JSON.parse(authDataJson);
|
|
429
|
-
// return authData ? new AuthenticationData(authData) : undefined;
|
|
430
|
-
return authData;
|
|
696
|
+
const sessionData = this.sessionService.getSessionData();
|
|
697
|
+
return sessionData || undefined;
|
|
431
698
|
}
|
|
432
699
|
async loadUserInfo() {
|
|
433
700
|
return this.oauthService.loadUserProfile();
|
|
434
701
|
}
|
|
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
702
|
handleError(error) {
|
|
444
|
-
|
|
445
|
-
|
|
446
|
-
}
|
|
447
|
-
else if (error?.message) {
|
|
448
|
-
throw new Error(error.message);
|
|
449
|
-
}
|
|
450
|
-
else {
|
|
451
|
-
throw new Error('Network or server error occurred');
|
|
452
|
-
}
|
|
703
|
+
console.error('Authentication error:', error);
|
|
704
|
+
throw error;
|
|
453
705
|
}
|
|
454
706
|
//#region getter
|
|
455
707
|
get name() {
|
|
456
|
-
return '
|
|
708
|
+
return 'oidc';
|
|
457
709
|
}
|
|
458
|
-
static { this.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "20.1.
|
|
459
|
-
static { this.ɵprov = i0.ɵɵngDeclareInjectable({ minVersion: "12.0.0", version: "20.1.
|
|
710
|
+
static { this.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "20.1.4", ngImport: i0, type: AXCAPIOidcStrategy, deps: null, target: i0.ɵɵFactoryTarget.Injectable }); }
|
|
711
|
+
static { this.ɵprov = i0.ɵɵngDeclareInjectable({ minVersion: "12.0.0", version: "20.1.4", ngImport: i0, type: AXCAPIOidcStrategy }); }
|
|
460
712
|
}
|
|
461
|
-
i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "20.1.
|
|
713
|
+
i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "20.1.4", ngImport: i0, type: AXCAPIOidcStrategy, decorators: [{
|
|
462
714
|
type: Injectable
|
|
463
715
|
}] });
|
|
464
716
|
|
|
@@ -483,10 +735,10 @@ class AXMOidcPermissionLoader {
|
|
|
483
735
|
const truePolicies = Object.keys(policies).filter((key) => policies[key] === true);
|
|
484
736
|
return truePolicies;
|
|
485
737
|
}
|
|
486
|
-
static { this.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "20.1.
|
|
487
|
-
static { this.ɵprov = i0.ɵɵngDeclareInjectable({ minVersion: "12.0.0", version: "20.1.
|
|
738
|
+
static { this.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "20.1.4", ngImport: i0, type: AXMOidcPermissionLoader, deps: [{ token: i1.HttpClient }], target: i0.ɵɵFactoryTarget.Injectable }); }
|
|
739
|
+
static { this.ɵprov = i0.ɵɵngDeclareInjectable({ minVersion: "12.0.0", version: "20.1.4", ngImport: i0, type: AXMOidcPermissionLoader }); }
|
|
488
740
|
}
|
|
489
|
-
i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "20.1.
|
|
741
|
+
i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "20.1.4", ngImport: i0, type: AXMOidcPermissionLoader, decorators: [{
|
|
490
742
|
type: Injectable
|
|
491
743
|
}], ctorParameters: () => [{ type: i1.HttpClient }] });
|
|
492
744
|
|
|
@@ -512,419 +764,29 @@ class AXMOidcTenantLoader {
|
|
|
512
764
|
// Add other fields and defaults as needed, and handle the logo if applicable
|
|
513
765
|
};
|
|
514
766
|
}
|
|
515
|
-
static { this.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "20.1.
|
|
516
|
-
static { this.ɵprov = i0.ɵɵngDeclareInjectable({ minVersion: "12.0.0", version: "20.1.
|
|
767
|
+
static { this.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "20.1.4", ngImport: i0, type: AXMOidcTenantLoader, deps: [{ token: i1.HttpClient }], target: i0.ɵɵFactoryTarget.Injectable }); }
|
|
768
|
+
static { this.ɵprov = i0.ɵɵngDeclareInjectable({ minVersion: "12.0.0", version: "20.1.4", ngImport: i0, type: AXMOidcTenantLoader }); }
|
|
517
769
|
}
|
|
518
|
-
i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "20.1.
|
|
770
|
+
i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "20.1.4", ngImport: i0, type: AXMOidcTenantLoader, decorators: [{
|
|
519
771
|
type: Injectable
|
|
520
772
|
}], ctorParameters: () => [{ type: i1.HttpClient }] });
|
|
521
773
|
|
|
522
|
-
class AXCFileStorageApiService extends AXPFileStorageService {
|
|
523
|
-
constructor() {
|
|
524
|
-
super(...arguments);
|
|
525
|
-
this.http = inject(HttpClient);
|
|
526
|
-
//#region ---- API Endpoints ----
|
|
527
|
-
this.baseUrl = '/api/file-storage';
|
|
528
|
-
//#endregion
|
|
529
|
-
//#region ---- Fallback Data ----
|
|
530
|
-
this.fallbackFileInfo = {
|
|
531
|
-
fileId: 'fallback-file-id',
|
|
532
|
-
refId: 'fallback-ref-id',
|
|
533
|
-
refType: 'fallback-ref-type',
|
|
534
|
-
category: 'fallback-category',
|
|
535
|
-
size: 0,
|
|
536
|
-
mimeType: 'application/octet-stream',
|
|
537
|
-
uploadedAt: new Date(),
|
|
538
|
-
isPublic: true,
|
|
539
|
-
isPrimary: false,
|
|
540
|
-
status: AXPFileStorageStatus.Temporary,
|
|
541
|
-
name: 'fallback-file',
|
|
542
|
-
binary: new File([''], 'fallback-file'),
|
|
543
|
-
};
|
|
544
|
-
}
|
|
545
|
-
//#endregion
|
|
546
|
-
async save(request) {
|
|
547
|
-
try {
|
|
548
|
-
const formData = new FormData();
|
|
549
|
-
formData.append('file', request.file);
|
|
550
|
-
formData.append('refId', request.refId);
|
|
551
|
-
formData.append('refType', request.refType);
|
|
552
|
-
formData.append('category', request.category);
|
|
553
|
-
if (request.name) {
|
|
554
|
-
formData.append('name', request.name);
|
|
555
|
-
}
|
|
556
|
-
if (request.path) {
|
|
557
|
-
formData.append('path', request.path);
|
|
558
|
-
}
|
|
559
|
-
if (request.isPrimary !== undefined) {
|
|
560
|
-
formData.append('isPrimary', request.isPrimary.toString());
|
|
561
|
-
}
|
|
562
|
-
if (request.status) {
|
|
563
|
-
formData.append('status', request.status);
|
|
564
|
-
}
|
|
565
|
-
if (request.metadata) {
|
|
566
|
-
formData.append('metadata', JSON.stringify(request.metadata));
|
|
567
|
-
}
|
|
568
|
-
return await firstValueFrom(this.http.post(`${this.baseUrl}/save`, formData).pipe(catchError(() => of(this.fallbackFileInfo))));
|
|
569
|
-
}
|
|
570
|
-
catch {
|
|
571
|
-
return this.fallbackFileInfo;
|
|
572
|
-
}
|
|
573
|
-
}
|
|
574
|
-
async update(request) {
|
|
575
|
-
try {
|
|
576
|
-
const updateData = {
|
|
577
|
-
metadata: request.metadata,
|
|
578
|
-
};
|
|
579
|
-
if (request.path !== undefined) {
|
|
580
|
-
updateData.path = request.path;
|
|
581
|
-
}
|
|
582
|
-
if (request.isPrimary !== undefined) {
|
|
583
|
-
updateData.isPrimary = request.isPrimary;
|
|
584
|
-
}
|
|
585
|
-
return await firstValueFrom(this.http.put(`${this.baseUrl}/update/${request.fileId}`, updateData).pipe(catchError(() => of(this.fallbackFileInfo))));
|
|
586
|
-
}
|
|
587
|
-
catch {
|
|
588
|
-
return this.fallbackFileInfo;
|
|
589
|
-
}
|
|
590
|
-
}
|
|
591
|
-
async find(request) {
|
|
592
|
-
try {
|
|
593
|
-
let params = new HttpParams();
|
|
594
|
-
if (request.refId) {
|
|
595
|
-
params = params.set('refId', request.refId);
|
|
596
|
-
}
|
|
597
|
-
if (request.refType) {
|
|
598
|
-
params = params.set('refType', request.refType);
|
|
599
|
-
}
|
|
600
|
-
if (request.category) {
|
|
601
|
-
params = params.set('category', request.category);
|
|
602
|
-
}
|
|
603
|
-
if (request.mimeType) {
|
|
604
|
-
params = params.set('mimeType', request.mimeType);
|
|
605
|
-
}
|
|
606
|
-
if (request.isPublic !== undefined) {
|
|
607
|
-
params = params.set('isPublic', request.isPublic.toString());
|
|
608
|
-
}
|
|
609
|
-
if (request.isPrimary !== undefined) {
|
|
610
|
-
params = params.set('isPrimary', request.isPrimary.toString());
|
|
611
|
-
}
|
|
612
|
-
if (request.uploadedAtRange) {
|
|
613
|
-
params = params.set('uploadedAtFrom', request.uploadedAtRange.from.toISOString());
|
|
614
|
-
params = params.set('uploadedAtTo', request.uploadedAtRange.to.toISOString());
|
|
615
|
-
}
|
|
616
|
-
return await firstValueFrom(this.http.get(`${this.baseUrl}/find`, { params }).pipe(catchError(() => of([]))));
|
|
617
|
-
}
|
|
618
|
-
catch {
|
|
619
|
-
return [];
|
|
620
|
-
}
|
|
621
|
-
}
|
|
622
|
-
async getInfo(fileId) {
|
|
623
|
-
try {
|
|
624
|
-
return await firstValueFrom(this.http.get(`${this.baseUrl}/info/${fileId}`).pipe(catchError(() => of(this.fallbackFileInfo))));
|
|
625
|
-
}
|
|
626
|
-
catch {
|
|
627
|
-
return this.fallbackFileInfo;
|
|
628
|
-
}
|
|
629
|
-
}
|
|
630
|
-
async remove(fileId) {
|
|
631
|
-
try {
|
|
632
|
-
await firstValueFrom(this.http.delete(`${this.baseUrl}/remove/${fileId}`).pipe(catchError(() => of(void 0))));
|
|
633
|
-
}
|
|
634
|
-
catch {
|
|
635
|
-
// Silently fail in fallback mode
|
|
636
|
-
}
|
|
637
|
-
}
|
|
638
|
-
async commit(fileId) {
|
|
639
|
-
try {
|
|
640
|
-
await firstValueFrom(this.http.post(`${this.baseUrl}/commit/${fileId}`, {}).pipe(catchError(() => of(void 0))));
|
|
641
|
-
}
|
|
642
|
-
catch {
|
|
643
|
-
// Silently fail in fallback mode
|
|
644
|
-
}
|
|
645
|
-
}
|
|
646
|
-
async markForDeletion(fileId) {
|
|
647
|
-
try {
|
|
648
|
-
await firstValueFrom(this.http.post(`${this.baseUrl}/mark-for-deletion/${fileId}`, {}).pipe(catchError(() => of(void 0))));
|
|
649
|
-
}
|
|
650
|
-
catch {
|
|
651
|
-
// Silently fail in fallback mode
|
|
652
|
-
}
|
|
653
|
-
}
|
|
654
|
-
static { this.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "20.1.3", ngImport: i0, type: AXCFileStorageApiService, deps: null, target: i0.ɵɵFactoryTarget.Injectable }); }
|
|
655
|
-
static { this.ɵprov = i0.ɵɵngDeclareInjectable({ minVersion: "12.0.0", version: "20.1.3", ngImport: i0, type: AXCFileStorageApiService }); }
|
|
656
|
-
}
|
|
657
|
-
i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "20.1.3", ngImport: i0, type: AXCFileStorageApiService, decorators: [{
|
|
658
|
-
type: Injectable
|
|
659
|
-
}] });
|
|
660
|
-
|
|
661
|
-
class AXCRegionalApiService extends AXPRegionalService {
|
|
662
|
-
constructor() {
|
|
663
|
-
super(...arguments);
|
|
664
|
-
this.http = inject(HttpClient);
|
|
665
|
-
this.languageService = inject(AXTranslationService);
|
|
666
|
-
//#region ---- API Endpoints ----
|
|
667
|
-
this.baseUrl = '/api/regional';
|
|
668
|
-
//#endregion
|
|
669
|
-
//#region ---- Fallback Data ----
|
|
670
|
-
this.fallbackCountries = [
|
|
671
|
-
{
|
|
672
|
-
code: 'US',
|
|
673
|
-
title: 'United States',
|
|
674
|
-
native: 'United States',
|
|
675
|
-
regional: 'en',
|
|
676
|
-
timezone: 'America/New_York'
|
|
677
|
-
},
|
|
678
|
-
{
|
|
679
|
-
code: 'CA',
|
|
680
|
-
title: 'Canada',
|
|
681
|
-
native: 'Canada',
|
|
682
|
-
regional: 'en',
|
|
683
|
-
timezone: 'America/Toronto'
|
|
684
|
-
},
|
|
685
|
-
{
|
|
686
|
-
code: 'GB',
|
|
687
|
-
title: 'United Kingdom',
|
|
688
|
-
native: 'United Kingdom',
|
|
689
|
-
regional: 'en',
|
|
690
|
-
timezone: 'Europe/London'
|
|
691
|
-
}
|
|
692
|
-
];
|
|
693
|
-
this.fallbackProvinces = [
|
|
694
|
-
{
|
|
695
|
-
code: 'CA',
|
|
696
|
-
title: 'California',
|
|
697
|
-
native: 'California',
|
|
698
|
-
timezone: 'America/Los_Angeles'
|
|
699
|
-
},
|
|
700
|
-
{
|
|
701
|
-
code: 'NY',
|
|
702
|
-
title: 'New York',
|
|
703
|
-
native: 'New York',
|
|
704
|
-
timezone: 'America/New_York'
|
|
705
|
-
},
|
|
706
|
-
{
|
|
707
|
-
code: 'ON',
|
|
708
|
-
title: 'Ontario',
|
|
709
|
-
native: 'Ontario',
|
|
710
|
-
timezone: 'America/Toronto'
|
|
711
|
-
}
|
|
712
|
-
];
|
|
713
|
-
this.fallbackCities = [
|
|
714
|
-
{
|
|
715
|
-
code: 'NYC',
|
|
716
|
-
title: 'New York City',
|
|
717
|
-
native: 'New York City',
|
|
718
|
-
timezone: 'America/New_York'
|
|
719
|
-
},
|
|
720
|
-
{
|
|
721
|
-
code: 'LA',
|
|
722
|
-
title: 'Los Angeles',
|
|
723
|
-
native: 'Los Angeles',
|
|
724
|
-
timezone: 'America/Los_Angeles'
|
|
725
|
-
},
|
|
726
|
-
{
|
|
727
|
-
code: 'TOR',
|
|
728
|
-
title: 'Toronto',
|
|
729
|
-
native: 'Toronto',
|
|
730
|
-
timezone: 'America/Toronto'
|
|
731
|
-
}
|
|
732
|
-
];
|
|
733
|
-
this.fallbackCurrencies = [
|
|
734
|
-
{
|
|
735
|
-
code: 'USD',
|
|
736
|
-
title: 'United States Dollar',
|
|
737
|
-
symbol: '$',
|
|
738
|
-
format: '${amount}'
|
|
739
|
-
},
|
|
740
|
-
{
|
|
741
|
-
code: 'CAD',
|
|
742
|
-
title: 'Canadian Dollar',
|
|
743
|
-
symbol: 'CA$',
|
|
744
|
-
format: 'CA${amount}'
|
|
745
|
-
},
|
|
746
|
-
{
|
|
747
|
-
code: 'GBP',
|
|
748
|
-
title: 'British Pound',
|
|
749
|
-
symbol: '£',
|
|
750
|
-
format: '£{amount}'
|
|
751
|
-
}
|
|
752
|
-
];
|
|
753
|
-
this.fallbackLocaleProfiles = [
|
|
754
|
-
{
|
|
755
|
-
...AXUSLocaleProfile,
|
|
756
|
-
code: 'en-US',
|
|
757
|
-
title: 'English (United States)',
|
|
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
|
-
},
|
|
789
|
-
{
|
|
790
|
-
code: 'America/Los_Angeles',
|
|
791
|
-
title: 'Pacific Time (US & Canada)',
|
|
792
|
-
offset: '-08:00',
|
|
793
|
-
iana: 'America/Los_Angeles',
|
|
794
|
-
abbr: 'PST'
|
|
795
|
-
},
|
|
796
|
-
{
|
|
797
|
-
code: 'Europe/London',
|
|
798
|
-
title: 'Greenwich Mean Time',
|
|
799
|
-
offset: '+00:00',
|
|
800
|
-
iana: 'Europe/London',
|
|
801
|
-
abbr: 'GMT'
|
|
802
|
-
}
|
|
803
|
-
];
|
|
804
|
-
}
|
|
805
|
-
//#endregion
|
|
806
|
-
async getCountries() {
|
|
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
|
-
}
|
|
835
|
-
}
|
|
836
|
-
async getProvinces(countryId) {
|
|
837
|
-
let params = new HttpParams();
|
|
838
|
-
if (countryId) {
|
|
839
|
-
params = params.set('countryId', countryId);
|
|
840
|
-
}
|
|
841
|
-
try {
|
|
842
|
-
return await firstValueFrom(this.http.get(`${this.baseUrl}/provinces`, { params }).pipe(catchError(() => of(this.fallbackProvinces))));
|
|
843
|
-
}
|
|
844
|
-
catch {
|
|
845
|
-
return this.fallbackProvinces;
|
|
846
|
-
}
|
|
847
|
-
}
|
|
848
|
-
async getCities(filter) {
|
|
849
|
-
let params = new HttpParams();
|
|
850
|
-
if (filter?.countryId) {
|
|
851
|
-
params = params.set('countryId', filter.countryId);
|
|
852
|
-
}
|
|
853
|
-
if (filter?.provinceId) {
|
|
854
|
-
params = params.set('provinceId', filter.provinceId);
|
|
855
|
-
}
|
|
856
|
-
try {
|
|
857
|
-
return await firstValueFrom(this.http.get(`${this.baseUrl}/cities`, { params }).pipe(catchError(() => of(this.fallbackCities))));
|
|
858
|
-
}
|
|
859
|
-
catch {
|
|
860
|
-
return this.fallbackCities;
|
|
861
|
-
}
|
|
862
|
-
}
|
|
863
|
-
async getCurrencies() {
|
|
864
|
-
try {
|
|
865
|
-
return await firstValueFrom(this.http.get(`${this.baseUrl}/currencies`).pipe(catchError(() => of(this.fallbackCurrencies))));
|
|
866
|
-
}
|
|
867
|
-
catch {
|
|
868
|
-
return this.fallbackCurrencies;
|
|
869
|
-
}
|
|
870
|
-
}
|
|
871
|
-
async getLocaleProfiles() {
|
|
872
|
-
try {
|
|
873
|
-
return await firstValueFrom(this.http.get(`${this.baseUrl}/locale-profiles`).pipe(catchError(() => of(this.fallbackLocaleProfiles))));
|
|
874
|
-
}
|
|
875
|
-
catch {
|
|
876
|
-
return this.fallbackLocaleProfiles;
|
|
877
|
-
}
|
|
878
|
-
}
|
|
879
|
-
async getLanguages() {
|
|
880
|
-
try {
|
|
881
|
-
return await firstValueFrom(this.http.get(`${this.baseUrl}/languages`).pipe(catchError(() => of(this.fallbackLanguages))));
|
|
882
|
-
}
|
|
883
|
-
catch {
|
|
884
|
-
return this.fallbackLanguages;
|
|
885
|
-
}
|
|
886
|
-
}
|
|
887
|
-
async getAvailableLanguages() {
|
|
888
|
-
try {
|
|
889
|
-
return await firstValueFrom(this.http.get(`${this.baseUrl}/available-languages`).pipe(catchError(() => of(this.fallbackLanguages))));
|
|
890
|
-
}
|
|
891
|
-
catch {
|
|
892
|
-
return this.fallbackLanguages;
|
|
893
|
-
}
|
|
894
|
-
}
|
|
895
|
-
async getBrowserTimeZoneCode() {
|
|
896
|
-
return Intl.DateTimeFormat().resolvedOptions().timeZone;
|
|
897
|
-
}
|
|
898
|
-
async getTimeZones() {
|
|
899
|
-
try {
|
|
900
|
-
return await firstValueFrom(this.http.get(`${this.baseUrl}/timezones`).pipe(catchError(() => of(this.fallbackTimeZones))));
|
|
901
|
-
}
|
|
902
|
-
catch {
|
|
903
|
-
return this.fallbackTimeZones;
|
|
904
|
-
}
|
|
905
|
-
}
|
|
906
|
-
}
|
|
907
|
-
|
|
908
774
|
class AXCApiModule {
|
|
909
|
-
static { this.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "20.1.
|
|
910
|
-
static { this.ɵmod = i0.ɵɵngDeclareNgModule({ minVersion: "14.0.0", version: "20.1.
|
|
911
|
-
static { this.ɵinj = i0.ɵɵngDeclareInjector({ minVersion: "12.0.0", version: "20.1.
|
|
775
|
+
static { this.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "20.1.4", ngImport: i0, type: AXCApiModule, deps: [], target: i0.ɵɵFactoryTarget.NgModule }); }
|
|
776
|
+
static { this.ɵmod = i0.ɵɵngDeclareNgModule({ minVersion: "14.0.0", version: "20.1.4", ngImport: i0, type: AXCApiModule, imports: [i1$1.OAuthModule, i2.AXPAuthModule, AXCUtilsModule] }); }
|
|
777
|
+
static { this.ɵinj = i0.ɵɵngDeclareInjector({ minVersion: "12.0.0", version: "20.1.4", ngImport: i0, type: AXCApiModule, providers: [
|
|
912
778
|
{
|
|
913
779
|
provide: AXPEntityStorageService,
|
|
914
780
|
useClass: AXCApiEntityStorageService,
|
|
915
781
|
},
|
|
916
|
-
{
|
|
917
|
-
provide: AXPRegionalService,
|
|
918
|
-
useClass: AXCRegionalApiService,
|
|
919
|
-
},
|
|
920
782
|
{
|
|
921
783
|
provide: AXPFileStorageService,
|
|
922
784
|
useClass: AXCFileStorageApiService,
|
|
923
785
|
},
|
|
924
|
-
|
|
925
|
-
|
|
926
|
-
|
|
927
|
-
|
|
786
|
+
{
|
|
787
|
+
provide: AXP_TENANT_LOADER,
|
|
788
|
+
useClass: AXMOidcTenantLoader,
|
|
789
|
+
},
|
|
928
790
|
{
|
|
929
791
|
provide: AXP_APPLICATION_LOADER,
|
|
930
792
|
useClass: AXMOidcApplicationLoader,
|
|
@@ -946,35 +808,33 @@ class AXCApiModule {
|
|
|
946
808
|
},
|
|
947
809
|
], imports: [OAuthModule.forRoot(),
|
|
948
810
|
AXPAuthModule.forRoot({
|
|
949
|
-
strategies: [],
|
|
950
|
-
})
|
|
811
|
+
strategies: [AXCAPIOidcStrategy],
|
|
812
|
+
}),
|
|
813
|
+
AXCUtilsModule] }); }
|
|
951
814
|
}
|
|
952
|
-
i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "20.1.
|
|
815
|
+
i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "20.1.4", ngImport: i0, type: AXCApiModule, decorators: [{
|
|
953
816
|
type: NgModule,
|
|
954
817
|
args: [{
|
|
955
818
|
imports: [
|
|
956
819
|
OAuthModule.forRoot(),
|
|
957
820
|
AXPAuthModule.forRoot({
|
|
958
|
-
strategies: [],
|
|
821
|
+
strategies: [AXCAPIOidcStrategy],
|
|
959
822
|
}),
|
|
823
|
+
AXCUtilsModule,
|
|
960
824
|
],
|
|
961
825
|
providers: [
|
|
962
826
|
{
|
|
963
827
|
provide: AXPEntityStorageService,
|
|
964
828
|
useClass: AXCApiEntityStorageService,
|
|
965
829
|
},
|
|
966
|
-
{
|
|
967
|
-
provide: AXPRegionalService,
|
|
968
|
-
useClass: AXCRegionalApiService,
|
|
969
|
-
},
|
|
970
830
|
{
|
|
971
831
|
provide: AXPFileStorageService,
|
|
972
832
|
useClass: AXCFileStorageApiService,
|
|
973
833
|
},
|
|
974
|
-
|
|
975
|
-
|
|
976
|
-
|
|
977
|
-
|
|
834
|
+
{
|
|
835
|
+
provide: AXP_TENANT_LOADER,
|
|
836
|
+
useClass: AXMOidcTenantLoader,
|
|
837
|
+
},
|
|
978
838
|
{
|
|
979
839
|
provide: AXP_APPLICATION_LOADER,
|
|
980
840
|
useClass: AXMOidcApplicationLoader,
|
|
@@ -998,9 +858,280 @@ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "20.1.3", ngImpor
|
|
|
998
858
|
}]
|
|
999
859
|
}] });
|
|
1000
860
|
|
|
861
|
+
//#region ---- Class Definition ----
|
|
862
|
+
class APIGoogleStrategy extends AXPAuthStrategy {
|
|
863
|
+
constructor() {
|
|
864
|
+
super();
|
|
865
|
+
this.aXMAuthConfigs = inject(AXM_AUTH_CONFIG_TOKEN);
|
|
866
|
+
this.oauthService = inject(OAuthService);
|
|
867
|
+
this.http = inject(HttpClient);
|
|
868
|
+
this.sessionService = inject(AXPSessionService);
|
|
869
|
+
this.router = inject(Router);
|
|
870
|
+
this.externalAuthorizationService = inject(AXCExternalAuthorizationService);
|
|
871
|
+
this.tenantLoader = inject(AXP_TENANT_LOADER);
|
|
872
|
+
this.applicationLoader = inject(AXP_APPLICATION_LOADER);
|
|
873
|
+
}
|
|
874
|
+
get name() {
|
|
875
|
+
return 'google';
|
|
876
|
+
}
|
|
877
|
+
async configureOAuth() {
|
|
878
|
+
if (this.openidConfigurationInfo)
|
|
879
|
+
return;
|
|
880
|
+
if (!this.authConfig) {
|
|
881
|
+
if (!this.aXMAuthConfigs.authConfig) {
|
|
882
|
+
throw new Error('authConfig is missing');
|
|
883
|
+
}
|
|
884
|
+
this.authConfig = this.aXMAuthConfigs.authConfig;
|
|
885
|
+
}
|
|
886
|
+
this.oauthService.configure(this.authConfig);
|
|
887
|
+
this.oauthService.setStorage(localStorage);
|
|
888
|
+
this.openidConfigurationInfo = await this.oauthService.loadDiscoveryDocument();
|
|
889
|
+
if (!this.openidConfigurationInfo) {
|
|
890
|
+
throw new Error('openidConfigurationInfo is missing');
|
|
891
|
+
}
|
|
892
|
+
this.oauthService.events.subscribe(async (event) => {
|
|
893
|
+
// console.log('event', event);
|
|
894
|
+
// if (event.type === 'token_received') {
|
|
895
|
+
// console.log('Token has been refreshed');
|
|
896
|
+
// }
|
|
897
|
+
// if (event.type === 'token_expires') {
|
|
898
|
+
// console.log('Token is about to expire. Triggering silent refresh...');
|
|
899
|
+
// }
|
|
900
|
+
});
|
|
901
|
+
const oidcJson = localStorage.getItem(AXPSessionService.SESSION_KEY);
|
|
902
|
+
if (oidcJson) {
|
|
903
|
+
const authData = JSON.parse(oidcJson);
|
|
904
|
+
if (authData) {
|
|
905
|
+
this.sessionService.setSession(authData);
|
|
906
|
+
if (authData.expiresIn && new Date(authData.expiresIn) < new Date()) {
|
|
907
|
+
if (authData.expiresIn) {
|
|
908
|
+
this.sessionService.refreshToken();
|
|
909
|
+
}
|
|
910
|
+
else {
|
|
911
|
+
this.signout();
|
|
912
|
+
}
|
|
913
|
+
}
|
|
914
|
+
}
|
|
915
|
+
}
|
|
916
|
+
}
|
|
917
|
+
async signin(credentials) {
|
|
918
|
+
const providerName = credentials['strategy'];
|
|
919
|
+
await this.externalAuthorizationService.signin(providerName);
|
|
920
|
+
}
|
|
921
|
+
async signout() {
|
|
922
|
+
localStorage.removeItem('pkce_code_verifier');
|
|
923
|
+
localStorage.removeItem('oauth_provider');
|
|
924
|
+
console.log('User signed out');
|
|
925
|
+
}
|
|
926
|
+
async refreshToken(context) {
|
|
927
|
+
try {
|
|
928
|
+
await this.configureOAuth();
|
|
929
|
+
if (!this.authConfig || !this.authConfig.clientId) {
|
|
930
|
+
throw new Error('authConfig or clientId is missing');
|
|
931
|
+
}
|
|
932
|
+
const authData = this.loadAuthData();
|
|
933
|
+
if (!authData) {
|
|
934
|
+
return { succeed: false };
|
|
935
|
+
}
|
|
936
|
+
const refreshToken = authData.refreshToken;
|
|
937
|
+
if (!refreshToken) {
|
|
938
|
+
return { succeed: false };
|
|
939
|
+
}
|
|
940
|
+
const body = new URLSearchParams({
|
|
941
|
+
grant_type: 'refresh_token',
|
|
942
|
+
client_id: this.authConfig.clientId,
|
|
943
|
+
refresh_token: refreshToken,
|
|
944
|
+
});
|
|
945
|
+
const response = await fetch(this.openidConfigurationInfo.info.discoveryDocument.token_endpoint, {
|
|
946
|
+
method: 'POST',
|
|
947
|
+
headers: { 'Content-Type': 'application/x-www-form-urlencoded' },
|
|
948
|
+
body: body.toString(),
|
|
949
|
+
});
|
|
950
|
+
if (!response.ok) {
|
|
951
|
+
throw new Error(`Token refresh failed: ${response.status} ${response.statusText}`);
|
|
952
|
+
}
|
|
953
|
+
const tokenData = await response.json();
|
|
954
|
+
// Extract user information from the refreshed token
|
|
955
|
+
const payload = JwtUtil.parseJwt(tokenData.id_token);
|
|
956
|
+
const user = {
|
|
957
|
+
id: payload['sub'] || '',
|
|
958
|
+
title: payload['name'] || payload['email'] || '',
|
|
959
|
+
name: payload['name'] || payload['email'] || '',
|
|
960
|
+
avatar: payload['picture'] || '',
|
|
961
|
+
};
|
|
962
|
+
const tenant = payload['tenantid'] || payload['tenant']
|
|
963
|
+
? {
|
|
964
|
+
id: payload['tenantid'] || payload['tenant'] || '',
|
|
965
|
+
name: payload['tenantname'] || '',
|
|
966
|
+
title: payload['tenanttitle'] || '',
|
|
967
|
+
}
|
|
968
|
+
: undefined;
|
|
969
|
+
const application = payload['applicationid'] || payload['application']
|
|
970
|
+
? {
|
|
971
|
+
id: payload['applicationid'] || payload['application'] || '',
|
|
972
|
+
name: payload['applicationname'] || '',
|
|
973
|
+
title: payload['applicationtitle'] || '',
|
|
974
|
+
}
|
|
975
|
+
: undefined;
|
|
976
|
+
const sessionData = {
|
|
977
|
+
accessToken: tokenData.access_token,
|
|
978
|
+
refreshToken: tokenData.refresh_token,
|
|
979
|
+
idToken: tokenData.id_token,
|
|
980
|
+
strategy: 'google',
|
|
981
|
+
expiresIn: TimeUtil.calculateExpireInDate(tokenData.expires_in || 0),
|
|
982
|
+
user,
|
|
983
|
+
tenant,
|
|
984
|
+
application,
|
|
985
|
+
};
|
|
986
|
+
return {
|
|
987
|
+
succeed: true,
|
|
988
|
+
data: {
|
|
989
|
+
...sessionData,
|
|
990
|
+
user: sessionData.user,
|
|
991
|
+
},
|
|
992
|
+
};
|
|
993
|
+
}
|
|
994
|
+
catch (error) {
|
|
995
|
+
console.error('Error refreshing token', error);
|
|
996
|
+
return { succeed: false };
|
|
997
|
+
}
|
|
998
|
+
}
|
|
999
|
+
async updateToken(params) {
|
|
1000
|
+
try {
|
|
1001
|
+
// Ensure OAuth is configured first
|
|
1002
|
+
if (!this.openidConfigurationInfo) {
|
|
1003
|
+
await this.configureOAuth();
|
|
1004
|
+
}
|
|
1005
|
+
// If params contains 'code', exchange it for tokens
|
|
1006
|
+
if (params['code']) {
|
|
1007
|
+
const code = params['code'];
|
|
1008
|
+
const redirectUri = params['redirectUri'] || this.authConfig.redirectUri;
|
|
1009
|
+
const clientId = params['clientId'] || this.authConfig.clientId;
|
|
1010
|
+
const tokenEndpoint = this.openidConfigurationInfo.info.discoveryDocument.token_endpoint;
|
|
1011
|
+
// Get code_verifier from localStorage (PKCE)
|
|
1012
|
+
const codeVerifier = localStorage.getItem('pkce_code_verifier');
|
|
1013
|
+
localStorage.removeItem('pkce_code_verifier');
|
|
1014
|
+
if (!codeVerifier) {
|
|
1015
|
+
throw new Error('Code verifier not found. Please try signing in again.');
|
|
1016
|
+
}
|
|
1017
|
+
// Prepare body for token request
|
|
1018
|
+
const body = new URLSearchParams({
|
|
1019
|
+
grant_type: 'authorization_code',
|
|
1020
|
+
client_id: clientId,
|
|
1021
|
+
code_verifier: codeVerifier,
|
|
1022
|
+
code: code,
|
|
1023
|
+
redirect_uri: redirectUri,
|
|
1024
|
+
});
|
|
1025
|
+
// Call the token endpoint
|
|
1026
|
+
const response = await fetch(tokenEndpoint, {
|
|
1027
|
+
method: 'POST',
|
|
1028
|
+
headers: { 'Content-Type': 'application/x-www-form-urlencoded' },
|
|
1029
|
+
body: body.toString(),
|
|
1030
|
+
});
|
|
1031
|
+
if (!response.ok) {
|
|
1032
|
+
throw new Error(`Token exchange failed: ${response.status} ${response.statusText}`);
|
|
1033
|
+
}
|
|
1034
|
+
const tokenData = await response.json();
|
|
1035
|
+
if (!tokenData) {
|
|
1036
|
+
throw new Error('Token data not found');
|
|
1037
|
+
}
|
|
1038
|
+
// Parse the ID token to extract user information
|
|
1039
|
+
const payload = JwtUtil.parseJwt(tokenData.id_token);
|
|
1040
|
+
if (!payload) {
|
|
1041
|
+
throw new Error('Payload not found');
|
|
1042
|
+
}
|
|
1043
|
+
const user = {
|
|
1044
|
+
id: payload['sub'] || '',
|
|
1045
|
+
title: payload['name'] || payload['email'] || '',
|
|
1046
|
+
name: payload['name'] || payload['email'] || '',
|
|
1047
|
+
avatar: payload['picture'] || '',
|
|
1048
|
+
};
|
|
1049
|
+
const tenant = payload['tenantid'] || payload['tenant']
|
|
1050
|
+
? {
|
|
1051
|
+
id: payload['tenantid'] || payload['tenant'] || '',
|
|
1052
|
+
name: payload['tenantname'] || '',
|
|
1053
|
+
title: payload['tenanttitle'] || '',
|
|
1054
|
+
}
|
|
1055
|
+
: undefined;
|
|
1056
|
+
const application = payload['applicationid'] || payload['application']
|
|
1057
|
+
? {
|
|
1058
|
+
id: payload['applicationid'] || payload['application'] || '',
|
|
1059
|
+
name: payload['applicationname'] || '',
|
|
1060
|
+
title: payload['applicationtitle'] || '',
|
|
1061
|
+
}
|
|
1062
|
+
: undefined;
|
|
1063
|
+
return {
|
|
1064
|
+
succeed: true,
|
|
1065
|
+
data: {
|
|
1066
|
+
accessToken: tokenData.access_token,
|
|
1067
|
+
refreshToken: tokenData.refresh_token,
|
|
1068
|
+
idToken: tokenData.id_token,
|
|
1069
|
+
expiresIn: TimeUtil.calculateExpireInDate(tokenData.expires_in || 0),
|
|
1070
|
+
user,
|
|
1071
|
+
tenant,
|
|
1072
|
+
application,
|
|
1073
|
+
},
|
|
1074
|
+
};
|
|
1075
|
+
}
|
|
1076
|
+
// get Authorizeation Code
|
|
1077
|
+
else {
|
|
1078
|
+
// Extract parameters
|
|
1079
|
+
// Support both direct id fields and nested tenant/application objects
|
|
1080
|
+
const tenantId = params['tenantId'] ?? params['tenant']?.id ?? null;
|
|
1081
|
+
const applicationId = params['applicationId'] ?? params['application']?.id ?? null;
|
|
1082
|
+
const redirectUri = params['redirectUri'] || this.authConfig.redirectUri;
|
|
1083
|
+
const scope = params['scope'] || this.authConfig.scope;
|
|
1084
|
+
// Generate PKCE code verifier and challenge
|
|
1085
|
+
const codeVerifier = PkceUtil.generateRandomString(128);
|
|
1086
|
+
localStorage.setItem('pkce_code_verifier', codeVerifier);
|
|
1087
|
+
const codeChallenge = await PkceUtil.generateCodeChallenge(codeVerifier);
|
|
1088
|
+
// Build authorization URL
|
|
1089
|
+
const authorizeEndpoint = this.openidConfigurationInfo.info.discoveryDocument.authorization_endpoint;
|
|
1090
|
+
const clientId = this.authConfig.clientId;
|
|
1091
|
+
const responseType = 'code';
|
|
1092
|
+
const state = Math.random().toString(36).substring(2);
|
|
1093
|
+
const queryParams = [
|
|
1094
|
+
`response_type=${encodeURIComponent(responseType)}`,
|
|
1095
|
+
`client_id=${encodeURIComponent(clientId)}`,
|
|
1096
|
+
`redirect_uri=${encodeURIComponent(redirectUri)}`,
|
|
1097
|
+
`scope=${encodeURIComponent(scope)}`,
|
|
1098
|
+
`state=${encodeURIComponent(state)}`,
|
|
1099
|
+
tenantId ? `tenant_id=${encodeURIComponent(tenantId)}` : null,
|
|
1100
|
+
applicationId ? `application_id=${encodeURIComponent(applicationId)}` : null,
|
|
1101
|
+
`code_challenge=${encodeURIComponent(codeChallenge)}`,
|
|
1102
|
+
`code_challenge_method=S256`,
|
|
1103
|
+
]
|
|
1104
|
+
.filter(Boolean)
|
|
1105
|
+
.join('&');
|
|
1106
|
+
const authorizeUrl = `${authorizeEndpoint}?${queryParams}`;
|
|
1107
|
+
window.location.href = authorizeUrl;
|
|
1108
|
+
await new Promise(() => { });
|
|
1109
|
+
return;
|
|
1110
|
+
}
|
|
1111
|
+
}
|
|
1112
|
+
catch (error) {
|
|
1113
|
+
console.error('Error in updateToken:', error);
|
|
1114
|
+
throw error;
|
|
1115
|
+
}
|
|
1116
|
+
}
|
|
1117
|
+
loadAuthData() {
|
|
1118
|
+
const sessionData = this.sessionService.getSessionData();
|
|
1119
|
+
return sessionData || undefined;
|
|
1120
|
+
}
|
|
1121
|
+
handleError(error) {
|
|
1122
|
+
console.error('Authentication error:', error);
|
|
1123
|
+
throw error;
|
|
1124
|
+
}
|
|
1125
|
+
static { this.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "20.1.4", ngImport: i0, type: APIGoogleStrategy, deps: [], target: i0.ɵɵFactoryTarget.Injectable }); }
|
|
1126
|
+
static { this.ɵprov = i0.ɵɵngDeclareInjectable({ minVersion: "12.0.0", version: "20.1.4", ngImport: i0, type: APIGoogleStrategy }); }
|
|
1127
|
+
}
|
|
1128
|
+
i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "20.1.4", ngImport: i0, type: APIGoogleStrategy, decorators: [{
|
|
1129
|
+
type: Injectable
|
|
1130
|
+
}], ctorParameters: () => [] });
|
|
1131
|
+
|
|
1001
1132
|
/**
|
|
1002
1133
|
* Generated bundle index. Do not edit.
|
|
1003
1134
|
*/
|
|
1004
1135
|
|
|
1005
|
-
export { AXCApiEntityStorageService, AXCApiModule, AXMConfigurationService, AXMOidcApplicationLoader, AXMOidcFeatureLoader, AXMOidcPermissionLoader,
|
|
1136
|
+
export { APIGoogleStrategy, AXCAPIOidcStrategy, AXCApiEntityStorageService, AXCApiModule, AXMConfigurationService, AXMOidcApplicationLoader, AXMOidcFeatureLoader, AXMOidcPermissionLoader, AXMOidcTenantLoader };
|
|
1006
1137
|
//# sourceMappingURL=acorex-connectivity-api.mjs.map
|