add middleware

This commit is contained in:
qpismont 2024-05-26 23:36:44 +02:00
parent c4d902c276
commit abad2cec96
10 changed files with 181 additions and 49 deletions

BIN
bun.lockb

Binary file not shown.

View file

@ -12,10 +12,10 @@
"dependencies": { "dependencies": {
"@astrojs/check": "^0.7.0", "@astrojs/check": "^0.7.0",
"@astrojs/node": "^8.2.5", "@astrojs/node": "^8.2.5",
"@astrojs/react": "^3.3.4", "@astrojs/react": "^3.4.0",
"@types/react": "^18.3.2", "@types/react": "^18.3.2",
"@types/react-dom": "^18.3.0", "@types/react-dom": "^18.3.0",
"astro": "^4.8.4", "astro": "^4.9.1",
"bootstrap": "^5.3.3", "bootstrap": "^5.3.3",
"react": "^18.3.1", "react": "^18.3.1",
"react-dom": "^18.3.1", "react-dom": "^18.3.1",

View file

@ -1,23 +1,71 @@
export default function LoginForm() { import { useState } from "react";
export interface LoginFormValue {
username: string;
password: string;
}
interface LoginFormProps {
onSubmit: (data: LoginFormValue) => void;
}
export default function LoginForm(props: LoginFormProps) {
const [form, setForm] = useState<LoginFormValue>({
username: "",
password: "",
});
function handleInputChange(event: React.ChangeEvent<HTMLInputElement>) {
const target = event.target;
const name = target.name;
const value = target.value;
setForm({
...form,
[name]: value,
});
}
function handleBtnClick() {
props.onSubmit({ ...form });
}
return ( return (
<div className="card"> <div className="card">
<div className="card-body"> <div className="card-body">
<form> <form>
<div className="form-floating mb-3"> <div className="form-floating mb-3">
<input type="text" className="form-control" id="username" /> <input
type="text"
className="form-control"
id="username"
name="username"
value={form.username}
onChange={handleInputChange}
/>
<label className="form-label">Nom d'utilisateur</label> <label className="form-label">Nom d'utilisateur</label>
</div> </div>
<div className="form-floating mb-3"> <div className="form-floating mb-3">
<input type="password" className="form-control" id="password" /> <input
type="password"
className="form-control"
id="password"
name="password"
onChange={handleInputChange}
value={form.password}
/>
<label className="form-label">Mot de passe</label> <label className="form-label">Mot de passe</label>
</div> </div>
</form>
<div className="d-grid"> <div className="d-grid">
<button type="submit" className="btn btn-primary"> <button
type="button"
onClick={handleBtnClick}
className="btn btn-primary"
>
Connexion Connexion
</button> </button>
</div> </div>
</form>
</div> </div>
</div> </div>
); );

View file

@ -0,0 +1,22 @@
import LoginForm, { type LoginFormValue } from "./LoginForm";
export default function LoginFormData() {
function handleOnFormSubmit(data: LoginFormValue) {
fetch(`${import.meta.env.PUBLIC_API_URL}/accounts/login`, {
method: "POST",
body: JSON.stringify(data),
credentials: "include",
headers: {
Accept: "application/json",
"Content-Type": "application/json",
},
})
.then((res) => res.json())
.then((json) => {
window.location.href = "/home";
})
.catch((err) => console.log(err));
}
return <LoginForm onSubmit={handleOnFormSubmit} />;
}

10
src/env.d.ts vendored
View file

@ -1 +1,11 @@
/// <reference types="astro/client" /> /// <reference types="astro/client" />
declare namespace App {
interface Locals {
account?: {
id: number;
username: string;
role_id: number;
};
}
}

View file

@ -0,0 +1,25 @@
---
import RootLayout from "./RootLayout.astro";
interface Props {
title: string;
}
const { title } = Astro.props;
---
<RootLayout title={title}>
<div class="row justify-content-center">
<div class="col-auto">Films</div>
<div class="col-auto">Compte</div>
<div class="col-auto">Deconnexion</div>
</div>
<div class="row">
<div class="col">
<slot />
</div>
</div>
</RootLayout>
<script></script>

29
src/middleware.ts Normal file
View file

@ -0,0 +1,29 @@
import { defineMiddleware, sequence } from "astro:middleware";
const protectedRoutes = defineMiddleware(async (ctx, next) => {
const pathname = ctx.url.pathname;
if (!["/", "/register"].includes(pathname)) {
const jwt = ctx.cookies.get("token");
if (!jwt) {
return ctx.redirect("/");
}
const res = await fetch(
`${import.meta.env.PUBLIC_API_URL}/accounts/recovery`,
{
credentials: "include",
headers: ctx.request.headers,
},
);
if (res.status !== 201) {
return ctx.redirect("/");
}
ctx.locals.account = JSON.parse(await res.text()).account;
}
return await next();
});
export const onRequest = sequence(defineMiddleware(protectedRoutes));

View file

@ -0,0 +1,9 @@
---
import HomeLayout from "../../layouts/HomeLayout.astro";
const account = Astro.locals.account;
---
<HomeLayout title="Trepa">
Hello {account?.username}
</HomeLayout>

View file

@ -1,10 +1,8 @@
--- ---
import LoginFormData from "../components/forms/LoginFormData";
import EmptyLayout from "../layouts/EmptyLayout.astro"; import EmptyLayout from "../layouts/EmptyLayout.astro";
const jwt = Astro.cookies.get("jwt");
if (!jwt) {
Astro.redirect("/login");
}
--- ---
<EmptyLayout title="Welcome to Astro." /> <EmptyLayout title="Trepa - Connexion">
<LoginFormData client:load />
</EmptyLayout>

View file

@ -1,9 +0,0 @@
---
import RootLayout from "../layouts/RootLayout.astro";
import LoginForm from "../components/forms/LoginForm";
import EmptyLayout from "../layouts/EmptyLayout.astro";
---
<EmptyLayout title="Welcome to Astro.">
<LoginForm />
</EmptyLayout>