Commit 253e1a2c23

253e1a2c233388e196f3db55aca93a26605c2ab7

parent: a8ba660761

Verified · cmc ci/build: success ci/test: success

cmc <hello@cleberg.net> · 2026-09-28 08:17 UTC

token: create refuses a zero or negative --ttl

Ref #277

Layout: unified · split

internal/control/token.go +4 −9
@@ -69,21 +69,16 @@ func runTokenCreate(c *Ctx, args []string) int {
6969 if err != nil {
7070 return c.fail(protocol.ExitUsage, "%v", err)
7171 }
72 name, scope, ttl := f.Value("--name"), "read", f.Value("--ttl")
72 name, scope := f.Value("--name"), "read"
7373 if f.Has("--scope") {
7474 scope = f.Value("--scope")
7575 }
7676 if name == "" || (scope != "full" && scope != "read") {
7777 return c.usage()
7878 }
79 var expires *time.Time
80 if ttl != "" {
81 d, err := parseTTL(ttl)
82 if err != nil {
83 return c.failInput(err)
84 }
85 t := time.Now().Add(d)
86 expires = &t
79 expires, code := c.ttlFlag(f)
80 if code >= 0 {
81 return code
8782 }
8883 raw, _, err := store.NewToken()
8984 if err != nil {
internal/control/token_test.go +14
@@ -102,3 +102,17 @@ func TestTokenCreateDefaultsToReadAndRecordsCreator(t *testing.T) {
102102 t.Fatal(`no token named "child"`)
103103 }
104104}
105
106func TestTokenCreateRefusesNonPositiveTTL(t *testing.T) {
107 st, _, uid := newQueueTestRepo(t)
108 for _, ttl := range []string{"0s", "-1h"} {
109 c, _ := pruneCtx(st, t.TempDir(), store.User{ID: uid, Username: "alice"})
110 c.Cfg.Limits.WriteRate = -1
111 if code := Dispatch(c, []string{"token", "create", "--name", "x", "--ttl", ttl}); code != protocol.ExitUsage {
112 t.Errorf("--ttl %s: exit %d", ttl, code)
113 }
114 }
115 if toks, err := st.ListAPITokens(uid); err != nil || len(toks) != 0 {
116 t.Fatalf("tokens: %+v %v", toks, err)
117 }
118}