Add bcrypt user file auth, JWT middleware on all write routes, Pinia authStore with localStorage persistence, login view with redirect support, and v-if guards on all CRUD controls and admin nav link. Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
76 lines
2.2 KiB
Go
76 lines
2.2 KiB
Go
package handler_test
|
|
|
|
import (
|
|
"net/http"
|
|
"net/http/httptest"
|
|
"strings"
|
|
"testing"
|
|
|
|
"golang.org/x/crypto/bcrypt"
|
|
|
|
"github.com/labstack/echo/v4"
|
|
|
|
"osdb/internal/handler"
|
|
)
|
|
|
|
func makeUsersMap(username, password string) map[string]string {
|
|
h, _ := bcrypt.GenerateFromPassword([]byte(username+":"+password), bcrypt.MinCost)
|
|
return map[string]string{username: string(h)}
|
|
}
|
|
|
|
func TestAuthHandler_Login_ValidCredentials(t *testing.T) {
|
|
users := makeUsersMap("admin", "secret")
|
|
h := handler.NewAuthHandler(users, "jwttest")
|
|
|
|
body := `{"username":"admin","password":"secret"}`
|
|
req := httptest.NewRequest(http.MethodPost, "/api/v1/auth/login", strings.NewReader(body))
|
|
req.Header.Set("Content-Type", "application/json")
|
|
rec := httptest.NewRecorder()
|
|
c := echo.New().NewContext(req, rec)
|
|
|
|
if err := h.Login(c); err != nil {
|
|
t.Fatalf("unexpected error: %v", err)
|
|
}
|
|
if rec.Code != http.StatusOK {
|
|
t.Errorf("expected 200, got %d — body: %s", rec.Code, rec.Body.String())
|
|
}
|
|
if !strings.Contains(rec.Body.String(), "token") {
|
|
t.Errorf("expected 'token' in response, got: %s", rec.Body.String())
|
|
}
|
|
}
|
|
|
|
func TestAuthHandler_Login_InvalidCredentials(t *testing.T) {
|
|
users := makeUsersMap("admin", "secret")
|
|
h := handler.NewAuthHandler(users, "jwttest")
|
|
|
|
body := `{"username":"admin","password":"wrong"}`
|
|
req := httptest.NewRequest(http.MethodPost, "/api/v1/auth/login", strings.NewReader(body))
|
|
req.Header.Set("Content-Type", "application/json")
|
|
rec := httptest.NewRecorder()
|
|
c := echo.New().NewContext(req, rec)
|
|
|
|
if err := h.Login(c); err != nil {
|
|
t.Fatalf("unexpected error: %v", err)
|
|
}
|
|
if rec.Code != http.StatusUnauthorized {
|
|
t.Errorf("expected 401, got %d", rec.Code)
|
|
}
|
|
}
|
|
|
|
func TestAuthHandler_Login_MissingBody(t *testing.T) {
|
|
users := makeUsersMap("admin", "secret")
|
|
h := handler.NewAuthHandler(users, "jwttest")
|
|
|
|
req := httptest.NewRequest(http.MethodPost, "/api/v1/auth/login", nil)
|
|
req.Header.Set("Content-Type", "application/json")
|
|
rec := httptest.NewRecorder()
|
|
c := echo.New().NewContext(req, rec)
|
|
|
|
if err := h.Login(c); err != nil {
|
|
t.Fatalf("unexpected error: %v", err)
|
|
}
|
|
if rec.Code != http.StatusUnauthorized {
|
|
t.Errorf("expected 401, got %d", rec.Code)
|
|
}
|
|
}
|