You can not select more than 25 topics
Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
181 lines
5.9 KiB
181 lines
5.9 KiB
import {getClient} from "../utils/database.js";
|
|
import {body, param} from "express-validator";
|
|
import jwt from "jsonwebtoken";
|
|
|
|
export const Video = {
|
|
|
|
id: param("id").notEmpty().isNumeric().trim(),
|
|
title: body("title").notEmpty().trim(),
|
|
description: body("description").optional({values: "falsy"}).trim(),
|
|
channel: body("channel").notEmpty().isNumeric().trim(),
|
|
visibility: body("visibility").notEmpty().isAlpha().trim(),
|
|
idBody: body("video").notEmpty().isNumeric().trim(),
|
|
tags: body("tags").optional({values: "falsy"}).isArray().custom((value) => {
|
|
if (value.length > 10) {
|
|
throw new Error("Too many tags, maximum is 10");
|
|
}
|
|
return true;
|
|
}),
|
|
}
|
|
|
|
export const VideoCreate = {
|
|
title: body("title").notEmpty().trim(),
|
|
description: body("description").optional({values: "falsy"}).trim(),
|
|
channel: body("channel").notEmpty().isNumeric().trim(),
|
|
visibility: body("visibility").notEmpty().isAlpha().trim(),
|
|
authorizedUsers: body("authorizedUsers")
|
|
.optional({values: "falsy"})
|
|
.customSanitizer((value) => {
|
|
// Parse JSON string back to array
|
|
if (typeof value === 'string') {
|
|
try {
|
|
return JSON.parse(value);
|
|
} catch (error) {
|
|
return [];
|
|
}
|
|
}
|
|
return value;
|
|
})
|
|
.isArray()
|
|
.withMessage("Authorized users must be an array"),
|
|
}
|
|
|
|
export const VideoThumbnail = {
|
|
video: body("video").notEmpty().isNumeric().trim(),
|
|
}
|
|
|
|
export async function isOwner(req, res, next) {
|
|
const logger = req.body.logger;
|
|
const channelId = req.body.channel;
|
|
const token = req.headers.authorization.split(' ')[1];
|
|
const claims = jwt.decode(token);
|
|
const client = await getClient();
|
|
try {
|
|
const channelQuery = `SELECT owner FROM channels WHERE id = $1`;
|
|
const channelResult = await client.query(channelQuery, [channelId]);
|
|
const channelInBase = channelResult.rows[0];
|
|
if (channelInBase.owner !== claims.id) {
|
|
logger.write("failed because user is not owner", 403);
|
|
res.status(403).json({error: "Not authorized"});
|
|
return
|
|
}
|
|
next()
|
|
} finally {
|
|
client.release();
|
|
}
|
|
}
|
|
|
|
export async function doVideoExists(req, res, next) {
|
|
const logger = req.body.logger;
|
|
const videoId = req.body.video;
|
|
|
|
const client = await getClient();
|
|
try {
|
|
const query = `SELECT * FROM videos WHERE id = $1`;
|
|
const result = await client.query(query, [videoId]);
|
|
const videos = result.rows;
|
|
if (videos.length === 0) {
|
|
logger.write("failed because video not found", 404);
|
|
res.status(404).json({error: "Not Found"});
|
|
return
|
|
}
|
|
next()
|
|
} finally {
|
|
client.release();
|
|
}
|
|
}
|
|
|
|
export async function doVideoExistsParam(req, res, next) {
|
|
const logger = req.body.logger;
|
|
const videoId = req.params.id;
|
|
|
|
const client = await getClient();
|
|
try {
|
|
const query = `SELECT * FROM videos WHERE id = $1`;
|
|
const result = await client.query(query, [videoId]);
|
|
const video = result.rows[0];
|
|
if (!video) {
|
|
logger.write("failed because video not found", 404);
|
|
res.status(404).json({error: "Not Found"});
|
|
return
|
|
}
|
|
next()
|
|
} finally {
|
|
client.release();
|
|
}
|
|
}
|
|
|
|
export async function doAuthorizedUserExists(req, res, next) {
|
|
const logger = req.body.logger;
|
|
let authorizedUsers = req.body.authorizedUsers;
|
|
|
|
// Parse JSON string if needed
|
|
if (typeof authorizedUsers === 'string') {
|
|
try {
|
|
authorizedUsers = JSON.parse(authorizedUsers);
|
|
} catch (error) {
|
|
logger.write("failed because authorizedUsers is not valid JSON", 400);
|
|
res.status(400).json({error: "Invalid authorized users format"});
|
|
return;
|
|
}
|
|
}
|
|
|
|
if (authorizedUsers && Array.isArray(authorizedUsers) && authorizedUsers.length > 0) {
|
|
const client = await getClient();
|
|
try {
|
|
for (const userId of authorizedUsers) {
|
|
const query = `SELECT id FROM users WHERE id = $1`;
|
|
const result = await client.query(query, [userId]);
|
|
const foundUser = result.rows[0];
|
|
if (!foundUser) {
|
|
logger.write("failed because authorized user not found", 404);
|
|
res.status(404).json({error: "Not Found"});
|
|
return
|
|
}
|
|
}
|
|
} finally {
|
|
client.release();
|
|
}
|
|
}
|
|
next()
|
|
}
|
|
|
|
export async function hasAccess(req, res, next) {
|
|
const logger = req.body.logger;
|
|
const videoId = req.params.id;
|
|
|
|
const client = await getClient();
|
|
try {
|
|
const videoQuery = "SELECT visibility FROM videos WHERE id = $1";
|
|
const videoResult = await client.query(videoQuery, [videoId]);
|
|
const video = videoResult.rows[0];
|
|
|
|
console.log(video);
|
|
|
|
if (video.visibility === 'private') {
|
|
const token = req.headers.authorization?.split(" ")[1];
|
|
|
|
if (!req.headers.authorization || !token) {
|
|
logger.write("failed because no token provided", 401);
|
|
res.status(401).json({error: "Unauthorized"});
|
|
return;
|
|
}
|
|
|
|
const claims = jwt.decode(token);
|
|
const userId = claims.id;
|
|
const query = `SELECT * FROM video_authorized_users WHERE video_id = $1 AND user_id = $2`;
|
|
const result = await client.query(query, [videoId, userId]);
|
|
const isAuthorized = result.rows.length > 0;
|
|
|
|
if (!isAuthorized) {
|
|
logger.write("failed because user is not authorized", 403);
|
|
res.status(403).json({error: "Not authorized"});
|
|
return;
|
|
}
|
|
}
|
|
|
|
next();
|
|
} finally {
|
|
client.release();
|
|
}
|
|
}
|
|
|