@enterprisestandard/react 0.0.5-beta.20260114.3 → 0.0.5-beta.20260115.2
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/group-store.js +127 -0
- package/dist/iam.js +680 -0
- package/dist/index.d.ts +2 -2
- package/dist/index.d.ts.map +1 -1
- package/dist/index.js +144 -3687
- package/dist/session-store.js +105 -0
- package/dist/sso-server.d.ts +13 -0
- package/dist/sso-server.d.ts.map +1 -0
- package/dist/sso-server.js +46 -0
- package/dist/sso.d.ts +1 -1
- package/dist/sso.d.ts.map +1 -1
- package/dist/sso.js +820 -0
- package/dist/tenant-server.js +6 -0
- package/dist/tenant.d.ts.map +1 -1
- package/dist/tenant.js +324 -0
- package/dist/types/base-user.js +1 -0
- package/dist/types/enterprise-user.js +1 -0
- package/dist/types/oidc-schema.js +328 -0
- package/dist/types/scim-schema.js +519 -0
- package/dist/types/standard-schema.js +1 -0
- package/dist/types/user.js +1 -0
- package/dist/types/workload-schema.js +208 -0
- package/dist/ui/sign-in-loading.js +8 -0
- package/dist/ui/signed-in.js +8 -0
- package/dist/ui/signed-out.js +8 -0
- package/dist/ui/sso-provider.js +275 -0
- package/dist/user-store.js +114 -0
- package/dist/utils.js +23 -0
- package/dist/vault.js +22 -0
- package/dist/workload-server.d.ts +7 -6
- package/dist/workload-server.d.ts.map +1 -1
- package/dist/workload-server.js +167 -0
- package/dist/workload-token-store.js +95 -0
- package/dist/workload.d.ts.map +1 -1
- package/dist/workload.js +691 -0
- package/package.json +1 -1
- package/dist/index.js.map +0 -29
- package/dist/server.d.ts +0 -9
- package/dist/server.d.ts.map +0 -1
|
@@ -0,0 +1,519 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Validates a string field
|
|
3
|
+
*/
|
|
4
|
+
function validateString(value, fieldName, required, issues, path) {
|
|
5
|
+
if (value === undefined || value === null) {
|
|
6
|
+
if (required) {
|
|
7
|
+
issues.push({
|
|
8
|
+
message: `${fieldName} is required`,
|
|
9
|
+
path,
|
|
10
|
+
});
|
|
11
|
+
}
|
|
12
|
+
return undefined;
|
|
13
|
+
}
|
|
14
|
+
if (typeof value !== 'string') {
|
|
15
|
+
issues.push({
|
|
16
|
+
message: `${fieldName} must be a string`,
|
|
17
|
+
path,
|
|
18
|
+
});
|
|
19
|
+
return undefined;
|
|
20
|
+
}
|
|
21
|
+
return value;
|
|
22
|
+
}
|
|
23
|
+
/**
|
|
24
|
+
* Validates a boolean field
|
|
25
|
+
*/
|
|
26
|
+
function validateBoolean(value, fieldName, issues, path) {
|
|
27
|
+
if (value === undefined || value === null) {
|
|
28
|
+
return undefined;
|
|
29
|
+
}
|
|
30
|
+
if (typeof value !== 'boolean') {
|
|
31
|
+
issues.push({
|
|
32
|
+
message: `${fieldName} must be a boolean`,
|
|
33
|
+
path,
|
|
34
|
+
});
|
|
35
|
+
return undefined;
|
|
36
|
+
}
|
|
37
|
+
return value;
|
|
38
|
+
}
|
|
39
|
+
/**
|
|
40
|
+
* Validates a SCIM Name object
|
|
41
|
+
*/
|
|
42
|
+
function validateName(value, issues, basePath) {
|
|
43
|
+
if (value === undefined || value === null) {
|
|
44
|
+
return undefined;
|
|
45
|
+
}
|
|
46
|
+
if (typeof value !== 'object' || value === null) {
|
|
47
|
+
issues.push({
|
|
48
|
+
message: 'name must be an object',
|
|
49
|
+
path: basePath,
|
|
50
|
+
});
|
|
51
|
+
return undefined;
|
|
52
|
+
}
|
|
53
|
+
const name = value;
|
|
54
|
+
const result = {};
|
|
55
|
+
result.formatted = validateString(name.formatted, 'formatted', false, issues, [...basePath, 'formatted']);
|
|
56
|
+
result.familyName = validateString(name.familyName, 'familyName', false, issues, [...basePath, 'familyName']);
|
|
57
|
+
result.givenName = validateString(name.givenName, 'givenName', false, issues, [...basePath, 'givenName']);
|
|
58
|
+
result.middleName = validateString(name.middleName, 'middleName', false, issues, [...basePath, 'middleName']);
|
|
59
|
+
result.honorificPrefix = validateString(name.honorificPrefix, 'honorificPrefix', false, issues, [
|
|
60
|
+
...basePath,
|
|
61
|
+
'honorificPrefix',
|
|
62
|
+
]);
|
|
63
|
+
result.honorificSuffix = validateString(name.honorificSuffix, 'honorificSuffix', false, issues, [
|
|
64
|
+
...basePath,
|
|
65
|
+
'honorificSuffix',
|
|
66
|
+
]);
|
|
67
|
+
return result;
|
|
68
|
+
}
|
|
69
|
+
/**
|
|
70
|
+
* Validates a SCIM Email array
|
|
71
|
+
*/
|
|
72
|
+
function validateEmails(value, issues, basePath) {
|
|
73
|
+
if (value === undefined || value === null) {
|
|
74
|
+
return undefined;
|
|
75
|
+
}
|
|
76
|
+
if (!Array.isArray(value)) {
|
|
77
|
+
issues.push({
|
|
78
|
+
message: 'emails must be an array',
|
|
79
|
+
path: basePath,
|
|
80
|
+
});
|
|
81
|
+
return undefined;
|
|
82
|
+
}
|
|
83
|
+
const emails = [];
|
|
84
|
+
for (let i = 0; i < value.length; i++) {
|
|
85
|
+
const email = value[i];
|
|
86
|
+
const emailPath = [...basePath, i];
|
|
87
|
+
if (typeof email !== 'object' || email === null) {
|
|
88
|
+
issues.push({
|
|
89
|
+
message: 'email must be an object',
|
|
90
|
+
path: emailPath,
|
|
91
|
+
});
|
|
92
|
+
continue;
|
|
93
|
+
}
|
|
94
|
+
const emailObj = email;
|
|
95
|
+
const emailValue = validateString(emailObj.value, 'value', true, issues, [...emailPath, 'value']);
|
|
96
|
+
if (emailValue) {
|
|
97
|
+
emails.push({
|
|
98
|
+
value: emailValue,
|
|
99
|
+
display: validateString(emailObj.display, 'display', false, issues, [...emailPath, 'display']),
|
|
100
|
+
type: validateString(emailObj.type, 'type', false, issues, [...emailPath, 'type']),
|
|
101
|
+
primary: validateBoolean(emailObj.primary, 'primary', issues, [...emailPath, 'primary']),
|
|
102
|
+
});
|
|
103
|
+
}
|
|
104
|
+
}
|
|
105
|
+
return emails.length > 0 ? emails : undefined;
|
|
106
|
+
}
|
|
107
|
+
/**
|
|
108
|
+
* Validates a SCIM PhoneNumber array
|
|
109
|
+
*/
|
|
110
|
+
function validatePhoneNumbers(value, issues, basePath) {
|
|
111
|
+
if (value === undefined || value === null) {
|
|
112
|
+
return undefined;
|
|
113
|
+
}
|
|
114
|
+
if (!Array.isArray(value)) {
|
|
115
|
+
issues.push({
|
|
116
|
+
message: 'phoneNumbers must be an array',
|
|
117
|
+
path: basePath,
|
|
118
|
+
});
|
|
119
|
+
return undefined;
|
|
120
|
+
}
|
|
121
|
+
const phoneNumbers = [];
|
|
122
|
+
for (let i = 0; i < value.length; i++) {
|
|
123
|
+
const phone = value[i];
|
|
124
|
+
const phonePath = [...basePath, i];
|
|
125
|
+
if (typeof phone !== 'object' || phone === null) {
|
|
126
|
+
issues.push({
|
|
127
|
+
message: 'phoneNumber must be an object',
|
|
128
|
+
path: phonePath,
|
|
129
|
+
});
|
|
130
|
+
continue;
|
|
131
|
+
}
|
|
132
|
+
const phoneObj = phone;
|
|
133
|
+
const phoneValue = validateString(phoneObj.value, 'value', true, issues, [...phonePath, 'value']);
|
|
134
|
+
if (phoneValue) {
|
|
135
|
+
phoneNumbers.push({
|
|
136
|
+
value: phoneValue,
|
|
137
|
+
display: validateString(phoneObj.display, 'display', false, issues, [...phonePath, 'display']),
|
|
138
|
+
type: validateString(phoneObj.type, 'type', false, issues, [...phonePath, 'type']),
|
|
139
|
+
primary: validateBoolean(phoneObj.primary, 'primary', issues, [...phonePath, 'primary']),
|
|
140
|
+
});
|
|
141
|
+
}
|
|
142
|
+
}
|
|
143
|
+
return phoneNumbers.length > 0 ? phoneNumbers : undefined;
|
|
144
|
+
}
|
|
145
|
+
/**
|
|
146
|
+
* Validates a SCIM Address array
|
|
147
|
+
*/
|
|
148
|
+
function validateAddresses(value, issues, basePath) {
|
|
149
|
+
if (value === undefined || value === null) {
|
|
150
|
+
return undefined;
|
|
151
|
+
}
|
|
152
|
+
if (!Array.isArray(value)) {
|
|
153
|
+
issues.push({
|
|
154
|
+
message: 'addresses must be an array',
|
|
155
|
+
path: basePath,
|
|
156
|
+
});
|
|
157
|
+
return undefined;
|
|
158
|
+
}
|
|
159
|
+
const addresses = [];
|
|
160
|
+
for (let i = 0; i < value.length; i++) {
|
|
161
|
+
const address = value[i];
|
|
162
|
+
const addressPath = [...basePath, i];
|
|
163
|
+
if (typeof address !== 'object' || address === null) {
|
|
164
|
+
issues.push({
|
|
165
|
+
message: 'address must be an object',
|
|
166
|
+
path: addressPath,
|
|
167
|
+
});
|
|
168
|
+
continue;
|
|
169
|
+
}
|
|
170
|
+
const addressObj = address;
|
|
171
|
+
addresses.push({
|
|
172
|
+
formatted: validateString(addressObj.formatted, 'formatted', false, issues, [...addressPath, 'formatted']),
|
|
173
|
+
streetAddress: validateString(addressObj.streetAddress, 'streetAddress', false, issues, [
|
|
174
|
+
...addressPath,
|
|
175
|
+
'streetAddress',
|
|
176
|
+
]),
|
|
177
|
+
locality: validateString(addressObj.locality, 'locality', false, issues, [...addressPath, 'locality']),
|
|
178
|
+
region: validateString(addressObj.region, 'region', false, issues, [...addressPath, 'region']),
|
|
179
|
+
postalCode: validateString(addressObj.postalCode, 'postalCode', false, issues, [...addressPath, 'postalCode']),
|
|
180
|
+
country: validateString(addressObj.country, 'country', false, issues, [...addressPath, 'country']),
|
|
181
|
+
type: validateString(addressObj.type, 'type', false, issues, [...addressPath, 'type']),
|
|
182
|
+
primary: validateBoolean(addressObj.primary, 'primary', issues, [...addressPath, 'primary']),
|
|
183
|
+
});
|
|
184
|
+
}
|
|
185
|
+
return addresses.length > 0 ? addresses : undefined;
|
|
186
|
+
}
|
|
187
|
+
/**
|
|
188
|
+
* Validates a SCIM Group array
|
|
189
|
+
*/
|
|
190
|
+
function validateGroups(value, issues, basePath) {
|
|
191
|
+
if (value === undefined || value === null) {
|
|
192
|
+
return undefined;
|
|
193
|
+
}
|
|
194
|
+
if (!Array.isArray(value)) {
|
|
195
|
+
issues.push({
|
|
196
|
+
message: 'groups must be an array',
|
|
197
|
+
path: basePath,
|
|
198
|
+
});
|
|
199
|
+
return undefined;
|
|
200
|
+
}
|
|
201
|
+
const groups = [];
|
|
202
|
+
for (let i = 0; i < value.length; i++) {
|
|
203
|
+
const group = value[i];
|
|
204
|
+
const groupPath = [...basePath, i];
|
|
205
|
+
if (typeof group !== 'object' || group === null) {
|
|
206
|
+
issues.push({
|
|
207
|
+
message: 'group must be an object',
|
|
208
|
+
path: groupPath,
|
|
209
|
+
});
|
|
210
|
+
continue;
|
|
211
|
+
}
|
|
212
|
+
const groupObj = group;
|
|
213
|
+
const groupValue = validateString(groupObj.value, 'value', true, issues, [...groupPath, 'value']);
|
|
214
|
+
if (groupValue) {
|
|
215
|
+
groups.push({
|
|
216
|
+
value: groupValue,
|
|
217
|
+
$ref: validateString(groupObj.$ref, '$ref', false, issues, [...groupPath, '$ref']),
|
|
218
|
+
display: validateString(groupObj.display, 'display', false, issues, [...groupPath, 'display']),
|
|
219
|
+
type: validateString(groupObj.type, 'type', false, issues, [...groupPath, 'type']),
|
|
220
|
+
});
|
|
221
|
+
}
|
|
222
|
+
}
|
|
223
|
+
return groups.length > 0 ? groups : undefined;
|
|
224
|
+
}
|
|
225
|
+
/**
|
|
226
|
+
* Validates a SCIM Role array
|
|
227
|
+
*/
|
|
228
|
+
function validateRoles(value, issues, basePath) {
|
|
229
|
+
if (value === undefined || value === null) {
|
|
230
|
+
return undefined;
|
|
231
|
+
}
|
|
232
|
+
if (!Array.isArray(value)) {
|
|
233
|
+
issues.push({
|
|
234
|
+
message: 'roles must be an array',
|
|
235
|
+
path: basePath,
|
|
236
|
+
});
|
|
237
|
+
return undefined;
|
|
238
|
+
}
|
|
239
|
+
const roles = [];
|
|
240
|
+
for (let i = 0; i < value.length; i++) {
|
|
241
|
+
const role = value[i];
|
|
242
|
+
const rolePath = [...basePath, i];
|
|
243
|
+
if (typeof role !== 'object' || role === null) {
|
|
244
|
+
issues.push({
|
|
245
|
+
message: 'role must be an object',
|
|
246
|
+
path: rolePath,
|
|
247
|
+
});
|
|
248
|
+
continue;
|
|
249
|
+
}
|
|
250
|
+
const roleObj = role;
|
|
251
|
+
const roleValue = validateString(roleObj.value, 'value', true, issues, [...rolePath, 'value']);
|
|
252
|
+
if (roleValue) {
|
|
253
|
+
roles.push({
|
|
254
|
+
value: roleValue,
|
|
255
|
+
display: validateString(roleObj.display, 'display', false, issues, [...rolePath, 'display']),
|
|
256
|
+
type: validateString(roleObj.type, 'type', false, issues, [...rolePath, 'type']),
|
|
257
|
+
primary: validateBoolean(roleObj.primary, 'primary', issues, [...rolePath, 'primary']),
|
|
258
|
+
});
|
|
259
|
+
}
|
|
260
|
+
}
|
|
261
|
+
return roles.length > 0 ? roles : undefined;
|
|
262
|
+
}
|
|
263
|
+
/**
|
|
264
|
+
* Validates a SCIM Enterprise User extension
|
|
265
|
+
*/
|
|
266
|
+
function validateEnterpriseUser(value, issues, basePath) {
|
|
267
|
+
if (value === undefined || value === null) {
|
|
268
|
+
return undefined;
|
|
269
|
+
}
|
|
270
|
+
if (typeof value !== 'object' || value === null) {
|
|
271
|
+
issues.push({
|
|
272
|
+
message: 'Enterprise User extension must be an object',
|
|
273
|
+
path: basePath,
|
|
274
|
+
});
|
|
275
|
+
return undefined;
|
|
276
|
+
}
|
|
277
|
+
const enterprise = value;
|
|
278
|
+
const result = {};
|
|
279
|
+
result.employeeNumber = validateString(enterprise.employeeNumber, 'employeeNumber', false, issues, [
|
|
280
|
+
...basePath,
|
|
281
|
+
'employeeNumber',
|
|
282
|
+
]);
|
|
283
|
+
result.costCenter = validateString(enterprise.costCenter, 'costCenter', false, issues, [...basePath, 'costCenter']);
|
|
284
|
+
result.organization = validateString(enterprise.organization, 'organization', false, issues, [
|
|
285
|
+
...basePath,
|
|
286
|
+
'organization',
|
|
287
|
+
]);
|
|
288
|
+
result.division = validateString(enterprise.division, 'division', false, issues, [...basePath, 'division']);
|
|
289
|
+
result.department = validateString(enterprise.department, 'department', false, issues, [...basePath, 'department']);
|
|
290
|
+
if (enterprise.manager !== undefined && enterprise.manager !== null) {
|
|
291
|
+
if (typeof enterprise.manager !== 'object' || enterprise.manager === null) {
|
|
292
|
+
issues.push({
|
|
293
|
+
message: 'manager must be an object',
|
|
294
|
+
path: [...basePath, 'manager'],
|
|
295
|
+
});
|
|
296
|
+
}
|
|
297
|
+
else {
|
|
298
|
+
const manager = enterprise.manager;
|
|
299
|
+
result.manager = {
|
|
300
|
+
value: validateString(manager.value, 'value', false, issues, [...basePath, 'manager', 'value']),
|
|
301
|
+
$ref: validateString(manager.$ref, '$ref', false, issues, [...basePath, 'manager', '$ref']),
|
|
302
|
+
displayName: validateString(manager.displayName, 'displayName', false, issues, [
|
|
303
|
+
...basePath,
|
|
304
|
+
'manager',
|
|
305
|
+
'displayName',
|
|
306
|
+
]),
|
|
307
|
+
};
|
|
308
|
+
}
|
|
309
|
+
}
|
|
310
|
+
return result;
|
|
311
|
+
}
|
|
312
|
+
/**
|
|
313
|
+
* Creates a StandardSchemaV1 for validating SCIM User resources.
|
|
314
|
+
* @param vendor - The name of the vendor creating this schema
|
|
315
|
+
* @returns A StandardSchemaV1 instance for SCIM User resources
|
|
316
|
+
*/
|
|
317
|
+
export function userSchema(vendor) {
|
|
318
|
+
return {
|
|
319
|
+
'~standard': {
|
|
320
|
+
version: 1,
|
|
321
|
+
vendor,
|
|
322
|
+
validate: (value) => {
|
|
323
|
+
if (typeof value !== 'object' || value === null) {
|
|
324
|
+
return {
|
|
325
|
+
issues: [
|
|
326
|
+
{
|
|
327
|
+
message: 'Expected an object',
|
|
328
|
+
},
|
|
329
|
+
],
|
|
330
|
+
};
|
|
331
|
+
}
|
|
332
|
+
const user = value;
|
|
333
|
+
const issues = [];
|
|
334
|
+
const result = {};
|
|
335
|
+
// userName is REQUIRED
|
|
336
|
+
const userName = validateString(user.userName, 'userName', true, issues, ['userName']);
|
|
337
|
+
if (!userName) {
|
|
338
|
+
return { issues };
|
|
339
|
+
}
|
|
340
|
+
result.userName = userName;
|
|
341
|
+
// Optional string fields
|
|
342
|
+
result.id = validateString(user.id, 'id', false, issues, ['id']);
|
|
343
|
+
result.externalId = validateString(user.externalId, 'externalId', false, issues, ['externalId']);
|
|
344
|
+
result.displayName = validateString(user.displayName, 'displayName', false, issues, ['displayName']);
|
|
345
|
+
result.nickName = validateString(user.nickName, 'nickName', false, issues, ['nickName']);
|
|
346
|
+
result.profileUrl = validateString(user.profileUrl, 'profileUrl', false, issues, ['profileUrl']);
|
|
347
|
+
result.title = validateString(user.title, 'title', false, issues, ['title']);
|
|
348
|
+
result.userType = validateString(user.userType, 'userType', false, issues, ['userType']);
|
|
349
|
+
result.preferredLanguage = validateString(user.preferredLanguage, 'preferredLanguage', false, issues, [
|
|
350
|
+
'preferredLanguage',
|
|
351
|
+
]);
|
|
352
|
+
result.locale = validateString(user.locale, 'locale', false, issues, ['locale']);
|
|
353
|
+
result.timezone = validateString(user.timezone, 'timezone', false, issues, ['timezone']);
|
|
354
|
+
result.password = validateString(user.password, 'password', false, issues, ['password']);
|
|
355
|
+
// Boolean field
|
|
356
|
+
result.active = validateBoolean(user.active, 'active', issues, ['active']);
|
|
357
|
+
// Complex sub-attributes
|
|
358
|
+
result.name = validateName(user.name, issues, ['name']);
|
|
359
|
+
result.emails = validateEmails(user.emails, issues, ['emails']);
|
|
360
|
+
result.phoneNumbers = validatePhoneNumbers(user.phoneNumbers, issues, ['phoneNumbers']);
|
|
361
|
+
result.addresses = validateAddresses(user.addresses, issues, ['addresses']);
|
|
362
|
+
result.groups = validateGroups(user.groups, issues, ['groups']);
|
|
363
|
+
result.roles = validateRoles(user.roles, issues, ['roles']);
|
|
364
|
+
// Enterprise User Extension
|
|
365
|
+
const enterpriseKey = 'urn:ietf:params:scim:schemas:extension:enterprise:2.0:User';
|
|
366
|
+
if (user[enterpriseKey] !== undefined) {
|
|
367
|
+
result[enterpriseKey] = validateEnterpriseUser(user[enterpriseKey], issues, [enterpriseKey]);
|
|
368
|
+
}
|
|
369
|
+
// Schemas array
|
|
370
|
+
if (user.schemas !== undefined) {
|
|
371
|
+
if (Array.isArray(user.schemas)) {
|
|
372
|
+
result.schemas = user.schemas.filter((s) => typeof s === 'string');
|
|
373
|
+
}
|
|
374
|
+
else {
|
|
375
|
+
issues.push({
|
|
376
|
+
message: 'schemas must be an array',
|
|
377
|
+
path: ['schemas'],
|
|
378
|
+
});
|
|
379
|
+
}
|
|
380
|
+
}
|
|
381
|
+
// Meta object (basic validation)
|
|
382
|
+
if (user.meta !== undefined) {
|
|
383
|
+
if (typeof user.meta === 'object' && user.meta !== null) {
|
|
384
|
+
const meta = user.meta;
|
|
385
|
+
result.meta = {
|
|
386
|
+
resourceType: typeof meta.resourceType === 'string' ? meta.resourceType : undefined,
|
|
387
|
+
created: typeof meta.created === 'string' ? meta.created : undefined,
|
|
388
|
+
lastModified: typeof meta.lastModified === 'string' ? meta.lastModified : undefined,
|
|
389
|
+
location: typeof meta.location === 'string' ? meta.location : undefined,
|
|
390
|
+
version: typeof meta.version === 'string' ? meta.version : undefined,
|
|
391
|
+
};
|
|
392
|
+
}
|
|
393
|
+
else {
|
|
394
|
+
issues.push({
|
|
395
|
+
message: 'meta must be an object',
|
|
396
|
+
path: ['meta'],
|
|
397
|
+
});
|
|
398
|
+
}
|
|
399
|
+
}
|
|
400
|
+
if (issues.length > 0) {
|
|
401
|
+
return { issues };
|
|
402
|
+
}
|
|
403
|
+
return { value: result };
|
|
404
|
+
},
|
|
405
|
+
},
|
|
406
|
+
};
|
|
407
|
+
}
|
|
408
|
+
/**
|
|
409
|
+
* Validates a SCIM GroupMember array
|
|
410
|
+
*/
|
|
411
|
+
function validateMembers(value, issues, basePath) {
|
|
412
|
+
if (value === undefined || value === null) {
|
|
413
|
+
return undefined;
|
|
414
|
+
}
|
|
415
|
+
if (!Array.isArray(value)) {
|
|
416
|
+
issues.push({
|
|
417
|
+
message: 'members must be an array',
|
|
418
|
+
path: basePath,
|
|
419
|
+
});
|
|
420
|
+
return undefined;
|
|
421
|
+
}
|
|
422
|
+
const members = [];
|
|
423
|
+
for (let i = 0; i < value.length; i++) {
|
|
424
|
+
const member = value[i];
|
|
425
|
+
const memberPath = [...basePath, i];
|
|
426
|
+
if (typeof member !== 'object' || member === null) {
|
|
427
|
+
issues.push({
|
|
428
|
+
message: 'member must be an object',
|
|
429
|
+
path: memberPath,
|
|
430
|
+
});
|
|
431
|
+
continue;
|
|
432
|
+
}
|
|
433
|
+
const memberObj = member;
|
|
434
|
+
const memberValue = validateString(memberObj.value, 'value', true, issues, [...memberPath, 'value']);
|
|
435
|
+
if (memberValue) {
|
|
436
|
+
const memberType = validateString(memberObj.type, 'type', false, issues, [...memberPath, 'type']);
|
|
437
|
+
members.push({
|
|
438
|
+
value: memberValue,
|
|
439
|
+
$ref: validateString(memberObj.$ref, '$ref', false, issues, [...memberPath, '$ref']),
|
|
440
|
+
display: validateString(memberObj.display, 'display', false, issues, [...memberPath, 'display']),
|
|
441
|
+
type: memberType === 'User' || memberType === 'Group' ? memberType : undefined,
|
|
442
|
+
});
|
|
443
|
+
}
|
|
444
|
+
}
|
|
445
|
+
return members.length > 0 ? members : undefined;
|
|
446
|
+
}
|
|
447
|
+
/**
|
|
448
|
+
* Creates a StandardSchemaV1 for validating SCIM Group resources.
|
|
449
|
+
* @param vendor - The name of the vendor creating this schema
|
|
450
|
+
* @returns A StandardSchemaV1 instance for SCIM Group resources
|
|
451
|
+
*/
|
|
452
|
+
export function groupResourceSchema(vendor) {
|
|
453
|
+
return {
|
|
454
|
+
'~standard': {
|
|
455
|
+
version: 1,
|
|
456
|
+
vendor,
|
|
457
|
+
validate: (value) => {
|
|
458
|
+
if (typeof value !== 'object' || value === null) {
|
|
459
|
+
return {
|
|
460
|
+
issues: [
|
|
461
|
+
{
|
|
462
|
+
message: 'Expected an object',
|
|
463
|
+
},
|
|
464
|
+
],
|
|
465
|
+
};
|
|
466
|
+
}
|
|
467
|
+
const group = value;
|
|
468
|
+
const issues = [];
|
|
469
|
+
const result = {};
|
|
470
|
+
// displayName is REQUIRED
|
|
471
|
+
const displayName = validateString(group.displayName, 'displayName', true, issues, ['displayName']);
|
|
472
|
+
if (!displayName) {
|
|
473
|
+
return { issues };
|
|
474
|
+
}
|
|
475
|
+
result.displayName = displayName;
|
|
476
|
+
// Optional string fields
|
|
477
|
+
result.id = validateString(group.id, 'id', false, issues, ['id']);
|
|
478
|
+
result.externalId = validateString(group.externalId, 'externalId', false, issues, ['externalId']);
|
|
479
|
+
// Members array
|
|
480
|
+
result.members = validateMembers(group.members, issues, ['members']);
|
|
481
|
+
// Schemas array
|
|
482
|
+
if (group.schemas !== undefined) {
|
|
483
|
+
if (Array.isArray(group.schemas)) {
|
|
484
|
+
result.schemas = group.schemas.filter((s) => typeof s === 'string');
|
|
485
|
+
}
|
|
486
|
+
else {
|
|
487
|
+
issues.push({
|
|
488
|
+
message: 'schemas must be an array',
|
|
489
|
+
path: ['schemas'],
|
|
490
|
+
});
|
|
491
|
+
}
|
|
492
|
+
}
|
|
493
|
+
// Meta object (basic validation)
|
|
494
|
+
if (group.meta !== undefined) {
|
|
495
|
+
if (typeof group.meta === 'object' && group.meta !== null) {
|
|
496
|
+
const meta = group.meta;
|
|
497
|
+
result.meta = {
|
|
498
|
+
resourceType: typeof meta.resourceType === 'string' ? meta.resourceType : undefined,
|
|
499
|
+
created: typeof meta.created === 'string' ? meta.created : undefined,
|
|
500
|
+
lastModified: typeof meta.lastModified === 'string' ? meta.lastModified : undefined,
|
|
501
|
+
location: typeof meta.location === 'string' ? meta.location : undefined,
|
|
502
|
+
version: typeof meta.version === 'string' ? meta.version : undefined,
|
|
503
|
+
};
|
|
504
|
+
}
|
|
505
|
+
else {
|
|
506
|
+
issues.push({
|
|
507
|
+
message: 'meta must be an object',
|
|
508
|
+
path: ['meta'],
|
|
509
|
+
});
|
|
510
|
+
}
|
|
511
|
+
}
|
|
512
|
+
if (issues.length > 0) {
|
|
513
|
+
return { issues };
|
|
514
|
+
}
|
|
515
|
+
return { value: result };
|
|
516
|
+
},
|
|
517
|
+
},
|
|
518
|
+
};
|
|
519
|
+
}
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
export {};
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
export {};
|