瀏覽代碼

增加权限

xjg 4 月之前
父節點
當前提交
84bbe7d9ff

+ 5 - 3
Makefile

@@ -12,8 +12,6 @@ user:
 role:
 	protoc --proto_path=. --micro_out=. --go_out=:. proto/admin_role_service.proto
 
-
-
 .PHONY: base
 base:
 	protoc --proto_path=. --micro_out=. --go_out=:. proto/base_service.proto
@@ -24,4 +22,8 @@ health:
 
 .PHONY: auth
 auth:
-	protoc --proto_path=. --micro_out=. --go_out=:. proto/authentication.proto
+	protoc --proto_path=. --micro_out=. --go_out=:. proto/authentication.proto
+
+.PHONY: permission
+permission:
+	protoc --proto_path=. --micro_out=. --go_out=:. proto/admin_permission_service.proto

+ 10 - 0
domain/model/base/base.go

@@ -75,3 +75,13 @@ func PermissionsToProto(permissions []req.AdminPermission) []*pb.AdminBase {
 	}
 	return bases
 }
+func RolesProto(roles []req.AdminRole) []*pb.AdminBase {
+	bases := make([]*pb.AdminBase, 0)
+	for _, role := range roles {
+		bases = append(bases, &pb.AdminBase{
+			Key:   role.Name,
+			Value: fmt.Sprintf("%d", role.ID),
+		})
+	}
+	return bases
+}

+ 15 - 10
domain/model/request/admin_permission.go

@@ -1,15 +1,20 @@
 package request
 
-import "time"
+import (
+	pb "sghgogs.com/sghblog/authorization-service/proto"
+	"time"
+)
 
 type AdminPermission struct {
-	ID          int64       `gorm:"primary_key;not_null;auto_increment;" json:"id"`
-	Name        string      `json:"name"`
-	Description string      `json:"description"`
-	Roles       []AdminRole `gorm:"many2many:admin_role_permission;" json:"roles"`
-	CreatedAt   time.Time   `json:"created_at"`
-	CreatedBy   string      `json:"created_by"`
-	UpdatedAt   *time.Time  `json:"updated_at"`
-	Status      string      `json:"status"` // 可以是 "enabled", "disabled", "deleted" 等
-	IsReserved  bool        `json:"is_reserved"`
+	ID          int64         `gorm:"primary_key;not_null;auto_increment;" json:"id"`
+	Name        string        `json:"name"`
+	Endpoint    string        `json:"endpoint"`
+	Description string        `json:"description"`
+	Roles       []AdminRole   `gorm:"many2many:admin_role_permission;" json:"roles"`
+	CreatedAt   time.Time     `json:"created_at"`
+	CreatedBy   string        `json:"created_by"`
+	UpdatedAt   *time.Time    `json:"updated_at"`
+	UpdatedBy   string        `json:"updated_by"`
+	Status      pb.StatusEnum `json:"status"` // 可以是 "enabled", "disabled", "deleted" 等
+	IsReserved  bool          `json:"is_reserved"`
 }

+ 184 - 0
domain/repository/admin_permission.go

@@ -0,0 +1,184 @@
+package repository
+
+import (
+	"fmt"
+	"github.com/pkg/errors"
+	"gorm.io/gorm"
+	"sghgogs.com/sghblog/authorization-service/domain/model/base"
+	req "sghgogs.com/sghblog/authorization-service/domain/model/request"
+	pb "sghgogs.com/sghblog/authorization-service/proto"
+)
+
+func (u *Repository) IsAdminPermissionExists(identifier interface{}) (bool, error) {
+	var user req.AdminPermission
+	if err := u.db.Where("id = ? OR name = ?", identifier, identifier).First(&user).Error; err != nil {
+		if errors.Is(err, gorm.ErrRecordNotFound) {
+			return false, nil // 记录不存在,账号不存在
+		}
+		return false, err // 发生其他错误
+	}
+	return true, nil
+}
+
+func (u *Repository) GetAdminPermissionList(query *pb.GetAdminPermissionListRequest) ([]req.AdminPermission, int64, error) {
+	permissions := make([]req.AdminPermission, 0)
+	var totalCount int64
+	tx := u.db.Model(&req.AdminPermission{}).Order("id desc").
+		Preload("Roles", "status = ?", pb.StatusEnum_ENABLED)
+	if query.Keyword != "" {
+		tx.Where("name = ?", query.Keyword)
+	}
+	if base.IsStatusEnum(query.Status) {
+		tx.Where("status = ?", query.Status)
+	}
+	tx.Count(&totalCount)
+	return permissions, totalCount, tx.Limit(int(query.PageSize)).Offset(int((query.Page - 1) * query.PageSize)).Find(&permissions).Error
+}
+
+func (u *Repository) GetAdminPermissionAll() ([]req.AdminPermission, error) {
+	var permissions []req.AdminPermission
+	return permissions, u.db.Model(&req.AdminPermission{}).Where("status = ?", pb.StatusEnum_ENABLED).Find(&permissions).Error
+}
+
+func (u *Repository) GetAdminPermission(query *pb.GetAdminPermissionRequest) (req.AdminPermission, error) {
+	var permission req.AdminPermission
+	return permission, u.db.
+		Model(req.AdminPermission{}).Where("id = ?", query.Id).
+		Preload("Roles", "status = ?", pb.StatusEnum_ENABLED).
+		First(&permission).Error
+}
+
+func (u *Repository) CreateAdminPermission(permission req.AdminPermission, roles []int64) error {
+	// 开始事务
+	tx := u.db.Begin()
+	// 错误处理
+	defer func() {
+		if r := recover(); r != nil {
+			tx.Rollback()
+		}
+	}()
+	if err := tx.Create(&permission).Error; err != nil {
+		tx.Rollback()
+		return err
+	}
+	if len(roles) > 0 {
+		if _, err := u.getAdminPermissionValidIDs(roles); err != nil {
+			tx.Rollback()
+			return err
+		}
+		permissionRoles := make([]req.AdminRole, 0)
+		for _, ID := range roles {
+			permissionRoles = append(permissionRoles, req.AdminRole{ID: ID})
+		}
+		if err := tx.Model(&permission).Association("Roles").Append(&permissionRoles); err != nil {
+			tx.Rollback()
+			return err
+		}
+	}
+	return tx.Commit().Error
+}
+
+func (u *Repository) UpdateAdminPermission(permissionId int64, reqPermission map[string]interface{}, reqRoles []int64) error {
+	fmt.Println("reqPermission", reqPermission)
+	fmt.Println("reqRoles", reqRoles)
+	// 开始事务
+	tx := u.db.Begin()
+	// 错误处理
+	defer func() {
+		if r := recover(); r != nil {
+			tx.Rollback()
+		}
+	}()
+	var permission req.AdminPermission
+	if err := tx.First(&permission, permissionId).Error; err != nil {
+		tx.Rollback()
+		return err
+	}
+	if err := tx.Model(&permission).Association("Roles").Clear(); err != nil {
+		tx.Rollback()
+		return err
+	}
+	if len(reqRoles) > 0 {
+		if _, err := u.getAdminRoleValidIDs(reqRoles); err != nil {
+			tx.Rollback()
+			return err
+		}
+		roles := make([]req.AdminRole, 0)
+		for _, ID := range reqRoles {
+			roles = append(roles, req.AdminRole{ID: ID})
+		}
+		if err := tx.Model(&permission).Association("Roles").Append(&roles); err != nil {
+			tx.Rollback()
+			return err
+		}
+	}
+	if err := tx.Model(&permission).Updates(reqPermission).Error; err != nil {
+		tx.Rollback()
+		return err
+	}
+	return tx.Commit().Error
+}
+
+func (u *Repository) DeleteAdminPermission(permissionId int64) error {
+	// 开始事务
+	tx := u.db.Begin()
+	// 错误处理
+	defer func() {
+		if r := recover(); r != nil {
+			tx.Rollback()
+		}
+	}()
+	var permission req.AdminPermission
+	// 1.查询角色
+	if err := tx.First(&permission, permissionId).Error; err != nil {
+		tx.Rollback()
+		return err
+	}
+	// 2 删除关联用户
+	if err := tx.Model(&permission).Association("Roles").Clear(); err != nil {
+		tx.Rollback()
+		return err
+	}
+
+	// 4. 彻底删除
+	if err := tx.Model(&req.AdminPermission{}).Delete(&req.AdminPermission{
+		ID: permissionId,
+	}).Error; err != nil {
+		tx.Rollback()
+		return err
+	}
+	return tx.Commit().Error
+}
+
+func (u *Repository) ToggleAdminPermission(query *pb.ToggleAdminPermissionRequest) error {
+	// 1. 开启事务
+	tx := u.db.Begin()
+	// 错误处理
+	defer func() {
+		if r := recover(); r != nil {
+			tx.Rollback()
+		}
+	}()
+	var permission req.AdminPermission
+	// 1.查询角色
+	if err := tx.First(&permission, query.PermissionId).Error; err != nil {
+		tx.Rollback()
+		return err
+	}
+	if query.Status == pb.StatusEnum_DELETED {
+		// 1.1删除关联角色
+		if err := tx.Model(&permission).Association("Roles").Clear(); err != nil {
+			tx.Rollback()
+			return err
+		}
+	}
+	// enum
+	// 2. 更新状态
+	if err := tx.Model(&req.AdminPermission{}).Where("id = ?", query.PermissionId).Updates(map[string]interface{}{
+		"status": query.Status,
+	}).Error; err != nil {
+		tx.Rollback()
+		return err
+	}
+	return tx.Commit().Error
+}

