@adobe/acc-js-sdk 1.1.32 → 1.1.34

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.
@@ -64,6 +64,8 @@
64
64
  link: messageCenter.html
65
65
  - name: Reports Data API
66
66
  link: reportData.html
67
+ - name: AEM asset upload API
68
+ link: uploadAemAsset.html
67
69
  - name: --
68
70
  - name: Advanced Topics
69
71
  children:
@@ -3,6 +3,20 @@ layout: page
3
3
  title: Change Log
4
4
  ---
5
5
 
6
+ <section class="changelog"><h1>Version 1.1.34</h1>
7
+ <h2>2023/07/25</h2>
8
+ <li>
9
+ Added `uploadAemAsset` method which downloads an asset from AEM and uploads it to Campaign. See <a href="https://opensource.adobe.com/acc-js-sdk/uploadAemAsset.html"></a> for more information.
10
+ </li>
11
+ </section>
12
+
13
+ <section class="changelog"><h1>Version 1.1.33</h1>
14
+ <h2>2023/07/08</h2>
15
+ <li>
16
+ Because of a server-side bug, there could be shemas with multiple copies of an enumeration. Make sure the SDK will not fail loading such schemas (only the first copy of the enumeration will be considered)
17
+ </li>
18
+ </section>
19
+
6
20
  <section class="changelog"><h1>Version 1.1.32</h1>
7
21
  <h2>2023/06/22</h2>
8
22
  <li>
