Add Backend Validation

Dieser Commit ist enthalten in:
Chaoscaot 2023-08-16 13:36:53 +02:00
Ursprung b14ef2981e
Commit 4a501ea870
Signiert von: Chaoscaot
GPG-Schlüssel-ID: BDF8FADD7D5EDB7A
8 geänderte Dateien mit 104 neuen und 70 gelöschten Zeilen

Datei anzeigen

@ -14,6 +14,10 @@
"@tsconfig/svelte": "^4.0.1",
"autoprefixer": "^10.4.14",
"flowbite-svelte-icons": "^0.2.5",
"flowbite": "^1.7.0",
"flowbite-svelte": "^0.39.2",
"svelte-awesome": "^3.2.0",
"tailwind-merge": "^1.13.2",
"postcss": "^8.4.24",
"sass": "^1.62.0",
"svelte": "^4.0.1",
@ -25,14 +29,9 @@
"vite": "^4.3.9"
},
"dependencies": {
"@popperjs/core": "^2.11.8",
"color": "^4.2.3",
"flowbite": "^1.7.0",
"flowbite-svelte": "^0.39.2",
"install": "^0.13.0",
"moment": "^2.29.4",
"svelte-awesome": "^3.2.0",
"svelte-spa-router": "^3.3.0",
"tailwind-merge": "^1.13.2"
"zod": "^3.21.4"
}
}

Datei anzeigen

@ -28,6 +28,9 @@ dependencies:
tailwind-merge:
specifier: ^1.13.2
version: 1.13.2
zod:
specifier: ^3.21.4
version: 3.21.4
devDependencies:
'@sveltejs/vite-plugin-svelte':
@ -1459,6 +1462,10 @@ packages:
engines: {node: '>= 14'}
dev: true
/zod@3.21.4:
resolution: {integrity: sha512-m46AKbrzKVzOzs/DZgVnG5H55N1sv1M8qZU3A8RIKbs3mrACDNeIOeilDymVb2HdmP8uwshOCF4uJ8uM9rCqJw==}
dev: false
settings:
autoInstallPeers: true
excludeLinksFromLockfile: false

Datei anzeigen

