128 lines
2.8 KiB
Go
128 lines
2.8 KiB
Go
|
|
package main
|
||
|
|
|
||
|
|
import (
|
||
|
|
"net/http"
|
||
|
|
"net/http/httptest"
|
||
|
|
"testing"
|
||
|
|
)
|
||
|
|
|
||
|
|
func TestLoginValid(t *testing.T) {
|
||
|
|
app := testApp(t)
|
||
|
|
admin := testAdminUser(t, app)
|
||
|
|
mux := testMux(app)
|
||
|
|
|
||
|
|
req := testRequest("POST", "/api/login", map[string]string{
|
||
|
|
"username": admin.Username,
|
||
|
|
"password": "admin123",
|
||
|
|
})
|
||
|
|
w := httptest.NewRecorder()
|
||
|
|
mux.ServeHTTP(w, req)
|
||
|
|
|
||
|
|
if w.Code != http.StatusOK {
|
||
|
|
t.Fatalf("status = %d, want 200\nbody: %s", w.Code, w.Body.String())
|
||
|
|
}
|
||
|
|
result := parseJSON(t, w)
|
||
|
|
if result["token"] == nil || result["token"] == "" {
|
||
|
|
t.Error("missing token in response")
|
||
|
|
}
|
||
|
|
user, ok := result["user"].(map[string]any)
|
||
|
|
if !ok || user["username"] != "admin" {
|
||
|
|
t.Errorf("user = %v", result["user"])
|
||
|
|
}
|
||
|
|
}
|
||
|
|
|
||
|
|
func TestLoginWrongPassword(t *testing.T) {
|
||
|
|
app := testApp(t)
|
||
|
|
testAdminUser(t, app)
|
||
|
|
mux := testMux(app)
|
||
|
|
|
||
|
|
req := testRequest("POST", "/api/login", map[string]string{
|
||
|
|
"username": "admin",
|
||
|
|
"password": "wrong",
|
||
|
|
})
|
||
|
|
w := httptest.NewRecorder()
|
||
|
|
mux.ServeHTTP(w, req)
|
||
|
|
|
||
|
|
if w.Code != http.StatusUnauthorized {
|
||
|
|
t.Errorf("status = %d, want 401", w.Code)
|
||
|
|
}
|
||
|
|
}
|
||
|
|
|
||
|
|
func TestLoginNonexistentUser(t *testing.T) {
|
||
|
|
app := testApp(t)
|
||
|
|
mux := testMux(app)
|
||
|
|
|
||
|
|
req := testRequest("POST", "/api/login", map[string]string{
|
||
|
|
"username": "nobody",
|
||
|
|
"password": "test",
|
||
|
|
})
|
||
|
|
w := httptest.NewRecorder()
|
||
|
|
mux.ServeHTTP(w, req)
|
||
|
|
|
||
|
|
if w.Code != http.StatusUnauthorized {
|
||
|
|
t.Errorf("status = %d, want 401", w.Code)
|
||
|
|
}
|
||
|
|
}
|
||
|
|
|
||
|
|
func TestAuthMiddlewareNoToken(t *testing.T) {
|
||
|
|
app := testApp(t)
|
||
|
|
mux := testMux(app)
|
||
|
|
|
||
|
|
req := testRequest("GET", "/api/me", nil)
|
||
|
|
w := httptest.NewRecorder()
|
||
|
|
mux.ServeHTTP(w, req)
|
||
|
|
|
||
|
|
if w.Code != http.StatusUnauthorized {
|
||
|
|
t.Errorf("status = %d, want 401", w.Code)
|
||
|
|
}
|
||
|
|
}
|
||
|
|
|
||
|
|
func TestAuthMiddlewareInvalidToken(t *testing.T) {
|
||
|
|
app := testApp(t)
|
||
|
|
mux := testMux(app)
|
||
|
|
|
||
|
|
req := testAuthRequest("GET", "/api/me", nil, "bad-token")
|
||
|
|
w := httptest.NewRecorder()
|
||
|
|
mux.ServeHTTP(w, req)
|
||
|
|
|
||
|
|
if w.Code != http.StatusUnauthorized {
|
||
|
|
t.Errorf("status = %d, want 401", w.Code)
|
||
|
|
}
|
||
|
|
}
|
||
|
|
|
||
|
|
func TestAuthMiddlewareRoleEnforcement(t *testing.T) {
|
||
|
|
app := testApp(t)
|
||
|
|
mux := testMux(app)
|
||
|
|
|
||
|
|
// Create a gate user — should not be able to access /api/users (admin only)
|
||
|
|
gate := testUserWithRole(t, app, "gateuser", "gate", []int{})
|
||
|
|
token := testToken(t, app, gate)
|
||
|
|
|
||
|
|
req := testAuthRequest("GET", "/api/users", nil, token)
|
||
|
|
w := httptest.NewRecorder()
|
||
|
|
mux.ServeHTTP(w, req)
|
||
|
|
|
||
|
|
if w.Code != http.StatusForbidden {
|
||
|
|
t.Errorf("status = %d, want 403", w.Code)
|
||
|
|
}
|
||
|
|
}
|
||
|
|
|
||
|
|
func TestMeEndpoint(t *testing.T) {
|
||
|
|
app := testApp(t)
|
||
|
|
admin := testAdminUser(t, app)
|
||
|
|
token := testToken(t, app, admin)
|
||
|
|
mux := testMux(app)
|
||
|
|
|
||
|
|
req := testAuthRequest("GET", "/api/me", nil, token)
|
||
|
|
w := httptest.NewRecorder()
|
||
|
|
mux.ServeHTTP(w, req)
|
||
|
|
|
||
|
|
if w.Code != http.StatusOK {
|
||
|
|
t.Fatalf("status = %d", w.Code)
|
||
|
|
}
|
||
|
|
result := parseJSON(t, w)
|
||
|
|
if result["username"] != "admin" {
|
||
|
|
t.Errorf("username = %v", result["username"])
|
||
|
|
}
|
||
|
|
}
|