From db5858a344655b6b9c9b4dbcb57cc90f88fb6151 Mon Sep 17 00:00:00 2001 From: Adam <45126464+KeyZox71@users.noreply.github.com> Date: Mon, 29 Sep 2025 20:35:25 +0200 Subject: [PATCH 01/18] les crampte la XD --- doc/auth/me.md | 6 ++++++ 1 file changed, 6 insertions(+) diff --git a/doc/auth/me.md b/doc/auth/me.md index 4c907e2..26a2e15 100644 --- a/doc/auth/me.md +++ b/doc/auth/me.md @@ -3,3 +3,9 @@ GET `/me` Inputs : just need the JWT cookie Returns the user of the account + +``` +{ + user: ":userId" +} +``` From ae4838166be24eedee63dac2c645b110d05566fc Mon Sep 17 00:00:00 2001 From: adjoly Date: Wed, 1 Oct 2025 19:44:48 +0200 Subject: [PATCH 02/18] =?UTF-8?q?=E3=80=8C=E2=9C=A8=E3=80=8D=20feat(auth-a?= =?UTF-8?q?pi):=20/logout=20added?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- src/api/auth/default.js | 3 +++ src/api/auth/logout.js | 17 +++++++++++++++++ 2 files changed, 20 insertions(+) create mode 100644 src/api/auth/logout.js diff --git a/src/api/auth/default.js b/src/api/auth/default.js index 6a15651..78e7411 100644 --- a/src/api/auth/default.js +++ b/src/api/auth/default.js @@ -10,6 +10,7 @@ import { gRegisterCallback } from './gRegisterCallback.js'; import { totpSetup } from './totpSetup.js'; import { totpDelete } from './totpDelete.js'; import { totpVerify } from './totpVerify.js'; +import { logout } from './logout.js'; const saltRounds = 10; export const appName = process.env.APP_NAME || 'knl_meowscendence'; @@ -107,4 +108,6 @@ export default async function(fastify, options) { } } }, async (request, reply) => { return register(request, reply, saltRounds, fastify); }); + + fastify.get('/logout', {}, async (request, reply) => { return logout(request, reply, fastify); }) } diff --git a/src/api/auth/logout.js b/src/api/auth/logout.js new file mode 100644 index 0000000..d4117b8 --- /dev/null +++ b/src/api/auth/logout.js @@ -0,0 +1,17 @@ +/** + * @async + * @param {import("fastify").FastifyReply} reply + * + * @returns {import("fastify").FastifyReply} + */ +export async function logout(reply) { + try { + return reply + .code(200) + .clearCookie() + .send({ msg: "Logout successful" }); + } catch { + fastify.log.error(err); + return reply.code(500).send({ error: "Internal server error" }); + } +} From e23922d4e3441ccb7b74df9d53a483e3c0a613e5 Mon Sep 17 00:00:00 2001 From: adjoly Date: Wed, 1 Oct 2025 19:50:03 +0200 Subject: [PATCH 03/18] =?UTF-8?q?=E3=80=8C=F0=9F=93=9D=E3=80=8D=20doc(auth?= =?UTF-8?q?-api):=20logout=20doc=20added?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- doc/auth/logout.md | 24 ++++++++++++++++++++++++ 1 file changed, 24 insertions(+) create mode 100644 doc/auth/logout.md diff --git a/doc/auth/logout.md b/doc/auth/logout.md new file mode 100644 index 0000000..98b6edc --- /dev/null +++ b/doc/auth/logout.md @@ -0,0 +1,24 @@ +# Logout + +Available endpoints: +- GET `/logout` + +Common return: +- 500 with response +```json +{ + "error": "Internal server error" +} +``` + +## GET `/logout` + +Used to logout the client (it just delete the cookie) + +Returns: +- 200 with response and clear cookie +```json +{ + "msg": "Logout successful" +} +``` From 544289e2af9f88ae64282ee85f1fc91d3482edc8 Mon Sep 17 00:00:00 2001 From: adjoly Date: Wed, 1 Oct 2025 20:11:27 +0200 Subject: [PATCH 04/18] =?UTF-8?q?=E3=80=8C=F0=9F=94=A8=E3=80=8D=20fix:=20f?= =?UTF-8?q?ixed=20a=20massive=20skill=20issue=20but=20f*ck=20js?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- src/api/auth/default.js | 2 +- src/api/auth/logout.js | 3 ++- 2 files changed, 3 insertions(+), 2 deletions(-) diff --git a/src/api/auth/default.js b/src/api/auth/default.js index 78e7411..0e491ac 100644 --- a/src/api/auth/default.js +++ b/src/api/auth/default.js @@ -109,5 +109,5 @@ export default async function(fastify, options) { } }, async (request, reply) => { return register(request, reply, saltRounds, fastify); }); - fastify.get('/logout', {}, async (request, reply) => { return logout(request, reply, fastify); }) + fastify.get('/logout', {}, async (request, reply) => { return logout(reply, fastify); }) } diff --git a/src/api/auth/logout.js b/src/api/auth/logout.js index d4117b8..84d1d22 100644 --- a/src/api/auth/logout.js +++ b/src/api/auth/logout.js @@ -1,10 +1,11 @@ /** * @async * @param {import("fastify").FastifyReply} reply + * @param {import("fastify").FastifyInstance} fastify * * @returns {import("fastify").FastifyReply} */ -export async function logout(reply) { +export async function logout(reply, fastify) { try { return reply .code(200) From 705571ee120e2f86ade38b2c8768211867aa555c Mon Sep 17 00:00:00 2001 From: adjoly Date: Wed, 1 Oct 2025 20:16:58 +0200 Subject: [PATCH 05/18] =?UTF-8?q?=E3=80=8C=F0=9F=94=A8=E3=80=8D=20fix:=20f?= =?UTF-8?q?ixed=20some=20things.?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- src/api/auth/logout.js | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/api/auth/logout.js b/src/api/auth/logout.js index 84d1d22..b3c57ef 100644 --- a/src/api/auth/logout.js +++ b/src/api/auth/logout.js @@ -9,7 +9,7 @@ export async function logout(reply, fastify) { try { return reply .code(200) - .clearCookie() + .clearCookie("token") .send({ msg: "Logout successful" }); } catch { fastify.log.error(err); From d15161dba4dc676a449282cfbcb49ca5baf89ab8 Mon Sep 17 00:00:00 2001 From: adjoly Date: Mon, 13 Oct 2025 15:10:54 +0200 Subject: [PATCH 06/18] =?UTF-8?q?=E3=80=8C=E2=9C=A8=E3=80=8D=20feat:=20now?= =?UTF-8?q?=20creating=20user=20on=20the=20user=20api=20when=20registering?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .env.example | 3 +++ src/api/auth/gRegisterCallback.js | 3 +++ src/api/auth/register.js | 3 +++ src/utils/authUserCreate.js | 24 ++++++++++++++++++++++++ 4 files changed, 33 insertions(+) create mode 100644 src/utils/authUserCreate.js diff --git a/.env.example b/.env.example index 8ecbc62..72ae740 100644 --- a/.env.example +++ b/.env.example @@ -24,3 +24,6 @@ SMTP_FROM= SMTP_AUTH_USERNAME= SMTP_AUTH_PASSWORD= EMAIL_TO= + +USER_URL= +AUTH_URL= diff --git a/src/api/auth/gRegisterCallback.js b/src/api/auth/gRegisterCallback.js index f79542f..40d8111 100644 --- a/src/api/auth/gRegisterCallback.js +++ b/src/api/auth/gRegisterCallback.js @@ -1,6 +1,7 @@ import axios from 'axios' import authDB from '../../utils/authDB.js'; +import { authUserCreate } from '../../utils/authUserCreate.js'; var env = process.env.NODE_ENV || 'development'; @@ -46,6 +47,8 @@ export async function gRegisterCallback(request, reply, fastify) { authDB.addUser(user.username, ''); + authUserCreate(user.username, fastify) + const token = fastify.jwt.sign(user); return reply diff --git a/src/api/auth/register.js b/src/api/auth/register.js index 7463452..5e10ff1 100644 --- a/src/api/auth/register.js +++ b/src/api/auth/register.js @@ -2,6 +2,7 @@ import bcrypt from 'bcrypt'; import { isValidString } from '../../utils/authUtils.js'; import authDB from '../../utils/authDB.js'; +import { authUserCreate } from '../../utils/authUserCreate.js'; var env = process.env.NODE_ENV || 'development'; @@ -36,6 +37,8 @@ export async function register(request, reply, saltRounds, fastify) { const hash = await bcrypt.hash(password, saltRounds); authDB.addUser(user, hash); + authUserCreate(user, fastify) + const token = fastify.jwt.sign({ user }); return reply diff --git a/src/utils/authUserCreate.js b/src/utils/authUserCreate.js new file mode 100644 index 0000000..d453285 --- /dev/null +++ b/src/utils/authUserCreate.js @@ -0,0 +1,24 @@ +import axios from 'axios'; + +/** + * @param {string} username + * @param {import('fastify').FastifyInstance} fastify + */ +export async function authUserCreate(username, fastify) { + const payload = { + displayName: username, + }; + const cookie = fastify.jwt.sign({ user: "admin" }); + + const url = process.env.USER_URL || "http://localhost:3002/" + + await axios.post( + "http://localhost:3002/users/" + username, + payload, + { + headers: { + 'Cookie': 'token=' + cookie, + }, + } + ); +} From cf59dd07612ab00b40dbf49ca4d11608122cc173 Mon Sep 17 00:00:00 2001 From: adjoly Date: Tue, 14 Oct 2025 13:48:01 +0200 Subject: [PATCH 07/18] =?UTF-8?q?=E3=80=8C=F0=9F=94=A8=E3=80=8D=20fix:=20n?= =?UTF-8?q?ow=20redirecting=20on=20/?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- src/api/auth/gLogCallback.js | 4 +--- src/api/auth/gRegisterCallback.js | 4 +--- 2 files changed, 2 insertions(+), 6 deletions(-) diff --git a/src/api/auth/gLogCallback.js b/src/api/auth/gLogCallback.js index 975b7d6..c596cd4 100644 --- a/src/api/auth/gLogCallback.js +++ b/src/api/auth/gLogCallback.js @@ -45,9 +45,7 @@ export async function gLogCallback(request, reply, fastify) { path: '/', secure: env !== 'development', sameSite: 'lax', - }) - .code(200) - .send({ msg: "Login successful" }); + }).redirect('/'); } catch (error) { fastify.log.error(error); reply.code(500).send({ error: 'Internal server error' }); diff --git a/src/api/auth/gRegisterCallback.js b/src/api/auth/gRegisterCallback.js index f79542f..bfa8a11 100644 --- a/src/api/auth/gRegisterCallback.js +++ b/src/api/auth/gRegisterCallback.js @@ -54,9 +54,7 @@ export async function gRegisterCallback(request, reply, fastify) { path: '/', secure: env !== 'development', sameSite: 'lax', - }) - .code(200) - .send({ msg: "Register successful" }); + }).redirect('/'); } catch (error) { fastify.log.error(error); reply.code(500).send({ error: 'Internal server error' }); From 67cae236e1812fa87804c07d49c61c9e0f41faf6 Mon Sep 17 00:00:00 2001 From: adjoly Date: Tue, 14 Oct 2025 13:49:23 +0200 Subject: [PATCH 08/18] =?UTF-8?q?=E3=80=8C=F0=9F=94=A8=E3=80=8D=20fix:=20g?= =?UTF-8?q?etting=20from=20env=20instead?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- src/api/auth/gLogCallback.js | 2 +- src/api/auth/gRegisterCallback.js | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/src/api/auth/gLogCallback.js b/src/api/auth/gLogCallback.js index c596cd4..a8c2f20 100644 --- a/src/api/auth/gLogCallback.js +++ b/src/api/auth/gLogCallback.js @@ -45,7 +45,7 @@ export async function gLogCallback(request, reply, fastify) { path: '/', secure: env !== 'development', sameSite: 'lax', - }).redirect('/'); + }).redirect(process.env.CALLBACK_REDIR); } catch (error) { fastify.log.error(error); reply.code(500).send({ error: 'Internal server error' }); diff --git a/src/api/auth/gRegisterCallback.js b/src/api/auth/gRegisterCallback.js index bfa8a11..7ef5afc 100644 --- a/src/api/auth/gRegisterCallback.js +++ b/src/api/auth/gRegisterCallback.js @@ -54,7 +54,7 @@ export async function gRegisterCallback(request, reply, fastify) { path: '/', secure: env !== 'development', sameSite: 'lax', - }).redirect('/'); + }).redirect(process.env.CALLBACK_REDIR); } catch (error) { fastify.log.error(error); reply.code(500).send({ error: 'Internal server error' }); From 036798ab56f649b70ba9e5f524ae64a3164d0065 Mon Sep 17 00:00:00 2001 From: adjoly Date: Tue, 14 Oct 2025 13:54:20 +0200 Subject: [PATCH 09/18] =?UTF-8?q?=E3=80=8C=F0=9F=93=9D=E3=80=8D=20doc:=20a?= =?UTF-8?q?dded=20redir=20env?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .env.example | 3 +++ 1 file changed, 3 insertions(+) diff --git a/.env.example b/.env.example index 8ecbc62..ed35459 100644 --- a/.env.example +++ b/.env.example @@ -12,6 +12,8 @@ GRAPH_PORT=3000 ELK_PORT=5601 GOOGLE_CALLBACK_URL=https://localhost:8443/api/v1 +# the url to which the user will be redirected when it logs with google +CALLBACK_REDIR=http://localhost:3000 GOOGLE_CLIENT_SECRET=susAF GOOGLE_CLIENT_ID=Really @@ -24,3 +26,4 @@ SMTP_FROM= SMTP_AUTH_USERNAME= SMTP_AUTH_PASSWORD= EMAIL_TO= + From d80beff543f91abe616e007d2007876145821d0b Mon Sep 17 00:00:00 2001 From: adjoly Date: Tue, 14 Oct 2025 18:24:22 +0200 Subject: [PATCH 10/18] =?UTF-8?q?=E3=80=8C=F0=9F=94=A8=E3=80=8D=20fix:=20f?= =?UTF-8?q?ixed=20cookie=20with=20google=20callback?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- src/api/auth/gLogCallback.js | 2 +- src/api/auth/gRegisterCallback.js | 2 +- src/utils/authUserCreate.js | 2 +- 3 files changed, 3 insertions(+), 3 deletions(-) diff --git a/src/api/auth/gLogCallback.js b/src/api/auth/gLogCallback.js index a8c2f20..6b3c78b 100644 --- a/src/api/auth/gLogCallback.js +++ b/src/api/auth/gLogCallback.js @@ -37,7 +37,7 @@ export async function gLogCallback(request, reply, fastify) { return reply.code(400).send({ error: "User does not exist" }); } - const token = fastify.jwt.sign(user); + const token = fastify.jwt.sign({ user: user.username}); return reply .setCookie('token', token, { diff --git a/src/api/auth/gRegisterCallback.js b/src/api/auth/gRegisterCallback.js index 4265413..217fae5 100644 --- a/src/api/auth/gRegisterCallback.js +++ b/src/api/auth/gRegisterCallback.js @@ -49,7 +49,7 @@ export async function gRegisterCallback(request, reply, fastify) { authUserCreate(user.username, fastify) - const token = fastify.jwt.sign(user); + const token = fastify.jwt.sign({ user: user.username}); return reply .setCookie('token', token, { diff --git a/src/utils/authUserCreate.js b/src/utils/authUserCreate.js index d453285..a1d6bba 100644 --- a/src/utils/authUserCreate.js +++ b/src/utils/authUserCreate.js @@ -13,7 +13,7 @@ export async function authUserCreate(username, fastify) { const url = process.env.USER_URL || "http://localhost:3002/" await axios.post( - "http://localhost:3002/users/" + username, + url + "users/" + username, payload, { headers: { From 2cafd7afac0604906f2e1f635ab7deb6bfb5a7f1 Mon Sep 17 00:00:00 2001 From: adjoly Date: Thu, 16 Oct 2025 13:25:36 +0200 Subject: [PATCH 11/18] =?UTF-8?q?=E3=80=8C=E2=9C=A8=E3=80=8D=20feat:=20add?= =?UTF-8?q?ed=20env=20variable=20to=20front?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- docker/api-base/compose.yml | 2 +- docker/front/Dockerfile | 7 +++++-- docker/front/compose.yml | 3 +++ src/utils/authUserCreate.js | 2 +- 4 files changed, 10 insertions(+), 4 deletions(-) diff --git a/docker/api-base/compose.yml b/docker/api-base/compose.yml index 76b987e..85b77c4 100644 --- a/docker/api-base/compose.yml +++ b/docker/api-base/compose.yml @@ -29,7 +29,7 @@ services: - back environment: - TZ=Europe/Paris - - GOOGLE_CALLBACK_URL=${GOOGLE_CALLBACK_URL} + - GOOGLE_CALLBACK_URL=${AUTH_URL} - GOOGLE_CLIENT_ID=${GOOGLE_CLIENT_ID} - GOOGLE_CLIENT_SECRET=${GOOGLE_CLIENT_SECRET} - API_TARGET=auth diff --git a/docker/front/Dockerfile b/docker/front/Dockerfile index b8f2ce2..36fc0e5 100644 --- a/docker/front/Dockerfile +++ b/docker/front/Dockerfile @@ -13,6 +13,9 @@ RUN cd /build \ FROM node:lts-alpine AS builder-vite +ARG VITE_USER_URL +ARG VITE_AUTH_URL + RUN npm install -g pnpm WORKDIR /app @@ -24,8 +27,8 @@ RUN pnpm install --frozen-lockfile COPY vite.config.js tailwind.config.js ./ COPY src ./src -RUN pnpm vite build - +RUN VITE_USER_URL=${VITE_USER_URL} VITE_AUTH_URL=${VITE_AUTH_URL}\ + pnpm vite build FROM alpine:3.22 diff --git a/docker/front/compose.yml b/docker/front/compose.yml index 72b2b67..134b29d 100644 --- a/docker/front/compose.yml +++ b/docker/front/compose.yml @@ -4,6 +4,9 @@ services: build: dockerfile: docker/front/Dockerfile context: ../../ + args: + - VITE_USER_URL=${USER_URL} + - VITE_AUTH_URL=${AUTH_URL} environment: - TZ=Europe/Paris networks: diff --git a/src/utils/authUserCreate.js b/src/utils/authUserCreate.js index a1d6bba..1ee3d38 100644 --- a/src/utils/authUserCreate.js +++ b/src/utils/authUserCreate.js @@ -10,7 +10,7 @@ export async function authUserCreate(username, fastify) { }; const cookie = fastify.jwt.sign({ user: "admin" }); - const url = process.env.USER_URL || "http://localhost:3002/" + const url = process.env.USER_URL + "/" || "http://localhost:3002/" await axios.post( url + "users/" + username, From 627197f8f3ca5a5d0e09f9064ad45b9059594a5a Mon Sep 17 00:00:00 2001 From: adjoly Date: Thu, 16 Oct 2025 13:28:07 +0200 Subject: [PATCH 12/18] =?UTF-8?q?=E3=80=8C=F0=9F=94=A8=E3=80=8D=20fix:=20f?= =?UTF-8?q?ixed=20this=20shit?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- src/utils/authUserCreate.js | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/utils/authUserCreate.js b/src/utils/authUserCreate.js index 1ee3d38..e8a6771 100644 --- a/src/utils/authUserCreate.js +++ b/src/utils/authUserCreate.js @@ -10,10 +10,10 @@ export async function authUserCreate(username, fastify) { }; const cookie = fastify.jwt.sign({ user: "admin" }); - const url = process.env.USER_URL + "/" || "http://localhost:3002/" + const url = process.env.USER_URL || "http://localhost:3002" await axios.post( - url + "users/" + username, + url + "/users/" + username, payload, { headers: { From 2314b0bd3a2b3a37769ef7e8a4ddbd2c04f5ee43 Mon Sep 17 00:00:00 2001 From: adjoly Date: Sat, 18 Oct 2025 20:04:34 +0200 Subject: [PATCH 13/18] =?UTF-8?q?=E3=80=8C=F0=9F=8F=97=EF=B8=8F=E3=80=8D?= =?UTF-8?q?=20wip:=20starting=20being=20a=20fullstack=20dev?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- src/front/static/ts/main.ts | 31 +++++++++---------- src/front/static/ts/views/Friends.ts | 45 ++++++++++++++++++++++++++++ 2 files changed, 59 insertions(+), 17 deletions(-) create mode 100644 src/front/static/ts/views/Friends.ts diff --git a/src/front/static/ts/main.ts b/src/front/static/ts/main.ts index 6533fd8..112b5a9 100644 --- a/src/front/static/ts/main.ts +++ b/src/front/static/ts/main.ts @@ -7,10 +7,9 @@ export async function isLogged(): Promise { method: "GET", credentials: "include", }); - if (uuid_req.status === 200) - { + if (uuid_req.status === 200) { let uuid = await uuid_req.json(); - document.cookie = `uuid=${uuid.user};max-age=${60*60*24*7}`; + document.cookie = `uuid=${uuid.user};max-age=${60 * 60 * 24 * 7}`; return true; } else // 401 @@ -40,6 +39,8 @@ const routes = [ { path: "/login", view: () => import("./views/LoginPage.ts") }, { path: "/register", view: () => import("./views/RegisterPage.ts") }, + + { path: "/friends", view: () => import("./views/Friends.ts") } ]; const router = async () => { @@ -65,20 +66,18 @@ const router = async () => { view.run(); }; -document.getElementById("profile-button")?.addEventListener("click", () => {profile_view.run();}); +document.getElementById("profile-button")?.addEventListener("click", () => { profile_view.run(); }); window.addEventListener("popstate", router); document.addEventListener("DOMContentLoaded", () => { isLogged(); - document.body.addEventListener("click", e=> { - if (!e.target.closest("#taskbar-menu") && !e.target.matches("#profile-button")) - { - profile_view.open = false; - document.getElementById("taskbar-menu").innerHTML = ""; - } - if (e.target.matches("[data-link]")) - { + document.body.addEventListener("click", e => { + if (!e.target.closest("#taskbar-menu") && !e.target.matches("#profile-button")) { + profile_view.open = false; + document.getElementById("taskbar-menu").innerHTML = ""; + } + if (e.target.matches("[data-link]")) { e.preventDefault(); navigationManager(e.target.href); } @@ -86,9 +85,8 @@ document.addEventListener("DOMContentLoaded", () => { e.preventDefault(); }); - document.body.addEventListener("dblclick", e=> { - if (e.target.closest("[data-icon]")) - { + document.body.addEventListener("dblclick", e => { + if (e.target.closest("[data-icon]")) { e.preventDefault(); navigationManager(e.target.closest("[data-icon]").href); } @@ -99,8 +97,7 @@ document.addEventListener("DOMContentLoaded", () => { oneko(); -function updateClock() -{ +function updateClock() { const days = ['sun', 'mon', 'tue', 'wed', 'thu', 'fri', 'sat']; const months = ['jan', 'feb', 'mar', 'apr', 'may', 'jun', 'jul', 'aug', 'sep', 'oct', 'nov', 'dec']; const clock = document.getElementById("taskbar-clock"); diff --git a/src/front/static/ts/views/Friends.ts b/src/front/static/ts/views/Friends.ts new file mode 100644 index 0000000..d384508 --- /dev/null +++ b/src/front/static/ts/views/Friends.ts @@ -0,0 +1,45 @@ +import Aview from "./Aview.ts" +import { setOnekoState } from "../oneko.ts" + +export default class extends Aview { + + constructor() { + super(); + this.setTitle("Friends list"); + setOnekoState("default"); + } + + async getHTML() { + return ` +
+
+ friends.ts +
+ + + × +
+
+ +
+

