List and delete accounts with last-admin and Administrators-group guards, and expose editable network settings via the configuration UI.
96 lines
2.7 KiB
Go
96 lines
2.7 KiB
Go
package api
|
|
|
|
import (
|
|
"bytes"
|
|
"encoding/base64"
|
|
"encoding/json"
|
|
"net/http"
|
|
"net/http/httptest"
|
|
"testing"
|
|
|
|
"codeberg.org/SquidSE/ClusterCanvas/service/internal/settings"
|
|
)
|
|
|
|
func TestSetupStatusIncomplete(t *testing.T) {
|
|
t.Parallel()
|
|
configDir := t.TempDir()
|
|
request := httptest.NewRequest(http.MethodGet, "/api/v1/setup/status", nil)
|
|
recorder := httptest.NewRecorder()
|
|
NewRouter(configDir).ServeHTTP(recorder, request)
|
|
if recorder.Code != http.StatusOK {
|
|
t.Fatalf("status %d", recorder.Code)
|
|
}
|
|
var payload setupStatusResponse
|
|
if err := json.NewDecoder(recorder.Body).Decode(&payload); err != nil {
|
|
t.Fatal(err)
|
|
}
|
|
if payload.Completed {
|
|
t.Fatal("expected incomplete")
|
|
}
|
|
}
|
|
|
|
func TestSetupCompleteAndLogin(t *testing.T) {
|
|
configDir := t.TempDir()
|
|
keyBytes := make([]byte, 32)
|
|
for index := range keyBytes {
|
|
keyBytes[index] = byte(index + 3)
|
|
}
|
|
t.Setenv(settings.ConfigKeyEnvVar, base64.StdEncoding.EncodeToString(keyBytes))
|
|
|
|
router := NewRouter(configDir)
|
|
body := map[string]any{
|
|
"username": "Admin",
|
|
"password": "apple banana cherry date elderberry",
|
|
"totp_secret": "",
|
|
"totp_confirmed": false,
|
|
"network": map[string]any{
|
|
"listen_address": "0.0.0.0",
|
|
"public_hostname": "",
|
|
"access_mode": "open",
|
|
"rules": []string{},
|
|
},
|
|
"security": settings.DefaultSecuritySettings(),
|
|
}
|
|
encoded, err := json.Marshal(body)
|
|
if err != nil {
|
|
t.Fatal(err)
|
|
}
|
|
|
|
completeReq := httptest.NewRequest(http.MethodPost, "/api/v1/setup/complete", bytes.NewReader(encoded))
|
|
completeRec := httptest.NewRecorder()
|
|
router.ServeHTTP(completeRec, completeReq)
|
|
if completeRec.Code != http.StatusOK {
|
|
t.Fatalf("complete status %d body %s", completeRec.Code, completeRec.Body.String())
|
|
}
|
|
|
|
loginBody := []byte(`{"username":"Admin","password":"apple banana cherry date elderberry"}`)
|
|
loginReq := httptest.NewRequest(http.MethodPost, "/api/v1/auth/login", bytes.NewReader(loginBody))
|
|
loginRec := httptest.NewRecorder()
|
|
router.ServeHTTP(loginRec, loginReq)
|
|
if loginRec.Code != http.StatusOK {
|
|
t.Fatalf("login status %d body %s", loginRec.Code, loginRec.Body.String())
|
|
}
|
|
|
|
var sessionCookie *http.Cookie
|
|
for _, cookie := range loginRec.Result().Cookies() {
|
|
if cookie.Name == "__Host-ClusterCanvas-Session" {
|
|
sessionCookie = cookie
|
|
break
|
|
}
|
|
}
|
|
if sessionCookie == nil {
|
|
t.Fatal("missing session cookie")
|
|
}
|
|
if !sessionCookie.Secure || !sessionCookie.HttpOnly || sessionCookie.Path != "/" {
|
|
t.Fatalf("cookie flags incorrect: %#v", sessionCookie)
|
|
}
|
|
|
|
meReq := httptest.NewRequest(http.MethodGet, "/api/v1/auth/me", nil)
|
|
meReq.AddCookie(sessionCookie)
|
|
meRec := httptest.NewRecorder()
|
|
router.ServeHTTP(meRec, meReq)
|
|
if meRec.Code != http.StatusOK {
|
|
t.Fatalf("me status %d body %s", meRec.Code, meRec.Body.String())
|
|
}
|
|
}
|