sys_role.go 13 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487
  1. package service
  2. import (
  3. "Medical_OAuth/common/actions"
  4. cDto "Medical_OAuth/common/dto"
  5. "Medical_OAuth/common/global"
  6. "Medical_OAuth/conf"
  7. "encoding/json"
  8. "errors"
  9. "fmt"
  10. "github.com/casbin/casbin/v2"
  11. "github.com/go-resty/resty/v2"
  12. "gogs.baozhida.cn/zoie/OAuth-core/pkg"
  13. "gogs.baozhida.cn/zoie/OAuth-core/pkg/utils"
  14. "gogs.baozhida.cn/zoie/OAuth-core/service"
  15. "strconv"
  16. "strings"
  17. "Medical_OAuth/app/admin/model"
  18. "Medical_OAuth/app/admin/service/dto"
  19. "gorm.io/gorm"
  20. )
  21. type SysRole struct {
  22. service.Service
  23. }
  24. // GetPage 获取SysRole列表
  25. func (e *SysRole) GetPage(c *dto.SysRoleGetPageReq, list *[]model.SysRole, count *int64, p *actions.DataPermission) error {
  26. var err error
  27. var data model.SysRole
  28. err = e.Orm.Model(&data).
  29. Scopes(
  30. cDto.MakeCondition(c.GetNeedSearch()),
  31. cDto.Paginate(c.GetPageSize(), c.GetPageIndex()),
  32. actions.Permission(data.TableName(), p),
  33. ).
  34. Find(list).Limit(-1).Offset(-1).
  35. Count(count).Error
  36. if err != nil {
  37. e.Log.Errorf("db error: %s", err)
  38. return global.GetFailedErr
  39. }
  40. return nil
  41. }
  42. // Get 获取SysRole对象
  43. func (e *SysRole) Get(d *dto.SysRoleGetReq, roleModel *model.SysRole, p *actions.DataPermission) error {
  44. err := e.Orm.
  45. Scopes(actions.Permission(roleModel.TableName(), p)).
  46. First(roleModel, d.GetId()).Error
  47. if err != nil {
  48. e.Log.Errorf("db error: %s", err)
  49. if errors.Is(err, gorm.ErrRecordNotFound) {
  50. return global.GetNotFoundOrNoPermissionErr
  51. }
  52. return global.GetFailedErr
  53. }
  54. //roleModel.MenuIds, err = e.GetRoleMenuId(roleModel.Id)
  55. if err != nil {
  56. e.Log.Errorf("get menuIds error, %s", err)
  57. return global.GetFailedErr
  58. }
  59. return nil
  60. }
  61. // Insert 创建SysRole对象
  62. func (e *SysRole) Insert(c *dto.SysRoleInsertReq) error {
  63. var err error
  64. var data model.SysRole
  65. tx := e.Orm.Begin()
  66. defer func() {
  67. if err != nil {
  68. tx.Rollback()
  69. } else {
  70. tx.Commit()
  71. }
  72. }()
  73. var roleKey string
  74. for {
  75. var count int64
  76. roleKey = utils.GetRandString(8, "", 0)
  77. var i int64
  78. err = tx.Model(&data).Where("role_key = ?", roleKey).Count(&count).Error
  79. if err != nil {
  80. continue
  81. }
  82. if i == 0 {
  83. break
  84. }
  85. }
  86. c.Generate(&data)
  87. data.RoleKey = roleKey
  88. err = tx.Create(&data).Error
  89. if err != nil {
  90. e.Log.Errorf("db error: %s", err)
  91. return global.CreateFailedErr
  92. }
  93. c.Id = data.Id
  94. return nil
  95. }
  96. // Update 修改SysRole对象
  97. func (e *SysRole) Update(c *dto.SysRoleUpdateReq, p *actions.DataPermission) error {
  98. var err error
  99. tx := e.Orm.Begin()
  100. defer func() {
  101. if err != nil {
  102. tx.Rollback()
  103. } else {
  104. tx.Commit()
  105. }
  106. }()
  107. var roleModel = model.SysRole{}
  108. // 查询角色是否存在
  109. err = e.Orm.Scopes(actions.Permission(roleModel.TableName(), p)).
  110. First(&roleModel, c.GetId()).Error
  111. if err != nil {
  112. e.Log.Errorf("db error: %s", err)
  113. if errors.Is(err, gorm.ErrRecordNotFound) {
  114. return global.UpdateNotFoundOrNoPermissionErr
  115. }
  116. return global.UpdateFailedErr
  117. }
  118. c.Generate(&roleModel)
  119. err = tx.Save(&roleModel).Error
  120. if err != nil {
  121. e.Log.Errorf("db error: %s", err)
  122. return global.UpdateFailedErr
  123. }
  124. c.Id = roleModel.Id
  125. return nil
  126. }
  127. // Remove 删除SysRole
  128. func (e *SysRole) Remove(c *dto.SysRoleDeleteReq, p *actions.DataPermission, cb *casbin.SyncedEnforcer) error {
  129. var err error
  130. tx := e.Orm.Begin()
  131. defer func() {
  132. if err != nil {
  133. tx.Rollback()
  134. } else {
  135. tx.Commit()
  136. }
  137. }()
  138. var userList = make([]model.SysUser, 0)
  139. var roleModel model.SysRole
  140. err = e.Orm.Where("role_id = ?", c.Id).Find(&userList).Error
  141. if err != nil {
  142. e.Log.Errorf("db error: %s", err)
  143. return global.DeleteFailedErr
  144. }
  145. // 统计与用户关联的角色名
  146. if len(userList) > 0 {
  147. var roleNameStr string
  148. for i := 0; i < len(userList); i++ {
  149. roleNameStr += fmt.Sprintf(" %s,", userList[i].Username)
  150. }
  151. if !pkg.IsEmptyStr(roleNameStr) {
  152. // eg: role1,role2有用户关联,禁止删除!
  153. return errors.New(strings.TrimRight(roleNameStr, ",") + "有用户关联,禁止删除!")
  154. }
  155. }
  156. // 查询角色是否存在
  157. err = e.Orm.Scopes(actions.Permission(roleModel.TableName(), p)).
  158. First(&roleModel, c.GetId()).Error
  159. if err != nil {
  160. e.Log.Errorf("db error: %s", err)
  161. if errors.Is(err, gorm.ErrRecordNotFound) {
  162. return global.DeleteNotFoundOrNoPermissionErr
  163. }
  164. return global.DeleteFailedErr
  165. }
  166. db := tx.Delete(&roleModel)
  167. if err = db.Error; err != nil {
  168. e.Log.Errorf("db error: %s", err)
  169. return global.DeleteFailedErr
  170. }
  171. if db.RowsAffected == 0 {
  172. return global.DeleteNotFoundOrNoPermissionErr
  173. }
  174. // 删除之前的角色关联的api
  175. var roleApi model.ServRoleApi
  176. err = tx.Where("role_key = ?", roleModel.RoleKey).Delete(&roleApi).Error
  177. if err != nil {
  178. return global.UpdateFailedErr
  179. }
  180. // 删除之前的角色关联的菜单
  181. var roleMenu model.SysRoleMenu
  182. err = tx.Where("role_key = ?", roleModel.RoleKey).Delete(&roleMenu).Error
  183. if err != nil {
  184. return global.UpdateFailedErr
  185. }
  186. // 清除 sys_casbin_rule 权限表里 当前角色的所有记录
  187. _, _ = cb.RemoveFilteredPolicy(0, roleModel.RoleKey)
  188. return nil
  189. }
  190. // GetRoleMenuId 获取角色对应的菜单ids
  191. func (e *SysRole) GetRoleMenuId(roleId int) ([]int, error) {
  192. var err error
  193. var roleModel model.SysRole
  194. var menuIds []int
  195. err = e.Orm.Where("id = ?", roleId).First(&roleModel).Error
  196. if err != nil {
  197. return []int{}, global.GetFailedErr
  198. }
  199. err = e.Orm.Model(&model.SysRoleMenu{}).Select("menu_id").Where("role_key = ? ", roleModel.RoleKey).Scan(&menuIds).Error
  200. if err != nil {
  201. return []int{}, global.GetFailedErr
  202. }
  203. return menuIds, nil
  204. }
  205. // GetWithName 获取SysRole对象
  206. func (e *SysRole) GetWithName(d *dto.SysRoleByName, roleModel *model.SysRole) *SysRole {
  207. err := e.Orm.Where("name = ?", d.RoleName).First(roleModel).Error
  208. if err != nil {
  209. e.Log.Errorf("db error: %s", err)
  210. if errors.Is(err, gorm.ErrRecordNotFound) {
  211. err = global.GetNotFoundOrNoPermissionErr
  212. } else {
  213. err = global.GetFailedErr
  214. }
  215. _ = e.AddError(err)
  216. return e
  217. }
  218. //roleModel.MenuIds, err = e.GetRoleMenuId(roleModel.Id)
  219. if err != nil {
  220. e.Log.Errorf("get menuIds error, %s", err.Error())
  221. _ = e.AddError(global.GetFailedErr)
  222. return e
  223. }
  224. return e
  225. }
  226. // GetById 获取SysRole对象
  227. func (e *SysRole) GetById(roleId int) ([]string, error) {
  228. permissions := make([]string, 0)
  229. roleModel := model.SysRole{}
  230. roleModel.Id = roleId
  231. err := e.Orm.Model(&roleModel).First(&roleModel).Error
  232. if err != nil {
  233. e.Log.Errorf("db error: %s", err)
  234. if errors.Is(err, gorm.ErrRecordNotFound) {
  235. err = global.GetNotFoundOrNoPermissionErr
  236. } else {
  237. err = global.GetFailedErr
  238. }
  239. return nil, err
  240. }
  241. //l := *roleModel.SysMenu
  242. //for i := 0; i < len(l); i++ {
  243. // permissions = append(permissions, l[i].Permission)
  244. //}
  245. return permissions, nil
  246. }
  247. func (e *SysRole) SaveRoleApiCache(roleKey string, serviceId int, apiList []model.ServApi) {
  248. key := "role_api-" + roleKey + strconv.Itoa(serviceId)
  249. s, err := json.Marshal(apiList)
  250. err = e.Cache.Set(key, s, 24*60*60)
  251. if err != nil {
  252. e.Log.Errorf("save apiIds error to redis, %s", err)
  253. }
  254. }
  255. func (e *SysRole) GetRoleApiCache(roleKey string, serviceId int, apiList *[]model.ServApi) (err error) {
  256. key := "role_api-" + roleKey + strconv.Itoa(serviceId)
  257. s, err := e.Cache.Get(key)
  258. if err != nil {
  259. return err
  260. }
  261. err = json.Unmarshal([]byte(s), &apiList)
  262. return err
  263. }
  264. // UpdateRoleApi
  265. func (e *SysRole) UpdateRoleApi(d *dto.SysRoleUpdateRoleApiReq, cb *casbin.SyncedEnforcer) error {
  266. var err error
  267. tx := e.Orm.Begin()
  268. defer func() {
  269. if err != nil {
  270. tx.Rollback()
  271. } else {
  272. tx.Commit()
  273. }
  274. }()
  275. var roleModel model.SysRole
  276. err = e.Orm.Where("id = ?", d.GetId()).First(&roleModel).Error
  277. if err != nil {
  278. return global.GetFailedErr
  279. }
  280. var serviceModel model.SysService
  281. err = e.Orm.Where("id = ?", d.ServiceId).First(&serviceModel).Error
  282. if err != nil {
  283. return global.GetFailedErr
  284. }
  285. var apiList []model.ServApi
  286. err = e.Orm.Where("service_id = ? and id in (?)", d.ServiceId, d.ApiIds).Find(&apiList).Error
  287. if err != nil {
  288. return global.GetFailedErr
  289. }
  290. if len(apiList) == 0 {
  291. return errors.New("api接口不存在!")
  292. }
  293. // 发送api权限回调
  294. if serviceModel.No != conf.ExtConfig.Service.Number {
  295. // 调用回调地址
  296. client := resty.New()
  297. resp, err := client.R().
  298. SetHeader("Content-Type", "application/json").
  299. SetHeader("AuthCode", serviceModel.AuthCode).
  300. SetBody(map[string]interface{}{
  301. "roleKey": roleModel.RoleKey,
  302. "apiList": apiList,
  303. }).
  304. Post(serviceModel.Host + serviceModel.RoleApiUrl)
  305. if err != nil {
  306. return err
  307. }
  308. if resp.RawResponse.StatusCode != 200 {
  309. return errors.New("请求服务角色授权接口失败!")
  310. }
  311. }
  312. // 删除之前的角色关联的api
  313. var roleApi model.ServRoleApi
  314. err = tx.Where("role_key = ?", roleModel.RoleKey).Delete(&roleApi).Error
  315. if err != nil {
  316. return global.UpdateFailedErr
  317. }
  318. var roleApiList []model.ServRoleApi
  319. // 添加新增的角色关联的api
  320. for _, v := range apiList {
  321. roleApiObj := model.ServRoleApi{
  322. ServiceId: serviceModel.Id,
  323. RoleKey: roleModel.RoleKey,
  324. ApiId: v.Id,
  325. }
  326. roleApiObj.SetCreateBy(d.CreateBy)
  327. roleApiList = append(roleApiList, roleApiObj)
  328. }
  329. err = tx.Save(&roleApiList).Error
  330. if err != nil {
  331. e.Log.Errorf("save apiIds error, %s", err)
  332. return global.UpdateFailedErr
  333. }
  334. e.SaveRoleApiCache(roleModel.RoleKey, serviceModel.Id, apiList)
  335. polices := make([][]string, 0)
  336. for _, api := range apiList {
  337. sub, dom, obj, act := FormatRoutePolicyForRole(roleModel.RoleKey, &api)
  338. polices = append(polices, []string{sub, dom, obj, act})
  339. }
  340. // 清除 sys_casbin_rule 权限表里 当前角色的所有记录
  341. _, err = cb.RemoveFilteredPolicy(0, roleModel.RoleKey)
  342. _, err = cb.AddNamedPolicies("p", polices)
  343. if err != nil {
  344. return err
  345. }
  346. return nil
  347. }
  348. // GetRoleApiList
  349. func (e *SysRole) GetRoleApiList(d *dto.SysRoleGetRoleApiListReq, apiIds *[]int, apiList *[]model.ServApi) error {
  350. var err error
  351. var roleModel model.SysRole
  352. err = e.Orm.Where("id = ?", d.GetId()).First(&roleModel).Error
  353. if err != nil {
  354. return global.GetFailedErr
  355. }
  356. var serviceModel model.SysService
  357. err = e.Orm.Where("id = ?", d.ServiceId).First(&serviceModel).Error
  358. if err != nil {
  359. return global.GetFailedErr
  360. }
  361. e.Orm.Model(&model.ServRoleApi{}).Select("api_id").Where("role_key = ? and service_id = ?", roleModel.RoleKey, serviceModel.Id).Scan(apiIds)
  362. // 从redis获取角色对应的api列表
  363. err = e.GetRoleApiCache(roleModel.RoleKey, serviceModel.Id, apiList)
  364. if err == nil {
  365. return nil
  366. }
  367. err = e.Orm.Where("id in (?)", *apiIds).Find(&apiList).Error
  368. if err != nil {
  369. e.Log.Errorf("get apiIds error, %s", err)
  370. return global.GetFailedErr
  371. }
  372. e.SaveRoleApiCache(roleModel.RoleKey, serviceModel.Id, *apiList)
  373. return nil
  374. }
  375. func FormatRoutePolicyForRole(roleKey string, servApi *model.ServApi) (sub, dom, obj, act string) {
  376. sub = fmt.Sprintf("role:%s", roleKey) // 希望访问资源的角色
  377. dom = fmt.Sprintf("service:%d:api", servApi.ServiceId) // 域/域租户,这里以资源为单位
  378. obj = servApi.Path // 要访问的资源
  379. act = servApi.Action // 用户对资源执行的操作
  380. return
  381. }
  382. func FormatRoutePolicyForScope(roleKey string, servApi *model.ServApi) (sub, dom, obj, act string) {
  383. sub = fmt.Sprintf("scope:%s", roleKey) // 希望访问资源的范围
  384. dom = fmt.Sprintf("service:%d:api", servApi.ServiceId) // 域/域租户,这里以资源为单位
  385. obj = servApi.Path // 要访问的资源
  386. act = servApi.Action // 用户对资源执行的操作
  387. return
  388. }
  389. // UpdateRoleMenu 修改角色绑定的菜单
  390. func (e *SysRole) UpdateRoleMenu(d *dto.SysRoleUpdateRoleMenuReq) error {
  391. var err error
  392. tx := e.Orm.Begin()
  393. defer func() {
  394. if err != nil {
  395. tx.Rollback()
  396. } else {
  397. tx.Commit()
  398. }
  399. }()
  400. var roleModel model.SysRole
  401. err = e.Orm.Where("id = ?", d.GetId()).First(&roleModel).Error
  402. if err != nil {
  403. return global.GetFailedErr
  404. }
  405. var menuList []model.SysMenu
  406. err = e.Orm.Where("id in (?)", d.MenuIds).Find(&menuList).Error
  407. if err != nil {
  408. return global.GetFailedErr
  409. }
  410. if len(menuList) == 0 {
  411. return errors.New("菜单不存在!")
  412. }
  413. // 删除之前的角色关联的菜单
  414. var roleMenu model.SysRoleMenu
  415. err = tx.Where("role_key = ?", roleModel.RoleKey).Delete(&roleMenu).Error
  416. if err != nil {
  417. return global.UpdateFailedErr
  418. }
  419. var roleMenuList []model.SysRoleMenu
  420. // 添加角色关联的菜单
  421. for _, v := range menuList {
  422. roleMenuObj := model.SysRoleMenu{
  423. RoleKey: roleModel.RoleKey,
  424. MenuId: v.Id,
  425. }
  426. roleMenuObj.SetCreateBy(d.CreateBy)
  427. roleMenuList = append(roleMenuList, roleMenuObj)
  428. }
  429. err = tx.Save(&roleMenuList).Error
  430. if err != nil {
  431. e.Log.Errorf("save menuIds error, %s", err)
  432. return global.UpdateFailedErr
  433. }
  434. return nil
  435. }