Merge pull request #779 from ONLYOFFICE/feature/user-quota

Feature/user quota
This commit is contained in:
Pavel Bannov 2022-10-07 17:09:52 +03:00 committed by GitHub
commit d0682bb467
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
46 changed files with 1223 additions and 1282 deletions

View File

@ -34,10 +34,13 @@ namespace ASC.ActiveDirectory.Base.Data;
public class LdapObjectExtension
{
private readonly TenantUtil _tenantUtil;
private readonly SettingsManager _settingsManager;
private readonly ILogger<LdapObjectExtension> _logger;
public LdapObjectExtension(TenantUtil tenantUtil, ILogger<LdapObjectExtension> logger)
public LdapObjectExtension(TenantUtil tenantUtil, SettingsManager settingsManager, ILogger<LdapObjectExtension> logger)
{
_tenantUtil = tenantUtil;
_settingsManager = settingsManager;
_logger = logger;
}
public string GetAttribute(LdapObject ldapObject, string attribute)
@ -145,6 +148,8 @@ public class LdapObjectExtension
var emails = GetContacts(ldapUser, Mapping.AdditionalMail, settings);
var skype = GetContacts(ldapUser, Mapping.Skype, settings);
var quotaSettings = _settingsManager.Load<TenantUserQuotaSettings>();
var quota = settings.LdapMapping.ContainsKey(Mapping.UserQuotaLimit) ? ByteConverter.ConvertSizeToBytes(GetAttribute(ldapUser, settings.LdapMapping[Mapping.UserQuotaLimit])) : quotaSettings.DefaultUserQuota;
if (string.IsNullOrEmpty(userName))
{
@ -168,7 +173,8 @@ public class LdapObjectExtension
Title = !string.IsNullOrEmpty(title) ? title : string.Empty,
Location = !string.IsNullOrEmpty(location) ? location : string.Empty,
WorkFromDate = _tenantUtil.DateTimeNow(),
ContactsList = contacts
ContactsList = contacts,
LdapQouta = quota
};
if (!string.IsNullOrEmpty(firstName))

View File

@ -57,7 +57,9 @@ public class LdapSettings : ISettings<LdapSettings>, ICloneable
AdditionalPhone,
AdditionalMobilePhone,
AdditionalMail,
Skype
Skype,
UserQuotaLimit
}
public enum AccessRight

View File

@ -68,8 +68,9 @@ global using ASC.Notify.Recipients;
global using ASC.Security.Cryptography;
global using ASC.Web.Core;
global using ASC.Web.Core.PublicResources;
global using ASC.Web.Core.Users;
global using ASC.Web.Studio.Utility;
global using ASC.Web.Core.Users;
global using ASC.Web.Core.Utility;
global using ASC.Web.Studio.Utility;
global using Microsoft.EntityFrameworkCore;
global using Microsoft.Extensions.Configuration;
@ -80,4 +81,6 @@ global using Microsoft.Extensions.Logging;
global using Novell.Directory.Ldap;
global using Novell.Directory.Ldap.Controls;
global using Novell.Directory.Ldap.Rfc2251;
global using Novell.Directory.Ldap.Utilclass;
global using Novell.Directory.Ldap.Utilclass;
global using ByteConverter = ASC.Core.Common.ByteConverter;

View File

@ -155,6 +155,13 @@ public class LdapUserManager
portalUserInfo = _userManager.SaveUserInfo(ldapUserInfo);
var quotaSettings = _settingsManager.Load<TenantUserQuotaSettings>();
if (quotaSettings.EnableUserQuota)
{
_settingsManager.SaveForUser(new UserQuotaSettings { UserQuota = ldapUserInfo.LdapQouta }, ldapUserInfo.Id);
}
var passwordHash = LdapUtils.GeneratePassword();
_logger.DebugSetUserPassword(portalUserInfo.Id);

View File

@ -56,6 +56,8 @@ public class EmployeeFullDto : EmployeeDto
public MobilePhoneActivationStatus MobilePhoneActivationStatus { get; set; }
public bool IsSSO { get; set; }
public DarkThemeSettingsEnum? Theme { get; set; }
public long QuotaLimit { get; set; }
public double UsedSpace { get; set; }
public static new EmployeeFullDto GetSample()
{
@ -97,6 +99,8 @@ public class EmployeeFullDtoHelper : EmployeeDtoHelper
private readonly WebItemSecurity _webItemSecurity;
private readonly ApiDateTimeHelper _apiDateTimeHelper;
private readonly WebItemManager _webItemManager;
private readonly SettingsManager _settingsManager;
private readonly IQuotaService _quotaService;
public EmployeeFullDtoHelper(
ApiContext context,
@ -106,13 +110,17 @@ public class EmployeeFullDtoHelper : EmployeeDtoHelper
CommonLinkUtility commonLinkUtility,
DisplayUserSettingsHelper displayUserSettingsHelper,
ApiDateTimeHelper apiDateTimeHelper,
WebItemManager webItemManager)
WebItemManager webItemManager,
SettingsManager settingsManager,
IQuotaService quotaService)
: base(context, displayUserSettingsHelper, userPhotoManager, commonLinkUtility, userManager)
{
_context = context;
_webItemSecurity = webItemSecurity;
_apiDateTimeHelper = apiDateTimeHelper;
_webItemManager = webItemManager;
_settingsManager = settingsManager;
_quotaService = quotaService;
}
public static Expression<Func<User, UserInfo>> GetExpression(ApiContext apiContext)
@ -186,10 +194,20 @@ public class EmployeeFullDtoHelper : EmployeeDtoHelper
IsAdmin = _userManager.IsAdmin(userInfo),
IsOwner = userInfo.IsOwner(_context.Tenant),
IsLDAP = userInfo.IsLDAP(),
IsSSO = userInfo.IsSSO()
};
IsSSO = userInfo.IsSSO()
await Init(result, userInfo);
};
await Init(result, userInfo);
var quotaSettings = _settingsManager.Load<TenantUserQuotaSettings>();
if (quotaSettings.EnableUserQuota)
{
result.UsedSpace = Math.Max(0, _quotaService.FindUserQuotaRows(_context.Tenant.Id, userInfo.Id).Where(r => !string.IsNullOrEmpty(r.Tag)).Sum(r => r.Counter));
var userQuotaSettings = _settingsManager.LoadForUser<UserQuotaSettings>(userInfo);
result.QuotaLimit = userQuotaSettings != null ? userQuotaSettings.UserQuota : quotaSettings.DefaultUserQuota;
}
if (userInfo.Sex.HasValue)
{

View File

@ -41,4 +41,46 @@ public static class ByteConverter
return bytes < MB ? bytes * MB : bytes;
}
public static long ConvertSizeToBytes(string size)
{
long bytes = 0;
try
{
var regex = new Regex(@"\d+|\w+");
var matches = regex.Matches(size);
if (matches.Count > 0)
{
var num = int.Parse(matches[0].Value);
var unit = matches[1].Value.ToLower();
switch (unit)
{
case "bytes":
bytes = num;
break;
case "kb":
bytes = num * 1024;
break;
case "mb":
bytes = Convert.ToInt64(num * Math.Pow(1024, 2));
break;
case "gb":
bytes = Convert.ToInt64(num * Math.Pow(1024, 3));
break;
case "tb":
bytes = Convert.ToInt64(num * Math.Pow(1024, 4));
break;
case "pb":
bytes = Convert.ToInt64(num * Math.Pow(1024, 5));
break;
}
return bytes;
}
}
catch (Exception)
{
}
return -1;
}
}

View File

@ -31,6 +31,7 @@ class QuotaServiceCache
{
internal const string KeyQuota = "quota";
internal const string KeyQuotaRows = "quotarows";
internal const string KeyUserQuotaRows = "userquotarows";
internal readonly ICache Cache;
internal readonly ICacheNotify<QuotaCacheItem> CacheNotify;
internal readonly bool QuotaCacheEnabled;
@ -122,7 +123,12 @@ class CachedQuotaService : IQuotaService
public void SetTenantQuotaRow(TenantQuotaRow row, bool exchange)
{
Service.SetTenantQuotaRow(row, exchange);
CacheNotify.Publish(new QuotaCacheItem { Key = GetKey(row.Tenant) }, CacheNotifyAction.InsertOrUpdate);
CacheNotify.Publish(new QuotaCacheItem { Key = GetKey(row.Tenant) }, CacheNotifyAction.Any);
if (row.UserId != Guid.Empty)
{
CacheNotify.Publish(new QuotaCacheItem { Key = GetKey(row.Tenant, row.UserId) }, CacheNotifyAction.Any);
}
}
public IEnumerable<TenantQuotaRow> FindTenantQuotaRows(int tenantId)
@ -139,8 +145,27 @@ class CachedQuotaService : IQuotaService
return result;
}
public IEnumerable<TenantQuotaRow> FindUserQuotaRows(int tenantId, Guid userId)
{
var key = GetKey(tenantId, userId);
var result = Cache.Get<IEnumerable<TenantQuotaRow>>(key);
if (result == null)
{
result = Service.FindUserQuotaRows(tenantId, userId);
Cache.Insert(key, result, DateTime.UtcNow.Add(_cacheExpiration));
}
return result;
}
public string GetKey(int tenant)
{
return QuotaServiceCache.KeyQuotaRows + tenant;
}
public string GetKey(int tenant, Guid userId)
{
return QuotaServiceCache.KeyQuotaRows + tenant + userId;
}
}

View File

@ -31,6 +31,7 @@ public interface IQuotaService
{
IEnumerable<TenantQuota> GetTenantQuotas();
IEnumerable<TenantQuotaRow> FindTenantQuotaRows(int tenantId);
IEnumerable<TenantQuotaRow> FindUserQuotaRows(int tenantId, Guid userId);
TenantQuota GetTenantQuota(int id);
TenantQuota SaveTenantQuota(TenantQuota quota);
void RemoveTenantQuota(int id);

View File

@ -71,6 +71,7 @@ public sealed class UserInfo : IDirectRecipient, ICloneable, IMapFrom<User>
public string MobilePhone { get; set; }
public MobilePhoneActivationStatus MobilePhoneActivationStatus { get; set; }
public string Sid { get; set; } // LDAP user identificator
public long LdapQouta { get; set; } // LDAP user quota attribute
public string SsoNameId { get; set; } // SSO SAML user identificator
public string SsoSessionId { get; set; } // SSO SAML user session identificator
public DateTime CreateDate { get; set; }

View File

@ -31,7 +31,6 @@ class DbQuotaService : IQuotaService
{
private readonly IDbContextFactory<CoreDbContext> _dbContextFactory;
private readonly IMapper _mapper;
public DbQuotaService(IDbContextFactory<CoreDbContext> dbContextManager, IMapper mapper)
{
_dbContextFactory = dbContextManager;
@ -102,27 +101,46 @@ class DbQuotaService : IQuotaService
using var coreDbContext = _dbContextFactory.CreateDbContext();
using var tx = coreDbContext.Database.BeginTransaction();
var counter = coreDbContext.QuotaRows
.Where(r => r.Path == row.Path && r.Tenant == row.Tenant)
AddQuota(coreDbContext, Guid.Empty);
if (row.UserId != Guid.Empty)
{
AddQuota(coreDbContext, row.UserId);
}
tx.Commit();
});
void AddQuota(CoreDbContext coreDbContext, Guid userId)
{
var dbTenantQuotaRow = _mapper.Map<TenantQuotaRow, DbQuotaRow>(row);
dbTenantQuotaRow.UserId = userId;
if (exchange)
{
var counter = coreDbContext.QuotaRows
.Where(r => r.Path == row.Path && r.Tenant == row.Tenant && r.UserId == userId)
.Select(r => r.Counter)
.Take(1)
.FirstOrDefault();
var dbQuotaRow = _mapper.Map<TenantQuotaRow, DbQuotaRow>(row);
dbQuotaRow.Counter = exchange ? counter + row.Counter : row.Counter;
dbQuotaRow.LastModified = DateTime.UtcNow;
dbTenantQuotaRow.Counter = counter + row.Counter;
}
coreDbContext.AddOrUpdate(r => r.QuotaRows, dbQuotaRow);
coreDbContext.AddOrUpdate(r => r.QuotaRows, dbTenantQuotaRow);
coreDbContext.SaveChanges();
tx.Commit();
});
}
}
public IEnumerable<TenantQuotaRow> FindTenantQuotaRows(int tenantId)
{
return FindUserQuotaRows(tenantId, Guid.Empty);
}
public IEnumerable<TenantQuotaRow> FindUserQuotaRows(int tenantId, Guid userId)
{
using var coreDbContext = _dbContextFactory.CreateDbContext();
IQueryable<DbQuotaRow> q = coreDbContext.QuotaRows;
var q = coreDbContext.QuotaRows.Where(r => r.UserId == userId);
if (tenantId != Tenant.DefaultTenant)
{

View File

@ -254,6 +254,11 @@ public class DbSettingsManager
return LoadSettingsFor<T>(TenantID, userId);
}
public T LoadForUser<T>(UserInfo user) where T : class, ISettings<T>
{
return LoadSettingsFor<T>(TenantID, user.Id);
}
public T LoadForDefaultTenant<T>() where T : class, ISettings<T>
{
return LoadForTenant<T>(Tenant.DefaultTenant);
@ -279,6 +284,11 @@ public class DbSettingsManager
return SaveSettingsFor(data, TenantID, userId);
}
public bool SaveForUser<T>(T data, UserInfo user) where T : class, ISettings<T>
{
return SaveSettingsFor(data, TenantID, user.Id);
}
public bool SaveForDefaultTenant<T>(T data) where T : class, ISettings<T>
{
return SaveForTenant(data, Tenant.DefaultTenant);

View File

@ -33,10 +33,10 @@ public class DbQuotaRow : BaseEntity, IMapFrom<TenantQuotaRow>
public long Counter { get; set; }
public string Tag { get; set; }
public DateTime LastModified { get; set; }
public Guid UserId { get; set; }
public override object[] GetKeys()
{
return new object[] { Tenant, Path };
return new object[] { Tenant, UserId, Path };
}
}
@ -55,7 +55,7 @@ public static class DbQuotaRowExtension
{
modelBuilder.Entity<DbQuotaRow>(entity =>
{
entity.HasKey(e => new { e.Tenant, e.Path })
entity.HasKey(e => new { e.Tenant, e.UserId, e.Path })
.HasName("PRIMARY");
entity.ToTable("tenants_quotarow")
@ -85,6 +85,12 @@ public static class DbQuotaRowExtension
.HasColumnType("varchar(1024)")
.HasCharSet("utf8")
.UseCollation("utf8_general_ci");
entity.Property(e => e.UserId)
.HasColumnName("user_id")
.HasColumnType("char(36)")
.HasCharSet("utf8")
.UseCollation("utf8_general_ci");
});
}
public static void PgSqlAddDbQuotaRow(this ModelBuilder modelBuilder)
@ -117,6 +123,11 @@ public static class DbQuotaRowExtension
.HasColumnName("tag")
.HasMaxLength(1024)
.HasDefaultValueSql("'0'");
entity.Property(e => e.UserId)
.HasColumnName("user_id")
.HasMaxLength(36)
.HasDefaultValueSql("NULL");
});
}
}

