refactor: admin 模块按 handler/model/service 分层
This commit is contained in:
@@ -0,0 +1,56 @@
|
||||
package admin
|
||||
|
||||
import (
|
||||
"time"
|
||||
|
||||
"github.com/gin-gonic/gin"
|
||||
"gorm.io/gorm"
|
||||
|
||||
adminhandler "wx_service/internal/admin/handler"
|
||||
adminmodel "wx_service/internal/admin/model"
|
||||
adminservice "wx_service/internal/admin/service"
|
||||
)
|
||||
|
||||
type Admin = adminmodel.Admin
|
||||
type Handler = adminhandler.Handler
|
||||
type Service = adminservice.Service
|
||||
type Claims = adminservice.Claims
|
||||
|
||||
type LoginResult = adminservice.LoginResult
|
||||
type ListMiniProgramsQuery = adminservice.ListMiniProgramsQuery
|
||||
type MiniProgramItem = adminservice.MiniProgramItem
|
||||
type ListMiniProgramsResult = adminservice.ListMiniProgramsResult
|
||||
type CreateMiniProgramInput = adminservice.CreateMiniProgramInput
|
||||
type UpdateMiniProgramInput = adminservice.UpdateMiniProgramInput
|
||||
type MiniProgramDetailStats = adminservice.MiniProgramDetailStats
|
||||
type OverviewStats = adminservice.OverviewStats
|
||||
type MiniProgramStatsItem = adminservice.MiniProgramStatsItem
|
||||
type UserGrowthPoint = adminservice.UserGrowthPoint
|
||||
|
||||
var (
|
||||
ErrInvalidCredentials = adminservice.ErrInvalidCredentials
|
||||
ErrInvalidToken = adminservice.ErrInvalidToken
|
||||
ErrMissingJWTSecret = adminservice.ErrMissingJWTSecret
|
||||
ErrMiniProgramNotFound = adminservice.ErrMiniProgramNotFound
|
||||
ErrMiniProgramHasUsers = adminservice.ErrMiniProgramHasUsers
|
||||
ErrMiniProgramAppIDUsed = adminservice.ErrMiniProgramAppIDUsed
|
||||
ErrInvalidInput = adminservice.ErrInvalidInput
|
||||
)
|
||||
|
||||
const ContextAdminClaimsKey = adminhandler.ContextAdminClaimsKey
|
||||
|
||||
func NewService(db *gorm.DB, jwtSecret string, tokenTTL time.Duration, defaultUsername, defaultPassword string) *Service {
|
||||
return adminservice.NewService(db, jwtSecret, tokenTTL, defaultUsername, defaultPassword)
|
||||
}
|
||||
|
||||
func NewHandler(svc *Service) *Handler {
|
||||
return adminhandler.NewHandler(svc)
|
||||
}
|
||||
|
||||
func AuthMiddleware(svc *Service) gin.HandlerFunc {
|
||||
return adminhandler.AuthMiddleware(svc)
|
||||
}
|
||||
|
||||
func CurrentAdminClaims(c *gin.Context) (*Claims, bool) {
|
||||
return adminhandler.CurrentAdminClaims(c)
|
||||
}
|
||||
@@ -1,4 +1,4 @@
|
||||
package admin
|
||||
package handler
|
||||
|
||||
import (
|
||||
"errors"
|
||||
@@ -6,6 +6,7 @@ import (
|
||||
|
||||
"github.com/gin-gonic/gin"
|
||||
|
||||
adminservice "wx_service/internal/admin/service"
|
||||
"wx_service/internal/model"
|
||||
)
|
||||
|
||||
@@ -24,11 +25,11 @@ func (h *Handler) Login(c *gin.Context) {
|
||||
result, err := h.svc.Login(c.Request.Context(), req.Username, req.Password)
|
||||
if err != nil {
|
||||
switch {
|
||||
case errors.Is(err, ErrInvalidCredentials):
|
||||
case errors.Is(err, adminservice.ErrInvalidCredentials):
|
||||
c.JSON(http.StatusUnauthorized, model.Error(http.StatusUnauthorized, "用户名或密码错误"))
|
||||
case errors.Is(err, ErrMissingJWTSecret):
|
||||
case errors.Is(err, adminservice.ErrMissingJWTSecret):
|
||||
c.JSON(http.StatusServiceUnavailable, model.Error(http.StatusServiceUnavailable, "管理员认证未配置,请检查 JWT_SECRET"))
|
||||
case errors.Is(err, ErrInvalidInput):
|
||||
case errors.Is(err, adminservice.ErrInvalidInput):
|
||||
c.JSON(http.StatusBadRequest, model.Error(http.StatusBadRequest, "用户名和密码不能为空"))
|
||||
default:
|
||||
c.JSON(http.StatusInternalServerError, model.Error(http.StatusInternalServerError, "admin login failed"))
|
||||
@@ -1,4 +1,4 @@
|
||||
package admin
|
||||
package handler
|
||||
|
||||
import (
|
||||
"errors"
|
||||
@@ -6,13 +6,15 @@ import (
|
||||
"strings"
|
||||
|
||||
"github.com/gin-gonic/gin"
|
||||
|
||||
adminservice "wx_service/internal/admin/service"
|
||||
)
|
||||
|
||||
type Handler struct {
|
||||
svc *Service
|
||||
svc *adminservice.Service
|
||||
}
|
||||
|
||||
func NewHandler(svc *Service) *Handler {
|
||||
func NewHandler(svc *adminservice.Service) *Handler {
|
||||
return &Handler{svc: svc}
|
||||
}
|
||||
|
||||
@@ -1,4 +1,4 @@
|
||||
package admin
|
||||
package handler
|
||||
|
||||
import (
|
||||
"net/http"
|
||||
@@ -6,12 +6,13 @@ import (
|
||||
|
||||
"github.com/gin-gonic/gin"
|
||||
|
||||
adminservice "wx_service/internal/admin/service"
|
||||
"wx_service/internal/model"
|
||||
)
|
||||
|
||||
const ContextAdminClaimsKey = "adminClaims"
|
||||
|
||||
func AuthMiddleware(svc *Service) gin.HandlerFunc {
|
||||
func AuthMiddleware(svc *adminservice.Service) gin.HandlerFunc {
|
||||
return func(c *gin.Context) {
|
||||
token := extractBearerToken(c.GetHeader("Authorization"))
|
||||
if token == "" {
|
||||
@@ -30,12 +31,12 @@ func AuthMiddleware(svc *Service) gin.HandlerFunc {
|
||||
}
|
||||
}
|
||||
|
||||
func CurrentAdminClaims(c *gin.Context) (*Claims, bool) {
|
||||
func CurrentAdminClaims(c *gin.Context) (*adminservice.Claims, bool) {
|
||||
value, ok := c.Get(ContextAdminClaimsKey)
|
||||
if !ok {
|
||||
return nil, false
|
||||
}
|
||||
claims, ok := value.(*Claims)
|
||||
claims, ok := value.(*adminservice.Claims)
|
||||
return claims, ok
|
||||
}
|
||||
|
||||
+14
-13
@@ -1,4 +1,4 @@
|
||||
package admin
|
||||
package handler
|
||||
|
||||
import (
|
||||
"errors"
|
||||
@@ -8,6 +8,7 @@ import (
|
||||
|
||||
"github.com/gin-gonic/gin"
|
||||
|
||||
adminservice "wx_service/internal/admin/service"
|
||||
"wx_service/internal/model"
|
||||
)
|
||||
|
||||
@@ -15,7 +16,7 @@ func (h *Handler) ListMiniPrograms(c *gin.Context) {
|
||||
page, _ := strconv.Atoi(strings.TrimSpace(c.DefaultQuery("page", "1")))
|
||||
pageSize, _ := strconv.Atoi(strings.TrimSpace(c.DefaultQuery("page_size", "20")))
|
||||
|
||||
data, err := h.svc.ListMiniPrograms(c.Request.Context(), ListMiniProgramsQuery{
|
||||
data, err := h.svc.ListMiniPrograms(c.Request.Context(), adminservice.ListMiniProgramsQuery{
|
||||
Page: page,
|
||||
PageSize: pageSize,
|
||||
Keyword: c.Query("keyword"),
|
||||
@@ -36,7 +37,7 @@ func (h *Handler) GetMiniProgram(c *gin.Context) {
|
||||
|
||||
data, err := h.svc.GetMiniProgram(c.Request.Context(), id)
|
||||
if err != nil {
|
||||
if errors.Is(err, ErrMiniProgramNotFound) {
|
||||
if errors.Is(err, adminservice.ErrMiniProgramNotFound) {
|
||||
c.JSON(http.StatusNotFound, model.Error(http.StatusNotFound, "mini program not found"))
|
||||
return
|
||||
}
|
||||
@@ -55,7 +56,7 @@ func (h *Handler) GetMiniProgramStats(c *gin.Context) {
|
||||
|
||||
data, err := h.svc.GetMiniProgramStats(c.Request.Context(), id)
|
||||
if err != nil {
|
||||
if errors.Is(err, ErrMiniProgramNotFound) {
|
||||
if errors.Is(err, adminservice.ErrMiniProgramNotFound) {
|
||||
c.JSON(http.StatusNotFound, model.Error(http.StatusNotFound, "mini program not found"))
|
||||
return
|
||||
}
|
||||
@@ -79,7 +80,7 @@ func (h *Handler) CreateMiniProgram(c *gin.Context) {
|
||||
return
|
||||
}
|
||||
|
||||
data, err := h.svc.CreateMiniProgram(c.Request.Context(), CreateMiniProgramInput{
|
||||
data, err := h.svc.CreateMiniProgram(c.Request.Context(), adminservice.CreateMiniProgramInput{
|
||||
Name: req.Name,
|
||||
AppID: req.AppID,
|
||||
AppSecret: req.AppSecret,
|
||||
@@ -87,9 +88,9 @@ func (h *Handler) CreateMiniProgram(c *gin.Context) {
|
||||
})
|
||||
if err != nil {
|
||||
switch {
|
||||
case errors.Is(err, ErrInvalidInput):
|
||||
case errors.Is(err, adminservice.ErrInvalidInput):
|
||||
c.JSON(http.StatusBadRequest, model.Error(http.StatusBadRequest, "name/app_id/app_secret are required"))
|
||||
case errors.Is(err, ErrMiniProgramAppIDUsed):
|
||||
case errors.Is(err, adminservice.ErrMiniProgramAppIDUsed):
|
||||
c.JSON(http.StatusBadRequest, model.Error(http.StatusBadRequest, "app_id already exists"))
|
||||
default:
|
||||
c.JSON(http.StatusInternalServerError, model.Error(http.StatusInternalServerError, "create mini-program failed"))
|
||||
@@ -119,7 +120,7 @@ func (h *Handler) UpdateMiniProgram(c *gin.Context) {
|
||||
return
|
||||
}
|
||||
|
||||
data, err := h.svc.UpdateMiniProgram(c.Request.Context(), id, UpdateMiniProgramInput{
|
||||
data, err := h.svc.UpdateMiniProgram(c.Request.Context(), id, adminservice.UpdateMiniProgramInput{
|
||||
Name: req.Name,
|
||||
AppID: req.AppID,
|
||||
AppSecret: req.AppSecret,
|
||||
@@ -127,11 +128,11 @@ func (h *Handler) UpdateMiniProgram(c *gin.Context) {
|
||||
})
|
||||
if err != nil {
|
||||
switch {
|
||||
case errors.Is(err, ErrMiniProgramNotFound):
|
||||
case errors.Is(err, adminservice.ErrMiniProgramNotFound):
|
||||
c.JSON(http.StatusNotFound, model.Error(http.StatusNotFound, "mini program not found"))
|
||||
case errors.Is(err, ErrInvalidInput):
|
||||
case errors.Is(err, adminservice.ErrInvalidInput):
|
||||
c.JSON(http.StatusBadRequest, model.Error(http.StatusBadRequest, "name/app_id are required"))
|
||||
case errors.Is(err, ErrMiniProgramAppIDUsed):
|
||||
case errors.Is(err, adminservice.ErrMiniProgramAppIDUsed):
|
||||
c.JSON(http.StatusBadRequest, model.Error(http.StatusBadRequest, "app_id already exists"))
|
||||
default:
|
||||
c.JSON(http.StatusInternalServerError, model.Error(http.StatusInternalServerError, "update mini-program failed"))
|
||||
@@ -151,9 +152,9 @@ func (h *Handler) DeleteMiniProgram(c *gin.Context) {
|
||||
err = h.svc.DeleteMiniProgram(c.Request.Context(), id)
|
||||
if err != nil {
|
||||
switch {
|
||||
case errors.Is(err, ErrMiniProgramNotFound):
|
||||
case errors.Is(err, adminservice.ErrMiniProgramNotFound):
|
||||
c.JSON(http.StatusNotFound, model.Error(http.StatusNotFound, "mini program not found"))
|
||||
case errors.Is(err, ErrMiniProgramHasUsers):
|
||||
case errors.Is(err, adminservice.ErrMiniProgramHasUsers):
|
||||
c.JSON(http.StatusBadRequest, model.Error(http.StatusBadRequest, "mini program has related users"))
|
||||
default:
|
||||
c.JSON(http.StatusInternalServerError, model.Error(http.StatusInternalServerError, "delete mini-program failed"))
|
||||
@@ -1,4 +1,4 @@
|
||||
package admin
|
||||
package handler
|
||||
|
||||
import (
|
||||
"net/http"
|
||||
@@ -1,4 +1,4 @@
|
||||
package admin
|
||||
package model
|
||||
|
||||
import (
|
||||
"time"
|
||||
@@ -1,4 +1,4 @@
|
||||
package admin
|
||||
package service
|
||||
|
||||
import (
|
||||
"context"
|
||||
@@ -7,6 +7,8 @@ import (
|
||||
"strings"
|
||||
"time"
|
||||
|
||||
adminmodel "wx_service/internal/admin/model"
|
||||
|
||||
"github.com/golang-jwt/jwt/v5"
|
||||
"golang.org/x/crypto/bcrypt"
|
||||
"gorm.io/gorm"
|
||||
@@ -14,7 +16,7 @@ import (
|
||||
|
||||
func (s *Service) EnsureDefaultAdmin(ctx context.Context) error {
|
||||
var count int64
|
||||
if err := s.db.WithContext(ctx).Model(&Admin{}).Count(&count).Error; err != nil {
|
||||
if err := s.db.WithContext(ctx).Model(&adminmodel.Admin{}).Count(&count).Error; err != nil {
|
||||
return err
|
||||
}
|
||||
if count > 0 {
|
||||
@@ -35,7 +37,7 @@ func (s *Service) EnsureDefaultAdmin(ctx context.Context) error {
|
||||
return err
|
||||
}
|
||||
|
||||
record := &Admin{
|
||||
record := &adminmodel.Admin{
|
||||
Username: username,
|
||||
Password: string(hashedPassword),
|
||||
Role: "super_admin",
|
||||
@@ -51,7 +53,7 @@ func (s *Service) EnsureDefaultAdmin(ctx context.Context) error {
|
||||
|
||||
type LoginResult struct {
|
||||
Token string `json:"token"`
|
||||
Admin *Admin `json:"admin"`
|
||||
Admin *adminmodel.Admin `json:"admin"`
|
||||
}
|
||||
|
||||
func (s *Service) Login(ctx context.Context, username, password string) (*LoginResult, error) {
|
||||
@@ -60,7 +62,7 @@ func (s *Service) Login(ctx context.Context, username, password string) (*LoginR
|
||||
return nil, ErrInvalidInput
|
||||
}
|
||||
|
||||
var admin Admin
|
||||
var admin adminmodel.Admin
|
||||
if err := s.db.WithContext(ctx).Where("username = ?", username).First(&admin).Error; err != nil {
|
||||
if errors.Is(err, gorm.ErrRecordNotFound) {
|
||||
return nil, ErrInvalidCredentials
|
||||
@@ -111,7 +113,7 @@ func (s *Service) ParseToken(token string) (*Claims, error) {
|
||||
return claims, nil
|
||||
}
|
||||
|
||||
func (s *Service) generateToken(admin *Admin) (string, error) {
|
||||
func (s *Service) generateToken(admin *adminmodel.Admin) (string, error) {
|
||||
if len(s.jwtSecret) == 0 {
|
||||
return "", ErrMissingJWTSecret
|
||||
}
|
||||
@@ -132,8 +134,8 @@ func (s *Service) generateToken(admin *Admin) (string, error) {
|
||||
return t.SignedString(s.jwtSecret)
|
||||
}
|
||||
|
||||
func (s *Service) GetProfile(ctx context.Context, adminID uint) (*Admin, error) {
|
||||
var admin Admin
|
||||
func (s *Service) GetProfile(ctx context.Context, adminID uint) (*adminmodel.Admin, error) {
|
||||
var admin adminmodel.Admin
|
||||
if err := s.db.WithContext(ctx).
|
||||
Select("id", "username", "role", "last_login_at", "created_at", "updated_at").
|
||||
Where("id = ?", adminID).
|
||||
+1
-1
@@ -1,4 +1,4 @@
|
||||
package admin
|
||||
package service
|
||||
|
||||
import (
|
||||
"context"
|
||||
@@ -1,4 +1,4 @@
|
||||
package admin
|
||||
package service
|
||||
|
||||
import (
|
||||
"context"
|
||||
@@ -1,4 +1,4 @@
|
||||
package admin
|
||||
package service
|
||||
|
||||
import (
|
||||
"errors"
|
||||
Reference in New Issue
Block a user