@sap-ux/odata-service-inquirer 0.6.9 → 0.6.11

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.
@@ -179,6 +179,7 @@ export declare class ConnectionValidator {
179
179
  * @param connectConfig.serviceInfo the service info
180
180
  * @param connectConfig.odataVersion the odata version to restrict the catalog requests if only a specific version is required
181
181
  * @param connectConfig.destination the destination to connect with
182
+ * @param connectConfig.refreshToken
182
183
  * @throws an error if the connection attempt fails, callers should handle the error
183
184
  */
184
185
  private createSystemConnection;
@@ -200,6 +201,7 @@ export declare class ConnectionValidator {
200
201
  *
201
202
  * @param url the system url
202
203
  * @param serviceInfo the service info
204
+ * @param refreshToken
203
205
  * @returns the service provider
204
206
  */
205
207
  private getAbapOnCloudServiceProvider;
@@ -210,9 +212,10 @@ export declare class ConnectionValidator {
210
212
  *
211
213
  * @param serviceInfo the service info containing the UAA details
212
214
  * @param odataVersion the odata version to restrict the catalog requests if only a specific version is required
215
+ * @param refreshToken the refresh token for the Abap on Cloud environment, will be used to avoid re-authentication while the token is valid
213
216
  * @returns true if the system is reachable and authenticated, if required, false if not, or an error message string
214
217
  */
215
- validateServiceInfo(serviceInfo: ServiceInfo, odataVersion?: ODataVersion): Promise<ValidationResult>;
218
+ validateServiceInfo(serviceInfo: ServiceInfo, odataVersion?: ODataVersion, refreshToken?: string): Promise<ValidationResult>;
216
219
  /**
217
220
  * Validate the specified destination connectivity, determining if authentication is required or if the destination is misconfigured.
218
221
  *
@@ -299,13 +299,14 @@ class ConnectionValidator {
299
299
  * @param connectConfig.serviceInfo the service info
300
300
  * @param connectConfig.odataVersion the odata version to restrict the catalog requests if only a specific version is required
301
301
  * @param connectConfig.destination the destination to connect with
302
+ * @param connectConfig.refreshToken
302
303
  * @throws an error if the connection attempt fails, callers should handle the error
303
304
  */
304
- async createSystemConnection({ axiosConfig, url, serviceInfo, destination, odataVersion }) {
305
+ async createSystemConnection({ axiosConfig, url, serviceInfo, destination, odataVersion, refreshToken }) {
305
306
  this.resetConnectionState();
306
307
  this.resetValidity();
307
308
  if (this.systemAuthType === 'reentranceTicket' || this.systemAuthType === 'serviceKey') {
308
- this._serviceProvider = this.getAbapOnCloudServiceProvider(url, serviceInfo);
309
+ this._serviceProvider = this.getAbapOnCloudServiceProvider(url, serviceInfo, refreshToken);
309
310
  }
310
311
  else if (destination) {
311
312
  // Assumption: the destination configured URL is a valid URL, will be needed later for basic auth error handling
@@ -378,9 +379,10 @@ class ConnectionValidator {
378
379
  *
379
380
  * @param url the system url
380
381
  * @param serviceInfo the service info
382
+ * @param refreshToken
381
383
  * @returns the service provider
382
384
  */
383
- getAbapOnCloudServiceProvider(url, serviceInfo) {
385
+ getAbapOnCloudServiceProvider(url, serviceInfo, refreshToken) {
384
386
  if (this.systemAuthType === 'reentranceTicket' && url) {
385
387
  return (0, axios_extension_1.createForAbapOnCloud)({
386
388
  environment: axios_extension_1.AbapCloudEnvironment.EmbeddedSteampunk,
@@ -391,6 +393,7 @@ class ConnectionValidator {
391
393
  return (0, axios_extension_1.createForAbapOnCloud)({
392
394
  environment: axios_extension_1.AbapCloudEnvironment.Standalone,
393
395
  service: serviceInfo,
396
+ refreshToken,
394
397
  refreshTokenChangedCb: this.refreshTokenChangedCb.bind(this)
395
398
  });
396
399
  }
@@ -403,15 +406,16 @@ class ConnectionValidator {
403
406
  *
404
407
  * @param serviceInfo the service info containing the UAA details
405
408
  * @param odataVersion the odata version to restrict the catalog requests if only a specific version is required
409
+ * @param refreshToken the refresh token for the Abap on Cloud environment, will be used to avoid re-authentication while the token is valid
406
410
  * @returns true if the system is reachable and authenticated, if required, false if not, or an error message string
407
411
  */
408
- async validateServiceInfo(serviceInfo, odataVersion) {
412
+ async validateServiceInfo(serviceInfo, odataVersion, refreshToken) {
409
413
  if (!serviceInfo) {
410
414
  return false;
411
415
  }
412
416
  try {
413
417
  this.systemAuthType = 'serviceKey';
414
- await this.createSystemConnection({ serviceInfo, odataVersion });
418
+ await this.createSystemConnection({ serviceInfo, odataVersion, refreshToken });
415
419
  // Cache the user info
416
420
  this._connectedUserName = await this.serviceProvider.user();
417
421
  this._serviceInfo = serviceInfo;
@@ -476,15 +480,20 @@ class ConnectionValidator {
476
480
  this.resetValidity();
477
481
  // Get the destination URL in the BAS specific form <protocol>://<destinationName>.dest
478
482
  const destUrl = (0, btp_utils_1.getDestinationUrlForAppStudio)(destination.Name, servicePath);
479
- // Get the destination URL in the portable form <protocol>://<host>:<port>
480
- this._destinationUrl = servicePath ? new URL(`${destination.Host}${servicePath}`).toString() : destination.Host;
483
+ // Get the destination URL in the portable form <protocol>://<host>:<port>.
484
+ // We remove trailing slashes (up to 10, infinite would allow DOS attack) from the host to avoid double slashes when appending the service path.
485
+ this._destinationUrl = servicePath
486
+ ? destUrl.replace(`https://${destination.Name}.dest`, destination.Host.replace(/\/{1,10}$/, ''))
487
+ : destination.Host;
481
488
  this._destination = destination;
482
489
  // No need to apply sap-client as this happens automatically (from destination config) when going through the BAS proxy
483
490
  const status = await this.checkUrl(new URL(destUrl), undefined, undefined, {
484
491
  odataVersion: requiredOdataVersion
485
492
  });
486
- this._validatedUrl = destUrl;
487
493
  const validationResult = this.getValidationResultFromStatusCode(status);
494
+ if (this.validity.reachable && (!this.validity.authRequired || this.validity.authenticated)) {
495
+ this._validatedUrl = destUrl;
496
+ }
488
497
  if (!this.validity.reachable) {
489
498
  // Log the error
490
499
  const errorLog = prompt_helpers_1.errorHandler.logErrorMsgs(status);
@@ -41,7 +41,7 @@ async function connectWithBackendSystem(backendSystem, connectionValidator, requ
41
41
  });
42
42
  }
43
43
  else if (backendSystem.serviceKeys) {
44
- connectValResult = await connectionValidator.validateServiceInfo(backendSystem.serviceKeys);
44
+ connectValResult = await connectionValidator.validateServiceInfo(backendSystem.serviceKeys, (0, utils_1.convertODataVersionType)(requiredOdataVersion), backendSystem.refreshToken);
45
45
  }
46
46
  else if (backendSystem.authenticationType === 'basic' || !backendSystem.authenticationType) {
47
47
  let errorType;
@@ -93,7 +93,10 @@ async function getSystemConnectionQuestions(connectionValidator, promptOptions)
93
93
  type: promptOptions?.systemSelection?.useAutoComplete ? 'autocomplete' : 'list',
94
94
  name: types_1.promptNames.systemSelection,
95
95
  message: (0, i18n_1.t)('prompts.systemSelection.message'),
96
- hint: (0, i18n_1.t)('prompts.systemSelection.hint'),
96
+ guiOptions: {
97
+ breadcrumb: true,
98
+ hint: (0, i18n_1.t)('prompts.systemSelection.hint')
99
+ },
97
100
  source: (prevAnswers, input) => (0, inquirer_common_1.searchChoices)(input, systemChoices),
98
101
  choices: systemChoices,
99
102
  default: defaultChoiceIndex,
@@ -137,16 +140,22 @@ async function getSystemConnectionQuestions(connectionValidator, promptOptions)
137
140
  guiOptions: {
138
141
  hint: (0, i18n_1.t)('prompts.destinationServicePath.hint'),
139
142
  mandatory: true,
140
- breadcrumb: true
143
+ breadcrumb: true,
144
+ applyDefaultWhenDirty: true
141
145
  },
146
+ default: '',
142
147
  validate: async (servicePath, answers) => {
143
- if (!servicePath) {
148
+ // @sap-ux/btp-utils getDestinationUrlForAppStudio() enforces a path length of > 1, even though it could be a valid path
149
+ // Double slashes are not allowed at the start of the path as they break URL construction
150
+ if (!servicePath || servicePath.trim().length < 2 || servicePath.startsWith('//')) {
151
+ connectionValidator.resetConnectionState(true);
144
152
  return (0, i18n_1.t)('prompts.destinationServicePath.invalidServicePathWarning');
145
153
  }
146
154
  // Validate format of the service path, note this relies on the assumption that the destination is correctly configured with a valid URL
147
155
  const selectedDestination = answers?.[types_1.promptNames.systemSelection]?.system;
148
156
  const valUrlResult = (0, validators_1.validateServiceUrl)(selectedDestination.Host, servicePath);
149
157
  if (valUrlResult !== true) {
158
+ connectionValidator.resetConnectionState(true);
150
159
  return valUrlResult;
151
160
  }
152
161
  const connectValResult = await (0, prompt_helpers_1.connectWithDestination)(selectedDestination, connectionValidator, requiredOdataVersion, servicePath);
@@ -61,7 +61,7 @@
61
61
  "annotationsNotFound": "Annotations not found for specified service"
62
62
  },
63
63
  "warnings": {
64
- "nonUIServiceTypeWarningMessage": "Please note that {{serviceType}} services are not intended to be used for the generation of SAP Fiori UI applications",
64
+ "nonUIServiceTypeWarningMessage": "Please note that {{serviceType}} services, or not classified services, are not intended to be used for the generation of SAP Fiori UI applications",
65
65
  "noServicesAvailable": "No services available for the selected system, see logs for further details.",
66
66
  "noServicesAvailableForOdataVersion": "There are no V{{odataVersion}} OData services available from the selected system and the template you have chosen supports V{{odataVersion}} OData services only"
67
67
  },
package/package.json CHANGED
@@ -1,7 +1,7 @@
1
1
  {
2
2
  "name": "@sap-ux/odata-service-inquirer",
3
3
  "description": "Prompts module that can prompt users for inputs required for odata service writing",
4
- "version": "0.6.9",
4
+ "version": "0.6.11",
5
5
  "repository": {
6
6
  "type": "git",
7
7
  "url": "https://github.com/SAP/open-ux-tools.git",
@@ -26,15 +26,15 @@
26
26
  "i18next": "23.5.1",
27
27
  "inquirer-autocomplete-prompt": "2.0.1",
28
28
  "os-name": "4.0.1",
29
- "@sap-ux/axios-extension": "1.17.4",
30
- "@sap-ux/fiori-generator-shared": "0.7.10",
31
29
  "@sap-ux/btp-utils": "0.17.0",
32
30
  "@sap-ux/guided-answers-helper": "0.1.0",
33
- "@sap-ux/inquirer-common": "0.5.4",
34
31
  "@sap-ux/telemetry": "0.5.44",
35
- "@sap-ux/logger": "0.6.0",
32
+ "@sap-ux/axios-extension": "1.17.4",
33
+ "@sap-ux/fiori-generator-shared": "0.7.10",
34
+ "@sap-ux/inquirer-common": "0.5.4",
36
35
  "@sap-ux/project-access": "1.28.7",
37
36
  "@sap-ux/project-input-validator": "0.3.3",
37
+ "@sap-ux/logger": "0.6.0",
38
38
  "@sap-ux/store": "0.9.3"
39
39
  },
40
40
  "devDependencies": {