Signal: validate account input

This commit is contained in:
Vignesh Natarajan
2026-02-12 15:11:49 -08:00
parent 61d57be4c2
commit 0969eaf038
2 changed files with 64 additions and 8 deletions

View File

@@ -0,0 +1,27 @@
import { describe, expect, it } from "vitest";
import { normalizeSignalAccountInput } from "./signal.js";
describe("normalizeSignalAccountInput", () => {
it("accepts already normalized numbers", () => {
expect(normalizeSignalAccountInput("+15555550123")).toBe("+15555550123");
});
it("normalizes formatted input", () => {
expect(normalizeSignalAccountInput(" +1 (555) 000-1234 ")).toBe("+15550001234");
});
it("rejects empty input", () => {
expect(normalizeSignalAccountInput(" ")).toBeNull();
});
it("rejects non-numeric input", () => {
expect(normalizeSignalAccountInput("ok")).toBeNull();
expect(normalizeSignalAccountInput("++--")).toBeNull();
});
it("rejects numbers that are too short or too long", () => {
expect(normalizeSignalAccountInput("+1234")).toBeNull();
expect(normalizeSignalAccountInput("+1234567890123456")).toBeNull();
});
});

View File

@@ -16,6 +16,23 @@ import { normalizeE164 } from "../../../utils.js";
import { addWildcardAllowFrom, promptAccountId } from "./helpers.js";
const channel = "signal" as const;
const MIN_E164_DIGITS = 5;
const MAX_E164_DIGITS = 15;
const INVALID_SIGNAL_ACCOUNT_ERROR =
"Invalid E.164 phone number (must start with + and country code, e.g. +15555550123)";
export function normalizeSignalAccountInput(value: string | null | undefined): string | null {
const trimmed = value?.trim();
if (!trimmed) {
return null;
}
const normalized = normalizeE164(trimmed);
const digits = normalized.slice(1);
if (digits.length < MIN_E164_DIGITS || digits.length > MAX_E164_DIGITS) {
return null;
}
return normalized;
}
function setSignalDmPolicy(cfg: OpenClawConfig, dmPolicy: DmPolicy) {
const allowFrom =
@@ -243,22 +260,34 @@ export const signalOnboardingAdapter: ChannelOnboardingAdapter = {
let account = accountConfig.account ?? "";
if (account) {
const keep = await prompter.confirm({
message: `Signal account set (${account}). Keep it?`,
initialValue: true,
});
if (!keep) {
const normalizedExisting = normalizeSignalAccountInput(account);
if (!normalizedExisting) {
await prompter.note(
"Existing Signal account isn't a valid E.164 number. Please enter it again.",
"Signal",
);
account = "";
} else {
account = normalizedExisting;
const keep = await prompter.confirm({
message: `Signal account set (${account}). Keep it?`,
initialValue: true,
});
if (!keep) account = "";
}
}
if (!account) {
account = String(
const rawAccount = String(
await prompter.text({
message: "Signal bot number (E.164)",
validate: (value) => (value?.trim() ? undefined : "Required"),
validate: (value) =>
normalizeSignalAccountInput(String(value ?? ""))
? undefined
: INVALID_SIGNAL_ACCOUNT_ERROR,
}),
).trim();
);
account = normalizeSignalAccountInput(rawAccount) ?? "";
}
if (account) {