package server import ( "context" "testing" ) func TestViewColors(t *testing.T) { e := newAPIEnv(t) in := e.do("POST", "/views", e.token, map[string]any{"name": "internal", "match_clients": []string{"10.0.0.0/8"}}, 201)["object"].(map[string]any) ex := e.do("POST", "/views", e.token, map[string]any{"name": "external"}, 201)["object"].(map[string]any) inID, exID := int64(in["id"].(float64)), int64(ex["id"].(float64)) applied := len(e.list("/changesets?status=applied", e.token)) v := e.do("PUT", "/views/internal/color", e.token, map[string]any{"color": "green"}, 200) if v["color"] != "green" || v["name"] != "internal" { t.Errorf("set colour = %v", v) } e.do("PUT", "/views/"+itoa(exID)+"/color", e.token, map[string]any{"color": "purple"}, 200) got := map[string]any{} for _, v := range e.list("/views", e.token) { got[v["name"].(string)] = v["color"] } if got["internal"] != "green" || got["external"] != "purple" { t.Errorf("listed colours = %v", got) } if v := e.do("GET", "/views/internal", e.token, nil, 200); v["color"] != "green" { t.Errorf("get view colour = %v", v["color"]) } // A colour is not configuration: no changeset. if n := len(e.list("/changesets?status=applied", e.token)); n != applied { t.Errorf("colour changes made changesets: %d -> %d", applied, n) } if v := e.do("PATCH", "/views/internal", e.token, map[string]any{"comment": "LAN"}, 200)["object"].(map[string]any); v["color"] != "green" { t.Errorf("colour after update = %v", v["color"]) } if _, status := e.req("PUT", "/views/internal/color", e.token, map[string]any{"color": "#ff0000"}); status != 400 { t.Errorf("bad colour = %d", status) } if _, status := e.req("PUT", "/views/nope/color", e.token, map[string]any{"color": "red"}); status != 404 { t.Errorf("unknown view = %d", status) } // Readers of views can't change colours. e.do("POST", "/users", e.token, map[string]any{"username": "reader", "password": "reader-password-123", "grant_strings": []string{"views:read"}}, 201) var readerID int64 for _, u := range e.list("/users", e.token) { if u["username"] == "reader" { readerID = int64(u["id"].(float64)) } } rt := e.do("POST", "/users/"+itoa(readerID)+"/tokens", e.token, map[string]any{"name": "t"}, 201)["token"].(string) if _, status := e.req("PUT", "/views/internal/color", rt, map[string]any{"color": "red"}); status != 403 { t.Errorf("reader set a colour: %d", status) } // A view created in a draft can be given a colour before it is applied. cs := itoa(int64(e.do("POST", "/changesets", e.token, map[string]any{"description": "dmz"}, 201)["id"].(float64))) e.do("POST", "/views?changeset="+cs, e.token, map[string]any{"name": "dmz"}, 202) if _, status := e.req("PUT", "/views/dmz/color", e.token, map[string]any{"color": "orange"}); status != 404 { t.Errorf("draft view found outside its changeset: %d", status) } e.do("PUT", "/views/dmz/color?changeset="+cs, e.token, map[string]any{"color": "orange"}, 200) e.do("PUT", "/views/internal/color", e.token, map[string]any{"color": "teal"}, 200) e.do("POST", "/changesets/"+cs+"/apply", e.token, nil, 200) if v := e.do("GET", "/views/dmz", e.token, nil, 200); v["color"] != "orange" { t.Errorf("draft view colour after apply = %v", v["color"]) } // "" goes back to the default. if v := e.do("PUT", "/views/internal/color", e.token, map[string]any{"color": ""}, 200); v["color"] != nil { t.Errorf("reset colour = %v", v["color"]) } colors, err := e.st.ViewColors(context.Background()) if err != nil { t.Fatal(err) } if _, ok := colors[inID]; ok { t.Errorf("stored colours after reset = %v", colors) } }