Merge branch 'feature/backend-refactor' into feature/people-refactor

This commit is contained in:
Maksim Chegulov 2022-03-01 15:27:07 +03:00
commit b48bd37ea6
433 changed files with 28971 additions and 29259 deletions

View File

@ -80,7 +80,7 @@ public class ConfirmAuthHandler : AuthenticationHandler<AuthenticationSchemeOpti
}
else
{
userId = _userManager.GetUserByEmail(emailValidationKeyModel.Email).ID;
userId = _userManager.GetUserByEmail(emailValidationKeyModel.Email).Id;
}
}
}

View File

@ -28,7 +28,7 @@ public class TenantStatusFilter : IResourceFilter
if (tenant.Status == TenantStatus.RemovePending || tenant.Status == TenantStatus.Suspended)
{
context.Result = new StatusCodeResult((int)HttpStatusCode.NotFound);
_logger.WarnFormat("Tenant {0} is not removed or suspended", tenant.TenantId);
_logger.WarnFormat("Tenant {0} is not removed or suspended", tenant.Id);
return;
}

View File

@ -88,7 +88,7 @@ public class EmployeeDtoHelper
protected EmployeeDto Init(EmployeeDto result, UserInfo userInfo)
{
result.Id = userInfo.ID;
result.Id = userInfo.Id;
result.DisplayName = _displayUserSettingsHelper.GetFullUserName(userInfo);
if (!string.IsNullOrEmpty(userInfo.Title))
@ -100,7 +100,7 @@ public class EmployeeDtoHelper
if (_httpContext.Check("avatarSmall"))
{
result.AvatarSmall = UserPhotoManager.GetSmallPhotoURL(userInfo.ID, out var isdef)
result.AvatarSmall = UserPhotoManager.GetSmallPhotoURL(userInfo.Id, out var isdef)
+ (isdef ? "" : $"?_={userInfoLM}");
}

View File

@ -126,7 +126,7 @@ public class EmployeeFullDtoHelper : EmployeeDtoHelper
if (apiContext.Check("Id"))
{
bindExprs.Add(Expression.Bind(typeof(UserInfo).GetProperty("ID"),
Expression.Property(parameter, typeof(User).GetProperty("Id"))));
Expression.Property(parameter, typeof(User).GetProperty("Id"))));
}
var body = Expression.MemberInit(newExpr, bindExprs);
@ -188,7 +188,7 @@ public class EmployeeFullDtoHelper : EmployeeDtoHelper
if (_context.Check("groups") || _context.Check("department"))
{
var groups = UserManager.GetUserGroups(userInfo.ID)
var groups = UserManager.GetUserGroups(userInfo.Id)
.Select(x => new GroupSummaryDto(x, UserManager))
.ToList();
@ -207,23 +207,23 @@ public class EmployeeFullDtoHelper : EmployeeDtoHelper
if (_context.Check("avatarMax"))
{
result.AvatarMax = UserPhotoManager.GetMaxPhotoURL(userInfo.ID, out var isdef) + (isdef ? "" : $"?_={userInfoLM}");
result.AvatarMax = UserPhotoManager.GetMaxPhotoURL(userInfo.Id, out var isdef) + (isdef ? "" : $"?_={userInfoLM}");
}
if (_context.Check("avatarMedium"))
{
result.AvatarMedium = UserPhotoManager.GetMediumPhotoURL(userInfo.ID, out var isdef) + (isdef ? "" : $"?_={userInfoLM}");
result.AvatarMedium = UserPhotoManager.GetMediumPhotoURL(userInfo.Id, out var isdef) + (isdef ? "" : $"?_={userInfoLM}");
}
if (_context.Check("avatar"))
{
result.Avatar = UserPhotoManager.GetBigPhotoURL(userInfo.ID, out var isdef) + (isdef ? "" : $"?_={userInfoLM}");
result.Avatar = UserPhotoManager.GetBigPhotoURL(userInfo.Id, out var isdef) + (isdef ? "" : $"?_={userInfoLM}");
}
if (_context.Check("listAdminModules"))
{
var listAdminModules = userInfo.GetListAdminModules(_webItemSecurity);
if (listAdminModules.Count > 0)
if (listAdminModules.Count > 0)
{
result.ListAdminModules = listAdminModules;
}
@ -249,7 +249,7 @@ public class EmployeeFullDtoHelper : EmployeeDtoHelper
}
}
if (contacts.Count > 0)
if (contacts.Count > 0)
{
employeeWraperFull.Contacts = contacts;
}

View File

@ -30,4 +30,5 @@ public interface ISecurityObjectId
{
object SecurityId { get; }
Type ObjectType { get; }
string FullId { get; }
}

View File

@ -30,6 +30,7 @@ public class SecurityObjectId : ISecurityObjectId
{
public object SecurityId { get; private set; }
public Type ObjectType { get; private set; }
public string FullId => AzObjectIdHelper.GetFullObjectId(this);
public SecurityObjectId(object id, Type objType)
{

View File

@ -23,219 +23,233 @@
*
*/
namespace ASC.Core.Common
namespace ASC.Core.Common;
[Scope]
public class CommonLinkUtilitySettings
{
[Scope]
public class CommonLinkUtilitySettings
public string ServerUri { get; set; }
}
[Scope]
public class BaseCommonLinkUtility
{
private const string LocalHost = "localhost";
private UriBuilder _serverRoot;
private string _vpath;
protected IHttpContextAccessor HttpContextAccessor;
public BaseCommonLinkUtility(
CoreBaseSettings coreBaseSettings,
CoreSettings coreSettings,
TenantManager tenantManager,
IOptionsMonitor<ILog> options,
CommonLinkUtilitySettings settings)
: this(null, coreBaseSettings, coreSettings, tenantManager, options, settings)
{
public string ServerUri { get; set; }
}
[Scope]
public class BaseCommonLinkUtility
public BaseCommonLinkUtility(
IHttpContextAccessor httpContextAccessor,
CoreBaseSettings coreBaseSettings,
CoreSettings coreSettings,
TenantManager tenantManager,
IOptionsMonitor<ILog> options,
CommonLinkUtilitySettings settings)
{
private const string LOCALHOST = "localhost";
var serverUri = settings.ServerUri;
private UriBuilder _serverRoot;
private string _vpath;
protected IHttpContextAccessor HttpContextAccessor { get; set; }
public BaseCommonLinkUtility(
CoreBaseSettings coreBaseSettings,
CoreSettings coreSettings,
TenantManager tenantManager,
IOptionsMonitor<ILog> options,
CommonLinkUtilitySettings settings)
: this(null, coreBaseSettings, coreSettings, tenantManager, options, settings)
{
}
public BaseCommonLinkUtility(
IHttpContextAccessor httpContextAccessor,
CoreBaseSettings coreBaseSettings,
CoreSettings coreSettings,
TenantManager tenantManager,
IOptionsMonitor<ILog> options,
CommonLinkUtilitySettings settings)
{
var serverUri = settings.ServerUri;
if (!string.IsNullOrEmpty(serverUri))
{
var uri = new Uri(serverUri.Replace('*', 'x').Replace('+', 'x'));
_serverRoot = new UriBuilder(uri.Scheme, uri.Host != "x" ? uri.Host : LOCALHOST, uri.Port);
_vpath = "/" + uri.AbsolutePath.Trim('/');
}
else
{
try
{
HttpContextAccessor = httpContextAccessor;
var uriBuilder = new UriBuilder(Uri.UriSchemeHttp, LOCALHOST);
if (HttpContextAccessor?.HttpContext?.Request != null)
{
var u = HttpContextAccessor?.HttpContext.Request.GetUrlRewriter();
if (u == null) throw new ArgumentNullException("u");
uriBuilder = new UriBuilder(u.Scheme, LOCALHOST, u.Port);
}
_serverRoot = uriBuilder;
}
catch (Exception error)
{
options.Get("ASC.Web").Error(error);
}
}
CoreBaseSettings = coreBaseSettings;
CoreSettings = coreSettings;
TenantManager = tenantManager;
}
public string VirtualRoot
{
get { return ToAbsolute("~"); }
}
protected CoreBaseSettings CoreBaseSettings { get; }
private CoreSettings CoreSettings { get; }
protected TenantManager TenantManager { get; }
private string serverRootPath;
public string ServerRootPath
{
get
{
if (!string.IsNullOrEmpty(serverRootPath)) return serverRootPath;
UriBuilder result;
// first, take from current request
if (HttpContextAccessor?.HttpContext?.Request != null)
{
var u = HttpContextAccessor?.HttpContext?.Request.GetUrlRewriter();
if (u == null) throw new ArgumentNullException("u");
result = new UriBuilder(u.Scheme, u.Host, u.Port);
if (CoreBaseSettings.Standalone && !result.Uri.IsLoopback)
{
// save for stanalone
_serverRoot.Host = result.Host;
}
}
else
{
result = new UriBuilder(_serverRoot.Uri);
}
if (result.Uri.IsLoopback)
{
// take values from db if localhost or no http context thread
var tenant = TenantManager.GetCurrentTenant();
result.Host = tenant.GetTenantDomain(CoreSettings);
#if DEBUG
// for Visual Studio debug
if (tenant.TenantAlias == LOCALHOST)
{
result.Host = LOCALHOST;
}
#endif
if (!string.IsNullOrEmpty(tenant.MappedDomain))
{
var mapped = tenant.MappedDomain.ToLowerInvariant();
if (!mapped.Contains(Uri.SchemeDelimiter))
{
mapped = Uri.UriSchemeHttp + Uri.SchemeDelimiter + mapped;
}
result = new UriBuilder(mapped);
}
}
return serverRootPath = result.Uri.ToString().TrimEnd('/');
}
}
public string GetFullAbsolutePath(string virtualPath)
{
if (string.IsNullOrEmpty(virtualPath))
{
return ServerRootPath;
}
if (virtualPath.StartsWith("http://", StringComparison.InvariantCultureIgnoreCase) ||
virtualPath.StartsWith("mailto:", StringComparison.InvariantCultureIgnoreCase) ||
virtualPath.StartsWith("javascript:", StringComparison.InvariantCultureIgnoreCase) ||
virtualPath.StartsWith("https://", StringComparison.InvariantCultureIgnoreCase))
return virtualPath;
if (virtualPath.StartsWith('/'))
{
return ServerRootPath + virtualPath;
}
return ServerRootPath + VirtualRoot.TrimEnd('/') + "/" + virtualPath.TrimStart('~', '/');
}
public string ToAbsolute(string virtualPath)
{
if (_vpath == null)
{
return VirtualPathUtility.ToAbsolute(virtualPath);
}
if (string.IsNullOrEmpty(virtualPath) || virtualPath.StartsWith('/'))
{
return virtualPath;
}
return (_vpath != "/" ? _vpath : string.Empty) + "/" + virtualPath.TrimStart('~', '/');
}
public static string GetRegionalUrl(string url, string lang)
{
if (string.IsNullOrEmpty(url))
return url;
//-replace language
var regex = new Regex("{.*?}");
var matches = regex.Matches(url);
if (string.IsNullOrEmpty(lang))
{
url = matches.Aggregate(url, (current, match) => current.Replace(match.Value, string.Empty));
}
else
{
foreach (Match match in matches)
{
var values = match.Value.TrimStart('{').TrimEnd('}').Split('|');
url = url.Replace(match.Value, values.Contains(lang) ? lang : string.Empty);
}
}
//-
//--remove redundant slashes
var uri = new Uri(url);
if (uri.Scheme == "mailto")
return uri.OriginalString;
var baseUri = new UriBuilder(uri.Scheme, uri.Host, uri.Port).Uri;
baseUri = uri.Segments.Aggregate(baseUri, (current, segment) => new Uri(current, segment));
//--
//todo: lost query string!!!
return baseUri.ToString().TrimEnd('/');
}
public void Initialize(string serverUri, bool localhost = true)
if (!string.IsNullOrEmpty(serverUri))
{
var uri = new Uri(serverUri.Replace('*', 'x').Replace('+', 'x'));
_serverRoot = new UriBuilder(uri.Scheme, localhost ? LOCALHOST : uri.Host, uri.Port);
_serverRoot = new UriBuilder(uri.Scheme, uri.Host != "x" ? uri.Host : LocalHost, uri.Port);
_vpath = "/" + uri.AbsolutePath.Trim('/');
}
else
{
try
{
HttpContextAccessor = httpContextAccessor;
var uriBuilder = new UriBuilder(Uri.UriSchemeHttp, LocalHost);
if (HttpContextAccessor?.HttpContext?.Request != null)
{
var u = HttpContextAccessor?.HttpContext.Request.GetUrlRewriter();
if (u == null)
{
throw new ArgumentNullException(nameof(u));
}
uriBuilder = new UriBuilder(u.Scheme, LocalHost, u.Port);
}
_serverRoot = uriBuilder;
}
catch (Exception error)
{
options.Get("ASC.Web").Error(error);
}
}
CoreBaseSettings = coreBaseSettings;
_coreSettings = coreSettings;
TenantManager = tenantManager;
}
public string VirtualRoot => ToAbsolute("~");
protected CoreBaseSettings CoreBaseSettings;
private readonly CoreSettings _coreSettings;
protected TenantManager TenantManager;
private string _serverRootPath;
public string ServerRootPath
{
get
{
if (!string.IsNullOrEmpty(_serverRootPath))
{
return _serverRootPath;
}
UriBuilder result;
// first, take from current request
if (HttpContextAccessor?.HttpContext?.Request != null)
{
var u = HttpContextAccessor?.HttpContext?.Request.GetUrlRewriter();
if (u == null)
{
throw new ArgumentNullException(nameof(u));
}
result = new UriBuilder(u.Scheme, u.Host, u.Port);
if (CoreBaseSettings.Standalone && !result.Uri.IsLoopback)
{
// save for stanalone
_serverRoot.Host = result.Host;
}
}
else
{
result = new UriBuilder(_serverRoot.Uri);
}
if (result.Uri.IsLoopback)
{
// take values from db if localhost or no http context thread
var tenant = TenantManager.GetCurrentTenant();
result.Host = tenant.GetTenantDomain(_coreSettings);
#if DEBUG
// for Visual Studio debug
if (tenant.Alias == LocalHost)
{
result.Host = LocalHost;
}
#endif
if (!string.IsNullOrEmpty(tenant.MappedDomain))
{
var mapped = tenant.MappedDomain.ToLowerInvariant();
if (!mapped.Contains(Uri.SchemeDelimiter))
{
mapped = Uri.UriSchemeHttp + Uri.SchemeDelimiter + mapped;
}
result = new UriBuilder(mapped);
}
}
return _serverRootPath = result.Uri.ToString().TrimEnd('/');
}
}
public string GetFullAbsolutePath(string virtualPath)
{
if (string.IsNullOrEmpty(virtualPath))
{
return ServerRootPath;
}
if (virtualPath.StartsWith("http://", StringComparison.InvariantCultureIgnoreCase) ||
virtualPath.StartsWith("mailto:", StringComparison.InvariantCultureIgnoreCase) ||
virtualPath.StartsWith("javascript:", StringComparison.InvariantCultureIgnoreCase) ||
virtualPath.StartsWith("https://", StringComparison.InvariantCultureIgnoreCase))
{
return virtualPath;
}
if (virtualPath.StartsWith('/'))
{
return ServerRootPath + virtualPath;
}
return ServerRootPath + VirtualRoot.TrimEnd('/') + "/" + virtualPath.TrimStart('~', '/');
}
public string ToAbsolute(string virtualPath)
{
if (_vpath == null)
{
return VirtualPathUtility.ToAbsolute(virtualPath);
}
if (string.IsNullOrEmpty(virtualPath) || virtualPath.StartsWith('/'))
{
return virtualPath;
}
return (_vpath != "/" ? _vpath : string.Empty) + "/" + virtualPath.TrimStart('~', '/');
}
public static string GetRegionalUrl(string url, string lang)
{
if (string.IsNullOrEmpty(url))
{
return url;
}
//-replace language
var regex = new Regex("{.*?}");
var matches = regex.Matches(url);
if (string.IsNullOrEmpty(lang))
{
url = matches.Aggregate(url, (current, match) => current.Replace(match.Value, string.Empty));
}
else
{
foreach (Match match in matches)
{
var values = match.Value.TrimStart('{').TrimEnd('}').Split('|');
url = url.Replace(match.Value, values.Contains(lang) ? lang : string.Empty);
}
}
//-
//--remove redundant slashes
var uri = new Uri(url);
if (uri.Scheme == "mailto")
{
return uri.OriginalString;
}
var baseUri = new UriBuilder(uri.Scheme, uri.Host, uri.Port).Uri;
baseUri = uri.Segments.Aggregate(baseUri, (current, segment) => new Uri(current, segment));
//--
//todo: lost query string!!!
return baseUri.ToString().TrimEnd('/');
}
public void Initialize(string serverUri, bool localhost = true)
{
var uri = new Uri(serverUri.Replace('*', 'x').Replace('+', 'x'));
_serverRoot = new UriBuilder(uri.Scheme, localhost ? LocalHost : uri.Host, uri.Port);
_vpath = "/" + uri.AbsolutePath.Trim('/');
}
}

View File

@ -25,333 +25,336 @@
using JsonSerializer = System.Text.Json.JsonSerializer;
namespace ASC.Core.Billing
namespace ASC.Core.Billing;
[Singletone]
public class BillingClient
{
[Singletone]
public class BillingClient
public readonly bool Configured = false;
private readonly string _billingDomain;
private readonly string _billingKey;
private readonly string _billingSecret;
private readonly bool _test;
private const int AvangatePaymentSystemId = 1;
private static readonly HttpClient _httpClient = new HttpClient();
public BillingClient(IConfiguration configuration)
: this(false, configuration)
{
public readonly bool Configured = false;
private readonly string _billingDomain;
private readonly string _billingKey;
private readonly string _billingSecret;
private readonly bool _test;
}
private const int AvangatePaymentSystemId = 1;
public BillingClient(bool test, IConfiguration configuration)
{
_test = test;
static readonly HttpClient HttpClient = new HttpClient();
var billingDomain = configuration["core:payment-url"];
public BillingClient(IConfiguration configuration)
: this(false, configuration)
_billingDomain = (billingDomain ?? "").Trim().TrimEnd('/');
if (!string.IsNullOrEmpty(_billingDomain))
{
_billingDomain += "/billing/";
_billingKey = configuration["core:payment-key"];
_billingSecret = configuration["core:payment-secret"];
Configured = true;
}
}
public PaymentLast GetLastPayment(string portalId)
{
var result = Request("GetActiveResource", portalId);
var paymentLast = JsonSerializer.Deserialize<PaymentLast>(result);
if (!_test && paymentLast.PaymentStatus == 4)
{
throw new BillingException("Can not accept test payment.", new { PortalId = portalId });
}
public BillingClient(bool test, IConfiguration configuration)
return paymentLast;
}
public IEnumerable<PaymentInfo> GetPayments(string portalId)
{
string result = Request("GetPayments", portalId);
var payments = JsonSerializer.Deserialize<List<PaymentInfo>>(result);
return payments;
}
public IDictionary<string, Tuple<Uri, Uri>> GetPaymentUrls(string portalId, string[] products, string affiliateId = null, string campaign = null, string currency = null, string language = null, string customerId = null, string quantity = null)
{
var urls = new Dictionary<string, Tuple<Uri, Uri>>();
var additionalParameters = new List<Tuple<string, string>>() { Tuple.Create("PaymentSystemId", AvangatePaymentSystemId.ToString()) };
if (!string.IsNullOrEmpty(affiliateId))
{
_test = test;
additionalParameters.Add(Tuple.Create("AffiliateId", affiliateId));
}
if (!string.IsNullOrEmpty(campaign))
{
additionalParameters.Add(Tuple.Create("campaign", campaign));
}
if (!string.IsNullOrEmpty(currency))
{
additionalParameters.Add(Tuple.Create("Currency", currency));
}
if (!string.IsNullOrEmpty(language))
{
additionalParameters.Add(Tuple.Create("Language", language));
}
if (!string.IsNullOrEmpty(customerId))
{
additionalParameters.Add(Tuple.Create("CustomerID", customerId));
}
if (!string.IsNullOrEmpty(quantity))
{
additionalParameters.Add(Tuple.Create("Quantity", quantity));
}
var billingDomain = configuration["core:payment-url"];
var parameters = products
.Distinct()
.Select(p => Tuple.Create("ProductId", p))
.Concat(additionalParameters)
.ToArray();
_billingDomain = (billingDomain ?? "").Trim().TrimEnd('/');
if (!string.IsNullOrEmpty(_billingDomain))
//max 100 products
var result = Request("GetPaymentUrl", portalId, parameters);
var paymentUrls = JsonSerializer.Deserialize<Dictionary<string, string>>(result);
var upgradeUrls = new Dictionary<string, string>();
if (!string.IsNullOrEmpty(portalId)
//TODO: remove
&& false)
{
try
{
//max 100 products
result = Request("GetPaymentUpgradeUrl", portalId, parameters);
upgradeUrls = JsonSerializer.Deserialize<Dictionary<string, string>>(result);
}
catch (BillingNotFoundException)
{
_billingDomain += "/billing/";
_billingKey = configuration["core:payment-key"];
_billingSecret = configuration["core:payment-secret"];
Configured = true;
}
}
public PaymentLast GetLastPayment(string portalId)
foreach (var p in products)
{
var result = Request("GetActiveResource", portalId);
var paymentLast = JsonSerializer.Deserialize<PaymentLast>(result);
if (!_test && paymentLast.PaymentStatus == 4)
string url;
var paymentUrl = (Uri)null;
var upgradeUrl = (Uri)null;
if (paymentUrls.TryGetValue(p, out url))
{
throw new BillingException("Can not accept test payment.", new { PortalId = portalId });
}
return paymentLast;
}
public IEnumerable<PaymentInfo> GetPayments(string portalId)
{
string result = Request("GetPayments", portalId);
var payments = JsonSerializer.Deserialize<List<PaymentInfo>>(result);
return payments;
}
public IDictionary<string, Tuple<Uri, Uri>> GetPaymentUrls(string portalId, string[] products, string affiliateId = null, string campaign = null, string currency = null, string language = null, string customerId = null, string quantity = null)
{
var urls = new Dictionary<string, Tuple<Uri, Uri>>();
var additionalParameters = new List<Tuple<string, string>>() { Tuple.Create("PaymentSystemId", AvangatePaymentSystemId.ToString()) };
if (!string.IsNullOrEmpty(affiliateId))
{
additionalParameters.Add(Tuple.Create("AffiliateId", affiliateId));
}
if (!string.IsNullOrEmpty(campaign))
{
additionalParameters.Add(Tuple.Create("campaign", campaign));
}
if (!string.IsNullOrEmpty(currency))
{
additionalParameters.Add(Tuple.Create("Currency", currency));
}
if (!string.IsNullOrEmpty(language))
{
additionalParameters.Add(Tuple.Create("Language", language));
}
if (!string.IsNullOrEmpty(customerId))
{
additionalParameters.Add(Tuple.Create("CustomerID", customerId));
}
if (!string.IsNullOrEmpty(quantity))
{
additionalParameters.Add(Tuple.Create("Quantity", quantity));
}
var parameters = products
.Distinct()
.Select(p => Tuple.Create("ProductId", p))
.Concat(additionalParameters)
.ToArray();
//max 100 products
var result = Request("GetPaymentUrl", portalId, parameters);
var paymentUrls = JsonSerializer.Deserialize<Dictionary<string, string>>(result);
var upgradeUrls = new Dictionary<string, string>();
if (!string.IsNullOrEmpty(portalId)
//TODO: remove
&& false)
{
try
{
//max 100 products
result = Request("GetPaymentUpgradeUrl", portalId, parameters);
upgradeUrls = JsonSerializer.Deserialize<Dictionary<string, string>>(result);
}
catch (BillingNotFoundException)
url = ToUrl(url);
if (!string.IsNullOrEmpty(url))
{
paymentUrl = new Uri(url);
}
}
foreach (var p in products)
if (upgradeUrls.TryGetValue(p, out url))
{
string url;
var paymentUrl = (Uri)null;
var upgradeUrl = (Uri)null;
if (paymentUrls.TryGetValue(p, out url))
url = ToUrl(url);
if (!string.IsNullOrEmpty(url))
{
url = ToUrl(url);
if (!string.IsNullOrEmpty(url))
{
paymentUrl = new Uri(url);
}
upgradeUrl = new Uri(url);
}
if (upgradeUrls.TryGetValue(p, out url))
{
url = ToUrl(url);
if (!string.IsNullOrEmpty(url))
{
upgradeUrl = new Uri(url);
}
}
urls[p] = Tuple.Create(paymentUrl, upgradeUrl);
}
return urls;
urls[p] = Tuple.Create(paymentUrl, upgradeUrl);
}
public IDictionary<string, Dictionary<string, decimal>> GetProductPriceInfo(params string[] productIds)
return urls;
}
public IDictionary<string, Dictionary<string, decimal>> GetProductPriceInfo(params string[] productIds)
{
if (productIds == null)
{
if (productIds == null)
{
throw new ArgumentNullException(nameof(productIds));
}
var parameters = productIds.Select(pid => Tuple.Create("ProductId", pid)).ToList();
parameters.Add(Tuple.Create("PaymentSystemId", AvangatePaymentSystemId.ToString()));
var result = Request("GetProductsPrices", null, parameters.ToArray());
var prices = JsonSerializer.Deserialize<Dictionary<int, Dictionary<string, Dictionary<string, decimal>>>>(result);
if (prices.TryGetValue(AvangatePaymentSystemId, out var pricesPaymentSystem))
{
return productIds.Select(productId =>
{
if (pricesPaymentSystem.TryGetValue(productId, out var prices))
{
return new { ProductId = productId, Prices = prices };
}
return new { ProductId = productId, Prices = new Dictionary<string, decimal>() };
})
.ToDictionary(e => e.ProductId, e => e.Prices);
}
return new Dictionary<string, Dictionary<string, decimal>>();
throw new ArgumentNullException(nameof(productIds));
}
var parameters = productIds.Select(pid => Tuple.Create("ProductId", pid)).ToList();
parameters.Add(Tuple.Create("PaymentSystemId", AvangatePaymentSystemId.ToString()));
private string CreateAuthToken(string pkey, string machinekey)
var result = Request("GetProductsPrices", null, parameters.ToArray());
var prices = JsonSerializer.Deserialize<Dictionary<int, Dictionary<string, Dictionary<string, decimal>>>>(result);
if (prices.TryGetValue(AvangatePaymentSystemId, out var pricesPaymentSystem))
{
using (var hasher = new HMACSHA1(Encoding.UTF8.GetBytes(machinekey)))
return productIds.Select(productId =>
{
var now = DateTime.UtcNow.ToString("yyyyMMddHHmmss");
var hash = WebEncoders.Base64UrlEncode(hasher.ComputeHash(Encoding.UTF8.GetBytes(string.Join("\n", now, pkey))));
return "ASC " + pkey + ":" + now + ":" + hash;
if (pricesPaymentSystem.TryGetValue(productId, out var prices))
{
return new { ProductId = productId, Prices = prices };
}
return new { ProductId = productId, Prices = new Dictionary<string, decimal>() };
})
.ToDictionary(e => e.ProductId, e => e.Prices);
}
return new Dictionary<string, Dictionary<string, decimal>>();
}
private string CreateAuthToken(string pkey, string machinekey)
{
using (var hasher = new HMACSHA1(Encoding.UTF8.GetBytes(machinekey)))
{
var now = DateTime.UtcNow.ToString("yyyyMMddHHmmss");
var hash = WebEncoders.Base64UrlEncode(hasher.ComputeHash(Encoding.UTF8.GetBytes(string.Join("\n", now, pkey))));
return "ASC " + pkey + ":" + now + ":" + hash;
}
}
private string Request(string method, string portalId, params Tuple<string, string>[] parameters)
{
var url = _billingDomain + method;
var request = new HttpRequestMessage();
request.RequestUri = new Uri(url);
request.Method = HttpMethod.Post;
if (!string.IsNullOrEmpty(_billingKey))
{
request.Headers.Add("Authorization", CreateAuthToken(_billingKey, _billingSecret));
}
_httpClient.Timeout = TimeSpan.FromMilliseconds(60000);
var data = new Dictionary<string, List<string>>();
if (!string.IsNullOrEmpty(portalId))
{
data.Add("PortalId", new List<string>() { portalId });
}
foreach (var parameter in parameters)
{
if (!data.ContainsKey(parameter.Item1))
{
data.Add(parameter.Item1, new List<string>() { parameter.Item2 });
}
else
{
data[parameter.Item1].Add(parameter.Item2);
}
}
private string Request(string method, string portalId, params Tuple<string, string>[] parameters)
var body = JsonSerializer.Serialize(data);
request.Content = new StringContent(body, Encoding.UTF8, "application/json");
string result;
using (var response = _httpClient.Send(request))
using (var stream = response.Content.ReadAsStream())
{
var url = _billingDomain + method;
var request = new HttpRequestMessage();
request.RequestUri = new Uri(url);
request.Method = HttpMethod.Post;
if (!string.IsNullOrEmpty(_billingKey))
{
request.Headers.Add("Authorization", CreateAuthToken(_billingKey, _billingSecret));
}
HttpClient.Timeout = TimeSpan.FromMilliseconds(60000);
var data = new Dictionary<string, List<string>>();
if (!string.IsNullOrEmpty(portalId))
{
data.Add("PortalId", new List<string>() { portalId });
}
foreach (var parameter in parameters)
{
if (!data.ContainsKey(parameter.Item1))
{
data.Add(parameter.Item1, new List<string>() { parameter.Item2 });
}
else
{
data[parameter.Item1].Add(parameter.Item2);
}
}
var body = JsonSerializer.Serialize(data);
request.Content = new StringContent(body, Encoding.UTF8, "application/json");
string result;
using (var response = HttpClient.Send(request))
using (var stream = response.Content.ReadAsStream())
{
if (stream == null)
{
throw new BillingNotConfiguredException("Billing response is null");
}
using (var readStream = new StreamReader(stream))
{
result = readStream.ReadToEnd();
}
}
if (string.IsNullOrEmpty(result))
if (stream == null)
{
throw new BillingNotConfiguredException("Billing response is null");
}
if (!result.StartsWith("{\"Message\":\"error"))
using (var readStream = new StreamReader(stream))
{
return result;
result = readStream.ReadToEnd();
}
var @params = parameters.Select(p => p.Item1 + ": " + p.Item2);
var info = new { Method = method, PortalId = portalId, Params = string.Join(", ", @params) };
if (result.Contains("{\"Message\":\"error: cannot find "))
{
throw new BillingNotFoundException(result, info);
}
throw new BillingException(result, info);
}
private string ToUrl(string s)
if (string.IsNullOrEmpty(result))
{
s = s.Trim();
if (s.StartsWith("error", StringComparison.InvariantCultureIgnoreCase))
{
return string.Empty;
}
if (_test && !s.Contains("&DOTEST = 1"))
{
s += "&DOTEST=1";
}
return s;
throw new BillingNotConfiguredException("Billing response is null");
}
if (!result.StartsWith("{\"Message\":\"error"))
{
return result;
}
var @params = parameters.Select(p => p.Item1 + ": " + p.Item2);
var info = new { Method = method, PortalId = portalId, Params = string.Join(", ", @params) };
if (result.Contains("{\"Message\":\"error: cannot find "))
{
throw new BillingNotFoundException(result, info);
}
throw new BillingException(result, info);
}
[ServiceContract]
public interface IService
private string ToUrl(string s)
{
[OperationContract]
Message Request(Message message);
}
s = s.Trim();
if (s.StartsWith("error", StringComparison.InvariantCultureIgnoreCase))
{
return string.Empty;
}
[Serializable]
public class Message
if (_test && !s.Contains("&DOTEST = 1"))
{
s += "&DOTEST=1";
}
return s;
}
}
[ServiceContract]
public interface IService
{
[OperationContract]
Message Request(Message message);
}
[Serializable]
public class Message
{
public string Content { get; set; }
public MessageType Type { get; set; }
}
public enum MessageType
{
Undefined = 0,
Data = 1,
Error = 2,
}
[Serializable]
public class BillingException : Exception
{
public BillingException(string message, object debugInfo = null) : base(message + (debugInfo != null ? " Debug info: " + debugInfo : string.Empty))
{
public string Content { get; set; }
public MessageType Type { get; set; }
}
public enum MessageType
public BillingException(string message, Exception inner) : base(message, inner)
{
Undefined = 0,
Data = 1,
Error = 2,
}
[Serializable]
public class BillingException : Exception
protected BillingException(SerializationInfo info, StreamingContext context) : base(info, context)
{
public BillingException(string message, object debugInfo = null) : base(message + (debugInfo != null ? " Debug info: " + debugInfo : string.Empty))
{
}
public BillingException(string message, Exception inner) : base(message, inner)
{
}
protected BillingException(SerializationInfo info, StreamingContext context) : base(info, context)
{
}
}
}
[Serializable]
public class BillingNotFoundException : BillingException
[Serializable]
public class BillingNotFoundException : BillingException
{
public BillingNotFoundException(string message, object debugInfo = null) : base(message, debugInfo)
{
public BillingNotFoundException(string message, object debugInfo = null) : base(message, debugInfo)
{
}
protected BillingNotFoundException(SerializationInfo info, StreamingContext context) : base(info, context)
{
}
}
[Serializable]
public class BillingNotConfiguredException : BillingException
protected BillingNotFoundException(SerializationInfo info, StreamingContext context) : base(info, context)
{
public BillingNotConfiguredException(string message, object debugInfo = null) : base(message, debugInfo)
{
}
public BillingNotConfiguredException(string message, Exception inner) : base(message, inner)
{
}
protected BillingNotConfiguredException(SerializationInfo info, StreamingContext context) : base(info, context)
{
}
}
}
}
[Serializable]
public class BillingNotConfiguredException : BillingException
{
public BillingNotConfiguredException(string message, object debugInfo = null) : base(message, debugInfo)
{
}
public BillingNotConfiguredException(string message, Exception inner) : base(message, inner)
{
}
protected BillingNotConfiguredException(SerializationInfo info, StreamingContext context) : base(info, context)
{
}
}

View File

@ -26,296 +26,297 @@
using ConfigurationManager = System.Configuration.ConfigurationManager;
using ConfigurationSection = System.Configuration.ConfigurationSection;
namespace ASC.Core.Common.Billing
namespace ASC.Core.Common.Billing;
[Singletone]
public class CouponManager
{
[Singletone]
public class CouponManager
{
private IEnumerable<AvangateProduct> Products { get; set; }
private IHttpClientFactory ClientFactory { get; }
private IEnumerable<string> Groups { get; set; }
private readonly int Percent;
private readonly int Schedule;
private readonly string VendorCode;
private readonly byte[] Secret;
private readonly Uri BaseAddress;
private readonly string ApiVersion;
private readonly SemaphoreSlim SemaphoreSlim;
private readonly ILog Log;
public CouponManager(IOptionsMonitor<ILog> option, IHttpClientFactory clientFactory)
{
SemaphoreSlim = new SemaphoreSlim(1, 1);
Log = option.CurrentValue;
ClientFactory = clientFactory;
try
{
var cfg = (AvangateCfgSectionHandler)ConfigurationManager.GetSection("avangate");
Secret = Encoding.UTF8.GetBytes(cfg.Secret);
VendorCode = cfg.Vendor;
Percent = cfg.Percent;
Schedule = cfg.Schedule;
BaseAddress = new Uri(cfg.BaseAddress);
ApiVersion = "/rest/" + cfg.ApiVersion.TrimStart('/');
Groups = (cfg.Groups ?? "").Split(',', '|', ' ');
}
catch (Exception e)
{
Secret = Encoding.UTF8.GetBytes("");
VendorCode = "";
Percent = AvangateCfgSectionHandler.DefaultPercent;
Schedule = AvangateCfgSectionHandler.DefaultShedule;
BaseAddress = new Uri(AvangateCfgSectionHandler.DefaultAdress);
ApiVersion = AvangateCfgSectionHandler.DefaultApiVersion;
Groups = new List<string>();
Log.Fatal(e);
}
}
public string CreateCoupon(TenantManager tenantManager)
{
return CreatePromotionAsync(tenantManager).Result;
}
private async Task<string> CreatePromotionAsync(TenantManager tenantManager)
{
try
{
using var httpClient = PrepaireClient();
using var content = new StringContent(await Promotion.GeneratePromotion(Log, this, tenantManager, Percent, Schedule), Encoding.Default, "application/json");
using var response = await httpClient.PostAsync($"{ApiVersion}/promotions/", content);
if (!response.IsSuccessStatusCode)
throw new Exception(response.ReasonPhrase);
var result = await response.Content.ReadAsStringAsync();
await Task.Delay(1000 - DateTime.UtcNow.Millisecond); // otherwise authorize exception
var createdPromotion = JsonConvert.DeserializeObject<Promotion>(result);
return createdPromotion.Coupon.Code;
}
catch (Exception ex)
{
Log.Error(ex.Message, ex);
throw;
}
}
internal Task<IEnumerable<AvangateProduct>> GetProducts()
{
if (Products != null) return Task.FromResult(Products);
return InternalGetProducts();
}
private async Task<IEnumerable<AvangateProduct>> InternalGetProducts()
private IEnumerable<AvangateProduct> _products;
private readonly IHttpClientFactory _clientFactory;
private IEnumerable<string> _groups;
private readonly int _percent;
private readonly int _schedule;
private readonly string _vendorCode;
private readonly byte[] _secret;
private readonly Uri _baseAddress;
private readonly string _apiVersion;
private readonly SemaphoreSlim _semaphoreSlim;
private readonly ILog _logger;
public CouponManager(IOptionsMonitor<ILog> option, IHttpClientFactory clientFactory)
{
_semaphoreSlim = new SemaphoreSlim(1, 1);
_logger = option.CurrentValue;
_clientFactory = clientFactory;
try
{
await SemaphoreSlim.WaitAsync();
if (Products != null)
{
SemaphoreSlim.Release();
return Products;
}
try
{
using var httpClient = PrepaireClient();
using var response = await httpClient.GetAsync($"{ApiVersion}/products/?Limit=1000&Enabled=true");
if (!response.IsSuccessStatusCode)
throw new Exception(response.ReasonPhrase);
var result = await response.Content.ReadAsStringAsync();
Log.Debug(result);
var products = JsonConvert.DeserializeObject<List<AvangateProduct>>(result);
products = products.Where(r => r.ProductGroup != null && Groups.Contains(r.ProductGroup.Code)).ToList();
return Products = products;
}
catch (Exception ex)
{
Log.Error(ex.Message, ex);
throw;
}
finally
{
SemaphoreSlim.Release();
}
}
private HttpClient PrepaireClient()
{
const string applicationJson = "application/json";
var httpClient = ClientFactory.CreateClient();
httpClient.BaseAddress = BaseAddress;
httpClient.Timeout = TimeSpan.FromMinutes(3);
httpClient.DefaultRequestHeaders.TryAddWithoutValidation("accept", applicationJson);
httpClient.DefaultRequestHeaders.TryAddWithoutValidation("Content-Type", applicationJson);
httpClient.DefaultRequestHeaders.TryAddWithoutValidation("X-Avangate-Authentication", CreateAuthHeader());
return httpClient;
}
private string CreateAuthHeader()
{
using var hmac = new HMACMD5(Secret);
var date = DateTime.UtcNow.ToString("yyyy-MM-dd HH:mm:ss");
var hash = VendorCode.Length + VendorCode + date.Length + date;
var data = hmac.ComputeHash(Encoding.UTF8.GetBytes(hash));
var sBuilder = new StringBuilder();
foreach (var t in data)
{
sBuilder.Append(t.ToString("x2"));
}
var stringBuilder = new StringBuilder();
stringBuilder.Append($"code='{VendorCode}' ");
stringBuilder.Append($"date='{date}' ");
stringBuilder.Append($"hash='{sBuilder}'");
return stringBuilder.ToString();
}
}
class Promotion
{
public string Code { get; set; }
public string Name { get; set; }
public string Type { get; set; }
public string StartDate { get; set; }
public string EndDate { get; set; }
public bool Enabled { get; set; }
public int MaximumOrdersNumber { get; set; }
public bool InstantDiscount { get; set; }
public string ChannelType { get; set; }
public string ApplyRecurring { get; set; }
public Coupon Coupon { get; set; }
public Discount Discount { get; set; }
public IEnumerable<CouponProduct> Products { get; set; }
public int PublishToAffiliatesNetwork { get; set; }
public int AutoApply { get; set; }
public static async Task<string> GeneratePromotion(ILog log, CouponManager couponManager, TenantManager tenantManager, int percent, int schedule)
{
try
{
var tenant = tenantManager.GetCurrentTenant();
var startDate = DateTime.UtcNow.Date;
var endDate = startDate.AddDays(schedule);
var code = tenant.TenantAlias;
var promotion = new Promotion
{
Type = "REGULAR",
Enabled = true,
MaximumOrdersNumber = 1,
InstantDiscount = false,
ChannelType = "ECOMMERCE",
ApplyRecurring = "NONE",
PublishToAffiliatesNetwork = 0,
AutoApply = 0,
StartDate = startDate.ToString("yyyy-MM-dd"),
EndDate = endDate.ToString("yyyy-MM-dd"),
Name = string.Format("{0} {1}% off", code, percent),
Coupon = new Coupon { Type = "SINGLE", Code = code },
Discount = new Discount { Type = "PERCENT", Value = percent },
Products = (await couponManager.GetProducts()).Select(r => new CouponProduct { Code = r.ProductCode })
};
return JsonConvert.SerializeObject(promotion);
}
catch (Exception ex)
{
log.Error(ex.Message, ex);
throw;
}
}
}
class Coupon
{
public string Type { get; set; }
public string Code { get; set; }
}
class Discount
{
public string Type { get; set; }
public int Value { get; set; }
}
class AvangateProduct
{
public string ProductCode { get; set; }
public string ProductName { get; set; }
public AvangateProductGroup ProductGroup { get; set; }
}
class AvangateProductGroup
{
public string Name { get; set; }
public string Code { get; set; }
}
class CouponProduct
{
public string Code { get; set; }
}
class AvangateCfgSectionHandler : ConfigurationSection
{
public const string DefaultAdress = "https://api.avangate.com/";
public const string DefaultApiVersion = "4.0";
public const int DefaultPercent = 5;
public const int DefaultShedule = 10;
[ConfigurationProperty("secret")]
public string Secret
{
get { return (string)this["secret"]; }
}
[ConfigurationProperty("vendor")]
public string Vendor
{
get { return (string)this["vendor"]; }
set { this["vendor"] = value; }
}
[ConfigurationProperty("percent", DefaultValue = DefaultPercent)]
public int Percent
{
get { return Convert.ToInt32(this["percent"]); }
set { this["percent"] = value; }
}
[ConfigurationProperty("schedule", DefaultValue = DefaultShedule)]
public int Schedule
{
get { return Convert.ToInt32(this["schedule"]); }
set { this["schedule"] = value; }
}
[ConfigurationProperty("groups")]
public string Groups
{
get { return (string)this["groups"]; }
}
[ConfigurationProperty("address", DefaultValue = DefaultAdress)]
public string BaseAddress
{
get { return (string)this["address"]; }
set { this["address"] = value; }
}
[ConfigurationProperty("apiVersion", DefaultValue = DefaultApiVersion)]
public string ApiVersion
{
get { return (string)this["apiVersion"]; }
set { this["apiVersion"] = value; }
}
}
}
var cfg = (AvangateCfgSectionHandler)ConfigurationManager.GetSection("avangate");
_secret = Encoding.UTF8.GetBytes(cfg.Secret);
_vendorCode = cfg.Vendor;
_percent = cfg.Percent;
_schedule = cfg.Schedule;
_baseAddress = new Uri(cfg.BaseAddress);
_apiVersion = "/rest/" + cfg.ApiVersion.TrimStart('/');
_groups = (cfg.Groups ?? "").Split(',', '|', ' ');
}
catch (Exception e)
{
_secret = Encoding.UTF8.GetBytes("");
_vendorCode = "";
_percent = AvangateCfgSectionHandler.DefaultPercent;
_schedule = AvangateCfgSectionHandler.DefaultShedule;
_baseAddress = new Uri(AvangateCfgSectionHandler.DefaultAdress);
_apiVersion = AvangateCfgSectionHandler.DefaultApiVersion;
_groups = new List<string>();
_logger.Fatal(e);
}
}
public string CreateCoupon(TenantManager tenantManager)
{
return CreatePromotionAsync(tenantManager).Result;
}
private async Task<string> CreatePromotionAsync(TenantManager tenantManager)
{
try
{
using var httpClient = PrepaireClient();
using var content = new StringContent(await Promotion.GeneratePromotion(_logger, this, tenantManager, _percent, _schedule), Encoding.Default, "application/json");
using var response = await httpClient.PostAsync($"{_apiVersion}/promotions/", content);
if (!response.IsSuccessStatusCode)
{
throw new Exception(response.ReasonPhrase);
}
var result = await response.Content.ReadAsStringAsync();
await Task.Delay(1000 - DateTime.UtcNow.Millisecond); // otherwise authorize exception
var createdPromotion = JsonConvert.DeserializeObject<Promotion>(result);
return createdPromotion.Coupon.Code;
}
catch (Exception ex)
{
_logger.Error(ex.Message, ex);
throw;
}
}
internal Task<IEnumerable<AvangateProduct>> GetProducts()
{
return _products != null ? Task.FromResult(_products) : InternalGetProducts();
}
private async Task<IEnumerable<AvangateProduct>> InternalGetProducts()
{
await _semaphoreSlim.WaitAsync();
if (_products != null)
{
_semaphoreSlim.Release();
return _products;
}
try
{
using var httpClient = PrepaireClient();
using var response = await httpClient.GetAsync($"{_apiVersion}/products/?Limit=1000&Enabled=true");
if (!response.IsSuccessStatusCode)
{
throw new Exception(response.ReasonPhrase);
}
var result = await response.Content.ReadAsStringAsync();
_logger.Debug(result);
var products = JsonConvert.DeserializeObject<List<AvangateProduct>>(result);
products = products.Where(r => r.ProductGroup != null && _groups.Contains(r.ProductGroup.Code)).ToList();
return _products = products;
}
catch (Exception ex)
{
_logger.Error(ex.Message, ex);
throw;
}
finally
{
_semaphoreSlim.Release();
}
}
private HttpClient PrepaireClient()
{
const string applicationJson = "application/json";
var httpClient = _clientFactory.CreateClient();
httpClient.BaseAddress = _baseAddress;
httpClient.Timeout = TimeSpan.FromMinutes(3);
httpClient.DefaultRequestHeaders.TryAddWithoutValidation("accept", applicationJson);
httpClient.DefaultRequestHeaders.TryAddWithoutValidation("Content-Type", applicationJson);
httpClient.DefaultRequestHeaders.TryAddWithoutValidation("X-Avangate-Authentication", CreateAuthHeader());
return httpClient;
}
private string CreateAuthHeader()
{
using var hmac = new HMACMD5(_secret);
var date = DateTime.UtcNow.ToString("yyyy-MM-dd HH:mm:ss");
var hash = _vendorCode.Length + _vendorCode + date.Length + date;
var data = hmac.ComputeHash(Encoding.UTF8.GetBytes(hash));
var sBuilder = new StringBuilder();
foreach (var t in data)
{
sBuilder.Append(t.ToString("x2"));
}
var stringBuilder = new StringBuilder();
stringBuilder.Append($"code='{_vendorCode}' ");
stringBuilder.Append($"date='{date}' ");
stringBuilder.Append($"hash='{sBuilder}'");
return stringBuilder.ToString();
}
}
class Promotion
{
public string Code { get; set; }
public string Name { get; set; }
public string Type { get; set; }
public string StartDate { get; set; }
public string EndDate { get; set; }
public bool Enabled { get; set; }
public int MaximumOrdersNumber { get; set; }
public bool InstantDiscount { get; set; }
public string ChannelType { get; set; }
public string ApplyRecurring { get; set; }
public Coupon Coupon { get; set; }
public Discount Discount { get; set; }
public IEnumerable<CouponProduct> Products { get; set; }
public int PublishToAffiliatesNetwork { get; set; }
public int AutoApply { get; set; }
public static async Task<string> GeneratePromotion(ILog log, CouponManager couponManager, TenantManager tenantManager, int percent, int schedule)
{
try
{
var tenant = tenantManager.GetCurrentTenant();
var startDate = DateTime.UtcNow.Date;
var endDate = startDate.AddDays(schedule);
var code = tenant.Alias;
var promotion = new Promotion
{
Type = "REGULAR",
Enabled = true,
MaximumOrdersNumber = 1,
InstantDiscount = false,
ChannelType = "ECOMMERCE",
ApplyRecurring = "NONE",
PublishToAffiliatesNetwork = 0,
AutoApply = 0,
StartDate = startDate.ToString("yyyy-MM-dd"),
EndDate = endDate.ToString("yyyy-MM-dd"),
Name = string.Format("{0} {1}% off", code, percent),
Coupon = new Coupon { Type = "SINGLE", Code = code },
Discount = new Discount { Type = "PERCENT", Value = percent },
Products = (await couponManager.GetProducts()).Select(r => new CouponProduct { Code = r.ProductCode })
};
return JsonConvert.SerializeObject(promotion);
}
catch (Exception ex)
{
log.Error(ex.Message, ex);
throw;
}
}
}
class Coupon
{
public string Type { get; set; }
public string Code { get; set; }
}
class Discount
{
public string Type { get; set; }
public int Value { get; set; }
}
class AvangateProduct
{
public string ProductCode { get; set; }
public string ProductName { get; set; }
public AvangateProductGroup ProductGroup { get; set; }
}
class AvangateProductGroup
{
public string Name { get; set; }
public string Code { get; set; }
}
class CouponProduct
{
public string Code { get; set; }
}
class AvangateCfgSectionHandler : ConfigurationSection
{
public const string DefaultAdress = "https://api.avangate.com/";
public const string DefaultApiVersion = "4.0";
public const int DefaultPercent = 5;
public const int DefaultShedule = 10;
[ConfigurationProperty("secret")]
public string Secret => (string)this["secret"];
[ConfigurationProperty("vendor")]
public string Vendor
{
get => (string)this["vendor"];
set => this["vendor"] = value;
}
[ConfigurationProperty("percent", DefaultValue = DefaultPercent)]
public int Percent
{
get => Convert.ToInt32(this["percent"]);
set => this["percent"] = value;
}
[ConfigurationProperty("schedule", DefaultValue = DefaultShedule)]
public int Schedule
{
get => Convert.ToInt32(this["schedule"]);
set => this["schedule"] = value;
}
[ConfigurationProperty("groups")]
public string Groups => (string)this["groups"];
[ConfigurationProperty("address", DefaultValue = DefaultAdress)]
public string BaseAddress
{
get => (string)this["address"];
set => this["address"] = value;
}
[ConfigurationProperty("apiVersion", DefaultValue = DefaultApiVersion)]
public string ApiVersion
{
get => (string)this["apiVersion"];
set => this["apiVersion"] = value;
}
}

View File

@ -23,27 +23,18 @@
*
*/
namespace ASC.Core.Billing
namespace ASC.Core.Billing;
[Scope(typeof(ConfigureTariffService))]
public interface ITariffService
{
[Scope(typeof(ConfigureTariffService))]
public interface ITariffService
{
Tariff GetTariff(int tenantId, bool withRequestToPaymentSystem = true);
void SetTariff(int tenantId, Tariff tariff);
void DeleteDefaultBillingInfo();
void ClearCache(int tenantId);
IEnumerable<PaymentInfo> GetPayments(int tenantId);
Uri GetShoppingUri(int? tenant, int quotaId, string affiliateId, string currency = null, string language = null, string customerId = null, string quantity = null);
IDictionary<string, Dictionary<string, decimal>> GetProductPriceInfo(params string[] productIds);
string GetButton(int tariffId, string partnerId);
void SaveButton(int tariffId, string partnerId, string buttonUrl);
}
IDictionary<string, Dictionary<string, decimal>> GetProductPriceInfo(params string[] productIds);
IEnumerable<PaymentInfo> GetPayments(int tenantId);
string GetButton(int tariffId, string partnerId);
Tariff GetTariff(int tenantId, bool withRequestToPaymentSystem = true);
Uri GetShoppingUri(int? tenant, int quotaId, string affiliateId, string currency = null, string language = null, string customerId = null, string quantity = null);
void ClearCache(int tenantId);
void DeleteDefaultBillingInfo();
void SaveButton(int tariffId, string partnerId, string buttonUrl);
void SetTariff(int tenantId, Tariff tariff);
}

View File

@ -25,126 +25,124 @@
using JsonSerializer = System.Text.Json.JsonSerializer;
namespace ASC.Core.Billing
{
[Serializable]
[DebuggerDisplay("{DueDate}")]
public class License
{
public string OriginalLicense { get; set; }
namespace ASC.Core.Billing;
[JsonPropertyName("affiliate_id")]
public string AffiliateId { get; set; }
//[Obsolete]
public bool WhiteLabel { get; set; }
public bool Customization { get; set; }
[Serializable]
[DebuggerDisplay("{DueDate}")]
public class License
{
public string OriginalLicense { get; set; }
public bool Branding { get; set; }
[JsonPropertyName("affiliate_id")]
public string AffiliateId { get; set; }
public bool SSBranding { get; set; }
//[Obsolete]
public bool WhiteLabel { get; set; }
public bool Customization { get; set; }
public bool Branding { get; set; }
public bool SSBranding { get; set; }
[JsonPropertyName("end_date")]
public DateTime DueDate { get; set; }
[JsonPropertyName("end_date")]
public DateTime DueDate { get; set; }
[JsonPropertyName("portal_count")]
public int PortalCount { get; set; }
[JsonPropertyName("portal_count")]
public int PortalCount { get; set; }
public bool Trial { get; set; }
public bool Trial { get; set; }
[JsonPropertyName("user_quota")]
public int ActiveUsers { get; set; }
[JsonPropertyName("user_quota")]
public int ActiveUsers { get; set; }
[JsonPropertyName("customer_id")]
public string CustomerId { get; set; }
public string Signature { get; set; }
[JsonPropertyName("customer_id")]
public string CustomerId { get; set; }
public string Signature { get; set; }
public bool? DiscEncryption { get; set; }
public bool? DiscEncryption { get; set; }
[JsonPropertyName("users_count")]
public int DSUsersCount { get; set; }
[JsonPropertyName("users_count")]
public int DSUsersCount { get; set; }
[JsonPropertyName("users_expire")]
public int DSUsersExpire { get; set; }
[JsonPropertyName("users_expire")]
public int DSUsersExpire { get; set; }
[JsonPropertyName("connections")]
public int DSConnections { get; set; }
[JsonPropertyName("connections")]
public int DSConnections { get; set; }
public static License Parse(string licenseString)
{
if (string.IsNullOrEmpty(licenseString)) throw new BillingNotFoundException("License file is empty");
try
{
var options = new JsonSerializerOptions
{
AllowTrailingCommas = true,
PropertyNameCaseInsensitive = true
};
options.Converters.Add(new LicenseConverter());
var license = JsonSerializer.Deserialize<License>(licenseString, options);
if (license == null) throw new BillingNotFoundException("Can't parse license");
license.OriginalLicense = licenseString;
return license;
}
catch (Exception)
{
throw new BillingNotFoundException("Can't parse license");
}
}
}
public class LicenseConverter : System.Text.Json.Serialization.JsonConverter<object>
public static License Parse(string licenseString)
{
public override bool CanConvert(Type typeToConvert)
if (string.IsNullOrEmpty(licenseString))
{
return
typeof(int) == typeToConvert ||
typeof(bool) == typeToConvert;
throw new BillingNotFoundException("License file is empty");
}
public override object Read(ref Utf8JsonReader reader, Type typeToConvert, JsonSerializerOptions options)
try
{
if (typeToConvert == typeof(int) && reader.TokenType == JsonTokenType.String)
var options = new JsonSerializerOptions
{
AllowTrailingCommas = true,
PropertyNameCaseInsensitive = true
};
options.Converters.Add(new LicenseConverter());
var license = JsonSerializer.Deserialize<License>(licenseString, options);
if (license == null)
{
throw new BillingNotFoundException("Can't parse license");
}
license.OriginalLicense = licenseString;
return license;
}
catch (Exception)
{
throw new BillingNotFoundException("Can't parse license");
}
}
}
public class LicenseConverter : System.Text.Json.Serialization.JsonConverter<object>
{
public override bool CanConvert(Type typeToConvert)
{
return typeof(int) == typeToConvert ||
typeof(bool) == typeToConvert;
}
public override object Read(ref Utf8JsonReader reader, Type typeToConvert, JsonSerializerOptions options)
{
if (typeToConvert == typeof(int) && reader.TokenType == JsonTokenType.String)
{
var i = reader.GetString();
if (!int.TryParse(i, out var result))
{
return 0;
}
return result;
}
if (typeToConvert == typeof(bool))
{
if (reader.TokenType == JsonTokenType.String)
{
var i = reader.GetString();
if (!int.TryParse(i, out var result))
if (!bool.TryParse(i, out var result))
{
return 0;
return false;
}
return result;
}
if (typeToConvert == typeof(bool))
{
if (reader.TokenType == JsonTokenType.String)
{
var i = reader.GetString();
if (!bool.TryParse(i, out var result))
{
return false;
}
return result;
}
return reader.GetBoolean();
}
return null;
return reader.GetBoolean();
}
public override void Write(Utf8JsonWriter writer, object value, JsonSerializerOptions options)
{
return;
}
}
}
return null;
}
public override void Write(Utf8JsonWriter writer, object value, JsonSerializerOptions options)
{
return;
}
}

View File

@ -23,37 +23,28 @@
*
*/
namespace ASC.Core.Billing
namespace ASC.Core.Billing;
[Serializable]
public class LicenseException : BillingException
{
[Serializable]
public class LicenseException : BillingException
{
public LicenseException(string message, object debugInfo = null) : base(message, debugInfo)
{
}
}
public LicenseException(string message, object debugInfo = null) : base(message, debugInfo) { }
}
[Serializable]
public class LicenseExpiredException : LicenseException
{
public LicenseExpiredException(string message, object debugInfo = null) : base(message, debugInfo)
{
}
}
[Serializable]
public class LicenseExpiredException : LicenseException
{
public LicenseExpiredException(string message, object debugInfo = null) : base(message, debugInfo) { }
}
[Serializable]
public class LicenseQuotaException : LicenseException
{
public LicenseQuotaException(string message, object debugInfo = null) : base(message, debugInfo)
{
}
}
[Serializable]
public class LicenseQuotaException : LicenseException
{
public LicenseQuotaException(string message, object debugInfo = null) : base(message, debugInfo) { }
}
[Serializable]
public class LicensePortalException : LicenseException
{
public LicensePortalException(string message, object debugInfo = null) : base(message, debugInfo)
{
}
}
}
[Serializable]
public class LicensePortalException : LicenseException
{
public LicensePortalException(string message, object debugInfo = null) : base(message, debugInfo) { }
}

View File

@ -23,310 +23,325 @@
*
*/
namespace ASC.Core.Billing
namespace ASC.Core.Billing;
[Scope]
public class LicenseReader
{
[Scope]
public class LicenseReader
{
private readonly ILog Log;
public readonly string LicensePath;
private readonly string LicensePathTemp;
public const string CustomerIdKey = "CustomerId";
public const int MaxUserCount = 10000;
public LicenseReader(
UserManager userManager,
TenantManager tenantManager,
PaymentManager paymentManager,
CoreSettings coreSettings,
IConfiguration configuration,
IOptionsMonitor<ILog> options)
{
UserManager = userManager;
TenantManager = tenantManager;
PaymentManager = paymentManager;
CoreSettings = coreSettings;
Configuration = configuration;
LicensePath = Configuration["license:file:path"] ?? "";
LicensePathTemp = LicensePath + ".tmp";
Log = options.CurrentValue;
}
public string CustomerId
{
get { return CoreSettings.GetSetting(CustomerIdKey); }
private set { CoreSettings.SaveSetting(CustomerIdKey, value); }
}
private Stream GetLicenseStream(bool temp = false)
{
var path = temp ? LicensePathTemp : LicensePath;
if (!File.Exists(path)) throw new BillingNotFoundException("License not found");
return File.OpenRead(path);
}
public void RejectLicense()
{
if (File.Exists(LicensePathTemp))
File.Delete(LicensePathTemp);
if (File.Exists(LicensePath))
File.Delete(LicensePath);
PaymentManager.DeleteDefaultTariff();
}
public void RefreshLicense()
{
try
{
var temp = true;
if (!File.Exists(LicensePathTemp))
{
Log.Debug("Temp license not found");
if (!File.Exists(LicensePath))
{
throw new BillingNotFoundException("License not found");
}
temp = false;
}
using (var licenseStream = GetLicenseStream(temp))
using (var reader = new StreamReader(licenseStream))
{
var licenseJsonString = reader.ReadToEnd();
var license = License.Parse(licenseJsonString);
LicenseToDB(license);
if (temp)
{
SaveLicense(licenseStream, LicensePath);
}
}
if (temp)
File.Delete(LicensePathTemp);
}
catch (Exception ex)
{
LogError(ex);
throw;
}
}
public DateTime SaveLicenseTemp(Stream licenseStream)
{
try
{
using var reader = new StreamReader(licenseStream);
var licenseJsonString = reader.ReadToEnd();
var license = License.Parse(licenseJsonString);
var dueDate = Validate(license);
SaveLicense(licenseStream, LicensePathTemp);
return dueDate;
}
catch (Exception ex)
{
LogError(ex);
throw;
}
}
private static void SaveLicense(Stream licenseStream, string path)
{
if (licenseStream == null) throw new ArgumentNullException(nameof(licenseStream));
if (licenseStream.CanSeek)
{
licenseStream.Seek(0, SeekOrigin.Begin);
}
using var fs = File.Open(path, FileMode.Create);
licenseStream.CopyTo(fs);
}
private DateTime Validate(License license)
{
if (string.IsNullOrEmpty(license.CustomerId)
|| string.IsNullOrEmpty(license.Signature))
{
throw new BillingNotConfiguredException("License not correct", license.OriginalLicense);
}
if (license.DueDate.Date < VersionReleaseDate)
{
throw new LicenseExpiredException("License expired", license.OriginalLicense);
}
if (license.ActiveUsers.Equals(default) || license.ActiveUsers < 1)
license.ActiveUsers = MaxUserCount;
if (license.ActiveUsers < UserManager.GetUsers(EmployeeStatus.Default, EmployeeType.User).Length)
{
throw new LicenseQuotaException("License quota", license.OriginalLicense);
}
if (license.PortalCount <= 0)
{
license.PortalCount = TenantManager.GetTenantQuota(Tenant.DEFAULT_TENANT).CountPortals;
}
var activePortals = TenantManager.GetTenants().Count;
if (activePortals > 1 && license.PortalCount < activePortals)
{
throw new LicensePortalException("License portal count", license.OriginalLicense);
}
return license.DueDate.Date;
}
private void LicenseToDB(License license)
{
Validate(license);
private readonly ILog _logger;
public readonly string LicensePath;
private readonly string _licensePathTemp;
CustomerId = license.CustomerId;
public const string CustomerIdKey = "CustomerId";
public const int MaxUserCount = 10000;
var defaultQuota = TenantManager.GetTenantQuota(Tenant.DEFAULT_TENANT);
public LicenseReader(
UserManager userManager,
TenantManager tenantManager,
PaymentManager paymentManager,
CoreSettings coreSettings,
IConfiguration configuration,
IOptionsMonitor<ILog> options)
{
_userManager = userManager;
_tenantManager = tenantManager;
_paymentManager = paymentManager;
_coreSettings = coreSettings;
_configuration = configuration;
LicensePath = _configuration["license:file:path"] ?? "";
_licensePathTemp = LicensePath + ".tmp";
_logger = options.CurrentValue;
}
var quota = new TenantQuota(-1000)
public string CustomerId
{
get => _coreSettings.GetSetting(CustomerIdKey);
private set => _coreSettings.SaveSetting(CustomerIdKey, value);
}
private Stream GetLicenseStream(bool temp = false)
{
var path = temp ? _licensePathTemp : LicensePath;
if (!File.Exists(path))
{
throw new BillingNotFoundException("License not found");
}
return File.OpenRead(path);
}
public void RejectLicense()
{
if (File.Exists(_licensePathTemp))
{
File.Delete(_licensePathTemp);
}
if (File.Exists(LicensePath))
{
File.Delete(LicensePath);
}
_paymentManager.DeleteDefaultTariff();
}
public void RefreshLicense()
{
try
{
var temp = true;
if (!File.Exists(_licensePathTemp))
{
ActiveUsers = license.ActiveUsers,
MaxFileSize = defaultQuota.MaxFileSize,
MaxTotalSize = defaultQuota.MaxTotalSize,
Name = "license",
DocsEdition = true,
HasDomain = true,
Audit = true,
ControlPanel = true,
HealthCheck = true,
Ldap = true,
Sso = true,
Customization = license.Customization,
WhiteLabel = license.WhiteLabel || license.Customization,
Branding = license.Branding,
SSBranding = license.SSBranding,
Update = true,
Support = true,
Trial = license.Trial,
CountPortals = license.PortalCount,
DiscEncryption = true,
PrivacyRoom = true,
Restore = true,
ContentSearch = true
};
_logger.Debug("Temp license not found");
if (defaultQuota.Name != "overdue" && !defaultQuota.Trial)
{
quota.WhiteLabel |= defaultQuota.WhiteLabel;
quota.Branding |= defaultQuota.Branding;
quota.SSBranding |= defaultQuota.SSBranding;
if (!File.Exists(LicensePath))
{
throw new BillingNotFoundException("License not found");
}
quota.CountPortals = Math.Max(defaultQuota.CountPortals, quota.CountPortals);
temp = false;
}
TenantManager.SaveTenantQuota(quota);
var tariff = new Tariff
using (var licenseStream = GetLicenseStream(temp))
using (var reader = new StreamReader(licenseStream))
{
QuotaId = quota.Id,
DueDate = license.DueDate,
};
var licenseJsonString = reader.ReadToEnd();
var license = License.Parse(licenseJsonString);
PaymentManager.SetTariff(-1, tariff);
LicenseToDB(license);
if (!string.IsNullOrEmpty(license.AffiliateId))
if (temp)
{
SaveLicense(licenseStream, LicensePath);
}
}
if (temp)
{
var tenant = TenantManager.GetCurrentTenant();
tenant.AffiliateId = license.AffiliateId;
TenantManager.SaveTenant(tenant);
}
}
private void LogError(Exception error)
{
if (error is BillingNotFoundException)
{
Log.DebugFormat("License not found: {0}", error.Message);
}
else
{
if (Log.IsDebugEnabled)
{
Log.Error(error);
}
else
{
Log.Error(error.Message);
}
}
}
private static readonly DateTime _date = DateTime.MinValue;
public DateTime VersionReleaseDate
{
get
File.Delete(_licensePathTemp);
}
}
catch (Exception ex)
{
LogError(ex);
throw;
}
}
public DateTime SaveLicenseTemp(Stream licenseStream)
{
try
{
using var reader = new StreamReader(licenseStream);
var licenseJsonString = reader.ReadToEnd();
var license = License.Parse(licenseJsonString);
var dueDate = Validate(license);
SaveLicense(licenseStream, _licensePathTemp);
return dueDate;
}
catch (Exception ex)
{
LogError(ex);
throw;
}
}
private static void SaveLicense(Stream licenseStream, string path)
{
if (licenseStream == null)
{
throw new ArgumentNullException(nameof(licenseStream));
}
if (licenseStream.CanSeek)
{
licenseStream.Seek(0, SeekOrigin.Begin);
}
using var fs = File.Open(path, FileMode.Create);
licenseStream.CopyTo(fs);
}
private DateTime Validate(License license)
{
if (string.IsNullOrEmpty(license.CustomerId)
|| string.IsNullOrEmpty(license.Signature))
{
throw new BillingNotConfiguredException("License not correct", license.OriginalLicense);
}
if (license.DueDate.Date < VersionReleaseDate)
{
throw new LicenseExpiredException("License expired", license.OriginalLicense);
}
if (license.ActiveUsers.Equals(default) || license.ActiveUsers < 1)
license.ActiveUsers = MaxUserCount;
if (license.ActiveUsers < _userManager.GetUsers(EmployeeStatus.Default, EmployeeType.User).Length)
{
throw new LicenseQuotaException("License quota", license.OriginalLicense);
}
if (license.PortalCount <= 0)
{
license.PortalCount = _tenantManager.GetTenantQuota(Tenant.DefaultTenant).CountPortals;
}
var activePortals = _tenantManager.GetTenants().Count;
if (activePortals > 1 && license.PortalCount < activePortals)
{
throw new LicensePortalException("License portal count", license.OriginalLicense);
}
return license.DueDate.Date;
}
private void LicenseToDB(License license)
{
Validate(license);
CustomerId = license.CustomerId;
var defaultQuota = _tenantManager.GetTenantQuota(Tenant.DefaultTenant);
var quota = new TenantQuota(-1000)
{
ActiveUsers = license.ActiveUsers,
MaxFileSize = defaultQuota.MaxFileSize,
MaxTotalSize = defaultQuota.MaxTotalSize,
Name = "license",
DocsEdition = true,
HasDomain = true,
Audit = true,
ControlPanel = true,
HealthCheck = true,
Ldap = true,
Sso = true,
Customization = license.Customization,
WhiteLabel = license.WhiteLabel || license.Customization,
Branding = license.Branding,
SSBranding = license.SSBranding,
Update = true,
Support = true,
Trial = license.Trial,
CountPortals = license.PortalCount,
DiscEncryption = true,
PrivacyRoom = true,
Restore = true,
ContentSearch = true
};
if (defaultQuota.Name != "overdue" && !defaultQuota.Trial)
{
quota.WhiteLabel |= defaultQuota.WhiteLabel;
quota.Branding |= defaultQuota.Branding;
quota.SSBranding |= defaultQuota.SSBranding;
quota.CountPortals = Math.Max(defaultQuota.CountPortals, quota.CountPortals);
}
_tenantManager.SaveTenantQuota(quota);
var tariff = new Tariff
{
QuotaId = quota.Tenant,
DueDate = license.DueDate,
};
_paymentManager.SetTariff(-1, tariff);
if (!string.IsNullOrEmpty(license.AffiliateId))
{
var tenant = _tenantManager.GetCurrentTenant();
tenant.AffiliateId = license.AffiliateId;
_tenantManager.SaveTenant(tenant);
}
}
private void LogError(Exception error)
{
if (error is BillingNotFoundException)
{
_logger.DebugFormat("License not found: {0}", error.Message);
}
else
{
if (_logger.IsDebugEnabled)
{
// release sign is not longer requered
return _date;
_logger.Error(error);
}
else
{
_logger.Error(error.Message);
}
}
}
//if (_date != DateTime.MinValue) return _date;
private static readonly DateTime _date = DateTime.MinValue;
//_date = DateTime.MaxValue;
//try
//{
// var versionDate = Configuration["version:release:date"];
// var sign = Configuration["version:release:sign"];
public DateTime VersionReleaseDate
{
get
{
// release sign is not longer requered
return _date;
// if (!sign.StartsWith("ASC "))
// {
// throw new Exception("sign without ASC");
// }
//if (_date != DateTime.MinValue) return _date;
// var splitted = sign.Substring(4).Split(':');
// var pkey = splitted[0];
// if (pkey != versionDate)
// {
// throw new Exception("sign with different date");
// }
//_date = DateTime.MaxValue;
//try
//{
// var versionDate = Configuration["version:release:date"];
// var sign = Configuration["version:release:sign"];
// var date = splitted[1];
// var orighash = splitted[2];
// if (!sign.StartsWith("ASC "))
// {
// throw new Exception("sign without ASC");
// }
//var skey = MachinePseudoKeys.GetMachineConstant();
// var splitted = sign.Substring(4).Split(':');
// var pkey = splitted[0];
// if (pkey != versionDate)
// {
// throw new Exception("sign with different date");
// }
//using (var hasher = new HMACSHA1(skey))
// {
// var data = string.Join("\n", date, pkey);
// var hash = hasher.ComputeHash(Encoding.UTF8.GetBytes(data));
// if (WebEncoders.Base64UrlEncode(hash) != orighash && Convert.ToBase64String(hash) != orighash)
// {
// throw new Exception("incorrect hash");
// }
// }
// var date = splitted[1];
// var orighash = splitted[2];
// var year = int.Parse(versionDate.Substring(0, 4));
// var month = int.Parse(versionDate.Substring(4, 2));
// var day = int.Parse(versionDate.Substring(6, 2));
// _date = new DateTime(year, month, day);
//}
//catch (Exception ex)
//{
// Log.Error("VersionReleaseDate", ex);
//}
//return _date;
}
}
private UserManager UserManager { get; }
private TenantManager TenantManager { get; }
private PaymentManager PaymentManager { get; }
private CoreSettings CoreSettings { get; }
private IConfiguration Configuration { get; }
}
}
//var skey = MachinePseudoKeys.GetMachineConstant();
//using (var hasher = new HMACSHA1(skey))
// {
// var data = string.Join("\n", date, pkey);
// var hash = hasher.ComputeHash(Encoding.UTF8.GetBytes(data));
// if (WebEncoders.Base64UrlEncode(hash) != orighash && Convert.ToBase64String(hash) != orighash)
// {
// throw new Exception("incorrect hash");
// }
// }
// var year = int.Parse(versionDate.Substring(0, 4));
// var month = int.Parse(versionDate.Substring(4, 2));
// var day = int.Parse(versionDate.Substring(6, 2));
// _date = new DateTime(year, month, day);
//}
//catch (Exception ex)
//{
// Log.Error("VersionReleaseDate", ex);
//}
//return _date;
}
}
private readonly UserManager _userManager;
private readonly TenantManager _tenantManager;
private readonly PaymentManager _paymentManager;
private readonly CoreSettings _coreSettings;
private readonly IConfiguration _configuration;
}

View File

@ -23,39 +23,14 @@
*
*/
namespace ASC.Core.Billing
namespace ASC.Core.Billing;
[Serializable]
public class PaymentLast
{
[Serializable]
public class PaymentLast
{
public string ProductId
{
get;
set;
}
public DateTime EndDate
{
get;
set;
}
public bool Autorenewal
{
get;
set;
}
public int PaymentStatus
{
get;
set;
}
public int Quantity
{
get;
set;
}
}
public string ProductId { get; set; }
public DateTime EndDate { get; set; }
public bool Autorenewal { get; set; }
public int PaymentStatus { get; set; }
public int Quantity { get; set; }
}

View File

@ -23,37 +23,23 @@
*
*/
namespace ASC.Core.Billing
namespace ASC.Core.Billing;
[Serializable]
public class PaymentInfo
{
[Serializable]
public class PaymentInfo
{
public int ID { get; set; }
public int Status { get; set; }
public int PaymentSystemId { get; set; }
public string CartId { get; set; }
public string FName { get; set; }
public string LName { get; set; }
public string Email { get; set; }
public DateTime PaymentDate { get; set; }
public Decimal Price { get; set; }
public string PaymentCurrency { get; set; }
public string PaymentMethod { get; set; }
public int QuotaId { get; set; }
public string ProductRef { get; set; }
public string CustomerId { get; set; }
}
public int ID { get; set; }
public int Status { get; set; }
public int PaymentSystemId { get; set; }
public string CartId { get; set; }
public string FName { get; set; }
public string LName { get; set; }
public string Email { get; set; }
public DateTime PaymentDate { get; set; }
public Decimal Price { get; set; }
public string PaymentCurrency { get; set; }
public string PaymentMethod { get; set; }
public int QuotaId { get; set; }
public string ProductRef { get; set; }
public string CustomerId { get; set; }
}

View File

@ -23,58 +23,50 @@
*
*/
namespace ASC.Core.Billing
{
[DebuggerDisplay("{QuotaId} ({State} before {DueDate})")]
[Serializable]
public class Tariff
{
public int QuotaId { get; set; }
public TariffState State { get; set; }
public DateTime DueDate { get; set; }
public DateTime DelayDueDate { get; set; }
public DateTime LicenseDate { get; set; }
public bool Autorenewal { get; set; }
public bool Prolongable { get; set; }
namespace ASC.Core.Billing;
public int Quantity { get; set; }
public static Tariff CreateDefault()
{
return new Tariff
{
QuotaId = Tenant.DEFAULT_TENANT,
State = TariffState.Paid,
DueDate = DateTime.MaxValue,
DelayDueDate = DateTime.MaxValue,
LicenseDate = DateTime.MaxValue,
Quantity = 1
};
}
public override int GetHashCode()
{
return QuotaId.GetHashCode();
}
public override bool Equals(object obj)
{
return obj is Tariff t && t.QuotaId == QuotaId;
}
[DebuggerDisplay("{QuotaId} ({State} before {DueDate})")]
[Serializable]
public class Tariff
{
public int QuotaId { get; set; }
public TariffState State { get; set; }
public DateTime DueDate { get; set; }
public DateTime DelayDueDate { get; set; }
public DateTime LicenseDate { get; set; }
public bool Autorenewal { get; set; }
public bool Prolongable { get; set; }
public int Quantity { get; set; }
public bool EqualsByParams(Tariff t)
public static Tariff CreateDefault()
{
return new Tariff
{
return t != null
&& t.QuotaId == QuotaId
&& t.DueDate == DueDate
&& t.Quantity == Quantity;
}
}
}
QuotaId = Tenant.DefaultTenant,
State = TariffState.Paid,
DueDate = DateTime.MaxValue,
DelayDueDate = DateTime.MaxValue,
LicenseDate = DateTime.MaxValue,
Quantity = 1
};
}
public override int GetHashCode()
{
return QuotaId.GetHashCode();
}
public override bool Equals(object obj)
{
return obj is Tariff t && t.QuotaId == QuotaId;
}
public bool EqualsByParams(Tariff t)
{
return t != null
&& t.QuotaId == QuotaId
&& t.DueDate == DueDate
&& t.Quantity == Quantity;
}
}

File diff suppressed because it is too large Load Diff

View File

@ -24,13 +24,12 @@
*/
namespace ASC.Core.Billing
namespace ASC.Core.Billing;
public enum TariffState
{
public enum TariffState
{
Trial,
Paid,
Delay,
NotPaid,
}
}
Trial,
Paid,
Delay,
NotPaid,
}

View File

@ -0,0 +1,18 @@
namespace ASC.Core.Common;
public static class ByteConverter
{
public static long GetInMBytes(long bytes)
{
const long MB = 1024 * 1024;
return bytes < MB * MB ? bytes / MB : bytes;
}
public static long GetInBytes(long bytes)
{
const long MB = 1024 * 1024;
return bytes < MB ? bytes * MB : bytes;
}
}

View File

@ -23,60 +23,66 @@
*
*/
namespace ASC.Core.Caching
namespace ASC.Core.Caching;
class AzRecordStore : IEnumerable<AzRecord>
{
class AzRecordStore : IEnumerable<AzRecord>
private readonly Dictionary<string, List<AzRecord>> byObjectId = new Dictionary<string, List<AzRecord>>();
public AzRecordStore(IEnumerable<AzRecord> aces)
{
private readonly Dictionary<string, List<AzRecord>> byObjectId = new Dictionary<string, List<AzRecord>>();
public AzRecordStore(IEnumerable<AzRecord> aces)
foreach (var a in aces)
{
foreach (var a in aces)
{
Add(a);
}
}
public IEnumerable<AzRecord> Get(string objectId)
{
byObjectId.TryGetValue(objectId ?? string.Empty, out var aces);
return aces ?? new List<AzRecord>();
}
public void Add(AzRecord r)
{
if (r == null) return;
var id = r.ObjectId ?? string.Empty;
if (!byObjectId.ContainsKey(id))
{
byObjectId[id] = new List<AzRecord>();
}
byObjectId[id].RemoveAll(a => a.SubjectId == r.SubjectId && a.ActionId == r.ActionId); // remove escape, see DbAzService
byObjectId[id].Add(r);
}
public void Remove(AzRecord r)
{
if (r == null) return;
var id = r.ObjectId ?? string.Empty;
if (byObjectId.TryGetValue(id, out var list))
{
list.RemoveAll(a => a.SubjectId == r.SubjectId && a.ActionId == r.ActionId && a.Reaction == r.Reaction);
}
}
public IEnumerator<AzRecord> GetEnumerator()
{
return byObjectId.Values.SelectMany(v => v).GetEnumerator();
}
IEnumerator IEnumerable.GetEnumerator()
{
return GetEnumerator();
Add(a);
}
}
}
public IEnumerable<AzRecord> Get(string objectId)
{
byObjectId.TryGetValue(objectId ?? string.Empty, out var aces);
return aces ?? new List<AzRecord>();
}
public void Add(AzRecord r)
{
if (r == null)
{
return;
}
var id = r.Object ?? string.Empty;
if (!byObjectId.ContainsKey(id))
{
byObjectId[id] = new List<AzRecord>();
}
byObjectId[id].RemoveAll(a => a.Subject == r.Subject && a.Action == r.Action); // remove escape, see DbAzService
byObjectId[id].Add(r);
}
public void Remove(AzRecord r)
{
if (r == null)
{
return;
}
var id = r.Object ?? string.Empty;
if (byObjectId.TryGetValue(id, out var list))
{
list.RemoveAll(a => a.Subject == r.Subject && a.Action == r.Action && a.AceType == r.AceType);
}
}
public IEnumerator<AzRecord> GetEnumerator()
{
return byObjectId.Values.SelectMany(v => v).GetEnumerator();
}
IEnumerator IEnumerable.GetEnumerator()
{
return GetEnumerator();
}
}

View File

@ -23,93 +23,91 @@
*
*/
namespace ASC.Core.Caching
{
[Singletone]
class AzServiceCache
{
internal ICache Cache { get; }
internal ICacheNotify<AzRecordCache> CacheNotify { get; }
public AzServiceCache(ICacheNotify<AzRecordCache> cacheNotify, ICache cache)
{
CacheNotify = cacheNotify;
Cache = cache;
cacheNotify.Subscribe((r) => UpdateCache(r, true), ASC.Common.Caching.CacheNotifyAction.Remove);
cacheNotify.Subscribe((r) => UpdateCache(r, false), ASC.Common.Caching.CacheNotifyAction.InsertOrUpdate);
}
private void UpdateCache(AzRecord r, bool remove)
{
var aces = Cache.Get<AzRecordStore>(GetKey(r.Tenant));
if (aces != null)
{
lock (aces)
{
if (remove)
{
aces.Remove(r);
}
else
{
aces.Add(r);
}
}
}
}
public static string GetKey(int tenant)
{
return "acl" + tenant.ToString();
}
}
namespace ASC.Core.Caching;
[Scope]
class CachedAzService : IAzService
{
private readonly IAzService service;
private readonly ICacheNotify<AzRecordCache> cacheNotify;
private ICache Cache { get; }
private TimeSpan CacheExpiration { get; set; }
public CachedAzService(DbAzService service, AzServiceCache azServiceCache)
{
this.service = service ?? throw new ArgumentNullException(nameof(service));
Cache = azServiceCache.Cache;
cacheNotify = azServiceCache.CacheNotify;
CacheExpiration = TimeSpan.FromMinutes(10);
}
public IEnumerable<AzRecord> GetAces(int tenant, DateTime from)
{
var key = AzServiceCache.GetKey(tenant);
var aces = Cache.Get<AzRecordStore>(key);
if (aces == null)
{
var records = service.GetAces(tenant, default);
aces = new AzRecordStore(records);
Cache.Insert(key, aces, DateTime.UtcNow.Add(CacheExpiration));
}
return aces;
}
public AzRecord SaveAce(int tenant, AzRecord r)
{
r = service.SaveAce(tenant, r);
cacheNotify.Publish(r, ASC.Common.Caching.CacheNotifyAction.InsertOrUpdate);
return r;
}
public void RemoveAce(int tenant, AzRecord r)
{
service.RemoveAce(tenant, r);
cacheNotify.Publish(r, ASC.Common.Caching.CacheNotifyAction.Remove);
}
}
}
[Singletone]
class AzServiceCache
{
internal readonly ICache Cache;
internal readonly ICacheNotify<AzRecordCache> CacheNotify;
public AzServiceCache(ICacheNotify<AzRecordCache> cacheNotify, ICache cache)
{
CacheNotify = cacheNotify;
Cache = cache;
cacheNotify.Subscribe((r) => UpdateCache(r, true), CacheNotifyAction.Remove);
cacheNotify.Subscribe((r) => UpdateCache(r, false), CacheNotifyAction.InsertOrUpdate);
}
private void UpdateCache(AzRecord r, bool remove)
{
var aces = Cache.Get<AzRecordStore>(GetKey(r.Tenant));
if (aces != null)
{
lock (aces)
{
if (remove)
{
aces.Remove(r);
}
else
{
aces.Add(r);
}
}
}
}
public static string GetKey(int tenant)
{
return "acl" + tenant.ToString();
}
}
[Scope]
class CachedAzService : IAzService
{
private readonly IAzService _service;
private readonly ICacheNotify<AzRecordCache> _cacheNotify;
private readonly ICache _cache;
private readonly TimeSpan _cacheExpiration;
public CachedAzService(DbAzService service, AzServiceCache azServiceCache)
{
_service = service ?? throw new ArgumentNullException(nameof(service));
_cache = azServiceCache.Cache;
_cacheNotify = azServiceCache.CacheNotify;
_cacheExpiration = TimeSpan.FromMinutes(10);
}
public IEnumerable<AzRecord> GetAces(int tenant, DateTime from)
{
var key = AzServiceCache.GetKey(tenant);
var aces = _cache.Get<AzRecordStore>(key);
if (aces == null)
{
var records = _service.GetAces(tenant, default);
aces = new AzRecordStore(records);
_cache.Insert(key, aces, DateTime.UtcNow.Add(_cacheExpiration));
}
return aces;
}
public AzRecord SaveAce(int tenant, AzRecord r)
{
r = _service.SaveAce(tenant, r);
_cacheNotify.Publish(r, CacheNotifyAction.InsertOrUpdate);
return r;
}
public void RemoveAce(int tenant, AzRecord r)
{
_service.RemoveAce(tenant, r);
_cacheNotify.Publish(r, CacheNotifyAction.Remove);
}
}

View File

@ -23,158 +23,157 @@
*
*/
namespace ASC.Core.Caching
namespace ASC.Core.Caching;
[Singletone]
class QuotaServiceCache
{
[Singletone]
class QuotaServiceCache
{
internal const string KEY_QUOTA = "quota";
internal const string KEY_QUOTA_ROWS = "quotarows";
internal TrustInterval Interval { get; set; }
internal ICache Cache { get; }
internal ICacheNotify<QuotaCacheItem> CacheNotify { get; }
internal bool QuotaCacheEnabled { get; }
public QuotaServiceCache(IConfiguration Configuration, ICacheNotify<QuotaCacheItem> cacheNotify, ICache cache)
{
if (Configuration["core:enable-quota-cache"] == null)
{
QuotaCacheEnabled = true;
}
else
{
QuotaCacheEnabled = !bool.TryParse(Configuration["core:enable-quota-cache"], out var enabled) || enabled;
}
CacheNotify = cacheNotify;
Cache = cache;
Interval = new TrustInterval();
internal const string KeyQuota = "quota";
internal const string KeyQuotaRows = "quotarows";
cacheNotify.Subscribe((i) =>
{
if (i.Key == KEY_QUOTA)
{
Cache.Remove(KEY_QUOTA);
}
else
{
Cache.Remove(i.Key);
}
}, ASC.Common.Caching.CacheNotifyAction.Any);
}
}
internal TrustInterval Interval;
internal readonly ICache Cache;
internal readonly ICacheNotify<QuotaCacheItem> CacheNotify;
internal readonly bool QuotaCacheEnabled;
[Scope]
class ConfigureCachedQuotaService : IConfigureNamedOptions<CachedQuotaService>
public QuotaServiceCache(IConfiguration Configuration, ICacheNotify<QuotaCacheItem> cacheNotify, ICache cache)
{
private IOptionsSnapshot<DbQuotaService> Service { get; }
private QuotaServiceCache QuotaServiceCache { get; }
public ConfigureCachedQuotaService(
IOptionsSnapshot<DbQuotaService> service,
QuotaServiceCache quotaServiceCache)
if (Configuration["core:enable-quota-cache"] == null)
{
Service = service;
QuotaServiceCache = quotaServiceCache;
QuotaCacheEnabled = true;
}
else
{
QuotaCacheEnabled = !bool.TryParse(Configuration["core:enable-quota-cache"], out var enabled) || enabled;
}
public void Configure(string name, CachedQuotaService options)
{
Configure(options);
options.Service = Service.Get(name);
}
CacheNotify = cacheNotify;
Cache = cache;
Interval = new TrustInterval();
public void Configure(CachedQuotaService options)
cacheNotify.Subscribe((i) =>
{
options.Service = Service.Value;
options.QuotaServiceCache = QuotaServiceCache;
options.Cache = QuotaServiceCache.Cache;
options.CacheNotify = QuotaServiceCache.CacheNotify;
}
if (i.Key == KeyQuota)
{
Cache.Remove(KeyQuota);
}
else
{
Cache.Remove(i.Key);
}
}, CacheNotifyAction.Any);
}
}
[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;
}
[Scope]
class CachedQuotaService : IQuotaService
{
internal IQuotaService Service { get; set; }
internal ICache Cache { get; set; }
internal ICacheNotify<QuotaCacheItem> CacheNotify { get; set; }
internal TrustInterval Interval { get; set; }
internal TimeSpan CacheExpiration { get; set; }
internal QuotaServiceCache QuotaServiceCache { get; set; }
public CachedQuotaService()
{
Interval = new TrustInterval();
CacheExpiration = TimeSpan.FromMinutes(10);
}
public CachedQuotaService(DbQuotaService service, QuotaServiceCache quotaServiceCache) : this()
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
{
internal IQuotaService Service;
internal ICache Cache;
internal ICacheNotify<QuotaCacheItem> CacheNotify;
internal TrustInterval Interval;
internal TimeSpan CacheExpiration;
internal QuotaServiceCache QuotaServiceCache;
public CachedQuotaService()
{
Interval = new TrustInterval();
CacheExpiration = TimeSpan.FromMinutes(10);
}
public CachedQuotaService(DbQuotaService service, QuotaServiceCache quotaServiceCache) : this()
{
Service = service ?? throw new ArgumentNullException(nameof(service));
QuotaServiceCache = quotaServiceCache;
Cache = quotaServiceCache.Cache;
CacheNotify = quotaServiceCache.CacheNotify;
}
public IEnumerable<TenantQuota> GetTenantQuotas()
{
var quotas = Cache.Get<IEnumerable<TenantQuota>>(QuotaServiceCache.KeyQuota);
if (quotas == null)
{
Service = service ?? throw new ArgumentNullException(nameof(service));
QuotaServiceCache = quotaServiceCache;
Cache = quotaServiceCache.Cache;
CacheNotify = quotaServiceCache.CacheNotify;
}
public IEnumerable<TenantQuota> GetTenantQuotas()
{
var quotas = Cache.Get<IEnumerable<TenantQuota>>(QuotaServiceCache.KEY_QUOTA);
if (quotas == null)
{
quotas = Service.GetTenantQuotas();
if (QuotaServiceCache.QuotaCacheEnabled)
{
Cache.Insert(QuotaServiceCache.KEY_QUOTA, quotas, DateTime.UtcNow.Add(CacheExpiration));
}
}
return quotas;
}
public TenantQuota GetTenantQuota(int tenant)
{
return GetTenantQuotas().SingleOrDefault(q => q.Id == tenant);
}
public TenantQuota SaveTenantQuota(TenantQuota quota)
{
var q = Service.SaveTenantQuota(quota);
CacheNotify.Publish(new QuotaCacheItem { Key = QuotaServiceCache.KEY_QUOTA }, ASC.Common.Caching.CacheNotifyAction.Any);
return q;
}
public void RemoveTenantQuota(int tenant)
{
throw new NotImplementedException();
}
public void SetTenantQuotaRow(TenantQuotaRow row, bool exchange)
{
Service.SetTenantQuotaRow(row, exchange);
CacheNotify.Publish(new QuotaCacheItem { Key = GetKey(row.Tenant) }, ASC.Common.Caching.CacheNotifyAction.InsertOrUpdate);
}
public IEnumerable<TenantQuotaRow> FindTenantQuotaRows(int tenantId)
{
var key = GetKey(tenantId);
var result = Cache.Get<IEnumerable<TenantQuotaRow>>(key);
if (result == null)
quotas = Service.GetTenantQuotas();
if (QuotaServiceCache.QuotaCacheEnabled)
{
result = Service.FindTenantQuotaRows(tenantId);
Cache.Insert(key, result, DateTime.UtcNow.Add(CacheExpiration));
Cache.Insert(QuotaServiceCache.KeyQuota, quotas, DateTime.UtcNow.Add(CacheExpiration));
}
return result;
}
public string GetKey(int tenant)
return quotas;
}
public TenantQuota GetTenantQuota(int tenant)
{
return GetTenantQuotas().SingleOrDefault(q => q.Tenant == tenant);
}
public TenantQuota SaveTenantQuota(TenantQuota quota)
{
var q = Service.SaveTenantQuota(quota);
CacheNotify.Publish(new QuotaCacheItem { Key = QuotaServiceCache.KeyQuota }, CacheNotifyAction.Any);
return q;
}
public void RemoveTenantQuota(int tenant)
{
throw new NotImplementedException();
}
public void SetTenantQuotaRow(TenantQuotaRow row, bool exchange)
{
Service.SetTenantQuotaRow(row, exchange);
CacheNotify.Publish(new QuotaCacheItem { Key = GetKey(row.Tenant) }, CacheNotifyAction.InsertOrUpdate);
}
public IEnumerable<TenantQuotaRow> FindTenantQuotaRows(int tenantId)
{
var key = GetKey(tenantId);
var result = Cache.Get<IEnumerable<TenantQuotaRow>>(key);
if (result == null)
{
return QuotaServiceCache.KEY_QUOTA_ROWS + tenant;
}
}
result = Service.FindTenantQuotaRows(tenantId);
Cache.Insert(key, result, DateTime.UtcNow.Add(CacheExpiration));
}
return result;
}
public string GetKey(int tenant)
{
return QuotaServiceCache.KeyQuotaRows + tenant;
}
}

View File

@ -23,274 +23,274 @@
*
*/
namespace ASC.Core.Caching
namespace ASC.Core.Caching;
[Singletone]
public class SubscriptionServiceCache
{
[Singletone]
public class SubscriptionServiceCache
internal readonly ICache Cache;
internal readonly ICacheNotify<SubscriptionRecord> NotifyRecord;
internal readonly ICacheNotify<SubscriptionMethodCache> NotifyMethod;
public SubscriptionServiceCache(ICacheNotify<SubscriptionRecord> notifyRecord, ICacheNotify<SubscriptionMethodCache> notifyMethod, ICache cache)
{
internal ICache Cache { get; }
internal ICacheNotify<SubscriptionRecord> NotifyRecord { get; }
internal ICacheNotify<SubscriptionMethodCache> NotifyMethod { get; }
Cache = cache;
NotifyRecord = notifyRecord;
NotifyMethod = notifyMethod;
public SubscriptionServiceCache(ICacheNotify<SubscriptionRecord> notifyRecord, ICacheNotify<SubscriptionMethodCache> notifyMethod, ICache cache)
notifyRecord.Subscribe((s) =>
{
Cache = cache;
NotifyRecord = notifyRecord;
NotifyMethod = notifyMethod;
notifyRecord.Subscribe((s) =>
var store = GetSubsciptionsStore(s.Tenant, s.SourceId, s.ActionId);
if (store != null)
{
var store = GetSubsciptionsStore(s.Tenant, s.SourceId, s.ActionId);
if (store != null)
lock (store)
{
lock (store)
store.SaveSubscription(s);
}
}
}, CacheNotifyAction.InsertOrUpdate);
notifyRecord.Subscribe((s) =>
{
var store = GetSubsciptionsStore(s.Tenant, s.SourceId, s.ActionId);
if (store != null)
{
lock (store)
{
if (s.ObjectId == null)
{
store.SaveSubscription(s);
store.RemoveSubscriptions();
}
else
{
store.RemoveSubscriptions(s.ObjectId);
}
}
}, ASC.Common.Caching.CacheNotifyAction.InsertOrUpdate);
}
}, CacheNotifyAction.Remove);
notifyRecord.Subscribe((s) =>
{
var store = GetSubsciptionsStore(s.Tenant, s.SourceId, s.ActionId);
if (store != null)
{
lock (store)
{
if (s.ObjectId == null)
{
store.RemoveSubscriptions();
}
else
{
store.RemoveSubscriptions(s.ObjectId);
}
}
}
}, ASC.Common.Caching.CacheNotifyAction.Remove);
notifyMethod.Subscribe((m) =>
{
var store = GetSubsciptionsStore(m.Tenant, m.SourceId, m.ActionId);
if (store != null)
{
lock (store)
{
store.SetSubscriptionMethod(m);
}
}
}, ASC.Common.Caching.CacheNotifyAction.Any);
}
private SubsciptionsStore GetSubsciptionsStore(int tenant, string sourceId, string actionId)
notifyMethod.Subscribe((m) =>
{
return Cache.Get<SubsciptionsStore>(GetKey(tenant, sourceId, actionId));
}
public static string GetKey(int tenant, string sourceId, string actionId)
{
return string.Format("sub/{0}/{1}/{2}", tenant, sourceId, actionId);
}
var store = GetSubsciptionsStore(m.Tenant, m.SourceId, m.ActionId);
if (store != null)
{
lock (store)
{
store.SetSubscriptionMethod(m);
}
}
}, CacheNotifyAction.Any);
}
[Scope]
public class CachedSubscriptionService : ISubscriptionService
private SubsciptionsStore GetSubsciptionsStore(int tenant, string sourceId, string actionId)
{
private readonly ISubscriptionService service;
private readonly ICache cache;
private readonly ICacheNotify<SubscriptionRecord> notifyRecord;
private readonly ICacheNotify<SubscriptionMethodCache> notifyMethod;
private TimeSpan CacheExpiration { get; set; }
public CachedSubscriptionService(DbSubscriptionService service, SubscriptionServiceCache subscriptionServiceCache)
{
this.service = service ?? throw new ArgumentNullException(nameof(service));
cache = subscriptionServiceCache.Cache;
notifyRecord = subscriptionServiceCache.NotifyRecord;
notifyMethod = subscriptionServiceCache.NotifyMethod;
CacheExpiration = TimeSpan.FromMinutes(5);
}
public IEnumerable<SubscriptionRecord> GetSubscriptions(int tenant, string sourceId, string actionId)
{
var store = GetSubsciptionsStore(tenant, sourceId, actionId);
lock (store)
{
return store.GetSubscriptions();
}
}
public IEnumerable<SubscriptionRecord> GetSubscriptions(int tenant, string sourceId, string actionId, string recipientId, string objectId)
{
var store = GetSubsciptionsStore(tenant, sourceId, actionId);
lock (store)
{
return store.GetSubscriptions(recipientId, objectId);
}
}
public string[] GetRecipients(int tenant, string sourceID, string actionID, string objectID)
{
return service.GetRecipients(tenant, sourceID, actionID, objectID);
}
public string[] GetSubscriptions(int tenant, string sourceId, string actionId, string recipientId, bool checkSubscribe)
{
return service.GetSubscriptions(tenant, sourceId, actionId, recipientId, checkSubscribe);
}
public SubscriptionRecord GetSubscription(int tenant, string sourceId, string actionId, string recipientId, string objectId)
{
var store = GetSubsciptionsStore(tenant, sourceId, actionId);
lock (store)
{
return store.GetSubscription(recipientId, objectId);
}
}
public void SaveSubscription(SubscriptionRecord s)
{
service.SaveSubscription(s);
notifyRecord.Publish(s, ASC.Common.Caching.CacheNotifyAction.InsertOrUpdate);
}
public void RemoveSubscriptions(int tenant, string sourceId, string actionId)
{
service.RemoveSubscriptions(tenant, sourceId, actionId);
notifyRecord.Publish(new SubscriptionRecord { Tenant = tenant, SourceId = sourceId, ActionId = actionId }, ASC.Common.Caching.CacheNotifyAction.Remove);
}
public void RemoveSubscriptions(int tenant, string sourceId, string actionId, string objectId)
{
service.RemoveSubscriptions(tenant, sourceId, actionId, objectId);
notifyRecord.Publish(new SubscriptionRecord { Tenant = tenant, SourceId = sourceId, ActionId = actionId, ObjectId = objectId }, ASC.Common.Caching.CacheNotifyAction.Remove);
}
public IEnumerable<SubscriptionMethod> GetSubscriptionMethods(int tenant, string sourceId, string actionId, string recipientId)
{
var store = GetSubsciptionsStore(tenant, sourceId, actionId);
lock (store)
{
return store.GetSubscriptionMethods(recipientId);
}
}
public void SetSubscriptionMethod(SubscriptionMethod m)
{
service.SetSubscriptionMethod(m);
notifyMethod.Publish(m, ASC.Common.Caching.CacheNotifyAction.Any);
}
private SubsciptionsStore GetSubsciptionsStore(int tenant, string sourceId, string actionId)
{
var key = SubscriptionServiceCache.GetKey(tenant, sourceId, actionId);
var store = cache.Get<SubsciptionsStore>(key);
if (store == null)
{
var records = service.GetSubscriptions(tenant, sourceId, actionId);
var methods = service.GetSubscriptionMethods(tenant, sourceId, actionId, null);
store = new SubsciptionsStore(records, methods);
cache.Insert(key, store, DateTime.UtcNow.Add(CacheExpiration));
}
return store;
}
public bool IsUnsubscribe(int tenant, string sourceId, string actionId, string recipientId, string objectId)
{
return service.IsUnsubscribe(tenant, sourceId, actionId, recipientId, objectId);
}
return Cache.Get<SubsciptionsStore>(GetKey(tenant, sourceId, actionId));
}
internal class SubsciptionsStore
public static string GetKey(int tenant, string sourceId, string actionId)
{
private readonly List<SubscriptionRecord> records;
private IDictionary<string, List<SubscriptionRecord>> recordsByRec;
private IDictionary<string, List<SubscriptionRecord>> recordsByObj;
private readonly List<SubscriptionMethod> methods;
private IDictionary<string, List<SubscriptionMethod>> methodsByRec;
public SubsciptionsStore(IEnumerable<SubscriptionRecord> records, IEnumerable<SubscriptionMethod> methods)
{
this.records = records.ToList();
this.methods = methods.ToList();
BuildSubscriptionsIndex(records);
BuildMethodsIndex(methods);
}
public IEnumerable<SubscriptionRecord> GetSubscriptions()
{
return records.ToList();
}
public IEnumerable<SubscriptionRecord> GetSubscriptions(string recipientId, string objectId)
{
return recipientId != null ?
recordsByRec.ContainsKey(recipientId) ? recordsByRec[recipientId].ToList() : new List<SubscriptionRecord>() :
recordsByObj.ContainsKey(objectId ?? string.Empty) ? recordsByObj[objectId ?? string.Empty].ToList() : new List<SubscriptionRecord>();
}
public SubscriptionRecord GetSubscription(string recipientId, string objectId)
{
return recordsByRec.ContainsKey(recipientId) ?
recordsByRec[recipientId].Where(s => s.ObjectId == (objectId ?? "")).FirstOrDefault() :
null;
}
public void SaveSubscription(SubscriptionRecord s)
{
var old = GetSubscription(s.RecipientId, s.ObjectId);
if (old != null)
{
old.Subscribed = s.Subscribed;
}
else
{
records.Add(s);
BuildSubscriptionsIndex(records);
}
}
public void RemoveSubscriptions()
{
records.Clear();
BuildSubscriptionsIndex(records);
}
public void RemoveSubscriptions(string objectId)
{
records.RemoveAll(s => s.ObjectId == (objectId ?? ""));
BuildSubscriptionsIndex(records);
}
public IEnumerable<SubscriptionMethod> GetSubscriptionMethods(string recipientId)
{
return string.IsNullOrEmpty(recipientId) ?
methods.ToList() :
methodsByRec.ContainsKey(recipientId) ? methodsByRec[recipientId].ToList() : new List<SubscriptionMethod>();
}
public void SetSubscriptionMethod(SubscriptionMethod m)
{
methods.RemoveAll(r => r.Tenant == m.Tenant && r.SourceId == m.SourceId && r.ActionId == m.ActionId && r.RecipientId == m.RecipientId);
if (m.Methods != null && 0 < m.Methods.Length)
{
methods.Add(m);
}
BuildMethodsIndex(methods);
}
private void BuildSubscriptionsIndex(IEnumerable<SubscriptionRecord> records)
{
recordsByRec = records.GroupBy(r => r.RecipientId).ToDictionary(g => g.Key, g => g.ToList());
recordsByObj = records.GroupBy(r => r.ObjectId ?? string.Empty).ToDictionary(g => g.Key, g => g.ToList());
}
private void BuildMethodsIndex(IEnumerable<SubscriptionMethod> methods)
{
methodsByRec = methods.GroupBy(r => r.RecipientId).ToDictionary(g => g.Key, g => g.ToList());
}
return string.Format("sub/{0}/{1}/{2}", tenant, sourceId, actionId);
}
}
[Scope]
public class CachedSubscriptionService : ISubscriptionService
{
private readonly ISubscriptionService _service;
private readonly ICache _cache;
private readonly ICacheNotify<SubscriptionRecord> _notifyRecord;
private readonly ICacheNotify<SubscriptionMethodCache> _notifyMethod;
private TimeSpan _cacheExpiration;
public CachedSubscriptionService(DbSubscriptionService service, SubscriptionServiceCache subscriptionServiceCache)
{
_service = service ?? throw new ArgumentNullException(nameof(service));
_cache = subscriptionServiceCache.Cache;
_notifyRecord = subscriptionServiceCache.NotifyRecord;
_notifyMethod = subscriptionServiceCache.NotifyMethod;
_cacheExpiration = TimeSpan.FromMinutes(5);
}
public IEnumerable<SubscriptionRecord> GetSubscriptions(int tenant, string sourceId, string actionId)
{
var store = GetSubsciptionsStore(tenant, sourceId, actionId);
lock (store)
{
return store.GetSubscriptions();
}
}
public IEnumerable<SubscriptionRecord> GetSubscriptions(int tenant, string sourceId, string actionId, string recipientId, string objectId)
{
var store = GetSubsciptionsStore(tenant, sourceId, actionId);
lock (store)
{
return store.GetSubscriptions(recipientId, objectId);
}
}
public string[] GetRecipients(int tenant, string sourceID, string actionID, string objectID)
{
return _service.GetRecipients(tenant, sourceID, actionID, objectID);
}
public string[] GetSubscriptions(int tenant, string sourceId, string actionId, string recipientId, bool checkSubscribe)
{
return _service.GetSubscriptions(tenant, sourceId, actionId, recipientId, checkSubscribe);
}
public SubscriptionRecord GetSubscription(int tenant, string sourceId, string actionId, string recipientId, string objectId)
{
var store = GetSubsciptionsStore(tenant, sourceId, actionId);
lock (store)
{
return store.GetSubscription(recipientId, objectId);
}
}
public void SaveSubscription(SubscriptionRecord s)
{
_service.SaveSubscription(s);
_notifyRecord.Publish(s, ASC.Common.Caching.CacheNotifyAction.InsertOrUpdate);
}
public void RemoveSubscriptions(int tenant, string sourceId, string actionId)
{
_service.RemoveSubscriptions(tenant, sourceId, actionId);
_notifyRecord.Publish(new SubscriptionRecord { Tenant = tenant, SourceId = sourceId, ActionId = actionId }, ASC.Common.Caching.CacheNotifyAction.Remove);
}
public void RemoveSubscriptions(int tenant, string sourceId, string actionId, string objectId)
{
_service.RemoveSubscriptions(tenant, sourceId, actionId, objectId);
_notifyRecord.Publish(new SubscriptionRecord { Tenant = tenant, SourceId = sourceId, ActionId = actionId, ObjectId = objectId }, ASC.Common.Caching.CacheNotifyAction.Remove);
}
public IEnumerable<SubscriptionMethod> GetSubscriptionMethods(int tenant, string sourceId, string actionId, string recipientId)
{
var store = GetSubsciptionsStore(tenant, sourceId, actionId);
lock (store)
{
return store.GetSubscriptionMethods(recipientId);
}
}
public void SetSubscriptionMethod(SubscriptionMethod m)
{
_service.SetSubscriptionMethod(m);
_notifyMethod.Publish(m, ASC.Common.Caching.CacheNotifyAction.Any);
}
private SubsciptionsStore GetSubsciptionsStore(int tenant, string sourceId, string actionId)
{
var key = SubscriptionServiceCache.GetKey(tenant, sourceId, actionId);
var store = _cache.Get<SubsciptionsStore>(key);
if (store == null)
{
var records = _service.GetSubscriptions(tenant, sourceId, actionId);
var methods = _service.GetSubscriptionMethods(tenant, sourceId, actionId, null);
store = new SubsciptionsStore(records, methods);
_cache.Insert(key, store, DateTime.UtcNow.Add(_cacheExpiration));
}
return store;
}
public bool IsUnsubscribe(int tenant, string sourceId, string actionId, string recipientId, string objectId)
{
return _service.IsUnsubscribe(tenant, sourceId, actionId, recipientId, objectId);
}
}
internal class SubsciptionsStore
{
private readonly List<SubscriptionRecord> _records;
private IDictionary<string, List<SubscriptionRecord>> _recordsByRec;
private IDictionary<string, List<SubscriptionRecord>> _recordsByObj;
private readonly List<SubscriptionMethod> _methods;
private IDictionary<string, List<SubscriptionMethod>> _methodsByRec;
public SubsciptionsStore(IEnumerable<SubscriptionRecord> records, IEnumerable<SubscriptionMethod> methods)
{
_records = records.ToList();
_methods = methods.ToList();
BuildSubscriptionsIndex(records);
BuildMethodsIndex(methods);
}
public IEnumerable<SubscriptionRecord> GetSubscriptions()
{
return _records.ToList();
}
public IEnumerable<SubscriptionRecord> GetSubscriptions(string recipientId, string objectId)
{
return recipientId != null ?
_recordsByRec.ContainsKey(recipientId) ? _recordsByRec[recipientId].ToList() : new List<SubscriptionRecord>() :
_recordsByObj.ContainsKey(objectId ?? string.Empty) ? _recordsByObj[objectId ?? string.Empty].ToList() : new List<SubscriptionRecord>();
}
public SubscriptionRecord GetSubscription(string recipientId, string objectId)
{
return _recordsByRec.ContainsKey(recipientId) ?
_recordsByRec[recipientId].Where(s => s.ObjectId == (objectId ?? "")).FirstOrDefault() :
null;
}
public void SaveSubscription(SubscriptionRecord s)
{
var old = GetSubscription(s.RecipientId, s.ObjectId);
if (old != null)
{
old.Subscribed = s.Subscribed;
}
else
{
_records.Add(s);
BuildSubscriptionsIndex(_records);
}
}
public void RemoveSubscriptions()
{
_records.Clear();
BuildSubscriptionsIndex(_records);
}
public void RemoveSubscriptions(string objectId)
{
_records.RemoveAll(s => s.ObjectId == (objectId ?? ""));
BuildSubscriptionsIndex(_records);
}
public IEnumerable<SubscriptionMethod> GetSubscriptionMethods(string recipientId)
{
return string.IsNullOrEmpty(recipientId) ?
_methods.ToList() :
_methodsByRec.ContainsKey(recipientId) ? _methodsByRec[recipientId].ToList() : new List<SubscriptionMethod>();
}
public void SetSubscriptionMethod(SubscriptionMethod m)
{
_methods.RemoveAll(r => r.Tenant == m.Tenant && r.Source == m.Source && r.Action == m.Action && r.Recipient == m.Recipient);
if (m.Methods != null && 0 < m.Methods.Length)
{
_methods.Add(m);
}
BuildMethodsIndex(_methods);
}
private void BuildSubscriptionsIndex(IEnumerable<SubscriptionRecord> records)
{
_recordsByRec = records.GroupBy(r => r.RecipientId).ToDictionary(g => g.Key, g => g.ToList());
_recordsByObj = records.GroupBy(r => r.ObjectId ?? string.Empty).ToDictionary(g => g.Key, g => g.ToList());
}
private void BuildMethodsIndex(IEnumerable<SubscriptionMethod> methods)
{
_methodsByRec = methods.GroupBy(r => r.Recipient).ToDictionary(g => g.Key, g => g.ToList());
}
}

View File

@ -23,283 +23,303 @@
*
*/
namespace ASC.Core.Caching
namespace ASC.Core.Caching;
[Singletone]
class TenantServiceCache
{
[Singletone]
class TenantServiceCache
{
private const string KEY = "tenants";
private TimeSpan CacheExpiration { get; set; }
internal ICache Cache { get; }
internal ICacheNotify<TenantCacheItem> CacheNotifyItem { get; }
internal ICacheNotify<TenantSetting> CacheNotifySettings { get; }
public TenantServiceCache(
CoreBaseSettings coreBaseSettings,
ICacheNotify<TenantCacheItem> cacheNotifyItem,
ICacheNotify<TenantSetting> cacheNotifySettings,
ICache cache)
{
CacheNotifyItem = cacheNotifyItem;
CacheNotifySettings = cacheNotifySettings;
Cache = cache;
CacheExpiration = TimeSpan.FromMinutes(2);
cacheNotifyItem.Subscribe((t) =>
{
var tenants = GetTenantStore();
tenants.Remove(t.TenantId);
tenants.Clear(coreBaseSettings);
}, ASC.Common.Caching.CacheNotifyAction.InsertOrUpdate);
cacheNotifySettings.Subscribe((s) =>
{
Cache.Remove(s.Key);
}, ASC.Common.Caching.CacheNotifyAction.Remove);
}
internal TenantStore GetTenantStore()
{
var store = Cache.Get<TenantStore>(KEY);
if (store == null)
{
store = new TenantStore();
Cache.Insert(KEY, store, DateTime.UtcNow.Add(CacheExpiration));
}
return store;
}
internal class TenantStore
{
private readonly Dictionary<int, Tenant> byId = new Dictionary<int, Tenant>();
private readonly Dictionary<string, Tenant> byDomain = new Dictionary<string, Tenant>();
private readonly object locker = new object();
public Tenant Get(int id)
{
Tenant t;
lock (locker)
{
byId.TryGetValue(id, out t);
}
return t;
}
public Tenant Get(string domain)
{
if (string.IsNullOrEmpty(domain)) return null;
Tenant t;
lock (locker)
{
byDomain.TryGetValue(domain, out t);
}
return t;
}
public void Insert(Tenant t, string ip = null)
{
if (t == null)
{
return;
}
Remove(t.TenantId);
lock (locker)
{
byId[t.TenantId] = t;
byDomain[t.TenantAlias] = t;
if (!string.IsNullOrEmpty(t.MappedDomain)) byDomain[t.MappedDomain] = t;
if (!string.IsNullOrEmpty(ip)) byDomain[ip] = t;
}
}
public void Remove(int id)
{
var t = Get(id);
if (t != null)
{
lock (locker)
{
byId.Remove(id);
byDomain.Remove(t.TenantAlias);
if (!string.IsNullOrEmpty(t.MappedDomain))
{
byDomain.Remove(t.MappedDomain);
}
}
}
}
internal void Clear(CoreBaseSettings coreBaseSettings)
{
if (!coreBaseSettings.Standalone) return;
lock (locker)
{
byId.Clear();
byDomain.Clear();
}
}
}
}
private const string Key = "tenants";
private TimeSpan _cacheExpiration;
internal readonly ICache Cache;
internal readonly ICacheNotify<TenantCacheItem> CacheNotifyItem;
internal readonly ICacheNotify<TenantSetting> CacheNotifySettings;
[Scope]
class ConfigureCachedTenantService : IConfigureNamedOptions<CachedTenantService>
public TenantServiceCache(
CoreBaseSettings coreBaseSettings,
ICacheNotify<TenantCacheItem> cacheNotifyItem,
ICacheNotify<TenantSetting> cacheNotifySettings,
ICache cache)
{
private IOptionsSnapshot<DbTenantService> Service { get; }
private TenantServiceCache TenantServiceCache { get; }
CacheNotifyItem = cacheNotifyItem;
CacheNotifySettings = cacheNotifySettings;
Cache = cache;
_cacheExpiration = TimeSpan.FromMinutes(2);
public ConfigureCachedTenantService(
IOptionsSnapshot<DbTenantService> service,
TenantServiceCache tenantServiceCache)
cacheNotifyItem.Subscribe((t) =>
{
Service = service;
TenantServiceCache = tenantServiceCache;
}
var tenants = GetTenantStore();
tenants.Remove(t.TenantId);
tenants.Clear(coreBaseSettings);
}, CacheNotifyAction.InsertOrUpdate);
public void Configure(string name, CachedTenantService options)
cacheNotifySettings.Subscribe((s) =>
{
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;
}
Cache.Remove(s.Key);
}, CacheNotifyAction.Remove);
}
[Scope]
class CachedTenantService : ITenantService
{
internal ITenantService Service { get; set; }
private readonly ICache cache;
internal ICacheNotify<TenantSetting> CacheNotifySettings { get; set; }
internal ICacheNotify<TenantCacheItem> CacheNotifyItem { get; set; }
private TimeSpan SettingsExpiration { get; set; }
internal TenantServiceCache TenantServiceCache { get; set; }
public CachedTenantService()
{
SettingsExpiration = TimeSpan.FromMinutes(2);
}
public CachedTenantService(DbTenantService service, TenantServiceCache tenantServiceCache, ICache cache) : this()
internal TenantStore GetTenantStore()
{
var store = Cache.Get<TenantStore>(Key);
if (store == null)
{
this.cache = cache;
Service = service ?? throw new ArgumentNullException(nameof(service));
TenantServiceCache = tenantServiceCache;
CacheNotifyItem = tenantServiceCache.CacheNotifyItem;
CacheNotifySettings = tenantServiceCache.CacheNotifySettings;
}
public void ValidateDomain(string domain)
{
Service.ValidateDomain(domain);
}
public IEnumerable<Tenant> GetTenants(string login, string passwordHash)
{
return Service.GetTenants(login, passwordHash);
}
public IEnumerable<Tenant> GetTenants(DateTime from, bool active = true)
{
return Service.GetTenants(from, active);
store = new TenantStore();
Cache.Insert(Key, store, DateTime.UtcNow.Add(_cacheExpiration));
}
public IEnumerable<Tenant> GetTenants(List<int> ids)
return store;
}
internal class TenantStore
{
private readonly Dictionary<int, Tenant> _byId = new Dictionary<int, Tenant>();
private readonly Dictionary<string, Tenant> _byDomain = new Dictionary<string, Tenant>();
private readonly object _locker = new object();
public Tenant Get(int id)
{
return Service.GetTenants(ids);
Tenant t;
lock (_locker)
{
_byId.TryGetValue(id, out t);
}
return t;
}
public Tenant GetTenant(int id)
{
var tenants = TenantServiceCache.GetTenantStore();
var t = tenants.Get(id);
if (t == null)
{
t = Service.GetTenant(id);
if (t != null)
{
tenants.Insert(t);
}
}
return t;
}
public Tenant GetTenant(string domain)
{
var tenants = TenantServiceCache.GetTenantStore();
var t = tenants.Get(domain);
if (t == null)
{
t = Service.GetTenant(domain);
if (t != null)
{
tenants.Insert(t);
}
}
return t;
}
public Tenant GetTenantForStandaloneWithoutAlias(string ip)
{
var tenants = TenantServiceCache.GetTenantStore();
var t = tenants.Get(ip);
if (t == null)
{
t = Service.GetTenantForStandaloneWithoutAlias(ip);
if (t != null)
{
tenants.Insert(t, ip);
}
}
return t;
}
public Tenant SaveTenant(CoreSettings coreSettings, Tenant tenant)
{
tenant = Service.SaveTenant(coreSettings, tenant);
CacheNotifyItem.Publish(new TenantCacheItem() { TenantId = tenant.TenantId }, ASC.Common.Caching.CacheNotifyAction.InsertOrUpdate);
return tenant;
}
public void RemoveTenant(int id, bool auto = false)
{
Service.RemoveTenant(id, auto);
CacheNotifyItem.Publish(new TenantCacheItem() { TenantId = id }, ASC.Common.Caching.CacheNotifyAction.InsertOrUpdate);
}
public IEnumerable<TenantVersion> GetTenantVersions()
{
return Service.GetTenantVersions();
}
public byte[] GetTenantSettings(int tenant, string key)
{
var cacheKey = string.Format("settings/{0}/{1}", tenant, key);
var data = cache.Get<byte[]>(cacheKey);
if (data == null)
{
data = Service.GetTenantSettings(tenant, key);
cache.Insert(cacheKey, data ?? Array.Empty<byte>(), DateTime.UtcNow + SettingsExpiration);
}
return data == null ? null : data.Length == 0 ? null : data;
}
public void SetTenantSettings(int tenant, string key, byte[] data)
{
Service.SetTenantSettings(tenant, key, data);
var cacheKey = string.Format("settings/{0}/{1}", tenant, key);
CacheNotifySettings.Publish(new TenantSetting { Key = cacheKey }, ASC.Common.Caching.CacheNotifyAction.Remove);
}
}
public Tenant Get(string domain)
{
if (string.IsNullOrEmpty(domain))
{
return null;
}
Tenant t;
lock (_locker)
{
_byDomain.TryGetValue(domain, out t);
}
return t;
}
public void Insert(Tenant t, string ip = null)
{
if (t == null)
{
return;
}
Remove(t.Id);
lock (_locker)
{
_byId[t.Id] = t;
_byDomain[t.Alias] = t;
if (!string.IsNullOrEmpty(t.MappedDomain))
{
_byDomain[t.MappedDomain] = t;
}
if (!string.IsNullOrEmpty(ip))
{
_byDomain[ip] = t;
}
}
}
public void Remove(int id)
{
var t = Get(id);
if (t != null)
{
lock (_locker)
{
_byId.Remove(id);
_byDomain.Remove(t.Alias);
if (!string.IsNullOrEmpty(t.MappedDomain))
{
_byDomain.Remove(t.MappedDomain);
}
}
}
}
internal void Clear(CoreBaseSettings coreBaseSettings)
{
if (!coreBaseSettings.Standalone)
{
return;
}
lock (_locker)
{
_byId.Clear();
_byDomain.Clear();
}
}
}
}
[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;
private readonly ICache _cache;
internal ICacheNotify<TenantSetting> CacheNotifySettings;
internal ICacheNotify<TenantCacheItem> CacheNotifyItem;
private TimeSpan _settingsExpiration;
internal TenantServiceCache TenantServiceCache;
public CachedTenantService()
{
_settingsExpiration = TimeSpan.FromMinutes(2);
}
public CachedTenantService(DbTenantService service, TenantServiceCache tenantServiceCache, ICache cache) : this()
{
this._cache = cache;
Service = service ?? throw new ArgumentNullException(nameof(service));
TenantServiceCache = tenantServiceCache;
CacheNotifyItem = tenantServiceCache.CacheNotifyItem;
CacheNotifySettings = tenantServiceCache.CacheNotifySettings;
}
public void ValidateDomain(string domain)
{
Service.ValidateDomain(domain);
}
public IEnumerable<Tenant> GetTenants(string login, string passwordHash)
{
return Service.GetTenants(login, passwordHash);
}
public IEnumerable<Tenant> GetTenants(DateTime from, bool active = true)
{
return Service.GetTenants(from, active);
}
public IEnumerable<Tenant> GetTenants(List<int> ids)
{
return Service.GetTenants(ids);
}
public Tenant GetTenant(int id)
{
var tenants = TenantServiceCache.GetTenantStore();
var t = tenants.Get(id);
if (t == null)
{
t = Service.GetTenant(id);
if (t != null)
{
tenants.Insert(t);
}
}
return t;
}
public Tenant GetTenant(string domain)
{
var tenants = TenantServiceCache.GetTenantStore();
var t = tenants.Get(domain);
if (t == null)
{
t = Service.GetTenant(domain);
if (t != null)
{
tenants.Insert(t);
}
}
return t;
}
public Tenant GetTenantForStandaloneWithoutAlias(string ip)
{
var tenants = TenantServiceCache.GetTenantStore();
var t = tenants.Get(ip);
if (t == null)
{
t = Service.GetTenantForStandaloneWithoutAlias(ip);
if (t != null)
{
tenants.Insert(t, ip);
}
}
return t;
}
public Tenant SaveTenant(CoreSettings coreSettings, Tenant tenant)
{
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);
}
public IEnumerable<TenantVersion> GetTenantVersions()
{
return Service.GetTenantVersions();
}
public byte[] GetTenantSettings(int tenant, string key)
{
var cacheKey = string.Format("settings/{0}/{1}", tenant, key);
var data = _cache.Get<byte[]>(cacheKey);
if (data == null)
{
data = Service.GetTenantSettings(tenant, key);
_cache.Insert(cacheKey, data ?? Array.Empty<byte>(), DateTime.UtcNow + _settingsExpiration);
}
return data == null ? null : data.Length == 0 ? null : data;
}
public void SetTenantSettings(int tenant, string key, byte[] data)
{
Service.SetTenantSettings(tenant, key, data);
var cacheKey = string.Format("settings/{0}/{1}", tenant, key);
CacheNotifySettings.Publish(new TenantSetting { Key = cacheKey }, ASC.Common.Caching.CacheNotifyAction.Remove);
}
}

View File

@ -23,388 +23,397 @@
*
*/
namespace ASC.Core.Caching
namespace ASC.Core.Caching;
[Singletone]
public class UserServiceCache
{
[Singletone]
public class UserServiceCache
public const string Users = "users";
private const string Groups = "groups";
public const string Refs = "refs";
internal readonly ICache Cache;
internal readonly CoreBaseSettings CoreBaseSettings;
internal readonly ICacheNotify<UserInfoCacheItem> CacheUserInfoItem;
internal readonly ICacheNotify<UserPhotoCacheItem> CacheUserPhotoItem;
internal readonly ICacheNotify<GroupCacheItem> CacheGroupCacheItem;
internal readonly ICacheNotify<UserGroupRefCacheItem> CacheUserGroupRefItem;
public UserServiceCache(
CoreBaseSettings coreBaseSettings,
ICacheNotify<UserInfoCacheItem> cacheUserInfoItem,
ICacheNotify<UserPhotoCacheItem> cacheUserPhotoItem,
ICacheNotify<GroupCacheItem> cacheGroupCacheItem,
ICacheNotify<UserGroupRefCacheItem> cacheUserGroupRefItem,
ICache cache)
{
public const string USERS = "users";
private const string GROUPS = "groups";
public const string REFS = "refs";
Cache = cache;
CoreBaseSettings = coreBaseSettings;
CacheUserInfoItem = cacheUserInfoItem;
CacheUserPhotoItem = cacheUserPhotoItem;
CacheGroupCacheItem = cacheGroupCacheItem;
CacheUserGroupRefItem = cacheUserGroupRefItem;
internal ICache Cache { get; }
internal CoreBaseSettings CoreBaseSettings { get; }
internal ICacheNotify<UserInfoCacheItem> CacheUserInfoItem { get; }
internal ICacheNotify<UserPhotoCacheItem> CacheUserPhotoItem { get; }
internal ICacheNotify<GroupCacheItem> CacheGroupCacheItem { get; }
internal ICacheNotify<UserGroupRefCacheItem> CacheUserGroupRefItem { get; }
cacheUserInfoItem.Subscribe((u) => InvalidateCache(u), ASC.Common.Caching.CacheNotifyAction.Any);
cacheUserPhotoItem.Subscribe((p) => Cache.Remove(p.Key), ASC.Common.Caching.CacheNotifyAction.Remove);
cacheGroupCacheItem.Subscribe((g) => InvalidateCache(), ASC.Common.Caching.CacheNotifyAction.Any);
public UserServiceCache(
CoreBaseSettings coreBaseSettings,
ICacheNotify<UserInfoCacheItem> cacheUserInfoItem,
ICacheNotify<UserPhotoCacheItem> cacheUserPhotoItem,
ICacheNotify<GroupCacheItem> cacheGroupCacheItem,
ICacheNotify<UserGroupRefCacheItem> cacheUserGroupRefItem,
ICache cache)
cacheUserGroupRefItem.Subscribe((r) => UpdateUserGroupRefCache(r, true), ASC.Common.Caching.CacheNotifyAction.Remove);
cacheUserGroupRefItem.Subscribe((r) => UpdateUserGroupRefCache(r, false), ASC.Common.Caching.CacheNotifyAction.InsertOrUpdate);
}
public void InvalidateCache()
{
InvalidateCache(null);
}
private void InvalidateCache(UserInfoCacheItem userInfo)
{
if (userInfo != null)
{
Cache = cache;
CoreBaseSettings = coreBaseSettings;
CacheUserInfoItem = cacheUserInfoItem;
CacheUserPhotoItem = cacheUserPhotoItem;
CacheGroupCacheItem = cacheGroupCacheItem;
CacheUserGroupRefItem = cacheUserGroupRefItem;
cacheUserInfoItem.Subscribe((u) => InvalidateCache(u), ASC.Common.Caching.CacheNotifyAction.Any);
cacheUserPhotoItem.Subscribe((p) => Cache.Remove(p.Key), ASC.Common.Caching.CacheNotifyAction.Remove);
cacheGroupCacheItem.Subscribe((g) => InvalidateCache(), ASC.Common.Caching.CacheNotifyAction.Any);
cacheUserGroupRefItem.Subscribe((r) => UpdateUserGroupRefCache(r, true), ASC.Common.Caching.CacheNotifyAction.Remove);
cacheUserGroupRefItem.Subscribe((r) => UpdateUserGroupRefCache(r, false), ASC.Common.Caching.CacheNotifyAction.InsertOrUpdate);
}
public void InvalidateCache()
{
InvalidateCache(null);
}
private void InvalidateCache(UserInfoCacheItem userInfo)
{
if (userInfo != null)
{
var key = GetUserCacheKey(userInfo.Tenant, new Guid(userInfo.Id));
Cache.Remove(key);
}
}
private void UpdateUserGroupRefCache(UserGroupRef r, bool remove)
{
var key = GetRefCacheKey(r.Tenant);
var refs = Cache.Get<UserGroupRefStore>(key);
if (!remove && refs != null)
{
lock (refs)
{
refs[r.CreateKey()] = r;
}
}
else
{
InvalidateCache();
}
}
public static string GetUserPhotoCacheKey(int tenant, Guid userId)
{
return tenant.ToString() + "userphoto" + userId.ToString();
}
public static string GetGroupCacheKey(int tenant)
{
return tenant.ToString() + GROUPS;
}
public static string GetGroupCacheKey(int tenant, Guid groupId)
{
return tenant.ToString() + GROUPS + groupId;
}
public static string GetRefCacheKey(int tenant)
{
return tenant.ToString() + REFS;
}
public static string GetRefCacheKey(int tenant, Guid groupId, UserGroupRefType refType)
{
return tenant.ToString() + groupId + (int)refType;
}
public static string GetUserCacheKey(int tenant)
{
return tenant.ToString() + USERS;
}
public static string GetUserCacheKey(int tenant, Guid userId)
{
return tenant.ToString() + USERS + userId;
var key = GetUserCacheKey(userInfo.Tenant, new Guid(userInfo.Id));
Cache.Remove(key);
}
}
[Scope]
class ConfigureCachedUserService : IConfigureNamedOptions<CachedUserService>
private void UpdateUserGroupRefCache(UserGroupRef r, bool remove)
{
internal IOptionsSnapshot<EFUserService> Service { get; }
internal UserServiceCache UserServiceCache { get; }
internal CoreBaseSettings CoreBaseSettings { get; }
public ConfigureCachedUserService(
IOptionsSnapshot<EFUserService> service,
UserServiceCache userServiceCache,
CoreBaseSettings coreBaseSettings)
var key = GetRefCacheKey(r.Tenant);
var refs = Cache.Get<UserGroupRefStore>(key);
if (!remove && refs != null)
{
Service = service;
UserServiceCache = userServiceCache;
CoreBaseSettings = coreBaseSettings;
lock (refs)
{
refs[r.CreateKey()] = r;
}
}
public void Configure(string name, CachedUserService options)
else
{
Configure(options);
options.Service = Service.Get(name);
}
public void Configure(CachedUserService options)
{
options.Service = Service.Value;
options.CoreBaseSettings = CoreBaseSettings;
options.UserServiceCache = UserServiceCache;
options.Cache = UserServiceCache.Cache;
options.CacheUserInfoItem = UserServiceCache.CacheUserInfoItem;
options.CacheUserPhotoItem = UserServiceCache.CacheUserPhotoItem;
options.CacheGroupCacheItem = UserServiceCache.CacheGroupCacheItem;
options.CacheUserGroupRefItem = UserServiceCache.CacheUserGroupRefItem;
InvalidateCache();
}
}
[Scope]
public class CachedUserService : IUserService, ICachedService
public static string GetUserPhotoCacheKey(int tenant, Guid userId)
{
internal IUserService Service { get; set; }
internal ICache Cache { get; set; }
return tenant.ToString() + "userphoto" + userId.ToString();
}
internal TrustInterval TrustInterval { get; set; }
public static string GetGroupCacheKey(int tenant)
{
return tenant.ToString() + Groups;
}
private TimeSpan CacheExpiration { get; set; }
private TimeSpan PhotoExpiration { get; set; }
internal CoreBaseSettings CoreBaseSettings { get; set; }
internal UserServiceCache UserServiceCache { get; set; }
internal ICacheNotify<UserInfoCacheItem> CacheUserInfoItem { get; set; }
internal ICacheNotify<UserPhotoCacheItem> CacheUserPhotoItem { get; set; }
internal ICacheNotify<GroupCacheItem> CacheGroupCacheItem { get; set; }
internal ICacheNotify<UserGroupRefCacheItem> CacheUserGroupRefItem { get; set; }
public static string GetGroupCacheKey(int tenant, Guid groupId)
{
return tenant.ToString() + Groups + groupId;
}
public CachedUserService()
{
CacheExpiration = TimeSpan.FromMinutes(20);
PhotoExpiration = TimeSpan.FromMinutes(10);
}
public static string GetRefCacheKey(int tenant)
{
return tenant.ToString() + Refs;
}
public static string GetRefCacheKey(int tenant, Guid groupId, UserGroupRefType refType)
{
return tenant.ToString() + groupId + (int)refType;
}
public CachedUserService(
EFUserService service,
CoreBaseSettings coreBaseSettings,
UserServiceCache userServiceCache
) : this()
{
Service = service ?? throw new ArgumentNullException(nameof(service));
CoreBaseSettings = coreBaseSettings;
UserServiceCache = userServiceCache;
Cache = userServiceCache.Cache;
CacheUserInfoItem = userServiceCache.CacheUserInfoItem;
CacheUserPhotoItem = userServiceCache.CacheUserPhotoItem;
CacheGroupCacheItem = userServiceCache.CacheGroupCacheItem;
CacheUserGroupRefItem = userServiceCache.CacheUserGroupRefItem;
}
public static string GetUserCacheKey(int tenant)
{
return tenant.ToString() + Users;
}
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)
{
return Service.GetUsers(tenant, isAdmin, employeeStatus, includeGroups, excludeGroups, activationStatus, text, sortBy, sortOrderAsc, limit, offset, out total, out count);
}
public UserInfo GetUser(int tenant, Guid id)
{
var key = UserServiceCache.GetUserCacheKey(tenant, id);
var user = Cache.Get<UserInfo>(key);
if (user == null)
{
user = Service.GetUser(tenant, id);
if (user != null)
{
Cache.Insert(key, user, CacheExpiration);
}
}
return user;
}
public UserInfo GetUser(int tenant, string email)
{
return Service.GetUser(tenant, email);
}
public UserInfo GetUserByUserName(int tenant, string userName)
{
return Service.GetUserByUserName(tenant, userName);
}
public UserInfo GetUserByPasswordHash(int tenant, string login, string passwordHash)
{
return Service.GetUserByPasswordHash(tenant, login, passwordHash);
}
public IEnumerable<UserInfo> GetUsersAllTenants(IEnumerable<Guid> userIds)
{
return Service.GetUsersAllTenants(userIds);
}
public UserInfo SaveUser(int tenant, UserInfo user)
{
user = Service.SaveUser(tenant, user);
CacheUserInfoItem.Publish(new UserInfoCacheItem { Id = user.ID.ToString(), Tenant = tenant }, ASC.Common.Caching.CacheNotifyAction.Any);
return user;
}
public void RemoveUser(int tenant, Guid id)
{
Service.RemoveUser(tenant, id);
CacheUserInfoItem.Publish(new UserInfoCacheItem { Tenant = tenant, Id = id.ToString() }, ASC.Common.Caching.CacheNotifyAction.Any);
}
public byte[] GetUserPhoto(int tenant, Guid id)
{
var photo = Cache.Get<byte[]>(UserServiceCache.GetUserPhotoCacheKey(tenant, id));
if (photo == null)
{
photo = Service.GetUserPhoto(tenant, id);
Cache.Insert(UserServiceCache.GetUserPhotoCacheKey(tenant, id), photo, PhotoExpiration);
}
return photo;
}
public void SetUserPhoto(int tenant, Guid id, byte[] photo)
{
Service.SetUserPhoto(tenant, id, photo);
CacheUserPhotoItem.Publish(new UserPhotoCacheItem { Key = UserServiceCache.GetUserPhotoCacheKey(tenant, id) }, ASC.Common.Caching.CacheNotifyAction.Remove);
}
public DateTime GetUserPasswordStamp(int tenant, Guid id)
{
return Service.GetUserPasswordStamp(tenant, id);
}
public void SetUserPasswordHash(int tenant, Guid id, string passwordHash)
{
Service.SetUserPasswordHash(tenant, id, passwordHash);
}
public Group GetGroup(int tenant, Guid id)
{
var key = UserServiceCache.GetGroupCacheKey(tenant, id);
var group = Cache.Get<Group>(key);
if (group == null)
{
group = Service.GetGroup(tenant, id);
if (group != null) Cache.Insert(key, group, CacheExpiration);
}
return group;
}
public Group SaveGroup(int tenant, Group group)
{
group = Service.SaveGroup(tenant, group);
CacheGroupCacheItem.Publish(new GroupCacheItem { Id = group.Id.ToString() }, ASC.Common.Caching.CacheNotifyAction.Any);
return group;
}
public void RemoveGroup(int tenant, Guid id)
{
Service.RemoveGroup(tenant, id);
CacheGroupCacheItem.Publish(new GroupCacheItem { Id = id.ToString() }, ASC.Common.Caching.CacheNotifyAction.Any);
}
public IDictionary<string, UserGroupRef> GetUserGroupRefs(int tenant)
{
var key = UserServiceCache.GetRefCacheKey(tenant);
if (!(Cache.Get<UserGroupRefStore>(key) is IDictionary<string, UserGroupRef> refs))
{
refs = Service.GetUserGroupRefs(tenant);
Cache.Insert(key, new UserGroupRefStore(refs), CacheExpiration);
}
return refs;
}
public UserGroupRef GetUserGroupRef(int tenant, Guid groupId, UserGroupRefType refType)
{
var key = UserServiceCache.GetRefCacheKey(tenant, groupId, refType);
var groupRef = Cache.Get<UserGroupRef>(key);
if (groupRef == null)
{
groupRef = Service.GetUserGroupRef(tenant, groupId, refType);
if (groupRef != null) Cache.Insert(key, groupRef, CacheExpiration);
}
return groupRef;
}
public UserGroupRef SaveUserGroupRef(int tenant, UserGroupRef r)
{
r = Service.SaveUserGroupRef(tenant, r);
CacheUserGroupRefItem.Publish(r, ASC.Common.Caching.CacheNotifyAction.InsertOrUpdate);
return r;
}
public void RemoveUserGroupRef(int tenant, Guid userId, Guid groupId, UserGroupRefType refType)
{
Service.RemoveUserGroupRef(tenant, userId, groupId, refType);
var r = new UserGroupRef(userId, groupId, refType) { Tenant = tenant };
CacheUserGroupRefItem.Publish(r, ASC.Common.Caching.CacheNotifyAction.Remove);
}
public IEnumerable<UserInfo> GetUsers(int tenant)
{
var key = UserServiceCache.GetUserCacheKey(tenant);
var users = Cache.Get<IEnumerable<UserInfo>>(key);
if (users == null)
{
users = Service.GetUsers(tenant);
Cache.Insert(key, users, CacheExpiration);
}
return users;
}
public IEnumerable<Group> GetGroups(int tenant)
{
var key = UserServiceCache.GetGroupCacheKey(tenant);
var groups = Cache.Get<IEnumerable<Group>>(key);
if (groups == null)
{
groups = Service.GetGroups(tenant);
Cache.Insert(key, groups, CacheExpiration);
}
return groups;
}
public void InvalidateCache()
{
UserServiceCache.InvalidateCache();
}
public UserInfo GetUser(int tenant, Guid id, Expression<Func<User, UserInfo>> exp)
{
if (exp == null) return GetUser(tenant, id);
return Service.GetUser(tenant, id, exp);
}
public static string GetUserCacheKey(int tenant, Guid userId)
{
return tenant.ToString() + Users + userId;
}
}
[Scope]
class ConfigureCachedUserService : IConfigureNamedOptions<CachedUserService>
{
internal readonly IOptionsSnapshot<EFUserService> Service;
internal readonly UserServiceCache UserServiceCache;
internal readonly CoreBaseSettings CoreBaseSettings;
public ConfigureCachedUserService(
IOptionsSnapshot<EFUserService> service,
UserServiceCache userServiceCache,
CoreBaseSettings coreBaseSettings)
{
Service = service;
UserServiceCache = userServiceCache;
CoreBaseSettings = coreBaseSettings;
}
public void Configure(string name, CachedUserService options)
{
Configure(options);
options.Service = Service.Get(name);
}
public void Configure(CachedUserService options)
{
options.Service = Service.Value;
options.CoreBaseSettings = CoreBaseSettings;
options.UserServiceCache = UserServiceCache;
options.Cache = UserServiceCache.Cache;
options.CacheUserInfoItem = UserServiceCache.CacheUserInfoItem;
options.CacheUserPhotoItem = UserServiceCache.CacheUserPhotoItem;
options.CacheGroupCacheItem = UserServiceCache.CacheGroupCacheItem;
options.CacheUserGroupRefItem = UserServiceCache.CacheUserGroupRefItem;
}
}
[Scope]
public class CachedUserService : IUserService, ICachedService
{
internal IUserService Service;
internal ICache Cache;
internal TrustInterval TrustInterval;
private TimeSpan _cacheExpiration;
private TimeSpan _photoExpiration;
internal CoreBaseSettings CoreBaseSettings;
internal UserServiceCache UserServiceCache;
internal ICacheNotify<UserInfoCacheItem> CacheUserInfoItem;
internal ICacheNotify<UserPhotoCacheItem> CacheUserPhotoItem;
internal ICacheNotify<GroupCacheItem> CacheGroupCacheItem;
internal ICacheNotify<UserGroupRefCacheItem> CacheUserGroupRefItem;
public CachedUserService()
{
_cacheExpiration = TimeSpan.FromMinutes(20);
_photoExpiration = TimeSpan.FromMinutes(10);
}
public CachedUserService(
EFUserService service,
CoreBaseSettings coreBaseSettings,
UserServiceCache userServiceCache
) : this()
{
Service = service ?? throw new ArgumentNullException(nameof(service));
CoreBaseSettings = coreBaseSettings;
UserServiceCache = userServiceCache;
Cache = userServiceCache.Cache;
CacheUserInfoItem = userServiceCache.CacheUserInfoItem;
CacheUserPhotoItem = userServiceCache.CacheUserPhotoItem;
CacheGroupCacheItem = userServiceCache.CacheGroupCacheItem;
CacheUserGroupRefItem = userServiceCache.CacheUserGroupRefItem;
}
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)
{
return Service.GetUsers(tenant, isAdmin, employeeStatus, includeGroups, excludeGroups, activationStatus, text, sortBy, sortOrderAsc, limit, offset, out total, out count);
}
public UserInfo GetUser(int tenant, Guid id)
{
var key = UserServiceCache.GetUserCacheKey(tenant, id);
var user = Cache.Get<UserInfo>(key);
if (user == null)
{
user = Service.GetUser(tenant, id);
if (user != null)
{
Cache.Insert(key, user, _cacheExpiration);
}
}
return user;
}
public UserInfo GetUser(int tenant, string email)
{
return Service.GetUser(tenant, email);
}
public UserInfo GetUserByUserName(int tenant, string userName)
{
return Service.GetUserByUserName(tenant, userName);
}
public UserInfo GetUserByPasswordHash(int tenant, string login, string passwordHash)
{
return Service.GetUserByPasswordHash(tenant, login, passwordHash);
}
public IEnumerable<UserInfo> GetUsersAllTenants(IEnumerable<Guid> userIds)
{
return Service.GetUsersAllTenants(userIds);
}
public UserInfo SaveUser(int tenant, UserInfo user)
{
user = Service.SaveUser(tenant, user);
CacheUserInfoItem.Publish(new UserInfoCacheItem { Id = user.Id.ToString(), Tenant = tenant }, CacheNotifyAction.Any);
return user;
}
public void RemoveUser(int tenant, Guid id)
{
Service.RemoveUser(tenant, id);
CacheUserInfoItem.Publish(new UserInfoCacheItem { Tenant = tenant, Id = id.ToString() }, CacheNotifyAction.Any);
}
public byte[] GetUserPhoto(int tenant, Guid id)
{
var photo = Cache.Get<byte[]>(UserServiceCache.GetUserPhotoCacheKey(tenant, id));
if (photo == null)
{
photo = Service.GetUserPhoto(tenant, id);
Cache.Insert(UserServiceCache.GetUserPhotoCacheKey(tenant, id), photo, _photoExpiration);
}
return photo;
}
public void SetUserPhoto(int tenant, Guid id, byte[] photo)
{
Service.SetUserPhoto(tenant, id, photo);
CacheUserPhotoItem.Publish(new UserPhotoCacheItem { Key = UserServiceCache.GetUserPhotoCacheKey(tenant, id) }, ASC.Common.Caching.CacheNotifyAction.Remove);
}
public DateTime GetUserPasswordStamp(int tenant, Guid id)
{
return Service.GetUserPasswordStamp(tenant, id);
}
public void SetUserPasswordHash(int tenant, Guid id, string passwordHash)
{
Service.SetUserPasswordHash(tenant, id, passwordHash);
}
public Group GetGroup(int tenant, Guid id)
{
var key = UserServiceCache.GetGroupCacheKey(tenant, id);
var group = Cache.Get<Group>(key);
if (group == null)
{
group = Service.GetGroup(tenant, id);
if (group != null) Cache.Insert(key, group, _cacheExpiration);
}
return group;
}
public Group SaveGroup(int tenant, Group group)
{
group = Service.SaveGroup(tenant, group);
CacheGroupCacheItem.Publish(new GroupCacheItem { Id = group.Id.ToString() }, CacheNotifyAction.Any);
return group;
}
public void RemoveGroup(int tenant, Guid id)
{
Service.RemoveGroup(tenant, id);
CacheGroupCacheItem.Publish(new GroupCacheItem { Id = id.ToString() }, CacheNotifyAction.Any);
}
public IDictionary<string, UserGroupRef> GetUserGroupRefs(int tenant)
{
var key = UserServiceCache.GetRefCacheKey(tenant);
if (!(Cache.Get<UserGroupRefStore>(key) is IDictionary<string, UserGroupRef> refs))
{
refs = Service.GetUserGroupRefs(tenant);
Cache.Insert(key, new UserGroupRefStore(refs), _cacheExpiration);
}
return refs;
}
public UserGroupRef GetUserGroupRef(int tenant, Guid groupId, UserGroupRefType refType)
{
var key = UserServiceCache.GetRefCacheKey(tenant, groupId, refType);
var groupRef = Cache.Get<UserGroupRef>(key);
if (groupRef == null)
{
groupRef = Service.GetUserGroupRef(tenant, groupId, refType);
if (groupRef != null)
{
Cache.Insert(key, groupRef, _cacheExpiration);
}
}
return groupRef;
}
public UserGroupRef SaveUserGroupRef(int tenant, UserGroupRef r)
{
r = Service.SaveUserGroupRef(tenant, r);
CacheUserGroupRefItem.Publish(r, CacheNotifyAction.InsertOrUpdate);
return r;
}
public void RemoveUserGroupRef(int tenant, Guid userId, Guid groupId, UserGroupRefType refType)
{
Service.RemoveUserGroupRef(tenant, userId, groupId, refType);
var r = new UserGroupRef(userId, groupId, refType) { Tenant = tenant };
CacheUserGroupRefItem.Publish(r, CacheNotifyAction.Remove);
}
public IEnumerable<UserInfo> GetUsers(int tenant)
{
var key = UserServiceCache.GetUserCacheKey(tenant);
var users = Cache.Get<IEnumerable<UserInfo>>(key);
if (users == null)
{
users = Service.GetUsers(tenant);
Cache.Insert(key, users, _cacheExpiration);
}
return users;
}
public IEnumerable<Group> GetGroups(int tenant)
{
var key = UserServiceCache.GetGroupCacheKey(tenant);
var groups = Cache.Get<IEnumerable<Group>>(key);
if (groups == null)
{
groups = Service.GetGroups(tenant);
Cache.Insert(key, groups, _cacheExpiration);
}
return groups;
}
public void InvalidateCache()
{
UserServiceCache.InvalidateCache();
}
public UserInfo GetUser(int tenant, Guid id, Expression<Func<User, UserInfo>> exp)
{
if (exp == null)
{
return GetUser(tenant, id);
}
return Service.GetUser(tenant, id, exp);
}
}

View File

@ -24,10 +24,9 @@
*/
namespace ASC.Core.Caching
namespace ASC.Core.Caching;
public interface ICachedService
{
public interface ICachedService
{
void InvalidateCache();
}
void InvalidateCache();
}

View File

@ -23,34 +23,22 @@
*
*/
namespace ASC.Core.Caching
namespace ASC.Core.Caching;
public class TrustInterval
{
public class TrustInterval
private TimeSpan _interval;
public DateTime StartTime { get; private set; }
public bool Expired => _interval == default || _interval < (DateTime.UtcNow - StartTime).Duration();
public void Start(TimeSpan interval)
{
private TimeSpan interval;
_interval = interval;
StartTime = DateTime.UtcNow;
}
public DateTime StartTime
{
get;
private set;
}
public bool Expired
{
get { return interval == default || interval < (DateTime.UtcNow - StartTime).Duration(); }
}
public void Start(TimeSpan interval)
{
this.interval = interval;
StartTime = DateTime.UtcNow;
}
public void Expire()
{
interval = default;
}
public void Expire()
{
_interval = default;
}
}

View File

@ -23,130 +23,117 @@
*
*/
namespace ASC.Core.Caching
namespace ASC.Core.Caching;
class UserGroupRefStore : IDictionary<string, UserGroupRef>
{
class UserGroupRefStore : IDictionary<string, UserGroupRef>
private readonly IDictionary<string, UserGroupRef> _refs;
private ILookup<Guid, UserGroupRef> _index;
private bool _changed;
public UserGroupRefStore(IDictionary<string, UserGroupRef> refs)
{
private readonly IDictionary<string, UserGroupRef> refs;
private ILookup<Guid, UserGroupRef> index;
private bool changed;
_refs = refs;
_changed = true;
}
public UserGroupRefStore(IDictionary<string, UserGroupRef> refs)
public void Add(string key, UserGroupRef value)
{
_refs.Add(key, value);
RebuildIndex();
}
public bool ContainsKey(string key)
{
return _refs.ContainsKey(key);
}
public ICollection<string> Keys => _refs.Keys;
public bool Remove(string key)
{
var result = _refs.Remove(key);
RebuildIndex();
return result;
}
public bool TryGetValue(string key, out UserGroupRef value)
{
return _refs.TryGetValue(key, out value);
}
public ICollection<UserGroupRef> Values => _refs.Values;
public UserGroupRef this[string key]
{
get => _refs[key];
set
{
this.refs = refs;
changed = true;
}
public void Add(string key, UserGroupRef value)
{
refs.Add(key, value);
_refs[key] = value;
RebuildIndex();
}
public bool ContainsKey(string key)
{
return refs.ContainsKey(key);
}
public ICollection<string> Keys
{
get { return refs.Keys; }
}
public bool Remove(string key)
{
var result = refs.Remove(key);
RebuildIndex();
return result;
}
public bool TryGetValue(string key, out UserGroupRef value)
{
return refs.TryGetValue(key, out value);
}
public ICollection<UserGroupRef> Values
{
get { return refs.Values; }
}
public UserGroupRef this[string key]
{
get
{
return refs[key];
}
set
{
refs[key] = value;
RebuildIndex();
}
}
public void Add(KeyValuePair<string, UserGroupRef> item)
{
refs.Add(item);
RebuildIndex();
}
public void Clear()
{
refs.Clear();
RebuildIndex();
}
public bool Contains(KeyValuePair<string, UserGroupRef> item)
{
return refs.Contains(item);
}
public void CopyTo(KeyValuePair<string, UserGroupRef>[] array, int arrayIndex)
{
refs.CopyTo(array, arrayIndex);
}
public int Count
{
get { return refs.Count; }
}
public bool IsReadOnly
{
get { return refs.IsReadOnly; }
}
public bool Remove(KeyValuePair<string, UserGroupRef> item)
{
var result = refs.Remove(item);
RebuildIndex();
return result;
}
public IEnumerator<KeyValuePair<string, UserGroupRef>> GetEnumerator()
{
return refs.GetEnumerator();
}
IEnumerator IEnumerable.GetEnumerator()
{
return refs.GetEnumerator();
}
public IEnumerable<UserGroupRef> GetRefsByUser(Guid userId)
{
if (changed)
{
index = refs.Values.ToLookup(r => r.UserId);
changed = false;
}
return index[userId];
}
private void RebuildIndex()
{
changed = true;
}
}
public void Add(KeyValuePair<string, UserGroupRef> item)
{
_refs.Add(item);
RebuildIndex();
}
public void Clear()
{
_refs.Clear();
RebuildIndex();
}
public bool Contains(KeyValuePair<string, UserGroupRef> item)
{
return _refs.Contains(item);
}
public void CopyTo(KeyValuePair<string, UserGroupRef>[] array, int arrayIndex)
{
_refs.CopyTo(array, arrayIndex);
}
public int Count => _refs.Count;
public bool IsReadOnly => _refs.IsReadOnly;
public bool Remove(KeyValuePair<string, UserGroupRef> item)
{
var result = _refs.Remove(item);
RebuildIndex();
return result;
}
public IEnumerator<KeyValuePair<string, UserGroupRef>> GetEnumerator()
{
return _refs.GetEnumerator();
}
IEnumerator IEnumerable.GetEnumerator()
{
return _refs.GetEnumerator();
}
public IEnumerable<UserGroupRef> GetRefsByUser(Guid userId)
{
if (_changed)
{
_index = _refs.Values.ToLookup(r => r.UserId);
_changed = false;
}
return _index[userId];
}
private void RebuildIndex()
{
_changed = true;
}
}

View File

@ -24,13 +24,12 @@
*/
namespace ASC.Core.Common.Configuration
namespace ASC.Core.Common.Configuration;
public class AmazonS3Settings
{
public class AmazonS3Settings
{
public string AccessKeyId { get; set; }
public string SecretAccessKey { get; set; }
public string Bucket { get; set; }
public string Region { get; set; }
}
public string AccessKeyId { get; set; }
public string SecretAccessKey { get; set; }
public string Bucket { get; set; }
public string Region { get; set; }
}

View File

@ -23,89 +23,88 @@
*
*/
namespace ASC.Core.Configuration
{
public class AmiPublicDnsSyncService : IServiceController
namespace ASC.Core.Configuration;
public class AmiPublicDnsSyncService : IServiceController
{
public static IServiceProvider ServiceProvider { get; set; }
public void Start()
{
public static IServiceProvider ServiceProvider { get; set; }
public void Start()
{
Synchronize();
}
public void Stop()
{
}
public static void Synchronize()
Synchronize();
}
public void Stop() { }
public static void Synchronize()
{
using var scope = ServiceProvider.CreateScope();
var scopeClass = scope.ServiceProvider.GetService<AmiPublicDnsSyncServiceScope>();
var (tenantManager, coreBaseSettings, clientFactory) = scopeClass;
if (coreBaseSettings.Standalone)
{
using var scope = ServiceProvider.CreateScope();
var scopeClass = scope.ServiceProvider.GetService<AmiPublicDnsSyncServiceScope>();
var (tenantManager, coreBaseSettings, clientFactory) = scopeClass;
if (coreBaseSettings.Standalone)
{
var tenants = tenantManager.GetTenants(false).Where(t => MappedDomainNotSettedByUser(t.MappedDomain));
if (tenants.Any())
{
var dnsname = GetAmiPublicDnsName(clientFactory);
foreach (var tenant in tenants.Where(t => !string.IsNullOrEmpty(dnsname) && t.MappedDomain != dnsname))
{
tenant.MappedDomain = dnsname;
tenantManager.SaveTenant(tenant);
}
}
}
}
private static bool MappedDomainNotSettedByUser(string domain)
{
return string.IsNullOrEmpty(domain) || Regex.IsMatch(domain, "^ec2.+\\.compute\\.amazonaws\\.com$", RegexOptions.CultureInvariant | RegexOptions.IgnoreCase);
}
private static string GetAmiPublicDnsName(IHttpClientFactory clientFactory)
{
try
var tenants = tenantManager.GetTenants(false).Where(t => MappedDomainNotSettedByUser(t.MappedDomain));
if (tenants.Any())
{
var request = new HttpRequestMessage();
request.RequestUri = new Uri("http://169.254.169.254/latest/meta-data/public-hostname");
request.Method = HttpMethod.Get;
var dnsname = GetAmiPublicDnsName(clientFactory);
foreach (var tenant in tenants.Where(t => !string.IsNullOrEmpty(dnsname) && t.MappedDomain != dnsname))
{
tenant.MappedDomain = dnsname;
tenantManager.SaveTenant(tenant);
}
}
}
}
var httpClient = clientFactory.CreateClient();
httpClient.Timeout = TimeSpan.FromMilliseconds(5000);
using var responce = httpClient.Send(request);
using var stream = responce.Content.ReadAsStream();
using var reader = new StreamReader(stream);
return reader.ReadToEnd();
}
catch (HttpRequestException ex)
{
if (ex.StatusCode == HttpStatusCode.NotFound || ex.StatusCode == HttpStatusCode.Conflict)
{
throw;
}
}
return null;
}
}
public class AmiPublicDnsSyncServiceScope
private static bool MappedDomainNotSettedByUser(string domain)
{
private TenantManager TenantManager { get; }
private CoreBaseSettings CoreBaseSettings { get; }
private IHttpClientFactory ClientFactory { get; }
return string.IsNullOrEmpty(domain) || Regex.IsMatch(domain, "^ec2.+\\.compute\\.amazonaws\\.com$", RegexOptions.CultureInvariant | RegexOptions.IgnoreCase);
}
public AmiPublicDnsSyncServiceScope(TenantManager tenantManager, CoreBaseSettings coreBaseSettings, IHttpClientFactory clientFactory)
private static string GetAmiPublicDnsName(IHttpClientFactory clientFactory)
{
try
{
TenantManager = tenantManager;
CoreBaseSettings = coreBaseSettings;
ClientFactory = clientFactory;
var request = new HttpRequestMessage();
request.RequestUri = new Uri("http://169.254.169.254/latest/meta-data/public-hostname");
request.Method = HttpMethod.Get;
var httpClient = clientFactory.CreateClient();
httpClient.Timeout = TimeSpan.FromMilliseconds(5000);
using var responce = httpClient.Send(request);
using var stream = responce.Content.ReadAsStream();
using var reader = new StreamReader(stream);
return reader.ReadToEnd();
}
catch (HttpRequestException ex)
{
if (ex.StatusCode == HttpStatusCode.NotFound || ex.StatusCode == HttpStatusCode.Conflict)
{
throw;
}
}
public void Deconstruct(out TenantManager tenantManager, out CoreBaseSettings coreBaseSettings, out IHttpClientFactory clientFactory)
{
(tenantManager, coreBaseSettings, clientFactory) = (TenantManager, CoreBaseSettings, ClientFactory);
}
}
return null;
}
}
public class AmiPublicDnsSyncServiceScope
{
private TenantManager _tenantManager;
private CoreBaseSettings _coreBaseSettings;
private IHttpClientFactory _clientFactory;
public AmiPublicDnsSyncServiceScope(TenantManager tenantManager, CoreBaseSettings coreBaseSettings, IHttpClientFactory clientFactory)
{
_tenantManager = tenantManager;
_coreBaseSettings = coreBaseSettings;
_clientFactory = clientFactory;
}
public void Deconstruct(out TenantManager tenantManager, out CoreBaseSettings coreBaseSettings, out IHttpClientFactory clientFactory)
{
(tenantManager, coreBaseSettings, clientFactory) = (_tenantManager, _coreBaseSettings, _clientFactory);
}
}

View File

@ -23,19 +23,18 @@
*
*/
namespace ASC.Core.Configuration
{
//todo: remove
//class ConnectionStringNameTypeConverter : TypeConverter
//{
// public override bool CanConvertFrom(ITypeDescriptorContext context, Type sourceType)
// {
// return sourceType == typeof(string);
// }
// public override object ConvertFrom(ITypeDescriptorContext context, CultureInfo culture, object value)
// {
// return DbRegistry.GetConnectionString((string)value);
// }
//}
}
namespace ASC.Core.Configuration;
//todo: remove
//class ConnectionStringNameTypeConverter : TypeConverter
//{
// public override bool CanConvertFrom(ITypeDescriptorContext context, Type sourceType)
// {
// return sourceType == typeof(string);
// }
// public override object ConvertFrom(ITypeDescriptorContext context, CultureInfo culture, object value)
// {
// return DbRegistry.GetConnectionString((string)value);
// }
//}

View File

@ -23,26 +23,17 @@
*
*/
namespace ASC.Core.Configuration
{
public static class Constants
{
public static readonly string NotifyEMailSenderSysName = "email.sender";
public static readonly string NotifyMessengerSenderSysName = "messanger.sender";
public static readonly string NotifyPushSenderSysName = "push.sender";
namespace ASC.Core.Configuration;
public static readonly string NotifyTelegramSenderSysName = "telegram.sender";
public static readonly ISystemAccount CoreSystem = new SystemAccount(new Guid("A37EE56E-3302-4a7b-B67E-DDBEA64CD032"), "asc system", true);
public static readonly ISystemAccount Guest = new SystemAccount(new Guid("712D9EC3-5D2B-4b13-824F-71F00191DCCA"), "guest", false);
public static readonly IPrincipal Anonymous = new GenericPrincipal(Guest, new[] { Role.Everyone });
public static readonly ISystemAccount[] SystemAccounts = new[] { CoreSystem, Guest };
public static readonly int DefaultTrialPeriod = 30;
}
}
public static class Constants
{
public static readonly string NotifyEMailSenderSysName = "email.sender";
public static readonly string NotifyMessengerSenderSysName = "messanger.sender";
public static readonly string NotifyPushSenderSysName = "push.sender";
public static readonly string NotifyTelegramSenderSysName = "telegram.sender";
public static readonly ISystemAccount CoreSystem = new SystemAccount(new Guid("A37EE56E-3302-4a7b-B67E-DDBEA64CD032"), "asc system", true);
public static readonly ISystemAccount Guest = new SystemAccount(new Guid("712D9EC3-5D2B-4b13-824F-71F00191DCCA"), "guest", false);
public static readonly IPrincipal Anonymous = new GenericPrincipal(Guest, new[] { Role.Everyone });
public static readonly ISystemAccount[] SystemAccounts = new[] { CoreSystem, Guest };
public static readonly int DefaultTrialPeriod = 30;
}

View File

@ -23,397 +23,375 @@
*
*/
namespace ASC.Core.Common.Configuration
{
public class Consumer : IDictionary<string, string>
{
public bool CanSet { get; private set; }
public int Order { get; private set; }
public string Name { get; private set; }
protected readonly Dictionary<string, string> Props;
public IEnumerable<string> ManagedKeys
{
get { return Props.Select(r => r.Key); }
}
protected readonly Dictionary<string, string> Additional;
public virtual IEnumerable<string> AdditionalKeys
{
get { return Additional.Select(r => r.Key); }
}
public ICollection<string> Keys { get { return AllProps.Keys; } }
public ICollection<string> Values { get { return AllProps.Values; } }
private Dictionary<string, string> AllProps
{
get
{
var result = Props.ToDictionary(item => item.Key, item => item.Value);
foreach (var item in Additional.Where(item => !result.ContainsKey(item.Key)))
{
result.Add(item.Key, item.Value);
}
return result;
}
}
private readonly bool OnlyDefault;
internal protected TenantManager TenantManager { get; set; }
internal protected CoreBaseSettings CoreBaseSettings { get; set; }
internal protected CoreSettings CoreSettings { get; set; }
internal protected ConsumerFactory ConsumerFactory { get; set; }
internal protected IConfiguration Configuration { get; }
internal protected ICacheNotify<ConsumerCacheItem> Cache { get; }
public bool IsSet
{
get { return Props.Count > 0 && !Props.All(r => string.IsNullOrEmpty(this[r.Key])); }
}
static Consumer()
{
}
public Consumer()
{
Props = new Dictionary<string, string>();
Additional = new Dictionary<string, string>();
}
public Consumer(
TenantManager tenantManager,
CoreBaseSettings coreBaseSettings,
CoreSettings coreSettings,
IConfiguration configuration,
ICacheNotify<ConsumerCacheItem> cache,
ConsumerFactory consumerFactory) : this()
{
TenantManager = tenantManager;
CoreBaseSettings = coreBaseSettings;
CoreSettings = coreSettings;
Configuration = configuration;
Cache = cache;
ConsumerFactory = consumerFactory;
OnlyDefault = configuration["core:default-consumers"] == "true";
Name = "";
Order = int.MaxValue;
}
public Consumer(
TenantManager tenantManager,
CoreBaseSettings coreBaseSettings,
CoreSettings coreSettings,
IConfiguration configuration,
ICacheNotify<ConsumerCacheItem> cache,
ConsumerFactory consumerFactory,
string name, int order, Dictionary<string, string> additional)
: this(tenantManager, coreBaseSettings, coreSettings, configuration, cache, consumerFactory)
{
Name = name;
Order = order;
Props = new Dictionary<string, string>();
Additional = additional;
}
public Consumer(
TenantManager tenantManager,
CoreBaseSettings coreBaseSettings,
CoreSettings coreSettings,
IConfiguration configuration,
ICacheNotify<ConsumerCacheItem> cache,
ConsumerFactory consumerFactory,
string name, int order, Dictionary<string, string> props, Dictionary<string, string> additional = null)
: this(tenantManager, coreBaseSettings, coreSettings, configuration, cache, consumerFactory)
{
Name = name;
Order = order;
Props = props ?? new Dictionary<string, string>();
Additional = additional ?? new Dictionary<string, string>();
if (props != null && props.Count > 0)
{
CanSet = props.All(r => string.IsNullOrEmpty(r.Value));
}
}
public IEnumerator<KeyValuePair<string, string>> GetEnumerator()
{
return AllProps.GetEnumerator();
}
IEnumerator IEnumerable.GetEnumerator()
{
return GetEnumerator();
}
public void Add(KeyValuePair<string, string> item)
{
}
public void Clear()
{
if (!CanSet)
{
throw new NotSupportedException("Key for read only. Consumer " + Name);
}
foreach (var providerProp in Props)
{
this[providerProp.Key] = null;
}
Cache.Publish(new ConsumerCacheItem() { Name = this.Name }, ASC.Common.Caching.CacheNotifyAction.Remove);
}
public bool Contains(KeyValuePair<string, string> item)
{
return AllProps.Contains(item);
}
public void CopyTo(KeyValuePair<string, string>[] array, int arrayIndex)
{
}
public bool Remove(KeyValuePair<string, string> item)
{
return AllProps.Remove(item.Key);
}
public int Count { get { return AllProps.Count; } }
public bool IsReadOnly { get { return true; } }
public bool ContainsKey(string key)
{
return AllProps.ContainsKey(key);
}
public void Add(string key, string value)
{
}
public bool Remove(string key)
{
return false;
}
public bool TryGetValue(string key, out string value)
{
return AllProps.TryGetValue(key, out value);
}
public string this[string key]
{
get { return Get(key); }
set { Set(key, value); }
}
private string Get(string name)
{
string value = null;
if (!OnlyDefault && CanSet)
{
var tenant = CoreBaseSettings.Standalone
? Tenant.DEFAULT_TENANT
: TenantManager.GetCurrentTenant().TenantId;
value = CoreSettings.GetSetting(GetSettingsKey(name), tenant);
}
if (string.IsNullOrEmpty(value))
{
AllProps.TryGetValue(name, out value);
}
return value;
}
private void Set(string name, string value)
{
if (!CanSet)
{
throw new NotSupportedException("Key for read only. Key " + name);
}
if (!ManagedKeys.Contains(name))
{
if (Additional.ContainsKey(name))
{
Additional[name] = value;
}
else
{
Additional.Add(name, value);
}
return;
}
var tenant = CoreBaseSettings.Standalone
? Tenant.DEFAULT_TENANT
: TenantManager.GetCurrentTenant().TenantId;
CoreSettings.SaveSetting(GetSettingsKey(name), value, tenant);
}
protected virtual string GetSettingsKey(string name)
{
return "AuthKey_" + name;
}
}
public class DataStoreConsumer : Consumer, ICloneable
{
public Type HandlerType { get; private set; }
public DataStoreConsumer Cdn { get; private set; }
public const string HandlerTypeKey = "handlerType";
public const string CdnKey = "cdn";
public DataStoreConsumer() : base()
{
}
public DataStoreConsumer(
TenantManager tenantManager,
CoreBaseSettings coreBaseSettings,
CoreSettings coreSettings,
IConfiguration configuration,
ICacheNotify<ConsumerCacheItem> cache,
ConsumerFactory consumerFactory)
: base(tenantManager, coreBaseSettings, coreSettings, configuration, cache, consumerFactory)
{
}
public DataStoreConsumer(
TenantManager tenantManager,
CoreBaseSettings coreBaseSettings,
CoreSettings coreSettings,
IConfiguration configuration,
ICacheNotify<ConsumerCacheItem> cache,
ConsumerFactory consumerFactory,
string name, int order, Dictionary<string, string> additional)
: base(tenantManager, coreBaseSettings, coreSettings, configuration, cache, consumerFactory, name, order, additional)
{
Init(additional);
}
public DataStoreConsumer(
TenantManager tenantManager,
CoreBaseSettings coreBaseSettings,
CoreSettings coreSettings,
IConfiguration configuration,
ICacheNotify<ConsumerCacheItem> cache,
ConsumerFactory consumerFactory,
string name, int order, Dictionary<string, string> props, Dictionary<string, string> additional)
: base(tenantManager, coreBaseSettings, coreSettings, configuration, cache, consumerFactory, name, order, props, additional)
{
Init(additional);
}
public override IEnumerable<string> AdditionalKeys
{
get { return base.AdditionalKeys.Where(r => r != HandlerTypeKey && r != "cdn"); }
}
protected override string GetSettingsKey(string name)
{
return base.GetSettingsKey(Name + name);
}
private void Init(IReadOnlyDictionary<string, string> additional)
{
if (additional == null || !additional.ContainsKey(HandlerTypeKey))
throw new ArgumentException(HandlerTypeKey);
HandlerType = Type.GetType(additional[HandlerTypeKey]);
if (additional.TryGetValue(CdnKey, out var value))
{
Cdn = GetCdn(value);
}
}
private DataStoreConsumer GetCdn(string cdn)
{
var fromConfig = ConsumerFactory.GetByKey<Consumer>(cdn);
if (string.IsNullOrEmpty(fromConfig.Name)) return null;
var props = ManagedKeys.ToDictionary(prop => prop, prop => this[prop]);
var additional = fromConfig.AdditionalKeys.ToDictionary(prop => prop, prop => fromConfig[prop]);
additional.Add(HandlerTypeKey, HandlerType.AssemblyQualifiedName);
return new DataStoreConsumer(fromConfig.TenantManager, fromConfig.CoreBaseSettings, fromConfig.CoreSettings, fromConfig.Configuration, fromConfig.Cache, fromConfig.ConsumerFactory, fromConfig.Name, fromConfig.Order, props, additional);
}
public object Clone()
{
return new DataStoreConsumer(TenantManager, CoreBaseSettings, CoreSettings, Configuration, Cache, ConsumerFactory, Name, Order, Props.ToDictionary(r => r.Key, r => r.Value), Additional.ToDictionary(r => r.Key, r => r.Value));
}
}
namespace ASC.Core.Common.Configuration;
[Scope]
public class ConsumerFactory : IDisposable
{
public ILifetimeScope Builder { get; set; }
public class Consumer : IDictionary<string, string>
{
public bool CanSet { get; private set; }
public int Order { get; private set; }
public string Name { get; private set; }
protected readonly Dictionary<string, string> Props;
public IEnumerable<string> ManagedKeys => Props.Select(r => r.Key);
public ConsumerFactory(IContainer builder)
{
Builder = builder.BeginLifetimeScope();
}
protected readonly Dictionary<string, string> Additional;
public virtual IEnumerable<string> AdditionalKeys => Additional.Select(r => r.Key);
public ConsumerFactory(ILifetimeScope builder)
{
Builder = builder;
}
public Consumer GetByKey(string key)
{
if (Builder.TryResolveKeyed(key, typeof(Consumer), out var result))
{
return (Consumer)result;
}
return new Consumer();
}
public T GetByKey<T>(string key) where T : Consumer, new()
{
if (Builder.TryResolveKeyed(key, typeof(T), out var result))
{
return (T)result;
}
return new T();
}
public T Get<T>() where T : Consumer, new()
{
if (Builder.TryResolve(out T result))
{
return result;
}
return new T();
}
public IEnumerable<T> GetAll<T>() where T : Consumer, new()
{
return Builder.Resolve<IEnumerable<T>>();
}
public ICollection<string> Keys => AllProps.Keys;
public ICollection<string> Values => AllProps.Values;
public void Dispose()
private Dictionary<string, string> AllProps
{
get
{
Builder.Dispose();
var result = Props.ToDictionary(item => item.Key, item => item.Value);
foreach (var item in Additional.Where(item => !result.ContainsKey(item.Key)))
{
result.Add(item.Key, item.Value);
}
return result;
}
}
}
private readonly bool _onlyDefault;
internal protected TenantManager TenantManager;
internal protected CoreBaseSettings CoreBaseSettings;
internal protected CoreSettings CoreSettings;
internal protected ConsumerFactory ConsumerFactory;
internal protected readonly IConfiguration Configuration;
internal protected readonly ICacheNotify<ConsumerCacheItem> Cache;
public bool IsSet => Props.Count > 0 && !Props.All(r => string.IsNullOrEmpty(this[r.Key]));
static Consumer() { }
public Consumer()
{
Props = new Dictionary<string, string>();
Additional = new Dictionary<string, string>();
}
public Consumer(
TenantManager tenantManager,
CoreBaseSettings coreBaseSettings,
CoreSettings coreSettings,
IConfiguration configuration,
ICacheNotify<ConsumerCacheItem> cache,
ConsumerFactory consumerFactory) : this()
{
TenantManager = tenantManager;
CoreBaseSettings = coreBaseSettings;
CoreSettings = coreSettings;
Configuration = configuration;
Cache = cache;
ConsumerFactory = consumerFactory;
_onlyDefault = configuration["core:default-consumers"] == "true";
Name = "";
Order = int.MaxValue;
}
public Consumer(
TenantManager tenantManager,
CoreBaseSettings coreBaseSettings,
CoreSettings coreSettings,
IConfiguration configuration,
ICacheNotify<ConsumerCacheItem> cache,
ConsumerFactory consumerFactory,
string name, int order, Dictionary<string, string> additional)
: this(tenantManager, coreBaseSettings, coreSettings, configuration, cache, consumerFactory)
{
Name = name;
Order = order;
Props = new Dictionary<string, string>();
Additional = additional;
}
public Consumer(
TenantManager tenantManager,
CoreBaseSettings coreBaseSettings,
CoreSettings coreSettings,
IConfiguration configuration,
ICacheNotify<ConsumerCacheItem> cache,
ConsumerFactory consumerFactory,
string name, int order, Dictionary<string, string> props, Dictionary<string, string> additional = null)
: this(tenantManager, coreBaseSettings, coreSettings, configuration, cache, consumerFactory)
{
Name = name;
Order = order;
Props = props ?? new Dictionary<string, string>();
Additional = additional ?? new Dictionary<string, string>();
if (props != null && props.Count > 0)
{
CanSet = props.All(r => string.IsNullOrEmpty(r.Value));
}
}
public IEnumerator<KeyValuePair<string, string>> GetEnumerator()
{
return AllProps.GetEnumerator();
}
IEnumerator IEnumerable.GetEnumerator()
{
return GetEnumerator();
}
public void Add(KeyValuePair<string, string> item) { }
public void Clear()
{
if (!CanSet)
{
throw new NotSupportedException("Key for read only. Consumer " + Name);
}
foreach (var providerProp in Props)
{
this[providerProp.Key] = null;
}
Cache.Publish(new ConsumerCacheItem() { Name = this.Name }, CacheNotifyAction.Remove);
}
public bool Contains(KeyValuePair<string, string> item)
{
return AllProps.Contains(item);
}
public void CopyTo(KeyValuePair<string, string>[] array, int arrayIndex) { }
public bool Remove(KeyValuePair<string, string> item)
{
return AllProps.Remove(item.Key);
}
public int Count => AllProps.Count;
public bool IsReadOnly => true;
public bool ContainsKey(string key)
{
return AllProps.ContainsKey(key);
}
public void Add(string key, string value) { }
public bool Remove(string key)
{
return false;
}
public bool TryGetValue(string key, out string value)
{
return AllProps.TryGetValue(key, out value);
}
public string this[string key]
{
get => Get(key);
set => Set(key, value);
}
private string Get(string name)
{
string value = null;
if (!_onlyDefault && CanSet)
{
var tenant = CoreBaseSettings.Standalone
? Tenant.DefaultTenant
: TenantManager.GetCurrentTenant().Id;
value = CoreSettings.GetSetting(GetSettingsKey(name), tenant);
}
if (string.IsNullOrEmpty(value))
{
AllProps.TryGetValue(name, out value);
}
return value;
}
private void Set(string name, string value)
{
if (!CanSet)
{
throw new NotSupportedException("Key for read only. Key " + name);
}
if (!ManagedKeys.Contains(name))
{
if (Additional.ContainsKey(name))
{
Additional[name] = value;
}
else
{
Additional.Add(name, value);
}
return;
}
var tenant = CoreBaseSettings.Standalone
? Tenant.DefaultTenant
: TenantManager.GetCurrentTenant().Id;
CoreSettings.SaveSetting(GetSettingsKey(name), value, tenant);
}
protected virtual string GetSettingsKey(string name)
{
return "AuthKey_" + name;
}
}
public class DataStoreConsumer : Consumer, ICloneable
{
public Type HandlerType { get; private set; }
public DataStoreConsumer Cdn { get; private set; }
public const string HandlerTypeKey = "handlerType";
public const string CdnKey = "cdn";
public DataStoreConsumer() : base() { }
public DataStoreConsumer(
TenantManager tenantManager,
CoreBaseSettings coreBaseSettings,
CoreSettings coreSettings,
IConfiguration configuration,
ICacheNotify<ConsumerCacheItem> cache,
ConsumerFactory consumerFactory)
: base(tenantManager, coreBaseSettings, coreSettings, configuration, cache, consumerFactory)
{
}
public DataStoreConsumer(
TenantManager tenantManager,
CoreBaseSettings coreBaseSettings,
CoreSettings coreSettings,
IConfiguration configuration,
ICacheNotify<ConsumerCacheItem> cache,
ConsumerFactory consumerFactory,
string name, int order, Dictionary<string, string> additional)
: base(tenantManager, coreBaseSettings, coreSettings, configuration, cache, consumerFactory, name, order, additional)
{
Init(additional);
}
public DataStoreConsumer(
TenantManager tenantManager,
CoreBaseSettings coreBaseSettings,
CoreSettings coreSettings,
IConfiguration configuration,
ICacheNotify<ConsumerCacheItem> cache,
ConsumerFactory consumerFactory,
string name, int order, Dictionary<string, string> props, Dictionary<string, string> additional)
: base(tenantManager, coreBaseSettings, coreSettings, configuration, cache, consumerFactory, name, order, props, additional)
{
Init(additional);
}
public override IEnumerable<string> AdditionalKeys => base.AdditionalKeys.Where(r => r != HandlerTypeKey && r != "cdn");
protected override string GetSettingsKey(string name)
{
return base.GetSettingsKey(Name + name);
}
private void Init(IReadOnlyDictionary<string, string> additional)
{
if (additional == null || !additional.ContainsKey(HandlerTypeKey))
{
throw new ArgumentException(HandlerTypeKey);
}
HandlerType = Type.GetType(additional[HandlerTypeKey]);
if (additional.TryGetValue(CdnKey, out var value))
{
Cdn = GetCdn(value);
}
}
private DataStoreConsumer GetCdn(string cdn)
{
var fromConfig = ConsumerFactory.GetByKey<Consumer>(cdn);
if (string.IsNullOrEmpty(fromConfig.Name))
{
return null;
}
var props = ManagedKeys.ToDictionary(prop => prop, prop => this[prop]);
var additional = fromConfig.AdditionalKeys.ToDictionary(prop => prop, prop => fromConfig[prop]);
additional.Add(HandlerTypeKey, HandlerType.AssemblyQualifiedName);
return new DataStoreConsumer(fromConfig.TenantManager, fromConfig.CoreBaseSettings, fromConfig.CoreSettings, fromConfig.Configuration, fromConfig.Cache, fromConfig.ConsumerFactory, fromConfig.Name, fromConfig.Order, props, additional);
}
public object Clone()
{
return new DataStoreConsumer(TenantManager, CoreBaseSettings, CoreSettings, Configuration, Cache, ConsumerFactory, Name, Order, Props.ToDictionary(r => r.Key, r => r.Value), Additional.ToDictionary(r => r.Key, r => r.Value));
}
}
[Scope]
public class ConsumerFactory : IDisposable
{
public ILifetimeScope Builder { get; set; }
public ConsumerFactory(IContainer builder)
{
Builder = builder.BeginLifetimeScope();
}
public ConsumerFactory(ILifetimeScope builder)
{
Builder = builder;
}
public Consumer GetByKey(string key)
{
if (Builder.TryResolveKeyed(key, typeof(Consumer), out var result))
{
return (Consumer)result;
}
return new Consumer();
}
public T GetByKey<T>(string key) where T : Consumer, new()
{
if (Builder.TryResolveKeyed(key, typeof(T), out var result))
{
return (T)result;
}
return new T();
}
public T Get<T>() where T : Consumer, new()
{
if (Builder.TryResolve(out T result))
{
return result;
}
return new T();
}
public IEnumerable<T> GetAll<T>() where T : Consumer, new()
{
return Builder.Resolve<IEnumerable<T>>();
}
public void Dispose()
{
Builder.Dispose();
}
}

View File

@ -23,147 +23,133 @@
*
*/
namespace ASC.Core.Configuration
{
public class SmtpSettings
{
public const int DefaultSmtpPort = 25;
public const string DefaultSenderDisplayName = "ONLYOFFICE Postman";
public string Host { get; private set; }
public int Port { get; private set; }
public string SenderAddress { get; private set; }
public string SenderDisplayName { get; private set; }
public string CredentialsDomain { get; private set; }
public string CredentialsUserName { get; private set; }
public string CredentialsUserPassword { get; private set; }
public bool EnableSSL { get; set; }
public bool EnableAuth { get; set; }
public bool IsDefaultSettings { get; internal set; }
public static readonly SmtpSettings Empty = new SmtpSettings();
private SmtpSettings()
namespace ASC.Core.Configuration;
public class SmtpSettings
{
public const int DefaultSmtpPort = 25;
public const string DefaultSenderDisplayName = "ONLYOFFICE Postman";
public string Host { get; private set; }
public int Port { get; private set; }
public string SenderAddress { get; private set; }
public string SenderDisplayName { get; private set; }
public string CredentialsDomain { get; private set; }
public string CredentialsUserName { get; private set; }
public string CredentialsUserPassword { get; private set; }
public bool EnableSSL { get; set; }
public bool EnableAuth { get; set; }
public bool IsDefaultSettings { get; internal set; }
public static readonly SmtpSettings Empty = new SmtpSettings();
private SmtpSettings() { }
public SmtpSettings(string host, string senderAddress)
: this(host, senderAddress, DefaultSenderDisplayName)
{
}
public SmtpSettings(string host, string senderAddress, string senderDisplayName)
: this(host, DefaultSmtpPort, senderAddress, senderDisplayName)
{
}
public SmtpSettings(string host, int port, string senderAddress)
: this(host, port, senderAddress, DefaultSenderDisplayName)
{
}
public SmtpSettings(string host, int port, string senderAddress, string senderDisplayName)
{
if (string.IsNullOrEmpty(host))
{
}
public SmtpSettings(string host, string senderAddress)
: this(host, senderAddress, DefaultSenderDisplayName)
throw new ArgumentException("Empty smtp host.", nameof(host));
}
if (string.IsNullOrEmpty(senderAddress))
{
throw new ArgumentException("Empty sender address.", nameof(senderAddress));
}
}
public SmtpSettings(string host, string senderAddress, string senderDisplayName)
: this(host, DefaultSmtpPort, senderAddress, senderDisplayName)
{
}
public SmtpSettings(string host, int port, string senderAddress)
: this(host, port, senderAddress, DefaultSenderDisplayName)
{
}
public SmtpSettings(string host, int port, string senderAddress, string senderDisplayName)
{
if (string.IsNullOrEmpty(host))
{
throw new ArgumentException("Empty smtp host.", nameof(host));
}
if (string.IsNullOrEmpty(senderAddress))
{
throw new ArgumentException("Empty sender address.", nameof(senderAddress));
}
Host = host;
Port = port;
SenderAddress = senderAddress;
SenderDisplayName = senderDisplayName ?? throw new ArgumentNullException(nameof(senderDisplayName));
}
Host = host;
Port = port;
SenderAddress = senderAddress;
SenderDisplayName = senderDisplayName ?? throw new ArgumentNullException(nameof(senderDisplayName));
}
public void SetCredentials(string userName, string password)
{
SetCredentials(userName, password, string.Empty);
}
public void SetCredentials(string userName, string password, string domain)
{
if (string.IsNullOrEmpty(userName))
{
throw new ArgumentException("Empty user name.", nameof(userName));
}
if (string.IsNullOrEmpty(password))
{
throw new ArgumentException("Empty password.", nameof(password));
}
CredentialsUserName = userName;
CredentialsUserPassword = password;
CredentialsDomain = domain;
}
public string Serialize()
{
return ToString();
}
public static SmtpSettings Deserialize(string value)
{
if (string.IsNullOrEmpty(value))
{
return Empty;
}
var props = value.Split(new[] { '#' }, StringSplitOptions.None);
props = Array.ConvertAll(props, p => !string.IsNullOrEmpty(p) ? p : null);
var host = HttpUtility.UrlDecode(props[3]);
var port = !string.IsNullOrEmpty(props[4]) ? int.Parse(props[4]) : DefaultSmtpPort;
var senderAddress = HttpUtility.UrlDecode(props[5]);
var senderDisplayName = HttpUtility.UrlDecode(props[6]) ?? DefaultSenderDisplayName;
var settings = new SmtpSettings(host, port, senderAddress, senderDisplayName)
{
EnableSSL = 7 < props.Length && !string.IsNullOrEmpty(props[7]) && Convert.ToBoolean(props[7])
};
var credentialsUserName = HttpUtility.UrlDecode(props[1]);
var credentialsUserPassword = HttpUtility.UrlDecode(props[2]);
var credentialsDomain = HttpUtility.UrlDecode(props[0]);
if (!string.IsNullOrEmpty(credentialsUserName) && !string.IsNullOrEmpty(credentialsUserPassword))
{
settings.SetCredentials(credentialsUserName, credentialsUserPassword, credentialsDomain);
settings.EnableAuth = true;
}
else
{
settings.EnableAuth = false;
}
public void SetCredentials(string userName, string password)
{
SetCredentials(userName, password, string.Empty);
}
return settings;
}
public override string ToString()
{
return string.Join("#",
HttpUtility.UrlEncode(CredentialsDomain),
HttpUtility.UrlEncode(CredentialsUserName),
HttpUtility.UrlEncode(CredentialsUserPassword),
HttpUtility.UrlEncode(Host),
Port.ToString(),
HttpUtility.UrlEncode(SenderAddress),
HttpUtility.UrlEncode(SenderDisplayName),
EnableSSL.ToString());
}
}
public void SetCredentials(string userName, string password, string domain)
{
if (string.IsNullOrEmpty(userName))
{
throw new ArgumentException("Empty user name.", nameof(userName));
}
if (string.IsNullOrEmpty(password))
{
throw new ArgumentException("Empty password.", nameof(password));
}
CredentialsUserName = userName;
CredentialsUserPassword = password;
CredentialsDomain = domain;
}
public string Serialize()
{
return ToString();
}
public static SmtpSettings Deserialize(string value)
{
if (string.IsNullOrEmpty(value))
{
return Empty;
}
var props = value.Split(new[] { '#' }, StringSplitOptions.None);
props = Array.ConvertAll(props, p => !string.IsNullOrEmpty(p) ? p : null);
var host = HttpUtility.UrlDecode(props[3]);
var port = !string.IsNullOrEmpty(props[4]) ? int.Parse(props[4]) : DefaultSmtpPort;
var senderAddress = HttpUtility.UrlDecode(props[5]);
var senderDisplayName = HttpUtility.UrlDecode(props[6]) ?? DefaultSenderDisplayName;
var settings = new SmtpSettings(host, port, senderAddress, senderDisplayName)
{
EnableSSL = 7 < props.Length && !string.IsNullOrEmpty(props[7]) && Convert.ToBoolean(props[7])
};
var credentialsUserName = HttpUtility.UrlDecode(props[1]);
var credentialsUserPassword = HttpUtility.UrlDecode(props[2]);
var credentialsDomain = HttpUtility.UrlDecode(props[0]);
if (!string.IsNullOrEmpty(credentialsUserName) && !string.IsNullOrEmpty(credentialsUserPassword))
{
settings.SetCredentials(credentialsUserName, credentialsUserPassword, credentialsDomain);
settings.EnableAuth = true;
}
else
{
settings.EnableAuth = false;
}
return settings;
}
public override string ToString()
{
return string.Join("#",
HttpUtility.UrlEncode(CredentialsDomain),
HttpUtility.UrlEncode(CredentialsUserName),
HttpUtility.UrlEncode(CredentialsUserPassword),
HttpUtility.UrlEncode(Host),
Port.ToString(),
HttpUtility.UrlEncode(SenderAddress),
HttpUtility.UrlEncode(SenderDisplayName),
EnableSSL.ToString());
}
}

View File

@ -23,54 +23,55 @@
*
*/
namespace ASC.Core
{
[Scope]
public class AuthManager
{
private readonly IUserService userService;
private UserManager UserManager { get; }
private UserFormatter UserFormatter { get; }
private TenantManager TenantManager { get; }
namespace ASC.Core;
public AuthManager(IUserService service, UserManager userManager, UserFormatter userFormatter, TenantManager tenantManager)
{
userService = service;
UserManager = userManager;
UserFormatter = userFormatter;
TenantManager = tenantManager;
}
public IUserAccount[] GetUserAccounts(Tenant tenant)
{
return UserManager.GetUsers(EmployeeStatus.Active).Select(u => ToAccount(tenant.TenantId, u)).ToArray();
}
public void SetUserPasswordHash(Guid userID, string passwordHash)
[Scope]
public class AuthManager
{
private readonly IUserService _userService;
private readonly UserManager _userManager;
private readonly UserFormatter _userFormatter;
private readonly TenantManager _tenantManager;
public AuthManager(IUserService service, UserManager userManager, UserFormatter userFormatter, TenantManager tenantManager)
{
_userService = service;
_userManager = userManager;
_userFormatter = userFormatter;
_tenantManager = tenantManager;
}
public IUserAccount[] GetUserAccounts(Tenant tenant)
{
return _userManager.GetUsers(EmployeeStatus.Active).Select(u => ToAccount(tenant.Id, u)).ToArray();
}
public void SetUserPasswordHash(Guid userID, string passwordHash)
{
_userService.SetUserPasswordHash(_tenantManager.GetCurrentTenant().Id, userID, passwordHash);
}
public DateTime GetUserPasswordStamp(Guid userID)
{
return _userService.GetUserPasswordStamp(_tenantManager.GetCurrentTenant().Id, userID);
}
public IAccount GetAccountByID(int tenantId, Guid id)
{
var s = ASC.Core.Configuration.Constants.SystemAccounts.FirstOrDefault(a => a.ID == id);
if (s != null)
{
userService.SetUserPasswordHash(TenantManager.GetCurrentTenant().TenantId, userID, passwordHash);
return s;
}
public DateTime GetUserPasswordStamp(Guid userID)
{
return userService.GetUserPasswordStamp(TenantManager.GetCurrentTenant().TenantId, userID);
}
public IAccount GetAccountByID(int tenantId, Guid id)
{
var s = ASC.Core.Configuration.Constants.SystemAccounts.FirstOrDefault(a => a.ID == id);
if (s != null) return s;
var u = UserManager.GetUsers(id);
return !Users.Constants.LostUser.Equals(u) && u.Status == EmployeeStatus.Active ? (IAccount)ToAccount(tenantId, u) : ASC.Core.Configuration.Constants.Guest;
}
private IUserAccount ToAccount(int tenantId, UserInfo u)
{
return new UserAccount(u, tenantId, UserFormatter);
}
}
}
var u = _userManager.GetUsers(id);
return !Users.Constants.LostUser.Equals(u) && u.Status == EmployeeStatus.Active ? (IAccount)ToAccount(tenantId, u) : ASC.Core.Configuration.Constants.Guest;
}
private IUserAccount ToAccount(int tenantId, UserInfo u)
{
return new UserAccount(u, tenantId, _userFormatter);
}
}

View File

@ -23,100 +23,103 @@
*
*/
namespace ASC.Core
namespace ASC.Core;
[Scope]
public class AuthorizationManager
{
[Scope]
public class AuthorizationManager
{
private readonly IAzService service;
private TenantManager TenantManager { get; }
public AuthorizationManager(IAzService service, TenantManager tenantManager)
{
this.service = service;
TenantManager = tenantManager;
}
public IEnumerable<AzRecord> GetAces(Guid subjectId, Guid actionId)
{
var aces = service.GetAces(TenantManager.GetCurrentTenant().TenantId, default);
return aces
.Where(a => a.ActionId == actionId && (a.SubjectId == subjectId || subjectId == Guid.Empty))
.ToList();
}
public IEnumerable<AzRecord> GetAces(Guid subjectId, Guid actionId, ISecurityObjectId objectId)
{
var aces = service.GetAces(TenantManager.GetCurrentTenant().TenantId, default);
return FilterAces(aces, subjectId, actionId, objectId)
.ToList();
}
public IEnumerable<AzRecord> GetAcesWithInherits(Guid subjectId, Guid actionId, ISecurityObjectId objectId, ISecurityObjectProvider secObjProvider)
{
if (objectId == null)
{
return GetAces(subjectId, actionId, null);
}
var result = new List<AzRecord>();
var aces = service.GetAces(TenantManager.GetCurrentTenant().TenantId, default);
result.AddRange(FilterAces(aces, subjectId, actionId, objectId));
var inherits = new List<AzRecord>();
var secObjProviderHelper = new AzObjectSecurityProviderHelper(objectId, secObjProvider);
while (secObjProviderHelper.NextInherit())
{
inherits.AddRange(FilterAces(aces, subjectId, actionId, secObjProviderHelper.CurrentObjectId));
}
inherits.AddRange(FilterAces(aces, subjectId, actionId, null));
result.AddRange(DistinctAces(inherits));
return result;
}
public void AddAce(AzRecord r)
{
service.SaveAce(TenantManager.GetCurrentTenant().TenantId, r);
}
public void RemoveAce(AzRecord r)
{
service.RemoveAce(TenantManager.GetCurrentTenant().TenantId, r);
}
public void RemoveAllAces(ISecurityObjectId id)
{
foreach (var r in GetAces(Guid.Empty, Guid.Empty, id))
{
RemoveAce(r);
}
}
private IEnumerable<AzRecord> GetAcesInternal()
{
return service.GetAces(TenantManager.GetCurrentTenant().TenantId, default);
}
private IEnumerable<AzRecord> DistinctAces(IEnumerable<AzRecord> inheritAces)
{
var aces = new Dictionary<string, AzRecord>();
foreach (var a in inheritAces)
{
aces[string.Format("{0}{1}{2:D}", a.SubjectId, a.ActionId, a.Reaction)] = a;
}
return aces.Values;
}
private IEnumerable<AzRecord> FilterAces(IEnumerable<AzRecord> aces, Guid subjectId, Guid actionId, ISecurityObjectId objectId)
{
var objId = AzObjectIdHelper.GetFullObjectId(objectId);
return aces is AzRecordStore store ?
store.Get(objId).Where(a => (a.SubjectId == subjectId || subjectId == Guid.Empty) && (a.ActionId == actionId || actionId == Guid.Empty)) :
aces.Where(a => (a.SubjectId == subjectId || subjectId == Guid.Empty) && (a.ActionId == actionId || actionId == Guid.Empty) && a.ObjectId == objId);
}
}
}
private readonly IAzService _service;
private readonly TenantManager _tenantManager;
public AuthorizationManager(IAzService service, TenantManager tenantManager)
{
_service = service;
_tenantManager = tenantManager;
}
public IEnumerable<AzRecord> GetAces(Guid subjectId, Guid actionId)
{
var aces = _service.GetAces(_tenantManager.GetCurrentTenant().Id, default);
return aces
.Where(a => a.Action == actionId && (a.Subject == subjectId || subjectId == Guid.Empty))
.ToList();
}
public IEnumerable<AzRecord> GetAces(Guid subjectId, Guid actionId, ISecurityObjectId objectId)
{
var aces = _service.GetAces(_tenantManager.GetCurrentTenant().Id, default);
return FilterAces(aces, subjectId, actionId, objectId)
.ToList();
}
public IEnumerable<AzRecord> GetAcesWithInherits(Guid subjectId, Guid actionId, ISecurityObjectId objectId, ISecurityObjectProvider secObjProvider)
{
if (objectId == null)
{
return GetAces(subjectId, actionId, null);
}
var result = new List<AzRecord>();
var aces = _service.GetAces(_tenantManager.GetCurrentTenant().Id, default);
result.AddRange(FilterAces(aces, subjectId, actionId, objectId));
var inherits = new List<AzRecord>();
var secObjProviderHelper = new AzObjectSecurityProviderHelper(objectId, secObjProvider);
while (secObjProviderHelper.NextInherit())
{
inherits.AddRange(FilterAces(aces, subjectId, actionId, secObjProviderHelper.CurrentObjectId));
}
inherits.AddRange(FilterAces(aces, subjectId, actionId, null));
result.AddRange(DistinctAces(inherits));
return result;
}
public void AddAce(AzRecord r)
{
_service.SaveAce(_tenantManager.GetCurrentTenant().Id, r);
}
public void RemoveAce(AzRecord r)
{
_service.RemoveAce(_tenantManager.GetCurrentTenant().Id, r);
}
public void RemoveAllAces(ISecurityObjectId id)
{
foreach (var r in GetAces(Guid.Empty, Guid.Empty, id))
{
RemoveAce(r);
}
}
private IEnumerable<AzRecord> GetAcesInternal()
{
return _service.GetAces(_tenantManager.GetCurrentTenant().Id, default);
}
private IEnumerable<AzRecord> DistinctAces(IEnumerable<AzRecord> inheritAces)
{
var aces = new Dictionary<string, AzRecord>();
foreach (var a in inheritAces)
{
aces[string.Format("{0}{1}{2:D}", a.Subject, a.Action, a.AceType)] = a;
}
return aces.Values;
}
private IEnumerable<AzRecord> FilterAces(IEnumerable<AzRecord> aces, Guid subjectId, Guid actionId, ISecurityObjectId objectId)
{
var objId = AzObjectIdHelper.GetFullObjectId(objectId);
return aces is AzRecordStore store ?
store.Get(objId).Where(a => (a.Subject == subjectId || subjectId == Guid.Empty) && (a.Action == actionId || actionId == Guid.Empty)) :
aces.Where(a => (a.Subject == subjectId || subjectId == Guid.Empty) && (a.Action == actionId || actionId == Guid.Empty) && a.Object == objId);
}
}

View File

@ -23,349 +23,354 @@
*
*/
namespace ASC.Core
namespace ASC.Core;
[Singletone]
public class CoreBaseSettings
{
[Singletone]
public class CoreBaseSettings
{
private bool? standalone;
private string basedomain;
private bool? personal;
private bool? customMode;
private IConfiguration Configuration { get; }
public CoreBaseSettings(IConfiguration configuration)
{
Configuration = configuration;
}
public string Basedomain
{
get
{
if (basedomain == null)
{
basedomain = Configuration["core:base-domain"] ?? string.Empty;
}
return basedomain;
}
}
public bool Standalone
{
get { return standalone ?? (bool)(standalone = Configuration["core:base-domain"] == "localhost"); }
}
public bool Personal
{
get
{
//TODO:if (CustomMode && HttpContext.Current != null && HttpContext.Current.Request.SailfishApp()) return true;
return personal ?? (bool)(personal = string.Equals(Configuration["core:personal"], "true", StringComparison.OrdinalIgnoreCase));
}
}
public bool CustomMode
{
get { return customMode ?? (bool)(customMode = string.Equals(Configuration["core:custom-mode"], "true", StringComparison.OrdinalIgnoreCase));}
}
}
class ConfigureCoreSettings : IConfigureNamedOptions<CoreSettings>
private bool? _standalone;
private string _basedomain;
private bool? _personal;
private bool? _customMode;
private IConfiguration Configuration { get; }
public CoreBaseSettings(IConfiguration configuration)
{
private IOptionsSnapshot<CachedTenantService> TenantService { get; }
private CoreBaseSettings CoreBaseSettings { get; }
private IConfiguration Configuration { get; }
Configuration = configuration;
}
public ConfigureCoreSettings(
IOptionsSnapshot<CachedTenantService> tenantService,
CoreBaseSettings coreBaseSettings,
IConfiguration configuration
)
public string Basedomain
{
get
{
TenantService = tenantService;
CoreBaseSettings = coreBaseSettings;
Configuration = configuration;
}
if (_basedomain == null)
{
_basedomain = Configuration["core:base-domain"] ?? string.Empty;
}
public void Configure(string name, CoreSettings options)
{
Configure(options);
options.TenantService = TenantService.Get(name);
}
public void Configure(CoreSettings options)
{
options.Configuration = Configuration;
options.CoreBaseSettings = CoreBaseSettings;
options.TenantService = TenantService.Value;
return _basedomain;
}
}
[Scope(typeof(ConfigureCoreSettings))]
public class CoreSettings
{
public string BaseDomain
{
get
{
string result;
if (CoreBaseSettings.Standalone || string.IsNullOrEmpty(CoreBaseSettings.Basedomain))
{
result = GetSetting("BaseDomain") ?? CoreBaseSettings.Basedomain;
}
else
{
result = CoreBaseSettings.Basedomain;
}
return result;
}
set
{
if (CoreBaseSettings.Standalone || string.IsNullOrEmpty(CoreBaseSettings.Basedomain))
{
SaveSetting("BaseDomain", value);
}
}
}
internal ITenantService TenantService { get; set; }
internal CoreBaseSettings CoreBaseSettings { get; set; }
internal IConfiguration Configuration { get; set; }
public CoreSettings()
{
public bool Standalone => _standalone ?? (bool)(_standalone = Configuration["core:base-domain"] == "localhost");
}
public bool Personal =>
//TODO:if (CustomMode && HttpContext.Current != null && HttpContext.Current.Request.SailfishApp()) return true;
_personal ?? (bool)(_personal = string.Equals(Configuration["core:personal"], "true", StringComparison.OrdinalIgnoreCase));
public CoreSettings(
ITenantService tenantService,
CoreBaseSettings coreBaseSettings,
IConfiguration configuration)
{
TenantService = tenantService;
CoreBaseSettings = coreBaseSettings;
Configuration = configuration;
}
public string GetBaseDomain(string hostedRegion)
{
var baseHost = BaseDomain;
if (string.IsNullOrEmpty(hostedRegion) || string.IsNullOrEmpty(baseHost) || baseHost.IndexOf('.') < 0)
{
return baseHost;
}
var subdomain = baseHost.Remove(baseHost.IndexOf('.') + 1);
return hostedRegion.StartsWith(subdomain) ? hostedRegion : (subdomain + hostedRegion.TrimStart('.'));
}
public void SaveSetting(string key, string value, int tenant = Tenant.DEFAULT_TENANT)
{
if (string.IsNullOrEmpty(key))
{
throw new ArgumentNullException(nameof(key));
}
byte[] bytes = null;
if (value != null)
{
bytes = Crypto.GetV(Encoding.UTF8.GetBytes(value), 2, true);
}
TenantService.SetTenantSettings(tenant, key, bytes);
}
public string GetSetting(string key, int tenant = Tenant.DEFAULT_TENANT)
{
if (string.IsNullOrEmpty(key))
{
throw new ArgumentNullException(nameof(key));
}
var bytes = TenantService.GetTenantSettings(tenant, key);
var result = bytes != null ? Encoding.UTF8.GetString(Crypto.GetV(bytes, 2, false)) : null;
return result;
}
public string GetKey(int tenant)
{
if (CoreBaseSettings.Standalone)
{
var key = GetSetting("PortalId");
if (string.IsNullOrEmpty(key))
{
lock (TenantService)
{
// thread safe
key = GetSetting("PortalId");
if (string.IsNullOrEmpty(key))
{
key = Guid.NewGuid().ToString();
SaveSetting("PortalId", key);
}
}
}
return key;
}
else
{
var t = TenantService.GetTenant(tenant);
if (t != null && !string.IsNullOrWhiteSpace(t.PaymentId))
return t.PaymentId;
return Configuration["core:payment:region"] + tenant;
}
}
public string GetAffiliateId(int tenant)
{
var t = TenantService.GetTenant(tenant);
if (t != null && !string.IsNullOrWhiteSpace(t.AffiliateId))
return t.AffiliateId;
return null;
}
public string GetCampaign(int tenant)
{
var t = TenantService.GetTenant(tenant);
if (t != null && !string.IsNullOrWhiteSpace(t.Campaign))
return t.Campaign;
return null;
}
}
public bool CustomMode => _customMode ?? (bool)(_customMode = string.Equals(Configuration["core:custom-mode"], "true", StringComparison.OrdinalIgnoreCase));
}
[Scope]
public class CoreConfiguration
{
private long? personalMaxSpace;
public CoreConfiguration(CoreSettings coreSettings, TenantManager tenantManager, IConfiguration configuration)
{
CoreSettings = coreSettings;
TenantManager = tenantManager;
Configuration = configuration;
}
public long PersonalMaxSpace(SettingsManager settingsManager)
{
var quotaSettings = settingsManager.LoadForCurrentUser<PersonalQuotaSettings>();
if (quotaSettings.MaxSpace != long.MaxValue)
return quotaSettings.MaxSpace;
if (personalMaxSpace.HasValue)
return personalMaxSpace.Value;
if (!long.TryParse(Configuration["core:personal.maxspace"], out var value))
value = long.MaxValue;
personalMaxSpace = value;
return personalMaxSpace.Value;
}
public SmtpSettings SmtpSettings
{
get
{
var isDefaultSettings = false;
var tenant = TenantManager.GetCurrentTenant(false);
if (tenant != null)
{
var settingsValue = GetSetting("SmtpSettings", tenant.TenantId);
if (string.IsNullOrEmpty(settingsValue))
{
isDefaultSettings = true;
settingsValue = GetSetting("SmtpSettings");
}
var settings = SmtpSettings.Deserialize(settingsValue);
settings.IsDefaultSettings = isDefaultSettings;
return settings;
}
else
{
var settingsValue = GetSetting("SmtpSettings");
var settings = SmtpSettings.Deserialize(settingsValue);
settings.IsDefaultSettings = true;
return settings;
}
}
set { SaveSetting("SmtpSettings", value?.Serialize(), TenantManager.GetCurrentTenant().TenantId); }
}
private CoreSettings CoreSettings { get; }
private TenantManager TenantManager { get; }
private IConfiguration Configuration { get; }
#region Methods Get/Save Setting
public void SaveSetting(string key, string value, int tenant = Tenant.DEFAULT_TENANT)
class ConfigureCoreSettings : IConfigureNamedOptions<CoreSettings>
{
private readonly IOptionsSnapshot<CachedTenantService> _tenantService;
private readonly CoreBaseSettings _coreBaseSettings;
private readonly IConfiguration _configuration;
public ConfigureCoreSettings(
IOptionsSnapshot<CachedTenantService> tenantService,
CoreBaseSettings coreBaseSettings,
IConfiguration configuration
)
{
_tenantService = tenantService;
_coreBaseSettings = coreBaseSettings;
_configuration = configuration;
}
public void Configure(string name, CoreSettings options)
{
Configure(options);
options.TenantService = _tenantService.Get(name);
}
public void Configure(CoreSettings options)
{
options.Configuration = _configuration;
options.CoreBaseSettings = _coreBaseSettings;
options.TenantService = _tenantService.Value;
}
}
[Scope(typeof(ConfigureCoreSettings))]
public class CoreSettings
{
public string BaseDomain
{
get
{
CoreSettings.SaveSetting(key, value, tenant);
string result;
if (CoreBaseSettings.Standalone || string.IsNullOrEmpty(CoreBaseSettings.Basedomain))
{
result = GetSetting("BaseDomain") ?? CoreBaseSettings.Basedomain;
}
else
{
result = CoreBaseSettings.Basedomain;
}
return result;
}
public string GetSetting(string key, int tenant = Tenant.DEFAULT_TENANT)
set
{
return CoreSettings.GetSetting(key, tenant);
if (CoreBaseSettings.Standalone || string.IsNullOrEmpty(CoreBaseSettings.Basedomain))
{
SaveSetting("BaseDomain", value);
}
}
}
internal ITenantService TenantService;
internal CoreBaseSettings CoreBaseSettings;
internal IConfiguration Configuration;
public CoreSettings() { }
public CoreSettings(
ITenantService tenantService,
CoreBaseSettings coreBaseSettings,
IConfiguration configuration)
{
TenantService = tenantService;
CoreBaseSettings = coreBaseSettings;
Configuration = configuration;
}
public string GetBaseDomain(string hostedRegion)
{
var baseHost = BaseDomain;
if (string.IsNullOrEmpty(hostedRegion) || string.IsNullOrEmpty(baseHost) || baseHost.IndexOf('.') < 0)
{
return baseHost;
}
var subdomain = baseHost.Remove(baseHost.IndexOf('.') + 1);
return hostedRegion.StartsWith(subdomain) ? hostedRegion : (subdomain + hostedRegion.TrimStart('.'));
}
public void SaveSetting(string key, string value, int tenant = Tenant.DefaultTenant)
{
if (string.IsNullOrEmpty(key))
{
throw new ArgumentNullException(nameof(key));
}
#endregion
byte[] bytes = null;
if (value != null)
{
bytes = Crypto.GetV(Encoding.UTF8.GetBytes(value), 2, true);
}
#region Methods Get/Set Section
TenantService.SetTenantSettings(tenant, key, bytes);
}
public T GetSection<T>() where T : class
{
return GetSection<T>(typeof(T).Name);
}
public T GetSection<T>(int tenantId) where T : class
{
return GetSection<T>(tenantId, typeof(T).Name);
}
public T GetSection<T>(string sectionName) where T : class
{
return GetSection<T>(TenantManager.GetCurrentTenant().TenantId, sectionName);
}
public T GetSection<T>(int tenantId, string sectionName) where T : class
{
var serializedSection = GetSetting(sectionName, tenantId);
if (serializedSection == null && tenantId != Tenant.DEFAULT_TENANT)
{
serializedSection = GetSetting(sectionName, Tenant.DEFAULT_TENANT);
}
return serializedSection != null ? JsonConvert.DeserializeObject<T>(serializedSection) : null;
}
public void SaveSection<T>(string sectionName, T section) where T : class
{
SaveSection(TenantManager.GetCurrentTenant().TenantId, sectionName, section);
}
public void SaveSection<T>(T section) where T : class
{
SaveSection(typeof(T).Name, section);
}
public void SaveSection<T>(int tenantId, T section) where T : class
{
SaveSection(tenantId, typeof(T).Name, section);
}
public void SaveSection<T>(int tenantId, string sectionName, T section) where T : class
{
var serializedSection = section != null ? JsonConvert.SerializeObject(section) : null;
SaveSetting(sectionName, serializedSection, tenantId);
}
#endregion
}
}
public string GetSetting(string key, int tenant = Tenant.DefaultTenant)
{
if (string.IsNullOrEmpty(key))
{
throw new ArgumentNullException(nameof(key));
}
var bytes = TenantService.GetTenantSettings(tenant, key);
var result = bytes != null ? Encoding.UTF8.GetString(Crypto.GetV(bytes, 2, false)) : null;
return result;
}
public string GetKey(int tenant)
{
if (CoreBaseSettings.Standalone)
{
var key = GetSetting("PortalId");
if (string.IsNullOrEmpty(key))
{
lock (TenantService)
{
// thread safe
key = GetSetting("PortalId");
if (string.IsNullOrEmpty(key))
{
key = Guid.NewGuid().ToString();
SaveSetting("PortalId", key);
}
}
}
return key;
}
else
{
var t = TenantService.GetTenant(tenant);
if (t != null && !string.IsNullOrWhiteSpace(t.PaymentId))
{
return t.PaymentId;
}
return Configuration["core:payment:region"] + tenant;
}
}
public string GetAffiliateId(int tenant)
{
var t = TenantService.GetTenant(tenant);
if (t != null && !string.IsNullOrWhiteSpace(t.AffiliateId))
{
return t.AffiliateId;
}
return null;
}
public string GetCampaign(int tenant)
{
var t = TenantService.GetTenant(tenant);
if (t != null && !string.IsNullOrWhiteSpace(t.Campaign))
{
return t.Campaign;
}
return null;
}
}
[Scope]
public class CoreConfiguration
{
private long? _personalMaxSpace;
public CoreConfiguration(CoreSettings coreSettings, TenantManager tenantManager, IConfiguration configuration)
{
_coreSettings = coreSettings;
_tenantManager = tenantManager;
_configuration = configuration;
}
public long PersonalMaxSpace(SettingsManager settingsManager)
{
var quotaSettings = settingsManager.LoadForCurrentUser<PersonalQuotaSettings>();
if (quotaSettings.MaxSpace != long.MaxValue)
{
return quotaSettings.MaxSpace;
}
if (_personalMaxSpace.HasValue)
{
return _personalMaxSpace.Value;
}
if (!long.TryParse(_configuration["core:personal.maxspace"], out var value))
{
value = long.MaxValue;
}
_personalMaxSpace = value;
return _personalMaxSpace.Value;
}
public SmtpSettings SmtpSettings
{
get
{
var isDefaultSettings = false;
var tenant = _tenantManager.GetCurrentTenant(false);
if (tenant != null)
{
var settingsValue = GetSetting("SmtpSettings", tenant.Id);
if (string.IsNullOrEmpty(settingsValue))
{
isDefaultSettings = true;
settingsValue = GetSetting("SmtpSettings");
}
var settings = SmtpSettings.Deserialize(settingsValue);
settings.IsDefaultSettings = isDefaultSettings;
return settings;
}
else
{
var settingsValue = GetSetting("SmtpSettings");
var settings = SmtpSettings.Deserialize(settingsValue);
settings.IsDefaultSettings = true;
return settings;
}
}
set { SaveSetting("SmtpSettings", value?.Serialize(), _tenantManager.GetCurrentTenant().Id); }
}
private readonly CoreSettings _coreSettings;
private readonly TenantManager _tenantManager;
private readonly IConfiguration _configuration;
#region Methods Get/Save Setting
public void SaveSetting(string key, string value, int tenant = Tenant.DefaultTenant)
{
_coreSettings.SaveSetting(key, value, tenant);
}
public string GetSetting(string key, int tenant = Tenant.DefaultTenant)
{
return _coreSettings.GetSetting(key, tenant);
}
#endregion
#region Methods Get/Set Section
public T GetSection<T>() where T : class
{
return GetSection<T>(typeof(T).Name);
}
public T GetSection<T>(int tenantId) where T : class
{
return GetSection<T>(tenantId, typeof(T).Name);
}
public T GetSection<T>(string sectionName) where T : class
{
return GetSection<T>(_tenantManager.GetCurrentTenant().Id, sectionName);
}
public T GetSection<T>(int tenantId, string sectionName) where T : class
{
var serializedSection = GetSetting(sectionName, tenantId);
if (serializedSection == null && tenantId != Tenant.DefaultTenant)
{
serializedSection = GetSetting(sectionName, Tenant.DefaultTenant);
}
return serializedSection != null ? JsonConvert.DeserializeObject<T>(serializedSection) : null;
}
public void SaveSection<T>(string sectionName, T section) where T : class
{
SaveSection(_tenantManager.GetCurrentTenant().Id, sectionName, section);
}
public void SaveSection<T>(T section) where T : class
{
SaveSection(typeof(T).Name, section);
}
public void SaveSection<T>(int tenantId, T section) where T : class
{
SaveSection(tenantId, typeof(T).Name, section);
}
public void SaveSection<T>(int tenantId, string sectionName, T section) where T : class
{
var serializedSection = section != null ? JsonConvert.SerializeObject(section) : null;
SaveSetting(sectionName, serializedSection, tenantId);
}
#endregion
}

View File

@ -23,103 +23,103 @@
*
*/
namespace ASC.Core
namespace ASC.Core;
[Scope]
public class PaymentManager
{
[Scope]
public class PaymentManager
{
private readonly ITariffService tariffService;
private readonly string partnerUrl;
private readonly string partnerKey;
private TenantManager TenantManager { get; }
private IConfiguration Configuration { get; }
private IHttpClientFactory ClientFactory { get; }
public PaymentManager(TenantManager tenantManager, ITariffService tariffService, IConfiguration configuration, IHttpClientFactory clientFactory)
{
TenantManager = tenantManager;
this.tariffService = tariffService;
Configuration = configuration;
partnerUrl = (Configuration["core:payment:partners"] ?? "https://partners.onlyoffice.com/api").TrimEnd('/');
partnerKey = Configuration["core:machinekey"] ?? "C5C1F4E85A3A43F5B3202C24D97351DF";
ClientFactory = clientFactory;
}
public Tariff GetTariff(int tenantId)
{
return tariffService.GetTariff(tenantId);
}
public void SetTariff(int tenantId, Tariff tariff)
{
tariffService.SetTariff(tenantId, tariff);
}
public void DeleteDefaultTariff()
{
tariffService.DeleteDefaultBillingInfo();
}
public IEnumerable<PaymentInfo> GetTariffPayments(int tenant)
{
return tariffService.GetPayments(tenant);
}
private readonly ITariffService _tariffService;
private readonly string _partnerUrl;
private readonly string _partnerKey;
public IDictionary<string, Dictionary<string, decimal>> GetProductPriceInfo(params string[] productIds)
private readonly TenantManager _tenantManager;
private readonly IConfiguration _configuration;
private readonly IHttpClientFactory _clientFactory;
public PaymentManager(TenantManager tenantManager, ITariffService tariffService, IConfiguration configuration, IHttpClientFactory clientFactory)
{
_tenantManager = tenantManager;
_tariffService = tariffService;
_configuration = configuration;
_partnerUrl = (_configuration["core:payment:partners"] ?? "https://partners.onlyoffice.com/api").TrimEnd('/');
_partnerKey = _configuration["core:machinekey"] ?? "C5C1F4E85A3A43F5B3202C24D97351DF";
_clientFactory = clientFactory;
}
public Tariff GetTariff(int tenantId)
{
return _tariffService.GetTariff(tenantId);
}
public void SetTariff(int tenantId, Tariff tariff)
{
_tariffService.SetTariff(tenantId, tariff);
}
public void DeleteDefaultTariff()
{
_tariffService.DeleteDefaultBillingInfo();
}
public IEnumerable<PaymentInfo> GetTariffPayments(int tenant)
{
return _tariffService.GetPayments(tenant);
}
public IDictionary<string, Dictionary<string, decimal>> GetProductPriceInfo(params string[] productIds)
{
return _tariffService.GetProductPriceInfo(productIds);
}
public Uri GetShoppingUri(int quotaId, bool forCurrentTenant = true, string affiliateId = null, string currency = null, string language = null, string customerId = null, string quantity = null)
{
return _tariffService.GetShoppingUri(forCurrentTenant ? _tenantManager.GetCurrentTenant().Id : (int?)null, quotaId, affiliateId, currency, language, customerId, quantity);
}
public Uri GetShoppingUri(int quotaId, string affiliateId, string currency = null, string language = null, string customerId = null, string quantity = null)
{
return _tariffService.GetShoppingUri(null, quotaId, affiliateId, currency, language, customerId, quantity);
}
public void ActivateKey(string key)
{
if (string.IsNullOrEmpty(key))
{
return tariffService.GetProductPriceInfo(productIds);
throw new ArgumentNullException(nameof(key));
}
public Uri GetShoppingUri(int quotaId, bool forCurrentTenant = true, string affiliateId = null, string currency = null, string language = null, string customerId = null, string quantity = null)
{
return tariffService.GetShoppingUri(forCurrentTenant ? TenantManager.GetCurrentTenant().TenantId : (int?)null, quotaId, affiliateId, currency, language, customerId, quantity);
}
public Uri GetShoppingUri(int quotaId, string affiliateId, string currency = null, string language = null, string customerId = null, string quantity = null)
{
return tariffService.GetShoppingUri(null, quotaId, affiliateId, currency, language, customerId, quantity);
}
public void ActivateKey(string key)
{
if (string.IsNullOrEmpty(key))
{
throw new ArgumentNullException(nameof(key));
}
var now = DateTime.UtcNow;
var actionUrl = "/partnerapi/ActivateKey?code=" + HttpUtility.UrlEncode(key) + "&portal=" + HttpUtility.UrlEncode(TenantManager.GetCurrentTenant().TenantAlias);
var request = new HttpRequestMessage();
request.Headers.Add("Authorization", GetPartnerAuthHeader(actionUrl));
request.RequestUri = new Uri(partnerUrl + actionUrl);
var now = DateTime.UtcNow;
var actionUrl = "/partnerapi/ActivateKey?code=" + HttpUtility.UrlEncode(key) + "&portal=" + HttpUtility.UrlEncode(_tenantManager.GetCurrentTenant().Alias);
var httpClient = ClientFactory.CreateClient();
var request = new HttpRequestMessage();
request.Headers.Add("Authorization", GetPartnerAuthHeader(actionUrl));
request.RequestUri = new Uri(_partnerUrl + actionUrl);
using var response = httpClient.Send(request);
var httpClient = _clientFactory.CreateClient();
using var response = httpClient.Send(request);
_tariffService.ClearCache(_tenantManager.GetCurrentTenant().Id);
var timeout = DateTime.UtcNow - now - TimeSpan.FromSeconds(5);
if (TimeSpan.Zero < timeout)
{
// clear tenant cache
Thread.Sleep(timeout);
}
_tenantManager.GetTenant(_tenantManager.GetCurrentTenant().Id);
}
private string GetPartnerAuthHeader(string url)
{
using var hasher = new HMACSHA1(Encoding.UTF8.GetBytes(_partnerKey));
var now = DateTime.UtcNow.ToString("yyyyMMddHHmmss", CultureInfo.InvariantCulture);
var data = string.Join("\n", now, "/api/" + url.TrimStart('/')); //data: UTC DateTime (yyyy:MM:dd HH:mm:ss) + \n + url
var hash = WebEncoders.Base64UrlEncode(hasher.ComputeHash(Encoding.UTF8.GetBytes(data)));
return $"ASC :{now}:{hash}";
}
tariffService.ClearCache(TenantManager.GetCurrentTenant().TenantId);
var timeout = DateTime.UtcNow - now - TimeSpan.FromSeconds(5);
if (TimeSpan.Zero < timeout)
{
// clear tenant cache
Thread.Sleep(timeout);
}
TenantManager.GetTenant(TenantManager.GetCurrentTenant().TenantId);
}
private string GetPartnerAuthHeader(string url)
{
using var hasher = new HMACSHA1(Encoding.UTF8.GetBytes(partnerKey));
var now = DateTime.UtcNow.ToString("yyyyMMddHHmmss", CultureInfo.InvariantCulture);
var data = string.Join("\n", now, "/api/" + url.TrimStart('/')); //data: UTC DateTime (yyyy:MM:dd HH:mm:ss) + \n + url
var hash = WebEncoders.Base64UrlEncode(hasher.ComputeHash(Encoding.UTF8.GetBytes(data)));
return $"ASC :{now}:{hash}";
}
}
}

View File

@ -25,199 +25,194 @@
using Constants = ASC.Common.Security.Authorizing.Constants;
namespace ASC.Core
namespace ASC.Core;
[Scope]
public class SubscriptionManager
{
[Scope]
public class SubscriptionManager
{
private readonly ISubscriptionService service;
private readonly ISubscriptionService _service;
private readonly TenantManager _tenantManager;
private ICache _cache;
public static readonly object CacheLocker = new object();
public static readonly List<Guid> Groups = Groups = new List<Guid>
{
Constants.Admin.ID,
Constants.Everyone.ID,
Constants.User.ID
};
private TenantManager TenantManager { get; }
public SubscriptionManager(CachedSubscriptionService service, TenantManager tenantManager, ICache cache)
{
_service = service ?? throw new ArgumentNullException("subscriptionManager");
_tenantManager = tenantManager;
_cache = cache;
}
private ICache Cache { get; set; }
public static readonly object CacheLocker = new object();
public static readonly List<Guid> Groups = Groups = new List<Guid>
{
Constants.Admin.ID,
Constants.Everyone.ID,
Constants.User.ID
};
public SubscriptionManager(CachedSubscriptionService service, TenantManager tenantManager, ICache cache)
{
this.service = service ?? throw new ArgumentNullException("subscriptionManager");
TenantManager = tenantManager;
Cache = cache;
}
public void Subscribe(string sourceID, string actionID, string objectID, string recipientID)
{
var s = new SubscriptionRecord
{
Tenant = GetTenant(),
Subscribed = true,
};
if (sourceID != null)
{
s.SourceId = sourceID;
}
if (actionID != null)
{
s.ActionId = actionID;
}
if (recipientID != null)
{
s.RecipientId = recipientID;
}
if (objectID != null)
{
s.ObjectId = objectID;
}
service.SaveSubscription(s);
}
public void Unsubscribe(string sourceID, string actionID, string objectID, string recipientID)
{
var s = new SubscriptionRecord
{
Tenant = GetTenant(),
Subscribed = false,
};
if (sourceID != null)
{
s.SourceId = sourceID;
}
if (actionID != null)
{
s.ActionId = actionID;
}
if (recipientID != null)
{
s.RecipientId = recipientID;
}
if (objectID != null)
{
s.ObjectId = objectID;
}
service.SaveSubscription(s);
}
public void UnsubscribeAll(string sourceID, string actionID, string objectID)
{
service.RemoveSubscriptions(GetTenant(), sourceID, actionID, objectID);
}
public void UnsubscribeAll(string sourceID, string actionID)
{
service.RemoveSubscriptions(GetTenant(), sourceID, actionID);
}
public string[] GetSubscriptionMethod(string sourceID, string actionID, string recipientID)
{
IEnumerable<SubscriptionMethod> methods;
if (Groups.Any(r => r.ToString() == recipientID))
{
methods = GetDefaultSubscriptionMethodsFromCache(sourceID, actionID, recipientID);
}
else
{
methods = service.GetSubscriptionMethods(GetTenant(), sourceID, actionID, recipientID);
}
var m = methods
.FirstOrDefault(x => x.ActionId.Equals(actionID, StringComparison.OrdinalIgnoreCase));
if (m == null)
{
m = methods.FirstOrDefault();
}
return m != null ? m.Methods : Array.Empty<string>();
}
public string[] GetRecipients(string sourceID, string actionID, string objectID)
public void Subscribe(string sourceID, string actionID, string objectID, string recipientID)
{
var s = new SubscriptionRecord
{
return service.GetRecipients(GetTenant(), sourceID, actionID, objectID);
}
public object GetSubscriptionRecord(string sourceID, string actionID, string recipientID, string objectID)
{
return service.GetSubscription(GetTenant(), sourceID, actionID, recipientID, objectID);
}
public string[] GetSubscriptions(string sourceID, string actionID, string recipientID, bool checkSubscribe = true)
Tenant = GetTenant(),
Subscribed = true,
};
if (sourceID != null)
{
return service.GetSubscriptions(GetTenant(), sourceID, actionID, recipientID, checkSubscribe);
}
public bool IsUnsubscribe(string sourceID, string recipientID, string actionID, string objectID)
{
return service.IsUnsubscribe(GetTenant(), sourceID, actionID, recipientID, objectID);
}
public void UpdateSubscriptionMethod(string sourceID, string actionID, string recipientID, string[] senderNames)
{
var m = new SubscriptionMethod
{
Tenant = GetTenant()
};
if (sourceID != null)
{
m.SourceId = sourceID;
}
if (actionID != null)
{
m.ActionId = actionID;
}
if (recipientID != null)
{
m.RecipientId = recipientID;
}
if (senderNames != null)
{
m.Methods = senderNames;
}
service.SetSubscriptionMethod(m);
s.SourceId = sourceID;
}
private IEnumerable<SubscriptionMethod> GetDefaultSubscriptionMethodsFromCache(string sourceID, string actionID, string recepient)
if (actionID != null)
{
lock (CacheLocker)
{
var key = $"subs|-1{sourceID}{actionID}{recepient}";
var result = Cache.Get<IEnumerable<SubscriptionMethod>>(key);
if (result == null)
{
result = service.GetSubscriptionMethods(-1, sourceID, actionID, recepient);
Cache.Insert(key, result, DateTime.UtcNow.AddDays(1));
}
return result;
}
s.ActionId = actionID;
}
if (recipientID != null)
{
s.RecipientId = recipientID;
}
if (objectID != null)
{
s.ObjectId = objectID;
}
_service.SaveSubscription(s);
}
private int GetTenant()
{
return TenantManager.GetCurrentTenant().TenantId;
}
public void Unsubscribe(string sourceID, string actionID, string objectID, string recipientID)
{
var s = new SubscriptionRecord
{
Tenant = GetTenant(),
Subscribed = false,
};
if (sourceID != null)
{
s.SourceId = sourceID;
}
if (actionID != null)
{
s.ActionId = actionID;
}
if (recipientID != null)
{
s.RecipientId = recipientID;
}
if (objectID != null)
{
s.ObjectId = objectID;
}
_service.SaveSubscription(s);
}
public void UnsubscribeAll(string sourceID, string actionID, string objectID)
{
_service.RemoveSubscriptions(GetTenant(), sourceID, actionID, objectID);
}
public void UnsubscribeAll(string sourceID, string actionID)
{
_service.RemoveSubscriptions(GetTenant(), sourceID, actionID);
}
public string[] GetSubscriptionMethod(string sourceID, string actionID, string recipientID)
{
IEnumerable<SubscriptionMethod> methods;
if (Groups.Any(r => r.ToString() == recipientID))
{
methods = GetDefaultSubscriptionMethodsFromCache(sourceID, actionID, recipientID);
}
else
{
methods = _service.GetSubscriptionMethods(GetTenant(), sourceID, actionID, recipientID);
}
var m = methods
.FirstOrDefault(x => x.Action.Equals(actionID, StringComparison.OrdinalIgnoreCase));
if (m == null)
{
m = methods.FirstOrDefault();
}
return m != null ? m.Methods : Array.Empty<string>();
}
public string[] GetRecipients(string sourceID, string actionID, string objectID)
{
return _service.GetRecipients(GetTenant(), sourceID, actionID, objectID);
}
public object GetSubscriptionRecord(string sourceID, string actionID, string recipientID, string objectID)
{
return _service.GetSubscription(GetTenant(), sourceID, actionID, recipientID, objectID);
}
public string[] GetSubscriptions(string sourceID, string actionID, string recipientID, bool checkSubscribe = true)
{
return _service.GetSubscriptions(GetTenant(), sourceID, actionID, recipientID, checkSubscribe);
}
public bool IsUnsubscribe(string sourceID, string recipientID, string actionID, string objectID)
{
return _service.IsUnsubscribe(GetTenant(), sourceID, actionID, recipientID, objectID);
}
public void UpdateSubscriptionMethod(string sourceID, string actionID, string recipientID, string[] senderNames)
{
var m = new SubscriptionMethod
{
Tenant = GetTenant()
};
if (sourceID != null)
{
m.Source = sourceID;
}
if (actionID != null)
{
m.Action = actionID;
}
if (recipientID != null)
{
m.Recipient = recipientID;
}
if (senderNames != null)
{
m.Methods = senderNames;
}
_service.SetSubscriptionMethod(m);
}
private IEnumerable<SubscriptionMethod> GetDefaultSubscriptionMethodsFromCache(string sourceID, string actionID, string recepient)
{
lock (CacheLocker)
{
var key = $"subs|-1{sourceID}{actionID}{recepient}";
var result = _cache.Get<IEnumerable<SubscriptionMethod>>(key);
if (result == null)
{
result = _service.GetSubscriptionMethods(-1, sourceID, actionID, recepient);
_cache.Insert(key, result, DateTime.UtcNow.AddDays(1));
}
return result;
}
}
private int GetTenant()
{
return _tenantManager.GetCurrentTenant().Id;
}
}

View File

@ -23,330 +23,347 @@
*
*/
namespace ASC.Core
namespace ASC.Core;
[Scope]
class ConfigureTenantManager : IConfigureNamedOptions<TenantManager>
{
[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
)
{
private IOptionsSnapshot<CachedTenantService> TenantService { get; }
private IOptionsSnapshot<CachedQuotaService> QuotaService { get; }
private IOptionsSnapshot<TariffService> TariffService { get; }
private IHttpContextAccessor HttpContextAccessor { get; }
private CoreBaseSettings CoreBaseSettings { get; }
private CoreSettings CoreSettings { get; }
_tenantService = tenantService;
_quotaService = quotaService;
_tariffService = tariffService;
_httpContextAccessor = httpContextAccessor;
_coreBaseSettings = coreBaseSettings;
_coreSettings = coreSettings;
}
public ConfigureTenantManager(
IOptionsSnapshot<CachedTenantService> tenantService,
IOptionsSnapshot<CachedQuotaService> quotaService,
IOptionsSnapshot<TariffService> tariffService,
IHttpContextAccessor 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;
public const string CurrentTenant = "CURRENT_TENANT";
internal ITenantService TenantService;
internal IQuotaService QuotaService;
internal ITariffService TariffService;
private static readonly List<string> _thisCompAddresses = new List<string>();
internal IHttpContextAccessor HttpContextAccessor;
internal CoreBaseSettings CoreBaseSettings;
internal CoreSettings CoreSettings;
static TenantManager()
{
_thisCompAddresses.Add("localhost");
_thisCompAddresses.Add(Dns.GetHostName().ToLowerInvariant());
_thisCompAddresses.AddRange(Dns.GetHostAddresses("localhost").Select(a => a.ToString()));
try
{
TenantService = tenantService;
QuotaService = quotaService;
TariffService = tariffService;
HttpContextAccessor = httpContextAccessor;
CoreBaseSettings = coreBaseSettings;
CoreSettings = coreSettings;
_thisCompAddresses.AddRange(Dns.GetHostAddresses(Dns.GetHostName()).Select(a => a.ToString()));
}
public void Configure(string name, TenantManager options)
catch
{
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;
// ignore
}
}
[Scope(typeof(ConfigureTenantManager))]
public class TenantManager
public TenantManager()
{
private Tenant CurrentTenant { get; set; }
public const string CURRENT_TENANT = "CURRENT_TENANT";
internal ITenantService TenantService { get; set; }
internal IQuotaService QuotaService { get; set; }
internal ITariffService TariffService { get; set; }
private static readonly List<string> thisCompAddresses = new List<string>();
internal IHttpContextAccessor HttpContextAccessor { get; set; }
internal CoreBaseSettings CoreBaseSettings { get; set; }
internal CoreSettings CoreSettings { get; set; }
static TenantManager()
{
thisCompAddresses.Add("localhost");
thisCompAddresses.Add(Dns.GetHostName().ToLowerInvariant());
thisCompAddresses.AddRange(Dns.GetHostAddresses("localhost").Select(a => a.ToString()));
try
{
thisCompAddresses.AddRange(Dns.GetHostAddresses(Dns.GetHostName()).Select(a => a.ToString()));
}
catch
{
// ignore
}
}
public TenantManager()
{
}
public TenantManager(
ITenantService tenantService,
IQuotaService quotaService,
ITariffService tariffService,
CoreBaseSettings coreBaseSettings,
CoreSettings coreSettings)
{
TenantService = tenantService;
QuotaService = quotaService;
TariffService = tariffService;
CoreBaseSettings = coreBaseSettings;
CoreSettings = coreSettings;
}
public TenantManager(
ITenantService tenantService,
IQuotaService quotaService,
ITariffService tariffService,
IHttpContextAccessor httpContextAccessor,
CoreBaseSettings coreBaseSettings,
CoreSettings coreSettings) : this(tenantService, quotaService, tariffService, coreBaseSettings, coreSettings)
{
HttpContextAccessor = httpContextAccessor;
}
public List<Tenant> GetTenants(bool active = true)
{
return TenantService.GetTenants(default, active).ToList();
}
public List<Tenant> GetTenants(List<int> ids)
}
public TenantManager(
ITenantService tenantService,
IQuotaService quotaService,
ITariffService tariffService,
CoreBaseSettings coreBaseSettings,
CoreSettings coreSettings)
{
TenantService = tenantService;
QuotaService = quotaService;
TariffService = tariffService;
CoreBaseSettings = coreBaseSettings;
CoreSettings = coreSettings;
}
public TenantManager(
ITenantService tenantService,
IQuotaService quotaService,
ITariffService tariffService,
IHttpContextAccessor httpContextAccessor,
CoreBaseSettings coreBaseSettings,
CoreSettings coreSettings) : this(tenantService, quotaService, tariffService, coreBaseSettings, coreSettings)
{
HttpContextAccessor = httpContextAccessor;
}
public List<Tenant> GetTenants(bool active = true)
{
return TenantService.GetTenants(default, active).ToList();
}
public List<Tenant> GetTenants(List<int> ids)
{
return TenantService.GetTenants(ids).ToList();
}
public Tenant GetTenant(int tenantId)
{
return TenantService.GetTenant(tenantId);
}
public Tenant GetTenant(string domain)
{
if (string.IsNullOrEmpty(domain))
{
return TenantService.GetTenants(ids).ToList();
return null;
}
public Tenant GetTenant(int tenantId)
{
return TenantService.GetTenant(tenantId);
}
public Tenant GetTenant(string domain)
{
if (string.IsNullOrEmpty(domain)) return null;
Tenant t = null;
if (thisCompAddresses.Contains(domain, StringComparer.InvariantCultureIgnoreCase))
{
t = TenantService.GetTenant("localhost");
}
var isAlias = false;
if (t == null)
{
var baseUrl = CoreSettings.BaseDomain;
if (!string.IsNullOrEmpty(baseUrl) && domain.EndsWith("." + baseUrl, StringComparison.InvariantCultureIgnoreCase))
{
isAlias = true;
t = TenantService.GetTenant(domain.Substring(0, domain.Length - baseUrl.Length - 1));
}
}
if (t == null)
{
t = TenantService.GetTenant(domain);
}
if (t == null && CoreBaseSettings.Standalone && !isAlias)
{
t = TenantService.GetTenantForStandaloneWithoutAlias(domain);
}
return t;
}
public Tenant SetTenantVersion(Tenant tenant, int version)
{
if (tenant == null) throw new ArgumentNullException(nameof(tenant));
if (tenant.Version != version)
{
tenant.Version = version;
SaveTenant(tenant);
}
else
{
throw new ArgumentException("This is current version already");
}
return tenant;
}
public Tenant SaveTenant(Tenant tenant)
{
var newTenant = TenantService.SaveTenant(CoreSettings, tenant);
if (CallContext.GetData(CURRENT_TENANT) is Tenant) SetCurrentTenant(newTenant);
return newTenant;
}
public void RemoveTenant(int tenantId, bool auto = false)
{
TenantService.RemoveTenant(tenantId, auto);
}
public Tenant GetCurrentTenant(HttpContext context)
{
return GetCurrentTenant(true, context);
}
public Tenant GetCurrentTenant(bool throwIfNotFound, HttpContext context)
Tenant t = null;
if (_thisCompAddresses.Contains(domain, StringComparer.InvariantCultureIgnoreCase))
{
if (CurrentTenant != null)
t = TenantService.GetTenant("localhost");
}
var isAlias = false;
if (t == null)
{
var baseUrl = CoreSettings.BaseDomain;
if (!string.IsNullOrEmpty(baseUrl) && domain.EndsWith("." + baseUrl, StringComparison.InvariantCultureIgnoreCase))
{
return CurrentTenant;
isAlias = true;
t = TenantService.GetTenant(domain.Substring(0, domain.Length - baseUrl.Length - 1));
}
}
if (t == null)
{
t = TenantService.GetTenant(domain);
}
if (t == null && CoreBaseSettings.Standalone && !isAlias)
{
t = TenantService.GetTenantForStandaloneWithoutAlias(domain);
}
return t;
}
public Tenant SetTenantVersion(Tenant tenant, int version)
{
if (tenant == null)
{
throw new ArgumentNullException(nameof(tenant));
}
if (tenant.Version != version)
{
tenant.Version = version;
SaveTenant(tenant);
}
else
{
throw new ArgumentException("This is current version already");
}
return tenant;
}
public Tenant SaveTenant(Tenant tenant)
{
var newTenant = TenantService.SaveTenant(CoreSettings, tenant);
if (CallContext.GetData(CurrentTenant) is Tenant)
{
SetCurrentTenant(newTenant);
}
return newTenant;
}
public void RemoveTenant(int tenantId, bool auto = false)
{
TenantService.RemoveTenant(tenantId, auto);
}
public Tenant GetCurrentTenant(HttpContext context)
{
return GetCurrentTenant(true, context);
}
public Tenant GetCurrentTenant(bool throwIfNotFound, HttpContext context)
{
if (_currentTenant != null)
{
return _currentTenant;
}
Tenant tenant = null;
if (context != null)
{
tenant = context.Items[CurrentTenant] as Tenant;
if (tenant == null && context.Request != null)
{
tenant = GetTenant(context.Request.GetUrlRewriter().Host);
context.Items[CurrentTenant] = tenant;
}
}
if (tenant == null && throwIfNotFound)
{
throw new Exception("Could not resolve current tenant :-(.");
}
_currentTenant = tenant;
return tenant;
}
public Tenant GetCurrentTenant()
{
return GetCurrentTenant(true);
}
public Tenant GetCurrentTenant(bool throwIfNotFound)
{
return GetCurrentTenant(throwIfNotFound, HttpContextAccessor?.HttpContext);
}
public void SetCurrentTenant(Tenant tenant)
{
if (tenant != null)
{
_currentTenant = tenant;
if (HttpContextAccessor?.HttpContext != null)
{
HttpContextAccessor.HttpContext.Items[CurrentTenant] = tenant;
}
Tenant tenant = null;
if (context != null)
{
tenant = context.Items[CURRENT_TENANT] as Tenant;
if (tenant == null && context.Request != null)
{
tenant = GetTenant(context.Request.GetUrlRewriter().Host);
context.Items[CURRENT_TENANT] = tenant;
}
}
if (tenant == null && throwIfNotFound)
{
throw new Exception("Could not resolve current tenant :-(.");
}
Thread.CurrentThread.CurrentCulture = tenant.GetCulture();
Thread.CurrentThread.CurrentUICulture = tenant.GetCulture();
}
}
CurrentTenant = tenant;
public Tenant SetCurrentTenant(int tenantId)
{
var result = GetTenant(tenantId);
SetCurrentTenant(result);
return tenant;
}
public Tenant GetCurrentTenant()
{
return GetCurrentTenant(true);
}
public Tenant GetCurrentTenant(bool throwIfNotFound)
{
return GetCurrentTenant(throwIfNotFound, HttpContextAccessor?.HttpContext);
}
public void SetCurrentTenant(Tenant tenant)
{
if (tenant != null)
{
CurrentTenant = tenant;
if (HttpContextAccessor?.HttpContext != null)
{
HttpContextAccessor.HttpContext.Items[CURRENT_TENANT] = tenant;
}
Thread.CurrentThread.CurrentCulture = tenant.GetCulture();
Thread.CurrentThread.CurrentUICulture = tenant.GetCulture();
}
}
public Tenant SetCurrentTenant(int tenantId)
{
var result = GetTenant(tenantId);
SetCurrentTenant(result);
return result;
}
public Tenant SetCurrentTenant(string domain)
{
var result = GetTenant(domain);
SetCurrentTenant(result);
return result;
}
public void CheckTenantAddress(string address)
{
TenantService.ValidateDomain(address);
}
public IEnumerable<TenantVersion> GetTenantVersions()
{
return TenantService.GetTenantVersions();
}
public IEnumerable<TenantQuota> GetTenantQuotas()
{
return GetTenantQuotas(false);
}
public IEnumerable<TenantQuota> GetTenantQuotas(bool all)
{
return QuotaService.GetTenantQuotas().Where(q => q.Id < 0 && (all || q.Visible)).OrderByDescending(q => q.Id).ToList();
}
return result;
}
public TenantQuota GetTenantQuota(int tenant)
public Tenant SetCurrentTenant(string domain)
{
var result = GetTenant(domain);
SetCurrentTenant(result);
return result;
}
public void CheckTenantAddress(string address)
{
TenantService.ValidateDomain(address);
}
public IEnumerable<TenantVersion> GetTenantVersions()
{
return TenantService.GetTenantVersions();
}
public IEnumerable<TenantQuota> GetTenantQuotas()
{
return GetTenantQuotas(false);
}
public IEnumerable<TenantQuota> GetTenantQuotas(bool all)
{
return QuotaService.GetTenantQuotas().Where(q => q.Tenant < 0 && (all || q.Visible)).OrderByDescending(q => q.Tenant).ToList();
}
public TenantQuota GetTenantQuota(int tenant)
{
var defaultQuota = QuotaService.GetTenantQuota(tenant) ?? QuotaService.GetTenantQuota(Tenant.DefaultTenant) ?? TenantQuota.Default;
if (defaultQuota.Tenant != tenant && TariffService != null)
{
var defaultQuota = QuotaService.GetTenantQuota(tenant) ?? QuotaService.GetTenantQuota(Tenant.DEFAULT_TENANT) ?? TenantQuota.Default;
if (defaultQuota.Id != tenant && TariffService != null)
var tariff = TariffService.GetTariff(tenant);
var currentQuota = QuotaService.GetTenantQuota(tariff.QuotaId);
if (currentQuota != null)
{
var tariff = TariffService.GetTariff(tenant);
var currentQuota = QuotaService.GetTenantQuota(tariff.QuotaId);
if (currentQuota != null)
currentQuota = (TenantQuota)currentQuota.Clone();
if (currentQuota.ActiveUsers == -1)
{
currentQuota = (TenantQuota)currentQuota.Clone();
if (currentQuota.ActiveUsers == -1)
{
currentQuota.ActiveUsers = tariff.Quantity;
currentQuota.MaxTotalSize *= currentQuota.ActiveUsers;
}
return currentQuota;
currentQuota.ActiveUsers = tariff.Quantity;
currentQuota.MaxTotalSize *= currentQuota.ActiveUsers;
}
return currentQuota;
}
return defaultQuota;
}
public IDictionary<string, Dictionary<string, decimal>> GetProductPriceInfo(bool all = true)
{
var productIds = GetTenantQuotas(all)
.Select(p => p.AvangateId)
.Where(id => !string.IsNullOrEmpty(id))
.Distinct()
.ToArray();
return TariffService.GetProductPriceInfo(productIds);
}
public TenantQuota SaveTenantQuota(TenantQuota quota)
{
quota = QuotaService.SaveTenantQuota(quota);
return quota;
}
public void SetTenantQuotaRow(TenantQuotaRow row, bool exchange)
{
QuotaService.SetTenantQuotaRow(row, exchange);
}
public List<TenantQuotaRow> FindTenantQuotaRows(int tenantId)
{
return QuotaService.FindTenantQuotaRows(tenantId).ToList();
}
}
return defaultQuota;
}
public IDictionary<string, Dictionary<string, decimal>> GetProductPriceInfo(bool all = true)
{
var productIds = GetTenantQuotas(all)
.Select(p => p.AvangateId)
.Where(id => !string.IsNullOrEmpty(id))
.Distinct()
.ToArray();
return TariffService.GetProductPriceInfo(productIds);
}
public TenantQuota SaveTenantQuota(TenantQuota quota)
{
quota = QuotaService.SaveTenantQuota(quota);
return quota;
}
public void SetTenantQuotaRow(TenantQuotaRow row, bool exchange)
{
QuotaService.SetTenantQuotaRow(row, exchange);
}
public List<TenantQuotaRow> FindTenantQuotaRows(int tenantId)
{
return QuotaService.FindTenantQuotaRows(tenantId).ToList();
}
}

File diff suppressed because it is too large Load Diff

View File

@ -23,352 +23,361 @@
*
*/
namespace ASC.Core
namespace ASC.Core;
[Scope]
public class SecurityContext
{
[Scope]
public class SecurityContext
private readonly ILog _logger;
public IAccount CurrentAccount => _authContext.CurrentAccount;
public bool IsAuthenticated => _authContext.IsAuthenticated;
private readonly UserManager _userManager;
private readonly AuthManager _authentication;
private readonly AuthContext _authContext;
private readonly TenantManager _tenantManager;
private readonly UserFormatter _userFormatter;
private readonly CookieStorage _cookieStorage;
private readonly TenantCookieSettingsHelper _tenantCookieSettingsHelper;
private readonly IHttpContextAccessor _httpContextAccessor;
public SecurityContext(
UserManager userManager,
AuthManager authentication,
AuthContext authContext,
TenantManager tenantManager,
UserFormatter userFormatter,
CookieStorage cookieStorage,
TenantCookieSettingsHelper tenantCookieSettingsHelper,
IOptionsMonitor<ILog> options
)
{
private readonly ILog log;
_logger = options.CurrentValue;
_userManager = userManager;
_authentication = authentication;
_authContext = authContext;
_tenantManager = tenantManager;
_userFormatter = userFormatter;
_cookieStorage = cookieStorage;
_tenantCookieSettingsHelper = tenantCookieSettingsHelper;
}
public SecurityContext(
IHttpContextAccessor httpContextAccessor,
UserManager userManager,
AuthManager authentication,
AuthContext authContext,
TenantManager tenantManager,
UserFormatter userFormatter,
CookieStorage cookieStorage,
TenantCookieSettingsHelper tenantCookieSettingsHelper,
IOptionsMonitor<ILog> options
) : this(userManager, authentication, authContext, tenantManager, userFormatter, cookieStorage, tenantCookieSettingsHelper, options)
{
_httpContextAccessor = httpContextAccessor;
}
public IAccount CurrentAccount
public string AuthenticateMe(string login, string passwordHash)
{
if (login == null)
{
get => AuthContext.CurrentAccount;
throw new ArgumentNullException(nameof(login));
}
public bool IsAuthenticated
if (passwordHash == null)
{
get => AuthContext.IsAuthenticated;
throw new ArgumentNullException(nameof(passwordHash));
}
private UserManager UserManager { get; }
private AuthManager Authentication { get; }
private AuthContext AuthContext { get; }
private TenantManager TenantManager { get; }
private UserFormatter UserFormatter { get; }
private CookieStorage CookieStorage { get; }
private TenantCookieSettingsHelper TenantCookieSettingsHelper { get; }
private IHttpContextAccessor HttpContextAccessor { get; }
var tenantid = _tenantManager.GetCurrentTenant().Id;
var u = _userManager.GetUsersByPasswordHash(tenantid, login, passwordHash);
public SecurityContext(
UserManager userManager,
AuthManager authentication,
AuthContext authContext,
TenantManager tenantManager,
UserFormatter userFormatter,
CookieStorage cookieStorage,
TenantCookieSettingsHelper tenantCookieSettingsHelper,
IOptionsMonitor<ILog> options
)
return AuthenticateMe(new UserAccount(u, tenantid, _userFormatter));
}
public bool AuthenticateMe(string cookie)
{
if (!string.IsNullOrEmpty(cookie))
{
log = options.CurrentValue;
UserManager = userManager;
Authentication = authentication;
AuthContext = authContext;
TenantManager = tenantManager;
UserFormatter = userFormatter;
CookieStorage = cookieStorage;
TenantCookieSettingsHelper = tenantCookieSettingsHelper;
}
public SecurityContext(
IHttpContextAccessor httpContextAccessor,
UserManager userManager,
AuthManager authentication,
AuthContext authContext,
TenantManager tenantManager,
UserFormatter userFormatter,
CookieStorage cookieStorage,
TenantCookieSettingsHelper tenantCookieSettingsHelper,
IOptionsMonitor<ILog> options
) : this(userManager, authentication, authContext, tenantManager, userFormatter, cookieStorage, tenantCookieSettingsHelper, options)
{
HttpContextAccessor = httpContextAccessor;
}
public string AuthenticateMe(string login, string passwordHash)
{
if (login == null) throw new ArgumentNullException(nameof(login));
if (passwordHash == null) throw new ArgumentNullException(nameof(passwordHash));
var tenantid = TenantManager.GetCurrentTenant().TenantId;
var u = UserManager.GetUsersByPasswordHash(tenantid, login, passwordHash);
return AuthenticateMe(new UserAccount(u, tenantid, UserFormatter));
}
public bool AuthenticateMe(string cookie)
{
if (!string.IsNullOrEmpty(cookie))
if (cookie.Equals("Bearer", StringComparison.InvariantCulture))
{
if (cookie.Equals("Bearer", StringComparison.InvariantCulture))
var ipFrom = string.Empty;
var address = string.Empty;
if (_httpContextAccessor?.HttpContext != null)
{
var ipFrom = string.Empty;
var address = string.Empty;
if (HttpContextAccessor?.HttpContext != null)
var request = _httpContextAccessor?.HttpContext.Request;
if (request == null)
{
var request = HttpContextAccessor?.HttpContext.Request;
if (request == null) throw new ArgumentNullException("request");
ipFrom = "from " + (request.Headers["X-Forwarded-For"].ToString() ?? request.GetUserHostAddress());
address = "for " + request.GetUrlRewriter();
throw new ArgumentNullException(nameof(request));
}
log.InfoFormat("Empty Bearer cookie: {0} {1}", ipFrom, address);
ipFrom = "from " + (request.Headers["X-Forwarded-For"].ToString() ?? request.GetUserHostAddress());
address = "for " + request.GetUrlRewriter();
}
else if (CookieStorage.DecryptCookie(cookie, out var tenant, out var userid, out var indexTenant, out var expire, out var indexUser))
_logger.InfoFormat("Empty Bearer cookie: {0} {1}", ipFrom, address);
}
else if (_cookieStorage.DecryptCookie(cookie, out var tenant, out var userid, out var indexTenant, out var expire, out var indexUser))
{
if (tenant != _tenantManager.GetCurrentTenant().Id)
{
if (tenant != TenantManager.GetCurrentTenant().TenantId)
return false;
}
var settingsTenant = _tenantCookieSettingsHelper.GetForTenant(tenant);
if (indexTenant != settingsTenant.Index)
{
return false;
}
if (expire != DateTime.MaxValue && expire < DateTime.UtcNow)
{
return false;
}
try
{
var settingsUser = _tenantCookieSettingsHelper.GetForUser(userid);
if (indexUser != settingsUser.Index)
{
return false;
}
var settingsTenant = TenantCookieSettingsHelper.GetForTenant(tenant);
if (indexTenant != settingsTenant.Index)
{
return false;
}
AuthenticateMeWithoutCookie(new UserAccount(new UserInfo { Id = userid }, tenant, _userFormatter));
if (expire != DateTime.MaxValue && expire < DateTime.UtcNow)
{
return false;
}
try
{
var settingsUser = TenantCookieSettingsHelper.GetForUser(userid);
if (indexUser != settingsUser.Index)
{
return false;
}
AuthenticateMeWithoutCookie(new UserAccount(new UserInfo { ID = userid }, tenant, UserFormatter));
return true;
}
catch (InvalidCredentialException ice)
{
log.DebugFormat("{0}: cookie {1}, tenant {2}, userid {3}", ice.Message, cookie, tenant, userid);
}
catch (SecurityException se)
{
log.DebugFormat("{0}: cookie {1}, tenant {2}, userid {3}", se.Message, cookie, tenant, userid);
}
catch (Exception err)
{
log.ErrorFormat("Authenticate error: cookie {0}, tenant {1}, userid {2}, : {3}", cookie, tenant, userid, err);
}
return true;
}
else
catch (InvalidCredentialException ice)
{
var ipFrom = string.Empty;
var address = string.Empty;
if (HttpContextAccessor?.HttpContext != null)
{
var request = HttpContextAccessor?.HttpContext.Request;
if (request == null) throw new ArgumentNullException("request");
address = "for " + request.GetUrlRewriter();
ipFrom = "from " + (request.Headers["X-Forwarded-For"].ToString() ?? request.GetUserHostAddress());
}
log.WarnFormat("Can not decrypt cookie: {0} {1} {2}", cookie, ipFrom, address);
_logger.DebugFormat("{0}: cookie {1}, tenant {2}, userid {3}", ice.Message, cookie, tenant, userid);
}
catch (SecurityException se)
{
_logger.DebugFormat("{0}: cookie {1}, tenant {2}, userid {3}", se.Message, cookie, tenant, userid);
}
catch (Exception err)
{
_logger.ErrorFormat("Authenticate error: cookie {0}, tenant {1}, userid {2}, : {3}", cookie, tenant, userid, err);
}
}
return false;
else
{
var ipFrom = string.Empty;
var address = string.Empty;
if (_httpContextAccessor?.HttpContext != null)
{
var request = _httpContextAccessor?.HttpContext.Request;
if (request == null)
{
throw new ArgumentNullException(nameof(request));
}
address = "for " + request.GetUrlRewriter();
ipFrom = "from " + (request.Headers["X-Forwarded-For"].ToString() ?? request.GetUserHostAddress());
}
_logger.WarnFormat("Can not decrypt cookie: {0} {1} {2}", cookie, ipFrom, address);
}
}
public string AuthenticateMe(IAccount account, List<Claim> additionalClaims = null)
return false;
}
public string AuthenticateMe(IAccount account, List<Claim> additionalClaims = null)
{
AuthenticateMeWithoutCookie(account, additionalClaims);
string cookie = null;
if (account is IUserAccount)
{
AuthenticateMeWithoutCookie(account, additionalClaims);
string cookie = null;
if (account is IUserAccount)
{
cookie = CookieStorage.EncryptCookie(TenantManager.GetCurrentTenant().TenantId, account.ID);
}
return cookie;
cookie = _cookieStorage.EncryptCookie(_tenantManager.GetCurrentTenant().Id, account.ID);
}
public void AuthenticateMeWithoutCookie(IAccount account, List<Claim> additionalClaims = null)
return cookie;
}
public void AuthenticateMeWithoutCookie(IAccount account, List<Claim> additionalClaims = null)
{
if (account == null || account.Equals(Configuration.Constants.Guest))
{
if (account == null || account.Equals(Configuration.Constants.Guest)) throw new InvalidCredentialException("account");
throw new InvalidCredentialException("account");
}
var roles = new List<string> { Role.Everyone };
var roles = new List<string> { Role.Everyone };
if (account is ISystemAccount && account.ID == Configuration.Constants.CoreSystem.ID)
if (account is ISystemAccount && account.ID == Configuration.Constants.CoreSystem.ID)
{
roles.Add(Role.System);
}
if (account is IUserAccount)
{
var tenant = _tenantManager.GetCurrentTenant();
var u = _userManager.GetUsers(account.ID);
if (u.Id == Users.Constants.LostUser.Id)
{
roles.Add(Role.System);
throw new InvalidCredentialException("Invalid username or password.");
}
if (u.Status != EmployeeStatus.Active)
{
throw new SecurityException("Account disabled.");
}
if (account is IUserAccount)
// for LDAP users only
if (u.Sid != null)
{
var tenant = TenantManager.GetCurrentTenant();
var u = UserManager.GetUsers(account.ID);
if (u.ID == Users.Constants.LostUser.ID)
if (!_tenantManager.GetTenantQuota(tenant.Id).Ldap)
{
throw new InvalidCredentialException("Invalid username or password.");
throw new BillingException("Your tariff plan does not support this option.", "Ldap");
}
if (u.Status != EmployeeStatus.Active)
{
throw new SecurityException("Account disabled.");
}
// for LDAP users only
if (u.Sid != null)
{
if (!TenantManager.GetTenantQuota(tenant.TenantId).Ldap)
{
throw new BillingException("Your tariff plan does not support this option.", "Ldap");
}
}
if (UserManager.IsUserInGroup(u.ID, Users.Constants.GroupAdmin.ID))
{
roles.Add(Role.Administrators);
}
roles.Add(Role.Users);
account = new UserAccount(u, TenantManager.GetCurrentTenant().TenantId, UserFormatter);
}
var claims = new List<Claim>
if (_userManager.IsUserInGroup(u.Id, Users.Constants.GroupAdmin.ID))
{
roles.Add(Role.Administrators);
}
roles.Add(Role.Users);
account = new UserAccount(u, _tenantManager.GetCurrentTenant().Id, _userFormatter);
}
var claims = new List<Claim>
{
new Claim(ClaimTypes.Sid, account.ID.ToString()),
new Claim(ClaimTypes.Name, account.Name)
};
claims.AddRange(roles.Select(r => new Claim(ClaimTypes.Role, r)));
claims.AddRange(roles.Select(r => new Claim(ClaimTypes.Role, r)));
if (additionalClaims != null)
{
claims.AddRange(additionalClaims);
}
AuthContext.Principal = new CustomClaimsPrincipal(new ClaimsIdentity(account, claims), account);
}
public string AuthenticateMe(Guid userId, List<Claim> additionalClaims = null)
if (additionalClaims != null)
{
var account = Authentication.GetAccountByID(TenantManager.GetCurrentTenant().TenantId, userId);
return AuthenticateMe(account, additionalClaims);
claims.AddRange(additionalClaims);
}
public void AuthenticateMeWithoutCookie(Guid userId, List<Claim> additionalClaims = null)
{
var account = Authentication.GetAccountByID(TenantManager.GetCurrentTenant().TenantId, userId);
AuthenticateMeWithoutCookie(account, additionalClaims);
}
public void Logout()
{
AuthContext.Logout();
}
public void SetUserPasswordHash(Guid userID, string passwordHash)
{
var tenantid = TenantManager.GetCurrentTenant().TenantId;
var u = UserManager.GetUsersByPasswordHash(tenantid, userID.ToString(), passwordHash);
if (!Equals(u, Users.Constants.LostUser))
{
throw new PasswordException("A new password must be used");
}
Authentication.SetUserPasswordHash(userID, passwordHash);
}
public class PasswordException : Exception
{
public PasswordException(string message) : base(message)
{
}
}
_authContext.Principal = new CustomClaimsPrincipal(new ClaimsIdentity(account, claims), account);
}
[Scope]
public class PermissionContext
public string AuthenticateMe(Guid userId, List<Claim> additionalClaims = null)
{
public IPermissionResolver PermissionResolver { get; set; }
private AuthContext AuthContext { get; }
var account = _authentication.GetAccountByID(_tenantManager.GetCurrentTenant().Id, userId);
public PermissionContext(IPermissionResolver permissionResolver, AuthContext authContext)
{
PermissionResolver = permissionResolver;
AuthContext = authContext;
}
public bool CheckPermissions(params IAction[] actions)
{
return PermissionResolver.Check(AuthContext.CurrentAccount, actions);
}
public bool CheckPermissions(ISecurityObject securityObject, params IAction[] actions)
{
return CheckPermissions(securityObject, null, actions);
}
public bool CheckPermissions(ISecurityObjectId objectId, ISecurityObjectProvider securityObjProvider, params IAction[] actions)
{
return PermissionResolver.Check(AuthContext.CurrentAccount, objectId, securityObjProvider, actions);
}
public void DemandPermissions(params IAction[] actions)
{
PermissionResolver.Demand(AuthContext.CurrentAccount, actions);
}
public void DemandPermissions(ISecurityObject securityObject, params IAction[] actions)
{
DemandPermissions(securityObject, null, actions);
}
public void DemandPermissions(ISecurityObjectId objectId, ISecurityObjectProvider securityObjProvider, params IAction[] actions)
{
PermissionResolver.Demand(AuthContext.CurrentAccount, objectId, securityObjProvider, actions);
}
return AuthenticateMe(account, additionalClaims);
}
[Scope]
public class AuthContext
public void AuthenticateMeWithoutCookie(Guid userId, List<Claim> additionalClaims = null)
{
private IHttpContextAccessor HttpContextAccessor { get; }
var account = _authentication.GetAccountByID(_tenantManager.GetCurrentTenant().Id, userId);
public AuthContext()
AuthenticateMeWithoutCookie(account, additionalClaims);
}
public void Logout()
{
_authContext.Logout();
}
public void SetUserPasswordHash(Guid userID, string passwordHash)
{
var tenantid = _tenantManager.GetCurrentTenant().Id;
var u = _userManager.GetUsersByPasswordHash(tenantid, userID.ToString(), passwordHash);
if (!Equals(u, Users.Constants.LostUser))
{
throw new PasswordException("A new password must be used");
}
public AuthContext(IHttpContextAccessor httpContextAccessor)
{
HttpContextAccessor = httpContextAccessor;
}
_authentication.SetUserPasswordHash(userID, passwordHash);
}
public IAccount CurrentAccount
{
get { return Principal?.Identity is IAccount ? (IAccount)Principal.Identity : Configuration.Constants.Guest; }
}
public class PasswordException : Exception
{
public PasswordException(string message) : base(message) { }
}
}
public bool IsAuthenticated
{
get { return CurrentAccount.IsAuthenticated; }
}
[Scope]
public class PermissionContext
{
public IPermissionResolver PermissionResolver { get; set; }
private AuthContext AuthContext { get; }
public void Logout()
{
Principal = null;
}
public PermissionContext(IPermissionResolver permissionResolver, AuthContext authContext)
{
PermissionResolver = permissionResolver;
AuthContext = authContext;
}
internal ClaimsPrincipal Principal
public bool CheckPermissions(params IAction[] actions)
{
return PermissionResolver.Check(AuthContext.CurrentAccount, actions);
}
public bool CheckPermissions(ISecurityObject securityObject, params IAction[] actions)
{
return CheckPermissions(securityObject, null, actions);
}
public bool CheckPermissions(ISecurityObjectId objectId, ISecurityObjectProvider securityObjProvider, params IAction[] actions)
{
return PermissionResolver.Check(AuthContext.CurrentAccount, objectId, securityObjProvider, actions);
}
public void DemandPermissions(params IAction[] actions)
{
PermissionResolver.Demand(AuthContext.CurrentAccount, actions);
}
public void DemandPermissions(ISecurityObject securityObject, params IAction[] actions)
{
DemandPermissions(securityObject, null, actions);
}
public void DemandPermissions(ISecurityObjectId objectId, ISecurityObjectProvider securityObjProvider, params IAction[] actions)
{
PermissionResolver.Demand(AuthContext.CurrentAccount, objectId, securityObjProvider, actions);
}
}
[Scope]
public class AuthContext
{
private IHttpContextAccessor HttpContextAccessor { get; }
public AuthContext()
{
}
public AuthContext(IHttpContextAccessor httpContextAccessor)
{
HttpContextAccessor = httpContextAccessor;
}
public IAccount CurrentAccount => Principal?.Identity is IAccount ? (IAccount)Principal.Identity : Configuration.Constants.Guest;
public bool IsAuthenticated => CurrentAccount.IsAuthenticated;
public void Logout()
{
Principal = null;
}
internal ClaimsPrincipal Principal
{
get => Thread.CurrentPrincipal as ClaimsPrincipal ?? HttpContextAccessor?.HttpContext?.User;
set
{
get => Thread.CurrentPrincipal as ClaimsPrincipal ?? HttpContextAccessor?.HttpContext?.User;
set
Thread.CurrentPrincipal = value;
if (HttpContextAccessor?.HttpContext != null)
{
Thread.CurrentPrincipal = value;
if (HttpContextAccessor?.HttpContext != null) HttpContextAccessor.HttpContext.User = value;
HttpContextAccessor.HttpContext.User = value;
}
}
}
}
}

View File

@ -27,139 +27,138 @@
using Constants = ASC.Core.Configuration.Constants;
using NotifyContext = ASC.Notify.Context;
namespace ASC.Core
{
public static class WorkContext
{
private static readonly object syncRoot = new object();
private static bool notifyStarted;
private static bool? ismono;
private static string monoversion;
public static NotifyContext NotifyContext { get; private set; }
public static string[] DefaultClientSenders
{
get { return new[] { Constants.NotifyEMailSenderSysName, }; }
}
public static bool IsMono
{
get
{
if (ismono.HasValue)
{
return ismono.Value;
}
var monoRuntime = Type.GetType("Mono.Runtime");
ismono = monoRuntime != null;
if (monoRuntime != null)
{
var dispalayName = monoRuntime.GetMethod("GetDisplayName", BindingFlags.NonPublic | BindingFlags.Static);
if (dispalayName != null)
{
monoversion = dispalayName.Invoke(null, null) as string;
}
}
return ismono.Value;
}
}
public static string MonoVersion
{
get
{
return IsMono ? monoversion : null;
}
}
public static void NotifyStartUp(IServiceProvider serviceProvider)
{
if (notifyStarted) return;
lock (syncRoot)
{
if (notifyStarted) return;
var configuration = serviceProvider.GetService<IConfiguration>();
var cacheNotify = serviceProvider.GetService<ICacheNotify<NotifyMessage>>();
var cacheInvoke = serviceProvider.GetService<ICacheNotify<NotifyInvoke>>();
var options = serviceProvider.GetService<IOptionsMonitor<ILog>>();
NotifyContext = new NotifyContext(serviceProvider);
INotifySender jabberSender = new NotifyServiceSender(cacheNotify, cacheInvoke);
INotifySender emailSender = new NotifyServiceSender(cacheNotify, cacheInvoke);
INotifySender telegramSender = new TelegramSender(options, serviceProvider);
var postman = configuration["core:notify:postman"];
if ("ases".Equals(postman, StringComparison.InvariantCultureIgnoreCase) || "smtp".Equals(postman, StringComparison.InvariantCultureIgnoreCase))
{
jabberSender = new JabberSender(serviceProvider);
var properties = new Dictionary<string, string>
{
["useCoreSettings"] = "true"
};
if ("ases".Equals(postman, StringComparison.InvariantCultureIgnoreCase))
{
emailSender = new AWSSender(serviceProvider, options);
properties["accessKey"] = configuration["ses:accessKey"];
properties["secretKey"] = configuration["ses:secretKey"];
properties["refreshTimeout"] = configuration["ses:refreshTimeout"];
}
else
{
emailSender = new SmtpSender(serviceProvider, options);
}
emailSender.Init(properties);
}
NotifyContext.NotifyService.RegisterSender(Constants.NotifyEMailSenderSysName, new EmailSenderSink(emailSender, serviceProvider, options));
NotifyContext.NotifyService.RegisterSender(Constants.NotifyMessengerSenderSysName, new JabberSenderSink(jabberSender, serviceProvider));
NotifyContext.NotifyService.RegisterSender(Constants.NotifyTelegramSenderSysName, new TelegramSenderSink(telegramSender, serviceProvider));
NotifyContext.NotifyEngine.BeforeTransferRequest += NotifyEngine_BeforeTransferRequest;
NotifyContext.NotifyEngine.AfterTransferRequest += NotifyEngine_AfterTransferRequest;
notifyStarted = true;
}
}
public static void RegisterSendMethod(Action<DateTime> method, string cron)
{
NotifyContext.NotifyEngine.RegisterSendMethod(method, cron);
}
public static void UnregisterSendMethod(Action<DateTime> method)
{
NotifyContext.NotifyEngine.UnregisterSendMethod(method);
}
private static void NotifyEngine_BeforeTransferRequest(NotifyEngine sender, NotifyRequest request, IServiceScope serviceScope)
{
request.Properties.Add("Tenant", serviceScope.ServiceProvider.GetService<TenantManager>().GetCurrentTenant(false));
}
private static void NotifyEngine_AfterTransferRequest(NotifyEngine sender, NotifyRequest request, IServiceScope scope)
{
if ((request.Properties.Contains("Tenant") ? request.Properties["Tenant"] : null) is Tenant tenant)
{
var tenantManager = scope.ServiceProvider.GetService<TenantManager>();
tenantManager.SetCurrentTenant(tenant);
}
}
namespace ASC.Core;
public static class WorkContext
{
private static readonly object _syncRoot = new object();
private static bool _notifyStarted;
private static bool? _isMono;
private static string _monoVersion;
public static NotifyContext NotifyContext { get; private set; }
public static string[] DefaultClientSenders => new[] { Constants.NotifyEMailSenderSysName, };
public static bool IsMono
{
get
{
if (_isMono.HasValue)
{
return _isMono.Value;
}
var monoRuntime = Type.GetType("Mono.Runtime");
_isMono = monoRuntime != null;
if (monoRuntime != null)
{
var dispalayName = monoRuntime.GetMethod("GetDisplayName", BindingFlags.NonPublic | BindingFlags.Static);
if (dispalayName != null)
{
_monoVersion = dispalayName.Invoke(null, null) as string;
}
}
return _isMono.Value;
}
}
public static class WorkContextExtension
public static string MonoVersion => IsMono ? _monoVersion : null;
public static void NotifyStartUp(IServiceProvider serviceProvider)
{
public static void Register(DIHelper dIHelper)
if (_notifyStarted)
{
dIHelper.TryAdd<TelegramHelper>();
dIHelper.TryAdd<EmailSenderSinkScope>();
dIHelper.TryAdd<JabberSenderSinkScope>();
return;
}
}
}
lock (_syncRoot)
{
if (_notifyStarted)
{
return;
}
var configuration = serviceProvider.GetService<IConfiguration>();
var cacheNotify = serviceProvider.GetService<ICacheNotify<NotifyMessage>>();
var cacheInvoke = serviceProvider.GetService<ICacheNotify<NotifyInvoke>>();
var options = serviceProvider.GetService<IOptionsMonitor<ILog>>();
NotifyContext = new NotifyContext(serviceProvider);
INotifySender jabberSender = new NotifyServiceSender(cacheNotify, cacheInvoke);
INotifySender emailSender = new NotifyServiceSender(cacheNotify, cacheInvoke);
INotifySender telegramSender = new TelegramSender(options, serviceProvider);
var postman = configuration["core:notify:postman"];
if ("ases".Equals(postman, StringComparison.InvariantCultureIgnoreCase) || "smtp".Equals(postman, StringComparison.InvariantCultureIgnoreCase))
{
jabberSender = new JabberSender(serviceProvider);
var properties = new Dictionary<string, string>
{
["useCoreSettings"] = "true"
};
if ("ases".Equals(postman, StringComparison.InvariantCultureIgnoreCase))
{
emailSender = new AWSSender(serviceProvider, options);
properties["accessKey"] = configuration["ses:accessKey"];
properties["secretKey"] = configuration["ses:secretKey"];
properties["refreshTimeout"] = configuration["ses:refreshTimeout"];
}
else
{
emailSender = new SmtpSender(serviceProvider, options);
}
emailSender.Init(properties);
}
NotifyContext.NotifyService.RegisterSender(Constants.NotifyEMailSenderSysName, new EmailSenderSink(emailSender, serviceProvider, options));
NotifyContext.NotifyService.RegisterSender(Constants.NotifyMessengerSenderSysName, new JabberSenderSink(jabberSender, serviceProvider));
NotifyContext.NotifyService.RegisterSender(Constants.NotifyTelegramSenderSysName, new TelegramSenderSink(telegramSender, serviceProvider));
NotifyContext.NotifyEngine.BeforeTransferRequest += NotifyEngine_BeforeTransferRequest;
NotifyContext.NotifyEngine.AfterTransferRequest += NotifyEngine_AfterTransferRequest;
_notifyStarted = true;
}
}
public static void RegisterSendMethod(Action<DateTime> method, string cron)
{
NotifyContext.NotifyEngine.RegisterSendMethod(method, cron);
}
public static void UnregisterSendMethod(Action<DateTime> method)
{
NotifyContext.NotifyEngine.UnregisterSendMethod(method);
}
private static void NotifyEngine_BeforeTransferRequest(NotifyEngine sender, NotifyRequest request, IServiceScope serviceScope)
{
request.Properties.Add("Tenant", serviceScope.ServiceProvider.GetService<TenantManager>().GetCurrentTenant(false));
}
private static void NotifyEngine_AfterTransferRequest(NotifyEngine sender, NotifyRequest request, IServiceScope scope)
{
if ((request.Properties.Contains("Tenant") ? request.Properties["Tenant"] : null) is Tenant tenant)
{
var tenantManager = scope.ServiceProvider.GetService<TenantManager>();
tenantManager.SetCurrentTenant(tenant);
}
}
}
public static class WorkContextExtension
{
public static void Register(DIHelper dIHelper)
{
dIHelper.TryAdd<TelegramHelper>();
dIHelper.TryAdd<EmailSenderSinkScope>();
dIHelper.TryAdd<JabberSenderSinkScope>();
}
}

View File

@ -23,103 +23,88 @@
*
*/
namespace ASC.Core
{
[Serializable]
public class AzRecord
{
public Guid SubjectId { get; set; }
public Guid ActionId { get; set; }
public string ObjectId { get; set; }
public AceType Reaction { get; set; }
public int Tenant { get; set; }
namespace ASC.Core;
[Serializable]
public class AzRecord : IMapFrom<Acl>
{
public Guid Subject { get; set; }
public Guid Action { get; set; }
public string Object { get; set; }
public AceType AceType { get; set; }
public int Tenant { get; set; }
public AzRecord() { }
public AzRecord(Guid subjectId, Guid actionId, AceType reaction)
: this(subjectId, actionId, reaction, default(string))
{
}
public AzRecord(Guid subjectId, Guid actionId, AceType reaction, string fullId)
{
Subject = subjectId;
Action = actionId;
AceType = reaction;
Object = fullId;
}
public static implicit operator AzRecord(AzRecordCache cache)
{
var result = new AzRecord()
{
Tenant = cache.Tenant
};
public AzRecord()
{
}
public AzRecord(Guid subjectId, Guid actionId, AceType reaction)
: this(subjectId, actionId, reaction, default(string))
{
}
public AzRecord(Guid subjectId, Guid actionId, AceType reaction, ISecurityObjectId objectId)
: this(subjectId, actionId, reaction, AzObjectIdHelper.GetFullObjectId(objectId))
{
}
internal AzRecord(Guid subjectId, Guid actionId, AceType reaction, string objectId)
{
SubjectId = subjectId;
ActionId = actionId;
Reaction = reaction;
ObjectId = objectId;
if (Guid.TryParse(cache.SubjectId, out var subjectId))
{
result.Subject = subjectId;
}
public static implicit operator AzRecord(AzRecordCache cache)
if (Guid.TryParse(cache.ActionId, out var actionId))
{
var result = new AzRecord()
{
Tenant = cache.Tenant
};
if (Guid.TryParse(cache.SubjectId, out var subjectId))
{
result.SubjectId = subjectId;
}
if (Guid.TryParse(cache.ActionId, out var actionId))
{
result.ActionId = actionId;
}
result.ObjectId = cache.ObjectId;
if (Enum.TryParse<AceType>(cache.Reaction, out var reaction))
{
result.Reaction = reaction;
}
return result;
result.Action = actionId;
}
public static implicit operator AzRecordCache(AzRecord cache)
result.Object = cache.ObjectId;
if (Enum.TryParse<AceType>(cache.Reaction, out var reaction))
{
return new AzRecordCache
{
SubjectId = cache.SubjectId.ToString(),
ActionId = cache.ActionId.ToString(),
ObjectId = cache.ObjectId,
Reaction = cache.Reaction.ToString(),
Tenant = cache.Tenant
};
}
public override bool Equals(object obj)
{
return obj is AzRecord r &&
r.Tenant == Tenant &&
r.SubjectId == SubjectId &&
r.ActionId == ActionId &&
r.ObjectId == ObjectId &&
r.Reaction == Reaction;
}
public override int GetHashCode()
{
return Tenant.GetHashCode() ^
SubjectId.GetHashCode() ^
ActionId.GetHashCode() ^
(ObjectId ?? string.Empty).GetHashCode() ^
Reaction.GetHashCode();
}
}
result.AceType = reaction;
}
return result;
}
public static implicit operator AzRecordCache(AzRecord cache)
{
return new AzRecordCache
{
SubjectId = cache.Subject.ToString(),
ActionId = cache.Action.ToString(),
ObjectId = cache.Object,
Reaction = cache.AceType.ToString(),
Tenant = cache.Tenant
};
}
public override bool Equals(object obj)
{
return obj is AzRecord r &&
r.Tenant == Tenant &&
r.Subject == Subject &&
r.Action == Action &&
r.Object == Object &&
r.AceType == AceType;
}
public override int GetHashCode()
{
return Tenant.GetHashCode() ^
Subject.GetHashCode() ^
Action.GetHashCode() ^
(Object ?? string.Empty).GetHashCode() ^
AceType.GetHashCode();
}
}

View File

@ -23,326 +23,326 @@
*
*/
namespace TMResourceData
{
public class DBResourceManager : ResourceManager
{
public static readonly bool WhiteLableEnabled = false;
private readonly ConcurrentDictionary<string, ResourceSet> resourceSets = new ConcurrentDictionary<string, ResourceSet>();
public DBResourceManager(string filename, Assembly assembly)
: base(filename, assembly)
{
}
public DBResourceManager(
IConfiguration configuration,
IOptionsMonitor<ILog> option,
DbContextManager<ResourceDbContext> dbContext,
string filename,
Assembly assembly)
: base(filename, assembly)
{
Configuration = configuration;
Option = option;
DbContext = dbContext;
}
public static void PatchAssemblies(IOptionsMonitor<ILog> option)
{
AppDomain.CurrentDomain.AssemblyLoad += (_, a) => PatchAssembly(option, a.LoadedAssembly);
Array.ForEach(AppDomain.CurrentDomain.GetAssemblies(), a => PatchAssembly(option, a));
}
public static void PatchAssembly(IOptionsMonitor<ILog> option, Assembly a, bool onlyAsc = true)
{
var log = option.CurrentValue;
if (!onlyAsc || Accept(a))
{
var types = new Type[0];
try
{
types = a.GetTypes();
}
catch (ReflectionTypeLoadException rtle)
{
log.WarnFormat("Can not GetTypes() from assembly {0}, try GetExportedTypes(), error: {1}", a.FullName, rtle.Message);
foreach (var e in rtle.LoaderExceptions)
{
log.Info(e.Message);
}
try
{
types = a.GetExportedTypes();
}
catch (Exception err)
{
log.ErrorFormat("Can not GetExportedTypes() from assembly {0}: {1}", a.FullName, err.Message);
}
}
foreach (var type in types)
{
var prop = type.GetProperty("ResourceManager", BindingFlags.Static | BindingFlags.NonPublic | BindingFlags.Public);
if (prop != null)
{
var rm = (ResourceManager)prop.GetValue(type);
if (!(rm is DBResourceManager))
{
var dbrm = new DBResourceManager(rm.BaseName, a);
type.InvokeMember("resourceMan", BindingFlags.Static | BindingFlags.NonPublic | BindingFlags.SetField, null, type, new object[] { dbrm });
}
}
}
}
}
private static bool Accept(Assembly a)
{
var n = a.GetName().Name;
return (n.StartsWith("ASC.") || n.StartsWith("App_GlobalResources")) && a.GetManifestResourceNames().Length > 0;
}
public override Type ResourceSetType
{
get { return typeof(DBResourceSet); }
}
private IConfiguration Configuration { get; }
private IOptionsMonitor<ILog> Option { get; }
private DbContextManager<ResourceDbContext> DbContext { get; }
protected override ResourceSet InternalGetResourceSet(CultureInfo culture, bool createIfNotExists, bool tryParents)
{
resourceSets.TryGetValue(culture.Name, out var set);
if (set == null)
{
var invariant = culture == CultureInfo.InvariantCulture ? base.InternalGetResourceSet(CultureInfo.InvariantCulture, true, true) : null;
set = new DBResourceSet(Configuration, Option, DbContext, invariant, culture, BaseName);
resourceSets.AddOrUpdate(culture.Name, set, (k, v) => set);
}
return set;
}
class DBResourceSet : ResourceSet
{
private const string NEUTRAL_CULTURE = "Neutral";
private readonly TimeSpan cacheTimeout = TimeSpan.FromMinutes(120); // for performance
private readonly object locker = new object();
private readonly MemoryCache cache;
private readonly ResourceSet invariant;
private readonly string culture;
private readonly string filename;
private readonly ILog log;
private DbContextManager<ResourceDbContext> DbContext { get; }
public DBResourceSet(
IConfiguration configuration,
IOptionsMonitor<ILog> option,
DbContextManager<ResourceDbContext> dbContext,
ResourceSet invariant,
CultureInfo culture,
string filename)
{
if (culture == null)
{
throw new ArgumentNullException(nameof(culture));
}
if (string.IsNullOrEmpty(filename))
{
throw new ArgumentNullException(nameof(filename));
}
DbContext = dbContext;
log = option.CurrentValue;
try
{
var defaultValue = ((int)cacheTimeout.TotalMinutes).ToString();
cacheTimeout = TimeSpan.FromMinutes(Convert.ToInt32(configuration["resources:cache-timeout"] ?? defaultValue));
}
catch (Exception err)
{
log.Error(err);
}
this.invariant = invariant;
this.culture = invariant != null ? NEUTRAL_CULTURE : culture.Name;
this.filename = filename.Split('.').Last() + ".resx";
cache = MemoryCache.Default;
}
public override string GetString(string name, bool ignoreCase)
{
var result = (string)null;
try
{
var dic = GetResources();
dic.TryGetValue(name, out result);
}
catch (Exception err)
{
log.ErrorFormat("Can not get resource from {0} for {1}: GetString({2}), {3}", filename, culture, name, err);
}
if (invariant != null && result == null)
{
result = invariant.GetString(name, ignoreCase);
}
return result;
}
public override IDictionaryEnumerator GetEnumerator()
{
var result = new Hashtable();
if (invariant != null)
{
foreach (DictionaryEntry e in invariant)
{
result[e.Key] = e.Value;
}
}
try
{
var dic = GetResources();
foreach (var e in dic)
{
result[e.Key] = e.Value;
}
}
catch (Exception err)
{
log.Error(err);
}
return result.GetEnumerator();
}
private Dictionary<string, string> GetResources()
{
var key = $"{filename}/{culture}";
if (!(cache.Get(key) is Dictionary<string, string> dic))
{
lock (locker)
{
dic = cache.Get(key) as Dictionary<string, string>;
if (dic == null)
{
var policy = cacheTimeout == TimeSpan.Zero ? null : new CacheItemPolicy() { AbsoluteExpiration = DateTimeOffset.Now.Add(cacheTimeout) };
dic = LoadResourceSet(filename, culture);
cache.Set(key, dic, policy);
}
}
}
return dic;
}
private Dictionary<string, string> LoadResourceSet(string filename, string culture)
{
using var context = DbContext.Get("tmresource");
var q = context.ResData
.Where(r => r.CultureTitle == culture)
.Join(context.ResFiles, r => r.FileId, a => a.Id, (d, f) => new { data = d, files = f })
.Where(r => r.files.ResName == filename);
return q
.ToDictionary(r => r.data.Title, r => r.data.TextValue, StringComparer.InvariantCultureIgnoreCase);
}
}
}
namespace TMResourceData;
[Singletone]
public class WhiteLabelHelper
{
private readonly ILog log;
private readonly ConcurrentDictionary<int, string> whiteLabelDictionary;
public string DefaultLogoText { get; set; }
private IConfiguration Configuration { get; }
public WhiteLabelHelper(IConfiguration configuration, IOptionsMonitor<ILog> option)
{
log = option.Get("ASC.Resources");
whiteLabelDictionary = new ConcurrentDictionary<int, string>();
DefaultLogoText = "";
Configuration = configuration;
}
public void SetNewText(int tenantId, string newText)
{
try
{
whiteLabelDictionary.AddOrUpdate(tenantId, r => newText, (i, s) => newText);
}
catch (Exception e)
{
log.Error("SetNewText", e);
}
}
public void RestoreOldText(int tenantId)
{
try
{
whiteLabelDictionary.TryRemove(tenantId, out var text);
}
catch (Exception e)
{
log.Error("RestoreOldText", e);
}
}
internal string ReplaceLogo(TenantManager tenantManager, IHttpContextAccessor httpContextAccessor, string resourceName, string resourceValue)
{
if (string.IsNullOrEmpty(resourceValue))
{
return resourceValue;
}
if (!DBResourceManager.WhiteLableEnabled)
{
return resourceValue;
}
if (httpContextAccessor.HttpContext != null) //if in Notify Service or other process without HttpContext
{
try
{
var tenant = tenantManager.GetCurrentTenant(false);
if (tenant == null) return resourceValue;
if (whiteLabelDictionary.TryGetValue(tenant.TenantId, out var newText))
{
var newTextReplacement = newText;
if (resourceValue.IndexOf('<') >= 0 && resourceValue.IndexOf('>') >= 0 || resourceName.StartsWith("pattern_"))
{
newTextReplacement = HttpUtility.HtmlEncode(newTextReplacement);
}
if (resourceValue.Contains("{0"))
{
//Hack for string which used in string.Format
newTextReplacement = newTextReplacement.Replace("{", "{{").Replace("}", "}}");
}
var replPattern = Configuration["resources:whitelabel-text.replacement.pattern"] ?? "(?<=[^@/\\\\]|^)({0})(?!\\.com)";
var pattern = string.Format(replPattern, DefaultLogoText);
//Hack for resource strings with mails looked like ...@onlyoffice... or with website http://www.onlyoffice.com link or with the https://www.facebook.com/pages/OnlyOffice/833032526736775
return Regex.Replace(resourceValue, pattern, newTextReplacement, RegexOptions.IgnoreCase).Replace("™", "");
}
}
catch (Exception e)
{
log.Error("ReplaceLogo", e);
}
}
return resourceValue;
}
}
public class DBResourceManager : ResourceManager
{
public static readonly bool WhiteLableEnabled = false;
private readonly ConcurrentDictionary<string, ResourceSet> _resourceSets = new ConcurrentDictionary<string, ResourceSet>();
public DBResourceManager(string filename, Assembly assembly)
: base(filename, assembly)
{
}
public DBResourceManager(
IConfiguration configuration,
IOptionsMonitor<ILog> option,
DbContextManager<ResourceDbContext> dbContext,
string filename,
Assembly assembly)
: base(filename, assembly)
{
_configuration = configuration;
_option = option;
_dbContext = dbContext;
}
public static void PatchAssemblies(IOptionsMonitor<ILog> option)
{
AppDomain.CurrentDomain.AssemblyLoad += (_, a) => PatchAssembly(option, a.LoadedAssembly);
Array.ForEach(AppDomain.CurrentDomain.GetAssemblies(), a => PatchAssembly(option, a));
}
public static void PatchAssembly(IOptionsMonitor<ILog> option, Assembly a, bool onlyAsc = true)
{
var log = option.CurrentValue;
if (!onlyAsc || Accept(a))
{
var types = Array.Empty<Type>();
try
{
types = a.GetTypes();
}
catch (ReflectionTypeLoadException rtle)
{
log.WarnFormat("Can not GetTypes() from assembly {0}, try GetExportedTypes(), error: {1}", a.FullName, rtle.Message);
foreach (var e in rtle.LoaderExceptions)
{
log.Info(e.Message);
}
try
{
types = a.GetExportedTypes();
}
catch (Exception err)
{
log.ErrorFormat("Can not GetExportedTypes() from assembly {0}: {1}", a.FullName, err.Message);
}
}
foreach (var type in types)
{
var prop = type.GetProperty("ResourceManager", BindingFlags.Static | BindingFlags.NonPublic | BindingFlags.Public);
if (prop != null)
{
var rm = (ResourceManager)prop.GetValue(type);
if (!(rm is DBResourceManager))
{
var dbrm = new DBResourceManager(rm.BaseName, a);
type.InvokeMember("resourceMan", BindingFlags.Static | BindingFlags.NonPublic | BindingFlags.SetField, null, type, new object[] { dbrm });
}
}
}
}
}
private static bool Accept(Assembly a)
{
var n = a.GetName().Name;
return (n.StartsWith("ASC.") || n.StartsWith("App_GlobalResources")) && a.GetManifestResourceNames().Length > 0;
}
public override Type ResourceSetType => typeof(DBResourceSet);
private readonly IConfiguration _configuration;
private readonly IOptionsMonitor<ILog> _option;
private readonly DbContextManager<ResourceDbContext> _dbContext;
protected override ResourceSet InternalGetResourceSet(CultureInfo culture, bool createIfNotExists, bool tryParents)
{
_resourceSets.TryGetValue(culture.Name, out var set);
if (set == null)
{
var invariant = culture == CultureInfo.InvariantCulture ? base.InternalGetResourceSet(CultureInfo.InvariantCulture, true, true) : null;
set = new DBResourceSet(_configuration, _option, _dbContext, invariant, culture, BaseName);
_resourceSets.AddOrUpdate(culture.Name, set, (k, v) => set);
}
return set;
}
class DBResourceSet : ResourceSet
{
private const string NeutralCulture = "Neutral";
private readonly TimeSpan _cacheTimeout = TimeSpan.FromMinutes(120); // for performance
private readonly object _locker = new object();
private readonly MemoryCache _cache;
private readonly ResourceSet _invariant;
private readonly string _culture;
private readonly string _fileName;
private readonly ILog _logger;
private readonly DbContextManager<ResourceDbContext> _dbContext;
public DBResourceSet(
IConfiguration configuration,
IOptionsMonitor<ILog> option,
DbContextManager<ResourceDbContext> dbContext,
ResourceSet invariant,
CultureInfo culture,
string filename)
{
if (culture == null)
{
throw new ArgumentNullException(nameof(culture));
}
if (string.IsNullOrEmpty(filename))
{
throw new ArgumentNullException(nameof(filename));
}
_dbContext = dbContext;
_logger = option.CurrentValue;
try
{
var defaultValue = ((int)_cacheTimeout.TotalMinutes).ToString();
_cacheTimeout = TimeSpan.FromMinutes(Convert.ToInt32(configuration["resources:cache-timeout"] ?? defaultValue));
}
catch (Exception err)
{
_logger.Error(err);
}
_invariant = invariant;
_culture = invariant != null ? NeutralCulture : culture.Name;
_fileName = filename.Split('.').Last() + ".resx";
_cache = MemoryCache.Default;
}
public override string GetString(string name, bool ignoreCase)
{
var result = (string)null;
try
{
var dic = GetResources();
dic.TryGetValue(name, out result);
}
catch (Exception err)
{
_logger.ErrorFormat("Can not get resource from {0} for {1}: GetString({2}), {3}", _fileName, _culture, name, err);
}
if (_invariant != null && result == null)
{
result = _invariant.GetString(name, ignoreCase);
}
return result;
}
public override IDictionaryEnumerator GetEnumerator()
{
var result = new Hashtable();
if (_invariant != null)
{
foreach (DictionaryEntry e in _invariant)
{
result[e.Key] = e.Value;
}
}
try
{
var dic = GetResources();
foreach (var e in dic)
{
result[e.Key] = e.Value;
}
}
catch (Exception err)
{
_logger.Error(err);
}
return result.GetEnumerator();
}
private Dictionary<string, string> GetResources()
{
var key = $"{_fileName}/{_culture}";
if (!(_cache.Get(key) is Dictionary<string, string> dic))
{
lock (_locker)
{
dic = _cache.Get(key) as Dictionary<string, string>;
if (dic == null)
{
var policy = _cacheTimeout == TimeSpan.Zero ? null : new CacheItemPolicy() { AbsoluteExpiration = DateTimeOffset.Now.Add(_cacheTimeout) };
dic = LoadResourceSet(_fileName, _culture);
_cache.Set(key, dic, policy);
}
}
}
return dic;
}
private Dictionary<string, string> LoadResourceSet(string filename, string culture)
{
using var context = _dbContext.Get("tmresource");
var q = context.ResData
.Where(r => r.CultureTitle == culture)
.Join(context.ResFiles, r => r.FileId, a => a.Id, (d, f) => new { data = d, files = f })
.Where(r => r.files.ResName == filename);
return q
.ToDictionary(r => r.data.Title, r => r.data.TextValue, StringComparer.InvariantCultureIgnoreCase);
}
}
}
[Singletone]
public class WhiteLabelHelper
{
private readonly ILog _logger;
private readonly ConcurrentDictionary<int, string> _whiteLabelDictionary;
public string DefaultLogoText { get; set; }
private readonly IConfiguration _configuration;
public WhiteLabelHelper(IConfiguration configuration, IOptionsMonitor<ILog> option)
{
_logger = option.Get("ASC.Resources");
_whiteLabelDictionary = new ConcurrentDictionary<int, string>();
DefaultLogoText = string.Empty;
_configuration = configuration;
}
public void SetNewText(int tenantId, string newText)
{
try
{
_whiteLabelDictionary.AddOrUpdate(tenantId, r => newText, (i, s) => newText);
}
catch (Exception e)
{
_logger.Error("SetNewText", e);
}
}
public void RestoreOldText(int tenantId)
{
try
{
_whiteLabelDictionary.TryRemove(tenantId, out var text);
}
catch (Exception e)
{
_logger.Error("RestoreOldText", e);
}
}
internal string ReplaceLogo(TenantManager tenantManager, IHttpContextAccessor httpContextAccessor, string resourceName, string resourceValue)
{
if (string.IsNullOrEmpty(resourceValue))
{
return resourceValue;
}
if (!DBResourceManager.WhiteLableEnabled)
{
return resourceValue;
}
if (httpContextAccessor.HttpContext != null) //if in Notify Service or other process without HttpContext
{
try
{
var tenant = tenantManager.GetCurrentTenant(false);
if (tenant == null)
{
return resourceValue;
}
if (_whiteLabelDictionary.TryGetValue(tenant.Id, out var newText))
{
var newTextReplacement = newText;
if (resourceValue.IndexOf('<') >= 0 && resourceValue.IndexOf('>') >= 0 || resourceName.StartsWith("pattern_"))
{
newTextReplacement = HttpUtility.HtmlEncode(newTextReplacement);
}
if (resourceValue.Contains("{0"))
{
//Hack for string which used in string.Format
newTextReplacement = newTextReplacement.Replace("{", "{{").Replace("}", "}}");
}
var replPattern = _configuration["resources:whitelabel-text.replacement.pattern"] ?? "(?<=[^@/\\\\]|^)({0})(?!\\.com)";
var pattern = string.Format(replPattern, DefaultLogoText);
//Hack for resource strings with mails looked like ...@onlyoffice... or with website http://www.onlyoffice.com link or with the https://www.facebook.com/pages/OnlyOffice/833032526736775
return Regex.Replace(resourceValue, pattern, newTextReplacement, RegexOptions.IgnoreCase).Replace("™", "");
}
}
catch (Exception e)
{
_logger.Error("ReplaceLogo", e);
}
}
return resourceValue;
}
}

View File

@ -23,21 +23,20 @@
*
*/
namespace ASC.Core.Users
{
[Flags]
public enum EmployeeActivationStatus
{
NotActivated = 0,
Activated = 1,
Pending = 2,
AutoGenerated = 4
}
namespace ASC.Core.Users;
[Flags]
public enum MobilePhoneActivationStatus
{
NotActivated = 0,
Activated = 1
}
}
[Flags]
public enum EmployeeActivationStatus
{
NotActivated = 0,
Activated = 1,
Pending = 2,
AutoGenerated = 4
}
[Flags]
public enum MobilePhoneActivationStatus
{
NotActivated = 0,
Activated = 1
}

View File

@ -23,19 +23,14 @@
*
*/
namespace ASC.Core.Users
namespace ASC.Core.Users;
[Flags]
public enum EmployeeStatus
{
[Flags]
public enum EmployeeStatus
{
Active = 1,
Terminated = 2,
LeaveOfAbsence = 4,
All = Active | Terminated | LeaveOfAbsence,
Default = Active | LeaveOfAbsence
}
}
Active = 1,
Terminated = 2,
LeaveOfAbsence = 4,
All = Active | Terminated | LeaveOfAbsence,
Default = Active | LeaveOfAbsence
}

View File

@ -26,16 +26,13 @@
using JsonConverter = System.Text.Json.Serialization.JsonConverter;
using JsonConverterAttribute = System.Text.Json.Serialization.JsonConverterAttribute;
namespace ASC.Core.Users
{
[Flags]
[JsonConverter(typeof(JsonStringEnumConverter))]
public enum EmployeeType
{
All = 0,
User = 1,
Visitor = 2
}
}
namespace ASC.Core.Users;
[Flags]
[JsonConverter(typeof(JsonStringEnumConverter))]
public enum EmployeeType
{
All = 0,
User = 1,
Visitor = 2
}

View File

@ -23,71 +23,40 @@
*
*/
namespace ASC.Core
namespace ASC.Core;
public class Group : IMapFrom<DbGroup>
{
public class Group
public Guid Id { get; set; }
public Guid ParentId { get; set; }
public string Name { get; set; }
public Guid CategoryId { get; set; }
public bool Removed { get; set; }
public DateTime LastModified { get; set; }
public int Tenant { get; set; }
public string Sid { get; set; }
public override string ToString()
{
public Guid Id
{
get;
set;
}
return Name;
}
public Guid ParentId
{
get;
set;
}
public override int GetHashCode()
{
return Id.GetHashCode();
}
public string Name
{
get;
set;
}
public override bool Equals(object obj)
{
return obj is Group g && g.Id == Id;
}
public Guid CategoryId
{
get;
set;
}
public void Mapping(Profile profile)
{
profile.CreateMap<DbGroup, Group>()
.ForMember(src => src.CategoryId, opt => opt.NullSubstitute(Guid.Empty))
.ForMember(src => src.ParentId, opt => opt.NullSubstitute(Guid.Empty));
public bool Removed
{
get;
set;
}
public DateTime LastModified
{
get;
set;
}
public int Tenant
{
get;
set;
}
public string Sid
{
get;
set;
}
public override string ToString()
{
return Name;
}
public override int GetHashCode()
{
return Id.GetHashCode();
}
public override bool Equals(object obj)
{
return obj is Group g && g.Id == Id;
}
profile.CreateMap<GroupInfo, Group>();
}
}

View File

@ -23,67 +23,51 @@
*
*/
namespace ASC.Core.Users
namespace ASC.Core.Users;
[Serializable]
public class GroupInfo : IRole, IRecipientsGroup
{
[Serializable]
public class GroupInfo : IRole, IRecipientsGroup
public Guid ID { get; internal set; }
public string Name { get; set; }
public Guid CategoryID { get; set; }
public GroupInfo Parent { get; internal set; }
public string Sid { get; set; }
public GroupInfo() { }
public GroupInfo(Guid categoryID)
{
public Guid ID { get; internal set; }
public string Name { get; set; }
public Guid CategoryID { get; set; }
public GroupInfo Parent { get; internal set; }
public string Sid { get; set; }
public GroupInfo()
{
}
public GroupInfo(Guid categoryID)
{
CategoryID = categoryID;
}
public override string ToString()
{
return Name;
}
public override int GetHashCode()
{
return ID != Guid.Empty ? ID.GetHashCode() : base.GetHashCode();
}
public override bool Equals(object obj)
{
if (!(obj is GroupInfo g)) return false;
if (ID == Guid.Empty && g.ID == Guid.Empty) return ReferenceEquals(this, g);
return g.ID == ID;
}
string IRecipient.ID
{
get { return ID.ToString(); }
}
string IRecipient.Name
{
get { return Name; }
}
public string AuthenticationType
{
get { return "ASC"; }
}
public bool IsAuthenticated
{
get { return false; }
}
CategoryID = categoryID;
}
}
public override string ToString()
{
return Name;
}
public override int GetHashCode()
{
return ID != Guid.Empty ? ID.GetHashCode() : base.GetHashCode();
}
public override bool Equals(object obj)
{
if (!(obj is GroupInfo g))
{
return false;
}
if (ID == Guid.Empty && g.ID == Guid.Empty)
{
return ReferenceEquals(this, g);
}
return g.ID == ID;
}
string IRecipient.ID => ID.ToString();
string IRecipient.Name => Name;
public string AuthenticationType => "ASC";
public bool IsAuthenticated => false;
}

View File

@ -23,15 +23,12 @@
*
*/
namespace ASC.Core
namespace ASC.Core;
[Scope(typeof(DbAzService), typeof(CachedAzService))]
public interface IAzService
{
[Scope(typeof(DbAzService), typeof(CachedAzService))]
public interface IAzService
{
IEnumerable<AzRecord> GetAces(int tenant, DateTime from);
AzRecord SaveAce(int tenant, AzRecord r);
void RemoveAce(int tenant, AzRecord r);
}
AzRecord SaveAce(int tenant, AzRecord r);
IEnumerable<AzRecord> GetAces(int tenant, DateTime from);
void RemoveAce(int tenant, AzRecord r);
}

View File

@ -23,21 +23,15 @@
*
*/
namespace ASC.Core
{
[Scope(typeof(ConfigureDbQuotaService), typeof(ConfigureCachedQuotaService))]
public interface IQuotaService
{
IEnumerable<TenantQuota> GetTenantQuotas();
TenantQuota GetTenantQuota(int id);
TenantQuota SaveTenantQuota(TenantQuota quota);
void RemoveTenantQuota(int id);
namespace ASC.Core;
IEnumerable<TenantQuotaRow> FindTenantQuotaRows(int tenantId);
void SetTenantQuotaRow(TenantQuotaRow row, bool exchange);
}
[Scope(typeof(ConfigureDbQuotaService), typeof(ConfigureCachedQuotaService))]
public interface IQuotaService
{
IEnumerable<TenantQuota> GetTenantQuotas();
IEnumerable<TenantQuotaRow> FindTenantQuotaRows(int tenantId);
TenantQuota GetTenantQuota(int id);
TenantQuota SaveTenantQuota(TenantQuota quota);
void RemoveTenantQuota(int id);
void SetTenantQuotaRow(TenantQuotaRow row, bool exchange);
}

View File

@ -23,32 +23,20 @@
*
*/
namespace ASC.Core
namespace ASC.Core;
[Scope(typeof(DbSubscriptionService))]
public interface ISubscriptionService
{
[Scope(typeof(DbSubscriptionService))]
public interface ISubscriptionService
{
string[] GetRecipients(int tenant, string sourceID, string actionID, string objectID);
IEnumerable<SubscriptionRecord> GetSubscriptions(int tenant, string sourceId, string actionId);
IEnumerable<SubscriptionRecord> GetSubscriptions(int tenant, string sourceId, string actionId, string recipientId, string objectId);
string[] GetSubscriptions(int tenant, string sourceId, string actionId, string recipientId, bool checkSubscribe);
SubscriptionRecord GetSubscription(int tenant, string sourceId, string actionId, string recipientId, string objectId);
bool IsUnsubscribe(int tenant, string sourceId, string actionId, string recipientId, string objectId);
void SaveSubscription(SubscriptionRecord s);
void RemoveSubscriptions(int tenant, string sourceId, string actionId);
void RemoveSubscriptions(int tenant, string sourceId, string actionId, string objectId);
IEnumerable<SubscriptionMethod> GetSubscriptionMethods(int tenant, string sourceId, string actionId, string recipientId);
void SetSubscriptionMethod(SubscriptionMethod m);
}
bool IsUnsubscribe(int tenant, string sourceId, string actionId, string recipientId, string objectId);
IEnumerable<SubscriptionMethod> GetSubscriptionMethods(int tenant, string sourceId, string actionId, string recipientId);
IEnumerable<SubscriptionRecord> GetSubscriptions(int tenant, string sourceId, string actionId);
IEnumerable<SubscriptionRecord> GetSubscriptions(int tenant, string sourceId, string actionId, string recipientId, string objectId);
string[] GetRecipients(int tenant, string sourceID, string actionID, string objectID);
string[] GetSubscriptions(int tenant, string sourceId, string actionId, string recipientId, bool checkSubscribe);
SubscriptionRecord GetSubscription(int tenant, string sourceId, string actionId, string recipientId, string objectId);
void RemoveSubscriptions(int tenant, string sourceId, string actionId);
void RemoveSubscriptions(int tenant, string sourceId, string actionId, string objectId);
void SaveSubscription(SubscriptionRecord s);
void SetSubscriptionMethod(SubscriptionMethod m);
}

View File

@ -23,33 +23,21 @@
*
*/
namespace ASC.Core
{
[Scope(typeof(ConfigureDbTenantService), typeof(ConfigureCachedTenantService))]
public interface ITenantService
{
void ValidateDomain(string domain);
IEnumerable<Tenant> GetTenants(DateTime from, bool active = true);
namespace ASC.Core;
IEnumerable<Tenant> GetTenants(List<int> ids);
IEnumerable<Tenant> GetTenants(string login, string passwordHash);
Tenant GetTenant(int id);
Tenant GetTenant(string domain);
Tenant GetTenantForStandaloneWithoutAlias(string ip);
Tenant SaveTenant(CoreSettings coreSettings, Tenant tenant);
void RemoveTenant(int id, bool auto = false);
byte[] GetTenantSettings(int tenant, string key);
void SetTenantSettings(int tenant, string key, byte[] data);
IEnumerable<TenantVersion> GetTenantVersions();
}
[Scope(typeof(ConfigureDbTenantService), typeof(ConfigureCachedTenantService))]
public interface ITenantService
{
byte[] GetTenantSettings(int tenant, string key);
IEnumerable<Tenant> GetTenants(DateTime from, bool active = true);
IEnumerable<Tenant> GetTenants(List<int> ids);
IEnumerable<Tenant> GetTenants(string login, string passwordHash);
IEnumerable<TenantVersion> GetTenantVersions();
Tenant GetTenant(int id);
Tenant GetTenant(string domain);
Tenant GetTenantForStandaloneWithoutAlias(string ip);
Tenant SaveTenant(CoreSettings coreSettings, Tenant tenant);
void RemoveTenant(int id, bool auto = false);
void SetTenantSettings(int tenant, string key, byte[] data);
void ValidateDomain(string domain);
}

View File

@ -23,64 +23,42 @@
*
*/
namespace ASC.Core
namespace ASC.Core;
[Scope(typeof(ConfigureEFUserService), typeof(ConfigureCachedUserService))]
public interface IUserService
{
[Scope(typeof(ConfigureEFUserService), typeof(ConfigureCachedUserService))]
public interface IUserService
{
IEnumerable<UserInfo> GetUsers(int tenant);
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);
UserInfo GetUser(int tenant, Guid id);
UserInfo GetUser(int tenant, string email);
UserInfo GetUserByUserName(int tenant, string userName);
UserInfo GetUser(int tenant, Guid id, Expression<Func<User, UserInfo>> exp);
UserInfo GetUserByPasswordHash(int tenant, string login, string passwordHash);
UserInfo SaveUser(int tenant, UserInfo user);
void RemoveUser(int tenant, Guid id);
byte[] GetUserPhoto(int tenant, Guid id);
void SetUserPhoto(int tenant, Guid id, byte[] photo);
DateTime GetUserPasswordStamp(int tenant, Guid id);
void SetUserPasswordHash(int tenant, Guid id, string passwordHash);
IEnumerable<Group> GetGroups(int tenant);
Group GetGroup(int tenant, Guid id);
Group SaveGroup(int tenant, Group group);
void RemoveGroup(int tenant, Guid id);
UserGroupRef GetUserGroupRef(int tenant, Guid groupId, UserGroupRefType refType);
IDictionary<string, UserGroupRef> GetUserGroupRefs(int tenant);
UserGroupRef SaveUserGroupRef(int tenant, UserGroupRef r);
void RemoveUserGroupRef(int tenant, Guid userId, Guid groupId, UserGroupRefType refType);
IEnumerable<UserInfo> GetUsersAllTenants(IEnumerable<Guid> userIds);
}
IEnumerable<UserInfo> GetUsers(int tenant);
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);
byte[] GetUserPhoto(int tenant, Guid id);
DateTime GetUserPasswordStamp(int tenant, Guid id);
Group GetGroup(int tenant, Guid id);
Group SaveGroup(int tenant, Group group);
IDictionary<string, UserGroupRef> GetUserGroupRefs(int tenant);
IEnumerable<Group> GetGroups(int tenant);
IEnumerable<UserInfo> GetUsersAllTenants(IEnumerable<Guid> userIds);
UserGroupRef GetUserGroupRef(int tenant, Guid groupId, UserGroupRefType refType);
UserGroupRef SaveUserGroupRef(int tenant, UserGroupRef r);
UserInfo GetUser(int tenant, Guid id);
UserInfo GetUser(int tenant, Guid id, Expression<Func<User, UserInfo>> exp);
UserInfo GetUser(int tenant, string email);
UserInfo GetUserByPasswordHash(int tenant, string login, string passwordHash);
UserInfo GetUserByUserName(int tenant, string userName);
UserInfo SaveUser(int tenant, UserInfo user);
void RemoveGroup(int tenant, Guid id);
void RemoveUser(int tenant, Guid id);
void RemoveUserGroupRef(int tenant, Guid userId, Guid groupId, UserGroupRefType refType);
void SetUserPasswordHash(int tenant, Guid id, string passwordHash);
void SetUserPhoto(int tenant, Guid id, byte[] photo);
}

View File

@ -23,17 +23,13 @@
*
*/
namespace ASC.Core.Users
namespace ASC.Core.Users;
[Flags]
public enum IncludeType
{
[Flags]
public enum IncludeType
{
Distinct = 1,
InParent = 2,
InChild = 4,
All = Distinct | InParent | InChild
}
}
Distinct = 1,
InParent = 2,
InChild = 4,
All = Distinct | InParent | InChild
}

View File

@ -23,113 +23,68 @@
*
*/
namespace ASC.Core
namespace ASC.Core;
public class Partner
{
public class Partner
public string Id { get; set; }
public string Email { get; set; }
public string FirstName { get; set; }
public string LastName { get; set; }
public string Url { get; set; }
public string Phone { get; set; }
public string Language { get; set; }
public string CompanyName { get; set; }
public string Country { get; set; }
public string CountryCode { get; set; }
public bool CountryHasVat { get; set; }
public string Address { get; set; }
public string VatId { get; set; }
public DateTime CreationDate { get; set; }
public PartnerStatus Status { get; set; }
public string Comment { get; set; }
public string Portal { get; set; }
public bool PortalConfirmed { get; set; }
public bool IsAdmin => PartnerType == PartnerType.Administrator;
public decimal Limit { get; set; }
public int Discount { get; set; }
public string PayPalAccount { get; set; }
public decimal Deposit { get; set; }
public bool Removed { get; set; }
public string Currency { get; set; }
public string LogoUrl { get; set; }
public string DisplayName { get; set; }
public PartnerDisplayType DisplayType { get; set; }
public string SupportPhone { get; set; }
public string SupportEmail { get; set; }
public string SalesEmail { get; set; }
public string TermsUrl { get; set; }
public string Theme { get; set; }
public string RuAccount { get; set; }
public string RuBank { get; set; }
public string RuKs { get; set; }
public string RuKpp { get; set; }
public string RuBik { get; set; }
public string RuInn { get; set; }
public PartnerType PartnerType { get; set; }
public PartnerPaymentMethod PaymentMethod { get; set; }
public string PaymentUrl { get; set; }
public decimal AvailableCredit { get; set; }
public bool CustomEmailSignature { get; set; }
public string AuthorizedKey { get; set; }
public override bool Equals(object obj)
{
public string Id { get; set; }
public string Email { get; set; }
public string FirstName { get; set; }
public string LastName { get; set; }
public string Url { get; set; }
public string Phone { get; set; }
public string Language { get; set; }
public string CompanyName { get; set; }
public string Country { get; set; }
public string CountryCode { get; set; }
public bool CountryHasVat { get; set; }
public string Address { get; set; }
public string VatId { get; set; }
public DateTime CreationDate { get; set; }
public PartnerStatus Status { get; set; }
public string Comment { get; set; }
public string Portal { get; set; }
public bool PortalConfirmed { get; set; }
public bool IsAdmin { get { return PartnerType == PartnerType.Administrator; } }
public decimal Limit { get; set; }
public int Discount { get; set; }
public string PayPalAccount { get; set; }
public decimal Deposit { get; set; }
public bool Removed { get; set; }
public string Currency { get; set; }
public string LogoUrl { get; set; }
public string DisplayName { get; set; }
public PartnerDisplayType DisplayType { get; set; }
public string SupportPhone { get; set; }
public string SupportEmail { get; set; }
public string SalesEmail { get; set; }
public string TermsUrl { get; set; }
public string Theme { get; set; }
public string RuAccount { get; set; }
public string RuBank { get; set; }
public string RuKs { get; set; }
public string RuKpp { get; set; }
public string RuBik { get; set; }
public string RuInn { get; set; }
public PartnerType PartnerType { get; set; }
public PartnerPaymentMethod PaymentMethod { get; set; }
public string PaymentUrl { get; set; }
public decimal AvailableCredit { get; set; }
public bool CustomEmailSignature { get; set; }
public string AuthorizedKey { get; set; }
public override bool Equals(object obj)
{
return obj is Partner p && p.Id == Id;
}
public override int GetHashCode()
{
return (Id ?? string.Empty).GetHashCode();
}
public override string ToString()
{
return FirstName + " " + LastName;
}
return obj is Partner p && p.Id == Id;
}
}
public override int GetHashCode()
{
return (Id ?? string.Empty).GetHashCode();
}
public override string ToString()
{
return FirstName + " " + LastName;
}
}

View File

@ -24,12 +24,11 @@
*/
namespace ASC.Core
namespace ASC.Core;
public enum PartnerDisplayType
{
public enum PartnerDisplayType
{
LogoOnly,
DisplayNameOnly,
All,
}
LogoOnly,
DisplayNameOnly,
All,
}

View File

@ -24,12 +24,11 @@
*/
namespace ASC.Core
namespace ASC.Core;
public enum PartnerPaymentMethod
{
public enum PartnerPaymentMethod
{
Keys,
PayPal,
External
}
}
Keys,
PayPal,
External
}

View File

@ -24,13 +24,12 @@
*/
namespace ASC.Core
namespace ASC.Core;
public enum PartnerStatus
{
public enum PartnerStatus
{
Created,
Approved,
Rejected,
Blocked
}
Created,
Approved,
Rejected,
Blocked
}

View File

@ -24,12 +24,11 @@
*/
namespace ASC.Core
namespace ASC.Core;
public enum PartnerType
{
public enum PartnerType
{
Default,
Administrator,
System,
}
}
Default,
Administrator,
System,
}

View File

@ -23,44 +23,43 @@
*
*/
namespace ASC.Core
{
[Serializable]
public class SubscriptionMethod
{
public int Tenant { get; set; }
public string SourceId { get; set; }
public string ActionId { get; set; }
public string RecipientId { get; set; }
public string[] Methods { get; set; }
namespace ASC.Core;
public string MethodsFromDb { set { Methods = value.Split(new[] { '|' }, StringSplitOptions.RemoveEmptyEntries); } }
[Serializable]
public class SubscriptionMethod : IMapFrom<DbSubscriptionMethod>
{
public int Tenant { get; set; }
public string Source { get; set; }
public string Action { get; set; }
public string Recipient { get; set; }
public string[] Methods { get; set; }
public static implicit operator SubscriptionMethod(SubscriptionMethodCache cache)
{
return new SubscriptionMethod()
{
Tenant = cache.Tenant,
SourceId = cache.SourceId,
ActionId = cache.ActionId,
RecipientId = cache.RecipientId
};
}
public static implicit operator SubscriptionMethodCache(SubscriptionMethod cache)
public static implicit operator SubscriptionMethod(SubscriptionMethodCache cache)
{
return new SubscriptionMethod()
{
return new SubscriptionMethodCache
{
Tenant = cache.Tenant,
SourceId = cache.SourceId,
ActionId = cache.ActionId,
RecipientId = cache.RecipientId
};
}
}
Tenant = cache.Tenant,
Source = cache.SourceId,
Action = cache.ActionId,
Recipient = cache.RecipientId
};
}
public static implicit operator SubscriptionMethodCache(SubscriptionMethod cache)
{
return new SubscriptionMethodCache
{
Tenant = cache.Tenant,
SourceId = cache.Source,
ActionId = cache.Action,
RecipientId = cache.Recipient
};
}
public void Mapping(Profile profile)
{
profile.CreateMap<DbSubscriptionMethod, SubscriptionMethod>()
.ForMember(dest => dest.Methods, opt => opt
.MapFrom(src => src.Sender.Split(new[] { '|' }, StringSplitOptions.RemoveEmptyEntries)));
}
}

View File

@ -0,0 +1,10 @@
namespace ASC.Core;
public partial class SubscriptionRecord : IMapFrom<Subscription>
{
public void Mapping(Profile profile)
{
profile.CreateMap<Subscription, SubscriptionRecord>()
.ForMember(dest => dest.Subscribed, opt => opt.MapFrom(src => !src.Unsubscribed));
}
}

View File

@ -23,86 +23,77 @@
*
*/
namespace ASC.Core
{
[DebuggerDisplay("{UserId} - {GroupId}")]
public class UserGroupRef
{
public Guid UserId { get; set; }
public Guid GroupId { get; set; }
public bool Removed { get; set; }
public DateTime LastModified { get; set; }
public UserGroupRefType RefType { get; set; }
public int Tenant { get; set; }
public UserGroupRef()
{
}
public UserGroupRef(Guid userId, Guid groupId, UserGroupRefType refType)
{
UserId = userId;
GroupId = groupId;
RefType = refType;
}
public static string CreateKey(int tenant, Guid userId, Guid groupId, UserGroupRefType refType)
{
return tenant.ToString() + userId.ToString("N") + groupId.ToString("N") + ((int)refType).ToString();
}
public string CreateKey()
{
return CreateKey(Tenant, UserId, GroupId, RefType);
}
public override int GetHashCode()
{
return UserId.GetHashCode() ^ GroupId.GetHashCode() ^ Tenant.GetHashCode() ^ RefType.GetHashCode();
}
public override bool Equals(object obj)
{
return obj is UserGroupRef r && r.Tenant == Tenant && r.UserId == UserId && r.GroupId == GroupId && r.RefType == RefType;
namespace ASC.Core;
[DebuggerDisplay("{UserId} - {GroupId}")]
public class UserGroupRef : IMapFrom<UserGroup>
{
public Guid UserId { get; set; }
public Guid GroupId { get; set; }
public bool Removed { get; set; }
public DateTime LastModified { get; set; }
public UserGroupRefType RefType { get; set; }
public int Tenant { get; set; }
public UserGroupRef() { }
public UserGroupRef(Guid userId, Guid groupId, UserGroupRefType refType)
{
UserId = userId;
GroupId = groupId;
RefType = refType;
}
public static string CreateKey(int tenant, Guid userId, Guid groupId, UserGroupRefType refType)
{
return tenant.ToString() + userId.ToString("N") + groupId.ToString("N") + ((int)refType).ToString();
}
public string CreateKey()
{
return CreateKey(Tenant, UserId, GroupId, RefType);
}
public override int GetHashCode()
{
return UserId.GetHashCode() ^ GroupId.GetHashCode() ^ Tenant.GetHashCode() ^ RefType.GetHashCode();
}
public override bool Equals(object obj)
{
return obj is UserGroupRef r && r.Tenant == Tenant && r.UserId == UserId && r.GroupId == GroupId && r.RefType == RefType;
}
public static implicit operator UserGroupRef(UserGroupRefCacheItem cache)
{
var result = new UserGroupRef
{
UserId = new Guid(cache.UserId),
GroupId = new Guid(cache.GroupId)
};
if (Enum.TryParse<UserGroupRefType>(cache.RefType, out var refType))
{
result.RefType = refType;
}
public static implicit operator UserGroupRef(UserGroupRefCacheItem cache)
result.Tenant = cache.Tenant;
result.LastModified = new DateTime(cache.LastModified);
result.Removed = cache.Removed;
return result;
}
public static implicit operator UserGroupRefCacheItem(UserGroupRef cache)
{
return new UserGroupRefCacheItem
{
var result = new UserGroupRef
{
UserId = new Guid(cache.UserId),
GroupId = new Guid(cache.GroupId)
};
if (Enum.TryParse<UserGroupRefType>(cache.RefType, out var refType))
{
result.RefType = refType;
}
result.Tenant = cache.Tenant;
result.LastModified = new DateTime(cache.LastModified);
result.Removed = cache.Removed;
return result;
}
public static implicit operator UserGroupRefCacheItem(UserGroupRef cache)
{
return new UserGroupRefCacheItem
{
GroupId = cache.GroupId.ToString(),
UserId = cache.UserId.ToString(),
RefType = cache.RefType.ToString(),
LastModified = cache.LastModified.Ticks,
Removed = cache.Removed,
Tenant = cache.Tenant
};
}
}
GroupId = cache.GroupId.ToString(),
UserId = cache.UserId.ToString(),
RefType = cache.RefType.ToString(),
LastModified = cache.LastModified.Ticks,
Removed = cache.Removed,
Tenant = cache.Tenant
};
}
}

View File

@ -23,135 +23,123 @@
*
*/
namespace ASC.Core
namespace ASC.Core;
public class UserGroupRefDictionary : IDictionary<string, UserGroupRef>
{
public class UserGroupRefDictionary : IDictionary<string, UserGroupRef>
private readonly IDictionary<string, UserGroupRef> _dict = new Dictionary<string, UserGroupRef>();
private IDictionary<Guid, IEnumerable<UserGroupRef>> _byUsers;
private IDictionary<Guid, IEnumerable<UserGroupRef>> _byGroups;
public int Count => _dict.Count;
public bool IsReadOnly => _dict.IsReadOnly;
public ICollection<string> Keys => _dict.Keys;
public ICollection<UserGroupRef> Values => _dict.Values;
public UserGroupRef this[string key]
{
private readonly IDictionary<string, UserGroupRef> d = new Dictionary<string, UserGroupRef>();
private IDictionary<Guid, IEnumerable<UserGroupRef>> byUsers;
private IDictionary<Guid, IEnumerable<UserGroupRef>> byGroups;
public int Count
get => _dict[key];
set
{
get { return d.Count; }
}
public bool IsReadOnly
{
get { return d.IsReadOnly; }
}
public ICollection<string> Keys
{
get { return d.Keys; }
}
public ICollection<UserGroupRef> Values
{
get { return d.Values; }
}
public UserGroupRef this[string key]
{
get { return d[key]; }
set
{
d[key] = value;
BuildIndexes();
}
}
public UserGroupRefDictionary(IDictionary<string, UserGroupRef> dic)
{
foreach (var p in dic)
{
d.Add(p);
}
_dict[key] = value;
BuildIndexes();
}
public void Add(string key, UserGroupRef value)
{
d.Add(key, value);
BuildIndexes();
}
public void Add(KeyValuePair<string, UserGroupRef> item)
{
d.Add(item);
BuildIndexes();
}
public bool Remove(string key)
{
var result = d.Remove(key);
BuildIndexes();
return result;
}
public bool Remove(KeyValuePair<string, UserGroupRef> item)
{
var result = d.Remove(item);
BuildIndexes();
return result;
}
public void Clear()
{
d.Clear();
BuildIndexes();
}
public bool TryGetValue(string key, out UserGroupRef value)
{
return d.TryGetValue(key, out value);
}
public bool ContainsKey(string key)
{
return d.ContainsKey(key);
}
public bool Contains(KeyValuePair<string, UserGroupRef> item)
{
return d.Contains(item);
}
public void CopyTo(KeyValuePair<string, UserGroupRef>[] array, int arrayIndex)
{
d.CopyTo(array, arrayIndex);
}
public IEnumerator<KeyValuePair<string, UserGroupRef>> GetEnumerator()
{
return d.GetEnumerator();
}
IEnumerator IEnumerable.GetEnumerator()
{
return ((IEnumerable)d).GetEnumerator();
}
public IEnumerable<UserGroupRef> GetByUser(Guid userId)
{
return byUsers.ContainsKey(userId) ? byUsers[userId].ToList() : new List<UserGroupRef>();
}
public IEnumerable<UserGroupRef> GetByGroups(Guid groupId)
{
return byGroups.ContainsKey(groupId) ? byGroups[groupId].ToList() : new List<UserGroupRef>();
}
private void BuildIndexes()
{
byUsers = d.Values.GroupBy(r => r.UserId).ToDictionary(g => g.Key, g => g.AsEnumerable());
byGroups = d.Values.GroupBy(r => r.GroupId).ToDictionary(g => g.Key, g => g.AsEnumerable());
}
}
public UserGroupRefDictionary(IDictionary<string, UserGroupRef> dic)
{
foreach (var p in dic)
{
_dict.Add(p);
}
BuildIndexes();
}
public void Add(string key, UserGroupRef value)
{
_dict.Add(key, value);
BuildIndexes();
}
public void Add(KeyValuePair<string, UserGroupRef> item)
{
_dict.Add(item);
BuildIndexes();
}
public bool Remove(string key)
{
var result = _dict.Remove(key);
BuildIndexes();
return result;
}
public bool Remove(KeyValuePair<string, UserGroupRef> item)
{
var result = _dict.Remove(item);
BuildIndexes();
return result;
}
public void Clear()
{
_dict.Clear();
BuildIndexes();
}
public bool TryGetValue(string key, out UserGroupRef value)
{
return _dict.TryGetValue(key, out value);
}
public bool ContainsKey(string key)
{
return _dict.ContainsKey(key);
}
public bool Contains(KeyValuePair<string, UserGroupRef> item)
{
return _dict.Contains(item);
}
public void CopyTo(KeyValuePair<string, UserGroupRef>[] array, int arrayIndex)
{
_dict.CopyTo(array, arrayIndex);
}
public IEnumerator<KeyValuePair<string, UserGroupRef>> GetEnumerator()
{
return _dict.GetEnumerator();
}
IEnumerator IEnumerable.GetEnumerator()
{
return ((IEnumerable)_dict).GetEnumerator();
}
public IEnumerable<UserGroupRef> GetByUser(Guid userId)
{
return _byUsers.ContainsKey(userId) ? _byUsers[userId].ToList() : new List<UserGroupRef>();
}
public IEnumerable<UserGroupRef> GetByGroups(Guid groupId)
{
return _byGroups.ContainsKey(groupId) ? _byGroups[groupId].ToList() : new List<UserGroupRef>();
}
private void BuildIndexes()
{
_byUsers = _dict.Values.GroupBy(r => r.UserId).ToDictionary(g => g.Key, g => g.AsEnumerable());
_byGroups = _dict.Values.GroupBy(r => r.GroupId).ToDictionary(g => g.Key, g => g.AsEnumerable());
}
}

View File

@ -24,11 +24,10 @@
*/
namespace ASC.Core
namespace ASC.Core;
public enum UserGroupRefType
{
public enum UserGroupRefType
{
Contains,
Manager,
}
Contains,
Manager,
}

View File

@ -23,164 +23,127 @@
*
*/
namespace ASC.Core.Users
{
[Serializable]
public sealed class UserInfo : IDirectRecipient, ICloneable
{
public UserInfo()
{
Status = EmployeeStatus.Active;
ActivationStatus = EmployeeActivationStatus.NotActivated;
LastModified = DateTime.UtcNow;
}
public Guid ID { get; set; }
public string FirstName { get; set; }
public string LastName { get; set; }
public string UserName { get; set; }
public DateTime? BirthDate { get; set; }
public bool? Sex { get; set; }
public EmployeeStatus Status { get; set; }
public EmployeeActivationStatus ActivationStatus { get; set; }
public DateTime? TerminatedDate { get; set; }
public string Title { get; set; }
public DateTime? WorkFromDate { get; set; }
public string Email { get; set; }
namespace ASC.Core.Users;
private string contacts;
public string Contacts
[Serializable]
public sealed class UserInfo : IDirectRecipient, ICloneable, IMapFrom<User>
{
public UserInfo()
{
Status = EmployeeStatus.Active;
ActivationStatus = EmployeeActivationStatus.NotActivated;
LastModified = DateTime.UtcNow;
}
public Guid Id { get; set; }
public string FirstName { get; set; }
public string LastName { get; set; }
public string UserName { get; set; }
public DateTime? BirthDate { get; set; }
public bool? Sex { get; set; }
public EmployeeStatus Status { get; set; }
public EmployeeActivationStatus ActivationStatus { get; set; }
public DateTime? TerminatedDate { get; set; }
public string Title { get; set; }
public DateTime? WorkFromDate { get; set; }
public string Email { get; set; }
private string _contacts;
public string Contacts
{
get => _contacts;
set
{
get => contacts;
set
{
contacts = value;
ContactsFromString(contacts);
}
_contacts = value;
ContactsFromString(_contacts);
}
}
public List<string> ContactsList { get; set; }
public string Location { get; set; }
public string Notes { get; set; }
public bool Removed { get; set; }
public DateTime LastModified { get; set; }
public int Tenant { get; set; }
public bool IsActive => ActivationStatus.HasFlag(EmployeeActivationStatus.Activated);
public string CultureName { get; set; }
public string MobilePhone { get; set; }
public MobilePhoneActivationStatus MobilePhoneActivationStatus { get; set; }
public string Sid { get; set; } // LDAP user identificator
public string SsoNameId { get; set; } // SSO SAML user identificator
public string SsoSessionId { get; set; } // SSO SAML user session identificator
public DateTime CreateDate { get; set; }
public override string ToString()
{
return $"{FirstName} {LastName}".Trim();
}
public override int GetHashCode()
{
return Id.GetHashCode();
}
public override bool Equals(object obj)
{
return obj is UserInfo ui && Id.Equals(ui.Id);
}
public bool Equals(UserInfo obj)
{
return obj != null && Id.Equals(obj.Id);
}
public CultureInfo GetCulture()
{
return string.IsNullOrEmpty(CultureName) ? CultureInfo.CurrentCulture : CultureInfo.GetCultureInfo(CultureName);
}
string[] IDirectRecipient.Addresses => !string.IsNullOrEmpty(Email) ? new[] { Email } : Array.Empty<string>();
public bool CheckActivation => !IsActive; /*if user already active we don't need activation*/
string IRecipient.ID => Id.ToString();
string IRecipient.Name => ToString();
public object Clone()
{
return MemberwiseClone();
}
internal string ContactsToString()
{
if (ContactsList == null || ContactsList.Count == 0)
{
return null;
}
public List<string> ContactsList { get; set; }
public string Location { get; set; }
public string Notes { get; set; }
public bool Removed { get; set; }
public DateTime LastModified { get; set; }
public int Tenant { get; set; }
public bool IsActive
{
get { return ActivationStatus.HasFlag(EmployeeActivationStatus.Activated); }
}
public string CultureName { get; set; }
public string MobilePhone { get; set; }
public MobilePhoneActivationStatus MobilePhoneActivationStatus { get; set; }
public string Sid { get; set; } // LDAP user identificator
public string SsoNameId { get; set; } // SSO SAML user identificator
public string SsoSessionId { get; set; } // SSO SAML user session identificator
public DateTime CreateDate { get; set; }
public override string ToString()
{
return $"{FirstName} {LastName}".Trim();
}
public override int GetHashCode()
{
return ID.GetHashCode();
}
public override bool Equals(object obj)
{
return obj is UserInfo ui && ID.Equals(ui.ID);
}
public bool Equals(UserInfo obj)
{
return obj != null && ID.Equals(obj.ID);
}
public CultureInfo GetCulture()
{
return string.IsNullOrEmpty(CultureName) ? CultureInfo.CurrentCulture : CultureInfo.GetCultureInfo(CultureName);
}
string[] IDirectRecipient.Addresses
{
get { return !string.IsNullOrEmpty(Email) ? new[] { Email } : Array.Empty<string>(); }
}
public bool CheckActivation
{
get { return !IsActive; /*if user already active we don't need activation*/ }
}
string IRecipient.ID
{
get { return ID.ToString(); }
}
string IRecipient.Name
{
get { return ToString(); }
}
public object Clone()
{
return MemberwiseClone();
}
internal string ContactsToString()
{
if (ContactsList == null || ContactsList.Count == 0) return null;
var sBuilder = new StringBuilder();
foreach (var contact in ContactsList)
{
sBuilder.Append($"{contact}|");
}
return sBuilder.ToString();
}
internal UserInfo ContactsFromString(string contacts)
{
if (string.IsNullOrEmpty(contacts)) return this;
var sBuilder = new StringBuilder();
foreach (var contact in ContactsList)
{
sBuilder.Append($"{contact}|");
}
if (ContactsList == null)
{
ContactsList = new List<string>();
}
else
{
ContactsList.Clear();
}
return sBuilder.ToString();
}
ContactsList.AddRange(contacts.Split(new[] { '|' }, StringSplitOptions.RemoveEmptyEntries));
return this;
}
}
}
internal UserInfo ContactsFromString(string contacts)
{
if (string.IsNullOrEmpty(contacts))
{
return this;
}
if (ContactsList == null)
{
ContactsList = new List<string>();
}
else
{
ContactsList.Clear();
}
ContactsList.AddRange(contacts.Split(new[] { '|' }, StringSplitOptions.RemoveEmptyEntries));
return this;
}
}

View File

@ -23,137 +23,122 @@
*
*/
namespace ASC.Core.Data
using AutoMapper.QueryableExtensions;
namespace ASC.Core.Data;
[Scope]
class DbAzService : IAzService
{
[Scope]
class DbAzService : IAzService
private UserDbContext UserDbContext => _lazyUserDbContext.Value;
private Lazy<UserDbContext> _lazyUserDbContext;
private readonly IMapper _mapper;
public DbAzService(DbContextManager<UserDbContext> dbContextManager, IMapper mapper)
{
public Expression<Func<Acl, AzRecord>> FromAclToAzRecord { get; set; }
_lazyUserDbContext = new Lazy<UserDbContext>(() => dbContextManager.Value);
_mapper = mapper;
}
private UserDbContext UserDbContext { get => LazyUserDbContext.Value; }
private Lazy<UserDbContext> LazyUserDbContext { get; set; }
public DbAzService(DbContextManager<UserDbContext> dbContextManager)
public IEnumerable<AzRecord> GetAces(int tenant, DateTime from)
{
// row with tenant = -1 - common for all tenants, but equal row with tenant != -1 escape common row for the portal
var commonAces =
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
.Where(r => r.Tenant == tenant)
.ProjectTo<AzRecord>(_mapper.ConfigurationProvider)
.ToList();
// remove excaped rows
foreach (var a in tenantAces)
{
LazyUserDbContext = new Lazy<UserDbContext>(() => dbContextManager.Value);
FromAclToAzRecord = r => new AzRecord
var key = string.Concat(a.Tenant.ToString(), a.Subject.ToString(), a.Action.ToString(), a.Object);
if (commonAces.TryGetValue(key, out var common))
{
ActionId = r.Action,
ObjectId = r.Object,
Reaction = r.AceType,
SubjectId = r.Subject,
Tenant = r.Tenant
};
}
public IEnumerable<AzRecord> GetAces(int tenant, DateTime from)
{
// row with tenant = -1 - common for all tenants, but equal row with tenant != -1 escape common row for the portal
var commonAces =
UserDbContext.Acl
.Where(r => r.Tenant == Tenant.DEFAULT_TENANT)
.Select(FromAclToAzRecord)
.ToDictionary(a => string.Concat(a.Tenant.ToString(), a.SubjectId.ToString(), a.ActionId.ToString(), a.ObjectId));
var tenantAces =
UserDbContext.Acl
.Where(r => r.Tenant == tenant)
.Select(FromAclToAzRecord)
.ToList();
// remove excaped rows
foreach (var a in tenantAces)
{
var key = string.Concat(a.Tenant.ToString(), a.SubjectId.ToString(), a.ActionId.ToString(), a.ObjectId);
if (commonAces.TryGetValue(key, out var common))
{
commonAces.Remove(key);
if (common.Reaction == a.Reaction)
{
tenantAces.Remove(a);
}
}
}
return commonAces.Values.Concat(tenantAces);
}
public AzRecord SaveAce(int tenant, AzRecord r)
{
r.Tenant = tenant;
using var tx = UserDbContext.Database.BeginTransaction();
if (!ExistEscapeRecord(r))
{
InsertRecord(r);
}
else
{
// unescape
DeleteRecord(r);
}
tx.Commit();
return r;
}
public void RemoveAce(int tenant, AzRecord r)
{
r.Tenant = tenant;
using var tx = UserDbContext.Database.BeginTransaction();
if (ExistEscapeRecord(r))
{
// escape
InsertRecord(r);
commonAces.Remove(key);
if (common.AceType == a.AceType)
{
tenantAces.Remove(a);
}
}
else
{
DeleteRecord(r);
}
tx.Commit();
}
private bool ExistEscapeRecord(AzRecord r)
{
return UserDbContext.Acl
.Where(a => a.Tenant == Tenant.DEFAULT_TENANT)
.Where(a => a.Subject == r.SubjectId)
.Where(a => a.Action == r.ActionId)
.Where(a => a.Object == (r.ObjectId ?? string.Empty))
.Where(a => a.AceType == r.Reaction)
.Any();
}
private void DeleteRecord(AzRecord r)
{
var record = UserDbContext.Acl
.Where(a => a.Tenant == r.Tenant)
.Where(a => a.Subject == r.SubjectId)
.Where(a => a.Action == r.ActionId)
.Where(a => a.Object == (r.ObjectId ?? string.Empty))
.Where(a => a.AceType == r.Reaction)
.FirstOrDefault();
}
if (record != null)
{
UserDbContext.Acl.Remove(record);
UserDbContext.SaveChanges();
}
}
private void InsertRecord(AzRecord r)
{
var record = new Acl
{
AceType = r.Reaction,
Action = r.ActionId,
Object = r.ObjectId ?? string.Empty,
Subject = r.SubjectId,
Tenant = r.Tenant
};
return commonAces.Values.Concat(tenantAces);
}
UserDbContext.AddOrUpdate(r => r.Acl, record);
UserDbContext.SaveChanges();
}
}
public AzRecord SaveAce(int tenant, AzRecord r)
{
r.Tenant = tenant;
using var tx = UserDbContext.Database.BeginTransaction();
if (!ExistEscapeRecord(r))
{
InsertRecord(r);
}
else
{
// unescape
DeleteRecord(r);
}
tx.Commit();
return r;
}
public void RemoveAce(int tenant, AzRecord r)
{
r.Tenant = tenant;
using var tx = UserDbContext.Database.BeginTransaction();
if (ExistEscapeRecord(r))
{
// escape
InsertRecord(r);
}
else
{
DeleteRecord(r);
}
tx.Commit();
}
private bool ExistEscapeRecord(AzRecord r)
{
return UserDbContext.Acl
.Where(a => a.Tenant == Tenant.DefaultTenant)
.Where(a => a.Subject == r.Subject)
.Where(a => a.Action == r.Action)
.Where(a => a.Object == (r.Object ?? string.Empty))
.Where(a => a.AceType == r.AceType)
.Any();
}
private void DeleteRecord(AzRecord r)
{
var record = UserDbContext.Acl
.Where(a => a.Tenant == r.Tenant)
.Where(a => a.Subject == r.Subject)
.Where(a => a.Action == r.Action)
.Where(a => a.Object == (r.Object ?? string.Empty))
.Where(a => a.AceType == r.AceType)
.FirstOrDefault();
if (record != null)
{
UserDbContext.Acl.Remove(record);
UserDbContext.SaveChanges();
}
}
private void InsertRecord(AzRecord r)
{
UserDbContext.AddOrUpdate(r => r.Acl, _mapper.Map<AzRecord, Acl>(r));
UserDbContext.SaveChanges();
}
}

View File

@ -23,174 +23,126 @@
*
*/
namespace ASC.Core.Data
using System.Diagnostics.Metrics;
using AutoMapper.QueryableExtensions;
namespace ASC.Core.Data;
[Scope]
class ConfigureDbQuotaService : IConfigureNamedOptions<DbQuotaService>
{
[Scope]
class ConfigureDbQuotaService : IConfigureNamedOptions<DbQuotaService>
private readonly DbContextManager<CoreDbContext> _dbContextManager;
public string DbId { get; set; }
public ConfigureDbQuotaService(DbContextManager<CoreDbContext> dbContextManager)
{
private DbContextManager<CoreDbContext> DbContextManager { get; }
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);
}
_dbContextManager = dbContextManager;
}
[Scope]
class DbQuotaService : IQuotaService
public void Configure(string name, DbQuotaService options)
{
private static Expression<Func<DbQuota, TenantQuota>> FromDbQuotaToTenantQuota { get; set; }
private static Expression<Func<DbQuotaRow, TenantQuotaRow>> FromDbQuotaRowToTenantQuotaRow { get; set; }
internal CoreDbContext CoreDbContext { get => LazyCoreDbContext.Value; }
internal Lazy<CoreDbContext> LazyCoreDbContext { get; set; }
static DbQuotaService()
{
FromDbQuotaToTenantQuota = r => new TenantQuota()
{
Id = r.Tenant,
Name = r.Name,
ActiveUsers = r.ActiveUsers != 0 ? r.ActiveUsers : int.MaxValue,
AvangateId = r.AvangateId,
Features = r.Features,
MaxFileSize = GetInBytes(r.MaxFileSize),
MaxTotalSize = GetInBytes(r.MaxTotalSize),
Price = r.Price,
Visible = r.Visible
};
options.LazyCoreDbContext = new Lazy<CoreDbContext>(() => _dbContextManager.Get(name));
}
FromDbQuotaRowToTenantQuotaRow = r => new TenantQuotaRow
{
Counter = r.Counter,
Path = r.Path,
Tag = r.Tag,
Tenant = r.Tenant
};
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 IMapper _mapper;
public DbQuotaService(DbContextManager<CoreDbContext> dbContextManager, IMapper mapper)
{
LazyCoreDbContext = new Lazy<CoreDbContext>(() => dbContextManager.Value);
_mapper = mapper;
}
public IEnumerable<TenantQuota> GetTenantQuotas()
{
return CoreDbContext.Quotas
.ProjectTo<TenantQuota>(_mapper.ConfigurationProvider)
.ToList();
}
public TenantQuota GetTenantQuota(int id)
{
return CoreDbContext.Quotas
.Where(r => r.Tenant == id)
.ProjectTo<TenantQuota>(_mapper.ConfigurationProvider)
.SingleOrDefault();
}
public TenantQuota SaveTenantQuota(TenantQuota quota)
{
if (quota == null)
{
throw new ArgumentNullException(nameof(quota));
}
public DbQuotaService(DbContextManager<CoreDbContext> dbContextManager)
CoreDbContext.AddOrUpdate(r => r.Quotas, _mapper.Map<TenantQuota, DbQuota>(quota));
CoreDbContext.SaveChanges();
return quota;
}
public void RemoveTenantQuota(int id)
{
using var tr = CoreDbContext.Database.BeginTransaction();
var d = CoreDbContext.Quotas
.Where(r => r.Tenant == id)
.SingleOrDefault();
if (d != null)
{
LazyCoreDbContext = new Lazy<CoreDbContext>(() => dbContextManager.Value);
CoreDbContext.Quotas.Remove(d);
CoreDbContext.SaveChanges();
}
public IEnumerable<TenantQuota> GetTenantQuotas()
{
return
CoreDbContext.Quotas
.Select(FromDbQuotaToTenantQuota)
.ToList();
}
public TenantQuota GetTenantQuota(int id)
{
return
CoreDbContext.Quotas
.Where(r => r.Tenant == id)
.Select(FromDbQuotaToTenantQuota)
.SingleOrDefault();
}
public TenantQuota SaveTenantQuota(TenantQuota quota)
{
if (quota == null) throw new ArgumentNullException(nameof(quota));
var dbQuota = new DbQuota
{
Tenant = quota.Id,
Name = quota.Name,
MaxFileSize = GetInMBytes(quota.MaxFileSize),
MaxTotalSize = GetInMBytes(quota.MaxTotalSize),
ActiveUsers = quota.ActiveUsers,
Features = quota.Features,
Price = quota.Price,
AvangateId = quota.AvangateId,
Visible = quota.Visible
};
tr.Commit();
}
CoreDbContext.AddOrUpdate(r => r.Quotas, dbQuota);
CoreDbContext.SaveChanges();
return quota;
}
public void RemoveTenantQuota(int id)
public void SetTenantQuotaRow(TenantQuotaRow row, bool exchange)
{
if (row == null)
{
using var tr = CoreDbContext.Database.BeginTransaction();
var d = CoreDbContext.Quotas
.Where(r => r.Tenant == id)
.SingleOrDefault();
throw new ArgumentNullException(nameof(row));
}
if (d != null)
{
CoreDbContext.Quotas.Remove(d);
CoreDbContext.SaveChanges();
}
using var tx = CoreDbContext.Database.BeginTransaction();
tr.Commit();
}
public void SetTenantQuotaRow(TenantQuotaRow row, bool exchange)
{
if (row == null) throw new ArgumentNullException(nameof(row));
var counter = CoreDbContext.QuotaRows
.Where(r => r.Path == row.Path && r.Tenant == row.Tenant)
.Select(r => r.Counter)
.Take(1)
.FirstOrDefault();
using var tx = CoreDbContext.Database.BeginTransaction();
var dbQuotaRow = _mapper.Map<TenantQuotaRow, DbQuotaRow>(row);
dbQuotaRow.Counter = exchange ? counter + row.Counter : row.Counter;
dbQuotaRow.LastModified = DateTime.UtcNow;
var counter = CoreDbContext.QuotaRows
.Where(r => r.Path == row.Path && r.Tenant == row.Tenant)
.Select(r => r.Counter)
.Take(1)
.FirstOrDefault();
CoreDbContext.AddOrUpdate(r => r.QuotaRows, dbQuotaRow);
CoreDbContext.SaveChanges();
var dbQuotaRow = new DbQuotaRow
{
Tenant = row.Tenant,
Path = row.Path,
Counter = exchange ? counter + row.Counter : row.Counter,
Tag = row.Tag,
LastModified = DateTime.UtcNow
};
tx.Commit();
}
CoreDbContext.AddOrUpdate(r => r.QuotaRows, dbQuotaRow);
CoreDbContext.SaveChanges();
public IEnumerable<TenantQuotaRow> FindTenantQuotaRows(int tenantId)
{
IQueryable<DbQuotaRow> q = CoreDbContext.QuotaRows;
tx.Commit();
}
public IEnumerable<TenantQuotaRow> FindTenantQuotaRows(int tenantId)
if (tenantId != Tenant.DefaultTenant)
{
IQueryable<DbQuotaRow> q = CoreDbContext.QuotaRows;
if (tenantId != Tenant.DEFAULT_TENANT)
{
q = q.Where(r => r.Tenant == tenantId);
}
return q.Select(FromDbQuotaRowToTenantQuotaRow).ToList();
}
private static long GetInBytes(long bytes)
{
const long MB = 1024 * 1024;
return bytes < MB ? bytes * MB : bytes;
}
private static long GetInMBytes(long bytes)
{
const long MB = 1024 * 1024;
return bytes < MB * MB ? bytes / MB : bytes;
}
}
q = q.Where(r => r.Tenant == tenantId);
}
return q.ProjectTo<TenantQuotaRow>(_mapper.ConfigurationProvider).ToList();
}
}

View File

@ -25,312 +25,320 @@
using JsonSerializer = System.Text.Json.JsonSerializer;
namespace ASC.Core.Data
namespace ASC.Core.Data;
[Singletone]
public class DbSettingsManagerCache
{
[Singletone]
public class DbSettingsManagerCache
{
public ICache Cache { get; }
private ICacheNotify<SettingsCacheItem> Notify { get; }
public DbSettingsManagerCache(ICacheNotify<SettingsCacheItem> notify, ICache cache)
{
Cache = cache;
Notify = notify;
Notify.Subscribe((i) => Cache.Remove(i.Key), ASC.Common.Caching.CacheNotifyAction.Remove);
}
public void Remove(string key)
{
Notify.Publish(new SettingsCacheItem { Key = key }, ASC.Common.Caching.CacheNotifyAction.Remove);
}
}
public ICache Cache { get; }
private readonly ICacheNotify<SettingsCacheItem> _notify;
[Scope]
class ConfigureDbSettingsManager : IConfigureNamedOptions<DbSettingsManager>
public DbSettingsManagerCache(ICacheNotify<SettingsCacheItem> notify, ICache cache)
{
private IServiceProvider ServiceProvider { get; }
private DbSettingsManagerCache DbSettingsManagerCache { get; }
private IOptionsMonitor<ILog> ILog { get; }
private AuthContext AuthContext { get; }
private IOptionsSnapshot<TenantManager> TenantManager { get; }
private DbContextManager<WebstudioDbContext> DbContextManager { get; }
Cache = cache;
_notify = notify;
_notify.Subscribe((i) => Cache.Remove(i.Key), CacheNotifyAction.Remove);
}
public ConfigureDbSettingsManager(
IServiceProvider serviceProvider,
DbSettingsManagerCache dbSettingsManagerCache,
IOptionsMonitor<ILog> iLog,
AuthContext authContext,
IOptionsSnapshot<TenantManager> tenantManager,
DbContextManager<WebstudioDbContext> dbContextManager
)
public void Remove(string key)
{
_notify.Publish(new SettingsCacheItem { Key = key }, CacheNotifyAction.Remove);
}
}
[Scope]
class ConfigureDbSettingsManager : IConfigureNamedOptions<DbSettingsManager>
{
private readonly IServiceProvider _serviceProvider;
private readonly DbSettingsManagerCache _dbSettingsManagerCache;
private readonly IOptionsMonitor<ILog> _logger;
private readonly AuthContext _authContext;
private readonly IOptionsSnapshot<TenantManager> _tenantManager;
private readonly DbContextManager<WebstudioDbContext> _dbContextManager;
public ConfigureDbSettingsManager(
IServiceProvider serviceProvider,
DbSettingsManagerCache dbSettingsManagerCache,
IOptionsMonitor<ILog> 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.CurrentValue;
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 ILog Logger;
internal ICache Cache;
internal IServiceProvider ServiceProvider;
internal DbSettingsManagerCache DbSettingsManagerCache;
internal AuthContext AuthContext;
internal TenantManager TenantManager;
internal Lazy<WebstudioDbContext> LazyWebstudioDbContext;
internal WebstudioDbContext WebstudioDbContext => LazyWebstudioDbContext.Value;
public DbSettingsManager() { }
public DbSettingsManager(
IServiceProvider serviceProvider,
DbSettingsManagerCache dbSettingsManagerCache,
IOptionsMonitor<ILog> option,
AuthContext authContext,
TenantManager tenantManager,
DbContextManager<WebstudioDbContext> dbContextManager)
{
ServiceProvider = serviceProvider;
DbSettingsManagerCache = dbSettingsManagerCache;
AuthContext = authContext;
TenantManager = tenantManager;
Cache = dbSettingsManagerCache.Cache;
Logger = option.CurrentValue;
LazyWebstudioDbContext = new Lazy<WebstudioDbContext>(() => dbContextManager.Value);
}
private int _tenantID;
private int TenantID
{
get
{
ServiceProvider = serviceProvider;
DbSettingsManagerCache = dbSettingsManagerCache;
ILog = iLog;
AuthContext = authContext;
TenantManager = tenantManager;
DbContextManager = dbContextManager;
if (_tenantID == 0) _tenantID = TenantManager.GetCurrentTenant().Id;
return _tenantID;
}
public void Configure(string name, DbSettingsManager options)
}
//
private Guid? _currentUserID;
private Guid CurrentUserID
{
get
{
Configure(options);
_currentUserID ??= AuthContext.CurrentAccount.ID;
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.Log = ILog.CurrentValue;
options.TenantManager = TenantManager.Value;
options.LazyWebstudioDbContext = new Lazy<WebstudioDbContext>(() => DbContextManager.Value);
return _currentUserID.Value;
}
}
[Scope(typeof(ConfigureDbSettingsManager))]
public class DbSettingsManager
{
private readonly TimeSpan expirationTimeout = TimeSpan.FromMinutes(5);
internal ILog Log { 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 { get; set; }
internal WebstudioDbContext WebstudioDbContext { get => LazyWebstudioDbContext.Value; }
public DbSettingsManager()
{
public bool SaveSettings<T>(T settings, int tenantId) where T : ISettings
{
return SaveSettingsFor(settings, tenantId, Guid.Empty);
}
public T LoadSettings<T>(int tenantId) where T : class, ISettings
{
return LoadSettingsFor<T>(tenantId, Guid.Empty);
}
public void ClearCache<T>(int tenantId) where T : class, ISettings
{
var settings = LoadSettings<T>(tenantId);
var key = settings.ID.ToString() + tenantId + Guid.Empty;
DbSettingsManagerCache.Remove(key);
}
public bool SaveSettingsFor<T>(T settings, int tenantId, Guid userId) where T : ISettings
{
if (settings == null)
{
throw new ArgumentNullException(nameof(settings));
}
public DbSettingsManager(
IServiceProvider serviceProvider,
DbSettingsManagerCache dbSettingsManagerCache,
IOptionsMonitor<ILog> option,
AuthContext authContext,
TenantManager tenantManager,
DbContextManager<WebstudioDbContext> dbContextManager)
{
ServiceProvider = serviceProvider;
DbSettingsManagerCache = dbSettingsManagerCache;
AuthContext = authContext;
TenantManager = tenantManager;
Cache = dbSettingsManagerCache.Cache;
Log = option.CurrentValue;
LazyWebstudioDbContext = new Lazy<WebstudioDbContext>(() => dbContextManager.Value);
}
private int tenantID;
private int TenantID
{
get
try
{
var key = settings.ID.ToString() + tenantId + userId;
var data = Serialize(settings);
var def = (T)settings.GetDefault(ServiceProvider);
var defaultData = Serialize(def);
if (data.SequenceEqual(defaultData))
{
if (tenantID == 0) tenantID = TenantManager.GetCurrentTenant().TenantId;
return tenantID;
}
}
//
private Guid? currentUserID;
private Guid CurrentUserID
{
get
{
currentUserID ??= AuthContext.CurrentAccount.ID;
return currentUserID.Value;
}
}
public bool SaveSettings<T>(T settings, int tenantId) where T : ISettings
{
return SaveSettingsFor(settings, tenantId, Guid.Empty);
}
public T LoadSettings<T>(int tenantId) where T : class, ISettings
{
return LoadSettingsFor<T>(tenantId, Guid.Empty);
}
public void ClearCache<T>(int tenantId) where T : class, ISettings
{
var settings = LoadSettings<T>(tenantId);
var key = settings.ID.ToString() + tenantId + Guid.Empty;
DbSettingsManagerCache.Remove(key);
}
public bool SaveSettingsFor<T>(T settings, int tenantId, Guid userId) where T : ISettings
{
if (settings == null) throw new ArgumentNullException(nameof(settings));
try
{
var key = settings.ID.ToString() + tenantId + userId;
var data = Serialize(settings);
var def = (T)settings.GetDefault(ServiceProvider);
var defaultData = Serialize(def);
if (data.SequenceEqual(defaultData))
using var tr = WebstudioDbContext.Database.BeginTransaction();
// remove default settings
var s = WebstudioDbContext.WebstudioSettings
.Where(r => r.Id == settings.ID)
.Where(r => r.TenantId == tenantId)
.Where(r => r.UserId == userId)
.FirstOrDefault();
if (s != null)
{
using var tr = WebstudioDbContext.Database.BeginTransaction();
// remove default settings
var s = WebstudioDbContext.WebstudioSettings
.Where(r => r.Id == settings.ID)
.Where(r => r.TenantId == tenantId)
.Where(r => r.UserId == userId)
.FirstOrDefault();
if (s != null)
{
WebstudioDbContext.WebstudioSettings.Remove(s);
}
WebstudioDbContext.WebstudioSettings.Remove(s);
}
WebstudioDbContext.SaveChanges();
tr.Commit();
}
else
{
var s = new DbWebstudioSettings
{
Id = settings.ID,
UserId = userId,
TenantId = tenantId,
Data = data
};
WebstudioDbContext.AddOrUpdate(r => r.WebstudioSettings, s);
WebstudioDbContext.SaveChanges();
}
DbSettingsManagerCache.Remove(key);
Cache.Insert(key, settings, expirationTimeout);
return true;
}
catch (Exception ex)
{
Log.Error(ex);
return false;
}
}
internal T LoadSettingsFor<T>(int tenantId, Guid userId) where T : class, ISettings
{
var settingsInstance = ActivatorUtilities.CreateInstance<T>(ServiceProvider);
var key = settingsInstance.ID.ToString() + tenantId + userId;
var def = (T)settingsInstance.GetDefault(ServiceProvider);
try
{
var settings = Cache.Get<T>(key);
if (settings != null) return settings;
var result = WebstudioDbContext.WebstudioSettings
.Where(r => r.Id == settingsInstance.ID)
.Where(r => r.TenantId == tenantId)
.Where(r => r.UserId == userId)
.Select(r => r.Data)
.FirstOrDefault();
if (result != null)
{
settings = Deserialize<T>(result);
}
else
{
settings = def;
}
Cache.Insert(key, settings, expirationTimeout);
return settings;
}
catch (Exception ex)
{
Log.Error(ex);
}
return def;
}
public T Load<T>() where T : class, ISettings
{
return LoadSettings<T>(TenantID);
}
public T LoadForCurrentUser<T>() where T : class, ISettings
{
return LoadForUser<T>(CurrentUserID);
}
public T LoadForUser<T>(Guid userId) where T : class, ISettings
{
return LoadSettingsFor<T>(TenantID, userId);
}
public T LoadForDefaultTenant<T>() where T : class, ISettings
{
return LoadForTenant<T>(Tenant.DEFAULT_TENANT);
}
public T LoadForTenant<T>(int tenantId) where T : class, ISettings
{
return LoadSettings<T>(tenantId);
}
public virtual bool Save<T>(T data) where T : class, ISettings
{
return SaveSettings(data, TenantID);
}
public bool SaveForCurrentUser<T>(T data) where T : class, ISettings
{
return SaveForUser(data, CurrentUserID);
}
public bool SaveForUser<T>(T data, Guid userId) where T : class, ISettings
{
return SaveSettingsFor(data, TenantID, userId);
}
public bool SaveForDefaultTenant<T>(T data) where T : class, ISettings
{
return SaveForTenant(data, Tenant.DEFAULT_TENANT);
}
public bool SaveForTenant<T>(T data, int tenantId) where T : class, ISettings
{
return SaveSettings(data, tenantId);
}
public void ClearCache<T>() where T : class, ISettings
{
ClearCache<T>(TenantID);
}
private T Deserialize<T>(string data)
{
var options = new JsonSerializerOptions
WebstudioDbContext.SaveChanges();
tr.Commit();
}
else
{
PropertyNameCaseInsensitive = true
};
var s = new DbWebstudioSettings
{
Id = settings.ID,
UserId = userId,
TenantId = tenantId,
Data = data
};
return JsonSerializer.Deserialize<T>(data, options);
}
private string Serialize<T>(T settings)
WebstudioDbContext.AddOrUpdate(r => r.WebstudioSettings, s);
WebstudioDbContext.SaveChanges();
}
DbSettingsManagerCache.Remove(key);
Cache.Insert(key, settings, _expirationTimeout);
return true;
}
catch (Exception ex)
{
return JsonSerializer.Serialize(settings);
}
}
}
Logger.Error(ex);
return false;
}
}
internal T LoadSettingsFor<T>(int tenantId, Guid userId) where T : class, ISettings
{
var settingsInstance = ActivatorUtilities.CreateInstance<T>(ServiceProvider);
var key = settingsInstance.ID.ToString() + tenantId + userId;
var def = (T)settingsInstance.GetDefault(ServiceProvider);
try
{
var settings = Cache.Get<T>(key);
if (settings != null)
{
return settings;
}
var result = WebstudioDbContext.WebstudioSettings
.Where(r => r.Id == settingsInstance.ID)
.Where(r => r.TenantId == tenantId)
.Where(r => r.UserId == userId)
.Select(r => r.Data)
.FirstOrDefault();
if (result != null)
{
settings = Deserialize<T>(result);
}
else
{
settings = def;
}
Cache.Insert(key, settings, _expirationTimeout);
return settings;
}
catch (Exception ex)
{
Logger.Error(ex);
}
return def;
}
public T Load<T>() where T : class, ISettings
{
return LoadSettings<T>(TenantID);
}
public T LoadForCurrentUser<T>() where T : class, ISettings
{
return LoadForUser<T>(CurrentUserID);
}
public T LoadForUser<T>(Guid userId) where T : class, ISettings
{
return LoadSettingsFor<T>(TenantID, userId);
}
public T LoadForDefaultTenant<T>() where T : class, ISettings
{
return LoadForTenant<T>(Tenant.DefaultTenant);
}
public T LoadForTenant<T>(int tenantId) where T : class, ISettings
{
return LoadSettings<T>(tenantId);
}
public virtual bool Save<T>(T data) where T : class, ISettings
{
return SaveSettings(data, TenantID);
}
public bool SaveForCurrentUser<T>(T data) where T : class, ISettings
{
return SaveForUser(data, CurrentUserID);
}
public bool SaveForUser<T>(T data, Guid userId) where T : class, ISettings
{
return SaveSettingsFor(data, TenantID, userId);
}
public bool SaveForDefaultTenant<T>(T data) where T : class, ISettings
{
return SaveForTenant(data, Tenant.DefaultTenant);
}
public bool SaveForTenant<T>(T data, int tenantId) where T : class, ISettings
{
return SaveSettings(data, tenantId);
}
public void ClearCache<T>() where T : class, ISettings
{
ClearCache<T>(TenantID);
}
private T Deserialize<T>(string data)
{
var options = new JsonSerializerOptions
{
PropertyNameCaseInsensitive = true
};
return JsonSerializer.Deserialize<T>(data, options);
}
private string Serialize<T>(T settings)
{
return JsonSerializer.Serialize(settings);
}
}

View File

@ -23,308 +23,345 @@
*
*/
namespace ASC.Core.Data
namespace ASC.Core.Data;
[Scope]
public class DbSubscriptionService : ISubscriptionService
{
[Scope]
public class DbSubscriptionService : ISubscriptionService
private readonly Lazy<UserDbContext> _lazyUserDbContext;
private UserDbContext UserDbContext => _lazyUserDbContext.Value;
private readonly IMapper _mapper;
public DbSubscriptionService(DbContextManager<UserDbContext> dbContextManager, IMapper mapper)
{
private Expression<Func<Subscription, SubscriptionRecord>> FromSubscriptionToSubscriptionRecord { get; set; }
private Expression<Func<DbSubscriptionMethod, SubscriptionMethod>> FromDbSubscriptionMethodToSubscriptionMethod { get; set; }
private Lazy<UserDbContext> LazyUserDbContext { get; }
private UserDbContext UserDbContext { get => LazyUserDbContext.Value; }
public DbSubscriptionService(DbContextManager<UserDbContext> dbContextManager)
{
LazyUserDbContext = new Lazy<UserDbContext>(() => dbContextManager.Value);
_lazyUserDbContext = new Lazy<UserDbContext>(() => dbContextManager.Value);
_mapper = mapper;
}
FromSubscriptionToSubscriptionRecord = r => new SubscriptionRecord
{
ActionId = r.Action,
ObjectId = r.Object,
RecipientId = r.Recipient,
SourceId = r.Source,
Subscribed = !r.Unsubscribed,
Tenant = r.Tenant
};
FromDbSubscriptionMethodToSubscriptionMethod = r => new SubscriptionMethod
{
ActionId = r.Action,
RecipientId = r.Recipient,
SourceId = r.Source,
Tenant = r.Tenant,
MethodsFromDb = r.Sender
};
public string[] GetRecipients(int tenant, string sourceId, string actionId, string objectId)
{
if (sourceId == null)
{
throw new ArgumentNullException(nameof(sourceId));
}
if (actionId == null)
{
throw new ArgumentNullException(nameof(actionId));
}
public string[] GetRecipients(int tenant, string sourceId, string actionId, string objectId)
var q = GetQuery(tenant, sourceId, actionId)
.Where(r => r.Object == (objectId ?? string.Empty))
.Where(r => !r.Unsubscribed)
.Select(r => r.Recipient)
.Distinct();
return q.ToArray();
}
public IEnumerable<SubscriptionRecord> GetSubscriptions(int tenant, string sourceId, string actionId)
{
if (sourceId == null)
{
if (sourceId == null) throw new ArgumentNullException(nameof(sourceId));
if (actionId == null) throw new ArgumentNullException(nameof(actionId));
var q = GetQuery(tenant, sourceId, actionId)
.Where(r => r.Object == (objectId ?? string.Empty))
.Where(r => !r.Unsubscribed)
.Select(r => r.Recipient)
.Distinct();
return q.ToArray();
throw new ArgumentNullException(nameof(sourceId));
}
if (actionId == null)
{
throw new ArgumentNullException(nameof(actionId));
}
public IEnumerable<SubscriptionRecord> GetSubscriptions(int tenant, string sourceId, string actionId)
{
if (sourceId == null) throw new ArgumentNullException(nameof(sourceId));
if (actionId == null) throw new ArgumentNullException(nameof(actionId));
var q = GetQuery(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);
if (recipientId != null)
{
q = q.Where(r => r.Recipient == recipientId);
}
else
{
q = q.Where(r => r.Object == (objectId ?? string.Empty));
}
return GetSubscriptions(q, tenant);
}
public SubscriptionRecord GetSubscription(int tenant, string sourceId, string actionId, string recipientId, string objectId)
{
if (recipientId == null) throw new ArgumentNullException(nameof(recipientId));
var q = GetQuery(tenant, sourceId, actionId)
.Where(r => r.Recipient == recipientId)
.Where(r => r.Object == (objectId ?? string.Empty));
return GetSubscriptions(q, tenant).Take(1).FirstOrDefault();
}
var q = GetQuery(tenant, sourceId, actionId);
public bool IsUnsubscribe(int tenant, string sourceId, string actionId, string recipientId, string objectId)
return GetSubscriptions(q, tenant);
}
public IEnumerable<SubscriptionRecord> GetSubscriptions(int tenant, string sourceId, string actionId, string recipientId, string objectId)
{
var q = GetQuery(tenant, sourceId, actionId);
if (recipientId != null)
{
if (recipientId == null) throw new ArgumentNullException(nameof(recipientId));
if (sourceId == null) throw new ArgumentNullException(nameof(sourceId));
if (actionId == null) throw new ArgumentNullException(nameof(actionId));
q = q.Where(r => r.Recipient == recipientId);
}
else
{
q = q.Where(r => r.Object == (objectId ?? string.Empty));
}
return GetSubscriptions(q, tenant);
}
public SubscriptionRecord GetSubscription(int tenant, string sourceId, string actionId, string recipientId, string objectId)
{
if (recipientId == null)
{
throw new ArgumentNullException(nameof(recipientId));
}
var q = GetQuery(tenant, sourceId, actionId)
.Where(r => r.Recipient == recipientId)
.Where(r => r.Object == (objectId ?? string.Empty));
return GetSubscriptions(q, tenant).Take(1).FirstOrDefault();
}
var q = UserDbContext.Subscriptions
.Where(r => r.Source == sourceId &&
r.Action == actionId &&
r.Tenant == tenant &&
r.Recipient == recipientId &&
r.Unsubscribed);
public bool IsUnsubscribe(int tenant, string sourceId, string actionId, string recipientId, string objectId)
{
if (recipientId == null)
{
throw new ArgumentNullException(nameof(recipientId));
}
if (sourceId == null)
{
throw new ArgumentNullException(nameof(sourceId));
}
if (actionId == null)
{
throw new ArgumentNullException(nameof(actionId));
}
if (!string.IsNullOrEmpty(objectId))
var q = UserDbContext.Subscriptions
.Where(r => r.Source == sourceId &&
r.Action == actionId &&
r.Tenant == tenant &&
r.Recipient == recipientId &&
r.Unsubscribed);
if (!string.IsNullOrEmpty(objectId))
{
q = q.Where(r => r.Object == objectId || r.Object == string.Empty);
}
else
{
q = q.Where(r => r.Object == string.Empty);
}
return q.Any();
}
public string[] GetSubscriptions(int tenant, string sourceId, string actionId, string recipientId, bool checkSubscribe)
{
if (recipientId == null)
{
throw new ArgumentNullException(nameof(recipientId));
}
if (sourceId == null)
{
throw new ArgumentNullException(nameof(sourceId));
}
if (actionId == null)
{
throw new ArgumentNullException(nameof(actionId));
}
var q = GetQuery(tenant, sourceId, actionId)
.Where(r => r.Recipient == recipientId)
.Distinct();
if (checkSubscribe)
{
q = q.Where(r => !r.Unsubscribed);
}
return q.Select(r => r.Object).ToArray();
}
public void SaveSubscription(SubscriptionRecord s)
{
if (s == null)
{
throw new ArgumentNullException(nameof(s));
}
var subs = new Subscription
{
Action = s.ActionId,
Object = s.ObjectId ?? string.Empty,
Recipient = s.RecipientId,
Source = s.SourceId,
Unsubscribed = !s.Subscribed,
Tenant = s.Tenant
};
UserDbContext.AddOrUpdate(r => r.Subscriptions, subs);
UserDbContext.SaveChanges();
}
public void RemoveSubscriptions(int tenant, string sourceId, string actionId)
{
RemoveSubscriptions(tenant, sourceId, actionId, string.Empty);
}
public void RemoveSubscriptions(int tenant, string sourceId, string actionId, string objectId)
{
if (sourceId == null)
{
throw new ArgumentNullException(nameof(sourceId));
}
if (actionId == null)
{
throw new ArgumentNullException(nameof(actionId));
}
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);
if (objectId.Length != 0)
{
q = q.Where(r => r.Object == (objectId ?? string.Empty));
}
var sub = q.FirstOrDefault();
if (sub != null)
{
UserDbContext.Subscriptions.Remove(sub);
}
tr.Commit();
}
public IEnumerable<SubscriptionMethod> GetSubscriptionMethods(int tenant, string sourceId, string actionId, string recipientId)
{
if (sourceId == null)
{
throw new ArgumentNullException(nameof(sourceId));
}
if (actionId == null)
{
throw new ArgumentNullException(nameof(actionId));
}
var q = UserDbContext.SubscriptionMethods
.Where(r => r.Tenant == -1 || r.Tenant == tenant)
.Where(r => r.Source == sourceId);
if (recipientId != null)
{
q = q.Where(r => r.Recipient == recipientId);
}
var a = q
.OrderBy(r => r.Tenant)
.Distinct();
var methods = a.ToList();
var result = new List<SubscriptionMethod>();
var common = new Dictionary<string, SubscriptionMethod>();
foreach (var r in methods)
{
var m = _mapper.Map<DbSubscriptionMethod, SubscriptionMethod>(r);
var key = m.Source + m.Action + m.Recipient;
if (m.Tenant == Tenant.DefaultTenant)
{
q = q.Where(r => r.Object == objectId || r.Object == string.Empty);
m.Tenant = tenant;
common.Add(key, m);
result.Add(m);
}
else
{
q = q.Where(r => r.Object == string.Empty);
if (!common.TryGetValue(key, out var rec))
{
result.Add(rec);
}
}
return q.Any();
}
public string[] GetSubscriptions(int tenant, string sourceId, string actionId, string recipientId, bool checkSubscribe)
return result;
}
public void SetSubscriptionMethod(SubscriptionMethod m)
{
if (m == null)
{
if (recipientId == null) throw new ArgumentNullException(nameof(recipientId));
if (sourceId == null) throw new ArgumentNullException(nameof(sourceId));
if (actionId == null) throw new ArgumentNullException(nameof(actionId));
var q = GetQuery(tenant, sourceId, actionId)
.Where(r => r.Recipient == recipientId)
.Distinct();
if (checkSubscribe)
{
q = q.Where(r => !r.Unsubscribed);
}
return q.Select(r => r.Object).ToArray();
throw new ArgumentNullException(nameof(m));
}
public void SaveSubscription(SubscriptionRecord s)
{
if (s == null) throw new ArgumentNullException(nameof(s));
var subs = new Subscription
{
Action = s.ActionId,
Object = s.ObjectId ?? string.Empty,
Recipient = s.RecipientId,
Source = s.SourceId,
Unsubscribed = !s.Subscribed,
Tenant = s.Tenant
};
UserDbContext.AddOrUpdate(r => r.Subscriptions, subs);
UserDbContext.SaveChanges();
}
public void RemoveSubscriptions(int tenant, string sourceId, string actionId)
{
RemoveSubscriptions(tenant, sourceId, actionId, string.Empty);
}
public void RemoveSubscriptions(int tenant, string sourceId, string actionId, string objectId)
{
if (sourceId == null) throw new ArgumentNullException(nameof(sourceId));
if (actionId == null) throw new ArgumentNullException(nameof(actionId));
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);
if (objectId.Length != 0)
{
q = q.Where(r => r.Object == (objectId ?? string.Empty));
}
var sub = q.FirstOrDefault();
if (sub != null)
{
UserDbContext.Subscriptions.Remove(sub);
}
tr.Commit();
}
public IEnumerable<SubscriptionMethod> GetSubscriptionMethods(int tenant, string sourceId, string actionId, string recipientId)
{
if (sourceId == null) throw new ArgumentNullException(nameof(sourceId));
if (actionId == null) throw new ArgumentNullException(nameof(actionId));
using var tr = UserDbContext.Database.BeginTransaction();
if (m.Methods == null || m.Methods.Length == 0)
{
var q = UserDbContext.SubscriptionMethods
.Where(r => r.Tenant == -1 || r.Tenant == tenant)
.Where(r => r.Source == sourceId);
.Where(r => r.Tenant == m.Tenant)
.Where(r => r.Source == m.Source)
.Where(r => r.Recipient == m.Recipient)
.Where(r => r.Action == m.Action);
if (recipientId != null)
var sm = q.FirstOrDefault();
if (sm != null)
{
q = q.Where(r => r.Recipient == recipientId);
UserDbContext.SubscriptionMethods.Remove(sm);
}
var a = q
.OrderBy(r => r.Tenant)
.Distinct();
var methods = a.ToList();
var result = new List<SubscriptionMethod>();
var common = new Dictionary<string, SubscriptionMethod>();
var conv = FromDbSubscriptionMethodToSubscriptionMethod.Compile();
foreach (var r in methods)
}
else
{
var sm = new DbSubscriptionMethod
{
var m = conv(r);
var key = m.SourceId + m.ActionId + m.RecipientId;
if (m.Tenant == Tenant.DEFAULT_TENANT)
{
m.Tenant = tenant;
common.Add(key, m);
result.Add(m);
}
else
{
if (!common.TryGetValue(key, out var rec))
{
result.Add(rec);
}
}
}
return result;
}
Action = m.Action,
Recipient = m.Recipient,
Source = m.Source,
Tenant = m.Tenant,
Sender = string.Join("|", m.Methods)
};
UserDbContext.AddOrUpdate(r => r.SubscriptionMethods, sm);
}
UserDbContext.SaveChanges();
tr.Commit();
}
public void SetSubscriptionMethod(SubscriptionMethod m)
{
if (m == null) throw new ArgumentNullException(nameof(m));
using var tr = UserDbContext.Database.BeginTransaction();
if (m.Methods == null || m.Methods.Length == 0)
private IQueryable<Subscription> GetQuery(int tenant, string sourceId, string actionId)
{
if (sourceId == null)
{
throw new ArgumentNullException(nameof(sourceId));
}
if (actionId == null)
{
throw new ArgumentNullException(nameof(actionId));
}
return
UserDbContext.Subscriptions
.Where(r => r.Source == sourceId)
.Where(r => r.Action == actionId)
.Where(r => r.Tenant == -1 || r.Tenant == tenant)
.OrderBy(r => r.Tenant);
}
private IEnumerable<SubscriptionRecord> GetSubscriptions(IQueryable<Subscription> q, int tenant)
{
var subs = q.ToList();
var result = new List<SubscriptionRecord>();
var common = new Dictionary<string, SubscriptionRecord>();
foreach (var r in subs)
{
var s = _mapper.Map<Subscription, SubscriptionRecord>(r);
var key = s.SourceId + s.ActionId + s.RecipientId + s.ObjectId;
if (s.Tenant == Tenant.DefaultTenant)
{
var q = UserDbContext.SubscriptionMethods
.Where(r => r.Tenant == m.Tenant)
.Where(r => r.Source == m.SourceId)
.Where(r => r.Recipient == m.RecipientId)
.Where(r => r.Action == m.ActionId);
var sm = q.FirstOrDefault();
if (sm != null)
{
UserDbContext.SubscriptionMethods.Remove(sm);
}
}
else
{
var sm = new DbSubscriptionMethod
{
Action = m.ActionId,
Recipient = m.RecipientId,
Source = m.SourceId,
Tenant = m.Tenant,
Sender = string.Join("|", m.Methods)
};
UserDbContext.AddOrUpdate(r => r.SubscriptionMethods, sm);
s.Tenant = tenant;
common.Add(key, s);
result.Add(s);
}
UserDbContext.SaveChanges();
tr.Commit();
}
private IQueryable<Subscription> GetQuery(int tenant, string sourceId, string actionId)
{
if (sourceId == null) throw new ArgumentNullException(nameof(sourceId));
if (actionId == null) throw new ArgumentNullException(nameof(actionId));
return
UserDbContext.Subscriptions
.Where(r => r.Source == sourceId)
.Where(r => r.Action == actionId)
.Where(r => r.Tenant == -1 || r.Tenant == tenant)
.OrderBy(r => r.Tenant)
;
}
private IEnumerable<SubscriptionRecord> GetSubscriptions(IQueryable<Subscription> q, int tenant)
{
var subs = q.ToList();
var result = new List<SubscriptionRecord>();
var common = new Dictionary<string, SubscriptionRecord>();
var conv = FromSubscriptionToSubscriptionRecord.Compile();
foreach (var r in subs)
else
{
var s = conv(r);
var key = s.SourceId + s.ActionId + s.RecipientId + s.ObjectId;
if (s.Tenant == Tenant.DEFAULT_TENANT)
{
s.Tenant = tenant;
common.Add(key, s);
result.Add(s);
}
else
{
if (!common.TryGetValue(key, out _))
{
result.Add(s);
}
}
}
return result;
}
}
if (!common.TryGetValue(key, out _))
{
result.Add(s);
}
}
}
return result;
}
}

View File

@ -23,503 +23,461 @@
*
*/
namespace ASC.Core.Data
using AutoMapper.QueryableExtensions;
namespace ASC.Core.Data;
[Scope]
public class ConfigureDbTenantService : IConfigureNamedOptions<DbTenantService>
{
[Scope]
public class ConfigureDbTenantService : IConfigureNamedOptions<DbTenantService>
private readonly TenantDomainValidator _tenantDomainValidator;
private readonly DbContextManager<TenantDbContext> _dbContextManager;
public ConfigureDbTenantService(
TenantDomainValidator tenantDomainValidator,
DbContextManager<TenantDbContext> dbContextManager)
{
private TenantDomainValidator TenantDomainValidator { get; }
private DbContextManager<TenantDbContext> DbContextManager { get; }
_tenantDomainValidator = tenantDomainValidator;
_dbContextManager = dbContextManager;
}
public ConfigureDbTenantService(
TenantDomainValidator tenantDomainValidator,
DbContextManager<TenantDbContext> 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
{
private List<string> _forbiddenDomains;
internal TenantDomainValidator TenantDomainValidator;
private readonly MachinePseudoKeys _machinePseudoKeys;
internal TenantDbContext TenantDbContext => LazyTenantDbContext.Value;
internal Lazy<TenantDbContext> LazyTenantDbContext;
internal UserDbContext UserDbContext => LazyUserDbContext.Value;
internal Lazy<UserDbContext> LazyUserDbContext;
private readonly IMapper _mapper;
public DbTenantService(
DbContextManager<TenantDbContext> dbContextManager,
DbContextManager<UserDbContext> DbContextManager,
TenantDomainValidator tenantDomainValidator,
MachinePseudoKeys machinePseudoKeys,
IMapper mapper)
{
LazyTenantDbContext = new Lazy<TenantDbContext>(() => dbContextManager.Value);
LazyUserDbContext = new Lazy<UserDbContext>(() => DbContextManager.Value);
TenantDomainValidator = tenantDomainValidator;
_machinePseudoKeys = machinePseudoKeys;
_mapper = mapper;
}
public void ValidateDomain(string domain)
{
using var tr = TenantDbContext.Database.BeginTransaction();
ValidateDomain(domain, Tenant.DefaultTenant, true);
}
public IEnumerable<Tenant> GetTenants(DateTime from, bool active = true)
{
var q = TenantsQuery();
if (active)
{
TenantDomainValidator = tenantDomainValidator;
DbContextManager = dbContextManager;
q = q.Where(r => r.Status == TenantStatus.Active);
}
public void Configure(string name, DbTenantService options)
if (from != default)
{
Configure(options);
options.LazyTenantDbContext = new Lazy<TenantDbContext>(() => DbContextManager.Get(name));
q = q.Where(r => r.LastModified >= from);
}
public void Configure(DbTenantService options)
return q.ProjectTo<Tenant>(_mapper.ConfigurationProvider).ToList();
}
public IEnumerable<Tenant> GetTenants(List<int> ids)
{
var q = TenantsQuery();
return q.Where(r => ids.Contains(r.Id) && r.Status == TenantStatus.Active)
.ProjectTo<Tenant>(_mapper.ConfigurationProvider).ToList();
}
public IEnumerable<Tenant> GetTenants(string login, string passwordHash)
{
if (string.IsNullOrEmpty(login))
{
options.TenantDomainValidator = TenantDomainValidator;
options.LazyTenantDbContext = new Lazy<TenantDbContext>(() => DbContextManager.Value);
throw new ArgumentNullException(nameof(login));
}
IQueryable<TenantUserSecurity> query() => TenantsQuery()
.Where(r => r.Status == TenantStatus.Active)
.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
{
DbTenant = tenantUser.tenant,
User = tenantUser.user,
UserSecurity = security
})
.Where(r => r.User.Status == EmployeeStatus.Active)
.Where(r => r.DbTenant.Status == TenantStatus.Active)
.Where(r => !r.User.Removed);
if (passwordHash == null)
{
var q = query()
.Where(r => login.Contains('@') ? r.User.Email == login : r.User.Id.ToString() == login);
return q.ProjectTo<Tenant>(_mapper.ConfigurationProvider).ToList();
}
if (Guid.TryParse(login, out var userId))
{
var pwdHash = GetPasswordHash(userId, passwordHash);
var oldHash = Hasher.Base64Hash(passwordHash, HashAlg.SHA256);
var q = query()
.Where(r => r.User.Id == userId)
.Where(r => r.UserSecurity.PwdHash == pwdHash || r.UserSecurity.PwdHash == oldHash) //todo: remove old scheme
;
return q.ProjectTo<Tenant>(_mapper.ConfigurationProvider).ToList();
}
else
{
var oldHash = Hasher.Base64Hash(passwordHash, HashAlg.SHA256);
var q =
query()
.Where(r => r.UserSecurity.PwdHash == oldHash);
if (login.Contains('@'))
{
q = q.Where(r => r.User.Email == login);
}
else if (Guid.TryParse(login, out var uId))
{
q = q.Where(r => r.User.Id == uId);
}
//old password
var result = q.ProjectTo<Tenant>(_mapper.ConfigurationProvider).ToList();
var usersQuery = UserDbContext.Users
.Where(r => r.Email == login)
.Where(r => r.Status == EmployeeStatus.Active)
.Where(r => !r.Removed)
.Select(r => r.Id)
.ToList();
var passwordHashs = usersQuery.Select(r => GetPasswordHash(r, passwordHash)).ToList();
q = query()
.Where(r => passwordHashs.Any(p => r.UserSecurity.PwdHash == p) && r.DbTenant.Status == TenantStatus.Active);
//new password
result = result.Concat(q.ProjectTo<Tenant>(_mapper.ConfigurationProvider)).ToList();
return result.Distinct();
}
}
[Scope]
public class DbTenantService : ITenantService
{
private List<string> forbiddenDomains;
public Tenant GetTenant(int id)
{
return TenantsQuery()
.Where(r => r.Id == id)
.ProjectTo<Tenant>(_mapper.ConfigurationProvider)
.SingleOrDefault();
}
internal TenantDomainValidator TenantDomainValidator { get; set; }
private MachinePseudoKeys MachinePseudoKeys { get; }
internal TenantDbContext TenantDbContext { get => LazyTenantDbContext.Value; }
internal Lazy<TenantDbContext> LazyTenantDbContext { get; set; }
internal UserDbContext UserDbContext { get => LazyUserDbContext.Value; }
internal Lazy<UserDbContext> LazyUserDbContext { get; set; }
private static Expression<Func<DbTenant, Tenant>> FromDbTenantToTenant { get; set; }
private static Expression<Func<TenantUserSecurity, Tenant>> FromTenantUserToTenant { get; set; }
static DbTenantService()
public Tenant GetTenant(string domain)
{
if (string.IsNullOrEmpty(domain))
{
FromDbTenantToTenant = r => new Tenant
{
Calls = r.Calls,
CreatedDateTime = r.CreationDateTime,
Industry = r.Industry != null ? r.Industry.Value : TenantIndustry.Other,
Language = r.Language,
LastModified = r.LastModified,
Name = r.Name,
OwnerId = r.OwnerId,
PaymentId = r.PaymentId,
Spam = r.Spam,
Status = r.Status,
StatusChangeDate = r.StatusChangedHack,
TenantAlias = r.Alias,
TenantId = r.Id,
MappedDomain = r.MappedDomain,
Version = r.Version,
VersionChanged = r.VersionChanged,
TrustedDomainsRaw = r.TrustedDomains,
TrustedDomainsType = r.TrustedDomainsEnabled,
//AffiliateId = r.Partner != null ? r.Partner.AffiliateId : null,
//PartnerId = r.Partner != null ? r.Partner.PartnerId : null,
TimeZone = r.TimeZone,
//Campaign = r.Partner != null ? r.Partner.Campaign : null
};
var fromDbTenantToTenant = FromDbTenantToTenant.Compile();
FromTenantUserToTenant = r => fromDbTenantToTenant(r.DbTenant);
throw new ArgumentNullException(nameof(domain));
}
public DbTenantService()
{
domain = domain.ToLowerInvariant();
return TenantsQuery()
.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)
.ProjectTo<Tenant>(_mapper.ConfigurationProvider)
.FirstOrDefault();
}
public Tenant GetTenantForStandaloneWithoutAlias(string ip)
{
return TenantsQuery()
.OrderBy(a => a.Status)
.ThenByDescending(a => a.Id)
.ProjectTo<Tenant>(_mapper.ConfigurationProvider)
.FirstOrDefault();
}
public Tenant SaveTenant(CoreSettings coreSettings, Tenant t)
{
if (t == null)
{
throw new ArgumentNullException("tenant");
}
public DbTenantService(
DbContextManager<TenantDbContext> dbContextManager,
DbContextManager<UserDbContext> DbContextManager,
TenantDomainValidator tenantDomainValidator,
MachinePseudoKeys machinePseudoKeys)
using var tx = TenantDbContext.Database.BeginTransaction();
if (!string.IsNullOrEmpty(t.MappedDomain))
{
LazyTenantDbContext = new Lazy<TenantDbContext>(() => dbContextManager.Value);
LazyUserDbContext = new Lazy<UserDbContext>(() => DbContextManager.Value);
TenantDomainValidator = tenantDomainValidator;
MachinePseudoKeys = machinePseudoKeys;
}
public void ValidateDomain(string domain)
{
using var tr = TenantDbContext.Database.BeginTransaction();
ValidateDomain(domain, Tenant.DEFAULT_TENANT, true);
}
public IEnumerable<Tenant> GetTenants(DateTime from, bool active = true)
{
var q = TenantsQuery();
var baseUrl = coreSettings.GetBaseDomain(t.HostedRegion);
if (active)
if (baseUrl != null && t.MappedDomain.EndsWith("." + baseUrl, StringComparison.InvariantCultureIgnoreCase))
{
q = q.Where(r => r.Status == TenantStatus.Active);
}
if (from != default)
{
q = q.Where(r => r.LastModified >= from);
}
return q.Select(FromDbTenantToTenant).ToList();
}
public IEnumerable<Tenant> GetTenants(List<int> ids)
{
var q = TenantsQuery();
return q.Where(r => ids.Contains(r.Id) && r.Status == TenantStatus.Active).Select(FromDbTenantToTenant).ToList();
}
public IEnumerable<Tenant> GetTenants(string login, string passwordHash)
{
if (string.IsNullOrEmpty(login)) throw new ArgumentNullException(nameof(login));
IQueryable<TenantUserSecurity> query() => TenantsQuery()
.Where(r => r.Status == TenantStatus.Active)
.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
{
DbTenant = tenantUser.tenant,
User = tenantUser.user,
UserSecurity = security
})
.Where(r => r.User.Status == EmployeeStatus.Active)
.Where(r => r.DbTenant.Status == TenantStatus.Active)
.Where(r => !r.User.Removed);
if (passwordHash == null)
{
var q = query()
.Where(r => login.Contains('@') ? r.User.Email == login : r.User.Id.ToString() == login);
return q.Select(FromTenantUserToTenant).ToList();
}
if (Guid.TryParse(login, out var userId))
{
var pwdHash = GetPasswordHash(userId, passwordHash);
var oldHash = Hasher.Base64Hash(passwordHash, HashAlg.SHA256);
var q = query()
.Where(r => r.User.Id == userId)
.Where(r => r.UserSecurity.PwdHash == pwdHash || r.UserSecurity.PwdHash == oldHash) //todo: remove old scheme
;
return q.Select(FromTenantUserToTenant).ToList();
ValidateDomain(t.MappedDomain.Substring(0, t.MappedDomain.Length - baseUrl.Length - 1), t.Id, false);
}
else
{
var oldHash = Hasher.Base64Hash(passwordHash, HashAlg.SHA256);
ValidateDomain(t.MappedDomain, t.Id, false);
}
}
var q =
query()
.Where(r => r.UserSecurity.PwdHash == oldHash);
if (login.Contains('@'))
{
q = q.Where(r => r.User.Email == login);
}
else if (Guid.TryParse(login, out var uId))
{
q = q.Where(r => r.User.Id == uId);
}
//old password
var result = q.Select(FromTenantUserToTenant).ToList();
var usersQuery = UserDbContext.Users
.Where(r => r.Email == login)
.Where(r => r.Status == EmployeeStatus.Active)
.Where(r => !r.Removed)
.Select(r => r.Id)
.ToList();
var passwordHashs = usersQuery.Select(r => GetPasswordHash(r, passwordHash)).ToList();
q = query()
.Where(r => passwordHashs.Any(p => r.UserSecurity.PwdHash == p) && r.DbTenant.Status == TenantStatus.Active);
//new password
result = result.Concat(q.Select(FromTenantUserToTenant)).ToList();
return result.Distinct();
}
}
public Tenant GetTenant(int id)
{
return TenantsQuery()
.Where(r => r.Id == id)
.Select(FromDbTenantToTenant)
.SingleOrDefault();
}
public Tenant GetTenant(string domain)
{
if (string.IsNullOrEmpty(domain)) throw new ArgumentNullException(nameof(domain));
domain = domain.ToLowerInvariant();
return TenantsQuery()
.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)
.Select(FromDbTenantToTenant)
.FirstOrDefault();
}
public Tenant GetTenantForStandaloneWithoutAlias(string ip)
{
return TenantsQuery()
.OrderBy(a => a.Status)
.ThenByDescending(a => a.Id)
.Select(FromDbTenantToTenant)
.FirstOrDefault();
}
public Tenant SaveTenant(CoreSettings coreSettings, Tenant t)
{
if (t == null) throw new ArgumentNullException("tenant");
using var tx = TenantDbContext.Database.BeginTransaction();
if (!string.IsNullOrEmpty(t.MappedDomain))
{
var baseUrl = coreSettings.GetBaseDomain(t.HostedRegion);
if (baseUrl != null && t.MappedDomain.EndsWith("." + baseUrl, StringComparison.InvariantCultureIgnoreCase))
{
ValidateDomain(t.MappedDomain.Substring(0, t.MappedDomain.Length - baseUrl.Length - 1), t.TenantId, false);
}
else
{
ValidateDomain(t.MappedDomain, t.TenantId, false);
}
}
if (t.TenantId == Tenant.DEFAULT_TENANT)
{
t.Version = TenantDbContext.TenantVersion
.Where(r => r.DefaultVersion == 1 || r.Id == 0)
.OrderByDescending(r => r.Id)
.Select(r => r.Id)
.FirstOrDefault();
t.LastModified = DateTime.UtcNow;
var tenant = new DbTenant
{
Id = t.TenantId,
Alias = t.TenantAlias.ToLowerInvariant(),
MappedDomain = !string.IsNullOrEmpty(t.MappedDomain) ? t.MappedDomain.ToLowerInvariant() : null,
Version = t.Version,
VersionChanged = t.VersionChanged,
Name = t.Name ?? t.TenantAlias,
Language = t.Language,
TimeZone = t.TimeZone,
OwnerId = t.OwnerId,
TrustedDomains = t.GetTrustedDomains(),
TrustedDomainsEnabled = t.TrustedDomainsType,
CreationDateTime = t.CreatedDateTime,
Status = t.Status,
StatusChanged = t.StatusChangeDate,
PaymentId = t.PaymentId,
LastModified = t.LastModified,
Industry = t.Industry,
Spam = t.Spam,
Calls = t.Calls
};
tenant = TenantDbContext.Tenants.Add(tenant).Entity;
TenantDbContext.SaveChanges();
t.TenantId = tenant.Id;
}
else
{
var tenant = TenantDbContext.Tenants
.Where(r => r.Id == t.TenantId)
.FirstOrDefault();
if (tenant != null)
{
tenant.Alias = t.TenantAlias.ToLowerInvariant();
tenant.MappedDomain = !string.IsNullOrEmpty(t.MappedDomain) ? t.MappedDomain.ToLowerInvariant() : null;
tenant.Version = t.Version;
tenant.VersionChanged = t.VersionChanged;
tenant.Name = t.Name ?? t.TenantAlias;
tenant.Language = t.Language;
tenant.TimeZone = t.TimeZone;
tenant.TrustedDomains = t.GetTrustedDomains();
tenant.TrustedDomainsEnabled = t.TrustedDomainsType;
tenant.CreationDateTime = t.CreatedDateTime;
tenant.Status = t.Status;
tenant.StatusChanged = t.StatusChangeDate;
tenant.PaymentId = t.PaymentId;
tenant.LastModified = t.LastModified = DateTime.UtcNow;
tenant.Industry = t.Industry;
tenant.Spam = t.Spam;
tenant.Calls = t.Calls;
}
TenantDbContext.SaveChanges();
}
if (string.IsNullOrEmpty(t.PartnerId) && string.IsNullOrEmpty(t.AffiliateId) && string.IsNullOrEmpty(t.Campaign))
{
var p = TenantDbContext.TenantPartner
.Where(r => r.TenantId == t.TenantId)
.FirstOrDefault();
if (p != null)
{
TenantDbContext.TenantPartner.Remove(p);
}
}
else
{
var tenantPartner = new DbTenantPartner
{
TenantId = t.TenantId,
PartnerId = t.PartnerId,
AffiliateId = t.AffiliateId,
Campaign = t.Campaign
};
TenantDbContext.TenantPartner.Add(tenantPartner);
}
tx.Commit();
//CalculateTenantDomain(t);
return t;
}
public void RemoveTenant(int id, bool auto = false)
{
var postfix = auto ? "_auto_deleted" : "_deleted";
using var tx = TenantDbContext.Database.BeginTransaction();
var alias = TenantDbContext.Tenants
.Where(r => r.Id == id)
.Select(r => r.Alias)
if (t.Id == Tenant.DefaultTenant)
{
t.Version = TenantDbContext.TenantVersion
.Where(r => r.DefaultVersion == 1 || r.Id == 0)
.OrderByDescending(r => r.Id)
.Select(r => r.Id)
.FirstOrDefault();
var count = TenantDbContext.Tenants
.Where(r => r.Alias.StartsWith(alias + postfix))
.Count();
t.LastModified = DateTime.UtcNow;
var tenant = TenantDbContext.Tenants.Where(r => r.Id == id).FirstOrDefault();
var tenant = _mapper.Map<Tenant, DbTenant>(t);
tenant = TenantDbContext.Tenants.Add(tenant).Entity;
TenantDbContext.SaveChanges();
t.Id = tenant.Id;
}
else
{
var tenant = TenantDbContext.Tenants
.Where(r => r.Id == t.Id)
.FirstOrDefault();
if (tenant != null)
{
tenant.Alias = alias + postfix + (count > 0 ? count.ToString() : "");
tenant.Status = TenantStatus.RemovePending;
tenant.StatusChanged = DateTime.UtcNow;
tenant.LastModified = DateTime.UtcNow;
tenant.Alias = t.Alias.ToLowerInvariant();
tenant.MappedDomain = !string.IsNullOrEmpty(t.MappedDomain) ? t.MappedDomain.ToLowerInvariant() : null;
tenant.Version = t.Version;
tenant.VersionChanged = t.VersionChanged;
tenant.Name = t.Name ?? t.Alias;
tenant.Language = t.Language;
tenant.TimeZone = t.TimeZone;
tenant.TrustedDomainsRaw = t.GetTrustedDomains();
tenant.TrustedDomainsEnabled = t.TrustedDomainsType;
tenant.CreationDateTime = t.CreationDateTime;
tenant.Status = t.Status;
tenant.StatusChanged = t.StatusChangeDate;
tenant.PaymentId = t.PaymentId;
tenant.LastModified = t.LastModified = DateTime.UtcNow;
tenant.Industry = t.Industry;
tenant.Spam = t.Spam;
tenant.Calls = t.Calls;
}
TenantDbContext.SaveChanges();
tx.Commit();
}
public IEnumerable<TenantVersion> GetTenantVersions()
{
return TenantDbContext.TenantVersion
.Where(r => r.Visible)
.Select(r => new TenantVersion(r.Id, r.Version))
.ToList();
}
public byte[] GetTenantSettings(int tenant, string key)
{
return TenantDbContext.CoreSettings
.Where(r => r.Tenant == tenant)
.Where(r => r.Id == key)
.Select(r => r.Value)
.FirstOrDefault();
}
public void SetTenantSettings(int tenant, string key, byte[] data)
{
using var tx = TenantDbContext.Database.BeginTransaction();
if (data == null || data.Length == 0)
{
var settings = TenantDbContext.CoreSettings
.Where(r => r.Tenant == tenant)
.Where(r => r.Id == key)
.FirstOrDefault();
if (settings != null)
{
TenantDbContext.CoreSettings.Remove(settings);
}
}
else
{
var settings = new DbCoreSettings
{
Id = key,
Tenant = tenant,
Value = data,
LastModified = DateTime.UtcNow
};
TenantDbContext.AddOrUpdate(r => r.CoreSettings, settings);
}
TenantDbContext.SaveChanges();
tx.Commit();
}
private IQueryable<DbTenant> TenantsQuery()
{
return TenantDbContext.Tenants;
}
private void ValidateDomain(string domain, int tenantId, bool validateCharacters)
{
// size
TenantDomainValidator.ValidateDomainLength(domain);
// characters
if (validateCharacters)
{
TenantDomainValidator.ValidateDomainCharacters(domain);
}
// forbidden or exists
var exists = false;
domain = domain.ToLowerInvariant();
if (forbiddenDomains == null)
{
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();
}
if (!exists)
{
exists = TenantDbContext.Tenants
.Where(r => r.MappedDomain == domain && r.Id != tenantId && !(r.Status == TenantStatus.RemovePending || r.Status == TenantStatus.Restoring))
.Any();
}
if (exists)
{
// cut number suffix
while (true)
{
if (6 < domain.Length && char.IsNumber(domain, domain.Length - 1))
{
domain = domain[0..^1];
}
else
{
break;
}
}
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);
}
}
protected string GetPasswordHash(Guid userId, string password)
if (string.IsNullOrEmpty(t.PartnerId) && string.IsNullOrEmpty(t.AffiliateId) && string.IsNullOrEmpty(t.Campaign))
{
return Hasher.Base64Hash(password + userId + Encoding.UTF8.GetString(MachinePseudoKeys.GetMachineConstant()), HashAlg.SHA512);
}
var p = TenantDbContext.TenantPartner
.Where(r => r.TenantId == t.Id)
.FirstOrDefault();
if (p != null)
{
TenantDbContext.TenantPartner.Remove(p);
}
}
else
{
var tenantPartner = new DbTenantPartner
{
TenantId = t.Id,
PartnerId = t.PartnerId,
AffiliateId = t.AffiliateId,
Campaign = t.Campaign
};
TenantDbContext.TenantPartner.Add(tenantPartner);
}
tx.Commit();
//CalculateTenantDomain(t);
return t;
}
public class TenantUserSecurity
public void RemoveTenant(int id, bool auto = false)
{
public DbTenant DbTenant { get; set; }
public User User { get; set; }
public UserSecurity UserSecurity { get; set; }
}
var postfix = auto ? "_auto_deleted" : "_deleted";
using var tx = TenantDbContext.Database.BeginTransaction();
var alias = TenantDbContext.Tenants
.Where(r => r.Id == id)
.Select(r => r.Alias)
.FirstOrDefault();
var count = TenantDbContext.Tenants
.Where(r => r.Alias.StartsWith(alias + postfix))
.Count();
var tenant = TenantDbContext.Tenants.Where(r => r.Id == id).FirstOrDefault();
if (tenant != null)
{
tenant.Alias = alias + postfix + (count > 0 ? count.ToString() : "");
tenant.Status = TenantStatus.RemovePending;
tenant.StatusChanged = DateTime.UtcNow;
tenant.LastModified = DateTime.UtcNow;
}
TenantDbContext.SaveChanges();
tx.Commit();
}
public IEnumerable<TenantVersion> GetTenantVersions()
{
return TenantDbContext.TenantVersion
.Where(r => r.Visible)
.Select(r => new TenantVersion(r.Id, r.Version))
.ToList();
}
public byte[] GetTenantSettings(int tenant, string key)
{
return TenantDbContext.CoreSettings
.Where(r => r.Tenant == tenant)
.Where(r => r.Id == key)
.Select(r => r.Value)
.FirstOrDefault();
}
public void SetTenantSettings(int tenant, string key, byte[] data)
{
using var tx = TenantDbContext.Database.BeginTransaction();
if (data == null || data.Length == 0)
{
var settings = TenantDbContext.CoreSettings
.Where(r => r.Tenant == tenant)
.Where(r => r.Id == key)
.FirstOrDefault();
if (settings != null)
{
TenantDbContext.CoreSettings.Remove(settings);
}
}
else
{
var settings = new DbCoreSettings
{
Id = key,
Tenant = tenant,
Value = data,
LastModified = DateTime.UtcNow
};
TenantDbContext.AddOrUpdate(r => r.CoreSettings, settings);
}
TenantDbContext.SaveChanges();
tx.Commit();
}
private IQueryable<DbTenant> TenantsQuery()
{
return TenantDbContext.Tenants;
}
private void ValidateDomain(string domain, int tenantId, bool validateCharacters)
{
// size
TenantDomainValidator.ValidateDomainLength(domain);
// characters
if (validateCharacters)
{
TenantDomainValidator.ValidateDomainCharacters(domain);
}
// forbidden or exists
var exists = false;
domain = domain.ToLowerInvariant();
if (_forbiddenDomains == null)
{
_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();
}
if (!exists)
{
exists = TenantDbContext.Tenants
.Where(r => r.MappedDomain == domain && r.Id != tenantId && !(r.Status == TenantStatus.RemovePending || r.Status == TenantStatus.Restoring))
.Any();
}
if (exists)
{
// cut number suffix
while (true)
{
if (6 < domain.Length && char.IsNumber(domain, domain.Length - 1))
{
domain = domain[0..^1];
}
else
{
break;
}
}
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);
}
}
protected string GetPasswordHash(Guid userId, string password)
{
return Hasher.Base64Hash(password + userId + Encoding.UTF8.GetString(_machinePseudoKeys.GetMachineConstant()), HashAlg.SHA512);
}
}
public class TenantUserSecurity
{
public DbTenant DbTenant { get; set; }
public User User { get; set; }
public UserSecurity UserSecurity { get; set; }
}

File diff suppressed because it is too large Load Diff

View File

@ -1,36 +1,35 @@
namespace ASC.Core.Common.EF.Context
{
public class MySqlAccountLinkContext : AccountLinkContext { }
public class PostgreSqlAccountLinkContext : AccountLinkContext { }
public class AccountLinkContext : BaseDbContext
{
public DbSet<AccountLinks> AccountLinks { get; set; }
namespace ASC.Core.Common.EF.Context;
protected override Dictionary<Provider, Func<BaseDbContext>> ProviderContext
public class MySqlAccountLinkContext : AccountLinkContext { }
public class PostgreSqlAccountLinkContext : AccountLinkContext { }
public class AccountLinkContext : BaseDbContext
{
public DbSet<AccountLinks> AccountLinks { get; set; }
protected override Dictionary<Provider, Func<BaseDbContext>> ProviderContext
{
get
{
get
{
return new Dictionary<Provider, Func<BaseDbContext>>()
return new Dictionary<Provider, Func<BaseDbContext>>()
{
{ Provider.MySql, () => new MySqlAccountLinkContext() } ,
{ Provider.PostgreSql, () => new PostgreSqlAccountLinkContext() } ,
};
}
}
protected override void OnModelCreating(ModelBuilder modelBuilder)
{
ModelBuilderWrapper
.From(modelBuilder, Provider)
.AddAccountLinks();
}
}
public static class AccountLinkContextExtension
protected override void OnModelCreating(ModelBuilder modelBuilder)
{
public static DIHelper AddAccountLinkContextService(this DIHelper services)
{
return services.AddDbContextManagerService<AccountLinkContext>();
}
ModelBuilderWrapper
.From(modelBuilder, Provider)
.AddAccountLinks();
}
}
public static class AccountLinkContextExtension
{
public static DIHelper AddAccountLinkContextService(this DIHelper services)
{
return services.AddDbContextManagerService<AccountLinkContext>();
}
}

View File

@ -1,163 +1,159 @@

using DbContext = Microsoft.EntityFrameworkCore.DbContext;
using DbContext = Microsoft.EntityFrameworkCore.DbContext;
namespace ASC.Core.Common.EF
namespace ASC.Core.Common.EF;
public enum Provider
{
public enum Provider
PostgreSql,
MySql
}
public class BaseDbContext : DbContext
{
public BaseDbContext() { }
public BaseDbContext(DbContextOptions options) : base(options) { }
internal string MigrateAssembly;
internal ILoggerFactory LoggerFactory;
public ConnectionStringSettings ConnectionStringSettings { get; set; }
protected internal Provider Provider;
public static readonly ServerVersion ServerVersion = ServerVersion.Parse("8.0.25");
protected virtual Dictionary<Provider, Func<BaseDbContext>> ProviderContext => null;
public void Migrate()
{
PostgreSql,
MySql
if (ProviderContext != null)
{
var provider = GetProviderByConnectionString();
using var sqlProvider = ProviderContext[provider]();
sqlProvider.ConnectionStringSettings = ConnectionStringSettings;
sqlProvider.LoggerFactory = LoggerFactory;
sqlProvider.MigrateAssembly = MigrateAssembly;
sqlProvider.Database.Migrate();
}
else
{
Database.Migrate();
}
}
public class BaseDbContext : DbContext
protected override void OnConfiguring(DbContextOptionsBuilder optionsBuilder)
{
public BaseDbContext() { }
public BaseDbContext(DbContextOptions options) : base(options)
optionsBuilder.UseLoggerFactory(LoggerFactory);
optionsBuilder.EnableSensitiveDataLogging();
Provider = GetProviderByConnectionString();
switch (Provider)
{
}
internal string MigrateAssembly { get; set; }
internal ILoggerFactory LoggerFactory { get; set; }
public ConnectionStringSettings ConnectionStringSettings { get; set; }
protected internal Provider Provider { get; set; }
public static readonly ServerVersion ServerVersion = ServerVersion.Parse("8.0.25");
protected virtual Dictionary<Provider, Func<BaseDbContext>> ProviderContext
{
get { return null; }
}
public void Migrate()
{
if (ProviderContext != null)
{
var provider = GetProviderByConnectionString();
using var sqlProvider = ProviderContext[provider]();
sqlProvider.ConnectionStringSettings = ConnectionStringSettings;
sqlProvider.LoggerFactory = LoggerFactory;
sqlProvider.MigrateAssembly = MigrateAssembly;
sqlProvider.Database.Migrate();
}
else
{
Database.Migrate();
}
}
protected override void OnConfiguring(DbContextOptionsBuilder optionsBuilder)
{
optionsBuilder.UseLoggerFactory(LoggerFactory);
optionsBuilder.EnableSensitiveDataLogging();
Provider = GetProviderByConnectionString();
switch (Provider)
{
case Provider.MySql:
optionsBuilder.UseMySql(ConnectionStringSettings.ConnectionString, ServerVersion, r =>
case Provider.MySql:
optionsBuilder.UseMySql(ConnectionStringSettings.ConnectionString, ServerVersion, r =>
{
if (!string.IsNullOrEmpty(MigrateAssembly))
{
if (!string.IsNullOrEmpty(MigrateAssembly))
{
r.MigrationsAssembly(MigrateAssembly);
}
});
break;
case Provider.PostgreSql:
optionsBuilder.UseNpgsql(ConnectionStringSettings.ConnectionString);
break;
}
}
public Provider GetProviderByConnectionString()
{
switch (ConnectionStringSettings.ProviderName)
{
case "MySql.Data.MySqlClient":
return Provider.MySql;
case "Npgsql":
return Provider.PostgreSql;
default:
break;
}
return Provider.MySql;
r.MigrationsAssembly(MigrateAssembly);
}
});
break;
case Provider.PostgreSql:
optionsBuilder.UseNpgsql(ConnectionStringSettings.ConnectionString);
break;
}
}
public static class BaseDbContextExtension
public Provider GetProviderByConnectionString()
{
public static T AddOrUpdate<T, TContext>(this TContext b, Expression<Func<TContext, DbSet<T>>> expressionDbSet, T entity) where T : BaseEntity where TContext : BaseDbContext
switch (ConnectionStringSettings.ProviderName)
{
var dbSet = expressionDbSet.Compile().Invoke(b);
var existingBlog = dbSet.Find(entity.GetKeys());
if (existingBlog == null)
{
return dbSet.Add(entity).Entity;
}
else
{
b.Entry(existingBlog).CurrentValues.SetValues(entity);
return entity;
}
case "MySql.Data.MySqlClient":
return Provider.MySql;
case "Npgsql":
return Provider.PostgreSql;
default:
break;
}
public static async Task<T> AddOrUpdateAsync<T, TContext>(this TContext b, Expression<Func<TContext, DbSet<T>>> expressionDbSet, T entity) where T : BaseEntity where TContext : BaseDbContext
return Provider.MySql;
}
}
public static class BaseDbContextExtension
{
public static T AddOrUpdate<T, TContext>(this TContext b, Expression<Func<TContext, DbSet<T>>> expressionDbSet, T entity) where T : BaseEntity where TContext : BaseDbContext
{
var dbSet = expressionDbSet.Compile().Invoke(b);
var existingBlog = dbSet.Find(entity.GetKeys());
if (existingBlog == null)
{
var dbSet = expressionDbSet.Compile().Invoke(b);
var existingBlog = await dbSet.FindAsync(entity.GetKeys());
if (existingBlog == null)
return dbSet.Add(entity).Entity;
}
else
{
b.Entry(existingBlog).CurrentValues.SetValues(entity);
return entity;
}
}
public static async Task<T> AddOrUpdateAsync<T, TContext>(this TContext b, Expression<Func<TContext, DbSet<T>>> expressionDbSet, T entity) where T : BaseEntity where TContext : BaseDbContext
{
var dbSet = expressionDbSet.Compile().Invoke(b);
var existingBlog = await dbSet.FindAsync(entity.GetKeys());
if (existingBlog == null)
{
var entityEntry = await dbSet.AddAsync(entity);
return entityEntry.Entity;
}
else
{
b.Entry(existingBlog).CurrentValues.SetValues(entity);
return entity;
}
}
}
public abstract class BaseEntity
{
public abstract object[] GetKeys();
}
public class MultiRegionalDbContext<T> : IDisposable, IAsyncDisposable where T : BaseDbContext, new()
{
public MultiRegionalDbContext() { }
internal List<T> Context;
public void Dispose()
{
if (Context == null)
{
return;
}
foreach (var c in Context)
{
if (c != null)
{
var entityEntry = await dbSet.AddAsync(entity);
return entityEntry.Entity;
}
else
{
b.Entry(existingBlog).CurrentValues.SetValues(entity);
return entity;
c.Dispose();
}
}
}
public abstract class BaseEntity
public ValueTask DisposeAsync()
{
public abstract object[] GetKeys();
return Context == null ? ValueTask.CompletedTask : InternalDisposeAsync();
}
public class MultiRegionalDbContext<T> : IDisposable, IAsyncDisposable where T : BaseDbContext, new()
private async ValueTask InternalDisposeAsync()
{
public MultiRegionalDbContext() { }
internal List<T> Context { get; set; }
public void Dispose()
foreach (var c in Context)
{
if (Context == null) return;
foreach (var c in Context)
if (c != null)
{
if (c != null)
{
c.Dispose();
}
}
}
public ValueTask DisposeAsync()
{
if (Context == null) return ValueTask.CompletedTask;
return InternalDisposeAsync();
}
private async ValueTask InternalDisposeAsync()
{
foreach (var c in Context)
{
if (c != null)
{
await c.DisposeAsync();
}
await c.DisposeAsync();
}
}
}

View File

@ -1,63 +1,62 @@
namespace ASC.Core.Common.EF
namespace ASC.Core.Common.EF;
[Scope]
public class ConfigureDbContext<T> : IConfigureNamedOptions<T> where T : BaseDbContext, new()
{
[Scope]
public class ConfigureDbContext<T> : IConfigureNamedOptions<T> where T : BaseDbContext, new()
public const string BaseName = "default";
private readonly EFLoggerFactory _loggerFactory;
private readonly ConfigurationExtension _configuration;
private readonly string _migrateAssembly;
public ConfigureDbContext(EFLoggerFactory loggerFactory, ConfigurationExtension configuration)
{
public const string baseName = "default";
private EFLoggerFactory LoggerFactory { get; }
private ConfigurationExtension Configuration { get; }
private string MigrateAssembly { get; }
public ConfigureDbContext(EFLoggerFactory loggerFactory, ConfigurationExtension configuration)
{
LoggerFactory = loggerFactory;
Configuration = configuration;
MigrateAssembly = Configuration["testAssembly"];
}
public void Configure(string name, T context)
{
context.LoggerFactory = LoggerFactory;
context.ConnectionStringSettings = Configuration.GetConnectionStrings(name) ?? Configuration.GetConnectionStrings(baseName);
context.MigrateAssembly = MigrateAssembly;
}
public void Configure(T context)
{
Configure(baseName, context);
}
_loggerFactory = loggerFactory;
_configuration = configuration;
_migrateAssembly = _configuration["testAssembly"];
}
public class ConfigureMultiRegionalDbContext<T> : IConfigureNamedOptions<MultiRegionalDbContext<T>> where T : BaseDbContext, new()
public void Configure(string name, T context)
{
private readonly string _baseName = "default";
private ConfigurationExtension Configuration { get; }
private DbContextManager<T> DbContext { get; }
context.LoggerFactory = _loggerFactory;
context.ConnectionStringSettings = _configuration.GetConnectionStrings(name) ?? _configuration.GetConnectionStrings(BaseName);
context.MigrateAssembly = _migrateAssembly;
}
public ConfigureMultiRegionalDbContext(ConfigurationExtension configuration, DbContextManager<T> dbContext)
{
Configuration = configuration;
DbContext = dbContext;
}
public void Configure(string name, MultiRegionalDbContext<T> context)
{
context.Context = new System.Collections.Generic.List<T>();
const StringComparison cmp = StringComparison.InvariantCultureIgnoreCase;
foreach (var c in Configuration.GetConnectionStrings().Where(r =>
r.Name.Equals(name, cmp) || r.Name.StartsWith(name + ".", cmp) ||
r.Name.Equals(_baseName, cmp) || r.Name.StartsWith(_baseName + ".", cmp)
))
{
context.Context.Add(DbContext.Get(c.Name));
}
}
public void Configure(MultiRegionalDbContext<T> context)
{
Configure(_baseName, context);
}
public void Configure(T context)
{
Configure(BaseName, context);
}
}
public class ConfigureMultiRegionalDbContext<T> : IConfigureNamedOptions<MultiRegionalDbContext<T>> where T : BaseDbContext, new()
{
private readonly string _baseName = "default";
private readonly ConfigurationExtension _configuration;
private readonly DbContextManager<T> _dbContext;
public ConfigureMultiRegionalDbContext(ConfigurationExtension configuration, DbContextManager<T> dbContext)
{
_configuration = configuration;
_dbContext = dbContext;
}
public void Configure(string name, MultiRegionalDbContext<T> context)
{
context.Context = new List<T>();
const StringComparison cmp = StringComparison.InvariantCultureIgnoreCase;
foreach (var c in _configuration.GetConnectionStrings().Where(r =>
r.Name.Equals(name, cmp) || r.Name.StartsWith(name + ".", cmp) ||
r.Name.Equals(_baseName, cmp) || r.Name.StartsWith(_baseName + ".", cmp)
))
{
context.Context.Add(_dbContext.Get(c.Name));
}
}
public void Configure(MultiRegionalDbContext<T> context)
{
Configure(_baseName, context);
}
}

View File

@ -1,32 +1,32 @@
namespace ASC.Core.Common.EF
namespace ASC.Core.Common.EF;
public class MySqlCoreDbContext : CoreDbContext { }
public class PostgreSqlCoreDbContext : CoreDbContext { }
public class CoreDbContext : BaseDbContext
{
public class MySqlCoreDbContext : CoreDbContext { }
public class PostgreSqlCoreDbContext : CoreDbContext { }
public class CoreDbContext : BaseDbContext
public DbSet<DbTariff> Tariffs { get; set; }
public DbSet<DbButton> Buttons { get; set; }
public DbSet<DbQuota> Quotas { get; set; }
public DbSet<DbQuotaRow> QuotaRows { get; set; }
protected override Dictionary<Provider, Func<BaseDbContext>> ProviderContext
{
public DbSet<DbTariff> Tariffs { get; set; }
public DbSet<DbButton> Buttons { get; set; }
public DbSet<DbQuota> Quotas { get; set; }
public DbSet<DbQuotaRow> QuotaRows { get; set; }
protected override Dictionary<Provider, Func<BaseDbContext>> ProviderContext
get
{
get
{
return new Dictionary<Provider, Func<BaseDbContext>>()
return new Dictionary<Provider, Func<BaseDbContext>>()
{
{ Provider.MySql, () => new MySqlCoreDbContext() } ,
{ Provider.PostgreSql, () => new PostgreSqlCoreDbContext() } ,
};
}
}
protected override void OnModelCreating(ModelBuilder modelBuilder)
{
ModelBuilderWrapper
.From(modelBuilder, Provider)
.AddDbButton()
.AddDbQuotaRow()
.AddDbQuota()
.AddDbTariff();
}
}
protected override void OnModelCreating(ModelBuilder modelBuilder)
{
ModelBuilderWrapper
.From(modelBuilder, Provider)
.AddDbButton()
.AddDbQuotaRow()
.AddDbQuota()
.AddDbTariff();
}
}

View File

@ -1,46 +1,42 @@
namespace ASC.Core.Common.EF.Context
namespace ASC.Core.Common.EF.Context;
public class MySqlDbContext : DbContext { }
public class PostgreSqlDbContext : DbContext { }
public class DbContext : BaseDbContext
{
public class MySqlDbContext : DbContext { }
public class PostgreSqlDbContext : DbContext { }
public class DbContext : BaseDbContext
public DbSet<MobileAppInstall> MobileAppInstall { get; set; }
public DbSet<DbipLocation> DbipLocation { get; set; }
public DbSet<Regions> Regions { get; set; }
public DbContext() { }
public DbContext(DbContextOptions options) : base(options) { }
protected override Dictionary<Provider, Func<BaseDbContext>> ProviderContext
{
public DbSet<MobileAppInstall> MobileAppInstall { get; set; }
public DbSet<DbipLocation> DbipLocation { get; set; }
public DbSet<Regions> Regions { get; set; }
public DbContext()
get
{
}
public DbContext(DbContextOptions options) : base(options)
{
}
protected override Dictionary<Provider, Func<BaseDbContext>> ProviderContext
{
get
return new Dictionary<Provider, Func<BaseDbContext>>()
{
return new Dictionary<Provider, Func<BaseDbContext>>()
{
{ Provider.MySql, () => new MySqlDbContext() } ,
{ Provider.PostgreSql, () => new PostgreSqlDbContext() } ,
};
}
}
protected override void OnModelCreating(ModelBuilder modelBuilder)
{
ModelBuilderWrapper
.From(modelBuilder, Provider)
.AddMobileAppInstall()
.AddDbipLocation()
.AddRegions();
{ Provider.MySql, () => new MySqlDbContext() } ,
{ Provider.PostgreSql, () => new PostgreSqlDbContext() } ,
};
}
}
public static class DbContextExtension
protected override void OnModelCreating(ModelBuilder modelBuilder)
{
public static DIHelper AddDbContextService(this DIHelper services)
{
return services.AddDbContextManagerService<DbContext>();
}
ModelBuilderWrapper
.From(modelBuilder, Provider)
.AddMobileAppInstall()
.AddDbipLocation()
.AddRegions();
}
}
public static class DbContextExtension
{
public static DIHelper AddDbContextService(this DIHelper services)
{
return services.AddDbContextManagerService<DbContext>();
}
}

View File

@ -1,91 +1,90 @@
namespace ASC.Core.Common.EF
namespace ASC.Core.Common.EF;
public class BaseDbContextManager<T> : OptionsManager<T>, IDisposable where T : class, IDisposable, IAsyncDisposable, new()
{
public class BaseDbContextManager<T> : OptionsManager<T>, IDisposable where T : class, IDisposable, IAsyncDisposable, new()
private Dictionary<string, T> _pairs;
private MigrationHistory _migrationHistory;
private List<T> _asyncList;
private IOptionsFactory<T> _factory;
private IConfiguration _configuration;
public BaseDbContextManager(IOptionsFactory<T> factory, IConfiguration configuration,
MigrationHistory migrationHistory) : base(factory)
{
private Dictionary<string, T> Pairs { get; set; }
private MigrationHistory MigrationHistory { get; set; }
private List<T> AsyncList { get; set; }
private IOptionsFactory<T> Factory { get; }
private IConfiguration Configuration { get; }
_pairs = new Dictionary<string, T>();
_asyncList = new List<T>();
_factory = factory;
_configuration = configuration;
_migrationHistory = migrationHistory;
}
public BaseDbContextManager(IOptionsFactory<T> factory, IConfiguration configuration,
MigrationHistory migrationHistory) : base(factory)
public override T Get(string name)
{
if (!_pairs.ContainsKey(name))
{
Pairs = new Dictionary<string, T>();
AsyncList = new List<T>();
Factory = factory;
Configuration = configuration;
MigrationHistory = migrationHistory;
}
var t = base.Get(name);
_pairs.Add(name, t);
public override T Get(string name)
{
if (!Pairs.ContainsKey(name))
if (t is BaseDbContext dbContext)
{
var t = base.Get(name);
Pairs.Add(name, t);
if (t is BaseDbContext dbContext)
if (_configuration["migration:enabled"] == "true"
&& _migrationHistory.TryAddMigratedContext(t.GetType()))
{
if (Configuration["migration:enabled"] == "true"
&& MigrationHistory.TryAddMigratedContext(t.GetType()))
{
dbContext.Migrate();
}
dbContext.Migrate();
}
}
return Pairs[name];
}
public T GetNew(string name = "default")
{
var result = Factory.Create(name);
AsyncList.Add(result);
return result;
}
public void Dispose()
{
foreach (var v in Pairs)
{
v.Value.Dispose();
}
foreach (var v in AsyncList)
{
v.Dispose();
}
}
return _pairs[name];
}
[Scope(typeof(ConfigureDbContext<>))]
public class DbContextManager<T> : BaseDbContextManager<T> where T : BaseDbContext, new()
public T GetNew(string name = "default")
{
public DbContextManager(IOptionsFactory<T> factory, IConfiguration configuration,
MigrationHistory migrationHistory) : base(factory, configuration, migrationHistory)
{
}
var result = _factory.Create(name);
_asyncList.Add(result);
return result;
}
public class MultiRegionalDbContextManager<T> : BaseDbContextManager<MultiRegionalDbContext<T>> where T : BaseDbContext, new()
public void Dispose()
{
public MultiRegionalDbContextManager(IOptionsFactory<MultiRegionalDbContext<T>> factory, IConfiguration configuration,
MigrationHistory migrationHistory) : base(factory, configuration, migrationHistory)
foreach (var v in _pairs)
{
v.Value.Dispose();
}
}
public static class DbContextManagerExtension
{
public static DIHelper AddDbContextManagerService<T>(this DIHelper services) where T : BaseDbContext, new()
foreach (var v in _asyncList)
{
//TODO
//services.TryAddScoped<MultiRegionalDbContextManager<T>>();
//services.TryAddScoped<IConfigureOptions<MultiRegionalDbContext<T>>, ConfigureMultiRegionalDbContext<T>>();
return services;
v.Dispose();
}
}
}
[Scope(typeof(ConfigureDbContext<>))]
public class DbContextManager<T> : BaseDbContextManager<T> where T : BaseDbContext, new()
{
public DbContextManager(IOptionsFactory<T> factory, IConfiguration configuration,
MigrationHistory migrationHistory) : base(factory, configuration, migrationHistory)
{
}
}
public class MultiRegionalDbContextManager<T> : BaseDbContextManager<MultiRegionalDbContext<T>> where T : BaseDbContext, new()
{
public MultiRegionalDbContextManager(IOptionsFactory<MultiRegionalDbContext<T>> factory, IConfiguration configuration,
MigrationHistory migrationHistory) : base(factory, configuration, migrationHistory)
{
}
}
public static class DbContextManagerExtension
{
public static DIHelper AddDbContextManagerService<T>(this DIHelper services) where T : BaseDbContext, new()
{
//TODO
//services.TryAddScoped<MultiRegionalDbContextManager<T>>();
//services.TryAddScoped<IConfigureOptions<MultiRegionalDbContext<T>>, ConfigureMultiRegionalDbContext<T>>();
return services;
}
}

View File

@ -1,34 +1,34 @@
namespace ASC.Core.Common.EF.Context
namespace ASC.Core.Common.EF.Context;
public class MySqlFilesDbContext : FilesDbContext { }
public class PostgreSqlFilesDbContext : FilesDbContext { }
public class FilesDbContext : BaseDbContext
{
public class MySqlFilesDbContext : FilesDbContext { }
public class PostgreSqlFilesDbContext : FilesDbContext { }
public class FilesDbContext : BaseDbContext
public DbSet<FilesConverts> FilesConverts { get; set; }
protected override Dictionary<Provider, Func<BaseDbContext>> ProviderContext
{
public DbSet<FilesConverts> FilesConverts { get; set; }
protected override Dictionary<Provider, Func<BaseDbContext>> ProviderContext
get
{
get
return new Dictionary<Provider, Func<BaseDbContext>>()
{
return new Dictionary<Provider, Func<BaseDbContext>>()
{
{ Provider.MySql, () => new MySqlFilesDbContext() } ,
{ Provider.PostgreSql, () => new PostgreSqlFilesDbContext() } ,
};
}
}
protected override void OnModelCreating(ModelBuilder modelBuilder)
{
ModelBuilderWrapper
.From(modelBuilder, Provider)
.AddFilesConverts();
{ Provider.MySql, () => new MySqlFilesDbContext() } ,
{ Provider.PostgreSql, () => new PostgreSqlFilesDbContext() } ,
};
}
}
public static class FilesDbExtension
protected override void OnModelCreating(ModelBuilder modelBuilder)
{
public static DIHelper AddFilesDbContextService(this DIHelper services)
{
return services.AddDbContextManagerService<FilesDbContext>();
}
ModelBuilderWrapper
.From(modelBuilder, Provider)
.AddFilesConverts();
}
}
public static class FilesDbExtension
{
public static DIHelper AddFilesDbContextService(this DIHelper services)
{
return services.AddDbContextManagerService<FilesDbContext>();
}
}

View File

@ -1,44 +1,44 @@
namespace ASC.Core.Common.EF.Context
{
public class MySqlMailDbContext : MailDbContext { }
public class PostgreSqlMailDbContext : MailDbContext { }
public class MailDbContext : BaseDbContext
{
public DbSet<MailboxServer> MailboxServer { get; set; }
public DbSet<ServerServer> ServerServer { get; set; }
public DbSet<MailboxProvider> MailboxProvider { get; set; }
public DbSet<Mailbox> Mailbox { get; set; }
public DbSet<ApiKeys> ApiKeys { get; set; }
public DbSet<GreyListingWhiteList> GreyListingWhiteList { get; set; }
namespace ASC.Core.Common.EF.Context;
public MailDbContext() { }
public MailDbContext(DbContextOptions options) : base(options) { }
protected override Dictionary<Provider, Func<BaseDbContext>> ProviderContext
public class MySqlMailDbContext : MailDbContext { }
public class PostgreSqlMailDbContext : MailDbContext { }
public class MailDbContext : BaseDbContext
{
public DbSet<MailboxServer> MailboxServer { get; set; }
public DbSet<ServerServer> ServerServer { get; set; }
public DbSet<MailboxProvider> MailboxProvider { get; set; }
public DbSet<Mailbox> Mailbox { get; set; }
public DbSet<ApiKeys> ApiKeys { get; set; }
public DbSet<GreyListingWhiteList> GreyListingWhiteList { get; set; }
public MailDbContext() { }
public MailDbContext(DbContextOptions options) : base(options) { }
protected override Dictionary<Provider, Func<BaseDbContext>> ProviderContext
{
get
{
get
return new Dictionary<Provider, Func<BaseDbContext>>()
{
return new Dictionary<Provider, Func<BaseDbContext>>()
{
{ Provider.MySql, () => new MySqlMailDbContext() } ,
{ Provider.PostgreSql, () => new PostgreSqlMailDbContext() } ,
};
}
}
protected override void OnModelCreating(ModelBuilder modelBuilder)
{
ModelBuilderWrapper
.From(modelBuilder, Provider)
.AddMailbox()
.AddMailboxProvider()
.AddServerServer()
.AddGreyListingWhiteList();
{ Provider.MySql, () => new MySqlMailDbContext() } ,
{ Provider.PostgreSql, () => new PostgreSqlMailDbContext() } ,
};
}
}
public static class MailDbExtension
protected override void OnModelCreating(ModelBuilder modelBuilder)
{
public static DIHelper AddMailDbContextService(this DIHelper services)
{
return services.AddDbContextManagerService<MailDbContext>();
}
ModelBuilderWrapper
.From(modelBuilder, Provider)
.AddMailbox()
.AddMailboxProvider()
.AddServerServer()
.AddGreyListingWhiteList();
}
}
public static class MailDbExtension
{
public static DIHelper AddMailDbContextService(this DIHelper services)
{
return services.AddDbContextManagerService<MailDbContext>();
}
}

View File

@ -1,36 +1,36 @@
namespace ASC.Core.Common.EF.Context
namespace ASC.Core.Common.EF.Context;
public class MySqlNotifyDbContext : NotifyDbContext { }
public class PostgreSqlNotifyDbContext : NotifyDbContext { }
public class NotifyDbContext : BaseDbContext
{
public class MySqlNotifyDbContext : NotifyDbContext { }
public class PostgreSqlNotifyDbContext : NotifyDbContext { }
public class NotifyDbContext : BaseDbContext
public DbSet<NotifyInfo> NotifyInfo { get; set; }
public DbSet<NotifyQueue> NotifyQueue { get; set; }
protected override Dictionary<Provider, Func<BaseDbContext>> ProviderContext
{
public DbSet<NotifyInfo> NotifyInfo { get; set; }
public DbSet<NotifyQueue> NotifyQueue { get; set; }
protected override Dictionary<Provider, Func<BaseDbContext>> ProviderContext
get
{
get
return new Dictionary<Provider, Func<BaseDbContext>>()
{
return new Dictionary<Provider, Func<BaseDbContext>>()
{
{ Provider.MySql, () => new MySqlNotifyDbContext() } ,
{ Provider.PostgreSql, () => new PostgreSqlNotifyDbContext() } ,
};
}
}
protected override void OnModelCreating(ModelBuilder modelBuilder)
{
ModelBuilderWrapper
.From(modelBuilder, Provider)
.AddNotifyInfo()
.AddNotifyQueue();
{ Provider.MySql, () => new MySqlNotifyDbContext() } ,
{ Provider.PostgreSql, () => new PostgreSqlNotifyDbContext() } ,
};
}
}
public static class NotifyDbExtension
protected override void OnModelCreating(ModelBuilder modelBuilder)
{
public static DIHelper AddNotifyDbContext(this DIHelper services)
{
return services.AddDbContextManagerService<NotifyDbContext>();
}
ModelBuilderWrapper
.From(modelBuilder, Provider)
.AddNotifyInfo()
.AddNotifyQueue();
}
}
public static class NotifyDbExtension
{
public static DIHelper AddNotifyDbContext(this DIHelper services)
{
return services.AddDbContextManagerService<NotifyDbContext>();
}
}

View File

@ -1,46 +1,46 @@
namespace ASC.Core.Common.EF.Context
namespace ASC.Core.Common.EF.Context;
public class MySqlResourceDbContext : ResourceDbContext { }
public class PostgreSqlResourceDbContext : ResourceDbContext { }
public class ResourceDbContext : BaseDbContext
{
public class MySqlResourceDbContext : ResourceDbContext { }
public class PostgreSqlResourceDbContext : ResourceDbContext { }
public class ResourceDbContext : BaseDbContext
public DbSet<ResAuthors> Authors { get; set; }
public DbSet<ResAuthorsFile> ResAuthorsFiles { get; set; }
public DbSet<ResAuthorsLang> ResAuthorsLang { get; set; }
public DbSet<ResCultures> ResCultures { get; set; }
public DbSet<ResData> ResData { get; set; }
public DbSet<ResFiles> ResFiles { get; set; }
public DbSet<ResReserve> ResReserve { get; set; }
protected override Dictionary<Provider, Func<BaseDbContext>> ProviderContext
{
public DbSet<ResAuthors> Authors { get; set; }
public DbSet<ResAuthorsFile> ResAuthorsFiles { get; set; }
public DbSet<ResAuthorsLang> ResAuthorsLang { get; set; }
public DbSet<ResCultures> ResCultures { get; set; }
public DbSet<ResData> ResData { get; set; }
public DbSet<ResFiles> ResFiles { get; set; }
public DbSet<ResReserve> ResReserve { get; set; }
protected override Dictionary<Provider, Func<BaseDbContext>> ProviderContext
get
{
get
return new Dictionary<Provider, Func<BaseDbContext>>()
{
return new Dictionary<Provider, Func<BaseDbContext>>()
{
{ Provider.MySql, () => new MySqlResourceDbContext() } ,
{ Provider.PostgreSql, () => new PostgreSqlResourceDbContext() } ,
};
}
}
protected override void OnModelCreating(ModelBuilder modelBuilder)
{
ModelBuilderWrapper
.From(modelBuilder, Provider)
.AddResAuthorsLang()
.AddResAuthorsFile()
.AddResCultures()
.AddResFiles()
.AddResData()
.AddResAuthors()
.AddResReserve();
{ Provider.MySql, () => new MySqlResourceDbContext() } ,
{ Provider.PostgreSql, () => new PostgreSqlResourceDbContext() } ,
};
}
}
public static class ResourceDbExtension
protected override void OnModelCreating(ModelBuilder modelBuilder)
{
public static DIHelper AddResourceDbService(this DIHelper services)
{
return services.AddDbContextManagerService<ResourceDbContext>();
}
ModelBuilderWrapper
.From(modelBuilder, Provider)
.AddResAuthorsLang()
.AddResAuthorsFile()
.AddResCultures()
.AddResFiles()
.AddResData()
.AddResAuthors()
.AddResReserve();
}
}
}
public static class ResourceDbExtension
{
public static DIHelper AddResourceDbService(this DIHelper services)
{
return services.AddDbContextManagerService<ResourceDbContext>();
}
}

View File

@ -1,40 +1,41 @@
namespace ASC.Core.Common.EF.Context
{
public class MySqlTelegramDbContext : TelegramDbContext { }
public class PostgreSqlTelegramDbContext : TelegramDbContext { }
public class TelegramDbContext : BaseDbContext
{
public DbSet<TelegramUser> Users { get; set; }
namespace ASC.Core.Common.EF.Context;
public TelegramDbContext() { }
public TelegramDbContext(DbContextOptions<TelegramDbContext> options)
: base(options)
public class MySqlTelegramDbContext : TelegramDbContext { }
public class PostgreSqlTelegramDbContext : TelegramDbContext { }
public class TelegramDbContext : BaseDbContext
{
public DbSet<TelegramUser> Users { get; set; }
public TelegramDbContext() { }
public TelegramDbContext(DbContextOptions<TelegramDbContext> options)
: base(options)
{
}
protected override Dictionary<Provider, Func<BaseDbContext>> ProviderContext
{
get
{
}
protected override Dictionary<Provider, Func<BaseDbContext>> ProviderContext
{
get
return new Dictionary<Provider, Func<BaseDbContext>>()
{
return new Dictionary<Provider, Func<BaseDbContext>>()
{
{ Provider.MySql, () => new MySqlTelegramDbContext() } ,
{ Provider.PostgreSql, () => new PostgreSqlTelegramDbContext() } ,
};
}
}
protected override void OnModelCreating(ModelBuilder modelBuilder)
{
ModelBuilderWrapper
.From(modelBuilder, Provider)
.AddTelegramUsers();
{ Provider.MySql, () => new MySqlTelegramDbContext() } ,
{ Provider.PostgreSql, () => new PostgreSqlTelegramDbContext() } ,
};
}
}
public static class TelegramDbContextExtension
protected override void OnModelCreating(ModelBuilder modelBuilder)
{
public static DIHelper AddTelegramDbContextService(this DIHelper services)
{
return services.AddDbContextManagerService<TelegramDbContext>();
}
ModelBuilderWrapper
.From(modelBuilder, Provider)
.AddTelegramUsers();
}
}
public static class TelegramDbContextExtension
{
public static DIHelper AddTelegramDbContextService(this DIHelper services)
{
return services.AddDbContextManagerService<TelegramDbContext>();
}
}

View File

@ -1,51 +1,51 @@
namespace ASC.Core.Common.EF.Context
namespace ASC.Core.Common.EF.Context;
public class MySqlTenantDbContext : TenantDbContext { }
public class PostgreSqlTenantDbContext : TenantDbContext { }
public class TenantDbContext : BaseDbContext
{
public class MySqlTenantDbContext : TenantDbContext { }
public class PostgreSqlTenantDbContext : TenantDbContext { }
public class TenantDbContext : BaseDbContext
public DbSet<DbTenant> Tenants { get; set; }
public DbSet<DbTenantVersion> TenantVersion { get; set; }
public DbSet<DbTenantPartner> TenantPartner { get; set; }
public DbSet<DbTenantForbiden> TenantForbiden { get; set; }
public DbSet<TenantIpRestrictions> TenantIpRestrictions { get; set; }
public DbSet<DbCoreSettings> CoreSettings { get; set; }
public TenantDbContext() { }
public TenantDbContext(DbContextOptions<TenantDbContext> options)
: base(options)
{
public DbSet<DbTenant> Tenants { get; set; }
public DbSet<DbTenantVersion> TenantVersion { get; set; }
public DbSet<DbTenantPartner> TenantPartner { get; set; }
public DbSet<DbTenantForbiden> TenantForbiden { get; set; }
public DbSet<TenantIpRestrictions> TenantIpRestrictions { get; set; }
public DbSet<DbCoreSettings> CoreSettings { get; set; }
}
public TenantDbContext() { }
public TenantDbContext(DbContextOptions<TenantDbContext> options)
: base(options)
protected override Dictionary<Provider, Func<BaseDbContext>> ProviderContext
{
get
{
}
protected override Dictionary<Provider, Func<BaseDbContext>> ProviderContext
{
get
return new Dictionary<Provider, Func<BaseDbContext>>()
{
return new Dictionary<Provider, Func<BaseDbContext>>()
{
{ Provider.MySql, () => new MySqlTenantDbContext() } ,
{ Provider.PostgreSql, () => new PostgreSqlTenantDbContext() } ,
};
}
}
protected override void OnModelCreating(ModelBuilder modelBuilder)
{
ModelBuilderWrapper
.From(modelBuilder, Provider)
.AddDbTenant()
.AddCoreSettings()
.AddDbTenantForbiden()
.AddTenantIpRestrictions()
.AddDbTenantPartner()
.AddDbTenantVersion();
{ Provider.MySql, () => new MySqlTenantDbContext() } ,
{ Provider.PostgreSql, () => new PostgreSqlTenantDbContext() } ,
};
}
}
public static class TenantDbExtension
protected override void OnModelCreating(ModelBuilder modelBuilder)
{
public static DIHelper AddTenantDbContextService(this DIHelper services)
{
return services.AddDbContextManagerService<TenantDbContext>();
}
ModelBuilderWrapper
.From(modelBuilder, Provider)
.AddDbTenant()
.AddCoreSettings()
.AddDbTenantForbiden()
.AddTenantIpRestrictions()
.AddDbTenantPartner()
.AddDbTenantVersion();
}
}
public static class TenantDbExtension
{
public static DIHelper AddTenantDbContextService(this DIHelper services)
{
return services.AddDbContextManagerService<TenantDbContext>();
}
}

View File

@ -1,56 +1,50 @@
namespace ASC.Core.Common.EF
namespace ASC.Core.Common.EF;
public class MySqlUserDbContext : UserDbContext { }
public class PostgreSqlUserDbContext : UserDbContext { }
public class UserDbContext : BaseDbContext
{
public class MySqlUserDbContext : UserDbContext { }
public DbSet<User> Users { get; set; }
public DbSet<UserSecurity> UserSecurity { get; set; }
public DbSet<UserPhoto> Photos { get; set; }
public DbSet<Acl> Acl { get; set; }
public DbSet<DbGroup> Groups { get; set; }
public DbSet<UserGroup> UserGroups { get; set; }
public DbSet<Subscription> Subscriptions { get; set; }
public DbSet<DbSubscriptionMethod> SubscriptionMethods { get; set; }
public class PostgreSqlUserDbContext : UserDbContext
protected override Dictionary<Provider, Func<BaseDbContext>> ProviderContext
{
}
public class UserDbContext : BaseDbContext
{
public DbSet<User> Users { get; set; }
public DbSet<UserSecurity> UserSecurity { get; set; }
public DbSet<UserPhoto> Photos { get; set; }
public DbSet<Acl> Acl { get; set; }
public DbSet<DbGroup> Groups { get; set; }
public DbSet<UserGroup> UserGroups { get; set; }
public DbSet<Subscription> Subscriptions { get; set; }
public DbSet<DbSubscriptionMethod> SubscriptionMethods { get; set; }
protected override Dictionary<Provider, Func<BaseDbContext>> ProviderContext
get
{
get
{
return new Dictionary<Provider, Func<BaseDbContext>>()
return new Dictionary<Provider, Func<BaseDbContext>>()
{
{ Provider.MySql, () => new MySqlUserDbContext() } ,
{ Provider.PostgreSql, () => new PostgreSqlUserDbContext() } ,
};
}
}
protected override void OnModelCreating(ModelBuilder modelBuilder)
{
ModelBuilderWrapper
.From(modelBuilder, Provider)
.AddSubscriptionMethod()
.AddUser()
.AddAcl()
.AddUserSecurity()
.AddUserPhoto()
.AddDbGroup()
.AddUserGroup()
.AddSubscription();
}
}
public static class UserDbExtension
protected override void OnModelCreating(ModelBuilder modelBuilder)
{
public static DIHelper AddUserDbContextService(this DIHelper services)
{
return services.AddDbContextManagerService<UserDbContext>();
}
ModelBuilderWrapper
.From(modelBuilder, Provider)
.AddSubscriptionMethod()
.AddUser()
.AddAcl()
.AddUserSecurity()
.AddUserPhoto()
.AddDbGroup()
.AddUserGroup()
.AddSubscription();
}
}
public static class UserDbExtension
{
public static DIHelper AddUserDbContextService(this DIHelper services)
{
return services.AddDbContextManagerService<UserDbContext>();
}
}

View File

@ -1,38 +1,39 @@
namespace ASC.Core.Common.EF.Context
namespace ASC.Core.Common.EF.Context;
public class MySqlVoipDbContext : VoipDbContext { }
public class PostgreSqlVoipDbContext : VoipDbContext { }
public class VoipDbContext : BaseDbContext
{
public class MySqlVoipDbContext : VoipDbContext { }
public class PostgreSqlVoipDbContext : VoipDbContext { }
public class VoipDbContext : BaseDbContext
public DbSet<VoipNumber> VoipNumbers { get; set; }
public DbSet<DbVoipCall> VoipCalls { get; set; }
public DbSet<CrmContact> CrmContact { get; set; }
protected override Dictionary<Provider, Func<BaseDbContext>> ProviderContext
{
public DbSet<VoipNumber> VoipNumbers { get; set; }
public DbSet<DbVoipCall> VoipCalls { get; set; }
public DbSet<CrmContact> CrmContact { get; set; }
protected override Dictionary<Provider, Func<BaseDbContext>> ProviderContext
get
{
get
return new Dictionary<Provider, Func<BaseDbContext>>()
{
return new Dictionary<Provider, Func<BaseDbContext>>()
{
{ Provider.MySql, () => new MySqlVoipDbContext() } ,
{ Provider.PostgreSql, () => new PostgreSqlVoipDbContext() } ,
};
}
}
protected override void OnModelCreating(ModelBuilder modelBuilder)
{
ModelBuilderWrapper
.From(modelBuilder, Provider)
.AddVoipNumber()
.AddDbVoipCall()
.AddCrmContact();
{ Provider.MySql, () => new MySqlVoipDbContext() } ,
{ Provider.PostgreSql, () => new PostgreSqlVoipDbContext() } ,
};
}
}
public static class VoipDbExtension
protected override void OnModelCreating(ModelBuilder modelBuilder)
{
public static DIHelper AddVoipDbContextService(this DIHelper services)
{
return services.AddDbContextManagerService<VoipDbContext>();
}
ModelBuilderWrapper
.From(modelBuilder, Provider)
.AddVoipNumber()
.AddDbVoipCall()
.AddCrmContact();
}
}
public static class VoipDbExtension
{
public static DIHelper AddVoipDbContextService(this DIHelper services)
{
return services.AddDbContextManagerService<VoipDbContext>();
}
}

View File

@ -1,38 +1,39 @@
namespace ASC.Core.Common.EF.Context
namespace ASC.Core.Common.EF.Context;
public class MySqlWebstudioDbContext : WebstudioDbContext { }
public class PostgreSqlWebstudioDbContext : WebstudioDbContext { }
public class WebstudioDbContext : BaseDbContext
{
public class MySqlWebstudioDbContext : WebstudioDbContext { }
public class PostgreSqlWebstudioDbContext : WebstudioDbContext { }
public class WebstudioDbContext : BaseDbContext
public DbSet<DbWebstudioSettings> WebstudioSettings { get; set; }
public DbSet<DbWebstudioUserVisit> WebstudioUserVisit { get; set; }
public DbSet<DbWebstudioIndex> WebstudioIndex { get; set; }
protected override Dictionary<Provider, Func<BaseDbContext>> ProviderContext
{
public DbSet<DbWebstudioSettings> WebstudioSettings { get; set; }
public DbSet<DbWebstudioUserVisit> WebstudioUserVisit { get; set; }
public DbSet<DbWebstudioIndex> WebstudioIndex { get; set; }
protected override Dictionary<Provider, Func<BaseDbContext>> ProviderContext
get
{
get
return new Dictionary<Provider, Func<BaseDbContext>>()
{
return new Dictionary<Provider, Func<BaseDbContext>>()
{
{ Provider.MySql, () => new MySqlWebstudioDbContext() } ,
{ Provider.PostgreSql, () => new PostgreSqlWebstudioDbContext() } ,
};
}
}
protected override void OnModelCreating(ModelBuilder modelBuilder)
{
ModelBuilderWrapper
.From(modelBuilder, Provider)
.AddWebstudioSettings()
.AddWebstudioUserVisit()
.AddDbWebstudioIndex();
{ Provider.MySql, () => new MySqlWebstudioDbContext() } ,
{ Provider.PostgreSql, () => new PostgreSqlWebstudioDbContext() } ,
};
}
}
public static class WebstudioDbExtension
protected override void OnModelCreating(ModelBuilder modelBuilder)
{
public static DIHelper AddWebstudioDbContextService(this DIHelper services)
{
return services.AddDbContextManagerService<WebstudioDbContext>();
}
ModelBuilderWrapper
.From(modelBuilder, Provider)
.AddWebstudioSettings()
.AddWebstudioUserVisit()
.AddDbWebstudioIndex();
}
}
public static class WebstudioDbExtension
{
public static DIHelper AddWebstudioDbContextService(this DIHelper services)
{
return services.AddDbContextManagerService<WebstudioDbContext>();
}
}

View File

@ -1,29 +1,29 @@
namespace ASC.Core.Common.EF
namespace ASC.Core.Common.EF;
public static class IQueryableExtensions
{
public static class IQueryableExtensions
public static string ToSql<TEntity>(this IQueryable<TEntity> query) where TEntity : class
{
public static string ToSql<TEntity>(this IQueryable<TEntity> query) where TEntity : class
{
var enumerator = query.Provider.Execute<IEnumerable<TEntity>>(query.Expression).GetEnumerator();
var relationalCommandCache = enumerator.Private("_relationalCommandCache");
var selectExpression = relationalCommandCache.Private<SelectExpression>("_selectExpression");
var factory = relationalCommandCache.Private<IQuerySqlGeneratorFactory>("_querySqlGeneratorFactory");
var enumerator = query.Provider.Execute<IEnumerable<TEntity>>(query.Expression).GetEnumerator();
var relationalCommandCache = enumerator.Private("_relationalCommandCache");
var selectExpression = relationalCommandCache.Private<SelectExpression>("_selectExpression");
var factory = relationalCommandCache.Private<IQuerySqlGeneratorFactory>("_querySqlGeneratorFactory");
var sqlGenerator = factory.Create();
var command = sqlGenerator.GetCommand(selectExpression);
var sqlGenerator = factory.Create();
var command = sqlGenerator.GetCommand(selectExpression);
var sql = command.CommandText;
return sql;
}
var sql = command.CommandText;
private static object Private(this object obj, string privateField)
{
return obj?.GetType().GetField(privateField, BindingFlags.Instance | BindingFlags.NonPublic)?.GetValue(obj);
}
return sql;
}
private static T Private<T>(this object obj, string privateField)
{
return (T)obj?.GetType().GetField(privateField, BindingFlags.Instance | BindingFlags.NonPublic)?.GetValue(obj);
}
private static object Private(this object obj, string privateField)
{
return obj?.GetType().GetField(privateField, BindingFlags.Instance | BindingFlags.NonPublic)?.GetValue(obj);
}
private static T Private<T>(this object obj, string privateField)
{
return (T)obj?.GetType().GetField(privateField, BindingFlags.Instance | BindingFlags.NonPublic)?.GetValue(obj);
}
}

View File

@ -1,11 +1,10 @@
namespace ASC.Core.Common.EF
namespace ASC.Core.Common.EF;
public static class JsonExtensions
{
public static class JsonExtensions
public static string JsonValue(string column, [NotParameterized] string path)
{
public static string JsonValue(string column, [NotParameterized] string path)
{
//not using
return column + path;
}
//not using
return column + path;
}
}

View File

@ -1,43 +1,47 @@
namespace ASC.Core.Common.EF
namespace ASC.Core.Common.EF;
public static class LinqExtensions
{
public static class LinqExtensions
public static IOrderedQueryable<T> OrderBy<T>(this IQueryable<T> query, string name, bool sortOrderAsc)
{
public static IOrderedQueryable<T> OrderBy<T>(this IQueryable<T> query, string name, bool sortOrderAsc)
{
var propInfo = GetPropertyInfo(typeof(T), name);
var expr = GetOrderExpression(typeof(T), propInfo);
var propInfo = GetPropertyInfo(typeof(T), name);
var expr = GetOrderExpression(typeof(T), propInfo);
var method = typeof(Queryable).GetMethods().FirstOrDefault(m => m.Name == (sortOrderAsc ? "OrderBy" : "OrderByDescending") && m.GetParameters().Length == 2);
var genericMethod = method.MakeGenericMethod(typeof(T), propInfo.PropertyType);
return (IOrderedQueryable<T>)genericMethod.Invoke(null, new object[] { query, expr });
var method = typeof(Queryable).GetMethods().FirstOrDefault(m => m.Name == (sortOrderAsc ? "OrderBy" : "OrderByDescending") && m.GetParameters().Length == 2);
var genericMethod = method.MakeGenericMethod(typeof(T), propInfo.PropertyType);
return (IOrderedQueryable<T>)genericMethod.Invoke(null, new object[] { query, expr });
}
public static IOrderedQueryable<T> ThenBy<T>(this IOrderedQueryable<T> query, string name, bool sortOrderAsc)
{
var propInfo = GetPropertyInfo(typeof(T), name);
var expr = GetOrderExpression(typeof(T), propInfo);
var method = typeof(Queryable).GetMethods().FirstOrDefault(m => m.Name == (sortOrderAsc ? "ThenBy" : "ThenByDescending") && m.GetParameters().Length == 2);
var genericMethod = method.MakeGenericMethod(typeof(T), propInfo.PropertyType);
return (IOrderedQueryable<T>)genericMethod.Invoke(null, new object[] { query, expr });
}
private static PropertyInfo GetPropertyInfo(Type objType, string name)
{
var properties = objType.GetProperties();
var matchedProperty = properties.FirstOrDefault(p => p.Name.Equals(name, StringComparison.OrdinalIgnoreCase));
if (matchedProperty == null)
{
throw new ArgumentException(nameof(name));
}
public static IOrderedQueryable<T> ThenBy<T>(this IOrderedQueryable<T> query, string name, bool sortOrderAsc)
{
var propInfo = GetPropertyInfo(typeof(T), name);
var expr = GetOrderExpression(typeof(T), propInfo);
return matchedProperty;
}
private static LambdaExpression GetOrderExpression(Type objType, PropertyInfo pi)
{
var paramExpr = Expression.Parameter(objType);
var propAccess = Expression.PropertyOrField(paramExpr, pi.Name);
var expr = Expression.Lambda(propAccess, paramExpr);
var method = typeof(Queryable).GetMethods().FirstOrDefault(m => m.Name == (sortOrderAsc ? "ThenBy" : "ThenByDescending") && m.GetParameters().Length == 2);
var genericMethod = method.MakeGenericMethod(typeof(T), propInfo.PropertyType);
return (IOrderedQueryable<T>)genericMethod.Invoke(null, new object[] { query, expr });
}
private static PropertyInfo GetPropertyInfo(Type objType, string name)
{
var properties = objType.GetProperties();
var matchedProperty = properties.FirstOrDefault(p => p.Name.Equals(name, StringComparison.OrdinalIgnoreCase));
if (matchedProperty == null)
throw new ArgumentException("name");
return matchedProperty;
}
private static LambdaExpression GetOrderExpression(Type objType, PropertyInfo pi)
{
var paramExpr = Expression.Parameter(objType);
var propAccess = Expression.PropertyOrField(paramExpr, pi.Name);
var expr = Expression.Lambda(propAccess, paramExpr);
return expr;
}
return expr;
}
}

View File

@ -1,14 +1,13 @@
namespace ASC.Core.Common.EF
{
[Singletone]
public class MigrationHistory
{
private ConcurrentDictionary<Type, bool> _historyStore
= new ConcurrentDictionary<Type, bool>();
namespace ASC.Core.Common.EF;
public bool TryAddMigratedContext(Type contextType)
{
return _historyStore.TryAdd(contextType, true);
}
[Singletone]
public class MigrationHistory
{
private readonly ConcurrentDictionary<Type, bool> _historyStore
= new ConcurrentDictionary<Type, bool>();
public bool TryAddMigratedContext(Type contextType)
{
return _historyStore.TryAdd(contextType, true);
}
}

View File

@ -1,102 +1,103 @@
namespace ASC.Core.Common.EF.Model
namespace ASC.Core.Common.EF.Model;
public class AccountLinks : BaseEntity
{
public class AccountLinks : BaseEntity
public string Id { get; set; }
public string UId { get; set; }
public string Provider { get; set; }
public string Profile { get; set; }
public DateTime Linked { get; set; }
public override object[] GetKeys()
{
public string Id { get; set; }
public string UId { get; set; }
public string Provider { get; set; }
public string Profile { get; set; }
public DateTime Linked { get; set; }
public override object[] GetKeys()
{
return new object[] { Id, UId };
}
}
public static class AccountLinksExtension
{
public static ModelBuilderWrapper AddAccountLinks(this ModelBuilderWrapper modelBuilder)
{
modelBuilder
.Add(MySqlAddAccountLinks, Provider.MySql)
.Add(PgSqlAddAccountLinks, Provider.PostgreSql);
return modelBuilder;
}
public static void MySqlAddAccountLinks(this ModelBuilder modelBuilder)
{
modelBuilder.Entity<AccountLinks>(entity =>
{
entity.HasKey(e => new { e.Id, e.UId })
.HasName("PRIMARY");
entity.ToTable("account_links");
entity.HasIndex(e => e.UId)
.HasDatabaseName("uid");
entity.Property(e => e.Id)
.HasColumnName("id")
.HasColumnType("varchar(200)")
.HasCharSet("utf8")
.UseCollation("utf8_general_ci");
entity.Property(e => e.UId)
.HasColumnName("uid")
.HasColumnType("varchar(200)")
.HasCharSet("utf8")
.UseCollation("utf8_general_ci");
entity.Property(e => e.Linked)
.HasColumnName("linked")
.HasColumnType("datetime");
entity.Property(e => e.Profile)
.IsRequired()
.HasColumnName("profile")
.HasColumnType("text")
.HasCharSet("utf8")
.UseCollation("utf8_general_ci");
entity.Property(e => e.Provider)
.HasColumnName("provider")
.HasColumnType("char(60)")
.HasCharSet("utf8")
.UseCollation("utf8_general_ci");
});
}
public static void PgSqlAddAccountLinks(this ModelBuilder modelBuilder)
{
modelBuilder.Entity<AccountLinks>(entity =>
{
entity.HasKey(e => new { e.Id, e.UId })
.HasName("account_links_pkey");
entity.ToTable("account_links", "onlyoffice");
entity.HasIndex(e => e.UId)
.HasDatabaseName("uid");
entity.Property(e => e.Id)
.HasColumnName("id")
.HasMaxLength(200);
entity.Property(e => e.UId)
.HasColumnName("uid")
.HasMaxLength(200);
entity.Property(e => e.Linked).HasColumnName("linked");
entity.Property(e => e.Profile)
.IsRequired()
.HasColumnName("profile");
entity.Property(e => e.Provider)
.HasColumnName("provider")
.HasMaxLength(60)
.IsFixedLength()
.HasDefaultValueSql("NULL");
});
}
return new object[] { Id, UId };
}
}
public static class AccountLinksExtension
{
public static ModelBuilderWrapper AddAccountLinks(this ModelBuilderWrapper modelBuilder)
{
modelBuilder
.Add(MySqlAddAccountLinks, Provider.MySql)
.Add(PgSqlAddAccountLinks, Provider.PostgreSql);
return modelBuilder;
}
public static void MySqlAddAccountLinks(this ModelBuilder modelBuilder)
{
modelBuilder.Entity<AccountLinks>(entity =>
{
entity.HasKey(e => new { e.Id, e.UId })
.HasName("PRIMARY");
entity.ToTable("account_links");
entity.HasIndex(e => e.UId)
.HasDatabaseName("uid");
entity.Property(e => e.Id)
.HasColumnName("id")
.HasColumnType("varchar(200)")
.HasCharSet("utf8")
.UseCollation("utf8_general_ci");
entity.Property(e => e.UId)
.HasColumnName("uid")
.HasColumnType("varchar(200)")
.HasCharSet("utf8")
.UseCollation("utf8_general_ci");
entity.Property(e => e.Linked)
.HasColumnName("linked")
.HasColumnType("datetime");
entity.Property(e => e.Profile)
.IsRequired()
.HasColumnName("profile")
.HasColumnType("text")
.HasCharSet("utf8")
.UseCollation("utf8_general_ci");
entity.Property(e => e.Provider)
.HasColumnName("provider")
.HasColumnType("char(60)")
.HasCharSet("utf8")
.UseCollation("utf8_general_ci");
});
}
public static void PgSqlAddAccountLinks(this ModelBuilder modelBuilder)
{
modelBuilder.Entity<AccountLinks>(entity =>
{
entity.HasKey(e => new { e.Id, e.UId })
.HasName("account_links_pkey");
entity.ToTable("account_links", "onlyoffice");
entity.HasIndex(e => e.UId)
.HasDatabaseName("uid");
entity.Property(e => e.Id)
.HasColumnName("id")
.HasMaxLength(200);
entity.Property(e => e.UId)
.HasColumnName("uid")
.HasMaxLength(200);
entity.Property(e => e.Linked).HasColumnName("linked");
entity.Property(e => e.Profile)
.IsRequired()
.HasColumnName("profile");
entity.Property(e => e.Provider)
.HasColumnName("provider")
.HasMaxLength(60)
.IsFixedLength()
.HasDefaultValueSql("NULL");
});
}
}

View File

@ -1,225 +1,225 @@
namespace ASC.Core.Common.EF.Model
namespace ASC.Core.Common.EF.Model;
public class CrmContact
{
public class CrmContact
public int Id { get; set; }
public int TenantId { get; set; }
public bool IsCompany { get; set; }
public string Notes { get; set; }
public string Title { get; set; }
public string FirstName { get; set; }
public string LastName { get; set; }
public string CompanyName { get; set; }
public string Industry { get; set; }
public int StatusId { get; set; }
public int CompanyId { get; set; }
public int ContactTypeId { get; set; }
public Guid CreateBy { get; set; }
public DateTime CreateOn { get; set; }
public Guid LastModifedBy { get; set; }
public DateTime LastModifedOn { get; set; }
public string DisplayName { get; set; }
public bool IsShared { get; set; }
public string Currency { get; set; }
}
public static class CrmContactExtension
{
public static ModelBuilderWrapper AddCrmContact(this ModelBuilderWrapper modelBuilder)
{
public int Id { get; set; }
public int TenantId { get; set; }
public bool IsCompany { get; set; }
public string Notes { get; set; }
public string Title { get; set; }
public string FirstName { get; set; }
public string LastName { get; set; }
public string CompanyName { get; set; }
public string Industry { get; set; }
public int StatusId { get; set; }
public int CompanyId { get; set; }
public int ContactTypeId { get; set; }
public Guid CreateBy { get; set; }
public DateTime CreateOn { get; set; }
public Guid LastModifedBy { get; set; }
public DateTime LastModifedOn { get; set; }
public string DisplayName { get; set; }
public bool IsShared { get; set; }
public string Currency { get; set; }
modelBuilder
.Add(MySqlAddCrmContact, Provider.MySql)
.Add(PgSqlAddCrmContact, Provider.PostgreSql);
return modelBuilder;
}
public static class CrmContactExtension
public static void MySqlAddCrmContact(this ModelBuilder modelBuilder)
{
public static ModelBuilderWrapper AddCrmContact(this ModelBuilderWrapper modelBuilder)
modelBuilder.Entity<CrmContact>(entity =>
{
modelBuilder
.Add(MySqlAddCrmContact, Provider.MySql)
.Add(PgSqlAddCrmContact, Provider.PostgreSql);
return modelBuilder;
}
public static void MySqlAddCrmContact(this ModelBuilder modelBuilder)
entity.ToTable("crm_contact");
entity.HasIndex(e => e.CreateOn)
.HasDatabaseName("create_on");
entity.HasIndex(e => new { e.LastModifedOn, e.TenantId })
.HasDatabaseName("last_modifed_on");
entity.HasIndex(e => new { e.TenantId, e.CompanyId })
.HasDatabaseName("company_id");
entity.HasIndex(e => new { e.TenantId, e.DisplayName })
.HasDatabaseName("display_name");
entity.Property(e => e.Id).HasColumnName("id");
entity.Property(e => e.CompanyId).HasColumnName("company_id");
entity.Property(e => e.CompanyName)
.HasColumnName("company_name")
.HasColumnType("varchar(255)")
.HasCharSet("utf8")
.UseCollation("utf8_general_ci");
entity.Property(e => e.ContactTypeId).HasColumnName("contact_type_id");
entity.Property(e => e.CreateBy)
.IsRequired()
.HasColumnName("create_by")
.HasColumnType("char(38)")
.HasCharSet("utf8")
.UseCollation("utf8_general_ci");
entity.Property(e => e.CreateOn)
.HasColumnName("create_on")
.HasColumnType("datetime");
entity.Property(e => e.Currency)
.HasColumnName("currency")
.HasColumnType("varchar(3)")
.HasCharSet("utf8")
.UseCollation("utf8_general_ci");
entity.Property(e => e.DisplayName)
.HasColumnName("display_name")
.HasColumnType("varchar(255)")
.HasCharSet("utf8")
.UseCollation("utf8_general_ci");
entity.Property(e => e.FirstName)
.HasColumnName("first_name")
.HasColumnType("varchar(255)")
.HasCharSet("utf8")
.UseCollation("utf8_general_ci");
entity.Property(e => e.Industry)
.HasColumnName("industry")
.HasColumnType("varchar(255)")
.HasCharSet("utf8")
.UseCollation("utf8_general_ci");
entity.Property(e => e.IsCompany).HasColumnName("is_company");
entity.Property(e => e.IsShared).HasColumnName("is_shared");
entity.Property(e => e.LastModifedBy)
.HasColumnName("last_modifed_by")
.HasColumnType("char(38)")
.HasCharSet("utf8")
.UseCollation("utf8_general_ci");
entity.Property(e => e.LastModifedOn)
.HasColumnName("last_modifed_on")
.HasColumnType("datetime");
entity.Property(e => e.LastName)
.HasColumnName("last_name")
.HasColumnType("varchar(255)")
.HasCharSet("utf8")
.UseCollation("utf8_general_ci");
entity.Property(e => e.Notes)
.HasColumnName("notes")
.HasColumnType("text")
.HasCharSet("utf8")
.UseCollation("utf8_general_ci");
entity.Property(e => e.StatusId).HasColumnName("status_id");
entity.Property(e => e.TenantId).HasColumnName("tenant_id");
entity.Property(e => e.Title)
.HasColumnName("title")
.HasColumnType("varchar(255)")
.HasCharSet("utf8")
.UseCollation("utf8_general_ci");
});
}
public static void PgSqlAddCrmContact(this ModelBuilder modelBuilder)
{
modelBuilder.Entity<CrmContact>(entity =>
{
modelBuilder.Entity<CrmContact>(entity =>
{
entity.ToTable("crm_contact");
entity.ToTable("crm_contact", "onlyoffice");
entity.HasIndex(e => e.CreateOn)
.HasDatabaseName("create_on");
entity.HasIndex(e => e.CreateOn)
.HasDatabaseName("create_on_crm_contact");
entity.HasIndex(e => new { e.LastModifedOn, e.TenantId })
.HasDatabaseName("last_modifed_on");
entity.HasIndex(e => new { e.LastModifedOn, e.TenantId })
.HasDatabaseName("last_modifed_on_crm_contact");
entity.HasIndex(e => new { e.TenantId, e.CompanyId })
.HasDatabaseName("company_id");
entity.HasIndex(e => new { e.TenantId, e.CompanyId })
.HasDatabaseName("company_id");
entity.HasIndex(e => new { e.TenantId, e.DisplayName })
.HasDatabaseName("display_name");
entity.HasIndex(e => new { e.TenantId, e.DisplayName })
.HasDatabaseName("display_name");
entity.Property(e => e.Id).HasColumnName("id");
entity.Property(e => e.Id).HasColumnName("id");
entity.Property(e => e.CompanyId).HasColumnName("company_id");
entity.Property(e => e.CompanyId).HasColumnName("company_id");
entity.Property(e => e.CompanyName)
.HasColumnName("company_name")
.HasColumnType("varchar(255)")
.HasCharSet("utf8")
.UseCollation("utf8_general_ci");
entity.Property(e => e.CompanyName)
.HasColumnName("company_name")
.HasMaxLength(255)
.HasDefaultValueSql("NULL::character varying");
entity.Property(e => e.ContactTypeId).HasColumnName("contact_type_id");
entity.Property(e => e.ContactTypeId).HasColumnName("contact_type_id");
entity.Property(e => e.CreateBy)
.IsRequired()
.HasColumnName("create_by")
.HasColumnType("char(38)")
.HasCharSet("utf8")
.UseCollation("utf8_general_ci");
entity.Property(e => e.CreateBy)
.IsRequired()
.HasColumnName("create_by")
.HasMaxLength(38)
.IsFixedLength();
entity.Property(e => e.CreateOn)
.HasColumnName("create_on")
.HasColumnType("datetime");
entity.Property(e => e.CreateOn).HasColumnName("create_on");
entity.Property(e => e.Currency)
.HasColumnName("currency")
.HasColumnType("varchar(3)")
.HasCharSet("utf8")
.UseCollation("utf8_general_ci");
entity.Property(e => e.Currency)
.HasColumnName("currency")
.HasMaxLength(3)
.HasDefaultValueSql("NULL");
entity.Property(e => e.DisplayName)
.HasColumnName("display_name")
.HasColumnType("varchar(255)")
.HasCharSet("utf8")
.UseCollation("utf8_general_ci");
entity.Property(e => e.DisplayName)
.HasColumnName("display_name")
.HasMaxLength(255)
.HasDefaultValueSql("NULL");
entity.Property(e => e.FirstName)
.HasColumnName("first_name")
.HasColumnType("varchar(255)")
.HasCharSet("utf8")
.UseCollation("utf8_general_ci");
entity.Property(e => e.FirstName)
.HasColumnName("first_name")
.HasMaxLength(255)
.HasDefaultValueSql("NULL");
entity.Property(e => e.Industry)
.HasColumnName("industry")
.HasColumnType("varchar(255)")
.HasCharSet("utf8")
.UseCollation("utf8_general_ci");
entity.Property(e => e.Industry)
.HasColumnName("industry")
.HasMaxLength(255)
.HasDefaultValueSql("NULL");
entity.Property(e => e.IsCompany).HasColumnName("is_company");
entity.Property(e => e.IsCompany).HasColumnName("is_company");
entity.Property(e => e.IsShared).HasColumnName("is_shared");
entity.Property(e => e.IsShared).HasColumnName("is_shared");
entity.Property(e => e.LastModifedBy)
.HasColumnName("last_modifed_by")
.HasColumnType("char(38)")
.HasCharSet("utf8")
.UseCollation("utf8_general_ci");
entity.Property(e => e.LastModifedBy)
.HasColumnName("last_modifed_by")
.HasMaxLength(38)
.HasDefaultValueSql("NULL");
entity.Property(e => e.LastModifedOn)
.HasColumnName("last_modifed_on")
.HasColumnType("datetime");
entity.Property(e => e.LastModifedOn)
.HasColumnName("last_modifed_on")
.HasDefaultValueSql("NULL");
entity.Property(e => e.LastName)
.HasColumnName("last_name")
.HasColumnType("varchar(255)")
.HasCharSet("utf8")
.UseCollation("utf8_general_ci");
entity.Property(e => e.LastName)
.HasColumnName("last_name")
.HasMaxLength(255)
.HasDefaultValueSql("NULL");
entity.Property(e => e.Notes)
.HasColumnName("notes")
.HasColumnType("text")
.HasCharSet("utf8")
.UseCollation("utf8_general_ci");
entity.Property(e => e.Notes).HasColumnName("notes");
entity.Property(e => e.StatusId).HasColumnName("status_id");
entity.Property(e => e.StatusId).HasColumnName("status_id");
entity.Property(e => e.TenantId).HasColumnName("tenant_id");
entity.Property(e => e.TenantId).HasColumnName("tenant_id");
entity.Property(e => e.Title)
.HasColumnName("title")
.HasColumnType("varchar(255)")
.HasCharSet("utf8")
.UseCollation("utf8_general_ci");
});
}
public static void PgSqlAddCrmContact(this ModelBuilder modelBuilder)
{
modelBuilder.Entity<CrmContact>(entity =>
{
entity.ToTable("crm_contact", "onlyoffice");
entity.Property(e => e.Title)
.HasColumnName("title")
.HasMaxLength(255)
.HasDefaultValueSql("NULL");
});
entity.HasIndex(e => e.CreateOn)
.HasDatabaseName("create_on_crm_contact");
entity.HasIndex(e => new { e.LastModifedOn, e.TenantId })
.HasDatabaseName("last_modifed_on_crm_contact");
entity.HasIndex(e => new { e.TenantId, e.CompanyId })
.HasDatabaseName("company_id");
entity.HasIndex(e => new { e.TenantId, e.DisplayName })
.HasDatabaseName("display_name");
entity.Property(e => e.Id).HasColumnName("id");
entity.Property(e => e.CompanyId).HasColumnName("company_id");
entity.Property(e => e.CompanyName)
.HasColumnName("company_name")
.HasMaxLength(255)
.HasDefaultValueSql("NULL::character varying");
entity.Property(e => e.ContactTypeId).HasColumnName("contact_type_id");
entity.Property(e => e.CreateBy)
.IsRequired()
.HasColumnName("create_by")
.HasMaxLength(38)
.IsFixedLength();
entity.Property(e => e.CreateOn).HasColumnName("create_on");
entity.Property(e => e.Currency)
.HasColumnName("currency")
.HasMaxLength(3)
.HasDefaultValueSql("NULL");
entity.Property(e => e.DisplayName)
.HasColumnName("display_name")
.HasMaxLength(255)
.HasDefaultValueSql("NULL");
entity.Property(e => e.FirstName)
.HasColumnName("first_name")
.HasMaxLength(255)
.HasDefaultValueSql("NULL");
entity.Property(e => e.Industry)
.HasColumnName("industry")
.HasMaxLength(255)
.HasDefaultValueSql("NULL");
entity.Property(e => e.IsCompany).HasColumnName("is_company");
entity.Property(e => e.IsShared).HasColumnName("is_shared");
entity.Property(e => e.LastModifedBy)
.HasColumnName("last_modifed_by")
.HasMaxLength(38)
.HasDefaultValueSql("NULL");
entity.Property(e => e.LastModifedOn)
.HasColumnName("last_modifed_on")
.HasDefaultValueSql("NULL");
entity.Property(e => e.LastName)
.HasColumnName("last_name")
.HasMaxLength(255)
.HasDefaultValueSql("NULL");
entity.Property(e => e.Notes).HasColumnName("notes");
entity.Property(e => e.StatusId).HasColumnName("status_id");
entity.Property(e => e.TenantId).HasColumnName("tenant_id");
entity.Property(e => e.Title)
.HasColumnName("title")
.HasMaxLength(255)
.HasDefaultValueSql("NULL");
});
}
}
}

View File

@ -1,181 +1,181 @@
namespace ASC.Core.Common.EF.Model
namespace ASC.Core.Common.EF.Model;
public class DbVoipCall
{
public class DbVoipCall
{
public string Id { get; set; }
public string ParentCallId { get; set; }
public string NumberFrom { get; set; }
public string NumberTo { get; set; }
public int Status { get; set; }
public Guid AnsweredBy { get; set; }
public DateTime DialDate { get; set; }
public int DialDuration { get; set; }
public string RecordSid { get; set; }
public string RecordUrl { get; set; }
public int RecordDuration { get; set; }
public decimal RecordPrice { get; set; }
public int ContactId { get; set; }
public decimal Price { get; set; }
public int TenantId { get; set; }
public string Id { get; set; }
public string ParentCallId { get; set; }
public string NumberFrom { get; set; }
public string NumberTo { get; set; }
public int Status { get; set; }
public Guid AnsweredBy { get; set; }
public DateTime DialDate { get; set; }
public int DialDuration { get; set; }
public string RecordSid { get; set; }
public string RecordUrl { get; set; }
public int RecordDuration { get; set; }
public decimal RecordPrice { get; set; }
public int ContactId { get; set; }
public decimal Price { get; set; }
public int TenantId { get; set; }
public CrmContact CrmContact { get; set; }
public CrmContact CrmContact { get; set; }
}
public static class DbVoipCallExtension
{
public static ModelBuilderWrapper AddDbVoipCall(this ModelBuilderWrapper modelBuilder)
{
modelBuilder
.Add(MySqlAddDbVoipCall, Provider.MySql)
.Add(PgSqlAddDbVoipCall, Provider.PostgreSql);
return modelBuilder;
}
public static class DbVoipCallExtension
public static void MySqlAddDbVoipCall(this ModelBuilder modelBuilder)
{
public static ModelBuilderWrapper AddDbVoipCall(this ModelBuilderWrapper modelBuilder)
modelBuilder.Entity<DbVoipCall>(entity =>
{
modelBuilder
.Add(MySqlAddDbVoipCall, Provider.MySql)
.Add(PgSqlAddDbVoipCall, Provider.PostgreSql);
return modelBuilder;
}
public static void MySqlAddDbVoipCall(this ModelBuilder modelBuilder)
entity.ToTable("crm_voip_calls");
entity.HasIndex(e => e.TenantId)
.HasDatabaseName("tenant_id");
entity.HasIndex(e => new { e.ParentCallId, e.TenantId })
.HasDatabaseName("parent_call_id");
entity.Property(e => e.Id)
.HasColumnName("id")
.HasColumnType("varchar(50)")
.HasCharSet("utf8")
.UseCollation("utf8_general_ci");
entity.Property(e => e.AnsweredBy)
.IsRequired()
.HasColumnName("answered_by")
.HasColumnType("varchar(50)")
.HasDefaultValueSql("'00000000-0000-0000-0000-000000000000'")
.HasCharSet("utf8")
.UseCollation("utf8_general_ci");
entity.Property(e => e.ContactId).HasColumnName("contact_id");
entity.Property(e => e.DialDate)
.HasColumnName("dial_date")
.HasColumnType("datetime");
entity.Property(e => e.DialDuration).HasColumnName("dial_duration");
entity.Property(e => e.NumberFrom)
.IsRequired()
.HasColumnName("number_from")
.HasColumnType("varchar(50)")
.HasCharSet("utf8")
.UseCollation("utf8_general_ci");
entity.Property(e => e.NumberTo)
.IsRequired()
.HasColumnName("number_to")
.HasColumnType("varchar(50)")
.HasCharSet("utf8")
.UseCollation("utf8_general_ci");
entity.Property(e => e.ParentCallId)
.IsRequired()
.HasColumnName("parent_call_id")
.HasColumnType("varchar(50)")
.HasCharSet("utf8")
.UseCollation("utf8_general_ci");
entity.Property(e => e.Price)
.HasColumnName("price")
.HasColumnType("decimal(10,4)");
entity.Property(e => e.RecordDuration).HasColumnName("record_duration");
entity.Property(e => e.RecordPrice)
.HasColumnName("record_price")
.HasColumnType("decimal(10,4)");
entity.Property(e => e.RecordSid)
.HasColumnName("record_sid")
.HasColumnType("varchar(50)")
.HasCharSet("utf8")
.UseCollation("utf8_general_ci");
entity.Property(e => e.RecordUrl)
.HasColumnName("record_url")
.HasColumnType("text")
.HasCharSet("utf8")
.UseCollation("utf8_general_ci");
entity.Property(e => e.Status).HasColumnName("status");
entity.Property(e => e.TenantId).HasColumnName("tenant_id");
});
}
public static void PgSqlAddDbVoipCall(this ModelBuilder modelBuilder)
{
modelBuilder.Entity<DbVoipCall>(entity =>
{
modelBuilder.Entity<DbVoipCall>(entity =>
{
entity.ToTable("crm_voip_calls");
entity.ToTable("crm_voip_calls", "onlyoffice");
entity.HasIndex(e => e.TenantId)
.HasDatabaseName("tenant_id");
entity.HasIndex(e => e.TenantId)
.HasDatabaseName("tenant_id_crm_voip_calls");
entity.HasIndex(e => new { e.ParentCallId, e.TenantId })
.HasDatabaseName("parent_call_id");
entity.HasIndex(e => new { e.ParentCallId, e.TenantId })
.HasDatabaseName("parent_call_id");
entity.Property(e => e.Id)
.HasColumnName("id")
.HasColumnType("varchar(50)")
.HasCharSet("utf8")
.UseCollation("utf8_general_ci");
entity.Property(e => e.Id)
.HasColumnName("id")
.HasMaxLength(50);
entity.Property(e => e.AnsweredBy)
.IsRequired()
.HasColumnName("answered_by")
.HasColumnType("varchar(50)")
.HasDefaultValueSql("'00000000-0000-0000-0000-000000000000'")
.HasCharSet("utf8")
.UseCollation("utf8_general_ci");
entity.Property(e => e.AnsweredBy)
.IsRequired()
.HasColumnName("answered_by")
.HasMaxLength(50)
.HasDefaultValueSql("'00000000-0000-0000-0000-000000000000'");
entity.Property(e => e.ContactId).HasColumnName("contact_id");
entity.Property(e => e.ContactId).HasColumnName("contact_id");
entity.Property(e => e.DialDate)
.HasColumnName("dial_date")
.HasColumnType("datetime");
entity.Property(e => e.DialDate).HasColumnName("dial_date");
entity.Property(e => e.DialDuration).HasColumnName("dial_duration");
entity.Property(e => e.DialDuration).HasColumnName("dial_duration");
entity.Property(e => e.NumberFrom)
.IsRequired()
.HasColumnName("number_from")
.HasColumnType("varchar(50)")
.HasCharSet("utf8")
.UseCollation("utf8_general_ci");
entity.Property(e => e.NumberFrom)
.IsRequired()
.HasColumnName("number_from")
.HasMaxLength(50);
entity.Property(e => e.NumberTo)
.IsRequired()
.HasColumnName("number_to")
.HasColumnType("varchar(50)")
.HasCharSet("utf8")
.UseCollation("utf8_general_ci");
entity.Property(e => e.NumberTo)
.IsRequired()
.HasColumnName("number_to")
.HasMaxLength(50);
entity.Property(e => e.ParentCallId)
.IsRequired()
.HasColumnName("parent_call_id")
.HasColumnType("varchar(50)")
.HasCharSet("utf8")
.UseCollation("utf8_general_ci");
entity.Property(e => e.ParentCallId)
.IsRequired()
.HasColumnName("parent_call_id")
.HasMaxLength(50);
entity.Property(e => e.Price)
.HasColumnName("price")
.HasColumnType("decimal(10,4)");
entity.Property(e => e.Price)
.HasColumnName("price")
.HasColumnType("numeric(10,4)")
.HasDefaultValueSql("NULL");
entity.Property(e => e.RecordDuration).HasColumnName("record_duration");
entity.Property(e => e.RecordDuration).HasColumnName("record_duration");
entity.Property(e => e.RecordPrice)
.HasColumnName("record_price")
.HasColumnType("decimal(10,4)");
entity.Property(e => e.RecordPrice)
.HasColumnName("record_price")
.HasColumnType("numeric(10,4)");
entity.Property(e => e.RecordSid)
.HasColumnName("record_sid")
.HasColumnType("varchar(50)")
.HasCharSet("utf8")
.UseCollation("utf8_general_ci");
entity.Property(e => e.RecordSid)
.HasColumnName("record_sid")
.HasMaxLength(50)
.HasDefaultValueSql("NULL");
entity.Property(e => e.RecordUrl)
.HasColumnName("record_url")
.HasColumnType("text")
.HasCharSet("utf8")
.UseCollation("utf8_general_ci");
entity.Property(e => e.RecordUrl).HasColumnName("record_url");
entity.Property(e => e.Status).HasColumnName("status");
entity.Property(e => e.Status).HasColumnName("status");
entity.Property(e => e.TenantId).HasColumnName("tenant_id");
});
}
public static void PgSqlAddDbVoipCall(this ModelBuilder modelBuilder)
{
modelBuilder.Entity<DbVoipCall>(entity =>
{
entity.ToTable("crm_voip_calls", "onlyoffice");
entity.HasIndex(e => e.TenantId)
.HasDatabaseName("tenant_id_crm_voip_calls");
entity.HasIndex(e => new { e.ParentCallId, e.TenantId })
.HasDatabaseName("parent_call_id");
entity.Property(e => e.Id)
.HasColumnName("id")
.HasMaxLength(50);
entity.Property(e => e.AnsweredBy)
.IsRequired()
.HasColumnName("answered_by")
.HasMaxLength(50)
.HasDefaultValueSql("'00000000-0000-0000-0000-000000000000'");
entity.Property(e => e.ContactId).HasColumnName("contact_id");
entity.Property(e => e.DialDate).HasColumnName("dial_date");
entity.Property(e => e.DialDuration).HasColumnName("dial_duration");
entity.Property(e => e.NumberFrom)
.IsRequired()
.HasColumnName("number_from")
.HasMaxLength(50);
entity.Property(e => e.NumberTo)
.IsRequired()
.HasColumnName("number_to")
.HasMaxLength(50);
entity.Property(e => e.ParentCallId)
.IsRequired()
.HasColumnName("parent_call_id")
.HasMaxLength(50);
entity.Property(e => e.Price)
.HasColumnName("price")
.HasColumnType("numeric(10,4)")
.HasDefaultValueSql("NULL");
entity.Property(e => e.RecordDuration).HasColumnName("record_duration");
entity.Property(e => e.RecordPrice)
.HasColumnName("record_price")
.HasColumnType("numeric(10,4)");
entity.Property(e => e.RecordSid)
.HasColumnName("record_sid")
.HasMaxLength(50)
.HasDefaultValueSql("NULL");
entity.Property(e => e.RecordUrl).HasColumnName("record_url");
entity.Property(e => e.Status).HasColumnName("status");
entity.Property(e => e.TenantId).HasColumnName("tenant_id");
});
}
entity.Property(e => e.TenantId).HasColumnName("tenant_id");
});
}
}

View File

@ -1,86 +1,86 @@
namespace ASC.Core.Common.EF.Model
namespace ASC.Core.Common.EF.Model;
public class VoipNumber
{
public class VoipNumber
public string Id { get; set; }
public string Number { get; set; }
public string Alias { get; set; }
public string Settings { get; set; }
public int TenantId { get; set; }
}
public static class VoipNumberExtension
{
public static ModelBuilderWrapper AddVoipNumber(this ModelBuilderWrapper modelBuilder)
{
public string Id { get; set; }
public string Number { get; set; }
public string Alias { get; set; }
public string Settings { get; set; }
public int TenantId { get; set; }
modelBuilder
.Add(MySqlAddVoipNumber, Provider.MySql)
.Add(PgSqlAddVoipNumber, Provider.PostgreSql);
return modelBuilder;
}
public static class VoipNumberExtension
public static void MySqlAddVoipNumber(this ModelBuilder modelBuilder)
{
public static ModelBuilderWrapper AddVoipNumber(this ModelBuilderWrapper modelBuilder)
modelBuilder.Entity<VoipNumber>(entity =>
{
modelBuilder
.Add(MySqlAddVoipNumber, Provider.MySql)
.Add(PgSqlAddVoipNumber, Provider.PostgreSql);
return modelBuilder;
}
public static void MySqlAddVoipNumber(this ModelBuilder modelBuilder)
entity.ToTable("crm_voip_number");
entity.HasIndex(e => e.TenantId)
.HasDatabaseName("tenant_id");
entity.Property(e => e.Id)
.HasColumnName("id")
.HasColumnType("varchar(50)")
.HasCharSet("utf8")
.UseCollation("utf8_general_ci");
entity.Property(e => e.Alias)
.HasColumnName("alias")
.HasColumnType("varchar(255)")
.HasCharSet("utf8")
.UseCollation("utf8_general_ci");
entity.Property(e => e.Number)
.IsRequired()
.HasColumnName("number")
.HasColumnType("varchar(50)")
.HasCharSet("utf8")
.UseCollation("utf8_general_ci");
entity.Property(e => e.Settings)
.HasColumnName("settings")
.HasColumnType("text")
.HasCharSet("utf8")
.UseCollation("utf8_general_ci");
entity.Property(e => e.TenantId).HasColumnName("tenant_id");
});
}
public static void PgSqlAddVoipNumber(this ModelBuilder modelBuilder)
{
modelBuilder.Entity<VoipNumber>(entity =>
{
modelBuilder.Entity<VoipNumber>(entity =>
{
entity.ToTable("crm_voip_number");
entity.ToTable("crm_voip_number", "onlyoffice");
entity.HasIndex(e => e.TenantId)
.HasDatabaseName("tenant_id");
entity.HasIndex(e => e.TenantId)
.HasDatabaseName("tenant_id_crm_voip_number");
entity.Property(e => e.Id)
.HasColumnName("id")
.HasColumnType("varchar(50)")
.HasCharSet("utf8")
.UseCollation("utf8_general_ci");
entity.Property(e => e.Id)
.HasColumnName("id")
.HasMaxLength(50);
entity.Property(e => e.Alias)
.HasColumnName("alias")
.HasColumnType("varchar(255)")
.HasCharSet("utf8")
.UseCollation("utf8_general_ci");
entity.Property(e => e.Alias)
.HasColumnName("alias")
.HasMaxLength(255)
.HasDefaultValueSql("NULL");
entity.Property(e => e.Number)
.IsRequired()
.HasColumnName("number")
.HasColumnType("varchar(50)")
.HasCharSet("utf8")
.UseCollation("utf8_general_ci");
entity.Property(e => e.Number)
.IsRequired()
.HasColumnName("number")
.HasMaxLength(50);
entity.Property(e => e.Settings)
.HasColumnName("settings")
.HasColumnType("text")
.HasCharSet("utf8")
.UseCollation("utf8_general_ci");
entity.Property(e => e.Settings).HasColumnName("settings");
entity.Property(e => e.TenantId).HasColumnName("tenant_id");
});
}
public static void PgSqlAddVoipNumber(this ModelBuilder modelBuilder)
{
modelBuilder.Entity<VoipNumber>(entity =>
{
entity.ToTable("crm_voip_number", "onlyoffice");
entity.HasIndex(e => e.TenantId)
.HasDatabaseName("tenant_id_crm_voip_number");
entity.Property(e => e.Id)
.HasColumnName("id")
.HasMaxLength(50);
entity.Property(e => e.Alias)
.HasColumnName("alias")
.HasMaxLength(255)
.HasDefaultValueSql("NULL");
entity.Property(e => e.Number)
.IsRequired()
.HasColumnName("number")
.HasMaxLength(50);
entity.Property(e => e.Settings).HasColumnName("settings");
entity.Property(e => e.TenantId).HasColumnName("tenant_id");
});
}
entity.Property(e => e.TenantId).HasColumnName("tenant_id");
});
}
}

View File

@ -1,157 +1,156 @@
namespace ASC.Core.Common.EF
namespace ASC.Core.Common.EF;
public class Acl : BaseEntity, IMapFrom<AzRecord>
{
public class Acl : BaseEntity
public int Tenant { get; set; }
public Guid Subject { get; set; }
public Guid Action { get; set; }
public string Object { get; set; }
public AceType AceType { get; set; }
public override object[] GetKeys()
{
public int Tenant { get; set; }
public Guid Subject { get; set; }
public Guid Action { get; set; }
public string Object { get; set; }
public AceType AceType { get; set; }
public override object[] GetKeys()
{
return new object[] { Tenant, Subject, Action, Object };
}
}
public static class AclExtension
{
public static ModelBuilderWrapper AddAcl(this ModelBuilderWrapper modelBuilder)
{
modelBuilder
.Add(MySqlAddAcl, Provider.MySql)
.Add(PgSqlAddAcl, Provider.PostgreSql)
.HasData(
new Acl { Tenant = -1, Subject = Guid.Parse("5d5b7260-f7f7-49f1-a1c9-95fbb6a12604"), Action = Guid.Parse("ef5e6790-f346-4b6e-b662-722bc28cb0db"), Object = "", AceType = 0 },
new Acl { Tenant = -1, Subject = Guid.Parse("5d5b7260-f7f7-49f1-a1c9-95fbb6a12604"), Action = Guid.Parse("f11e8f3f-46e6-4e55-90e3-09c22ec565bd"), Object = "", AceType = 0 },
new Acl { Tenant = -1, Subject = Guid.Parse("c5cc67d1-c3e8-43c0-a3ad-3928ae3e5b5e"), Action = Guid.Parse("088d5940-a80f-4403-9741-d610718ce95c"), Object = "", AceType = 0 },
new Acl { Tenant = -1, Subject = Guid.Parse("c5cc67d1-c3e8-43c0-a3ad-3928ae3e5b5e"), Action = Guid.Parse("08d66144-e1c9-4065-9aa1-aa4bba0a7bc8"), Object = "", AceType = 0 },
new Acl { Tenant = -1, Subject = Guid.Parse("abef62db-11a8-4673-9d32-ef1d8af19dc0"), Action = Guid.Parse("08d75c97-cf3f-494b-90d1-751c941fe2dd"), Object = "", AceType = 0 },
new Acl { Tenant = -1, Subject = Guid.Parse("abef62db-11a8-4673-9d32-ef1d8af19dc0"), Action = Guid.Parse("0d1f72a8-63da-47ea-ae42-0900e4ac72a9"), Object = "", AceType = 0 },
new Acl { Tenant = -1, Subject = Guid.Parse("abef62db-11a8-4673-9d32-ef1d8af19dc0"), Action = Guid.Parse("13e30b51-5b4d-40a5-8575-cb561899eeb1"), Object = "", AceType = 0 },
new Acl { Tenant = -1, Subject = Guid.Parse("abef62db-11a8-4673-9d32-ef1d8af19dc0"), Action = Guid.Parse("19f658ae-722b-4cd8-8236-3ad150801d96"), Object = "", AceType = 0 },
new Acl { Tenant = -1, Subject = Guid.Parse("abef62db-11a8-4673-9d32-ef1d8af19dc0"), Action = Guid.Parse("2c6552b3-b2e0-4a00-b8fd-13c161e337b1"), Object = "", AceType = 0 },
new Acl { Tenant = -1, Subject = Guid.Parse("c5cc67d1-c3e8-43c0-a3ad-3928ae3e5b5e"), Action = Guid.Parse("388c29d3-c662-4a61-bf47-fc2f7094224a"), Object = "", AceType = 0 },
new Acl { Tenant = -1, Subject = Guid.Parse("abef62db-11a8-4673-9d32-ef1d8af19dc0"), Action = Guid.Parse("40bf31f4-3132-4e76-8d5c-9828a89501a3"), Object = "", AceType = 0 },
new Acl { Tenant = -1, Subject = Guid.Parse("abef62db-11a8-4673-9d32-ef1d8af19dc0"), Action = Guid.Parse("49ae8915-2b30-4348-ab74-b152279364fb"), Object = "", AceType = 0 },
new Acl { Tenant = -1, Subject = Guid.Parse("c5cc67d1-c3e8-43c0-a3ad-3928ae3e5b5e"), Action = Guid.Parse("63e9f35f-6bb5-4fb1-afaa-e4c2f4dec9bd"), Object = "", AceType = 0 },
new Acl { Tenant = -1, Subject = Guid.Parse("c5cc67d1-c3e8-43c0-a3ad-3928ae3e5b5e"), Action = Guid.Parse("9018c001-24c2-44bf-a1db-d1121a570e74"), Object = "", AceType = 0 },
new Acl { Tenant = -1, Subject = Guid.Parse("abef62db-11a8-4673-9d32-ef1d8af19dc0"), Action = Guid.Parse("948ad738-434b-4a88-8e38-7569d332910a"), Object = "", AceType = 0 },
new Acl { Tenant = -1, Subject = Guid.Parse("abef62db-11a8-4673-9d32-ef1d8af19dc0"), Action = Guid.Parse("9d75a568-52aa-49d8-ad43-473756cd8903"), Object = "", AceType = 0 },
new Acl { Tenant = -1, Subject = Guid.Parse("c5cc67d1-c3e8-43c0-a3ad-3928ae3e5b5e"), Action = Guid.Parse("a362fe79-684e-4d43-a599-65bc1f4e167f"), Object = "", AceType = 0 },
new Acl { Tenant = -1, Subject = Guid.Parse("c5cc67d1-c3e8-43c0-a3ad-3928ae3e5b5e"), Action = Guid.Parse("c426c349-9ad4-47cd-9b8f-99fc30675951"), Object = "", AceType = 0 },
new Acl { Tenant = -1, Subject = Guid.Parse("c5cc67d1-c3e8-43c0-a3ad-3928ae3e5b5e"), Action = Guid.Parse("d11ebcb9-0e6e-45e6-a6d0-99c41d687598"), Object = "", AceType = 0 },
new Acl { Tenant = -1, Subject = Guid.Parse("c5cc67d1-c3e8-43c0-a3ad-3928ae3e5b5e"), Action = Guid.Parse("d1f3b53d-d9e2-4259-80e7-d24380978395"), Object = "", AceType = 0 },
new Acl { Tenant = -1, Subject = Guid.Parse("abef62db-11a8-4673-9d32-ef1d8af19dc0"), Action = Guid.Parse("d49f4e30-da10-4b39-bc6d-b41ef6e039d3"), Object = "", AceType = 0 },
new Acl { Tenant = -1, Subject = Guid.Parse("abef62db-11a8-4673-9d32-ef1d8af19dc0"), Action = Guid.Parse("d852b66f-6719-45e1-8657-18f0bb791690"), Object = "", AceType = 0 },
new Acl { Tenant = -1, Subject = Guid.Parse("c5cc67d1-c3e8-43c0-a3ad-3928ae3e5b5e"), Action = Guid.Parse("e0759a42-47f0-4763-a26a-d5aa665bec35"), Object = "", AceType = 0 },
new Acl { Tenant = -1, Subject = Guid.Parse("c5cc67d1-c3e8-43c0-a3ad-3928ae3e5b5e"), Action = Guid.Parse("e37239bd-c5b5-4f1e-a9f8-3ceeac209615"), Object = "", AceType = 0 },
new Acl { Tenant = -1, Subject = Guid.Parse("c5cc67d1-c3e8-43c0-a3ad-3928ae3e5b5e"), Action = Guid.Parse("fbc37705-a04c-40ad-a68c-ce2f0423f397"), Object = "", AceType = 0 },
new Acl { Tenant = -1, Subject = Guid.Parse("c5cc67d1-c3e8-43c0-a3ad-3928ae3e5b5e"), Action = Guid.Parse("fcac42b8-9386-48eb-a938-d19b3c576912"), Object = "", AceType = 0 },
new Acl { Tenant = -1, Subject = Guid.Parse("ba74ca02-873f-43dc-8470-8620c156bc67"), Action = Guid.Parse("13e30b51-5b4d-40a5-8575-cb561899eeb1"), Object = "", AceType = 0 },
new Acl { Tenant = -1, Subject = Guid.Parse("ba74ca02-873f-43dc-8470-8620c156bc67"), Action = Guid.Parse("49ae8915-2b30-4348-ab74-b152279364fb"), Object = "", AceType = 0 },
new Acl { Tenant = -1, Subject = Guid.Parse("ba74ca02-873f-43dc-8470-8620c156bc67"), Action = Guid.Parse("63e9f35f-6bb5-4fb1-afaa-e4c2f4dec9bd"), Object = "", AceType = 0 },
new Acl { Tenant = -1, Subject = Guid.Parse("ba74ca02-873f-43dc-8470-8620c156bc67"), Action = Guid.Parse("9018c001-24c2-44bf-a1db-d1121a570e74"), Object = "", AceType = 0 },
new Acl { Tenant = -1, Subject = Guid.Parse("ba74ca02-873f-43dc-8470-8620c156bc67"), Action = Guid.Parse("d1f3b53d-d9e2-4259-80e7-d24380978395"), Object = "", AceType = 0 },
new Acl { Tenant = -1, Subject = Guid.Parse("ba74ca02-873f-43dc-8470-8620c156bc67"), Action = Guid.Parse("e0759a42-47f0-4763-a26a-d5aa665bec35"), Object = "", AceType = 0 },
new Acl { Tenant = -1, Subject = Guid.Parse("ba74ca02-873f-43dc-8470-8620c156bc67"), Action = Guid.Parse("e37239bd-c5b5-4f1e-a9f8-3ceeac209615"), Object = "", AceType = 0 },
new Acl { Tenant = -1, Subject = Guid.Parse("ba74ca02-873f-43dc-8470-8620c156bc67"), Action = Guid.Parse("f11e88d7-f185-4372-927c-d88008d2c483"), Object = "", AceType = 0 },
new Acl { Tenant = -1, Subject = Guid.Parse("ba74ca02-873f-43dc-8470-8620c156bc67"), Action = Guid.Parse("f11e8f3f-46e6-4e55-90e3-09c22ec565bd"), Object = "", AceType = 0 },
new Acl { Tenant = -1, Subject = Guid.Parse("bba32183-a14d-48ed-9d39-c6b4d8925fbf"), Action = Guid.Parse("00e7dfc5-ac49-4fd3-a1d6-98d84e877ac4"), Object = "", AceType = 0 },
new Acl { Tenant = -1, Subject = Guid.Parse("bba32183-a14d-48ed-9d39-c6b4d8925fbf"), Action = Guid.Parse("14be970f-7af5-4590-8e81-ea32b5f7866d"), Object = "", AceType = 0 },
new Acl { Tenant = -1, Subject = Guid.Parse("bba32183-a14d-48ed-9d39-c6b4d8925fbf"), Action = Guid.Parse("18ecc94d-6afa-4994-8406-aee9dff12ce2"), Object = "", AceType = 0 },
new Acl { Tenant = -1, Subject = Guid.Parse("bba32183-a14d-48ed-9d39-c6b4d8925fbf"), Action = Guid.Parse("298530eb-435e-4dc6-a776-9abcd95c70e9"), Object = "", AceType = 0 },
new Acl { Tenant = -1, Subject = Guid.Parse("bba32183-a14d-48ed-9d39-c6b4d8925fbf"), Action = Guid.Parse("430eaf70-1886-483c-a746-1a18e3e6bb63"), Object = "", AceType = 0 },
new Acl { Tenant = -1, Subject = Guid.Parse("bba32183-a14d-48ed-9d39-c6b4d8925fbf"), Action = Guid.Parse("557d6503-633b-4490-a14c-6473147ce2b3"), Object = "", AceType = 0 }/*qwerty*/,
new Acl { Tenant = -1, Subject = Guid.Parse("bba32183-a14d-48ed-9d39-c6b4d8925fbf"), Action = Guid.Parse("724cbb75-d1c9-451e-bae0-4de0db96b1f7"), Object = "", AceType = 0 },
new Acl { Tenant = -1, Subject = Guid.Parse("bba32183-a14d-48ed-9d39-c6b4d8925fbf"), Action = Guid.Parse("7cb5c0d1-d254-433f-abe3-ff23373ec631"), Object = "", AceType = 0 },
new Acl { Tenant = -1, Subject = Guid.Parse("bba32183-a14d-48ed-9d39-c6b4d8925fbf"), Action = Guid.Parse("91b29dcd-9430-4403-b17a-27d09189be88"), Object = "", AceType = 0 },
new Acl { Tenant = -1, Subject = Guid.Parse("bba32183-a14d-48ed-9d39-c6b4d8925fbf"), Action = Guid.Parse("a18480a4-6d18-4c71-84fa-789888791f45"), Object = "", AceType = 0 },
new Acl { Tenant = -1, Subject = Guid.Parse("bba32183-a14d-48ed-9d39-c6b4d8925fbf"), Action = Guid.Parse("b630d29b-1844-4bda-bbbe-cf5542df3559"), Object = "", AceType = 0 },
new Acl { Tenant = -1, Subject = Guid.Parse("bba32183-a14d-48ed-9d39-c6b4d8925fbf"), Action = Guid.Parse("c62a9e8d-b24c-4513-90aa-7ff0f8ba38eb"), Object = "", AceType = 0 },
new Acl { Tenant = -1, Subject = Guid.Parse("bba32183-a14d-48ed-9d39-c6b4d8925fbf"), Action = Guid.Parse("d7cdb020-288b-41e5-a857-597347618533"), Object = "", AceType = 0 },
new Acl { Tenant = -1, Subject = Guid.Parse("bba32183-a14d-48ed-9d39-c6b4d8925fbf"), Action = Guid.Parse("662f3db7-9bc8-42cf-84da-2765f563e9b0"), Object = "", AceType = 0 },
new Acl { Tenant = -1, Subject = Guid.Parse("712d9ec3-5d2b-4b13-824f-71f00191dcca"), Action = Guid.Parse("e0759a42-47f0-4763-a26a-d5aa665bec35"), Object = "", AceType = 0 },
new Acl { Tenant = -1, Subject = Guid.Parse("bba32183-a14d-48ed-9d39-c6b4d8925fbf"), Action = Guid.Parse("0d68b142-e20a-446e-a832-0d6b0b65a164"), Object = "", AceType = 0 },
new Acl { Tenant = -1, Subject = Guid.Parse("c5cc67d1-c3e8-43c0-a3ad-3928ae3e5b5e"), Action = Guid.Parse("6f05c382-8bca-4469-9424-c807a98c40d7"), Object = "", AceType = 0 },
new Acl { Tenant = -1, Subject = Guid.Parse("c5cc67d1-c3e8-43c0-a3ad-3928ae3e5b5e"), Action = Guid.Parse("77777777-32ae-425f-99b5-83176061d1ae"), Object = "ASC.Web.Core.WebItemSecurity+WebItemSecurityObject|1e04460243b54d7982f3fd6208a11960", AceType = 0 },
new Acl { Tenant = -1, Subject = Guid.Parse("c5cc67d1-c3e8-43c0-a3ad-3928ae3e5b5e"), Action = Guid.Parse("77777777-32ae-425f-99b5-83176061d1ae"), Object = "ASC.Web.Core.WebItemSecurity+WebItemSecurityObject|6743007c6f954d208c88a8601ce5e76d", AceType = 0 },
new Acl { Tenant = -1, Subject = Guid.Parse("c5cc67d1-c3e8-43c0-a3ad-3928ae3e5b5e"), Action = Guid.Parse("77777777-32ae-425f-99b5-83176061d1ae"), Object = "ASC.Web.Core.WebItemSecurity+WebItemSecurityObject|e67be73df9ae4ce18fec1880cb518cb4", AceType = 0 },
new Acl { Tenant = -1, Subject = Guid.Parse("c5cc67d1-c3e8-43c0-a3ad-3928ae3e5b5e"), Action = Guid.Parse("77777777-32ae-425f-99b5-83176061d1ae"), Object = "ASC.Web.Core.WebItemSecurity+WebItemSecurityObject|ea942538e68e49079394035336ee0ba8", AceType = 0 },
new Acl { Tenant = -1, Subject = Guid.Parse("c5cc67d1-c3e8-43c0-a3ad-3928ae3e5b5e"), Action = Guid.Parse("77777777-32ae-425f-99b5-83176061d1ae"), Object = "ASC.Web.Core.WebItemSecurity+WebItemSecurityObject|32d24cb57ece46069c9419216ba42086", AceType = 0 },
new Acl { Tenant = -1, Subject = Guid.Parse("c5cc67d1-c3e8-43c0-a3ad-3928ae3e5b5e"), Action = Guid.Parse("77777777-32ae-425f-99b5-83176061d1ae"), Object = "ASC.Web.Core.WebItemSecurity+WebItemSecurityObject|bf88953e3c434850a3fbb1e43ad53a3e", AceType = 0 },
new Acl { Tenant = -1, Subject = Guid.Parse("c5cc67d1-c3e8-43c0-a3ad-3928ae3e5b5e"), Action = Guid.Parse("77777777-32ae-425f-99b5-83176061d1ae"), Object = "ASC.Web.Core.WebItemSecurity+WebItemSecurityObject|2a9230378b2d487b9a225ac0918acf3f", AceType = 0 },
new Acl { Tenant = -1, Subject = Guid.Parse("c5cc67d1-c3e8-43c0-a3ad-3928ae3e5b5e"), Action = Guid.Parse("77777777-32ae-425f-99b5-83176061d1ae"), Object = "ASC.Web.Core.WebItemSecurity+WebItemSecurityObject|f4d98afdd336433287783c6945c81ea0", AceType = 0 },
new Acl { Tenant = -1, Subject = Guid.Parse("c5cc67d1-c3e8-43c0-a3ad-3928ae3e5b5e"), Action = Guid.Parse("77777777-32ae-425f-99b5-83176061d1ae"), Object = "ASC.Web.Core.WebItemSecurity+WebItemSecurityObject|28b10049dd204f54b986873bc14ccfc7", AceType = 0 },
new Acl { Tenant = -1, Subject = Guid.Parse("c5cc67d1-c3e8-43c0-a3ad-3928ae3e5b5e"), Action = Guid.Parse("77777777-32ae-425f-99b5-83176061d1ae"), Object = "ASC.Web.Core.WebItemSecurity+WebItemSecurityObject|3cfd481b46f24a4ab55cb8c0c9def02c", AceType = 0 },
new Acl { Tenant = -1, Subject = Guid.Parse("c5cc67d1-c3e8-43c0-a3ad-3928ae3e5b5e"), Action = Guid.Parse("77777777-32ae-425f-99b5-83176061d1ae"), Object = "ASC.Web.Core.WebItemSecurity+WebItemSecurityObject|6a598c7491ae437da5f4ad339bd11bb2", AceType = 0 },
new Acl { Tenant = -1, Subject = Guid.Parse("c5cc67d1-c3e8-43c0-a3ad-3928ae3e5b5e"), Action = Guid.Parse("77777777-32ae-425f-99b5-83176061d1ae"), Object = "ASC.Web.Core.WebItemSecurity+WebItemSecurityObject|742cf945cbbc4a5782d61600a12cf8ca", AceType = 0 },
new Acl { Tenant = -1, Subject = Guid.Parse("c5cc67d1-c3e8-43c0-a3ad-3928ae3e5b5e"), Action = Guid.Parse("77777777-32ae-425f-99b5-83176061d1ae"), Object = "ASC.Web.Core.WebItemSecurity+WebItemSecurityObject|853b6eb973ee438d9b098ffeedf36234", AceType = 0 },
new Acl { Tenant = -1, Subject = Guid.Parse("c5cc67d1-c3e8-43c0-a3ad-3928ae3e5b5e"), Action = Guid.Parse("77777777-32ae-425f-99b5-83176061d1ae"), Object = "ASC.Web.Core.WebItemSecurity+WebItemSecurityObject|46cfa73af32046cf8d5bcd82e1d67f26", AceType = 0 }
);
return modelBuilder;
}
public static void MySqlAddAcl(this ModelBuilder modelBuilder)
{
modelBuilder.Entity<Acl>(entity =>
{
entity.HasKey(e => new { e.Tenant, e.Subject, e.Action, e.Object })
.HasName("PRIMARY");
entity.ToTable("core_acl");
entity.Property(e => e.Tenant).HasColumnName("tenant");
entity.Property(e => e.Subject)
.HasColumnName("subject")
.HasColumnType("varchar(38)")
.HasCharSet("utf8")
.UseCollation("utf8_general_ci");
entity.Property(e => e.Action)
.HasColumnName("action")
.HasColumnType("varchar(38)")
.HasCharSet("utf8")
.UseCollation("utf8_general_ci");
entity.Property(e => e.Object)
.HasColumnName("object")
.HasColumnType("varchar(255)")
.HasDefaultValueSql("''")
.HasCharSet("utf8")
.UseCollation("utf8_general_ci");
entity.Property(e => e.AceType).HasColumnName("acetype");
});
}
public static void PgSqlAddAcl(this ModelBuilder modelBuilder)
{
modelBuilder.Entity<Acl>(entity =>
{
entity.HasKey(e => new { e.Tenant, e.Subject, e.Action, e.Object })
.HasName("core_acl_pkey");
entity.ToTable("core_acl", "onlyoffice");
entity.Property(e => e.Tenant).HasColumnName("tenant");
entity.Property(e => e.Subject)
.HasColumnName("subject")
.HasMaxLength(38);
entity.Property(e => e.Action)
.HasColumnName("action")
.HasMaxLength(38);
entity.Property(e => e.Object)
.HasColumnName("object")
.HasMaxLength(255)
.HasDefaultValueSql("''");
entity.Property(e => e.AceType).HasColumnName("acetype");
});
}
return new object[] { Tenant, Subject, Action, Object };
}
}
public static class AclExtension
{
public static ModelBuilderWrapper AddAcl(this ModelBuilderWrapper modelBuilder)
{
modelBuilder
.Add(MySqlAddAcl, Provider.MySql)
.Add(PgSqlAddAcl, Provider.PostgreSql)
.HasData(
new Acl { Tenant = -1, Subject = Guid.Parse("5d5b7260-f7f7-49f1-a1c9-95fbb6a12604"), Action = Guid.Parse("ef5e6790-f346-4b6e-b662-722bc28cb0db"), Object = "", AceType = 0 },
new Acl { Tenant = -1, Subject = Guid.Parse("5d5b7260-f7f7-49f1-a1c9-95fbb6a12604"), Action = Guid.Parse("f11e8f3f-46e6-4e55-90e3-09c22ec565bd"), Object = "", AceType = 0 },
new Acl { Tenant = -1, Subject = Guid.Parse("c5cc67d1-c3e8-43c0-a3ad-3928ae3e5b5e"), Action = Guid.Parse("088d5940-a80f-4403-9741-d610718ce95c"), Object = "", AceType = 0 },
new Acl { Tenant = -1, Subject = Guid.Parse("c5cc67d1-c3e8-43c0-a3ad-3928ae3e5b5e"), Action = Guid.Parse("08d66144-e1c9-4065-9aa1-aa4bba0a7bc8"), Object = "", AceType = 0 },
new Acl { Tenant = -1, Subject = Guid.Parse("abef62db-11a8-4673-9d32-ef1d8af19dc0"), Action = Guid.Parse("08d75c97-cf3f-494b-90d1-751c941fe2dd"), Object = "", AceType = 0 },
new Acl { Tenant = -1, Subject = Guid.Parse("abef62db-11a8-4673-9d32-ef1d8af19dc0"), Action = Guid.Parse("0d1f72a8-63da-47ea-ae42-0900e4ac72a9"), Object = "", AceType = 0 },
new Acl { Tenant = -1, Subject = Guid.Parse("abef62db-11a8-4673-9d32-ef1d8af19dc0"), Action = Guid.Parse("13e30b51-5b4d-40a5-8575-cb561899eeb1"), Object = "", AceType = 0 },
new Acl { Tenant = -1, Subject = Guid.Parse("abef62db-11a8-4673-9d32-ef1d8af19dc0"), Action = Guid.Parse("19f658ae-722b-4cd8-8236-3ad150801d96"), Object = "", AceType = 0 },
new Acl { Tenant = -1, Subject = Guid.Parse("abef62db-11a8-4673-9d32-ef1d8af19dc0"), Action = Guid.Parse("2c6552b3-b2e0-4a00-b8fd-13c161e337b1"), Object = "", AceType = 0 },
new Acl { Tenant = -1, Subject = Guid.Parse("c5cc67d1-c3e8-43c0-a3ad-3928ae3e5b5e"), Action = Guid.Parse("388c29d3-c662-4a61-bf47-fc2f7094224a"), Object = "", AceType = 0 },
new Acl { Tenant = -1, Subject = Guid.Parse("abef62db-11a8-4673-9d32-ef1d8af19dc0"), Action = Guid.Parse("40bf31f4-3132-4e76-8d5c-9828a89501a3"), Object = "", AceType = 0 },
new Acl { Tenant = -1, Subject = Guid.Parse("abef62db-11a8-4673-9d32-ef1d8af19dc0"), Action = Guid.Parse("49ae8915-2b30-4348-ab74-b152279364fb"), Object = "", AceType = 0 },
new Acl { Tenant = -1, Subject = Guid.Parse("c5cc67d1-c3e8-43c0-a3ad-3928ae3e5b5e"), Action = Guid.Parse("63e9f35f-6bb5-4fb1-afaa-e4c2f4dec9bd"), Object = "", AceType = 0 },
new Acl { Tenant = -1, Subject = Guid.Parse("c5cc67d1-c3e8-43c0-a3ad-3928ae3e5b5e"), Action = Guid.Parse("9018c001-24c2-44bf-a1db-d1121a570e74"), Object = "", AceType = 0 },
new Acl { Tenant = -1, Subject = Guid.Parse("abef62db-11a8-4673-9d32-ef1d8af19dc0"), Action = Guid.Parse("948ad738-434b-4a88-8e38-7569d332910a"), Object = "", AceType = 0 },
new Acl { Tenant = -1, Subject = Guid.Parse("abef62db-11a8-4673-9d32-ef1d8af19dc0"), Action = Guid.Parse("9d75a568-52aa-49d8-ad43-473756cd8903"), Object = "", AceType = 0 },
new Acl { Tenant = -1, Subject = Guid.Parse("c5cc67d1-c3e8-43c0-a3ad-3928ae3e5b5e"), Action = Guid.Parse("a362fe79-684e-4d43-a599-65bc1f4e167f"), Object = "", AceType = 0 },
new Acl { Tenant = -1, Subject = Guid.Parse("c5cc67d1-c3e8-43c0-a3ad-3928ae3e5b5e"), Action = Guid.Parse("c426c349-9ad4-47cd-9b8f-99fc30675951"), Object = "", AceType = 0 },
new Acl { Tenant = -1, Subject = Guid.Parse("c5cc67d1-c3e8-43c0-a3ad-3928ae3e5b5e"), Action = Guid.Parse("d11ebcb9-0e6e-45e6-a6d0-99c41d687598"), Object = "", AceType = 0 },
new Acl { Tenant = -1, Subject = Guid.Parse("c5cc67d1-c3e8-43c0-a3ad-3928ae3e5b5e"), Action = Guid.Parse("d1f3b53d-d9e2-4259-80e7-d24380978395"), Object = "", AceType = 0 },
new Acl { Tenant = -1, Subject = Guid.Parse("abef62db-11a8-4673-9d32-ef1d8af19dc0"), Action = Guid.Parse("d49f4e30-da10-4b39-bc6d-b41ef6e039d3"), Object = "", AceType = 0 },
new Acl { Tenant = -1, Subject = Guid.Parse("abef62db-11a8-4673-9d32-ef1d8af19dc0"), Action = Guid.Parse("d852b66f-6719-45e1-8657-18f0bb791690"), Object = "", AceType = 0 },
new Acl { Tenant = -1, Subject = Guid.Parse("c5cc67d1-c3e8-43c0-a3ad-3928ae3e5b5e"), Action = Guid.Parse("e0759a42-47f0-4763-a26a-d5aa665bec35"), Object = "", AceType = 0 },
new Acl { Tenant = -1, Subject = Guid.Parse("c5cc67d1-c3e8-43c0-a3ad-3928ae3e5b5e"), Action = Guid.Parse("e37239bd-c5b5-4f1e-a9f8-3ceeac209615"), Object = "", AceType = 0 },
new Acl { Tenant = -1, Subject = Guid.Parse("c5cc67d1-c3e8-43c0-a3ad-3928ae3e5b5e"), Action = Guid.Parse("fbc37705-a04c-40ad-a68c-ce2f0423f397"), Object = "", AceType = 0 },
new Acl { Tenant = -1, Subject = Guid.Parse("c5cc67d1-c3e8-43c0-a3ad-3928ae3e5b5e"), Action = Guid.Parse("fcac42b8-9386-48eb-a938-d19b3c576912"), Object = "", AceType = 0 },
new Acl { Tenant = -1, Subject = Guid.Parse("ba74ca02-873f-43dc-8470-8620c156bc67"), Action = Guid.Parse("13e30b51-5b4d-40a5-8575-cb561899eeb1"), Object = "", AceType = 0 },
new Acl { Tenant = -1, Subject = Guid.Parse("ba74ca02-873f-43dc-8470-8620c156bc67"), Action = Guid.Parse("49ae8915-2b30-4348-ab74-b152279364fb"), Object = "", AceType = 0 },
new Acl { Tenant = -1, Subject = Guid.Parse("ba74ca02-873f-43dc-8470-8620c156bc67"), Action = Guid.Parse("63e9f35f-6bb5-4fb1-afaa-e4c2f4dec9bd"), Object = "", AceType = 0 },
new Acl { Tenant = -1, Subject = Guid.Parse("ba74ca02-873f-43dc-8470-8620c156bc67"), Action = Guid.Parse("9018c001-24c2-44bf-a1db-d1121a570e74"), Object = "", AceType = 0 },
new Acl { Tenant = -1, Subject = Guid.Parse("ba74ca02-873f-43dc-8470-8620c156bc67"), Action = Guid.Parse("d1f3b53d-d9e2-4259-80e7-d24380978395"), Object = "", AceType = 0 },
new Acl { Tenant = -1, Subject = Guid.Parse("ba74ca02-873f-43dc-8470-8620c156bc67"), Action = Guid.Parse("e0759a42-47f0-4763-a26a-d5aa665bec35"), Object = "", AceType = 0 },
new Acl { Tenant = -1, Subject = Guid.Parse("ba74ca02-873f-43dc-8470-8620c156bc67"), Action = Guid.Parse("e37239bd-c5b5-4f1e-a9f8-3ceeac209615"), Object = "", AceType = 0 },
new Acl { Tenant = -1, Subject = Guid.Parse("ba74ca02-873f-43dc-8470-8620c156bc67"), Action = Guid.Parse("f11e88d7-f185-4372-927c-d88008d2c483"), Object = "", AceType = 0 },
new Acl { Tenant = -1, Subject = Guid.Parse("ba74ca02-873f-43dc-8470-8620c156bc67"), Action = Guid.Parse("f11e8f3f-46e6-4e55-90e3-09c22ec565bd"), Object = "", AceType = 0 },
new Acl { Tenant = -1, Subject = Guid.Parse("bba32183-a14d-48ed-9d39-c6b4d8925fbf"), Action = Guid.Parse("00e7dfc5-ac49-4fd3-a1d6-98d84e877ac4"), Object = "", AceType = 0 },
new Acl { Tenant = -1, Subject = Guid.Parse("bba32183-a14d-48ed-9d39-c6b4d8925fbf"), Action = Guid.Parse("14be970f-7af5-4590-8e81-ea32b5f7866d"), Object = "", AceType = 0 },
new Acl { Tenant = -1, Subject = Guid.Parse("bba32183-a14d-48ed-9d39-c6b4d8925fbf"), Action = Guid.Parse("18ecc94d-6afa-4994-8406-aee9dff12ce2"), Object = "", AceType = 0 },
new Acl { Tenant = -1, Subject = Guid.Parse("bba32183-a14d-48ed-9d39-c6b4d8925fbf"), Action = Guid.Parse("298530eb-435e-4dc6-a776-9abcd95c70e9"), Object = "", AceType = 0 },
new Acl { Tenant = -1, Subject = Guid.Parse("bba32183-a14d-48ed-9d39-c6b4d8925fbf"), Action = Guid.Parse("430eaf70-1886-483c-a746-1a18e3e6bb63"), Object = "", AceType = 0 },
new Acl { Tenant = -1, Subject = Guid.Parse("bba32183-a14d-48ed-9d39-c6b4d8925fbf"), Action = Guid.Parse("557d6503-633b-4490-a14c-6473147ce2b3"), Object = "", AceType = 0 }/*qwerty*/,
new Acl { Tenant = -1, Subject = Guid.Parse("bba32183-a14d-48ed-9d39-c6b4d8925fbf"), Action = Guid.Parse("724cbb75-d1c9-451e-bae0-4de0db96b1f7"), Object = "", AceType = 0 },
new Acl { Tenant = -1, Subject = Guid.Parse("bba32183-a14d-48ed-9d39-c6b4d8925fbf"), Action = Guid.Parse("7cb5c0d1-d254-433f-abe3-ff23373ec631"), Object = "", AceType = 0 },
new Acl { Tenant = -1, Subject = Guid.Parse("bba32183-a14d-48ed-9d39-c6b4d8925fbf"), Action = Guid.Parse("91b29dcd-9430-4403-b17a-27d09189be88"), Object = "", AceType = 0 },
new Acl { Tenant = -1, Subject = Guid.Parse("bba32183-a14d-48ed-9d39-c6b4d8925fbf"), Action = Guid.Parse("a18480a4-6d18-4c71-84fa-789888791f45"), Object = "", AceType = 0 },
new Acl { Tenant = -1, Subject = Guid.Parse("bba32183-a14d-48ed-9d39-c6b4d8925fbf"), Action = Guid.Parse("b630d29b-1844-4bda-bbbe-cf5542df3559"), Object = "", AceType = 0 },
new Acl { Tenant = -1, Subject = Guid.Parse("bba32183-a14d-48ed-9d39-c6b4d8925fbf"), Action = Guid.Parse("c62a9e8d-b24c-4513-90aa-7ff0f8ba38eb"), Object = "", AceType = 0 },
new Acl { Tenant = -1, Subject = Guid.Parse("bba32183-a14d-48ed-9d39-c6b4d8925fbf"), Action = Guid.Parse("d7cdb020-288b-41e5-a857-597347618533"), Object = "", AceType = 0 },
new Acl { Tenant = -1, Subject = Guid.Parse("bba32183-a14d-48ed-9d39-c6b4d8925fbf"), Action = Guid.Parse("662f3db7-9bc8-42cf-84da-2765f563e9b0"), Object = "", AceType = 0 },
new Acl { Tenant = -1, Subject = Guid.Parse("712d9ec3-5d2b-4b13-824f-71f00191dcca"), Action = Guid.Parse("e0759a42-47f0-4763-a26a-d5aa665bec35"), Object = "", AceType = 0 },
new Acl { Tenant = -1, Subject = Guid.Parse("bba32183-a14d-48ed-9d39-c6b4d8925fbf"), Action = Guid.Parse("0d68b142-e20a-446e-a832-0d6b0b65a164"), Object = "", AceType = 0 },
new Acl { Tenant = -1, Subject = Guid.Parse("c5cc67d1-c3e8-43c0-a3ad-3928ae3e5b5e"), Action = Guid.Parse("6f05c382-8bca-4469-9424-c807a98c40d7"), Object = "", AceType = 0 },
new Acl { Tenant = -1, Subject = Guid.Parse("c5cc67d1-c3e8-43c0-a3ad-3928ae3e5b5e"), Action = Guid.Parse("77777777-32ae-425f-99b5-83176061d1ae"), Object = "ASC.Web.Core.WebItemSecurity+WebItemSecurityObject|1e04460243b54d7982f3fd6208a11960", AceType = 0 },
new Acl { Tenant = -1, Subject = Guid.Parse("c5cc67d1-c3e8-43c0-a3ad-3928ae3e5b5e"), Action = Guid.Parse("77777777-32ae-425f-99b5-83176061d1ae"), Object = "ASC.Web.Core.WebItemSecurity+WebItemSecurityObject|6743007c6f954d208c88a8601ce5e76d", AceType = 0 },
new Acl { Tenant = -1, Subject = Guid.Parse("c5cc67d1-c3e8-43c0-a3ad-3928ae3e5b5e"), Action = Guid.Parse("77777777-32ae-425f-99b5-83176061d1ae"), Object = "ASC.Web.Core.WebItemSecurity+WebItemSecurityObject|e67be73df9ae4ce18fec1880cb518cb4", AceType = 0 },
new Acl { Tenant = -1, Subject = Guid.Parse("c5cc67d1-c3e8-43c0-a3ad-3928ae3e5b5e"), Action = Guid.Parse("77777777-32ae-425f-99b5-83176061d1ae"), Object = "ASC.Web.Core.WebItemSecurity+WebItemSecurityObject|ea942538e68e49079394035336ee0ba8", AceType = 0 },
new Acl { Tenant = -1, Subject = Guid.Parse("c5cc67d1-c3e8-43c0-a3ad-3928ae3e5b5e"), Action = Guid.Parse("77777777-32ae-425f-99b5-83176061d1ae"), Object = "ASC.Web.Core.WebItemSecurity+WebItemSecurityObject|32d24cb57ece46069c9419216ba42086", AceType = 0 },
new Acl { Tenant = -1, Subject = Guid.Parse("c5cc67d1-c3e8-43c0-a3ad-3928ae3e5b5e"), Action = Guid.Parse("77777777-32ae-425f-99b5-83176061d1ae"), Object = "ASC.Web.Core.WebItemSecurity+WebItemSecurityObject|bf88953e3c434850a3fbb1e43ad53a3e", AceType = 0 },
new Acl { Tenant = -1, Subject = Guid.Parse("c5cc67d1-c3e8-43c0-a3ad-3928ae3e5b5e"), Action = Guid.Parse("77777777-32ae-425f-99b5-83176061d1ae"), Object = "ASC.Web.Core.WebItemSecurity+WebItemSecurityObject|2a9230378b2d487b9a225ac0918acf3f", AceType = 0 },
new Acl { Tenant = -1, Subject = Guid.Parse("c5cc67d1-c3e8-43c0-a3ad-3928ae3e5b5e"), Action = Guid.Parse("77777777-32ae-425f-99b5-83176061d1ae"), Object = "ASC.Web.Core.WebItemSecurity+WebItemSecurityObject|f4d98afdd336433287783c6945c81ea0", AceType = 0 },
new Acl { Tenant = -1, Subject = Guid.Parse("c5cc67d1-c3e8-43c0-a3ad-3928ae3e5b5e"), Action = Guid.Parse("77777777-32ae-425f-99b5-83176061d1ae"), Object = "ASC.Web.Core.WebItemSecurity+WebItemSecurityObject|28b10049dd204f54b986873bc14ccfc7", AceType = 0 },
new Acl { Tenant = -1, Subject = Guid.Parse("c5cc67d1-c3e8-43c0-a3ad-3928ae3e5b5e"), Action = Guid.Parse("77777777-32ae-425f-99b5-83176061d1ae"), Object = "ASC.Web.Core.WebItemSecurity+WebItemSecurityObject|3cfd481b46f24a4ab55cb8c0c9def02c", AceType = 0 },
new Acl { Tenant = -1, Subject = Guid.Parse("c5cc67d1-c3e8-43c0-a3ad-3928ae3e5b5e"), Action = Guid.Parse("77777777-32ae-425f-99b5-83176061d1ae"), Object = "ASC.Web.Core.WebItemSecurity+WebItemSecurityObject|6a598c7491ae437da5f4ad339bd11bb2", AceType = 0 },
new Acl { Tenant = -1, Subject = Guid.Parse("c5cc67d1-c3e8-43c0-a3ad-3928ae3e5b5e"), Action = Guid.Parse("77777777-32ae-425f-99b5-83176061d1ae"), Object = "ASC.Web.Core.WebItemSecurity+WebItemSecurityObject|742cf945cbbc4a5782d61600a12cf8ca", AceType = 0 },
new Acl { Tenant = -1, Subject = Guid.Parse("c5cc67d1-c3e8-43c0-a3ad-3928ae3e5b5e"), Action = Guid.Parse("77777777-32ae-425f-99b5-83176061d1ae"), Object = "ASC.Web.Core.WebItemSecurity+WebItemSecurityObject|853b6eb973ee438d9b098ffeedf36234", AceType = 0 },
new Acl { Tenant = -1, Subject = Guid.Parse("c5cc67d1-c3e8-43c0-a3ad-3928ae3e5b5e"), Action = Guid.Parse("77777777-32ae-425f-99b5-83176061d1ae"), Object = "ASC.Web.Core.WebItemSecurity+WebItemSecurityObject|46cfa73af32046cf8d5bcd82e1d67f26", AceType = 0 }
);
return modelBuilder;
}
public static void MySqlAddAcl(this ModelBuilder modelBuilder)
{
modelBuilder.Entity<Acl>(entity =>
{
entity.HasKey(e => new { e.Tenant, e.Subject, e.Action, e.Object })
.HasName("PRIMARY");
entity.ToTable("core_acl");
entity.Property(e => e.Tenant).HasColumnName("tenant");
entity.Property(e => e.Subject)
.HasColumnName("subject")
.HasColumnType("varchar(38)")
.HasCharSet("utf8")
.UseCollation("utf8_general_ci");
entity.Property(e => e.Action)
.HasColumnName("action")
.HasColumnType("varchar(38)")
.HasCharSet("utf8")
.UseCollation("utf8_general_ci");
entity.Property(e => e.Object)
.HasColumnName("object")
.HasColumnType("varchar(255)")
.HasDefaultValueSql("''")
.HasCharSet("utf8")
.UseCollation("utf8_general_ci");
entity.Property(e => e.AceType).HasColumnName("acetype");
});
}
public static void PgSqlAddAcl(this ModelBuilder modelBuilder)
{
modelBuilder.Entity<Acl>(entity =>
{
entity.HasKey(e => new { e.Tenant, e.Subject, e.Action, e.Object })
.HasName("core_acl_pkey");
entity.ToTable("core_acl", "onlyoffice");
entity.Property(e => e.Tenant).HasColumnName("tenant");
entity.Property(e => e.Subject)
.HasColumnName("subject")
.HasMaxLength(38);
entity.Property(e => e.Action)
.HasColumnName("action")
.HasMaxLength(38);
entity.Property(e => e.Object)
.HasColumnName("object")
.HasMaxLength(255)
.HasDefaultValueSql("''");
entity.Property(e => e.AceType).HasColumnName("acetype");
});
}
}

View File

@ -1,86 +1,85 @@
namespace ASC.Core.Common.EF.Model
namespace ASC.Core.Common.EF.Model;
public class DbCoreSettings : BaseEntity
{
public class DbCoreSettings : BaseEntity
public int Tenant { get; set; }
public string Id { get; set; }
public byte[] Value { get; set; }
public DateTime LastModified { get; set; }
public override object[] GetKeys()
{
public int Tenant { get; set; }
public string Id { get; set; }
public byte[] Value { get; set; }
public DateTime LastModified { get; set; }
public override object[] GetKeys()
{
return new object[] { Tenant, Id };
}
}
public static class CoreSettingsExtension
{
public static ModelBuilderWrapper AddCoreSettings(this ModelBuilderWrapper modelBuilder)
{
modelBuilder
.Add(MySqlAddCoreSettings, Provider.MySql)
.Add(PgSqlAddCoreSettings, Provider.PostgreSql)
.HasData(
new DbCoreSettings { Tenant = -1, Id = "CompanyWhiteLabelSettings", Value = new byte[] { 245, 71, 4, 138, 72, 101, 23, 21, 135, 217, 206, 188, 138, 73, 108, 96, 29, 150, 3, 31, 44, 28, 62, 145, 96, 53, 57, 66, 238, 118, 93, 172, 211, 22, 244, 181, 244, 40, 146, 67, 111, 196, 162, 27, 154, 109, 248, 255, 211, 188, 64, 54, 180, 126, 58, 90, 27, 76, 136, 27, 38, 96, 152, 105, 254, 187, 104, 72, 189, 136, 192, 46, 234, 198, 164, 204, 179, 232, 244, 4, 41, 8, 18, 240, 230, 225, 36, 165, 82, 190, 129, 165, 140, 100, 187, 139, 211, 201, 168, 192, 237, 225, 249, 66, 18, 129, 222, 12, 122, 248, 39, 51, 164, 188, 229, 21, 232, 86, 148, 196, 221, 167, 142, 34, 101, 43, 162, 137, 31, 206, 149, 120, 249, 114, 133, 168, 30, 18, 254, 223, 93, 101, 88, 97, 30, 58, 163, 224, 62, 173, 220, 170, 152, 40, 124, 100, 165, 81, 7, 87, 168, 129, 176, 12, 51, 69, 230, 252, 30, 34, 182, 7, 202, 45, 117, 60, 99, 241, 237, 148, 201, 35, 102, 219, 160, 228, 194, 230, 219, 22, 244, 74, 138, 176, 145, 0, 122, 167, 80, 93, 23, 228, 21, 48, 100, 60, 31, 250, 232, 34, 248, 249, 159, 210, 227, 12, 13, 239, 130, 223, 101, 196, 51, 36, 80, 127, 62, 92, 104, 228, 197, 226, 43, 232, 164, 12, 36, 66, 52, 133 } , LastModified = DateTime.UtcNow },
new DbCoreSettings { Tenant = -1, Id = "FullTextSearchSettings", Value = new byte[] { 8, 120, 207, 5, 153, 181, 23, 202, 162, 211, 218, 237, 157, 6, 76, 62, 220, 238, 175, 67, 31, 53, 166, 246, 66, 220, 173, 160, 72, 23, 227, 81, 50, 39, 187, 177, 222, 110, 43, 171, 235, 158, 16, 119, 178, 207, 49, 140, 72, 152, 20, 84, 94, 135, 117, 1, 246, 51, 251, 190, 148, 2, 44, 252, 221, 2, 91, 83, 149, 151, 58, 245, 16, 148, 52, 8, 187, 86, 150, 46, 227, 93, 163, 95, 47, 131, 116, 207, 95, 209, 38, 149, 53, 148, 73, 215, 206, 251, 194, 199, 189, 17, 42, 229, 135, 82, 23, 154, 162, 165, 158, 94, 23, 128, 30, 88, 12, 204, 96, 250, 236, 142, 189, 211, 214, 18, 196, 136, 102, 102, 217, 109, 108, 240, 96, 96, 94, 100, 201, 10, 31, 170, 128, 192 }, LastModified = DateTime.UtcNow },
new DbCoreSettings { Tenant = -1, Id = "SmtpSettings", Value = new byte[] { 240, 82, 224, 144, 161, 163, 117, 13, 173, 205, 78, 153, 97, 218, 4, 170, 81, 239, 1, 151, 226, 192, 98, 60, 241, 44, 88, 56, 191, 164, 10, 155, 72, 186, 239, 203, 227, 113, 88, 119, 49, 215, 227, 220, 158, 124, 96, 9, 116, 47, 158, 65, 93, 86, 219, 15, 10, 224, 142, 50, 248, 144, 75, 44, 68, 28, 198, 87, 198, 69, 67, 234, 238, 38, 32, 68, 162, 139, 67, 53, 220, 176, 240, 196, 233, 64, 29, 137, 31, 160, 99, 105, 249, 132, 202, 45, 71, 92, 134, 194, 55, 145, 121, 97, 197, 130, 119, 105, 131, 21, 133, 35, 10, 102, 172, 119, 135, 230, 251, 86, 253, 62, 55, 56, 146, 103, 164, 106 }, LastModified = DateTime.UtcNow }
);
return modelBuilder;
}
public static void MySqlAddCoreSettings(this ModelBuilder modelBuilder)
{
modelBuilder.Entity<DbCoreSettings>(entity =>
{
entity.HasKey(e => new { e.Tenant, e.Id })
.HasName("PRIMARY");
entity.ToTable("core_settings");
entity.Property(e => e.Tenant).HasColumnName("tenant");
entity.Property(e => e.Id)
.HasColumnName("id")
.HasColumnType("varchar(128)")
.HasCharSet("utf8")
.UseCollation("utf8_general_ci");
entity.Property(e => e.LastModified)
.HasColumnName("last_modified")
.HasColumnType("timestamp")
.HasDefaultValueSql("CURRENT_TIMESTAMP")
.ValueGeneratedOnAddOrUpdate();
entity.Property(e => e.Value)
.IsRequired()
.HasColumnName("value")
.HasColumnType("mediumblob");
});
}
public static void PgSqlAddCoreSettings(this ModelBuilder modelBuilder)
{
modelBuilder.Entity<DbCoreSettings>(entity =>
{
entity.HasKey(e => new { e.Tenant, e.Id })
.HasName("core_settings_pkey");
entity.ToTable("core_settings", "onlyoffice");
entity.Property(e => e.Tenant).HasColumnName("tenant");
entity.Property(e => e.Id)
.HasColumnName("id")
.HasMaxLength(128);
entity.Property(e => e.LastModified)
.HasColumnName("last_modified")
.HasDefaultValueSql("CURRENT_TIMESTAMP");
entity.Property(e => e.Value)
.IsRequired()
.HasColumnName("value");
});
}
return new object[] { Tenant, Id };
}
}
public static class CoreSettingsExtension
{
public static ModelBuilderWrapper AddCoreSettings(this ModelBuilderWrapper modelBuilder)
{
modelBuilder
.Add(MySqlAddCoreSettings, Provider.MySql)
.Add(PgSqlAddCoreSettings, Provider.PostgreSql)
.HasData(
new DbCoreSettings { Tenant = -1, Id = "CompanyWhiteLabelSettings", Value = new byte[] { 245, 71, 4, 138, 72, 101, 23, 21, 135, 217, 206, 188, 138, 73, 108, 96, 29, 150, 3, 31, 44, 28, 62, 145, 96, 53, 57, 66, 238, 118, 93, 172, 211, 22, 244, 181, 244, 40, 146, 67, 111, 196, 162, 27, 154, 109, 248, 255, 211, 188, 64, 54, 180, 126, 58, 90, 27, 76, 136, 27, 38, 96, 152, 105, 254, 187, 104, 72, 189, 136, 192, 46, 234, 198, 164, 204, 179, 232, 244, 4, 41, 8, 18, 240, 230, 225, 36, 165, 82, 190, 129, 165, 140, 100, 187, 139, 211, 201, 168, 192, 237, 225, 249, 66, 18, 129, 222, 12, 122, 248, 39, 51, 164, 188, 229, 21, 232, 86, 148, 196, 221, 167, 142, 34, 101, 43, 162, 137, 31, 206, 149, 120, 249, 114, 133, 168, 30, 18, 254, 223, 93, 101, 88, 97, 30, 58, 163, 224, 62, 173, 220, 170, 152, 40, 124, 100, 165, 81, 7, 87, 168, 129, 176, 12, 51, 69, 230, 252, 30, 34, 182, 7, 202, 45, 117, 60, 99, 241, 237, 148, 201, 35, 102, 219, 160, 228, 194, 230, 219, 22, 244, 74, 138, 176, 145, 0, 122, 167, 80, 93, 23, 228, 21, 48, 100, 60, 31, 250, 232, 34, 248, 249, 159, 210, 227, 12, 13, 239, 130, 223, 101, 196, 51, 36, 80, 127, 62, 92, 104, 228, 197, 226, 43, 232, 164, 12, 36, 66, 52, 133 }, LastModified = DateTime.UtcNow },
new DbCoreSettings { Tenant = -1, Id = "FullTextSearchSettings", Value = new byte[] { 8, 120, 207, 5, 153, 181, 23, 202, 162, 211, 218, 237, 157, 6, 76, 62, 220, 238, 175, 67, 31, 53, 166, 246, 66, 220, 173, 160, 72, 23, 227, 81, 50, 39, 187, 177, 222, 110, 43, 171, 235, 158, 16, 119, 178, 207, 49, 140, 72, 152, 20, 84, 94, 135, 117, 1, 246, 51, 251, 190, 148, 2, 44, 252, 221, 2, 91, 83, 149, 151, 58, 245, 16, 148, 52, 8, 187, 86, 150, 46, 227, 93, 163, 95, 47, 131, 116, 207, 95, 209, 38, 149, 53, 148, 73, 215, 206, 251, 194, 199, 189, 17, 42, 229, 135, 82, 23, 154, 162, 165, 158, 94, 23, 128, 30, 88, 12, 204, 96, 250, 236, 142, 189, 211, 214, 18, 196, 136, 102, 102, 217, 109, 108, 240, 96, 96, 94, 100, 201, 10, 31, 170, 128, 192 }, LastModified = DateTime.UtcNow },
new DbCoreSettings { Tenant = -1, Id = "SmtpSettings", Value = new byte[] { 240, 82, 224, 144, 161, 163, 117, 13, 173, 205, 78, 153, 97, 218, 4, 170, 81, 239, 1, 151, 226, 192, 98, 60, 241, 44, 88, 56, 191, 164, 10, 155, 72, 186, 239, 203, 227, 113, 88, 119, 49, 215, 227, 220, 158, 124, 96, 9, 116, 47, 158, 65, 93, 86, 219, 15, 10, 224, 142, 50, 248, 144, 75, 44, 68, 28, 198, 87, 198, 69, 67, 234, 238, 38, 32, 68, 162, 139, 67, 53, 220, 176, 240, 196, 233, 64, 29, 137, 31, 160, 99, 105, 249, 132, 202, 45, 71, 92, 134, 194, 55, 145, 121, 97, 197, 130, 119, 105, 131, 21, 133, 35, 10, 102, 172, 119, 135, 230, 251, 86, 253, 62, 55, 56, 146, 103, 164, 106 }, LastModified = DateTime.UtcNow }
);
return modelBuilder;
}
public static void MySqlAddCoreSettings(this ModelBuilder modelBuilder)
{
modelBuilder.Entity<DbCoreSettings>(entity =>
{
entity.HasKey(e => new { e.Tenant, e.Id })
.HasName("PRIMARY");
entity.ToTable("core_settings");
entity.Property(e => e.Tenant).HasColumnName("tenant");
entity.Property(e => e.Id)
.HasColumnName("id")
.HasColumnType("varchar(128)")
.HasCharSet("utf8")
.UseCollation("utf8_general_ci");
entity.Property(e => e.LastModified)
.HasColumnName("last_modified")
.HasColumnType("timestamp")
.HasDefaultValueSql("CURRENT_TIMESTAMP")
.ValueGeneratedOnAddOrUpdate();
entity.Property(e => e.Value)
.IsRequired()
.HasColumnName("value")
.HasColumnType("mediumblob");
});
}
public static void PgSqlAddCoreSettings(this ModelBuilder modelBuilder)
{
modelBuilder.Entity<DbCoreSettings>(entity =>
{
entity.HasKey(e => new { e.Tenant, e.Id })
.HasName("core_settings_pkey");
entity.ToTable("core_settings", "onlyoffice");
entity.Property(e => e.Tenant).HasColumnName("tenant");
entity.Property(e => e.Id)
.HasColumnName("id")
.HasMaxLength(128);
entity.Property(e => e.LastModified)
.HasColumnName("last_modified")
.HasDefaultValueSql("CURRENT_TIMESTAMP");
entity.Property(e => e.Value)
.IsRequired()
.HasColumnName("value");
});
}
}

View File

@ -1,129 +1,128 @@
namespace ASC.Core.Common.EF
namespace ASC.Core.Common.EF;
public class DbSubscriptionMethod : BaseEntity
{
public class DbSubscriptionMethod : BaseEntity
public int Tenant { get; set; }
public string Source { get; set; }
public string Action { get; set; }
public string Recipient { get; set; }
public string Sender { get; set; }
public override object[] GetKeys()
{
public int Tenant { get; set; }
public string Source { get; set; }
public string Action { get; set; }
public string Recipient { get; set; }
public string Sender { get; set; }
public override object[] GetKeys()
{
return new object[] { Tenant, Source, Action, Recipient };
}
}
public static class SubscriptionMethodExtension
{
public static ModelBuilderWrapper AddSubscriptionMethod(this ModelBuilderWrapper modelBuilder)
{
modelBuilder
.Add(MySqlAddSubscriptionMethod, Provider.MySql)
.Add(PgSqlAddSubscriptionMethod, Provider.PostgreSql)
.HasData(
new DbSubscriptionMethod { Source = "asc.web.studio", Action = "send_whats_new", Recipient = "c5cc67d1-c3e8-43c0-a3ad-3928ae3e5b5e", Sender = "email.sender", Tenant = -1 },
new DbSubscriptionMethod { Source = "6504977c-75af-4691-9099-084d3ddeea04", Action = "new feed", Recipient = "c5cc67d1-c3e8-43c0-a3ad-3928ae3e5b5e", Sender = "email.sender|messanger.sender", Tenant = -1 },
new DbSubscriptionMethod { Source = "6a598c74-91ae-437d-a5f4-ad339bd11bb2", Action = "new post", Recipient = "c5cc67d1-c3e8-43c0-a3ad-3928ae3e5b5e", Sender = "email.sender|messanger.sender", Tenant = -1 },
new DbSubscriptionMethod { Source = "853b6eb9-73ee-438d-9b09-8ffeedf36234", Action = "new topic in forum", Recipient = "c5cc67d1-c3e8-43c0-a3ad-3928ae3e5b5e", Sender = "email.sender|messanger.sender", Tenant = -1 },
new DbSubscriptionMethod { Source = "9d51954f-db9b-4aed-94e3-ed70b914e101", Action = "new photo uploaded", Recipient = "c5cc67d1-c3e8-43c0-a3ad-3928ae3e5b5e", Sender = "email.sender|messanger.sender", Tenant = -1 },
new DbSubscriptionMethod { Source = "28b10049-dd20-4f54-b986-873bc14ccfc7", Action = "new bookmark created", Recipient = "c5cc67d1-c3e8-43c0-a3ad-3928ae3e5b5e", Sender = "email.sender|messanger.sender", Tenant = -1 },
new DbSubscriptionMethod { Source = "742cf945-cbbc-4a57-82d6-1600a12cf8ca", Action = "new wiki page", Recipient = "c5cc67d1-c3e8-43c0-a3ad-3928ae3e5b5e", Sender = "email.sender|messanger.sender", Tenant = -1 },
new DbSubscriptionMethod { Source = "37620ae5-c40b-45ce-855a-39dd7d76a1fa", Action = "BirthdayReminder", Recipient = "abef62db-11a8-4673-9d32-ef1d8af19dc0", Sender = "email.sender|messanger.sender", Tenant = -1 },
new DbSubscriptionMethod { Source = "6fe286a4-479e-4c25-a8d9-0156e332b0c0", Action = "sharedocument", Recipient = "c5cc67d1-c3e8-43c0-a3ad-3928ae3e5b5e", Sender = "email.sender|messanger.sender", Tenant = -1 },
new DbSubscriptionMethod { Source = "6fe286a4-479e-4c25-a8d9-0156e332b0c0", Action = "sharefolder", Recipient = "c5cc67d1-c3e8-43c0-a3ad-3928ae3e5b5e", Sender = "email.sender|messanger.sender", Tenant = -1 },
new DbSubscriptionMethod { Source = "6fe286a4-479e-4c25-a8d9-0156e332b0c0", Action = "updatedocument", Recipient = "c5cc67d1-c3e8-43c0-a3ad-3928ae3e5b5e", Sender = "email.sender|messanger.sender", Tenant = -1 },
new DbSubscriptionMethod { Source = "6045b68c-2c2e-42db-9e53-c272e814c4ad", Action = "invitetoproject", Recipient = "c5cc67d1-c3e8-43c0-a3ad-3928ae3e5b5e", Sender = "email.sender|messanger.sender", Tenant = -1 },
new DbSubscriptionMethod { Source = "6045b68c-2c2e-42db-9e53-c272e814c4ad", Action = "milestonedeadline", Recipient = "c5cc67d1-c3e8-43c0-a3ad-3928ae3e5b5e", Sender = "email.sender|messanger.sender", Tenant = -1 },
new DbSubscriptionMethod { Source = "6045b68c-2c2e-42db-9e53-c272e814c4ad", Action = "newcommentformessage", Recipient = "c5cc67d1-c3e8-43c0-a3ad-3928ae3e5b5e", Sender = "email.sender|messanger.sender", Tenant = -1 },
new DbSubscriptionMethod { Source = "6045b68c-2c2e-42db-9e53-c272e814c4ad", Action = "newcommentformilestone", Recipient = "c5cc67d1-c3e8-43c0-a3ad-3928ae3e5b5e", Sender = "email.sender|messanger.sender", Tenant = -1 },
new DbSubscriptionMethod { Source = "6045b68c-2c2e-42db-9e53-c272e814c4ad", Action = "newcommentfortask", Recipient = "c5cc67d1-c3e8-43c0-a3ad-3928ae3e5b5e", Sender = "email.sender|messanger.sender", Tenant = -1 },
new DbSubscriptionMethod { Source = "6045b68c-2c2e-42db-9e53-c272e814c4ad", Action = "projectcreaterequest", Recipient = "c5cc67d1-c3e8-43c0-a3ad-3928ae3e5b5e", Sender = "email.sender|messanger.sender", Tenant = -1 },
new DbSubscriptionMethod { Source = "6045b68c-2c2e-42db-9e53-c272e814c4ad", Action = "projecteditrequest", Recipient = "c5cc67d1-c3e8-43c0-a3ad-3928ae3e5b5e", Sender = "email.sender|messanger.sender", Tenant = -1 },
new DbSubscriptionMethod { Source = "6045b68c-2c2e-42db-9e53-c272e814c4ad", Action = "removefromproject", Recipient = "c5cc67d1-c3e8-43c0-a3ad-3928ae3e5b5e", Sender = "email.sender|messanger.sender", Tenant = -1 },
new DbSubscriptionMethod { Source = "6045b68c-2c2e-42db-9e53-c272e814c4ad", Action = "responsibleforproject", Recipient = "c5cc67d1-c3e8-43c0-a3ad-3928ae3e5b5e", Sender = "email.sender|messanger.sender", Tenant = -1 },
new DbSubscriptionMethod { Source = "6045b68c-2c2e-42db-9e53-c272e814c4ad", Action = "responsiblefortask", Recipient = "c5cc67d1-c3e8-43c0-a3ad-3928ae3e5b5e", Sender = "email.sender|messanger.sender", Tenant = -1 },
new DbSubscriptionMethod { Source = "6045b68c-2c2e-42db-9e53-c272e814c4ad", Action = "taskclosed", Recipient = "c5cc67d1-c3e8-43c0-a3ad-3928ae3e5b5e", Sender = "email.sender|messanger.sender", Tenant = -1 },
new DbSubscriptionMethod { Source = "40650da3-f7c1-424c-8c89-b9c115472e08", Action = "calendar_sharing", Recipient = "c5cc67d1-c3e8-43c0-a3ad-3928ae3e5b5e", Sender = "email.sender|messanger.sender", Tenant = -1 },
new DbSubscriptionMethod { Source = "40650da3-f7c1-424c-8c89-b9c115472e08", Action = "event_alert", Recipient = "c5cc67d1-c3e8-43c0-a3ad-3928ae3e5b5e", Sender = "email.sender|messanger.sender", Tenant = -1 },
new DbSubscriptionMethod { Source = "asc.web.studio", Action = "admin_notify", Recipient = "cd84e66b-b803-40fc-99f9-b2969a54a1de", Sender = "email.sender", Tenant = -1 },
new DbSubscriptionMethod { Source = "13ff36fb-0272-4887-b416-74f52b0d0b02", Action = "SetAccess", Recipient = "abef62db-11a8-4673-9d32-ef1d8af19dc0", Sender = "email.sender|messanger.sender", Tenant = -1 },
new DbSubscriptionMethod { Source = "13ff36fb-0272-4887-b416-74f52b0d0b02", Action = "ResponsibleForTask", Recipient = "abef62db-11a8-4673-9d32-ef1d8af19dc0", Sender = "email.sender|messanger.sender", Tenant = -1 },
new DbSubscriptionMethod { Source = "13ff36fb-0272-4887-b416-74f52b0d0b02", Action = "AddRelationshipEvent", Recipient = "abef62db-11a8-4673-9d32-ef1d8af19dc0", Sender = "email.sender|messanger.sender", Tenant = -1 },
new DbSubscriptionMethod { Source = "13ff36fb-0272-4887-b416-74f52b0d0b02", Action = "ExportCompleted", Recipient = "abef62db-11a8-4673-9d32-ef1d8af19dc0", Sender = "email.sender|messanger.sender", Tenant = -1 },
new DbSubscriptionMethod { Source = "13ff36fb-0272-4887-b416-74f52b0d0b02", Action = "CreateNewContact", Recipient = "abef62db-11a8-4673-9d32-ef1d8af19dc0", Sender = "email.sender", Tenant = -1 },
new DbSubscriptionMethod { Source = "13ff36fb-0272-4887-b416-74f52b0d0b02", Action = "ResponsibleForOpportunity", Recipient = "abef62db-11a8-4673-9d32-ef1d8af19dc0", Sender = "email.sender|messanger.sender", Tenant = -1 },
new DbSubscriptionMethod { Source = "asc.web.studio", Action = "periodic_notify", Recipient = "c5cc67d1-c3e8-43c0-a3ad-3928ae3e5b5e", Sender = "email.sender", Tenant = -1 }
);
return modelBuilder;
}
public static void MySqlAddSubscriptionMethod(this ModelBuilder modelBuilder)
{
modelBuilder.Entity<DbSubscriptionMethod>(entity =>
{
entity.HasKey(e => new { e.Tenant, e.Source, e.Action, e.Recipient })
.HasName("PRIMARY");
entity.ToTable("core_subscriptionmethod");
entity.Property(e => e.Tenant).HasColumnName("tenant");
entity.Property(e => e.Source)
.HasColumnName("source")
.HasColumnType("varchar(38)")
.HasCharSet("utf8")
.UseCollation("utf8_general_ci");
entity.Property(e => e.Action)
.HasColumnName("action")
.HasColumnType("varchar(128)")
.HasCharSet("utf8")
.UseCollation("utf8_general_ci");
entity.Property(e => e.Recipient)
.HasColumnName("recipient")
.HasColumnType("varchar(38)")
.HasCharSet("utf8")
.UseCollation("utf8_general_ci");
entity.Property(e => e.Sender)
.IsRequired()
.HasColumnName("sender")
.HasColumnType("varchar(1024)")
.HasCharSet("utf8")
.UseCollation("utf8_general_ci");
});
}
public static void PgSqlAddSubscriptionMethod(this ModelBuilder modelBuilder)
{
modelBuilder.Entity<DbSubscriptionMethod>(entity =>
{
entity.HasKey(e => new { e.Tenant, e.Source, e.Action, e.Recipient })
.HasName("core_subscriptionmethod_pkey");
entity.ToTable("core_subscriptionmethod", "onlyoffice");
entity.Property(e => e.Tenant).HasColumnName("tenant");
entity.Property(e => e.Source)
.HasColumnName("source")
.HasMaxLength(38);
entity.Property(e => e.Action)
.HasColumnName("action")
.HasMaxLength(128);
entity.Property(e => e.Recipient)
.HasColumnName("recipient")
.HasMaxLength(38);
entity.Property(e => e.Sender)
.IsRequired()
.HasColumnName("sender")
.HasMaxLength(1024);
});
}
return new object[] { Tenant, Source, Action, Recipient };
}
}
public static class SubscriptionMethodExtension
{
public static ModelBuilderWrapper AddSubscriptionMethod(this ModelBuilderWrapper modelBuilder)
{
modelBuilder
.Add(MySqlAddSubscriptionMethod, Provider.MySql)
.Add(PgSqlAddSubscriptionMethod, Provider.PostgreSql)
.HasData(
new DbSubscriptionMethod { Source = "asc.web.studio", Action = "send_whats_new", Recipient = "c5cc67d1-c3e8-43c0-a3ad-3928ae3e5b5e", Sender = "email.sender", Tenant = -1 },
new DbSubscriptionMethod { Source = "6504977c-75af-4691-9099-084d3ddeea04", Action = "new feed", Recipient = "c5cc67d1-c3e8-43c0-a3ad-3928ae3e5b5e", Sender = "email.sender|messanger.sender", Tenant = -1 },
new DbSubscriptionMethod { Source = "6a598c74-91ae-437d-a5f4-ad339bd11bb2", Action = "new post", Recipient = "c5cc67d1-c3e8-43c0-a3ad-3928ae3e5b5e", Sender = "email.sender|messanger.sender", Tenant = -1 },
new DbSubscriptionMethod { Source = "853b6eb9-73ee-438d-9b09-8ffeedf36234", Action = "new topic in forum", Recipient = "c5cc67d1-c3e8-43c0-a3ad-3928ae3e5b5e", Sender = "email.sender|messanger.sender", Tenant = -1 },
new DbSubscriptionMethod { Source = "9d51954f-db9b-4aed-94e3-ed70b914e101", Action = "new photo uploaded", Recipient = "c5cc67d1-c3e8-43c0-a3ad-3928ae3e5b5e", Sender = "email.sender|messanger.sender", Tenant = -1 },
new DbSubscriptionMethod { Source = "28b10049-dd20-4f54-b986-873bc14ccfc7", Action = "new bookmark created", Recipient = "c5cc67d1-c3e8-43c0-a3ad-3928ae3e5b5e", Sender = "email.sender|messanger.sender", Tenant = -1 },
new DbSubscriptionMethod { Source = "742cf945-cbbc-4a57-82d6-1600a12cf8ca", Action = "new wiki page", Recipient = "c5cc67d1-c3e8-43c0-a3ad-3928ae3e5b5e", Sender = "email.sender|messanger.sender", Tenant = -1 },
new DbSubscriptionMethod { Source = "37620ae5-c40b-45ce-855a-39dd7d76a1fa", Action = "BirthdayReminder", Recipient = "abef62db-11a8-4673-9d32-ef1d8af19dc0", Sender = "email.sender|messanger.sender", Tenant = -1 },
new DbSubscriptionMethod { Source = "6fe286a4-479e-4c25-a8d9-0156e332b0c0", Action = "sharedocument", Recipient = "c5cc67d1-c3e8-43c0-a3ad-3928ae3e5b5e", Sender = "email.sender|messanger.sender", Tenant = -1 },
new DbSubscriptionMethod { Source = "6fe286a4-479e-4c25-a8d9-0156e332b0c0", Action = "sharefolder", Recipient = "c5cc67d1-c3e8-43c0-a3ad-3928ae3e5b5e", Sender = "email.sender|messanger.sender", Tenant = -1 },
new DbSubscriptionMethod { Source = "6fe286a4-479e-4c25-a8d9-0156e332b0c0", Action = "updatedocument", Recipient = "c5cc67d1-c3e8-43c0-a3ad-3928ae3e5b5e", Sender = "email.sender|messanger.sender", Tenant = -1 },
new DbSubscriptionMethod { Source = "6045b68c-2c2e-42db-9e53-c272e814c4ad", Action = "invitetoproject", Recipient = "c5cc67d1-c3e8-43c0-a3ad-3928ae3e5b5e", Sender = "email.sender|messanger.sender", Tenant = -1 },
new DbSubscriptionMethod { Source = "6045b68c-2c2e-42db-9e53-c272e814c4ad", Action = "milestonedeadline", Recipient = "c5cc67d1-c3e8-43c0-a3ad-3928ae3e5b5e", Sender = "email.sender|messanger.sender", Tenant = -1 },
new DbSubscriptionMethod { Source = "6045b68c-2c2e-42db-9e53-c272e814c4ad", Action = "newcommentformessage", Recipient = "c5cc67d1-c3e8-43c0-a3ad-3928ae3e5b5e", Sender = "email.sender|messanger.sender", Tenant = -1 },
new DbSubscriptionMethod { Source = "6045b68c-2c2e-42db-9e53-c272e814c4ad", Action = "newcommentformilestone", Recipient = "c5cc67d1-c3e8-43c0-a3ad-3928ae3e5b5e", Sender = "email.sender|messanger.sender", Tenant = -1 },
new DbSubscriptionMethod { Source = "6045b68c-2c2e-42db-9e53-c272e814c4ad", Action = "newcommentfortask", Recipient = "c5cc67d1-c3e8-43c0-a3ad-3928ae3e5b5e", Sender = "email.sender|messanger.sender", Tenant = -1 },
new DbSubscriptionMethod { Source = "6045b68c-2c2e-42db-9e53-c272e814c4ad", Action = "projectcreaterequest", Recipient = "c5cc67d1-c3e8-43c0-a3ad-3928ae3e5b5e", Sender = "email.sender|messanger.sender", Tenant = -1 },
new DbSubscriptionMethod { Source = "6045b68c-2c2e-42db-9e53-c272e814c4ad", Action = "projecteditrequest", Recipient = "c5cc67d1-c3e8-43c0-a3ad-3928ae3e5b5e", Sender = "email.sender|messanger.sender", Tenant = -1 },
new DbSubscriptionMethod { Source = "6045b68c-2c2e-42db-9e53-c272e814c4ad", Action = "removefromproject", Recipient = "c5cc67d1-c3e8-43c0-a3ad-3928ae3e5b5e", Sender = "email.sender|messanger.sender", Tenant = -1 },
new DbSubscriptionMethod { Source = "6045b68c-2c2e-42db-9e53-c272e814c4ad", Action = "responsibleforproject", Recipient = "c5cc67d1-c3e8-43c0-a3ad-3928ae3e5b5e", Sender = "email.sender|messanger.sender", Tenant = -1 },
new DbSubscriptionMethod { Source = "6045b68c-2c2e-42db-9e53-c272e814c4ad", Action = "responsiblefortask", Recipient = "c5cc67d1-c3e8-43c0-a3ad-3928ae3e5b5e", Sender = "email.sender|messanger.sender", Tenant = -1 },
new DbSubscriptionMethod { Source = "6045b68c-2c2e-42db-9e53-c272e814c4ad", Action = "taskclosed", Recipient = "c5cc67d1-c3e8-43c0-a3ad-3928ae3e5b5e", Sender = "email.sender|messanger.sender", Tenant = -1 },
new DbSubscriptionMethod { Source = "40650da3-f7c1-424c-8c89-b9c115472e08", Action = "calendar_sharing", Recipient = "c5cc67d1-c3e8-43c0-a3ad-3928ae3e5b5e", Sender = "email.sender|messanger.sender", Tenant = -1 },
new DbSubscriptionMethod { Source = "40650da3-f7c1-424c-8c89-b9c115472e08", Action = "event_alert", Recipient = "c5cc67d1-c3e8-43c0-a3ad-3928ae3e5b5e", Sender = "email.sender|messanger.sender", Tenant = -1 },
new DbSubscriptionMethod { Source = "asc.web.studio", Action = "admin_notify", Recipient = "cd84e66b-b803-40fc-99f9-b2969a54a1de", Sender = "email.sender", Tenant = -1 },
new DbSubscriptionMethod { Source = "13ff36fb-0272-4887-b416-74f52b0d0b02", Action = "SetAccess", Recipient = "abef62db-11a8-4673-9d32-ef1d8af19dc0", Sender = "email.sender|messanger.sender", Tenant = -1 },
new DbSubscriptionMethod { Source = "13ff36fb-0272-4887-b416-74f52b0d0b02", Action = "ResponsibleForTask", Recipient = "abef62db-11a8-4673-9d32-ef1d8af19dc0", Sender = "email.sender|messanger.sender", Tenant = -1 },
new DbSubscriptionMethod { Source = "13ff36fb-0272-4887-b416-74f52b0d0b02", Action = "AddRelationshipEvent", Recipient = "abef62db-11a8-4673-9d32-ef1d8af19dc0", Sender = "email.sender|messanger.sender", Tenant = -1 },
new DbSubscriptionMethod { Source = "13ff36fb-0272-4887-b416-74f52b0d0b02", Action = "ExportCompleted", Recipient = "abef62db-11a8-4673-9d32-ef1d8af19dc0", Sender = "email.sender|messanger.sender", Tenant = -1 },
new DbSubscriptionMethod { Source = "13ff36fb-0272-4887-b416-74f52b0d0b02", Action = "CreateNewContact", Recipient = "abef62db-11a8-4673-9d32-ef1d8af19dc0", Sender = "email.sender", Tenant = -1 },
new DbSubscriptionMethod { Source = "13ff36fb-0272-4887-b416-74f52b0d0b02", Action = "ResponsibleForOpportunity", Recipient = "abef62db-11a8-4673-9d32-ef1d8af19dc0", Sender = "email.sender|messanger.sender", Tenant = -1 },
new DbSubscriptionMethod { Source = "asc.web.studio", Action = "periodic_notify", Recipient = "c5cc67d1-c3e8-43c0-a3ad-3928ae3e5b5e", Sender = "email.sender", Tenant = -1 }
);
return modelBuilder;
}
public static void MySqlAddSubscriptionMethod(this ModelBuilder modelBuilder)
{
modelBuilder.Entity<DbSubscriptionMethod>(entity =>
{
entity.HasKey(e => new { e.Tenant, e.Source, e.Action, e.Recipient })
.HasName("PRIMARY");
entity.ToTable("core_subscriptionmethod");
entity.Property(e => e.Tenant).HasColumnName("tenant");
entity.Property(e => e.Source)
.HasColumnName("source")
.HasColumnType("varchar(38)")
.HasCharSet("utf8")
.UseCollation("utf8_general_ci");
entity.Property(e => e.Action)
.HasColumnName("action")
.HasColumnType("varchar(128)")
.HasCharSet("utf8")
.UseCollation("utf8_general_ci");
entity.Property(e => e.Recipient)
.HasColumnName("recipient")
.HasColumnType("varchar(38)")
.HasCharSet("utf8")
.UseCollation("utf8_general_ci");
entity.Property(e => e.Sender)
.IsRequired()
.HasColumnName("sender")
.HasColumnType("varchar(1024)")
.HasCharSet("utf8")
.UseCollation("utf8_general_ci");
});
}
public static void PgSqlAddSubscriptionMethod(this ModelBuilder modelBuilder)
{
modelBuilder.Entity<DbSubscriptionMethod>(entity =>
{
entity.HasKey(e => new { e.Tenant, e.Source, e.Action, e.Recipient })
.HasName("core_subscriptionmethod_pkey");
entity.ToTable("core_subscriptionmethod", "onlyoffice");
entity.Property(e => e.Tenant).HasColumnName("tenant");
entity.Property(e => e.Source)
.HasColumnName("source")
.HasMaxLength(38);
entity.Property(e => e.Action)
.HasColumnName("action")
.HasMaxLength(128);
entity.Property(e => e.Recipient)
.HasColumnName("recipient")
.HasMaxLength(38);
entity.Property(e => e.Sender)
.IsRequired()
.HasColumnName("sender")
.HasMaxLength(1024);
});
}
}

View File

@ -1,120 +1,119 @@
namespace ASC.Core.Common.EF
namespace ASC.Core.Common.EF;
public class Subscription : BaseEntity
{
public class Subscription : BaseEntity
public int Tenant { get; set; }
public string Source { get; set; }
public string Action { get; set; }
public string Recipient { get; set; }
public string Object { get; set; }
public bool Unsubscribed { get; set; }
public override object[] GetKeys()
{
public int Tenant { get; set; }
public string Source { get; set; }
public string Action { get; set; }
public string Recipient { get; set; }
public string Object { get; set; }
public bool Unsubscribed { get; set; }
public override object[] GetKeys()
{
return new object[] { Tenant, Source, Action, Recipient, Object };
}
}
public static class SubscriptionExtension
{
public static ModelBuilderWrapper AddSubscription(this ModelBuilderWrapper modelBuilder)
{
modelBuilder
.Add(MySqlAddSubscription, Provider.MySql)
.Add(PgSqlAddSubscription, Provider.PostgreSql)
.HasData(
new Subscription { Source = "asc.web.studio", Action = "send_whats_new", Recipient = "c5cc67d1-c3e8-43c0-a3ad-3928ae3e5b5e", Object = "", Tenant = -1 },
new Subscription { Source = "6504977c-75af-4691-9099-084d3ddeea04", Action = "new feed", Recipient = "c5cc67d1-c3e8-43c0-a3ad-3928ae3e5b5e", Object = "", Tenant = -1 },
new Subscription { Source = "6a598c74-91ae-437d-a5f4-ad339bd11bb2", Action = "new post", Recipient = "c5cc67d1-c3e8-43c0-a3ad-3928ae3e5b5e", Object = "", Tenant = -1 },
new Subscription { Source = "853b6eb9-73ee-438d-9b09-8ffeedf36234", Action = "new topic in forum", Recipient = "c5cc67d1-c3e8-43c0-a3ad-3928ae3e5b5e", Object = "", Tenant = -1 },
new Subscription { Source = "9d51954f-db9b-4aed-94e3-ed70b914e10", Action = "new photo uploaded", Recipient = "c5cc67d1-c3e8-43c0-a3ad-3928ae3e5b5e", Object = "", Tenant = -1 },
new Subscription { Source = "28b10049-dd20-4f54-b986-873bc14ccfc7", Action = "new bookmark created", Recipient = "c5cc67d1-c3e8-43c0-a3ad-3928ae3e5b5e", Object = "", Tenant = -1 },
new Subscription { Source = "742cf945-cbbc-4a57-82d6-1600a12cf8ca", Action = "new wiki page", Recipient = "c5cc67d1-c3e8-43c0-a3ad-3928ae3e5b5e", Object = "", Tenant = -1 },
new Subscription { Source = "37620ae5-c40b-45ce-855a-39dd7d76a1fa", Action = "BirthdayReminderd", Recipient = "abef62db-11a8-4673-9d32-ef1d8af19dc0", Object = "", Tenant = -1 },
new Subscription { Source = "6fe286a4-479e-4c25-a8d9-0156e332b0c0", Action = "sharedocument", Recipient = "c5cc67d1-c3e8-43c0-a3ad-3928ae3e5b5e", Object = "", Tenant = -1 },
new Subscription { Source = "6fe286a4-479e-4c25-a8d9-0156e332b0c0", Action = "sharefolder", Recipient = "c5cc67d1-c3e8-43c0-a3ad-3928ae3e5b5e", Object = "", Tenant = -1 },
new Subscription { Source = "40650da3-f7c1-424c-8c89-b9c115472e08", Action = "calendar_sharing", Recipient = "c5cc67d1-c3e8-43c0-a3ad-3928ae3e5b5e", Object = "", Tenant = -1 },
new Subscription { Source = "40650da3-f7c1-424c-8c89-b9c115472e08", Action = "event_alert", Recipient = "c5cc67d1-c3e8-43c0-a3ad-3928ae3e5b5e", Object = "", Tenant = -1 },
new Subscription { Source = "asc.web.studio", Action = "admin_notify", Recipient = "cd84e66b-b803-40fc-99f9-b2969a54a1de", Object = "", Tenant = -1 },
new Subscription { Source = "13ff36fb-0272-4887-b416-74f52b0d0b02", Action = "SetAccess", Recipient = "abef62db-11a8-4673-9d32-ef1d8af19dc0", Object = "", Tenant = -1 },
new Subscription { Source = "13ff36fb-0272-4887-b416-74f52b0d0b02", Action = "ResponsibleForTask", Recipient = "abef62db-11a8-4673-9d32-ef1d8af19dc0", Object = "", Tenant = -1 },
new Subscription { Source = "13ff36fb-0272-4887-b416-74f52b0d0b02", Action = "AddRelationshipEvent", Recipient = "abef62db-11a8-4673-9d32-ef1d8af19dc0", Object = "", Tenant = -1 },
new Subscription { Source = "13ff36fb-0272-4887-b416-74f52b0d0b02", Action = "ExportCompleted", Recipient = "abef62db-11a8-4673-9d32-ef1d8af19dc0", Object = "", Tenant = -1 },
new Subscription { Source = "13ff36fb-0272-4887-b416-74f52b0d0b02", Action = "CreateNewContact", Recipient = "abef62db-11a8-4673-9d32-ef1d8af19dc0", Object = "", Tenant = -1 },
new Subscription { Source = "13ff36fb-0272-4887-b416-74f52b0d0b02", Action = "ResponsibleForOpportunity", Recipient = "abef62db-11a8-4673-9d32-ef1d8af19dc0", Object = "", Tenant = -1 },
new Subscription { Source = "asc.web.studio", Action = "periodic_notify", Recipient = "c5cc67d1-c3e8-43c0-a3ad-3928ae3e5b5e", Object = "", Tenant = -1 }
);
return modelBuilder;
}
public static void MySqlAddSubscription(this ModelBuilder modelBuilder)
{
modelBuilder.Entity<Subscription>(entity =>
{
entity.HasKey(e => new { e.Tenant, e.Source, e.Action, e.Recipient, e.Object })
.HasName("PRIMARY");
entity.ToTable("core_subscription");
entity.Property(e => e.Tenant).HasColumnName("tenant");
entity.Property(e => e.Source)
.HasColumnName("source")
.HasColumnType("varchar(38)")
.HasCharSet("utf8")
.UseCollation("utf8_general_ci");
entity.Property(e => e.Action)
.HasColumnName("action")
.HasColumnType("varchar(128)")
.HasCharSet("utf8")
.UseCollation("utf8_general_ci");
entity.Property(e => e.Recipient)
.HasColumnName("recipient")
.HasColumnType("varchar(38)")
.HasCharSet("utf8")
.UseCollation("utf8_general_ci");
entity.Property(e => e.Object)
.HasColumnName("object")
.HasColumnType("varchar(128)")
.HasCharSet("utf8")
.UseCollation("utf8_general_ci");
entity.Property(e => e.Unsubscribed).HasColumnName("unsubscribed");
});
}
public static void PgSqlAddSubscription(this ModelBuilder modelBuilder)
{
modelBuilder.Entity<Subscription>(entity =>
{
entity.HasKey(e => new { e.Tenant, e.Source, e.Action, e.Recipient, e.Object })
.HasName("core_subscription_pkey");
entity.ToTable("core_subscription", "onlyoffice");
entity.Property(e => e.Tenant).HasColumnName("tenant");
entity.Property(e => e.Source)
.HasColumnName("source")
.HasMaxLength(38);
entity.Property(e => e.Action)
.HasColumnName("action")
.HasMaxLength(128);
entity.Property(e => e.Recipient)
.HasColumnName("recipient")
.HasMaxLength(38);
entity.Property(e => e.Object)
.HasColumnName("object")
.HasMaxLength(128);
entity.Property(e => e.Unsubscribed).HasColumnName("unsubscribed");
});
}
return new object[] { Tenant, Source, Action, Recipient, Object };
}
}
public static class SubscriptionExtension
{
public static ModelBuilderWrapper AddSubscription(this ModelBuilderWrapper modelBuilder)
{
modelBuilder
.Add(MySqlAddSubscription, Provider.MySql)
.Add(PgSqlAddSubscription, Provider.PostgreSql)
.HasData(
new Subscription { Source = "asc.web.studio", Action = "send_whats_new", Recipient = "c5cc67d1-c3e8-43c0-a3ad-3928ae3e5b5e", Object = "", Tenant = -1 },
new Subscription { Source = "6504977c-75af-4691-9099-084d3ddeea04", Action = "new feed", Recipient = "c5cc67d1-c3e8-43c0-a3ad-3928ae3e5b5e", Object = "", Tenant = -1 },
new Subscription { Source = "6a598c74-91ae-437d-a5f4-ad339bd11bb2", Action = "new post", Recipient = "c5cc67d1-c3e8-43c0-a3ad-3928ae3e5b5e", Object = "", Tenant = -1 },
new Subscription { Source = "853b6eb9-73ee-438d-9b09-8ffeedf36234", Action = "new topic in forum", Recipient = "c5cc67d1-c3e8-43c0-a3ad-3928ae3e5b5e", Object = "", Tenant = -1 },
new Subscription { Source = "9d51954f-db9b-4aed-94e3-ed70b914e10", Action = "new photo uploaded", Recipient = "c5cc67d1-c3e8-43c0-a3ad-3928ae3e5b5e", Object = "", Tenant = -1 },
new Subscription { Source = "28b10049-dd20-4f54-b986-873bc14ccfc7", Action = "new bookmark created", Recipient = "c5cc67d1-c3e8-43c0-a3ad-3928ae3e5b5e", Object = "", Tenant = -1 },
new Subscription { Source = "742cf945-cbbc-4a57-82d6-1600a12cf8ca", Action = "new wiki page", Recipient = "c5cc67d1-c3e8-43c0-a3ad-3928ae3e5b5e", Object = "", Tenant = -1 },
new Subscription { Source = "37620ae5-c40b-45ce-855a-39dd7d76a1fa", Action = "BirthdayReminderd", Recipient = "abef62db-11a8-4673-9d32-ef1d8af19dc0", Object = "", Tenant = -1 },
new Subscription { Source = "6fe286a4-479e-4c25-a8d9-0156e332b0c0", Action = "sharedocument", Recipient = "c5cc67d1-c3e8-43c0-a3ad-3928ae3e5b5e", Object = "", Tenant = -1 },
new Subscription { Source = "6fe286a4-479e-4c25-a8d9-0156e332b0c0", Action = "sharefolder", Recipient = "c5cc67d1-c3e8-43c0-a3ad-3928ae3e5b5e", Object = "", Tenant = -1 },
new Subscription { Source = "40650da3-f7c1-424c-8c89-b9c115472e08", Action = "calendar_sharing", Recipient = "c5cc67d1-c3e8-43c0-a3ad-3928ae3e5b5e", Object = "", Tenant = -1 },
new Subscription { Source = "40650da3-f7c1-424c-8c89-b9c115472e08", Action = "event_alert", Recipient = "c5cc67d1-c3e8-43c0-a3ad-3928ae3e5b5e", Object = "", Tenant = -1 },
new Subscription { Source = "asc.web.studio", Action = "admin_notify", Recipient = "cd84e66b-b803-40fc-99f9-b2969a54a1de", Object = "", Tenant = -1 },
new Subscription { Source = "13ff36fb-0272-4887-b416-74f52b0d0b02", Action = "SetAccess", Recipient = "abef62db-11a8-4673-9d32-ef1d8af19dc0", Object = "", Tenant = -1 },
new Subscription { Source = "13ff36fb-0272-4887-b416-74f52b0d0b02", Action = "ResponsibleForTask", Recipient = "abef62db-11a8-4673-9d32-ef1d8af19dc0", Object = "", Tenant = -1 },
new Subscription { Source = "13ff36fb-0272-4887-b416-74f52b0d0b02", Action = "AddRelationshipEvent", Recipient = "abef62db-11a8-4673-9d32-ef1d8af19dc0", Object = "", Tenant = -1 },
new Subscription { Source = "13ff36fb-0272-4887-b416-74f52b0d0b02", Action = "ExportCompleted", Recipient = "abef62db-11a8-4673-9d32-ef1d8af19dc0", Object = "", Tenant = -1 },
new Subscription { Source = "13ff36fb-0272-4887-b416-74f52b0d0b02", Action = "CreateNewContact", Recipient = "abef62db-11a8-4673-9d32-ef1d8af19dc0", Object = "", Tenant = -1 },
new Subscription { Source = "13ff36fb-0272-4887-b416-74f52b0d0b02", Action = "ResponsibleForOpportunity", Recipient = "abef62db-11a8-4673-9d32-ef1d8af19dc0", Object = "", Tenant = -1 },
new Subscription { Source = "asc.web.studio", Action = "periodic_notify", Recipient = "c5cc67d1-c3e8-43c0-a3ad-3928ae3e5b5e", Object = "", Tenant = -1 }
);
return modelBuilder;
}
public static void MySqlAddSubscription(this ModelBuilder modelBuilder)
{
modelBuilder.Entity<Subscription>(entity =>
{
entity.HasKey(e => new { e.Tenant, e.Source, e.Action, e.Recipient, e.Object })
.HasName("PRIMARY");
entity.ToTable("core_subscription");
entity.Property(e => e.Tenant).HasColumnName("tenant");
entity.Property(e => e.Source)
.HasColumnName("source")
.HasColumnType("varchar(38)")
.HasCharSet("utf8")
.UseCollation("utf8_general_ci");
entity.Property(e => e.Action)
.HasColumnName("action")
.HasColumnType("varchar(128)")
.HasCharSet("utf8")
.UseCollation("utf8_general_ci");
entity.Property(e => e.Recipient)
.HasColumnName("recipient")
.HasColumnType("varchar(38)")
.HasCharSet("utf8")
.UseCollation("utf8_general_ci");
entity.Property(e => e.Object)
.HasColumnName("object")
.HasColumnType("varchar(128)")
.HasCharSet("utf8")
.UseCollation("utf8_general_ci");
entity.Property(e => e.Unsubscribed).HasColumnName("unsubscribed");
});
}
public static void PgSqlAddSubscription(this ModelBuilder modelBuilder)
{
modelBuilder.Entity<Subscription>(entity =>
{
entity.HasKey(e => new { e.Tenant, e.Source, e.Action, e.Recipient, e.Object })
.HasName("core_subscription_pkey");
entity.ToTable("core_subscription", "onlyoffice");
entity.Property(e => e.Tenant).HasColumnName("tenant");
entity.Property(e => e.Source)
.HasColumnName("source")
.HasMaxLength(38);
entity.Property(e => e.Action)
.HasColumnName("action")
.HasMaxLength(128);
entity.Property(e => e.Recipient)
.HasColumnName("recipient")
.HasMaxLength(38);
entity.Property(e => e.Object)
.HasColumnName("object")
.HasMaxLength(128);
entity.Property(e => e.Unsubscribed).HasColumnName("unsubscribed");
});
}
}

Some files were not shown because too many files have changed in this diff Show More