baotian
2024-06-04 b959135a1139fb66646523d92e5bd20c5910f283
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
using iWare.Wms.Core;
using Furion.DatabaseAccessor;
using Furion.DatabaseAccessor.Extensions;
using Furion.DependencyInjection;
using Furion.DynamicApiController;
using Furion.FriendlyException;
using Mapster;
using Microsoft.AspNetCore.Mvc;
using Microsoft.EntityFrameworkCore;
 
namespace iWare.Wms.Application
{
    /// <summary>
    /// 角色服务
    /// </summary>
    [ApiDescriptionSettings(Name = "Role", Order = 149)]
    [Route("api")]
    public class SysRoleService : ISysRoleService, IDynamicApiController, ITransient
    {
        private readonly IRepository<SysRole> _sysRoleRep;  // 角色表仓储
        private readonly IRepository<SysUserRole> _sysUserRoleRep;  // 用户角色表仓储
        private readonly ISysRoleDataScopeService _sysRoleDataScopeService;
        private readonly ISysOrgService _sysOrgService;
        private readonly ISysRoleMenuService _sysRoleMenuService;
        private readonly ISysCacheService _sysCacheService;
 
        public SysRoleService(IRepository<SysRole> sysRoleRep,
                              IRepository<SysUserRole> sysUserRoleRep,
                              ISysRoleDataScopeService sysRoleDataScopeService,
                              ISysOrgService sysOrgService,
                              ISysRoleMenuService sysRoleMenuService,
                              ISysCacheService sysCacheService)
        {
            _sysRoleRep = sysRoleRep;
            _sysUserRoleRep = sysUserRoleRep;
            _sysRoleDataScopeService = sysRoleDataScopeService;
            _sysOrgService = sysOrgService;
            _sysRoleMenuService = sysRoleMenuService;
            _sysCacheService = sysCacheService;
        }
 
        /// <summary>
        /// 获取用户角色相关信息(登录)
        /// </summary>
        /// <param name="userId"></param>
        /// <returns></returns>
        [NonAction]
        public async Task<List<RoleOutput>> GetUserRoleList(long userId)
        {
            return await _sysUserRoleRep.Include(m => m.SysRole, false)
                  .Where(m => m.SysUserId == userId && m.SysRole.Status == CommonStatus.ENABLE)
                  .Select(m => new RoleOutput
                  {
                      Id = m.SysRoleId,
                      Code = m.SysRole.Code,
                      Name = m.SysRole.Name
                  }).ToListAsync();
        }
 
        /// <summary>
        /// 分页获取角色列表
        /// </summary>
        /// <param name="input"></param>
        /// <returns></returns>
        [HttpGet("sysRole/page")]
        public async Task<PageResult<SysRole>> QueryRolePageList([FromQuery] RolePageInput input)
        {
            var name = !string.IsNullOrEmpty(input.Name?.Trim());
            var code = !string.IsNullOrEmpty(input.Code?.Trim());
            var roles = await _sysRoleRep.DetachedEntities
                                         .Where((name, u => EF.Functions.Like(u.Name, $"%{input.Name.Trim()}%")),
                                                (code, u => EF.Functions.Like(u.Code, $"%{input.Code.Trim()}%")))
                                         .Where(u => u.Status == CommonStatus.ENABLE).OrderBy(u => u.Sort)
                                         .ToADPagedListAsync(input.PageNo, input.PageSize);
            return roles;
        }
 
        /// <summary>
        /// 获取角色列表
        /// </summary>
        /// <param name="input"></param>
        /// <returns></returns>
        [NonAction]
        public async Task<dynamic> GetRoleList([FromQuery] RoleInput input)
        {
            var name = !string.IsNullOrEmpty(input.Name?.Trim());
            var code = !string.IsNullOrEmpty(input.Code?.Trim());
            return await _sysRoleRep.DetachedEntities
                                    .Where((name, u => EF.Functions.Like(u.Name, $"%{input.Name.Trim()}%")),
                                           (code, u => EF.Functions.Like(u.Code, $"%{input.Code.Trim()}%")))
                                    .Where(u => u.Status == CommonStatus.ENABLE)
                                    .OrderBy(u => u.Sort)
                                    .Select(u => new
                                    {
                                        u.Id,
                                        Name = u.Name + "[" + u.Code + "]",
                                    })
                                    .ToListAsync();
        }
 