View File

@ -32,5 +32,7 @@ public class TenantQuotaRow : IMapFrom<DbQuotaRow>
public int Tenant { get; set; }
public string Path { get; set; }
public long Counter { get; set; }
public string Tag { get; set; }
public string Tag { get; set; }
public Guid UserId { get; set; }
public DateTime LastModified { get; set; }
}

View File

@ -0,0 +1,50 @@
// (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.Core.Tenants;
[Serializable]
public class TenantUserQuotaSettings : ISettings<TenantUserQuotaSettings>
{
public bool EnableUserQuota { get; set; }
public long DefaultUserQuota { get; set; }
public TenantUserQuotaSettings GetDefault()
{
return new TenantUserQuotaSettings
{
EnableUserQuota = false,
DefaultUserQuota = -1
};
}
[JsonIgnore]
public Guid ID
{
get { return new Guid("{5FE28053-BCD4-466B-8A4B-71B612F0D6FC}"); }
}
}

View File

@ -73,7 +73,6 @@ public sealed class Constants
private readonly IConfiguration _configuration;
#region system group and category groups
public static readonly Guid SysGroupCategoryId = new Guid("{7717039D-FBE9-45ad-81C1-68A1AA10CE1F}");

View File

@ -0,0 +1,47 @@
// (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.Core.Users;
[Serializable]
public class UserQuotaSettings : ISettings<UserQuotaSettings>
{
public long UserQuota { get; set; }
public UserQuotaSettings GetDefault()
{
return new UserQuotaSettings
{
UserQuota = -1
};
}
[JsonIgnore]
public Guid ID
{
get { return new Guid("{5A097CFA-1A8E-45CB-A4BB-FE8D2B5E5908}"); }
}
}

View File

@ -139,6 +139,8 @@ public class StorageFactory
private readonly SettingsManager _settingsManager;
private readonly StorageSettingsHelper _storageSettingsHelper;
private readonly TenantManager _tenantManager;
private readonly UserManager _userManager;
private readonly AuthContext _authContext;
private readonly CoreBaseSettings _coreBaseSettings;
private readonly IServiceProvider _serviceProvider;
@ -148,6 +150,8 @@ public class StorageFactory
SettingsManager settingsManager,
StorageSettingsHelper storageSettingsHelper,
TenantManager tenantManager,
UserManager userManager,
AuthContext authContext,
CoreBaseSettings coreBaseSettings)
{
_serviceProvider = serviceProvider;
@ -155,6 +159,8 @@ public class StorageFactory
_settingsManager = settingsManager;
_storageSettingsHelper = storageSettingsHelper;
_tenantManager = tenantManager;
_userManager = userManager;
_authContext = authContext;
_coreBaseSettings = coreBaseSettings;
}
@ -167,7 +173,7 @@ public class StorageFactory
{
int.TryParse(tenant, out var tenantId);
return GetStorage(configpath, tenant, module, new TenantQuotaController(tenantId, _tenantManager));
return GetStorage(configpath, tenant, module, new TenantQuotaController(tenantId, _tenantManager, _authContext));
}
public IDataStore GetStorage(string configpath, string tenant, string module, IQuotaController controller)
@ -214,7 +220,7 @@ public class StorageFactory
int.TryParse(tenant, out var tenantId);
return GetDataStore(tenant, module, consumer, new TenantQuotaController(tenantId, _tenantManager));
return GetDataStore(tenant, module, consumer, new TenantQuotaController(tenantId, _tenantManager, _authContext));
}
private IDataStore GetDataStore(string tenant, string module, DataStoreConsumer consumer, IQuotaController controller)

View File

@ -44,16 +44,18 @@ public class TenantQuotaController : IQuotaController
private readonly int _tenant;
private readonly TenantManager _tenantManager;
private readonly AuthContext _authContext;
private readonly Lazy<long> _lazyCurrentSize;
private long _currentSize;
public TenantQuotaController(int tenant, TenantManager tenantManager)
public TenantQuotaController(int tenant, TenantManager tenantManager, AuthContext authContext)
{
_tenant = tenant;
_tenantManager = tenantManager;
_lazyCurrentSize = new Lazy<long>(() => _tenantManager.FindTenantQuotaRows(tenant)
.Where(r => UsedInQuota(r.Tag))
.Sum(r => r.Counter));
_authContext = authContext;
}
#region IQuotaController Members
@ -67,7 +69,7 @@ public class TenantQuotaController : IQuotaController
CurrentSize += size;
}
SetTenantQuotaRow(module, domain, size, dataTag, true);
SetTenantQuotaRow(module, domain, size, dataTag, true, _authContext.CurrentAccount.ID);
}
public void QuotaUsedDelete(string module, string domain, string dataTag, long size)
@ -78,7 +80,7 @@ public class TenantQuotaController : IQuotaController
CurrentSize += size;
}
SetTenantQuotaRow(module, domain, size, dataTag, true);
SetTenantQuotaRow(module, domain, size, dataTag, true, _authContext.CurrentAccount.ID);
}
public void QuotaUsedSet(string module, string domain, string dataTag, long size)
@ -89,7 +91,7 @@ public class TenantQuotaController : IQuotaController
CurrentSize += size;
}
SetTenantQuotaRow(module, domain, size, dataTag, false);
SetTenantQuotaRow(module, domain, size, dataTag, false, Guid.Empty);
}
public void QuotaUsedCheck(long size)
@ -120,11 +122,12 @@ public class TenantQuotaController : IQuotaController
return CurrentSize;
}
private void SetTenantQuotaRow(string module, string domain, long size, string dataTag, bool exchange)
private void SetTenantQuotaRow(string module, string domain, long size, string dataTag, bool exchange, Guid userId)
{
_tenantManager.SetTenantQuotaRow(
new TenantQuotaRow { Tenant = _tenant, Path = $"/{module}/{domain}", Counter = size, Tag = dataTag },
new TenantQuotaRow { Tenant = _tenant, Path = $"/{module}/{domain}", Counter = size, Tag = dataTag, UserId = userId, LastModified = DateTime.UtcNow },
exchange);
}
private bool UsedInQuota(string tag)

View File

@ -0,0 +1,223 @@
// <auto-generated />
using System;
using ASC.Core.Common.EF;
using Microsoft.EntityFrameworkCore;
using Microsoft.EntityFrameworkCore.Infrastructure;
using Microsoft.EntityFrameworkCore.Migrations;
using Microsoft.EntityFrameworkCore.Storage.ValueConversion;
#nullable disable
namespace ASC.Migrations.MySql.Migrations.CoreDb
{
[DbContext(typeof(CoreDbContext))]
[Migration("20221007105933_CoreDbContext_Upgrade1")]
partial class CoreDbContext_Upgrade1
{
protected override void BuildTargetModel(ModelBuilder modelBuilder)
{
#pragma warning disable 612, 618
modelBuilder
.HasAnnotation("ProductVersion", "6.0.7")
.HasAnnotation("Relational:MaxIdentifierLength", 64);
modelBuilder.Entity("ASC.Core.Common.EF.DbButton", b =>
{
b.Property<int>("TariffId")
.HasColumnType("int")
.HasColumnName("tariff_id");
b.Property<string>("PartnerId")
.HasColumnType("varchar(50)")
.HasColumnName("partner_id")
.UseCollation("utf8_general_ci")
.HasAnnotation("MySql:CharSet", "utf8");
b.Property<string>("ButtonUrl")
.IsRequired()
.HasColumnType("text")
.HasColumnName("button_url")
.UseCollation("utf8_general_ci")
.HasAnnotation("MySql:CharSet", "utf8");
b.HasKey("TariffId", "PartnerId")
.HasName("PRIMARY");
b.ToTable("tenants_buttons", (string)null);
b.HasAnnotation("MySql:CharSet", "utf8");
});
modelBuilder.Entity("ASC.Core.Common.EF.DbQuota", b =>
{
b.Property<int>("Tenant")
.HasColumnType("int")
.HasColumnName("tenant");
b.Property<int>("ActiveUsers")
.ValueGeneratedOnAdd()
.HasColumnType("int")
.HasColumnName("active_users")
.HasDefaultValueSql("'0'");
b.Property<string>("AvangateId")
.HasColumnType("varchar(128)")
.HasColumnName("avangate_id")
.UseCollation("utf8_general_ci")
.HasAnnotation("MySql:CharSet", "utf8");
b.Property<string>("Description")
.HasColumnType("varchar(128)")
.HasColumnName("description")
.UseCollation("utf8_general_ci")
.HasAnnotation("MySql:CharSet", "utf8");
b.Property<string>("Features")
.HasColumnType("text")
.HasColumnName("features");
b.Property<long>("MaxFileSize")
.ValueGeneratedOnAdd()
.HasColumnType("bigint")
.HasColumnName("max_file_size")
.HasDefaultValueSql("'0'");
b.Property<long>("MaxTotalSize")
.ValueGeneratedOnAdd()
.HasColumnType("bigint")
.HasColumnName("max_total_size")
.HasDefaultValueSql("'0'");
b.Property<string>("Name")
.HasColumnType("varchar(128)")
.HasColumnName("name")
.UseCollation("utf8_general_ci")
.HasAnnotation("MySql:CharSet", "utf8");
b.Property<decimal>("Price")
.ValueGeneratedOnAdd()
.HasColumnType("decimal(10,2)")
.HasColumnName("price")
.HasDefaultValueSql("'0.00'");
b.Property<bool>("Visible")
.ValueGeneratedOnAdd()
.HasColumnType("tinyint(1)")
.HasColumnName("visible")
.HasDefaultValueSql("'0'");
b.HasKey("Tenant")
.HasName("PRIMARY");
b.ToTable("tenants_quota", (string)null);
b.HasAnnotation("MySql:CharSet", "utf8");
b.HasData(
new
{
Tenant = -1,
ActiveUsers = 10000,
AvangateId = "0",
Features = "domain,audit,controlpanel,healthcheck,ldap,sso,whitelabel,branding,ssbranding,update,support,portals:10000,discencryption,privacyroom,restore",
MaxFileSize = 102400L,
MaxTotalSize = 10995116277760L,
Name = "default",
Price = 0m,
Visible = false
});
});
modelBuilder.Entity("ASC.Core.Common.EF.DbQuotaRow", b =>
{
b.Property<int>("Tenant")
.HasColumnType("int")
.HasColumnName("tenant");
b.Property<Guid>("UserId")
.HasColumnType("char(36)")
.HasColumnName("user_id")
.UseCollation("utf8_general_ci")
.HasAnnotation("MySql:CharSet", "utf8");
b.Property<string>("Path")
.HasColumnType("varchar(255)")
.HasColumnName("path")
.UseCollation("utf8_general_ci")
.HasAnnotation("MySql:CharSet", "utf8");
b.Property<long>("Counter")
.ValueGeneratedOnAdd()
.HasColumnType("bigint")
.HasColumnName("counter")
.HasDefaultValueSql("'0'");
b.Property<DateTime>("LastModified")
.HasColumnType("timestamp")
.HasColumnName("last_modified");
b.Property<string>("Tag")
.HasColumnType("varchar(1024)")
.HasColumnName("tag")
.UseCollation("utf8_general_ci")
.HasAnnotation("MySql:CharSet", "utf8");
b.HasKey("Tenant", "UserId", "Path")
.HasName("PRIMARY");
b.HasIndex("LastModified")
.HasDatabaseName("last_modified");
b.ToTable("tenants_quotarow", (string)null);
b.HasAnnotation("MySql:CharSet", "utf8");
});
modelBuilder.Entity("ASC.Core.Common.EF.DbTariff", b =>
{
b.Property<int>("Id")
.ValueGeneratedOnAdd()
.HasColumnType("int")
.HasColumnName("id");
b.Property<string>("Comment")
.HasColumnType("varchar(255)")
.HasColumnName("comment")
.UseCollation("utf8_general_ci")
.HasAnnotation("MySql:CharSet", "utf8");
b.Property<DateTime>("CreateOn")
.HasColumnType("timestamp")
.HasColumnName("create_on");
b.Property<int>("Quantity")
.ValueGeneratedOnAdd()
.HasColumnType("int")
.HasColumnName("quantity")
.HasDefaultValueSql("'1'");
b.Property<DateTime>("Stamp")
.HasColumnType("datetime")
.HasColumnName("stamp");
b.Property<int>("Tariff")
.HasColumnType("int")
.HasColumnName("tariff");
b.Property<int>("Tenant")
.HasColumnType("int")
.HasColumnName("tenant");
b.HasKey("Id");
b.HasIndex("Tenant")
.HasDatabaseName("tenant");
b.ToTable("tenants_tariff", (string)null);
b.HasAnnotation("MySql:CharSet", "utf8");
});
#pragma warning restore 612, 618
}
}
}

