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 queue API endpoints #1534

Merged
merged 2 commits into from
Mar 20, 2024
Merged
Show file tree
Hide file tree
Changes from all 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
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";

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

View check run for this annotation

Codecov / codecov/patch

common/models/zod-schemas.ts#L3

Added line #L3 was not covered by tests

// These strings are not allowed to be used as room names.
const RESERVED_ROOM_NAMES = ["list", "create", "generate"];
Expand All @@ -28,3 +27,17 @@
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,
});

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

View check run for this annotation

Codecov / codecov/patch

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

Added lines #L30 - L43 were not covered by tests
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 {
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 @@
OttResponseBody<unknown>,
OttApiRequestAddToQueue
> = async (req, res) => {
const body = OttApiRequestAddToQueueSchema.parse(req.body);

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

View check run for this annotation

Codecov / codecov/patch

server/api/room.ts#L355

Added line #L355 was not covered by tests
let points = 5;
if ("videos" in req.body) {
points = 3 * req.body.videos.length;
if ("videos" in body) {
points = 3 * body.videos.length;

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

View check run for this annotation

Codecov / codecov/patch

server/api/room.ts#L357-L358

Added lines #L357 - L358 were not covered by tests
}
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) {

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

View check run for this annotation

Codecov / codecov/patch

server/api/room.ts#L366

Added line #L366 was not covered by tests
roomRequest = {
type: RoomRequestType.AddRequest,
videos: req.body.videos,
videos: body.videos,

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

View check run for this annotation

Codecov / codecov/patch

server/api/room.ts#L369

Added line #L369 was not covered by tests
};
} else if ("url" in req.body) {
} else if ("url" in body) {

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

View check run for this annotation

Codecov / codecov/patch

server/api/room.ts#L371

Added line #L371 was not covered by tests
roomRequest = {
type: RoomRequestType.AddRequest,
url: req.body.url,
url: body.url,

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

View check run for this annotation

Codecov / codecov/patch

server/api/room.ts#L374

Added line #L374 was not covered by tests
};
} else if ("service" in req.body && "id" in req.body) {
} else {

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

View check run for this annotation

Codecov / codecov/patch

server/api/room.ts#L376

Added line #L376 was not covered by tests
roomRequest = {
type: RoomRequestType.AddRequest,
video: {
service: req.body.service,
id: req.body.id,
service: body.service,
id: body.id,

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

View check run for this annotation

Codecov / codecov/patch

server/api/room.ts#L380-L381

Added lines #L380 - L381 were not covered by tests
},
};
} else {
throw new BadApiArgumentException("service,id", "missing");
}

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

View check run for this annotation

Codecov / codecov/patch

server/api/room.ts#L385

Added line #L385 was not covered by tests
await room.processUnauthorizedRequest(roomRequest, { token: req.token! });
res.json({
success: true,
Expand All @@ -392,26 +394,23 @@
OttResponseBody<unknown>,
OttApiRequestRemoveFromQueue
> = async (req, res) => {
const body = OttApiRequestRemoveFromQueueSchema.parse(req.body);

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

View check run for this annotation

Codecov / codecov/patch

server/api/room.ts#L397

Added line #L397 was not covered by tests
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,
});

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

View check run for this annotation

Codecov / codecov/patch

server/api/room.ts#L404-L413

Added lines #L404 - L413 were not covered by tests
};

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