Skip to content

Commit 8a10ded

Browse files
authored
fix(web): handle unlimited API key quota validation (#4881)
1 parent 554defe commit 8a10ded

9 files changed

Lines changed: 59 additions & 18 deletions

File tree

web/default/src/features/keys/components/api-keys-mutate-drawer.tsx

Lines changed: 9 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -17,7 +17,7 @@ along with this program. If not, see <https://www.gnu.org/licenses/>.
1717
For commercial licensing, please contact support@quantumnous.com
1818
*/
1919
import { useEffect, useState, type ReactNode } from 'react'
20-
import { useForm } from 'react-hook-form'
20+
import { useForm, type SubmitErrorHandler } from 'react-hook-form'
2121
import { zodResolver } from '@hookform/resolvers/zod'
2222
import { useQuery } from '@tanstack/react-query'
2323
import {
@@ -65,7 +65,7 @@ import { MultiSelect } from '@/components/multi-select'
6565
import { createApiKey, updateApiKey, getApiKey } from '../api'
6666
import { ERROR_MESSAGES, SUCCESS_MESSAGES } from '../constants'
6767
import {
68-
apiKeyFormSchema,
68+
getApiKeyFormSchema,
6969
type ApiKeyFormValues,
7070
getApiKeyFormDefaultValues,
7171
transformFormDataToPayload,
@@ -152,9 +152,10 @@ export function ApiKeysMutateDrawer({
152152
})
153153
)
154154
const backendHasAuto = groups.some((g) => g.value === 'auto')
155+
const schema = getApiKeyFormSchema(t)
155156

156157
const form = useForm<ApiKeyFormValues>({
157-
resolver: zodResolver(apiKeyFormSchema),
158+
resolver: zodResolver(schema),
158159
defaultValues: getApiKeyFormDefaultValues(defaultUseAutoGroup),
159160
})
160161

@@ -239,6 +240,10 @@ export function ApiKeysMutateDrawer({
239240
}
240241
}
241242

243+
const onInvalid: SubmitErrorHandler<ApiKeyFormValues> = () => {
244+
toast.error(t('Please fix the highlighted fields before saving'))
245+
}
246+
242247
const handleSetExpiry = (months: number, days: number, hours: number) => {
243248
if (months === 0 && days === 0 && hours === 0) {
244249
form.setValue('expired_time', undefined)
@@ -291,7 +296,7 @@ export function ApiKeysMutateDrawer({
291296
<Form {...form}>
292297
<form
293298
id='api-key-form'
294-
onSubmit={form.handleSubmit(onSubmit)}
299+
onSubmit={form.handleSubmit(onSubmit, onInvalid)}
295300
className='min-h-0 flex-1 space-y-3 overflow-y-auto overscroll-contain px-3 py-3 sm:space-y-4 sm:px-4 sm:py-4'
296301
>
297302
<ApiKeyFormSection

web/default/src/features/keys/lib/api-key-form.ts

Lines changed: 37 additions & 13 deletions
Original file line numberDiff line numberDiff line change
@@ -17,6 +17,7 @@ along with this program. If not, see <https://www.gnu.org/licenses/>.
1717
For commercial licensing, please contact support@quantumnous.com
1818
*/
1919
import { z } from 'zod'
20+
import type { TFunction } from 'i18next'
2021
import { parseQuotaFromDollars, quotaUnitsToDollars } from '@/lib/format'
2122
import { DEFAULT_GROUP } from '../constants'
2223
import { type ApiKeyFormData, type ApiKey } from '../types'
@@ -25,19 +26,40 @@ import { type ApiKeyFormData, type ApiKey } from '../types'
2526
// Form Schema
2627
// ============================================================================
2728

28-
export const apiKeyFormSchema = z.object({
29-
name: z.string().min(1, 'Name is required'),
30-
remain_quota_dollars: z.number().min(0).optional(),
31-
expired_time: z.date().optional(),
32-
unlimited_quota: z.boolean(),
33-
model_limits: z.array(z.string()),
34-
allow_ips: z.string().optional(),
35-
group: z.string().optional(),
36-
cross_group_retry: z.boolean().optional(),
37-
tokenCount: z.number().min(1).optional(),
38-
})
29+
export function getApiKeyFormSchema(t: TFunction) {
30+
return z
31+
.object({
32+
name: z.string().min(1, t('Please enter a name')),
33+
remain_quota_dollars: z.number().optional(),
34+
expired_time: z.date().optional(),
35+
unlimited_quota: z.boolean(),
36+
model_limits: z.array(z.string()),
37+
allow_ips: z.string().optional(),
38+
group: z.string().optional(),
39+
cross_group_retry: z.boolean().optional(),
40+
tokenCount: z.number().min(1).optional(),
41+
})
42+
.superRefine((data, ctx) => {
43+
if (data.unlimited_quota) {
44+
return
45+
}
3946

40-
export type ApiKeyFormValues = z.infer<typeof apiKeyFormSchema>
47+
if (
48+
data.remain_quota_dollars === undefined ||
49+
data.remain_quota_dollars < 0
50+
) {
51+
ctx.addIssue({
52+
code: 'custom',
53+
path: ['remain_quota_dollars'],
54+
message: t('Quota must be zero or greater'),
55+
})
56+
}
57+
})
58+
}
59+
60+
export type ApiKeyFormValues = z.infer<
61+
ReturnType<typeof getApiKeyFormSchema>
62+
>
4163

4264
// ============================================================================
4365
// Form Defaults
@@ -100,7 +122,9 @@ export function transformApiKeyToFormDefaults(
100122
): ApiKeyFormValues {
101123
return {
102124
name: apiKey.name,
103-
remain_quota_dollars: quotaUnitsToDollars(apiKey.remain_quota),
125+
remain_quota_dollars: apiKey.unlimited_quota
126+
? 0
127+
: quotaUnitsToDollars(apiKey.remain_quota),
104128
expired_time:
105129
apiKey.expired_time > 0
106130
? new Date(apiKey.expired_time * 1000)

web/default/src/features/keys/lib/index.ts

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -20,7 +20,7 @@ For commercial licensing, please contact support@quantumnous.com
2020
// Form Utilities
2121
// ============================================================================
2222
export {
23-
apiKeyFormSchema,
23+
getApiKeyFormSchema,
2424
type ApiKeyFormValues,
2525
API_KEY_FORM_DEFAULT_VALUES,
2626
getApiKeyFormDefaultValues,

web/default/src/i18n/locales/en.json

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -2921,6 +2921,7 @@
29212921
"Please enter your verification code": "Please enter your verification code",
29222922
"Please enter your verification code or backup code": "Please enter your verification code or backup code",
29232923
"Please fix JSON errors before saving": "Please fix JSON errors before saving",
2924+
"Please fix the highlighted fields before saving": "Please fix the highlighted fields before saving",
29242925
"Please log in with the appropriate credentials": "Please log in with the appropriate credentials",
29252926
"Please manually copy and open the authorization link": "Please manually copy and open the authorization link",
29262927
"Please select a container": "Please select a container",
@@ -3097,6 +3098,7 @@
30973098
"Quota given to invited users": "Quota given to invited users",
30983099
"Quota given to users who invite others": "Quota given to users who invite others",
30993100
"Quota must be a positive number": "Quota must be a positive number",
3101+
"Quota must be zero or greater": "Quota must be zero or greater",
31003102
"Quota Per Unit": "Quota Per Unit",
31013103
"Quota reminder (tokens)": "Quota reminder (tokens)",
31023104
"Quota Reset": "Quota Reset",

web/default/src/i18n/locales/fr.json

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -2921,6 +2921,7 @@
29212921
"Please enter your verification code": "Veuillez saisir votre code de vérification",
29222922
"Please enter your verification code or backup code": "Veuillez saisir votre code de vérification ou votre code de secours",
29232923
"Please fix JSON errors before saving": "Veuillez corriger les erreurs JSON avant d’enregistrer",
2924+
"Please fix the highlighted fields before saving": "Veuillez corriger les champs en surbrillance avant d’enregistrer",
29242925
"Please log in with the appropriate credentials": "Veuillez vous connecter avec les identifiants appropriés",
29252926
"Please manually copy and open the authorization link": "Veuillez copier et ouvrir manuellement le lien d'autorisation",
29262927
"Please select a container": "Veuillez sélectionner un conteneur",
@@ -3097,6 +3098,7 @@
30973098
"Quota given to invited users": "Quota attribué aux utilisateurs invités",
30983099
"Quota given to users who invite others": "Quota attribué aux utilisateurs qui invitent d'autres personnes",
30993100
"Quota must be a positive number": "Le quota doit être un nombre positif",
3101+
"Quota must be zero or greater": "Le quota ne peut pas être négatif",
31003102
"Quota Per Unit": "Quota par unité",
31013103
"Quota reminder (tokens)": "Rappel de quota (jetons)",
31023104
"Quota Reset": "Réinitialisation du quota",

web/default/src/i18n/locales/ja.json

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -2921,6 +2921,7 @@
29212921
"Please enter your verification code": "認証コードを入力してください",
29222922
"Please enter your verification code or backup code": "認証コードまたはバックアップコードを入力してください",
29232923
"Please fix JSON errors before saving": "保存する前に JSON エラーを直してください",
2924+
"Please fix the highlighted fields before saving": "保存する前に強調表示された項目を修正してください",
29242925
"Please log in with the appropriate credentials": "適切な認証情報でログインしてください",
29252926
"Please manually copy and open the authorization link": "認証リンクを手動でコピーして開いてください",
29262927
"Please select a container": "コンテナを選択してください",
@@ -3097,6 +3098,7 @@
30973098
"Quota given to invited users": "招待されたユーザーに付与されるクォータ",
30983099
"Quota given to users who invite others": "他のユーザーを招待したユーザーに付与されるクォータ",
30993100
"Quota must be a positive number": "クォータは正の数である必要があります",
3101+
"Quota must be zero or greater": "クォータは負の値にできません",
31003102
"Quota Per Unit": "ユニットあたりのクォータ",
31013103
"Quota reminder (tokens)": "クォータリマインダー (トークン)",
31023104
"Quota Reset": "クォータリセット",

web/default/src/i18n/locales/ru.json

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -2921,6 +2921,7 @@
29212921
"Please enter your verification code": "Пожалуйста, введите код подтверждения",
29222922
"Please enter your verification code or backup code": "Пожалуйста, введите код подтверждения или резервный код",
29232923
"Please fix JSON errors before saving": "Исправьте ошибки JSON перед сохранением",
2924+
"Please fix the highlighted fields before saving": "Исправьте выделенные поля перед сохранением",
29242925
"Please log in with the appropriate credentials": "Пожалуйста, войдите с соответствующими учетными данными",
29252926
"Please manually copy and open the authorization link": "Скопируйте и откройте ссылку авторизации вручную",
29262927
"Please select a container": "Пожалуйста, выберите контейнер",
@@ -3097,6 +3098,7 @@
30973098
"Quota given to invited users": "Квота, предоставляемая приглашенным пользователям",
30983099
"Quota given to users who invite others": "Квота, предоставляемая пользователям, которые приглашают других",
30993100
"Quota must be a positive number": "Квота должна быть положительным числом",
3101+
"Quota must be zero or greater": "Квота не может быть отрицательной",
31003102
"Quota Per Unit": "Квота на единицу",
31013103
"Quota reminder (tokens)": "Напоминание о квоте (токены)",
31023104
"Quota Reset": "Сброс квоты",

web/default/src/i18n/locales/vi.json

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -2921,6 +2921,7 @@
29212921
"Please enter your verification code": "Vui lòng nhập mã xác thực của bạn",
29222922
"Please enter your verification code or backup code": "Vui lòng nhập mã xác thực hoặc mã dự phòng của bạn",
29232923
"Please fix JSON errors before saving": "Vui lòng sửa lỗi JSON trước khi lưu",
2924+
"Please fix the highlighted fields before saving": "Vui lòng sửa các trường được đánh dấu trước khi lưu",
29242925
"Please log in with the appropriate credentials": "Vui lòng đăng nhập bằng thông tin xác thực phù hợp",
29252926
"Please manually copy and open the authorization link": "Vui lòng tự sao chép và mở liên kết ủy quyền",
29262927
"Please select a container": "Vui lòng chọn một container",
@@ -3097,6 +3098,7 @@
30973098
"Quota given to invited users": "Hạn mức được cấp cho người dùng được mời",
30983099
"Quota given to users who invite others": "Limit for users inviting others",
30993100
"Quota must be a positive number": "Hạn mức phải là một số dương",
3101+
"Quota must be zero or greater": "Hạn mức không được âm",
31003102
"Quota Per Unit": "Định mức mỗi đơn vị",
31013103
"Quota reminder (tokens)": "Nhắc nhở hạn mức (token)",
31023104
"Quota Reset": "Đặt lại hạn mức",

web/default/src/i18n/locales/zh.json

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -2921,6 +2921,7 @@
29212921
"Please enter your verification code": "请输入您的验证码",
29222922
"Please enter your verification code or backup code": "请输入您的验证码或备用码",
29232923
"Please fix JSON errors before saving": "请先修复 JSON 错误再保存",
2924+
"Please fix the highlighted fields before saving": "请先修复高亮字段后再保存",
29242925
"Please log in with the appropriate credentials": "请使用适当的凭据登录",
29252926
"Please manually copy and open the authorization link": "请手动复制并打开授权链接",
29262927
"Please select a container": "请选择一个容器",
@@ -3097,6 +3098,7 @@
30973098
"Quota given to invited users": "授予被邀请用户的配额",
30983099
"Quota given to users who invite others": "授予邀请其他用户的配额",
30993100
"Quota must be a positive number": "配额必须是正数",
3101+
"Quota must be zero or greater": "额度不能为负数",
31003102
"Quota Per Unit": "每单位配额",
31013103
"Quota reminder (tokens)": "配额提醒(token)",
31023104
"Quota Reset": "额度重置",

0 commit comments

Comments
 (0)