@sasjs/adapter 3.1.0 → 3.2.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.
Files changed (47) hide show
  1. package/SASViyaApiClient.d.ts +2 -8
  2. package/SASjs.d.ts +16 -10
  3. package/SASjsApiClient.d.ts +22 -0
  4. package/auth/AuthManager.d.ts +12 -4
  5. package/auth/getAccessTokenForSasjs.d.ts +11 -0
  6. package/auth/{getAccessToken.d.ts → getAccessTokenForViya.d.ts} +1 -1
  7. package/auth/getAuthCodeForSasjs.d.ts +9 -0
  8. package/auth/getTokens.d.ts +3 -2
  9. package/auth/refreshTokensForSasjs.d.ts +10 -0
  10. package/auth/{refreshTokens.d.ts → refreshTokensForViya.d.ts} +2 -2
  11. package/auth/spec/{getAccessToken.spec.d.ts → getAccessTokenForSasjs.spec.d.ts} +0 -0
  12. package/auth/spec/{refreshTokens.spec.d.ts → getAccessTokenForViya.spec.d.ts} +0 -0
  13. package/auth/spec/mockResponses.d.ts +4 -0
  14. package/auth/spec/refreshTokensForSasjs.spec.d.ts +1 -0
  15. package/auth/spec/refreshTokensForViya.spec.d.ts +1 -0
  16. package/index.js +2 -2
  17. package/node/SASViyaApiClient.d.ts +2 -8
  18. package/node/SASjs.d.ts +15 -9
  19. package/node/SASjsApiClient.d.ts +22 -0
  20. package/node/auth/AuthManager.d.ts +11 -3
  21. package/node/auth/getAccessTokenForSasjs.d.ts +11 -0
  22. package/node/auth/{getAccessToken.d.ts → getAccessTokenForViya.d.ts} +1 -1
  23. package/node/auth/getAuthCodeForSasjs.d.ts +9 -0
  24. package/node/auth/getTokens.d.ts +3 -2
  25. package/node/auth/refreshTokensForSasjs.d.ts +10 -0
  26. package/node/auth/{refreshTokens.d.ts → refreshTokensForViya.d.ts} +2 -2
  27. package/node/index.js +2 -2
  28. package/node/request/RequestClient.d.ts +4 -0
  29. package/node/request/SasjsRequestClient.d.ts +8 -0
  30. package/package.json +1 -1
  31. package/request/RequestClient.d.ts +4 -0
  32. package/request/SasjsRequestClient.d.ts +8 -0
  33. package/src/SASViyaApiClient.ts +10 -5
  34. package/src/SASjs.ts +83 -47
  35. package/src/SASjsApiClient.ts +43 -0
  36. package/src/auth/AuthManager.ts +65 -10
  37. package/src/auth/getAccessTokenForSasjs.ts +36 -0
  38. package/src/auth/{getAccessToken.ts → getAccessTokenForViya.ts} +1 -1
  39. package/src/auth/getAuthCodeForSasjs.ts +31 -0
  40. package/src/auth/getTokens.ts +16 -9
  41. package/src/auth/refreshTokensForSasjs.ts +35 -0
  42. package/src/auth/{refreshTokens.ts → refreshTokensForViya.ts} +2 -2
  43. package/src/auth/spec/mockResponses.ts +5 -0
  44. package/src/job-execution/WebJobExecutor.ts +0 -1
  45. package/src/request/RequestClient.ts +11 -0
  46. package/src/request/Sas9RequestClient.ts +1 -1
  47. package/src/request/SasjsRequestClient.ts +23 -0
@@ -0,0 +1,36 @@
1
+ import { prefixMessage } from '@sasjs/utils/error'
2
+ import { RequestClient } from '../request/RequestClient'
3
+
4
+ /**
5
+ * Exchanges the auth code for an access token for the given client.
6
+ * @param requestClient - the pre-configured HTTP request client
7
+ * @param clientId - the client ID to authenticate with.
8
+ * @param authCode - the auth code received from the server.
9
+ */
10
+ export async function getAccessTokenForSasjs(
11
+ requestClient: RequestClient,
12
+ clientId: string,
13
+ authCode: string
14
+ ) {
15
+ const url = '/SASjsApi/auth/token'
16
+ const data = {
17
+ clientId,
18
+ code: authCode
19
+ }
20
+
21
+ return await requestClient
22
+ .post(url, data, undefined)
23
+ .then((res) => {
24
+ const sasAuth = res.result as {
25
+ accessToken: string
26
+ refreshToken: string
27
+ }
28
+ return {
29
+ access_token: sasAuth.accessToken,
30
+ refresh_token: sasAuth.refreshToken
31
+ }
32
+ })
33
+ .catch((err) => {
34
+ throw prefixMessage(err, 'Error while getting access token. ')
35
+ })
36
+ }
@@ -10,7 +10,7 @@ import { RequestClient } from '../request/RequestClient'
10
10
  * @param clientSecret - the client secret to authenticate with.
