Fix CLI token set command
This commit is contained in:
@@ -112,6 +112,50 @@ func TestFormatDurationSpelling(t *testing.T) {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// A word the parser does not expect has to be refused, not ignored: the flag
|
||||||
|
// package stops at the first non-flag argument, so a command that accepted one
|
||||||
|
// would silently drop every option after it - including the one naming the
|
||||||
|
// file it writes.
|
||||||
|
func TestParseRefusesStrayArguments(t *testing.T) {
|
||||||
|
newSet := func() (*Set, *string, *bool) {
|
||||||
|
var listen string
|
||||||
|
var flagged bool
|
||||||
|
s := NewSet("test", "UNCENSORED_SEND_TEST_")
|
||||||
|
s.String(&listen, "listen", "l", "default", "ADDR", "listen address")
|
||||||
|
s.Bool(&flagged, "vanity", "", false, "a boolean")
|
||||||
|
return s, &listen, &flagged
|
||||||
|
}
|
||||||
|
|
||||||
|
for _, args := range [][]string{
|
||||||
|
{"--vanity", "false"}, // the value a boolean never takes
|
||||||
|
{"stray"}, // a word on its own
|
||||||
|
{"--vanity", "false", "-l", "here"}, // options after the stray word
|
||||||
|
} {
|
||||||
|
s, listen, _ := newSet()
|
||||||
|
err := s.Parse(args)
|
||||||
|
if err == nil {
|
||||||
|
t.Errorf("Parse(%q) was accepted; listen = %q", args, *listen)
|
||||||
|
continue
|
||||||
|
}
|
||||||
|
if !strings.Contains(err.Error(), "unexpected argument") {
|
||||||
|
t.Errorf("Parse(%q) failed with %v, which does not name the problem", args, err)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// The forms that are actually correct still parse.
|
||||||
|
for _, args := range [][]string{
|
||||||
|
{"--vanity=false"},
|
||||||
|
{"--vanity", "-l", "here"},
|
||||||
|
{"-l", "here"},
|
||||||
|
{},
|
||||||
|
} {
|
||||||
|
s, _, _ := newSet()
|
||||||
|
if err := s.Parse(args); err != nil {
|
||||||
|
t.Errorf("Parse(%q) = %v, want it accepted", args, err)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
// The convention is: one hyphen for a letter, two for a word. It is enforced
|
// The convention is: one hyphen for a letter, two for a word. It is enforced
|
||||||
// here because the stdlib flag package treats both forms as the same.
|
// here because the stdlib flag package treats both forms as the same.
|
||||||
func TestHyphenConvention(t *testing.T) {
|
func TestHyphenConvention(t *testing.T) {
|
||||||
|
|||||||
@@ -42,7 +42,6 @@ func NewSet(name, envPrefix string) *Set {
|
|||||||
return s
|
return s
|
||||||
}
|
}
|
||||||
|
|
||||||
func (s *Set) Args() []string { return s.fs.Args() }
|
|
||||||
func (s *Set) SetOutput(w io.Writer) { s.fs.SetOutput(w) }
|
func (s *Set) SetOutput(w io.Writer) { s.fs.SetOutput(w) }
|
||||||
func (s *Set) register(sp *spec) { s.specs = append(s.specs, sp) }
|
func (s *Set) register(sp *spec) { s.specs = append(s.specs, sp) }
|
||||||
func (s *Set) note(long, short string) {
|
func (s *Set) note(long, short string) {
|
||||||
@@ -208,7 +207,19 @@ func (s *Set) Parse(args []string) error {
|
|||||||
if err := s.checkConvention(args); err != nil {
|
if err := s.checkConvention(args); err != nil {
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
return s.fs.Parse(args)
|
if err := s.fs.Parse(args); err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
// A stray word is never harmless: the flag package stops parsing at the
|
||||||
|
// first non-flag argument, so every option after it is dropped in silence.
|
||||||
|
// Writing a boolean as "--vanity false" is the way this bites - it sets
|
||||||
|
// the flag to true and then discards the --data that says which file to
|
||||||
|
// write, leaving a cheerful message about the opposite of what was meant.
|
||||||
|
if extra := s.fs.Args(); len(extra) > 0 {
|
||||||
|
return fmt.Errorf("unexpected argument %q: an option's value attaches with %q, as in --name=value, and any positional argument comes first",
|
||||||
|
extra[0], "=")
|
||||||
|
}
|
||||||
|
return nil
|
||||||
}
|
}
|
||||||
|
|
||||||
// Changed reports whether an option was given on the command line.
|
// Changed reports whether an option was given on the command line.
|
||||||
|
|||||||
@@ -28,7 +28,14 @@ Usage:
|
|||||||
|
|
||||||
A token grants its own size and lifetime limits. Any limit left unset is
|
A token grants its own size and lifetime limits. Any limit left unset is
|
||||||
inherited from the running server's defaults, so a token with no options
|
inherited from the running server's defaults, so a token with no options
|
||||||
behaves exactly like the anonymous tier but may claim vanity names.
|
behaves exactly like the anonymous tier.
|
||||||
|
|
||||||
|
"set" changes only what you name on the command line; anything you leave out
|
||||||
|
keeps its current value. Give a limit an empty value to go back to inheriting
|
||||||
|
the server's default, and turn a flag off with "=false":
|
||||||
|
|
||||||
|
uncensored-send token set friend --max-size= inherit the default again
|
||||||
|
uncensored-send token set friend --vanity=false revoke custom names
|
||||||
|
|
||||||
Options:
|
Options:
|
||||||
`
|
`
|
||||||
@@ -144,8 +151,8 @@ func (o *tokenOptions) register() *config.Set {
|
|||||||
fs.String(&o.defExpiry, "default-expiry", "", "", "DURATION", "lifetime applied when this token does not ask for one")
|
fs.String(&o.defExpiry, "default-expiry", "", "", "DURATION", "lifetime applied when this token does not ask for one")
|
||||||
fs.String(&o.chosen, "token", "t", "", "VALUE",
|
fs.String(&o.chosen, "token", "t", "", "VALUE",
|
||||||
"use this token instead of a generated one; \"-\" reads it from standard input")
|
"use this token instead of a generated one; \"-\" reads it from standard input")
|
||||||
fs.Bool(&o.vanity, "vanity", "", false, "allow this token to claim custom names")
|
fs.Bool(&o.vanity, "vanity", "", false, "allow this token to claim custom names; --vanity=false revokes it")
|
||||||
fs.Bool(&o.admin, "admin", "", false, "allow this token to delete anyone's files")
|
fs.Bool(&o.admin, "admin", "", false, "allow this token to delete anyone's files; --admin=false revokes it")
|
||||||
return fs
|
return fs
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
Reference in New Issue
Block a user