http: POST /api/users — create + setup-token + audit
This commit is contained in:
@@ -1,9 +1,11 @@
|
||||
package http
|
||||
|
||||
import (
|
||||
"bytes"
|
||||
"encoding/json"
|
||||
"io"
|
||||
stdhttp "net/http"
|
||||
"strings"
|
||||
"testing"
|
||||
|
||||
"gitea.dcglab.co.uk/steve/restic-manager/internal/store"
|
||||
@@ -33,3 +35,72 @@ func TestAPIUsersList(t *testing.T) {
|
||||
t.Errorf("count: got %d want 2", len(got.Users))
|
||||
}
|
||||
}
|
||||
|
||||
func TestAPIUserCreate(t *testing.T) {
|
||||
t.Parallel()
|
||||
srv, ts, _ := rawTestServerWithUI(t)
|
||||
adminID := makeUser(t, srv, "admin1", store.RoleAdmin)
|
||||
cookie := loginAs(t, srv, adminID)
|
||||
|
||||
body, _ := json.Marshal(map[string]any{
|
||||
"username": "Bob", "email": "bob@example.com", "role": "operator",
|
||||
})
|
||||
req, _ := stdhttp.NewRequest("POST", ts.URL+"/api/users", bytes.NewReader(body))
|
||||
req.AddCookie(cookie)
|
||||
req.Header.Set("Content-Type", "application/json")
|
||||
res, err := stdhttp.DefaultClient.Do(req)
|
||||
if err != nil {
|
||||
t.Fatalf("POST: %v", err)
|
||||
}
|
||||
defer res.Body.Close()
|
||||
if res.StatusCode != stdhttp.StatusCreated {
|
||||
body, _ := io.ReadAll(res.Body)
|
||||
t.Fatalf("status: got %d body=%s", res.StatusCode, body)
|
||||
}
|
||||
var got struct {
|
||||
ID string `json:"id"`
|
||||
SetupURL string `json:"setup_url"`
|
||||
}
|
||||
_ = json.NewDecoder(res.Body).Decode(&got)
|
||||
if got.ID == "" || got.SetupURL == "" {
|
||||
t.Errorf("missing fields: %+v", got)
|
||||
}
|
||||
if !strings.Contains(got.SetupURL, "/setup?token=") {
|
||||
t.Errorf("setup_url shape: %q", got.SetupURL)
|
||||
}
|
||||
|
||||
// Verify lowercase-normalised.
|
||||
u, err := srv.deps.Store.GetUserByUsername(t.Context(), "bob")
|
||||
if err != nil {
|
||||
t.Fatalf("get: %v", err)
|
||||
}
|
||||
if u.Username != "bob" {
|
||||
t.Errorf("username: got %q want bob", u.Username)
|
||||
}
|
||||
if !u.MustChangePassword {
|
||||
t.Error("must_change_password not set")
|
||||
}
|
||||
}
|
||||
|
||||
func TestAPIUserCreateRejectsDuplicateEnabled(t *testing.T) {
|
||||
t.Parallel()
|
||||
srv, ts, _ := rawTestServerWithUI(t)
|
||||
adminID := makeUser(t, srv, "admin1", store.RoleAdmin)
|
||||
makeUser(t, srv, "alice", store.RoleOperator)
|
||||
cookie := loginAs(t, srv, adminID)
|
||||
|
||||
body, _ := json.Marshal(map[string]any{
|
||||
"username": "ALICE", "role": "operator",
|
||||
})
|
||||
req, _ := stdhttp.NewRequest("POST", ts.URL+"/api/users", bytes.NewReader(body))
|
||||
req.AddCookie(cookie)
|
||||
req.Header.Set("Content-Type", "application/json")
|
||||
res, err := stdhttp.DefaultClient.Do(req)
|
||||
if err != nil {
|
||||
t.Fatalf("POST: %v", err)
|
||||
}
|
||||
defer res.Body.Close()
|
||||
if res.StatusCode != stdhttp.StatusConflict {
|
||||
t.Errorf("status: got %d want 409", res.StatusCode)
|
||||
}
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user