Zum Inhalt

User-Input-Validierung

Die Validierung von Benutzereingaben verhindert, dass schädliche oder ungültige Daten in die Anwendung gelangen. Die Bibliothek validator bietet viele Funktionen zur Validierung und Sanitierung von Eingaben. 1

Installation von validator
npm install validator
Validierung von E-Mail-Adressen
const validator = require("validator");
const isValidEmail = validator.isEmail("test@example.com");
console.log(isValidEmail); // true oder false
Validierung von Benutzereingaben in Vue.js
<template>
    <v-card class="d-flex flex-column">
        <form @submit="onSubmit">
            <v-card-title>Neuen Berg erfassen:</v-card-title>
            <v-card-text>
                <v-text-field
                    v-model="mntName.value.value"
                    label="Name"
                    :error-messages="errors.mntName"
                    dense
                    clearable></v-text-field>
                <v-text-field
                    v-model="mntDescription.value.value"
                    label="Description"
                    :error-messages="errors.mntDescription"
                    dense
                    clearable></v-text-field>
                <v-text-field
                    v-model="mntLatitude.value.value"
                    label="Breitengrad"
                    :error-messages="errors.mntLatitude"
                    dense
                    clearable></v-text-field>
                <v-text-field
                    v-model="mntLongitude.value.value"
                    label="Längengrad"
                    :error-messages="errors.mntLongitude"
                    dense
                    clearable></v-text-field>
                <v-text-field
                    v-model="mntElevation.value.value"
                    label="Höhe"
                    :error-messages="errors.mntElevation"
                    dense
                    clearable></v-text-field>
                <v-file-input
                    v-model="file"
                    accept="image/png image/jpg image/jpeg"
                    label="Datei"
                    dense
                    clearable></v-file-input>
            </v-card-text>
            <v-card-actions class="mt-auto d-flex justify-end" width="100">
                <v-btn icon="mdi-close" @click="cancel"> </v-btn>
                <v-btn variant="tonal" type="submit" icon="mdi-check"> </v-btn>
            </v-card-actions>
        </form>
    </v-card>
</template>
Validierung von Benutzereingaben in Vue.js
<script>
import { ref } from "vue";
import { useUserStore } from "../stores/user.js";
import { useErrorStore } from "../stores/error.js";
import useHelpers from "../hooks/helpers.js";
import { storeToRefs } from "pinia";
import { useForm, useField } from "vee-validate";
import * as yup from "yup";

export default {
    emits: ["cancelNewMnt", "saveNewMnt"],

    setup(porps, ctx) {
        const {
            jwt,
            id: userId,
            isAuthenticated,
        } = storeToRefs(useUserStore());

        const { alert } = useErrorStore();
        const { checkHttpStatus } = useHelpers();

        const { handleSubmit, errors } = useForm({
            validationSchema: yup.object({
                mntName: yup.string().required("Pflichtfeld"),
                mntDescription: yup.string().required("Pflichtfeld"),
                mntLatitude: yup
                    .number()
                    .min(-90.0, "Breitengrad >= -90.0°")
                    .max(90.0, "Breitengrad <= 90.0°")
                    .required("Pflichtfeld")
                    .typeError("Breitengrad muss eine Zahl sein"),
                mntLongitude: yup
                    .number()
                    .min(-180.0, "Längengrad >= -180.0°")
                    .max(180.0, "Längengrad >= 180.0°")
                    .required("Pflichtfeld")
                    .typeError("Längengrad muss eine Zahl sein"),
                mntElevation: yup
                    .number()
                    .integer("Höhe muss eine ganze Zahl sein")
                    .required("Pflichtfeld")
                    .typeError("Höhe muss eine ganze Zahl sein"),
            }),
        });

        const mntName = useField("mntName");
        const mntDescription = useField("mntDescription");
        const mntLatitude = useField("mntLatitude");
        const mntLongitude = useField("mntLongitude");
        const mntElevation = useField("mntElevation");
        const file = ref([]);

        const onSubmit = handleSubmit((values) => {
            save();
        });

        function cancel() {
            ctx.emit("cancelNewMnt");
        }

        async function save() {
            try {
                let res;
                // step 1: create new mountain object at backend (without image)
                let reqBody = JSON.stringify({
                    name: mntName.value.value,
                    description: mntDescription.value.value,
                    elevation: mntElevation.value.value,
                    latitude: mntLatitude.value.value,
                    longitude: mntLongitude.value.value,
                    hasmountainrailway: false,
                });
                let postReqHeaders = { "Content-Type": "application/json" };
                let putReqHeaders = {};

                // add JWT to request header, if user-specific mountain should be added
                if (isAuthenticated.value) {
                    postReqHeaders["Authorization"] = `Bearer ${jwt.value}`;
                    putReqHeaders["Authorization"] = `Bearer ${jwt.value}`;
                }

                if (isAuthenticated.value) {
                    res = await fetch(
                        `${import.meta.env.VITE_BACKEND}/users/${
                            userId.value
                        }/mnts`,
                        {
                            method: "POST",
                            headers: postReqHeaders,
                            body: reqBody,
                        }
                    );
                } else {
                    res = await fetch(`${import.meta.env.VITE_BACKEND}/mnts`, {
                        method: "POST",
                        headers: postReqHeaders,
                        body: reqBody,
                    });
                }

                checkHttpStatus(res);
                let savedMnt = await res.json();

                // step 2: get id of newly created mountain, then upload image
                const mntId = savedMnt.properties.id;
                reqBody = new FormData();
                reqBody.append("image", file.value[0]);

                if (isAuthenticated.value) {
                    res = await fetch(
                        `${import.meta.env.VITE_BACKEND}/users/${
                            userId.value
                        }/mnts/${mntId}/img`,
                        {
                            method: "PUT",
                            body: reqBody,
                            headers: putReqHeaders,
                        }
                    );
                } else {
                    res = await fetch(
                        `${import.meta.env.VITE_BACKEND}/mnts/${mntId}/img`,
                        {
                            method: "PUT",
                            body: reqBody,
                        }
                    );
                }

                checkHttpStatus(res);
                savedMnt = await res.json();

                // step 3: notify parent component (gallery component) of newly added mountain
                ctx.emit("saveNewMnt", mntId);
            } catch (err) {
                alert(err.message, "error");
            }
        }

        return {
            mntName,
            mntDescription,
            mntLatitude,
            mntLongitude,
            mntElevation,
            file,
            errors,
            onSubmit,
            cancel,
            save,
        };
    },
};
</script>