package admin import ( "context" "fmt" "github.com/duke-git/lancet/v2/convertor" v1 "github.com/go-nunu/nunu-layout-advanced/api/v1" "github.com/go-nunu/nunu-layout-advanced/internal/model" "github.com/go-nunu/nunu-layout-advanced/internal/repository" "go.uber.org/zap" "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.Repository, ) AdminRepository { return &adminRepository{ Repository: repository, } } type adminRepository struct { *repository.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.DBWithName(ctx,"admin").Where("id = ?", id).First(&m).Error } func (r *adminRepository) GetRoleBySid(ctx context.Context, sid string) (model.Role, error) { m := model.Role{} return m, r.DBWithName(ctx,"admin").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.DBWithName(ctx,"admin").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.DBWithName(ctx,"admin").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.DBWithName(ctx,"admin").Where("id = ?", uid).First(&m).Error } func (r *adminRepository) AdminUserUpdate(ctx context.Context, m *model.AdminUser) error { return r.DBWithName(ctx,"admin").Where("id = ?", m.ID).Save(m).Error } func (r *adminRepository) AdminUserCreate(ctx context.Context, m *model.AdminUser) error { return r.DBWithName(ctx,"admin").Create(m).Error } func (r *adminRepository) AdminUserDelete(ctx context.Context, id uint) error { return r.DBWithName(ctx,"admin").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.DBWithName(ctx,"admin").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.DBWithName(ctx,"admin").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.DBWithName(ctx,"admin").Where("id = ?", m.ID).Save(m).Error } func (r *adminRepository) ApiCreate(ctx context.Context, m *model.Api) error { return r.DBWithName(ctx,"admin").Create(m).Error } func (r *adminRepository) ApiDelete(ctx context.Context, id uint) error { return r.DBWithName(ctx,"admin").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.DBWithName(ctx,"admin").Where("id = ?", m.ID).Save(m).Error } func (r *adminRepository) MenuCreate(ctx context.Context, m *model.Menu) error { return r.DBWithName(ctx,"admin").Save(m).Error } func (r *adminRepository) MenuDelete(ctx context.Context, id uint) error { return r.DBWithName(ctx,"admin").Where("id = ?", id).Delete(&model.Menu{}).Error } func (r *adminRepository) GetMenuList(ctx context.Context) ([]model.Menu, error) { var menuList []model.Menu if err := r.DBWithName(ctx,"admin").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.DBWithName(ctx,"admin").Where("id = ?", m.ID).UpdateColumn("name", m.Name).Error } func (r *adminRepository) RoleCreate(ctx context.Context, m *model.Role) error { return r.DBWithName(ctx,"admin").Create(m).Error } func (r *adminRepository) RoleDelete(ctx context.Context, id uint) error { return r.DBWithName(ctx,"admin").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.DBWithName(ctx,"admin").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 }