任务三
This commit is contained in:
+128
-273
@@ -1,13 +1,12 @@
|
||||
package system
|
||||
|
||||
import (
|
||||
"context"
|
||||
|
||||
"kra/internal/biz/system"
|
||||
"kra/internal/server/middleware"
|
||||
types "kra/internal/service/types/system"
|
||||
|
||||
"github.com/go-kratos/kratos/v2/errors"
|
||||
"github.com/go-kratos/kratos/v2/transport/http"
|
||||
khttp "github.com/go-kratos/kratos/v2/transport/http"
|
||||
)
|
||||
|
||||
// ApiService API服务
|
||||
@@ -20,45 +19,30 @@ func NewApiService(uc *system.ApiUsecase) *ApiService {
|
||||
return &ApiService{uc: uc}
|
||||
}
|
||||
|
||||
// ApiInfo API信息
|
||||
type ApiInfo struct {
|
||||
ID uint `json:"ID"`
|
||||
Path string `json:"path"`
|
||||
Description string `json:"description"`
|
||||
ApiGroup string `json:"apiGroup"`
|
||||
Method string `json:"method"`
|
||||
}
|
||||
|
||||
// CreateApiRequest 创建API请求
|
||||
type CreateApiRequest struct {
|
||||
Path string `json:"path"`
|
||||
Description string `json:"description"`
|
||||
ApiGroup string `json:"apiGroup"`
|
||||
Method string `json:"method"`
|
||||
}
|
||||
|
||||
// CreateApi 创建API
|
||||
func (s *ApiService) CreateApi(ctx context.Context, req *CreateApiRequest) error {
|
||||
func (s *ApiService) CreateApi(ctx khttp.Context) error {
|
||||
var req types.CreateApiRequest
|
||||
if err := ctx.Bind(&req); err != nil {
|
||||
return err
|
||||
}
|
||||
api := &system.Api{
|
||||
Path: req.Path,
|
||||
Description: req.Description,
|
||||
ApiGroup: req.ApiGroup,
|
||||
Method: req.Method,
|
||||
}
|
||||
return s.uc.CreateApi(ctx, api)
|
||||
}
|
||||
|
||||
// UpdateApiRequest 更新API请求
|
||||
type UpdateApiRequest struct {
|
||||
ID uint `json:"ID"`
|
||||
Path string `json:"path"`
|
||||
Description string `json:"description"`
|
||||
ApiGroup string `json:"apiGroup"`
|
||||
Method string `json:"method"`
|
||||
if err := s.uc.CreateApi(ctx, api); err != nil {
|
||||
return errors.BadRequest("CREATE_FAILED", err.Error())
|
||||
}
|
||||
return ctx.Result(200, nil)
|
||||
}
|
||||
|
||||
// UpdateApi 更新API
|
||||
func (s *ApiService) UpdateApi(ctx context.Context, req *UpdateApiRequest) error {
|
||||
func (s *ApiService) UpdateApi(ctx khttp.Context) error {
|
||||
var req types.UpdateApiRequest
|
||||
if err := ctx.Bind(&req); err != nil {
|
||||
return err
|
||||
}
|
||||
api := &system.Api{
|
||||
ID: req.ID,
|
||||
Path: req.Path,
|
||||
@@ -66,55 +50,55 @@ func (s *ApiService) UpdateApi(ctx context.Context, req *UpdateApiRequest) error
|
||||
ApiGroup: req.ApiGroup,
|
||||
Method: req.Method,
|
||||
}
|
||||
return s.uc.UpdateApi(ctx, api)
|
||||
if err := s.uc.UpdateApi(ctx, api); err != nil {
|
||||
return errors.BadRequest("UPDATE_FAILED", err.Error())
|
||||
}
|
||||
return ctx.Result(200, nil)
|
||||
}
|
||||
|
||||
// DeleteApi 删除API
|
||||
func (s *ApiService) DeleteApi(ctx context.Context, id uint) error {
|
||||
return s.uc.DeleteApi(ctx, id)
|
||||
}
|
||||
|
||||
// DeleteApisByIdsRequest 批量删除API请求
|
||||
type DeleteApisByIdsRequest struct {
|
||||
Ids []uint `json:"ids"`
|
||||
func (s *ApiService) DeleteApi(ctx khttp.Context) error {
|
||||
var req types.DeleteApiRequest
|
||||
if err := ctx.Bind(&req); err != nil {
|
||||
return err
|
||||
}
|
||||
if err := s.uc.DeleteApi(ctx, req.ID); err != nil {
|
||||
return errors.BadRequest("DELETE_FAILED", err.Error())
|
||||
}
|
||||
return ctx.Result(200, nil)
|
||||
}
|
||||
|
||||
// DeleteApisByIds 批量删除API
|
||||
func (s *ApiService) DeleteApisByIds(ctx context.Context, req *DeleteApisByIdsRequest) error {
|
||||
return s.uc.DeleteApisByIds(ctx, req.Ids)
|
||||
func (s *ApiService) DeleteApisByIds(ctx khttp.Context) error {
|
||||
var req types.DeleteApisByIdsRequest
|
||||
if err := ctx.Bind(&req); err != nil {
|
||||
return err
|
||||
}
|
||||
if err := s.uc.DeleteApisByIds(ctx, req.Ids); err != nil {
|
||||
return errors.BadRequest("DELETE_FAILED", err.Error())
|
||||
}
|
||||
return ctx.Result(200, nil)
|
||||
}
|
||||
|
||||
// GetApiById 根据ID获取API
|
||||
func (s *ApiService) GetApiById(ctx context.Context, id uint) (*ApiInfo, error) {
|
||||
api, err := s.uc.GetApiById(ctx, id)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
func (s *ApiService) GetApiById(ctx khttp.Context) error {
|
||||
var req types.GetApiByIdRequest
|
||||
if err := ctx.Bind(&req); err != nil {
|
||||
return err
|
||||
}
|
||||
return toApiInfo(api), nil
|
||||
}
|
||||
|
||||
// GetApiListRequest 获取API列表请求
|
||||
type GetApiListRequest struct {
|
||||
Page int `json:"page"`
|
||||
PageSize int `json:"pageSize"`
|
||||
Path string `json:"path"`
|
||||
Description string `json:"description"`
|
||||
Method string `json:"method"`
|
||||
ApiGroup string `json:"apiGroup"`
|
||||
OrderKey string `json:"orderKey"`
|
||||
Desc bool `json:"desc"`
|
||||
}
|
||||
|
||||
// GetApiListResponse 获取API列表响应
|
||||
type GetApiListResponse struct {
|
||||
List []*ApiInfo `json:"list"`
|
||||
Total int64 `json:"total"`
|
||||
Page int `json:"page"`
|
||||
PageSize int `json:"pageSize"`
|
||||
api, err := s.uc.GetApiById(ctx, req.ID)
|
||||
if err != nil {
|
||||
return errors.NotFound("NOT_FOUND", err.Error())
|
||||
}
|
||||
return ctx.Result(200, &types.GetApiByIdReply{Api: toTypesApiInfo(api)})
|
||||
}
|
||||
|
||||
// GetApiList 获取API列表
|
||||
func (s *ApiService) GetApiList(ctx context.Context, req *GetApiListRequest) (*GetApiListResponse, error) {
|
||||
func (s *ApiService) GetApiList(ctx khttp.Context) error {
|
||||
var req types.GetApiListRequest
|
||||
if err := ctx.Bind(&req); err != nil {
|
||||
return err
|
||||
}
|
||||
filters := make(map[string]string)
|
||||
if req.Path != "" {
|
||||
filters["path"] = req.Path
|
||||
@@ -128,94 +112,71 @@ func (s *ApiService) GetApiList(ctx context.Context, req *GetApiListRequest) (*G
|
||||
if req.ApiGroup != "" {
|
||||
filters["api_group"] = req.ApiGroup
|
||||
}
|
||||
|
||||
apis, total, err := s.uc.GetAPIInfoList(ctx, req.Page, req.PageSize, filters, req.OrderKey, req.Desc)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
return errors.InternalServer("LIST_ERROR", err.Error())
|
||||
}
|
||||
|
||||
list := make([]*ApiInfo, len(apis))
|
||||
list := make([]types.ApiInfo, len(apis))
|
||||
for i, api := range apis {
|
||||
list[i] = toApiInfo(api)
|
||||
list[i] = toTypesApiInfo(api)
|
||||
}
|
||||
|
||||
return &GetApiListResponse{
|
||||
List: list,
|
||||
Total: total,
|
||||
Page: req.Page,
|
||||
PageSize: req.PageSize,
|
||||
}, nil
|
||||
return ctx.Result(200, &types.GetApiListReply{List: list, Total: total, Page: req.Page, PageSize: req.PageSize})
|
||||
}
|
||||
|
||||
// GetAllApis 获取所有API
|
||||
func (s *ApiService) GetAllApis(ctx context.Context, authorityID uint) ([]*ApiInfo, error) {
|
||||
func (s *ApiService) GetAllApis(ctx khttp.Context) error {
|
||||
authorityID := middleware.GetAuthorityID(ctx)
|
||||
apis, err := s.uc.GetAllApis(ctx, authorityID)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
return errors.InternalServer("LIST_ERROR", err.Error())
|
||||
}
|
||||
list := make([]*ApiInfo, len(apis))
|
||||
list := make([]types.ApiInfo, len(apis))
|
||||
for i, api := range apis {
|
||||
list[i] = toApiInfo(api)
|
||||
list[i] = toTypesApiInfo(api)
|
||||
}
|
||||
return list, nil
|
||||
return ctx.Result(200, &types.GetAllApisReply{Apis: list})
|
||||
}
|
||||
|
||||
// GetApiGroups 获取API分组
|
||||
func (s *ApiService) GetApiGroups(ctx context.Context) ([]string, map[string]string, error) {
|
||||
return s.uc.GetApiGroups(ctx)
|
||||
}
|
||||
|
||||
// SyncApiResponse 同步API响应
|
||||
type SyncApiResponse struct {
|
||||
NewApis []*ApiInfo `json:"newApis"`
|
||||
DeleteApis []*ApiInfo `json:"deleteApis"`
|
||||
IgnoreApis []*ApiInfo `json:"ignoreApis"`
|
||||
func (s *ApiService) GetApiGroups(ctx khttp.Context) error {
|
||||
groups, apiGroupMap, err := s.uc.GetApiGroups(ctx)
|
||||
if err != nil {
|
||||
return errors.InternalServer("LIST_ERROR", err.Error())
|
||||
}
|
||||
return ctx.Result(200, &types.GetApiGroupsReply{Groups: groups, ApiGroupMap: apiGroupMap})
|
||||
}
|
||||
|
||||
// SyncApi 同步API
|
||||
func (s *ApiService) SyncApi(ctx context.Context) (*SyncApiResponse, error) {
|
||||
func (s *ApiService) SyncApi(ctx khttp.Context) error {
|
||||
newApis, deleteApis, ignoreApis, err := s.uc.SyncApi(ctx)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
return errors.InternalServer("SYNC_ERROR", err.Error())
|
||||
}
|
||||
|
||||
resp := &SyncApiResponse{
|
||||
NewApis: make([]*ApiInfo, len(newApis)),
|
||||
DeleteApis: make([]*ApiInfo, len(deleteApis)),
|
||||
IgnoreApis: make([]*ApiInfo, len(ignoreApis)),
|
||||
}
|
||||
for i, api := range newApis {
|
||||
resp.NewApis[i] = toApiInfo(api)
|
||||
}
|
||||
for i, api := range deleteApis {
|
||||
resp.DeleteApis[i] = toApiInfo(api)
|
||||
}
|
||||
for i, api := range ignoreApis {
|
||||
resp.IgnoreApis[i] = toApiInfo(api)
|
||||
}
|
||||
return resp, nil
|
||||
}
|
||||
|
||||
// IgnoreApiRequest 忽略API请求
|
||||
type IgnoreApiRequest struct {
|
||||
Path string `json:"path"`
|
||||
Method string `json:"method"`
|
||||
Flag bool `json:"flag"`
|
||||
return ctx.Result(200, &types.SyncApiReply{
|
||||
NewApis: toTypesApiInfoList(newApis),
|
||||
DeleteApis: toTypesApiInfoList(deleteApis),
|
||||
IgnoreApis: toTypesApiInfoList(ignoreApis),
|
||||
})
|
||||
}
|
||||
|
||||
// IgnoreApi 忽略API
|
||||
func (s *ApiService) IgnoreApi(ctx context.Context, req *IgnoreApiRequest) error {
|
||||
return s.uc.IgnoreApi(ctx, req.Path, req.Method, req.Flag)
|
||||
}
|
||||
|
||||
// EnterSyncApiRequest 确认同步API请求
|
||||
type EnterSyncApiRequest struct {
|
||||
NewApis []*ApiInfo `json:"newApis"`
|
||||
DeleteApis []*ApiInfo `json:"deleteApis"`
|
||||
func (s *ApiService) IgnoreApi(ctx khttp.Context) error {
|
||||
var req types.IgnoreApiRequest
|
||||
if err := ctx.Bind(&req); err != nil {
|
||||
return err
|
||||
}
|
||||
if err := s.uc.IgnoreApi(ctx, req.Path, req.Method, req.Flag); err != nil {
|
||||
return errors.BadRequest("IGNORE_FAILED", err.Error())
|
||||
}
|
||||
return ctx.Result(200, nil)
|
||||
}
|
||||
|
||||
// EnterSyncApi 确认同步API
|
||||
func (s *ApiService) EnterSyncApi(ctx context.Context, req *EnterSyncApiRequest) error {
|
||||
func (s *ApiService) EnterSyncApi(ctx khttp.Context) error {
|
||||
var req types.EnterSyncApiRequest
|
||||
if err := ctx.Bind(&req); err != nil {
|
||||
return err
|
||||
}
|
||||
newApis := make([]*system.Api, len(req.NewApis))
|
||||
for i, api := range req.NewApis {
|
||||
newApis[i] = &system.Api{
|
||||
@@ -233,17 +194,26 @@ func (s *ApiService) EnterSyncApi(ctx context.Context, req *EnterSyncApiRequest)
|
||||
Method: api.Method,
|
||||
}
|
||||
}
|
||||
return s.uc.EnterSyncApi(ctx, newApis, deleteApis)
|
||||
if err := s.uc.EnterSyncApi(ctx, newApis, deleteApis); err != nil {
|
||||
return errors.BadRequest("SYNC_FAILED", err.Error())
|
||||
}
|
||||
return ctx.Result(200, nil)
|
||||
}
|
||||
|
||||
// FreshCasbin 刷新Casbin缓存
|
||||
func (s *ApiService) FreshCasbin() error {
|
||||
return s.uc.FreshCasbin()
|
||||
func (s *ApiService) FreshCasbin(ctx khttp.Context) error {
|
||||
if err := s.uc.FreshCasbin(); err != nil {
|
||||
return errors.InternalServer("FRESH_FAILED", err.Error())
|
||||
}
|
||||
return ctx.Result(200, nil)
|
||||
}
|
||||
|
||||
// 转换函数
|
||||
func toApiInfo(api *system.Api) *ApiInfo {
|
||||
return &ApiInfo{
|
||||
// toTypesApiInfo 转换API信息为types格式
|
||||
func toTypesApiInfo(api *system.Api) types.ApiInfo {
|
||||
if api == nil {
|
||||
return types.ApiInfo{}
|
||||
}
|
||||
return types.ApiInfo{
|
||||
ID: api.ID,
|
||||
Path: api.Path,
|
||||
Description: api.Description,
|
||||
@@ -252,147 +222,32 @@ func toApiInfo(api *system.Api) *ApiInfo {
|
||||
}
|
||||
}
|
||||
|
||||
// RegisterRoutes 注册路由
|
||||
func (s *ApiService) RegisterRoutes(srv *http.Server) {
|
||||
r := srv.Route("/")
|
||||
|
||||
r.POST("/api/createApi", s.handleCreateApi)
|
||||
r.POST("/api/updateApi", s.handleUpdateApi)
|
||||
r.POST("/api/deleteApi", s.handleDeleteApi)
|
||||
r.DELETE("/api/deleteApisByIds", s.handleDeleteApisByIds)
|
||||
r.POST("/api/getApiList", s.handleGetApiList)
|
||||
r.POST("/api/getApiById", s.handleGetApiById)
|
||||
r.POST("/api/getAllApis", s.handleGetAllApis)
|
||||
r.GET("/api/getApiGroups", s.handleGetApiGroups)
|
||||
r.GET("/api/syncApi", s.handleSyncApi)
|
||||
r.POST("/api/ignoreApi", s.handleIgnoreApi)
|
||||
r.POST("/api/enterSyncApi", s.handleEnterSyncApi)
|
||||
r.GET("/api/freshCasbin", s.handleFreshCasbin)
|
||||
// toTypesApiInfoList 批量转换API信息
|
||||
func toTypesApiInfoList(apis []*system.Api) []types.ApiInfo {
|
||||
list := make([]types.ApiInfo, len(apis))
|
||||
for i, api := range apis {
|
||||
list[i] = toTypesApiInfo(api)
|
||||
}
|
||||
return list
|
||||
}
|
||||
|
||||
// HTTP Handlers
|
||||
func (s *ApiService) handleCreateApi(ctx http.Context) error {
|
||||
var req CreateApiRequest
|
||||
if err := ctx.Bind(&req); err != nil {
|
||||
return err
|
||||
}
|
||||
if err := s.CreateApi(ctx, &req); err != nil {
|
||||
return errors.BadRequest("CREATE_FAILED", err.Error())
|
||||
}
|
||||
return ctx.Result(200, map[string]any{"code": 0, "msg": "创建成功"})
|
||||
}
|
||||
// RegisterRoutes 注册API管理路由
|
||||
func (s *ApiService) RegisterRoutes(rg *RouterGroup) {
|
||||
// 公开路由
|
||||
rg.Public.GET("/api/freshCasbin", s.FreshCasbin)
|
||||
|
||||
func (s *ApiService) handleUpdateApi(ctx http.Context) error {
|
||||
var req UpdateApiRequest
|
||||
if err := ctx.Bind(&req); err != nil {
|
||||
return err
|
||||
}
|
||||
if err := s.UpdateApi(ctx, &req); err != nil {
|
||||
return errors.BadRequest("UPDATE_FAILED", err.Error())
|
||||
}
|
||||
return ctx.Result(200, map[string]any{"code": 0, "msg": "修改成功"})
|
||||
}
|
||||
// 私有路由 + 操作记录(写操作)
|
||||
rg.PrivateWithRecord.GET("/api/getApiGroups", s.GetApiGroups)
|
||||
rg.PrivateWithRecord.GET("/api/syncApi", s.SyncApi)
|
||||
rg.PrivateWithRecord.POST("/api/ignoreApi", s.IgnoreApi)
|
||||
rg.PrivateWithRecord.POST("/api/enterSyncApi", s.EnterSyncApi)
|
||||
rg.PrivateWithRecord.POST("/api/createApi", s.CreateApi)
|
||||
rg.PrivateWithRecord.POST("/api/deleteApi", s.DeleteApi)
|
||||
rg.PrivateWithRecord.POST("/api/getApiById", s.GetApiById)
|
||||
rg.PrivateWithRecord.POST("/api/updateApi", s.UpdateApi)
|
||||
rg.PrivateWithRecord.DELETE("/api/deleteApisByIds", s.DeleteApisByIds)
|
||||
|
||||
func (s *ApiService) handleDeleteApi(ctx http.Context) error {
|
||||
var req struct {
|
||||
ID uint `json:"ID"`
|
||||
}
|
||||
if err := ctx.Bind(&req); err != nil {
|
||||
return err
|
||||
}
|
||||
if err := s.DeleteApi(ctx, req.ID); err != nil {
|
||||
return errors.BadRequest("DELETE_FAILED", err.Error())
|
||||
}
|
||||
return ctx.Result(200, map[string]any{"code": 0, "msg": "删除成功"})
|
||||
}
|
||||
|
||||
func (s *ApiService) handleDeleteApisByIds(ctx http.Context) error {
|
||||
var req DeleteApisByIdsRequest
|
||||
if err := ctx.Bind(&req); err != nil {
|
||||
return err
|
||||
}
|
||||
if err := s.DeleteApisByIds(ctx, &req); err != nil {
|
||||
return errors.BadRequest("DELETE_FAILED", err.Error())
|
||||
}
|
||||
return ctx.Result(200, map[string]any{"code": 0, "msg": "删除成功"})
|
||||
}
|
||||
|
||||
func (s *ApiService) handleGetApiList(ctx http.Context) error {
|
||||
var req GetApiListRequest
|
||||
if err := ctx.Bind(&req); err != nil {
|
||||
return err
|
||||
}
|
||||
resp, err := s.GetApiList(ctx, &req)
|
||||
if err != nil {
|
||||
return errors.InternalServer("LIST_ERROR", err.Error())
|
||||
}
|
||||
return ctx.Result(200, map[string]any{"code": 0, "msg": "获取成功", "data": resp})
|
||||
}
|
||||
|
||||
func (s *ApiService) handleGetApiById(ctx http.Context) error {
|
||||
var req struct {
|
||||
ID uint `json:"ID"`
|
||||
}
|
||||
if err := ctx.Bind(&req); err != nil {
|
||||
return err
|
||||
}
|
||||
resp, err := s.GetApiById(ctx, req.ID)
|
||||
if err != nil {
|
||||
return errors.NotFound("NOT_FOUND", err.Error())
|
||||
}
|
||||
return ctx.Result(200, map[string]any{"code": 0, "msg": "获取成功", "data": map[string]any{"api": resp}})
|
||||
}
|
||||
|
||||
func (s *ApiService) handleGetAllApis(ctx http.Context) error {
|
||||
authorityID := middleware.GetAuthorityID(ctx)
|
||||
resp, err := s.GetAllApis(ctx, authorityID)
|
||||
if err != nil {
|
||||
return errors.InternalServer("LIST_ERROR", err.Error())
|
||||
}
|
||||
return ctx.Result(200, map[string]any{"code": 0, "msg": "获取成功", "data": map[string]any{"apis": resp}})
|
||||
}
|
||||
|
||||
func (s *ApiService) handleGetApiGroups(ctx http.Context) error {
|
||||
groups, apiGroupMap, err := s.GetApiGroups(ctx)
|
||||
if err != nil {
|
||||
return errors.InternalServer("LIST_ERROR", err.Error())
|
||||
}
|
||||
return ctx.Result(200, map[string]any{"code": 0, "msg": "获取成功", "data": map[string]any{"groups": groups, "apiGroupMap": apiGroupMap}})
|
||||
}
|
||||
|
||||
func (s *ApiService) handleSyncApi(ctx http.Context) error {
|
||||
resp, err := s.SyncApi(ctx)
|
||||
if err != nil {
|
||||
return errors.InternalServer("SYNC_ERROR", err.Error())
|
||||
}
|
||||
return ctx.Result(200, map[string]any{"code": 0, "data": resp})
|
||||
}
|
||||
|
||||
func (s *ApiService) handleIgnoreApi(ctx http.Context) error {
|
||||
var req IgnoreApiRequest
|
||||
if err := ctx.Bind(&req); err != nil {
|
||||
return err
|
||||
}
|
||||
if err := s.IgnoreApi(ctx, &req); err != nil {
|
||||
return errors.BadRequest("IGNORE_FAILED", err.Error())
|
||||
}
|
||||
return ctx.Result(200, map[string]any{"code": 0, "msg": "操作成功"})
|
||||
}
|
||||
|
||||
func (s *ApiService) handleEnterSyncApi(ctx http.Context) error {
|
||||
var req EnterSyncApiRequest
|
||||
if err := ctx.Bind(&req); err != nil {
|
||||
return err
|
||||
}
|
||||
if err := s.EnterSyncApi(ctx, &req); err != nil {
|
||||
return errors.BadRequest("SYNC_FAILED", err.Error())
|
||||
}
|
||||
return ctx.Result(200, map[string]any{"code": 0, "msg": "同步成功"})
|
||||
}
|
||||
|
||||
func (s *ApiService) handleFreshCasbin(ctx http.Context) error {
|
||||
if err := s.FreshCasbin(); err != nil {
|
||||
return errors.InternalServer("FRESH_FAILED", err.Error())
|
||||
}
|
||||
return ctx.Result(200, map[string]any{"code": 0, "msg": "刷新成功"})
|
||||
// 私有路由(读操作,不记录)
|
||||
rg.Private.POST("/api/getAllApis", s.GetAllApis)
|
||||
rg.Private.POST("/api/getApiList", s.GetApiList)
|
||||
}
|
||||
|
||||
@@ -5,6 +5,7 @@ import (
|
||||
|
||||
"kra/internal/biz/system"
|
||||
"kra/internal/server/middleware"
|
||||
types "kra/internal/service/types/system"
|
||||
|
||||
"github.com/go-kratos/kratos/v2/errors"
|
||||
"github.com/go-kratos/kratos/v2/transport/http"
|
||||
@@ -26,12 +27,12 @@ func NewAuthorityService(uc *system.AuthorityUsecase, casbin system.CasbinRepo)
|
||||
|
||||
// AuthorityInfo 角色信息
|
||||
type AuthorityFullInfo struct {
|
||||
AuthorityId uint `json:"authorityId"`
|
||||
AuthorityName string `json:"authorityName"`
|
||||
ParentId *uint `json:"parentId,omitempty"`
|
||||
DefaultRouter string `json:"defaultRouter"`
|
||||
DataAuthorityId []*AuthorityInfo `json:"dataAuthorityId,omitempty"`
|
||||
Children []*AuthorityFullInfo `json:"children,omitempty"`
|
||||
AuthorityId uint `json:"authorityId"`
|
||||
AuthorityName string `json:"authorityName"`
|
||||
ParentId *uint `json:"parentId,omitempty"`
|
||||
DefaultRouter string `json:"defaultRouter"`
|
||||
DataAuthorityId []*types.AuthorityInfo `json:"dataAuthorityId,omitempty"`
|
||||
Children []*AuthorityFullInfo `json:"children,omitempty"`
|
||||
}
|
||||
|
||||
// CreateAuthorityRequest 创建角色请求
|
||||
@@ -172,9 +173,9 @@ func toAuthorityFullInfoList(list []*system.AuthorityFull) []*AuthorityFullInfo
|
||||
}
|
||||
// DataAuthorityId
|
||||
if len(auth.DataAuthorityId) > 0 {
|
||||
result[i].DataAuthorityId = make([]*AuthorityInfo, len(auth.DataAuthorityId))
|
||||
result[i].DataAuthorityId = make([]*types.AuthorityInfo, len(auth.DataAuthorityId))
|
||||
for j, da := range auth.DataAuthorityId {
|
||||
result[i].DataAuthorityId[j] = &AuthorityInfo{
|
||||
result[i].DataAuthorityId[j] = &types.AuthorityInfo{
|
||||
AuthorityId: da.AuthorityId,
|
||||
AuthorityName: da.AuthorityName,
|
||||
ParentId: da.ParentId,
|
||||
@@ -187,15 +188,16 @@ func toAuthorityFullInfoList(list []*system.AuthorityFull) []*AuthorityFullInfo
|
||||
}
|
||||
|
||||
// RegisterRoutes 注册路由
|
||||
func (s *AuthorityService) RegisterRoutes(srv *http.Server) {
|
||||
r := srv.Route("/")
|
||||
func (s *AuthorityService) RegisterRoutes(rg *RouterGroup) {
|
||||
// 私有路由 + 操作记录(写操作)
|
||||
rg.PrivateWithRecord.POST("/authority/createAuthority", s.handleCreateAuthority)
|
||||
rg.PrivateWithRecord.POST("/authority/copyAuthority", s.handleCopyAuthority)
|
||||
rg.PrivateWithRecord.PUT("/authority/updateAuthority", s.handleUpdateAuthority)
|
||||
rg.PrivateWithRecord.POST("/authority/deleteAuthority", s.handleDeleteAuthority)
|
||||
rg.PrivateWithRecord.POST("/authority/setDataAuthority", s.handleSetDataAuthority)
|
||||
|
||||
r.POST("/authority/createAuthority", s.handleCreateAuthority)
|
||||
r.POST("/authority/copyAuthority", s.handleCopyAuthority)
|
||||
r.PUT("/authority/updateAuthority", s.handleUpdateAuthority)
|
||||
r.POST("/authority/deleteAuthority", s.handleDeleteAuthority)
|
||||
r.POST("/authority/getAuthorityList", s.handleGetAuthorityList)
|
||||
r.POST("/authority/setDataAuthority", s.handleSetDataAuthority)
|
||||
// 私有路由(读操作,不记录)
|
||||
rg.Private.POST("/authority/getAuthorityList", s.handleGetAuthorityList)
|
||||
}
|
||||
|
||||
// HTTP Handlers
|
||||
|
||||
@@ -38,11 +38,11 @@ type SetAuthorityBtnRequest struct {
|
||||
}
|
||||
|
||||
// RegisterRoutes 注册路由
|
||||
func (s *AuthorityBtnService) RegisterRoutes(srv *http.Server) {
|
||||
r := srv.Route("/")
|
||||
r.POST("/authorityBtn/getAuthorityBtn", s.handleGetAuthorityBtn)
|
||||
r.POST("/authorityBtn/setAuthorityBtn", s.handleSetAuthorityBtn)
|
||||
r.POST("/authorityBtn/canRemoveAuthorityBtn", s.handleCanRemoveAuthorityBtn)
|
||||
func (s *AuthorityBtnService) RegisterRoutes(rg *RouterGroup) {
|
||||
// 角色按钮权限(不需要操作记录)
|
||||
rg.Private.POST("/authorityBtn/getAuthorityBtn", s.handleGetAuthorityBtn)
|
||||
rg.Private.POST("/authorityBtn/setAuthorityBtn", s.handleSetAuthorityBtn)
|
||||
rg.Private.POST("/authorityBtn/canRemoveAuthorityBtn", s.handleCanRemoveAuthorityBtn)
|
||||
}
|
||||
|
||||
func (s *AuthorityBtnService) handleGetAuthorityBtn(ctx http.Context) error {
|
||||
|
||||
@@ -4,24 +4,30 @@ import (
|
||||
"sync"
|
||||
"time"
|
||||
|
||||
"kra/internal/conf"
|
||||
|
||||
"github.com/go-kratos/kratos/v2/transport/http"
|
||||
"github.com/mojocn/base64Captcha"
|
||||
)
|
||||
|
||||
// CaptchaService 验证码服务
|
||||
type CaptchaService struct {
|
||||
config CaptchaConfig
|
||||
store base64Captcha.Store
|
||||
blackCache *BlackCache
|
||||
keyLong int
|
||||
imgWidth int
|
||||
imgHeight int
|
||||
openCaptcha int // 防爆次数,0表示关闭
|
||||
openCaptchaTimeOut int // 缓存超时时间(秒)
|
||||
store base64Captcha.Store
|
||||
blackCache *BlackCache
|
||||
}
|
||||
|
||||
// CaptchaConfig 验证码配置
|
||||
// CaptchaConfig 验证码配置(保留用于兼容)
|
||||
type CaptchaConfig struct {
|
||||
KeyLong int
|
||||
ImgWidth int
|
||||
ImgHeight int
|
||||
OpenCaptcha int // 防爆次数,0表示关闭
|
||||
OpenCaptchaTimeOut int // 缓存超时时间(秒)
|
||||
OpenCaptcha int
|
||||
OpenCaptchaTimeOut int
|
||||
}
|
||||
|
||||
// BlackCache 黑名单缓存
|
||||
@@ -86,21 +92,22 @@ type CaptchaResponse struct {
|
||||
}
|
||||
|
||||
// NewCaptchaService 创建验证码服务
|
||||
func NewCaptchaService(config CaptchaConfig, store base64Captcha.Store) *CaptchaService {
|
||||
if store == nil {
|
||||
store = base64Captcha.DefaultMemStore
|
||||
}
|
||||
func NewCaptchaService(c *conf.Captcha) *CaptchaService {
|
||||
return &CaptchaService{
|
||||
config: config,
|
||||
store: store,
|
||||
blackCache: NewBlackCache(),
|
||||
keyLong: int(c.KeyLong),
|
||||
imgWidth: int(c.ImgWidth),
|
||||
imgHeight: int(c.ImgHeight),
|
||||
openCaptcha: int(c.OpenCaptcha),
|
||||
openCaptchaTimeOut: int(c.OpenCaptchaTimeout),
|
||||
store: base64Captcha.DefaultMemStore,
|
||||
blackCache: NewBlackCache(),
|
||||
}
|
||||
}
|
||||
|
||||
// RegisterRoutes 注册路由
|
||||
func (s *CaptchaService) RegisterRoutes(srv *http.Server) {
|
||||
r := srv.Route("/")
|
||||
r.POST("/base/captcha", s.handleCaptcha)
|
||||
func (s *CaptchaService) RegisterRoutes(rg *RouterGroup) {
|
||||
// 验证码(公开路由,无需认证)
|
||||
rg.Public.POST("/base/captcha", s.handleCaptcha)
|
||||
}
|
||||
|
||||
func (s *CaptchaService) handleCaptcha(ctx http.Context) error {
|
||||
@@ -108,8 +115,8 @@ func (s *CaptchaService) handleCaptcha(ctx http.Context) error {
|
||||
clientIP := ctx.Request().RemoteAddr
|
||||
|
||||
// 判断验证码是否开启
|
||||
openCaptcha := s.config.OpenCaptcha
|
||||
openCaptchaTimeOut := s.config.OpenCaptchaTimeOut
|
||||
openCaptcha := s.openCaptcha
|
||||
openCaptchaTimeOut := s.openCaptchaTimeOut
|
||||
|
||||
v, ok := s.blackCache.Get(clientIP)
|
||||
if !ok {
|
||||
@@ -123,9 +130,9 @@ func (s *CaptchaService) handleCaptcha(ctx http.Context) error {
|
||||
|
||||
// 生成验证码
|
||||
driver := base64Captcha.NewDriverDigit(
|
||||
s.config.ImgHeight,
|
||||
s.config.ImgWidth,
|
||||
s.config.KeyLong,
|
||||
s.imgHeight,
|
||||
s.imgWidth,
|
||||
s.keyLong,
|
||||
0.7,
|
||||
80,
|
||||
)
|
||||
@@ -144,7 +151,7 @@ func (s *CaptchaService) handleCaptcha(ctx http.Context) error {
|
||||
"data": CaptchaResponse{
|
||||
CaptchaId: id,
|
||||
PicPath: b64s,
|
||||
CaptchaLength: s.config.KeyLong,
|
||||
CaptchaLength: s.keyLong,
|
||||
OpenCaptcha: oc,
|
||||
},
|
||||
})
|
||||
|
||||
@@ -5,6 +5,7 @@ import (
|
||||
"strconv"
|
||||
|
||||
"kra/internal/biz/system"
|
||||
"kra/internal/conf"
|
||||
"kra/internal/server/middleware"
|
||||
|
||||
kerrors "github.com/go-kratos/kratos/v2/errors"
|
||||
@@ -20,12 +21,12 @@ type CasbinService struct {
|
||||
}
|
||||
|
||||
// NewCasbinService 创建Casbin服务
|
||||
func NewCasbinService(casbinRepo system.CasbinRepo, authUc *system.AuthorityUsecase, apiUc *system.ApiUsecase, useStrictAuth bool) *CasbinService {
|
||||
func NewCasbinService(casbinRepo system.CasbinRepo, authUc *system.AuthorityUsecase, apiUc *system.ApiUsecase, useStrictAuth conf.UseStrictAuth) *CasbinService {
|
||||
return &CasbinService{
|
||||
casbinRepo: casbinRepo,
|
||||
authUc: authUc,
|
||||
apiUc: apiUc,
|
||||
useStrictAuth: useStrictAuth,
|
||||
useStrictAuth: bool(useStrictAuth),
|
||||
}
|
||||
}
|
||||
|
||||
@@ -81,10 +82,12 @@ func (s *CasbinService) GetPolicyPathByAuthorityId(authorityId uint) []system.Ca
|
||||
}
|
||||
|
||||
// RegisterRoutes 注册路由
|
||||
func (s *CasbinService) RegisterRoutes(srv *http.Server) {
|
||||
r := srv.Route("/")
|
||||
r.POST("/casbin/UpdateCasbin", s.handleUpdateCasbin)
|
||||
r.POST("/casbin/getPolicyPathByAuthorityId", s.handleGetPolicyPath)
|
||||
func (s *CasbinService) RegisterRoutes(rg *RouterGroup) {
|
||||
// 私有路由 + 操作记录(写操作)
|
||||
rg.PrivateWithRecord.POST("/casbin/updateCasbin", s.handleUpdateCasbin)
|
||||
|
||||
// 私有路由(读操作,不记录)
|
||||
rg.Private.POST("/casbin/getPolicyPathByAuthorityId", s.handleGetPolicyPath)
|
||||
}
|
||||
|
||||
func (s *CasbinService) handleUpdateCasbin(ctx http.Context) error {
|
||||
|
||||
@@ -365,28 +365,30 @@ func toDictionaryDetailInfoList(list []*system.DictionaryDetail) []*DictionaryDe
|
||||
}
|
||||
|
||||
// RegisterRoutes 注册路由
|
||||
func (s *DictionaryService) RegisterRoutes(srv *http.Server) {
|
||||
r := srv.Route("/")
|
||||
func (s *DictionaryService) RegisterRoutes(rg *RouterGroup) {
|
||||
// 字典接口 - 写操作(带操作记录)
|
||||
rg.PrivateWithRecord.POST("/sysDictionary/createSysDictionary", s.handleCreateDictionary)
|
||||
rg.PrivateWithRecord.DELETE("/sysDictionary/deleteSysDictionary", s.handleDeleteDictionary)
|
||||
rg.PrivateWithRecord.PUT("/sysDictionary/updateSysDictionary", s.handleUpdateDictionary)
|
||||
rg.PrivateWithRecord.POST("/sysDictionary/importSysDictionary", s.handleImportDictionary)
|
||||
rg.PrivateWithRecord.GET("/sysDictionary/exportSysDictionary", s.handleExportDictionary)
|
||||
|
||||
// 字典接口
|
||||
r.POST("/sysDictionary/createSysDictionary", s.handleCreateDictionary)
|
||||
r.DELETE("/sysDictionary/deleteSysDictionary", s.handleDeleteDictionary)
|
||||
r.PUT("/sysDictionary/updateSysDictionary", s.handleUpdateDictionary)
|
||||
r.GET("/sysDictionary/findSysDictionary", s.handleGetDictionary)
|
||||
r.GET("/sysDictionary/getSysDictionaryList", s.handleGetDictionaryList)
|
||||
r.GET("/sysDictionary/exportSysDictionary", s.handleExportDictionary)
|
||||
r.POST("/sysDictionary/importSysDictionary", s.handleImportDictionary)
|
||||
// 字典接口 - 读操作(不记录)
|
||||
rg.Private.GET("/sysDictionary/findSysDictionary", s.handleGetDictionary)
|
||||
rg.Private.GET("/sysDictionary/getSysDictionaryList", s.handleGetDictionaryList)
|
||||
|
||||
// 字典详情接口
|
||||
r.POST("/sysDictionaryDetail/createSysDictionaryDetail", s.handleCreateDictionaryDetail)
|
||||
r.DELETE("/sysDictionaryDetail/deleteSysDictionaryDetail", s.handleDeleteDictionaryDetail)
|
||||
r.PUT("/sysDictionaryDetail/updateSysDictionaryDetail", s.handleUpdateDictionaryDetail)
|
||||
r.GET("/sysDictionaryDetail/findSysDictionaryDetail", s.handleGetDictionaryDetail)
|
||||
r.GET("/sysDictionaryDetail/getSysDictionaryDetailList", s.handleGetDictionaryDetailList)
|
||||
r.GET("/sysDictionaryDetail/getDictionaryTreeList", s.handleGetDictionaryTreeList)
|
||||
r.POST("/sysDictionaryDetail/getDictionaryDetailsByParent", s.handleGetDictionaryDetailsByParent)
|
||||
r.GET("/sysDictionaryDetail/getDictionaryListByType", s.handleGetDictionaryListByType)
|
||||
r.GET("/sysDictionaryDetail/getDictionaryTreeListByType", s.handleGetDictionaryTreeListByType)
|
||||
// 字典详情接口 - 写操作(带操作记录)
|
||||
rg.PrivateWithRecord.POST("/sysDictionaryDetail/createSysDictionaryDetail", s.handleCreateDictionaryDetail)
|
||||
rg.PrivateWithRecord.DELETE("/sysDictionaryDetail/deleteSysDictionaryDetail", s.handleDeleteDictionaryDetail)
|
||||
rg.PrivateWithRecord.PUT("/sysDictionaryDetail/updateSysDictionaryDetail", s.handleUpdateDictionaryDetail)
|
||||
|
||||
// 字典详情接口 - 读操作(不记录)
|
||||
rg.Private.GET("/sysDictionaryDetail/findSysDictionaryDetail", s.handleGetDictionaryDetail)
|
||||
rg.Private.GET("/sysDictionaryDetail/getSysDictionaryDetailList", s.handleGetDictionaryDetailList)
|
||||
rg.Private.GET("/sysDictionaryDetail/getDictionaryTreeList", s.handleGetDictionaryTreeList)
|
||||
rg.Private.GET("/sysDictionaryDetail/getDictionaryTreeListByType", s.handleGetDictionaryTreeListByType)
|
||||
rg.Private.GET("/sysDictionaryDetail/getDictionaryDetailsByParent", s.handleGetDictionaryDetailsByParent)
|
||||
rg.Private.GET("/sysDictionaryDetail/getDictionaryPath", s.handleGetDictionaryPath)
|
||||
}
|
||||
|
||||
// HTTP Handlers - Dictionary
|
||||
@@ -568,6 +570,16 @@ func (s *DictionaryService) handleGetDictionaryTreeListByType(ctx http.Context)
|
||||
return ctx.Result(200, map[string]any{"code": 0, "msg": "获取成功", "data": map[string]any{"list": resp}})
|
||||
}
|
||||
|
||||
func (s *DictionaryService) handleGetDictionaryPath(ctx http.Context) error {
|
||||
idStr := ctx.Query().Get("id")
|
||||
id, _ := parseUint(idStr)
|
||||
resp, err := s.uc.GetDictionaryPath(ctx, id)
|
||||
if err != nil {
|
||||
return errors.InternalServer("PATH_ERROR", err.Error())
|
||||
}
|
||||
return ctx.Result(200, map[string]any{"code": 0, "msg": "获取成功", "data": map[string]any{"path": toDictionaryDetailInfoList(resp)}})
|
||||
}
|
||||
|
||||
// parseUint 解析uint
|
||||
func parseUint(s string) (uint, error) {
|
||||
if s == "" {
|
||||
|
||||
@@ -34,7 +34,7 @@ func (s *JwtBlacklistService) JoinBlacklist(ctx http.Context) error {
|
||||
}
|
||||
|
||||
// RegisterRoutes 注册路由
|
||||
func (s *JwtBlacklistService) RegisterRoutes(srv *http.Server) {
|
||||
r := srv.Route("/")
|
||||
r.POST("/jwt/jsonInBlacklist", s.JoinBlacklist)
|
||||
func (s *JwtBlacklistService) RegisterRoutes(rg *RouterGroup) {
|
||||
// JWT黑名单(不需要操作记录)
|
||||
rg.Private.POST("/jwt/jsonInBlacklist", s.JoinBlacklist)
|
||||
}
|
||||
|
||||
@@ -322,18 +322,19 @@ func toBaseMenuInfo(m *system.BaseMenu) *MenuInfo {
|
||||
}
|
||||
|
||||
// RegisterRoutes 注册路由
|
||||
func (s *MenuService) RegisterRoutes(srv *http.Server) {
|
||||
r := srv.Route("/")
|
||||
func (s *MenuService) RegisterRoutes(rg *RouterGroup) {
|
||||
// 私有路由 + 操作记录(写操作)
|
||||
rg.PrivateWithRecord.POST("/menu/addBaseMenu", s.handleAddBaseMenu)
|
||||
rg.PrivateWithRecord.POST("/menu/addMenuAuthority", s.handleAddMenuAuthority)
|
||||
rg.PrivateWithRecord.POST("/menu/deleteBaseMenu", s.handleDeleteBaseMenu)
|
||||
rg.PrivateWithRecord.POST("/menu/updateBaseMenu", s.handleUpdateBaseMenu)
|
||||
|
||||
r.POST("/menu/getMenu", s.handleGetMenu)
|
||||
r.POST("/menu/getBaseMenuTree", s.handleGetBaseMenuTree)
|
||||
r.POST("/menu/getMenuList", s.handleGetMenuList)
|
||||
r.POST("/menu/addBaseMenu", s.handleAddBaseMenu)
|
||||
r.POST("/menu/updateBaseMenu", s.handleUpdateBaseMenu)
|
||||
r.POST("/menu/deleteBaseMenu", s.handleDeleteBaseMenu)
|
||||
r.POST("/menu/getBaseMenuById", s.handleGetBaseMenuById)
|
||||
r.POST("/menu/addMenuAuthority", s.handleAddMenuAuthority)
|
||||
r.POST("/menu/getMenuAuthority", s.handleGetMenuAuthority)
|
||||
// 私有路由(读操作,不记录)
|
||||
rg.Private.POST("/menu/getMenu", s.handleGetMenu)
|
||||
rg.Private.POST("/menu/getMenuList", s.handleGetMenuList)
|
||||
rg.Private.POST("/menu/getBaseMenuTree", s.handleGetBaseMenuTree)
|
||||
rg.Private.POST("/menu/getMenuAuthority", s.handleGetMenuAuthority)
|
||||
rg.Private.POST("/menu/getBaseMenuById", s.handleGetBaseMenuById)
|
||||
}
|
||||
|
||||
// HTTP Handlers
|
||||
|
||||
@@ -4,6 +4,7 @@ import (
|
||||
"fmt"
|
||||
|
||||
"kra/internal/biz/system"
|
||||
types "kra/internal/service/types/system"
|
||||
|
||||
"github.com/go-kratos/kratos/v2/errors"
|
||||
"github.com/go-kratos/kratos/v2/transport/http"
|
||||
@@ -21,18 +22,18 @@ func NewOperationRecordService(uc *system.OperationRecordUsecase) *OperationReco
|
||||
|
||||
// OperationRecordInfo 操作记录信息
|
||||
type OperationRecordInfo struct {
|
||||
ID uint `json:"id"`
|
||||
IP string `json:"ip"`
|
||||
Method string `json:"method"`
|
||||
Path string `json:"path"`
|
||||
Status int `json:"status"`
|
||||
Latency int64 `json:"latency"`
|
||||
Agent string `json:"agent"`
|
||||
ErrorMessage string `json:"error_message"`
|
||||
Body string `json:"body"`
|
||||
Resp string `json:"resp"`
|
||||
UserID uint `json:"user_id"`
|
||||
User *UserInfo `json:"user,omitempty"`
|
||||
ID uint `json:"id"`
|
||||
IP string `json:"ip"`
|
||||
Method string `json:"method"`
|
||||
Path string `json:"path"`
|
||||
Status int `json:"status"`
|
||||
Latency int64 `json:"latency"`
|
||||
Agent string `json:"agent"`
|
||||
ErrorMessage string `json:"error_message"`
|
||||
Body string `json:"body"`
|
||||
Resp string `json:"resp"`
|
||||
UserID uint `json:"user_id"`
|
||||
User *types.UserInfo `json:"user,omitempty"`
|
||||
}
|
||||
|
||||
// GetOperationRecordListRequest 获取操作记录列表请求
|
||||
@@ -64,12 +65,12 @@ type DeleteOperationRecordByIdsRequest struct {
|
||||
}
|
||||
|
||||
// RegisterRoutes 注册路由
|
||||
func (s *OperationRecordService) RegisterRoutes(srv *http.Server) {
|
||||
r := srv.Route("/")
|
||||
r.POST("/sysOperationRecord/getSysOperationRecordList", s.handleGetList)
|
||||
r.DELETE("/sysOperationRecord/deleteSysOperationRecord", s.handleDelete)
|
||||
r.DELETE("/sysOperationRecord/deleteSysOperationRecordByIds", s.handleDeleteByIds)
|
||||
r.GET("/sysOperationRecord/findSysOperationRecord", s.handleFind)
|
||||
func (s *OperationRecordService) RegisterRoutes(rg *RouterGroup) {
|
||||
// 操作记录(不需要操作记录中间件,避免递归)
|
||||
rg.Private.DELETE("/sysOperationRecord/deleteSysOperationRecord", s.handleDelete)
|
||||
rg.Private.DELETE("/sysOperationRecord/deleteSysOperationRecordByIds", s.handleDeleteByIds)
|
||||
rg.Private.GET("/sysOperationRecord/findSysOperationRecord", s.handleFind)
|
||||
rg.Private.GET("/sysOperationRecord/getSysOperationRecordList", s.handleGetList)
|
||||
}
|
||||
|
||||
func (s *OperationRecordService) handleGetList(ctx http.Context) error {
|
||||
@@ -159,7 +160,8 @@ func toOperationRecordInfo(r *system.OperationRecord) *OperationRecordInfo {
|
||||
UserID: r.UserID,
|
||||
}
|
||||
if r.User != nil {
|
||||
info.User = toUserInfo(r.User)
|
||||
userInfo := toTypesUserInfo(r.User)
|
||||
info.User = &userInfo
|
||||
}
|
||||
return info
|
||||
}
|
||||
|
||||
@@ -0,0 +1,224 @@
|
||||
package system
|
||||
|
||||
import (
|
||||
"strconv"
|
||||
|
||||
"kra/internal/biz/system"
|
||||
|
||||
"github.com/go-kratos/kratos/v2/errors"
|
||||
"github.com/go-kratos/kratos/v2/transport/http"
|
||||
)
|
||||
|
||||
// ParamsService 系统参数服务
|
||||
type ParamsService struct {
|
||||
uc *system.ParamsUsecase
|
||||
}
|
||||
|
||||
// NewParamsService 创建系统参数服务
|
||||
func NewParamsService(uc *system.ParamsUsecase) *ParamsService {
|
||||
return &ParamsService{uc: uc}
|
||||
}
|
||||
|
||||
// ParamsInfo 参数信息
|
||||
type ParamsInfo struct {
|
||||
ID uint `json:"ID"`
|
||||
Name string `json:"name"`
|
||||
Key string `json:"key"`
|
||||
Value string `json:"value"`
|
||||
Desc string `json:"desc"`
|
||||
CreatedAt string `json:"createdAt,omitempty"`
|
||||
UpdatedAt string `json:"updatedAt,omitempty"`
|
||||
}
|
||||
|
||||
// CreateParamsRequest 创建参数请求
|
||||
type CreateParamsRequest struct {
|
||||
Name string `json:"name"`
|
||||
Key string `json:"key"`
|
||||
Value string `json:"value"`
|
||||
Desc string `json:"desc"`
|
||||
}
|
||||
|
||||
// UpdateParamsRequest 更新参数请求
|
||||
type UpdateParamsRequest struct {
|
||||
ID uint `json:"ID"`
|
||||
Name string `json:"name"`
|
||||
Key string `json:"key"`
|
||||
Value string `json:"value"`
|
||||
Desc string `json:"desc"`
|
||||
}
|
||||
|
||||
// GetParamsListRequest 获取参数列表请求
|
||||
type GetParamsListRequest struct {
|
||||
Page int `json:"page" form:"page"`
|
||||
PageSize int `json:"pageSize" form:"pageSize"`
|
||||
Name string `json:"name" form:"name"`
|
||||
Key string `json:"key" form:"key"`
|
||||
}
|
||||
|
||||
// RegisterRoutes 注册路由
|
||||
func (s *ParamsService) RegisterRoutes(rg *RouterGroup) {
|
||||
// 写操作(带操作记录)
|
||||
rg.PrivateWithRecord.POST("/sysParams/createSysParams", s.handleCreateParams)
|
||||
rg.PrivateWithRecord.DELETE("/sysParams/deleteSysParams", s.handleDeleteParams)
|
||||
rg.PrivateWithRecord.DELETE("/sysParams/deleteSysParamsByIds", s.handleDeleteParamsByIds)
|
||||
rg.PrivateWithRecord.PUT("/sysParams/updateSysParams", s.handleUpdateParams)
|
||||
|
||||
// 读操作(不记录)
|
||||
rg.Private.GET("/sysParams/findSysParams", s.handleFindParams)
|
||||
rg.Private.GET("/sysParams/getSysParamsList", s.handleGetParamsList)
|
||||
rg.Private.GET("/sysParams/getSysParam", s.handleGetParamByKey)
|
||||
}
|
||||
|
||||
// handleCreateParams 创建参数
|
||||
func (s *ParamsService) handleCreateParams(ctx http.Context) error {
|
||||
var req CreateParamsRequest
|
||||
if err := ctx.Bind(&req); err != nil {
|
||||
return err
|
||||
}
|
||||
params := &system.Params{
|
||||
Name: req.Name,
|
||||
Key: req.Key,
|
||||
Value: req.Value,
|
||||
Desc: req.Desc,
|
||||
}
|
||||
if err := s.uc.Create(ctx, params); err != nil {
|
||||
return errors.BadRequest("CREATE_FAILED", "创建失败:"+err.Error())
|
||||
}
|
||||
return ctx.Result(200, map[string]any{"code": 0, "msg": "创建成功"})
|
||||
}
|
||||
|
||||
// handleDeleteParams 删除参数
|
||||
func (s *ParamsService) handleDeleteParams(ctx http.Context) error {
|
||||
idStr := ctx.Query().Get("ID")
|
||||
id, err := strconv.ParseUint(idStr, 10, 64)
|
||||
if err != nil {
|
||||
return errors.BadRequest("INVALID_ID", "无效的ID")
|
||||
}
|
||||
if err := s.uc.Delete(ctx, uint(id)); err != nil {
|
||||
return errors.BadRequest("DELETE_FAILED", "删除失败:"+err.Error())
|
||||
}
|
||||
return ctx.Result(200, map[string]any{"code": 0, "msg": "删除成功"})
|
||||
}
|
||||
|
||||
// handleDeleteParamsByIds 批量删除参数
|
||||
func (s *ParamsService) handleDeleteParamsByIds(ctx http.Context) error {
|
||||
idsStr := ctx.Query()["IDs[]"]
|
||||
if len(idsStr) == 0 {
|
||||
return errors.BadRequest("INVALID_IDS", "无效的IDs")
|
||||
}
|
||||
ids := make([]uint, 0, len(idsStr))
|
||||
for _, idStr := range idsStr {
|
||||
id, err := strconv.ParseUint(idStr, 10, 64)
|
||||
if err != nil {
|
||||
continue
|
||||
}
|
||||
ids = append(ids, uint(id))
|
||||
}
|
||||
if err := s.uc.DeleteByIds(ctx, ids); err != nil {
|
||||
return errors.BadRequest("DELETE_FAILED", "批量删除失败:"+err.Error())
|
||||
}
|
||||
return ctx.Result(200, map[string]any{"code": 0, "msg": "批量删除成功"})
|
||||
}
|
||||
|
||||
// handleUpdateParams 更新参数
|
||||
func (s *ParamsService) handleUpdateParams(ctx http.Context) error {
|
||||
var req UpdateParamsRequest
|
||||
if err := ctx.Bind(&req); err != nil {
|
||||
return err
|
||||
}
|
||||
params := &system.Params{
|
||||
ID: req.ID,
|
||||
Name: req.Name,
|
||||
Key: req.Key,
|
||||
Value: req.Value,
|
||||
Desc: req.Desc,
|
||||
}
|
||||
if err := s.uc.Update(ctx, params); err != nil {
|
||||
return errors.BadRequest("UPDATE_FAILED", "更新失败:"+err.Error())
|
||||
}
|
||||
return ctx.Result(200, map[string]any{"code": 0, "msg": "更新成功"})
|
||||
}
|
||||
|
||||
// handleFindParams 根据ID查询参数
|
||||
func (s *ParamsService) handleFindParams(ctx http.Context) error {
|
||||
idStr := ctx.Query().Get("ID")
|
||||
id, err := strconv.ParseUint(idStr, 10, 64)
|
||||
if err != nil {
|
||||
return errors.BadRequest("INVALID_ID", "无效的ID")
|
||||
}
|
||||
params, err := s.uc.GetByID(ctx, uint(id))
|
||||
if err != nil {
|
||||
return errors.NotFound("NOT_FOUND", "查询失败:"+err.Error())
|
||||
}
|
||||
return ctx.Result(200, map[string]any{"code": 0, "msg": "查询成功", "data": toParamsInfo(params)})
|
||||
}
|
||||
|
||||
// handleGetParamsList 分页获取参数列表
|
||||
func (s *ParamsService) handleGetParamsList(ctx http.Context) error {
|
||||
var req GetParamsListRequest
|
||||
if err := ctx.BindQuery(&req); err != nil {
|
||||
return err
|
||||
}
|
||||
if req.Page <= 0 {
|
||||
req.Page = 1
|
||||
}
|
||||
if req.PageSize <= 0 {
|
||||
req.PageSize = 10
|
||||
}
|
||||
filters := make(map[string]interface{})
|
||||
if req.Name != "" {
|
||||
filters["name"] = req.Name
|
||||
}
|
||||
if req.Key != "" {
|
||||
filters["key"] = req.Key
|
||||
}
|
||||
list, total, err := s.uc.GetList(ctx, req.Page, req.PageSize, filters)
|
||||
if err != nil {
|
||||
return errors.InternalServer("LIST_ERROR", "获取失败:"+err.Error())
|
||||
}
|
||||
result := make([]ParamsInfo, len(list))
|
||||
for i, p := range list {
|
||||
result[i] = toParamsInfo(p)
|
||||
}
|
||||
return ctx.Result(200, map[string]any{
|
||||
"code": 0,
|
||||
"msg": "获取成功",
|
||||
"data": map[string]any{
|
||||
"list": result,
|
||||
"total": total,
|
||||
"page": req.Page,
|
||||
"pageSize": req.PageSize,
|
||||
},
|
||||
})
|
||||
}
|
||||
|
||||
// handleGetParamByKey 根据key获取参数
|
||||
func (s *ParamsService) handleGetParamByKey(ctx http.Context) error {
|
||||
key := ctx.Query().Get("key")
|
||||
if key == "" {
|
||||
return errors.BadRequest("INVALID_KEY", "无效的key")
|
||||
}
|
||||
params, err := s.uc.GetByKey(ctx, key)
|
||||
if err != nil {
|
||||
return errors.NotFound("NOT_FOUND", "获取失败:"+err.Error())
|
||||
}
|
||||
return ctx.Result(200, map[string]any{"code": 0, "msg": "获取成功", "data": toParamsInfo(params)})
|
||||
}
|
||||
|
||||
// toParamsInfo 转换为ParamsInfo
|
||||
func toParamsInfo(p *system.Params) ParamsInfo {
|
||||
info := ParamsInfo{
|
||||
ID: p.ID,
|
||||
Name: p.Name,
|
||||
Key: p.Key,
|
||||
Value: p.Value,
|
||||
Desc: p.Desc,
|
||||
}
|
||||
if !p.CreatedAt.IsZero() {
|
||||
info.CreatedAt = p.CreatedAt.Format("2006-01-02 15:04:05")
|
||||
}
|
||||
if !p.UpdatedAt.IsZero() {
|
||||
info.UpdatedAt = p.UpdatedAt.Format("2006-01-02 15:04:05")
|
||||
}
|
||||
return info
|
||||
}
|
||||
@@ -0,0 +1,40 @@
|
||||
package system
|
||||
|
||||
import (
|
||||
"kra/pkg/server"
|
||||
|
||||
"github.com/go-kratos/kratos/v2/errors"
|
||||
"github.com/go-kratos/kratos/v2/transport/http"
|
||||
)
|
||||
|
||||
// SystemConfigService 系统配置服务
|
||||
type SystemConfigService struct {
|
||||
diskMountPoints []string
|
||||
}
|
||||
|
||||
// NewSystemConfigService 创建系统配置服务
|
||||
func NewSystemConfigService() *SystemConfigService {
|
||||
// 默认磁盘挂载点,可以从配置中读取
|
||||
return &SystemConfigService{
|
||||
diskMountPoints: []string{"/"},
|
||||
}
|
||||
}
|
||||
|
||||
// RegisterRoutes 注册路由
|
||||
func (s *SystemConfigService) RegisterRoutes(rg *RouterGroup) {
|
||||
// 读操作(不记录)
|
||||
rg.Private.POST("/system/getServerInfo", s.handleGetServerInfo)
|
||||
}
|
||||
|
||||
// handleGetServerInfo 获取服务器信息
|
||||
func (s *SystemConfigService) handleGetServerInfo(ctx http.Context) error {
|
||||
serverInfo, err := server.GetServerInfo(s.diskMountPoints)
|
||||
if err != nil {
|
||||
return errors.InternalServer("GET_SERVER_INFO_FAILED", "获取失败:"+err.Error())
|
||||
}
|
||||
return ctx.Result(200, map[string]any{
|
||||
"code": 0,
|
||||
"msg": "获取成功",
|
||||
"data": map[string]any{"server": serverInfo},
|
||||
})
|
||||
}
|
||||
+211
-466
@@ -1,18 +1,24 @@
|
||||
package system
|
||||
|
||||
import (
|
||||
"context"
|
||||
"encoding/json"
|
||||
"fmt"
|
||||
|
||||
"kra/internal/biz/system"
|
||||
"kra/internal/server/middleware"
|
||||
types "kra/internal/service/types/system"
|
||||
"kra/pkg/jwt"
|
||||
|
||||
"github.com/go-kratos/kratos/v2/errors"
|
||||
"github.com/go-kratos/kratos/v2/transport/http"
|
||||
khttp "github.com/go-kratos/kratos/v2/transport/http"
|
||||
)
|
||||
|
||||
// RouterGroup 路由组接口
|
||||
type RouterGroup struct {
|
||||
Public *khttp.Router // 公开路由(无需认证)
|
||||
Private *khttp.Router // 私有路由(需要JWT认证)
|
||||
PrivateWithRecord *khttp.Router // 私有路由 + 操作记录
|
||||
}
|
||||
|
||||
// UserService 用户服务
|
||||
type UserService struct {
|
||||
uc *system.UserUsecase
|
||||
@@ -24,93 +30,43 @@ func NewUserService(uc *system.UserUsecase, jwtPkg *jwt.JWT) *UserService {
|
||||
return &UserService{uc: uc, jwtPkg: jwtPkg}
|
||||
}
|
||||
|
||||
// LoginRequest 登录请求
|
||||
type LoginRequest struct {
|
||||
Username string `json:"username"`
|
||||
Password string `json:"password"`
|
||||
Captcha string `json:"captcha"`
|
||||
CaptchaId string `json:"captchaId"`
|
||||
}
|
||||
|
||||
// LoginResponse 登录响应
|
||||
type LoginResponse struct {
|
||||
User *UserInfo `json:"user"`
|
||||
Token string `json:"token"`
|
||||
ExpiresAt int64 `json:"expiresAt"`
|
||||
}
|
||||
|
||||
// UserInfo 用户信息
|
||||
type UserInfo struct {
|
||||
ID uint `json:"id"`
|
||||
UUID string `json:"uuid"`
|
||||
Username string `json:"username"`
|
||||
NickName string `json:"nickName"`
|
||||
SideMode string `json:"sideMode"`
|
||||
HeaderImg string `json:"headerImg"`
|
||||
BaseColor string `json:"baseColor"`
|
||||
AuthorityId uint `json:"authorityId"`
|
||||
Phone string `json:"phone"`
|
||||
Email string `json:"email"`
|
||||
Enable int `json:"enable"`
|
||||
OriginSetting json.RawMessage `json:"originSetting,omitempty"`
|
||||
Authority *AuthorityInfo `json:"authority,omitempty"`
|
||||
Authorities []*AuthorityInfo `json:"authorities,omitempty"`
|
||||
}
|
||||
|
||||
// AuthorityInfo 角色信息
|
||||
type AuthorityInfo struct {
|
||||
AuthorityId uint `json:"authorityId"`
|
||||
AuthorityName string `json:"authorityName"`
|
||||
ParentId *uint `json:"parentId,omitempty"`
|
||||
DefaultRouter string `json:"defaultRouter"`
|
||||
}
|
||||
|
||||
// Login 用户登录
|
||||
func (s *UserService) Login(ctx context.Context, req *LoginRequest) (*LoginResponse, error) {
|
||||
func (s *UserService) Login(ctx khttp.Context) error {
|
||||
var req types.LoginRequest
|
||||
if err := ctx.Bind(&req); err != nil {
|
||||
return err
|
||||
}
|
||||
user, err := s.uc.Login(ctx, req.Username, req.Password)
|
||||
if err != nil {
|
||||
return nil, errors.Unauthorized("LOGIN_FAILED", err.Error())
|
||||
return errors.Unauthorized("LOGIN_FAILED", err.Error())
|
||||
}
|
||||
|
||||
if user.Enable != 1 {
|
||||
return nil, errors.Forbidden("USER_DISABLED", "用户被禁止登录")
|
||||
return errors.Forbidden("USER_DISABLED", "用户被禁止登录")
|
||||
}
|
||||
|
||||
// 生成 JWT token
|
||||
claims := s.jwtPkg.CreateClaims(jwt.BaseClaims{
|
||||
UUID: user.UUID.String(),
|
||||
ID: uint(user.ID),
|
||||
ID: user.ID,
|
||||
Username: user.Username,
|
||||
NickName: user.NickName,
|
||||
AuthorityID: user.AuthorityId,
|
||||
})
|
||||
token, err := s.jwtPkg.CreateToken(claims.BaseClaims)
|
||||
if err != nil {
|
||||
return nil, errors.InternalServer("TOKEN_ERROR", "生成token失败")
|
||||
return errors.InternalServer("TOKEN_ERROR", "生成token失败")
|
||||
}
|
||||
|
||||
return &LoginResponse{
|
||||
User: toUserInfo(user),
|
||||
return ctx.Result(200, &types.LoginReply{
|
||||
User: toTypesUserInfo(user),
|
||||
Token: token,
|
||||
ExpiresAt: claims.ExpiresAt.UnixMilli(),
|
||||
}, nil
|
||||
}
|
||||
|
||||
// RegisterRequest 注册请求
|
||||
type RegisterRequest struct {
|
||||
Username string `json:"username"`
|
||||
Password string `json:"password"`
|
||||
NickName string `json:"nickName"`
|
||||
HeaderImg string `json:"headerImg"`
|
||||
AuthorityId uint `json:"authorityId"`
|
||||
AuthorityIds []uint `json:"authorityIds"`
|
||||
Phone string `json:"phone"`
|
||||
Email string `json:"email"`
|
||||
Enable int `json:"enable"`
|
||||
})
|
||||
}
|
||||
|
||||
// Register 用户注册
|
||||
func (s *UserService) Register(ctx context.Context, req *RegisterRequest) (*UserInfo, error) {
|
||||
func (s *UserService) Register(ctx khttp.Context) error {
|
||||
var req types.RegisterRequest
|
||||
if err := ctx.Bind(&req); err != nil {
|
||||
return err
|
||||
}
|
||||
user := &system.User{
|
||||
Username: req.Username,
|
||||
Password: req.Password,
|
||||
@@ -121,66 +77,60 @@ func (s *UserService) Register(ctx context.Context, req *RegisterRequest) (*User
|
||||
Email: req.Email,
|
||||
Enable: req.Enable,
|
||||
}
|
||||
|
||||
created, err := s.uc.Register(ctx, user)
|
||||
if err != nil {
|
||||
return nil, errors.BadRequest("REGISTER_FAILED", err.Error())
|
||||
return errors.BadRequest("REGISTER_FAILED", err.Error())
|
||||
}
|
||||
|
||||
return toUserInfo(created), nil
|
||||
}
|
||||
|
||||
// ChangePasswordRequest 修改密码请求
|
||||
type ChangePasswordRequest struct {
|
||||
Password string `json:"password"`
|
||||
NewPassword string `json:"newPassword"`
|
||||
return ctx.Result(200, &types.UserInfoReply{User: toTypesUserInfo(created)})
|
||||
}
|
||||
|
||||
// ChangePassword 修改密码
|
||||
func (s *UserService) ChangePassword(ctx context.Context, userID uint, req *ChangePasswordRequest) error {
|
||||
return s.uc.ChangePassword(ctx, userID, req.Password, req.NewPassword)
|
||||
}
|
||||
|
||||
// ResetPasswordRequest 重置密码请求
|
||||
type ResetPasswordRequest struct {
|
||||
ID uint `json:"id"`
|
||||
Password string `json:"password"`
|
||||
func (s *UserService) ChangePassword(ctx khttp.Context) error {
|
||||
var req types.ChangePasswordRequest
|
||||
if err := ctx.Bind(&req); err != nil {
|
||||
return err
|
||||
}
|
||||
userID := middleware.GetUserID(ctx)
|
||||
if userID == 0 {
|
||||
return errors.Unauthorized("UNAUTHORIZED", "请先登录")
|
||||
}
|
||||
if err := s.uc.ChangePassword(ctx, userID, req.Password, req.NewPassword); err != nil {
|
||||
return errors.BadRequest("CHANGE_PASSWORD_FAILED", err.Error())
|
||||
}
|
||||
return ctx.Result(200, nil)
|
||||
}
|
||||
|
||||
// ResetPassword 重置密码
|
||||
func (s *UserService) ResetPassword(ctx context.Context, req *ResetPasswordRequest) error {
|
||||
return s.uc.ResetPassword(ctx, req.ID, req.Password)
|
||||
func (s *UserService) ResetPassword(ctx khttp.Context) error {
|
||||
var req types.ResetPasswordRequest
|
||||
if err := ctx.Bind(&req); err != nil {
|
||||
return err
|
||||
}
|
||||
if err := s.uc.ResetPassword(ctx, req.ID, req.Password); err != nil {
|
||||
return errors.BadRequest("RESET_PASSWORD_FAILED", err.Error())
|
||||
}
|
||||
return ctx.Result(200, nil)
|
||||
}
|
||||
|
||||
// GetUserInfo 获取用户信息
|
||||
func (s *UserService) GetUserInfo(ctx context.Context, uuid string) (*UserInfo, error) {
|
||||
user, err := s.uc.GetUserInfo(ctx, uuid)
|
||||
if err != nil {
|
||||
return nil, errors.NotFound("USER_NOT_FOUND", err.Error())
|
||||
func (s *UserService) GetUserInfo(ctx khttp.Context) error {
|
||||
claims, ok := middleware.GetClaims(ctx)
|
||||
if !ok {
|
||||
return errors.Unauthorized("UNAUTHORIZED", "请先登录")
|
||||
}
|
||||
return toUserInfo(user), nil
|
||||
}
|
||||
|
||||
// GetUserListRequest 获取用户列表请求
|
||||
type GetUserListRequest struct {
|
||||
Page int `json:"page"`
|
||||
PageSize int `json:"pageSize"`
|
||||
Username string `json:"username"`
|
||||
NickName string `json:"nickName"`
|
||||
Phone string `json:"phone"`
|
||||
Email string `json:"email"`
|
||||
}
|
||||
|
||||
// GetUserListResponse 获取用户列表响应
|
||||
type GetUserListResponse struct {
|
||||
List []*UserInfo `json:"list"`
|
||||
Total int64 `json:"total"`
|
||||
Page int `json:"page"`
|
||||
PageSize int `json:"pageSize"`
|
||||
user, err := s.uc.GetUserInfo(ctx, claims.UUID)
|
||||
if err != nil {
|
||||
return errors.NotFound("USER_NOT_FOUND", err.Error())
|
||||
}
|
||||
return ctx.Result(200, &types.GetUserInfoReply{UserInfo: toTypesUserInfo(user)})
|
||||
}
|
||||
|
||||
// GetUserList 获取用户列表
|
||||
func (s *UserService) GetUserList(ctx context.Context, req *GetUserListRequest) (*GetUserListResponse, error) {
|
||||
func (s *UserService) GetUserList(ctx khttp.Context) error {
|
||||
var req types.GetUserListRequest
|
||||
if err := ctx.Bind(&req); err != nil {
|
||||
return err
|
||||
}
|
||||
filters := make(map[string]string)
|
||||
if req.Username != "" {
|
||||
filters["username"] = req.Username
|
||||
@@ -194,45 +144,23 @@ func (s *UserService) GetUserList(ctx context.Context, req *GetUserListRequest)
|
||||
if req.Email != "" {
|
||||
filters["email"] = req.Email
|
||||
}
|
||||
|
||||
users, total, err := s.uc.GetUserList(ctx, req.Page, req.PageSize, filters)
|
||||
if err != nil {
|
||||
return nil, errors.InternalServer("LIST_ERROR", err.Error())
|
||||
return errors.InternalServer("LIST_ERROR", err.Error())
|
||||
}
|
||||
|
||||
list := make([]*UserInfo, len(users))
|
||||
list := make([]types.UserInfo, len(users))
|
||||
for i, u := range users {
|
||||
list[i] = toUserInfo(u)
|
||||
list[i] = toTypesUserInfo(u)
|
||||
}
|
||||
|
||||
return &GetUserListResponse{
|
||||
List: list,
|
||||
Total: total,
|
||||
Page: req.Page,
|
||||
PageSize: req.PageSize,
|
||||
}, nil
|
||||
}
|
||||
|
||||
// SetUserInfoRequest 设置用户信息请求(管理员用)
|
||||
type SetUserInfoRequest struct {
|
||||
ID uint `json:"id"`
|
||||
NickName string `json:"nickName"`
|
||||
HeaderImg string `json:"headerImg"`
|
||||
Phone string `json:"phone"`
|
||||
Email string `json:"email"`
|
||||
Enable int `json:"enable"`
|
||||
AuthorityIds []uint `json:"authorityIds"`
|
||||
return ctx.Result(200, &types.GetUserListReply{List: list, Total: total, Page: req.Page, PageSize: req.PageSize})
|
||||
}
|
||||
|
||||
// SetUserInfo 设置用户信息
|
||||
func (s *UserService) SetUserInfo(ctx context.Context, adminAuthorityID uint, req *SetUserInfoRequest) error {
|
||||
// 如果提供了AuthorityIds,先设置用户角色(与GVA保持一致)
|
||||
if len(req.AuthorityIds) > 0 {
|
||||
if err := s.uc.SetUserAuthorities(ctx, adminAuthorityID, req.ID, req.AuthorityIds); err != nil {
|
||||
return err
|
||||
}
|
||||
func (s *UserService) SetUserInfo(ctx khttp.Context) error {
|
||||
var req types.SetUserInfoRequest
|
||||
if err := ctx.Bind(&req); err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
user := &system.User{
|
||||
ID: req.ID,
|
||||
NickName: req.NickName,
|
||||
@@ -241,360 +169,177 @@ func (s *UserService) SetUserInfo(ctx context.Context, adminAuthorityID uint, re
|
||||
Email: req.Email,
|
||||
Enable: req.Enable,
|
||||
}
|
||||
return s.uc.SetUserInfo(ctx, user)
|
||||
if err := s.uc.SetUserInfo(ctx, user); err != nil {
|
||||
return errors.BadRequest("SET_USER_INFO_FAILED", err.Error())
|
||||
}
|
||||
if len(req.AuthorityIds) > 0 {
|
||||
adminAuthorityID := middleware.GetAuthorityID(ctx)
|
||||
if err := s.uc.SetUserAuthorities(ctx, adminAuthorityID, req.ID, req.AuthorityIds); err != nil {
|
||||
return errors.BadRequest("SET_USER_AUTHORITIES_FAILED", err.Error())
|
||||
}
|
||||
}
|
||||
return ctx.Result(200, nil)
|
||||
}
|
||||
|
||||
// SetSelfInfoRequest 设置自己信息请求(用户用)
|
||||
type SetSelfInfoRequest struct {
|
||||
NickName string `json:"nickName"`
|
||||
HeaderImg string `json:"headerImg"`
|
||||
Phone string `json:"phone"`
|
||||
Email string `json:"email"`
|
||||
SideMode string `json:"sideMode"`
|
||||
BaseColor string `json:"baseColor"`
|
||||
}
|
||||
|
||||
// SetSelfInfo 设置自己的信息
|
||||
func (s *UserService) SetSelfInfo(ctx context.Context, userID uint, req *SetSelfInfoRequest) error {
|
||||
// SetSelfInfo 设置自己信息
|
||||
func (s *UserService) SetSelfInfo(ctx khttp.Context) error {
|
||||
var req types.SetSelfInfoRequest
|
||||
if err := ctx.Bind(&req); err != nil {
|
||||
return err
|
||||
}
|
||||
userID := middleware.GetUserID(ctx)
|
||||
if userID == 0 {
|
||||
return errors.Unauthorized("UNAUTHORIZED", "请先登录")
|
||||
}
|
||||
user := &system.User{
|
||||
ID: userID,
|
||||
NickName: req.NickName,
|
||||
HeaderImg: req.HeaderImg,
|
||||
Phone: req.Phone,
|
||||
Email: req.Email,
|
||||
SideMode: req.SideMode,
|
||||
BaseColor: req.BaseColor,
|
||||
}
|
||||
return s.uc.SetSelfInfo(ctx, user)
|
||||
if err := s.uc.SetSelfInfo(ctx, user); err != nil {
|
||||
return errors.BadRequest("SET_SELF_INFO_FAILED", err.Error())
|
||||
}
|
||||
return ctx.Result(200, nil)
|
||||
}
|
||||
|
||||
// SetSelfSetting 设置自己的配置
|
||||
func (s *UserService) SetSelfSetting(ctx context.Context, userID uint, setting json.RawMessage) error {
|
||||
return s.uc.SetSelfSetting(ctx, userID, setting)
|
||||
// SetSelfSetting 设置自己配置
|
||||
func (s *UserService) SetSelfSetting(ctx khttp.Context) error {
|
||||
var req types.SetSelfSettingRequest
|
||||
if err := ctx.Bind(&req); err != nil {
|
||||
return err
|
||||
}
|
||||
userID := middleware.GetUserID(ctx)
|
||||
if userID == 0 {
|
||||
return errors.Unauthorized("UNAUTHORIZED", "请先登录")
|
||||
}
|
||||
setting := json.RawMessage(req.Setting)
|
||||
if err := s.uc.SetSelfSetting(ctx, userID, setting); err != nil {
|
||||
return errors.BadRequest("SET_SELF_SETTING_FAILED", err.Error())
|
||||
}
|
||||
return ctx.Result(200, nil)
|
||||
}
|
||||
|
||||
// DeleteUser 删除用户
|
||||
func (s *UserService) DeleteUser(ctx context.Context, id uint) error {
|
||||
return s.uc.DeleteUser(ctx, id)
|
||||
}
|
||||
|
||||
// SetUserAuthorityRequest 设置用户角色请求
|
||||
type SetUserAuthorityRequest struct {
|
||||
AuthorityId uint `json:"authorityId"`
|
||||
}
|
||||
|
||||
// SetUserAuthorityResponse 设置用户角色响应
|
||||
type SetUserAuthorityResponse struct {
|
||||
Token string `json:"token"`
|
||||
ExpiresAt int64 `json:"expiresAt"`
|
||||
}
|
||||
|
||||
// SetUserAuthority 设置用户角色(切换角色)- 返回新token
|
||||
func (s *UserService) SetUserAuthority(ctx context.Context, userID uint, uuid string, username string, nickName string, req *SetUserAuthorityRequest) (*SetUserAuthorityResponse, error) {
|
||||
if err := s.uc.SetUserAuthority(ctx, userID, req.AuthorityId); err != nil {
|
||||
return nil, err
|
||||
func (s *UserService) DeleteUser(ctx khttp.Context) error {
|
||||
var req types.DeleteUserRequest
|
||||
if err := ctx.Bind(&req); err != nil {
|
||||
return err
|
||||
}
|
||||
currentUserID := middleware.GetUserID(ctx)
|
||||
if currentUserID == req.ID {
|
||||
return errors.BadRequest("DELETE_FAILED", "无法删除自己")
|
||||
}
|
||||
if err := s.uc.DeleteUser(ctx, req.ID); err != nil {
|
||||
return errors.BadRequest("DELETE_FAILED", err.Error())
|
||||
}
|
||||
return ctx.Result(200, nil)
|
||||
}
|
||||
|
||||
// 生成新的JWT token(与GVA保持一致)
|
||||
claims := s.jwtPkg.CreateClaims(jwt.BaseClaims{
|
||||
UUID: uuid,
|
||||
ID: userID,
|
||||
Username: username,
|
||||
NickName: nickName,
|
||||
AuthorityID: req.AuthorityId,
|
||||
})
|
||||
// SetUserAuthority 设置用户角色
|
||||
func (s *UserService) SetUserAuthority(ctx khttp.Context) error {
|
||||
var req types.SetUserAuthorityRequest
|
||||
if err := ctx.Bind(&req); err != nil {
|
||||
return err
|
||||
}
|
||||
userID := middleware.GetUserID(ctx)
|
||||
if userID == 0 {
|
||||
return errors.Unauthorized("UNAUTHORIZED", "请先登录")
|
||||
}
|
||||
if err := s.uc.SetUserAuthority(ctx, userID, req.AuthorityId); err != nil {
|
||||
return errors.BadRequest("SET_AUTHORITY_FAILED", err.Error())
|
||||
}
|
||||
// 重新生成token
|
||||
claims, ok := middleware.GetClaims(ctx)
|
||||
if !ok {
|
||||
return errors.Unauthorized("UNAUTHORIZED", "请先登录")
|
||||
}
|
||||
claims.AuthorityID = req.AuthorityId
|
||||
token, err := s.jwtPkg.CreateToken(claims.BaseClaims)
|
||||
if err != nil {
|
||||
return nil, errors.InternalServer("TOKEN_ERROR", "生成token失败")
|
||||
return errors.InternalServer("TOKEN_ERROR", "生成token失败")
|
||||
}
|
||||
|
||||
return &SetUserAuthorityResponse{
|
||||
Token: token,
|
||||
ExpiresAt: claims.ExpiresAt.UnixMilli(),
|
||||
}, nil
|
||||
}
|
||||
|
||||
// SetUserAuthoritiesRequest 设置用户多角色请求
|
||||
type SetUserAuthoritiesRequest struct {
|
||||
ID uint `json:"id"`
|
||||
AuthorityIds []uint `json:"authorityIds"`
|
||||
return ctx.Result(200, &types.SetUserAuthorityReply{Token: token, ExpiresAt: claims.ExpiresAt.UnixMilli()})
|
||||
}
|
||||
|
||||
// SetUserAuthorities 设置用户多角色
|
||||
func (s *UserService) SetUserAuthorities(ctx context.Context, adminAuthorityID uint, req *SetUserAuthoritiesRequest) error {
|
||||
return s.uc.SetUserAuthorities(ctx, adminAuthorityID, req.ID, req.AuthorityIds)
|
||||
func (s *UserService) SetUserAuthorities(ctx khttp.Context) error {
|
||||
var req types.SetUserAuthoritiesRequest
|
||||
if err := ctx.Bind(&req); err != nil {
|
||||
return err
|
||||
}
|
||||
adminAuthorityID := middleware.GetAuthorityID(ctx)
|
||||
if err := s.uc.SetUserAuthorities(ctx, adminAuthorityID, req.ID, req.AuthorityIds); err != nil {
|
||||
return errors.BadRequest("SET_AUTHORITIES_FAILED", err.Error())
|
||||
}
|
||||
return ctx.Result(200, nil)
|
||||
}
|
||||
|
||||
// 转换函数
|
||||
func toUserInfo(u *system.User) *UserInfo {
|
||||
info := &UserInfo{
|
||||
ID: u.ID,
|
||||
UUID: u.UUID.String(),
|
||||
Username: u.Username,
|
||||
NickName: u.NickName,
|
||||
SideMode: u.SideMode,
|
||||
HeaderImg: u.HeaderImg,
|
||||
BaseColor: u.BaseColor,
|
||||
AuthorityId: u.AuthorityId,
|
||||
Phone: u.Phone,
|
||||
Email: u.Email,
|
||||
Enable: u.Enable,
|
||||
OriginSetting: u.OriginSetting,
|
||||
// toTypesUserInfo 转换用户信息为types格式
|
||||
func toTypesUserInfo(user *system.User) types.UserInfo {
|
||||
if user == nil {
|
||||
return types.UserInfo{}
|
||||
}
|
||||
|
||||
if u.Authority != nil {
|
||||
info.Authority = &AuthorityInfo{
|
||||
AuthorityId: u.Authority.AuthorityId,
|
||||
AuthorityName: u.Authority.AuthorityName,
|
||||
ParentId: u.Authority.ParentId,
|
||||
DefaultRouter: u.Authority.DefaultRouter,
|
||||
info := types.UserInfo{
|
||||
ID: user.ID,
|
||||
UUID: user.UUID.String(),
|
||||
Username: user.Username,
|
||||
NickName: user.NickName,
|
||||
SideMode: user.SideMode,
|
||||
HeaderImg: user.HeaderImg,
|
||||
BaseColor: user.BaseColor,
|
||||
AuthorityId: user.AuthorityId,
|
||||
Phone: user.Phone,
|
||||
Email: user.Email,
|
||||
Enable: user.Enable,
|
||||
}
|
||||
if user.OriginSetting != nil {
|
||||
info.OriginSetting = string(user.OriginSetting)
|
||||
}
|
||||
if user.Authority != nil {
|
||||
auth := toTypesAuthorityInfo(user.Authority)
|
||||
info.Authority = &auth
|
||||
}
|
||||
if len(user.Authorities) > 0 {
|
||||
info.Authorities = make([]types.AuthorityInfo, len(user.Authorities))
|
||||
for i, a := range user.Authorities {
|
||||
info.Authorities[i] = toTypesAuthorityInfo(a)
|
||||
}
|
||||
}
|
||||
|
||||
if len(u.Authorities) > 0 {
|
||||
info.Authorities = make([]*AuthorityInfo, len(u.Authorities))
|
||||
for i, a := range u.Authorities {
|
||||
info.Authorities[i] = &AuthorityInfo{
|
||||
AuthorityId: a.AuthorityId,
|
||||
AuthorityName: a.AuthorityName,
|
||||
ParentId: a.ParentId,
|
||||
DefaultRouter: a.DefaultRouter,
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return info
|
||||
}
|
||||
|
||||
// RegisterRoutes 注册路由
|
||||
func (s *UserService) RegisterRoutes(srv *http.Server) {
|
||||
r := srv.Route("/")
|
||||
|
||||
// 公开接口
|
||||
r.POST("/base/login", s.handleLogin)
|
||||
|
||||
// 需要认证的接口
|
||||
r.POST("/user/register", s.handleRegister)
|
||||
r.POST("/user/changePassword", s.handleChangePassword)
|
||||
r.POST("/user/resetPassword", s.handleResetPassword)
|
||||
r.GET("/user/getUserInfo", s.handleGetUserInfo)
|
||||
r.POST("/user/getUserList", s.handleGetUserList)
|
||||
r.PUT("/user/setUserInfo", s.handleSetUserInfo)
|
||||
r.PUT("/user/setSelfInfo", s.handleSetSelfInfo)
|
||||
r.PUT("/user/setSelfSetting", s.handleSetSelfSetting)
|
||||
r.DELETE("/user/deleteUser", s.handleDeleteUser)
|
||||
r.POST("/user/setUserAuthority", s.handleSetUserAuthority)
|
||||
r.POST("/user/setUserAuthorities", s.handleSetUserAuthorities)
|
||||
// toTypesAuthorityInfo 转换角色信息为types格式
|
||||
func toTypesAuthorityInfo(auth *system.Authority) types.AuthorityInfo {
|
||||
if auth == nil {
|
||||
return types.AuthorityInfo{}
|
||||
}
|
||||
return types.AuthorityInfo{
|
||||
AuthorityId: auth.AuthorityId,
|
||||
AuthorityName: auth.AuthorityName,
|
||||
ParentId: auth.ParentId,
|
||||
DefaultRouter: auth.DefaultRouter,
|
||||
}
|
||||
}
|
||||
|
||||
// HTTP Handlers
|
||||
func (s *UserService) handleLogin(ctx http.Context) error {
|
||||
var req LoginRequest
|
||||
if err := ctx.Bind(&req); err != nil {
|
||||
return err
|
||||
}
|
||||
resp, err := s.Login(ctx, &req)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
return ctx.Result(200, map[string]any{
|
||||
"code": 0,
|
||||
"msg": "登录成功",
|
||||
"data": resp,
|
||||
})
|
||||
}
|
||||
// RegisterRoutes 注册用户路由
|
||||
func (s *UserService) RegisterRoutes(rg *RouterGroup) {
|
||||
// 公开路由(无需认证)
|
||||
rg.Public.POST("/base/login", s.Login)
|
||||
|
||||
func (s *UserService) handleRegister(ctx http.Context) error {
|
||||
var req RegisterRequest
|
||||
if err := ctx.Bind(&req); err != nil {
|
||||
return err
|
||||
}
|
||||
resp, err := s.Register(ctx, &req)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
return ctx.Result(200, map[string]any{
|
||||
"code": 0,
|
||||
"msg": "注册成功",
|
||||
"data": resp,
|
||||
})
|
||||
}
|
||||
// 私有路由 + 操作记录(写操作)
|
||||
rg.PrivateWithRecord.POST("/user/admin_register", s.Register)
|
||||
rg.PrivateWithRecord.POST("/user/changePassword", s.ChangePassword)
|
||||
rg.PrivateWithRecord.POST("/user/setUserAuthority", s.SetUserAuthority)
|
||||
rg.PrivateWithRecord.DELETE("/user/deleteUser", s.DeleteUser)
|
||||
rg.PrivateWithRecord.PUT("/user/setUserInfo", s.SetUserInfo)
|
||||
rg.PrivateWithRecord.PUT("/user/setSelfInfo", s.SetSelfInfo)
|
||||
rg.PrivateWithRecord.POST("/user/setUserAuthorities", s.SetUserAuthorities)
|
||||
rg.PrivateWithRecord.POST("/user/resetPassword", s.ResetPassword)
|
||||
rg.PrivateWithRecord.PUT("/user/setSelfSetting", s.SetSelfSetting)
|
||||
|
||||
func (s *UserService) handleChangePassword(ctx http.Context) error {
|
||||
var req ChangePasswordRequest
|
||||
if err := ctx.Bind(&req); err != nil {
|
||||
return err
|
||||
}
|
||||
userID := middleware.GetUserID(ctx)
|
||||
if userID == 0 {
|
||||
return errors.Unauthorized("UNAUTHORIZED", "请先登录")
|
||||
}
|
||||
if err := s.ChangePassword(ctx, userID, &req); err != nil {
|
||||
return err
|
||||
}
|
||||
return ctx.Result(200, map[string]any{
|
||||
"code": 0,
|
||||
"msg": "修改成功",
|
||||
})
|
||||
}
|
||||
|
||||
func (s *UserService) handleResetPassword(ctx http.Context) error {
|
||||
var req ResetPasswordRequest
|
||||
if err := ctx.Bind(&req); err != nil {
|
||||
return err
|
||||
}
|
||||
if err := s.ResetPassword(ctx, &req); err != nil {
|
||||
return err
|
||||
}
|
||||
return ctx.Result(200, map[string]any{
|
||||
"code": 0,
|
||||
"msg": "重置成功",
|
||||
})
|
||||
}
|
||||
|
||||
func (s *UserService) handleGetUserInfo(ctx http.Context) error {
|
||||
claims, ok := middleware.GetClaims(ctx)
|
||||
if !ok {
|
||||
return errors.Unauthorized("UNAUTHORIZED", "请先登录")
|
||||
}
|
||||
resp, err := s.GetUserInfo(ctx, claims.UUID)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
return ctx.Result(200, map[string]any{
|
||||
"code": 0,
|
||||
"msg": "获取成功",
|
||||
"data": map[string]any{"userInfo": resp},
|
||||
})
|
||||
}
|
||||
|
||||
func (s *UserService) handleGetUserList(ctx http.Context) error {
|
||||
var req GetUserListRequest
|
||||
if err := ctx.Bind(&req); err != nil {
|
||||
return err
|
||||
}
|
||||
resp, err := s.GetUserList(ctx, &req)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
return ctx.Result(200, map[string]any{
|
||||
"code": 0,
|
||||
"msg": "获取成功",
|
||||
"data": resp,
|
||||
})
|
||||
}
|
||||
|
||||
func (s *UserService) handleSetUserInfo(ctx http.Context) error {
|
||||
var req SetUserInfoRequest
|
||||
if err := ctx.Bind(&req); err != nil {
|
||||
return err
|
||||
}
|
||||
adminAuthorityID := middleware.GetAuthorityID(ctx)
|
||||
if adminAuthorityID == 0 {
|
||||
return errors.Unauthorized("UNAUTHORIZED", "请先登录")
|
||||
}
|
||||
if err := s.SetUserInfo(ctx, adminAuthorityID, &req); err != nil {
|
||||
return err
|
||||
}
|
||||
return ctx.Result(200, map[string]any{
|
||||
"code": 0,
|
||||
"msg": "设置成功",
|
||||
})
|
||||
}
|
||||
|
||||
func (s *UserService) handleSetSelfInfo(ctx http.Context) error {
|
||||
var req SetSelfInfoRequest
|
||||
if err := ctx.Bind(&req); err != nil {
|
||||
return err
|
||||
}
|
||||
userID := middleware.GetUserID(ctx)
|
||||
if userID == 0 {
|
||||
return errors.Unauthorized("UNAUTHORIZED", "请先登录")
|
||||
}
|
||||
if err := s.SetSelfInfo(ctx, userID, &req); err != nil {
|
||||
return err
|
||||
}
|
||||
return ctx.Result(200, map[string]any{
|
||||
"code": 0,
|
||||
"msg": "设置成功",
|
||||
})
|
||||
}
|
||||
|
||||
func (s *UserService) handleSetSelfSetting(ctx http.Context) error {
|
||||
var req json.RawMessage
|
||||
if err := ctx.Bind(&req); err != nil {
|
||||
return err
|
||||
}
|
||||
userID := middleware.GetUserID(ctx)
|
||||
if userID == 0 {
|
||||
return errors.Unauthorized("UNAUTHORIZED", "请先登录")
|
||||
}
|
||||
if err := s.SetSelfSetting(ctx, userID, req); err != nil {
|
||||
return err
|
||||
}
|
||||
return ctx.Result(200, map[string]any{
|
||||
"code": 0,
|
||||
"msg": "设置成功",
|
||||
})
|
||||
}
|
||||
|
||||
func (s *UserService) handleDeleteUser(ctx http.Context) error {
|
||||
var req struct {
|
||||
ID uint `json:"id"`
|
||||
}
|
||||
if err := ctx.Bind(&req); err != nil {
|
||||
return err
|
||||
}
|
||||
// 不能删除自己
|
||||
userID := middleware.GetUserID(ctx)
|
||||
if userID == req.ID {
|
||||
return errors.BadRequest("DELETE_SELF", "删除失败, 无法删除自己")
|
||||
}
|
||||
if err := s.DeleteUser(ctx, req.ID); err != nil {
|
||||
return err
|
||||
}
|
||||
return ctx.Result(200, map[string]any{
|
||||
"code": 0,
|
||||
"msg": "删除成功",
|
||||
})
|
||||
}
|
||||
|
||||
func (s *UserService) handleSetUserAuthority(ctx http.Context) error {
|
||||
var req SetUserAuthorityRequest
|
||||
if err := ctx.Bind(&req); err != nil {
|
||||
return err
|
||||
}
|
||||
claims, ok := middleware.GetClaims(ctx)
|
||||
if !ok {
|
||||
return errors.Unauthorized("UNAUTHORIZED", "请先登录")
|
||||
}
|
||||
resp, err := s.SetUserAuthority(ctx, claims.BaseClaims.ID, claims.UUID, claims.Username, claims.NickName, &req)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
// 设置响应头(与GVA保持一致)
|
||||
ctx.Response().Header().Set("new-token", resp.Token)
|
||||
ctx.Response().Header().Set("new-expires-at", fmt.Sprintf("%d", resp.ExpiresAt/1000))
|
||||
return ctx.Result(200, map[string]any{
|
||||
"code": 0,
|
||||
"msg": "修改成功",
|
||||
})
|
||||
}
|
||||
|
||||
func (s *UserService) handleSetUserAuthorities(ctx http.Context) error {
|
||||
var req SetUserAuthoritiesRequest
|
||||
if err := ctx.Bind(&req); err != nil {
|
||||
return err
|
||||
}
|
||||
adminAuthorityID := middleware.GetAuthorityID(ctx)
|
||||
if adminAuthorityID == 0 {
|
||||
return errors.Unauthorized("UNAUTHORIZED", "请先登录")
|
||||
}
|
||||
if err := s.SetUserAuthorities(ctx, adminAuthorityID, &req); err != nil {
|
||||
return err
|
||||
}
|
||||
return ctx.Result(200, map[string]any{
|
||||
"code": 0,
|
||||
"msg": "修改成功",
|
||||
})
|
||||
// 私有路由(读操作,不记录)
|
||||
rg.Private.POST("/user/getUserList", s.GetUserList)
|
||||
rg.Private.GET("/user/getUserInfo", s.GetUserInfo)
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user