Browse Source

Finish features/visibility

features/visibility
astria 4 months ago
parent
commit
da619172b6
  1. 2
      backend/app/controllers/channel.controller.js
  2. 7
      backend/app/controllers/recommendation.controller.js
  3. 2
      backend/app/controllers/search.controller.js
  4. 146
      backend/app/controllers/video.controller.js
  5. 84
      backend/app/middlewares/video.middleware.js
  6. 19
      backend/app/routes/video.route.js
  7. 7
      backend/app/utils/database.js
  8. 733
      backend/logs/access.log
  9. 2
      frontend/src/components/UserCard.jsx
  10. 27
      frontend/src/pages/AddVideo.jsx
  11. 120
      frontend/src/pages/ManageVideo.jsx
  12. 2
      frontend/src/pages/Video.jsx
  13. 33
      frontend/src/services/video.service.js

2
backend/app/controllers/channel.controller.js

@ -64,7 +64,7 @@ export async function getById(req, res) {
LEFT JOIN public.history h ON h.video = videos.id
LEFT JOIN public.likes ON likes.video = videos.id
LEFT JOIN public.comments c ON c.video = videos.id
WHERE videos.channel = $1
WHERE videos.channel = $1 AND videos.visibility = 'public'
GROUP BY videos.id, channels.name, channels.description, users.username, users.picture
`;

7
backend/app/controllers/recommendation.controller.js

@ -43,14 +43,15 @@ export async function getTrendingVideos(req, res) {
// GET 10 VIDEOS WITH THE MOST LIKES AND COMMENTS
let client = await getClient();
let queryTrendingVideos = `
SELECT v.id, v.title, v.description, v.release_date, v.thumbnail,
COUNT(DISTINCT l.id) AS like_count, COUNT(DISTINCT c.id) AS comment_count
SELECT v.id, v.title, v.description, v.release_date, v.thumbnail, v.visibility,
COUNT(DISTINCT l.id) AS like_count, COUNT(DISTINCT c.id) AS comment_count
FROM videos v
LEFT JOIN likes l ON v.id = l.video
LEFT JOIN comments c ON v.id = c.video
WHERE v.visibility = 'public'
GROUP BY v.id
ORDER BY like_count DESC, comment_count DESC
LIMIT 10;
LIMIT 10
`;
let result = await client.query(queryTrendingVideos);
const trendingVideos = result.rows;

2
backend/app/controllers/search.controller.js

@ -28,7 +28,7 @@ export async function search(req, res) {
JOIN public.channels c on v.channel = c.id
JOIN public.users u on c.owner = u.id
LEFT JOIN public.history h on h.video = v.id
WHERE v.title ILIKE $1
WHERE v.title ILIKE $1 AND v.visibility = 'public'
GROUP BY v.id, v.title, v.thumbnail, v.description, v.channel, v.visibility, v.file, v.slug, v.format, v.release_date,
c.id, c.owner, c.description, c.name, u.picture
OFFSET $2

146
backend/app/controllers/video.controller.js

@ -4,12 +4,13 @@ import * as fs from "node:fs";
import { fileURLToPath } from 'url';
import { dirname } from 'path';
import jwt from "jsonwebtoken";
import { query } from "express-validator";
import { sendEmail } from "../utils/mail.js";
const __filename = fileURLToPath(import.meta.url);
const __dirname = dirname(__filename);
export async function upload(req, res) {
// HANDLE VIDEO FILE
const fileBuffer = req.file.buffer;
let isGenerate = false;
while (isGenerate === false) {
@ -45,6 +46,7 @@ export async function upload(req, res) {
visibility: req.body.visibility,
}
// HANDLE VIDEO DETAILS
const logger = req.body.logger;
logger.write("try to upload video");
const releaseDate = new Date(Date.now()).toISOString();
@ -52,6 +54,108 @@ export async function upload(req, res) {
const query = `INSERT INTO videos (title, thumbnail, description, channel, visibility, file, slug, format, release_date) VALUES ($1, $2, $3, $4, $5, $6, $7, $8, $9) RETURNING id`;
const idResult = await client.query(query, [video.title, 'null', video.description, video.channel, video.visibility, video.file, video.slug, video.format, releaseDate]);
const id = idResult.rows[0].id;
console.log(req.body.visibility, req.body.authorizedUsers)
// HANDLE AUTHORIZED USERS
if (req.body.visibility === "private" && req.body.authorizedUsers) {
let authorizedUsers = req.body.authorizedUsers;
// Parse if still a string (safety check)
if (typeof authorizedUsers === 'string') {
try {
authorizedUsers = JSON.parse(authorizedUsers);
} catch (error) {
console.error("Failed to parse authorizedUsers:", error);
authorizedUsers = [];
}
}
if (Array.isArray(authorizedUsers) && authorizedUsers.length > 0) {
for (let i = 0; i < authorizedUsers.length; i++) {
const user = authorizedUsers[i];
console.log("authorized user", user);
const query = `INSERT INTO video_authorized_users (video_id, user_id) VALUES ($1, $2)`;
// SEND EMAIL TO AUTHORIZED USER
const emailQuery = `SELECT email FROM users WHERE id = $1`;
const emailResult = await client.query(emailQuery, [user]);
const email = emailResult.rows[0].email;
const textMessage = `Vous êtes autorisé à visionner une vidéo privée. ${process.env.FRONTEND_URL}/videos/${id}`;
const htmlMessage = `
<!DOCTYPE html>
<html>
<head>
<meta charset="utf-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>Accès à une vidéo privée - Freetube</title>
</head>
<body style="margin: 0; padding: 0; font-family: Arial, sans-serif; background-color: #f4f4f4;">
<div style="max-width: 600px; margin: 0 auto; background-color: #ffffff; border-radius: 8px; overflow: hidden; box-shadow: 0 2px 10px rgba(0,0,0,0.1);">
<!-- Header -->
<div style="background: linear-gradient(135deg, #667eea 0%, #764ba2 100%); padding: 40px 20px; text-align: center;">
<h1 style="color: #ffffff; margin: 0; font-size: 28px; font-weight: bold;">
🔐 Vidéo privée partagée avec vous!
</h1>
</div>
<!-- Content -->
<div style="padding: 40px 30px;">
<h2 style="color: #333333; margin-top: 0; font-size: 24px;">
Bonjour! 👋
</h2>
<p style="color: #666666; font-size: 16px; line-height: 1.6; margin: 20px 0;">
Vous avez été autorisé(e) à visionner une vidéo privée sur <strong>Freetube</strong>!
</p>
<p style="color: #666666; font-size: 16px; line-height: 1.6; margin: 20px 0;">
<strong>On vous a partagé une vidéo privée avec vous. Cliquez sur le bouton ci-dessous pour la regarder :
</p>
<!-- Video Info Box -->
<div style="background-color: #f8f9fa; border: 2px dashed #667eea; border-radius: 8px; padding: 25px; margin: 30px 0;">
<h3 style="color: #333333; font-size: 18px; margin: 0 0 10px 0; text-align: center;">
${video.title}
</h3>
<p style="color: #666666; font-size: 14px; margin: 0 0 20px 0; text-align: center; line-height: 1.4;">
${video.description}
</p>
<div style="text-align: center;">
<a href="${process.env.FRONTEND_URL}/videos/${video.id}" style="background: linear-gradient(135deg, #667eea 0%, #764ba2 100%); color: #ffffff; text-decoration: none; padding: 12px 25px; border-radius: 6px; font-size: 16px; font-weight: bold; display: inline-block;">
Regarder la vidéo
</a>
</div>
</div>
<p style="color: #999999; font-size: 14px; line-height: 1.5; margin: 30px 0 10px 0;">
🔒 Cette vidéo est privée et n'est accessible qu'aux personnes autorisées.
</p>
<p style="color: #999999; font-size: 14px; line-height: 1.5; margin: 10px 0;">
Si vous pensez avoir reçu cet e-mail par erreur, vous pouvez l'ignorer.
</p>
</div>
<!-- Footer -->
<div style="background-color: #f8f9fa; padding: 20px 30px; border-top: 1px solid #eee;">
<p style="color: #999999; font-size: 12px; margin: 0; text-align: center;">
© 2025 Freetube. Tous droits réservés.
</p>
</div>
</div>
</body>
</html>
`;
sendEmail(email, "Invitation à visionner une vidéo privée", textMessage, htmlMessage);
await client.query(query, [id, user]);
}
}
}
logger.write("successfully uploaded video", 200);
await client.end()
res.status(200).json({ "message": "Successfully uploaded video", "id": id });
@ -124,6 +228,11 @@ export async function getById(req, res) {
const tagsResult = await client.query(tagsQuery, [id]);
video.tags = tagsResult.rows.map(tag => tag.name);
// GET AUTHORIZED USERS
const authorizedUsersQuery = `SELECT u.id, u.username, u.picture FROM users u JOIN video_authorized_users vp ON u.id = vp.user_id WHERE vp.video_id = $1`;
const authorizedUsersResult = await client.query(authorizedUsersQuery, [id]);
video.authorizedUsers = authorizedUsersResult.rows;
logger.write("successfully get video " + id, 200);
client.end()
res.status(200).json(video);
@ -489,4 +598,39 @@ export async function addViews(req, res) {
logger.write("successfully added views for video " + id, 200);
await client.end();
res.status(200).json({ "message": "Successfully added views" });
}
export async function updateAuthorizedUsers(req, res) {
const id = req.params.id;
const logger = req.body.logger;
logger.action("try to update authorized users for video " + id);
const { authorizedUsers } = req.body;
console.log(authorizedUsers);
const client = await getClient();
try {
// Remove all existing authorized users
const deleteQuery = `DELETE FROM video_authorized_users WHERE video_id = $1`;
console.log(`DELETE FROM video_authorized_users WHERE video_id = ${id}`);
await client.query(deleteQuery, [id]);
// Add new authorized users
const insertQuery = `INSERT INTO video_authorized_users (video_id, user_id) VALUES ($1, $2)`;
for (let i = 0; i < authorizedUsers.length; i++) {
const user = authorizedUsers[i];
console.log(`INSERT INTO video_authorized_users (video_id, user_id) VALUES (${id}, ${user})`)
await client.query(insertQuery, [id, user]);
}
logger.write("successfully updated authorized users for video " + id, 200);
res.status(200).json({ "message": "Successfully updated authorized users" });
} catch (error) {
logger.write("Error updating authorized users: " + error.message, 500);
res.status(500).json({ error: "Internal server error" });
} finally {
await client.end();
}
}

84
backend/app/middlewares/video.middleware.js

@ -23,6 +23,21 @@ export const VideoCreate = {
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 = {
@ -79,3 +94,72 @@ export async function doVideoExistsParam(req, res, next) {
next()
}
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();
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
}
}
}
next()
}
export async function hasAccess(req, res, next) {
const logger = req.body.logger;
const videoId = req.params.id;
const client = await getClient();
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();
}

19
backend/app/routes/video.route.js

@ -10,7 +10,7 @@ import {
uploadThumbnail,
updateVideo,
toggleLike,
addTags, getSimilarVideos, addViews, getLikesPerDay
addTags, getSimilarVideos, addViews, getLikesPerDay, updateAuthorizedUsers
} from "../controllers/video.controller.js";
import {
doVideoExists,
@ -18,7 +18,9 @@ import {
isOwner,
Video,
VideoCreate,
VideoThumbnail
VideoThumbnail,
doAuthorizedUserExists,
hasAccess
} from "../middlewares/video.middleware.js";
import {Channel, doChannelExistBody, doChannelExists} from "../middlewares/channel.middleware.js";
import {thumbnailUpload, videoUpload} from "../middlewares/file.middleware.js";
@ -27,19 +29,20 @@ import validator from "../middlewares/error.middleware.js";
const router = Router();
// UPLOAD VIDEO
router.post("/", [videoUpload.single('file'), addLogger, isTokenValid, VideoCreate.title, VideoCreate.description, VideoCreate.visibility, VideoCreate.channel, validator, doChannelExistBody, isOwner], upload);
router.post("/", [videoUpload.single('file'), addLogger, isTokenValid, VideoCreate.title, VideoCreate.description, VideoCreate.visibility, VideoCreate.authorizedUsers, VideoCreate.channel, validator, doChannelExistBody, isOwner, doAuthorizedUserExists], upload);
// UPLOAD/UPDATE THUMBNAIL
router.post("/thumbnail", [thumbnailUpload.single('file'), addLogger, isTokenValid, VideoThumbnail.video, Video.channel, validator, doChannelExistBody, isOwner, doVideoExists], uploadThumbnail )
// GET BY ID
router.get("/:id", [addLogger, Video.id, validator, doVideoExistsParam], getById);
router.get("/:id", [addLogger, Video.id, validator, doVideoExistsParam, hasAccess], getById);
// GET BY CHANNEL
router.get("/channel/:id", [addLogger, isTokenValid, Channel.id, validator, doChannelExists], getByChannel);
router.get("/channel/:id", [addLogger, isTokenValid, Channel.id, validator, doChannelExists, hasAccess], getByChannel);
// UPDATE VIDEO DATA
router.put("/:id", [addLogger, isTokenValid, Video.id, VideoCreate.title, VideoCreate.description, VideoCreate.visibility, VideoCreate.channel, validator, doVideoExistsParam, doChannelExistBody, isOwner], update);
// UPDATE VIDEO
router.put("/:id/video", [videoUpload.single("file"), addLogger, isTokenValid, Video.id, Video.channel, validator, doVideoExistsParam, doChannelExistBody, isOwner ], updateVideo);
@ -53,13 +56,15 @@ router.get("/:id/like", [addLogger, isTokenValid, Video.id, validator, doVideoEx
router.put("/:id/tags", [addLogger, isTokenValid, Video.id, Video.tags, validator, doVideoExistsParam, isOwner], addTags);
// GET SIMILAR VIDEOS
router.get("/:id/similar", [addLogger, Video.id, validator, doVideoExistsParam], getSimilarVideos);
router.get("/:id/similar", [addLogger, Video.id, validator, doVideoExistsParam, hasAccess], getSimilarVideos);
// ADD VIEWS
router.get("/:id/views", [addLogger, isTokenValid, Video.id, validator, doVideoExistsParam], addViews);
router.get("/:id/views", [addLogger, isTokenValid, Video.id, validator, doVideoExistsParam, hasAccess], addViews);
// GET LIKE PER DAY
router.get("/:id/likes/day", [addLogger, isTokenValid, Video.id, validator, doVideoExistsParam], getLikesPerDay);
// UPDATE AUTHORIZED USERS
router.put("/:id/authorized-users", [addLogger, isTokenValid, Video.id, VideoCreate.authorizedUsers, validator, doVideoExistsParam, isOwner, doAuthorizedUserExists], updateAuthorizedUsers);
export default router;

7
backend/app/utils/database.js

@ -119,6 +119,13 @@ export async function initDb() {
)`;
await client.query(query);
query = `CREATE TABLE IF NOT EXISTS video_authorized_users (
id SERIAL PRIMARY KEY,
video_id INTEGER NOT NULL REFERENCES videos(id) ON DELETE CASCADE,
user_id INTEGER NOT NULL REFERENCES users(id) ON DELETE CASCADE
)`;
await client.query(query);
} catch (e) {
console.error("Error initializing database:", e);
}

