SettingManager.cs 18 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473
  1. using System.Collections.Generic;
  2. using System.Collections.Immutable;
  3. using System.Linq;
  4. using System.Threading.Tasks;
  5. using Abp;
  6. using Abp.Collections.Extensions;
  7. using Abp.Configuration;
  8. using Abp.Dependency;
  9. using Abp.Domain.Uow;
  10. using Abp.Runtime.Caching;
  11. using Abp.Runtime.Session;
  12. namespace IwbZero.Setting
  13. {
  14. /// <summary>
  15. /// This class implements <see cref="IIwbSettingManager"/> to manage setting values in the database.
  16. /// </summary>
  17. public class IwbSettingManager : IIwbSettingManager, ISingletonDependency
  18. {
  19. public const string ApplicationSettingsCacheKey = "ApplicationSettings";
  20. /// <summary>
  21. /// Reference to the current Session.
  22. /// </summary>
  23. public IAbpSession AbpSession { get; set; }
  24. /// <summary>
  25. /// Reference to the setting store.
  26. /// </summary>
  27. public ISettingStore SettingStore { get; set; }
  28. private readonly IIwbSettingDefinitionManager _settingDefinitionManager;
  29. private readonly ITypedCache<string, Dictionary<string, SettingInfo>> _applicationSettingCache;
  30. private readonly ITypedCache<int, Dictionary<string, SettingInfo>> _tenantSettingCache;
  31. private readonly ITypedCache<string, Dictionary<string, SettingInfo>> _userSettingCache;
  32. /// <inheritdoc/>
  33. public IwbSettingManager(IIwbSettingDefinitionManager settingDefinitionManager, ICacheManager cacheManager)
  34. {
  35. _settingDefinitionManager = settingDefinitionManager;
  36. AbpSession = NullAbpSession.Instance;
  37. SettingStore = IwbSettingStore.Instance;
  38. _applicationSettingCache = cacheManager.GetApplicationSettingsCache();
  39. _tenantSettingCache = cacheManager.GetTenantSettingsCache();
  40. _userSettingCache = cacheManager.GetUserSettingsCache();
  41. }
  42. #region Public methods
  43. public async Task RefreshAsync()
  44. {
  45. _settingDefinitionManager.Referesh();
  46. await _applicationSettingCache.RemoveAsync(ApplicationSettingsCacheKey);
  47. }
  48. public Task RefreshForUserAsync(long userId)
  49. {
  50. return RefreshForUserAsync(new UserIdentifier(null, userId));
  51. }
  52. public async Task RefreshForUserAsync(UserIdentifier user)
  53. {
  54. _settingDefinitionManager.Referesh();
  55. await _userSettingCache.RemoveAsync(user.ToUserIdentifierString());
  56. }
  57. /// <inheritdoc/>
  58. public Task<string> GetSettingValueAsync(string name)
  59. {
  60. return GetSettingValueInternalAsync(name, AbpSession.UserId);
  61. }
  62. public Task<string> GetSettingValueForApplicationAsync(string name)
  63. {
  64. return GetSettingValueInternalAsync(name);
  65. }
  66. public Task<string> GetSettingValueForApplicationAsync(string name, bool fallbackToDefault)
  67. {
  68. return GetSettingValueInternalAsync(name, fallbackToDefault: fallbackToDefault);
  69. }
  70. public Task<string> GetSettingValueForUserAsync(string name, long userId)
  71. {
  72. return GetSettingValueInternalAsync(name, userId);
  73. }
  74. public Task<string> GetSettingValueForUserAsync(string name, long userId, bool fallbackToDefault)
  75. {
  76. return GetSettingValueInternalAsync(name, userId, fallbackToDefault);
  77. }
  78. public async Task<IReadOnlyList<ISettingValue>> GetAllSettingValuesAsync()
  79. {
  80. return await GetAllSettingValuesAsync(SettingScopes.Application | SettingScopes.Tenant | SettingScopes.User);
  81. }
  82. /// <inheritdoc/>
  83. public async Task<IReadOnlyList<ISettingValue>> GetAllSettingValuesAsync(SettingScopes scopes)
  84. {
  85. var settingDefinitions = new Dictionary<string, SettingDefinition>();
  86. var settingValues = new Dictionary<string, ISettingValue>();
  87. //Fill all setting with default values.
  88. foreach (var setting in _settingDefinitionManager.GetAllSettingDefinitions())
  89. {
  90. settingDefinitions[setting.Name] = setting;
  91. settingValues[setting.Name] = new SettingValueObject(setting.Name, setting.DefaultValue);
  92. }
  93. //Overwrite application settings
  94. if (scopes.HasFlag(SettingScopes.Application))
  95. {
  96. foreach (var settingValue in await GetAllSettingValuesForApplicationAsync())
  97. {
  98. var setting = settingDefinitions.GetOrDefault(settingValue.Name);
  99. //TODO: Conditions get complicated, try to simplify it
  100. if (setting == null || !setting.Scopes.HasFlag(SettingScopes.Application))
  101. {
  102. continue;
  103. }
  104. if (!setting.IsInherited &&
  105. ((setting.Scopes.HasFlag(SettingScopes.Tenant) && AbpSession.TenantId.HasValue) || (setting.Scopes.HasFlag(SettingScopes.User) && AbpSession.UserId.HasValue)))
  106. {
  107. continue;
  108. }
  109. settingValues[settingValue.Name] = new SettingValueObject(settingValue.Name, settingValue.Value);
  110. }
  111. }
  112. //Overwrite tenant settings
  113. if (scopes.HasFlag(SettingScopes.Tenant) && AbpSession.TenantId.HasValue)
  114. {
  115. foreach (var settingValue in await GetAllSettingValuesForTenantAsync(AbpSession.TenantId.Value))
  116. {
  117. var setting = settingDefinitions.GetOrDefault(settingValue.Name);
  118. //TODO: Conditions get complicated, try to simplify it
  119. if (setting == null || !setting.Scopes.HasFlag(SettingScopes.Tenant))
  120. {
  121. continue;
  122. }
  123. if (!setting.IsInherited &&
  124. (setting.Scopes.HasFlag(SettingScopes.User) && AbpSession.UserId.HasValue))
  125. {
  126. continue;
  127. }
  128. settingValues[settingValue.Name] = new SettingValueObject(settingValue.Name, settingValue.Value);
  129. }
  130. }
  131. //Overwrite user settings
  132. if (scopes.HasFlag(SettingScopes.User) && AbpSession.UserId.HasValue)
  133. {
  134. foreach (var settingValue in await GetAllSettingValuesForUserAsync(AbpSession.ToUserIdentifier()))
  135. {
  136. var setting = settingDefinitions.GetOrDefault(settingValue.Name);
  137. if (setting != null && setting.Scopes.HasFlag(SettingScopes.User))
  138. {
  139. settingValues[settingValue.Name] = new SettingValueObject(settingValue.Name, settingValue.Value);
  140. }
  141. }
  142. }
  143. return settingValues.Values.ToImmutableList();
  144. }
  145. /// <inheritdoc/>
  146. public async Task<IReadOnlyList<ISettingValue>> GetAllSettingValuesForApplicationAsync()
  147. {
  148. return (await GetApplicationSettingsAsync()).Values
  149. .Select(setting => new SettingValueObject(setting.Name, setting.Value))
  150. .ToImmutableList();
  151. }
  152. /// <inheritdoc/>
  153. public async Task<IReadOnlyList<ISettingValue>> GetAllSettingValuesForTenantAsync(int tenantId)
  154. {
  155. return (await GetReadOnlyTenantSettings(tenantId)).Values
  156. .Select(setting => new SettingValueObject(setting.Name, setting.Value))
  157. .ToImmutableList();
  158. }
  159. public Task<IReadOnlyList<ISettingValue>> GetAllSettingValuesForUserAsync(long userId)
  160. {
  161. return GetAllSettingValuesForUserAsync(new UserIdentifier(AbpSession.TenantId, userId));
  162. }
  163. public async Task<IReadOnlyList<ISettingValue>> GetAllSettingValuesForUserAsync(UserIdentifier user)
  164. {
  165. return (await GetReadOnlyUserSettings(user)).Values
  166. .Select(setting => new SettingValueObject(setting.Name, setting.Value))
  167. .ToImmutableList();
  168. }
  169. /// <inheritdoc/>
  170. [UnitOfWork]
  171. public virtual async Task ChangeSettingForApplicationAsync(string name, string value)
  172. {
  173. //await InsertOrUpdateOrDeleteSettingValueAsync(name, value, null);
  174. _settingDefinitionManager.ChangeSettingDefinition(name, value);
  175. await _applicationSettingCache.RemoveAsync(ApplicationSettingsCacheKey);
  176. }
  177. /// <inheritdoc/>
  178. [UnitOfWork]
  179. public virtual async Task ChangeSettingForTenantAsync(int tenantId, string name, string value)
  180. {
  181. //await InsertOrUpdateOrDeleteSettingValueAsync(name, value, null);
  182. _settingDefinitionManager.ChangeSettingDefinition(name, value);
  183. await _tenantSettingCache.RemoveAsync(tenantId);
  184. }
  185. [UnitOfWork]
  186. public virtual Task ChangeSettingForUserAsync(long userId, string name, string value)
  187. {
  188. return ChangeSettingForUserAsync(new UserIdentifier(null, userId), name, value);
  189. }
  190. public async Task ChangeSettingForUserAsync(UserIdentifier user, string name, string value)
  191. {
  192. //await InsertOrUpdateOrDeleteSettingValueAsync(name, value, user.UserId);
  193. _settingDefinitionManager.ChangeSettingDefinition(name, value);
  194. await _userSettingCache.RemoveAsync(user.ToUserIdentifierString());
  195. }
  196. #endregion
  197. #region Private methods
  198. private async Task<string> GetSettingValueInternalAsync(string name, long? userId = null, bool fallbackToDefault = true)
  199. {
  200. var settingDefinition = _settingDefinitionManager.GetSettingDefinition(name);
  201. //Get for user if defined
  202. if (settingDefinition.Scopes.HasFlag(SettingScopes.User) && userId.HasValue)
  203. {
  204. var settingValue = await GetSettingValueForUserOrNullAsync(new UserIdentifier(null, userId.Value), name);
  205. if (settingValue != null)
  206. {
  207. return settingValue.Value;
  208. }
  209. if (!fallbackToDefault)
  210. {
  211. return null;
  212. }
  213. if (!settingDefinition.IsInherited)
  214. {
  215. return settingDefinition.DefaultValue;
  216. }
  217. }
  218. ////Get for tenant if defined
  219. //if (settingDefinition.Scopes.HasFlag(SettingScopes.Tenant) && tenantId.HasValue)
  220. //{
  221. // var settingValue = await GetSettingValueForTenantOrNullAsync(tenantId.Value, name);
  222. // if (settingValue != null)
  223. // {
  224. // return settingValue.Value;
  225. // }
  226. // if (!fallbackToDefault)
  227. // {
  228. // return null;
  229. // }
  230. // if (!settingDefinition.IsInherited)
  231. // {
  232. // return settingDefinition.DefaultValue;
  233. // }
  234. //}
  235. //Get for application if defined
  236. if (settingDefinition.Scopes.HasFlag(SettingScopes.Application))
  237. {
  238. var settingValue = await GetSettingValueForApplicationOrNullAsync(name);
  239. if (settingValue != null)
  240. {
  241. return settingValue.Value;
  242. }
  243. if (!fallbackToDefault)
  244. {
  245. return null;
  246. }
  247. }
  248. //Not defined, get default value
  249. return settingDefinition.DefaultValue;
  250. }
  251. private async Task<SettingInfo> InsertOrUpdateOrDeleteSettingValueAsync(string name, string value, long? userId)
  252. {
  253. var settingDefinition = _settingDefinitionManager.GetSettingDefinition(name);
  254. var settingValue = await SettingStore.GetSettingOrNullAsync(null, userId, name);
  255. //Determine defaultValue;
  256. var defaultValue = settingDefinition.DefaultValue;
  257. if (settingDefinition.IsInherited)
  258. {
  259. //For Tenant and User, Application's value overrides Setting Definition's default value.
  260. if (userId.HasValue)
  261. {
  262. var applicationValue = await GetSettingValueForApplicationOrNullAsync(name);
  263. if (applicationValue != null)
  264. {
  265. defaultValue = applicationValue.Value;
  266. }
  267. }
  268. //For User, Tenants's value overrides Application's default value.
  269. //if (userId.HasValue )
  270. //{
  271. // var tenantValue = await GetSettingValueForTenantOrNullAsync( name);
  272. // if (tenantValue != null)
  273. // {
  274. // defaultValue = tenantValue.Value;
  275. // }
  276. //}
  277. }
  278. //No need to store on database if the value is the default value
  279. if (value == defaultValue)
  280. {
  281. if (settingValue != null)
  282. {
  283. await SettingStore.DeleteAsync(settingValue);
  284. }
  285. return null;
  286. }
  287. //If it's not default value and not stored on database, then insert it
  288. if (settingValue == null)
  289. {
  290. settingValue = new SettingInfo
  291. {
  292. //TenantId = tenantId,
  293. UserId = userId,
  294. Name = name,
  295. Value = value
  296. };
  297. await SettingStore.CreateAsync(settingValue);
  298. return settingValue;
  299. }
  300. //It's same value in database, no need to update
  301. if (settingValue.Value == value)
  302. {
  303. return settingValue;
  304. }
  305. //Update the setting on database.
  306. settingValue.Value = value;
  307. await SettingStore.UpdateAsync(settingValue);
  308. return settingValue;
  309. }
  310. private async Task<SettingInfo> GetSettingValueForApplicationOrNullAsync(string name)
  311. {
  312. return (await GetApplicationSettingsAsync()).GetOrDefault(name);
  313. }
  314. private async Task<SettingInfo> GetSettingValueForUserOrNullAsync(UserIdentifier user, string name)
  315. {
  316. return (await GetReadOnlyUserSettings(user)).GetOrDefault(name);
  317. }
  318. private async Task<Dictionary<string, SettingInfo>> GetApplicationSettingsAsync()
  319. {
  320. return await _applicationSettingCache.GetAsync(ApplicationSettingsCacheKey, async () =>
  321. {
  322. var dictionary = new Dictionary<string, SettingInfo>();
  323. var settingValues = await SettingStore.GetAllListAsync(null, null);
  324. foreach (var settingValue in settingValues)
  325. {
  326. dictionary[settingValue.Name] = settingValue;
  327. }
  328. return dictionary;
  329. });
  330. }
  331. private async Task<ImmutableDictionary<string, SettingInfo>> GetReadOnlyTenantSettings(int tenantId)
  332. {
  333. var cachedDictionary = await GetTenantSettingsFromCache(tenantId);
  334. lock (cachedDictionary)
  335. {
  336. return cachedDictionary.ToImmutableDictionary();
  337. }
  338. }
  339. private async Task<ImmutableDictionary<string, SettingInfo>> GetReadOnlyUserSettings(UserIdentifier user)
  340. {
  341. var cachedDictionary = await GetUserSettingsFromCache(user);
  342. lock (cachedDictionary)
  343. {
  344. return cachedDictionary.ToImmutableDictionary();
  345. }
  346. }
  347. private async Task<Dictionary<string, SettingInfo>> GetTenantSettingsFromCache(int tenantId)
  348. {
  349. return await _tenantSettingCache.GetAsync(
  350. tenantId,
  351. async () =>
  352. {
  353. var dictionary = new Dictionary<string, SettingInfo>();
  354. var settingValues = await SettingStore.GetAllListAsync(tenantId, null);
  355. foreach (var settingValue in settingValues)
  356. {
  357. dictionary[settingValue.Name] = settingValue;
  358. }
  359. return dictionary;
  360. });
  361. }
  362. private async Task<Dictionary<string, SettingInfo>> GetUserSettingsFromCache(UserIdentifier user)
  363. {
  364. return await _userSettingCache.GetAsync(
  365. user.ToUserIdentifierString(),
  366. async () =>
  367. {
  368. var dictionary = new Dictionary<string, SettingInfo>();
  369. var settingValues = await SettingStore.GetAllListAsync(user.TenantId, user.UserId);
  370. foreach (var settingValue in settingValues)
  371. {
  372. dictionary[settingValue.Name] = settingValue;
  373. }
  374. return dictionary;
  375. });
  376. }
  377. public Task<string> GetSettingValueForUserAsync(string name, UserIdentifier user)
  378. {
  379. Check.NotNull(name, nameof(name));
  380. Check.NotNull(user, nameof(user));
  381. return GetSettingValueForUserAsync(name, user.UserId);
  382. }
  383. #endregion
  384. #region Nested classes
  385. private class SettingValueObject : ISettingValue
  386. {
  387. public string Name { get; private set; }
  388. public string Value { get; private set; }
  389. public SettingValueObject(string name, string value)
  390. {
  391. Value = value;
  392. Name = name;
  393. }
  394. }
  395. #endregion
  396. }
  397. }