@commercetools-backend/express 22.2.1 → 22.3.1

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.
@@ -46,14 +46,16 @@ const CLOUD_IDENTIFIERS = {
46
46
  GCP_EU: 'gcp-eu',
47
47
  GCP_US: 'gcp-us',
48
48
  AWS_FRA: 'aws-fra',
49
- AWS_OHIO: 'aws-ohio'
49
+ AWS_OHIO: 'aws-ohio',
50
+ AWS_CN: 'aws-cn'
50
51
  };
51
52
  const MC_API_URLS = {
52
53
  GCP_AU: 'https://mc-api.australia-southeast1.gcp.commercetools.com',
53
54
  GCP_EU: 'https://mc-api.europe-west1.gcp.commercetools.com',
54
55
  GCP_US: 'https://mc-api.us-central1.gcp.commercetools.com',
55
56
  AWS_FRA: 'https://mc-api.eu-central-1.aws.commercetools.com',
56
- AWS_OHIO: 'https://mc-api.us-east-2.aws.commercetools.com'
57
+ AWS_OHIO: 'https://mc-api.us-east-2.aws.commercetools.com',
58
+ AWS_CN: 'https://mc-api.cn-northwest-1.aws.commercetools.cn'
57
59
  };
58
60
  const MC_API_PROXY_HEADERS = {
59
61
  FORWARD_TO_VERSION: 'x-mc-api-forward-to-version',
@@ -62,42 +64,32 @@ const MC_API_PROXY_HEADERS = {
62
64
 
63
65
  const getHeaderByCaseInsensitiveKey = (headers, headerKey) => {
64
66
  var _context;
65
-
66
67
  const matchingHeader = _findInstanceProperty__default["default"](_context = _Object$entries__default["default"](headers)).call(_context, _ref => {
67
68
  let _ref2 = _slicedToArray(_ref, 1),
68
- key = _ref2[0];
69
-
69
+ key = _ref2[0];
70
70
  return headerKey.toLowerCase() === key.toLowerCase();
71
71
  });
72
-
73
72
  if (matchingHeader && matchingHeader.length > 0) {
74
73
  const _matchingHeader = _slicedToArray(matchingHeader, 2),
75
- headerValue = _matchingHeader[1];
76
-
74
+ headerValue = _matchingHeader[1];
77
75
  return _Array$isArray__default["default"](headerValue) ? headerValue[0] : headerValue;
78
76
  }
79
-
80
77
  return undefined;
81
78
  };
82
-
83
79
  const getFirstHeaderValueOrThrow = (headers, headerKey, errorMessage) => {
84
80
  const headerValue = getHeaderByCaseInsensitiveKey(headers, headerKey);
85
-
86
81
  if (!headerValue) {
87
82
  throw new Error(errorMessage);
88
83
  }
89
-
90
84
  return headerValue;
91
85
  };
92
86
 
93
87
  function ownKeys(object, enumerableOnly) { var keys = _Object$keys__default["default"](object); if (_Object$getOwnPropertySymbols__default["default"]) { var symbols = _Object$getOwnPropertySymbols__default["default"](object); enumerableOnly && (symbols = _filterInstanceProperty__default["default"](symbols).call(symbols, function (sym) { return _Object$getOwnPropertyDescriptor__default["default"](object, sym).enumerable; })), keys.push.apply(keys, symbols); } return keys; }
94
-
95
88
  function _objectSpread(target) { for (var i = 1; i < arguments.length; i++) { var _context3, _context4; var source = null != arguments[i] ? arguments[i] : {}; i % 2 ? _forEachInstanceProperty__default["default"](_context3 = ownKeys(Object(source), !0)).call(_context3, function (key) { _defineProperty(target, key, source[key]); }) : _Object$getOwnPropertyDescriptors__default["default"] ? _Object$defineProperties__default["default"](target, _Object$getOwnPropertyDescriptors__default["default"](source)) : _forEachInstanceProperty__default["default"](_context4 = ownKeys(Object(source))).call(_context4, function (key) { _Object$defineProperty__default["default"](target, key, _Object$getOwnPropertyDescriptor__default["default"](source, key)); }); } return target; }
96
- const decodedTokenKey = 'decoded_token'; // Assign a session object to the request object.
97
-
89
+ const decodedTokenKey = 'decoded_token';
90
+ // Assign a session object to the request object.
98
91
  const writeSessionContext = request => {
99
92
  const decodedToken = request[decodedTokenKey];
100
-
101
93
  if (decodedToken) {
102
94
  const publicClaimForProjectKey = "".concat(decodedToken.iss, "/claims/project_key");
103
95
  const publicClaimForUserPermissionsKey = "".concat(decodedToken.iss, "/claims/user_permissions");
@@ -106,143 +98,120 @@ const writeSessionContext = request => {
106
98
  projectKey: decodedToken[publicClaimForProjectKey]
107
99
  };
108
100
  const userPermissions = decodedToken[publicClaimForUserPermissionsKey];
109
-
110
101
  if (Boolean(userPermissions === null || userPermissions === void 0 ? void 0 : userPermissions.length)) {
111
102
  request.session.userPermissions = userPermissions;
112
103
  }
113
- } // Remove the field used by the JWT middleware.
114
-
104
+ }
115
105
 
106
+ // Remove the field used by the JWT middleware.
116
107
  delete request.decoded_token;
117
- }; // Given a cloud identifier, try to map it to one of the supported
108
+ };
109
+
110
+ // Given a cloud identifier, try to map it to one of the supported
118
111
  // environments and return the MC API URL for that environment.
119
112
  // The URL points to the new hostnames.
120
113
  // https://docs.commercetools.com/custom-applications/concepts/merchant-center-api#hostnames