        /// <summary>
        /// 角色下拉(用于授权角色时选择)
        /// </summary>
        /// <returns></returns>
        [HttpGet("sysRole/dropDown")]
        public async Task<List<RoleOutput>> GetRoleDropDown()
        {
            // 如果不是超级管理员,则查询自己拥有的角色集合
            var roles = CurrentUserInfo.IsSuperAdmin
                        ? await _sysUserRoleRep.Where(u => u.SysUserId == CurrentUserInfo.UserId).Select(u => u.SysRoleId).ToListAsync()
                        : new List<long>();
 
            return await _sysRoleRep.DetachedEntities
                                    .Where(roles.Count > 0, u => roles.Contains(u.Id))
                                    .Where(u => u.Status == CommonStatus.ENABLE)
                                    .ProjectToType<RoleOutput>()
                                    .ToListAsync();
        }
 
        /// <summary>
        /// 增加角色
        /// </summary>
        /// <param name="input"></param>
        /// <returns></returns>
        [HttpPost("sysRole/add")]
        public async Task AddRole(AddRoleInput input)
        {
            var isExist = await _sysRoleRep.DetachedEntities.AnyAsync(u => u.Code == input.Code || u.Name == input.Name);
            if (isExist)
                throw Oops.Oh(ErrorCode.D1006);
 
            var role = input.Adapt<SysRole>();
            role.DataScopeType = DataScopeType.ALL; // 新角色默认全部数据范围
            await role.InsertAsync();
        }
 
        /// <summary>
        /// 删除角色
        /// </summary>
        /// <param name="input"></param>
        /// <returns></returns>
        [HttpPost("sysRole/delete")]
        [UnitOfWork]
        public async Task DeleteRole(DeleteRoleInput input)
        {
            var sysRole = await _sysRoleRep.FirstOrDefaultAsync(u => u.Id == input.Id);
            if (sysRole.Code == CommonConst.SYS_MANAGER_ROLE_CODE)
                throw Oops.Oh(ErrorCode.D1019);
 
            await sysRole.DeleteAsync();
 
            //级联删除该角色对应的角色-数据范围关联信息
            await _sysRoleDataScopeService.DeleteRoleDataScopeListByRoleId(sysRole.Id);
 
            ////级联删除该角色对应的用户-角色表关联信息
            //await _sysUserRoleService.DeleteUserRoleListByRoleId(sysRole.Id); // 避免循环引用,故用下面逻辑
            var userRoles = await _sysUserRoleRep.Where(u => u.SysRoleId == sysRole.Id).ToListAsync();
            await _sysUserRoleRep.DeleteAsync(userRoles);
 
            //级联删除该角色对应的角色-菜单表关联信息
            await _sysRoleMenuService.DeleteRoleMenuListByRoleId(sysRole.Id);
        }
 
        /// <summary>
        /// 更新角色
        /// </summary>
        /// <param name="input"></param>
        /// <returns></returns>
        [HttpPost("sysRole/edit")]
        public async Task UpdateRole(UpdateRoleInput input)
        {
            var adminRole = await _sysRoleRep.DetachedEntities.FirstOrDefaultAsync(u => u.Id == input.Id);
            if (adminRole.Code == CommonConst.SYS_MANAGER_ROLE_CODE)
                throw Oops.Oh(ErrorCode.D1020);
 
            var isExist = await _sysRoleRep.DetachedEntities.AnyAsync(u => (u.Name == input.Name || u.Code == input.Code) && u.Id != input.Id);
            if (isExist)
                throw Oops.Oh(ErrorCode.D1006);
 
            var sysRole = input.Adapt<SysRole>();
            await sysRole.UpdateExcludeAsync(new[] { nameof(SysRole.DataScopeType) }, true);
        }
 
        /// <summary>
        /// 获取角色
        /// </summary>
        /// <param name="input"></param>
        /// <returns></returns>
        [HttpGet("sysRole/detail")]
        public async Task<SysRole> GetRoleInfo([FromQuery] QueryRoleInput input)
        {
            return await _sysRoleRep.DetachedEntities.FirstOrDefaultAsync(u => u.Id == input.Id);
        }
 
        /// <summary>
        /// 授权角色菜单
        /// </summary>
        /// <param name="input"></param>
        /// <returns></returns>
        [HttpPost("sysRole/grantMenu")]
        public async Task GrantMenu(GrantRoleMenuInput input)
        {
            var adminRole = await _sysRoleRep.DetachedEntities.FirstOrDefaultAsync(u => u.Id == input.Id);
            if (!CurrentUserInfo.IsSuperAdmin && adminRole.Code == CommonConst.SYS_MANAGER_ROLE_CODE)
                throw Oops.Oh(ErrorCode.D1021);
 
            await _sysRoleMenuService.GrantMenu(input);
        }
 
