From 2647588f1635dcff09fb8b24ff451ccc7c0005da Mon Sep 17 00:00:00 2001 From: vvandenb Date: Wed, 22 Mar 2023 17:21:13 +0100 Subject: [PATCH] * Global pipe added + typed data sent from front to back with DTOs --- .env_sample | 2 +- back/package-lock.json | 44 ------------- back/src/chat/dto/create-channel.dto.ts | 4 -- back/src/main.ts | 1 + front/src/Auth.ts | 6 +- front/src/components/Channels.svelte | 34 ++++++---- front/src/components/Chat.svelte | 65 +++++++++++++------ front/src/components/Profile.svelte | 12 +++- front/src/components/dtos/connection.dto.ts | 5 ++ .../src/components/dtos/create-channel.dto.ts | 8 +++ .../src/components/dtos/create-message.dto.ts | 5 ++ front/src/components/dtos/kickUser.dto.ts | 5 ++ .../src/components/dtos/update-channel.dto.ts | 9 +++ front/src/components/dtos/updateUser.dto.ts | 15 +++++ front/src/components/dtos/user.dto.ts | 8 +++ 15 files changed, 137 insertions(+), 86 deletions(-) create mode 100644 front/src/components/dtos/connection.dto.ts create mode 100644 front/src/components/dtos/create-channel.dto.ts create mode 100644 front/src/components/dtos/create-message.dto.ts create mode 100644 front/src/components/dtos/kickUser.dto.ts create mode 100644 front/src/components/dtos/update-channel.dto.ts create mode 100644 front/src/components/dtos/updateUser.dto.ts create mode 100644 front/src/components/dtos/user.dto.ts diff --git a/.env_sample b/.env_sample index eed2260..3b5f5d3 100644 --- a/.env_sample +++ b/.env_sample @@ -19,7 +19,7 @@ MAIL_PASSWORD= FT_OAUTH_CLIENT_ID= FT_OAUTH_CLIENT_SECRET= FT_OAUTH_CALLBACK_URL=http://localhost:3001/log/inReturn -JWT_SECRET=test +JWT_SECRET= JWT_EXPIRATION_TIME=900 ### DB ### diff --git a/back/package-lock.json b/back/package-lock.json index 0a84acd..e2b459e 100644 --- a/back/package-lock.json +++ b/back/package-lock.json @@ -36,7 +36,6 @@ "cookie-parser": "^1.4.6", "express": "^4.18.2", "express-session": "^1.17.3", - "joi": "^17.8.3", "multer": "^1.4.5-lts.1", "nestjs-paginate": "^4.13.0", "nodemailer": "^6.9.1", @@ -795,19 +794,6 @@ "fast-json-stringify": "^5.0.0" } }, - "node_modules/@hapi/hoek": { - "version": "9.3.0", - "resolved": "https://registry.npmjs.org/@hapi/hoek/-/hoek-9.3.0.tgz", - "integrity": "sha512-/c6rf4UJlmHlC9b5BaNvzAcFv7HZ2QHaV0D4/HNlBdvFnvQq8RI4kYdhyPCl7Xj+oWvTWQ8ujhqS53LIgAe6KQ==" - }, - "node_modules/@hapi/topo": { - "version": "5.1.0", - "resolved": "https://registry.npmjs.org/@hapi/topo/-/topo-5.1.0.tgz", - "integrity": "sha512-foQZKJig7Ob0BMAYBfcJk8d77QtOe7Wo4ox7ff1lQYoNNAb6jwcY1ncdoy2e9wQZzvNy7ODZCYJkK8kzmcAnAg==", - "dependencies": { - "@hapi/hoek": "^9.0.0" - } - }, "node_modules/@humanwhocodes/config-array": { "version": "0.11.8", "resolved": "https://registry.npmjs.org/@humanwhocodes/config-array/-/config-array-0.11.8.tgz", @@ -1731,24 +1717,6 @@ "url": "https://ko-fi.com/killymxi" } }, - "node_modules/@sideway/address": { - "version": "4.1.4", - "resolved": "https://registry.npmjs.org/@sideway/address/-/address-4.1.4.tgz", - "integrity": "sha512-7vwq+rOHVWjyXxVlR76Agnvhy8I9rpzjosTESvmhNeXOXdZZB15Fl+TI9x1SiHZH5Jv2wTGduSxFDIaq0m3DUw==", - "dependencies": { - "@hapi/hoek": "^9.0.0" - } - }, - "node_modules/@sideway/formula": { - "version": "3.0.1", - "resolved": "https://registry.npmjs.org/@sideway/formula/-/formula-3.0.1.tgz", - "integrity": "sha512-/poHZJJVjx3L+zVD6g9KgHfYnb443oi7wLu/XKojDviHy6HOEOA6z1Trk5aR1dGcmPenJEgb2sK2I80LeS3MIg==" - }, - "node_modules/@sideway/pinpoint": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/@sideway/pinpoint/-/pinpoint-2.0.0.tgz", - "integrity": "sha512-RNiOoTPkptFtSVzQevY/yWtZwf/RxyVnPy/OcA9HBM3MlGDnBEYL5B41H0MTn0Uec8Hi+2qUtTfG2WWZBmMejQ==" - }, "node_modules/@sinclair/typebox": { "version": "0.24.51", "resolved": "https://registry.npmjs.org/@sinclair/typebox/-/typebox-0.24.51.tgz", @@ -6987,18 +6955,6 @@ "url": "https://github.com/chalk/supports-color?sponsor=1" } }, - "node_modules/joi": { - "version": "17.8.3", - "resolved": "https://registry.npmjs.org/joi/-/joi-17.8.3.tgz", - "integrity": "sha512-q5Fn6Tj/jR8PfrLrx4fpGH4v9qM6o+vDUfD4/3vxxyg34OmKcNqYZ1qn2mpLza96S8tL0p0rIw2gOZX+/cTg9w==", - "dependencies": { - "@hapi/hoek": "^9.0.0", - "@hapi/topo": "^5.0.0", - "@sideway/address": "^4.1.3", - "@sideway/formula": "^3.0.1", - "@sideway/pinpoint": "^2.0.0" - } - }, "node_modules/js-beautify": { "version": "1.14.7", "resolved": "https://registry.npmjs.org/js-beautify/-/js-beautify-1.14.7.tgz", diff --git a/back/src/chat/dto/create-channel.dto.ts b/back/src/chat/dto/create-channel.dto.ts index eccf397..f71f5ff 100644 --- a/back/src/chat/dto/create-channel.dto.ts +++ b/back/src/chat/dto/create-channel.dto.ts @@ -8,10 +8,6 @@ import { } from 'class-validator' export class CreateChannelDto { - @IsOptional() - @IsPositive() - id: number - @IsString() name: string diff --git a/back/src/main.ts b/back/src/main.ts index 105ee22..a8e1622 100644 --- a/back/src/main.ts +++ b/back/src/main.ts @@ -40,6 +40,7 @@ async function bootstrap (): Promise { app.use(passport.session()) app.enableCors(cors) app.useWebSocketAdapter(new IoAdapter(app)) + app.useGlobalPipes(new ValidationPipe()) await app.listen(port) logger.log(`Application listening on port ${port}`) } diff --git a/front/src/Auth.ts b/front/src/Auth.ts index 7f0a131..3081f5e 100644 --- a/front/src/Auth.ts +++ b/front/src/Auth.ts @@ -1,6 +1,7 @@ import { writable } from "svelte/store"; import { content, show_popup } from "./components/Alert/content"; import {get} from 'svelte/store' +import type { EmailDto } from "./components/dtos/updateUser.dto"; let _user = localStorage.getItem("user"); export const store = writable(_user ? JSON.parse(_user) : null); store.subscribe((value) => { @@ -35,13 +36,14 @@ export async function verify() { let email : string; await show_popup("Enter your preferred email adress:\n(defaults to 42 email)") email = get(content); - if (email !== undefined && email !== '' && email !== 'ok') { + if (email !== undefined && email !== '' && email !== 'ok') { + const body: EmailDto = { email } const response = await fetch(API_URL + "/log/email", { method: "POST", mode: "cors", headers: {"Content-Type": "application/json",}, credentials: "include", - body: JSON.stringify({email: email}) + body: JSON.stringify(body) }) if (response.ok) {await show_popup("Email set",false)} else {await show_popup("Couldn't set Email",false); return } diff --git a/front/src/components/Channels.svelte b/front/src/components/Channels.svelte index 2f42083..907df2b 100644 --- a/front/src/components/Channels.svelte +++ b/front/src/components/Channels.svelte @@ -3,7 +3,9 @@ import { onMount } from "svelte"; import { API_URL, store } from "../Auth"; import type User from "./Profile.svelte"; - import { APPSTATE } from "../App.svelte"; + import type { APPSTATE } from "../App.svelte"; + import type { CreateChannelDto } from './dtos/create-channel.dto'; + import type { IdDto, PasswordDto } from './dtos/updateUser.dto'; export let appState: string; export let setAppState: (newState: APPSTATE | string) => void; @@ -119,6 +121,14 @@ } } name = "🚪 " + name; + const body: CreateChannelDto = { + name: name, + owner: $store.ftId, + password: password, + isPrivate: channelMode === "private", + isDM: false, + otherDMedUsername: "", + }; const response = await fetch(API_URL + "/channels", { credentials: "include", method: "POST", @@ -126,12 +136,7 @@ headers: { "Content-Type": "application/json", }, - body: JSON.stringify({ - name: name, - owner: $store.ftId, - password: password, - isPrivate: channelMode === "private", - }), + body: JSON.stringify(body), }); if (!response.ok) { const error = await response.json(); @@ -172,6 +177,9 @@ if (response.ok) { const user = await response.json(); console.log(user) + const body: IdDto = { + id: user.ftId + } const response2 = await fetch(API_URL + "/channels/" + id + "/invite", { credentials: "include", method: "POST", @@ -179,9 +187,7 @@ headers: { "Content-Type": "application/json", }, - body: JSON.stringify({ - id: user.ftId - }), + body: JSON.stringify(body), }); if (response2.ok) { await show_popup("User invited", false) @@ -199,7 +205,9 @@ const changePassword = async (id: number) => { await show_popup("Enter the new password for this channel (leave empty to remove password) :", true, true); - let string = $content + const body: PasswordDto = { + password: $content + } const response = await fetch(API_URL + "/channels/" + id + "/password", { credentials: "include", method: "POST", @@ -207,9 +215,7 @@ headers: { "Content-Type": "application/json", }, - body: JSON.stringify({ - password: string, - }), + body: JSON.stringify(body), }); if (!response.ok) { const error = await response.json(); diff --git a/front/src/components/Chat.svelte b/front/src/components/Chat.svelte index 8bfb21a..7ed52c6 100644 --- a/front/src/components/Chat.svelte +++ b/front/src/components/Chat.svelte @@ -6,6 +6,11 @@ import { APPSTATE } from "../App.svelte"; import { formatChannelNames, type ChannelsType, type chatMessagesType } from "./Channels.svelte"; import type User from "./Profile.svelte"; + import type { CreateChannelDto } from "./dtos/create-channel.dto"; + import type { IdDto, MuteDto } from "./dtos/updateUser.dto"; + import type { ConnectionDto } from "./dtos/connection.dto"; + import type { CreateMessageDto } from "./dtos/create-message.dto"; + import type { kickUserDto } from "./dtos/kickUser.dto"; @@ -47,17 +52,20 @@ await getCurrentChannel(); if (!channel) setAppState(APPSTATE.CHANNELS); if (!channel.password) { - socket.emit("joinChannel", { + const data: ConnectionDto = { UserId: $store.ftId, ChannelId: channel.id, - }); + pwd: "", + }; + socket.emit("joinChannel", data); } else { await show_popup("Channel is protected, enter password:", true, true); - socket.emit("joinChannel", { + const data: ConnectionDto = { UserId: $store.ftId, ChannelId: channel.id, pwd: $content, - }); + }; + socket.emit("joinChannel", data); } socket.on("newMessage", (msg: chatMessagesType) => { console.log(msg); @@ -116,11 +124,12 @@ const sendMessage = () => { if (newText !== "") { - socket.emit("addMessage", { + const data: CreateMessageDto = { text: newText, UserId: $store.ftId, ChannelId: channel.id, - }); + }; + socket.emit("addMessage", data); newText = ""; const messagesDiv = document.querySelector(".messages"); if (messagesDiv) { @@ -175,6 +184,14 @@ setAppState(APPSTATE.CHANNELS + "#" + DMChannel[0].name) } else { console.log("Creating DMChannel: " + $store.username + "&" + DMUsername) + const body: CreateChannelDto = { + name: "none", + owner: $store.ftId, + password: "", + isPrivate: true, + isDM: true, + otherDMedUsername: DMUsername + } fetch(API_URL + "/channels", { credentials: "include", method: "POST", @@ -182,14 +199,7 @@ headers: { "Content-Type": "application/json", }, - body: JSON.stringify({ - name: "none", - owner: $store.ftId, - password: "", - isPrivate: true, - isDM: true, - otherDMedUsername: DMUsername - }), + body: JSON.stringify(body), }).then(async () => { const response = await getDMs(DMUsername) if (response && response.ok) { @@ -266,6 +276,9 @@ const duration = $content; if (duration == "") return; + const body: MuteDto = { + data: [target.ftId, duration] + } response = await fetch(API_URL + "/channels/" + channel.id + "/ban", { credentials: "include", method: "POST", @@ -273,11 +286,16 @@ headers: { "Content-Type": "application/json", }, - body: JSON.stringify({ data: [target.ftId, duration] }), + body: JSON.stringify(body), }); if (response.ok) { await show_popup(`User banned for: ${duration} seconds`, false); - socket.emit("kickUser", channel.id, $store.ftId, target.ftId); + const data: kickUserDto = { + chan: channel.id, + from: $store.ftId, + to: target.ftId, + }; + socket.emit("kickUser", data); } else { const error = await response.json(); await show_popup(error.message, false) @@ -320,11 +338,12 @@ }); if (response.ok) { const target = await response.json(); - socket.emit("kickUser", { + const data: kickUserDto = { chan: channel.id, from: $store.ftId, to: target.ftId, - }); + }; + socket.emit("kickUser", data); } else { const error = await response.json(); await show_popup(error.message, false); @@ -341,6 +360,9 @@ }); const target = await response.json(); if (response.ok) { + const body: MuteDto = { + data: [target.ftId, +$content] + } response = await fetch(API_URL + "/channels/" + channel.id + "/mute", { credentials: "include", method: "POST", @@ -348,7 +370,7 @@ headers: { "Content-Type": "application/json", }, - body: JSON.stringify({ data: [target.ftId, +$content] }), + body: JSON.stringify(body), }); } if (response.ok) await show_popup("User muted", false); @@ -367,6 +389,9 @@ }); if (response.ok) { const target = await response.json(); + const body: IdDto = { + id: target.ftId + } response = await fetch(API_URL + "/channels/" + channel.id + "/admin", { credentials: "include", method: "POST", @@ -374,7 +399,7 @@ headers: { "Content-Type": "application/json", }, - body: JSON.stringify({ id: target.ftId }), + body: JSON.stringify(body), }); } if (response.ok) { diff --git a/front/src/components/Profile.svelte b/front/src/components/Profile.svelte index 1893b4b..77deb1a 100644 --- a/front/src/components/Profile.svelte +++ b/front/src/components/Profile.svelte @@ -17,6 +17,7 @@ import { API_URL, store, logout } from "../Auth"; import Alert from "./Alert/Alert.svelte"; import { popup } from "./Alert/content"; + import type { UserDto } from "./dtos/user.dto"; export let username: string = $store.username; export let gamePlaying: boolean; @@ -53,7 +54,16 @@ return; } - let response = await fetch(API_URL + "/users", { + const body: UserDto = { + username: newUsername, + ftId: $store.ftId, + status: $store.status, + authToken: $store.authToken, + avatar: $store.avatar, + isVerified: $store.isVerified + }; + console.log("body:", body); + const response = await fetch(API_URL + "/users", { headers: { "content-type": "application/json" }, method: "POST", body: JSON.stringify({ username: newUsername }), diff --git a/front/src/components/dtos/connection.dto.ts b/front/src/components/dtos/connection.dto.ts new file mode 100644 index 0000000..74ecae3 --- /dev/null +++ b/front/src/components/dtos/connection.dto.ts @@ -0,0 +1,5 @@ +export class ConnectionDto { + UserId: number + ChannelId: number + pwd: string +} diff --git a/front/src/components/dtos/create-channel.dto.ts b/front/src/components/dtos/create-channel.dto.ts new file mode 100644 index 0000000..8ff6731 --- /dev/null +++ b/front/src/components/dtos/create-channel.dto.ts @@ -0,0 +1,8 @@ +export class CreateChannelDto { + name: string + owner: number + password: string + isPrivate: boolean + isDM: boolean + otherDMedUsername: string +} diff --git a/front/src/components/dtos/create-message.dto.ts b/front/src/components/dtos/create-message.dto.ts new file mode 100644 index 0000000..d9fa70d --- /dev/null +++ b/front/src/components/dtos/create-message.dto.ts @@ -0,0 +1,5 @@ +export class CreateMessageDto { + text: string + UserId: number + ChannelId: number +} diff --git a/front/src/components/dtos/kickUser.dto.ts b/front/src/components/dtos/kickUser.dto.ts new file mode 100644 index 0000000..fba8d1c --- /dev/null +++ b/front/src/components/dtos/kickUser.dto.ts @@ -0,0 +1,5 @@ +export class kickUserDto { + chan: number + from: number + to: number +} diff --git a/front/src/components/dtos/update-channel.dto.ts b/front/src/components/dtos/update-channel.dto.ts new file mode 100644 index 0000000..87f243e --- /dev/null +++ b/front/src/components/dtos/update-channel.dto.ts @@ -0,0 +1,9 @@ +import { CreateChannelDto } from './create-channel.dto' + +export class UpdateChannelDto extends CreateChannelDto { + users: [number] + messages: [number] + owners: [number] // user id + banned: [number] // user id + muted: [number] // user id +} diff --git a/front/src/components/dtos/updateUser.dto.ts b/front/src/components/dtos/updateUser.dto.ts new file mode 100644 index 0000000..b7a9ada --- /dev/null +++ b/front/src/components/dtos/updateUser.dto.ts @@ -0,0 +1,15 @@ +export class IdDto { + id: number +} + +export class PasswordDto { + password: string +} + +export class MuteDto { + data: number[] +} + +export class EmailDto { + email: string +} diff --git a/front/src/components/dtos/user.dto.ts b/front/src/components/dtos/user.dto.ts new file mode 100644 index 0000000..ba21609 --- /dev/null +++ b/front/src/components/dtos/user.dto.ts @@ -0,0 +1,8 @@ +export class UserDto { + ftId: number + username: string + status: string + avatar: string + authToken: string + isVerified: boolean +}