View File

@ -0,0 +1,47 @@
using System;
using Microsoft.EntityFrameworkCore.Migrations;
#nullable disable
namespace ASC.Migrations.MySql.Migrations.CoreDb
{
public partial class CoreDbContext_Upgrade1 : Migration
{
protected override void Up(MigrationBuilder migrationBuilder)
{
migrationBuilder.DropPrimaryKey(
name: "PRIMARY",
table: "tenants_quotarow");
migrationBuilder.AddColumn<Guid>(
name: "user_id",
table: "tenants_quotarow",
type: "char(36)",
nullable: false,
defaultValue: new Guid("00000000-0000-0000-0000-000000000000"),
collation: "utf8_general_ci")
.Annotation("MySql:CharSet", "utf8");
migrationBuilder.AddPrimaryKey(
name: "PRIMARY",
table: "tenants_quotarow",
columns: new[] { "tenant", "user_id", "path" });
}
protected override void Down(MigrationBuilder migrationBuilder)
{
migrationBuilder.DropPrimaryKey(
name: "PRIMARY",
table: "tenants_quotarow");
migrationBuilder.DropColumn(
name: "user_id",
table: "tenants_quotarow");
migrationBuilder.AddPrimaryKey(
name: "PRIMARY",
table: "tenants_quotarow",
columns: new[] { "tenant", "path" });
}
}
}

View File

@ -16,7 +16,7 @@ namespace ASC.Migrations.MySql.Migrations
{
#pragma warning disable 612, 618
modelBuilder
.HasAnnotation("ProductVersion", "6.0.4")
.HasAnnotation("ProductVersion", "6.0.7")
.HasAnnotation("Relational:MaxIdentifierLength", 64);
modelBuilder.Entity("ASC.Core.Common.EF.DbButton", b =>
@ -121,7 +121,7 @@ namespace ASC.Migrations.MySql.Migrations
MaxFileSize = 102400L,
MaxTotalSize = 10995116277760L,
Name = "default",
Price = 0.00m,
Price = 0m,
Visible = false
});
});
@ -132,6 +132,12 @@ namespace ASC.Migrations.MySql.Migrations
.HasColumnType("int")
.HasColumnName("tenant");
b.Property<Guid>("UserId")
.HasColumnType("char(36)")
.HasColumnName("user_id")
.UseCollation("utf8_general_ci")
.HasAnnotation("MySql:CharSet", "utf8");
b.Property<string>("Path")
.HasColumnType("varchar(255)")
.HasColumnName("path")
@ -154,7 +160,7 @@ namespace ASC.Migrations.MySql.Migrations
.UseCollation("utf8_general_ci")
.HasAnnotation("MySql:CharSet", "utf8");
b.HasKey("Tenant", "Path")
b.HasKey("Tenant", "UserId", "Path")
.HasName("PRIMARY");
b.HasIndex("LastModified")

View File

