diff --git a/backend/app/controllers/playlist.controller.js b/backend/app/controllers/playlist.controller.js index 3bc2cb8..b300572 100644 --- a/backend/app/controllers/playlist.controller.js +++ b/backend/app/controllers/playlist.controller.js @@ -43,7 +43,18 @@ export async function getByUser(req, res) { const logger = req.body.logger; const client = await getClient(); - const query = `SELECT * FROM playlists WHERE owner = $1`; + const query = ` + SELECT * + FROM ( + SELECT playlists.id, playlists.name, playlists.owner, v.thumbnail as thumbnail, + ROW_NUMBER() OVER (PARTITION BY playlists.id ORDER BY pt.id DESC) as rn + FROM playlists + LEFT JOIN playlist_elements pt on playlist = playlists.id + LEFT JOIN videos v on pt.video = v.id + WHERE owner = $1 + ) ranked + WHERE rn = 1 OR rn IS NULL + `; try { const result = await client.query(query, [id]); diff --git a/backend/app/controllers/user.controller.js b/backend/app/controllers/user.controller.js index 69c1e69..a6d9300 100644 --- a/backend/app/controllers/user.controller.js +++ b/backend/app/controllers/user.controller.js @@ -35,8 +35,13 @@ export async function register(req, res) { const client = await getClient(); - const query = `INSERT INTO users (email, username, password, picture) VALUES ($1, $2, $3, $4)`; - await client.query(query, [user.email, user.username, user.password, user.picture]); + const query = `INSERT INTO users (email, username, password, picture) VALUES ($1, $2, $3, $4) RETURNING id`; + const result = await client.query(query, [user.email, user.username, user.password, user.picture]); + + const id = result.rows[0].id; + + const playlistQuery = `INSERT INTO playlists (name, owner) VALUES ('A regarder plus tard', $1)`; + await client.query(playlistQuery, [id]); console.log("Successfully registered"); client.end(); @@ -167,15 +172,19 @@ export async function update(req, res) { } } - const isPasswordValid = await bcrypt.compare(req.body.password, userInBase.password); + if (user.password) { + const isPasswordValid = await bcrypt.compare(req.body.password, userInBase.password); - if (!isPasswordValid) { - user.password = await bcrypt.hash(req.body.password, 10); + if (!isPasswordValid) { + user.password = await bcrypt.hash(req.body.password, 10); + } else { + user.password = userInBase.password; + } } else { user.password = userInBase.password; } - const updateQuery = `UPDATE users SET email = $1, username = $2, password = $3, picture = $4 WHERE id = $5`; + const updateQuery = `UPDATE users SET email = $1, username = $2, password = $3, picture = $4 WHERE id = $5 RETURNING id, email, username, picture`; const result = await client.query(updateQuery, [user.email, user.username, user.password, user.picture, id]); logger.write("successfully updated user " + id, 200); res.status(200).send({user: result.rows[0]}); @@ -195,4 +204,73 @@ export async function deleteUser(req, res) { await client.query(query, [id]); logger.write("successfully deleted user " + id); res.status(200).json({message: 'User deleted'}); +} + +export async function getChannel(req, res) { + const id = req.params.id; + const client = await getClient(); + const logger = req.body.logger; + logger.action("try to retrieve channel of user " + id); + + const query = `SELECT * FROM channels WHERE owner = $1`; + const result = await client.query(query, [id]); + + if (!result.rows[0]) { + logger.write("failed to retrieve channel of user " + id + " because it doesn't exist", 404); + res.status(404).json({error: "Channel Not Found"}); + return; + } + + logger.write("successfully retrieved channel of user " + id, 200); + res.status(200).json({channel: result.rows[0]}); +} + +export async function getHistory(req, res) { + const id = req.params.id; + const client = await getClient(); + const logger = req.body.logger; + logger.action("try to retrieve history of user " + id); + + const query = `SELECT + v.title, v.thumbnail, v.release_date, v.channel, c.name, u.picture, v.id + FROM history + JOIN public.videos v on history.video = v.id + JOIN public.channels c on v.channel = c.id + JOIN public.users u on c.owner = u.id + WHERE user_id = $1 + LIMIT 10 + `; + + const result = await client.query(query, [id]); + + const videos = []; + + for (const video of result.rows) { + // GET VIDEO VIEW COUNT + const videoQuery = `SELECT COUNT(*) as view_count FROM history WHERE video = $1`; + const videoResult = await client.query(videoQuery, [video.id]); + const videoToAdd = { + title: video.title, + thumbnail: video.thumbnail, + release_date: video.release_date, + views: videoResult.rows[0].view_count, + id: video.id, + creator: { + id: video.channel, + name: video.name, + profilePicture: video.picture + }, + user_picture: video.picture + }; + videos.push(videoToAdd); + } + + 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"}); + return; + } + + logger.write("successfully retrieved history of user " + id, 200); + res.status(200).json(videos); } \ No newline at end of file diff --git a/backend/app/routes/user.route.js b/backend/app/routes/user.route.js index 2b10c5b..75928f9 100644 --- a/backend/app/routes/user.route.js +++ b/backend/app/routes/user.route.js @@ -1,5 +1,13 @@ import {Router} from "express"; -import {register, login, getById, getByUsername, update, deleteUser} from "../controllers/user.controller.js"; +import { + register, + login, + getById, + getByUsername, + update, + deleteUser, + getChannel, getHistory +} from "../controllers/user.controller.js"; import { UserRegister, doEmailExists, @@ -35,4 +43,10 @@ router.put("/:id", [addLogger, isTokenValid, User.id, UserRegister.email, UserRe // DELETE USER router.delete("/:id", [addLogger, isTokenValid, User.id, validator, doUserExists, isOwner], deleteUser); +// GET USER CHANNEL +router.get("/:id/channel", [addLogger, isTokenValid, User.id, validator], getChannel); + +// GET USER HISTORY +router.get("/:id/history", [addLogger, isTokenValid, User.id, validator], getHistory); + export default router; \ No newline at end of file diff --git a/backend/logs/access.log b/backend/logs/access.log index 0863867..9feeea6 100644 --- a/backend/logs/access.log +++ b/backend/logs/access.log @@ -832,3 +832,389 @@ [2025-07-19 23:05:34.328] [undefined] GET(/:id/views): try to add views for video 3 [2025-07-19 23:05:34.333] [undefined] GET(/:id/views): successfully added views for video 3 with status 200 +[2025-07-20 19:33:35.299] [undefined] GET(/:id/channel): Invalid token with status 401 +[2025-07-20 19:35:03.964] [undefined] GET(/:id/channel): Invalid token with status 401 +[2025-07-20 19:35:18.137] [undefined] POST(/login): try to login with username 'astria' +[2025-07-20 19:35:18.199] [undefined] POST(/login): Successfully logged in with status 200 +[2025-07-20 19:35:27.429] [undefined] GET(/:id/channel): Invalid token with status 401 +[2025-07-20 19:35:45.291] [undefined] GET(/:id/channel): try to retrieve channel of user 1 +[2025-07-20 19:35:45.293] [undefined] GET(/:id/channel): failed to retrieve channel of user 1 because it doesn't exist with status 404 +[2025-07-20 19:37:19.690] [undefined] GET(/:id/channel): try to retrieve channel of user 1 +[2025-07-20 19:37:19.691] [undefined] GET(/:id/channel): failed to retrieve channel of user 1 because it doesn't exist with status 404 +[2025-07-20 19:39:50.682] [undefined] GET(/:id/channel): try to retrieve channel of user 1 +[2025-07-20 19:39:50.683] [undefined] GET(/:id/channel): failed to retrieve channel of user 1 because it doesn't exist with status 404 +[2025-07-20 19:40:09.868] [undefined] GET(/:id/channel): try to retrieve channel of user 1 +[2025-07-20 19:40:09.869] [undefined] GET(/:id/channel): failed to retrieve channel of user 1 because it doesn't exist with status 404 +[2025-07-20 19:40:22.261] [undefined] GET(/:id/channel): try to retrieve channel of user 1 +[2025-07-20 19:40:22.262] [undefined] GET(/:id/channel): failed to retrieve channel of user 1 because it doesn't exist with status 404 +[2025-07-20 19:40:35.388] [undefined] GET(/:id/channel): try to retrieve channel of user 1 +[2025-07-20 19:40:35.390] [undefined] GET(/:id/channel): failed to retrieve channel of user 1 because it doesn't exist with status 404 +[2025-07-20 19:40:41.890] [undefined] GET(/:id/channel): try to retrieve channel of user 1 +[2025-07-20 19:40:41.892] [undefined] GET(/:id/channel): failed to retrieve channel of user 1 because it doesn't exist with status 404 +[2025-07-20 19:41:00.392] [undefined] GET(/:id/channel): try to retrieve channel of user 1 +[2025-07-20 19:41:00.393] [undefined] GET(/:id/channel): failed to retrieve channel of user 1 because it doesn't exist with status 404 +[2025-07-20 19:41:05.286] [undefined] GET(/:id/channel): try to retrieve channel of user 1 +[2025-07-20 19:41:05.288] [undefined] GET(/:id/channel): failed to retrieve channel of user 1 because it doesn't exist with status 404 +[2025-07-20 19:41:17.319] [undefined] GET(/:id/channel): try to retrieve channel of user 1 +[2025-07-20 19:41:17.321] [undefined] GET(/:id/channel): failed to retrieve channel of user 1 because it doesn't exist with status 404 +[2025-07-20 19:41:26.059] [undefined] GET(/:id/channel): try to retrieve channel of user 1 +[2025-07-20 19:41:26.061] [undefined] GET(/:id/channel): failed to retrieve channel of user 1 because it doesn't exist with status 404 +[2025-07-20 19:41:37.603] [undefined] GET(/:id/channel): try to retrieve channel of user 1 +[2025-07-20 19:41:37.604] [undefined] GET(/:id/channel): failed to retrieve channel of user 1 because it doesn't exist with status 404 +[2025-07-20 19:42:02.913] [undefined] GET(/:id/channel): try to retrieve channel of user 1 +[2025-07-20 19:42:02.915] [undefined] GET(/:id/channel): failed to retrieve channel of user 1 because it doesn't exist with status 404 +[2025-07-20 19:42:13.514] [undefined] GET(/:id/channel): try to retrieve channel of user 1 +[2025-07-20 19:42:13.516] [undefined] GET(/:id/channel): failed to retrieve channel of user 1 because it doesn't exist with status 404 +[2025-07-20 19:42:25.385] [undefined] GET(/:id/channel): try to retrieve channel of user 1 +[2025-07-20 19:42:25.386] [undefined] GET(/:id/channel): failed to retrieve channel of user 1 because it doesn't exist with status 404 +[2025-07-20 19:42:26.021] [undefined] GET(/:id/channel): try to retrieve channel of user 1 +[2025-07-20 19:42:26.022] [undefined] GET(/:id/channel): failed to retrieve channel of user 1 because it doesn't exist with status 404 +[2025-07-20 19:42:26.448] [undefined] GET(/:id/channel): try to retrieve channel of user 1 +[2025-07-20 19:42:26.450] [undefined] GET(/:id/channel): failed to retrieve channel of user 1 because it doesn't exist with status 404 +[2025-07-20 19:42:37.675] [undefined] GET(/:id/channel): try to retrieve channel of user 1 +[2025-07-20 19:42:37.676] [undefined] GET(/:id/channel): failed to retrieve channel of user 1 because it doesn't exist with status 404 +[2025-07-20 19:42:50.565] [undefined] GET(/:id/channel): try to retrieve channel of user 1 +[2025-07-20 19:42:50.566] [undefined] GET(/:id/channel): failed to retrieve channel of user 1 because it doesn't exist with status 404 +[2025-07-20 19:43:05.604] [undefined] GET(/:id/channel): try to retrieve channel of user 1 +[2025-07-20 19:43:05.606] [undefined] GET(/:id/channel): failed to retrieve channel of user 1 because it doesn't exist with status 404 +[2025-07-20 19:43:12.166] [undefined] GET(/:id/channel): try to retrieve channel of user 1 +[2025-07-20 19:43:12.167] [undefined] GET(/:id/channel): failed to retrieve channel of user 1 because it doesn't exist with status 404 +[2025-07-20 19:44:00.052] [undefined] GET(/:id/channel): try to retrieve channel of user 1 +[2025-07-20 19:44:00.053] [undefined] GET(/:id/channel): failed to retrieve channel of user 1 because it doesn't exist with status 404 +[2025-07-20 19:44:03.413] [undefined] GET(/:id/channel): try to retrieve channel of user 1 +[2025-07-20 19:44:03.414] [undefined] GET(/:id/channel): failed to retrieve channel of user 1 because it doesn't exist with status 404 +[2025-07-20 19:45:44.513] [undefined] POST(/): failed because he wasn't the owner of the user with status 403 +[2025-07-20 19:46:05.183] [undefined] POST(/): try to create new channel with owner 1 and name Arcanas +[2025-07-20 19:46:05.184] [undefined] POST(/): Successfully created new channel with name Arcanas with status 200 +[2025-07-20 19:46:07.316] [undefined] GET(/:id/channel): try to retrieve channel of user 1 +[2025-07-20 19:46:07.318] [undefined] GET(/:id/channel): successfully retrieved channel of user 1 with status 200 +[2025-07-20 19:46:33.406] [undefined] GET(/:id/channel): try to retrieve channel of user 1 +[2025-07-20 19:46:33.407] [undefined] GET(/:id/channel): successfully retrieved channel of user 1 with status 200 +[2025-07-20 19:46:40.771] [undefined] GET(/:id/channel): try to retrieve channel of user 1 +[2025-07-20 19:46:40.773] [undefined] GET(/:id/channel): successfully retrieved channel of user 1 with status 200 +[2025-07-20 19:47:12.944] [undefined] GET(/:id/channel): try to retrieve channel of user 1 +[2025-07-20 19:47:12.946] [undefined] GET(/:id/channel): successfully retrieved channel of user 1 with status 200 +[2025-07-20 19:47:24.237] [undefined] GET(/:id/channel): try to retrieve channel of user 1 +[2025-07-20 19:47:24.239] [undefined] GET(/:id/channel): successfully retrieved channel of user 1 with status 200 +[2025-07-20 19:47:26.535] [undefined] GET(/:id/channel): try to retrieve channel of user 1 +[2025-07-20 19:47:26.537] [undefined] GET(/:id/channel): successfully retrieved channel of user 1 with status 200 +[2025-07-20 19:47:35.076] [undefined] GET(/:id/channel): try to retrieve channel of user 1 +[2025-07-20 19:47:35.077] [undefined] GET(/:id/channel): successfully retrieved channel of user 1 with status 200 +[2025-07-20 19:47:41.727] [undefined] GET(/:id/channel): try to retrieve channel of user 1 +[2025-07-20 19:47:41.729] [undefined] GET(/:id/channel): successfully retrieved channel of user 1 with status 200 +[2025-07-20 19:48:25.815] [undefined] POST(/): try to upload video with status undefined +[2025-07-20 19:48:25.818] [undefined] POST(/): successfully uploaded video with status 200 +[2025-07-20 19:48:28.228] [undefined] GET(/:id/channel): try to retrieve channel of user 1 +[2025-07-20 19:48:28.229] [undefined] GET(/:id/channel): successfully retrieved channel of user 1 with status 200 +[2025-07-20 19:48:40.072] [undefined] POST(/thumbnail): failed because user is not owner with status 403 +[2025-07-20 19:48:44.641] [undefined] POST(/thumbnail): try to add thumbnail to video 1 +[2025-07-20 19:48:44.643] [undefined] POST(/thumbnail): successfully uploaded thumbnail with status 200 +[2025-07-20 19:48:49.206] [undefined] GET(/:id): try to get video 1 +[2025-07-20 19:48:49.214] [undefined] GET(/:id): successfully get video 1 with status 200 +[2025-07-20 19:48:49.223] [undefined] GET(/:id/similar): try to get similar videos for video 1 +[2025-07-20 19:48:49.229] [undefined] GET(/:id/similar): No tags found for video 1 with status 404 +[2025-07-20 19:48:49.241] [undefined] GET(/:id/views): try to add views for video 1 +[2025-07-20 19:48:49.249] [undefined] GET(/:id/views): successfully added views for video 1 with status 200 +[2025-07-20 19:48:53.255] [undefined] GET(/:id/channel): try to retrieve channel of user 1 +[2025-07-20 19:48:53.257] [undefined] GET(/:id/channel): successfully retrieved channel of user 1 with status 200 +[2025-07-20 19:52:02.652] [undefined] GET(/:id/channel): try to retrieve channel of user 1 +[2025-07-20 19:52:02.655] [undefined] GET(/:id/channel): successfully retrieved channel of user 1 with status 200 +[2025-07-20 19:52:48.499] [undefined] GET(/:id/history): try to retrieve history of user 1 +[2025-07-20 19:52:48.501] [undefined] GET(/:id/history): successfully retrieved history of user 1 with status 200 +[2025-07-20 19:53:49.379] [undefined] GET(/:id/channel): try to retrieve channel of user 1 +[2025-07-20 19:53:49.380] [undefined] GET(/:id/history): try to retrieve history of user 1 +[2025-07-20 19:53:49.382] [undefined] GET(/:id/channel): successfully retrieved channel of user 1 with status 200 +[2025-07-20 19:53:49.383] [undefined] GET(/:id/history): successfully retrieved history of user 1 with status 200 +[2025-07-20 19:56:57.396] [undefined] GET(/:id/channel): try to retrieve channel of user 1 +[2025-07-20 19:56:57.397] [undefined] GET(/:id/history): try to retrieve history of user 1 +[2025-07-20 19:56:57.399] [undefined] GET(/:id/channel): successfully retrieved channel of user 1 with status 200 +[2025-07-20 19:56:57.401] [undefined] GET(/:id/history): successfully retrieved history of user 1 with status 200 +[2025-07-20 19:57:46.670] [undefined] GET(/:id/channel): try to retrieve channel of user 1 +[2025-07-20 19:57:46.671] [undefined] GET(/:id/history): try to retrieve history of user 1 +[2025-07-20 19:57:46.672] [undefined] GET(/:id/channel): successfully retrieved channel of user 1 with status 200 +[2025-07-20 19:57:46.673] [undefined] GET(/:id/history): successfully retrieved history of user 1 with status 200 +[2025-07-20 19:58:47.885] [undefined] GET(/:id/channel): try to retrieve channel of user 1 +[2025-07-20 19:58:47.886] [undefined] GET(/:id/history): try to retrieve history of user 1 +[2025-07-20 19:58:47.887] [undefined] GET(/:id/channel): successfully retrieved channel of user 1 with status 200 +[2025-07-20 19:58:47.888] [undefined] GET(/:id/history): successfully retrieved history of user 1 with status 200 +[2025-07-20 19:58:52.839] [undefined] GET(/:id/channel): try to retrieve channel of user 1 +[2025-07-20 19:58:52.840] [undefined] GET(/:id/channel): successfully retrieved channel of user 1 with status 200 +[2025-07-20 19:58:52.841] [undefined] GET(/:id/history): try to retrieve history of user 1 +[2025-07-20 19:58:52.843] [undefined] GET(/:id/history): successfully retrieved history of user 1 with status 200 +[2025-07-20 20:00:18.041] [undefined] GET(/:id/channel): try to retrieve channel of user 1 +[2025-07-20 20:00:18.042] [undefined] GET(/:id/history): try to retrieve history of user 1 +[2025-07-20 20:00:18.044] [undefined] GET(/:id/channel): successfully retrieved channel of user 1 with status 200 +[2025-07-20 20:00:18.045] [undefined] GET(/:id/history): successfully retrieved history of user 1 with status 200 +[2025-07-20 20:00:18.052] [undefined] GET(/user/:id): No playlists found for user with id 1 with status 404 +[2025-07-20 20:03:37.108] [undefined] POST(/): Playlist created with id 1 with status 200 +[2025-07-20 20:03:39.906] [undefined] GET(/:id/channel): try to retrieve channel of user 1 +[2025-07-20 20:03:39.908] [undefined] GET(/:id/channel): successfully retrieved channel of user 1 with status 200 +[2025-07-20 20:03:39.912] [undefined] GET(/:id/history): try to retrieve history of user 1 +[2025-07-20 20:03:39.913] [undefined] GET(/:id/history): successfully retrieved history of user 1 with status 200 +[2025-07-20 20:03:39.918] [undefined] GET(/user/:id): Playlists retrieved for user with id 1 with status 200 +[2025-07-20 20:11:24.718] [undefined] GET(/:id/channel): try to retrieve channel of user 1 +[2025-07-20 20:11:24.720] [undefined] GET(/:id/history): try to retrieve history of user 1 +[2025-07-20 20:11:24.722] [undefined] GET(/:id/channel): successfully retrieved channel of user 1 with status 200 +[2025-07-20 20:11:24.725] [undefined] GET(/:id/history): successfully retrieved history of user 1 with status 200 +[2025-07-20 20:11:24.732] [undefined] GET(/user/:id): No playlists found for user with id 1 with status 404 +[2025-07-20 20:12:16.190] [undefined] GET(/:id/channel): try to retrieve channel of user 1 +[2025-07-20 20:12:16.192] [undefined] GET(/:id/history): try to retrieve history of user 1 +[2025-07-20 20:12:16.194] [undefined] GET(/:id/channel): successfully retrieved channel of user 1 with status 200 +[2025-07-20 20:12:16.197] [undefined] GET(/:id/history): successfully retrieved history of user 1 with status 200 +[2025-07-20 20:12:16.204] [undefined] GET(/user/:id): Playlists retrieved for user with id 1 with status 200 +[2025-07-20 20:23:33.055] [undefined] GET(/:id/channel): try to retrieve channel of user 1 +[2025-07-20 20:23:33.057] [undefined] GET(/:id/channel): successfully retrieved channel of user 1 with status 200 +[2025-07-20 20:23:33.058] [undefined] GET(/:id/history): try to retrieve history of user 1 +[2025-07-20 20:23:33.060] [undefined] GET(/:id/history): successfully retrieved history of user 1 with status 200 +[2025-07-20 20:23:33.066] [undefined] GET(/user/:id): Playlists retrieved for user with id 1 with status 200 +[2025-07-20 20:24:48.901] [undefined] GET(/:id/channel): try to retrieve channel of user 1 +[2025-07-20 20:24:48.902] [undefined] GET(/:id/channel): successfully retrieved channel of user 1 with status 200 +[2025-07-20 20:24:48.905] [undefined] GET(/:id/history): try to retrieve history of user 1 +[2025-07-20 20:24:48.906] [undefined] GET(/:id/history): successfully retrieved history of user 1 with status 200 +[2025-07-20 20:24:48.914] [undefined] GET(/user/:id): Playlists retrieved for user with id 1 with status 200 +[2025-07-20 20:25:21.836] [undefined] GET(/:id/channel): try to retrieve channel of user 1 +[2025-07-20 20:25:21.838] [undefined] GET(/:id/channel): successfully retrieved channel of user 1 with status 200 +[2025-07-20 20:25:21.839] [undefined] GET(/:id/history): try to retrieve history of user 1 +[2025-07-20 20:25:21.841] [undefined] GET(/:id/history): successfully retrieved history of user 1 with status 200 +[2025-07-20 20:25:21.847] [undefined] GET(/user/:id): Playlists retrieved for user with id 1 with status 200 +[2025-07-20 20:25:51.530] [undefined] GET(/:id/channel): try to retrieve channel of user 1 +[2025-07-20 20:25:51.531] [undefined] GET(/:id/history): try to retrieve history of user 1 +[2025-07-20 20:25:51.531] [undefined] GET(/:id/channel): successfully retrieved channel of user 1 with status 200 +[2025-07-20 20:25:51.533] [undefined] GET(/:id/history): successfully retrieved history of user 1 with status 200 +[2025-07-20 20:25:51.540] [undefined] GET(/user/:id): Playlists retrieved for user with id 1 with status 200 +[2025-07-20 20:26:08.646] [undefined] GET(/:id/channel): try to retrieve channel of user 1 +[2025-07-20 20:26:08.647] [undefined] GET(/:id/history): try to retrieve history of user 1 +[2025-07-20 20:26:08.648] [undefined] GET(/:id/channel): successfully retrieved channel of user 1 with status 200 +[2025-07-20 20:26:08.649] [undefined] GET(/:id/history): successfully retrieved history of user 1 with status 200 +[2025-07-20 20:26:08.655] [undefined] GET(/user/:id): Playlists retrieved for user with id 1 with status 200 +[2025-07-20 20:26:20.383] [undefined] GET(/:id/channel): try to retrieve channel of user 1 +[2025-07-20 20:26:20.384] [undefined] GET(/:id/history): try to retrieve history of user 1 +[2025-07-20 20:26:20.385] [undefined] GET(/:id/channel): successfully retrieved channel of user 1 with status 200 +[2025-07-20 20:26:20.386] [undefined] GET(/:id/history): successfully retrieved history of user 1 with status 200 +[2025-07-20 20:26:20.392] [undefined] GET(/user/:id): Playlists retrieved for user with id 1 with status 200 +[2025-07-20 20:26:56.257] [undefined] GET(/:id/history): try to retrieve history of user 1 +[2025-07-20 20:26:56.258] [undefined] GET(/:id/channel): try to retrieve channel of user 1 +[2025-07-20 20:26:56.260] [undefined] GET(/:id/history): successfully retrieved history of user 1 with status 200 +[2025-07-20 20:26:56.261] [undefined] GET(/:id/channel): successfully retrieved channel of user 1 with status 200 +[2025-07-20 20:26:56.268] [undefined] GET(/user/:id): Playlists retrieved for user with id 1 with status 200 +[2025-07-20 20:27:10.084] [undefined] GET(/:id/history): try to retrieve history of user 1 +[2025-07-20 20:27:10.085] [undefined] GET(/:id/channel): try to retrieve channel of user 1 +[2025-07-20 20:27:10.087] [undefined] GET(/:id/history): successfully retrieved history of user 1 with status 200 +[2025-07-20 20:27:10.088] [undefined] GET(/:id/channel): successfully retrieved channel of user 1 with status 200 +[2025-07-20 20:27:10.095] [undefined] GET(/user/:id): Playlists retrieved for user with id 1 with status 200 +[2025-07-20 20:27:20.830] [undefined] GET(/:id/channel): try to retrieve channel of user 1 +[2025-07-20 20:27:20.831] [undefined] GET(/:id/channel): successfully retrieved channel of user 1 with status 200 +[2025-07-20 20:27:20.833] [undefined] GET(/:id/history): try to retrieve history of user 1 +[2025-07-20 20:27:20.835] [undefined] GET(/:id/history): successfully retrieved history of user 1 with status 200 +[2025-07-20 20:27:20.842] [undefined] GET(/user/:id): Playlists retrieved for user with id 1 with status 200 +[2025-07-20 20:27:47.761] [undefined] GET(/:id/channel): try to retrieve channel of user 1 +[2025-07-20 20:27:47.762] [undefined] GET(/:id/history): try to retrieve history of user 1 +[2025-07-20 20:27:47.764] [undefined] GET(/:id/channel): successfully retrieved channel of user 1 with status 200 +[2025-07-20 20:27:47.765] [undefined] GET(/:id/history): successfully retrieved history of user 1 with status 200 +[2025-07-20 20:27:47.774] [undefined] GET(/user/:id): Playlists retrieved for user with id 1 with status 200 +[2025-07-20 20:28:02.001] [undefined] GET(/:id/channel): try to retrieve channel of user 1 +[2025-07-20 20:28:02.003] [undefined] GET(/:id/channel): successfully retrieved channel of user 1 with status 200 +[2025-07-20 20:28:02.004] [undefined] GET(/:id/history): try to retrieve history of user 1 +[2025-07-20 20:28:02.006] [undefined] GET(/:id/history): successfully retrieved history of user 1 with status 200 +[2025-07-20 20:28:02.014] [undefined] GET(/user/:id): Playlists retrieved for user with id 1 with status 200 +[2025-07-20 20:28:08.842] [undefined] GET(/:id/channel): try to retrieve channel of user 1 +[2025-07-20 20:28:08.843] [undefined] GET(/:id/channel): successfully retrieved channel of user 1 with status 200 +[2025-07-20 20:28:08.846] [undefined] GET(/:id/history): try to retrieve history of user 1 +[2025-07-20 20:28:08.848] [undefined] GET(/:id/history): successfully retrieved history of user 1 with status 200 +[2025-07-20 20:28:08.854] [undefined] GET(/user/:id): Playlists retrieved for user with id 1 with status 200 +[2025-07-20 20:28:30.508] [undefined] GET(/:id/channel): try to retrieve channel of user 1 +[2025-07-20 20:28:30.509] [undefined] GET(/:id/history): try to retrieve history of user 1 +[2025-07-20 20:28:30.510] [undefined] GET(/:id/channel): successfully retrieved channel of user 1 with status 200 +[2025-07-20 20:28:30.511] [undefined] GET(/:id/history): successfully retrieved history of user 1 with status 200 +[2025-07-20 20:28:30.516] [undefined] GET(/user/:id): Playlists retrieved for user with id 1 with status 200 +[2025-07-20 20:28:41.406] [undefined] POST(/login): try to login with username 'astria' +[2025-07-20 20:28:41.454] [undefined] POST(/login): Successfully logged in with status 200 +[2025-07-20 20:28:47.226] [undefined] GET(/:id/channel): try to retrieve channel of user 1 +[2025-07-20 20:28:47.227] [undefined] GET(/:id/history): try to retrieve history of user 1 +[2025-07-20 20:28:47.227] [undefined] GET(/:id/channel): successfully retrieved channel of user 1 with status 200 +[2025-07-20 20:28:47.229] [undefined] GET(/:id/history): successfully retrieved history of user 1 with status 200 +[2025-07-20 20:28:47.235] [undefined] GET(/user/:id): Playlists retrieved for user with id 1 with status 200 +[2025-07-20 20:29:15.892] [undefined] GET(/:id/channel): try to retrieve channel of user 1 +[2025-07-20 20:29:15.892] [undefined] GET(/:id/history): try to retrieve history of user 1 +[2025-07-20 20:29:15.894] [undefined] GET(/:id/channel): successfully retrieved channel of user 1 with status 200 +[2025-07-20 20:29:15.896] [undefined] GET(/:id/history): successfully retrieved history of user 1 with status 200 +[2025-07-20 20:29:15.904] [undefined] GET(/user/:id): Playlists retrieved for user with id 1 with status 200 +[2025-07-20 20:31:06.851] [undefined] GET(/:id/channel): try to retrieve channel of user 1 +[2025-07-20 20:31:06.853] [undefined] GET(/:id/channel): successfully retrieved channel of user 1 with status 200 +[2025-07-20 20:31:06.855] [undefined] GET(/:id/history): try to retrieve history of user 1 +[2025-07-20 20:31:06.857] [undefined] GET(/:id/history): successfully retrieved history of user 1 with status 200 +[2025-07-20 20:31:06.864] [undefined] GET(/user/:id): Playlists retrieved for user with id 1 with status 200 +[2025-07-20 20:31:08.350] [undefined] GET(/:id/channel): try to retrieve channel of user 1 +[2025-07-20 20:31:08.352] [undefined] GET(/:id/channel): successfully retrieved channel of user 1 with status 200 +[2025-07-20 20:31:08.353] [undefined] GET(/:id/history): try to retrieve history of user 1 +[2025-07-20 20:31:08.355] [undefined] GET(/:id/history): successfully retrieved history of user 1 with status 200 +[2025-07-20 20:31:08.362] [undefined] GET(/user/:id): Playlists retrieved for user with id 1 with status 200 +[2025-07-20 20:31:16.188] [undefined] GET(/:id/channel): try to retrieve channel of user 1 +[2025-07-20 20:31:16.190] [undefined] GET(/:id/channel): successfully retrieved channel of user 1 with status 200 +[2025-07-20 20:31:16.192] [undefined] GET(/:id/history): try to retrieve history of user 1 +[2025-07-20 20:31:16.195] [undefined] GET(/:id/history): successfully retrieved history of user 1 with status 200 +[2025-07-20 20:31:16.200] [undefined] GET(/user/:id): Playlists retrieved for user with id 1 with status 200 +[2025-07-20 20:32:01.914] [undefined] GET(/:id/channel): try to retrieve channel of user 1 +[2025-07-20 20:32:01.916] [undefined] GET(/:id/channel): successfully retrieved channel of user 1 with status 200 +[2025-07-20 20:32:01.917] [undefined] GET(/:id/history): try to retrieve history of user 1 +[2025-07-20 20:32:01.919] [undefined] GET(/:id/history): successfully retrieved history of user 1 with status 200 +[2025-07-20 20:32:01.924] [undefined] GET(/user/:id): Playlists retrieved for user with id 1 with status 200 +[2025-07-20 20:32:17.682] [undefined] GET(/:id/channel): try to retrieve channel of user 1 +[2025-07-20 20:32:17.684] [undefined] GET(/:id/channel): successfully retrieved channel of user 1 with status 200 +[2025-07-20 20:32:17.686] [undefined] GET(/:id/history): try to retrieve history of user 1 +[2025-07-20 20:32:17.688] [undefined] GET(/:id/history): successfully retrieved history of user 1 with status 200 +[2025-07-20 20:32:17.696] [undefined] GET(/user/:id): Playlists retrieved for user with id 1 with status 200 +[2025-07-20 20:32:59.642] [undefined] GET(/:id/channel): try to retrieve channel of user 1 +[2025-07-20 20:32:59.644] [undefined] GET(/:id/channel): successfully retrieved channel of user 1 with status 200 +[2025-07-20 20:32:59.646] [undefined] GET(/:id/history): try to retrieve history of user 1 +[2025-07-20 20:32:59.648] [undefined] GET(/:id/history): successfully retrieved history of user 1 with status 200 +[2025-07-20 20:32:59.653] [undefined] GET(/user/:id): Playlists retrieved for user with id 1 with status 200 +[2025-07-20 20:33:52.972] [undefined] GET(/:id/channel): try to retrieve channel of user 1 +[2025-07-20 20:33:52.972] [undefined] GET(/:id/history): try to retrieve history of user 1 +[2025-07-20 20:33:52.974] [undefined] GET(/:id/channel): successfully retrieved channel of user 1 with status 200 +[2025-07-20 20:33:52.976] [undefined] GET(/:id/history): successfully retrieved history of user 1 with status 200 +[2025-07-20 20:33:52.982] [undefined] GET(/user/:id): Playlists retrieved for user with id 1 with status 200 +[2025-07-20 20:36:04.373] [undefined] GET(/:id/channel): try to retrieve channel of user 1 +[2025-07-20 20:36:04.374] [undefined] GET(/:id/history): try to retrieve history of user 1 +[2025-07-20 20:36:04.376] [undefined] GET(/:id/channel): successfully retrieved channel of user 1 with status 200 +[2025-07-20 20:36:04.377] [undefined] GET(/:id/history): successfully retrieved history of user 1 with status 200 +[2025-07-20 20:36:04.384] [undefined] GET(/user/:id): Playlists retrieved for user with id 1 with status 200 +[2025-07-20 20:36:18.347] [undefined] GET(/:id/channel): try to retrieve channel of user 1 +[2025-07-20 20:36:18.350] [undefined] GET(/:id/channel): successfully retrieved channel of user 1 with status 200 +[2025-07-20 20:36:18.352] [undefined] GET(/:id/history): try to retrieve history of user 1 +[2025-07-20 20:36:18.354] [undefined] GET(/:id/history): successfully retrieved history of user 1 with status 200 +[2025-07-20 20:36:18.363] [undefined] GET(/user/:id): Playlists retrieved for user with id 1 with status 200 +[2025-07-20 20:37:37.444] [undefined] GET(/:id/channel): try to retrieve channel of user 1 +[2025-07-20 20:37:37.446] [undefined] GET(/:id/history): try to retrieve history of user 1 +[2025-07-20 20:37:37.456] [undefined] GET(/:id/channel): successfully retrieved channel of user 1 with status 200 +[2025-07-20 20:37:37.460] [undefined] GET(/:id/history): successfully retrieved history of user 1 with status 200 +[2025-07-20 20:37:37.469] [undefined] GET(/user/:id): Playlists retrieved for user with id 1 with status 200 +[2025-07-20 20:37:41.175] [undefined] GET(/:id): failed due to invalid values with status 400 +[2025-07-20 20:37:41.179] [undefined] GET(/:id/similar): failed due to invalid values with status 400 +[2025-07-20 20:37:41.183] [undefined] GET(/:id/views): failed due to invalid values with status 400 +[2025-07-20 20:37:42.993] [undefined] GET(/:id/channel): try to retrieve channel of user 1 +[2025-07-20 20:37:42.994] [undefined] GET(/:id/channel): successfully retrieved channel of user 1 with status 200 +[2025-07-20 20:37:42.997] [undefined] GET(/:id/history): try to retrieve history of user 1 +[2025-07-20 20:37:42.999] [undefined] GET(/:id/history): successfully retrieved history of user 1 with status 200 +[2025-07-20 20:37:43.003] [undefined] GET(/user/:id): Playlists retrieved for user with id 1 with status 200 +[2025-07-20 20:38:25.527] [undefined] GET(/:id/channel): try to retrieve channel of user 1 +[2025-07-20 20:38:25.529] [undefined] GET(/:id/channel): successfully retrieved channel of user 1 with status 200 +[2025-07-20 20:38:25.532] [undefined] GET(/:id/history): try to retrieve history of user 1 +[2025-07-20 20:38:25.535] [undefined] GET(/:id/history): successfully retrieved history of user 1 with status 200 +[2025-07-20 20:38:25.543] [undefined] GET(/user/:id): Playlists retrieved for user with id 1 with status 200 +[2025-07-20 20:38:26.205] [undefined] GET(/:id): try to get video 1 +[2025-07-20 20:38:26.213] [undefined] GET(/:id): successfully get video 1 with status 200 +[2025-07-20 20:38:26.223] [undefined] GET(/:id/similar): try to get similar videos for video 1 +[2025-07-20 20:38:26.239] [undefined] GET(/:id/similar): No tags found for video 1 with status 404 +[2025-07-20 20:38:26.254] [undefined] GET(/:id/views): try to add views for video 1 +[2025-07-20 20:38:26.263] [undefined] GET(/:id/views): successfully added views for video 1 with status 200 +[2025-07-20 20:38:26.820] [undefined] GET(/:id/channel): try to retrieve channel of user 1 +[2025-07-20 20:38:26.821] [undefined] GET(/:id/channel): successfully retrieved channel of user 1 with status 200 +[2025-07-20 20:38:26.824] [undefined] GET(/:id/history): try to retrieve history of user 1 +[2025-07-20 20:38:26.826] [undefined] GET(/:id/history): successfully retrieved history of user 1 with status 200 +[2025-07-20 20:38:26.831] [undefined] GET(/user/:id): Playlists retrieved for user with id 1 with status 200 +[2025-07-20 20:38:49.852] [undefined] GET(/:id/channel): try to retrieve channel of user 1 +[2025-07-20 20:38:49.853] [undefined] GET(/:id/history): try to retrieve history of user 1 +[2025-07-20 20:38:49.855] [undefined] GET(/:id/channel): successfully retrieved channel of user 1 with status 200 +[2025-07-20 20:38:49.857] [undefined] GET(/:id/history): successfully retrieved history of user 1 with status 200 +[2025-07-20 20:38:49.863] [undefined] GET(/user/:id): Playlists retrieved for user with id 1 with status 200 +[2025-07-20 20:39:00.548] [undefined] GET(/:id/channel): try to retrieve channel of user 1 +[2025-07-20 20:39:00.550] [undefined] GET(/:id/channel): successfully retrieved channel of user 1 with status 200 +[2025-07-20 20:39:00.553] [undefined] GET(/:id/history): try to retrieve history of user 1 +[2025-07-20 20:39:00.555] [undefined] GET(/:id/history): successfully retrieved history of user 1 with status 200 +[2025-07-20 20:39:00.561] [undefined] GET(/user/:id): Playlists retrieved for user with id 1 with status 200 +[2025-07-20 20:39:20.688] [undefined] GET(/:id): try to get video 1 +[2025-07-20 20:39:20.697] [undefined] GET(/:id): successfully get video 1 with status 200 +[2025-07-20 20:39:20.706] [undefined] GET(/:id/similar): try to get similar videos for video 1 +[2025-07-20 20:39:20.714] [undefined] GET(/:id/similar): No tags found for video 1 with status 404 +[2025-07-20 20:39:20.727] [undefined] GET(/:id/views): try to add views for video 1 +[2025-07-20 20:39:20.734] [undefined] GET(/:id/views): successfully added views for video 1 with status 200 +[2025-07-20 20:39:21.942] [undefined] GET(/:id/channel): try to retrieve channel of user 1 +[2025-07-20 20:39:21.942] [undefined] GET(/:id/history): try to retrieve history of user 1 +[2025-07-20 20:39:21.944] [undefined] GET(/:id/channel): successfully retrieved channel of user 1 with status 200 +[2025-07-20 20:39:21.946] [undefined] GET(/:id/history): successfully retrieved history of user 1 with status 200 +[2025-07-20 20:39:21.951] [undefined] GET(/user/:id): Playlists retrieved for user with id 1 with status 200 +[2025-07-20 20:39:25.246] [undefined] GET(/:id): try to get video 1 +[2025-07-20 20:39:25.254] [undefined] GET(/:id): successfully get video 1 with status 200 +[2025-07-20 20:39:25.280] [undefined] GET(/:id/similar): try to get similar videos for video 1 +[2025-07-20 20:39:25.289] [undefined] GET(/:id/similar): No tags found for video 1 with status 404 +[2025-07-20 20:39:25.300] [undefined] GET(/:id/views): try to add views for video 1 +[2025-07-20 20:39:25.307] [undefined] GET(/:id/views): successfully added views for video 1 with status 200 +[2025-07-20 20:39:34.645] [undefined] GET(/:id/channel): try to retrieve channel of user 1 +[2025-07-20 20:39:34.646] [undefined] GET(/:id/history): try to retrieve history of user 1 +[2025-07-20 20:39:34.648] [undefined] GET(/:id/channel): successfully retrieved channel of user 1 with status 200 +[2025-07-20 20:39:34.649] [undefined] GET(/:id/history): successfully retrieved history of user 1 with status 200 +[2025-07-20 20:39:34.656] [undefined] GET(/user/:id): Playlists retrieved for user with id 1 with status 200 +[2025-07-20 20:40:05.834] [undefined] GET(/:id): try to get video 1 +[2025-07-20 20:40:05.842] [undefined] GET(/:id): successfully get video 1 with status 200 +[2025-07-20 20:40:05.853] [undefined] GET(/:id/similar): try to get similar videos for video 1 +[2025-07-20 20:40:05.861] [undefined] GET(/:id/similar): No tags found for video 1 with status 404 +[2025-07-20 20:40:05.889] [undefined] GET(/:id/views): try to add views for video 1 +[2025-07-20 20:40:05.900] [undefined] GET(/:id/views): successfully added views for video 1 with status 200 +[2025-07-20 20:40:17.058] [undefined] GET(/:id/like): try to toggle like on video 1 +[2025-07-20 20:40:17.065] [undefined] GET(/:id/like): no likes found adding likes for video 1 with status 200 +[2025-07-20 20:40:19.272] [undefined] GET(/:id/channel): try to retrieve channel of user 1 +[2025-07-20 20:40:19.273] [undefined] GET(/:id/history): try to retrieve history of user 1 +[2025-07-20 20:40:19.275] [undefined] GET(/:id/channel): successfully retrieved channel of user 1 with status 200 +[2025-07-20 20:40:19.276] [undefined] GET(/:id/history): successfully retrieved history of user 1 with status 200 +[2025-07-20 20:40:19.283] [undefined] GET(/user/:id): Playlists retrieved for user with id 1 with status 200 +[2025-07-20 20:42:28.889] [undefined] POST(/): failed due to invalid values with status 400 +[2025-07-20 20:42:40.896] [undefined] POST(/): try to upload video with status undefined +[2025-07-20 20:42:40.899] [undefined] POST(/): successfully uploaded video with status 200 +[2025-07-20 20:42:59.423] [undefined] POST(/thumbnail): try to add thumbnail to video 2 +[2025-07-20 20:42:59.425] [undefined] POST(/thumbnail): successfully uploaded thumbnail with status 200 +[2025-07-20 20:43:04.899] [undefined] GET(/:id): try to get video 2 +[2025-07-20 20:43:04.908] [undefined] GET(/:id): successfully get video 2 with status 200 +[2025-07-20 20:43:04.917] [undefined] GET(/:id/similar): try to get similar videos for video 2 +[2025-07-20 20:43:04.924] [undefined] GET(/:id/similar): No tags found for video 2 with status 404 +[2025-07-20 20:43:04.938] [undefined] GET(/:id/views): try to add views for video 2 +[2025-07-20 20:43:04.946] [undefined] GET(/:id/views): successfully added views for video 2 with status 200 +[2025-07-20 20:43:06.587] [undefined] GET(/:id/channel): try to retrieve channel of user 1 +[2025-07-20 20:43:06.589] [undefined] GET(/:id/channel): successfully retrieved channel of user 1 with status 200 +[2025-07-20 20:43:06.591] [undefined] GET(/:id/history): try to retrieve history of user 1 +[2025-07-20 20:43:06.594] [undefined] GET(/:id/history): successfully retrieved history of user 1 with status 200 +[2025-07-20 20:43:06.600] [undefined] GET(/user/:id): Playlists retrieved for user with id 1 with status 200 +[2025-07-20 20:43:22.392] [undefined] GET(/:id/channel): try to retrieve channel of user 1 +[2025-07-20 20:43:22.394] [undefined] GET(/:id/channel): successfully retrieved channel of user 1 with status 200 +[2025-07-20 20:43:22.395] [undefined] GET(/:id/history): try to retrieve history of user 1 +[2025-07-20 20:43:22.398] [undefined] GET(/:id/history): successfully retrieved history of user 1 with status 200 +[2025-07-20 20:43:22.404] [undefined] GET(/user/:id): Playlists retrieved for user with id 1 with status 200 +[2025-07-20 20:46:19.020] [undefined] GET(/:id/channel): try to retrieve channel of user 1 +[2025-07-20 20:46:19.021] [undefined] GET(/:id/channel): successfully retrieved channel of user 1 with status 200 +[2025-07-20 20:46:19.023] [undefined] GET(/:id/history): try to retrieve history of user 1 +[2025-07-20 20:46:19.025] [undefined] GET(/:id/history): successfully retrieved history of user 1 with status 200 +[2025-07-20 20:46:19.032] [undefined] GET(/user/:id): Playlists retrieved for user with id 1 with status 200 +[2025-07-20 20:46:54.686] [undefined] GET(/:id/channel): try to retrieve channel of user 1 +[2025-07-20 20:46:54.687] [undefined] GET(/:id/history): try to retrieve history of user 1 +[2025-07-20 20:46:54.689] [undefined] GET(/:id/channel): successfully retrieved channel of user 1 with status 200 +[2025-07-20 20:46:54.691] [undefined] GET(/:id/history): successfully retrieved history of user 1 with status 200 +[2025-07-20 20:46:54.699] [undefined] GET(/user/:id): Playlists retrieved for user with id 1 with status 200 +[2025-07-20 20:47:58.417] [undefined] GET(/:id/channel): try to retrieve channel of user 1 +[2025-07-20 20:47:58.418] [undefined] GET(/:id/channel): successfully retrieved channel of user 1 with status 200 +[2025-07-20 20:47:58.421] [undefined] GET(/:id/history): try to retrieve history of user 1 +[2025-07-20 20:47:58.423] [undefined] GET(/:id/history): successfully retrieved history of user 1 with status 200 +[2025-07-20 20:47:58.429] [undefined] GET(/user/:id): Playlists retrieved for user with id 1 with status 200 +[2025-07-20 20:48:25.448] [undefined] GET(/:id/channel): try to retrieve channel of user 1 +[2025-07-20 20:48:25.449] [undefined] GET(/:id/history): try to retrieve history of user 1 +[2025-07-20 20:48:25.449] [undefined] GET(/:id/channel): successfully retrieved channel of user 1 with status 200 +[2025-07-20 20:48:25.451] [undefined] GET(/:id/history): successfully retrieved history of user 1 with status 200 +[2025-07-20 20:49:10.898] [undefined] POST(/login): try to login with username 'sacha' +[2025-07-20 20:49:34.658] [undefined] POST(/login): try to login with username 'sacha' +[2025-07-20 20:49:34.667] [undefined] POST(/login): failed to login with status 401 +[2025-07-20 20:50:00.176] [undefined] POST(/login): try to login with username 'astria' +[2025-07-20 20:50:00.225] [undefined] POST(/login): Successfully logged in with status 200 +[2025-07-20 20:50:05.771] [undefined] GET(/:id/channel): try to retrieve channel of user 1 +[2025-07-20 20:50:05.772] [undefined] GET(/:id/history): try to retrieve history of user 1 +[2025-07-20 20:50:05.773] [undefined] GET(/:id/channel): successfully retrieved channel of user 1 with status 200 +[2025-07-20 20:50:05.775] [undefined] GET(/:id/history): successfully retrieved history of user 1 with status 200 +[2025-07-20 20:50:05.785] [undefined] GET(/user/:id): Playlists retrieved for user with id 1 with status 200 +[2025-07-20 20:51:22.884] [undefined] GET(/:id/channel): try to retrieve channel of user 1 +[2025-07-20 20:51:22.885] [undefined] GET(/:id/history): try to retrieve history of user 1 +[2025-07-20 20:51:22.886] [undefined] GET(/:id/channel): successfully retrieved channel of user 1 with status 200 +[2025-07-20 20:51:22.888] [undefined] GET(/:id/history): successfully retrieved history of user 1 with status 200 +[2025-07-20 20:51:22.893] [undefined] GET(/user/:id): Playlists retrieved for user with id 1 with status 200 +[2025-07-20 20:51:33.668] [undefined] PUT(/:id): try to update user 1 +[2025-07-20 20:51:33.710] [undefined] PUT(/:id): successfully updated user 1 with status 200 +[2025-07-20 20:51:37.656] [undefined] GET(/:id/channel): failed due to invalid values with status 400 +[2025-07-20 20:51:37.660] [undefined] GET(/:id/history): failed due to invalid values with status 400 +[2025-07-20 20:51:37.662] [undefined] GET(/user/:id): failed due to invalid values with status 400 diff --git a/backend/requests/channel.http b/backend/requests/channel.http index 940cb73..e9b8a30 100644 --- a/backend/requests/channel.http +++ b/backend/requests/channel.http @@ -1,4 +1,4 @@ -@token = eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJpZCI6MiwidXNlcm5hbWUiOiJhc3RyaWEiLCJpYXQiOjE3NTI4NjQ1ODN9.yyKcb1vLhAxEftBN1Z27wV7uM1pSruVEMb4dtiqDTrg +@token = eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJpZCI6MSwidXNlcm5hbWUiOiJhc3RyaWEiLCJpYXQiOjE3NTMwNDAxMTh9.GNGee4BYCL-wO3I8FtXXJIc-xsLMfuOoUlBhHjQJcWo ### CREATE CHANNEL POST http://localhost:8000/api/channels @@ -6,9 +6,9 @@ Authorization: Bearer {{token}} Content-Type: application/json { - "name": "Machin", + "name": "Arcanas", "description": "kljsdfjklsdfjkl", - "owner": 2 + "owner": 1 } ### GET CHANNEL BY ID diff --git a/backend/requests/playlist.http b/backend/requests/playlist.http new file mode 100644 index 0000000..ed94895 --- /dev/null +++ b/backend/requests/playlist.http @@ -0,0 +1,11 @@ +@token = eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJpZCI6MSwidXNlcm5hbWUiOiJhc3RyaWEiLCJpYXQiOjE3NTMwNDAxMTh9.GNGee4BYCL-wO3I8FtXXJIc-xsLMfuOoUlBhHjQJcWo + +### ADD PLAYLIST +POST http://localhost/api/playlists +Authorization: Bearer {{token}} +Content-Type: application/json + +{ + "name": "A regarder plus tard", + "owner": 1 +} \ No newline at end of file diff --git a/backend/requests/user.http b/backend/requests/user.http index be24e85..f46841f 100644 --- a/backend/requests/user.http +++ b/backend/requests/user.http @@ -1,4 +1,4 @@ -@token = eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJpZCI6MSwidXNlcm5hbWUiOiJhc3RyaWEiLCJpYXQiOjE3NTI3ODUwNTR9.yOEsanvke0yejwbizkA33SwJMzohfn-xymetVJwSFSs +@token = eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJpZCI6MSwidXNlcm5hbWUiOiJhc3RyaWEiLCJpYXQiOjE3NTMwNDAxMTh9.GNGee4BYCL-wO3I8FtXXJIc-xsLMfuOoUlBhHjQJcWo ### CREATE USER POST http://localhost:8000/api/users/ @@ -42,4 +42,8 @@ Content-Type: application/json ### DELETE USER DELETE http://localhost:8000/api/users/4 +Authorization: Bearer {{token}} + +### GET HISTORY +GET http://localhost:8000/api/users/1/history/ Authorization: Bearer {{token}} \ No newline at end of file diff --git a/docker-compose.yaml b/docker-compose.yaml index 997e29b..f2c6e24 100644 --- a/docker-compose.yaml +++ b/docker-compose.yaml @@ -18,7 +18,7 @@ services: PORT: ${BACKEND_PORT} volumes: - ./backend/logs:/var/log/freetube - - ./backend/app/uploads:/app/app/uploads + - ./backend:/app depends_on: - db diff --git a/frontend/src/assets/img/default_thumbnail.png b/frontend/src/assets/img/default_thumbnail.png new file mode 100644 index 0000000..fd2ee09 Binary files /dev/null and b/frontend/src/assets/img/default_thumbnail.png differ diff --git a/frontend/src/components/PlaylistCard.jsx b/frontend/src/components/PlaylistCard.jsx new file mode 100644 index 0000000..c9e9156 --- /dev/null +++ b/frontend/src/components/PlaylistCard.jsx @@ -0,0 +1,14 @@ +import Default from "../assets/img/default_thumbnail.png" + +export default function PlaylistCard(props){ + const {playlist, onClick} = props; + + return ( +
{onClick(playlist.id)}}> + {playlist.name} +
+

{playlist.name}

+
+
+ ); +} \ No newline at end of file diff --git a/frontend/src/pages/Account.jsx b/frontend/src/pages/Account.jsx index e87785f..2931bf2 100644 --- a/frontend/src/pages/Account.jsx +++ b/frontend/src/pages/Account.jsx @@ -1,22 +1,32 @@ import Navbar from "../components/Navbar.jsx"; -import {useState} from "react"; +import {useEffect, useState} from "react"; +import PlaylistCard from "../components/PlaylistCard.jsx"; +import VideoCard from "../components/VideoCard.jsx"; export default function Account() { let user = JSON.parse(localStorage.getItem("user")) || {}; + let token = localStorage.getItem("token") || ""; const [username, setUsername] = useState(user.username || ""); const [email, setEmail] = useState(user.email || ""); const [password, setPassword] = useState(""); const [confirmPassword, setConfirmPassword] = useState(""); const [isPictureEditActive, setIsPictureEditActive] = useState(false); + const [userHistory, setUserHistory] = useState([]); + const [userPlaylists, setUserPlaylists] = useState([]); const [userChannel, setUserChannel] = useState(null); const fetchUserChannel = async () => { try { - const response = await fetch(`/api/channels/${user.id}`); + const response = await fetch(`/api/users/${user.id}/channel`, { + method: "GET", + headers: { + "Authorization": `Bearer ${token}`, + } + }); if (!response.ok) { throw new Error("Failed to fetch user data"); } @@ -27,6 +37,54 @@ export default function Account() { return null; } } + const fetchUserHistory = async () => { + if (!user.id || !token) { + console.warn("User ID or token missing, skipping history fetch"); + return; + } + try { + const response = await fetch(`/api/users/${user.id}/history`, { + method: "GET", + headers: { + "Authorization": `Bearer ${token}`, + } + }); + if (!response.ok) { + throw new Error("Failed to fetch user history"); + } + const data = await response.json(); + setUserHistory(data); + } catch (error) { + console.error("Error fetching user history:", error); + } + } + const fetchUserPlaylists = async () => { + if (!user.id || !token) { + console.warn("User ID or token missing, skipping playlists fetch"); + return; + } + try { + const response = await fetch(`/api/playlists/user/${user.id}`, { + method: "GET", + headers: { + "Authorization": `Bearer ${token}`, + } + }); + if (!response.ok) { + throw new Error("Failed to fetch user playlists"); + } + const data = await response.json(); + setUserPlaylists(data); + } catch (error) { + console.error("Error fetching user playlists:", error); + } + } + + useEffect(() => { + fetchUserChannel(); + fetchUserHistory(); + fetchUserPlaylists(); + }, []); const [editMode, setEditMode] = useState(false); @@ -34,11 +92,51 @@ export default function Account() { const nonEditModeClasses = "text-2xl font-bold text-white p-2 focus:text-white focus:outline-none w-full font-montserrat"; const editModeClasses = nonEditModeClasses + " glassmorphism"; + const handlePlaylistClick = (playlistId) => { + + } + + const handleUpdateUser = async () => { + if (password !== confirmPassword) { + alert("Les mots de passe ne correspondent pas."); + return; + } + + const updatedUser = { + username, + email, + password: password || undefined, // Only send password if it's not empty + }; + + try { + const response = await fetch(`/api/users/${user.id}`, { + method: "PUT", + headers: { + "Content-Type": "application/json", + "Authorization": `Bearer ${token}`, + }, + body: JSON.stringify(updatedUser), + }); + + if (!response.ok) { + throw new Error("Failed to update user"); + } + + const data = await response.json(); + localStorage.setItem("user", JSON.stringify(data.user)); + setEditMode(false); + alert("Profil mis à jour avec succès !"); + } catch (error) { + console.error("Error updating user:", error); + alert("Erreur lors de la mise à jour du profil."); + } + } + return (
-
+
{/* Left side */} {/* Profile / Edit profile */} @@ -116,23 +214,82 @@ export default function Account() { }
- + { + editMode ? ( +
+ + +
+ ) : ( + + ) + }
{ /* Right side */} - {/* Channel */} - - {/* Playlists */} - - {/* History */} +
+ {/* Channel */} + {userChannel ? ( +
+

{userChannel.channel.name}

+ +
+ ) : ( +
+

Chaîne

+

Aucune chaîne associée à ce compte.

+ +
+ )} + {/* Playlists */} +

Playlists

+
+ { + userPlaylists.map((playlist, index) => ( + + )) + } +
+ {/* History */} +

Historique

+
+ { + userHistory.map((video, index) => ( +
+ +
+ )) + } +
+