diff --git a/common/err/common.go b/common/err/common.go new file mode 100644 index 0000000..8be5e88 --- /dev/null +++ b/common/err/common.go @@ -0,0 +1,13 @@ +package err + +import ( + "net/http" + + "github.com/rogeecn/gen" +) + +var ( + BindBodyFailed = gen.NewBusError(http.StatusBadRequest, http.StatusBadRequest, "Body参数错误") + BindQueryFailed = gen.NewBusError(http.StatusBadRequest, http.StatusBadRequest, "Query参数错误") + BindPathFailed = gen.NewBusError(http.StatusBadRequest, http.StatusBadRequest, "Path参数错误: %s") +) diff --git a/common/request/page.go b/common/request/page.go new file mode 100644 index 0000000..ea2ff23 --- /dev/null +++ b/common/request/page.go @@ -0,0 +1,6 @@ +package request + +type PageFilter struct { + Page uint64 `form:"page"` + Limit uint64 `form:"limit"` +} diff --git a/common/response/page.go b/common/response/page.go new file mode 100644 index 0000000..6dcc588 --- /dev/null +++ b/common/response/page.go @@ -0,0 +1,6 @@ +package response + +type PageResponse[T any] struct { + Items []T `json:"items,omitempty"` + Total uint64 `json:"total,omitempty"` +} diff --git a/database/seeders/sys_role.go b/database/seeders/sys_role.go new file mode 100755 index 0000000..e66bdf1 --- /dev/null +++ b/database/seeders/sys_role.go @@ -0,0 +1,47 @@ +package seeders + +import ( + "atom/container" + "atom/contracts" + "atom/database/models" + "log" + + "github.com/brianvoe/gofakeit/v6" + "go.uber.org/dig" + "gorm.io/gorm" +) + +func init() { + if err := container.Container.Provide(NewSysRoleSeeder, dig.Group("seeders")); err != nil { + log.Fatal(err) + } +} + +type SysRoleSeeder struct { +} + +func NewSysRoleSeeder() contracts.Seeder { + return &SysRoleSeeder{} +} + +func (s *SysRoleSeeder) Run(faker *gofakeit.Faker, db *gorm.DB) { + times := 10 + for i := 0; i < times; i++ { + data := s.Generate(faker, i) + if i == 0 { + stmt := &gorm.Statement{DB: db} + _ = stmt.Parse(&data) + log.Printf("seeding %s for %d times", stmt.Schema.Table, times) + } + db.Create(&data) + } +} + +func (s *SysRoleSeeder) Generate(faker *gofakeit.Faker, idx int) models.SysRole { + return models.SysRole{ + UUID: faker.UUID(), + Name: faker.Name(), + ParentID: uint64(faker.IntRange(1, 100)), + DefaultRouter: faker.Name(), + } +} diff --git a/go.mod b/go.mod index 0a398b3..38e605e 100644 --- a/go.mod +++ b/go.mod @@ -1,6 +1,6 @@ module atom -go 1.18 +go 1.19 require ( github.com/brianvoe/gofakeit/v6 v6.20.1 diff --git a/modules/auth/container/container.go b/modules/auth/container/container.go index 456b021..6660182 100755 --- a/modules/auth/container/container.go +++ b/modules/auth/container/container.go @@ -5,6 +5,7 @@ import ( "atom/modules/auth/controller" "atom/modules/auth/dao" "atom/modules/auth/routes" + "atom/modules/auth/service" "log" "go.uber.org/dig" @@ -22,6 +23,9 @@ func init() { } //service + if err := container.Container.Provide(service.NewRoleService); err != nil { + log.Fatal(err) + } // dao if err := container.Container.Provide(dao.NewRoleDao); err != nil { diff --git a/modules/auth/controller/role.go b/modules/auth/controller/role.go index 341e579..99cdbf0 100755 --- a/modules/auth/controller/role.go +++ b/modules/auth/controller/role.go @@ -1,28 +1,50 @@ package controller import ( + "atom/common/request" + "atom/common/response" + "atom/database/models" "atom/modules/auth/dto" - "atom/providers/config" + "atom/modules/auth/service" "github.com/gin-gonic/gin" ) type RoleController interface { - GetName(*gin.Context) (string, error) + GetByFilter(*gin.Context, dto.RoleRequestFilter, request.PageFilter) (*response.PageResponse[*models.SysRole], error) + Create(*gin.Context, dto.RoleRequestForm) error + Delete(*gin.Context, int) error + UpdateByID(*gin.Context, int, dto.RoleRequestForm) error } type roleControllerImpl struct { - conf *config.Config + roleSvc service.RoleService } -func NewRoleController(conf *config.Config) RoleController { - return &roleControllerImpl{conf: conf} +func NewRoleController( + roleSvc service.RoleService, +) RoleController { + return &roleControllerImpl{ + roleSvc: roleSvc, + } } -func (c *roleControllerImpl) GetName(ctx *gin.Context) (string, error) { - return "Role", nil +func (c *roleControllerImpl) GetByFilter( + ctx *gin.Context, + filter dto.RoleRequestFilter, + page request.PageFilter, +) (*response.PageResponse[*models.SysRole], error) { + return c.roleSvc.GetByFilter(ctx, filter, page) } -func (c *roleControllerImpl) Create(ctx *gin.Context, req *dto.RoleCreateRequest) error { - return nil +func (c *roleControllerImpl) Create(ctx *gin.Context, req dto.RoleRequestForm) error { + _, err := c.roleSvc.Create(ctx, req) + return err +} +func (c *roleControllerImpl) UpdateByID(ctx *gin.Context, id int, req dto.RoleRequestForm) error { + _, err := c.roleSvc.UpdateByID(ctx, uint64(id), req) + return err +} +func (c *roleControllerImpl) Delete(ctx *gin.Context, id int) error { + return c.roleSvc.DeleteByID(ctx, uint64(id)) } diff --git a/modules/auth/dao/role.go b/modules/auth/dao/role.go index 0e2b595..49eb73f 100755 --- a/modules/auth/dao/role.go +++ b/modules/auth/dao/role.go @@ -1,12 +1,15 @@ package dao import ( + "atom/common/request" "atom/database/models" "atom/database/query" + "atom/modules/auth/dto" "context" ) type RoleDao interface { + GetByFilter(context.Context, dto.RoleRequestFilter, request.PageFilter) ([]*models.SysRole, uint64, error) FindByID(context.Context, uint64) (*models.SysRole, error) Create(context.Context, *models.SysRole) (*models.SysRole, error) UpdateByID(context.Context, *models.SysRole) (*models.SysRole, error) @@ -22,6 +25,35 @@ func NewRoleDao(query *query.Query) RoleDao { return &roleDaoImpl{query: query} } +func (dao *roleDaoImpl) GetByFilter(ctx context.Context, filter dto.RoleRequestFilter, page request.PageFilter) ([]*models.SysRole, uint64, error) { + role := dao.query.SysRole + query := role.WithContext(ctx) + + if filter.DefaultRouter != nil { + query = query.Where(role.DefaultRouter.Eq(*filter.DefaultRouter)) + } + + if filter.Name != nil { + query = query.Where(role.Name.Like(*filter.Name)) + } + + if filter.ParentID != nil { + query = query.Where(role.ParentID.Eq(uint64(*filter.ParentID))) + } + + total, err := query.Count() + if err != nil { + return nil, 0, err + } + + items, err := query.Find() + if err != nil { + return nil, 0, err + } + + return items, uint64(total), nil +} + func (dao *roleDaoImpl) FindByID(ctx context.Context, id uint64) (*models.SysRole, error) { role := dao.query.SysRole return role.WithContext(ctx).Where(role.ID.Eq(id)).First() diff --git a/modules/auth/dto/role.go b/modules/auth/dto/role.go index 3bff91a..a60a62e 100644 --- a/modules/auth/dto/role.go +++ b/modules/auth/dto/role.go @@ -1,7 +1,12 @@ package dto -type RoleCreateRequest struct { - UUID string `json:"alias,omitempty"` +type RoleRequestFilter struct { + Name *string `form:"name"` + ParentID *uint `form:"parent_id"` + DefaultRouter *string `form:"default_router"` +} + +type RoleRequestForm struct { Name string `json:"name,omitempty"` ParentID uint `json:"parent_id,omitempty"` DefaultRouter string `json:"default_router,omitempty"` diff --git a/modules/auth/routes/routes.go b/modules/auth/routes/routes.go index 4f98e74..afb979e 100755 --- a/modules/auth/routes/routes.go +++ b/modules/auth/routes/routes.go @@ -1,8 +1,11 @@ package routes import ( + "atom/common/err" + "atom/common/request" "atom/contracts" "atom/modules/auth/controller" + "atom/modules/auth/dto" "atom/providers/http" "github.com/rogeecn/gen" @@ -29,9 +32,29 @@ func NewRoute( func (r *Route) Register() { group := r.svc.Engine.Group("auth") { - roleGroup := group.Group("role") + roleGroup := group.Group("roles") { - roleGroup.GET("/roles", gen.DataFunc(r.role.GetName)) + roleGroup.GET("", gen.DataFunc2( + r.role.GetByFilter, + gen.BindQuery(dto.RoleRequestFilter{}, err.BindQueryFailed), + gen.BindQuery(request.PageFilter{}, err.BindQueryFailed), + )) + + roleGroup.POST("", gen.Func1( + r.role.Create, + gen.BindBody(dto.RoleRequestForm{}, err.BindBodyFailed), + )) + + roleGroup.PUT("/:id", gen.Func2( + r.role.UpdateByID, + gen.Int("role_id", err.BindPathFailed.Format("id")), + gen.BindBody(dto.RoleRequestForm{}, err.BindBodyFailed), + )) + + roleGroup.DELETE("/:id", gen.Func1( + r.role.Delete, + gen.Int("role_id", err.BindPathFailed.Format("id")), + )) } permissionGroup := group.Group("permission") diff --git a/modules/auth/service/role.go b/modules/auth/service/role.go index 0eed7c3..901c28e 100755 --- a/modules/auth/service/role.go +++ b/modules/auth/service/role.go @@ -1,20 +1,75 @@ package service import ( + "atom/common/request" + "atom/common/response" + "atom/database/models" + "atom/modules/auth/dao" + "atom/modules/auth/dto" + "atom/providers/uuid" "context" ) type RoleService interface { - Create(ctx context.Context) error + GetByFilter(context.Context, dto.RoleRequestFilter, request.PageFilter) (*response.PageResponse[*models.SysRole], error) + Create(context.Context, dto.RoleRequestForm) (*models.SysRole, error) + UpdateByID(context.Context, uint64, dto.RoleRequestForm) (*models.SysRole, error) + DeleteByID(context.Context, uint64) error } type roleService struct { + dao dao.RoleDao + uuid *uuid.Generator } -func NewRoleService() RoleService { - return &roleService{} +func NewRoleService( + dao dao.RoleDao, + uuid *uuid.Generator, +) RoleService { + return &roleService{ + dao: dao, + uuid: uuid, + } } -func (svc *roleService) Create(ctx context.Context) error { - return nil +func (svc *roleService) GetByFilter( + ctx context.Context, + filter dto.RoleRequestFilter, + page request.PageFilter, +) (*response.PageResponse[*models.SysRole], error) { + items, count, err := svc.dao.GetByFilter(ctx, filter, page) + if err != nil { + return nil, err + } + + return &response.PageResponse[*models.SysRole]{ + Items: items, + Total: count, + }, nil +} + +func (svc *roleService) Create(ctx context.Context, req dto.RoleRequestForm) (*models.SysRole, error) { + model := models.SysRole{ + UUID: svc.uuid.MustGenerate(), + Name: req.Name, + ParentID: uint64(req.ParentID), + DefaultRouter: req.DefaultRouter, + } + return svc.dao.Create(ctx, &model) +} +func (svc *roleService) UpdateByID(ctx context.Context, id uint64, req dto.RoleRequestForm) (*models.SysRole, error) { + model, err := svc.dao.FindByID(ctx, id) + if err != nil { + return nil, err + } + + model.Name = req.Name + model.ParentID = uint64(req.ParentID) + model.DefaultRouter = req.DefaultRouter + + return svc.dao.UpdateByID(ctx, model) +} + +func (svc *roleService) DeleteByID(ctx context.Context, id uint64) error { + return svc.dao.DeleteByID(ctx, id) } diff --git a/providers/provider.go b/providers/provider.go index ad63e8c..952d1c6 100644 --- a/providers/provider.go +++ b/providers/provider.go @@ -11,4 +11,5 @@ import ( _ "atom/providers/log" _ "atom/providers/query" _ "atom/providers/single_flight" + _ "atom/providers/uuid" ) diff --git a/providers/uuid/uuid.go b/providers/uuid/uuid.go new file mode 100644 index 0000000..8e7e0da --- /dev/null +++ b/providers/uuid/uuid.go @@ -0,0 +1,37 @@ +package uuid + +import ( + "atom/container" + "log" + + "github.com/gofrs/uuid" +) + +func init() { + if err := container.Container.Provide(NewUUID); err != nil { + log.Fatal(err) + } +} + +type Generator struct { + generator uuid.Generator +} + +func NewUUID() (*Generator, error) { + return &Generator{ + generator: uuid.DefaultGenerator, + }, nil +} + +func (u *Generator) MustGenerate() string { + uuid, _ := u.Generate() + return uuid +} + +func (u *Generator) Generate() (string, error) { + uuid, err := u.generator.NewV4() + if err != nil { + return "", err + } + return uuid.String(), err +}