@sap-ux/axios-extension 1.22.10 → 1.23.0
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/abap/abap-service-provider.d.ts +15 -5
- package/dist/abap/abap-service-provider.js +30 -7
- package/dist/abap/adt-catalog/services/systeminfo-service.d.ts +14 -0
- package/dist/abap/adt-catalog/services/systeminfo-service.js +35 -0
- package/dist/abap/types/adt-types.d.ts +10 -0
- package/dist/auth/index.d.ts +2 -2
- package/dist/auth/index.js +5 -7
- package/dist/auth/reentrance-ticket/abap-virtual-host-provider.d.ts +42 -0
- package/dist/auth/reentrance-ticket/abap-virtual-host-provider.js +83 -0
- package/dist/auth/reentrance-ticket/index.d.ts +2 -1
- package/dist/auth/reentrance-ticket/index.js +6 -8
- package/dist/auth/reentrance-ticket/redirect.d.ts +2 -2
- package/dist/auth/reentrance-ticket/redirect.js +9 -3
- package/dist/base/service-provider.d.ts +10 -0
- package/dist/base/service-provider.js +13 -1
- package/dist/factory.d.ts +6 -7
- package/dist/factory.js +16 -8
- package/package.json +3 -3
- package/dist/auth/reentrance-ticket/abap-system.d.ts +0 -31
- package/dist/auth/reentrance-ticket/abap-system.js +0 -55
|
@@ -1,13 +1,13 @@
|
|
|
1
|
+
import { ODataVersion } from '../base/odata-service';
|
|
1
2
|
import { ServiceProvider } from '../base/service-provider';
|
|
2
|
-
import type { CatalogService } from './catalog';
|
|
3
|
-
import { Ui5AbapRepositoryService } from './ui5-abap-repository-service';
|
|
4
3
|
import { AppIndexService } from './app-index-service';
|
|
5
|
-
import {
|
|
4
|
+
import type { CatalogService } from './catalog';
|
|
6
5
|
import { LayeredRepositoryService } from './lrep-service';
|
|
7
|
-
import type { AbapCDSView, AtoSettings, BusinessObject } from './types';
|
|
8
|
-
import {
|
|
6
|
+
import type { AbapCDSView, AtoSettings, BusinessObject, SystemInfo } from './types';
|
|
7
|
+
import { Ui5AbapRepositoryService } from './ui5-abap-repository-service';
|
|
9
8
|
import { ODataServiceGenerator } from './adt-catalog/generators/odata-service-generator';
|
|
10
9
|
import { UiServiceGenerator } from './adt-catalog/generators/ui-service-generator';
|
|
10
|
+
import { type AdtService } from './adt-catalog/services';
|
|
11
11
|
/**
|
|
12
12
|
* Extension of the service provider for ABAP services.
|
|
13
13
|
*/
|
|
@@ -17,6 +17,10 @@ export declare class AbapServiceProvider extends ServiceProvider {
|
|
|
17
17
|
* Maintain the public facing URL which is required for destination related flows
|
|
18
18
|
*/
|
|
19
19
|
protected _publicUrl: string;
|
|
20
|
+
/**
|
|
21
|
+
* The connected system info
|
|
22
|
+
*/
|
|
23
|
+
protected _systemInfo: SystemInfo | undefined;
|
|
20
24
|
/**
|
|
21
25
|
* Get the name of the currently logged in user. This is the basic implementation that could be overwritten by subclasses.
|
|
22
26
|
* The function returns a promise because it may be required to fetch the information from the backend.
|
|
@@ -24,6 +28,12 @@ export declare class AbapServiceProvider extends ServiceProvider {
|
|
|
24
28
|
* @returns the username
|
|
25
29
|
*/
|
|
26
30
|
user(): Promise<string | undefined>;
|
|
31
|
+
/**
|
|
32
|
+
* Get user information.
|
|
33
|
+
*
|
|
34
|
+
* @returns user name or undefined
|
|
35
|
+
*/
|
|
36
|
+
getSystemInfo(): Promise<SystemInfo | undefined>;
|
|
27
37
|
/**
|
|
28
38
|
* Set the ATO settings for the provider so that it does not try to fetch them with the first request.
|
|
29
39
|
*
|
|
@@ -1,19 +1,20 @@
|
|
|
1
1
|
"use strict";
|
|
2
2
|
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
3
|
exports.AbapServiceProvider = void 0;
|
|
4
|
+
const odata_service_1 = require("../base/odata-service");
|
|
4
5
|
const service_provider_1 = require("../base/service-provider");
|
|
5
|
-
const
|
|
6
|
-
const ui5_abap_repository_service_1 = require("./ui5-abap-repository-service");
|
|
6
|
+
const adt_catalog_service_1 = require("./adt-catalog/adt-catalog-service");
|
|
7
7
|
const app_index_service_1 = require("./app-index-service");
|
|
8
|
-
const
|
|
8
|
+
const catalog_1 = require("./catalog");
|
|
9
9
|
const lrep_service_1 = require("./lrep-service");
|
|
10
|
-
const adt_catalog_service_1 = require("./adt-catalog/adt-catalog-service");
|
|
11
10
|
const types_1 = require("./types");
|
|
11
|
+
const ui5_abap_repository_service_1 = require("./ui5-abap-repository-service");
|
|
12
12
|
// Can't use an `import type` here. We need the classname at runtime to create object instances:
|
|
13
13
|
// eslint-disable-next-line @typescript-eslint/consistent-type-imports
|
|
14
|
-
const services_1 = require("./adt-catalog/services");
|
|
15
14
|
const odata_service_generator_1 = require("./adt-catalog/generators/odata-service-generator");
|
|
16
15
|
const ui_service_generator_1 = require("./adt-catalog/generators/ui-service-generator");
|
|
16
|
+
const services_1 = require("./adt-catalog/services");
|
|
17
|
+
const systeminfo_service_1 = require("./adt-catalog/services/systeminfo-service");
|
|
17
18
|
/**
|
|
18
19
|
* Extension of the service provider for ABAP services.
|
|
19
20
|
*/
|
|
@@ -23,14 +24,36 @@ class AbapServiceProvider extends service_provider_1.ServiceProvider {
|
|
|
23
24
|
* Maintain the public facing URL which is required for destination related flows
|
|
24
25
|
*/
|
|
25
26
|
_publicUrl;
|
|
27
|
+
/**
|
|
28
|
+
* The connected system info
|
|
29
|
+
*/
|
|
30
|
+
_systemInfo;
|
|
26
31
|
/**
|
|
27
32
|
* Get the name of the currently logged in user. This is the basic implementation that could be overwritten by subclasses.
|
|
28
33
|
* The function returns a promise because it may be required to fetch the information from the backend.
|
|
29
34
|
*
|
|
30
35
|
* @returns the username
|
|
31
36
|
*/
|
|
32
|
-
user() {
|
|
33
|
-
return Promise.resolve(this.defaults.auth?.username);
|
|
37
|
+
async user() {
|
|
38
|
+
return (await Promise.resolve(this.defaults.auth?.username)) || (await this.getSystemInfo())?.userName;
|
|
39
|
+
}
|
|
40
|
+
/**
|
|
41
|
+
* Get user information.
|
|
42
|
+
*
|
|
43
|
+
* @returns user name or undefined
|
|
44
|
+
*/
|
|
45
|
+
async getSystemInfo() {
|
|
46
|
+
if (this._systemInfo) {
|
|
47
|
+
return this._systemInfo;
|
|
48
|
+
}
|
|
49
|
+
try {
|
|
50
|
+
const systemInfoService = this.createService('', systeminfo_service_1.SystemInfoService);
|
|
51
|
+
this._systemInfo = await systemInfoService.getSystemInfo();
|
|
52
|
+
}
|
|
53
|
+
catch (error) {
|
|
54
|
+
this.log.error(`An error occurred retrieving system info: ${error}`);
|
|
55
|
+
}
|
|
56
|
+
return this._systemInfo;
|
|
34
57
|
}
|
|
35
58
|
/**
|
|
36
59
|
* Set the ATO settings for the provider so that it does not try to fetch them with the first request.
|
|
@@ -0,0 +1,14 @@
|
|
|
1
|
+
import type { SystemInfo } from 'abap/types';
|
|
2
|
+
import { AdtService } from './adt-service';
|
|
3
|
+
/**
|
|
4
|
+
* Retrieve system information using the ADT endpoint
|
|
5
|
+
*/
|
|
6
|
+
export declare class SystemInfoService extends AdtService {
|
|
7
|
+
/**
|
|
8
|
+
* Send ADT request to fetch ATO settings.
|
|
9
|
+
*
|
|
10
|
+
* @returns AtoSettings
|
|
11
|
+
*/
|
|
12
|
+
getSystemInfo(): Promise<SystemInfo | undefined>;
|
|
13
|
+
}
|
|
14
|
+
//# sourceMappingURL=systeminfo-service.d.ts.map
|
|
@@ -0,0 +1,35 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
+
exports.SystemInfoService = void 0;
|
|
4
|
+
const adt_service_1 = require("./adt-service");
|
|
5
|
+
/**
|
|
6
|
+
* Retrieve system information using the ADT endpoint
|
|
7
|
+
*/
|
|
8
|
+
class SystemInfoService extends adt_service_1.AdtService {
|
|
9
|
+
/**
|
|
10
|
+
* Send ADT request to fetch ATO settings.
|
|
11
|
+
*
|
|
12
|
+
* @returns AtoSettings
|
|
13
|
+
*/
|
|
14
|
+
async getSystemInfo() {
|
|
15
|
+
const acceptHeaders = {
|
|
16
|
+
headers: {
|
|
17
|
+
Accept: 'application/vnd.sap.adt.core.http.systeminformation.v1+json'
|
|
18
|
+
}
|
|
19
|
+
};
|
|
20
|
+
const response = await this.get('/sap/bc/adt/core/http/systeminformation', acceptHeaders);
|
|
21
|
+
if (typeof response.data === 'string') {
|
|
22
|
+
try {
|
|
23
|
+
return JSON.parse(response.data);
|
|
24
|
+
}
|
|
25
|
+
catch (parseError) {
|
|
26
|
+
this.log.error(`System info could not be parsed from response. Error: ${parseError.message}`);
|
|
27
|
+
}
|
|
28
|
+
}
|
|
29
|
+
else {
|
|
30
|
+
return response.data;
|
|
31
|
+
}
|
|
32
|
+
}
|
|
33
|
+
}
|
|
34
|
+
exports.SystemInfoService = SystemInfoService;
|
|
35
|
+
//# sourceMappingURL=systeminfo-service.js.map
|
|
@@ -143,4 +143,14 @@ export type ValidationResponse = {
|
|
|
143
143
|
short_text: string;
|
|
144
144
|
long_text: string;
|
|
145
145
|
};
|
|
146
|
+
/**
|
|
147
|
+
* Type for '/sap/bc/adt/core/http/systeminformation' response type 'application/vnd.sap.adt.core.http.systeminformation.v1+json'
|
|
148
|
+
*/
|
|
149
|
+
export type SystemInfo = {
|
|
150
|
+
systemID: string;
|
|
151
|
+
userName: string;
|
|
152
|
+
userFullName: string;
|
|
153
|
+
client: string;
|
|
154
|
+
language: string;
|
|
155
|
+
};
|
|
146
156
|
//# sourceMappingURL=adt-types.d.ts.map
|
package/dist/auth/index.d.ts
CHANGED
|
@@ -1,8 +1,8 @@
|
|
|
1
|
-
import { ServiceInfo } from '@sap-ux/btp-utils';
|
|
2
1
|
import type { Axios, InternalAxiosRequestConfig } from 'axios';
|
|
3
2
|
import type { ServiceProvider } from '../base/service-provider';
|
|
4
|
-
import type { AbapServiceProvider } from '../abap';
|
|
5
3
|
import { RefreshTokenChanged, Uaa } from './uaa';
|
|
4
|
+
import type { AbapServiceProvider } from 'abap/abap-service-provider';
|
|
5
|
+
import type { ServiceInfo } from '@sap-ux/btp-utils';
|
|
6
6
|
export * from './connection';
|
|
7
7
|
export * from './error';
|
|
8
8
|
export { ServiceInfo, RefreshTokenChanged, Uaa };
|
package/dist/auth/index.js
CHANGED
|
@@ -85,18 +85,16 @@ function attachReentranceTicketAuthInterceptor({ provider }) {
|
|
|
85
85
|
*/
|
|
86
86
|
function getReentranceTicketAuthInterceptor({ provider, ejectCallback }) {
|
|
87
87
|
return async (request) => {
|
|
88
|
-
const { reentranceTicket,
|
|
88
|
+
const { reentranceTicket, backend } = await (0, reentrance_ticket_1.getReentranceTicket)({
|
|
89
89
|
backendUrl: provider.defaults.baseURL,
|
|
90
90
|
logger: provider.log
|
|
91
91
|
});
|
|
92
|
-
|
|
93
|
-
|
|
94
|
-
// with the API hostname returned
|
|
95
|
-
provider.log.warn(`Replacing provider's default base URL (${provider.defaults.baseURL}) with API URL: ${apiUrl}`);
|
|
96
|
-
provider.defaults.baseURL = apiUrl;
|
|
97
|
-
}
|
|
92
|
+
// Update the base host (provided system url) to the API host for subsequent calls as only this should be used with re-entrance tickets to generate a secure session
|
|
93
|
+
provider.defaults.baseURL = (await backend?.apiHostname()) ?? provider.defaults.baseURL;
|
|
98
94
|
request.headers = request.headers ?? new axios_1.AxiosHeaders();
|
|
99
95
|
request.headers.MYSAPSSO2 = reentranceTicket;
|
|
96
|
+
// Request a secure session using the reentrance token
|
|
97
|
+
request.headers['x-sap-security-session'] = 'create';
|
|
100
98
|
// remove this interceptor since it is not needed anymore
|
|
101
99
|
ejectCallback();
|
|
102
100
|
return request;
|
|
@@ -0,0 +1,42 @@
|
|
|
1
|
+
import { type Logger } from '@sap-ux/logger';
|
|
2
|
+
/**
|
|
3
|
+
* Makes requests to determine the virtual host names for UI and API access.
|
|
4
|
+
*/
|
|
5
|
+
export declare class ABAPVirtualHostProvider {
|
|
6
|
+
private apiURL;
|
|
7
|
+
private uiURL;
|
|
8
|
+
private readonly systemURL;
|
|
9
|
+
private relatedUrls;
|
|
10
|
+
private readonly logger;
|
|
11
|
+
/**
|
|
12
|
+
*
|
|
13
|
+
* @param backendUrl backend Url
|
|
14
|
+
* @param logger
|
|
15
|
+
*/
|
|
16
|
+
constructor(backendUrl: string, logger?: Logger);
|
|
17
|
+
/**
|
|
18
|
+
* Retrieves the virtual host names for UI and API access from the ABAP system public endpoint at the backend host.
|
|
19
|
+
*
|
|
20
|
+
* @returns An object containing the related URLs for API and UI access.
|
|
21
|
+
*/
|
|
22
|
+
private getVirtualHosts;
|
|
23
|
+
/**
|
|
24
|
+
* Get the UI hostname, if not cached yet it will be fetched.
|
|
25
|
+
*
|
|
26
|
+
* @returns UI hostname
|
|
27
|
+
*/
|
|
28
|
+
uiHostname(): Promise<string>;
|
|
29
|
+
/**
|
|
30
|
+
* Get the API hostname, if not cached yet it will be fetched.
|
|
31
|
+
*
|
|
32
|
+
* @returns API hostname
|
|
33
|
+
*/
|
|
34
|
+
apiHostname(): Promise<string>;
|
|
35
|
+
/**
|
|
36
|
+
* Get the logoff URL.
|
|
37
|
+
*
|
|
38
|
+
* @returns logoff URL
|
|
39
|
+
*/
|
|
40
|
+
logoffUrl(): Promise<string>;
|
|
41
|
+
}
|
|
42
|
+
//# sourceMappingURL=abap-virtual-host-provider.d.ts.map
|
|
@@ -0,0 +1,83 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
var __importDefault = (this && this.__importDefault) || function (mod) {
|
|
3
|
+
return (mod && mod.__esModule) ? mod : { "default": mod };
|
|
4
|
+
};
|
|
5
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
6
|
+
exports.ABAPVirtualHostProvider = void 0;
|
|
7
|
+
const logger_1 = require("@sap-ux/logger");
|
|
8
|
+
const axios_1 = __importDefault(require("axios"));
|
|
9
|
+
/**
|
|
10
|
+
* Makes requests to determine the virtual host names for UI and API access.
|
|
11
|
+
*/
|
|
12
|
+
class ABAPVirtualHostProvider {
|
|
13
|
+
apiURL;
|
|
14
|
+
uiURL;
|
|
15
|
+
systemURL;
|
|
16
|
+
relatedUrls;
|
|
17
|
+
logger = new logger_1.ToolsLogger();
|
|
18
|
+
/**
|
|
19
|
+
*
|
|
20
|
+
* @param backendUrl backend Url
|
|
21
|
+
* @param logger
|
|
22
|
+
*/
|
|
23
|
+
constructor(backendUrl, logger) {
|
|
24
|
+
this.systemURL = new URL(backendUrl);
|
|
25
|
+
if (logger) {
|
|
26
|
+
this.logger = logger;
|
|
27
|
+
}
|
|
28
|
+
}
|
|
29
|
+
/**
|
|
30
|
+
* Retrieves the virtual host names for UI and API access from the ABAP system public endpoint at the backend host.
|
|
31
|
+
*
|
|
32
|
+
* @returns An object containing the related URLs for API and UI access.
|
|
33
|
+
*/
|
|
34
|
+
async getVirtualHosts() {
|
|
35
|
+
if (!this.relatedUrls) {
|
|
36
|
+
this.logger.debug(`Requesting virtual hosts from: ${this.systemURL}`);
|
|
37
|
+
const url = new URL('/sap/public/bc/icf/virtualhost', this.systemURL.origin);
|
|
38
|
+
const response = await axios_1.default.get(url.href, {
|
|
39
|
+
headers: {
|
|
40
|
+
Accept: 'application/json'
|
|
41
|
+
}
|
|
42
|
+
});
|
|
43
|
+
if (response.status !== 200) {
|
|
44
|
+
this.logger.debug(`Failed to fetch virtual hosts: from: ${url}. Error: ${response.statusText}`);
|
|
45
|
+
throw new Error(`Failed to fetch virtual hosts: ${response.statusText}`);
|
|
46
|
+
}
|
|
47
|
+
this.relatedUrls = response.data;
|
|
48
|
+
}
|
|
49
|
+
return this.relatedUrls;
|
|
50
|
+
}
|
|
51
|
+
/**
|
|
52
|
+
* Get the UI hostname, if not cached yet it will be fetched.
|
|
53
|
+
*
|
|
54
|
+
* @returns UI hostname
|
|
55
|
+
*/
|
|
56
|
+
async uiHostname() {
|
|
57
|
+
if (!this.uiURL) {
|
|
58
|
+
this.uiURL = new URL((await this.getVirtualHosts()).relatedUrls.UI);
|
|
59
|
+
}
|
|
60
|
+
return this.uiURL.origin;
|
|
61
|
+
}
|
|
62
|
+
/**
|
|
63
|
+
* Get the API hostname, if not cached yet it will be fetched.
|
|
64
|
+
*
|
|
65
|
+
* @returns API hostname
|
|
66
|
+
*/
|
|
67
|
+
async apiHostname() {
|
|
68
|
+
if (!this.apiURL) {
|
|
69
|
+
this.apiURL = new URL((await this.getVirtualHosts()).relatedUrls.API);
|
|
70
|
+
}
|
|
71
|
+
return this.apiURL.origin;
|
|
72
|
+
}
|
|
73
|
+
/**
|
|
74
|
+
* Get the logoff URL.
|
|
75
|
+
*
|
|
76
|
+
* @returns logoff URL
|
|
77
|
+
*/
|
|
78
|
+
async logoffUrl() {
|
|
79
|
+
return (await this.uiHostname()) + '/sap/public/bc/icf/logoff';
|
|
80
|
+
}
|
|
81
|
+
}
|
|
82
|
+
exports.ABAPVirtualHostProvider = ABAPVirtualHostProvider;
|
|
83
|
+
//# sourceMappingURL=abap-virtual-host-provider.js.map
|
|
@@ -1,4 +1,5 @@
|
|
|
1
1
|
import type { Logger } from '@sap-ux/logger';
|
|
2
|
+
import { ABAPVirtualHostProvider } from './abap-virtual-host-provider';
|
|
2
3
|
/**
|
|
3
4
|
* Get the reentrance ticket from the backend.
|
|
4
5
|
*
|
|
@@ -13,6 +14,6 @@ export declare function getReentranceTicket({ backendUrl, logger, timeout }: {
|
|
|
13
14
|
timeout?: number;
|
|
14
15
|
}): Promise<{
|
|
15
16
|
reentranceTicket: string;
|
|
16
|
-
|
|
17
|
+
backend?: ABAPVirtualHostProvider;
|
|
17
18
|
}>;
|
|
18
19
|
//# sourceMappingURL=index.d.ts.map
|
|
@@ -3,12 +3,8 @@ Object.defineProperty(exports, "__esModule", { value: true });
|
|
|
3
3
|
exports.getReentranceTicket = getReentranceTicket;
|
|
4
4
|
const open = require("open");
|
|
5
5
|
const connection_1 = require("../connection");
|
|
6
|
-
const
|
|
6
|
+
const abap_virtual_host_provider_1 = require("./abap-virtual-host-provider");
|
|
7
7
|
const redirect_1 = require("./redirect");
|
|
8
|
-
/**
|
|
9
|
-
* DO NOT USE THIS SERVICE ENDPOINT DIRECTLY.
|
|
10
|
-
* It might be removed in the future without notice.
|
|
11
|
-
*/
|
|
12
8
|
const ADT_REENTRANCE_ENDPOINT = '/sap/bc/sec/reentrance';
|
|
13
9
|
/**
|
|
14
10
|
* Get the reentrance ticket from the backend.
|
|
@@ -19,8 +15,9 @@ const ADT_REENTRANCE_ENDPOINT = '/sap/bc/sec/reentrance';
|
|
|
19
15
|
* @param options.timeout timeout in milliseconds
|
|
20
16
|
*/
|
|
21
17
|
async function getReentranceTicket({ backendUrl, logger, timeout = connection_1.defaultTimeout }) {
|
|
18
|
+
const backend = new abap_virtual_host_provider_1.ABAPVirtualHostProvider(backendUrl, logger);
|
|
19
|
+
const uiHostname = await backend.uiHostname();
|
|
22
20
|
return new Promise((resolve, reject) => {
|
|
23
|
-
const backend = new abap_system_1.ABAPSystem(backendUrl);
|
|
24
21
|
// Start local server to listen to redirect call, with timeout
|
|
25
22
|
const { server, redirectUrl } = (0, redirect_1.setupRedirectHandling)({ resolve, reject, timeout, backend, logger });
|
|
26
23
|
server.listen();
|
|
@@ -28,8 +25,9 @@ async function getReentranceTicket({ backendUrl, logger, timeout = connection_1.
|
|
|
28
25
|
// Open browser to handle SAML flow and return the reentrance ticket
|
|
29
26
|
const scenario = process.env.FIORI_TOOLS_SCENARIO ?? 'FTO1';
|
|
30
27
|
const endpoint = process.env.FIORI_TOOLS_REENTRANCE_ENDPOINT ?? ADT_REENTRANCE_ENDPOINT;
|
|
31
|
-
const url = `${
|
|
32
|
-
open(url)?.catch((error) => logger.error(error));
|
|
28
|
+
const url = `${uiHostname}${endpoint}?scenario=${scenario}&redirect-url=${redirectUrl(redirectPort)}`;
|
|
29
|
+
const result = open(url)?.catch((error) => logger.error(error));
|
|
30
|
+
return result;
|
|
33
31
|
});
|
|
34
32
|
}
|
|
35
33
|
//# sourceMappingURL=index.js.map
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
import type { Logger } from '@sap-ux/logger';
|
|
2
2
|
import http from 'http';
|
|
3
|
-
import type {
|
|
3
|
+
import type { ABAPVirtualHostProvider } from './abap-virtual-host-provider';
|
|
4
4
|
interface Redirect {
|
|
5
5
|
server: http.Server;
|
|
6
6
|
/**
|
|
@@ -15,7 +15,7 @@ export interface SetupRedirectOptions {
|
|
|
15
15
|
resolve: any;
|
|
16
16
|
reject: any;
|
|
17
17
|
timeout: number;
|
|
18
|
-
backend:
|
|
18
|
+
backend: ABAPVirtualHostProvider;
|
|
19
19
|
logger: Logger;
|
|
20
20
|
}
|
|
21
21
|
/**
|
|
@@ -36,10 +36,16 @@ function setupRedirectHandling({ resolve, reject, timeout, backend, logger }) {
|
|
|
36
36
|
const reentranceTicket = reqUrl.searchParams.get('reentrance-ticket')?.toString();
|
|
37
37
|
if (reentranceTicket) {
|
|
38
38
|
logger.debug('Got reentrance ticket: ' + reentranceTicket);
|
|
39
|
-
|
|
40
|
-
|
|
39
|
+
backend
|
|
40
|
+
.logoffUrl()
|
|
41
|
+
.then((url) => {
|
|
42
|
+
res.writeHead(200, { 'Content-Type': 'text/html' });
|
|
43
|
+
res.end(Buffer.from((0, static_1.redirectSuccessHtml)(url)));
|
|
44
|
+
})
|
|
45
|
+
.catch(() => { });
|
|
41
46
|
server.close();
|
|
42
|
-
|
|
47
|
+
// return the backend for convienience
|
|
48
|
+
resolve({ reentranceTicket, backend });
|
|
43
49
|
}
|
|
44
50
|
else {
|
|
45
51
|
logger.error('Error getting reentrance ticket');
|
|
@@ -16,6 +16,10 @@ export interface ProviderConfiguration {
|
|
|
16
16
|
* https://datatracker.ietf.org/doc/html/rfc6265#section-4.2
|
|
17
17
|
*/
|
|
18
18
|
cookies: string;
|
|
19
|
+
/**
|
|
20
|
+
* Allow a logger to be set by calls to provider creation
|
|
21
|
+
*/
|
|
22
|
+
logger?: Logger;
|
|
19
23
|
}
|
|
20
24
|
export interface ServiceProviderExtension {
|
|
21
25
|
/**
|
|
@@ -35,8 +39,14 @@ export declare class ServiceProvider extends Axios implements ServiceProviderExt
|
|
|
35
39
|
protected readonly services: {
|
|
36
40
|
[path: string]: Service;
|
|
37
41
|
};
|
|
42
|
+
/**
|
|
43
|
+
*
|
|
44
|
+
* @param providerConfig
|
|
45
|
+
*/
|
|
46
|
+
constructor(providerConfig?: AxiosRequestConfig & Partial<ProviderConfiguration>);
|
|
38
47
|
/**
|
|
39
48
|
* Set the logger for the service provider. Loggers may need to be restored after serialization/deserialization since they contain circular references.
|
|
49
|
+
* Note calling this will overwrite loggers sets via ProviderConfiguration.
|
|
40
50
|
*
|
|
41
51
|
* @param logger - Logger instance to be set
|
|
42
52
|
*/
|
|
@@ -12,8 +12,19 @@ class ServiceProvider extends axios_1.Axios {
|
|
|
12
12
|
_log = new logger_1.ToolsLogger();
|
|
13
13
|
cookies = new auth_1.Cookies();
|
|
14
14
|
services = {};
|
|
15
|
+
/**
|
|
16
|
+
*
|
|
17
|
+
* @param providerConfig
|
|
18
|
+
*/
|
|
19
|
+
constructor(providerConfig) {
|
|
20
|
+
super(providerConfig);
|
|
21
|
+
if (providerConfig?.logger) {
|
|
22
|
+
this._log = providerConfig.logger;
|
|
23
|
+
}
|
|
24
|
+
}
|
|
15
25
|
/**
|
|
16
26
|
* Set the logger for the service provider. Loggers may need to be restored after serialization/deserialization since they contain circular references.
|
|
27
|
+
* Note calling this will overwrite loggers sets via ProviderConfiguration.
|
|
17
28
|
*
|
|
18
29
|
* @param logger - Logger instance to be set
|
|
19
30
|
*/
|
|
@@ -48,10 +59,11 @@ class ServiceProvider extends axios_1.Axios {
|
|
|
48
59
|
*/
|
|
49
60
|
generateServiceConfig(path) {
|
|
50
61
|
const config = Object.assign({}, this.defaults);
|
|
62
|
+
const headers = Object.assign(this.defaults.headers?.common ?? {}, { Cookie: this.cookies.toString() });
|
|
51
63
|
return {
|
|
52
64
|
...config,
|
|
53
65
|
baseURL: this.defaults.baseURL + path,
|
|
54
|
-
headers
|
|
66
|
+
headers
|
|
55
67
|
};
|
|
56
68
|
}
|
|
57
69
|
/**
|
package/dist/factory.d.ts
CHANGED
|
@@ -1,11 +1,11 @@
|
|
|
1
|
-
import type { AxiosRequestConfig } from 'axios';
|
|
2
1
|
import { type Destination } from '@sap-ux/btp-utils';
|
|
3
|
-
import type {
|
|
2
|
+
import type { AxiosRequestConfig } from 'axios';
|
|
3
|
+
import { type HttpsProxyAgentOptions, HttpsProxyAgent } from 'https-proxy-agent';
|
|
4
|
+
import { AbapServiceProvider } from './abap';
|
|
5
|
+
import type { RefreshTokenChanged, ServiceInfo } from './auth';
|
|
6
|
+
import type { ODataService } from './base/odata-service';
|
|
4
7
|
import type { ProviderConfiguration } from './base/service-provider';
|
|
5
8
|
import { ServiceProvider } from './base/service-provider';
|
|
6
|
-
import type { ODataService } from './base/odata-service';
|
|
7
|
-
import { AbapServiceProvider } from './abap';
|
|
8
|
-
import { type HttpsProxyAgentOptions, HttpsProxyAgent } from 'https-proxy-agent';
|
|
9
9
|
/**
|
|
10
10
|
* PatchedHttpsProxyAgent is a custom implementation of HttpsProxyAgent that allows to pass additional options, currently not supported by the original implementation when calling tls.connect
|
|
11
11
|
*/
|
|
@@ -65,7 +65,7 @@ export interface AbapEmbeddedSteampunkOptions extends ReentranceTicketOptions {
|
|
|
65
65
|
environment: AbapCloudEnvironment.EmbeddedSteampunk;
|
|
66
66
|
}
|
|
67
67
|
/** Discriminated union of supported environments - {@link AbapCloudStandaloneOptions} and {@link AbapEmbeddedSteampunkOptions} */
|
|
68
|
-
type AbapCloudOptions = AbapCloudStandaloneOptions | AbapEmbeddedSteampunkOptions;
|
|
68
|
+
export type AbapCloudOptions = AbapCloudStandaloneOptions | AbapEmbeddedSteampunkOptions;
|
|
69
69
|
/**
|
|
70
70
|
* Create an instance of an ABAP service provider for a Cloud ABAP system.
|
|
71
71
|
*
|
|
@@ -94,5 +94,4 @@ export declare function createForDestination(options: AxiosRequestConfig & Parti
|
|
|
94
94
|
* @returns instance of a service
|
|
95
95
|
*/
|
|
96
96
|
export declare function createServiceForUrl(url: string, config?: AxiosRequestConfig & Partial<ProviderConfiguration>): ODataService;
|
|
97
|
-
export {};
|
|
98
97
|
//# sourceMappingURL=factory.d.ts.map
|
package/dist/factory.js
CHANGED
|
@@ -9,17 +9,17 @@ exports.createForAbap = createForAbap;
|
|
|
9
9
|
exports.createForAbapOnCloud = createForAbapOnCloud;
|
|
10
10
|
exports.createForDestination = createForDestination;
|
|
11
11
|
exports.createServiceForUrl = createServiceForUrl;
|
|
12
|
-
const cloneDeep_1 = __importDefault(require("lodash/cloneDeep"));
|
|
13
12
|
const btp_utils_1 = require("@sap-ux/btp-utils");
|
|
13
|
+
const http_proxy_agent_1 = require("http-proxy-agent");
|
|
14
14
|
const https_1 = require("https");
|
|
15
|
-
const
|
|
16
|
-
const
|
|
17
|
-
const
|
|
15
|
+
const https_proxy_agent_1 = require("https-proxy-agent");
|
|
16
|
+
const cloneDeep_1 = __importDefault(require("lodash/cloneDeep"));
|
|
17
|
+
const proxy_from_env_1 = require("proxy-from-env");
|
|
18
18
|
const util_1 = require("util");
|
|
19
|
+
const abap_1 = require("./abap");
|
|
20
|
+
const auth_1 = require("./auth");
|
|
19
21
|
const patchTls_1 = require("./base/patchTls");
|
|
20
|
-
const
|
|
21
|
-
const https_proxy_agent_1 = require("https-proxy-agent");
|
|
22
|
-
const http_proxy_agent_1 = require("http-proxy-agent");
|
|
22
|
+
const service_provider_1 = require("./base/service-provider");
|
|
23
23
|
/**
|
|
24
24
|
* PatchedHttpsProxyAgent is a custom implementation of HttpsProxyAgent that allows to pass additional options, currently not supported by the original implementation when calling tls.connect
|
|
25
25
|
*/
|
|
@@ -152,7 +152,15 @@ function createForAbapOnCloud(options) {
|
|
|
152
152
|
...config
|
|
153
153
|
});
|
|
154
154
|
if (!cookies) {
|
|
155
|
-
|
|
155
|
+
// Only in the case where a username and password are provided use UAA otherwise use re-entrance
|
|
156
|
+
// This is to support unattended authentication for now.
|
|
157
|
+
if (options.service?.uaa?.username && options.service.uaa.password) {
|
|
158
|
+
(0, auth_1.attachUaaAuthInterceptor)(provider, service, refreshToken, refreshTokenChangedCb);
|
|
159
|
+
}
|
|
160
|
+
else {
|
|
161
|
+
// Always use re-entrance tickets regardless of the ABAP Cloud environment where credentials are not provided
|
|
162
|
+
(0, auth_1.attachReentranceTicketAuthInterceptor)({ provider });
|
|
163
|
+
}
|
|
156
164
|
}
|
|
157
165
|
break;
|
|
158
166
|
}
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@sap-ux/axios-extension",
|
|
3
|
-
"version": "1.
|
|
3
|
+
"version": "1.23.0",
|
|
4
4
|
"description": "Extension of the Axios module adding convenience methods to interact with SAP systems especially with OData services.",
|
|
5
5
|
"repository": {
|
|
6
6
|
"type": "git",
|
|
@@ -27,14 +27,14 @@
|
|
|
27
27
|
"proxy-from-env": "1.1.0",
|
|
28
28
|
"@sap-ux/btp-utils": "1.1.4",
|
|
29
29
|
"@sap-ux/logger": "0.7.0",
|
|
30
|
-
"@sap-ux/feature-toggle": "0.3.
|
|
30
|
+
"@sap-ux/feature-toggle": "0.3.2"
|
|
31
31
|
},
|
|
32
32
|
"devDependencies": {
|
|
33
33
|
"@types/lodash": "4.14.202",
|
|
34
34
|
"nock": "13.4.0",
|
|
35
35
|
"supertest": "7.1.4",
|
|
36
36
|
"@types/proxy-from-env": "1.0.1",
|
|
37
|
-
"@sap-ux/project-access": "1.32.
|
|
37
|
+
"@sap-ux/project-access": "1.32.4"
|
|
38
38
|
},
|
|
39
39
|
"files": [
|
|
40
40
|
"dist",
|
|
@@ -1,31 +0,0 @@
|
|
|
1
|
-
/**
|
|
2
|
-
*
|
|
3
|
-
*/
|
|
4
|
-
export declare class ABAPSystem {
|
|
5
|
-
private apiURL;
|
|
6
|
-
private uiURL;
|
|
7
|
-
private systemURL;
|
|
8
|
-
/**
|
|
9
|
-
*
|
|
10
|
-
* @param backendUrl backend Url
|
|
11
|
-
*/
|
|
12
|
-
constructor(backendUrl: string);
|
|
13
|
-
/**
|
|
14
|
-
* Removes any `-api` suffix in the first label of the hostname.
|
|
15
|
-
*
|
|
16
|
-
* @returns UI hostname
|
|
17
|
-
*/
|
|
18
|
-
uiHostname(): string;
|
|
19
|
-
/**
|
|
20
|
-
* Adds a `-api` suffix to the first label of the hostname.
|
|
21
|
-
*
|
|
22
|
-
* @returns API hostname
|
|
23
|
-
*/
|
|
24
|
-
apiHostname(): string;
|
|
25
|
-
/**
|
|
26
|
-
*
|
|
27
|
-
* @returns logoff URL
|
|
28
|
-
*/
|
|
29
|
-
logoffUrl(): string;
|
|
30
|
-
}
|
|
31
|
-
//# sourceMappingURL=abap-system.d.ts.map
|
|
@@ -1,55 +0,0 @@
|
|
|
1
|
-
"use strict";
|
|
2
|
-
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
-
exports.ABAPSystem = void 0;
|
|
4
|
-
/**
|
|
5
|
-
*
|
|
6
|
-
*/
|
|
7
|
-
class ABAPSystem {
|
|
8
|
-
apiURL;
|
|
9
|
-
uiURL;
|
|
10
|
-
systemURL;
|
|
11
|
-
/**
|
|
12
|
-
*
|
|
13
|
-
* @param backendUrl backend Url
|
|
14
|
-
*/
|
|
15
|
-
constructor(backendUrl) {
|
|
16
|
-
this.systemURL = new URL(backendUrl);
|
|
17
|
-
}
|
|
18
|
-
/**
|
|
19
|
-
* Removes any `-api` suffix in the first label of the hostname.
|
|
20
|
-
*
|
|
21
|
-
* @returns UI hostname
|
|
22
|
-
*/
|
|
23
|
-
uiHostname() {
|
|
24
|
-
if (!this.uiURL) {
|
|
25
|
-
this.uiURL = new URL(this.systemURL.href);
|
|
26
|
-
const [first, ...rest] = this.uiURL.hostname.split('.');
|
|
27
|
-
this.uiURL.hostname = [first.replace(/-api$/, ''), ...rest].join('.');
|
|
28
|
-
}
|
|
29
|
-
return this.uiURL.origin;
|
|
30
|
-
}
|
|
31
|
-
/**
|
|
32
|
-
* Adds a `-api` suffix to the first label of the hostname.
|
|
33
|
-
*
|
|
34
|
-
* @returns API hostname
|
|
35
|
-
*/
|
|
36
|
-
apiHostname() {
|
|
37
|
-
if (!this.apiURL) {
|
|
38
|
-
this.apiURL = new URL(this.systemURL.href);
|
|
39
|
-
const [first, ...rest] = this.apiURL.hostname.split('.');
|
|
40
|
-
if (!first.endsWith('-api')) {
|
|
41
|
-
this.apiURL.hostname = [first + '-api', ...rest].join('.');
|
|
42
|
-
}
|
|
43
|
-
}
|
|
44
|
-
return this.apiURL.origin;
|
|
45
|
-
}
|
|
46
|
-
/**
|
|
47
|
-
*
|
|
48
|
-
* @returns logoff URL
|
|
49
|
-
*/
|
|
50
|
-
logoffUrl() {
|
|
51
|
-
return this.uiHostname() + '/sap/public/bc/icf/logoff';
|
|
52
|
-
}
|
|
53
|
-
}
|
|
54
|
-
exports.ABAPSystem = ABAPSystem;
|
|
55
|
-
//# sourceMappingURL=abap-system.js.map
|