Merge branch 'develop' into feature/get-thumbnail-from-thirdparty
This commit is contained in:
commit
29d3bb3fee
@ -126,13 +126,23 @@ public class EmployeeFullDtoHelper : EmployeeDtoHelper
|
||||
|
||||
//i => new UserInfo { ID = i.id }
|
||||
var parameter = Expression.Parameter(typeof(User), "i");
|
||||
var bindExprs = new List<MemberAssignment>();
|
||||
|
||||
if (apiContext.Check("Id"))
|
||||
{
|
||||
bindExprs.Add(Expression.Bind(typeof(UserInfo).GetProperty("ID"),
|
||||
Expression.Property(parameter, typeof(User).GetProperty("Id"))));
|
||||
}
|
||||
var bindExprs = new List<MemberAssignment>();
|
||||
|
||||
//foreach (var field in apiContext.Fields)
|
||||
//{
|
||||
// var userInfoProp = typeof(UserInfo).GetProperty(field);
|
||||
// var userProp = typeof(User).GetProperty(field);
|
||||
// if (userInfoProp != null && userProp != null)
|
||||
// {
|
||||
// bindExprs.Add(Expression.Bind(userInfoProp, Expression.Property(parameter, userProp)));
|
||||
// }
|
||||
//}
|
||||
|
||||
if (apiContext.Check("Id"))
|
||||
{
|
||||
bindExprs.Add(Expression.Bind(typeof(UserInfo).GetProperty("Id"),
|
||||
Expression.Property(parameter, typeof(User).GetProperty("Id"))));
|
||||
}
|
||||
|
||||
var body = Expression.MemberInit(newExpr, bindExprs);
|
||||
var lambda = Expression.Lambda<Func<User, UserInfo>>(body, parameter);
|
||||
|
42
common/ASC.Common/Data/TypeExtension.cs
Normal file
42
common/ASC.Common/Data/TypeExtension.cs
Normal file
@ -0,0 +1,42 @@
|
||||
// (c) Copyright Ascensio System SIA 2010-2022
|
||||
//
|
||||
// This program is a free software product.
|
||||
// You can redistribute it and/or modify it under the terms
|
||||
// of the GNU Affero General Public License (AGPL) version 3 as published by the Free Software
|
||||
// Foundation. In accordance with Section 7(a) of the GNU AGPL its Section 15 shall be amended
|
||||
// to the effect that Ascensio System SIA expressly excludes the warranty of non-infringement of
|
||||
// any third-party rights.
|
||||
//
|
||||
// This program is distributed WITHOUT ANY WARRANTY, without even the implied warranty
|
||||
// of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. For details, see
|
||||
// the GNU AGPL at: http://www.gnu.org/licenses/agpl-3.0.html
|
||||
//
|
||||
// You can contact Ascensio System SIA at Lubanas st. 125a-25, Riga, Latvia, EU, LV-1021.
|
||||
//
|
||||
// The interactive user interfaces in modified source and object code versions of the Program must
|
||||
// display Appropriate Legal Notices, as required under Section 5 of the GNU AGPL version 3.
|
||||
//
|
||||
// Pursuant to Section 7(b) of the License you must retain the original Product logo when
|
||||
// distributing the program. Pursuant to Section 7(e) we decline to grant you any rights under
|
||||
// trademark law for use of our trademarks.
|
||||
//
|
||||
// All the Product's GUI elements, including illustrations and icon sets, as well as technical writing
|
||||
// content are licensed under the terms of the Creative Commons Attribution-ShareAlike 4.0
|
||||
// International. See the License terms at http://creativecommons.org/licenses/by-sa/4.0/legalcode
|
||||
|
||||
namespace ASC.Common.Data;
|
||||
public static class TypeExtension
|
||||
{
|
||||
public static string GetFormattedName(this Type type)
|
||||
{
|
||||
if (type.IsGenericType)
|
||||
{
|
||||
var genericArguments = type.GetGenericArguments()
|
||||
.Select(x => x.Name)
|
||||
.Aggregate((x1, x2) => $"{x1}, {x2}");
|
||||
return $"{type.Name.Substring(0, type.Name.IndexOf("`"))}"
|
||||
+ $"<{genericArguments}>";
|
||||
}
|
||||
return type.Name;
|
||||
}
|
||||
}
|
@ -27,7 +27,7 @@
|
||||
namespace ASC.Common.Log;
|
||||
internal static partial class DistributedTaskQueueLogger
|
||||
{
|
||||
[LoggerMessage(Level = LogLevel.Trace, Message = "EnqueueTask '{distributedTaskId}' by instanse id '{instanceId}'")]
|
||||
[LoggerMessage(Level = LogLevel.Trace, Message = "EnqueueTask '{DistributedTaskId}' by instanse id '{instanceId}'")]
|
||||
public static partial void TraceEnqueueTask(this ILogger<DistributedTaskQueue> logger, string DistributedTaskId, int instanceId);
|
||||
|
||||
[LoggerMessage(Level = LogLevel.Trace, Message = "Publication DistributedTask '{DistributedTaskId}' by instanse id '{instanceId}' ")]
|
||||
|
@ -305,6 +305,13 @@ public class DistributedTaskQueue
|
||||
|
||||
private void SaveToCache(IEnumerable<DistributedTask> queueTasks)
|
||||
{
|
||||
if (!queueTasks.Any())
|
||||
{
|
||||
_distributedCache.Remove(_name);
|
||||
|
||||
return;
|
||||
}
|
||||
|
||||
using var ms = new MemoryStream();
|
||||
|
||||
Serializer.Serialize(ms, queueTasks);
|
||||
@ -332,21 +339,11 @@ public class DistributedTaskQueue
|
||||
|
||||
private IEnumerable<DistributedTask> DeleteOrphanCacheItem(IEnumerable<DistributedTask> queueTasks)
|
||||
{
|
||||
if (!queueTasks.Any())
|
||||
{
|
||||
return queueTasks;
|
||||
}
|
||||
var listTasks = queueTasks.ToList();
|
||||
|
||||
var orphans = queueTasks.Where(IsOrphanCacheItem);
|
||||
listTasks.RemoveAll(IsOrphanCacheItem);
|
||||
|
||||
if (!orphans.Any())
|
||||
{
|
||||
return queueTasks;
|
||||
}
|
||||
|
||||
queueTasks = queueTasks.Except(queueTasks);
|
||||
|
||||
SaveToCache(queueTasks);
|
||||
SaveToCache(listTasks);
|
||||
|
||||
return queueTasks;
|
||||
}
|
||||
|
@ -495,31 +495,36 @@ public class TariffService : ITariffService
|
||||
var currentTariff = GetBillingInfo(tenant);
|
||||
if (!tariffInfo.EqualsByParams(currentTariff))
|
||||
{
|
||||
using var tx = CoreDbContext.Database.BeginTransaction();
|
||||
var strategy = CoreDbContext.Database.CreateExecutionStrategy();
|
||||
|
||||
// last record is not the same
|
||||
var any = CoreDbContext.Tariffs
|
||||
.Any(r => r.Tenant == tenant && r.Tariff == tariffInfo.QuotaId && r.Stamp == tariffInfo.DueDate && r.Quantity == tariffInfo.Quantity);
|
||||
|
||||
if (tariffInfo.DueDate == DateTime.MaxValue || renewal || any)
|
||||
{
|
||||
var efTariff = new DbTariff
|
||||
strategy.Execute(() =>
|
||||
{
|
||||
Tenant = tenant,
|
||||
Tariff = tariffInfo.QuotaId,
|
||||
Stamp = tariffInfo.DueDate,
|
||||
Quantity = tariffInfo.Quantity,
|
||||
CreateOn = DateTime.UtcNow
|
||||
};
|
||||
using var tx = CoreDbContext.Database.BeginTransaction();
|
||||
|
||||
CoreDbContext.Tariffs.Add(efTariff);
|
||||
CoreDbContext.SaveChanges();
|
||||
// last record is not the same
|
||||
var any = CoreDbContext.Tariffs
|
||||
.Any(r => r.Tenant == tenant && r.Tariff == tariffInfo.QuotaId && r.Stamp == tariffInfo.DueDate && r.Quantity == tariffInfo.Quantity);
|
||||
|
||||
Cache.Remove(GetTariffCacheKey(tenant));
|
||||
inserted = true;
|
||||
}
|
||||
if (tariffInfo.DueDate == DateTime.MaxValue || renewal || any)
|
||||
{
|
||||
var efTariff = new DbTariff
|
||||
{
|
||||
Tenant = tenant,
|
||||
Tariff = tariffInfo.QuotaId,
|
||||
Stamp = tariffInfo.DueDate,
|
||||
Quantity = tariffInfo.Quantity,
|
||||
CreateOn = DateTime.UtcNow
|
||||
};
|
||||
|
||||
tx.Commit();
|
||||
CoreDbContext.Tariffs.Add(efTariff);
|
||||
CoreDbContext.SaveChanges();
|
||||
|
||||
Cache.Remove(GetTariffCacheKey(tenant));
|
||||
inserted = true;
|
||||
}
|
||||
|
||||
tx.Commit();
|
||||
});
|
||||
}
|
||||
|
||||
if (inserted)
|
||||
|
@ -76,17 +76,25 @@ class DbAzService : IAzService
|
||||
public AzRecord SaveAce(int tenant, AzRecord r)
|
||||
{
|
||||
r.Tenant = tenant;
|
||||
using var tx = UserDbContext.Database.BeginTransaction();
|
||||
if (!ExistEscapeRecord(r))
|
||||
|
||||
var strategy = UserDbContext.Database.CreateExecutionStrategy();
|
||||
|
||||
strategy.Execute(() =>
|
||||
{
|
||||
InsertRecord(r);
|
||||
}
|
||||
else
|
||||
{
|
||||
// unescape
|
||||
DeleteRecord(r);
|
||||
}
|
||||
tx.Commit();
|
||||
using var tx = UserDbContext.Database.BeginTransaction();
|
||||
|
||||
if (!ExistEscapeRecord(r))
|
||||
{
|
||||
InsertRecord(r);
|
||||
}
|
||||
else
|
||||
{
|
||||
// unescape
|
||||
DeleteRecord(r);
|
||||
}
|
||||
|
||||
tx.Commit();
|
||||
});
|
||||
|
||||
return r;
|
||||
}
|
||||
@ -94,18 +102,26 @@ class DbAzService : IAzService
|
||||
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();
|
||||
var strategy = UserDbContext.Database.CreateExecutionStrategy();
|
||||
|
||||
strategy.Execute(() =>
|
||||
{
|
||||
using var tx = UserDbContext.Database.BeginTransaction();
|
||||
|
||||
if (ExistEscapeRecord(r))
|
||||
{
|
||||
// escape
|
||||
InsertRecord(r);
|
||||
}
|
||||
else
|
||||
{
|
||||
DeleteRecord(r);
|
||||
}
|
||||
|
||||
tx.Commit();
|
||||
});
|
||||
|
||||
}
|
||||
|
||||
|
||||
|
@ -90,18 +90,23 @@ class DbQuotaService : IQuotaService
|
||||
|
||||
public void RemoveTenantQuota(int id)
|
||||
{
|
||||
using var tr = CoreDbContext.Database.BeginTransaction();
|
||||
var d = CoreDbContext.Quotas
|
||||
.Where(r => r.Tenant == id)
|
||||
.SingleOrDefault();
|
||||
var strategy = CoreDbContext.Database.CreateExecutionStrategy();
|
||||
|
||||
if (d != null)
|
||||
strategy.Execute(() =>
|
||||
{
|
||||
CoreDbContext.Quotas.Remove(d);
|
||||
CoreDbContext.SaveChanges();
|
||||
}
|
||||
using var tr = CoreDbContext.Database.BeginTransaction();
|
||||
var d = CoreDbContext.Quotas
|
||||
.Where(r => r.Tenant == id)
|
||||
.SingleOrDefault();
|
||||
|
||||
tr.Commit();
|
||||
if (d != null)
|
||||
{
|
||||
CoreDbContext.Quotas.Remove(d);
|
||||
CoreDbContext.SaveChanges();
|
||||
}
|
||||
|
||||
tr.Commit();
|
||||
});
|
||||
}
|
||||
|
||||
|
||||
@ -109,22 +114,27 @@ class DbQuotaService : IQuotaService
|
||||
{
|
||||
ArgumentNullException.ThrowIfNull(row);
|
||||
|
||||
using var tx = CoreDbContext.Database.BeginTransaction();
|
||||
var strategy = CoreDbContext.Database.CreateExecutionStrategy();
|
||||
|
||||
var counter = CoreDbContext.QuotaRows
|
||||
.Where(r => r.Path == row.Path && r.Tenant == row.Tenant)
|
||||
.Select(r => r.Counter)
|
||||
.Take(1)
|
||||
.FirstOrDefault();
|
||||
strategy.Execute(() =>
|
||||
{
|
||||
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 = _mapper.Map<TenantQuotaRow, DbQuotaRow>(row);
|
||||
dbQuotaRow.Counter = exchange ? counter + row.Counter : row.Counter;
|
||||
dbQuotaRow.LastModified = DateTime.UtcNow;
|
||||
|
||||
tx.Commit();
|
||||
CoreDbContext.AddOrUpdate(r => r.QuotaRows, dbQuotaRow);
|
||||
CoreDbContext.SaveChanges();
|
||||
|
||||
tx.Commit();
|
||||
});
|
||||
}
|
||||
|
||||
public IEnumerable<TenantQuotaRow> FindTenantQuotaRows(int tenantId)
|
||||
|
@ -185,21 +185,30 @@ public class DbSettingsManager
|
||||
|
||||
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();
|
||||
var strategy = WebstudioDbContext.Database.CreateExecutionStrategy();
|
||||
|
||||
if (s != null)
|
||||
strategy.Execute(() =>
|
||||
{
|
||||
WebstudioDbContext.WebstudioSettings.Remove(s);
|
||||
}
|
||||
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.SaveChanges();
|
||||
|
||||
tr.Commit();
|
||||
});
|
||||
|
||||
|
||||
|
||||
WebstudioDbContext.SaveChanges();
|
||||
tr.Commit();
|
||||
}
|
||||
else
|
||||
{
|
||||
|
@ -162,25 +162,30 @@ public class DbSubscriptionService : ISubscriptionService
|
||||
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)
|
||||
var strategy = UserDbContext.Database.CreateExecutionStrategy();
|
||||
|
||||
strategy.Execute(() =>
|
||||
{
|
||||
q = q.Where(r => r.Object == (objectId ?? string.Empty));
|
||||
}
|
||||
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);
|
||||
|
||||
var sub = q.FirstOrDefault();
|
||||
if (objectId.Length != 0)
|
||||
{
|
||||
q = q.Where(r => r.Object == (objectId ?? string.Empty));
|
||||
}
|
||||
|
||||
if (sub != null)
|
||||
{
|
||||
UserDbContext.Subscriptions.Remove(sub);
|
||||
}
|
||||
var sub = q.FirstOrDefault();
|
||||
|
||||
tr.Commit();
|
||||
if (sub != null)
|
||||
{
|
||||
UserDbContext.Subscriptions.Remove(sub);
|
||||
}
|
||||
|
||||
tr.Commit();
|
||||
});
|
||||
}
|
||||
|
||||
|
||||
@ -232,38 +237,47 @@ public class DbSubscriptionService : ISubscriptionService
|
||||
{
|
||||
ArgumentNullException.ThrowIfNull(m);
|
||||
|
||||
using var tr = UserDbContext.Database.BeginTransaction();
|
||||
var strategy = UserDbContext.Database.CreateExecutionStrategy();
|
||||
|
||||
if (m.Methods == null || m.Methods.Length == 0)
|
||||
strategy.Execute(() =>
|
||||
{
|
||||
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);
|
||||
using var tr = UserDbContext.Database.BeginTransaction();
|
||||
|
||||
var sm = q.FirstOrDefault();
|
||||
|
||||
if (sm != null)
|
||||
if (m.Methods == null || m.Methods.Length == 0)
|
||||
{
|
||||
UserDbContext.SubscriptionMethods.Remove(sm);
|
||||
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
|
||||
else
|
||||
{
|
||||
Action = m.Action,
|
||||
Recipient = m.Recipient,
|
||||
Source = m.Source,
|
||||
Tenant = m.Tenant,
|
||||
Sender = string.Join("|", m.Methods)
|
||||
};
|
||||
UserDbContext.AddOrUpdate(r => r.SubscriptionMethods, sm);
|
||||
}
|
||||
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();
|
||||
});
|
||||
|
||||
|
||||
|
||||
|
||||
UserDbContext.SaveChanges();
|
||||
tr.Commit();
|
||||
}
|
||||
|
||||
|
||||
|
@ -84,7 +84,8 @@ public class DbTenantService : ITenantService
|
||||
|
||||
public void ValidateDomain(string domain)
|
||||
{
|
||||
using var tr = TenantDbContext.Database.BeginTransaction();
|
||||
// TODO: Why does open transaction?
|
||||
// using var tr = TenantDbContext.Database.BeginTransaction();
|
||||
ValidateDomain(domain, Tenant.DefaultTenant, true);
|
||||
}
|
||||
|
||||
@ -228,93 +229,98 @@ public class DbTenantService : ITenantService
|
||||
{
|
||||
ArgumentNullException.ThrowIfNull(tenant);
|
||||
|
||||
using var tx = TenantDbContext.Database.BeginTransaction();
|
||||
var strategy = TenantDbContext.Database.CreateExecutionStrategy();
|
||||
|
||||
if (!string.IsNullOrEmpty(tenant.MappedDomain))
|
||||
strategy.Execute(() =>
|
||||
{
|
||||
var baseUrl = coreSettings.GetBaseDomain(tenant.HostedRegion);
|
||||
using var tx = TenantDbContext.Database.BeginTransaction();
|
||||
|
||||
if (baseUrl != null && tenant.MappedDomain.EndsWith("." + baseUrl, StringComparison.InvariantCultureIgnoreCase))
|
||||
if (!string.IsNullOrEmpty(tenant.MappedDomain))
|
||||
{
|
||||
ValidateDomain(tenant.MappedDomain.Substring(0, tenant.MappedDomain.Length - baseUrl.Length - 1), tenant.Id, false);
|
||||
var baseUrl = coreSettings.GetBaseDomain(tenant.HostedRegion);
|
||||
|
||||
if (baseUrl != null && tenant.MappedDomain.EndsWith("." + baseUrl, StringComparison.InvariantCultureIgnoreCase))
|
||||
{
|
||||
ValidateDomain(tenant.MappedDomain.Substring(0, tenant.MappedDomain.Length - baseUrl.Length - 1), tenant.Id, false);
|
||||
}
|
||||
else
|
||||
{
|
||||
ValidateDomain(tenant.MappedDomain, tenant.Id, false);
|
||||
}
|
||||
}
|
||||
|
||||
if (tenant.Id == Tenant.DefaultTenant)
|
||||
{
|
||||
tenant.Version = TenantDbContext.TenantVersion
|
||||
.Where(r => r.DefaultVersion == 1 || r.Id == 0)
|
||||
.OrderByDescending(r => r.Id)
|
||||
.Select(r => r.Id)
|
||||
.FirstOrDefault();
|
||||
|
||||
tenant.LastModified = DateTime.UtcNow;
|
||||
|
||||
var dbTenant = _mapper.Map<Tenant, DbTenant>(tenant);
|
||||
|
||||
dbTenant = TenantDbContext.Tenants.Add(dbTenant).Entity;
|
||||
TenantDbContext.SaveChanges();
|
||||
tenant.Id = dbTenant.Id;
|
||||
}
|
||||
else
|
||||
{
|
||||
ValidateDomain(tenant.MappedDomain, tenant.Id, false);
|
||||
}
|
||||
}
|
||||
var dbTenant = TenantDbContext.Tenants
|
||||
.Where(r => r.Id == tenant.Id)
|
||||
.FirstOrDefault();
|
||||
|
||||
if (tenant.Id == Tenant.DefaultTenant)
|
||||
{
|
||||
tenant.Version = TenantDbContext.TenantVersion
|
||||
.Where(r => r.DefaultVersion == 1 || r.Id == 0)
|
||||
.OrderByDescending(r => r.Id)
|
||||
.Select(r => r.Id)
|
||||
.FirstOrDefault();
|
||||
if (dbTenant != null)
|
||||
{
|
||||
dbTenant.Alias = tenant.Alias.ToLowerInvariant();
|
||||
dbTenant.MappedDomain = !string.IsNullOrEmpty(tenant.MappedDomain) ? tenant.MappedDomain.ToLowerInvariant() : null;
|
||||
dbTenant.Version = tenant.Version;
|
||||
dbTenant.VersionChanged = tenant.VersionChanged;
|
||||
dbTenant.Name = tenant.Name ?? tenant.Alias;
|
||||
dbTenant.Language = tenant.Language;
|
||||
dbTenant.TimeZone = tenant.TimeZone;
|
||||
dbTenant.TrustedDomainsRaw = tenant.GetTrustedDomains();
|
||||
dbTenant.TrustedDomainsEnabled = tenant.TrustedDomainsType;
|
||||
dbTenant.CreationDateTime = tenant.CreationDateTime;
|
||||
dbTenant.Status = tenant.Status;
|
||||
dbTenant.StatusChanged = tenant.StatusChangeDate;
|
||||
dbTenant.PaymentId = tenant.PaymentId;
|
||||
dbTenant.LastModified = tenant.LastModified = DateTime.UtcNow;
|
||||
dbTenant.Industry = tenant.Industry;
|
||||
dbTenant.Spam = tenant.Spam;
|
||||
dbTenant.Calls = tenant.Calls;
|
||||
}
|
||||
|
||||
tenant.LastModified = DateTime.UtcNow;
|
||||
|
||||
var dbTenant = _mapper.Map<Tenant, DbTenant>(tenant);
|
||||
|
||||
dbTenant = TenantDbContext.Tenants.Add(dbTenant).Entity;
|
||||
TenantDbContext.SaveChanges();
|
||||
tenant.Id = dbTenant.Id;
|
||||
}
|
||||
else
|
||||
{
|
||||
var dbTenant = TenantDbContext.Tenants
|
||||
.Where(r => r.Id == tenant.Id)
|
||||
.FirstOrDefault();
|
||||
|
||||
if (dbTenant != null)
|
||||
{
|
||||
dbTenant.Alias = tenant.Alias.ToLowerInvariant();
|
||||
dbTenant.MappedDomain = !string.IsNullOrEmpty(tenant.MappedDomain) ? tenant.MappedDomain.ToLowerInvariant() : null;
|
||||
dbTenant.Version = tenant.Version;
|
||||
dbTenant.VersionChanged = tenant.VersionChanged;
|
||||
dbTenant.Name = tenant.Name ?? tenant.Alias;
|
||||
dbTenant.Language = tenant.Language;
|
||||
dbTenant.TimeZone = tenant.TimeZone;
|
||||
dbTenant.TrustedDomainsRaw = tenant.GetTrustedDomains();
|
||||
dbTenant.TrustedDomainsEnabled = tenant.TrustedDomainsType;
|
||||
dbTenant.CreationDateTime = tenant.CreationDateTime;
|
||||
dbTenant.Status = tenant.Status;
|
||||
dbTenant.StatusChanged = tenant.StatusChangeDate;
|
||||
dbTenant.PaymentId = tenant.PaymentId;
|
||||
dbTenant.LastModified = tenant.LastModified = DateTime.UtcNow;
|
||||
dbTenant.Industry = tenant.Industry;
|
||||
dbTenant.Spam = tenant.Spam;
|
||||
dbTenant.Calls = tenant.Calls;
|
||||
TenantDbContext.SaveChanges();
|
||||
}
|
||||
|
||||
TenantDbContext.SaveChanges();
|
||||
}
|
||||
|
||||
if (string.IsNullOrEmpty(tenant.PartnerId) && string.IsNullOrEmpty(tenant.AffiliateId) && string.IsNullOrEmpty(tenant.Campaign))
|
||||
{
|
||||
var p = TenantDbContext.TenantPartner
|
||||
.Where(r => r.TenantId == tenant.Id)
|
||||
.FirstOrDefault();
|
||||
|
||||
if (p != null)
|
||||
if (string.IsNullOrEmpty(tenant.PartnerId) && string.IsNullOrEmpty(tenant.AffiliateId) && string.IsNullOrEmpty(tenant.Campaign))
|
||||
{
|
||||
TenantDbContext.TenantPartner.Remove(p);
|
||||
var p = TenantDbContext.TenantPartner
|
||||
.Where(r => r.TenantId == tenant.Id)
|
||||
.FirstOrDefault();
|
||||
|
||||
if (p != null)
|
||||
{
|
||||
TenantDbContext.TenantPartner.Remove(p);
|
||||
}
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
var tenantPartner = new DbTenantPartner
|
||||
else
|
||||
{
|
||||
TenantId = tenant.Id,
|
||||
PartnerId = tenant.PartnerId,
|
||||
AffiliateId = tenant.AffiliateId,
|
||||
Campaign = tenant.Campaign
|
||||
};
|
||||
var tenantPartner = new DbTenantPartner
|
||||
{
|
||||
TenantId = tenant.Id,
|
||||
PartnerId = tenant.PartnerId,
|
||||
AffiliateId = tenant.AffiliateId,
|
||||
Campaign = tenant.Campaign
|
||||
};
|
||||
|
||||
TenantDbContext.TenantPartner.Add(tenantPartner);
|
||||
}
|
||||
TenantDbContext.TenantPartner.Add(tenantPartner);
|
||||
}
|
||||
|
||||
tx.Commit();
|
||||
tx.Commit();
|
||||
});
|
||||
|
||||
//CalculateTenantDomain(t);
|
||||
return tenant;
|
||||
@ -324,30 +330,35 @@ public class DbTenantService : ITenantService
|
||||
{
|
||||
var postfix = auto ? "_auto_deleted" : "_deleted";
|
||||
|
||||
using var tx = TenantDbContext.Database.BeginTransaction();
|
||||
var strategy = TenantDbContext.Database.CreateExecutionStrategy();
|
||||
|
||||
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)
|
||||
strategy.Execute(() =>
|
||||
{
|
||||
tenant.Alias = alias + postfix + (count > 0 ? count.ToString() : "");
|
||||
tenant.Status = TenantStatus.RemovePending;
|
||||
tenant.StatusChanged = DateTime.UtcNow;
|
||||
tenant.LastModified = DateTime.UtcNow;
|
||||
}
|
||||
using var tx = TenantDbContext.Database.BeginTransaction();
|
||||
|
||||
TenantDbContext.SaveChanges();
|
||||
var alias = TenantDbContext.Tenants
|
||||
.Where(r => r.Id == id)
|
||||
.Select(r => r.Alias)
|
||||
.FirstOrDefault();
|
||||
|
||||
tx.Commit();
|
||||
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()
|
||||
@ -370,35 +381,40 @@ public class DbTenantService : ITenantService
|
||||
|
||||
public void SetTenantSettings(int tenant, string key, byte[] data)
|
||||
{
|
||||
using var tx = TenantDbContext.Database.BeginTransaction();
|
||||
var strategy = TenantDbContext.Database.CreateExecutionStrategy();
|
||||
|
||||
if (data == null || data.Length == 0)
|
||||
strategy.Execute(() =>
|
||||
{
|
||||
var settings = TenantDbContext.CoreSettings
|
||||
.Where(r => r.Tenant == tenant)
|
||||
.Where(r => r.Id == key)
|
||||
.FirstOrDefault();
|
||||
using var tx = TenantDbContext.Database.BeginTransaction();
|
||||
|
||||
if (settings != null)
|
||||
if (data == null || data.Length == 0)
|
||||
{
|
||||
TenantDbContext.CoreSettings.Remove(settings);
|
||||
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
|
||||
else
|
||||
{
|
||||
Id = key,
|
||||
Tenant = tenant,
|
||||
Value = data,
|
||||
LastModified = DateTime.UtcNow
|
||||
};
|
||||
var settings = new DbCoreSettings
|
||||
{
|
||||
Id = key,
|
||||
Tenant = tenant,
|
||||
Value = data,
|
||||
LastModified = DateTime.UtcNow
|
||||
};
|
||||
|
||||
TenantDbContext.AddOrUpdate(r => r.CoreSettings, settings);
|
||||
}
|
||||
TenantDbContext.AddOrUpdate(r => r.CoreSettings, settings);
|
||||
}
|
||||
|
||||
TenantDbContext.SaveChanges();
|
||||
tx.Commit();
|
||||
TenantDbContext.SaveChanges();
|
||||
tx.Commit();
|
||||
});
|
||||
}
|
||||
|
||||
private IQueryable<DbTenant> TenantsQuery()
|
||||
|
@ -318,36 +318,41 @@ public class EFUserService : IUserService
|
||||
var ids = CollectGroupChilds(tenant, id);
|
||||
var stringIds = ids.Select(r => r.ToString()).ToList();
|
||||
|
||||
using var tr = UserDbContext.Database.BeginTransaction();
|
||||
var strategy = UserDbContext.Database.CreateExecutionStrategy();
|
||||
|
||||
UserDbContext.Acl.RemoveRange(UserDbContext.Acl.Where(r => r.Tenant == tenant && ids.Any(i => i == r.Subject)));
|
||||
UserDbContext.Subscriptions.RemoveRange(UserDbContext.Subscriptions.Where(r => r.Tenant == tenant && stringIds.Any(i => i == r.Recipient)));
|
||||
UserDbContext.SubscriptionMethods.RemoveRange(UserDbContext.SubscriptionMethods.Where(r => r.Tenant == tenant && stringIds.Any(i => i == r.Recipient)));
|
||||
|
||||
var userGroups = UserDbContext.UserGroups.Where(r => r.Tenant == tenant && ids.Any(i => i == r.GroupId));
|
||||
var groups = UserDbContext.Groups.Where(r => r.Tenant == tenant && ids.Any(i => i == r.Id));
|
||||
|
||||
if (immediate)
|
||||
strategy.Execute(() =>
|
||||
{
|
||||
UserDbContext.UserGroups.RemoveRange(userGroups);
|
||||
UserDbContext.Groups.RemoveRange(groups);
|
||||
}
|
||||
else
|
||||
{
|
||||
foreach (var ug in userGroups)
|
||||
{
|
||||
ug.Removed = true;
|
||||
ug.LastModified = DateTime.UtcNow;
|
||||
}
|
||||
foreach (var g in groups)
|
||||
{
|
||||
g.Removed = true;
|
||||
g.LastModified = DateTime.UtcNow;
|
||||
}
|
||||
}
|
||||
using var tr = UserDbContext.Database.BeginTransaction();
|
||||
|
||||
UserDbContext.SaveChanges();
|
||||
tr.Commit();
|
||||
UserDbContext.Acl.RemoveRange(UserDbContext.Acl.Where(r => r.Tenant == tenant && ids.Any(i => i == r.Subject)));
|
||||
UserDbContext.Subscriptions.RemoveRange(UserDbContext.Subscriptions.Where(r => r.Tenant == tenant && stringIds.Any(i => i == r.Recipient)));
|
||||
UserDbContext.SubscriptionMethods.RemoveRange(UserDbContext.SubscriptionMethods.Where(r => r.Tenant == tenant && stringIds.Any(i => i == r.Recipient)));
|
||||
|
||||
var userGroups = UserDbContext.UserGroups.Where(r => r.Tenant == tenant && ids.Any(i => i == r.GroupId));
|
||||
var groups = UserDbContext.Groups.Where(r => r.Tenant == tenant && ids.Any(i => i == r.Id));
|
||||
|
||||
if (immediate)
|
||||
{
|
||||
UserDbContext.UserGroups.RemoveRange(userGroups);
|
||||
UserDbContext.Groups.RemoveRange(groups);
|
||||
}
|
||||
else
|
||||
{
|
||||
foreach (var ug in userGroups)
|
||||
{
|
||||
ug.Removed = true;
|
||||
ug.LastModified = DateTime.UtcNow;
|
||||
}
|
||||
foreach (var g in groups)
|
||||
{
|
||||
g.Removed = true;
|
||||
g.LastModified = DateTime.UtcNow;
|
||||
}
|
||||
}
|
||||
|
||||
UserDbContext.SaveChanges();
|
||||
tr.Commit();
|
||||
});
|
||||
}
|
||||
|
||||
public void RemoveUser(int tenant, Guid id)
|
||||
@ -357,43 +362,48 @@ public class EFUserService : IUserService
|
||||
|
||||
public void RemoveUser(int tenant, Guid id, bool immediate)
|
||||
{
|
||||
using var tr = UserDbContext.Database.BeginTransaction();
|
||||
var strategy = UserDbContext.Database.CreateExecutionStrategy();
|
||||
|
||||
UserDbContext.Acl.RemoveRange(UserDbContext.Acl.Where(r => r.Tenant == tenant && r.Subject == id));
|
||||
UserDbContext.Subscriptions.RemoveRange(UserDbContext.Subscriptions.Where(r => r.Tenant == tenant && r.Recipient == id.ToString()));
|
||||
UserDbContext.SubscriptionMethods.RemoveRange(UserDbContext.SubscriptionMethods.Where(r => r.Tenant == tenant && r.Recipient == id.ToString()));
|
||||
UserDbContext.Photos.RemoveRange(UserDbContext.Photos.Where(r => r.Tenant == tenant && r.UserId == id));
|
||||
|
||||
var userGroups = UserDbContext.UserGroups.Where(r => r.Tenant == tenant && r.UserId == id);
|
||||
var users = UserDbContext.Users.Where(r => r.Tenant == tenant && r.Id == id);
|
||||
var userSecurity = UserDbContext.UserSecurity.Where(r => r.Tenant == tenant && r.UserId == id);
|
||||
|
||||
if (immediate)
|
||||
strategy.Execute(() =>
|
||||
{
|
||||
UserDbContext.UserGroups.RemoveRange(userGroups);
|
||||
UserDbContext.Users.RemoveRange(users);
|
||||
UserDbContext.UserSecurity.RemoveRange(userSecurity);
|
||||
}
|
||||
else
|
||||
{
|
||||
foreach (var ug in userGroups)
|
||||
using var tr = UserDbContext.Database.BeginTransaction();
|
||||
|
||||
UserDbContext.Acl.RemoveRange(UserDbContext.Acl.Where(r => r.Tenant == tenant && r.Subject == id));
|
||||
UserDbContext.Subscriptions.RemoveRange(UserDbContext.Subscriptions.Where(r => r.Tenant == tenant && r.Recipient == id.ToString()));
|
||||
UserDbContext.SubscriptionMethods.RemoveRange(UserDbContext.SubscriptionMethods.Where(r => r.Tenant == tenant && r.Recipient == id.ToString()));
|
||||
UserDbContext.Photos.RemoveRange(UserDbContext.Photos.Where(r => r.Tenant == tenant && r.UserId == id));
|
||||
|
||||
var userGroups = UserDbContext.UserGroups.Where(r => r.Tenant == tenant && r.UserId == id);
|
||||
var users = UserDbContext.Users.Where(r => r.Tenant == tenant && r.Id == id);
|
||||
var userSecurity = UserDbContext.UserSecurity.Where(r => r.Tenant == tenant && r.UserId == id);
|
||||
|
||||
if (immediate)
|
||||
{
|
||||
ug.Removed = true;
|
||||
ug.LastModified = DateTime.UtcNow;
|
||||
UserDbContext.UserGroups.RemoveRange(userGroups);
|
||||
UserDbContext.Users.RemoveRange(users);
|
||||
UserDbContext.UserSecurity.RemoveRange(userSecurity);
|
||||
}
|
||||
else
|
||||
{
|
||||
foreach (var ug in userGroups)
|
||||
{
|
||||
ug.Removed = true;
|
||||
ug.LastModified = DateTime.UtcNow;
|
||||
}
|
||||
|
||||
foreach (var u in users)
|
||||
{
|
||||
u.Removed = true;
|
||||
u.Status = EmployeeStatus.Terminated;
|
||||
u.TerminatedDate = DateTime.UtcNow;
|
||||
u.LastModified = DateTime.UtcNow;
|
||||
}
|
||||
}
|
||||
|
||||
foreach (var u in users)
|
||||
{
|
||||
u.Removed = true;
|
||||
u.Status = EmployeeStatus.Terminated;
|
||||
u.TerminatedDate = DateTime.UtcNow;
|
||||
u.LastModified = DateTime.UtcNow;
|
||||
}
|
||||
}
|
||||
UserDbContext.SaveChanges();
|
||||
|
||||
UserDbContext.SaveChanges();
|
||||
|
||||
tr.Commit();
|
||||
tr.Commit();
|
||||
});
|
||||
}
|
||||
|
||||
public void RemoveUserGroupRef(int tenant, Guid userId, Guid groupId, UserGroupRefType refType)
|
||||
@ -403,26 +413,31 @@ public class EFUserService : IUserService
|
||||
|
||||
public void RemoveUserGroupRef(int tenant, Guid userId, Guid groupId, UserGroupRefType refType, bool immediate)
|
||||
{
|
||||
using var tr = UserDbContext.Database.BeginTransaction();
|
||||
var strategy = UserDbContext.Database.CreateExecutionStrategy();
|
||||
|
||||
var userGroups = UserDbContext.UserGroups.Where(r => r.Tenant == tenant && r.UserId == userId && r.GroupId == groupId && r.RefType == refType);
|
||||
if (immediate)
|
||||
strategy.Execute(() =>
|
||||
{
|
||||
UserDbContext.UserGroups.RemoveRange(userGroups);
|
||||
}
|
||||
else
|
||||
{
|
||||
foreach (var u in userGroups)
|
||||
using var tr = UserDbContext.Database.BeginTransaction();
|
||||
|
||||
var userGroups = UserDbContext.UserGroups.Where(r => r.Tenant == tenant && r.UserId == userId && r.GroupId == groupId && r.RefType == refType);
|
||||
if (immediate)
|
||||
{
|
||||
u.LastModified = DateTime.UtcNow;
|
||||
u.Removed = true;
|
||||
UserDbContext.UserGroups.RemoveRange(userGroups);
|
||||
}
|
||||
}
|
||||
var user = UserDbContext.Users.First(r => r.Tenant == tenant && r.Id == userId);
|
||||
user.LastModified = DateTime.UtcNow;
|
||||
UserDbContext.SaveChanges();
|
||||
else
|
||||
{
|
||||
foreach (var u in userGroups)
|
||||
{
|
||||
u.LastModified = DateTime.UtcNow;
|
||||
u.Removed = true;
|
||||
}
|
||||
}
|
||||
var user = UserDbContext.Users.First(r => r.Tenant == tenant && r.Id == userId);
|
||||
user.LastModified = DateTime.UtcNow;
|
||||
UserDbContext.SaveChanges();
|
||||
|
||||
tr.Commit();
|
||||
tr.Commit();
|
||||
});
|
||||
}
|
||||
|
||||
public Group SaveGroup(int tenant, Group group)
|
||||
@ -468,26 +483,31 @@ public class EFUserService : IUserService
|
||||
user.UserName = user.UserName.Trim();
|
||||
user.Email = user.Email.Trim();
|
||||
|
||||
using var tx = UserDbContext.Database.BeginTransaction();
|
||||
var any = GetUserQuery(tenant)
|
||||
.Any(r => r.UserName == user.UserName && r.Id != user.Id && !r.Removed);
|
||||
var strategy = UserDbContext.Database.CreateExecutionStrategy();
|
||||
|
||||
if (any)
|
||||
strategy.Execute(() =>
|
||||
{
|
||||
throw new ArgumentOutOfRangeException("Duplicate username.");
|
||||
}
|
||||
using var tx = UserDbContext.Database.BeginTransaction();
|
||||
var any = GetUserQuery(tenant)
|
||||
.Any(r => r.UserName == user.UserName && r.Id != user.Id && !r.Removed);
|
||||
|
||||
any = GetUserQuery(tenant)
|
||||
.Any(r => r.Email == user.Email && r.Id != user.Id && !r.Removed);
|
||||
if (any)
|
||||
{
|
||||
throw new ArgumentOutOfRangeException("Duplicate username.");
|
||||
}
|
||||
|
||||
if (any)
|
||||
{
|
||||
throw new ArgumentOutOfRangeException("Duplicate email.");
|
||||
}
|
||||
any = GetUserQuery(tenant)
|
||||
.Any(r => r.Email == user.Email && r.Id != user.Id && !r.Removed);
|
||||
|
||||
UserDbContext.AddOrUpdate(r => r.Users, _mapper.Map<UserInfo, User>(user));
|
||||
UserDbContext.SaveChanges();
|
||||
tx.Commit();
|
||||
if (any)
|
||||
{
|
||||
throw new ArgumentOutOfRangeException("Duplicate email.");
|
||||
}
|
||||
|
||||
UserDbContext.AddOrUpdate(r => r.Users, _mapper.Map<UserInfo, User>(user));
|
||||
UserDbContext.SaveChanges();
|
||||
tx.Commit();
|
||||
});
|
||||
|
||||
return user;
|
||||
}
|
||||
@ -499,17 +519,24 @@ public class EFUserService : IUserService
|
||||
userGroupRef.LastModified = DateTime.UtcNow;
|
||||
userGroupRef.Tenant = tenant;
|
||||
|
||||
using var tr = UserDbContext.Database.BeginTransaction();
|
||||
var strategy = UserDbContext.Database.CreateExecutionStrategy();
|
||||
|
||||
var user = GetUserQuery(tenant).FirstOrDefault(a => a.Tenant == tenant && a.Id == userGroupRef.UserId);
|
||||
if (user != null)
|
||||
strategy.Execute(() =>
|
||||
{
|
||||
user.LastModified = userGroupRef.LastModified;
|
||||
UserDbContext.AddOrUpdate(r => r.UserGroups, _mapper.Map<UserGroupRef, UserGroup>(userGroupRef));
|
||||
}
|
||||
using var tr = UserDbContext.Database.BeginTransaction();
|
||||
|
||||
var user = GetUserQuery(tenant).FirstOrDefault(a => a.Tenant == tenant && a.Id == userGroupRef.UserId);
|
||||
if (user != null)
|
||||
{
|
||||
user.LastModified = userGroupRef.LastModified;
|
||||
UserDbContext.AddOrUpdate(r => r.UserGroups, _mapper.Map<UserGroupRef, UserGroup>(userGroupRef));
|
||||
}
|
||||
|
||||
UserDbContext.SaveChanges();
|
||||
tr.Commit();
|
||||
});
|
||||
|
||||
|
||||
UserDbContext.SaveChanges();
|
||||
tr.Commit();
|
||||
|
||||
return userGroupRef;
|
||||
}
|
||||
@ -533,34 +560,39 @@ public class EFUserService : IUserService
|
||||
|
||||
public void SetUserPhoto(int tenant, Guid id, byte[] photo)
|
||||
{
|
||||
using var tr = UserDbContext.Database.BeginTransaction();
|
||||
var strategy = UserDbContext.Database.CreateExecutionStrategy();
|
||||
|
||||
var userPhoto = UserDbContext.Photos.FirstOrDefault(r => r.UserId == id && r.Tenant == tenant);
|
||||
if (photo != null && photo.Length != 0)
|
||||
strategy.Execute(() =>
|
||||
{
|
||||
if (userPhoto == null)
|
||||
using var tr = UserDbContext.Database.BeginTransaction();
|
||||
|
||||
var userPhoto = UserDbContext.Photos.FirstOrDefault(r => r.UserId == id && r.Tenant == tenant);
|
||||
if (photo != null && photo.Length != 0)
|
||||
{
|
||||
userPhoto = new UserPhoto
|
||||
if (userPhoto == null)
|
||||
{
|
||||
Tenant = tenant,
|
||||
UserId = id,
|
||||
Photo = photo
|
||||
};
|
||||
userPhoto = new UserPhoto
|
||||
{
|
||||
Tenant = tenant,
|
||||
UserId = id,
|
||||
Photo = photo
|
||||
};
|
||||
}
|
||||
else
|
||||
{
|
||||
userPhoto.Photo = photo;
|
||||
}
|
||||
|
||||
UserDbContext.AddOrUpdate(r => r.Photos, userPhoto);
|
||||
}
|
||||
else
|
||||
else if (userPhoto != null)
|
||||
{
|
||||
userPhoto.Photo = photo;
|
||||
UserDbContext.Photos.Remove(userPhoto);
|
||||
}
|
||||
|
||||
UserDbContext.AddOrUpdate(r => r.Photos, userPhoto);
|
||||
}
|
||||
else if (userPhoto != null)
|
||||
{
|
||||
UserDbContext.Photos.Remove(userPhoto);
|
||||
}
|
||||
|
||||
UserDbContext.SaveChanges();
|
||||
tr.Commit();
|
||||
UserDbContext.SaveChanges();
|
||||
tr.Commit();
|
||||
});
|
||||
}
|
||||
|
||||
private IQueryable<User> GetUserQuery(int tenant)
|
||||
|
@ -74,15 +74,15 @@ public class BaseDbContext : DbContext
|
||||
switch (_provider)
|
||||
{
|
||||
case Provider.MySql:
|
||||
optionsBuilder.UseMySql(ConnectionStringSettings.ConnectionString, ServerVersion, sqlOptions =>
|
||||
optionsBuilder.UseMySql(ConnectionStringSettings.ConnectionString, ServerVersion, providerOptions =>
|
||||
{
|
||||
if (!string.IsNullOrEmpty(MigrateAssembly))
|
||||
{
|
||||
sqlOptions.MigrationsAssembly(MigrateAssembly);
|
||||
providerOptions.MigrationsAssembly(MigrateAssembly);
|
||||
}
|
||||
|
||||
//Configuring Connection Resiliency: https://docs.microsoft.com/en-us/ef/core/miscellaneous/connection-resiliency
|
||||
// sqlOptions.EnableRetryOnFailure(maxRetryCount: 15, maxRetryDelay: TimeSpan.FromSeconds(30), errorNumbersToAdd: null);
|
||||
providerOptions.EnableRetryOnFailure(maxRetryCount: 15, maxRetryDelay: TimeSpan.FromSeconds(30), errorNumbersToAdd: null);
|
||||
});
|
||||
break;
|
||||
case Provider.PostgreSql:
|
||||
|
@ -149,3 +149,4 @@ global using ProtoBuf;
|
||||
global using Telegram.Bot;
|
||||
|
||||
global using static ASC.Security.Cryptography.EmailValidationKeyProvider;
|
||||
global using ASC.Common.Data;
|
@ -79,7 +79,7 @@ public class RegisterInstanceDao<T> : IRegisterInstanceDao<T> where T : IHostedS
|
||||
public async Task<IEnumerable<InstanceRegistration>> GetAll()
|
||||
{
|
||||
return await _instanceRegistrationContext.InstanceRegistrations
|
||||
.Where(x => x.WorkerTypeName == typeof(T).Name)
|
||||
.Where(x => x.WorkerTypeName == typeof(T).GetFormattedName())
|
||||
.ToListAsync();
|
||||
}
|
||||
|
||||
|
@ -51,7 +51,7 @@ public class RegisterInstanceManager<T> : IRegisterInstanceManager<T> where T :
|
||||
var instance = registeredInstance ?? new InstanceRegistration
|
||||
{
|
||||
InstanceRegistrationId = instanceId,
|
||||
WorkerTypeName = typeof(T).Name
|
||||
WorkerTypeName = typeof(T).GetFormattedName()
|
||||
};
|
||||
|
||||
instance.LastUpdated = DateTime.UtcNow;
|
||||
|
@ -24,7 +24,7 @@
|
||||
// content are licensed under the terms of the Creative Commons Attribution-ShareAlike 4.0
|
||||
// International. See the License terms at http://creativecommons.org/licenses/by-sa/4.0/legalcode
|
||||
|
||||
namespace ASC.Core.Common.Hosting;
|
||||
namespace ASC.Core.Common.Hosting;
|
||||
|
||||
[Singletone]
|
||||
public class RegisterInstanceWorkerService<T> : BackgroundService where T : IHostedService
|
||||
@ -33,7 +33,7 @@ public class RegisterInstanceWorkerService<T> : BackgroundService where T : IHos
|
||||
private readonly IHostApplicationLifetime _applicationLifetime;
|
||||
private readonly IServiceProvider _serviceProvider;
|
||||
public static readonly string InstanceId =
|
||||
$"{typeof(T).Name}_{DateTime.UtcNow.Ticks}";
|
||||
$"{typeof(T).GetFormattedName()}_{DateTime.UtcNow.Ticks}";
|
||||
|
||||
public RegisterInstanceWorkerService(
|
||||
ILogger<RegisterInstanceWorkerService<T>> logger,
|
||||
@ -58,7 +58,7 @@ public class RegisterInstanceWorkerService<T> : BackgroundService where T : IHos
|
||||
await registerInstanceService.Register(InstanceId);
|
||||
await registerInstanceService.DeleteOrphanInstances();
|
||||
|
||||
_logger.InformationWorkingRunnging(DateTimeOffset.Now);
|
||||
_logger.TraceWorkingRunnging(DateTimeOffset.Now);
|
||||
|
||||
await Task.Delay(1000, stoppingToken);
|
||||
}
|
||||
@ -87,5 +87,6 @@ public class RegisterInstanceWorkerService<T> : BackgroundService where T : IHos
|
||||
}
|
||||
|
||||
await base.StopAsync(cancellationToken);
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
|
@ -31,8 +31,8 @@ internal static partial class RegisterInstanceWorkerServiceLogger
|
||||
[LoggerMessage(Level = LogLevel.Trace, Message = "DbUpdateConcurrencyException: then updating {instanceName} at {time} time.")]
|
||||
public static partial void TraceDbUpdateConcurrencyException(this ILogger logger, string instanceName, DateTimeOffset time);
|
||||
|
||||
[LoggerMessage(Level = LogLevel.Information, Message = "Worker running at: {time}")]
|
||||
public static partial void InformationWorkingRunnging(this ILogger logger, DateTimeOffset time);
|
||||
[LoggerMessage(Level = LogLevel.Trace, Message = "Worker running at: {time}")]
|
||||
public static partial void TraceWorkingRunnging(this ILogger logger, DateTimeOffset time);
|
||||
|
||||
[LoggerMessage(Level = LogLevel.Information, Message = "UnRegister Instance {instanceName} running at: {time}.")]
|
||||
public static partial void InformationUnRegister(this ILogger logger, string instanceName, DateTimeOffset time);
|
||||
|
@ -166,26 +166,34 @@ public class AccountLinker
|
||||
|
||||
public void RemoveProvider(string obj, string provider = null, string hashId = null)
|
||||
{
|
||||
using var tr = AccountLinkContext.Database.BeginTransaction();
|
||||
var strategy = AccountLinkContext.Database.CreateExecutionStrategy();
|
||||
|
||||
var accountLinkQuery = AccountLinks
|
||||
.Where(r => r.Id == obj);
|
||||
|
||||
if (!string.IsNullOrEmpty(provider))
|
||||
strategy.Execute(() =>
|
||||
{
|
||||
accountLinkQuery = accountLinkQuery.Where(r => r.Provider == provider);
|
||||
}
|
||||
using var tr = AccountLinkContext.Database.BeginTransaction();
|
||||
|
||||
var accountLinkQuery = AccountLinks
|
||||
.Where(r => r.Id == obj);
|
||||
|
||||
if (!string.IsNullOrEmpty(provider))
|
||||
{
|
||||
accountLinkQuery = accountLinkQuery.Where(r => r.Provider == provider);
|
||||
}
|
||||
|
||||
if (!string.IsNullOrEmpty(hashId))
|
||||
{
|
||||
accountLinkQuery = accountLinkQuery.Where(r => r.UId == hashId);
|
||||
}
|
||||
|
||||
var accountLink = accountLinkQuery.FirstOrDefault();
|
||||
AccountLinks.Remove(accountLink);
|
||||
AccountLinkContext.SaveChanges();
|
||||
|
||||
tr.Commit();
|
||||
});
|
||||
|
||||
if (!string.IsNullOrEmpty(hashId))
|
||||
{
|
||||
accountLinkQuery = accountLinkQuery.Where(r => r.UId == hashId);
|
||||
}
|
||||
|
||||
var accountLink = accountLinkQuery.FirstOrDefault();
|
||||
AccountLinks.Remove(accountLink);
|
||||
AccountLinkContext.SaveChanges();
|
||||
|
||||
tr.Commit();
|
||||
AccountLinkerStorage.RemoveFromCache(obj);
|
||||
}
|
||||
|
||||
|
@ -98,57 +98,67 @@ public class FeedAggregateDataProvider
|
||||
|
||||
private void SaveFeedsPortion(IEnumerable<FeedRow> feeds, DateTime aggregatedDate)
|
||||
{
|
||||
using var tx = FeedDbContext.Database.BeginTransaction();
|
||||
var strategy = FeedDbContext.Database.CreateExecutionStrategy();
|
||||
|
||||
foreach (var f in feeds)
|
||||
strategy.Execute(() =>
|
||||
{
|
||||
if (0 >= f.Users.Count)
|
||||
{
|
||||
continue;
|
||||
}
|
||||
using var tx = FeedDbContext.Database.BeginTransaction();
|
||||
|
||||
var feedAggregate = _mapper.Map<FeedRow, FeedAggregate>(f);
|
||||
feedAggregate.AggregateDate = aggregatedDate;
|
||||
|
||||
if (f.ClearRightsBeforeInsert)
|
||||
foreach (var f in feeds)
|
||||
{
|
||||
var fu = FeedDbContext.FeedUsers.Where(r => r.FeedId == f.Id).FirstOrDefault();
|
||||
if (fu != null)
|
||||
if (0 >= f.Users.Count)
|
||||
{
|
||||
FeedDbContext.FeedUsers.Remove(fu);
|
||||
continue;
|
||||
}
|
||||
|
||||
var feedAggregate = _mapper.Map<FeedRow, FeedAggregate>(f);
|
||||
feedAggregate.AggregateDate = aggregatedDate;
|
||||
|
||||
if (f.ClearRightsBeforeInsert)
|
||||
{
|
||||
var fu = FeedDbContext.FeedUsers.Where(r => r.FeedId == f.Id).FirstOrDefault();
|
||||
if (fu != null)
|
||||
{
|
||||
FeedDbContext.FeedUsers.Remove(fu);
|
||||
}
|
||||
}
|
||||
|
||||
FeedDbContext.AddOrUpdate(r => r.FeedAggregates, feedAggregate);
|
||||
|
||||
foreach (var u in f.Users)
|
||||
{
|
||||
var feedUser = new FeedUsers
|
||||
{
|
||||
FeedId = f.Id,
|
||||
UserId = u
|
||||
};
|
||||
|
||||
FeedDbContext.AddOrUpdate(r => r.FeedUsers, feedUser);
|
||||
}
|
||||
}
|
||||
|
||||
FeedDbContext.AddOrUpdate(r => r.FeedAggregates, feedAggregate);
|
||||
FeedDbContext.SaveChanges();
|
||||
|
||||
foreach (var u in f.Users)
|
||||
{
|
||||
var feedUser = new FeedUsers
|
||||
{
|
||||
FeedId = f.Id,
|
||||
UserId = u
|
||||
};
|
||||
|
||||
FeedDbContext.AddOrUpdate(r => r.FeedUsers, feedUser);
|
||||
}
|
||||
}
|
||||
|
||||
FeedDbContext.SaveChanges();
|
||||
|
||||
tx.Commit();
|
||||
tx.Commit();
|
||||
});
|
||||
}
|
||||
|
||||
public void RemoveFeedAggregate(DateTime fromTime)
|
||||
{
|
||||
using var tx = FeedDbContext.Database.BeginTransaction(IsolationLevel.ReadUncommitted);
|
||||
var strategy = FeedDbContext.Database.CreateExecutionStrategy();
|
||||
|
||||
var aggregates = FeedDbContext.FeedAggregates.Where(r => r.AggregateDate <= fromTime);
|
||||
FeedDbContext.FeedAggregates.RemoveRange(aggregates);
|
||||
strategy.Execute(() =>
|
||||
{
|
||||
using var tx = FeedDbContext.Database.BeginTransaction(IsolationLevel.ReadUncommitted);
|
||||
|
||||
var users = FeedDbContext.FeedUsers.Where(r => FeedDbContext.FeedAggregates.Where(r => r.AggregateDate <= fromTime).Any(a => a.Id == r.FeedId));
|
||||
FeedDbContext.FeedUsers.RemoveRange(users);
|
||||
var aggregates = FeedDbContext.FeedAggregates.Where(r => r.AggregateDate <= fromTime);
|
||||
FeedDbContext.FeedAggregates.RemoveRange(aggregates);
|
||||
|
||||
tx.Commit();
|
||||
var users = FeedDbContext.FeedUsers.Where(r => FeedDbContext.FeedAggregates.Where(r => r.AggregateDate <= fromTime).Any(a => a.Id == r.FeedId));
|
||||
FeedDbContext.FeedUsers.RemoveRange(users);
|
||||
|
||||
tx.Commit();
|
||||
});
|
||||
}
|
||||
|
||||
public List<FeedResultItem> GetFeeds(FeedApiFilter filter)
|
||||
@ -273,17 +283,22 @@ public class FeedAggregateDataProvider
|
||||
|
||||
public void RemoveFeedItem(string id)
|
||||
{
|
||||
using var tx = FeedDbContext.Database.BeginTransaction(IsolationLevel.ReadUncommitted);
|
||||
var strategy = FeedDbContext.Database.CreateExecutionStrategy();
|
||||
|
||||
var aggregates = FeedDbContext.FeedAggregates.Where(r => r.Id == id);
|
||||
FeedDbContext.FeedAggregates.RemoveRange(aggregates);
|
||||
strategy.Execute(() =>
|
||||
{
|
||||
using var tx = FeedDbContext.Database.BeginTransaction(IsolationLevel.ReadUncommitted);
|
||||
|
||||
var users = FeedDbContext.FeedUsers.Where(r => r.FeedId == id);
|
||||
FeedDbContext.FeedUsers.RemoveRange(users);
|
||||
var aggregates = FeedDbContext.FeedAggregates.Where(r => r.Id == id);
|
||||
FeedDbContext.FeedAggregates.RemoveRange(aggregates);
|
||||
|
||||
FeedDbContext.SaveChanges();
|
||||
var users = FeedDbContext.FeedUsers.Where(r => r.FeedId == id);
|
||||
FeedDbContext.FeedUsers.RemoveRange(users);
|
||||
|
||||
tx.Commit();
|
||||
FeedDbContext.SaveChanges();
|
||||
|
||||
tx.Commit();
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -24,6 +24,8 @@
|
||||
// content are licensed under the terms of the Creative Commons Attribution-ShareAlike 4.0
|
||||
// International. See the License terms at http://creativecommons.org/licenses/by-sa/4.0/legalcode
|
||||
|
||||
using Microsoft.EntityFrameworkCore;
|
||||
|
||||
namespace ASC.IPSecurity;
|
||||
|
||||
[Scope]
|
||||
@ -52,21 +54,26 @@ public class IPRestrictionsRepository
|
||||
|
||||
public List<string> Save(IEnumerable<string> ips, int tenant)
|
||||
{
|
||||
using var tx = TenantDbContext.Database.BeginTransaction();
|
||||
var strategy = TenantDbContext.Database.CreateExecutionStrategy();
|
||||
|
||||
var restrictions = TenantDbContext.TenantIpRestrictions.Where(r => r.Tenant == tenant).ToList();
|
||||
TenantDbContext.TenantIpRestrictions.RemoveRange(restrictions);
|
||||
|
||||
var ipsList = ips.Select(r => new TenantIpRestrictions
|
||||
strategy.Execute(() =>
|
||||
{
|
||||
Tenant = tenant,
|
||||
Ip = r
|
||||
using var tx = TenantDbContext.Database.BeginTransaction();
|
||||
|
||||
var restrictions = TenantDbContext.TenantIpRestrictions.Where(r => r.Tenant == tenant).ToList();
|
||||
TenantDbContext.TenantIpRestrictions.RemoveRange(restrictions);
|
||||
|
||||
var ipsList = ips.Select(r => new TenantIpRestrictions
|
||||
{
|
||||
Tenant = tenant,
|
||||
Ip = r
|
||||
});
|
||||
|
||||
TenantDbContext.TenantIpRestrictions.AddRange(ipsList);
|
||||
|
||||
tx.Commit();
|
||||
});
|
||||
|
||||
TenantDbContext.TenantIpRestrictions.AddRange(ipsList);
|
||||
|
||||
tx.Commit();
|
||||
|
||||
return ips.ToList();
|
||||
}
|
||||
}
|
||||
|
@ -106,51 +106,56 @@ public class MessagesRepository : IDisposable
|
||||
return;
|
||||
}
|
||||
|
||||
using var scope = _serviceScopeFactory.CreateScope();
|
||||
using var ef = scope.ServiceProvider.GetService<DbContextManager<MessagesContext>>().Get("messages");
|
||||
using var tx = ef.Database.BeginTransaction(IsolationLevel.ReadUncommitted);
|
||||
var dict = new Dictionary<string, ClientInfo>();
|
||||
|
||||
foreach (var message in events)
|
||||
{
|
||||
if (!string.IsNullOrEmpty(message.UAHeader))
|
||||
{
|
||||
try
|
||||
{
|
||||
|
||||
ClientInfo clientInfo;
|
||||
|
||||
if (dict.TryGetValue(message.UAHeader, out clientInfo))
|
||||
{
|
||||
|
||||
}
|
||||
else
|
||||
{
|
||||
_parser = _parser ?? Parser.GetDefault();
|
||||
clientInfo = _parser.Parse(message.UAHeader);
|
||||
dict.Add(message.UAHeader, clientInfo);
|
||||
}
|
||||
|
||||
if (clientInfo != null)
|
||||
{
|
||||
message.Browser = GetBrowser(clientInfo);
|
||||
message.Platform = GetPlatform(clientInfo);
|
||||
}
|
||||
}
|
||||
catch (Exception e)
|
||||
{
|
||||
_logger.ErrorFlushCache(message.Id, e);
|
||||
}
|
||||
}
|
||||
|
||||
// messages with action code < 2000 are related to login-history
|
||||
if ((int)message.Action >= 2000)
|
||||
{
|
||||
AddAuditEvent(message, ef);
|
||||
}
|
||||
}
|
||||
|
||||
tx.Commit();
|
||||
using var scope = _serviceScopeFactory.CreateScope();
|
||||
using var ef = scope.ServiceProvider.GetService<DbContextManager<MessagesContext>>().Get("messages");
|
||||
var strategy = ef.Database.CreateExecutionStrategy();
|
||||
|
||||
strategy.Execute(() =>
|
||||
{
|
||||
using var tx = ef.Database.BeginTransaction(IsolationLevel.ReadUncommitted);
|
||||
var dict = new Dictionary<string, ClientInfo>();
|
||||
|
||||
foreach (var message in events)
|
||||
{
|
||||
if (!string.IsNullOrEmpty(message.UAHeader))
|
||||
{
|
||||
try
|
||||
{
|
||||
|
||||
ClientInfo clientInfo;
|
||||
|
||||
if (dict.TryGetValue(message.UAHeader, out clientInfo))
|
||||
{
|
||||
|
||||
}
|
||||
else
|
||||
{
|
||||
_parser = _parser ?? Parser.GetDefault();
|
||||
clientInfo = _parser.Parse(message.UAHeader);
|
||||
dict.Add(message.UAHeader, clientInfo);
|
||||
}
|
||||
|
||||
if (clientInfo != null)
|
||||
{
|
||||
message.Browser = GetBrowser(clientInfo);
|
||||
message.Platform = GetPlatform(clientInfo);
|
||||
}
|
||||
}
|
||||
catch (Exception e)
|
||||
{
|
||||
_logger.ErrorFlushCache(message.Id, e);
|
||||
}
|
||||
}
|
||||
|
||||
// messages with action code < 2000 are related to login-history
|
||||
if ((int)message.Action >= 2000)
|
||||
{
|
||||
AddAuditEvent(message, ef);
|
||||
}
|
||||
}
|
||||
|
||||
tx.Commit();
|
||||
});
|
||||
}
|
||||
|
||||
private void AddLoginEvent(EventMessage message, MessagesContext dbContext)
|
||||
|
@ -49,29 +49,35 @@ public class DbWorker
|
||||
var _mapper = scope.ServiceProvider.GetRequiredService<IMapper>();
|
||||
|
||||
using var dbContext = scope.ServiceProvider.GetService<DbContextManager<NotifyDbContext>>().Get(_dbid);
|
||||
using var tx = dbContext.Database.BeginTransaction(IsolationLevel.ReadCommitted);
|
||||
|
||||
var notifyQueue = _mapper.Map<NotifyMessage, NotifyQueue>(m);
|
||||
var strategy = dbContext.Database.CreateExecutionStrategy();
|
||||
|
||||
notifyQueue = dbContext.NotifyQueue.Add(notifyQueue).Entity;
|
||||
dbContext.SaveChanges();
|
||||
|
||||
var id = notifyQueue.NotifyId;
|
||||
|
||||
var info = new NotifyInfo
|
||||
strategy.Execute(() =>
|
||||
{
|
||||
NotifyId = id,
|
||||
State = 0,
|
||||
Attempts = 0,
|
||||
ModifyDate = DateTime.UtcNow,
|
||||
Priority = m.Priority
|
||||
};
|
||||
using var tx = dbContext.Database.BeginTransaction(IsolationLevel.ReadCommitted);
|
||||
|
||||
dbContext.NotifyInfo.Add(info);
|
||||
dbContext.SaveChanges();
|
||||
var notifyQueue = _mapper.Map<NotifyMessage, NotifyQueue>(m);
|
||||
|
||||
tx.Commit();
|
||||
notifyQueue = dbContext.NotifyQueue.Add(notifyQueue).Entity;
|
||||
dbContext.SaveChanges();
|
||||
|
||||
var id = notifyQueue.NotifyId;
|
||||
|
||||
var info = new NotifyInfo
|
||||
{
|
||||
NotifyId = id,
|
||||
State = 0,
|
||||
Attempts = 0,
|
||||
ModifyDate = DateTime.UtcNow,
|
||||
Priority = m.Priority
|
||||
};
|
||||
|
||||
dbContext.NotifyInfo.Add(info);
|
||||
dbContext.SaveChanges();
|
||||
|
||||
tx.Commit();
|
||||
});
|
||||
|
||||
return 1;
|
||||
}
|
||||
|
||||
@ -84,8 +90,7 @@ public class DbWorker
|
||||
var _mapper = scope.ServiceProvider.GetRequiredService<IMapper>();
|
||||
|
||||
using var dbContext = scope.ServiceProvider.GetService<DbContextManager<NotifyDbContext>>().Get(_dbid);
|
||||
using var tx = dbContext.Database.BeginTransaction();
|
||||
|
||||
|
||||
var q = dbContext.NotifyQueue
|
||||
.Join(dbContext.NotifyInfo, r => r.NotifyId, r => r.NotifyId, (queue, info) => new { queue, info })
|
||||
.Where(r => r.info.State == (int)MailSendingState.NotSended || r.info.State == (int)MailSendingState.Error && r.info.ModifyDate < DateTime.UtcNow - TimeSpan.Parse(_notifyServiceCfg.Process.AttemptsInterval))
|
||||
@ -113,15 +118,22 @@ public class DbWorker
|
||||
return res;
|
||||
});
|
||||
|
||||
var info = dbContext.NotifyInfo.Where(r => messages.Keys.Any(a => a == r.NotifyId)).ToList();
|
||||
var strategy = dbContext.Database.CreateExecutionStrategy();
|
||||
|
||||
foreach (var i in info)
|
||||
strategy.Execute(() =>
|
||||
{
|
||||
i.State = (int)MailSendingState.Sending;
|
||||
}
|
||||
using var tx = dbContext.Database.BeginTransaction();
|
||||
|
||||
dbContext.SaveChanges();
|
||||
tx.Commit();
|
||||
var info = dbContext.NotifyInfo.Where(r => messages.Keys.Any(a => a == r.NotifyId)).ToList();
|
||||
|
||||
foreach (var i in info)
|
||||
{
|
||||
i.State = (int)MailSendingState.Sending;
|
||||
}
|
||||
|
||||
dbContext.SaveChanges();
|
||||
tx.Commit();
|
||||
});
|
||||
|
||||
return messages;
|
||||
}
|
||||
@ -132,16 +144,21 @@ public class DbWorker
|
||||
using var scope = _serviceScopeFactory.CreateScope();
|
||||
using var dbContext = scope.ServiceProvider.GetService<DbContextManager<NotifyDbContext>>().Get(_dbid);
|
||||
|
||||
var tr = dbContext.Database.BeginTransaction();
|
||||
var info = dbContext.NotifyInfo.Where(r => r.State == 1).ToList();
|
||||
var strategy = dbContext.Database.CreateExecutionStrategy();
|
||||
|
||||
foreach (var i in info)
|
||||
strategy.Execute(() =>
|
||||
{
|
||||
i.State = 0;
|
||||
}
|
||||
var tr = dbContext.Database.BeginTransaction();
|
||||
var info = dbContext.NotifyInfo.Where(r => r.State == 1).ToList();
|
||||
|
||||
dbContext.SaveChanges();
|
||||
tr.Commit();
|
||||
foreach (var i in info)
|
||||
{
|
||||
i.State = 0;
|
||||
}
|
||||
|
||||
dbContext.SaveChanges();
|
||||
tr.Commit();
|
||||
});
|
||||
}
|
||||
|
||||
public void SetState(int id, MailSendingState result)
|
||||
@ -150,38 +167,43 @@ public class DbWorker
|
||||
using var dbContext = scope.ServiceProvider.GetService<DbContextManager<NotifyDbContext>>().Get(_dbid);
|
||||
using var tx = dbContext.Database.BeginTransaction();
|
||||
|
||||
if (result == MailSendingState.Sended)
|
||||
var strategy = dbContext.Database.CreateExecutionStrategy();
|
||||
|
||||
strategy.Execute(() =>
|
||||
{
|
||||
var d = dbContext.NotifyInfo.Where(r => r.NotifyId == id).FirstOrDefault();
|
||||
dbContext.NotifyInfo.Remove(d);
|
||||
dbContext.SaveChanges();
|
||||
}
|
||||
else
|
||||
{
|
||||
if (result == MailSendingState.Error)
|
||||
if (result == MailSendingState.Sended)
|
||||
{
|
||||
var attempts = dbContext.NotifyInfo.Where(r => r.NotifyId == id).Select(r => r.Attempts).FirstOrDefault();
|
||||
if (_notifyServiceCfg.Process.MaxAttempts <= attempts + 1)
|
||||
var d = dbContext.NotifyInfo.Where(r => r.NotifyId == id).FirstOrDefault();
|
||||
dbContext.NotifyInfo.Remove(d);
|
||||
dbContext.SaveChanges();
|
||||
}
|
||||
else
|
||||
{
|
||||
if (result == MailSendingState.Error)
|
||||
{
|
||||
result = MailSendingState.FatalError;
|
||||
var attempts = dbContext.NotifyInfo.Where(r => r.NotifyId == id).Select(r => r.Attempts).FirstOrDefault();
|
||||
if (_notifyServiceCfg.Process.MaxAttempts <= attempts + 1)
|
||||
{
|
||||
result = MailSendingState.FatalError;
|
||||
}
|
||||
}
|
||||
|
||||
var info = dbContext.NotifyInfo
|
||||
.Where(r => r.NotifyId == id)
|
||||
.ToList();
|
||||
|
||||
foreach (var i in info)
|
||||
{
|
||||
i.State = (int)result;
|
||||
i.Attempts += 1;
|
||||
i.ModifyDate = DateTime.UtcNow;
|
||||
}
|
||||
|
||||
dbContext.SaveChanges();
|
||||
}
|
||||
|
||||
var info = dbContext.NotifyInfo
|
||||
.Where(r => r.NotifyId == id)
|
||||
.ToList();
|
||||
|
||||
foreach (var i in info)
|
||||
{
|
||||
i.State = (int)result;
|
||||
i.Attempts += 1;
|
||||
i.ModifyDate = DateTime.UtcNow;
|
||||
}
|
||||
|
||||
dbContext.SaveChanges();
|
||||
}
|
||||
|
||||
tx.Commit();
|
||||
tx.Commit();
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -78,18 +78,23 @@ public class NotifyCleanerService : BackgroundService
|
||||
|
||||
using var scope = _scopeFactory.CreateScope();
|
||||
using var dbContext = scope.ServiceProvider.GetService<DbContextManager<NotifyDbContext>>().Get(_notifyServiceCfg.ConnectionStringName);
|
||||
using var tx = dbContext.Database.BeginTransaction();
|
||||
|
||||
var info = dbContext.NotifyInfo.Where(r => r.ModifyDate < date && r.State == 4).ToList();
|
||||
var queue = dbContext.NotifyQueue.Where(r => r.CreationDate < date).ToList();
|
||||
dbContext.NotifyInfo.RemoveRange(info);
|
||||
dbContext.NotifyQueue.RemoveRange(queue);
|
||||
var strategy = dbContext.Database.CreateExecutionStrategy();
|
||||
|
||||
dbContext.SaveChanges();
|
||||
tx.Commit();
|
||||
strategy.Execute(() =>
|
||||
{
|
||||
using var tx = dbContext.Database.BeginTransaction();
|
||||
|
||||
_logger.InformationClearNotifyMessages(info.Count, queue.Count);
|
||||
var info = dbContext.NotifyInfo.Where(r => r.ModifyDate < date && r.State == 4).ToList();
|
||||
var queue = dbContext.NotifyQueue.Where(r => r.CreationDate < date).ToList();
|
||||
dbContext.NotifyInfo.RemoveRange(info);
|
||||
dbContext.NotifyQueue.RemoveRange(queue);
|
||||
|
||||
dbContext.SaveChanges();
|
||||
tx.Commit();
|
||||
|
||||
_logger.InformationClearNotifyMessages(info.Count, queue.Count);
|
||||
});
|
||||
}
|
||||
catch (ThreadAbortException)
|
||||
{
|
||||
|
@ -390,67 +390,73 @@ internal class FileDao : AbstractDao, IFileDao<int>
|
||||
|
||||
lock (_syncRoot)
|
||||
{
|
||||
using var tx = FilesDbContext.Database.BeginTransaction();
|
||||
|
||||
if (file.Id == default)
|
||||
var strategy = FilesDbContext.Database.CreateExecutionStrategy();
|
||||
|
||||
strategy.Execute(() =>
|
||||
{
|
||||
file.Id = FilesDbContext.Files.Any() ? FilesDbContext.Files.Max(r => r.Id) + 1 : 1;
|
||||
file.Version = 1;
|
||||
file.VersionGroup = 1;
|
||||
isNew = true;
|
||||
}
|
||||
using var tx = FilesDbContext.Database.BeginTransaction();
|
||||
|
||||
file.Title = Global.ReplaceInvalidCharsAndTruncate(file.Title);
|
||||
//make lowerCase
|
||||
file.Title = FileUtility.ReplaceFileExtension(file.Title, FileUtility.GetFileExtension(file.Title));
|
||||
if (file.Id == default)
|
||||
{
|
||||
file.Id = FilesDbContext.Files.Any() ? FilesDbContext.Files.Max(r => r.Id) + 1 : 1;
|
||||
file.Version = 1;
|
||||
file.VersionGroup = 1;
|
||||
isNew = true;
|
||||
}
|
||||
|
||||
file.ModifiedBy = _authContext.CurrentAccount.ID;
|
||||
file.ModifiedOn = _tenantUtil.DateTimeNow();
|
||||
if (file.CreateBy == default)
|
||||
{
|
||||
file.CreateBy = _authContext.CurrentAccount.ID;
|
||||
}
|
||||
file.Title = Global.ReplaceInvalidCharsAndTruncate(file.Title);
|
||||
//make lowerCase
|
||||
file.Title = FileUtility.ReplaceFileExtension(file.Title, FileUtility.GetFileExtension(file.Title));
|
||||
|
||||
if (file.CreateOn == default)
|
||||
{
|
||||
file.CreateOn = _tenantUtil.DateTimeNow();
|
||||
}
|
||||
file.ModifiedBy = _authContext.CurrentAccount.ID;
|
||||
file.ModifiedOn = _tenantUtil.DateTimeNow();
|
||||
if (file.CreateBy == default)
|
||||
{
|
||||
file.CreateBy = _authContext.CurrentAccount.ID;
|
||||
}
|
||||
|
||||
var toUpdate = FilesDbContext.Files
|
||||
.FirstOrDefault(r => r.Id == file.Id && r.CurrentVersion && r.TenantId == TenantID);
|
||||
if (file.CreateOn == default)
|
||||
{
|
||||
file.CreateOn = _tenantUtil.DateTimeNow();
|
||||
}
|
||||
|
||||
if (toUpdate != null)
|
||||
{
|
||||
toUpdate.CurrentVersion = false;
|
||||
var toUpdate = FilesDbContext.Files
|
||||
.FirstOrDefault(r => r.Id == file.Id && r.CurrentVersion && r.TenantId == TenantID);
|
||||
|
||||
if (toUpdate != null)
|
||||
{
|
||||
toUpdate.CurrentVersion = false;
|
||||
FilesDbContext.SaveChanges();
|
||||
}
|
||||
|
||||
toInsert = new DbFile
|
||||
{
|
||||
Id = file.Id,
|
||||
Version = file.Version,
|
||||
VersionGroup = file.VersionGroup,
|
||||
CurrentVersion = true,
|
||||
ParentId = file.ParentId,
|
||||
Title = file.Title,
|
||||
ContentLength = file.ContentLength,
|
||||
Category = (int)file.FilterType,
|
||||
CreateBy = file.CreateBy,
|
||||
CreateOn = _tenantUtil.DateTimeToUtc(file.CreateOn),
|
||||
ModifiedBy = file.ModifiedBy,
|
||||
ModifiedOn = _tenantUtil.DateTimeToUtc(file.ModifiedOn),
|
||||
ConvertedType = file.ConvertedType,
|
||||
Comment = file.Comment,
|
||||
Encrypted = file.Encrypted,
|
||||
Forcesave = file.Forcesave,
|
||||
ThumbnailStatus = file.ThumbnailStatus,
|
||||
TenantId = TenantID
|
||||
};
|
||||
|
||||
FilesDbContext.AddOrUpdate(r => r.Files, toInsert);
|
||||
FilesDbContext.SaveChanges();
|
||||
}
|
||||
|
||||
toInsert = new DbFile
|
||||
{
|
||||
Id = file.Id,
|
||||
Version = file.Version,
|
||||
VersionGroup = file.VersionGroup,
|
||||
CurrentVersion = true,
|
||||
ParentId = file.ParentId,
|
||||
Title = file.Title,
|
||||
ContentLength = file.ContentLength,
|
||||
Category = (int)file.FilterType,
|
||||
CreateBy = file.CreateBy,
|
||||
CreateOn = _tenantUtil.DateTimeToUtc(file.CreateOn),
|
||||
ModifiedBy = file.ModifiedBy,
|
||||
ModifiedOn = _tenantUtil.DateTimeToUtc(file.ModifiedOn),
|
||||
ConvertedType = file.ConvertedType,
|
||||
Comment = file.Comment,
|
||||
Encrypted = file.Encrypted,
|
||||
Forcesave = file.Forcesave,
|
||||
ThumbnailStatus = file.ThumbnailStatus,
|
||||
TenantId = TenantID
|
||||
};
|
||||
|
||||
FilesDbContext.AddOrUpdate(r => r.Files, toInsert);
|
||||
FilesDbContext.SaveChanges();
|
||||
|
||||
tx.Commit();
|
||||
tx.Commit();
|
||||
});
|
||||
|
||||
file.PureTitle = file.Title;
|
||||
|
||||
@ -554,46 +560,51 @@ internal class FileDao : AbstractDao, IFileDao<int>
|
||||
List<int> parentFoldersIds;
|
||||
lock (_syncRoot)
|
||||
{
|
||||
using var tx = FilesDbContext.Database.BeginTransaction();
|
||||
var strategy = FilesDbContext.Database.CreateExecutionStrategy();
|
||||
|
||||
file.Title = Global.ReplaceInvalidCharsAndTruncate(file.Title);
|
||||
//make lowerCase
|
||||
file.Title = FileUtility.ReplaceFileExtension(file.Title, FileUtility.GetFileExtension(file.Title));
|
||||
|
||||
file.ModifiedBy = _authContext.CurrentAccount.ID;
|
||||
file.ModifiedOn = _tenantUtil.DateTimeNow();
|
||||
if (file.CreateBy == default)
|
||||
strategy.Execute(() =>
|
||||
{
|
||||
file.CreateBy = _authContext.CurrentAccount.ID;
|
||||
}
|
||||
using var tx = FilesDbContext.Database.BeginTransaction();
|
||||
|
||||
if (file.CreateOn == default)
|
||||
{
|
||||
file.CreateOn = _tenantUtil.DateTimeNow();
|
||||
}
|
||||
file.Title = Global.ReplaceInvalidCharsAndTruncate(file.Title);
|
||||
//make lowerCase
|
||||
file.Title = FileUtility.ReplaceFileExtension(file.Title, FileUtility.GetFileExtension(file.Title));
|
||||
|
||||
toUpdate = FilesDbContext.Files
|
||||
.FirstOrDefault(r => r.Id == file.Id && r.Version == file.Version && r.TenantId == TenantID);
|
||||
file.ModifiedBy = _authContext.CurrentAccount.ID;
|
||||
file.ModifiedOn = _tenantUtil.DateTimeNow();
|
||||
if (file.CreateBy == default)
|
||||
{
|
||||
file.CreateBy = _authContext.CurrentAccount.ID;
|
||||
}
|
||||
|
||||
toUpdate.Version = file.Version;
|
||||
toUpdate.VersionGroup = file.VersionGroup;
|
||||
toUpdate.ParentId = file.ParentId;
|
||||
toUpdate.Title = file.Title;
|
||||
toUpdate.ContentLength = file.ContentLength;
|
||||
toUpdate.Category = (int)file.FilterType;
|
||||
toUpdate.CreateBy = file.CreateBy;
|
||||
toUpdate.CreateOn = _tenantUtil.DateTimeToUtc(file.CreateOn);
|
||||
toUpdate.ModifiedBy = file.ModifiedBy;
|
||||
toUpdate.ModifiedOn = _tenantUtil.DateTimeToUtc(file.ModifiedOn);
|
||||
toUpdate.ConvertedType = file.ConvertedType;
|
||||
toUpdate.Comment = file.Comment;
|
||||
toUpdate.Encrypted = file.Encrypted;
|
||||
toUpdate.Forcesave = file.Forcesave;
|
||||
toUpdate.ThumbnailStatus = file.ThumbnailStatus;
|
||||
if (file.CreateOn == default)
|
||||
{
|
||||
file.CreateOn = _tenantUtil.DateTimeNow();
|
||||
}
|
||||
|
||||
FilesDbContext.SaveChanges();
|
||||
toUpdate = FilesDbContext.Files
|
||||
.FirstOrDefault(r => r.Id == file.Id && r.Version == file.Version && r.TenantId == TenantID);
|
||||
|
||||
tx.Commit();
|
||||
toUpdate.Version = file.Version;
|
||||
toUpdate.VersionGroup = file.VersionGroup;
|
||||
toUpdate.ParentId = file.ParentId;
|
||||
toUpdate.Title = file.Title;
|
||||
toUpdate.ContentLength = file.ContentLength;
|
||||
toUpdate.Category = (int)file.FilterType;
|
||||
toUpdate.CreateBy = file.CreateBy;
|
||||
toUpdate.CreateOn = _tenantUtil.DateTimeToUtc(file.CreateOn);
|
||||
toUpdate.ModifiedBy = file.ModifiedBy;
|
||||
toUpdate.ModifiedOn = _tenantUtil.DateTimeToUtc(file.ModifiedOn);
|
||||
toUpdate.ConvertedType = file.ConvertedType;
|
||||
toUpdate.Comment = file.Comment;
|
||||
toUpdate.Encrypted = file.Encrypted;
|
||||
toUpdate.Forcesave = file.Forcesave;
|
||||
toUpdate.ThumbnailStatus = file.ThumbnailStatus;
|
||||
|
||||
FilesDbContext.SaveChanges();
|
||||
|
||||
tx.Commit();
|
||||
});
|
||||
|
||||
file.PureTitle = file.Title;
|
||||
|
||||
@ -706,54 +717,59 @@ internal class FileDao : AbstractDao, IFileDao<int>
|
||||
|
||||
private async Task internalDeleteFileAsync(int fileId, bool deleteFolder)
|
||||
{
|
||||
using var tx = await FilesDbContext.Database.BeginTransactionAsync().ConfigureAwait(false);
|
||||
var strategy = FilesDbContext.Database.CreateExecutionStrategy();
|
||||
|
||||
var fromFolders = Query(FilesDbContext.Files)
|
||||
.Where(r => r.Id == fileId)
|
||||
.Select(a => a.ParentId)
|
||||
.Distinct()
|
||||
.AsAsyncEnumerable();
|
||||
|
||||
var toDeleteLinks = Query(FilesDbContext.TagLink).Where(r => r.EntryId == fileId.ToString() && r.EntryType == FileEntryType.File);
|
||||
FilesDbContext.RemoveRange(await toDeleteLinks.ToListAsync());
|
||||
|
||||
var toDeleteFiles = Query(FilesDbContext.Files).Where(r => r.Id == fileId);
|
||||
var toDeleteFile = await toDeleteFiles.FirstOrDefaultAsync(r => r.CurrentVersion).ConfigureAwait(false);
|
||||
|
||||
foreach (var d in toDeleteFiles)
|
||||
await strategy.ExecuteAsync(async () =>
|
||||
{
|
||||
await _factoryIndexer.DeleteAsync(d).ConfigureAwait(false);
|
||||
}
|
||||
using var tx = await FilesDbContext.Database.BeginTransactionAsync().ConfigureAwait(false);
|
||||
|
||||
FilesDbContext.RemoveRange(await toDeleteFiles.ToListAsync());
|
||||
var fromFolders = Query(FilesDbContext.Files)
|
||||
.Where(r => r.Id == fileId)
|
||||
.Select(a => a.ParentId)
|
||||
.Distinct()
|
||||
.AsAsyncEnumerable();
|
||||
|
||||
var tagsToRemove = Query(FilesDbContext.Tag)
|
||||
.Where(r => !Query(FilesDbContext.TagLink).Any(a => a.TagId == r.Id));
|
||||
var toDeleteLinks = Query(FilesDbContext.TagLink).Where(r => r.EntryId == fileId.ToString() && r.EntryType == FileEntryType.File);
|
||||
FilesDbContext.RemoveRange(await toDeleteLinks.ToListAsync());
|
||||
|
||||
FilesDbContext.Tag.RemoveRange(await tagsToRemove.ToListAsync());
|
||||
var toDeleteFiles = Query(FilesDbContext.Files).Where(r => r.Id == fileId);
|
||||
var toDeleteFile = await toDeleteFiles.FirstOrDefaultAsync(r => r.CurrentVersion).ConfigureAwait(false);
|
||||
|
||||
var securityToDelete = Query(FilesDbContext.Security)
|
||||
.Where(r => r.EntryId == fileId.ToString())
|
||||
.Where(r => r.EntryType == FileEntryType.File);
|
||||
foreach (var d in toDeleteFiles)
|
||||
{
|
||||
await _factoryIndexer.DeleteAsync(d).ConfigureAwait(false);
|
||||
}
|
||||
|
||||
FilesDbContext.Security.RemoveRange(await securityToDelete.ToListAsync());
|
||||
await FilesDbContext.SaveChangesAsync().ConfigureAwait(false);
|
||||
FilesDbContext.RemoveRange(await toDeleteFiles.ToListAsync());
|
||||
|
||||
await tx.CommitAsync().ConfigureAwait(false);
|
||||
var tagsToRemove = Query(FilesDbContext.Tag)
|
||||
.Where(r => !Query(FilesDbContext.TagLink).Any(a => a.TagId == r.Id));
|
||||
|
||||
var forEachTask = fromFolders.ForEachAwaitAsync(async folderId => await RecalculateFilesCountAsync(folderId).ConfigureAwait(false)).ConfigureAwait(false);
|
||||
FilesDbContext.Tag.RemoveRange(await tagsToRemove.ToListAsync());
|
||||
|
||||
if (deleteFolder)
|
||||
{
|
||||
await DeleteFolderAsync(fileId);
|
||||
}
|
||||
var securityToDelete = Query(FilesDbContext.Security)
|
||||
.Where(r => r.EntryId == fileId.ToString())
|
||||
.Where(r => r.EntryType == FileEntryType.File);
|
||||
|
||||
if (toDeleteFile != null)
|
||||
{
|
||||
await _factoryIndexer.DeleteAsync(toDeleteFile).ConfigureAwait(false);
|
||||
}
|
||||
FilesDbContext.Security.RemoveRange(await securityToDelete.ToListAsync());
|
||||
await FilesDbContext.SaveChangesAsync().ConfigureAwait(false);
|
||||
|
||||
await forEachTask;
|
||||
await tx.CommitAsync().ConfigureAwait(false);
|
||||
|
||||
var forEachTask = fromFolders.ForEachAwaitAsync(async folderId => await RecalculateFilesCountAsync(folderId).ConfigureAwait(false)).ConfigureAwait(false);
|
||||
|
||||
if (deleteFolder)
|
||||
{
|
||||
await DeleteFolderAsync(fileId);
|
||||
}
|
||||
|
||||
if (toDeleteFile != null)
|
||||
{
|
||||
await _factoryIndexer.DeleteAsync(toDeleteFile).ConfigureAwait(false);
|
||||
}
|
||||
|
||||
await forEachTask;
|
||||
});
|
||||
}
|
||||
|
||||
public Task<bool> IsExistAsync(string title, object folderId)
|
||||
@ -807,9 +823,7 @@ internal class FileDao : AbstractDao, IFileDao<int>
|
||||
|
||||
var trashIdTask = _globalFolder.GetFolderTrashAsync<int>(_daoFactory);
|
||||
|
||||
using (var tx = await FilesDbContext.Database.BeginTransactionAsync().ConfigureAwait(false))
|
||||
{
|
||||
var fromFolders = await Query(FilesDbContext.Files)
|
||||
var fromFolders = await Query(FilesDbContext.Files)
|
||||
.Where(r => r.Id == fileId)
|
||||
.Select(a => a.ParentId)
|
||||
.Distinct()
|
||||
@ -817,33 +831,42 @@ internal class FileDao : AbstractDao, IFileDao<int>
|
||||
.ToListAsync()
|
||||
.ConfigureAwait(false);
|
||||
|
||||
toUpdate = await Query(FilesDbContext.Files)
|
||||
.Where(r => r.Id == fileId)
|
||||
.ToListAsync()
|
||||
.ConfigureAwait(false);
|
||||
toUpdate = await Query(FilesDbContext.Files)
|
||||
.Where(r => r.Id == fileId)
|
||||
.ToListAsync()
|
||||
.ConfigureAwait(false);
|
||||
|
||||
foreach (var f in toUpdate)
|
||||
|
||||
var strategy = FilesDbContext.Database.CreateExecutionStrategy();
|
||||
|
||||
await strategy.ExecuteAsync(async () =>
|
||||
{
|
||||
using (var tx = await FilesDbContext.Database.BeginTransactionAsync().ConfigureAwait(false))
|
||||
{
|
||||
f.ParentId = toFolderId;
|
||||
|
||||
var trashId = await trashIdTask;
|
||||
if (trashId.Equals(toFolderId))
|
||||
foreach (var f in toUpdate)
|
||||
{
|
||||
f.ModifiedBy = _authContext.CurrentAccount.ID;
|
||||
f.ModifiedOn = DateTime.UtcNow;
|
||||
f.ParentId = toFolderId;
|
||||
|
||||
var trashId = await trashIdTask;
|
||||
if (trashId.Equals(toFolderId))
|
||||
{
|
||||
f.ModifiedBy = _authContext.CurrentAccount.ID;
|
||||
f.ModifiedOn = DateTime.UtcNow;
|
||||
}
|
||||
}
|
||||
|
||||
await FilesDbContext.SaveChangesAsync().ConfigureAwait(false);
|
||||
await tx.CommitAsync().ConfigureAwait(false);
|
||||
|
||||
foreach (var f in fromFolders)
|
||||
{
|
||||
await RecalculateFilesCountAsync(f).ConfigureAwait(false);
|
||||
}
|
||||
|
||||
await RecalculateFilesCountAsync(toFolderId).ConfigureAwait(false);
|
||||
}
|
||||
|
||||
await FilesDbContext.SaveChangesAsync().ConfigureAwait(false);
|
||||
await tx.CommitAsync().ConfigureAwait(false);
|
||||
|
||||
foreach (var f in fromFolders)
|
||||
{
|
||||
await RecalculateFilesCountAsync(f).ConfigureAwait(false);
|
||||
}
|
||||
|
||||
await RecalculateFilesCountAsync(toFolderId).ConfigureAwait(false);
|
||||
}
|
||||
});
|
||||
|
||||
var parentFoldersTask =
|
||||
FilesDbContext.Tree
|
||||
@ -992,29 +1015,34 @@ internal class FileDao : AbstractDao, IFileDao<int>
|
||||
|
||||
public async Task ContinueVersionAsync(int fileId, int fileVersion)
|
||||
{
|
||||
using var tx = await FilesDbContext.Database.BeginTransactionAsync().ConfigureAwait(false);
|
||||
var strategy = FilesDbContext.Database.CreateExecutionStrategy();
|
||||
|
||||
var versionGroup = await Query(FilesDbContext.Files)
|
||||
.AsNoTracking()
|
||||
.Where(r => r.Id == fileId)
|
||||
.Where(r => r.Version == fileVersion)
|
||||
.Select(r => r.VersionGroup)
|
||||
.FirstOrDefaultAsync()
|
||||
.ConfigureAwait(false);
|
||||
|
||||
var toUpdate = Query(FilesDbContext.Files)
|
||||
.Where(r => r.Id == fileId)
|
||||
.Where(r => r.Version > fileVersion)
|
||||
.Where(r => r.VersionGroup > versionGroup);
|
||||
|
||||
foreach (var f in toUpdate)
|
||||
await strategy.ExecuteAsync(async () =>
|
||||
{
|
||||
f.VersionGroup -= 1;
|
||||
}
|
||||
using var tx = await FilesDbContext.Database.BeginTransactionAsync().ConfigureAwait(false);
|
||||
|
||||
await FilesDbContext.SaveChangesAsync().ConfigureAwait(false);
|
||||
var versionGroup = await Query(FilesDbContext.Files)
|
||||
.AsNoTracking()
|
||||
.Where(r => r.Id == fileId)
|
||||
.Where(r => r.Version == fileVersion)
|
||||
.Select(r => r.VersionGroup)
|
||||
.FirstOrDefaultAsync()
|
||||
.ConfigureAwait(false);
|
||||
|
||||
await tx.CommitAsync().ConfigureAwait(false);
|
||||
var toUpdate = Query(FilesDbContext.Files)
|
||||
.Where(r => r.Id == fileId)
|
||||
.Where(r => r.Version > fileVersion)
|
||||
.Where(r => r.VersionGroup > versionGroup);
|
||||
|
||||
foreach (var f in toUpdate)
|
||||
{
|
||||
f.VersionGroup -= 1;
|
||||
}
|
||||
|
||||
await FilesDbContext.SaveChangesAsync().ConfigureAwait(false);
|
||||
|
||||
await tx.CommitAsync().ConfigureAwait(false);
|
||||
});
|
||||
}
|
||||
|
||||
public bool UseTrashForRemove(File<int> file)
|
||||
|
@ -303,6 +303,32 @@ internal class FolderDao : AbstractDao, IFolderDao<int>
|
||||
}
|
||||
|
||||
public async Task<int> InternalSaveFolderAsync(Folder<int> folder, IDbContextTransaction transaction)
|
||||
{
|
||||
var folderId = folder.Id;
|
||||
|
||||
if (transaction == null)
|
||||
{
|
||||
var strategy = FilesDbContext.Database.CreateExecutionStrategy();
|
||||
|
||||
await strategy.ExecuteAsync(async () =>
|
||||
{
|
||||
using var tx = await FilesDbContext.Database.BeginTransactionAsync();
|
||||
|
||||
folderId = await InternalSaveFolderToDbAsync(folder);
|
||||
|
||||
await tx.CommitAsync().ConfigureAwait(false);
|
||||
});
|
||||
}
|
||||
else
|
||||
{
|
||||
folderId = await InternalSaveFolderToDbAsync(folder);
|
||||
}
|
||||
|
||||
//FactoryIndexer.IndexAsync(FoldersWrapper.GetFolderWrapper(ServiceProvider, folder));
|
||||
return folderId;
|
||||
}
|
||||
|
||||
public async Task<int> InternalSaveFolderToDbAsync(Folder<int> folder)
|
||||
{
|
||||
folder.Title = Global.ReplaceInvalidCharsAndTruncate(folder.Title);
|
||||
|
||||
@ -320,8 +346,6 @@ internal class FolderDao : AbstractDao, IFolderDao<int>
|
||||
|
||||
var isnew = false;
|
||||
|
||||
var tx = transaction ?? FilesDbContext.Database.BeginTransaction();
|
||||
|
||||
if (folder.Id != default && await IsExistAsync(folder.Id).ConfigureAwait(false))
|
||||
{
|
||||
var toUpdate = await Query(FilesDbContext.Folders)
|
||||
@ -399,19 +423,13 @@ internal class FolderDao : AbstractDao, IFolderDao<int>
|
||||
await FilesDbContext.SaveChangesAsync().ConfigureAwait(false);
|
||||
}
|
||||
|
||||
if (transaction == null)
|
||||
{
|
||||
await tx.CommitAsync().ConfigureAwait(false);
|
||||
tx.Dispose();
|
||||
}
|
||||
|
||||
if (isnew)
|
||||
{
|
||||
await RecalculateFoldersCountAsync(folder.Id).ConfigureAwait(false);
|
||||
}
|
||||
|
||||
//FactoryIndexer.IndexAsync(FoldersWrapper.GetFolderWrapper(ServiceProvider, folder));
|
||||
return folder.Id;
|
||||
|
||||
}
|
||||
|
||||
private Task<bool> IsExistAsync(int folderId)
|
||||
@ -432,66 +450,70 @@ internal class FolderDao : AbstractDao, IFolderDao<int>
|
||||
|
||||
private async Task InternalDeleteFolderAsync(int id)
|
||||
{
|
||||
using var tx = FilesDbContext.Database.BeginTransaction();
|
||||
var subfolders =
|
||||
await FilesDbContext.Tree
|
||||
.AsQueryable()
|
||||
.Where(r => r.ParentId == id)
|
||||
.Select(r => r.FolderId)
|
||||
.ToListAsync().ConfigureAwait(false);
|
||||
var strategy = FilesDbContext.Database.CreateExecutionStrategy();
|
||||
|
||||
if (!subfolders.Contains(id))
|
||||
await strategy.ExecuteAsync(async () =>
|
||||
{
|
||||
subfolders.Add(id); // chashed folder_tree
|
||||
}
|
||||
using var tx = await FilesDbContext.Database.BeginTransactionAsync();
|
||||
var subfolders =
|
||||
await FilesDbContext.Tree
|
||||
.AsQueryable()
|
||||
.Where(r => r.ParentId == id)
|
||||
.Select(r => r.FolderId)
|
||||
.ToListAsync().ConfigureAwait(false);
|
||||
|
||||
var parent = await Query(FilesDbContext.Folders)
|
||||
.Where(r => r.Id == id)
|
||||
.Select(r => r.ParentId)
|
||||
.FirstOrDefaultAsync().ConfigureAwait(false);
|
||||
if (!subfolders.Contains(id))
|
||||
{
|
||||
subfolders.Add(id); // chashed folder_tree
|
||||
}
|
||||
|
||||
var folderToDelete = await Query(FilesDbContext.Folders).Where(r => subfolders.Contains(r.Id)).ToListAsync();
|
||||
FilesDbContext.Folders.RemoveRange(folderToDelete);
|
||||
var parent = await Query(FilesDbContext.Folders)
|
||||
.Where(r => r.Id == id)
|
||||
.Select(r => r.ParentId)
|
||||
.FirstOrDefaultAsync().ConfigureAwait(false);
|
||||
|
||||
foreach (var f in folderToDelete)
|
||||
{
|
||||
await _factoryIndexer.DeleteAsync(f).ConfigureAwait(false);
|
||||
}
|
||||
var folderToDelete = await Query(FilesDbContext.Folders).Where(r => subfolders.Contains(r.Id)).ToListAsync();
|
||||
FilesDbContext.Folders.RemoveRange(folderToDelete);
|
||||
|
||||
var treeToDelete = await FilesDbContext.Tree.AsQueryable().Where(r => subfolders.Contains(r.FolderId)).ToListAsync();
|
||||
FilesDbContext.Tree.RemoveRange(treeToDelete);
|
||||
foreach (var f in folderToDelete)
|
||||
{
|
||||
await _factoryIndexer.DeleteAsync(f).ConfigureAwait(false);
|
||||
}
|
||||
|
||||
var subfoldersStrings = subfolders.Select(r => r.ToString()).ToList();
|
||||
var linkToDelete = await Query(FilesDbContext.TagLink)
|
||||
.Where(r => subfoldersStrings.Contains(r.EntryId))
|
||||
.Where(r => r.EntryType == FileEntryType.Folder)
|
||||
.ToListAsync();
|
||||
FilesDbContext.TagLink.RemoveRange(linkToDelete);
|
||||
var treeToDelete = await FilesDbContext.Tree.AsQueryable().Where(r => subfolders.Contains(r.FolderId)).ToListAsync();
|
||||
FilesDbContext.Tree.RemoveRange(treeToDelete);
|
||||
|
||||
var tagsToRemove = await Query(FilesDbContext.Tag)
|
||||
.Where(r => !Query(FilesDbContext.TagLink).Any(a => a.TagId == r.Id))
|
||||
.ToListAsync();
|
||||
|
||||
FilesDbContext.Tag.RemoveRange(tagsToRemove);
|
||||
|
||||
var securityToDelete = await Query(FilesDbContext.Security)
|
||||
var subfoldersStrings = subfolders.Select(r => r.ToString()).ToList();
|
||||
var linkToDelete = await Query(FilesDbContext.TagLink)
|
||||
.Where(r => subfoldersStrings.Contains(r.EntryId))
|
||||
.Where(r => r.EntryType == FileEntryType.Folder)
|
||||
.ToListAsync();
|
||||
FilesDbContext.TagLink.RemoveRange(linkToDelete);
|
||||
|
||||
FilesDbContext.Security.RemoveRange(securityToDelete);
|
||||
await FilesDbContext.SaveChangesAsync().ConfigureAwait(false);
|
||||
var tagsToRemove = await Query(FilesDbContext.Tag)
|
||||
.Where(r => !Query(FilesDbContext.TagLink).Any(a => a.TagId == r.Id))
|
||||
.ToListAsync();
|
||||
|
||||
var bunchToDelete = await Query(FilesDbContext.BunchObjects)
|
||||
.Where(r => r.LeftNode == id.ToString())
|
||||
.ToListAsync();
|
||||
FilesDbContext.Tag.RemoveRange(tagsToRemove);
|
||||
|
||||
FilesDbContext.RemoveRange(bunchToDelete);
|
||||
await FilesDbContext.SaveChangesAsync().ConfigureAwait(false);
|
||||
var securityToDelete = await Query(FilesDbContext.Security)
|
||||
.Where(r => subfoldersStrings.Contains(r.EntryId))
|
||||
.Where(r => r.EntryType == FileEntryType.Folder)
|
||||
.ToListAsync();
|
||||
|
||||
await tx.CommitAsync().ConfigureAwait(false);
|
||||
FilesDbContext.Security.RemoveRange(securityToDelete);
|
||||
await FilesDbContext.SaveChangesAsync().ConfigureAwait(false);
|
||||
|
||||
await RecalculateFoldersCountAsync(parent).ConfigureAwait(false);
|
||||
var bunchToDelete = await Query(FilesDbContext.BunchObjects)
|
||||
.Where(r => r.LeftNode == id.ToString())
|
||||
.ToListAsync();
|
||||
|
||||
FilesDbContext.RemoveRange(bunchToDelete);
|
||||
await FilesDbContext.SaveChangesAsync().ConfigureAwait(false);
|
||||
|
||||
await tx.CommitAsync().ConfigureAwait(false);
|
||||
await RecalculateFoldersCountAsync(parent).ConfigureAwait(false);
|
||||
});
|
||||
|
||||
//FactoryIndexer.DeleteAsync(new FoldersWrapper { Id = id });
|
||||
}
|
||||
@ -513,86 +535,93 @@ internal class FolderDao : AbstractDao, IFolderDao<int>
|
||||
|
||||
public async Task<int> MoveFolderAsync(int folderId, int toFolderId, CancellationToken? cancellationToken)
|
||||
{
|
||||
using (var tx = FilesDbContext.Database.BeginTransaction())
|
||||
var strategy = FilesDbContext.Database.CreateExecutionStrategy();
|
||||
|
||||
await strategy.ExecuteAsync(async () =>
|
||||
{
|
||||
var folder = await GetFolderAsync(folderId).ConfigureAwait(false);
|
||||
|
||||
if (folder.FolderType != FolderType.DEFAULT)
|
||||
using (var tx = await FilesDbContext.Database.BeginTransactionAsync())
|
||||
{
|
||||
throw new ArgumentException("It is forbidden to move the System folder.", nameof(folderId));
|
||||
}
|
||||
var folder = await GetFolderAsync(folderId).ConfigureAwait(false);
|
||||
|
||||
var recalcFolders = new List<int> { toFolderId };
|
||||
var parent = await FilesDbContext.Folders
|
||||
.AsQueryable()
|
||||
.Where(r => r.Id == folderId)
|
||||
.Select(r => r.ParentId)
|
||||
.FirstOrDefaultAsync()
|
||||
.ConfigureAwait(false);
|
||||
|
||||
if (parent != 0 && !recalcFolders.Contains(parent))
|
||||
{
|
||||
recalcFolders.Add(parent);
|
||||
}
|
||||
|
||||
var toUpdate = await Query(FilesDbContext.Folders)
|
||||
.Where(r => r.Id == folderId)
|
||||
.FirstOrDefaultAsync()
|
||||
.ConfigureAwait(false);
|
||||
|
||||
toUpdate.ParentId = toFolderId;
|
||||
toUpdate.ModifiedOn = DateTime.UtcNow;
|
||||
toUpdate.ModifiedBy = _authContext.CurrentAccount.ID;
|
||||
|
||||
await FilesDbContext.SaveChangesAsync().ConfigureAwait(false);
|
||||
|
||||
var subfolders = await FilesDbContext.Tree
|
||||
.AsQueryable()
|
||||
.Where(r => r.ParentId == folderId)
|
||||
.ToDictionaryAsync(r => r.FolderId, r => r.Level)
|
||||
.ConfigureAwait(false);
|
||||
|
||||
var toDelete = await FilesDbContext.Tree
|
||||
.AsQueryable()
|
||||
.Where(r => subfolders.ContainsKey(r.FolderId) && !subfolders.ContainsKey(r.ParentId))
|
||||
.ToListAsync();
|
||||
|
||||
FilesDbContext.Tree.RemoveRange(toDelete);
|
||||
await FilesDbContext.SaveChangesAsync().ConfigureAwait(false);
|
||||
|
||||
var toInsert = await FilesDbContext.Tree
|
||||
.AsQueryable()
|
||||
.Where(r => r.FolderId == toFolderId)
|
||||
.OrderBy(r => r.Level)
|
||||
.ToListAsync()
|
||||
.ConfigureAwait(false);
|
||||
|
||||
foreach (var subfolder in subfolders)
|
||||
{
|
||||
foreach (var f in toInsert)
|
||||
if (folder.FolderType != FolderType.DEFAULT)
|
||||
{
|
||||
var newTree = new DbFolderTree
|
||||
throw new ArgumentException("It is forbidden to move the System folder.", nameof(folderId));
|
||||
}
|
||||
|
||||
var recalcFolders = new List<int> { toFolderId };
|
||||
var parent = await FilesDbContext.Folders
|
||||
.AsQueryable()
|
||||
.Where(r => r.Id == folderId)
|
||||
.Select(r => r.ParentId)
|
||||
.FirstOrDefaultAsync()
|
||||
.ConfigureAwait(false);
|
||||
|
||||
if (parent != 0 && !recalcFolders.Contains(parent))
|
||||
{
|
||||
recalcFolders.Add(parent);
|
||||
}
|
||||
|
||||
var toUpdate = await Query(FilesDbContext.Folders)
|
||||
.Where(r => r.Id == folderId)
|
||||
.FirstOrDefaultAsync()
|
||||
.ConfigureAwait(false);
|
||||
|
||||
toUpdate.ParentId = toFolderId;
|
||||
toUpdate.ModifiedOn = DateTime.UtcNow;
|
||||
toUpdate.ModifiedBy = _authContext.CurrentAccount.ID;
|
||||
|
||||
await FilesDbContext.SaveChangesAsync().ConfigureAwait(false);
|
||||
|
||||
var subfolders = await FilesDbContext.Tree
|
||||
.AsQueryable()
|
||||
.Where(r => r.ParentId == folderId)
|
||||
.ToDictionaryAsync(r => r.FolderId, r => r.Level)
|
||||
.ConfigureAwait(false);
|
||||
|
||||
#pragma warning disable CA1841 // Prefer Dictionary.Contains methods
|
||||
var toDelete = await FilesDbContext.Tree
|
||||
.AsQueryable()
|
||||
.Where(r => subfolders.Keys.Contains(r.FolderId) && !subfolders.Keys.Contains(r.ParentId))
|
||||
.ToListAsync();
|
||||
#pragma warning restore CA1841 // Prefer Dictionary.Contains methods
|
||||
|
||||
FilesDbContext.Tree.RemoveRange(toDelete);
|
||||
await FilesDbContext.SaveChangesAsync().ConfigureAwait(false);
|
||||
|
||||
var toInsert = await FilesDbContext.Tree
|
||||
.AsQueryable()
|
||||
.Where(r => r.FolderId == toFolderId)
|
||||
.OrderBy(r => r.Level)
|
||||
.ToListAsync()
|
||||
.ConfigureAwait(false);
|
||||
|
||||
foreach (var subfolder in subfolders)
|
||||
{
|
||||
foreach (var f in toInsert)
|
||||
{
|
||||
FolderId = subfolder.Key,
|
||||
ParentId = f.ParentId,
|
||||
Level = subfolder.Value + 1 + f.Level
|
||||
};
|
||||
await FilesDbContext.AddOrUpdateAsync(r => r.Tree, newTree).ConfigureAwait(false);
|
||||
var newTree = new DbFolderTree
|
||||
{
|
||||
FolderId = subfolder.Key,
|
||||
ParentId = f.ParentId,
|
||||
Level = subfolder.Value + 1 + f.Level
|
||||
};
|
||||
await FilesDbContext.AddOrUpdateAsync(r => r.Tree, newTree).ConfigureAwait(false);
|
||||
}
|
||||
}
|
||||
|
||||
await FilesDbContext.SaveChangesAsync().ConfigureAwait(false);
|
||||
await tx.CommitAsync().ConfigureAwait(false);
|
||||
|
||||
foreach (var e in recalcFolders)
|
||||
{
|
||||
await RecalculateFoldersCountAsync(e);
|
||||
}
|
||||
foreach (var e in recalcFolders)
|
||||
{
|
||||
await GetRecalculateFilesCountUpdateAsync(e);
|
||||
}
|
||||
}
|
||||
|
||||
await FilesDbContext.SaveChangesAsync().ConfigureAwait(false);
|
||||
await tx.CommitAsync().ConfigureAwait(false);
|
||||
|
||||
foreach (var e in recalcFolders)
|
||||
{
|
||||
await RecalculateFoldersCountAsync(e);
|
||||
}
|
||||
foreach (var e in recalcFolders)
|
||||
{
|
||||
await GetRecalculateFilesCountUpdateAsync(e);
|
||||
}
|
||||
}
|
||||
});
|
||||
|
||||
return folderId;
|
||||
}
|
||||
@ -966,21 +995,27 @@ internal class FolderDao : AbstractDao, IFolderDao<int>
|
||||
folder.Title = key;
|
||||
break;
|
||||
}
|
||||
using var tx = await FilesDbContext.Database.BeginTransactionAsync().ConfigureAwait(false);//NOTE: Maybe we shouldn't start transaction here at all
|
||||
|
||||
newFolderId = await SaveFolderAsync(folder, tx).ConfigureAwait(false); //Save using our db manager
|
||||
var strategy = FilesDbContext.Database.CreateExecutionStrategy();
|
||||
|
||||
var newBunch = new DbFilesBunchObjects
|
||||
await strategy.ExecuteAsync(async () =>
|
||||
{
|
||||
LeftNode = newFolderId.ToString(),
|
||||
RightNode = key,
|
||||
TenantId = TenantID
|
||||
};
|
||||
using var tx = await FilesDbContext.Database.BeginTransactionAsync().ConfigureAwait(false);//NOTE: Maybe we shouldn't start transaction here at all
|
||||
|
||||
await FilesDbContext.AddOrUpdateAsync(r => r.BunchObjects, newBunch).ConfigureAwait(false);
|
||||
await FilesDbContext.SaveChangesAsync().ConfigureAwait(false);
|
||||
newFolderId = await SaveFolderAsync(folder, tx).ConfigureAwait(false); //Save using our db manager
|
||||
|
||||
await tx.CommitAsync().ConfigureAwait(false); //Commit changes
|
||||
var newBunch = new DbFilesBunchObjects
|
||||
{
|
||||
LeftNode = newFolderId.ToString(),
|
||||
RightNode = key,
|
||||
TenantId = TenantID
|
||||
};
|
||||
|
||||
await FilesDbContext.AddOrUpdateAsync(r => r.BunchObjects, newBunch).ConfigureAwait(false);
|
||||
await FilesDbContext.SaveChangesAsync().ConfigureAwait(false);
|
||||
|
||||
await tx.CommitAsync().ConfigureAwait(false); //Commit changes
|
||||
});
|
||||
}
|
||||
|
||||
folderIds.Add(newFolderId);
|
||||
@ -1062,19 +1097,25 @@ internal class FolderDao : AbstractDao, IFolderDao<int>
|
||||
folder.Title = key;
|
||||
break;
|
||||
}
|
||||
using var tx = await FilesDbContext.Database.BeginTransactionAsync().ConfigureAwait(false); //NOTE: Maybe we shouldn't start transaction here at all
|
||||
newFolderId = await SaveFolderAsync(folder, tx).ConfigureAwait(false); //Save using our db manager
|
||||
var toInsert = new DbFilesBunchObjects
|
||||
|
||||
var strategy = FilesDbContext.Database.CreateExecutionStrategy();
|
||||
|
||||
await strategy.ExecuteAsync(async () =>
|
||||
{
|
||||
LeftNode = newFolderId.ToString(),
|
||||
RightNode = key,
|
||||
TenantId = TenantID
|
||||
};
|
||||
using var tx = await FilesDbContext.Database.BeginTransactionAsync().ConfigureAwait(false); //NOTE: Maybe we shouldn't start transaction here at all
|
||||
newFolderId = await SaveFolderAsync(folder, tx).ConfigureAwait(false); //Save using our db manager
|
||||
var toInsert = new DbFilesBunchObjects
|
||||
{
|
||||
LeftNode = newFolderId.ToString(),
|
||||
RightNode = key,
|
||||
TenantId = TenantID
|
||||
};
|
||||
|
||||
await FilesDbContext.AddOrUpdateAsync(r => r.BunchObjects, toInsert).ConfigureAwait(false);
|
||||
await FilesDbContext.SaveChangesAsync().ConfigureAwait(false);
|
||||
await FilesDbContext.AddOrUpdateAsync(r => r.BunchObjects, toInsert).ConfigureAwait(false);
|
||||
await FilesDbContext.SaveChangesAsync().ConfigureAwait(false);
|
||||
|
||||
await tx.CommitAsync().ConfigureAwait(false); //Commit changes
|
||||
await tx.CommitAsync().ConfigureAwait(false); //Commit changes
|
||||
});
|
||||
}
|
||||
|
||||
return newFolderId;
|
||||
|
@ -64,23 +64,28 @@ internal class SecurityDao<T> : AbstractDao, ISecurityDao<T>
|
||||
|
||||
public async Task DeleteShareRecordsAsync(IEnumerable<FileShareRecord> records)
|
||||
{
|
||||
using var tx = await FilesDbContext.Database.BeginTransactionAsync();
|
||||
var strategy = FilesDbContext.Database.CreateExecutionStrategy();
|
||||
|
||||
foreach (var record in records)
|
||||
await strategy.ExecuteAsync(async () =>
|
||||
{
|
||||
var query = await FilesDbContext.Security
|
||||
.AsQueryable()
|
||||
.Where(r => r.TenantId == record.TenantId)
|
||||
.Where(r => r.EntryType == record.EntryType)
|
||||
.Where(r => r.Subject == record.Subject)
|
||||
.AsAsyncEnumerable()
|
||||
.WhereAwait(async r => r.EntryId == (await MappingIDAsync(record.EntryId)).ToString())
|
||||
.ToListAsync();
|
||||
using var tx = await FilesDbContext.Database.BeginTransactionAsync();
|
||||
|
||||
FilesDbContext.RemoveRange(query);
|
||||
}
|
||||
foreach (var record in records)
|
||||
{
|
||||
var query = await FilesDbContext.Security
|
||||
.AsQueryable()
|
||||
.Where(r => r.TenantId == record.TenantId)
|
||||
.Where(r => r.EntryType == record.EntryType)
|
||||
.Where(r => r.Subject == record.Subject)
|
||||
.AsAsyncEnumerable()
|
||||
.WhereAwait(async r => r.EntryId == (await MappingIDAsync(record.EntryId)).ToString())
|
||||
.ToListAsync();
|
||||
|
||||
await tx.CommitAsync();
|
||||
FilesDbContext.RemoveRange(query);
|
||||
}
|
||||
|
||||
await tx.CommitAsync();
|
||||
});
|
||||
}
|
||||
|
||||
public ValueTask<bool> IsSharedAsync(object entryId, FileEntryType type)
|
||||
@ -101,60 +106,66 @@ internal class SecurityDao<T> : AbstractDao, ISecurityDao<T>
|
||||
return;
|
||||
}
|
||||
|
||||
using var tx = await FilesDbContext.Database.BeginTransactionAsync();
|
||||
var files = new List<string>();
|
||||
var strategy = FilesDbContext.Database.CreateExecutionStrategy();
|
||||
|
||||
if (r.EntryType == FileEntryType.Folder)
|
||||
{
|
||||
var folders = new List<string>();
|
||||
if (int.TryParse(entryId, out var intEntryId))
|
||||
{
|
||||
var foldersInt = await FilesDbContext.Tree
|
||||
.AsQueryable()
|
||||
.Where(r => r.ParentId.ToString() == entryId)
|
||||
.Select(r => r.FolderId)
|
||||
.ToListAsync();
|
||||
await strategy.ExecuteAsync(async () =>
|
||||
{
|
||||
using var tx = await FilesDbContext.Database.BeginTransactionAsync();
|
||||
var files = new List<string>();
|
||||
|
||||
folders.AddRange(foldersInt.Select(folderInt => folderInt.ToString()));
|
||||
files.AddRange(await Query(FilesDbContext.Files).Where(r => foldersInt.Contains(r.ParentId)).Select(r => r.Id.ToString()).ToListAsync());
|
||||
}
|
||||
else
|
||||
{
|
||||
folders.Add(entryId);
|
||||
}
|
||||
if (r.EntryType == FileEntryType.Folder)
|
||||
{
|
||||
var folders = new List<string>();
|
||||
if (int.TryParse(entryId, out var intEntryId))
|
||||
{
|
||||
var foldersInt = await FilesDbContext.Tree
|
||||
.AsQueryable()
|
||||
.Where(r => r.ParentId.ToString() == entryId)
|
||||
.Select(r => r.FolderId)
|
||||
.ToListAsync();
|
||||
|
||||
var toDelete = await FilesDbContext.Security
|
||||
.AsQueryable()
|
||||
.Where(a => a.TenantId == r.TenantId &&
|
||||
folders.Contains(a.EntryId) &&
|
||||
a.EntryType == FileEntryType.Folder &&
|
||||
a.Subject == r.Subject)
|
||||
.ToListAsync();
|
||||
folders.AddRange(foldersInt.Select(folderInt => folderInt.ToString()));
|
||||
files.AddRange(await Query(FilesDbContext.Files).Where(r => foldersInt.Contains(r.ParentId)).Select(r => r.Id.ToString()).ToListAsync());
|
||||
}
|
||||
else
|
||||
{
|
||||
folders.Add(entryId);
|
||||
}
|
||||
|
||||
FilesDbContext.Security.RemoveRange(toDelete);
|
||||
await FilesDbContext.SaveChangesAsync();
|
||||
var toDelete = await FilesDbContext.Security
|
||||
.AsQueryable()
|
||||
.Where(a => a.TenantId == r.TenantId &&
|
||||
folders.Contains(a.EntryId) &&
|
||||
a.EntryType == FileEntryType.Folder &&
|
||||
a.Subject == r.Subject)
|
||||
.ToListAsync();
|
||||
|
||||
}
|
||||
else
|
||||
{
|
||||
files.Add(entryId);
|
||||
}
|
||||
FilesDbContext.Security.RemoveRange(toDelete);
|
||||
await FilesDbContext.SaveChangesAsync();
|
||||
|
||||
if (0 < files.Count)
|
||||
{
|
||||
var toDelete = await FilesDbContext.Security
|
||||
.AsQueryable()
|
||||
.Where(a => a.TenantId == r.TenantId &&
|
||||
files.Contains(a.EntryId) &&
|
||||
a.EntryType == FileEntryType.File &&
|
||||
a.Subject == r.Subject)
|
||||
.ToListAsync();
|
||||
}
|
||||
else
|
||||
{
|
||||
files.Add(entryId);
|
||||
}
|
||||
|
||||
FilesDbContext.Security.RemoveRange(toDelete);
|
||||
await FilesDbContext.SaveChangesAsync();
|
||||
}
|
||||
if (0 < files.Count)
|
||||
{
|
||||
var toDelete = await FilesDbContext.Security
|
||||
.AsQueryable()
|
||||
.Where(a => a.TenantId == r.TenantId &&
|
||||
files.Contains(a.EntryId) &&
|
||||
a.EntryType == FileEntryType.File &&
|
||||
a.Subject == r.Subject)
|
||||
.ToListAsync();
|
||||
|
||||
await tx.CommitAsync();
|
||||
FilesDbContext.Security.RemoveRange(toDelete);
|
||||
await FilesDbContext.SaveChangesAsync();
|
||||
}
|
||||
|
||||
await tx.CommitAsync();
|
||||
|
||||
});
|
||||
}
|
||||
else
|
||||
{
|
||||
@ -363,18 +374,23 @@ internal class SecurityDao<T> : AbstractDao, ISecurityDao<T>
|
||||
|
||||
public async Task RemoveSubjectAsync(Guid subject)
|
||||
{
|
||||
using var tr = await FilesDbContext.Database.BeginTransactionAsync();
|
||||
var strategy = FilesDbContext.Database.CreateExecutionStrategy();
|
||||
|
||||
var toDelete1 = await FilesDbContext.Security.AsQueryable().Where(r => r.Subject == subject).ToListAsync();
|
||||
var toDelete2 = await FilesDbContext.Security.AsQueryable().Where(r => r.Owner == subject).ToListAsync();
|
||||
await strategy.ExecuteAsync(async () =>
|
||||
{
|
||||
using var tr = await FilesDbContext.Database.BeginTransactionAsync();
|
||||
|
||||
FilesDbContext.RemoveRange(toDelete1);
|
||||
await FilesDbContext.SaveChangesAsync();
|
||||
var toDelete1 = await FilesDbContext.Security.AsQueryable().Where(r => r.Subject == subject).ToListAsync();
|
||||
var toDelete2 = await FilesDbContext.Security.AsQueryable().Where(r => r.Owner == subject).ToListAsync();
|
||||
|
||||
FilesDbContext.RemoveRange(toDelete2);
|
||||
await FilesDbContext.SaveChangesAsync();
|
||||
FilesDbContext.RemoveRange(toDelete1);
|
||||
await FilesDbContext.SaveChangesAsync();
|
||||
|
||||
await tr.CommitAsync();
|
||||
FilesDbContext.RemoveRange(toDelete2);
|
||||
await FilesDbContext.SaveChangesAsync();
|
||||
|
||||
await tr.CommitAsync();
|
||||
});
|
||||
}
|
||||
|
||||
private IQueryable<DbFilesSecurity> GetQuery(Expression<Func<DbFilesSecurity, bool>> where = null)
|
||||
|
@ -233,15 +233,20 @@ internal class TagDao<T> : AbstractDao, ITagDao<T>
|
||||
|
||||
lock (_syncRoot)
|
||||
{
|
||||
using var tx = FilesDbContext.Database.BeginTransaction();
|
||||
DeleteTagsBeforeSave();
|
||||
var strategy = FilesDbContext.Database.CreateExecutionStrategy();
|
||||
|
||||
var createOn = _tenantUtil.DateTimeToUtc(_tenantUtil.DateTimeNow());
|
||||
var cacheTagId = new Dictionary<string, int>();
|
||||
strategy.Execute(() =>
|
||||
{
|
||||
using var tx = FilesDbContext.Database.BeginTransaction();
|
||||
DeleteTagsBeforeSave();
|
||||
|
||||
result.AddRange(tags.Select(t => SaveTagAsync(t, cacheTagId, createOn).Result));
|
||||
var createOn = _tenantUtil.DateTimeToUtc(_tenantUtil.DateTimeNow());
|
||||
var cacheTagId = new Dictionary<string, int>();
|
||||
|
||||
tx.Commit();
|
||||
result.AddRange(tags.Select(t => SaveTagAsync(t, cacheTagId, createOn).Result));
|
||||
|
||||
tx.Commit();
|
||||
});
|
||||
}
|
||||
|
||||
return result;
|
||||
@ -263,15 +268,20 @@ internal class TagDao<T> : AbstractDao, ITagDao<T>
|
||||
|
||||
lock (_syncRoot)
|
||||
{
|
||||
using var tx = FilesDbContext.Database.BeginTransaction();
|
||||
DeleteTagsBeforeSave();
|
||||
var strategy = FilesDbContext.Database.CreateExecutionStrategy();
|
||||
|
||||
var createOn = _tenantUtil.DateTimeToUtc(_tenantUtil.DateTimeNow());
|
||||
var cacheTagId = new Dictionary<string, int>();
|
||||
strategy.Execute(() =>
|
||||
{
|
||||
using var tx = FilesDbContext.Database.BeginTransaction();
|
||||
DeleteTagsBeforeSave();
|
||||
|
||||
result.Add(SaveTagAsync(tag, cacheTagId, createOn).Result);
|
||||
var createOn = _tenantUtil.DateTimeToUtc(_tenantUtil.DateTimeNow());
|
||||
var cacheTagId = new Dictionary<string, int>();
|
||||
|
||||
tx.Commit();
|
||||
result.Add(SaveTagAsync(tag, cacheTagId, createOn).Result);
|
||||
|
||||
tx.Commit();
|
||||
});
|
||||
}
|
||||
|
||||
return result;
|
||||
@ -368,15 +378,20 @@ internal class TagDao<T> : AbstractDao, ITagDao<T>
|
||||
|
||||
lock (_syncRoot)
|
||||
{
|
||||
using var tx = FilesDbContext.Database.BeginTransaction();
|
||||
var createOn = _tenantUtil.DateTimeToUtc(_tenantUtil.DateTimeNow());
|
||||
var strategy = FilesDbContext.Database.CreateExecutionStrategy();
|
||||
|
||||
foreach (var tag in tags)
|
||||
strategy.Execute(() =>
|
||||
{
|
||||
UpdateNewTagsInDbAsync(tag, createOn).Wait();
|
||||
}
|
||||
using var tx = FilesDbContext.Database.BeginTransaction();
|
||||
var createOn = _tenantUtil.DateTimeToUtc(_tenantUtil.DateTimeNow());
|
||||
|
||||
tx.Commit();
|
||||
foreach (var tag in tags)
|
||||
{
|
||||
UpdateNewTagsInDbAsync(tag, createOn).Wait();
|
||||
}
|
||||
|
||||
tx.Commit();
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
@ -432,13 +447,19 @@ internal class TagDao<T> : AbstractDao, ITagDao<T>
|
||||
|
||||
lock (_syncRoot)
|
||||
{
|
||||
using var tx = FilesDbContext.Database.BeginTransaction();
|
||||
foreach (var t in tags)
|
||||
{
|
||||
RemoveTagInDbAsync(t).Wait();
|
||||
}
|
||||
var strategy = FilesDbContext.Database.CreateExecutionStrategy();
|
||||
|
||||
tx.Commit();
|
||||
strategy.Execute(() =>
|
||||
{
|
||||
using var tx = FilesDbContext.Database.BeginTransaction();
|
||||
|
||||
foreach (var t in tags)
|
||||
{
|
||||
RemoveTagInDbAsync(t).Wait();
|
||||
}
|
||||
|
||||
tx.Commit();
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
@ -451,10 +472,16 @@ internal class TagDao<T> : AbstractDao, ITagDao<T>
|
||||
|
||||
lock (_syncRoot)
|
||||
{
|
||||
using var tx = FilesDbContext.Database.BeginTransaction();
|
||||
RemoveTagInDbAsync(tag).Wait();
|
||||
var strategy = FilesDbContext.Database.CreateExecutionStrategy();
|
||||
|
||||
tx.Commit();
|
||||
strategy.Execute(() =>
|
||||
{
|
||||
using var tx = FilesDbContext.Database.BeginTransaction();
|
||||
RemoveTagInDbAsync(tag).Wait();
|
||||
|
||||
tx.Commit();
|
||||
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -349,40 +349,45 @@ internal class BoxFileDao : BoxDaoBase, IFileDao<string>
|
||||
|
||||
var id = MakeId(boxFile.Id);
|
||||
|
||||
using (var tx = await FilesDbContext.Database.BeginTransactionAsync().ConfigureAwait(false))
|
||||
var strategy = FilesDbContext.Database.CreateExecutionStrategy();
|
||||
|
||||
await strategy.ExecuteAsync(async () =>
|
||||
{
|
||||
var hashIDs = Query(FilesDbContext.ThirdpartyIdMapping)
|
||||
.Where(r => r.Id.StartsWith(id))
|
||||
.Select(r => r.HashId);
|
||||
using (var tx = await FilesDbContext.Database.BeginTransactionAsync().ConfigureAwait(false))
|
||||
{
|
||||
var hashIDs = Query(FilesDbContext.ThirdpartyIdMapping)
|
||||
.Where(r => r.Id.StartsWith(id))
|
||||
.Select(r => r.HashId);
|
||||
|
||||
var link = await Query(FilesDbContext.TagLink)
|
||||
.Where(r => hashIDs.Any(h => h == r.EntryId))
|
||||
.ToListAsync();
|
||||
var link = await Query(FilesDbContext.TagLink)
|
||||
.Where(r => hashIDs.Any(h => h == r.EntryId))
|
||||
.ToListAsync();
|
||||
|
||||
FilesDbContext.TagLink.RemoveRange(link);
|
||||
await FilesDbContext.SaveChangesAsync().ConfigureAwait(false);
|
||||
FilesDbContext.TagLink.RemoveRange(link);
|
||||
await FilesDbContext.SaveChangesAsync().ConfigureAwait(false);
|
||||
|
||||
var tagsToRemove = from ft in FilesDbContext.Tag
|
||||
join ftl in FilesDbContext.TagLink.DefaultIfEmpty() on new { TenantId = ft.TenantId, Id = ft.Id } equals new { TenantId = ftl.TenantId, Id = ftl.TagId }
|
||||
where ftl == null
|
||||
select ft;
|
||||
var tagsToRemove = from ft in FilesDbContext.Tag
|
||||
join ftl in FilesDbContext.TagLink.DefaultIfEmpty() on new { TenantId = ft.TenantId, Id = ft.Id } equals new { TenantId = ftl.TenantId, Id = ftl.TagId }
|
||||
where ftl == null
|
||||
select ft;
|
||||
|
||||
FilesDbContext.Tag.RemoveRange(await tagsToRemove.ToListAsync());
|
||||
FilesDbContext.Tag.RemoveRange(await tagsToRemove.ToListAsync());
|
||||
|
||||
var securityToDelete = Query(FilesDbContext.Security)
|
||||
.Where(r => hashIDs.Any(h => h == r.EntryId));
|
||||
var securityToDelete = Query(FilesDbContext.Security)
|
||||
.Where(r => hashIDs.Any(h => h == r.EntryId));
|
||||
|
||||
FilesDbContext.Security.RemoveRange(await securityToDelete.ToListAsync());
|
||||
await FilesDbContext.SaveChangesAsync().ConfigureAwait(false);
|
||||
FilesDbContext.Security.RemoveRange(await securityToDelete.ToListAsync());
|
||||
await FilesDbContext.SaveChangesAsync().ConfigureAwait(false);
|
||||
|
||||
var mappingToDelete = Query(FilesDbContext.ThirdpartyIdMapping)
|
||||
.Where(r => hashIDs.Any(h => h == r.HashId));
|
||||
var mappingToDelete = Query(FilesDbContext.ThirdpartyIdMapping)
|
||||
.Where(r => hashIDs.Any(h => h == r.HashId));
|
||||
|
||||
FilesDbContext.ThirdpartyIdMapping.RemoveRange(await mappingToDelete.ToListAsync());
|
||||
await FilesDbContext.SaveChangesAsync().ConfigureAwait(false);
|
||||
FilesDbContext.ThirdpartyIdMapping.RemoveRange(await mappingToDelete.ToListAsync());
|
||||
await FilesDbContext.SaveChangesAsync().ConfigureAwait(false);
|
||||
|
||||
await tx.CommitAsync().ConfigureAwait(false);
|
||||
}
|
||||
await tx.CommitAsync().ConfigureAwait(false);
|
||||
}
|
||||
});
|
||||
|
||||
if (boxFile is not ErrorFile)
|
||||
{
|
||||
|
@ -225,43 +225,48 @@ internal class BoxFolderDao : BoxDaoBase, IFolderDao<string>
|
||||
var boxFolder = await GetBoxFolderAsync(folderId).ConfigureAwait(false);
|
||||
var id = MakeId(boxFolder);
|
||||
|
||||
using (var tx = await FilesDbContext.Database.BeginTransactionAsync().ConfigureAwait(false))
|
||||
var strategy = FilesDbContext.Database.CreateExecutionStrategy();
|
||||
|
||||
await strategy.ExecuteAsync(async () =>
|
||||
{
|
||||
var hashIDs = await Query(FilesDbContext.ThirdpartyIdMapping)
|
||||
.Where(r => r.Id.StartsWith(id))
|
||||
.Select(r => r.HashId)
|
||||
.ToListAsync()
|
||||
.ConfigureAwait(false);
|
||||
using (var tx = await FilesDbContext.Database.BeginTransactionAsync().ConfigureAwait(false))
|
||||
{
|
||||
var hashIDs = await Query(FilesDbContext.ThirdpartyIdMapping)
|
||||
.Where(r => r.Id.StartsWith(id))
|
||||
.Select(r => r.HashId)
|
||||
.ToListAsync()
|
||||
.ConfigureAwait(false);
|
||||
|
||||
var link = await Query(FilesDbContext.TagLink)
|
||||
.Where(r => hashIDs.Any(h => h == r.EntryId))
|
||||
.ToListAsync()
|
||||
.ConfigureAwait(false);
|
||||
var link = await Query(FilesDbContext.TagLink)
|
||||
.Where(r => hashIDs.Any(h => h == r.EntryId))
|
||||
.ToListAsync()
|
||||
.ConfigureAwait(false);
|
||||
|
||||
FilesDbContext.TagLink.RemoveRange(link);
|
||||
await FilesDbContext.SaveChangesAsync().ConfigureAwait(false);
|
||||
FilesDbContext.TagLink.RemoveRange(link);
|
||||
await FilesDbContext.SaveChangesAsync().ConfigureAwait(false);
|
||||
|
||||
var tagsToRemove = from ft in FilesDbContext.Tag
|
||||
join ftl in FilesDbContext.TagLink.DefaultIfEmpty() on new { TenantId = ft.TenantId, Id = ft.Id } equals new { TenantId = ftl.TenantId, Id = ftl.TagId }
|
||||
where ftl == null
|
||||
select ft;
|
||||
var tagsToRemove = from ft in FilesDbContext.Tag
|
||||
join ftl in FilesDbContext.TagLink.DefaultIfEmpty() on new { TenantId = ft.TenantId, Id = ft.Id } equals new { TenantId = ftl.TenantId, Id = ftl.TagId }
|
||||
where ftl == null
|
||||
select ft;
|
||||
|
||||
FilesDbContext.Tag.RemoveRange(await tagsToRemove.ToListAsync());
|
||||
FilesDbContext.Tag.RemoveRange(await tagsToRemove.ToListAsync());
|
||||
|
||||
var securityToDelete = Query(FilesDbContext.Security)
|
||||
.Where(r => hashIDs.Any(h => h == r.EntryId));
|
||||
var securityToDelete = Query(FilesDbContext.Security)
|
||||
.Where(r => hashIDs.Any(h => h == r.EntryId));
|
||||
|
||||
FilesDbContext.Security.RemoveRange(await securityToDelete.ToListAsync());
|
||||
await FilesDbContext.SaveChangesAsync().ConfigureAwait(false);
|
||||
FilesDbContext.Security.RemoveRange(await securityToDelete.ToListAsync());
|
||||
await FilesDbContext.SaveChangesAsync().ConfigureAwait(false);
|
||||
|
||||
var mappingToDelete = Query(FilesDbContext.ThirdpartyIdMapping)
|
||||
.Where(r => hashIDs.Any(h => h == r.HashId));
|
||||
var mappingToDelete = Query(FilesDbContext.ThirdpartyIdMapping)
|
||||
.Where(r => hashIDs.Any(h => h == r.HashId));
|
||||
|
||||
FilesDbContext.ThirdpartyIdMapping.RemoveRange(await mappingToDelete.ToListAsync());
|
||||
await FilesDbContext.SaveChangesAsync().ConfigureAwait(false);
|
||||
FilesDbContext.ThirdpartyIdMapping.RemoveRange(await mappingToDelete.ToListAsync());
|
||||
await FilesDbContext.SaveChangesAsync().ConfigureAwait(false);
|
||||
|
||||
await tx.CommitAsync().ConfigureAwait(false);
|
||||
}
|
||||
await tx.CommitAsync().ConfigureAwait(false);
|
||||
}
|
||||
});
|
||||
|
||||
if (boxFolder is not ErrorFolder)
|
||||
{
|
||||
|
@ -349,43 +349,49 @@ internal class DropboxFileDao : DropboxDaoBase, IFileDao<string>
|
||||
|
||||
var id = MakeId(dropboxFile);
|
||||
|
||||
using (var tx = await FilesDbContext.Database.BeginTransactionAsync())
|
||||
var strategy = FilesDbContext.Database.CreateExecutionStrategy();
|
||||
|
||||
await strategy.ExecuteAsync(async () =>
|
||||
{
|
||||
var hashIDs = await Query(FilesDbContext.ThirdpartyIdMapping)
|
||||
.Where(r => r.Id.StartsWith(id))
|
||||
.Select(r => r.HashId)
|
||||
.ToListAsync()
|
||||
.ConfigureAwait(false);
|
||||
using (var tx = await FilesDbContext.Database.BeginTransactionAsync())
|
||||
{
|
||||
var hashIDs = await Query(FilesDbContext.ThirdpartyIdMapping)
|
||||
.Where(r => r.Id.StartsWith(id))
|
||||
.Select(r => r.HashId)
|
||||
.ToListAsync()
|
||||
.ConfigureAwait(false);
|
||||
|
||||
var link = await Query(FilesDbContext.TagLink)
|
||||
.Where(r => hashIDs.Any(h => h == r.EntryId))
|
||||
.ToListAsync()
|
||||
.ConfigureAwait(false);
|
||||
var link = await Query(FilesDbContext.TagLink)
|
||||
.Where(r => hashIDs.Any(h => h == r.EntryId))
|
||||
.ToListAsync()
|
||||
.ConfigureAwait(false);
|
||||
|
||||
FilesDbContext.TagLink.RemoveRange(link);
|
||||
await FilesDbContext.SaveChangesAsync().ConfigureAwait(false);
|
||||
FilesDbContext.TagLink.RemoveRange(link);
|
||||
await FilesDbContext.SaveChangesAsync().ConfigureAwait(false);
|
||||
|
||||
var tagsToRemove = from ft in FilesDbContext.Tag
|
||||
join ftl in FilesDbContext.TagLink.DefaultIfEmpty() on new { TenantId = ft.TenantId, Id = ft.Id } equals new { TenantId = ftl.TenantId, Id = ftl.TagId }
|
||||
where ftl == null
|
||||
select ft;
|
||||
var tagsToRemove = from ft in FilesDbContext.Tag
|
||||
join ftl in FilesDbContext.TagLink.DefaultIfEmpty() on new { TenantId = ft.TenantId, Id = ft.Id } equals new { TenantId = ftl.TenantId, Id = ftl.TagId }
|
||||
where ftl == null
|
||||
select ft;
|
||||
|
||||
FilesDbContext.Tag.RemoveRange(await tagsToRemove.ToListAsync());
|
||||
FilesDbContext.Tag.RemoveRange(await tagsToRemove.ToListAsync());
|
||||
|
||||
var securityToDelete = Query(FilesDbContext.Security)
|
||||
.Where(r => hashIDs.Any(h => h == r.EntryId));
|
||||
var securityToDelete = Query(FilesDbContext.Security)
|
||||
.Where(r => hashIDs.Any(h => h == r.EntryId));
|
||||
|
||||
FilesDbContext.Security.RemoveRange(await securityToDelete.ToListAsync());
|
||||
await FilesDbContext.SaveChangesAsync().ConfigureAwait(false);
|
||||
FilesDbContext.Security.RemoveRange(await securityToDelete.ToListAsync());
|
||||
await FilesDbContext.SaveChangesAsync().ConfigureAwait(false);
|
||||
|
||||
var mappingToDelete = Query(FilesDbContext.ThirdpartyIdMapping)
|
||||
.Where(r => hashIDs.Any(h => h == r.HashId));
|
||||
var mappingToDelete = Query(FilesDbContext.ThirdpartyIdMapping)
|
||||
.Where(r => hashIDs.Any(h => h == r.HashId));
|
||||
|
||||
FilesDbContext.ThirdpartyIdMapping.RemoveRange(await mappingToDelete.ToListAsync());
|
||||
await FilesDbContext.SaveChangesAsync().ConfigureAwait(false);
|
||||
FilesDbContext.ThirdpartyIdMapping.RemoveRange(await mappingToDelete.ToListAsync());
|
||||
await FilesDbContext.SaveChangesAsync().ConfigureAwait(false);
|
||||
|
||||
await tx.CommitAsync().ConfigureAwait(false);
|
||||
}
|
||||
});
|
||||
|
||||
await tx.CommitAsync().ConfigureAwait(false);
|
||||
}
|
||||
|
||||
if (dropboxFile is not ErrorFile)
|
||||
{
|
||||
|
@ -224,43 +224,48 @@ internal class DropboxFolderDao : DropboxDaoBase, IFolderDao<string>
|
||||
var dropboxFolder = await GetDropboxFolderAsync(folderId).ConfigureAwait(false);
|
||||
var id = MakeId(dropboxFolder);
|
||||
|
||||
using (var tx = await FilesDbContext.Database.BeginTransactionAsync().ConfigureAwait(false))
|
||||
var strategy = FilesDbContext.Database.CreateExecutionStrategy();
|
||||
|
||||
await strategy.ExecuteAsync(async () =>
|
||||
{
|
||||
var hashIDs = await Query(FilesDbContext.ThirdpartyIdMapping)
|
||||
.Where(r => r.Id.StartsWith(id))
|
||||
.Select(r => r.HashId)
|
||||
.ToListAsync()
|
||||
.ConfigureAwait(false);
|
||||
using (var tx = await FilesDbContext.Database.BeginTransactionAsync().ConfigureAwait(false))
|
||||
{
|
||||
var hashIDs = await Query(FilesDbContext.ThirdpartyIdMapping)
|
||||
.Where(r => r.Id.StartsWith(id))
|
||||
.Select(r => r.HashId)
|
||||
.ToListAsync()
|
||||
.ConfigureAwait(false);
|
||||
|
||||
var link = await Query(FilesDbContext.TagLink)
|
||||
.Where(r => hashIDs.Any(h => h == r.EntryId))
|
||||
.ToListAsync()
|
||||
.ConfigureAwait(false);
|
||||
var link = await Query(FilesDbContext.TagLink)
|
||||
.Where(r => hashIDs.Any(h => h == r.EntryId))
|
||||
.ToListAsync()
|
||||
.ConfigureAwait(false);
|
||||
|
||||
FilesDbContext.TagLink.RemoveRange(link);
|
||||
await FilesDbContext.SaveChangesAsync().ConfigureAwait(false);
|
||||
FilesDbContext.TagLink.RemoveRange(link);
|
||||
await FilesDbContext.SaveChangesAsync().ConfigureAwait(false);
|
||||
|
||||
var tagsToRemove = from ft in FilesDbContext.Tag
|
||||
join ftl in FilesDbContext.TagLink.DefaultIfEmpty() on new { TenantId = ft.TenantId, Id = ft.Id } equals new { TenantId = ftl.TenantId, Id = ftl.TagId }
|
||||
where ftl == null
|
||||
select ft;
|
||||
var tagsToRemove = from ft in FilesDbContext.Tag
|
||||
join ftl in FilesDbContext.TagLink.DefaultIfEmpty() on new { TenantId = ft.TenantId, Id = ft.Id } equals new { TenantId = ftl.TenantId, Id = ftl.TagId }
|
||||
where ftl == null
|
||||
select ft;
|
||||
|
||||
FilesDbContext.Tag.RemoveRange(await tagsToRemove.ToListAsync());
|
||||
FilesDbContext.Tag.RemoveRange(await tagsToRemove.ToListAsync());
|
||||
|
||||
var securityToDelete = Query(FilesDbContext.Security)
|
||||
.Where(r => hashIDs.Any(h => h == r.EntryId));
|
||||
var securityToDelete = Query(FilesDbContext.Security)
|
||||
.Where(r => hashIDs.Any(h => h == r.EntryId));
|
||||
|
||||
FilesDbContext.Security.RemoveRange(await securityToDelete.ToListAsync());
|
||||
await FilesDbContext.SaveChangesAsync().ConfigureAwait(false);
|
||||
FilesDbContext.Security.RemoveRange(await securityToDelete.ToListAsync());
|
||||
await FilesDbContext.SaveChangesAsync().ConfigureAwait(false);
|
||||
|
||||
var mappingToDelete = Query(FilesDbContext.ThirdpartyIdMapping)
|
||||
.Where(r => hashIDs.Any(h => h == r.HashId));
|
||||
var mappingToDelete = Query(FilesDbContext.ThirdpartyIdMapping)
|
||||
.Where(r => hashIDs.Any(h => h == r.HashId));
|
||||
|
||||
FilesDbContext.ThirdpartyIdMapping.RemoveRange(await mappingToDelete.ToListAsync());
|
||||
await FilesDbContext.SaveChangesAsync().ConfigureAwait(false);
|
||||
FilesDbContext.ThirdpartyIdMapping.RemoveRange(await mappingToDelete.ToListAsync());
|
||||
await FilesDbContext.SaveChangesAsync().ConfigureAwait(false);
|
||||
|
||||
await tx.CommitAsync().ConfigureAwait(false);
|
||||
}
|
||||
await tx.CommitAsync().ConfigureAwait(false);
|
||||
}
|
||||
});
|
||||
|
||||
if (dropboxFolder is not ErrorFolder)
|
||||
{
|
||||
|
@ -344,43 +344,48 @@ internal class GoogleDriveFileDao : GoogleDriveDaoBase, IFileDao<string>
|
||||
|
||||
var id = MakeId(driveFile.Id);
|
||||
|
||||
using (var tx = FilesDbContext.Database.BeginTransaction())
|
||||
var strategy = FilesDbContext.Database.CreateExecutionStrategy();
|
||||
|
||||
await strategy.ExecuteAsync(async () =>
|
||||
{
|
||||
var hashIDs = await Query(FilesDbContext.ThirdpartyIdMapping)
|
||||
.Where(r => r.Id.StartsWith(id))
|
||||
.Select(r => r.HashId)
|
||||
.ToListAsync()
|
||||
.ConfigureAwait(false);
|
||||
using (var tx = await FilesDbContext.Database.BeginTransactionAsync())
|
||||
{
|
||||
var hashIDs = await Query(FilesDbContext.ThirdpartyIdMapping)
|
||||
.Where(r => r.Id.StartsWith(id))
|
||||
.Select(r => r.HashId)
|
||||
.ToListAsync()
|
||||
.ConfigureAwait(false);
|
||||
|
||||
var link = await Query(FilesDbContext.TagLink)
|
||||
.Where(r => hashIDs.Any(h => h == r.EntryId))
|
||||
.ToListAsync()
|
||||
.ConfigureAwait(false);
|
||||
var link = await Query(FilesDbContext.TagLink)
|
||||
.Where(r => hashIDs.Any(h => h == r.EntryId))
|
||||
.ToListAsync()
|
||||
.ConfigureAwait(false);
|
||||
|
||||
FilesDbContext.TagLink.RemoveRange(link);
|
||||
await FilesDbContext.SaveChangesAsync().ConfigureAwait(false);
|
||||
FilesDbContext.TagLink.RemoveRange(link);
|
||||
await FilesDbContext.SaveChangesAsync().ConfigureAwait(false);
|
||||
|
||||
var tagsToRemove = from ft in FilesDbContext.Tag
|
||||
join ftl in FilesDbContext.TagLink.DefaultIfEmpty() on new { TenantId = ft.TenantId, Id = ft.Id } equals new { TenantId = ftl.TenantId, Id = ftl.TagId }
|
||||
where ftl == null
|
||||
select ft;
|
||||
var tagsToRemove = from ft in FilesDbContext.Tag
|
||||
join ftl in FilesDbContext.TagLink.DefaultIfEmpty() on new { TenantId = ft.TenantId, Id = ft.Id } equals new { TenantId = ftl.TenantId, Id = ftl.TagId }
|
||||
where ftl == null
|
||||
select ft;
|
||||
|
||||
FilesDbContext.Tag.RemoveRange(await tagsToRemove.ToListAsync());
|
||||
FilesDbContext.Tag.RemoveRange(await tagsToRemove.ToListAsync());
|
||||
|
||||
var securityToDelete = Query(FilesDbContext.Security)
|
||||
.Where(r => hashIDs.Any(h => h == r.EntryId));
|
||||
var securityToDelete = Query(FilesDbContext.Security)
|
||||
.Where(r => hashIDs.Any(h => h == r.EntryId));
|
||||
|
||||
FilesDbContext.Security.RemoveRange(await securityToDelete.ToListAsync());
|
||||
await FilesDbContext.SaveChangesAsync().ConfigureAwait(false);
|
||||
FilesDbContext.Security.RemoveRange(await securityToDelete.ToListAsync());
|
||||
await FilesDbContext.SaveChangesAsync().ConfigureAwait(false);
|
||||
|
||||
var mappingToDelete = Query(FilesDbContext.ThirdpartyIdMapping)
|
||||
.Where(r => hashIDs.Any(h => h == r.HashId));
|
||||
var mappingToDelete = Query(FilesDbContext.ThirdpartyIdMapping)
|
||||
.Where(r => hashIDs.Any(h => h == r.HashId));
|
||||
|
||||
FilesDbContext.ThirdpartyIdMapping.RemoveRange(await mappingToDelete.ToListAsync());
|
||||
await FilesDbContext.SaveChangesAsync().ConfigureAwait(false);
|
||||
FilesDbContext.ThirdpartyIdMapping.RemoveRange(await mappingToDelete.ToListAsync());
|
||||
await FilesDbContext.SaveChangesAsync().ConfigureAwait(false);
|
||||
|
||||
await tx.CommitAsync().ConfigureAwait(false);
|
||||
}
|
||||
await tx.CommitAsync().ConfigureAwait(false);
|
||||
}
|
||||
});
|
||||
|
||||
if (driveFile is not ErrorDriveEntry)
|
||||
{
|
||||
|
@ -214,43 +214,49 @@ internal class GoogleDriveFolderDao : GoogleDriveDaoBase, IFolderDao<string>
|
||||
var driveFolder = await GetDriveEntryAsync(folderId).ConfigureAwait(false);
|
||||
var id = MakeId(driveFolder);
|
||||
|
||||
using (var tx = await FilesDbContext.Database.BeginTransactionAsync().ConfigureAwait(false))
|
||||
var strategy = FilesDbContext.Database.CreateExecutionStrategy();
|
||||
|
||||
await strategy.ExecuteAsync(async () =>
|
||||
{
|
||||
var hashIDs = await Query(FilesDbContext.ThirdpartyIdMapping)
|
||||
.Where(r => r.Id.StartsWith(id))
|
||||
.Select(r => r.HashId)
|
||||
.ToListAsync()
|
||||
.ConfigureAwait(false);
|
||||
using (var tx = await FilesDbContext.Database.BeginTransactionAsync().ConfigureAwait(false))
|
||||
{
|
||||
var hashIDs = await Query(FilesDbContext.ThirdpartyIdMapping)
|
||||
.Where(r => r.Id.StartsWith(id))
|
||||
.Select(r => r.HashId)
|
||||
.ToListAsync()
|
||||
.ConfigureAwait(false);
|
||||
|
||||
var link = await Query(FilesDbContext.TagLink)
|
||||
.Where(r => hashIDs.Any(h => h == r.EntryId))
|
||||
.ToListAsync()
|
||||
.ConfigureAwait(false);
|
||||
var link = await Query(FilesDbContext.TagLink)
|
||||
.Where(r => hashIDs.Any(h => h == r.EntryId))
|
||||
.ToListAsync()
|
||||
.ConfigureAwait(false);
|
||||
|
||||
FilesDbContext.TagLink.RemoveRange(link);
|
||||
await FilesDbContext.SaveChangesAsync().ConfigureAwait(false);
|
||||
FilesDbContext.TagLink.RemoveRange(link);
|
||||
await FilesDbContext.SaveChangesAsync().ConfigureAwait(false);
|
||||
|
||||
var tagsToRemove = from ft in FilesDbContext.Tag
|
||||
join ftl in FilesDbContext.TagLink.DefaultIfEmpty() on new { TenantId = ft.TenantId, Id = ft.Id } equals new { TenantId = ftl.TenantId, Id = ftl.TagId }
|
||||
where ftl == null
|
||||
select ft;
|
||||
var tagsToRemove = from ft in FilesDbContext.Tag
|
||||
join ftl in FilesDbContext.TagLink.DefaultIfEmpty() on new { TenantId = ft.TenantId, Id = ft.Id } equals new { TenantId = ftl.TenantId, Id = ftl.TagId }
|
||||
where ftl == null
|
||||
select ft;
|
||||
|
||||
FilesDbContext.Tag.RemoveRange(await tagsToRemove.ToListAsync());
|
||||
FilesDbContext.Tag.RemoveRange(await tagsToRemove.ToListAsync());
|
||||
|
||||
var securityToDelete = Query(FilesDbContext.Security)
|
||||
.Where(r => hashIDs.Any(h => h == r.EntryId));
|
||||
var securityToDelete = Query(FilesDbContext.Security)
|
||||
.Where(r => hashIDs.Any(h => h == r.EntryId));
|
||||
|
||||
FilesDbContext.Security.RemoveRange(await securityToDelete.ToListAsync());
|
||||
await FilesDbContext.SaveChangesAsync().ConfigureAwait(false);
|
||||
FilesDbContext.Security.RemoveRange(await securityToDelete.ToListAsync());
|
||||
await FilesDbContext.SaveChangesAsync().ConfigureAwait(false);
|
||||
|
||||
var mappingToDelete = Query(FilesDbContext.ThirdpartyIdMapping)
|
||||
.Where(r => hashIDs.Any(h => h == r.HashId));
|
||||
var mappingToDelete = Query(FilesDbContext.ThirdpartyIdMapping)
|
||||
.Where(r => hashIDs.Any(h => h == r.HashId));
|
||||
|
||||
FilesDbContext.ThirdpartyIdMapping.RemoveRange(await mappingToDelete.ToListAsync());
|
||||
await FilesDbContext.SaveChangesAsync().ConfigureAwait(false);
|
||||
FilesDbContext.ThirdpartyIdMapping.RemoveRange(await mappingToDelete.ToListAsync());
|
||||
await FilesDbContext.SaveChangesAsync().ConfigureAwait(false);
|
||||
|
||||
await tx.CommitAsync().ConfigureAwait(false);
|
||||
}
|
||||
});
|
||||
|
||||
await tx.CommitAsync().ConfigureAwait(false);
|
||||
}
|
||||
|
||||
if (driveFolder is not ErrorDriveEntry)
|
||||
{
|
||||
|
@ -352,43 +352,48 @@ internal class OneDriveFileDao : OneDriveDaoBase, IFileDao<string>
|
||||
|
||||
var id = MakeId(onedriveFile.Id);
|
||||
|
||||
using (var tx = await FilesDbContext.Database.BeginTransactionAsync().ConfigureAwait(false))
|
||||
var strategy = FilesDbContext.Database.CreateExecutionStrategy();
|
||||
|
||||
await strategy.ExecuteAsync(async () =>
|
||||
{
|
||||
var hashIDs = await Query(FilesDbContext.ThirdpartyIdMapping)
|
||||
.Where(r => r.Id.StartsWith(id))
|
||||
.Select(r => r.HashId)
|
||||
.ToListAsync()
|
||||
.ConfigureAwait(false);
|
||||
using (var tx = await FilesDbContext.Database.BeginTransactionAsync().ConfigureAwait(false))
|
||||
{
|
||||
var hashIDs = await Query(FilesDbContext.ThirdpartyIdMapping)
|
||||
.Where(r => r.Id.StartsWith(id))
|
||||
.Select(r => r.HashId)
|
||||
.ToListAsync()
|
||||
.ConfigureAwait(false);
|
||||
|
||||
var link = await Query(FilesDbContext.TagLink)
|
||||
.Where(r => hashIDs.Any(h => h == r.EntryId))
|
||||
.ToListAsync()
|
||||
.ConfigureAwait(false);
|
||||
var link = await Query(FilesDbContext.TagLink)
|
||||
.Where(r => hashIDs.Any(h => h == r.EntryId))
|
||||
.ToListAsync()
|
||||
.ConfigureAwait(false);
|
||||
|
||||
FilesDbContext.TagLink.RemoveRange(link);
|
||||
await FilesDbContext.SaveChangesAsync().ConfigureAwait(false);
|
||||
FilesDbContext.TagLink.RemoveRange(link);
|
||||
await FilesDbContext.SaveChangesAsync().ConfigureAwait(false);
|
||||
|
||||
var tagsToRemove = from ft in FilesDbContext.Tag
|
||||
join ftl in FilesDbContext.TagLink.DefaultIfEmpty() on new { TenantId = ft.TenantId, Id = ft.Id } equals new { TenantId = ftl.TenantId, Id = ftl.TagId }
|
||||
where ftl == null
|
||||
select ft;
|
||||
var tagsToRemove = from ft in FilesDbContext.Tag
|
||||
join ftl in FilesDbContext.TagLink.DefaultIfEmpty() on new { TenantId = ft.TenantId, Id = ft.Id } equals new { TenantId = ftl.TenantId, Id = ftl.TagId }
|
||||
where ftl == null
|
||||
select ft;
|
||||
|
||||
FilesDbContext.Tag.RemoveRange(await tagsToRemove.ToListAsync());
|
||||
FilesDbContext.Tag.RemoveRange(await tagsToRemove.ToListAsync());
|
||||
|
||||
var securityToDelete = Query(FilesDbContext.Security)
|
||||
.Where(r => hashIDs.Any(h => h == r.EntryId));
|
||||
var securityToDelete = Query(FilesDbContext.Security)
|
||||
.Where(r => hashIDs.Any(h => h == r.EntryId));
|
||||
|
||||
FilesDbContext.Security.RemoveRange(await securityToDelete.ToListAsync());
|
||||
await FilesDbContext.SaveChangesAsync().ConfigureAwait(false);
|
||||
FilesDbContext.Security.RemoveRange(await securityToDelete.ToListAsync());
|
||||
await FilesDbContext.SaveChangesAsync().ConfigureAwait(false);
|
||||
|
||||
var mappingToDelete = Query(FilesDbContext.ThirdpartyIdMapping)
|
||||
.Where(r => hashIDs.Any(h => h == r.HashId));
|
||||
var mappingToDelete = Query(FilesDbContext.ThirdpartyIdMapping)
|
||||
.Where(r => hashIDs.Any(h => h == r.HashId));
|
||||
|
||||
FilesDbContext.ThirdpartyIdMapping.RemoveRange(await mappingToDelete.ToListAsync());
|
||||
await FilesDbContext.SaveChangesAsync().ConfigureAwait(false);
|
||||
FilesDbContext.ThirdpartyIdMapping.RemoveRange(await mappingToDelete.ToListAsync());
|
||||
await FilesDbContext.SaveChangesAsync().ConfigureAwait(false);
|
||||
|
||||
await tx.CommitAsync().ConfigureAwait(false);
|
||||
}
|
||||
await tx.CommitAsync().ConfigureAwait(false);
|
||||
}
|
||||
});
|
||||
|
||||
if (onedriveFile is not ErrorItem)
|
||||
{
|
||||
|
@ -222,42 +222,49 @@ internal class OneDriveFolderDao : OneDriveDaoBase, IFolderDao<string>
|
||||
var onedriveFolder = await GetOneDriveItemAsync(folderId).ConfigureAwait(false);
|
||||
var id = MakeId(onedriveFolder);
|
||||
|
||||
using (var tx = await FilesDbContext.Database.BeginTransactionAsync().ConfigureAwait(false))
|
||||
var strategy = FilesDbContext.Database.CreateExecutionStrategy();
|
||||
|
||||
await strategy.ExecuteAsync(async () =>
|
||||
{
|
||||
var hashIDs = await Query(FilesDbContext.ThirdpartyIdMapping)
|
||||
.Where(r => r.Id.StartsWith(id))
|
||||
.Select(r => r.HashId)
|
||||
.ToListAsync()
|
||||
.ConfigureAwait(false);
|
||||
using (var tx = await FilesDbContext.Database.BeginTransactionAsync().ConfigureAwait(false))
|
||||
{
|
||||
var hashIDs = await Query(FilesDbContext.ThirdpartyIdMapping)
|
||||
.Where(r => r.Id.StartsWith(id))
|
||||
.Select(r => r.HashId)
|
||||
.ToListAsync()
|
||||
.ConfigureAwait(false);
|
||||
|
||||
var link = await Query(FilesDbContext.TagLink)
|
||||
.Where(r => hashIDs.Any(h => h == r.EntryId))
|
||||
.ToListAsync().ConfigureAwait(false);
|
||||
var link = await Query(FilesDbContext.TagLink)
|
||||
.Where(r => hashIDs.Any(h => h == r.EntryId))
|
||||
.ToListAsync().ConfigureAwait(false);
|
||||
|
||||
FilesDbContext.TagLink.RemoveRange(link);
|
||||
await FilesDbContext.SaveChangesAsync().ConfigureAwait(false);
|
||||
FilesDbContext.TagLink.RemoveRange(link);
|
||||
await FilesDbContext.SaveChangesAsync().ConfigureAwait(false);
|
||||
|
||||
var tagsToRemove = from ft in FilesDbContext.Tag
|
||||
join ftl in FilesDbContext.TagLink.DefaultIfEmpty() on new { TenantId = ft.TenantId, Id = ft.Id } equals new { TenantId = ftl.TenantId, Id = ftl.TagId }
|
||||
where ftl == null
|
||||
select ft;
|
||||
var tagsToRemove = from ft in FilesDbContext.Tag
|
||||
join ftl in FilesDbContext.TagLink.DefaultIfEmpty() on new { TenantId = ft.TenantId, Id = ft.Id } equals new { TenantId = ftl.TenantId, Id = ftl.TagId }
|
||||
where ftl == null
|
||||
select ft;
|
||||
|
||||
FilesDbContext.Tag.RemoveRange(await tagsToRemove.ToListAsync());
|
||||
FilesDbContext.Tag.RemoveRange(await tagsToRemove.ToListAsync());
|
||||
|
||||
var securityToDelete = Query(FilesDbContext.Security)
|
||||
.Where(r => hashIDs.Any(h => h == r.EntryId));
|
||||
var securityToDelete = Query(FilesDbContext.Security)
|
||||
.Where(r => hashIDs.Any(h => h == r.EntryId));
|
||||
|
||||
FilesDbContext.Security.RemoveRange(await securityToDelete.ToListAsync());
|
||||
await FilesDbContext.SaveChangesAsync().ConfigureAwait(false);
|
||||
FilesDbContext.Security.RemoveRange(await securityToDelete.ToListAsync());
|
||||
await FilesDbContext.SaveChangesAsync().ConfigureAwait(false);
|
||||
|
||||
var mappingToDelete = Query(FilesDbContext.ThirdpartyIdMapping)
|
||||
.Where(r => hashIDs.Any(h => h == r.HashId));
|
||||
var mappingToDelete = Query(FilesDbContext.ThirdpartyIdMapping)
|
||||
.Where(r => hashIDs.Any(h => h == r.HashId));
|
||||
|
||||
FilesDbContext.ThirdpartyIdMapping.RemoveRange(await mappingToDelete.ToListAsync());
|
||||
await FilesDbContext.SaveChangesAsync().ConfigureAwait(false);
|
||||
|
||||
await tx.CommitAsync().ConfigureAwait(false);
|
||||
}
|
||||
});
|
||||
|
||||
FilesDbContext.ThirdpartyIdMapping.RemoveRange(await mappingToDelete.ToListAsync());
|
||||
await FilesDbContext.SaveChangesAsync().ConfigureAwait(false);
|
||||
|
||||
await tx.CommitAsync().ConfigureAwait(false);
|
||||
}
|
||||
|
||||
if (onedriveFolder is not ErrorItem)
|
||||
{
|
||||
|
@ -310,48 +310,53 @@ internal class ProviderAccountDao : IProviderDao
|
||||
|
||||
public virtual async Task RemoveProviderInfoAsync(int linkId)
|
||||
{
|
||||
using var tx = await FilesDbContext.Database.BeginTransactionAsync().ConfigureAwait(false);
|
||||
var folderId = (await GetProviderInfoAsync(linkId)).RootFolderId;
|
||||
var strategy = FilesDbContext.Database.CreateExecutionStrategy();
|
||||
|
||||
var entryIDs = await FilesDbContext.ThirdpartyIdMapping
|
||||
.AsQueryable()
|
||||
.Where(r => r.TenantId == TenantID)
|
||||
.Where(r => r.Id.StartsWith(folderId))
|
||||
.Select(r => r.HashId)
|
||||
.ToListAsync()
|
||||
.ConfigureAwait(false);
|
||||
await strategy.ExecuteAsync(async () =>
|
||||
{
|
||||
using var tx = await FilesDbContext.Database.BeginTransactionAsync().ConfigureAwait(false);
|
||||
var folderId = (await GetProviderInfoAsync(linkId)).RootFolderId;
|
||||
|
||||
var forDelete = await FilesDbContext.Security
|
||||
.AsQueryable()
|
||||
.Where(r => r.TenantId == TenantID)
|
||||
.Where(r => entryIDs.Any(a => a == r.EntryId))
|
||||
.ToListAsync()
|
||||
.ConfigureAwait(false);
|
||||
var entryIDs = await FilesDbContext.ThirdpartyIdMapping
|
||||
.AsQueryable()
|
||||
.Where(r => r.TenantId == TenantID)
|
||||
.Where(r => r.Id.StartsWith(folderId))
|
||||
.Select(r => r.HashId)
|
||||
.ToListAsync()
|
||||
.ConfigureAwait(false);
|
||||
|
||||
FilesDbContext.Security.RemoveRange(forDelete);
|
||||
await FilesDbContext.SaveChangesAsync().ConfigureAwait(false);
|
||||
var forDelete = await FilesDbContext.Security
|
||||
.AsQueryable()
|
||||
.Where(r => r.TenantId == TenantID)
|
||||
.Where(r => entryIDs.Any(a => a == r.EntryId))
|
||||
.ToListAsync()
|
||||
.ConfigureAwait(false);
|
||||
|
||||
var linksForDelete = await FilesDbContext.TagLink
|
||||
.AsQueryable()
|
||||
.Where(r => r.TenantId == TenantID)
|
||||
.Where(r => entryIDs.Any(e => e == r.EntryId))
|
||||
.ToListAsync()
|
||||
.ConfigureAwait(false);
|
||||
FilesDbContext.Security.RemoveRange(forDelete);
|
||||
await FilesDbContext.SaveChangesAsync().ConfigureAwait(false);
|
||||
|
||||
FilesDbContext.TagLink.RemoveRange(linksForDelete);
|
||||
await FilesDbContext.SaveChangesAsync().ConfigureAwait(false);
|
||||
var linksForDelete = await FilesDbContext.TagLink
|
||||
.AsQueryable()
|
||||
.Where(r => r.TenantId == TenantID)
|
||||
.Where(r => entryIDs.Any(e => e == r.EntryId))
|
||||
.ToListAsync()
|
||||
.ConfigureAwait(false);
|
||||
|
||||
var accountsForDelete = await FilesDbContext.ThirdpartyAccount
|
||||
.AsQueryable()
|
||||
.Where(r => r.Id == linkId)
|
||||
.Where(r => r.TenantId == TenantID)
|
||||
.ToListAsync()
|
||||
.ConfigureAwait(false);
|
||||
FilesDbContext.TagLink.RemoveRange(linksForDelete);
|
||||
await FilesDbContext.SaveChangesAsync().ConfigureAwait(false);
|
||||
|
||||
FilesDbContext.ThirdpartyAccount.RemoveRange(accountsForDelete);
|
||||
await FilesDbContext.SaveChangesAsync().ConfigureAwait(false);
|
||||
var accountsForDelete = await FilesDbContext.ThirdpartyAccount
|
||||
.AsQueryable()
|
||||
.Where(r => r.Id == linkId)
|
||||
.Where(r => r.TenantId == TenantID)
|
||||
.ToListAsync()
|
||||
.ConfigureAwait(false);
|
||||
|
||||
await tx.CommitAsync().ConfigureAwait(false);
|
||||
FilesDbContext.ThirdpartyAccount.RemoveRange(accountsForDelete);
|
||||
await FilesDbContext.SaveChangesAsync().ConfigureAwait(false);
|
||||
|
||||
await tx.CommitAsync().ConfigureAwait(false);
|
||||
});
|
||||
}
|
||||
|
||||
private IProviderInfo ToProviderInfo(int id, ProviderTypes providerKey, string customerTitle, AuthData authData, Guid owner, FolderType type, DateTime createOn)
|
||||
|
@ -124,54 +124,59 @@ internal class SharePointDaoBase : ThirdPartyProviderDao<SharePointProviderInfo>
|
||||
|
||||
private async Task InternalUpdatePathInDBAsync(string oldValue, string newValue)
|
||||
{
|
||||
using var tx = FilesDbContext.Database.BeginTransaction();
|
||||
var oldIDs = await Query(FilesDbContext.ThirdpartyIdMapping)
|
||||
.Where(r => r.Id.StartsWith(oldValue))
|
||||
.Select(r => r.Id)
|
||||
.ToListAsync();
|
||||
var strategy = FilesDbContext.Database.CreateExecutionStrategy();
|
||||
|
||||
foreach (var oldID in oldIDs)
|
||||
await strategy.ExecuteAsync(async () =>
|
||||
{
|
||||
var oldHashID = await MappingIDAsync(oldID);
|
||||
var newID = oldID.Replace(oldValue, newValue);
|
||||
var newHashID = await MappingIDAsync(newID);
|
||||
|
||||
var mappingForUpdate = await Query(FilesDbContext.ThirdpartyIdMapping)
|
||||
.Where(r => r.HashId == oldHashID)
|
||||
using var tx = FilesDbContext.Database.BeginTransaction();
|
||||
var oldIDs = await Query(FilesDbContext.ThirdpartyIdMapping)
|
||||
.Where(r => r.Id.StartsWith(oldValue))
|
||||
.Select(r => r.Id)
|
||||
.ToListAsync();
|
||||
|
||||
foreach (var m in mappingForUpdate)
|
||||
foreach (var oldID in oldIDs)
|
||||
{
|
||||
m.Id = newID;
|
||||
m.HashId = newHashID;
|
||||
var oldHashID = await MappingIDAsync(oldID);
|
||||
var newID = oldID.Replace(oldValue, newValue);
|
||||
var newHashID = await MappingIDAsync(newID);
|
||||
|
||||
var mappingForUpdate = await Query(FilesDbContext.ThirdpartyIdMapping)
|
||||
.Where(r => r.HashId == oldHashID)
|
||||
.ToListAsync();
|
||||
|
||||
foreach (var m in mappingForUpdate)
|
||||
{
|
||||
m.Id = newID;
|
||||
m.HashId = newHashID;
|
||||
}
|
||||
|
||||
await FilesDbContext.SaveChangesAsync();
|
||||
|
||||
var securityForUpdate = await Query(FilesDbContext.Security)
|
||||
.Where(r => r.EntryId == oldHashID)
|
||||
.ToListAsync();
|
||||
|
||||
foreach (var s in securityForUpdate)
|
||||
{
|
||||
s.EntryId = newHashID;
|
||||
}
|
||||
|
||||
await FilesDbContext.SaveChangesAsync();
|
||||
|
||||
var linkForUpdate = await Query(FilesDbContext.TagLink)
|
||||
.Where(r => r.EntryId == oldHashID)
|
||||
.ToListAsync();
|
||||
|
||||
foreach (var l in linkForUpdate)
|
||||
{
|
||||
l.EntryId = newHashID;
|
||||
}
|
||||
|
||||
await FilesDbContext.SaveChangesAsync();
|
||||
}
|
||||
|
||||
await FilesDbContext.SaveChangesAsync();
|
||||
|
||||
var securityForUpdate = await Query(FilesDbContext.Security)
|
||||
.Where(r => r.EntryId == oldHashID)
|
||||
.ToListAsync();
|
||||
|
||||
foreach (var s in securityForUpdate)
|
||||
{
|
||||
s.EntryId = newHashID;
|
||||
}
|
||||
|
||||
await FilesDbContext.SaveChangesAsync();
|
||||
|
||||
var linkForUpdate = await Query(FilesDbContext.TagLink)
|
||||
.Where(r => r.EntryId == oldHashID)
|
||||
.ToListAsync();
|
||||
|
||||
foreach (var l in linkForUpdate)
|
||||
{
|
||||
l.EntryId = newHashID;
|
||||
}
|
||||
|
||||
await FilesDbContext.SaveChangesAsync();
|
||||
}
|
||||
|
||||
await tx.CommitAsync();
|
||||
await tx.CommitAsync();
|
||||
});
|
||||
}
|
||||
|
||||
protected Task<string> MappingIDAsync(string id)
|
||||
|
@ -210,43 +210,49 @@ internal class SharePointFolderDao : SharePointDaoBase, IFolderDao<string>
|
||||
{
|
||||
var folder = await ProviderInfo.GetFolderByIdAsync(folderId).ConfigureAwait(false);
|
||||
|
||||
using (var tx = await FilesDbContext.Database.BeginTransactionAsync().ConfigureAwait(false))
|
||||
var strategy = FilesDbContext.Database.CreateExecutionStrategy();
|
||||
|
||||
await strategy.ExecuteAsync(async () =>
|
||||
{
|
||||
var hashIDs = await Query(FilesDbContext.ThirdpartyIdMapping)
|
||||
.Where(r => r.Id.StartsWith(folder.ServerRelativeUrl))
|
||||
.Select(r => r.HashId)
|
||||
.ToListAsync()
|
||||
.ConfigureAwait(false);
|
||||
using (var tx = await FilesDbContext.Database.BeginTransactionAsync().ConfigureAwait(false))
|
||||
{
|
||||
var hashIDs = await Query(FilesDbContext.ThirdpartyIdMapping)
|
||||
.Where(r => r.Id.StartsWith(folder.ServerRelativeUrl))
|
||||
.Select(r => r.HashId)
|
||||
.ToListAsync()
|
||||
.ConfigureAwait(false);
|
||||
|
||||
var link = await Query(FilesDbContext.TagLink)
|
||||
.Where(r => hashIDs.Any(h => h == r.EntryId))
|
||||
.ToListAsync()
|
||||
.ConfigureAwait(false);
|
||||
var link = await Query(FilesDbContext.TagLink)
|
||||
.Where(r => hashIDs.Any(h => h == r.EntryId))
|
||||
.ToListAsync()
|
||||
.ConfigureAwait(false);
|
||||
|
||||
FilesDbContext.TagLink.RemoveRange(link);
|
||||
await FilesDbContext.SaveChangesAsync().ConfigureAwait(false);
|
||||
FilesDbContext.TagLink.RemoveRange(link);
|
||||
await FilesDbContext.SaveChangesAsync().ConfigureAwait(false);
|
||||
|
||||
var tagsToRemove = from ft in FilesDbContext.Tag
|
||||
join ftl in FilesDbContext.TagLink.DefaultIfEmpty() on new { TenantId = ft.TenantId, Id = ft.Id } equals new { TenantId = ftl.TenantId, Id = ftl.TagId }
|
||||
where ftl == null
|
||||
select ft;
|
||||
var tagsToRemove = from ft in FilesDbContext.Tag
|
||||
join ftl in FilesDbContext.TagLink.DefaultIfEmpty() on new { TenantId = ft.TenantId, Id = ft.Id } equals new { TenantId = ftl.TenantId, Id = ftl.TagId }
|
||||
where ftl == null
|
||||
select ft;
|
||||
|
||||
FilesDbContext.Tag.RemoveRange(await tagsToRemove.ToListAsync());
|
||||
FilesDbContext.Tag.RemoveRange(await tagsToRemove.ToListAsync());
|
||||
|
||||
var securityToDelete = Query(FilesDbContext.Security)
|
||||
.Where(r => hashIDs.Any(h => h == r.EntryId));
|
||||
var securityToDelete = Query(FilesDbContext.Security)
|
||||
.Where(r => hashIDs.Any(h => h == r.EntryId));
|
||||
|
||||
FilesDbContext.Security.RemoveRange(await securityToDelete.ToListAsync());
|
||||
await FilesDbContext.SaveChangesAsync().ConfigureAwait(false);
|
||||
FilesDbContext.Security.RemoveRange(await securityToDelete.ToListAsync());
|
||||
await FilesDbContext.SaveChangesAsync().ConfigureAwait(false);
|
||||
|
||||
var mappingToDelete = Query(FilesDbContext.ThirdpartyIdMapping)
|
||||
.Where(r => hashIDs.Any(h => h == r.HashId));
|
||||
var mappingToDelete = Query(FilesDbContext.ThirdpartyIdMapping)
|
||||
.Where(r => hashIDs.Any(h => h == r.HashId));
|
||||
|
||||
FilesDbContext.ThirdpartyIdMapping.RemoveRange(await mappingToDelete.ToListAsync());
|
||||
await FilesDbContext.SaveChangesAsync().ConfigureAwait(false);
|
||||
FilesDbContext.ThirdpartyIdMapping.RemoveRange(await mappingToDelete.ToListAsync());
|
||||
await FilesDbContext.SaveChangesAsync().ConfigureAwait(false);
|
||||
|
||||
await tx.CommitAsync().ConfigureAwait(false);
|
||||
}
|
||||
});
|
||||
|
||||
await tx.CommitAsync().ConfigureAwait(false);
|
||||
}
|
||||
|
||||
await ProviderInfo.DeleteFolderAsync(folderId).ConfigureAwait(false);
|
||||
}
|
||||
|
@ -144,54 +144,59 @@ internal abstract class SharpBoxDaoBase : ThirdPartyProviderDao<SharpBoxProvider
|
||||
return;
|
||||
}
|
||||
|
||||
using var tx = FilesDbContext.Database.BeginTransaction();
|
||||
var oldIDs = await Query(FilesDbContext.ThirdpartyIdMapping)
|
||||
.Where(r => r.Id.StartsWith(oldValue))
|
||||
.Select(r => r.Id)
|
||||
.ToListAsync();
|
||||
var strategy = FilesDbContext.Database.CreateExecutionStrategy();
|
||||
|
||||
foreach (var oldID in oldIDs)
|
||||
await strategy.ExecuteAsync(async () =>
|
||||
{
|
||||
var oldHashID = await MappingIDAsync(oldID);
|
||||
var newID = oldID.Replace(oldValue, newValue);
|
||||
var newHashID = await MappingIDAsync(newID);
|
||||
|
||||
var mappingForUpdate = await Query(FilesDbContext.ThirdpartyIdMapping)
|
||||
.Where(r => r.HashId == oldHashID)
|
||||
using var tx = await FilesDbContext.Database.BeginTransactionAsync();
|
||||
var oldIDs = await Query(FilesDbContext.ThirdpartyIdMapping)
|
||||
.Where(r => r.Id.StartsWith(oldValue))
|
||||
.Select(r => r.Id)
|
||||
.ToListAsync();
|
||||
|
||||
foreach (var m in mappingForUpdate)
|
||||
foreach (var oldID in oldIDs)
|
||||
{
|
||||
m.Id = newID;
|
||||
m.HashId = newHashID;
|
||||
var oldHashID = await MappingIDAsync(oldID);
|
||||
var newID = oldID.Replace(oldValue, newValue);
|
||||
var newHashID = await MappingIDAsync(newID);
|
||||
|
||||
var mappingForUpdate = await Query(FilesDbContext.ThirdpartyIdMapping)
|
||||
.Where(r => r.HashId == oldHashID)
|
||||
.ToListAsync();
|
||||
|
||||
foreach (var m in mappingForUpdate)
|
||||
{
|
||||
m.Id = newID;
|
||||
m.HashId = newHashID;
|
||||
}
|
||||
|
||||
await FilesDbContext.SaveChangesAsync();
|
||||
|
||||
var securityForUpdate = await Query(FilesDbContext.Security)
|
||||
.Where(r => r.EntryId == oldHashID)
|
||||
.ToListAsync();
|
||||
|
||||
foreach (var s in securityForUpdate)
|
||||
{
|
||||
s.EntryId = newHashID;
|
||||
}
|
||||
|
||||
await FilesDbContext.SaveChangesAsync();
|
||||
|
||||
var linkForUpdate = await Query(FilesDbContext.TagLink)
|
||||
.Where(r => r.EntryId == oldHashID)
|
||||
.ToListAsync();
|
||||
|
||||
foreach (var l in linkForUpdate)
|
||||
{
|
||||
l.EntryId = newHashID;
|
||||
}
|
||||
|
||||
await FilesDbContext.SaveChangesAsync();
|
||||
}
|
||||
|
||||
await FilesDbContext.SaveChangesAsync();
|
||||
|
||||
var securityForUpdate = await Query(FilesDbContext.Security)
|
||||
.Where(r => r.EntryId == oldHashID)
|
||||
.ToListAsync();
|
||||
|
||||
foreach (var s in securityForUpdate)
|
||||
{
|
||||
s.EntryId = newHashID;
|
||||
}
|
||||
|
||||
await FilesDbContext.SaveChangesAsync();
|
||||
|
||||
var linkForUpdate = await Query(FilesDbContext.TagLink)
|
||||
.Where(r => r.EntryId == oldHashID)
|
||||
.ToListAsync();
|
||||
|
||||
foreach (var l in linkForUpdate)
|
||||
{
|
||||
l.EntryId = newHashID;
|
||||
}
|
||||
|
||||
await FilesDbContext.SaveChangesAsync();
|
||||
}
|
||||
|
||||
await tx.CommitAsync();
|
||||
await tx.CommitAsync();
|
||||
});
|
||||
}
|
||||
|
||||
protected string MakePath(object entryId)
|
||||
|
@ -363,43 +363,51 @@ internal class SharpBoxFileDao : SharpBoxDaoBase, IFileDao<string>
|
||||
|
||||
var id = MakeId(file);
|
||||
|
||||
using (var tx = FilesDbContext.Database.BeginTransaction())
|
||||
var strategy = FilesDbContext.Database.CreateExecutionStrategy();
|
||||
|
||||
await strategy.ExecuteAsync(async () =>
|
||||
{
|
||||
var hashIDs = await Query(FilesDbContext.ThirdpartyIdMapping)
|
||||
.Where(r => r.Id.StartsWith(id))
|
||||
.Select(r => r.HashId)
|
||||
.ToListAsync()
|
||||
.ConfigureAwait(false);
|
||||
using (var tx = FilesDbContext.Database.BeginTransaction())
|
||||
{
|
||||
var hashIDs = await Query(FilesDbContext.ThirdpartyIdMapping)
|
||||
.Where(r => r.Id.StartsWith(id))
|
||||
.Select(r => r.HashId)
|
||||
.ToListAsync()
|
||||
.ConfigureAwait(false);
|
||||
|
||||
var link = await Query(FilesDbContext.TagLink)
|
||||
.Where(r => hashIDs.Any(h => h == r.EntryId))
|
||||
.ToListAsync()
|
||||
.ConfigureAwait(false);
|
||||
var link = await Query(FilesDbContext.TagLink)
|
||||
.Where(r => hashIDs.Any(h => h == r.EntryId))
|
||||
.ToListAsync()
|
||||
.ConfigureAwait(false);
|
||||
|
||||
FilesDbContext.TagLink.RemoveRange(link);
|
||||
await FilesDbContext.SaveChangesAsync().ConfigureAwait(false);
|
||||
FilesDbContext.TagLink.RemoveRange(link);
|
||||
await FilesDbContext.SaveChangesAsync().ConfigureAwait(false);
|
||||
|
||||
var tagsToRemove = from ft in FilesDbContext.Tag
|
||||
join ftl in FilesDbContext.TagLink.DefaultIfEmpty() on new { TenantId = ft.TenantId, Id = ft.Id } equals new { TenantId = ftl.TenantId, Id = ftl.TagId }
|
||||
where ftl == null
|
||||
select ft;
|
||||
var tagsToRemove = from ft in FilesDbContext.Tag
|
||||
join ftl in FilesDbContext.TagLink.DefaultIfEmpty() on new { TenantId = ft.TenantId, Id = ft.Id } equals new { TenantId = ftl.TenantId, Id = ftl.TagId }
|
||||
where ftl == null
|
||||
select ft;
|
||||
|
||||
FilesDbContext.Tag.RemoveRange(await tagsToRemove.ToListAsync());
|
||||
FilesDbContext.Tag.RemoveRange(await tagsToRemove.ToListAsync());
|
||||
|
||||
var securityToDelete = Query(FilesDbContext.Security)
|
||||
.Where(r => hashIDs.Any(h => h == r.EntryId));
|
||||
var securityToDelete = Query(FilesDbContext.Security)
|
||||
.Where(r => hashIDs.Any(h => h == r.EntryId));
|
||||
|
||||
FilesDbContext.Security.RemoveRange(await securityToDelete.ToListAsync());
|
||||
await FilesDbContext.SaveChangesAsync().ConfigureAwait(false);
|
||||
FilesDbContext.Security.RemoveRange(await securityToDelete.ToListAsync());
|
||||
await FilesDbContext.SaveChangesAsync().ConfigureAwait(false);
|
||||
|
||||
var mappingToDelete = Query(FilesDbContext.ThirdpartyIdMapping)
|
||||
.Where(r => hashIDs.Any(h => h == r.HashId));
|
||||
|
||||
FilesDbContext.ThirdpartyIdMapping.RemoveRange(await mappingToDelete.ToListAsync());
|
||||
await FilesDbContext.SaveChangesAsync().ConfigureAwait(false);
|
||||
|
||||
await tx.CommitAsync().ConfigureAwait(false);
|
||||
}
|
||||
});
|
||||
|
||||
var mappingToDelete = Query(FilesDbContext.ThirdpartyIdMapping)
|
||||
.Where(r => hashIDs.Any(h => h == r.HashId));
|
||||
|
||||
FilesDbContext.ThirdpartyIdMapping.RemoveRange(await mappingToDelete.ToListAsync());
|
||||
await FilesDbContext.SaveChangesAsync().ConfigureAwait(false);
|
||||
|
||||
await tx.CommitAsync().ConfigureAwait(false);
|
||||
}
|
||||
|
||||
if (file is not ErrorEntry)
|
||||
{
|
||||
|
@ -220,43 +220,51 @@ internal class SharpBoxFolderDao : SharpBoxDaoBase, IFolderDao<string>
|
||||
var folder = GetFolderById(folderId);
|
||||
var id = MakeId(folder);
|
||||
|
||||
using (var tx = await FilesDbContext.Database.BeginTransactionAsync().ConfigureAwait(false))
|
||||
var strategy = FilesDbContext.Database.CreateExecutionStrategy();
|
||||
|
||||
await strategy.ExecuteAsync(async () =>
|
||||
{
|
||||
var hashIDs = await Query(FilesDbContext.ThirdpartyIdMapping)
|
||||
.Where(r => r.Id.StartsWith(id))
|
||||
.Select(r => r.HashId)
|
||||
.ToListAsync()
|
||||
.ConfigureAwait(false);
|
||||
using (var tx = await FilesDbContext.Database.BeginTransactionAsync().ConfigureAwait(false))
|
||||
{
|
||||
var hashIDs = await Query(FilesDbContext.ThirdpartyIdMapping)
|
||||
.Where(r => r.Id.StartsWith(id))
|
||||
.Select(r => r.HashId)
|
||||
.ToListAsync()
|
||||
.ConfigureAwait(false);
|
||||
|
||||
var link = await Query(FilesDbContext.TagLink)
|
||||
.Where(r => hashIDs.Any(h => h == r.EntryId))
|
||||
.ToListAsync()
|
||||
.ConfigureAwait(false);
|
||||
var link = await Query(FilesDbContext.TagLink)
|
||||
.Where(r => hashIDs.Any(h => h == r.EntryId))
|
||||
.ToListAsync()
|
||||
.ConfigureAwait(false);
|
||||
|
||||
FilesDbContext.TagLink.RemoveRange(link);
|
||||
await FilesDbContext.SaveChangesAsync().ConfigureAwait(false);
|
||||
FilesDbContext.TagLink.RemoveRange(link);
|
||||
await FilesDbContext.SaveChangesAsync().ConfigureAwait(false);
|
||||
|
||||
var tagsToRemove = from ft in FilesDbContext.Tag
|
||||
join ftl in FilesDbContext.TagLink.DefaultIfEmpty() on new { TenantId = ft.TenantId, Id = ft.Id } equals new { TenantId = ftl.TenantId, Id = ftl.TagId }
|
||||
where ftl == null
|
||||
select ft;
|
||||
var tagsToRemove = from ft in FilesDbContext.Tag
|
||||
join ftl in FilesDbContext.TagLink.DefaultIfEmpty() on new { TenantId = ft.TenantId, Id = ft.Id } equals new { TenantId = ftl.TenantId, Id = ftl.TagId }
|
||||
where ftl == null
|
||||
select ft;
|
||||
|
||||
FilesDbContext.Tag.RemoveRange(await tagsToRemove.ToListAsync());
|
||||
FilesDbContext.Tag.RemoveRange(await tagsToRemove.ToListAsync());
|
||||
|
||||
var securityToDelete = Query(FilesDbContext.Security)
|
||||
.Where(r => hashIDs.Any(h => h == r.EntryId));
|
||||
var securityToDelete = Query(FilesDbContext.Security)
|
||||
.Where(r => hashIDs.Any(h => h == r.EntryId));
|
||||
|
||||
FilesDbContext.Security.RemoveRange(await securityToDelete.ToListAsync());
|
||||
await FilesDbContext.SaveChangesAsync().ConfigureAwait(false);
|
||||
FilesDbContext.Security.RemoveRange(await securityToDelete.ToListAsync());
|
||||
await FilesDbContext.SaveChangesAsync().ConfigureAwait(false);
|
||||
|
||||
var mappingToDelete = Query(FilesDbContext.ThirdpartyIdMapping)
|
||||
.Where(r => hashIDs.Any(h => h == r.HashId));
|
||||
|
||||
FilesDbContext.ThirdpartyIdMapping.RemoveRange(await mappingToDelete.ToListAsync());
|
||||
await FilesDbContext.SaveChangesAsync().ConfigureAwait(false);
|
||||
|
||||
await tx.CommitAsync().ConfigureAwait(false);
|
||||
}
|
||||
});
|
||||
|
||||
var mappingToDelete = Query(FilesDbContext.ThirdpartyIdMapping)
|
||||
.Where(r => hashIDs.Any(h => h == r.HashId));
|
||||
|
||||
FilesDbContext.ThirdpartyIdMapping.RemoveRange(await mappingToDelete.ToListAsync());
|
||||
await FilesDbContext.SaveChangesAsync().ConfigureAwait(false);
|
||||
|
||||
await tx.CommitAsync().ConfigureAwait(false);
|
||||
}
|
||||
|
||||
if (folder is not ErrorEntry)
|
||||
{
|
||||
|
@ -26,16 +26,32 @@
|
||||
|
||||
namespace ASC.Web.Files.Services.WCFService.FileOperations;
|
||||
|
||||
[ProtoContract]
|
||||
[ProtoInclude(100, typeof(FileConverterOperationResult))]
|
||||
public class FileOperationResult
|
||||
{
|
||||
[ProtoMember(1)]
|
||||
public string Id { get; set; }
|
||||
|
||||
[JsonPropertyName("operation")]
|
||||
[ProtoMember(2)]
|
||||
public FileOperationType OperationType { get; set; }
|
||||
|
||||
[ProtoMember(3)]
|
||||
public int Progress { get; set; }
|
||||
|
||||
[ProtoMember(4)]
|
||||
public string Source { get; set; }
|
||||
|
||||
[ProtoMember(5)]
|
||||
public string Result { get; set; }
|
||||
|
||||
[ProtoMember(6)]
|
||||
public string Error { get; set; }
|
||||
|
||||
[ProtoMember(7)]
|
||||
public string Processed { get; set; }
|
||||
|
||||
[ProtoMember(8)]
|
||||
public bool Finished { get; set; }
|
||||
}
|
||||
|
@ -24,44 +24,42 @@
|
||||
// content are licensed under the terms of the Creative Commons Attribution-ShareAlike 4.0
|
||||
// International. See the License terms at http://creativecommons.org/licenses/by-sa/4.0/legalcode
|
||||
|
||||
using Microsoft.Extensions.Caching.Distributed;
|
||||
|
||||
using Timeout = System.Threading.Timeout;
|
||||
|
||||
namespace ASC.Web.Files.Utils;
|
||||
|
||||
[Singletone(Additional = typeof(FileConverterQueueExtension))]
|
||||
internal class FileConverterQueue<T> : IDisposable
|
||||
[Singletone]
|
||||
public class FileConverterQueue<T>
|
||||
{
|
||||
private readonly object _singleThread = new object();
|
||||
private readonly IDictionary<File<T>, ConvertFileOperationResult> _conversionQueue;
|
||||
private readonly Timer _timer;
|
||||
private readonly object _locker;
|
||||
private readonly ICache _cache;
|
||||
private const int _timerPeriod = 500;
|
||||
private readonly object _locker = new object();
|
||||
private readonly IDistributedCache _distributedCache;
|
||||
private readonly string _cache_key_prefix = "asc_file_converter_queue_";
|
||||
|
||||
private readonly IServiceScopeFactory _serviceScopeFactory;
|
||||
|
||||
public FileConverterQueue(IServiceScopeFactory serviceScopeFactory, ICache cache)
|
||||
public FileConverterQueue(IDistributedCache distributedCache)
|
||||
{
|
||||
_conversionQueue = new Dictionary<File<T>, ConvertFileOperationResult>(new FileComparer<T>());
|
||||
_timer = new Timer(CheckConvertFilesStatus, null, 0, Timeout.Infinite);
|
||||
_locker = new object();
|
||||
_serviceScopeFactory = serviceScopeFactory;
|
||||
_cache = cache;
|
||||
_distributedCache = distributedCache;
|
||||
}
|
||||
|
||||
public void Add(File<T> file, string password, int tenantId, IAccount account, bool deleteAfter, string url, string serverRootPath)
|
||||
public void Add(File<T> file,
|
||||
string password,
|
||||
int tenantId,
|
||||
IAccount account,
|
||||
bool deleteAfter,
|
||||
string url,
|
||||
string serverRootPath)
|
||||
{
|
||||
lock (_locker)
|
||||
{
|
||||
if (_conversionQueue.ContainsKey(file))
|
||||
var task = PeekTask(file);
|
||||
|
||||
if (Contains(task))
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
var queueResult = new ConvertFileOperationResult
|
||||
var queueResult = new FileConverterOperationResult
|
||||
{
|
||||
Source = string.Format("{{\"id\":\"{0}\", \"version\":\"{1}\"}}", file.Id, file.Version),
|
||||
Source = System.Text.Json.JsonSerializer.Serialize(new { id = file.Id, version = file.Version }),
|
||||
OperationType = FileOperationType.Convert,
|
||||
Error = string.Empty,
|
||||
Progress = 0,
|
||||
@ -69,316 +67,95 @@ internal class FileConverterQueue<T> : IDisposable
|
||||
Processed = "",
|
||||
Id = string.Empty,
|
||||
TenantId = tenantId,
|
||||
Account = account,
|
||||
Account = account.ID,
|
||||
Delete = deleteAfter,
|
||||
StartDateTime = DateTime.Now,
|
||||
Url = url,
|
||||
Password = password,
|
||||
ServerRootPath = serverRootPath
|
||||
};
|
||||
_conversionQueue.Add(file, queueResult);
|
||||
_cache.Insert(GetKey(file), queueResult, TimeSpan.FromMinutes(10));
|
||||
|
||||
_timer.Change(0, Timeout.Infinite);
|
||||
|
||||
Enqueue(queueResult);
|
||||
}
|
||||
}
|
||||
|
||||
public async Task<ConvertFileOperationResult> GetStatusAsync(KeyValuePair<File<T>, bool> pair, FileSecurity fileSecurity)
|
||||
|
||||
|
||||
public void Enqueue(FileConverterOperationResult val)
|
||||
{
|
||||
var file = pair.Key;
|
||||
var key = GetKey(file);
|
||||
var operation = _cache.Get<ConvertFileOperationResult>(key);
|
||||
if (operation != null && (pair.Value || await fileSecurity.CanReadAsync(file)))
|
||||
var fromCache = LoadFromCache().ToList();
|
||||
|
||||
fromCache.Add(val);
|
||||
|
||||
SaveToCache(fromCache);
|
||||
}
|
||||
|
||||
public void Dequeue(FileConverterOperationResult val)
|
||||
{
|
||||
var fromCache = LoadFromCache().ToList();
|
||||
|
||||
fromCache.Remove(val);
|
||||
|
||||
SaveToCache(fromCache);
|
||||
}
|
||||
|
||||
public FileConverterOperationResult PeekTask(File<T> file)
|
||||
{
|
||||
var exist = LoadFromCache();
|
||||
|
||||
return exist.FirstOrDefault(x =>
|
||||
{
|
||||
lock (_locker)
|
||||
{
|
||||
if (operation.Progress == 100)
|
||||
{
|
||||
_conversionQueue.Remove(file);
|
||||
_cache.Remove(key);
|
||||
}
|
||||
var fileId = JsonDocument.Parse(x.Source).RootElement.GetProperty("id").Deserialize<T>();
|
||||
var fileVersion = JsonDocument.Parse(x.Source).RootElement.GetProperty("version").Deserialize<int>();
|
||||
|
||||
return operation;
|
||||
}
|
||||
}
|
||||
|
||||
return null;
|
||||
return file.Id.ToString() == fileId.ToString() && file.Version == fileVersion;
|
||||
});
|
||||
}
|
||||
|
||||
public bool IsConverting(File<T> file)
|
||||
{
|
||||
var result = _cache.Get<ConvertFileOperationResult>(GetKey(file));
|
||||
var result = PeekTask(file);
|
||||
|
||||
return result != null && result.Progress != 100 && string.IsNullOrEmpty(result.Error);
|
||||
}
|
||||
|
||||
private void CheckConvertFilesStatus(object _)
|
||||
|
||||
public IEnumerable<FileConverterOperationResult> GetAllTask()
|
||||
{
|
||||
if (Monitor.TryEnter(_singleThread))
|
||||
var queueTasks = LoadFromCache();
|
||||
|
||||
queueTasks = DeleteOrphanCacheItem(queueTasks);
|
||||
|
||||
return queueTasks;
|
||||
}
|
||||
|
||||
public void SetAllTask(IEnumerable<FileConverterOperationResult> queueTasks)
|
||||
{
|
||||
SaveToCache(queueTasks);
|
||||
}
|
||||
|
||||
|
||||
public async Task<FileConverterOperationResult> GetStatusAsync(KeyValuePair<File<T>, bool> pair, FileSecurity fileSecurity)
|
||||
{
|
||||
var file = pair.Key;
|
||||
var operation = PeekTask(pair.Key);
|
||||
|
||||
if (operation != null && (pair.Value || await fileSecurity.CanReadAsync(file)))
|
||||
{
|
||||
using var scope = _serviceScopeFactory.CreateScope();
|
||||
TenantManager tenantManager;
|
||||
UserManager userManager;
|
||||
SecurityContext securityContext;
|
||||
IDaoFactory daoFactory;
|
||||
FileSecurity fileSecurity;
|
||||
PathProvider pathProvider;
|
||||
SetupInfo setupInfo;
|
||||
FileUtility fileUtility;
|
||||
DocumentServiceHelper documentServiceHelper;
|
||||
DocumentServiceConnector documentServiceConnector;
|
||||
EntryStatusManager entryManager;
|
||||
FileConverter fileConverter;
|
||||
|
||||
var logger = scope.ServiceProvider.GetService<ILogger<FileConverterQueue<T>>>();
|
||||
|
||||
try
|
||||
if (operation.Progress == 100)
|
||||
{
|
||||
var filesIsConverting = new List<File<T>>();
|
||||
lock (_locker)
|
||||
{
|
||||
_timer.Change(Timeout.Infinite, Timeout.Infinite);
|
||||
|
||||
var queues = _conversionQueue.Where(x => !string.IsNullOrEmpty(x.Value.Processed)
|
||||
&& (x.Value.Progress == 100 && DateTime.UtcNow - x.Value.StopDateTime > TimeSpan.FromMinutes(1) ||
|
||||
DateTime.UtcNow - x.Value.StopDateTime > TimeSpan.FromMinutes(10)))
|
||||
.ToList();
|
||||
var task = PeekTask(file);
|
||||
|
||||
foreach (var q in queues)
|
||||
{
|
||||
_conversionQueue.Remove(q);
|
||||
_cache.Remove(GetKey(q.Key));
|
||||
}
|
||||
|
||||
logger.DebugRunCheckConvertFilesStatus(_conversionQueue.Count);
|
||||
|
||||
if (_conversionQueue.Count == 0)
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
filesIsConverting = _conversionQueue
|
||||
.Where(x => string.IsNullOrEmpty(x.Value.Processed))
|
||||
.Select(x => x.Key)
|
||||
.ToList();
|
||||
}
|
||||
|
||||
string convertedFileUrl = null;
|
||||
|
||||
foreach (var file in filesIsConverting)
|
||||
{
|
||||
var fileUri = file.Id.ToString();
|
||||
int operationResultProgress;
|
||||
|
||||
try
|
||||
{
|
||||
int tenantId;
|
||||
IAccount account;
|
||||
string password;
|
||||
string serverRootPath;
|
||||
|
||||
lock (_locker)
|
||||
{
|
||||
if (!_conversionQueue.ContainsKey(file))
|
||||
{
|
||||
continue;
|
||||
}
|
||||
|
||||
var operationResult = _conversionQueue[file];
|
||||
if (!string.IsNullOrEmpty(operationResult.Processed))
|
||||
{
|
||||
continue;
|
||||
}
|
||||
|
||||
operationResult.Processed = "1";
|
||||
tenantId = operationResult.TenantId;
|
||||
account = operationResult.Account;
|
||||
password = operationResult.Password;
|
||||
serverRootPath = operationResult.ServerRootPath;
|
||||
|
||||
//if (HttpContext.Current == null && !WorkContext.IsMono)
|
||||
//{
|
||||
// HttpContext.Current = new HttpContext(
|
||||
// new HttpRequest("hack", operationResult.Url, string.Empty),
|
||||
// new HttpResponse(new StringWriter()));
|
||||
//}
|
||||
|
||||
_cache.Insert(GetKey(file), operationResult, TimeSpan.FromMinutes(10));
|
||||
}
|
||||
|
||||
var commonLinkUtilitySettings = scope.ServiceProvider.GetService<CommonLinkUtilitySettings>();
|
||||
commonLinkUtilitySettings.ServerUri = serverRootPath;
|
||||
|
||||
var scopeClass = scope.ServiceProvider.GetService<FileConverterQueueScope>();
|
||||
(_, tenantManager, userManager, securityContext, daoFactory, fileSecurity, pathProvider, setupInfo, fileUtility, documentServiceHelper, documentServiceConnector, entryManager, fileConverter) = scopeClass;
|
||||
|
||||
tenantManager.SetCurrentTenant(tenantId);
|
||||
|
||||
securityContext.AuthenticateMeWithoutCookie(account);
|
||||
|
||||
var user = userManager.GetUsers(account.ID);
|
||||
var culture = string.IsNullOrEmpty(user.CultureName) ? tenantManager.GetCurrentTenant().GetCulture() : CultureInfo.GetCultureInfo(user.CultureName);
|
||||
Thread.CurrentThread.CurrentCulture = culture;
|
||||
Thread.CurrentThread.CurrentUICulture = culture;
|
||||
|
||||
if (!fileSecurity.CanReadAsync(file).Result && file.RootFolderType != FolderType.BUNCH)
|
||||
{
|
||||
//No rights in CRM after upload before attach
|
||||
throw new SecurityException(FilesCommonResource.ErrorMassage_SecurityException_ReadFile);
|
||||
}
|
||||
if (file.ContentLength > setupInfo.AvailableFileSize)
|
||||
{
|
||||
throw new Exception(string.Format(FilesCommonResource.ErrorMassage_FileSizeConvert, FileSizeComment.FilesSizeToString(setupInfo.AvailableFileSize)));
|
||||
}
|
||||
|
||||
fileUri = pathProvider.GetFileStreamUrl(file);
|
||||
|
||||
var toExtension = fileUtility.GetInternalExtension(file.Title);
|
||||
var fileExtension = file.ConvertedExtension;
|
||||
var docKey = documentServiceHelper.GetDocKey(file);
|
||||
|
||||
fileUri = documentServiceConnector.ReplaceCommunityAdress(fileUri);
|
||||
(operationResultProgress, convertedFileUrl) = documentServiceConnector.GetConvertedUriAsync(fileUri, fileExtension, toExtension, docKey, password, null, null, true).Result;
|
||||
}
|
||||
catch (Exception exception)
|
||||
{
|
||||
var password = exception.InnerException is DocumentServiceException documentServiceException
|
||||
&& documentServiceException.Code == DocumentServiceException.ErrorCode.ConvertPassword;
|
||||
|
||||
logger.ErrorConvertFileWithUrl(file.Id.ToString(), fileUri, exception);
|
||||
lock (_locker)
|
||||
{
|
||||
if (_conversionQueue.TryGetValue(file, out var operationResult))
|
||||
{
|
||||
if (operationResult.Delete)
|
||||
{
|
||||
_conversionQueue.Remove(file);
|
||||
_cache.Remove(GetKey(file));
|
||||
}
|
||||
else
|
||||
{
|
||||
operationResult.Progress = 100;
|
||||
operationResult.StopDateTime = DateTime.UtcNow;
|
||||
operationResult.Error = exception.Message;
|
||||
if (password)
|
||||
{
|
||||
operationResult.Result = "password";
|
||||
}
|
||||
|
||||
_cache.Insert(GetKey(file), operationResult, TimeSpan.FromMinutes(10));
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
continue;
|
||||
}
|
||||
|
||||
operationResultProgress = Math.Min(operationResultProgress, 100);
|
||||
if (operationResultProgress < 100)
|
||||
{
|
||||
lock (_locker)
|
||||
{
|
||||
if (_conversionQueue.TryGetValue(file, out var operationResult))
|
||||
{
|
||||
if (DateTime.Now - operationResult.StartDateTime > TimeSpan.FromMinutes(10))
|
||||
{
|
||||
operationResult.StopDateTime = DateTime.UtcNow;
|
||||
operationResult.Error = FilesCommonResource.ErrorMassage_ConvertTimeout;
|
||||
logger.ErrorCheckConvertFilesStatus(file.Id.ToString(), file.ContentLength);
|
||||
}
|
||||
else
|
||||
{
|
||||
operationResult.Processed = "";
|
||||
}
|
||||
operationResult.Progress = operationResultProgress;
|
||||
_cache.Insert(GetKey(file), operationResult, TimeSpan.FromMinutes(10));
|
||||
}
|
||||
}
|
||||
|
||||
logger.DebugCheckConvertFilesStatusIterationContinue();
|
||||
|
||||
continue;
|
||||
}
|
||||
|
||||
File<T> newFile = null;
|
||||
var operationResultError = string.Empty;
|
||||
|
||||
try
|
||||
{
|
||||
newFile = fileConverter.SaveConvertedFileAsync(file, convertedFileUrl).Result;
|
||||
}
|
||||
catch (Exception e)
|
||||
{
|
||||
operationResultError = e.Message;
|
||||
|
||||
logger.ErrorOperation(operationResultError, convertedFileUrl, fileUri, e);
|
||||
|
||||
continue;
|
||||
}
|
||||
finally
|
||||
{
|
||||
lock (_locker)
|
||||
{
|
||||
if (_conversionQueue.TryGetValue(file, out var operationResult))
|
||||
{
|
||||
if (operationResult.Delete)
|
||||
{
|
||||
_conversionQueue.Remove(file);
|
||||
_cache.Remove(GetKey(file));
|
||||
}
|
||||
else
|
||||
{
|
||||
if (newFile != null)
|
||||
{
|
||||
var folderDao = daoFactory.GetFolderDao<T>();
|
||||
var folder = folderDao.GetFolderAsync(newFile.ParentId).Result;
|
||||
var folderTitle = fileSecurity.CanReadAsync(folder).Result ? folder.Title : null;
|
||||
operationResult.Result = FileJsonSerializerAsync(entryManager, newFile, folderTitle).Result;
|
||||
}
|
||||
|
||||
operationResult.Progress = 100;
|
||||
operationResult.StopDateTime = DateTime.UtcNow;
|
||||
operationResult.Processed = "1";
|
||||
if (!string.IsNullOrEmpty(operationResultError))
|
||||
{
|
||||
operationResult.Error = operationResultError;
|
||||
}
|
||||
|
||||
_cache.Insert(GetKey(file), operationResult, TimeSpan.FromMinutes(10));
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
logger.DebugCheckConvertFilesStatusIterationEnd();
|
||||
}
|
||||
|
||||
lock (_locker)
|
||||
{
|
||||
_timer.Change(_timerPeriod, _timerPeriod);
|
||||
}
|
||||
}
|
||||
catch (Exception exception)
|
||||
{
|
||||
logger.ErrorWithException(exception);
|
||||
lock (_locker)
|
||||
{
|
||||
_timer.Change(Timeout.Infinite, Timeout.Infinite);
|
||||
}
|
||||
}
|
||||
finally
|
||||
{
|
||||
Monitor.Exit(_singleThread);
|
||||
Dequeue(task);
|
||||
}
|
||||
|
||||
return operation;
|
||||
}
|
||||
|
||||
return null;
|
||||
}
|
||||
|
||||
|
||||
private string GetKey(File<T> f)
|
||||
{
|
||||
return string.Format("fileConvertation-{0}", f.Id);
|
||||
}
|
||||
|
||||
internal async Task<string> FileJsonSerializerAsync(EntryStatusManager EntryManager, File<T> file, string folderTitle)
|
||||
public async Task<string> FileJsonSerializerAsync(EntryStatusManager EntryManager, File<T> file, string folderTitle)
|
||||
{
|
||||
if (file == null)
|
||||
{
|
||||
@ -406,94 +183,73 @@ internal class FileConverterQueue<T> : IDisposable
|
||||
}, options);
|
||||
}
|
||||
|
||||
public void Dispose()
|
||||
private bool Contains(FileConverterOperationResult val)
|
||||
{
|
||||
if (_timer != null)
|
||||
var queueTasks = LoadFromCache();
|
||||
|
||||
return queueTasks.Any(x =>
|
||||
{
|
||||
_timer.Dispose();
|
||||
return String.Compare(x.Source, val.Source) == 0;
|
||||
});
|
||||
}
|
||||
|
||||
private bool IsOrphanCacheItem(FileConverterOperationResult x)
|
||||
{
|
||||
return !string.IsNullOrEmpty(x.Processed)
|
||||
&& (x.Progress == 100 && DateTime.UtcNow - x.StopDateTime > TimeSpan.FromMinutes(1) ||
|
||||
DateTime.UtcNow - x.StopDateTime > TimeSpan.FromMinutes(10));
|
||||
}
|
||||
|
||||
private IEnumerable<FileConverterOperationResult> DeleteOrphanCacheItem(IEnumerable<FileConverterOperationResult> queueTasks)
|
||||
{
|
||||
var listTasks = queueTasks.ToList();
|
||||
|
||||
listTasks.RemoveAll(IsOrphanCacheItem);
|
||||
|
||||
SaveToCache(listTasks);
|
||||
|
||||
return queueTasks;
|
||||
}
|
||||
|
||||
private void SaveToCache(IEnumerable<FileConverterOperationResult> queueTasks)
|
||||
{
|
||||
if (!queueTasks.Any())
|
||||
{
|
||||
_distributedCache.Remove(GetCacheKey());
|
||||
|
||||
return;
|
||||
}
|
||||
|
||||
using var ms = new MemoryStream();
|
||||
|
||||
ProtoBuf.Serializer.Serialize(ms, queueTasks);
|
||||
|
||||
_distributedCache.Set(GetCacheKey(), ms.ToArray(), new DistributedCacheEntryOptions
|
||||
{
|
||||
SlidingExpiration = TimeSpan.FromMinutes(15)
|
||||
});
|
||||
}
|
||||
|
||||
private string GetCacheKey()
|
||||
{
|
||||
return $"{_cache_key_prefix}_{typeof(T).Name}".ToLowerInvariant();
|
||||
}
|
||||
|
||||
private IEnumerable<FileConverterOperationResult> LoadFromCache()
|
||||
{
|
||||
var serializedObject = _distributedCache.Get(GetCacheKey());
|
||||
|
||||
if (serializedObject == null)
|
||||
{
|
||||
return new List<FileConverterOperationResult>();
|
||||
}
|
||||
|
||||
using var ms = new MemoryStream(serializedObject);
|
||||
|
||||
return ProtoBuf.Serializer.Deserialize<List<FileConverterOperationResult>>(ms);
|
||||
}
|
||||
}
|
||||
|
||||
[Scope]
|
||||
public class FileConverterQueueScope
|
||||
{
|
||||
private readonly ILogger _options;
|
||||
private readonly TenantManager _tenantManager;
|
||||
private readonly UserManager _userManager;
|
||||
private readonly SecurityContext _securityContext;
|
||||
private readonly IDaoFactory _daoFactory;
|
||||
private readonly FileSecurity _fileSecurity;
|
||||
private readonly PathProvider _pathProvider;
|
||||
private readonly SetupInfo _setupInfo;
|
||||
private readonly FileUtility _fileUtility;
|
||||
private readonly DocumentServiceHelper _documentServiceHelper;
|
||||
private readonly DocumentServiceConnector _documentServiceConnector;
|
||||
private readonly EntryStatusManager _entryManager;
|
||||
private readonly FileConverter _fileConverter;
|
||||
|
||||
public FileConverterQueueScope(
|
||||
ILogger<FileConverterQueueScope> options,
|
||||
TenantManager tenantManager,
|
||||
UserManager userManager,
|
||||
SecurityContext securityContext,
|
||||
IDaoFactory daoFactory,
|
||||
FileSecurity fileSecurity,
|
||||
PathProvider pathProvider,
|
||||
SetupInfo setupInfo,
|
||||
FileUtility fileUtility,
|
||||
DocumentServiceHelper documentServiceHelper,
|
||||
DocumentServiceConnector documentServiceConnector,
|
||||
EntryStatusManager entryManager,
|
||||
FileConverter fileConverter)
|
||||
{
|
||||
_options = options;
|
||||
_tenantManager = tenantManager;
|
||||
_userManager = userManager;
|
||||
_securityContext = securityContext;
|
||||
_daoFactory = daoFactory;
|
||||
_fileSecurity = fileSecurity;
|
||||
_pathProvider = pathProvider;
|
||||
_setupInfo = setupInfo;
|
||||
_fileUtility = fileUtility;
|
||||
_documentServiceHelper = documentServiceHelper;
|
||||
_documentServiceConnector = documentServiceConnector;
|
||||
_entryManager = entryManager;
|
||||
_fileConverter = fileConverter;
|
||||
}
|
||||
|
||||
|
||||
public void Deconstruct(out ILogger optionsMonitor,
|
||||
out TenantManager tenantManager,
|
||||
out UserManager userManager,
|
||||
out SecurityContext securityContext,
|
||||
out IDaoFactory daoFactory,
|
||||
out FileSecurity fileSecurity,
|
||||
out PathProvider pathProvider,
|
||||
out SetupInfo setupInfo,
|
||||
out FileUtility fileUtility,
|
||||
out DocumentServiceHelper documentServiceHelper,
|
||||
out DocumentServiceConnector documentServiceConnector,
|
||||
out EntryStatusManager entryManager,
|
||||
out FileConverter fileConverter)
|
||||
{
|
||||
optionsMonitor = _options;
|
||||
tenantManager = _tenantManager;
|
||||
userManager = _userManager;
|
||||
securityContext = _securityContext;
|
||||
daoFactory = _daoFactory;
|
||||
fileSecurity = _fileSecurity;
|
||||
pathProvider = _pathProvider;
|
||||
setupInfo = _setupInfo;
|
||||
fileUtility = _fileUtility;
|
||||
documentServiceHelper = _documentServiceHelper;
|
||||
documentServiceConnector = _documentServiceConnector;
|
||||
entryManager = _entryManager;
|
||||
fileConverter = _fileConverter;
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
public class FileJsonSerializerData<T>
|
||||
{
|
||||
public T Id { get; set; }
|
||||
@ -710,9 +466,9 @@ public class FileConverter
|
||||
var uriTuple = await _documentServiceConnector.GetConvertedUriAsync(fileUri, fileExtension, toExtension, docKey, null, null, null, false);
|
||||
var convertUri = uriTuple.ConvertedDocumentUri;
|
||||
|
||||
var operationResult = new ConvertFileOperationResult
|
||||
var operationResult = new FileConverterOperationResult
|
||||
{
|
||||
Source = string.Format("{{\"id\":\"{0}\", \"version\":\"{1}\"}}", file.Id, file.Version),
|
||||
Source = System.Text.Json.JsonSerializer.Serialize(new { id = file.Id, version = file.Version }),
|
||||
OperationType = FileOperationType.Convert,
|
||||
Error = string.Empty,
|
||||
Progress = 0,
|
||||
@ -720,7 +476,7 @@ public class FileConverter
|
||||
Processed = "",
|
||||
Id = string.Empty,
|
||||
TenantId = _tenantManager.GetCurrentTenant().Id,
|
||||
Account = _authContext.CurrentAccount,
|
||||
Account = _authContext.CurrentAccount.ID,
|
||||
Delete = false,
|
||||
StartDateTime = DateTime.Now,
|
||||
Url = _httpContextAccesor?.HttpContext != null ? _httpContextAccesor.HttpContext.Request.GetUrlRewriter().ToString() : null,
|
||||
@ -918,27 +674,6 @@ internal class FileComparer<T> : IEqualityComparer<File<T>>
|
||||
}
|
||||
}
|
||||
|
||||
internal class ConvertFileOperationResult : FileOperationResult
|
||||
{
|
||||
public DateTime StartDateTime { get; set; }
|
||||
public DateTime StopDateTime { get; set; }
|
||||
public int TenantId { get; set; }
|
||||
public IAccount Account { get; set; }
|
||||
public bool Delete { get; set; }
|
||||
public string Url { get; set; }
|
||||
public string Password { get; set; }
|
||||
|
||||
//hack for download
|
||||
public string ServerRootPath { get; set; }
|
||||
}
|
||||
|
||||
public static class FileConverterQueueExtension
|
||||
{
|
||||
public static void Register(DIHelper services)
|
||||
{
|
||||
services.TryAdd<FileConverterQueueScope>();
|
||||
}
|
||||
}
|
||||
|
||||
public static class FileConverterExtension
|
||||
{
|
||||
|
@ -0,0 +1,56 @@
|
||||
// (c) Copyright Ascensio System SIA 2010-2022
|
||||
//
|
||||
// This program is a free software product.
|
||||
// You can redistribute it and/or modify it under the terms
|
||||
// of the GNU Affero General Public License (AGPL) version 3 as published by the Free Software
|
||||
// Foundation. In accordance with Section 7(a) of the GNU AGPL its Section 15 shall be amended
|
||||
// to the effect that Ascensio System SIA expressly excludes the warranty of non-infringement of
|
||||
// any third-party rights.
|
||||
//
|
||||
// This program is distributed WITHOUT ANY WARRANTY, without even the implied warranty
|
||||
// of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. For details, see
|
||||
// the GNU AGPL at: http://www.gnu.org/licenses/agpl-3.0.html
|
||||
//
|
||||
// You can contact Ascensio System SIA at Lubanas st. 125a-25, Riga, Latvia, EU, LV-1021.
|
||||
//
|
||||
// The interactive user interfaces in modified source and object code versions of the Program must
|
||||
// display Appropriate Legal Notices, as required under Section 5 of the GNU AGPL version 3.
|
||||
//
|
||||
// Pursuant to Section 7(b) of the License you must retain the original Product logo when
|
||||
// distributing the program. Pursuant to Section 7(e) we decline to grant you any rights under
|
||||
// trademark law for use of our trademarks.
|
||||
//
|
||||
// All the Product's GUI elements, including illustrations and icon sets, as well as technical writing
|
||||
// content are licensed under the terms of the Creative Commons Attribution-ShareAlike 4.0
|
||||
// International. See the License terms at http://creativecommons.org/licenses/by-sa/4.0/legalcode
|
||||
|
||||
namespace ASC.Web.Files.Utils;
|
||||
|
||||
[ProtoContract]
|
||||
public class FileConverterOperationResult : FileOperationResult
|
||||
{
|
||||
[ProtoMember(1)]
|
||||
public DateTime StartDateTime { get; set; }
|
||||
|
||||
[ProtoMember(2)]
|
||||
public DateTime StopDateTime { get; set; }
|
||||
|
||||
[ProtoMember(3)]
|
||||
public int TenantId { get; set; }
|
||||
|
||||
[ProtoMember(4)]
|
||||
public Guid Account { get; set; }
|
||||
|
||||
[ProtoMember(5)]
|
||||
public bool Delete { get; set; }
|
||||
|
||||
[ProtoMember(6)]
|
||||
public string Url { get; set; }
|
||||
|
||||
[ProtoMember(7)]
|
||||
public string Password { get; set; }
|
||||
|
||||
[ProtoMember(8)]
|
||||
//hack for download
|
||||
public string ServerRootPath { get; set; }
|
||||
}
|
@ -27,14 +27,14 @@
|
||||
namespace ASC.Api.Documents;
|
||||
|
||||
[ConstraintRoute("int")]
|
||||
internal class PrivacyRoomControllerInternal : PrivacyRoomController<int>
|
||||
public class PrivacyRoomControllerInternal : PrivacyRoomController<int>
|
||||
{
|
||||
public PrivacyRoomControllerInternal(SettingsManager settingsManager, EncryptionKeyPairDtoHelper encryptionKeyPairHelper, FileStorageService<int> fileStorageService) : base(settingsManager, encryptionKeyPairHelper, fileStorageService)
|
||||
{
|
||||
}
|
||||
}
|
||||
|
||||
internal class PrivacyRoomControllerThirdparty : PrivacyRoomController<string>
|
||||
public class PrivacyRoomControllerThirdparty : PrivacyRoomController<string>
|
||||
{
|
||||
public PrivacyRoomControllerThirdparty(SettingsManager settingsManager, EncryptionKeyPairDtoHelper encryptionKeyPairHelper, FileStorageService<string> fileStorageService) : base(settingsManager, encryptionKeyPairHelper, fileStorageService)
|
||||
{
|
||||
@ -45,7 +45,7 @@ internal class PrivacyRoomControllerThirdparty : PrivacyRoomController<string>
|
||||
[DefaultRoute]
|
||||
[ApiController]
|
||||
[ControllerName("privacyroom")]
|
||||
internal abstract class PrivacyRoomController<T> : ControllerBase
|
||||
public abstract class PrivacyRoomController<T> : ControllerBase
|
||||
{
|
||||
private readonly EncryptionKeyPairDtoHelper _encryptionKeyPairHelper;
|
||||
private readonly FileStorageService<T> _fileStorageService;
|
||||
@ -81,7 +81,7 @@ internal abstract class PrivacyRoomController<T> : ControllerBase
|
||||
[DefaultRoute]
|
||||
[ApiController]
|
||||
[ControllerName("privacyroom")]
|
||||
public abstract class PrivacyRoomControllerCommon : ControllerBase
|
||||
public class PrivacyRoomControllerCommon : ControllerBase
|
||||
{
|
||||
private readonly AuthContext _authContext;
|
||||
private readonly EncryptionKeyPairDtoHelper _encryptionKeyPairHelper;
|
||||
|
362
products/ASC.Files/Service/FileConverterService.cs
Normal file
362
products/ASC.Files/Service/FileConverterService.cs
Normal file
@ -0,0 +1,362 @@
|
||||
// (c) Copyright Ascensio System SIA 2010-2022
|
||||
//
|
||||
// This program is a free software product.
|
||||
// You can redistribute it and/or modify it under the terms
|
||||
// of the GNU Affero General Public License (AGPL) version 3 as published by the Free Software
|
||||
// Foundation. In accordance with Section 7(a) of the GNU AGPL its Section 15 shall be amended
|
||||
// to the effect that Ascensio System SIA expressly excludes the warranty of non-infringement of
|
||||
// any third-party rights.
|
||||
//
|
||||
// This program is distributed WITHOUT ANY WARRANTY, without even the implied warranty
|
||||
// of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. For details, see
|
||||
// the GNU AGPL at: http://www.gnu.org/licenses/agpl-3.0.html
|
||||
//
|
||||
// You can contact Ascensio System SIA at Lubanas st. 125a-25, Riga, Latvia, EU, LV-1021.
|
||||
//
|
||||
// The interactive user interfaces in modified source and object code versions of the Program must
|
||||
// display Appropriate Legal Notices, as required under Section 5 of the GNU AGPL version 3.
|
||||
//
|
||||
// Pursuant to Section 7(b) of the License you must retain the original Product logo when
|
||||
// distributing the program. Pursuant to Section 7(e) we decline to grant you any rights under
|
||||
// trademark law for use of our trademarks.
|
||||
//
|
||||
// All the Product's GUI elements, including illustrations and icon sets, as well as technical writing
|
||||
// content are licensed under the terms of the Creative Commons Attribution-ShareAlike 4.0
|
||||
// International. See the License terms at http://creativecommons.org/licenses/by-sa/4.0/legalcode
|
||||
|
||||
using System.Globalization;
|
||||
using System.Text.Json;
|
||||
|
||||
using ASC.Common.Log;
|
||||
using ASC.Core.Common.Hosting;
|
||||
using ASC.Core.Common.Hosting.Interfaces;
|
||||
using ASC.Files.Core.Log;
|
||||
using ASC.Files.Core.Resources;
|
||||
using ASC.Web.Files.Utils;
|
||||
using ASC.Web.Studio.Core;
|
||||
|
||||
using static ASC.Web.Core.Files.DocumentService;
|
||||
|
||||
namespace ASC.Files.ThumbnailBuilder;
|
||||
|
||||
[Singletone(Additional = typeof(FileConverterQueueExtension))]
|
||||
internal class FileConverterService<T> : BackgroundService
|
||||
{
|
||||
private readonly IServiceScopeFactory _serviceScopeFactory;
|
||||
private readonly int _timerDelay = 1000;
|
||||
private readonly ILogger<FileConverterService<T>> _logger;
|
||||
|
||||
public FileConverterService(
|
||||
IServiceScopeFactory serviceScopeFactory,
|
||||
ILogger<FileConverterService<T>> logger)
|
||||
{
|
||||
_logger = logger;
|
||||
_serviceScopeFactory = serviceScopeFactory;
|
||||
}
|
||||
|
||||
protected override async Task ExecuteAsync(CancellationToken stoppingToken)
|
||||
{
|
||||
_logger.DebugFileConverterServiceRuning();
|
||||
|
||||
stoppingToken.Register(() => _logger.DebugFileConverterServiceStopping());
|
||||
|
||||
while (!stoppingToken.IsCancellationRequested)
|
||||
{
|
||||
using var serviceScope = _serviceScopeFactory.CreateScope();
|
||||
|
||||
var registerInstanceService = serviceScope.ServiceProvider.GetService<IRegisterInstanceManager<FileConverterService<T>>>();
|
||||
|
||||
if (!await registerInstanceService.IsActive(RegisterInstanceWorkerService<FileConverterService<T>>.InstanceId))
|
||||
{
|
||||
await Task.Delay(1000, stoppingToken);
|
||||
|
||||
continue;
|
||||
}
|
||||
|
||||
await ExecuteCheckFileConverterStatus(serviceScope);
|
||||
|
||||
await Task.Delay(_timerDelay, stoppingToken);
|
||||
}
|
||||
}
|
||||
|
||||
private async Task ExecuteCheckFileConverterStatus(IServiceScope scope)
|
||||
{
|
||||
TenantManager tenantManager;
|
||||
UserManager userManager;
|
||||
SecurityContext securityContext;
|
||||
IDaoFactory daoFactory;
|
||||
FileSecurity fileSecurity;
|
||||
PathProvider pathProvider;
|
||||
SetupInfo setupInfo;
|
||||
FileUtility fileUtility;
|
||||
DocumentServiceHelper documentServiceHelper;
|
||||
DocumentServiceConnector documentServiceConnector;
|
||||
EntryStatusManager entryManager;
|
||||
FileConverter fileConverter;
|
||||
FileConverterQueue<T> fileConverterQueue;
|
||||
|
||||
var logger = scope.ServiceProvider.GetService<ILogger<FileConverterQueue<T>>>();
|
||||
|
||||
try
|
||||
{
|
||||
var scopeClass = scope.ServiceProvider.GetService<FileConverterQueueScope>();
|
||||
(_, tenantManager, userManager, securityContext, daoFactory, fileSecurity, pathProvider, setupInfo, fileUtility, documentServiceHelper, documentServiceConnector, entryManager, fileConverter) = scopeClass;
|
||||
|
||||
fileConverterQueue = scope.ServiceProvider.GetService<FileConverterQueue<T>>();
|
||||
|
||||
var _conversionQueue = fileConverterQueue.GetAllTask().ToList();
|
||||
|
||||
logger.DebugRunCheckConvertFilesStatus(_conversionQueue.Count);
|
||||
|
||||
var filesIsConverting = _conversionQueue
|
||||
.Where(x => string.IsNullOrEmpty(x.Processed))
|
||||
.ToList();
|
||||
|
||||
foreach (var converter in filesIsConverting)
|
||||
{
|
||||
var fileId = JsonDocument.Parse(converter.Source).RootElement.GetProperty("id").Deserialize<T>();
|
||||
var fileVersion = JsonDocument.Parse(converter.Source).RootElement.GetProperty("version").Deserialize<int>();
|
||||
|
||||
int operationResultProgress;
|
||||
var password = converter.Password;
|
||||
|
||||
var commonLinkUtilitySettings = scope.ServiceProvider.GetService<CommonLinkUtilitySettings>();
|
||||
commonLinkUtilitySettings.ServerUri = converter.ServerRootPath;
|
||||
|
||||
tenantManager.SetCurrentTenant(converter.TenantId);
|
||||
|
||||
securityContext.AuthenticateMeWithoutCookie(converter.Account);
|
||||
|
||||
var file = await daoFactory.GetFileDao<T>().GetFileAsync(fileId, fileVersion);
|
||||
var fileUri = file.Id.ToString();
|
||||
|
||||
string convertedFileUrl;
|
||||
|
||||
try
|
||||
{
|
||||
|
||||
var user = userManager.GetUsers(converter.Account);
|
||||
|
||||
var culture = string.IsNullOrEmpty(user.CultureName) ? tenantManager.GetCurrentTenant().GetCulture() : CultureInfo.GetCultureInfo(user.CultureName);
|
||||
|
||||
Thread.CurrentThread.CurrentCulture = culture;
|
||||
Thread.CurrentThread.CurrentUICulture = culture;
|
||||
|
||||
if (!fileSecurity.CanReadAsync(file).Result && file.RootFolderType != FolderType.BUNCH)
|
||||
{
|
||||
//No rights in CRM after upload before attach
|
||||
throw new System.Security.SecurityException(FilesCommonResource.ErrorMassage_SecurityException_ReadFile);
|
||||
}
|
||||
|
||||
if (file.ContentLength > setupInfo.AvailableFileSize)
|
||||
{
|
||||
throw new Exception(string.Format(FilesCommonResource.ErrorMassage_FileSizeConvert, FileSizeComment.FilesSizeToString(setupInfo.AvailableFileSize)));
|
||||
}
|
||||
|
||||
fileUri = pathProvider.GetFileStreamUrl(file);
|
||||
|
||||
var toExtension = fileUtility.GetInternalExtension(file.Title);
|
||||
var fileExtension = file.ConvertedExtension;
|
||||
var docKey = documentServiceHelper.GetDocKey(file);
|
||||
|
||||
fileUri = documentServiceConnector.ReplaceCommunityAdress(fileUri);
|
||||
(operationResultProgress, convertedFileUrl) = documentServiceConnector.GetConvertedUriAsync(fileUri, fileExtension, toExtension, docKey, password, null, null, true).Result;
|
||||
}
|
||||
catch (Exception exception)
|
||||
{
|
||||
var password1 = exception.InnerException is DocumentServiceException documentServiceException
|
||||
&& documentServiceException.Code == DocumentServiceException.ErrorCode.ConvertPassword;
|
||||
|
||||
logger.ErrorConvertFileWithUrl(file.Id.ToString(), fileUri, exception);
|
||||
|
||||
var operationResult = converter;
|
||||
|
||||
if (operationResult.Delete)
|
||||
{
|
||||
_conversionQueue.Remove(operationResult);
|
||||
}
|
||||
else
|
||||
{
|
||||
operationResult.Progress = 100;
|
||||
operationResult.StopDateTime = DateTime.UtcNow;
|
||||
operationResult.Error = exception.Message;
|
||||
|
||||
if (password1)
|
||||
{
|
||||
operationResult.Result = "password";
|
||||
}
|
||||
}
|
||||
|
||||
continue;
|
||||
}
|
||||
|
||||
operationResultProgress = Math.Min(operationResultProgress, 100);
|
||||
|
||||
if (operationResultProgress < 100)
|
||||
{
|
||||
var operationResult = converter;
|
||||
|
||||
if (DateTime.Now - operationResult.StartDateTime > TimeSpan.FromMinutes(10))
|
||||
{
|
||||
operationResult.StopDateTime = DateTime.UtcNow;
|
||||
operationResult.Error = FilesCommonResource.ErrorMassage_ConvertTimeout;
|
||||
|
||||
logger.ErrorCheckConvertFilesStatus(file.Id.ToString(), file.ContentLength);
|
||||
}
|
||||
else
|
||||
{
|
||||
operationResult.Processed = "";
|
||||
}
|
||||
|
||||
operationResult.Progress = operationResultProgress;
|
||||
|
||||
logger.DebugCheckConvertFilesStatusIterationContinue();
|
||||
|
||||
continue;
|
||||
}
|
||||
|
||||
File<T> newFile = null;
|
||||
|
||||
var operationResultError = string.Empty;
|
||||
|
||||
try
|
||||
{
|
||||
newFile = fileConverter.SaveConvertedFileAsync(file, convertedFileUrl).Result;
|
||||
}
|
||||
catch (Exception e)
|
||||
{
|
||||
operationResultError = e.Message;
|
||||
|
||||
logger.ErrorOperation(operationResultError, convertedFileUrl, fileUri, e);
|
||||
|
||||
continue;
|
||||
}
|
||||
finally
|
||||
{
|
||||
var operationResult = converter;
|
||||
|
||||
if (operationResult.Delete)
|
||||
{
|
||||
_conversionQueue.Remove(operationResult);
|
||||
}
|
||||
else
|
||||
{
|
||||
if (newFile != null)
|
||||
{
|
||||
var folderDao = daoFactory.GetFolderDao<T>();
|
||||
var folder = folderDao.GetFolderAsync(newFile.ParentId).Result;
|
||||
var folderTitle = fileSecurity.CanReadAsync(folder).Result ? folder.Title : null;
|
||||
|
||||
operationResult.Result = fileConverterQueue.FileJsonSerializerAsync(entryManager, newFile, folderTitle).Result;
|
||||
}
|
||||
|
||||
operationResult.Progress = 100;
|
||||
operationResult.StopDateTime = DateTime.UtcNow;
|
||||
operationResult.Processed = "1";
|
||||
|
||||
if (!string.IsNullOrEmpty(operationResultError))
|
||||
{
|
||||
operationResult.Error = operationResultError;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
logger.DebugCheckConvertFilesStatusIterationEnd();
|
||||
}
|
||||
|
||||
fileConverterQueue.SetAllTask(_conversionQueue);
|
||||
|
||||
}
|
||||
catch (Exception exception)
|
||||
{
|
||||
logger.ErrorWithException(exception);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
public static class FileConverterQueueExtension
|
||||
{
|
||||
public static void Register(DIHelper services)
|
||||
{
|
||||
services.TryAdd<FileConverterQueueScope>();
|
||||
}
|
||||
}
|
||||
|
||||
[Scope]
|
||||
public class FileConverterQueueScope
|
||||
{
|
||||
private readonly ILogger _options;
|
||||
private readonly TenantManager _tenantManager;
|
||||
private readonly UserManager _userManager;
|
||||
private readonly SecurityContext _securityContext;
|
||||
private readonly IDaoFactory _daoFactory;
|
||||
private readonly FileSecurity _fileSecurity;
|
||||
private readonly PathProvider _pathProvider;
|
||||
private readonly SetupInfo _setupInfo;
|
||||
private readonly FileUtility _fileUtility;
|
||||
private readonly DocumentServiceHelper _documentServiceHelper;
|
||||
private readonly DocumentServiceConnector _documentServiceConnector;
|
||||
private readonly EntryStatusManager _entryManager;
|
||||
private readonly FileConverter _fileConverter;
|
||||
|
||||
public FileConverterQueueScope(
|
||||
ILogger<FileConverterQueueScope> options,
|
||||
TenantManager tenantManager,
|
||||
UserManager userManager,
|
||||
SecurityContext securityContext,
|
||||
IDaoFactory daoFactory,
|
||||
FileSecurity fileSecurity,
|
||||
PathProvider pathProvider,
|
||||
SetupInfo setupInfo,
|
||||
FileUtility fileUtility,
|
||||
DocumentServiceHelper documentServiceHelper,
|
||||
DocumentServiceConnector documentServiceConnector,
|
||||
EntryStatusManager entryManager,
|
||||
FileConverter fileConverter)
|
||||
{
|
||||
_options = options;
|
||||
_tenantManager = tenantManager;
|
||||
_userManager = userManager;
|
||||
_securityContext = securityContext;
|
||||
_daoFactory = daoFactory;
|
||||
_fileSecurity = fileSecurity;
|
||||
_pathProvider = pathProvider;
|
||||
_setupInfo = setupInfo;
|
||||
_fileUtility = fileUtility;
|
||||
_documentServiceHelper = documentServiceHelper;
|
||||
_documentServiceConnector = documentServiceConnector;
|
||||
_entryManager = entryManager;
|
||||
_fileConverter = fileConverter;
|
||||
}
|
||||
|
||||
|
||||
public void Deconstruct(out ILogger optionsMonitor,
|
||||
out TenantManager tenantManager,
|
||||
out UserManager userManager,
|
||||
out SecurityContext securityContext,
|
||||
out IDaoFactory daoFactory,
|
||||
out FileSecurity fileSecurity,
|
||||
out PathProvider pathProvider,
|
||||
out SetupInfo setupInfo,
|
||||
out FileUtility fileUtility,
|
||||
out DocumentServiceHelper documentServiceHelper,
|
||||
out DocumentServiceConnector documentServiceConnector,
|
||||
out EntryStatusManager entryManager,
|
||||
out FileConverter fileConverter)
|
||||
{
|
||||
optionsMonitor = _options;
|
||||
tenantManager = _tenantManager;
|
||||
userManager = _userManager;
|
||||
securityContext = _securityContext;
|
||||
daoFactory = _daoFactory;
|
||||
fileSecurity = _fileSecurity;
|
||||
pathProvider = _pathProvider;
|
||||
setupInfo = _setupInfo;
|
||||
fileUtility = _fileUtility;
|
||||
documentServiceHelper = _documentServiceHelper;
|
||||
documentServiceConnector = _documentServiceConnector;
|
||||
entryManager = _entryManager;
|
||||
fileConverter = _fileConverter;
|
||||
}
|
||||
|
||||
}
|
@ -25,7 +25,7 @@
|
||||
// International. See the License terms at http://creativecommons.org/licenses/by-sa/4.0/legalcode
|
||||
|
||||
namespace ASC.Files.Core.Log;
|
||||
internal static partial class FileConverterLogger
|
||||
public static partial class FileConverterLogger
|
||||
{
|
||||
[LoggerMessage(Level = LogLevel.Debug, Message = "Run CheckConvertFilesStatus: count {count}")]
|
||||
public static partial void DebugRunCheckConvertFilesStatus(this ILogger logger, int count);
|
||||
@ -44,4 +44,11 @@ internal static partial class FileConverterLogger
|
||||
|
||||
[LoggerMessage(Level = LogLevel.Error, Message = "CheckConvertFilesStatus timeout: {fileId} ({contentLengthString})")]
|
||||
public static partial void ErrorCheckConvertFilesStatus(this ILogger logger, string fileId, long contentLengthString);
|
||||
|
||||
[LoggerMessage(Level = LogLevel.Debug, Message = "FileConverterService is starting.")]
|
||||
public static partial void DebugFileConverterServiceRuning(this ILogger logger);
|
||||
|
||||
[LoggerMessage(Level = LogLevel.Debug, Message = "FileConverterService is stopping")]
|
||||
public static partial void DebugFileConverterServiceStopping(this ILogger logger);
|
||||
|
||||
}
|
@ -68,6 +68,13 @@ builder.Host.ConfigureDefault(args, (hostContext, config, env, path) =>
|
||||
|
||||
diHelper.TryAdd<FileDataQueue>();
|
||||
|
||||
services.AddActivePassiveHostedService<FileConverterService<string>>();
|
||||
diHelper.TryAdd<FileConverterService<string>>();
|
||||
|
||||
services.AddActivePassiveHostedService<FileConverterService<int>>();
|
||||
diHelper.TryAdd<FileConverterService<int>>();
|
||||
|
||||
|
||||
services.AddHostedService<ThumbnailBuilderService>();
|
||||
diHelper.TryAdd<ThumbnailBuilderService>();
|
||||
|
||||
|
@ -31,7 +31,7 @@
|
||||
<PackageReference Include="Moq" Version="4.14.7" />
|
||||
<PackageReference Include="MSTest.TestFramework" Version="2.1.2" />
|
||||
<PackageReference Include="NEST" Version="7.15.2" />
|
||||
<PackageReference Include="NLog" Version="4.7.15" />
|
||||
<PackageReference Include="NLog" Version="5.0.0" />
|
||||
<PackageReference Include="nunit" Version="3.13.3" />
|
||||
<PackageReference Include="NUnit3TestAdapter" Version="4.2.1" />
|
||||
<PackageReference Include="Microsoft.NET.Test.Sdk" Version="16.9.4" />
|
||||
|
@ -206,113 +206,118 @@ public class MailServiceHelper
|
||||
{
|
||||
DemandPermission();
|
||||
|
||||
using var transaction = MailDbContext.Database.BeginTransaction();
|
||||
var strategy = MailDbContext.Database.CreateExecutionStrategy();
|
||||
|
||||
var mailboxProvider = new MailboxProvider
|
||||
strategy.Execute(() =>
|
||||
{
|
||||
Id = 0,
|
||||
Name = hostname
|
||||
};
|
||||
using var transaction = MailDbContext.Database.BeginTransaction();
|
||||
|
||||
var pReq = MailDbContext.MailboxProvider.Add(mailboxProvider);
|
||||
MailDbContext.SaveChanges();
|
||||
mailboxProvider = pReq.Entity;
|
||||
|
||||
var providerId = mailboxProvider.Id;
|
||||
|
||||
var mailboxServer = new MailboxServer
|
||||
{
|
||||
Id = 0,
|
||||
IdProvider = providerId,
|
||||
Type = "smtp",
|
||||
Hostname = hostname,
|
||||
Port = 587,
|
||||
SocketType = "STARTTLS",
|
||||
UserName = "%EMAILADDRESS%",
|
||||
Authentication = "",
|
||||
IsUserData = false
|
||||
};
|
||||
|
||||
var req = MailDbContext.MailboxServer.Add(mailboxServer);
|
||||
MailDbContext.SaveChanges();
|
||||
|
||||
mailboxServer = req.Entity;
|
||||
|
||||
var smtpServerId = mailboxServer.Id;
|
||||
|
||||
mailboxServer = new MailboxServer
|
||||
{
|
||||
Id = 0,
|
||||
IdProvider = providerId,
|
||||
Type = "imap",
|
||||
Hostname = hostname,
|
||||
Port = 143,
|
||||
SocketType = "STARTTLS",
|
||||
UserName = "%EMAILADDRESS%",
|
||||
Authentication = "",
|
||||
IsUserData = false
|
||||
};
|
||||
|
||||
req = MailDbContext.MailboxServer.Add(mailboxServer);
|
||||
MailDbContext.SaveChanges();
|
||||
|
||||
mailboxServer = req.Entity;
|
||||
|
||||
var imapServerId = mailboxServer.Id;
|
||||
|
||||
var mailServerData = MailDbContext.ServerServer.FirstOrDefault();
|
||||
|
||||
var connectionString = JsonConvert.SerializeObject(mailServer);
|
||||
|
||||
var server = new ServerServer
|
||||
{
|
||||
Id = 0,
|
||||
MxRecord = hostname,
|
||||
ConnectionString = connectionString,
|
||||
ServerType = 2,
|
||||
SmtpSettingsId = smtpServerId,
|
||||
ImapSettingsId = imapServerId
|
||||
};
|
||||
|
||||
MailDbContext.ServerServer.Add(server);
|
||||
MailDbContext.SaveChanges();
|
||||
|
||||
if (mailServerData != null)
|
||||
{
|
||||
server = MailDbContext.ServerServer.Where(r => r.Id == mailServerData.Id).FirstOrDefault();
|
||||
MailDbContext.ServerServer.Remove(server);
|
||||
MailDbContext.SaveChanges();
|
||||
|
||||
providerId = MailDbContext.MailboxServer
|
||||
.Where(r => r.Id == mailServerData.SmtpSettingsId)
|
||||
.Select(r => r.IdProvider)
|
||||
.FirstOrDefault();
|
||||
|
||||
var providers = MailDbContext.MailboxProvider.Where(r => r.Id == providerId).ToList();
|
||||
MailDbContext.MailboxProvider.RemoveRange(providers);
|
||||
MailDbContext.SaveChanges();
|
||||
|
||||
var servers = MailDbContext.MailboxServer
|
||||
.Where(r => new[] { mailServerData.SmtpSettingsId, mailServerData.ImapSettingsId }.Any(a => a == r.Id))
|
||||
.ToList();
|
||||
|
||||
MailDbContext.MailboxServer.RemoveRange(servers);
|
||||
MailDbContext.SaveChanges();
|
||||
|
||||
var mailboxId = MailDbContext.Mailbox
|
||||
.Where(r => r.IdSmtpServer == mailServerData.SmtpSettingsId)
|
||||
.Where(r => r.IdInServer == mailServerData.ImapSettingsId)
|
||||
.ToArray();
|
||||
|
||||
foreach (var m in mailboxId)
|
||||
var mailboxProvider = new MailboxProvider
|
||||
{
|
||||
m.IdSmtpServer = smtpServerId;
|
||||
m.IdInServer = imapServerId;
|
||||
}
|
||||
MailDbContext.SaveChanges();
|
||||
}
|
||||
Id = 0,
|
||||
Name = hostname
|
||||
};
|
||||
|
||||
transaction.Commit();
|
||||
var pReq = MailDbContext.MailboxProvider.Add(mailboxProvider);
|
||||
MailDbContext.SaveChanges();
|
||||
mailboxProvider = pReq.Entity;
|
||||
|
||||
var providerId = mailboxProvider.Id;
|
||||
|
||||
var mailboxServer = new MailboxServer
|
||||
{
|
||||
Id = 0,
|
||||
IdProvider = providerId,
|
||||
Type = "smtp",
|
||||
Hostname = hostname,
|
||||
Port = 587,
|
||||
SocketType = "STARTTLS",
|
||||
UserName = "%EMAILADDRESS%",
|
||||
Authentication = "",
|
||||
IsUserData = false
|
||||
};
|
||||
|
||||
var req = MailDbContext.MailboxServer.Add(mailboxServer);
|
||||
MailDbContext.SaveChanges();
|
||||
|
||||
mailboxServer = req.Entity;
|
||||
|
||||
var smtpServerId = mailboxServer.Id;
|
||||
|
||||
mailboxServer = new MailboxServer
|
||||
{
|
||||
Id = 0,
|
||||
IdProvider = providerId,
|
||||
Type = "imap",
|
||||
Hostname = hostname,
|
||||
Port = 143,
|
||||
SocketType = "STARTTLS",
|
||||
UserName = "%EMAILADDRESS%",
|
||||
Authentication = "",
|
||||
IsUserData = false
|
||||
};
|
||||
|
||||
req = MailDbContext.MailboxServer.Add(mailboxServer);
|
||||
MailDbContext.SaveChanges();
|
||||
|
||||
mailboxServer = req.Entity;
|
||||
|
||||
var imapServerId = mailboxServer.Id;
|
||||
|
||||
var mailServerData = MailDbContext.ServerServer.FirstOrDefault();
|
||||
|
||||
var connectionString = JsonConvert.SerializeObject(mailServer);
|
||||
|
||||
var server = new ServerServer
|
||||
{
|
||||
Id = 0,
|
||||
MxRecord = hostname,
|
||||
ConnectionString = connectionString,
|
||||
ServerType = 2,
|
||||
SmtpSettingsId = smtpServerId,
|
||||
ImapSettingsId = imapServerId
|
||||
};
|
||||
|
||||
MailDbContext.ServerServer.Add(server);
|
||||
MailDbContext.SaveChanges();
|
||||
|
||||
if (mailServerData != null)
|
||||
{
|
||||
server = MailDbContext.ServerServer.Where(r => r.Id == mailServerData.Id).FirstOrDefault();
|
||||
MailDbContext.ServerServer.Remove(server);
|
||||
MailDbContext.SaveChanges();
|
||||
|
||||
providerId = MailDbContext.MailboxServer
|
||||
.Where(r => r.Id == mailServerData.SmtpSettingsId)
|
||||
.Select(r => r.IdProvider)
|
||||
.FirstOrDefault();
|
||||
|
||||
var providers = MailDbContext.MailboxProvider.Where(r => r.Id == providerId).ToList();
|
||||
MailDbContext.MailboxProvider.RemoveRange(providers);
|
||||
MailDbContext.SaveChanges();
|
||||
|
||||
var servers = MailDbContext.MailboxServer
|
||||
.Where(r => new[] { mailServerData.SmtpSettingsId, mailServerData.ImapSettingsId }.Any(a => a == r.Id))
|
||||
.ToList();
|
||||
|
||||
MailDbContext.MailboxServer.RemoveRange(servers);
|
||||
MailDbContext.SaveChanges();
|
||||
|
||||
var mailboxId = MailDbContext.Mailbox
|
||||
.Where(r => r.IdSmtpServer == mailServerData.SmtpSettingsId)
|
||||
.Where(r => r.IdInServer == mailServerData.ImapSettingsId)
|
||||
.ToArray();
|
||||
|
||||
foreach (var m in mailboxId)
|
||||
{
|
||||
m.IdSmtpServer = smtpServerId;
|
||||
m.IdInServer = imapServerId;
|
||||
}
|
||||
MailDbContext.SaveChanges();
|
||||
}
|
||||
|
||||
transaction.Commit();
|
||||
});
|
||||
|
||||
_mailServiceHelperStorage.Remove();
|
||||
}
|
||||
|
@ -131,27 +131,33 @@ public class StatisticManager
|
||||
_lastSave = DateTime.UtcNow;
|
||||
}
|
||||
|
||||
using var tx = WebstudioDbContext.Database.BeginTransaction(IsolationLevel.ReadUncommitted);
|
||||
foreach (var v in visits)
|
||||
var strategy = WebstudioDbContext.Database.CreateExecutionStrategy();
|
||||
|
||||
strategy.Execute(() =>
|
||||
{
|
||||
var w = new DbWebstudioUserVisit
|
||||
{
|
||||
TenantId = v.TenantID,
|
||||
ProductId = v.ProductID,
|
||||
UserId = v.UserID,
|
||||
VisitDate = v.VisitDate.Date,
|
||||
FirstVisitTime = v.VisitDate,
|
||||
VisitCount = v.VisitCount
|
||||
};
|
||||
using var tx = WebstudioDbContext.Database.BeginTransaction(IsolationLevel.ReadUncommitted);
|
||||
|
||||
if (v.LastVisitTime.HasValue)
|
||||
foreach (var v in visits)
|
||||
{
|
||||
w.LastVisitTime = v.LastVisitTime.Value;
|
||||
var w = new DbWebstudioUserVisit
|
||||
{
|
||||
TenantId = v.TenantID,
|
||||
ProductId = v.ProductID,
|
||||
UserId = v.UserID,
|
||||
VisitDate = v.VisitDate.Date,
|
||||
FirstVisitTime = v.VisitDate,
|
||||
VisitCount = v.VisitCount
|
||||
};
|
||||
|
||||
if (v.LastVisitTime.HasValue)
|
||||
{
|
||||
w.LastVisitTime = v.LastVisitTime.Value;
|
||||
}
|
||||
|
||||
WebstudioDbContext.WebstudioUserVisit.Add(w);
|
||||
WebstudioDbContext.SaveChanges();
|
||||
}
|
||||
|
||||
WebstudioDbContext.WebstudioUserVisit.Add(w);
|
||||
WebstudioDbContext.SaveChanges();
|
||||
}
|
||||
tx.Commit();
|
||||
tx.Commit();
|
||||
});
|
||||
}
|
||||
}
|
||||
|
Loading…
Reference in New Issue
Block a user