@ -21,376 +21,6 @@ namespace ASC.Migrations.MySql.Migrations
.HasAnnotation("ProductVersion", "6.0.4")
.HasAnnotation("Relational:MaxIdentifierLength", 64);
modelBuilder.Entity("ASC.Core.Common.EF.Model.DbTenant", b =>
{
b.Property<int>("Id")
.ValueGeneratedOnAdd()
.HasColumnType("int")
.HasColumnName("id");
b.Property<string>("Alias")
.IsRequired()
.HasColumnType("varchar(100)")
.HasColumnName("alias")
.UseCollation("utf8_general_ci")
.HasAnnotation("MySql:CharSet", "utf8");
b.Property<bool>("Calls")
.ValueGeneratedOnAdd()
.HasColumnType("tinyint(1)")
.HasColumnName("calls")
.HasDefaultValueSql("'1'");
b.Property<DateTime>("CreationDateTime")
.HasColumnType("datetime")
.HasColumnName("creationdatetime");
b.Property<int>("Industry")
.ValueGeneratedOnAdd()
.HasColumnType("int")
.HasColumnName("industry")
.HasDefaultValueSql("'0'");
b.Property<string>("Language")
.IsRequired()
.ValueGeneratedOnAdd()
.HasColumnType("char(10)")
.HasColumnName("language")
.HasDefaultValueSql("'en-US'")
.UseCollation("utf8_general_ci")
.HasAnnotation("MySql:CharSet", "utf8");
b.Property<DateTime>("LastModified")
.HasColumnType("timestamp")
.HasColumnName("last_modified");
b.Property<string>("MappedDomain")
.HasColumnType("varchar(100)")
.HasColumnName("mappeddomain")
.UseCollation("utf8_general_ci")
.HasAnnotation("MySql:CharSet", "utf8");
b.Property<string>("Name")
.IsRequired()
.HasColumnType("varchar(255)")
.HasColumnName("name")
.UseCollation("utf8_general_ci")
.HasAnnotation("MySql:CharSet", "utf8");
b.Property<string>("OwnerId")
.HasColumnType("varchar(38)")
.HasColumnName("owner_id")
.UseCollation("utf8_general_ci")
.HasAnnotation("MySql:CharSet", "utf8");
b.Property<string>("PaymentId")
.HasColumnType("varchar(38)")
.HasColumnName("payment_id")
.UseCollation("utf8_general_ci")
.HasAnnotation("MySql:CharSet", "utf8");
b.Property<bool>("Spam")
.ValueGeneratedOnAdd()
.HasColumnType("tinyint(1)")
.HasColumnName("spam")
.HasDefaultValueSql("'1'");
b.Property<int>("Status")
.ValueGeneratedOnAdd()
.HasColumnType("int")
.HasColumnName("status")
.HasDefaultValueSql("'0'");
b.Property<DateTime?>("StatusChanged")
.HasColumnType("datetime")
.HasColumnName("statuschanged");
b.Property<string>("TimeZone")
.HasColumnType("varchar(50)")
.HasColumnName("timezone")
.UseCollation("utf8_general_ci")
.HasAnnotation("MySql:CharSet", "utf8");
b.Property<int>("TrustedDomainsEnabled")
.ValueGeneratedOnAdd()
.HasColumnType("int")
.HasColumnName("trusteddomainsenabled")
.HasDefaultValueSql("'1'");
b.Property<string>("TrustedDomainsRaw")
.HasColumnType("varchar(1024)")
.HasColumnName("trusteddomains")
.UseCollation("utf8_general_ci")
.HasAnnotation("MySql:CharSet", "utf8");
b.Property<int>("Version")
.ValueGeneratedOnAdd()
.HasColumnType("int")
.HasColumnName("version")
.HasDefaultValueSql("'2'");
b.Property<DateTime?>("Version_Changed")
.HasColumnType("datetime")
.HasColumnName("version_changed");
b.HasKey("Id");
b.HasIndex("Alias")
.IsUnique()
.HasDatabaseName("alias");
b.HasIndex("LastModified")
.HasDatabaseName("last_modified");
b.HasIndex("MappedDomain")
.HasDatabaseName("mappeddomain");
b.HasIndex("Version")
.HasDatabaseName("version");
b.ToTable("tenants_tenants", (string)null);
b.HasAnnotation("MySql:CharSet", "utf8");
b.HasData(
new
{
Id = 1,
Alias = "localhost",
Calls = false,
CreationDateTime = new DateTime(2021, 3, 9, 17, 46, 59, 97, DateTimeKind.Utc).AddTicks(4317),
Industry = 0,
LastModified = new DateTime(2022, 7, 8, 0, 0, 0, 0, DateTimeKind.Unspecified),
Name = "Web Office",
OwnerId = "66faa6e4-f133-11ea-b126-00ffeec8b4ef",
Spam = false,
Status = 0,
TrustedDomainsEnabled = 0,
Version = 0
});
});
modelBuilder.Entity("ASC.Core.Common.EF.Model.DbWebstudioSettings", b =>
{
b.Property<int>("TenantId")
.HasColumnType("int")
.HasColumnName("TenantID");
b.Property<string>("Id")
.HasColumnType("varchar(64)")
.HasColumnName("ID")
.UseCollation("utf8_general_ci")
.HasAnnotation("MySql:CharSet", "utf8");
b.Property<string>("UserId")
.HasColumnType("varchar(64)")
.HasColumnName("UserID")
.UseCollation("utf8_general_ci")
.HasAnnotation("MySql:CharSet", "utf8");
b.Property<string>("Data")
.IsRequired()
.HasColumnType("mediumtext")
.UseCollation("utf8_general_ci")
.HasAnnotation("MySql:CharSet", "utf8");
b.HasKey("TenantId", "Id", "UserId")
.HasName("PRIMARY");
b.HasIndex("Id")
.HasDatabaseName("ID");
b.ToTable("webstudio_settings", (string)null);
b.HasAnnotation("MySql:CharSet", "utf8");
b.HasData(
new
{
TenantId = 1,
Id = "9a925891-1f92-4ed7-b277-d6f649739f06",
UserId = "00000000-0000-0000-0000-000000000000",
Data = "{\"Completed\":false}"
});
});
modelBuilder.Entity("ASC.Core.Common.EF.User", b =>
{
b.Property<string>("Id")
.ValueGeneratedOnAdd()
.HasColumnType("varchar(38)")
.HasColumnName("id")
.UseCollation("utf8_general_ci")
.HasAnnotation("MySql:CharSet", "utf8");
b.Property<int>("ActivationStatus")
.ValueGeneratedOnAdd()
.HasColumnType("int")
.HasColumnName("activation_status")
.HasDefaultValueSql("'0'");
b.Property<DateTime?>("BirthDate")
.HasColumnType("datetime")
.HasColumnName("bithdate");
b.Property<string>("Contacts")
.HasColumnType("varchar(1024)")
.HasColumnName("contacts")
.UseCollation("utf8_general_ci")
.HasAnnotation("MySql:CharSet", "utf8");
b.Property<DateTime>("CreateDate")
.HasColumnType("timestamp")
.HasColumnName("create_on");
b.Property<string>("CultureName")
.HasColumnType("varchar(20)")
.HasColumnName("culture")
.UseCollation("utf8_general_ci")
.HasAnnotation("MySql:CharSet", "utf8");
b.Property<string>("Email")
.HasColumnType("varchar(255)")
.HasColumnName("email")
.UseCollation("utf8_general_ci")
.HasAnnotation("MySql:CharSet", "utf8");
b.Property<string>("FirstName")
.IsRequired()
.HasColumnType("varchar(64)")
.HasColumnName("firstname")
.UseCollation("utf8_general_ci")
.HasAnnotation("MySql:CharSet", "utf8");
b.Property<DateTime>("LastModified")
.HasColumnType("datetime")
.HasColumnName("last_modified");
b.Property<string>("LastName")
.IsRequired()
.HasColumnType("varchar(64)")
.HasColumnName("lastname")
.UseCollation("utf8_general_ci")
.HasAnnotation("MySql:CharSet", "utf8");
b.Property<string>("Location")
.HasColumnType("varchar(255)")
.HasColumnName("location")
.UseCollation("utf8_general_ci")
.HasAnnotation("MySql:CharSet", "utf8");
b.Property<string>("MobilePhone")
.HasColumnType("varchar(255)")
.HasColumnName("phone")
.UseCollation("utf8_general_ci")
.HasAnnotation("MySql:CharSet", "utf8");
b.Property<int>("MobilePhoneActivation")
.ValueGeneratedOnAdd()
.HasColumnType("int")
.HasColumnName("phone_activation")
.HasDefaultValueSql("'0'");
b.Property<string>("Notes")
.HasColumnType("varchar(512)")
.HasColumnName("notes")
.UseCollation("utf8_general_ci")
.HasAnnotation("MySql:CharSet", "utf8");
b.Property<bool>("Removed")
.ValueGeneratedOnAdd()
.HasColumnType("tinyint(1)")
.HasColumnName("removed")
.HasDefaultValueSql("'0'");
b.Property<bool?>("Sex")
.HasColumnType("tinyint(1)")
.HasColumnName("sex");
b.Property<string>("Sid")
.HasColumnType("varchar(512)")
.HasColumnName("sid")
.UseCollation("utf8_general_ci")
.HasAnnotation("MySql:CharSet", "utf8");
b.Property<string>("SsoNameId")
.HasColumnType("varchar(512)")
.HasColumnName("sso_name_id")
.UseCollation("utf8_general_ci")
.HasAnnotation("MySql:CharSet", "utf8");
b.Property<string>("SsoSessionId")
.HasColumnType("varchar(512)")
.HasColumnName("sso_session_id")
.UseCollation("utf8_general_ci")
.HasAnnotation("MySql:CharSet", "utf8");
b.Property<int>("Status")
.ValueGeneratedOnAdd()
.HasColumnType("int")
.HasColumnName("status")
.HasDefaultValueSql("'1'");
b.Property<int>("Tenant")
.HasColumnType("int")
.HasColumnName("tenant");
b.Property<DateTime?>("TerminatedDate")
.HasColumnType("datetime")
.HasColumnName("terminateddate");
b.Property<string>("Title")
.HasColumnType("varchar(64)")
.HasColumnName("title")
.UseCollation("utf8_general_ci")
.HasAnnotation("MySql:CharSet", "utf8");
b.Property<string>("UserName")
.IsRequired()
.HasColumnType("varchar(255)")
.HasColumnName("username")
.UseCollation("utf8_general_ci")
.HasAnnotation("MySql:CharSet", "utf8");
b.Property<DateTime?>("WorkFromDate")
.HasColumnType("datetime")
.HasColumnName("workfromdate");
b.HasKey("Id")
.HasName("PRIMARY");
b.HasIndex("Email")
.HasDatabaseName("email");
b.HasIndex("LastModified")
.HasDatabaseName("last_modified");
b.HasIndex("Tenant", "UserName")
.HasDatabaseName("username");
b.ToTable("core_user", (string)null);
b.HasAnnotation("MySql:CharSet", "utf8");
b.HasData(
new
{
Id = "66faa6e4-f133-11ea-b126-00ffeec8b4ef",
ActivationStatus = 0,
CreateDate = new DateTime(2022, 7, 8, 0, 0, 0, 0, DateTimeKind.Unspecified),
Email = "",
FirstName = "Administrator",
LastModified = new DateTime(2021, 3, 9, 9, 52, 55, 765, DateTimeKind.Utc).AddTicks(1420),
LastName = "",
MobilePhoneActivation = 0,
Removed = false,
Status = 1,
Tenant = 1,
UserName = "administrator",
WorkFromDate = new DateTime(2021, 3, 9, 9, 52, 55, 764, DateTimeKind.Utc).AddTicks(9157)
});
});
modelBuilder.Entity("ASC.MessagingSystem.EF.Model.AuditEvent", b =>
{
b.Property<int>("Id")

View File

@ -1,4 +1,29 @@
using System;
// (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 Microsoft.EntityFrameworkCore.Metadata;
using Microsoft.EntityFrameworkCore.Migrations;
@ -45,56 +70,6 @@ namespace ASC.Migrations.MySql.Migrations
})
.Annotation("MySql:CharSet", "utf8");
migrationBuilder.CreateTable(
name: "core_user",
columns: table => new
{
id = table.Column<string>(type: "varchar(38)", nullable: false, collation: "utf8_general_ci")
.Annotation("MySql:CharSet", "utf8"),
tenant = table.Column<int>(type: "int", nullable: false),
username = table.Column<string>(type: "varchar(255)", nullable: false, collation: "utf8_general_ci")
.Annotation("MySql:CharSet", "utf8"),
firstname = table.Column<string>(type: "varchar(64)", nullable: false, collation: "utf8_general_ci")
.Annotation("MySql:CharSet", "utf8"),
lastname = table.Column<string>(type: "varchar(64)", nullable: false, collation: "utf8_general_ci")
.Annotation("MySql:CharSet", "utf8"),
sex = table.Column<bool>(type: "tinyint(1)", nullable: true),
bithdate = table.Column<DateTime>(type: "datetime", nullable: true),
status = table.Column<int>(type: "int", nullable: false, defaultValueSql: "'1'"),
activation_status = table.Column<int>(type: "int", nullable: false, defaultValueSql: "'0'"),
email = table.Column<string>(type: "varchar(255)", nullable: true, collation: "utf8_general_ci")
.Annotation("MySql:CharSet", "utf8"),
workfromdate = table.Column<DateTime>(type: "datetime", nullable: true),
terminateddate = table.Column<DateTime>(type: "datetime", nullable: true),
title = table.Column<string>(type: "varchar(64)", nullable: true, collation: "utf8_general_ci")
.Annotation("MySql:CharSet", "utf8"),
culture = table.Column<string>(type: "varchar(20)", nullable: true, collation: "utf8_general_ci")
.Annotation("MySql:CharSet", "utf8"),
contacts = table.Column<string>(type: "varchar(1024)", nullable: true, collation: "utf8_general_ci")
.Annotation("MySql:CharSet", "utf8"),
phone = table.Column<string>(type: "varchar(255)", nullable: true, collation: "utf8_general_ci")
.Annotation("MySql:CharSet", "utf8"),
phone_activation = table.Column<int>(type: "int", nullable: false, defaultValueSql: "'0'"),
location = table.Column<string>(type: "varchar(255)", nullable: true, collation: "utf8_general_ci")
.Annotation("MySql:CharSet", "utf8"),
notes = table.Column<string>(type: "varchar(512)", nullable: true, collation: "utf8_general_ci")
.Annotation("MySql:CharSet", "utf8"),
sid = table.Column<string>(type: "varchar(512)", nullable: true, collation: "utf8_general_ci")
.Annotation("MySql:CharSet", "utf8"),
sso_name_id = table.Column<string>(type: "varchar(512)", nullable: true, collation: "utf8_general_ci")
.Annotation("MySql:CharSet", "utf8"),
sso_session_id = table.Column<string>(type: "varchar(512)", nullable: true, collation: "utf8_general_ci")
.Annotation("MySql:CharSet", "utf8"),
removed = table.Column<bool>(type: "tinyint(1)", nullable: false, defaultValueSql: "'0'"),
create_on = table.Column<DateTime>(type: "timestamp", nullable: false),
last_modified = table.Column<DateTime>(type: "datetime", nullable: false)
},
constraints: table =>
{
table.PrimaryKey("PRIMARY", x => x.id);
})
.Annotation("MySql:CharSet", "utf8");
migrationBuilder.CreateTable(
name: "login_events",
columns: table => new
@ -126,98 +101,11 @@ namespace ASC.Migrations.MySql.Migrations
})
.Annotation("MySql:CharSet", "utf8");
migrationBuilder.CreateTable(
name: "tenants_tenants",
columns: table => new
{
id = table.Column<int>(type: "int", nullable: false)
.Annotation("MySql:ValueGenerationStrategy", MySqlValueGenerationStrategy.IdentityColumn),
name = table.Column<string>(type: "varchar(255)", nullable: false, collation: "utf8_general_ci")
.Annotation("MySql:CharSet", "utf8"),
alias = table.Column<string>(type: "varchar(100)", nullable: false, collation: "utf8_general_ci")
.Annotation("MySql:CharSet", "utf8"),
mappeddomain = table.Column<string>(type: "varchar(100)", nullable: true, collation: "utf8_general_ci")
.Annotation("MySql:CharSet", "utf8"),
version = table.Column<int>(type: "int", nullable: false, defaultValueSql: "'2'"),
version_changed = table.Column<DateTime>(type: "datetime", nullable: true),
language = table.Column<string>(type: "char(10)", nullable: false, defaultValueSql: "'en-US'", collation: "utf8_general_ci")
.Annotation("MySql:CharSet", "utf8"),
timezone = table.Column<string>(type: "varchar(50)", nullable: true, collation: "utf8_general_ci")
.Annotation("MySql:CharSet", "utf8"),
trusteddomains = table.Column<string>(type: "varchar(1024)", nullable: true, collation: "utf8_general_ci")
.Annotation("MySql:CharSet", "utf8"),
trusteddomainsenabled = table.Column<int>(type: "int", nullable: false, defaultValueSql: "'1'"),
status = table.Column<int>(type: "int", nullable: false, defaultValueSql: "'0'"),
statuschanged = table.Column<DateTime>(type: "datetime", nullable: true),
creationdatetime = table.Column<DateTime>(type: "datetime", nullable: false),
owner_id = table.Column<string>(type: "varchar(38)", nullable: true, collation: "utf8_general_ci")
.Annotation("MySql:CharSet", "utf8"),
payment_id = table.Column<string>(type: "varchar(38)", nullable: true, collation: "utf8_general_ci")
.Annotation("MySql:CharSet", "utf8"),
industry = table.Column<int>(type: "int", nullable: false, defaultValueSql: "'0'"),
last_modified = table.Column<DateTime>(type: "timestamp", nullable: false),
spam = table.Column<bool>(type: "tinyint(1)", nullable: false, defaultValueSql: "'1'"),
calls = table.Column<bool>(type: "tinyint(1)", nullable: false, defaultValueSql: "'1'")
},
constraints: table =>
{
table.PrimaryKey("PK_tenants_tenants", x => x.id);
})
.Annotation("MySql:CharSet", "utf8");
migrationBuilder.CreateTable(
name: "webstudio_settings",
columns: table => new
{
TenantID = table.Column<int>(type: "int", nullable: false),
ID = table.Column<string>(type: "varchar(64)", nullable: false, collation: "utf8_general_ci")
.Annotation("MySql:CharSet", "utf8"),
UserID = table.Column<string>(type: "varchar(64)", nullable: false, collation: "utf8_general_ci")
.Annotation("MySql:CharSet", "utf8"),
Data = table.Column<string>(type: "mediumtext", nullable: false, collation: "utf8_general_ci")
.Annotation("MySql:CharSet", "utf8")
},
constraints: table =>
{
table.PrimaryKey("PRIMARY", x => new { x.TenantID, x.ID, x.UserID });
})
.Annotation("MySql:CharSet", "utf8");
migrationBuilder.InsertData(
table: "core_user",
columns: new[] { "id", "bithdate", "contacts", "create_on", "culture", "email", "firstname", "last_modified", "lastname", "location", "phone", "notes", "sex", "sid", "sso_name_id", "sso_session_id", "status", "tenant", "terminateddate", "title", "username", "workfromdate" },
values: new object[] { "66faa6e4-f133-11ea-b126-00ffeec8b4ef", null, null, new DateTime(2022, 7, 8, 0, 0, 0, 0, DateTimeKind.Unspecified), null, "", "Administrator", new DateTime(2021, 3, 9, 9, 52, 55, 765, DateTimeKind.Utc).AddTicks(1420), "", null, null, null, null, null, null, null, 1, 1, null, null, "administrator", new DateTime(2021, 3, 9, 9, 52, 55, 764, DateTimeKind.Utc).AddTicks(9157) });
migrationBuilder.InsertData(
table: "tenants_tenants",
columns: new[] { "id", "alias", "creationdatetime", "last_modified", "mappeddomain", "name", "owner_id", "payment_id", "statuschanged", "timezone", "trusteddomains", "version_changed" },
values: new object[] { 1, "localhost", new DateTime(2021, 3, 9, 17, 46, 59, 97, DateTimeKind.Utc).AddTicks(4317), new DateTime(2022, 7, 8, 0, 0, 0, 0, DateTimeKind.Unspecified), null, "Web Office", "66faa6e4-f133-11ea-b126-00ffeec8b4ef", null, null, null, null, null });
migrationBuilder.InsertData(
table: "webstudio_settings",
columns: new[] { "ID", "TenantID", "UserID", "Data" },
values: new object[] { "9a925891-1f92-4ed7-b277-d6f649739f06", 1, "00000000-0000-0000-0000-000000000000", "{\"Completed\":false}" });
migrationBuilder.CreateIndex(
name: "date",
table: "audit_events",
columns: new[] { "tenant_id", "date" });
migrationBuilder.CreateIndex(
name: "email",
table: "core_user",
column: "email");
migrationBuilder.CreateIndex(
name: "last_modified",
table: "core_user",
column: "last_modified");
migrationBuilder.CreateIndex(
name: "username",
table: "core_user",
columns: new[] { "tenant", "username" });
migrationBuilder.CreateIndex(
name: "date",
table: "login_events",
@ -227,32 +115,6 @@ namespace ASC.Migrations.MySql.Migrations
name: "tenant_id",
table: "login_events",
columns: new[] { "tenant_id", "user_id" });
migrationBuilder.CreateIndex(
name: "alias",
table: "tenants_tenants",
column: "alias",
unique: true);
migrationBuilder.CreateIndex(
name: "last_modified",
table: "tenants_tenants",
column: "last_modified");
migrationBuilder.CreateIndex(
name: "mappeddomain",
table: "tenants_tenants",
column: "mappeddomain");
migrationBuilder.CreateIndex(
name: "version",
table: "tenants_tenants",
column: "version");
migrationBuilder.CreateIndex(
name: "ID",
table: "webstudio_settings",
column: "ID");
}
protected override void Down(MigrationBuilder migrationBuilder)
@ -260,17 +122,8 @@ namespace ASC.Migrations.MySql.Migrations
migrationBuilder.DropTable(
name: "audit_events");
migrationBuilder.DropTable(
name: "core_user");
migrationBuilder.DropTable(
name: "login_events");
migrationBuilder.DropTable(
name: "tenants_tenants");
migrationBuilder.DropTable(
name: "webstudio_settings");
}
}
}

View File

