mirror of
https://github.com/infiniflow/ragflow.git
synced 2025-12-08 20:42:30 +08:00
Feat: Add frontend support for third-party login integration (#7553)
### What problem does this PR solve? Add frontend support for third-party login integration: - Used `getLoginChannels` API to fetch available login channels from the server - Used `loginWithChannel` function to initiate login based on the selected channel - Refactored `useLoginWithGithub` hook to `useOAuthCallback` for generalized OAuth callback handling - Updated the login page to dynamically render third-party login buttons based on the fetched channel list - Styled third-party login buttons to improve user experience - Removed unused code snippets > This PR removes the previously hardcoded GitHub login button. Since the functionality only worked when `location.host` was equal to `demo.ragflow.io`, and the authentication logic is now based on `login.ragflow.io`, this change does not affect the existing logic and is considered a non-breaking change --- #### Frontend Screenshot && Backend Configuration  ```yaml # docker/service_conf.yaml.template # ... oauth: github: icon: github display_name: "Github" # ... custom_channel: display_name: "OIDC" # ... custom_channel_2: display_name: "OAuth2" # ... ``` --- - Related pull requests: - #7379 - #7521 - Related issues: - #3495 ### Type of change - [x] New Feature (non-breaking change which adds functionality) - [x] Refactoring - [x] Performance Improvement
This commit is contained in:
@ -3,7 +3,7 @@ import { message } from 'antd';
|
||||
import { useEffect, useMemo, useState } from 'react';
|
||||
import { useNavigate, useSearchParams } from 'umi';
|
||||
|
||||
export const useLoginWithGithub = () => {
|
||||
export const useOAuthCallback = () => {
|
||||
const [currentQueryParameters, setSearchParams] = useSearchParams();
|
||||
const error = currentQueryParameters.get('error');
|
||||
const newQueryParameters: URLSearchParams = useMemo(
|
||||
@ -12,26 +12,38 @@ export const useLoginWithGithub = () => {
|
||||
);
|
||||
const navigate = useNavigate();
|
||||
|
||||
if (error) {
|
||||
message.error(error);
|
||||
navigate('/login');
|
||||
newQueryParameters.delete('error');
|
||||
setSearchParams(newQueryParameters);
|
||||
return;
|
||||
}
|
||||
useEffect(() => {
|
||||
if (error) {
|
||||
message.error(error);
|
||||
setTimeout(() => {
|
||||
navigate('/login');
|
||||
newQueryParameters.delete('error');
|
||||
setSearchParams(newQueryParameters);
|
||||
}, 1000);
|
||||
return;
|
||||
}
|
||||
|
||||
const auth = currentQueryParameters.get('auth');
|
||||
const auth = currentQueryParameters.get('auth');
|
||||
if (auth) {
|
||||
authorizationUtil.setAuthorization(auth);
|
||||
newQueryParameters.delete('auth');
|
||||
setSearchParams(newQueryParameters);
|
||||
navigate('/knowledge');
|
||||
}
|
||||
}, [
|
||||
error,
|
||||
currentQueryParameters,
|
||||
newQueryParameters,
|
||||
navigate,
|
||||
setSearchParams,
|
||||
]);
|
||||
|
||||
if (auth) {
|
||||
authorizationUtil.setAuthorization(auth);
|
||||
newQueryParameters.delete('auth');
|
||||
setSearchParams(newQueryParameters);
|
||||
}
|
||||
return auth;
|
||||
console.debug(currentQueryParameters.get('auth'));
|
||||
return currentQueryParameters.get('auth');
|
||||
};
|
||||
|
||||
export const useAuth = () => {
|
||||
const auth = useLoginWithGithub();
|
||||
const auth = useOAuthCallback();
|
||||
const [isLogin, setIsLogin] = useState<Nullable<boolean>>(null);
|
||||
|
||||
useEffect(() => {
|
||||
|
||||
@ -1,7 +1,10 @@
|
||||
import { Authorization } from '@/constants/authorization';
|
||||
import userService from '@/services/user-service';
|
||||
import userService, {
|
||||
getLoginChannels,
|
||||
loginWithChannel,
|
||||
} from '@/services/user-service';
|
||||
import authorizationUtil, { redirectToLogin } from '@/utils/authorization-util';
|
||||
import { useMutation } from '@tanstack/react-query';
|
||||
import { useMutation, useQuery } from '@tanstack/react-query';
|
||||
import { Form, message } from 'antd';
|
||||
import { FormInstance } from 'antd/lib';
|
||||
import { useEffect, useState } from 'react';
|
||||
@ -16,6 +19,36 @@ export interface IRegisterRequestBody extends ILoginRequestBody {
|
||||
nickname: string;
|
||||
}
|
||||
|
||||
export interface ILoginChannel {
|
||||
channel: string;
|
||||
display_name: string;
|
||||
icon: string;
|
||||
}
|
||||
|
||||
export const useLoginChannels = () => {
|
||||
const { data, isLoading } = useQuery({
|
||||
queryKey: ['loginChannels'],
|
||||
queryFn: async () => {
|
||||
const { data: res = {} } = await getLoginChannels();
|
||||
return res.data || [];
|
||||
},
|
||||
});
|
||||
|
||||
return { channels: data as ILoginChannel[], loading: isLoading };
|
||||
};
|
||||
|
||||
export const useLoginWithChannel = () => {
|
||||
const { isPending: loading, mutateAsync } = useMutation({
|
||||
mutationKey: ['loginWithChannel'],
|
||||
mutationFn: async (channel: string) => {
|
||||
loginWithChannel(channel);
|
||||
return Promise.resolve();
|
||||
},
|
||||
});
|
||||
|
||||
return { loading, login: mutateAsync };
|
||||
};
|
||||
|
||||
export const useLogin = () => {
|
||||
const { t } = useTranslation();
|
||||
|
||||
@ -67,8 +100,13 @@ export const useRegister = () => {
|
||||
const { data = {} } = await userService.register(params);
|
||||
if (data.code === 0) {
|
||||
message.success(t('message.registered'));
|
||||
} else if (data.message && data.message.includes('registration is disabled')) {
|
||||
message.error(t('message.registerDisabled') || 'User registration is disabled');
|
||||
} else if (
|
||||
data.message &&
|
||||
data.message.includes('registration is disabled')
|
||||
) {
|
||||
message.error(
|
||||
t('message.registerDisabled') || 'User registration is disabled',
|
||||
);
|
||||
}
|
||||
return data.code;
|
||||
},
|
||||
|
||||
Reference in New Issue
Block a user