fix: custom apikey
This commit is contained in:
@@ -19,7 +19,9 @@ export default {
|
|||||||
'apikeys.models.selected': 'Allowed models',
|
'apikeys.models.selected': 'Allowed models',
|
||||||
'apikeys.models.noModelsFound': 'No models found',
|
'apikeys.models.noModelsFound': 'No models found',
|
||||||
'apikeys.accessScope.all': 'All',
|
'apikeys.accessScope.all': 'All',
|
||||||
'apikeys.accessScope.management': 'Management APIs',
|
'apikeys.accessScope.management': 'Platform Management',
|
||||||
'apikeys.accessScope.inference': 'Inference APIs',
|
'apikeys.accessScope.inference': 'Inference APIs',
|
||||||
'apikeys.access.permissions': 'Access Permissions'
|
'apikeys.access.permissions': 'Access Permissions',
|
||||||
|
'apikeys.type.auto': 'Auto-generated',
|
||||||
|
'apikeys.type.custom': 'Custom'
|
||||||
};
|
};
|
||||||
|
|||||||
@@ -19,9 +19,11 @@ export default {
|
|||||||
'apikeys.models.selected': 'Allowed models',
|
'apikeys.models.selected': 'Allowed models',
|
||||||
'apikeys.models.noModelsFound': 'No models found',
|
'apikeys.models.noModelsFound': 'No models found',
|
||||||
'apikeys.accessScope.all': 'All',
|
'apikeys.accessScope.all': 'All',
|
||||||
'apikeys.accessScope.management': 'Management APIs',
|
'apikeys.accessScope.management': 'Platform Management',
|
||||||
'apikeys.accessScope.inference': 'Inference APIs',
|
'apikeys.accessScope.inference': 'Inference APIs',
|
||||||
'apikeys.access.permissions': 'Access Permissions'
|
'apikeys.access.permissions': 'Access Permissions',
|
||||||
|
'apikeys.type.auto': 'Auto-generated',
|
||||||
|
'apikeys.type.custom': 'Custom'
|
||||||
};
|
};
|
||||||
|
|
||||||
// ========== To-Do: Translate Keys (Remove After Translation) ==========
|
// ========== To-Do: Translate Keys (Remove After Translation) ==========
|
||||||
|
|||||||
@@ -19,9 +19,11 @@ export default {
|
|||||||
'apikeys.models.selected': 'Разрешенные модели',
|
'apikeys.models.selected': 'Разрешенные модели',
|
||||||
'apikeys.models.noModelsFound': 'Модели не найдены',
|
'apikeys.models.noModelsFound': 'Модели не найдены',
|
||||||
'apikeys.accessScope.all': 'All',
|
'apikeys.accessScope.all': 'All',
|
||||||
'apikeys.accessScope.management': 'Management APIs',
|
'apikeys.accessScope.management': 'Platform Management',
|
||||||
'apikeys.accessScope.inference': 'Inference APIs',
|
'apikeys.accessScope.inference': 'Inference APIs',
|
||||||
'apikeys.access.permissions': 'Access Permissions'
|
'apikeys.access.permissions': 'Access Permissions',
|
||||||
|
'apikeys.type.auto': 'Auto-generated',
|
||||||
|
'apikeys.type.custom': 'Custom'
|
||||||
};
|
};
|
||||||
|
|
||||||
// ========== To-Do: Translate Keys (Remove After Translation) ==========
|
// ========== To-Do: Translate Keys (Remove After Translation) ==========
|
||||||
|
|||||||
@@ -19,7 +19,9 @@ export default {
|
|||||||
'apikeys.models.selected': 'İzin verilen modeller',
|
'apikeys.models.selected': 'İzin verilen modeller',
|
||||||
'apikeys.models.noModelsFound': 'Model bulunamadı',
|
'apikeys.models.noModelsFound': 'Model bulunamadı',
|
||||||
'apikeys.accessScope.all': 'All',
|
'apikeys.accessScope.all': 'All',
|
||||||
'apikeys.accessScope.management': 'Management APIs',
|
'apikeys.accessScope.management': 'Platform Management',
|
||||||
'apikeys.accessScope.inference': 'Inference APIs',
|
'apikeys.accessScope.inference': 'Inference APIs',
|
||||||
'apikeys.access.permissions': 'Access Permissions'
|
'apikeys.access.permissions': 'Access Permissions',
|
||||||
|
'apikeys.type.auto': 'Auto-generated',
|
||||||
|
'apikeys.type.custom': 'Custom'
|
||||||
};
|
};
|
||||||
|
|||||||
@@ -18,7 +18,9 @@ export default {
|
|||||||
'apikeys.models.selected': '指定模型',
|
'apikeys.models.selected': '指定模型',
|
||||||
'apikeys.models.noModelsFound': '未找到模型',
|
'apikeys.models.noModelsFound': '未找到模型',
|
||||||
'apikeys.accessScope.all': '全部',
|
'apikeys.accessScope.all': '全部',
|
||||||
'apikeys.accessScope.management': '管理接口',
|
'apikeys.accessScope.management': '平台管理',
|
||||||
'apikeys.accessScope.inference': '推理接口',
|
'apikeys.accessScope.inference': '推理接口',
|
||||||
'apikeys.access.permissions': '访问权限'
|
'apikeys.access.permissions': '访问权限',
|
||||||
|
'apikeys.type.auto': '自动生成',
|
||||||
|
'apikeys.type.custom': '自定义'
|
||||||
};
|
};
|
||||||
|
|||||||
@@ -32,13 +32,12 @@ const AllowModelsForm: React.FC<{
|
|||||||
const [modelList, setModelList] = useState<{ key: string; title: string }[]>(
|
const [modelList, setModelList] = useState<{ key: string; title: string }[]>(
|
||||||
[]
|
[]
|
||||||
);
|
);
|
||||||
const [queryParams, setQueryParams] = useState<Global.SearchParams>({
|
|
||||||
page: -1
|
|
||||||
});
|
|
||||||
|
|
||||||
const getModelList = async () => {
|
const getModelList = async () => {
|
||||||
try {
|
try {
|
||||||
const res = await queryMyModels(queryParams);
|
const res = await queryMyModels({
|
||||||
|
page: -1
|
||||||
|
});
|
||||||
const options = res.items.map((item) => item.name);
|
const options = res.items.map((item) => item.name);
|
||||||
if (action === PageAction.EDIT && currentData) {
|
if (action === PageAction.EDIT && currentData) {
|
||||||
const list = new Set([
|
const list = new Set([
|
||||||
@@ -57,6 +56,11 @@ const AllowModelsForm: React.FC<{
|
|||||||
const handleAllowTypeChange = (e: any) => {
|
const handleAllowTypeChange = (e: any) => {
|
||||||
const value = e.target.value;
|
const value = e.target.value;
|
||||||
onValuesChange?.({ allowed_type: value }, form.getFieldsValue());
|
onValuesChange?.({ allowed_type: value }, form.getFieldsValue());
|
||||||
|
if (value === 'management') {
|
||||||
|
form.setFieldsValue({ scope: ['management'] });
|
||||||
|
} else {
|
||||||
|
form.setFieldsValue({ scope: ['inference'] });
|
||||||
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
useEffect(() => {
|
useEffect(() => {
|
||||||
@@ -66,7 +70,7 @@ const AllowModelsForm: React.FC<{
|
|||||||
return (
|
return (
|
||||||
<div>
|
<div>
|
||||||
<Divider></Divider>
|
<Divider></Divider>
|
||||||
<Label>{intl.formatMessage({ id: 'apikeys.table.bindModels' })}</Label>
|
<Label>{intl.formatMessage({ id: 'apikeys.access.permissions' })}</Label>
|
||||||
<Form.Item
|
<Form.Item
|
||||||
name="allowed_type"
|
name="allowed_type"
|
||||||
initialValue="all"
|
initialValue="all"
|
||||||
@@ -75,6 +79,12 @@ const AllowModelsForm: React.FC<{
|
|||||||
<Radio.Group
|
<Radio.Group
|
||||||
onChange={handleAllowTypeChange}
|
onChange={handleAllowTypeChange}
|
||||||
options={[
|
options={[
|
||||||
|
{
|
||||||
|
label: intl.formatMessage({
|
||||||
|
id: 'apikeys.accessScope.management'
|
||||||
|
}),
|
||||||
|
value: 'management'
|
||||||
|
},
|
||||||
{
|
{
|
||||||
label: intl.formatMessage({ id: 'apikeys.models.all' }),
|
label: intl.formatMessage({ id: 'apikeys.models.all' }),
|
||||||
value: 'all'
|
value: 'all'
|
||||||
@@ -88,7 +98,7 @@ const AllowModelsForm: React.FC<{
|
|||||||
</Form.Item>
|
</Form.Item>
|
||||||
<Form.Item
|
<Form.Item
|
||||||
name="allowed_model_names"
|
name="allowed_model_names"
|
||||||
hidden={allowedType === 'all'}
|
hidden={allowedType === 'all' || allowedType === 'management'}
|
||||||
rules={[
|
rules={[
|
||||||
{
|
{
|
||||||
required: allowedType === 'custom',
|
required: allowedType === 'custom',
|
||||||
|
|||||||
@@ -16,17 +16,7 @@ const APIKeyForm: React.FC<{
|
|||||||
onValuesChange?: (changedValues: any, allValues: any) => void;
|
onValuesChange?: (changedValues: any, allValues: any) => void;
|
||||||
}> = ({ action, currentData, onValuesChange }) => {
|
}> = ({ action, currentData, onValuesChange }) => {
|
||||||
const intl = useIntl();
|
const intl = useIntl();
|
||||||
|
const keyType = Form.useWatch('key_type') as FormData['key_type'];
|
||||||
const optionRender = (option: any) => {
|
|
||||||
return (
|
|
||||||
<span className="flex-center gap-4">
|
|
||||||
{option.label}
|
|
||||||
{option.data.description && (
|
|
||||||
<span className="text-tertiary">[{option.data.description}]</span>
|
|
||||||
)}
|
|
||||||
</span>
|
|
||||||
);
|
|
||||||
};
|
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<>
|
<>
|
||||||
@@ -51,28 +41,7 @@ const APIKeyForm: React.FC<{
|
|||||||
required
|
required
|
||||||
></SealInput.Input>
|
></SealInput.Input>
|
||||||
</Form.Item>
|
</Form.Item>
|
||||||
{action === PageAction.CREATE && (
|
|
||||||
<Form.Item<FormData> name="custom">
|
|
||||||
<Password
|
|
||||||
trim
|
|
||||||
autoComplete="new-password"
|
|
||||||
label={intl.formatMessage({ id: 'playground.params.custom' })}
|
|
||||||
></Password>
|
|
||||||
</Form.Item>
|
|
||||||
)}
|
|
||||||
<Form.Item<FormData>
|
|
||||||
name="scope"
|
|
||||||
normalize={(value) => (value ? [value] : [])}
|
|
||||||
getValueProps={(value) => ({
|
|
||||||
value: Array.isArray(value) ? value[0] : value
|
|
||||||
})}
|
|
||||||
>
|
|
||||||
<SealSelect
|
|
||||||
optionRender={optionRender}
|
|
||||||
options={accessScopeOptions}
|
|
||||||
label={intl.formatMessage({ id: 'models.table.accessScope' })}
|
|
||||||
></SealSelect>
|
|
||||||
</Form.Item>
|
|
||||||
<Form.Item<FormData>
|
<Form.Item<FormData>
|
||||||
name="expires_in"
|
name="expires_in"
|
||||||
rules={[
|
rules={[
|
||||||
@@ -102,6 +71,63 @@ const APIKeyForm: React.FC<{
|
|||||||
label={intl.formatMessage({ id: 'common.table.description' })}
|
label={intl.formatMessage({ id: 'common.table.description' })}
|
||||||
></SealInput.TextArea>
|
></SealInput.TextArea>
|
||||||
</Form.Item>
|
</Form.Item>
|
||||||
|
{action === PageAction.CREATE && (
|
||||||
|
<>
|
||||||
|
<Form.Item<FormData> name="key_type" initialValue="auto">
|
||||||
|
<SealSelect
|
||||||
|
options={[
|
||||||
|
{
|
||||||
|
label: intl.formatMessage({ id: 'apikeys.type.auto' }),
|
||||||
|
value: 'auto'
|
||||||
|
},
|
||||||
|
{
|
||||||
|
label: intl.formatMessage({ id: 'apikeys.type.custom' }),
|
||||||
|
value: 'custom'
|
||||||
|
}
|
||||||
|
]}
|
||||||
|
label={intl.formatMessage({ id: 'common.table.type' })}
|
||||||
|
></SealSelect>
|
||||||
|
</Form.Item>
|
||||||
|
{keyType === 'custom' && (
|
||||||
|
<Form.Item<FormData>
|
||||||
|
name="custom"
|
||||||
|
rules={[
|
||||||
|
{
|
||||||
|
required: true,
|
||||||
|
message: intl.formatMessage(
|
||||||
|
{ id: 'common.form.rule.input' },
|
||||||
|
{
|
||||||
|
name: intl.formatMessage({
|
||||||
|
id: 'apikeys.table.key'
|
||||||
|
})
|
||||||
|
}
|
||||||
|
)
|
||||||
|
}
|
||||||
|
]}
|
||||||
|
>
|
||||||
|
<Password
|
||||||
|
trim
|
||||||
|
required
|
||||||
|
autoComplete="new-password"
|
||||||
|
label={intl.formatMessage({ id: 'apikeys.table.key' })}
|
||||||
|
></Password>
|
||||||
|
</Form.Item>
|
||||||
|
)}
|
||||||
|
</>
|
||||||
|
)}
|
||||||
|
<Form.Item<FormData>
|
||||||
|
name="scope"
|
||||||
|
hidden
|
||||||
|
normalize={(value) => (value ? [value] : [])}
|
||||||
|
getValueProps={(value) => ({
|
||||||
|
value: Array.isArray(value) ? value[0] : value
|
||||||
|
})}
|
||||||
|
>
|
||||||
|
<SealSelect
|
||||||
|
options={accessScopeOptions}
|
||||||
|
label={intl.formatMessage({ id: 'models.table.accessScope' })}
|
||||||
|
></SealSelect>
|
||||||
|
</Form.Item>
|
||||||
<AllowModelsForm
|
<AllowModelsForm
|
||||||
currentData={currentData}
|
currentData={currentData}
|
||||||
action={action}
|
action={action}
|
||||||
|
|||||||
@@ -113,12 +113,12 @@ const AddModal: React.FC<AddModalProps> = ({
|
|||||||
|
|
||||||
const handleOnOk = async (formdata: FormData) => {
|
const handleOnOk = async (formdata: FormData) => {
|
||||||
try {
|
try {
|
||||||
console.log('formdata=========', formdata);
|
|
||||||
setLoading(true);
|
setLoading(true);
|
||||||
const data = {
|
const data = {
|
||||||
..._.omit(formdata, ['allowed_type']),
|
..._.omit(formdata, ['allowed_type']),
|
||||||
allowed_model_names:
|
allowed_model_names:
|
||||||
formdata.allowed_type === 'all'
|
formdata.allowed_type === 'all' ||
|
||||||
|
formdata.allowed_type === 'management'
|
||||||
? []
|
? []
|
||||||
: formdata.allowed_model_names || []
|
: formdata.allowed_model_names || []
|
||||||
};
|
};
|
||||||
@@ -183,9 +183,12 @@ const AddModal: React.FC<AddModalProps> = ({
|
|||||||
form.setFieldsValue({
|
form.setFieldsValue({
|
||||||
name: currentData.name,
|
name: currentData.name,
|
||||||
description: currentData.description,
|
description: currentData.description,
|
||||||
|
scope: currentData.scope,
|
||||||
allowed_type: currentData.allowed_model_names?.length
|
allowed_type: currentData.allowed_model_names?.length
|
||||||
? 'custom'
|
? 'custom'
|
||||||
: 'all',
|
: currentData.scope?.includes('management')
|
||||||
|
? 'management'
|
||||||
|
: 'all',
|
||||||
expires_in: parseExpireValue(currentData as ListItem),
|
expires_in: parseExpireValue(currentData as ListItem),
|
||||||
allowed_model_names: currentData.allowed_model_names || []
|
allowed_model_names: currentData.allowed_model_names || []
|
||||||
});
|
});
|
||||||
@@ -269,7 +272,7 @@ const AddModal: React.FC<AddModalProps> = ({
|
|||||||
onFinish={handleOnOk}
|
onFinish={handleOnOk}
|
||||||
preserve={false}
|
preserve={false}
|
||||||
initialValues={{
|
initialValues={{
|
||||||
scope: ['*']
|
scope: ['inference']
|
||||||
}}
|
}}
|
||||||
>
|
>
|
||||||
{!showKey && (
|
{!showKey && (
|
||||||
|
|||||||
@@ -27,18 +27,13 @@ export const expirationOptions = [
|
|||||||
|
|
||||||
export const accessScopeOptions = [
|
export const accessScopeOptions = [
|
||||||
{
|
{
|
||||||
label: 'apikeys.accessScope.all',
|
label: 'management',
|
||||||
value: '*',
|
|
||||||
locale: true
|
|
||||||
},
|
|
||||||
{
|
|
||||||
label: 'apikeys.accessScope.management',
|
|
||||||
value: 'management',
|
value: 'management',
|
||||||
description: 'v2/',
|
description: 'v2/',
|
||||||
locale: true
|
locale: true
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
label: 'apikeys.accessScope.inference',
|
label: 'inference',
|
||||||
value: 'inference',
|
value: 'inference',
|
||||||
description: 'v1/',
|
description: 'v1/',
|
||||||
locale: true
|
locale: true
|
||||||
|
|||||||
@@ -13,7 +13,8 @@ export interface ListItem {
|
|||||||
|
|
||||||
export interface FormData {
|
export interface FormData {
|
||||||
name: string;
|
name: string;
|
||||||
allowed_type: 'all' | 'custom';
|
allowed_type: 'all' | 'custom' | 'management';
|
||||||
|
key_type: 'auto' | 'custom';
|
||||||
description: string;
|
description: string;
|
||||||
allowed_model_names: string[];
|
allowed_model_names: string[];
|
||||||
expires_in: number | null;
|
expires_in: number | null;
|
||||||
|
|||||||
@@ -110,27 +110,13 @@ const useModelsColumns = ({
|
|||||||
showTitle: false
|
showTitle: false
|
||||||
},
|
},
|
||||||
render: (text: string[], record: ListItem) => (
|
render: (text: string[], record: ListItem) => (
|
||||||
<div
|
<AutoTooltip ghost>
|
||||||
style={{
|
{record.scope?.[0] === 'management'
|
||||||
display: 'grid',
|
? intl.formatMessage({ id: 'apikeys.accessScope.management' })
|
||||||
gridTemplateColumns: 'max-content 1fr',
|
: record.allowed_model_names?.length
|
||||||
gap: 8,
|
? record.allowed_model_names.join(', ')
|
||||||
alignItems: 'center'
|
: intl.formatMessage({ id: 'apikeys.models.all' })}
|
||||||
}}
|
</AutoTooltip>
|
||||||
>
|
|
||||||
<span className="text-primary">APIs:</span>
|
|
||||||
<AutoTooltip ghost>{renderAPIs(record)}</AutoTooltip>
|
|
||||||
<span className="text-primary">
|
|
||||||
{intl.formatMessage({ id: 'models.title' })}:
|
|
||||||
</span>
|
|
||||||
<AutoTooltip ghost>
|
|
||||||
<span>
|
|
||||||
{text?.length
|
|
||||||
? text?.join(', ')
|
|
||||||
: intl.formatMessage({ id: 'common.select.option' })}
|
|
||||||
</span>
|
|
||||||
</AutoTooltip>
|
|
||||||
</div>
|
|
||||||
)
|
)
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
|
|||||||
Reference in New Issue
Block a user