namespace ASC.Core.Data; [Scope] public class DbSubscriptionService : ISubscriptionService { private readonly Lazy _lazyUserDbContext; private UserDbContext UserDbContext => _lazyUserDbContext.Value; private readonly IMapper _mapper; public DbSubscriptionService(DbContextManager dbContextManager, IMapper mapper) { _lazyUserDbContext = new Lazy(() => dbContextManager.Value); _mapper = mapper; } public string[] GetRecipients(int tenant, string sourceId, string actionId, string objectId) { ArgumentNullException.ThrowIfNull(sourceId); ArgumentNullException.ThrowIfNull(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(); } public IEnumerable GetSubscriptions(int tenant, string sourceId, string actionId) { ArgumentNullException.ThrowIfNull(sourceId); ArgumentNullException.ThrowIfNull(actionId); var q = GetQuery(tenant, sourceId, actionId); return GetSubscriptions(q, tenant); } public IEnumerable 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) { ArgumentNullException.ThrowIfNull(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(); } public bool IsUnsubscribe(int tenant, string sourceId, string actionId, string recipientId, string objectId) { ArgumentNullException.ThrowIfNull(recipientId); ArgumentNullException.ThrowIfNull(sourceId); ArgumentNullException.ThrowIfNull(actionId); 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) { ArgumentNullException.ThrowIfNull(recipientId); ArgumentNullException.ThrowIfNull(sourceId); ArgumentNullException.ThrowIfNull(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) { ArgumentNullException.ThrowIfNull(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) { ArgumentNullException.ThrowIfNull(sourceId); ArgumentNullException.ThrowIfNull(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 GetSubscriptionMethods(int tenant, string sourceId, string actionId, string recipientId) { ArgumentNullException.ThrowIfNull(sourceId); ArgumentNullException.ThrowIfNull(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(); var common = new Dictionary(); foreach (var r in methods) { var m = _mapper.Map(r); var key = m.Source + m.Action + m.Recipient; if (m.Tenant == Tenant.DefaultTenant) { m.Tenant = tenant; common.Add(key, m); result.Add(m); } else { if (!common.TryGetValue(key, out var rec)) { result.Add(rec); } } } return result; } public void SetSubscriptionMethod(SubscriptionMethod m) { ArgumentNullException.ThrowIfNull(m); using var tr = UserDbContext.Database.BeginTransaction(); if (m.Methods == null || m.Methods.Length == 0) { var q = UserDbContext.SubscriptionMethods .Where(r => r.Tenant == m.Tenant) .Where(r => r.Source == m.Source) .Where(r => r.Recipient == m.Recipient) .Where(r => r.Action == m.Action); var sm = q.FirstOrDefault(); if (sm != null) { UserDbContext.SubscriptionMethods.Remove(sm); } } else { var sm = new DbSubscriptionMethod { 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(); } private IQueryable GetQuery(int tenant, string sourceId, string actionId) { ArgumentNullException.ThrowIfNull(sourceId); ArgumentNullException.ThrowIfNull(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 GetSubscriptions(IQueryable q, int tenant) { var subs = q.ToList(); var result = new List(); var common = new Dictionary(); foreach (var r in subs) { var s = _mapper.Map(r); var key = s.SourceId + s.ActionId + s.RecipientId + s.ObjectId; if (s.Tenant == Tenant.DefaultTenant) { s.Tenant = tenant; common.Add(key, s); result.Add(s); } else { if (!common.TryGetValue(key, out _)) { result.Add(s); } } } return result; } }