        /// <summary>
        /// 授权角色数据范围
        /// </summary>
        /// <param name="input"></param>
        /// <returns></returns>
        [HttpPost("sysRole/grantData")]
        public async Task GrantData(GrantRoleDataInput input)
        {
            // 清除所有用户数据范围缓存
            await _sysCacheService.DelByPatternAsync(CommonConst.CACHE_KEY_DATASCOPE);
 
            var role = await _sysRoleRep.FirstOrDefaultAsync(u => u.Id == input.Id);
            var dataScopeType = input.DataScopeType;
            if (!CurrentUserInfo.IsSuperAdmin)
            {
                //如果授权的角色的数据范围类型为全部,则没权限,只有超级管理员有
                if ((int)DataScopeType.ALL == dataScopeType)
                    throw Oops.Oh(ErrorCode.D1016);
 
                //如果授权的角色数据范围类型为自定义,则要判断授权的数据范围是否在自己的数据范围内
                if ((int)DataScopeType.DEFINE == dataScopeType)
                {
                    var dataScopes = await _sysOrgService.GetUserDataScopeIdList();
                    var grantOrgIdList = input.GrantOrgIdList; //要授权的数据范围列表
                    if (grantOrgIdList.Count > 0)
                    {
                        if (dataScopes.Count < 1)
                            throw Oops.Oh(ErrorCode.D1016);
                        //else if (!dataScopes.All(u => grantOrgIdList.Any(c => c == u)))
                        //    throw Oops.Oh(ErrorCode.D1016);
                        else if (!grantOrgIdList.All(u => dataScopes.Any(c => c == u)))
                            throw Oops.Oh(ErrorCode.D1016);
                    }
                }
            }
            role.DataScopeType = (DataScopeType)dataScopeType;
            await _sysRoleDataScopeService.GrantDataScope(input);
        }
 
        /// <summary>
        /// 根据角色Id集合获取数据范围Id集合
        /// </summary>
        /// <param name="roleIdList"></param>
        /// <param name="orgId"></param>
        /// <returns></returns>
        [NonAction]
        public async Task<List<long>> GetUserDataScopeIdList(List<long> roleIdList, long orgId)
        {
            // 定义角色中最大数据范围的类型,目前按最大范围策略来,如果你同时拥有ALL和SELF的权限,最后按ALL返回
            int strongerDataScopeType = (int)DataScopeType.SELF;
 
            var customDataScopeRoleIdList = new List<long>();
            if (roleIdList != null && roleIdList.Count > 0)
            {
                var roles = await _sysRoleRep.DetachedEntities.Where(u => roleIdList.Contains(u.Id)).ToListAsync();
                roles.ForEach(u =>
                {
                    if (u.DataScopeType == DataScopeType.DEFINE)
                        customDataScopeRoleIdList.Add(u.Id);
                    else if ((int)u.DataScopeType <= strongerDataScopeType)
                        strongerDataScopeType = (int)u.DataScopeType;
                });
            }
 
            // 自定义数据范围的角色对应的数据范围
            var roleDataScopeIdList = await _sysRoleDataScopeService.GetRoleDataScopeIdList(customDataScopeRoleIdList);
 
            // 角色中拥有最大数据范围类型的数据范围
            var dataScopeIdList = await _sysOrgService.GetDataScopeListByDataScopeType(strongerDataScopeType, orgId);
 
            return roleDataScopeIdList.Concat(dataScopeIdList).Distinct().ToList(); //并集
        }
 
        /// <summary>
        /// 根据角色Id获取角色名称
        /// </summary>
        /// <param name="roleId"></param>
        /// <returns></returns>
        [NonAction]
        public async Task<string> GetNameByRoleId(long roleId)
        {
            var role = await _sysRoleRep.DetachedEntities.FirstOrDefaultAsync(u => u.Id == roleId);
            if (role == null)
                throw Oops.Oh(ErrorCode.D1002);
            return role.Name;
        }
 
        /// <summary>
        /// 获取角色拥有菜单Id集合
        /// </summary>
        /// <param name="input"></param>
        /// <returns></returns>
        [HttpGet("sysRole/ownMenu")]
        public async Task<List<long>> OwnMenu([FromQuery] QueryRoleInput input)
        {
            return await _sysRoleMenuService.GetRoleMenuIdList(new List<long> { input.Id });
        }
 
        /// <summary>
        /// 获取角色拥有数据Id集合
        /// </summary>
        /// <param name="input"></param>
        /// <returns></returns>
        [HttpGet("sysRole/ownData")]
        public async Task<List<long>> OwnData([FromQuery] QueryRoleInput input)
        {
            return await _sysRoleDataScopeService.GetRoleDataScopeIdList(new List<long> { input.Id });
        }
    }
}