fix(cli): clearer whitelist usage errors
`whitelist <in|out> <add|remove|list>` has two positional slots; omitting either let a --flag slide into the slot and produced a misleading "--account is required". Validate the direction and the subcommand up front, before flag parsing, so the real mistake is reported. Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
This commit is contained in:
+12
-3
@@ -330,7 +330,19 @@ func runWhitelist(args []string, role store.Role, out, errOut io.Writer) int {
|
||||
return 2
|
||||
}
|
||||
dir := store.Direction(args[0])
|
||||
if dir != store.DirIn && dir != store.DirOut {
|
||||
fmt.Fprintf(errOut, "whitelist direction must be \"in\" or \"out\", got %q\n", args[0])
|
||||
fmt.Fprintln(errOut, "usage: emcli whitelist <in|out> <add|remove|list> [flags]")
|
||||
return 2
|
||||
}
|
||||
sub, rest := args[1], args[2:]
|
||||
switch sub {
|
||||
case "add", "remove", "list": // valid
|
||||
default:
|
||||
fmt.Fprintf(errOut, "unknown whitelist subcommand %q (want add|remove|list)\n", sub)
|
||||
fmt.Fprintln(errOut, "usage: emcli whitelist <in|out> <add|remove|list> [flags]")
|
||||
return 2
|
||||
}
|
||||
fs := flag.NewFlagSet("whitelist", flag.ContinueOnError)
|
||||
fs.SetOutput(errOut)
|
||||
account := fs.String("account", "", "account name")
|
||||
@@ -371,9 +383,6 @@ func runWhitelist(args []string, role store.Role, out, errOut io.Writer) int {
|
||||
for _, a := range addrs {
|
||||
fmt.Fprintln(out, a)
|
||||
}
|
||||
default:
|
||||
fmt.Fprintf(errOut, "unknown whitelist subcommand %q\n", sub)
|
||||
return 2
|
||||
}
|
||||
return 0
|
||||
}
|
||||
|
||||
@@ -110,6 +110,51 @@ func TestAccountEditPartialPreservesOtherFields(t *testing.T) {
|
||||
}
|
||||
}
|
||||
|
||||
// A missing direction (e.g. `whitelist list`) must report the real problem —
|
||||
// the in|out direction — not the misleading "--account is required".
|
||||
func TestWhitelistMissingDirectionReported(t *testing.T) {
|
||||
adminEnv(t)
|
||||
code, _, errOut := run(t, "whitelist", "list", "--account", "bobby")
|
||||
if code == 0 {
|
||||
t.Fatal("missing direction must be a usage error")
|
||||
}
|
||||
if strings.Contains(errOut, "--account is required") {
|
||||
t.Fatalf("misleading error; want a direction complaint, got: %q", errOut)
|
||||
}
|
||||
if !strings.Contains(errOut, "in") || !strings.Contains(errOut, "out") {
|
||||
t.Fatalf("error should name the in|out direction, got: %q", errOut)
|
||||
}
|
||||
}
|
||||
|
||||
// A missing subcommand (e.g. `whitelist out --account x`) must report the real
|
||||
// problem — the add|remove|list subcommand — not "--account is required".
|
||||
func TestWhitelistMissingSubcommandReported(t *testing.T) {
|
||||
adminEnv(t)
|
||||
code, _, errOut := run(t, "whitelist", "out", "--account", "bobby")
|
||||
if code == 0 {
|
||||
t.Fatal("missing subcommand must be a usage error")
|
||||
}
|
||||
if strings.Contains(errOut, "--account is required") {
|
||||
t.Fatalf("misleading error; want a subcommand complaint, got: %q", errOut)
|
||||
}
|
||||
if !strings.Contains(errOut, "add") || !strings.Contains(errOut, "list") {
|
||||
t.Fatalf("error should name the add|remove|list subcommand, got: %q", errOut)
|
||||
}
|
||||
}
|
||||
|
||||
// The happy path still works after the direction/subcommand validation.
|
||||
func TestWhitelistListWorks(t *testing.T) {
|
||||
adminEnv(t)
|
||||
run(t, "account", "add", "--name", "bobby", "--imap-host", "h", "--username", "u@x.com")
|
||||
if code, _, e := run(t, "whitelist", "out", "add", "--account", "bobby", "--address", "@x.com"); code != 0 {
|
||||
t.Fatalf("add failed: %s", e)
|
||||
}
|
||||
code, out, _ := run(t, "whitelist", "out", "list", "--account", "bobby")
|
||||
if code != 0 || !strings.Contains(out, "@x.com") {
|
||||
t.Fatalf("list: code=%d out=%q", code, out)
|
||||
}
|
||||
}
|
||||
|
||||
func TestAuditListCoreRenders(t *testing.T) {
|
||||
st, err := store.Open(filepath.Join(t.TempDir(), "e.db"))
|
||||
if err != nil {
|
||||
|
||||
Reference in New Issue
Block a user