nunu-layout-admin/internal/repository/admin.go

328 lines
10 KiB
Go

package repository
import (
"context"
"fmt"
"github.com/duke-git/lancet/v2/convertor"
"go.uber.org/zap"
v1 "nunu-layout-admin/api/v1"
"nunu-layout-admin/internal/model"
"strings"
)
type AdminRepository interface {
GetAdminUsers(ctx context.Context, req *v1.GetAdminUsersRequest) ([]model.AdminUser, int64, error)
GetAdminUser(ctx context.Context, uid uint) (model.AdminUser, error)
GetAdminUserByUsername(ctx context.Context, username string) (model.AdminUser, error)
AdminUserUpdate(ctx context.Context, m *model.AdminUser) error
AdminUserCreate(ctx context.Context, m *model.AdminUser) error
AdminUserDelete(ctx context.Context, id uint) error
GetUserPermissions(ctx context.Context, uid uint) ([][]string, error)
GetUserRoles(ctx context.Context, uid uint) ([]string, error)
GetRolePermissions(ctx context.Context, role string) ([][]string, error)
UpdateRolePermission(ctx context.Context, role string, permissions map[string]struct{}) error
UpdateUserRoles(ctx context.Context, uid uint, roles []string) error
DeleteUserRoles(ctx context.Context, uid uint) error
GetMenuList(ctx context.Context) ([]model.Menu, error)
MenuUpdate(ctx context.Context, m *model.Menu) error
MenuCreate(ctx context.Context, m *model.Menu) error
MenuDelete(ctx context.Context, id uint) error
GetRoles(ctx context.Context, req *v1.GetRoleListRequest) ([]model.Role, int64, error)
RoleUpdate(ctx context.Context, m *model.Role) error
RoleCreate(ctx context.Context, m *model.Role) error
RoleDelete(ctx context.Context, id uint) error
CasbinRoleDelete(ctx context.Context, role string) error
GetRole(ctx context.Context, id uint) (model.Role, error)
GetRoleBySid(ctx context.Context, sid string) (model.Role, error)
GetApis(ctx context.Context, req *v1.GetApisRequest) ([]model.Api, int64, error)
GetApiGroups(ctx context.Context) ([]string, error)
ApiUpdate(ctx context.Context, m *model.Api) error
ApiCreate(ctx context.Context, m *model.Api) error
ApiDelete(ctx context.Context, id uint) error
}
func NewAdminRepository(
repository *Repository,
) AdminRepository {
return &adminRepository{
Repository: repository,
}
}
type adminRepository struct {
*Repository
}
func (r *adminRepository) CasbinRoleDelete(ctx context.Context, role string) error {
_, err := r.e.DeleteRole(role)
return err
}
func (r *adminRepository) GetRole(ctx context.Context, id uint) (model.Role, error) {
m := model.Role{}
return m, r.DB(ctx).Where("id = ?", id).First(&m).Error
}
func (r *adminRepository) GetRoleBySid(ctx context.Context, sid string) (model.Role, error) {
m := model.Role{}
return m, r.DB(ctx).Where("sid = ?", sid).First(&m).Error
}
func (r *adminRepository) DeleteUserRoles(ctx context.Context, uid uint) error {
_, err := r.e.DeleteRolesForUser(convertor.ToString(uid))
return err
}
func (r *adminRepository) UpdateUserRoles(ctx context.Context, uid uint, roles []string) error {
if len(roles) == 0 {
_, err := r.e.DeleteRolesForUser(convertor.ToString(uid))
return err
}
old, err := r.e.GetRolesForUser(convertor.ToString(uid))
if err != nil {
return err
}
oldMap := make(map[string]struct{})
newMap := make(map[string]struct{})
for _, v := range old {
oldMap[v] = struct{}{}
}
for _, v := range roles {
newMap[v] = struct{}{}
}
addRoles := make([]string, 0)
delRoles := make([]string, 0)
for key, _ := range oldMap {
if _, exists := newMap[key]; !exists {
delRoles = append(delRoles, key)
}
}
for key, _ := range newMap {
if _, exists := oldMap[key]; !exists {
addRoles = append(addRoles, key)
}
}
if len(addRoles) == 0 && len(delRoles) == 0 {
return nil
}
for _, role := range delRoles {
if _, err := r.e.DeleteRoleForUser(convertor.ToString(uid), role); err != nil {
r.logger.WithContext(ctx).Error("DeleteRoleForUser error", zap.Error(err))
return err
}
}
_, err = r.e.AddRolesForUser(convertor.ToString(uid), addRoles)
return err
}
func (r *adminRepository) GetAdminUserByUsername(ctx context.Context, username string) (model.AdminUser, error) {
m := model.AdminUser{}
return m, r.DB(ctx).Where("username = ?", username).First(&m).Error
}
func (r *adminRepository) GetAdminUsers(ctx context.Context, req *v1.GetAdminUsersRequest) ([]model.AdminUser, int64, error) {
var list []model.AdminUser
var total int64
scope := r.DB(ctx).Model(&model.AdminUser{})
if req.Username != "" {
scope = scope.Where("username LIKE ?", "%"+req.Username+"%")
}
if req.Nickname != "" {
scope = scope.Where("nickname LIKE ?", "%"+req.Nickname+"%")
}
if req.Email != "" {
scope = scope.Where("email LIKE ?", "%"+req.Email+"%")
}
if req.Phone != "" {
scope = scope.Where("phone LIKE ?", "%"+req.Phone+"%")
}
if err := scope.Count(&total).Error; err != nil {
return nil, total, err
}
if err := scope.Offset((req.Page - 1) * req.PageSize).Limit(req.PageSize).Order("id DESC").Find(&list).Error; err != nil {
return nil, total, err
}
return list, total, nil
}
func (r *adminRepository) GetAdminUser(ctx context.Context, uid uint) (model.AdminUser, error) {
m := model.AdminUser{}
return m, r.DB(ctx).Where("id = ?", uid).First(&m).Error
}
func (r *adminRepository) AdminUserUpdate(ctx context.Context, m *model.AdminUser) error {
return r.DB(ctx).Where("id = ?", m.ID).Save(m).Error
}
func (r *adminRepository) AdminUserCreate(ctx context.Context, m *model.AdminUser) error {
return r.DB(ctx).Create(m).Error
}
func (r *adminRepository) AdminUserDelete(ctx context.Context, id uint) error {
return r.DB(ctx).Where("id = ?", id).Delete(&model.AdminUser{}).Error
}
func (r *adminRepository) UpdateRolePermission(ctx context.Context, role string, newPermSet map[string]struct{}) error {
if len(newPermSet) == 0 {
return nil
}
// 获取当前角色的所有权限
oldPermissions, err := r.e.GetPermissionsForUser(role)
if err != nil {
return err
}
// 将旧权限转换为 map 方便查找
oldPermSet := make(map[string]struct{})
for _, perm := range oldPermissions {
if len(perm) == 3 {
oldPermSet[strings.Join([]string{perm[1], perm[2]}, model.PermSep)] = struct{}{}
}
}
// 找出需要删除的权限
var removePermissions [][]string
for key, _ := range oldPermSet {
if _, exists := newPermSet[key]; !exists {
removePermissions = append(removePermissions, strings.Split(key, model.PermSep))
}
}
// 找出需要添加的权限
var addPermissions [][]string
for key, _ := range newPermSet {
if _, exists := oldPermSet[key]; !exists {
addPermissions = append(addPermissions, strings.Split(key, model.PermSep))
}
}
// 先移除多余的权限(使用 DeletePermissionForUser 逐条删除)
for _, perm := range removePermissions {
_, err := r.e.DeletePermissionForUser(role, perm...)
if err != nil {
return fmt.Errorf("移除权限失败: %v", err)
}
}
// 再添加新的权限
if len(addPermissions) > 0 {
_, err = r.e.AddPermissionsForUser(role, addPermissions...)
if err != nil {
return fmt.Errorf("添加新权限失败: %v", err)
}
}
return nil
}
func (r *adminRepository) GetApiGroups(ctx context.Context) ([]string, error) {
res := make([]string, 0)
if err := r.DB(ctx).Model(&model.Api{}).Group("`group`").Pluck("`group`", &res).Error; err != nil {
return nil, err
}
return res, nil
}
func (r *adminRepository) GetApis(ctx context.Context, req *v1.GetApisRequest) ([]model.Api, int64, error) {
var list []model.Api
var total int64
scope := r.DB(ctx).Model(&model.Api{})
if req.Name != "" {
scope = scope.Where("name LIKE ?", "%"+req.Name+"%")
}
if req.Group != "" {
scope = scope.Where("`group` LIKE ?", "%"+req.Group+"%")
}
if req.Path != "" {
scope = scope.Where("path LIKE ?", "%"+req.Path+"%")
}
if req.Method != "" {
scope = scope.Where("method = ?", req.Method)
}
if err := scope.Count(&total).Error; err != nil {
return nil, total, err
}
if err := scope.Offset((req.Page - 1) * req.PageSize).Limit(req.PageSize).Order("`group` ASC").Find(&list).Error; err != nil {
return nil, total, err
}
return list, total, nil
}
func (r *adminRepository) ApiUpdate(ctx context.Context, m *model.Api) error {
return r.DB(ctx).Where("id = ?", m.ID).Save(m).Error
}
func (r *adminRepository) ApiCreate(ctx context.Context, m *model.Api) error {
return r.DB(ctx).Create(m).Error
}
func (r *adminRepository) ApiDelete(ctx context.Context, id uint) error {
return r.DB(ctx).Where("id = ?", id).Delete(&model.Api{}).Error
}
func (r *adminRepository) GetUserPermissions(ctx context.Context, uid uint) ([][]string, error) {
return r.e.GetImplicitPermissionsForUser(convertor.ToString(uid))
}
func (r *adminRepository) GetRolePermissions(ctx context.Context, role string) ([][]string, error) {
return r.e.GetPermissionsForUser(role)
}
func (r *adminRepository) GetUserRoles(ctx context.Context, uid uint) ([]string, error) {
return r.e.GetRolesForUser(convertor.ToString(uid))
}
func (r *adminRepository) MenuUpdate(ctx context.Context, m *model.Menu) error {
return r.DB(ctx).Where("id = ?", m.ID).Save(m).Error
}
func (r *adminRepository) MenuCreate(ctx context.Context, m *model.Menu) error {
return r.DB(ctx).Save(m).Error
}
func (r *adminRepository) MenuDelete(ctx context.Context, id uint) error {
return r.DB(ctx).Where("id = ?", id).Delete(&model.Menu{}).Error
}
func (r *adminRepository) GetMenuList(ctx context.Context) ([]model.Menu, error) {
var menuList []model.Menu
if err := r.DB(ctx).Order("weight DESC").Find(&menuList).Error; err != nil {
return nil, err
}
return menuList, nil
}
func (r *adminRepository) RoleUpdate(ctx context.Context, m *model.Role) error {
return r.DB(ctx).Where("id = ?", m.ID).UpdateColumn("name", m.Name).Error
}
func (r *adminRepository) RoleCreate(ctx context.Context, m *model.Role) error {
return r.DB(ctx).Create(m).Error
}
func (r *adminRepository) RoleDelete(ctx context.Context, id uint) error {
return r.DB(ctx).Where("id = ?", id).Delete(&model.Role{}).Error
}
func (r *adminRepository) GetRoles(ctx context.Context, req *v1.GetRoleListRequest) ([]model.Role, int64, error) {
var list []model.Role
var total int64
scope := r.DB(ctx).Model(&model.Role{})
if req.Name != "" {
scope = scope.Where("name LIKE ?", "%"+req.Name+"%")
}
if req.Sid != "" {
scope = scope.Where("sid = ?", req.Sid)
}
if err := scope.Count(&total).Error; err != nil {
return nil, total, err
}
if err := scope.Offset((req.Page - 1) * req.PageSize).Limit(req.PageSize).Find(&list).Error; err != nil {
return nil, total, err
}
return list, total, nil
}