@ -16,7 +16,7 @@ namespace ASC.Migrations.MySql.Migrations
{
#pragma warning disable 612, 618
modelBuilder
.HasAnnotation("ProductVersion", "6.0.4")
.HasAnnotation("ProductVersion", "6.0.7")
.HasAnnotation("Relational:MaxIdentifierLength", 64);
modelBuilder.Entity("ASC.Core.Common.EF.Model.DbTenant", b =>

View File

@ -16,7 +16,7 @@ namespace ASC.Migrations.MySql.Migrations
{
#pragma warning disable 612, 618
modelBuilder
.HasAnnotation("ProductVersion", "6.0.4")
.HasAnnotation("ProductVersion", "6.0.7")
.HasAnnotation("Relational:MaxIdentifierLength", 64);
modelBuilder.Entity("ASC.Core.Common.EF.Acl", b =>

View File

@ -0,0 +1,212 @@
// <auto-generated />
using System;
using ASC.Core.Common.EF;
using Microsoft.EntityFrameworkCore;
using Microsoft.EntityFrameworkCore.Infrastructure;
using Microsoft.EntityFrameworkCore.Migrations;
using Microsoft.EntityFrameworkCore.Storage.ValueConversion;
using Npgsql.EntityFrameworkCore.PostgreSQL.Metadata;
#nullable disable
namespace ASC.Migrations.PostgreSql.Migrations.CoreDb
{
[DbContext(typeof(CoreDbContext))]
[Migration("20221007105933_CoreDbContext_Upgrade1")]
partial class CoreDbContext_Upgrade1
{
protected override void BuildTargetModel(ModelBuilder modelBuilder)
{
#pragma warning disable 612, 618
modelBuilder
.HasAnnotation("Npgsql:ValueGenerationStrategy", NpgsqlValueGenerationStrategy.IdentityByDefaultColumn)
.HasAnnotation("ProductVersion", "6.0.7")
.HasAnnotation("Relational:MaxIdentifierLength", 63);
modelBuilder.Entity("ASC.Core.Common.EF.DbButton", b =>
{
b.Property<int>("TariffId")
.HasColumnType("integer")
.HasColumnName("tariff_id");
b.Property<string>("PartnerId")
.HasMaxLength(50)
.HasColumnType("character varying(50)")
.HasColumnName("partner_id");
b.Property<string>("ButtonUrl")
.IsRequired()
.HasColumnType("text")
.HasColumnName("button_url");
b.HasKey("TariffId", "PartnerId")
.HasName("tenants_buttons_pkey");
b.ToTable("tenants_buttons", "onlyoffice");
});
modelBuilder.Entity("ASC.Core.Common.EF.DbQuota", b =>
{
b.Property<int>("Tenant")
.HasColumnType("integer")
.HasColumnName("tenant");
b.Property<int>("ActiveUsers")
.HasColumnType("integer")
.HasColumnName("active_users");
b.Property<string>("AvangateId")
.ValueGeneratedOnAdd()
.HasMaxLength(128)
.HasColumnType("character varying(128)")
.HasColumnName("avangate_id")
.HasDefaultValueSql("NULL");
b.Property<string>("Description")
.HasColumnType("character varying")
.HasColumnName("description");
b.Property<string>("Features")
.HasColumnType("text")
.HasColumnName("features");
b.Property<long>("MaxFileSize")
.ValueGeneratedOnAdd()
.HasColumnType("bigint")
.HasColumnName("max_file_size")
.HasDefaultValueSql("'0'");
b.Property<long>("MaxTotalSize")
.ValueGeneratedOnAdd()
.HasColumnType("bigint")
.HasColumnName("max_total_size")
.HasDefaultValueSql("'0'");
b.Property<string>("Name")
.HasColumnType("character varying")
.HasColumnName("name");
b.Property<decimal>("Price")
.ValueGeneratedOnAdd()
.HasColumnType("numeric(10,2)")
.HasColumnName("price")
.HasDefaultValueSql("0.00");
b.Property<bool>("Visible")
.HasColumnType("boolean")
.HasColumnName("visible");
b.HasKey("Tenant")
.HasName("tenants_quota_pkey");
b.ToTable("tenants_quota", "onlyoffice");
b.HasData(
new
{
Tenant = -1,
ActiveUsers = 10000,
AvangateId = "0",
Features = "domain,audit,controlpanel,healthcheck,ldap,sso,whitelabel,branding,ssbranding,update,support,portals:10000,discencryption,privacyroom,restore",
MaxFileSize = 102400L,
MaxTotalSize = 10995116277760L,
Name = "default",
Price = 0m,
Visible = false
});
});
modelBuilder.Entity("ASC.Core.Common.EF.DbQuotaRow", b =>
{
b.Property<int>("Tenant")
.HasColumnType("integer")
.HasColumnName("tenant");
b.Property<string>("Path")
.HasMaxLength(255)
.HasColumnType("character varying(255)")
.HasColumnName("path");
b.Property<long>("Counter")
.ValueGeneratedOnAdd()
.HasColumnType("bigint")
.HasColumnName("counter")
.HasDefaultValueSql("'0'");
b.Property<DateTime>("LastModified")
.ValueGeneratedOnAdd()
.HasColumnType("timestamp with time zone")
.HasColumnName("last_modified")
.HasDefaultValueSql("CURRENT_TIMESTAMP");
b.Property<string>("Tag")
.ValueGeneratedOnAdd()
.HasMaxLength(1024)
.HasColumnType("character varying(1024)")
.HasColumnName("tag")
.HasDefaultValueSql("'0'");
b.Property<Guid>("UserId")
.ValueGeneratedOnAdd()
.HasMaxLength(36)
.HasColumnType("uuid")
.HasColumnName("user_id")
.HasDefaultValueSql("NULL");
b.HasKey("Tenant", "Path")
.HasName("tenants_quotarow_pkey");
b.HasIndex("LastModified")
.HasDatabaseName("last_modified_tenants_quotarow");
b.ToTable("tenants_quotarow", "onlyoffice");
});
modelBuilder.Entity("ASC.Core.Common.EF.DbTariff", b =>
{
b.Property<int>("Id")
.ValueGeneratedOnAdd()
.HasColumnType("integer")
.HasColumnName("id")
.HasAnnotation("Npgsql:ValueGenerationStrategy", NpgsqlValueGenerationStrategy.IdentityByDefaultColumn);
b.Property<string>("Comment")
.ValueGeneratedOnAdd()
.HasMaxLength(255)
.HasColumnType("character varying(255)")
.HasColumnName("comment")
.HasDefaultValueSql("NULL");
b.Property<DateTime>("CreateOn")
.ValueGeneratedOnAdd()
.HasColumnType("timestamp with time zone")
.HasColumnName("create_on")
.HasDefaultValueSql("CURRENT_TIMESTAMP");
b.Property<int>("Quantity")
.HasColumnType("integer")
.HasColumnName("quantity");
b.Property<DateTime>("Stamp")
.HasColumnType("timestamp with time zone")
.HasColumnName("stamp");
b.Property<int>("Tariff")
.HasColumnType("integer")
.HasColumnName("tariff");
b.Property<int>("Tenant")
.HasColumnType("integer")
.HasColumnName("tenant");
b.HasKey("Id");
b.HasIndex("Tenant")
.HasDatabaseName("tenant_tenants_tariff");
b.ToTable("tenants_tariff", "onlyoffice");
});
#pragma warning restore 612, 618
}
}
}

View File

@ -0,0 +1,50 @@
using System;
using Microsoft.EntityFrameworkCore.Migrations;
#nullable disable
namespace ASC.Migrations.PostgreSql.Migrations.CoreDb
{
public partial class CoreDbContext_Upgrade1 : Migration
{
protected override void Up(MigrationBuilder migrationBuilder)
{
migrationBuilder.DropTable(
name: "users_quotarow",
schema: "onlyoffice");
migrationBuilder.AddColumn<Guid>(
name: "user_id",
schema: "onlyoffice",
table: "tenants_quotarow",
type: "uuid",
maxLength: 36,
nullable: false,
defaultValueSql: "NULL");
}
protected override void Down(MigrationBuilder migrationBuilder)
{
migrationBuilder.DropColumn(
name: "user_id",
schema: "onlyoffice",
table: "tenants_quotarow");
migrationBuilder.CreateTable(
name: "users_quotarow",
schema: "onlyoffice",
columns: table => new
{
tenant = table.Column<int>(type: "integer", nullable: false),
UserId = table.Column<Guid>(type: "uuid", nullable: false),
path = table.Column<string>(type: "character varying(255)", maxLength: 255, nullable: false),
counter = table.Column<long>(type: "bigint", nullable: false, defaultValueSql: "'0'"),
tag = table.Column<string>(type: "character varying(36)", maxLength: 36, nullable: true, defaultValueSql: "'0'")
},
constraints: table =>
{
table.PrimaryKey("tenants_userquotarow_pkey", x => new { x.tenant, x.UserId, x.path });
});
}
}
}

View File

@ -18,7 +18,7 @@ namespace ASC.Migrations.PostgreSql.Migrations
#pragma warning disable 612, 618
modelBuilder
.HasAnnotation("Npgsql:ValueGenerationStrategy", NpgsqlValueGenerationStrategy.IdentityByDefaultColumn)
.HasAnnotation("ProductVersion", "6.0.4")
.HasAnnotation("ProductVersion", "6.0.7")
.HasAnnotation("Relational:MaxIdentifierLength", 63);
modelBuilder.Entity("ASC.Core.Common.EF.DbButton", b =>
@ -109,7 +109,7 @@ namespace ASC.Migrations.PostgreSql.Migrations
MaxFileSize = 102400L,
MaxTotalSize = 10995116277760L,
Name = "default",
Price = 0.00m,
Price = 0m,
Visible = false
});
});
@ -144,6 +144,13 @@ namespace ASC.Migrations.PostgreSql.Migrations
.HasColumnName("tag")
.HasDefaultValueSql("'0'");
b.Property<Guid>("UserId")
.ValueGeneratedOnAdd()
.HasMaxLength(36)
.HasColumnType("uuid")
.HasColumnName("user_id")
.HasDefaultValueSql("NULL");
b.HasKey("Tenant", "Path")
.HasName("tenants_quotarow_pkey");

View File

@ -23,408 +23,6 @@ namespace ASC.Migrations.PostgreSql.Migrations
.HasAnnotation("ProductVersion", "6.0.4")
.HasAnnotation("Relational:MaxIdentifierLength", 63);
modelBuilder.Entity("ASC.Core.Common.EF.Model.DbTenant", b =>
{
b.Property<int>("Id")
.ValueGeneratedOnAdd()
.HasColumnType("integer")
.HasColumnName("id")
.HasAnnotation("Npgsql:ValueGenerationStrategy", NpgsqlValueGenerationStrategy.IdentityByDefaultColumn);
b.Property<string>("Alias")
.IsRequired()
.HasMaxLength(100)
.HasColumnType("character varying(100)")
.HasColumnName("alias");
b.Property<bool>("Calls")
.ValueGeneratedOnAdd()
.HasColumnType("boolean")
.HasColumnName("calls")
.HasDefaultValueSql("true");
b.Property<DateTime>("CreationDateTime")
.HasColumnType("timestamp with time zone")
.HasColumnName("creationdatetime");
b.Property<int>("Industry")
.HasColumnType("integer")
.HasColumnName("industry");
b.Property<string>("Language")
.IsRequired()
.ValueGeneratedOnAdd()
.HasMaxLength(10)
.HasColumnType("character(10)")
.HasColumnName("language")
.HasDefaultValueSql("'en-US'")
.IsFixedLength();
b.Property<DateTime>("LastModified")
.ValueGeneratedOnAdd()
.HasColumnType("timestamp with time zone")
.HasColumnName("last_modified")
.HasDefaultValueSql("CURRENT_TIMESTAMP");
b.Property<string>("MappedDomain")
.ValueGeneratedOnAdd()
.HasMaxLength(100)
.HasColumnType("character varying(100)")
.HasColumnName("mappeddomain")
.HasDefaultValueSql("NULL");
b.Property<string>("Name")
.IsRequired()
.HasMaxLength(255)
.HasColumnType("character varying(255)")
.HasColumnName("name");
b.Property<Guid?>("OwnerId")
.ValueGeneratedOnAdd()
.HasMaxLength(38)
.HasColumnType("uuid")
.HasColumnName("owner_id")
.HasDefaultValueSql("NULL");
b.Property<string>("PaymentId")
.ValueGeneratedOnAdd()
.HasMaxLength(38)
.HasColumnType("character varying(38)")
.HasColumnName("payment_id")
.HasDefaultValueSql("NULL");
b.Property<bool>("Spam")
.ValueGeneratedOnAdd()
.HasColumnType("boolean")
.HasColumnName("spam")
.HasDefaultValueSql("true");
b.Property<int>("Status")
.HasColumnType("integer")
.HasColumnName("status");
b.Property<DateTime?>("StatusChanged")
.HasColumnType("timestamp with time zone")
.HasColumnName("statuschanged");
b.Property<string>("TimeZone")
.ValueGeneratedOnAdd()
.HasMaxLength(50)
.HasColumnType("character varying(50)")
.HasColumnName("timezone")
.HasDefaultValueSql("NULL");
b.Property<int>("TrustedDomainsEnabled")
.ValueGeneratedOnAdd()
.HasColumnType("integer")
.HasColumnName("trusteddomainsenabled")
.HasDefaultValueSql("1");
b.Property<string>("TrustedDomainsRaw")
.ValueGeneratedOnAdd()
.HasMaxLength(1024)
.HasColumnType("character varying(1024)")
.HasColumnName("trusteddomains")
.HasDefaultValueSql("NULL");
b.Property<int>("Version")
.ValueGeneratedOnAdd()
.HasColumnType("integer")
.HasColumnName("version")
.HasDefaultValueSql("2");
b.Property<DateTime?>("Version_Changed")
.HasColumnType("timestamp with time zone")
.HasColumnName("version_changed");
b.HasKey("Id");
b.HasIndex("Alias")
.IsUnique()
.HasDatabaseName("alias");
b.HasIndex("LastModified")
.HasDatabaseName("last_modified_tenants_tenants");
b.HasIndex("MappedDomain")
.HasDatabaseName("mappeddomain");
b.HasIndex("Version")
.HasDatabaseName("version");
b.ToTable("tenants_tenants", "onlyoffice");
b.HasData(
new
{
Id = 1,
Alias = "localhost",
Calls = false,
CreationDateTime = new DateTime(2021, 3, 9, 17, 46, 59, 97, DateTimeKind.Utc).AddTicks(4317),
Industry = 0,
LastModified = new DateTime(2022, 7, 8, 0, 0, 0, 0, DateTimeKind.Unspecified),
Name = "Web Office",
OwnerId = new Guid("66faa6e4-f133-11ea-b126-00ffeec8b4ef"),
Spam = false,
Status = 0,
TrustedDomainsEnabled = 0,
Version = 0
});
});
modelBuilder.Entity("ASC.Core.Common.EF.Model.DbWebstudioSettings", b =>
{
b.Property<int>("TenantId")
.HasColumnType("integer")
.HasColumnName("TenantID");
b.Property<Guid>("Id")
.HasMaxLength(64)
.HasColumnType("uuid")
.HasColumnName("ID");
b.Property<Guid>("UserId")
.HasMaxLength(64)
.HasColumnType("uuid")
.HasColumnName("UserID");
b.Property<string>("Data")
.IsRequired()
.HasColumnType("text");
b.HasKey("TenantId", "Id", "UserId")
.HasName("webstudio_settings_pkey");
b.HasIndex("Id")
.HasDatabaseName("ID");
b.ToTable("webstudio_settings", "onlyoffice");
b.HasData(
new
{
TenantId = 1,
Id = new Guid("9a925891-1f92-4ed7-b277-d6f649739f06"),
UserId = new Guid("00000000-0000-0000-0000-000000000000"),
Data = "{\"Completed\":false}"
});
});
modelBuilder.Entity("ASC.Core.Common.EF.User", b =>
{
b.Property<Guid>("Id")
.ValueGeneratedOnAdd()
.HasMaxLength(38)
.HasColumnType("uuid")
.HasColumnName("id");
b.Property<int>("ActivationStatus")
.HasColumnType("integer")
.HasColumnName("activation_status");
b.Property<DateTime?>("BirthDate")
.HasColumnType("timestamp with time zone")
.HasColumnName("bithdate");
b.Property<string>("Contacts")
.ValueGeneratedOnAdd()
.HasMaxLength(1024)
.HasColumnType("character varying(1024)")
.HasColumnName("contacts")
.HasDefaultValueSql("NULL");
b.Property<DateTime>("CreateDate")
.ValueGeneratedOnAdd()
.HasColumnType("timestamp with time zone")
.HasColumnName("create_on")
.HasDefaultValueSql("CURRENT_TIMESTAMP");
b.Property<string>("CultureName")
.ValueGeneratedOnAdd()
.HasMaxLength(20)
.HasColumnType("character varying(20)")
.HasColumnName("culture")
.HasDefaultValueSql("NULL");
b.Property<string>("Email")
.ValueGeneratedOnAdd()
.HasMaxLength(255)
.HasColumnType("character varying(255)")
.HasColumnName("email")
.HasDefaultValueSql("NULL");
b.Property<string>("FirstName")
.IsRequired()
.HasMaxLength(64)
.HasColumnType("character varying(64)")
.HasColumnName("firstname");
b.Property<DateTime>("LastModified")
.HasColumnType("timestamp with time zone")
.HasColumnName("last_modified");
b.Property<string>("LastName")
.IsRequired()
.HasMaxLength(64)
.HasColumnType("character varying(64)")
.HasColumnName("lastname");
b.Property<string>("Location")
.ValueGeneratedOnAdd()
.HasMaxLength(255)
.HasColumnType("character varying(255)")
.HasColumnName("location")
.HasDefaultValueSql("NULL");
b.Property<string>("MobilePhone")
.ValueGeneratedOnAdd()
.HasMaxLength(255)
.HasColumnType("character varying(255)")
.HasColumnName("phone")
.HasDefaultValueSql("NULL");
b.Property<int>("MobilePhoneActivation")
.HasColumnType("integer")
.HasColumnName("phone_activation");
b.Property<string>("Notes")
.ValueGeneratedOnAdd()
.HasMaxLength(512)
.HasColumnType("character varying(512)")
.HasColumnName("notes")
.HasDefaultValueSql("NULL");
b.Property<bool>("Removed")
.HasColumnType("boolean")
.HasColumnName("removed");
b.Property<bool?>("Sex")
.HasColumnType("boolean")
.HasColumnName("sex");
b.Property<string>("Sid")
.ValueGeneratedOnAdd()
.HasMaxLength(512)
.HasColumnType("character varying(512)")
.HasColumnName("sid")
.HasDefaultValueSql("NULL");
b.Property<string>("SsoNameId")
.ValueGeneratedOnAdd()
.HasMaxLength(512)
.HasColumnType("character varying(512)")
.HasColumnName("sso_name_id")
.HasDefaultValueSql("NULL");
b.Property<string>("SsoSessionId")
.ValueGeneratedOnAdd()
.HasMaxLength(512)
.HasColumnType("character varying(512)")
.HasColumnName("sso_session_id")
.HasDefaultValueSql("NULL");
b.Property<int>("Status")
.ValueGeneratedOnAdd()
.HasColumnType("integer")
.HasColumnName("status")
.HasDefaultValueSql("1");
b.Property<int>("Tenant")
.HasColumnType("integer")
.HasColumnName("tenant");
b.Property<DateTime?>("TerminatedDate")
.HasColumnType("timestamp with time zone")
.HasColumnName("terminateddate");
b.Property<string>("Title")
.ValueGeneratedOnAdd()
.HasMaxLength(64)
.HasColumnType("character varying(64)")
.HasColumnName("title")
.HasDefaultValueSql("NULL");
b.Property<string>("UserName")
.IsRequired()
.HasMaxLength(255)
.HasColumnType("character varying(255)")
.HasColumnName("username");
b.Property<DateTime?>("WorkFromDate")
.HasColumnType("timestamp with time zone")
.HasColumnName("workfromdate");
b.HasKey("Id");
b.HasIndex("Email")
.HasDatabaseName("email");
b.HasIndex("LastModified")
.HasDatabaseName("last_modified_core_user");
b.HasIndex("UserName", "Tenant")
.HasDatabaseName("username");
b.ToTable("core_user", "onlyoffice");
b.HasData(
new
{
Id = new Guid("66faa6e4-f133-11ea-b126-00ffeec8b4ef"),
ActivationStatus = 0,
CreateDate = new DateTime(2022, 7, 8, 0, 0, 0, 0, DateTimeKind.Unspecified),
Email = "",
FirstName = "Administrator",
LastModified = new DateTime(2021, 3, 9, 9, 52, 55, 765, DateTimeKind.Utc).AddTicks(1420),
LastName = "",
MobilePhoneActivation = 0,
Removed = false,
Status = 1,
Tenant = 1,
UserName = "administrator",
WorkFromDate = new DateTime(2021, 3, 9, 9, 52, 55, 764, DateTimeKind.Utc).AddTicks(9157)
});
});
modelBuilder.Entity("ASC.Core.Common.EF.UserGroup", b =>
{
b.Property<int>("Tenant")
.HasColumnType("integer")
.HasColumnName("tenant");
b.Property<Guid>("Userid")
.HasMaxLength(38)
.HasColumnType("uuid")
.HasColumnName("userid");
b.Property<Guid>("UserGroupId")
.HasMaxLength(38)
.HasColumnType("uuid")
.HasColumnName("groupid");
b.Property<int>("RefType")
.HasColumnType("integer")
.HasColumnName("ref_type");
b.Property<DateTime>("LastModified")
.ValueGeneratedOnAdd()
.HasColumnType("timestamp with time zone")
.HasColumnName("last_modified")
.HasDefaultValueSql("CURRENT_TIMESTAMP");
b.Property<bool>("Removed")
.HasColumnType("boolean")
.HasColumnName("removed");
b.HasKey("Tenant", "Userid", "UserGroupId", "RefType")
.HasName("core_usergroup_pkey");
b.HasIndex("LastModified")
.HasDatabaseName("last_modified_core_usergroup");
b.ToTable("core_usergroup", "onlyoffice");
});
modelBuilder.Entity("ASC.MessagingSystem.EF.Model.AuditEvent", b =>
{
b.Property<int>("Id")

View File

@ -1,5 +1,31 @@
using System;
// (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 Microsoft.EntityFrameworkCore.Migrations;
using Npgsql.EntityFrameworkCore.PostgreSQL.Metadata;
#nullable disable
@ -37,59 +63,6 @@ namespace ASC.Migrations.PostgreSql.Migrations
table.PrimaryKey("PK_audit_events", x => x.id);
});
migrationBuilder.CreateTable(
name: "core_user",
schema: "onlyoffice",
columns: table => new
{
id = table.Column<Guid>(type: "uuid", maxLength: 38, nullable: false),
tenant = table.Column<int>(type: "integer", nullable: false),
username = table.Column<string>(type: "character varying(255)", maxLength: 255, nullable: false),
firstname = table.Column<string>(type: "character varying(64)", maxLength: 64, nullable: false),
lastname = table.Column<string>(type: "character varying(64)", maxLength: 64, nullable: false),
sex = table.Column<bool>(type: "boolean", nullable: true),
bithdate = table.Column<DateTime>(type: "timestamp with time zone", nullable: true),
status = table.Column<int>(type: "integer", nullable: false, defaultValueSql: "1"),
activation_status = table.Column<int>(type: "integer", nullable: false),
email = table.Column<string>(type: "character varying(255)", maxLength: 255, nullable: true, defaultValueSql: "NULL"),
workfromdate = table.Column<DateTime>(type: "timestamp with time zone", nullable: true),
terminateddate = table.Column<DateTime>(type: "timestamp with time zone", nullable: true),
title = table.Column<string>(type: "character varying(64)", maxLength: 64, nullable: true, defaultValueSql: "NULL"),
culture = table.Column<string>(type: "character varying(20)", maxLength: 20, nullable: true, defaultValueSql: "NULL"),
contacts = table.Column<string>(type: "character varying(1024)", maxLength: 1024, nullable: true, defaultValueSql: "NULL"),
phone = table.Column<string>(type: "character varying(255)", maxLength: 255, nullable: true, defaultValueSql: "NULL"),
phone_activation = table.Column<int>(type: "integer", nullable: false),
location = table.Column<string>(type: "character varying(255)", maxLength: 255, nullable: true, defaultValueSql: "NULL"),
notes = table.Column<string>(type: "character varying(512)", maxLength: 512, nullable: true, defaultValueSql: "NULL"),
sid = table.Column<string>(type: "character varying(512)", maxLength: 512, nullable: true, defaultValueSql: "NULL"),
sso_name_id = table.Column<string>(type: "character varying(512)", maxLength: 512, nullable: true, defaultValueSql: "NULL"),
sso_session_id = table.Column<string>(type: "character varying(512)", maxLength: 512, nullable: true, defaultValueSql: "NULL"),
removed = table.Column<bool>(type: "boolean", nullable: false),
create_on = table.Column<DateTime>(type: "timestamp with time zone", nullable: false, defaultValueSql: "CURRENT_TIMESTAMP"),
last_modified = table.Column<DateTime>(type: "timestamp with time zone", nullable: false)
},
constraints: table =>
{
table.PrimaryKey("PK_core_user", x => x.id);
});
migrationBuilder.CreateTable(
name: "core_usergroup",
schema: "onlyoffice",
columns: table => new
{
tenant = table.Column<int>(type: "integer", nullable: false),
userid = table.Column<Guid>(type: "uuid", maxLength: 38, nullable: false),
groupid = table.Column<Guid>(type: "uuid", maxLength: 38, nullable: false),
ref_type = table.Column<int>(type: "integer", nullable: false),
removed = table.Column<bool>(type: "boolean", nullable: false),
last_modified = table.Column<DateTime>(type: "timestamp with time zone", nullable: false, defaultValueSql: "CURRENT_TIMESTAMP")
},
constraints: table =>
{
table.PrimaryKey("core_usergroup_pkey", x => new { x.tenant, x.userid, x.groupid, x.ref_type });
});
migrationBuilder.CreateTable(
name: "login_events",
schema: "onlyoffice",
@ -114,100 +87,12 @@ namespace ASC.Migrations.PostgreSql.Migrations
table.PrimaryKey("PK_login_events", x => x.id);
});
migrationBuilder.CreateTable(
name: "tenants_tenants",
schema: "onlyoffice",
columns: table => new
{
id = table.Column<int>(type: "integer", nullable: false)
.Annotation("Npgsql:ValueGenerationStrategy", NpgsqlValueGenerationStrategy.IdentityByDefaultColumn),
name = table.Column<string>(type: "character varying(255)", maxLength: 255, nullable: false),
alias = table.Column<string>(type: "character varying(100)", maxLength: 100, nullable: false),
mappeddomain = table.Column<string>(type: "character varying(100)", maxLength: 100, nullable: true, defaultValueSql: "NULL"),
version = table.Column<int>(type: "integer", nullable: false, defaultValueSql: "2"),
version_changed = table.Column<DateTime>(type: "timestamp with time zone", nullable: true),
language = table.Column<string>(type: "character(10)", fixedLength: true, maxLength: 10, nullable: false, defaultValueSql: "'en-US'"),
timezone = table.Column<string>(type: "character varying(50)", maxLength: 50, nullable: true, defaultValueSql: "NULL"),
trusteddomains = table.Column<string>(type: "character varying(1024)", maxLength: 1024, nullable: true, defaultValueSql: "NULL"),
trusteddomainsenabled = table.Column<int>(type: "integer", nullable: false, defaultValueSql: "1"),
status = table.Column<int>(type: "integer", nullable: false),
statuschanged = table.Column<DateTime>(type: "timestamp with time zone", nullable: true),
creationdatetime = table.Column<DateTime>(type: "timestamp with time zone", nullable: false),
owner_id = table.Column<Guid>(type: "uuid", maxLength: 38, nullable: true, defaultValueSql: "NULL"),
payment_id = table.Column<string>(type: "character varying(38)", maxLength: 38, nullable: true, defaultValueSql: "NULL"),
industry = table.Column<int>(type: "integer", nullable: false),
last_modified = table.Column<DateTime>(type: "timestamp with time zone", nullable: false, defaultValueSql: "CURRENT_TIMESTAMP"),
spam = table.Column<bool>(type: "boolean", nullable: false, defaultValueSql: "true"),
calls = table.Column<bool>(type: "boolean", nullable: false, defaultValueSql: "true")
},
constraints: table =>
{
table.PrimaryKey("PK_tenants_tenants", x => x.id);
});
migrationBuilder.CreateTable(
name: "webstudio_settings",
schema: "onlyoffice",
columns: table => new
{
TenantID = table.Column<int>(type: "integer", nullable: false),
ID = table.Column<Guid>(type: "uuid", maxLength: 64, nullable: false),
UserID = table.Column<Guid>(type: "uuid", maxLength: 64, nullable: false),
Data = table.Column<string>(type: "text", nullable: false)
},
constraints: table =>
{
table.PrimaryKey("webstudio_settings_pkey", x => new { x.TenantID, x.ID, x.UserID });
});
migrationBuilder.InsertData(
schema: "onlyoffice",
table: "core_user",
columns: new[] { "id", "activation_status", "bithdate", "create_on", "email", "firstname", "last_modified", "lastname", "phone_activation", "removed", "sex", "status", "tenant", "terminateddate", "username", "workfromdate" },
values: new object[] { new Guid("66faa6e4-f133-11ea-b126-00ffeec8b4ef"), 0, null, new DateTime(2022, 7, 8, 0, 0, 0, 0, DateTimeKind.Unspecified), "", "Administrator", new DateTime(2021, 3, 9, 9, 52, 55, 765, DateTimeKind.Utc).AddTicks(1420), "", 0, false, null, 1, 1, null, "administrator", new DateTime(2021, 3, 9, 9, 52, 55, 764, DateTimeKind.Utc).AddTicks(9157) });
migrationBuilder.InsertData(
schema: "onlyoffice",
table: "tenants_tenants",
columns: new[] { "id", "alias", "creationdatetime", "industry", "last_modified", "name", "owner_id", "status", "statuschanged", "version_changed" },
values: new object[] { 1, "localhost", new DateTime(2021, 3, 9, 17, 46, 59, 97, DateTimeKind.Utc).AddTicks(4317), 0, new DateTime(2022, 7, 8, 0, 0, 0, 0, DateTimeKind.Unspecified), "Web Office", new Guid("66faa6e4-f133-11ea-b126-00ffeec8b4ef"), 0, null, null });
migrationBuilder.InsertData(
schema: "onlyoffice",
table: "webstudio_settings",
columns: new[] { "ID", "TenantID", "UserID", "Data" },
values: new object[] { new Guid("9a925891-1f92-4ed7-b277-d6f649739f06"), 1, new Guid("00000000-0000-0000-0000-000000000000"), "{\"Completed\":false}" });
migrationBuilder.CreateIndex(
name: "date",
schema: "onlyoffice",
table: "audit_events",
columns: new[] { "tenant_id", "date" });
migrationBuilder.CreateIndex(
name: "email",
schema: "onlyoffice",
table: "core_user",
column: "email");
migrationBuilder.CreateIndex(
name: "last_modified_core_user",
schema: "onlyoffice",
table: "core_user",
column: "last_modified");
migrationBuilder.CreateIndex(
name: "username",
schema: "onlyoffice",
table: "core_user",
columns: new[] { "username", "tenant" });
migrationBuilder.CreateIndex(
name: "last_modified_core_usergroup",
schema: "onlyoffice",
table: "core_usergroup",
column: "last_modified");
migrationBuilder.CreateIndex(
name: "date_login_events",
schema: "onlyoffice",
@ -219,37 +104,6 @@ namespace ASC.Migrations.PostgreSql.Migrations
schema: "onlyoffice",
table: "login_events",
columns: new[] { "user_id", "tenant_id" });
migrationBuilder.CreateIndex(
name: "alias",
schema: "onlyoffice",
table: "tenants_tenants",
column: "alias",
unique: true);
migrationBuilder.CreateIndex(
name: "last_modified_tenants_tenants",
schema: "onlyoffice",
table: "tenants_tenants",
column: "last_modified");
migrationBuilder.CreateIndex(
name: "mappeddomain",
schema: "onlyoffice",
table: "tenants_tenants",
column: "mappeddomain");
migrationBuilder.CreateIndex(
name: "version",
schema: "onlyoffice",
table: "tenants_tenants",
column: "version");
migrationBuilder.CreateIndex(
name: "ID",
schema: "onlyoffice",
table: "webstudio_settings",
column: "ID");
}
protected override void Down(MigrationBuilder migrationBuilder)
@ -258,25 +112,9 @@ namespace ASC.Migrations.PostgreSql.Migrations
name: "audit_events",
schema: "onlyoffice");
migrationBuilder.DropTable(
name: "core_user",
schema: "onlyoffice");
migrationBuilder.DropTable(
name: "core_usergroup",
schema: "onlyoffice");
migrationBuilder.DropTable(
name: "login_events",
schema: "onlyoffice");
migrationBuilder.DropTable(
name: "tenants_tenants",
schema: "onlyoffice");
migrationBuilder.DropTable(
name: "webstudio_settings",
schema: "onlyoffice");
}
}
}

