@sasjs/adapter 4.10.2 → 4.11.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.
@@ -0,0 +1,5 @@
1
+ /**
2
+ * Provides preferred language of the user.
3
+ * @returns A string representing the preferred language of the user, usually the language of the browser UI. Examples of valid language codes include "en", "en-US", "fr", "fr-FR", "es-ES". More info available https://datatracker.ietf.org/doc/html/rfc5646
4
+ */
5
+ export declare const getUserLanguage: () => string | undefined;
@@ -20,3 +20,4 @@ export * from './serialize';
20
20
  export * from './splitChunks';
21
21
  export * from './validateInput';
22
22
  export * from './getFormData';
23
+ export * from './getUserLanguage';
package/package.json CHANGED
@@ -84,5 +84,5 @@
84
84
  "https": "1.0.0",
85
85
  "tough-cookie": "4.1.3"
86
86
  },
87
- "version": "4.10.2"
87
+ "version": "4.11.0"
88
88
  }
@@ -7,6 +7,7 @@ import { extractUserLongNameSas9 } from '../utils/sas9/extractUserLongNameSas9'
7
7
  import { openWebPage } from './openWebPage'
8
8
  import { verifySas9Login } from './verifySas9Login'
9
9
  import { verifySasViyaLogin } from './verifySasViyaLogin'
10
+ import { isLogInSuccessHeaderPresent } from './'
10
11
 
