using System.Globalization;
using System.Text.RegularExpressions;
using Abp;
using Abp.Domain.Repositories;
using Abp.Domain.Services;
using Abp.Domain.Uow;
using Abp.Localization;
using Abp.Runtime.Caching;
using Abp.UI;
using VberZero;
using VberZero.BaseSystem.MultiTenancy;
// ReSharper disable once CheckNamespace - This is done to add extension methods to Microsoft.Extensions.DependencyInjection namespace
namespace Microsoft.Extensions.DependencyInjection;
///
/// 租户管理器为 实现域逻辑
///
public class VzTenantManager : IDomainService
//, IEventHandler>
//,IEventHandler>
{
//public AbpEditionManager EditionManager { get; set; }
public ILocalizationManager LocalizationManager { get; set; }
protected string LocalizationSourceName { get; set; }
public ICacheManager CacheManager { get; set; }
//public IFeatureManager FeatureManager { get; set; }
public IUnitOfWorkManager UnitOfWorkManager { get; set; }
protected IRepository TenantRepository { get; set; }
//protected IRepository TenantFeatureRepository { get; set; }
//private readonly IAbpZeroFeatureValueStore _featureValueStore;
public VzTenantManager(IRepository tenantRepository)
{
//_featureValueStore = featureValueStore;
TenantRepository = tenantRepository;
//TenantFeatureRepository = tenantFeatureRepository;
//EditionManager = editionManager;
LocalizationManager = NullLocalizationManager.Instance;
LocalizationSourceName = VzConsts.LocalizationSourceName;
}
public virtual IQueryable Tenants => TenantRepository.GetAll();
public virtual async Task CreateAsync(Tenant tenant)
{
await UnitOfWorkManager.WithUnitOfWorkAsync(async () =>
{
await ValidateTenantAsync(tenant);
if (await TenantRepository.FirstOrDefaultAsync(t => t.TenancyName == tenant.TenancyName) != null)
{
throw new UserFriendlyException(string.Format(L("TenancyNameIsAlreadyTaken"), tenant.TenancyName));
}
await TenantRepository.InsertAsync(tenant);
});
}
public virtual void Create(Tenant tenant)
{
UnitOfWorkManager.WithUnitOfWork(() =>
{
ValidateTenant(tenant);
if (TenantRepository.FirstOrDefault(t => t.TenancyName == tenant.TenancyName) != null)
{
throw new UserFriendlyException(string.Format(L("TenancyNameIsAlreadyTaken"), tenant.TenancyName));
}
TenantRepository.Insert(tenant);
});
}
public virtual async Task UpdateAsync(Tenant tenant)
{
await UnitOfWorkManager.WithUnitOfWorkAsync(async () =>
{
if (await TenantRepository.FirstOrDefaultAsync(t => t.TenancyName == tenant.TenancyName && t.Id != tenant.Id) != null)
{
throw new UserFriendlyException(string.Format(L("TenancyNameIsAlreadyTaken"), tenant.TenancyName));
}
await TenantRepository.UpdateAsync(tenant);
});
}
public virtual void Update(Tenant tenant)
{
UnitOfWorkManager.WithUnitOfWork(() =>
{
if (TenantRepository.FirstOrDefault(t => t.TenancyName == tenant.TenancyName && t.Id != tenant.Id) != null)
{
throw new UserFriendlyException(string.Format(L("TenancyNameIsAlreadyTaken"), tenant.TenancyName));
}
TenantRepository.Update(tenant);
});
}
public virtual async Task FindByIdAsync(int id)
{
return await UnitOfWorkManager.WithUnitOfWorkAsync(async () => await TenantRepository.FirstOrDefaultAsync(id));
}
public virtual Tenant FindById(int id)
{
return UnitOfWorkManager.WithUnitOfWork(() => TenantRepository.FirstOrDefault(id));
}
public virtual async Task GetByIdAsync(int id)
{
var tenant = await FindByIdAsync(id);
if (tenant == null)
{
throw new AbpException("There is no tenant with id: " + id);
}
return tenant;
}
public virtual Tenant GetById(int id)
{
var tenant = FindById(id);
if (tenant == null)
{
throw new AbpException("There is no tenant with id: " + id);
}
return tenant;
}
public virtual async Task FindByTenancyNameAsync(string tenancyName)
{
return await UnitOfWorkManager.WithUnitOfWorkAsync(async () =>
{
return await TenantRepository.FirstOrDefaultAsync(t => t.TenancyName == tenancyName);
});
}
public virtual Tenant FindByTenancyName(string tenancyName)
{
return UnitOfWorkManager.WithUnitOfWork(() =>
{
return TenantRepository.FirstOrDefault(t => t.TenancyName == tenancyName);
});
}
public virtual async Task DeleteAsync(Tenant tenant)
{
await UnitOfWorkManager.WithUnitOfWorkAsync(async () =>
{
await TenantRepository.DeleteAsync(tenant);
});
}
public virtual void Delete(Tenant tenant)
{
UnitOfWorkManager.WithUnitOfWork(() =>
{
TenantRepository.Delete(tenant);
});
}
protected virtual async Task ValidateTenantAsync(Tenant tenant)
{
await ValidateTenancyNameAsync(tenant.TenancyName);
}
protected virtual void ValidateTenant(Tenant tenant)
{
ValidateTenancyName(tenant.TenancyName);
}
protected virtual Task ValidateTenancyNameAsync(string tenancyName)
{
if (!Regex.IsMatch(tenancyName, Tenant.TenancyNameRegex))
{
throw new UserFriendlyException(L("InvalidTenancyName"));
}
return Task.FromResult(0);
}
protected virtual void ValidateTenancyName(string tenancyName)
{
if (!Regex.IsMatch(tenancyName, Tenant.TenancyNameRegex))
{
throw new UserFriendlyException(L("InvalidTenancyName"));
}
}
protected virtual string L(string name)
{
return LocalizationManager.GetString(LocalizationSourceName, name);
}
protected virtual string L(string name, CultureInfo cultureInfo)
{
return LocalizationManager.GetString(LocalizationSourceName, name, cultureInfo);
}
/*
public Task GetFeatureValueOrNullAsync(int tenantId, string featureName)
{
return _featureValueStore.GetValueOrNullAsync(tenantId, featureName);
}
public string GetFeatureValueOrNull(int tenantId, string featureName)
{
return _featureValueStore.GetValueOrNull(tenantId, featureName);
}
public virtual async Task> GetFeatureValuesAsync(int tenantId)
{
var values = new List();
foreach (var feature in FeatureManager.GetAll())
{
values.Add(new NameValue(feature.Name, await GetFeatureValueOrNullAsync(tenantId, feature.Name) ?? feature.DefaultValue));
}
return values;
}
public virtual IReadOnlyList GetFeatureValues(int tenantId)
{
var values = new List();
foreach (var feature in FeatureManager.GetAll())
{
values.Add(new NameValue(feature.Name, GetFeatureValueOrNull(tenantId, feature.Name) ?? feature.DefaultValue));
}
return values;
}
public virtual async Task SetFeatureValuesAsync(int tenantId, params NameValue[] values)
{
if (values.IsNullOrEmpty())
{
return;
}
foreach (var value in values)
{
await SetFeatureValueAsync(tenantId, value.Name, value.Value);
}
}
public virtual void SetFeatureValues(int tenantId, params NameValue[] values)
{
if (values.IsNullOrEmpty())
{
return;
}
foreach (var value in values)
{
SetFeatureValue(tenantId, value.Name, value.Value);
}
}
public virtual async Task SetFeatureValueAsync(int tenantId, string featureName, string value)
{
await UnitOfWorkManager.WithUnitOfWorkAsync(async () =>
{
await SetFeatureValueAsync(await GetByIdAsync(tenantId), featureName, value);
});
}
public virtual void SetFeatureValue(int tenantId, string featureName, string value)
{
UnitOfWorkManager.WithUnitOfWork(() =>
{
SetFeatureValue(GetById(tenantId), featureName, value);
});
}
public virtual async Task SetFeatureValueAsync(AbpTenant tenant, string featureName, string value)
{
await UnitOfWorkManager.WithUnitOfWorkAsync(async () =>
{
//No need to change if it's already equals to the current value
if (await GetFeatureValueOrNullAsync(tenant.Id, featureName) == value)
{
return;
}
//Get the current feature setting
TenantFeatureSetting currentSetting;
using (UnitOfWorkManager.Current.EnableFilter(AbpDataFilters.MayHaveTenant))
using (UnitOfWorkManager.Current.SetTenantId(tenant.Id))
{
currentSetting = await TenantFeatureRepository.FirstOrDefaultAsync(f => f.Name == featureName);
}
//Get the feature
var feature = FeatureManager.GetOrNull(featureName);
if (feature == null)
{
if (currentSetting != null)
{
await TenantFeatureRepository.DeleteAsync(currentSetting);
}
return;
}
//Determine default value
var defaultValue = tenant.EditionId.HasValue
? (await EditionManager.GetFeatureValueOrNullAsync(tenant.EditionId.Value, featureName) ?? feature.DefaultValue)
: feature.DefaultValue;
//No need to store value if it's default
if (value == defaultValue)
{
if (currentSetting != null)
{
await TenantFeatureRepository.DeleteAsync(currentSetting);
}
return;
}
//Insert/update the feature value
if (currentSetting == null)
{
await TenantFeatureRepository.InsertAsync(new TenantFeatureSetting(tenant.Id, featureName, value));
}
else
{
currentSetting.Value = value;
}
});
}
public virtual void SetFeatureValue(AbpTenant tenant, string featureName, string value)
{
UnitOfWorkManager.WithUnitOfWork(() =>
{
//No need to change if it's already equals to the current value
if (GetFeatureValueOrNull(tenant.Id, featureName) == value)
{
return;
}
//Get the current feature setting
TenantFeatureSetting currentSetting;
using (UnitOfWorkManager.Current.EnableFilter(AbpDataFilters.MayHaveTenant))
using (UnitOfWorkManager.Current.SetTenantId(tenant.Id))
{
currentSetting = TenantFeatureRepository.FirstOrDefault(f => f.Name == featureName);
}
//Get the feature
var feature = FeatureManager.GetOrNull(featureName);
if (feature == null)
{
if (currentSetting != null)
{
TenantFeatureRepository.Delete(currentSetting);
}
return;
}
//Determine default value
var defaultValue = tenant.EditionId.HasValue
? (EditionManager.GetFeatureValueOrNull(tenant.EditionId.Value, featureName) ?? feature.DefaultValue)
: feature.DefaultValue;
//No need to store value if it's default
if (value == defaultValue)
{
if (currentSetting != null)
{
TenantFeatureRepository.Delete(currentSetting);
}
return;
}
//Insert/update the feature value
if (currentSetting == null)
{
TenantFeatureRepository.Insert(new TenantFeatureSetting(tenant.Id, featureName, value));
}
else
{
currentSetting.Value = value;
}
});
}
///
/// Resets all custom feature settings for a tenant.
/// Tenant will have features according to it's edition.
///
/// Tenant Id
public virtual async Task ResetAllFeaturesAsync(int tenantId)
{
await UnitOfWorkManager.WithUnitOfWorkAsync(async () =>
{
using (UnitOfWorkManager.Current.EnableFilter(AbpDataFilters.MayHaveTenant))
using (UnitOfWorkManager.Current.SetTenantId(tenantId))
{
await TenantFeatureRepository.DeleteAsync(f => f.TenantId == tenantId);
}
});
}
///
/// Resets all custom feature settings for a tenant.
/// Tenant will have features according to it's edition.
///
/// Tenant Id
public virtual void ResetAllFeatures(int tenantId)
{
UnitOfWorkManager.WithUnitOfWork(() =>
{
using (UnitOfWorkManager.Current.EnableFilter(AbpDataFilters.MayHaveTenant))
using (UnitOfWorkManager.Current.SetTenantId(tenantId))
{
TenantFeatureRepository.Delete(f => f.TenantId == tenantId);
}
});
}*/
/*
public void HandleEvent(EntityChangedEventData eventData)
{
if (eventData.Entity.IsTransient())
{
return;
}
CacheManager.GeAbpTenantFeatureCache().Remove(eventData.Entity.Id);
}
public virtual void HandleEvent(EntityDeletedEventData eventData)
{
UnitOfWorkManager.WithUnitOfWork(() =>
{
var relatedTenants = TenantRepository.GetAllList(t => t.EditionId == eventData.Entity.Id);
foreach (var relatedTenant in relatedTenants)
{
relatedTenant.EditionId = null;
}
});
}
*/
}