11
11
  * @param authCode - the auth code received from the server.
12
12
  */
13
- export async function getAccessToken(
13
+ export async function getAccessTokenForViya(
14
14
  requestClient: RequestClient,
15
15
  clientId: string,
16
16
  clientSecret: string,
@@ -0,0 +1,31 @@
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
+ }
@@ -3,18 +3,21 @@ import {
3
3
  isRefreshTokenExpiring,
4
4
  hasTokenExpired
5
5
  } from '@sasjs/utils/auth'
6
- import { AuthConfig } from '@sasjs/utils/types'
6
+ import { AuthConfig, ServerType } from '@sasjs/utils/types'
7
7
  import { RequestClient } from '../request/RequestClient'
8
- import { refreshTokens } from './refreshTokens'
8
+ import { refreshTokensForViya } from './refreshTokensForViya'
9
+ import { refreshTokensForSasjs } from './refreshTokensForSasjs'
9
10
 
10
11
  /**
11
12
  * Returns the auth configuration, refreshing the tokens if necessary.
12
13
  * @param requestClient - the pre-configured HTTP request client
13
14
  * @param authConfig - an object containing a client ID, secret, access token and refresh token
15
+ * @param serverType - server type for which refreshing the tokens, defaults to SASVIYA
14
16
  */
15
17
  export async function getTokens(
16
18
  requestClient: RequestClient,
17
- authConfig: AuthConfig
19
+ authConfig: AuthConfig,
20
+ serverType: ServerType = ServerType.SasViya
18
21
  ): Promise<AuthConfig> {
19
22
  const logger = process.logger || console
20
23
  let { access_token, refresh_token, client, secret } = authConfig
@@ -29,12 +32,16 @@ export async function getTokens(
29
32
  throw new Error(error)
30
33
  }
31
34
  logger.info('Refreshing access and refresh tokens.')
32
- ;({ access_token, refresh_token } = await refreshTokens(
33
- requestClient,
34
- client,
35
- secret,
36
- refresh_token
37
- ))
35
+ const tokens =
36
+ serverType === ServerType.SasViya
37
+ ? await refreshTokensForViya(
38
+ requestClient,
39
+ client,
40
+ secret,
41
+ refresh_token
42
+ )
43
+ : await refreshTokensForSasjs(requestClient, refresh_token)
44
+ ;({ access_token, refresh_token } = tokens)
38
45
  }
39
46
  return { access_token, refresh_token, client, secret }
40
47
  }
@@ -0,0 +1,35 @@
1
+ import { prefixMessage } from '@sasjs/utils/error'
2
+ import { RequestClient } from '../request/RequestClient'
3
+
4
+ /**
5
+ * Exchanges the refresh token for an access token for the given client.
6
+ * @param requestClient - the pre-configured HTTP request client
7
+ * @param refreshToken - the refresh token received from the server.
8
+ */
9
+ export async function refreshTokensForSasjs(
10
+ requestClient: RequestClient,
11
+ refreshToken: string
12
+ ) {
13
+ const url = '/SASjsApi/auth/refresh'
14
+ const headers = {
15
+ Authorization: 'Bearer ' + refreshToken
16
+ }
17
+
18
+ const authResponse = await requestClient
19
+ .post(url, undefined, undefined, undefined, headers)
20
+ .then((res) => {
21
+ const sasAuth = res.result as {
22
+ accessToken: string
23
+ refreshToken: string
24
+ }
25
+ return {
26
+ access_token: sasAuth.accessToken,
27
+ refresh_token: sasAuth.refreshToken
28
+ }
29
+ })
30
+ .catch((err) => {
31
+ throw prefixMessage(err, 'Error while refreshing tokens')
32
+ })
33
+
34
+ return authResponse
35
+ }
@@ -8,9 +8,9 @@ import { RequestClient } from '../request/RequestClient'
8
8
  * @param requestClient - the pre-configured HTTP request client
