| 123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473 |
- using System.Collections.Generic;
- using System.Collections.Immutable;
- using System.Linq;
- using System.Threading.Tasks;
- using Abp.Collections.Extensions;
- using Abp.Dependency;
- using Abp.Domain.Uow;
- using Abp.Runtime.Caching;
- using Abp.Runtime.Session;
- namespace Abp.Configuration
- {
- /// <summary>
- /// This class implements <see cref="ISettingManager"/> to manage setting values in the database.
- /// </summary>
- public class SettingManager : ISettingManager, ISingletonDependency
- {
- public const string ApplicationSettingsCacheKey = "ApplicationSettings";
- /// <summary>
- /// Reference to the current Session.
- /// </summary>
- public IAbpSession AbpSession { get; set; }
- /// <summary>
- /// Reference to the setting store.
- /// </summary>
- public ISettingStore SettingStore { get; set; }
- private readonly ISettingDefinitionManager _settingDefinitionManager;
- private readonly ITypedCache<string, Dictionary<string, SettingInfo>> _applicationSettingCache;
- private readonly ITypedCache<int, Dictionary<string, SettingInfo>> _tenantSettingCache;
- private readonly ITypedCache<string, Dictionary<string, SettingInfo>> _userSettingCache;
- /// <inheritdoc/>
- public SettingManager(ISettingDefinitionManager settingDefinitionManager, ICacheManager cacheManager)
- {
- _settingDefinitionManager = settingDefinitionManager;
- AbpSession = NullAbpSession.Instance;
- SettingStore = DefaultConfigSettingStore.Instance;
- _applicationSettingCache = cacheManager.GetApplicationSettingsCache();
- _tenantSettingCache = cacheManager.GetTenantSettingsCache();
- _userSettingCache = cacheManager.GetUserSettingsCache();
- }
- #region Public methods
- /// <inheritdoc/>
- public Task<string> GetSettingValueAsync(string name)
- {
- return GetSettingValueInternalAsync(name, AbpSession.TenantId, AbpSession.UserId);
- }
- public Task<string> GetSettingValueForApplicationAsync(string name)
- {
- return GetSettingValueInternalAsync(name);
- }
- public Task<string> GetSettingValueForApplicationAsync(string name, bool fallbackToDefault)
- {
- return GetSettingValueInternalAsync(name, fallbackToDefault: fallbackToDefault);
- }
- public Task<string> GetSettingValueForTenantAsync(string name, int tenantId)
- {
- return GetSettingValueInternalAsync(name, tenantId);
- }
- public Task<string> GetSettingValueForTenantAsync(string name, int tenantId, bool fallbackToDefault)
- {
- return GetSettingValueInternalAsync(name, tenantId, fallbackToDefault: fallbackToDefault);
- }
- public Task<string> GetSettingValueForUserAsync(string name, int? tenantId, long userId)
- {
- return GetSettingValueInternalAsync(name, tenantId, userId);
- }
- public Task<string> GetSettingValueForUserAsync(string name, int? tenantId, long userId, bool fallbackToDefault)
- {
- return GetSettingValueInternalAsync(name, tenantId, userId, fallbackToDefault);
- }
- public async Task<IReadOnlyList<ISettingValue>> GetAllSettingValuesAsync()
- {
- return await GetAllSettingValuesAsync(SettingScopes.Application | SettingScopes.Tenant | SettingScopes.User);
- }
- /// <inheritdoc/>
- public async Task<IReadOnlyList<ISettingValue>> GetAllSettingValuesAsync(SettingScopes scopes)
- {
- var settingDefinitions = new Dictionary<string, SettingDefinition>();
- var settingValues = new Dictionary<string, ISettingValue>();
- //Fill all setting with default values.
- foreach (var setting in _settingDefinitionManager.GetAllSettingDefinitions())
- {
- settingDefinitions[setting.Name] = setting;
- settingValues[setting.Name] = new SettingValueObject(setting.Name, setting.DefaultValue);
- }
- //Overwrite application settings
- if (scopes.HasFlag(SettingScopes.Application))
- {
- foreach (var settingValue in await GetAllSettingValuesForApplicationAsync())
- {
- var setting = settingDefinitions.GetOrDefault(settingValue.Name);
- //TODO: Conditions get complicated, try to simplify it
- if (setting == null || !setting.Scopes.HasFlag(SettingScopes.Application))
- {
- continue;
- }
- if (!setting.IsInherited &&
- ((setting.Scopes.HasFlag(SettingScopes.Tenant) && AbpSession.TenantId.HasValue) || (setting.Scopes.HasFlag(SettingScopes.User) && AbpSession.UserId.HasValue)))
- {
- continue;
- }
- settingValues[settingValue.Name] = new SettingValueObject(settingValue.Name, settingValue.Value);
- }
- }
- //Overwrite tenant settings
- if (scopes.HasFlag(SettingScopes.Tenant) && AbpSession.TenantId.HasValue)
- {
- foreach (var settingValue in await GetAllSettingValuesForTenantAsync(AbpSession.TenantId.Value))
- {
- var setting = settingDefinitions.GetOrDefault(settingValue.Name);
- //TODO: Conditions get complicated, try to simplify it
- if (setting == null || !setting.Scopes.HasFlag(SettingScopes.Tenant))
- {
- continue;
- }
- if (!setting.IsInherited &&
- (setting.Scopes.HasFlag(SettingScopes.User) && AbpSession.UserId.HasValue))
- {
- continue;
- }
- settingValues[settingValue.Name] = new SettingValueObject(settingValue.Name, settingValue.Value);
- }
- }
- //Overwrite user settings
- if (scopes.HasFlag(SettingScopes.User) && AbpSession.UserId.HasValue)
- {
- foreach (var settingValue in await GetAllSettingValuesForUserAsync(AbpSession.ToUserIdentifier()))
- {
- var setting = settingDefinitions.GetOrDefault(settingValue.Name);
- if (setting != null && setting.Scopes.HasFlag(SettingScopes.User))
- {
- settingValues[settingValue.Name] = new SettingValueObject(settingValue.Name, settingValue.Value);
- }
- }
- }
- return settingValues.Values.ToImmutableList();
- }
- /// <inheritdoc/>
- public async Task<IReadOnlyList<ISettingValue>> GetAllSettingValuesForApplicationAsync()
- {
- return (await GetApplicationSettingsAsync()).Values
- .Select(setting => new SettingValueObject(setting.Name, setting.Value))
- .ToImmutableList();
- }
- /// <inheritdoc/>
- public async Task<IReadOnlyList<ISettingValue>> GetAllSettingValuesForTenantAsync(int tenantId)
- {
- return (await GetReadOnlyTenantSettings(tenantId)).Values
- .Select(setting => new SettingValueObject(setting.Name, setting.Value))
- .ToImmutableList();
- }
- /// <inheritdoc/>
- public Task<IReadOnlyList<ISettingValue>> GetAllSettingValuesForUserAsync(long userId)
- {
- return GetAllSettingValuesForUserAsync(new UserIdentifier(AbpSession.TenantId, userId));
- }
- public async Task<IReadOnlyList<ISettingValue>> GetAllSettingValuesForUserAsync(UserIdentifier user)
- {
- return (await GetReadOnlyUserSettings(user)).Values
- .Select(setting => new SettingValueObject(setting.Name, setting.Value))
- .ToImmutableList();
- }
- /// <inheritdoc/>
- [UnitOfWork]
- public virtual async Task ChangeSettingForApplicationAsync(string name, string value)
- {
- await InsertOrUpdateOrDeleteSettingValueAsync(name, value, null, null);
- await _applicationSettingCache.RemoveAsync(ApplicationSettingsCacheKey);
- }
- /// <inheritdoc/>
- [UnitOfWork]
- public virtual async Task ChangeSettingForTenantAsync(int tenantId, string name, string value)
- {
- await InsertOrUpdateOrDeleteSettingValueAsync(name, value, tenantId, null);
- await _tenantSettingCache.RemoveAsync(tenantId);
- }
- /// <inheritdoc/>
- [UnitOfWork]
- public virtual Task ChangeSettingForUserAsync(long userId, string name, string value)
- {
- return ChangeSettingForUserAsync(new UserIdentifier(AbpSession.TenantId, userId), name, value);
- }
- public async Task ChangeSettingForUserAsync(UserIdentifier user, string name, string value)
- {
- await InsertOrUpdateOrDeleteSettingValueAsync(name, value, user.TenantId, user.UserId);
- await _userSettingCache.RemoveAsync(user.ToUserIdentifierString());
- }
- #endregion
- #region Private methods
- private async Task<string> GetSettingValueInternalAsync(string name, int? tenantId = null, long? userId = null, bool fallbackToDefault = true)
- {
- var settingDefinition = _settingDefinitionManager.GetSettingDefinition(name);
- //Get for user if defined
- if (settingDefinition.Scopes.HasFlag(SettingScopes.User) && userId.HasValue)
- {
- var settingValue = await GetSettingValueForUserOrNullAsync(new UserIdentifier(tenantId, userId.Value), name);
- if (settingValue != null)
- {
- return settingValue.Value;
- }
- if (!fallbackToDefault)
- {
- return null;
- }
- if (!settingDefinition.IsInherited)
- {
- return settingDefinition.DefaultValue;
- }
- }
- //Get for tenant if defined
- if (settingDefinition.Scopes.HasFlag(SettingScopes.Tenant) && tenantId.HasValue)
- {
- var settingValue = await GetSettingValueForTenantOrNullAsync(tenantId.Value, name);
- if (settingValue != null)
- {
- return settingValue.Value;
- }
- if (!fallbackToDefault)
- {
- return null;
- }
- if (!settingDefinition.IsInherited)
- {
- return settingDefinition.DefaultValue;
- }
- }
- //Get for application if defined
- if (settingDefinition.Scopes.HasFlag(SettingScopes.Application))
- {
- var settingValue = await GetSettingValueForApplicationOrNullAsync(name);
- if (settingValue != null)
- {
- return settingValue.Value;
- }
- if (!fallbackToDefault)
- {
- return null;
- }
- }
- //Not defined, get default value
- return settingDefinition.DefaultValue;
- }
- private async Task<SettingInfo> InsertOrUpdateOrDeleteSettingValueAsync(string name, string value, int? tenantId, long? userId)
- {
- var settingDefinition = _settingDefinitionManager.GetSettingDefinition(name);
- var settingValue = await SettingStore.GetSettingOrNullAsync(tenantId, userId, name);
- //Determine defaultValue
- var defaultValue = settingDefinition.DefaultValue;
- if (settingDefinition.IsInherited)
- {
- //For Tenant and User, Application's value overrides Setting Definition's default value.
- if (tenantId.HasValue || userId.HasValue)
- {
- var applicationValue = await GetSettingValueForApplicationOrNullAsync(name);
- if (applicationValue != null)
- {
- defaultValue = applicationValue.Value;
- }
- }
- //For User, Tenants's value overrides Application's default value.
- if (userId.HasValue && tenantId.HasValue)
- {
- var tenantValue = await GetSettingValueForTenantOrNullAsync(tenantId.Value, name);
- if (tenantValue != null)
- {
- defaultValue = tenantValue.Value;
- }
- }
- }
- //No need to store on database if the value is the default value
- if (value == defaultValue)
- {
- if (settingValue != null)
- {
- await SettingStore.DeleteAsync(settingValue);
- }
- return null;
- }
- //If it's not default value and not stored on database, then insert it
- if (settingValue == null)
- {
- settingValue = new SettingInfo
- {
- TenantId = tenantId,
- UserId = userId,
- Name = name,
- Value = value
- };
- await SettingStore.CreateAsync(settingValue);
- return settingValue;
- }
- //It's same value in database, no need to update
- if (settingValue.Value == value)
- {
- return settingValue;
- }
- //Update the setting on database.
- settingValue.Value = value;
- await SettingStore.UpdateAsync(settingValue);
- return settingValue;
- }
- private async Task<SettingInfo> GetSettingValueForApplicationOrNullAsync(string name)
- {
- return (await GetApplicationSettingsAsync()).GetOrDefault(name);
- }
- private async Task<SettingInfo> GetSettingValueForTenantOrNullAsync(int tenantId, string name)
- {
- return (await GetReadOnlyTenantSettings(tenantId)).GetOrDefault(name);
- }
- private async Task<SettingInfo> GetSettingValueForUserOrNullAsync(UserIdentifier user, string name)
- {
- return (await GetReadOnlyUserSettings(user)).GetOrDefault(name);
- }
- private async Task<Dictionary<string, SettingInfo>> GetApplicationSettingsAsync()
- {
- return await _applicationSettingCache.GetAsync(ApplicationSettingsCacheKey, async () =>
- {
- var dictionary = new Dictionary<string, SettingInfo>();
- var settingValues = await SettingStore.GetAllListAsync(null, null);
- foreach (var settingValue in settingValues)
- {
- dictionary[settingValue.Name] = settingValue;
- }
- return dictionary;
- });
- }
- private async Task<ImmutableDictionary<string, SettingInfo>> GetReadOnlyTenantSettings(int tenantId)
- {
- var cachedDictionary = await GetTenantSettingsFromCache(tenantId);
- lock (cachedDictionary)
- {
- return cachedDictionary.ToImmutableDictionary();
- }
- }
- private async Task<ImmutableDictionary<string, SettingInfo>> GetReadOnlyUserSettings(UserIdentifier user)
- {
- var cachedDictionary = await GetUserSettingsFromCache(user);
- lock (cachedDictionary)
- {
- return cachedDictionary.ToImmutableDictionary();
- }
- }
- private async Task<Dictionary<string, SettingInfo>> GetTenantSettingsFromCache(int tenantId)
- {
- return await _tenantSettingCache.GetAsync(
- tenantId,
- async () =>
- {
- var dictionary = new Dictionary<string, SettingInfo>();
- var settingValues = await SettingStore.GetAllListAsync(tenantId, null);
- foreach (var settingValue in settingValues)
- {
- dictionary[settingValue.Name] = settingValue;
- }
- return dictionary;
- });
- }
- private async Task<Dictionary<string, SettingInfo>> GetUserSettingsFromCache(UserIdentifier user)
- {
- return await _userSettingCache.GetAsync(
- user.ToUserIdentifierString(),
- async () =>
- {
- var dictionary = new Dictionary<string, SettingInfo>();
- var settingValues = await SettingStore.GetAllListAsync(user.TenantId, user.UserId);
- foreach (var settingValue in settingValues)
- {
- dictionary[settingValue.Name] = settingValue;
- }
- return dictionary;
- });
- }
- public Task<string> GetSettingValueForUserAsync(string name, UserIdentifier user)
- {
- Check.NotNull(name, nameof(name));
- Check.NotNull(user, nameof(user));
- return GetSettingValueForUserAsync(name, user.TenantId, user.UserId);
- }
- #endregion
- #region Nested classes
- private class SettingValueObject : ISettingValue
- {
- public string Name { get; private set; }
- public string Value { get; private set; }
- public SettingValueObject(string name, string value)
- {
- Value = value;
- Name = name;
- }
- }
- #endregion
- }
- }
|