VzRoleStore.cs 16 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466
  1. using Abp;
  2. using Abp.Dependency;
  3. using Abp.Domain.Repositories;
  4. using Abp.Domain.Uow;
  5. using Abp.Extensions;
  6. using Castle.Core.Logging;
  7. using Microsoft.AspNetCore.Identity;
  8. using System.Security.Claims;
  9. using VberZero.BaseSystem.Roles;
  10. using VberZero.Tools;
  11. using ILogger = Castle.Core.Logging.ILogger;
  12. namespace VberZero.Authorization.Roles;
  13. /// <summary>
  14. /// 为角色创建持久性存储的新实例
  15. /// </summary>
  16. public class VzRoleStore :
  17. IRoleStore<Role>,
  18. IRoleClaimStore<Role>,
  19. IRolePermissionStore<Role>,
  20. IQueryableRoleStore<Role>,
  21. ITransientDependency
  22. {
  23. public ILogger Logger { get; set; }
  24. /// <summary>
  25. /// 获取或设置当前操作发生的任何错误的 <see cref="IdentityErrorDescriber"/>
  26. /// </summary>
  27. public IdentityErrorDescriber ErrorDescriber { get; set; }
  28. /// <summary>
  29. /// 获取或设置一个标志,该标志指示在调用 CreateAsync、UpdateAsync 和 DeleteAsync 后是否应保存。
  30. /// </summary>
  31. /// <value>
  32. /// 如果应自动保存,则为 true,否则为 false。
  33. /// </value>
  34. public bool AutoSaveChanges { get; set; } = true;
  35. public IQueryable<Role> Roles => _roleRepository.GetAll();
  36. private readonly IRepository<Role> _roleRepository;
  37. private readonly IUnitOfWorkManager _unitOfWorkManager;
  38. private readonly IRepository<RolePermissionSetting, long> _rolePermissionSettingRepository;
  39. public VzRoleStore(
  40. IUnitOfWorkManager unitOfWorkManager,
  41. IRepository<Role> roleRepository,
  42. IRepository<RolePermissionSetting, long> rolePermissionSettingRepository)
  43. {
  44. _unitOfWorkManager = unitOfWorkManager;
  45. _roleRepository = roleRepository;
  46. _rolePermissionSettingRepository = rolePermissionSettingRepository;
  47. ErrorDescriber = new IdentityErrorDescriber();
  48. Logger = NullLogger.Instance;
  49. }
  50. /// <summary>
  51. /// 保存当前库
  52. /// </summary>
  53. /// <param name="cancellationToken"><see cref="CancellationToken"/> 取消操作的通知</param>
  54. /// <returns></returns>
  55. protected Task SaveChanges(CancellationToken cancellationToken)
  56. {
  57. if (!AutoSaveChanges || _unitOfWorkManager.Current == null)
  58. {
  59. return Task.CompletedTask;
  60. }
  61. return _unitOfWorkManager.Current.SaveChangesAsync();
  62. }
  63. /// <summary>
  64. /// 创建一个新角色
  65. /// </summary>
  66. /// <param name="role"></param>
  67. /// <param name="cancellationToken"><see cref="CancellationToken"/> 取消操作的通知</param>
  68. /// <returns></returns>
  69. public virtual async Task<IdentityResult> CreateAsync(Role role, CancellationToken cancellationToken = default)
  70. {
  71. return await _unitOfWorkManager.WithUnitOfWorkAsync(async () =>
  72. {
  73. cancellationToken.ThrowIfCancellationRequested();
  74. Check.NotNull(role, nameof(role));
  75. await _roleRepository.InsertAsync(role);
  76. await SaveChanges(cancellationToken);
  77. return IdentityResult.Success;
  78. });
  79. }
  80. /// <summary>
  81. /// 更新一个新角色
  82. /// </summary>
  83. /// <param name="role"></param>
  84. /// <param name="cancellationToken"><see cref="CancellationToken"/> 取消操作的通知</param>
  85. /// <returns></returns>
  86. public virtual async Task<IdentityResult> UpdateAsync(Role role, CancellationToken cancellationToken = default)
  87. {
  88. return await _unitOfWorkManager.WithUnitOfWorkAsync(async () =>
  89. {
  90. cancellationToken.ThrowIfCancellationRequested();
  91. Check.NotNull(role, nameof(role));
  92. role.ConcurrencyStamp = Guid.NewGuid().ToString();
  93. await _roleRepository.UpdateAsync(role);
  94. try
  95. {
  96. await SaveChanges(cancellationToken);
  97. }
  98. catch (AbpDbConcurrencyException ex)
  99. {
  100. Logger.Warn(ex.ToString(), ex);
  101. return IdentityResult.Failed(ErrorDescriber.ConcurrencyFailure());
  102. }
  103. await SaveChanges(cancellationToken);
  104. return IdentityResult.Success;
  105. });
  106. }
  107. /// <summary>
  108. /// 删除一个新角色
  109. /// </summary>
  110. /// <param name="role"></param>
  111. /// <param name="cancellationToken"><see cref="CancellationToken"/> 取消操作的通知</param>
  112. /// <returns></returns>
  113. public virtual async Task<IdentityResult> DeleteAsync(Role role, CancellationToken cancellationToken = default)
  114. {
  115. return await _unitOfWorkManager.WithUnitOfWorkAsync(async () =>
  116. {
  117. cancellationToken.ThrowIfCancellationRequested();
  118. Check.NotNull(role, nameof(role));
  119. await _roleRepository.DeleteAsync(role);
  120. try
  121. {
  122. await SaveChanges(cancellationToken);
  123. }
  124. catch (AbpDbConcurrencyException ex)
  125. {
  126. Logger.Warn(ex.ToString(), ex);
  127. return IdentityResult.Failed(ErrorDescriber.ConcurrencyFailure());
  128. }
  129. await SaveChanges(cancellationToken);
  130. return IdentityResult.Success;
  131. });
  132. }
  133. /// <summary>
  134. /// 获取角色的 ID
  135. /// </summary>
  136. /// <param name="role"></param>
  137. /// <param name="cancellationToken"><see cref="CancellationToken"/> 取消操作的通知</param>
  138. /// <returns></returns>
  139. public Task<string> GetRoleIdAsync(Role role, CancellationToken cancellationToken = default)
  140. {
  141. cancellationToken.ThrowIfCancellationRequested();
  142. Check.NotNull(role, nameof(role));
  143. return Task.FromResult(role.Id.ToString());
  144. }
  145. /// <summary>
  146. /// 获取角色的 Name
  147. /// </summary>
  148. /// <param name="role"></param>
  149. /// <param name="cancellationToken"><see cref="CancellationToken"/> 取消操作的通知</param>
  150. /// <returns></returns>
  151. public Task<string> GetRoleNameAsync(Role role, CancellationToken cancellationToken = default)
  152. {
  153. cancellationToken.ThrowIfCancellationRequested();
  154. Check.NotNull(role, nameof(role));
  155. return Task.FromResult(role.Name);
  156. }
  157. /// <summary>
  158. /// 设置角色名称
  159. /// </summary>
  160. /// <param name="role"></param>
  161. /// <param name="roleName"></param>
  162. /// <param name="cancellationToken"><see cref="CancellationToken"/> 取消操作的通知</param>
  163. /// <returns></returns>
  164. public Task SetRoleNameAsync(Role role, string roleName, CancellationToken cancellationToken = default)
  165. {
  166. cancellationToken.ThrowIfCancellationRequested();
  167. Check.NotNull(role, nameof(role));
  168. role.Name = roleName;
  169. return Task.CompletedTask;
  170. }
  171. /// <summary>
  172. /// 查询指定 ID 的角色
  173. /// </summary>
  174. /// <param name="id"></param>
  175. /// <param name="cancellationToken"><see cref="CancellationToken"/> 取消操作的通知</param>
  176. /// <returns></returns>
  177. public virtual async Task<Role> FindByIdAsync(string id, CancellationToken cancellationToken = default)
  178. {
  179. return await _unitOfWorkManager.WithUnitOfWorkAsync(async () =>
  180. {
  181. cancellationToken.ThrowIfCancellationRequested();
  182. return await _roleRepository.FirstOrDefaultAsync(id.To<int>());
  183. });
  184. }
  185. /// <summary>
  186. /// 查询指定 ID 的角色
  187. /// </summary>
  188. /// <param name="id"></param>
  189. /// <param name="cancellationToken"><see cref="CancellationToken"/> 取消操作的通知</param>
  190. /// <returns></returns>
  191. public virtual Role FindById(string id, CancellationToken cancellationToken = default)
  192. {
  193. return _unitOfWorkManager.WithUnitOfWork(() =>
  194. {
  195. cancellationToken.ThrowIfCancellationRequested();
  196. return _roleRepository.FirstOrDefault(id.To<int>());
  197. });
  198. }
  199. /// <summary>
  200. /// 查询指定 Name 的角色
  201. /// </summary>
  202. /// <param name="normalizedName"></param>
  203. /// <param name="cancellationToken"><see cref="CancellationToken"/> 取消操作的通知</param>
  204. /// <returns></returns>
  205. public virtual async Task<Role> FindByNameAsync(string normalizedName, CancellationToken cancellationToken = default)
  206. {
  207. return await _unitOfWorkManager.WithUnitOfWorkAsync(async () =>
  208. {
  209. cancellationToken.ThrowIfCancellationRequested();
  210. Check.NotNull(normalizedName, nameof(normalizedName));
  211. return await _roleRepository.FirstOrDefaultAsync(r => r.NormalizedName == normalizedName);
  212. });
  213. }
  214. /// <summary>
  215. /// 查询指定 Name 的角色
  216. /// </summary>
  217. /// <param name="normalizedName"></param>
  218. /// <param name="cancellationToken"><see cref="CancellationToken"/> 取消操作的通知</param>
  219. /// <returns></returns>
  220. public virtual Role FindByName(string normalizedName, CancellationToken cancellationToken = default)
  221. {
  222. return _unitOfWorkManager.WithUnitOfWork(() =>
  223. {
  224. cancellationToken.ThrowIfCancellationRequested();
  225. Check.NotNull(normalizedName, nameof(normalizedName));
  226. return _roleRepository.FirstOrDefault(r => r.NormalizedName == normalizedName);
  227. });
  228. }
  229. /// <summary>
  230. /// 获取角色的规范化名称
  231. /// </summary>
  232. /// <param name="role"></param>
  233. /// <param name="cancellationToken"><see cref="CancellationToken"/> 取消操作的通知</param>
  234. /// <returns></returns>
  235. public virtual Task<string> GetNormalizedRoleNameAsync(Role role, CancellationToken cancellationToken = default)
  236. {
  237. cancellationToken.ThrowIfCancellationRequested();
  238. Check.NotNull(role, nameof(role));
  239. return Task.FromResult(role.NormalizedName);
  240. }
  241. /// <summary>
  242. /// 设置角色的规范化名称
  243. /// </summary>
  244. /// <param name="role"></param>
  245. /// <param name="normalizedName">The normalized name to set</param>
  246. /// <param name="cancellationToken"><see cref="CancellationToken"/> 取消操作的通知</param>
  247. /// <returns></returns>
  248. public virtual Task SetNormalizedRoleNameAsync(Role role, string normalizedName, CancellationToken cancellationToken = default)
  249. {
  250. cancellationToken.ThrowIfCancellationRequested();
  251. Check.NotNull(role, nameof(role));
  252. role.NormalizedName = normalizedName;
  253. return Task.CompletedTask;
  254. }
  255. /// <summary>
  256. /// Dispose
  257. /// </summary>
  258. public void Dispose()
  259. {
  260. }
  261. /// <summary>
  262. /// 获取与指定的 <paramref name="role"/> 关联的声明
  263. /// </summary>
  264. /// <param name="role"></param>
  265. /// <param name="cancellationToken"><see cref="CancellationToken"/> 取消操作的通知</param>
  266. /// <returns></returns>
  267. public virtual async Task<IList<Claim>> GetClaimsAsync(Role role, CancellationToken cancellationToken = default)
  268. {
  269. return await _unitOfWorkManager.WithUnitOfWorkAsync(async () =>
  270. {
  271. cancellationToken.ThrowIfCancellationRequested();
  272. Check.NotNull(role, nameof(role));
  273. await _roleRepository.EnsureCollectionLoadedAsync(role, u => u.Claims, cancellationToken);
  274. return role.Claims.Select(c => new Claim(c.ClaimType, c.ClaimValue)).ToList();
  275. });
  276. }
  277. /// <summary>
  278. /// 将给定的 <paramref name="claim"/> 添加到指定的 <paramref name="role"/>
  279. /// </summary>
  280. /// <param name="role"></param>
  281. /// <param name="claim"></param>
  282. /// <param name="cancellationToken"><see cref="CancellationToken"/> 取消操作的通知</param>
  283. /// <returns></returns>
  284. public async Task AddClaimAsync(Role role, Claim claim, CancellationToken cancellationToken = default)
  285. {
  286. await _unitOfWorkManager.WithUnitOfWorkAsync(async () =>
  287. {
  288. cancellationToken.ThrowIfCancellationRequested();
  289. Check.NotNull(role, nameof(role));
  290. Check.NotNull(claim, nameof(claim));
  291. await _roleRepository.EnsureCollectionLoadedAsync(role, u => u.Claims, cancellationToken);
  292. role.Claims.Add(new RoleClaim(role, claim));
  293. });
  294. }
  295. /// <summary>
  296. /// 从指定的 <paramref name="role"/> 中移除给定的 <paramref name="claim"/>
  297. /// </summary>
  298. /// <param name="role"></param>
  299. /// <param name="claim"></param>
  300. /// <param name="cancellationToken"><see cref="CancellationToken"/> 取消操作的通知</param>
  301. /// <returns></returns>
  302. public async Task RemoveClaimAsync(Role role, Claim claim, CancellationToken cancellationToken = default)
  303. {
  304. await _unitOfWorkManager.WithUnitOfWorkAsync(async () =>
  305. {
  306. Check.NotNull(role, nameof(role));
  307. Check.NotNull(claim, nameof(claim));
  308. await _roleRepository.EnsureCollectionLoadedAsync(role, u => u.Claims, cancellationToken);
  309. role.Claims.RemoveAll(c => c.ClaimValue == claim.Value && c.ClaimType == claim.Type);
  310. });
  311. }
  312. public virtual async Task<Role> FindByDisplayNameAsync(string displayName)
  313. {
  314. return await _unitOfWorkManager.WithUnitOfWorkAsync(async () =>
  315. {
  316. return await _roleRepository.FirstOrDefaultAsync(
  317. role => role.DisplayName == displayName
  318. );
  319. });
  320. }
  321. public virtual async Task AddPermissionAsync(Role role, PermissionGrantInfo permissionGrant)
  322. {
  323. await _unitOfWorkManager.WithUnitOfWorkAsync(async () =>
  324. {
  325. if (await HasPermissionAsync(role.Id, permissionGrant))
  326. {
  327. return;
  328. }
  329. await _rolePermissionSettingRepository.InsertAsync(
  330. new RolePermissionSetting(role.Id)
  331. {
  332. TenantId = role.TenantId,
  333. //RoleId = role.Id,
  334. Name = permissionGrant.Name,
  335. IsGranted = permissionGrant.IsGranted
  336. });
  337. });
  338. }
  339. /// <inheritdoc/>
  340. public virtual async Task RemovePermissionAsync(Role role, PermissionGrantInfo permissionGrant)
  341. {
  342. await _unitOfWorkManager.WithUnitOfWorkAsync(async () =>
  343. {
  344. await _rolePermissionSettingRepository.DeleteAsync(
  345. permissionSetting => permissionSetting.RoleId == role.Id &&
  346. permissionSetting.Name == permissionGrant.Name &&
  347. permissionSetting.IsGranted == permissionGrant.IsGranted
  348. );
  349. });
  350. }
  351. /// <inheritdoc/>
  352. public virtual Task<IList<PermissionGrantInfo>> GetPermissionsAsync(Role role)
  353. {
  354. return GetPermissionsAsync(role.Id);
  355. }
  356. /// <inheritdoc/>
  357. public virtual IList<PermissionGrantInfo> GetPermissions(Role role)
  358. {
  359. return GetPermissions(role.Id);
  360. }
  361. public async Task<IList<PermissionGrantInfo>> GetPermissionsAsync(int roleId)
  362. {
  363. return await _unitOfWorkManager.WithUnitOfWorkAsync(async () =>
  364. {
  365. return (await _rolePermissionSettingRepository.GetAllListAsync(p => p.RoleId == roleId))
  366. .Select(p => new PermissionGrantInfo(p.Name, p.IsGranted))
  367. .ToList();
  368. });
  369. }
  370. public IList<PermissionGrantInfo> GetPermissions(int roleId)
  371. {
  372. return _unitOfWorkManager.WithUnitOfWork(() =>
  373. {
  374. return (_rolePermissionSettingRepository.GetAllList(p => p.RoleId == roleId))
  375. .Select(p => new PermissionGrantInfo(p.Name, p.IsGranted))
  376. .ToList();
  377. });
  378. }
  379. /// <inheritdoc/>
  380. public virtual async Task<bool> HasPermissionAsync(int roleId, PermissionGrantInfo permissionGrant)
  381. {
  382. return await _unitOfWorkManager.WithUnitOfWorkAsync(async () =>
  383. {
  384. return await _rolePermissionSettingRepository.FirstOrDefaultAsync(
  385. p => p.RoleId == roleId &&
  386. p.Name == permissionGrant.Name &&
  387. p.IsGranted == permissionGrant.IsGranted
  388. ) != null;
  389. });
  390. }
  391. /// <inheritdoc/>
  392. public virtual async Task RemoveAllPermissionSettingsAsync(Role role)
  393. {
  394. await _unitOfWorkManager.WithUnitOfWorkAsync(async () =>
  395. {
  396. await _rolePermissionSettingRepository.DeleteAsync(s => s.RoleId == role.Id);
  397. });
  398. }
  399. }