mirror of
https://github.com/openclaw/openclaw.git
synced 2026-06-06 05:51:15 +08:00
fix(slack): bound external menu cache clocks
This commit is contained in:
44
extensions/slack/src/monitor/external-arg-menu-store.test.ts
Normal file
44
extensions/slack/src/monitor/external-arg-menu-store.test.ts
Normal file
@@ -0,0 +1,44 @@
|
||||
import { describe, expect, it } from "vitest";
|
||||
import {
|
||||
createSlackExternalArgMenuStore,
|
||||
SLACK_EXTERNAL_ARG_MENU_PREFIX,
|
||||
} from "./external-arg-menu-store.js";
|
||||
|
||||
describe("createSlackExternalArgMenuStore", () => {
|
||||
const choices = [{ label: "Daily", value: "day" }];
|
||||
|
||||
it("returns entries before their expiry", () => {
|
||||
const store = createSlackExternalArgMenuStore();
|
||||
const token = store.create({ choices, userId: "U1" }, 1_700_000_000_000);
|
||||
|
||||
expect(store.get(token, 1_700_000_001_000)).toEqual({
|
||||
choices,
|
||||
userId: "U1",
|
||||
expiresAt: 1_700_000_600_000,
|
||||
});
|
||||
});
|
||||
|
||||
it("drops entries when the current clock is not a valid date timestamp", () => {
|
||||
const store = createSlackExternalArgMenuStore();
|
||||
const token = store.create({ choices, userId: "U1" }, 1_700_000_000_000);
|
||||
|
||||
expect(store.get(token, Number.NaN)).toBeUndefined();
|
||||
expect(store.get(token, 1_700_000_001_000)).toBeUndefined();
|
||||
});
|
||||
|
||||
it("does not retain entries when expiry would exceed the valid date range", () => {
|
||||
const store = createSlackExternalArgMenuStore();
|
||||
const token = store.create({ choices, userId: "U1" }, 8_640_000_000_000_000);
|
||||
|
||||
expect(store.get(token, 1_700_000_001_000)).toBeUndefined();
|
||||
});
|
||||
|
||||
it("reads only prefixed valid menu tokens", () => {
|
||||
const store = createSlackExternalArgMenuStore();
|
||||
const token = store.create({ choices, userId: "U1" }, 1_700_000_000_000);
|
||||
|
||||
expect(store.readToken(`${SLACK_EXTERNAL_ARG_MENU_PREFIX}${token}`)).toBe(token);
|
||||
expect(store.readToken(token)).toBeUndefined();
|
||||
expect(store.readToken(`${SLACK_EXTERNAL_ARG_MENU_PREFIX}not a token`)).toBeUndefined();
|
||||
});
|
||||
});
|
||||
@@ -1,3 +1,7 @@
|
||||
import {
|
||||
asDateTimestampMs,
|
||||
resolveExpiresAtMsFromDurationMs,
|
||||
} from "openclaw/plugin-sdk/number-runtime";
|
||||
import { generateSecureToken } from "openclaw/plugin-sdk/secure-random-runtime";
|
||||
|
||||
const SLACK_EXTERNAL_ARG_MENU_TOKEN_BYTES = 18;
|
||||
@@ -20,10 +24,15 @@ type SlackExternalArgMenuEntry = {
|
||||
|
||||
function pruneSlackExternalArgMenuStore(
|
||||
store: Map<string, SlackExternalArgMenuEntry>,
|
||||
now: number,
|
||||
rawNow: number,
|
||||
): void {
|
||||
const now = asDateTimestampMs(rawNow);
|
||||
if (now === undefined) {
|
||||
store.clear();
|
||||
return;
|
||||
}
|
||||
for (const [token, entry] of store.entries()) {
|
||||
if (entry.expiresAt <= now) {
|
||||
if (asDateTimestampMs(entry.expiresAt) === undefined || entry.expiresAt <= now) {
|
||||
store.delete(token);
|
||||
}
|
||||
}
|
||||
@@ -47,11 +56,16 @@ export function createSlackExternalArgMenuStore() {
|
||||
): string {
|
||||
pruneSlackExternalArgMenuStore(store, now);
|
||||
const token = createSlackExternalArgMenuToken(store);
|
||||
store.set(token, {
|
||||
choices: params.choices,
|
||||
userId: params.userId,
|
||||
expiresAt: now + SLACK_EXTERNAL_ARG_MENU_TTL_MS,
|
||||
const expiresAt = resolveExpiresAtMsFromDurationMs(SLACK_EXTERNAL_ARG_MENU_TTL_MS, {
|
||||
nowMs: now,
|
||||
});
|
||||
if (expiresAt !== undefined) {
|
||||
store.set(token, {
|
||||
choices: params.choices,
|
||||
userId: params.userId,
|
||||
expiresAt,
|
||||
});
|
||||
}
|
||||
return token;
|
||||
},
|
||||
readToken(raw: unknown): string | undefined {
|
||||
|
||||
Reference in New Issue
Block a user