Added implementation for base page and log in log out

This commit is contained in:
fedyna-k
2025-01-14 23:34:40 +01:00
parent 9a97591bda
commit ccad788e19
27 changed files with 374 additions and 479 deletions
+31
View File
@@ -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-----
+52
View File
@@ -0,0 +1,52 @@
-----BEGIN PRIVATE KEY-----
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
TbEoB7CaVs+VEYE4GJpDXp3V2CQ3
-----END PRIVATE KEY-----
+2
View File
@@ -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",
+7 -1
View File
@@ -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
}
});
+12 -4
View File
@@ -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,
-127
View File
@@ -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);
}
}
-37
View File
@@ -1,37 +0,0 @@
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>Mock</title>
<link rel="stylesheet" href="base.css">
<link rel="stylesheet" href="main.css">
<meta name="theme-color" content="#57575a">
<meta name="msapplication-TileColor" content="#57575a">
<meta name="msapplication-navbutton-color" content="#57575a">
<meta name="apple-mobile-web-app-status-bar-style" content="#57575a">
</head>
<body>
<!-- <section id="background">
<svg class="waves" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink"
viewBox="0 24 150 28" preserveAspectRatio="none" shape-rendering="auto">
<defs>
<path id="gentle-wave" d="M-160 44c30 0 58-18 88-18s 58 18 88 18 58-18 88-18 58 18 88 18 v44h-352z" />
</defs>
<g class="parallax">
<use xlink:href="#gentle-wave" x="48" y="5" fill="#fff1" />
<use xlink:href="#gentle-wave" x="48" y="3" fill="#fff1" />
<use xlink:href="#gentle-wave" x="48" y="0" fill="#fff1" />
<use xlink:href="#gentle-wave" x="48" y="7" fill="#fff1" />
</g>
</svg>
</section> -->
<section id="main">
<h1>PolyMPR</h1>
<p>Random text go brrr</p>
</section>
</body>
</html>
-13
View File
@@ -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;
}
-38
View File
@@ -1,38 +0,0 @@
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>Mock</title>
<link rel="stylesheet" href="base.css">
<link rel="stylesheet" href="loading-page.css">
<meta name="theme-color" content="#57575a">
<meta name="msapplication-TileColor" content="#57575a">
<meta name="msapplication-navbutton-color" content="#57575a">
<meta name="apple-mobile-web-app-status-bar-style" content="#57575a">
</head>
<body>
<!-- <section id="background">
<svg class="waves" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink"
viewBox="0 24 150 28" preserveAspectRatio="none" shape-rendering="auto">
<defs>
<path id="gentle-wave" d="M-160 44c30 0 58-18 88-18s 58 18 88 18 58-18 88-18 58 18 88 18 v44h-352z" />
</defs>
<g class="parallax">
<use xlink:href="#gentle-wave" x="48" y="5" fill="#fff1" />
<use xlink:href="#gentle-wave" x="48" y="3" fill="#fff1" />
<use xlink:href="#gentle-wave" x="48" y="0" fill="#fff1" />
<use xlink:href="#gentle-wave" x="48" y="7" fill="#fff1" />
</g>
</svg>
</section> -->
<section id="main">
<h1>PolyMPR</h1>
<p>Logging in with amU credentials...</p>
<div class="loader"></div>
</section>
</body>
</html>
-15
View File
@@ -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;
}
View File
+1 -16
View File
@@ -6,22 +6,7 @@ export default function Error404() {
<Head>
<title>404 - Page not found</title>
</Head>
<div class="px-4 py-8 mx-auto bg-[#86efac]">
<div class="max-w-screen-md mx-auto flex flex-col items-center justify-center">
<img
class="my-6"
src="/logo.svg"
width="128"
height="128"
alt="the Fresh logo: a sliced lemon dripping with juice"
/>
<h1 class="text-4xl font-bold">404 - Page not found</h1>
<p class="my-4">
The page you were looking for doesn't exist.
</p>
<a href="/" class="underline">Go back home</a>
</div>
</div>
<p>404</p>
</>
);
}
+24 -7
View File
@@ -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 (
<html>
<head>
<meta charset="utf-8" />
<meta name="viewport" content="width=device-width, initial-scale=1.0" />
<title>polympr</title>
<link rel="stylesheet" href="/styles.css" />
<title>PolyMPR</title>
<link rel="stylesheet" href="/styles/main.css" />
</head>
<body>
<Component />
<body f-client-nav>
<header>
<h1>PolyMPR</h1>
<nav>
<a href="/modules" f-partial="/partials/modules">Modules</a>
<a href={`/log${link}`} f-client-nav={false}>Log {link}</a>
</nav>
</header>
<Partial name="body">
<context.Component />
</Partial>
<footer>
<p>&copy; 2025 PolyMPR - <a href="/about" f-partial="/partials/about">About</a></p>
</footer>
</body>
</html>
);
}
}
+39
View File
@@ -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<State>) {
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<State>) {
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();
}
];
-21
View File
@@ -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);
};
-5
View File
@@ -1,5 +0,0 @@
import { PageProps } from "$fresh/server.ts";
export default function Greet(props: PageProps) {
return <div>Hello {props.params.name}</div>;
}
+1 -18
View File
@@ -2,24 +2,7 @@ import { useSignal } from "@preact/signals";
import Counter from "../islands/Counter.tsx";
export default function Home() {
const count = useSignal(3);
return (
<div class="px-4 py-8 mx-auto bg-[#86efac]">
<div class="max-w-screen-md mx-auto flex flex-col items-center justify-center">
<img
class="my-6"
src="/logo.svg"
width="128"
height="128"
alt="the Fresh logo: a sliced lemon dripping with juice"
/>
<h1 class="text-4xl font-bold">Welcome to Fresh</h1>
<p class="my-4">
Try updating this message in the
<code class="mx-2">./routes/index.tsx</code> file, and refresh.
</p>
<Counter count={count} />
</div>
</div>
<h1>PolyMPR</h1>
);
}
+102
View File
@@ -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<string> {
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<any, State> = {
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}`
}
});
}
}
};
+32
View File
@@ -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<any, State> = {
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: "/"
}
});
}
}
};
+15
View File
@@ -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 (
<Partial name="body">
<p>C'est nous wsh</p>
</Partial>
);
};
View File
Binary file not shown.

Before

Width:  |  Height:  |  Size: 22 KiB

-6
View File
@@ -1,6 +0,0 @@
<svg width="40" height="40" fill="none" xmlns="http://www.w3.org/2000/svg">
<path d="M34.092 8.845C38.929 20.652 34.092 27 30 30.5c1 3.5-2.986 4.222-4.5 2.5-4.457 1.537-13.512 1.487-20-5C2 24.5 4.73 16.714 14 11.5c8-4.5 16-7 20.092-2.655Z" fill="#FFDB1E"/>
<path d="M14 11.5c6.848-4.497 15.025-6.38 18.368-3.47C37.5 12.5 21.5 22.612 15.5 25c-6.5 2.587-3 8.5-6.5 8.5-3 0-2.5-4-5.183-7.75C2.232 23.535 6.16 16.648 14 11.5Z" fill="#fff" stroke="#FFDB1E"/>
<path d="M28.535 8.772c4.645 1.25-.365 5.695-4.303 8.536-3.732 2.692-6.606 4.21-7.923 4.83-.366.173-1.617-2.252-1.617-1 0 .417-.7 2.238-.934 2.326-1.365.512-4.223 1.29-5.835 1.29-3.491 0-1.923-4.754 3.014-9.122.892-.789 1.478-.645 2.283-.645-.537-.773-.534-.917.403-1.546C17.79 10.64 23 8.77 25.212 8.42c.366.014.82.35.82.629.41-.14 2.095-.388 2.503-.278Z" fill="#FFE600"/>
<path d="M14.297 16.49c.985-.747 1.644-1.01 2.099-2.526.566.121.841-.08 1.29-.701.324.466 1.657.608 2.453.701-.715.451-1.057.852-1.452 2.106-1.464-.611-3.167-.302-4.39.42Z" fill="#fff"/>
</svg>

Before

Width:  |  Height:  |  Size: 1.0 KiB

-129
View File
@@ -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;
}
+56
View File
@@ -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));
}
-27
View File
@@ -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()
-15
View File
@@ -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();