Skip to content

Commit

Permalink
Switch to using zod for validation on queue API endpoints (#1534)
Browse files Browse the repository at this point in the history
* create que schemas and use them for validation

* made requested changes
  • Loading branch information
Victor-M-Giraldo authored Mar 20, 2024
1 parent 6a5de38 commit 9446cd4
Show file tree
Hide file tree
Showing 3 changed files with 47 additions and 37 deletions.
18 changes: 8 additions & 10 deletions common/models/rest-api.ts
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,12 @@ 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 { OttApiRequestRoomCreateSchema, OttApiRequestVoteSchema } from "./zod-schemas";
import {
OttApiRequestRoomCreateSchema,
OttApiRequestVoteSchema,
OttApiRequestAddToQueueSchema,
OttApiRequestRemoveFromQueueSchema,
} from "./zod-schemas";
import { z } from "zod";

export type OttResponseBody<T = unknown, E extends OttApiError = OttApiError> =
Expand Down Expand Up @@ -68,16 +73,9 @@ export interface OttApiRequestUndo {
event: ServerMessageEvent;
}

export type OttApiRequestAddToQueue =
| {
videos: VideoId[];
}
| VideoId
| {
url: string;
};
export type OttApiRequestAddToQueue = z.infer<typeof OttApiRequestAddToQueueSchema>;

export type OttApiRequestRemoveFromQueue = VideoId;
export type OttApiRequestRemoveFromQueue = z.infer<typeof OttApiRequestRemoveFromQueueSchema>;

export type OttApiResponseAddPreview = {
result: Video[];
Expand Down
17 changes: 15 additions & 2 deletions common/models/zod-schemas.ts
Original file line number Diff line number Diff line change
@@ -1,7 +1,6 @@
import { ALL_VIDEO_SERVICES, ROOM_NAME_REGEX } from "ott-common/constants";
import { Visibility, QueueMode } from "ott-common/models/types";
import { VideoService } from "./video";
import { string, z } from "zod";
import { z } from "zod";

// These strings are not allowed to be used as room names.
const RESERVED_ROOM_NAMES = ["list", "create", "generate"];
Expand All @@ -28,3 +27,17 @@ const VideoIdSchema = z.object({
export const OttApiRequestVoteSchema = z.object({
...VideoIdSchema.shape,
});

export const OttApiRequestAddToQueueSchema = z.union([
z.object({
videos: z.array(VideoIdSchema),
}),
VideoIdSchema,
z.object({
url: z.string(),
}),
]);

export const OttApiRequestRemoveFromQueueSchema = z.object({
...VideoIdSchema.shape,
});
49 changes: 24 additions & 25 deletions server/api/room.ts
Original file line number Diff line number Diff line change
Expand Up @@ -35,6 +35,8 @@ import { conf } from "../ott-config";
import {
OttApiRequestRoomCreateSchema,
OttApiRequestVoteSchema,
OttApiRequestAddToQueueSchema,
OttApiRequestRemoveFromQueueSchema,
} from "ott-common/models/zod-schemas";
import { ZodError } from "zod";
import { fromZodError } from "zod-validation-error";
Expand Down Expand Up @@ -350,37 +352,37 @@ const addToQueue: RequestHandler<
OttResponseBody<unknown>,
OttApiRequestAddToQueue
> = async (req, res) => {
const body = OttApiRequestAddToQueueSchema.parse(req.body);
let points = 5;
if ("videos" in req.body) {
points = 3 * req.body.videos.length;
if ("videos" in body) {
points = 3 * body.videos.length;
}
if (!(await consumeRateLimitPoints(res, req.ip, points))) {
return;
}
const room = (await roommanager.getRoom(req.params.name)).unwrap();

let roomRequest: AddRequest;
if ("videos" in req.body) {
if ("videos" in body) {
roomRequest = {
type: RoomRequestType.AddRequest,
videos: req.body.videos,
videos: body.videos,
};
} else if ("url" in req.body) {
} else if ("url" in body) {
roomRequest = {
type: RoomRequestType.AddRequest,
url: req.body.url,
url: body.url,
};
} else if ("service" in req.body && "id" in req.body) {
} else {
roomRequest = {
type: RoomRequestType.AddRequest,
video: {
service: req.body.service,
id: req.body.id,
service: body.service,
id: body.id,
},
};
} else {
throw new BadApiArgumentException("service,id", "missing");
}

await room.processUnauthorizedRequest(roomRequest, { token: req.token! });
res.json({
success: true,
Expand All @@ -392,26 +394,23 @@ const removeFromQueue: RequestHandler<
OttResponseBody<unknown>,
OttApiRequestRemoveFromQueue
> = async (req, res) => {
const body = OttApiRequestRemoveFromQueueSchema.parse(req.body);
let points = 5;
if (!(await consumeRateLimitPoints(res, req.ip, points))) {
return;
}
const room = (await roommanager.getRoom(req.params.name)).unwrap();

if (req.body.service && req.body.id) {
await room.processUnauthorizedRequest(
{
type: RoomRequestType.RemoveRequest,
video: { service: req.body.service, id: req.body.id },
},
{ token: req.token! }
);
res.json({
success: true,
});
} else {
throw new BadApiArgumentException("service,id", "missing");
}
await room.processUnauthorizedRequest(
{
type: RoomRequestType.RemoveRequest,
video: { service: body.service, id: body.id },
},
{ token: req.token! }
);
res.json({
success: true,
});
};

const errorHandler: ErrorRequestHandler = (err: Error, req, res) => {
Expand Down

0 comments on commit 9446cd4

Please sign in to comment.