admin.go 10 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327
  1. package repository
  2. import (
  3. "context"
  4. "fmt"
  5. "github.com/duke-git/lancet/v2/convertor"
  6. v1 "github.com/go-nunu/nunu-layout-advanced/api/v1"
  7. "github.com/go-nunu/nunu-layout-advanced/internal/model"
  8. "go.uber.org/zap"
  9. "strings"
  10. )
  11. type AdminRepository interface {
  12. GetAdminUsers(ctx context.Context, req *v1.GetAdminUsersRequest) ([]model.AdminUser, int64, error)
  13. GetAdminUser(ctx context.Context, uid uint) (model.AdminUser, error)
  14. GetAdminUserByUsername(ctx context.Context, username string) (model.AdminUser, error)
  15. AdminUserUpdate(ctx context.Context, m *model.AdminUser) error
  16. AdminUserCreate(ctx context.Context, m *model.AdminUser) error
  17. AdminUserDelete(ctx context.Context, id uint) error
  18. GetUserPermissions(ctx context.Context, uid uint) ([][]string, error)
  19. GetUserRoles(ctx context.Context, uid uint) ([]string, error)
  20. GetRolePermissions(ctx context.Context, role string) ([][]string, error)
  21. UpdateRolePermission(ctx context.Context, role string, permissions map[string]struct{}) error
  22. UpdateUserRoles(ctx context.Context, uid uint, roles []string) error
  23. DeleteUserRoles(ctx context.Context, uid uint) error
  24. GetMenuList(ctx context.Context) ([]model.Menu, error)
  25. MenuUpdate(ctx context.Context, m *model.Menu) error
  26. MenuCreate(ctx context.Context, m *model.Menu) error
  27. MenuDelete(ctx context.Context, id uint) error
  28. GetRoles(ctx context.Context, req *v1.GetRoleListRequest) ([]model.Role, int64, error)
  29. RoleUpdate(ctx context.Context, m *model.Role) error
  30. RoleCreate(ctx context.Context, m *model.Role) error
  31. RoleDelete(ctx context.Context, id uint) error
  32. CasbinRoleDelete(ctx context.Context, role string) error
  33. GetRole(ctx context.Context, id uint) (model.Role, error)
  34. GetRoleBySid(ctx context.Context, sid string) (model.Role, error)
  35. GetApis(ctx context.Context, req *v1.GetApisRequest) ([]model.Api, int64, error)
  36. GetApiGroups(ctx context.Context) ([]string, error)
  37. ApiUpdate(ctx context.Context, m *model.Api) error
  38. ApiCreate(ctx context.Context, m *model.Api) error
  39. ApiDelete(ctx context.Context, id uint) error
  40. }
  41. func NewAdminRepository(
  42. repository *Repository,
  43. ) AdminRepository {
  44. return &adminRepository{
  45. Repository: repository,
  46. }
  47. }
  48. type adminRepository struct {
  49. *Repository
  50. }
  51. func (r *adminRepository) CasbinRoleDelete(ctx context.Context, role string) error {
  52. _, err := r.e.DeleteRole(role)
  53. return err
  54. }
  55. func (r *adminRepository) GetRole(ctx context.Context, id uint) (model.Role, error) {
  56. m := model.Role{}
  57. return m, r.DB(ctx).Where("id = ?", id).First(&m).Error
  58. }
  59. func (r *adminRepository) GetRoleBySid(ctx context.Context, sid string) (model.Role, error) {
  60. m := model.Role{}
  61. return m, r.DB(ctx).Where("sid = ?", sid).First(&m).Error
  62. }
  63. func (r *adminRepository) DeleteUserRoles(ctx context.Context, uid uint) error {
  64. _, err := r.e.DeleteRolesForUser(convertor.ToString(uid))
  65. return err
  66. }
  67. func (r *adminRepository) UpdateUserRoles(ctx context.Context, uid uint, roles []string) error {
  68. if len(roles) == 0 {
  69. _, err := r.e.DeleteRolesForUser(convertor.ToString(uid))
  70. return err
  71. }
  72. old, err := r.e.GetRolesForUser(convertor.ToString(uid))
  73. if err != nil {
  74. return err
  75. }
  76. oldMap := make(map[string]struct{})
  77. newMap := make(map[string]struct{})
  78. for _, v := range old {
  79. oldMap[v] = struct{}{}
  80. }
  81. for _, v := range roles {
  82. newMap[v] = struct{}{}
  83. }
  84. addRoles := make([]string, 0)
  85. delRoles := make([]string, 0)
  86. for key, _ := range oldMap {
  87. if _, exists := newMap[key]; !exists {
  88. delRoles = append(delRoles, key)
  89. }
  90. }
  91. for key, _ := range newMap {
  92. if _, exists := oldMap[key]; !exists {
  93. addRoles = append(addRoles, key)
  94. }
  95. }
  96. if len(addRoles) == 0 && len(delRoles) == 0 {
  97. return nil
  98. }
  99. for _, role := range delRoles {
  100. if _, err := r.e.DeleteRoleForUser(convertor.ToString(uid), role); err != nil {
  101. r.logger.WithContext(ctx).Error("DeleteRoleForUser error", zap.Error(err))
  102. return err
  103. }
  104. }
  105. _, err = r.e.AddRolesForUser(convertor.ToString(uid), addRoles)
  106. return err
  107. }
  108. func (r *adminRepository) GetAdminUserByUsername(ctx context.Context, username string) (model.AdminUser, error) {
  109. m := model.AdminUser{}
  110. return m, r.DB(ctx).Where("username = ?", username).First(&m).Error
  111. }
  112. func (r *adminRepository) GetAdminUsers(ctx context.Context, req *v1.GetAdminUsersRequest) ([]model.AdminUser, int64, error) {
  113. var list []model.AdminUser
  114. var total int64
  115. scope := r.DB(ctx).Model(&model.AdminUser{})
  116. if req.Username != "" {
  117. scope = scope.Where("username LIKE ?", "%"+req.Username+"%")
  118. }
  119. if req.Nickname != "" {
  120. scope = scope.Where("nickname LIKE ?", "%"+req.Nickname+"%")
  121. }
  122. if req.Email != "" {
  123. scope = scope.Where("email LIKE ?", "%"+req.Email+"%")
  124. }
  125. if req.Phone != "" {
  126. scope = scope.Where("phone LIKE ?", "%"+req.Phone+"%")
  127. }
  128. if err := scope.Count(&total).Error; err != nil {
  129. return nil, total, err
  130. }
  131. if err := scope.Offset((req.Page - 1) * req.PageSize).Limit(req.PageSize).Order("id DESC").Find(&list).Error; err != nil {
  132. return nil, total, err
  133. }
  134. return list, total, nil
  135. }
  136. func (r *adminRepository) GetAdminUser(ctx context.Context, uid uint) (model.AdminUser, error) {
  137. m := model.AdminUser{}
  138. return m, r.DB(ctx).Where("id = ?", uid).First(&m).Error
  139. }
  140. func (r *adminRepository) AdminUserUpdate(ctx context.Context, m *model.AdminUser) error {
  141. return r.DB(ctx).Where("id = ?", m.ID).Save(m).Error
  142. }
  143. func (r *adminRepository) AdminUserCreate(ctx context.Context, m *model.AdminUser) error {
  144. return r.DB(ctx).Create(m).Error
  145. }
  146. func (r *adminRepository) AdminUserDelete(ctx context.Context, id uint) error {
  147. return r.DB(ctx).Where("id = ?", id).Delete(&model.AdminUser{}).Error
  148. }
  149. func (r *adminRepository) UpdateRolePermission(ctx context.Context, role string, newPermSet map[string]struct{}) error {
  150. if len(newPermSet) == 0 {
  151. return nil
  152. }
  153. // 获取当前角色的所有权限
  154. oldPermissions, err := r.e.GetPermissionsForUser(role)
  155. if err != nil {
  156. return err
  157. }
  158. // 将旧权限转换为 map 方便查找
  159. oldPermSet := make(map[string]struct{})
  160. for _, perm := range oldPermissions {
  161. if len(perm) == 3 {
  162. oldPermSet[strings.Join([]string{perm[1], perm[2]}, model.PermSep)] = struct{}{}
  163. }
  164. }
  165. // 找出需要删除的权限
  166. var removePermissions [][]string
  167. for key, _ := range oldPermSet {
  168. if _, exists := newPermSet[key]; !exists {
  169. removePermissions = append(removePermissions, strings.Split(key, model.PermSep))
  170. }
  171. }
  172. // 找出需要添加的权限
  173. var addPermissions [][]string
  174. for key, _ := range newPermSet {
  175. if _, exists := oldPermSet[key]; !exists {
  176. addPermissions = append(addPermissions, strings.Split(key, model.PermSep))
  177. }
  178. }
  179. // 先移除多余的权限(使用 DeletePermissionForUser 逐条删除)
  180. for _, perm := range removePermissions {
  181. _, err := r.e.DeletePermissionForUser(role, perm...)
  182. if err != nil {
  183. return fmt.Errorf("移除权限失败: %v", err)
  184. }
  185. }
  186. // 再添加新的权限
  187. if len(addPermissions) > 0 {
  188. _, err = r.e.AddPermissionsForUser(role, addPermissions...)
  189. if err != nil {
  190. return fmt.Errorf("添加新权限失败: %v", err)
  191. }
  192. }
  193. return nil
  194. }
  195. func (r *adminRepository) GetApiGroups(ctx context.Context) ([]string, error) {
  196. res := make([]string, 0)
  197. if err := r.DB(ctx).Model(&model.Api{}).Group("`group`").Pluck("`group`", &res).Error; err != nil {
  198. return nil, err
  199. }
  200. return res, nil
  201. }
  202. func (r *adminRepository) GetApis(ctx context.Context, req *v1.GetApisRequest) ([]model.Api, int64, error) {
  203. var list []model.Api
  204. var total int64
  205. scope := r.DB(ctx).Model(&model.Api{})
  206. if req.Name != "" {
  207. scope = scope.Where("name LIKE ?", "%"+req.Name+"%")
  208. }
  209. if req.Group != "" {
  210. scope = scope.Where("`group` LIKE ?", "%"+req.Group+"%")
  211. }
  212. if req.Path != "" {
  213. scope = scope.Where("path LIKE ?", "%"+req.Path+"%")
  214. }
  215. if req.Method != "" {
  216. scope = scope.Where("method = ?", req.Method)
  217. }
  218. if err := scope.Count(&total).Error; err != nil {
  219. return nil, total, err
  220. }
  221. if err := scope.Offset((req.Page - 1) * req.PageSize).Limit(req.PageSize).Order("`group` ASC").Find(&list).Error; err != nil {
  222. return nil, total, err
  223. }
  224. return list, total, nil
  225. }
  226. func (r *adminRepository) ApiUpdate(ctx context.Context, m *model.Api) error {
  227. return r.DB(ctx).Where("id = ?", m.ID).Save(m).Error
  228. }
  229. func (r *adminRepository) ApiCreate(ctx context.Context, m *model.Api) error {
  230. return r.DB(ctx).Create(m).Error
  231. }
  232. func (r *adminRepository) ApiDelete(ctx context.Context, id uint) error {
  233. return r.DB(ctx).Where("id = ?", id).Delete(&model.Api{}).Error
  234. }
  235. func (r *adminRepository) GetUserPermissions(ctx context.Context, uid uint) ([][]string, error) {
  236. return r.e.GetImplicitPermissionsForUser(convertor.ToString(uid))
  237. }
  238. func (r *adminRepository) GetRolePermissions(ctx context.Context, role string) ([][]string, error) {
  239. return r.e.GetPermissionsForUser(role)
  240. }
  241. func (r *adminRepository) GetUserRoles(ctx context.Context, uid uint) ([]string, error) {
  242. return r.e.GetRolesForUser(convertor.ToString(uid))
  243. }
  244. func (r *adminRepository) MenuUpdate(ctx context.Context, m *model.Menu) error {
  245. return r.DB(ctx).Where("id = ?", m.ID).Save(m).Error
  246. }
  247. func (r *adminRepository) MenuCreate(ctx context.Context, m *model.Menu) error {
  248. return r.DB(ctx).Save(m).Error
  249. }
  250. func (r *adminRepository) MenuDelete(ctx context.Context, id uint) error {
  251. return r.DB(ctx).Where("id = ?", id).Delete(&model.Menu{}).Error
  252. }
  253. func (r *adminRepository) GetMenuList(ctx context.Context) ([]model.Menu, error) {
  254. var menuList []model.Menu
  255. if err := r.DB(ctx).Order("weight DESC").Find(&menuList).Error; err != nil {
  256. return nil, err
  257. }
  258. return menuList, nil
  259. }
  260. func (r *adminRepository) RoleUpdate(ctx context.Context, m *model.Role) error {
  261. return r.DB(ctx).Where("id = ?", m.ID).UpdateColumn("name", m.Name).Error
  262. }
  263. func (r *adminRepository) RoleCreate(ctx context.Context, m *model.Role) error {
  264. return r.DB(ctx).Create(m).Error
  265. }
  266. func (r *adminRepository) RoleDelete(ctx context.Context, id uint) error {
  267. return r.DB(ctx).Where("id = ?", id).Delete(&model.Role{}).Error
  268. }
  269. func (r *adminRepository) GetRoles(ctx context.Context, req *v1.GetRoleListRequest) ([]model.Role, int64, error) {
  270. var list []model.Role
  271. var total int64
  272. scope := r.DB(ctx).Model(&model.Role{})
  273. if req.Name != "" {
  274. scope = scope.Where("name LIKE ?", "%"+req.Name+"%")
  275. }
  276. if req.Sid != "" {
  277. scope = scope.Where("sid = ?", req.Sid)
  278. }
  279. if err := scope.Count(&total).Error; err != nil {
  280. return nil, total, err
  281. }
  282. if err := scope.Offset((req.Page - 1) * req.PageSize).Limit(req.PageSize).Find(&list).Error; err != nil {
  283. return nil, total, err
  284. }
  285. return list, total, nil
  286. }