introduced central package registry by package init function
This commit is contained in:
@@ -0,0 +1,14 @@
|
||||
package appsystem
|
||||
|
||||
import "bamort/registry"
|
||||
|
||||
// init self-registers the appsystem module with the central registry.
|
||||
// main.go blank-imports this package to trigger this function.
|
||||
func init() {
|
||||
// Protected API routes (/api/version, /api/systeminfo).
|
||||
registry.RegisterRoutes(RegisterRoutes)
|
||||
|
||||
// Public routes (/api/public/version, /api/public/systeminfo).
|
||||
registry.RegisterPublicRoutes(RegisterPublicRoutes)
|
||||
//registry.RegisterMigration(MigrateStructure)
|
||||
}
|
||||
@@ -0,0 +1,14 @@
|
||||
package character
|
||||
|
||||
import "bamort/registry"
|
||||
|
||||
// init self-registers the character module with the central registry.
|
||||
// main.go blank-imports this package to trigger this function.
|
||||
func init() {
|
||||
// Protected API routes (/api/version, /api/systeminfo).
|
||||
registry.RegisterRoutes(RegisterRoutes)
|
||||
|
||||
// Public routes (/api/public/version, /api/public/systeminfo).
|
||||
registry.RegisterPublicRoutes(RegisterPublicRoutes)
|
||||
//registry.RegisterMigration(MigrateStructure)
|
||||
}
|
||||
@@ -88,3 +88,8 @@ func RegisterRoutes(r *gin.RouterGroup) {
|
||||
charGrp.POST("/calculate-static-fields", CalculateStaticFields) // Berechnung ohne Würfelwürfe
|
||||
charGrp.POST("/calculate-rolled-field", CalculateRolledField) // Berechnung mit Würfelwürfen
|
||||
}
|
||||
|
||||
// RegisterPublicRoutes registers public config routes (no auth required)
|
||||
func RegisterPublicRoutes(r *gin.Engine) {
|
||||
// Public version endpoint - no authentication required
|
||||
}
|
||||
|
||||
+35
-22
@@ -1,19 +1,21 @@
|
||||
package main
|
||||
|
||||
import (
|
||||
"bamort/appsystem"
|
||||
"bamort/character"
|
||||
_ "bamort/appsystem"
|
||||
_ "bamort/character"
|
||||
"bamort/config"
|
||||
"bamort/database"
|
||||
"bamort/equipment"
|
||||
"bamort/gsmaster"
|
||||
"bamort/importer"
|
||||
_ "bamort/equipment"
|
||||
_ "bamort/gsmaster"
|
||||
_ "bamort/importer"
|
||||
"bamort/logger"
|
||||
"bamort/maintenance"
|
||||
_ "bamort/maintenance"
|
||||
"bamort/pdfrender"
|
||||
_ "bamort/pdfrender"
|
||||
"bamort/registry"
|
||||
"bamort/router"
|
||||
"bamort/transfer"
|
||||
"bamort/user"
|
||||
_ "bamort/transfer"
|
||||
_ "bamort/user"
|
||||
|
||||
"github.com/gin-gonic/gin"
|
||||
)
|
||||
@@ -81,26 +83,37 @@ func main() {
|
||||
r := gin.Default()
|
||||
router.SetupGin(r)
|
||||
|
||||
// Routes registrieren
|
||||
// Routes registrieren (alle Module via registry)
|
||||
logger.Debug("Registriere API-Routen...")
|
||||
protected := router.BaseRouterGrp(r)
|
||||
// Register your module routes
|
||||
user.RegisterRoutes(protected)
|
||||
gsmaster.RegisterRoutes(protected)
|
||||
character.RegisterRoutes(protected)
|
||||
equipment.RegisterRoutes(protected)
|
||||
maintenance.RegisterRoutes(protected)
|
||||
importer.RegisterRoutes(protected)
|
||||
pdfrender.RegisterRoutes(protected)
|
||||
transfer.RegisterRoutes(protected)
|
||||
appsystem.RegisterRoutes(protected)
|
||||
registry.RunAllRoutes(protected)
|
||||
|
||||
// Register public routes (no authentication)
|
||||
pdfrender.RegisterPublicRoutes(r)
|
||||
appsystem.RegisterPublicRoutes(r)
|
||||
// Öffentliche Routen registrieren
|
||||
registry.RunAllPublicRoutes(r)
|
||||
|
||||
logger.Info("API-Routen erfolgreich registriert")
|
||||
|
||||
/*
|
||||
// Routes registrieren
|
||||
logger.Debug("Registriere API-Routen...")
|
||||
protected := router.BaseRouterGrp(r)
|
||||
// Register your module routes
|
||||
user.RegisterRoutes(protected)
|
||||
gsmaster.RegisterRoutes(protected)
|
||||
character.RegisterRoutes(protected)
|
||||
equipment.RegisterRoutes(protected)
|
||||
maintenance.RegisterRoutes(protected)
|
||||
importer.RegisterRoutes(protected)
|
||||
pdfrender.RegisterRoutes(protected)
|
||||
transfer.RegisterRoutes(protected)
|
||||
appsystem.RegisterRoutes(protected)
|
||||
|
||||
// Register public routes (no authentication)
|
||||
pdfrender.RegisterPublicRoutes(r)
|
||||
appsystem.RegisterPublicRoutes(r)
|
||||
*/
|
||||
logger.Info("API-Routen erfolgreich registriert")
|
||||
|
||||
// Server starten
|
||||
serverAddress := cfg.GetServerAddress()
|
||||
logger.Info("Server startet auf Adresse: %s", serverAddress)
|
||||
|
||||
@@ -0,0 +1,14 @@
|
||||
package database
|
||||
|
||||
import "bamort/registry"
|
||||
|
||||
// init self-registers the character module with the central registry.
|
||||
// main.go blank-imports this package to trigger this function.
|
||||
func init() {
|
||||
// Protected API routes (/api/version, /api/systeminfo).
|
||||
registry.RegisterRoutes(RegisterRoutes)
|
||||
|
||||
// Public routes (/api/public/version, /api/public/systeminfo).
|
||||
registry.RegisterPublicRoutes(RegisterPublicRoutes)
|
||||
registry.RegisterMigration(MigrateStructure)
|
||||
}
|
||||
@@ -0,0 +1,15 @@
|
||||
package database
|
||||
|
||||
import (
|
||||
"github.com/gin-gonic/gin"
|
||||
)
|
||||
|
||||
func RegisterRoutes(r *gin.RouterGroup) {
|
||||
route := r.Group("/database")
|
||||
route.GET("/setupcheck", SetupCheck)
|
||||
}
|
||||
|
||||
// RegisterPublicRoutes registers public config routes (no auth required)
|
||||
func RegisterPublicRoutes(r *gin.Engine) {
|
||||
// Public version endpoint - no authentication required
|
||||
}
|
||||
@@ -0,0 +1,14 @@
|
||||
package equipment
|
||||
|
||||
import "bamort/registry"
|
||||
|
||||
// init self-registers the character module with the central registry.
|
||||
// main.go blank-imports this package to trigger this function.
|
||||
func init() {
|
||||
// Protected API routes (/api/version, /api/systeminfo).
|
||||
registry.RegisterRoutes(RegisterRoutes)
|
||||
|
||||
// Public routes (/api/public/version, /api/public/systeminfo).
|
||||
registry.RegisterPublicRoutes(RegisterPublicRoutes)
|
||||
//registry.RegisterMigration(MigrateStructure)
|
||||
}
|
||||
@@ -19,3 +19,8 @@ func RegisterRoutes(r *gin.RouterGroup) {
|
||||
weaponGrp.PUT("/:waffe_id", UpdateWaffe)
|
||||
weaponGrp.DELETE("/:waffe_id", DeleteWaffe)
|
||||
}
|
||||
|
||||
// RegisterPublicRoutes registers public config routes (no auth required)
|
||||
func RegisterPublicRoutes(r *gin.Engine) {
|
||||
// Public version endpoint - no authentication required
|
||||
}
|
||||
|
||||
@@ -0,0 +1,14 @@
|
||||
package gamesystem
|
||||
|
||||
import "bamort/registry"
|
||||
|
||||
// init self-registers the character module with the central registry.
|
||||
// main.go blank-imports this package to trigger this function.
|
||||
func init() {
|
||||
// Protected API routes (/api/version, /api/systeminfo).
|
||||
registry.RegisterRoutes(RegisterRoutes)
|
||||
|
||||
// Public routes (/api/public/version, /api/public/systeminfo).
|
||||
registry.RegisterPublicRoutes(RegisterPublicRoutes)
|
||||
registry.RegisterMigration(MigrateStructure)
|
||||
}
|
||||
@@ -0,0 +1,15 @@
|
||||
package gamesystem
|
||||
|
||||
import (
|
||||
"github.com/gin-gonic/gin"
|
||||
)
|
||||
|
||||
func RegisterRoutes(r *gin.RouterGroup) {
|
||||
//route := r.Group("/database")
|
||||
//route.GET("/setupcheck", SetupCheck)
|
||||
}
|
||||
|
||||
// RegisterPublicRoutes registers public config routes (no auth required)
|
||||
func RegisterPublicRoutes(r *gin.Engine) {
|
||||
// Public version endpoint - no authentication required
|
||||
}
|
||||
@@ -0,0 +1,14 @@
|
||||
package gsmaster
|
||||
|
||||
import "bamort/registry"
|
||||
|
||||
// init self-registers the character module with the central registry.
|
||||
// main.go blank-imports this package to trigger this function.
|
||||
func init() {
|
||||
// Protected API routes (/api/version, /api/systeminfo).
|
||||
registry.RegisterRoutes(RegisterRoutes)
|
||||
|
||||
// Public routes (/api/public/version, /api/public/systeminfo).
|
||||
registry.RegisterPublicRoutes(RegisterPublicRoutes)
|
||||
//registry.RegisterMigration(MigrateStructure)
|
||||
}
|
||||
@@ -1,62 +1,15 @@
|
||||
package gsmaster
|
||||
|
||||
import (
|
||||
"bamort/user"
|
||||
|
||||
"github.com/gin-gonic/gin"
|
||||
)
|
||||
|
||||
func RegisterRoutes(r *gin.RouterGroup) {
|
||||
maintGrp := r.Group("/maintenance")
|
||||
|
||||
maintGrp.GET("", GetMasterData)
|
||||
maintGrp.GET("/skills", GetMDSkills)
|
||||
maintGrp.GET("/skills-enhanced", GetEnhancedMDSkills) // New enhanced endpoint
|
||||
maintGrp.GET("/skills/:id", GetMDSkill)
|
||||
maintGrp.GET("/skills-enhanced/:id", GetEnhancedMDSkill) // New enhanced endpoint
|
||||
maintGrp.GET("/weaponskills", GetMDWeaponSkills)
|
||||
maintGrp.GET("/weaponskills-enhanced", GetEnhancedMDWeaponSkills) // New enhanced endpoint
|
||||
maintGrp.GET("/weaponskills/:id", GetMDWeaponSkill)
|
||||
maintGrp.GET("/weaponskills-enhanced/:id", GetEnhancedMDWeaponSkill) // New enhanced endpoint
|
||||
maintGrp.GET("/spells", GetMDSpells)
|
||||
maintGrp.GET("/spells-enhanced", GetEnhancedMDSpells) // New enhanced endpoint
|
||||
maintGrp.GET("/spells/:id", GetMDSpell)
|
||||
maintGrp.GET("/spells-enhanced/:id", GetEnhancedMDSpell) // New enhanced endpoint
|
||||
maintGrp.GET("/equipment", GetMDEquipments)
|
||||
maintGrp.GET("/equipment-enhanced", GetEnhancedMDEquipment) // New enhanced endpoint
|
||||
maintGrp.GET("/equipment/:id", GetMDEquipment)
|
||||
maintGrp.GET("/equipment-enhanced/:id", GetEnhancedMDEquipmentItem) // New enhanced endpoint
|
||||
maintGrp.GET("/weapons", GetMDWeapons)
|
||||
maintGrp.GET("/weapons-enhanced", GetEnhancedMDWeapons) // New enhanced endpoint
|
||||
maintGrp.GET("/weapons/:id", GetMDWeapon)
|
||||
maintGrp.GET("/weapons-enhanced/:id", GetEnhancedMDWeapon) // New enhanced endpoint
|
||||
|
||||
maintGrp.Use(user.RequireMaintainer())
|
||||
{
|
||||
maintGrp.POST("/skills-enhanced", CreateEnhancedMDSkill) // Create new skill
|
||||
maintGrp.PUT("/skills/:id", UpdateMDSkill)
|
||||
maintGrp.PUT("/skills-enhanced/:id", UpdateEnhancedMDSkill) // New enhanced endpoint
|
||||
maintGrp.POST("/skills", AddSkill)
|
||||
maintGrp.DELETE("/skills/:id", DeleteMDSkill)
|
||||
|
||||
maintGrp.PUT("/weaponskills/:id", UpdateMDWeaponSkill)
|
||||
maintGrp.PUT("/weaponskills-enhanced/:id", UpdateEnhancedMDWeaponSkill) // New enhanced endpoint
|
||||
maintGrp.POST("/weaponskills", AddWeaponSkill)
|
||||
maintGrp.DELETE("/weaponskills/:id", DeleteMDWeaponSkill)
|
||||
|
||||
maintGrp.PUT("/spells/:id", UpdateMDSpell)
|
||||
maintGrp.PUT("/spells-enhanced/:id", UpdateEnhancedMDSpell) // New enhanced endpoint
|
||||
maintGrp.POST("/spells", AddSpell)
|
||||
maintGrp.DELETE("/spells/:id", DeleteMDSpell)
|
||||
|
||||
maintGrp.PUT("/equipment/:id", UpdateMDEquipment)
|
||||
maintGrp.PUT("/equipment-enhanced/:id", UpdateEnhancedMDEquipmentItem) // New enhanced endpoint
|
||||
maintGrp.POST("/equipment", AddEquipment)
|
||||
maintGrp.DELETE("/equipment/:id", DeleteMDEquipment)
|
||||
|
||||
maintGrp.PUT("/weapons/:id", UpdateMDWeapon)
|
||||
maintGrp.PUT("/weapons-enhanced/:id", UpdateEnhancedMDWeapon) // New enhanced endpoint
|
||||
maintGrp.POST("/weapons", AddWeapon)
|
||||
maintGrp.DELETE("/weapons/:id", DeleteMDWeapon)
|
||||
}
|
||||
//route := r.Group("/database")
|
||||
//route.GET("/setupcheck", SetupCheck)
|
||||
}
|
||||
|
||||
// RegisterPublicRoutes registers public config routes (no auth required)
|
||||
func RegisterPublicRoutes(r *gin.Engine) {
|
||||
// Public version endpoint - no authentication required
|
||||
}
|
||||
|
||||
@@ -0,0 +1,13 @@
|
||||
package importer
|
||||
|
||||
import "bamort/registry"
|
||||
|
||||
// init self-registers the character module with the central registry.
|
||||
// main.go blank-imports this package to trigger this function.
|
||||
func init() {
|
||||
// Protected API routes (/api/version, /api/systeminfo).
|
||||
registry.RegisterRoutes(RegisterRoutes)
|
||||
|
||||
// Public routes (/api/public/version, /api/public/systeminfo).
|
||||
registry.RegisterPublicRoutes(RegisterPublicRoutes)
|
||||
}
|
||||
@@ -18,3 +18,8 @@ func RegisterRoutes(r *gin.RouterGroup) {
|
||||
exportGrp.GET("/csv/:id", ExportCharacterCSVHandler)
|
||||
exportGrp.GET("/spells/csv", ExportSpellsCSVHandler)
|
||||
}
|
||||
|
||||
// RegisterPublicRoutes registers public config routes (no auth required)
|
||||
func RegisterPublicRoutes(r *gin.Engine) {
|
||||
// Public version endpoint - no authentication required
|
||||
}
|
||||
|
||||
@@ -0,0 +1,14 @@
|
||||
package maintenance
|
||||
|
||||
import "bamort/registry"
|
||||
|
||||
// init self-registers the maintenance module with the central registry.
|
||||
// main.go blank-imports this package to trigger this function.
|
||||
func init() {
|
||||
// Protected API routes (/api/version, /api/systeminfo).
|
||||
registry.RegisterRoutes(RegisterRoutes)
|
||||
|
||||
// Public routes (/api/public/version, /api/public/systeminfo).
|
||||
registry.RegisterPublicRoutes(RegisterPublicRoutes)
|
||||
//registry.RegisterMigration(MigrateStructure)
|
||||
}
|
||||
@@ -35,3 +35,8 @@ func RegisterRoutes(r *gin.RouterGroup) {
|
||||
*/
|
||||
}
|
||||
}
|
||||
|
||||
// RegisterPublicRoutes registers public config routes (no auth required)
|
||||
func RegisterPublicRoutes(r *gin.Engine) {
|
||||
// Public version endpoint - no authentication required
|
||||
}
|
||||
|
||||
@@ -0,0 +1,14 @@
|
||||
package models
|
||||
|
||||
import "bamort/registry"
|
||||
|
||||
// init self-registers the character module with the central registry.
|
||||
// main.go blank-imports this package to trigger this function.
|
||||
func init() {
|
||||
// Protected API routes (/api/version, /api/systeminfo).
|
||||
//registry.RegisterRoutes(RegisterRoutes)
|
||||
|
||||
// Public routes (/api/public/version, /api/public/systeminfo).
|
||||
//registry.RegisterPublicRoutes(RegisterPublicRoutes)
|
||||
registry.RegisterMigration(MigrateStructure)
|
||||
}
|
||||
@@ -0,0 +1,14 @@
|
||||
package pdfrender
|
||||
|
||||
import "bamort/registry"
|
||||
|
||||
// init self-registers the character module with the central registry.
|
||||
// main.go blank-imports this package to trigger this function.
|
||||
func init() {
|
||||
// Protected API routes (/api/version, /api/systeminfo).
|
||||
registry.RegisterRoutes(RegisterRoutes)
|
||||
|
||||
// Public routes (/api/public/version, /api/public/systeminfo).
|
||||
registry.RegisterPublicRoutes(RegisterPublicRoutes)
|
||||
//registry.RegisterMigration(MigrateStructure)
|
||||
}
|
||||
@@ -0,0 +1,101 @@
|
||||
// Package registry provides a central module self-registration mechanism.
|
||||
// Modules register their routes and migrations via init() functions,
|
||||
// keeping each module self-contained without direct cross-module imports.
|
||||
// main.go blank-imports each module to trigger its init() and then calls
|
||||
// the Run* helpers here to wire everything together.
|
||||
package registry
|
||||
|
||||
import (
|
||||
"github.com/gin-gonic/gin"
|
||||
"gorm.io/gorm"
|
||||
)
|
||||
|
||||
// MigrateFunc is a function that runs database migrations for a module.
|
||||
type MigrateFunc func(db ...*gorm.DB) error
|
||||
|
||||
// RouteFunc registers protected routes on an API router group.
|
||||
type RouteFunc func(r *gin.RouterGroup)
|
||||
|
||||
// PublicRouteFunc registers public routes directly on the gin engine.
|
||||
type PublicRouteFunc func(r *gin.Engine)
|
||||
|
||||
// BaseRouteFunc registers base routes (login, register, etc.) on the gin engine.
|
||||
type BaseRouteFunc func(r *gin.Engine)
|
||||
|
||||
// AuthMiddlewareProvider returns a gin.HandlerFunc used for JWT authentication.
|
||||
type AuthMiddlewareProvider func() gin.HandlerFunc
|
||||
|
||||
var (
|
||||
routeFuncs []RouteFunc
|
||||
publicRouteFuncs []PublicRouteFunc
|
||||
baseRouteFuncs []BaseRouteFunc
|
||||
migrateFuncs []MigrateFunc
|
||||
authProvider AuthMiddlewareProvider
|
||||
)
|
||||
|
||||
// RegisterRoutes adds a module's protected route registrar to the registry.
|
||||
func RegisterRoutes(fn RouteFunc) {
|
||||
routeFuncs = append(routeFuncs, fn)
|
||||
}
|
||||
|
||||
// RegisterPublicRoutes adds a module's public route registrar to the registry.
|
||||
func RegisterPublicRoutes(fn PublicRouteFunc) {
|
||||
publicRouteFuncs = append(publicRouteFuncs, fn)
|
||||
}
|
||||
|
||||
// RegisterBaseRoutes adds a module's unauthenticated base route registrar
|
||||
// (e.g. login, register, password-reset) to the registry.
|
||||
func RegisterBaseRoutes(fn BaseRouteFunc) {
|
||||
baseRouteFuncs = append(baseRouteFuncs, fn)
|
||||
}
|
||||
|
||||
// RegisterMigration adds a module's migration function to the registry.
|
||||
func RegisterMigration(fn MigrateFunc) {
|
||||
migrateFuncs = append(migrateFuncs, fn)
|
||||
}
|
||||
|
||||
// SetAuthMiddleware sets the authentication middleware provider.
|
||||
// Only one module (user) should call this.
|
||||
func SetAuthMiddleware(fn AuthMiddlewareProvider) {
|
||||
authProvider = fn
|
||||
}
|
||||
|
||||
// GetAuthMiddleware returns the registered auth middleware handler.
|
||||
// Falls back to a no-op pass-through when none has been registered.
|
||||
func GetAuthMiddleware() gin.HandlerFunc {
|
||||
if authProvider != nil {
|
||||
return authProvider()
|
||||
}
|
||||
return func(c *gin.Context) { c.Next() }
|
||||
}
|
||||
|
||||
// RunAllBaseRoutes calls all registered base route functions on the engine.
|
||||
func RunAllBaseRoutes(r *gin.Engine) {
|
||||
for _, fn := range baseRouteFuncs {
|
||||
fn(r)
|
||||
}
|
||||
}
|
||||
|
||||
// RunAllRoutes calls all registered protected route functions on the router group.
|
||||
func RunAllRoutes(r *gin.RouterGroup) {
|
||||
for _, fn := range routeFuncs {
|
||||
fn(r)
|
||||
}
|
||||
}
|
||||
|
||||
// RunAllPublicRoutes calls all registered public route functions on the engine.
|
||||
func RunAllPublicRoutes(r *gin.Engine) {
|
||||
for _, fn := range publicRouteFuncs {
|
||||
fn(r)
|
||||
}
|
||||
}
|
||||
|
||||
// RunAllMigrations runs every registered migration function with the provided DB.
|
||||
func RunAllMigrations(db *gorm.DB) error {
|
||||
for _, fn := range migrateFuncs {
|
||||
if err := fn(db); err != nil {
|
||||
return err
|
||||
}
|
||||
}
|
||||
return nil
|
||||
}
|
||||
@@ -0,0 +1,277 @@
|
||||
package registry
|
||||
|
||||
import (
|
||||
"errors"
|
||||
"net/http"
|
||||
"net/http/httptest"
|
||||
"testing"
|
||||
|
||||
"github.com/gin-gonic/gin"
|
||||
"github.com/stretchr/testify/assert"
|
||||
"github.com/stretchr/testify/require"
|
||||
"gorm.io/driver/sqlite"
|
||||
"gorm.io/gorm"
|
||||
)
|
||||
|
||||
// resetRegistry clears all registered functions so each test starts with a
|
||||
// clean slate. Only callable from within the registry package (_test.go).
|
||||
func resetRegistry() {
|
||||
routeFuncs = nil
|
||||
publicRouteFuncs = nil
|
||||
baseRouteFuncs = nil
|
||||
migrateFuncs = nil
|
||||
authProvider = nil
|
||||
}
|
||||
|
||||
func newTestEngine() *gin.Engine {
|
||||
gin.SetMode(gin.TestMode)
|
||||
return gin.New()
|
||||
}
|
||||
|
||||
func newTestDB(t *testing.T) *gorm.DB {
|
||||
t.Helper()
|
||||
db, err := gorm.Open(sqlite.Open(":memory:"), &gorm.Config{})
|
||||
require.NoError(t, err)
|
||||
return db
|
||||
}
|
||||
|
||||
// ---------------------------------------------------------------------------
|
||||
// RegisterRoutes / RunAllRoutes
|
||||
// ---------------------------------------------------------------------------
|
||||
|
||||
func TestRegisterRoutes_SingleFunc_IsCalled(t *testing.T) {
|
||||
resetRegistry()
|
||||
|
||||
called := false
|
||||
RegisterRoutes(func(r *gin.RouterGroup) {
|
||||
called = true
|
||||
r.GET("/ping", func(c *gin.Context) { c.Status(http.StatusOK) })
|
||||
})
|
||||
|
||||
engine := newTestEngine()
|
||||
RunAllRoutes(engine.Group("/api"))
|
||||
|
||||
assert.True(t, called)
|
||||
|
||||
w := httptest.NewRecorder()
|
||||
req, _ := http.NewRequest(http.MethodGet, "/api/ping", nil)
|
||||
engine.ServeHTTP(w, req)
|
||||
assert.Equal(t, http.StatusOK, w.Code)
|
||||
}
|
||||
|
||||
func TestRegisterRoutes_MultipleFuncs_AllCalled(t *testing.T) {
|
||||
resetRegistry()
|
||||
|
||||
count := 0
|
||||
for i := 0; i < 3; i++ {
|
||||
RegisterRoutes(func(r *gin.RouterGroup) { count++ })
|
||||
}
|
||||
RunAllRoutes(newTestEngine().Group("/api"))
|
||||
assert.Equal(t, 3, count)
|
||||
}
|
||||
|
||||
func TestRunAllRoutes_NoFuncs_DoesNotPanic(t *testing.T) {
|
||||
resetRegistry()
|
||||
assert.NotPanics(t, func() { RunAllRoutes(newTestEngine().Group("/api")) })
|
||||
}
|
||||
|
||||
// ---------------------------------------------------------------------------
|
||||
// RegisterPublicRoutes / RunAllPublicRoutes
|
||||
// ---------------------------------------------------------------------------
|
||||
|
||||
func TestRegisterPublicRoutes_SingleFunc_IsCalled(t *testing.T) {
|
||||
resetRegistry()
|
||||
|
||||
called := false
|
||||
RegisterPublicRoutes(func(r *gin.Engine) {
|
||||
called = true
|
||||
r.GET("/health", func(c *gin.Context) { c.Status(http.StatusOK) })
|
||||
})
|
||||
|
||||
engine := newTestEngine()
|
||||
RunAllPublicRoutes(engine)
|
||||
|
||||
assert.True(t, called)
|
||||
|
||||
w := httptest.NewRecorder()
|
||||
req, _ := http.NewRequest(http.MethodGet, "/health", nil)
|
||||
engine.ServeHTTP(w, req)
|
||||
assert.Equal(t, http.StatusOK, w.Code)
|
||||
}
|
||||
|
||||
func TestRunAllPublicRoutes_NoFuncs_DoesNotPanic(t *testing.T) {
|
||||
resetRegistry()
|
||||
assert.NotPanics(t, func() { RunAllPublicRoutes(newTestEngine()) })
|
||||
}
|
||||
|
||||
// ---------------------------------------------------------------------------
|
||||
// RegisterBaseRoutes / RunAllBaseRoutes
|
||||
// ---------------------------------------------------------------------------
|
||||
|
||||
func TestRegisterBaseRoutes_SingleFunc_IsCalled(t *testing.T) {
|
||||
resetRegistry()
|
||||
|
||||
called := false
|
||||
RegisterBaseRoutes(func(r *gin.Engine) {
|
||||
called = true
|
||||
r.POST("/login", func(c *gin.Context) { c.Status(http.StatusOK) })
|
||||
})
|
||||
|
||||
engine := newTestEngine()
|
||||
RunAllBaseRoutes(engine)
|
||||
|
||||
assert.True(t, called)
|
||||
|
||||
w := httptest.NewRecorder()
|
||||
req, _ := http.NewRequest(http.MethodPost, "/login", nil)
|
||||
engine.ServeHTTP(w, req)
|
||||
assert.Equal(t, http.StatusOK, w.Code)
|
||||
}
|
||||
|
||||
func TestRunAllBaseRoutes_NoFuncs_DoesNotPanic(t *testing.T) {
|
||||
resetRegistry()
|
||||
assert.NotPanics(t, func() { RunAllBaseRoutes(newTestEngine()) })
|
||||
}
|
||||
|
||||
// ---------------------------------------------------------------------------
|
||||
// SetAuthMiddleware / GetAuthMiddleware
|
||||
// ---------------------------------------------------------------------------
|
||||
|
||||
func TestGetAuthMiddleware_NoProvider_ReturnsPassThrough(t *testing.T) {
|
||||
resetRegistry()
|
||||
|
||||
mw := GetAuthMiddleware()
|
||||
require.NotNil(t, mw)
|
||||
|
||||
engine := newTestEngine()
|
||||
engine.Use(mw)
|
||||
engine.GET("/test", func(c *gin.Context) { c.Status(http.StatusOK) })
|
||||
|
||||
w := httptest.NewRecorder()
|
||||
req, _ := http.NewRequest(http.MethodGet, "/test", nil)
|
||||
engine.ServeHTTP(w, req)
|
||||
assert.Equal(t, http.StatusOK, w.Code, "pass-through should not block requests")
|
||||
}
|
||||
|
||||
func TestSetAuthMiddleware_ProviderIsUsed(t *testing.T) {
|
||||
resetRegistry()
|
||||
|
||||
providerCalled := false
|
||||
SetAuthMiddleware(func() gin.HandlerFunc {
|
||||
providerCalled = true
|
||||
return func(c *gin.Context) {
|
||||
c.Header("X-Auth", "ok")
|
||||
c.Next()
|
||||
}
|
||||
})
|
||||
|
||||
mw := GetAuthMiddleware()
|
||||
assert.True(t, providerCalled)
|
||||
|
||||
engine := newTestEngine()
|
||||
engine.Use(mw)
|
||||
engine.GET("/secure", func(c *gin.Context) { c.Status(http.StatusOK) })
|
||||
|
||||
w := httptest.NewRecorder()
|
||||
req, _ := http.NewRequest(http.MethodGet, "/secure", nil)
|
||||
engine.ServeHTTP(w, req)
|
||||
assert.Equal(t, "ok", w.Header().Get("X-Auth"))
|
||||
}
|
||||
|
||||
func TestSetAuthMiddleware_OverwritesPreviousProvider(t *testing.T) {
|
||||
resetRegistry()
|
||||
|
||||
SetAuthMiddleware(func() gin.HandlerFunc {
|
||||
return func(c *gin.Context) { c.Header("X-Version", "first"); c.Next() }
|
||||
})
|
||||
SetAuthMiddleware(func() gin.HandlerFunc {
|
||||
return func(c *gin.Context) { c.Header("X-Version", "second"); c.Next() }
|
||||
})
|
||||
|
||||
engine := newTestEngine()
|
||||
engine.Use(GetAuthMiddleware())
|
||||
engine.GET("/v", func(c *gin.Context) { c.Status(http.StatusOK) })
|
||||
|
||||
w := httptest.NewRecorder()
|
||||
req, _ := http.NewRequest(http.MethodGet, "/v", nil)
|
||||
engine.ServeHTTP(w, req)
|
||||
assert.Equal(t, "second", w.Header().Get("X-Version"), "last registration wins")
|
||||
}
|
||||
|
||||
// ---------------------------------------------------------------------------
|
||||
// RegisterMigration / RunAllMigrations
|
||||
// ---------------------------------------------------------------------------
|
||||
|
||||
func TestRunAllMigrations_NoFuncs_ReturnsNil(t *testing.T) {
|
||||
resetRegistry()
|
||||
assert.NoError(t, RunAllMigrations(newTestDB(t)))
|
||||
}
|
||||
|
||||
func TestRunAllMigrations_SingleFunc_IsCalled(t *testing.T) {
|
||||
resetRegistry()
|
||||
|
||||
called := false
|
||||
RegisterMigration(func(d ...*gorm.DB) error {
|
||||
called = true
|
||||
return nil
|
||||
})
|
||||
|
||||
require.NoError(t, RunAllMigrations(newTestDB(t)))
|
||||
assert.True(t, called)
|
||||
}
|
||||
|
||||
func TestRunAllMigrations_ReceivesCorrectDB(t *testing.T) {
|
||||
resetRegistry()
|
||||
db := newTestDB(t)
|
||||
|
||||
var received *gorm.DB
|
||||
RegisterMigration(func(d ...*gorm.DB) error {
|
||||
if len(d) > 0 {
|
||||
received = d[0]
|
||||
}
|
||||
return nil
|
||||
})
|
||||
|
||||
require.NoError(t, RunAllMigrations(db))
|
||||
assert.Same(t, db, received, "RunAllMigrations should pass the provided DB instance")
|
||||
}
|
||||
|
||||
func TestRunAllMigrations_MultipleFuncs_AllCalled(t *testing.T) {
|
||||
resetRegistry()
|
||||
|
||||
count := 0
|
||||
for i := 0; i < 3; i++ {
|
||||
RegisterMigration(func(d ...*gorm.DB) error { count++; return nil })
|
||||
}
|
||||
require.NoError(t, RunAllMigrations(newTestDB(t)))
|
||||
assert.Equal(t, 3, count)
|
||||
}
|
||||
|
||||
func TestRunAllMigrations_FirstErrorAbortsChain(t *testing.T) {
|
||||
resetRegistry()
|
||||
|
||||
secondCalled := false
|
||||
RegisterMigration(func(d ...*gorm.DB) error { return errors.New("migration failed") })
|
||||
RegisterMigration(func(d ...*gorm.DB) error { secondCalled = true; return nil })
|
||||
|
||||
err := RunAllMigrations(newTestDB(t))
|
||||
assert.Error(t, err)
|
||||
assert.False(t, secondCalled, "subsequent migrations must not run after an error")
|
||||
}
|
||||
|
||||
func TestRunAllMigrations_AutoMigratesModel(t *testing.T) {
|
||||
resetRegistry()
|
||||
db := newTestDB(t)
|
||||
|
||||
type SampleModel struct {
|
||||
gorm.Model
|
||||
Name string
|
||||
}
|
||||
|
||||
RegisterMigration(func(d ...*gorm.DB) error {
|
||||
return d[0].AutoMigrate(&SampleModel{})
|
||||
})
|
||||
|
||||
require.NoError(t, RunAllMigrations(db))
|
||||
assert.True(t, db.Migrator().HasTable(&SampleModel{}), "table should exist after migration")
|
||||
}
|
||||
@@ -1,22 +1,20 @@
|
||||
package router
|
||||
|
||||
import (
|
||||
"bamort/user"
|
||||
"bamort/registry"
|
||||
|
||||
"github.com/gin-gonic/gin"
|
||||
)
|
||||
|
||||
// BaseRouterGrp registers all base (unauthenticated) routes from every module
|
||||
// and returns the protected /api router group secured with the registered auth
|
||||
// middleware. Modules self-register via their init() functions; no direct
|
||||
// module imports are required here.
|
||||
func BaseRouterGrp(r *gin.Engine) *gin.RouterGroup {
|
||||
// Routes
|
||||
r.POST("/register", user.RegisterUser)
|
||||
r.POST("/login", user.LoginUser)
|
||||
|
||||
// Password Reset Routes (unprotected)
|
||||
r.POST("/password-reset/request", user.RequestPasswordReset)
|
||||
r.GET("/password-reset/validate/:token", user.ValidateResetToken)
|
||||
r.POST("/password-reset/reset", user.ResetPassword)
|
||||
// Call all base-route registrars (login, register, password-reset, …)
|
||||
registry.RunAllBaseRoutes(r)
|
||||
|
||||
protected := r.Group("/api")
|
||||
protected.Use(user.AuthMiddleware())
|
||||
protected.Use(registry.GetAuthMiddleware())
|
||||
return protected
|
||||
}
|
||||
|
||||
@@ -24,11 +24,11 @@ func SetupGin(r *gin.Engine) {
|
||||
} else {
|
||||
allowedOrigins := []string{
|
||||
config.Cfg.FrontendURL,
|
||||
"http://localhost:5173", // Development frontend
|
||||
"http://192.168.0.48:5173", // Development frontend
|
||||
"http://192.168.0.36:5173", // Development frontend
|
||||
"https://bamort.trokan.de", // Production frontend
|
||||
"http://wails.localhost", // Wails desktop WebView
|
||||
"http://localhost:5173", // Development frontend
|
||||
"http://192.168.0.48:5173", // Development frontend
|
||||
"http://192.168.0.36:5173", // Development frontend
|
||||
"https://conorga.trokan.de", // Production frontend
|
||||
"http://wails.localhost", // Wails desktop WebView
|
||||
}
|
||||
corsConfig = cors.Config{
|
||||
AllowOrigins: allowedOrigins,
|
||||
|
||||
Reference in New Issue
Block a user