updates on the address while creasating the orders and security updates as well

This commit is contained in:
2026-09-11 11:39:34 +05:30
parent 8936669f94
commit c85f57324a
24 changed files with 4409 additions and 170 deletions

View File

@@ -2,29 +2,32 @@ import PropTypes from 'prop-types';
import { useEffect } from 'react';
import { useLocation, useNavigate } from 'react-router-dom';
// project import
import useAuth from 'hooks/useAuth';
import { isSessionValid } from './authState';
// ==============================|| AUTH GUARD ||============================== //
// Blocks a protected route when there is no valid session.
//
// Previously this used useAuth(), which throws unless JWTProvider wraps the
// tree -- and that provider is commented out in App.js. That is why the guard
// was disabled in the route files rather than fixed, leaving every route
// publicly reachable. It now reads the same localStorage session the rest of
// the app uses.
//
// Children are withheld while unauthenticated so a protected page cannot
// paint (and fire its data queries) during the redirect.
const AuthGuard = ({ children }) => {
const { isLoggedIn } = useAuth();
const navigate = useNavigate();
const location = useLocation();
const ok = isSessionValid();
useEffect(() => {
if (!isLoggedIn) {
navigate('login', {
state: {
from: location.pathname
},
replace: true
});
navigate('login', { replace: true });
if (!ok) {
navigate('/login', { state: { from: location.pathname }, replace: true });
}
}, [isLoggedIn, navigate, location]);
}, [ok, navigate, location.pathname]);
return children;
return ok ? children : null;
};
AuthGuard.propTypes = {

View File

@@ -2,28 +2,30 @@ import PropTypes from 'prop-types';
import { useEffect } from 'react';
import { useLocation, useNavigate } from 'react-router-dom';
// project import
import { APP_DEFAULT_PATH } from 'config';
import useAuth from 'hooks/useAuth';
import { isSessionValid } from './authState';
// ==============================|| GUEST GUARD ||============================== //
// Keeps an already-signed-in user off the login page, sending them back to
// wherever AuthGuard bounced them from (or the default landing path).
//
// Reads the same localStorage session as AuthGuard -- see authState.js for why
// this no longer uses useAuth().
const GuestGuard = ({ children }) => {
const { isLoggedIn } = useAuth();
const navigate = useNavigate();
const location = useLocation();
const ok = isSessionValid();
useEffect(() => {
if (isLoggedIn) {
navigate(location?.state?.from ? location?.state?.from : APP_DEFAULT_PATH, {
state: {
from: ''
},
replace: true
});
if (ok) {
navigate(location?.state?.from || APP_DEFAULT_PATH, { state: { from: '' }, replace: true });
}
}, [isLoggedIn, navigate, location]);
}, [ok, navigate, location]);
// Unlike AuthGuard, render children regardless: a signed-in user seeing the
// login form for one frame is harmless, whereas blanking it would leave a
// signed-out user staring at nothing if the redirect ever failed.
return children;
};

View File

@@ -0,0 +1,25 @@
// Single source of truth for "is this session still valid".
//
// The app authenticates via localStorage (login.js writes authname/tenantid/
// applocationid/...), NOT via the JWTContext this template shipped with --
// JWTProvider is commented out in App.js, so useAuth() throws. The guards
// therefore read localStorage directly, using the same 1-hour window App.js
// already enforces on its interval, so both agree on when a session is over.
export const SESSION_MAX_AGE_MS = 60 * 60 * 1000;
export const isSessionValid = () => {
if (typeof window === 'undefined') return false;
try {
if (!localStorage.getItem('authname')) return false;
const started = Number(localStorage.getItem('sessionStartTime'));
// A missing/unparseable start time means a session written before this
// check existed. Treat it as valid rather than logging the user out --
// App.js stamps one on mount.
if (!Number.isFinite(started) || started <= 0) return true;
return Date.now() - started < SESSION_MAX_AGE_MS;
} catch (e) {
// Private mode or blocked storage: fail closed.
return false;
}
};

View File

@@ -0,0 +1,70 @@
/**
* Session-validity tests. This function now gates every protected route, so
* a wrong answer either locks out a legitimate operator or leaves the console
* publicly reachable.
*/
import { isSessionValid, SESSION_MAX_AGE_MS } from './authState';
const setSession = (authname, startedMsAgo) => {
localStorage.clear();
if (authname !== null) localStorage.setItem('authname', authname);
if (startedMsAgo !== undefined) localStorage.setItem('sessionStartTime', String(Date.now() - startedMsAgo));
};
beforeEach(() => localStorage.clear());
describe('isSessionValid', () => {
it('rejects when nothing is stored', () => {
expect(isSessionValid()).toBe(false);
});
it('rejects when authname is absent even if a start time exists', () => {
localStorage.setItem('sessionStartTime', String(Date.now()));
expect(isSessionValid()).toBe(false);
});
it('accepts a fresh session', () => {
setSession('operator', 1000);
expect(isSessionValid()).toBe(true);
});
it('accepts a session just inside the window', () => {
setSession('operator', SESSION_MAX_AGE_MS - 5000);
expect(isSessionValid()).toBe(true);
});
it('rejects a session past the window', () => {
setSession('operator', SESSION_MAX_AGE_MS + 1000);
expect(isSessionValid()).toBe(false);
});
it('rejects exactly at the boundary', () => {
setSession('operator', SESSION_MAX_AGE_MS);
expect(isSessionValid()).toBe(false);
});
it('accepts when the start time is missing, rather than logging the user out', () => {
// A session written before this check existed. App.js stamps one on mount.
localStorage.setItem('authname', 'operator');
expect(isSessionValid()).toBe(true);
});
it.each([['not-a-number'], [''], ['0'], ['-1']])('accepts an unparseable start time (%p)', (value) => {
localStorage.setItem('authname', 'operator');
localStorage.setItem('sessionStartTime', value);
expect(isSessionValid()).toBe(true);
});
it('fails closed when storage throws', () => {
const spy = jest.spyOn(Storage.prototype, 'getItem').mockImplementation(() => {
throw new Error('SecurityError: storage blocked');
});
expect(isSessionValid()).toBe(false);
spy.mockRestore();
});
it('matches the 1-hour window App.js enforces', () => {
expect(SESSION_MAX_AGE_MS).toBe(60 * 60 * 1000);
});
});