@authing/react-ui-components 3.0.2-beta.9 → 3.1.1-rc.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 (144) hide show
  1. package/.eslintignore +6 -0
  2. package/.eslintrc.js +7 -0
  3. package/.prettierrc +5 -0
  4. package/.vscode/settings.json +31 -0
  5. package/LICENSE +21 -0
  6. package/config/antdReplacer.js +51 -0
  7. package/config/env.js +106 -0
  8. package/config/getHttpsConfig.js +66 -0
  9. package/config/jest/cssTransform.js +14 -0
  10. package/config/jest/fileTransform.js +40 -0
  11. package/config/modules.js +134 -0
  12. package/config/paths.js +71 -0
  13. package/config/pnpTs.js +35 -0
  14. package/config/webpack.config.js +857 -0
  15. package/config/webpackDevServer.config.js +130 -0
  16. package/lib/index.d.ts +211 -1669
  17. package/lib/index.min.css +1 -2
  18. package/lib/index.min.js +1 -1
  19. package/lib/index.min.js.LICENSE.txt +0 -32
  20. package/package.json +18 -42
  21. package/public/favicon.ico +0 -0
  22. package/public/index.html +43 -0
  23. package/public/logo192.png +0 -0
  24. package/public/logo512.png +0 -0
  25. package/public/manifest.json +25 -0
  26. package/public/robots.txt +3 -0
  27. package/scripts/build.js +212 -0
  28. package/scripts/lib.js +200 -0
  29. package/scripts/start.js +166 -0
  30. package/scripts/test.js +53 -0
  31. package/src/common/AuthingDropdown/index.tsx +52 -0
  32. package/src/common/AuthingDropdown/style.less +43 -0
  33. package/src/common/AuthingTabs/index.tsx +98 -0
  34. package/src/common/AuthingTabs/style.less +135 -0
  35. package/src/common/CopyAbleText/index.tsx +54 -0
  36. package/src/common/CopyAbleText/style.less +13 -0
  37. package/src/common/VerifyCodeInput/index.tsx +76 -0
  38. package/src/common/VerifyCodeInput/style.less +24 -0
  39. package/src/components/AuthingGuard/AppMFALayout/index.tsx +74 -0
  40. package/src/components/AuthingGuard/AppMFALayout/style.less +12 -0
  41. package/src/components/AuthingGuard/CompleteUserInfoLayout/index.tsx +29 -0
  42. package/src/components/AuthingGuard/CompleteUserInfoLayout/style.less +8 -0
  43. package/src/components/AuthingGuard/Forms/ADLoginForm/index.tsx +117 -0
  44. package/src/components/AuthingGuard/Forms/Agreements/index.tsx +81 -0
  45. package/src/components/AuthingGuard/Forms/Agreements/style.less +44 -0
  46. package/src/components/AuthingGuard/Forms/CompleteUserInfoForm/index.tsx +139 -0
  47. package/src/components/AuthingGuard/Forms/EmailMfaVerifyForm/CheckEmailForm.tsx +86 -0
  48. package/src/components/AuthingGuard/Forms/EmailMfaVerifyForm/VerifyCodeForm.tsx +116 -0
  49. package/src/components/AuthingGuard/Forms/EmailMfaVerifyForm/index.tsx +40 -0
  50. package/src/components/AuthingGuard/Forms/EmailMfaVerifyForm/style.less +0 -0
  51. package/src/components/AuthingGuard/Forms/EmailRegisterForm/index.tsx +181 -0
  52. package/src/components/AuthingGuard/Forms/EmailRegisterForm/style.less +0 -0
  53. package/src/components/AuthingGuard/Forms/LdapLoginForm/index.tsx +161 -0
  54. package/src/components/AuthingGuard/Forms/LdapLoginForm/style.less +0 -0
  55. package/src/components/AuthingGuard/Forms/LoginFormFooter/index.tsx +76 -0
  56. package/src/components/AuthingGuard/Forms/LoginFormFooter/style.less +6 -0
  57. package/src/components/AuthingGuard/Forms/MfaResetCodeForm/Step1.tsx +86 -0
  58. package/src/components/AuthingGuard/Forms/MfaResetCodeForm/Step2.tsx +53 -0
  59. package/src/components/AuthingGuard/Forms/MfaResetCodeForm/index.tsx +65 -0
  60. package/src/components/AuthingGuard/Forms/MfaResetCodeForm/style.less +20 -0
  61. package/src/components/AuthingGuard/Forms/MfaVerifyForm/index.tsx +105 -0
  62. package/src/components/AuthingGuard/Forms/MfaVerifyForm/style.less +12 -0
  63. package/src/components/AuthingGuard/Forms/PasswordLoginForm/index.tsx +261 -0
  64. package/src/components/AuthingGuard/Forms/PhoneCodeLoginForm/index.tsx +133 -0
  65. package/src/components/AuthingGuard/Forms/PhoneRegisterForm/index.tsx +202 -0
  66. package/src/components/AuthingGuard/Forms/QrCodeLoginForm/index.tsx +61 -0
  67. package/src/components/AuthingGuard/Forms/QrCodeLoginForm/style.less +14 -0
  68. package/src/components/AuthingGuard/Forms/RegisterFormFooter/index.tsx +56 -0
  69. package/src/components/AuthingGuard/Forms/RegisterFormFooter/style.less +0 -0
  70. package/src/components/AuthingGuard/Forms/ResetPwdForm/Footer.tsx +21 -0
  71. package/src/components/AuthingGuard/Forms/ResetPwdForm/Step1.tsx +86 -0
  72. package/src/components/AuthingGuard/Forms/ResetPwdForm/Step2.tsx +127 -0
  73. package/src/components/AuthingGuard/Forms/ResetPwdForm/Step3.tsx +141 -0
  74. package/src/components/AuthingGuard/Forms/ResetPwdForm/Step4.tsx +51 -0
  75. package/src/components/AuthingGuard/Forms/ResetPwdForm/index.tsx +96 -0
  76. package/src/components/AuthingGuard/Forms/ResetPwdForm/style.less +3 -0
  77. package/src/components/AuthingGuard/Forms/SendPhoneCode/SendCodeBtn.tsx +88 -0
  78. package/src/components/AuthingGuard/Forms/SendPhoneCode/index.tsx +50 -0
  79. package/src/components/AuthingGuard/Forms/SendPhoneCode/style.less +26 -0
  80. package/src/components/AuthingGuard/Forms/SmsMfaVerifyForm/CheckPhoneForm.tsx +86 -0
  81. package/src/components/AuthingGuard/Forms/SmsMfaVerifyForm/VerifyCodeForm.tsx +113 -0
  82. package/src/components/AuthingGuard/Forms/SmsMfaVerifyForm/index.tsx +40 -0
  83. package/src/components/AuthingGuard/Forms/SmsMfaVerifyForm/style.less +3 -0
  84. package/src/components/AuthingGuard/Forms/SocialAndIdpLogin/index.tsx +325 -0
  85. package/src/components/AuthingGuard/Forms/SocialAndIdpLogin/style.less +75 -0
  86. package/src/components/AuthingGuard/Forms/UploadImage/index.tsx +70 -0
  87. package/src/components/AuthingGuard/Forms/index.ts +13 -0
  88. package/src/components/AuthingGuard/GuardLayout/index.tsx +488 -0
  89. package/src/components/AuthingGuard/GuardLayout/style.less +111 -0
  90. package/src/components/AuthingGuard/Header/index.tsx +28 -0
  91. package/src/components/AuthingGuard/Header/style.less +64 -0
  92. package/src/components/AuthingGuard/IconFont/iconfont.js +74 -0
  93. package/src/components/AuthingGuard/IconFont/index.tsx +19 -0
  94. package/src/components/AuthingGuard/IconFont/style.less +6 -0
  95. package/src/components/AuthingGuard/IconFont/svg.js +2 -0
  96. package/src/components/AuthingGuard/LoginLayout/index.tsx +205 -0
  97. package/src/components/AuthingGuard/LoginLayout/style.less +0 -0
  98. package/src/components/AuthingGuard/MfaLayout/Steps.ts +4 -0
  99. package/src/components/AuthingGuard/MfaLayout/index.tsx +49 -0
  100. package/src/components/AuthingGuard/MfaLayout/style.less +3 -0
  101. package/src/components/AuthingGuard/RegisterLayout/index.tsx +89 -0
  102. package/src/components/AuthingGuard/RegisterLayout/style.less +0 -0
  103. package/src/components/AuthingGuard/ResetPwdLayout/index.tsx +20 -0
  104. package/src/components/AuthingGuard/ToggleLang/index.tsx +51 -0
  105. package/src/components/AuthingGuard/api/appConfig.ts +154 -0
  106. package/src/components/AuthingGuard/api/http.ts +88 -0
  107. package/src/components/AuthingGuard/api/index.ts +3 -0
  108. package/src/components/AuthingGuard/api/sso.ts +29 -0
  109. package/src/components/AuthingGuard/api/userPoolConfig.ts +112 -0
  110. package/src/components/AuthingGuard/constants.ts +107 -0
  111. package/src/components/AuthingGuard/hooks/index.tsx +70 -0
  112. package/src/components/AuthingGuard/hooks/useScreenSize.tsx +68 -0
  113. package/src/components/AuthingGuard/index.tsx +134 -0
  114. package/src/components/AuthingGuard/locales/en/common.json +185 -0
  115. package/src/components/AuthingGuard/locales/en/index.ts +6 -0
  116. package/src/components/AuthingGuard/locales/en/login.json +94 -0
  117. package/src/components/AuthingGuard/locales/en/map.json +4 -0
  118. package/src/components/AuthingGuard/locales/en/user.json +81 -0
  119. package/src/components/AuthingGuard/locales/index.ts +45 -0
  120. package/src/components/AuthingGuard/locales/zh/common.json +185 -0
  121. package/src/components/AuthingGuard/locales/zh/index.ts +6 -0
  122. package/src/components/AuthingGuard/locales/zh/login.json +94 -0
  123. package/src/components/AuthingGuard/locales/zh/map.json +4 -0
  124. package/src/components/AuthingGuard/locales/zh/user.json +81 -0
  125. package/src/components/AuthingGuard/style.less +108 -0
  126. package/src/components/AuthingGuard/types/Forms.ts +95 -0
  127. package/src/components/AuthingGuard/types/GuardConfig.ts +424 -0
  128. package/src/components/AuthingGuard/types/GuardState.ts +7 -0
  129. package/src/components/AuthingGuard/types/Locales.ts +12 -0
  130. package/src/components/AuthingGuard/types/index.ts +4 -0
  131. package/src/components/index.ts +7 -0
  132. package/src/context/base.tsx +28 -0
  133. package/src/context/global/context.tsx +39 -0
  134. package/src/context/global/reducer.tsx +56 -0
  135. package/src/index.tsx +142 -0
  136. package/src/logo.svg +7 -0
  137. package/src/react-app-env.d.ts +71 -0
  138. package/src/reportWebVitals.ts +15 -0
  139. package/src/setupTests.ts +5 -0
  140. package/src/utils/clipboard.ts +27 -0
  141. package/src/utils/index.ts +180 -0
  142. package/src/utils/popupCenter.ts +48 -0
  143. package/tsconfig.json +24 -0
  144. package/lib/static/media/loading.4a67a5f3.svg +0 -29
