@sap/cds-dk 4.9.5 → 4.9.6

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/CHANGELOG.md CHANGED
@@ -6,6 +6,17 @@ This project adheres to [Semantic Versioning](http://semver.org/).
6
6
 
7
7
  The format is based on [Keep a Changelog](http://keepachangelog.com/).
8
8
 
9
+ ## Version 4.9.6 - 2022-06-08
10
+
11
+ ### Changed
12
+
13
+ - Include `@sap/cds` 5.9.6
14
+
15
+ ### Fixed
16
+
17
+ - `cds login` (and `cds extend`, `cds activate` if previously logged in) now properly renew token URL
18
+ - Improved logging during those commands
19
+
9
20
  ## Version 4.9.5 - 2022-05-17
10
21
 
11
22
  ### Changed
@@ -47,7 +47,12 @@ function escapeRegex(str) {
47
47
  return str.replace(/[.*+?^${}()|[\]\\]/g, '\\$&');
48
48
  }
49
49
 
50
+ function capitalize(str) {
51
+ return str.charAt(0).toUpperCase() + str.slice(1);
52
+ }
53
+
50
54
  module.exports = {
51
55
  formatObjectsFixedWidth,
52
- escapeRegex
56
+ escapeRegex,
57
+ capitalize
53
58
  };
@@ -12,6 +12,7 @@ const Logger = require('./helper/logging');
12
12
  const Question = require('./helper/question');
13
13
  const { defaultSchema, extractSubdomain, schemaRegex } = require('./helper/url_helper');
14
14
  const { ParamCollection, Persistence } = require('./params');
15
+ const { capitalize } = require('./helper/string_helper');
15
16
 
16
17
  const CONFIG_SUBDIRS = {
17
18
  linux: '.config',
@@ -107,7 +108,7 @@ function getKeyringAccountName(params) {
107
108
 
108
109
  function logConfigPaths() {
109
110
  Logger.debug(`Settings are stored in ${CONFIG.paths.settings}`);
110
- Logger.debug(`Authentication data is stored in ${CONFIG.paths.auth} or keyring ('${CONFIG.keyringDesignation}' on this platform)`);
111
+ Logger.debug(`Authentication data is stored in ${CONFIG.paths.auth} (${TOKEN_STORAGE_DESC.plain}) or ${CONFIG.keyringDesignation} (${TOKEN_STORAGE_DESC.keyring})`);
111
112
  }
112
113
 
113
114
  function notifyLoggedIn(params) {
@@ -133,9 +134,6 @@ class SettingsManager {
133
134
  // Call with 'projectFolder' param as a resolved path.
134
135
  static async saveSettings(params) {
135
136
  Logger.debug(`Saving settings for project ${params.get('projectFolder')}`);
136
- if (params.has('token') && ! params.has('tokenStorage')) {
137
- Logger.log('Note: the authentication token is not saved by default. To save the token for later commands, please run `cds login`.');
138
- }
139
137
 
140
138
  await this._saveToFile(params.get('projectFolder'), params.toValueMap(Persistence.setting));
141
139
 
@@ -153,6 +151,8 @@ class SettingsManager {
153
151
  await this._saveAuthToFile(params, params.toValueMap(Persistence.auth));
154
152
  } else if (params.get('tokenStorage') === 'keyring') {
155
153
  await this._saveAuthToKeyring(params, params.toValueMap(Persistence.auth));
154
+ } else {
155
+ Logger.log('Note: the authentication token is not saved by default. To save the token for later commands, please run `cds login`.');
156
156
  }
157
157
  }
158
158
 
@@ -160,19 +160,19 @@ class SettingsManager {
160
160
  const projectFolder = getProjectFolder(params);
161
161
  params.set('projectFolder', projectFolder);
162
162
 
163
- Logger.debug(`Loading settings for project ${projectFolder}`);
164
163
  const loadedSettings = await this._loadFromFile(projectFolder);
165
- Logger.debug(`Loaded project settings: ${loadedSettings.format()}`);
164
+ Logger.debug(`Loaded project settings for ${params.get('projectFolder')}: ${loadedSettings.format()}`);
165
+ const loadedAppUrl = loadedSettings.get('appUrl');
166
166
 
167
167
  params.mergeLower(loadedSettings);
168
168
 
169
- await this.updateUrls(params, logout);
169
+ await this.updateUrls(params, logout, loadedAppUrl);
170
170
  await this.checkKeytar(params, logout);
171
171
  await this.addAuth(params, logout);
172
172
  Logger.debug(`Effective project settings: ${params.format()}`);
173
173
  }
174
174
 
175
- static async updateUrls(params, logout) {
175
+ static async updateUrls(params, logout, loadedAppUrl) {
176
176
  async function addAppUrlAndSubdomain() {
177
177
  if (params.has('appUrl') && !schemaRegex.test(params.get('appUrl'))) {
178
178
  params.set('appUrl', defaultSchema + params.get('appUrl'));
@@ -202,7 +202,7 @@ class SettingsManager {
202
202
  }
203
203
  }
204
204
  function renewTokenUrl() {
205
- const renewUrl = params.get('appUrl') !== params.get('appUrl');
205
+ const renewUrl = params.get('appUrl') !== loadedAppUrl;
206
206
  if (!params.get('tokenUrl') || renewUrl) {
207
207
  params.set('tokenUrl', getTokenBaseUrl(params, renewUrl));
208
208
  }
@@ -218,7 +218,7 @@ class SettingsManager {
218
218
  static async checkKeytar(params, logout) {
219
219
  if (isBas()) {
220
220
  if (params.get('tokenStorage') === 'keyring') {
221
- Logger.log(`NOTE: Keyring storage not supported on SAP Business Application Studio. Switching to plain-text storage.`);
221
+ Logger.log(`NOTE: ${capitalize(TOKEN_STORAGE_DESC.keyring)} not supported on SAP Business Application Studio. Switching to ${TOKEN_STORAGE_DESC.plain}.`);
222
222
  params.set('tokenStorage', 'plain');
223
223
  }
224
224
  return;
@@ -227,11 +227,11 @@ class SettingsManager {
227
227
  return;
228
228
  }
229
229
  if (params.get('tokenStorage') === 'keyring') {
230
- throw new Error('Keyring storage requested but keytar not installed. Please run `npm install -g keytar` or ' +
231
- 'switch to plain-text storage by adding `--plain` (discouraged).');
230
+ throw new Error(`${capitalize(TOKEN_STORAGE_DESC.keyring)} requested but keytar not installed. Run 'npm install -g keytar' or ` +
231
+ `switch to ${TOKEN_STORAGE_DESC.plain} by adding '--plain' (discouraged).`);
232
232
  }
233
233
  if (params.get('renewLogin') || logout) {
234
- Logger.log('Disabling keyring functionality: \'keytar\' module not found. Run `npm install -g keytar` to install it.');
234
+ Logger.log(`Disabling ${TOKEN_STORAGE_DESC.keyring} functionality: 'keytar' module not found. Run 'npm install -g keytar' to install it.`);
235
235
  }
236
236
  }
237
237
 
@@ -288,8 +288,6 @@ class SettingsManager {
288
288
  }
289
289
  }
290
290
 
291
- Logger.debug(`Consolidating authentication data for project ${params.get('projectFolder')}`);
292
-
293
291
  if (params.has('username')) {
294
292
  if (!params.get('password') && !logout) {
295
293
  await addPassword();
@@ -325,7 +323,7 @@ class SettingsManager {
325
323
 
326
324
  fromStorage = fromStorage || allParams.get('tokenStorage');
327
325
  if (!fromStorage) {
328
- Logger.log(`No authentication data found for ${target}`);
326
+ Logger.log(`Failed to delete authentication data: none found for ${target}`);
329
327
  return;
330
328
  }
331
329
 
@@ -339,13 +337,10 @@ class SettingsManager {
339
337
 
340
338
  static async deleteSettingsWithoutToken(params) {
341
339
  const projectFolder = getProjectFolder(params);
342
- Logger.debug(`Deleting settings for project ${projectFolder}`);
343
340
  await this._saveToFile(projectFolder, null);
344
341
  }
345
342
 
346
343
  static async deleteInvalid() {
347
- Logger.log('Deleting invalid project settings');
348
-
349
344
  const settingsByFolder = await this._loadFromFile(undefined);
350
345
  const deletionFolders = [];
351
346
  const deletionUrlsAndSubdomains = new Set();
@@ -395,11 +390,10 @@ class SettingsManager {
395
390
  }
396
391
 
397
392
  static async _saveAuthToFile(params, authValues) {
398
- Logger.debug(`Updating authentication data to ${CONFIG.paths.auth}`);
399
393
  const appUrl = params.get('appUrl');
400
- const location = `plain-text storage for app URL ${appUrl}, subdomain ${params.get('subdomain')}`;
401
-
394
+ const location = `${TOKEN_STORAGE_DESC.plain} at ${CONFIG.paths.auth} for app URL ${appUrl}, subdomain ${params.get('subdomain')}`;
402
395
  const allAuthValues = await this._loadAuthFromFile(undefined, undefined);
396
+
403
397
  if (authValues !== null) {
404
398
  (allAuthValues[appUrl] || (allAuthValues[appUrl] = {}))[params.get('subdomain')] = authValues;
405
399
  await fse.outputJson(CONFIG.paths.auth, allAuthValues, { spaces: 2 });
@@ -412,7 +406,7 @@ class SettingsManager {
412
406
  await fse.outputJson(CONFIG.paths.auth, allAuthValues, { spaces: 2 });
413
407
  Logger.log(`Deleted authentication data from ${location}`);
414
408
  } else {
415
- Logger.log(`No authentication data to delete from ${location}`);
409
+ notifyLoggedIn(params)(`No authentication data to delete from ${location}`);
416
410
  }
417
411
  }
418
412
 
@@ -421,8 +415,7 @@ class SettingsManager {
421
415
  return;
422
416
  }
423
417
 
424
- Logger.debug('Updating authentication data to keyring');
425
- const location = `keyring for app URL ${params.get('appUrl')}, subdomain ${params.get('subdomain')}`;
418
+ const location = `${TOKEN_STORAGE_DESC.keyring} for app URL ${params.get('appUrl')}, subdomain ${params.get('subdomain')}`;
426
419
 
427
420
  if (auth !== null) {
428
421
  await keytar.setPassword(MTX_FULLY_QUALIFIED, getKeyringAccountName(params), JSON.stringify(auth));
@@ -437,11 +430,10 @@ class SettingsManager {
437
430
  const all = !projectFolder;
438
431
 
439
432
  if (!fs.existsSync(CONFIG.paths.settings)) {
440
- Logger.debug('Settings file absent');
433
+ Logger.debug('Settings file not found');
441
434
  return emptyData(all);
442
435
  }
443
436
 
444
- Logger.debug('Reading settings file');
445
437
  const settingsByFolder = await fse.readJson(CONFIG.paths.settings);
446
438
 
447
439
  if (!settingsByFolder) {
@@ -465,15 +457,14 @@ class SettingsManager {
465
457
  const all = !appUrl;
466
458
 
467
459
  if (!fs.existsSync(CONFIG.paths.auth)) {
468
- Logger.debug('Authentication-data file absent');
460
+ Logger.debug('Authentication-data file not found');
469
461
  return emptyData(all);
470
462
  }
471
463
 
472
- Logger.debug(`Reading authentication data from ${CONFIG.paths.auth}`);
473
464
  const allAuth = await fse.readJson(CONFIG.paths.auth);
474
465
 
475
466
  if (!allAuth) {
476
- Logger.debug('Empty authentication data');
467
+ Logger.debug('Empty authentication-data file');
477
468
  return emptyData(all);
478
469
  }
479
470
 
@@ -482,14 +473,14 @@ class SettingsManager {
482
473
  }
483
474
 
484
475
  if (!allAuth[appUrl]) {
485
- Logger.debug(`No authentication data found for app URL ${appUrl}`);
476
+ Logger.debug(`File contains no authentication data for app URL ${appUrl}`);
486
477
  return new ParamCollection();
487
478
  }
488
479
 
489
480
  const authForSubdomain = allAuth[appUrl][subdomain];
490
481
 
491
482
  if (!authForSubdomain) {
492
- Logger.debug(`No authentication data found for subdomain ${subdomain}`);
483
+ Logger.debug(`File contains no authentication data for subdomain ${subdomain} (app URL: ${appUrl})`);
493
484
  return new ParamCollection();
494
485
  }
495
486
 
@@ -505,12 +496,10 @@ class SettingsManager {
505
496
  return new ParamCollection();
506
497
  }
507
498
 
508
- Logger.debug('Reading authentication data from keyring');
509
-
510
499
  const authString = await keytar.getPassword(MTX_FULLY_QUALIFIED, getKeyringAccountName(new ParamCollection({ appUrl, subdomain })));
511
500
 
512
501
  if (!authString) {
513
- Logger.debug(`No authentication data found for URL ${appUrl} and subdomain '${subdomain}'`);
502
+ Logger.debug(`${capitalize(TOKEN_STORAGE_DESC.keyring)} contains no authentication data for URL ${appUrl} and subdomain '${subdomain}'`);
514
503
  return new ParamCollection();
515
504
  }
516
505