Download src/plugin-sdk/allow-from.test.ts from SaylorTwift/openclaw: direct link, hf CLI and curl.
- Browser
- Download file 7.36 kB
-
https://huggingface.co/SaylorTwift/openclaw/resolve/main/src/plugin-sdk/allow-from.test.ts
- Command line
-
hf download hf://SaylorTwift/openclaw/src/plugin-sdk/allow-from.test.ts
-
curl -L -o allow-from.test.ts https://huggingface.co/SaylorTwift/openclaw/resolve/main/src/plugin-sdk/allow-from.test.ts
7.36 kB
| /** | |
| * Tests allow-from parsing and normalization helpers. | |
| */ | |
| import { describe, expect, it } from "vitest"; | |
| import { | |
| formatAllowFromLowercase, | |
| formatNormalizedAllowFromEntries, | |
| isAllowedParsedChatSender, | |
| isNormalizedSenderAllowed, | |
| mapAllowlistResolutionInputs, | |
| parseAllowFromEntries, | |
| resolveBasicAllowFromEntries, | |
| } from "./allow-from.js"; | |
| function parseAllowTarget( | |
| entry: string, | |
| ): | |
| | { kind: "chat_id"; chatId: number } | |
| | { kind: "chat_guid"; chatGuid: string } | |
| | { kind: "chat_identifier"; chatIdentifier: string } | |
| | { kind: "handle"; handle: string } { | |
| const trimmed = entry.trim(); | |
| const lower = trimmed.toLowerCase(); | |
| if (lower.startsWith("chat_id:")) { | |
| return { kind: "chat_id", chatId: Number.parseInt(trimmed.slice("chat_id:".length), 10) }; | |
| } | |
| if (lower.startsWith("chat_guid:")) { | |
| return { kind: "chat_guid", chatGuid: trimmed.slice("chat_guid:".length) }; | |
| } | |
| if (lower.startsWith("chat_identifier:")) { | |
| return { | |
| kind: "chat_identifier", | |
| chatIdentifier: trimmed.slice("chat_identifier:".length), | |
| }; | |
| } | |
| return { kind: "handle", handle: lower }; | |
| } | |
| describe("isAllowedParsedChatSender", () => { | |
| it.each([ | |
| { | |
| name: "denies when allowFrom is empty", | |
| input: { | |
| allowFrom: [], | |
| sender: "+15551234567", | |
| normalizeSender: (sender: string) => sender, | |
| parseAllowTarget, | |
| }, | |
| expected: false, | |
| }, | |
| { | |
| name: "allows wildcard entries", | |
| input: { | |
| allowFrom: ["*"], | |
| sender: "user@example.com", | |
| normalizeSender: (sender: string) => sender.toLowerCase(), | |
| parseAllowTarget, | |
| }, | |
| expected: true, | |
| }, | |
| { | |
| name: "matches normalized handles", | |
| input: { | |
| allowFrom: ["User@Example.com"], | |
| sender: "user@example.com", | |
| normalizeSender: (sender: string) => sender.toLowerCase(), | |
| parseAllowTarget, | |
| }, | |
| expected: true, | |
| }, | |
| { | |
| name: "does not match conversation targets by default", | |
| input: [ | |
| { | |
| allowFrom: ["chat_id:42"], | |
| sender: "+15551234567", | |
| chatId: 42, | |
| normalizeSender: (sender: string) => sender, | |
| parseAllowTarget, | |
| }, | |
| { | |
| allowFrom: ["chat_guid:thread-42"], | |
| sender: "+15551234567", | |
| chatGuid: "thread-42", | |
| normalizeSender: (sender: string) => sender, | |
| parseAllowTarget, | |
| }, | |
| { | |
| allowFrom: ["chat_identifier:team"], | |
| sender: "+15551234567", | |
| chatIdentifier: "team", | |
| normalizeSender: (sender: string) => sender, | |
| parseAllowTarget, | |
| }, | |
| ], | |
| expected: [false, false, false], | |
| }, | |
| { | |
| name: "matches conversation targets when they are enabled", | |
| input: [ | |
| { | |
| allowFrom: ["chat_id:42"], | |
| sender: "+15551234567", | |
| chatId: 42, | |
| allowConversationTargets: true, | |
| normalizeSender: (sender: string) => sender, | |
| parseAllowTarget, | |
| }, | |
| { | |
| allowFrom: ["chat_guid:thread-42"], | |
| sender: "+15551234567", | |
| chatGuid: "thread-42", | |
| allowConversationTargets: true, | |
| normalizeSender: (sender: string) => sender, | |
| parseAllowTarget, | |
| }, | |
| { | |
| allowFrom: ["chat_identifier:team"], | |
| sender: "+15551234567", | |
| chatIdentifier: "team", | |
| allowConversationTargets: true, | |
| normalizeSender: (sender: string) => sender, | |
| parseAllowTarget, | |
| }, | |
| ], | |
| expected: [true, true, true], | |
| }, | |
| ])("$name", ({ input, expected }) => { | |
| if (Array.isArray(input)) { | |
| expect(input.map((entry) => isAllowedParsedChatSender(entry))).toEqual(expected); | |
| return; | |
| } | |
| expect(isAllowedParsedChatSender(input)).toBe(expected); | |
| }); | |
| }); | |
| describe("isNormalizedSenderAllowed", () => { | |
| it.each([ | |
| { | |
| name: "allows wildcard", | |
| input: { | |
| senderId: "attacker", | |
| allowFrom: ["*"], | |
| }, | |
| expected: true, | |
| }, | |
| { | |
| name: "normalizes case and strips prefixes", | |
| input: { | |
| senderId: "12345", | |
| allowFrom: ["ZALO:12345", "zl:777"], | |
| stripPrefixRe: /^(zalo|zl):/i, | |
| }, | |
| expected: true, | |
| }, | |
| { | |
| name: "rejects when sender is missing", | |
| input: { | |
| senderId: "999", | |
| allowFrom: ["zl:12345"], | |
| stripPrefixRe: /^(zalo|zl):/i, | |
| }, | |
| expected: false, | |
| }, | |
| ])("$name", ({ input, expected }) => { | |
| expect(isNormalizedSenderAllowed(input)).toBe(expected); | |
| }); | |
| }); | |
| describe("formatAllowFromLowercase", () => { | |
| it("trims, strips prefixes, and lowercases entries", () => { | |
| expect( | |
| formatAllowFromLowercase({ | |
| allowFrom: [" Telegram:UserA ", "tg:UserB", " "], | |
| stripPrefixRe: /^(telegram|tg):/i, | |
| }), | |
| ).toEqual(["usera", "userb"]); | |
| }); | |
| }); | |
| describe("formatNormalizedAllowFromEntries", () => { | |
| it.each([ | |
| { | |
| name: "applies custom normalization after trimming", | |
| input: { | |
| allowFrom: [" @Alice ", "", " @Bob "], | |
| normalizeEntry: (entry: string) => entry.replace(/^@/, "").toLowerCase(), | |
| }, | |
| expected: ["alice", "bob"], | |
| }, | |
| { | |
| name: "filters empty normalized entries", | |
| input: { | |
| allowFrom: ["@", "valid"], | |
| normalizeEntry: (entry: string) => entry.replace(/^@$/, ""), | |
| }, | |
| expected: ["valid"], | |
| }, | |
| ])("$name", ({ input, expected }) => { | |
| expect(formatNormalizedAllowFromEntries(input)).toEqual(expected); | |
| }); | |
| }); | |
| describe("parseAllowFromEntries", () => { | |
| it("preserves wildcard entries and returns the first parser error", () => { | |
| const parse = (raw: string) => | |
| parseAllowFromEntries(raw, (entry) => | |
| entry === "bad" ? { error: "invalid" } : { value: entry.toLowerCase() }, | |
| ); | |
| expect(parse(" Alice, *, alice ")).toEqual({ entries: ["alice", "*"] }); | |
| expect(parse("ok; bad; later")).toEqual({ entries: [], error: "invalid" }); | |
| }); | |
| }); | |
| describe("resolveBasicAllowFromEntries", () => { | |
| it("uses unresolved records without a token and canonicalizes resolved ids", async () => { | |
| const resolveEntries = async ({ entries }: { token: string; entries: string[] }) => | |
| entries.map((input) => ({ | |
| input, | |
| resolved: true, | |
| id: input === "missing" ? undefined : "1", | |
| })); | |
| await expect( | |
| resolveBasicAllowFromEntries({ entries: ["alice"], resolveEntries }), | |
| ).resolves.toEqual([{ input: "alice", resolved: false, id: null }]); | |
| await expect( | |
| resolveBasicAllowFromEntries({ | |
| token: " token ", | |
| entries: ["alice", "missing"], | |
| resolveEntries, | |
| }), | |
| ).resolves.toEqual([ | |
| { input: "alice", resolved: true, id: "1" }, | |
| { input: "missing", resolved: true, id: null }, | |
| ]); | |
| }); | |
| }); | |
| describe("mapAllowlistResolutionInputs", () => { | |
| it("maps inputs sequentially and preserves order", async () => { | |
| const visited: string[] = []; | |
| const result = await mapAllowlistResolutionInputs({ | |
| inputs: ["one", "two", "three"], | |
| mapInput: async (input) => { | |
| visited.push(input); | |
| return input.toUpperCase(); | |
| }, | |
| }); | |
| expect(visited).toEqual(["one", "two", "three"]); | |
| expect(result).toEqual(["ONE", "TWO", "THREE"]); | |
| }); | |
| }); | |