forked from baron/baron-sso
golangci lint 적용
This commit is contained in:
@@ -13,7 +13,7 @@ import (
|
||||
)
|
||||
|
||||
// Mock DB for ApiKey tests using a real GORM instance but with a hijacked connection
|
||||
// or just a simple mock if we only check nil.
|
||||
// or just a simple mock if we only check nil.
|
||||
// For ApiKeyHandler, it uses DB for Create/List/Delete.
|
||||
|
||||
func TestApiKeyHandler_CreateApiKey(t *testing.T) {
|
||||
@@ -22,11 +22,11 @@ func TestApiKeyHandler_CreateApiKey(t *testing.T) {
|
||||
// Since we don't have a real DB here, we'll check if it fails gracefully
|
||||
// or we can use sqlite in-memory for a more realistic test.
|
||||
h := &ApiKeyHandler{DB: nil} // Testing ServiceUnavailable
|
||||
|
||||
|
||||
app.Post("/api-keys", h.CreateApiKey)
|
||||
|
||||
input := map[string]interface{}{
|
||||
"name": "M2M Test",
|
||||
"name": "M2M Test",
|
||||
"scopes": []string{"read", "write"},
|
||||
}
|
||||
body, _ := json.Marshal(input)
|
||||
@@ -41,8 +41,8 @@ func TestApiKeyHandler_CreateApiKey(t *testing.T) {
|
||||
func TestApiKeyHandler_Validation(t *testing.T) {
|
||||
app := fiber.New()
|
||||
// Using a dummy DB pointer to pass the nil check
|
||||
h := &ApiKeyHandler{DB: &gorm.DB{}}
|
||||
|
||||
h := &ApiKeyHandler{DB: &gorm.DB{}}
|
||||
|
||||
app.Post("/api-keys", h.CreateApiKey)
|
||||
|
||||
// Missing name
|
||||
|
||||
@@ -3820,6 +3820,7 @@ func (h *AuthHandler) resolveCurrentProfile(c *fiber.Ctx) (*domain.UserProfileRe
|
||||
|
||||
return profile, nil
|
||||
}
|
||||
|
||||
func (h *AuthHandler) resolveConsentSubject(c *fiber.Ctx) (string, error) {
|
||||
token := h.getBearerToken(c)
|
||||
if token != "" {
|
||||
|
||||
@@ -31,12 +31,15 @@ type MockIdentityProvider struct {
|
||||
func (m *MockIdentityProvider) Name() string {
|
||||
return "mock-idp"
|
||||
}
|
||||
|
||||
func (m *MockIdentityProvider) GetMetadata() (*domain.IDPMetadata, error) {
|
||||
return nil, nil
|
||||
}
|
||||
|
||||
func (m *MockIdentityProvider) CreateUser(user *domain.BrokerUser, password string) (string, error) {
|
||||
return "", nil
|
||||
}
|
||||
|
||||
func (m *MockIdentityProvider) SignIn(loginID, password string) (*domain.AuthInfo, error) {
|
||||
args := m.Called(loginID, password)
|
||||
if args.Get(0) == nil {
|
||||
@@ -44,27 +47,35 @@ func (m *MockIdentityProvider) SignIn(loginID, password string) (*domain.AuthInf
|
||||
}
|
||||
return args.Get(0).(*domain.AuthInfo), args.Error(1)
|
||||
}
|
||||
|
||||
func (m *MockIdentityProvider) UserExists(loginID string) (bool, error) {
|
||||
return true, nil
|
||||
}
|
||||
|
||||
func (m *MockIdentityProvider) IssueSession(loginID string) (*domain.AuthInfo, error) {
|
||||
return nil, nil
|
||||
}
|
||||
|
||||
func (m *MockIdentityProvider) InitiateLinkLogin(loginID, returnTo string) (*domain.LinkLoginInit, error) {
|
||||
return nil, nil
|
||||
}
|
||||
|
||||
func (m *MockIdentityProvider) VerifyLoginCode(loginID, flowID, code string) (*domain.AuthInfo, error) {
|
||||
return nil, nil
|
||||
}
|
||||
|
||||
func (m *MockIdentityProvider) GetPasswordPolicy() (*domain.PasswordPolicy, error) {
|
||||
return nil, nil
|
||||
}
|
||||
|
||||
func (m *MockIdentityProvider) InitiatePasswordReset(loginID, redirectUrl string) error {
|
||||
return nil
|
||||
}
|
||||
|
||||
func (m *MockIdentityProvider) VerifyPasswordResetToken(token string) (*domain.AuthInfo, error) {
|
||||
return nil, nil
|
||||
}
|
||||
|
||||
func (m *MockIdentityProvider) UpdateUserPassword(loginID, newPassword string, r *http.Request) error {
|
||||
return nil
|
||||
}
|
||||
@@ -102,7 +113,7 @@ func mockHydraTransport(handler http.Handler) http.RoundTripper {
|
||||
|
||||
func TestPasswordLogin_OIDC_Success(t *testing.T) {
|
||||
mockIdp := new(MockIdentityProvider)
|
||||
|
||||
|
||||
// Mock IDP SignIn Success
|
||||
mockIdp.On("SignIn", "user@example.com", "password").Return(&domain.AuthInfo{
|
||||
SessionToken: &domain.Token{JWT: "valid-jwt"},
|
||||
@@ -142,7 +153,7 @@ func TestPasswordLogin_OIDC_Success(t *testing.T) {
|
||||
// Inject Mock Kratos (Hack: overwrite the service field if it was an interface, but it's a struct pointer)
|
||||
// AuthHandler uses *service.KratosAdminService struct pointer.
|
||||
// KratosAdminService methods are real. We need to mock HTTP client inside KratosAdminService too.
|
||||
|
||||
|
||||
kratosHandler := http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) {
|
||||
// Mock FindIdentityIDByIdentifier response
|
||||
if strings.Contains(r.URL.Path, "/identities") {
|
||||
@@ -159,8 +170,8 @@ func TestPasswordLogin_OIDC_Success(t *testing.T) {
|
||||
app := newAuthLoginTestApp(h)
|
||||
|
||||
body, _ := json.Marshal(map[string]string{
|
||||
"loginId": "user@example.com",
|
||||
"password": "password",
|
||||
"loginId": "user@example.com",
|
||||
"password": "password",
|
||||
"login_challenge": "challenge-123",
|
||||
})
|
||||
req := httptest.NewRequest(http.MethodPost, "/api/v1/auth/login", bytes.NewReader(body))
|
||||
@@ -209,7 +220,7 @@ func TestPasswordLogin_OIDC_InactiveClient(t *testing.T) {
|
||||
HTTPClient: &http.Client{Transport: mockHydraTransport(hydraHandler)},
|
||||
},
|
||||
}
|
||||
|
||||
|
||||
kratosHandler := http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) {
|
||||
json.NewEncoder(w).Encode([]map[string]interface{}{{"id": "kratos-identity-id"}})
|
||||
})
|
||||
@@ -219,8 +230,8 @@ func TestPasswordLogin_OIDC_InactiveClient(t *testing.T) {
|
||||
app := newAuthLoginTestApp(h)
|
||||
|
||||
body, _ := json.Marshal(map[string]string{
|
||||
"loginId": "user@example.com",
|
||||
"password": "password",
|
||||
"loginId": "user@example.com",
|
||||
"password": "password",
|
||||
"login_challenge": "challenge-inactive",
|
||||
})
|
||||
req := httptest.NewRequest(http.MethodPost, "/api/v1/auth/login", bytes.NewReader(body))
|
||||
@@ -250,7 +261,7 @@ func TestPasswordLogin_NoOIDC_Success(t *testing.T) {
|
||||
KratosAdmin: service.NewKratosAdminService(),
|
||||
Hydra: service.NewHydraAdminService(),
|
||||
}
|
||||
|
||||
|
||||
kratosHandler := http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) {
|
||||
json.NewEncoder(w).Encode([]map[string]interface{}{{"id": "kratos-identity-id"}})
|
||||
})
|
||||
|
||||
@@ -1,6 +1,7 @@
|
||||
package handler
|
||||
|
||||
import (
|
||||
"baron-sso-backend/internal/service"
|
||||
"bytes"
|
||||
"encoding/json"
|
||||
"io"
|
||||
@@ -9,8 +10,6 @@ import (
|
||||
"testing"
|
||||
|
||||
"github.com/gofiber/fiber/v2"
|
||||
|
||||
"baron-sso-backend/internal/service"
|
||||
)
|
||||
|
||||
func newOidcLoginTestApp(h *AuthHandler) *fiber.App {
|
||||
|
||||
@@ -12,17 +12,17 @@ import (
|
||||
|
||||
// FederationHandler handles API requests for IdP federation.
|
||||
type FederationHandler struct {
|
||||
fedSvc *service.FederationService
|
||||
repo repository.FederationRepository // For IdP Config CRUD
|
||||
db *gorm.DB // For tenant existence checks, etc. in CRUD
|
||||
fedSvc *service.FederationService
|
||||
repo repository.FederationRepository // For IdP Config CRUD
|
||||
db *gorm.DB // For tenant existence checks, etc. in CRUD
|
||||
}
|
||||
|
||||
// NewFederationHandler creates a new FederationHandler.
|
||||
func NewFederationHandler(fedSvc *service.FederationService, repo repository.FederationRepository, db *gorm.DB) *FederationHandler {
|
||||
return &FederationHandler{
|
||||
fedSvc: fedSvc,
|
||||
repo: repo,
|
||||
db: db,
|
||||
fedSvc: fedSvc,
|
||||
repo: repo,
|
||||
db: db,
|
||||
}
|
||||
}
|
||||
|
||||
@@ -98,7 +98,7 @@ func (h *FederationHandler) CreateIdpConfigForClient(c *fiber.Ctx) error {
|
||||
if req.DisplayName == "" || req.ProviderType == "" {
|
||||
return c.Status(fiber.StatusBadRequest).JSON(fiber.Map{"error": "display_name and provider_type are required"})
|
||||
}
|
||||
|
||||
|
||||
// TODO: Optionally, validate if the clientID exists in Hydra
|
||||
|
||||
// Create in DB
|
||||
@@ -108,8 +108,6 @@ func (h *FederationHandler) CreateIdpConfigForClient(c *fiber.Ctx) error {
|
||||
|
||||
return c.Status(fiber.StatusCreated).JSON(req)
|
||||
}
|
||||
|
||||
|
||||
// --- Deprecated Tenant-based IdP Config Methods ---
|
||||
|
||||
// ListIdpConfigsForTenant handles listing all IdP configurations for a tenant.
|
||||
@@ -150,7 +148,7 @@ func (h *FederationHandler) CreateIdpConfig(c *fiber.Ctx) error {
|
||||
}
|
||||
return c.Status(fiber.StatusInternalServerError).JSON(fiber.Map{"error": err.Error()})
|
||||
}
|
||||
|
||||
|
||||
// Create in DB
|
||||
if err := h.db.Create(&req).Error; err != nil {
|
||||
return c.Status(fiber.StatusInternalServerError).JSON(fiber.Map{"error": err.Error()})
|
||||
@@ -158,4 +156,5 @@ func (h *FederationHandler) CreateIdpConfig(c *fiber.Ctx) error {
|
||||
|
||||
return c.Status(fiber.StatusCreated).JSON(req)
|
||||
}
|
||||
|
||||
// TODO: Re-implement Update, Delete handlers for IdP Configs for Clients
|
||||
|
||||
@@ -3,8 +3,9 @@ package handler
|
||||
import (
|
||||
"baron-sso-backend/internal/domain"
|
||||
"baron-sso-backend/internal/service"
|
||||
"github.com/gofiber/fiber/v2"
|
||||
"log/slog"
|
||||
|
||||
"github.com/gofiber/fiber/v2"
|
||||
)
|
||||
|
||||
type RelyingPartyHandler struct {
|
||||
|
||||
@@ -139,8 +139,8 @@ func (h *TenantHandler) CreateTenant(c *fiber.Ctx) error {
|
||||
}
|
||||
|
||||
var req struct {
|
||||
Name string `json:"name"`
|
||||
Slug string `json:"slug"`
|
||||
Name string `json:"name"`
|
||||
Slug string `json:"slug"`
|
||||
Description string `json:"description"`
|
||||
Status string `json:"status"`
|
||||
Domains []string `json:"domains"`
|
||||
@@ -204,8 +204,8 @@ func (h *TenantHandler) UpdateTenant(c *fiber.Ctx) error {
|
||||
}
|
||||
|
||||
var req struct {
|
||||
Name *string `json:"name"`
|
||||
Slug *string `json:"slug"`
|
||||
Name *string `json:"name"`
|
||||
Slug *string `json:"slug"`
|
||||
Description *string `json:"description"`
|
||||
Status *string `json:"status"`
|
||||
Domains []string `json:"domains"`
|
||||
|
||||
@@ -74,13 +74,13 @@ func TestTenantHandler_CreateTenant(t *testing.T) {
|
||||
app := fiber.New()
|
||||
mockSvc := new(MockTenantService)
|
||||
// CreateTenant checks h.DB != nil
|
||||
h := &TenantHandler{Service: mockSvc, DB: &gorm.DB{}}
|
||||
|
||||
h := &TenantHandler{Service: mockSvc, DB: &gorm.DB{}}
|
||||
|
||||
app.Post("/tenants", h.CreateTenant)
|
||||
|
||||
input := map[string]interface{}{
|
||||
"name": "Test Tenant",
|
||||
"slug": "test-tenant",
|
||||
"name": "Test Tenant",
|
||||
"slug": "test-tenant",
|
||||
"domains": []string{"test.com"},
|
||||
}
|
||||
body, _ := json.Marshal(input)
|
||||
@@ -102,7 +102,7 @@ func TestTenantHandler_ApproveTenant(t *testing.T) {
|
||||
app := fiber.New()
|
||||
mockSvc := new(MockTenantService)
|
||||
h := &TenantHandler{Service: mockSvc}
|
||||
|
||||
|
||||
app.Post("/tenants/:id/approve", h.ApproveTenant)
|
||||
|
||||
mockSvc.On("ApproveTenant", mock.Anything, "t1").Return(nil)
|
||||
|
||||
@@ -3,6 +3,7 @@ package handler
|
||||
import (
|
||||
"baron-sso-backend/internal/domain"
|
||||
"baron-sso-backend/internal/service"
|
||||
|
||||
"github.com/gofiber/fiber/v2"
|
||||
)
|
||||
|
||||
|
||||
@@ -548,7 +548,7 @@ func (h *UserHandler) DeleteUser(c *fiber.Ctx) error {
|
||||
ctx := context.Background()
|
||||
// Fetch user from DB before cleanup if needed, but here we cleanup common namespaces
|
||||
_ = h.KetoService.DeleteRelation(ctx, "System", "global", "super_admins", uID)
|
||||
|
||||
|
||||
// If we had more complex relations, we would query Keto first or use user metadata
|
||||
slog.Info("Keto relations cleaned up for user", "userID", uID)
|
||||
}(userID)
|
||||
|
||||
Reference in New Issue
Block a user