add middleware
This commit is contained in:
parent
c4d902c276
commit
abad2cec96
10 changed files with 181 additions and 49 deletions
BIN
bun.lockb
BIN
bun.lockb
Binary file not shown.
|
@ -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",
|
||||||
|
|
|
@ -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>
|
||||||
);
|
);
|
||||||
|
|
22
src/components/forms/LoginFormData.tsx
Normal file
22
src/components/forms/LoginFormData.tsx
Normal 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
10
src/env.d.ts
vendored
|
@ -1 +1,11 @@
|
||||||
/// <reference types="astro/client" />
|
/// <reference types="astro/client" />
|
||||||
|
|
||||||
|
declare namespace App {
|
||||||
|
interface Locals {
|
||||||
|
account?: {
|
||||||
|
id: number;
|
||||||
|
username: string;
|
||||||
|
role_id: number;
|
||||||
|
};
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
25
src/layouts/HomeLayout.astro
Normal file
25
src/layouts/HomeLayout.astro
Normal 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
29
src/middleware.ts
Normal 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));
|
9
src/pages/home/index.astro
Normal file
9
src/pages/home/index.astro
Normal file
|
@ -0,0 +1,9 @@
|
||||||
|
---
|
||||||
|
import HomeLayout from "../../layouts/HomeLayout.astro";
|
||||||
|
|
||||||
|
const account = Astro.locals.account;
|
||||||
|
---
|
||||||
|
|
||||||
|
<HomeLayout title="Trepa">
|
||||||
|
Hello {account?.username}
|
||||||
|
</HomeLayout>
|
|
@ -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>
|
||||||
|
|
|
@ -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>
|
|
Loading…
Reference in a new issue