155 lines
5.2 KiB
Go
155 lines
5.2 KiB
Go
package api
|
|
|
|
import (
|
|
"net/http"
|
|
"testing"
|
|
"time"
|
|
|
|
"github.com/gofiber/fiber/v2"
|
|
|
|
"wucher/internal/config"
|
|
"wucher/internal/service"
|
|
"wucher/internal/transport/http/handlers"
|
|
)
|
|
|
|
func TestForgotPasswordIPLimiter(t *testing.T) {
|
|
cfg := config.AuthConfig{
|
|
ForgotPasswordIPRateMax: 1,
|
|
ForgotPasswordIPRateWindow: time.Minute,
|
|
}
|
|
svc := service.NewAuthService(nil, nil, nil, nil, service.AuthServiceDependencies{SSO: nil, Protector: nil, Config: cfg})
|
|
|
|
app := fiber.New()
|
|
app.Post("/forgot", forgotPasswordIPLimiter(svc), func(c *fiber.Ctx) error {
|
|
return c.SendStatus(http.StatusOK)
|
|
})
|
|
|
|
req1, _ := http.NewRequest(http.MethodPost, "/forgot", nil)
|
|
resp1, err := app.Test(req1)
|
|
if err != nil {
|
|
t.Fatalf("first request failed: %v", err)
|
|
}
|
|
if resp1.StatusCode != http.StatusOK {
|
|
t.Fatalf("expected first request 200, got %d", resp1.StatusCode)
|
|
}
|
|
|
|
req2, _ := http.NewRequest(http.MethodPost, "/forgot", nil)
|
|
resp2, err := app.Test(req2)
|
|
if err != nil {
|
|
t.Fatalf("second request failed: %v", err)
|
|
}
|
|
if resp2.StatusCode != http.StatusTooManyRequests {
|
|
t.Fatalf("expected second request 429, got %d", resp2.StatusCode)
|
|
}
|
|
}
|
|
|
|
func TestLoginIPLimiter(t *testing.T) {
|
|
cfg := config.AuthConfig{
|
|
LoginIPRateMax: 1,
|
|
LoginIPRateWindow: time.Minute,
|
|
}
|
|
svc := service.NewAuthService(nil, nil, nil, nil, service.AuthServiceDependencies{SSO: nil, Protector: nil, Config: cfg})
|
|
|
|
app := fiber.New()
|
|
app.Post("/login", loginIPLimiter(svc), func(c *fiber.Ctx) error {
|
|
return c.SendStatus(http.StatusOK)
|
|
})
|
|
|
|
req1, _ := http.NewRequest(http.MethodPost, "/login", nil)
|
|
resp1, err := app.Test(req1)
|
|
if err != nil {
|
|
t.Fatalf("first request failed: %v", err)
|
|
}
|
|
if resp1.StatusCode != http.StatusOK {
|
|
t.Fatalf("expected first request 200, got %d", resp1.StatusCode)
|
|
}
|
|
|
|
req2, _ := http.NewRequest(http.MethodPost, "/login", nil)
|
|
resp2, err := app.Test(req2)
|
|
if err != nil {
|
|
t.Fatalf("second request failed: %v", err)
|
|
}
|
|
if resp2.StatusCode != http.StatusTooManyRequests {
|
|
t.Fatalf("expected second request 429, got %d", resp2.StatusCode)
|
|
}
|
|
}
|
|
|
|
func TestRegisterAuthRoutes(t *testing.T) {
|
|
app := fiber.New()
|
|
v1 := app.Group("/api/v1")
|
|
|
|
svc := service.NewAuthService(nil, nil, nil, nil, service.AuthServiceDependencies{SSO: nil, Protector: nil, Config: config.AuthConfig{}})
|
|
authHandler := handlers.NewAuthHandler(svc)
|
|
registerAuthRoutes(v1, authHandler, svc, nil)
|
|
|
|
routes := app.GetRoutes(true)
|
|
required := []struct {
|
|
method string
|
|
path string
|
|
}{
|
|
{method: http.MethodPost, path: "/api/v1/auth/register"},
|
|
{method: http.MethodPost, path: "/api/v1/auth/invite"},
|
|
{method: http.MethodPost, path: "/api/v1/auth/invite/resend-set-password"},
|
|
{method: http.MethodPost, path: "/api/v1/auth/forgot-password"},
|
|
{method: http.MethodPost, path: "/api/v1/auth/reset-password"},
|
|
{method: http.MethodPost, path: "/api/v1/auth/pin/setup"},
|
|
{method: http.MethodPost, path: "/api/v1/auth/pin/verify"},
|
|
{method: http.MethodPost, path: "/api/v1/auth/pin/change"},
|
|
{method: http.MethodPost, path: "/api/v1/auth/pin/request-reset"},
|
|
{method: http.MethodPost, path: "/api/v1/auth/pin/forgot"},
|
|
{method: http.MethodPost, path: "/api/v1/auth/pin/reset"},
|
|
{method: http.MethodPost, path: "/api/v1/auth/login"},
|
|
{method: http.MethodPost, path: "/api/v1/auth/exchange"},
|
|
{method: http.MethodPost, path: "/api/v1/auth/webauthn/register/begin"},
|
|
{method: http.MethodPost, path: "/api/v1/auth/webauthn/register/finish"},
|
|
{method: http.MethodPost, path: "/api/v1/auth/webauthn/login/begin"},
|
|
{method: http.MethodPost, path: "/api/v1/auth/webauthn/login/finish"},
|
|
{method: http.MethodPost, path: "/api/v1/auth/webauthn/reset-setup"},
|
|
{method: http.MethodPost, path: "/api/v1/auth/refresh"},
|
|
{method: http.MethodGet, path: "/api/v1/auth/sessions"},
|
|
{method: http.MethodDelete, path: "/api/v1/auth/sessions/:session_id"},
|
|
{method: http.MethodGet, path: "/api/v1/auth/me"},
|
|
{method: http.MethodGet, path: "/api/v1/auth/microsoft/login"},
|
|
{method: http.MethodGet, path: "/api/v1/auth/microsoft/login-check"},
|
|
{method: http.MethodGet, path: "/api/v1/auth/microsoft/link"},
|
|
{method: http.MethodPost, path: "/api/v1/auth/sso/link"},
|
|
{method: http.MethodDelete, path: "/api/v1/auth/sso/unlink"},
|
|
{method: http.MethodPost, path: "/api/v1/auth/totp/verify"},
|
|
{method: http.MethodPost, path: "/api/v1/auth/totp/reset-setup"},
|
|
}
|
|
|
|
for _, tc := range required {
|
|
if !hasRoute(routes, tc.method, tc.path) {
|
|
t.Fatalf("route %s %s not registered", tc.method, tc.path)
|
|
}
|
|
}
|
|
|
|
var forgotRoute *fiber.Route
|
|
for i := range routes {
|
|
if routes[i].Method == http.MethodPost && routes[i].Path == "/api/v1/auth/forgot-password" {
|
|
forgotRoute = &routes[i]
|
|
break
|
|
}
|
|
}
|
|
if forgotRoute == nil {
|
|
t.Fatalf("forgot password route not found")
|
|
}
|
|
if len(forgotRoute.Handlers) < 2 {
|
|
t.Fatalf("expected forgot password route to have limiter and handler, got %d handlers", len(forgotRoute.Handlers))
|
|
}
|
|
|
|
var loginRoute *fiber.Route
|
|
for i := range routes {
|
|
if routes[i].Method == http.MethodPost && routes[i].Path == "/api/v1/auth/login" {
|
|
loginRoute = &routes[i]
|
|
break
|
|
}
|
|
}
|
|
if loginRoute == nil {
|
|
t.Fatalf("login route not found")
|
|
}
|
|
if len(loginRoute.Handlers) < 2 {
|
|
t.Fatalf("expected login route to have limiter and handler, got %d handlers", len(loginRoute.Handlers))
|
|
}
|
|
}
|