diff --git a/src/apps/napcat-webui-gateway/infrastructure/session/napcat-webui-gateway-redis.store.ts b/src/apps/napcat-webui-gateway/infrastructure/session/napcat-webui-gateway-redis.store.ts index 9b60601..24d385b 100644 --- a/src/apps/napcat-webui-gateway/infrastructure/session/napcat-webui-gateway-redis.store.ts +++ b/src/apps/napcat-webui-gateway/infrastructure/session/napcat-webui-gateway-redis.store.ts @@ -63,7 +63,7 @@ if terminal[next["status"]] then return {1, nextJson} end -if indexValue and indexValue ~= ARGV[1] then +if indexValue ~= ARGV[1] then return {0, "Gateway session is not active"} end diff --git a/test/apps/napcat-webui-gateway/session-store.spec.ts b/test/apps/napcat-webui-gateway/session-store.spec.ts index 950f6c3..a04f71e 100644 --- a/test/apps/napcat-webui-gateway/session-store.spec.ts +++ b/test/apps/napcat-webui-gateway/session-store.spec.ts @@ -217,7 +217,7 @@ class FakeRedis { return [1, nextSessionJson]; } - if (indexValue && indexValue !== sessionId) { + if (indexValue !== sessionId) { return [0, 'Gateway session is not active']; } @@ -584,6 +584,41 @@ describe('NapcatWebuiGatewayRedisStore', () => { }); }); + it('rejects non-terminal updates when the user-account index is missing', async () => { + const redis = new FakeRedis(); + const config = createConfig({ value: 1000 }); + const store = new NapcatWebuiGatewayRedisStore( + redis as never, + config as never, + ); + const session: NapcatWebuiGatewaySession = { + ...createSessionInput(), + createdAt: 1000, + expiresAt: 61_000, + sessionId: 'session-missing-index', + status: 'created', + }; + const sessionKey = `napcat:webui:session:${session.sessionId}`; + const indexKey = 'napcat:webui:user-account:admin-1:account-1'; + + await store.create(session); + redis.values.delete(indexKey); + redis.ttl.delete(indexKey); + + await expect( + store.update(session.sessionId, { + activeAt: 2000, + expiresAt: 62_000, + lastSeenAt: 2000, + status: 'active', + }), + ).rejects.toThrow('Gateway session is not active'); + expect(redis.values.get(indexKey)).toBeUndefined(); + expect(JSON.parse(redis.values.get(sessionKey) || '{}')).toMatchObject({ + status: 'created', + }); + }); + it('keeps delayed old heartbeat and activation from reviving a replaced session', async () => { const redis = new FakeRedis(); const currentTime = { value: 1000 };