Merge branch 'feature/backend-refactor' into feature/people-refactor
This commit is contained in:
commit
b48bd37ea6
@ -80,7 +80,7 @@ public class ConfirmAuthHandler : AuthenticationHandler<AuthenticationSchemeOpti
|
||||
}
|
||||
else
|
||||
{
|
||||
userId = _userManager.GetUserByEmail(emailValidationKeyModel.Email).ID;
|
||||
userId = _userManager.GetUserByEmail(emailValidationKeyModel.Email).Id;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -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;
|
||||
}
|
||||
|
@ -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}");
|
||||
}
|
||||
|
||||
|
@ -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;
|
||||
}
|
||||
|
@ -30,4 +30,5 @@ public interface ISecurityObjectId
|
||||
{
|
||||
object SecurityId { get; }
|
||||
Type ObjectType { get; }
|
||||
string FullId { get; }
|
||||
}
|
||||
|
@ -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)
|
||||
{
|
||||
|
@ -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('/');
|
||||
}
|
||||
}
|
||||
|
@ -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)
|
||||
{
|
||||
}
|
||||
}
|
||||
|
@ -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;
|
||||
}
|
||||
}
|
||||
|
@ -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);
|
||||
}
|
||||
|
@ -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;
|
||||
}
|
||||
}
|
||||
|
@ -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) { }
|
||||
}
|
||||
|
@ -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;
|
||||
}
|
||||
|
@ -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; }
|
||||
}
|
||||
|
@ -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; }
|
||||
}
|
||||
|
@ -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
@ -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,
|
||||
}
|
||||
|
18
common/ASC.Core.Common/ByteConverter.cs
Normal file
18
common/ASC.Core.Common/ByteConverter.cs
Normal 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;
|
||||
}
|
||||
}
|
@ -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();
|
||||
}
|
||||
}
|
||||
|
@ -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);
|
||||
}
|
||||
}
|
||||
|
@ -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;
|
||||
}
|
||||
}
|
||||
|
@ -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());
|
||||
}
|
||||
}
|
||||
|
@ -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);
|
||||
}
|
||||
}
|
||||
|
@ -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);
|
||||
}
|
||||
}
|
||||
|
@ -24,10 +24,9 @@
|
||||
*/
|
||||
|
||||
|
||||
namespace ASC.Core.Caching
|
||||
namespace ASC.Core.Caching;
|
||||
|
||||
public interface ICachedService
|
||||
{
|
||||
public interface ICachedService
|
||||
{
|
||||
void InvalidateCache();
|
||||
}
|
||||
void InvalidateCache();
|
||||
}
|
||||
|
@ -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;
|
||||
}
|
||||
}
|
||||
|
@ -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;
|
||||
}
|
||||
}
|
||||
|
@ -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; }
|
||||
}
|
||||
|
@ -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);
|
||||
}
|
||||
}
|
||||
|
@ -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);
|
||||
// }
|
||||
//}
|
||||
|
@ -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;
|
||||
}
|
||||
|
@ -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();
|
||||
}
|
||||
}
|
||||
|
@ -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());
|
||||
}
|
||||
}
|
||||
|
@ -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);
|
||||
}
|
||||
}
|
||||
|
@ -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);
|
||||
}
|
||||
}
|
||||
|
@ -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
|
||||
}
|
||||
|
@ -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}";
|
||||
}
|
||||
|
||||
}
|
||||
}
|
||||
|
@ -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;
|
||||
}
|
||||
}
|
||||
|
@ -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
@ -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;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -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>();
|
||||
}
|
||||
}
|
||||
|
@ -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();
|
||||
}
|
||||
}
|
||||
|
@ -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;
|
||||
}
|
||||
}
|
||||
|
@ -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
|
||||
}
|
||||
|
@ -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
|
||||
}
|
||||
|
@ -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
|
||||
}
|
||||
|
@ -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>();
|
||||
}
|
||||
}
|
||||
|
@ -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;
|
||||
}
|
||||
|
@ -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);
|
||||
}
|
||||
|
@ -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);
|
||||
}
|
||||
|
@ -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);
|
||||
}
|
||||
|
@ -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);
|
||||
}
|
||||
|
@ -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);
|
||||
}
|
||||
|
@ -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
|
||||
}
|
||||
|
@ -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;
|
||||
}
|
||||
}
|
||||
|
@ -24,12 +24,11 @@
|
||||
*/
|
||||
|
||||
|
||||
namespace ASC.Core
|
||||
namespace ASC.Core;
|
||||
|
||||
public enum PartnerDisplayType
|
||||
{
|
||||
public enum PartnerDisplayType
|
||||
{
|
||||
LogoOnly,
|
||||
DisplayNameOnly,
|
||||
All,
|
||||
}
|
||||
LogoOnly,
|
||||
DisplayNameOnly,
|
||||
All,
|
||||
}
|
||||
|
@ -24,12 +24,11 @@
|
||||
*/
|
||||
|
||||
|
||||
namespace ASC.Core
|
||||
namespace ASC.Core;
|
||||
|
||||
public enum PartnerPaymentMethod
|
||||
{
|
||||
public enum PartnerPaymentMethod
|
||||
{
|
||||
Keys,
|
||||
PayPal,
|
||||
External
|
||||
}
|
||||
}
|
||||
Keys,
|
||||
PayPal,
|
||||
External
|
||||
}
|
||||
|
@ -24,13 +24,12 @@
|
||||
*/
|
||||
|
||||
|
||||
namespace ASC.Core
|
||||
namespace ASC.Core;
|
||||
|
||||
public enum PartnerStatus
|
||||
{
|
||||
public enum PartnerStatus
|
||||
{
|
||||
Created,
|
||||
Approved,
|
||||
Rejected,
|
||||
Blocked
|
||||
}
|
||||
Created,
|
||||
Approved,
|
||||
Rejected,
|
||||
Blocked
|
||||
}
|
||||
|
@ -24,12 +24,11 @@
|
||||
*/
|
||||
|
||||
|
||||
namespace ASC.Core
|
||||
namespace ASC.Core;
|
||||
|
||||
public enum PartnerType
|
||||
{
|
||||
public enum PartnerType
|
||||
{
|
||||
Default,
|
||||
Administrator,
|
||||
System,
|
||||
}
|
||||
}
|
||||
Default,
|
||||
Administrator,
|
||||
System,
|
||||
}
|
||||
|
@ -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)));
|
||||
}
|
||||
}
|
||||
|
10
common/ASC.Core.Common/Core/SubscriptionRecord.cs
Normal file
10
common/ASC.Core.Common/Core/SubscriptionRecord.cs
Normal 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));
|
||||
}
|
||||
}
|
@ -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
|
||||
};
|
||||
}
|
||||
}
|
||||
|
@ -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());
|
||||
}
|
||||
}
|
||||
|
@ -24,11 +24,10 @@
|
||||
*/
|
||||
|
||||
|
||||
namespace ASC.Core
|
||||
namespace ASC.Core;
|
||||
|
||||
public enum UserGroupRefType
|
||||
{
|
||||
public enum UserGroupRefType
|
||||
{
|
||||
Contains,
|
||||
Manager,
|
||||
}
|
||||
Contains,
|
||||
Manager,
|
||||
}
|
||||
|
@ -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;
|
||||
}
|
||||
}
|
||||
|
@ -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();
|
||||
}
|
||||
}
|
||||
|
@ -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();
|
||||
}
|
||||
}
|
||||
|
@ -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);
|
||||
}
|
||||
}
|
||||
|
@ -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;
|
||||
}
|
||||
}
|
||||
|
@ -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
@ -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>();
|
||||
}
|
||||
}
|
||||
|
@ -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();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -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);
|
||||
}
|
||||
}
|
||||
|
@ -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();
|
||||
}
|
||||
}
|
||||
|
@ -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>();
|
||||
}
|
||||
}
|
||||
|
@ -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;
|
||||
}
|
||||
}
|
||||
|
@ -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>();
|
||||
}
|
||||
}
|
||||
|
@ -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>();
|
||||
}
|
||||
}
|
||||
|
@ -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>();
|
||||
}
|
||||
}
|
||||
|
@ -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>();
|
||||
}
|
||||
}
|
||||
|
@ -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>();
|
||||
}
|
||||
}
|
||||
|
@ -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>();
|
||||
}
|
||||
}
|
||||
|
@ -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>();
|
||||
}
|
||||
}
|
||||
|
@ -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>();
|
||||
}
|
||||
}
|
||||
|
@ -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>();
|
||||
}
|
||||
}
|
||||
|
@ -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);
|
||||
}
|
||||
}
|
||||
|
@ -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;
|
||||
}
|
||||
}
|
||||
|
@ -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;
|
||||
}
|
||||
}
|
||||
|
@ -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);
|
||||
}
|
||||
}
|
||||
|
@ -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");
|
||||
});
|
||||
}
|
||||
}
|
||||
|
@ -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");
|
||||
});
|
||||
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -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");
|
||||
});
|
||||
}
|
||||
}
|
||||
|
@ -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");
|
||||
});
|
||||
}
|
||||
}
|
||||
|
@ -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");
|
||||
});
|
||||
}
|
||||
}
|
||||
|
@ -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");
|
||||
});
|
||||
}
|
||||
}
|
||||
|
@ -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);
|
||||
});
|
||||
}
|
||||
}
|
||||
|
@ -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
Loading…
Reference in New Issue
Block a user