Common: added dbcontext pool

This commit is contained in:
pavelbannov 2022-07-28 15:29:03 +03:00
parent 997e20898a
commit 8d89d8e8f2
42 changed files with 667 additions and 998 deletions

View File

@ -24,6 +24,8 @@
// content are licensed under the terms of the Creative Commons Attribution-ShareAlike 4.0
// International. See the License terms at http://creativecommons.org/licenses/by-sa/4.0/legalcode
using ASC.Core.Common.EF.Context;
using JsonConverter = System.Text.Json.Serialization.JsonConverter;
namespace ASC.Api.Core;
@ -58,6 +60,13 @@ public abstract class BaseStartup
services.AddHttpContextAccessor();
services.AddMemoryCache();
services.AddHttpClient();
services.AddBaseDbContext<AccountLinkContext>();
services.AddBaseDbContext<CoreDbContext>();
services.AddBaseDbContext<TenantDbContext>();
services.AddBaseDbContext<UserDbContext>();
services.AddBaseDbContext<TelegramDbContext>();
services.AddBaseDbContext<CustomDbContext>();
services.AddBaseDbContext<WebstudioDbContext>();
if (AddAndUseSession)
{

View File

@ -24,6 +24,8 @@
// content are licensed under the terms of the Creative Commons Attribution-ShareAlike 4.0
// International. See the License terms at http://creativecommons.org/licenses/by-sa/4.0/legalcode
using ASC.Core.Common.EF.Context;
namespace ASC.Api.Core;
public class BaseWorkerStartup
@ -39,6 +41,13 @@ public class BaseWorkerStartup
{
services.AddHttpContextAccessor();
services.AddCustomHealthCheck(_configuration);
services.AddBaseDbContext<AccountLinkContext>();
services.AddBaseDbContext<CoreDbContext>();
services.AddBaseDbContext<TenantDbContext>();
services.AddBaseDbContext<UserDbContext>();
services.AddBaseDbContext<TelegramDbContext>();
services.AddBaseDbContext<CustomDbContext>();
services.AddBaseDbContext<WebstudioDbContext>();
}
public virtual void Configure(IApplicationBuilder app)

View File

@ -26,7 +26,7 @@
namespace ASC.Core.Billing;
[Scope(typeof(ConfigureTariffService))]
[Scope(typeof(TariffService))]
public interface ITariffService
{
IDictionary<string, Dictionary<string, decimal>> GetProductPriceInfo(params string[] productIds);

View File

@ -60,88 +60,25 @@ public class TariffServiceStorage
}
}
[Scope]
class ConfigureTariffService : IConfigureNamedOptions<TariffService>
{
private readonly IOptionsSnapshot<CachedQuotaService> _quotaService;
private readonly IOptionsSnapshot<CachedTenantService> _tenantService;
private readonly CoreBaseSettings _coreBaseSettings;
private readonly CoreSettings _coreSettings;
private readonly IConfiguration _configuration;
private readonly DbContextManager<CoreDbContext> _coreDbContextManager;
private readonly TariffServiceStorage _tariffServiceStorage;
private readonly ILogger<TariffService> _logger;
public ConfigureTariffService(
IOptionsSnapshot<CachedQuotaService> quotaService,
IOptionsSnapshot<CachedTenantService> tenantService,
CoreBaseSettings coreBaseSettings,
CoreSettings coreSettings,
IConfiguration configuration,
DbContextManager<CoreDbContext> coreDbContextManager,
TariffServiceStorage tariffServiceStorage,
ILogger<TariffService> options)
{
_quotaService = quotaService;
_tenantService = tenantService;
_coreBaseSettings = coreBaseSettings;
_coreSettings = coreSettings;
_configuration = configuration;
_coreDbContextManager = coreDbContextManager;
_tariffServiceStorage = tariffServiceStorage;
_logger = options;
}
public void Configure(string name, TariffService options)
{
Configure(options);
options.QuotaService = _quotaService.Get(name);
options.TenantService = _tenantService.Get(name);
options.LazyCoreDbContext = new Lazy<CoreDbContext>(() => _coreDbContextManager.Get(name));
}
public void Configure(TariffService options)
{
options.Logger = _logger;
options.CoreSettings = _coreSettings;
options.Configuration = _configuration;
options.TariffServiceStorage = _tariffServiceStorage;
options.CoreBaseSettings = _coreBaseSettings;
options.Test = _configuration["core:payment:test"] == "true";
int.TryParse(_configuration["core:payment:delay"], out var paymentDelay);
options.PaymentDelay = paymentDelay;
options.Cache = _tariffServiceStorage.Cache;
options.Notify = _tariffServiceStorage.Notify;
options.QuotaService = _quotaService.Value;
options.TenantService = _tenantService.Value;
options.LazyCoreDbContext = new Lazy<CoreDbContext>(() => _coreDbContextManager.Value);
}
}
public class TariffService : ITariffService
{
private const int DefaultTrialPeriod = 30;
private static readonly TimeSpan _defaultCacheExpiration = TimeSpan.FromMinutes(5);
private static readonly TimeSpan _standaloneCacheExpiration = TimeSpan.FromMinutes(15);
internal ICache Cache { get; set; }
internal ICacheNotify<TariffCacheItem> Notify { get; set; }
internal ILogger<TariffService> Logger { get; set; }
internal IQuotaService QuotaService { get; set; }
internal ITenantService TenantService { get; set; }
internal bool Test { get; set; }
internal int PaymentDelay { get; set; }
public TimeSpan CacheExpiration { get; set; }
internal CoreBaseSettings CoreBaseSettings { get; set; }
internal CoreSettings CoreSettings { get; set; }
internal IConfiguration Configuration { get; set; }
internal CoreDbContext CoreDbContext => LazyCoreDbContext.Value;
internal Lazy<CoreDbContext> LazyCoreDbContext;
internal TariffServiceStorage TariffServiceStorage { get; set; }
private readonly ICache _cache;
private readonly ICacheNotify<TariffCacheItem> _notify;
private readonly ILogger<TariffService> _logger;
private readonly IQuotaService _quotaService;
private readonly ITenantService _tenantService;
private readonly bool _test;
private readonly int _paymentDelay;
private TimeSpan _cacheExpiration;
private readonly CoreBaseSettings _coreBaseSettings;
private readonly CoreSettings _coreSettings;
private readonly IConfiguration _configuration;
private readonly IDbContextFactory<CoreDbContext> _dbContextFactory;
private readonly TariffServiceStorage _tariffServiceStorage;
private readonly BillingClient _billingClient;
private readonly IHttpClientFactory _httpClientFactory;
private readonly int _activeUsersMin;
@ -149,7 +86,7 @@ public class TariffService : ITariffService
public TariffService()
{
CacheExpiration = _defaultCacheExpiration;
_cacheExpiration = _defaultCacheExpiration;
}
public TariffService(
@ -158,7 +95,7 @@ public class TariffService : ITariffService
CoreBaseSettings coreBaseSettings,
CoreSettings coreSettings,
IConfiguration configuration,
DbContextManager<CoreDbContext> coreDbContextManager,
IDbContextFactory<CoreDbContext> coreDbContextManager,
TariffServiceStorage tariffServiceStorage,
ILogger<TariffService> logger,
BillingClient billingClient,
@ -166,24 +103,24 @@ public class TariffService : ITariffService
: this()
{
Logger = logger;
QuotaService = quotaService;
TenantService = tenantService;
CoreSettings = coreSettings;
Configuration = configuration;
TariffServiceStorage = tariffServiceStorage;
_logger = logger;
_quotaService = quotaService;
_tenantService = tenantService;
_coreSettings = coreSettings;
_configuration = configuration;
_tariffServiceStorage = tariffServiceStorage;
_billingClient = billingClient;
_httpClientFactory = httpClientFactory;
CoreBaseSettings = coreBaseSettings;
Test = configuration["core:payment:test"] == "true";
_coreBaseSettings = coreBaseSettings;
_test = configuration["core:payment:test"] == "true";
int.TryParse(configuration["core:payment:delay"], out var paymentDelay);
PaymentDelay = paymentDelay;
_paymentDelay = paymentDelay;
Cache = TariffServiceStorage.Cache;
Notify = TariffServiceStorage.Notify;
LazyCoreDbContext = new Lazy<CoreDbContext>(() => coreDbContextManager.Value);
var range = (Configuration["core.payment-user-range"] ?? "").Split('-');
_cache = _tariffServiceStorage.Cache;
_notify = _tariffServiceStorage.Notify;
_dbContextFactory = coreDbContextManager;
var range = (_configuration["core.payment-user-range"] ?? "").Split('-');
if (!int.TryParse(range[0], out _activeUsersMin))
{
_activeUsersMin = 0;
@ -197,18 +134,18 @@ public class TariffService : ITariffService
public Tariff GetTariff(int tenantId, bool withRequestToPaymentSystem = true)
{
//single tariff for all portals
if (CoreBaseSettings.Standalone)
if (_coreBaseSettings.Standalone)
{
tenantId = -1;
}
var key = GetTariffCacheKey(tenantId);
var tariff = Cache.Get<Tariff>(key);
var tariff = _cache.Get<Tariff>(key);
if (tariff == null)
{
tariff = GetBillingInfo(tenantId);
tariff = CalculateTariff(tenantId, tariff);
Cache.Insert(key, tariff, DateTime.UtcNow.Add(GetCacheExpiration()));
_cache.Insert(key, tariff, DateTime.UtcNow.Add(GetCacheExpiration()));
if (_billingClient.Configured && withRequestToPaymentSystem)
{
@ -219,7 +156,7 @@ public class TariffService : ITariffService
var client = GetBillingClient();
var lastPayment = client.GetLastPayment(GetPortalId(tenantId));
var quota = QuotaService.GetTenantQuotas().SingleOrDefault(q => q.AvangateId == lastPayment.ProductId);
var quota = _quotaService.GetTenantQuotas().SingleOrDefault(q => q.AvangateId == lastPayment.ProductId);
if (quota == null)
{
throw new InvalidOperationException($"Quota with id {lastPayment.ProductId} not found for portal {GetPortalId(tenantId)}.");
@ -241,12 +178,12 @@ public class TariffService : ITariffService
{
asynctariff = CalculateTariff(tenantId, asynctariff);
ClearCache(tenantId);
Cache.Insert(key, asynctariff, DateTime.UtcNow.Add(GetCacheExpiration()));
_cache.Insert(key, asynctariff, DateTime.UtcNow.Add(GetCacheExpiration()));
}
}
catch (BillingNotFoundException)
{
var q = QuotaService.GetTenantQuota(tariff.QuotaId);
var q = _quotaService.GetTenantQuota(tariff.QuotaId);
if (q != null
&& !q.Trial
@ -265,7 +202,7 @@ public class TariffService : ITariffService
{
asynctariff = CalculateTariff(tenantId, asynctariff);
ClearCache(tenantId);
Cache.Insert(key, asynctariff, DateTime.UtcNow.Add(GetCacheExpiration()));
_cache.Insert(key, asynctariff, DateTime.UtcNow.Add(GetCacheExpiration()));
}
}
}
@ -284,7 +221,7 @@ public class TariffService : ITariffService
{
ArgumentNullException.ThrowIfNull(tariff);
var q = QuotaService.GetTenantQuota(tariff.QuotaId);
var q = _quotaService.GetTenantQuota(tariff.QuotaId);
if (q == null)
{
return;
@ -294,11 +231,11 @@ public class TariffService : ITariffService
if (q.Trial)
{
// reset trial date
var tenant = TenantService.GetTenant(tenantId);
var tenant = _tenantService.GetTenant(tenantId);
if (tenant != null)
{
tenant.VersionChanged = DateTime.UtcNow;
TenantService.SaveTenant(CoreSettings, tenant);
_tenantService.SaveTenant(_coreSettings, tenant);
}
}
@ -323,13 +260,13 @@ public class TariffService : ITariffService
public void ClearCache(int tenantId)
{
Notify.Publish(new TariffCacheItem { TenantId = tenantId }, CacheNotifyAction.Remove);
_notify.Publish(new TariffCacheItem { TenantId = tenantId }, CacheNotifyAction.Remove);
}
public IEnumerable<PaymentInfo> GetPayments(int tenantId)
{
var key = GetBillingPaymentCacheKey(tenantId);
var payments = Cache.Get<List<PaymentInfo>>(key);
var payments = _cache.Get<List<PaymentInfo>>(key);
if (payments == null)
{
payments = new List<PaymentInfo>();
@ -337,7 +274,7 @@ public class TariffService : ITariffService
{
try
{
var quotas = QuotaService.GetTenantQuotas();
var quotas = _quotaService.GetTenantQuotas();
var client = GetBillingClient();
foreach (var pi in client.GetPayments(GetPortalId(tenantId)))
{
@ -355,7 +292,7 @@ public class TariffService : ITariffService
}
}
Cache.Insert(key, payments, DateTime.UtcNow.Add(TimeSpan.FromMinutes(10)));
_cache.Insert(key, payments, DateTime.UtcNow.Add(TimeSpan.FromMinutes(10)));
}
return payments;
@ -363,7 +300,7 @@ public class TariffService : ITariffService
public Uri GetShoppingUri(int? tenant, int quotaId, string affiliateId, string currency = null, string language = null, string customerId = null, string quantity = null)
{
var quota = QuotaService.GetTenantQuota(quotaId);
var quota = _quotaService.GetTenantQuota(quotaId);
if (quota == null)
{
return null;
@ -373,14 +310,14 @@ public class TariffService : ITariffService
? GetBillingUrlCacheKey(tenant.Value)
: string.Format($"notenant{(!string.IsNullOrEmpty(affiliateId) ? "_" + affiliateId : "")}");
key += quota.Visible ? "" : "0";
if (Cache.Get<Dictionary<string, Uri>>(key) is not IDictionary<string, Uri> urls)
if (_cache.Get<Dictionary<string, Uri>>(key) is not IDictionary<string, Uri> urls)
{
urls = new Dictionary<string, Uri>();
if (_billingClient.Configured)
{
try
{
var products = QuotaService.GetTenantQuotas()
var products = _quotaService.GetTenantQuotas()
.Where(q => !string.IsNullOrEmpty(q.AvangateId) && q.Visible == quota.Visible)
.Select(q => q.AvangateId)
.ToArray();
@ -400,10 +337,10 @@ public class TariffService : ITariffService
}
catch (Exception error)
{
Logger.ErrorGetShoppingUri(error);
_logger.ErrorGetShoppingUri(error);
}
}
Cache.Insert(key, urls, DateTime.UtcNow.Add(TimeSpan.FromMinutes(10)));
_cache.Insert(key, urls, DateTime.UtcNow.Add(TimeSpan.FromMinutes(10)));
}
ResetCacheExpiration();
@ -428,7 +365,7 @@ public class TariffService : ITariffService
public Uri GetShoppingUri(string[] productIds, string affiliateId = null, string currency = null, string language = null, string customerId = null, string quantity = null)
{
var key = "shopingurl" + string.Join("_", productIds) + (!string.IsNullOrEmpty(affiliateId) ? "_" + affiliateId : "");
var url = Cache.Get<string>(key);
var url = _cache.Get<string>(key);
if (url == null)
{
url = string.Empty;
@ -451,10 +388,10 @@ public class TariffService : ITariffService
}
catch (Exception error)
{
Logger.ErrorWithException(error);
_logger.ErrorWithException(error);
}
}
Cache.Insert(key, url, DateTime.UtcNow.Add(TimeSpan.FromMinutes(10)));
_cache.Insert(key, url, DateTime.UtcNow.Add(TimeSpan.FromMinutes(10)));
}
ResetCacheExpiration();
@ -480,12 +417,12 @@ public class TariffService : ITariffService
try
{
var key = "biling-prices" + string.Join(",", productIds);
var result = Cache.Get<IDictionary<string, Dictionary<string, decimal>>>(key);
var result = _cache.Get<IDictionary<string, Dictionary<string, decimal>>>(key);
if (result == null)
{
var client = GetBillingClient();
result = client.GetProductPriceInfo(productIds);
Cache.Insert(key, result, DateTime.Now.AddHours(1));
_cache.Insert(key, result, DateTime.Now.AddHours(1));
}
return result;
@ -503,7 +440,9 @@ public class TariffService : ITariffService
public string GetButton(int tariffId, string partnerId)
{
return CoreDbContext.Buttons
using var coreDbContext = _dbContextFactory.CreateDbContext();
return coreDbContext.Buttons
.Where(r => r.TariffId == tariffId && r.PartnerId == partnerId)
.Select(r => r.ButtonUrl)
.SingleOrDefault();
@ -518,14 +457,16 @@ public class TariffService : ITariffService
ButtonUrl = buttonUrl
};
CoreDbContext.AddOrUpdate(r => r.Buttons, efButton);
CoreDbContext.SaveChanges();
using var coreDbContext = _dbContextFactory.CreateDbContext();
coreDbContext.AddOrUpdate(r => r.Buttons, efButton);
coreDbContext.SaveChanges();
}
private Tariff GetBillingInfo(int tenant)
{
var r = CoreDbContext.Tariffs
using var coreDbContext = _dbContextFactory.CreateDbContext();
var r = coreDbContext.Tariffs
.Where(r => r.Tenant == tenant)
.OrderByDescending(r => r.Id)
.FirstOrDefault();
@ -549,45 +490,47 @@ public class TariffService : ITariffService
var currentTariff = GetBillingInfo(tenant);
if (!tariffInfo.EqualsByParams(currentTariff))
{
var strategy = CoreDbContext.Database.CreateExecutionStrategy();
using var dbContext = _dbContextFactory.CreateDbContext();
var strategy = dbContext.Database.CreateExecutionStrategy();
strategy.Execute(() =>
{
using var dbContext = _dbContextFactory.CreateDbContext();
using var tx = dbContext.Database.BeginTransaction();
// last record is not the same
var any = dbContext.Tariffs
.Any(r => r.Tenant == tenant && r.Tariff == tariffInfo.QuotaId && r.Stamp == tariffInfo.DueDate && r.Quantity == tariffInfo.Quantity);
if (tariffInfo.DueDate == DateTime.MaxValue || renewal || any)
{
using var tx = CoreDbContext.Database.BeginTransaction();
// last record is not the same
var any = CoreDbContext.Tariffs
.Any(r => r.Tenant == tenant && r.Tariff == tariffInfo.QuotaId && r.Stamp == tariffInfo.DueDate && r.Quantity == tariffInfo.Quantity);
if (tariffInfo.DueDate == DateTime.MaxValue || renewal || any)
var efTariff = new DbTariff
{
var efTariff = new DbTariff
{
Tenant = tenant,
Tariff = tariffInfo.QuotaId,
Stamp = tariffInfo.DueDate,
Quantity = tariffInfo.Quantity,
CreateOn = DateTime.UtcNow
};
Tenant = tenant,
Tariff = tariffInfo.QuotaId,
Stamp = tariffInfo.DueDate,
Quantity = tariffInfo.Quantity,
CreateOn = DateTime.UtcNow
};
CoreDbContext.Tariffs.Add(efTariff);
CoreDbContext.SaveChanges();
dbContext.Tariffs.Add(efTariff);
dbContext.SaveChanges();
Cache.Remove(GetTariffCacheKey(tenant));
inserted = true;
}
_cache.Remove(GetTariffCacheKey(tenant));
inserted = true;
}
tx.Commit();
});
tx.Commit();
});
}
if (inserted)
{
var t = TenantService.GetTenant(tenant);
var t = _tenantService.GetTenant(tenant);
if (t != null)
{
// update tenant.LastModified to flush cache in documents
TenantService.SaveTenant(CoreSettings, t);
_tenantService.SaveTenant(_coreSettings, t);
}
}
@ -598,7 +541,8 @@ public class TariffService : ITariffService
{
const int tenant = Tenant.DefaultTenant;
var tariffs = CoreDbContext.Tariffs.Where(r => r.Tenant == tenant).ToList();
using var coreDbContext = _dbContextFactory.CreateDbContext();
var tariffs = coreDbContext.Tariffs.Where(r => r.Tenant == tenant).ToList();
foreach (var t in tariffs)
{
@ -606,7 +550,7 @@ public class TariffService : ITariffService
t.CreateOn = DateTime.UtcNow;
}
CoreDbContext.SaveChanges();
coreDbContext.SaveChanges();
ClearCache(tenant);
}
@ -615,12 +559,12 @@ public class TariffService : ITariffService
private Tariff CalculateTariff(int tenantId, Tariff tariff)
{
tariff.State = TariffState.Paid;
var q = QuotaService.GetTenantQuota(tariff.QuotaId);
var q = _quotaService.GetTenantQuota(tariff.QuotaId);
if (q == null || q.GetFeature("old"))
{
tariff.QuotaId = Tenant.DefaultTenant;
q = QuotaService.GetTenantQuota(tariff.QuotaId);
q = _quotaService.GetTenantQuota(tariff.QuotaId);
}
var delay = 0;
@ -629,7 +573,7 @@ public class TariffService : ITariffService
tariff.State = TariffState.Trial;
if (tariff.DueDate == DateTime.MinValue || tariff.DueDate == DateTime.MaxValue)
{
var tenant = TenantService.GetTenant(tenantId);
var tenant = _tenantService.GetTenant(tenantId);
if (tenant != null)
{
var fromDate = tenant.CreationDateTime < tenant.VersionChanged ? tenant.VersionChanged : tenant.CreationDateTime;
@ -649,7 +593,7 @@ public class TariffService : ITariffService
}
else
{
delay = PaymentDelay;
delay = _paymentDelay;
}
if (tariff.DueDate != DateTime.MinValue && tariff.DueDate.Date < DateTime.Today && delay > 0)
@ -664,16 +608,16 @@ public class TariffService : ITariffService
{
tariff.State = TariffState.NotPaid;
if (CoreBaseSettings.Standalone)
if (_coreBaseSettings.Standalone)
{
if (q != null)
{
var defaultQuota = QuotaService.GetTenantQuota(Tenant.DefaultTenant);
var defaultQuota = _quotaService.GetTenantQuota(Tenant.DefaultTenant);
defaultQuota.Name = "overdue";
defaultQuota.Features = q.Features;
QuotaService.SaveTenantQuota(defaultQuota);
_quotaService.SaveTenantQuota(defaultQuota);
}
var unlimTariff = Tariff.CreateDefault();
@ -692,7 +636,7 @@ public class TariffService : ITariffService
private int GetPeriod(string key, int defaultValue)
{
var settings = TenantService.GetTenantSettings(Tenant.DefaultTenant, key);
var settings = _tenantService.GetTenantSettings(Tenant.DefaultTenant, key);
return settings != null ? Convert.ToInt32(Encoding.UTF8.GetString(settings)) : defaultValue;
}
@ -701,7 +645,7 @@ public class TariffService : ITariffService
{
try
{
return new BillingClient(Test, Configuration, _httpClientFactory);
return new BillingClient(_test, _configuration, _httpClientFactory);
}
catch (InvalidOperationException ioe)
{
@ -709,40 +653,40 @@ public class TariffService : ITariffService
}
catch (ReflectionTypeLoadException rtle)
{
Logger.ErrorLoaderExceptions(string.Join(Environment.NewLine, rtle.LoaderExceptions.Select(e => e.ToString())), rtle);
_logger.ErrorLoaderExceptions(string.Join(Environment.NewLine, rtle.LoaderExceptions.Select(e => e.ToString())), rtle);
throw;
}
}
private string GetPortalId(int tenant)
{
return CoreSettings.GetKey(tenant);
return _coreSettings.GetKey(tenant);
}
private string GetAffiliateId(int tenant)
{
return CoreSettings.GetAffiliateId(tenant);
return _coreSettings.GetAffiliateId(tenant);
}
private string GetCampaign(int tenant)
{
return CoreSettings.GetCampaign(tenant);
return _coreSettings.GetCampaign(tenant);
}
private TimeSpan GetCacheExpiration()
{
if (CoreBaseSettings.Standalone && CacheExpiration < _standaloneCacheExpiration)
if (_coreBaseSettings.Standalone && _cacheExpiration < _standaloneCacheExpiration)
{
CacheExpiration = CacheExpiration.Add(TimeSpan.FromSeconds(30));
_cacheExpiration = _cacheExpiration.Add(TimeSpan.FromSeconds(30));
}
return CacheExpiration;
return _cacheExpiration;
}
private void ResetCacheExpiration()
{
if (CoreBaseSettings.Standalone)
if (_coreBaseSettings.Standalone)
{
CacheExpiration = _defaultCacheExpiration;
_cacheExpiration = _defaultCacheExpiration;
}
}
@ -750,21 +694,21 @@ public class TariffService : ITariffService
{
if (error is BillingNotFoundException)
{
Logger.DebugPaymentTenant(tenantId, error.Message);
_logger.DebugPaymentTenant(tenantId, error.Message);
}
else if (error is BillingNotConfiguredException)
{
Logger.DebugBillingTenant(tenantId, error.Message);
_logger.DebugBillingTenant(tenantId, error.Message);
}
else
{
if (Logger.IsEnabled(LogLevel.Debug))
if (_logger.IsEnabled(LogLevel.Debug))
{
Logger.ErrorBillingWithException(tenantId, error);
_logger.ErrorBillingWithException(tenantId, error);
}
else
{
Logger.ErrorBilling(tenantId, error.Message);
_logger.ErrorBilling(tenantId, error.Message);
}
}
}

View File

@ -63,35 +63,6 @@ class QuotaServiceCache
}
}
[Scope]
class ConfigureCachedQuotaService : IConfigureNamedOptions<CachedQuotaService>
{
private readonly IOptionsSnapshot<DbQuotaService> _service;
private readonly QuotaServiceCache _quotaServiceCache;
public ConfigureCachedQuotaService(
IOptionsSnapshot<DbQuotaService> service,
QuotaServiceCache quotaServiceCache)
{
_service = service;
_quotaServiceCache = quotaServiceCache;
}
public void Configure(string name, CachedQuotaService options)
{
Configure(options);
options.Service = _service.Get(name);
}
public void Configure(CachedQuotaService options)
{
options.Service = _service.Value;
options.QuotaServiceCache = _quotaServiceCache;
options.Cache = _quotaServiceCache.Cache;
options.CacheNotify = _quotaServiceCache.CacheNotify;
}
}
[Scope]
class CachedQuotaService : IQuotaService
{

View File

@ -161,43 +161,13 @@ class TenantServiceCache
}
}
[Scope]
class ConfigureCachedTenantService : IConfigureNamedOptions<CachedTenantService>
{
private readonly IOptionsSnapshot<DbTenantService> _service;
private readonly TenantServiceCache _tenantServiceCache;
public ConfigureCachedTenantService(
IOptionsSnapshot<DbTenantService> service,
TenantServiceCache tenantServiceCache)
{
_service = service;
_tenantServiceCache = tenantServiceCache;
}
public void Configure(string name, CachedTenantService options)
{
Configure(options);
options.Service = _service.Get(name);
}
public void Configure(CachedTenantService options)
{
options.Service = _service.Value;
options.TenantServiceCache = _tenantServiceCache;
options.CacheNotifyItem = _tenantServiceCache.CacheNotifyItem;
options.CacheNotifySettings = _tenantServiceCache.CacheNotifySettings;
}
}
[Scope]
class CachedTenantService : ITenantService
{
internal ITenantService Service { get; set; }
internal ICacheNotify<TenantSetting> CacheNotifySettings { get; set; }
internal ICacheNotify<TenantCacheItem> CacheNotifyItem { get; set; }
internal TenantServiceCache TenantServiceCache { get; set; }
private readonly ITenantService _service;
private readonly ICacheNotify<TenantSetting> _cacheNotifySettings;
private readonly ICacheNotify<TenantCacheItem> _cacheNotifyItem;
private readonly TenantServiceCache _tenantServiceCache;
private readonly TimeSpan _settingsExpiration;
private readonly ICache _cache;
@ -209,38 +179,38 @@ class CachedTenantService : ITenantService
public CachedTenantService(DbTenantService service, TenantServiceCache tenantServiceCache, ICache cache) : this()
{
_cache = cache;
Service = service ?? throw new ArgumentNullException(nameof(service));
TenantServiceCache = tenantServiceCache;
CacheNotifyItem = tenantServiceCache.CacheNotifyItem;
CacheNotifySettings = tenantServiceCache.CacheNotifySettings;
_service = service ?? throw new ArgumentNullException(nameof(service));
_tenantServiceCache = tenantServiceCache;
_cacheNotifyItem = tenantServiceCache.CacheNotifyItem;
_cacheNotifySettings = tenantServiceCache.CacheNotifySettings;
}
public void ValidateDomain(string domain)
{
Service.ValidateDomain(domain);
_service.ValidateDomain(domain);
}
public IEnumerable<Tenant> GetTenants(string login, string passwordHash)
{
return Service.GetTenants(login, passwordHash);
return _service.GetTenants(login, passwordHash);
}
public IEnumerable<Tenant> GetTenants(DateTime from, bool active = true)
{
return Service.GetTenants(from, active);
return _service.GetTenants(from, active);
}
public IEnumerable<Tenant> GetTenants(List<int> ids)
{
return Service.GetTenants(ids);
return _service.GetTenants(ids);
}
public Tenant GetTenant(int id)
{
var tenants = TenantServiceCache.GetTenantStore();
var tenants = _tenantServiceCache.GetTenantStore();
var t = tenants.Get(id);
if (t == null)
{
t = Service.GetTenant(id);
t = _service.GetTenant(id);
if (t != null)
{
tenants.Insert(t);
@ -252,11 +222,11 @@ class CachedTenantService : ITenantService
public Tenant GetTenant(string domain)
{
var tenants = TenantServiceCache.GetTenantStore();
var tenants = _tenantServiceCache.GetTenantStore();
var t = tenants.Get(domain);
if (t == null)
{
t = Service.GetTenant(domain);
t = _service.GetTenant(domain);
if (t != null)
{
tenants.Insert(t);
@ -268,11 +238,11 @@ class CachedTenantService : ITenantService
public Tenant GetTenantForStandaloneWithoutAlias(string ip)
{
var tenants = TenantServiceCache.GetTenantStore();
var tenants = _tenantServiceCache.GetTenantStore();
var t = tenants.Get(ip);
if (t == null)
{
t = Service.GetTenantForStandaloneWithoutAlias(ip);
t = _service.GetTenantForStandaloneWithoutAlias(ip);
if (t != null)
{
tenants.Insert(t, ip);
@ -284,21 +254,21 @@ class CachedTenantService : ITenantService
public Tenant SaveTenant(CoreSettings coreSettings, Tenant tenant)
{
tenant = Service.SaveTenant(coreSettings, tenant);
CacheNotifyItem.Publish(new TenantCacheItem() { TenantId = tenant.Id }, CacheNotifyAction.InsertOrUpdate);
tenant = _service.SaveTenant(coreSettings, tenant);
_cacheNotifyItem.Publish(new TenantCacheItem() { TenantId = tenant.Id }, CacheNotifyAction.InsertOrUpdate);
return tenant;
}
public void RemoveTenant(int id, bool auto = false)
{
Service.RemoveTenant(id, auto);
CacheNotifyItem.Publish(new TenantCacheItem() { TenantId = id }, CacheNotifyAction.InsertOrUpdate);
_service.RemoveTenant(id, auto);
_cacheNotifyItem.Publish(new TenantCacheItem() { TenantId = id }, CacheNotifyAction.InsertOrUpdate);
}
public IEnumerable<TenantVersion> GetTenantVersions()
{
return Service.GetTenantVersions();
return _service.GetTenantVersions();
}
public byte[] GetTenantSettings(int tenant, string key)
@ -307,7 +277,7 @@ class CachedTenantService : ITenantService
var data = _cache.Get<byte[]>(cacheKey);
if (data == null)
{
data = Service.GetTenantSettings(tenant, key);
data = _service.GetTenantSettings(tenant, key);
_cache.Insert(cacheKey, data ?? Array.Empty<byte>(), DateTime.UtcNow + _settingsExpiration);
}
@ -317,9 +287,9 @@ class CachedTenantService : ITenantService
public void SetTenantSettings(int tenant, string key, byte[] data)
{
Service.SetTenantSettings(tenant, key, data);
_service.SetTenantSettings(tenant, key, data);
var cacheKey = string.Format("settings/{0}/{1}", tenant, key);
CacheNotifySettings.Publish(new TenantSetting { Key = cacheKey }, CacheNotifyAction.Remove);
_cacheNotifySettings.Publish(new TenantSetting { Key = cacheKey }, CacheNotifyAction.Remove);
}
}

View File

@ -26,55 +26,8 @@
namespace ASC.Core;
[Scope]
class ConfigureTenantManager : IConfigureNamedOptions<TenantManager>
{
private readonly IOptionsSnapshot<CachedTenantService> _tenantService;
private readonly IOptionsSnapshot<CachedQuotaService> _quotaService;
private readonly IOptionsSnapshot<TariffService> _tariffService;
private readonly IHttpContextAccessor _httpContextAccessor;
private readonly CoreBaseSettings _coreBaseSettings;
private readonly CoreSettings _coreSettings;
public ConfigureTenantManager(
IOptionsSnapshot<CachedTenantService> tenantService,
IOptionsSnapshot<CachedQuotaService> quotaService,
IOptionsSnapshot<TariffService> tariffService,
IHttpContextAccessor httpContextAccessor,
CoreBaseSettings coreBaseSettings,
CoreSettings coreSettings
)
{
_tenantService = tenantService;
_quotaService = quotaService;
_tariffService = tariffService;
_httpContextAccessor = httpContextAccessor;
_coreBaseSettings = coreBaseSettings;
_coreSettings = coreSettings;
}
public void Configure(string name, TenantManager options)
{
Configure(options);
options.TenantService = _tenantService.Get(name);
options.QuotaService = _quotaService.Get(name);
options.TariffService = _tariffService.Get(name);
}
public void Configure(TenantManager options)
{
options.HttpContextAccessor = _httpContextAccessor;
options.CoreBaseSettings = _coreBaseSettings;
options.CoreSettings = _coreSettings;
options.TenantService = _tenantService.Value;
options.QuotaService = _quotaService.Value;
options.TariffService = _tariffService.Value;
}
}
[Scope(typeof(ConfigureTenantManager))]
public class TenantManager
{
private Tenant _currentTenant;

View File

@ -26,7 +26,7 @@
namespace ASC.Core;
[Scope(typeof(ConfigureDbQuotaService), typeof(ConfigureCachedQuotaService))]
[Scope(typeof(CachedQuotaService))]
public interface IQuotaService
{
IEnumerable<TenantQuota> GetTenantQuotas();

View File

@ -26,7 +26,7 @@
namespace ASC.Core;
[Scope(typeof(ConfigureDbTenantService), typeof(ConfigureCachedTenantService))]
[Scope(typeof(CachedTenantService))]
public interface ITenantService
{
byte[] GetTenantSettings(int tenant, string key);

View File

@ -26,7 +26,7 @@
namespace ASC.Core;
[Scope(typeof(ConfigureEFUserService), typeof(ConfigureCachedUserService))]
[Scope(typeof(CachedUserService))]
public interface IUserService
{
IEnumerable<UserInfo> GetUsers(int tenant);

View File

@ -29,27 +29,28 @@ namespace ASC.Core.Data;
[Scope]
class DbAzService : IAzService
{
private UserDbContext UserDbContext => _lazyUserDbContext.Value;
private readonly Lazy<UserDbContext> _lazyUserDbContext;
private readonly IDbContextFactory<UserDbContext> _dbContextFactory;
private readonly IMapper _mapper;
public DbAzService(DbContextManager<UserDbContext> dbContextManager, IMapper mapper)
public DbAzService(IDbContextFactory<UserDbContext> dbContextFactory, IMapper mapper)
{
_lazyUserDbContext = new Lazy<UserDbContext>(() => dbContextManager.Value);
_dbContextFactory = dbContextFactory;
_mapper = mapper;
}
public IEnumerable<AzRecord> GetAces(int tenant, DateTime from)
{
using var userDbContext = _dbContextFactory.CreateDbContext();
// row with tenant = -1 - common for all tenants, but equal row with tenant != -1 escape common row for the portal
var commonAces =
UserDbContext.Acl
userDbContext.Acl
.Where(r => r.Tenant == Tenant.DefaultTenant)
.ProjectTo<AzRecord>(_mapper.ConfigurationProvider)
.ToDictionary(a => string.Concat(a.Tenant.ToString(), a.Subject.ToString(), a.Action.ToString(), a.Object));
var tenantAces =
UserDbContext.Acl
userDbContext.Acl
.Where(r => r.Tenant == tenant)
.ProjectTo<AzRecord>(_mapper.ConfigurationProvider)
.ToList();
@ -75,11 +76,13 @@ class DbAzService : IAzService
{
r.Tenant = tenant;
var strategy = UserDbContext.Database.CreateExecutionStrategy();
using var userDbContext = _dbContextFactory.CreateDbContext();
var strategy = userDbContext.Database.CreateExecutionStrategy();
strategy.Execute(() =>
{
using var tx = UserDbContext.Database.BeginTransaction();
using var userDbContext = _dbContextFactory.CreateDbContext();
using var tx = userDbContext.Database.BeginTransaction();
if (!ExistEscapeRecord(r))
{
@ -101,11 +104,13 @@ class DbAzService : IAzService
{
r.Tenant = tenant;
var strategy = UserDbContext.Database.CreateExecutionStrategy();
using var userDbContext = _dbContextFactory.CreateDbContext();
var strategy = userDbContext.Database.CreateExecutionStrategy();
strategy.Execute(() =>
{
using var tx = UserDbContext.Database.BeginTransaction();
using var userDbContext = _dbContextFactory.CreateDbContext();
using var tx = userDbContext.Database.BeginTransaction();
if (ExistEscapeRecord(r))
{
@ -125,7 +130,8 @@ class DbAzService : IAzService
private bool ExistEscapeRecord(AzRecord r)
{
return UserDbContext.Acl
using var userDbContext = _dbContextFactory.CreateDbContext();
return userDbContext.Acl
.Where(a => a.Tenant == Tenant.DefaultTenant)
.Where(a => a.Subject == r.Subject)
.Where(a => a.Action == r.Action)
@ -136,7 +142,8 @@ class DbAzService : IAzService
private void DeleteRecord(AzRecord r)
{
var record = UserDbContext.Acl
using var userDbContext = _dbContextFactory.CreateDbContext();
var record = userDbContext.Acl
.Where(a => a.Tenant == r.Tenant)
.Where(a => a.Subject == r.Subject)
.Where(a => a.Action == r.Action)
@ -146,14 +153,15 @@ class DbAzService : IAzService
if (record != null)
{
UserDbContext.Acl.Remove(record);
UserDbContext.SaveChanges();
userDbContext.Acl.Remove(record);
userDbContext.SaveChanges();
}
}
private void InsertRecord(AzRecord r)
{
UserDbContext.AddOrUpdate(r => r.Acl, _mapper.Map<AzRecord, Acl>(r));
UserDbContext.SaveChanges();
using var userDbContext = _dbContextFactory.CreateDbContext();
userDbContext.AddOrUpdate(r => r.Acl, _mapper.Map<AzRecord, Acl>(r));
userDbContext.SaveChanges();
}
}

View File

@ -26,51 +26,30 @@
namespace ASC.Core.Data;
[Scope]
class ConfigureDbQuotaService : IConfigureNamedOptions<DbQuotaService>
{
private readonly DbContextManager<CoreDbContext> _dbContextManager;
public string DbId { get; set; }
public ConfigureDbQuotaService(DbContextManager<CoreDbContext> dbContextManager)
{
_dbContextManager = dbContextManager;
}
public void Configure(string name, DbQuotaService options)
{
options.LazyCoreDbContext = new Lazy<CoreDbContext>(() => _dbContextManager.Get(name));
}
public void Configure(DbQuotaService options)
{
options.LazyCoreDbContext = new Lazy<CoreDbContext>(() => _dbContextManager.Value);
}
}
[Scope]
class DbQuotaService : IQuotaService
{
internal CoreDbContext CoreDbContext => LazyCoreDbContext.Value;
internal Lazy<CoreDbContext> LazyCoreDbContext;
private readonly IDbContextFactory<CoreDbContext> _dbContextFactory;
private readonly IMapper _mapper;
public DbQuotaService(DbContextManager<CoreDbContext> dbContextManager, IMapper mapper)
public DbQuotaService(IDbContextFactory<CoreDbContext> dbContextManager, IMapper mapper)
{
LazyCoreDbContext = new Lazy<CoreDbContext>(() => dbContextManager.Value);
_dbContextFactory = dbContextManager;
_mapper = mapper;
}
public IEnumerable<TenantQuota> GetTenantQuotas()
{
return CoreDbContext.Quotas
using var coreDbContext = _dbContextFactory.CreateDbContext();
return coreDbContext.Quotas
.ProjectTo<TenantQuota>(_mapper.ConfigurationProvider)
.ToList();
}
public TenantQuota GetTenantQuota(int id)
{
return CoreDbContext.Quotas
using var coreDbContext = _dbContextFactory.CreateDbContext();
return coreDbContext.Quotas
.Where(r => r.Tenant == id)
.ProjectTo<TenantQuota>(_mapper.ConfigurationProvider)
.SingleOrDefault();
@ -80,27 +59,30 @@ class DbQuotaService : IQuotaService
{
ArgumentNullException.ThrowIfNull(quota);
CoreDbContext.AddOrUpdate(r => r.Quotas, _mapper.Map<TenantQuota, DbQuota>(quota));
CoreDbContext.SaveChanges();
using var coreDbContext = _dbContextFactory.CreateDbContext();
coreDbContext.AddOrUpdate(r => r.Quotas, _mapper.Map<TenantQuota, DbQuota>(quota));
coreDbContext.SaveChanges();
return quota;
}
public void RemoveTenantQuota(int id)
{
var strategy = CoreDbContext.Database.CreateExecutionStrategy();
using var coreDbContext = _dbContextFactory.CreateDbContext();
var strategy = coreDbContext.Database.CreateExecutionStrategy();
strategy.Execute(() =>
{
using var tr = CoreDbContext.Database.BeginTransaction();
var d = CoreDbContext.Quotas
using var coreDbContext = _dbContextFactory.CreateDbContext();
using var tr = coreDbContext.Database.BeginTransaction();
var d = coreDbContext.Quotas
.Where(r => r.Tenant == id)
.SingleOrDefault();
if (d != null)
{
CoreDbContext.Quotas.Remove(d);
CoreDbContext.SaveChanges();
coreDbContext.Quotas.Remove(d);
coreDbContext.SaveChanges();
}
tr.Commit();
@ -112,13 +94,15 @@ class DbQuotaService : IQuotaService
{
ArgumentNullException.ThrowIfNull(row);
var strategy = CoreDbContext.Database.CreateExecutionStrategy();
using var coreDbContext = _dbContextFactory.CreateDbContext();
var strategy = coreDbContext.Database.CreateExecutionStrategy();
strategy.Execute(() =>
{
using var tx = CoreDbContext.Database.BeginTransaction();
using var coreDbContext = _dbContextFactory.CreateDbContext();
using var tx = coreDbContext.Database.BeginTransaction();
var counter = CoreDbContext.QuotaRows
var counter = coreDbContext.QuotaRows
.Where(r => r.Path == row.Path && r.Tenant == row.Tenant)
.Select(r => r.Counter)
.Take(1)
@ -128,8 +112,8 @@ class DbQuotaService : IQuotaService
dbQuotaRow.Counter = exchange ? counter + row.Counter : row.Counter;
dbQuotaRow.LastModified = DateTime.UtcNow;
CoreDbContext.AddOrUpdate(r => r.QuotaRows, dbQuotaRow);
CoreDbContext.SaveChanges();
coreDbContext.AddOrUpdate(r => r.QuotaRows, dbQuotaRow);
coreDbContext.SaveChanges();
tx.Commit();
});
@ -137,7 +121,8 @@ class DbQuotaService : IQuotaService
public IEnumerable<TenantQuotaRow> FindTenantQuotaRows(int tenantId)
{
IQueryable<DbQuotaRow> q = CoreDbContext.QuotaRows;
using var coreDbContext = _dbContextFactory.CreateDbContext();
IQueryable<DbQuotaRow> q = coreDbContext.QuotaRows;
if (tenantId != Tenant.DefaultTenant)
{

View File

@ -48,67 +48,17 @@ public class DbSettingsManagerCache
}
[Scope]
class ConfigureDbSettingsManager : IConfigureNamedOptions<DbSettingsManager>
{
private readonly IServiceProvider _serviceProvider;
private readonly DbSettingsManagerCache _dbSettingsManagerCache;
private readonly ILogger<DbSettingsManager> _logger;
private readonly AuthContext _authContext;
private readonly IOptionsSnapshot<TenantManager> _tenantManager;
private readonly DbContextManager<WebstudioDbContext> _dbContextManager;
public ConfigureDbSettingsManager(
IServiceProvider serviceProvider,
DbSettingsManagerCache dbSettingsManagerCache,
ILogger<DbSettingsManager> iLog,
AuthContext authContext,
IOptionsSnapshot<TenantManager> tenantManager,
DbContextManager<WebstudioDbContext> dbContextManager
)
{
_serviceProvider = serviceProvider;
_dbSettingsManagerCache = dbSettingsManagerCache;
_logger = iLog;
_authContext = authContext;
_tenantManager = tenantManager;
_dbContextManager = dbContextManager;
}
public void Configure(string name, DbSettingsManager options)
{
Configure(options);
options.TenantManager = _tenantManager.Get(name);
options.LazyWebstudioDbContext = new Lazy<WebstudioDbContext>(() => _dbContextManager.Get(name));
}
public void Configure(DbSettingsManager options)
{
options.ServiceProvider = _serviceProvider;
options.DbSettingsManagerCache = _dbSettingsManagerCache;
options.AuthContext = _authContext;
options.Logger = _logger;
options.TenantManager = _tenantManager.Value;
options.LazyWebstudioDbContext = new Lazy<WebstudioDbContext>(() => _dbContextManager.Value);
}
}
[Scope(typeof(ConfigureDbSettingsManager))]
public class DbSettingsManager
{
private readonly TimeSpan _expirationTimeout = TimeSpan.FromMinutes(5);
internal ILogger<DbSettingsManager> Logger { get; set; }
internal ICache Cache { get; set; }
internal IServiceProvider ServiceProvider { get; set; }
internal DbSettingsManagerCache DbSettingsManagerCache { get; set; }
internal AuthContext AuthContext { get; set; }
internal TenantManager TenantManager { get; set; }
internal Lazy<WebstudioDbContext> LazyWebstudioDbContext;
internal WebstudioDbContext WebstudioDbContext => LazyWebstudioDbContext.Value;
public DbSettingsManager() { }
private readonly ILogger<DbSettingsManager> _logger;
private readonly ICache _cache;
private readonly IServiceProvider _serviceProvider;
private readonly DbSettingsManagerCache _dbSettingsManagerCache;
private readonly AuthContext _authContext;
private readonly TenantManager _tenantManager;
private readonly IDbContextFactory<WebstudioDbContext> _dbContextFactory;
public DbSettingsManager(
IServiceProvider serviceProvider,
@ -116,15 +66,15 @@ public class DbSettingsManager
ILogger<DbSettingsManager> logger,
AuthContext authContext,
TenantManager tenantManager,
DbContextManager<WebstudioDbContext> dbContextManager)
IDbContextFactory<WebstudioDbContext> dbContextFactory)
{
ServiceProvider = serviceProvider;
DbSettingsManagerCache = dbSettingsManagerCache;
AuthContext = authContext;
TenantManager = tenantManager;
Cache = dbSettingsManagerCache.Cache;
Logger = logger;
LazyWebstudioDbContext = new Lazy<WebstudioDbContext>(() => dbContextManager.Value);
_serviceProvider = serviceProvider;
_dbSettingsManagerCache = dbSettingsManagerCache;
_authContext = authContext;
_tenantManager = tenantManager;
_dbContextFactory = dbContextFactory;
_cache = dbSettingsManagerCache.Cache;
_logger = logger;
}
private int _tenantID;
@ -134,7 +84,7 @@ public class DbSettingsManager
{
if (_tenantID == 0)
{
_tenantID = TenantManager.GetCurrentTenant().Id;
_tenantID = _tenantManager.GetCurrentTenant().Id;
}
return _tenantID;
@ -146,7 +96,7 @@ public class DbSettingsManager
{
get
{
_currentUserID ??= AuthContext.CurrentAccount.ID;
_currentUserID ??= _authContext.CurrentAccount.ID;
return _currentUserID.Value;
}
@ -167,7 +117,7 @@ public class DbSettingsManager
var settings = LoadSettings<T>(tenantId);
var key = settings.ID.ToString() + tenantId + Guid.Empty;
DbSettingsManagerCache.Remove(key);
_dbSettingsManagerCache.Remove(key);
}
@ -175,6 +125,8 @@ public class DbSettingsManager
{
ArgumentNullException.ThrowIfNull(settings);
using var webstudioDbContext = _dbContextFactory.CreateDbContext();
try
{
var key = settings.ID.ToString() + tenantId + userId;
@ -185,13 +137,13 @@ public class DbSettingsManager
if (data.SequenceEqual(defaultData))
{
var strategy = WebstudioDbContext.Database.CreateExecutionStrategy();
var strategy = webstudioDbContext.Database.CreateExecutionStrategy();
strategy.Execute(() =>
{
using var tr = WebstudioDbContext.Database.BeginTransaction();
using var tr = webstudioDbContext.Database.BeginTransaction();
// remove default settings
var s = WebstudioDbContext.WebstudioSettings
var s = webstudioDbContext.WebstudioSettings
.Where(r => r.Id == settings.ID)
.Where(r => r.TenantId == tenantId)
.Where(r => r.UserId == userId)
@ -199,10 +151,10 @@ public class DbSettingsManager
if (s != null)
{
WebstudioDbContext.WebstudioSettings.Remove(s);
webstudioDbContext.WebstudioSettings.Remove(s);
}
WebstudioDbContext.SaveChanges();
webstudioDbContext.SaveChanges();
tr.Commit();
});
@ -220,20 +172,20 @@ public class DbSettingsManager
Data = data
};
WebstudioDbContext.AddOrUpdate(r => r.WebstudioSettings, s);
webstudioDbContext.AddOrUpdate(r => r.WebstudioSettings, s);
WebstudioDbContext.SaveChanges();
webstudioDbContext.SaveChanges();
}
DbSettingsManagerCache.Remove(key);
_dbSettingsManagerCache.Remove(key);
Cache.Insert(key, settings, _expirationTimeout);
_cache.Insert(key, settings, _expirationTimeout);
return true;
}
catch (Exception ex)
{
Logger.ErrorSaveSettingsFor(ex);
_logger.ErrorSaveSettingsFor(ex);
return false;
}
@ -246,13 +198,14 @@ public class DbSettingsManager
try
{
var settings = Cache.Get<T>(key);
var settings = _cache.Get<T>(key);
if (settings != null)
{
return settings;
}
var result = WebstudioDbContext.WebstudioSettings
using var webstudioDbContext = _dbContextFactory.CreateDbContext();
var result = webstudioDbContext.WebstudioSettings
.Where(r => r.Id == def.ID)
.Where(r => r.TenantId == tenantId)
.Where(r => r.UserId == userId)
@ -268,13 +221,13 @@ public class DbSettingsManager
settings = def;
}
Cache.Insert(key, settings, _expirationTimeout);
_cache.Insert(key, settings, _expirationTimeout);
return settings;
}
catch (Exception ex)
{
Logger.ErrorLoadSettingsFor(ex);
_logger.ErrorLoadSettingsFor(ex);
}
return def;
@ -282,7 +235,7 @@ public class DbSettingsManager
public T GetDefault<T>() where T : class, ISettings<T>
{
var settingsInstance = ActivatorUtilities.CreateInstance<T>(ServiceProvider);
var settingsInstance = ActivatorUtilities.CreateInstance<T>(_serviceProvider);
return settingsInstance.GetDefault();
}

View File

@ -29,13 +29,12 @@ namespace ASC.Core.Data;
[Scope]
public class DbSubscriptionService : ISubscriptionService
{
private readonly Lazy<UserDbContext> _lazyUserDbContext;
private UserDbContext UserDbContext => _lazyUserDbContext.Value;
private readonly IDbContextFactory<UserDbContext> _dbContextFactory;
private readonly IMapper _mapper;
public DbSubscriptionService(DbContextManager<UserDbContext> dbContextManager, IMapper mapper)
public DbSubscriptionService(IDbContextFactory<UserDbContext> dbContextFactory, IMapper mapper)
{
_lazyUserDbContext = new Lazy<UserDbContext>(() => dbContextManager.Value);
_dbContextFactory = dbContextFactory;
_mapper = mapper;
}
@ -44,7 +43,8 @@ public class DbSubscriptionService : ISubscriptionService
ArgumentNullException.ThrowIfNull(sourceId);
ArgumentNullException.ThrowIfNull(actionId);
var q = GetQuery(tenant, sourceId, actionId)
using var userDbContext = _dbContextFactory.CreateDbContext();
var q = GetQuery(userDbContext, tenant, sourceId, actionId)
.Where(r => r.Object == (objectId ?? string.Empty))
.Where(r => !r.Unsubscribed)
.Select(r => r.Recipient)
@ -58,14 +58,18 @@ public class DbSubscriptionService : ISubscriptionService
ArgumentNullException.ThrowIfNull(sourceId);
ArgumentNullException.ThrowIfNull(actionId);
var q = GetQuery(tenant, sourceId, actionId);
using var userDbContext = _dbContextFactory.CreateDbContext();
var q = GetQuery(userDbContext, tenant, sourceId, actionId);
return GetSubscriptions(q, tenant);
}
public IEnumerable<SubscriptionRecord> GetSubscriptions(int tenant, string sourceId, string actionId, string recipientId, string objectId)
{
var q = GetQuery(tenant, sourceId, actionId);
using var userDbContext = _dbContextFactory.CreateDbContext();
var q = GetQuery(userDbContext, tenant, sourceId, actionId);
if (recipientId != null)
{
@ -83,7 +87,9 @@ public class DbSubscriptionService : ISubscriptionService
{
ArgumentNullException.ThrowIfNull(recipientId);
var q = GetQuery(tenant, sourceId, actionId)
using var userDbContext = _dbContextFactory.CreateDbContext();
var q = GetQuery(userDbContext, tenant, sourceId, actionId)
.Where(r => r.Recipient == recipientId)
.Where(r => r.Object == (objectId ?? string.Empty));
@ -96,7 +102,8 @@ public class DbSubscriptionService : ISubscriptionService
ArgumentNullException.ThrowIfNull(sourceId);
ArgumentNullException.ThrowIfNull(actionId);
var q = UserDbContext.Subscriptions
using var userDbContext = _dbContextFactory.CreateDbContext();
var q = userDbContext.Subscriptions
.Where(r => r.Source == sourceId &&
r.Action == actionId &&
r.Tenant == tenant &&
@ -121,7 +128,9 @@ public class DbSubscriptionService : ISubscriptionService
ArgumentNullException.ThrowIfNull(sourceId);
ArgumentNullException.ThrowIfNull(actionId);
var q = GetQuery(tenant, sourceId, actionId)
using var userDbContext = _dbContextFactory.CreateDbContext();
var q = GetQuery(userDbContext, tenant, sourceId, actionId)
.Where(r => r.Recipient == recipientId)
.Distinct();
@ -148,8 +157,9 @@ public class DbSubscriptionService : ISubscriptionService
Tenant = s.Tenant
};
UserDbContext.AddOrUpdate(r => r.Subscriptions, subs);
UserDbContext.SaveChanges();
using var userDbContext = _dbContextFactory.CreateDbContext();
userDbContext.AddOrUpdate(r => r.Subscriptions, subs);
userDbContext.SaveChanges();
}
public void RemoveSubscriptions(int tenant, string sourceId, string actionId)
@ -162,12 +172,14 @@ public class DbSubscriptionService : ISubscriptionService
ArgumentNullException.ThrowIfNull(sourceId);
ArgumentNullException.ThrowIfNull(actionId);
var strategy = UserDbContext.Database.CreateExecutionStrategy();
using var userDbContext = _dbContextFactory.CreateDbContext();
var strategy = userDbContext.Database.CreateExecutionStrategy();
strategy.Execute(() =>
{
using var tr = UserDbContext.Database.BeginTransaction();
var q = UserDbContext.Subscriptions
using var userDbContext = _dbContextFactory.CreateDbContext();
using var tr = userDbContext.Database.BeginTransaction();
var q = userDbContext.Subscriptions
.Where(r => r.Tenant == tenant)
.Where(r => r.Source == sourceId)
.Where(r => r.Action == actionId);
@ -181,7 +193,7 @@ public class DbSubscriptionService : ISubscriptionService
if (sub != null)
{
UserDbContext.Subscriptions.Remove(sub);
userDbContext.Subscriptions.Remove(sub);
}
tr.Commit();
@ -194,7 +206,8 @@ public class DbSubscriptionService : ISubscriptionService
ArgumentNullException.ThrowIfNull(sourceId);
ArgumentNullException.ThrowIfNull(actionId);
var q = UserDbContext.SubscriptionMethods
using var userDbContext = _dbContextFactory.CreateDbContext();
var q = userDbContext.SubscriptionMethods
.Where(r => r.Tenant == -1 || r.Tenant == tenant)
.Where(r => r.Source == sourceId);
@ -237,15 +250,17 @@ public class DbSubscriptionService : ISubscriptionService
{
ArgumentNullException.ThrowIfNull(m);
var strategy = UserDbContext.Database.CreateExecutionStrategy();
using var userDbContext = _dbContextFactory.CreateDbContext();
var strategy = userDbContext.Database.CreateExecutionStrategy();
strategy.Execute(() =>
{
using var tr = UserDbContext.Database.BeginTransaction();
using var userDbContext = _dbContextFactory.CreateDbContext();
using var tr = userDbContext.Database.BeginTransaction();
if (m.Methods == null || m.Methods.Length == 0)
{
var q = UserDbContext.SubscriptionMethods
var q = userDbContext.SubscriptionMethods
.Where(r => r.Tenant == m.Tenant)
.Where(r => r.Source == m.Source)
.Where(r => r.Recipient == m.Recipient)
@ -255,7 +270,7 @@ public class DbSubscriptionService : ISubscriptionService
if (sm != null)
{
UserDbContext.SubscriptionMethods.Remove(sm);
userDbContext.SubscriptionMethods.Remove(sm);
}
}
else
@ -268,26 +283,22 @@ public class DbSubscriptionService : ISubscriptionService
Tenant = m.Tenant,
Sender = string.Join("|", m.Methods)
};
UserDbContext.AddOrUpdate(r => r.SubscriptionMethods, sm);
userDbContext.AddOrUpdate(r => r.SubscriptionMethods, sm);
}
UserDbContext.SaveChanges();
userDbContext.SaveChanges();
tr.Commit();
});
}
private IQueryable<Subscription> GetQuery(int tenant, string sourceId, string actionId)
private IQueryable<Subscription> GetQuery(UserDbContext userDbContext, int tenant, string sourceId, string actionId)
{
ArgumentNullException.ThrowIfNull(sourceId);
ArgumentNullException.ThrowIfNull(actionId);
return
UserDbContext.Subscriptions
userDbContext.Subscriptions
.Where(r => r.Source == sourceId)
.Where(r => r.Action == actionId)
.Where(r => r.Tenant == -1 || r.Tenant == tenant)

View File

@ -26,56 +26,26 @@
namespace ASC.Core.Data;
[Scope]
public class ConfigureDbTenantService : IConfigureNamedOptions<DbTenantService>
{
private readonly TenantDomainValidator _tenantDomainValidator;
private readonly DbContextManager<TenantDbContext> _dbContextManager;
public ConfigureDbTenantService(
TenantDomainValidator tenantDomainValidator,
DbContextManager<TenantDbContext> dbContextManager)
{
_tenantDomainValidator = tenantDomainValidator;
_dbContextManager = dbContextManager;
}
public void Configure(string name, DbTenantService options)
{
Configure(options);
options.LazyTenantDbContext = new Lazy<TenantDbContext>(() => _dbContextManager.Get(name));
}
public void Configure(DbTenantService options)
{
options.TenantDomainValidator = _tenantDomainValidator;
options.LazyTenantDbContext = new Lazy<TenantDbContext>(() => _dbContextManager.Value);
}
}
[Scope]
public class DbTenantService : ITenantService
{
internal TenantDomainValidator TenantDomainValidator { get; set; }
internal TenantDbContext TenantDbContext => LazyTenantDbContext.Value;
internal UserDbContext UserDbContext => LazyUserDbContext.Value;
internal Lazy<TenantDbContext> LazyTenantDbContext;
internal Lazy<UserDbContext> LazyUserDbContext;
private readonly TenantDomainValidator _tenantDomainValidator;
private readonly IDbContextFactory<TenantDbContext> _dbContextFactory;
private readonly IDbContextFactory<UserDbContext> _userDbContextFactory;
private readonly IMapper _mapper;
private readonly MachinePseudoKeys _machinePseudoKeys;
private List<string> _forbiddenDomains;
public DbTenantService(
DbContextManager<TenantDbContext> dbContextManager,
DbContextManager<UserDbContext> DbContextManager,
IDbContextFactory<TenantDbContext> dbContextFactory,
IDbContextFactory<UserDbContext> userDbContextFactory,
TenantDomainValidator tenantDomainValidator,
MachinePseudoKeys machinePseudoKeys,
IMapper mapper)
{
LazyTenantDbContext = new Lazy<TenantDbContext>(() => dbContextManager.Value);
LazyUserDbContext = new Lazy<UserDbContext>(() => DbContextManager.Value);
TenantDomainValidator = tenantDomainValidator;
_dbContextFactory = dbContextFactory;
_userDbContextFactory = userDbContextFactory;
_tenantDomainValidator = tenantDomainValidator;
_machinePseudoKeys = machinePseudoKeys;
_mapper = mapper;
}
@ -89,7 +59,8 @@ public class DbTenantService : ITenantService
public IEnumerable<Tenant> GetTenants(DateTime from, bool active = true)
{
var q = TenantsQuery();
using var tenantDbContext = _dbContextFactory.CreateDbContext();
var q = tenantDbContext.Tenants.AsQueryable();
if (active)
{
@ -106,24 +77,28 @@ public class DbTenantService : ITenantService
public IEnumerable<Tenant> GetTenants(List<int> ids)
{
var q = TenantsQuery();
using var tenantDbContext = _dbContextFactory.CreateDbContext();
return q.Where(r => ids.Contains(r.Id) && r.Status == TenantStatus.Active)
.ProjectTo<Tenant>(_mapper.ConfigurationProvider).ToList();
return tenantDbContext.Tenants
.Where(r => ids.Contains(r.Id) && r.Status == TenantStatus.Active)
.ProjectTo<Tenant>(_mapper.ConfigurationProvider)
.ToList();
}
public IEnumerable<Tenant> GetTenants(string login, string passwordHash)
{
ArgumentNullOrEmptyException.ThrowIfNullOrEmpty(login);
IQueryable<TenantUserSecurity> query() => TenantsQuery()
using var tenantDbContext = _dbContextFactory.CreateDbContext();
using var userDbContext = _userDbContextFactory.CreateDbContext();//TODO: remove
IQueryable<TenantUserSecurity> query() => tenantDbContext.Tenants
.Where(r => r.Status == TenantStatus.Active)
.Join(UserDbContext.Users, r => r.Id, r => r.Tenant, (tenant, user) => new
.Join(userDbContext.Users, r => r.Id, r => r.Tenant, (tenant, user) => new
{
tenant,
user
})
.Join(UserDbContext.UserSecurity, r => r.user.Id, r => r.UserId, (tenantUser, security) => new TenantUserSecurity
.Join(userDbContext.UserSecurity, r => r.user.Id, r => r.UserId, (tenantUser, security) => new TenantUserSecurity
{
DbTenant = tenantUser.tenant,
User = tenantUser.user,
@ -154,7 +129,7 @@ public class DbTenantService : ITenantService
}
else
{
var usersQuery = UserDbContext.Users
var usersQuery = userDbContext.Users
.Where(r => r.Email == login)
.Where(r => r.Status == EmployeeStatus.Active)
.Where(r => !r.Removed)
@ -172,7 +147,8 @@ public class DbTenantService : ITenantService
public Tenant GetTenant(int id)
{
return TenantsQuery()
using var tenantDbContext = _dbContextFactory.CreateDbContext();
return tenantDbContext.Tenants
.Where(r => r.Id == id)
.ProjectTo<Tenant>(_mapper.ConfigurationProvider)
.SingleOrDefault();
@ -184,7 +160,9 @@ public class DbTenantService : ITenantService
domain = domain.ToLowerInvariant();
return TenantsQuery()
using var tenantDbContext = _dbContextFactory.CreateDbContext();
return tenantDbContext.Tenants
.Where(r => r.Alias == domain || r.MappedDomain == domain)
.OrderBy(a => a.Status == TenantStatus.Restoring ? TenantStatus.Active : a.Status)
.ThenByDescending(a => a.Status == TenantStatus.Restoring ? 0 : a.Id)
@ -194,7 +172,9 @@ public class DbTenantService : ITenantService
public Tenant GetTenantForStandaloneWithoutAlias(string ip)
{
return TenantsQuery()
using var tenantDbContext = _dbContextFactory.CreateDbContext();
return tenantDbContext.Tenants
.OrderBy(a => a.Status)
.ThenByDescending(a => a.Id)
.ProjectTo<Tenant>(_mapper.ConfigurationProvider)
@ -205,11 +185,13 @@ public class DbTenantService : ITenantService
{
ArgumentNullException.ThrowIfNull(tenant);
var strategy = TenantDbContext.Database.CreateExecutionStrategy();
using var tenantDbContext = _dbContextFactory.CreateDbContext();
var strategy = tenantDbContext.Database.CreateExecutionStrategy();
strategy.Execute(() =>
{
using var tx = TenantDbContext.Database.BeginTransaction();
using var tenantDbContext = _dbContextFactory.CreateDbContext();
using var tx = tenantDbContext.Database.BeginTransaction();
if (!string.IsNullOrEmpty(tenant.MappedDomain))
{
@ -227,7 +209,7 @@ public class DbTenantService : ITenantService
if (tenant.Id == Tenant.DefaultTenant)
{
tenant.Version = TenantDbContext.TenantVersion
tenant.Version = tenantDbContext.TenantVersion
.Where(r => r.DefaultVersion == 1 || r.Id == 0)
.OrderByDescending(r => r.Id)
.Select(r => r.Id)
@ -237,13 +219,13 @@ public class DbTenantService : ITenantService
var dbTenant = _mapper.Map<Tenant, DbTenant>(tenant);
dbTenant = TenantDbContext.Tenants.Add(dbTenant).Entity;
TenantDbContext.SaveChanges();
dbTenant = tenantDbContext.Tenants.Add(dbTenant).Entity;
tenantDbContext.SaveChanges();
tenant.Id = dbTenant.Id;
}
else
{
var dbTenant = TenantDbContext.Tenants
var dbTenant = tenantDbContext.Tenants
.Where(r => r.Id == tenant.Id)
.FirstOrDefault();
@ -268,18 +250,18 @@ public class DbTenantService : ITenantService
dbTenant.Calls = tenant.Calls;
}
TenantDbContext.SaveChanges();
tenantDbContext.SaveChanges();
}
if (string.IsNullOrEmpty(tenant.PartnerId) && string.IsNullOrEmpty(tenant.AffiliateId) && string.IsNullOrEmpty(tenant.Campaign))
{
var p = TenantDbContext.TenantPartner
var p = tenantDbContext.TenantPartner
.Where(r => r.TenantId == tenant.Id)
.FirstOrDefault();
if (p != null)
{
TenantDbContext.TenantPartner.Remove(p);
tenantDbContext.TenantPartner.Remove(p);
}
}
else
@ -292,7 +274,7 @@ public class DbTenantService : ITenantService
Campaign = tenant.Campaign
};
TenantDbContext.TenantPartner.Add(tenantPartner);
tenantDbContext.TenantPartner.Add(tenantPartner);
}
tx.Commit();
@ -306,22 +288,24 @@ public class DbTenantService : ITenantService
{
var postfix = auto ? "_auto_deleted" : "_deleted";
var strategy = TenantDbContext.Database.CreateExecutionStrategy();
using var tenantDbContext = _dbContextFactory.CreateDbContext();
var strategy = tenantDbContext.Database.CreateExecutionStrategy();
strategy.Execute(() =>
{
using var tx = TenantDbContext.Database.BeginTransaction();
using var tenantDbContext = _dbContextFactory.CreateDbContext();
using var tx = tenantDbContext.Database.BeginTransaction();
var alias = TenantDbContext.Tenants
var alias = tenantDbContext.Tenants
.Where(r => r.Id == id)
.Select(r => r.Alias)
.FirstOrDefault();
var count = TenantDbContext.Tenants
var count = tenantDbContext.Tenants
.Where(r => r.Alias.StartsWith(alias + postfix))
.Count();
var tenant = TenantDbContext.Tenants.Where(r => r.Id == id).FirstOrDefault();
var tenant = tenantDbContext.Tenants.Where(r => r.Id == id).FirstOrDefault();
if (tenant != null)
{
@ -331,7 +315,7 @@ public class DbTenantService : ITenantService
tenant.LastModified = DateTime.UtcNow;
}
TenantDbContext.SaveChanges();
tenantDbContext.SaveChanges();
tx.Commit();
});
@ -339,7 +323,8 @@ public class DbTenantService : ITenantService
public IEnumerable<TenantVersion> GetTenantVersions()
{
return TenantDbContext.TenantVersion
using var tenantDbContext = _dbContextFactory.CreateDbContext();
return tenantDbContext.TenantVersion
.Where(r => r.Visible)
.Select(r => new TenantVersion(r.Id, r.Version))
.ToList();
@ -348,7 +333,8 @@ public class DbTenantService : ITenantService
public byte[] GetTenantSettings(int tenant, string key)
{
return TenantDbContext.CoreSettings
using var tenantDbContext = _dbContextFactory.CreateDbContext();
return tenantDbContext.CoreSettings
.Where(r => r.Tenant == tenant)
.Where(r => r.Id == key)
.Select(r => r.Value)
@ -357,22 +343,24 @@ public class DbTenantService : ITenantService
public void SetTenantSettings(int tenant, string key, byte[] data)
{
var strategy = TenantDbContext.Database.CreateExecutionStrategy();
using var tenantDbContext = _dbContextFactory.CreateDbContext();
var strategy = tenantDbContext.Database.CreateExecutionStrategy();
strategy.Execute(() =>
{
using var tx = TenantDbContext.Database.BeginTransaction();
using var tenantDbContext = _dbContextFactory.CreateDbContext();
using var tx = tenantDbContext.Database.BeginTransaction();
if (data == null || data.Length == 0)
{
var settings = TenantDbContext.CoreSettings
var settings = tenantDbContext.CoreSettings
.Where(r => r.Tenant == tenant)
.Where(r => r.Id == key)
.FirstOrDefault();
if (settings != null)
{
TenantDbContext.CoreSettings.Remove(settings);
tenantDbContext.CoreSettings.Remove(settings);
}
}
else
@ -385,23 +373,18 @@ public class DbTenantService : ITenantService
LastModified = DateTime.UtcNow
};
TenantDbContext.AddOrUpdate(r => r.CoreSettings, settings);
tenantDbContext.AddOrUpdate(r => r.CoreSettings, settings);
}
TenantDbContext.SaveChanges();
tenantDbContext.SaveChanges();
tx.Commit();
});
}
private IQueryable<DbTenant> TenantsQuery()
{
return TenantDbContext.Tenants;
}
private void ValidateDomain(string domain, int tenantId, bool validateCharacters)
{
// size
TenantDomainValidator.ValidateDomainLength(domain);
_tenantDomainValidator.ValidateDomainLength(domain);
// characters
if (validateCharacters)
@ -409,24 +392,25 @@ public class DbTenantService : ITenantService
TenantDomainValidator.ValidateDomainCharacters(domain);
}
using var tenantDbContext = _dbContextFactory.CreateDbContext();
// forbidden or exists
var exists = false;
domain = domain.ToLowerInvariant();
if (_forbiddenDomains == null)
{
_forbiddenDomains = TenantDbContext.TenantForbiden.Select(r => r.Address).ToList();
_forbiddenDomains = tenantDbContext.TenantForbiden.Select(r => r.Address).ToList();
}
exists = tenantId != 0 && _forbiddenDomains.Contains(domain);
if (!exists)
{
exists = TenantDbContext.Tenants.Where(r => r.Alias == domain && r.Id != tenantId).Any();
exists = tenantDbContext.Tenants.Where(r => r.Alias == domain && r.Id != tenantId).Any();
}
if (!exists)
{
exists = TenantDbContext.Tenants
exists = tenantDbContext.Tenants
.Where(r => r.MappedDomain == domain && r.Id != tenantId && !(r.Status == TenantStatus.RemovePending || r.Status == TenantStatus.Restoring))
.Any();
}
@ -435,7 +419,7 @@ public class DbTenantService : ITenantService
// cut number suffix
while (true)
{
if (TenantDomainValidator.MinLength < domain.Length && char.IsNumber(domain, domain.Length - 1))
if (_tenantDomainValidator.MinLength < domain.Length && char.IsNumber(domain, domain.Length - 1))
{
domain = domain[0..^1];
}
@ -445,9 +429,9 @@ public class DbTenantService : ITenantService
}
}
var existsTenants = TenantDbContext.TenantForbiden.Where(r => r.Address.StartsWith(domain)).Select(r => r.Address)
.Union(TenantDbContext.Tenants.Where(r => r.Alias.StartsWith(domain) && r.Id != tenantId).Select(r => r.Alias))
.Union(TenantDbContext.Tenants.Where(r => r.MappedDomain.StartsWith(domain) && r.Id != tenantId && r.Status != TenantStatus.RemovePending).Select(r => r.MappedDomain));
var existsTenants = tenantDbContext.TenantForbiden.Where(r => r.Address.StartsWith(domain)).Select(r => r.Address)
.Union(tenantDbContext.Tenants.Where(r => r.Alias.StartsWith(domain) && r.Id != tenantId).Select(r => r.Alias))
.Union(tenantDbContext.Tenants.Where(r => r.MappedDomain.StartsWith(domain) && r.Id != tenantId && r.Status != TenantStatus.RemovePending).Select(r => r.MappedDomain));
throw new TenantAlreadyExistsException("Address busy.", existsTenants);
}

View File

@ -26,57 +26,27 @@
namespace ASC.Core.Data;
[Scope]
public class ConfigureEFUserService : IConfigureNamedOptions<EFUserService>
{
private readonly DbContextManager<UserDbContext> _dbContextManager;
public ConfigureEFUserService(DbContextManager<UserDbContext> dbContextManager)
{
_dbContextManager = dbContextManager;
}
public void Configure(string name, EFUserService options)
{
options.DbId = name;
options.LazyUserDbContext = new Lazy<UserDbContext>(() => _dbContextManager.Get(name));
options.UserDbContextManager = _dbContextManager;
}
public void Configure(EFUserService options)
{
options.LazyUserDbContext = new Lazy<UserDbContext>(() => _dbContextManager.Value);
options.UserDbContextManager = _dbContextManager;
}
}
[Scope]
public class EFUserService : IUserService
{
internal UserDbContext UserDbContext => LazyUserDbContext.Value;
internal Lazy<UserDbContext> LazyUserDbContext;
internal DbContextManager<UserDbContext> UserDbContextManager;
private readonly PasswordHasher _passwordHasher;
public readonly MachinePseudoKeys MachinePseudoKeys;
internal string DbId { get; set; }
private readonly IDbContextFactory<UserDbContext> _dbContextFactory;
private readonly MachinePseudoKeys _machinePseudoKeys;
private readonly IMapper _mapper;
public EFUserService(
DbContextManager<UserDbContext> userDbContextManager,
PasswordHasher passwordHasher,
IDbContextFactory<UserDbContext> dbContextFactory,
MachinePseudoKeys machinePseudoKeys,
IMapper mapper)
{
UserDbContextManager = userDbContextManager;
_passwordHasher = passwordHasher;
MachinePseudoKeys = machinePseudoKeys;
LazyUserDbContext = new Lazy<UserDbContext>(() => UserDbContextManager.Value);
_dbContextFactory = dbContextFactory;
_machinePseudoKeys = machinePseudoKeys;
_mapper = mapper;
}
public Group GetGroup(int tenant, Guid id)
{
return GetGroupQuery(tenant)
using var userDbContext = _dbContextFactory.CreateDbContext();
return GetGroupQuery(userDbContext, tenant)
.Where(r => r.Id == id)
.ProjectTo<Group>(_mapper.ConfigurationProvider)
.FirstOrDefault();
@ -84,14 +54,16 @@ public class EFUserService : IUserService
public IEnumerable<Group> GetGroups(int tenant)
{
return GetGroupQuery(tenant)
using var userDbContext = _dbContextFactory.CreateDbContext();
return GetGroupQuery(userDbContext, tenant)
.ProjectTo<Group>(_mapper.ConfigurationProvider)
.ToList();
}
public UserInfo GetUser(int tenant, Guid id)
{
return GetUserQuery(tenant)
using var userDbContext = _dbContextFactory.CreateDbContext();
return GetUserQuery(userDbContext, tenant)
.Where(r => r.Id == id)
.ProjectTo<UserInfo>(_mapper.ConfigurationProvider)
.FirstOrDefault();
@ -99,14 +71,16 @@ public class EFUserService : IUserService
public UserInfo GetUser(int tenant, string email)
{
return GetUserQuery(tenant)
using var userDbContext = _dbContextFactory.CreateDbContext();
return GetUserQuery(userDbContext, tenant)
.ProjectTo<UserInfo>(_mapper.ConfigurationProvider)
.FirstOrDefault(r => r.Email == email && !r.Removed);
}
public UserInfo GetUserByUserName(int tenant, string userName)
{
return GetUserQuery(tenant)
using var userDbContext = _dbContextFactory.CreateDbContext();
return GetUserQuery(userDbContext, tenant)
.ProjectTo<UserInfo>(_mapper.ConfigurationProvider)
.FirstOrDefault(r => r.UserName == userName && !r.Removed);
}
@ -115,14 +89,15 @@ public class EFUserService : IUserService
{
ArgumentNullOrEmptyException.ThrowIfNullOrEmpty(login);
using var userDbContext = _dbContextFactory.CreateDbContext();
if (Guid.TryParse(login, out var userId))
{
var pwdHash = GetPasswordHash(userId, passwordHash);
var q = GetUserQuery(tenant)
var q = GetUserQuery(userDbContext, tenant)
.Where(r => !r.Removed)
.Where(r => r.Id == userId)
.Join(UserDbContext.UserSecurity, r => r.Id, r => r.UserId, (user, security) => new DbUserSecurity
.Join(userDbContext.UserSecurity, r => r.Id, r => r.UserId, (user, security) => new DbUserSecurity
{
User = user,
UserSecurity = security
@ -141,7 +116,7 @@ public class EFUserService : IUserService
}
else
{
var q = GetUserQuery(tenant)
var q = GetUserQuery(userDbContext, tenant)
.Where(r => !r.Removed)
.Where(r => r.Email == login);
@ -150,7 +125,7 @@ public class EFUserService : IUserService
{
var pwdHash = GetPasswordHash(user.Id, passwordHash);
var any = UserDbContext.UserSecurity
var any = userDbContext.UserSecurity
.Any(r => r.UserId == user.Id && (r.PwdHash == pwdHash));
if (any)
@ -165,7 +140,8 @@ public class EFUserService : IUserService
public IEnumerable<UserInfo> GetUsersAllTenants(IEnumerable<Guid> userIds)
{
var q = UserDbContext.Users
using var userDbContext = _dbContextFactory.CreateDbContext();
var q = userDbContext.Users
.Where(r => userIds.Contains(r.Id))
.Where(r => !r.Removed);
@ -174,7 +150,8 @@ public class EFUserService : IUserService
public UserGroupRef GetUserGroupRef(int tenant, Guid groupId, UserGroupRefType refType)
{
IQueryable<UserGroup> q = UserDbContext.UserGroups;
using var userDbContext = _dbContextFactory.CreateDbContext();
IQueryable<UserGroup> q = userDbContext.UserGroups;
if (tenant != Tenant.DefaultTenant)
{
@ -187,7 +164,8 @@ public class EFUserService : IUserService
public IDictionary<string, UserGroupRef> GetUserGroupRefs(int tenant)
{
IQueryable<UserGroup> q = UserDbContext.UserGroups;
using var userDbContext = _dbContextFactory.CreateDbContext();
IQueryable<UserGroup> q = userDbContext.UserGroups;
if (tenant != Tenant.DefaultTenant)
{
@ -200,7 +178,8 @@ public class EFUserService : IUserService
public DateTime GetUserPasswordStamp(int tenant, Guid id)
{
var stamp = UserDbContext.UserSecurity
using var userDbContext = _dbContextFactory.CreateDbContext();
var stamp = userDbContext.UserSecurity
.Where(r => r.Tenant == tenant)
.Where(r => r.UserId == id)
.Select(r => r.LastModified)
@ -211,7 +190,8 @@ public class EFUserService : IUserService
public byte[] GetUserPhoto(int tenant, Guid id)
{
var photo = UserDbContext.Photos
using var userDbContext = _dbContextFactory.CreateDbContext();
var photo = userDbContext.Photos
.Where(r => r.Tenant == tenant)
.Where(r => r.UserId == id)
.Select(r => r.Photo)
@ -222,21 +202,22 @@ public class EFUserService : IUserService
public IEnumerable<UserInfo> GetUsers(int tenant)
{
return GetUserQuery(tenant)
using var userDbContext = _dbContextFactory.CreateDbContext();
return GetUserQuery(userDbContext, tenant)
.ProjectTo<UserInfo>(_mapper.ConfigurationProvider)
.ToList();
}
public IQueryable<UserInfo> GetUsers(int tenant, bool isAdmin, EmployeeStatus? employeeStatus, List<List<Guid>> includeGroups, List<Guid> excludeGroups, EmployeeActivationStatus? activationStatus, string text, string sortBy, bool sortOrderAsc, long limit, long offset, out int total, out int count)
{
var userDbContext = UserDbContextManager.GetNew(DbId);
var userDbContext = _dbContextFactory.CreateDbContext();
var totalQuery = GetUserQuery(userDbContext, tenant);
totalQuery = GetUserQueryForFilter(totalQuery, isAdmin, employeeStatus, includeGroups, excludeGroups, activationStatus, text);
totalQuery = GetUserQueryForFilter(userDbContext, totalQuery, isAdmin, employeeStatus, includeGroups, excludeGroups, activationStatus, text);
total = totalQuery.Count();
var q = GetUserQuery(userDbContext, tenant);
q = GetUserQueryForFilter(q, isAdmin, employeeStatus, includeGroups, excludeGroups, activationStatus, text);
q = GetUserQueryForFilter(userDbContext, q, isAdmin, employeeStatus, includeGroups, excludeGroups, activationStatus, text);
if (!string.IsNullOrEmpty(sortBy))
{
@ -260,7 +241,7 @@ public class EFUserService : IUserService
public IQueryable<UserInfo> GetUsers(int tenant, out int total)
{
var userDbContext = UserDbContextManager.GetNew(DbId);
var userDbContext = _dbContextFactory.CreateDbContext();
total = userDbContext.Users.Count(r => r.Tenant == tenant);
return GetUserQuery(userDbContext, tenant)
@ -274,26 +255,28 @@ public class EFUserService : IUserService
public void RemoveGroup(int tenant, Guid id, bool immediate)
{
var ids = CollectGroupChilds(tenant, id);
using var userDbContext = _dbContextFactory.CreateDbContext();
var ids = CollectGroupChilds(userDbContext, tenant, id);
var stringIds = ids.Select(r => r.ToString()).ToList();
var strategy = UserDbContext.Database.CreateExecutionStrategy();
var strategy = userDbContext.Database.CreateExecutionStrategy();
strategy.Execute(() =>
{
using var tr = UserDbContext.Database.BeginTransaction();
using var userDbContext = _dbContextFactory.CreateDbContext();
using var tr = userDbContext.Database.BeginTransaction();
UserDbContext.Acl.RemoveRange(UserDbContext.Acl.Where(r => r.Tenant == tenant && ids.Any(i => i == r.Subject)));
UserDbContext.Subscriptions.RemoveRange(UserDbContext.Subscriptions.Where(r => r.Tenant == tenant && stringIds.Any(i => i == r.Recipient)));
UserDbContext.SubscriptionMethods.RemoveRange(UserDbContext.SubscriptionMethods.Where(r => r.Tenant == tenant && stringIds.Any(i => i == r.Recipient)));
userDbContext.Acl.RemoveRange(userDbContext.Acl.Where(r => r.Tenant == tenant && ids.Any(i => i == r.Subject)));
userDbContext.Subscriptions.RemoveRange(userDbContext.Subscriptions.Where(r => r.Tenant == tenant && stringIds.Any(i => i == r.Recipient)));
userDbContext.SubscriptionMethods.RemoveRange(userDbContext.SubscriptionMethods.Where(r => r.Tenant == tenant && stringIds.Any(i => i == r.Recipient)));
var userGroups = UserDbContext.UserGroups.Where(r => r.Tenant == tenant && ids.Any(i => i == r.UserGroupId));
var groups = UserDbContext.Groups.Where(r => r.Tenant == tenant && ids.Any(i => i == r.Id));
var userGroups = userDbContext.UserGroups.Where(r => r.Tenant == tenant && ids.Any(i => i == r.UserGroupId));
var groups = userDbContext.Groups.Where(r => r.Tenant == tenant && ids.Any(i => i == r.Id));
if (immediate)
{
UserDbContext.UserGroups.RemoveRange(userGroups);
UserDbContext.Groups.RemoveRange(groups);
userDbContext.UserGroups.RemoveRange(userGroups);
userDbContext.Groups.RemoveRange(groups);
}
else
{
@ -309,7 +292,7 @@ public class EFUserService : IUserService
}
}
UserDbContext.SaveChanges();
userDbContext.SaveChanges();
tr.Commit();
});
}
@ -321,26 +304,28 @@ public class EFUserService : IUserService
public void RemoveUser(int tenant, Guid id, bool immediate)
{
var strategy = UserDbContext.Database.CreateExecutionStrategy();
using var userDbContext = _dbContextFactory.CreateDbContext();
var strategy = userDbContext.Database.CreateExecutionStrategy();
strategy.Execute(() =>
{
using var tr = UserDbContext.Database.BeginTransaction();
using var userDbContext = _dbContextFactory.CreateDbContext();
using var tr = userDbContext.Database.BeginTransaction();
UserDbContext.Acl.RemoveRange(UserDbContext.Acl.Where(r => r.Tenant == tenant && r.Subject == id));
UserDbContext.Subscriptions.RemoveRange(UserDbContext.Subscriptions.Where(r => r.Tenant == tenant && r.Recipient == id.ToString()));
UserDbContext.SubscriptionMethods.RemoveRange(UserDbContext.SubscriptionMethods.Where(r => r.Tenant == tenant && r.Recipient == id.ToString()));
UserDbContext.Photos.RemoveRange(UserDbContext.Photos.Where(r => r.Tenant == tenant && r.UserId == id));
userDbContext.Acl.RemoveRange(userDbContext.Acl.Where(r => r.Tenant == tenant && r.Subject == id));
userDbContext.Subscriptions.RemoveRange(userDbContext.Subscriptions.Where(r => r.Tenant == tenant && r.Recipient == id.ToString()));
userDbContext.SubscriptionMethods.RemoveRange(userDbContext.SubscriptionMethods.Where(r => r.Tenant == tenant && r.Recipient == id.ToString()));
userDbContext.Photos.RemoveRange(userDbContext.Photos.Where(r => r.Tenant == tenant && r.UserId == id));
var userGroups = UserDbContext.UserGroups.Where(r => r.Tenant == tenant && r.Userid == id);
var users = UserDbContext.Users.Where(r => r.Tenant == tenant && r.Id == id);
var userSecurity = UserDbContext.UserSecurity.Where(r => r.Tenant == tenant && r.UserId == id);
var userGroups = userDbContext.UserGroups.Where(r => r.Tenant == tenant && r.Userid == id);
var users = userDbContext.Users.Where(r => r.Tenant == tenant && r.Id == id);
var userSecurity = userDbContext.UserSecurity.Where(r => r.Tenant == tenant && r.UserId == id);
if (immediate)
{
UserDbContext.UserGroups.RemoveRange(userGroups);
UserDbContext.Users.RemoveRange(users);
UserDbContext.UserSecurity.RemoveRange(userSecurity);
userDbContext.UserGroups.RemoveRange(userGroups);
userDbContext.Users.RemoveRange(users);
userDbContext.UserSecurity.RemoveRange(userSecurity);
}
else
{
@ -359,7 +344,7 @@ public class EFUserService : IUserService
}
}
UserDbContext.SaveChanges();
userDbContext.SaveChanges();
tr.Commit();
});
@ -372,16 +357,18 @@ public class EFUserService : IUserService
public void RemoveUserGroupRef(int tenant, Guid userId, Guid groupId, UserGroupRefType refType, bool immediate)
{
var strategy = UserDbContext.Database.CreateExecutionStrategy();
using var userDbContext = _dbContextFactory.CreateDbContext();
var strategy = userDbContext.Database.CreateExecutionStrategy();
strategy.Execute(() =>
{
using var tr = UserDbContext.Database.BeginTransaction();
using var userDbContext = _dbContextFactory.CreateDbContext();
using var tr = userDbContext.Database.BeginTransaction();
var userGroups = UserDbContext.UserGroups.Where(r => r.Tenant == tenant && r.Userid == userId && r.UserGroupId == groupId && r.RefType == refType);
var userGroups = userDbContext.UserGroups.Where(r => r.Tenant == tenant && r.Userid == userId && r.UserGroupId == groupId && r.RefType == refType);
if (immediate)
{
UserDbContext.UserGroups.RemoveRange(userGroups);
userDbContext.UserGroups.RemoveRange(userGroups);
}
else
{
@ -391,9 +378,9 @@ public class EFUserService : IUserService
u.Removed = true;
}
}
var user = UserDbContext.Users.First(r => r.Tenant == tenant && r.Id == userId);
var user = userDbContext.Users.First(r => r.Tenant == tenant && r.Id == userId);
user.LastModified = DateTime.UtcNow;
UserDbContext.SaveChanges();
userDbContext.SaveChanges();
tr.Commit();
});
@ -412,8 +399,10 @@ public class EFUserService : IUserService
group.Tenant = tenant;
var dbGroup = _mapper.Map<Group, DbGroup>(group);
UserDbContext.AddOrUpdate(r => r.Groups, dbGroup);
UserDbContext.SaveChanges();
using var userDbContext = _dbContextFactory.CreateDbContext();
userDbContext.AddOrUpdate(r => r.Groups, dbGroup);
userDbContext.SaveChanges();
return group;
}
@ -442,12 +431,14 @@ public class EFUserService : IUserService
user.UserName = user.UserName.Trim();
user.Email = user.Email.Trim();
var strategy = UserDbContext.Database.CreateExecutionStrategy();
using var userDbContext = _dbContextFactory.CreateDbContext();
var strategy = userDbContext.Database.CreateExecutionStrategy();
strategy.Execute(() =>
{
using var tx = UserDbContext.Database.BeginTransaction();
var any = GetUserQuery(tenant)
using var userDbContext = _dbContextFactory.CreateDbContext();
using var tx = userDbContext.Database.BeginTransaction();
var any = GetUserQuery(userDbContext, tenant)
.Any(r => r.UserName == user.UserName && r.Id != user.Id && !r.Removed);
if (any)
@ -455,7 +446,7 @@ public class EFUserService : IUserService
throw new ArgumentOutOfRangeException("Duplicate username.");
}
any = GetUserQuery(tenant)
any = GetUserQuery(userDbContext, tenant)
.Any(r => r.Email == user.Email && r.Id != user.Id && !r.Removed);
if (any)
@ -463,8 +454,8 @@ public class EFUserService : IUserService
throw new ArgumentOutOfRangeException("Duplicate email.");
}
UserDbContext.AddOrUpdate(r => r.Users, _mapper.Map<UserInfo, User>(user));
UserDbContext.SaveChanges();
userDbContext.AddOrUpdate(r => r.Users, _mapper.Map<UserInfo, User>(user));
userDbContext.SaveChanges();
tx.Commit();
});
@ -478,20 +469,21 @@ public class EFUserService : IUserService
userGroupRef.LastModified = DateTime.UtcNow;
userGroupRef.Tenant = tenant;
var strategy = UserDbContext.Database.CreateExecutionStrategy();
using var userDbContext = _dbContextFactory.CreateDbContext();
var strategy = userDbContext.Database.CreateExecutionStrategy();
strategy.Execute(() =>
{
using var tr = UserDbContext.Database.BeginTransaction();
using var tr = userDbContext.Database.BeginTransaction();
var user = GetUserQuery(tenant).FirstOrDefault(a => a.Tenant == tenant && a.Id == userGroupRef.UserId);
var user = GetUserQuery(userDbContext, tenant).FirstOrDefault(a => a.Tenant == tenant && a.Id == userGroupRef.UserId);
if (user != null)
{
user.LastModified = userGroupRef.LastModified;
UserDbContext.AddOrUpdate(r => r.UserGroups, _mapper.Map<UserGroupRef, UserGroup>(userGroupRef));
userDbContext.AddOrUpdate(r => r.UserGroups, _mapper.Map<UserGroupRef, UserGroup>(userGroupRef));
}
UserDbContext.SaveChanges();
userDbContext.SaveChanges();
tr.Commit();
});
@ -512,19 +504,22 @@ public class EFUserService : IUserService
LastModified = DateTime.UtcNow
};
UserDbContext.AddOrUpdate(r => r.UserSecurity, us);
UserDbContext.SaveChanges();
using var userDbContext = _dbContextFactory.CreateDbContext();
userDbContext.AddOrUpdate(r => r.UserSecurity, us);
userDbContext.SaveChanges();
}
public void SetUserPhoto(int tenant, Guid id, byte[] photo)
{
var strategy = UserDbContext.Database.CreateExecutionStrategy();
using var userDbContext = _dbContextFactory.CreateDbContext();
var strategy = userDbContext.Database.CreateExecutionStrategy();
strategy.Execute(() =>
{
using var tr = UserDbContext.Database.BeginTransaction();
using var userDbContext = _dbContextFactory.CreateDbContext();
using var tr = userDbContext.Database.BeginTransaction();
var userPhoto = UserDbContext.Photos.FirstOrDefault(r => r.UserId == id && r.Tenant == tenant);
var userPhoto = userDbContext.Photos.FirstOrDefault(r => r.UserId == id && r.Tenant == tenant);
if (photo != null && photo.Length != 0)
{
if (userPhoto == null)
@ -541,23 +536,18 @@ public class EFUserService : IUserService
userPhoto.Photo = photo;
}
UserDbContext.AddOrUpdate(r => r.Photos, userPhoto);
userDbContext.AddOrUpdate(r => r.Photos, userPhoto);
}
else if (userPhoto != null)
{
UserDbContext.Photos.Remove(userPhoto);
userDbContext.Photos.Remove(userPhoto);
}
UserDbContext.SaveChanges();
userDbContext.SaveChanges();
tr.Commit();
});
}
private IQueryable<User> GetUserQuery(int tenant)
{
return GetUserQuery(UserDbContext, tenant);
}
private IQueryable<User> GetUserQuery(UserDbContext userDbContext, int tenant)
{
var q = userDbContext.Users.AsQueryable();
@ -577,9 +567,9 @@ public class EFUserService : IUserService
return q;
}
private IQueryable<DbGroup> GetGroupQuery(int tenant)
private IQueryable<DbGroup> GetGroupQuery(UserDbContext userDbContext, int tenant)
{
var q = UserDbContext.Groups.Where(r => true);
var q = userDbContext.Groups.Where(r => true);
if (tenant != Tenant.DefaultTenant)
{
@ -590,6 +580,7 @@ public class EFUserService : IUserService
}
private IQueryable<User> GetUserQueryForFilter(
UserDbContext userDbContext,
IQueryable<User> q,
bool isAdmin,
EmployeeStatus? employeeStatus,
@ -598,14 +589,13 @@ public class EFUserService : IUserService
EmployeeActivationStatus? activationStatus,
string text)
{
q = q.Where(r => !r.Removed);
if (includeGroups != null && includeGroups.Count > 0)
{
foreach (var ig in includeGroups)
{
q = q.Where(r => UserDbContext.UserGroups.Any(a => !a.Removed && a.Tenant == r.Tenant && a.Userid == r.Id && ig.Any(r => r == a.UserGroupId)));
q = q.Where(r => userDbContext.UserGroups.Any(a => !a.Removed && a.Tenant == r.Tenant && a.Userid == r.Id && ig.Any(r => r == a.UserGroupId)));
}
}
@ -613,7 +603,7 @@ public class EFUserService : IUserService
{
foreach (var eg in excludeGroups)
{
q = q.Where(r => !UserDbContext.UserGroups.Any(a => !a.Removed && a.Tenant == r.Tenant && a.Userid == r.Id && a.UserGroupId == eg));
q = q.Where(r => !userDbContext.UserGroups.Any(a => !a.Removed && a.Tenant == r.Tenant && a.Userid == r.Id && a.UserGroupId == eg));
}
}
@ -669,11 +659,11 @@ public class EFUserService : IUserService
return q;
}
private List<Guid> CollectGroupChilds(int tenant, Guid id)
private List<Guid> CollectGroupChilds(UserDbContext userDbContext, int tenant, Guid id)
{
var result = new List<Guid>();
var childs = UserDbContext.Groups
var childs = userDbContext.Groups
.Where(r => r.Tenant == tenant)
.Where(r => r.ParentId == id)
.Select(r => r.Id);
@ -681,7 +671,7 @@ public class EFUserService : IUserService
foreach (var child in childs)
{
result.Add(child);
result.AddRange(CollectGroupChilds(tenant, child));
result.AddRange(CollectGroupChilds(userDbContext, tenant, child));
}
result.Add(id);
@ -691,7 +681,8 @@ public class EFUserService : IUserService
public UserInfo GetUser(int tenant, Guid id, Expression<Func<User, UserInfo>> exp)
{
var q = GetUserQuery(tenant).Where(r => r.Id == id);
using var userDbContext = _dbContextFactory.CreateDbContext();
var q = GetUserQuery(userDbContext, tenant).Where(r => r.Id == id);
if (exp != null)
{
@ -705,8 +696,9 @@ public class EFUserService : IUserService
public IEnumerable<string> GetDavUserEmails(int tenant)
{
return (from usersDav in UserDbContext.UsersDav
join users in UserDbContext.Users on new { tenant = usersDav.TenantId, userId = usersDav.UserId } equals new { tenant = users.Tenant, userId = users.Id }
using var userDbContext = _dbContextFactory.CreateDbContext();
return (from usersDav in userDbContext.UsersDav
join users in userDbContext.Users on new { tenant = usersDav.TenantId, userId = usersDav.UserId } equals new { tenant = users.Tenant, userId = users.Id }
where usersDav.TenantId == tenant
select users.Email)
.Distinct()
@ -715,7 +707,7 @@ public class EFUserService : IUserService
protected string GetPasswordHash(Guid userId, string password)
{
return Hasher.Base64Hash(password + userId + Encoding.UTF8.GetString(MachinePseudoKeys.GetMachineConstant()), HashAlg.SHA512);
return Hasher.Base64Hash(password + userId + Encoding.UTF8.GetString(_machinePseudoKeys.GetMachineConstant()), HashAlg.SHA512);
}
}

View File

@ -26,22 +26,16 @@
namespace ASC.Core.Common.EF.Context;
public class AccountLinkContext : BaseDbContext
public class AccountLinkContext : DbContext
{
public DbSet<AccountLinks> AccountLinks { get; set; }
public AccountLinkContext(DbContextOptions options) : base(options) { }
protected override void OnModelCreating(ModelBuilder modelBuilder)
{
ModelBuilderWrapper
.From(modelBuilder, _provider)
.From(modelBuilder, Database)
.AddAccountLinks();
}
}
public static class AccountLinkContextExtension
{
public static DIHelper AddAccountLinkContextService(this DIHelper services)
{
return services.AddDbContextManagerService<AccountLinkContext>();
}
}

View File

@ -26,16 +26,18 @@
namespace ASC.Core.Common.EF;
public class CoreDbContext : BaseDbContext
public class CoreDbContext : DbContext
{
public DbSet<DbTariff> Tariffs { get; set; }
public DbSet<DbButton> Buttons { get; set; }
public DbSet<DbQuota> Quotas { get; set; }
public DbSet<DbQuotaRow> QuotaRows { get; set; }
public CoreDbContext(DbContextOptions options) : base(options) { }
protected override void OnModelCreating(ModelBuilder modelBuilder)
{
ModelBuilderWrapper
.From(modelBuilder, _provider)
.From(modelBuilder, Database)
.AddDbButton()
.AddDbQuotaRow()
.AddDbQuota()

View File

@ -26,36 +26,19 @@
namespace ASC.Core.Common.EF.Context;
public class CustomDbContext : BaseDbContext
public class CustomDbContext : DbContext
{
public CustomDbContext()
{
}
public CustomDbContext(DbContextOptions<CustomDbContext> options) : base(options)
{
}
public DbSet<MobileAppInstall> MobileAppInstall { get; set; }
public DbSet<DbipLocation> DbipLocation { get; set; }
public DbSet<Regions> Regions { get; set; }
public CustomDbContext(DbContextOptions options) : base(options) { }
protected override void OnModelCreating(ModelBuilder modelBuilder)
{
ModelBuilderWrapper
.From(modelBuilder, _provider)
.From(modelBuilder, Database)
.AddMobileAppInstall()
.AddDbipLocation()
.AddRegions();
}
}
public static class CustomDbContextExtension
{
public static DIHelper AddDbContextService(this DIHelper services)
{
return services.AddDbContextManagerService<CustomDbContext>();
}
}

View File

@ -26,24 +26,21 @@
namespace ASC.Core.Common.EF.Context;
public class NotifyDbContext : BaseDbContext
public class NotifyDbContext : DbContext
{
public DbSet<NotifyInfo> NotifyInfo { get; set; }
public DbSet<NotifyQueue> NotifyQueue { get; set; }
public NotifyDbContext(DbContextOptions options) : base(options)
{
}
protected override void OnModelCreating(ModelBuilder modelBuilder)
{
ModelBuilderWrapper
.From(modelBuilder, _provider)
.From(modelBuilder, Database)
.AddNotifyInfo()
.AddNotifyQueue();
}
}
public static class NotifyDbExtension
{
public static DIHelper AddNotifyDbContext(this DIHelper services)
{
return services.AddDbContextManagerService<NotifyDbContext>();
}
}

View File

@ -26,22 +26,19 @@
namespace ASC.Core.Common.EF.Context;
public class TelegramDbContext : BaseDbContext
public class TelegramDbContext : DbContext
{
public DbSet<TelegramUser> Users { get; set; }
public TelegramDbContext(DbContextOptions options) : base(options)
{
}
protected override void OnModelCreating(ModelBuilder modelBuilder)
{
ModelBuilderWrapper
.From(modelBuilder, _provider)
.From(modelBuilder, Database)
.AddTelegramUsers();
}
}
public static class TelegramDbContextExtension
{
public static DIHelper AddTelegramDbContextService(this DIHelper services)
{
return services.AddDbContextManagerService<TelegramDbContext>();
}
}

View File

@ -26,7 +26,7 @@
namespace ASC.Core.Common.EF.Context;
public class TenantDbContext : BaseDbContext
public class TenantDbContext : DbContext
{
public DbSet<DbTenant> Tenants { get; set; }
public DbSet<DbTenantVersion> TenantVersion { get; set; }
@ -34,11 +34,12 @@ public class TenantDbContext : BaseDbContext
public DbSet<DbTenantForbiden> TenantForbiden { get; set; }
public DbSet<TenantIpRestrictions> TenantIpRestrictions { get; set; }
public DbSet<DbCoreSettings> CoreSettings { get; set; }
public TenantDbContext(DbContextOptions options) : base(options) { }
protected override void OnModelCreating(ModelBuilder modelBuilder)
{
ModelBuilderWrapper
.From(modelBuilder, _provider)
.From(modelBuilder, Database)
.AddDbTenant()
.AddCoreSettings()
.AddDbTenantForbiden()
@ -47,11 +48,3 @@ public class TenantDbContext : BaseDbContext
.AddDbTenantVersion();
}
}
public static class TenantDbExtension
{
public static DIHelper AddTenantDbContextService(this DIHelper services)
{
return services.AddDbContextManagerService<TenantDbContext>();
}
}

View File

@ -26,12 +26,17 @@
namespace ASC.Core.Common.EF.Context;
public class UrlShortenerFakeDbContext : BaseDbContext
public class UrlShortenerFakeDbContext : DbContext
{
public UrlShortenerFakeDbContext(DbContextOptions dbContextOptions) : base(dbContextOptions)
{
}
protected override void OnModelCreating(ModelBuilder modelBuilder)
{
ModelBuilderWrapper
.From(modelBuilder, _provider)
.From(modelBuilder, Database)
.AddShortLinks();
}
}

View File

@ -26,7 +26,7 @@
namespace ASC.Core.Common.EF;
public class UserDbContext : BaseDbContext
public class UserDbContext : DbContext
{
public DbSet<User> Users { get; set; }
public DbSet<UserSecurity> UserSecurity { get; set; }
@ -38,10 +38,15 @@ public class UserDbContext : BaseDbContext
public DbSet<DbSubscriptionMethod> SubscriptionMethods { get; set; }
public DbSet<UserDav> UsersDav { get; set; }
public UserDbContext(DbContextOptions dbContextOptions) : base(dbContextOptions)
{
}
protected override void OnModelCreating(ModelBuilder modelBuilder)
{
ModelBuilderWrapper
.From(modelBuilder, _provider)
.From(modelBuilder, Database)
.AddSubscriptionMethod()
.AddUser()
.AddAcl()
@ -53,11 +58,3 @@ public class UserDbContext : BaseDbContext
.AddUserDav();
}
}
public static class UserDbExtension
{
public static DIHelper AddUserDbContextService(this DIHelper services)
{
return services.AddDbContextManagerService<UserDbContext>();
}
}

View File

@ -26,17 +26,22 @@
namespace ASC.Core.Common.EF.Context;
public class WebstudioDbContext : BaseDbContext
public class WebstudioDbContext : DbContext
{
public DbSet<DbTenant> Tenants { get; set; }
public DbSet<DbWebstudioSettings> WebstudioSettings { get; set; }
public DbSet<DbWebstudioUserVisit> WebstudioUserVisit { get; set; }
public DbSet<DbWebstudioIndex> WebstudioIndex { get; set; }
public WebstudioDbContext(DbContextOptions options) : base(options)
{
}
protected override void OnModelCreating(ModelBuilder modelBuilder)
{
ModelBuilderWrapper
.From(modelBuilder, _provider)
.From(modelBuilder, Database)
.AddWebstudioSettings()
.AddWebstudioUserVisit()
.AddDbWebstudioIndex()
@ -44,11 +49,3 @@ public class WebstudioDbContext : BaseDbContext
.AddDbFunction();
}
}
public static class WebstudioDbExtension
{
public static DIHelper AddWebstudioDbContextService(this DIHelper services)
{
return services.AddDbContextManagerService<WebstudioDbContext>();
}
}

View File

@ -28,22 +28,22 @@ namespace ASC.Geolocation;
public class GeolocationHelper
{
public string Dbid { get; set; }
private readonly IDbContextFactory<CustomDbContext> _dbContextFactory;
private readonly ILogger<GeolocationHelper> _logger;
private readonly CustomDbContext _dbContext;
public GeolocationHelper(DbContextManager<CustomDbContext> dbContext, ILogger<GeolocationHelper> logger)
public GeolocationHelper(IDbContextFactory<CustomDbContext> dbContextFactory, ILogger<GeolocationHelper> logger)
{
_dbContextFactory = dbContextFactory;
_logger = logger;
_dbContext = dbContext.Get(Dbid);
}
public IPGeolocationInfo GetIPGeolocation(string ip)
{
try
{
using var dbContext = _dbContextFactory.CreateDbContext();
var ipformatted = FormatIP(ip);
var q = _dbContext.DbipLocation
var q = dbContext.DbipLocation
.Where(r => r.IPStart.CompareTo(ipformatted) <= 0)
.Where(r => ipformatted.CompareTo(r.IPEnd) <= 0)
.OrderByDescending(r => r.IPStart)

View File

@ -28,71 +28,8 @@ using Constants = ASC.Core.Users.Constants;
namespace ASC.Core;
[Scope]
class ConfigureHostedSolution : IConfigureNamedOptions<HostedSolution>
{
private readonly UserFormatter _userFormatter;
private readonly IOptionsSnapshot<CachedTenantService> _tenantService;
private readonly IOptionsSnapshot<CachedUserService> _userService;
private readonly IOptionsSnapshot<CachedQuotaService> _quotaService;
private readonly IOptionsSnapshot<TariffService> _tariffService;
private readonly IOptionsSnapshot<TenantManager> _tenantManager;
private readonly IOptionsSnapshot<TenantUtil> _tenantUtil;
private readonly IOptionsSnapshot<DbSettingsManager> _dbSettingsManager;
private readonly IOptionsSnapshot<CoreSettings> _coreSettings;
public ConfigureHostedSolution(
UserFormatter userFormatter,
IOptionsSnapshot<CachedTenantService> tenantService,
IOptionsSnapshot<CachedUserService> userService,
IOptionsSnapshot<CachedQuotaService> quotaService,
IOptionsSnapshot<TariffService> tariffService,
IOptionsSnapshot<TenantManager> tenantManager,
IOptionsSnapshot<TenantUtil> tenantUtil,
IOptionsSnapshot<DbSettingsManager> dbSettingsManager,
IOptionsSnapshot<CoreSettings> coreSettings
)
{
_userFormatter = userFormatter;
_tenantService = tenantService;
_userService = userService;
_quotaService = quotaService;
_tariffService = tariffService;
_tenantManager = tenantManager;
_tenantUtil = tenantUtil;
_dbSettingsManager = dbSettingsManager;
_coreSettings = coreSettings;
}
public void Configure(HostedSolution hostedSolution)
{
hostedSolution.UserFormatter = _userFormatter;
hostedSolution.TenantService = _tenantService.Value;
hostedSolution.UserService = _userService.Value;
hostedSolution.QuotaService = _quotaService.Value;
hostedSolution.TariffService = _tariffService.Value;
hostedSolution.ClientTenantManager = _tenantManager.Value;
hostedSolution.TenantUtil = _tenantUtil.Value;
hostedSolution.SettingsManager = _dbSettingsManager.Value;
hostedSolution.CoreSettings = _coreSettings.Value;
}
public void Configure(string name, HostedSolution hostedSolution)
{
Configure(hostedSolution);
hostedSolution.Region = name;
hostedSolution.TenantService = _tenantService.Get(name);
hostedSolution.UserService = _userService.Get(name);
hostedSolution.QuotaService = _quotaService.Get(name);
hostedSolution.TariffService = _tariffService.Get(name);
hostedSolution.ClientTenantManager = _tenantManager.Get(name);
hostedSolution.TenantUtil = _tenantUtil.Get(name);
hostedSolution.SettingsManager = _dbSettingsManager.Get(name);
hostedSolution.CoreSettings = _coreSettings.Get(name);
}
}
[Scope(typeof(ConfigureHostedSolution))]
public class HostedSolution
{
internal ITenantService TenantService { get; set; }

View File

@ -29,12 +29,12 @@ namespace ASC.Core.Common.Notify.Telegram;
[Scope]
public class TelegramDao
{
public TelegramDbContext TelegramDbContext { get; set; }
public TelegramDao() { }
private readonly IDbContextFactory<TelegramDbContext> _dbContextFactory;
public TelegramDao(DbContextManager<TelegramDbContext> dbContextManager)
public TelegramDao(IDbContextFactory<TelegramDbContext> dbContextFactory)
{
TelegramDbContext = dbContextManager.Value;
_dbContextFactory = dbContextFactory;
}
public void RegisterUser(Guid userId, int tenantId, long telegramId)
@ -46,18 +46,22 @@ public class TelegramDao
TelegramUserId = telegramId
};
TelegramDbContext.AddOrUpdate(r => r.Users, user);
TelegramDbContext.SaveChanges();
using var dbContext = _dbContextFactory.CreateDbContext();
dbContext.AddOrUpdate(r => r.Users, user);
dbContext.SaveChanges();
}
public TelegramUser GetUser(Guid userId, int tenantId)
{
return TelegramDbContext.Users.Find(tenantId, userId);
using var dbContext = _dbContextFactory.CreateDbContext();
return dbContext.Users.Find(tenantId, userId);
}
public List<TelegramUser> GetUser(long telegramId)
{
return TelegramDbContext.Users
using var dbContext = _dbContextFactory.CreateDbContext();
return dbContext.Users
.AsNoTracking()
.Where(r => r.TelegramUserId == telegramId)
.ToList();
@ -65,22 +69,26 @@ public class TelegramDao
public void Delete(Guid userId, int tenantId)
{
var toRemove = TelegramDbContext.Users
using var dbContext = _dbContextFactory.CreateDbContext();
var toRemove = dbContext.Users
.Where(r => r.PortalUserId == userId)
.Where(r => r.TenantId == tenantId)
.ToList();
TelegramDbContext.Users.RemoveRange(toRemove);
TelegramDbContext.SaveChanges();
dbContext.Users.RemoveRange(toRemove);
dbContext.SaveChanges();
}
public void Delete(long telegramId)
{
var toRemove = TelegramDbContext.Users
using var dbContext = _dbContextFactory.CreateDbContext();
var toRemove = dbContext.Users
.Where(r => r.TelegramUserId == telegramId)
.ToList();
TelegramDbContext.Users.RemoveRange(toRemove);
TelegramDbContext.SaveChanges();
dbContext.Users.RemoveRange(toRemove);
dbContext.SaveChanges();
}
}

View File

@ -29,32 +29,35 @@ namespace ASC.Common.Radicale.Core;
[Scope]
public class DbRadicale
{
private UserDbContext UserDbContext => _lazyUserDbContext.Value;
private readonly Lazy<UserDbContext> _lazyUserDbContext;
public DbRadicale(DbContextManager<UserDbContext> dbContextManager)
private readonly IDbContextFactory<UserDbContext> _dbContextFactory;
public DbRadicale(IDbContextFactory<UserDbContext> dbContextFactory)
{
_lazyUserDbContext = new Lazy<UserDbContext>(() => dbContextManager.Value);
_dbContextFactory = dbContextFactory;
}
public void SaveCardDavUser(int tenant, Guid id)
{
UserDbContext.AddOrUpdate(r => r.UsersDav, new UserDav() { TenantId = tenant, UserId = id });
UserDbContext.SaveChanges();
using var userDbContext = _dbContextFactory.CreateDbContext();
userDbContext.AddOrUpdate(r => r.UsersDav, new UserDav() { TenantId = tenant, UserId = id });
userDbContext.SaveChanges();
}
public async Task RemoveCardDavUser(int tenant, Guid id)
{
var userDav = await UserDbContext.UsersDav.FirstOrDefaultAsync(r => r.TenantId == tenant && r.UserId == id);
using var userDbContext = _dbContextFactory.CreateDbContext();
var userDav = await userDbContext.UsersDav.FirstOrDefaultAsync(r => r.TenantId == tenant && r.UserId == id);
if (userDav != null)
{
UserDbContext.UsersDav.Remove(userDav);
await UserDbContext.SaveChangesAsync();
userDbContext.UsersDav.Remove(userDav);
await userDbContext.SaveChangesAsync();
}
}
public async Task<bool> IsExistCardDavUser(int tenant, Guid id)
{
return await UserDbContext.UsersDav.AnyAsync(r => r.TenantId == tenant && r.UserId == id);
using var userDbContext = _dbContextFactory.CreateDbContext();
return await userDbContext.UsersDav.AnyAsync(r => r.TenantId == tenant && r.UserId == id);
}
}

View File

@ -35,7 +35,7 @@ public class SettingsManager : DbSettingsManager
ILogger<DbSettingsManager> option,
AuthContext authContext,
TenantManager tenantManager,
DbContextManager<WebstudioDbContext> dbContextManager)
IDbContextFactory<WebstudioDbContext> dbContextManager)
: base(serviceProvider, dbSettingsManagerCache, option, authContext, tenantManager, dbContextManager)
{

View File

@ -43,12 +43,12 @@ public class DbHelper : IDisposable
public DbHelper(
ILogger<DbHelper> logger,
ConnectionStringSettings connectionString,
TenantDbContext tenantDbContext,
CoreDbContext coreDbContext)
IDbContextFactory<TenantDbContext> tenantDbContext,
IDbContextFactory<CoreDbContext> coreDbContext)
{
_logger = logger;
_tenantDbContext = tenantDbContext;
_coreDbContext = coreDbContext;
_tenantDbContext = tenantDbContext.CreateDbContext();
_coreDbContext = coreDbContext.CreateDbContext();
var file = connectionString.ElementInformation.Source;
if ("web.connections.config".Equals(Path.GetFileName(file), StringComparison.InvariantCultureIgnoreCase))

View File

@ -58,54 +58,16 @@ public class AccountLinkerStorage
}
[Scope]
public class ConfigureAccountLinker : IConfigureNamedOptions<AccountLinker>
public class AccountLinker
{
private readonly Signature _signature;
private readonly InstanceCrypto _instanceCrypto;
private readonly AccountLinkerStorage _accountLinkerStorage;
private readonly DbContextManager<AccountLinkContext> _dbContextManager;
public ConfigureAccountLinker(
Signature signature,
InstanceCrypto instanceCrypto,
AccountLinkerStorage accountLinkerStorage,
DbContextManager<AccountLinkContext> dbContextManager)
{
_signature = signature;
_instanceCrypto = instanceCrypto;
_accountLinkerStorage = accountLinkerStorage;
_dbContextManager = dbContextManager;
}
public void Configure(string name, AccountLinker options)
{
options.DbId = name;
options.AccountLinkerStorage = _accountLinkerStorage;
options.InstanceCrypto = _instanceCrypto;
options.Signature = _signature;
options.AccountLinkContextManager = _dbContextManager;
}
public void Configure(AccountLinker options)
{
Configure("default", options);
}
}
[Scope(typeof(ConfigureAccountLinker))]
public class AccountLinker
{
public string DbId { get; set; }
public AccountLinkContext AccountLinkContext => AccountLinkContextManager.Get(DbId);
public DbSet<AccountLinks> AccountLinks => AccountLinkContext.AccountLinks;
internal Signature Signature { get; set; }
internal InstanceCrypto InstanceCrypto { get; set; }
internal AccountLinkerStorage AccountLinkerStorage { get; set; }
internal DbContextManager<AccountLinkContext> AccountLinkContextManager { get; set; }
private readonly IDbContextFactory<AccountLinkContext> _accountLinkContextManager;
public IEnumerable<string> GetLinkedObjects(string id, string provider)
{
return GetLinkedObjects(new LoginProfile(Signature, InstanceCrypto) { Id = id, Provider = provider });
return GetLinkedObjects(new LoginProfile(_signature, _instanceCrypto) { Id = id, Provider = provider });
}
public IEnumerable<string> GetLinkedObjects(LoginProfile profile)
@ -115,7 +77,8 @@ public class AccountLinker
public IEnumerable<string> GetLinkedObjectsByHashId(string hashid)
{
return AccountLinks
using var accountLinkContext = _accountLinkContextManager.CreateDbContext();
return accountLinkContext.AccountLinks
.Where(r => r.UId == hashid)
.Where(r => r.Provider != string.Empty)
.Select(r => r.Id)
@ -129,7 +92,7 @@ public class AccountLinker
public IEnumerable<LoginProfile> GetLinkedProfiles(string obj)
{
return AccountLinkerStorage.GetFromCache(obj, GetLinkedProfilesFromDB);
return _accountLinkerStorage.GetFromCache(obj, GetLinkedProfilesFromDB);
}
public void AddLink(string obj, LoginProfile profile)
@ -143,20 +106,21 @@ public class AccountLinker
Linked = DateTime.UtcNow
};
AccountLinkContext.AddOrUpdate(r => r.AccountLinks, accountLink);
AccountLinkContext.SaveChanges();
using var accountLinkContext = _accountLinkContextManager.CreateDbContext();
accountLinkContext.AddOrUpdate(r => r.AccountLinks, accountLink);
accountLinkContext.SaveChanges();
AccountLinkerStorage.RemoveFromCache(obj);
_accountLinkerStorage.RemoveFromCache(obj);
}
public void AddLink(string obj, string id, string provider)
{
AddLink(obj, new LoginProfile(Signature, InstanceCrypto) { Id = id, Provider = provider });
AddLink(obj, new LoginProfile(_signature, _instanceCrypto) { Id = id, Provider = provider });
}
public void RemoveLink(string obj, string id, string provider)
{
RemoveLink(obj, new LoginProfile(Signature, InstanceCrypto) { Id = id, Provider = provider });
RemoveLink(obj, new LoginProfile(_signature, _instanceCrypto) { Id = id, Provider = provider });
}
public void RemoveLink(string obj, LoginProfile profile)
@ -166,13 +130,15 @@ public class AccountLinker
public void RemoveProvider(string obj, string provider = null, string hashId = null)
{
var strategy = AccountLinkContext.Database.CreateExecutionStrategy();
using var accountLinkContext = _accountLinkContextManager.CreateDbContext();
var strategy = accountLinkContext.Database.CreateExecutionStrategy();
strategy.Execute(() =>
{
using var tr = AccountLinkContext.Database.BeginTransaction();
using var accountLinkContext = _accountLinkContextManager.CreateDbContext();
using var tr = accountLinkContext.Database.BeginTransaction();
var accountLinkQuery = AccountLinks
var accountLinkQuery = accountLinkContext.AccountLinks
.Where(r => r.Id == obj);
if (!string.IsNullOrEmpty(provider))
@ -186,24 +152,26 @@ public class AccountLinker
}
var accountLink = accountLinkQuery.FirstOrDefault();
AccountLinks.Remove(accountLink);
AccountLinkContext.SaveChanges();
accountLinkContext.AccountLinks.Remove(accountLink);
accountLinkContext.SaveChanges();
tr.Commit();
});
AccountLinkerStorage.RemoveFromCache(obj);
_accountLinkerStorage.RemoveFromCache(obj);
}
private List<LoginProfile> GetLinkedProfilesFromDB(string obj)
{
using var accountLinkContext = _accountLinkContextManager.CreateDbContext();
//Retrieve by uinque id
return AccountLinks
return accountLinkContext.AccountLinks
.Where(r => r.Id == obj)
.Select(r => r.Profile)
.ToList()
.ConvertAll(x => LoginProfile.CreateFromSerializedString(Signature, InstanceCrypto, x));
.ConvertAll(x => LoginProfile.CreateFromSerializedString(_signature, _instanceCrypto, x));
}
}

View File

@ -29,22 +29,19 @@ namespace ASC.IPSecurity;
[Scope]
public class IPRestrictionsRepository
{
private TenantDbContext TenantDbContext => _lazyTenantDbContext.Value;
private const string DbId = "core";
private readonly Lazy<TenantDbContext> _lazyTenantDbContext;
private readonly IDbContextFactory<TenantDbContext> _dbContextManager;
private readonly IMapper _mapper;
public IPRestrictionsRepository(DbContextManager<TenantDbContext> dbContextManager, IMapper mapper)
public IPRestrictionsRepository(IDbContextFactory<TenantDbContext> dbContextManager, IMapper mapper)
{
_lazyTenantDbContext = new Lazy<TenantDbContext>(() => dbContextManager.Get(DbId));
_dbContextManager = dbContextManager;
_mapper = mapper;
}
public List<IPRestriction> Get(int tenant)
{
return TenantDbContext.TenantIpRestrictions
using var tenantDbContext = _dbContextManager.CreateDbContext();
return tenantDbContext.TenantIpRestrictions
.Where(r => r.Tenant == tenant)
.ProjectTo<IPRestriction>(_mapper.ConfigurationProvider)
.ToList();
@ -52,15 +49,17 @@ public class IPRestrictionsRepository
public List<string> Save(IEnumerable<string> ips, int tenant)
{
var strategy = TenantDbContext.Database.CreateExecutionStrategy();
using var tenantDbContext = _dbContextManager.CreateDbContext();
var strategy = tenantDbContext.Database.CreateExecutionStrategy();
strategy.Execute(() =>
{
using var tx = TenantDbContext.Database.BeginTransaction();
using var tenantDbContext = _dbContextManager.CreateDbContext();
using var tx = tenantDbContext.Database.BeginTransaction();
var restrictions = TenantDbContext.TenantIpRestrictions.Where(r => r.Tenant == tenant).ToList();
TenantDbContext.TenantIpRestrictions.RemoveRange(restrictions);
TenantDbContext.SaveChanges();
var restrictions = tenantDbContext.TenantIpRestrictions.Where(r => r.Tenant == tenant).ToList();
tenantDbContext.TenantIpRestrictions.RemoveRange(restrictions);
tenantDbContext.SaveChanges();
var ipsList = ips.Select(r => new TenantIpRestrictions
{
@ -68,8 +67,8 @@ public class IPRestrictionsRepository
Ip = r
});
TenantDbContext.TenantIpRestrictions.AddRange(ipsList);
TenantDbContext.SaveChanges();
tenantDbContext.TenantIpRestrictions.AddRange(ipsList);
tenantDbContext.SaveChanges();
tx.Commit();
});

View File

@ -24,6 +24,8 @@
// content are licensed under the terms of the Creative Commons Attribution-ShareAlike 4.0
// International. See the License terms at http://creativecommons.org/licenses/by-sa/4.0/legalcode
using Microsoft.EntityFrameworkCore;
namespace ASC.ElasticSearch;
public enum UpdateAction
@ -63,22 +65,21 @@ public class BaseIndexer<T> where T : class, ISearchItem
protected internal T Wrapper => _serviceProvider.GetService<T>();
internal string IndexName => Wrapper.IndexName;
private WebstudioDbContext WebstudioDbContext => _lazyWebstudioDbContext.Value;
private bool _isExist;
private readonly Client _client;
private readonly ILogger _logger;
private readonly IDbContextFactory<WebstudioDbContext> _dbContextFactory;
protected readonly TenantManager _tenantManager;
private readonly BaseIndexerHelper _baseIndexerHelper;
private readonly Settings _settings;
private readonly IServiceProvider _serviceProvider;
private readonly Lazy<WebstudioDbContext> _lazyWebstudioDbContext;
private static readonly object _locker = new object();
public BaseIndexer(
Client client,
ILogger<BaseIndexer<T>> logger,
DbContextManager<WebstudioDbContext> dbContextManager,
IDbContextFactory<WebstudioDbContext> dbContextFactory,
TenantManager tenantManager,
BaseIndexerHelper baseIndexerHelper,
Settings settings,
@ -86,11 +87,11 @@ public class BaseIndexer<T> where T : class, ISearchItem
{
_client = client;
_logger = logger;
_dbContextFactory = dbContextFactory;
_tenantManager = tenantManager;
_baseIndexerHelper = baseIndexerHelper;
_settings = settings;
_serviceProvider = serviceProvider;
_lazyWebstudioDbContext = new Lazy<WebstudioDbContext>(() => dbContextManager.Value);
}
public IEnumerable<List<T>> IndexAll(
@ -98,8 +99,9 @@ public class BaseIndexer<T> where T : class, ISearchItem
Func<DateTime, List<int>> getIds,
Func<long, long, DateTime, List<T>> getData)
{
using var webstudioDbContext = _dbContextFactory.CreateDbContext();
var now = DateTime.UtcNow;
var lastIndexed = WebstudioDbContext.WebstudioIndex
var lastIndexed = webstudioDbContext.WebstudioIndex
.Where(r => r.IndexName == Wrapper.IndexName)
.Select(r => r.LastModified)
.FirstOrDefault();
@ -121,13 +123,13 @@ public class BaseIndexer<T> where T : class, ISearchItem
yield return getData(ids[i], ids[i + 1], lastIndexed);
}
WebstudioDbContext.AddOrUpdate(r => r.WebstudioIndex, new DbWebstudioIndex()
webstudioDbContext.AddOrUpdate(r => r.WebstudioIndex, new DbWebstudioIndex()
{
IndexName = Wrapper.IndexName,
LastModified = now
});
WebstudioDbContext.SaveChanges();
webstudioDbContext.SaveChanges();
_logger.DebugIndexCompleted(Wrapper.IndexName);
}
@ -533,14 +535,15 @@ public class BaseIndexer<T> where T : class, ISearchItem
private void Clear()
{
var index = WebstudioDbContext.WebstudioIndex.Where(r => r.IndexName == Wrapper.IndexName).FirstOrDefault();
using var webstudioDbContext = _dbContextFactory.CreateDbContext();
var index = webstudioDbContext.WebstudioIndex.Where(r => r.IndexName == Wrapper.IndexName).FirstOrDefault();
if (index != null)
{
WebstudioDbContext.WebstudioIndex.Remove(index);
webstudioDbContext.WebstudioIndex.Remove(index);
}
WebstudioDbContext.SaveChanges();
webstudioDbContext.SaveChanges();
_logger.DebugIndexDeleted(Wrapper.IndexName);
_client.Instance.Indices.Delete(Wrapper.IndexName);

View File

@ -26,10 +26,9 @@
namespace ASC.Notify;
[Singletone(Additional = typeof(DbWorkerExtension))]
[Singletone]
public class DbWorker
{
private readonly string _dbid;
private readonly object _syncRoot = new object();
private readonly IServiceScopeFactory _serviceScopeFactory;
@ -39,7 +38,6 @@ public class DbWorker
{
_serviceScopeFactory = serviceScopeFactory;
_notifyServiceCfg = notifyServiceCfg.Value;
_dbid = _notifyServiceCfg.ConnectionStringName;
}
public int SaveMessage(NotifyMessage m)
@ -48,7 +46,7 @@ public class DbWorker
var _mapper = scope.ServiceProvider.GetRequiredService<IMapper>();
using var dbContext = scope.ServiceProvider.GetService<DbContextManager<NotifyDbContext>>().Get(_dbid);
using var dbContext = scope.ServiceProvider.GetService<IDbContextFactory<NotifyDbContext>>().CreateDbContext();
var strategy = dbContext.Database.CreateExecutionStrategy();
@ -89,7 +87,7 @@ public class DbWorker
var _mapper = scope.ServiceProvider.GetRequiredService<IMapper>();
using var dbContext = scope.ServiceProvider.GetService<DbContextManager<NotifyDbContext>>().Get(_dbid);
using var dbContext = scope.ServiceProvider.GetService<IDbContextFactory<NotifyDbContext>>().CreateDbContext();
var q = dbContext.NotifyQueue
.Join(dbContext.NotifyInfo, r => r.NotifyId, r => r.NotifyId, (queue, info) => new { queue, info })
@ -142,7 +140,7 @@ public class DbWorker
public void ResetStates()
{
using var scope = _serviceScopeFactory.CreateScope();
using var dbContext = scope.ServiceProvider.GetService<DbContextManager<NotifyDbContext>>().Get(_dbid);
using var dbContext = scope.ServiceProvider.GetService<IDbContextFactory<NotifyDbContext>>().CreateDbContext();
var strategy = dbContext.Database.CreateExecutionStrategy();
@ -164,7 +162,7 @@ public class DbWorker
public void SetState(int id, MailSendingState result)
{
using var scope = _serviceScopeFactory.CreateScope();
using var dbContext = scope.ServiceProvider.GetService<DbContextManager<NotifyDbContext>>().Get(_dbid);
using var dbContext = scope.ServiceProvider.GetService<IDbContextFactory<NotifyDbContext>>().CreateDbContext();
using var tx = dbContext.Database.BeginTransaction();
var strategy = dbContext.Database.CreateExecutionStrategy();
@ -206,11 +204,3 @@ public class DbWorker
});
}
}
public static class DbWorkerExtension
{
public static void Register(DIHelper services)
{
services.TryAdd<DbContextManager<NotifyDbContext>>();
}
}

View File

@ -60,6 +60,8 @@ builder.Host.ConfigureDefault(args, (hostContext, config, env, path) =>
services.AddActivePassiveHostedService<NotifySenderService>();
services.AddActivePassiveHostedService<NotifyCleanerService>();
services.AddBaseDbContext<NotifyDbContext>();
});
var startup = new BaseWorkerStartup(builder.Configuration);

View File

@ -77,7 +77,7 @@ public class NotifyCleanerService : BackgroundService
var date = DateTime.UtcNow.AddDays(-_notifyServiceCfg.StoreMessagesDays);
using var scope = _scopeFactory.CreateScope();
using var dbContext = scope.ServiceProvider.GetService<DbContextManager<NotifyDbContext>>().Get(_notifyServiceCfg.ConnectionStringName);
using var dbContext = scope.ServiceProvider.GetService<IDbContextFactory<NotifyDbContext>>().CreateDbContext();
var strategy = dbContext.Database.CreateExecutionStrategy();

View File

@ -34,7 +34,7 @@ public class BaseIndexerFile : BaseIndexer<DbFile>
public BaseIndexerFile(
Client client,
ILogger<BaseIndexerFile> log,
DbContextManager<WebstudioDbContext> dbContextManager,
IDbContextFactory<WebstudioDbContext> dbContextManager,
TenantManager tenantManager,
BaseIndexerHelper baseIndexerHelper,
Settings settings,

View File

@ -26,6 +26,8 @@
using ASC.Core.Common.EF.Context;
using Microsoft.EntityFrameworkCore;
namespace ASC.Files.AutoCleanUp;
[Singletone]
@ -53,7 +55,7 @@ public class Worker
using (var scope = _serviceScopeFactory.CreateScope())
{
var dbContext = scope.ServiceProvider.GetRequiredService<DbContextManager<WebstudioDbContext>>().Value;
using var dbContext = scope.ServiceProvider.GetRequiredService<IDbContextFactory<WebstudioDbContext>>().CreateDbContext();
activeTenantsUsers = GetTenantsUsers(dbContext);
}

View File

@ -77,7 +77,6 @@ public class ConnectionsController : ControllerBase
_cookiesManager = cookiesManager;
_cookieStorage = cookieStorage;
_geolocationHelper = geolocationHelper;
_geolocationHelper.Dbid = "teamlabsite";
}
[HttpGet("activeconnections")]

View File

@ -29,12 +29,11 @@ namespace ASC.Web.Core.Mobile;
[Scope]
public class MobileAppInstallRegistrator : IMobileAppInstallRegistrator
{
private readonly Lazy<CustomDbContext> _lazyDbContext;
private CustomDbContext DbContext { get => _lazyDbContext.Value; }
private readonly IDbContextFactory<CustomDbContext> _dbContextFactory;
public MobileAppInstallRegistrator(DbContextManager<CustomDbContext> dbContext)
public MobileAppInstallRegistrator(IDbContextFactory<CustomDbContext> dbContextFactory)
{
_lazyDbContext = new Lazy<CustomDbContext>(() => dbContext.Value);
_dbContextFactory = dbContextFactory;
}
public void RegisterInstall(string userEmail, MobileAppType appType)
@ -47,13 +46,15 @@ public class MobileAppInstallRegistrator : IMobileAppInstallRegistrator
LastSign = DateTime.UtcNow
};
DbContext.MobileAppInstall.Add(mai);
DbContext.SaveChanges();
using var dbContext = _dbContextFactory.CreateDbContext();
dbContext.MobileAppInstall.Add(mai);
dbContext.SaveChanges();
}
public bool IsInstallRegistered(string userEmail, MobileAppType? appType)
{
var q = DbContext.MobileAppInstall.Where(r => r.UserEmail == userEmail);
using var dbContext = _dbContextFactory.CreateDbContext();
var q = dbContext.MobileAppInstall.Where(r => r.UserEmail == userEmail);
if (appType.HasValue)
{

View File

@ -32,13 +32,11 @@ public class StatisticManager
private static DateTime _lastSave = DateTime.UtcNow;
private static readonly TimeSpan _cacheTime = TimeSpan.FromMinutes(2);
private static readonly IDictionary<string, UserVisit> _cache = new Dictionary<string, UserVisit>();
private readonly IDbContextFactory<WebstudioDbContext> _dbContextFactory;
private readonly Lazy<WebstudioDbContext> _lazyWebstudioDbContext;
private WebstudioDbContext WebstudioDbContext { get => _lazyWebstudioDbContext.Value; }
public StatisticManager(DbContextManager<WebstudioDbContext> dbContextManager)
public StatisticManager(IDbContextFactory<WebstudioDbContext> dbContextFactory)
{
_lazyWebstudioDbContext = new Lazy<WebstudioDbContext>(() => dbContextManager.Value);
_dbContextFactory = dbContextFactory;
}
public void SaveUserVisit(int tenantID, Guid userID, Guid productID)
@ -71,7 +69,8 @@ public class StatisticManager
public List<Guid> GetVisitorsToday(int tenantID, Guid productID)
{
var users = WebstudioDbContext.WebstudioUserVisit
using var webstudioDbContext = _dbContextFactory.CreateDbContext();
var users = webstudioDbContext.WebstudioUserVisit
.Where(r => r.VisitDate == DateTime.UtcNow.Date)
.Where(r => r.TenantId == tenantID)
.Where(r => r.ProductId == productID)
@ -95,7 +94,8 @@ public class StatisticManager
public List<UserVisit> GetHitsByPeriod(int tenantID, DateTime startDate, DateTime endPeriod)
{
return WebstudioDbContext.WebstudioUserVisit
using var webstudioDbContext = _dbContextFactory.CreateDbContext();
return webstudioDbContext.WebstudioUserVisit
.Where(r => r.TenantId == tenantID)
.Where(r => r.VisitDate >= startDate && r.VisitDate <= endPeriod)
.OrderBy(r => r.VisitDate)
@ -106,8 +106,9 @@ public class StatisticManager
public List<UserVisit> GetHostsByPeriod(int tenantID, DateTime startDate, DateTime endPeriod)
{
using var webstudioDbContext = _dbContextFactory.CreateDbContext();
return
WebstudioDbContext.WebstudioUserVisit
webstudioDbContext.WebstudioUserVisit
.Where(r => r.TenantId == tenantID)
.Where(r => r.VisitDate >= startDate && r.VisitDate <= endPeriod)
.OrderBy(r => r.VisitDate)
@ -131,11 +132,13 @@ public class StatisticManager
_lastSave = DateTime.UtcNow;
}
var strategy = WebstudioDbContext.Database.CreateExecutionStrategy();
using var webstudioDbContext = _dbContextFactory.CreateDbContext();
var strategy = webstudioDbContext.Database.CreateExecutionStrategy();
strategy.Execute(() =>
{
using var tx = WebstudioDbContext.Database.BeginTransaction(IsolationLevel.ReadUncommitted);
using var webstudioDbContext = _dbContextFactory.CreateDbContext();
using var tx = webstudioDbContext.Database.BeginTransaction(IsolationLevel.ReadUncommitted);
foreach (var v in visits)
{
@ -154,8 +157,8 @@ public class StatisticManager
w.LastVisitTime = v.LastVisitTime.Value;
}
WebstudioDbContext.WebstudioUserVisit.Add(w);
WebstudioDbContext.SaveChanges();
webstudioDbContext.WebstudioUserVisit.Add(w);
webstudioDbContext.SaveChanges();
}
tx.Commit();
});