mirror of
https://github.com/KeyZox71/knl_meowscendence.git
synced 2025-12-31 21:56:41 +01:00
Merge branch 'front' of github.com:keyzox71/knl_meowscendence into front
This commit is contained in:
@ -11,7 +11,8 @@ GRAPH_PORT=3000
|
|||||||
|
|
||||||
ELK_PORT=5601
|
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_SECRET=susAF
|
||||||
GOOGLE_CLIENT_ID=Really
|
GOOGLE_CLIENT_ID=Really
|
||||||
|
|
||||||
@ -25,4 +26,6 @@ SMTP_AUTH_USERNAME=<smtp-user>
|
|||||||
SMTP_AUTH_PASSWORD=<smtp pass>
|
SMTP_AUTH_PASSWORD=<smtp pass>
|
||||||
EMAIL_TO=<mail to send to>
|
EMAIL_TO=<mail to send to>
|
||||||
|
|
||||||
|
USER_URL=<the url to the user api>
|
||||||
|
AUTH_URL=<the url to the auth api>
|
||||||
CORS_ORIGIN=<the url of origin for cors>
|
CORS_ORIGIN=<the url of origin for cors>
|
||||||
|
|||||||
24
doc/auth/logout.md
Normal file
24
doc/auth/logout.md
Normal file
@ -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"
|
||||||
|
}
|
||||||
|
```
|
||||||
@ -3,3 +3,9 @@ GET `/me`
|
|||||||
Inputs : just need the JWT cookie
|
Inputs : just need the JWT cookie
|
||||||
|
|
||||||
Returns the user of the account
|
Returns the user of the account
|
||||||
|
|
||||||
|
```
|
||||||
|
{
|
||||||
|
user: ":userId"
|
||||||
|
}
|
||||||
|
```
|
||||||
|
|||||||
@ -30,7 +30,7 @@ services:
|
|||||||
- back
|
- back
|
||||||
environment:
|
environment:
|
||||||
- TZ=Europe/Paris
|
- TZ=Europe/Paris
|
||||||
- GOOGLE_CALLBACK_URL=${GOOGLE_CALLBACK_URL}
|
- GOOGLE_CALLBACK_URL=${AUTH_URL}
|
||||||
- GOOGLE_CLIENT_ID=${GOOGLE_CLIENT_ID}
|
- GOOGLE_CLIENT_ID=${GOOGLE_CLIENT_ID}
|
||||||
- GOOGLE_CLIENT_SECRET=${GOOGLE_CLIENT_SECRET}
|
- GOOGLE_CLIENT_SECRET=${GOOGLE_CLIENT_SECRET}
|
||||||
- API_TARGET=auth
|
- API_TARGET=auth
|
||||||
|
|||||||
@ -13,6 +13,9 @@ RUN cd /build \
|
|||||||
|
|
||||||
FROM node:lts-alpine AS builder-vite
|
FROM node:lts-alpine AS builder-vite
|
||||||
|
|
||||||
|
ARG VITE_USER_URL
|
||||||
|
ARG VITE_AUTH_URL
|
||||||
|
|
||||||
RUN npm install -g pnpm
|
RUN npm install -g pnpm
|
||||||
|
|
||||||
WORKDIR /app
|
WORKDIR /app
|
||||||
@ -24,8 +27,8 @@ RUN pnpm install --frozen-lockfile
|
|||||||
COPY vite.config.js tailwind.config.js ./
|
COPY vite.config.js tailwind.config.js ./
|
||||||
COPY src ./src
|
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
|
FROM alpine:3.22
|
||||||
|
|
||||||
|
|||||||
@ -4,6 +4,9 @@ services:
|
|||||||
build:
|
build:
|
||||||
dockerfile: docker/front/Dockerfile
|
dockerfile: docker/front/Dockerfile
|
||||||
context: ../../
|
context: ../../
|
||||||
|
args:
|
||||||
|
- VITE_USER_URL=${USER_URL}
|
||||||
|
- VITE_AUTH_URL=${AUTH_URL}
|
||||||
environment:
|
environment:
|
||||||
- TZ=Europe/Paris
|
- TZ=Europe/Paris
|
||||||
networks:
|
networks:
|
||||||
|
|||||||
@ -11,6 +11,7 @@ import { gRegisterCallback } from './gRegisterCallback.js';
|
|||||||
import { totpSetup } from './totpSetup.js';
|
import { totpSetup } from './totpSetup.js';
|
||||||
import { totpDelete } from './totpDelete.js';
|
import { totpDelete } from './totpDelete.js';
|
||||||
import { totpVerify } from './totpVerify.js';
|
import { totpVerify } from './totpVerify.js';
|
||||||
|
import { logout } from './logout.js';
|
||||||
|
|
||||||
const saltRounds = 10;
|
const saltRounds = 10;
|
||||||
export const appName = process.env.APP_NAME || 'knl_meowscendence';
|
export const appName = process.env.APP_NAME || 'knl_meowscendence';
|
||||||
@ -114,4 +115,6 @@ export default async function(fastify, options) {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
}, async (request, reply) => { return register(request, reply, saltRounds, fastify); });
|
}, async (request, reply) => { return register(request, reply, saltRounds, fastify); });
|
||||||
|
|
||||||
|
fastify.get('/logout', {}, async (request, reply) => { return logout(reply, fastify); })
|
||||||
}
|
}
|
||||||
|
|||||||
@ -37,7 +37,7 @@ export async function gLogCallback(request, reply, fastify) {
|
|||||||
return reply.code(400).send({ error: "User does not exist" });
|
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
|
return reply
|
||||||
.setCookie('token', token, {
|
.setCookie('token', token, {
|
||||||
@ -45,9 +45,7 @@ export async function gLogCallback(request, reply, fastify) {
|
|||||||
path: '/',
|
path: '/',
|
||||||
secure: env !== 'development',
|
secure: env !== 'development',
|
||||||
sameSite: 'lax',
|
sameSite: 'lax',
|
||||||
})
|
}).redirect(process.env.CALLBACK_REDIR);
|
||||||
.code(200)
|
|
||||||
.send({ msg: "Login successful" });
|
|
||||||
} catch (error) {
|
} catch (error) {
|
||||||
fastify.log.error(error);
|
fastify.log.error(error);
|
||||||
reply.code(500).send({ error: 'Internal server error' });
|
reply.code(500).send({ error: 'Internal server error' });
|
||||||
|
|||||||
@ -1,6 +1,7 @@
|
|||||||
import axios from 'axios'
|
import axios from 'axios'
|
||||||
|
|
||||||
import authDB from '../../utils/authDB.js';
|
import authDB from '../../utils/authDB.js';
|
||||||
|
import { authUserCreate } from '../../utils/authUserCreate.js';
|
||||||
|
|
||||||
var env = process.env.NODE_ENV || 'development';
|
var env = process.env.NODE_ENV || 'development';
|
||||||
|
|
||||||
@ -46,7 +47,9 @@ export async function gRegisterCallback(request, reply, fastify) {
|
|||||||
|
|
||||||
authDB.addUser(user.username, '');
|
authDB.addUser(user.username, '');
|
||||||
|
|
||||||
const token = fastify.jwt.sign(user);
|
authUserCreate(user.username, fastify)
|
||||||
|
|
||||||
|
const token = fastify.jwt.sign({ user: user.username});
|
||||||
|
|
||||||
return reply
|
return reply
|
||||||
.setCookie('token', token, {
|
.setCookie('token', token, {
|
||||||
@ -54,9 +57,7 @@ export async function gRegisterCallback(request, reply, fastify) {
|
|||||||
path: '/',
|
path: '/',
|
||||||
secure: env !== 'development',
|
secure: env !== 'development',
|
||||||
sameSite: 'lax',
|
sameSite: 'lax',
|
||||||
})
|
}).redirect(process.env.CALLBACK_REDIR);
|
||||||
.code(200)
|
|
||||||
.send({ msg: "Register successful" });
|
|
||||||
} catch (error) {
|
} catch (error) {
|
||||||
fastify.log.error(error);
|
fastify.log.error(error);
|
||||||
reply.code(500).send({ error: 'Internal server error' });
|
reply.code(500).send({ error: 'Internal server error' });
|
||||||
|
|||||||
18
src/api/auth/logout.js
Normal file
18
src/api/auth/logout.js
Normal file
@ -0,0 +1,18 @@
|
|||||||
|
/**
|
||||||
|
* @async
|
||||||
|
* @param {import("fastify").FastifyReply} reply
|
||||||
|
* @param {import("fastify").FastifyInstance} fastify
|
||||||
|
*
|
||||||
|
* @returns {import("fastify").FastifyReply}
|
||||||
|
*/
|
||||||
|
export async function logout(reply, fastify) {
|
||||||
|
try {
|
||||||
|
return reply
|
||||||
|
.code(200)
|
||||||
|
.clearCookie("token")
|
||||||
|
.send({ msg: "Logout successful" });
|
||||||
|
} catch {
|
||||||
|
fastify.log.error(err);
|
||||||
|
return reply.code(500).send({ error: "Internal server error" });
|
||||||
|
}
|
||||||
|
}
|
||||||
@ -2,6 +2,7 @@ import bcrypt from 'bcrypt';
|
|||||||
|
|
||||||
import { isValidString } from '../../utils/authUtils.js';
|
import { isValidString } from '../../utils/authUtils.js';
|
||||||
import authDB from '../../utils/authDB.js';
|
import authDB from '../../utils/authDB.js';
|
||||||
|
import { authUserCreate } from '../../utils/authUserCreate.js';
|
||||||
|
|
||||||
var env = process.env.NODE_ENV || 'development';
|
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);
|
const hash = await bcrypt.hash(password, saltRounds);
|
||||||
authDB.addUser(user, hash);
|
authDB.addUser(user, hash);
|
||||||
|
|
||||||
|
authUserCreate(user, fastify)
|
||||||
|
|
||||||
const token = fastify.jwt.sign({ user });
|
const token = fastify.jwt.sign({ user });
|
||||||
|
|
||||||
return reply
|
return reply
|
||||||
|
|||||||
@ -36,6 +36,7 @@
|
|||||||
</div>
|
</div>
|
||||||
|
|
||||||
<div id="taskbar-menu" class="absolute bottom-13 left-0"></div>
|
<div id="taskbar-menu" class="absolute bottom-13 left-0"></div>
|
||||||
|
<div id="friends-menu" class="absolute bottom-13 right-0"></div>
|
||||||
|
|
||||||
<div class="border-t-2 border-neutral-300 dark:border-neutral-800 sticky bottom-0">
|
<div class="border-t-2 border-neutral-300 dark:border-neutral-800 sticky bottom-0">
|
||||||
<nav class="bg-neutral-200 dark:bg-neutral-900 shadow-md border-t-2 border-neutral-400 dark:border-neutral-700 flex justify-between h-12 items-center content-center space-x-6 font-[Kubasta]">
|
<nav class="bg-neutral-200 dark:bg-neutral-900 shadow-md border-t-2 border-neutral-400 dark:border-neutral-700 flex justify-between h-12 items-center content-center space-x-6 font-[Kubasta]">
|
||||||
@ -45,8 +46,11 @@
|
|||||||
<a target="_blank" class="taskbar-button" href="https://rusty.42angouleme.fr/">rusty</a>
|
<a target="_blank" class="taskbar-button" href="https://rusty.42angouleme.fr/">rusty</a>
|
||||||
<a target="_blank" class="taskbar-button" href="https://dn720004.ca.archive.org/0/items/2009-tetris-variant-concepts_202201/2009%20Tetris%20Design%20Guideline.pdf">tetris-guideline.pdf</a>
|
<a target="_blank" class="taskbar-button" href="https://dn720004.ca.archive.org/0/items/2009-tetris-variant-concepts_202201/2009%20Tetris%20Design%20Guideline.pdf">tetris-guideline.pdf</a>
|
||||||
</div>
|
</div>
|
||||||
<div class="reverse-border m-1.5 h-8/10 content-center">
|
<div class="flex px-4 items-center content-center space-x-2">
|
||||||
<span id="taskbar-clock" class="text- neutral-900 dark:text-white px-4">12:37</span>
|
<button id="friends-btn" class="taskbar-button">friends</button>
|
||||||
|
<div class="reverse-border m-1.5 h-8/10 content-center">
|
||||||
|
<span id="taskbar-clock" class="text-neutral-900 dark:text-white px-4">12:37</span>
|
||||||
|
</div>
|
||||||
</div>
|
</div>
|
||||||
</nav>
|
</nav>
|
||||||
</div>
|
</div>
|
||||||
|
|||||||
@ -1,6 +1,8 @@
|
|||||||
import { oneko } from "./oneko.ts";
|
import { oneko } from "./oneko.ts";
|
||||||
import ProfileMenu from "./views/ProfileMenu.ts";
|
import ProfileMenu from "./views/ProfileMenu.ts";
|
||||||
|
import FriendsMenu from "./views/Friends.ts";
|
||||||
let profile_view = new ProfileMenu;
|
let profile_view = new ProfileMenu;
|
||||||
|
let friends_view = new FriendsMenu;
|
||||||
|
|
||||||
export async function isLogged(): Promise<boolean> {
|
export async function isLogged(): Promise<boolean> {
|
||||||
let uuid_req = await fetch("http://localhost:3001/me", {
|
let uuid_req = await fetch("http://localhost:3001/me", {
|
||||||
@ -78,6 +80,10 @@ document.addEventListener("DOMContentLoaded", () => {
|
|||||||
profile_view.open = false;
|
profile_view.open = false;
|
||||||
document.getElementById("taskbar-menu").innerHTML = "";
|
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]")) {
|
if (e.target.matches("[data-link]")) {
|
||||||
e.preventDefault();
|
e.preventDefault();
|
||||||
navigationManager(e.target.href);
|
navigationManager(e.target.href);
|
||||||
@ -96,7 +102,10 @@ document.addEventListener("DOMContentLoaded", () => {
|
|||||||
router();
|
router();
|
||||||
});
|
});
|
||||||
|
|
||||||
function updateClock() {
|
oneko();
|
||||||
|
|
||||||
|
function updateClock()
|
||||||
|
{
|
||||||
const days = ['sun', 'mon', 'tue', 'wed', 'thu', 'fri', 'sat'];
|
const days = ['sun', 'mon', 'tue', 'wed', 'thu', 'fri', 'sat'];
|
||||||
const months = ['jan', 'feb', 'mar', 'apr', 'may', 'jun', 'jul', 'aug', 'sep', 'oct', 'nov', 'dec'];
|
const months = ['jan', 'feb', 'mar', 'apr', 'may', 'jun', 'jul', 'aug', 'sep', 'oct', 'nov', 'dec'];
|
||||||
const clock = document.getElementById("taskbar-clock");
|
const clock = document.getElementById("taskbar-clock");
|
||||||
|
|||||||
200
src/front/static/ts/views/Friends.ts
Normal file
200
src/front/static/ts/views/Friends.ts
Normal file
@ -0,0 +1,200 @@
|
|||||||
|
import Aview from "./Aview.ts"
|
||||||
|
import { setOnekoState } from "../oneko.ts"
|
||||||
|
import { dragElement } from "./drag.ts";
|
||||||
|
import { isLogged, navigationManager } from "../main.ts"
|
||||||
|
|
||||||
|
export default class extends Aview {
|
||||||
|
|
||||||
|
open: Boolean = false;
|
||||||
|
|
||||||
|
constructor() {
|
||||||
|
super();
|
||||||
|
this.setTitle("friends list");
|
||||||
|
setOnekoState("default");
|
||||||
|
}
|
||||||
|
|
||||||
|
async getHTML() {
|
||||||
|
return `
|
||||||
|
<div class="relative b-0 default-border bg-neutral-200">
|
||||||
|
<div class="bg-linear-to-r from-orange-200 to-orange-300 flex flex-row min-w-40 justify-between px-2">
|
||||||
|
<span class="font-[Kubasta]">friends.ts</span>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<div class="bg-neutral-200 pb-5 dark:bg-neutral-800 justify-center text-center reverse-border">
|
||||||
|
<form method="dialog" class="justify-center bg-neutral-200 dark:bg-neutral-800 space-y-4 space-x-2 px-4 pt-4">
|
||||||
|
<input type="text" id="new-friend" placeholder="new friend" class="bg-white text-neutral-900 input-border" required></input>
|
||||||
|
<button id="add-friends-button" type="submit" class="default-button text-center mx-0 my-0">add friend</button>
|
||||||
|
<p id="add-friend-err" class="hidden text-red-700 dark:text-red-500"></p>
|
||||||
|
<p id="add-friend-msg" class="hidden text-gray-900 dark:text-white text-lg"></p>
|
||||||
|
</form>
|
||||||
|
<p id="friends-error-message" class="hidden text-red-700 dark:text-red-500"></p>
|
||||||
|
<p id="friend-msg" class="hidden text-gray-900 dark:text-white text-lg"></p>
|
||||||
|
<div class="flex flex-row space-x-4 w-full min-w-60 px-4 py-2">
|
||||||
|
<ul id="friends_list" class="bg-neutral-300 dark:bg-neutral-900 reverse-border space-y-2 hidden text-gray-900 dark:text-white overflow-scroll h-48 w-full">
|
||||||
|
</ul>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
`;
|
||||||
|
}
|
||||||
|
|
||||||
|
async run() {
|
||||||
|
if (!await isLogged())
|
||||||
|
navigationManager("/");
|
||||||
|
|
||||||
|
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 friends_error_message = (document.getElementById("friends-error-message") 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: 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 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<Boolean> {
|
||||||
|
const data_req = await fetch("http://localhost:3002/ping/" + name, {
|
||||||
|
method: "GET",
|
||||||
|
credentials: "include",
|
||||||
|
});
|
||||||
|
|
||||||
|
if (data_req.status === 404)
|
||||||
|
return false;
|
||||||
|
|
||||||
|
return (await data_req.json()).isLogged
|
||||||
|
}
|
||||||
|
|
||||||
|
const list_friends = async () => {
|
||||||
|
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 === 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", {
|
||||||
|
method: "GET",
|
||||||
|
headers: {
|
||||||
|
"Content-Type": "application/json",
|
||||||
|
},
|
||||||
|
credentials: "include",
|
||||||
|
});
|
||||||
|
if (list_req.status == 404) {
|
||||||
|
friends_list.classList.add("hidden")
|
||||||
|
return;
|
||||||
|
} else 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');
|
||||||
|
|
||||||
|
const activitySpan = document.createElement('span');
|
||||||
|
const isLogged = await isFriendLogged(list[i].friendName)
|
||||||
|
activitySpan.textContent = "•";
|
||||||
|
if (isLogged == true)
|
||||||
|
activitySpan.className = "px-0 text-green-500";
|
||||||
|
else
|
||||||
|
activitySpan.className = "px-0 text-red-500";
|
||||||
|
|
||||||
|
|
||||||
|
const span = document.createElement('span');
|
||||||
|
span.className = "px-3";
|
||||||
|
span.textContent = list[i].friendName;
|
||||||
|
|
||||||
|
const but = document.createElement('button');
|
||||||
|
but.textContent = "-";
|
||||||
|
but.classList.add("px-0", "py-0", "taskbar-button");
|
||||||
|
but.onclick = function() {
|
||||||
|
removeFriend(list[i].friendName);
|
||||||
|
};
|
||||||
|
|
||||||
|
new_friends.appendChild(activitySpan);
|
||||||
|
new_friends.appendChild(span);
|
||||||
|
new_friends.appendChild(but);
|
||||||
|
friends_list.appendChild(new_friends);
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
friends_error_message.innerHTML = (await list_req.json()).error;
|
||||||
|
friends_error_message.classList.remove("hidden");
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
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",
|
||||||
|
credentials: "include",
|
||||||
|
});
|
||||||
|
let data = await data_req.json()
|
||||||
|
if (data_req.status === 200) {
|
||||||
|
add_friend_msg.innerHTML = data.msg;
|
||||||
|
add_friend_msg.classList.remove("hidden");
|
||||||
|
if (!add_friend_err.classList.contains("hidden"))
|
||||||
|
add_friend_err.classList.add("hidden")
|
||||||
|
} else {
|
||||||
|
add_friend_err.innerHTML = data.error;
|
||||||
|
add_friend_err.classList.remove("hidden");
|
||||||
|
if (!add_friend_msg.classList.contains("hidden"))
|
||||||
|
add_friend_msg.classList.add("hidden")
|
||||||
|
list_friends()
|
||||||
|
return
|
||||||
|
}
|
||||||
|
list_friends()
|
||||||
|
new_friend.value = '';
|
||||||
|
}
|
||||||
|
|
||||||
|
try {
|
||||||
|
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();
|
||||||
|
list_friends()
|
||||||
|
}
|
||||||
|
} catch (error) {
|
||||||
|
friends_error_message.innerHTML = "failed to fetch friends";
|
||||||
|
friends_error_message.classList.remove("hidden");
|
||||||
|
}
|
||||||
|
document.getElementById("add-friends-button")?.addEventListener("click", add_friend);
|
||||||
|
setInterval(list_friends, 30000);
|
||||||
|
}
|
||||||
|
}
|
||||||
@ -2,7 +2,6 @@ import Aview from "./Aview.ts"
|
|||||||
import { isLogged, navigationManager } from "../main.ts"
|
import { isLogged, navigationManager } from "../main.ts"
|
||||||
|
|
||||||
export default class extends Aview {
|
export default class extends Aview {
|
||||||
|
|
||||||
async getHTML() {
|
async getHTML() {
|
||||||
return `
|
return `
|
||||||
<div id="main-window" class="default-border shadow-2x1 bg-neutral-200 dark:bg-neutral-800">
|
<div id="main-window" class="default-border shadow-2x1 bg-neutral-200 dark:bg-neutral-800">
|
||||||
@ -66,6 +65,7 @@ export default class extends Aview {
|
|||||||
<hr class="my-2 w-32 reverse-border">
|
<hr class="my-2 w-32 reverse-border">
|
||||||
<a class="menu-default-button inline-flex items-center justify-center" href="/profile" data-link>profile</a>
|
<a class="menu-default-button inline-flex items-center justify-center" href="/profile" data-link>profile</a>
|
||||||
<a class="menu-default-button inline-flex items-center justify-center" href="/settings" data-link>settings</a>
|
<a class="menu-default-button inline-flex items-center justify-center" href="/settings" data-link>settings</a>
|
||||||
|
<a class="menu-default-button inline-flex items-center justify-center" href="/friends" data-link>friends</a>
|
||||||
`;
|
`;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
24
src/utils/authUserCreate.js
Normal file
24
src/utils/authUserCreate.js
Normal file
@ -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(
|
||||||
|
url + "/users/" + username,
|
||||||
|
payload,
|
||||||
|
{
|
||||||
|
headers: {
|
||||||
|
'Cookie': 'token=' + cookie,
|
||||||
|
},
|
||||||
|
}
|
||||||
|
);
|
||||||
|
}
|
||||||
Reference in New Issue
Block a user