@@ -0,0 +1,116 @@
1
+ import { EmailScene, User } from 'authing-js-sdk'
2
+ import React, { FC, useState } from 'react'
3
+ import { Button, Form } from 'antd'
4
+
5
+ import { VerifyCodeInput } from '../../../../common/VerifyCodeInput'
6
+ import { useGuardContext } from '../../../../context/global/context'
7
+ import { EmailMFAVerifyFormProps } from '../../../../components/AuthingGuard/types'
8
+
9
+ import './style.less'
10
+ import { SendCodeBtn } from '../SendPhoneCode/SendCodeBtn'
11
+ import { useTranslation } from 'react-i18next'
12
+
13
+ const CODE_LEN = 4
14
+
15
+ export const VerifyCodeForm: FC<EmailMFAVerifyFormProps> = ({
16
+ onSuccess,
17
+ onFail,
18
+ email,
19
+ mfaToken,
20
+ sendCodeRef,
21
+ }) => {
22
+ const {
23
+ state: { authClient },
24
+ } = useGuardContext()
25
+
26
+ const { t } = useTranslation()
27
+
28
+ const [rawForm] = Form.useForm()
29
+
30
+ const [MfaCode, setMFACode] = useState(new Array(CODE_LEN).fill(''))
31
+ const [loading, setLoading] = useState(false)
32
+
33
+ const [sending, setSending] = useState(false)
34
+ const [sent, setSent] = useState(false)
35
+
36
+ const onFinish = async (values: any) => {
37
+ try {
38
+ const user: User = await authClient.mfa.verifyAppEmailMfa({
39
+ mfaToken,
40
+ email: email!,
41
+ code: MfaCode.join(''),
42
+ })
43
+ onSuccess && onSuccess(user)
44
+ } catch (e) {
45
+ onFail?.(e)
46
+ } finally {
47
+ setLoading(false)
48
+ }
49
+ }
50
+
51
+ const sendVerifyCode = async () => {
52
+ try {
53
+ setSending(true)
54
+ await authClient.sendEmail(email!, EmailScene.MfaVerify)
55
+ setSent(true)
56
+ return true
57
+ } catch (e) {
58
+ return false
59
+ } finally {
60
+ setSending(false)
61
+ }
62
+ }
63
+
64
+ return (
65
+ <>
66
+ <h3 className="authing-guard-mfa-title">{t('login.inputEmailCode')}</h3>
67
+ <p className="authing-guard-mfa-tips">
68
+ {sending
69
+ ? t('login.sendingVerifyCode')
70
+ : sent
71
+ ? `${t('login.verifyCodeSended')} ${email}`
72
+ : t('login.clickSent')}
73
+ </p>
74
+ <Form
75
+ form={rawForm}
76
+ onSubmitCapture={() => setLoading(true)}
77
+ onFinish={onFinish}
78
+ onFinishFailed={() => setLoading(false)}
79
+ >
80
+ <Form.Item
81
+ name="mfaCode"
82
+ rules={[
83
+ {
84
+ validateTrigger: [],
85
+ validator() {
86
+ if (MfaCode.some((item) => !item)) {
87
+ return Promise.reject(t('login.inputFullMfaCode'))
88
+ }
89
+ return Promise.resolve()
90
+ },
91
+ },
92
+ ]}
93
+ >
94
+ <VerifyCodeInput
95
+ length={CODE_LEN}
96
+ verifyCode={MfaCode}
97
+ setVerifyCode={setMFACode}
98
+ />
99
+ </Form.Item>
100
+
101
+ <SendCodeBtn btnRef={sendCodeRef} beforeSend={() => sendVerifyCode()} />
102
+
103
+ <Button
104
+ className="authing-guard-mfa-confirm-btn"
105
+ loading={loading}
106
+ block
107
+ htmlType="submit"
108
+ type="primary"
109
+ size="large"
110
+ >
111
+ {t('common.sure')}
112
+ </Button>
113
+ </Form>
114
+ </>
115
+ )
116
+ }
@@ -0,0 +1,40 @@
1
+ import React, { FC, useRef, useState } from 'react'
2
+ import { useGuardContext } from 'src/context/global/context'
3
+ import { CheckEmailForm } from './CheckEmailForm'
4
+ import { VerifyCodeForm } from './VerifyCodeForm'
5
+ import { SmsMFAFormProps } from '../../types'
6
+
7
+ export const EmailMfaVerifyForm: FC<SmsMFAFormProps> = ({
8
+ onSuccess,
9
+ onFail,
10
+ }) => {
11
+ const {
12
+ state: {
13
+ mfaData: { mfaToken, email: userEmail },
14
+ },
15
+ } = useGuardContext()
16
+ const [email, setEmail] = useState(userEmail)
17
+ const sendCodeRef = useRef<HTMLButtonElement>(null)
18
+
19
+ return (
20
+ <>
21
+ {email ? (
22
+ <VerifyCodeForm
23
+ sendCodeRef={sendCodeRef}
24
+ onSuccess={onSuccess}
25
+ onFail={onFail}
26
+ email={email!}
27
+ mfaToken={mfaToken}
28
+ ></VerifyCodeForm>
29
+ ) : (
30
+ <CheckEmailForm
31
+ mfaToken={mfaToken}
32
+ onSuccess={(email) => {
33
+ setEmail(email)
34
+ sendCodeRef.current?.click()
35
+ }}
36
+ ></CheckEmailForm>
37
+ )}
38
+ </>
39
+ )
40
+ }
@@ -0,0 +1,181 @@
1
+ import React, { forwardRef, useImperativeHandle, useState } from 'react'
2
+ import { Input, Form, message } from 'antd'
3
+ import { FormInstance } from 'antd/lib/form'
4
+ import { UserOutlined, LockOutlined } from '@ant-design/icons'
5
+
6
+ import {
7
+ getDeviceName,
8
+ getRequiredRules,
9
+ getUserRegisterParams,
10
+ VALIDATE_PATTERN,
11
+ } from '../../../../utils'
12
+ import { useGuardContext } from '../../../../context/global/context'
13
+ import {
14
+ EmailRegisterFormProps,
15
+ RegisterMethods,
16
+ } from '../../../../components/AuthingGuard/types'
17
+ import { RegisterFormFooter } from '../../../../components/AuthingGuard/Forms/RegisterFormFooter'
18
+ import { useTranslation } from 'react-i18next'
19
+ import { Agreements } from '../Agreements'
20
+
21
+ export const EmailRegisterForm = forwardRef<
22
+ FormInstance,
23
+ EmailRegisterFormProps
24
+ >(({ onSuccess, onFail, onValidateFail }, ref) => {
25
+ const { t } = useTranslation()
26
+ const {
27
+ state: { authClient, config, guardEvents },
28
+ } = useGuardContext()
29
+
30
+ const { agreements, agreementEnabled } = config
31
+
32
+ const [rawForm] = Form.useForm()
33
+
34
+ const [loading, setLoading] = useState(false)
35
+
36
+ const onFinishFailed = (errorInfo: any) => {
37
+ setLoading(false)
38
+ onValidateFail && onValidateFail(errorInfo)
39
+ }
40
+
41
+ const [acceptedAgreements, setAcceptedAgreements] = useState(false)
42
+
43
+ /** 表单是否被提交校验过 */
44
+ const [validated, setValidated] = useState(false)
45
+
46
+ const onFinish = async (values: any) => {
47
+ if (guardEvents.onBeforeRegister) {
48
+ try {
49
+ const canRegister = await guardEvents.onBeforeRegister(
50
+ {
51
+ type: RegisterMethods.Email,
52
+ data: {
53
+ email: values.email,
54
+ password: values.password,
55
+ },
56
+ },
57
+ authClient
58
+ )
59
+
60
+ if (!canRegister) {
61
+ setLoading(false)
62
+ return
63
+ }
64
+ } catch (e) {
65
+ if (typeof e === 'string') {
66
+ message.error(e)
67
+ } else {
68
+ message.error(e.message)
69
+ }
70
+ setLoading(false)
71
+ return
72
+ }
73
+ }
74
+
75
+ try {
76
+ await rawForm.validateFields()
77
+
78
+ setValidated(true)
79
+
80
+ if (agreementEnabled && agreements?.length && !acceptedAgreements) {
81
+ return
82
+ }
83
+
84
+ const { email, password } = values
85
+ // 注册并获取登录态
86
+ const user = await authClient.registerByEmail(
87
+ email,
88
+ password,
89
+ {
90
+ browser:
91
+ typeof navigator !== 'undefined' ? navigator.userAgent : null,
92
+ device: getDeviceName(),
93
+ },
94
+ {
95
+ generateToken: true,
96
+ params: getUserRegisterParams(),
97
+ }
98
+ )
99
+ onSuccess && onSuccess(user)
100
+ } catch (error) {
101
+ onFail && onFail(error)
102
+ } finally {
103
+ setLoading(false)
104
+ }
105
+ }
106
+
107
+ useImperativeHandle(ref, () => rawForm)
108
+
109
+ const formItems = [
110
+ {
111
+ component: (
112
+ <Input
113
+ autoComplete="email"
114
+ size="large"
115
+ placeholder={t('login.inputEmail')}
116
+ prefix={<UserOutlined style={{ color: '#ddd' }} />}
117
+ />
118
+ ),
119
+ name: 'email',
120
+ rules: getRequiredRules(t('common.emailNotNull')).concat({
121
+ pattern: VALIDATE_PATTERN.email,
122
+ message: t('login.emailError'),
123
+ }),
124
+ },
125
+ {
126
+ component: (
127
+ <Input.Password
128
+ size="large"
129
+ placeholder={t('common.setPassword')}
130
+ prefix={<LockOutlined style={{ color: '#ddd' }} />}
131
+ />
132
+ ),
133
+ name: 'password',
134
+ rules: getRequiredRules(t('common.passwordNotNull')),
135
+ },
136
+ {
137
+ component: (
138
+ <Input.Password
139
+ size="large"
140
+ placeholder={t('login.inputPwdAgain')}
141
+ prefix={<LockOutlined style={{ color: '#ddd' }} />}
142
+ />
143
+ ),
144
+ name: 'new-password',
145
+ rules: getRequiredRules(t('common.repeatPassword')).concat({
146
+ validator: (rule, value) => {
147
+ if (value !== rawForm.getFieldValue('password')) {
148
+ return Promise.reject(t('common.repeatPasswordDoc'))
149
+ } else {
150
+ return Promise.resolve()
151
+ }
152
+ },
153
+ }),
154
+ },
155
+ ]
156
+
157
+ return (
158
+ <Form
159
+ form={rawForm}
160
+ onFinish={onFinish}
161
+ onSubmitCapture={() => setLoading(true)}
162
+ onFinishFailed={onFinishFailed}
163
+ >
164
+ {formItems.map((item) => (
165
+ <Form.Item key={item.name} name={item.name} rules={item.rules}>
166
+ {item.component}
167
+ </Form.Item>
168
+ ))}
169
+
170
+ {config.agreementEnabled && Boolean(agreements?.length) && (
171
+ <Agreements
172
+ onChange={setAcceptedAgreements}
173
+ agreements={agreements}
174
+ showError={validated}
175
+ />
176
+ )}
177
+
178
+ <RegisterFormFooter loading={loading} />
179
+ </Form>
180
+ )
181
+ })
@@ -0,0 +1,161 @@
1
+ import { Input, Form, message } from 'antd'
2
+ import { FormInstance } from 'antd/lib/form'
3
+ import { UserOutlined, LockOutlined } from '@ant-design/icons'
4
+ import React, { forwardRef, useImperativeHandle, useState } from 'react'
5
+
6
+ import { getRequiredRules } from '../../../../utils'
7
+ import { useGuardContext } from '../../../../context/global/context'
8
+ import { NEED_CAPTCHA } from '../../../../components/AuthingGuard/constants'
9
+ import {
10
+ LoginMethods,
11
+ PasswordLoginFormProps,
12
+ } from '../../../../components/AuthingGuard/types'
13
+ import { LoginFormFooter } from '../../../../components/AuthingGuard/Forms/LoginFormFooter'
14
+ import { useTranslation } from 'react-i18next'
15
+
16
+ export const LdapLoginForm = forwardRef<FormInstance, PasswordLoginFormProps>(
17
+ ({ onSuccess, onValidateFail, onFail }, ref) => {
18
+ const { t } = useTranslation()
19
+
20
+ const { state } = useGuardContext()
21
+ const { authClient, realHost, guardEvents } = state
22
+
23
+ const [rawForm] = Form.useForm()
24
+
25
+ const [needCaptcha, setNeedCaptcha] = useState(false)
26
+ const [verifyCodeUrl, setVerifyCodeUrl] = useState<string | null>(null)
27
+ const [loading, setLoading] = useState(false)
28
+
29
+ const captchaUrl = `${realHost}/api/v2/security/captcha`
30
+ const getCaptchaUrl = () => `${captchaUrl}?r=${+new Date()}`
31
+
32
+ const onFinishFailed = (errorInfo: any) => {
33
+ setLoading(false)
34
+ onValidateFail && onValidateFail(errorInfo)
35
+ }
36
+
37
+ const onFinish = async (values: any) => {
38
+ if (guardEvents.onBeforeLogin) {
39
+ try {
40
+ const canLogin = await guardEvents.onBeforeLogin(
41
+ {
42
+ type: LoginMethods.LDAP,
43
+ data: {
44
+ identity: values.identity,
45
+ password: values.password,
46
+ captchaCode: values.captchaCode,
47
+ },
48
+ },
49
+ authClient
50
+ )
51
+
52
+ if (!canLogin) {
53
+ setLoading(false)
54
+ return
55
+ }
56
+ } catch (e) {
57
+ if (typeof e === 'string') {
58
+ message.error(e)
59
+ } else {
60
+ message.error(e.message)
61
+ }
62
+ setLoading(false)
63
+ return
64
+ }
65
+ }
66
+
67
+ try {
68
+ const identity = values.identity && values.identity.trim()
69
+ const password = values.password && values.password.trim()
70
+
71
+ const user = await authClient.loginByLdap(identity, password)
72
+ onSuccess && onSuccess(user)
73
+ } catch (error) {
74
+ if (typeof error.message === 'string') {
75
+ // js sdk httpclient 的报错,这里只有一种情况就是用户开启了 mfa 的报错
76
+ try {
77
+ const errorData = JSON.parse(error.message)
78
+ onFail && onFail(errorData)
79
+ return
80
+ } catch (_) {}
81
+ }
82
+
83
+ if (error.code === NEED_CAPTCHA && verifyCodeUrl === null) {
84
+ setNeedCaptcha(true)
85
+ setVerifyCodeUrl(getCaptchaUrl())
86
+ }
87
+
88
+ onFail && onFail(error)
89
+ } finally {
90
+ setLoading(false)
91
+ }
92
+ }
93
+
94
+ useImperativeHandle(ref, () => rawForm)
95
+
96
+ const formItems = [
97
+ {
98
+ component: (
99
+ <Input
100
+ autoComplete="ldap,username"
101
+ size="large"
102
+ placeholder={t('login.inputLdapUsername')}
103
+ prefix={<UserOutlined style={{ color: '#ddd' }} />}
104
+ />
105
+ ),
106
+ name: 'identity',
107
+ rules: getRequiredRules(t('common.LDAPAccountNotNull')),
108
+ },
109
+ {
110
+ component: (
111
+ <Input.Password
112
+ size="large"
113
+ placeholder={t('login.inputLdapPwd')}
114
+ prefix={<LockOutlined style={{ color: '#ddd' }} />}
115
+ />
116
+ ),
117
+ name: 'password',
118
+ rules: getRequiredRules(t('common.passwordNotNull')),
119
+ },
120
+ {
121
+ component: (
122
+ <Input
123
+ size="large"
124
+ placeholder={t('login.inputCaptchaCode')}
125
+ addonAfter={
126
+ <img
127
+ src={verifyCodeUrl ?? ''}
128
+ alt={t('login.captchaCode')}
129
+ style={{ height: '2em', cursor: 'pointer' }}
130
+ onClick={() => setVerifyCodeUrl(getCaptchaUrl())}
131
+ />
132
+ }
133
+ />
134
+ ),
135
+ name: 'captchaCode',
136
+ rules: getRequiredRules(t('common.captchaCodeNotNull')),
137
+ hide: !needCaptcha,
138
+ },
139
+ ]
140
+
141
+ return (
142
+ <Form
143
+ form={rawForm}
144
+ onSubmitCapture={() => setLoading(true)}
145
+ onFinishFailed={onFinishFailed}
146
+ onFinish={onFinish}
147
+ >
148
+ {formItems.map(
149
+ (item) =>
150
+ !item.hide && (
151
+ <Form.Item key={item.name} name={item.name} rules={item.rules}>
152
+ {item.component}
153
+ </Form.Item>
154
+ )
155
+ )}
156
+
157
+ <LoginFormFooter loading={loading}></LoginFormFooter>
158
+ </Form>
159
+ )
160
+ }
161
+ )
@@ -0,0 +1,76 @@
1
+ import { Button, Divider } from 'antd'
2
+ import React, { FC } from 'react'
3
+ import { useGuardContext } from '../../../../context/global/context'
4
+ import { GuardScenes } from '../../../../components/AuthingGuard/types'
5
+ import './style.less'
6
+ import { useTranslation } from 'react-i18next'
7
+
8
+ export interface LoginFormFooterProps {
9
+ loading: boolean
10
+ needRestPwd?: boolean
11
+ needRegister?: boolean
12
+ }
13
+
14
+ export const LoginFormFooter: FC<LoginFormFooterProps> = ({
15
+ loading,
16
+ needRestPwd = false,
17
+ needRegister = false,
18
+ }) => {
19
+ const { t } = useTranslation()
20
+
21
+ const {
22
+ setValue,
23
+ state: { config },
24
+ } = useGuardContext()
25
+
26
+ return (
27
+ <>
28
+ <Button
29
+ htmlType="submit"
30
+ className="authing-guard-form-submit-btn"
31
+ size="large"
32
+ type="primary"
33
+ loading={loading}
34
+ block
35
+ >
36
+ {loading
37
+ ? t(
38
+ `map.${config.text?.loginBtn?.loading}`,
39
+ config.text?.loginBtn?.loading
40
+ )
41
+ : t(
42
+ `map.${config.text?.loginBtn?.normal}`,
43
+ config.text?.loginBtn?.normal
44
+ )}
45
+ </Button>
46
+
47
+ <div className="authing-guard-form-actions">
48
+ {needRestPwd && !config.disableResetPwd && (
49
+ <Button
50
+ onClick={() => setValue('guardScenes', GuardScenes.RestPassword)}
51
+ className="authing-guard-text-btn"
52
+ type="text"
53
+ >
54
+ {t('common.hasForgotPwd')}
55
+ </Button>
56
+ )}
57
+ {needRestPwd &&
58
+ needRegister &&
59
+ !config.disableResetPwd &&
60
+ !config.disableRegister && <Divider type="vertical" />}
61
+ {needRegister && !config.disableRegister && (
62
+ <div className="authing-guard-tip-btn-comb">
63
+ <span className="authing-guard-tip">{t('common.noAccYet')}</span>
64
+ <Button
65
+ onClick={() => setValue('guardScenes', GuardScenes.Register)}
66
+ className="authing-guard-text-btn authing-guard-to-register-btn"
67
+ type="text"
68
+ >
69
+ {t('common.registerImmediate')}
70
+ </Button>
71
+ </div>
72
+ )}
73
+ </div>
74
+ </>
75
+ )
76
+ }
@@ -0,0 +1,6 @@
1
+ @media only screen and (max-width: 719px) {
2
+ .authing-guard-form-submit-btn {
3
+ margin-top: 56px;
4
+ font-size: 14px;
5
+ }
6
+ }
@@ -0,0 +1,86 @@
1
+ import { Input, Form, Button } from 'antd'
2
+ import React, { FC, useState } from 'react'
3
+ import { LockOutlined } from '@ant-design/icons'
4
+ import { getRequiredRules } from '../../../../utils'
5
+ import { useGuardContext } from '../../../../context/global/context'
6
+ import { User } from 'authing-js-sdk'
7
+ import { useTranslation } from 'react-i18next'
8
+
9
+ export const MfaResetStep1: FC<{
10
+ mfaToken: string
11
+ onSuccess: (
12
+ user: User & {
13
+ recoveryCode: string
14
+ }
15
+ ) => void
16
+ goVerify: () => void
17
+ onFail?: (error: any) => void
18
+ }> = ({ mfaToken, onSuccess, goVerify, onFail }) => {
19
+ const [loading, setLoading] = useState(false)
20
+ const { t } = useTranslation()
21
+
22
+ const {
23
+ state: { authClient },
24
+ } = useGuardContext()
25
+
26
+ const onFinish = async (values: any) => {
27
+ try {
28
+ const user = await authClient.mfa.verifyTotpRecoveryCode({
29
+ recoveryCode: values.recoverCode,
30
+ mfaToken,
31
+ })
32
+ onSuccess(
33
+ user as User & {
34
+ recoveryCode: string
35
+ }
36
+ )
37
+ } catch (e) {
38
+ onFail?.(e)
39
+ } finally {
40
+ setLoading(false)
41
+ }
42
+ }
43
+
44
+ return (
45
+ <Form
46
+ onSubmitCapture={() => setLoading(true)}
47
+ onFinishFailed={() => setLoading(false)}
48
+ onFinish={onFinish}
49
+ >
50
+ <Form.Item
51
+ rules={getRequiredRules(t('common.recoverCodeNotNull'))}
52
+ name="recoverCode"
53
+ >
54
+ <Input
55
+ prefix={<LockOutlined style={{ color: '#ddd' }} />}
56
+ placeholder={t('login.inputRecoverCode')}
57
+ size="large"
58
+ ></Input>
59
+ </Form.Item>
60
+
61
+ <Button
62
+ className="authing-guard-mfa-confirm-btn"
63
+ loading={loading}
64
+ htmlType="submit"
65
+ block
66
+ type="primary"
67
+ size="large"
68
+ >
69
+ {t('common.sure')}
70
+ </Button>
71
+
72
+ <div className="authing-guard-form-actions">
73
+ <div className="authing-guard-tip-btn-comb">
74
+ <Button
75
+ htmlType="button"
76
+ onClick={goVerify}
77
+ className="authing-guard-text-btn"
78
+ type="text"
79
+ >
80
+ {t('login.findedSafetyCode')}
81
+ </Button>
82
+ </div>
83
+ </div>
84
+ </Form>
85
+ )
86
+ }