diff --git a/certs/cert.pem b/certs/cert.pem
new file mode 100644
index 0000000..1c825f4
--- /dev/null
+++ b/certs/cert.pem
@@ -0,0 +1,31 @@
+-----BEGIN CERTIFICATE-----
+MIIFazCCA1OgAwIBAgIUBzpjXMENeWGtcDHiOJ6mvvP+C48wDQYJKoZIhvcNAQEL
+BQAwRTELMAkGA1UEBhMCQVUxEzARBgNVBAgMClNvbWUtU3RhdGUxITAfBgNVBAoM
+GEludGVybmV0IFdpZGdpdHMgUHR5IEx0ZDAeFw0yNTAxMTQxNjUwMzhaFw0yNjAx
+MTQxNjUwMzhaMEUxCzAJBgNVBAYTAkFVMRMwEQYDVQQIDApTb21lLVN0YXRlMSEw
+HwYDVQQKDBhJbnRlcm5ldCBXaWRnaXRzIFB0eSBMdGQwggIiMA0GCSqGSIb3DQEB
+AQUAA4ICDwAwggIKAoICAQCrwtnHsgIcPgiiwbJuwx7qDxIAoDX4TpGCfSemHJyp
+OTHbEbYkuTwgFqMhn83fm3DMnn/vorDfWOCpm4OvYIJ4QB9ZeiwDyvmjJQITX0o7
+pm2J0tpmFv4WK9BF+46bq81TtXUG99/ryH9NKFGT0WSdu0XHIqtg9OfVHolw9vPD
+PmmxRcPXg+2HziWBQuxqXHazdU31Cf8JDv3iBSYAIOmAsIAp4KuJtfX6MYK4/3jT
+huSfGzCnMlieDYj2mUcvCEx4iMk+nshryp5UB6+mgmqC9XgBwPOsqbybd3WnQXaA
+gT8bGqjLIYMqJrDVBPcuz+J9i3PFtheHtvmwE82aWSzWAK188NXzK6J2+BJFp97f
+dmPaSh5sEFe3twXNeIQgYjQ0b1Y6K9wSyk0mEgitIrp+ARmuSR7a9SHgdLg9FaMg
+LkUSrRk46r6P/lO9hSrCusH0cFwMIxgclS0DOPbfwqDIELClSaxO6umKh161W0kP
+k38k1DIdrWDUQnb4dMrQdSZrYmpyXhDNsLfHF+hZtNSy+376Utuud0UJSnO6k4QK
+JtpPaZRPPBIxcZ3a05JY09pVKHmev+j5U0fcuGWGyRa/cyPsHgU1kGVVOLaC21SJ
+h8qWZCqUYby9AsbuTqz9qOpGNmCivmgUESs+h4VZoOOzj+5zGCK5LbIfsLL/nI2+
+QQIDAQABo1MwUTAdBgNVHQ4EFgQUrCJYEE6AckkV62vmB6NpgFSM1QYwHwYDVR0j
+BBgwFoAUrCJYEE6AckkV62vmB6NpgFSM1QYwDwYDVR0TAQH/BAUwAwEB/zANBgkq
+hkiG9w0BAQsFAAOCAgEApzFmj9XCez3mRLctBCsrTHMueNFrLovscoxb2kWirnIJ
+nM0GfLhZcx56+ZXUea5khbIbJrF47Eyh4GVz6ezZnoVBkb2PnD5FzafLxQEhg/bT
+9zMWrcGVCe9/Uz1znUXDh7ljj15h60CdhyG3EVCfWxzJs3m/sOGDlA6qDxx0MNdY
+PjdQaPPHCH1yDn7vkBWD9SRHJh4/wAl+LAf+3eF9Uz7CRRYA/sYu2dzLLfUXo+My
+LJ8JIss2p24pRl6FyHNH5pJ1Uvr0wGfJ9h0rrKixfHgJ3478cxVxns8Ig0BTWJPV
+kMdh+rplnnE4CSAaPWnAbD6O4WM7pDQDRXc8kfrcyt0MQ0UYPLwcpQ72umIOkonK
+R0FsPLvRe0lmsMeG+Id34CEFtxegbsGCt5OOMKzA3k69JVvLvS85FuLO2a+TrDYg
+itCKHVX06oAGa8XAsy1q/s9BMxNWzVDAza6svINaIqubHk1YGJ/hiAvVvBuEKHnT
+Gc9uYQEngA3zVjhoiPx2Z6AoSj6Ve2K38JZgPOAfo887W+4a/mguV8QlVv2qeibm
+jZKTKglZvH6Iz/v+zM2mWdh+RsyW+hkUum6lH/0vpQnZAUcMK8U5YnAjsFF8tfWy
+eJY2gFisHwz6pVY5FwUW/FvaWRIfPTp9CdTHJlhlGTNb3SlLODaM+um46aFaUz0=
+-----END CERTIFICATE-----
diff --git a/certs/key.pem b/certs/key.pem
new file mode 100644
index 0000000..21816ce
--- /dev/null
+++ b/certs/key.pem
@@ -0,0 +1,52 @@
+-----BEGIN PRIVATE KEY-----
+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
+TbEoB7CaVs+VEYE4GJpDXp3V2CQ3
+-----END PRIVATE KEY-----
diff --git a/deno.json b/deno.json
index 76ef608..ef4b243 100644
--- a/deno.json
+++ b/deno.json
@@ -22,6 +22,8 @@
],
"imports": {
"$fresh/": "https://deno.land/x/fresh@1.7.3/",
+ "@melvdouc/xml-parser": "jsr:@melvdouc/xml-parser@^0.1.1",
+ "@popov/jwt": "jsr:@popov/jwt@^1.0.1",
"preact": "https://esm.sh/preact@10.22.0",
"preact/": "https://esm.sh/preact@10.22.0/",
"@preact/signals": "https://esm.sh/*@preact/signals@1.2.2",
diff --git a/fresh.config.ts b/fresh.config.ts
index e7b63d9..783c68c 100644
--- a/fresh.config.ts
+++ b/fresh.config.ts
@@ -1,3 +1,9 @@
import { defineConfig } from "$fresh/server.ts";
-export default defineConfig({});
+export default defineConfig({
+ server: {
+ cert: await Deno.readTextFile("certs/cert.pem"),
+ key: await Deno.readTextFile("certs/key.pem"),
+ port: 443
+ }
+});
diff --git a/fresh.gen.ts b/fresh.gen.ts
index dd4df1a..cce7416 100644
--- a/fresh.gen.ts
+++ b/fresh.gen.ts
@@ -2,21 +2,29 @@
// This file SHOULD be checked into source version control.
// This file is automatically updated during development when running `dev.ts`.
+import * as $_modules_notes_index from "./routes/(modules)/notes/index.tsx";
import * as $_404 from "./routes/_404.tsx";
import * as $_app from "./routes/_app.tsx";
-import * as $api_joke from "./routes/api/joke.ts";
-import * as $greet_name_ from "./routes/greet/[name].tsx";
+import * as $_middleware from "./routes/_middleware.ts";
import * as $index from "./routes/index.tsx";
+import * as $login from "./routes/login.tsx";
+import * as $logout from "./routes/logout.tsx";
+import * as $partials_about from "./routes/partials/about.tsx";
+import * as $partials_modules from "./routes/partials/modules.tsx";
import * as $Counter from "./islands/Counter.tsx";
import type { Manifest } from "$fresh/server.ts";
const manifest = {
routes: {
+ "./routes/(modules)/notes/index.tsx": $_modules_notes_index,
"./routes/_404.tsx": $_404,
"./routes/_app.tsx": $_app,
- "./routes/api/joke.ts": $api_joke,
- "./routes/greet/[name].tsx": $greet_name_,
+ "./routes/_middleware.ts": $_middleware,
"./routes/index.tsx": $index,
+ "./routes/login.tsx": $login,
+ "./routes/logout.tsx": $logout,
+ "./routes/partials/about.tsx": $partials_about,
+ "./routes/partials/modules.tsx": $partials_modules,
},
islands: {
"./islands/Counter.tsx": $Counter,
diff --git a/mock/base.css b/mock/base.css
deleted file mode 100644
index 7a1aa9f..0000000
--- a/mock/base.css
+++ /dev/null
@@ -1,127 +0,0 @@
-@import url('https://fonts.googleapis.com/css2?family=Jost:ital,wght@0,100..900;1,100..900&family=JetBrains+Mono:ital,wght@0,100..800;1,100..800&display=swap');
-
-:root {
- color-scheme: light dark;
-
- --dark-background-color: rgb(30, 30, 42);
- --dark-background-color-ui: rgb(50, 50, 62);
- --dark-foreground: rgb(241, 241, 255);
-
- --light-background-color: rgb(225, 225, 237);
- --light-background-color-ui: rgb(241, 241, 255);
- --light-foreground: rgb(30, 30, 42);
-
- --wave-color-1: #282830;
- --wave-color-2: #383840;
- --wave-color-3: #585860;
- --wave-color-4: #969698;
-
- --loader-size: 0.5em;
-}
-
-* {
- box-sizing: border-box;
-}
-
-html, body {
- margin: 0;
- padding: 0;
- color: light-dark(var(--light-foreground), var(--dark-foreground));
- background-color: light-dark(var(--light-background-color), var(--dark-background-color));
- height: 100dvh;
- width: 100dvw;
-}
-
-body {
- display: grid;
- font-family: Jost, sans-serif;
- font-feature-settings: "ss01" 1;
- font-weight: 500;
- place-content: center;
- padding: 0.75em;
-}
-
-h1 {
- font-family: Jost, sans-serif;
- margin: 0;
- font-size: 1.5em;
-}
-
-@media screen and (max-width: 750px) {
- section#main {
- font-size: 1em;
- }
-}
-
-/** loader */
-
-.loader {
- margin: 2em 0;
- width: calc(4 * var(--loader-size));
- height: calc(4 * var(--loader-size));
- position: relative;
- --c:no-repeat linear-gradient(light-dark(var(--light-foreground), var(--dark-foreground)) 0 0);
- background:
- var(--c) center/100% var(--loader-size),
- var(--c) center/var(--loader-size) 100%;
-}
-
-.loader:before {
- content:'';
- position: absolute;
- inset: 0;
- background:
- var(--c) 0 0,
- var(--c) 100% 0,
- var(--c) 0 100%,
- var(--c) 100% 100%;
- background-size: calc(1.55 * var(--loader-size)) calc(1.55 * var(--loader-size));
- animation: l16 1.5s infinite cubic-bezier(0.3,1,0,1);
-}
-
-@keyframes l16 {
- 33% {inset:calc(-1 * var(--loader-size));transform: rotate(0deg)}
- 66% {inset:calc(-1 * var(--loader-size));transform: rotate(90deg)}
- 100% {inset:0 ;transform: rotate(90deg)}
-}
-
-/** waves */
-
-section#background {
- position: absolute;
- bottom: 0;
- width: 100%;
-}
-
-.parallax > use {
- animation: move-forever 25s cubic-bezier(.55,.5,.45,.5) infinite;
-}
-
-.parallax > use:nth-child(1) {
- animation-delay: -2s;
- animation-duration: 7s;
-}
-
-.parallax > use:nth-child(2) {
- animation-delay: -3s;
- animation-duration: 10s;
-}
-
-.parallax > use:nth-child(3) {
- animation-delay: -4s;
- animation-duration: 13s;
-}
-
-.parallax > use:nth-child(4) {
- animation-delay: -5s;
- animation-duration: 20s;
-}
-
-@keyframes move-forever {
- 0% {
- transform: translate3d(-90px,0,0);
- }
- 100% {
- transform: translate3d(85px,0,0);
- }
-}
\ No newline at end of file
diff --git a/mock/index.html b/mock/index.html
deleted file mode 100644
index fc623d4..0000000
--- a/mock/index.html
+++ /dev/null
@@ -1,37 +0,0 @@
-
-
-
-
-
- Mock
-
-
-
-
-
-
-
-
-
-
-
-
-
- PolyMPR
- Random text go brrr
-
-
-
\ No newline at end of file
diff --git a/mock/loading-page.css b/mock/loading-page.css
deleted file mode 100644
index 78e7714..0000000
--- a/mock/loading-page.css
+++ /dev/null
@@ -1,13 +0,0 @@
-section#main {
- display: flex;
- flex-direction: column;
- justify-content: center;
- align-items: center;
- text-align: center;
-
- background-color: light-dark(var(--light-background-color-ui), var(--dark-background-color-ui));
- padding: 2em;
- font-size: 2em;
- border-radius: 0.5em;
- z-index: 999;
-}
\ No newline at end of file
diff --git a/mock/loading.html b/mock/loading.html
deleted file mode 100644
index c785837..0000000
--- a/mock/loading.html
+++ /dev/null
@@ -1,38 +0,0 @@
-
-
-
-
-
- Mock
-
-
-
-
-
-
-
-
-
-
-
-
-
- PolyMPR
- Logging in with amU credentials...
-
-
-
-
\ No newline at end of file
diff --git a/mock/main.css b/mock/main.css
deleted file mode 100644
index e2ef1ee..0000000
--- a/mock/main.css
+++ /dev/null
@@ -1,15 +0,0 @@
-section#main {
- display: flex;
- flex-direction: column;
- justify-content: flex-start;
- align-items: start;
-
- background-color: light-dark(var(--light-background-color-ui), var(--dark-background-color-ui));
- padding: 2em;
- font-size: 2em;
- border-radius: 0.5em;
- z-index: 999;
-
- width: 90dvw;
- height: 90dvh;
-}
\ No newline at end of file
diff --git a/routes/(modules)/notes/index.tsx b/routes/(modules)/notes/index.tsx
new file mode 100644
index 0000000..e69de29
diff --git a/routes/_404.tsx b/routes/_404.tsx
index c63ae2e..fb42994 100644
--- a/routes/_404.tsx
+++ b/routes/_404.tsx
@@ -6,22 +6,7 @@ export default function Error404() {
404 - Page not found
-
-
-
-
404 - Page not found
-
- The page you were looking for doesn't exist.
-
-
Go back home
-
-
+ 404
>
);
}
diff --git a/routes/_app.tsx b/routes/_app.tsx
index 6e4ecf6..0d62d67 100644
--- a/routes/_app.tsx
+++ b/routes/_app.tsx
@@ -1,16 +1,33 @@
-import { type PageProps } from "$fresh/server.ts";
-export default function App({ Component }: PageProps) {
+import { FreshContext } from "$fresh/server.ts";
+import { Partial } from "$fresh/runtime.ts";
+
+
+export default async function App(request: Request, context: FreshContext) {
+ const link = context.state.isAuthenticated ? "out" : "in";
+
return (
- polympr
-
+ PolyMPR
+
-
-
+
+
+
+
+
+
+ © 2025 PolyMPR - About
+
);
-}
+}
\ No newline at end of file
diff --git a/routes/_middleware.ts b/routes/_middleware.ts
new file mode 100644
index 0000000..b26a63e
--- /dev/null
+++ b/routes/_middleware.ts
@@ -0,0 +1,39 @@
+import { MiddlewareHandlerContext } from "$fresh/server.ts";
+import { getCookies } from "$std/http/cookie.ts";
+import { isJwtValid } from "@popov/jwt";
+
+
+const PUBLIC_ROUTES = ["/", "/login", "/logout", "/about", "/contact"];
+
+interface State {
+ isAuthenticated: boolean;
+}
+
+
+function isRoutePublic(route: string) {
+ return PUBLIC_ROUTES.includes(route) || route.match(/\..+$/);
+}
+
+
+export const handler = [
+ async function checkAuthentication(request: Request, context: MiddlewareHandlerContext) {
+ const cookies = getCookies(request.headers);
+ context.state.isAuthenticated = await isJwtValid(cookies["sessionToken"] ?? "", "NEED TO CHANGE THIS KEY FURTHER IN DEV");
+
+ return context.next();
+ },
+ async function ensureAuthentication(request: Request, context: MiddlewareHandlerContext) {
+ const url = new URL(request.url);
+
+ if (!isRoutePublic(url.pathname) && !context.state.isAuthenticated) {
+ return new Response(null, {
+ status: 302,
+ headers: {
+ Location: "/login"
+ }
+ });
+ }
+
+ return context.next();
+ }
+];
\ No newline at end of file
diff --git a/routes/api/joke.ts b/routes/api/joke.ts
deleted file mode 100644
index db17edd..0000000
--- a/routes/api/joke.ts
+++ /dev/null
@@ -1,21 +0,0 @@
-import { FreshContext } from "$fresh/server.ts";
-
-// Jokes courtesy of https://punsandoneliners.com/randomness/programmer-jokes/
-const JOKES = [
- "Why do Java developers often wear glasses? They can't C#.",
- "A SQL query walks into a bar, goes up to two tables and says “can I join you?”",
- "Wasn't hard to crack Forrest Gump's password. 1forrest1.",
- "I love pressing the F5 key. It's refreshing.",
- "Called IT support and a chap from Australia came to fix my network connection. I asked “Do you come from a LAN down under?”",
- "There are 10 types of people in the world. Those who understand binary and those who don't.",
- "Why are assembly programmers often wet? They work below C level.",
- "My favourite computer based band is the Black IPs.",
- "What programme do you use to predict the music tastes of former US presidential candidates? An Al Gore Rhythm.",
- "An SEO expert walked into a bar, pub, inn, tavern, hostelry, public house.",
-];
-
-export const handler = (_req: Request, _ctx: FreshContext): Response => {
- const randomIndex = Math.floor(Math.random() * JOKES.length);
- const body = JOKES[randomIndex];
- return new Response(body);
-};
diff --git a/routes/greet/[name].tsx b/routes/greet/[name].tsx
deleted file mode 100644
index 9c06827..0000000
--- a/routes/greet/[name].tsx
+++ /dev/null
@@ -1,5 +0,0 @@
-import { PageProps } from "$fresh/server.ts";
-
-export default function Greet(props: PageProps) {
- return Hello {props.params.name}
;
-}
diff --git a/routes/index.tsx b/routes/index.tsx
index fc8061e..d06b743 100644
--- a/routes/index.tsx
+++ b/routes/index.tsx
@@ -2,24 +2,7 @@ import { useSignal } from "@preact/signals";
import Counter from "../islands/Counter.tsx";
export default function Home() {
- const count = useSignal(3);
return (
-
-
-
-
Welcome to Fresh
-
- Try updating this message in the
- ./routes/index.tsx file, and refresh.
-
-
-
-
+ PolyMPR
);
}
diff --git a/routes/login.tsx b/routes/login.tsx
new file mode 100644
index 0000000..fd0db53
--- /dev/null
+++ b/routes/login.tsx
@@ -0,0 +1,102 @@
+import { Handlers } from "$fresh/server.ts";
+import { State } from "./_middleware.ts";
+import { parse, type XmlNode } from "@melvdouc/xml-parser";
+import { createJwt } from "@popov/jwt";
+import { setCookie } from "$std/http/cookie.ts";
+
+
+const SERVICE = "https://localhost/login";
+const CAS = "https://ident.univ-amu.fr/cas";
+
+
+function getTag(tag: XmlNode): [string, string] {
+ return [
+ tag.tagName.replace("cas:", ""),
+ tag.children[0].value
+ ];
+}
+
+
+async function createUserJWT(casResponse: XmlNode): Promise {
+ const nodes = casResponse.children[1].children.map(getTag);
+ const fullUserInfos = {};
+
+ nodes.forEach(([key, value]) => {
+ if (fullUserInfos[key] && Array.isArray(fullUserInfos[key])) {
+ fullUserInfos[key].push(value);
+ }
+ else if (fullUserInfos[key]) {
+ fullUserInfos[key] = [fullUserInfos[key], value];
+ }
+ else {
+ fullUserInfos[key] = value;
+ }
+ });
+
+ const now = Math.floor(Date.now() / 1000);
+ const oneHour = 60 * 60;
+
+ const payload = {
+ iss: "PolyMPR",
+ iat: now,
+ exp: now + oneHour,
+ aud: "PolyMPR",
+ user: fullUserInfos
+ };
+
+ const key = "NEED TO CHANGE THIS KEY FURTHER IN DEV";
+ return createJwt(payload, key);
+}
+
+
+export const handler: Handlers = {
+ async GET(request, context) {
+ const url = new URL(request.url);
+ const ticket = url.searchParams.get("ticket");
+
+ if (ticket) {
+ const response = await fetch(`${CAS}/serviceValidate?service=${SERVICE}&ticket=${ticket}`);
+ const body = parse(await response.text(), "application/xml");
+ const casResponse = body[0].children[0];
+
+ if (casResponse.tagName != "cas:authenticationSuccess") {
+ return new Response(null, {
+ status: 302,
+ headers: {
+ Location: `${CAS}/login?service=${SERVICE}`
+ }
+ });
+ }
+
+ const headers = new Headers();
+
+ setCookie(headers, {
+ name: "sessionToken",
+ value: await createUserJWT(casResponse)
+ });
+ headers.set("Location", "/apps");
+
+ return new Response(null, {
+ status: 302,
+ headers
+ });
+ }
+
+ if (context.state.isAuthenticated) {
+ return new Response(null, {
+ status: 302,
+ headers: {
+ Location: "/apps"
+ }
+ });
+ }
+ else {
+ return new Response(null, {
+ status: 302,
+ headers: {
+ Location: `${CAS}/login?service=${SERVICE}`
+ }
+ });
+ }
+ }
+};
\ No newline at end of file
diff --git a/routes/logout.tsx b/routes/logout.tsx
new file mode 100644
index 0000000..730d9d3
--- /dev/null
+++ b/routes/logout.tsx
@@ -0,0 +1,32 @@
+import { Handlers } from "$fresh/server.ts";
+import { State } from "./_middleware.ts";
+import { deleteCookie } from "$std/http/cookie.ts";
+
+
+const SERVICE = "https://localhost/";
+const CAS = "https://ident.univ-amu.fr/cas";
+
+
+export const handler: Handlers = {
+ async GET(request, context) {
+ if (context.state.isAuthenticated) {
+ const headers = new Headers();
+
+ deleteCookie(headers, "sessionToken", { path: "/" });
+ headers.set("Location", `${CAS}/logout?service=${SERVICE}`);
+
+ return new Response(null, {
+ status: 302,
+ headers
+ });
+ }
+ else {
+ return new Response(null, {
+ status: 302,
+ headers: {
+ Location: "/"
+ }
+ });
+ }
+ }
+};
\ No newline at end of file
diff --git a/routes/partials/about.tsx b/routes/partials/about.tsx
new file mode 100644
index 0000000..f4f920c
--- /dev/null
+++ b/routes/partials/about.tsx
@@ -0,0 +1,15 @@
+import { RouteConfig } from "$fresh/server.ts";
+import { Partial } from "$fresh/runtime.ts";
+
+export const config: RouteConfig = {
+ skipAppWrapper: true,
+ skipInheritedLayouts: true,
+};
+
+export default async function About(request, context) {
+ return (
+
+ C'est nous wsh
+
+ );
+};
\ No newline at end of file
diff --git a/routes/partials/modules.tsx b/routes/partials/modules.tsx
new file mode 100644
index 0000000..e69de29
diff --git a/static/favicon.ico b/static/favicon.ico
deleted file mode 100644
index 1cfaaa2..0000000
Binary files a/static/favicon.ico and /dev/null differ
diff --git a/static/logo.svg b/static/logo.svg
deleted file mode 100644
index ef2fbe4..0000000
--- a/static/logo.svg
+++ /dev/null
@@ -1,6 +0,0 @@
-
-
-
-
-
-
\ No newline at end of file
diff --git a/static/styles.css b/static/styles.css
deleted file mode 100644
index e94132d..0000000
--- a/static/styles.css
+++ /dev/null
@@ -1,129 +0,0 @@
-
-*,
-*::before,
-*::after {
- box-sizing: border-box;
-}
-* {
- margin: 0;
-}
-button {
- color: inherit;
-}
-button, [role="button"] {
- cursor: pointer;
-}
-code {
- font-family: ui-monospace, SFMono-Regular, Menlo, Monaco, Consolas,
- "Liberation Mono", "Courier New", monospace;
- font-size: 1em;
-}
-img,
-svg {
- display: block;
-}
-img,
-video {
- max-width: 100%;
- height: auto;
-}
-
-html {
- line-height: 1.5;
- -webkit-text-size-adjust: 100%;
- font-family: ui-sans-serif, system-ui, -apple-system, BlinkMacSystemFont,
- "Segoe UI", Roboto, "Helvetica Neue", Arial, "Noto Sans", sans-serif,
- "Apple Color Emoji", "Segoe UI Emoji", "Segoe UI Symbol", "Noto Color Emoji";
-}
-.transition-colors {
- transition-property: background-color, border-color, color, fill, stroke;
- transition-timing-function: cubic-bezier(0.4, 0, 0.2, 1);
- transition-duration: 150ms;
-}
-.my-6 {
- margin-bottom: 1.5rem;
- margin-top: 1.5rem;
-}
-.text-4xl {
- font-size: 2.25rem;
- line-height: 2.5rem;
-}
-.mx-2 {
- margin-left: 0.5rem;
- margin-right: 0.5rem;
-}
-.my-4 {
- margin-bottom: 1rem;
- margin-top: 1rem;
-}
-.mx-auto {
- margin-left: auto;
- margin-right: auto;
-}
-.px-4 {
- padding-left: 1rem;
- padding-right: 1rem;
-}
-.py-8 {
- padding-bottom: 2rem;
- padding-top: 2rem;
-}
-.bg-\[\#86efac\] {
- background-color: #86efac;
-}
-.text-3xl {
- font-size: 1.875rem;
- line-height: 2.25rem;
-}
-.py-6 {
- padding-bottom: 1.5rem;
- padding-top: 1.5rem;
-}
-.px-2 {
- padding-left: 0.5rem;
- padding-right: 0.5rem;
-}
-.py-1 {
- padding-bottom: 0.25rem;
- padding-top: 0.25rem;
-}
-.border-gray-500 {
- border-color: #6b7280;
-}
-.bg-white {
- background-color: #fff;
-}
-.flex {
- display: flex;
-}
-.gap-8 {
- grid-gap: 2rem;
- gap: 2rem;
-}
-.font-bold {
- font-weight: 700;
-}
-.max-w-screen-md {
- max-width: 768px;
-}
-.flex-col {
- flex-direction: column;
-}
-.items-center {
- align-items: center;
-}
-.justify-center {
- justify-content: center;
-}
-.border-2 {
- border-width: 2px;
-}
-.rounded {
- border-radius: 0.25rem;
-}
-.hover\:bg-gray-200:hover {
- background-color: #e5e7eb;
-}
-.tabular-nums {
- font-variant-numeric: tabular-nums;
-}
diff --git a/static/styles/main.css b/static/styles/main.css
new file mode 100644
index 0000000..9cedc36
--- /dev/null
+++ b/static/styles/main.css
@@ -0,0 +1,56 @@
+@import url('https://fonts.googleapis.com/css2?family=JetBrains+Mono:ital,wght@0,100..800;1,100..800&display=swap');
+
+:root {
+ color-scheme: light dark;
+
+ --dark-background-color: rgb(30, 30, 42);
+ --dark-background-color-ui: rgb(50, 50, 62);
+ --dark-foreground: rgb(241, 241, 255);
+ --dark-foreground-dim: rgb(171, 171, 179);
+
+ --light-background-color: rgb(225, 225, 237);
+ --light-background-color-ui: rgb(241, 241, 255);
+ --light-foreground: rgb(30, 30, 42);
+ --light-foreground-dim: rgb(171, 171, 179);
+
+ --accent-color: rgb(38, 157, 217);
+
+ --loader-size: 0.5em;
+}
+
+* {
+ box-sizing: border-box;
+ font-family: "Jetbrains Mono";
+}
+
+html, body {
+ margin: 0;
+ padding: 0;
+}
+
+body {
+ min-height: 100dvh;
+ display: grid;
+ grid-template-rows: auto 1fr auto;
+ background-color: light-dark(var(--light-background-color), var(--dark-background-color));
+ color: light-dark(var(--light-foreground), var(--dark-foreground));
+}
+
+header {
+ padding: 0.5em 2em;
+ display: flex;
+ justify-content: space-between;
+ align-items: center;
+}
+
+header > nav {
+ display: flex;
+ gap: 1em;
+}
+
+footer {
+ padding: 0.5em;
+ display: flex;
+ justify-content: center;
+ color: light-dark(var(--light-foreground-dim), var(--dark-foreground-dim));
+}
\ No newline at end of file
diff --git a/test/cas.js b/test/cas.js
deleted file mode 100644
index e2d442c..0000000
--- a/test/cas.js
+++ /dev/null
@@ -1,27 +0,0 @@
-async function main() {
- const initResponse = await fetch("https://ident.univ-amu.fr/cas/login");
- const initHTML = await initResponse.text();
- const execution = initHTML.match(/(?<=name="execution" value=").*?(?=")/)[0];
-
- const data = new URLSearchParams();
- data.append("username", Deno.env.get("CAS_USERNAME"));
- data.append("password", Deno.env.get("CAS_PASSWORD"));
- data.append("_eventId", "submit");
- data.append("execution", execution);
-
- const response = await fetch("https://ident.univ-amu.fr/cas/login", {
- method: "POST",
- headers: {
- "Content-Type": "application/x-www-form-urlencoded"
- },
- body: data.toString()
- });
- console.log(response.status)
- console.log(response.headers);
-
- const content = await response.text();
- console.log(content);
-}
-
-main()
-
diff --git a/test/getInfo.js b/test/getInfo.js
deleted file mode 100644
index 269043a..0000000
--- a/test/getInfo.js
+++ /dev/null
@@ -1,15 +0,0 @@
-const token = Deno.env.get("CAS_TOKEN");
-
-async function main() {
- const response = await fetch("https://ident.univ-amu.fr/login?service=http://localhost", {
- "Cookie": `TGC=${token}`
- });
- console.log(response.headers);
-
-
- const responseText = await response.text();
-
- console.log(responseText);
-}
-
-main();
\ No newline at end of file