@adobe/acc-js-sdk 1.1.24 → 1.1.26
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/docs/changeLog.html +25 -1
- package/docs/connecting.html +62 -4
- package/docs/samples.html +1 -1
- package/package-lock.json +2 -2
- package/package.json +1 -1
- package/src/client.js +127 -49
- package/src/domUtil.js +8 -10
- package/src/soap.js +12 -4
- package/src/util.js +1 -12
- package/test/client.test.js +108 -1
- package/test/domUtil.test.js +14 -0
- package/test/imBearerToken.test.js +174 -0
package/docs/changeLog.html
CHANGED
|
@@ -2,9 +2,33 @@
|
|
|
2
2
|
layout: page
|
|
3
3
|
title: Change Log
|
|
4
4
|
---
|
|
5
|
-
|
|
5
|
+
|
|
6
|
+
<section class="changelog"><h1>Version 1.1.26</h1>
|
|
7
|
+
<h2>2023/04/17</h2>
|
|
8
|
+
|
|
9
|
+
<li>
|
|
10
|
+
Added support for IMS Bearer tokens without require any session and security tokens. See <a href="https://opensource.adobe.com/acc-js-sdk/connecting.html"> for more details.</a>
|
|
11
|
+
</li>
|
|
12
|
+
<li>
|
|
13
|
+
Fixed a bug causing incorrect JSON to XML transformation when the JSON object has a property named 'length'
|
|
14
|
+
</li>
|
|
15
|
+
</section>
|
|
16
|
+
|
|
17
|
+
<section class="changelog"><h1>Version 1.1.25</h1>
|
|
6
18
|
<h2>2023/03/07</h2>
|
|
7
19
|
|
|
20
|
+
<li>
|
|
21
|
+
Added an (optional) parameter "options" to the file upload function. This parameter contains an "action" property whose value
|
|
22
|
+
can be "publishIfNeeded" or "none" and indicates which action the upload function should perform after it uploaded the file.
|
|
23
|
+
The default is "publishIfNeeded" which consists of creating a public resources with the file content and publishing it (making
|
|
24
|
+
it available publicly). The other action "none" means that no action is taken and that it is the responsibility of the caller
|
|
25
|
+
to post-process the uploaded file by calling the relevant APIs.
|
|
26
|
+
</li>
|
|
27
|
+
</section>
|
|
28
|
+
|
|
29
|
+
<section class="changelog"><h1>Version 1.1.24</h1>
|
|
30
|
+
<h2>2023/04/07</h2>
|
|
31
|
+
|
|
8
32
|
<li>
|
|
9
33
|
Added support for abortable requests. See <a href="https://opensource.adobe.com/acc-js-sdk/abortRequest.html"> for more details.</a>
|
|
10
34
|
</li>
|
package/docs/connecting.html
CHANGED
|
@@ -51,19 +51,58 @@ await client.logoff();
|
|
|
51
51
|
<li>Informations about the connected user, and it's privileges</li>
|
|
52
52
|
</ul>
|
|
53
53
|
|
|
54
|
-
<p>
|
|
55
|
-
he most convenient way to access this information is by using the <a href="{{ site.baseurl }}/application.html">Application object</a>, but you can
|
|
54
|
+
<p>The most convenient way to access this information is by using the <a href="{{ site.baseurl }}/application.html">Application object</a>, but you can
|
|
56
55
|
also use the <b>client.getSessionInfo().serverInfo</b> and <b>client.getSessionInfo().sessionInfo</b> calls.
|
|
57
56
|
</p>
|
|
58
57
|
|
|
58
|
+
<p class="info">Note: depending on the type of credentials used, user and server info may not be returned.
|
|
59
|
+
</p>
|
|
59
60
|
|
|
61
|
+
<table>
|
|
62
|
+
<thead>
|
|
63
|
+
<tr>
|
|
64
|
+
<th>Credentials Type</th>
|
|
65
|
+
<th>Returns info</th>
|
|
66
|
+
</tr>
|
|
67
|
+
</thead>
|
|
68
|
+
<tbody>
|
|
69
|
+
<tr>
|
|
70
|
+
<td>UserPassword</td>
|
|
71
|
+
<td>Yes</td>
|
|
72
|
+
</tr>
|
|
73
|
+
<tr>
|
|
74
|
+
<td>ImsServiceToken</td>
|
|
75
|
+
<td>Yes</td>
|
|
76
|
+
</tr>
|
|
77
|
+
<tr>
|
|
78
|
+
<td>SessionToken</td>
|
|
79
|
+
<td>No</td>
|
|
80
|
+
</tr>
|
|
81
|
+
<tr>
|
|
82
|
+
<td>AnonymousUser</td>
|
|
83
|
+
<td>No</td>
|
|
84
|
+
</tr>
|
|
85
|
+
<tr>
|
|
86
|
+
<td>SecurityToken</td>
|
|
87
|
+
<td>Yes</td>
|
|
88
|
+
</tr>
|
|
89
|
+
<tr>
|
|
90
|
+
<td>BearerToken</td>
|
|
91
|
+
<td>Yes</td>
|
|
92
|
+
</tr>
|
|
93
|
+
<tr>
|
|
94
|
+
<td>ImsBearerToken</td>
|
|
95
|
+
<td>No</td>
|
|
96
|
+
</tr>
|
|
97
|
+
</tbody>
|
|
98
|
+
</table>
|
|
60
99
|
|
|
61
100
|
<h1>Credentials</h1>
|
|
62
101
|
|
|
63
102
|
<p>
|
|
64
103
|
There are several methods of the <b>sdk.ConnectionParameters</b> depending on the type of authentication you want to use. They are
|
|
65
104
|
described below.
|
|
66
|
-
</p
|
|
105
|
+
</p>
|
|
67
106
|
|
|
68
107
|
<h2>Login with user and password</h2>
|
|
69
108
|
<p>This is the most common method to log in to Campaign. User the <b>ofUserAndPassword</b> function and pass it the user name and password</p>
|
|
@@ -75,7 +114,26 @@ const connectionParameters = sdk.ConnectionParameters.ofUserAndPassword(
|
|
|
75
114
|
|
|
76
115
|
|
|
77
116
|
<h2>Login with IMS access token</h2>
|
|
78
|
-
|
|
117
|
+
|
|
118
|
+
<p>In Campaign 8.5 and above, native support for IMS bearer tokens is avaiable and can be used in the SDK as the preferred connection method.</p>
|
|
119
|
+
<pre class="code">
|
|
120
|
+
const connectionParameters = sdk.ConnectionParameters.ofImsBearerToken(
|
|
121
|
+
"https://myInstance.campaign.adobe.com",
|
|
122
|
+
"ims_bearer_token");
|
|
123
|
+
</pre>
|
|
124
|
+
|
|
125
|
+
|
|
126
|
+
<p class="info">Note: You still need to call Logon
|
|
127
|
+
</p>
|
|
128
|
+
|
|
129
|
+
<p>With this authentication method, an IMS Bearer token is obtained outside of Campaign, for example using IMS APIs and is passed directly to
|
|
130
|
+
all Campaign APIs. Campaigns itslef will verify the token and grant the corresponding access.
|
|
131
|
+
</p>
|
|
132
|
+
|
|
133
|
+
|
|
134
|
+
<p>For older versions of Campaign, you can still use IMS tokens with the <b>ofBearerToken</b> function. The difference between ofImsBearerToken and ofBearerToken
|
|
135
|
+
is that ofBearerToken will internally call "xtk:session#BearerTokenLogon" to exchange the IMS token for Campaign session and security tokens. Subsequent
|
|
136
|
+
API calls will use Campaign tokens. It's recommended to us <b>ofImsBearerToken</b> logon whenever possible.</p>
|
|
79
137
|
<pre class="code">
|
|
80
138
|
const connectionParameters = sdk.ConnectionParameters.ofBearerToken(
|
|
81
139
|
"https://myInstance.campaign.adobe.com",
|
package/docs/samples.html
CHANGED
|
@@ -3,7 +3,7 @@ layout: page
|
|
|
3
3
|
title: Sample Code
|
|
4
4
|
---
|
|
5
5
|
|
|
6
|
-
<p>The <b>samples</b> folder contains several samples illustrating how to use the various
|
|
6
|
+
<p>The <b>samples</b> folder contains several samples illustrating how to use the various Campaign APIs.</p>
|
|
7
7
|
|
|
8
8
|
<p>A sample file looks like this</p>
|
|
9
9
|
|
package/package-lock.json
CHANGED
|
@@ -1,12 +1,12 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@adobe/acc-js-sdk",
|
|
3
|
-
"version": "1.1.
|
|
3
|
+
"version": "1.1.26",
|
|
4
4
|
"lockfileVersion": 3,
|
|
5
5
|
"requires": true,
|
|
6
6
|
"packages": {
|
|
7
7
|
"": {
|
|
8
8
|
"name": "@adobe/acc-js-sdk",
|
|
9
|
-
"version": "1.1.
|
|
9
|
+
"version": "1.1.26",
|
|
10
10
|
"license": "ISC",
|
|
11
11
|
"dependencies": {
|
|
12
12
|
"axios": "^1.2.1",
|
package/package.json
CHANGED
package/src/client.js
CHANGED
|
@@ -11,7 +11,7 @@ governing permissions and limitations under the License.
|
|
|
11
11
|
*/
|
|
12
12
|
(function() {
|
|
13
13
|
"use strict";
|
|
14
|
-
|
|
14
|
+
/*jshint sub:true*/
|
|
15
15
|
|
|
16
16
|
/**********************************************************************************
|
|
17
17
|
*
|
|
@@ -244,12 +244,12 @@ class Credentials {
|
|
|
244
244
|
*/
|
|
245
245
|
constructor(type, sessionToken, securityToken) {
|
|
246
246
|
if (type != "UserPassword" && type != "ImsServiceToken" && type != "SessionToken" &&
|
|
247
|
-
type != "AnonymousUser" && type != "SecurityToken" && type != "BearerToken")
|
|
247
|
+
type != "AnonymousUser" && type != "SecurityToken" && type != "BearerToken" && type != "ImsBearerToken")
|
|
248
248
|
throw CampaignException.INVALID_CREDENTIALS_TYPE(type);
|
|
249
249
|
this._type = type;
|
|
250
250
|
this._sessionToken = sessionToken || "";
|
|
251
251
|
this._securityToken = securityToken || "";
|
|
252
|
-
if (type == "BearerToken") {
|
|
252
|
+
if (type == "BearerToken" || type === "ImsBearerToken") {
|
|
253
253
|
this._bearerToken = sessionToken || "";
|
|
254
254
|
this._sessionToken = "";
|
|
255
255
|
}
|
|
@@ -397,8 +397,13 @@ class ConnectionParameters {
|
|
|
397
397
|
}
|
|
398
398
|
|
|
399
399
|
/**
|
|
400
|
-
* Creates connection parameters for a Campaign instance from bearer token
|
|
401
|
-
*
|
|
400
|
+
* Creates connection parameters for a Campaign instance from bearer token.
|
|
401
|
+
* This authentication method uses an IMS Bearer token and calls the xtk:session#BearerTokenLogin method
|
|
402
|
+
* which will exchange the IMS bearer token with Campaign session and security tokens.
|
|
403
|
+
* This is a legacy method. Campaign 8.5 will has an authentication method which allows to directly
|
|
404
|
+
* use the IMS bearer token and which is recommended.
|
|
405
|
+
* To avoid an extra call to "BearerTokenLogin", use the "ofImsBearerToken" method.
|
|
406
|
+
*
|
|
402
407
|
* @param {string} endpoint The campaign endpoint (URL)
|
|
403
408
|
* @param {string} bearerToken IMS bearer token
|
|
404
409
|
* @param {*} options connection options
|
|
@@ -408,6 +413,23 @@ class ConnectionParameters {
|
|
|
408
413
|
const credentials = new Credentials("BearerToken", bearerToken);
|
|
409
414
|
return new ConnectionParameters(endpoint, credentials, options);
|
|
410
415
|
}
|
|
416
|
+
|
|
417
|
+
/**
|
|
418
|
+
* Creates connection parameters for a Campaign instance from a IMS bearer token.
|
|
419
|
+
* This authentication method does not require exchange the IMS token with session and security tokens
|
|
420
|
+
* and only works in ACC 8.5 and above.
|
|
421
|
+
* For older version of ACC or to use session/seurity tokens, use the "ofBearerToken" method.
|
|
422
|
+
*
|
|
423
|
+
* @param {string} endpoint The campaign endpoint (URL)
|
|
424
|
+
* @param {string} bearerToken IMS bearer token
|
|
425
|
+
* @param {*} options connection options
|
|
426
|
+
* @returns {ConnectionParameters} a ConnectionParameters object which can be used to create a Client
|
|
427
|
+
*/
|
|
428
|
+
static ofImsBearerToken(endpoint, bearerToken, options) {
|
|
429
|
+
const credentials = new Credentials("ImsBearerToken", bearerToken);
|
|
430
|
+
return new ConnectionParameters(endpoint, credentials, options);
|
|
431
|
+
}
|
|
432
|
+
|
|
411
433
|
/**
|
|
412
434
|
* Creates connection parameters for a Campaign instance, using an IMS service token and a user name (the user to impersonate)
|
|
413
435
|
*
|
|
@@ -520,6 +542,13 @@ class ConnectionParameters {
|
|
|
520
542
|
// File Uploader
|
|
521
543
|
// ========================================================================================
|
|
522
544
|
|
|
545
|
+
/**
|
|
546
|
+
* @typedef {Object} FileUploadOptions
|
|
547
|
+
* @property {"publishIfNeeded"|"none"|undefined} the post-processing action to execute. Defaults to "publishIfNeeded"
|
|
548
|
+
* @memberOf Campaign
|
|
549
|
+
*/
|
|
550
|
+
|
|
551
|
+
|
|
523
552
|
/**
|
|
524
553
|
* File Uploader API for JS SDK(Currently available only in browsers)
|
|
525
554
|
* @private
|
|
@@ -535,26 +564,28 @@ const fileUploader = (client) => {
|
|
|
535
564
|
* This is the exposed/public method for fileUploader instance which will do all the processing related to the upload process internally and returns the promise containing all the required data.
|
|
536
565
|
* @ignore
|
|
537
566
|
* @param file, where file is an instance of [File](https://developer.mozilla.org/en-US/docs/Web/API/File)
|
|
567
|
+
* @param {FileUploadOptions|undefined} options
|
|
538
568
|
* @returns {Promise<{name: string, md5: string, type: string, size: string, url: string}>}
|
|
539
569
|
*/
|
|
540
|
-
upload: (file) => {
|
|
570
|
+
upload: (file, options) => {
|
|
541
571
|
console.log(`fileuploader.upload is an experimental feature and is not currently fully functional. It is work in progress and will change in the future.`);
|
|
542
572
|
return new Promise((resolve, reject) => {
|
|
573
|
+
const action = (options && options.action) ? options.action : "publishIfNeeded";
|
|
574
|
+
if (action !== "publishIfNeeded" && action !== "none")
|
|
575
|
+
reject(CampaignException.BAD_PARAMETER("action", action, "The 'action' parameter of the upload API should be 'publishIfNeeded' or 'none'"));
|
|
543
576
|
try {
|
|
544
577
|
if (!Util.isBrowser()) {
|
|
545
578
|
throw 'File uploading is only supported in browser based calls.';
|
|
546
579
|
}
|
|
547
580
|
const data = new FormData();
|
|
548
581
|
data.append('file_noMd5', file);
|
|
582
|
+
const headers = client._getAuthHeaders(false);
|
|
549
583
|
client._makeHttpCall({
|
|
550
584
|
url: `${client._connectionParameters._endpoint}/nl/jsp/uploadFile.jsp`,
|
|
551
585
|
processData: false,
|
|
552
586
|
method: 'POST',
|
|
553
587
|
data: data,
|
|
554
|
-
headers:
|
|
555
|
-
'X-Security-Token': client._securityToken,
|
|
556
|
-
'X-Session-Token': client._sessionToken,
|
|
557
|
-
}
|
|
588
|
+
headers: headers
|
|
558
589
|
}).then((okay) => {
|
|
559
590
|
if (!okay.startsWith('Ok')) {
|
|
560
591
|
throw okay;
|
|
@@ -569,28 +600,31 @@ const fileUploader = (client) => {
|
|
|
569
600
|
// https://git.corp.adobe.com/Campaign/ac/blob/v6-master/wpp/xtk/web/dce/uploader.js
|
|
570
601
|
return reject(CampaignException.FILE_UPLOAD_FAILED(file.name, 'Malformed data:' + data.toString()));
|
|
571
602
|
}
|
|
572
|
-
const
|
|
573
|
-
const fileRes= {
|
|
574
|
-
internalName: 'RES' + counter,
|
|
575
|
-
md5: data[0].md5,
|
|
576
|
-
label: data[0].fileName,
|
|
577
|
-
fileName: data[0].fileName,
|
|
578
|
-
originalName: data[0].fileName,
|
|
579
|
-
useMd5AsFilename: '1',
|
|
580
|
-
storageType: 5,
|
|
581
|
-
xtkschema: 'xtk:fileRes'
|
|
582
|
-
|
|
583
|
-
};
|
|
584
|
-
await client.NLWS.xtkSession.write(fileRes);
|
|
585
|
-
await client.NLWS.xtkFileRes.create(fileRes).publishIfNeeded();
|
|
586
|
-
const url = await client.NLWS.xtkFileRes.create(fileRes).getURL();
|
|
587
|
-
resolve({
|
|
603
|
+
const result = {
|
|
588
604
|
name: data[0].fileName,
|
|
589
605
|
md5: data[0].md5,
|
|
590
606
|
type: file.type,
|
|
591
607
|
size: file.size,
|
|
592
|
-
|
|
593
|
-
|
|
608
|
+
};
|
|
609
|
+
if (action === "publishIfNeeded") {
|
|
610
|
+
const counter = await client.NLWS.xtkCounter.increaseValue({name: 'xtkResource'});
|
|
611
|
+
const fileRes= {
|
|
612
|
+
internalName: 'RES' + counter,
|
|
613
|
+
md5: data[0].md5,
|
|
614
|
+
label: data[0].fileName,
|
|
615
|
+
fileName: data[0].fileName,
|
|
616
|
+
originalName: data[0].fileName,
|
|
617
|
+
useMd5AsFilename: '1',
|
|
618
|
+
storageType: 5,
|
|
619
|
+
xtkschema: 'xtk:fileRes'
|
|
620
|
+
|
|
621
|
+
};
|
|
622
|
+
await client.NLWS.xtkSession.write(fileRes);
|
|
623
|
+
await client.NLWS.xtkFileRes.create(fileRes).publishIfNeeded();
|
|
624
|
+
const url = await client.NLWS.xtkFileRes.create(fileRes).getURL();
|
|
625
|
+
result.url = url;
|
|
626
|
+
}
|
|
627
|
+
resolve(result);
|
|
594
628
|
}
|
|
595
629
|
};
|
|
596
630
|
const html = `<body>${okay}</body>`;
|
|
@@ -631,13 +665,28 @@ class Client {
|
|
|
631
665
|
*/
|
|
632
666
|
constructor(sdk, connectionParameters) {
|
|
633
667
|
this.sdk = sdk;
|
|
668
|
+
this.reinit(connectionParameters);
|
|
669
|
+
|
|
670
|
+
this._observers = [];
|
|
671
|
+
this._cacheChangeListeners = [];
|
|
672
|
+
}
|
|
673
|
+
|
|
674
|
+
/**
|
|
675
|
+
* Re-initialize a client with new connection parameters.
|
|
676
|
+
* Typically called from the refreshClient callback after a connection expires.
|
|
677
|
+
* Conserves observers
|
|
678
|
+
*
|
|
679
|
+
* @param {Campaign.ConnectionParameters} user user name, for instance admin
|
|
680
|
+
*/
|
|
681
|
+
reinit(connectionParameters) {
|
|
634
682
|
this._connectionParameters = connectionParameters; // ## TODO security concern (password kept in memory)
|
|
635
683
|
this._representation = connectionParameters._options.representation;
|
|
636
684
|
|
|
637
685
|
this._sessionInfo = undefined;
|
|
638
686
|
this._sessionToken = undefined;
|
|
639
687
|
this._securityToken = undefined;
|
|
640
|
-
this.
|
|
688
|
+
this._bearerToken = undefined; // set when using Bearer authentication and "ImsBearer" credential type
|
|
689
|
+
this._installedPackages = {}; // package set (key and value = package id, ex: "nms:amp")
|
|
641
690
|
|
|
642
691
|
this._secretKeyCipher = undefined;
|
|
643
692
|
|
|
@@ -653,7 +702,7 @@ class Client {
|
|
|
653
702
|
const rootKeyType = connectionParameters._options.cacheRootKey;
|
|
654
703
|
let rootKey = "";
|
|
655
704
|
if (!rootKeyType || rootKeyType === "default")
|
|
656
|
-
rootKey = `acc.js.sdk.${sdk.getSDKVersion().version}.${instanceKey}.cache.`;
|
|
705
|
+
rootKey = `acc.js.sdk.${this.sdk.getSDKVersion().version}.${instanceKey}.cache.`;
|
|
657
706
|
|
|
658
707
|
// Clear storage cache if the sdk versions or the instances are different
|
|
659
708
|
if (this._storage && typeof this._storage.removeItem === 'function') {
|
|
@@ -673,8 +722,6 @@ class Client {
|
|
|
673
722
|
|
|
674
723
|
this._transport = connectionParameters._options.transport;
|
|
675
724
|
this._traceAPICalls = connectionParameters._options.traceAPICalls;
|
|
676
|
-
this._observers = [];
|
|
677
|
-
this._cacheChangeListeners = [];
|
|
678
725
|
this._refreshClient = connectionParameters._options.refreshClient;
|
|
679
726
|
|
|
680
727
|
// expose utilities
|
|
@@ -735,6 +782,26 @@ class Client {
|
|
|
735
782
|
return `${version.name}/${version.version} ${version.description}`;
|
|
736
783
|
}
|
|
737
784
|
|
|
785
|
+
/**
|
|
786
|
+
* Get HTTP authentication headers
|
|
787
|
+
* @param
|
|
788
|
+
* @returns {Object} the headers
|
|
789
|
+
*/
|
|
790
|
+
_getAuthHeaders(setCookie) {
|
|
791
|
+
const headers = {};
|
|
792
|
+
if (this._bearerToken) {
|
|
793
|
+
headers['Authorization'] = `Bearer ${this._bearerToken}`;
|
|
794
|
+
}
|
|
795
|
+
else {
|
|
796
|
+
headers['X-Security-Token'] = this._securityToken;
|
|
797
|
+
headers['X-Session-Token'] = this._sessionToken;
|
|
798
|
+
if (setCookie) {
|
|
799
|
+
headers['Cookie'] = '__sessiontoken=' + this._sessionToken;
|
|
800
|
+
}
|
|
801
|
+
}
|
|
802
|
+
return headers;
|
|
803
|
+
}
|
|
804
|
+
|
|
738
805
|
/**
|
|
739
806
|
* Convert an XML object into a representation
|
|
740
807
|
*
|
|
@@ -915,6 +982,9 @@ class Client {
|
|
|
915
982
|
const credentialsType = this._connectionParameters._credentials._type;
|
|
916
983
|
if (credentialsType == "AnonymousUser")
|
|
917
984
|
return true;
|
|
985
|
+
else if (credentialsType == "ImsBearerToken") {
|
|
986
|
+
return !!this._bearerToken;
|
|
987
|
+
}
|
|
918
988
|
|
|
919
989
|
// When using bearer token authentication we are considered logged only after
|
|
920
990
|
// the bearer token has been converted into session token and security token
|
|
@@ -953,7 +1023,8 @@ class Client {
|
|
|
953
1023
|
this._sessionToken, this._securityToken,
|
|
954
1024
|
this._getUserAgentString(),
|
|
955
1025
|
Object.assign({}, this._connectionParameters._options, pushDownOptions),
|
|
956
|
-
extraHttpHeaders
|
|
1026
|
+
extraHttpHeaders,
|
|
1027
|
+
this._bearerToken);
|
|
957
1028
|
soapCall.internal = !!internal;
|
|
958
1029
|
soapCall.isStatic = isStatic;
|
|
959
1030
|
return soapCall;
|
|
@@ -1310,6 +1381,7 @@ class Client {
|
|
|
1310
1381
|
this.application = null;
|
|
1311
1382
|
this._sessionToken = "";
|
|
1312
1383
|
this._securityToken = "";
|
|
1384
|
+
this._bearerToken = undefined;
|
|
1313
1385
|
const credentials = this._connectionParameters._credentials;
|
|
1314
1386
|
|
|
1315
1387
|
const sdkVersion = this.sdk.getSDKVersion();
|
|
@@ -1335,6 +1407,7 @@ class Client {
|
|
|
1335
1407
|
that._installedPackages = {};
|
|
1336
1408
|
that._sessionToken = credentials._sessionToken;
|
|
1337
1409
|
that._securityToken = "";
|
|
1410
|
+
that._bearerToken = undefined;
|
|
1338
1411
|
that._onLogon();
|
|
1339
1412
|
return Promise.resolve();
|
|
1340
1413
|
}
|
|
@@ -1343,6 +1416,16 @@ class Client {
|
|
|
1343
1416
|
that._installedPackages = {};
|
|
1344
1417
|
that._sessionToken = "";
|
|
1345
1418
|
that._securityToken = credentials._securityToken;
|
|
1419
|
+
that._bearerToken = undefined;
|
|
1420
|
+
that._onLogon();
|
|
1421
|
+
return Promise.resolve();
|
|
1422
|
+
}
|
|
1423
|
+
else if (credentials._type == "ImsBearerToken") {
|
|
1424
|
+
that._sessionInfo = undefined;
|
|
1425
|
+
that._installedPackages = {};
|
|
1426
|
+
that._sessionToken = "";
|
|
1427
|
+
that._securityToken = "";
|
|
1428
|
+
that._bearerToken = credentials._bearerToken;
|
|
1346
1429
|
that._onLogon();
|
|
1347
1430
|
return Promise.resolve();
|
|
1348
1431
|
}
|
|
@@ -1393,6 +1476,7 @@ class Client {
|
|
|
1393
1476
|
// store member variables after all parameters are decode the ensure atomicity
|
|
1394
1477
|
that._sessionToken = sessionToken;
|
|
1395
1478
|
that._securityToken = securityToken;
|
|
1479
|
+
that._bearerToken = undefined;
|
|
1396
1480
|
|
|
1397
1481
|
that._onLogon();
|
|
1398
1482
|
});
|
|
@@ -1430,6 +1514,7 @@ class Client {
|
|
|
1430
1514
|
return this._makeSoapCall(soapCall).then(function() {
|
|
1431
1515
|
that._sessionToken = "";
|
|
1432
1516
|
that._securityToken = "";
|
|
1517
|
+
that._bearerToken = undefined;
|
|
1433
1518
|
that.application = null;
|
|
1434
1519
|
soapCall.checkNoMoreArgs();
|
|
1435
1520
|
});
|
|
@@ -1437,6 +1522,7 @@ class Client {
|
|
|
1437
1522
|
else {
|
|
1438
1523
|
that._sessionToken = "";
|
|
1439
1524
|
that._securityToken = "";
|
|
1525
|
+
that._bearerToken = undefined;
|
|
1440
1526
|
that.application = null;
|
|
1441
1527
|
}
|
|
1442
1528
|
} finally {
|
|
@@ -1900,13 +1986,10 @@ class Client {
|
|
|
1900
1986
|
* @returns {Campaign.PingStatus} an object describing the server status
|
|
1901
1987
|
*/
|
|
1902
1988
|
async ping() {
|
|
1989
|
+
const headers = this._getAuthHeaders(true);
|
|
1903
1990
|
const request = {
|
|
1904
1991
|
url: `${this._connectionParameters._endpoint}/nl/jsp/ping.jsp`,
|
|
1905
|
-
headers:
|
|
1906
|
-
'X-Security-Token': this._securityToken,
|
|
1907
|
-
'X-Session-Token': this._sessionToken,
|
|
1908
|
-
'Cookie': '__sessiontoken=' + this._sessionToken
|
|
1909
|
-
}
|
|
1992
|
+
headers: headers,
|
|
1910
1993
|
};
|
|
1911
1994
|
for (let h in this._connectionParameters._options.extraHttpHeaders)
|
|
1912
1995
|
request.headers[h] = this._connectionParameters._options.extraHttpHeaders[h];
|
|
@@ -1939,14 +2022,12 @@ class Client {
|
|
|
1939
2022
|
callContext.formData.ctx = DomUtil.toXMLString(xmlCtx);
|
|
1940
2023
|
}
|
|
1941
2024
|
const selectionCount = callContext.selection.split(',').length;
|
|
1942
|
-
|
|
2025
|
+
|
|
2026
|
+
const headers = this._getAuthHeaders(false);
|
|
2027
|
+
headers['Content-Type'] = 'application/x-www-form-urlencoded';
|
|
1943
2028
|
const request = {
|
|
1944
2029
|
url: `${this._connectionParameters._endpoint}/report/${callContext.reportName}?${encodeURI(`_noRender=true&_schema=${callContext.schema}&_context=${callContext.context}&_selection=${callContext.selection}`)}&_selectionCount=${selectionCount}`,
|
|
1945
|
-
headers:
|
|
1946
|
-
'X-Security-Token': this._securityToken,
|
|
1947
|
-
'X-Session-Token': this._sessionToken,
|
|
1948
|
-
'Content-Type': 'application/x-www-form-urlencoded'
|
|
1949
|
-
},
|
|
2030
|
+
headers: headers,
|
|
1950
2031
|
method: 'POST',
|
|
1951
2032
|
data : qsStringify(callContext.formData)
|
|
1952
2033
|
};
|
|
@@ -1971,13 +2052,10 @@ class Client {
|
|
|
1971
2052
|
* @returns {Campaign.McPingStatus} an object describing Message Center server status
|
|
1972
2053
|
*/
|
|
1973
2054
|
async mcPing() {
|
|
2055
|
+
const headers = this._getAuthHeaders(true);
|
|
1974
2056
|
const request = {
|
|
1975
2057
|
url: `${this._connectionParameters._endpoint}/nl/jsp/mcPing.jsp`,
|
|
1976
|
-
headers:
|
|
1977
|
-
'X-Security-Token': this._securityToken,
|
|
1978
|
-
'X-Session-Token': this._sessionToken,
|
|
1979
|
-
'Cookie': '__sessiontoken=' + this._sessionToken
|
|
1980
|
-
}
|
|
2058
|
+
headers: headers
|
|
1981
2059
|
};
|
|
1982
2060
|
for (let h in this._connectionParameters._options.extraHttpHeaders)
|
|
1983
2061
|
request.headers[h] = this._connectionParameters._options.extraHttpHeaders[h];
|
package/src/domUtil.js
CHANGED
|
@@ -341,20 +341,18 @@ class DomUtil {
|
|
|
341
341
|
xmlElement.textContent = value;
|
|
342
342
|
xmlRoot.appendChild(xmlElement);
|
|
343
343
|
}
|
|
344
|
-
else if (
|
|
345
|
-
|
|
346
|
-
for (var i=0; i<value.length; i++) {
|
|
347
|
-
const xmlElement = doc.createElement(att);
|
|
348
|
-
this._fromJSON(doc, xmlElement, value[i], flavor);
|
|
349
|
-
xmlRoot.appendChild(xmlElement);
|
|
350
|
-
}
|
|
351
|
-
}
|
|
352
|
-
else {
|
|
344
|
+
else if (Util.isArray(value)) {
|
|
345
|
+
for (var i=0; i<value.length; i++) {
|
|
353
346
|
const xmlElement = doc.createElement(att);
|
|
354
|
-
this._fromJSON(doc, xmlElement, value, flavor);
|
|
347
|
+
this._fromJSON(doc, xmlElement, value[i], flavor);
|
|
355
348
|
xmlRoot.appendChild(xmlElement);
|
|
356
349
|
}
|
|
357
350
|
}
|
|
351
|
+
else if (t == "object") {
|
|
352
|
+
const xmlElement = doc.createElement(att);
|
|
353
|
+
this._fromJSON(doc, xmlElement, value, flavor);
|
|
354
|
+
xmlRoot.appendChild(xmlElement);
|
|
355
|
+
}
|
|
358
356
|
else
|
|
359
357
|
throw new DomException(`Cannot cast JSON to XML: element '${att}' type '${t}' is unknown or not supported yet`);
|
|
360
358
|
}
|
package/src/soap.js
CHANGED
|
@@ -11,7 +11,7 @@ governing permissions and limitations under the License.
|
|
|
11
11
|
*/
|
|
12
12
|
(function() {
|
|
13
13
|
"use strict";
|
|
14
|
-
|
|
14
|
+
/*jshint sub:true*/
|
|
15
15
|
|
|
16
16
|
/**********************************************************************************
|
|
17
17
|
*
|
|
@@ -80,11 +80,12 @@ const NS_XSD = "http://www.w3.org/2001/XMLSchema";
|
|
|
80
80
|
* @param {string} userAgentString The user agent string to use for HTTP requests
|
|
81
81
|
* @param {string} pushDownOptions Options to push down to the request (comes from connectionParameters._options)
|
|
82
82
|
* @param {{ name:string, value:string}} extraHttpHeaders key/value pair of HTTP header (will override any other headers)
|
|
83
|
+
* @param {string} bearerToken The bearer token to use for HTTP requests. Only required for ImsBearerToken authentication
|
|
83
84
|
* @memberof SOAP
|
|
84
85
|
*/
|
|
85
86
|
class SoapMethodCall {
|
|
86
87
|
|
|
87
|
-
constructor(transport, urn, methodName, sessionToken, securityToken, userAgentString, pushDownOptions, extraHttpHeaders) {
|
|
88
|
+
constructor(transport, urn, methodName, sessionToken, securityToken, userAgentString, pushDownOptions, extraHttpHeaders, bearerToken) {
|
|
88
89
|
this.request = undefined; // The HTTP request (object literal passed to the transport layer)
|
|
89
90
|
this.requestOptions = undefined;
|
|
90
91
|
this.response = undefined; // The HTTP response object (in case of success)
|
|
@@ -103,6 +104,7 @@ class SoapMethodCall {
|
|
|
103
104
|
|
|
104
105
|
this._sessionToken = sessionToken || "";
|
|
105
106
|
this._securityToken = securityToken || "";
|
|
107
|
+
this._bearerToken = bearerToken; // may be undefined if not using bearer token authentication
|
|
106
108
|
this._userAgentString = userAgentString;
|
|
107
109
|
this._pushDownOptions = pushDownOptions || {};
|
|
108
110
|
this._charset = this._pushDownOptions.charset || '';
|
|
@@ -538,9 +540,14 @@ class SoapMethodCall {
|
|
|
538
540
|
const headers = {
|
|
539
541
|
'Content-type': `application/soap+xml${this._charset ? ";charset=" + this._charset : ""}`,
|
|
540
542
|
'SoapAction': `${this.urn}#${this.methodName}`,
|
|
541
|
-
'X-Security-Token': this._securityToken,
|
|
542
|
-
'X-Session-Token': this._sessionToken,
|
|
543
543
|
};
|
|
544
|
+
if (this._bearerToken) {
|
|
545
|
+
headers['Authorization'] = `Bearer ${this._bearerToken}`;
|
|
546
|
+
}
|
|
547
|
+
else {
|
|
548
|
+
headers['X-Security-Token'] = this._securityToken;
|
|
549
|
+
headers['X-Session-Token'] = this._sessionToken;
|
|
550
|
+
}
|
|
544
551
|
|
|
545
552
|
// Add HTTP headers specific to the SOAP call for better tracing/troubleshooting
|
|
546
553
|
if (this._extraHttpHeaders && this._extraHttpHeaders['ACC-SDK-Version']) {
|
|
@@ -579,6 +586,7 @@ class SoapMethodCall {
|
|
|
579
586
|
if (client) {
|
|
580
587
|
this._sessionToken = client._sessionToken;
|
|
581
588
|
this._securityToken = client._securityToken;
|
|
589
|
+
this._bearerToken = client._bearerToken;
|
|
582
590
|
}
|
|
583
591
|
|
|
584
592
|
var cookieHeader = DomUtil.findElement(this._header, "Cookie");
|
package/src/util.js
CHANGED
|
@@ -51,18 +51,7 @@ class Util {
|
|
|
51
51
|
* @returns {boolean} true if the object is an array
|
|
52
52
|
*/
|
|
53
53
|
static isArray(obj) {
|
|
54
|
-
|
|
55
|
-
// JavaScript arrays are objects
|
|
56
|
-
if (typeof obj != "object") return false;
|
|
57
|
-
// They also have a length property. But checking the length is not enough
|
|
58
|
-
// since, it can also be an object literal with a "length" property. Campaign
|
|
59
|
-
// schema attributes typically have a "length" attribute and are not arrays
|
|
60
|
-
if (obj.length === undefined || obj.length === null) return false;
|
|
61
|
-
// So check for a "push" function
|
|
62
|
-
if (obj.push === undefined || obj.push === null) return false;
|
|
63
|
-
if (typeof obj.push != "function")
|
|
64
|
-
return false;
|
|
65
|
-
return true;
|
|
54
|
+
return Array.isArray(obj);
|
|
66
55
|
}
|
|
67
56
|
|
|
68
57
|
// Helper function for trim() to replace text between 2 indices
|
package/test/client.test.js
CHANGED
|
@@ -3511,8 +3511,115 @@ describe('ACC Client', function () {
|
|
|
3511
3511
|
}).catch((ex) => {
|
|
3512
3512
|
expect(ex.message).toMatch('500 - Error 16384: SDK-000013 "Failed to upload file abcd.txt. Malformed data:');
|
|
3513
3513
|
})
|
|
3514
|
+
});
|
|
3514
3515
|
|
|
3515
|
-
|
|
3516
|
+
it("Should support 'publishIfNeeded' action", async () => {
|
|
3517
|
+
// Create a mock client and logon
|
|
3518
|
+
const client = await Mock.makeClient();
|
|
3519
|
+
client._transport.mockReturnValueOnce(Mock.LOGON_RESPONSE);
|
|
3520
|
+
await client.NLWS.xtkSession.logon();
|
|
3521
|
+
|
|
3522
|
+
// Mock the upload protocol
|
|
3523
|
+
// - the upload.jsp (which returns the content of an iframe and JS to eval)
|
|
3524
|
+
// - call to xtk:counter#IncreaseValue (first, retrieve the schema xtk:counter then call the function)
|
|
3525
|
+
// - call to xtk:session#Write
|
|
3526
|
+
// - call to xtk:fileRes#PublishIfNeeded
|
|
3527
|
+
// - call to xtk:fileRes#GetURL
|
|
3528
|
+
|
|
3529
|
+
client._transport.mockReturnValueOnce(Promise.resolve(`Ok
|
|
3530
|
+
<html xmlns="http://www.w3.org/1999/xhtml">
|
|
3531
|
+
<head>
|
|
3532
|
+
<script type="text/javascript">if(window.parent&&window.parent.document.controller&&"function"==typeof window.parent.document.controller.uploadFileCallBack){var aFilesInfo=new Array;aFilesInfo.push({paramName:"file",fileName:"test.txt",newFileName:"d8e8fca2dc0f896fd7cb4cb0031ba249.txt",md5:"d8e8fca2dc0f896fd7cb4cb0031ba249"}),window.parent.document.controller.uploadFileCallBack(aFilesInfo)}</script>
|
|
3533
|
+
</head>
|
|
3534
|
+
<body></body>
|
|
3535
|
+
</html>`)); // upload.jsp
|
|
3536
|
+
|
|
3537
|
+
client._transport.mockReturnValueOnce(Promise.resolve(Mock.GET_XTK_COUNTER_RESPONSE)); // GetEntityIfMoreRecentResponse - counter
|
|
3538
|
+
client._transport.mockReturnValueOnce(Mock.INCREASE_VALUE_RESPONSE); // xtk:counter#IncreaseValue
|
|
3539
|
+
|
|
3540
|
+
client._transport.mockReturnValueOnce(Mock.GET_XTK_SESSION_SCHEMA_RESPONSE); // GetEntityIfMoreRecentResponse - session
|
|
3541
|
+
client._transport.mockReturnValueOnce(Mock.FILE_RES_WRITE_RESPONSE); // xtk:session#Write
|
|
3542
|
+
|
|
3543
|
+
client._transport.mockReturnValueOnce(Promise.resolve(Mock.GET_FILERES_QUERY_SCHEMA_RESPONSE)); // GetEntityIfMoreRecentResponse - fileRes
|
|
3544
|
+
client._transport.mockReturnValueOnce(Promise.resolve(Mock.PUBLISH_IF_NEEDED_RESPONSE)); // xtk:fileRes#PublishIfNeeded
|
|
3545
|
+
|
|
3546
|
+
client._transport.mockReturnValueOnce(Promise.resolve(Mock.GET_URL_RESPONSE)); // xtk:fileRes#GetURL
|
|
3547
|
+
|
|
3548
|
+
// Call upload
|
|
3549
|
+
const result = await client.fileUploader.upload({
|
|
3550
|
+
type: 'text/html',
|
|
3551
|
+
size: 12345
|
|
3552
|
+
}, { action: "publishIfNeeded" });
|
|
3553
|
+
|
|
3554
|
+
expect(result).toMatchObject({
|
|
3555
|
+
md5: "d8e8fca2dc0f896fd7cb4cb0031ba249",
|
|
3556
|
+
name: "test.txt",
|
|
3557
|
+
size: 12345,
|
|
3558
|
+
type: "text/html",
|
|
3559
|
+
url: "http://hello.com"
|
|
3560
|
+
});
|
|
3561
|
+
});
|
|
3562
|
+
|
|
3563
|
+
it("Should support 'none' action", async () => {
|
|
3564
|
+
// Create a mock client and logon
|
|
3565
|
+
const client = await Mock.makeClient();
|
|
3566
|
+
client._transport.mockReturnValueOnce(Mock.LOGON_RESPONSE);
|
|
3567
|
+
await client.NLWS.xtkSession.logon();
|
|
3568
|
+
|
|
3569
|
+
// Mock the upload protocol
|
|
3570
|
+
// With the "none" action, we skip the counter & publication
|
|
3571
|
+
// - the upload.jsp (which returns the content of an iframe and JS to eval)
|
|
3572
|
+
client._transport.mockReturnValueOnce(Promise.resolve(`Ok
|
|
3573
|
+
<html xmlns="http://www.w3.org/1999/xhtml">
|
|
3574
|
+
<head>
|
|
3575
|
+
<script type="text/javascript">if(window.parent&&window.parent.document.controller&&"function"==typeof window.parent.document.controller.uploadFileCallBack){var aFilesInfo=new Array;aFilesInfo.push({paramName:"file",fileName:"test.txt",newFileName:"d8e8fca2dc0f896fd7cb4cb0031ba249.txt",md5:"d8e8fca2dc0f896fd7cb4cb0031ba249"}),window.parent.document.controller.uploadFileCallBack(aFilesInfo)}</script>
|
|
3576
|
+
</head>
|
|
3577
|
+
<body></body>
|
|
3578
|
+
</html>`)); // upload.jsp
|
|
3579
|
+
|
|
3580
|
+
// Call upload
|
|
3581
|
+
const result = await client.fileUploader.upload({
|
|
3582
|
+
type: 'text/html',
|
|
3583
|
+
size: 12345
|
|
3584
|
+
}, { action: "none" });
|
|
3585
|
+
|
|
3586
|
+
expect(result).toMatchObject({
|
|
3587
|
+
md5: "d8e8fca2dc0f896fd7cb4cb0031ba249",
|
|
3588
|
+
name: "test.txt",
|
|
3589
|
+
size: 12345,
|
|
3590
|
+
type: "text/html",
|
|
3591
|
+
});
|
|
3592
|
+
expect(result.url).toBeUndefined();
|
|
3593
|
+
});
|
|
3594
|
+
|
|
3595
|
+
it("Should failed with invalid action", async () => {
|
|
3596
|
+
// Create a mock client and logon
|
|
3597
|
+
const client = await Mock.makeClient();
|
|
3598
|
+
client._transport.mockReturnValueOnce(Mock.LOGON_RESPONSE);
|
|
3599
|
+
await client.NLWS.xtkSession.logon();
|
|
3600
|
+
|
|
3601
|
+
// Mock the upload protocol
|
|
3602
|
+
// With the "none" action, we skip the counter & publication
|
|
3603
|
+
// - the upload.jsp (which returns the content of an iframe and JS to eval)
|
|
3604
|
+
client._transport.mockReturnValueOnce(Promise.resolve(`Ok
|
|
3605
|
+
<html xmlns="http://www.w3.org/1999/xhtml">
|
|
3606
|
+
<head>
|
|
3607
|
+
<script type="text/javascript">if(window.parent&&window.parent.document.controller&&"function"==typeof window.parent.document.controller.uploadFileCallBack){var aFilesInfo=new Array;aFilesInfo.push({paramName:"file",fileName:"test.txt",newFileName:"d8e8fca2dc0f896fd7cb4cb0031ba249.txt",md5:"d8e8fca2dc0f896fd7cb4cb0031ba249"}),window.parent.document.controller.uploadFileCallBack(aFilesInfo)}</script>
|
|
3608
|
+
</head>
|
|
3609
|
+
<body></body>
|
|
3610
|
+
</html>`)); // upload.jsp
|
|
3611
|
+
|
|
3612
|
+
// Call upload
|
|
3613
|
+
await expect(client.fileUploader.upload({
|
|
3614
|
+
type: 'text/html',
|
|
3615
|
+
size: 12345
|
|
3616
|
+
}, { action: "invalid" })).rejects.toMatchObject({
|
|
3617
|
+
errorCode: "SDK-000006",
|
|
3618
|
+
"faultCode": 16384,
|
|
3619
|
+
"faultString": "Bad parameter 'action' with value 'invalid'",
|
|
3620
|
+
"statusCode": 400
|
|
3621
|
+
});
|
|
3622
|
+
});
|
|
3516
3623
|
});
|
|
3517
3624
|
|
|
3518
3625
|
describe("Setting the xtkschema attribute", () => {
|
package/test/domUtil.test.js
CHANGED
|
@@ -157,6 +157,20 @@ describe('DomUtil', function() {
|
|
|
157
157
|
assert.strictEqual(fromJSON({ "a": null }), '<root/>');
|
|
158
158
|
assert.strictEqual(fromJSON({ "a": undefined }), '<root/>');
|
|
159
159
|
});
|
|
160
|
+
|
|
161
|
+
it("Should support attributes named 'length'", () => {
|
|
162
|
+
const json = {
|
|
163
|
+
element: {
|
|
164
|
+
attribute: {
|
|
165
|
+
length: "256",
|
|
166
|
+
name: "id",
|
|
167
|
+
},
|
|
168
|
+
}
|
|
169
|
+
};
|
|
170
|
+
const doc = DomUtil.fromJSON("extension", json);
|
|
171
|
+
const xml = DomUtil.toXMLString(doc);
|
|
172
|
+
expect(xml).toEqual('<extension><element><attribute length="256" name="id"/></element></extension>');
|
|
173
|
+
});
|
|
160
174
|
});
|
|
161
175
|
|
|
162
176
|
describe('fromJSON (default)', function() {
|
|
@@ -0,0 +1,174 @@
|
|
|
1
|
+
/*
|
|
2
|
+
Copyright 2023 Adobe. All rights reserved.
|
|
3
|
+
This file is licensed to you under the Apache License, Version 2.0 (the "License");
|
|
4
|
+
you may not use this file except in compliance with the License. You may obtain a copy
|
|
5
|
+
of the License at http://www.apache.org/licenses/LICENSE-2.0
|
|
6
|
+
|
|
7
|
+
Unless required by applicable law or agreed to in writing, software distributed under
|
|
8
|
+
the License is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR REPRESENTATIONS
|
|
9
|
+
OF ANY KIND, either express or implied. See the License for the specific language
|
|
10
|
+
governing permissions and limitations under the License.
|
|
11
|
+
*/
|
|
12
|
+
|
|
13
|
+
|
|
14
|
+
/**********************************************************************************
|
|
15
|
+
*
|
|
16
|
+
* Unit tests for IMS Bearer Token authentication
|
|
17
|
+
*
|
|
18
|
+
*********************************************************************************/
|
|
19
|
+
const sdk = require('../src/index.js');
|
|
20
|
+
const Mock = require('./mock.js').Mock;
|
|
21
|
+
|
|
22
|
+
describe('IMS Bearer Toekn', function () {
|
|
23
|
+
|
|
24
|
+
async function makeImsClient(options) {
|
|
25
|
+
const connectionParameters = sdk.ConnectionParameters.ofImsBearerToken("http://acc-sdk:8080", "ey...", options);
|
|
26
|
+
const client = await sdk.init(connectionParameters);
|
|
27
|
+
if (!options || !options.transport) // allow tests to explicitely set the transport
|
|
28
|
+
client._transport = jest.fn();
|
|
29
|
+
return client;
|
|
30
|
+
}
|
|
31
|
+
|
|
32
|
+
it('Should logon with IMS Bearer Token', async () => {
|
|
33
|
+
const client = await makeImsClient();
|
|
34
|
+
// No "Logon" API call is made when using IMS Bearer Token
|
|
35
|
+
//client._transport.mockReturnValueOnce(Mock.LOGON_RESPONSE);
|
|
36
|
+
await client.NLWS.xtkSession.logon();
|
|
37
|
+
expect(client.isLogged()).toBe(true);
|
|
38
|
+
});
|
|
39
|
+
|
|
40
|
+
// The logoff API invalidates the session created on the server side and does not invalidate
|
|
41
|
+
// the bearer token. To invalidate the bearer token, IMS should be used
|
|
42
|
+
it('Should logoff', async () => {
|
|
43
|
+
const client = await makeImsClient();
|
|
44
|
+
await client.NLWS.xtkSession.logon();
|
|
45
|
+
|
|
46
|
+
client._transport.mockReturnValueOnce(Mock.LOGOFF_RESPONSE);
|
|
47
|
+
await client.NLWS.xtkSession.logoff();
|
|
48
|
+
expect(client.isLogged()).toBe(false);
|
|
49
|
+
|
|
50
|
+
expect(client._transport).toBeCalledTimes(1);
|
|
51
|
+
const calls = client._transport.mock.calls;
|
|
52
|
+
expect(calls[0][0].headers).toMatchObject({
|
|
53
|
+
"ACC-SDK-Auth": "ImsBearerToken",
|
|
54
|
+
"Authorization": "Bearer ey..."
|
|
55
|
+
});
|
|
56
|
+
expect(calls[0][0].headers["X-Security-Token"]).toBeUndefined();
|
|
57
|
+
expect(calls[0][0].headers["X-Session-Token"]).toBeUndefined();
|
|
58
|
+
});
|
|
59
|
+
|
|
60
|
+
it('Should call API with Bearer Token', async () => {
|
|
61
|
+
const client = await makeImsClient();
|
|
62
|
+
await client.NLWS.xtkSession.logon();
|
|
63
|
+
|
|
64
|
+
// Get Option
|
|
65
|
+
client._transport.mockReturnValueOnce(Mock.GET_XTK_SESSION_SCHEMA_RESPONSE);
|
|
66
|
+
client._transport.mockReturnValueOnce(Mock.GET_DATABASEID_RESPONSE);
|
|
67
|
+
var databaseId = await client.getOption("XtkDatabaseId");
|
|
68
|
+
expect(databaseId).toBe("uFE80000000000000F1FA913DD7CC7C480041161C");
|
|
69
|
+
|
|
70
|
+
// Check that headers were correctly populated for both calls
|
|
71
|
+
expect(client._transport).toBeCalledTimes(2);
|
|
72
|
+
const calls = client._transport.mock.calls;
|
|
73
|
+
expect(calls[0][0].headers).toMatchObject({
|
|
74
|
+
"ACC-SDK-Auth": "ImsBearerToken",
|
|
75
|
+
"ACC-SDK-Call-Internal": "1",
|
|
76
|
+
"Authorization": "Bearer ey..."
|
|
77
|
+
});
|
|
78
|
+
expect(calls[0][0].headers["X-Security-Token"]).toBeUndefined();
|
|
79
|
+
expect(calls[0][0].headers["X-Session-Token"]).toBeUndefined();
|
|
80
|
+
|
|
81
|
+
expect(calls[1][0].headers).toMatchObject({
|
|
82
|
+
"ACC-SDK-Auth": "ImsBearerToken",
|
|
83
|
+
"Authorization": "Bearer ey..."
|
|
84
|
+
});
|
|
85
|
+
expect(calls[1][0].headers["ACC-SDK-Call-Internal"]).toBeUndefined();
|
|
86
|
+
expect(calls[1][0].headers["X-Security-Token"]).toBeUndefined();
|
|
87
|
+
expect(calls[1][0].headers["X-Session-Token"]).toBeUndefined();
|
|
88
|
+
});
|
|
89
|
+
|
|
90
|
+
it("Expired session refresh client callback", async () => {
|
|
91
|
+
|
|
92
|
+
const refreshClient = async (client) => {
|
|
93
|
+
const connectionParameters = sdk.ConnectionParameters.ofImsBearerToken("http://acc-sdk:8080", "ey2...", options);
|
|
94
|
+
client.reinit(connectionParameters);
|
|
95
|
+
await client.NLWS.xtkSession.logon();
|
|
96
|
+
return client;
|
|
97
|
+
};
|
|
98
|
+
|
|
99
|
+
const transport = jest.fn();
|
|
100
|
+
const options = {
|
|
101
|
+
transport: transport,
|
|
102
|
+
refreshClient: refreshClient,
|
|
103
|
+
};
|
|
104
|
+
const connectionParameters = sdk.ConnectionParameters.ofImsBearerToken("http://acc-sdk:8080", "ey1...", options);
|
|
105
|
+
const client = await sdk.init(connectionParameters);
|
|
106
|
+
await client.NLWS.xtkSession.logon();
|
|
107
|
+
|
|
108
|
+
client._transport.mockReturnValueOnce(Promise.resolve(`XSV-350008 Session has expired or is invalid. Please reconnect.`));
|
|
109
|
+
client._transport.mockReturnValueOnce(Mock.GET_XTK_SESSION_SCHEMA_RESPONSE);
|
|
110
|
+
client._transport.mockReturnValueOnce(Mock.GET_DATABASEID_RESPONSE);
|
|
111
|
+
var databaseId = await client.getOption("XtkDatabaseId");
|
|
112
|
+
expect(databaseId).toBe("uFE80000000000000F1FA913DD7CC7C480041161C");
|
|
113
|
+
const lastCall = client._transport.mock.calls[client._transport.mock.calls.length - 1];
|
|
114
|
+
expect(lastCall[0].headers).toMatchObject({
|
|
115
|
+
"ACC-SDK-Auth": "ImsBearerToken",
|
|
116
|
+
"Authorization": "Bearer ey2..."
|
|
117
|
+
});
|
|
118
|
+
expect(lastCall[0].headers["X-Security-Token"]).toBeUndefined();
|
|
119
|
+
expect(lastCall[0].headers["X-Session-Token"]).toBeUndefined();
|
|
120
|
+
});
|
|
121
|
+
|
|
122
|
+
|
|
123
|
+
it("Should call ping API", async () => {
|
|
124
|
+
const client = await makeImsClient();
|
|
125
|
+
await client.NLWS.xtkSession.logon();
|
|
126
|
+
|
|
127
|
+
client._transport.mockReturnValueOnce(Mock.PING);
|
|
128
|
+
const ping = await client.ping();
|
|
129
|
+
expect(ping.status).toBe("OK");
|
|
130
|
+
expect(ping.timestamp).toBe("2021-08-27 15:43:48.862Z");
|
|
131
|
+
|
|
132
|
+
const lastCall = client._transport.mock.calls[client._transport.mock.calls.length - 1];
|
|
133
|
+
expect(lastCall[0].headers).toMatchObject({
|
|
134
|
+
"ACC-SDK-Auth": "ImsBearerToken",
|
|
135
|
+
"Authorization": "Bearer ey..."
|
|
136
|
+
});
|
|
137
|
+
expect(lastCall[0].headers["X-Security-Token"]).toBeUndefined();
|
|
138
|
+
expect(lastCall[0].headers["X-Session-Token"]).toBeUndefined();
|
|
139
|
+
});
|
|
140
|
+
|
|
141
|
+
it("Should call mcPing API", async () => {
|
|
142
|
+
const client = await makeImsClient();
|
|
143
|
+
await client.NLWS.xtkSession.logon();
|
|
144
|
+
|
|
145
|
+
client._transport.mockReturnValueOnce(Mock.MC_PING);
|
|
146
|
+
const ping = await client.mcPing();
|
|
147
|
+
expect(ping.status).toBe("Ok");
|
|
148
|
+
|
|
149
|
+
const lastCall = client._transport.mock.calls[client._transport.mock.calls.length - 1];
|
|
150
|
+
expect(lastCall[0].headers).toMatchObject({
|
|
151
|
+
"ACC-SDK-Auth": "ImsBearerToken",
|
|
152
|
+
"Authorization": "Bearer ey..."
|
|
153
|
+
});
|
|
154
|
+
expect(lastCall[0].headers["X-Security-Token"]).toBeUndefined();
|
|
155
|
+
expect(lastCall[0].headers["X-Session-Token"]).toBeUndefined();
|
|
156
|
+
});
|
|
157
|
+
|
|
158
|
+
it("Should allow to use the application object", async () => {
|
|
159
|
+
const client = await makeImsClient();
|
|
160
|
+
await client.NLWS.xtkSession.logon();
|
|
161
|
+
const application = client.application;
|
|
162
|
+
expect(application).toBeDefined();
|
|
163
|
+
|
|
164
|
+
client._transport.mockReturnValueOnce(Mock.GET_NMS_EXTACCOUNT_SCHEMA_RESPONSE);
|
|
165
|
+
const schema = await application.getSchema("nms:extAccount");
|
|
166
|
+
expect(schema).toBeDefined();
|
|
167
|
+
expect(schema.name).toBe("extAccount");
|
|
168
|
+
|
|
169
|
+
// But the application object does not have any info about packages
|
|
170
|
+
// since we are using a bearer token. Packages are only available
|
|
171
|
+
// when using one of the Logon methods (Logno or BearertokenLogon)
|
|
172
|
+
expect(application.packages).toBeUndefined();
|
|
173
|
+
});
|
|
174
|
+
});
|