733
backend/logs/access.log

@ -7624,3 +7624,736 @@
[2025-08-18 17:59:00.909] [undefined] GET(/:id/channel): successfully retrieved channel of user 1 with status 200
[2025-08-18 17:59:02.119] [undefined] GET(/search): try to search user by username a
[2025-08-18 17:59:02.123] [undefined] GET(/search): successfully found user with username a with status 200
[2025-08-19 16:50:31.703] [undefined] POST(/): try to register a user with username: astria and email: sachaguerin.sg@gmail.com
[2025-08-19 16:50:32.709] [undefined] POST(/): successfully registered with status 200
[2025-08-19 16:50:44.851] [undefined] POST(/verify-email): try to verify email for sachaguerin.sg@gmail.com with token 8f9c5
[2025-08-19 16:50:44.861] [undefined] POST(/verify-email): successfully verified email for sachaguerin.sg@gmail.com with status 200
[2025-08-19 16:50:53.604] [undefined] POST(/login): failed due to invalid values with status 400
[2025-08-19 16:51:09.256] [undefined] POST(/login): failed due to invalid values with status 400
[2025-08-19 16:51:19.455] [undefined] POST(/login): try to login with username 'astria'
[2025-08-19 16:51:19.508] [undefined] POST(/login): Successfully logged in with status 200
[2025-08-19 16:51:23.577] [undefined] GET(/:id/channel): try to retrieve channel of user 1
[2025-08-19 16:51:23.581] [undefined] GET(/:id/history): try to retrieve history of user 1
[2025-08-19 16:51:23.584] [undefined] GET(/:id/channel): failed to retrieve channel of user 1 because it doesn't exist with status 404
[2025-08-19 16:51:23.588] [undefined] GET(/:id/history): failed to retrieve history of user 1 because it doesn't exist with status 404
[2025-08-19 16:51:23.598] [undefined] GET(/user/:id): Playlists retrieved for user with id 1 with status 200
[2025-08-19 16:51:27.795] [undefined] POST(/): try to create new channel with owner 1 and name astria
[2025-08-19 16:51:27.798] [undefined] POST(/): Successfully created new channel with name astria with status 200
[2025-08-19 16:51:27.811] [undefined] GET(/:id/channel): try to retrieve channel of user 1
[2025-08-19 16:51:27.814] [undefined] GET(/:id/channel): successfully retrieved channel of user 1 with status 200
[2025-08-19 16:51:30.510] [undefined] GET(/:id): try to get channel with id 1
[2025-08-19 16:51:30.526] [undefined] GET(/:id/stats): try to get stats
[2025-08-19 16:51:30.531] [undefined] GET(/:id): Successfully get channel with id 1 with status 200
[2025-08-19 16:51:30.539] [undefined] GET(/:id/stats): Successfully get stats with status 200
[2025-08-19 16:51:33.254] [undefined] GET(/:id/channel): try to retrieve channel of user 1
[2025-08-19 16:51:33.258] [undefined] GET(/:id/channel): successfully retrieved channel of user 1 with status 200
[2025-08-19 16:51:40.046] [undefined] GET(/search): try to search user by username a
[2025-08-19 16:51:40.050] [undefined] GET(/search): successfully found user with username a with status 200
[2025-08-19 16:51:40.285] [undefined] GET(/search): try to search user by username as
[2025-08-19 16:51:40.289] [undefined] GET(/search): successfully found user with username as with status 200
[2025-08-19 16:51:40.470] [undefined] GET(/search): try to search user by username ast
[2025-08-19 16:51:40.474] [undefined] GET(/search): successfully found user with username ast with status 200
[2025-08-19 16:51:40.573] [undefined] GET(/search): try to search user by username astr
[2025-08-19 16:51:40.577] [undefined] GET(/search): successfully found user with username astr with status 200
[2025-08-19 16:51:40.705] [undefined] GET(/search): try to search user by username astri
[2025-08-19 16:51:40.708] [undefined] GET(/search): successfully found user with username astri with status 200
[2025-08-19 17:46:55.010] [undefined] GET(/:id/channel): try to retrieve channel of user 1
[2025-08-19 17:46:55.015] [undefined] GET(/:id/channel): successfully retrieved channel of user 1 with status 200
[2025-08-19 17:47:00.226] [undefined] GET(/search): try to search user by username a
[2025-08-19 17:47:00.229] [undefined] GET(/search): successfully found user with username a with status 200
[2025-08-19 17:47:00.465] [undefined] GET(/search): try to search user by username as
[2025-08-19 17:47:00.469] [undefined] GET(/search): successfully found user with username as with status 200
[2025-08-19 17:47:00.646] [undefined] GET(/search): try to search user by username ast
[2025-08-19 17:47:00.649] [undefined] GET(/search): successfully found user with username ast with status 200
[2025-08-19 17:47:00.741] [undefined] GET(/search): try to search user by username astr
[2025-08-19 17:47:00.744] [undefined] GET(/search): successfully found user with username astr with status 200
[2025-08-19 17:47:00.880] [undefined] GET(/search): try to search user by username astri
[2025-08-19 17:47:00.883] [undefined] GET(/search): successfully found user with username astri with status 200
[2025-08-19 17:47:31.274] [undefined] GET(/:id/channel): try to retrieve channel of user 1
[2025-08-19 17:47:31.277] [undefined] GET(/:id/channel): successfully retrieved channel of user 1 with status 200
[2025-08-19 17:47:32.638] [undefined] GET(/search): try to search user by username a
[2025-08-19 17:47:32.642] [undefined] GET(/search): successfully found user with username a with status 200
[2025-08-19 17:47:59.477] [undefined] GET(/:id/channel): try to retrieve channel of user 1
[2025-08-19 17:47:59.480] [undefined] GET(/:id/channel): successfully retrieved channel of user 1 with status 200
[2025-08-19 17:48:00.360] [undefined] GET(/search): try to search user by username a
[2025-08-19 17:48:00.363] [undefined] GET(/search): successfully found user with username a with status 200
[2025-08-19 17:48:10.809] [undefined] GET(/:id/channel): try to retrieve channel of user 1
[2025-08-19 17:48:10.813] [undefined] GET(/:id/channel): successfully retrieved channel of user 1 with status 200
[2025-08-19 17:48:11.729] [undefined] GET(/search): try to search user by username a
[2025-08-19 17:48:11.732] [undefined] GET(/search): successfully found user with username a with status 200
[2025-08-19 17:48:28.248] [undefined] GET(/search): try to search user by username as
[2025-08-19 17:48:28.252] [undefined] GET(/search): successfully found user with username as with status 200
[2025-08-19 17:48:50.152] [undefined] GET(/:id/channel): try to retrieve channel of user 1
[2025-08-19 17:48:50.156] [undefined] GET(/:id/channel): successfully retrieved channel of user 1 with status 200
[2025-08-19 17:48:51.115] [undefined] GET(/search): try to search user by username a
[2025-08-19 17:48:51.119] [undefined] GET(/search): successfully found user with username a with status 200
[2025-08-19 17:48:55.267] [undefined] GET(/search): try to search user by username a
[2025-08-19 17:48:55.270] [undefined] GET(/search): successfully found user with username a with status 200
[2025-08-19 17:51:38.016] [undefined] GET(/:id/channel): try to retrieve channel of user 1
[2025-08-19 17:51:38.020] [undefined] GET(/:id/channel): successfully retrieved channel of user 1 with status 200
[2025-08-19 17:51:39.279] [undefined] GET(/search): try to search user by username a
[2025-08-19 17:51:39.282] [undefined] GET(/search): successfully found user with username a with status 200
[2025-08-19 17:51:40.911] [undefined] GET(/search): try to search user by username a
[2025-08-19 17:51:40.915] [undefined] GET(/search): successfully found user with username a with status 200
[2025-08-19 17:51:53.055] [undefined] GET(/:id/channel): try to retrieve channel of user 1
[2025-08-19 17:51:53.059] [undefined] GET(/:id/channel): successfully retrieved channel of user 1 with status 200
[2025-08-19 17:51:53.750] [undefined] GET(/search): try to search user by username a
[2025-08-19 17:51:53.754] [undefined] GET(/search): successfully found user with username a with status 200
[2025-08-19 17:51:54.033] [undefined] GET(/search): try to search user by username as
[2025-08-19 17:51:54.036] [undefined] GET(/search): successfully found user with username as with status 200
[2025-08-19 17:51:56.357] [undefined] GET(/search): try to search user by username a
[2025-08-19 17:51:56.360] [undefined] GET(/search): successfully found user with username a with status 200
[2025-08-19 17:52:06.577] [undefined] GET(/:id/channel): try to retrieve channel of user 1
[2025-08-19 17:52:06.582] [undefined] GET(/:id/channel): successfully retrieved channel of user 1 with status 200
[2025-08-19 17:52:07.598] [undefined] GET(/search): try to search user by username a
[2025-08-19 17:52:07.602] [undefined] GET(/search): successfully found user with username a with status 200
[2025-08-19 17:52:09.890] [undefined] GET(/search): try to search user by username a
[2025-08-19 17:52:09.893] [undefined] GET(/search): successfully found user with username a with status 200
[2025-08-19 17:52:50.407] [undefined] GET(/:id/channel): try to retrieve channel of user 1
[2025-08-19 17:52:50.411] [undefined] GET(/:id/channel): successfully retrieved channel of user 1 with status 200
[2025-08-19 17:52:52.482] [undefined] GET(/search): try to search user by username a
[2025-08-19 17:52:52.486] [undefined] GET(/search): successfully found user with username a with status 200
[2025-08-19 18:09:16.637] [undefined] GET(/search): try to search user by username a
[2025-08-19 18:09:16.640] [undefined] GET(/search): successfully found user with username a with status 200
[2025-08-19 18:09:52.553] [undefined] POST(/): try to upload video with status undefined
[2025-08-19 18:09:52.559] [undefined] POST(/): successfully uploaded video with status 200
[2025-08-19 18:09:52.636] [undefined] POST(/thumbnail): try to add thumbnail to video 1
[2025-08-19 18:09:52.640] [undefined] POST(/thumbnail): successfully uploaded thumbnail with status 200
[2025-08-19 18:09:52.656] [undefined] PUT(/:id/tags): try to add tags to video 1
[2025-08-19 18:09:52.666] [undefined] PUT(/:id/tags): successfully added tags to video 1 with status 200
[2025-08-19 18:10:20.468] [undefined] POST(/): try to upload video with status undefined
[2025-08-19 18:10:20.473] [undefined] POST(/): successfully uploaded video with status 200
[2025-08-19 18:10:20.560] [undefined] POST(/thumbnail): try to add thumbnail to video 2
[2025-08-19 18:10:20.563] [undefined] POST(/thumbnail): successfully uploaded thumbnail with status 200
[2025-08-19 18:10:20.582] [undefined] PUT(/:id/tags): try to add tags to video 2
[2025-08-19 18:10:20.590] [undefined] PUT(/:id/tags): Tag sa already exists for video 2 with status 200
[2025-08-19 18:10:20.594] [undefined] PUT(/:id/tags): successfully added tags to video 2 with status 200
[2025-08-19 18:10:34.430] [undefined] GET(/:id/channel): try to retrieve channel of user 1
[2025-08-19 18:10:34.434] [undefined] GET(/:id/channel): successfully retrieved channel of user 1 with status 200
[2025-08-19 18:10:39.472] [undefined] GET(/search): try to search user by username a
[2025-08-19 18:10:39.475] [undefined] GET(/search): successfully found user with username a with status 200
[2025-08-19 18:10:48.026] [undefined] POST(/): try to upload video with status undefined
[2025-08-19 18:10:48.036] [undefined] POST(/): successfully uploaded video with status 200
[2025-08-19 18:10:48.238] [undefined] POST(/thumbnail): try to add thumbnail to video 3
[2025-08-19 18:10:48.243] [undefined] POST(/thumbnail): successfully uploaded thumbnail with status 200
[2025-08-19 18:10:48.260] [undefined] PUT(/:id/tags): try to add tags to video 3
[2025-08-19 18:10:48.268] [undefined] PUT(/:id/tags): Tag sa already exists for video 3 with status 200
[2025-08-19 18:10:48.272] [undefined] PUT(/:id/tags): successfully added tags to video 3 with status 200
[2025-08-19 18:11:37.923] [undefined] POST(/): failed due to invalid values with status 400
[2025-08-19 18:11:49.155] [undefined] POST(/): failed due to invalid values with status 400
[2025-08-19 18:13:15.887] [undefined] POST(/): failed due to invalid values with status 400
[2025-08-19 18:15:41.313] [undefined] POST(/): try to upload video with status undefined
[2025-08-19 18:15:41.318] [undefined] POST(/): successfully uploaded video with status 200
[2025-08-19 18:15:41.402] [undefined] POST(/thumbnail): try to add thumbnail to video 4
[2025-08-19 18:15:41.405] [undefined] POST(/thumbnail): successfully uploaded thumbnail with status 200
[2025-08-19 18:15:41.429] [undefined] PUT(/:id/tags): try to add tags to video 4
[2025-08-19 18:15:41.437] [undefined] PUT(/:id/tags): Tag sa already exists for video 4 with status 200
[2025-08-19 18:15:41.441] [undefined] PUT(/:id/tags): successfully added tags to video 4 with status 200
[2025-08-19 18:16:20.905] [undefined] POST(/): try to upload video with status undefined
[2025-08-19 18:16:20.933] [undefined] POST(/): successfully uploaded video with status 200
[2025-08-19 18:16:21.025] [undefined] POST(/thumbnail): try to add thumbnail to video 5
[2025-08-19 18:16:21.029] [undefined] POST(/thumbnail): successfully uploaded thumbnail with status 200
[2025-08-19 18:16:21.054] [undefined] PUT(/:id/tags): try to add tags to video 5
[2025-08-19 18:16:21.063] [undefined] PUT(/:id/tags): Tag sa already exists for video 5 with status 200
[2025-08-19 18:16:21.068] [undefined] PUT(/:id/tags): successfully added tags to video 5 with status 200
[2025-08-19 18:17:10.822] [undefined] POST(/): try to upload video with status undefined
[2025-08-19 18:17:10.834] [undefined] POST(/): successfully uploaded video with status 200
[2025-08-19 18:17:10.916] [undefined] POST(/thumbnail): try to add thumbnail to video 6
[2025-08-19 18:17:10.920] [undefined] POST(/thumbnail): successfully uploaded thumbnail with status 200
[2025-08-19 18:17:10.943] [undefined] PUT(/:id/tags): try to add tags to video 6
[2025-08-19 18:17:10.951] [undefined] PUT(/:id/tags): Tag sa already exists for video 6 with status 200
[2025-08-19 18:17:10.955] [undefined] PUT(/:id/tags): successfully added tags to video 6 with status 200
[2025-08-19 18:18:05.738] [undefined] POST(/): try to upload video with status undefined
[2025-08-19 18:18:05.744] [undefined] POST(/): successfully uploaded video with status 200
[2025-08-19 18:18:05.824] [undefined] POST(/thumbnail): try to add thumbnail to video 7
[2025-08-19 18:18:05.827] [undefined] POST(/thumbnail): successfully uploaded thumbnail with status 200
[2025-08-19 18:18:05.850] [undefined] PUT(/:id/tags): try to add tags to video 7
[2025-08-19 18:18:05.858] [undefined] PUT(/:id/tags): Tag sa already exists for video 7 with status 200
[2025-08-19 18:18:05.863] [undefined] PUT(/:id/tags): successfully added tags to video 7 with status 200
[2025-08-19 18:18:48.664] [undefined] POST(/): try to upload video with status undefined
[2025-08-19 18:18:48.671] [undefined] POST(/): successfully uploaded video with status 200
[2025-08-19 18:18:48.756] [undefined] POST(/thumbnail): try to add thumbnail to video 8
[2025-08-19 18:18:48.759] [undefined] POST(/thumbnail): successfully uploaded thumbnail with status 200
[2025-08-19 18:18:48.785] [undefined] PUT(/:id/tags): try to add tags to video 8
[2025-08-19 18:18:48.793] [undefined] PUT(/:id/tags): Tag sa already exists for video 8 with status 200
[2025-08-19 18:18:48.798] [undefined] PUT(/:id/tags): successfully added tags to video 8 with status 200
[2025-08-19 18:20:25.872] [undefined] POST(/): try to upload video with status undefined
[2025-08-19 18:20:25.877] [undefined] POST(/): successfully uploaded video with status 200
[2025-08-19 18:20:25.959] [undefined] POST(/thumbnail): try to add thumbnail to video 9
[2025-08-19 18:20:25.962] [undefined] POST(/thumbnail): successfully uploaded thumbnail with status 200
[2025-08-19 18:20:25.984] [undefined] PUT(/:id/tags): try to add tags to video 9
[2025-08-19 18:20:25.992] [undefined] PUT(/:id/tags): Tag sa already exists for video 9 with status 200
[2025-08-19 18:20:25.996] [undefined] PUT(/:id/tags): successfully added tags to video 9 with status 200
[2025-08-19 18:21:11.157] [undefined] POST(/): try to upload video with status undefined
[2025-08-19 18:21:11.164] [undefined] POST(/): successfully uploaded video with status 200
[2025-08-19 18:21:11.249] [undefined] POST(/thumbnail): try to add thumbnail to video 10
[2025-08-19 18:21:11.252] [undefined] POST(/thumbnail): successfully uploaded thumbnail with status 200
[2025-08-19 18:21:11.280] [undefined] PUT(/:id/tags): try to add tags to video 10
[2025-08-19 18:21:11.288] [undefined] PUT(/:id/tags): Tag sa already exists for video 10 with status 200
[2025-08-19 18:21:11.292] [undefined] PUT(/:id/tags): successfully added tags to video 10 with status 200
[2025-08-19 18:30:49.537] [undefined] GET(/:id): try to get video 1
[2025-08-19 18:30:49.547] [undefined] GET(/user/:id): Playlists retrieved for user with id 1 with status 200
[2025-08-19 18:30:49.565] [undefined] GET(/:id): successfully get video 1 with status 200
[2025-08-19 18:30:49.575] [undefined] GET(/:id/similar): try to get similar videos for video 1
[2025-08-19 18:30:49.591] [undefined] GET(/:id/similar): successfully get similar videos for video 1 with status 200
[2025-08-19 18:30:49.610] [undefined] GET(/:id/views): try to add views for video 1
[2025-08-19 18:30:49.625] [undefined] GET(/:id/views): successfully added views for video 1 with status 200
[2025-08-19 18:31:42.637] [undefined] GET(/:id): failed because video not found with status 404
[2025-08-19 18:31:42.648] [undefined] GET(/user/:id): Playlists retrieved for user with id 1 with status 200
[2025-08-19 18:31:42.653] [undefined] GET(/:id/similar): failed because video not found with status 404
[2025-08-19 18:31:42.664] [undefined] GET(/:id/views): failed because video not found with status 404
[2025-08-19 18:31:47.656] [undefined] GET(/:id/channel): try to retrieve channel of user 1
[2025-08-19 18:31:47.660] [undefined] GET(/:id/channel): successfully retrieved channel of user 1 with status 200
[2025-08-19 18:31:47.664] [undefined] GET(/:id/history): try to retrieve history of user 1
[2025-08-19 18:31:47.669] [undefined] GET(/:id/history): failed to retrieve history of user 1 because it doesn't exist with status 404
[2025-08-19 18:31:47.679] [undefined] GET(/user/:id): Playlists retrieved for user with id 1 with status 200
[2025-08-19 18:32:24.652] [undefined] GET(/:id): try to get channel with id 1
[2025-08-19 18:32:24.662] [undefined] GET(/:id/stats): try to get stats
[2025-08-19 18:32:24.667] [undefined] GET(/:id): Successfully get channel with id 1 with status 200
[2025-08-19 18:32:24.675] [undefined] GET(/:id/stats): Successfully get stats with status 200
[2025-08-19 18:32:25.767] [undefined] GET(/:id/channel): try to retrieve channel of user 1
[2025-08-19 18:32:25.771] [undefined] GET(/:id/channel): successfully retrieved channel of user 1 with status 200
[2025-08-19 18:33:12.054] [undefined] GET(/search): try to search user by username a
[2025-08-19 18:33:12.058] [undefined] GET(/search): successfully found user with username a with status 200
[2025-08-19 18:33:25.364] [undefined] POST(/): try to upload video with status undefined
[2025-08-19 18:33:25.372] [undefined] POST(/): successfully uploaded video with status 200
[2025-08-19 18:33:25.453] [undefined] POST(/thumbnail): try to add thumbnail to video 11
[2025-08-19 18:33:25.456] [undefined] POST(/thumbnail): successfully uploaded thumbnail with status 200
[2025-08-19 18:33:25.474] [undefined] PUT(/:id/tags): try to add tags to video 11
[2025-08-19 18:33:25.488] [undefined] PUT(/:id/tags): successfully added tags to video 11 with status 200
[2025-08-19 18:33:30.850] [undefined] GET(/:id): try to get video 11
[2025-08-19 18:33:30.860] [undefined] GET(/user/:id): Playlists retrieved for user with id 1 with status 200
[2025-08-19 18:33:30.867] [undefined] GET(/:id): successfully get video 11 with status 200
[2025-08-19 18:33:30.876] [undefined] GET(/:id/similar): try to get similar videos for video 11
[2025-08-19 18:33:30.888] [undefined] GET(/:id/similar): successfully get similar videos for video 11 with status 200
[2025-08-19 18:33:30.904] [undefined] GET(/:id/views): try to add views for video 11
[2025-08-19 18:33:30.918] [undefined] GET(/:id/views): successfully added views for video 11 with status 200
[2025-08-19 18:33:38.304] [undefined] GET(/:id/like): try to toggle like on video 11
[2025-08-19 18:33:38.312] [undefined] GET(/:id/like): no likes found adding likes for video 11 with status 200
[2025-08-19 18:33:39.877] [undefined] POST(/:id): Video added to playlist with id 1 with status 200
[2025-08-19 18:33:41.409] [undefined] POST(/:id/subscribe): try to toggle subscription for channel with id 1
[2025-08-19 18:33:41.417] [undefined] POST(/:id/subscribe): Successfully subscribed to channel with status 200
[2025-08-19 18:33:46.037] [undefined] GET(/:id/channel): try to retrieve channel of user 1
[2025-08-19 18:33:46.041] [undefined] GET(/:id/channel): successfully retrieved channel of user 1 with status 200
[2025-08-19 18:33:46.048] [undefined] GET(/:id/history): try to retrieve history of user 1
[2025-08-19 18:33:46.052] [undefined] GET(/:id/history): successfully retrieved history of user 1 with status 200
[2025-08-19 18:33:46.056] [undefined] GET(/user/:id): Playlists retrieved for user with id 1 with status 200
[2025-08-19 18:33:46.647] [undefined] GET(/:id): try to get channel with id 1
[2025-08-19 18:33:46.657] [undefined] GET(/:id/stats): try to get stats
[2025-08-19 18:33:46.662] [undefined] GET(/:id): Successfully get channel with id 1 with status 200
[2025-08-19 18:33:46.672] [undefined] GET(/:id/stats): Successfully get stats with status 200
[2025-08-19 18:33:47.714] [undefined] GET(/:id): try to get video 11
[2025-08-19 18:33:47.717] [undefined] GET(/:id/likes/day): try to get likes per day
[2025-08-19 18:33:47.729] [undefined] GET(/:id/likes/day): successfully retrieved likes per day with status 200
[2025-08-19 18:33:47.734] [undefined] GET(/:id): successfully get video 11 with status 200
[2025-08-19 18:35:42.063] [undefined] GET(/:id): try to get video 11
[2025-08-19 18:35:42.068] [undefined] GET(/:id/likes/day): try to get likes per day
[2025-08-19 18:35:42.079] [undefined] GET(/:id/likes/day): successfully retrieved likes per day with status 200
[2025-08-19 18:35:42.084] [undefined] GET(/:id): successfully get video 11 with status 200
[2025-08-19 18:36:03.707] [undefined] GET(/:id/likes/day): try to get likes per day
[2025-08-19 18:36:03.710] [undefined] GET(/:id): try to get video 11
[2025-08-19 18:36:03.721] [undefined] GET(/:id/likes/day): successfully retrieved likes per day with status 200
[2025-08-19 18:36:03.727] [undefined] GET(/:id): successfully get video 11 with status 200
[2025-08-19 18:37:10.825] [undefined] GET(/:id): try to get video 11
[2025-08-19 18:37:10.829] [undefined] GET(/:id/likes/day): try to get likes per day
[2025-08-19 18:37:10.839] [undefined] GET(/:id/likes/day): successfully retrieved likes per day with status 200
[2025-08-19 18:37:14.577] [undefined] GET(/:id/likes/day): try to get likes per day
[2025-08-19 18:37:14.580] [undefined] GET(/:id): try to get video 11
[2025-08-19 18:37:14.592] [undefined] GET(/:id/likes/day): successfully retrieved likes per day with status 200
[2025-08-19 18:38:02.999] [undefined] GET(/:id/likes/day): try to get likes per day
[2025-08-19 18:38:03.002] [undefined] GET(/:id): try to get video 11
[2025-08-19 18:38:03.034] [undefined] GET(/:id/likes/day): successfully retrieved likes per day with status 200
[2025-08-19 18:38:03.041] [undefined] GET(/:id): successfully get video 11 with status 200
[2025-08-19 18:38:21.751] [undefined] GET(/:id/likes/day): try to get likes per day
[2025-08-19 18:38:21.754] [undefined] GET(/:id): try to get video 11
[2025-08-19 18:38:21.766] [undefined] GET(/:id/likes/day): successfully retrieved likes per day with status 200
[2025-08-19 18:38:21.773] [undefined] GET(/:id): successfully get video 11 with status 200
[2025-08-19 18:39:10.233] [undefined] GET(/:id): try to get video 11
[2025-08-19 18:39:10.236] [undefined] GET(/:id/likes/day): try to get likes per day
[2025-08-19 18:39:10.247] [undefined] GET(/:id/likes/day): successfully retrieved likes per day with status 200
[2025-08-19 18:39:10.253] [undefined] GET(/:id): successfully get video 11 with status 200
[2025-08-19 18:39:21.826] [undefined] GET(/:id): try to get video 11
[2025-08-19 18:39:21.829] [undefined] GET(/:id/likes/day): try to get likes per day
[2025-08-19 18:39:21.841] [undefined] GET(/:id/likes/day): successfully retrieved likes per day with status 200
[2025-08-19 18:39:21.847] [undefined] GET(/:id): successfully get video 11 with status 200
[2025-08-19 18:41:07.602] [undefined] GET(/:id): try to get video 11
[2025-08-19 18:41:07.606] [undefined] GET(/:id/likes/day): try to get likes per day
[2025-08-19 18:41:07.618] [undefined] GET(/:id/likes/day): successfully retrieved likes per day with status 200
[2025-08-19 18:41:07.624] [undefined] GET(/:id): successfully get video 11 with status 200
[2025-08-19 18:41:28.238] [undefined] GET(/:id): try to get video 11
[2025-08-19 18:41:28.242] [undefined] GET(/:id/likes/day): try to get likes per day
[2025-08-19 18:41:28.253] [undefined] GET(/:id/likes/day): successfully retrieved likes per day with status 200
[2025-08-19 18:41:28.259] [undefined] GET(/:id): successfully get video 11 with status 200
[2025-08-20 17:38:45.740] [undefined] GET(/:id/channel): try to retrieve channel of user 1
[2025-08-20 17:38:45.743] [undefined] GET(/:id/history): try to retrieve history of user 1
[2025-08-20 17:38:45.749] [undefined] GET(/:id/channel): successfully retrieved channel of user 1 with status 200
[2025-08-20 17:38:45.755] [undefined] GET(/:id/history): successfully retrieved history of user 1 with status 200
[2025-08-20 17:38:45.764] [undefined] GET(/user/:id): Playlists retrieved for user with id 1 with status 200
[2025-08-20 17:38:49.831] [undefined] GET(/:id): try to get channel with id 1
[2025-08-20 17:38:49.843] [undefined] GET(/:id/stats): try to get stats
[2025-08-20 17:38:49.847] [undefined] GET(/:id): Successfully get channel with id 1 with status 200
[2025-08-20 17:38:49.855] [undefined] GET(/:id/stats): Successfully get stats with status 200
[2025-08-20 17:38:51.435] [undefined] GET(/:id): try to get video 11
[2025-08-20 17:38:51.437] [undefined] GET(/:id/likes/day): try to get likes per day
[2025-08-20 17:38:51.448] [undefined] GET(/:id/likes/day): successfully retrieved likes per day with status 200
[2025-08-20 17:38:51.454] [undefined] GET(/:id): successfully get video 11 with status 200
[2025-08-20 17:45:30.859] [undefined] GET(/:id): try to get video 11
[2025-08-20 17:45:30.865] [undefined] GET(/:id/likes/day): try to get likes per day
[2025-08-20 17:45:30.874] [undefined] GET(/:id): successfully get video 11 with status 200
[2025-08-20 17:45:30.878] [undefined] GET(/:id/likes/day): successfully retrieved likes per day with status 200
[2025-08-20 17:46:49.844] [undefined] GET(/:id/likes/day): try to get likes per day
[2025-08-20 17:46:49.847] [undefined] GET(/:id): try to get video 11
[2025-08-20 17:46:49.858] [undefined] GET(/:id/likes/day): successfully retrieved likes per day with status 200
[2025-08-20 17:46:49.865] [undefined] GET(/:id): successfully get video 11 with status 200
[2025-08-20 17:46:51.040] [undefined] GET(/search): try to search user by username a
[2025-08-20 17:46:51.044] [undefined] GET(/search): successfully found user with username a with status 200
[2025-08-20 17:47:56.099] [undefined] GET(/:id/likes/day): try to get likes per day
[2025-08-20 17:47:56.103] [undefined] GET(/:id): try to get video 11
[2025-08-20 17:47:56.114] [undefined] GET(/:id/likes/day): successfully retrieved likes per day with status 200
[2025-08-20 17:47:56.119] [undefined] GET(/:id): successfully get video 11 with status 200
[2025-08-20 17:47:58.471] [undefined] GET(/search): try to search user by username a
[2025-08-20 17:47:58.475] [undefined] GET(/search): successfully found user with username a with status 200
[2025-08-20 17:48:02.406] [undefined] GET(/search): try to search user by username as
[2025-08-20 17:48:02.409] [undefined] GET(/search): successfully found user with username as with status 200
[2025-08-20 17:48:02.648] [undefined] GET(/search): try to search user by username a
[2025-08-20 17:48:02.651] [undefined] GET(/search): successfully found user with username a with status 200
[2025-08-20 18:02:01.655] [undefined] GET(/:id): try to get video 11
[2025-08-20 18:02:01.658] [undefined] GET(/:id/likes/day): try to get likes per day
[2025-08-20 18:02:01.669] [undefined] GET(/:id/likes/day): successfully retrieved likes per day with status 200
[2025-08-20 18:02:01.676] [undefined] GET(/:id): successfully get video 11 with status 200
[2025-08-20 18:02:03.971] [undefined] GET(/search): try to search user by username a
[2025-08-20 18:02:03.977] [undefined] GET(/search): successfully found user with username a with status 200
[2025-08-20 18:02:09.242] [undefined] GET(/:id): try to get video 11
[2025-08-20 18:02:09.255] [undefined] GET(/:id): successfully get video 11 with status 200
[2025-08-20 18:02:09.261] [undefined] GET(/:id/likes/day): try to get likes per day
[2025-08-20 18:02:09.275] [undefined] GET(/:id/likes/day): successfully retrieved likes per day with status 200
[2025-08-20 18:02:40.257] [undefined] PUT(/:id/tags): try to add tags to video 11
[2025-08-20 18:02:40.268] [undefined] PUT(/:id/tags): Tag CS2 already exists for video 11 with status 200
[2025-08-20 18:02:40.272] [undefined] PUT(/:id/tags): Tag CSGO already exists for video 11 with status 200
[2025-08-20 18:02:40.277] [undefined] PUT(/:id/tags): Tag Squeezie already exists for video 11 with status 200
[2025-08-20 18:02:40.281] [undefined] PUT(/:id/tags): successfully added tags to video 11 with status 200
[2025-08-20 18:02:44.040] [undefined] PUT(/:id/tags): try to add tags to video 11
[2025-08-20 18:02:44.049] [undefined] PUT(/:id/tags): Tag CS2 already exists for video 11 with status 200
[2025-08-20 18:02:44.054] [undefined] PUT(/:id/tags): Tag CSGO already exists for video 11 with status 200
[2025-08-20 18:02:44.059] [undefined] PUT(/:id/tags): Tag Squeezie already exists for video 11 with status 200
[2025-08-20 18:02:44.066] [undefined] PUT(/:id/tags): successfully added tags to video 11 with status 200
[2025-08-20 18:35:54.696] [undefined] GET(/:id): try to get video 11
[2025-08-20 18:35:54.699] [undefined] GET(/:id/likes/day): try to get likes per day
[2025-08-20 18:35:54.710] [undefined] GET(/:id/likes/day): successfully retrieved likes per day with status 200
[2025-08-20 18:35:54.716] [undefined] GET(/:id): successfully get video 11 with status 200
[2025-08-20 18:36:12.459] [undefined] GET(/:id): try to get video 11
[2025-08-20 18:36:12.472] [undefined] GET(/:id/likes/day): try to get likes per day
[2025-08-20 18:36:12.479] [undefined] GET(/:id): successfully get video 11 with status 200
[2025-08-20 18:36:12.486] [undefined] GET(/:id/likes/day): successfully retrieved likes per day with status 200
[2025-08-20 18:36:18.031] [undefined] GET(/:id): try to get video 11
[2025-08-20 18:36:18.036] [undefined] GET(/:id/likes/day): try to get likes per day
[2025-08-20 18:36:18.048] [undefined] GET(/:id/likes/day): successfully retrieved likes per day with status 200
[2025-08-20 18:36:18.055] [undefined] GET(/:id): successfully get video 11 with status 200
[2025-08-20 18:37:05.587] [undefined] GET(/:id/likes/day): try to get likes per day
[2025-08-20 18:37:05.590] [undefined] GET(/:id): try to get video 11
[2025-08-20 18:37:05.602] [undefined] GET(/:id/likes/day): successfully retrieved likes per day with status 200
[2025-08-20 18:37:05.608] [undefined] GET(/:id): successfully get video 11 with status 200
[2025-08-20 18:37:22.780] [undefined] GET(/:id): try to get video 11
[2025-08-20 18:37:22.784] [undefined] GET(/:id/likes/day): try to get likes per day
[2025-08-20 18:37:22.795] [undefined] GET(/:id/likes/day): successfully retrieved likes per day with status 200
[2025-08-20 18:37:22.800] [undefined] GET(/:id): successfully get video 11 with status 200
[2025-08-20 18:37:42.008] [undefined] GET(/:id): try to get video 11
[2025-08-20 18:37:42.021] [undefined] GET(/:id/likes/day): try to get likes per day
[2025-08-20 18:37:42.028] [undefined] GET(/:id): successfully get video 11 with status 200
[2025-08-20 18:37:42.035] [undefined] GET(/:id/likes/day): successfully retrieved likes per day with status 200
[2025-08-20 18:37:59.051] [undefined] GET(/:id): try to get video 11
[2025-08-20 18:37:59.058] [undefined] GET(/:id/likes/day): try to get likes per day
[2025-08-20 18:37:59.067] [undefined] GET(/:id): successfully get video 11 with status 200
[2025-08-20 18:37:59.072] [undefined] GET(/:id/likes/day): successfully retrieved likes per day with status 200
[2025-08-20 18:38:20.881] [undefined] GET(/:id): try to get video 11
[2025-08-20 18:38:20.894] [undefined] GET(/:id/likes/day): try to get likes per day
[2025-08-20 18:38:20.899] [undefined] GET(/:id): successfully get video 11 with status 200
[2025-08-20 18:38:20.907] [undefined] GET(/:id/likes/day): successfully retrieved likes per day with status 200
[2025-08-20 18:38:24.327] [undefined] GET(/:id): try to get video 11
[2025-08-20 18:38:24.338] [undefined] GET(/:id): successfully get video 11 with status 200
[2025-08-20 18:38:24.341] [undefined] GET(/user/:id): Playlists retrieved for user with id 1 with status 200
[2025-08-20 18:38:24.351] [undefined] GET(/:id/similar): try to get similar videos for video 11
[2025-08-20 18:38:24.364] [undefined] GET(/:id/similar): successfully get similar videos for video 11 with status 200
[2025-08-20 18:38:24.391] [undefined] GET(/:id/views): try to add views for video 11
[2025-08-20 18:38:24.400] [undefined] GET(/:id/views): successfully added views for video 11 with status 200
[2025-08-20 18:38:31.467] [undefined] GET(/:id/likes/day): try to get likes per day
[2025-08-20 18:38:31.471] [undefined] GET(/:id): try to get video 11
[2025-08-20 18:38:31.483] [undefined] GET(/:id/likes/day): successfully retrieved likes per day with status 200
[2025-08-20 18:38:31.489] [undefined] GET(/:id): successfully get video 11 with status 200
[2025-08-20 18:38:52.804] [undefined] GET(/:id/likes/day): try to get likes per day
[2025-08-20 18:38:52.808] [undefined] GET(/:id): try to get video 11
[2025-08-20 18:38:52.820] [undefined] GET(/:id/likes/day): successfully retrieved likes per day with status 200
[2025-08-20 18:38:52.826] [undefined] GET(/:id): successfully get video 11 with status 200
[2025-08-20 18:38:53.675] [undefined] GET(/search): try to search user by username a
[2025-08-20 18:38:53.680] [undefined] GET(/search): successfully found user with username a with status 200
[2025-08-20 18:39:14.264] [undefined] GET(/:id): try to get video 11
[2025-08-20 18:39:14.267] [undefined] GET(/:id/likes/day): try to get likes per day
[2025-08-20 18:39:14.279] [undefined] GET(/:id/likes/day): successfully retrieved likes per day with status 200
[2025-08-20 18:39:14.285] [undefined] GET(/:id): successfully get video 11 with status 200
[2025-08-20 18:39:34.063] [undefined] GET(/:id): try to get video 11
[2025-08-20 18:39:34.074] [undefined] GET(/:id/likes/day): try to get likes per day
[2025-08-20 18:39:34.081] [undefined] GET(/:id): successfully get video 11 with status 200
[2025-08-20 18:39:34.088] [undefined] GET(/:id/likes/day): successfully retrieved likes per day with status 200
[2025-08-20 18:39:44.733] [undefined] GET(/:id): try to get video 11
[2025-08-20 18:39:44.737] [undefined] GET(/:id/likes/day): try to get likes per day
[2025-08-20 18:39:44.749] [undefined] GET(/:id/likes/day): successfully retrieved likes per day with status 200
[2025-08-20 18:39:44.756] [undefined] GET(/:id): successfully get video 11 with status 200
[2025-08-20 18:40:25.085] [undefined] GET(/:id): try to get video 11
[2025-08-20 18:40:25.090] [undefined] GET(/:id/likes/day): try to get likes per day
[2025-08-20 18:40:25.099] [undefined] GET(/:id/likes/day): successfully retrieved likes per day with status 200
[2025-08-20 18:40:25.103] [undefined] GET(/:id): successfully get video 11 with status 200
[2025-08-20 18:41:11.226] [undefined] GET(/:id/likes/day): try to get likes per day
[2025-08-20 18:41:11.230] [undefined] GET(/:id): try to get video 11
[2025-08-20 18:41:11.242] [undefined] GET(/:id/likes/day): successfully retrieved likes per day with status 200
[2025-08-20 18:41:11.247] [undefined] GET(/:id): successfully get video 11 with status 200
[2025-08-20 18:41:23.586] [undefined] GET(/:id): try to get video 11
[2025-08-20 18:41:23.589] [undefined] GET(/:id/likes/day): try to get likes per day
[2025-08-20 18:41:23.601] [undefined] GET(/:id/likes/day): successfully retrieved likes per day with status 200
[2025-08-20 18:41:23.607] [undefined] GET(/:id): successfully get video 11 with status 200
[2025-08-20 18:41:49.036] [undefined] GET(/:id): try to get video 11
[2025-08-20 18:41:49.040] [undefined] GET(/:id/likes/day): try to get likes per day
[2025-08-20 18:41:49.053] [undefined] GET(/:id/likes/day): successfully retrieved likes per day with status 200
[2025-08-20 18:41:49.059] [undefined] GET(/:id): successfully get video 11 with status 200
[2025-08-20 18:41:57.988] [undefined] GET(/:id/likes/day): try to get likes per day
[2025-08-20 18:41:57.991] [undefined] GET(/:id): try to get video 11
[2025-08-20 18:41:58.002] [undefined] GET(/:id/likes/day): successfully retrieved likes per day with status 200
[2025-08-20 18:41:58.009] [undefined] GET(/:id): successfully get video 11 with status 200
[2025-08-20 18:42:16.719] [undefined] GET(/:id/likes/day): try to get likes per day
[2025-08-20 18:42:16.722] [undefined] GET(/:id): try to get video 11
[2025-08-20 18:42:16.734] [undefined] GET(/:id/likes/day): successfully retrieved likes per day with status 200
[2025-08-20 18:42:16.740] [undefined] GET(/:id): successfully get video 11 with status 200
[2025-08-20 18:42:28.808] [undefined] GET(/:id): try to get video 11
[2025-08-20 18:42:28.813] [undefined] GET(/:id/likes/day): try to get likes per day
[2025-08-20 18:42:28.823] [undefined] GET(/:id): successfully get video 11 with status 200
[2025-08-20 18:42:28.827] [undefined] GET(/:id/likes/day): successfully retrieved likes per day with status 200
[2025-08-20 18:43:05.588] [undefined] GET(/:id): try to get video 11
[2025-08-20 18:43:05.591] [undefined] GET(/:id/likes/day): try to get likes per day
[2025-08-20 18:43:05.609] [undefined] GET(/:id/likes/day): successfully retrieved likes per day with status 200
[2025-08-20 18:43:05.616] [undefined] GET(/:id): successfully get video 11 with status 200
[2025-08-20 18:43:59.851] [undefined] GET(/:id): try to get video 11
[2025-08-20 18:43:59.862] [undefined] GET(/:id/likes/day): try to get likes per day
[2025-08-20 18:43:59.870] [undefined] GET(/:id): successfully get video 11 with status 200
[2025-08-20 18:43:59.877] [undefined] GET(/:id/likes/day): successfully retrieved likes per day with status 200
[2025-08-20 18:44:01.475] [undefined] PUT(/:id/authorized-users): try to update authorized users for video 11
[2025-08-20 18:44:01.484] [undefined] PUT(/:id/authorized-users): successfully updated authorized users for video 11 with status 200
[2025-08-20 18:44:03.494] [undefined] GET(/:id): try to get video 11
[2025-08-20 18:44:03.498] [undefined] GET(/:id/likes/day): try to get likes per day
[2025-08-20 18:44:03.508] [undefined] GET(/:id/likes/day): successfully retrieved likes per day with status 200
[2025-08-20 18:44:03.512] [undefined] GET(/:id): successfully get video 11 with status 200
[2025-08-20 18:44:05.260] [undefined] GET(/search): try to search user by username a
[2025-08-20 18:44:05.264] [undefined] GET(/search): successfully found user with username a with status 200
[2025-08-20 18:44:26.525] [undefined] GET(/:id/likes/day): try to get likes per day
[2025-08-20 18:44:26.529] [undefined] GET(/:id): try to get video 11
[2025-08-20 18:44:26.541] [undefined] GET(/:id/likes/day): successfully retrieved likes per day with status 200
[2025-08-20 18:44:26.547] [undefined] GET(/:id): successfully get video 11 with status 200
[2025-08-20 18:44:28.395] [undefined] GET(/search): try to search user by username a
[2025-08-20 18:44:28.401] [undefined] GET(/search): successfully found user with username a with status 200
[2025-08-20 18:44:42.183] [undefined] GET(/:id/likes/day): try to get likes per day
[2025-08-20 18:44:42.189] [undefined] GET(/:id): try to get video 11
[2025-08-20 18:44:42.199] [undefined] GET(/:id/likes/day): successfully retrieved likes per day with status 200
[2025-08-20 18:44:42.205] [undefined] GET(/:id): successfully get video 11 with status 200
[2025-08-20 18:44:44.521] [undefined] GET(/search): try to search user by username a
[2025-08-20 18:44:44.526] [undefined] GET(/search): successfully found user with username a with status 200
[2025-08-20 18:45:18.672] [undefined] GET(/:id): try to get video 11
[2025-08-20 18:45:18.677] [undefined] GET(/:id/likes/day): try to get likes per day
[2025-08-20 18:45:18.707] [undefined] GET(/:id/likes/day): successfully retrieved likes per day with status 200
[2025-08-20 18:45:18.713] [undefined] GET(/:id): successfully get video 11 with status 200
[2025-08-20 18:45:19.810] [undefined] GET(/search): try to search user by username a
[2025-08-20 18:45:19.816] [undefined] GET(/search): successfully found user with username a with status 200
[2025-08-20 18:45:21.387] [undefined] PUT(/:id/authorized-users): try to update authorized users for video 11
[2025-08-20 18:45:21.396] [undefined] PUT(/:id/authorized-users): Error updating authorized users: null value in column "user_id" of relation "video_authorized_users" violates not-null constraint with status 500
[2025-08-20 18:47:45.836] [undefined] GET(/search): try to search user by username a
[2025-08-20 18:47:45.842] [undefined] GET(/search): successfully found user with username a with status 200
[2025-08-20 18:47:49.720] [undefined] PUT(/:id/authorized-users): try to update authorized users for video 11
[2025-08-20 18:47:49.729] [undefined] PUT(/:id/authorized-users): Error updating authorized users: null value in column "user_id" of relation "video_authorized_users" violates not-null constraint with status 500
[2025-08-20 18:48:11.345] [undefined] GET(/:id/likes/day): try to get likes per day
[2025-08-20 18:48:11.348] [undefined] GET(/:id): try to get video 11
[2025-08-20 18:48:11.361] [undefined] GET(/:id/likes/day): successfully retrieved likes per day with status 200
[2025-08-20 18:48:11.367] [undefined] GET(/:id): successfully get video 11 with status 200
[2025-08-20 18:48:12.079] [undefined] GET(/search): try to search user by username a
[2025-08-20 18:48:12.083] [undefined] GET(/search): successfully found user with username a with status 200
[2025-08-20 18:48:13.768] [undefined] PUT(/:id/authorized-users): try to update authorized users for video 11
[2025-08-20 18:48:13.776] [undefined] PUT(/:id/authorized-users): Error updating authorized users: null value in column "user_id" of relation "video_authorized_users" violates not-null constraint with status 500
[2025-08-20 18:49:02.787] [undefined] PUT(/:id/authorized-users): try to update authorized users for video 11
[2025-08-20 18:49:02.797] [undefined] PUT(/:id/authorized-users): successfully updated authorized users for video 11 with status 200
[2025-08-20 18:49:05.674] [undefined] GET(/search): try to search user by username a
[2025-08-20 18:49:05.678] [undefined] GET(/search): successfully found user with username a with status 200
[2025-08-20 18:49:10.645] [undefined] PUT(/:id/authorized-users): try to update authorized users for video 11
[2025-08-20 18:49:10.657] [undefined] PUT(/:id/authorized-users): successfully updated authorized users for video 11 with status 200
[2025-08-20 18:49:13.914] [undefined] GET(/:id): try to get video 11
[2025-08-20 18:49:13.918] [undefined] GET(/:id/likes/day): try to get likes per day
[2025-08-20 18:49:13.930] [undefined] GET(/:id/likes/day): successfully retrieved likes per day with status 200
[2025-08-20 18:49:13.936] [undefined] GET(/:id): successfully get video 11 with status 200
[2025-08-20 18:49:18.941] [undefined] PUT(/:id/authorized-users): try to update authorized users for video 11
[2025-08-20 18:49:18.949] [undefined] PUT(/:id/authorized-users): successfully updated authorized users for video 11 with status 200
[2025-08-20 18:49:19.663] [undefined] GET(/search): try to search user by username a
[2025-08-20 18:49:19.667] [undefined] GET(/search): successfully found user with username a with status 200
[2025-08-20 18:49:24.635] [undefined] PUT(/:id/authorized-users): try to update authorized users for video 11
[2025-08-20 18:49:24.650] [undefined] PUT(/:id/authorized-users): successfully updated authorized users for video 11 with status 200
[2025-08-20 18:49:37.611] [undefined] GET(/:id/likes/day): try to get likes per day
[2025-08-20 18:49:37.614] [undefined] GET(/:id): try to get video 11
[2025-08-20 18:49:37.627] [undefined] GET(/:id/likes/day): successfully retrieved likes per day with status 200
[2025-08-20 18:49:37.634] [undefined] GET(/:id): successfully get video 11 with status 200
[2025-08-20 18:49:39.397] [undefined] PUT(/:id/authorized-users): try to update authorized users for video 11
[2025-08-20 18:49:39.405] [undefined] PUT(/:id/authorized-users): successfully updated authorized users for video 11 with status 200
[2025-08-20 18:49:40.021] [undefined] GET(/search): try to search user by username a
[2025-08-20 18:49:40.025] [undefined] GET(/search): successfully found user with username a with status 200
[2025-08-20 18:49:41.573] [undefined] PUT(/:id/authorized-users): try to update authorized users for video 11
[2025-08-20 18:49:41.582] [undefined] PUT(/:id/authorized-users): successfully updated authorized users for video 11 with status 200
[2025-08-20 18:49:58.339] [undefined] GET(/:id): try to get video 11
[2025-08-20 18:49:58.346] [undefined] GET(/:id/likes/day): try to get likes per day
[2025-08-20 18:49:58.355] [undefined] GET(/:id): successfully get video 11 with status 200
[2025-08-20 18:49:58.361] [undefined] GET(/:id/likes/day): successfully retrieved likes per day with status 200
[2025-08-20 18:49:59.991] [undefined] PUT(/:id/authorized-users): try to update authorized users for video 11
[2025-08-20 18:49:59.999] [undefined] PUT(/:id/authorized-users): successfully updated authorized users for video 11 with status 200
[2025-08-20 18:50:00.647] [undefined] GET(/search): try to search user by username a
[2025-08-20 18:50:00.650] [undefined] GET(/search): successfully found user with username a with status 200
[2025-08-20 18:50:02.527] [undefined] PUT(/:id/authorized-users): try to update authorized users for video 11
[2025-08-20 18:50:02.554] [undefined] PUT(/:id/authorized-users): successfully updated authorized users for video 11 with status 200
[2025-08-20 18:51:15.624] [undefined] GET(/:id): try to get video 11
[2025-08-20 18:51:15.628] [undefined] GET(/:id/likes/day): try to get likes per day
[2025-08-20 18:51:15.640] [undefined] GET(/:id/likes/day): successfully retrieved likes per day with status 200
[2025-08-20 18:51:15.645] [undefined] GET(/:id): successfully get video 11 with status 200
[2025-08-20 18:51:17.660] [undefined] GET(/:id/channel): try to retrieve channel of user 1
[2025-08-20 18:51:17.664] [undefined] GET(/:id/channel): successfully retrieved channel of user 1 with status 200
[2025-08-20 18:51:17.668] [undefined] GET(/:id/history): try to retrieve history of user 1
[2025-08-20 18:51:17.673] [undefined] GET(/:id/history): successfully retrieved history of user 1 with status 200
[2025-08-20 18:51:17.684] [undefined] GET(/user/:id): Playlists retrieved for user with id 1 with status 200
[2025-08-20 18:51:18.298] [undefined] GET(/:id): try to get channel with id 1
[2025-08-20 18:51:18.309] [undefined] GET(/:id/stats): try to get stats
[2025-08-20 18:51:18.314] [undefined] GET(/:id): Successfully get channel with id 1 with status 200
[2025-08-20 18:51:18.321] [undefined] GET(/:id/stats): Successfully get stats with status 200
[2025-08-20 18:51:19.216] [undefined] GET(/:id/channel): try to retrieve channel of user 1
[2025-08-20 18:51:19.219] [undefined] GET(/:id/channel): successfully retrieved channel of user 1 with status 200
[2025-08-20 18:51:29.478] [undefined] POST(/): try to upload video with status undefined
[2025-08-20 18:51:29.485] [undefined] POST(/): successfully uploaded video with status 200
[2025-08-20 18:51:29.566] [undefined] POST(/thumbnail): try to add thumbnail to video 12
[2025-08-20 18:51:29.573] [undefined] POST(/thumbnail): successfully uploaded thumbnail with status 200
[2025-08-20 18:51:29.594] [undefined] PUT(/:id/tags): try to add tags to video 12
[2025-08-20 18:51:29.604] [undefined] PUT(/:id/tags): successfully added tags to video 12 with status 200
[2025-08-20 18:51:30.916] [undefined] GET(/:id/channel): try to retrieve channel of user 1
[2025-08-20 18:51:30.920] [undefined] GET(/:id/history): try to retrieve history of user 1
[2025-08-20 18:51:30.922] [undefined] GET(/:id/channel): successfully retrieved channel of user 1 with status 200
[2025-08-20 18:51:30.926] [undefined] GET(/:id/history): successfully retrieved history of user 1 with status 200
[2025-08-20 18:51:30.934] [undefined] GET(/user/:id): Playlists retrieved for user with id 1 with status 200
[2025-08-20 18:51:32.526] [undefined] GET(/:id): try to get channel with id 1
[2025-08-20 18:51:32.537] [undefined] GET(/:id/stats): try to get stats
[2025-08-20 18:51:32.541] [undefined] GET(/:id): Successfully get channel with id 1 with status 200
[2025-08-20 18:51:32.550] [undefined] GET(/:id/stats): Successfully get stats with status 200
[2025-08-20 18:51:33.588] [undefined] GET(/:id): try to get video 12
[2025-08-20 18:51:33.592] [undefined] GET(/:id/likes/day): try to get likes per day
[2025-08-20 18:51:33.603] [undefined] GET(/:id/likes/day): successfully retrieved likes per day with status 200
[2025-08-20 18:51:33.608] [undefined] GET(/:id): successfully get video 12 with status 200
[2025-08-20 18:51:40.247] [undefined] GET(/:id): try to get video 11
[2025-08-20 18:51:40.259] [undefined] GET(/user/:id): Playlists retrieved for user with id 1 with status 200
[2025-08-20 18:51:40.263] [undefined] GET(/:id): successfully get video 11 with status 200
[2025-08-20 18:51:40.277] [undefined] GET(/:id/similar): try to get similar videos for video 11
[2025-08-20 18:51:40.289] [undefined] GET(/:id/similar): successfully get similar videos for video 11 with status 200
[2025-08-20 18:51:40.315] [undefined] GET(/:id/views): try to add views for video 11
[2025-08-20 18:51:40.325] [undefined] GET(/:id/views): successfully added views for video 11 with status 200
[2025-08-20 18:51:44.448] [undefined] GET(/:id/like): try to toggle like on video 11
[2025-08-20 18:51:44.458] [undefined] GET(/:id/like): likes found, removing like for video 11 with status 200
[2025-08-20 18:51:44.912] [undefined] GET(/:id/like): try to toggle like on video 11
[2025-08-20 18:51:44.921] [undefined] GET(/:id/like): no likes found adding likes for video 11 with status 200
[2025-08-20 18:53:00.124] [undefined] POST(/): try to register a user with username: sacha and email: thelolshow974@gmail.com
[2025-08-20 18:53:01.068] [undefined] POST(/): successfully registered with status 200
[2025-08-20 18:53:27.277] [undefined] POST(/verify-email): try to verify email for thelolshow974@gmail.com with token 44046
[2025-08-20 18:53:27.287] [undefined] POST(/verify-email): successfully verified email for thelolshow974@gmail.com with status 200
[2025-08-20 18:53:37.170] [undefined] POST(/login): failed due to invalid values with status 400
[2025-08-20 18:54:00.492] [undefined] POST(/login): failed due to invalid values with status 400
[2025-08-20 18:54:05.877] [undefined] POST(/login): failed due to invalid values with status 400
[2025-08-20 18:54:12.816] [undefined] POST(/login): try to login with username 'sacha'
[2025-08-20 18:54:12.866] [undefined] POST(/login): Successfully logged in with status 200
[2025-08-20 18:54:22.722] [undefined] GET(/:id): try to get video 11
[2025-08-20 18:54:22.734] [undefined] GET(/user/:id): Playlists retrieved for user with id 2 with status 200
[2025-08-20 18:54:22.740] [undefined] GET(/:id): successfully get video 11 with status 200
[2025-08-20 18:54:22.751] [undefined] GET(/:id/similar): try to get similar videos for video 11
[2025-08-20 18:54:22.765] [undefined] GET(/:id/similar): successfully get similar videos for video 11 with status 200
[2025-08-20 18:54:22.783] [undefined] GET(/:id/views): try to add views for video 11
[2025-08-20 18:54:22.796] [undefined] GET(/:id/views): successfully added views for video 11 with status 200
[2025-08-20 18:59:18.332] [undefined] GET(/user/:id): Playlists retrieved for user with id 2 with status 200
[2025-08-20 18:59:23.959] [undefined] GET(/user/:id): Playlists retrieved for user with id 2 with status 200
[2025-08-20 19:00:08.055] [undefined] GET(/user/:id): Playlists retrieved for user with id 2 with status 200
[2025-08-20 19:00:43.038] [undefined] GET(/user/:id): Playlists retrieved for user with id 2 with status 200
[2025-08-20 19:03:20.114] [undefined] GET(/user/:id): Playlists retrieved for user with id 2 with status 200
[2025-08-20 19:03:30.944] [undefined] GET(/user/:id): Playlists retrieved for user with id 2 with status 200
[2025-08-20 19:03:46.729] [undefined] GET(/:id): failed because user is not authorized with status 403
[2025-08-20 19:03:46.733] [undefined] GET(/user/:id): Playlists retrieved for user with id 2 with status 200
[2025-08-20 19:03:46.776] [undefined] GET(/:id/views): failed because user is not authorized with status 403
[2025-08-20 19:04:41.036] [undefined] GET(/:id): failed because user is not authorized with status 403
[2025-08-20 19:04:41.040] [undefined] GET(/user/:id): Playlists retrieved for user with id 2 with status 200
[2025-08-20 19:05:00.712] [undefined] GET(/user/:id): Playlists retrieved for user with id 2 with status 200
[2025-08-20 19:05:00.716] [undefined] GET(/:id): failed because user is not authorized with status 403
[2025-08-20 19:05:00.763] [undefined] GET(/:id/views): failed because user is not authorized with status 403
[2025-08-20 19:05:06.854] [undefined] GET(/:id): failed because user is not authorized with status 403
[2025-08-20 19:05:06.858] [undefined] GET(/user/:id): Playlists retrieved for user with id 2 with status 200
[2025-08-20 19:05:06.889] [undefined] GET(/:id/views): failed because user is not authorized with status 403
[2025-08-20 19:05:08.248] [undefined] GET(/:id): try to get video 12
[2025-08-20 19:05:08.251] [undefined] GET(/user/:id): Playlists retrieved for user with id 2 with status 200
[2025-08-20 19:05:08.262] [undefined] GET(/:id): successfully get video 12 with status 200
[2025-08-20 19:05:08.279] [undefined] GET(/:id/similar): try to get similar videos for video 12
[2025-08-20 19:05:08.292] [undefined] GET(/:id/similar): successfully get similar videos for video 12 with status 200
[2025-08-20 19:05:08.314] [undefined] GET(/:id/views): try to add views for video 12
[2025-08-20 19:05:08.328] [undefined] GET(/:id/views): successfully added views for video 12 with status 200
[2025-08-20 19:05:10.522] [undefined] GET(/:id): failed because user is not authorized with status 403
[2025-08-20 19:05:10.526] [undefined] GET(/user/:id): Playlists retrieved for user with id 2 with status 200
[2025-08-20 19:05:10.557] [undefined] GET(/:id/views): failed because user is not authorized with status 403
[2025-08-20 19:05:21.932] [undefined] POST(/login): try to login with username 'astria'
[2025-08-20 19:05:21.984] [undefined] POST(/login): Successfully logged in with status 200
[2025-08-20 19:05:23.932] [undefined] GET(/:id/channel): try to retrieve channel of user 1
[2025-08-20 19:05:23.936] [undefined] GET(/:id/channel): successfully retrieved channel of user 1 with status 200
[2025-08-20 19:05:23.941] [undefined] GET(/:id/history): try to retrieve history of user 1
[2025-08-20 19:05:23.946] [undefined] GET(/:id/history): successfully retrieved history of user 1 with status 200
[2025-08-20 19:05:23.956] [undefined] GET(/user/:id): Playlists retrieved for user with id 1 with status 200
[2025-08-20 19:05:24.823] [undefined] GET(/:id): try to get channel with id 1
[2025-08-20 19:05:24.835] [undefined] GET(/:id/stats): try to get stats
[2025-08-20 19:05:24.840] [undefined] GET(/:id): Successfully get channel with id 1 with status 200
[2025-08-20 19:05:24.849] [undefined] GET(/:id/stats): Successfully get stats with status 200
[2025-08-20 19:05:26.215] [undefined] GET(/:id/likes/day): try to get likes per day
[2025-08-20 19:05:26.227] [undefined] GET(/:id): try to get video 11
[2025-08-20 19:05:26.230] [undefined] GET(/:id/likes/day): successfully retrieved likes per day with status 200
[2025-08-20 19:05:26.240] [undefined] GET(/:id): successfully get video 11 with status 200
[2025-08-20 19:05:28.154] [undefined] GET(/search): try to search user by username s
[2025-08-20 19:05:28.160] [undefined] GET(/search): successfully found user with username s with status 200
[2025-08-20 19:05:28.330] [undefined] GET(/search): try to search user by username sa
[2025-08-20 19:05:28.335] [undefined] GET(/search): successfully found user with username sa with status 200
[2025-08-20 19:05:38.951] [undefined] POST(/login): try to login with username 'sacha'
[2025-08-20 19:05:39.003] [undefined] POST(/login): Successfully logged in with status 200
[2025-08-20 19:05:40.150] [undefined] GET(/:id): failed because user is not authorized with status 403
[2025-08-20 19:05:40.154] [undefined] GET(/user/:id): Playlists retrieved for user with id 2 with status 200
[2025-08-20 19:05:40.190] [undefined] GET(/:id/views): failed because user is not authorized with status 403
[2025-08-20 19:05:52.482] [undefined] GET(/:id): failed because user is not authorized with status 403
[2025-08-20 19:05:52.486] [undefined] GET(/user/:id): Playlists retrieved for user with id 2 with status 200
[2025-08-20 19:05:52.522] [undefined] GET(/:id/views): failed because user is not authorized with status 403
[2025-08-20 19:06:24.972] [undefined] GET(/:id): failed because user is not authorized with status 403
[2025-08-20 19:06:24.975] [undefined] GET(/user/:id): Playlists retrieved for user with id 2 with status 200
[2025-08-20 19:06:25.009] [undefined] GET(/:id/views): failed because user is not authorized with status 403
[2025-08-20 19:06:45.416] [undefined] POST(/login): try to login with username 'astria'
[2025-08-20 19:06:45.467] [undefined] POST(/login): Successfully logged in with status 200
[2025-08-20 19:06:46.977] [undefined] GET(/:id/channel): try to retrieve channel of user 1
[2025-08-20 19:06:46.980] [undefined] GET(/:id/history): try to retrieve history of user 1
[2025-08-20 19:06:46.983] [undefined] GET(/:id/channel): successfully retrieved channel of user 1 with status 200
[2025-08-20 19:06:46.988] [undefined] GET(/:id/history): successfully retrieved history of user 1 with status 200
[2025-08-20 19:06:47.004] [undefined] GET(/user/:id): Playlists retrieved for user with id 1 with status 200
[2025-08-20 19:06:48.280] [undefined] GET(/:id): try to get channel with id 1
[2025-08-20 19:06:48.293] [undefined] GET(/:id/stats): try to get stats
[2025-08-20 19:06:48.298] [undefined] GET(/:id): Successfully get channel with id 1 with status 200
[2025-08-20 19:06:48.306] [undefined] GET(/:id/stats): Successfully get stats with status 200
[2025-08-20 19:06:49.874] [undefined] GET(/:id/likes/day): try to get likes per day
[2025-08-20 19:06:49.889] [undefined] GET(/:id): try to get video 11
[2025-08-20 19:06:49.893] [undefined] GET(/:id/likes/day): successfully retrieved likes per day with status 200
[2025-08-20 19:06:49.904] [undefined] GET(/:id): successfully get video 11 with status 200
[2025-08-20 19:06:51.790] [undefined] GET(/search): try to search user by username s
[2025-08-20 19:06:51.793] [undefined] GET(/search): successfully found user with username s with status 200
[2025-08-20 19:08:02.813] [undefined] GET(/search): try to search user by username sacha
[2025-08-20 19:08:02.817] [undefined] GET(/search): successfully found user with username sacha with status 200
[2025-08-20 19:09:14.120] [undefined] GET(/:id/likes/day): try to get likes per day
[2025-08-20 19:09:14.132] [undefined] GET(/:id): try to get video 11
[2025-08-20 19:09:14.135] [undefined] GET(/:id/likes/day): successfully retrieved likes per day with status 200
[2025-08-20 19:09:14.147] [undefined] GET(/:id): successfully get video 11 with status 200
[2025-08-20 19:09:15.375] [undefined] GET(/search): try to search user by username s
[2025-08-20 19:09:15.379] [undefined] GET(/search): successfully found user with username s with status 200
[2025-08-20 19:09:17.129] [undefined] PUT(/:id/authorized-users): try to update authorized users for video 11
[2025-08-20 19:09:17.139] [undefined] PUT(/:id/authorized-users): successfully updated authorized users for video 11 with status 200
[2025-08-20 19:09:19.758] [undefined] GET(/:id/likes/day): try to get likes per day
[2025-08-20 19:09:19.768] [undefined] GET(/:id): try to get video 11
[2025-08-20 19:09:19.772] [undefined] GET(/:id/likes/day): successfully retrieved likes per day with status 200
[2025-08-20 19:09:19.782] [undefined] GET(/:id): successfully get video 11 with status 200
[2025-08-20 19:09:27.005] [undefined] GET(/search): try to search user by username s
[2025-08-20 19:09:27.009] [undefined] GET(/search): successfully found user with username s with status 200
[2025-08-20 19:09:28.823] [undefined] PUT(/:id/authorized-users): try to update authorized users for video 11
[2025-08-20 19:09:28.831] [undefined] PUT(/:id/authorized-users): successfully updated authorized users for video 11 with status 200
[2025-08-20 19:09:51.055] [undefined] GET(/:id/likes/day): try to get likes per day
[2025-08-20 19:09:51.067] [undefined] GET(/:id): try to get video 11
[2025-08-20 19:09:51.071] [undefined] GET(/:id/likes/day): successfully retrieved likes per day with status 200
[2025-08-20 19:09:51.083] [undefined] GET(/:id): successfully get video 11 with status 200
[2025-08-20 19:11:19.136] [undefined] GET(/search): try to search user by username s
[2025-08-20 19:11:19.140] [undefined] GET(/search): successfully found user with username s with status 200
[2025-08-20 19:11:21.265] [undefined] PUT(/:id/authorized-users): try to update authorized users for video 11
[2025-08-20 19:11:21.275] [undefined] PUT(/:id/authorized-users): successfully updated authorized users for video 11 with status 200
[2025-08-20 19:13:19.229] [undefined] GET(/:id/likes/day): try to get likes per day
[2025-08-20 19:13:19.241] [undefined] GET(/:id): try to get video 11
[2025-08-20 19:13:19.244] [undefined] GET(/:id/likes/day): successfully retrieved likes per day with status 200
[2025-08-20 19:13:19.255] [undefined] GET(/:id): successfully get video 11 with status 200
[2025-08-20 19:13:20.095] [undefined] GET(/search): try to search user by username s
[2025-08-20 19:13:20.100] [undefined] GET(/search): successfully found user with username s with status 200
[2025-08-20 19:13:20.110] [undefined] GET(/search): try to search user by username sq
[2025-08-20 19:13:20.116] [undefined] GET(/search): no user found with username sq with status 404
[2025-08-20 19:13:21.488] [undefined] GET(/search): try to search user by username s
[2025-08-20 19:13:21.491] [undefined] GET(/search): successfully found user with username s with status 200
[2025-08-20 19:13:21.707] [undefined] GET(/search): try to search user by username sa
[2025-08-20 19:13:21.711] [undefined] GET(/search): successfully found user with username sa with status 200
[2025-08-20 19:13:22.932] [undefined] PUT(/:id/authorized-users): try to update authorized users for video 11
[2025-08-20 19:13:22.942] [undefined] PUT(/:id/authorized-users): successfully updated authorized users for video 11 with status 200
[2025-08-20 19:13:37.018] [undefined] POST(/login): try to login with username 'sacha'
[2025-08-20 19:13:37.069] [undefined] POST(/login): Successfully logged in with status 200
[2025-08-20 19:13:38.705] [undefined] GET(/:id): try to get video 11
[2025-08-20 19:13:38.709] [undefined] GET(/user/:id): Playlists retrieved for user with id 2 with status 200
[2025-08-20 19:13:38.719] [undefined] GET(/:id): successfully get video 11 with status 200
[2025-08-20 19:13:38.738] [undefined] GET(/:id/similar): failed because no token provided with status 401
[2025-08-20 19:13:38.762] [undefined] GET(/:id/views): try to add views for video 11
[2025-08-20 19:13:38.772] [undefined] GET(/:id/views): successfully added views for video 11 with status 200
[2025-08-20 19:19:28.651] [undefined] GET(/:id): try to get channel with id 1
[2025-08-20 19:19:28.663] [undefined] GET(/:id): Successfully get channel with id 1 with status 200
[2025-08-20 19:19:28.681] [undefined] GET(/:id/channel/subscribed): check if user 2 is subscribed to channel 1
[2025-08-20 19:19:28.688] [undefined] GET(/:id/channel/subscribed): user 2 is not subscribed to channel 1 with status 200
[2025-08-20 19:25:39.807] [undefined] GET(/:id/channel): try to retrieve channel of user 2
[2025-08-20 19:25:39.813] [undefined] GET(/:id/channel): failed to retrieve channel of user 2 because it doesn't exist with status 404
[2025-08-20 19:25:39.818] [undefined] GET(/:id/history): try to retrieve history of user 2
[2025-08-20 19:25:39.824] [undefined] GET(/:id/history): successfully retrieved history of user 2 with status 200
[2025-08-20 19:25:39.834] [undefined] GET(/user/:id): Playlists retrieved for user with id 2 with status 200
[2025-08-20 19:25:44.286] [undefined] POST(/): try to create new channel with owner 2 and name sacha
[2025-08-20 19:25:44.289] [undefined] POST(/): Successfully created new channel with name sacha with status 200
[2025-08-20 19:25:44.300] [undefined] GET(/:id/channel): try to retrieve channel of user 2
[2025-08-20 19:25:44.304] [undefined] GET(/:id/channel): successfully retrieved channel of user 2 with status 200
[2025-08-20 19:25:45.115] [undefined] GET(/:id): try to get channel with id 2
[2025-08-20 19:25:45.127] [undefined] GET(/:id/stats): try to get stats
[2025-08-20 19:25:45.131] [undefined] GET(/:id): Successfully get channel with id 2 with status 200
[2025-08-20 19:25:45.139] [undefined] GET(/:id/stats): Successfully get stats with status 200
[2025-08-20 19:25:46.051] [undefined] GET(/:id/channel): try to retrieve channel of user 2
[2025-08-20 19:25:46.055] [undefined] GET(/:id/channel): successfully retrieved channel of user 2 with status 200
[2025-08-20 19:25:58.216] [undefined] GET(/search): try to search user by username a
[2025-08-20 19:25:58.220] [undefined] GET(/search): successfully found user with username a with status 200
[2025-08-20 19:26:10.194] [undefined] POST(/): try to upload video with status undefined
[2025-08-20 19:26:51.145] [undefined] POST(/): try to upload video with status undefined
[2025-08-20 19:26:51.163] [undefined] POST(/): successfully uploaded video with status 200
[2025-08-20 19:26:51.250] [undefined] POST(/thumbnail): try to add thumbnail to video 14
[2025-08-20 19:26:51.254] [undefined] POST(/thumbnail): successfully uploaded thumbnail with status 200
[2025-08-20 19:26:51.304] [undefined] PUT(/:id/tags): try to add tags to video 14
[2025-08-20 19:26:51.315] [undefined] PUT(/:id/tags): successfully added tags to video 14 with status 200
[2025-08-20 19:27:28.048] [undefined] POST(/): try to upload video with status undefined
[2025-08-20 19:27:28.081] [undefined] POST(/): successfully uploaded video with status 200
[2025-08-20 19:27:28.191] [undefined] POST(/thumbnail): try to add thumbnail to video 15
[2025-08-20 19:27:28.197] [undefined] POST(/thumbnail): successfully uploaded thumbnail with status 200
[2025-08-20 19:27:28.222] [undefined] PUT(/:id/tags): try to add tags to video 15
[2025-08-20 19:27:28.231] [undefined] PUT(/:id/tags): Tag csgo already exists for video 15 with status 200
[2025-08-20 19:27:28.236] [undefined] PUT(/:id/tags): successfully added tags to video 15 with status 200
[2025-08-20 19:29:54.451] [undefined] POST(/): try to upload video with status undefined
[2025-08-20 19:29:54.468] [undefined] POST(/): successfully uploaded video with status 200
[2025-08-20 19:29:54.576] [undefined] POST(/thumbnail): try to add thumbnail to video 16
[2025-08-20 19:29:54.581] [undefined] POST(/thumbnail): successfully uploaded thumbnail with status 200
[2025-08-20 19:29:54.606] [undefined] PUT(/:id/tags): try to add tags to video 16
[2025-08-20 19:29:54.615] [undefined] PUT(/:id/tags): Tag csgo already exists for video 16 with status 200
[2025-08-20 19:29:54.620] [undefined] PUT(/:id/tags): successfully added tags to video 16 with status 200
[2025-08-20 19:30:18.925] [undefined] POST(/): try to upload video with status undefined
[2025-08-20 19:30:18.938] [undefined] POST(/): successfully uploaded video with status 200
[2025-08-20 19:30:19.056] [undefined] POST(/thumbnail): try to add thumbnail to video 17
[2025-08-20 19:30:19.061] [undefined] POST(/thumbnail): successfully uploaded thumbnail with status 200
[2025-08-20 19:30:19.086] [undefined] PUT(/:id/tags): try to add tags to video 17
[2025-08-20 19:30:19.095] [undefined] PUT(/:id/tags): Tag csgo already exists for video 17 with status 200
[2025-08-20 19:30:19.100] [undefined] PUT(/:id/tags): successfully added tags to video 17 with status 200
[2025-08-20 19:31:31.875] [undefined] POST(/): try to upload video with status undefined
[2025-08-20 19:31:31.885] [undefined] POST(/): successfully uploaded video with status 200
[2025-08-20 19:31:31.987] [undefined] POST(/thumbnail): try to add thumbnail to video 18
[2025-08-20 19:31:31.990] [undefined] POST(/thumbnail): successfully uploaded thumbnail with status 200
[2025-08-20 19:31:32.014] [undefined] PUT(/:id/tags): try to add tags to video 18
[2025-08-20 19:31:32.022] [undefined] PUT(/:id/tags): Tag csgo already exists for video 18 with status 200
[2025-08-20 19:31:32.026] [undefined] PUT(/:id/tags): successfully added tags to video 18 with status 200
[2025-08-20 19:34:17.736] [undefined] POST(/): try to upload video with status undefined
[2025-08-20 19:34:42.939] [undefined] POST(/): try to upload video with status undefined
[2025-08-20 19:34:42.956] [undefined] POST(/): successfully uploaded video with status 200
[2025-08-20 19:34:43.059] [undefined] POST(/thumbnail): try to add thumbnail to video 20
[2025-08-20 19:34:43.063] [undefined] POST(/thumbnail): successfully uploaded thumbnail with status 200
[2025-08-20 19:34:43.088] [undefined] PUT(/:id/tags): try to add tags to video 20
[2025-08-20 19:34:43.096] [undefined] PUT(/:id/tags): Tag csgo already exists for video 20 with status 200
[2025-08-20 19:34:43.100] [undefined] PUT(/:id/tags): successfully added tags to video 20 with status 200