View File

@ -18,7 +18,7 @@ namespace ASC.Migrations.PostgreSql.Migrations
#pragma warning disable 612, 618
modelBuilder
.HasAnnotation("Npgsql:ValueGenerationStrategy", NpgsqlValueGenerationStrategy.IdentityByDefaultColumn)
.HasAnnotation("ProductVersion", "6.0.4")
.HasAnnotation("ProductVersion", "6.0.7")
.HasAnnotation("Relational:MaxIdentifierLength", 63);
modelBuilder.Entity("ASC.Core.Common.EF.Model.DbTenant", b =>

View File

@ -18,7 +18,7 @@ namespace ASC.Migrations.PostgreSql.Migrations
#pragma warning disable 612, 618
modelBuilder
.HasAnnotation("Npgsql:ValueGenerationStrategy", NpgsqlValueGenerationStrategy.IdentityByDefaultColumn)
.HasAnnotation("ProductVersion", "6.0.4")
.HasAnnotation("ProductVersion", "6.0.7")
.HasAnnotation("Relational:MaxIdentifierLength", 63);
modelBuilder.Entity("ASC.Core.Common.EF.Acl", b =>

View File

@ -138,9 +138,9 @@ public class FilesUserSpaceUsage : IUserSpaceUsage
var my = _globalFolder.GetFolderMy(_fileMarker, _daoFactory);
var trash = await _globalFolder.GetFolderTrashAsync<int>(_daoFactory);
using var filesDbContext = _dbContextFactory.CreateDbContext();
using var filesDbContext = _dbContextFactory.CreateDbContext();
return await filesDbContext.Files
.Where(r => r.TenantId == tenantId && (r.ParentId == my || r.ParentId == trash))
.Where(r => r.TenantId == tenantId && r.CreateBy == userId && (r.ParentId == my || r.ParentId == trash))
.SumAsync(r => r.ContentLength);
}
}

