94 lines
2.7 KiB
Go
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)
|
|
}
|
|
}
|
|
}
|