@sasjs/adapter 3.9.1 → 3.9.4
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/.git-hooks/pre-commit +12 -0
- package/SASjs.d.ts +1 -1
- package/SASjsApiClient.d.ts +1 -8
- package/auth/AuthManager.d.ts +0 -9
- package/index.js +2 -2
- package/node/SASjs.d.ts +1 -1
- package/node/SASjsApiClient.d.ts +1 -8
- package/node/auth/AuthManager.d.ts +0 -9
- package/node/index.js +2 -2
- package/package.json +4 -3
- package/src/SASjs.ts +2 -11
- package/src/SASjsApiClient.ts +4 -17
- package/src/auth/AuthManager.ts +24 -53
- package/src/job-execution/WebJobExecutor.ts +13 -3
- package/src/utils/convertToCsv.ts +5 -5
- package/auth/getAuthCodeForSasjs.d.ts +0 -9
- package/node/auth/getAuthCodeForSasjs.d.ts +0 -9
- package/src/auth/getAuthCodeForSasjs.ts +0 -31
package/package.json
CHANGED
|
@@ -8,8 +8,9 @@
|
|
|
8
8
|
"build": "rimraf build && rimraf node && mkdir node && copyfiles -u 1 \"./src/**/*\" ./node && webpack && rimraf build/src && rimraf node",
|
|
9
9
|
"package:lib": "npm run build && copyfiles ./package.json ./checkNodeVersion.js build && cd build && npm version \"5.0.0\" && npm pack",
|
|
10
10
|
"publish:lib": "npm run build && cd build && npm publish",
|
|
11
|
-
"lint:fix": "npx prettier --write \"src/**/*.{ts,tsx,js,jsx,html,css,sass,less,json,yml,md,graphql}\" && npx prettier --write \"sasjs-tests/src/**/*.{ts,tsx,js,jsx,html,css,sass,less,json,yml,md,graphql}\"",
|
|
11
|
+
"lint:fix": "npx prettier --loglevel silent --write \"src/**/*.{ts,tsx,js,jsx,html,css,sass,less,json,yml,md,graphql}\" && npx prettier --loglevel silent --write \"sasjs-tests/src/**/*.{ts,tsx,js,jsx,html,css,sass,less,json,yml,md,graphql}\"",
|
|
12
12
|
"lint": "npx prettier --check \"src/**/*.{ts,tsx,js,jsx,html,css,sass,less,json,yml,md,graphql}\" && npx prettier --check \"sasjs-tests/src/**/*.{ts,tsx,js,jsx,html,css,sass,less,json,yml,md,graphql}\"",
|
|
13
|
+
"lint:silent": "npx prettier --loglevel silent --check \"src/**/*.{ts,tsx,js,jsx,html,css,sass,less,json,yml,md,graphql}\" && npx prettier --loglevel silent --check \"sasjs-tests/src/**/*.{ts,tsx,js,jsx,html,css,sass,less,json,yml,md,graphql}\"",
|
|
13
14
|
"test": "jest --silent --coverage",
|
|
14
15
|
"prepublishOnly": "cp -r ./build/* . && rm -rf ./build",
|
|
15
16
|
"postpublish": "git clean -fd",
|
|
@@ -72,12 +73,12 @@
|
|
|
72
73
|
},
|
|
73
74
|
"main": "index.js",
|
|
74
75
|
"dependencies": {
|
|
75
|
-
"@sasjs/utils": "2.
|
|
76
|
+
"@sasjs/utils": "2.44.0",
|
|
76
77
|
"axios": "0.26.0",
|
|
77
78
|
"axios-cookiejar-support": "1.0.1",
|
|
78
79
|
"form-data": "4.0.0",
|
|
79
80
|
"https": "1.0.0",
|
|
80
81
|
"tough-cookie": "4.0.0"
|
|
81
82
|
},
|
|
82
|
-
"version": "3.9.
|
|
83
|
+
"version": "3.9.4"
|
|
83
84
|
}
|
package/src/SASjs.ts
CHANGED
|
@@ -592,15 +592,6 @@ export default class SASjs {
|
|
|
592
592
|
'A username and password are required when using the default login mechanism.'
|
|
593
593
|
)
|
|
594
594
|
|
|
595
|
-
if (this.sasjsConfig.serverType === ServerType.Sasjs) {
|
|
596
|
-
if (!clientId)
|
|
597
|
-
throw new Error(
|
|
598
|
-
'A username, password and clientId are required when using the default login mechanism with server type SASJS.'
|
|
599
|
-
)
|
|
600
|
-
|
|
601
|
-
return this.authManager!.logInSasjs(username, password, clientId)
|
|
602
|
-
}
|
|
603
|
-
|
|
604
595
|
return this.authManager!.logIn(username, password)
|
|
605
596
|
}
|
|
606
597
|
|
|
@@ -916,8 +907,8 @@ export default class SASjs {
|
|
|
916
907
|
return await this.sasJSApiClient?.deploy(dataJson, appLoc, authConfig)
|
|
917
908
|
}
|
|
918
909
|
|
|
919
|
-
public async executeJobSASjs(query: ExecutionQuery) {
|
|
920
|
-
return await this.sasJSApiClient?.executeJob(query)
|
|
910
|
+
public async executeJobSASjs(query: ExecutionQuery, authConfig?: AuthConfig) {
|
|
911
|
+
return await this.sasJSApiClient?.executeJob(query, authConfig)
|
|
921
912
|
}
|
|
922
913
|
|
|
923
914
|
/**
|
package/src/SASjsApiClient.ts
CHANGED
|
@@ -3,7 +3,6 @@ import { ExecutionQuery } from './types'
|
|
|
3
3
|
import { RequestClient } from './request/RequestClient'
|
|
4
4
|
import { getAccessTokenForSasjs } from './auth/getAccessTokenForSasjs'
|
|
5
5
|
import { refreshTokensForSasjs } from './auth/refreshTokensForSasjs'
|
|
6
|
-
import { getAuthCodeForSasjs } from './auth/getAuthCodeForSasjs'
|
|
7
6
|
import { parseWeboutResponse } from './utils'
|
|
8
7
|
import { getTokens } from './auth/getTokens'
|
|
9
8
|
|
|
@@ -43,7 +42,9 @@ export class SASjsApiClient {
|
|
|
43
42
|
return Promise.resolve(result)
|
|
44
43
|
}
|
|
45
44
|
|
|
46
|
-
public async executeJob(query: ExecutionQuery) {
|
|
45
|
+
public async executeJob(query: ExecutionQuery, authConfig?: AuthConfig) {
|
|
46
|
+
const access_token = authConfig ? authConfig.access_token : undefined
|
|
47
|
+
|
|
47
48
|
const { result } = await this.requestClient.post<{
|
|
48
49
|
status: string
|
|
49
50
|
message: string
|
|
@@ -51,7 +52,7 @@ export class SASjsApiClient {
|
|
|
51
52
|
logPath?: string
|
|
52
53
|
error?: {}
|
|
53
54
|
_webout?: string
|
|
54
|
-
}>('SASjsApi/stp/execute', query,
|
|
55
|
+
}>('SASjsApi/stp/execute', query, access_token)
|
|
55
56
|
|
|
56
57
|
if (Object.keys(result).includes('_webout')) {
|
|
57
58
|
result._webout = parseWeboutResponse(result._webout!)
|
|
@@ -112,20 +113,6 @@ export class SASjsApiClient {
|
|
|
112
113
|
public async refreshTokens(refreshToken: string): Promise<SASjsAuthResponse> {
|
|
113
114
|
return refreshTokensForSasjs(this.requestClient, refreshToken)
|
|
114
115
|
}
|
|
115
|
-
|
|
116
|
-
/**
|
|
117
|
-
* Performs a login authenticate and returns an auth code for the given client.
|
|
118
|
-
* @param username - a string representing the username.
|
|
119
|
-
* @param password - a string representing the password.
|
|
120
|
-
* @param clientId - the client ID to authenticate with.
|
|
121
|
-
*/
|
|
122
|
-
public async getAuthCode(
|
|
123
|
-
username: string,
|
|
124
|
-
password: string,
|
|
125
|
-
clientId: string
|
|
126
|
-
) {
|
|
127
|
-
return getAuthCodeForSasjs(this.requestClient, username, password, clientId)
|
|
128
|
-
}
|
|
129
116
|
}
|
|
130
117
|
|
|
131
118
|
// todo move to sasjs/utils
|
package/src/auth/AuthManager.ts
CHANGED
|
@@ -2,8 +2,6 @@ import { ServerType } from '@sasjs/utils/types'
|
|
|
2
2
|
import { RequestClient } from '../request/RequestClient'
|
|
3
3
|
import { LoginOptions, LoginResult } from '../types/Login'
|
|
4
4
|
import { serialize } from '../utils'
|
|
5
|
-
import { getAccessTokenForSasjs } from './getAccessTokenForSasjs'
|
|
6
|
-
import { getAuthCodeForSasjs } from './getAuthCodeForSasjs'
|
|
7
5
|
import { openWebPage } from './openWebPage'
|
|
8
6
|
import { verifySas9Login } from './verifySas9Login'
|
|
9
7
|
import { verifySasViyaLogin } from './verifySasViyaLogin'
|
|
@@ -83,39 +81,6 @@ export class AuthManager {
|
|
|
83
81
|
return { isLoggedIn: false, userName: '' }
|
|
84
82
|
}
|
|
85
83
|
|
|
86
|
-
/**
|
|
87
|
-
* Logs into the SAS server with the supplied credentials.
|
|
88
|
-
* @param userName - a string representing the username.
|
|
89
|
-
* @param password - a string representing the password.
|
|
90
|
-
* @param clientId - a string representing the client ID.
|
|
91
|
-
* @returns - a boolean `isLoggedin` and a string `username`
|
|
92
|
-
*/
|
|
93
|
-
public async logInSasjs(
|
|
94
|
-
username: string,
|
|
95
|
-
password: string,
|
|
96
|
-
clientId: string
|
|
97
|
-
): Promise<LoginResult> {
|
|
98
|
-
const isLoggedIn = await this.sendLoginRequestSasjs(
|
|
99
|
-
username,
|
|
100
|
-
password,
|
|
101
|
-
clientId
|
|
102
|
-
)
|
|
103
|
-
.then((res) => {
|
|
104
|
-
this.userName = username
|
|
105
|
-
this.requestClient.saveLocalStorageToken(
|
|
106
|
-
res.access_token,
|
|
107
|
-
res.refresh_token
|
|
108
|
-
)
|
|
109
|
-
return true
|
|
110
|
-
})
|
|
111
|
-
.catch(() => false)
|
|
112
|
-
|
|
113
|
-
return {
|
|
114
|
-
isLoggedIn,
|
|
115
|
-
userName: this.userName
|
|
116
|
-
}
|
|
117
|
-
}
|
|
118
|
-
|
|
119
84
|
/**
|
|
120
85
|
* Logs into the SAS server with the supplied credentials.
|
|
121
86
|
* @param username - a string representing the username.
|
|
@@ -152,7 +117,7 @@ export class AuthManager {
|
|
|
152
117
|
|
|
153
118
|
let loginResponse = await this.sendLoginRequest(loginForm, loginParams)
|
|
154
119
|
|
|
155
|
-
let isLoggedIn = isLogInSuccess(loginResponse)
|
|
120
|
+
let isLoggedIn = isLogInSuccess(this.serverType, loginResponse)
|
|
156
121
|
|
|
157
122
|
if (!isLoggedIn) {
|
|
158
123
|
if (isCredentialsVerifyError(loginResponse)) {
|
|
@@ -196,6 +161,17 @@ export class AuthManager {
|
|
|
196
161
|
loginForm: { [key: string]: any },
|
|
197
162
|
loginParams: { [key: string]: any }
|
|
198
163
|
) {
|
|
164
|
+
if (this.serverType === ServerType.Sasjs) {
|
|
165
|
+
const { username, password } = loginParams
|
|
166
|
+
const { result: loginResponse } = await this.requestClient.post<string>(
|
|
167
|
+
this.loginUrl,
|
|
168
|
+
{ username, password },
|
|
169
|
+
undefined
|
|
170
|
+
)
|
|
171
|
+
|
|
172
|
+
return loginResponse
|
|
173
|
+
}
|
|
174
|
+
|
|
199
175
|
for (const key in loginForm) {
|
|
200
176
|
loginParams[key] = loginForm[key]
|
|
201
177
|
}
|
|
@@ -215,19 +191,6 @@ export class AuthManager {
|
|
|
215
191
|
return loginResponse
|
|
216
192
|
}
|
|
217
193
|
|
|
218
|
-
private async sendLoginRequestSasjs(
|
|
219
|
-
username: string,
|
|
220
|
-
password: string,
|
|
221
|
-
clientId: string
|
|
222
|
-
) {
|
|
223
|
-
const authCode = await getAuthCodeForSasjs(
|
|
224
|
-
this.requestClient,
|
|
225
|
-
username,
|
|
226
|
-
password,
|
|
227
|
-
clientId
|
|
228
|
-
)
|
|
229
|
-
return getAccessTokenForSasjs(this.requestClient, clientId, authCode)
|
|
230
|
-
}
|
|
231
194
|
/**
|
|
232
195
|
* Checks whether a session is active, or login is required.
|
|
233
196
|
* @returns - a promise which resolves with an object containing three values
|
|
@@ -248,8 +211,7 @@ export class AuthManager {
|
|
|
248
211
|
//Residue can happen in case of session expiration
|
|
249
212
|
await this.logOut()
|
|
250
213
|
|
|
251
|
-
|
|
252
|
-
loginForm = await this.getNewLoginForm()
|
|
214
|
+
loginForm = await this.getNewLoginForm()
|
|
253
215
|
}
|
|
254
216
|
|
|
255
217
|
return Promise.resolve({
|
|
@@ -260,6 +222,12 @@ export class AuthManager {
|
|
|
260
222
|
}
|
|
261
223
|
|
|
262
224
|
private async getNewLoginForm() {
|
|
225
|
+
if (this.serverType === ServerType.Sasjs) {
|
|
226
|
+
// server will be sending CSRF cookie,
|
|
227
|
+
// http client will use it automatically
|
|
228
|
+
return this.requestClient.get('/', undefined)
|
|
229
|
+
}
|
|
230
|
+
|
|
263
231
|
const { result: formResponse } = await this.requestClient.get<string>(
|
|
264
232
|
this.loginUrl.replace('.do', ''),
|
|
265
233
|
undefined,
|
|
@@ -384,5 +352,8 @@ const isCredentialsVerifyError = (response: string): boolean =>
|
|
|
384
352
|
response
|
|
385
353
|
)
|
|
386
354
|
|
|
387
|
-
const isLogInSuccess = (response:
|
|
388
|
-
|
|
355
|
+
const isLogInSuccess = (serverType: ServerType, response: any): boolean => {
|
|
356
|
+
if (serverType === ServerType.Sasjs) return response?.loggedin
|
|
357
|
+
|
|
358
|
+
return /You have signed in/gm.test(response)
|
|
359
|
+
}
|
|
@@ -21,6 +21,7 @@ import {
|
|
|
21
21
|
} from '../utils'
|
|
22
22
|
import { BaseJobExecutor } from './JobExecutor'
|
|
23
23
|
import { parseWeboutResponse } from '../utils/parseWeboutResponse'
|
|
24
|
+
import { Server } from 'https'
|
|
24
25
|
|
|
25
26
|
export interface WaitingRequstPromise {
|
|
26
27
|
promise: Promise<any> | null
|
|
@@ -46,7 +47,7 @@ export class WebJobExecutor extends BaseJobExecutor {
|
|
|
46
47
|
authConfig?: AuthConfig,
|
|
47
48
|
extraResponseAttributes: ExtraResponseAttributes[] = []
|
|
48
49
|
) {
|
|
49
|
-
const loginCallback = loginRequiredCallback
|
|
50
|
+
const loginCallback = loginRequiredCallback
|
|
50
51
|
const program = isRelativePath(sasJob)
|
|
51
52
|
? config.appLoc
|
|
52
53
|
? config.appLoc.replace(/\/?$/, '/') + sasJob.replace(/^\//, '')
|
|
@@ -79,7 +80,7 @@ export class WebJobExecutor extends BaseJobExecutor {
|
|
|
79
80
|
)
|
|
80
81
|
})
|
|
81
82
|
|
|
82
|
-
await loginCallback()
|
|
83
|
+
if (loginCallback) await loginCallback()
|
|
83
84
|
} else {
|
|
84
85
|
reject(new ErrorResponse(e?.message, e))
|
|
85
86
|
}
|
|
@@ -220,6 +221,15 @@ export class WebJobExecutor extends BaseJobExecutor {
|
|
|
220
221
|
}
|
|
221
222
|
|
|
222
223
|
if (e instanceof LoginRequiredError) {
|
|
224
|
+
if (!loginRequiredCallback) {
|
|
225
|
+
reject(
|
|
226
|
+
new ErrorResponse(
|
|
227
|
+
'Request is not authenticated. Make sure .env file exists with valid credentials.',
|
|
228
|
+
e
|
|
229
|
+
)
|
|
230
|
+
)
|
|
231
|
+
}
|
|
232
|
+
|
|
223
233
|
this.appendWaitingRequest(() => {
|
|
224
234
|
return this.execute(
|
|
225
235
|
sasJob,
|
|
@@ -238,7 +248,7 @@ export class WebJobExecutor extends BaseJobExecutor {
|
|
|
238
248
|
)
|
|
239
249
|
})
|
|
240
250
|
|
|
241
|
-
await loginCallback()
|
|
251
|
+
if (loginCallback) await loginCallback()
|
|
242
252
|
} else {
|
|
243
253
|
reject(new ErrorResponse(e?.message, e))
|
|
244
254
|
}
|
|
@@ -1,3 +1,5 @@
|
|
|
1
|
+
import { isSpecialMissing } from '@sasjs/utils/input/validators'
|
|
2
|
+
|
|
1
3
|
/**
|
|
2
4
|
* Converts the given JSON object array to a CSV string.
|
|
3
5
|
* @param data - the array of JSON objects to convert.
|
|
@@ -18,7 +20,6 @@ export const convertToCSV = (
|
|
|
18
20
|
let headers: string[] = []
|
|
19
21
|
let csvTest
|
|
20
22
|
let invalidString = false
|
|
21
|
-
const specialMissingValueRegExp = /^[a-z_]{1}$/i
|
|
22
23
|
|
|
23
24
|
if (formats) {
|
|
24
25
|
headers = Object.keys(formats).map((key) => `${key}:${formats![key]}`)
|
|
@@ -36,7 +37,7 @@ export const convertToCSV = (
|
|
|
36
37
|
hasNullOrNumber = true
|
|
37
38
|
} else if (
|
|
38
39
|
typeof row[field] === 'string' &&
|
|
39
|
-
|
|
40
|
+
isSpecialMissing(row[field])
|
|
40
41
|
) {
|
|
41
42
|
hasSpecialMissingString = true
|
|
42
43
|
}
|
|
@@ -130,10 +131,9 @@ export const convertToCSV = (
|
|
|
130
131
|
value = currentCell === null ? '' : currentCell
|
|
131
132
|
|
|
132
133
|
if (formats && formats[fieldName] === 'best.') {
|
|
133
|
-
if (value && !
|
|
134
|
-
console.log(`🤖[value]🤖`, value)
|
|
134
|
+
if (value && !isSpecialMissing(value)) {
|
|
135
135
|
throw new Error(
|
|
136
|
-
|
|
136
|
+
`A Special missing value can only be a single character from 'A' to 'Z', '_', '.[a-z]', '._'`
|
|
137
137
|
)
|
|
138
138
|
}
|
|
139
139
|
|
|
@@ -1,9 +0,0 @@
|
|
|
1
|
-
import { RequestClient } from '../request/RequestClient';
|
|
2
|
-
/**
|
|
3
|
-
* Performs a login authenticate and returns an auth code for the given client.
|
|
4
|
-
* @param requestClient - the pre-configured HTTP request client
|
|
5
|
-
* @param username - a string representing the username.
|
|
6
|
-
* @param password - a string representing the password.
|
|
7
|
-
* @param clientId - the client ID to authenticate with.
|
|
8
|
-
*/
|
|
9
|
-
export declare const getAuthCodeForSasjs: (requestClient: RequestClient, username: string, password: string, clientId: string) => Promise<string>;
|
|
@@ -1,9 +0,0 @@
|
|
|
1
|
-
import { RequestClient } from '../request/RequestClient';
|
|
2
|
-
/**
|
|
3
|
-
* Performs a login authenticate and returns an auth code for the given client.
|
|
4
|
-
* @param requestClient - the pre-configured HTTP request client
|
|
5
|
-
* @param username - a string representing the username.
|
|
6
|
-
* @param password - a string representing the password.
|
|
7
|
-
* @param clientId - the client ID to authenticate with.
|
|
8
|
-
*/
|
|
9
|
-
export declare const getAuthCodeForSasjs: (requestClient: RequestClient, username: string, password: string, clientId: string) => Promise<string>;
|
|
@@ -1,31 +0,0 @@
|
|
|
1
|
-
import { prefixMessage } from '@sasjs/utils/error'
|
|
2
|
-
import { RequestClient } from '../request/RequestClient'
|
|
3
|
-
|
|
4
|
-
/**
|
|
5
|
-
* Performs a login authenticate and returns an auth code for the given client.
|
|
6
|
-
* @param requestClient - the pre-configured HTTP request client
|
|
7
|
-
* @param username - a string representing the username.
|
|
8
|
-
* @param password - a string representing the password.
|
|
9
|
-
* @param clientId - the client ID to authenticate with.
|
|
10
|
-
*/
|
|
11
|
-
export const getAuthCodeForSasjs = async (
|
|
12
|
-
requestClient: RequestClient,
|
|
13
|
-
username: string,
|
|
14
|
-
password: string,
|
|
15
|
-
clientId: string
|
|
16
|
-
) => {
|
|
17
|
-
const url = '/SASjsApi/auth/authorize'
|
|
18
|
-
const data = { username, password, clientId }
|
|
19
|
-
|
|
20
|
-
const { code: authCode } = await requestClient
|
|
21
|
-
.post<{ code: string }>(url, data, undefined)
|
|
22
|
-
.then((res) => res.result)
|
|
23
|
-
.catch((err) => {
|
|
24
|
-
throw prefixMessage(
|
|
25
|
-
err,
|
|
26
|
-
'Error while authenticating with provided username, password and clientId. '
|
|
27
|
-
)
|
|
28
|
-
})
|
|
29
|
-
|
|
30
|
-
return authCode
|
|
31
|
-
}
|