@sap-ux/odata-service-inquirer 0.5.3 → 0.5.5
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/dist/prompts/connectionValidator.d.ts +12 -1
- package/dist/prompts/connectionValidator.js +55 -7
- package/dist/prompts/datasources/sap-system/abap-on-prem/questions.js +13 -4
- package/dist/prompts/datasources/sap-system/new-system/questions.js +8 -5
- package/dist/prompts/datasources/sap-system/validators.d.ts +1 -2
- package/dist/prompts/datasources/sap-system/validators.js +4 -2
- package/dist/translations/odata-service-inquirer.i18n.json +3 -2
- package/package.json +2 -2
|
@@ -21,6 +21,7 @@ type ValidationResult = string | boolean | IValidationLink;
|
|
|
21
21
|
export declare class ConnectionValidator {
|
|
22
22
|
readonly validity: Validity;
|
|
23
23
|
private _validatedUrl;
|
|
24
|
+
private _validatedClient;
|
|
24
25
|
private _odataService;
|
|
25
26
|
private _serviceProvider;
|
|
26
27
|
private _axiosConfig;
|
|
@@ -93,7 +94,7 @@ export declare class ConnectionValidator {
|
|
|
93
94
|
* @param serviceUrl the odata service url to validate
|
|
94
95
|
* @param options options for the connection validation
|
|
95
96
|
* @param options.ignoreCertError ignore some certificate errors
|
|
96
|
-
* @param options.forceReValidation force re-validation of the url
|
|
97
|
+
* @param options.forceReValidation force re-validation of the url even if the same url has been prevously validated
|
|
97
98
|
* @param options.isSystem if true, the url will be treated as a system url rather than a service url
|
|
98
99
|
* @param options.odataVersion if specified will restrict catalog requests to only the specified odata version
|
|
99
100
|
* @returns true if the url is reachable, false if not, or an error message string
|
|
@@ -126,6 +127,16 @@ export declare class ConnectionValidator {
|
|
|
126
127
|
* @returns true if the url has already been validated
|
|
127
128
|
*/
|
|
128
129
|
private isUrlValidated;
|
|
130
|
+
/**
|
|
131
|
+
* Check whether basic auth is required for the given url, or for the previously validated url if none specified.
|
|
132
|
+
* This will also set the validity state for the url. This will not validate the URL.
|
|
133
|
+
*
|
|
134
|
+
* @param urlString - the url to validate, if not provided the previously validated url will be used
|
|
135
|
+
* @param client - optional, sap client code, if not provided the previously validated client will be used
|
|
136
|
+
* @param ignoreCertError
|
|
137
|
+
* @returns true if basic auth is required, false if not
|
|
138
|
+
*/
|
|
139
|
+
isAuthRequired(urlString?: string | undefined, client?: string | undefined, ignoreCertError?: boolean): Promise<boolean>;
|
|
129
140
|
/**
|
|
130
141
|
* Test the connectivity with the specified service url using the provided credentials.
|
|
131
142
|
*
|
|
@@ -22,7 +22,10 @@ const ignorableCertErrors = [error_handler_1.ERROR_TYPE.CERT_SELF_SIGNED, error_
|
|
|
22
22
|
*/
|
|
23
23
|
class ConnectionValidator {
|
|
24
24
|
validity = {};
|
|
25
|
+
// The current valid url (not necessarily authenticated but the url is in a valid format)
|
|
25
26
|
_validatedUrl;
|
|
27
|
+
// The current client code used for requests, the client code has been validated by a successful request
|
|
28
|
+
_validatedClient;
|
|
26
29
|
_odataService;
|
|
27
30
|
_serviceProvider;
|
|
28
31
|
_axiosConfig;
|
|
@@ -97,6 +100,7 @@ class ConnectionValidator {
|
|
|
97
100
|
// Full service URL
|
|
98
101
|
await this.createServiceConnection(axiosConfig, url.pathname);
|
|
99
102
|
}
|
|
103
|
+
this._validatedClient = url.searchParams.get(types_1.SAP_CLIENT_KEY) ?? undefined;
|
|
100
104
|
return 200;
|
|
101
105
|
}
|
|
102
106
|
catch (e) {
|
|
@@ -191,7 +195,7 @@ class ConnectionValidator {
|
|
|
191
195
|
* @param serviceUrl the odata service url to validate
|
|
192
196
|
* @param options options for the connection validation
|
|
193
197
|
* @param options.ignoreCertError ignore some certificate errors
|
|
194
|
-
* @param options.forceReValidation force re-validation of the url
|
|
198
|
+
* @param options.forceReValidation force re-validation of the url even if the same url has been prevously validated
|
|
195
199
|
* @param options.isSystem if true, the url will be treated as a system url rather than a service url
|
|
196
200
|
* @param options.odataVersion if specified will restrict catalog requests to only the specified odata version
|
|
197
201
|
* @returns true if the url is reachable, false if not, or an error message string
|
|
@@ -224,7 +228,7 @@ class ConnectionValidator {
|
|
|
224
228
|
// More helpful context specific error
|
|
225
229
|
if (error_handler_1.ErrorHandler.getErrorType(error) === error_handler_1.ERROR_TYPE.CONNECTION) {
|
|
226
230
|
this.validity.reachable = false;
|
|
227
|
-
return prompt_helpers_1.errorHandler.logErrorMsgs((0, i18n_1.t)('errors.
|
|
231
|
+
return prompt_helpers_1.errorHandler.logErrorMsgs((0, i18n_1.t)('errors.systemOrserviceUrlNotFound', { url: serviceUrl }));
|
|
228
232
|
}
|
|
229
233
|
this.resetValidity();
|
|
230
234
|
const errorMsg = prompt_helpers_1.errorHandler.getErrorMsg(error);
|
|
@@ -240,10 +244,10 @@ class ConnectionValidator {
|
|
|
240
244
|
*/
|
|
241
245
|
getValidationResultFromStatusCode(status) {
|
|
242
246
|
if (status === 200) {
|
|
247
|
+
this.validity.reachable = true;
|
|
243
248
|
this.validity.authenticated = true;
|
|
244
|
-
this.validity.authRequired = false;
|
|
245
249
|
}
|
|
246
|
-
else if (status ===
|
|
250
|
+
else if (error_handler_1.ErrorHandler.getErrorType(status) === error_handler_1.ERROR_TYPE.NOT_FOUND) {
|
|
247
251
|
this.validity.reachable = false;
|
|
248
252
|
return error_handler_1.ErrorHandler.getErrorMsgFromType(error_handler_1.ERROR_TYPE.NOT_FOUND) ?? false;
|
|
249
253
|
}
|
|
@@ -255,12 +259,13 @@ class ConnectionValidator {
|
|
|
255
259
|
else if (error_handler_1.ErrorHandler.getErrorType(status) === error_handler_1.ERROR_TYPE.AUTH) {
|
|
256
260
|
this.validity.reachable = true;
|
|
257
261
|
this.validity.authRequired = true;
|
|
262
|
+
this.validity.authenticated = false;
|
|
258
263
|
}
|
|
259
264
|
else if (error_handler_1.ErrorHandler.getErrorType(status) === error_handler_1.ERROR_TYPE.REDIRECT) {
|
|
260
265
|
this.validity.reachable = true;
|
|
261
266
|
return (0, i18n_1.t)('errors.urlRedirect');
|
|
262
267
|
}
|
|
263
|
-
else if (status
|
|
268
|
+
else if (error_handler_1.ErrorHandler.getErrorType(status) === error_handler_1.ERROR_TYPE.CONNECTION) {
|
|
264
269
|
this.validity.reachable = false;
|
|
265
270
|
return error_handler_1.ErrorHandler.getErrorMsgFromType(error_handler_1.ERROR_TYPE.CONNECTION, `http code: ${status}`) ?? false;
|
|
266
271
|
}
|
|
@@ -289,6 +294,40 @@ class ConnectionValidator {
|
|
|
289
294
|
this.resetValidity();
|
|
290
295
|
return false;
|
|
291
296
|
}
|
|
297
|
+
/**
|
|
298
|
+
* Check whether basic auth is required for the given url, or for the previously validated url if none specified.
|
|
299
|
+
* This will also set the validity state for the url. This will not validate the URL.
|
|
300
|
+
*
|
|
301
|
+
* @param urlString - the url to validate, if not provided the previously validated url will be used
|
|
302
|
+
* @param client - optional, sap client code, if not provided the previously validated client will be used
|
|
303
|
+
* @param ignoreCertError
|
|
304
|
+
* @returns true if basic auth is required, false if not
|
|
305
|
+
*/
|
|
306
|
+
async isAuthRequired(urlString = this._validatedUrl, client = this._validatedClient, ignoreCertError = false) {
|
|
307
|
+
if (!urlString) {
|
|
308
|
+
return false;
|
|
309
|
+
}
|
|
310
|
+
// Dont re-request if already validated
|
|
311
|
+
if (this._validatedUrl === urlString &&
|
|
312
|
+
this._validatedClient === client &&
|
|
313
|
+
this.validity.authRequired !== undefined) {
|
|
314
|
+
return this.validity.authRequired;
|
|
315
|
+
}
|
|
316
|
+
// New URL or client so we need to re-request
|
|
317
|
+
try {
|
|
318
|
+
const url = new URL(urlString);
|
|
319
|
+
if (client) {
|
|
320
|
+
url.searchParams.append(types_1.SAP_CLIENT_KEY, client);
|
|
321
|
+
}
|
|
322
|
+
this.validity.authRequired = this.validity.reachable =
|
|
323
|
+
error_handler_1.ErrorHandler.getErrorType(await this.checkSapService(url, undefined, undefined, { ignoreCertError })) === error_handler_1.ERROR_TYPE.AUTH;
|
|
324
|
+
return this.validity.authRequired;
|
|
325
|
+
}
|
|
326
|
+
catch (error) {
|
|
327
|
+
prompt_helpers_1.errorHandler.logErrorMsgs(error);
|
|
328
|
+
return false; // Cannot determine if auth required
|
|
329
|
+
}
|
|
330
|
+
}
|
|
292
331
|
/**
|
|
293
332
|
* Test the connectivity with the specified service url using the provided credentials.
|
|
294
333
|
*
|
|
@@ -316,9 +355,18 @@ class ConnectionValidator {
|
|
|
316
355
|
isSystem,
|
|
317
356
|
odataVersion
|
|
318
357
|
});
|
|
358
|
+
logger_helper_1.default.logger.debug(`ConnectionValidator.validateUrl() - status: ${status}; url: ${url}`);
|
|
359
|
+
// Since an exception was not thrown, this is a valid url
|
|
360
|
+
this.validity.urlFormat = true;
|
|
361
|
+
this._validatedUrl = url;
|
|
319
362
|
const valResult = this.getValidationResultFromStatusCode(status);
|
|
320
|
-
if (valResult === true
|
|
321
|
-
|
|
363
|
+
if (valResult === true) {
|
|
364
|
+
if (this.validity.authenticated === true) {
|
|
365
|
+
return true;
|
|
366
|
+
}
|
|
367
|
+
else if (this.validity.authenticated === false) {
|
|
368
|
+
return (0, i18n_1.t)('errors.authenticationFailed');
|
|
369
|
+
}
|
|
322
370
|
}
|
|
323
371
|
return valResult;
|
|
324
372
|
}
|
|
@@ -149,6 +149,7 @@ exports.getAbapOnPremQuestions = getAbapOnPremQuestions;
|
|
|
149
149
|
*/
|
|
150
150
|
function getAbapOnPremSystemQuestions(systemNamePromptOptions, connectionValidator, requiredOdataVersion) {
|
|
151
151
|
const connectValidator = connectionValidator ?? new connectionValidator_1.ConnectionValidator();
|
|
152
|
+
let validClient = true;
|
|
152
153
|
const questions = [
|
|
153
154
|
{
|
|
154
155
|
type: 'input',
|
|
@@ -179,10 +180,18 @@ function getAbapOnPremSystemQuestions(systemNamePromptOptions, connectionValidat
|
|
|
179
180
|
guiOptions: {
|
|
180
181
|
breadcrumb: (0, i18n_1.t)('prompts.sapClient.breadcrumb')
|
|
181
182
|
},
|
|
182
|
-
validate:
|
|
183
|
+
validate: (client) => {
|
|
184
|
+
const valRes = (0, project_input_validator_1.validateClient)(client);
|
|
185
|
+
if (valRes === true) {
|
|
186
|
+
validClient = true;
|
|
187
|
+
return true;
|
|
188
|
+
}
|
|
189
|
+
validClient = false;
|
|
190
|
+
return valRes;
|
|
191
|
+
}
|
|
183
192
|
},
|
|
184
193
|
{
|
|
185
|
-
when: () =>
|
|
194
|
+
when: () => connectValidator.isAuthRequired(),
|
|
186
195
|
type: 'input',
|
|
187
196
|
name: abapOnPremInternalPromptNames.systemUsername,
|
|
188
197
|
message: (0, i18n_1.t)('prompts.systemUsername.message'),
|
|
@@ -192,7 +201,7 @@ function getAbapOnPremSystemQuestions(systemNamePromptOptions, connectionValidat
|
|
|
192
201
|
validate: (user) => user?.length > 0
|
|
193
202
|
},
|
|
194
203
|
{
|
|
195
|
-
when: () =>
|
|
204
|
+
when: () => connectValidator.isAuthRequired(),
|
|
196
205
|
type: 'password',
|
|
197
206
|
guiOptions: {
|
|
198
207
|
mandatory: true
|
|
@@ -202,7 +211,7 @@ function getAbapOnPremSystemQuestions(systemNamePromptOptions, connectionValidat
|
|
|
202
211
|
guiType: 'login',
|
|
203
212
|
mask: '*',
|
|
204
213
|
validate: async (password, { systemUrl, abapSystemUsername, sapClient }) => {
|
|
205
|
-
if (!(systemUrl && abapSystemUsername && password)) {
|
|
214
|
+
if (!(systemUrl && abapSystemUsername && password && validClient)) {
|
|
206
215
|
return false;
|
|
207
216
|
}
|
|
208
217
|
const valResult = await connectValidator.validateAuth(systemUrl, abapSystemUsername, password, {
|
|
@@ -64,6 +64,7 @@ exports.getNewSystemQuestions = getNewSystemQuestions;
|
|
|
64
64
|
*/
|
|
65
65
|
function getUserSystemNameQuestion() {
|
|
66
66
|
let defaultSystemName;
|
|
67
|
+
let userModifiedSystemName = false;
|
|
67
68
|
const newSystemNamePrompt = {
|
|
68
69
|
type: 'input',
|
|
69
70
|
guiOptions: {
|
|
@@ -74,19 +75,21 @@ function getUserSystemNameQuestion() {
|
|
|
74
75
|
name: types_1.promptNames.userSystemName,
|
|
75
76
|
message: (0, i18n_1.t)('prompts.systemName.message'),
|
|
76
77
|
default: async (answers) => {
|
|
77
|
-
if (answers.newSystemType === 'abapOnPrem' && answers.systemUrl) {
|
|
78
|
+
if (answers.newSystemType === 'abapOnPrem' && answers.systemUrl && !userModifiedSystemName) {
|
|
78
79
|
defaultSystemName = await (0, prompt_helpers_1.suggestSystemName)(answers.systemUrl, answers.sapClient);
|
|
80
|
+
return defaultSystemName;
|
|
79
81
|
}
|
|
80
|
-
return
|
|
82
|
+
return answers.userSystemName;
|
|
81
83
|
},
|
|
82
84
|
validate: async (systemName, answers) => {
|
|
83
|
-
let validationResult = false;
|
|
84
85
|
// Dont validate the suggested default system name
|
|
85
86
|
if (systemName === defaultSystemName) {
|
|
86
|
-
|
|
87
|
+
return true;
|
|
87
88
|
}
|
|
88
|
-
validationResult = await (0, validators_1.validateSystemName)(systemName);
|
|
89
|
+
const validationResult = await (0, validators_1.validateSystemName)(systemName);
|
|
89
90
|
if (validationResult === true) {
|
|
91
|
+
// Not the default system name, so the user modified
|
|
92
|
+
userModifiedSystemName = true;
|
|
90
93
|
const backendSystem = new store_1.BackendSystem({
|
|
91
94
|
name: systemName,
|
|
92
95
|
url: answers.systemUrl,
|
|
@@ -3,6 +3,5 @@
|
|
|
3
3
|
*
|
|
4
4
|
* @param systemName a system name to validate
|
|
5
5
|
* @returns true if the name is valid, otherwise an error message
|
|
6
|
-
*/
|
|
7
|
-
export declare function validateSystemName(systemName: string): Promise<boolean | string>;
|
|
6
|
+
*/ export declare function validateSystemName(systemName: string): Promise<boolean | string>;
|
|
8
7
|
//# sourceMappingURL=validators.d.ts.map
|
|
@@ -22,8 +22,10 @@ async function isSystemNameInUse(systemName) {
|
|
|
22
22
|
*
|
|
23
23
|
* @param systemName a system name to validate
|
|
24
24
|
* @returns true if the name is valid, otherwise an error message
|
|
25
|
-
*/
|
|
26
|
-
|
|
25
|
+
*/ async function validateSystemName(systemName) {
|
|
26
|
+
if (!systemName) {
|
|
27
|
+
return (0, i18n_1.t)('prompts.systemName.emptySystemNameWarning');
|
|
28
|
+
}
|
|
27
29
|
const systemExists = await isSystemNameInUse(systemName);
|
|
28
30
|
if (systemExists) {
|
|
29
31
|
return (0, i18n_1.t)('prompts.systemName.systemNameExistsWarning');
|
|
@@ -95,7 +95,8 @@
|
|
|
95
95
|
"message": "System name",
|
|
96
96
|
"hint": "Entering a system name will save the connection for re-use.",
|
|
97
97
|
"systemNameExistsWarning": "A system with that name already exists in the secure storage. Please try a different name.",
|
|
98
|
-
"reservedSystemNameWarning": "'{{ systemName }}' is a reserved system name. Please try a different name."
|
|
98
|
+
"reservedSystemNameWarning": "'{{ systemName }}' is a reserved system name. Please try a different name.",
|
|
99
|
+
"emptySystemNameWarning": "System name cannot be empty."
|
|
99
100
|
},
|
|
100
101
|
"systemSelection": {
|
|
101
102
|
"newSystemChoiceLabel": "New system"
|
|
@@ -128,7 +129,7 @@
|
|
|
128
129
|
"noSuchHostError": "No such host is known",
|
|
129
130
|
"odataServiceVersionMismatch": "The template you have chosen supports V{{requiredVersion}} OData services only. The provided version is V{{serviceVersion}}.",
|
|
130
131
|
"destinationAuthError": "The selected system is returning an authentication error. Please verify the destination configuration",
|
|
131
|
-
"
|
|
132
|
+
"systemOrserviceUrlNotFound": "Please verify the url: {{- url}}, target system configuration and network connectivity",
|
|
132
133
|
"urlRedirect": "The service URL is redirecting",
|
|
133
134
|
"certValidationRequired": "Certificate validation is required to continue.",
|
|
134
135
|
"exitingGeneration": "Exiting generation. {{exitReason}}",
|
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.5.
|
|
4
|
+
"version": "0.5.5",
|
|
5
5
|
"repository": {
|
|
6
6
|
"type": "git",
|
|
7
7
|
"url": "https://github.com/SAP/open-ux-tools.git",
|
|
@@ -25,7 +25,7 @@
|
|
|
25
25
|
"i18next": "23.5.1",
|
|
26
26
|
"inquirer-autocomplete-prompt": "2.0.1",
|
|
27
27
|
"os-name": "4.0.1",
|
|
28
|
-
"@sap-ux/axios-extension": "1.16.
|
|
28
|
+
"@sap-ux/axios-extension": "1.16.1",
|
|
29
29
|
"@sap-ux/btp-utils": "0.15.0",
|
|
30
30
|
"@sap-ux/telemetry": "0.5.9",
|
|
31
31
|
"@sap-ux/inquirer-common": "0.4.2",
|