From c2f0c3d06e409ed2e3424d005784b227ddbebeab Mon Sep 17 00:00:00 2001 From: SaAxok Date: Thu, 19 Dec 2024 15:31:31 +0100 Subject: [PATCH 01/11] fix dashboard cards and add ethernet module --- front-js/src/app/dashboard/page.tsx | 17 ++-- front-js/src/app/modules/ethernet/page.tsx | 104 +++++++++++++++++++++ 2 files changed, 113 insertions(+), 8 deletions(-) diff --git a/front-js/src/app/dashboard/page.tsx b/front-js/src/app/dashboard/page.tsx index 711bbbf..0079122 100644 --- a/front-js/src/app/dashboard/page.tsx +++ b/front-js/src/app/dashboard/page.tsx @@ -112,56 +112,57 @@ export default function Dashboard() { router.push("/modules/ethernet")} /> diff --git a/front-js/src/app/modules/ethernet/page.tsx b/front-js/src/app/modules/ethernet/page.tsx index e69de29..ecfb021 100644 --- a/front-js/src/app/modules/ethernet/page.tsx +++ b/front-js/src/app/modules/ethernet/page.tsx @@ -0,0 +1,104 @@ +"use client"; + +import Box from "@/components/Box"; +import Layout from "@/components/Layout"; +import Header from "@/components/Header"; +import { useRouter } from "next/navigation"; +import Cookies from "js-cookie"; +import axios from "@/axiosConfig"; +import { useEffect, useState } from "react"; +import { CircularProgress, Grid2 } from "@mui/material"; +import Title from "@/components/Title"; +import { EmojiProvider, Emoji } from "react-apple-emojis"; +import emojiData from "react-apple-emojis/src/data.json"; +import { Spacer } from "@nextui-org/spacer"; +import Card from "@/components/Card"; + +export default function Dashboard() { + const router = useRouter(); + const [hasAccessToken, setHasAccessToken] = useState(false); + + const [isLoading, setIsLoading] = useState(true); + + useEffect(() => { + const checkTokens = async () => { + const token = Cookies.get("access_token"); + const refresh = Cookies.get("refresh_token"); + if (!token && refresh) { + try { + const response = await axios.post("/auth/refresh", { + refresh_token: refresh, + }); + const data = response.data; + if (response.status === 200) { + Cookies.set("access_token", data.access_token); + Cookies.set("refresh_token", refresh); + } + } catch { + Cookies.remove("access_token"); + Cookies.remove("refresh_token"); + } + } + setHasAccessToken(!!token); + + if (!token && !refresh) { + router.push("/"); + } + }; + + checkTokens(); + }, [router]); + + const [username, setUsername] = useState(""); + + useEffect(() => { + const getUser = async () => { + setIsLoading(true); + try { + const response = await axios.get("/users/me", { + headers: { + Authorization: `Bearer ${Cookies.get("access_token")}`, + }, + }); + setUsername(response.data.username); + } catch { + Cookies.remove("access_token"); + Cookies.remove("refresh_token"); + router.push("/"); + } + setIsLoading(false); + }; + + getUser(); + }, [router]); + return ( + + + + {hasAccessToken && ( +
router.push(`/${tab.toLowerCase()}`)} + onClickLogout={() => router.push("/auth/logout")} + onClickLogo={() => router.push("/")} + /> + )} + + {isLoading ? ( + + ) : ( + <> + + Ethernet + + + )} + + + ); +} From 205dafbc3b06161e9e4b14a566a1208ce1a9e4c5 Mon Sep 17 00:00:00 2001 From: SaAxok Date: Thu, 19 Dec 2024 16:53:11 +0100 Subject: [PATCH 02/11] ethernet module page --- .../modules_assets/example_ethernet.png | Bin 0 -> 46864 bytes front-js/src/app/modules/ethernet/page.tsx | 207 +++++++++++------- 2 files changed, 125 insertions(+), 82 deletions(-) create mode 100644 front-js/public/modules_assets/example_ethernet.png diff --git a/front-js/public/modules_assets/example_ethernet.png b/front-js/public/modules_assets/example_ethernet.png new file mode 100644 index 0000000000000000000000000000000000000000..a743e199b8f99ab437f748e22ece353acec9ccfd GIT binary patch literal 46864 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 D1v9DF literal 0 HcmV?d00001 diff --git a/front-js/src/app/modules/ethernet/page.tsx b/front-js/src/app/modules/ethernet/page.tsx index ecfb021..83e2053 100644 --- a/front-js/src/app/modules/ethernet/page.tsx +++ b/front-js/src/app/modules/ethernet/page.tsx @@ -1,6 +1,7 @@ "use client"; import Box from "@/components/Box"; +import Text from "@/components/Text"; import Layout from "@/components/Layout"; import Header from "@/components/Header"; import { useRouter } from "next/navigation"; @@ -9,96 +10,138 @@ import axios from "@/axiosConfig"; import { useEffect, useState } from "react"; import { CircularProgress, Grid2 } from "@mui/material"; import Title from "@/components/Title"; -import { EmojiProvider, Emoji } from "react-apple-emojis"; +import { EmojiProvider } from "react-apple-emojis"; import emojiData from "react-apple-emojis/src/data.json"; -import { Spacer } from "@nextui-org/spacer"; -import Card from "@/components/Card"; +import Space from "@/components/Space"; +import Image from "next/image"; export default function Dashboard() { - const router = useRouter(); - const [hasAccessToken, setHasAccessToken] = useState(false); + const router = useRouter(); + const [hasAccessToken, setHasAccessToken] = useState(false); - const [isLoading, setIsLoading] = useState(true); + const [isLoading, setIsLoading] = useState(true); - useEffect(() => { - const checkTokens = async () => { - const token = Cookies.get("access_token"); - const refresh = Cookies.get("refresh_token"); - if (!token && refresh) { - try { - const response = await axios.post("/auth/refresh", { - refresh_token: refresh, - }); - const data = response.data; - if (response.status === 200) { - Cookies.set("access_token", data.access_token); - Cookies.set("refresh_token", refresh); - } - } catch { - Cookies.remove("access_token"); - Cookies.remove("refresh_token"); - } - } - setHasAccessToken(!!token); + useEffect(() => { + const checkTokens = async () => { + const token = Cookies.get("access_token"); + const refresh = Cookies.get("refresh_token"); + if (!token && refresh) { + try { + const response = await axios.post("/auth/refresh", { + refresh_token: refresh, + }); + const data = response.data; + if (response.status === 200) { + Cookies.set("access_token", data.access_token); + Cookies.set("refresh_token", refresh); + } + } catch { + Cookies.remove("access_token"); + Cookies.remove("refresh_token"); + } + } + setHasAccessToken(!!token); - if (!token && !refresh) { - router.push("/"); - } - }; + if (!token && !refresh) { + router.push("/"); + } + }; - checkTokens(); - }, [router]); + checkTokens(); + }, [router]); - const [username, setUsername] = useState(""); + const [username, setUsername] = useState(""); - useEffect(() => { - const getUser = async () => { - setIsLoading(true); - try { - const response = await axios.get("/users/me", { - headers: { - Authorization: `Bearer ${Cookies.get("access_token")}`, - }, - }); - setUsername(response.data.username); - } catch { - Cookies.remove("access_token"); - Cookies.remove("refresh_token"); - router.push("/"); - } - setIsLoading(false); - }; + useEffect(() => { + const getUser = async () => { + setIsLoading(true); + try { + const response = await axios.get("/users/me", { + headers: { + Authorization: `Bearer ${Cookies.get("access_token")}`, + }, + }); + setUsername(response.data.username); + } catch { + Cookies.remove("access_token"); + Cookies.remove("refresh_token"); + router.push("/"); + } + setIsLoading(false); + }; - getUser(); - }, [router]); - return ( - - - - {hasAccessToken && ( -

router.push(`/${tab.toLowerCase()}`)} - onClickLogout={() => router.push("/auth/logout")} - onClickLogo={() => router.push("/")} - /> - )} - - {isLoading ? ( - - ) : ( - <> - - Ethernet - - - )} - - - ); + getUser(); + }, [router]); + return ( + + + + {hasAccessToken && ( +
router.push(`/${tab.toLowerCase()}`)} + onClickLogout={() => router.push("/auth/logout")} + onClickLogo={() => router.push("/")} + /> + )} + + {isLoading ? ( + + ) : ( + <> + + + + + Ethernet + + Bienvenue sur le module Ethernet. Ce module génère une trame Ethernet basée sur les paramètres fournis. + Elle utilise les informations sur les adresses MAC source et destination ainsi que le type Ethernet (exprimé en hexadécimal). + La trame générée est renvoyée au format JSON. + + + + + + + Entrées : + ・Adresse MAC de destination, (par exemple, FF:FF:FF:FF:FF:FF). + ・Adresse MAC source, (par exemple, 00:11:22:33:44:55). + ・Type de trame ethernet, (cf Types de trames). + + + + + Types de trames Ethernet : + ・0x0800 pour IPv4 + ・0x0806 pour ARP + ・0x86DD pour IPv6 + ・0x8100 pour VLAN + + + + + Exemple de réponse 200 OK + Example ethernet + + + + + + + + )} + + + ); } From eefb2f026ae70220991d85c948e3dd4adfa7252f Mon Sep 17 00:00:00 2001 From: SaAxok Date: Fri, 20 Dec 2024 10:00:48 +0100 Subject: [PATCH 03/11] continue ethernet --- front-js/src/app/modules/ethernet/page.tsx | 88 ++++++++++++---------- 1 file changed, 50 insertions(+), 38 deletions(-) diff --git a/front-js/src/app/modules/ethernet/page.tsx b/front-js/src/app/modules/ethernet/page.tsx index 83e2053..0991ca1 100644 --- a/front-js/src/app/modules/ethernet/page.tsx +++ b/front-js/src/app/modules/ethernet/page.tsx @@ -8,7 +8,7 @@ import { useRouter } from "next/navigation"; import Cookies from "js-cookie"; import axios from "@/axiosConfig"; import { useEffect, useState } from "react"; -import { CircularProgress, Grid2 } from "@mui/material"; +import { CircularProgress, Grid, Grid2, Input } from "@mui/material"; import Title from "@/components/Title"; import { EmojiProvider } from "react-apple-emojis"; import emojiData from "react-apple-emojis/src/data.json"; @@ -95,48 +95,60 @@ export default function Dashboard() { ) : ( <> - - - - Ethernet - - Bienvenue sur le module Ethernet. Ce module génère une trame Ethernet basée sur les paramètres fournis. - Elle utilise les informations sur les adresses MAC source et destination ainsi que le type Ethernet (exprimé en hexadécimal). - La trame générée est renvoyée au format JSON. - - - - - - - Entrées : - ・Adresse MAC de destination, (par exemple, FF:FF:FF:FF:FF:FF). - ・Adresse MAC source, (par exemple, 00:11:22:33:44:55). - ・Type de trame ethernet, (cf Types de trames). - - - - - Types de trames Ethernet : - ・0x0800 pour IPv4 - ・0x0806 pour ARP - ・0x86DD pour IPv6 - ・0x8100 pour VLAN - - - - - Exemple de réponse 200 OK - + + + Ethernet + + Bienvenue sur le module Ethernet. Ce module génère une trame Ethernet basée sur les paramètres fournis. + Elle utilise les informations sur les adresses MAC source et destination ainsi que le type Ethernet (exprimé en hexadécimal). + La trame générée est renvoyée au format JSON. + + + + + + Entrées : + ・Adresse MAC de destination, (par exemple, FF:FF:FF:FF:FF:FF). + ・Adresse MAC source, (par exemple, 00:11:22:33:44:55). + ・Type de trame ethernet, (cf Types de trames). + + + + + Types de trames Ethernet : + ・0x0800 pour IPv4 + ・0x0806 pour ARP + ・0x86DD pour IPv6 + ・0x8100 pour VLAN + + + + + Exemple de réponse 200 OK + Example ethernet - - + style={{ width: "auto", height: "auto" }} /> + + + + + Exemple : + + + + + + + Réponse : - + From 69dae25f3e4d9e7a7f132f524f91bb647cc448a3 Mon Sep 17 00:00:00 2001 From: SaAxok Date: Fri, 20 Dec 2024 10:27:04 +0100 Subject: [PATCH 04/11] ethernet split files, page, cours, sandbox --- front-js/src/app/modules/ethernet/Cours.tsx | 88 +++++++++++ .../app/modules/ethernet/EthernetSandbox.tsx | 139 ++++++++++++++++++ front-js/src/app/modules/ethernet/page.tsx | 137 ++++++----------- 3 files changed, 273 insertions(+), 91 deletions(-) create mode 100644 front-js/src/app/modules/ethernet/Cours.tsx create mode 100644 front-js/src/app/modules/ethernet/EthernetSandbox.tsx diff --git a/front-js/src/app/modules/ethernet/Cours.tsx b/front-js/src/app/modules/ethernet/Cours.tsx new file mode 100644 index 0000000..95babc4 --- /dev/null +++ b/front-js/src/app/modules/ethernet/Cours.tsx @@ -0,0 +1,88 @@ +import Header from "@/components/Header" +import Layout from "@/components/Layout" +import Space from "@/components/Space" +import Title from "@/components/Title" +import { Box, CircularProgress, Grid2, Input } from "@mui/material" +import axios, { AxiosError } from "axios" +import router from "next/router" +import { useState } from "react" +import { EmojiProvider } from "react-apple-emojis" +import Cookies from "js-cookie"; +import Image from "next/image"; +import Text from "@/components/Text" +import emojiData from "react-apple-emojis/src/data.json"; + + + +const CoursEthernet: React.FC = () => { + + const [ipv6test, setIPv6test] = useState(""); + const [res, setRes] = useState(""); + const [valid, setValid] = useState(false); + + const handleSimplify = async (e: { preventDefault: () => void }) => { + e.preventDefault(); + try { + const response = await axios.get( + "/ipv6/simplify/fe80:0000:0000:0000:0202:b3ff:fe1e:8329", + { + headers: { + Authorization: `Bearer ${Cookies.get("access_token")}`, + }, + }, + ); + const data = response.data; + if (response.status === 200) { + setRes(data.ipv6); + setValid(res == ipv6test); + } + } catch (error: unknown) { + const axiosError = error as AxiosError; + if (axiosError.response?.status === 400) { + const data = axiosError.response.data as { detail: string }; + if (data.detail === "Invalid IPv6") { + setRes("false"); + } else { + setRes("false"); + } + } else { + setRes("false"); + } + } + }; + + return ( + + + + Ethernet + + Bienvenue sur le module Ethernet. Ce module génère une trame Ethernet basée sur les paramètres fournis. + Elle utilise les informations sur les adresses MAC source et destination ainsi que le type Ethernet (exprimé en hexadécimal). + La trame générée est renvoyée au format JSON. + + + Entrées : + ・Adresse MAC de destination, (par exemple, FF:FF:FF:FF:FF:FF). + ・Adresse MAC source, (par exemple, 00:11:22:33:44:55). + ・Type de trame ethernet, (cf Types de trames). + + Types de trames Ethernet : + ・0x0800 pour IPv4 + ・0x0806 pour ARP + ・0x86DD pour IPv6 + ・0x8100 pour VLAN + + Exemple de réponse 200 OK + Example ethernet + + + ) +} + +export default CoursEthernet \ No newline at end of file diff --git a/front-js/src/app/modules/ethernet/EthernetSandbox.tsx b/front-js/src/app/modules/ethernet/EthernetSandbox.tsx new file mode 100644 index 0000000..b3a723f --- /dev/null +++ b/front-js/src/app/modules/ethernet/EthernetSandbox.tsx @@ -0,0 +1,139 @@ +import Title from "@/components/Title"; +import Button from "@/components/Button"; +import Input from "@/components/Input"; +import Space from "@/components/Space"; +import React from "react"; +import { useState } from "react"; +import axios from "@/axiosConfig"; +import Cookies from "js-cookie"; +import { AxiosError } from "axios"; +import { Alert } from "@mui/material"; +import Box from "@/components/Box"; + +const EthernetSandbox: React.FC = () => { + const [simpleIpv6, setSimpleIpv6] = useState(""); + const [simpleRes, setSimpleRes] = useState(""); + + const handleSimplify = async (e: { preventDefault: () => void }) => { + e.preventDefault(); + try { + const response = await axios.get("/ipv6/simplify/ " + simpleIpv6, { + headers: { + Authorization: `Bearer ${Cookies.get("access_token")}`, + }, + }); + const data = response.data; + if (response.status === 200) { + setSimpleRes(data.ipv6); + } + } catch (error: unknown) { + const axiosError = error as AxiosError; + if (axiosError.response?.status === 400) { + const data = axiosError.response.data as { detail: string }; + if (data.detail === "Invalid IPv6") { + setSimpleRes("Adresse IPv6 invalide"); + } else { + setSimpleRes("Adresse IPv6 invalide"); + } + } else { + setSimpleRes("Erreur lors de la simplification de l'adresse IPv6"); + } + } + }; + + const [extendIpv6, setExtendIpv6] = useState(""); + const [extendRes, setExtendRes] = useState(""); + + const handleExtend = async (e: { preventDefault: () => void }) => { + e.preventDefault(); + try { + const response = await axios.get("/ipv6/extend/" + extendIpv6, { + headers: { + Authorization: `Bearer ${Cookies.get("access_token")}`, + }, + }); + const data = response.data; + if (response.status === 200) { + setExtendRes(data.ipv6); + } + } catch (error: unknown) { + const axiosError = error as AxiosError; + if (axiosError.response?.status === 400) { + const data = axiosError.response.data as { detail: string }; + if (data.detail === "Invalid IPv6") { + setExtendRes("Adresse IPv6 invalide"); + } else { + setExtendRes("Adresse IPv6 invalide"); + } + } else { + setExtendRes("Erreur lors de l'extension de l'adresse IPv6"); + } + } + }; + + return ( + <> + +
+ Rédiger votre trame Ethernet : + + setSimpleIpv6(e.target.value)} + required + label="Adresse mac destination" + /> + setSimpleIpv6(e.target.value)} + required + label="Adresse mac source" + /> + setSimpleIpv6(e.target.value)} + required + label="Type de trame Ethernet" + /> +