+
+
+ `; + } + + async run() { + let uuid: String; + + uuid = document.cookie.match(new RegExp('(^| )' + "uuid" + '=([^;]+)'))[2]; + + const userdata_req = await fetch(`http://localhost:3002/users/${uuid}`, { + method: "GET", + credentials: "include", + }); + if (userdata_req.status == 404) { + console.error("invalid user"); + return; + } + } +} From 451a7e88a3f0226635228cd61c507529e7821919 Mon Sep 17 00:00:00 2001 From: adjoly Date: Sat, 18 Oct 2025 21:29:51 +0200 Subject: [PATCH 14/18] =?UTF-8?q?=E3=80=8C=F0=9F=8F=97=EF=B8=8F=E3=80=8D?= =?UTF-8?q?=20wip:=20friends=20list=20working=20(kinda)?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- src/front/static/ts/views/Friends.ts | 65 +++++++++++++++++++++++----- 1 file changed, 55 insertions(+), 10 deletions(-) diff --git a/src/front/static/ts/views/Friends.ts b/src/front/static/ts/views/Friends.ts index d384508..2908abf 100644 --- a/src/front/static/ts/views/Friends.ts +++ b/src/front/static/ts/views/Friends.ts @@ -1,5 +1,6 @@ import Aview from "./Aview.ts" import { setOnekoState } from "../oneko.ts" +import { dragElement } from "./drag.ts"; export default class extends Aview { @@ -21,8 +22,11 @@ export default class extends Aview { -
-

