任务三
This commit is contained in:
parent
1a06053b30
commit
c83b773a40
|
|
@ -0,0 +1,60 @@
|
|||
package system
|
||||
|
||||
import "context"
|
||||
|
||||
// JwtBlacklist JWT黑名单实体
|
||||
type JwtBlacklist struct {
|
||||
ID uint
|
||||
Jwt string
|
||||
}
|
||||
|
||||
// JwtBlacklistRepo JWT黑名单仓储接口
|
||||
type JwtBlacklistRepo interface {
|
||||
Create(ctx context.Context, jwt string) error
|
||||
IsInBlacklist(ctx context.Context, jwt string) bool
|
||||
LoadAll(ctx context.Context) ([]string, error)
|
||||
}
|
||||
|
||||
// JwtBlacklistUsecase JWT黑名单用例
|
||||
type JwtBlacklistUsecase struct {
|
||||
repo JwtBlacklistRepo
|
||||
cache map[string]struct{} // 内存缓存
|
||||
}
|
||||
|
||||
// NewJwtBlacklistUsecase 创建JWT黑名单用例
|
||||
func NewJwtBlacklistUsecase(repo JwtBlacklistRepo) *JwtBlacklistUsecase {
|
||||
uc := &JwtBlacklistUsecase{
|
||||
repo: repo,
|
||||
cache: make(map[string]struct{}),
|
||||
}
|
||||
// 加载黑名单到缓存
|
||||
uc.LoadAll(context.Background())
|
||||
return uc
|
||||
}
|
||||
|
||||
// JoinBlacklist 加入黑名单
|
||||
func (uc *JwtBlacklistUsecase) JoinBlacklist(ctx context.Context, jwt string) error {
|
||||
if err := uc.repo.Create(ctx, jwt); err != nil {
|
||||
return err
|
||||
}
|
||||
uc.cache[jwt] = struct{}{}
|
||||
return nil
|
||||
}
|
||||
|
||||
// IsInBlacklist 检查是否在黑名单中
|
||||
func (uc *JwtBlacklistUsecase) IsInBlacklist(jwt string) bool {
|
||||
_, ok := uc.cache[jwt]
|
||||
return ok
|
||||
}
|
||||
|
||||
// LoadAll 加载所有黑名单到缓存
|
||||
func (uc *JwtBlacklistUsecase) LoadAll(ctx context.Context) error {
|
||||
jwts, err := uc.repo.LoadAll(ctx)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
for _, jwt := range jwts {
|
||||
uc.cache[jwt] = struct{}{}
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
|
@ -0,0 +1,37 @@
|
|||
package system
|
||||
|
||||
import (
|
||||
"context"
|
||||
|
||||
"kra/internal/biz/system"
|
||||
"kra/internal/data/model"
|
||||
"kra/internal/data/query"
|
||||
|
||||
"gorm.io/gorm"
|
||||
)
|
||||
|
||||
type jwtBlacklistRepo struct {
|
||||
db *gorm.DB
|
||||
}
|
||||
|
||||
// NewJwtBlacklistRepo 创建JWT黑名单仓储
|
||||
func NewJwtBlacklistRepo(db *gorm.DB) system.JwtBlacklistRepo {
|
||||
query.SetDefault(db)
|
||||
return &jwtBlacklistRepo{db: db}
|
||||
}
|
||||
|
||||
func (r *jwtBlacklistRepo) Create(ctx context.Context, jwt string) error {
|
||||
m := &model.JwtBlacklist{Jwt: jwt}
|
||||
return query.JwtBlacklist.WithContext(ctx).Create(m)
|
||||
}
|
||||
|
||||
func (r *jwtBlacklistRepo) IsInBlacklist(ctx context.Context, jwt string) bool {
|
||||
count, _ := query.JwtBlacklist.WithContext(ctx).Where(query.JwtBlacklist.Jwt.Eq(jwt)).Count()
|
||||
return count > 0
|
||||
}
|
||||
|
||||
func (r *jwtBlacklistRepo) LoadAll(ctx context.Context) ([]string, error) {
|
||||
var jwts []string
|
||||
err := r.db.WithContext(ctx).Model(&model.JwtBlacklist{}).Pluck("jwt", &jwts).Error
|
||||
return jwts, err
|
||||
}
|
||||
|
|
@ -220,18 +220,54 @@ func (r *userRepo) SetUserAuthorities(ctx context.Context, adminAuthorityID, use
|
|||
}
|
||||
|
||||
func checkAuthorityIDAuth(tx *gorm.DB, adminAuthorityID, targetAuthorityID uint) error {
|
||||
// 超级管理员(888)直接通过
|
||||
if adminAuthorityID == 888 {
|
||||
return nil
|
||||
}
|
||||
var authority model.SysAuthority
|
||||
if err := tx.Where("authority_id = ? AND parent_id = ?", targetAuthorityID, adminAuthorityID).First(&authority).Error; err != nil {
|
||||
if errors.Is(err, gorm.ErrRecordNotFound) {
|
||||
return errors.New("您没有权限分配该角色")
|
||||
}
|
||||
|
||||
// 获取管理员角色的所有子角色ID(递归)
|
||||
authIDs, err := getStructAuthorityList(tx, adminAuthorityID)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
// 检查目标角色是否在权限列表中
|
||||
for _, id := range authIDs {
|
||||
if id == targetAuthorityID {
|
||||
return nil
|
||||
}
|
||||
}
|
||||
return errors.New("您没有权限分配该角色")
|
||||
}
|
||||
|
||||
// getStructAuthorityList 递归获取角色ID列表(包含子角色)
|
||||
func getStructAuthorityList(tx *gorm.DB, authorityID uint) ([]uint, error) {
|
||||
var auth model.SysAuthority
|
||||
if err := tx.First(&auth, "authority_id = ?", authorityID).Error; err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
var list []uint
|
||||
var children []model.SysAuthority
|
||||
if err := tx.Where("parent_id = ?", authorityID).Find(&children).Error; err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
for _, child := range children {
|
||||
list = append(list, uint(child.AuthorityID))
|
||||
childList, err := getStructAuthorityList(tx, uint(child.AuthorityID))
|
||||
if err == nil {
|
||||
list = append(list, childList...)
|
||||
}
|
||||
}
|
||||
|
||||
// 如果是顶级角色,包含自己
|
||||
if auth.ParentID == 0 {
|
||||
list = append(list, authorityID)
|
||||
}
|
||||
|
||||
return list, nil
|
||||
}
|
||||
|
||||
func (r *userRepo) CheckUserHasAuthority(ctx context.Context, userId, authorityId uint) (bool, error) {
|
||||
var count int64
|
||||
|
|
|
|||
|
|
@ -154,3 +154,11 @@ func GetAuthorityID(ctx context.Context) uint {
|
|||
}
|
||||
return 0
|
||||
}
|
||||
|
||||
// GetToken 从context获取token
|
||||
func GetToken(ctx context.Context) string {
|
||||
if tr, ok := transport.FromServerContext(ctx); ok {
|
||||
return extractToken(tr)
|
||||
}
|
||||
return ""
|
||||
}
|
||||
|
|
|
|||
|
|
@ -0,0 +1,40 @@
|
|||
package system
|
||||
|
||||
import (
|
||||
"kra/internal/biz/system"
|
||||
"kra/internal/server/middleware"
|
||||
|
||||
"github.com/go-kratos/kratos/v2/errors"
|
||||
"github.com/go-kratos/kratos/v2/transport/http"
|
||||
)
|
||||
|
||||
// JwtBlacklistService JWT黑名单服务
|
||||
type JwtBlacklistService struct {
|
||||
uc *system.JwtBlacklistUsecase
|
||||
}
|
||||
|
||||
// NewJwtBlacklistService 创建JWT黑名单服务
|
||||
func NewJwtBlacklistService(uc *system.JwtBlacklistUsecase) *JwtBlacklistService {
|
||||
return &JwtBlacklistService{uc: uc}
|
||||
}
|
||||
|
||||
// JoinBlacklist 加入黑名单(登出时调用)
|
||||
func (s *JwtBlacklistService) JoinBlacklist(ctx http.Context) error {
|
||||
token := middleware.GetToken(ctx)
|
||||
if token == "" {
|
||||
return errors.BadRequest("TOKEN_EMPTY", "token为空")
|
||||
}
|
||||
if err := s.uc.JoinBlacklist(ctx, token); err != nil {
|
||||
return errors.InternalServer("BLACKLIST_ERROR", err.Error())
|
||||
}
|
||||
return ctx.Result(200, map[string]any{
|
||||
"code": 0,
|
||||
"msg": "登出成功",
|
||||
})
|
||||
}
|
||||
|
||||
// RegisterRoutes 注册路由
|
||||
func (s *JwtBlacklistService) RegisterRoutes(srv *http.Server) {
|
||||
r := srv.Route("/")
|
||||
r.POST("/jwt/jsonInBlacklist", s.JoinBlacklist)
|
||||
}
|
||||
|
|
@ -1,7 +1,7 @@
|
|||
package system
|
||||
|
||||
import (
|
||||
"context"
|
||||
"fmt"
|
||||
|
||||
"kra/internal/biz/system"
|
||||
|
||||
|
|
@ -21,7 +21,7 @@ func NewOperationRecordService(uc *system.OperationRecordUsecase) *OperationReco
|
|||
|
||||
// OperationRecordInfo 操作记录信息
|
||||
type OperationRecordInfo struct {
|
||||
ID uint `json:"ID"`
|
||||
ID uint `json:"id"`
|
||||
IP string `json:"ip"`
|
||||
Method string `json:"method"`
|
||||
Path string `json:"path"`
|
||||
|
|
@ -35,30 +35,6 @@ type OperationRecordInfo struct {
|
|||
User *UserInfo `json:"user,omitempty"`
|
||||
}
|
||||
|
||||
// DeleteOperationRecord 删除操作记录
|
||||
func (s *OperationRecordService) DeleteOperationRecord(ctx context.Context, id uint) error {
|
||||
return s.uc.DeleteOperationRecord(ctx, id)
|
||||
}
|
||||
|
||||
// DeleteOperationRecordByIdsRequest 批量删除请求
|
||||
type DeleteOperationRecordByIdsRequest struct {
|
||||
Ids []uint `json:"ids"`
|
||||
}
|
||||
|
||||
// DeleteOperationRecordByIds 批量删除操作记录
|
||||
func (s *OperationRecordService) DeleteOperationRecordByIds(ctx context.Context, req *DeleteOperationRecordByIdsRequest) error {
|
||||
return s.uc.DeleteOperationRecordByIds(ctx, req.Ids)
|
||||
}
|
||||
|
||||
// GetOperationRecord 获取操作记录
|
||||
func (s *OperationRecordService) GetOperationRecord(ctx context.Context, id uint) (*OperationRecordInfo, error) {
|
||||
record, err := s.uc.GetOperationRecord(ctx, id)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
return toOperationRecordInfo(record), nil
|
||||
}
|
||||
|
||||
// GetOperationRecordListRequest 获取操作记录列表请求
|
||||
type GetOperationRecordListRequest struct {
|
||||
Page int `json:"page"`
|
||||
|
|
@ -66,6 +42,7 @@ type GetOperationRecordListRequest struct {
|
|||
Method string `json:"method"`
|
||||
Path string `json:"path"`
|
||||
Status int `json:"status"`
|
||||
UserID uint `json:"user_id"`
|
||||
}
|
||||
|
||||
// GetOperationRecordListResponse 获取操作记录列表响应
|
||||
|
|
@ -76,8 +53,30 @@ type GetOperationRecordListResponse struct {
|
|||
PageSize int `json:"pageSize"`
|
||||
}
|
||||
|
||||
// GetOperationRecordList 获取操作记录列表
|
||||
func (s *OperationRecordService) GetOperationRecordList(ctx context.Context, req *GetOperationRecordListRequest) (*GetOperationRecordListResponse, error) {
|
||||
// DeleteOperationRecordRequest 删除操作记录请求
|
||||
type DeleteOperationRecordRequest struct {
|
||||
ID uint `json:"id"`
|
||||
}
|
||||
|
||||
// DeleteOperationRecordByIdsRequest 批量删除操作记录请求
|
||||
type DeleteOperationRecordByIdsRequest struct {
|
||||
IDs []uint `json:"ids"`
|
||||
}
|
||||
|
||||
// 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) handleGetList(ctx http.Context) error {
|
||||
var req GetOperationRecordListRequest
|
||||
if err := ctx.Bind(&req); err != nil {
|
||||
return err
|
||||
}
|
||||
filters := make(map[string]interface{})
|
||||
if req.Method != "" {
|
||||
filters["method"] = req.Method
|
||||
|
|
@ -88,26 +87,63 @@ func (s *OperationRecordService) GetOperationRecordList(ctx context.Context, req
|
|||
if req.Status != 0 {
|
||||
filters["status"] = req.Status
|
||||
}
|
||||
|
||||
if req.UserID != 0 {
|
||||
filters["user_id"] = req.UserID
|
||||
}
|
||||
list, total, err := s.uc.GetOperationRecordList(ctx, req.Page, req.PageSize, filters)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
return errors.InternalServer("LIST_ERROR", err.Error())
|
||||
}
|
||||
|
||||
result := make([]*OperationRecordInfo, len(list))
|
||||
for i, r := range list {
|
||||
result[i] = toOperationRecordInfo(r)
|
||||
}
|
||||
|
||||
return &GetOperationRecordListResponse{
|
||||
List: result,
|
||||
resp := &GetOperationRecordListResponse{
|
||||
List: make([]*OperationRecordInfo, len(list)),
|
||||
Total: total,
|
||||
Page: req.Page,
|
||||
PageSize: req.PageSize,
|
||||
}, nil
|
||||
}
|
||||
for i, r := range list {
|
||||
resp.List[i] = toOperationRecordInfo(r)
|
||||
}
|
||||
return ctx.Result(200, map[string]any{"code": 0, "msg": "获取成功", "data": resp})
|
||||
}
|
||||
|
||||
func (s *OperationRecordService) handleDelete(ctx http.Context) error {
|
||||
var req DeleteOperationRecordRequest
|
||||
if err := ctx.Bind(&req); err != nil {
|
||||
return err
|
||||
}
|
||||
if err := s.uc.DeleteOperationRecord(ctx, req.ID); err != nil {
|
||||
return errors.InternalServer("DELETE_ERROR", err.Error())
|
||||
}
|
||||
return ctx.Result(200, map[string]any{"code": 0, "msg": "删除成功"})
|
||||
}
|
||||
|
||||
func (s *OperationRecordService) handleDeleteByIds(ctx http.Context) error {
|
||||
var req DeleteOperationRecordByIdsRequest
|
||||
if err := ctx.Bind(&req); err != nil {
|
||||
return err
|
||||
}
|
||||
if err := s.uc.DeleteOperationRecordByIds(ctx, req.IDs); err != nil {
|
||||
return errors.InternalServer("DELETE_ERROR", err.Error())
|
||||
}
|
||||
return ctx.Result(200, map[string]any{"code": 0, "msg": "批量删除成功"})
|
||||
}
|
||||
|
||||
func (s *OperationRecordService) handleFind(ctx http.Context) error {
|
||||
idStr := ctx.Request().URL.Query().Get("id")
|
||||
if idStr == "" {
|
||||
return errors.BadRequest("INVALID_ID", "id参数不能为空")
|
||||
}
|
||||
var id uint
|
||||
if _, err := fmt.Sscanf(idStr, "%d", &id); err != nil {
|
||||
return errors.BadRequest("INVALID_ID", "id参数格式错误")
|
||||
}
|
||||
record, err := s.uc.GetOperationRecord(ctx, id)
|
||||
if err != nil {
|
||||
return errors.NotFound("NOT_FOUND", err.Error())
|
||||
}
|
||||
return ctx.Result(200, map[string]any{"code": 0, "msg": "获取成功", "data": toOperationRecordInfo(record)})
|
||||
}
|
||||
|
||||
// 转换函数
|
||||
func toOperationRecordInfo(r *system.OperationRecord) *OperationRecordInfo {
|
||||
info := &OperationRecordInfo{
|
||||
ID: r.ID,
|
||||
|
|
@ -127,60 +163,3 @@ func toOperationRecordInfo(r *system.OperationRecord) *OperationRecordInfo {
|
|||
}
|
||||
return info
|
||||
}
|
||||
|
||||
// RegisterRoutes 注册路由
|
||||
func (s *OperationRecordService) RegisterRoutes(srv *http.Server) {
|
||||
r := srv.Route("/")
|
||||
|
||||
r.DELETE("/sysOperationRecord/deleteSysOperationRecord", s.handleDeleteOperationRecord)
|
||||
r.DELETE("/sysOperationRecord/deleteSysOperationRecordByIds", s.handleDeleteOperationRecordByIds)
|
||||
r.GET("/sysOperationRecord/findSysOperationRecord", s.handleGetOperationRecord)
|
||||
r.GET("/sysOperationRecord/getSysOperationRecordList", s.handleGetOperationRecordList)
|
||||
}
|
||||
|
||||
// HTTP Handlers
|
||||
func (s *OperationRecordService) handleDeleteOperationRecord(ctx http.Context) error {
|
||||
var req struct {
|
||||
ID uint `json:"ID"`
|
||||
}
|
||||
if err := ctx.Bind(&req); err != nil {
|
||||
return err
|
||||
}
|
||||
if err := s.DeleteOperationRecord(ctx, req.ID); err != nil {
|
||||
return errors.BadRequest("DELETE_FAILED", err.Error())
|
||||
}
|
||||
return ctx.Result(200, map[string]any{"code": 0, "msg": "删除成功"})
|
||||
}
|
||||
|
||||
func (s *OperationRecordService) handleDeleteOperationRecordByIds(ctx http.Context) error {
|
||||
var req DeleteOperationRecordByIdsRequest
|
||||
if err := ctx.Bind(&req); err != nil {
|
||||
return err
|
||||
}
|
||||
if err := s.DeleteOperationRecordByIds(ctx, &req); err != nil {
|
||||
return errors.BadRequest("DELETE_FAILED", err.Error())
|
||||
}
|
||||
return ctx.Result(200, map[string]any{"code": 0, "msg": "删除成功"})
|
||||
}
|
||||
|
||||
func (s *OperationRecordService) handleGetOperationRecord(ctx http.Context) error {
|
||||
idStr := ctx.Query().Get("ID")
|
||||
id, _ := parseUint(idStr)
|
||||
resp, err := s.GetOperationRecord(ctx, 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{"reSysOperationRecord": resp}})
|
||||
}
|
||||
|
||||
func (s *OperationRecordService) handleGetOperationRecordList(ctx http.Context) error {
|
||||
var req GetOperationRecordListRequest
|
||||
if err := ctx.BindQuery(&req); err != nil {
|
||||
return err
|
||||
}
|
||||
resp, err := s.GetOperationRecordList(ctx, &req)
|
||||
if err != nil {
|
||||
return errors.InternalServer("LIST_ERROR", err.Error())
|
||||
}
|
||||
return ctx.Result(200, map[string]any{"code": 0, "msg": "获取成功", "data": resp})
|
||||
}
|
||||
|
|
|
|||
Loading…
Reference in New Issue