Merge branch 'adding-login' of Controls/CMS-Client into master
This commit is contained in:
@@ -104,7 +104,7 @@ const ForgotPasswordForm = () => {
|
|||||||
|
|
||||||
<Box as="div" textAlign="center" mt="20px">
|
<Box as="div" textAlign="center" mt="20px">
|
||||||
<Link
|
<Link
|
||||||
href="/auth/sign-in/"
|
href="/auth/login/"
|
||||||
className="primaryColor text-decoration-none"
|
className="primaryColor text-decoration-none"
|
||||||
>
|
>
|
||||||
<i className="ri-arrow-left-s-line"></i> Back to Sign in
|
<i className="ri-arrow-left-s-line"></i> Back to Sign in
|
||||||
|
|||||||
@@ -1,6 +1,9 @@
|
|||||||
import React, { useState } from "react";
|
import React, { useState } from "react";
|
||||||
|
import { useRouter } from "next/router";
|
||||||
|
// import { cookies } from "next/headers";
|
||||||
import Link from "next/link";
|
import Link from "next/link";
|
||||||
import Grid from "@mui/material/Grid";
|
import Grid from "@mui/material/Grid";
|
||||||
|
import LoadingButton from "@mui/lab/LoadingButton";
|
||||||
import IconButton from "@mui/material/IconButton";
|
import IconButton from "@mui/material/IconButton";
|
||||||
import { Typography } from "@mui/material";
|
import { Typography } from "@mui/material";
|
||||||
import { Box } from "@mui/system";
|
import { Box } from "@mui/system";
|
||||||
@@ -10,16 +13,77 @@ import Button from "@mui/material/Button";
|
|||||||
import Visibility from "@mui/icons-material/Visibility";
|
import Visibility from "@mui/icons-material/Visibility";
|
||||||
import VisibilityOff from "@mui/icons-material/VisibilityOff";
|
import VisibilityOff from "@mui/icons-material/VisibilityOff";
|
||||||
import styles from "./signinform.module.css";
|
import styles from "./signinform.module.css";
|
||||||
import WrenchBoardLogo from "@/public/images/logos/wrenchboard-logo.png";
|
import Fetcher from "services/Fetcher";
|
||||||
|
|
||||||
const SignInForm = () => {
|
const SignInForm = () => {
|
||||||
const handleSubmit = (event) => {
|
const [formValues, setFormValues] = useState({
|
||||||
|
email: "",
|
||||||
|
password: "",
|
||||||
|
});
|
||||||
|
const [errorHandlers, setErrorHandlers] = useState({
|
||||||
|
email: false,
|
||||||
|
password: false,
|
||||||
|
});
|
||||||
|
const [loading, setLoading] = useState(false);
|
||||||
|
const api = new Fetcher();
|
||||||
|
const router = useRouter();
|
||||||
|
|
||||||
|
const handleChange = (event) => {
|
||||||
|
setFormValues({ ...formValues, [event.target.name]: event.target.value });
|
||||||
|
};
|
||||||
|
|
||||||
|
// "use server"
|
||||||
|
const handleSubmit = async (event) => {
|
||||||
event.preventDefault();
|
event.preventDefault();
|
||||||
const data = new FormData(event.currentTarget);
|
|
||||||
console.log({
|
const { email, password } = formValues;
|
||||||
email: data.get("email"),
|
|
||||||
password: data.get("password"),
|
if (email === "" || password === "") {
|
||||||
});
|
setErrorHandlers({ ...errorHandlers, email: true, password: true });
|
||||||
|
setTimeout(() => {
|
||||||
|
setErrorHandlers({ ...errorHandlers, email: false, password: false });
|
||||||
|
}, 1500);
|
||||||
|
return;
|
||||||
|
} else if (email === "") {
|
||||||
|
setErrorHandlers({ ...errorHandlers, email: true });
|
||||||
|
setTimeout(() => {
|
||||||
|
setErrorHandlers({ ...errorHandlers, email: false });
|
||||||
|
}, 1500);
|
||||||
|
return;
|
||||||
|
} else if (password === "") {
|
||||||
|
setErrorHandlers({ ...errorHandlers, password: true });
|
||||||
|
setTimeout(() => {
|
||||||
|
setErrorHandlers({ ...errorHandlers, password: false });
|
||||||
|
}, 1500);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
setLoading(true);
|
||||||
|
try {
|
||||||
|
const data = {
|
||||||
|
username: email,
|
||||||
|
password,
|
||||||
|
};
|
||||||
|
const res = await api.login(data);
|
||||||
|
|
||||||
|
if (res.status === 204 || res.length === 0) {
|
||||||
|
setErrorHandlers({ ...errorHandlers, email: true, password: true });
|
||||||
|
}
|
||||||
|
|
||||||
|
// Store the token in cookies
|
||||||
|
// const cookieStore = cookies();
|
||||||
|
// cookieStore.set("cmc-profile", { ...res.profile }, { secure: true });
|
||||||
|
// cookieStore.set("cmc-token", res.token, { secure: true });
|
||||||
|
document.cookie = "cmc-token=" + res.token;
|
||||||
|
|
||||||
|
// setLoading(false);
|
||||||
|
router.push("/");
|
||||||
|
|
||||||
|
console.log(res);
|
||||||
|
} catch (error) {
|
||||||
|
setLoading(false);
|
||||||
|
console.log(error);
|
||||||
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
const [showPassword, setShowPassword] = useState(false);
|
const [showPassword, setShowPassword] = useState(false);
|
||||||
@@ -95,13 +159,20 @@ const SignInForm = () => {
|
|||||||
required
|
required
|
||||||
fullWidth
|
fullWidth
|
||||||
id="email"
|
id="email"
|
||||||
label="Email Address"
|
label={
|
||||||
|
errorHandlers.email
|
||||||
|
? "Incomplete/wrong email"
|
||||||
|
: "Email Address"
|
||||||
|
}
|
||||||
|
value={formValues.email}
|
||||||
|
onChange={handleChange}
|
||||||
name="email"
|
name="email"
|
||||||
autoComplete="email"
|
autoComplete="email"
|
||||||
InputProps={{
|
InputProps={{
|
||||||
style: { borderRadius: 8 },
|
style: { borderRadius: 8 },
|
||||||
}}
|
}}
|
||||||
sx={textFieldStyles}
|
sx={textFieldStyles}
|
||||||
|
error={errorHandlers.email}
|
||||||
/>
|
/>
|
||||||
</Grid>
|
</Grid>
|
||||||
|
|
||||||
@@ -122,10 +193,17 @@ const SignInForm = () => {
|
|||||||
required
|
required
|
||||||
fullWidth
|
fullWidth
|
||||||
name="password"
|
name="password"
|
||||||
label="Password"
|
label={
|
||||||
|
errorHandlers.password
|
||||||
|
? "Incomplete/wrong password"
|
||||||
|
: "Password"
|
||||||
|
}
|
||||||
|
value={formValues.password}
|
||||||
type={showPassword ? "text" : "password"}
|
type={showPassword ? "text" : "password"}
|
||||||
id="password"
|
id="password"
|
||||||
autoComplete="new-password"
|
autoComplete="new-password"
|
||||||
|
onChange={handleChange}
|
||||||
|
error={errorHandlers.password}
|
||||||
InputProps={{
|
InputProps={{
|
||||||
style: { borderRadius: 8 },
|
style: { borderRadius: 8 },
|
||||||
endAdornment: (
|
endAdornment: (
|
||||||
@@ -154,26 +232,29 @@ const SignInForm = () => {
|
|||||||
</Grid>
|
</Grid>
|
||||||
</Box>
|
</Box>
|
||||||
|
|
||||||
<Button
|
<Box sx={{ backgroundColor: "#4687BA" }}>
|
||||||
type="submit"
|
<LoadingButton
|
||||||
fullWidth
|
type="submit"
|
||||||
variant="contained"
|
fullWidth
|
||||||
sx={{
|
variant="contained"
|
||||||
mt: 2,
|
loading={loading}
|
||||||
backgroundColor: "#4687BA",
|
disabled={loading}
|
||||||
textTransform: "capitalize",
|
// loadingPosition="end"
|
||||||
borderRadius: "8px",
|
sx={{
|
||||||
fontWeight: "500",
|
textTransform: "capitalize",
|
||||||
fontSize: "16px",
|
borderRadius: "8px",
|
||||||
padding: "12px 10px",
|
fontWeight: "500",
|
||||||
color: "#fff !important",
|
fontSize: "16px",
|
||||||
"&:hover": {
|
padding: "12px 10px",
|
||||||
backgroundColor: "rgba(70, 135, 186, 0.8)"
|
color: "#fff !important",
|
||||||
},
|
"&:hover": {
|
||||||
}}
|
backgroundColor: "rgba(70, 135, 186, 0.8)",
|
||||||
>
|
},
|
||||||
Sign In
|
}}
|
||||||
</Button>
|
>
|
||||||
|
<span>Sign In</span>
|
||||||
|
</LoadingButton>
|
||||||
|
</Box>
|
||||||
</Box>
|
</Box>
|
||||||
</Box>
|
</Box>
|
||||||
</Grid>
|
</Grid>
|
||||||
|
|||||||
@@ -45,7 +45,7 @@ const SignUpForm = () => {
|
|||||||
<Typography fontSize="15px" mb="30px">
|
<Typography fontSize="15px" mb="30px">
|
||||||
Already have an account?{" "}
|
Already have an account?{" "}
|
||||||
<Link
|
<Link
|
||||||
href="/auth/sign-in/"
|
href="/auth/login/"
|
||||||
className="primaryColor text-decoration-none"
|
className="primaryColor text-decoration-none"
|
||||||
>
|
>
|
||||||
Sign in
|
Sign in
|
||||||
|
|||||||
@@ -20,8 +20,9 @@ const Layout = ({ children }) => {
|
|||||||
|
|
||||||
useEffect(() => {
|
useEffect(() => {
|
||||||
const authenticationPages = [
|
const authenticationPages = [
|
||||||
|
// "/",
|
||||||
"/auth",
|
"/auth",
|
||||||
"/auth/sign-in",
|
"/auth/login",
|
||||||
"/auth/sign-up",
|
"/auth/sign-up",
|
||||||
"/auth/forgot-password",
|
"/auth/forgot-password",
|
||||||
"/auth/lock-screen",
|
"/auth/lock-screen",
|
||||||
@@ -36,6 +37,9 @@ const Layout = ({ children }) => {
|
|||||||
console.log("isAuthenticationPage:", isAuthenticationPage, router.pathname);
|
console.log("isAuthenticationPage:", isAuthenticationPage, router.pathname);
|
||||||
|
|
||||||
const title = isAuthenticationPage ? "CMC - auth" : "CMC - dashboard";
|
const title = isAuthenticationPage ? "CMC - auth" : "CMC - dashboard";
|
||||||
|
const mainWrapper = {
|
||||||
|
paddingLeft: typeof window !== "undefined" && isAuthenticationPage && "0"
|
||||||
|
}
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<>
|
<>
|
||||||
@@ -46,9 +50,7 @@ const Layout = ({ children }) => {
|
|||||||
|
|
||||||
<div
|
<div
|
||||||
className={`main-wrapper-content ${active ? "active" : ""}`}
|
className={`main-wrapper-content ${active ? "active" : ""}`}
|
||||||
style={{
|
style={mainWrapper}
|
||||||
paddingLeft: isAuthenticationPage && "0",
|
|
||||||
}}
|
|
||||||
>
|
>
|
||||||
{!isAuthenticationPage && (
|
{!isAuthenticationPage && (
|
||||||
<>
|
<>
|
||||||
|
|||||||
@@ -450,7 +450,7 @@ export const SidebarData = [
|
|||||||
},
|
},
|
||||||
{
|
{
|
||||||
title: "Authentication",
|
title: "Authentication",
|
||||||
path: "/auth/sign-in/",
|
path: "/auth/login/",
|
||||||
icon: <LockIcon />,
|
icon: <LockIcon />,
|
||||||
iconClosed: <KeyboardArrowRightIcon />,
|
iconClosed: <KeyboardArrowRightIcon />,
|
||||||
iconOpened: <KeyboardArrowDownIcon />,
|
iconOpened: <KeyboardArrowDownIcon />,
|
||||||
|
|||||||
@@ -0,0 +1,83 @@
|
|||||||
|
import { NextResponse } from "next/server";
|
||||||
|
import { cookies } from "next/headers";
|
||||||
|
|
||||||
|
const checkAuthentication = async () => {
|
||||||
|
const token = req.cookies["cmc-token"]; // Access the token from cookies
|
||||||
|
console.log("checking token", token);
|
||||||
|
const isAuthenticated = token ? true : false; // Check if the user is authenticated.
|
||||||
|
return isAuthenticated;
|
||||||
|
};
|
||||||
|
|
||||||
|
const isTokenValid = () => {
|
||||||
|
const cookies = document.cookie.split("; "); // Get all cookies and split them into an array
|
||||||
|
|
||||||
|
for (const cookie of cookies) {
|
||||||
|
const [name, value] = cookie.split("="); // Split the cookie into its name and value
|
||||||
|
|
||||||
|
if (name === "cmc-token" && value) {
|
||||||
|
return true; // The cmc-token cookie exists
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return false; // The cmc-token cookie does not exist
|
||||||
|
};
|
||||||
|
|
||||||
|
export async function middleware(req) {
|
||||||
|
const token = isTokenValid()
|
||||||
|
// req.cookies["cmc-token"]; // Access the token from cookies
|
||||||
|
const cookieList = cookies();
|
||||||
|
|
||||||
|
const headers = new Headers(req.headers);
|
||||||
|
headers.set("X-XSS-Protection", "1; mode=block");
|
||||||
|
headers.set("X-Frame-Options", "SAMEORIGIN");
|
||||||
|
headers.set("Content-Security-Policy", "frame-ancestors 'same';");
|
||||||
|
|
||||||
|
const { origin, pathname } = req.nextUrl;
|
||||||
|
|
||||||
|
try {
|
||||||
|
if (pathname === "/auth/login" && token) {
|
||||||
|
// Redirect to the home page if already authenticated
|
||||||
|
return NextResponse.redirect(new URL("/"), { status: 307 });
|
||||||
|
}
|
||||||
|
|
||||||
|
if (!authenticationPages.includes(pathname) && !token) {
|
||||||
|
// Redirect to the login page if not authenticated
|
||||||
|
return NextResponse.redirect(new URL("/auth/login", origin), {
|
||||||
|
status: 307,
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
// Add authentication logic here (verify the token, etc.)
|
||||||
|
// const isAuthenticated = verifyToken(token);
|
||||||
|
const isAuthenticated = cookieList.has("cmc-token");
|
||||||
|
console.log(token)
|
||||||
|
|
||||||
|
if (!isAuthenticated) {
|
||||||
|
// Handle unauthenticated users
|
||||||
|
return NextResponse.error(new Error("Authentication failed"), {
|
||||||
|
status: 401,
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
// Continue with the request if authenticated
|
||||||
|
return NextResponse.next();
|
||||||
|
} catch (error) {
|
||||||
|
console.error("Error during authentication check:", error);
|
||||||
|
return NextResponse.error();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
export const config = {
|
||||||
|
matcher: "/",
|
||||||
|
};
|
||||||
|
|
||||||
|
const authenticationPages = [
|
||||||
|
// "/",
|
||||||
|
"/auth",
|
||||||
|
"/auth/login",
|
||||||
|
"/auth/sign-up",
|
||||||
|
"/auth/forgot-password",
|
||||||
|
"/auth/lock-screen",
|
||||||
|
"/auth/confirm-mail",
|
||||||
|
"/auth/logout",
|
||||||
|
];
|
||||||
+22
-10
@@ -1,24 +1,36 @@
|
|||||||
"use client";
|
"use client"
|
||||||
import { useEffect } from "react";
|
import { useEffect } from "react";
|
||||||
import { useRouter } from "next/router";
|
import { useRouter } from "next/router";
|
||||||
|
|
||||||
/**
|
|
||||||
* This function is used to protect routes in a web application.
|
|
||||||
* It checks if the user is authenticated and redirects them to the sign-in page if they are not.
|
|
||||||
|
|
||||||
*/
|
|
||||||
const AuthRoute = ({ children }) => {
|
const AuthRoute = ({ children }) => {
|
||||||
const router = useRouter();
|
const router = useRouter();
|
||||||
|
|
||||||
|
const token = req.cookies["cmc-token"]; // Access the token from cookies
|
||||||
useEffect(() => {
|
useEffect(() => {
|
||||||
const isAuthenticated = false; // In a real application, this would be determined based on the user's authentication status.
|
|
||||||
|
|
||||||
if (!isAuthenticated) {
|
const isAuthenticated = token ? true : false;
|
||||||
router.push("/auth/sign-in");
|
|
||||||
|
if (router.pathname === "/auth/login" && isAuthenticated) {
|
||||||
|
router.push("/");
|
||||||
}
|
}
|
||||||
}, [router]);
|
|
||||||
|
if (!authenticationPages.includes(router.pathname) && !isAuthenticated) {
|
||||||
|
router.push("/auth/login");
|
||||||
|
}
|
||||||
|
}, []);
|
||||||
|
|
||||||
return <>{children}</>;
|
return <>{children}</>;
|
||||||
};
|
};
|
||||||
|
|
||||||
export default AuthRoute;
|
export default AuthRoute;
|
||||||
|
|
||||||
|
const authenticationPages = [
|
||||||
|
// "/",
|
||||||
|
"/auth",
|
||||||
|
"/auth/login",
|
||||||
|
"/auth/sign-up",
|
||||||
|
"/auth/forgot-password",
|
||||||
|
"/auth/lock-screen",
|
||||||
|
"/auth/confirm-mail",
|
||||||
|
"/auth/logout",
|
||||||
|
];
|
||||||
+1
-1
@@ -14,7 +14,7 @@ const nextConfig = {
|
|||||||
i18n: {
|
i18n: {
|
||||||
locales: ['en', 'ar'],
|
locales: ['en', 'ar'],
|
||||||
defaultLocale: 'en',
|
defaultLocale: 'en',
|
||||||
}
|
},
|
||||||
}
|
}
|
||||||
|
|
||||||
module.exports = nextConfig
|
module.exports = nextConfig
|
||||||
|
|||||||
+2
-1
@@ -41,7 +41,8 @@
|
|||||||
"react-simple-maps": "^3.0.0",
|
"react-simple-maps": "^3.0.0",
|
||||||
"react-tabs": "^6.0.0",
|
"react-tabs": "^6.0.0",
|
||||||
"recharts": "^2.2.0",
|
"recharts": "^2.2.0",
|
||||||
"swiper": "^8.4.5"
|
"swiper": "^8.4.5",
|
||||||
|
"axios": "^0.24.0"
|
||||||
},
|
},
|
||||||
"devDependencies": {
|
"devDependencies": {
|
||||||
"sass": "^1.57.1"
|
"sass": "^1.57.1"
|
||||||
|
|||||||
+2
-2
@@ -23,11 +23,11 @@ function MyApp({ Component, pageProps }) {
|
|||||||
<>
|
<>
|
||||||
<ThemeProvider theme={theme}>
|
<ThemeProvider theme={theme}>
|
||||||
<CssBaseline />
|
<CssBaseline />
|
||||||
<AuthRoute>
|
{/* <AuthRoute> */}
|
||||||
<Layout>
|
<Layout>
|
||||||
<Component {...pageProps} />
|
<Component {...pageProps} />
|
||||||
</Layout>
|
</Layout>
|
||||||
</AuthRoute>
|
{/* </AuthRoute> */}
|
||||||
</ThemeProvider>
|
</ThemeProvider>
|
||||||
</>
|
</>
|
||||||
);
|
);
|
||||||
|
|||||||
@@ -1,3 +1,4 @@
|
|||||||
|
import AuthRoute from "middlewares/AuthRoute";
|
||||||
import Document, { Html, Head, Main, NextScript } from "next/document";
|
import Document, { Html, Head, Main, NextScript } from "next/document";
|
||||||
|
|
||||||
class MyDocument extends Document {
|
class MyDocument extends Document {
|
||||||
|
|||||||
@@ -1,5 +1,5 @@
|
|||||||
import SignInForm from "@/components/Authentication/SignInForm";
|
import SignInForm from "@/components/Authentication/SignInForm";
|
||||||
|
|
||||||
export default function SignIn() {
|
export default function Login() {
|
||||||
return <SignInForm />;
|
return <SignInForm />;
|
||||||
}
|
}
|
||||||
@@ -15,6 +15,7 @@ import RecentOrders from "@/components/Dashboard/eCommerce/RecentOrders";
|
|||||||
import TeamMembersList from "@/components/Dashboard/eCommerce/TeamMembersList";
|
import TeamMembersList from "@/components/Dashboard/eCommerce/TeamMembersList";
|
||||||
import BestSellingProducts from "@/components/Dashboard/eCommerce/BestSellingProducts";
|
import BestSellingProducts from "@/components/Dashboard/eCommerce/BestSellingProducts";
|
||||||
import LiveVisitsOnOurSite from "@/components/Dashboard/eCommerce/LiveVisitsOnOurSite";
|
import LiveVisitsOnOurSite from "@/components/Dashboard/eCommerce/LiveVisitsOnOurSite";
|
||||||
|
import AuthRoute from "middlewares/AuthRoute";
|
||||||
|
|
||||||
function MainPage() {
|
function MainPage() {
|
||||||
return (
|
return (
|
||||||
|
|||||||
@@ -0,0 +1,61 @@
|
|||||||
|
import Axios from "axios";
|
||||||
|
|
||||||
|
class Fetcher {
|
||||||
|
constructor(url) {
|
||||||
|
// this.url = url;
|
||||||
|
console.log("first request!!!");
|
||||||
|
}
|
||||||
|
|
||||||
|
// Endpoints Here
|
||||||
|
// GET /api/
|
||||||
|
|
||||||
|
// POST /api/
|
||||||
|
login(values) {
|
||||||
|
return this.postAuxEnd("/auth/login", values);
|
||||||
|
}
|
||||||
|
|
||||||
|
//---------------------------------------- -----
|
||||||
|
// Unified call below
|
||||||
|
//---------------------------------------- -----
|
||||||
|
|
||||||
|
async getAuxEnd(uri, reqData) {
|
||||||
|
const endPoint =
|
||||||
|
(process.env.AUX_ENDPOINT || "http://localhost:50016/api") + uri;
|
||||||
|
console.log("Checking endpoint get request", endPoint);
|
||||||
|
try {
|
||||||
|
const response = await Axios.get(endPoint);
|
||||||
|
console.log(response.data); // Log the response data if needed.
|
||||||
|
return response.data;
|
||||||
|
} catch (error) {
|
||||||
|
this.handleAxiosError(error);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
async postAuxEnd(uri, reqData) {
|
||||||
|
const endPoint =
|
||||||
|
(process.env.AUX_ENDPOINT || "http://localhost:50016/api") + uri;
|
||||||
|
console.log("Checking endpoint post request", endPoint);
|
||||||
|
try {
|
||||||
|
const response = await Axios.post(endPoint, reqData);
|
||||||
|
console.log(response.data); // Log the response data if needed.
|
||||||
|
return response.data;
|
||||||
|
} catch (error) {
|
||||||
|
this.handleAxiosError(error);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
handleAxiosError(error) {
|
||||||
|
if (error.response) {
|
||||||
|
// Response status is an error code.
|
||||||
|
console.log(error.response.status);
|
||||||
|
} else if (error.request) {
|
||||||
|
// Response not received though the request was sent.
|
||||||
|
console.log(error.request);
|
||||||
|
} else {
|
||||||
|
// An error occurred when setting up the request.
|
||||||
|
console.log(error.message);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
export default Fetcher;
|
||||||
Reference in New Issue
Block a user