Web UI: administrators make tokens for other users

New token on a user's row under Users, with the Account page's dialog
(now tokenDialog in users.js), offering only roles within that user's
permissions.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
This commit is contained in:
abrown38andClaude Opus 5.5 committed 2026-10-22 23:49:12 +01:00
1 parent 9ce4190e01
commit 0e958289de
5 files changed
+79 -36

No files matched your search

+27
View File
@@ -1335,3 +1335,30 @@ func TestCreatePlaced(t *testing.T) {
t.Errorf("%d rules", n)
}
}
// TestTokenForUser: an administrator makes a token for another user (the
// web UI's New token on a user's row); that user can't make one for
// someone else.
func TestTokenForUser(t *testing.T) {
e := newEnv(t)
var u api.User
if code := e.call(e.token, "POST", "/users", api.UserInput{Username: ptr("portal"), Grants: &[]string{"sets:write"}}, &u); code != 201 {
t.Fatalf("user: %d", code)
}
var tok api.Token
if code := e.call(e.token, "POST", "/users/"+itoa(u.ID)+"/tokens", api.TokenInput{Name: "portal", ExpiresIn: "30d"}, &tok); code != 201 || tok.Secret == "" || tok.UserID != u.ID {
t.Fatalf("token for portal: %d %+v", code, tok)
}
if code := e.call(tok.Secret, "GET", "/rules", nil, nil); code != 403 {
t.Errorf("the token can do more than its user: %d", code)
}
var users []api.User
e.call(e.token, "GET", "/users", nil, &users)
for _, o := range users {
if o.ID != u.ID {
if code := e.call(tok.Secret, "POST", "/users/"+itoa(o.ID)+"/tokens", api.TokenInput{Name: "x"}, nil); code != 403 {
t.Errorf("a token for another user, made by a non-administrator: %d", code)
}
}
}
}