11
12
  export class AuthManager {
12
13
  public userName = ''
@@ -132,7 +133,7 @@ export class AuthManager {
132
133
 
133
134
  let loginResponse = await this.sendLoginRequest(loginForm, loginParams)
134
135
 
135
- let isLoggedIn = isLogInSuccess(this.serverType, loginResponse)
136
+ let isLoggedIn = isLogInSuccessHeaderPresent(this.serverType, loginResponse)
136
137
 
137
138
  if (!isLoggedIn) {
138
139
  if (isCredentialsVerifyError(loginResponse)) {
@@ -217,7 +218,7 @@ export class AuthManager {
217
218
  * - a boolean `isLoggedIn`
218
219
  * - a string `userName`,
219
220
  * - a string `userFullName` and
220
- * - a form `loginForm` if not loggedin.
221
+ * - a form `loginForm` if not loggedIn.
221
222
  */
222
223
  public async checkSession(): Promise<LoginResultInternal> {
223
224
  const { isLoggedIn, userName, userLongName } = await this.fetchUserName()
@@ -384,9 +385,3 @@ const isCredentialsVerifyError = (response: string): boolean =>
384
385
  /An error occurred while the system was verifying your credentials. Please enter your credentials again./gm.test(
385
386
  response
386
387
  )
387
-
388
- const isLogInSuccess = (serverType: ServerType, response: any): boolean => {
389
- if (serverType === ServerType.Sasjs) return response?.loggedin
390
-
391
- return /You have signed in/gm.test(response)
392
- }
package/src/auth/index.ts CHANGED
@@ -1,3 +1,4 @@
1
1
  export * from './AuthManager'
2
2
  export * from './isAuthorizeFormRequired'
3
3
  export * from './isLoginRequired'
4
+ export * from './loginHeader'
@@ -0,0 +1,97 @@
1
+ import { ServerType } from '@sasjs/utils/types'
2
+ import { getUserLanguage } from '../utils'
3
+
4
+ const enLoginSuccessHeader = 'You have signed in.'
5
+
6
+ export const defaultSuccessHeaderKey = 'default'
7
+
8
+ // The following headers provided by https://github.com/sasjs/adapter/issues/835#issuecomment-2177818601
9
+ export const loginSuccessHeaders: { [key: string]: string } = {
10
+ es: `Ya se ha iniciado la sesi\u00f3n.`,
11
+ th: `\u0e04\u0e38\u0e13\u0e25\u0e07\u0e0a\u0e37\u0e48\u0e2d\u0e40\u0e02\u0e49\u0e32\u0e43\u0e0a\u0e49\u0e41\u0e25\u0e49\u0e27`,
12
+ ja: `\u30b5\u30a4\u30f3\u30a4\u30f3\u3057\u307e\u3057\u305f\u3002`,
13
+ nb: `Du har logget deg p\u00e5.`,
14
+ sl: `Prijavili ste se.`,
15
+ ar: `\u0644\u0642\u062f \u0642\u0645\u062a `,
16
+ sk: `Prihl\u00e1sili ste sa.`,
17
+ zh_HK: `\u60a8\u5df2\u767b\u5165\u3002`,
18
+ zh_CN: `\u60a8\u5df2\u767b\u5f55\u3002`,
19
+ it: `L'utente si \u00e8 connesso.`,
20
+ sv: `Du har loggat in.`,
21
+ he: `\u05e0\u05db\u05e0\u05e1\u05ea `,
22
+ nl: `U hebt zich aangemeld.`,
23
+ pl: `Zosta\u0142e\u015b zalogowany.`,
24
+ ko: `\ub85c\uadf8\uc778\ud588\uc2b5\ub2c8\ub2e4.`,
25
+ zh_TW: `\u60a8\u5df2\u767b\u5165\u3002`,
26
+ tr: `Oturum a\u00e7t\u0131n\u0131z.`,
27
+ iw: `\u05e0\u05db\u05e0\u05e1\u05ea `,
28
+ fr: `Vous \u00eates connect\u00e9.`,
29
+ uk: `\u0412\u0438 \u0432\u0432\u0456\u0439\u0448\u043b\u0438 \u0432 \u043e\u0431\u043b\u0456\u043a\u043e\u0432\u0438\u0439 \u0437\u0430\u043f\u0438\u0441.`,
30
+ pt_BR: `Voc\u00ea se conectou.`,
31
+ no: `Du har logget deg p\u00e5.`,
32
+ cs: `Jste p\u0159ihl\u00e1\u0161eni.`,
33
+ fi: `Olet kirjautunut sis\u00e4\u00e4n.`,
34
+ ru: `\u0412\u044b \u0432\u044b\u043f\u043e\u043b\u043d\u0438\u043b\u0438 \u0432\u0445\u043e\u0434 \u0432 \u0441\u0438\u0441\u0442\u0435\u043c\u0443.`,
35
+ el: `\u0388\u03c7\u03b5\u03c4\u03b5 \u03c3\u03c5\u03bd\u03b4\u03b5\u03b8\u03b5\u03af.`,
36
+ hr: `Prijavili ste se.`,
37
+ da: `Du er logget p\u00e5.`,
38
+ de: `Sie sind jetzt angemeldet.`,
39
+ sh: `Prijavljeni ste.`,
40
+ pt: `Iniciou sess\u00e3o.`,
41
+ hu: `Bejelentkezett.`,
42
+ sr: `Prijavljeni ste.`,
43
+ en: enLoginSuccessHeader,
44
+ [defaultSuccessHeaderKey]: enLoginSuccessHeader
45
+ }
46
+
47
+ /**
48
+ * Provides expected login header based on language settings of the browser.
49
+ * @returns - expected header as a string.
50
+ */
51
+ export const getExpectedLogInSuccessHeader = (): string => {
52
+ // get default success header
53
+ let successHeader = loginSuccessHeaders[defaultSuccessHeaderKey]
54
+
55
+ // get user language based on language settings of the browser
56
+ const userLang = getUserLanguage()
57
+
58
+ if (userLang) {
59
+ // get success header on exact match of the language code
60
+ let userLangSuccessHeader = loginSuccessHeaders[userLang]
61
+
62
+ // handle case when there is no exact match of the language code
63
+ if (!userLangSuccessHeader) {
64
+ // get all supported language codes
65
+ const headerLanguages = Object.keys(loginSuccessHeaders)
66
+
67
+ // find language code on partial match
68
+ const headerLanguage = headerLanguages.find((language) =>
69
+ new RegExp(language, 'i').test(userLang)
70
+ )
71
+
72
+ // reassign success header if partial match was found
73
+ if (headerLanguage) {
74
+ successHeader = loginSuccessHeaders[headerLanguage]
75
+ }
76
+ } else {
77
+ successHeader = userLangSuccessHeader
78
+ }
79
+ }
80
+
81
+ return successHeader
82
+ }
83
+
84
+ /**
85
+ * Checks if Login success header is present in the response based on language settings of the browser.
86
+ * @param serverType - server type.
87
+ * @param response - response object.
88
+ * @returns - boolean indicating if Login success header is present.
89
+ */
90
+ export const isLogInSuccessHeaderPresent = (
91
+ serverType: ServerType,
92
+ response: any
93
+ ): boolean => {
94
+ if (serverType === ServerType.Sasjs) return response?.loggedIn
95
+
96
+ return new RegExp(getExpectedLogInSuccessHeader(), 'gm').test(response)
97
+ }
@@ -1,7 +1,6 @@
1
1
  import { SasAuthResponse } from '@sasjs/utils/types'
2
2
 
3
3
  export const mockLoginAuthoriseRequiredResponse = `<form id="application_authorization" action="/SASLogon/oauth/authorize" method="POST"><input type="hidden" name="X-Uaa-Csrf" value="2nfuxIn6WaOURWL7tzTXCe"/>`
4
- export const mockLoginSuccessResponse = `You have signed in`
5
4
 
6
5
  export const mockAuthResponse: SasAuthResponse = {
7
6
  access_token: 'acc355',
@@ -1,4 +1,5 @@
1
1
  import { delay } from '../utils'
2
+ import { getExpectedLogInSuccessHeader } from './'
2
3
 
3
4
  export async function verifySas9Login(loginPopup: Window): Promise<{
4
5
  isLoggedIn: boolean
@@ -6,13 +7,17 @@ export async function verifySas9Login(loginPopup: Window): Promise<{
6
7
  let isLoggedIn = false
7
8
  let startTime = new Date()
8
9
  let elapsedSeconds = 0
10
+
9
11
  do {
10
12
  await delay(1000)
11
13
  if (loginPopup.closed) break
12
14
 
13
15
  isLoggedIn =
14
16
  loginPopup.window.location.href.includes('SASLogon') &&
15
- loginPopup.window.document.body.innerText.includes('You have signed in.')
17
+ loginPopup.window.document.body.innerText.includes(
18
+ getExpectedLogInSuccessHeader()
19
+ )
20
+
16
21
  elapsedSeconds = (new Date().valueOf() - startTime.valueOf()) / 1000
17
22
  } while (!isLoggedIn && elapsedSeconds < 5 * 60)
18
23
 
@@ -1,4 +1,5 @@
1
1
  import { delay } from '../utils'
2
+ import { getExpectedLogInSuccessHeader } from './'
2
3
 
3
4
  export async function verifySasViyaLogin(loginPopup: Window): Promise<{
4
5
  isLoggedIn: boolean
@@ -6,23 +7,32 @@ export async function verifySasViyaLogin(loginPopup: Window): Promise<{
6
7
  let isLoggedIn = false
7
8
  let startTime = new Date()
8
9
  let elapsedSeconds = 0
10
+
9
11
  do {
10
12
  await delay(1000)
13
+
11
14
  if (loginPopup.closed) break
15
+
12
16
  isLoggedIn = isLoggedInSASVIYA()
17
+
13
18
  elapsedSeconds = (new Date().valueOf() - startTime.valueOf()) / 1000
14
19
  } while (!isLoggedIn && elapsedSeconds < 5 * 60)
15
20
 
16
21
  let isAuthorized = false
22
+
17
23
  startTime = new Date()
24
+
18
25
  do {
19
26
  await delay(1000)
27
+
20
28
  if (loginPopup.closed) break
29
+
21
30
  isAuthorized =
22
31
  loginPopup.window.location.href.includes('SASLogon') ||
23
32
  loginPopup.window.document.body?.innerText?.includes(
24
- 'You have signed in.'
33
+ getExpectedLogInSuccessHeader()
25
34
  )
35
+
26
36
  elapsedSeconds = (new Date().valueOf() - startTime.valueOf()) / 1000
27
37
  } while (!isAuthorized && elapsedSeconds < 5 * 60)
28
38
 
@@ -0,0 +1,10 @@
1
+ interface IEnavigator {
2
+ userLanguage?: string
3
+ }
4
+
5
+ /**
6
+ * Provides preferred language of the user.
7
+ * @returns A string representing the preferred language of the user, usually the language of the browser UI. Examples of valid language codes include "en", "en-US", "fr", "fr-FR", "es-ES". More info available https://datatracker.ietf.org/doc/html/rfc5646
8
+ */
9
+ export const getUserLanguage = () =>
10
+ window.navigator.language || (window.navigator as IEnavigator).userLanguage
@@ -20,3 +20,4 @@ export * from './serialize'
20
20
  export * from './splitChunks'
21
21
  export * from './validateInput'
22
22
  export * from './getFormData'
23
+ export * from './getUserLanguage'
@@ -0,0 +1,5 @@
1
+ /**
2
+ * Provides preferred language of the user.
3
+ * @returns A string representing the preferred language of the user, usually the language of the browser UI. Examples of valid language codes include "en", "en-US", "fr", "fr-FR", "es-ES". More info available https://datatracker.ietf.org/doc/html/rfc5646
4
+ */
5
+ export declare const getUserLanguage: () => string | undefined;
package/utils/index.d.ts CHANGED
@@ -20,3 +20,4 @@ export * from './serialize';
20
20
  export * from './splitChunks';
21
21
  export * from './validateInput';
22
22
  export * from './getFormData';
23
+ export * from './getUserLanguage';