121
-
122
-
123
114
  const mapCloudIdentifierToIssuer = issuer => {
124
115
  switch (issuer) {
125
116
  case CLOUD_IDENTIFIERS.GCP_AU:
126
117
  return MC_API_URLS.GCP_AU;
127
-
128
118
  case CLOUD_IDENTIFIERS.GCP_EU:
129
119
  return MC_API_URLS.GCP_EU;
130
-
131
120
  case CLOUD_IDENTIFIERS.GCP_US:
132
121
  return MC_API_URLS.GCP_US;
133
-
134
122
  case CLOUD_IDENTIFIERS.AWS_FRA:
135
123
  return MC_API_URLS.AWS_FRA;
136
-
137
124
  case CLOUD_IDENTIFIERS.AWS_OHIO:
138
125
  return MC_API_URLS.AWS_OHIO;
139
-
126
+ case CLOUD_IDENTIFIERS.AWS_CN:
127
+ return MC_API_URLS.AWS_CN;
140
128
  default:
141
129
  return undefined;
142
130
  }
143
- }; // Given a cloud identifier, try to map it to a legacy hostname.
131
+ };
132
+ // Given a cloud identifier, try to map it to a legacy hostname.
144
133
  // This is for backwards compatibility.
145
-
146
-
147
134
  const mapToLegacyIssuer = cloudIdentifier => {
148
135
  switch (cloudIdentifier) {
149
136
  case CLOUD_IDENTIFIERS.GCP_EU:
150
137
  return 'https://mc-api.commercetools.com';
151
-
152
138
  case CLOUD_IDENTIFIERS.GCP_US:
153
139
  return 'https://mc-api.commercetools.co';
154
-
155
140
  default:
156
141
  return undefined;
157
142
  }
158
- }; // Verifies that the issuer is a valid URL.
159
-
160
-
143
+ };
144
+ // Verifies that the issuer is a valid URL.
161
145
  const throwIfIssuerIsNotAValidUrl = issuer => {
162
146
  try {
163
147
  new _URL__default["default"](issuer);
164
148
  } catch (error) {
165
149
  throw new Error("Invalid issuer URL \"".concat(issuer, "\". Expected a valid URL to the Merchant Center API Gateway, or a cloud identifier to one of the available cloud regions. See https://docs.commercetools.com/custom-applications/concepts/merchant-center-api#hostnames."));
166
150
  }
167
- }; // Validates required option values.
168
-
169
-
151
+ };
152
+ // Validates required option values.
170
153
  const validateRequiredValues = options => {
171
154
  if (!options.audience) {
172
155
  throw new Error("Missing required option \"audience\"");
173
156
  }
174
-
175
157
  if (!options.issuer) {
176
158
  throw new Error("Missing required option \"issuer\"");
177
159
  }
178
- }; // Attempt to parse the given issuer. If the value is a cloud identifier, it will
160
+ };
161
+ // Attempt to parse the given issuer. If the value is a cloud identifier, it will
179
162
  // be mapped to one of the supported values. If not, we assume the value is a valid URL.
180
-
181
-
182
163
  const getConfiguredDefaultIssuer = options => {
183
164
  const issuer = mapCloudIdentifierToIssuer(options.issuer);
184
-
185
165
  if (!issuer) {
186
166
  throwIfIssuerIsNotAValidUrl(options.issuer);
187
167
  return options.issuer;
188
168
  }
189
-
190
169
  return issuer;
191
- }; // Construct the audience from the given option + the request path.
170
+ };
171
+
172
+ // Construct the audience from the given option + the request path.
192
173
  // If the request path is `/`, do not append it to the audience, otherwise
193
174
  // the token validation might fail because of mismatching audiences.
194
-
195
-
196
175
  const getConfiguredAudience = (options, requestPath) => {
197
176
  var _context;
198
-
199
177
  // remove the trailing slash
200
178
  const url = new _URL__default["default"](_concatInstanceProperty__default["default"](_context = "".concat(options.audience.replace(/\/?$/, ''))).call(_context, requestPath));
201
-
202
179
  switch (options.audiencePolicy) {
203
180
  case 'forward-url-origin':
204
181
  return url.origin;
205
-
206
182
  default:
207
183
  {
208
184
  var _context2;
209
-
210
185
  if (requestPath === '/') {
211
186
  return url.origin;
212
187
  }
213
-
214
188
  return _concatInstanceProperty__default["default"](_context2 = "".concat(url.origin)).call(_context2, url.pathname);
215
189
  }
216
190
  }
217
191
  };
