package adminapi import ( "net/http" "strings" "testing" "time" "github.com/iceBear67/simplepages/api" ) func TestWhoAmIReportsTheCaller(t *testing.T) { e := newEnv(t) e.createProject(t, "demo") future := time.Now().Add(time.Hour).Truncate(time.Second) proj := e.createKey(t, api.PathProjectKeys("demo"), e.adminToken, api.CreateKeyRequest{Name: "ci", ExpiresAt: &future}) t.Run("project scope", func(t *testing.T) { status, body := e.do(t, http.MethodGet, api.PathWhoAmI(), proj.Token, nil) var who api.WhoAmI mustJSON(t, status, http.StatusOK, body, &who) if who.KeyID != proj.Key.ID { t.Errorf("key_id = %q, want %q", who.KeyID, proj.Key.ID) } if who.Scope != api.ScopeProject || who.Project != "demo" || who.Name != "ci" { t.Errorf("whoami = %+v, want scope project on demo named ci", who) } if who.ExpiresAt == nil || !who.ExpiresAt.Equal(future) { t.Errorf("expires_at = %v, want %v", who.ExpiresAt, future) } }) t.Run("admin scope", func(t *testing.T) { status, body := e.do(t, http.MethodGet, api.PathWhoAmI(), e.adminToken, nil) var who api.WhoAmI mustJSON(t, status, http.StatusOK, body, &who) if who.Scope != api.ScopeAdmin { t.Errorf("scope = %q, want admin", who.Scope) } // An admin key belongs to no project, and saying otherwise would suggest // the caller is confined to one. if who.Project != "" { t.Errorf("project = %q, want empty for an admin key", who.Project) } }) // whoami names a credential, so it must not be cached by anything between // the CLI and the server. t.Run("no-store", func(t *testing.T) { resp := e.doResp(t, http.MethodGet, api.PathWhoAmI(), proj.Token, nil) if cc := resp.Header.Get("Cache-Control"); !strings.Contains(cc, "no-store") { t.Errorf("Cache-Control = %q, want it to contain no-store", cc) } }) } func TestSystemInfo(t *testing.T) { e := newEnv(t) e.createProject(t, "a") e.createProject(t, "b") status, body := e.do(t, http.MethodGet, api.PathSystemInfo(), e.adminToken, nil) var info api.SystemInfo mustJSON(t, status, http.StatusOK, body, &info) if info.Projects != 2 { t.Errorf("projects = %d, want 2", info.Projects) } if info.Deployments != 0 || info.Blobs != 0 || info.CASBytes != 0 { t.Errorf("expected an empty CAS, got %+v", info) } if info.SchemaVer < 1 { t.Errorf("schema_version = %d, want at least 1", info.SchemaVer) } if info.Version == "" { t.Error("version is empty") } // The link mode is not known until the CAS is opened in M2; reporting an // empty string would read as "no linking" rather than "not determined". if info.LinkMode != "unknown" { t.Errorf("link_mode = %q, want unknown", info.LinkMode) } if info.UptimeS < 0 { t.Errorf("uptime_s = %d", info.UptimeS) } } func TestSystemInfoIsAdminOnly(t *testing.T) { e := newEnv(t) e.createProject(t, "demo") token := e.mintProject(t, e.projectID(t, "demo"), "ci") status, body := e.do(t, http.MethodGet, api.PathSystemInfo(), token, nil) if status != http.StatusForbidden { t.Fatalf("status = %d, want 403; body: %s", status, body) } if got := errCode(t, body); got != api.CodeForbidden { t.Errorf("code = %q, want %q", got, api.CodeForbidden) } }