diff --git a/packages/backend/src/modules/app-lifecycle/dto/app-lifecycle.dto.ts b/packages/backend/src/modules/app-lifecycle/dto/app-lifecycle.dto.ts index 2068081172..3621c16684 100644 --- a/packages/backend/src/modules/app-lifecycle/dto/app-lifecycle.dto.ts +++ b/packages/backend/src/modules/app-lifecycle/dto/app-lifecycle.dto.ts @@ -3,7 +3,7 @@ import { z } from 'zod'; export const appFormSchema = z .object({ - port: z.coerce.number().optional(), + port: z.coerce.number().min(1024).max(65535).optional(), exposed: z.boolean().optional(), exposedLocal: z.boolean().optional(), openPort: z.boolean().optional().default(true), @@ -13,16 +13,7 @@ export const appFormSchema = z .extend({}) .catchall(z.unknown()); -export class AppFormBody extends createZodDto( - z.object({ - port: z.string().optional(), - exposed: z.boolean().optional(), - exposedLocal: z.boolean().optional(), - openPort: z.boolean().optional(), - domain: z.string().optional(), - isVisibleOnGuestDashboard: z.boolean().optional(), - }), -) {} +export class AppFormBody extends createZodDto(appFormSchema) {} export class UninstallAppBody extends createZodDto(z.object({ removeBackups: z.boolean() })) {} diff --git a/packages/backend/src/swagger.json b/packages/backend/src/swagger.json index 1f5fc6501d..1780743622 100644 --- a/packages/backend/src/swagger.json +++ b/packages/backend/src/swagger.json @@ -2994,7 +2994,11 @@ "type": "object", "properties": { "port": { - "type": "string" + "type": "number", + "minimum": 1024, + "exclusiveMinimum": false, + "maximum": 65535, + "exclusiveMaximum": false }, "exposed": { "type": "boolean" @@ -3003,7 +3007,8 @@ "type": "boolean" }, "openPort": { - "type": "boolean" + "type": "boolean", + "default": true }, "domain": { "type": "string" diff --git a/packages/frontend/src/api-client/types.gen.ts b/packages/frontend/src/api-client/types.gen.ts index 7194694711..4af274c873 100644 --- a/packages/frontend/src/api-client/types.gen.ts +++ b/packages/frontend/src/api-client/types.gen.ts @@ -77,7 +77,7 @@ export type AppContextDto = { }; export type AppFormBody = { - port?: string; + port?: number; exposed?: boolean; exposedLocal?: boolean; openPort?: boolean; diff --git a/packages/frontend/src/modules/app/components/dialogs/install-dialog/install-dialog.tsx b/packages/frontend/src/modules/app/components/dialogs/install-dialog/install-dialog.tsx index 2209d0b203..a8394767d0 100644 --- a/packages/frontend/src/modules/app/components/dialogs/install-dialog/install-dialog.tsx +++ b/packages/frontend/src/modules/app/components/dialogs/install-dialog/install-dialog.tsx @@ -10,7 +10,7 @@ import { useId } from 'react'; import toast from 'react-hot-toast'; import { useTranslation } from 'react-i18next'; import { InstallFormButtons } from '../../install-form-buttons/install-form-buttons'; -import { InstallForm } from '../../install-form/install-form'; +import { type FormValues, InstallForm } from '../../install-form/install-form'; interface IProps { info: AppInfo; @@ -34,6 +34,13 @@ export const InstallDialog: React.FC = ({ info, isOpen, onClose }) => { }, }); + const normalizeFormValues = (values: FormValues) => { + return { + ...values, + port: values.port ? Number(values.port) : undefined, + }; + }; + return ( @@ -43,7 +50,7 @@ export const InstallDialog: React.FC = ({ info, isOpen, onClose }) => { installMutation.mutate({ path: { urn: info.urn }, body: data })} + onSubmit={(data) => installMutation.mutate({ path: { urn: info.urn }, body: normalizeFormValues(data) })} formFields={info.form_fields} info={info} formId={formId} diff --git a/packages/frontend/src/modules/app/components/dialogs/update-settings-dialog/update-settings-dialog.tsx b/packages/frontend/src/modules/app/components/dialogs/update-settings-dialog/update-settings-dialog.tsx index 7f23371ea9..c30987f5fb 100644 --- a/packages/frontend/src/modules/app/components/dialogs/update-settings-dialog/update-settings-dialog.tsx +++ b/packages/frontend/src/modules/app/components/dialogs/update-settings-dialog/update-settings-dialog.tsx @@ -37,6 +37,13 @@ export const UpdateSettingsDialog: React.FC = ({ info, config, isOpen, o }, }); + const normalizeFormValues = (values: FormValues) => { + return { + ...values, + port: values.port ? Number(values.port) : undefined, + }; + }; + return ( @@ -46,7 +53,7 @@ export const UpdateSettingsDialog: React.FC = ({ info, config, isOpen, o updateConfig.mutate({ path: { urn: info.urn }, body: values })} + onSubmit={(values: FormValues) => updateConfig.mutate({ path: { urn: info.urn }, body: normalizeFormValues(values) })} formFields={info.form_fields} info={info} initialValues={{ ...config }}