View File

@ -28,7 +28,7 @@ namespace ASC.Files.Core.Data;
public class AbstractDao
{
protected readonly ICache _cache;
private int _tenantID;
protected internal int TenantID
{
@ -43,6 +43,7 @@ public class AbstractDao
}
}
protected readonly ICache _cache;
protected readonly IDbContextFactory<FilesDbContext> _dbContextFactory;
protected readonly UserManager _userManager;
protected readonly TenantManager _tenantManager;

View File

@ -45,6 +45,7 @@ internal class FileDao : AbstractDao, IFileDao<int>
private readonly Settings _settings;
private readonly IMapper _mapper;
private readonly ThumbnailSettings _thumbnailSettings;
private readonly IQuotaService _quotaService;
public FileDao(
ILogger<FileDao> logger,
@ -72,7 +73,8 @@ internal class FileDao : AbstractDao, IFileDao<int>
CrossDao crossDao,
Settings settings,
IMapper mapper,
ThumbnailSettings thumbnailSettings)
ThumbnailSettings thumbnailSettings,
IQuotaService quotaService)
: base(
dbContextManager,
userManager,
@ -101,6 +103,7 @@ internal class FileDao : AbstractDao, IFileDao<int>
_settings = settings;
_mapper = mapper;
_thumbnailSettings = thumbnailSettings;
_quotaService = quotaService;
}
public Task InvalidateCacheAsync(int fileId)
@ -416,6 +419,25 @@ internal class FileDao : AbstractDao, IFileDao<int>
}
}
var quotaSettings = _settingsManager.Load<TenantUserQuotaSettings>();
if (quotaSettings.EnableUserQuota)
{
var user = _userManager.GetUsers(file.Id == default ? _authContext.CurrentAccount.ID : file.CreateBy);
var userQuotaSettings = _settingsManager.LoadForUser<UserQuotaSettings>(user);
var quotaLimit = userQuotaSettings.UserQuota;
if (quotaLimit != -1)
{
var userUsedSpace = Math.Max(0, _quotaService.FindUserQuotaRows(TenantID, user.Id).Where(r => !string.IsNullOrEmpty(r.Tag)).Sum(r => r.Counter));
if (quotaLimit - userUsedSpace < file.ContentLength)
{
throw FileSizeComment.GetPersonalFreeSpaceException(quotaLimit);
}
}
}
var isNew = false;
List<int> parentFoldersIds;
DbFile toInsert = null;

View File

@ -128,7 +128,8 @@ global using ASC.Web.Core.Files;
global using ASC.Web.Core.ModuleManagement.Common;
global using ASC.Web.Core.PublicResources;
global using ASC.Web.Core.Subscriptions;
global using ASC.Web.Core.Users;
global using ASC.Web.Core.Users;
global using ASC.Web.Core.Utility;
global using ASC.Web.Core.Utility.Skins;
global using ASC.Web.Core.WhiteLabel;
global using ASC.Web.Files;

View File

