Files

94 lines
2.7 KiB
Go

package api
import (
"encoding/json"
"git.misaka.ren/m1saka/dsh-web/internal/store"
"golang.org/x/crypto/bcrypt"
"net/http"
"net/http/httptest"
"path/filepath"
"strings"
"testing"
)
func TestAuthenticationAndAdmin(t *testing.T) {
s, e := store.Open(filepath.Join(t.TempDir(), "test.sqlite"))
if e != nil {
t.Fatal(e)
}
defer s.Close()
h, _ := bcrypt.GenerateFromPassword([]byte("test-password-123"), bcrypt.MinCost)
if e = s.CreateUser(store.User{ID: "admin", Username: "admin", Admin: true, Quota: 1024}, string(h)); e != nil {
t.Fatal(e)
}
a := New(s, t.TempDir())
a.origin = "http://panel.test"
var access *http.Cookie
request := func(method, path, body, csrf string, cookie *http.Cookie) *httptest.ResponseRecorder {
r := httptest.NewRequest(method, path, strings.NewReader(body))
r.Header.Set("Origin", a.origin)
r.Header.Set("X-CSRF-Token", csrf)
if cookie != nil {
r.AddCookie(cookie)
if access != nil {
r.AddCookie(access)
}
}
w := httptest.NewRecorder()
a.Handler().ServeHTTP(w, r)
return w
}
if w := request("GET", "/api/me", "", "", nil); w.Code != 401 {
t.Fatal(w.Code)
}
w := request("POST", "/api/login", `{"username":"admin","password":"test-password-123"}`, "", nil)
if w.Code != 200 {
t.Fatal(w.Code, w.Body.String())
}
var login struct {
CSRF string `json:"csrf_token"`
}
json.Unmarshal(w.Body.Bytes(), &login)
var cookie *http.Cookie
for _, c := range w.Result().Cookies() {
if c.Name == "dsh_access" {
access = c
}
if c.Name == "dsh_session" {
cookie = c
}
}
if cookie == nil || !cookie.HttpOnly || cookie.Secure {
t.Fatal("wrong local cookie settings")
}
if w = request("GET", "/api/users", "", "", cookie); w.Code != 200 {
t.Fatal(w.Code, w.Body.String())
}
if w = request("POST", "/api/users", `{"username":"member","password":"member-password-123"}`, "", cookie); w.Code != 403 {
t.Fatal("CSRF accepted", w.Code)
}
if w = request("POST", "/api/users", `{"username":"member","password":"member-password-123"}`, login.CSRF, cookie); w.Code != 200 {
t.Fatal(w.Code, w.Body.String())
}
if w = request("POST", "/api/logout", "", login.CSRF, cookie); w.Code != 200 {
t.Fatal(w.Code)
}
if w = request("GET", "/api/me", "", "", cookie); w.Code != 401 {
t.Fatal("session not revoked")
}
}
func TestOriginRequiredWithoutPublicURL(t *testing.T) {
a := &API{}
for _, tc := range []struct {
origin string
want bool
}{{"", false}, {"http://evil.test", false}, {"http://panel.test", true}} {
r := httptest.NewRequest("POST", "http://panel.test/api/login", nil)
r.Header.Set("Origin", tc.origin)
if a.panelOriginAllowed(r) != tc.want {
t.Fatalf("origin %q", tc.origin)
}
}
}