+ 9 - 0
domain/repository/repository.go

@@ -41,6 +41,15 @@ type IRepository interface {
 	IsAdminUserExists(interface{}) (bool, error)
 	IsAdminRoleExists(interface{}) (bool, error)
 	CreateAuditLog(*req.AuditLog) error
+
+	GetAdminPermissionList(request *pb.GetAdminPermissionListRequest) ([]req.AdminPermission, int64, error)
+	GetAdminPermission(*pb.GetAdminPermissionRequest) (req.AdminPermission, error)
+	GetAdminPermissionAll() ([]req.AdminPermission, error)
+	CreateAdminPermission(req.AdminPermission, []int64) error
+	UpdateAdminPermission(int64, map[string]interface{}, []int64) error
+	DeleteAdminPermission(int64) error
+	ToggleAdminPermission(*pb.ToggleAdminPermissionRequest) error
+	IsAdminPermissionExists(interface{}) (bool, error)
 }
 
 func NewRepository(db *gorm.DB) IRepository {

+ 166 - 0
domain/service/admin_permission.go

@@ -0,0 +1,166 @@
+package service
+
+import (
+	"context"
+	"fmt"
+	"github.com/pkg/errors"
+	"gorm.io/gorm"
+	"sghgogs.com/sghblog/authorization-service/domain/model/base"
+	req "sghgogs.com/sghblog/authorization-service/domain/model/request"
+	pb "sghgogs.com/sghblog/authorization-service/proto"
+	"sghgogs.com/sghblog/authorization-service/utils/authutil"
+	"sghgogs.com/sghblog/common"
+	"sghgogs.com/sghblog/common/errorcode"
+	"time"
+)
+
+func (s *Service) GetAdminPermissionList(query *pb.GetAdminPermissionListRequest) ([]*pb.AdminPermission, int64, error) {
+	permissions := make([]*pb.AdminPermission, 0)
+	list, count, err := s.Repository.GetAdminPermissionList(query)
+	if err != nil {
+		if errors.Is(err, gorm.ErrRecordNotFound) {
+			return permissions, 0, nil
+		}
+		return permissions, 0, errorcode.New("authorization service", err.Error(), 500)
+	}
+	for _, item := range list {
+		var res *pb.AdminPermission
+		common.SwapTo(item, &res)
+		res.UpdatedAt = ConvertTimeToInt64(*item.UpdatedAt)
+		res.CreatedAt = ConvertTimeToInt64(item.CreatedAt)
+		res.Status = item.Status
+		res.Roles = base.RolesProto(item.Roles)
+		res.Endpoint = item.Endpoint
+		permissions = append(permissions, res)
+	}
+	return permissions, count, nil
+}
+
+func (s *Service) GetAdminPermissionAll() ([]req.AdminPermission, error) {
+	return s.Repository.GetAdminPermissionAll()
+}
+
+func (s *Service) GetAdminPermission(query *pb.GetAdminPermissionRequest) (pb.AdminPermission, error) {
+	if exists, err := s.Repository.IsAdminPermissionExists(query.Id); err != nil {
+		return pb.AdminPermission{}, errorcode.New("authorization service", err.Error(), 500)
+	} else {
+		if !exists {
+			return pb.AdminPermission{}, errorcode.New("authorization service", common.ErrorMessage[common.InvalidRoleID], 400)
+		}
+	}
+	fmt.Println("进入了")
+	permission, err := s.Repository.GetAdminPermission(query)
+	if err != nil {
+		return pb.AdminPermission{}, errorcode.New("authorization service", err.Error(), 500)
+	}
+	return pb.AdminPermission{
+		Id:          permission.ID,
+		Name:        permission.Name,
+		Description: permission.Description,
+		Roles:       base.RolesProto(permission.Roles),
+		CreatedAt:   ConvertTimeToInt64(permission.CreatedAt),
+		CreatedBy:   permission.CreatedBy,
+		UpdatedAt:   ConvertTimeToInt64(*permission.UpdatedAt),
+		Status:      permission.Status,
+		Endpoint:    permission.Endpoint,
+		IsReserved:  permission.IsReserved,
+	}, nil
+}
+
+func (s *Service) CreateAdminPermission(ctx context.Context, permission *pb.CreateAdminPermissionRequest) error {
+	_, createdBy, _, _ := ParseMetadata(ctx)
+	adminPermission := req.AdminPermission{
+		Name:        permission.Name,
+		Description: permission.Description,
+		CreatedAt:   time.Now(),
+		CreatedBy:   createdBy,
+		UpdatedAt:   nil,
+		Endpoint:    permission.Endpoint,
+		Status:      permission.Status,
+		IsReserved:  false,
+	}
+	if err := s.Repository.CreateAdminPermission(adminPermission, permission.Roles); err != nil {
+		return errorcode.New("authorization service", err.Error(), 500)
+	}
+	return nil
+}
+
+func (s *Service) UpdateAdminPermission(ctx context.Context, permission *pb.UpdateAdminPermissionRequest) error {
+	// 获取权限ID作为锁的键
+	lockKey := fmt.Sprintf("update_admin_permission_%d", permission.PermissionId)
+	lock := authutil.JWTAuthService.Mu.NewMutex(lockKey)
+	// 获取锁,保证原子性
+	if err := lock.Lock(); err != nil {
+		return err
+	}
+	defer lock.Unlock()
+	// 1.查询角色是否存在
+	if exists, err := s.Repository.IsAdminPermissionExists(permission.PermissionId); err != nil {
+		return errorcode.New("authorization service", err.Error(), 500)
+	} else {
+		if !exists {
+			return errorcode.New("authorization service", common.ErrorMessage[common.InvalidRoleID], 400)
+		}
+	}
+	_, createdBy, _, _ := ParseMetadata(ctx)
+	m := map[string]interface{}{
+		"updated_by": createdBy,
+	}
+	if permission.Description != "" {
+		m["description"] = permission.Description
+	}
+	if permission.Endpoint != "" {
+		m["endpoint"] = permission.Endpoint
+	}
+	if err := s.Repository.UpdateAdminPermission(permission.PermissionId, m, permission.Roles); err != nil {
+		return errorcode.New("authorization service", err.Error(), 500)
+	}
+	return nil
+}
+
+func (s *Service) DeleteAdminPermission(permission *pb.DeleteAdminPermissionRequest) error {
+	// 获取权限ID作为锁的键
+	lockKey := fmt.Sprintf("delete_admin_permission_%d", permission.PermissionId)
+	lock := authutil.JWTAuthService.Mu.NewMutex(lockKey)
+	// 获取锁,保证原子性
+	if err := lock.Lock(); err != nil {
+		return err
+	}
+	defer lock.Unlock()
+	// 1.查询角色是否存在
+	if exists, err := s.Repository.IsAdminPermissionExists(permission.PermissionId); err != nil {
+		return errorcode.New("authorization service", err.Error(), 500)
+	} else {
+		if !exists {
+			return errorcode.New("authorization service", common.ErrorMessage[common.InvalidRoleID], 400)
+		}
+	}
+	// 彻底删除角色
+	if err := s.Repository.DeleteAdminPermission(permission.PermissionId); err != nil {
+		return errorcode.New("authorization service", err.Error(), 500)
+	}
+	return nil
+}
+
+func (s *Service) ToggleAdminPermission(query *pb.ToggleAdminPermissionRequest) error {
+	// 获取权限ID作为锁的键
+	lockKey := fmt.Sprintf("toggle_admin_permission_%d", query.PermissionId)
+	lock := authutil.JWTAuthService.Mu.NewMutex(lockKey)
+	// 获取锁,保证原子性
+	if err := lock.Lock(); err != nil {
+		return err
+	}
+	defer lock.Unlock()
+
+	if exists, err := s.Repository.IsAdminPermissionExists(query.PermissionId); err != nil {
+		return errorcode.New("authorization service", err.Error(), 500)
+	} else {
+		if !exists {
+			return errorcode.New("authorization service", common.ErrorMessage[common.AccountDoesNotExist], 400)
+		}
+	}
+	if err := s.Repository.ToggleAdminPermission(query); err != nil {
+		return errorcode.New("authorization service", err.Error(), 500)
+	}
+	return nil
+}

+ 7 - 0
domain/service/service.go

@@ -40,6 +40,13 @@ type IService interface {
 	ToggleAdminRole(*pb.ToggleAdminRoleRequest) error
 	DeleteAdminRole(int64) error
 
+	GetAdminPermissionList(*pb.GetAdminPermissionListRequest) ([]*pb.AdminPermission, int64, error)
+	GetAdminPermission(*pb.GetAdminPermissionRequest) (pb.AdminPermission, error)
+	GetAdminPermissionAll() ([]req.AdminPermission, error)
+	CreateAdminPermission(context.Context, *pb.CreateAdminPermissionRequest) error
+	UpdateAdminPermission(context.Context, *pb.UpdateAdminPermissionRequest) error
+	DeleteAdminPermission(*pb.DeleteAdminPermissionRequest) error
+	ToggleAdminPermission(*pb.ToggleAdminPermissionRequest) error
 	// AssociateUserWithRole(context.Context, *pb.AssociateAdminUserWithRoleRequest) error
 	// UpdateAdminUserProfileInfoRequest(*pb.UpdateAdminUserProfileInfoRequest) error
 }

+ 0 - 2
handler/admin_common.go

@@ -69,7 +69,6 @@ func (svc *AdminCommon) AdminLogin(ctx context.Context, loginUser *pb.AdminLogin
 }
 
 func (svc *AdminCommon) AdminLogout(ctx context.Context, logoutRequest *pb.AdminLogoutRequest, rsp *pb.AdminLogoutResponse) error {
-	fmt.Println("进退出")
 	md, b := metadata.FromContext(ctx)
 	if !b {
 		return errorcode.Unauthorized("authorization service", common.ErrorMessage[common.UnauthorizedErrorCode])
@@ -85,7 +84,6 @@ func (svc *AdminCommon) AdminLogout(ctx context.Context, logoutRequest *pb.Admin
 	token := strings.TrimPrefix(authHeader, auth.BearerScheme)
 
 	token = strings.TrimSpace(token)
-	fmt.Println("logout 退出")
 	if err := authutil.JWTAuthService.Blacklist(token); err != nil {
 		return errorcode.Unauthorized("authorization service", common.ErrorMessage[common.FailedRedisInternalServerErrorCode])
 	}

+ 62 - 0
handler/admin_permission.go

@@ -0,0 +1,62 @@
+package handler
+
+import (
+	"context"
+	"sghgogs.com/sghblog/authorization-service/domain/service"
+	pb "sghgogs.com/sghblog/authorization-service/proto"
+)
+
+type AdminPermission struct {
+	Service service.IService
+}
+
+func (svc *AdminPermission) GetAdminPermissionList(ctx context.Context, query *pb.GetAdminPermissionListRequest, rsp *pb.GetAdminPermissionListResponse) error {
+	list, count, err := svc.Service.GetAdminPermissionList(query)
+	if err != nil {
+		return err
+	} else {
+		rsp.Items = list
+		rsp.TotalCount = count
+	}
+	return nil
+}
+func (svc *AdminPermission) GetAdminPermission(ctx context.Context, query *pb.GetAdminPermissionRequest, rsp *pb.GetAdminPermissionResponse) error {
+	if permission, err := svc.Service.GetAdminPermission(query); err != nil {
+		return err
+	} else {
+		rsp.Data = &permission
+		return nil
+	}
+}
+
+func (svc *AdminPermission) CreateAdminPermission(ctx context.Context, query *pb.CreateAdminPermissionRequest, rsp *pb.CreateAdminPermissionResponse) error {
+	err := svc.Service.CreateAdminPermission(ctx, query)
+	if err != nil {
+		return err
+	}
+	return nil
+}
+
+func (svc *AdminPermission) UpdateAdminPermission(ctx context.Context, query *pb.UpdateAdminPermissionRequest, rsp *pb.UpdateAdminPermissionResponse) error {
+	err := svc.Service.UpdateAdminPermission(ctx, query)
+	if err != nil {
+		return err
+	}
+	return nil
+}
+
+func (svc *AdminPermission) DeleteAdminPermission(ctx context.Context, query *pb.DeleteAdminPermissionRequest, rsp *pb.DeleteAdminPermissionResponse) error {
+	err := svc.Service.DeleteAdminPermission(query)
+	if err != nil {
+		return err
+	}
+	return nil
+}
+
+func (svc *AdminPermission) ToggleAdminPermission(ctx context.Context, query *pb.ToggleAdminPermissionRequest, rsp *pb.ToggleAdminPermissionResponse) error {
+	err := svc.Service.ToggleAdminPermission(query)
+	if err != nil {
+		return err
+	}
+	return nil
+}

+ 49 - 10
main.go

@@ -7,18 +7,20 @@ import (
 	"github.com/go-micro/plugins/v4/registry/consul"
 	grpcs "github.com/go-micro/plugins/v4/server/grpc"
 	"github.com/go-micro/plugins/v4/wrapper/trace/opentelemetry"
+	"github.com/google/uuid"
 	"github.com/redis/go-redis/v9"
 	"github.com/sirupsen/logrus"
 	"go-micro.dev/v4"
+	"go-micro.dev/v4/auth"
 	"go-micro.dev/v4/registry"
 	"go-micro.dev/v4/server"
 	"go.opentelemetry.io/otel"
 	"go.opentelemetry.io/otel/propagation"
 	"gorm.io/driver/mysql"
 	"gorm.io/gorm"
-	"gorm.io/gorm/logger"
 	"gorm.io/gorm/schema"
 	"sghgogs.com/sghblog/authorization-service/config"
+	req "sghgogs.com/sghblog/authorization-service/domain/model/request"
 	"sghgogs.com/sghblog/authorization-service/domain/repository"
 	"sghgogs.com/sghblog/authorization-service/domain/service"
 	"sghgogs.com/sghblog/authorization-service/handler"
@@ -40,20 +42,13 @@ func main() {
 	if err := config.Load(); err != nil {
 		logrus.Fatal(err)
 	}
-	if cfg := config.RedisAddress(); cfg.Enable {
-		authutil.NewJWTAuth(redis.NewClient(&redis.Options{
-			Addr:     cfg.URL,      // Redis 服务器地址
-			Password: cfg.Password, // Redis 密码,如果有的话
-			DB:       0,            // 默认数据库
-		}), name, cfg.Enable)
-		// cfg.Password
-	}
+
 	// 1. 连接数据库
 	var db *gorm.DB
 	if cfg := config.DataBase(); cfg.Enable {
 		address := fmt.Sprintf("%v:%v@(%v:%v)/%v?charset=utf8mb4,utf8&parseTime=True&loc=Local", cfg.Mysql.User, cfg.Mysql.Password, cfg.Mysql.Host, cfg.Mysql.Port, cfg.Mysql.DataBase)
 		db, _ = gorm.Open(mysql.Open(address), &gorm.Config{
-			Logger: logger.Default.LogMode(logger.Info),
+			// Logger: logger.Default.LogMode(logger.Info),
 			NamingStrategy: schema.NamingStrategy{
 				SingularTable: true,
 			}})
@@ -62,6 +57,17 @@ func main() {
 		logrus.Info("There is no database configured")
 	}
 
+	if cfg := config.RedisAddress(); cfg.Enable {
+		// UpdateRulesItems
+		roles := make([]req.AdminRole, 0)
+		db.Model(&req.AdminRole{}).Where("status = ?", authorization_service.StatusEnum_ENABLED).Preload("Permissions", "status = ?", authorization_service.StatusEnum_ENABLED).Find(&roles)
+		authutil.NewJWTAuth(redis.NewClient(&redis.Options{
+			Addr:     cfg.URL,      // Redis 服务器地址
+			Password: cfg.Password, // Redis 密码,如果有的话
+			DB:       0,            // 默认数据库
+		}), name, cfg.Enable, UpdateRulesItems(roles))
+		// cfg.Password
+	}
 	// 2. Create service
 	srv := micro.NewService(
 		micro.Server(grpcs.NewServer()),
@@ -130,6 +136,10 @@ func main() {
 		Service: newService,
 	})
 	authorization_service.RegisterAdminUserServiceHandler(srv.Server(), &handler.AdminUser{Service: newService})
+
+	authorization_service.RegisterAdminPermissionServiceHandler(srv.Server(), &handler.AdminPermission{
+		Service: newService,
+	})
 	// 权限认证使用
 	authorization_service.RegisterAuthenticationServiceHandler(srv.Server(), &handler.Authentication{})
 	// Run service
@@ -138,3 +148,32 @@ func main() {
 		logrus.Fatal(err)
 	}
 }
+
+func UpdateRulesItems(roles []req.AdminRole) []*auth.Rule {
+	rules := make([]*auth.Rule, 0)
+	for _, role := range roles {
+		for _, permission := range role.Permissions {
+			rules = append(rules, &auth.Rule{
+				Resource: &auth.Resource{
+					Name:     "authorizationservice",
+					Type:     "user",
+					Endpoint: permission.Endpoint,
+				},
+				ID:       uuid.New().String(),
+				Scope:    role.Name,
+				Priority: 1,
+			})
+			fmt.Println(&auth.Rule{
+				Resource: &auth.Resource{
+					Name:     "authorizationservice",
+					Type:     "user",
+					Endpoint: permission.Endpoint,
+				},
+				ID:       uuid.New().String(),
+				Scope:    role.Name,
+				Priority: 1,
+			})
+		}
+	}
+	return rules
+}

+ 67 - 0
proto/admin_permission_service.proto

@@ -0,0 +1,67 @@
+syntax = "proto3";
+
+package admin_permission_service;
+
+option go_package = "./proto;authorization_service";
+
+import "proto/base_service.proto";
+
+service AdminPermissionService {
+  rpc GetAdminPermissionList(GetAdminPermissionListRequest) returns (GetAdminPermissionListResponse);
+  rpc GetAdminPermission(GetAdminPermissionRequest) returns(GetAdminPermissionResponse);
+  rpc CreateAdminPermission(CreateAdminPermissionRequest) returns(CreateAdminPermissionResponse);
+  rpc UpdateAdminPermission(UpdateAdminPermissionRequest) returns(UpdateAdminPermissionResponse);
+  rpc DeleteAdminPermission(DeleteAdminPermissionRequest) returns(DeleteAdminPermissionResponse);
+  rpc ToggleAdminPermission(ToggleAdminPermissionRequest) returns (ToggleAdminPermissionResponse);
+}
+
+message GetAdminPermissionListRequest {
+  int32 page = 1;
+  int32 page_size = 2;
+  string keyword = 3;
+  base_service.StatusEnum status = 4;
+}
+
+message GetAdminPermissionListResponse{
+  repeated base_service.AdminPermission items = 1;
+  int64 total_count = 2;
+}
+
+message GetAdminPermissionRequest{
+  int64 id = 1;
+}
+
+message GetAdminPermissionResponse{
+  base_service.AdminPermission data = 1;
+}
+
+message CreateAdminPermissionRequest{
+  string name = 1;
+  string description = 2;
+  string endpoint = 3;
+  base_service.StatusEnum status = 4;
+  repeated int64 roles = 5;
+}
+
+message CreateAdminPermissionResponse{}
+
+message UpdateAdminPermissionRequest{
+  int64 permission_id = 1;
+  string description = 2;
+  base_service.StatusEnum status = 3;
+  repeated int64 roles = 4;
+  string endpoint = 5;
+}
+message UpdateAdminPermissionResponse{}
+
+message DeleteAdminPermissionRequest{
+  int64 permission_id = 1;
+}
+
+message DeleteAdminPermissionResponse{}
+
+message ToggleAdminPermissionRequest{
+  int64 permission_id = 1;
+  base_service.StatusEnum status = 2;
+}
+message ToggleAdminPermissionResponse{}

+ 174 - 19
proto/base_service.pb.go

@@ -373,6 +373,125 @@ func (x *AdminRole) GetIsReserved() bool {
 	return false
 }
 
+type AdminPermission struct {
+	state         protoimpl.MessageState
+	sizeCache     protoimpl.SizeCache
+	unknownFields protoimpl.UnknownFields
+
+	Id          int64        `protobuf:"varint,1,opt,name=id,proto3" json:"id,omitempty"`
+	Name        string       `protobuf:"bytes,2,opt,name=name,proto3" json:"name,omitempty"`
+	Description string       `protobuf:"bytes,3,opt,name=description,proto3" json:"description,omitempty"`
+	Roles       []*AdminBase `protobuf:"bytes,4,rep,name=roles,proto3" json:"roles,omitempty"`
+	CreatedAt   int64        `protobuf:"varint,5,opt,name=created_at,json=createdAt,proto3" json:"created_at,omitempty"`
+	CreatedBy   string       `protobuf:"bytes,6,opt,name=created_by,json=createdBy,proto3" json:"created_by,omitempty"`
+	UpdatedAt   int64        `protobuf:"varint,7,opt,name=updated_at,json=updatedAt,proto3" json:"updated_at,omitempty"`
+	Status      StatusEnum   `protobuf:"varint,8,opt,name=status,proto3,enum=base_service.StatusEnum" json:"status,omitempty"`
+	IsReserved  bool         `protobuf:"varint,9,opt,name=is_reserved,json=isReserved,proto3" json:"is_reserved,omitempty"`
+	Endpoint    string       `protobuf:"bytes,10,opt,name=endpoint,proto3" json:"endpoint,omitempty"`
+}
+
+func (x *AdminPermission) Reset() {
+	*x = AdminPermission{}
+	if protoimpl.UnsafeEnabled {
+		mi := &file_proto_base_service_proto_msgTypes[3]
+		ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x))
+		ms.StoreMessageInfo(mi)
+	}
+}
+
+func (x *AdminPermission) String() string {
+	return protoimpl.X.MessageStringOf(x)
+}
+
+func (*AdminPermission) ProtoMessage() {}
+
+func (x *AdminPermission) ProtoReflect() protoreflect.Message {
+	mi := &file_proto_base_service_proto_msgTypes[3]
+	if protoimpl.UnsafeEnabled && x != nil {
+		ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x))
+		if ms.LoadMessageInfo() == nil {
+			ms.StoreMessageInfo(mi)
+		}
+		return ms
+	}
+	return mi.MessageOf(x)
+}
+
+// Deprecated: Use AdminPermission.ProtoReflect.Descriptor instead.
+func (*AdminPermission) Descriptor() ([]byte, []int) {
+	return file_proto_base_service_proto_rawDescGZIP(), []int{3}
+}
+
+func (x *AdminPermission) GetId() int64 {
+	if x != nil {
+		return x.Id
+	}
+	return 0
+}
+
+func (x *AdminPermission) GetName() string {
+	if x != nil {
+		return x.Name
+	}
+	return ""
+}
+
+func (x *AdminPermission) GetDescription() string {
+	if x != nil {
+		return x.Description
+	}
+	return ""
+}
+
+func (x *AdminPermission) GetRoles() []*AdminBase {
+	if x != nil {
+		return x.Roles
+	}
+	return nil
+}
+
+func (x *AdminPermission) GetCreatedAt() int64 {
+	if x != nil {
+		return x.CreatedAt
+	}
+	return 0
+}
+
+func (x *AdminPermission) GetCreatedBy() string {
+	if x != nil {
+		return x.CreatedBy
+	}
+	return ""
+}
+
+func (x *AdminPermission) GetUpdatedAt() int64 {
+	if x != nil {
+		return x.UpdatedAt
+	}
+	return 0
+}
+
+func (x *AdminPermission) GetStatus() StatusEnum {
+	if x != nil {
+		return x.Status
+	}
+	return StatusEnum_UNKNOWN
+}
+
+func (x *AdminPermission) GetIsReserved() bool {
+	if x != nil {
+		return x.IsReserved
+	}
+	return false
+}
+
+func (x *AdminPermission) GetEndpoint() string {
+	if x != nil {
+		return x.Endpoint
+	}
+	return ""
+}
+
 var File_proto_base_service_proto protoreflect.FileDescriptor
 
 var file_proto_base_service_proto_rawDesc = []byte{
@@ -428,14 +547,35 @@ var file_proto_base_service_proto_rawDesc = []byte{
 	0x65, 0x2e, 0x53, 0x74, 0x61, 0x74, 0x75, 0x73, 0x45, 0x6e, 0x75, 0x6d, 0x52, 0x06, 0x73, 0x74,
 	0x61, 0x74, 0x75, 0x73, 0x12, 0x1f, 0x0a, 0x0b, 0x69, 0x73, 0x5f, 0x72, 0x65, 0x73, 0x65, 0x72,
 	0x76, 0x65, 0x64, 0x18, 0x0a, 0x20, 0x01, 0x28, 0x08, 0x52, 0x0a, 0x69, 0x73, 0x52, 0x65, 0x73,
-	0x65, 0x72, 0x76, 0x65, 0x64, 0x2a, 0x41, 0x0a, 0x0a, 0x53, 0x74, 0x61, 0x74, 0x75, 0x73, 0x45,
-	0x6e, 0x75, 0x6d, 0x12, 0x0b, 0x0a, 0x07, 0x55, 0x4e, 0x4b, 0x4e, 0x4f, 0x57, 0x4e, 0x10, 0x00,
-	0x12, 0x0b, 0x0a, 0x07, 0x45, 0x4e, 0x41, 0x42, 0x4c, 0x45, 0x44, 0x10, 0x01, 0x12, 0x0c, 0x0a,
-	0x08, 0x44, 0x49, 0x53, 0x41, 0x42, 0x4c, 0x45, 0x44, 0x10, 0x02, 0x12, 0x0b, 0x0a, 0x07, 0x44,
-	0x45, 0x4c, 0x45, 0x54, 0x45, 0x44, 0x10, 0x03, 0x42, 0x1f, 0x5a, 0x1d, 0x2e, 0x2f, 0x70, 0x72,
-	0x6f, 0x74, 0x6f, 0x3b, 0x61, 0x75, 0x74, 0x68, 0x6f, 0x72, 0x69, 0x7a, 0x61, 0x74, 0x69, 0x6f,
-	0x6e, 0x5f, 0x73, 0x65, 0x72, 0x76, 0x69, 0x63, 0x65, 0x62, 0x06, 0x70, 0x72, 0x6f, 0x74, 0x6f,
-	0x33,
+	0x65, 0x72, 0x76, 0x65, 0x64, 0x22, 0xd2, 0x02, 0x0a, 0x0f, 0x41, 0x64, 0x6d, 0x69, 0x6e, 0x50,
+	0x65, 0x72, 0x6d, 0x69, 0x73, 0x73, 0x69, 0x6f, 0x6e, 0x12, 0x0e, 0x0a, 0x02, 0x69, 0x64, 0x18,
+	0x01, 0x20, 0x01, 0x28, 0x03, 0x52, 0x02, 0x69, 0x64, 0x12, 0x12, 0x0a, 0x04, 0x6e, 0x61, 0x6d,
+	0x65, 0x18, 0x02, 0x20, 0x01, 0x28, 0x09, 0x52, 0x04, 0x6e, 0x61, 0x6d, 0x65, 0x12, 0x20, 0x0a,
+	0x0b, 0x64, 0x65, 0x73, 0x63, 0x72, 0x69, 0x70, 0x74, 0x69, 0x6f, 0x6e, 0x18, 0x03, 0x20, 0x01,
+	0x28, 0x09, 0x52, 0x0b, 0x64, 0x65, 0x73, 0x63, 0x72, 0x69, 0x70, 0x74, 0x69, 0x6f, 0x6e, 0x12,
+	0x2d, 0x0a, 0x05, 0x72, 0x6f, 0x6c, 0x65, 0x73, 0x18, 0x04, 0x20, 0x03, 0x28, 0x0b, 0x32, 0x17,
+	0x2e, 0x62, 0x61, 0x73, 0x65, 0x5f, 0x73, 0x65, 0x72, 0x76, 0x69, 0x63, 0x65, 0x2e, 0x41, 0x64,
+	0x6d, 0x69, 0x6e, 0x42, 0x61, 0x73, 0x65, 0x52, 0x05, 0x72, 0x6f, 0x6c, 0x65, 0x73, 0x12, 0x1d,
+	0x0a, 0x0a, 0x63, 0x72, 0x65, 0x61, 0x74, 0x65, 0x64, 0x5f, 0x61, 0x74, 0x18, 0x05, 0x20, 0x01,
+	0x28, 0x03, 0x52, 0x09, 0x63, 0x72, 0x65, 0x61, 0x74, 0x65, 0x64, 0x41, 0x74, 0x12, 0x1d, 0x0a,
+	0x0a, 0x63, 0x72, 0x65, 0x61, 0x74, 0x65, 0x64, 0x5f, 0x62, 0x79, 0x18, 0x06, 0x20, 0x01, 0x28,
+	0x09, 0x52, 0x09, 0x63, 0x72, 0x65, 0x61, 0x74, 0x65, 0x64, 0x42, 0x79, 0x12, 0x1d, 0x0a, 0x0a,
+	0x75, 0x70, 0x64, 0x61, 0x74, 0x65, 0x64, 0x5f, 0x61, 0x74, 0x18, 0x07, 0x20, 0x01, 0x28, 0x03,
+	0x52, 0x09, 0x75, 0x70, 0x64, 0x61, 0x74, 0x65, 0x64, 0x41, 0x74, 0x12, 0x30, 0x0a, 0x06, 0x73,
+	0x74, 0x61, 0x74, 0x75, 0x73, 0x18, 0x08, 0x20, 0x01, 0x28, 0x0e, 0x32, 0x18, 0x2e, 0x62, 0x61,
+	0x73, 0x65, 0x5f, 0x73, 0x65, 0x72, 0x76, 0x69, 0x63, 0x65, 0x2e, 0x53, 0x74, 0x61, 0x74, 0x75,
+	0x73, 0x45, 0x6e, 0x75, 0x6d, 0x52, 0x06, 0x73, 0x74, 0x61, 0x74, 0x75, 0x73, 0x12, 0x1f, 0x0a,
+	0x0b, 0x69, 0x73, 0x5f, 0x72, 0x65, 0x73, 0x65, 0x72, 0x76, 0x65, 0x64, 0x18, 0x09, 0x20, 0x01,
+	0x28, 0x08, 0x52, 0x0a, 0x69, 0x73, 0x52, 0x65, 0x73, 0x65, 0x72, 0x76, 0x65, 0x64, 0x12, 0x1a,
+	0x0a, 0x08, 0x65, 0x6e, 0x64, 0x70, 0x6f, 0x69, 0x6e, 0x74, 0x18, 0x0a, 0x20, 0x01, 0x28, 0x09,
+	0x52, 0x08, 0x65, 0x6e, 0x64, 0x70, 0x6f, 0x69, 0x6e, 0x74, 0x2a, 0x41, 0x0a, 0x0a, 0x53, 0x74,
+	0x61, 0x74, 0x75, 0x73, 0x45, 0x6e, 0x75, 0x6d, 0x12, 0x0b, 0x0a, 0x07, 0x55, 0x4e, 0x4b, 0x4e,
+	0x4f, 0x57, 0x4e, 0x10, 0x00, 0x12, 0x0b, 0x0a, 0x07, 0x45, 0x4e, 0x41, 0x42, 0x4c, 0x45, 0x44,
+	0x10, 0x01, 0x12, 0x0c, 0x0a, 0x08, 0x44, 0x49, 0x53, 0x41, 0x42, 0x4c, 0x45, 0x44, 0x10, 0x02,
+	0x12, 0x0b, 0x0a, 0x07, 0x44, 0x45, 0x4c, 0x45, 0x54, 0x45, 0x44, 0x10, 0x03, 0x42, 0x1f, 0x5a,
+	0x1d, 0x2e, 0x2f, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x3b, 0x61, 0x75, 0x74, 0x68, 0x6f, 0x72, 0x69,
+	0x7a, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x5f, 0x73, 0x65, 0x72, 0x76, 0x69, 0x63, 0x65, 0x62, 0x06,
+	0x70, 0x72, 0x6f, 0x74, 0x6f, 0x33,
 }
 
 var (
@@ -451,12 +591,13 @@ func file_proto_base_service_proto_rawDescGZIP() []byte {
 }
 
 var file_proto_base_service_proto_enumTypes = make([]protoimpl.EnumInfo, 1)
-var file_proto_base_service_proto_msgTypes = make([]protoimpl.MessageInfo, 3)
+var file_proto_base_service_proto_msgTypes = make([]protoimpl.MessageInfo, 4)
 var file_proto_base_service_proto_goTypes = []interface{}{
-	(StatusEnum)(0),   // 0: base_service.StatusEnum
-	(*AdminBase)(nil), // 1: base_service.AdminBase
-	(*AdminUser)(nil), // 2: base_service.AdminUser
-	(*AdminRole)(nil), // 3: base_service.AdminRole
+	(StatusEnum)(0),         // 0: base_service.StatusEnum
+	(*AdminBase)(nil),       // 1: base_service.AdminBase
+	(*AdminUser)(nil),       // 2: base_service.AdminUser
+	(*AdminRole)(nil),       // 3: base_service.AdminRole
+	(*AdminPermission)(nil), // 4: base_service.AdminPermission
 }
 var file_proto_base_service_proto_depIdxs = []int32{
 	0, // 0: base_service.AdminUser.status:type_name -> base_service.StatusEnum
@@ -465,11 +606,13 @@ var file_proto_base_service_proto_depIdxs = []int32{
 	1, // 3: base_service.AdminRole.users:type_name -> base_service.AdminBase
 	1, // 4: base_service.AdminRole.permissions:type_name -> base_service.AdminBase
 	0, // 5: base_service.AdminRole.status:type_name -> base_service.StatusEnum
-	6, // [6:6] is the sub-list for method output_type
-	6, // [6:6] is the sub-list for method input_type
-	6, // [6:6] is the sub-list for extension type_name
-	6, // [6:6] is the sub-list for extension extendee
-	0, // [0:6] is the sub-list for field type_name
+	1, // 6: base_service.AdminPermission.roles:type_name -> base_service.AdminBase
+	0, // 7: base_service.AdminPermission.status:type_name -> base_service.StatusEnum
+	8, // [8:8] is the sub-list for method output_type
+	8, // [8:8] is the sub-list for method input_type
+	8, // [8:8] is the sub-list for extension type_name
+	8, // [8:8] is the sub-list for extension extendee
+	0, // [0:8] is the sub-list for field type_name
 }
 
 func init() { file_proto_base_service_proto_init() }
@@ -514,6 +657,18 @@ func file_proto_base_service_proto_init() {
 				return nil
 			}
 		}
+		file_proto_base_service_proto_msgTypes[3].Exporter = func(v interface{}, i int) interface{} {
+			switch v := v.(*AdminPermission); i {
+			case 0:
+				return &v.state
+			case 1:
+				return &v.sizeCache
+			case 2:
+				return &v.unknownFields
+			default:
+				return nil
+			}
+		}
 	}
 	type x struct{}
 	out := protoimpl.TypeBuilder{
@@ -521,7 +676,7 @@ func file_proto_base_service_proto_init() {
 			GoPackagePath: reflect.TypeOf(x{}).PkgPath(),
 			RawDescriptor: file_proto_base_service_proto_rawDesc,
 			NumEnums:      1,
-			NumMessages:   3,
+			NumMessages:   4,
 			NumExtensions: 0,
 			NumServices:   0,
 		},

+ 24 - 0
proto/base_service.proto

@@ -35,6 +35,30 @@ message AdminRole {
   base_service.StatusEnum status = 9;
   bool is_reserved =10;
 }
+//    type AdminPermission struct {
+//ID          int64       `gorm:"primary_key;not_null;auto_increment;" json:"id"`
+//Name        string      `json:"name"`
+//    Description string      `json:"description"`
+//    Roles       []AdminRole `gorm:"many2many:admin_role_permission;" json:"roles"`
+//    CreatedAt   time.Time   `json:"created_at"`
+//    CreatedBy   string      `json:"created_by"`
+//    UpdatedAt   *time.Time  `json:"updated_at"`
+//    Status      string      `json:"status"` // 可以是 "enabled", "disabled", "deleted" 等
+//    IsReserved  bool        `json:"is_reserved"`
+//    }
+
+message AdminPermission {
+  int64 id = 1;
+  string name = 2;
+  string description = 3;
+  repeated base_service.AdminBase roles = 4;
+  int64 created_at = 5;
+  string created_by = 6;
+  int64 updated_at = 7;
+  base_service.StatusEnum status = 8;
+  bool is_reserved = 9;
+  string endpoint = 10;
+}
 
 enum StatusEnum {
   UNKNOWN = 0;

+ 83 - 0
test/admin_permission/admin_permission_test.go

@@ -0,0 +1,83 @@
+package admin_permission
+
+import (
+	"context"
+	"fmt"
+	"gorm.io/driver/mysql"
+	"gorm.io/gorm"
+	"gorm.io/gorm/logger"
+	"gorm.io/gorm/schema"
+	"sghgogs.com/sghblog/authorization-service/domain/repository"
+	"sghgogs.com/sghblog/authorization-service/domain/service"
+	pb "sghgogs.com/sghblog/authorization-service/proto"
+	"testing"
+)
+
+func TestPermission(t *testing.T) {
+	address := fmt.Sprintf("%v:%v@(%v:%v)/%v?charset=utf8mb4,utf8&parseTime=True&loc=Local", "root", "xugang131500", "47.56.16.206", 3306, "sghblog")
+	db, err := gorm.Open(mysql.Open(address), &gorm.Config{
+		Logger: logger.Default.LogMode(logger.Info),
+		NamingStrategy: schema.NamingStrategy{
+			SingularTable: true,
+		}})
+	if err != nil {
+		t.Fatal(err)
+	}
+	// type AdminPermission struct {
+	// 	ID          int64         `gorm:"primary_key;not_null;auto_increment;" json:"id"`
+	// 	Name        string        `json:"name"`
+	// 	Description string        `json:"description"`
+	// 	Roles       []AdminRole   `gorm:"many2many:admin_role_permission;" json:"roles"`
+	// 	CreatedAt   time.Time     `json:"created_at"`
+	// 	CreatedBy   string        `json:"created_by"`
+	// 	UpdatedAt   *time.Time    `json:"updated_at"`
+	// 	UpdatedBy   string        `json:"updated_by"`
+	// 	Status      pb.StatusEnum `json:"status"` // 可以是 "enabled", "disabled", "deleted" 等
+	// 	IsReserved  bool          `json:"is_reserved"`
+	// }
+
+	repo := repository.NewRepository(db)
+	newService := service.NewService(repo)
+	// getAuthentication = &auth.Resource{
+	// 	Type:     "user",
+	// 	Name:     name,
+	// 	Endpoint: "AuthenticationService.GetAuthentication",
+	// }
+	// // catchallResource
+	// rulesItems = []*auth.Rule{
+	// 	// {Scope: "*", Resource: catchallResource}, toggleAdminRole
+	// 	{Scope: "admin", Resource: adminLogout, ID: uuid.New().String(), Priority: 1},
+	// authorizationservice
+	t.Run("创建权限", func(t *testing.T) {
+		err = newService.CreateAdminPermission(context.Background(), &pb.CreateAdminPermissionRequest{
+			Name:        "authorizationservice",
+			Description: "设置权限状态",
+			Endpoint:    "AdminPermissionService.ToggleAdminPermission",
+			Status:      pb.StatusEnum_ENABLED,
+		})
+		fmt.Println(err)
+	})
+	t.Run("角色分配权限", func(t *testing.T) {
+		roles := []int64{2}
+		err = newService.UpdateAdminPermission(context.Background(), &pb.UpdateAdminPermissionRequest{
+			PermissionId: 21,
+			Status:       pb.StatusEnum_ENABLED,
+			Roles:        roles,
+		})
+		fmt.Println(err)
+	})
+	t.Run("获取权限详情", func(t *testing.T) {
+		permission, err2 := newService.GetAdminPermission(&pb.GetAdminPermissionRequest{
+			Id: 1,
+		})
+		fmt.Println(fmt.Sprintf("%+v", permission))
+		fmt.Println(err2)
+	})
+	t.Run("获取权限列表", func(t *testing.T) {
+		all, err2 := newService.GetAdminPermissionAll()
+		fmt.Println(err2)
+		for _, item := range all {
+			fmt.Println(fmt.Sprintf("%+v \n", item))
+		}
+	})
+}

+ 35 - 0
test/admin_role/admin_role_test.go

@@ -3,6 +3,8 @@ package admin_role
 import (
 	"context"
 	"fmt"
+	"github.com/google/uuid"
+	"go-micro.dev/v4/auth"
 	"golang.org/x/crypto/bcrypt"
 	"gorm.io/driver/mysql"
 	"gorm.io/gorm"
@@ -100,9 +102,42 @@ func TestAdminLogin(t *testing.T) {
 		})
 		fmt.Println(err2)
 	})
+	t.Run("初始化配置", func(t *testing.T) {
+		// []*auth.Rule
+		roles := make([]req.AdminRole, 0)
+		db.Model(&req.AdminRole{}).Where("status = ?", pb.StatusEnum_ENABLED).Preload("Permissions", "status = ?", pb.StatusEnum_ENABLED).Find(&roles)
+	})
 	// user, err := repo.AdminLogin(loginRequest)
 	// 断言期望的结果
 	// assert.NoError(t, err)
 	// assert.NotNil(t, user)
 	// assert.Equal(t, loginRequest.Username, user.Username)
 }
+func UpdateRulesItems(roles []req.AdminRole) []*auth.Rule {
+	rules := make([]*auth.Rule, 0)
+	for _, role := range roles {
+		for _, permission := range role.Permissions {
+			fmt.Println(fmt.Sprintf("%+v", auth.Rule{
+				ID:       uuid.New().String(),
+				Scope:    role.Name,
+				Priority: 1,
+			}))
+			fmt.Println(fmt.Sprintf("%+v", auth.Resource{
+				Name:     "authorizationservice",
+				Type:     "user",
+				Endpoint: permission.Endpoint,
+			}))
+			rules = append(rules, &auth.Rule{
+				Resource: &auth.Resource{
+					Name:     "authorizationservice",
+					Type:     "user",
+					Endpoint: permission.Endpoint,
+				},
+				ID:       uuid.New().String(),
+				Scope:    role.Name,
+				Priority: 1,
+			})
+		}
+	}
+	return rules
+}

+ 18 - 11
utils/authutil/authutil.go

@@ -31,14 +31,15 @@ const (
 )
 
 type JWTAuth struct {
-	Mu        *redsync.Redsync
-	Client    *goredislib.Client
-	Auth      auth.Auth
-	namespace string
-	Enable    bool
+	Mu         *redsync.Redsync
+	Client     *goredislib.Client
+	Auth       auth.Auth
+	namespace  string
+	Enable     bool
+	RulesItems []*auth.Rule
 }
 
-func NewJWTAuth(client *goredislib.Client, namespace string, enable bool) *JWTAuth {
+func NewJWTAuth(client *goredislib.Client, namespace string, enable bool, items []*auth.Rule) *JWTAuth {
 
 	jwtAuthServiceOnce.Do(func() {
 		newAuth := jwt.NewAuth(
@@ -53,18 +54,24 @@ func NewJWTAuth(client *goredislib.Client, namespace string, enable bool) *JWTAu
 		// lock.
 		rs := redsync.New(pool)
 		JWTAuthService = &JWTAuth{
-			Mu:        rs,
-			Client:    client,
-			Auth:      newAuth,
-			namespace: namespace,
-			Enable:    enable,
+			Mu:         rs,
+			Client:     client,
+			Auth:       newAuth,
+			namespace:  namespace,
+			Enable:     enable,
+			RulesItems: items,
 		}
+
 		handleSignals(client)
 	})
 
 	return JWTAuthService
 }
 
+func (svc *JWTAuth) UpdateRulesItems(rules []*auth.Rule) {
+	svc.RulesItems = rules
+}
+
 // GenerateToken 示例:生成令牌
 func (svc *JWTAuth) GenerateToken(userID int64, provider, withType, secret string, scopes []string, md map[string]string) (*auth.Account, error) {
 	var account *auth.Account

+ 142 - 143
utils/middleware/middleware.go

@@ -3,7 +3,6 @@ package middleware
 import (
 	"context"
 	"fmt"
-	"github.com/google/uuid"
 	"github.com/pkg/errors"
 	"github.com/sirupsen/logrus"
 	"go-micro.dev/v4"
@@ -44,6 +43,7 @@ const (
 )
 
 func Verify(rules []*auth.Rule, acc *auth.Account, res *auth.Resource) error {
+
 	// the rule is only to be applied if the type matches the resource or is catch-all (*)
 	validTypes := []string{"*", res.Type}
 
@@ -58,7 +58,6 @@ func Verify(rules []*auth.Rule, acc *auth.Account, res *auth.Resource) error {
 			validEndpoints = append(validEndpoints, wildcard)
 		}
 	}
-
 	// filter the rules to the ones which match the criteria above
 	filteredRules := make([]*auth.Rule, 0)
 	for _, rule := range rules {
@@ -73,11 +72,12 @@ func Verify(rules []*auth.Rule, acc *auth.Account, res *auth.Resource) error {
 		}
 		filteredRules = append(filteredRules, rule)
 	}
-
+	fmt.Println("2-")
 	// sort the filtered rules by priority, highest to lowest
 	sort.SliceStable(filteredRules, func(i, j int) bool {
 		return filteredRules[i].Priority > filteredRules[j].Priority
 	})
+	fmt.Println("3-")
 	// loop through the rules and check for a rule which applies to this account
 	for _, rule := range filteredRules {
 		// a blank scope indicates the rule applies to everyone, even nil accounts
@@ -99,7 +99,6 @@ func Verify(rules []*auth.Rule, acc *auth.Account, res *auth.Resource) error {
 		}
 		// 去掉首尾的方括号
 		// if the account has the necessary scope
-		fmt.Println(acc.Scopes, rule.Scope)
 		if include(acc.Scopes, rule.Scope) && rule.Access == AccessDenied {
 			return ErrForbidden
 		} else if include(acc.Scopes, rule.Scope) && rule.Access == AccessGranted {
@@ -144,141 +143,142 @@ func include(slice []string, val string) bool {
 	return false
 }
 
-var (
-	catchallResource = &auth.Resource{
-		Type:     "*",
-		Name:     "*",
-		Endpoint: "*",
-	}
-
-	adminLogout = &auth.Resource{
-		Type:     "user",
-		Name:     name,
-		Endpoint: "CommonService.AdminLogout",
-	}
-	adminProfile = &auth.Resource{
-		Type:     "user",
-		Name:     name,
-		Endpoint: "CommonService.AdminProfile",
-	}
-	listAdminRoles = &auth.Resource{
-		Type:     "user",
-		Name:     name,
-		Endpoint: "AdminRoleService.ListAdminRoles",
-	}
-	updateAdminRole = &auth.Resource{
-		Type:     "user",
-		Name:     name,
-		Endpoint: "AdminRoleService.UpdateAdminRole",
-	}
-	createAdminRole = &auth.Resource{
-		Type:     "user",
-		Name:     name,
-		Endpoint: "AdminRoleService.CreateAdminRole",
-	}
-	deleteAdminRole = &auth.Resource{
-		Type:     "user",
-		Name:     name,
-		Endpoint: "AdminRoleService.DeleteAdminRole",
-	}
-	getAdminRole = &auth.Resource{
-		Type:     "user",
-		Name:     name,
-		Endpoint: "AdminRoleService.GetAdminRole",
-	}
-	toggleAdminRole = &auth.Resource{
-		Type:     "user",
-		Name:     name,
-		Endpoint: "AdminRoleService.ToggleAdminRole",
-	}
-	retrieveEnabledRoles = &auth.Resource{
-		Type:     "user",
-		Name:     name,
-		Endpoint: "AdminRoleService.RetrieveEnabledRoles",
-	}
-
-	getUnassignedAdminRoles = &auth.Resource{
-		Type:     "user",
-		Name:     name,
-		Endpoint: "AdminUserService.GetUnassignedAdminRoles",
-	}
-	getAdminUser = &auth.Resource{
-		Type:     "user",
-		Name:     name,
-		Endpoint: "AdminUserService.GetAdminUser",
-	}
-	createAdminUser = &auth.Resource{
-		Type:     "user",
-		Name:     name,
-		Endpoint: "AdminUserService.CreateAdminUser",
-	}
-	associateAdminUserWithRole = &auth.Resource{
-		Type:     "user",
-		Name:     name,
-		Endpoint: "AdminUserService.AssociateAdminUserWithRole",
-	}
-	updateAdminUser = &auth.Resource{
-		Type:     "user",
-		Name:     name,
-		Endpoint: "AdminUserService.UpdateAdminUser",
-	}
-	revokeAdminUserWithRole = &auth.Resource{
-		Type:     "user",
-		Name:     name,
-		Endpoint: "AdminUserService.RevokeAdminUserWithRole",
-	}
-	listAdminUsers = &auth.Resource{
-		Type:     "user",
-		Name:     name,
-		Endpoint: "AdminUserService.ListAdminUsers",
-	}
-	retrieveEnabledUsers = &auth.Resource{
-		Type:     "user",
-		Name:     name,
-		Endpoint: "AdminUserService.RetrieveEnabledUsers",
-	}
-
-	deleteAdminUser = &auth.Resource{
-		Type:     "user",
-		Name:     name,
-		Endpoint: "AdminUserService.DeleteAdminUser",
-	}
-	toggleAdminUser = &auth.Resource{
-		Type:     "user",
-		Name:     name,
-		Endpoint: "AdminUserService.ToggleAdminUser",
-	}
-
-	getAuthentication = &auth.Resource{
-		Type:     "user",
-		Name:     name,
-		Endpoint: "AuthenticationService.GetAuthentication",
-	}
-	// catchallResource
-	rulesItems = []*auth.Rule{
-		// {Scope: "*", Resource: catchallResource}, toggleAdminRole
-		{Scope: "admin", Resource: adminLogout, ID: uuid.New().String(), Priority: 1},
-		{Scope: "admin", Resource: adminProfile, ID: uuid.New().String(), Priority: 1},
-		{Scope: "admin", Resource: listAdminRoles, ID: uuid.New().String(), Priority: 1},
-		{Scope: "admin", Resource: updateAdminRole, ID: uuid.New().String(), Priority: 1},
-		{Scope: "admin", Resource: createAdminRole, ID: uuid.New().String(), Priority: 1},
-		{Scope: "admin", Resource: toggleAdminRole, ID: uuid.New().String(), Priority: 1},
-		{Scope: "admin", Resource: getUnassignedAdminRoles, ID: uuid.New().String(), Priority: 1},
-		{Scope: "admin", Resource: deleteAdminRole, ID: uuid.New().String(), Priority: 1},
-		{Scope: "admin", Resource: getAdminRole, ID: uuid.New().String(), Priority: 1},
-		{Scope: "admin", Resource: retrieveEnabledRoles, ID: uuid.New().String(), Priority: 1},
-		{Scope: "admin", Resource: getAdminUser, ID: uuid.New().String(), Priority: 1},
-		{Scope: "admin", Resource: createAdminUser, ID: uuid.New().String(), Priority: 1},
-		{Scope: "admin", Resource: associateAdminUserWithRole, ID: uuid.New().String(), Priority: 1},
-		{Scope: "admin", Resource: updateAdminUser, ID: uuid.New().String(), Priority: 1},
-		{Scope: "admin", Resource: revokeAdminUserWithRole, ID: uuid.New().String(), Priority: 1},
-		{Scope: "admin", Resource: listAdminUsers, ID: uuid.New().String(), Priority: 1},
-		{Scope: "admin", Resource: retrieveEnabledUsers, ID: uuid.New().String(), Priority: 1},
-		{Scope: "admin", Resource: deleteAdminUser, ID: uuid.New().String(), Priority: 1},
-		{Scope: "admin", Resource: toggleAdminUser, ID: uuid.New().String(), Priority: 1},
-		{Scope: "kube_admin", Resource: getAuthentication, ID: uuid.New().String(), Priority: 1},
-	}
-)
+// var (
+// 	catchallResource = &auth.Resource{
+// 		Type:     "*",
+// 		Name:     "*",
+// 		Endpoint: "*",
+// 	}
+//
+// 	adminLogout = &auth.Resource{
+// 		Type:     "user",
+// 		Name:     name,
+// 		Endpoint: "CommonService.AdminLogout",
+// 	}
+// 	adminProfile = &auth.Resource{
+// 		Type:     "user",
+// 		Name:     name,
+// 		Endpoint: "CommonService.AdminProfile",
+// 	}
+// 	listAdminRoles = &auth.Resource{
+// 		Type:     "user",
+// 		Name:     name,
+// 		Endpoint: "AdminRoleService.ListAdminRoles",
+// 	}
+// 	updateAdminRole = &auth.Resource{
+// 		Type:     "user",
+// 		Name:     name,
+// 		Endpoint: "AdminRoleService.UpdateAdminRole",
+// 	}
+// 	createAdminRole = &auth.Resource{
+// 		Type:     "user",
+// 		Name:     name,
+// 		Endpoint: "AdminRoleService.CreateAdminRole",
+// 	}
+// 	deleteAdminRole = &auth.Resource{
+// 		Type:     "user",
+// 		Name:     name,
+// 		Endpoint: "AdminRoleService.DeleteAdminRole",
+// 	}
+// 	getAdminRole = &auth.Resource{
+// 		Type:     "user",
+// 		Name:     name,
+// 		Endpoint: "AdminRoleService.GetAdminRole",
+// 	}
+// 	toggleAdminRole = &auth.Resource{
+// 		Type:     "user",
+// 		Name:     name,
+// 		Endpoint: "AdminRoleService.ToggleAdminRole",
+// 	}
+// 	retrieveEnabledRoles = &auth.Resource{
+// 		Type:     "user",
+// 		Name:     name,
+// 		Endpoint: "AdminRoleService.RetrieveEnabledRoles",
+// 	}
+//
+// 	getUnassignedAdminRoles = &auth.Resource{
+// 		Type:     "user",
+// 		Name:     name,
+// 		Endpoint: "AdminUserService.GetUnassignedAdminRoles",
+// 	}
+// 	getAdminUser = &auth.Resource{
+// 		Type:     "user",
+// 		Name:     name,
+// 		Endpoint: "AdminUserService.GetAdminUser",
+// 	}
+// 	createAdminUser = &auth.Resource{
+// 		Type:     "user",
+// 		Name:     name,
+// 		Endpoint: "AdminUserService.CreateAdminUser",
+// 	}
+// 	associateAdminUserWithRole = &auth.Resource{
+// 		Type:     "user",
+// 		Name:     name,
+// 		Endpoint: "AdminUserService.AssociateAdminUserWithRole",
+// 	}
+// 	updateAdminUser = &auth.Resource{
+// 		Type:     "user",
+// 		Name:     name,
+// 		Endpoint: "AdminUserService.UpdateAdminUser",
+// 	}
+// 	revokeAdminUserWithRole = &auth.Resource{
+// 		Type:     "user",
+// 		Name:     name,
+// 		Endpoint: "AdminUserService.RevokeAdminUserWithRole",
+// 	}
+// 	listAdminUsers = &auth.Resource{
+// 		Type:     "user",
+// 		Name:     name,
+// 		Endpoint: "AdminUserService.ListAdminUsers",
+// 	}
+// 	retrieveEnabledUsers = &auth.Resource{
+// 		Type:     "user",
+// 		Name:     name,
+// 		Endpoint: "AdminUserService.RetrieveEnabledUsers",
+// 	}
+//
+// 	deleteAdminUser = &auth.Resource{
+// 		Type:     "user",
+// 		Name:     name,
+// 		Endpoint: "AdminUserService.DeleteAdminUser",
+// 	}
+// 	toggleAdminUser = &auth.Resource{
+// 		Type:     "user",
+// 		Name:     name,
+// 		Endpoint: "AdminUserService.ToggleAdminUser",
+// 	}
+//
+// 	getAuthentication = &auth.Resource{
+// 		Type:     "user",
+// 		Name:     name,
+// 		Endpoint: "AuthenticationService.GetAuthentication",
+// 	}
+// 	// catchallResource
+// 	rulesItems = []*auth.Rule{
+// 		// {Scope: "*", Resource: catchallResource}, toggleAdminRole
+// 		{Scope: "admin", Resource: adminLogout, ID: uuid.New().String(), Priority: 1},
+// 		{Scope: "admin", Resource: adminProfile, ID: uuid.New().String(), Priority: 1},
+// 		{Scope: "admin", Resource: listAdminRoles, ID: uuid.New().String(), Priority: 1},
+// 		{Scope: "admin", Resource: updateAdminRole, ID: uuid.New().String(), Priority: 1},
+// 		{Scope: "admin", Resource: createAdminRole, ID: uuid.New().String(), Priority: 1},
+// 		{Scope: "admin", Resource: toggleAdminRole, ID: uuid.New().String(), Priority: 1},
+// 		{Scope: "admin", Resource: getUnassignedAdminRoles, ID: uuid.New().String(), Priority: 1},
+// 		{Scope: "admin", Resource: deleteAdminRole, ID: uuid.New().String(), Priority: 1},
+// 		{Scope: "admin", Resource: getAdminRole, ID: uuid.New().String(), Priority: 1},
+// 		{Scope: "admin", Resource: retrieveEnabledRoles, ID: uuid.New().String(), Priority: 1},
+// 		{Scope: "admin", Resource: getAdminUser, ID: uuid.New().String(), Priority: 1},
+// 		{Scope: "admin", Resource: createAdminUser, ID: uuid.New().String(), Priority: 1},
+// 		{Scope: "admin", Resource: associateAdminUserWithRole, ID: uuid.New().String(), Priority: 1},
+// 		{Scope: "admin", Resource: updateAdminUser, ID: uuid.New().String(), Priority: 1},
+// 		{Scope: "admin", Resource: revokeAdminUserWithRole, ID: uuid.New().String(), Priority: 1},
+// 		{Scope: "admin", Resource: listAdminUsers, ID: uuid.New().String(), Priority: 1},
+// 		{Scope: "admin", Resource: retrieveEnabledUsers, ID: uuid.New().String(), Priority: 1},
+// 		{Scope: "admin", Resource: deleteAdminUser, ID: uuid.New().String(), Priority: 1},
+// 		{Scope: "admin", Resource: toggleAdminUser, ID: uuid.New().String(), Priority: 1},
+// 		{Scope: "kubernetes", Resource: adminProfile, ID: uuid.New().String(), Priority: 1},
+// 		{Scope: "kubernetes", Resource: getAuthentication, ID: uuid.New().String(), Priority: 1},
+// 	}
+// )
 
 func NewAuthWrapper(service micro.Service) server.HandlerWrapper {
 	return func(h server.HandlerFunc) server.HandlerFunc {
@@ -325,7 +325,6 @@ func NewAuthWrapper(service micro.Service) server.HandlerWrapper {
 
 			// 校验redis 存储数据
 			blacklisted, err := authutil.JWTAuthService.IsBlacklisted(token)
-			fmt.Println("blacklisted", blacklisted)
 			if err == nil && blacklisted {
 				return errorcode.Unauthorized("authorization service", common.ErrorMessage[common.ExpiredLonInAgainErrorCode])
 			}
@@ -336,12 +335,12 @@ func NewAuthWrapper(service micro.Service) server.HandlerWrapper {
 				Name:     md["Micro-Service"],
 				Endpoint: md["Micro-Endpoint"],
 			}
-
+			fmt.Println("acc.Scopes", acc.Scopes)
 			// Verify if account has access. 验证帐户是否具有访问权限。
-			if err = Verify(rulesItems, acc, &currentResource); err != nil {
+			if err = Verify(authutil.JWTAuthService.RulesItems, acc, &currentResource); err != nil {
 				return errorcode.Unauthorized("authorization service", common.ErrorMessage[common.NoAccessErrorCode])
 			}
-			// 验证通过后记录操作日志
+			// 验证通过后记录操作日志x
 			logrus.Infof("User %s is performing operation %s body %v", acc.ID, req.Endpoint(), req.Body())
 			return h(ctx, req, rsp)
 		}