9
9
  * @param clientId - the client ID to authenticate with.
10
10
  * @param clientSecret - the client secret to authenticate with.
11
- * @param authCode - the refresh token received from the server.
11
+ * @param refreshToken - the refresh token received from the server.
12
12
  */
13
- export async function refreshTokens(
13
+ export async function refreshTokensForViya(
14
14
  requestClient: RequestClient,
15
15
  clientId: string,
16
16
  clientSecret: string,
@@ -13,6 +13,11 @@ export const mockAuthResponse: SasAuthResponse = {
13
13
  jti: 'test'
14
14
  }
15
15
 
16
+ export const mockSasjsAuthResponse = {
17
+ access_token: 'acc355',
18
+ refresh_token: 'r3fr35h'
19
+ }
20
+
16
21
  export const generateToken = (timeToLiveSeconds: number): string => {
17
22
  const exp =
18
23
  new Date(new Date().getTime() + timeToLiveSeconds * 1000).getTime() / 1000
@@ -144,7 +144,6 @@ export class WebJobExecutor extends BaseJobExecutor {
144
144
  }
145
145
 
146
146
  const requestPromise = new Promise((resolve, reject) => {
147
- // Access token is required for server type `SASjs`
148
147
  this.requestClient!.post(apiUrl, formData, authConfig?.access_token)
149
148
  .then(async (res: any) => {
150
149
  const resObj =
@@ -48,7 +48,9 @@ export interface HttpClient {
48
48
  ): Promise<{ result: T; etag: string }>
49
49
 
50
50
  getCsrfToken(type: 'general' | 'file'): CsrfToken | undefined
51
+ saveLocalStorageToken(accessToken: string, refreshToken: string): void
51
52
  clearCsrfTokens(): void
53
+ clearLocalStorageTokens(): void
52
54
  getBaseUrl(): string
53
55
  }
54
56
 
@@ -70,6 +72,11 @@ export class RequestClient implements HttpClient {
70
72
  this.createHttpClient(baseUrl, httpsAgentOptions)
71
73
  }
72
74
 
75
+ public saveLocalStorageToken(accessToken: string, refreshToken: string) {
76
+ localStorage.setItem('accessToken', accessToken)
77
+ localStorage.setItem('refreshToken', refreshToken)
78
+ }
79
+
73
80
  public getCsrfToken(type: 'general' | 'file' = 'general') {
74
81
  return type === 'file' ? this.fileUploadCsrfToken : this.csrfToken
75
82
  }
@@ -78,6 +85,10 @@ export class RequestClient implements HttpClient {
78
85
  this.csrfToken = { headerName: '', value: '' }
79
86
  this.fileUploadCsrfToken = { headerName: '', value: '' }
80
87
  }
88
+ public clearLocalStorageTokens() {
89
+ localStorage.setItem('accessToken', '')
90
+ localStorage.setItem('refreshToken', '')
91
+ }
81
92
 
82
93
  public getBaseUrl() {
83
94
  return this.httpClient.defaults.baseURL || ''
@@ -87,7 +87,7 @@ export class Sas9RequestClient extends RequestClient {
87
87
  })
88
88
  }
89
89
 
90
- public post<T>(
90
+ public async post<T>(
91
91
  url: string,
92
92
  data: any,
93
93
  accessToken: string | undefined,
@@ -0,0 +1,23 @@
1
+ import { RequestClient } from './RequestClient'
2
+
3
+ /**
4
+ * Specific request client for SASJS.
5
+ * Append tokens in headers.
6
+ */
7
+ export class SasjsRequestClient extends RequestClient {
8
+ getHeaders = (accessToken: string | undefined, contentType: string) => {
9
+ const headers: any = {}
10
+
11
+ if (contentType !== 'application/x-www-form-urlencoded')
12
+ headers['Content-Type'] = contentType
13
+
14
+ headers.Accept = contentType === 'application/json' ? contentType : '*/*'
15
+
16
+ if (!accessToken)
17
+ accessToken = localStorage.getItem('accessToken') ?? undefined
18
+
19
+ if (accessToken) headers.Authorization = `Bearer ${accessToken}`
20
+
21
+ return headers
22
+ }
23
+ }