2
frontend/src/components/UserCard.jsx

@ -2,7 +2,7 @@
export default function UserCard({ user, onSubmit, doShowControls, control }) {
return (
<div className="glassmorphism flex items-center justify-between p-2">
<div className="glassmorphism flex items-center justify-between p-2" id={user.id} >
<div className="flex items-center gap-4">
<img src={user.picture || '/default-profile.png'} alt={`${user.username}'s profile`} className="w-10 h-10 rounded-full mr-2" />
<span className="text-white text-lg font-montserrat font-semibold">{user.username}</span>

27
frontend/src/pages/AddVideo.jsx

@ -72,6 +72,7 @@ export default function AddVideo() {
formData.append("description", videoDescription);
formData.append("channel", channel.id.toString());
formData.append("visibility", visibility);
formData.append("authorizedUsers", JSON.stringify(authorizedUsers.map(user => user.id)));
formData.append("file", videoFile);
const request = await uploadVideo(formData, token, addAlert);
@ -124,7 +125,18 @@ export default function AddVideo() {
}
const onAuthorizedUserAdd = (user) => {
// Verify if user is not already authorized
if (authorizedUsers.find((u) => u.id === user.id)) {
addAlert('error', 'Utilisateur déjà autorisé.');
setSearchUser("")
setSearchResults([]);
return;
}
setAuthorizedUsers([...authorizedUsers, user]);
setSearchResults([]);
setSearchUser("")
};
const onAuthorizedUserRemove = (user) => {
@ -205,14 +217,14 @@ export default function AddVideo() {
{
visibility == "private" && (
<div className="mb-4">
<div className="mb-4 glassmorphism p-4">
<label className="block text-white text-xl font-montserrat font-semibold mb-2" htmlFor="authorizedUsers">Utilisateurs autorisés</label>
<div>
<div className="mb-4">
<input
type="text"
id="authorizedUsers"
name="authorizedUsers"
className="w-full p-2 mb-4 glassmorphism focus:outline-none font-inter text-xl text-white"
className="w-full p-2 mb-2 glassmorphism focus:outline-none font-inter text-xl text-white"
placeholder="Rechercher un utilisateur"
value={searchUser}
onChange={(e) => setSearchUser(e.target.value)}
@ -236,8 +248,11 @@ export default function AddVideo() {
))}
</div>
</div>
<div className="max-h-40 overflow-y-auto">
{authorizedUsers.map((user, index) => (
{authorizedUsers.length > 0 ? authorizedUsers.map((user, index) => (
<UserCard
user={user}
onSubmit={onAuthorizedUserRemove}
@ -249,7 +264,9 @@ export default function AddVideo() {
</button>
}
/>
))}
)) : (
<p className="text-white">Aucun utilisateur autorisé</p>
)}
</div>
</div>
)

120
frontend/src/pages/ManageVideo.jsx

@ -5,7 +5,9 @@ import {useEffect, useState} from "react";
import LinearGraph from "../components/LinearGraph.jsx";
import Comment from "../components/Comment.jsx";
import Tag from "../components/Tag.jsx";
import {getVideoById, getLikesPerDay, updateVideo, updateVideoFile, uploadThumbnail, uploadTags} from "../services/video.service.js";
import UserCard from "../components/UserCard.jsx";
import {getVideoById, getLikesPerDay, updateVideo, updateVideoFile, uploadThumbnail, uploadTags, updateAuthorizedUsers} from "../services/video.service.js";
import {searchByUsername} from "../services/user.service.js";
export default function ManageVideo() {
@ -24,6 +26,8 @@ export default function ManageVideo() {
const [thumbnailPreview, setThumbnailPreview] = useState(null);
const [videoFile, setVideoFile] = useState(null);
const [alerts, setAlerts] = useState([]);
const [searchUser, setSearchUser] = useState("");
const [searchResults, setSearchResults] = useState([]);
const nonEditModeClasses = "text-md font-normal text-white p-2 focus:text-white focus:outline-none w-full font-montserrat resizable-none";
const editModeClasses = nonEditModeClasses + " glassmorphism";
@ -140,6 +144,60 @@ export default function ManageVideo() {
setAlerts(alerts.filter(alert => alert !== alertToRemove));
};
const onUserSearch = async (value) => {
if (value.trim() === "") {
setSearchResults([]);
return;
}
const results = await searchByUsername(value, token, addAlert);
setSearchResults(results);
};
const onAuthorizedUserAdd = async (user) => {
// Don't modify video directly - use current state
const currentAuthorizedUsers = video?.authorizedUsers || [];
if (currentAuthorizedUsers.some(u => u.id === user.id)) {
addAlert('error', "Cet utilisateur est déjà autorisé.");
return;
}
// authorizedUsers = only ids
const body = {
authorizedUsers: [...currentAuthorizedUsers.map(u => u.id), user.id],
channel: video.channel
};
console.log("Sending to API:", body); // Debug log
const request = await updateAuthorizedUsers(id, body, token, addAlert);
// Only update state after successful API call
setVideo({
...video,
authorizedUsers: [...currentAuthorizedUsers, user]
});
setSearchUser("");
setSearchResults([]);
addAlert('success', "Utilisateur ajouté avec succès.");
}
const onRemoveAuthorizedUser = async (user) => {
console.log("Êtes-vous sûr de vouloir supprimer cet utilisateur autorisé ?", user.id);
const body = {
authorizedUsers: video.authorizedUsers.filter(u => u.id !== user.id),
channel: video.channel
};
const request = await updateAuthorizedUsers(id, body, token, addAlert);
setVideo({
...video,
authorizedUsers: video.authorizedUsers.filter(u => u.id !== user.id)
});
addAlert('success', "Utilisateur supprimé avec succès.");
}
return (
<div className="min-w-screen min-h-screen bg-linear-to-br from-left-gradient to-right-gradient">
@ -267,6 +325,66 @@ export default function ManageVideo() {
</form>
{/* AUTHORIZED USERS */}
{
video && video.visibility === "private" && (
<div className="glassmorphism p-4 mt-4 flex-1" >
<h2 className="text-2xl font-bold text-white mb-4">Utilisateurs autorisés</h2>
<div className="mb-4">
<input
type="text"
id="authorizedUsers"
name="authorizedUsers"
className="w-full p-2 mb-2 glassmorphism focus:outline-none font-inter text-xl text-white"
placeholder="Rechercher un utilisateur"
value={searchUser}
onChange={(e) => {
setSearchUser(e.target.value);
onUserSearch(e.target.value);
}}
/>
<div>
{searchResults && searchResults.map((user, index) => (
<UserCard
user={user}
onSubmit={onAuthorizedUserAdd}
doShowControls={true}
key={index}
control={
<button type="button" className="bg-primary text-white font-montserrat p-3 rounded-lg text-lg font-bold cursor-pointer">
ajouter
</button>
}
/>
))}
</div>
</div>
<div>
{video && video.authorizedUsers && video.authorizedUsers.length > 0 ? (
video.authorizedUsers.map((user) => (
<UserCard
key={user.id}
id={user.id}
user={user}
doShowControls={true}
onSubmit={onRemoveAuthorizedUser}
control={
<button type="button" className="bg-red-500 text-white font-montserrat p-3 rounded-lg text-lg font-bold cursor-pointer">
supprimer
</button>
} />
))
) : (
<p className="text-gray-500">Aucun utilisateur autorisé</p>
)}
</div>
</div>
)
}
</div>

2
frontend/src/pages/Video.jsx

@ -44,7 +44,7 @@ export default function Video() {
return;
}
const data = await getVideoById(id, addAlert);
const data = await getVideoById(id, navigation, addAlert);
if (!data) return;
setVideo(data);

33
frontend/src/services/video.service.js

@ -68,15 +68,23 @@ export async function uploadTags(body, videoId, token, addAlert) {
}
}
export async function getVideoById(id, addAlert) {
export async function getVideoById(id, navigator, addAlert) {
const token = localStorage.getItem('token');
try {
const request = await fetch(`/api/videos/${id}`, {
method: 'GET',
headers: {
'Content-Type': 'application/json',
'Authorization': `Bearer ${token ? token : ''}`
}
});
if (!request.ok) {
if (request.status === 403) {
addAlert('error', 'Accès refusé');
navigator('/');
}
addAlert('error', 'Erreur lors de la récupération de la vidéo');
}
const data = await request.json();
@ -209,4 +217,27 @@ export async function toggleLike(id, token, addAlert) {
console.error("Error toggling like:", error);
addAlert('error', 'Erreur lors du changement de like');
}
}
export async function updateAuthorizedUsers(id, body, token, addAlert) {
try {
const request = await fetch(`/api/videos/${id}/authorized-users`, {
method: 'PUT',
headers: {
'Content-Type': 'application/json',
'Authorization': `Bearer ${token}`
},
body: JSON.stringify(body)
});
if (!request.ok) {
const errorData = await request.json();
console.error("Backend validation errors:", errorData);
addAlert('error', 'Erreur lors de la mise à jour des utilisateurs autorisés');
return;
}
return request;
} catch (error) {
console.error("Error updating authorized users:", error);
addAlert('error', 'Erreur lors de la mise à jour des utilisateurs autorisés');
}
}
Loading…
Cancel
Save