ef-keycloak-connect 1.8.2-RC2 → 1.8.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/.vscode/settings.json +2 -0
- package/README.md +16 -1
- package/package.json +1 -1
- package/services/ciscoSyncService.js +7 -9
- package/services/keycloakService.js +377 -0
package/README.md
CHANGED
|
@@ -40,6 +40,7 @@ This adapter is extended from keycloak-connect and have functionalities of both
|
|
|
40
40
|
- getRealmRoles
|
|
41
41
|
- assignRoleToUser
|
|
42
42
|
- authenticateFinesse
|
|
43
|
+
- createRealmAsTenant
|
|
43
44
|
|
|
44
45
|
```
|
|
45
46
|
### Example
|
|
@@ -98,7 +99,9 @@ Sample `config` is given below:
|
|
|
98
99
|
"ef-server-url": "https://<cx instance fqdn>/unified-admin/",
|
|
99
100
|
"FINESSE_USERNAME_ADMIN": "<cisco admin username>",
|
|
100
101
|
"FINESSE_PASSWORD_ADMIN": "<cisco admin username>",
|
|
101
|
-
"SYNC_AGENT_PASSWORD": "<qm sync agent/supervisor password>"
|
|
102
|
+
"SYNC_AGENT_PASSWORD": "<qm sync agent/supervisor password>",
|
|
103
|
+
"MASTER_USERNAME": "master_admin_username",
|
|
104
|
+
"MASTER_PASSWORD": "master_admin_password"
|
|
102
105
|
}
|
|
103
106
|
```
|
|
104
107
|
Here is the definition of each property defined in config file/object.
|
|
@@ -129,6 +132,8 @@ Here is the definition of each property defined in config file/object.
|
|
|
129
132
|
- **FINESSE_PASSWORD_ADMIN:** Finesse Administrator Password of instance in use.
|
|
130
133
|
- **FINESSE_URL**: Finesse Instance URL currently in use.
|
|
131
134
|
- **SYNC_AGENT_PASSWORD**: Password for Users being synced to Keycloak/CX.
|
|
135
|
+
- **MASTER_USERNAME**: Keycloak master admin username.
|
|
136
|
+
- **MASTER_PASSWORD**: Keycloak master password username.
|
|
132
137
|
|
|
133
138
|
For using keycloak-connect features:
|
|
134
139
|
```js
|
|
@@ -420,6 +425,16 @@ It takes a signle argument:
|
|
|
420
425
|
|
|
421
426
|
- adminToken: Admin token is required to authorize the list of roles to return.
|
|
422
427
|
|
|
428
|
+
### createRealmAsTenant(tenantName, realmFile, authzConfigFilePath)
|
|
429
|
+
|
|
430
|
+
This function creates a new Realm as a Teant in keycloak and also import its permission/policies based on configurations given in realm and authz files.
|
|
431
|
+
|
|
432
|
+
It takes 3 arguments:
|
|
433
|
+
|
|
434
|
+
- tenantName: Name of realm that will be created as tenant in keycloak.
|
|
435
|
+
- realmFile: Realm configurations given in a JSON format, against which tenant will be created in keycloak, this is the path of file.
|
|
436
|
+
- authzConfigFilePath: Authz configurations given in a JSON format, against which policies/permissions will be created in keycloak, this is the path of file.
|
|
437
|
+
|
|
423
438
|
### authenticateFinesse(username, password, finesseUrl, userRoles, finesseToken)
|
|
424
439
|
|
|
425
440
|
This function sync finesse user in keycloak, it first authenticates user from finesse, then check for its existance in keycloak. If it exists in keycloak then generates an access_token along with role mapping and return it to user. If user doesn't exist then it creates a user, assign it roles and return the access_token along with role mapping for newly created user.
|
package/package.json
CHANGED
|
@@ -57,8 +57,11 @@ class CiscoSyncService {
|
|
|
57
57
|
|
|
58
58
|
reject( {
|
|
59
59
|
|
|
60
|
-
error_message:
|
|
61
|
-
error_detail: error
|
|
60
|
+
error_message: `Finesse Team Sync Error: Error occured while creating cx core team. TEAM ID: ${ciscoTeam.id}, TEAM NAME: ${ciscoTeam.name}`,
|
|
61
|
+
error_detail: ( error?.status && error?.status == 409 ) ? {
|
|
62
|
+
status: 409,
|
|
63
|
+
reason: `CX Team ${ciscoTeam.name} already exists against this Cisco Team with different ID, Causing Conflict.`
|
|
64
|
+
} : error
|
|
62
65
|
} );
|
|
63
66
|
}
|
|
64
67
|
} );
|
|
@@ -120,9 +123,6 @@ class CiscoSyncService {
|
|
|
120
123
|
}
|
|
121
124
|
} );
|
|
122
125
|
|
|
123
|
-
//testing with only 2 teams for now
|
|
124
|
-
//ciscoTeams = ciscoTeams.slice( 0, 2 );
|
|
125
|
-
|
|
126
126
|
// Iterate over Cisco teams and sync them with CX
|
|
127
127
|
for ( let ciscoTeam of ciscoTeams ) {
|
|
128
128
|
|
|
@@ -1442,8 +1442,6 @@ class CiscoSyncService {
|
|
|
1442
1442
|
} );
|
|
1443
1443
|
}
|
|
1444
1444
|
|
|
1445
|
-
// Output the results
|
|
1446
|
-
|
|
1447
1445
|
return {
|
|
1448
1446
|
agentsToAdd: agentsToAdd,
|
|
1449
1447
|
agentsToRemove: agentsToRemove,
|
|
@@ -1737,8 +1735,8 @@ class CiscoSyncService {
|
|
|
1737
1735
|
}
|
|
1738
1736
|
|
|
1739
1737
|
cxAgents[ ciscoTeamId ].push( {
|
|
1740
|
-
id:
|
|
1741
|
-
username:
|
|
1738
|
+
id: keycloakAgent?.id,
|
|
1739
|
+
username: keycloakAgent?.username
|
|
1742
1740
|
} );
|
|
1743
1741
|
}
|
|
1744
1742
|
} );
|
|
@@ -1,5 +1,6 @@
|
|
|
1
1
|
let session = require( "express-session" );
|
|
2
2
|
let Keycloak = require( "keycloak-connect" );
|
|
3
|
+
const fs = require( 'fs' );
|
|
3
4
|
const Joi = require( "joi" );
|
|
4
5
|
const qrcode = require( "qrcode" );
|
|
5
6
|
const speakeasy = require( 'speakeasy' )
|
|
@@ -4276,6 +4277,382 @@ class KeycloakService extends Keycloak {
|
|
|
4276
4277
|
} );
|
|
4277
4278
|
}
|
|
4278
4279
|
|
|
4280
|
+
// !-------------- Multitenancy -----------------!
|
|
4281
|
+
|
|
4282
|
+
async createRealmAsTenant( tenantName, realmFile, authzConfigFilePath ) {
|
|
4283
|
+
|
|
4284
|
+
return new Promise( async ( resolve, reject ) => {
|
|
4285
|
+
|
|
4286
|
+
let realmImportSuccessful = false;
|
|
4287
|
+
let mainMessage = "";
|
|
4288
|
+
let realmConfigString = '';
|
|
4289
|
+
let realmData = '';
|
|
4290
|
+
let authzConfigString = '';
|
|
4291
|
+
let authzConfig = '';
|
|
4292
|
+
|
|
4293
|
+
let accessToken;
|
|
4294
|
+
let URL = keycloakConfig[ "auth-server-url" ] + "realms/master/protocol/openid-connect/token";
|
|
4295
|
+
|
|
4296
|
+
let config = {
|
|
4297
|
+
method: "post",
|
|
4298
|
+
url: URL,
|
|
4299
|
+
headers: {
|
|
4300
|
+
"Content-Type": "application/x-www-form-urlencoded",
|
|
4301
|
+
},
|
|
4302
|
+
data: {
|
|
4303
|
+
client_id: "admin-cli",
|
|
4304
|
+
grant_type: "password",
|
|
4305
|
+
username: keycloakConfig[ "MASTER_USERNAME" ],
|
|
4306
|
+
password: keycloakConfig[ "MASTER_PASSWORD" ]
|
|
4307
|
+
},
|
|
4308
|
+
};
|
|
4309
|
+
|
|
4310
|
+
try {
|
|
4311
|
+
|
|
4312
|
+
let adminAccessToken = await requestController.httpRequest( config, true );
|
|
4313
|
+
|
|
4314
|
+
accessToken = adminAccessToken.data.access_token;
|
|
4315
|
+
|
|
4316
|
+
let createRealmUrl = keycloakConfig[ "auth-server-url" ] + 'admin/realms';
|
|
4317
|
+
|
|
4318
|
+
// 1. Read the realm configuration JSON file
|
|
4319
|
+
console.log( `Reading realm configuration from: ${realmFile}` );
|
|
4320
|
+
|
|
4321
|
+
try {
|
|
4322
|
+
|
|
4323
|
+
realmConfigString = await fs.readFileSync( realmFile, 'utf-8' );
|
|
4324
|
+
|
|
4325
|
+
} catch ( fileReadError ) {
|
|
4326
|
+
|
|
4327
|
+
if ( fileReadError.code === 'ENOENT' ) {
|
|
4328
|
+
|
|
4329
|
+
reject( {
|
|
4330
|
+
"error_message": "Error occurred while reading Realm file during Tenant creation process.",
|
|
4331
|
+
"error_detail": {
|
|
4332
|
+
"status": 404,
|
|
4333
|
+
"reason": `Realm configuration file not found at provided path: ${realmFile} `
|
|
4334
|
+
}
|
|
4335
|
+
} );
|
|
4336
|
+
}
|
|
4337
|
+
|
|
4338
|
+
reject( {
|
|
4339
|
+
"error_message": "Error occurred while reading Realm file during Tenant creation process.",
|
|
4340
|
+
"error_detail": {
|
|
4341
|
+
"status": 500,
|
|
4342
|
+
"reason": `Error reading realm configuration file: ${fileReadError.message}. {file path: ${realmFile}} `
|
|
4343
|
+
}
|
|
4344
|
+
} )
|
|
4345
|
+
|
|
4346
|
+
}
|
|
4347
|
+
|
|
4348
|
+
if ( !realmConfigString || realmConfigString.trim() === '' ) {
|
|
4349
|
+
|
|
4350
|
+
reject( {
|
|
4351
|
+
"error_message": "Error occurred while reading Realm file during Tenant creation process.",
|
|
4352
|
+
"error_detail": {
|
|
4353
|
+
"status": 404,
|
|
4354
|
+
"reason": `Provided Realm configuration file to create Tenant is empty. Please provide valid realm file in JSON format. `
|
|
4355
|
+
}
|
|
4356
|
+
} );
|
|
4357
|
+
|
|
4358
|
+
}
|
|
4359
|
+
|
|
4360
|
+
try {
|
|
4361
|
+
|
|
4362
|
+
realmData = JSON.parse( realmConfigString );
|
|
4363
|
+
|
|
4364
|
+
} catch ( parseError ) {
|
|
4365
|
+
|
|
4366
|
+
if ( parseError instanceof SyntaxError ) {
|
|
4367
|
+
|
|
4368
|
+
reject( {
|
|
4369
|
+
"error_message": "Error occurred while parsing Realm file during Tenant creation process.",
|
|
4370
|
+
"error_detail": {
|
|
4371
|
+
"status": 400,
|
|
4372
|
+
"reason": `Invalid JSON in realm configuration file: ${parseError.message} `
|
|
4373
|
+
}
|
|
4374
|
+
} );
|
|
4375
|
+
}
|
|
4376
|
+
|
|
4377
|
+
reject( {
|
|
4378
|
+
"error_message": "Error occurred while parsing Realm file during Tenant creation process.",
|
|
4379
|
+
"error_detail": {
|
|
4380
|
+
"status": 500,
|
|
4381
|
+
"reason": `Error parsing realm configuration file: ${parseError.message}`
|
|
4382
|
+
}
|
|
4383
|
+
} );
|
|
4384
|
+
}
|
|
4385
|
+
|
|
4386
|
+
|
|
4387
|
+
realmData.id = tenantName;
|
|
4388
|
+
realmData.realm = tenantName;
|
|
4389
|
+
|
|
4390
|
+
|
|
4391
|
+
let config1 = {
|
|
4392
|
+
|
|
4393
|
+
method: "post",
|
|
4394
|
+
url: createRealmUrl,
|
|
4395
|
+
headers: {
|
|
4396
|
+
"Content-Type": "application/json",
|
|
4397
|
+
"Authorization": `Bearer ${accessToken}`
|
|
4398
|
+
},
|
|
4399
|
+
data: realmData
|
|
4400
|
+
};
|
|
4401
|
+
|
|
4402
|
+
try {
|
|
4403
|
+
|
|
4404
|
+
let realmCreation = await requestController.httpRequest( config1, false );
|
|
4405
|
+
|
|
4406
|
+
if ( realmCreation.status === 201 ) {
|
|
4407
|
+
|
|
4408
|
+
realmImportSuccessful = true;
|
|
4409
|
+
mainMessage = `Realm '${tenantName}' imported successfully!\n`;
|
|
4410
|
+
|
|
4411
|
+
}
|
|
4412
|
+
|
|
4413
|
+
// --- Authorization Settings Import (if applicable) ---
|
|
4414
|
+
if ( realmImportSuccessful && authzConfigFilePath ) {
|
|
4415
|
+
|
|
4416
|
+
let targetClientIdForAuthz = 'cim';
|
|
4417
|
+
|
|
4418
|
+
console.log( `Proceeding to import authorization settings for client '${targetClientIdForAuthz}' in realm '${tenantName}'.` );
|
|
4419
|
+
let clientUuid = '';
|
|
4420
|
+
|
|
4421
|
+
try {
|
|
4422
|
+
|
|
4423
|
+
// 4. Get the internal UUID of the target client
|
|
4424
|
+
console.log( `Fetching UUID for client '${targetClientIdForAuthz}' in realm '${tenantName}'...` );
|
|
4425
|
+
const getClientUrl = `${keycloakConfig[ "auth-server-url" ]}admin/realms/${tenantName}/clients`;
|
|
4426
|
+
|
|
4427
|
+
let config2 = {
|
|
4428
|
+
|
|
4429
|
+
method: "get",
|
|
4430
|
+
url: getClientUrl,
|
|
4431
|
+
headers: {
|
|
4432
|
+
"Content-Type": "application/json",
|
|
4433
|
+
"Authorization": `Bearer ${accessToken}`
|
|
4434
|
+
},
|
|
4435
|
+
params: {
|
|
4436
|
+
clientId: targetClientIdForAuthz,
|
|
4437
|
+
search: true
|
|
4438
|
+
}
|
|
4439
|
+
};
|
|
4440
|
+
|
|
4441
|
+
const clientSearchResponse = await requestController.httpRequest( config2, false );
|
|
4442
|
+
|
|
4443
|
+
if ( clientSearchResponse.data && clientSearchResponse.data.length > 0 ) {
|
|
4444
|
+
|
|
4445
|
+
// Filter to be sure, as Keycloak might return multiple if clientId is a substring without exact match flag
|
|
4446
|
+
const foundClient = clientSearchResponse?.data?.find( client => client?.clientId === targetClientIdForAuthz );
|
|
4447
|
+
|
|
4448
|
+
if ( foundClient ) {
|
|
4449
|
+
|
|
4450
|
+
clientUuid = foundClient.id;
|
|
4451
|
+
console.log( `Found client UUID: ${clientUuid}` );
|
|
4452
|
+
} else {
|
|
4453
|
+
|
|
4454
|
+
throw new Error( `Client with clientId '${targetClientIdForAuthz}' not found in realm '${tenantName}' after filtering.` );
|
|
4455
|
+
}
|
|
4456
|
+
} else {
|
|
4457
|
+
throw new Error( `Client with clientId '${targetClientIdForAuthz}' not found in realm '${tenantName}'. Response: ${JSON.stringify( clientSearchResponse.data )}` );
|
|
4458
|
+
}
|
|
4459
|
+
|
|
4460
|
+
// 5. Read the authorization settings JSON file
|
|
4461
|
+
console.log( `Reading authorization settings from: ${authzConfigFilePath}` );
|
|
4462
|
+
|
|
4463
|
+
try {
|
|
4464
|
+
|
|
4465
|
+
authzConfigString = await fs.readFileSync( authzConfigFilePath, 'utf-8' );
|
|
4466
|
+
|
|
4467
|
+
} catch ( fileReadError ) {
|
|
4468
|
+
|
|
4469
|
+
if ( fileReadError.code === 'ENOENT' ) {
|
|
4470
|
+
|
|
4471
|
+
reject( {
|
|
4472
|
+
"error_message": `Error occurred while reading Authz file while importing Permissions/Policies in ${targetClientIdForAuthz} during Tenant creation process.`,
|
|
4473
|
+
"error_detail": {
|
|
4474
|
+
"status": 404,
|
|
4475
|
+
"reason": `Authz file not found at provided path: ${authzConfigString}. `
|
|
4476
|
+
}
|
|
4477
|
+
} );
|
|
4478
|
+
}
|
|
4479
|
+
|
|
4480
|
+
reject( {
|
|
4481
|
+
"error_message": `Error occurred while reading Authz file while importing Permissions/Policies in ${targetClientIdForAuthz} during Tenant creation process.`,
|
|
4482
|
+
"error_detail": {
|
|
4483
|
+
"status": 500,
|
|
4484
|
+
"reason": `Error reading authz file: ${fileReadError.message}. {file path: ${authzConfigString}} `
|
|
4485
|
+
}
|
|
4486
|
+
} )
|
|
4487
|
+
|
|
4488
|
+
}
|
|
4489
|
+
|
|
4490
|
+
if ( !authzConfigString || authzConfigString.trim() === '' ) {
|
|
4491
|
+
|
|
4492
|
+
reject( {
|
|
4493
|
+
"error_message": `Error occurred while reading Authz file while importing Permissions/Policies in ${targetClientIdForAuthz} during Tenant creation process.`,
|
|
4494
|
+
"error_detail": {
|
|
4495
|
+
"status": 404,
|
|
4496
|
+
"reason": `Provided authz file to import Permissions/Policies is empty. Please provide valid authz file in JSON format. `
|
|
4497
|
+
}
|
|
4498
|
+
} );
|
|
4499
|
+
|
|
4500
|
+
}
|
|
4501
|
+
|
|
4502
|
+
try {
|
|
4503
|
+
|
|
4504
|
+
authzConfig = JSON.parse( authzConfigString );
|
|
4505
|
+
|
|
4506
|
+
} catch ( parseError ) {
|
|
4507
|
+
|
|
4508
|
+
if ( parseError instanceof SyntaxError ) {
|
|
4509
|
+
|
|
4510
|
+
reject( {
|
|
4511
|
+
"error_message": `Error occurred while parsing Authz file while importing Permissions/Policies in ${targetClientIdForAuthz} during Tenant creation process.`,
|
|
4512
|
+
"error_detail": {
|
|
4513
|
+
"status": 400,
|
|
4514
|
+
"reason": `Invalid JSON in authz configuration file: ${parseError.message} `
|
|
4515
|
+
}
|
|
4516
|
+
} );
|
|
4517
|
+
}
|
|
4518
|
+
|
|
4519
|
+
reject( {
|
|
4520
|
+
"error_message": `Error occurred while parsing Authz file while importing Permissions/Policies in ${targetClientIdForAuthz} during Tenant creation process.`,
|
|
4521
|
+
"error_detail": {
|
|
4522
|
+
"status": 500,
|
|
4523
|
+
"reason": `Error parsing JSON in authz configuration file: ${parseError.message}`
|
|
4524
|
+
}
|
|
4525
|
+
} );
|
|
4526
|
+
}
|
|
4527
|
+
|
|
4528
|
+
|
|
4529
|
+
// 6. Make the API call to Keycloak to import/update authorization settings
|
|
4530
|
+
console.log( `Importing authorization settings for client UUID '${clientUuid}'...` );
|
|
4531
|
+
|
|
4532
|
+
const importAuthzUrl = `${keycloakConfig[ "auth-server-url" ]}admin/realms/${tenantName}/clients/${clientUuid}/authz/resource-server/import`;
|
|
4533
|
+
|
|
4534
|
+
let config3 = {
|
|
4535
|
+
|
|
4536
|
+
method: "post",
|
|
4537
|
+
url: importAuthzUrl,
|
|
4538
|
+
headers: {
|
|
4539
|
+
"Content-Type": "application/json",
|
|
4540
|
+
"Authorization": `Bearer ${accessToken}`
|
|
4541
|
+
},
|
|
4542
|
+
data: authzConfig
|
|
4543
|
+
};
|
|
4544
|
+
|
|
4545
|
+
const authzResponse = await requestController.httpRequest( config3, false );
|
|
4546
|
+
|
|
4547
|
+
try {
|
|
4548
|
+
|
|
4549
|
+
// Keycloak typically returns 204 No Content for successful PUT on authz settings
|
|
4550
|
+
if ( authzResponse.status === 204 || authzResponse.status === 200 || authzResponse.status === 201 ) {
|
|
4551
|
+
|
|
4552
|
+
const authzSuccessMessage = ` Authorization settings for client '${targetClientIdForAuthz}' (UUID: ${clientUuid}) imported successfully into realm '${tenantName}'.`;
|
|
4553
|
+
|
|
4554
|
+
console.log( authzSuccessMessage );
|
|
4555
|
+
mainMessage += `${authzSuccessMessage}`;
|
|
4556
|
+
|
|
4557
|
+
resolve( {
|
|
4558
|
+
|
|
4559
|
+
status: 201,
|
|
4560
|
+
message: mainMessage
|
|
4561
|
+
} );
|
|
4562
|
+
|
|
4563
|
+
} else {
|
|
4564
|
+
|
|
4565
|
+
const authzWarningMessage = ` Authorization settings import for client '${targetClientIdForAuthz}' may have completed with status: ${authzResponse.status}. Response: ${JSON.stringify( authzResponse.data )}`;
|
|
4566
|
+
console.warn( authzWarningMessage );
|
|
4567
|
+
mainMessage += `${authzWarningMessage}`;
|
|
4568
|
+
|
|
4569
|
+
resolve( {
|
|
4570
|
+
|
|
4571
|
+
status: 201,
|
|
4572
|
+
message: mainMessage
|
|
4573
|
+
} );
|
|
4574
|
+
}
|
|
4575
|
+
|
|
4576
|
+
} catch ( er ) {
|
|
4577
|
+
|
|
4578
|
+
console.error( `Error importing authorization settings for client '${targetClientIdForAuthz}':` );
|
|
4579
|
+
|
|
4580
|
+
if ( er?.response ) {
|
|
4581
|
+
|
|
4582
|
+
console.error( 'Keycloak API Error Status (Authz Import):', er?.response?.status );
|
|
4583
|
+
console.error( 'Keycloak API Error Data (Authz Import):', JSON.stringify( er?.response?.data, null, 2 ) );
|
|
4584
|
+
|
|
4585
|
+
} else if ( er?.request ) {
|
|
4586
|
+
|
|
4587
|
+
console.error( 'No response received from Keycloak (Authz Import):', er.request );
|
|
4588
|
+
|
|
4589
|
+
|
|
4590
|
+
} else if ( er?.code === 'ENOENT' && er?.path === authzConfigFilePath ) {
|
|
4591
|
+
|
|
4592
|
+
console.error( 'Authorization settings file not found:', authzConfigFilePath );
|
|
4593
|
+
|
|
4594
|
+
} else {
|
|
4595
|
+
|
|
4596
|
+
console.error( 'Error during authz import request setup or client lookup:', er?.message );
|
|
4597
|
+
}
|
|
4598
|
+
|
|
4599
|
+
let error = await errorService.handleError( er );
|
|
4600
|
+
|
|
4601
|
+
reject( {
|
|
4602
|
+
error_message: "Realm Creation Error: Error while importing permissions/policies in newly created tenant in keycloak from authz file.",
|
|
4603
|
+
error_detail: error
|
|
4604
|
+
} );
|
|
4605
|
+
|
|
4606
|
+
}
|
|
4607
|
+
|
|
4608
|
+
} catch ( er ) {
|
|
4609
|
+
|
|
4610
|
+
let error = await errorService.handleError( er );
|
|
4611
|
+
|
|
4612
|
+
reject( {
|
|
4613
|
+
|
|
4614
|
+
error_message: "Realm Creation Error: Error occurred while fetching list of clients of newly created tenant",
|
|
4615
|
+
error_detail: error
|
|
4616
|
+
} );
|
|
4617
|
+
|
|
4618
|
+
}
|
|
4619
|
+
}
|
|
4620
|
+
|
|
4621
|
+
} catch ( er ) {
|
|
4622
|
+
|
|
4623
|
+
let error = await errorService.handleError( er );
|
|
4624
|
+
|
|
4625
|
+
reject( {
|
|
4626
|
+
error_message: "Realm Creation Error: Error while creating realm in keycloak from realm-file.",
|
|
4627
|
+
error_detail: error
|
|
4628
|
+
} );
|
|
4629
|
+
|
|
4630
|
+
}
|
|
4631
|
+
|
|
4632
|
+
} catch ( error ) {
|
|
4633
|
+
|
|
4634
|
+
if ( error.response ) {
|
|
4635
|
+
|
|
4636
|
+
if ( error.response.data.error_description == "Token is not active" ) {
|
|
4637
|
+
error.response.data.error_description = "Refresh Token Expired: The refresh token has expired. Please log in again.";
|
|
4638
|
+
}
|
|
4639
|
+
|
|
4640
|
+
reject( {
|
|
4641
|
+
status: error.response.status,
|
|
4642
|
+
message: `${error.response.data.error_description}`,
|
|
4643
|
+
} );
|
|
4644
|
+
} else {
|
|
4645
|
+
|
|
4646
|
+
reject( { message: error.message } );
|
|
4647
|
+
}
|
|
4648
|
+
|
|
4649
|
+
}
|
|
4650
|
+
} );
|
|
4651
|
+
|
|
4652
|
+
}
|
|
4653
|
+
|
|
4654
|
+
// !-------------- Multitenancy End -----------------!
|
|
4655
|
+
|
|
4279
4656
|
//start
|
|
4280
4657
|
startUserMonitoring = async ( { pollingInterval }, callback ) => {
|
|
4281
4658
|
|