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
+7 -7
View File
@@ -9,17 +9,17 @@ import (
"github.com/dhao2001/mygo/internal/api"
"github.com/dhao2001/mygo/internal/model"
"github.com/dhao2001/mygo/internal/repository"
"github.com/dhao2001/mygo/internal/service"
)
// AdminHandler handles admin-only endpoints for user management.
type AdminHandler struct {
userRepo repository.UserRepository
adminService *service.AdminService
}
// NewAdminHandler creates an AdminHandler.
func NewAdminHandler(userRepo repository.UserRepository) *AdminHandler {
return &AdminHandler{userRepo: userRepo}
func NewAdminHandler(adminService *service.AdminService) *AdminHandler {
return &AdminHandler{adminService: adminService}
}
// adminUserResponse exposes all user fields, including status, for admin views.
@@ -55,7 +55,7 @@ func toAdminResponse(u *model.User) adminUserResponse {
func (h *AdminHandler) DeleteUser(c *gin.Context) {
id := c.Param("id")
if err := h.userRepo.Delete(c.Request.Context(), id); err != nil {
if err := h.adminService.DeleteUser(c.Request.Context(), id); err != nil {
api.RespondError(c, err)
return
}
@@ -67,7 +67,7 @@ func (h *AdminHandler) DeleteUser(c *gin.Context) {
func (h *AdminHandler) GetUser(c *gin.Context) {
id := c.Param("id")
user, err := h.userRepo.FindByIDIncludeDeleted(c.Request.Context(), id)
user, err := h.adminService.GetUser(c.Request.Context(), id)
if err != nil {
api.RespondError(c, err)
return
@@ -93,7 +93,7 @@ func (h *AdminHandler) ListUsers(c *gin.Context) {
limit = 200
}
users, total, err := h.userRepo.ListIncludeDeleted(c.Request.Context(), offset, limit)
users, total, err := h.adminService.ListUsers(c.Request.Context(), offset, limit)
if err != nil {
api.RespondError(c, err)
return