Added tests, shift 'delete'. Fixed overnight shifts, sync, error handling.
This commit is contained in:
parent
9d0fa1f0af
commit
f9c4facad6
21 changed files with 2522 additions and 40 deletions
127
auth_test.go
Normal file
127
auth_test.go
Normal file
|
|
@ -0,0 +1,127 @@
|
|||
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"])
|
||||
}
|
||||
}
|
||||
Loading…
Add table
Add a link
Reference in a new issue