login-authorization-v2 1.1.5 → 2.0.0-beta.1

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 (94) hide show
  1. package/README.md +54 -54
  2. package/babel.config.js +6 -0
  3. package/coverage/clover.xml +140 -0
  4. package/coverage/coverage-final.json +8 -0
  5. package/coverage/lcov-report/base.css +224 -0
  6. package/coverage/lcov-report/block-navigation.js +87 -0
  7. package/coverage/lcov-report/common-authorization-v2/index.html +116 -0
  8. package/coverage/lcov-report/common-authorization-v2/index.ts.html +547 -0
  9. package/coverage/lcov-report/common-authorization-v2/src/compatible.ts.html +223 -0
  10. package/coverage/lcov-report/common-authorization-v2/src/constance.ts.html +106 -0
  11. package/coverage/lcov-report/common-authorization-v2/src/cookie.ts.html +346 -0
  12. package/coverage/lcov-report/common-authorization-v2/src/dom.ts.html +262 -0
  13. package/coverage/lcov-report/common-authorization-v2/src/index.html +206 -0
  14. package/coverage/lcov-report/common-authorization-v2/src/request.ts.html +361 -0
  15. package/coverage/lcov-report/common-authorization-v2/src/shares.ts.html +163 -0
  16. package/coverage/lcov-report/common-authorization-v2/src/types.ts.html +412 -0
  17. package/coverage/lcov-report/common-authorization-v2/src/utils.ts.html +145 -0
  18. package/coverage/lcov-report/compatible.ts.html +223 -0
  19. package/coverage/lcov-report/constance.ts.html +106 -0
  20. package/coverage/lcov-report/cookie.ts.html +310 -0
  21. package/coverage/lcov-report/dom.ts.html +262 -0
  22. package/coverage/lcov-report/favicon.png +0 -0
  23. package/coverage/lcov-report/index.html +206 -0
  24. package/coverage/lcov-report/prettify.css +1 -0
  25. package/coverage/lcov-report/prettify.js +2 -0
  26. package/coverage/lcov-report/shares.ts.html +163 -0
  27. package/coverage/lcov-report/sort-arrow-sprite.png +0 -0
  28. package/coverage/lcov-report/sorter.js +210 -0
  29. package/coverage/lcov-report/types.ts.html +412 -0
  30. package/coverage/lcov-report/utils.ts.html +145 -0
  31. package/coverage/lcov.info +268 -0
  32. package/dist/compatible.d.ts +10 -0
  33. package/dist/compatible.d.ts.map +1 -0
  34. package/dist/constance.d.ts +6 -0
  35. package/dist/constance.d.ts.map +1 -0
  36. package/dist/cookie.d.ts +8 -0
  37. package/dist/cookie.d.ts.map +1 -0
  38. package/dist/dom.d.ts +2 -0
  39. package/dist/dom.d.ts.map +1 -0
  40. package/dist/index.d.ts +15 -0
  41. package/dist/index.d.ts.map +1 -0
  42. package/dist/index.esm.js +498 -0
  43. package/dist/index.js.LICENSE.txt +1 -0
  44. package/dist/{index.js → index.umd.js} +125 -14
  45. package/dist/request.d.ts +36 -0
  46. package/dist/request.d.ts.map +1 -0
  47. package/dist/shares.d.ts +10 -0
  48. package/dist/shares.d.ts.map +1 -0
  49. package/dist/src/compatible.d.ts +10 -0
  50. package/dist/src/compatible.d.ts.map +1 -0
  51. package/dist/src/constance.d.ts +8 -0
  52. package/dist/src/constance.d.ts.map +1 -0
  53. package/dist/src/cookie.d.ts +8 -0
  54. package/dist/src/cookie.d.ts.map +1 -0
  55. package/dist/src/dom.d.ts +3 -0
  56. package/dist/src/dom.d.ts.map +1 -0
  57. package/dist/src/request.d.ts +36 -0
  58. package/dist/src/request.d.ts.map +1 -0
  59. package/dist/src/shares.d.ts +10 -0
  60. package/dist/src/shares.d.ts.map +1 -0
  61. package/dist/src/types.d.ts +89 -0
  62. package/dist/src/types.d.ts.map +1 -0
  63. package/dist/src/utils.d.ts +4 -0
  64. package/dist/src/utils.d.ts.map +1 -0
  65. package/dist/test/cookie.test.d.ts +2 -0
  66. package/dist/test/cookie.test.d.ts.map +1 -0
  67. package/dist/test/shares.test.d.ts +2 -0
  68. package/dist/test/shares.test.d.ts.map +1 -0
  69. package/dist/types.d.ts +89 -0
  70. package/dist/types.d.ts.map +1 -0
  71. package/dist/utils.d.ts +2 -0
  72. package/dist/utils.d.ts.map +1 -0
  73. package/index.html +28 -0
  74. package/index.ts +154 -0
  75. package/jest.config.js +6 -0
  76. package/package.json +55 -28
  77. package/src/compatible.ts +46 -0
  78. package/src/constance.ts +7 -0
  79. package/src/cookie.ts +75 -0
  80. package/src/dom.ts +59 -0
  81. package/src/request.ts +99 -0
  82. package/src/shares.ts +26 -0
  83. package/src/types.ts +109 -0
  84. package/src/utils.ts +20 -0
  85. package/tests/compatible.test.ts +420 -0
  86. package/tests/cookie.test.ts +78 -0
  87. package/tests/dom.test.ts +95 -0
  88. package/tests/index.test.ts +126 -0
  89. package/tests/shares.test.ts +52 -0
  90. package/tests/utils.test.ts +79 -0
  91. package/tsconfig.json +49 -0
  92. package/webpack.config.mjs +47 -0
  93. package/index.js +0 -304
  94. package/webpack.config.js +0 -9
