Merge branch 'adding-login' of Controls/CMS-Client into master

This commit is contained in:
2023-10-21 10:32:27 +00:00
committed by Gogs
15 changed files with 296 additions and 53 deletions
+1
View File
@@ -0,0 +1 @@
AUX_ENDPOINT="http://localhost:50016/api"
@@ -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
+110 -29
View File
@@ -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>
+1 -1
View File
@@ -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
+6 -4
View File
@@ -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 && (
<> <>
+1 -1
View File
@@ -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 />,
+83
View File
@@ -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
View File
@@ -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
View File
@@ -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
View File
@@ -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
View File
@@ -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
View File
@@ -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 />;
} }
+1
View File
@@ -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 (
+61
View File
@@ -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;