218
-
219
192
  function createSessionAuthVerifier(options) {
220
193
  validateRequiredValues(options);
221
- const configuredDefaultIssuer = getConfiguredDefaultIssuer(options); // Returns an async HTTP handler.
194
+ const configuredDefaultIssuer = getConfiguredDefaultIssuer(options);
222
195
 
196
+ // Returns an async HTTP handler.
223
197
  return async (request, response) => {
224
198
  var _mapCloudIdentifierTo, _request$originalUrl;
225
-
226
199
  // Get the cloud identifier header, forwarded by the `/proxy/forward-to` endpoint.
227
200
  const cloudIdentifierHeader = getFirstHeaderValueOrThrow(request.headers, MC_API_PROXY_HEADERS.CLOUD_IDENTIFIER, "Missing \"X-MC-API-Cloud-Identifier\" header.");
228
- let issuer = options.inferIssuer && cloudIdentifierHeader ? (_mapCloudIdentifierTo = mapCloudIdentifierToIssuer(cloudIdentifierHeader)) !== null && _mapCloudIdentifierTo !== void 0 ? _mapCloudIdentifierTo : configuredDefaultIssuer : configuredDefaultIssuer; // Get the `Accept-version` header, forwarded by the `/proxy/forward-to` endpoint.
229
- // The version should be sent by the client making the request, to use the features of v2.
201
+ let issuer = options.inferIssuer && cloudIdentifierHeader ? (_mapCloudIdentifierTo = mapCloudIdentifierToIssuer(cloudIdentifierHeader)) !== null && _mapCloudIdentifierTo !== void 0 ? _mapCloudIdentifierTo : configuredDefaultIssuer : configuredDefaultIssuer;
230
202
 
203
+ // Get the `Accept-version` header, forwarded by the `/proxy/forward-to` endpoint.
204
+ // The version should be sent by the client making the request, to use the features of v2.
231
205
  const proxyForwardVersion = getFirstHeaderValueOrThrow(request.headers, MC_API_PROXY_HEADERS.FORWARD_TO_VERSION, "Missing \"X-MC-API-Forward-To-Version\" header.");
232
-
233
206
  if (proxyForwardVersion === 'v1') {
234
207
  var _mapToLegacyIssuer;
235
-
236
208
  // Fall back to legacy issuer domains
237
209
  issuer = (_mapToLegacyIssuer = mapToLegacyIssuer(cloudIdentifierHeader)) !== null && _mapToLegacyIssuer !== void 0 ? _mapToLegacyIssuer : issuer;
238
210
  }
239
-
240
211
  const requestUrlPath = options.getRequestUrl ? options.getRequestUrl(request) : (_request$originalUrl = request.originalUrl) !== null && _request$originalUrl !== void 0 ? _request$originalUrl : request.url;
241
-
242
212
  if (!requestUrlPath || !_startsWithInstanceProperty__default["default"](requestUrlPath).call(requestUrlPath, '/')) {
243
213
  throw new Error("Invalid request URI path \"".concat(requestUrlPath, "\". Please make sure that the \"request\" object has either a property \"originalUrl\" or \"url\". If not, you should implement the \"getRequestUrl\" function and make sure to return a valid URI path value starting with \"/\". More info at https://docs.commercetools.com/custom-applications/concepts/integrate-with-your-own-api#validating-the-json-web-token"));
244
214
  }
245
-
246
215
  const audience = getConfiguredAudience(options, requestUrlPath);
247
216
  return new _Promise__default["default"]((resolve, reject) => {
248
217
  expressJwt.expressjwt({
@@ -261,8 +230,8 @@ function createSessionAuthVerifier(options) {
261
230
  // Validate the audience and the issuer.
262
231
  audience,
263
232
  issuer,
264
- algorithms: ['RS256'] // @ts-ignore: the middleware expects an Express.js Request/Response objects
265
-
233
+ algorithms: ['RS256']
234
+ // @ts-ignore: the middleware expects an Express.js Request/Response objects
266
235
  })(request, response !== null && response !== void 0 ? response : {}, error => {
267
236
  if (error) {
268
237
  reject(error);
@@ -46,14 +46,16 @@ const CLOUD_IDENTIFIERS = {
46
46
  GCP_EU: 'gcp-eu',
47
47
  GCP_US: 'gcp-us',
48
48
  AWS_FRA: 'aws-fra',
49
- AWS_OHIO: 'aws-ohio'
49
+ AWS_OHIO: 'aws-ohio',
50
+ AWS_CN: 'aws-cn'
50
51
  };
51
52
  const MC_API_URLS = {
52
53
  GCP_AU: 'https://mc-api.australia-southeast1.gcp.commercetools.com',
53
54
  GCP_EU: 'https://mc-api.europe-west1.gcp.commercetools.com',
54
55
  GCP_US: 'https://mc-api.us-central1.gcp.commercetools.com',
55
56
  AWS_FRA: 'https://mc-api.eu-central-1.aws.commercetools.com',
56
- AWS_OHIO: 'https://mc-api.us-east-2.aws.commercetools.com'
57
+ AWS_OHIO: 'https://mc-api.us-east-2.aws.commercetools.com',
58
+ AWS_CN: 'https://mc-api.cn-northwest-1.aws.commercetools.cn'
57
59
  };
58
60
  const MC_API_PROXY_HEADERS = {
59
61
  FORWARD_TO_VERSION: 'x-mc-api-forward-to-version',
@@ -62,42 +64,32 @@ const MC_API_PROXY_HEADERS = {
62
64
 
63
65
  const getHeaderByCaseInsensitiveKey = (headers, headerKey) => {
64
66
  var _context;
65
-
66
67
  const matchingHeader = _findInstanceProperty__default["default"](_context = _Object$entries__default["default"](headers)).call(_context, _ref => {
67
68
  let _ref2 = _slicedToArray(_ref, 1),
68
- key = _ref2[0];
69
-
69
+ key = _ref2[0];
70
70
  return headerKey.toLowerCase() === key.toLowerCase();
71
71
  });
72
-
73
72
  if (matchingHeader && matchingHeader.length > 0) {
74
73
  const _matchingHeader = _slicedToArray(matchingHeader, 2),
75
- headerValue = _matchingHeader[1];
76
-
74
+ headerValue = _matchingHeader[1];
77
75
  return _Array$isArray__default["default"](headerValue) ? headerValue[0] : headerValue;
78
76
  }
79
-
80
77
  return undefined;
81
78
  };
82
-
83
79
  const getFirstHeaderValueOrThrow = (headers, headerKey, errorMessage) => {
84
80
  const headerValue = getHeaderByCaseInsensitiveKey(headers, headerKey);
85
-
86
81
  if (!headerValue) {
87
82
  throw new Error(errorMessage);
88
83
  }
89
-
90
84
  return headerValue;
91
85
  };
92
86
 
93
87
  function ownKeys(object, enumerableOnly) { var keys = _Object$keys__default["default"](object); if (_Object$getOwnPropertySymbols__default["default"]) { var symbols = _Object$getOwnPropertySymbols__default["default"](object); enumerableOnly && (symbols = _filterInstanceProperty__default["default"](symbols).call(symbols, function (sym) { return _Object$getOwnPropertyDescriptor__default["default"](object, sym).enumerable; })), keys.push.apply(keys, symbols); } return keys; }
94
-
95
88
  function _objectSpread(target) { for (var i = 1; i < arguments.length; i++) { var _context3, _context4; var source = null != arguments[i] ? arguments[i] : {}; i % 2 ? _forEachInstanceProperty__default["default"](_context3 = ownKeys(Object(source), !0)).call(_context3, function (key) { _defineProperty(target, key, source[key]); }) : _Object$getOwnPropertyDescriptors__default["default"] ? _Object$defineProperties__default["default"](target, _Object$getOwnPropertyDescriptors__default["default"](source)) : _forEachInstanceProperty__default["default"](_context4 = ownKeys(Object(source))).call(_context4, function (key) { _Object$defineProperty__default["default"](target, key, _Object$getOwnPropertyDescriptor__default["default"](source, key)); }); } return target; }
96
- const decodedTokenKey = 'decoded_token'; // Assign a session object to the request object.
97
-
89
+ const decodedTokenKey = 'decoded_token';
90
+ // Assign a session object to the request object.
98
91
  const writeSessionContext = request => {
99
92
  const decodedToken = request[decodedTokenKey];
100
-
101
93
  if (decodedToken) {
102
94
  const publicClaimForProjectKey = "".concat(decodedToken.iss, "/claims/project_key");
103
95
  const publicClaimForUserPermissionsKey = "".concat(decodedToken.iss, "/claims/user_permissions");
@@ -106,143 +98,120 @@ const writeSessionContext = request => {
106
98
  projectKey: decodedToken[publicClaimForProjectKey]
107
99
  };
108
100
  const userPermissions = decodedToken[publicClaimForUserPermissionsKey];
109
-
110
101
  if (Boolean(userPermissions === null || userPermissions === void 0 ? void 0 : userPermissions.length)) {
111
102
  request.session.userPermissions = userPermissions;
112
103
  }
113
- } // Remove the field used by the JWT middleware.
114
-
104
+ }
115
105
 
106
+ // Remove the field used by the JWT middleware.
116
107
  delete request.decoded_token;
117
- }; // Given a cloud identifier, try to map it to one of the supported
108
+ };
109
+
110
+ // Given a cloud identifier, try to map it to one of the supported
118
111
  // environments and return the MC API URL for that environment.
119
112
  // The URL points to the new hostnames.
120
113
  // https://docs.commercetools.com/custom-applications/concepts/merchant-center-api#hostnames
121
-
122
-
123
114
  const mapCloudIdentifierToIssuer = issuer => {
124
115
  switch (issuer) {
125
116
  case CLOUD_IDENTIFIERS.GCP_AU:
126
117
  return MC_API_URLS.GCP_AU;
127
-
128
118
  case CLOUD_IDENTIFIERS.GCP_EU:
129
119
  return MC_API_URLS.GCP_EU;
130
-
131
120
  case CLOUD_IDENTIFIERS.GCP_US:
132
121
  return MC_API_URLS.GCP_US;
133
-
134
122
  case CLOUD_IDENTIFIERS.AWS_FRA:
135
123
  return MC_API_URLS.AWS_FRA;
136
-
137
124
  case CLOUD_IDENTIFIERS.AWS_OHIO:
138
125
  return MC_API_URLS.AWS_OHIO;
139
-
126
+ case CLOUD_IDENTIFIERS.AWS_CN:
127
+ return MC_API_URLS.AWS_CN;
140
128
  default:
141
129
  return undefined;
142
130
  }
143
- }; // Given a cloud identifier, try to map it to a legacy hostname.
131
+ };
132
+ // Given a cloud identifier, try to map it to a legacy hostname.
144
133
  // This is for backwards compatibility.
145
-
146
-
147
134
  const mapToLegacyIssuer = cloudIdentifier => {
148
135
  switch (cloudIdentifier) {
149
136
  case CLOUD_IDENTIFIERS.GCP_EU:
150
137
  return 'https://mc-api.commercetools.com';
151
-
152
138
  case CLOUD_IDENTIFIERS.GCP_US:
153
139
  return 'https://mc-api.commercetools.co';
154
-
155
140
  default:
156
141
  return undefined;
157
142
  }
158
- }; // Verifies that the issuer is a valid URL.
159
-
160
-
143
+ };
144
+ // Verifies that the issuer is a valid URL.
161
145
  const throwIfIssuerIsNotAValidUrl = issuer => {
162
146
  try {
163
147
  new _URL__default["default"](issuer);
164
148
  } catch (error) {
165
149
  throw new Error("Invalid issuer URL \"".concat(issuer, "\". Expected a valid URL to the Merchant Center API Gateway, or a cloud identifier to one of the available cloud regions. See https://docs.commercetools.com/custom-applications/concepts/merchant-center-api#hostnames."));
166
150
  }
167
- }; // Validates required option values.
168
-
169
-
151
+ };
152
+ // Validates required option values.
170
153
  const validateRequiredValues = options => {
171
154
  if (!options.audience) {
172
155
  throw new Error("Missing required option \"audience\"");
173
156
  }
174
-
175
157
  if (!options.issuer) {
176
158
  throw new Error("Missing required option \"issuer\"");
177
159
  }
178
- }; // Attempt to parse the given issuer. If the value is a cloud identifier, it will
160
+ };
161
+ // Attempt to parse the given issuer. If the value is a cloud identifier, it will
179
162
  // be mapped to one of the supported values. If not, we assume the value is a valid URL.
180
-
181
-
182
163
  const getConfiguredDefaultIssuer = options => {
183
164
  const issuer = mapCloudIdentifierToIssuer(options.issuer);
184
-
185
165
  if (!issuer) {
186
166
  throwIfIssuerIsNotAValidUrl(options.issuer);
187
167
  return options.issuer;
188
168
  }
189
-
190
169
  return issuer;
191
- }; // Construct the audience from the given option + the request path.
170
+ };
171
+
172
+ // Construct the audience from the given option + the request path.
192
173
  // If the request path is `/`, do not append it to the audience, otherwise
193
174
  // the token validation might fail because of mismatching audiences.
194
-
195
-
196
175
  const getConfiguredAudience = (options, requestPath) => {
197
176
  var _context;
198
-
199
177
  // remove the trailing slash
200
178
  const url = new _URL__default["default"](_concatInstanceProperty__default["default"](_context = "".concat(options.audience.replace(/\/?$/, ''))).call(_context, requestPath));
201
-
202
179
  switch (options.audiencePolicy) {
203
180
  case 'forward-url-origin':
204
181
  return url.origin;
205
-
206
182
  default:
207
183
  {
208
184
  var _context2;
209
-
210
185
  if (requestPath === '/') {
211
186
  return url.origin;
212
187
  }
213
-
214
188
  return _concatInstanceProperty__default["default"](_context2 = "".concat(url.origin)).call(_context2, url.pathname);
215
189
  }
216
190
  }
217
191
  };
218
-
219
192
  function createSessionAuthVerifier(options) {
220
193
  validateRequiredValues(options);
221
- const configuredDefaultIssuer = getConfiguredDefaultIssuer(options); // Returns an async HTTP handler.
194
+ const configuredDefaultIssuer = getConfiguredDefaultIssuer(options);
222
195
 
196
+ // Returns an async HTTP handler.
223
197
  return async (request, response) => {
224
198
  var _mapCloudIdentifierTo, _request$originalUrl;
225
-
226
199
  // Get the cloud identifier header, forwarded by the `/proxy/forward-to` endpoint.
227
200
  const cloudIdentifierHeader = getFirstHeaderValueOrThrow(request.headers, MC_API_PROXY_HEADERS.CLOUD_IDENTIFIER, "Missing \"X-MC-API-Cloud-Identifier\" header.");
228
- let issuer = options.inferIssuer && cloudIdentifierHeader ? (_mapCloudIdentifierTo = mapCloudIdentifierToIssuer(cloudIdentifierHeader)) !== null && _mapCloudIdentifierTo !== void 0 ? _mapCloudIdentifierTo : configuredDefaultIssuer : configuredDefaultIssuer; // Get the `Accept-version` header, forwarded by the `/proxy/forward-to` endpoint.
229
- // The version should be sent by the client making the request, to use the features of v2.
201
+ let issuer = options.inferIssuer && cloudIdentifierHeader ? (_mapCloudIdentifierTo = mapCloudIdentifierToIssuer(cloudIdentifierHeader)) !== null && _mapCloudIdentifierTo !== void 0 ? _mapCloudIdentifierTo : configuredDefaultIssuer : configuredDefaultIssuer;
230
202
 
203
+ // Get the `Accept-version` header, forwarded by the `/proxy/forward-to` endpoint.
204
+ // The version should be sent by the client making the request, to use the features of v2.
231
205
  const proxyForwardVersion = getFirstHeaderValueOrThrow(request.headers, MC_API_PROXY_HEADERS.FORWARD_TO_VERSION, "Missing \"X-MC-API-Forward-To-Version\" header.");
232
-
233
206
  if (proxyForwardVersion === 'v1') {
234
207
  var _mapToLegacyIssuer;
235
-
236
208
  // Fall back to legacy issuer domains
237
209
  issuer = (_mapToLegacyIssuer = mapToLegacyIssuer(cloudIdentifierHeader)) !== null && _mapToLegacyIssuer !== void 0 ? _mapToLegacyIssuer : issuer;
238
210
  }
239
-
240
211
  const requestUrlPath = options.getRequestUrl ? options.getRequestUrl(request) : (_request$originalUrl = request.originalUrl) !== null && _request$originalUrl !== void 0 ? _request$originalUrl : request.url;
241
-
242
212
  if (!requestUrlPath || !_startsWithInstanceProperty__default["default"](requestUrlPath).call(requestUrlPath, '/')) {
243
213
  throw new Error("Invalid request URI path \"".concat(requestUrlPath, "\". Please make sure that the \"request\" object has either a property \"originalUrl\" or \"url\". If not, you should implement the \"getRequestUrl\" function and make sure to return a valid URI path value starting with \"/\". More info at https://docs.commercetools.com/custom-applications/concepts/integrate-with-your-own-api#validating-the-json-web-token"));
244
214
  }
245
-
246
215
  const audience = getConfiguredAudience(options, requestUrlPath);
247
216
  return new _Promise__default["default"]((resolve, reject) => {
248
217
  expressJwt.expressjwt({
@@ -261,8 +230,8 @@ function createSessionAuthVerifier(options) {
261
230
  // Validate the audience and the issuer.
262
231
  audience,
263
232
  issuer,
264
- algorithms: ['RS256'] // @ts-ignore: the middleware expects an Express.js Request/Response objects
265
-
233
+ algorithms: ['RS256']
234
+ // @ts-ignore: the middleware expects an Express.js Request/Response objects
266
235
  })(request, response !== null && response !== void 0 ? response : {}, error => {
267
236
  if (error) {
268
237
  reject(error);
@@ -23,14 +23,16 @@ const CLOUD_IDENTIFIERS = {
23
23
  GCP_EU: 'gcp-eu',
24
24
  GCP_US: 'gcp-us',
25
25
  AWS_FRA: 'aws-fra',
26
- AWS_OHIO: 'aws-ohio'
26
+ AWS_OHIO: 'aws-ohio',
27
+ AWS_CN: 'aws-cn'
27
28
  };
28
29
  const MC_API_URLS = {
29
30
  GCP_AU: 'https://mc-api.australia-southeast1.gcp.commercetools.com',
30
31
  GCP_EU: 'https://mc-api.europe-west1.gcp.commercetools.com',
31
32
  GCP_US: 'https://mc-api.us-central1.gcp.commercetools.com',
32
33
  AWS_FRA: 'https://mc-api.eu-central-1.aws.commercetools.com',
33
- AWS_OHIO: 'https://mc-api.us-east-2.aws.commercetools.com'
34
+ AWS_OHIO: 'https://mc-api.us-east-2.aws.commercetools.com',
35
+ AWS_CN: 'https://mc-api.cn-northwest-1.aws.commercetools.cn'
34
36
  };
35
37
  const MC_API_PROXY_HEADERS = {
36
38
  FORWARD_TO_VERSION: 'x-mc-api-forward-to-version',
@@ -39,42 +41,32 @@ const MC_API_PROXY_HEADERS = {
39
41
 
40
42
  const getHeaderByCaseInsensitiveKey = (headers, headerKey) => {
41
43
  var _context;
42
-
43
44
  const matchingHeader = _findInstanceProperty(_context = _Object$entries(headers)).call(_context, _ref => {
44
45
  let _ref2 = _slicedToArray(_ref, 1),
45
- key = _ref2[0];
46
-
46
+ key = _ref2[0];
47
47
  return headerKey.toLowerCase() === key.toLowerCase();
48
48
  });
49
-
50
49
  if (matchingHeader && matchingHeader.length > 0) {
51
50
  const _matchingHeader = _slicedToArray(matchingHeader, 2),
52
- headerValue = _matchingHeader[1];
53
-
51
+ headerValue = _matchingHeader[1];
54
52
  return _Array$isArray(headerValue) ? headerValue[0] : headerValue;
55
53
  }
56
-
57
54
  return undefined;
58
55
  };
59
-
60
56
  const getFirstHeaderValueOrThrow = (headers, headerKey, errorMessage) => {
61
57
  const headerValue = getHeaderByCaseInsensitiveKey(headers, headerKey);
62
-
63
58
  if (!headerValue) {
64
59
  throw new Error(errorMessage);
65
60
  }
66
-
67
61
  return headerValue;
68
62
  };
69
63
 
70
64
  function ownKeys(object, enumerableOnly) { var keys = _Object$keys(object); if (_Object$getOwnPropertySymbols) { var symbols = _Object$getOwnPropertySymbols(object); enumerableOnly && (symbols = _filterInstanceProperty(symbols).call(symbols, function (sym) { return _Object$getOwnPropertyDescriptor(object, sym).enumerable; })), keys.push.apply(keys, symbols); } return keys; }
71
-
72
65
  function _objectSpread(target) { for (var i = 1; i < arguments.length; i++) { var _context3, _context4; var source = null != arguments[i] ? arguments[i] : {}; i % 2 ? _forEachInstanceProperty(_context3 = ownKeys(Object(source), !0)).call(_context3, function (key) { _defineProperty(target, key, source[key]); }) : _Object$getOwnPropertyDescriptors ? _Object$defineProperties(target, _Object$getOwnPropertyDescriptors(source)) : _forEachInstanceProperty(_context4 = ownKeys(Object(source))).call(_context4, function (key) { _Object$defineProperty(target, key, _Object$getOwnPropertyDescriptor(source, key)); }); } return target; }
73
- const decodedTokenKey = 'decoded_token'; // Assign a session object to the request object.
74
-
66
+ const decodedTokenKey = 'decoded_token';
67
+ // Assign a session object to the request object.
75
68
  const writeSessionContext = request => {
76
69
  const decodedToken = request[decodedTokenKey];
77
-
78
70
  if (decodedToken) {
79
71
  const publicClaimForProjectKey = "".concat(decodedToken.iss, "/claims/project_key");
80
72
  const publicClaimForUserPermissionsKey = "".concat(decodedToken.iss, "/claims/user_permissions");
@@ -83,143 +75,120 @@ const writeSessionContext = request => {
83
75
  projectKey: decodedToken[publicClaimForProjectKey]
84
76
  };
85
77
  const userPermissions = decodedToken[publicClaimForUserPermissionsKey];
86
-
87
78
  if (Boolean(userPermissions === null || userPermissions === void 0 ? void 0 : userPermissions.length)) {
88
79
  request.session.userPermissions = userPermissions;
89
80
  }
90
- } // Remove the field used by the JWT middleware.
91
-
81
+ }
92
82
 
83
+ // Remove the field used by the JWT middleware.
93
84
  delete request.decoded_token;
94
- }; // Given a cloud identifier, try to map it to one of the supported
85
+ };
86
+
87
+ // Given a cloud identifier, try to map it to one of the supported
95
88
  // environments and return the MC API URL for that environment.
96
89
  // The URL points to the new hostnames.
97
90
  // https://docs.commercetools.com/custom-applications/concepts/merchant-center-api#hostnames
98
-
99
-
100
91
  const mapCloudIdentifierToIssuer = issuer => {
101
92
  switch (issuer) {
102
93
  case CLOUD_IDENTIFIERS.GCP_AU:
103
94
  return MC_API_URLS.GCP_AU;
104
-
105
95
  case CLOUD_IDENTIFIERS.GCP_EU:
106
96
  return MC_API_URLS.GCP_EU;
107
-
108
97
  case CLOUD_IDENTIFIERS.GCP_US:
109
98
  return MC_API_URLS.GCP_US;
110
-
111
99
  case CLOUD_IDENTIFIERS.AWS_FRA:
112
100
  return MC_API_URLS.AWS_FRA;
113
-
114
101
  case CLOUD_IDENTIFIERS.AWS_OHIO:
115
102
  return MC_API_URLS.AWS_OHIO;
116
-
103
+ case CLOUD_IDENTIFIERS.AWS_CN:
104
+ return MC_API_URLS.AWS_CN;
117
105
  default:
118
106
  return undefined;
119
107
  }
120
- }; // Given a cloud identifier, try to map it to a legacy hostname.
108
+ };
109
+ // Given a cloud identifier, try to map it to a legacy hostname.
121
110
  // This is for backwards compatibility.
122
-
123
-
124
111
  const mapToLegacyIssuer = cloudIdentifier => {
125
112
  switch (cloudIdentifier) {
126
113
  case CLOUD_IDENTIFIERS.GCP_EU:
127
114
  return 'https://mc-api.commercetools.com';
128
-
129
115
  case CLOUD_IDENTIFIERS.GCP_US:
130
116
  return 'https://mc-api.commercetools.co';
131
-
132
117
  default:
133
118
  return undefined;
134
119
  }
135
- }; // Verifies that the issuer is a valid URL.
136
-
137
-
120
+ };
121
+ // Verifies that the issuer is a valid URL.
138
122
  const throwIfIssuerIsNotAValidUrl = issuer => {
139
123
  try {
140
124
  new _URL(issuer);
141
125
  } catch (error) {
142
126
  throw new Error("Invalid issuer URL \"".concat(issuer, "\". Expected a valid URL to the Merchant Center API Gateway, or a cloud identifier to one of the available cloud regions. See https://docs.commercetools.com/custom-applications/concepts/merchant-center-api#hostnames."));
143
127
  }
144
- }; // Validates required option values.
145
-
146
-
128
+ };
129
+ // Validates required option values.
147
130
  const validateRequiredValues = options => {
148
131
  if (!options.audience) {
149
132
  throw new Error("Missing required option \"audience\"");
150
133
  }
151
-
152
134
  if (!options.issuer) {
153
135
  throw new Error("Missing required option \"issuer\"");
154
136
  }
155
- }; // Attempt to parse the given issuer. If the value is a cloud identifier, it will
137
+ };
138
+ // Attempt to parse the given issuer. If the value is a cloud identifier, it will
156
139
  // be mapped to one of the supported values. If not, we assume the value is a valid URL.
157
-
158
-
159
140
  const getConfiguredDefaultIssuer = options => {
160
141
  const issuer = mapCloudIdentifierToIssuer(options.issuer);
161
-
162
142
  if (!issuer) {
163
143
  throwIfIssuerIsNotAValidUrl(options.issuer);
164
144
  return options.issuer;
165
145
  }
166
-
167
146
  return issuer;
168
- }; // Construct the audience from the given option + the request path.
147
+ };
148
+
149
+ // Construct the audience from the given option + the request path.
169
150
  // If the request path is `/`, do not append it to the audience, otherwise
170
151
  // the token validation might fail because of mismatching audiences.
171
-
172
-
173
152
  const getConfiguredAudience = (options, requestPath) => {
174
153
  var _context;
175
-
176
154
  // remove the trailing slash
177
155
  const url = new _URL(_concatInstanceProperty(_context = "".concat(options.audience.replace(/\/?$/, ''))).call(_context, requestPath));
178
-
179
156
  switch (options.audiencePolicy) {
180
157
  case 'forward-url-origin':
181
158
  return url.origin;
182
-
183
159
  default:
184
160
  {
185
161
  var _context2;
186
-
187
162
  if (requestPath === '/') {
188
163
  return url.origin;
189
164
  }
190
-
191
165
  return _concatInstanceProperty(_context2 = "".concat(url.origin)).call(_context2, url.pathname);
192
166
  }
193
167
  }
194
168
  };
195
-
196
169
  function createSessionAuthVerifier(options) {
197
170
  validateRequiredValues(options);
198
- const configuredDefaultIssuer = getConfiguredDefaultIssuer(options); // Returns an async HTTP handler.
171
+ const configuredDefaultIssuer = getConfiguredDefaultIssuer(options);
199
172
 
173
+ // Returns an async HTTP handler.
200
174
  return async (request, response) => {
201
175
  var _mapCloudIdentifierTo, _request$originalUrl;
202
-
203
176
  // Get the cloud identifier header, forwarded by the `/proxy/forward-to` endpoint.
204
177
  const cloudIdentifierHeader = getFirstHeaderValueOrThrow(request.headers, MC_API_PROXY_HEADERS.CLOUD_IDENTIFIER, "Missing \"X-MC-API-Cloud-Identifier\" header.");
205
- let issuer = options.inferIssuer && cloudIdentifierHeader ? (_mapCloudIdentifierTo = mapCloudIdentifierToIssuer(cloudIdentifierHeader)) !== null && _mapCloudIdentifierTo !== void 0 ? _mapCloudIdentifierTo : configuredDefaultIssuer : configuredDefaultIssuer; // Get the `Accept-version` header, forwarded by the `/proxy/forward-to` endpoint.
206
- // The version should be sent by the client making the request, to use the features of v2.
178
+ let issuer = options.inferIssuer && cloudIdentifierHeader ? (_mapCloudIdentifierTo = mapCloudIdentifierToIssuer(cloudIdentifierHeader)) !== null && _mapCloudIdentifierTo !== void 0 ? _mapCloudIdentifierTo : configuredDefaultIssuer : configuredDefaultIssuer;
207
179
 
180
+ // Get the `Accept-version` header, forwarded by the `/proxy/forward-to` endpoint.
181
+ // The version should be sent by the client making the request, to use the features of v2.
208
182
  const proxyForwardVersion = getFirstHeaderValueOrThrow(request.headers, MC_API_PROXY_HEADERS.FORWARD_TO_VERSION, "Missing \"X-MC-API-Forward-To-Version\" header.");
209
-
210
183
  if (proxyForwardVersion === 'v1') {
211
184
  var _mapToLegacyIssuer;
212
-
213
185
  // Fall back to legacy issuer domains
214
186
  issuer = (_mapToLegacyIssuer = mapToLegacyIssuer(cloudIdentifierHeader)) !== null && _mapToLegacyIssuer !== void 0 ? _mapToLegacyIssuer : issuer;
215
187
  }
216
-
217
188
  const requestUrlPath = options.getRequestUrl ? options.getRequestUrl(request) : (_request$originalUrl = request.originalUrl) !== null && _request$originalUrl !== void 0 ? _request$originalUrl : request.url;
218
-
219
189
  if (!requestUrlPath || !_startsWithInstanceProperty(requestUrlPath).call(requestUrlPath, '/')) {
220
190
  throw new Error("Invalid request URI path \"".concat(requestUrlPath, "\". Please make sure that the \"request\" object has either a property \"originalUrl\" or \"url\". If not, you should implement the \"getRequestUrl\" function and make sure to return a valid URI path value starting with \"/\". More info at https://docs.commercetools.com/custom-applications/concepts/integrate-with-your-own-api#validating-the-json-web-token"));
221
191
  }
222
-
223
192
  const audience = getConfiguredAudience(options, requestUrlPath);
224
193
  return new _Promise((resolve, reject) => {
225
194
  expressjwt({
@@ -238,8 +207,8 @@ function createSessionAuthVerifier(options) {
238
207
  // Validate the audience and the issuer.
239
208
  audience,
240
209
  issuer,
241
- algorithms: ['RS256'] // @ts-ignore: the middleware expects an Express.js Request/Response objects
242
-
210
+ algorithms: ['RS256']
211
+ // @ts-ignore: the middleware expects an Express.js Request/Response objects
243
212
  })(request, response !== null && response !== void 0 ? response : {}, error => {
244
213
  if (error) {
245
214
  reject(error);
@@ -4,10 +4,10 @@ type TDecodedJWT = {
4
4
  iss: string;
5
5
  [property: string]: string | string[];
6
6
  };
7
- declare const writeSessionContext: <Request_1 extends TBaseRequest>(request: Request_1 & {
7
+ declare const writeSessionContext: <Request extends TBaseRequest>(request: Request & {
8
8
  decoded_token?: TDecodedJWT | undefined;
9
9
  session?: TSession | undefined;
10
10
  }) => void;
11
- export declare const getConfiguredAudience: <Request_1 extends TBaseRequest>(options: TSessionMiddlewareOptions<Request_1>, requestPath: string) => string;
11
+ export declare const getConfiguredAudience: <Request extends TBaseRequest>(options: TSessionMiddlewareOptions<Request>, requestPath: string) => string;
12
12
  declare function createSessionAuthVerifier<Request extends TBaseRequest>(options: TSessionMiddlewareOptions<Request>): (request: Request, response?: unknown) => Promise<void>;
13
13
  export { createSessionAuthVerifier, writeSessionContext };
@@ -4,6 +4,7 @@ export declare const CLOUD_IDENTIFIERS: {
4
4
  readonly GCP_US: "gcp-us";
5
5
  readonly AWS_FRA: "aws-fra";
6
6
  readonly AWS_OHIO: "aws-ohio";
7
+ readonly AWS_CN: "aws-cn";
7
8
  };
8
9
  export declare const MC_API_URLS: {
9
10
  readonly GCP_AU: "https://mc-api.australia-southeast1.gcp.commercetools.com";
@@ -11,6 +12,7 @@ export declare const MC_API_URLS: {
11
12
  readonly GCP_US: "https://mc-api.us-central1.gcp.commercetools.com";
12
13
  readonly AWS_FRA: "https://mc-api.eu-central-1.aws.commercetools.com";
13
14
  readonly AWS_OHIO: "https://mc-api.us-east-2.aws.commercetools.com";
15
+ readonly AWS_CN: "https://mc-api.cn-northwest-1.aws.commercetools.cn";
14
16
  };
15
17
  export declare const MC_API_PROXY_HEADERS: {
16
18
  readonly FORWARD_TO_VERSION: "x-mc-api-forward-to-version";
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@commercetools-backend/express",
3
- "version": "22.2.1",
3
+ "version": "22.3.1",
4
4
  "description": "Zero-config HTTP server as Express.js to facilitate development",
5
5
  "bugs": "https://github.com/commercetools/merchant-center-application-kit/issues",
6
6
  "repository": {
@@ -9,17 +9,30 @@
9
9
  "directory": "packages-backend/express"
10
10
  },
11
11
  "homepage": "https://docs.commercetools.com/custom-applications",
12
- "keywords": ["javascript", "nodejs", "express", "http", "server", "toolkit"],
12
+ "keywords": [
13
+ "javascript",
14
+ "nodejs",
15
+ "express",
16
+ "http",
17
+ "server",
18
+ "toolkit"
19
+ ],
13
20
  "license": "MIT",
14
21
  "publishConfig": {
15
22
  "access": "public"
16
23
  },
17
24
  "main": "dist/commercetools-backend-express.cjs.js",
18
25
  "module": "dist/commercetools-backend-express.esm.js",
19
- "files": ["dist", "package.json", "LICENSE", "README.md"],
26
+ "files": [
27
+ "dist",
28
+ "package.json",
29
+ "LICENSE",
30
+ "README.md"
31
+ ],
20
32
  "dependencies": {
21
33
  "@babel/runtime": "^7.20.13",
22
34
  "@babel/runtime-corejs3": "^7.20.13",
35
+ "@types/express": "^4.17.17",
23
36
  "@types/node": "^18.15.11",
24
37
  "express": "4.18.2",
25
38
  "express-jwt": "8.4.1",
@@ -32,4 +45,4 @@
32
45
  "jose": "2.0.6",
33
46
  "msw": "0.49.3"
34
47
  }
35
- }
48
+ }