refactor(api): enforce protocol-neutral service boundaries

- refactor: move HTTP status and DTO concerns out of model and service
  layers into API and handler code.
- feat: add admin service boundary and route auth through services
  instead of direct repository access.
- test: add architecture and error tests covering package boundaries,
  redaction, and service behavior.
- docs: record the protocol-neutral boundary decision and update
  architecture and roadmap notes.
This commit is contained in:
2026-07-05 23:30:17 +08:00
parent 28e17a5b08
commit 63ede5c237
34 changed files with 1028 additions and 438 deletions
+3 -4
View File
@@ -9,12 +9,11 @@ import (
)
func setupProtectedRoutes(rg *gin.RouterGroup, webApp *app.WebApp) {
jwtSecret := []byte(webApp.Config.JWT.Secret)
accountHandler := handler.NewAccountHandler(webApp.AuthService)
fileHandler := handler.NewFileHandler(webApp.FileService)
adminHandler := handler.NewAdminHandler(webApp.UserRepo)
adminHandler := handler.NewAdminHandler(webApp.AdminService)
rg.Use(middleware.AuthRequired(jwtSecret))
rg.Use(middleware.AuthRequired(webApp.AuthService))
account := rg.Group("/account")
{
@@ -39,7 +38,7 @@ func setupProtectedRoutes(rg *gin.RouterGroup, webApp *app.WebApp) {
}
admin := rg.Group("/admin")
admin.Use(middleware.AdminRequired(webApp.UserRepo))
admin.Use(middleware.AdminRequired())
{
admin.GET("/users", adminHandler.ListUsers)
admin.GET("/users/:id", adminHandler.GetUser)
+3 -2
View File
@@ -25,7 +25,7 @@ func TestVersionRoute(t *testing.T) {
},
}
authService := service.NewAuthService(nil, nil, nil, nil, 15*time.Minute, 7*24*time.Hour)
webApp := app.NewWebApp(cfg, nil, nil, nil, nil, nil, authService, nil, nil)
webApp := app.NewWebApp(cfg, nil, nil, nil, nil, nil, authService, nil, nil, nil)
router := NewRouter(webApp)
req := httptest.NewRequest(http.MethodGet, "/api/v1/version", nil)
@@ -84,6 +84,7 @@ func TestAdminRoutes(t *testing.T) {
refreshTTL := 168 * time.Hour
authService := service.NewAuthService(userRepo, sessionRepo, credentialRepo, jwtSecret, accessTTL, refreshTTL)
adminService := service.NewAdminService(userRepo)
cfg := &config.Config{
JWT: config.JWTConfig{
@@ -93,7 +94,7 @@ func TestAdminRoutes(t *testing.T) {
},
}
webApp := app.NewWebApp(cfg, db, userRepo, sessionRepo, nil, credentialRepo, authService, nil, nil)
webApp := app.NewWebApp(cfg, db, userRepo, sessionRepo, nil, credentialRepo, authService, adminService, nil, nil)
router := NewRouter(webApp)
// Helper: register a user via POST /api/v1/auth/register and return the user ID.