@@ -0,0 +1,45 @@
1
+ ---
2
+ layout: page
3
+ title: AEM asset upload API
4
+ ---
5
+
6
+ <p>Campaign API for downloading & uploading(publishing) AEM cloud asset on campaign publication server. Just like all APIs in the SDK, it's been wrapped into a function and will return a JSON object containing publishedUrl.</p>
7
+ <p class="warning">Note: This API can be used only with assetInfo url of AEM asset. AssetInfo url returns signed download url when called with GET API.
8
+ </p>
9
+ <h1>/nms/aemAssetDownload.jssp</h1>
10
+ <p>This API is authenticated only using ims user token and run directly on the Apache front server.</p>
11
+ <pre class="code">
12
+ const version = sdk.getSDKVersion();
13
+ console.log(`${version.description} version ${version.version}`);
14
+
15
+ <span class="comment">// Logon to a Campaign instance with ImsBearerToken</span>
16
+ const connectionParameters = sdk.ConnectionParameters.ofImsBearerToken("http://acc-sdk:8080", "ey...", options);
17
+ console.log(connectionParameters);
18
+
19
+ const client = await sdk.init(connectionParameters);
20
+ await client.logon();
21
+
22
+ const url = "https://abcd.adobexyzcloud.domain.com/asset/xyz.png";
23
+ const response = await client.fileUploader.uploadAemAsset(url);
24
+ console.log(response);
25
+ </pre>
26
+
27
+ <p>will return in this format</p>
28
+ <pre class="code">
29
+ {
30
+ "publishedURL": "http://trk-my-instance.my.domain.com/res/trk-inst/12f6710969d74ad965a333d31cf8c06d.jpeg"
31
+ }
32
+ </pre>
33
+
34
+ <p class="warning">Note: This API can only be authenticated using ImsBearerToken because the same Ims user token
35
+ is used to authenticate AEM asset GET call.
36
+ </p>
37
+ <pre class="code">
38
+ const connectionParameters = sdk.ConnectionParameters.ofImsBearerToken("http://acc-sdk:8080", "ey...", options);
39
+ console.log(connectionParameters);
40
+ </pre>
41
+
42
+ <p class="info">The API returns error with error code whenever it fails.<br>
43
+ The sdk error is "SDK-000017 Failed to upload AEM asset". It will also include specific reason for failure
44
+ and error code.
45
+ </p>
package/package-lock.json CHANGED
@@ -1,12 +1,12 @@
1
1
  {
2
2
  "name": "@adobe/acc-js-sdk",
3
- "version": "1.1.32",
3
+ "version": "1.1.34",
4
4
  "lockfileVersion": 2,
5
5
  "requires": true,
6
6
  "packages": {
7
7
  "": {
8
8
  "name": "@adobe/acc-js-sdk",
9
- "version": "1.1.32",
9
+ "version": "1.1.34",
10
10
  "license": "ISC",
11
11
  "dependencies": {
12
12
  "axios": "^1.2.1",
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@adobe/acc-js-sdk",
3
- "version": "1.1.32",
3
+ "version": "1.1.34",
4
4
  "description": "ACC Javascript SDK",
5
5
  "main": "src/index.js",
6
6
  "homepage": "https://github.com/adobe/acc-js-sdk#readme",
@@ -1224,7 +1224,9 @@ class XtkSchema extends XtkSchemaNode {
1224
1224
  this.enumerations = new ArrayMap();
1225
1225
  for (var child of EntityAccessor.getChildElements(xml, "enumeration")) {
1226
1226
  const e = new XtkEnumeration(this.id, child);
1227
- this.enumerations._push(e.shortName, e);
1227
+ if (this.enumerations.get(e.shortName) === undefined) {
1228
+ this.enumerations._push(e.shortName, e);
1229
+ }
1228
1230
  }
1229
1231
  }
1230
1232
 
package/src/campaign.js CHANGED
@@ -42,6 +42,7 @@ const { Util } = require("./util.js");
42
42
  static REPORT_FETCH_FAILED(name, details) { return new CampaignException(undefined, 500, 16384, `SDK-000014 Failed to fetch report ${name}`, details); }
43
43
  static FEATURE_NOT_SUPPORTED(name) { return new CampaignException(undefined, 500, 16384, `SDK-000015 ${name} feature is not supported by the ACC instance`); }
44
44
  static REQUEST_ABORTED( ) { return new CampaignException(undefined, 500, -53, `SDK-000016 Request was aborted by the client`); }
45
+ static AEM_ASSET_UPLOAD_FAILED(details, statusCode=500) { return new CampaignException(undefined, statusCode, 16384, `SDK-000017 Failed to upload AEM asset`, details); }
45
46
 
46
47
 
47
48
  /**
@@ -226,13 +227,14 @@ function makeCampaignException(call, err) {
226
227
 
227
228
  if (err.statusCode && ctor && ctor.name == "HttpError") {
228
229
  var faultString = err.statusText;
229
- var details = err.data;
230
+ var details = typeof err.data == 'object' ? JSON.stringify(err.data) : err.data;
230
231
  if (!faultString) {
231
- faultString = err.data;
232
+ faultString = typeof err.data == 'object' ? JSON.stringify(err.data) : err.data;
232
233
  details = undefined;
233
234
  }
235
+
234
236
  // Session expiration case must return a 401
235
- if (err.data && err.data.indexOf(`XSV-350008`) != -1)
237
+ if (err.data && typeof err.data == 'string' && err.data.indexOf(`XSV-350008`) != -1)
236
238
  return CampaignException.SESSION_EXPIRED();
237
239
  return new CampaignException(call, err.statusCode, "", faultString, details, err);
238
240
  }
package/src/client.js CHANGED
@@ -639,6 +639,41 @@ const fileUploader = (client) => {
639
639
  reject(CampaignException.FILE_UPLOAD_FAILED(file.name, ex));
640
640
  }
641
641
  });
642
+ },
643
+
644
+ /**
645
+ * Exposed method to call aemAssetDownload.jssp which will
646
+ * download the asset from AEM and upload it to Campaign.
647
+ */
648
+ uploadAemAsset: async (assetDownloadUrl) => {
649
+ const url = `${client._connectionParameters._endpoint}/nms/aemAssetDownload.jssp`;
650
+ const headers = client._getAuthHeaders(false);
651
+ headers['Content-Type'] = 'application/json';
652
+
653
+ try {
654
+ // We need to pass the Authorization header to AEM to download the asset from AEM
655
+ // as well as authenticating campaign server.
656
+ // A user token having access to campaign as well as AEM is required
657
+ if(headers['Authorization'] === undefined || headers['Authorization'] === '' || headers['Authorization'] === 'null') {
658
+ throw 'Bearer token is missing';
659
+ }
660
+
661
+ const response = await client._makeHttpCall({
662
+ url: url,
663
+ method: 'POST',
664
+ data: {assetDownloadUrl: assetDownloadUrl},
665
+ headers: headers
666
+ });
667
+ if(response.publishedURL)
668
+ return response;
669
+ else
670
+ throw 'Publishing failed';
671
+ } catch (ex) {
672
+ if(ex instanceof CampaignException)
673
+ throw CampaignException.AEM_ASSET_UPLOAD_FAILED(ex.faultString, ex.statusCode);
674
+ else
675
+ throw CampaignException.AEM_ASSET_UPLOAD_FAILED(ex, ex.statusCode);
676
+ }
642
677
  }
643
678
  };
644
679
  };
@@ -2002,7 +2037,7 @@ class Client {
2002
2037
  if (this._traceAPICalls)
2003
2038
  console.log("HTTP//failure", err);
2004
2039
  this._notifyObservers((observer) => observer.onHTTPCallFailure && observer.onHTTPCallFailure(request, err) );
2005
- const ex = makeCampaignException({ request:request, reqponse:err.response }, err);
2040
+ const ex = makeCampaignException({ request:request, response:err.response }, err);
2006
2041
  this._trackEvent('HTTP//failure', event, { }, ex);
2007
2042
  throw ex;
2008
2043
  }
@@ -345,6 +345,19 @@ describe('Application', () => {
345
345
  expect(enumerations[1].label).toBe("Status code");
346
346
  });
347
347
 
348
+ it("Should support duplicate enumerations", () => {
349
+ var xml = DomUtil.parse(`<schema namespace='nms' name='recipient'>
350
+ <enumeration name="duplicated" basetype="byte"/>
351
+ <enumeration name="duplicated" basetype="byte"/>
352
+ <element name='recipient' label='Recipients'></element>
353
+ </schema>`);
354
+ var schema = newSchema(xml);
355
+ var enumerations = schema.enumerations;
356
+ expect(enumerations.duplicated.dummy).toBeFalsy();
357
+ expect(enumerations[0].label).toBe("Duplicated");
358
+ expect(enumerations[1]).toBeUndefined();
359
+ });
360
+
348
361
  it("Should test images", () => {
349
362
  var xml = DomUtil.parse(`<schema namespace='nms' name='recipient'>
350
363
  <enumeration name="gender" basetype="byte">
@@ -26,6 +26,7 @@ const { Cipher } = require('../src/crypto.js');
26
26
  const { EntityAccessor } = require('../src/entityAccessor.js');
27
27
  const { JSDOM } = require('jsdom');
28
28
  const dom = new JSDOM();
29
+ const { CampaignException } = require('../src/campaign.js');
29
30
 
30
31
  describe('ACC Client', function () {
31
32
 
@@ -1746,6 +1747,83 @@ describe('ACC Client', function () {
1746
1747
  });
1747
1748
  });
1748
1749
 
1750
+ // write unit test for client.fileUploader.uploadAemAsset method
1751
+ describe("Tests for client.fileUploader.uploadAemAsset method", () => {
1752
+ // Case 1: uploadAemAsset method should return a valid response
1753
+ it("Should return correct response", async () => {
1754
+ const client = await Mock.makeClient();
1755
+ client._transport.mockReturnValueOnce(Mock.LOGON_RESPONSE);
1756
+ await client.NLWS.xtkSession.logon();
1757
+
1758
+ const mockResponse = {
1759
+ "publishedURL" : "http://trk-inst-xyz.campaign.adobe.com/res/trk-inst/409afb8798180a36591456e152b6c406.jpeg"
1760
+ };
1761
+ client._bearerToken = 'Bearer 1234567890';
1762
+ client._transport.mockReturnValueOnce(mockResponse);
1763
+ const response = await client.fileUploader.uploadAemAsset("https://author-p74953-e183988-cmstg.adobeaemcloud.com/adobe/repository/content/dam/projects/children-kids-group-eating-ice-cream-funny-party-72701973%20%281%29%20%2812%29%20%282%29%20%283%29.jpg;api=block_download");
1764
+ expect(response).toBe(mockResponse);
1765
+
1766
+ client._transport.mockReturnValueOnce(Mock.LOGOFF_RESPONSE);
1767
+ await client.NLWS.xtkSession.logoff();
1768
+ });
1769
+
1770
+ // Case 2: Bearertoken is not provided, but the client is already authenticated with session token
1771
+ it("Should throw error for missing authentication token", async () => {
1772
+ const client = await Mock.makeClient();
1773
+ client._transport.mockReturnValueOnce(Mock.LOGON_RESPONSE);
1774
+ await client.NLWS.xtkSession.logon();
1775
+
1776
+ await (client.fileUploader.uploadAemAsset("https://author-p74953-e183988-cmstg.adobeaemcloud.com/adobe/repository/content/dam/projects/children-kids-group-eating-ice-cream-funny-party-72701973%20%281%29%20%2812%29%20%282%29%20%283%29.jpg;api=block_download"))
1777
+ .catch( e => { expect(e).toMatchObject(CampaignException.AEM_ASSET_UPLOAD_FAILED('Bearer token is missing'))});
1778
+
1779
+ client._transport.mockReturnValueOnce(Mock.LOGOFF_RESPONSE);
1780
+ await client.NLWS.xtkSession.logoff();
1781
+ });
1782
+
1783
+ // Case 3: 200 response but publishedURL is not returned
1784
+ // It shouldn't occur as API also checks non-emptiness of publishedURL before returning the response.
1785
+ it("Should throw error for missing publishedURL", async () => {
1786
+ const client = await Mock.makeClient();
1787
+ client._transport.mockReturnValueOnce(Mock.LOGON_RESPONSE);
1788
+ await client.NLWS.xtkSession.logon();
1789
+
1790
+ const mockResponse = {};
1791
+ client._transport.mockReturnValueOnce(mockResponse);
1792
+ client._bearerToken = 'Bearer 1234567890';
1793
+
1794
+ await (client.fileUploader.uploadAemAsset("https://author-p74953-e183988-cmstg.adobeaemcloud.com/adobe/repository/content/dam/projects/children-kids-group-eating-ice-cream-funny-party-72701973%20%281%29%20%2812%29%20%282%29%20%283%29.jpg;api=block_download"))
1795
+ .catch( e => { console.log(e); expect(e).toMatchObject(CampaignException.AEM_ASSET_UPLOAD_FAILED('Publishing failed'))});
1796
+
1797
+ client._transport.mockReturnValueOnce(Mock.LOGOFF_RESPONSE);
1798
+ await client.NLWS.xtkSession.logoff();
1799
+ });
1800
+
1801
+ // Case 4: AEM Asset upload failed (reason maybe aem not reachable, assetlink not reachable, etc)
1802
+ it("Should throw error when AEM Asset upload failed", async () => {
1803
+ const client = await Mock.makeClient();
1804
+ client._transport.mockReturnValueOnce(Mock.LOGON_RESPONSE);
1805
+ await client.NLWS.xtkSession.logon();
1806
+
1807
+ //const mockResponse = {};
1808
+ client._transport.mockImplementation(() => {
1809
+ var ex = CampaignException.AEM_ASSET_UPLOAD_FAILED('The requested content does not exist', 400);
1810
+ ex.faultString = 'The requested content does not exist';
1811
+ ex.detail = 'Failed to upload AEM asset';
1812
+ throw ex;
1813
+ });
1814
+ client._bearerToken = 'Bearer 1234567890';
1815
+
1816
+ var ex = CampaignException.AEM_ASSET_UPLOAD_FAILED('The requested content does not exist', 400);
1817
+ await (client.fileUploader.uploadAemAsset("https://author-p74953-e183988-cmstg.adobeaemcloud.com/adobe/repository/content/dam/projects/children-kids-group-eating-ice-cream-funny-party-72701973%20%281%29%20%2812%29%20%282%29%20%283%29.jpg;api=block_download"))
1818
+ .catch( e => { console.log(e); expect(e).toMatchObject(ex)});
1819
+
1820
+ client._transport.mockReturnValueOnce(Mock.LOGOFF_RESPONSE);
1821
+ await client.NLWS.xtkSession.logoff();
1822
+ });
1823
+
1824
+ });
1825
+
1826
+
1749
1827
  describe("Observers", () => {
1750
1828
 
1751
1829
  it("Should observe SOAP api Call (getOption)", async () => {