@@ -0,0 +1,89 @@
1
+ declare const modules: readonly [{
2
+ readonly href: "";
3
+ readonly name: "commonLogin";
4
+ }, {
5
+ readonly href: "";
6
+ readonly name: "App";
7
+ }, {
8
+ readonly href: "";
9
+ readonly name: "Portal";
10
+ }, {
11
+ readonly href: "";
12
+ readonly name: "AgentPortal";
13
+ }, {
14
+ readonly href: "";
15
+ readonly name: "AdminPortal";
16
+ }, {
17
+ readonly href: "";
18
+ readonly name: "CRM";
19
+ }, {
20
+ readonly href: "";
21
+ readonly name: "Finance";
22
+ }, {
23
+ readonly href: "";
24
+ readonly name: "FundingAdmin";
25
+ }, {
26
+ readonly href: "";
27
+ readonly name: "MessageTemplate";
28
+ }, {
29
+ readonly href: "";
30
+ readonly name: "Translate";
31
+ }, {
32
+ readonly href: "";
33
+ readonly name: "TradeConfig";
34
+ }, {
35
+ readonly href: "";
36
+ readonly name: "Ticket";
37
+ }, {
38
+ readonly href: "";
39
+ readonly name: "IBPortalAdmin";
40
+ }, {
41
+ readonly href: "";
42
+ readonly name: "OPPortal";
43
+ }, {
44
+ readonly href: "";
45
+ readonly name: "ClientInfoHub";
46
+ }, {
47
+ readonly href: "";
48
+ readonly name: "Promotion";
49
+ }];
50
+ export type ModuleName = typeof modules[number]['name'];
51
+ export type UserInfo = {
52
+ 'aud': string;
53
+ 'aud_time': number;
54
+ 'cognito:groups': ModuleName[];
55
+ 'cognito:username': string;
56
+ 'custom:encrypt_email_var': string;
57
+ 'custom:tenant_id': Tenant;
58
+ 'custom:user_id': string;
59
+ 'email': string;
60
+ 'email_verified': boolean;
61
+ 'exp': number;
62
+ 'event_id': string;
63
+ 'iat': number;
64
+ 'iss': string;
65
+ 'jti': string;
66
+ 'origin_jti': string;
67
+ 'preferred_username': string;
68
+ 'sub': string;
69
+ 'token_use': string;
70
+ };
71
+ export declare enum Brand {
72
+ ZERO = 1,
73
+ HEDGEHOOD = 2,
74
+ NISE = 3
75
+ }
76
+ export declare enum Tenant {
77
+ ZERO_INT = 1,
78
+ HEDGEHOOD = 2,
79
+ ZERO_NZ = 3,
80
+ ZERO_LA = 4,
81
+ ZERO_BR = 4,
82
+ NISE_EU = 5
83
+ }
84
+ export declare enum SystemType {
85
+ Staff = "staff",
86
+ Client = "client"
87
+ }
88
+ export {};
89
+ //# sourceMappingURL=types.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"types.d.ts","sourceRoot":"","sources":["../src/types.ts"],"names":[],"mappings":"AAAA,QAAA,MAAM,OAAO;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;EAiEH,CAAA;AAEV,MAAM,MAAM,UAAU,GAAG,OAAO,OAAO,CAAC,MAAM,CAAC,CAAC,MAAM,CAAC,CAAA;AAEvD,MAAM,MAAM,QAAQ,GAAG;IACrB,KAAK,EAAE,MAAM,CAAA;IACb,UAAU,EAAE,MAAM,CAAA;IAClB,gBAAgB,EAAE,UAAU,EAAE,CAAA;IAC9B,kBAAkB,EAAE,MAAM,CAAA;IAC1B,0BAA0B,EAAE,MAAM,CAAA;IAClC,kBAAkB,EAAE,MAAM,CAAA;IAC1B,gBAAgB,EAAE,MAAM,CAAA;IACxB,OAAO,EAAE,MAAM,CAAA;IACf,gBAAgB,EAAE,OAAO,CAAA;IACzB,KAAK,EAAE,MAAM,CAAA;IACb,UAAU,EAAE,MAAM,CAAA;IAClB,KAAK,EAAE,MAAM,CAAA;IACb,KAAK,EAAE,MAAM,CAAA;IACb,KAAK,EAAE,MAAM,CAAA;IACb,YAAY,EAAE,MAAM,CAAA;IACpB,oBAAoB,EAAE,MAAM,CAAA;IAC5B,KAAK,EAAE,MAAM,CAAA;IACb,WAAW,EAAE,MAAM,CAAA;CACpB,CAAA;AAED,oBAAY,KAAK;IACf,IAAI,IAAI;IACR,SAAS,IAAI;IACb,IAAI,IAAI;CACT;AAED,oBAAY,MAAM;IAChB,QAAQ,IAAI;IACZ,SAAS,IAAI;IACb,OAAO,IAAI;IACX,OAAO,IAAI;IACX,OAAO,IAAI;IACX,OAAO,IAAI;CACZ;AAED,oBAAY,UAAU;IACpB,KAAK,UAAU;IACf,MAAM,WAAW;CAClB"}
@@ -0,0 +1,2 @@
1
+ export declare const isMobile: () => boolean;
2
+ //# sourceMappingURL=utils.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"utils.d.ts","sourceRoot":"","sources":["../src/utils.ts"],"names":[],"mappings":"AAAA,eAAO,MAAM,QAAQ,QAAM,OAG1B,CAAA"}
package/index.html ADDED
@@ -0,0 +1,28 @@
1
+ <!doctype html>
2
+ <html lang="en">
3
+ <head>
4
+ <meta charset="UTF-8">
5
+ <meta name="viewport"
6
+ content="width=device-width, user-scalable=no, initial-scale=1.0, maximum-scale=1.0, minimum-scale=1.0">
7
+ <meta http-equiv="X-UA-Compatible" content="ie=edge">
8
+ <title>Document</title>
9
+ </head>
10
+ <body>
11
+ </body>
12
+ <script type="module">
13
+ import { make, setAccessToken, setRefreshToken } from './dist/index.esm.js';
14
+
15
+ setAccessToken('eyJraWQiOiJUQTVBanVVYURheGlZdFVYR3l6ajlEZEdPZFJIYUVlUTRTRnF6VWdzc0ZNPSIsImFsZyI6IlJTMjU2In0.eyJzdWIiOiJkNzQ0M2FmOC1mMGExLTcwMzItZGIzMC0wM2Y3NDczZTY0ZDciLCJjb2duaXRvOmdyb3VwcyI6WyJBZ2VudFBvcnRhbCIsIkZpbmFuY2UiLCJUaWNrZXQiLCJQb3J0YWwiXSwiZW1haWxfdmVyaWZpZWQiOnRydWUsImlzcyI6Imh0dHBzOlwvXC9jb2duaXRvLWlkcC5hcC1ub3J0aGVhc3QtMS5hbWF6b25hd3MuY29tXC9hcC1ub3J0aGVhc3QtMV9JSFp0Y2JNZnQiLCJjdXN0b206dXNlcl9pZCI6IjUiLCJjb2duaXRvOnVzZXJuYW1lIjoiZmJjM2Q0ZDIwNzUxNGMwOGEyMGM1NDRjMGNjNmRlYTciLCJjdXN0b206dGVuYW50X2lkIjoiMSIsInByZWZlcnJlZF91c2VybmFtZSI6IuaZk-e6oiDlvKAiLCJjdXN0b206ZW5jcnlwdF9lbWFpbF92YXIiOiJjbGllbnQrNUBoZWRnZWhvb2QuY2MiLCJvcmlnaW5fanRpIjoiYWE4YjY3NzctYzhhZC00MDU3LWJlNTEtZjI1Nzc0M2E5NDY2IiwiYXVkIjoibjRibnJxdGY1OXBqazB1OG01dnVoM2ZxdCIsImV2ZW50X2lkIjoiNmI0ZTJkMjktODI3YS00ODg4LWE1NjUtZjgwYTVkNWU0MGI0IiwidG9rZW5fdXNlIjoiaWQiLCJhdXRoX3RpbWUiOjE3NjU3NzY5NTQsImV4cCI6MTc2NTc4NDE1NCwiaWF0IjoxNzY1Nzc2OTU0LCJlbWFpbCI6Im9ubGluZV90ZXN0QHRtcGVtbC5jb20iLCJqdGkiOiI3NGIzYzUzMi1kOWFlLTQ5YTItOWIzZC1mNzNmNjZkOGM3NDYifQ.VnCQy9EleScDCFLUkOyFdglxos3a2lQ7UGjoZv4sQPibfZrOlp69qlozqDHVoxEboaZ9foZ_EtxnUUkuK2G8rpBGF2mViGdqsNBOYATAN9At1JDTgZsr8yldtJy1EtCgKx6BjBKcL22EQkTreOLXJNpMLY_pkhyjrRoOZ_UTQmKvHthkRU9kCYldk0wh_NsncR8vUSIwG7f9rDqpY01Xu8_FctxudV_zg0WR3YEi45Sql47_RjeYKjoKTVcN2YYSbngJZa3dgfU93tfyx4C2qU5ZC-k7IZsKaRk_G3zcLzP1VeeuVPYgLlb8b-WMJsMJdR4megvmbbDAxWDpQQ-zCQ')
16
+ setRefreshToken('eyJjdHkiOiJKV1QiLCJlbmMiOiJBMjU2R0NNIiwiYWxnIjoiUlNBLU9BRVAifQ.i9ZK_G5dMP0mol3m85EAun1VLyeMh1cnwhFC6jX5jTsxY0qp1exdE8_EyhZdYJJG__hqqXptk1LBAC6NrDPXQ9LC2QcaOfq4CxE8Ai4RTR7dOSOhQbpWu1vxSmIX1Gy9HiFMmlUxyknPDcVC1JXdXtLFPbeOWctXIg_S6xLILG3Kb2B9wMeJEHYPiAb2bIZk7qnT-I8geh9XzabUqeXqLBBHMp2xr3BU3ycgOEnuQQat_W7J0U0Szo5pD9Td7T5QytLYNkFBxo5CNzJzmq2B-alwBqYTm0pXUL1gASI757dlMbVig8tpnJgGtziv67EUiP0NCkTSTeqd4S-WY8H48Q.iJeo5oRqo5MnjbFI.kgtUI6ipZFsTehsicL8mT4DAORSY7J-8JAgYVta8GEyFnXAol2hJIaj4ob9cSOWZENoO8ZT_i7Co8DCLLFoTA4aNeLebFCnJTzdJSYDhBeJ6OrRVEtw8-dniJd1VZriuN53ZWjmM-RxPSYrFYFpUFpYG_xk00w06CWowxSy0WrhUzgrrC-OLUViTRL3Sl3TPW7AxNnzjgMZVZUQ2udWaw3Y2EfcyGYE_Un2HvyLYYbEUm6EMqRTh5BgNMxnCiFrhiaQpuJaABskHH-PUSFdtoHnWONqayjlRazCF_lTYpKglIgi7PQp12SVU8A_gZP6JEGc3nYLpyj2CeR8ocvkMWP58bnzYoU9Jdke0avrAjC2YPfO2R-YcF2LUM6q3HECe_ukMGAEiYM5YwM5o8w2Mcbn-WtRS6nZxTWhChfqMYYme61QaEm2nsZO72aoGc9nTN27PU_j-lq9-HLC-caDzpPYLq5wpZgLvK5HsRAsxknDtJh02wb-6miLZHAZTbdjAlCOMXz3334Vdha17by1lTu_L4C5rUpSPSQaspdRl0moBqH7He27XIoHem6RXlWb-a-jXjGhA1FLHu73rTYU40gZ681UE6qrVz2aQCVDcbhE1iytUS7NcLXI2i5zbzo4YBnYGNvOVLd58CesSI1T_T0_Y4ip966lEypERJAVYJ20Ji2F54KDYPr17Cv3ltz80qqqPN_1QI5oRszt6xU7IjTCp47YGVAHt7RcfR2FemiodpW3_-Xm2PYgo0rwgkEX7z7fZ6Ban1jSeZsYD0vPrlf6nlD8QvA7bP6acZufmfok5oMJ2SC5hv7mGjggd9HT8h3yj8yH4exfga2BSIHTwgNXU-cBw_mQyZCScELof20HJdpE8f3TzOHZfURn1uJdKSZ0tZAdIaTqdHIUlEgUZ8xok7JRpqayVsXve1GvCaZylG0Mw9FTx5DJRi6IblXVdL7yZwLFk8FUYcn4KqtPlamoxR9rpGGMtXIexY4yN99v-hc8_gn3ilYMeA3-a4cFx1mmld8VRQJeD7q_u0lRheDBqW9K6JRBjn8s59hLfyoiRPMi_NZFc2OJNwJofNJbmTcfQmR1dQtsTh2Rtv4krG2YnczzGmPZJppOpaebictrv_ogc93NnXZqJtZGAbSy4RdQYj3Fnx17EY-NSU-VQerlhgV_e35cz8ZNmsiISq7Lp6zUTQwr6ASztyLQ8i_71Xr0OXgf4l4qXWyVQJhbOTJdIUyX5s3ebJruU1qSwPG20Fd3Pm6boIbIlsGHWM6VvRxON8CbJ0PGU_rcIJPVkEGZ0MoiMGvh3BnFYaZYtSPD5p7F9w_LBMRdzb3JimdzNtn48jGYG.XHICmXlRw5-f1fQVFS1Zdw')
17
+
18
+ const { init } = make({
19
+ brand: 1,
20
+ tenantId: 1,
21
+ moduleName: 'Portal',
22
+ moduleBaseUrl: 'https://servers-api.gztest.net:8107',
23
+ loginPageUrl: 'http://huangcheng.ddmarketinghub.com:8080',
24
+ })
25
+
26
+ init()
27
+ </script>
28
+ </html>
package/index.ts ADDED
@@ -0,0 +1,154 @@
1
+ export * from './src/cookie'
2
+ export * from './src/compatible'
3
+
4
+ import { openDialog } from './src/dom'
5
+ import { getAccessToken, getRefreshToken, setAccessToken, setRefreshToken, setSystemType } from './src/cookie'
6
+ import { fetchServerListHTTP, fetchRefreshTokenHTTP, initInstance, fetchLogoutHTTP } from './src/request'
7
+ import { NO_ACCESS_TOKEN, NO_MODULE_BASE_URL, NO_REFRESH_TOKEN } from './src/constance'
8
+ import { setTenantId, setBrand, setModuleBaseUrl, setLoginPageUrl } from './src/shares'
9
+ import { type ModuleName, type Tenant, type Brand, type UserInfo } from './src/types'
10
+ import { SystemType } from './src/types'
11
+ import { getUserInfo } from './src/utils'
12
+
13
+ type MakeFnParams = {
14
+ brand: Brand
15
+ tenantId: Tenant
16
+ moduleName: ModuleName
17
+ moduleBaseUrl: string,
18
+ loginPageUrl: string
19
+ }
20
+
21
+ export const make = (config: MakeFnParams) => {
22
+ if (!config.moduleBaseUrl) {
23
+ throw new Error(NO_MODULE_BASE_URL)
24
+ }
25
+ let timer: number | undefined | null = undefined
26
+
27
+ setModuleBaseUrl(config.moduleBaseUrl)
28
+ setLoginPageUrl(config.loginPageUrl)
29
+ setTenantId(config.tenantId)
30
+ setBrand(config.brand)
31
+ initInstance()
32
+
33
+ const init = () => {
34
+ const token = getAccessToken()
35
+ const refreshToken = getRefreshToken()
36
+
37
+ if (!token) {
38
+ setAccessToken(null)
39
+ setRefreshToken(null)
40
+ return Promise.reject(new Error(NO_ACCESS_TOKEN))
41
+ }
42
+ if (!refreshToken) {
43
+ setAccessToken(null)
44
+ setRefreshToken(null)
45
+ return Promise.reject(new Error(NO_REFRESH_TOKEN))
46
+ }
47
+
48
+ return getUserInfo()
49
+ .then(async (userInfo) => {
50
+ const valid = detectUserInfoGroupAuth(userInfo)
51
+
52
+ if (!valid) {
53
+ return Promise.reject()
54
+ }
55
+
56
+ return fetchServerListHTTP()
57
+ })
58
+ .catch(error => {
59
+ openDialog()
60
+
61
+ throw error
62
+ })
63
+ .then(resp => {
64
+ const menus = resp.data.content || []
65
+
66
+ if (menus.length <= 0) return Promise.reject()
67
+ const group = menus.find(menu => menu.groupName === config.moduleName)
68
+ if (group) {
69
+ setSystemType(group.staffEndpoint ? SystemType.Staff : SystemType.Client)
70
+ }
71
+ setupRefreshTokenTimer()
72
+
73
+ return Promise.resolve()
74
+ })
75
+ .catch(async (error) => {
76
+ clearRefreshTokenTimer()
77
+ setAccessToken(null)
78
+ setRefreshToken(null)
79
+
80
+ await logout()
81
+
82
+ throw error
83
+ })
84
+ }
85
+
86
+ const detectUserInfoGroupAuth = (userInfo: UserInfo): boolean => {
87
+ const groups = userInfo['cognito:groups'] || []
88
+
89
+ if (
90
+ !groups.includes(config.moduleName)
91
+ && config.moduleName !== 'commonLogin'
92
+ && config.moduleName !== 'App'
93
+ ) {
94
+ return false
95
+ }
96
+
97
+ return true
98
+ }
99
+
100
+ const setupRefreshTokenTimer = () => {
101
+ const refreshToken = getRefreshToken()
102
+
103
+ if (!refreshToken) return
104
+
105
+ if (timer) {
106
+ clearInterval(timer)
107
+ }
108
+
109
+ timer = setInterval(() => {
110
+ fetchRefreshTokenHTTP(refreshToken)
111
+ .then(resp => {
112
+ const { content: { idToken } } = resp.data
113
+
114
+ setAccessToken(idToken)
115
+ return getUserInfo()
116
+ })
117
+ .then(userInfo => {
118
+ const valid = detectUserInfoGroupAuth(userInfo)
119
+
120
+ if (!valid) {
121
+ clearRefreshTokenTimer()
122
+ openDialog()
123
+
124
+ return logout()
125
+ }
126
+ })
127
+ .catch(error => {
128
+ clearRefreshTokenTimer()
129
+
130
+ throw error
131
+ })
132
+ }, 1e3 * 60 * 3) // 3 minutes
133
+ }
134
+
135
+ const logout = () => {
136
+ return fetchLogoutHTTP()
137
+ .finally(() => {
138
+ clearRefreshTokenTimer()
139
+ setAccessToken(null)
140
+ setRefreshToken(null)
141
+ })
142
+ }
143
+
144
+ const clearRefreshTokenTimer = () => {
145
+ if (!timer) return
146
+ clearInterval(timer)
147
+ timer = null
148
+ }
149
+
150
+ return {
151
+ init,
152
+ logout
153
+ }
154
+ }
package/jest.config.js ADDED
@@ -0,0 +1,6 @@
1
+ export default {
2
+ coveragePathIgnorePatterns: [
3
+ 'request.ts'
4
+ ],
5
+ testEnvironment: 'jsdom'
6
+ }
package/package.json CHANGED
@@ -1,28 +1,55 @@
1
- {
2
- "name": "login-authorization-v2",
3
- "version": "1.1.5",
4
- "description": "login authorization",
5
- "main": "index.js",
6
- "scripts": {
7
- "test": "echo \"Error: no test specified\" && exit 1",
8
- "build": "webpack"
9
- },
10
- "keywords": [
11
- "login",
12
- "authorization"
13
- ],
14
- "author": "huangcheng",
15
- "license": "ISC",
16
- "dependencies": {
17
- "axios": "^0.24.0",
18
- "js-base64": "^3.7.7"
19
- },
20
- "devDependencies": {
21
- "@babel/core": "^7.16.5",
22
- "@babel/plugin-transform-runtime": "^7.16.5",
23
- "@babel/preset-env": "^7.16.5",
24
- "babel-loader": "^8.2.3",
25
- "webpack": "^5.65.0",
26
- "webpack-cli": "^4.9.1"
27
- }
28
- }
1
+ {
2
+ "type": "module",
3
+ "name": "login-authorization-v2",
4
+ "version": "2.0.0-beta.1",
5
+ "engines": {
6
+ "node": "^20"
7
+ },
8
+ "description": "login authorization",
9
+ "main": "dist/index.umd.js",
10
+ "module": "dist/index.esm.js",
11
+ "exports": {
12
+ "import": "./dist/index.esm.js",
13
+ "require": "./dist/index.umd.js"
14
+ },
15
+ "scripts": {
16
+ "serve": "webpack -w",
17
+ "build": "webpack",
18
+ "test": "jest --coverage"
19
+ },
20
+ "keywords": [
21
+ "login",
22
+ "authorization"
23
+ ],
24
+ "author": "huangcheng",
25
+ "license": "ISC",
26
+ "dependencies": {
27
+ "@types/axios": "^0.14.4",
28
+ "@types/js-base64": "^3.0.0",
29
+ "@types/js-cookie": "^3.0.6",
30
+ "axios": "^0.24.0",
31
+ "js-base64": "^3.7.7",
32
+ "js-cookie": "^3.0.5",
33
+ "lodash": "^4.17.21",
34
+ "ts-loader": "^9.5.4"
35
+ },
36
+ "devDependencies": {
37
+ "@babel/core": "^7.16.5",
38
+ "@babel/plugin-transform-runtime": "^7.16.5",
39
+ "@babel/preset-env": "^7.16.5",
40
+ "@babel/preset-typescript": "^7.28.5",
41
+ "@jest/globals": "^30.2.0",
42
+ "@rollup/plugin-node-resolve": "^16.0.3",
43
+ "@rollup/plugin-typescript": "^12.3.0",
44
+ "@types/jest": "^30.0.0",
45
+ "babel-loader": "^8.2.3",
46
+ "jest": "^30.2.0",
47
+ "jest-environment-jsdom": "^30.2.0",
48
+ "rollup": "^4.53.3",
49
+ "ts-jest": "^29.4.6",
50
+ "tslib": "^2.8.1",
51
+ "typescript": "^5.9.3",
52
+ "webpack": "^5.65.0",
53
+ "webpack-cli": "^4.9.1"
54
+ }
55
+ }
@@ -0,0 +1,46 @@
1
+ /**
2
+ * 这个文件是写一些兼容的方法,避免各个项目做出大量调整
3
+ */
4
+
5
+ import { getAccessToken, setAccessToken, setRefreshToken } from './cookie'
6
+ import Cookie from 'js-cookie'
7
+
8
+ export const setIdToken = setAccessToken
9
+ export const getIdToken = getAccessToken
10
+
11
+ export const setCookie = (
12
+ name: string,
13
+ value: string | undefined | null,
14
+ domain: string,
15
+ path: string = '/',
16
+ time = 30 * 24 * 60 * 60 * 1000
17
+ ) => {
18
+ if (value === null || value === undefined) {
19
+ return Cookie.remove(name)
20
+ }
21
+ Cookie.set(name, value, {
22
+ domain,
23
+ path,
24
+ expires: time / (24 * 60 * 60 * 1000)
25
+ })
26
+ }
27
+ export const clearLoginCookie = () => {
28
+ setAccessToken(null)
29
+ setRefreshToken(null)
30
+ }
31
+
32
+ export const getCookie = (c_name: string) => {
33
+ if (!c_name) return null
34
+ const reg = new RegExp('(?:^|; )' + encodeURIComponent(c_name) + '=([^;]*)')
35
+ const result = reg.exec(document.cookie)
36
+ return result ? decodeURIComponent(result[1] || '') : null
37
+ }
38
+
39
+
40
+ export const getUrlParam = (key: string, href?: string) => {
41
+ const search = '?' + ((href || window.location.href).split('?')[1] || '')
42
+
43
+ const searchParams = new URLSearchParams(search)
44
+
45
+ return searchParams.get(key)
46
+ }
@@ -0,0 +1,7 @@
1
+ export const NO_ACCESS_TOKEN = 'Access token not found'
2
+ export const INVALID_ACCESS_TOKEN = 'Invalid access token'
3
+ export const INVALID_REFRESH_TOKEN = 'Invalid refresh token'
4
+ export const NO_REFRESH_TOKEN = 'Refresh token not found'
5
+ export const NO_MODULE_BASE_URL = 'Module base URL is required'
6
+ export const INVALID_TENANT_ID = 'Invalid tenant ID'
7
+ export const INVALID_BRAND = 'Invalid brand'
package/src/cookie.ts ADDED
@@ -0,0 +1,75 @@
1
+ import Cookie from 'js-cookie'
2
+ import type Cookies from 'js-cookie'
3
+ import { INVALID_ACCESS_TOKEN, INVALID_REFRESH_TOKEN } from './constance'
4
+
5
+ export type CookieKeys =
6
+ 'access_token'
7
+ | 'refresh_token'
8
+ | 'idTokenFront'
9
+ | 'idTokenBack'
10
+ | 'refreshTokenFront'
11
+ | 'refreshTokenBack'
12
+ | 'currentSystemType'
13
+
14
+ const makeSetCookieFn = (key: CookieKeys, options?: Cookies.CookieAttributes) => {
15
+ const index = window.location.hostname.indexOf('.')
16
+ const domain =
17
+ index === -1
18
+ ? window.location.hostname
19
+ : window.location.hostname.slice(index)
20
+
21
+ return (value: string | null) => {
22
+ if (value === null) {
23
+ return Cookie.remove(key, { domain, ...options } )
24
+ }
25
+ Cookie.set(key, value, {
26
+ domain,
27
+ expires: 30,
28
+ ...options
29
+ })
30
+ }
31
+ }
32
+
33
+ const setIdTokenFront = makeSetCookieFn('idTokenFront')
34
+ const setIdTokenBack = makeSetCookieFn('idTokenBack')
35
+ const setRefreshTokenFront = makeSetCookieFn('refreshTokenFront')
36
+ const setRefreshTokenBack = makeSetCookieFn('refreshTokenBack')
37
+ export const setRefreshToken = (token: string | null) => {
38
+ if (!token) {
39
+ setIdTokenBack(null)
40
+ setIdTokenFront(null)
41
+ makeSetCookieFn('refresh_token')(null)
42
+ return
43
+ }
44
+ const splits = token.split('.')
45
+ if (splits.length < 5) throw new Error(INVALID_REFRESH_TOKEN)
46
+ const refreshTokenFront = splits[0] + '.' + splits[1]
47
+ const refreshTokenBack = splits[2] + '.' + splits[3] + '.' + splits[4]
48
+
49
+ setRefreshTokenFront(refreshTokenFront)
50
+ setRefreshTokenBack(refreshTokenBack)
51
+ makeSetCookieFn('refresh_token')(token)
52
+ }
53
+ export const setAccessToken = (token: string | null) => {
54
+ if (!token) {
55
+ setIdTokenBack(null)
56
+ setIdTokenFront(null)
57
+ makeSetCookieFn('access_token')(null)
58
+ return
59
+ }
60
+ const splits = token.split('.')
61
+ if (splits.length < 3) throw new Error(INVALID_ACCESS_TOKEN)
62
+ const idTokenFront = splits[0] + '.' + splits[1]
63
+ const idTokenBack = splits[2] || ''
64
+
65
+ setIdTokenFront(idTokenFront)
66
+ setIdTokenBack(idTokenBack)
67
+
68
+ makeSetCookieFn('access_token')(token)
69
+ }
70
+
71
+ export const getAccessToken = () => Cookie.get('access_token')
72
+ export const getRefreshToken = () => Cookie.get('refresh_token')
73
+
74
+ export const setSystemType = makeSetCookieFn('currentSystemType')
75
+ export const getSystemType = () => Cookie.get('currentSystemType')
package/src/dom.ts ADDED
@@ -0,0 +1,59 @@
1
+ import { isMobile } from './utils'
2
+ import { loginPageUrl } from './shares'
3
+
4
+ const createPcDialog = () => {
5
+ return `<div id="confirm-container" style="box-sizing:border-box;position:fixed;width:615px;height:145px;box-shadow: 0 0 2px 2px #eeeeee;border-radius: 5px;z-index: 10000000;display: block;left: 35%;padding:20px 20px;top:10px;font-size: 16px;">
6
+ <div id="href" style="color: rgb(32,33,36);"></div>
7
+ <div style="margin: 10px 0 20px 0;color: rgb(32,33,36);font-size: 14px;">You do not have access to the system.</div>
8
+ <div style="display: flex;justify-content: flex-end;">
9
+ <button id="cancel" style="padding: 8px 15px;background: #ffffff;color:rgb(26,115,232);border:1px solid #ccc;border-radius:5px;cursor: pointer;font-size:14px;">Cancel</button>
10
+ <button id="confirm" style="padding: 8px 15px;background: rgb(26,115,232);color:#ffffff;border:none;border-radius:5px;margin-left: 10px;cursor: pointer;font-size:14px;">Sign in to another ZERO account</button>
11
+ </div>
12
+ </div>`
13
+ }
14
+
15
+ const createMobileDialog = () => {
16
+ return `<div id="confirm-container" style="box-sizing:border-box;position:fixed;width:97.6vw;height:145px;box-shadow: 0 0 2px 2px #eeeeee;border-radius: 5px;z-index: 10000000;display: block;left:0px;padding:20px 20px;top:4px;margin:0 4px;font-size: 16px;">
17
+ <div id="href" style="color: rgb(32,33,36);"></div>
18
+ <div style="margin: 10px 0 20px 0;color: rgb(32,33,36);font-size: 14px;">You do not have access to the system.</div>
19
+ <div style="display: flex;justify-content: flex-end;">
20
+ <div style="display: flex;justify-content: flex-end;">
21
+ <button id="cancel" style="padding: 8px 15px;background: #ffffff;color:rgb(26,115,232);border:1px solid #ccc;border-radius:5px;cursor: pointer;font-size:14px;">Cancel</button>
22
+ <button id="confirm" style="padding: 8px 15px;background: rgb(26,115,232);color:#ffffff;border:none;border-radius:5px;margin-left: 10px;cursor: pointer;font-size:14px;">Sign in to another ZERO account</button>
23
+ </div>
24
+ </div>
25
+ </div>`
26
+ }
27
+
28
+ const onConfirmHandler = (evt: Event) => {
29
+ closeDialog()
30
+ window.location.href = loginPageUrl
31
+ }
32
+
33
+ const onCancelHandler = () => {
34
+ closeDialog()
35
+ window.location.href = 'about:blank'
36
+ }
37
+
38
+ export const closeDialog = () => {
39
+ const container = document.getElementById('confirm-container')
40
+
41
+ if (!container || !container.parentNode) return
42
+ document.body.removeChild(container.parentNode)
43
+ }
44
+
45
+ export const openDialog = () => {
46
+ const container = document.createElement('div')
47
+
48
+ isMobile()
49
+ ? container.innerHTML = createMobileDialog()
50
+ : container.innerHTML = createPcDialog()
51
+
52
+ const confirmButton = container.querySelector('#confirm')
53
+ const cancelButton = container.querySelector('#cancel')
54
+
55
+ confirmButton?.addEventListener('click', onConfirmHandler)
56
+ cancelButton?.addEventListener('click', onCancelHandler)
57
+
58
+ document.body.appendChild(container)
59
+ }
package/src/request.ts ADDED
@@ -0,0 +1,99 @@
1
+ import axios from 'axios'
2
+ import { tenantId, brand, moduleBaseUrl } from './shares'
3
+ import type { ModuleName, UserInfo } from './types'
4
+ import { getAccessToken } from './cookie'
5
+ import type { AxiosInstance, AxiosPromise } from 'axios'
6
+ import { getUserInfo } from './utils'
7
+
8
+ let instance!: AxiosInstance
9
+
10
+ /**
11
+ * 没找到更好的方式,只能这样做了
12
+ */
13
+ export const initInstance = async () => {
14
+ let userInfo: UserInfo | null = null
15
+ try {
16
+ userInfo = await getUserInfo()
17
+ } catch (error) {
18
+ console.warn('initInstance getUserInfo error:', error)
19
+ }
20
+ instance = axios.create({
21
+ baseURL: moduleBaseUrl,
22
+ timeout: 1.5e4,
23
+ headers: {
24
+ 'X-tenant-id': userInfo ? userInfo['custom:tenant_id'].toString() : tenantId.toString(),
25
+ 'X-brand': brand.toString(),
26
+ 'Authorization': `Bearer ${getAccessToken()}`,
27
+ }
28
+ })
29
+
30
+ instance.interceptors.request.use(
31
+ (config) => {
32
+ return config
33
+ },
34
+ (error) => {
35
+ return Promise.reject(error)
36
+ }
37
+ )
38
+
39
+ instance.interceptors.response.use(
40
+ (response) => {
41
+ if (response.data.code !== 200) {
42
+ return Promise.reject(response.data.msg)
43
+ }
44
+ return response
45
+ },
46
+ (error) => {
47
+ return Promise.reject(error)
48
+ }
49
+ )
50
+ }
51
+
52
+ type RefreshTokenResponse = {
53
+ code: string
54
+ msg: string
55
+ content: {
56
+ accessToken: string
57
+ expiresIn: number
58
+ idToken: string
59
+ newDeviceMetadata: null
60
+ refreshToken: string
61
+ tokenType: 'Bearer'
62
+ }
63
+ }
64
+ export const fetchRefreshTokenHTTP = (refreshToken: string) => {
65
+ return instance({
66
+ method: 'post',
67
+ url: '/user-profile/refresh-token/refresh',
68
+ data: {
69
+ refreshToken
70
+ }
71
+ }) as AxiosPromise<RefreshTokenResponse>
72
+ }
73
+
74
+ export const fetchLogoutHTTP = () => {
75
+ return instance({
76
+ method: 'get',
77
+ url: '/user-profile/logout'
78
+ })
79
+ }
80
+
81
+ type Content = {
82
+ groupName: ModuleName
83
+ icon: string
84
+ id: number
85
+ label: string
86
+ staffEndpoint: boolean
87
+ url: string
88
+ }
89
+ type ServerListResponse = {
90
+ content: Array<Content>
91
+ code: number
92
+ totalElements: number
93
+ }
94
+ export const fetchServerListHTTP = () => {
95
+ return instance({
96
+ method: 'get',
97
+ url: '/session/current/servers'
98
+ }) as AxiosPromise<ServerListResponse>
99
+ }