Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Switch to using zod for validation on voting API endpoints #1476

Merged
merged 8 commits into from
Mar 12, 2024
Merged
Show file tree
Hide file tree
Changes from 6 commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
6 changes: 3 additions & 3 deletions common/models/rest-api.ts
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,7 @@ import { ServerMessageEvent } from "./messages";
import { BehaviorOption, QueueMode, RoomSettings, RoomUserInfo, Visibility } from "./types";
import { QueueItem, Video, VideoId } from "./video";
import type { Category } from "sponsorblock-api";
import { createRoomSchema } from "./zod-schemas";
import { OttApiRequestRoomCreateSchema, OttApiRequestVoteSchema } from "./zod-schemas";
import { z } from "zod";

export type OttResponseBody<T = unknown, E extends OttApiError = OttApiError> =
Expand Down Expand Up @@ -35,7 +35,7 @@ export interface OttApiResponseRoomGenerate {
}

/** Endpoint: `/api/room/create` */
export type OttApiRequestRoomCreate = z.infer<typeof createRoomSchema>;
export type OttApiRequestRoomCreate = z.infer<typeof OttApiRequestRoomCreateSchema>;

/** Endpoint: `/api/room/create` */
export interface OttApiResponseRoomCreate {}
Expand Down Expand Up @@ -83,7 +83,7 @@ export type OttApiResponseAddPreview = {
result: Video[];
};

export interface OttApiRequestVote extends VideoId {}
export type OttApiRequestVote = z.infer<typeof OttApiRequestVoteSchema>;

export type OttApiRequestAccountRecoveryStart = {
email?: string;
Expand Down
16 changes: 13 additions & 3 deletions common/models/zod-schemas.ts
Original file line number Diff line number Diff line change
@@ -1,11 +1,12 @@
import { ROOM_NAME_REGEX } from "ott-common/constants";
import { ALL_VIDEO_SERVICES, ROOM_NAME_REGEX } from "ott-common/constants";
import { Visibility, QueueMode } from "ott-common/models/types";
import { z } from "zod";
import { VideoService } from "./video";
import { string, z } from "zod";

Check warning on line 4 in common/models/zod-schemas.ts

View check run for this annotation

Codecov / codecov/patch

common/models/zod-schemas.ts#L3-L4

Added lines #L3 - L4 were not covered by tests

// These strings are not allowed to be used as room names.
const RESERVED_ROOM_NAMES = ["list", "create", "generate"];

export const createRoomSchema = z.object({
export const OttApiRequestRoomCreateSchema = z.object({

Check warning on line 9 in common/models/zod-schemas.ts

View check run for this annotation

Codecov / codecov/patch

common/models/zod-schemas.ts#L9

Added line #L9 was not covered by tests
name: z
.string()
.min(3, "too short, must be atleast 3 characters")
Expand All @@ -18,3 +19,12 @@
visibility: z.nativeEnum(Visibility).default(Visibility.Public).optional(),
queueMode: z.nativeEnum(QueueMode).optional(),
});

const VideoIdSchema = z.object({
service: z.enum(ALL_VIDEO_SERVICES),
id: z.string(),
Victor-M-Giraldo marked this conversation as resolved.
Show resolved Hide resolved
});

export const OttApiRequestVoteSchema = z.object({
...VideoIdSchema.shape,
});

Check warning on line 30 in common/models/zod-schemas.ts

View check run for this annotation

Codecov / codecov/patch

common/models/zod-schemas.ts#L22-L30

Added lines #L22 - L30 were not covered by tests
23 changes: 9 additions & 14 deletions server/api/room.ts
Original file line number Diff line number Diff line change
Expand Up @@ -32,7 +32,10 @@
import { v4 as uuidv4 } from "uuid";
import { counterHttpErrors } from "../metrics";
import { conf } from "../ott-config";
import { createRoomSchema } from "ott-common/models/zod-schemas";
import {
OttApiRequestRoomCreateSchema,
OttApiRequestVoteSchema,
} from "ott-common/models/zod-schemas";
import { ZodError } from "zod";
import { fromZodError } from "zod-validation-error";

Expand Down Expand Up @@ -119,7 +122,7 @@
OttResponseBody<OttApiResponseRoomCreate>,
OttApiRequestRoomCreate
> = async (req, res) => {
const body = createRoomSchema.parse(req.body);
const body = OttApiRequestRoomCreateSchema.parse(req.body);

if (body.isTemporary && !conf.get("room.enable_create_temporary")) {
throw new FeatureDisabledException("Temporary rooms are disabled.");
Expand Down Expand Up @@ -304,15 +307,11 @@
};

const addVote: RequestHandler<{ name: string }, unknown, OttApiRequestVote> = async (req, res) => {
const body = OttApiRequestVoteSchema.parse(req.body);
Victor-M-Giraldo marked this conversation as resolved.
Show resolved Hide resolved

Check warning on line 311 in server/api/room.ts

View check run for this annotation

Codecov / codecov/patch

server/api/room.ts#L310-L311

Added lines #L310 - L311 were not covered by tests
if (!req.token) {
Victor-M-Giraldo marked this conversation as resolved.
Show resolved Hide resolved
throw new OttException("Missing token");
}
if (!req.body.service) {
throw new BadApiArgumentException("service", "missing");
}
if (!req.body.id) {
throw new BadApiArgumentException("id", "missing");
}

const client = clientmanager.getClientByToken(req.token, req.params.name);
await clientmanager.makeRoomRequest(client, {
Expand All @@ -329,15 +328,11 @@
req,
res
) => {
const body = OttApiRequestVoteSchema.parse(req.body);
Victor-M-Giraldo marked this conversation as resolved.
Show resolved Hide resolved

Check warning on line 332 in server/api/room.ts

View check run for this annotation

Codecov / codecov/patch

server/api/room.ts#L331-L332

Added lines #L331 - L332 were not covered by tests
if (!req.token) {
throw new OttException("Missing token");
}
if (!req.body.service) {
throw new BadApiArgumentException("service", "missing");
}
if (!req.body.id) {
throw new BadApiArgumentException("id", "missing");
}

const client = clientmanager.getClientByToken(req.token, req.params.name);
await clientmanager.makeRoomRequest(client, {
Expand Down
Loading