@ -34,7 +34,8 @@ public class UserController : PeopleControllerBase
private Tenant Tenant => _apiContext.Tenant;
private readonly ICache _cache;
private readonly TenantManager _tenantManager;
private readonly TenantManager _tenantManager;
private readonly GlobalSpace _globalSpace;
private readonly Constants _constants;
private readonly CookiesManager _cookiesManager;
private readonly CoreBaseSettings _coreBaseSettings;
@ -64,10 +65,12 @@ public class UserController : PeopleControllerBase
private readonly SettingsManager _settingsManager;
private readonly RoomLinkService _roomLinkService;
private readonly FileSecurity _fileSecurity;
private readonly IQuotaService _quotaService;
public UserController(
ICache cache,
TenantManager tenantManager,
TenantManager tenantManager,
GlobalSpace globalSpace,
Constants constants,
CookiesManager cookiesManager,
CoreBaseSettings coreBaseSettings,
@ -102,11 +105,13 @@ public class UserController : PeopleControllerBase
IHttpContextAccessor httpContextAccessor,
SettingsManager settingsManager,
RoomLinkService roomLinkService,
FileSecurity fileSecurity)
FileSecurity fileSecurity,
IQuotaService quotaService)
: base(userManager, permissionContext, apiContext, userPhotoManager, httpClientFactory, httpContextAccessor)
{
_cache = cache;
_tenantManager = tenantManager;
_globalSpace = globalSpace;
_constants = constants;
_cookiesManager = cookiesManager;
_coreBaseSettings = coreBaseSettings;
@ -136,6 +141,7 @@ public class UserController : PeopleControllerBase
_settingsManager = settingsManager;
_roomLinkService = roomLinkService;
_fileSecurity = fileSecurity;
_quotaService = quotaService;
}
[HttpPost("active")]
@ -1062,7 +1068,43 @@ public class UserController : PeopleControllerBase
{
yield return await _employeeFullDtoHelper.GetFull(user);
}
}
}
[HttpPut("quota")]
public async IAsyncEnumerable<EmployeeFullDto> UpdateUserQuota(UpdateMembersQuotaRequestDto inDto)
{
var users = inDto.UserIds
.Where(userId => !_userManager.IsSystemUser(userId))
.Select(userId => _userManager.GetUsers(userId))
.ToList();
foreach (var user in users)
{
if (inDto.Quota != -1)
{
var usedSpace = Math.Max(0,
_quotaService.FindUserQuotaRows(
_tenantManager.GetCurrentTenant().Id,
user.Id
)
.Where(r => !string.IsNullOrEmpty(r.Tag)).Sum(r => r.Counter));
var tenanSpaceQuota = _tenantExtra.GetTenantQuota().MaxTotalSize;
if (tenanSpaceQuota < inDto.Quota || usedSpace > inDto.Quota)
{
continue;
}
}
var quotaSettings = _settingsManager.Load<TenantUserQuotaSettings>();
_settingsManager.SaveForUser(new UserQuotaSettings { UserQuota = inDto.Quota }, user);
yield return await _employeeFullDtoHelper.GetFull(user);
}
}
private void UpdateDepartments(IEnumerable<Guid> department, UserInfo user)
{

View File

@ -0,0 +1,33 @@
// (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.People.ApiModels.RequestDto;
public class UpdateMembersQuotaRequestDto
{
public IEnumerable<Guid> UserIds { get; set; }
public long Quota { get; set; }
}

View File

@ -38,7 +38,8 @@ global using ASC.Common;
global using ASC.Common.Caching;
global using ASC.Common.Utils;
global using ASC.Common.Web;
global using ASC.Core;
global using ASC.Core;
global using ASC.Core.Common;
global using ASC.Core.Common.Settings;
global using ASC.Core.Tenants;
global using ASC.Core.Users;
@ -63,7 +64,9 @@ global using ASC.Web.Api.Routing;
global using ASC.Web.Core;
global using ASC.Web.Core.Mobile;
global using ASC.Web.Core.PublicResources;
global using ASC.Web.Core.Users;
global using ASC.Web.Core.Users;
global using ASC.Web.Core.Utility;
global using ASC.Web.Files.Classes;
global using ASC.Web.Studio.Core;
global using ASC.Web.Studio.Core.Notify;
global using ASC.Web.Studio.UserControls.Statistics;

View File

@ -28,7 +28,7 @@ using Constants = ASC.Core.Users.Constants;
namespace ASC.Web.Api.Controllers.Settings;
public class SettingsController : BaseSettingsController
{
{
private static readonly object locked = new object();
private Tenant Tenant { get { return ApiContext.Tenant; } }
@ -62,7 +62,8 @@ public class SettingsController : BaseSettingsController
private readonly Constants _constants;
private readonly DnsSettings _dnsSettings;
private readonly AdditionalWhiteLabelSettingsHelper _additionalWhiteLabelSettingsHelper;
private readonly CustomColorThemesSettingsHelper _customColorThemesSettingsHelper;
private readonly CustomColorThemesSettingsHelper _customColorThemesSettingsHelper;
private readonly QuotaSyncOperation _quotaSyncOperation;
public SettingsController(
ILoggerProvider option,
@ -98,8 +99,9 @@ public class SettingsController : BaseSettingsController
Constants constants,
IHttpContextAccessor httpContextAccessor,
DnsSettings dnsSettings,
AdditionalWhiteLabelSettingsHelper additionalWhiteLabelSettingsHelper,
CustomColorThemesSettingsHelper customColorThemesSettingsHelper
AdditionalWhiteLabelSettingsHelper additionalWhiteLabelSettingsHelper,
CustomColorThemesSettingsHelper customColorThemesSettingsHelper,
QuotaSyncOperation quotaSyncOperation
) : base(apiContext, memoryCache, webItemManager, httpContextAccessor)
{
_log = option.CreateLogger("ASC.Api");
@ -132,7 +134,8 @@ public class SettingsController : BaseSettingsController
_constants = constants;
_dnsSettings = dnsSettings;
_additionalWhiteLabelSettingsHelper = additionalWhiteLabelSettingsHelper;
_customColorThemesSettingsHelper = customColorThemesSettingsHelper;
_quotaSyncOperation = quotaSyncOperation;
_customColorThemesSettingsHelper = customColorThemesSettingsHelper;
}
[HttpGet("")]
@ -266,6 +269,16 @@ public class SettingsController : BaseSettingsController
public QuotaDto GetQuotaUsed()
{
return new QuotaDto(Tenant, _coreBaseSettings, _coreConfiguration, _tenantExtra, _tenantStatisticsProvider, _authContext, _settingsManager, WebItemManager, _constants);
}
[HttpPost("userquotasettings")]
public object SaveUserQuotaSettings(UserQuotaSettingsRequestsDto inDto)
{
_permissionContext.DemandPermissions(SecutiryConstants.EditPortalSettings);
_settingsManager.Save(new TenantUserQuotaSettings { EnableUserQuota = inDto.EnableUserQuota, DefaultUserQuota = inDto.DefaultUserQuota });
return Resource.SuccessfullySaveSettingsMessage;
}
[AllowAnonymous]
@ -317,39 +330,19 @@ public class SettingsController : BaseSettingsController
return _dnsSettings.SaveDnsSettings(model.DnsName, model.Enable);
}
//[HttpGet("recalculatequota")]
//public void RecalculateQuota()
//{
// SecurityContext.DemandPermissions(Tenant, SecutiryConstants.EditPortalSettings);
[HttpGet("recalculatequota")]
public void RecalculateQuota()
{
_permissionContext.DemandPermissions(SecutiryConstants.EditPortalSettings);
_quotaSyncOperation.RecalculateQuota(_tenantManager.GetCurrentTenant());
}
// var operations = quotaTasks.GetTasks()
// .Where(t => t.GetProperty<int>(QuotaSync.IdKey) == Tenant.Id);
// if (operations.Any(o => o.Status <= DistributedTaskStatus.Running))
// {
// throw new InvalidOperationException(Resource.LdapSettingsTooManyOperations);
// }
// var op = new QuotaSync(Tenant.Id, ServiceProvider);
// quotaTasks.QueueTask(op.RunJob, op.GetDistributedTask());
//}
//[HttpGet("checkrecalculatequota")]
//public bool CheckRecalculateQuota()
//{
// PermissionContext.DemandPermissions(SecutiryConstants.EditPortalSettings);
// var task = quotaTasks.GetTasks().FirstOrDefault(t => t.GetProperty<int>(QuotaSync.IdKey) == Tenant.Id);
// if (task != null && task.Status == DistributedTaskStatus.Completed)
// {
// quotaTasks.RemoveTask(task.Id);
// return false;
// }
// return task != null;
//}
[HttpGet("checkrecalculatequota")]
public bool CheckRecalculateQuota()
{
_permissionContext.DemandPermissions(SecutiryConstants.EditPortalSettings);
return _quotaSyncOperation.CheckRecalculateQuota(_tenantManager.GetCurrentTenant());
}
[HttpGet("logo")]
public object GetLogo()
@ -385,7 +378,7 @@ public class SettingsController : BaseSettingsController
collaboratorPopupSettings.FirstVisit = false;
_settingsManager.SaveForCurrentUser(collaboratorPopupSettings);
}
[AllowAnonymous]
[HttpGet("colortheme")]
public CustomColorThemesSettingsDto GetColorTheme()
@ -396,7 +389,7 @@ public class SettingsController : BaseSettingsController
[HttpPut("colortheme")]
public CustomColorThemesSettingsDto SaveColorTheme(CustomColorThemesSettingsRequestsDto inDto)
{
_permissionContext.DemandPermissions(SecutiryConstants.EditPortalSettings);
_permissionContext.DemandPermissions(SecutiryConstants.EditPortalSettings);
var settings = _settingsManager.Load<CustomColorThemesSettings>();
if (inDto.Themes != null)
@ -434,8 +427,8 @@ public class SettingsController : BaseSettingsController
{
settings.Selected = inDto.Selected.Value;
_settingsManager.Save(settings);
_messageService.Send(MessageAction.ColorThemeChanged);
}
_messageService.Send(MessageAction.ColorThemeChanged);
}
return new CustomColorThemesSettingsDto(settings, _customColorThemesSettingsHelper.Limit);
}

View File

@ -0,0 +1,34 @@
// (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.Api.ApiModel.RequestsDto;
public class UserQuotaSettingsRequestsDto
{
public bool EnableUserQuota { get; set; }
public long DefaultUserQuota { get; set; }
}

View File

@ -119,10 +119,11 @@ global using ASC.Web.Core.WebZones;
global using ASC.Web.Core.WhiteLabel;
global using ASC.Web.Files.Services.DocumentService;
global using ASC.Web.Studio.Core;
global using ASC.Web.Studio.Core.Notify;
global using ASC.Web.Studio.Core.Notify;
global using ASC.Web.Studio.Core.Quota;
global using ASC.Web.Studio.Core.SMS;
global using ASC.Web.Studio.Core.Statistic;
global using ASC.Web.Studio.Core.TFA;
global using ASC.Web.Studio.Core.TFA;
global using ASC.Web.Studio.UserControls.CustomNavigation;
global using ASC.Web.Studio.UserControls.FirstTime;
global using ASC.Web.Studio.UserControls.Management;

View File

@ -2004,6 +2004,33 @@ namespace ASC.Web.Core.PublicResources {
}
}
/// <summary>
/// Looks up a localized string similar to Failed to set the memory quota - the memory quota you set is greater than portals quota..
/// </summary>
public static string QuotaGreaterPortalError {
get {
return ResourceManager.GetString("QuotaGreaterPortalError", resourceCulture);
}
}
/// <summary>
/// Looks up a localized string similar to Failed to set the memory quota - some users cannot use this quota..
/// </summary>
public static string QuotaGroupError {
get {
return ResourceManager.GetString("QuotaGroupError", resourceCulture);
}
}
/// <summary>
/// Looks up a localized string similar to Failed to set the memory quota - the memory quota you set is less than used memory..
/// </summary>
public static string QuotaLessUsedMemoryError {
get {
return ResourceManager.GetString("QuotaLessUsedMemoryError", resourceCulture);
}
}
/// <summary>
/// Looks up a localized string similar to Data reassign process for {0} is not complete..
/// </summary>

View File

@ -828,4 +828,13 @@
<data name="MessageRoomInvitationsSentOnEmail" xml:space="preserve">
<value>Virtual room {0} invitations sent successfully.</value>
</data>
<data name="QuotaGreaterPortalError" xml:space="preserve">
<value>Failed to set the memory quota - the memory quota you set is greater than portals quota.</value>
</data>
<data name="QuotaGroupError" xml:space="preserve">
<value>Failed to set the memory quota - some users cannot use this quota.</value>
</data>
<data name="QuotaLessUsedMemoryError" xml:space="preserve">
<value>Failed to set the memory quota - the memory quota you set is less than used memory.</value>
</data>
</root>

View File

@ -23,67 +23,127 @@
// 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.Studio.Core.Quota;
public class QuotaSync
[Singletone(Additional = typeof(QuotaSyncOperationExtension))]
public class QuotaSyncOperation
{
public const string TenantIdKey = "tenantID";
protected DistributedTask TaskInfo { get; private set; }
private readonly int _tenantId;
public const string CUSTOM_DISTRIBUTED_TASK_QUEUE_NAME = "ldapOperation";
private readonly DistributedTaskQueue _progressQueue;
private readonly IServiceProvider _serviceProvider;
public QuotaSync(int tenantId, IServiceProvider serviceProvider)
public QuotaSyncOperation(IServiceProvider serviceProvider, IDistributedTaskQueueFactory queueFactory)
{
_tenantId = tenantId;
TaskInfo = new DistributedTask();
;
_serviceProvider = serviceProvider;
_progressQueue = queueFactory.CreateQueue(CUSTOM_DISTRIBUTED_TASK_QUEUE_NAME);
}
public void RunJob()//DistributedTask distributedTask, CancellationToken cancellationToken)
public void RecalculateQuota(Tenant tenant)
{
using var scope = _serviceProvider.CreateScope();
var scopeClass = scope.ServiceProvider.GetService<QuotaSyncJob>();
scopeClass.RunJob(_tenantId);
}
public virtual DistributedTask GetDistributedTask()
{
TaskInfo[TenantIdKey] = _tenantId;
return TaskInfo;
}
}
class QuotaSyncJob
{
private readonly TenantManager _tenantManager;
private readonly StorageFactoryConfig _storageFactoryConfig;
private readonly StorageFactory _storageFactory;
public QuotaSyncJob(TenantManager tenantManager, StorageFactoryConfig storageFactoryConfig, StorageFactory storageFactory)
{
_tenantManager = tenantManager;
_storageFactoryConfig = storageFactoryConfig;
_storageFactory = storageFactory;
}
public void RunJob(int tenantId)
{
_tenantManager.SetCurrentTenant(tenantId);
var storageModules = _storageFactoryConfig.GetModuleList(string.Empty);
foreach (var module in storageModules)
var item = _progressQueue.GetAllTasks<QuotaSyncJob>().FirstOrDefault(t => t.TenantId == tenant.Id);
if (item != null && item.IsCompleted)
{
var storage = _storageFactory.GetStorage(tenantId.ToString(), module);
storage.ResetQuotaAsync("").Wait();
_progressQueue.DequeueTask(item.Id);
item = null;
}
if (item == null)
{
item = _serviceProvider.GetRequiredService<QuotaSyncJob>();
item.InitJob(tenant);
_progressQueue.EnqueueTask(item);
}
var domains = _storageFactoryConfig.GetDomainList(string.Empty, module);
foreach (var domain in domains)
{
storage.ResetQuotaAsync(domain).Wait();
}
item.PublishChanges();
}
public bool CheckRecalculateQuota(Tenant tenant)
{
var item = _progressQueue.GetAllTasks<QuotaSyncJob>().FirstOrDefault(t => t.TenantId == tenant.Id);
if (item != null && item.IsCompleted)
{
_progressQueue.DequeueTask(item.Id);
return false;
}
return item != null;
}
public static class QuotaSyncOperationExtension
{
public static void Register(DIHelper services)
{
services.TryAdd<QuotaSyncJob>();
}
}
}
public class QuotaSyncJob : DistributedTaskProgress
{
private readonly IServiceScopeFactory _serviceScopeFactory;
private int? _tenantId;
public int TenantId
{
get
{
return _tenantId ?? this[nameof(_tenantId)];
}
private set
{
_tenantId = value;
this[nameof(_tenantId)] = value;
}
}
public QuotaSyncJob(IServiceScopeFactory serviceScopeFactory)
{
_serviceScopeFactory = serviceScopeFactory;
}
public void InitJob(Tenant tenant)
{
TenantId = tenant.Id;
}
protected override void DoJob()
{
try
{
using var scope = _serviceScopeFactory.CreateScope();
var _tenantManager = scope.ServiceProvider.GetRequiredService<TenantManager>();
var _storageFactoryConfig = scope.ServiceProvider.GetRequiredService<StorageFactoryConfig>();
var _storageFactory = scope.ServiceProvider.GetRequiredService<StorageFactory>();
_tenantManager.SetCurrentTenant(TenantId);
var storageModules = _storageFactoryConfig.GetModuleList(string.Empty);
foreach (var module in storageModules)
{
var storage = _storageFactory.GetStorage(TenantId.ToString(), module);
storage.ResetQuotaAsync("").Wait();
var domains = _storageFactoryConfig.GetDomainList(string.Empty, module);
foreach (var domain in domains)
{
storage.ResetQuotaAsync(domain).Wait();
}
}
}
catch (Exception ex)
{
Status = DistributedTaskStatus.Failted;
Exception = ex;
}
finally
{
IsCompleted = true;
}
PublishChanges();
}
}

View File

@ -139,7 +139,7 @@ public class SmsManager
{
if (await _smsSender.SendSMSAsync(mobilePhone, string.Format(Resource.SmsAuthenticationMessageToUser, key)))
{
_tenantManager.SetTenantQuotaRow(new TenantQuotaRow { Tenant = _tenantManager.GetCurrentTenant().Id, Path = "/sms", Counter = 1 }, true);
_tenantManager.SetTenantQuotaRow(new TenantQuotaRow { Tenant = _tenantManager.GetCurrentTenant().Id, Path = "/sms", Counter = 1, LastModified = DateTime.UtcNow }, true);
}
}