sys_authority.go 11 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330
  1. package system
  2. import (
  3. "errors"
  4. "strconv"
  5. systemReq "github.com/flipped-aurora/gin-vue-admin/server/model/system/request"
  6. "github.com/flipped-aurora/gin-vue-admin/server/global"
  7. "github.com/flipped-aurora/gin-vue-admin/server/model/common/request"
  8. "github.com/flipped-aurora/gin-vue-admin/server/model/system"
  9. "github.com/flipped-aurora/gin-vue-admin/server/model/system/response"
  10. "gorm.io/gorm"
  11. )
  12. var ErrRoleExistence = errors.New("存在相同角色id")
  13. //@author: [piexlmax](https://github.com/piexlmax)
  14. //@function: CreateAuthority
  15. //@description: 创建一个角色
  16. //@param: auth model.SysAuthority
  17. //@return: authority system.SysAuthority, err error
  18. type AuthorityService struct{}
  19. var AuthorityServiceApp = new(AuthorityService)
  20. func (authorityService *AuthorityService) CreateAuthority(auth system.SysAuthority) (authority system.SysAuthority, err error) {
  21. if err = global.GVA_DB.Where("authority_id = ?", auth.AuthorityId).First(&system.SysAuthority{}).Error; !errors.Is(err, gorm.ErrRecordNotFound) {
  22. return auth, ErrRoleExistence
  23. }
  24. e := global.GVA_DB.Transaction(func(tx *gorm.DB) error {
  25. if err = tx.Create(&auth).Error; err != nil {
  26. return err
  27. }
  28. auth.SysBaseMenus = systemReq.DefaultMenu()
  29. if err = tx.Model(&auth).Association("SysBaseMenus").Replace(&auth.SysBaseMenus); err != nil {
  30. return err
  31. }
  32. casbinInfos := systemReq.DefaultCasbin()
  33. authorityId := strconv.Itoa(int(auth.AuthorityId))
  34. rules := [][]string{}
  35. for _, v := range casbinInfos {
  36. rules = append(rules, []string{authorityId, v.Path, v.Method})
  37. }
  38. return CasbinServiceApp.AddPolicies(tx, rules)
  39. })
  40. return auth, e
  41. }
  42. //@author: [piexlmax](https://github.com/piexlmax)
  43. //@function: CopyAuthority
  44. //@description: 复制一个角色
  45. //@param: copyInfo response.SysAuthorityCopyResponse
  46. //@return: authority system.SysAuthority, err error
  47. func (authorityService *AuthorityService) CopyAuthority(adminAuthorityID uint, copyInfo response.SysAuthorityCopyResponse) (authority system.SysAuthority, err error) {
  48. var authorityBox system.SysAuthority
  49. if !errors.Is(global.GVA_DB.Where("authority_id = ?", copyInfo.Authority.AuthorityId).First(&authorityBox).Error, gorm.ErrRecordNotFound) {
  50. return authority, ErrRoleExistence
  51. }
  52. copyInfo.Authority.Children = []system.SysAuthority{}
  53. menus, err := MenuServiceApp.GetMenuAuthority(&request.GetAuthorityId{AuthorityId: copyInfo.OldAuthorityId})
  54. if err != nil {
  55. return
  56. }
  57. var baseMenu []system.SysBaseMenu
  58. for _, v := range menus {
  59. intNum := v.MenuId
  60. v.SysBaseMenu.ID = uint(intNum)
  61. baseMenu = append(baseMenu, v.SysBaseMenu)
  62. }
  63. copyInfo.Authority.SysBaseMenus = baseMenu
  64. err = global.GVA_DB.Create(&copyInfo.Authority).Error
  65. if err != nil {
  66. return
  67. }
  68. var btns []system.SysAuthorityBtn
  69. err = global.GVA_DB.Find(&btns, "authority_id = ?", copyInfo.OldAuthorityId).Error
  70. if err != nil {
  71. return
  72. }
  73. if len(btns) > 0 {
  74. for i := range btns {
  75. btns[i].AuthorityId = copyInfo.Authority.AuthorityId
  76. }
  77. err = global.GVA_DB.Create(&btns).Error
  78. if err != nil {
  79. return
  80. }
  81. }
  82. paths := CasbinServiceApp.GetPolicyPathByAuthorityId(copyInfo.OldAuthorityId)
  83. err = CasbinServiceApp.UpdateCasbin(adminAuthorityID, copyInfo.Authority.AuthorityId, paths)
  84. if err != nil {
  85. _ = authorityService.DeleteAuthority(&copyInfo.Authority)
  86. }
  87. return copyInfo.Authority, err
  88. }
  89. //@author: [piexlmax](https://github.com/piexlmax)
  90. //@function: UpdateAuthority
  91. //@description: 更改一个角色
  92. //@param: auth model.SysAuthority
  93. //@return: authority system.SysAuthority, err error
  94. func (authorityService *AuthorityService) UpdateAuthority(auth system.SysAuthority) (authority system.SysAuthority, err error) {
  95. var oldAuthority system.SysAuthority
  96. err = global.GVA_DB.Where("authority_id = ?", auth.AuthorityId).First(&oldAuthority).Error
  97. if err != nil {
  98. global.GVA_LOG.Debug(err.Error())
  99. return system.SysAuthority{}, errors.New("查询角色数据失败")
  100. }
  101. err = global.GVA_DB.Model(&oldAuthority).Updates(&auth).Error
  102. return auth, err
  103. }
  104. //@author: [piexlmax](https://github.com/piexlmax)
  105. //@function: DeleteAuthority
  106. //@description: 删除角色
  107. //@param: auth *model.SysAuthority
  108. //@return: err error
  109. func (authorityService *AuthorityService) DeleteAuthority(auth *system.SysAuthority) error {
  110. if errors.Is(global.GVA_DB.Debug().Preload("Users").First(&auth).Error, gorm.ErrRecordNotFound) {
  111. return errors.New("该角色不存在")
  112. }
  113. if len(auth.Users) != 0 {
  114. return errors.New("此角色有用户正在使用禁止删除")
  115. }
  116. if !errors.Is(global.GVA_DB.Where("authority_id = ?", auth.AuthorityId).First(&system.SysUser{}).Error, gorm.ErrRecordNotFound) {
  117. return errors.New("此角色有用户正在使用禁止删除")
  118. }
  119. if !errors.Is(global.GVA_DB.Where("parent_id = ?", auth.AuthorityId).First(&system.SysAuthority{}).Error, gorm.ErrRecordNotFound) {
  120. return errors.New("此角色存在子角色不允许删除")
  121. }
  122. return global.GVA_DB.Transaction(func(tx *gorm.DB) error {
  123. var err error
  124. if err = tx.Preload("SysBaseMenus").Preload("DataAuthorityId").Where("authority_id = ?", auth.AuthorityId).First(auth).Unscoped().Delete(auth).Error; err != nil {
  125. return err
  126. }
  127. if len(auth.SysBaseMenus) > 0 {
  128. if err = tx.Model(auth).Association("SysBaseMenus").Delete(auth.SysBaseMenus); err != nil {
  129. return err
  130. }
  131. // err = db.Association("SysBaseMenus").Delete(&auth)
  132. }
  133. if len(auth.DataAuthorityId) > 0 {
  134. if err = tx.Model(auth).Association("DataAuthorityId").Delete(auth.DataAuthorityId); err != nil {
  135. return err
  136. }
  137. }
  138. if err = tx.Delete(&system.SysUserAuthority{}, "sys_authority_authority_id = ?", auth.AuthorityId).Error; err != nil {
  139. return err
  140. }
  141. if err = tx.Where("authority_id = ?", auth.AuthorityId).Delete(&[]system.SysAuthorityBtn{}).Error; err != nil {
  142. return err
  143. }
  144. authorityId := strconv.Itoa(int(auth.AuthorityId))
  145. if err = CasbinServiceApp.RemoveFilteredPolicy(tx, authorityId); err != nil {
  146. return err
  147. }
  148. return nil
  149. })
  150. }
  151. //@author: [piexlmax](https://github.com/piexlmax)
  152. //@function: GetAuthorityInfoList
  153. //@description: 分页获取数据
  154. //@param: info request.PageInfo
  155. //@return: list interface{}, total int64, err error
  156. func (authorityService *AuthorityService) GetAuthorityInfoList(authorityID uint) (list []system.SysAuthority, err error) {
  157. var authority system.SysAuthority
  158. err = global.GVA_DB.Where("authority_id = ?", authorityID).First(&authority).Error
  159. if err != nil {
  160. return nil, err
  161. }
  162. var authorities []system.SysAuthority
  163. db := global.GVA_DB.Model(&system.SysAuthority{})
  164. if global.GVA_CONFIG.System.UseStrictAuth {
  165. // 当开启了严格树形结构后
  166. if *authority.ParentId == 0 {
  167. // 只有顶级角色可以修改自己的权限和以下权限
  168. err = db.Preload("DataAuthorityId").Where("authority_id = ?", authorityID).Find(&authorities).Error
  169. } else {
  170. // 非顶级角色只能修改以下权限
  171. err = db.Debug().Preload("DataAuthorityId").Where("parent_id = ?", authorityID).Find(&authorities).Error
  172. }
  173. } else {
  174. err = db.Preload("DataAuthorityId").Where("parent_id = ?", "0").Find(&authorities).Error
  175. }
  176. for k := range authorities {
  177. err = authorityService.findChildrenAuthority(&authorities[k])
  178. }
  179. return authorities, err
  180. }
  181. //@author: [piexlmax](https://github.com/piexlmax)
  182. //@function: GetAuthorityInfoList
  183. //@description: 分页获取数据
  184. //@param: info request.PageInfo
  185. //@return: list interface{}, total int64, err error
  186. func (authorityService *AuthorityService) GetStructAuthorityList(authorityID uint) (list []uint, err error) {
  187. var auth system.SysAuthority
  188. _ = global.GVA_DB.First(&auth, "authority_id = ?", authorityID).Error
  189. var authorities []system.SysAuthority
  190. err = global.GVA_DB.Preload("DataAuthorityId").Where("parent_id = ?", authorityID).Find(&authorities).Error
  191. if len(authorities) > 0 {
  192. for k := range authorities {
  193. list = append(list, authorities[k].AuthorityId)
  194. childrenList, err := authorityService.GetStructAuthorityList(authorities[k].AuthorityId)
  195. if err == nil {
  196. list = append(list, childrenList...)
  197. }
  198. }
  199. }
  200. if *auth.ParentId == 0 {
  201. list = append(list, authorityID)
  202. }
  203. return list, err
  204. }
  205. func (authorityService *AuthorityService) CheckAuthorityIDAuth(authorityID, targetID uint) (err error) {
  206. if !global.GVA_CONFIG.System.UseStrictAuth {
  207. return nil
  208. }
  209. authIDS, err := authorityService.GetStructAuthorityList(authorityID)
  210. if err != nil {
  211. return err
  212. }
  213. hasAuth := false
  214. for _, v := range authIDS {
  215. if v == targetID {
  216. hasAuth = true
  217. break
  218. }
  219. }
  220. if !hasAuth {
  221. return errors.New("您提交的角色ID不合法")
  222. }
  223. return nil
  224. }
  225. //@author: [piexlmax](https://github.com/piexlmax)
  226. //@function: GetAuthorityInfo
  227. //@description: 获取所有角色信息
  228. //@param: auth model.SysAuthority
  229. //@return: sa system.SysAuthority, err error
  230. func (authorityService *AuthorityService) GetAuthorityInfo(auth system.SysAuthority) (sa system.SysAuthority, err error) {
  231. err = global.GVA_DB.Preload("DataAuthorityId").Where("authority_id = ?", auth.AuthorityId).First(&sa).Error
  232. return sa, err
  233. }
  234. //@author: [piexlmax](https://github.com/piexlmax)
  235. //@function: SetDataAuthority
  236. //@description: 设置角色资源权限
  237. //@param: auth model.SysAuthority
  238. //@return: error
  239. func (authorityService *AuthorityService) SetDataAuthority(adminAuthorityID uint, auth system.SysAuthority) error {
  240. var checkIDs []uint
  241. checkIDs = append(checkIDs, auth.AuthorityId)
  242. for i := range auth.DataAuthorityId {
  243. checkIDs = append(checkIDs, auth.DataAuthorityId[i].AuthorityId)
  244. }
  245. for i := range checkIDs {
  246. err := authorityService.CheckAuthorityIDAuth(adminAuthorityID, checkIDs[i])
  247. if err != nil {
  248. return err
  249. }
  250. }
  251. var s system.SysAuthority
  252. global.GVA_DB.Preload("DataAuthorityId").First(&s, "authority_id = ?", auth.AuthorityId)
  253. err := global.GVA_DB.Model(&s).Association("DataAuthorityId").Replace(&auth.DataAuthorityId)
  254. return err
  255. }
  256. //@author: [piexlmax](https://github.com/piexlmax)
  257. //@function: SetMenuAuthority
  258. //@description: 菜单与角色绑定
  259. //@param: auth *model.SysAuthority
  260. //@return: error
  261. func (authorityService *AuthorityService) SetMenuAuthority(auth *system.SysAuthority) error {
  262. var s system.SysAuthority
  263. global.GVA_DB.Preload("SysBaseMenus").First(&s, "authority_id = ?", auth.AuthorityId)
  264. err := global.GVA_DB.Model(&s).Association("SysBaseMenus").Replace(&auth.SysBaseMenus)
  265. return err
  266. }
  267. //@author: [piexlmax](https://github.com/piexlmax)
  268. //@function: findChildrenAuthority
  269. //@description: 查询子角色
  270. //@param: authority *model.SysAuthority
  271. //@return: err error
  272. func (authorityService *AuthorityService) findChildrenAuthority(authority *system.SysAuthority) (err error) {
  273. err = global.GVA_DB.Preload("DataAuthorityId").Where("parent_id = ?", authority.AuthorityId).Find(&authority.Children).Error
  274. if len(authority.Children) > 0 {
  275. for k := range authority.Children {
  276. err = authorityService.findChildrenAuthority(&authority.Children[k])
  277. }
  278. }
  279. return err
  280. }
  281. func (authorityService *AuthorityService) GetParentAuthorityID(authorityID uint) (parentID uint, err error) {
  282. var authority system.SysAuthority
  283. err = global.GVA_DB.Where("authority_id = ?", authorityID).First(&authority).Error
  284. return *authority.ParentId, err
  285. }