mirror of
https://github.com/infiniflow/ragflow.git
synced 2025-12-18 03:26:42 +08:00
Fix several admin UI issues (#10869)
### What problem does this PR solve? - Fix login card will overlap title in admin login page. - Disable unnecessary `listRoles()` query in user management page and create user form - Disable admin UI API queries and mutations retry mechanism - Fix page not redirect to login page automatically if API reports unauthorized (401) - Fix change password form not reset when change password modal close - Resolve admin UI content (mostly long texts) may break layout main box issue ### Type of change - [x] Bug Fix (non-breaking change which fixes an issue)
This commit is contained in:
@ -24,7 +24,9 @@ import {
|
|||||||
SelectValue,
|
SelectValue,
|
||||||
} from '@/components/ui/select';
|
} from '@/components/ui/select';
|
||||||
import { listRoles } from '@/services/admin-service';
|
import { listRoles } from '@/services/admin-service';
|
||||||
|
|
||||||
import EnterpriseFeature from '../components/enterprise-feature';
|
import EnterpriseFeature from '../components/enterprise-feature';
|
||||||
|
import { IS_ENTERPRISE } from '../utils';
|
||||||
|
|
||||||
interface CreateUserFormData {
|
interface CreateUserFormData {
|
||||||
email: string;
|
email: string;
|
||||||
@ -49,6 +51,8 @@ export const CreateUserForm = ({
|
|||||||
const { data: roleList } = useQuery({
|
const { data: roleList } = useQuery({
|
||||||
queryKey: ['admin/listRoles'],
|
queryKey: ['admin/listRoles'],
|
||||||
queryFn: async () => (await listRoles()).data.data.roles,
|
queryFn: async () => (await listRoles()).data.data.roles,
|
||||||
|
enabled: IS_ENTERPRISE,
|
||||||
|
retry: false,
|
||||||
});
|
});
|
||||||
|
|
||||||
return (
|
return (
|
||||||
|
|||||||
@ -1,3 +1,16 @@
|
|||||||
|
import { type AxiosResponseHeaders } from 'axios';
|
||||||
|
import { useEffect, useId, useState } from 'react';
|
||||||
|
import { useForm } from 'react-hook-form';
|
||||||
|
import { useTranslation } from 'react-i18next';
|
||||||
|
import { useNavigate } from 'umi';
|
||||||
|
|
||||||
|
import { LucideEye, LucideEyeOff } from 'lucide-react';
|
||||||
|
|
||||||
|
import { useMutation } from '@tanstack/react-query';
|
||||||
|
|
||||||
|
import { zodResolver } from '@hookform/resolvers/zod';
|
||||||
|
import { z } from 'zod';
|
||||||
|
|
||||||
import Spotlight from '@/components/spotlight';
|
import Spotlight from '@/components/spotlight';
|
||||||
import { ButtonLoading } from '@/components/ui/button';
|
import { ButtonLoading } from '@/components/ui/button';
|
||||||
import { Card, CardContent, CardFooter } from '@/components/ui/card';
|
import { Card, CardContent, CardFooter } from '@/components/ui/card';
|
||||||
@ -11,22 +24,17 @@ import {
|
|||||||
FormMessage,
|
FormMessage,
|
||||||
} from '@/components/ui/form';
|
} from '@/components/ui/form';
|
||||||
import { Input } from '@/components/ui/input';
|
import { Input } from '@/components/ui/input';
|
||||||
|
import { ScrollArea } from '@/components/ui/scroll-area';
|
||||||
import { Authorization } from '@/constants/authorization';
|
import { Authorization } from '@/constants/authorization';
|
||||||
|
|
||||||
import { useAuth } from '@/hooks/auth-hooks';
|
import { useAuth } from '@/hooks/auth-hooks';
|
||||||
import { cn } from '@/lib/utils';
|
import { cn } from '@/lib/utils';
|
||||||
import { Routes } from '@/routes';
|
import { Routes } from '@/routes';
|
||||||
import adminService from '@/services/admin-service';
|
|
||||||
import { rsaPsw } from '@/utils';
|
import { rsaPsw } from '@/utils';
|
||||||
import authorizationUtil from '@/utils/authorization-util';
|
import authorizationUtil from '@/utils/authorization-util';
|
||||||
import { zodResolver } from '@hookform/resolvers/zod';
|
|
||||||
import { useMutation } from '@tanstack/react-query';
|
import { login } from '@/services/admin-service';
|
||||||
import { AxiosResponseHeaders } from 'axios';
|
|
||||||
import { LucideEye, LucideEyeOff } from 'lucide-react';
|
|
||||||
import { useEffect, useId, useState } from 'react';
|
|
||||||
import { SubmitHandler, useForm } from 'react-hook-form';
|
|
||||||
import { useTranslation } from 'react-i18next';
|
|
||||||
import { useNavigate } from 'umi';
|
|
||||||
import { z } from 'zod';
|
|
||||||
import { BgSvg } from '../login-next/bg';
|
import { BgSvg } from '../login-next/bg';
|
||||||
import ThemeSwitch from './components/theme-switch';
|
import ThemeSwitch from './components/theme-switch';
|
||||||
|
|
||||||
@ -37,13 +45,19 @@ function AdminLogin() {
|
|||||||
|
|
||||||
const [showPassword, setShowPassword] = useState(false);
|
const [showPassword, setShowPassword] = useState(false);
|
||||||
|
|
||||||
const { isPending: signLoading, mutateAsync: login } = useMutation({
|
const loginMutation = useMutation({
|
||||||
mutationKey: ['adminLogin'],
|
mutationKey: ['adminLogin'],
|
||||||
mutationFn: async (params: { email: string; password: string }) => {
|
mutationFn: async (params: { email: string; password: string }) => {
|
||||||
const request = await adminService.login(params);
|
const rsaPassWord = rsaPsw(params.password) as string;
|
||||||
|
return await login({
|
||||||
|
email: params.email,
|
||||||
|
password: rsaPassWord,
|
||||||
|
});
|
||||||
|
},
|
||||||
|
onSuccess: (request) => {
|
||||||
const { data: req, headers } = request;
|
const { data: req, headers } = request;
|
||||||
|
|
||||||
if (req.code === 0) {
|
if (req?.code === 0) {
|
||||||
const authorization = (headers as AxiosResponseHeaders)?.get(
|
const authorization = (headers as AxiosResponseHeaders)?.get(
|
||||||
Authorization,
|
Authorization,
|
||||||
);
|
);
|
||||||
@ -60,13 +74,17 @@ function AdminLogin() {
|
|||||||
Token: token,
|
Token: token,
|
||||||
userInfo: JSON.stringify(userInfo),
|
userInfo: JSON.stringify(userInfo),
|
||||||
});
|
});
|
||||||
}
|
|
||||||
|
|
||||||
return req;
|
navigate('/admin/services');
|
||||||
|
}
|
||||||
},
|
},
|
||||||
|
onError: (error) => {
|
||||||
|
console.log('Failed:', error);
|
||||||
|
},
|
||||||
|
retry: false,
|
||||||
});
|
});
|
||||||
|
|
||||||
const loading = signLoading;
|
const loading = loginMutation.isPending;
|
||||||
|
|
||||||
useEffect(() => {
|
useEffect(() => {
|
||||||
if (isLogin) {
|
if (isLogin) {
|
||||||
@ -93,25 +111,9 @@ function AdminLogin() {
|
|||||||
resolver: zodResolver(FormSchema),
|
resolver: zodResolver(FormSchema),
|
||||||
});
|
});
|
||||||
|
|
||||||
const onCheck: SubmitHandler<z.infer<typeof FormSchema>> = async (params) => {
|
|
||||||
try {
|
|
||||||
const rsaPassWord = rsaPsw(params.password) as string;
|
|
||||||
|
|
||||||
const { code } = await login({
|
|
||||||
email: `${params.email}`.trim(),
|
|
||||||
password: rsaPassWord,
|
|
||||||
});
|
|
||||||
|
|
||||||
if (code === 0) {
|
|
||||||
navigate('/admin/services');
|
|
||||||
}
|
|
||||||
} catch (errorInfo) {
|
|
||||||
console.log('Failed:', errorInfo);
|
|
||||||
}
|
|
||||||
};
|
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<div className="relative w-screen h-screen">
|
<ScrollArea className="w-screen h-screen">
|
||||||
|
<div className="relative">
|
||||||
<Spotlight opcity={0.4} coverage={60} color="rgb(128, 255, 248)" />
|
<Spotlight opcity={0.4} coverage={60} color="rgb(128, 255, 248)" />
|
||||||
<Spotlight
|
<Spotlight
|
||||||
opcity={0.3}
|
opcity={0.3}
|
||||||
@ -141,7 +143,7 @@ function AdminLogin() {
|
|||||||
</h1>
|
</h1>
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
<div className="flex items-center justify-center w-screen h-screen">
|
<div className="flex items-center justify-center w-screen min-h-[1050px]">
|
||||||
<div className="w-full max-w-[540px]">
|
<div className="w-full max-w-[540px]">
|
||||||
<Card className="w-full bg-bg-component backdrop-blur-sm rounded-2xl border border-border-button">
|
<Card className="w-full bg-bg-component backdrop-blur-sm rounded-2xl border border-border-button">
|
||||||
<CardContent className="px-10 pt-14 pb-10">
|
<CardContent className="px-10 pt-14 pb-10">
|
||||||
@ -149,7 +151,9 @@ function AdminLogin() {
|
|||||||
<form
|
<form
|
||||||
id={formId}
|
id={formId}
|
||||||
className="space-y-8 text-text-primary"
|
className="space-y-8 text-text-primary"
|
||||||
onSubmit={form.handleSubmit(onCheck)}
|
onSubmit={form.handleSubmit((data) =>
|
||||||
|
loginMutation.mutate(data),
|
||||||
|
)}
|
||||||
>
|
>
|
||||||
<FormField
|
<FormField
|
||||||
control={form.control}
|
control={form.control}
|
||||||
@ -259,6 +263,7 @@ function AdminLogin() {
|
|||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
|
</ScrollArea>
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@ -14,13 +14,12 @@ import {
|
|||||||
} from 'lucide-react';
|
} from 'lucide-react';
|
||||||
import { useMemo } from 'react';
|
import { useMemo } from 'react';
|
||||||
import { useTranslation } from 'react-i18next';
|
import { useTranslation } from 'react-i18next';
|
||||||
import { NavLink, Outlet, useLocation, useNavigate } from 'umi';
|
import { NavLink, Outlet, useNavigate } from 'umi';
|
||||||
import ThemeSwitch from './components/theme-switch';
|
import ThemeSwitch from './components/theme-switch';
|
||||||
import { IS_ENTERPRISE } from './utils';
|
import { IS_ENTERPRISE } from './utils';
|
||||||
|
|
||||||
const AdminLayout = () => {
|
const AdminLayout = () => {
|
||||||
const { t } = useTranslation();
|
const { t } = useTranslation();
|
||||||
const { pathname } = useLocation();
|
|
||||||
const navigate = useNavigate();
|
const navigate = useNavigate();
|
||||||
|
|
||||||
const navItems = useMemo(
|
const navItems = useMemo(
|
||||||
@ -58,11 +57,7 @@ const AdminLayout = () => {
|
|||||||
[t],
|
[t],
|
||||||
);
|
);
|
||||||
|
|
||||||
const {
|
const logoutMutation = useMutation({
|
||||||
data,
|
|
||||||
isPending,
|
|
||||||
mutateAsync: logout,
|
|
||||||
} = useMutation({
|
|
||||||
mutationKey: ['adminLogout'],
|
mutationKey: ['adminLogout'],
|
||||||
mutationFn: async () => {
|
mutationFn: async () => {
|
||||||
await adminService.logout();
|
await adminService.logout();
|
||||||
@ -71,11 +66,12 @@ const AdminLayout = () => {
|
|||||||
authorizationUtil.removeAll();
|
authorizationUtil.removeAll();
|
||||||
navigate(Routes.Admin);
|
navigate(Routes.Admin);
|
||||||
},
|
},
|
||||||
|
retry: false,
|
||||||
});
|
});
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<main className="w-screen h-screen flex flex-row px-6 pt-12 pb-6 dark:*:focus-visible:ring-white">
|
<main className="w-screen h-screen flex flex-row px-6 pt-12 pb-6 dark:*:focus-visible:ring-white">
|
||||||
<aside className="w-[28rem] mr-6 flex flex-col gap-6">
|
<aside className="w-72 mr-6 flex flex-col gap-6">
|
||||||
<div className="flex items-center mb-6">
|
<div className="flex items-center mb-6">
|
||||||
<img className="size-8 mr-5" src="/logo.svg" alt="logo" />
|
<img className="size-8 mr-5" src="/logo.svg" alt="logo" />
|
||||||
<span className="text-xl font-bold">{t('admin.title')}</span>
|
<span className="text-xl font-bold">{t('admin.title')}</span>
|
||||||
@ -87,17 +83,18 @@ const AdminLayout = () => {
|
|||||||
<li key={it.path}>
|
<li key={it.path}>
|
||||||
<NavLink
|
<NavLink
|
||||||
to={it.path}
|
to={it.path}
|
||||||
className={cn(
|
className={({ isActive }) =>
|
||||||
|
cn(
|
||||||
'px-4 py-3 rounded-lg',
|
'px-4 py-3 rounded-lg',
|
||||||
'text-base w-full flex items-center justify-start text-text-secondary',
|
'text-base w-full flex items-center justify-start text-text-secondary',
|
||||||
'hover:bg-bg-card focus:bg-bg-card focus-visible:bg-bg-card',
|
'hover:bg-bg-card focus:bg-bg-card focus-visible:bg-bg-card',
|
||||||
'hover:text-text-primary focus:text-text-primary focus-visible:text-text-primary',
|
'hover:text-text-primary focus:text-text-primary focus-visible:text-text-primary',
|
||||||
'active:text-text-primary',
|
'active:text-text-primary',
|
||||||
{
|
{
|
||||||
'bg-bg-card text-text-primary':
|
'bg-bg-card text-text-primary': isActive,
|
||||||
it.path && pathname.startsWith(it.path),
|
|
||||||
},
|
},
|
||||||
)}
|
)
|
||||||
|
}
|
||||||
>
|
>
|
||||||
{it.icon}
|
{it.icon}
|
||||||
<span className="ml-3">{it.name}</span>
|
<span className="ml-3">{it.name}</span>
|
||||||
@ -116,14 +113,14 @@ const AdminLayout = () => {
|
|||||||
size="lg"
|
size="lg"
|
||||||
variant="transparent"
|
variant="transparent"
|
||||||
className="block w-full dark:border-border-button"
|
className="block w-full dark:border-border-button"
|
||||||
onClick={() => logout()}
|
onClick={() => logoutMutation.mutate()}
|
||||||
>
|
>
|
||||||
{t('header.logout')}
|
{t('header.logout')}
|
||||||
</Button>
|
</Button>
|
||||||
</div>
|
</div>
|
||||||
</aside>
|
</aside>
|
||||||
|
|
||||||
<section className="w-full h-full">
|
<section className="flex-1 h-full">
|
||||||
<Outlet />
|
<Outlet />
|
||||||
</section>
|
</section>
|
||||||
</main>
|
</main>
|
||||||
|
|||||||
@ -307,6 +307,7 @@ function AdminUserDetail() {
|
|||||||
};
|
};
|
||||||
},
|
},
|
||||||
enabled: !!id,
|
enabled: !!id,
|
||||||
|
retry: false,
|
||||||
});
|
});
|
||||||
|
|
||||||
return (
|
return (
|
||||||
|
|||||||
@ -126,11 +126,14 @@ function AdminUserManagement() {
|
|||||||
const { data: roleList } = useQuery({
|
const { data: roleList } = useQuery({
|
||||||
queryKey: ['admin/listRoles'],
|
queryKey: ['admin/listRoles'],
|
||||||
queryFn: async () => (await listRoles()).data.data.roles,
|
queryFn: async () => (await listRoles()).data.data.roles,
|
||||||
|
enabled: IS_ENTERPRISE,
|
||||||
|
retry: false,
|
||||||
});
|
});
|
||||||
|
|
||||||
const { data: usersList, isPending } = useQuery({
|
const { data: usersList, isPending } = useQuery({
|
||||||
queryKey: ['admin/listUsers'],
|
queryKey: ['admin/listUsers'],
|
||||||
queryFn: async () => (await listUsers()).data.data,
|
queryFn: async () => (await listUsers()).data.data,
|
||||||
|
retry: false,
|
||||||
});
|
});
|
||||||
|
|
||||||
// Delete user mutation
|
// Delete user mutation
|
||||||
@ -142,17 +145,19 @@ function AdminUserManagement() {
|
|||||||
setDeleteModalOpen(false);
|
setDeleteModalOpen(false);
|
||||||
setUserToMakeAction(null);
|
setUserToMakeAction(null);
|
||||||
},
|
},
|
||||||
|
retry: false,
|
||||||
});
|
});
|
||||||
|
|
||||||
// Change password mutation
|
// Change password mutation
|
||||||
const changePasswordMutation = useMutation({
|
const changePasswordMutation = useMutation({
|
||||||
mutationFn: ({ email, password }: { email: string; password: string }) =>
|
mutationFn: ({ email, password }: { email: string; password: string }) =>
|
||||||
updateUserPassword(email, password),
|
updateUserPassword(email, rsaPsw(password) as string),
|
||||||
onSuccess: () => {
|
onSuccess: () => {
|
||||||
// message.success(t('admin.passwordChangedSuccessfully'));
|
// message.success(t('admin.passwordChangedSuccessfully'));
|
||||||
setPasswordModalOpen(false);
|
setPasswordModalOpen(false);
|
||||||
setUserToMakeAction(null);
|
setUserToMakeAction(null);
|
||||||
},
|
},
|
||||||
|
retry: false,
|
||||||
});
|
});
|
||||||
|
|
||||||
// Update user role mutation
|
// Update user role mutation
|
||||||
@ -162,6 +167,7 @@ function AdminUserManagement() {
|
|||||||
onSuccess: () => {
|
onSuccess: () => {
|
||||||
queryClient.invalidateQueries({ queryKey: ['admin/listUsers'] });
|
queryClient.invalidateQueries({ queryKey: ['admin/listUsers'] });
|
||||||
},
|
},
|
||||||
|
retry: false,
|
||||||
});
|
});
|
||||||
|
|
||||||
// Create user mutation
|
// Create user mutation
|
||||||
@ -175,7 +181,7 @@ function AdminUserManagement() {
|
|||||||
password: string;
|
password: string;
|
||||||
role?: string;
|
role?: string;
|
||||||
}) => {
|
}) => {
|
||||||
await createUser(email, password);
|
await createUser(email, rsaPsw(password) as string);
|
||||||
|
|
||||||
if (IS_ENTERPRISE && role) {
|
if (IS_ENTERPRISE && role) {
|
||||||
await updateUserRoleMutation.mutateAsync({ email, role });
|
await updateUserRoleMutation.mutateAsync({ email, role });
|
||||||
@ -187,6 +193,7 @@ function AdminUserManagement() {
|
|||||||
setCreateUserModalOpen(false);
|
setCreateUserModalOpen(false);
|
||||||
createUserForm.form.reset();
|
createUserForm.form.reset();
|
||||||
},
|
},
|
||||||
|
retry: false,
|
||||||
});
|
});
|
||||||
|
|
||||||
// Update user status mutation
|
// Update user status mutation
|
||||||
@ -196,6 +203,7 @@ function AdminUserManagement() {
|
|||||||
onSuccess: () => {
|
onSuccess: () => {
|
||||||
queryClient.invalidateQueries({ queryKey: ['admin/listUsers'] });
|
queryClient.invalidateQueries({ queryKey: ['admin/listUsers'] });
|
||||||
},
|
},
|
||||||
|
retry: false,
|
||||||
});
|
});
|
||||||
|
|
||||||
const columnDefs = useMemo(
|
const columnDefs = useMemo(
|
||||||
@ -573,7 +581,8 @@ function AdminUserManagement() {
|
|||||||
className="px-4 h-10"
|
className="px-4 h-10"
|
||||||
variant="destructive"
|
variant="destructive"
|
||||||
onClick={() =>
|
onClick={() =>
|
||||||
deleteUserMutation.mutate(userToMakeAction?.email || '')
|
userToMakeAction &&
|
||||||
|
deleteUserMutation.mutate(userToMakeAction?.email)
|
||||||
}
|
}
|
||||||
disabled={deleteUserMutation.isPending}
|
disabled={deleteUserMutation.isPending}
|
||||||
loading={deleteUserMutation.isPending}
|
loading={deleteUserMutation.isPending}
|
||||||
@ -586,7 +595,14 @@ function AdminUserManagement() {
|
|||||||
|
|
||||||
{/* Change Password Modal */}
|
{/* Change Password Modal */}
|
||||||
<Dialog open={passwordModalOpen} onOpenChange={setPasswordModalOpen}>
|
<Dialog open={passwordModalOpen} onOpenChange={setPasswordModalOpen}>
|
||||||
<DialogContent className="p-0 border-border-button">
|
<DialogContent
|
||||||
|
className="p-0 border-border-button"
|
||||||
|
onAnimationEnd={() => {
|
||||||
|
if (!passwordModalOpen) {
|
||||||
|
changePasswordForm.form.reset();
|
||||||
|
}
|
||||||
|
}}
|
||||||
|
>
|
||||||
<DialogHeader className="p-6 border-b border-border-button">
|
<DialogHeader className="p-6 border-b border-border-button">
|
||||||
<DialogTitle>{t('admin.changePassword')}</DialogTitle>
|
<DialogTitle>{t('admin.changePassword')}</DialogTitle>
|
||||||
</DialogHeader>
|
</DialogHeader>
|
||||||
@ -599,7 +615,7 @@ function AdminUserManagement() {
|
|||||||
if (userToMakeAction) {
|
if (userToMakeAction) {
|
||||||
changePasswordMutation.mutate({
|
changePasswordMutation.mutate({
|
||||||
email: userToMakeAction.email,
|
email: userToMakeAction.email,
|
||||||
password: rsaPsw(newPassword) as string,
|
password: newPassword,
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
}}
|
}}
|
||||||
@ -649,12 +665,7 @@ function AdminUserManagement() {
|
|||||||
<section className="px-12 py-4">
|
<section className="px-12 py-4">
|
||||||
<createUserForm.FormComponent
|
<createUserForm.FormComponent
|
||||||
id={createUserForm.id}
|
id={createUserForm.id}
|
||||||
onSubmit={({ email, password }) => {
|
onSubmit={createUserMutation.mutate}
|
||||||
createUserMutation.mutate({
|
|
||||||
email: email,
|
|
||||||
password: rsaPsw(password) as string,
|
|
||||||
});
|
|
||||||
}}
|
|
||||||
/>
|
/>
|
||||||
</section>
|
</section>
|
||||||
|
|
||||||
|
|||||||
@ -1,6 +1,6 @@
|
|||||||
import { message, notification } from 'antd';
|
import { message, notification } from 'antd';
|
||||||
import axios from 'axios';
|
import axios from 'axios';
|
||||||
import { Navigate } from 'umi';
|
import { history } from 'umi';
|
||||||
|
|
||||||
import { Authorization } from '@/constants/authorization';
|
import { Authorization } from '@/constants/authorization';
|
||||||
import i18n from '@/locales/config';
|
import i18n from '@/locales/config';
|
||||||
@ -48,7 +48,7 @@ request.interceptors.response.use(
|
|||||||
});
|
});
|
||||||
|
|
||||||
authorizationUtil.removeAll();
|
authorizationUtil.removeAll();
|
||||||
Navigate({ to: Routes.Admin });
|
history.push(Routes.Admin);
|
||||||
} else if (data?.code && data.code !== 0) {
|
} else if (data?.code && data.code !== 0) {
|
||||||
notification.error({
|
notification.error({
|
||||||
message: `${i18n.t('message.hint')}: ${data?.code}`,
|
message: `${i18n.t('message.hint')}: ${data?.code}`,
|
||||||
@ -70,15 +70,16 @@ request.interceptors.response.use(
|
|||||||
});
|
});
|
||||||
} else if (data?.code === 100) {
|
} else if (data?.code === 100) {
|
||||||
message.error(data?.message);
|
message.error(data?.message);
|
||||||
} else if (data?.code === 401) {
|
} else if (response.status === 401 || data?.code === 401) {
|
||||||
notification.error({
|
notification.error({
|
||||||
message: data?.message,
|
message: data?.message || response.statusText,
|
||||||
description: data?.message,
|
description:
|
||||||
|
data?.message || RetcodeMessage[response?.status as ResultCode],
|
||||||
duration: 3,
|
duration: 3,
|
||||||
});
|
});
|
||||||
|
|
||||||
authorizationUtil.removeAll();
|
authorizationUtil.removeAll();
|
||||||
Navigate({ to: Routes.Admin });
|
history.push(Routes.Admin);
|
||||||
} else if (data?.code && data.code !== 0) {
|
} else if (data?.code && data.code !== 0) {
|
||||||
notification.error({
|
notification.error({
|
||||||
message: `${i18n.t('message.hint')}: ${data?.code}`,
|
message: `${i18n.t('message.hint')}: ${data?.code}`,
|
||||||
@ -93,17 +94,9 @@ request.interceptors.response.use(
|
|||||||
});
|
});
|
||||||
} else if (response.status === 413 || response?.status === 504) {
|
} else if (response.status === 413 || response?.status === 504) {
|
||||||
message.error(RetcodeMessage[response?.status as ResultCode]);
|
message.error(RetcodeMessage[response?.status as ResultCode]);
|
||||||
} else if (response.status === 401) {
|
|
||||||
notification.error({
|
|
||||||
message: response.data.message,
|
|
||||||
description: response.data.message,
|
|
||||||
duration: 3,
|
|
||||||
});
|
|
||||||
authorizationUtil.removeAll();
|
|
||||||
window.location.href = location.origin + '/admin';
|
|
||||||
}
|
}
|
||||||
|
|
||||||
return error;
|
throw error;
|
||||||
},
|
},
|
||||||
);
|
);
|
||||||
|
|
||||||
@ -112,7 +105,7 @@ const {
|
|||||||
adminLogout,
|
adminLogout,
|
||||||
adminListUsers,
|
adminListUsers,
|
||||||
adminCreateUser,
|
adminCreateUser,
|
||||||
adminGetUserDetails: adminShowUserDetails,
|
adminGetUserDetails,
|
||||||
adminUpdateUserStatus,
|
adminUpdateUserStatus,
|
||||||
adminUpdateUserPassword,
|
adminUpdateUserPassword,
|
||||||
adminDeleteUser,
|
adminDeleteUser,
|
||||||
@ -260,11 +253,11 @@ export namespace AdminService {
|
|||||||
update_date: string;
|
update_date: string;
|
||||||
};
|
};
|
||||||
|
|
||||||
export type AssignRolePermissionInput = {
|
export type AssignRolePermissionsInput = Record<
|
||||||
permissions: Record<string, Partial<PermissionData>>;
|
string,
|
||||||
};
|
Partial<PermissionData>
|
||||||
|
>;
|
||||||
export type RevokeRolePermissionInput = AssignRolePermissionInput;
|
export type RevokeRolePermissionInput = AssignRolePermissionsInput;
|
||||||
|
|
||||||
export type UserDetailWithPermission = {
|
export type UserDetailWithPermission = {
|
||||||
user: {
|
user: {
|
||||||
@ -293,7 +286,7 @@ export const createUser = (email: string, password: string) =>
|
|||||||
});
|
});
|
||||||
export const getUserDetails = (email: string) =>
|
export const getUserDetails = (email: string) =>
|
||||||
request.get<ResponseData<[AdminService.UserDetail]>>(
|
request.get<ResponseData<[AdminService.UserDetail]>>(
|
||||||
adminShowUserDetails(email),
|
adminGetUserDetails(email),
|
||||||
);
|
);
|
||||||
export const listUserDatasets = (email: string) =>
|
export const listUserDatasets = (email: string) =>
|
||||||
request.get<ResponseData<AdminService.ListUserDatasetItem[]>>(
|
request.get<ResponseData<AdminService.ListUserDatasetItem[]>>(
|
||||||
@ -317,7 +310,10 @@ export const showServiceDetails = (serviceId: number) =>
|
|||||||
adminShowServiceDetails(String(serviceId)),
|
adminShowServiceDetails(String(serviceId)),
|
||||||
);
|
);
|
||||||
|
|
||||||
export const createRole = (params: { roleName: string; description: string }) =>
|
export const createRole = (params: {
|
||||||
|
roleName: string;
|
||||||
|
description?: string;
|
||||||
|
}) =>
|
||||||
request.post<ResponseData<AdminService.RoleDetail>>(adminCreateRole, params);
|
request.post<ResponseData<AdminService.RoleDetail>>(adminCreateRole, params);
|
||||||
export const updateRoleDescription = (role: string, description: string) =>
|
export const updateRoleDescription = (role: string, description: string) =>
|
||||||
request.put<ResponseData<AdminService.RoleDetail>>(
|
request.put<ResponseData<AdminService.RoleDetail>>(
|
||||||
@ -343,15 +339,17 @@ export const getRolePermissions = (role: string) =>
|
|||||||
);
|
);
|
||||||
export const assignRolePermissions = (
|
export const assignRolePermissions = (
|
||||||
role: string,
|
role: string,
|
||||||
params: AdminService.AssignRolePermissionInput,
|
permissions: Partial<AdminService.AssignRolePermissionsInput>,
|
||||||
) =>
|
) =>
|
||||||
request.post<ResponseData<never>>(adminAssignRolePermissions(role), params);
|
request.post<ResponseData<never>>(adminAssignRolePermissions(role), {
|
||||||
|
new_permissions: permissions,
|
||||||
|
});
|
||||||
export const revokeRolePermissions = (
|
export const revokeRolePermissions = (
|
||||||
role: string,
|
role: string,
|
||||||
params: AdminService.RevokeRolePermissionInput,
|
permissions: Partial<AdminService.RevokeRolePermissionInput>,
|
||||||
) =>
|
) =>
|
||||||
request.delete<ResponseData<never>>(adminRevokeRolePermissions(role), {
|
request.delete<ResponseData<never>>(adminRevokeRolePermissions(role), {
|
||||||
data: params,
|
data: { revoke_permissions: permissions },
|
||||||
});
|
});
|
||||||
|
|
||||||
export const updateUserRole = (username: string, role: string) =>
|
export const updateUserRole = (username: string, role: string) =>
|
||||||
@ -365,12 +363,23 @@ export const getUserPermissions = (username: string) =>
|
|||||||
export const listResources = () =>
|
export const listResources = () =>
|
||||||
request.get<ResponseData<AdminService.ResourceType>>(adminListResources);
|
request.get<ResponseData<AdminService.ResourceType>>(adminListResources);
|
||||||
|
|
||||||
|
export const whitelistImportFromExcel = (file: File) => {
|
||||||
|
const fd = new FormData();
|
||||||
|
|
||||||
|
fd.append('file', file);
|
||||||
|
|
||||||
|
return request.post<ResponseData<never>>(
|
||||||
|
'/api/v1/admin/whitelist/import',
|
||||||
|
fd,
|
||||||
|
);
|
||||||
|
};
|
||||||
|
|
||||||
export default {
|
export default {
|
||||||
login,
|
login,
|
||||||
logout,
|
logout,
|
||||||
listUsers,
|
listUsers,
|
||||||
createUser,
|
createUser,
|
||||||
showUserDetails: getUserDetails,
|
getUserDetails,
|
||||||
updateUserStatus,
|
updateUserStatus,
|
||||||
updateUserPassword,
|
updateUserPassword,
|
||||||
deleteUser,
|
deleteUser,
|
||||||
|
|||||||
Reference in New Issue
Block a user