@ -1,6 +1,8 @@
import type {ExtendedEvent, ShortEvent, SWEvent} from "../types/event.js";
import {fetchWithToken} from "./repo.js";
import type {Moment} from "moment";
import {ExtendedEventSchema, ShortEventSchema, SWEventSchema} from "../types/event.js";
import {z} from "zod";
export interface CreateEvent {
name: string
@ -26,7 +28,7 @@ export class EventRepo {
const res = await fetchWithToken(this.token, "/events");
if (res.ok) {
return await res.json() as ShortEvent[];
return z.array(ShortEventSchema).parse(await res.json());
} else {
throw new Error("Could not fetch events: " + res.statusText);
}
@ -36,7 +38,7 @@ export class EventRepo {
const res = await fetchWithToken(this.token, `/events/${id}`);
if (res.ok) {
return await res.json() as ExtendedEvent;
return ExtendedEventSchema.parse(await res.json());
} else {
throw new Error("Could not fetch event: " + res.statusText);
}
@ -53,7 +55,7 @@ export class EventRepo {
});
if (res.ok) {
return await res.json() as SWEvent;
return SWEventSchema.parse(await res.json());
} else {
throw new Error("Could not create event: " + res.statusText);
}
@ -78,7 +80,7 @@ export class EventRepo {
});
if (res.ok) {
return await res.json() as SWEvent;
return SWEventSchema.parse(await res.json());
} else {
throw new Error("Could not update event: " + res.statusText);
}

Datei anzeigen

@ -1,6 +1,8 @@
import type {EventFight} from "../types/event.js";
import {fetchWithToken} from "./repo.js";
import type {Moment} from "moment";
import {z} from "zod";
import {EventFightSchema} from "../types/event.js";
export interface CreateFight {
spielmodus: string
@ -29,7 +31,7 @@ export class FightRepo {
const res = await fetchWithToken(this.token, `/events/${eventId}/fights`);
if (res.ok) {
return await res.json() as EventFight[];
return z.array(EventFightSchema).parse(await res.json());
} else {
throw new Error("Could not fetch fights: " + res.statusText);
}
@ -51,7 +53,7 @@ export class FightRepo {
})
if (res.ok) {
return await res.json() as EventFight;
return EventFightSchema.parse(await res.json());
} else {
throw new Error("Could not create fight: " + res.statusText);
}
@ -72,7 +74,7 @@ export class FightRepo {
})
if (res.ok) {
return await res.json() as EventFight;
return EventFightSchema.parse(await res.json());
} else {
throw new Error("Could not update fight: " + res.statusText);
}

Datei anzeigen

@ -3,20 +3,23 @@ import {cached, cachedFamily} from "./cached.js";
import type {Team} from "../types/team.js";
import {get, writable} from "svelte/store";
import {tokenStore} from "../repo/repo.js";
import {PlayerSchema} from "../types/data.js";
import {z} from "zod";
import {TeamSchema} from "../types/team.js";
export const schemTypes = cached<SchematicType[]>([], () => {
return fetch("https://steamwar.de/eventplanner-api/data/schematicTypes", {headers: {"X-SW-Auth": get(tokenStore)}})
.then(res => res.json())
})
export const players = cached<Player[]>([], () => {
return fetch("https://steamwar.de/eventplanner-api/data/users", {headers: {"X-SW-Auth": get(tokenStore)}})
.then(res => res.json())
export const players = cached<Player[]>([], async () => {
const res = await fetch("https://steamwar.de/eventplanner-api/data/users", {headers: {"X-SW-Auth": get(tokenStore)}});
return z.array(PlayerSchema).parse(await res.json());
})
export const gamemodes = cached<string[]>([], () => {
return fetch("https://steamwar.de/eventplanner-api/data/gamemodes", {headers: {"X-SW-Auth": get(tokenStore)}})
.then(res => res.json())
export const gamemodes = cached<string[]>([], async () => {
const res = await fetch("https://steamwar.de/eventplanner-api/data/gamemodes", {headers: {"X-SW-Auth": get(tokenStore)}});
return z.array(z.string()).parse(await res.json());
})
export const maps = cachedFamily<string, string[]>([], async (gamemode) => {
@ -30,14 +33,14 @@ export const maps = cachedFamily<string, string[]>([], async (gamemode) => {
}
})
export const groups = cached<string[]>([], () => {
return fetch("https://steamwar.de/eventplanner-api/data/groups", {headers: {"X-SW-Auth": get(tokenStore)}})
.then(res => res.json())
export const groups = cached<string[]>([], async () => {
const res = await fetch("https://steamwar.de/eventplanner-api/data/groups", {headers: {"X-SW-Auth": get(tokenStore)}});
return z.array(z.string()).parse(await res.json());
})
export const teams = cached<Team[]>([], () => {
return fetch("https://steamwar.de/eventplanner-api/team", {headers: {"X-SW-Auth": get(tokenStore)}})
.then(res => res.json())
export const teams = cached<Team[]>([], async () => {
const res = await fetch("https://steamwar.de/eventplanner-api/team", {headers: {"X-SW-Auth": get(tokenStore)}});
return z.array(TeamSchema).parse(await res.json());
})
export const isWide = writable(window.innerWidth >= 640);

Datei anzeigen

@ -1,10 +1,16 @@
export interface SchematicType {
name: string;
db: string;
}
import {z} from "zod";
export interface Player {
id: number;
name: string;
uuid: string;
}
export const SchematicTypeSchema = z.object({
name: z.string(),
db: z.string(),
})
export type SchematicType = z.infer<typeof SchematicTypeSchema>;
export const PlayerSchema = z.object({
id: z.number(),
name: z.string(),
uuid: z.string().uuid(),
})
export type Player = z.infer<typeof PlayerSchema>;

Datei anzeigen

@ -1,35 +1,46 @@
import type {Team} from "./team.js";
import type {Player} from "./data.js";
import {z} from "zod";
import {TeamSchema} from "./team.js";
import {PlayerSchema} from "./data.js";
export interface ShortEvent {
id: number;
name: string;
start: number;
end: number;
}
export const ShortEventSchema = z.object({
id: z.number(),
name: z.string(),
start: z.number(),
end: z.number(),
})
export interface SWEvent extends ShortEvent {
deadline: number;
maxTeamMembers: number;
schemType: string | null;
publicSchemsOnly: boolean;
spectateSystem: boolean;
}
export type ShortEvent = z.infer<typeof ShortEventSchema>;
export interface EventFight {
id: number;
spielmodus: string;
map: string;
blueTeam: Team;
redTeam: Team;
kampfleiter: Player | null;
start: number;
ergebnis: number;
group: string | null;
}
export const SWEventSchema = ShortEventSchema.extend({
deadline: z.number(),
maxTeamMembers: z.number(),
schemType: z.string().nullable(),
publicSchemsOnly: z.boolean(),
spectateSystem: z.boolean(),
})
export interface ExtendedEvent {
event: SWEvent;
teams: Team[];
fights: EventFight[];
}
export type SWEvent = z.infer<typeof SWEventSchema>;
export const EventFightSchema = z.object({
id: z.number(),
spielmodus: z.string(),
map: z.string(),
blueTeam: TeamSchema,
redTeam: TeamSchema,
kampfleiter: PlayerSchema.nullable(),
start: z.number(),
ergebnis: z.number(),
group: z.string().nullable(),
})
export type EventFight = z.infer<typeof EventFightSchema>;
export const ExtendedEventSchema = z.object({
event: SWEventSchema,
teams: z.array(TeamSchema),
fights: z.array(EventFightSchema),
})
export type ExtendedEvent = z.infer<typeof ExtendedEventSchema>;

Datei anzeigen

@ -1,8 +1,12 @@
import Color from "color";
import {z} from "zod";
export const TeamSchema = z.object({
id: z.number(),
name: z.string(),
kuerzel: z.string().min(1).max(4),
color: z.string().max(1),
})
export type Team = z.infer<typeof TeamSchema>;
export interface Team {
id: number;
name: string;
kuerzel: string;
color: string;
}