+
+ + +
`; @@ -31,15 +35,56 @@ export default class extends Aview { async run() { let uuid: String; - uuid = document.cookie.match(new RegExp('(^| )' + "uuid" + '=([^;]+)'))[2]; + dragElement(document.getElementById("window")); + const n_friends = (document.getElementById("friends_n") as HTMLParagraphElement); + const friends_error_message = (document.getElementById("friends-error-message") as HTMLParagraphElement); + const friends_list = (document.getElementById("friends_list") as HTMLUListElement); - const userdata_req = await fetch(`http://localhost:3002/users/${uuid}`, { - method: "GET", - credentials: "include", - }); - if (userdata_req.status == 404) { - console.error("invalid user"); - return; + try { + uuid = document.cookie.match(new RegExp('(^| )' + "uuid" + '=([^;]+)'))[2]; + const data_req = await fetch("http://localhost:3002/users/" + uuid + "/friends/count", { + method: "GET", + headers: { + "Content-Type": "application/json", + }, + credentials: "include", + }); + if (data_req.status === 200) { + let data = await data_req.json(); + n_friends.innerHTML = ":D friends count : " + data.n_friends; + n_friends.classList.remove("hidden"); + + if (data.n_friends > 0) { + const list_req = await fetch("http://localhost:3002/users/" + uuid + "/friends?iStart=0&iEnd=20", { + method: "GET", + headers: { + "Content-Type": "application/json", + }, + credentials: "include", + }); + if (list_req.status === 200) { + friends_list.classList.remove("hidden") + + let list = (await list_req.json()).friends as JSON; + + for (let i = 0; i < data.n_friends; i++) { + let new_friends = document.createElement('li') + new_friends.innerHTML = list[i].friendName; + friends_list.appendChild(new_friends); + } + } else { + n_friends.classList.add("hidden"); + friends_error_message.innerHTML = (await list_req.json()).error; + friends_error_message.classList.remove("hidden"); + } + } else { + friends_error_message.innerHTML = "failed to fetch friends"; + friends_error_message.classList.remove("hidden"); + } + } + } catch (error) { + friends_error_message.innerHTML = "failed to fetch friends"; + friends_error_message.classList.remove("hidden"); } } } From c0b019064d78a7cf0d03e9a01df1c1c477365ba2 Mon Sep 17 00:00:00 2001 From: adjoly Date: Sat, 18 Oct 2025 21:55:49 +0200 Subject: [PATCH 15/18] =?UTF-8?q?=E3=80=8C=F0=9F=8F=97=EF=B8=8F=E3=80=8D?= =?UTF-8?q?=20wip:=20add=20and=20remove=20working?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- src/front/static/ts/views/Friends.ts | 131 +++++++++++++++++++++------ 1 file changed, 103 insertions(+), 28 deletions(-) diff --git a/src/front/static/ts/views/Friends.ts b/src/front/static/ts/views/Friends.ts index 2908abf..054ea3f 100644 --- a/src/front/static/ts/views/Friends.ts +++ b/src/front/static/ts/views/Friends.ts @@ -23,6 +23,14 @@ export default class extends Aview {
+ +
+ + + + + +
- -
+ -
+
+
-
- 12:37 +
+ +
+ 12:37 +
diff --git a/src/front/static/ts/main.ts b/src/front/static/ts/main.ts index 5301e4e..731a972 100644 --- a/src/front/static/ts/main.ts +++ b/src/front/static/ts/main.ts @@ -1,6 +1,8 @@ import { oneko } from "./oneko.ts"; import ProfileMenu from "./views/ProfileMenu.ts"; +import FriendsMenu from "./views/Friends.ts"; let profile_view = new ProfileMenu; +let friends_view = new FriendsMenu; export async function isLogged(): Promise { let uuid_req = await fetch("http://localhost:3001/me", { @@ -40,7 +42,6 @@ const routes = [ { path: "/login", view: () => import("./views/LoginPage.ts") }, { path: "/register", view: () => import("./views/RegisterPage.ts") }, - { path: "/friends", view: () => import("./views/Friends.ts") }, { path: "/profile", view: () => import("./views/Profile.ts") }, { path: "/settings", view: () => import("./views/Settings.ts") }, ]; @@ -74,11 +75,17 @@ window.addEventListener("popstate", router); document.addEventListener("DOMContentLoaded", () => { isLogged(); + + document.body.addEventListener("click", e => { if (!e.target.closest("#taskbar-menu") && !e.target.matches("#profile-button")) { profile_view.open = false; document.getElementById("taskbar-menu").innerHTML = ""; } + if (e.target.matches("#friends-btn")) { + friends_view.open = !friends_view.open; + friends_view.run(); + } if (e.target.matches("[data-link]")) { e.preventDefault(); navigationManager(e.target.href); @@ -114,6 +121,8 @@ function updateClock() clock.innerHTML = `${days[now.getDay()]} ${now.getDate()} ${months[now.getMonth()]} ` + hours + ":" + minutes; } +friends_view.run(); + setInterval(updateClock, 5000); updateClock(); diff --git a/src/front/static/ts/views/Friends.ts b/src/front/static/ts/views/Friends.ts index 2a9d0b3..7e11e4e 100644 --- a/src/front/static/ts/views/Friends.ts +++ b/src/front/static/ts/views/Friends.ts @@ -5,6 +5,8 @@ import { isLogged, navigationManager } from "../main.ts" export default class extends Aview { + open: Boolean = false; + constructor() { super(); this.setTitle("friends list"); @@ -13,28 +15,22 @@ export default class extends Aview { async getHTML() { return ` -
-
+
+
friends.ts -
- - - × -
-
-
- - +
+ + + - -
-
@@ -46,27 +42,37 @@ export default class extends Aview { if (!await isLogged()) navigationManager("/"); - dragElement(document.getElementById("window")); + if (this.open === true) { + document.getElementById("friends-menu").innerHTML = await this.getHTML(); + } else { + document.getElementById("friends-menu").innerHTML = ""; + return; + } + let uuid: String; uuid = document.cookie.match(new RegExp('(^| )' + "uuid" + '=([^;]+)'))[2]; - const n_friends = (document.getElementById("friends_n") as HTMLParagraphElement); const friends_error_message = (document.getElementById("friends-error-message") as HTMLParagraphElement); - const friends_message = (document.getElementById("friends-msg") as HTMLParagraphElement) const friends_list = (document.getElementById("friends_list") as HTMLUListElement); const new_friend = (document.getElementById("new-friend") as HTMLInputElement); const add_friend_err = (document.getElementById("add-friend-err") as HTMLParagraphElement); const add_friend_msg = (document.getElementById("add-friend-msg") as HTMLParagraphElement); - async function removeFriend(name) { + async function removeFriend(name: String) { const data_req = await fetch("http://localhost:3002/users/" + uuid + "/friends/" + name, { method: "DELETE", credentials: "include", }); if (data_req.status === 200) { - console.log("friends removed success fully"); + console.log("friends removed successfully"); } else { console.log("could not remove friend"); } + list_friends(); + list_friends(); + list_friends(); + list_friends(); + list_friends(); + list_friends(); } async function isFriendLogged(name: string): Promise { @@ -92,6 +98,9 @@ export default class extends Aview { if (data_req.status === 404) { } let data = await data_req.json(); + while (friends_list.firstChild) { + friends_list.removeChild(friends_list.firstChild); + } if (data.n_friends > 0) { const list_req = await fetch("http://localhost:3002/users/" + uuid + "/friends?iStart=0&iEnd=2147483647", { @@ -105,9 +114,6 @@ export default class extends Aview { friends_list.classList.add("hidden") return; } else if (list_req.status === 200) { - while (friends_list.firstChild) { - friends_list.removeChild(friends_list.firstChild); - } friends_list.classList.remove("hidden") let list = (await list_req.json()).friends as JSON; @@ -120,7 +126,7 @@ export default class extends Aview { activitySpan.textContent = "•"; if (isLogged == true) activitySpan.className = "px-0 text-green-500"; - else + else activitySpan.className = "px-0 text-red-500"; @@ -130,11 +136,10 @@ export default class extends Aview { const but = document.createElement('button'); but.textContent = "-"; - but.className = "bg-red-500 text-white px-2 py-0 rounded hover:bg-red-600"; + but.classList.add("px-0", "py-0", "taskbar-button"); but.onclick = function() { removeFriend(list[i].friendName); - list_friends() - } + }; new_friends.appendChild(activitySpan); new_friends.appendChild(span); @@ -142,17 +147,14 @@ export default class extends Aview { friends_list.appendChild(new_friends); } } else { - n_friends.classList.add("hidden"); friends_error_message.innerHTML = (await list_req.json()).error; friends_error_message.classList.remove("hidden"); } } else { - friends_message.innerHTML = "you have no friends D:"; - friends_message.classList.remove("hidden"); + friends_list.classList.add("hidden") } } - const add_friend = async () => { const data_req = await fetch("http://localhost:3002/users/" + uuid + "/friends/" + new_friend.value, { method: "POST", @@ -185,10 +187,7 @@ export default class extends Aview { credentials: "include", }); if (data_req.status === 200) { - let data = await data_req.json(); - n_friends.innerHTML = ":D friends count : " + data.n_friends; - n_friends.classList.remove("hidden"); - + // let data = await data_req.json(); list_friends() } } catch (error) { diff --git a/src/front/static/ts/views/ProfileMenu.ts b/src/front/static/ts/views/ProfileMenu.ts index 9409360..c2937d5 100644 --- a/src/front/static/ts/views/ProfileMenu.ts +++ b/src/front/static/ts/views/ProfileMenu.ts @@ -2,7 +2,6 @@ import Aview from "./Aview.ts" import { isLogged, navigationManager } from "../main.ts" export default class extends Aview { - async getHTML() { return `