samlesa 2.12.3 → 2.12.5

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.

Potentially problematic release.


This version of samlesa might be problematic. Click here for more details.

Files changed (60) hide show
  1. package/build/.idea/workspace.xml +13 -1
  2. package/build/index.js +54 -64
  3. package/build/index.js.map +1 -1
  4. package/build/src/api.js +24 -23
  5. package/build/src/api.js.map +1 -1
  6. package/build/src/binding-post.js +358 -368
  7. package/build/src/binding-post.js.map +1 -1
  8. package/build/src/binding-redirect.js +333 -332
  9. package/build/src/binding-redirect.js.map +1 -1
  10. package/build/src/binding-simplesign.js +222 -232
  11. package/build/src/binding-simplesign.js.map +1 -1
  12. package/build/src/entity-idp.js +130 -130
  13. package/build/src/entity-idp.js.map +1 -1
  14. package/build/src/entity-sp.js +96 -96
  15. package/build/src/entity-sp.js.map +1 -1
  16. package/build/src/entity.js +225 -235
  17. package/build/src/entity.js.map +1 -1
  18. package/build/src/extractor.js +385 -369
  19. package/build/src/extractor.js.map +1 -1
  20. package/build/src/flow.js +320 -319
  21. package/build/src/flow.js.map +1 -1
  22. package/build/src/libsaml.js +665 -641
  23. package/build/src/libsaml.js.map +1 -1
  24. package/build/src/metadata-idp.js +127 -127
  25. package/build/src/metadata-idp.js.map +1 -1
  26. package/build/src/metadata-sp.js +231 -231
  27. package/build/src/metadata-sp.js.map +1 -1
  28. package/build/src/metadata.js +166 -176
  29. package/build/src/metadata.js.map +1 -1
  30. package/build/src/types.js +11 -11
  31. package/build/src/urn.js +212 -212
  32. package/build/src/urn.js.map +1 -1
  33. package/build/src/utility.js +292 -248
  34. package/build/src/utility.js.map +1 -1
  35. package/build/src/validator.js +27 -26
  36. package/build/src/validator.js.map +1 -1
  37. package/package.json +8 -10
  38. package/src/api.ts +1 -1
  39. package/src/binding-redirect.ts +83 -64
  40. package/src/extractor.ts +23 -5
  41. package/src/libsaml.ts +95 -62
  42. package/src/utility.ts +147 -76
  43. package/types/index.d.ts +10 -10
  44. package/types/src/api.d.ts +13 -13
  45. package/types/src/binding-post.d.ts +46 -46
  46. package/types/src/binding-redirect.d.ts +52 -52
  47. package/types/src/binding-simplesign.d.ts +39 -39
  48. package/types/src/entity-idp.d.ts +42 -42
  49. package/types/src/entity-sp.d.ts +36 -36
  50. package/types/src/entity.d.ts +101 -99
  51. package/types/src/extractor.d.ts +25 -25
  52. package/types/src/flow.d.ts +6 -6
  53. package/types/src/libsaml.d.ts +200 -210
  54. package/types/src/metadata-idp.d.ts +24 -24
  55. package/types/src/metadata-sp.d.ts +36 -36
  56. package/types/src/metadata.d.ts +59 -57
  57. package/types/src/types.d.ts +129 -127
  58. package/types/src/urn.d.ts +194 -194
  59. package/types/src/utility.d.ts +134 -134
  60. package/types/src/validator.d.ts +3 -3
