@contentstack/cli-utilities 1.3.0 → 1.3.2

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
@@ -0,0 +1,382 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
3
+ const tslib_1 = require("tslib");
4
+ const cli_ux_1 = tslib_1.__importDefault(require("./cli-ux"));
5
+ const logger_1 = tslib_1.__importDefault(require("./logger"));
6
+ const http_client_1 = tslib_1.__importDefault(require("./http-client"));
7
+ const config_handler_1 = tslib_1.__importDefault(require("./config-handler"));
8
+ const ContentstackManagementSDK = tslib_1.__importStar(require("@contentstack/management"));
9
+ const http = require('http');
10
+ const url = require('url');
11
+ const open_1 = tslib_1.__importDefault(require("open"));
12
+ const crypto = require('crypto');
13
+ /**
14
+ * @class
15
+ * Auth handler
16
+ */
17
+ class AuthHandler {
18
+ set host(contentStackHost) {
19
+ this._host = contentStackHost;
20
+ }
21
+ constructor() {
22
+ this.checkExpiryAndRefresh = (force = false) => this.compareOAuthExpiry(force);
23
+ this.codeVerifier = crypto.pseudoRandomBytes(32).toString('hex');
24
+ this.OAuthAppId = process.env.OAUTH_APP_ID || '6400aa06db64de001a31c8a9';
25
+ this.OAuthClientId = process.env.OAUTH_CLIENT_ID || 'Ie0FEfTzlfAHL4xM';
26
+ this.OAuthRedirectURL = process.env.OAUTH_APP_REDIRECT_URL || 'http://localhost:8184';
27
+ this.OAuthScope = '';
28
+ this.OAuthResponseType = 'code';
29
+ this.authTokenKeyName = 'authtoken';
30
+ this.authEmailKeyName = 'email';
31
+ this.oauthAccessTokenKeyName = 'oauthAccessToken';
32
+ this.oauthDateTimeKeyName = 'oauthDateTime';
33
+ this.oauthUserUidKeyName = 'oauthUserUid';
34
+ this.oauthOrgUidKeyName = 'oauthOrgUid';
35
+ this.oauthRefreshTokenKeyName = 'oauthRefreshToken';
36
+ this.authorisationTypeKeyName = 'authorisationType';
37
+ this.authorisationTypeOAUTHValue = 'OAUTH';
38
+ this.authorisationTypeAUTHValue = 'BASIC';
39
+ this.allAuthConfigItems = {
40
+ refreshToken: [
41
+ this.authTokenKeyName,
42
+ this.oauthAccessTokenKeyName,
43
+ this.oauthDateTimeKeyName,
44
+ this.oauthRefreshTokenKeyName,
45
+ ],
46
+ default: [
47
+ this.authTokenKeyName,
48
+ this.authEmailKeyName,
49
+ this.oauthAccessTokenKeyName,
50
+ this.oauthDateTimeKeyName,
51
+ this.oauthUserUidKeyName,
52
+ this.oauthOrgUidKeyName,
53
+ this.oauthRefreshTokenKeyName,
54
+ this.authorisationTypeKeyName,
55
+ ],
56
+ };
57
+ }
58
+ async setOAuthBaseURL() {
59
+ if (config_handler_1.default.get('region')['uiHost']) {
60
+ this.OAuthBaseURL = config_handler_1.default.get('region')['uiHost'] || '';
61
+ }
62
+ else {
63
+ throw new Error('Invalid ui-host URL while authenticating. Please set your region correctly using the command - csdx config:set:region');
64
+ }
65
+ }
66
+ /*
67
+ *
68
+ * Login into Contentstack
69
+ * @returns {Promise} Promise object returns {} on success
70
+ */
71
+ async oauth() {
72
+ return new Promise((resolve, reject) => {
73
+ this.createHTTPServer()
74
+ .then(() => {
75
+ this.openOAuthURL()
76
+ .then(() => {
77
+ //set timeout for authorization
78
+ resolve({});
79
+ })
80
+ .catch((error) => {
81
+ logger_1.default.error('OAuth login failed', error.message);
82
+ reject(error);
83
+ });
84
+ })
85
+ .catch((error) => {
86
+ logger_1.default.error('OAuth login failed', error.message);
87
+ reject(error);
88
+ });
89
+ });
90
+ }
91
+ async createHTTPServer() {
92
+ return new Promise((resolve, reject) => {
93
+ try {
94
+ const server = http.createServer((req, res) => {
95
+ const reqURL = req.url;
96
+ const queryObject = url.parse(reqURL, true).query;
97
+ if (queryObject.code) {
98
+ cli_ux_1.default.print('Auth code successfully fetched.');
99
+ this.getAccessToken(queryObject.code)
100
+ .then(async () => {
101
+ await this.setOAuthBaseURL();
102
+ cli_ux_1.default.print('Access token fetched using auth code successfully.');
103
+ cli_ux_1.default.print(`You can review the access permissions on the page - ${this.OAuthBaseURL}/#!/marketplace/authorized-apps`);
104
+ res.writeHead(200, { 'Content-Type': 'text/html' });
105
+ res.end(`<h1>Successfully authorized!</h1><h2>You can close this window now.</h2><p>You can review the access permissions on - <a href="${this.OAuthBaseURL}/#!/marketplace/authorized-apps" target="_blank">Authorized Apps page</a></p>`);
106
+ stopServer();
107
+ })
108
+ .catch((error) => {
109
+ cli_ux_1.default.error('Error occoured while login with OAuth, please login with command - csdx auth:login --oauth');
110
+ cli_ux_1.default.error(error);
111
+ res.writeHead(200, { 'Content-Type': 'text/html' });
112
+ res.end(`<h1>Sorry!</h1><h2>Something went wrong, please login with command - csdx auth:login --oauth(</h2>`);
113
+ stopServer();
114
+ });
115
+ }
116
+ else {
117
+ cli_ux_1.default.error('Error occoured while login with OAuth, please login with command - csdx auth:login --oauth');
118
+ res.writeHead(200, { 'Content-Type': 'text/html' });
119
+ res.end(`<h1>Sorry!</h1><h2>Something went wrong, please login with command - csdx auth:login --oauth(</h2>`);
120
+ stopServer();
121
+ }
122
+ });
123
+ const stopServer = () => {
124
+ server.close();
125
+ process.exit();
126
+ };
127
+ server.listen(8184, () => {
128
+ cli_ux_1.default.print('Waiting for the authorization server to respond...');
129
+ resolve({ true: true });
130
+ });
131
+ }
132
+ catch (error) {
133
+ cli_ux_1.default.error(error);
134
+ reject(error);
135
+ }
136
+ });
137
+ }
138
+ async openOAuthURL() {
139
+ return new Promise(async (resolve, reject) => {
140
+ try {
141
+ const digest = crypto.createHash('sha256').update(this.codeVerifier).digest();
142
+ const codeChallenge = digest.toString('base64').replace(/\+/g, '-').replace(/\//g, '_').replace(/=/g, '');
143
+ await this.setOAuthBaseURL();
144
+ let url = `${this.OAuthBaseURL}/#!/apps/${this.OAuthAppId}/authorize?response_type=${this.OAuthResponseType}&client_id=${this.OAuthClientId}&redirect_uri=${this.OAuthRedirectURL}&code_challenge=${codeChallenge}&code_challenge_method=S256`;
145
+ if (this.OAuthScope) {
146
+ url += `&scope=${encodeURIComponent(this.OAuthScope)}`;
147
+ }
148
+ cli_ux_1.default.print('This will automatically start the browser and open the below URL, if it does not, you can copy and paste the below URL in the browser without terminating this command.', { color: 'yellow' });
149
+ cli_ux_1.default.print(url, { color: 'green' });
150
+ resolve((0, open_1.default)(url));
151
+ }
152
+ catch (error) {
153
+ reject(error);
154
+ }
155
+ });
156
+ }
157
+ async getAccessToken(code) {
158
+ return new Promise((resolve, reject) => {
159
+ const headers = { 'Content-Type': 'application/x-www-form-urlencoded' };
160
+ const payload = {
161
+ grant_type: 'authorization_code',
162
+ client_id: this.OAuthClientId,
163
+ code_verifier: this.codeVerifier,
164
+ redirect_uri: this.OAuthRedirectURL,
165
+ code: code,
166
+ };
167
+ this.setOAuthBaseURL();
168
+ const httpClient = new http_client_1.default().headers(headers).asFormParams();
169
+ httpClient
170
+ .post(`${this.OAuthBaseURL}/apps-api/apps/token`, payload)
171
+ .then(({ data }) => {
172
+ return this.getUserDetails(data);
173
+ })
174
+ .then((data) => {
175
+ if (data['access_token'] && data['refresh_token']) {
176
+ return this.setConfigData('oauth', data);
177
+ }
178
+ else {
179
+ reject('Invalid request');
180
+ }
181
+ })
182
+ .then(resolve)
183
+ .catch((error) => {
184
+ cli_ux_1.default.error('An error occoured while fetching the access token, run the command - csdx auth:login --oauth');
185
+ cli_ux_1.default.error(error);
186
+ reject(error);
187
+ });
188
+ });
189
+ }
190
+ async setConfigData(type, userData = {}) {
191
+ return new Promise(async (resolve, reject) => {
192
+ //Delete the old configstore auth data
193
+ this.unsetConfigData(type)
194
+ .then(() => {
195
+ switch (type) {
196
+ case 'oauth':
197
+ if (userData.access_token && userData.refresh_token) {
198
+ //Set the new OAuth tokens info
199
+ config_handler_1.default.set(this.oauthAccessTokenKeyName, userData.access_token);
200
+ config_handler_1.default.set(this.oauthRefreshTokenKeyName, userData.refresh_token);
201
+ config_handler_1.default.set(this.authEmailKeyName, userData.email);
202
+ config_handler_1.default.set(this.oauthDateTimeKeyName, new Date());
203
+ config_handler_1.default.set(this.oauthUserUidKeyName, userData.user_uid);
204
+ config_handler_1.default.set(this.oauthOrgUidKeyName, userData.organization_uid);
205
+ config_handler_1.default.set(this.authorisationTypeKeyName, this.authorisationTypeOAUTHValue);
206
+ resolve(userData);
207
+ }
208
+ else {
209
+ reject('Invalid request');
210
+ }
211
+ break;
212
+ case 'refreshToken':
213
+ if (userData.access_token && userData.refresh_token) {
214
+ //Set the new OAuth tokens info
215
+ config_handler_1.default.set(this.oauthAccessTokenKeyName, userData.access_token);
216
+ config_handler_1.default.set(this.oauthRefreshTokenKeyName, userData.refresh_token);
217
+ config_handler_1.default.set(this.oauthDateTimeKeyName, new Date());
218
+ resolve(userData);
219
+ }
220
+ else {
221
+ reject('Invalid request');
222
+ }
223
+ break;
224
+ case 'basicAuth':
225
+ if (userData.authtoken && userData.email) {
226
+ //Set the new auth tokens info
227
+ config_handler_1.default.set(this.authTokenKeyName, userData.authtoken);
228
+ config_handler_1.default.set(this.authEmailKeyName, userData.email);
229
+ config_handler_1.default.set(this.authorisationTypeKeyName, this.authorisationTypeAUTHValue);
230
+ resolve(userData);
231
+ }
232
+ else {
233
+ reject('Invalid request');
234
+ }
235
+ break;
236
+ case 'logout':
237
+ resolve(userData);
238
+ break;
239
+ default:
240
+ reject('Invalid request');
241
+ break;
242
+ }
243
+ })
244
+ .catch((error) => {
245
+ reject(error);
246
+ });
247
+ });
248
+ }
249
+ async unsetConfigData(type = 'default') {
250
+ return new Promise(async (resolve, reject) => {
251
+ //Delete the old auth tokens info
252
+ let removeItems = this.allAuthConfigItems.default;
253
+ if (type === 'refreshToken') {
254
+ removeItems = this.allAuthConfigItems.refreshToken;
255
+ }
256
+ removeItems.forEach((element) => {
257
+ config_handler_1.default.delete(element);
258
+ });
259
+ resolve();
260
+ });
261
+ }
262
+ async refreshToken() {
263
+ return new Promise((resolve, reject) => {
264
+ const configOauthRefreshToken = config_handler_1.default.get(this.oauthRefreshTokenKeyName);
265
+ const configAuthorisationType = config_handler_1.default.get(this.authorisationTypeKeyName);
266
+ if (configAuthorisationType === this.authorisationTypeOAUTHValue && configOauthRefreshToken) {
267
+ const headers = { 'Content-Type': 'application/x-www-form-urlencoded' };
268
+ const payload = {
269
+ grant_type: 'refresh_token',
270
+ client_id: this.OAuthClientId,
271
+ redirect_uri: this.OAuthRedirectURL,
272
+ refresh_token: configOauthRefreshToken,
273
+ };
274
+ this.setOAuthBaseURL();
275
+ const httpClient = new http_client_1.default().headers(headers).asFormParams();
276
+ httpClient
277
+ .post(`${this.OAuthBaseURL}/apps-api/apps/token`, payload)
278
+ .then(({ data }) => {
279
+ if (data.error || (data.statusCode != 200 && data.message)) {
280
+ let errorMessage = '';
281
+ if (data.message) {
282
+ if (data.message[0]) {
283
+ errorMessage = data.message[0];
284
+ }
285
+ else {
286
+ errorMessage = data.message;
287
+ }
288
+ }
289
+ else {
290
+ errorMessage = data.error;
291
+ }
292
+ reject(errorMessage);
293
+ }
294
+ else {
295
+ if (data['access_token'] && data['refresh_token']) {
296
+ return this.setConfigData('refreshToken', data);
297
+ }
298
+ else {
299
+ reject('Invalid request');
300
+ }
301
+ }
302
+ })
303
+ .then(resolve)
304
+ .catch((error) => {
305
+ cli_ux_1.default.error('An error occoured while refreshing the token');
306
+ cli_ux_1.default.error(error);
307
+ reject(error);
308
+ });
309
+ }
310
+ else {
311
+ cli_ux_1.default.error('Invalid/Empty refresh token, run the command- csdx auth:login --oauth');
312
+ reject('Invalid/Empty refresh token');
313
+ }
314
+ });
315
+ }
316
+ async getUserDetails(data) {
317
+ return new Promise((resolve, reject) => {
318
+ const accessToken = data.access_token;
319
+ if (accessToken) {
320
+ const param = {
321
+ host: this._host,
322
+ authorization: `Bearer ${accessToken}`,
323
+ };
324
+ const managementAPIClient = ContentstackManagementSDK.client(param);
325
+ managementAPIClient
326
+ .getUser()
327
+ .then((user) => {
328
+ data.email = (user === null || user === void 0 ? void 0 : user.email) || '';
329
+ resolve(data);
330
+ })
331
+ .catch((error) => {
332
+ reject(error);
333
+ });
334
+ }
335
+ else {
336
+ cli_ux_1.default.error('Invalid/Empty access token, run the command - csdx auth:login --oauth');
337
+ reject('Invalid/Empty access token');
338
+ }
339
+ });
340
+ }
341
+ async isAuthenticated() {
342
+ const authorizationType = config_handler_1.default.get(this.authorisationTypeKeyName);
343
+ return (authorizationType === this.authorisationTypeOAUTHValue || authorizationType === this.authorisationTypeAUTHValue);
344
+ }
345
+ async getAuthorisationType() {
346
+ return config_handler_1.default.get(this.authorisationTypeKeyName) ? config_handler_1.default.get(this.authorisationTypeKeyName) : false;
347
+ }
348
+ async isAuthorisationTypeBasic() {
349
+ return config_handler_1.default.get(this.authorisationTypeKeyName) === this.authorisationTypeAUTHValue ? true : false;
350
+ }
351
+ async isAuthorisationTypeOAuth() {
352
+ return config_handler_1.default.get(this.authorisationTypeKeyName) === this.authorisationTypeOAUTHValue ? true : false;
353
+ }
354
+ async compareOAuthExpiry(force = false) {
355
+ const oauthDateTime = config_handler_1.default.get(this.oauthDateTimeKeyName);
356
+ const authorisationType = config_handler_1.default.get(this.authorisationTypeKeyName);
357
+ if (oauthDateTime && authorisationType === this.authorisationTypeOAUTHValue) {
358
+ const now = new Date();
359
+ const oauthDate = new Date(oauthDateTime);
360
+ const oauthValidUpto = new Date();
361
+ oauthValidUpto.setTime(oauthDate.getTime() + 59 * 60 * 1000);
362
+ if (force) {
363
+ cli_ux_1.default.print('Force refreshing the token');
364
+ return this.refreshToken();
365
+ }
366
+ else {
367
+ if (oauthValidUpto > now) {
368
+ return Promise.resolve();
369
+ }
370
+ else {
371
+ cli_ux_1.default.print('Token expired, refreshing the token');
372
+ return this.refreshToken();
373
+ }
374
+ }
375
+ }
376
+ else {
377
+ cli_ux_1.default.print('No OAuth set');
378
+ return this.unsetConfigData();
379
+ }
380
+ }
381
+ }
382
+ exports.default = new AuthHandler();
@@ -5,7 +5,7 @@ const conf_1 = tslib_1.__importDefault(require("conf"));
5
5
  const uuid_1 = require("uuid");
6
6
  const fs_1 = require("fs");
7
7
  const ENC_KEY = process.env.ENC_KEY || 'encryptionKey';
8
- const ENCRYPT_CONF = process.env.ENCRYPT_CONF === 'true' || false;
8
+ const ENCRYPT_CONF = process.env.ENCRYPT_CONF === 'true' || true;
9
9
  const CONFIG_NAME = process.env.CONFIG_NAME || 'contentstack_cli';
10
10
  const ENC_CONFIG_NAME = process.env.ENC_CONFIG_NAME || 'contentstack_cli_obfuscate';
11
11
  const OLD_CONFIG_BACKUP_FLAG = 'isOldConfigBackup';
@@ -22,9 +22,7 @@ class Config {
22
22
  this.importOldConfig();
23
23
  }
24
24
  init() {
25
- return ENCRYPT_CONF === true
26
- ? this.getEncryptedConfig()
27
- : this.getDecryptedConfig();
25
+ return ENCRYPT_CONF === true ? this.getEncryptedConfig() : this.getDecryptedConfig();
28
26
  }
29
27
  importOldConfig() {
30
28
  if (!this.get(OLD_CONFIG_BACKUP_FLAG)) {
@@ -36,7 +34,7 @@ class Config {
36
34
  }
37
35
  }
38
36
  catch (error) {
39
- console.log("No data to be imported from Old config file");
37
+ console.log('No data to be imported from Old config file');
40
38
  }
41
39
  this.set(OLD_CONFIG_BACKUP_FLAG, true);
42
40
  }
@@ -46,7 +44,7 @@ class Config {
46
44
  for (const key in data) {
47
45
  const value = data[key];
48
46
  const setPath = _path ? _path + '.' + key : key;
49
- if (typeof (value) == "object") {
47
+ if (typeof value == 'object') {
50
48
  this.setOldConfigStoreData(value, setPath);
51
49
  }
52
50
  else {
@@ -3,6 +3,7 @@ Object.defineProperty(exports, "__esModule", { value: true });
3
3
  exports.managementSDKInitiator = void 0;
4
4
  const tslib_1 = require("tslib");
5
5
  const management_1 = require("@contentstack/management");
6
+ const auth_handler_1 = tslib_1.__importDefault(require("./auth-handler"));
6
7
  const node_https_1 = require("node:https");
7
8
  const config_handler_1 = tslib_1.__importDefault(require("./config-handler"));
8
9
  class ManagementSDKInitiator {
@@ -48,9 +49,33 @@ class ManagementSDKInitiator {
48
49
  },
49
50
  },
50
51
  refreshToken: () => {
51
- return Promise.reject('You do not have permissions to perform this action, please login to proceed');
52
+ return new Promise((resolve, reject) => {
53
+ const authorisationType = config_handler_1.default.get('authorisationType');
54
+ if (authorisationType === 'BASIC') {
55
+ // Handle basic auth 401 here
56
+ reject('Session timed out, please login to proceed');
57
+ }
58
+ else if (authorisationType === 'OAUTH') {
59
+ return auth_handler_1.default
60
+ .compareOAuthExpiry(true)
61
+ .then(() => {
62
+ resolve({
63
+ authorization: `Bearer ${config_handler_1.default.get('oauthAccessToken')}`,
64
+ });
65
+ })
66
+ .catch((error) => {
67
+ reject(error);
68
+ });
69
+ }
70
+ else {
71
+ reject('You do not have permissions to perform this action, please login to proceed');
72
+ }
73
+ });
52
74
  },
53
75
  };
76
+ if (config.endpoint) {
77
+ option.endpoint = config.endpoint;
78
+ }
54
79
  if (typeof config.branchName === 'string') {
55
80
  if (!option.headers)
56
81
  option.headers = {};
@@ -62,11 +87,21 @@ class ManagementSDKInitiator {
62
87
  option.headers['X-CS-CLI'] = this.analyticsInfo;
63
88
  }
64
89
  if (!config.management_token) {
65
- const authtoken = config_handler_1.default.get('authtoken');
66
- if (authtoken) {
67
- option.authtoken = authtoken;
90
+ const authorisationType = config_handler_1.default.get('authorisationType');
91
+ if (authorisationType === 'BASIC') {
92
+ option.authtoken = config_handler_1.default.get('authtoken');
68
93
  option.authorization = '';
69
94
  }
95
+ else if (authorisationType === 'OAUTH') {
96
+ if (!config.skipTokenValidity) {
97
+ await auth_handler_1.default.compareOAuthExpiry();
98
+ option.authorization = `Bearer ${config_handler_1.default.get('oauthAccessToken')}`;
99
+ }
100
+ else {
101
+ option.authtoken = '';
102
+ option.authorization = '';
103
+ }
104
+ }
70
105
  else {
71
106
  option.authtoken = '';
72
107
  option.authorization = '';
package/lib/helpers.js CHANGED
@@ -2,14 +2,6 @@
2
2
  Object.defineProperty(exports, "__esModule", { value: true });
3
3
  exports.isAuthenticated = void 0;
4
4
  const tslib_1 = require("tslib");
5
- const config_handler_1 = tslib_1.__importDefault(require("./config-handler"));
6
- function isAuthenticated() {
7
- const authtoken = config_handler_1.default.get('authtoken');
8
- if (authtoken) {
9
- return true;
10
- }
11
- else {
12
- return false;
13
- }
14
- }
5
+ const auth_handler_1 = tslib_1.__importDefault(require("./auth-handler"));
6
+ const isAuthenticated = () => auth_handler_1.default.isAuthenticated();
15
7
  exports.isAuthenticated = isAuthenticated;
@@ -0,0 +1,27 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
3
+ exports.BaseClientDecorator = void 0;
4
+ class BaseClientDecorator {
5
+ constructor(client) {
6
+ this.client = client;
7
+ }
8
+ headers(headers) {
9
+ return this.client.headers(headers);
10
+ }
11
+ contentType(contentType) {
12
+ return this.client.contentType(contentType);
13
+ }
14
+ get(url, queryParams = {}) {
15
+ return this.client.get(url, queryParams);
16
+ }
17
+ post(url, payload) {
18
+ return this.client.post(url, payload);
19
+ }
20
+ put(url, payload) {
21
+ return this.client.put(url, payload);
22
+ }
23
+ delete(url, queryParams = {}) {
24
+ return this.client.delete(url, queryParams);
25
+ }
26
+ }
27
+ exports.BaseClientDecorator = BaseClientDecorator;
@@ -0,0 +1,2 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
@@ -4,6 +4,8 @@ exports.HttpClient = void 0;
4
4
  const tslib_1 = require("tslib");
5
5
  const axios_1 = tslib_1.__importDefault(require("axios"));
6
6
  const http_response_1 = require("./http-response");
7
+ const config_handler_1 = tslib_1.__importDefault(require("../config-handler"));
8
+ const auth_handler_1 = tslib_1.__importDefault(require("../auth-handler"));
7
9
  class HttpClient {
8
10
  /**
9
11
  * Createa new pending HTTP request instance.
@@ -300,8 +302,26 @@ class HttpClient {
300
302
  * @returns {Request}
301
303
  */
302
304
  async createAndSendRequest(method, url) {
303
- return await this.axiosInstance(Object.assign(Object.assign({ url,
304
- method, withCredentials: true }, this.request), { data: this.prepareRequestPayload() }));
305
+ let counter = 0;
306
+ this.axiosInstance.interceptors.response.use(null, async (error) => {
307
+ var _a, _b;
308
+ const { message, response } = error;
309
+ if ((_b = (_a = response === null || response === void 0 ? void 0 : response.data) === null || _a === void 0 ? void 0 : _a.error_message) === null || _b === void 0 ? void 0 : _b.includes('access token is invalid or expired')) {
310
+ const token = await this.refreshToken();
311
+ this.headers(Object.assign(Object.assign({}, this.request.headers), { authorization: token.authorization }));
312
+ return await this.axiosInstance(Object.assign(Object.assign({ url, method, withCredentials: true }, this.request), { data: this.prepareRequestPayload() }));
313
+ }
314
+ // Retry while Network timeout or Network Error
315
+ if (!(message.includes('timeout') || message.includes('Network Error') || message.includes('getaddrinfo ENOTFOUND'))) {
316
+ return Promise.reject(error);
317
+ }
318
+ if (counter < 1) {
319
+ counter++;
320
+ return await this.axiosInstance(Object.assign(Object.assign({ url, method, withCredentials: true }, this.request), { data: this.prepareRequestPayload() }));
321
+ }
322
+ return Promise.reject(error);
323
+ });
324
+ return await this.axiosInstance(Object.assign(Object.assign({ url, method, withCredentials: true }, this.request), { data: this.prepareRequestPayload() }));
305
325
  }
306
326
  /**
307
327
  * Returns the request payload depending on the selected request payload format.
@@ -309,5 +329,19 @@ class HttpClient {
309
329
  prepareRequestPayload() {
310
330
  return this.bodyFormat === 'formParams' ? new URLSearchParams(this.request.data).toString() : this.request.data;
311
331
  }
332
+ async refreshToken() {
333
+ const authorisationType = config_handler_1.default.get('authorisationType');
334
+ if (authorisationType === 'BASIC') {
335
+ return Promise.reject('Your session is timed out, please login to proceed');
336
+ }
337
+ else if (authorisationType === 'OAUTH') {
338
+ return auth_handler_1.default.compareOAuthExpiry(true)
339
+ .then(() => Promise.resolve({ authorization: `Bearer ${config_handler_1.default.get('oauthAccessToken')}`, }))
340
+ .catch((error) => Promise.reject(error));
341
+ }
342
+ else {
343
+ return Promise.reject('You do not have permissions to perform this action, please login to proceed');
344
+ }
345
+ }
312
346
  }
313
347
  exports.HttpClient = HttpClient;
@@ -0,0 +1,32 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
3
+ exports.HttpClientDecorator = void 0;
4
+ const base_client_decorator_1 = require("./base-client-decorator");
5
+ class HttpClientDecorator extends base_client_decorator_1.BaseClientDecorator {
6
+ constructor(client) {
7
+ super(client);
8
+ this.client = client;
9
+ }
10
+ headers(headers) {
11
+ return this.client.headers({
12
+ authtoken: headers.auth_token,
13
+ organization_uid: headers.org_uid,
14
+ });
15
+ }
16
+ contentType(contentType) {
17
+ return this.client.contentType(contentType);
18
+ }
19
+ get(url, queryParams = {}) {
20
+ return this.client.get(url, queryParams);
21
+ }
22
+ post(url, payload) {
23
+ return this.client.post(url, payload);
24
+ }
25
+ put(url, payload) {
26
+ return this.client.put(url, payload);
27
+ }
28
+ delete(url, queryParams = {}) {
29
+ return this.client.delete(url, queryParams);
30
+ }
31
+ }
32
+ exports.HttpClientDecorator = HttpClientDecorator;
@@ -5,3 +5,5 @@ const client_1 = require("./client");
5
5
  exports.default = client_1.HttpClient;
6
6
  tslib_1.__exportStar(require("./client"), exports);
7
7
  tslib_1.__exportStar(require("./http-response"), exports);
8
+ tslib_1.__exportStar(require("./http-client-decorator"), exports);
9
+ tslib_1.__exportStar(require("./oauth-decorator"), exports);
@@ -0,0 +1,49 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
3
+ exports.OauthDecorator = void 0;
4
+ const tslib_1 = require("tslib");
5
+ const base_client_decorator_1 = require("./base-client-decorator");
6
+ const config_handler_1 = tslib_1.__importDefault(require("../config-handler"));
7
+ const auth_handler_1 = tslib_1.__importDefault(require("../auth-handler"));
8
+ class OauthDecorator extends base_client_decorator_1.BaseClientDecorator {
9
+ constructor(client) {
10
+ super(client);
11
+ this.client = client;
12
+ }
13
+ async preHeadersCheck(config) {
14
+ const headers = {};
15
+ headers.organization_uid = config.org_uid;
16
+ const authorisationType = config_handler_1.default.get('authorisationType');
17
+ if (authorisationType === 'BASIC') {
18
+ headers.authtoken = config_handler_1.default.get('authtoken');
19
+ }
20
+ else if (authorisationType === 'OAUTH') {
21
+ await auth_handler_1.default.compareOAuthExpiry();
22
+ headers.authorization = `Bearer ${config_handler_1.default.get('oauthAccessToken')}`;
23
+ }
24
+ else {
25
+ headers.authtoken = '';
26
+ headers.authorization = '';
27
+ }
28
+ return headers;
29
+ }
30
+ headers(headers) {
31
+ return this.client.headers(headers);
32
+ }
33
+ contentType(contentType) {
34
+ return this.client.contentType(contentType);
35
+ }
36
+ get(url, queryParams) {
37
+ return this.client.get(url, queryParams);
38
+ }
39
+ post(url, payload) {
40
+ return this.client.post(url, payload);
41
+ }
42
+ put(url, payload) {
43
+ return this.client.put(url, payload);
44
+ }
45
+ delete(url, queryParams) {
46
+ return this.client.delete(url, queryParams);
47
+ }
48
+ }
49
+ exports.OauthDecorator = OauthDecorator;
package/lib/index.js CHANGED
@@ -1,6 +1,6 @@
1
1
  "use strict";
2
2
  Object.defineProperty(exports, "__esModule", { value: true });
3
- exports.stdout = exports.stderr = exports.execute = exports.ux = exports.flush = exports.settings = exports.toConfiguredId = exports.toStandardizedId = exports.tsPath = exports.toCached = exports.run = exports.Plugin = exports.Parser = exports.Interfaces = exports.HelpBase = exports.Help = exports.loadHelpClass = exports.Flags = exports.Errors = exports.Config = exports.CommandHelp = exports.Args = exports.Command = exports.flags = exports.args = exports.NodeCrypto = exports.printFlagDeprecation = exports.managementSDKInitiator = exports.managementSDKClient = exports.configHandler = exports.messageHandler = exports.CLIError = exports.cliux = exports.logger = void 0;
3
+ exports.stdout = exports.stderr = exports.execute = exports.ux = exports.flush = exports.settings = exports.toConfiguredId = exports.toStandardizedId = exports.tsPath = exports.toCached = exports.run = exports.Plugin = exports.Parser = exports.Interfaces = exports.HelpBase = exports.Help = exports.loadHelpClass = exports.Flags = exports.Errors = exports.Config = exports.CommandHelp = exports.Args = exports.Command = exports.flags = exports.args = exports.NodeCrypto = exports.printFlagDeprecation = exports.managementSDKInitiator = exports.managementSDKClient = exports.configHandler = exports.authHandler = exports.messageHandler = exports.CLIError = exports.cliux = exports.logger = void 0;
4
4
  const tslib_1 = require("tslib");
5
5
  var logger_1 = require("./logger");
6
6
  Object.defineProperty(exports, "logger", { enumerable: true, get: function () { return tslib_1.__importDefault(logger_1).default; } });
@@ -10,6 +10,8 @@ var cli_error_1 = require("./cli-error");
10
10
  Object.defineProperty(exports, "CLIError", { enumerable: true, get: function () { return tslib_1.__importDefault(cli_error_1).default; } });
11
11
  var message_handler_1 = require("./message-handler");
12
12
  Object.defineProperty(exports, "messageHandler", { enumerable: true, get: function () { return tslib_1.__importDefault(message_handler_1).default; } });
13
+ var auth_handler_1 = require("./auth-handler");
14
+ Object.defineProperty(exports, "authHandler", { enumerable: true, get: function () { return tslib_1.__importDefault(auth_handler_1).default; } });
13
15
  var config_handler_1 = require("./config-handler");
14
16
  Object.defineProperty(exports, "configHandler", { enumerable: true, get: function () { return tslib_1.__importDefault(config_handler_1).default; } });
15
17
  var contentstack_management_sdk_1 = require("./contentstack-management-sdk");
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@contentstack/cli-utilities",
3
- "version": "1.3.0",
3
+ "version": "1.3.2",
4
4
  "description": "Utilities for contentstack projects",
5
5
  "main": "lib/index.js",
6
6
  "types": "./types/index.d.ts",
@@ -41,6 +41,7 @@
41
41
  "inquirer-search-checkbox": "^1.0.0",
42
42
  "inquirer-search-list": "^1.2.6",
43
43
  "lodash": "^4.17.15",
44
+ "open": "^8.4.2",
44
45
  "ora": "^5.4.0",
45
46
  "unique-string": "^2.0.0",
46
47
  "uuid": "^9.0.0",
@@ -68,7 +69,7 @@
68
69
  "sinon": "^15.0.1",
69
70
  "tmp": "^0.2.1",
70
71
  "ts-node": "^10.9.1",
71
- "typescript": "^4.9.3",
72
- "tslib": "^1.13.0"
72
+ "tslib": "^1.13.0",
73
+ "typescript": "^4.9.3"
73
74
  }
74
- }
75
+ }
@@ -0,0 +1,45 @@
1
+ /**
2
+ * @class
3
+ * Auth handler
4
+ */
5
+ declare class AuthHandler {
6
+ private _client;
7
+ private _host;
8
+ private _appHost;
9
+ private codeVerifier;
10
+ private OAuthBaseURL;
11
+ private OAuthAppId;
12
+ private OAuthClientId;
13
+ private OAuthRedirectURL;
14
+ private OAuthScope;
15
+ private OAuthResponseType;
16
+ private authTokenKeyName;
17
+ private authEmailKeyName;
18
+ private oauthAccessTokenKeyName;
19
+ private oauthDateTimeKeyName;
20
+ private oauthUserUidKeyName;
21
+ private oauthOrgUidKeyName;
22
+ private oauthRefreshTokenKeyName;
23
+ private authorisationTypeKeyName;
24
+ private authorisationTypeOAUTHValue;
25
+ private authorisationTypeAUTHValue;
26
+ private allAuthConfigItems;
27
+ set host(contentStackHost: any);
28
+ constructor();
29
+ oauth(): Promise<object>;
30
+ createHTTPServer(): Promise<object>;
31
+ openOAuthURL(): Promise<object>;
32
+ getAccessToken(code: string): Promise<object>;
33
+ setConfigData(type: string, userData?: any): Promise<object>;
34
+ unsetConfigData(type?: string): Promise<void>;
35
+ refreshToken(): Promise<object>;
36
+ getUserDetails(data: any): Promise<object>;
37
+ isAuthenticated(): Promise<boolean>;
38
+ checkExpiryAndRefresh: (force?: boolean) => Promise<void | object>;
39
+ compareOAuthExpiry(force?: boolean): Promise<void | object>;
40
+ getAuthorisationType(): Promise<boolean>;
41
+ isAuthorisationTypeBasic(): Promise<boolean>;
42
+ isAuthorisationTypeOAuth(): Promise<boolean>;
43
+ }
44
+ declare const _default: AuthHandler;
45
+ export default _default;
@@ -1,11 +1,11 @@
1
1
  import { ContentstackClient, ContentstackConfig } from '@contentstack/management';
2
2
  declare class ManagementSDKInitiator {
3
- private analyticsInfo;
4
- constructor();
5
- init(context: any): void;
6
- createAPIClient(config: any): Promise<ContentstackClient>;
3
+ private analyticsInfo;
4
+ constructor();
5
+ init(context: any): void;
6
+ createAPIClient(config: any): Promise<ContentstackClient>;
7
7
  }
8
+ declare const _default: (config: any) => Promise<ContentstackClient>;
8
9
  export declare const managementSDKInitiator: ManagementSDKInitiator;
9
- declare const _default: any;
10
10
  export default _default;
11
11
  export { ContentstackConfig, ContentstackClient };
@@ -1,6 +1,7 @@
1
1
  import { AxiosRequestConfig, AxiosResponse } from 'axios';
2
+ import { IHttpClient } from './client-interface';
2
3
  import { HttpResponse } from './http-response';
3
- export declare class HttpClient {
4
+ export declare class HttpClient implements IHttpClient {
4
5
  /**
5
6
  * The request configuration.
6
7
  */
@@ -2,3 +2,5 @@ import { HttpClient } from './client';
2
2
  export default HttpClient;
3
3
  export * from './client';
4
4
  export * from './http-response';
5
+ export * from './http-client-decorator';
6
+ export * from './oauth-decorator';
package/types/index.d.ts CHANGED
@@ -2,12 +2,76 @@ export { default as logger } from './logger';
2
2
  export { default as cliux } from './cli-ux';
3
3
  export { default as CLIError } from './cli-error';
4
4
  export { default as messageHandler } from './message-handler';
5
+ export { default as authHandler } from './auth-handler';
5
6
  export { default as configHandler } from './config-handler';
6
- export { default as managementSDKClient, managementSDKInitiator, ContentstackClient, ContentstackConfig, } from './contentstack-management-sdk';
7
+ export {
8
+ default as managementSDKClient,
9
+ managementSDKInitiator,
10
+ ContentstackClient,
11
+ ContentstackConfig,
12
+ } from './contentstack-management-sdk';
7
13
  export { default as printFlagDeprecation } from './flag-deprecation-check';
8
14
  export * from './http-client';
9
15
  export { default as NodeCrypto } from './encrypter';
10
16
  export { Args as args, Flags as flags, Command } from './cli-ux';
17
+ export {
18
+ Args,
19
+ CommandHelp,
20
+ Config,
21
+ Errors,
22
+ Flags,
23
+ loadHelpClass,
24
+ Help,
25
+ HelpBase,
26
+ HelpSection,
27
+ HelpSectionRenderer,
28
+ HelpSectionKeyValueTable,
29
+ Hook,
30
+ Interfaces,
31
+ Parser,
32
+ Plugin,
33
+ run,
34
+ toCached,
35
+ tsPath,
36
+ toStandardizedId,
37
+ toConfiguredId,
38
+ settings,
39
+ Settings,
40
+ flush,
41
+ ux,
42
+ execute,
43
+ stderr,
44
+ stdout,
45
+ } from '@oclif/core';
46
+ export { FlagInput } from '@oclif/core/lib/interfaces/parser';
11
47
  export * from './helpers';
12
- export { Args, CommandHelp, Config, Errors, Flags, loadHelpClass, Help, HelpBase, HelpSection, HelpSectionRenderer, HelpSectionKeyValueTable, Hook, Interfaces, Parser, Plugin, run, toCached, tsPath, toStandardizedId, toConfiguredId, settings, Settings, flush, ux, execute, stderr, stdout, } from '@oclif/core';
48
+ export {
49
+ Args,
50
+ CommandHelp,
51
+ Config,
52
+ Errors,
53
+ Flags,
54
+ loadHelpClass,
55
+ Help,
56
+ HelpBase,
57
+ HelpSection,
58
+ HelpSectionRenderer,
59
+ HelpSectionKeyValueTable,
60
+ Hook,
61
+ Interfaces,
62
+ Parser,
63
+ Plugin,
64
+ run,
65
+ toCached,
66
+ tsPath,
67
+ toStandardizedId,
68
+ toConfiguredId,
69
+ settings,
70
+ Settings,
71
+ flush,
72
+ ux,
73
+ execute,
74
+ stderr,
75
+ stdout,
76
+ } from '@oclif/core';
13
77
  export { FlagInput } from '@oclif/core/lib/interfaces/parser';
@@ -0,0 +1,19 @@
1
+ declare class CustomAbortSignal {
2
+ aborted: any;
3
+ onabort: any;
4
+ eventEmitter: any;
5
+ constructor();
6
+ toString(): string;
7
+ get [Symbol.toStringTag](): string;
8
+ removeEventListener(name: any, handler: any): void;
9
+ addEventListener(name: any, handler: any): void;
10
+ dispatchEvent(type: any): void;
11
+ }
12
+ declare class CustomAbortController {
13
+ signal: any;
14
+ constructor();
15
+ abort(): void;
16
+ toString(): string;
17
+ get [Symbol.toStringTag](): string;
18
+ }
19
+ export { CustomAbortController, CustomAbortSignal };