live-sfu-demo/internal/auth/auth_test.go

168 lines
4.7 KiB
Go

package auth
import (
"net/http"
"net/http/httptest"
"os"
"testing"
"time"
)
func TestUserStore(t *testing.T) {
store, _ := NewUserStore("")
if _, ok := store.Get("admin"); !ok {
t.Fatal("admin should exist")
}
_, ok := store.Verify("admin", "Admin123!")
if !ok {
t.Fatal("admin password should verify")
}
if _, ok := store.Verify("admin", "wrong"); ok {
t.Fatal("wrong password should fail")
}
if _, err := store.Create("bob", "secret123", "viewer"); err != nil {
t.Fatalf("create bob: %v", err)
}
if _, err := store.Create("bob", "secret123", "viewer"); err == nil {
t.Fatal("duplicate should fail")
}
}
func TestJWT(t *testing.T) {
mgr := NewJWTManager("test-secret", time.Hour)
tok, err := mgr.Sign("alice", "admin")
if err != nil {
t.Fatalf("sign: %v", err)
}
claims, err := mgr.Verify(tok)
if err != nil {
t.Fatalf("verify: %v", err)
}
if claims.Username != "alice" || claims.Role != "admin" {
t.Fatalf("claims mismatch: %+v", claims)
}
if _, err := mgr.Verify(tok + "x"); err == nil {
t.Fatal("tampered should fail")
}
mgr2 := NewJWTManager("test-secret", -time.Hour)
tok2, _ := mgr2.Sign("alice", "admin")
if _, err := mgr2.Verify(tok2); err == nil {
t.Fatal("expired should fail")
}
}
func TestCasbinEnforcer(t *testing.T) {
tmpPol := os.TempDir() + "/test_policy.csv"
data, _ := os.ReadFile("policy.csv")
_ = os.WriteFile(tmpPol, data, 0644)
defer os.Remove(tmpPol)
store, _ := NewUserStore("")
_, _ = store.Create("alice", "pass12345", "viewer")
_, _ = store.Create("pub", "pass12345", "publisher")
enc, err := NewEnforcer("model.conf", tmpPol, store)
if err != nil {
t.Fatalf("new enforcer: %v", err)
}
ok, _ := enc.Enforce("admin", "room", "publish")
if !ok {
t.Fatal("admin should can publish")
}
ok, _ = enc.Enforce("viewer", "room", "publish")
if ok {
t.Fatal("viewer should not publish")
}
ok, _ = enc.Enforce("viewer", "room", "subscribe")
if !ok {
t.Fatal("viewer should can subscribe")
}
ok, _ = enc.Enforce("publisher", "room", "publish")
if !ok {
t.Fatal("publisher should can publish")
}
ok, _ = enc.Enforce("guest", "room", "watch")
if ok {
t.Fatal("guest should not watch")
}
ok, _ = enc.Enforce("alice", "room", "subscribe")
if !ok {
t.Fatal("alice (viewer) should can subscribe")
}
ok, _ = enc.Enforce("alice", "room", "publish")
if ok {
t.Fatal("alice (viewer) should not publish")
}
}
func TestAuthManagerLogin(t *testing.T) {
tmpPol := os.TempDir() + "/test_policy2.csv"
data, _ := os.ReadFile("policy.csv")
_ = os.WriteFile(tmpPol, data, 0644)
defer os.Remove(tmpPol)
store, _ := NewUserStore("")
enc, _ := NewEnforcer("model.conf", tmpPol, store)
mgr := NewManagerWithStore(store, "test-jwt", time.Hour, enc)
tok, user, err := mgr.Login("admin", "Admin123!")
if err != nil {
t.Fatalf("login admin: %v", err)
}
if tok == "" || user.Username != "admin" {
t.Fatalf("login result bad: %v %v", tok, user)
}
if _, _, err := mgr.Login("admin", "wrong"); err == nil {
t.Fatal("wrong pwd should fail")
}
tok2, u2, err := mgr.Register("newuser", "pass12345", "viewer")
if err != nil {
t.Fatalf("register: %v", err)
}
if tok2 == "" || u2.Role != "viewer" {
t.Fatalf("register result bad")
}
claims, _, err := mgr.VerifyToken(tok)
if err != nil || claims.Username != "admin" {
t.Fatalf("verify token: %v %+v", err, claims)
}
}
func TestHTTPMiddleware(t *testing.T) {
tmpPol := os.TempDir() + "/test_policy3.csv"
data, _ := os.ReadFile("policy.csv")
_ = os.WriteFile(tmpPol, data, 0644)
defer os.Remove(tmpPol)
store, _ := NewUserStore("")
enc, _ := NewEnforcer("model.conf", tmpPol, store)
mgr := NewManagerWithStore(store, "test-jwt", time.Hour, enc)
protected := mgr.AuthorizeMiddleware("room", "publish", true)(http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) {
w.Write([]byte("ok"))
}))
req := httptest.NewRequest("GET", "/", nil)
rec := httptest.NewRecorder()
protected.ServeHTTP(rec, req)
if rec.Code != http.StatusUnauthorized {
t.Fatalf("expected 401, got %d", rec.Code)
}
tokViewer, _, _ := mgr.Login("viewer", "Viewer123!")
req2 := httptest.NewRequest("GET", "/", nil)
req2.Header.Set("Authorization", "Bearer "+tokViewer)
rec2 := httptest.NewRecorder()
protected.ServeHTTP(rec2, req2)
if rec2.Code != http.StatusForbidden {
t.Fatalf("viewer should be forbidden, got %d body=%s", rec2.Code, rec2.Body.String())
}
tokPub, _, _ := mgr.Login("publisher", "Publisher123!")
req3 := httptest.NewRequest("GET", "/", nil)
req3.Header.Set("Authorization", "Bearer "+tokPub)
rec3 := httptest.NewRecorder()
protected.ServeHTTP(rec3, req3)
if rec3.Code != http.StatusOK {
t.Fatalf("publisher should ok, got %d body=%s", rec3.Code, rec3.Body.String())
}
}