From f730b4af3dfabde81f7c5b211c0ff0015b27f190 Mon Sep 17 00:00:00 2001 From: astria Date: Mon, 18 Aug 2025 18:30:45 +0000 Subject: [PATCH] Fixed playlist --- backend/app/controllers/user.controller.js | 60 ++++---- backend/app/middlewares/user.middleware.js | 6 +- backend/app/routes/user.route.js | 9 +- backend/logs/access.log | 159 +++++++++++++++++++++ docker-compose.yaml | 1 + frontend/package-lock.json | 7 - frontend/src/components/UserCard.jsx | 18 ++- frontend/src/pages/AddVideo.jsx | 49 +++++-- frontend/src/services/playlist.service.js | 10 +- frontend/src/services/user.service.js | 14 +- 10 files changed, 263 insertions(+), 70 deletions(-) diff --git a/backend/app/controllers/user.controller.js b/backend/app/controllers/user.controller.js index 13eab1d..97e9c95 100644 --- a/backend/app/controllers/user.controller.js +++ b/backend/app/controllers/user.controller.js @@ -1,11 +1,11 @@ import bcrypt from "bcrypt"; -import {getClient} from "../utils/database.js"; +import { getClient } from "../utils/database.js"; import jwt from "jsonwebtoken"; -import path, {dirname} from "path"; +import path, { dirname } from "path"; import fs from "fs"; -import {fileURLToPath} from "url"; +import { fileURLToPath } from "url"; import crypto from "crypto"; -import {sendEmail} from "../utils/mail.js"; +import { sendEmail } from "../utils/mail.js"; export async function register(req, res) { try { @@ -49,7 +49,7 @@ export async function register(req, res) { const token = crypto.randomBytes(32).toString("hex").slice(0, 5); const textMessage = "Merci de vous être inscrit. Veuillez vérifier votre e-mail. Code: " + token; - + const htmlMessage = ` @@ -126,7 +126,7 @@ export async function register(req, res) { console.log("Successfully registered"); client.end(); logger.write("successfully registered", 200); - res.status(200).send({user: user}); + res.status(200).send({ user: user }); } catch (err) { console.log(err); @@ -187,7 +187,7 @@ export async function login(req, res) { if (!userInBase) { logger.write("failed to login", 401) - res.status(401).json({error: "Invalid credentials"}); + res.status(401).json({ error: "Invalid credentials" }); return } @@ -195,7 +195,7 @@ export async function login(req, res) { if (!isPasswordValid) { logger.write("failed to login", 401) - res.status(401).json({error: "Invalid credentials"}); + res.status(401).json({ error: "Invalid credentials" }); return } @@ -215,7 +215,7 @@ export async function login(req, res) { logger.write("Successfully logged in", 200); client.end(); - res.status(200).json({token: token, user: userData}); + res.status(200).json({ token: token, user: userData }); } @@ -231,12 +231,12 @@ export async function getById(req, res) { if (!result.rows[0]) { logger.write("failed to retrieve user " + id + " because it doesn't exist", 404); client.end() - res.status(404).json({error: "Not Found"}); + res.status(404).json({ error: "Not Found" }); return } logger.write("successfully retrieved user " + id, 200); if (result.rows[0].picture) { - return res.status(200).json({user: result.rows[0]}); + return res.status(200).json({ user: result.rows[0] }); } } @@ -250,12 +250,12 @@ export async function getByUsername(req, res) { if (!result.rows[0]) { logger.write("failed to retrieve user " + username + " because it doesn't exist", 404); client.end() - res.status(404).json({error: "Not Found"}); + res.status(404).json({ error: "Not Found" }); return } logger.write("successfully retrieved user " + username, 200); client.end(); - return res.status(200).json({user: result.rows[0]}); + return res.status(200).json({ user: result.rows[0] }); } export async function update(req, res) { @@ -283,7 +283,7 @@ export async function update(req, res) { if (emailResult.rows[0]) { logger.write("failed to update because email is already used", 400) client.end(); - res.status(400).json({error: "Email already exists"}); + res.status(400).json({ error: "Email already exists" }); } } @@ -293,7 +293,7 @@ export async function update(req, res) { if (usernameResult.rows[0]) { logger.write("failed to update because username is already used", 400) client.end(); - res.status(400).json({error: "Username already exists"}); + res.status(400).json({ error: "Username already exists" }); } } @@ -318,12 +318,12 @@ export async function update(req, res) { path.join(__dirname, "..", "uploads", "profiles", profilePicture), path.join(__dirname, "..", "uploads", "profiles", user.username + "." + profilePicture.split(".").pop()), (err) => { - if (err) { - logger.write("failed to update profile picture", 500); - console.error("Error renaming file:", err); - throw err; - } - }); + if (err) { + logger.write("failed to update profile picture", 500); + console.error("Error renaming file:", err); + throw err; + } + }); profilePicture = "/api/media/profile/" + user.username + "." + profilePicture.split(".").pop(); const updateQuery = `UPDATE users SET email = $1, username = $2, password = $3, picture = $4 WHERE id = $5 RETURNING id, email, username, picture`; @@ -334,7 +334,7 @@ export async function update(req, res) { } catch (err) { console.log(err); client.end() - res.status(500).json({error: err}); + res.status(500).json({ error: err }); } } @@ -348,7 +348,7 @@ export async function deleteUser(req, res) { await client.query(query, [id]); logger.write("successfully deleted user " + id); client.end(); - res.status(200).json({message: 'User deleted'}); + res.status(200).json({ message: 'User deleted' }); } export async function getChannel(req, res) { @@ -363,13 +363,13 @@ export async function getChannel(req, res) { if (!result.rows[0]) { logger.write("failed to retrieve channel of user " + id + " because it doesn't exist", 404); client.end(); - res.status(404).json({error: "Channel Not Found"}); + res.status(404).json({ error: "Channel Not Found" }); return; } logger.write("successfully retrieved channel of user " + id, 200); client.end(); - res.status(200).json({channel: result.rows[0]}); + res.status(200).json({ channel: result.rows[0] }); } export async function getHistory(req, res) { @@ -414,7 +414,7 @@ export async function getHistory(req, res) { if (!result.rows[0]) { logger.write("failed to retrieve history of user " + id + " because it doesn't exist", 404); - res.status(404).json({error: "History Not Found"}); + res.status(404).json({ error: "History Not Found" }); client.end(); return; } @@ -440,11 +440,11 @@ export async function isSubscribed(req, res) { if (result.rows[0]) { logger.write(`user ${userId} is subscribed to channel ${channelId}`, 200); client.end(); - return res.status(200).json({subscribed: true}); + return res.status(200).json({ subscribed: true }); } else { logger.write(`user ${userId} is not subscribed to channel ${channelId}`, 200); client.end(); - return res.status(200).json({subscribed: false}); + return res.status(200).json({ subscribed: false }); } } @@ -454,13 +454,13 @@ export async function searchByUsername(req, res) { const logger = req.body.logger; logger.action("try to search user by username " + username); - const query = `SELECT * FROM users WHERE username ILIKE $1`; + const query = `SELECT id, username, picture, email, is_verified FROM users WHERE username ILIKE $1`; const result = await client.query(query, [`%${username}%`]); if (result.rows.length === 0) { logger.write("no user found with username " + username, 404); client.end(); - return res.status(404).json({error: "User Not Found"}); + return res.status(404).json({ error: "User Not Found" }); } logger.write("successfully found user with username " + username, 200); diff --git a/backend/app/middlewares/user.middleware.js b/backend/app/middlewares/user.middleware.js index 303179d..d75cb93 100644 --- a/backend/app/middlewares/user.middleware.js +++ b/backend/app/middlewares/user.middleware.js @@ -1,4 +1,4 @@ -import {body, param} from "express-validator"; +import {body, param, query} from "express-validator"; import {getClient} from "../utils/database.js"; import jwt from "jsonwebtoken"; @@ -37,6 +37,10 @@ export const UserRequest = { username: param("username").notEmpty().isAlphanumeric("fr-FR", {ignore: " _-"}).trim(), } +export const UserSearch = { + username: query("username").notEmpty().isAlphanumeric("fr-FR", {ignore: " _-"}).trim(), +} + export async function doEmailExists(req, res, next) { const client = await getClient(); const logger = req.body.logger; diff --git a/backend/app/routes/user.route.js b/backend/app/routes/user.route.js index e405495..5ec8765 100644 --- a/backend/app/routes/user.route.js +++ b/backend/app/routes/user.route.js @@ -19,7 +19,8 @@ import { isOwner, UserLogin, User, - UserRequest + UserRequest, + UserSearch } from "../middlewares/user.middleware.js"; import validator from "../middlewares/error.middleware.js"; import {isTokenValid} from "../middlewares/jwt.middleware.js"; @@ -35,6 +36,9 @@ router.post("/", [profileUpload.single("profile"), addLogger, UserRegister.email // LOGIN A USER router.post("/login", [addLogger, UserLogin.username, UserLogin.password, validator], login) +// SEARCH BY USERNAME +router.get("/search", [addLogger, isTokenValid, UserSearch.username, validator], searchByUsername); + // GET USER BY ID router.get("/:id", [addLogger, isTokenValid, User.id, validator], getById) @@ -59,7 +63,4 @@ router.get("/:id/channel/subscribed", [addLogger, isTokenValid, User.id, Channel // VERIFY EMAIL router.post("/verify-email", [addLogger, validator], verifyEmail); -// SEARCH BY USERNAME -router.get("/search", [addLogger, isTokenValid], searchByUsername); - export default router; \ No newline at end of file diff --git a/backend/logs/access.log b/backend/logs/access.log index f3e3a42..707ab93 100644 --- a/backend/logs/access.log +++ b/backend/logs/access.log @@ -7465,3 +7465,162 @@ [2025-08-17 10:59:30.938] [undefined] GET(/:id): Invalid token with status 401 [2025-08-17 11:04:33.569] [undefined] GET(/:id): Invalid token with status 401 [2025-08-17 11:07:46.550] [undefined] POST(/): Invalid token with status 401 +[2025-08-18 16:43:00.578] [undefined] POST(/): try to register a user with username: astria and email: sachaguerin.sg@gmail.com +[2025-08-18 16:43:05.605] [undefined] POST(/): successfully registered with status 200 +[2025-08-18 16:43:20.564] [undefined] POST(/verify-email): try to verify email for sachaguerin.sg@gmail.com with token 4563d +[2025-08-18 16:43:20.576] [undefined] POST(/verify-email): successfully verified email for sachaguerin.sg@gmail.com with status 200 +[2025-08-18 16:55:58.836] [undefined] POST(/login): try to login with username 'astria' +[2025-08-18 16:55:58.891] [undefined] POST(/login): Successfully logged in with status 200 +[2025-08-18 16:56:01.446] [undefined] GET(/:id/channel): try to retrieve channel of user 1 +[2025-08-18 16:56:01.449] [undefined] GET(/:id/channel): failed to retrieve channel of user 1 because it doesn't exist with status 404 +[2025-08-18 16:56:01.453] [undefined] GET(/:id/history): try to retrieve history of user 1 +[2025-08-18 16:56:01.458] [undefined] GET(/:id/history): failed to retrieve history of user 1 because it doesn't exist with status 404 +[2025-08-18 16:56:01.467] [undefined] GET(/user/:id): Playlists retrieved for user with id 1 with status 200 +[2025-08-18 16:56:13.681] [undefined] POST(/): try to create new channel with owner 1 and name astria +[2025-08-18 16:56:13.684] [undefined] POST(/): Successfully created new channel with name astria with status 200 +[2025-08-18 16:56:13.698] [undefined] GET(/:id/channel): try to retrieve channel of user 1 +[2025-08-18 16:56:13.701] [undefined] GET(/:id/channel): successfully retrieved channel of user 1 with status 200 +[2025-08-18 16:56:15.038] [undefined] GET(/:id): try to get channel with id 1 +[2025-08-18 16:56:15.049] [undefined] GET(/:id/stats): try to get stats +[2025-08-18 16:56:15.053] [undefined] GET(/:id): Successfully get channel with id 1 with status 200 +[2025-08-18 16:56:15.063] [undefined] GET(/:id/stats): Successfully get stats with status 200 +[2025-08-18 16:57:54.267] [undefined] GET(/:id/channel): try to retrieve channel of user 1 +[2025-08-18 16:57:54.270] [undefined] GET(/:id/channel): successfully retrieved channel of user 1 with status 200 +[2025-08-18 16:58:07.426] [undefined] GET(/:id): failed due to invalid values with status 400 +[2025-08-18 16:58:17.830] [undefined] GET(/:id): failed due to invalid values with status 400 +[2025-08-18 16:59:16.058] [undefined] GET(/:id): failed due to invalid values with status 400 +[2025-08-18 17:02:02.699] [undefined] GET(/:id/channel): try to retrieve channel of user 1 +[2025-08-18 17:02:02.704] [undefined] GET(/:id/channel): successfully retrieved channel of user 1 with status 200 +[2025-08-18 17:02:14.301] [undefined] GET(/:id): failed due to invalid values with status 400 +[2025-08-18 17:04:10.822] [undefined] GET(/:id/channel): try to retrieve channel of user 1 +[2025-08-18 17:04:10.825] [undefined] GET(/:id/channel): successfully retrieved channel of user 1 with status 200 +[2025-08-18 17:04:18.423] [undefined] GET(/:id): failed due to invalid values with status 400 +[2025-08-18 17:17:56.386] [undefined] GET(/:id/channel): try to retrieve channel of user 1 +[2025-08-18 17:17:56.389] [undefined] GET(/:id/channel): successfully retrieved channel of user 1 with status 200 +[2025-08-18 17:17:59.561] [undefined] GET(/:id): failed due to invalid values with status 400 +[2025-08-18 17:19:04.710] [undefined] GET(/search): try to search user by username as +[2025-08-18 17:19:04.715] [undefined] GET(/search): successfully found user with username as with status 200 +[2025-08-18 17:37:33.042] [undefined] GET(/search): try to search user by username as +[2025-08-18 17:37:33.048] [undefined] GET(/search): successfully found user with username as with status 200 +[2025-08-18 17:39:59.796] [undefined] GET(/:id/channel): try to retrieve channel of user 1 +[2025-08-18 17:39:59.800] [undefined] GET(/:id/channel): successfully retrieved channel of user 1 with status 200 +[2025-08-18 17:40:00.890] [undefined] GET(/search): try to search user by username a +[2025-08-18 17:40:00.893] [undefined] GET(/search): successfully found user with username a with status 200 +[2025-08-18 17:40:01.717] [undefined] GET(/search): try to search user by username as +[2025-08-18 17:40:01.721] [undefined] GET(/search): successfully found user with username as with status 200 +[2025-08-18 17:40:02.564] [undefined] GET(/search): try to search user by username ast +[2025-08-18 17:40:02.567] [undefined] GET(/search): successfully found user with username ast with status 200 +[2025-08-18 17:40:02.713] [undefined] GET(/search): try to search user by username astr +[2025-08-18 17:40:02.717] [undefined] GET(/search): successfully found user with username astr with status 200 +[2025-08-18 17:40:03.133] [undefined] GET(/search): try to search user by username astri +[2025-08-18 17:40:03.137] [undefined] GET(/search): successfully found user with username astri with status 200 +[2025-08-18 17:44:43.499] [undefined] GET(/:id/channel): try to retrieve channel of user 1 +[2025-08-18 17:44:43.502] [undefined] GET(/:id/channel): successfully retrieved channel of user 1 with status 200 +[2025-08-18 17:44:46.281] [undefined] GET(/search): try to search user by username a +[2025-08-18 17:44:46.285] [undefined] GET(/search): successfully found user with username a with status 200 +[2025-08-18 17:44:50.193] [undefined] GET(/search): try to search user by username as +[2025-08-18 17:44:50.196] [undefined] GET(/search): successfully found user with username as with status 200 +[2025-08-18 17:44:50.396] [undefined] GET(/search): try to search user by username ast +[2025-08-18 17:44:50.400] [undefined] GET(/search): successfully found user with username ast with status 200 +[2025-08-18 17:44:50.485] [undefined] GET(/search): try to search user by username astr +[2025-08-18 17:44:50.489] [undefined] GET(/search): successfully found user with username astr with status 200 +[2025-08-18 17:44:50.666] [undefined] GET(/search): try to search user by username astri +[2025-08-18 17:44:50.671] [undefined] GET(/search): successfully found user with username astri with status 200 +[2025-08-18 17:45:11.427] [undefined] GET(/:id/channel): try to retrieve channel of user 1 +[2025-08-18 17:45:11.431] [undefined] GET(/:id/channel): successfully retrieved channel of user 1 with status 200 +[2025-08-18 17:45:12.426] [undefined] GET(/search): try to search user by username a +[2025-08-18 17:45:12.429] [undefined] GET(/search): successfully found user with username a with status 200 +[2025-08-18 17:46:02.236] [undefined] GET(/:id/channel): try to retrieve channel of user 1 +[2025-08-18 17:46:02.239] [undefined] GET(/:id/channel): successfully retrieved channel of user 1 with status 200 +[2025-08-18 17:46:04.407] [undefined] GET(/search): try to search user by username a +[2025-08-18 17:46:04.411] [undefined] GET(/search): successfully found user with username a with status 200 +[2025-08-18 17:46:06.643] [undefined] GET(/:id/channel): try to retrieve channel of user 1 +[2025-08-18 17:46:06.646] [undefined] GET(/:id/channel): successfully retrieved channel of user 1 with status 200 +[2025-08-18 17:46:10.552] [undefined] GET(/search): try to search user by username a +[2025-08-18 17:46:10.557] [undefined] GET(/search): successfully found user with username a with status 200 +[2025-08-18 17:46:32.809] [undefined] GET(/:id/channel): try to retrieve channel of user 1 +[2025-08-18 17:46:32.813] [undefined] GET(/:id/channel): successfully retrieved channel of user 1 with status 200 +[2025-08-18 17:46:34.704] [undefined] GET(/search): try to search user by username a +[2025-08-18 17:46:34.708] [undefined] GET(/search): successfully found user with username a with status 200 +[2025-08-18 17:48:10.395] [undefined] GET(/:id/channel): try to retrieve channel of user 1 +[2025-08-18 17:48:10.399] [undefined] GET(/:id/channel): successfully retrieved channel of user 1 with status 200 +[2025-08-18 17:48:12.431] [undefined] GET(/search): try to search user by username a +[2025-08-18 17:48:12.434] [undefined] GET(/search): successfully found user with username a with status 200 +[2025-08-18 17:48:15.528] [undefined] GET(/search): try to search user by username as +[2025-08-18 17:48:15.532] [undefined] GET(/search): successfully found user with username as with status 200 +[2025-08-18 17:48:15.707] [undefined] GET(/search): try to search user by username a +[2025-08-18 17:48:15.710] [undefined] GET(/search): successfully found user with username a with status 200 +[2025-08-18 17:48:47.100] [undefined] GET(/:id/channel): try to retrieve channel of user 1 +[2025-08-18 17:48:47.104] [undefined] GET(/:id/channel): successfully retrieved channel of user 1 with status 200 +[2025-08-18 17:48:48.333] [undefined] GET(/search): try to search user by username a +[2025-08-18 17:48:48.337] [undefined] GET(/search): successfully found user with username a with status 200 +[2025-08-18 17:49:01.390] [undefined] GET(/:id/channel): try to retrieve channel of user 1 +[2025-08-18 17:49:01.394] [undefined] GET(/:id/channel): successfully retrieved channel of user 1 with status 200 +[2025-08-18 17:49:04.296] [undefined] GET(/search): try to search user by username a +[2025-08-18 17:49:04.300] [undefined] GET(/search): successfully found user with username a with status 200 +[2025-08-18 17:49:37.858] [undefined] GET(/:id/channel): try to retrieve channel of user 1 +[2025-08-18 17:49:37.862] [undefined] GET(/:id/channel): successfully retrieved channel of user 1 with status 200 +[2025-08-18 17:49:38.853] [undefined] GET(/search): try to search user by username a +[2025-08-18 17:49:38.857] [undefined] GET(/search): successfully found user with username a with status 200 +[2025-08-18 17:49:57.908] [undefined] GET(/:id/channel): try to retrieve channel of user 1 +[2025-08-18 17:49:57.912] [undefined] GET(/:id/channel): successfully retrieved channel of user 1 with status 200 +[2025-08-18 17:49:59.214] [undefined] GET(/search): try to search user by username a +[2025-08-18 17:49:59.218] [undefined] GET(/search): successfully found user with username a with status 200 +[2025-08-18 17:50:47.064] [undefined] GET(/:id/channel): try to retrieve channel of user 1 +[2025-08-18 17:50:47.068] [undefined] GET(/:id/channel): successfully retrieved channel of user 1 with status 200 +[2025-08-18 17:50:48.062] [undefined] GET(/search): try to search user by username a +[2025-08-18 17:50:48.065] [undefined] GET(/search): successfully found user with username a with status 200 +[2025-08-18 17:50:57.499] [undefined] GET(/:id/channel): try to retrieve channel of user 1 +[2025-08-18 17:50:57.503] [undefined] GET(/:id/channel): successfully retrieved channel of user 1 with status 200 +[2025-08-18 17:50:58.394] [undefined] GET(/search): try to search user by username a +[2025-08-18 17:50:58.398] [undefined] GET(/search): successfully found user with username a with status 200 +[2025-08-18 17:51:33.403] [undefined] GET(/:id/channel): try to retrieve channel of user 1 +[2025-08-18 17:51:33.407] [undefined] GET(/:id/channel): successfully retrieved channel of user 1 with status 200 +[2025-08-18 17:51:34.352] [undefined] GET(/search): try to search user by username a +[2025-08-18 17:51:34.356] [undefined] GET(/search): successfully found user with username a with status 200 +[2025-08-18 17:51:41.430] [undefined] GET(/:id/channel): try to retrieve channel of user 1 +[2025-08-18 17:51:41.433] [undefined] GET(/:id/channel): successfully retrieved channel of user 1 with status 200 +[2025-08-18 17:51:42.519] [undefined] GET(/search): try to search user by username a +[2025-08-18 17:51:42.523] [undefined] GET(/search): successfully found user with username a with status 200 +[2025-08-18 17:51:51.265] [undefined] GET(/:id/channel): try to retrieve channel of user 1 +[2025-08-18 17:51:51.268] [undefined] GET(/:id/channel): successfully retrieved channel of user 1 with status 200 +[2025-08-18 17:51:53.003] [undefined] GET(/search): try to search user by username a +[2025-08-18 17:51:53.006] [undefined] GET(/search): successfully found user with username a with status 200 +[2025-08-18 17:52:09.869] [undefined] GET(/:id/channel): try to retrieve channel of user 1 +[2025-08-18 17:52:09.872] [undefined] GET(/:id/channel): successfully retrieved channel of user 1 with status 200 +[2025-08-18 17:52:11.174] [undefined] GET(/search): try to search user by username a +[2025-08-18 17:52:11.178] [undefined] GET(/search): successfully found user with username a with status 200 +[2025-08-18 17:52:18.702] [undefined] GET(/:id/channel): try to retrieve channel of user 1 +[2025-08-18 17:52:18.706] [undefined] GET(/:id/channel): successfully retrieved channel of user 1 with status 200 +[2025-08-18 17:52:19.655] [undefined] GET(/search): try to search user by username a +[2025-08-18 17:52:19.659] [undefined] GET(/search): successfully found user with username a with status 200 +[2025-08-18 17:53:23.241] [undefined] GET(/:id/channel): try to retrieve channel of user 1 +[2025-08-18 17:53:23.245] [undefined] GET(/:id/channel): successfully retrieved channel of user 1 with status 200 +[2025-08-18 17:53:24.233] [undefined] GET(/search): try to search user by username a +[2025-08-18 17:53:24.236] [undefined] GET(/search): successfully found user with username a with status 200 +[2025-08-18 17:53:40.448] [undefined] GET(/:id/channel): try to retrieve channel of user 1 +[2025-08-18 17:53:40.452] [undefined] GET(/:id/channel): successfully retrieved channel of user 1 with status 200 +[2025-08-18 17:53:42.339] [undefined] GET(/search): try to search user by username a +[2025-08-18 17:53:42.343] [undefined] GET(/search): successfully found user with username a with status 200 +[2025-08-18 17:56:02.368] [undefined] GET(/:id/channel): try to retrieve channel of user 1 +[2025-08-18 17:56:02.371] [undefined] GET(/:id/channel): successfully retrieved channel of user 1 with status 200 +[2025-08-18 17:56:04.593] [undefined] GET(/search): try to search user by username a +[2025-08-18 17:56:04.596] [undefined] GET(/search): successfully found user with username a with status 200 +[2025-08-18 17:56:25.107] [undefined] GET(/:id/channel): try to retrieve channel of user 1 +[2025-08-18 17:56:25.110] [undefined] GET(/:id/channel): successfully retrieved channel of user 1 with status 200 +[2025-08-18 17:56:52.324] [undefined] GET(/:id/channel): try to retrieve channel of user 1 +[2025-08-18 17:56:52.328] [undefined] GET(/:id/channel): successfully retrieved channel of user 1 with status 200 +[2025-08-18 17:56:53.719] [undefined] GET(/search): try to search user by username a +[2025-08-18 17:56:53.723] [undefined] GET(/search): successfully found user with username a with status 200 +[2025-08-18 17:57:15.686] [undefined] GET(/:id/channel): try to retrieve channel of user 1 +[2025-08-18 17:57:15.690] [undefined] GET(/:id/channel): successfully retrieved channel of user 1 with status 200 +[2025-08-18 17:57:16.727] [undefined] GET(/search): try to search user by username a +[2025-08-18 17:57:16.730] [undefined] GET(/search): successfully found user with username a with status 200 +[2025-08-18 17:58:20.073] [undefined] GET(/:id/channel): try to retrieve channel of user 1 +[2025-08-18 17:58:20.077] [undefined] GET(/:id/channel): successfully retrieved channel of user 1 with status 200 +[2025-08-18 17:58:20.844] [undefined] GET(/search): try to search user by username a +[2025-08-18 17:58:20.848] [undefined] GET(/search): successfully found user with username a with status 200 +[2025-08-18 17:59:00.905] [undefined] GET(/:id/channel): try to retrieve channel of user 1 +[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 diff --git a/docker-compose.yaml b/docker-compose.yaml index 42be633..66550d8 100644 --- a/docker-compose.yaml +++ b/docker-compose.yaml @@ -4,6 +4,7 @@ services: build: context: ./backend dockerfile: Dockerfile + network: host container_name: resit_backend ports: - "8000:8000" diff --git a/frontend/package-lock.json b/frontend/package-lock.json index adf4da8..a2cbbf8 100644 --- a/frontend/package-lock.json +++ b/frontend/package-lock.json @@ -10,7 +10,6 @@ "dependencies": { "@tailwindcss/vite": "^4.1.11", "chart.js": "^4.5.0", - "chartjs": "^0.3.24", "react": "^19.1.0", "react-chartjs-2": "^5.3.0", "react-dom": "^19.1.0", @@ -1815,12 +1814,6 @@ "pnpm": ">=8" } }, - "node_modules/chartjs": { - "version": "0.3.24", - "resolved": "https://registry.npmjs.org/chartjs/-/chartjs-0.3.24.tgz", - "integrity": "sha512-h6G9qcDqmFYnSWqjWCzQMeOLiypS+pM6Fq2Rj7LPty8Kjx5yHonwwJ7oEHImZpQ2u9Pu36XGYfardvvBiQVrhg==", - "license": "MIT" - }, "node_modules/chownr": { "version": "3.0.0", "resolved": "https://registry.npmjs.org/chownr/-/chownr-3.0.0.tgz", diff --git a/frontend/src/components/UserCard.jsx b/frontend/src/components/UserCard.jsx index b64e7fe..6daba1b 100644 --- a/frontend/src/components/UserCard.jsx +++ b/frontend/src/components/UserCard.jsx @@ -1,13 +1,19 @@ -export default function UserCard({user, doShowControls}) { +export default function UserCard({ user, onSubmit, doShowControls, control }) { return ( -
- {user.username} +
+
+ {`${user.username}'s + {user.username} +
{doShowControls && ( - + +
{ + onSubmit(user); + }}> + {control} +
)}
); diff --git a/frontend/src/pages/AddVideo.jsx b/frontend/src/pages/AddVideo.jsx index 0fa8132..06916a1 100644 --- a/frontend/src/pages/AddVideo.jsx +++ b/frontend/src/pages/AddVideo.jsx @@ -3,7 +3,7 @@ import { useEffect, useState } from "react"; import Tag from "../components/Tag.jsx"; import { getChannel, searchByUsername } from "../services/user.service.js"; import { uploadVideo, uploadThumbnail, uploadTags } from "../services/video.service.js"; -import { on } from "node:events"; +import UserCard from "../components/UserCard.jsx"; export default function AddVideo() { @@ -112,6 +112,7 @@ export default function AddVideo() { // Call the API to search for users searchByUsername(searchUser, token, addAlert) .then((results) => { + console.log(results); setSearchResults(results); }) .catch((error) => { @@ -122,6 +123,14 @@ export default function AddVideo() { } } + const onAuthorizedUserAdd = (user) => { + setAuthorizedUsers([...authorizedUsers, user]); + }; + + const onAuthorizedUserRemove = (user) => { + setAuthorizedUsers(authorizedUsers.filter((u) => u.id !== user.id)); + }; + return (
@@ -208,26 +217,38 @@ export default function AddVideo() { value={searchUser} onChange={(e) => setSearchUser(e.target.value)} onKeyDown={(e) => { - if (e.key === 'Enter' && searchUser.trim() !== "") { - onUserSearch(e); - } + onUserSearch(e) }} />
- + {searchResults && searchResults.map((user, index) => ( + + ajouter + + } + /> + ))}
{authorizedUsers.map((user, index) => ( -
- {user} - -
+ + supprimer + + } + /> ))}
diff --git a/frontend/src/services/playlist.service.js b/frontend/src/services/playlist.service.js index 8a30711..e19e401 100644 --- a/frontend/src/services/playlist.service.js +++ b/frontend/src/services/playlist.service.js @@ -1,7 +1,7 @@ export async function createPlaylist(body, token, addAlert) { try { - const response = await fetch(`https://localhost/api/playlists`, { + const response = await fetch(`/api/playlists`, { method: 'POST', headers: { 'Content-Type': 'application/json', @@ -24,7 +24,7 @@ export async function createPlaylist(body, token, addAlert) { export async function addToPlaylist(id, body, token, addAlert) { try { - const response = await fetch(`https://localhost/api/playlists/${id}`, { + const response = await fetch(`/api/playlists/${id}`, { method: 'POST', headers: { 'Content-Type': 'application/json', @@ -48,7 +48,7 @@ export async function addToPlaylist(id, body, token, addAlert) { export async function getPlaylistById(id, token, addAlert) { try { - const response = await fetch(`https://localhost/api/playlists/${id}`, { + const response = await fetch(`/api/playlists/${id}`, { headers: { 'Authorization': `Bearer ${token}` } @@ -67,7 +67,7 @@ export async function getPlaylistById(id, token, addAlert) { export async function deletePlaylist(id, token, addAlert) { try { - const response = await fetch(`https://localhost/api/playlists/${id}`, { + const response = await fetch(`/api/playlists/${id}`, { method: 'DELETE', headers: { 'Authorization': `Bearer ${token}` @@ -86,7 +86,7 @@ export async function deletePlaylist(id, token, addAlert) { export async function deleteVideo(playlistId, videoId, token, addAlert) { try { - const response = await fetch(`https://localhost/api/playlists/${playlistId}/video/${videoId}`, { + const response = await fetch(`/api/playlists/${playlistId}/video/${videoId}`, { method: 'DELETE', headers: { 'Authorization': `Bearer ${token}` diff --git a/frontend/src/services/user.service.js b/frontend/src/services/user.service.js index 1dec4c6..81f4630 100644 --- a/frontend/src/services/user.service.js +++ b/frontend/src/services/user.service.js @@ -126,19 +126,27 @@ export async function verifyEmail(email, token, addAlert) { export async function searchByUsername(username, token, addAlert) { try { - const response = await fetch(`/api/users/search?username=${encodeURIComponent(username)}`, { + // Validate input before sending request + if (!username || username.trim().length === 0) { + addAlert('error', "Le nom d'utilisateur ne peut pas être vide."); + return; + } + + const response = await fetch(`/api/users/search?username=${encodeURIComponent(username.trim())}`, { method: "GET", headers: { "Authorization": `Bearer ${token}`, } }); if (!response.ok) { - throw new Error("Failed to search user"); + const errorData = await response.json().catch(() => ({})); + console.log(errorData); + throw new Error(errorData.error || "Failed to search user"); } const data = await response.json(); return data; } catch (error) { console.error("Error searching user by username:", error); - addAlert('error', "Erreur lors de la recherche de l'utilisateur."); + addAlert('error', error.message || "Erreur lors de la recherche de l'utilisateur."); } } \ No newline at end of file