no submod
This commit is contained in:
361
work/notea/server/authenticate_test.go
Normal file
361
work/notea/server/authenticate_test.go
Normal file
@@ -0,0 +1,361 @@
|
||||
package main
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
"net/http"
|
||||
"net/http/httptest"
|
||||
"path"
|
||||
"testing"
|
||||
"time"
|
||||
|
||||
"github.com/google/uuid"
|
||||
)
|
||||
|
||||
func TestEncodeDecodeCookie(t *testing.T) {
|
||||
newTestServer(t)
|
||||
|
||||
for i := 0; i < 5; i++ {
|
||||
value := uuid.New().String()
|
||||
encoded := encodeCookie(value)
|
||||
for j := 0; j < 5; j++ {
|
||||
decoded, ok := decodeCookie(encoded)
|
||||
if !ok || decoded != value {
|
||||
t.Errorf("value=%s, encoded=%s, decoded=%s", value, encoded, decoded)
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
func TestEncodeDecodeUserCookie(t *testing.T) {
|
||||
newTestServer(t)
|
||||
|
||||
user := User{
|
||||
User: "abc",
|
||||
Groups: []string{"def", "ghi"},
|
||||
}
|
||||
encoded := encodeUserCookie(user)
|
||||
decoded, ok := decodeUserCookie(encoded)
|
||||
if !ok {
|
||||
t.Fatal(ok)
|
||||
}
|
||||
if fmt.Sprint(user) != fmt.Sprint(decoded) {
|
||||
t.Fatal(user, decoded)
|
||||
}
|
||||
}
|
||||
|
||||
func TestGetCookie(t *testing.T) {
|
||||
r := httptest.NewRequest(http.MethodGet, "/", nil)
|
||||
r.AddCookie(&http.Cookie{
|
||||
Name: "abc",
|
||||
Value: "def",
|
||||
Expires: time.Now().Add(time.Hour),
|
||||
})
|
||||
got, _ := getCookie("abc", r)
|
||||
if got != "def" {
|
||||
t.Fatal(r.Cookies(), got)
|
||||
}
|
||||
}
|
||||
|
||||
func TestGetSetLoginCookie(t *testing.T) {
|
||||
w := httptest.NewRecorder()
|
||||
r := httptest.NewRequest(http.MethodGet, "/", nil)
|
||||
user := User{User: "a", Groups: []string{"g"}}
|
||||
|
||||
setLoginCookie(w, r, user)
|
||||
if w.Header().Get("Set-Cookie") == "" {
|
||||
t.Error(w.Header())
|
||||
}
|
||||
|
||||
got, ok := loginCookie(r)
|
||||
if !ok {
|
||||
t.Error(ok)
|
||||
}
|
||||
if fmt.Sprint(user) != fmt.Sprint(got) {
|
||||
t.Error(user, got)
|
||||
}
|
||||
}
|
||||
|
||||
func TestChangeNamespace(t *testing.T) {
|
||||
newTestServer(t)
|
||||
user := User{
|
||||
User: "user",
|
||||
Groups: []string{"group", "othergroup"},
|
||||
Group: "group",
|
||||
}
|
||||
|
||||
t.Run("noop", func(t *testing.T) {
|
||||
r := httptest.NewRequest(http.MethodGet, "/", nil)
|
||||
w := httptest.NewRecorder()
|
||||
done, err := changeNamespace(w, r)
|
||||
if err != nil {
|
||||
t.Error(err)
|
||||
}
|
||||
if done {
|
||||
t.Error(done)
|
||||
}
|
||||
})
|
||||
|
||||
t.Run("change to ``", func(t *testing.T) {
|
||||
r := httptest.NewRequest(http.MethodGet, "/?namespace=", nil)
|
||||
w := httptest.NewRecorder()
|
||||
done, err := changeNamespace(w, r)
|
||||
if err != nil {
|
||||
t.Error(err)
|
||||
}
|
||||
if done {
|
||||
t.Error(done)
|
||||
}
|
||||
})
|
||||
|
||||
t.Run("change to bad", func(t *testing.T) {
|
||||
r := httptest.NewRequest(http.MethodGet, "/?namespace=never", nil)
|
||||
w := httptest.NewRecorder()
|
||||
setLoginCookie(w, r, user)
|
||||
done, err := changeNamespace(w, r)
|
||||
if err != nil {
|
||||
t.Error(err)
|
||||
}
|
||||
if done {
|
||||
t.Error(done)
|
||||
}
|
||||
user, ok := loginCookie(r)
|
||||
if !ok {
|
||||
t.Error(ok)
|
||||
}
|
||||
if user.Group == "never" {
|
||||
t.Error("change namespace acknowledged bad change")
|
||||
}
|
||||
})
|
||||
|
||||
t.Run("change without login", func(t *testing.T) {
|
||||
r := httptest.NewRequest(http.MethodGet, "/?namespace="+user.Group, nil)
|
||||
w := httptest.NewRecorder()
|
||||
done, err := changeNamespace(w, r)
|
||||
if err != nil {
|
||||
t.Error(err)
|
||||
}
|
||||
if !done {
|
||||
t.Error(done)
|
||||
}
|
||||
})
|
||||
|
||||
t.Run("change to same", func(t *testing.T) {
|
||||
r := httptest.NewRequest(http.MethodGet, "/?namespace="+user.Group, nil)
|
||||
w := httptest.NewRecorder()
|
||||
setLoginCookie(w, r, user)
|
||||
done, err := changeNamespace(w, r)
|
||||
if err != nil {
|
||||
t.Error(err)
|
||||
}
|
||||
if done {
|
||||
t.Error(done)
|
||||
}
|
||||
})
|
||||
|
||||
t.Run("change to ok", func(t *testing.T) {
|
||||
r := httptest.NewRequest(http.MethodGet, "/?namespace="+user.Groups[1], nil)
|
||||
w := httptest.NewRecorder()
|
||||
setLoginCookie(w, r, user)
|
||||
done, err := changeNamespace(w, r)
|
||||
if err != nil {
|
||||
t.Error(err)
|
||||
}
|
||||
if done {
|
||||
t.Error(done)
|
||||
}
|
||||
user, ok := loginCookie(r)
|
||||
if !ok {
|
||||
t.Error(ok)
|
||||
}
|
||||
if user.Group != user.Groups[1] {
|
||||
t.Error(user.Group)
|
||||
}
|
||||
if w.Header().Get("Set-Cookie") == "" {
|
||||
t.Error(w.Header())
|
||||
}
|
||||
})
|
||||
}
|
||||
|
||||
func TestNeedsLogin(t *testing.T) {
|
||||
w := httptest.NewRecorder()
|
||||
user := User{User: "user", Groups: []string{"group0", "group1"}, Group: "group0"}
|
||||
|
||||
t.Run("no login provided", func(t *testing.T) {
|
||||
r := httptest.NewRequest(http.MethodGet, "/", nil)
|
||||
if ok, err := needsLogin(r); err != nil {
|
||||
t.Fatal(err)
|
||||
} else if !ok {
|
||||
t.Fatal(ok)
|
||||
}
|
||||
})
|
||||
|
||||
t.Run("no namespace provided", func(t *testing.T) {
|
||||
r := httptest.NewRequest(http.MethodGet, "/", nil)
|
||||
u2 := user
|
||||
u2.Group = ""
|
||||
setLoginCookie(w, r, u2)
|
||||
if ok, err := needsLogin(r); err != nil {
|
||||
t.Fatal(err)
|
||||
} else if !ok {
|
||||
t.Fatal(ok)
|
||||
}
|
||||
})
|
||||
|
||||
t.Run("cookie tampered", func(t *testing.T) {
|
||||
r := httptest.NewRequest(http.MethodGet, "/", nil)
|
||||
setLoginCookie(w, r, user)
|
||||
cookieSecret += "modified"
|
||||
if ok, err := needsLogin(r); err != nil {
|
||||
t.Fatal(err)
|
||||
} else if !ok {
|
||||
t.Fatal(ok)
|
||||
}
|
||||
})
|
||||
|
||||
t.Run("bad namespace", func(t *testing.T) {
|
||||
r := httptest.NewRequest(http.MethodGet, "/", nil)
|
||||
u2 := user
|
||||
u2.Group = "teehee"
|
||||
setLoginCookie(w, r, u2)
|
||||
if ok, err := needsLogin(r); err != nil {
|
||||
t.Fatal(err)
|
||||
} else if !ok {
|
||||
t.Fatal(ok)
|
||||
}
|
||||
})
|
||||
|
||||
t.Run("ok", func(t *testing.T) {
|
||||
r := httptest.NewRequest(http.MethodGet, "/", nil)
|
||||
setLoginCookie(w, r, user)
|
||||
if ok, err := needsLogin(r); err != nil {
|
||||
t.Fatal(err)
|
||||
} else if ok {
|
||||
t.Fatal(ok)
|
||||
}
|
||||
})
|
||||
}
|
||||
|
||||
func TestServerParseLogin(t *testing.T) {
|
||||
server := newTestServer(t)
|
||||
|
||||
t.Run("no basic auth", func(t *testing.T) {
|
||||
w := httptest.NewRecorder()
|
||||
r := httptest.NewRequest(http.MethodGet, "/", nil)
|
||||
if done, err := server.parseLogin(w, r); done || err != nil {
|
||||
t.Fatal(done, err)
|
||||
}
|
||||
if w.Code == http.StatusUnauthorized {
|
||||
t.Error(w.Code)
|
||||
}
|
||||
})
|
||||
|
||||
t.Run("bad basic auth", func(t *testing.T) {
|
||||
w := httptest.NewRecorder()
|
||||
r := httptest.NewRequest(http.MethodGet, "/", nil)
|
||||
r.SetBasicAuth("junk", "junk")
|
||||
if done, err := server.parseLogin(w, r); !done || err != nil {
|
||||
t.Fatal(done, err)
|
||||
}
|
||||
if w.Code != http.StatusUnauthorized {
|
||||
t.Error(w.Code)
|
||||
}
|
||||
})
|
||||
|
||||
t.Run("ok", func(t *testing.T) {
|
||||
w := httptest.NewRecorder()
|
||||
r := httptest.NewRequest(http.MethodGet, "/", nil)
|
||||
r.SetBasicAuth("user", "passw")
|
||||
if done, err := server.parseLogin(w, r); done || err != nil {
|
||||
t.Fatal(done, err)
|
||||
}
|
||||
if w.Code == http.StatusUnauthorized {
|
||||
t.Error(w.Code)
|
||||
}
|
||||
if len(w.Header()["Set-Cookie"]) != 1 {
|
||||
t.Error(w.Header())
|
||||
}
|
||||
if user, ok := loginCookie(r); !ok || user.User != "user" || user.Groups[0] != "group" || user.Groups[1] != "othergroup" {
|
||||
t.Error(user)
|
||||
}
|
||||
})
|
||||
}
|
||||
|
||||
func TestServerAuthenticate(t *testing.T) {
|
||||
server := newTestServer(t)
|
||||
|
||||
t.Run("ok: already logged in", func(t *testing.T) {
|
||||
r := httptest.NewRequest(http.MethodGet, "/", nil)
|
||||
setLoginCookie(httptest.NewRecorder(), r, User{User: "user", Group: "othergroup", Groups: []string{"group", "othergroup"}})
|
||||
s2, done, err := server.authenticate(nil, r)
|
||||
if err != nil {
|
||||
t.Error(err)
|
||||
}
|
||||
if done {
|
||||
t.Error(done)
|
||||
}
|
||||
if server == s2 {
|
||||
t.Error(done)
|
||||
}
|
||||
if server.user != nil {
|
||||
t.Error(server.user)
|
||||
}
|
||||
if s2.user == nil {
|
||||
t.Error(s2.user)
|
||||
}
|
||||
if s2.user.User != "user" {
|
||||
t.Error(s2.user)
|
||||
}
|
||||
if s2.user.Group != "othergroup" {
|
||||
t.Error(s2.user)
|
||||
}
|
||||
if fmt.Sprint(s2.user.Groups) != fmt.Sprint([]string{"group", "othergroup"}) {
|
||||
t.Error(s2.user)
|
||||
}
|
||||
})
|
||||
|
||||
t.Run("ok: basic auth", func(t *testing.T) {
|
||||
r := httptest.NewRequest(http.MethodGet, "/", nil)
|
||||
w := httptest.NewRecorder()
|
||||
r.SetBasicAuth("user", "passw")
|
||||
s2, done, err := server.authenticate(w, r)
|
||||
if err != nil {
|
||||
t.Error(err)
|
||||
}
|
||||
if done {
|
||||
t.Error(done)
|
||||
}
|
||||
if server == s2 {
|
||||
t.Error(done)
|
||||
}
|
||||
if server.user != nil {
|
||||
t.Error(server.user)
|
||||
}
|
||||
if s2.user == nil {
|
||||
t.Error(s2.user)
|
||||
}
|
||||
if s2.user.User != "user" {
|
||||
t.Error(s2.user)
|
||||
}
|
||||
if s2.user.Group != "group" {
|
||||
t.Error(s2.user)
|
||||
}
|
||||
if fmt.Sprint(s2.user.Groups) != fmt.Sprint([]string{"group", "othergroup"}) {
|
||||
t.Error(s2.user)
|
||||
}
|
||||
if w.Code != http.StatusOK {
|
||||
t.Error(w.Code)
|
||||
}
|
||||
if len(w.Header()["Set-Cookie"]) != 1 {
|
||||
t.Error(w.Header())
|
||||
}
|
||||
})
|
||||
}
|
||||
|
||||
func newTestServer(t *testing.T) *Server {
|
||||
cookieSecret = uuid.New().String()
|
||||
p := path.Join(t.TempDir(), "auth.yaml")
|
||||
ensureAndWrite(p, []byte(`{"users":{"user":{"password":"passw", "groups":["group", "othergroup"]}}}`))
|
||||
return &Server{
|
||||
auth: NewFileAuth(p),
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user