diff --git a/web/berry/src/assets/images/icons/lark.svg b/web/berry/src/assets/images/icons/lark.svg
new file mode 100644
index 00000000..239e1bef
--- /dev/null
+++ b/web/berry/src/assets/images/icons/lark.svg
@@ -0,0 +1 @@
+
\ No newline at end of file
diff --git a/web/berry/src/hooks/useLogin.js b/web/berry/src/hooks/useLogin.js
index 53626577..39d8b407 100644
--- a/web/berry/src/hooks/useLogin.js
+++ b/web/berry/src/hooks/useLogin.js
@@ -48,6 +48,28 @@ const useLogin = () => {
}
};
+ const larkLogin = async (code, state) => {
+ try {
+ const res = await API.get(`/api/oauth/lark?code=${code}&state=${state}`);
+ const { success, message, data } = res.data;
+ if (success) {
+ if (message === 'bind') {
+ showSuccess('绑定成功!');
+ navigate('/panel');
+ } else {
+ dispatch({ type: LOGIN, payload: data });
+ localStorage.setItem('user', JSON.stringify(data));
+ showSuccess('登录成功!');
+ navigate('/panel');
+ }
+ }
+ return { success, message };
+ } catch (err) {
+ // 请求失败,设置错误信息
+ return { success: false, message: '' };
+ }
+ };
+
const wechatLogin = async (code) => {
try {
const res = await API.get(`/api/oauth/wechat?code=${code}`);
@@ -72,7 +94,7 @@ const useLogin = () => {
navigate('/');
};
- return { login, logout, githubLogin, wechatLogin };
+ return { login, logout, githubLogin, wechatLogin, larkLogin };
};
export default useLogin;
diff --git a/web/berry/src/routes/OtherRoutes.js b/web/berry/src/routes/OtherRoutes.js
index 085c4add..58c0b660 100644
--- a/web/berry/src/routes/OtherRoutes.js
+++ b/web/berry/src/routes/OtherRoutes.js
@@ -8,6 +8,7 @@ import MinimalLayout from 'layout/MinimalLayout';
const AuthLogin = Loadable(lazy(() => import('views/Authentication/Auth/Login')));
const AuthRegister = Loadable(lazy(() => import('views/Authentication/Auth/Register')));
const GitHubOAuth = Loadable(lazy(() => import('views/Authentication/Auth/GitHubOAuth')));
+const LarkOAuth = Loadable(lazy(() => import('views/Authentication/Auth/LarkOAuth')));
const ForgetPassword = Loadable(lazy(() => import('views/Authentication/Auth/ForgetPassword')));
const ResetPassword = Loadable(lazy(() => import('views/Authentication/Auth/ResetPassword')));
const Home = Loadable(lazy(() => import('views/Home')));
@@ -48,6 +49,10 @@ const OtherRoutes = {
path: '/oauth/github',
element:
},
+ {
+ path: '/oauth/lark',
+ element:
+ },
{
path: '/404',
element:
diff --git a/web/berry/src/utils/common.js b/web/berry/src/utils/common.js
index d8dabac3..947df3bf 100644
--- a/web/berry/src/utils/common.js
+++ b/web/berry/src/utils/common.js
@@ -91,6 +91,13 @@ export async function onGitHubOAuthClicked(github_client_id, openInNewTab = fals
}
}
+export async function onLarkOAuthClicked(lark_client_id) {
+ const state = await getOAuthState();
+ if (!state) return;
+ let redirect_uri = `${window.location.origin}/oauth/lark`;
+ window.open(`https://open.feishu.cn/open-apis/authen/v1/index?redirect_uri=${redirect_uri}&app_id=${lark_client_id}&state=${state}`);
+}
+
export function isAdmin() {
let user = localStorage.getItem('user');
if (!user) return false;
diff --git a/web/berry/src/views/Authentication/Auth/LarkOAuth.js b/web/berry/src/views/Authentication/Auth/LarkOAuth.js
new file mode 100644
index 00000000..88ced5d8
--- /dev/null
+++ b/web/berry/src/views/Authentication/Auth/LarkOAuth.js
@@ -0,0 +1,94 @@
+import { Link, useNavigate, useSearchParams } from 'react-router-dom';
+import React, { useEffect, useState } from 'react';
+import { showError } from 'utils/common';
+import useLogin from 'hooks/useLogin';
+
+// material-ui
+import { useTheme } from '@mui/material/styles';
+import { Grid, Stack, Typography, useMediaQuery, CircularProgress } from '@mui/material';
+
+// project imports
+import AuthWrapper from '../AuthWrapper';
+import AuthCardWrapper from '../AuthCardWrapper';
+import Logo from 'ui-component/Logo';
+
+// assets
+
+// ================================|| AUTH3 - LOGIN ||================================ //
+
+const LarkOAuth = () => {
+ const theme = useTheme();
+ const matchDownSM = useMediaQuery(theme.breakpoints.down('md'));
+
+ const [searchParams] = useSearchParams();
+ const [prompt, setPrompt] = useState('处理中...');
+ const { larkLogin } = useLogin();
+
+ let navigate = useNavigate();
+
+ const sendCode = async (code, state, count) => {
+ const { success, message } = await larkLogin(code, state);
+ if (!success) {
+ if (message) {
+ showError(message);
+ }
+ if (count === 0) {
+ setPrompt(`操作失败,重定向至登录界面中...`);
+ await new Promise((resolve) => setTimeout(resolve, 2000));
+ navigate('/login');
+ return;
+ }
+ count++;
+ setPrompt(`出现错误,第 ${count} 次重试中...`);
+ await new Promise((resolve) => setTimeout(resolve, 2000));
+ await sendCode(code, state, count);
+ }
+ };
+
+ useEffect(() => {
+ let code = searchParams.get('code');
+ let state = searchParams.get('state');
+ sendCode(code, state, 0).then();
+ }, []);
+
+ return (
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+ 飞书 登录
+
+
+
+
+
+
+
+
+ {prompt}
+
+
+
+
+
+
+
+
+
+ );
+};
+
+export default LarkOAuth;
diff --git a/web/berry/src/views/Authentication/AuthForms/AuthLogin.js b/web/berry/src/views/Authentication/AuthForms/AuthLogin.js
index 9420b098..bc7a35c0 100644
--- a/web/berry/src/views/Authentication/AuthForms/AuthLogin.js
+++ b/web/berry/src/views/Authentication/AuthForms/AuthLogin.js
@@ -35,7 +35,8 @@ import VisibilityOff from '@mui/icons-material/VisibilityOff';
import Github from 'assets/images/icons/github.svg';
import Wechat from 'assets/images/icons/wechat.svg';
-import { onGitHubOAuthClicked } from 'utils/common';
+import Lark from 'assets/images/icons/lark.svg';
+import { onGitHubOAuthClicked, onLarkOAuthClicked } from 'utils/common';
// ============================|| FIREBASE - LOGIN ||============================ //
@@ -49,7 +50,7 @@ const LoginForm = ({ ...others }) => {
// const [checked, setChecked] = useState(true);
let tripartiteLogin = false;
- if (siteInfo.github_oauth || siteInfo.wechat_login) {
+ if (siteInfo.github_oauth || siteInfo.wechat_login || siteInfo.lark_client_id) {
tripartiteLogin = true;
}
@@ -121,6 +122,29 @@ const LoginForm = ({ ...others }) => {
)}
+ {siteInfo.lark_client_id && (
+
+
+
+
+
+ )}
{inputs.email || '未绑定'}
+
@@ -205,6 +210,13 @@ export default function Profile() {
)}
+ {status.lark_client_id && !inputs.lark_id && (
+
+
+
+ )}
+
+ {' '}
+ 用以支持通过飞书进行登录注册,
+
+ 点击此处
+
+ 管理你的飞书应用
+
+ }
+ >
+
+
+
+ 主页链接填 {inputs.ServerAddress}
+ ,重定向 URL 填 {`${inputs.ServerAddress}/oauth/lark`}
+
+
+
+
+ App ID
+
+
+
+
+
+ App Secret
+
+
+
+
+
+
+
+