import test from 'node:test' import assert from 'node:assert/strict' import { PDA_AUTHORITY, PDA_ROLE, applyWarehouseProfile, replaceTokens, restoreSession, session, decodeAccessToken, signInWithTokens, signOut, validatePdaToken } from '../src/stores/session.js' import { receiving } from '../src/stores/receiving.js' import { fulfillment, restoreFulfillmentDraft, updateFulfillmentDraft } from '../src/stores/fulfillment.js' const future = () => Math.floor(Date.now() / 1000) + 3600 const jwt = (claims) => [ Buffer.from(JSON.stringify({ alg: 'none', typ: 'JWT' })).toString('base64url'), Buffer.from(JSON.stringify(claims)).toString('base64url'), 'signature' ].join('.') const rawJwt = (json) => [ Buffer.from(JSON.stringify({ alg: 'none', typ: 'JWT' })).toString('base64url'), Buffer.from(json).toString('base64url'), 'signature' ].join('.') function tokenPair(overrides = {}) { const base = { user_id: 42, membership_id: 84, tenant_id: 0, app_code: 'PLATFORM', overseas_warehouse_id: 900, exp: future() } const domestic = { ...base, username: 'picker-42', ...(overrides.domestic || {}) } return { accessToken: jwt(domestic), refreshToken: overrides.refreshToken ?? 'refresh-42', roles: Object.hasOwn(overrides, 'roles') ? overrides.roles : [PDA_ROLE], authorities: Object.hasOwn(overrides, 'authorities') ? overrides.authorities : [PDA_AUTHORITY] } } function storage() { const values = new Map() globalThis.uni = { setStorageSync: (key, value) => values.set(key, JSON.parse(JSON.stringify(value))), getStorageSync: (key) => values.get(key), removeStorageSync: (key) => values.delete(key) } return values } test('valid platform warehouse picker tokens freeze the same operator and warehouse', () => { storage(); signOut() const tokens = tokenPair() const pair = validatePdaToken(tokens.accessToken, tokens) assert.equal(pair.warehouseId, '900') const user = signInWithTokens(tokens) assert.deepEqual(user.roles, [PDA_ROLE]) assert.equal(user.warehouseId, '900') assert.equal(user.warehouse, '') assert.equal(session.tenantId, '0') assert.equal(session.token, tokens.accessToken) assert.deepEqual(session.authorization, { roles: [PDA_ROLE], authorities: [PDA_AUTHORITY] }) assert.equal(decodeAccessToken(tokens.accessToken).roles, undefined) assert.equal(decodeAccessToken(tokens.accessToken).authorities, undefined) }) test('JWT decoding preserves unquoted snowflake subjects and warehouse IDs exactly', () => { const decoded = decodeAccessToken(rawJwt('{"user_id":2091919753535229955,"membership_id":2091919753535229956,"tenant_id":0,"overseas_warehouse_id":2091919753155878914}')) assert.equal(decoded.user_id, '2091919753535229955') assert.equal(decoded.membership_id, '2091919753535229956') assert.equal(decoded.overseas_warehouse_id, '2091919753155878914') }) test('warehouse master profile replaces the technical ID only for the token-bound warehouse', () => { storage(); signOut(); signInWithTokens(tokenPair()) applyWarehouseProfile({ warehouseId: '900', warehouseCode: 'US-LAX-01', warehouseName: '洛杉矶一号仓' }) assert.equal(session.currentUser.warehouse, '洛杉矶一号仓') assert.equal(session.currentUser.warehouseCode, 'US-LAX-01') assert.throws(() => applyWarehouseProfile({ warehouseId: '901', warehouseName: '其他仓' }), /不一致/) }) test('login fails closed for wrong role, authority, warehouse, application, or token subject', () => { storage(); signOut() const invalidPairs = [ tokenPair({ roles: ['PLATFORM_ADMIN'] }), tokenPair({ authorities: [] }), tokenPair({ roles: null }), tokenPair({ authorities: null }), tokenPair({ domestic: { overseas_warehouse_id: null } }), tokenPair({ domestic: { app_code: 'MERCHANT', tenant_id: 100 } }), tokenPair({ domestic: { user_id: null } }), tokenPair({ domestic: { membership_id: null } }), tokenPair({ domestic: { exp: null } }) ] for (const tokens of invalidPairs) { assert.throws(() => signInWithTokens(tokens)) assert.equal(session.currentUser, null) } }) test('refresh replacement validates the unified token before atomically changing session', () => { storage(); signOut() const original = tokenPair() signInWithTokens(original) const before = { access: session.token, refresh: session.refreshToken } const invalid = tokenPair({ authorities: [], refreshToken: 'invalid-refresh' }) assert.throws(() => replaceTokens(invalid), /lastleg:pda:operate/) assert.deepEqual({ access: session.token, refresh: session.refreshToken }, before) const replacement = tokenPair({ refreshToken: 'refresh-43' }) replaceTokens(replacement) assert.equal(session.token, replacement.accessToken) assert.equal(session.refreshToken, 'refresh-43') }) test('refresh cannot carry an old operation into another user, membership, tenant or warehouse', () => { storage(); signOut(); signInWithTokens(tokenPair()) const original = session.token for (const domestic of [{ user_id: 99 }, { membership_id: 85 }, { tenant_id: 1 }, { overseas_warehouse_id: 901 }]) { assert.throws(() => replaceTokens(tokenPair({ domestic })), /主体或绑定仓库已变更|不属于平台仓库作业端/) assert.equal(session.token, original) assert.equal(session.currentUser.warehouseId, '900') } }) test('legacy dual-token storage requires a fresh login', () => { const values = storage(); signOut(); signInWithTokens(tokenPair()) const saved = structuredClone([...values.values()][0]) delete saved.version signOut(); values.set('overseas-pda-auth-session', saved) assert.equal(restoreSession(), false) assert.equal(session.currentUser, null) }) test('restore rebuilds identity from claims and removes expired or tampered storage', () => { const values = storage(); signOut() signInWithTokens(tokenPair()) const saved = structuredClone([...values.values()][0]) signOut(); values.set('overseas-pda-auth-session', saved) assert.equal(restoreSession(), true) assert.equal(session.currentUser.warehouseId, '900') const missingAuthorization = { ...saved } delete missingAuthorization.authorization signOut(); values.set('overseas-pda-auth-session', missingAuthorization) assert.equal(restoreSession(), false) assert.equal(values.has('overseas-pda-auth-session'), false) const tampered = { ...saved, token: tokenPair({ domestic: { overseas_warehouse_id: 901 } }).accessToken } signOut(); values.set('overseas-pda-auth-session', tampered) assert.equal(restoreSession(), false) assert.equal(session.currentUser, null) assert.equal(values.has('overseas-pda-auth-session'), false) const expired = tokenPair({ domestic: { exp: 1 } }) values.set('overseas-pda-auth-session', { ...saved, token: expired.accessToken }) assert.equal(restoreSession(), false) assert.equal(values.has('overseas-pda-auth-session'), false) }) test('sign out clears tokens, frozen warehouse identity, and every receiving or fulfillment draft', () => { const values = storage(); signOut() signInWithTokens(tokenPair()) receiving.candidates = [{ containerNo: 'CONT-1' }] receiving.current = { containerNo: 'CONT-1', status: 'RECEIVING' } receiving.selected = receiving.current receiving.photoSlots = [{ fileId: '1' }, null, null] receiving.resolvedCarton = { cartonMark: 'BOX-1' } receiving.resolvedPallet = { palletCode: 'PALLET-1' } receiving.lastReceipt = { acceptedPackages: 1 } restoreFulfillmentDraft('42:900') updateFulfillmentDraft('dispatch', { currentNo: 'DSP-1', palletCode: 'PLT-1' }) updateFulfillmentDraft('outbound', { currentTaskNo: 'PDA-1', scanCode: 'BOX-1' }) signOut() assert.equal(session.currentUser, null) assert.equal(session.token, '') assert.equal(session.refreshToken, '') assert.deepEqual(session.authorization, { roles: [], authorities: [] }) assert.equal(values.has('overseas-pda-auth-session'), false) assert.deepEqual(receiving.candidates, []) assert.equal(receiving.current, null) assert.equal(receiving.selected, null) assert.deepEqual(receiving.photoSlots, [null, null, null]) assert.equal(receiving.resolvedCarton, null) assert.equal(receiving.resolvedPallet, null) assert.equal(receiving.lastReceipt, null) assert.equal(fulfillment.scopeKey, '') assert.equal(fulfillment.dispatch.currentNo, '') assert.equal(fulfillment.outbound.currentTaskNo, '') assert.equal(values.has('overseas-pda-fulfillment-draft-v1'), false) })