rsf-admin/src/api/auth/index.js | ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史 | |
rsf-admin/src/page/login/Register.jsx | ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史 | |
rsf-framework/src/main/java/com/vincent/rsf/framework/common/BaseRes.java | ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史 | |
rsf-server/src/main/java/com/vincent/rsf/server/common/service/EmailService.java | ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史 | |
rsf-server/src/main/java/com/vincent/rsf/server/system/controller/AuthController.java | ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史 |
rsf-admin/src/api/auth/index.js
@@ -9,7 +9,7 @@ } export async function tenants(_params) { const res = await request.get('/tenant/list', _params); const res = await request.get('/tenant/list', { params: _params }); if (res.data.code === 200) { return res.data.data; } @@ -25,7 +25,7 @@ } export async function menus(_params) { return await request.get('/auth/menu', _params); return await request.get('/auth/menu', { params: _params }); if (res.data.code === 200) { return res.data.data; } @@ -33,7 +33,7 @@ } export async function queryUserInfo(_params) { const res = await request.get('/auth/user', _params); const res = await request.get('/auth/user', { params: _params }); if (res.data.code === 200) { return res.data.data; } @@ -51,4 +51,9 @@ export async function requestResetPassword(_params) { const res = await request.post('/auth/reset/password', _params); return res.data; } export async function sendEmailCode(_params) { const res = await request.get('/email/code', { params: _params }); return res.data; } rsf-admin/src/page/login/Register.jsx
@@ -15,11 +15,13 @@ useTranslate, useLogin, useNotify, email as validEmail, } from 'react-admin'; import { useForm, Controller } from 'react-hook-form'; import ProviderChoices from "./ProviderChoices"; import Visibility from '@mui/icons-material/Visibility'; import VisibilityOff from '@mui/icons-material/VisibilityOff'; import { sendEmailCode } from '@/api/auth'; const Register = (props) => { const translate = useTranslate(); @@ -28,7 +30,7 @@ const location = useLocation(); const { systemInfo } = props; const { control, watch, handleSubmit, setValue } = useForm(); const { control, watch, handleSubmit, setValue, setError, clearErrors } = useForm(); const email = watch('email'); const username = watch('username'); @@ -36,20 +38,40 @@ const confirmPassword = watch('confirmPassword'); const [loading, setLoading] = useState(false); const [codeLoading, setCodeLoading] = useState(false); const [showPassword, setShowPassword] = useState(true); const [isCounting, setIsCounting] = useState(false); const [countdown, setCountdown] = useState(60); // 处理验证码按钮点击 const handleSendCode = async () => { // 这里假设发送验证码的请求 const response = await fetch('/api/send-code'); if (response.ok) { setIsCounting(true); localStorage.setItem('codeCountdown', 60); // 存储倒计时到本地 if (!email) { setError("email", { message: translate('ra.validation.required') }) return; } const emailError = validEmail()(email); if (emailError) { setError("email", { message: translate("ra.validation.email") }) return; } clearErrors("email"); setCodeLoading(true); sendEmailCode({ email }).then(res => { setCodeLoading(false); const { code, msg, data } = res; if (code === 200) { notify(msg, { type: 'success', messageArgs: { _: msg } }); } else { notify(msg, { type: 'error', messageArgs: { _: msg } }); } }).catch((error) => { setCodeLoading(false); notify(error.message, { type: 'error', messageArgs: { _: error.message } }); console.error(error); }) }; // 倒计时功能 @@ -260,19 +282,22 @@ <Button variant="outlined" onClick={handleSendCode} disabled={isCounting || loading} disabled={codeLoading || isCounting} sx={{ width: '35%', mt: 1, whiteSpace: 'nowrap', }} > {isCounting ? ( <> <CircularProgress size={20} color="primary" sx={{ marginRight: 1 }} /> {`${countdown}s`} </> ) : ( translate('page.login.button.code') )} {codeLoading ? ( <CircularProgress size={20} color="primary" sx={{ marginRight: 1 }} /> ) : isCounting ? ( `${countdown}s` ) : ( translate('page.login.button.code') ) } </Button> </Box> rsf-framework/src/main/java/com/vincent/rsf/framework/common/BaseRes.java
@@ -5,7 +5,7 @@ String OK = "200-Success"; String EMPTY = "201-Empty Data"; String LIMIT = "202-No Authority"; String PARAM = "401-Parameters Cannot Be Empty"; String PARAM = "203-Parameters Cannot Be Empty"; String DENIED = "403-Please Re-Login"; String REPEAT = "407-Already Exist"; String NO_ACTIVATION = "409-Please Activate The System First"; @@ -14,7 +14,7 @@ // String OK = "200-操作成功"; // String EMPTY = "201-暂无数据"; // String LIMIT = "202-无权限"; // String PARAM = "401-参数为空"; // String PARAM = "203-参数为空"; // String DENIED = "403-请重新登录"; // String REPEAT = "407-已存在"; // String NO_ACTIVATION = "409-请先激活系统"; rsf-server/src/main/java/com/vincent/rsf/server/common/service/EmailService.java
@@ -15,15 +15,17 @@ import javax.mail.MessagingException; import javax.mail.internet.MimeMessage; import java.util.Map; import java.util.regex.Matcher; import java.util.regex.Pattern; @Slf4j @Service public class EmailService { private static final String EMAIL_REGEX = "^[a-zA-Z0-9_+&*-]+(?:\\.[a-zA-Z0-9_+&*-]+)*@(?:[a-zA-Z0-9-]+\\.)+[a-zA-Z]{2,7}$"; @Value("${spring.mail.username}") private String from; private final static String TEMPLATE = "Your verification code is: ${code}"; @Autowired @SuppressWarnings("all") @@ -65,4 +67,13 @@ } } public boolean isValid(String email) { if (Cools.isEmpty(email)) { return false; } Pattern pattern = Pattern.compile(EMAIL_REGEX); Matcher matcher = pattern.matcher(email); return matcher.matches(); } } rsf-server/src/main/java/com/vincent/rsf/server/system/controller/AuthController.java
@@ -83,10 +83,13 @@ } @GetMapping("/email/code") public R emailCode(@RequestParam("email") String email) { public R emailCode(@RequestParam(value = "email", required = false) String email) { if (Cools.isEmpty(email)) { return R.parse(BaseRes.PARAM); } if (!emailService.isValid(email)) { return R.error("Please enter a valid email address"); } if (null != userService.getByEmail(email, null)) { return R.error("Email Already Exist"); }