1
0
mirror of https://github.com/sasjs/adapter.git synced 2025-12-11 17:34:34 +00:00

Compare commits

...

7 Commits

Author SHA1 Message Date
Krishna Acondy
596c1de5cb fix(request-client): return Internal Server Error code in case of Stored Process Error 2021-12-12 20:37:19 +00:00
Allan Bowe
b645d1495b Merge pull request #586 from sasjs/handle-sasjs-server-response
fix: handle sasjs server response
2021-12-08 09:09:42 +00:00
3a4a4c3460 chore: sasjs path optional 2021-12-06 17:44:08 +01:00
Saad Jutt
182de51f9b chore: added comments 2021-12-05 19:27:07 +05:00
Saad Jutt
712d1549c7 feat(server): added sasjs server support 2021-12-05 18:31:36 +05:00
Allan Bowe
81d959c7c1 fix: parsing _webout from response regardless of debug status 2021-11-18 19:56:12 +00:00
7c5adeabb5 feat: parse response in webJobExecutor when server type is sasjs server 2021-11-19 00:35:02 +05:00
7 changed files with 57 additions and 21 deletions

View File

@@ -33,6 +33,7 @@ import { LoginOptions, LoginResult } from './types/Login'
const defaultConfig: SASjsConfig = { const defaultConfig: SASjsConfig = {
serverUrl: '', serverUrl: '',
pathSASJS: '/SASjsApi/stp/execute',
pathSAS9: '/SASStoredProcess/do', pathSAS9: '/SASStoredProcess/do',
pathSASViya: '/SASJobExecution', pathSASViya: '/SASJobExecution',
appLoc: '/Public/seedapp', appLoc: '/Public/seedapp',
@@ -527,10 +528,11 @@ export default class SASjs {
/** /**
* Checks whether a session is active, or login is required. * Checks whether a session is active, or login is required.
* @param accessToken - an optional access token is required for SASjs server type.
* @returns - a promise which resolves with an object containing two values - a boolean `isLoggedIn`, and a string `userName`. * @returns - a promise which resolves with an object containing two values - a boolean `isLoggedIn`, and a string `userName`.
*/ */
public async checkSession() { public async checkSession(accessToken?: string) {
return this.authManager!.checkSession() return this.authManager!.checkSession(accessToken)
} }
/** /**
@@ -563,9 +565,10 @@ export default class SASjs {
/** /**
* Logs out of the configured SAS server. * Logs out of the configured SAS server.
* @param accessToken - an optional access token is required for SASjs server type.
*/ */
public logOut() { public logOut(accessToken?: string) {
return this.authManager!.logOut() return this.authManager!.logOut(accessToken)
} }
/** /**
@@ -975,7 +978,9 @@ export default class SASjs {
this.jobsPath = this.jobsPath =
this.sasjsConfig.serverType === ServerType.SasViya this.sasjsConfig.serverType === ServerType.SasViya
? this.sasjsConfig.pathSASViya ? this.sasjsConfig.pathSASViya
: this.sasjsConfig.pathSAS9 : this.sasjsConfig.serverType === ServerType.Sas9
? this.sasjsConfig.pathSAS9
: this.sasjsConfig.pathSASJS || ''
this.authManager = new AuthManager( this.authManager = new AuthManager(
this.sasjsConfig.serverUrl, this.sasjsConfig.serverUrl,

View File

@@ -21,7 +21,9 @@ export class AuthManager {
this.logoutUrl = this.logoutUrl =
this.serverType === ServerType.Sas9 this.serverType === ServerType.Sas9
? '/SASLogon/logout?' ? '/SASLogon/logout?'
: '/SASLogon/logout.do?' : this.serverType === ServerType.SasViya
? '/SASLogon/logout.do?'
: '/SASjsApi/auth/logout'
} }
/** /**
@@ -180,20 +182,21 @@ export class AuthManager {
/** /**
* Checks whether a session is active, or login is required. * Checks whether a session is active, or login is required.
* @param accessToken - an optional access token is required for SASjs server type.
* @returns - a promise which resolves with an object containing three values * @returns - a promise which resolves with an object containing three values
* - a boolean `isLoggedIn` * - a boolean `isLoggedIn`
* - a string `userName` and * - a string `userName` and
* - a form `loginForm` if not loggedin. * - a form `loginForm` if not loggedin.
*/ */
public async checkSession(): Promise<{ public async checkSession(accessToken?: string): Promise<{
isLoggedIn: boolean isLoggedIn: boolean
userName: string userName: string
loginForm?: any loginForm?: any
}> { }> {
const { isLoggedIn, userName } = await this.fetchUserName() const { isLoggedIn, userName } = await this.fetchUserName(accessToken)
let loginForm = null let loginForm = null
if (!isLoggedIn) { if (!isLoggedIn && this.serverType !== ServerType.Sasjs) {
//We will logout to make sure cookies are removed and login form is presented //We will logout to make sure cookies are removed and login form is presented
//Residue can happen in case of session expiration //Residue can happen in case of session expiration
await this.logOut() await this.logOut()
@@ -218,19 +221,20 @@ export class AuthManager {
return await this.getLoginForm(formResponse) return await this.getLoginForm(formResponse)
} }
private async fetchUserName(): Promise<{ private async fetchUserName(accessToken?: string): Promise<{
isLoggedIn: boolean isLoggedIn: boolean
userName: string userName: string
}> { }> {
//For VIYA we will send request on API endpoint. Which is faster then pinging SASJobExecution.
//For SAS9 we will send request on SASStoredProcess
const url = const url =
this.serverType === ServerType.SasViya this.serverType === ServerType.SasViya
? `${this.serverUrl}/identities/users/@currentUser` ? `${this.serverUrl}/identities/users/@currentUser`
: `${this.serverUrl}/SASStoredProcess` : this.serverType === ServerType.Sas9
? `${this.serverUrl}/SASStoredProcess`
: `${this.serverUrl}/SASjsApi/session`
// Access token is required for server type `SASjs`
const { result: loginResponse } = await this.requestClient const { result: loginResponse } = await this.requestClient
.get<string>(url, undefined, 'text/plain') .get<string>(url, accessToken, 'text/plain')
.catch((err: any) => { .catch((err: any) => {
return { result: 'authErr' } return { result: 'authErr' }
}) })
@@ -257,6 +261,9 @@ export class AuthManager {
.map((name: string) => name.slice(0, 3).toLowerCase()) .map((name: string) => name.slice(0, 3).toLowerCase())
.join('') .join('')
case ServerType.Sasjs:
return response?.username
default: default:
console.error('Server Type not found in extractUserName function') console.error('Server Type not found in extractUserName function')
return '' return ''
@@ -306,8 +313,12 @@ export class AuthManager {
/** /**
* Logs out of the configured SAS server. * Logs out of the configured SAS server.
* @param accessToken - an optional access token is required for SASjs server type.
*/ */
public logOut() { public logOut(accessToken?: string) {
if (this.serverType === ServerType.Sasjs) {
return this.requestClient.post(this.logoutUrl, undefined, accessToken)
}
this.requestClient.clearCsrfTokens() this.requestClient.clearCsrfTokens()
return this.requestClient.get(this.logoutUrl, undefined).then(() => true) return this.requestClient.get(this.logoutUrl, undefined).then(() => true)
} }

View File

@@ -15,7 +15,8 @@ import { SASViyaApiClient } from '../SASViyaApiClient'
import { import {
isRelativePath, isRelativePath,
parseSasViyaDebugResponse, parseSasViyaDebugResponse,
appendExtraResponseAttributes appendExtraResponseAttributes,
getValidJson
} from '../utils' } from '../utils'
import { BaseJobExecutor } from './JobExecutor' import { BaseJobExecutor } from './JobExecutor'
import { parseWeboutResponse } from '../utils/parseWeboutResponse' import { parseWeboutResponse } from '../utils/parseWeboutResponse'
@@ -113,6 +114,7 @@ export class WebJobExecutor extends BaseJobExecutor {
const stringifiedData = JSON.stringify(data) const stringifiedData = JSON.stringify(data)
if ( if (
config.serverType === ServerType.Sas9 || config.serverType === ServerType.Sas9 ||
config.serverType === ServerType.Sasjs ||
stringifiedData.length > 500000 || stringifiedData.length > 500000 ||
stringifiedData.includes(';') stringifiedData.includes(';')
) { ) {
@@ -142,12 +144,25 @@ export class WebJobExecutor extends BaseJobExecutor {
} }
const requestPromise = new Promise((resolve, reject) => { const requestPromise = new Promise((resolve, reject) => {
this.requestClient!.post(apiUrl, formData, undefined) // Access token is required for server type `SASjs`
this.requestClient!.post(apiUrl, formData, authConfig?.access_token)
.then(async (res: any) => { .then(async (res: any) => {
this.requestClient!.appendRequest(res, sasJob, config.debug) const resObj =
this.serverType === ServerType.Sasjs
? {
result: res.result._webout,
log: res.result.log
}
: res
this.requestClient!.appendRequest(resObj, sasJob, config.debug)
let jsonResponse = res.result let jsonResponse = res.result
if (this.serverType === ServerType.Sasjs) {
const webout = parseWeboutResponse(res.result._webout, apiUrl)
jsonResponse = getValidJson(webout)
}
if (config.debug) { if (config.debug) {
switch (this.serverType) { switch (this.serverType) {
case ServerType.SasViya: case ServerType.SasViya:

View File

@@ -627,7 +627,7 @@ const parseError = (data: string) => {
if (parts.length > 1) { if (parts.length > 1) {
const log = parts[1].split('<pre>')[1].split('</pre>')[0] const log = parts[1].split('<pre>')[1].split('</pre>')[0]
const message = `This request completed with errors.` const message = `This request completed with errors.`
return new JobExecutionError(404, message, log) return new JobExecutionError(500, message, log)
} }
} }
} catch (_) {} } catch (_) {}

View File

@@ -12,6 +12,11 @@ export class SASjsConfig {
* streamed. * streamed.
*/ */
serverUrl: string = '' serverUrl: string = ''
/**
* The location of the STP Process Web Application. By default the adapter
* will use '/SASjsApi/stp/execute' on SAS JS.
*/
pathSASJS?: string = ''
/** /**
* The location of the Stored Process Web Application. By default the adapter * The location of the Stored Process Web Application. By default the adapter
* will use '/SASStoredProcess/do' on SAS 9. * will use '/SASStoredProcess/do' on SAS 9.

View File

@@ -4,7 +4,7 @@ import { JsonParseArrayError, InvalidJsonError } from '../types/errors'
* if string passed then parse the string to json else if throw error for all other types unless it is not a valid json object. * if string passed then parse the string to json else if throw error for all other types unless it is not a valid json object.
* @param str - string to check. * @param str - string to check.
*/ */
export const getValidJson = (str: string | object) => { export const getValidJson = (str: string | object): object => {
try { try {
if (str === null || str === undefined) throw new InvalidJsonError() if (str === null || str === undefined) throw new InvalidJsonError()

View File

@@ -1,6 +1,6 @@
import { WeboutResponseError } from '../types/errors' import { WeboutResponseError } from '../types/errors'
export const parseWeboutResponse = (response: string, url?: string) => { export const parseWeboutResponse = (response: string, url?: string): string => {
let sasResponse = '' let sasResponse = ''
if (response.includes('>>weboutBEGIN<<')) { if (response.includes('>>weboutBEGIN<<')) {