From c1c6088c5d30feeb31277654963150ffcce87d2f Mon Sep 17 00:00:00 2001
From: Bernd Storath <999999bst@gmail.com>
Date: Tue, 7 Jan 2025 16:11:51 +0100
Subject: [PATCH] handle form submit using js
avoid weird behavior with FormData
---
src/app/components/form/ActionField.vue | 4 ---
src/app/components/form/Element.vue | 6 +---
src/app/pages/clients/[id].vue | 8 +++--
src/i18n/locales/en.json | 2 ++
src/package.json | 3 +-
src/pnpm-lock.yaml | 12 -------
.../api/client/[clientId]/index.post.ts | 2 +-
src/server/utils/apiHelper.ts | 31 -------------------
src/server/utils/types.ts | 29 +++++++----------
9 files changed, 22 insertions(+), 75 deletions(-)
delete mode 100644 src/server/utils/apiHelper.ts
diff --git a/src/app/components/form/ActionField.vue b/src/app/components/form/ActionField.vue
index af03e176..46cefd80 100644
--- a/src/app/components/form/ActionField.vue
+++ b/src/app/components/form/ActionField.vue
@@ -2,8 +2,6 @@
@@ -12,7 +10,5 @@
defineProps<{
label: string;
type?: string;
- formaction?: string;
- formmethod?: string;
}>();
diff --git a/src/app/components/form/Element.vue b/src/app/components/form/Element.vue
index c0771931..20d8b517 100644
--- a/src/app/components/form/Element.vue
+++ b/src/app/components/form/Element.vue
@@ -1,9 +1,5 @@
-
-
-
diff --git a/src/app/pages/clients/[id].vue b/src/app/pages/clients/[id].vue
index 9e1139a3..0caa25f2 100644
--- a/src/app/pages/clients/[id].vue
+++ b/src/app/pages/clients/[id].vue
@@ -5,7 +5,7 @@
-
+
{{ $t('me.sectionGeneral') }}
@@ -74,13 +74,15 @@ authStore.update();
const route = useRoute();
const id = route.params.id as string;
-const submitAction = computed(() => `/api/client/${id}`);
-
const { data: _data, refresh } = await useFetch(`/api/client/${id}`, {
method: 'get',
});
const data = toRef(_data.value);
+function submit() {
+ console.log(data.value);
+}
+
async function revert() {
await refresh();
data.value = toRef(_data.value).value;
diff --git a/src/i18n/locales/en.json b/src/i18n/locales/en.json
index 93e17436..370c1d07 100644
--- a/src/i18n/locales/en.json
+++ b/src/i18n/locales/en.json
@@ -52,6 +52,8 @@
"serverAllowedIPs": "Allowed IPs must be a valid array of strings",
"name": "Name must be a valid string",
"nameMin": "Name must be at least 1 Character",
+ "mtu": "MTU must be a valid number",
+ "persistentKeepalive": "Persistent Keepalive must be a valid number",
"file": "File must be a valid string",
"username": "Username must be a valid string",
"usernameMin": "Username must be at least 8 Characters",
diff --git a/src/package.json b/src/package.json
index 07f73bc3..9abf671d 100644
--- a/src/package.json
+++ b/src/package.json
@@ -41,8 +41,7 @@
"timeago.js": "^4.0.2",
"vue": "latest",
"vue3-apexcharts": "^1.8.0",
- "zod": "^3.24.1",
- "zod-form-data": "^2.0.5"
+ "zod": "^3.24.1"
},
"devDependencies": {
"@nuxt/eslint-config": "^0.7.3",
diff --git a/src/pnpm-lock.yaml b/src/pnpm-lock.yaml
index b20435f5..1ec25ac0 100644
--- a/src/pnpm-lock.yaml
+++ b/src/pnpm-lock.yaml
@@ -83,9 +83,6 @@ importers:
zod:
specifier: ^3.24.1
version: 3.24.1
- zod-form-data:
- specifier: ^2.0.5
- version: 2.0.5(zod@3.24.1)
devDependencies:
'@nuxt/eslint-config':
specifier: ^0.7.3
@@ -4541,11 +4538,6 @@ packages:
resolution: {integrity: sha512-zK7YHHz4ZXpW89AHXUPbQVGKI7uvkd3hzusTdotCg1UxyaVtg0zFJSTfW/Dq5f7OBBVnq6cZIaC8Ti4hb6dtCA==}
engines: {node: '>= 14'}
- zod-form-data@2.0.5:
- resolution: {integrity: sha512-T7dV6lTBCwkd8PyvJVCnjXKpgXomU8gEm/TcvEZY7qNdRhIo9T17HrdlHIK68PzTAYaV2HxR9rgwpTSWv0L+QQ==}
- peerDependencies:
- zod: '>= 3.11.0'
-
zod@3.24.1:
resolution: {integrity: sha512-muH7gBL9sI1nciMZV67X5fTKKBLtwpZ5VBp1vsOQzj1MhrBZ4wlVCm3gedKZWLp0Oyel8sIGfeiz54Su+OVT+A==}
@@ -9426,8 +9418,4 @@ snapshots:
compress-commons: 6.0.2
readable-stream: 4.5.2
- zod-form-data@2.0.5(zod@3.24.1):
- dependencies:
- zod: 3.24.1
-
zod@3.24.1: {}
diff --git a/src/server/api/client/[clientId]/index.post.ts b/src/server/api/client/[clientId]/index.post.ts
index da5584a1..5568957f 100644
--- a/src/server/api/client/[clientId]/index.post.ts
+++ b/src/server/api/client/[clientId]/index.post.ts
@@ -3,7 +3,7 @@ export default defineEventHandler(async (event) => {
event,
validateZod(clientIdType)
);
- const data = await readValidatedFormData(
+ const data = await readValidatedBody(
event,
validateZod(clientUpdateType, event)
);
diff --git a/src/server/utils/apiHelper.ts b/src/server/utils/apiHelper.ts
deleted file mode 100644
index f0a816b2..00000000
--- a/src/server/utils/apiHelper.ts
+++ /dev/null
@@ -1,31 +0,0 @@
-import type { H3Event, InferEventInput } from 'h3';
-
-export async function readValidatedFormData<
- Event extends H3Event = H3Event,
- T = InferEventInput<'body', Event, null>,
->(event: Event, validate: (data: FormData) => T) {
- const _form = await readFormData(event);
- return validateData(_form, validate);
-}
-
-async function validateData(data: T, fn: (data: T) => K) {
- try {
- const res = await fn(data);
- if (res === false) {
- throw createValidationError();
- }
- return res;
- } catch (error) {
- throw createValidationError(error);
- }
-}
-
-// eslint-disable-next-line @typescript-eslint/no-explicit-any
-function createValidationError(validateError?: any) {
- throw createError({
- status: 400,
- statusMessage: 'Validation Error',
- message: validateError?.message || 'Validation Error',
- data: validateError,
- });
-}
diff --git a/src/server/utils/types.ts b/src/server/utils/types.ts
index 5b145ff4..c7ddec52 100644
--- a/src/server/utils/types.ts
+++ b/src/server/utils/types.ts
@@ -2,7 +2,6 @@ import type { ZodSchema, ZodTypeDef } from 'zod';
import { z, ZodError } from 'zod';
import type { H3Event, EventHandlerRequest } from 'h3';
import { LOCALES } from '#shared/locales';
-import { zfd } from 'zod-form-data';
// TODO: make objects strict
@@ -155,22 +154,18 @@ const address6 = z
.pipe(safeStringRefine);
/** expects formdata, strict */
-export const clientUpdateType = zfd.formData({
- name: zfd.text(name),
- enabled: zfd.checkbox(),
- expiresAt: zfd.text(expireDate.optional()),
- address4: zfd.text(address4),
- address6: zfd.text(address6),
- allowedIPs: zfd.repeatable(
- z
- .array(zfd.text(address), { message: 'zod.allowedIPs' })
- .min(1, { message: 'zod.allowedIPsMin' })
- ),
- serverAllowedIPs: zfd.repeatable(
- z.array(zfd.text(address), { message: 'zod.serverAllowedIPs' })
- ),
- mtu: zfd.numeric(),
- persistentKeepalive: zfd.numeric(),
+export const clientUpdateType = z.strictObject({
+ name: name,
+ enabled: z.boolean(),
+ expiresAt: expireDate,
+ address4: address4,
+ address6: address6,
+ allowedIPs: z
+ .array(address, { message: 'zod.allowedIPs' })
+ .min(1, { message: 'zod.allowedIPsMin' }),
+ serverAllowedIPs: z.array(address, { message: 'zod.serverAllowedIPs' }),
+ mtu: z.number({ message: 'zod.mtu' }),
+ persistentKeepalive: z.number({ message: 'zod.persistentKeepalive' }),
});
// from https://github.com/airjp73/rvf/blob/7e7c35d98015ea5ecff5affaf89f78296e84e8b9/packages/zod-form-data/src/helpers.ts#L117