feat: ip access control
This commit is contained in:
@@ -341,7 +341,7 @@ export default (props: any) => {
|
||||
config={{
|
||||
apiBaseUrl: GPUSTACK_API_BASE_URL,
|
||||
theme: userSettings.theme,
|
||||
iconUrl: '//at.alicdn.com/t/c/font_4613488_mk9rqojjoqk.js',
|
||||
iconUrl: '//at.alicdn.com/t/c/font_4613488_ueevrwt2v9.js',
|
||||
isDarkTheme: userSettings.isDarkTheme,
|
||||
defaultColorPrimary: COLOR_PRIMARY
|
||||
}}
|
||||
|
||||
@@ -1,39 +1,66 @@
|
||||
// columns.ts
|
||||
import { tableSorter } from '@/config/settings';
|
||||
import { AutoTooltip, DropdownButtons, icons } from '@gpustack/core-ui';
|
||||
import { getGPUStackPlugin } from '@/plugins';
|
||||
import {
|
||||
AutoTooltip,
|
||||
DropdownButtons,
|
||||
IconFont,
|
||||
icons
|
||||
} from '@gpustack/core-ui';
|
||||
import { useIntl } from '@umijs/max';
|
||||
import { Tag } from 'antd';
|
||||
import { MenuProps, Tag } from 'antd';
|
||||
import { ColumnsType } from 'antd/lib/table';
|
||||
import dayjs from 'dayjs';
|
||||
import { useMemo } from 'react';
|
||||
import { ListItem } from '../config/types';
|
||||
|
||||
type APIKeyAction = Global.ActionItem<ListItem> & {
|
||||
onClick?: (record: ListItem) => void;
|
||||
};
|
||||
|
||||
interface ColumnsHookProps {
|
||||
handleSelect: (val: string, record: ListItem) => void;
|
||||
handleSelect: (val: string, record: ListItem, item?: APIKeyAction) => void;
|
||||
sortOrder: string[];
|
||||
is_admin?: boolean;
|
||||
onIPConfig?: (record: ListItem) => void;
|
||||
}
|
||||
|
||||
const actionList: Global.ActionItem<string>[] = [
|
||||
{
|
||||
label: 'common.button.edit',
|
||||
key: 'edit',
|
||||
icon: icons.EditOutlined
|
||||
},
|
||||
{
|
||||
label: 'common.button.delete',
|
||||
key: 'delete',
|
||||
icon: icons.DeleteOutlined,
|
||||
props: { danger: true }
|
||||
}
|
||||
];
|
||||
|
||||
const useModelsColumns = ({
|
||||
handleSelect,
|
||||
sortOrder,
|
||||
is_admin
|
||||
is_admin,
|
||||
onIPConfig
|
||||
}: ColumnsHookProps): ColumnsType<ListItem> => {
|
||||
const intl = useIntl();
|
||||
|
||||
const actionList = useMemo<APIKeyAction[]>(() => {
|
||||
const list: APIKeyAction[] = [
|
||||
{
|
||||
label: 'common.button.edit',
|
||||
key: 'edit',
|
||||
icon: icons.EditOutlined
|
||||
},
|
||||
{
|
||||
label: 'common.button.delete',
|
||||
key: 'delete',
|
||||
icon: icons.DeleteOutlined,
|
||||
props: { danger: true }
|
||||
}
|
||||
];
|
||||
|
||||
const ipConfigComponent = getGPUStackPlugin()?.APIKeyIPConfig?.form;
|
||||
if (ipConfigComponent && onIPConfig) {
|
||||
list.splice(1, 0, {
|
||||
label: 'apikeys.button.ipConfig',
|
||||
key: 'ipConfig',
|
||||
icon: <IconFont type="icon-safe-ip" />,
|
||||
onClick: (record: ListItem) => onIPConfig(record)
|
||||
});
|
||||
}
|
||||
|
||||
return list;
|
||||
}, [onIPConfig]);
|
||||
|
||||
return useMemo(() => {
|
||||
return [
|
||||
{
|
||||
@@ -172,13 +199,15 @@ const useModelsColumns = ({
|
||||
span: 3,
|
||||
render: (text, record) => (
|
||||
<DropdownButtons
|
||||
items={actionList}
|
||||
onSelect={(val) => handleSelect(val, record)}
|
||||
items={actionList as MenuProps['items']}
|
||||
onSelect={(val, item) =>
|
||||
handleSelect(val, record, item as APIKeyAction)
|
||||
}
|
||||
/>
|
||||
)
|
||||
}
|
||||
];
|
||||
}, [intl, is_admin, handleSelect]);
|
||||
}, [intl, is_admin, handleSelect, actionList]);
|
||||
};
|
||||
|
||||
export default useModelsColumns;
|
||||
|
||||
@@ -3,6 +3,7 @@ import { PaginationKey } from '@/config/settings';
|
||||
import type { PageActionType } from '@/config/types';
|
||||
import useTableFetch from '@/hooks/use-table-fetch';
|
||||
import useQueryUserList from '@/pages/users/services/use-query-user-list';
|
||||
import { getGPUStackPlugin } from '@/plugins';
|
||||
import { useModel } from '@@/plugin-model';
|
||||
import { DeleteModal, FilterBar, IconFont, NoResult } from '@gpustack/core-ui';
|
||||
import { useIntl } from '@umijs/max';
|
||||
@@ -53,6 +54,12 @@ const APIKeys: React.FC = () => {
|
||||
});
|
||||
|
||||
const intl = useIntl();
|
||||
|
||||
const apiKeyIPConfig = getGPUStackPlugin()?.APIKeyIPConfig;
|
||||
const APIKeyIPConfigForm = apiKeyIPConfig?.form;
|
||||
const { openIPConfigModalStatus, openIPConfigModal, closeIPConfigModal } =
|
||||
apiKeyIPConfig?.useCreateIPConfig?.() || {};
|
||||
|
||||
const [openAddModal, setOpenAddModal] = useState<{
|
||||
open: boolean;
|
||||
action: PageActionType;
|
||||
@@ -115,13 +122,23 @@ const APIKeys: React.FC = () => {
|
||||
});
|
||||
};
|
||||
|
||||
const onSelect = useMemoizedFn(async (val: string, record: ListItem) => {
|
||||
if (val === 'delete') {
|
||||
handleDelete(record);
|
||||
} else if (val === 'edit') {
|
||||
handleEditKey(record);
|
||||
const onSelect = useMemoizedFn(
|
||||
async (
|
||||
val: string,
|
||||
record: ListItem,
|
||||
item?: { onClick?: (r: ListItem) => void }
|
||||
) => {
|
||||
if (item?.onClick) {
|
||||
item.onClick(record);
|
||||
return;
|
||||
}
|
||||
if (val === 'delete') {
|
||||
handleDelete(record);
|
||||
} else if (val === 'edit') {
|
||||
handleEditKey(record);
|
||||
}
|
||||
}
|
||||
});
|
||||
);
|
||||
|
||||
const handleUserChange = (val: string) => {
|
||||
handleQueryChange({
|
||||
@@ -152,7 +169,8 @@ const APIKeys: React.FC = () => {
|
||||
const columns = useKeysColumns({
|
||||
handleSelect: onSelect,
|
||||
sortOrder,
|
||||
is_admin: currentUser?.is_admin
|
||||
is_admin: currentUser?.is_admin,
|
||||
onIPConfig: openIPConfigModal
|
||||
});
|
||||
|
||||
return (
|
||||
@@ -207,6 +225,13 @@ const APIKeys: React.FC = () => {
|
||||
onCancel={handleModalCancel}
|
||||
onOk={handleModalOk}
|
||||
></AddAPIKeyModal>
|
||||
{APIKeyIPConfigForm && (
|
||||
<APIKeyIPConfigForm
|
||||
open={openIPConfigModalStatus.open}
|
||||
apiKey={openIPConfigModalStatus.currentData}
|
||||
onClose={closeIPConfigModal}
|
||||
/>
|
||||
)}
|
||||
<DeleteModal ref={modalRef}></DeleteModal>
|
||||
</>
|
||||
);
|
||||
|
||||
@@ -22,7 +22,6 @@ ${formatCurlArgs(parameters, isFormdata)}`.trim();
|
||||
if (edit) {
|
||||
curlCode = `
|
||||
curl ${host}${api} \\
|
||||
-H "Content-Type: multipart/form-data" \\
|
||||
-H "Authorization: Bearer $\{YOUR_GPUSTACK_API_KEY}" \\${modelProxy ? `\n-H "X-GPUStack-Model: ${parameters.model}" \\` : ''}
|
||||
-F image="@image.png" \\
|
||||
-F mask="@mask.png" \\
|
||||
|
||||
@@ -2,6 +2,7 @@ import { PageAction, PasswordReg } from '@/config';
|
||||
import { PageActionType } from '@/config/types';
|
||||
import {
|
||||
Input as CInput,
|
||||
FormDrawer,
|
||||
IconFont,
|
||||
Select as SealSelect,
|
||||
Switch as SealSwitch
|
||||
@@ -9,7 +10,6 @@ import {
|
||||
import { useIntl, useModel } from '@umijs/max';
|
||||
import { Form, Select } from 'antd';
|
||||
import { useEffect } from 'react';
|
||||
import FormDrawer from '../../_components/form-drawer';
|
||||
import { UserRoles, UserRolesOptions } from '../config';
|
||||
import { FormData, ListItem } from '../config/types';
|
||||
|
||||
|
||||
@@ -124,7 +124,7 @@ export interface AppPlugin {
|
||||
/**
|
||||
* components extension
|
||||
*/
|
||||
components?: Record<string, ComponentType>;
|
||||
components?: Record<string, ComponentType<any>>;
|
||||
|
||||
/**
|
||||
* Hooks extension
|
||||
|
||||
Reference in New Issue
Block a user