Refactor API calls in product editor and bulk edit components to use apiClient instead of axios. Enhance UploadFlow and MatchColumnsStep to support restoring previously matched columns for better user experience during back navigation. Introduce mapping signature handling in ValidationStep for improved data integrity on navigation. Update types and store management to accommodate new features.
This commit is contained in:
@@ -66,7 +66,16 @@ export function authenticate({ pool, secret = process.env.JWT_SECRET, kioskIps =
|
||||
const kioskIpSet = parseKioskIps(kioskIps);
|
||||
|
||||
return async function authenticateMiddleware(req, res, next) {
|
||||
if (kioskIpSet.size > 0 && kioskIpSet.has(req.ip)) {
|
||||
// Kiosk IP bypass ONLY when no Authorization header was provided. A real
|
||||
// user on the same network (e.g. logged-in staff sharing the office NAT)
|
||||
// must keep their actual identity and permissions — otherwise this bypass
|
||||
// silently downgrades them to the permissionless kiosk user and they get
|
||||
// 403 on every gated route.
|
||||
if (
|
||||
kioskIpSet.size > 0 &&
|
||||
kioskIpSet.has(req.ip) &&
|
||||
!req.headers.authorization
|
||||
) {
|
||||
req.user = {
|
||||
id: 'kiosk',
|
||||
username: 'kiosk',
|
||||
|
||||
@@ -159,6 +159,25 @@ describe('authenticate middleware', () => {
|
||||
expect(req.user.is_kiosk).toBeUndefined();
|
||||
});
|
||||
|
||||
it('does NOT bypass when a Bearer token is present, even from a kiosk IP', async () => {
|
||||
// A real user logged in from the same NAT'd network as the kiosk must
|
||||
// keep their actual identity — otherwise the bypass silently strips
|
||||
// their permissions and they 403 on gated routes.
|
||||
const pool = makeFakePool({ 1: activeUser }, { 1: ['product_import'] });
|
||||
const mw = authenticate({ pool, secret: SECRET, kioskIps: '203.0.113.7' });
|
||||
const req = {
|
||||
headers: { authorization: `Bearer ${validToken}` },
|
||||
ip: '203.0.113.7',
|
||||
};
|
||||
const res = makeRes();
|
||||
const next = vi.fn();
|
||||
await mw(req, res, next);
|
||||
expect(next).toHaveBeenCalledOnce();
|
||||
expect(req.user.id).toBe(1);
|
||||
expect(req.user.is_kiosk).toBeUndefined();
|
||||
expect(req.user.permissions).toEqual(['product_import']);
|
||||
});
|
||||
|
||||
it('does not bypass when KIOSK_IPS is empty, even if req.ip is undefined', async () => {
|
||||
const pool = makeFakePool({ 1: activeUser });
|
||||
const mw = authenticate({ pool, secret: SECRET, kioskIps: '' });
|
||||
|
||||
Reference in New Issue
Block a user