✨ Page verrouilée
This commit is contained in:
parent
03dfacee1e
commit
581d50d26e
@ -9,6 +9,7 @@ import Image from "next/image";
|
||||
|
||||
export type IProps = IBaseFieldProps & {
|
||||
canCopy?: boolean;
|
||||
password?: boolean;
|
||||
};
|
||||
|
||||
export default class TextField extends BaseField<IProps> {
|
||||
@ -32,6 +33,7 @@ export default class TextField extends BaseField<IProps> {
|
||||
onBlur={this.onBlur}
|
||||
name={this.props.name}
|
||||
disabled={this.props.disabled}
|
||||
type={this.props.password ? "password" : "text"}
|
||||
/>
|
||||
<div className={classes["fake-placeholder"]}>
|
||||
{this.props.placeholder} {!this.props.required && " (Facultatif)"}
|
||||
|
29
src/front/Components/Layouts/Protect/classes.module.scss
Normal file
29
src/front/Components/Layouts/Protect/classes.module.scss
Normal file
@ -0,0 +1,29 @@
|
||||
@import "@Themes/constants.scss";
|
||||
|
||||
.root {
|
||||
display: flex;
|
||||
align-items: center;
|
||||
justify-content: center;
|
||||
flex-direction: column;
|
||||
height: 100%;
|
||||
max-width: 530px;
|
||||
margin: auto;
|
||||
|
||||
.title {
|
||||
margin: 32px 0;
|
||||
text-align: center;
|
||||
|
||||
@media (max-width: $screen-s) {
|
||||
font-family: 48px;
|
||||
}
|
||||
}
|
||||
|
||||
.forget-password {
|
||||
margin-top: 32px;
|
||||
margin-bottom: 8px;
|
||||
}
|
||||
|
||||
.form {
|
||||
display: flex;
|
||||
}
|
||||
}
|
57
src/front/Components/Layouts/Protect/index.tsx
Normal file
57
src/front/Components/Layouts/Protect/index.tsx
Normal file
@ -0,0 +1,57 @@
|
||||
import Module from "@Front/Config/Module";
|
||||
import { useRouter } from "next/router";
|
||||
import { useState } from "react";
|
||||
import Image from "next/image";
|
||||
import classes from "./classes.module.scss";
|
||||
import LandingImage from "./landing-connect.jpeg";
|
||||
import DefaultDoubleSidePage from "@Front/Components/LayoutTemplates/DefaultDoubleSidePage";
|
||||
import Typography, { ITypo } from "@Front/Components/DesignSystem/Typography";
|
||||
import CoffreIcon from "@Assets/Icons/coffre.svg";
|
||||
import TextField from "@Front/Components/DesignSystem/Form/TextField";
|
||||
import Button from "@Front/Components/DesignSystem/Button";
|
||||
|
||||
export default function Protect() {
|
||||
const [password, setPassword] = useState("");
|
||||
const router = useRouter();
|
||||
const setPasswordFromInput = (event: React.ChangeEvent<HTMLInputElement | HTMLSelectElement | HTMLTextAreaElement>) => {
|
||||
setPassword(event.target.value);
|
||||
};
|
||||
|
||||
const submitAuth = (e: React.FormEvent<HTMLFormElement>) => {
|
||||
e.preventDefault();
|
||||
|
||||
if (password === "team-fullstack") {
|
||||
console.log("ok");
|
||||
setCookie("protect_staging", Date.now().toString());
|
||||
router.push(Module.getInstance().get().modules.pages.Login.props.path);
|
||||
} else {
|
||||
console.log("pas ok");
|
||||
}
|
||||
};
|
||||
|
||||
const setCookie = (name: string, value: string) => {
|
||||
if (!name || !value) throw new Error("Cookie name or value is empty");
|
||||
const date = new Date();
|
||||
|
||||
// Set it expire in 7 days
|
||||
date.setTime(date.getTime() + 7 * 24 * 60 * 60 * 1000);
|
||||
|
||||
// Set it
|
||||
document.cookie = name + "=" + value + "; expires=" + date.toUTCString() + "; path=/";
|
||||
};
|
||||
|
||||
return (
|
||||
<DefaultDoubleSidePage title={"Login"} image={LandingImage}>
|
||||
<div className={classes["root"]}>
|
||||
<Image alt="coffre" src={CoffreIcon} />
|
||||
<Typography typo={ITypo.H1}>
|
||||
<div className={classes["title"]}>Le site est verrouillé</div>
|
||||
</Typography>
|
||||
<form onSubmit={submitAuth} className={classes["form"]}>
|
||||
<TextField placeholder="Password" onChange={setPasswordFromInput} password />
|
||||
<Button type="submit">Submit</Button>
|
||||
</form>
|
||||
</div>
|
||||
</DefaultDoubleSidePage>
|
||||
);
|
||||
}
|
BIN
src/front/Components/Layouts/Protect/landing-connect.jpeg
Normal file
BIN
src/front/Components/Layouts/Protect/landing-connect.jpeg
Normal file
Binary file not shown.
After Width: | Height: | Size: 2.5 MiB |
@ -4,11 +4,28 @@ import { NextResponse } from "next/server";
|
||||
import type { NextRequest } from "next/server";
|
||||
|
||||
export async function middleware(request: NextRequest) {
|
||||
const cookieStaging = request.cookies.get("protect_staging");
|
||||
console.log(cookieStaging);
|
||||
if (!cookieStaging) return NextResponse.redirect(new URL("/protect", request.url));
|
||||
|
||||
// Get the JWT from the cookies
|
||||
const cookies = request.cookies.get("leCoffreAccessToken");
|
||||
if (!cookies) return NextResponse.redirect(new URL("/login", request.url));
|
||||
|
||||
// Decode it
|
||||
const userDecodedToken = jwt_decode(cookies.value) as IUserJwtPayload;
|
||||
const customerDecodedToken = jwt_decode(cookies.value) as ICustomerJwtPayload;
|
||||
|
||||
// If no JWT provided, redirect to login page
|
||||
if (!userDecodedToken && !customerDecodedToken) return NextResponse.redirect(new URL("/login", request.url));
|
||||
|
||||
// If JWT expired, redirect to login page
|
||||
const token = userDecodedToken ?? customerDecodedToken;
|
||||
const now = Math.floor(Date.now() / 1000);
|
||||
if (token.exp < now) {
|
||||
return NextResponse.redirect(new URL("/login", request.url));
|
||||
}
|
||||
|
||||
const requestUrlPath = request.nextUrl.pathname;
|
||||
if (
|
||||
requestUrlPath.startsWith("/collaborators") ||
|
||||
@ -21,7 +38,8 @@ export async function middleware(request: NextRequest) {
|
||||
if (userDecodedToken.role !== "admin" && userDecodedToken.role !== "super-admin")
|
||||
return NextResponse.redirect(new URL("/404", request.url));
|
||||
}
|
||||
if ((requestUrlPath.startsWith("/my-account") || requestUrlPath.startsWith("/document-types")) && !userDecodedToken) return NextResponse.redirect(new URL("/404", request.url));
|
||||
if ((requestUrlPath.startsWith("/my-account") || requestUrlPath.startsWith("/document-types")) && !userDecodedToken)
|
||||
return NextResponse.redirect(new URL("/404", request.url));
|
||||
if (requestUrlPath.startsWith("/client-dashboard") && !customerDecodedToken) return NextResponse.redirect(new URL("/404", request.url));
|
||||
|
||||
return NextResponse.next();
|
||||
@ -33,7 +51,7 @@ export const config = {
|
||||
"/collaborators/:path*",
|
||||
"/customer/:path*",
|
||||
"/document-types/:path*",
|
||||
"/deed-types/:path*",
|
||||
"/deed-types/:path*",
|
||||
"/folders/:path*",
|
||||
"/my-account/:path*",
|
||||
"/offices/:path*",
|
||||
|
5
src/pages/protect.tsx
Normal file
5
src/pages/protect.tsx
Normal file
@ -0,0 +1,5 @@
|
||||
import Protect from "@Front/Components/Layouts/Protect";
|
||||
|
||||
export default function Route() {
|
||||
return <Protect />;
|
||||
}
|
Loading…
x
Reference in New Issue
Block a user