mirror of
https://github.com/openclaw/openclaw.git
synced 2026-05-06 12:50:42 +00:00
fix: guard WhatsApp setup prompt values (#67895) (thanks @lawrence3699)
* fix(whatsapp): guard setup prompt values * fix(whatsapp): preserve allowFrom invalid input details * fix: guard WhatsApp setup prompt values (#67895) (thanks @lawrence3699) --------- Co-authored-by: lawrence3699 <lawrence3699@users.noreply.github.com> Co-authored-by: Ayaan Zaidi <hi@obviy.us>
This commit is contained in:
@@ -8,6 +8,7 @@ Docs: https://docs.openclaw.ai
|
||||
|
||||
- Onboarding/non-interactive: preserve existing gateway auth tokens during re-onboard so active local gateway clients are not disconnected by an implicit token rotation. (#67821) Thanks @BKF-Gitty.
|
||||
- OpenAI Codex/Responses: unify native Responses API capability detection so Codex OAuth requests emit the required `store: false` field on the native Responses path. (#67918) Thanks @obviyus.
|
||||
- WhatsApp/setup: guard personal-phone and allowlist prompt values so setup fails with clear validation errors instead of crashing on undefined prompt text. (#67895) Thanks @lawrence3699.
|
||||
|
||||
## 2026.4.15
|
||||
|
||||
|
||||
@@ -169,6 +169,19 @@ describe("whatsapp setup wizard", () => {
|
||||
expectWhatsAppAllowlistModeSetup(result.cfg);
|
||||
});
|
||||
|
||||
it("throws a user-facing error instead of crashing when allowlist input is undefined", async () => {
|
||||
const harness = createSeparatePhoneHarness({
|
||||
selectValues: ["separate", "allowlist", "list"],
|
||||
});
|
||||
harness.text.mockResolvedValueOnce(undefined as never);
|
||||
|
||||
await expect(
|
||||
runConfigureWithHarness({
|
||||
harness,
|
||||
}),
|
||||
).rejects.toThrow("Invalid WhatsApp allowFrom list");
|
||||
});
|
||||
|
||||
it("enables allowlist self-chat mode for personal-phone setup", async () => {
|
||||
hoisted.pathExists.mockResolvedValue(true);
|
||||
const harness = createWhatsAppPersonalPhoneHarness(createQueuedWizardPrompter);
|
||||
@@ -180,6 +193,18 @@ describe("whatsapp setup wizard", () => {
|
||||
expectWhatsAppPersonalPhoneSetup(result.cfg);
|
||||
});
|
||||
|
||||
it("throws a user-facing error instead of crashing when personal-phone input is undefined", async () => {
|
||||
hoisted.pathExists.mockResolvedValue(true);
|
||||
const harness = createWhatsAppPersonalPhoneHarness(createQueuedWizardPrompter);
|
||||
harness.text.mockResolvedValueOnce(undefined as never);
|
||||
|
||||
await expect(
|
||||
runConfigureWithHarness({
|
||||
harness,
|
||||
}),
|
||||
).rejects.toThrow("Invalid WhatsApp owner number");
|
||||
});
|
||||
|
||||
it("forces wildcard allowFrom for open policy without allowFrom follow-up prompts", async () => {
|
||||
hoisted.pathExists.mockResolvedValue(true);
|
||||
const harness = createSeparatePhoneHarness({
|
||||
|
||||
@@ -23,6 +23,10 @@ type SetupRuntime = Parameters<NonNullable<ChannelSetupWizard["finalize"]>>[0]["
|
||||
type WhatsAppConfig = NonNullable<NonNullable<OpenClawConfig["channels"]>["whatsapp"]>;
|
||||
type WhatsAppAccountConfig = NonNullable<NonNullable<WhatsAppConfig["accounts"]>[string]>;
|
||||
|
||||
function trimPromptText(value: string | null | undefined): string {
|
||||
return value?.trim() ?? "";
|
||||
}
|
||||
|
||||
function mergeWhatsAppConfig(
|
||||
cfg: OpenClawConfig,
|
||||
accountId: string,
|
||||
@@ -124,7 +128,7 @@ async function promptWhatsAppOwnerAllowFrom(params: {
|
||||
placeholder: "+15555550123",
|
||||
initialValue: existingAllowFrom[0],
|
||||
validate: (value) => {
|
||||
const raw = value.trim();
|
||||
const raw = trimPromptText(value);
|
||||
if (!raw) {
|
||||
return "Required";
|
||||
}
|
||||
@@ -136,7 +140,7 @@ async function promptWhatsAppOwnerAllowFrom(params: {
|
||||
},
|
||||
});
|
||||
|
||||
const normalized = normalizeE164(entry.trim());
|
||||
const normalized = normalizeE164(trimPromptText(entry));
|
||||
if (!normalized) {
|
||||
throw new Error("Invalid WhatsApp owner number (expected E.164 after validation).");
|
||||
}
|
||||
@@ -311,7 +315,7 @@ async function promptWhatsAppDmAccess(params: {
|
||||
message: "Allowed sender numbers (comma-separated, E.164)",
|
||||
placeholder: "+15555550123, +447700900123",
|
||||
validate: (value) => {
|
||||
const raw = value.trim();
|
||||
const raw = trimPromptText(value);
|
||||
if (!raw) {
|
||||
return "Required";
|
||||
}
|
||||
@@ -326,7 +330,13 @@ async function promptWhatsAppDmAccess(params: {
|
||||
},
|
||||
});
|
||||
|
||||
const parsed = parseWhatsAppAllowFromEntries(allowRaw);
|
||||
const parsed = parseWhatsAppAllowFromEntries(trimPromptText(allowRaw));
|
||||
if (parsed.invalidEntry) {
|
||||
throw new Error(`Invalid number: ${parsed.invalidEntry}`);
|
||||
}
|
||||
if (parsed.entries.length === 0) {
|
||||
throw new Error("Invalid WhatsApp allowFrom list (expected at least one E.164 number).");
|
||||
}
|
||||
return setWhatsAppAllowFrom(next, accountId, parsed.entries);
|
||||
}
|
||||
|
||||
|
||||
Reference in New Issue
Block a user