@rockcarver/frodo-lib 0.11.0
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/.eslintrc +32 -0
- package/.github/ISSUE_TEMPLATE/bug_report.md +30 -0
- package/.github/ISSUE_TEMPLATE/feature_request.md +20 -0
- package/.github/README.md +121 -0
- package/.github/workflows/pipeline.yml +287 -0
- package/.prettierrc +6 -0
- package/CHANGELOG.md +512 -0
- package/CODE_OF_CONDUCT.md +128 -0
- package/LICENSE +21 -0
- package/README.md +8 -0
- package/docs/CONTRIBUTE.md +96 -0
- package/docs/PIPELINE.md +169 -0
- package/docs/images/npm_versioning_guidelines.png +0 -0
- package/docs/images/release_pipeline.png +0 -0
- package/jsconfig.json +6 -0
- package/package.json +95 -0
- package/resources/sampleEntitiesFile.json +8 -0
- package/resources/sampleEnvFile.env +2 -0
- package/src/api/AuthenticateApi.js +33 -0
- package/src/api/BaseApi.js +242 -0
- package/src/api/CirclesOfTrustApi.js +87 -0
- package/src/api/EmailTemplateApi.js +37 -0
- package/src/api/IdmConfigApi.js +88 -0
- package/src/api/LogApi.js +45 -0
- package/src/api/ManagedObjectApi.js +62 -0
- package/src/api/OAuth2ClientApi.js +69 -0
- package/src/api/OAuth2OIDCApi.js +73 -0
- package/src/api/OAuth2ProviderApi.js +32 -0
- package/src/api/RealmApi.js +99 -0
- package/src/api/Saml2Api.js +176 -0
- package/src/api/ScriptApi.js +84 -0
- package/src/api/SecretsApi.js +151 -0
- package/src/api/ServerInfoApi.js +41 -0
- package/src/api/SocialIdentityProvidersApi.js +114 -0
- package/src/api/StartupApi.js +45 -0
- package/src/api/ThemeApi.js +181 -0
- package/src/api/TreeApi.js +207 -0
- package/src/api/VariablesApi.js +104 -0
- package/src/api/utils/ApiUtils.js +77 -0
- package/src/api/utils/ApiUtils.test.js +96 -0
- package/src/api/utils/Base64.js +62 -0
- package/src/index.js +32 -0
- package/src/index.test.js +13 -0
- package/src/ops/AdminOps.js +901 -0
- package/src/ops/AuthenticateOps.js +342 -0
- package/src/ops/CirclesOfTrustOps.js +350 -0
- package/src/ops/ConnectionProfileOps.js +254 -0
- package/src/ops/EmailTemplateOps.js +326 -0
- package/src/ops/IdmOps.js +227 -0
- package/src/ops/IdpOps.js +342 -0
- package/src/ops/JourneyOps.js +2026 -0
- package/src/ops/LogOps.js +357 -0
- package/src/ops/ManagedObjectOps.js +34 -0
- package/src/ops/OAuth2ClientOps.js +151 -0
- package/src/ops/OrganizationOps.js +85 -0
- package/src/ops/RealmOps.js +139 -0
- package/src/ops/SamlOps.js +541 -0
- package/src/ops/ScriptOps.js +211 -0
- package/src/ops/SecretsOps.js +288 -0
- package/src/ops/StartupOps.js +114 -0
- package/src/ops/ThemeOps.js +379 -0
- package/src/ops/VariablesOps.js +185 -0
- package/src/ops/templates/OAuth2ClientTemplate.json +270 -0
- package/src/ops/templates/OrgModelUserAttributesTemplate.json +149 -0
- package/src/ops/templates/cloud/GenericExtensionAttributesTemplate.json +392 -0
- package/src/ops/templates/cloud/managed.json +4119 -0
- package/src/ops/utils/Console.js +434 -0
- package/src/ops/utils/DataProtection.js +92 -0
- package/src/ops/utils/DataProtection.test.js +28 -0
- package/src/ops/utils/ExportImportUtils.js +146 -0
- package/src/ops/utils/ExportImportUtils.test.js +119 -0
- package/src/ops/utils/OpsUtils.js +76 -0
- package/src/ops/utils/Wordwrap.js +11 -0
- package/src/storage/SessionStorage.js +45 -0
- package/src/storage/StaticStorage.js +15 -0
- package/test/e2e/journey/baseline/ForgottenUsername.journey.json +216 -0
- package/test/e2e/journey/baseline/Login.journey.json +205 -0
- package/test/e2e/journey/baseline/PasswordGrant.journey.json +139 -0
- package/test/e2e/journey/baseline/ProgressiveProfile.journey.json +198 -0
- package/test/e2e/journey/baseline/Registration.journey.json +249 -0
- package/test/e2e/journey/baseline/ResetPassword.journey.json +268 -0
- package/test/e2e/journey/baseline/UpdatePassword.journey.json +323 -0
- package/test/e2e/journey/baseline/allAlphaJourneys.journeys.json +1520 -0
- package/test/e2e/journey/delete/ForgottenUsername.journey.json +216 -0
- package/test/e2e/journey/delete/Login.journey.json +205 -0
- package/test/e2e/journey/delete/PasswordGrant.journey.json +139 -0
- package/test/e2e/journey/delete/ProgressiveProfile.journey.json +198 -0
- package/test/e2e/journey/delete/Registration.journey.json +249 -0
- package/test/e2e/journey/delete/ResetPassword.journey.json +268 -0
- package/test/e2e/journey/delete/UpdatePassword.journey.json +323 -0
- package/test/e2e/journey/delete/deleteMe.journey.json +230 -0
- package/test/e2e/journey/list/Disabled.journey.json +43 -0
- package/test/e2e/journey/list/ForgottenUsername.journey.json +216 -0
- package/test/e2e/journey/list/Login.journey.json +205 -0
- package/test/e2e/journey/list/PasswordGrant.journey.json +139 -0
- package/test/e2e/journey/list/ProgressiveProfile.journey.json +198 -0
- package/test/e2e/journey/list/Registration.journey.json +249 -0
- package/test/e2e/journey/list/ResetPassword.journey.json +268 -0
- package/test/e2e/journey/list/UpdatePassword.journey.json +323 -0
- package/test/e2e/setup.js +107 -0
- package/test/e2e/theme/baseline/Contrast.theme.json +95 -0
- package/test/e2e/theme/baseline/Highlander.theme.json +95 -0
- package/test/e2e/theme/baseline/Robroy.theme.json +95 -0
- package/test/e2e/theme/baseline/Starter-Theme.theme.json +94 -0
- package/test/e2e/theme/baseline/Zardoz.theme.json +95 -0
- package/test/e2e/theme/import/Contrast.theme.json +95 -0
- package/test/e2e/theme/import/Highlander.theme.json +95 -0
- package/test/e2e/theme/import/Robroy.theme.json +95 -0
- package/test/e2e/theme/import/Starter-Theme.theme.json +94 -0
- package/test/e2e/theme/import/Zardoz.default.theme.json +95 -0
- package/test/fs_tmp/.gitkeep +2 -0
- package/test/global/setup.js +65 -0
|
@@ -0,0 +1,901 @@
|
|
|
1
|
+
import fs from 'fs';
|
|
2
|
+
import _ from 'lodash';
|
|
3
|
+
import {
|
|
4
|
+
getOAuth2Clients,
|
|
5
|
+
getOAuth2Client,
|
|
6
|
+
putOAuth2Client,
|
|
7
|
+
} from '../api/OAuth2ClientApi.js';
|
|
8
|
+
import { getConfigEntity, putConfigEntity } from '../api/IdmConfigApi.js';
|
|
9
|
+
import { isEqualJson, getRealmManagedUser } from './utils/OpsUtils.js';
|
|
10
|
+
import { getRealmManagedOrganization } from './OrganizationOps.js';
|
|
11
|
+
import { getOAuth2Provider } from '../api/OAuth2ProviderApi.js';
|
|
12
|
+
import { putSecret } from '../api/SecretsApi.js';
|
|
13
|
+
import { clientCredentialsGrant } from '../api/OAuth2OIDCApi.js';
|
|
14
|
+
// import OAUTH2_CLIENT from './templates/OAuth2ClientTemplate.json' assert { type: 'json' };
|
|
15
|
+
// import ORG_MODEL_USER_ATTRIBUTES from './templates/OrgModelUserAttributesTemplate.json' assert { type: 'json' };
|
|
16
|
+
// import GENERIC_EXTENSION_ATTRIBUTES from './templates/cloud/GenericExtensionAttributesTemplate.json' assert { type: 'json' };
|
|
17
|
+
import { printMessage } from './utils/Console.js';
|
|
18
|
+
|
|
19
|
+
const OAUTH2_CLIENT = JSON.parse(
|
|
20
|
+
fs.readFileSync(
|
|
21
|
+
new URL('./templates/OAuth2ClientTemplate.json', import.meta.url)
|
|
22
|
+
)
|
|
23
|
+
);
|
|
24
|
+
const GENERIC_EXTENSION_ATTRIBUTES = JSON.parse(
|
|
25
|
+
fs.readFileSync(
|
|
26
|
+
new URL(
|
|
27
|
+
'./templates/cloud/GenericExtensionAttributesTemplate.json',
|
|
28
|
+
import.meta.url
|
|
29
|
+
)
|
|
30
|
+
)
|
|
31
|
+
);
|
|
32
|
+
|
|
33
|
+
const protectedClients = ['ui', 'idm-provisioning'];
|
|
34
|
+
const protectedSubjects = ['amadmin', 'autoid-resource-server'];
|
|
35
|
+
|
|
36
|
+
const privilegedScopes = [
|
|
37
|
+
'am-introspect-all-tokens',
|
|
38
|
+
'fr:idm:*',
|
|
39
|
+
'fr:idc:esv:*',
|
|
40
|
+
];
|
|
41
|
+
// const privilegedUsers = ['openidm-admin'];
|
|
42
|
+
const privilegedRoles = [
|
|
43
|
+
'internal/role/openidm-authorized',
|
|
44
|
+
'internal/role/openidm-admin',
|
|
45
|
+
];
|
|
46
|
+
|
|
47
|
+
const adminScopes = ['fr:idm:*', 'fr:idc:esv:*'];
|
|
48
|
+
const adminDefaultScopes = ['fr:idm:*'];
|
|
49
|
+
const adminRoles = [
|
|
50
|
+
'internal/role/openidm-authorized',
|
|
51
|
+
'internal/role/openidm-admin',
|
|
52
|
+
];
|
|
53
|
+
const autoIdRoles = [
|
|
54
|
+
'internal/role/platform-provisioning',
|
|
55
|
+
'internal/role/openidm-authorized',
|
|
56
|
+
'internal/role/openidm-admin',
|
|
57
|
+
];
|
|
58
|
+
|
|
59
|
+
/*
|
|
60
|
+
* List all oauth2 clients, which have a corresponding staticUserMapping
|
|
61
|
+
* in the IDM authentication.json:
|
|
62
|
+
{
|
|
63
|
+
"_id": "authentication",
|
|
64
|
+
"rsFilter": {
|
|
65
|
+
...
|
|
66
|
+
"staticUserMapping": [
|
|
67
|
+
{
|
|
68
|
+
"subject": "someOauth2ClientID",
|
|
69
|
+
"localUser": "internal/user/openidm-admin",
|
|
70
|
+
"userRoles": "authzRoles/*",
|
|
71
|
+
"roles": [
|
|
72
|
+
"internal/role/openidm-authorized",
|
|
73
|
+
"internal/role/openidm-admin"
|
|
74
|
+
]
|
|
75
|
+
},
|
|
76
|
+
{
|
|
77
|
+
"subject": "RCSClient",
|
|
78
|
+
"localUser": "internal/user/idm-provisioning"
|
|
79
|
+
}
|
|
80
|
+
]
|
|
81
|
+
}
|
|
82
|
+
}
|
|
83
|
+
*/
|
|
84
|
+
export async function listOAuth2CustomClients() {
|
|
85
|
+
let clients = (await getOAuth2Clients()).data.result;
|
|
86
|
+
clients = clients
|
|
87
|
+
.map((client) => client._id)
|
|
88
|
+
.filter((client) => !protectedClients.includes(client));
|
|
89
|
+
const authentication = (await getConfigEntity('authentication')).data;
|
|
90
|
+
const subjects = authentication.rsFilter.staticUserMapping
|
|
91
|
+
.map((mapping) => mapping.subject)
|
|
92
|
+
.filter((subject) => !protectedSubjects.includes(subject));
|
|
93
|
+
const adminClients = subjects.filter((subject) => clients.includes(subject));
|
|
94
|
+
return adminClients;
|
|
95
|
+
}
|
|
96
|
+
|
|
97
|
+
/*
|
|
98
|
+
* List all oauth2 clients, which have the fr:idm:* scope and a
|
|
99
|
+
* corresponding staticUserMapping in the IDM authentication.json
|
|
100
|
+
* and are assigned admin privileges:
|
|
101
|
+
{
|
|
102
|
+
"_id": "authentication",
|
|
103
|
+
"rsFilter": {
|
|
104
|
+
...
|
|
105
|
+
"staticUserMapping": [
|
|
106
|
+
{
|
|
107
|
+
"subject": "someOauth2ClientID",
|
|
108
|
+
"localUser": "internal/user/openidm-admin",
|
|
109
|
+
"userRoles": "authzRoles/*",
|
|
110
|
+
"roles": [
|
|
111
|
+
"internal/role/openidm-authorized",
|
|
112
|
+
"internal/role/openidm-admin"
|
|
113
|
+
]
|
|
114
|
+
}
|
|
115
|
+
]
|
|
116
|
+
}
|
|
117
|
+
}
|
|
118
|
+
*/
|
|
119
|
+
export async function listOAuth2AdminClients() {
|
|
120
|
+
let clients = (await getOAuth2Clients()).data.result;
|
|
121
|
+
clients = clients
|
|
122
|
+
.filter((client) => {
|
|
123
|
+
let isPrivileged = false;
|
|
124
|
+
if (client.coreOAuth2ClientConfig.scopes) {
|
|
125
|
+
client.coreOAuth2ClientConfig.scopes.forEach((scope) => {
|
|
126
|
+
if (privilegedScopes.includes(scope)) {
|
|
127
|
+
isPrivileged = true;
|
|
128
|
+
}
|
|
129
|
+
});
|
|
130
|
+
}
|
|
131
|
+
return isPrivileged;
|
|
132
|
+
})
|
|
133
|
+
.map((client) => client._id)
|
|
134
|
+
.filter((client) => !protectedClients.includes(client));
|
|
135
|
+
const authentication = (await getConfigEntity('authentication')).data;
|
|
136
|
+
const subjects = authentication.rsFilter.staticUserMapping
|
|
137
|
+
.filter((mapping) => {
|
|
138
|
+
let isPrivileged = false;
|
|
139
|
+
if (mapping.roles) {
|
|
140
|
+
mapping.roles.forEach((role) => {
|
|
141
|
+
if (privilegedRoles.includes(role)) {
|
|
142
|
+
isPrivileged = true;
|
|
143
|
+
}
|
|
144
|
+
});
|
|
145
|
+
}
|
|
146
|
+
return isPrivileged;
|
|
147
|
+
})
|
|
148
|
+
.map((mapping) => mapping.subject)
|
|
149
|
+
.filter((subject) => !protectedSubjects.includes(subject));
|
|
150
|
+
const adminClients = subjects.filter((subject) => clients.includes(subject));
|
|
151
|
+
return adminClients;
|
|
152
|
+
}
|
|
153
|
+
|
|
154
|
+
/*
|
|
155
|
+
* List all static user mappings that are not oauth2 clients in authentication.json
|
|
156
|
+
* and are assigned admin privileges:
|
|
157
|
+
{
|
|
158
|
+
"_id": "authentication",
|
|
159
|
+
"rsFilter": {
|
|
160
|
+
...
|
|
161
|
+
"staticUserMapping": [
|
|
162
|
+
{
|
|
163
|
+
"subject": "amadmin",
|
|
164
|
+
"localUser": "internal/user/openidm-admin",
|
|
165
|
+
"userRoles": "authzRoles/*",
|
|
166
|
+
"roles": [
|
|
167
|
+
"internal/role/openidm-authorized",
|
|
168
|
+
"internal/role/openidm-admin"
|
|
169
|
+
]
|
|
170
|
+
},
|
|
171
|
+
{
|
|
172
|
+
"subject": "idm-provisioning",
|
|
173
|
+
"localUser": "internal/user/idm-provisioning",
|
|
174
|
+
"roles": [
|
|
175
|
+
"internal/role/platform-provisioning"
|
|
176
|
+
]
|
|
177
|
+
},
|
|
178
|
+
{
|
|
179
|
+
"subject": "RCSClient",
|
|
180
|
+
"localUser": "internal/user/idm-provisioning"
|
|
181
|
+
},
|
|
182
|
+
{
|
|
183
|
+
"subject": "autoid-resource-server",
|
|
184
|
+
"localUser": "internal/user/idm-provisioning",
|
|
185
|
+
"roles": [
|
|
186
|
+
"internal/role/platform-provisioning",
|
|
187
|
+
"internal/role/openidm-authorized",
|
|
188
|
+
"internal/role/openidm-admin"
|
|
189
|
+
]
|
|
190
|
+
}
|
|
191
|
+
]
|
|
192
|
+
}
|
|
193
|
+
}
|
|
194
|
+
*/
|
|
195
|
+
export async function listNonOAuth2AdminStaticUserMappings(showProtected) {
|
|
196
|
+
let clients = (await getOAuth2Clients()).data.result;
|
|
197
|
+
clients = clients
|
|
198
|
+
.map((client) => client._id)
|
|
199
|
+
.filter((client) => !protectedClients.includes(client));
|
|
200
|
+
const authentication = (await getConfigEntity('authentication')).data;
|
|
201
|
+
let subjects = authentication.rsFilter.staticUserMapping
|
|
202
|
+
.filter((mapping) => {
|
|
203
|
+
let isPrivileged = false;
|
|
204
|
+
if (mapping.roles) {
|
|
205
|
+
mapping.roles.forEach((role) => {
|
|
206
|
+
if (privilegedRoles.includes(role)) {
|
|
207
|
+
isPrivileged = true;
|
|
208
|
+
}
|
|
209
|
+
});
|
|
210
|
+
}
|
|
211
|
+
return isPrivileged;
|
|
212
|
+
})
|
|
213
|
+
.map((mapping) => mapping.subject);
|
|
214
|
+
if (!showProtected) {
|
|
215
|
+
subjects = subjects.filter(
|
|
216
|
+
(subject) => !protectedSubjects.includes(subject)
|
|
217
|
+
);
|
|
218
|
+
}
|
|
219
|
+
const adminSubjects = subjects.filter(
|
|
220
|
+
(subject) => !clients.includes(subject)
|
|
221
|
+
);
|
|
222
|
+
return adminSubjects;
|
|
223
|
+
}
|
|
224
|
+
|
|
225
|
+
async function getDynamicClientRegistrationScope() {
|
|
226
|
+
const provider = (await getOAuth2Provider()).data;
|
|
227
|
+
return provider.clientDynamicRegistrationConfig
|
|
228
|
+
.dynamicClientRegistrationScope;
|
|
229
|
+
}
|
|
230
|
+
|
|
231
|
+
async function addAdminScopes(clientId, client) {
|
|
232
|
+
const modClient = client;
|
|
233
|
+
const allAdminScopes = adminScopes.concat([
|
|
234
|
+
await getDynamicClientRegistrationScope(),
|
|
235
|
+
]);
|
|
236
|
+
let addScopes = [];
|
|
237
|
+
if (
|
|
238
|
+
modClient.coreOAuth2ClientConfig.scopes &&
|
|
239
|
+
modClient.coreOAuth2ClientConfig.scopes.value
|
|
240
|
+
) {
|
|
241
|
+
addScopes = allAdminScopes.filter((scope) => {
|
|
242
|
+
let add = false;
|
|
243
|
+
if (!modClient.coreOAuth2ClientConfig.scopes.value.includes(scope)) {
|
|
244
|
+
add = true;
|
|
245
|
+
}
|
|
246
|
+
return add;
|
|
247
|
+
});
|
|
248
|
+
modClient.coreOAuth2ClientConfig.scopes.value =
|
|
249
|
+
modClient.coreOAuth2ClientConfig.scopes.value.concat(addScopes);
|
|
250
|
+
} else {
|
|
251
|
+
modClient.coreOAuth2ClientConfig.scopes.value = allAdminScopes;
|
|
252
|
+
}
|
|
253
|
+
let addDefaultScope = false;
|
|
254
|
+
if (
|
|
255
|
+
modClient.coreOAuth2ClientConfig.defaultScopes &&
|
|
256
|
+
modClient.coreOAuth2ClientConfig.defaultScopes.value
|
|
257
|
+
) {
|
|
258
|
+
if (modClient.coreOAuth2ClientConfig.defaultScopes.value.length === 0) {
|
|
259
|
+
addDefaultScope = true;
|
|
260
|
+
modClient.coreOAuth2ClientConfig.defaultScopes.value = adminDefaultScopes;
|
|
261
|
+
} else {
|
|
262
|
+
printMessage(
|
|
263
|
+
`Client "${clientId}" already has default scopes configured, not adding admin default scope.`
|
|
264
|
+
);
|
|
265
|
+
}
|
|
266
|
+
}
|
|
267
|
+
if (addScopes.length > 0 || addDefaultScope) {
|
|
268
|
+
printMessage(`Adding admin scopes to client "${clientId}"...`);
|
|
269
|
+
} else {
|
|
270
|
+
printMessage(`Client "${clientId}" already has admin scopes.`);
|
|
271
|
+
}
|
|
272
|
+
return modClient;
|
|
273
|
+
}
|
|
274
|
+
|
|
275
|
+
function addClientCredentialsGrantType(clientId, client) {
|
|
276
|
+
const modClient = client;
|
|
277
|
+
let modified = false;
|
|
278
|
+
if (
|
|
279
|
+
modClient.advancedOAuth2ClientConfig.grantTypes &&
|
|
280
|
+
modClient.advancedOAuth2ClientConfig.grantTypes.value
|
|
281
|
+
) {
|
|
282
|
+
if (
|
|
283
|
+
!modClient.advancedOAuth2ClientConfig.grantTypes.value.includes(
|
|
284
|
+
'client_credentials'
|
|
285
|
+
)
|
|
286
|
+
) {
|
|
287
|
+
modified = true;
|
|
288
|
+
modClient.advancedOAuth2ClientConfig.grantTypes.value.push(
|
|
289
|
+
'client_credentials'
|
|
290
|
+
);
|
|
291
|
+
}
|
|
292
|
+
} else {
|
|
293
|
+
modClient.advancedOAuth2ClientConfig.grantTypes.value = [
|
|
294
|
+
'client_credentials',
|
|
295
|
+
];
|
|
296
|
+
}
|
|
297
|
+
modClient.advancedOAuth2ClientConfig.grantTypes.inherited = false;
|
|
298
|
+
if (modified) {
|
|
299
|
+
printMessage(
|
|
300
|
+
`Adding client credentials grant type to client "${clientId}"...`
|
|
301
|
+
);
|
|
302
|
+
} else {
|
|
303
|
+
printMessage(
|
|
304
|
+
`Client "${clientId}" already has client credentials grant type.`
|
|
305
|
+
);
|
|
306
|
+
}
|
|
307
|
+
return modClient;
|
|
308
|
+
}
|
|
309
|
+
|
|
310
|
+
async function addAdminStaticUserMapping(name) {
|
|
311
|
+
let authentication = {};
|
|
312
|
+
try {
|
|
313
|
+
authentication = (await getConfigEntity('authentication')).data;
|
|
314
|
+
} catch (error) {
|
|
315
|
+
printMessage(
|
|
316
|
+
`Error reading IDM authentication configuration: ${error.message}`,
|
|
317
|
+
'error'
|
|
318
|
+
);
|
|
319
|
+
}
|
|
320
|
+
let needsAdminMapping = true;
|
|
321
|
+
let addRoles = [];
|
|
322
|
+
const mappings = authentication.rsFilter.staticUserMapping.map((mapping) => {
|
|
323
|
+
// ignore mappings for other subjects
|
|
324
|
+
if (mapping.subject !== name) {
|
|
325
|
+
return mapping;
|
|
326
|
+
}
|
|
327
|
+
needsAdminMapping = false;
|
|
328
|
+
addRoles = adminRoles.filter((role) => {
|
|
329
|
+
let add = false;
|
|
330
|
+
if (!mapping.roles.includes(role)) {
|
|
331
|
+
add = true;
|
|
332
|
+
}
|
|
333
|
+
return add;
|
|
334
|
+
});
|
|
335
|
+
const newMapping = mapping;
|
|
336
|
+
newMapping.roles = newMapping.roles.concat(addRoles);
|
|
337
|
+
return newMapping;
|
|
338
|
+
});
|
|
339
|
+
if (needsAdminMapping) {
|
|
340
|
+
printMessage(`Creating static user mapping for client "${name}"...`);
|
|
341
|
+
mappings.push({
|
|
342
|
+
subject: name,
|
|
343
|
+
localUser: 'internal/user/openidm-admin',
|
|
344
|
+
userRoles: 'authzRoles/*',
|
|
345
|
+
roles: adminRoles,
|
|
346
|
+
});
|
|
347
|
+
}
|
|
348
|
+
authentication.rsFilter.staticUserMapping = mappings;
|
|
349
|
+
if (addRoles.length > 0 || needsAdminMapping) {
|
|
350
|
+
printMessage(
|
|
351
|
+
`Adding admin roles to static user mapping for client "${name}"...`
|
|
352
|
+
);
|
|
353
|
+
try {
|
|
354
|
+
await putConfigEntity('authentication', authentication);
|
|
355
|
+
} catch (putConfigEntityError) {
|
|
356
|
+
printMessage(putConfigEntityError, 'error');
|
|
357
|
+
printMessage(`Error: ${putConfigEntityError}`, 'error');
|
|
358
|
+
}
|
|
359
|
+
} else {
|
|
360
|
+
printMessage(
|
|
361
|
+
`Static user mapping for client "${name}" already has admin roles.`
|
|
362
|
+
);
|
|
363
|
+
}
|
|
364
|
+
}
|
|
365
|
+
|
|
366
|
+
/*
|
|
367
|
+
* Add AutoId static user mapping to authentication.json to enable dashboards and other AutoId-based functionality.
|
|
368
|
+
{
|
|
369
|
+
"_id": "authentication",
|
|
370
|
+
"rsFilter": {
|
|
371
|
+
...
|
|
372
|
+
"staticUserMapping": [
|
|
373
|
+
...
|
|
374
|
+
{
|
|
375
|
+
"subject": "autoid-resource-server",
|
|
376
|
+
"localUser": "internal/user/idm-provisioning",
|
|
377
|
+
"roles": [
|
|
378
|
+
"internal/role/platform-provisioning",
|
|
379
|
+
"internal/role/openidm-authorized",
|
|
380
|
+
"internal/role/openidm-admin"
|
|
381
|
+
]
|
|
382
|
+
}
|
|
383
|
+
]
|
|
384
|
+
}
|
|
385
|
+
}
|
|
386
|
+
*/
|
|
387
|
+
export async function addAutoIdStaticUserMapping() {
|
|
388
|
+
const name = 'autoid-resource-server';
|
|
389
|
+
const authentication = (await getConfigEntity('authentication')).data;
|
|
390
|
+
let needsAdminMapping = true;
|
|
391
|
+
let addRoles = [];
|
|
392
|
+
const mappings = authentication.rsFilter.staticUserMapping.map((mapping) => {
|
|
393
|
+
// ignore mappings for other subjects
|
|
394
|
+
if (mapping.subject !== name) {
|
|
395
|
+
return mapping;
|
|
396
|
+
}
|
|
397
|
+
needsAdminMapping = false;
|
|
398
|
+
addRoles = autoIdRoles.filter((role) => {
|
|
399
|
+
let add = false;
|
|
400
|
+
if (!mapping.roles.includes(role)) {
|
|
401
|
+
add = true;
|
|
402
|
+
}
|
|
403
|
+
return add;
|
|
404
|
+
});
|
|
405
|
+
const newMapping = mapping;
|
|
406
|
+
newMapping.roles = newMapping.roles.concat(addRoles);
|
|
407
|
+
return newMapping;
|
|
408
|
+
});
|
|
409
|
+
if (needsAdminMapping) {
|
|
410
|
+
printMessage(`Creating static user mapping for AutoId client "${name}"...`);
|
|
411
|
+
mappings.push({
|
|
412
|
+
subject: name,
|
|
413
|
+
localUser: 'internal/user/idm-provisioning',
|
|
414
|
+
userRoles: 'authzRoles/*',
|
|
415
|
+
roles: autoIdRoles,
|
|
416
|
+
});
|
|
417
|
+
}
|
|
418
|
+
authentication.rsFilter.staticUserMapping = mappings;
|
|
419
|
+
if (addRoles.length > 0 || needsAdminMapping) {
|
|
420
|
+
printMessage(
|
|
421
|
+
`Adding required roles to static user mapping for AutoId client "${name}"...`
|
|
422
|
+
);
|
|
423
|
+
try {
|
|
424
|
+
await putConfigEntity('authentication', authentication);
|
|
425
|
+
} catch (putConfigEntityError) {
|
|
426
|
+
printMessage(putConfigEntityError, 'error');
|
|
427
|
+
printMessage(`Error: ${putConfigEntityError}`, 'error');
|
|
428
|
+
}
|
|
429
|
+
} else {
|
|
430
|
+
printMessage(
|
|
431
|
+
`Static user mapping for AutoId client "${name}" already has all required roles.`
|
|
432
|
+
);
|
|
433
|
+
}
|
|
434
|
+
}
|
|
435
|
+
|
|
436
|
+
export async function grantOAuth2ClientAdminPrivileges(clientId) {
|
|
437
|
+
let client = (await getOAuth2Client(clientId)).data;
|
|
438
|
+
if (client.coreOAuth2ClientConfig.clientName.value.length === 0) {
|
|
439
|
+
client.coreOAuth2ClientConfig.clientName.value = [clientId];
|
|
440
|
+
}
|
|
441
|
+
if (
|
|
442
|
+
client.advancedOAuth2ClientConfig.descriptions.value.length === 0 ||
|
|
443
|
+
client.advancedOAuth2ClientConfig.descriptions.value[0].startsWith(
|
|
444
|
+
'Modified by Frodo'
|
|
445
|
+
) ||
|
|
446
|
+
client.advancedOAuth2ClientConfig.descriptions.value[0].startsWith(
|
|
447
|
+
'Created by Frodo'
|
|
448
|
+
)
|
|
449
|
+
) {
|
|
450
|
+
client.advancedOAuth2ClientConfig.descriptions.value = [
|
|
451
|
+
`Modified by Frodo on ${new Date().toLocaleString()}`,
|
|
452
|
+
];
|
|
453
|
+
}
|
|
454
|
+
client = await addAdminScopes(clientId, client);
|
|
455
|
+
client = addClientCredentialsGrantType(clientId, client);
|
|
456
|
+
await putOAuth2Client(clientId, client);
|
|
457
|
+
await addAdminStaticUserMapping(clientId);
|
|
458
|
+
}
|
|
459
|
+
|
|
460
|
+
async function removeAdminScopes(name, client) {
|
|
461
|
+
const modClient = client;
|
|
462
|
+
const allAdminScopes = adminScopes.concat([
|
|
463
|
+
await getDynamicClientRegistrationScope(),
|
|
464
|
+
]);
|
|
465
|
+
let finalScopes = [];
|
|
466
|
+
if (
|
|
467
|
+
modClient.coreOAuth2ClientConfig.scopes &&
|
|
468
|
+
modClient.coreOAuth2ClientConfig.scopes.value
|
|
469
|
+
) {
|
|
470
|
+
finalScopes = modClient.coreOAuth2ClientConfig.scopes.value.filter(
|
|
471
|
+
(scope) => !allAdminScopes.includes(scope)
|
|
472
|
+
);
|
|
473
|
+
}
|
|
474
|
+
if (
|
|
475
|
+
modClient.coreOAuth2ClientConfig.scopes.value.length > finalScopes.length
|
|
476
|
+
) {
|
|
477
|
+
printMessage(`Removing admin scopes from client "${name}"...`);
|
|
478
|
+
modClient.coreOAuth2ClientConfig.scopes.value = finalScopes;
|
|
479
|
+
} else {
|
|
480
|
+
printMessage(`Client "${name}" has no admin scopes.`);
|
|
481
|
+
}
|
|
482
|
+
let finalDefaultScopes = [];
|
|
483
|
+
if (
|
|
484
|
+
modClient.coreOAuth2ClientConfig.defaultScopes &&
|
|
485
|
+
modClient.coreOAuth2ClientConfig.defaultScopes.value
|
|
486
|
+
) {
|
|
487
|
+
finalDefaultScopes =
|
|
488
|
+
modClient.coreOAuth2ClientConfig.defaultScopes.value.filter(
|
|
489
|
+
(scope) => !adminDefaultScopes.includes(scope)
|
|
490
|
+
);
|
|
491
|
+
}
|
|
492
|
+
if (
|
|
493
|
+
modClient.coreOAuth2ClientConfig.defaultScopes.value.length >
|
|
494
|
+
finalDefaultScopes.length
|
|
495
|
+
) {
|
|
496
|
+
printMessage(`Removing admin default scopes from client "${name}"...`);
|
|
497
|
+
modClient.coreOAuth2ClientConfig.defaultScopes.value = finalDefaultScopes;
|
|
498
|
+
} else {
|
|
499
|
+
printMessage(`Client "${name}" has no admin default scopes.`);
|
|
500
|
+
}
|
|
501
|
+
return modClient;
|
|
502
|
+
}
|
|
503
|
+
|
|
504
|
+
function removeClientCredentialsGrantType(clientId, client) {
|
|
505
|
+
const modClient = client;
|
|
506
|
+
let modified = false;
|
|
507
|
+
let finalGrantTypes = [];
|
|
508
|
+
if (
|
|
509
|
+
modClient.advancedOAuth2ClientConfig.grantTypes &&
|
|
510
|
+
modClient.advancedOAuth2ClientConfig.grantTypes.value
|
|
511
|
+
) {
|
|
512
|
+
finalGrantTypes =
|
|
513
|
+
modClient.advancedOAuth2ClientConfig.grantTypes.value.filter(
|
|
514
|
+
(grantType) => grantType !== 'client_credentials'
|
|
515
|
+
);
|
|
516
|
+
modified =
|
|
517
|
+
modClient.advancedOAuth2ClientConfig.grantTypes.value.length >
|
|
518
|
+
finalGrantTypes.length;
|
|
519
|
+
}
|
|
520
|
+
if (modified) {
|
|
521
|
+
printMessage(
|
|
522
|
+
`Removing client credentials grant type from client "${clientId}"...`
|
|
523
|
+
);
|
|
524
|
+
modClient.advancedOAuth2ClientConfig.grantTypes.value = finalGrantTypes;
|
|
525
|
+
} else {
|
|
526
|
+
printMessage(
|
|
527
|
+
`Client "${clientId}" does not allow client credentials grant type.`
|
|
528
|
+
);
|
|
529
|
+
}
|
|
530
|
+
return modClient;
|
|
531
|
+
}
|
|
532
|
+
|
|
533
|
+
async function removeAdminStaticUserMapping(name) {
|
|
534
|
+
const authentication = (await getConfigEntity('authentication')).data;
|
|
535
|
+
let finalRoles = [];
|
|
536
|
+
let removeMapping = false;
|
|
537
|
+
let modified = false;
|
|
538
|
+
const mappings = authentication.rsFilter.staticUserMapping
|
|
539
|
+
.map((mapping) => {
|
|
540
|
+
// ignore mappings for other subjects
|
|
541
|
+
if (mapping.subject !== name) {
|
|
542
|
+
return mapping;
|
|
543
|
+
}
|
|
544
|
+
finalRoles = mapping.roles.filter((role) => !adminRoles.includes(role));
|
|
545
|
+
const newMapping = mapping;
|
|
546
|
+
removeMapping = finalRoles.length === 0; // if there are no more roles left on this mapping, flag it for removal
|
|
547
|
+
modified = mapping.roles.length > finalRoles.length; // if there were roles removed, set modified flag
|
|
548
|
+
newMapping.roles = finalRoles;
|
|
549
|
+
return newMapping;
|
|
550
|
+
})
|
|
551
|
+
.filter((mapping) => mapping.subject !== name || !removeMapping);
|
|
552
|
+
authentication.rsFilter.staticUserMapping = mappings;
|
|
553
|
+
if (modified || removeMapping) {
|
|
554
|
+
if (removeMapping) {
|
|
555
|
+
printMessage(`Removing static user mapping for client "${name}"...`);
|
|
556
|
+
} else {
|
|
557
|
+
printMessage(
|
|
558
|
+
`Removing admin roles from static user mapping for client "${name}"...`
|
|
559
|
+
);
|
|
560
|
+
}
|
|
561
|
+
try {
|
|
562
|
+
await putConfigEntity('authentication', authentication);
|
|
563
|
+
} catch (putConfigEntityError) {
|
|
564
|
+
printMessage(putConfigEntityError, 'error');
|
|
565
|
+
printMessage(`Error: ${putConfigEntityError}`, 'error');
|
|
566
|
+
}
|
|
567
|
+
} else {
|
|
568
|
+
printMessage(
|
|
569
|
+
`Static user mapping for client "${name}" has no admin roles.`
|
|
570
|
+
);
|
|
571
|
+
}
|
|
572
|
+
}
|
|
573
|
+
|
|
574
|
+
export async function revokeOAuth2ClientAdminPrivileges(clientId) {
|
|
575
|
+
let client = (await getOAuth2Client(clientId)).data;
|
|
576
|
+
if (client.coreOAuth2ClientConfig.clientName.value.length === 0) {
|
|
577
|
+
client.coreOAuth2ClientConfig.clientName.value = [clientId];
|
|
578
|
+
}
|
|
579
|
+
if (
|
|
580
|
+
client.advancedOAuth2ClientConfig.descriptions.value.length === 0 ||
|
|
581
|
+
client.advancedOAuth2ClientConfig.descriptions.value[0].startsWith(
|
|
582
|
+
'Modified by Frodo'
|
|
583
|
+
) ||
|
|
584
|
+
client.advancedOAuth2ClientConfig.descriptions.value[0].startsWith(
|
|
585
|
+
'Created by Frodo'
|
|
586
|
+
)
|
|
587
|
+
) {
|
|
588
|
+
client.advancedOAuth2ClientConfig.descriptions.value = [
|
|
589
|
+
`Modified by Frodo on ${new Date().toLocaleString()}`,
|
|
590
|
+
];
|
|
591
|
+
}
|
|
592
|
+
client = await removeAdminScopes(clientId, client);
|
|
593
|
+
client = removeClientCredentialsGrantType(clientId, client);
|
|
594
|
+
await putOAuth2Client(clientId, client);
|
|
595
|
+
await removeAdminStaticUserMapping(clientId);
|
|
596
|
+
}
|
|
597
|
+
|
|
598
|
+
export async function createOAuth2ClientWithAdminPrivileges(
|
|
599
|
+
clientId,
|
|
600
|
+
clientSecret
|
|
601
|
+
) {
|
|
602
|
+
let client = OAUTH2_CLIENT;
|
|
603
|
+
client.coreOAuth2ClientConfig.userpassword = clientSecret;
|
|
604
|
+
client.coreOAuth2ClientConfig.clientName.value = [clientId];
|
|
605
|
+
client.advancedOAuth2ClientConfig.descriptions.value = [
|
|
606
|
+
`Created by Frodo on ${new Date().toLocaleString()}`,
|
|
607
|
+
];
|
|
608
|
+
try {
|
|
609
|
+
client = await addAdminScopes(clientId, client);
|
|
610
|
+
await putOAuth2Client(clientId, client);
|
|
611
|
+
await addAdminStaticUserMapping(clientId);
|
|
612
|
+
} catch (error) {
|
|
613
|
+
printMessage(`Error creating oauth2 client: ${error.message}`, 'error');
|
|
614
|
+
}
|
|
615
|
+
}
|
|
616
|
+
|
|
617
|
+
export async function createLongLivedToken(
|
|
618
|
+
clientId,
|
|
619
|
+
clientSecret,
|
|
620
|
+
scope,
|
|
621
|
+
secret,
|
|
622
|
+
lifetime
|
|
623
|
+
) {
|
|
624
|
+
// get oauth2 client
|
|
625
|
+
const client = (await getOAuth2Client(clientId)).data;
|
|
626
|
+
client.userpassword = clientSecret;
|
|
627
|
+
// remember current lifetime
|
|
628
|
+
const rememberedLifetime =
|
|
629
|
+
client.coreOAuth2ClientConfig.accessTokenLifetime.value || 3600;
|
|
630
|
+
// set long token lifetime
|
|
631
|
+
client.coreOAuth2ClientConfig.accessTokenLifetime.value = lifetime;
|
|
632
|
+
await putOAuth2Client(clientId, client);
|
|
633
|
+
const response = (await clientCredentialsGrant(clientId, clientSecret, scope))
|
|
634
|
+
.data;
|
|
635
|
+
const expires = new Date().getTime() + 1000 * response.expires_in;
|
|
636
|
+
response.expires_on = new Date(expires).toLocaleString();
|
|
637
|
+
// reset token lifetime
|
|
638
|
+
client.coreOAuth2ClientConfig.accessTokenLifetime.value = rememberedLifetime;
|
|
639
|
+
await putOAuth2Client(clientId, client);
|
|
640
|
+
// create secret with token as value
|
|
641
|
+
const description = 'Long-lived admin token';
|
|
642
|
+
try {
|
|
643
|
+
await putSecret(secret, response.access_token, description);
|
|
644
|
+
response.secret = secret;
|
|
645
|
+
} catch (error) {
|
|
646
|
+
if (
|
|
647
|
+
_.get(error, 'response.data.code') === 400 &&
|
|
648
|
+
_.get(error, 'response.data.message') ===
|
|
649
|
+
'Failed to create secret, the secret already exists'
|
|
650
|
+
) {
|
|
651
|
+
const newSecret = `${secret}-${expires}`;
|
|
652
|
+
printMessage(
|
|
653
|
+
`esv '${secret}' already exists, using ${newSecret}`,
|
|
654
|
+
'warn'
|
|
655
|
+
);
|
|
656
|
+
await putSecret(newSecret, response.access_token, description);
|
|
657
|
+
response.secret = newSecret;
|
|
658
|
+
}
|
|
659
|
+
}
|
|
660
|
+
delete response.access_token;
|
|
661
|
+
return response;
|
|
662
|
+
}
|
|
663
|
+
|
|
664
|
+
export async function removeStaticUserMapping(subject) {
|
|
665
|
+
const authentication = (await getConfigEntity('authentication')).data;
|
|
666
|
+
let removeMapping = false;
|
|
667
|
+
const mappings = authentication.rsFilter.staticUserMapping.filter(
|
|
668
|
+
(mapping) => {
|
|
669
|
+
// find the subject and flag it
|
|
670
|
+
if (mapping.subject === subject) {
|
|
671
|
+
removeMapping = true;
|
|
672
|
+
}
|
|
673
|
+
// ignore mappings for other subjects
|
|
674
|
+
return mapping.subject !== subject;
|
|
675
|
+
}
|
|
676
|
+
);
|
|
677
|
+
authentication.rsFilter.staticUserMapping = mappings;
|
|
678
|
+
if (removeMapping) {
|
|
679
|
+
printMessage(`Removing static user mapping for subject "${subject}"...`);
|
|
680
|
+
try {
|
|
681
|
+
await putConfigEntity('authentication', authentication);
|
|
682
|
+
} catch (putConfigEntityError) {
|
|
683
|
+
printMessage(putConfigEntityError, 'error');
|
|
684
|
+
printMessage(`Error: ${putConfigEntityError}`, 'error');
|
|
685
|
+
}
|
|
686
|
+
} else {
|
|
687
|
+
printMessage(`No static user mapping for subject "${subject}" found.`);
|
|
688
|
+
}
|
|
689
|
+
}
|
|
690
|
+
|
|
691
|
+
export async function hideGenericExtensionAttributes(
|
|
692
|
+
includeCustomized,
|
|
693
|
+
dryRun
|
|
694
|
+
) {
|
|
695
|
+
const managed = (await getConfigEntity('managed')).data;
|
|
696
|
+
const propertyNames = Object.keys(GENERIC_EXTENSION_ATTRIBUTES);
|
|
697
|
+
const updatedObjects = managed.objects.map((object) => {
|
|
698
|
+
// ignore all other objects
|
|
699
|
+
if (object.name !== getRealmManagedUser()) {
|
|
700
|
+
return object;
|
|
701
|
+
}
|
|
702
|
+
propertyNames.forEach((name) => {
|
|
703
|
+
if (
|
|
704
|
+
isEqualJson(
|
|
705
|
+
GENERIC_EXTENSION_ATTRIBUTES[name],
|
|
706
|
+
object.schema.properties[name],
|
|
707
|
+
['viewable', 'usageDescription']
|
|
708
|
+
) ||
|
|
709
|
+
includeCustomized
|
|
710
|
+
) {
|
|
711
|
+
if (object.schema.properties[name].viewable) {
|
|
712
|
+
printMessage(`${name}: hide`);
|
|
713
|
+
// eslint-disable-next-line no-param-reassign
|
|
714
|
+
object.schema.properties[name].viewable = false;
|
|
715
|
+
} else {
|
|
716
|
+
printMessage(`${name}: ignore (already hidden)`);
|
|
717
|
+
}
|
|
718
|
+
} else {
|
|
719
|
+
printMessage(`${name}: skip (customized)`);
|
|
720
|
+
}
|
|
721
|
+
});
|
|
722
|
+
return object;
|
|
723
|
+
});
|
|
724
|
+
managed.objects = updatedObjects;
|
|
725
|
+
if (dryRun) {
|
|
726
|
+
printMessage('Dry-run only. Changes are not saved.');
|
|
727
|
+
} else {
|
|
728
|
+
try {
|
|
729
|
+
await putConfigEntity('managed', managed);
|
|
730
|
+
} catch (putConfigEntityError) {
|
|
731
|
+
printMessage(putConfigEntityError, 'error');
|
|
732
|
+
printMessage(`Error: ${putConfigEntityError}`, 'error');
|
|
733
|
+
}
|
|
734
|
+
}
|
|
735
|
+
}
|
|
736
|
+
|
|
737
|
+
export async function showGenericExtensionAttributes(
|
|
738
|
+
includeCustomized,
|
|
739
|
+
dryRun
|
|
740
|
+
) {
|
|
741
|
+
const managed = (await getConfigEntity('managed')).data;
|
|
742
|
+
const propertyNames = Object.keys(GENERIC_EXTENSION_ATTRIBUTES);
|
|
743
|
+
const updatedObjects = managed.objects.map((object) => {
|
|
744
|
+
// ignore all other objects
|
|
745
|
+
if (object.name !== getRealmManagedUser()) {
|
|
746
|
+
return object;
|
|
747
|
+
}
|
|
748
|
+
propertyNames.forEach((name) => {
|
|
749
|
+
if (
|
|
750
|
+
isEqualJson(
|
|
751
|
+
GENERIC_EXTENSION_ATTRIBUTES[name],
|
|
752
|
+
object.schema.properties[name],
|
|
753
|
+
['viewable', 'usageDescription']
|
|
754
|
+
) ||
|
|
755
|
+
includeCustomized
|
|
756
|
+
) {
|
|
757
|
+
if (!object.schema.properties[name].viewable) {
|
|
758
|
+
printMessage(`${name}: show`);
|
|
759
|
+
// eslint-disable-next-line no-param-reassign
|
|
760
|
+
object.schema.properties[name].viewable = true;
|
|
761
|
+
} else {
|
|
762
|
+
printMessage(`${name}: ignore (already showing)`);
|
|
763
|
+
}
|
|
764
|
+
} else {
|
|
765
|
+
printMessage(`${name}: skip (customized)`);
|
|
766
|
+
}
|
|
767
|
+
});
|
|
768
|
+
return object;
|
|
769
|
+
});
|
|
770
|
+
managed.objects = updatedObjects;
|
|
771
|
+
if (dryRun) {
|
|
772
|
+
printMessage('Dry-run only. Changes are not saved.');
|
|
773
|
+
} else {
|
|
774
|
+
try {
|
|
775
|
+
await putConfigEntity('managed', managed);
|
|
776
|
+
} catch (putConfigEntityError) {
|
|
777
|
+
printMessage(putConfigEntityError, 'error');
|
|
778
|
+
printMessage(`Error: ${putConfigEntityError}`, 'error');
|
|
779
|
+
}
|
|
780
|
+
}
|
|
781
|
+
}
|
|
782
|
+
|
|
783
|
+
async function repairOrgModelUser(dryRun) {
|
|
784
|
+
const managed = (await getConfigEntity('managed')).data;
|
|
785
|
+
const RDVPs = ['memberOfOrgIDs'];
|
|
786
|
+
let repairData = false;
|
|
787
|
+
const updatedObjects = managed.objects.map((object) => {
|
|
788
|
+
// ignore all other objects
|
|
789
|
+
if (object.name !== getRealmManagedUser()) {
|
|
790
|
+
return object;
|
|
791
|
+
}
|
|
792
|
+
printMessage(`${object.name}: checking...`);
|
|
793
|
+
RDVPs.forEach((name) => {
|
|
794
|
+
if (!object.schema.properties[name].queryConfig.flattenProperties) {
|
|
795
|
+
printMessage(`- ${name}: repairing - needs flattening`, 'warn');
|
|
796
|
+
// eslint-disable-next-line no-param-reassign
|
|
797
|
+
object.schema.properties[name].queryConfig.flattenProperties = true;
|
|
798
|
+
repairData = true;
|
|
799
|
+
} else {
|
|
800
|
+
printMessage(`- ${name}: OK`);
|
|
801
|
+
}
|
|
802
|
+
});
|
|
803
|
+
return object;
|
|
804
|
+
});
|
|
805
|
+
managed.objects = updatedObjects;
|
|
806
|
+
if (!dryRun) {
|
|
807
|
+
try {
|
|
808
|
+
await putConfigEntity('managed', managed);
|
|
809
|
+
} catch (putConfigEntityError) {
|
|
810
|
+
printMessage(putConfigEntityError, 'error');
|
|
811
|
+
printMessage(`Error: ${putConfigEntityError}`, 'error');
|
|
812
|
+
}
|
|
813
|
+
}
|
|
814
|
+
return repairData;
|
|
815
|
+
}
|
|
816
|
+
|
|
817
|
+
async function repairOrgModelOrg(dryRun) {
|
|
818
|
+
const managed = (await getConfigEntity('managed')).data;
|
|
819
|
+
const RDVPs = [
|
|
820
|
+
'adminIDs',
|
|
821
|
+
'ownerIDs',
|
|
822
|
+
'parentAdminIDs',
|
|
823
|
+
'parentOwnerIDs',
|
|
824
|
+
'parentIDs',
|
|
825
|
+
];
|
|
826
|
+
let repairData = false;
|
|
827
|
+
const updatedObjects = managed.objects.map((object) => {
|
|
828
|
+
// ignore all other objects
|
|
829
|
+
if (object.name !== getRealmManagedOrganization()) {
|
|
830
|
+
return object;
|
|
831
|
+
}
|
|
832
|
+
printMessage(`${object.name}: checking...`);
|
|
833
|
+
RDVPs.forEach((name) => {
|
|
834
|
+
if (!object.schema.properties[name].queryConfig.flattenProperties) {
|
|
835
|
+
printMessage(`- ${name}: repairing - needs flattening`, 'warn');
|
|
836
|
+
// eslint-disable-next-line no-param-reassign
|
|
837
|
+
object.schema.properties[name].queryConfig.flattenProperties = true;
|
|
838
|
+
repairData = true;
|
|
839
|
+
} else {
|
|
840
|
+
printMessage(`- ${name}: OK`);
|
|
841
|
+
}
|
|
842
|
+
});
|
|
843
|
+
return object;
|
|
844
|
+
});
|
|
845
|
+
managed.objects = updatedObjects;
|
|
846
|
+
if (!dryRun) {
|
|
847
|
+
try {
|
|
848
|
+
await putConfigEntity('managed', managed);
|
|
849
|
+
} catch (putConfigEntityError) {
|
|
850
|
+
printMessage(putConfigEntityError, 'error');
|
|
851
|
+
printMessage(`Error: ${putConfigEntityError}`, 'error');
|
|
852
|
+
}
|
|
853
|
+
}
|
|
854
|
+
return repairData;
|
|
855
|
+
}
|
|
856
|
+
|
|
857
|
+
async function repairOrgModelData(dryRun = false) {
|
|
858
|
+
if (!dryRun) {
|
|
859
|
+
// const rootOrgs = await findRootOrganizations();
|
|
860
|
+
}
|
|
861
|
+
}
|
|
862
|
+
|
|
863
|
+
async function extendOrgModelPermissins(dryRun = false) {
|
|
864
|
+
if (!dryRun) {
|
|
865
|
+
// const rootOrgs = await findRootOrganizations();
|
|
866
|
+
}
|
|
867
|
+
}
|
|
868
|
+
|
|
869
|
+
export async function repairOrgModel(
|
|
870
|
+
excludeCustomized,
|
|
871
|
+
extendPermissions,
|
|
872
|
+
dryRun
|
|
873
|
+
) {
|
|
874
|
+
let repairData = false;
|
|
875
|
+
repairData = repairData || (await repairOrgModelUser(dryRun));
|
|
876
|
+
repairData = repairData || (await repairOrgModelOrg(dryRun));
|
|
877
|
+
if (repairData) {
|
|
878
|
+
await repairOrgModelData(dryRun);
|
|
879
|
+
}
|
|
880
|
+
if (extendPermissions) {
|
|
881
|
+
await extendOrgModelPermissins(dryRun);
|
|
882
|
+
}
|
|
883
|
+
if (dryRun) {
|
|
884
|
+
printMessage('Dry-run only. Changes are not saved.', 'warn');
|
|
885
|
+
}
|
|
886
|
+
}
|
|
887
|
+
|
|
888
|
+
// suggested by John K.
|
|
889
|
+
// eslint-disable-next-line no-empty-function
|
|
890
|
+
export async function removeRealmNameFromManagedObjectLabels() {}
|
|
891
|
+
|
|
892
|
+
// eslint-disable-next-line no-empty-function
|
|
893
|
+
export async function addRealmNameToManagedObjectLabels() {}
|
|
894
|
+
|
|
895
|
+
// suggested by John K.
|
|
896
|
+
// eslint-disable-next-line no-empty-function
|
|
897
|
+
export async function cleanUpPostmanArtifacts() {}
|
|
898
|
+
|
|
899
|
+
// suggested by John K.
|
|
900
|
+
// eslint-disable-next-line no-empty-function
|
|
901
|
+
export async function createSampleThemes() {}
|