@@ -1,370 +1,386 @@
1
- "use strict";
2
- var __importDefault = (this && this.__importDefault) || function (mod) {
3
- return (mod && mod.__esModule) ? mod : { "default": mod };
4
- };
5
- Object.defineProperty(exports, "__esModule", { value: true });
6
- exports.logoutResponseFields = exports.logoutRequestFields = exports.loginResponseFields = exports.logoutResponseStatusFields = exports.loginResponseStatusFields = exports.loginRequestFields = void 0;
7
- exports.extract = extract;
8
- const xpath_1 = require("xpath");
9
- const utility_js_1 = require("./utility.js");
10
- const api_js_1 = require("./api.js");
11
- const camelcase_1 = __importDefault(require("camelcase"));
12
- function buildAbsoluteXPath(paths) {
13
- return paths.reduce((currentPath, name) => {
14
- let appendedPath = currentPath;
15
- const isWildcard = name.startsWith('~');
16
- if (isWildcard) {
17
- const pathName = name.replace('~', '');
18
- appendedPath = currentPath + `/*[contains(local-name(), '${pathName}')]`;
19
- }
20
- if (!isWildcard) {
21
- appendedPath = currentPath + `/*[local-name(.)='${name}']`;
22
- }
23
- return appendedPath;
24
- }, '');
25
- }
26
- function buildAttributeXPath(attributes) {
27
- if (attributes.length === 0) {
28
- return '/text()';
29
- }
30
- if (attributes.length === 1) {
31
- return `/@${attributes[0]}`;
32
- }
33
- const filters = attributes.map(attribute => `name()='${attribute}'`).join(' or ');
34
- return `/@*[${filters}]`;
35
- }
36
- exports.loginRequestFields = [
37
- {
38
- key: 'request',
39
- localPath: ['AuthnRequest'],
40
- attributes: ['ID', 'IssueInstant', 'Destination', 'AssertionConsumerServiceURL']
41
- },
42
- {
43
- key: 'issuer',
44
- localPath: ['AuthnRequest', 'Issuer'],
45
- attributes: []
46
- },
47
- {
48
- key: 'nameIDPolicy',
49
- localPath: ['AuthnRequest', 'NameIDPolicy'],
50
- attributes: ['Format', 'AllowCreate']
51
- },
52
- {
53
- key: 'authnContextClassRef',
54
- localPath: ['AuthnRequest', 'AuthnContextClassRef'],
55
- attributes: []
56
- },
57
- {
58
- key: 'signature',
59
- localPath: ['AuthnRequest', 'Signature'],
60
- attributes: [],
61
- context: true
62
- }
63
- ];
64
- // support two-tiers status code
65
- exports.loginResponseStatusFields = [
66
- {
67
- key: 'top',
68
- localPath: ['Response', 'Status', 'StatusCode'],
69
- attributes: ['Value'],
70
- },
71
- {
72
- key: 'second',
73
- localPath: ['Response', 'Status', 'StatusCode', 'StatusCode'],
74
- attributes: ['Value'],
75
- }
76
- ];
77
- // support two-tiers status code
78
- exports.logoutResponseStatusFields = [
79
- {
80
- key: 'top',
81
- localPath: ['LogoutResponse', 'Status', 'StatusCode'],
82
- attributes: ['Value']
83
- },
84
- {
85
- key: 'second',
86
- localPath: ['LogoutResponse', 'Status', 'StatusCode', 'StatusCode'],
87
- attributes: ['Value'],
88
- }
89
- ];
90
- const loginResponseFields = assertion => [
91
- {
92
- key: 'conditions',
93
- localPath: ['Assertion', 'Conditions'],
94
- attributes: ['NotBefore', 'NotOnOrAfter'],
95
- shortcut: assertion
96
- },
97
- {
98
- key: 'response',
99
- localPath: ['Response'],
100
- attributes: ['ID', 'IssueInstant', 'Destination', 'InResponseTo'],
101
- },
102
- {
103
- key: 'audience',
104
- localPath: ['Assertion', 'Conditions', 'AudienceRestriction', 'Audience'],
105
- attributes: [],
106
- shortcut: assertion
107
- },
108
- // {
109
- // key: 'issuer',
110
- // localPath: ['Response', 'Issuer'],
111
- // attributes: []
112
- // },
113
- {
114
- key: 'issuer',
115
- localPath: ['Assertion', 'Issuer'],
116
- attributes: [],
117
- shortcut: assertion
118
- },
119
- {
120
- key: 'nameID',
121
- localPath: ['Assertion', 'Subject', 'NameID'],
122
- attributes: [],
123
- shortcut: assertion
124
- },
125
- {
126
- key: 'sessionIndex',
127
- localPath: ['Assertion', 'AuthnStatement'],
128
- attributes: ['AuthnInstant', 'SessionNotOnOrAfter', 'SessionIndex'],
129
- shortcut: assertion
130
- },
131
- {
132
- key: 'attributes',
133
- localPath: ['Assertion', 'AttributeStatement', 'Attribute'],
134
- index: ['Name'],
135
- attributePath: ['AttributeValue'],
136
- attributes: [],
137
- shortcut: assertion
138
- }
139
- ];
140
- exports.loginResponseFields = loginResponseFields;
141
- exports.logoutRequestFields = [
142
- {
143
- key: 'request',
144
- localPath: ['LogoutRequest'],
145
- attributes: ['ID', 'IssueInstant', 'Destination']
146
- },
147
- {
148
- key: 'issuer',
149
- localPath: ['LogoutRequest', 'Issuer'],
150
- attributes: []
151
- },
152
- {
153
- key: 'nameID',
154
- localPath: ['LogoutRequest', 'NameID'],
155
- attributes: []
156
- },
157
- {
158
- key: 'sessionIndex',
159
- localPath: ['LogoutRequest', 'SessionIndex'],
160
- attributes: []
161
- },
162
- {
163
- key: 'signature',
164
- localPath: ['LogoutRequest', 'Signature'],
165
- attributes: [],
166
- context: true
167
- }
168
- ];
169
- exports.logoutResponseFields = [
170
- {
171
- key: 'response',
172
- localPath: ['LogoutResponse'],
173
- attributes: ['ID', 'Destination', 'InResponseTo']
174
- },
175
- {
176
- key: 'issuer',
177
- localPath: ['LogoutResponse', 'Issuer'],
178
- attributes: []
179
- },
180
- {
181
- key: 'signature',
182
- localPath: ['LogoutResponse', 'Signature'],
183
- attributes: [],
184
- context: true
185
- }
186
- ];
187
- function extract(context, fields) {
188
- const { dom } = (0, api_js_1.getContext)();
189
- const rootDoc = dom.parseFromString(context);
190
- return fields.reduce((result, field) => {
191
- // get essential fields
192
- const key = field.key;
193
- const localPath = field.localPath;
194
- const attributes = field.attributes;
195
- const isEntire = field.context;
196
- const shortcut = field.shortcut;
197
- // get optional fields
198
- const index = field.index;
199
- const attributePath = field.attributePath;
200
- // set allowing overriding if there is a shortcut injected
201
- let targetDoc = rootDoc;
202
- // if shortcut is used, then replace the doc
203
- // it's a design for overriding the doc used during runtime
204
- if (shortcut) {
205
- targetDoc = dom.parseFromString(shortcut);
206
- }
207
- // special case: multiple path
208
- /*
209
- {
210
- key: 'issuer',
211
- localPath: [
212
- ['Response', 'Issuer'],
213
- ['Response', 'Assertion', 'Issuer']
214
- ],
215
- attributes: []
216
- }
217
- */
218
- if (localPath.every(path => Array.isArray(path))) {
219
- const multiXPaths = localPath
220
- .map(path => {
221
- // not support attribute yet, so ignore it
222
- return `${buildAbsoluteXPath(path)}/text()`;
223
- })
224
- .join(' | ');
225
- return {
226
- ...result,
227
- [key]: (0, utility_js_1.uniq)((0, xpath_1.select)(multiXPaths, targetDoc).map((n) => n.nodeValue).filter(utility_js_1.notEmpty))
228
- };
229
- }
230
- // eo special case: multiple path
231
- const baseXPath = buildAbsoluteXPath(localPath);
232
- const attributeXPath = buildAttributeXPath(attributes);
233
- // special case: get attributes where some are in child, some are in parent
234
- /*
235
- {
236
- key: 'attributes',
237
- localPath: ['Response', 'Assertion', 'AttributeStatement', 'Attribute'],
238
- index: ['Name'],
239
- attributePath: ['AttributeValue'],
240
- attributes: []
241
- }
242
- */
243
- if (index && attributePath) {
244
- // find the index in localpath
245
- const indexPath = buildAttributeXPath(index);
246
- const fullLocalXPath = `${baseXPath}${indexPath}`;
247
- const parentNodes = (0, xpath_1.select)(baseXPath, targetDoc);
248
- // [uid, mail, edupersonaffiliation], ready for aggregate
249
- const parentAttributes = (0, xpath_1.select)(fullLocalXPath, targetDoc).map((n) => n.value);
250
- // [attribute, attributevalue]
251
- const childXPath = buildAbsoluteXPath([(0, utility_js_1.last)(localPath)].concat(attributePath));
252
- const childAttributeXPath = buildAttributeXPath(attributes);
253
- const fullChildXPath = `${childXPath}${childAttributeXPath}`;
254
- // [ 'test', 'test@example.com', [ 'users', 'examplerole1' ] ]
255
- const childAttributes = parentNodes.map(node => {
256
- const nodeDoc = dom.parseFromString(node.toString());
257
- if (attributes.length === 0) {
258
- const childValues = (0, xpath_1.select)(fullChildXPath, nodeDoc).map((n) => n.nodeValue);
259
- if (childValues.length === 1) {
260
- return childValues[0];
261
- }
262
- return childValues;
263
- }
264
- if (attributes.length > 0) {
265
- const childValues = (0, xpath_1.select)(fullChildXPath, nodeDoc).map((n) => n.value);
266
- if (childValues.length === 1) {
267
- return childValues[0];
268
- }
269
- return childValues;
270
- }
271
- return null;
272
- });
273
- // aggregation
274
- const obj = (0, utility_js_1.zipObject)(parentAttributes, childAttributes, false);
275
- return {
276
- ...result,
277
- [key]: obj
278
- };
279
- }
280
- // case: fetch entire content, only allow one existence
281
- /*
282
- {
283
- key: 'signature',
284
- localPath: ['AuthnRequest', 'Signature'],
285
- attributes: [],
286
- context: true
287
- }
288
- */
289
- if (isEntire) {
290
- const node = (0, xpath_1.select)(baseXPath, targetDoc);
291
- let value = null;
292
- if (node.length === 1) {
293
- value = node[0].toString();
294
- }
295
- if (node.length > 1) {
296
- value = node.map(n => n.toString());
297
- }
298
- return {
299
- ...result,
300
- [key]: value
301
- };
302
- }
303
- // case: multiple attribute
304
- /*
305
- {
306
- key: 'nameIDPolicy',
307
- localPath: ['AuthnRequest', 'NameIDPolicy'],
308
- attributes: ['Format', 'AllowCreate']
309
- }
310
- */
311
- if (attributes.length > 1) {
312
- const baseNode = (0, xpath_1.select)(baseXPath, targetDoc).map(n => n.toString());
313
- const childXPath = `${buildAbsoluteXPath([(0, utility_js_1.last)(localPath)])}${attributeXPath}`;
314
- const attributeValues = baseNode.map((node) => {
315
- const nodeDoc = dom.parseFromString(node);
316
- const values = (0, xpath_1.select)(childXPath, nodeDoc).reduce((r, n) => {
317
- r[(0, camelcase_1.default)(n.name, { locale: 'en-us' })] = n.value;
318
- return r;
319
- }, {});
320
- return values;
321
- });
322
- return {
323
- ...result,
324
- [key]: attributeValues.length === 1 ? attributeValues[0] : attributeValues
325
- };
326
- }
327
- // case: single attribute
328
- /*
329
- {
330
- key: 'statusCode',
331
- localPath: ['Response', 'Status', 'StatusCode'],
332
- attributes: ['Value'],
333
- }
334
- */
335
- if (attributes.length === 1) {
336
- const fullPath = `${baseXPath}${attributeXPath}`;
337
- const attributeValues = (0, xpath_1.select)(fullPath, targetDoc).map((n) => n.value);
338
- return {
339
- ...result,
340
- [key]: attributeValues[0]
341
- };
342
- }
343
- // case: zero attribute
344
- /*
345
- {
346
- key: 'issuer',
347
- localPath: ['AuthnRequest', 'Issuer'],
348
- attributes: []
349
- }
350
- */
351
- if (attributes.length === 0) {
352
- let attributeValue = null;
353
- const node = (0, xpath_1.select)(baseXPath, targetDoc);
354
- if (node.length === 1) {
355
- const fullPath = `string(${baseXPath}${attributeXPath})`;
356
- attributeValue = (0, xpath_1.select)(fullPath, targetDoc);
357
- }
358
- if (node.length > 1) {
359
- attributeValue = node.filter((n) => n.firstChild)
360
- .map((n) => n.firstChild.nodeValue);
361
- }
362
- return {
363
- ...result,
364
- [key]: attributeValue
365
- };
366
- }
367
- return result;
368
- }, {});
369
- }
1
+ "use strict";
2
+ var __importDefault = (this && this.__importDefault) || function (mod) {
3
+ return (mod && mod.__esModule) ? mod : { "default": mod };
4
+ };
5
+ Object.defineProperty(exports, "__esModule", { value: true });
6
+ exports.extract = exports.logoutResponseFields = exports.logoutRequestFields = exports.loginResponseFields = exports.logoutResponseStatusFields = exports.loginResponseStatusFields = exports.loginRequestFields = void 0;
7
+ const xpath_1 = require("xpath");
8
+ const utility_js_1 = require("./utility.js");
9
+ const api_js_1 = require("./api.js");
10
+ const camelcase_1 = __importDefault(require("camelcase"));
11
+ function buildAbsoluteXPath(paths) {
12
+ return paths.reduce((currentPath, name) => {
13
+ let appendedPath = currentPath;
14
+ const isWildcard = name.startsWith('~');
15
+ if (isWildcard) {
16
+ const pathName = name.replace('~', '');
17
+ appendedPath = currentPath + `/*[contains(local-name(), '${pathName}')]`;
18
+ }
19
+ if (!isWildcard) {
20
+ appendedPath = currentPath + `/*[local-name(.)='${name}']`;
21
+ }
22
+ return appendedPath;
23
+ }, '');
24
+ }
25
+ function buildAttributeXPath(attributes) {
26
+ if (attributes.length === 0) {
27
+ return '/text()';
28
+ }
29
+ if (attributes.length === 1) {
30
+ return `/@${attributes[0]}`;
31
+ }
32
+ const filters = attributes.map(attribute => `name()='${attribute}'`).join(' or ');
33
+ return `/@*[${filters}]`;
34
+ }
35
+ exports.loginRequestFields = [
36
+ {
37
+ key: 'request',
38
+ localPath: ['AuthnRequest'],
39
+ attributes: ['ID', 'IssueInstant', 'Destination', 'AssertionConsumerServiceURL']
40
+ },
41
+ {
42
+ key: 'issuer',
43
+ localPath: ['AuthnRequest', 'Issuer'],
44
+ attributes: []
45
+ },
46
+ {
47
+ key: 'nameIDPolicy',
48
+ localPath: ['AuthnRequest', 'NameIDPolicy'],
49
+ attributes: ['Format', 'AllowCreate']
50
+ },
51
+ {
52
+ key: 'authnContextClassRef',
53
+ localPath: ['AuthnRequest', 'AuthnContextClassRef'],
54
+ attributes: []
55
+ },
56
+ {
57
+ key: 'signature',
58
+ localPath: ['AuthnRequest', 'Signature'],
59
+ attributes: [],
60
+ context: true
61
+ }
62
+ ];
63
+ // support two-tiers status code
64
+ exports.loginResponseStatusFields = [
65
+ {
66
+ key: 'top',
67
+ localPath: ['Response', 'Status', 'StatusCode'],
68
+ attributes: ['Value'],
69
+ },
70
+ {
71
+ key: 'second',
72
+ localPath: ['Response', 'Status', 'StatusCode', 'StatusCode'],
73
+ attributes: ['Value'],
74
+ }
75
+ ];
76
+ // support two-tiers status code
77
+ exports.logoutResponseStatusFields = [
78
+ {
79
+ key: 'top',
80
+ localPath: ['LogoutResponse', 'Status', 'StatusCode'],
81
+ attributes: ['Value']
82
+ },
83
+ {
84
+ key: 'second',
85
+ localPath: ['LogoutResponse', 'Status', 'StatusCode', 'StatusCode'],
86
+ attributes: ['Value'],
87
+ }
88
+ ];
89
+ const loginResponseFields = assertion => [
90
+ {
91
+ key: 'conditions',
92
+ localPath: ['Assertion', 'Conditions'],
93
+ attributes: ['NotBefore', 'NotOnOrAfter'],
94
+ shortcut: assertion
95
+ },
96
+ {
97
+ key: 'response',
98
+ localPath: ['Response'],
99
+ attributes: ['ID', 'IssueInstant', 'Destination', 'InResponseTo'],
100
+ },
101
+ {
102
+ key: 'audience',
103
+ localPath: ['Assertion', 'Conditions', 'AudienceRestriction', 'Audience'],
104
+ attributes: [],
105
+ shortcut: assertion
106
+ },
107
+ // {
108
+ // key: 'issuer',
109
+ // localPath: ['Response', 'Issuer'],
110
+ // attributes: []
111
+ // },
112
+ {
113
+ key: 'issuer',
114
+ localPath: ['Assertion', 'Issuer'],
115
+ attributes: [],
116
+ shortcut: assertion
117
+ },
118
+ {
119
+ key: 'nameID',
120
+ localPath: ['Assertion', 'Subject', 'NameID'],
121
+ attributes: [],
122
+ shortcut: assertion
123
+ },
124
+ {
125
+ key: 'sessionIndex',
126
+ localPath: ['Assertion', 'AuthnStatement'],
127
+ attributes: ['AuthnInstant', 'SessionNotOnOrAfter', 'SessionIndex'],
128
+ shortcut: assertion
129
+ },
130
+ {
131
+ key: 'attributes',
132
+ localPath: ['Assertion', 'AttributeStatement', 'Attribute'],
133
+ index: ['Name'],
134
+ attributePath: ['AttributeValue'],
135
+ attributes: [],
136
+ shortcut: assertion
137
+ }
138
+ ];
139
+ exports.loginResponseFields = loginResponseFields;
140
+ exports.logoutRequestFields = [
141
+ {
142
+ key: 'request',
143
+ localPath: ['LogoutRequest'],
144
+ attributes: ['ID', 'IssueInstant', 'Destination']
145
+ },
146
+ {
147
+ key: 'issuer',
148
+ localPath: ['LogoutRequest', 'Issuer'],
149
+ attributes: []
150
+ },
151
+ {
152
+ key: 'nameID',
153
+ localPath: ['LogoutRequest', 'NameID'],
154
+ attributes: []
155
+ },
156
+ {
157
+ key: 'sessionIndex',
158
+ localPath: ['LogoutRequest', 'SessionIndex'],
159
+ attributes: []
160
+ },
161
+ {
162
+ key: 'signature',
163
+ localPath: ['LogoutRequest', 'Signature'],
164
+ attributes: [],
165
+ context: true
166
+ }
167
+ ];
168
+ exports.logoutResponseFields = [
169
+ {
170
+ key: 'response',
171
+ localPath: ['LogoutResponse'],
172
+ attributes: ['ID', 'Destination', 'InResponseTo']
173
+ },
174
+ {
175
+ key: 'issuer',
176
+ localPath: ['LogoutResponse', 'Issuer'],
177
+ attributes: []
178
+ },
179
+ {
180
+ key: 'signature',
181
+ localPath: ['LogoutResponse', 'Signature'],
182
+ attributes: [],
183
+ context: true
184
+ }
185
+ ];
186
+ function extract(context, fields) {
187
+ const { dom } = (0, api_js_1.getContext)();
188
+ const rootDoc = dom.parseFromString(context, 'application/xml');
189
+ return fields.reduce((result, field) => {
190
+ // get essential fields
191
+ const key = field.key;
192
+ const localPath = field.localPath;
193
+ const attributes = field.attributes;
194
+ const isEntire = field.context;
195
+ const shortcut = field.shortcut;
196
+ // get optional fields
197
+ const index = field.index;
198
+ const attributePath = field.attributePath;
199
+ // set allowing overriding if there is a shortcut injected
200
+ let targetDoc = rootDoc;
201
+ // if shortcut is used, then replace the doc
202
+ // it's a design for overriding the doc used during runtime
203
+ if (shortcut) {
204
+ targetDoc = dom.parseFromString(shortcut, 'application/xml');
205
+ }
206
+ // special case: multiple path
207
+ /*
208
+ {
209
+ key: 'issuer',
210
+ localPath: [
211
+ ['Response', 'Issuer'],
212
+ ['Response', 'Assertion', 'Issuer']
213
+ ],
214
+ attributes: []
215
+ }
216
+ */
217
+ if (localPath.every(path => Array.isArray(path))) {
218
+ const multiXPaths = localPath
219
+ .map(path => {
220
+ // not support attribute yet, so ignore it
221
+ return `${buildAbsoluteXPath(path)}/text()`;
222
+ })
223
+ .join(' | ');
224
+ return {
225
+ ...result,
226
+ // @ts-expect-error misssing Node properties are not needed
227
+ [key]: (0, utility_js_1.uniq)((0, xpath_1.select)(multiXPaths, targetDoc).map((n) => n.nodeValue).filter(utility_js_1.notEmpty))
228
+ };
229
+ }
230
+ // eo special case: multiple path
231
+ const baseXPath = buildAbsoluteXPath(localPath);
232
+ const attributeXPath = buildAttributeXPath(attributes);
233
+ // special case: get attributes where some are in child, some are in parent
234
+ /*
235
+ {
236
+ key: 'attributes',
237
+ localPath: ['Response', 'Assertion', 'AttributeStatement', 'Attribute'],
238
+ index: ['Name'],
239
+ attributePath: ['AttributeValue'],
240
+ attributes: []
241
+ }
242
+ */
243
+ if (index && attributePath) {
244
+ // find the index in localpath
245
+ const indexPath = buildAttributeXPath(index);
246
+ const fullLocalXPath = `${baseXPath}${indexPath}`;
247
+ const parentNodes = (0, xpath_1.select)(baseXPath, targetDoc);
248
+ // [uid, mail, edupersonaffiliation], ready for aggregate
249
+ // @ts-expect-error misssing Node properties are not needed
250
+ const parentAttributes = (0, xpath_1.select)(fullLocalXPath, targetDoc).map((n) => n.value);
251
+ // [attribute, attributevalue]
252
+ const childXPath = buildAbsoluteXPath([(0, utility_js_1.last)(localPath)].concat(attributePath));
253
+ const childAttributeXPath = buildAttributeXPath(attributes);
254
+ const fullChildXPath = `${childXPath}${childAttributeXPath}`;
255
+ // [ 'test', 'test@example.com', [ 'users', 'examplerole1' ] ]
256
+ // @ts-expect-error misssing Node properties are not needed
257
+ const childAttributes = parentNodes.map(node => {
258
+ const nodeDoc = dom.parseFromString(node.toString(), 'application/xml');
259
+ if (attributes.length === 0) {
260
+ // @ts-expect-error misssing Node properties are not needed
261
+ const childValues = (0, xpath_1.select)(fullChildXPath, nodeDoc).map((n) => n.nodeValue);
262
+ if (childValues.length === 1) {
263
+ return childValues[0];
264
+ }
265
+ return childValues;
266
+ }
267
+ if (attributes.length > 0) {
268
+ // @ts-expect-error misssing Node properties are not needed
269
+ const childValues = (0, xpath_1.select)(fullChildXPath, nodeDoc).map((n) => n.value);
270
+ if (childValues.length === 1) {
271
+ return childValues[0];
272
+ }
273
+ return childValues;
274
+ }
275
+ return null;
276
+ });
277
+ // aggregation
278
+ const obj = (0, utility_js_1.zipObject)(parentAttributes, childAttributes, false);
279
+ return {
280
+ ...result,
281
+ [key]: obj
282
+ };
283
+ }
284
+ // case: fetch entire content, only allow one existence
285
+ /*
286
+ {
287
+ key: 'signature',
288
+ localPath: ['AuthnRequest', 'Signature'],
289
+ attributes: [],
290
+ context: true
291
+ }
292
+ */
293
+ if (isEntire) {
294
+ const node = (0, xpath_1.select)(baseXPath, targetDoc);
295
+ let value = null;
296
+ // @ts-expect-error misssing Node properties are not needed
297
+ if (node.length === 1) {
298
+ // @ts-expect-error misssing Node properties are not needed
299
+ value = node[0].toString();
300
+ }
301
+ // @ts-expect-error misssing Node properties are not needed
302
+ if (node.length > 1) {
303
+ // @ts-expect-error misssing Node properties are not needed
304
+ value = node.map(n => n.toString());
305
+ }
306
+ return {
307
+ ...result,
308
+ [key]: value
309
+ };
310
+ }
311
+ // case: multiple attribute
312
+ /*
313
+ {
314
+ key: 'nameIDPolicy',
315
+ localPath: ['AuthnRequest', 'NameIDPolicy'],
316
+ attributes: ['Format', 'AllowCreate']
317
+ }
318
+ */
319
+ if (attributes.length > 1) {
320
+ // @ts-expect-error misssing Node properties are not needed
321
+ const baseNode = (0, xpath_1.select)(baseXPath, targetDoc).map(n => n.toString());
322
+ const childXPath = `${buildAbsoluteXPath([(0, utility_js_1.last)(localPath)])}${attributeXPath}`;
323
+ const attributeValues = baseNode.map((node) => {
324
+ const nodeDoc = dom.parseFromString(node, 'application/xml');
325
+ // @ts-expect-error misssing Node properties are not needed
326
+ const values = (0, xpath_1.select)(childXPath, nodeDoc).reduce((r, n) => {
327
+ r[(0, camelcase_1.default)(n.name, { locale: 'en-us' })] = n.value;
328
+ return r;
329
+ }, {});
330
+ return values;
331
+ });
332
+ return {
333
+ ...result,
334
+ [key]: attributeValues.length === 1 ? attributeValues[0] : attributeValues
335
+ };
336
+ }
337
+ // case: single attribute
338
+ /*
339
+ {
340
+ key: 'statusCode',
341
+ localPath: ['Response', 'Status', 'StatusCode'],
342
+ attributes: ['Value'],
343
+ }
344
+ */
345
+ if (attributes.length === 1) {
346
+ const fullPath = `${baseXPath}${attributeXPath}`;
347
+ // @ts-expect-error misssing Node properties are not needed
348
+ const attributeValues = (0, xpath_1.select)(fullPath, targetDoc).map((n) => n.value);
349
+ return {
350
+ ...result,
351
+ [key]: attributeValues[0]
352
+ };
353
+ }
354
+ // case: zero attribute
355
+ /*
356
+ {
357
+ key: 'issuer',
358
+ localPath: ['AuthnRequest', 'Issuer'],
359
+ attributes: []
360
+ }
361
+ */
362
+ if (attributes.length === 0) {
363
+ let attributeValue = null;
364
+ const node = (0, xpath_1.select)(baseXPath, targetDoc);
365
+ // @ts-expect-error misssing Node properties are not needed
366
+ if (node.length === 1) {
367
+ const fullPath = `string(${baseXPath}${attributeXPath})`;
368
+ // @ts-expect-error misssing Node properties are not needed
369
+ attributeValue = (0, xpath_1.select)(fullPath, targetDoc);
370
+ }
371
+ // @ts-expect-error misssing Node properties are not needed
372
+ if (node.length > 1) {
373
+ // @ts-expect-error misssing Node properties are not needed
374
+ attributeValue = node.filter((n) => n.firstChild)
375
+ .map((n) => n.firstChild.nodeValue);
376
+ }
377
+ return {
378
+ ...result,
379
+ [key]: attributeValue
380
+ };
381
+ }
382
+ return result;
383
+ }, {});
384
+ }
385
+ exports.extract = extract;
370
386
  //# sourceMappingURL=extractor.js.map