Merge branch 'develop' of github.com:ONLYOFFICE/AppServer into feature/sso

# Conflicts:
#	web/ASC.Web.Client/public/locales/en/Settings.json
This commit is contained in:
Viktor Fomin 2022-07-19 21:22:18 +03:00
commit 9e68c29d4f
679 changed files with 8675 additions and 34397 deletions

22
.gitignore vendored
View File

@ -17,3 +17,25 @@ Logs/
build/deploy/
/public/debuginfo.md
TestsResults/
/Data.Test
/build/install/RadicalePlugins/app_auth_plugin/app_auth_plugin.egg-info/PKG-INFO
/build/install/RadicalePlugins/app_auth_plugin/app_auth_plugin.egg-info/SOURCES.txt
/build/install/RadicalePlugins/app_auth_plugin/app_auth_plugin.egg-info/dependency_links.txt
/build/install/RadicalePlugins/app_auth_plugin/app_auth_plugin.egg-info/top_level.txt
/build/install/RadicalePlugins/app_auth_plugin/build/lib/app_auth_plugin/__init__.py
/build/install/RadicalePlugins/app_rights_plugin/app_rights_plugin.egg-info/PKG-INFO
/build/install/RadicalePlugins/app_rights_plugin/app_rights_plugin.egg-info/SOURCES.txt
/build/install/RadicalePlugins/app_rights_plugin/app_rights_plugin.egg-info/dependency_links.txt
/build/install/RadicalePlugins/app_rights_plugin/app_rights_plugin.egg-info/top_level.txt
/build/install/RadicalePlugins/app_rights_plugin/build/lib/app_rights_plugin/__init__.py
/build/install/RadicalePlugins/app_store_plugin/app_store_plugin.egg-info/PKG-INFO
/build/install/RadicalePlugins/app_store_plugin/app_store_plugin.egg-info/SOURCES.txt
/build/install/RadicalePlugins/app_store_plugin/app_store_plugin.egg-info/dependency_links.txt
/build/install/RadicalePlugins/app_store_plugin/app_store_plugin.egg-info/top_level.txt
/build/install/RadicalePlugins/app_store_plugin/build/lib/app_store_plugin/__init__.py
/build/install/RadicalePlugins/app_store_plugin/build/lib/app_store_plugin/cache.py
/build/install/RadicalePlugins/app_store_plugin/build/lib/app_store_plugin/delete.py
/build/install/RadicalePlugins/app_store_plugin/build/lib/app_store_plugin/history.py
/build/install/RadicalePlugins/app_store_plugin/build/lib/app_store_plugin/log.py
/build/install/RadicalePlugins/app_store_plugin/build/lib/app_store_plugin/sync.py
/build/install/RadicalePlugins/app_store_plugin/build/lib/app_store_plugin/upload.py

View File

@ -24,8 +24,6 @@ Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "ASC.FederatedLogin", "commo
EndProject
Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "ASC.Web.Core", "web\ASC.Web.Core\ASC.Web.Core.csproj", "{02C40A64-FE22-41D0-9037-69F0D6F787A9}"
EndProject
Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "ASC.VoipService", "common\ASC.VoipService\ASC.VoipService.csproj", "{988536C1-4B89-4649-8F77-5C16F55D95D1}"
EndProject
Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "ASC.MessagingSystem", "common\ASC.MessagingSystem\ASC.MessagingSystem.csproj", "{BD8A18A5-60C5-4411-9719-0AA11B4BE0E9}"
EndProject
Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "ASC.IPSecurity", "common\ASC.IPSecurity\ASC.IPSecurity.csproj", "{2FF2177F-2D1A-4396-84EB-51F14FD99385}"
@ -54,8 +52,6 @@ Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "ASC.ApiSystem", "common\ser
EndProject
Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "ASC.Feed.Aggregator", "common\services\ASC.Feed.Aggregator\ASC.Feed.Aggregator.csproj", "{07CCC11F-76CB-448E-B15A-72E09FBB348B}"
EndProject
Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "ASC.Thumbnails.Svc", "common\services\ASC.Thumbnails.Svc\ASC.Thumbnails.Svc.csproj", "{1D2F61B2-B1F4-45F0-83CA-03370FD6E62C}"
EndProject
Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "ASC.Files.Core", "products\ASC.Files\Core\ASC.Files.Core.csproj", "{F0A39728-940D-4DBE-A37A-05D4EB57F342}"
EndProject
Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "ASC.Data.Storage.Migration", "common\services\ASC.Data.Storage.Migration\ASC.Data.Storage.Migration.csproj", "{02356BD7-7E99-457B-BEFF-090CE4DF067D}"
@ -147,10 +143,6 @@ Global
{02C40A64-FE22-41D0-9037-69F0D6F787A9}.Debug|Any CPU.Build.0 = Debug|Any CPU
{02C40A64-FE22-41D0-9037-69F0D6F787A9}.Release|Any CPU.ActiveCfg = Release|Any CPU
{02C40A64-FE22-41D0-9037-69F0D6F787A9}.Release|Any CPU.Build.0 = Release|Any CPU
{988536C1-4B89-4649-8F77-5C16F55D95D1}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
{988536C1-4B89-4649-8F77-5C16F55D95D1}.Debug|Any CPU.Build.0 = Debug|Any CPU
{988536C1-4B89-4649-8F77-5C16F55D95D1}.Release|Any CPU.ActiveCfg = Release|Any CPU
{988536C1-4B89-4649-8F77-5C16F55D95D1}.Release|Any CPU.Build.0 = Release|Any CPU
{BD8A18A5-60C5-4411-9719-0AA11B4BE0E9}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
{BD8A18A5-60C5-4411-9719-0AA11B4BE0E9}.Debug|Any CPU.Build.0 = Debug|Any CPU
{BD8A18A5-60C5-4411-9719-0AA11B4BE0E9}.Release|Any CPU.ActiveCfg = Release|Any CPU
@ -207,10 +199,6 @@ Global
{07CCC11F-76CB-448E-B15A-72E09FBB348B}.Debug|Any CPU.Build.0 = Debug|Any CPU
{07CCC11F-76CB-448E-B15A-72E09FBB348B}.Release|Any CPU.ActiveCfg = Release|Any CPU
{07CCC11F-76CB-448E-B15A-72E09FBB348B}.Release|Any CPU.Build.0 = Release|Any CPU
{1D2F61B2-B1F4-45F0-83CA-03370FD6E62C}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
{1D2F61B2-B1F4-45F0-83CA-03370FD6E62C}.Debug|Any CPU.Build.0 = Debug|Any CPU
{1D2F61B2-B1F4-45F0-83CA-03370FD6E62C}.Release|Any CPU.ActiveCfg = Release|Any CPU
{1D2F61B2-B1F4-45F0-83CA-03370FD6E62C}.Release|Any CPU.Build.0 = Release|Any CPU
{F0A39728-940D-4DBE-A37A-05D4EB57F342}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
{F0A39728-940D-4DBE-A37A-05D4EB57F342}.Debug|Any CPU.Build.0 = Debug|Any CPU
{F0A39728-940D-4DBE-A37A-05D4EB57F342}.Release|Any CPU.ActiveCfg = Release|Any CPU

View File

@ -20,7 +20,6 @@
"common\\ASC.Migration\\ASC.Migration.csproj",
"common\\ASC.Notify.Textile\\ASC.Notify.Textile.csproj",
"common\\ASC.Textile\\ASC.Textile.csproj",
"common\\ASC.VoipService\\ASC.VoipService.csproj",
"common\\ASC.Webhooks.Core\\ASC.Webhooks.Core.csproj",
"common\\services\\ASC.AuditTrail\\ASC.AuditTrail.csproj",
"common\\services\\ASC.ClearEvents\\ASC.ClearEvents.csproj",

View File

@ -26,6 +26,8 @@
using static ASC.Security.Cryptography.EmailValidationKeyProvider;
using Constants = ASC.Core.Users.Constants;
namespace ASC.Api.Core.Security;
[Transient]
@ -58,7 +60,7 @@ public class EmailValidationKeyModelHelper
{
var request = QueryHelpers.ParseQuery(_httpContextAccessor.HttpContext.Request.Headers["confirm"]);
request.TryGetValue("type", out var type);
var type = request.ContainsKey("type") ? request["type"].FirstOrDefault() : null;
ConfirmType? cType = null;
if (ConfirmTypeExtensions.TryParse(type, out var confirmType))
@ -141,7 +143,7 @@ public class EmailValidationKeyModelHelper
case ConfirmType.ProfileRemove:
// validate UiD
var user = _userManager.GetUsers(uiD.GetValueOrDefault());
if (user == null || user.Status == EmployeeStatus.Terminated || _authContext.IsAuthenticated && _authContext.CurrentAccount.ID != uiD)
if (user == null || user == Constants.LostUser || user.Status == EmployeeStatus.Terminated || _authContext.IsAuthenticated && _authContext.CurrentAccount.ID != uiD)
{
return ValidationResult.Invalid;
}

View File

@ -46,8 +46,8 @@ public class AscCacheNotify
public void OnClearCache()
{
_cache.Reset();
}
}
}
[Singletone]
public class AscCache : ICache
@ -67,27 +67,14 @@ public class AscCache : ICache
return _memoryCache.Get<T>(key);
}
public void Insert(string key, object value, TimeSpan sligingExpiration)
public void Insert(string key, object value, TimeSpan sligingExpiration, Action<object, object, EvictionReason, object> evictionCallback = null)
{
var options = new MemoryCacheEntryOptions()
.SetSlidingExpiration(sligingExpiration)
.RegisterPostEvictionCallback(EvictionCallback)
.AddExpirationToken(new CancellationChangeToken(_resetCacheToken.Token));
_memoryCache.Set(key, value, options);
_memoryCacheKeys.TryAdd(key, null);
Insert(key, value, sligingExpiration, null, evictionCallback);
}
public void Insert(string key, object value, DateTime absolutExpiration)
public void Insert(string key, object value, DateTime absolutExpiration, Action<object, object, EvictionReason, object> evictionCallback = null)
{
var options = new MemoryCacheEntryOptions()
.SetAbsoluteExpiration(absolutExpiration == DateTime.MaxValue ? DateTimeOffset.MaxValue : new DateTimeOffset(absolutExpiration))
.RegisterPostEvictionCallback(EvictionCallback)
.AddExpirationToken(new CancellationChangeToken(_resetCacheToken.Token));
_memoryCache.Set(key, value, options);
_memoryCacheKeys.TryAdd(key, null);
Insert(key, value, null, absolutExpiration, evictionCallback);
}
public void Remove(string key)
@ -160,6 +147,31 @@ public class AscCache : ICache
}
}
private void Insert(string key, object value, TimeSpan? sligingExpiration = null, DateTime? absolutExpiration = null, Action<object, object, EvictionReason, object> evictionCallback = null)
{
var options = new MemoryCacheEntryOptions()
.RegisterPostEvictionCallback(EvictionCallback)
.AddExpirationToken(new CancellationChangeToken(_resetCacheToken.Token));
if (sligingExpiration.HasValue)
{
options = options.SetSlidingExpiration(sligingExpiration.Value);
}
if (absolutExpiration.HasValue)
{
options = options.SetAbsoluteExpiration(absolutExpiration.Value == DateTime.MaxValue ? DateTimeOffset.MaxValue : new DateTimeOffset(absolutExpiration.Value));
}
if (evictionCallback != null)
{
options = options.RegisterPostEvictionCallback(new PostEvictionDelegate(evictionCallback));
}
_memoryCache.Set(key, value, options);
_memoryCacheKeys.TryAdd(key, null);
}
private void EvictionCallback(object key, object value, EvictionReason reason, object state)
{
_memoryCacheKeys.TryRemove(key.ToString(), out _);

View File

@ -31,9 +31,9 @@ public interface ICache
{
T Get<T>(string key) where T : class;
void Insert(string key, object value, TimeSpan sligingExpiration);
void Insert(string key, object value, TimeSpan sligingExpiration, Action<object, object, EvictionReason, object> evictionCallback = null);
void Insert(string key, object value, DateTime absolutExpiration);
void Insert(string key, object value, DateTime absolutExpiration, Action<object, object, EvictionReason, object> evictionCallback = null);
void Remove(string key);
@ -44,6 +44,6 @@ public interface ICache
T HashGet<T>(string key, string field);
void HashSet<T>(string key, string field, T value);
void Reset();
}

View File

@ -50,6 +50,11 @@ public class AzRecord : IMapFrom<Acl>
Object = fullId;
}
public AzRecord(Guid subjectId, Guid actionId, AceType reaction, ISecurityObjectId objectId)
: this(subjectId, actionId, reaction, AzObjectIdHelper.GetFullObjectId(objectId))
{
}
public static implicit operator AzRecord(AzRecordCache cache)
{
var result = new AzRecord()

View File

@ -45,7 +45,6 @@ public class DbLoginEventsManager
(int)MessageAction.LoginSuccessViaApiTfa
};
private readonly ICache _cache;
private readonly TenantManager _tenantManager;
private readonly AuthContext _authContext;
private readonly IMapper _mapper;
@ -54,14 +53,11 @@ public class DbLoginEventsManager
private readonly Lazy<MessagesContext> _lazyLoginEventContext;
public DbLoginEventsManager(
ICache cache,
TenantManager tenantManager,
AuthContext authContext,
DbContextManager<MessagesContext> dbContextManager,
TenantUtil tenantUtil,
IMapper mapper)
{
_cache = cache;
_tenantManager = tenantManager;
_authContext = authContext;
_mapper = mapper;
@ -69,25 +65,13 @@ public class DbLoginEventsManager
}
public async Task<List<int>> GetLoginEventIds(int tenantId, Guid userId)
{
var commonKey = GetCacheKey(tenantId, userId);
var cacheKeys = _cache.Get<List<int>>(commonKey);
if (cacheKeys != null)
{
return cacheKeys;
}
{
var date = DateTime.UtcNow.AddYears(-1);
var resultList = await LoginEventContext.LoginEvents
.Where(r => r.TenantId == tenantId && r.UserId == userId && _loginActions.Contains(r.Action) && r.Date >= date && r.Active)
.Select(r => r.Id)
.ToListAsync();
if (resultList != null)
{
_cache.Insert(commonKey, resultList, _expirationTimeout);
}
return resultList;
}
@ -174,7 +158,6 @@ public class DbLoginEventsManager
public void ResetCache(int tenantId, Guid userId)
{
var key = GetCacheKey(tenantId, userId);
_cache.Remove(key);
}
private string GetCacheKey(int tenantId, Guid userId)

View File

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

View File

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

View File

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

View File

@ -65,6 +65,7 @@ public class DbTenant : IMapFrom<Tenant>
public void Mapping(Profile profile)
{
profile.CreateMap<Tenant, DbTenant>()
.ForMember(dest => dest.TrustedDomainsEnabled, opt => opt.MapFrom(dest => dest.TrustedDomainsType))
.ForMember(dest => dest.TrustedDomainsRaw, opt => opt.MapFrom(dest => dest.GetTrustedDomains()))
.ForMember(dest => dest.Alias, opt => opt.MapFrom(dest => dest.Alias.ToLowerInvariant()))
.ForMember(dest => dest.LastModified, opt => opt.MapFrom(dest => DateTime.UtcNow))

View File

@ -160,3 +160,5 @@ global using ProtoBuf;
global using Telegram.Bot;
global using static ASC.Security.Cryptography.EmailValidationKeyProvider;
global using JsonIgnoreAttribute = System.Text.Json.Serialization.JsonIgnoreAttribute;

View File

@ -34,7 +34,8 @@ public class EventTypeConverter : ITypeConverter<EventMessage, LoginEvent>, ITyp
var messageEvent = context.Mapper.Map<EventMessage, MessageEvent>(source);
var loginEvent = context.Mapper.Map<MessageEvent, LoginEvent>(messageEvent);
loginEvent.Login = source.Initiator;
loginEvent.Login = source.Initiator;
loginEvent.Active = source.Active;
if (source.Description != null && source.Description.Count > 0)
{

View File

@ -35,6 +35,7 @@ public class LoginEvent : MessageEvent, IMapFrom<EventMessage>
public void Mapping(Profile profile)
{
profile.CreateMap<MessageEvent, LoginEvent>();
profile.CreateMap<EventMessage, LoginEvent>()
.ConvertUsing<EventTypeConverter>();
}

View File

@ -1,282 +0,0 @@
// <auto-generated />
namespace ASC.Core.Common.Migrations.MySql.VoipDbContextMySql
{
[DbContext(typeof(MySqlVoipDbContext))]
[Migration("20211012145344_VoipDbContextMySql")]
partial class VoipDbContextMySql
{
protected override void BuildTargetModel(ModelBuilder modelBuilder)
{
#pragma warning disable 612, 618
modelBuilder
.HasAnnotation("Relational:MaxIdentifierLength", 64)
.HasAnnotation("ProductVersion", "5.0.10");
modelBuilder.Entity("ASC.Core.Common.EF.Model.CrmContact", b =>
{
b.Property<int>("Id")
.ValueGeneratedOnAdd()
.HasColumnType("int")
.HasColumnName("id");
b.Property<int>("CompanyId")
.HasColumnType("int")
.HasColumnName("company_id");
b.Property<string>("CompanyName")
.HasColumnType("varchar(255)")
.HasColumnName("company_name")
.UseCollation("utf8_general_ci")
.HasAnnotation("MySql:CharSet", "utf8");
b.Property<int>("ContactTypeId")
.HasColumnType("int")
.HasColumnName("contact_type_id");
b.Property<string>("CreateBy")
.IsRequired()
.HasColumnType("char(38)")
.HasColumnName("create_by")
.UseCollation("utf8_general_ci")
.HasAnnotation("MySql:CharSet", "utf8");
b.Property<DateTime>("CreateOn")
.HasColumnType("datetime")
.HasColumnName("create_on");
b.Property<string>("Currency")
.HasColumnType("varchar(3)")
.HasColumnName("currency")
.UseCollation("utf8_general_ci")
.HasAnnotation("MySql:CharSet", "utf8");
b.Property<string>("DisplayName")
.HasColumnType("varchar(255)")
.HasColumnName("display_name")
.UseCollation("utf8_general_ci")
.HasAnnotation("MySql:CharSet", "utf8");
b.Property<string>("FirstName")
.HasColumnType("varchar(255)")
.HasColumnName("first_name")
.UseCollation("utf8_general_ci")
.HasAnnotation("MySql:CharSet", "utf8");
b.Property<string>("Industry")
.HasColumnType("varchar(255)")
.HasColumnName("industry")
.UseCollation("utf8_general_ci")
.HasAnnotation("MySql:CharSet", "utf8");
b.Property<bool>("IsCompany")
.HasColumnType("tinyint(1)")
.HasColumnName("is_company");
b.Property<bool>("IsShared")
.HasColumnType("tinyint(1)")
.HasColumnName("is_shared");
b.Property<string>("LastModifedBy")
.IsRequired()
.HasColumnType("char(38)")
.HasColumnName("last_modifed_by")
.UseCollation("utf8_general_ci")
.HasAnnotation("MySql:CharSet", "utf8");
b.Property<DateTime>("LastModifedOn")
.HasColumnType("datetime")
.HasColumnName("last_modifed_on");
b.Property<string>("LastName")
.HasColumnType("varchar(255)")
.HasColumnName("last_name")
.UseCollation("utf8_general_ci")
.HasAnnotation("MySql:CharSet", "utf8");
b.Property<string>("Notes")
.HasColumnType("text")
.HasColumnName("notes")
.UseCollation("utf8_general_ci")
.HasAnnotation("MySql:CharSet", "utf8");
b.Property<int>("StatusId")
.HasColumnType("int")
.HasColumnName("status_id");
b.Property<int>("TenantId")
.HasColumnType("int")
.HasColumnName("tenant_id");
b.Property<string>("Title")
.HasColumnType("varchar(255)")
.HasColumnName("title")
.UseCollation("utf8_general_ci")
.HasAnnotation("MySql:CharSet", "utf8");
b.HasKey("Id");
b.HasIndex("CreateOn")
.HasDatabaseName("create_on");
b.HasIndex("LastModifedOn", "TenantId")
.HasDatabaseName("last_modifed_on");
b.HasIndex("TenantId", "CompanyId")
.HasDatabaseName("company_id");
b.HasIndex("TenantId", "DisplayName")
.HasDatabaseName("display_name");
b.ToTable("crm_contact");
});
modelBuilder.Entity("ASC.Core.Common.EF.Model.DbVoipCall", b =>
{
b.Property<string>("Id")
.HasColumnType("varchar(50)")
.HasColumnName("id")
.UseCollation("utf8_general_ci")
.HasAnnotation("MySql:CharSet", "utf8");
b.Property<string>("AnsweredBy")
.IsRequired()
.ValueGeneratedOnAdd()
.HasColumnType("varchar(50)")
.HasColumnName("answered_by")
.HasDefaultValueSql("'00000000-0000-0000-0000-000000000000'")
.UseCollation("utf8_general_ci")
.HasAnnotation("MySql:CharSet", "utf8");
b.Property<int>("ContactId")
.HasColumnType("int")
.HasColumnName("contact_id");
b.Property<int?>("CrmContactId")
.HasColumnType("int");
b.Property<DateTime>("DialDate")
.HasColumnType("datetime")
.HasColumnName("dial_date");
b.Property<int>("DialDuration")
.HasColumnType("int")
.HasColumnName("dial_duration");
b.Property<string>("NumberFrom")
.IsRequired()
.HasColumnType("varchar(50)")
.HasColumnName("number_from")
.UseCollation("utf8_general_ci")
.HasAnnotation("MySql:CharSet", "utf8");
b.Property<string>("NumberTo")
.IsRequired()
.HasColumnType("varchar(50)")
.HasColumnName("number_to")
.UseCollation("utf8_general_ci")
.HasAnnotation("MySql:CharSet", "utf8");
b.Property<string>("ParentCallId")
.IsRequired()
.HasColumnType("varchar(50)")
.HasColumnName("parent_call_id")
.UseCollation("utf8_general_ci")
.HasAnnotation("MySql:CharSet", "utf8");
b.Property<decimal>("Price")
.HasColumnType("decimal(10,4)")
.HasColumnName("price");
b.Property<int>("RecordDuration")
.HasColumnType("int")
.HasColumnName("record_duration");
b.Property<decimal>("RecordPrice")
.HasColumnType("decimal(10,4)")
.HasColumnName("record_price");
b.Property<string>("RecordSid")
.HasColumnType("varchar(50)")
.HasColumnName("record_sid")
.UseCollation("utf8_general_ci")
.HasAnnotation("MySql:CharSet", "utf8");
b.Property<string>("RecordUrl")
.HasColumnType("text")
.HasColumnName("record_url")
.UseCollation("utf8_general_ci")
.HasAnnotation("MySql:CharSet", "utf8");
b.Property<int>("Status")
.HasColumnType("int")
.HasColumnName("status");
b.Property<int>("TenantId")
.HasColumnType("int")
.HasColumnName("tenant_id");
b.HasKey("Id");
b.HasIndex("CrmContactId");
b.HasIndex("TenantId")
.HasDatabaseName("tenant_id");
b.HasIndex("ParentCallId", "TenantId")
.HasDatabaseName("parent_call_id");
b.ToTable("crm_voip_calls");
});
modelBuilder.Entity("ASC.Core.Common.EF.Model.VoipNumber", b =>
{
b.Property<string>("Id")
.HasColumnType("varchar(50)")
.HasColumnName("id")
.UseCollation("utf8_general_ci")
.HasAnnotation("MySql:CharSet", "utf8");
b.Property<string>("Alias")
.HasColumnType("varchar(255)")
.HasColumnName("alias")
.UseCollation("utf8_general_ci")
.HasAnnotation("MySql:CharSet", "utf8");
b.Property<string>("Number")
.IsRequired()
.HasColumnType("varchar(50)")
.HasColumnName("number")
.UseCollation("utf8_general_ci")
.HasAnnotation("MySql:CharSet", "utf8");
b.Property<string>("Settings")
.HasColumnType("text")
.HasColumnName("settings")
.UseCollation("utf8_general_ci")
.HasAnnotation("MySql:CharSet", "utf8");
b.Property<int>("TenantId")
.HasColumnType("int")
.HasColumnName("tenant_id");
b.HasKey("Id");
b.HasIndex("TenantId")
.HasDatabaseName("tenant_id");
b.ToTable("crm_voip_number");
});
modelBuilder.Entity("ASC.Core.Common.EF.Model.DbVoipCall", b =>
{
b.HasOne("ASC.Core.Common.EF.Model.CrmContact", "CrmContact")
.WithMany()
.HasForeignKey("CrmContactId");
b.Navigation("CrmContact");
});
#pragma warning restore 612, 618
}
}
}

View File

@ -1,189 +0,0 @@
// (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.Common.Migrations.MySql.VoipDbContextMySql;
public partial class VoipDbContextMySql : Migration
{
protected override void Up(MigrationBuilder migrationBuilder)
{
migrationBuilder.AlterDatabase()
.Annotation("MySql:CharSet", "utf8mb4");
migrationBuilder.CreateTable(
name: "crm_contact",
columns: table => new
{
id = table.Column<int>(type: "int", nullable: false)
.Annotation("MySql:ValueGenerationStrategy", MySqlValueGenerationStrategy.IdentityColumn),
tenant_id = table.Column<int>(type: "int", nullable: false),
is_company = table.Column<bool>(type: "tinyint(1)", nullable: false),
notes = table.Column<string>(type: "text", nullable: true, collation: "utf8_general_ci")
.Annotation("MySql:CharSet", "utf8"),
title = table.Column<string>(type: "varchar(255)", nullable: true, collation: "utf8_general_ci")
.Annotation("MySql:CharSet", "utf8"),
first_name = table.Column<string>(type: "varchar(255)", nullable: true, collation: "utf8_general_ci")
.Annotation("MySql:CharSet", "utf8"),
last_name = table.Column<string>(type: "varchar(255)", nullable: true, collation: "utf8_general_ci")
.Annotation("MySql:CharSet", "utf8"),
company_name = table.Column<string>(type: "varchar(255)", nullable: true, collation: "utf8_general_ci")
.Annotation("MySql:CharSet", "utf8"),
industry = table.Column<string>(type: "varchar(255)", nullable: true, collation: "utf8_general_ci")
.Annotation("MySql:CharSet", "utf8"),
status_id = table.Column<int>(type: "int", nullable: false),
company_id = table.Column<int>(type: "int", nullable: false),
contact_type_id = table.Column<int>(type: "int", nullable: false),
create_by = table.Column<string>(type: "char(38)", nullable: false, collation: "utf8_general_ci")
.Annotation("MySql:CharSet", "utf8"),
create_on = table.Column<DateTime>(type: "datetime", nullable: false),
last_modifed_by = table.Column<string>(type: "char(38)", nullable: false, collation: "utf8_general_ci")
.Annotation("MySql:CharSet", "utf8"),
last_modifed_on = table.Column<DateTime>(type: "datetime", nullable: false),
display_name = table.Column<string>(type: "varchar(255)", nullable: true, collation: "utf8_general_ci")
.Annotation("MySql:CharSet", "utf8"),
is_shared = table.Column<bool>(type: "tinyint(1)", nullable: false),
currency = table.Column<string>(type: "varchar(3)", nullable: true, collation: "utf8_general_ci")
.Annotation("MySql:CharSet", "utf8")
},
constraints: table =>
{
table.PrimaryKey("PK_crm_contact", x => x.id);
})
.Annotation("MySql:CharSet", "utf8mb4");
migrationBuilder.CreateTable(
name: "crm_voip_number",
columns: table => new
{
id = table.Column<string>(type: "varchar(50)", nullable: false, collation: "utf8_general_ci")
.Annotation("MySql:CharSet", "utf8"),
number = table.Column<string>(type: "varchar(50)", nullable: false, collation: "utf8_general_ci")
.Annotation("MySql:CharSet", "utf8"),
alias = table.Column<string>(type: "varchar(255)", nullable: true, collation: "utf8_general_ci")
.Annotation("MySql:CharSet", "utf8"),
settings = table.Column<string>(type: "text", nullable: true, collation: "utf8_general_ci")
.Annotation("MySql:CharSet", "utf8"),
tenant_id = table.Column<int>(type: "int", nullable: false)
},
constraints: table =>
{
table.PrimaryKey("PK_crm_voip_number", x => x.id);
})
.Annotation("MySql:CharSet", "utf8mb4");
migrationBuilder.CreateTable(
name: "crm_voip_calls",
columns: table => new
{
id = table.Column<string>(type: "varchar(50)", nullable: false, collation: "utf8_general_ci")
.Annotation("MySql:CharSet", "utf8"),
parent_call_id = table.Column<string>(type: "varchar(50)", nullable: false, collation: "utf8_general_ci")
.Annotation("MySql:CharSet", "utf8"),
number_from = table.Column<string>(type: "varchar(50)", nullable: false, collation: "utf8_general_ci")
.Annotation("MySql:CharSet", "utf8"),
number_to = table.Column<string>(type: "varchar(50)", nullable: false, collation: "utf8_general_ci")
.Annotation("MySql:CharSet", "utf8"),
status = table.Column<int>(type: "int", nullable: false),
answered_by = table.Column<string>(type: "varchar(50)", nullable: false, defaultValueSql: "'00000000-0000-0000-0000-000000000000'", collation: "utf8_general_ci")
.Annotation("MySql:CharSet", "utf8"),
dial_date = table.Column<DateTime>(type: "datetime", nullable: false),
dial_duration = table.Column<int>(type: "int", nullable: false),
record_sid = table.Column<string>(type: "varchar(50)", nullable: true, collation: "utf8_general_ci")
.Annotation("MySql:CharSet", "utf8"),
record_url = table.Column<string>(type: "text", nullable: true, collation: "utf8_general_ci")
.Annotation("MySql:CharSet", "utf8"),
record_duration = table.Column<int>(type: "int", nullable: false),
record_price = table.Column<decimal>(type: "decimal(10,4)", nullable: false),
contact_id = table.Column<int>(type: "int", nullable: false),
price = table.Column<decimal>(type: "decimal(10,4)", nullable: false),
tenant_id = table.Column<int>(type: "int", nullable: false),
CrmContactId = table.Column<int>(type: "int", nullable: true)
},
constraints: table =>
{
table.PrimaryKey("PK_crm_voip_calls", x => x.id);
table.ForeignKey(
name: "FK_crm_voip_calls_crm_contact_CrmContactId",
column: x => x.CrmContactId,
principalTable: "crm_contact",
principalColumn: "id",
onDelete: ReferentialAction.Restrict);
})
.Annotation("MySql:CharSet", "utf8mb4");
migrationBuilder.CreateIndex(
name: "company_id",
table: "crm_contact",
columns: new[] { "tenant_id", "company_id" });
migrationBuilder.CreateIndex(
name: "create_on",
table: "crm_contact",
column: "create_on");
migrationBuilder.CreateIndex(
name: "display_name",
table: "crm_contact",
columns: new[] { "tenant_id", "display_name" });
migrationBuilder.CreateIndex(
name: "last_modifed_on",
table: "crm_contact",
columns: new[] { "last_modifed_on", "tenant_id" });
migrationBuilder.CreateIndex(
name: "IX_crm_voip_calls_CrmContactId",
table: "crm_voip_calls",
column: "CrmContactId");
migrationBuilder.CreateIndex(
name: "parent_call_id",
table: "crm_voip_calls",
columns: new[] { "parent_call_id", "tenant_id" });
migrationBuilder.CreateIndex(
name: "tenant_id",
table: "crm_voip_calls",
column: "tenant_id");
migrationBuilder.CreateIndex(
name: "tenant_id",
table: "crm_voip_number",
column: "tenant_id");
}
protected override void Down(MigrationBuilder migrationBuilder)
{
migrationBuilder.DropTable(
name: "crm_voip_calls");
migrationBuilder.DropTable(
name: "crm_voip_number");
migrationBuilder.DropTable(
name: "crm_contact");
}
}

View File

@ -1,281 +0,0 @@
// <auto-generated />
namespace ASC.Core.Common.Migrations.MySql.VoipDbContextMySql
{
[DbContext(typeof(MySqlVoipDbContext))]
partial class MySqlVoipDbContextModelSnapshot : ModelSnapshot
{
protected override void BuildModel(ModelBuilder modelBuilder)
{
#pragma warning disable 612, 618
modelBuilder
.HasAnnotation("Relational:MaxIdentifierLength", 64)
.HasAnnotation("ProductVersion", "5.0.10");
modelBuilder.Entity("ASC.Core.Common.EF.Model.CrmContact", b =>
{
b.Property<int>("Id")
.ValueGeneratedOnAdd()
.HasColumnType("int")
.HasColumnName("id");
b.Property<int>("CompanyId")
.HasColumnType("int")
.HasColumnName("company_id");
b.Property<string>("CompanyName")
.HasColumnType("varchar(255)")
.HasColumnName("company_name")
.UseCollation("utf8_general_ci")
.HasAnnotation("MySql:CharSet", "utf8");
b.Property<int>("ContactTypeId")
.HasColumnType("int")
.HasColumnName("contact_type_id");
b.Property<string>("CreateBy")
.IsRequired()
.HasColumnType("char(38)")
.HasColumnName("create_by")
.UseCollation("utf8_general_ci")
.HasAnnotation("MySql:CharSet", "utf8");
b.Property<DateTime>("CreateOn")
.HasColumnType("datetime")
.HasColumnName("create_on");
b.Property<string>("Currency")
.HasColumnType("varchar(3)")
.HasColumnName("currency")
.UseCollation("utf8_general_ci")
.HasAnnotation("MySql:CharSet", "utf8");
b.Property<string>("DisplayName")
.HasColumnType("varchar(255)")
.HasColumnName("display_name")
.UseCollation("utf8_general_ci")
.HasAnnotation("MySql:CharSet", "utf8");
b.Property<string>("FirstName")
.HasColumnType("varchar(255)")
.HasColumnName("first_name")
.UseCollation("utf8_general_ci")
.HasAnnotation("MySql:CharSet", "utf8");
b.Property<string>("Industry")
.HasColumnType("varchar(255)")
.HasColumnName("industry")
.UseCollation("utf8_general_ci")
.HasAnnotation("MySql:CharSet", "utf8");
b.Property<bool>("IsCompany")
.HasColumnType("tinyint(1)")
.HasColumnName("is_company");
b.Property<bool>("IsShared")
.HasColumnType("tinyint(1)")
.HasColumnName("is_shared");
b.Property<string>("LastModifedBy")
.IsRequired()
.HasColumnType("char(38)")
.HasColumnName("last_modifed_by")
.UseCollation("utf8_general_ci")
.HasAnnotation("MySql:CharSet", "utf8");
b.Property<DateTime>("LastModifedOn")
.HasColumnType("datetime")
.HasColumnName("last_modifed_on");
b.Property<string>("LastName")
.HasColumnType("varchar(255)")
.HasColumnName("last_name")
.UseCollation("utf8_general_ci")
.HasAnnotation("MySql:CharSet", "utf8");
b.Property<string>("Notes")
.HasColumnType("text")
.HasColumnName("notes")
.UseCollation("utf8_general_ci")
.HasAnnotation("MySql:CharSet", "utf8");
b.Property<int>("StatusId")
.HasColumnType("int")
.HasColumnName("status_id");
b.Property<int>("TenantId")
.HasColumnType("int")
.HasColumnName("tenant_id");
b.Property<string>("Title")
.HasColumnType("varchar(255)")
.HasColumnName("title")
.UseCollation("utf8_general_ci")
.HasAnnotation("MySql:CharSet", "utf8");
b.HasKey("Id");
b.HasIndex("CreateOn")
.HasDatabaseName("create_on");
b.HasIndex("LastModifedOn", "TenantId")
.HasDatabaseName("last_modifed_on");
b.HasIndex("TenantId", "CompanyId")
.HasDatabaseName("company_id");
b.HasIndex("TenantId", "DisplayName")
.HasDatabaseName("display_name");
b.ToTable("crm_contact");
});
modelBuilder.Entity("ASC.Core.Common.EF.Model.DbVoipCall", b =>
{
b.Property<string>("Id")
.HasColumnType("varchar(50)")
.HasColumnName("id")
.UseCollation("utf8_general_ci")
.HasAnnotation("MySql:CharSet", "utf8");
b.Property<string>("AnsweredBy")
.IsRequired()
.ValueGeneratedOnAdd()
.HasColumnType("varchar(50)")
.HasColumnName("answered_by")
.HasDefaultValueSql("'00000000-0000-0000-0000-000000000000'")
.UseCollation("utf8_general_ci")
.HasAnnotation("MySql:CharSet", "utf8");
b.Property<int>("ContactId")
.HasColumnType("int")
.HasColumnName("contact_id");
b.Property<int?>("CrmContactId")
.HasColumnType("int");
b.Property<DateTime>("DialDate")
.HasColumnType("datetime")
.HasColumnName("dial_date");
b.Property<int>("DialDuration")
.HasColumnType("int")
.HasColumnName("dial_duration");
b.Property<string>("NumberFrom")
.IsRequired()
.HasColumnType("varchar(50)")
.HasColumnName("number_from")
.UseCollation("utf8_general_ci")
.HasAnnotation("MySql:CharSet", "utf8");
b.Property<string>("NumberTo")
.IsRequired()
.HasColumnType("varchar(50)")
.HasColumnName("number_to")
.UseCollation("utf8_general_ci")
.HasAnnotation("MySql:CharSet", "utf8");
b.Property<string>("ParentCallId")
.IsRequired()
.HasColumnType("varchar(50)")
.HasColumnName("parent_call_id")
.UseCollation("utf8_general_ci")
.HasAnnotation("MySql:CharSet", "utf8");
b.Property<decimal>("Price")
.HasColumnType("decimal(10,4)")
.HasColumnName("price");
b.Property<int>("RecordDuration")
.HasColumnType("int")
.HasColumnName("record_duration");
b.Property<decimal>("RecordPrice")
.HasColumnType("decimal(10,4)")
.HasColumnName("record_price");
b.Property<string>("RecordSid")
.HasColumnType("varchar(50)")
.HasColumnName("record_sid")
.UseCollation("utf8_general_ci")
.HasAnnotation("MySql:CharSet", "utf8");
b.Property<string>("RecordUrl")
.HasColumnType("text")
.HasColumnName("record_url")
.UseCollation("utf8_general_ci")
.HasAnnotation("MySql:CharSet", "utf8");
b.Property<int>("Status")
.HasColumnType("int")
.HasColumnName("status");
b.Property<int>("TenantId")
.HasColumnType("int")
.HasColumnName("tenant_id");
b.HasKey("Id");
b.HasIndex("CrmContactId");
b.HasIndex("TenantId")
.HasDatabaseName("tenant_id");
b.HasIndex("ParentCallId", "TenantId")
.HasDatabaseName("parent_call_id");
b.ToTable("crm_voip_calls");
});
modelBuilder.Entity("ASC.Core.Common.EF.Model.VoipNumber", b =>
{
b.Property<string>("Id")
.HasColumnType("varchar(50)")
.HasColumnName("id")
.UseCollation("utf8_general_ci")
.HasAnnotation("MySql:CharSet", "utf8");
b.Property<string>("Alias")
.HasColumnType("varchar(255)")
.HasColumnName("alias")
.UseCollation("utf8_general_ci")
.HasAnnotation("MySql:CharSet", "utf8");
b.Property<string>("Number")
.IsRequired()
.HasColumnType("varchar(50)")
.HasColumnName("number")
.UseCollation("utf8_general_ci")
.HasAnnotation("MySql:CharSet", "utf8");
b.Property<string>("Settings")
.HasColumnType("text")
.HasColumnName("settings")
.UseCollation("utf8_general_ci")
.HasAnnotation("MySql:CharSet", "utf8");
b.Property<int>("TenantId")
.HasColumnType("int")
.HasColumnName("tenant_id");
b.HasKey("Id");
b.HasIndex("TenantId")
.HasDatabaseName("tenant_id");
b.ToTable("crm_voip_number");
});
modelBuilder.Entity("ASC.Core.Common.EF.Model.DbVoipCall", b =>
{
b.HasOne("ASC.Core.Common.EF.Model.CrmContact", "CrmContact")
.WithMany()
.HasForeignKey("CrmContactId");
b.Navigation("CrmContact");
});
#pragma warning restore 612, 618
}
}
}

View File

@ -1,282 +0,0 @@
// <auto-generated />
namespace ASC.Core.Common.Migrations.PostgreSql.VoipDbContextPostgreSql
{
[DbContext(typeof(PostgreSqlVoipDbContext))]
[Migration("20211012145345_VoipDbContextPostgreSql")]
partial class VoipDbContextPostgreSql
{
protected override void BuildTargetModel(ModelBuilder modelBuilder)
{
#pragma warning disable 612, 618
modelBuilder
.HasAnnotation("Relational:MaxIdentifierLength", 64)
.HasAnnotation("ProductVersion", "5.0.10");
modelBuilder.Entity("ASC.Core.Common.EF.Model.CrmContact", b =>
{
b.Property<int>("Id")
.ValueGeneratedOnAdd()
.HasColumnType("int")
.HasColumnName("id");
b.Property<int>("CompanyId")
.HasColumnType("int")
.HasColumnName("company_id");
b.Property<string>("CompanyName")
.HasColumnType("varchar(255)")
.HasColumnName("company_name")
.UseCollation("utf8_general_ci")
.HasAnnotation("MySql:CharSet", "utf8");
b.Property<int>("ContactTypeId")
.HasColumnType("int")
.HasColumnName("contact_type_id");
b.Property<string>("CreateBy")
.IsRequired()
.HasColumnType("char(38)")
.HasColumnName("create_by")
.UseCollation("utf8_general_ci")
.HasAnnotation("MySql:CharSet", "utf8");
b.Property<DateTime>("CreateOn")
.HasColumnType("datetime")
.HasColumnName("create_on");
b.Property<string>("Currency")
.HasColumnType("varchar(3)")
.HasColumnName("currency")
.UseCollation("utf8_general_ci")
.HasAnnotation("MySql:CharSet", "utf8");
b.Property<string>("DisplayName")
.HasColumnType("varchar(255)")
.HasColumnName("display_name")
.UseCollation("utf8_general_ci")
.HasAnnotation("MySql:CharSet", "utf8");
b.Property<string>("FirstName")
.HasColumnType("varchar(255)")
.HasColumnName("first_name")
.UseCollation("utf8_general_ci")
.HasAnnotation("MySql:CharSet", "utf8");
b.Property<string>("Industry")
.HasColumnType("varchar(255)")
.HasColumnName("industry")
.UseCollation("utf8_general_ci")
.HasAnnotation("MySql:CharSet", "utf8");
b.Property<bool>("IsCompany")
.HasColumnType("tinyint(1)")
.HasColumnName("is_company");
b.Property<bool>("IsShared")
.HasColumnType("tinyint(1)")
.HasColumnName("is_shared");
b.Property<string>("LastModifedBy")
.IsRequired()
.HasColumnType("char(38)")
.HasColumnName("last_modifed_by")
.UseCollation("utf8_general_ci")
.HasAnnotation("MySql:CharSet", "utf8");
b.Property<DateTime>("LastModifedOn")
.HasColumnType("datetime")
.HasColumnName("last_modifed_on");
b.Property<string>("LastName")
.HasColumnType("varchar(255)")
.HasColumnName("last_name")
.UseCollation("utf8_general_ci")
.HasAnnotation("MySql:CharSet", "utf8");
b.Property<string>("Notes")
.HasColumnType("text")
.HasColumnName("notes")
.UseCollation("utf8_general_ci")
.HasAnnotation("MySql:CharSet", "utf8");
b.Property<int>("StatusId")
.HasColumnType("int")
.HasColumnName("status_id");
b.Property<int>("TenantId")
.HasColumnType("int")
.HasColumnName("tenant_id");
b.Property<string>("Title")
.HasColumnType("varchar(255)")
.HasColumnName("title")
.UseCollation("utf8_general_ci")
.HasAnnotation("MySql:CharSet", "utf8");
b.HasKey("Id");
b.HasIndex("CreateOn")
.HasDatabaseName("create_on");
b.HasIndex("LastModifedOn", "TenantId")
.HasDatabaseName("last_modifed_on");
b.HasIndex("TenantId", "CompanyId")
.HasDatabaseName("company_id");
b.HasIndex("TenantId", "DisplayName")
.HasDatabaseName("display_name");
b.ToTable("crm_contact");
});
modelBuilder.Entity("ASC.Core.Common.EF.Model.DbVoipCall", b =>
{
b.Property<string>("Id")
.HasColumnType("varchar(50)")
.HasColumnName("id")
.UseCollation("utf8_general_ci")
.HasAnnotation("MySql:CharSet", "utf8");
b.Property<string>("AnsweredBy")
.IsRequired()
.ValueGeneratedOnAdd()
.HasColumnType("varchar(50)")
.HasColumnName("answered_by")
.HasDefaultValueSql("'00000000-0000-0000-0000-000000000000'")
.UseCollation("utf8_general_ci")
.HasAnnotation("MySql:CharSet", "utf8");
b.Property<int>("ContactId")
.HasColumnType("int")
.HasColumnName("contact_id");
b.Property<int?>("CrmContactId")
.HasColumnType("int");
b.Property<DateTime>("DialDate")
.HasColumnType("datetime")
.HasColumnName("dial_date");
b.Property<int>("DialDuration")
.HasColumnType("int")
.HasColumnName("dial_duration");
b.Property<string>("NumberFrom")
.IsRequired()
.HasColumnType("varchar(50)")
.HasColumnName("number_from")
.UseCollation("utf8_general_ci")
.HasAnnotation("MySql:CharSet", "utf8");
b.Property<string>("NumberTo")
.IsRequired()
.HasColumnType("varchar(50)")
.HasColumnName("number_to")
.UseCollation("utf8_general_ci")
.HasAnnotation("MySql:CharSet", "utf8");
b.Property<string>("ParentCallId")
.IsRequired()
.HasColumnType("varchar(50)")
.HasColumnName("parent_call_id")
.UseCollation("utf8_general_ci")
.HasAnnotation("MySql:CharSet", "utf8");
b.Property<decimal>("Price")
.HasColumnType("decimal(10,4)")
.HasColumnName("price");
b.Property<int>("RecordDuration")
.HasColumnType("int")
.HasColumnName("record_duration");
b.Property<decimal>("RecordPrice")
.HasColumnType("decimal(10,4)")
.HasColumnName("record_price");
b.Property<string>("RecordSid")
.HasColumnType("varchar(50)")
.HasColumnName("record_sid")
.UseCollation("utf8_general_ci")
.HasAnnotation("MySql:CharSet", "utf8");
b.Property<string>("RecordUrl")
.HasColumnType("text")
.HasColumnName("record_url")
.UseCollation("utf8_general_ci")
.HasAnnotation("MySql:CharSet", "utf8");
b.Property<int>("Status")
.HasColumnType("int")
.HasColumnName("status");
b.Property<int>("TenantId")
.HasColumnType("int")
.HasColumnName("tenant_id");
b.HasKey("Id");
b.HasIndex("CrmContactId");
b.HasIndex("TenantId")
.HasDatabaseName("tenant_id");
b.HasIndex("ParentCallId", "TenantId")
.HasDatabaseName("parent_call_id");
b.ToTable("crm_voip_calls");
});
modelBuilder.Entity("ASC.Core.Common.EF.Model.VoipNumber", b =>
{
b.Property<string>("Id")
.HasColumnType("varchar(50)")
.HasColumnName("id")
.UseCollation("utf8_general_ci")
.HasAnnotation("MySql:CharSet", "utf8");
b.Property<string>("Alias")
.HasColumnType("varchar(255)")
.HasColumnName("alias")
.UseCollation("utf8_general_ci")
.HasAnnotation("MySql:CharSet", "utf8");
b.Property<string>("Number")
.IsRequired()
.HasColumnType("varchar(50)")
.HasColumnName("number")
.UseCollation("utf8_general_ci")
.HasAnnotation("MySql:CharSet", "utf8");
b.Property<string>("Settings")
.HasColumnType("text")
.HasColumnName("settings")
.UseCollation("utf8_general_ci")
.HasAnnotation("MySql:CharSet", "utf8");
b.Property<int>("TenantId")
.HasColumnType("int")
.HasColumnName("tenant_id");
b.HasKey("Id");
b.HasIndex("TenantId")
.HasDatabaseName("tenant_id");
b.ToTable("crm_voip_number");
});
modelBuilder.Entity("ASC.Core.Common.EF.Model.DbVoipCall", b =>
{
b.HasOne("ASC.Core.Common.EF.Model.CrmContact", "CrmContact")
.WithMany()
.HasForeignKey("CrmContactId");
b.Navigation("CrmContact");
});
#pragma warning restore 612, 618
}
}
}

View File

@ -1,189 +0,0 @@
// (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.Common.Migrations.PostgreSql.VoipDbContextPostgreSql;
public partial class VoipDbContextPostgreSql : Migration
{
protected override void Up(MigrationBuilder migrationBuilder)
{
migrationBuilder.AlterDatabase()
.Annotation("MySql:CharSet", "utf8mb4");
migrationBuilder.CreateTable(
name: "crm_contact",
columns: table => new
{
id = table.Column<int>(type: "int", nullable: false)
.Annotation("MySql:ValueGenerationStrategy", MySqlValueGenerationStrategy.IdentityColumn),
tenant_id = table.Column<int>(type: "int", nullable: false),
is_company = table.Column<bool>(type: "tinyint(1)", nullable: false),
notes = table.Column<string>(type: "text", nullable: true, collation: "utf8_general_ci")
.Annotation("MySql:CharSet", "utf8"),
title = table.Column<string>(type: "varchar(255)", nullable: true, collation: "utf8_general_ci")
.Annotation("MySql:CharSet", "utf8"),
first_name = table.Column<string>(type: "varchar(255)", nullable: true, collation: "utf8_general_ci")
.Annotation("MySql:CharSet", "utf8"),
last_name = table.Column<string>(type: "varchar(255)", nullable: true, collation: "utf8_general_ci")
.Annotation("MySql:CharSet", "utf8"),
company_name = table.Column<string>(type: "varchar(255)", nullable: true, collation: "utf8_general_ci")
.Annotation("MySql:CharSet", "utf8"),
industry = table.Column<string>(type: "varchar(255)", nullable: true, collation: "utf8_general_ci")
.Annotation("MySql:CharSet", "utf8"),
status_id = table.Column<int>(type: "int", nullable: false),
company_id = table.Column<int>(type: "int", nullable: false),
contact_type_id = table.Column<int>(type: "int", nullable: false),
create_by = table.Column<string>(type: "char(38)", nullable: false, collation: "utf8_general_ci")
.Annotation("MySql:CharSet", "utf8"),
create_on = table.Column<DateTime>(type: "datetime", nullable: false),
last_modifed_by = table.Column<string>(type: "char(38)", nullable: false, collation: "utf8_general_ci")
.Annotation("MySql:CharSet", "utf8"),
last_modifed_on = table.Column<DateTime>(type: "datetime", nullable: false),
display_name = table.Column<string>(type: "varchar(255)", nullable: true, collation: "utf8_general_ci")
.Annotation("MySql:CharSet", "utf8"),
is_shared = table.Column<bool>(type: "tinyint(1)", nullable: false),
currency = table.Column<string>(type: "varchar(3)", nullable: true, collation: "utf8_general_ci")
.Annotation("MySql:CharSet", "utf8")
},
constraints: table =>
{
table.PrimaryKey("PK_crm_contact", x => x.id);
})
.Annotation("MySql:CharSet", "utf8mb4");
migrationBuilder.CreateTable(
name: "crm_voip_number",
columns: table => new
{
id = table.Column<string>(type: "varchar(50)", nullable: false, collation: "utf8_general_ci")
.Annotation("MySql:CharSet", "utf8"),
number = table.Column<string>(type: "varchar(50)", nullable: false, collation: "utf8_general_ci")
.Annotation("MySql:CharSet", "utf8"),
alias = table.Column<string>(type: "varchar(255)", nullable: true, collation: "utf8_general_ci")
.Annotation("MySql:CharSet", "utf8"),
settings = table.Column<string>(type: "text", nullable: true, collation: "utf8_general_ci")
.Annotation("MySql:CharSet", "utf8"),
tenant_id = table.Column<int>(type: "int", nullable: false)
},
constraints: table =>
{
table.PrimaryKey("PK_crm_voip_number", x => x.id);
})
.Annotation("MySql:CharSet", "utf8mb4");
migrationBuilder.CreateTable(
name: "crm_voip_calls",
columns: table => new
{
id = table.Column<string>(type: "varchar(50)", nullable: false, collation: "utf8_general_ci")
.Annotation("MySql:CharSet", "utf8"),
parent_call_id = table.Column<string>(type: "varchar(50)", nullable: false, collation: "utf8_general_ci")
.Annotation("MySql:CharSet", "utf8"),
number_from = table.Column<string>(type: "varchar(50)", nullable: false, collation: "utf8_general_ci")
.Annotation("MySql:CharSet", "utf8"),
number_to = table.Column<string>(type: "varchar(50)", nullable: false, collation: "utf8_general_ci")
.Annotation("MySql:CharSet", "utf8"),
status = table.Column<int>(type: "int", nullable: false),
answered_by = table.Column<string>(type: "varchar(50)", nullable: false, defaultValueSql: "'00000000-0000-0000-0000-000000000000'", collation: "utf8_general_ci")
.Annotation("MySql:CharSet", "utf8"),
dial_date = table.Column<DateTime>(type: "datetime", nullable: false),
dial_duration = table.Column<int>(type: "int", nullable: false),
record_sid = table.Column<string>(type: "varchar(50)", nullable: true, collation: "utf8_general_ci")
.Annotation("MySql:CharSet", "utf8"),
record_url = table.Column<string>(type: "text", nullable: true, collation: "utf8_general_ci")
.Annotation("MySql:CharSet", "utf8"),
record_duration = table.Column<int>(type: "int", nullable: false),
record_price = table.Column<decimal>(type: "decimal(10,4)", nullable: false),
contact_id = table.Column<int>(type: "int", nullable: false),
price = table.Column<decimal>(type: "decimal(10,4)", nullable: false),
tenant_id = table.Column<int>(type: "int", nullable: false),
CrmContactId = table.Column<int>(type: "int", nullable: true)
},
constraints: table =>
{
table.PrimaryKey("PK_crm_voip_calls", x => x.id);
table.ForeignKey(
name: "FK_crm_voip_calls_crm_contact_CrmContactId",
column: x => x.CrmContactId,
principalTable: "crm_contact",
principalColumn: "id",
onDelete: ReferentialAction.Restrict);
})
.Annotation("MySql:CharSet", "utf8mb4");
migrationBuilder.CreateIndex(
name: "company_id",
table: "crm_contact",
columns: new[] { "tenant_id", "company_id" });
migrationBuilder.CreateIndex(
name: "create_on",
table: "crm_contact",
column: "create_on");
migrationBuilder.CreateIndex(
name: "display_name",
table: "crm_contact",
columns: new[] { "tenant_id", "display_name" });
migrationBuilder.CreateIndex(
name: "last_modifed_on",
table: "crm_contact",
columns: new[] { "last_modifed_on", "tenant_id" });
migrationBuilder.CreateIndex(
name: "IX_crm_voip_calls_CrmContactId",
table: "crm_voip_calls",
column: "CrmContactId");
migrationBuilder.CreateIndex(
name: "parent_call_id",
table: "crm_voip_calls",
columns: new[] { "parent_call_id", "tenant_id" });
migrationBuilder.CreateIndex(
name: "tenant_id",
table: "crm_voip_calls",
column: "tenant_id");
migrationBuilder.CreateIndex(
name: "tenant_id",
table: "crm_voip_number",
column: "tenant_id");
}
protected override void Down(MigrationBuilder migrationBuilder)
{
migrationBuilder.DropTable(
name: "crm_voip_calls");
migrationBuilder.DropTable(
name: "crm_voip_number");
migrationBuilder.DropTable(
name: "crm_contact");
}
}

View File

@ -1,281 +0,0 @@
// <auto-generated />
namespace ASC.Core.Common.Migrations.PostgreSql.VoipDbContextPostgreSql
{
[DbContext(typeof(PostgreSqlVoipDbContext))]
partial class PostgreSqlVoipDbContextModelSnapshot : ModelSnapshot
{
protected override void BuildModel(ModelBuilder modelBuilder)
{
#pragma warning disable 612, 618
modelBuilder
.HasAnnotation("Relational:MaxIdentifierLength", 64)
.HasAnnotation("ProductVersion", "5.0.10");
modelBuilder.Entity("ASC.Core.Common.EF.Model.CrmContact", b =>
{
b.Property<int>("Id")
.ValueGeneratedOnAdd()
.HasColumnType("int")
.HasColumnName("id");
b.Property<int>("CompanyId")
.HasColumnType("int")
.HasColumnName("company_id");
b.Property<string>("CompanyName")
.HasColumnType("varchar(255)")
.HasColumnName("company_name")
.UseCollation("utf8_general_ci")
.HasAnnotation("MySql:CharSet", "utf8");
b.Property<int>("ContactTypeId")
.HasColumnType("int")
.HasColumnName("contact_type_id");
b.Property<string>("CreateBy")
.IsRequired()
.HasColumnType("char(38)")
.HasColumnName("create_by")
.UseCollation("utf8_general_ci")
.HasAnnotation("MySql:CharSet", "utf8");
b.Property<DateTime>("CreateOn")
.HasColumnType("datetime")
.HasColumnName("create_on");
b.Property<string>("Currency")
.HasColumnType("varchar(3)")
.HasColumnName("currency")
.UseCollation("utf8_general_ci")
.HasAnnotation("MySql:CharSet", "utf8");
b.Property<string>("DisplayName")
.HasColumnType("varchar(255)")
.HasColumnName("display_name")
.UseCollation("utf8_general_ci")
.HasAnnotation("MySql:CharSet", "utf8");
b.Property<string>("FirstName")
.HasColumnType("varchar(255)")
.HasColumnName("first_name")
.UseCollation("utf8_general_ci")
.HasAnnotation("MySql:CharSet", "utf8");
b.Property<string>("Industry")
.HasColumnType("varchar(255)")
.HasColumnName("industry")
.UseCollation("utf8_general_ci")
.HasAnnotation("MySql:CharSet", "utf8");
b.Property<bool>("IsCompany")
.HasColumnType("tinyint(1)")
.HasColumnName("is_company");
b.Property<bool>("IsShared")
.HasColumnType("tinyint(1)")
.HasColumnName("is_shared");
b.Property<string>("LastModifedBy")
.IsRequired()
.HasColumnType("char(38)")
.HasColumnName("last_modifed_by")
.UseCollation("utf8_general_ci")
.HasAnnotation("MySql:CharSet", "utf8");
b.Property<DateTime>("LastModifedOn")
.HasColumnType("datetime")
.HasColumnName("last_modifed_on");
b.Property<string>("LastName")
.HasColumnType("varchar(255)")
.HasColumnName("last_name")
.UseCollation("utf8_general_ci")
.HasAnnotation("MySql:CharSet", "utf8");
b.Property<string>("Notes")
.HasColumnType("text")
.HasColumnName("notes")
.UseCollation("utf8_general_ci")
.HasAnnotation("MySql:CharSet", "utf8");
b.Property<int>("StatusId")
.HasColumnType("int")
.HasColumnName("status_id");
b.Property<int>("TenantId")
.HasColumnType("int")
.HasColumnName("tenant_id");
b.Property<string>("Title")
.HasColumnType("varchar(255)")
.HasColumnName("title")
.UseCollation("utf8_general_ci")
.HasAnnotation("MySql:CharSet", "utf8");
b.HasKey("Id");
b.HasIndex("CreateOn")
.HasDatabaseName("create_on");
b.HasIndex("LastModifedOn", "TenantId")
.HasDatabaseName("last_modifed_on");
b.HasIndex("TenantId", "CompanyId")
.HasDatabaseName("company_id");
b.HasIndex("TenantId", "DisplayName")
.HasDatabaseName("display_name");
b.ToTable("crm_contact");
});
modelBuilder.Entity("ASC.Core.Common.EF.Model.DbVoipCall", b =>
{
b.Property<string>("Id")
.HasColumnType("varchar(50)")
.HasColumnName("id")
.UseCollation("utf8_general_ci")
.HasAnnotation("MySql:CharSet", "utf8");
b.Property<string>("AnsweredBy")
.IsRequired()
.ValueGeneratedOnAdd()
.HasColumnType("varchar(50)")
.HasColumnName("answered_by")
.HasDefaultValueSql("'00000000-0000-0000-0000-000000000000'")
.UseCollation("utf8_general_ci")
.HasAnnotation("MySql:CharSet", "utf8");
b.Property<int>("ContactId")
.HasColumnType("int")
.HasColumnName("contact_id");
b.Property<int?>("CrmContactId")
.HasColumnType("int");
b.Property<DateTime>("DialDate")
.HasColumnType("datetime")
.HasColumnName("dial_date");
b.Property<int>("DialDuration")
.HasColumnType("int")
.HasColumnName("dial_duration");
b.Property<string>("NumberFrom")
.IsRequired()
.HasColumnType("varchar(50)")
.HasColumnName("number_from")
.UseCollation("utf8_general_ci")
.HasAnnotation("MySql:CharSet", "utf8");
b.Property<string>("NumberTo")
.IsRequired()
.HasColumnType("varchar(50)")
.HasColumnName("number_to")
.UseCollation("utf8_general_ci")
.HasAnnotation("MySql:CharSet", "utf8");
b.Property<string>("ParentCallId")
.IsRequired()
.HasColumnType("varchar(50)")
.HasColumnName("parent_call_id")
.UseCollation("utf8_general_ci")
.HasAnnotation("MySql:CharSet", "utf8");
b.Property<decimal>("Price")
.HasColumnType("decimal(10,4)")
.HasColumnName("price");
b.Property<int>("RecordDuration")
.HasColumnType("int")
.HasColumnName("record_duration");
b.Property<decimal>("RecordPrice")
.HasColumnType("decimal(10,4)")
.HasColumnName("record_price");
b.Property<string>("RecordSid")
.HasColumnType("varchar(50)")
.HasColumnName("record_sid")
.UseCollation("utf8_general_ci")
.HasAnnotation("MySql:CharSet", "utf8");
b.Property<string>("RecordUrl")
.HasColumnType("text")
.HasColumnName("record_url")
.UseCollation("utf8_general_ci")
.HasAnnotation("MySql:CharSet", "utf8");
b.Property<int>("Status")
.HasColumnType("int")
.HasColumnName("status");
b.Property<int>("TenantId")
.HasColumnType("int")
.HasColumnName("tenant_id");
b.HasKey("Id");
b.HasIndex("CrmContactId");
b.HasIndex("TenantId")
.HasDatabaseName("tenant_id");
b.HasIndex("ParentCallId", "TenantId")
.HasDatabaseName("parent_call_id");
b.ToTable("crm_voip_calls");
});
modelBuilder.Entity("ASC.Core.Common.EF.Model.VoipNumber", b =>
{
b.Property<string>("Id")
.HasColumnType("varchar(50)")
.HasColumnName("id")
.UseCollation("utf8_general_ci")
.HasAnnotation("MySql:CharSet", "utf8");
b.Property<string>("Alias")
.HasColumnType("varchar(255)")
.HasColumnName("alias")
.UseCollation("utf8_general_ci")
.HasAnnotation("MySql:CharSet", "utf8");
b.Property<string>("Number")
.IsRequired()
.HasColumnType("varchar(50)")
.HasColumnName("number")
.UseCollation("utf8_general_ci")
.HasAnnotation("MySql:CharSet", "utf8");
b.Property<string>("Settings")
.HasColumnType("text")
.HasColumnName("settings")
.UseCollation("utf8_general_ci")
.HasAnnotation("MySql:CharSet", "utf8");
b.Property<int>("TenantId")
.HasColumnType("int")
.HasColumnName("tenant_id");
b.HasKey("Id");
b.HasIndex("TenantId")
.HasDatabaseName("tenant_id");
b.ToTable("crm_voip_number");
});
modelBuilder.Entity("ASC.Core.Common.EF.Model.DbVoipCall", b =>
{
b.HasOne("ASC.Core.Common.EF.Model.CrmContact", "CrmContact")
.WithMany()
.HasForeignKey("CrmContactId");
b.Navigation("CrmContact");
});
#pragma warning restore 612, 618
}
}
}

View File

@ -321,17 +321,17 @@ public class SignalrServiceClient
}
}
public void UpdateFile<T>(T fileId, string room, string data)
{
try
{
MakeRequest("update-file", new { room, fileId, data });
}
catch (Exception error)
{
ProcessError(error);
}
public void UpdateFile<T>(T fileId, string room, string data)
{
try
{
MakeRequest("update-file", new { room, fileId, data });
}
catch (Exception error)
{
ProcessError(error);
}
}
public void DeleteFile<T>(T fileId, string room)
{

View File

@ -149,7 +149,8 @@ public class Tenant : IMapFrom<DbTenant>
public void Mapping(Profile profile)
{
profile.CreateMap<DbTenant, Tenant>();
profile.CreateMap<DbTenant, Tenant>()
.ForMember(r => r.TrustedDomainsType, opt => opt.MapFrom(src => src.TrustedDomainsEnabled));
profile.CreateMap<TenantUserSecurity, Tenant>()
.IncludeMembers(src => src.DbTenant);

View File

@ -35,6 +35,8 @@ public class TenantAuditSettings : ISettings<TenantAuditSettings>
public int AuditTrailLifeTime { get; set; }
public static readonly Guid Guid = new Guid("{8337D0FB-AD67-4552-8297-802312E7F503}");
[JsonIgnore]
public Guid ID => Guid;
public TenantAuditSettings GetDefault()

View File

@ -31,8 +31,9 @@ namespace ASC.Core.Tenants;
public class TenantControlPanelSettings : ISettings<TenantControlPanelSettings>
{
[DataMember(Name = "LimitedAccess")]
public bool LimitedAccess { get; set; }
public bool LimitedAccess { get; set; }
[JsonIgnore]
public Guid ID => new Guid("{880585C4-52CD-4AE2-8DA4-3B8E2772753B}");
public TenantControlPanelSettings GetDefault()

View File

@ -49,6 +49,7 @@ public class TenantCookieSettings : ISettings<TenantCookieSettings>
return new TenantCookieSettings();
}
[JsonIgnore]
public Guid ID => new Guid("{16FB8E67-E96D-4B22-B217-C80F25C5DE1B}");
}

View File

@ -29,7 +29,7 @@ namespace ASC.Web.Core.Users;
[Serializable]
public class DarkThemeSettings : ISettings<DarkThemeSettings>
{
[System.Text.Json.Serialization.JsonIgnore]
[JsonIgnore]
public Guid ID
{
get { return new Guid("{38362061-066D-4C57-A23E-8953CF34EFC3}"); }

View File

@ -29,6 +29,7 @@ namespace ASC.Web.Core.Users;
[Serializable]
public class DisplayUserSettings : ISettings<DisplayUserSettings>
{
[JsonIgnore]
public Guid ID => new Guid("2EF59652-E1A7-4814-BF71-FEB990149428");
public bool IsDisableGettingStarted { get; set; }

View File

@ -31,6 +31,7 @@ public class PersonalQuotaSettings : ISettings<PersonalQuotaSettings>
{
public long MaxSpace { get; set; }
[JsonIgnore]
public Guid ID => new Guid("{C634A747-C39B-4517-8698-B3B39BF2BD8E}");
public PersonalQuotaSettings GetDefault()

View File

@ -40,6 +40,7 @@ public class MailWhiteLabelSettings : ISettings<MailWhiteLabelSettings>
public string DemoUrl { get; set; }
public string SiteUrl { get; set; }
[JsonIgnore]
public Guid ID => new Guid("{C3602052-5BA2-452A-BD2A-ADD0FAF8EB88}");
public MailWhiteLabelSettings(IConfiguration configuration)

View File

@ -97,6 +97,7 @@ public abstract class BaseStorageSettings<T> : ISettings<BaseStorageSettings<T>>
[Serializable]
public class StorageSettings : BaseStorageSettings<StorageSettings>, ISettings<StorageSettings>
{
[JsonIgnore]
public override Guid ID => new Guid("F13EAF2D-FA53-44F1-A6D6-A5AEDA46FA2B");
StorageSettings ISettings<StorageSettings>.GetDefault()
@ -109,6 +110,7 @@ public class StorageSettings : BaseStorageSettings<StorageSettings>, ISettings<S
[Serializable]
public class CdnStorageSettings : BaseStorageSettings<CdnStorageSettings>, ISettings<CdnStorageSettings>
{
[JsonIgnore]
public override Guid ID => new Guid("0E9AE034-F398-42FE-B5EE-F86D954E9FB2");
public override Func<DataStoreConsumer, DataStoreConsumer> Switch => d => d.Cdn;

View File

@ -59,7 +59,8 @@ public class IPRestrictionsRepository
using var tx = TenantDbContext.Database.BeginTransaction();
var restrictions = TenantDbContext.TenantIpRestrictions.Where(r => r.Tenant == tenant).ToList();
TenantDbContext.TenantIpRestrictions.RemoveRange(restrictions);
TenantDbContext.TenantIpRestrictions.RemoveRange(restrictions);
TenantDbContext.SaveChanges();
var ipsList = ips.Select(r => new TenantIpRestrictions
{
@ -67,7 +68,8 @@ public class IPRestrictionsRepository
Ip = r
});
TenantDbContext.TenantIpRestrictions.AddRange(ipsList);
TenantDbContext.TenantIpRestrictions.AddRange(ipsList);
TenantDbContext.SaveChanges();
tx.Commit();
});

View File

@ -24,6 +24,8 @@
// content are licensed under the terms of the Creative Commons Attribution-ShareAlike 4.0
// International. See the License terms at http://creativecommons.org/licenses/by-sa/4.0/legalcode
using System.Text.Json.Serialization;
namespace ASC.IPSecurity;
[Serializable]
@ -31,6 +33,7 @@ public class IPRestrictionsSettings : ISettings<IPRestrictionsSettings>
{
public bool Enable { get; set; }
[JsonIgnore]
public Guid ID => new Guid("{2EDDDF64-F792-4498-A638-2E3E6EBB13C9}");
public IPRestrictionsSettings GetDefault()

View File

@ -1,40 +0,0 @@
<Project Sdk="Microsoft.NET.Sdk">
<PropertyGroup>
<TargetFramework>net6.0</TargetFramework>
<ApplicationIcon />
<OutputType>Library</OutputType>
<StartupObject />
<ImplicitUsings>enable</ImplicitUsings>
</PropertyGroup>
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Release|AnyCPU'">
<DebugType>none</DebugType>
<DebugSymbols>false</DebugSymbols>
</PropertyGroup>
<ItemGroup>
<Compile Remove="Properties\**" />
<Compile Remove="VoxImplant\**" />
<EmbeddedResource Remove="Properties\**" />
<EmbeddedResource Remove="VoxImplant\**" />
<None Remove="Properties\**" />
<None Remove="VoxImplant\**" />
</ItemGroup>
<ItemGroup>
<PackageReference Include="Grpc.Tools" Version="2.45.0">
<PrivateAssets>all</PrivateAssets>
<IncludeAssets>runtime; build; native; contentfiles; analyzers; buildtransitive</IncludeAssets>
</PackageReference>
<PackageReference Include="Twilio" Version="5.6.0" />
</ItemGroup>
<ItemGroup>
<ProjectReference Include="..\ASC.Core.Common\ASC.Core.Common.csproj" />
</ItemGroup>
<ItemGroup>
<Protobuf Include="protos\cached_voip_item.proto" />
</ItemGroup>
</Project>

View File

@ -1,64 +0,0 @@
// (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.VoipService.Dao;
public class AbstractDao
{
private readonly string _dbid = "default";
private readonly Lazy<VoipDbContext> _lazyVoipDbContext;
protected VoipDbContext VoipDbContext { get => _lazyVoipDbContext.Value; }
protected int TenantID
{
get;
private set;
}
protected AbstractDao(DbContextManager<VoipDbContext> dbOptions, TenantManager tenantManager)
{
_lazyVoipDbContext = new Lazy<VoipDbContext>(() => dbOptions.Get(_dbid));
TenantID = tenantManager.GetCurrentTenant().Id;
}
protected string GetTenantColumnName(string table)
{
const string tenant = "tenant_id";
if (!table.Contains(' '))
{
return tenant;
}
return table.Substring(table.IndexOf(" ", StringComparison.Ordinal)).Trim() + "." + tenant;
}
protected static Guid ToGuid(object guid)
{
var str = guid as string;
return !string.IsNullOrEmpty(str) ? new Guid(str) : Guid.Empty;
}
}

View File

@ -1,113 +0,0 @@
// (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.VoipService.Dao;
public class VoipCallFilter
{
public string Type { get; set; }
public DateTime? FromDate { get; set; }
public DateTime? ToDate { get; set; }
public Guid? Agent { get; set; }
public int? Client { get; set; }
public int? ContactID { get; set; }
public string Id { get; set; }
public string ParentId { get; set; }
public string SortBy { get; set; }
public bool SortOrder { get; set; }
public string SearchText { get; set; }
public long Offset { get; set; }
public long Max { get; set; }
public int? TypeStatus
{
get
{
if (string.IsNullOrWhiteSpace(Type))
{
return null;
}
if (TypeStatuses.TryGetValue(Type, out var status))
{
return status;
}
return null;
}
}
public string SortByColumn
{
get
{
if (string.IsNullOrWhiteSpace(SortBy))
{
return null;
}
return SortColumns.ContainsKey(SortBy) ? SortColumns[SortBy] : null;
}
}
private static Dictionary<string, int> TypeStatuses
{
get
{
return new Dictionary<string, int>
{
{
"answered", (int)VoipCallStatus.Answered
},
{
"missed", (int)VoipCallStatus.Missed
},
{
"outgoing", (int)VoipCallStatus.Outcoming
}
};
}
}
private static Dictionary<string, string> SortColumns
{
get
{
return new Dictionary<string, string>
{
{
"date", "dial_date"
},
{
"duration", "dial_duration"
},
{
"price", "price"
},
};
}
}
}

View File

@ -1,326 +0,0 @@
// (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.VoipService.Dao;
[Scope(Additional = typeof(EventTypeConverterExtension))]
public class VoipDao : AbstractDao
{
private readonly AuthContext _authContext;
private readonly TenantUtil _tenantUtil;
private readonly SecurityContext _securityContext;
private readonly BaseCommonLinkUtility _baseCommonLinkUtility;
private readonly ConsumerFactory _consumerFactory;
private readonly IMapper _mapper;
public VoipDao(
TenantManager tenantManager,
DbContextManager<VoipDbContext> dbOptions,
AuthContext authContext,
TenantUtil tenantUtil,
SecurityContext securityContext,
BaseCommonLinkUtility baseCommonLinkUtility,
ConsumerFactory consumerFactory,
IMapper mapper)
: base(dbOptions, tenantManager)
{
_authContext = authContext;
_tenantUtil = tenantUtil;
_securityContext = securityContext;
_baseCommonLinkUtility = baseCommonLinkUtility;
_consumerFactory = consumerFactory;
_mapper = mapper;
}
public virtual VoipPhone SaveOrUpdateNumber(VoipPhone phone)
{
if (!string.IsNullOrEmpty(phone.Number))
{
phone.Number = phone.Number.TrimStart('+');
}
var voipNumber = new VoipNumber
{
Id = phone.Id,
Number = phone.Number,
Alias = phone.Alias,
Settings = phone.Settings.ToString(),
TenantId = TenantID
};
VoipDbContext.VoipNumbers.Add(voipNumber);
VoipDbContext.SaveChanges();
return phone;
}
public virtual void DeleteNumber(string phoneId = "")
{
var number = VoipDbContext.VoipNumbers.Where(r => r.Id == phoneId && r.TenantId == TenantID).FirstOrDefault();
VoipDbContext.VoipNumbers.Remove(number);
VoipDbContext.SaveChanges();
}
public virtual IEnumerable<VoipPhone> GetAllNumbers()
{
return VoipDbContext.VoipNumbers
.Where(r => r.TenantId == TenantID)
.ToList()
.ConvertAll(ToPhone);
}
public virtual IEnumerable<VoipPhone> GetNumbers(params string[] ids)
{
var numbers = VoipDbContext.VoipNumbers.Where(r => r.TenantId == TenantID);
if (ids.Length > 0)
{
numbers = numbers.Where(r => ids.Any(a => a == r.Number || a == r.Id));
}
return numbers.ToList().ConvertAll(ToPhone);
}
public VoipPhone GetNumber(string id)
{
return GetNumbers(id.TrimStart('+')).FirstOrDefault();
}
public virtual VoipPhone GetCurrentNumber()
{
return GetNumbers().FirstOrDefault(r => r.Caller != null);
}
public VoipCall SaveOrUpdateCall(VoipCall call)
{
var voipCall = new DbVoipCall
{
TenantId = TenantID,
Id = call.Id,
NumberFrom = call.NumberFrom,
NumberTo = call.NumberTo,
ContactId = call.ContactId
};
if (!string.IsNullOrEmpty(call.ParentCallId))
{
voipCall.ParentCallId = call.ParentCallId;
}
if (call.Status.HasValue)
{
voipCall.Status = (int)call.Status.Value;
}
if (!call.AnsweredBy.Equals(Guid.Empty))
{
voipCall.AnsweredBy = call.AnsweredBy;
}
if (call.DialDate == DateTime.MinValue)
{
call.DialDate = DateTime.UtcNow;
}
voipCall.DialDate = _tenantUtil.DateTimeToUtc(call.DialDate);
if (call.DialDuration > 0)
{
voipCall.DialDuration = call.DialDuration;
}
if (call.Price > decimal.Zero)
{
voipCall.Price = call.Price;
}
if (call.VoipRecord != null)
{
if (!string.IsNullOrEmpty(call.VoipRecord.Sid))
{
voipCall.Sid = call.VoipRecord.Sid;
}
if (!string.IsNullOrEmpty(call.VoipRecord.Uri))
{
voipCall.Uri = call.VoipRecord.Uri;
}
if (call.VoipRecord.Duration != 0)
{
voipCall.Duration = call.VoipRecord.Duration;
}
if (call.VoipRecord.Price != default)
{
voipCall.RecordPrice = call.VoipRecord.Price;
}
}
VoipDbContext.VoipCalls.Add(voipCall);
VoipDbContext.SaveChanges();
return call;
}
public IEnumerable<VoipCall> GetCalls(VoipCallFilter filter)
{
var query = GetCallsQuery(filter);
if (filter.SortByColumn != null)
{
query.OrderBy(filter.SortByColumn, filter.SortOrder);
}
query = query.Skip((int)filter.Offset);
query = query.Take((int)filter.Max * 3);
var calls = _mapper.Map<List<CallContact>, IEnumerable<VoipCall>>(query.ToList());
calls = calls.GroupJoin(calls, call => call.Id, h => h.ParentCallId, (call, h) =>
{
call.ChildCalls.AddRange(h);
return call;
}).Where(r => string.IsNullOrEmpty(r.ParentCallId)).ToList();
return calls;
}
public VoipCall GetCall(string id)
{
return GetCalls(new VoipCallFilter { Id = id }).FirstOrDefault();
}
public int GetCallsCount(VoipCallFilter filter)
{
return GetCallsQuery(filter).Where(r => r.DbVoipCall.ParentCallId == "").Count();
}
public IEnumerable<VoipCall> GetMissedCalls(Guid agent, long count = 0, DateTime? from = null)
{
var query = GetCallsQuery(new VoipCallFilter { Agent = agent, SortBy = "date", SortOrder = true, Type = "missed" });
if (from.HasValue)
{
query = query.Where(r => r.DbVoipCall.DialDate >= _tenantUtil.DateTimeFromUtc(from.Value));
}
if (count != 0)
{
query = query.Take((int)count);
}
query = query.Select(ca => new
{
dbVoipCall = ca,
tmpDate = VoipDbContext.VoipCalls
.Where(tmp => tmp.TenantId == ca.DbVoipCall.TenantId)
.Where(tmp => tmp.NumberFrom == ca.DbVoipCall.NumberFrom || tmp.NumberTo == ca.DbVoipCall.NumberFrom)
.Where(tmp => tmp.Status <= (int)VoipCallStatus.Missed)
.Max(tmp => tmp.DialDate)
}).Where(r => r.dbVoipCall.DbVoipCall.DialDate >= r.tmpDate || r.tmpDate == default)
.Select(q => q.dbVoipCall);
return _mapper.Map<List<CallContact>, IEnumerable<VoipCall>>(query.ToList());
}
private IQueryable<CallContact> GetCallsQuery(VoipCallFilter filter)
{
var q = VoipDbContext.VoipCalls
.Where(r => r.TenantId == TenantID);
if (!string.IsNullOrEmpty(filter.Id))
{
q = q.Where(r => r.Id == filter.Id || r.ParentCallId == filter.Id);
}
if (filter.ContactID.HasValue)
{
q = q.Where(r => r.ContactId == filter.ContactID.Value);
}
if (!string.IsNullOrWhiteSpace(filter.SearchText))
{
q = q.Where(r => r.Id.StartsWith(filter.SearchText));
}
if (filter.TypeStatus.HasValue)
{
q = q.Where(r => r.Status == filter.TypeStatus.Value);
}
if (filter.FromDate.HasValue)
{
q = q.Where(r => r.DialDate >= filter.FromDate.Value);
}
if (filter.ToDate.HasValue)
{
q = q.Where(r => r.DialDate <= filter.ToDate.Value);
}
if (filter.Agent.HasValue)
{
q = q.Where(r => r.AnsweredBy == filter.Agent.Value);
}
return from voipCalls in q
join crmContact in VoipDbContext.CrmContact on voipCalls.ContactId equals crmContact.Id into grouping
from g in grouping.DefaultIfEmpty()
select new CallContact { DbVoipCall = voipCalls, CrmContact = g };
}
private VoipPhone ToPhone(VoipNumber r)
{
return GetProvider().GetPhone(r);
}
public Consumer Consumer
{
get { return _consumerFactory.GetByKey("twilio"); }
}
public TwilioProvider GetProvider()
{
return new TwilioProvider(Consumer["twilioAccountSid"], Consumer["twilioAuthToken"], _authContext, _tenantUtil, _securityContext, _baseCommonLinkUtility);
}
public bool ConfigSettingsExist
{
get
{
return !string.IsNullOrEmpty(Consumer["twilioAccountSid"]) &&
!string.IsNullOrEmpty(Consumer["twilioAuthToken"]);
}
}
}
public class CallContact
{
public DbVoipCall DbVoipCall { get; set; }
public CrmContact CrmContact { get; set; }
}

View File

@ -1,58 +0,0 @@
// (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
global using System.Reflection;
global using System.Text;
global using System.Web;
global using ASC.Common;
global using ASC.Common.Mapping;
global using ASC.Core;
global using ASC.Core.Common;
global using ASC.Core.Common.Configuration;
global using ASC.Core.Common.EF;
global using ASC.Core.Common.EF.Context;
global using ASC.Core.Common.EF.Model;
global using ASC.Core.Tenants;
global using ASC.VoipService.Dao;
global using ASC.VoipService.Mappings;
global using ASC.VoipService.Twilio;
global using AutoMapper;
global using Newtonsoft.Json;
global using Newtonsoft.Json.Linq;
global using Newtonsoft.Json.Serialization;
global using Twilio.Clients;
global using Twilio.Exceptions;
global using Twilio.Jwt;
global using Twilio.Jwt.Client;
global using Twilio.Rest.Api.V2010.Account;
global using Twilio.Rest.Api.V2010.Account.AvailablePhoneNumberCountry;
global using Twilio.Rest.Api.V2010.Account.Queue;
global using Twilio.TwiML;
global using Twilio.Types;

View File

@ -1,54 +0,0 @@
// (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.VoipService;
public interface IVoipProvider
{
IEnumerable<VoipPhone> GetExistingPhoneNumbers();
IEnumerable<VoipPhone> GetAvailablePhoneNumbers(PhoneNumberType phoneNumberType, string isoCountryCode);
VoipPhone BuyNumber(string phoneNumber);
VoipPhone DeleteNumber(VoipPhone phone);
VoipPhone GetPhone(VoipNumber r);
VoipPhone GetPhone(string id);
VoipCall GetCall(string callId);
string GetToken(Agent agent, int seconds = 60 * 60 * 24);
void UpdateSettings(VoipPhone phone);
VoipRecord GetRecord(string callId, string recordId);
void CreateQueue(VoipPhone newPhone);
void DisablePhone(VoipPhone phone);
}

View File

@ -1,60 +0,0 @@
// (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.VoipService.Mappings;
[Scope]
public class CallTypeConverter : ITypeConverter<CallContact, VoipCall>
{
public VoipCall Convert(CallContact source, VoipCall destination, ResolutionContext context)
{
var result = context.Mapper.Map<DbVoipCall, VoipCall>(source.DbVoipCall);
result.VoipRecord = context.Mapper.Map<DbVoipCall, VoipRecord>(source.DbVoipCall);
if (source.CrmContact != null)
{
result.ContactId = source.CrmContact.Id;
result.ContactIsCompany = source.CrmContact.IsCompany;
result.ContactTitle = result.ContactIsCompany
? source.CrmContact.CompanyName
: source.CrmContact.FirstName == null || source.CrmContact.LastName == null ? null : $"{source.CrmContact.FirstName} {source.CrmContact.LastName}";
}
else
{
result.ContactId = 0;
}
return result;
}
}
public class EventTypeConverterExtension
{
public static void Register(DIHelper services)
{
services.TryAdd<CallTypeConverter>();
}
}

View File

@ -1,126 +0,0 @@
// (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 HttpMethod = Twilio.Http.HttpMethod;
namespace ASC.VoipService.Twilio;
public class TwilioPhone : VoipPhone
{
private readonly TwilioRestClient _twilio;
public TwilioPhone(
TwilioRestClient twilio,
AuthContext authContext,
TenantUtil tenantUtil,
SecurityContext securityContext,
BaseCommonLinkUtility baseCommonLinkUtility) :
base(authContext, tenantUtil, securityContext, baseCommonLinkUtility)
{
_twilio = twilio;
Settings = new TwilioVoipSettings(authContext, tenantUtil, securityContext, baseCommonLinkUtility);
}
#region Calls
public override VoipCall Call(string to, string contactId = null)
{
var number = to.Split('#');
var call = CallResource.Create(new CreateCallOptions(new PhoneNumber("+" + number[0].TrimStart('+')), new PhoneNumber("+" + Number.TrimStart('+')))
{
SendDigits = number.Length > 1 ? number[1] + "#" : string.Empty,
Record = Settings.Caller.Record,
Url = new Uri(Settings.Connect(contactId: contactId))
}, _twilio);
return new VoipCall { Id = call.Sid, NumberFrom = call.From, NumberTo = call.To };
}
public override VoipCall LocalCall(string to)
{
return Call(Number + "#" + to);
}
public override VoipCall RedirectCall(string callId, string to)
{
var call = CallResource.Update(callId, url: new Uri(Settings.Redirect(to)), method: HttpMethod.Post, client: _twilio);
return new VoipCall { Id = call.Sid, NumberTo = to };
}
public override VoipCall HoldUp(string callId)
{
return RedirectCall(callId, "hold");
}
#endregion
#region Queue
public Queue CreateQueue(string name, int size, string waitUrl, int waitTime)
{
var queues = QueueResource.Read(new ReadQueueOptions(), _twilio);
var queue = queues.FirstOrDefault(r => r.FriendlyName == name);
if (queue == null)
{
queue = QueueResource.Create(name, client: _twilio);
}
return new Queue(queue.Sid, name, size, waitUrl, waitTime);
}
public string GetQueue(string name)
{
var queues = QueueResource.Read(new ReadQueueOptions(), _twilio);
return queues.First(r => r.FriendlyName == name).Sid;
}
public IEnumerable<string> QueueCalls(string id)
{
var calls = MemberResource.Read(id, client: _twilio);
return calls.Select(r => r.CallSid);
}
private void AnswerQueueCall(string queueId, string callId, bool reject = false)
{
var calls = QueueCalls(queueId);
if (calls.Contains(callId))
{
MemberResource.Update(queueId, callId, new Uri(Settings.Dequeue(reject)), HttpMethod.Post,
client: _twilio);
}
}
public override void AnswerQueueCall(string callId)
{
AnswerQueueCall(Settings.Queue.Id, callId);
}
public override void RejectQueueCall(string callId)
{
AnswerQueueCall(Settings.Queue.Id, callId, true);
}
#endregion
}

View File

@ -1,232 +0,0 @@
// (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 RecordingResource = Twilio.Rest.Api.V2010.Account.Call.RecordingResource;
namespace ASC.VoipService.Twilio;
public class TwilioProvider : IVoipProvider
{
private readonly string _accountSid;
private readonly string _authToken;
private readonly TwilioRestClient _client;
private readonly AuthContext _authContext;
private readonly TenantUtil _tenantUtil;
private readonly SecurityContext _securityContext;
private readonly BaseCommonLinkUtility _baseCommonLinkUtility;
public TwilioProvider(string accountSid, string authToken, AuthContext authContext, TenantUtil tenantUtil, SecurityContext securityContext, BaseCommonLinkUtility baseCommonLinkUtility)
{
ArgumentNullOrEmptyException.ThrowIfNullOrEmpty(accountSid);
ArgumentNullOrEmptyException.ThrowIfNullOrEmpty(authToken);
_authToken = authToken;
_authContext = authContext;
_tenantUtil = tenantUtil;
_securityContext = securityContext;
_baseCommonLinkUtility = baseCommonLinkUtility;
_accountSid = accountSid;
_client = new TwilioRestClient(accountSid, authToken);
}
#region Call
public VoipRecord GetRecord(string callId, string recordSid)
{
var result = new VoipRecord { Sid = recordSid };
var count = 6;
while (count > 0)
{
try
{
var record = RecordingResource.Fetch(callId, recordSid, client: _client);
if (!record.Price.HasValue)
{
count--;
Thread.Sleep(10000);
continue;
}
result.Price = (-1) * record.Price.Value;
result.Duration = Convert.ToInt32(record.Duration);
if (record.Uri != null)
{
result.Uri = record.Uri;
}
break;
}
catch (ApiException)
{
count--;
Thread.Sleep(10000);
}
}
return result;
}
public void CreateQueue(VoipPhone newPhone)
{
newPhone.Settings.Queue = ((TwilioPhone)newPhone).CreateQueue(newPhone.Number, 5, string.Empty, 5);
}
#endregion
#region Numbers
public VoipPhone BuyNumber(string phoneNumber)
{
var newNumber = IncomingPhoneNumberResource.Create(
new CreateIncomingPhoneNumberOptions
{
PathAccountSid = _accountSid,
PhoneNumber = new PhoneNumber(phoneNumber)
}, _client);
return new TwilioPhone(_client, _authContext, _tenantUtil, _securityContext, _baseCommonLinkUtility) { Id = newNumber.Sid, Number = phoneNumber.Substring(1) };
}
public VoipPhone DeleteNumber(VoipPhone phone)
{
IncomingPhoneNumberResource.Delete(phone.Id, client: _client);
return phone;
}
public IEnumerable<VoipPhone> GetExistingPhoneNumbers()
{
var result = IncomingPhoneNumberResource.Read(client: _client);
return result.Select(r => new TwilioPhone(_client, _authContext, _tenantUtil, _securityContext, _baseCommonLinkUtility) { Id = r.Sid, Number = r.PhoneNumber.ToString() });
}
public IEnumerable<VoipPhone> GetAvailablePhoneNumbers(PhoneNumberType phoneNumberType, string isoCountryCode)
{
return phoneNumberType switch
{
PhoneNumberType.Local => LocalResource.Read(isoCountryCode, voiceEnabled: true, client: _client).Select(r => new TwilioPhone(_client, _authContext, _tenantUtil, _securityContext, _baseCommonLinkUtility) { Number = r.PhoneNumber.ToString() }),
PhoneNumberType.TollFree => TollFreeResource.Read(isoCountryCode, voiceEnabled: true, client: _client).Select(r => new TwilioPhone(_client, _authContext, _tenantUtil, _securityContext, _baseCommonLinkUtility) { Number = r.PhoneNumber.ToString() }),
_ => new List<VoipPhone>(),
};
}
public VoipPhone GetPhone(string phoneSid)
{
var phone = IncomingPhoneNumberResource.Fetch(phoneSid, client: _client);
var result = new TwilioPhone(_client, _authContext, _tenantUtil, _securityContext, _baseCommonLinkUtility)
{
Id = phone.Sid,
Number = phone.PhoneNumber.ToString(),
Settings = new TwilioVoipSettings(_authContext, _tenantUtil, _securityContext, _baseCommonLinkUtility)
};
if (phone.VoiceUrl == null)
{
result.Settings.VoiceUrl = result.Settings.Connect(false);
}
return result;
}
public VoipPhone GetPhone(VoipNumber data)
{
return new TwilioPhone(_client, _authContext, _tenantUtil, _securityContext, _baseCommonLinkUtility)
{
Id = data.Id,
Number = data.Number,
Alias = data.Alias,
Settings = new TwilioVoipSettings(data.Settings, _authContext)
};
}
public VoipCall GetCall(string callId)
{
var result = new VoipCall { Id = callId };
var count = 6;
while (count > 0)
{
try
{
var call = CallResource.Fetch(result.Id, client: _client);
if (!call.Price.HasValue || string.IsNullOrEmpty(call.Duration))
{
count--;
Thread.Sleep(10000);
continue;
}
result.Price = (-1) * call.Price.Value;
result.DialDuration = Convert.ToInt32(call.Duration);
break;
}
catch (ApiException)
{
count--;
Thread.Sleep(10000);
}
}
return result;
}
public string GetToken(Agent agent, int seconds = 60 * 60 * 24)
{
var scopes = new HashSet<IScope>
{
new IncomingClientScope(agent.ClientID)
};
var capability = new ClientCapability(_accountSid, _authToken, scopes: scopes);
return capability.ToJwt();
}
public void UpdateSettings(VoipPhone phone)
{
IncomingPhoneNumberResource.Update(phone.Id, voiceUrl: new Uri(phone.Settings.Connect(false)), client: _client);
}
public void DisablePhone(VoipPhone phone)
{
IncomingPhoneNumberResource.Update(phone.Id, voiceUrl: new Uri("https://demo.twilio.com/welcome/voice/"), client: _client);
}
#endregion
}
public enum PhoneNumberType
{
Local,
/* Mobile,*/
TollFree
}

View File

@ -1,216 +0,0 @@
// (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.VoipService.Twilio;
public class TwilioResponseHelper
{
private readonly VoipSettings _settings;
private readonly string _baseUrl;
private readonly AuthContext _authContext;
private readonly TenantUtil _tenantUtil;
private readonly SecurityContext _securityContext;
public TwilioResponseHelper(
VoipSettings settings,
string baseUrl,
AuthContext authContext,
TenantUtil tenantUtil,
SecurityContext securityContext)
{
_settings = settings;
_authContext = authContext;
_tenantUtil = tenantUtil;
_securityContext = securityContext;
_baseUrl = baseUrl.TrimEnd('/') + "/twilio/";
}
public VoiceResponse Inbound(Tuple<Agent, bool> agentTuple)
{
var agent = agentTuple?.Item1;
var anyOnline = agentTuple != null && agentTuple.Item2;
var response = new VoiceResponse();
if (_settings.WorkingHours != null && _settings.WorkingHours.Enabled)
{
var now = _tenantUtil.DateTimeFromUtc(DateTime.UtcNow);
if (!(_settings.WorkingHours.From <= now.TimeOfDay && _settings.WorkingHours.To >= now.TimeOfDay))
{
return AddVoiceMail(response);
}
}
if (anyOnline)
{
if (!string.IsNullOrEmpty(_settings.GreetingAudio))
{
response.Play(Uri.EscapeDataString(_settings.GreetingAudio));
}
response.Enqueue(_settings.Queue.Name, GetEcho("Enqueue", agent != null), "POST",
GetEcho("Wait", agent != null), "POST");
}
return AddVoiceMail(response);
}
public VoiceResponse Outbound()
{
return !_settings.Caller.AllowOutgoingCalls
? new VoiceResponse()
: AddToResponse(new VoiceResponse(), _settings.Caller);
}
public VoiceResponse Dial()
{
return new VoiceResponse();
}
public VoiceResponse Queue()
{
return new VoiceResponse();
}
public VoiceResponse Enqueue(string queueResult)
{
return queueResult == "leave" ? AddVoiceMail(new VoiceResponse()) : new VoiceResponse();
}
public VoiceResponse Dequeue()
{
return AddToResponse(new VoiceResponse(), _settings.Caller);
}
public VoiceResponse Leave()
{
return AddVoiceMail(new VoiceResponse());
}
public VoiceResponse Wait(string queueTime, string queueSize)
{
var response = new VoiceResponse();
var queue = _settings.Queue;
if (Convert.ToInt32(queueTime) > queue.WaitTime || Convert.ToInt32(queueSize) > queue.Size)
{
return response.Leave();
}
if (!string.IsNullOrEmpty(queue.WaitUrl))
{
var gather = new Gather(method: "POST", action: GetEcho("gatherQueue"));
gather.Play(Uri.EscapeDataString(queue.WaitUrl));
response.Gather(gather);
}
else
{
response.Pause(queue.WaitTime);
}
return response;
}
public VoiceResponse GatherQueue(string digits, List<Agent> availableOperators)
{
var response = new VoiceResponse();
if (digits == "#")
{
return AddVoiceMail(response);
}
var oper = _settings.Operators.Find(r => r.PostFix == digits && availableOperators.Contains(r)) ??
_settings.Operators.FirstOrDefault(r => availableOperators.Contains(r));
return oper != null ? AddToResponse(response, oper) : response;
}
public VoiceResponse Redirect(string to)
{
if (to == "hold")
{
return new VoiceResponse().Play(Uri.EscapeDataString(_settings.HoldAudio), 0);
}
if (Guid.TryParse(to, out var newCallerId))
{
_securityContext.AuthenticateMeWithoutCookie(newCallerId);
}
return new VoiceResponse().Enqueue(_settings.Queue.Name, GetEcho("enqueue"), "POST",
GetEcho("wait") + "&RedirectTo=" + to, "POST");
}
public VoiceResponse VoiceMail()
{
return new VoiceResponse();
}
private VoiceResponse AddToResponse(VoiceResponse response, Agent agent)
{
var dial = new Dial(method: "POST", action: GetEcho("dial"), timeout: agent.TimeOut, record: agent.Record ? "record-from-answer" : "do-not-record");
switch (agent.Answer)
{
case AnswerType.Number:
response.Dial(dial.Number(agent.PhoneNumber, method: "POST", url: GetEcho("client")));
break;
case AnswerType.Client:
response.Dial(dial.Client(agent.ClientID, "POST", GetEcho("client")));
break;
case AnswerType.Sip:
response.Dial(dial.Sip(agent.ClientID, method: "POST", url: GetEcho("client")));
break;
}
return response;
}
private VoiceResponse AddVoiceMail(VoiceResponse response)
{
return string.IsNullOrEmpty(_settings.VoiceMail)
? response.Say("")
: response.Play(Uri.EscapeDataString(_settings.VoiceMail)).Record(method: "POST", action: GetEcho("voiceMail"), maxLength: 30);
}
public string GetEcho(string action, bool user = true)
{
var result = _baseUrl.TrimEnd('/');
if (!string.IsNullOrEmpty(action))
{
result += "/" + action.TrimStart('/');
}
if (user)
{
result += "?CallerId=" + _authContext.CurrentAccount.ID;
}
return result;
}
}

View File

@ -1,85 +0,0 @@
// (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 Uri = System.Uri;
namespace ASC.VoipService.Twilio;
public class TwilioVoipSettings : VoipSettings
{
public TwilioVoipSettings(
AuthContext authContext,
TenantUtil tenantUtil,
SecurityContext securityContext,
BaseCommonLinkUtility baseCommonLinkUtility) :
base(authContext, tenantUtil, securityContext, baseCommonLinkUtility)
{ }
public TwilioVoipSettings(
Uri voiceUrl,
AuthContext authContext,
TenantUtil tenantUtil,
SecurityContext securityContext,
BaseCommonLinkUtility baseCommonLinkUtility) :
this(authContext, tenantUtil, securityContext, baseCommonLinkUtility)
{
if (string.IsNullOrEmpty(voiceUrl.Query))
{
return;
}
JsonSettings = Encoding.UTF8.GetString(Convert.FromBase64String(HttpUtility.UrlDecode(HttpUtility.ParseQueryString(voiceUrl.Query)["settings"])));
}
public TwilioVoipSettings(string settings, AuthContext authContext) : base(settings, authContext)
{
}
public override string Connect(bool user = true, string contactId = null)
{
var result = GetEcho("", user);
if (!string.IsNullOrEmpty(contactId))
{
result += "&ContactId=" + contactId;
}
return result;
}
public override string Redirect(string to)
{
return GetEcho("redirect") + "&RedirectTo=" + to;
}
public override string Dequeue(bool reject)
{
return GetEcho("dequeue") + "&Reject=" + reject;
}
private string GetEcho(string method, bool user = true)
{
return new TwilioResponseHelper(this, BaseCommonLinkUtility.GetFullAbsolutePath(""), AuthContext, TenantUtil, SecurityContext).GetEcho(method, user);
}
}

View File

@ -1,69 +0,0 @@
// (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.VoipService;
public class VoipCall : IMapFrom<CallContact>
{
public string Id { get; set; }
public string ParentCallId { get; set; }
public string NumberFrom { get; set; }
public string NumberTo { get; set; }
public Guid AnsweredBy { get; set; }
public DateTime DialDate { get; set; }
public int DialDuration { get; set; }
public VoipCallStatus? Status { get; set; }
public decimal Price { get; set; }
public int ContactId { get; set; }
public bool ContactIsCompany { get; set; }
public string ContactTitle { get; set; }
public DateTime Date { get; set; }
public DateTime EndDialDate { get; set; }
public VoipRecord VoipRecord { get; set; }
public List<VoipCall> ChildCalls { get; set; }
public VoipCall()
{
ChildCalls = new List<VoipCall>();
VoipRecord = new VoipRecord();
}
public void Mapping(Profile profile)
{
profile.CreateMap<DbVoipCall, VoipCall>();
profile.CreateMap<CallContact, VoipCall>()
.ConvertUsing<CallTypeConverter>();
}
}
public enum VoipCallStatus
{
Incoming,
Outcoming,
Answered,
Missed
}

View File

@ -1,163 +0,0 @@
// (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.VoipService;
public class Agent
{
public Guid Id { get; set; }
public AnswerType Answer { get; set; }
public string ClientID { get { return PhoneNumber + PostFix; } }
public bool Record { get; set; }
public int TimeOut { get; set; }
public AgentStatus Status { get; set; }
public bool AllowOutgoingCalls { get; set; }
public string PostFix { get; set; }
public string PhoneNumber { get; set; }
public string RedirectToNumber { get; set; }
public Agent()
{
Status = AgentStatus.Offline;
TimeOut = 30;
AllowOutgoingCalls = true;
Record = true;
}
public Agent(Guid id, AnswerType answer, VoipPhone phone, string postFix)
: this()
{
Id = id;
Answer = answer;
PhoneNumber = phone.Number;
AllowOutgoingCalls = phone.Settings.AllowOutgoingCalls;
Record = phone.Settings.Record;
PostFix = postFix;
}
}
public class Queue
{
public string Id { get; set; }
public string Name { get; set; }
public int Size { get; set; }
public string WaitUrl { get; set; }
public int WaitTime { get; set; }
public Queue() { }
public Queue(string id, string name, int size, string waitUrl, int waitTime)
{
Id = id;
Name = name;
WaitUrl = waitUrl;
WaitTime = waitTime;
Size = size;
}
}
public sealed class WorkingHours
{
public bool Enabled { get; set; }
public TimeSpan? From { get; set; }
public TimeSpan? To { get; set; }
public WorkingHours() { }
public WorkingHours(TimeSpan from, TimeSpan to)
{
From = from;
To = to;
}
private bool Equals(WorkingHours other)
{
return Enabled.Equals(other.Enabled) && From.Equals(other.From) && To.Equals(other.To);
}
public override bool Equals(object obj)
{
if (obj is null)
{
return false;
}
if (ReferenceEquals(this, obj))
{
return true;
}
if (obj.GetType() != GetType())
{
return false;
}
return Equals((WorkingHours)obj);
}
public override int GetHashCode()
{
return HashCode.Combine(Enabled, From, To);
}
}
public class VoipUpload
{
public string Name { get; set; }
public string Path { get; set; }
public AudioType AudioType { get; set; }
public bool IsDefault { get; set; }
}
public enum AnswerType
{
Number,
Sip,
Client
}
public enum GreetingMessageVoice
{
Man,
Woman,
Alice
}
public enum AgentStatus
{
Online,
Paused,
Offline
}
public enum AudioType
{
Greeting,
HoldUp,
VoiceMail,
Queue
}

View File

@ -1,88 +0,0 @@
// (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.VoipService;
public class VoipPhone
{
public string Id { get; set; }
public string Number { get; set; }
public string Alias { get; set; }
public VoipSettings Settings { get; set; }
public Agent Caller
{
get { return Settings.Caller; }
}
public VoipPhone(AuthContext authContext, TenantUtil tenantUtil, SecurityContext securityContext, BaseCommonLinkUtility baseCommonLinkUtility)
{
Settings = new VoipSettings(authContext, tenantUtil, securityContext, baseCommonLinkUtility);
}
public virtual VoipCall Call(string to, string contactId = null)
{
throw new NotImplementedException();
}
public virtual VoipCall LocalCall(string to)
{
throw new NotImplementedException();
}
public virtual VoipCall RedirectCall(string callId, string to)
{
throw new NotImplementedException();
}
public virtual VoipCall HoldUp(string callId)
{
throw new NotImplementedException();
}
public virtual void AnswerQueueCall(string callId)
{
throw new NotImplementedException();
}
public virtual void RejectQueueCall(string callId)
{
throw new NotImplementedException();
}
}
public class VoipRecord : IMapFrom<DbVoipCall>
{
public string Sid { get; set; }
public string Uri { get; set; }
public int Duration { get; set; }
public decimal Price { get; set; }
public void Mapping(Profile profile)
{
profile.CreateMap<DbVoipCall, VoipRecord>()
.ForMember(dest => dest.Price, opt => opt.MapFrom(src => src.RecordPrice));
}
}

View File

@ -1,175 +0,0 @@
// (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.VoipService;
public class VoipSettings
{
public string VoiceUrl { get; set; }
public string Name { get; set; }
public List<Agent> Operators { get; set; }
public Queue Queue { get; set; }
public Agent Caller { get { return Operators.FirstOrDefault(r => r.Id == AuthContext.CurrentAccount.ID); } }
public WorkingHours WorkingHours { get; set; }
public string VoiceMail { get; set; }
public string GreetingAudio { get; set; }
public string HoldAudio { get; set; }
public bool AllowOutgoingCalls { get; set; }
public bool Pause { get; set; }
public bool Record { get; set; }
internal string JsonSettings
{
get
{
return JsonConvert.SerializeObject(
new
{
Operators,
GreetingAudio,
Name,
Queue,
WorkingHours,
VoiceMail,
HoldAudio,
AllowOutgoingCalls,
Pause,
Record
},
new JsonSerializerSettings { ContractResolver = CustomSerializeContractResolver.Instance });
}
set
{
try
{
var settings = JsonConvert.DeserializeObject<VoipSettings>(value, new JsonSerializerSettings { ContractResolver = CustomSerializeContractResolver.Instance });
Operators = settings.Operators ?? new List<Agent>();
Name = settings.Name;
Queue = settings.Queue;
WorkingHours = settings.WorkingHours;
GreetingAudio = settings.GreetingAudio;
VoiceMail = settings.VoiceMail;
HoldAudio = settings.HoldAudio;
AllowOutgoingCalls = settings.AllowOutgoingCalls;
Pause = settings.Pause;
Record = settings.Record;
}
catch (Exception)
{
}
}
}
protected AuthContext AuthContext { get; }
protected TenantUtil TenantUtil { get; }
protected SecurityContext SecurityContext { get; }
protected BaseCommonLinkUtility BaseCommonLinkUtility { get; }
public VoipSettings(AuthContext authContext, TenantUtil tenantUtil, SecurityContext securityContext, BaseCommonLinkUtility baseCommonLinkUtility)
{
Operators = new List<Agent>();
AuthContext = authContext;
TenantUtil = tenantUtil;
SecurityContext = securityContext;
BaseCommonLinkUtility = baseCommonLinkUtility;
}
public VoipSettings(string settings, AuthContext authContext)
{
JsonSettings = settings;
AuthContext = authContext;
}
public virtual string Connect(bool user = true, string contactId = null)
{
throw new NotImplementedException();
}
public virtual string Redirect(string to)
{
throw new NotImplementedException();
}
public virtual string Dequeue(bool reject)
{
throw new NotImplementedException();
}
public override string ToString()
{
return JsonSettings;
}
public VoipSettings GetSettings(string settings)
{
return new VoipSettings(AuthContext, TenantUtil, SecurityContext, BaseCommonLinkUtility) { JsonSettings = settings };
}
}
class CustomSerializeContractResolver : CamelCasePropertyNamesContractResolver
{
public static readonly CustomSerializeContractResolver Instance = new CustomSerializeContractResolver();
protected override JsonProperty CreateProperty(MemberInfo member, MemberSerialization memberSerialization)
{
var property = base.CreateProperty(member, memberSerialization);
if (property.PropertyName == "voiceMail")
{
property.Converter = new VoiceMailConverter();
}
return property;
}
}
class VoiceMailConverter : JsonConverter
{
public override void WriteJson(JsonWriter writer, object value, JsonSerializer serializer)
{
serializer.Serialize(writer, value);
}
public override object ReadJson(JsonReader reader, Type objectType, object existingValue, JsonSerializer serializer)
{
if (reader.ValueType != null && reader.ValueType.Name == "String")
{
return reader.Value;
}
var jObject = JObject.Load(reader);
var url = jObject.Value<string>("url");
return !string.IsNullOrEmpty(url) ? url : "";
}
public override bool CanConvert(Type objectType)
{
return true;
}
}

View File

@ -1,7 +0,0 @@
syntax = "proto3";
package ASC.VoipService.Dao;
message CachedVoipItem {
int32 tenant = 1;
}

View File

@ -33,14 +33,15 @@ public class AuthHandler : AuthenticationHandler<AuthenticationSchemeOptions>
public AuthHandler(IOptionsMonitor<AuthenticationSchemeOptions> options, ILoggerFactory logger, UrlEncoder encoder, ISystemClock clock) :
base(options, logger, encoder, clock)
{
}
}
public AuthHandler(
IOptionsMonitor<AuthenticationSchemeOptions> options,
ILoggerFactory logger,
UrlEncoder encoder,
ISystemClock clock,
IConfiguration configuration,
IOptionsMonitor<ILog> option,
ILogger<AuthHandler> log,
ApiSystemHelper apiSystemHelper,
MachinePseudoKeys machinePseudoKeys,
IHttpContextAccessor httpContextAccessor) :
@ -48,14 +49,14 @@ public class AuthHandler : AuthenticationHandler<AuthenticationSchemeOptions>
{
Configuration = configuration;
Log = option.Get("ASC.ApiSystem");
Log = log;
ApiSystemHelper = apiSystemHelper;
MachinePseudoKeys = machinePseudoKeys;
HttpContextAccessor = httpContextAccessor;
}
private ILog Log { get; }
private ILogger<AuthHandler> Log { get; }
private IConfiguration Configuration { get; }
@ -67,7 +68,7 @@ public class AuthHandler : AuthenticationHandler<AuthenticationSchemeOptions>
{
if (Convert.ToBoolean(Configuration[Scheme.Name] ?? "false"))
{
Log.DebugFormat("Auth for {0} skipped", Scheme.Name);
Log.LogDebug("Auth for {0} skipped", Scheme.Name);
return Task.FromResult(AuthenticateResult.Success(new AuthenticationTicket(Context.User, new AuthenticationProperties(), Scheme.Name)));
}
@ -80,7 +81,7 @@ public class AuthHandler : AuthenticationHandler<AuthenticationSchemeOptions>
if (string.IsNullOrEmpty(header))
{
Log.Debug("Auth header is NULL");
Log.LogDebug("Auth header is NULL");
return Task.FromResult(AuthenticateResult.Fail(new AuthenticationException(nameof(HttpStatusCode.Unauthorized))));
}
@ -93,7 +94,7 @@ public class AuthHandler : AuthenticationHandler<AuthenticationSchemeOptions>
if (splitted.Length < 3)
{
Log.DebugFormat("Auth failed: invalid token {0}.", header);
Log.LogDebug("Auth failed: invalid token {0}.", header);
return Task.FromResult(AuthenticateResult.Fail(new AuthenticationException(nameof(HttpStatusCode.Unauthorized))));
}
@ -102,7 +103,7 @@ public class AuthHandler : AuthenticationHandler<AuthenticationSchemeOptions>
var date = splitted[1];
var orighash = splitted[2];
Log.Debug("Variant of correct auth:" + ApiSystemHelper.CreateAuthToken(pkey));
Log.LogDebug("Variant of correct auth:" + ApiSystemHelper.CreateAuthToken(pkey));
if (!string.IsNullOrWhiteSpace(date))
{
@ -112,7 +113,7 @@ public class AuthHandler : AuthenticationHandler<AuthenticationSchemeOptions>
if (DateTime.UtcNow > timestamp.Add(trustInterval))
{
Log.DebugFormat("Auth failed: invalid timesatmp {0}, now {1}.", timestamp, DateTime.UtcNow);
Log.LogDebug("Auth failed: invalid timesatmp {0}, now {1}.", timestamp, DateTime.UtcNow);
return Task.FromResult(AuthenticateResult.Fail(new AuthenticationException(nameof(HttpStatusCode.Forbidden))));
}
@ -125,27 +126,27 @@ public class AuthHandler : AuthenticationHandler<AuthenticationSchemeOptions>
if (WebEncoders.Base64UrlEncode(hash) != orighash && Convert.ToBase64String(hash) != orighash)
{
Log.DebugFormat("Auth failed: invalid token {0}, expect {1} or {2}.", orighash, WebEncoders.Base64UrlEncode(hash), Convert.ToBase64String(hash));
Log.LogDebug("Auth failed: invalid token {0}, expect {1} or {2}.", orighash, WebEncoders.Base64UrlEncode(hash), Convert.ToBase64String(hash));
return Task.FromResult(AuthenticateResult.Fail(new AuthenticationException(nameof(HttpStatusCode.Forbidden))));
}
}
else
{
Log.DebugFormat("Auth failed: invalid auth header. Sheme: {0}, parameter: {1}.", Scheme.Name, header);
Log.LogDebug("Auth failed: invalid auth header. Sheme: {0}, parameter: {1}.", Scheme.Name, header);
return Task.FromResult(AuthenticateResult.Fail(new AuthenticationException(nameof(HttpStatusCode.Forbidden))));
}
}
catch (Exception ex)
{
Log.Error(ex);
Log.LogError(ex, "auth error");
return Task.FromResult(AuthenticateResult.Fail(new AuthenticationException(nameof(HttpStatusCode.InternalServerError))));
}
var identity = new ClaimsIdentity(Scheme.Name);
Log.InfoFormat("Auth success {0}", Scheme.Name);
Log.LogInformation("Auth success {0}", Scheme.Name);
if (HttpContextAccessor?.HttpContext != null) HttpContextAccessor.HttpContext.User = new CustomClaimsPrincipal(new ClaimsIdentity(Scheme.Name), identity);
return Task.FromResult(AuthenticateResult.Success(new AuthenticationTicket(Context.User, new AuthenticationProperties(), Scheme.Name)));
}

View File

@ -61,7 +61,7 @@ public class CommonMethods
private IConfiguration Configuration { get; }
private ILog Log { get; }
private ILogger<CommonMethods> Log { get; }
private CoreSettings CoreSettings { get; }
@ -86,7 +86,7 @@ public class CommonMethods
public CommonMethods(
IHttpContextAccessor httpContextAccessor,
IConfiguration configuration,
IOptionsMonitor<ILog> option,
ILogger<CommonMethods> log,
CoreSettings coreSettings,
CommonLinkUtility commonLinkUtility,
EmailValidationKeyProvider emailValidationKeyProvider,
@ -101,7 +101,7 @@ public class CommonMethods
Configuration = configuration;
Log = option.Get("ASC.ApiSystem");
Log = log;
CoreSettings = coreSettings;
@ -166,7 +166,7 @@ public class CommonMethods
if (skipWelcome)
{
Log.DebugFormat("congratulations skiped");
Log.LogDebug("congratulations skiped");
return false;
}
@ -183,7 +183,7 @@ public class CommonMethods
var result = reader.ReadToEnd();
Log.DebugFormat("congratulations result = {0}", result);
Log.LogDebug("congratulations result = {0}", result);
var resObj = JObject.Parse(result);
@ -194,7 +194,7 @@ public class CommonMethods
}
catch (Exception ex)
{
Log.Error("SendCongratulations error", ex);
Log.LogError(ex, "SendCongratulations error");
return false;
}
@ -241,7 +241,7 @@ public class CommonMethods
{
if (IsTestEmail(model.Email)) return false;
Log.DebugFormat("clientIP = {0}", clientIP);
Log.LogDebug("clientIP = {0}", clientIP);
var cacheKey = "ip_" + clientIP;
@ -272,7 +272,7 @@ public class CommonMethods
if (ipAttemptsCount <= CommonConstants.MaxAttemptsCount) return false;
Log.DebugFormat("PortalName = {0}; Too much reqests from ip: {1}", model.PortalName, clientIP);
Log.LogDebug("PortalName = {0}; Too much reqests from ip: {1}", model.PortalName, clientIP);
sw.Stop();
return true;
@ -338,17 +338,17 @@ public class CommonMethods
}
else
{
Log.DebugFormat("Recaptcha error: {0}", resp);
Log.LogDebug("Recaptcha error: {0}", resp);
}
if (resObj["error-codes"] != null && resObj["error-codes"].HasValues)
{
Log.DebugFormat("Recaptcha api returns errors: {0}", resp);
Log.LogDebug("Recaptcha api returns errors: {0}", resp);
}
}
catch (Exception ex)
{
Log.Error(ex);
Log.LogError(ex, "ValidateRecaptcha");
}
return false;
}

View File

@ -1,3 +1,29 @@
// (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
/*
*
* (c) Copyright Ascensio System Limited 2010-2018
@ -28,13 +54,13 @@ namespace ASC.ApiSystem.Classes;
[Singletone]
public class TimeZonesProvider
{
public ILog Log { get; }
public ILogger<TimeZonesProvider> Log { get; }
private CommonConstants CommonConstants { get; }
public TimeZonesProvider(IOptionsMonitor<ILog> option, CommonConstants commonConstants)
public TimeZonesProvider(ILogger<TimeZonesProvider> logger, CommonConstants commonConstants)
{
Log = option.Get("ASC.ApiSystem");
Log = logger;
CommonConstants = commonConstants;
}
@ -112,7 +138,7 @@ public class TimeZonesProvider
}
catch (Exception e)
{
Log.Error(e);
Log.LogError(e, "GetCurrentTimeZoneInfo");
return TimeZoneInfo.Utc;
}

View File

@ -1,3 +1,29 @@
// (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
/*
*
* (c) Copyright Ascensio System Limited 2010-2018
@ -35,7 +61,7 @@ public class CalDavController : ControllerBase
private CoreSettings CoreSettings { get; }
private CommonConstants CommonConstants { get; }
public InstanceCrypto InstanceCrypto { get; }
private ILog Log { get; }
private ILogger<CalDavController> Log { get; }
private IHttpClientFactory ClientFactory { get; }
public CalDavController(
@ -44,14 +70,14 @@ public class CalDavController : ControllerBase
CoreSettings coreSettings,
CommonConstants commonConstants,
InstanceCrypto instanceCrypto,
IOptionsMonitor<ILog> option)
ILogger<CalDavController> logger)
{
CommonMethods = commonMethods;
EmailValidationKeyProvider = emailValidationKeyProvider;
CoreSettings = coreSettings;
CommonConstants = commonConstants;
InstanceCrypto = instanceCrypto;
Log = option.Get("ASC.ApiSystem");
Log = logger;
}
#region For TEST api
@ -85,7 +111,7 @@ public class CalDavController : ControllerBase
}
catch (Exception ex)
{
Log.Error("Error change_to_storage", ex);
Log.LogError(ex, "Error change_to_storage");
return StatusCode(StatusCodes.Status500InternalServerError, new
{
@ -114,7 +140,7 @@ public class CalDavController : ControllerBase
}
catch (Exception ex)
{
Log.Error("Error caldav_delete_event", ex);
Log.LogError(ex, "Error caldav_delete_event");
return StatusCode(StatusCodes.Status500InternalServerError, new
{
@ -132,7 +158,7 @@ public class CalDavController : ControllerBase
{
if (userPassword == null || string.IsNullOrEmpty(userPassword.User) || string.IsNullOrEmpty(userPassword.Password))
{
Log.Error("CalDav authenticated data is null");
Log.LogError("CalDav authenticated data is null");
return BadRequest(new
{
@ -149,7 +175,7 @@ public class CalDavController : ControllerBase
try
{
Log.Info(string.Format("Caldav auth user: {0}, tenant: {1}", email, tenant.Id));
Log.LogInformation(string.Format("Caldav auth user: {0}, tenant: {1}", email, tenant.Id));
if (InstanceCrypto.Encrypt(email) == userPassword.Password)
{
@ -172,7 +198,7 @@ public class CalDavController : ControllerBase
}
catch (Exception ex)
{
Log.Error("Caldav authenticated", ex);
Log.LogError(ex, "Caldav authenticated");
return StatusCode(StatusCodes.Status500InternalServerError, new
{
@ -192,7 +218,7 @@ public class CalDavController : ControllerBase
if (string.IsNullOrEmpty(calendarParam))
{
Log.Error("calendarParam is empty");
Log.LogError("calendarParam is empty");
error = new
{
@ -204,7 +230,7 @@ public class CalDavController : ControllerBase
return false;
}
Log.Info($"CalDav calendarParam: {calendarParam}");
Log.LogInformation($"CalDav calendarParam: {calendarParam}");
var userParam = calendarParam.Split('/')[0];
return GetUserData(userParam, out _, out tenant, out error);
@ -218,7 +244,7 @@ public class CalDavController : ControllerBase
if (string.IsNullOrEmpty(userParam))
{
Log.Error("userParam is empty");
Log.LogError("userParam is empty");
error = new
{
@ -234,7 +260,7 @@ public class CalDavController : ControllerBase
if (userData.Length < 3)
{
Log.Error($"Error Caldav username: {userParam}");
Log.LogError($"Error Caldav username: {userParam}");
error = new
{
@ -257,13 +283,13 @@ public class CalDavController : ControllerBase
tenantName = tenantName.Replace("." + baseUrl, "");
}
Log.Info($"CalDav: user:{userParam} tenantName:{tenantName}");
Log.LogInformation($"CalDav: user:{userParam} tenantName:{tenantName}");
var tenantModel = new TenantModel { PortalName = tenantName };
if (!CommonMethods.GetTenant(tenantModel, out tenant))
{
Log.Error("Model without tenant");
Log.LogError("Model without tenant");
error = new
{
@ -277,7 +303,7 @@ public class CalDavController : ControllerBase
if (tenant == null)
{
Log.Error("Tenant not found " + tenantName);
Log.LogError("Tenant not found " + tenantName);
error = new
{
@ -305,7 +331,7 @@ public class CalDavController : ControllerBase
var url = $"{requestUriScheme}{Uri.SchemeDelimiter}{tenant.GetTenantDomain(CoreSettings)}{CommonConstants.WebApiBaseUrl}{path}{(string.IsNullOrEmpty(query) ? "" : "?" + query)}";
Log.Info($"CalDav: SendToApi: {url}");
Log.LogInformation($"CalDav: SendToApi: {url}");
var request = new HttpRequestMessage();
request.RequestUri = new Uri(url);

View File

@ -48,7 +48,7 @@ namespace ASC.ApiSystem.Controllers;
[Route("[controller]")]
public class PeopleController : ControllerBase
{
private ILog Log { get; }
private ILogger<PeopleController> Log { get; }
private HostedSolution HostedSolution { get; }
private UserFormatter UserFormatter { get; }
private ICache Cache { get; }
@ -57,7 +57,7 @@ public class PeopleController : ControllerBase
public IHttpContextAccessor HttpContextAccessor { get; }
public PeopleController(
IOptionsMonitor<ILog> option,
ILogger<PeopleController> option,
IOptionsSnapshot<HostedSolution> hostedSolutionOptions,
UserFormatter userFormatter,
ICache cache,
@ -65,7 +65,7 @@ public class PeopleController : ControllerBase
CommonLinkUtility commonLinkUtility,
IHttpContextAccessor httpContextAccessor)
{
Log = option.Get("ASC.ApiSystem.People");
Log = option;
HostedSolution = hostedSolutionOptions.Value;
UserFormatter = userFormatter;
Cache = cache;
@ -107,7 +107,7 @@ public class PeopleController : ControllerBase
link = GetUserProfileLink(user)
});
Log.DebugFormat("People find {0} / {1}; Elapsed {2} ms", result.Count(), userIds.Count(), sw.ElapsedMilliseconds);
Log.LogDebug("People find {0} / {1}; Elapsed {2} ms", result.Count(), userIds.Count(), sw.ElapsedMilliseconds);
sw.Stop();
return Ok(new

View File

@ -46,7 +46,7 @@ public class PortalController : ControllerBase
private TimeZonesProvider TimeZonesProvider { get; }
private TimeZoneConverter TimeZoneConverter { get; }
public PasswordHasher PasswordHasher { get; }
private ILog Log { get; }
private ILogger<PortalController> Log { get; }
public PortalController(
IConfiguration configuration,
@ -61,7 +61,7 @@ public class PortalController : ControllerBase
UserFormatter userFormatter,
UserManagerWrapper userManagerWrapper,
CommonConstants commonConstants,
IOptionsMonitor<ILog> option,
ILogger<PortalController> option,
TimeZonesProvider timeZonesProvider,
TimeZoneConverter timeZoneConverter,
PasswordHasher passwordHasher)
@ -81,7 +81,7 @@ public class PortalController : ControllerBase
TimeZonesProvider = timeZonesProvider;
TimeZoneConverter = timeZoneConverter;
PasswordHasher = passwordHasher;
Log = option.Get("ASC.ApiSystem");
Log = option;
}
#region For TEST api
@ -170,7 +170,7 @@ public class PortalController : ControllerBase
return BadRequest(error);
}
Log.DebugFormat("PortalName = {0}; Elapsed ms. CheckExistingNamePortal: {1}", model.PortalName, sw.ElapsedMilliseconds);
Log.LogDebug("PortalName = {0}; Elapsed ms. CheckExistingNamePortal: {1}", model.PortalName, sw.ElapsedMilliseconds);
var clientIP = CommonMethods.GetClientIp();
@ -188,27 +188,22 @@ public class PortalController : ControllerBase
return BadRequest(error);
}
if (!CheckRegistrationPayment(out error))
{
return BadRequest(error);
}
var language = model.Language ?? string.Empty;
var tz = TimeZonesProvider.GetCurrentTimeZoneInfo(language);
Log.DebugFormat("PortalName = {0}; Elapsed ms. TimeZonesProvider.GetCurrentTimeZoneInfo: {1}", model.PortalName, sw.ElapsedMilliseconds);
Log.LogDebug("PortalName = {0}; Elapsed ms. TimeZonesProvider.GetCurrentTimeZoneInfo: {1}", model.PortalName, sw.ElapsedMilliseconds);
if (!string.IsNullOrEmpty(model.TimeZoneName))
{
tz = TimeZoneConverter.GetTimeZone(model.TimeZoneName.Trim(), false) ?? tz;
Log.DebugFormat("PortalName = {0}; Elapsed ms. TimeZonesProvider.OlsonTimeZoneToTimeZoneInfo: {1}", model.PortalName, sw.ElapsedMilliseconds);
Log.LogDebug("PortalName = {0}; Elapsed ms. TimeZonesProvider.OlsonTimeZoneToTimeZoneInfo: {1}", model.PortalName, sw.ElapsedMilliseconds);
}
var lang = TimeZonesProvider.GetCurrentCulture(language);
Log.DebugFormat("PortalName = {0}; model.Language = {1}, resultLang.DisplayName = {2}", model.PortalName, language, lang.DisplayName);
Log.LogDebug("PortalName = {0}; model.Language = {1}, resultLang.DisplayName = {2}", model.PortalName, language, lang.DisplayName);
var info = new TenantRegistrationInfo
{
@ -255,20 +250,20 @@ public class PortalController : ControllerBase
{
await ApiSystemHelper.AddTenantToCacheAsync(info.Address, SecurityContext.CurrentAccount.ID);
Log.DebugFormat("PortalName = {0}; Elapsed ms. CacheController.AddTenantToCache: {1}", model.PortalName, sw.ElapsedMilliseconds);
Log.LogDebug("PortalName = {0}; Elapsed ms. CacheController.AddTenantToCache: {1}", model.PortalName, sw.ElapsedMilliseconds);
}
HostedSolution.RegisterTenant(info, out t);
/*********/
Log.DebugFormat("PortalName = {0}; Elapsed ms. HostedSolution.RegisterTenant: {1}", model.PortalName, sw.ElapsedMilliseconds);
Log.LogDebug("PortalName = {0}; Elapsed ms. HostedSolution.RegisterTenant: {1}", model.PortalName, sw.ElapsedMilliseconds);
}
catch (Exception e)
{
sw.Stop();
Log.Error(e);
Log.LogError(e, "");
return StatusCode(StatusCodes.Status500InternalServerError, new
{
@ -321,13 +316,13 @@ public class PortalController : ControllerBase
}
catch (Exception e)
{
Log.Error(e);
Log.LogError(e, "RegisterAsync");
}
}
var reference = CommonMethods.CreateReference(Request.Scheme, t.GetTenantDomain(CoreSettings), info.Email, isFirst);
Log.DebugFormat("PortalName = {0}; Elapsed ms. CreateReferenceByCookie...: {1}", model.PortalName, sw.ElapsedMilliseconds);
Log.LogDebug("PortalName = {0}; Elapsed ms. CreateReferenceByCookie...: {1}", model.PortalName, sw.ElapsedMilliseconds);
sw.Stop();
@ -346,7 +341,7 @@ public class PortalController : ControllerBase
{
if (!CommonMethods.GetTenant(model, out var tenant))
{
Log.Error("Model without tenant");
Log.LogError("Model without tenant");
return BadRequest(new
{
@ -357,7 +352,7 @@ public class PortalController : ControllerBase
if (tenant == null)
{
Log.Error("Tenant not found");
Log.LogError("Tenant not found");
return BadRequest(new
{
@ -381,7 +376,7 @@ public class PortalController : ControllerBase
{
if (!CommonMethods.GetTenant(model, out var tenant))
{
Log.Error("Model without tenant");
Log.LogError("Model without tenant");
return BadRequest(new
{
@ -392,7 +387,7 @@ public class PortalController : ControllerBase
if (tenant == null)
{
Log.Error("Tenant not found");
Log.LogError("Tenant not found");
return BadRequest(new
{
@ -505,7 +500,7 @@ public class PortalController : ControllerBase
}
catch (Exception ex)
{
Log.Error(ex);
Log.LogError(ex, "");
return StatusCode(StatusCodes.Status500InternalServerError, new
{
@ -578,7 +573,7 @@ public class PortalController : ControllerBase
}
catch (Exception ex)
{
Log.Error(ex);
Log.LogError(ex, "CheckExistingNamePortal");
error = new { error = "error", message = ex.Message, stacktrace = ex.StackTrace };
return (false, error);
}
@ -624,28 +619,6 @@ public class PortalController : ControllerBase
return true;
}
private bool CheckRegistrationPayment(out object error)
{
error = null;
if (Configuration["core:base-domain"] == "localhost")
{
var tenants = HostedSolution.GetTenants(DateTime.MinValue);
var firstTenant = tenants.FirstOrDefault();
if (firstTenant != null)
{
var activePortals = tenants.Count(r => r.Status != TenantStatus.Suspended && r.Status != TenantStatus.RemovePending);
var quota = HostedSolution.GetTenantQuota(firstTenant.Id);
if (quota.CountPortals > 0 && quota.CountPortals <= activePortals)
{
error = new { error = "portalsCountTooMuch", message = "Too much portals registered already", };
return false;
}
}
}
return true;
}
#region Recaptcha
@ -657,7 +630,7 @@ public class PortalController : ControllerBase
{
if (!string.IsNullOrEmpty(model.AppKey) && CommonConstants.AppSecretKeys.Contains(model.AppKey))
{
Log.DebugFormat("PortalName = {0}; Elapsed ms. ValidateRecaptcha via app key: {1}. {2}", model.PortalName, model.AppKey, sw.ElapsedMilliseconds);
Log.LogDebug("PortalName = {0}; Elapsed ms. ValidateRecaptcha via app key: {1}. {2}", model.PortalName, model.AppKey, sw.ElapsedMilliseconds);
return true;
}
@ -666,7 +639,7 @@ public class PortalController : ControllerBase
/*** validate recaptcha ***/
if (!CommonMethods.ValidateRecaptcha(model.RecaptchaResponse, model.RecaptchaType, clientIP))
{
Log.DebugFormat("PortalName = {0}; Elapsed ms. ValidateRecaptcha error: {1} {2}", model.PortalName, sw.ElapsedMilliseconds, data);
Log.LogDebug("PortalName = {0}; Elapsed ms. ValidateRecaptcha error: {1} {2}", model.PortalName, sw.ElapsedMilliseconds, data);
sw.Stop();
error = new { error = "recaptchaInvalid", message = "Recaptcha is invalid" };
@ -674,7 +647,7 @@ public class PortalController : ControllerBase
}
Log.DebugFormat("PortalName = {0}; Elapsed ms. ValidateRecaptcha: {1} {2}", model.PortalName, sw.ElapsedMilliseconds, data);
Log.LogDebug("PortalName = {0}; Elapsed ms. ValidateRecaptcha: {1} {2}", model.PortalName, sw.ElapsedMilliseconds, data);
}
return true;

View File

@ -1,3 +1,29 @@
// (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
/*
*
* (c) Copyright Ascensio System Limited 2010-2018
@ -32,16 +58,16 @@ public class SettingsController : ControllerBase
{
private CommonMethods CommonMethods { get; }
private CoreSettings CoreSettings { get; }
private ILog Log { get; }
private ILogger<SettingsController> Log { get; }
public SettingsController(
CommonMethods commonMethods,
CoreSettings coreSettings,
IOptionsMonitor<ILog> option)
ILogger<SettingsController> option)
{
CommonMethods = commonMethods;
CoreSettings = coreSettings;
Log = option.Get("ASC.ApiSystem");
Log = option;
}
#region For TEST api
@ -112,7 +138,7 @@ public class SettingsController : ControllerBase
});
}
Log.DebugFormat("Set {0} value {1} for {2}", model.Key, model.Value, tenantId);
Log.LogDebug("Set {0} value {1} for {2}", model.Key, model.Value, tenantId);
CoreSettings.SaveSetting(model.Key, model.Value, tenantId);
@ -141,7 +167,7 @@ public class SettingsController : ControllerBase
message = "PortalName is required"
};
Log.Error("Model is null");
Log.LogError("Model is null");
return false;
}
@ -160,7 +186,7 @@ public class SettingsController : ControllerBase
message = "PortalName is required"
};
Log.Error("Model without tenant");
Log.LogError("Model without tenant");
return false;
}
@ -173,7 +199,7 @@ public class SettingsController : ControllerBase
message = "Portal not found"
};
Log.Error("Tenant not found");
Log.LogError("Tenant not found");
return false;
}

View File

@ -58,16 +58,16 @@ public class TariffController : ControllerBase
{
private CommonMethods CommonMethods { get; }
private HostedSolution HostedSolution { get; }
private ILog Log { get; }
private ILogger<TariffController> Log { get; }
public TariffController(
CommonMethods commonMethods,
IOptionsSnapshot<HostedSolution> hostedSolutionOptions,
IOptionsMonitor<ILog> option
ILogger<TariffController> option
)
{
CommonMethods = commonMethods;
HostedSolution = hostedSolutionOptions.Value;
Log = option.Get("ASC.ApiSystem");
Log = option;
}
#region For TEST api
@ -92,7 +92,7 @@ public class TariffController : ControllerBase
{
if (!CommonMethods.GetTenant(model, out var tenant))
{
Log.Error("Model without tenant");
Log.LogError("Model without tenant");
return BadRequest(new
{
@ -103,7 +103,7 @@ public class TariffController : ControllerBase
if (tenant == null)
{
Log.Error("Tenant not found");
Log.LogError("Tenant not found");
return BadRequest(new
{
@ -156,7 +156,7 @@ public class TariffController : ControllerBase
{
if (!CommonMethods.GetTenant(model, out var tenant))
{
Log.Error("Model without tenant");
Log.LogError("Model without tenant");
return BadRequest(new
{
@ -167,7 +167,7 @@ public class TariffController : ControllerBase
if (tenant == null)
{
Log.Error("Tenant not found");
Log.LogError("Tenant not found");
return BadRequest(new
{

View File

@ -58,8 +58,6 @@ public class LoginEventsRepository
from q in MessagesContext.LoginEvents
from p in MessagesContext.Users.Where(p => q.UserId == p.Id).DefaultIfEmpty()
where q.TenantId == tenant
where q.Date >= fromDate
where q.Date <= to
orderby q.Date descending
select new LoginEventQuery
{

View File

@ -20,10 +20,10 @@
<ItemGroup>
<PackageReference Include="Autofac.Extensions.DependencyInjection" Version="7.2.0" />
<PackageReference Include="Grpc" Version="2.32.0">
<PackageReference Include="Grpc" Version="2.45.0">
<TreatAsUsed>true</TreatAsUsed>
</PackageReference>
<PackageReference Include="Grpc.Tools" Version="2.40.0">
<PackageReference Include="Grpc.Tools" Version="2.45.0">
<PrivateAssets>all</PrivateAssets>
<IncludeAssets>runtime; build; native; contentfiles; analyzers; buildtransitive</IncludeAssets>
</PackageReference>

View File

@ -1,64 +0,0 @@
/*
*
* (c) Copyright Ascensio System Limited 2010-2020
*
* This program is freeware. You can redistribute it and/or modify it under the terms of the GNU
* General Public License (GPL) version 3 as published by the Free Software Foundation (https://www.gnu.org/copyleft/gpl.html).
* In accordance with Section 7(a) of the GNU GPL 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 more details, see GNU GPL at https://www.gnu.org/copyleft/gpl.html
*
* You can contact Ascensio System SIA by email at sales@onlyoffice.com
*
* The interactive user interfaces in modified source and object code versions of ONLYOFFICE must display
* Appropriate Legal Notices, as required under Section 5 of the GNU GPL version 3.
*
* Pursuant to Section 7 § 3(b) of the GNU GPL you must retain the original ONLYOFFICE logo which contains
* relevant author attributions when distributing the software. If the display of the logo in its graphic
* form is not reasonably feasible for technical reasons, you must include the words "Powered by ONLYOFFICE"
* in every copy of the program you distribute.
* Pursuant to Section 7 § 3(e) we decline to grant you any rights under trademark law for use of our trademarks.
*
*/
using System.Threading;
using System.Threading.Tasks;
using ASC.Common;
using Microsoft.Extensions.Hosting;
namespace ASC.Data.Storage.Encryption
{
[Singletone]
public class EncryptionServiceLauncher : IHostedService
{
private EncryptionServiceListener EncryptionServiceListener { get; set; }
public EncryptionServiceLauncher(EncryptionServiceListener encryptionServiceListener)
{
EncryptionServiceListener = encryptionServiceListener;
}
public Task StartAsync(CancellationToken cancellationToken)
{
if (EncryptionServiceListener != null)
{
EncryptionServiceListener.Start();
}
return Task.CompletedTask;
}
public Task StopAsync(CancellationToken cancellationToken)
{
if (EncryptionServiceListener != null)
{
EncryptionServiceListener.Stop();
}
return Task.CompletedTask;
}
}
}

View File

@ -1,67 +0,0 @@
/*
*
* (c) Copyright Ascensio System Limited 2010-2020
*
* This program is freeware. You can redistribute it and/or modify it under the terms of the GNU
* General Public License (GPL) version 3 as published by the Free Software Foundation (https://www.gnu.org/copyleft/gpl.html).
* In accordance with Section 7(a) of the GNU GPL 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 more details, see GNU GPL at https://www.gnu.org/copyleft/gpl.html
*
* You can contact Ascensio System SIA by email at sales@onlyoffice.com
*
* The interactive user interfaces in modified source and object code versions of ONLYOFFICE must display
* Appropriate Legal Notices, as required under Section 5 of the GNU GPL version 3.
*
* Pursuant to Section 7 § 3(b) of the GNU GPL you must retain the original ONLYOFFICE logo which contains
* relevant author attributions when distributing the software. If the display of the logo in its graphic
* form is not reasonably feasible for technical reasons, you must include the words "Powered by ONLYOFFICE"
* in every copy of the program you distribute.
* Pursuant to Section 7 § 3(e) we decline to grant you any rights under trademark law for use of our trademarks.
*
*/
using ASC.Common;
using ASC.Common.Caching;
using ASC.Core.Encryption;
namespace ASC.Data.Storage.Encryption
{
[Singletone]
public class EncryptionServiceListener
{
private ICacheNotify<EncryptionSettingsProto> NotifySettings { get; }
private ICacheNotify<EncryptionStop> NotifyStop { get; }
private EncryptionWorker EncryptionWorker { get; }
public EncryptionServiceListener(ICacheNotify<EncryptionSettingsProto> notifySettings, ICacheNotify<EncryptionStop> notifyStop, EncryptionWorker encryptionWorker)
{
NotifySettings = notifySettings;
NotifyStop = notifyStop;
EncryptionWorker = encryptionWorker;
}
public void Start()
{
NotifySettings.Subscribe((n) => StartEncryption(n), CacheNotifyAction.Insert);
NotifyStop.Subscribe((n) => StopEncryption(), CacheNotifyAction.Insert);
}
public void Stop()
{
NotifySettings.Unsubscribe(CacheNotifyAction.Insert);
NotifySettings.Unsubscribe(CacheNotifyAction.Insert);
}
public void StartEncryption(EncryptionSettingsProto encryptionSettings)
{
EncryptionWorker.Start(encryptionSettings);
}
public void StopEncryption()
{
EncryptionWorker.Stop();
}
}
}

View File

@ -1,110 +1,64 @@
/*
*
* (c) Copyright Ascensio System Limited 2010-2020
*
* This program is freeware. You can redistribute it and/or modify it under the terms of the GNU
* General Public License (GPL) version 3 as published by the Free Software Foundation (https://www.gnu.org/copyleft/gpl.html).
* In accordance with Section 7(a) of the GNU GPL 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 more details, see GNU GPL at https://www.gnu.org/copyleft/gpl.html
*
* You can contact Ascensio System SIA by email at sales@onlyoffice.com
*
* The interactive user interfaces in modified source and object code versions of ONLYOFFICE must display
* Appropriate Legal Notices, as required under Section 5 of the GNU GPL version 3.
*
* Pursuant to Section 7 § 3(b) of the GNU GPL you must retain the original ONLYOFFICE logo which contains
* relevant author attributions when distributing the software. If the display of the logo in its graphic
* form is not reasonably feasible for technical reasons, you must include the words "Powered by ONLYOFFICE"
* in every copy of the program you distribute.
* Pursuant to Section 7 § 3(e) we decline to grant you any rights under trademark law for use of our trademarks.
*
*/
// (c) Copyright Ascensio System SIA 2010-2022
//
// This program is a free software product.
// You can redistribute it and/or modify it under the terms
// of the GNU Affero General Public License (AGPL) version 3 as published by the Free Software
// Foundation. In accordance with Section 7(a) of the GNU AGPL its Section 15 shall be amended
// to the effect that Ascensio System SIA expressly excludes the warranty of non-infringement of
// any third-party rights.
//
// This program is distributed WITHOUT ANY WARRANTY, without even the implied warranty
// of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. For details, see
// the GNU AGPL at: http://www.gnu.org/licenses/agpl-3.0.html
//
// You can contact Ascensio System SIA at Lubanas st. 125a-25, Riga, Latvia, EU, LV-1021.
//
// The interactive user interfaces in modified source and object code versions of the Program must
// display Appropriate Legal Notices, as required under Section 5 of the GNU AGPL version 3.
//
// Pursuant to Section 7(b) of the License you must retain the original Product logo when
// distributing the program. Pursuant to Section 7(e) we decline to grant you any rights under
// trademark law for use of our trademarks.
//
// All the Product's GUI elements, including illustrations and icon sets, as well as technical writing
// content are licensed under the terms of the Creative Commons Attribution-ShareAlike 4.0
// International. See the License terms at http://creativecommons.org/licenses/by-sa/4.0/legalcode
using System;
using System.Collections.Generic;
using System.IO;
using System.Runtime.InteropServices;
using System.Threading.Tasks;
using System.Reflection;
using ASC.Api.Core;
using ASC.Common.Utils;
using ASC.Api.Core.Extensions;
using ASC.Data.Storage.Encryption.IntegrationEvents.Events;
using ASC.EventBus.Abstractions;
using ASC.Notify.IntegrationEvents.EventHandling;
using Autofac.Extensions.DependencyInjection;
using Microsoft.AspNetCore.Builder;
using Microsoft.Extensions.DependencyInjection;
using Microsoft.Extensions.Hosting.WindowsServices;
using Microsoft.AspNetCore.Hosting;
using Microsoft.Extensions.Configuration;
using Microsoft.Extensions.Hosting;
namespace ASC.Data.Storage.Encryption
{
public class Program
{
public async static Task Main(string[] args)
{
var host = CreateHostBuilder(args).Build();
var options = new WebApplicationOptions
{
Args = args,
ContentRootPath = WindowsServiceHelpers.IsWindowsService() ? AppContext.BaseDirectory : default
};
await host.RunAsync();
}
public static IHostBuilder CreateHostBuilder(string[] args) =>
Host.CreateDefaultBuilder(args)
.UseSystemd()
.UseWindowsService()
.UseServiceProviderFactory(new AutofacServiceProviderFactory())
.ConfigureWebHostDefaults(webBuilder =>
{
var builder = webBuilder.UseStartup<Startup>();
var builder = WebApplication.CreateBuilder(options);
builder.ConfigureKestrel((hostingContext, serverOptions) =>
{
var kestrelConfig = hostingContext.Configuration.GetSection("Kestrel");
builder.Host.ConfigureDefault(args);
if (!kestrelConfig.Exists()) return;
builder.WebHost.ConfigureDefaultKestrel();
var unixSocket = kestrelConfig.GetValue<string>("ListenUnixSocket");
if (RuntimeInformation.IsOSPlatform(OSPlatform.Linux))
{
if (!String.IsNullOrWhiteSpace(unixSocket))
{
unixSocket = String.Format(unixSocket, hostingContext.HostingEnvironment.ApplicationName.Replace("ASC.", "").Replace(".", ""));
var app = builder.Build();
serverOptions.ListenUnixSocket(unixSocket);
}
}
});
})
.ConfigureAppConfiguration((hostContext, config) =>
{
var buided = config.Build();
var path = buided["pathToConf"];
if (!Path.IsPathRooted(path))
{
path = Path.GetFullPath(CrossPlatform.PathCombine(hostContext.HostingEnvironment.ContentRootPath, path));
}
config.SetBasePath(path);
var env = hostContext.Configuration.GetValue("ENVIRONMENT", "Production");
config
.AddInMemoryCollection(new Dictionary<string, string>
{
{"pathToConf", path }
}
)
.AddJsonFile("appsettings.json")
.AddJsonFile($"appsettings.{env}.json", true)
.AddJsonFile("storage.json")
.AddJsonFile("notify.json")
.AddJsonFile($"notify.{env}.json", true)
.AddJsonFile("kafka.json")
.AddJsonFile($"kafka.{env}.json", true)
.AddJsonFile("rabbitmq.json")
.AddJsonFile($"rabbitmq.{env}.json", true)
.AddJsonFile("redis.json")
.AddJsonFile($"redis.{env}.json", true)
.AddEnvironmentVariables();
})
.ConfigureNLogLogging();
}
}
var eventBus = ((IApplicationBuilder)app).ApplicationServices.GetRequiredService<IEventBus>();
eventBus.Subscribe<EncryptionDataStorageRequestedIntegration, EncryptionDataStorageRequestedIntegrationEventHandler>();
app.Run();
public partial class Program
{
public static string AppName = Assembly.GetExecutingAssembly().GetName().Name;
}

View File

@ -1,54 +0,0 @@
/*
*
* (c) Copyright Ascensio System Limited 2010-2020
*
* This program is freeware. You can redistribute it and/or modify it under the terms of the GNU
* General Public License (GPL) version 3 as published by the Free Software Foundation (https://www.gnu.org/copyleft/gpl.html).
* In accordance with Section 7(a) of the GNU GPL 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 more details, see GNU GPL at https://www.gnu.org/copyleft/gpl.html
*
* You can contact Ascensio System SIA by email at sales@onlyoffice.com
*
* The interactive user interfaces in modified source and object code versions of ONLYOFFICE must display
* Appropriate Legal Notices, as required under Section 5 of the GNU GPL version 3.
*
* Pursuant to Section 7 § 3(b) of the GNU GPL you must retain the original ONLYOFFICE logo which contains
* relevant author attributions when distributing the software. If the display of the logo in its graphic
* form is not reasonably feasible for technical reasons, you must include the words "Powered by ONLYOFFICE"
* in every copy of the program you distribute.
* Pursuant to Section 7 § 3(e) we decline to grant you any rights under trademark law for use of our trademarks.
*
*/
using ASC.Api.Core;
using ASC.Common;
using Microsoft.Extensions.Configuration;
using Microsoft.Extensions.DependencyInjection;
using Microsoft.Extensions.Hosting;
using StackExchange.Redis.Extensions.Core.Configuration;
using StackExchange.Redis.Extensions.Newtonsoft;
namespace ASC.Data.Storage.Encryption
{
public class Startup : BaseStartup
{
public Startup(IConfiguration configuration, IHostEnvironment hostEnvironment) : base(configuration, hostEnvironment)
{
}
public override void ConfigureServices(IServiceCollection services)
{
base.ConfigureServices(services);
DIHelper.TryAdd<EncryptionServiceLauncher>();
services.AddHostedService<EncryptionServiceLauncher>();
}
}
}

View File

@ -1,4 +1,30 @@
/*
// (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
/*
*
* (c) Copyright Ascensio System Limited 2010-2018
*
@ -28,13 +54,12 @@ using System;
using ASC.Common;
using ASC.Common.Caching;
using ASC.Common.Logging;
using ASC.Core;
using ASC.Data.Storage.Configuration;
using ASC.Protos.Migration;
using Microsoft.Extensions.DependencyInjection;
using Microsoft.Extensions.Options;
using Microsoft.Extensions.Logging;
namespace ASC.Data.Storage.Migration
{
@ -87,20 +112,20 @@ namespace ASC.Data.Storage.Migration
public StaticUploader StaticUploader { get; }
public StorageFactoryConfig StorageFactoryConfig { get; }
public IServiceProvider ServiceProvider { get; }
public ILog Log { get; }
public ILogger<MigrationService> Log { get; }
public MigrationService(
StorageUploader storageUploader,
StaticUploader staticUploader,
StorageFactoryConfig storageFactoryConfig,
IServiceProvider serviceProvider,
IOptionsMonitor<ILog> options)
ILogger<MigrationService> logger)
{
StorageUploader = storageUploader;
StaticUploader = staticUploader;
StorageFactoryConfig = storageFactoryConfig;
ServiceProvider = serviceProvider;
Log = options.Get("ASC.Data.Storage.Migration");
Log = logger;
}
public void Migrate(int tenantId, StorageSettings newStorageSettings)
@ -115,7 +140,7 @@ namespace ASC.Data.Storage.Migration
tenantManager.SetCurrentTenant(tenantId);
StaticUploader.UploadDir(relativePath, mappedPath);
Log.DebugFormat("UploadDir {0}", mappedPath);
Log.LogDebug("UploadDir {0}", mappedPath);
}
public double GetProgress(int tenantId)

View File

@ -30,6 +30,8 @@ namespace ASC.ElasticSearch.Core;
public class SearchSettings : ISettings<SearchSettings>
{
public string Data { get; set; }
[JsonIgnore]
public Guid ID => new Guid("{93784AB2-10B5-4C2F-9B36-F2662CCCF316}");
internal List<SearchSettingsItem> Items
{

View File

@ -1,34 +0,0 @@
<Project Sdk="Microsoft.NET.Sdk.Web">
<PropertyGroup>
<TargetFramework>net6.0</TargetFramework>
<ApplicationIcon />
<OutputType>Exe</OutputType>
<RazorCompileOnBuild>false</RazorCompileOnBuild>
<GenerateMvcApplicationPartsAssemblyAttributes>false</GenerateMvcApplicationPartsAssemblyAttributes>
<AppendTargetFrameworkToOutputPath>false</AppendTargetFrameworkToOutputPath>
</PropertyGroup>
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Release|AnyCPU'">
<DebugType>none</DebugType>
<DebugSymbols>false</DebugSymbols>
</PropertyGroup>
<ItemGroup>
<ProjectReference Include="..\..\ASC.Api.Core\ASC.Api.Core.csproj" />
<ProjectReference Include="..\..\ASC.Data.Encryption\ASC.Data.Encryption.csproj" />
<ProjectReference Include="..\..\ASC.Data.Storage\ASC.Data.Storage.csproj" />
</ItemGroup>
<ItemGroup>
<Folder Include="Properties\" />
</ItemGroup>
<ItemGroup>
<PackageReference Include="Autofac.Extensions.DependencyInjection" Version="7.2.0" />
<PackageReference Include="Microsoft.Extensions.Hosting.Systemd" Version="6.0.0" />
<PackageReference Include="StackExchange.Redis.Extensions.AspNetCore" Version="8.0.4" />
<PackageReference Include="StackExchange.Redis.Extensions.Newtonsoft" Version="8.0.4" />
</ItemGroup>
</Project>

View File

@ -1,133 +0,0 @@
/*
*
* (c) Copyright Ascensio System Limited 2010-2020
*
* This program is freeware. You can redistribute it and/or modify it under the terms of the GNU
* General Public License (GPL) version 3 as published by the Free Software Foundation (https://www.gnu.org/copyleft/gpl.html).
* In accordance with Section 7(a) of the GNU GPL 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 more details, see GNU GPL at https://www.gnu.org/copyleft/gpl.html
*
* You can contact Ascensio System SIA by email at sales@onlyoffice.com
*
* The interactive user interfaces in modified source and object code versions of ONLYOFFICE must display
* Appropriate Legal Notices, as required under Section 5 of the GNU GPL version 3.
*
* Pursuant to Section 7 § 3(b) of the GNU GPL you must retain the original ONLYOFFICE logo which contains
* relevant author attributions when distributing the software. If the display of the logo in its graphic
* form is not reasonably feasible for technical reasons, you must include the words "Powered by ONLYOFFICE"
* in every copy of the program you distribute.
* Pursuant to Section 7 § 3(e) we decline to grant you any rights under trademark law for use of our trademarks.
*
*/
using System.Collections.Generic;
using System.IO;
using System.Threading.Tasks;
using ASC.Api.Core;
using ASC.Common;
using ASC.Common.Caching;
using ASC.Common.DependencyInjection;
using ASC.Common.Utils;
using Autofac;
using Autofac.Extensions.DependencyInjection;
using Microsoft.AspNetCore.Hosting;
using Microsoft.Extensions.Configuration;
using Microsoft.Extensions.DependencyInjection;
using Microsoft.Extensions.Hosting;
using StackExchange.Redis.Extensions.Core.Configuration;
using StackExchange.Redis.Extensions.Newtonsoft;
namespace ASC.Thumbnails.Svc
{
public class Program
{
public async static Task Main(string[] args)
{
var host = CreateHostBuilder(args).Build();
await host.RunAsync();
}
public static IHostBuilder CreateHostBuilder(string[] args) =>
Host.CreateDefaultBuilder(args)
.UseSystemd()
.UseWindowsService()
.UseServiceProviderFactory(new AutofacServiceProviderFactory())
.ConfigureWebHostDefaults(webBuilder => webBuilder.UseStartup<BaseWorkerStartup>())
.ConfigureAppConfiguration((hostContext, config) =>
{
var buided = config.Build();
var path = buided["pathToConf"];
if (!Path.IsPathRooted(path))
{
path = Path.GetFullPath(CrossPlatform.PathCombine(hostContext.HostingEnvironment.ContentRootPath, path));
}
config.SetBasePath(path);
var env = hostContext.Configuration.GetValue("ENVIRONMENT", "Production");
config
.AddJsonFile("appsettings.json")
.AddJsonFile("storage.json")
.AddJsonFile("kafka.json")
.AddJsonFile($"kafka.{env}.json", true)
.AddJsonFile("rabbitmq.json")
.AddJsonFile($"rabbitmq.{env}.json", true)
.AddJsonFile("redis.json")
.AddJsonFile($"redis.{env}.json", true)
.AddJsonFile("thumb.json")
.AddJsonFile($"appsettings.{env}.json", true)
.AddJsonFile($"thumb.{env}.json", true)
.AddEnvironmentVariables()
.AddCommandLine(args)
.AddInMemoryCollection(new Dictionary<string, string>
{
{"pathToConf", path }
}
);
})
.ConfigureServices((hostContext, services) =>
{
services.AddMemoryCache();
var diHelper = new DIHelper(services);
var redisConfiguration = hostContext.Configuration.GetSection("Redis").Get<RedisConfiguration>();
var kafkaConfiguration = hostContext.Configuration.GetSection("kafka").Get<KafkaSettings>();
var rabbitMQConfiguration = hostContext.Configuration.GetSection("RabbitMQ").Get<RabbitMQSettings>();
if (kafkaConfiguration != null)
{
diHelper.TryAdd(typeof(ICacheNotify<>), typeof(KafkaCacheNotify<>));
}
else if (rabbitMQConfiguration != null)
{
diHelper.TryAdd(typeof(ICacheNotify<>), typeof(RabbitMQCache<>));
}
else if (redisConfiguration != null)
{
diHelper.TryAdd(typeof(ICacheNotify<>), typeof(RedisCacheNotify<>));
services.AddStackExchangeRedisExtensions<NewtonsoftSerializer>(redisConfiguration);
}
else
{
diHelper.TryAdd(typeof(ICacheNotify<>), typeof(MemoryCacheNotify<>));
}
services.AddHostedService<ThumbnailsServiceLauncher>();
diHelper.TryAdd<ThumbnailsServiceLauncher>();
})
.ConfigureContainer<ContainerBuilder>((context, builder) =>
{
builder.Register(context.Configuration, false, false);
})
.ConfigureNLogLogging();
}
}

View File

@ -1,29 +0,0 @@
{
"profiles": {
"Kestrel WebServer": {
"commandName": "Project",
"launchBrowser": false,
"environmentVariables": {
"$STORAGE_ROOT": "../../../Data",
"log__name": "thumbnails",
"log__dir": "../../../Logs",
"core__products__folder": "../../../products",
"ASPNETCORE_URLS": "http://localhost:5030",
"ASPNETCORE_ENVIRONMENT": "Development"
}
},
"WSL 2 : Ubuntu 20.04": {
"commandName": "WSL2",
"launchBrowser": false,
"environmentVariables": {
"$STORAGE_ROOT": "../../../Data",
"log__name": "thumbnails",
"log__dir": "../../../Logs",
"core__products__folder": "../../../products",
"ASPNETCORE_URLS": "http://localhost:5030",
"ASPNETCORE_ENVIRONMENT": "Development"
},
"distributionName": "Ubuntu-20.04"
}
}
}

View File

@ -1,119 +0,0 @@
/*
*
* (c) Copyright Ascensio System Limited 2010-2018
*
* This program is freeware. You can redistribute it and/or modify it under the terms of the GNU
* General Public License (GPL) version 3 as published by the Free Software Foundation (https://www.gnu.org/copyleft/gpl.html).
* In accordance with Section 7(a) of the GNU GPL 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 more details, see GNU GPL at https://www.gnu.org/copyleft/gpl.html
*
* You can contact Ascensio System SIA by email at sales@onlyoffice.com
*
* The interactive user interfaces in modified source and object code versions of ONLYOFFICE must display
* Appropriate Legal Notices, as required under Section 5 of the GNU GPL version 3.
*
* Pursuant to Section 7 § 3(b) of the GNU GPL you must retain the original ONLYOFFICE logo which contains
* relevant author attributions when distributing the software. If the display of the logo in its graphic
* form is not reasonably feasible for technical reasons, you must include the words "Powered by ONLYOFFICE"
* in every copy of the program you distribute.
* Pursuant to Section 7 § 3(e) we decline to grant you any rights under trademark law for use of our trademarks.
*
*/
using System;
using System.Diagnostics;
using System.IO;
using System.Threading;
using System.Threading.Tasks;
using ASC.Common;
using ASC.Common.Logging;
using ASC.Common.Utils;
using Microsoft.Extensions.Hosting;
using Microsoft.Extensions.Options;
namespace ASC.Thumbnails.Svc
{
[Singletone]
public class ThumbnailsServiceLauncher : IHostedService
{
private ProcessStartInfo StartInfo { get; set; }
private Process Proc { get; set; }
private ILog Logger { get; set; }
private ConfigurationExtension Configuration { get; set; }
private IHostEnvironment HostEnvironment { get; set; }
public ThumbnailsServiceLauncher(IOptionsMonitor<ILog> options, ConfigurationExtension configuration, IHostEnvironment hostEnvironment)
{
Logger = options.CurrentValue;
Configuration = configuration;
HostEnvironment = hostEnvironment;
}
public Task StartAsync(CancellationToken cancellationToken)
{
try
{
var settings = Configuration.GetSetting<ThumbnailsSettings>("thumb");
StartInfo = new ProcessStartInfo
{
CreateNoWindow = false,
UseShellExecute = false,
FileName = "node",
WindowStyle = ProcessWindowStyle.Hidden,
Arguments = $"\"{Path.GetFullPath(CrossPlatform.PathCombine(HostEnvironment.ContentRootPath, settings.Path, "index.js"))}\"",
WorkingDirectory = AppDomain.CurrentDomain.BaseDirectory
};
var savePath = settings.SavePath;
if (!savePath.EndsWith("/"))
{
savePath += "/";
}
StartInfo.EnvironmentVariables.Add("port", settings.Port);
StartInfo.EnvironmentVariables.Add("logPath", CrossPlatform.PathCombine(Logger.LogDirectory, "web.thumbnails.log"));
StartInfo.EnvironmentVariables.Add("savePath", Path.GetFullPath(savePath));
StartNode(cancellationToken);
}
catch (Exception e)
{
Logger.Error("Start", e);
}
return Task.CompletedTask;
}
public Task StopAsync(CancellationToken cancellationToken)
{
try
{
if (Proc != null && !Proc.HasExited)
{
Proc.Kill();
Proc.WaitForExit(10000);
Proc.Close();
Proc.Dispose();
Proc = null;
}
}
catch (Exception e)
{
Logger.Error("Stop", e);
}
return Task.CompletedTask;
}
private void StartNode(CancellationToken cancellationToken)
{
StopAsync(cancellationToken);
Proc = Process.Start(StartInfo);
}
}
}

View File

@ -1,9 +0,0 @@
namespace ASC.Thumbnails.Svc
{
public class ThumbnailsSettings
{
public string Path { get; set; }
public string Port { get; set; }
public string SavePath { get; set; }
}
}

View File

@ -1,3 +0,0 @@
{
"pathToConf": "..\\..\\..\\config"
}

File diff suppressed because it is too large Load Diff

View File

@ -1,5 +1,5 @@
<?xml version="1.0" encoding="UTF-8"?>
<babeledit_project be_version="3.0.0" version="1.2">
<babeledit_project be_version="3.0.1" version="1.2">
<!--
BabelEdit project file

View File

@ -1,5 +1,5 @@
<?xml version="1.0" encoding="UTF-8"?>
<babeledit_project be_version="3.0.0" version="1.2">
<babeledit_project be_version="3.0.1" version="1.2">
<!--
BabelEdit project file
@ -3458,12 +3458,16 @@
<name>DeleteProfileEverDialog</name>
<children>
<concept_node>
<name>DeleteUserConfirmation</name>
<name>DeleteUser</name>
<definition_loaded>false</definition_loaded>
<description/>
<comment/>
<default_text/>
<translations>
<translation>
<language>az-Cyrl-AZ</language>
<approved>false</approved>
</translation>
<translation>
<language>bg-BG</language>
<approved>false</approved>
@ -3524,6 +3528,10 @@
<language>pl-PL</language>
<approved>false</approved>
</translation>
<translation>
<language>pt-BR</language>
<approved>false</approved>
</translation>
<translation>
<language>pt-PT</language>
<approved>false</approved>
@ -3541,19 +3549,7 @@
<approved>false</approved>
</translation>
<translation>
<language>az-Cyrl-AZ</language>
<approved>false</approved>
</translation>
<translation>
<language>zh-CN</language>
<approved>false</approved>
</translation>
<translation>
<language>vi-VN</language>
<approved>false</approved>
</translation>
<translation>
<language>uk-UA</language>
<language>sl-SI</language>
<approved>false</approved>
</translation>
<translation>
@ -3561,22 +3557,30 @@
<approved>false</approved>
</translation>
<translation>
<language>sl-SI</language>
<language>uk-UA</language>
<approved>false</approved>
</translation>
<translation>
<language>pt-BR</language>
<language>vi-VN</language>
<approved>false</approved>
</translation>
<translation>
<language>zh-CN</language>
<approved>false</approved>
</translation>
</translations>
</concept_node>
<concept_node>
<name>DeleteUserDataConfirmation</name>
<name>DeleteUserMessage</name>
<definition_loaded>false</definition_loaded>
<description/>
<comment/>
<default_text/>
<translations>
<translation>
<language>az-Cyrl-AZ</language>
<approved>false</approved>
</translation>
<translation>
<language>bg-BG</language>
<approved>false</approved>
@ -3637,6 +3641,10 @@
<language>pl-PL</language>
<approved>false</approved>
</translation>
<translation>
<language>pt-BR</language>
<approved>false</approved>
</translation>
<translation>
<language>pt-PT</language>
<approved>false</approved>
@ -3654,19 +3662,7 @@
<approved>false</approved>
</translation>
<translation>
<language>az-Cyrl-AZ</language>
<approved>false</approved>
</translation>
<translation>
<language>zh-CN</language>
<approved>false</approved>
</translation>
<translation>
<language>vi-VN</language>
<approved>false</approved>
</translation>
<translation>
<language>uk-UA</language>
<language>sl-SI</language>
<approved>false</approved>
</translation>
<translation>
@ -3674,11 +3670,15 @@
<approved>false</approved>
</translation>
<translation>
<language>sl-SI</language>
<language>uk-UA</language>
<approved>false</approved>
</translation>
<translation>
<language>pt-BR</language>
<language>vi-VN</language>
<approved>false</approved>
</translation>
<translation>
<language>zh-CN</language>
<approved>false</approved>
</translation>
</translations>
@ -4034,232 +4034,6 @@
<file_node>
<name>DeleteUsersDialog</name>
<children>
<concept_node>
<name>DeleteGroupUsersMessage</name>
<definition_loaded>false</definition_loaded>
<description/>
<comment/>
<default_text/>
<translations>
<translation>
<language>bg-BG</language>
<approved>false</approved>
</translation>
<translation>
<language>cs-CZ</language>
<approved>false</approved>
</translation>
<translation>
<language>de-DE</language>
<approved>false</approved>
</translation>
<translation>
<language>el-GR</language>
<approved>false</approved>
</translation>
<translation>
<language>en-US</language>
<approved>false</approved>
</translation>
<translation>
<language>es-ES</language>
<approved>false</approved>
</translation>
<translation>
<language>fi-FI</language>
<approved>false</approved>
</translation>
<translation>
<language>fr-FR</language>
<approved>false</approved>
</translation>
<translation>
<language>it-IT</language>
<approved>false</approved>
</translation>
<translation>
<language>ja-JP</language>
<approved>false</approved>
</translation>
<translation>
<language>ko-KR</language>
<approved>false</approved>
</translation>
<translation>
<language>lo-LA</language>
<approved>false</approved>
</translation>
<translation>
<language>lv-LV</language>
<approved>false</approved>
</translation>
<translation>
<language>nl-NL</language>
<approved>false</approved>
</translation>
<translation>
<language>pl-PL</language>
<approved>false</approved>
</translation>
<translation>
<language>pt-PT</language>
<approved>false</approved>
</translation>
<translation>
<language>ro-RO</language>
<approved>false</approved>
</translation>
<translation>
<language>ru-RU</language>
<approved>false</approved>
</translation>
<translation>
<language>sk-SK</language>
<approved>false</approved>
</translation>
<translation>
<language>az-Cyrl-AZ</language>
<approved>false</approved>
</translation>
<translation>
<language>zh-CN</language>
<approved>false</approved>
</translation>
<translation>
<language>vi-VN</language>
<approved>false</approved>
</translation>
<translation>
<language>uk-UA</language>
<approved>false</approved>
</translation>
<translation>
<language>tr-TR</language>
<approved>false</approved>
</translation>
<translation>
<language>sl-SI</language>
<approved>false</approved>
</translation>
<translation>
<language>pt-BR</language>
<approved>false</approved>
</translation>
</translations>
</concept_node>
<concept_node>
<name>DeleteGroupUsersMessageHeader</name>
<definition_loaded>false</definition_loaded>
<description/>
<comment/>
<default_text/>
<translations>
<translation>
<language>bg-BG</language>
<approved>false</approved>
</translation>
<translation>
<language>cs-CZ</language>
<approved>false</approved>
</translation>
<translation>
<language>de-DE</language>
<approved>false</approved>
</translation>
<translation>
<language>el-GR</language>
<approved>false</approved>
</translation>
<translation>
<language>en-US</language>
<approved>false</approved>
</translation>
<translation>
<language>es-ES</language>
<approved>false</approved>
</translation>
<translation>
<language>fi-FI</language>
<approved>false</approved>
</translation>
<translation>
<language>fr-FR</language>
<approved>false</approved>
</translation>
<translation>
<language>it-IT</language>
<approved>false</approved>
</translation>
<translation>
<language>ja-JP</language>
<approved>false</approved>
</translation>
<translation>
<language>ko-KR</language>
<approved>false</approved>
</translation>
<translation>
<language>lo-LA</language>
<approved>false</approved>
</translation>
<translation>
<language>lv-LV</language>
<approved>false</approved>
</translation>
<translation>
<language>nl-NL</language>
<approved>false</approved>
</translation>
<translation>
<language>pl-PL</language>
<approved>false</approved>
</translation>
<translation>
<language>pt-PT</language>
<approved>false</approved>
</translation>
<translation>
<language>ro-RO</language>
<approved>false</approved>
</translation>
<translation>
<language>ru-RU</language>
<approved>false</approved>
</translation>
<translation>
<language>sk-SK</language>
<approved>false</approved>
</translation>
<translation>
<language>az-Cyrl-AZ</language>
<approved>false</approved>
</translation>
<translation>
<language>zh-CN</language>
<approved>false</approved>
</translation>
<translation>
<language>vi-VN</language>
<approved>false</approved>
</translation>
<translation>
<language>uk-UA</language>
<approved>false</approved>
</translation>
<translation>
<language>tr-TR</language>
<approved>false</approved>
</translation>
<translation>
<language>sl-SI</language>
<approved>false</approved>
</translation>
<translation>
<language>pt-BR</language>
<approved>false</approved>
</translation>
</translations>
</concept_node>
<concept_node>
<name>DeleteGroupUsersSuccessMessage</name>
<definition_loaded>false</definition_loaded>
@ -4374,12 +4148,16 @@
</translations>
</concept_node>
<concept_node>
<name>DeleteUserDataConfirmation</name>
<name>DeleteUsers</name>
<definition_loaded>false</definition_loaded>
<description/>
<comment/>
<default_text/>
<translations>
<translation>
<language>az-Cyrl-AZ</language>
<approved>false</approved>
</translation>
<translation>
<language>bg-BG</language>
<approved>false</approved>
@ -4440,6 +4218,10 @@
<language>pl-PL</language>
<approved>false</approved>
</translation>
<translation>
<language>pt-BR</language>
<approved>false</approved>
</translation>
<translation>
<language>pt-PT</language>
<approved>false</approved>
@ -4457,19 +4239,7 @@
<approved>false</approved>
</translation>
<translation>
<language>az-Cyrl-AZ</language>
<approved>false</approved>
</translation>
<translation>
<language>zh-CN</language>
<approved>false</approved>
</translation>
<translation>
<language>vi-VN</language>
<approved>false</approved>
</translation>
<translation>
<language>uk-UA</language>
<language>sl-SI</language>
<approved>false</approved>
</translation>
<translation>
@ -4477,13 +4247,130 @@
<approved>false</approved>
</translation>
<translation>
<language>sl-SI</language>
<language>uk-UA</language>
<approved>false</approved>
</translation>
<translation>
<language>vi-VN</language>
<approved>false</approved>
</translation>
<translation>
<language>zh-CN</language>
<approved>false</approved>
</translation>
</translations>
</concept_node>
<concept_node>
<name>DeleteUsersMessage</name>
<definition_loaded>false</definition_loaded>
<description/>
<comment/>
<default_text/>
<translations>
<translation>
<language>az-Cyrl-AZ</language>
<approved>false</approved>
</translation>
<translation>
<language>bg-BG</language>
<approved>false</approved>
</translation>
<translation>
<language>cs-CZ</language>
<approved>false</approved>
</translation>
<translation>
<language>de-DE</language>
<approved>false</approved>
</translation>
<translation>
<language>el-GR</language>
<approved>false</approved>
</translation>
<translation>
<language>en-US</language>
<approved>false</approved>
</translation>
<translation>
<language>es-ES</language>
<approved>false</approved>
</translation>
<translation>
<language>fi-FI</language>
<approved>false</approved>
</translation>
<translation>
<language>fr-FR</language>
<approved>false</approved>
</translation>
<translation>
<language>it-IT</language>
<approved>false</approved>
</translation>
<translation>
<language>ja-JP</language>
<approved>false</approved>
</translation>
<translation>
<language>ko-KR</language>
<approved>false</approved>
</translation>
<translation>
<language>lo-LA</language>
<approved>false</approved>
</translation>
<translation>
<language>lv-LV</language>
<approved>false</approved>
</translation>
<translation>
<language>nl-NL</language>
<approved>false</approved>
</translation>
<translation>
<language>pl-PL</language>
<approved>false</approved>
</translation>
<translation>
<language>pt-BR</language>
<approved>false</approved>
</translation>
<translation>
<language>pt-PT</language>
<approved>false</approved>
</translation>
<translation>
<language>ro-RO</language>
<approved>false</approved>
</translation>
<translation>
<language>ru-RU</language>
<approved>false</approved>
</translation>
<translation>
<language>sk-SK</language>
<approved>false</approved>
</translation>
<translation>
<language>sl-SI</language>
<approved>false</approved>
</translation>
<translation>
<language>tr-TR</language>
<approved>false</approved>
</translation>
<translation>
<language>uk-UA</language>
<approved>false</approved>
</translation>
<translation>
<language>vi-VN</language>
<approved>false</approved>
</translation>
<translation>
<language>zh-CN</language>
<approved>false</approved>
</translation>
</translations>
</concept_node>
</children>
@ -9607,119 +9494,6 @@
</translation>
</translations>
</concept_node>
<concept_node>
<name>Disconnect</name>
<definition_loaded>false</definition_loaded>
<description/>
<comment/>
<default_text/>
<translations>
<translation>
<language>bg-BG</language>
<approved>false</approved>
</translation>
<translation>
<language>cs-CZ</language>
<approved>false</approved>
</translation>
<translation>
<language>de-DE</language>
<approved>false</approved>
</translation>
<translation>
<language>el-GR</language>
<approved>false</approved>
</translation>
<translation>
<language>en-US</language>
<approved>false</approved>
</translation>
<translation>
<language>es-ES</language>
<approved>false</approved>
</translation>
<translation>
<language>fi-FI</language>
<approved>false</approved>
</translation>
<translation>
<language>fr-FR</language>
<approved>false</approved>
</translation>
<translation>
<language>it-IT</language>
<approved>false</approved>
</translation>
<translation>
<language>ja-JP</language>
<approved>false</approved>
</translation>
<translation>
<language>ko-KR</language>
<approved>false</approved>
</translation>
<translation>
<language>lo-LA</language>
<approved>false</approved>
</translation>
<translation>
<language>lv-LV</language>
<approved>false</approved>
</translation>
<translation>
<language>nl-NL</language>
<approved>false</approved>
</translation>
<translation>
<language>pl-PL</language>
<approved>false</approved>
</translation>
<translation>
<language>pt-PT</language>
<approved>false</approved>
</translation>
<translation>
<language>ro-RO</language>
<approved>false</approved>
</translation>
<translation>
<language>ru-RU</language>
<approved>false</approved>
</translation>
<translation>
<language>sk-SK</language>
<approved>false</approved>
</translation>
<translation>
<language>az-Cyrl-AZ</language>
<approved>false</approved>
</translation>
<translation>
<language>zh-CN</language>
<approved>false</approved>
</translation>
<translation>
<language>vi-VN</language>
<approved>false</approved>
</translation>
<translation>
<language>uk-UA</language>
<approved>false</approved>
</translation>
<translation>
<language>tr-TR</language>
<approved>false</approved>
</translation>
<translation>
<language>sl-SI</language>
<approved>false</approved>
</translation>
<translation>
<language>pt-BR</language>
<approved>false</approved>
</translation>
</translations>
</concept_node>
<concept_node>
<name>EditPhoto</name>
<definition_loaded>false</definition_loaded>
@ -15281,6 +15055,119 @@
</translation>
</translations>
</concept_node>
<concept_node>
<name>DeleteUserDataConfirmation</name>
<definition_loaded>false</definition_loaded>
<description/>
<comment/>
<default_text/>
<translations>
<translation>
<language>az-Cyrl-AZ</language>
<approved>false</approved>
</translation>
<translation>
<language>bg-BG</language>
<approved>false</approved>
</translation>
<translation>
<language>cs-CZ</language>
<approved>false</approved>
</translation>
<translation>
<language>de-DE</language>
<approved>false</approved>
</translation>
<translation>
<language>el-GR</language>
<approved>false</approved>
</translation>
<translation>
<language>en-US</language>
<approved>false</approved>
</translation>
<translation>
<language>es-ES</language>
<approved>false</approved>
</translation>
<translation>
<language>fi-FI</language>
<approved>false</approved>
</translation>
<translation>
<language>fr-FR</language>
<approved>false</approved>
</translation>
<translation>
<language>it-IT</language>
<approved>false</approved>
</translation>
<translation>
<language>ja-JP</language>
<approved>false</approved>
</translation>
<translation>
<language>ko-KR</language>
<approved>false</approved>
</translation>
<translation>
<language>lo-LA</language>
<approved>false</approved>
</translation>
<translation>
<language>lv-LV</language>
<approved>false</approved>
</translation>
<translation>
<language>nl-NL</language>
<approved>false</approved>
</translation>
<translation>
<language>pl-PL</language>
<approved>false</approved>
</translation>
<translation>
<language>pt-BR</language>
<approved>false</approved>
</translation>
<translation>
<language>pt-PT</language>
<approved>false</approved>
</translation>
<translation>
<language>ro-RO</language>
<approved>false</approved>
</translation>
<translation>
<language>ru-RU</language>
<approved>false</approved>
</translation>
<translation>
<language>sk-SK</language>
<approved>false</approved>
</translation>
<translation>
<language>sl-SI</language>
<approved>false</approved>
</translation>
<translation>
<language>tr-TR</language>
<approved>false</approved>
</translation>
<translation>
<language>uk-UA</language>
<approved>false</approved>
</translation>
<translation>
<language>vi-VN</language>
<approved>false</approved>
</translation>
<translation>
<language>zh-CN</language>
<approved>false</approved>
</translation>
</translations>
</concept_node>
<concept_node>
<name>DisableUserButton</name>
<definition_loaded>false</definition_loaded>
@ -16411,119 +16298,6 @@
</translation>
</translations>
</concept_node>
<concept_node>
<name>NotBeUndone</name>
<definition_loaded>false</definition_loaded>
<description/>
<comment/>
<default_text/>
<translations>
<translation>
<language>bg-BG</language>
<approved>false</approved>
</translation>
<translation>
<language>cs-CZ</language>
<approved>false</approved>
</translation>
<translation>
<language>de-DE</language>
<approved>false</approved>
</translation>
<translation>
<language>el-GR</language>
<approved>false</approved>
</translation>
<translation>
<language>en-US</language>
<approved>false</approved>
</translation>
<translation>
<language>es-ES</language>
<approved>false</approved>
</translation>
<translation>
<language>fi-FI</language>
<approved>false</approved>
</translation>
<translation>
<language>fr-FR</language>
<approved>false</approved>
</translation>
<translation>
<language>it-IT</language>
<approved>false</approved>
</translation>
<translation>
<language>ja-JP</language>
<approved>false</approved>
</translation>
<translation>
<language>ko-KR</language>
<approved>false</approved>
</translation>
<translation>
<language>lo-LA</language>
<approved>false</approved>
</translation>
<translation>
<language>lv-LV</language>
<approved>false</approved>
</translation>
<translation>
<language>nl-NL</language>
<approved>false</approved>
</translation>
<translation>
<language>pl-PL</language>
<approved>false</approved>
</translation>
<translation>
<language>pt-PT</language>
<approved>false</approved>
</translation>
<translation>
<language>ro-RO</language>
<approved>false</approved>
</translation>
<translation>
<language>ru-RU</language>
<approved>false</approved>
</translation>
<translation>
<language>sk-SK</language>
<approved>false</approved>
</translation>
<translation>
<language>az-Cyrl-AZ</language>
<approved>false</approved>
</translation>
<translation>
<language>zh-CN</language>
<approved>false</approved>
</translation>
<translation>
<language>vi-VN</language>
<approved>false</approved>
</translation>
<translation>
<language>uk-UA</language>
<approved>false</approved>
</translation>
<translation>
<language>tr-TR</language>
<approved>false</approved>
</translation>
<translation>
<language>sl-SI</language>
<approved>false</approved>
</translation>
<translation>
<language>pt-BR</language>
<approved>false</approved>
</translation>
</translations>
</concept_node>
<concept_node>
<name>PasswordChangeButton</name>
<definition_loaded>false</definition_loaded>

View File

@ -55,18 +55,32 @@ export function setDNSSettings(dnsName, enable) {
});
}
export function getIpRestrictions() {
return request({
method: "get",
url: "/settings/iprestrictions",
});
}
export function setIpRestrictions(data) {
return request({
method: "put",
url: "/settings/iprestrictions.json",
url: "/settings/iprestrictions",
data,
});
}
export function getIpRestrictionsEnable() {
return request({
method: "get",
url: "/settings/iprestrictions/settings",
});
}
export function setIpRestrictionsEnable(data) {
return request({
method: "put",
url: "/settings/iprestrictions/settings.json",
url: "/settings/iprestrictions/settings",
data,
});
}
@ -87,6 +101,13 @@ export function setCookieSettings(lifeTime) {
});
}
export function getCookieSettings() {
return request({
method: "get",
url: "/settings/cookiesettings.json",
});
}
export function setLifetimeAuditSettings(data) {
return request({
method: "post",

View File

@ -121,6 +121,7 @@ const StyledArticle = styled.article`
.article-body__scrollbar {
.scroll-body {
padding-top: 16px;
padding-right: 0px !important;
@media ${mobile} {
@ -158,7 +159,7 @@ const StyledArticleHeader = styled.div`
@media ${mobile} {
border-bottom: ${(props) => props.theme.catalog.header.borderBottom};
padding: 12px 16px 12px;
margin-bottom: 16px !important;
//margin-bottom: 16px !important;
}
${isTablet &&
@ -173,7 +174,7 @@ const StyledArticleHeader = styled.div`
border-bottom: ${(props) =>
props.theme.catalog.header.borderBottom} !important;
padding: 12px 16px 12px !important;
margin-bottom: 16px !important;
//margin-bottom: 16px !important;
`}
-webkit-tap-highlight-color: rgba(0, 0, 0, 0);
@ -262,11 +263,10 @@ const StyledArticleMainButton = styled.div`
`;
const StyledControlContainer = styled.div`
background: ${(props) => props.theme.catalog.control.background};
width: 24px;
height: 24px;
width: 17px;
height: 17px;
position: absolute;
top: 30px;
top: 37px;
right: 10px;
border-radius: 100px;
cursor: pointer;
@ -279,8 +279,8 @@ const StyledControlContainer = styled.div`
StyledControlContainer.defaultProps = { theme: Base };
const StyledCrossIcon = styled(CrossIcon)`
width: 12px;
height: 12px;
width: 17px;
height: 17px;
path {
fill: ${(props) => props.theme.catalog.control.fill};
}

View File

@ -4,21 +4,25 @@ import StyledDialogAsideLoader from "./StyledDialogAsideLoader";
import Aside from "@appserver/components/aside";
import Backdrop from "@appserver/components/backdrop";
const DialogAsideLoader = ({ isPanel, withoutAside }) => {
const DialogAsideLoader = ({
isPanel,
withoutAside,
withFooterBorder = false,
}) => {
const zIndex = 310;
const renderClearDialogAsideLoader = () => {
return (
<StyledDialogAsideLoader visible isPanel={isPanel}>
<StyledDialogAsideLoader withFooterBorder={withFooterBorder} visible>
<div className="dialog-loader-header">
<Loaders.Rectangle />
<Loaders.Rectangle height="29px" />
</div>
<div className="dialog-loader-body">
<Loaders.Rectangle height="200px" />
</div>
<div className="dialog-loader-footer">
<Loaders.Rectangle />
<Loaders.Rectangle height="40px" />
</div>
</StyledDialogAsideLoader>
);

View File

@ -40,18 +40,23 @@ const StyledDialogAsideLoader = styled.div`
`
: css`
.dialog-loader-header {
border-bottom: 1px solid rgb(222, 226, 230);
padding: 12px 0;
border-bottom: ${(props) =>
`1px solid ${props.theme.modalDialog.headerBorderColor}`};
padding: 12px 16px;
}
.dialog-loader-body {
padding: 16px 0;
padding: 16px;
}
.dialog-loader-footer {
${(props) =>
props.withFooterBorder &&
`border-top: 1px solid ${props.theme.modalDialog.headerBorderColor}`};
padding: 16px;
position: fixed;
bottom: 16px;
width: 293px;
bottom: 0;
width: calc(100% - 32px);
}
`}
`;

View File

@ -2,28 +2,18 @@ import React from "react";
import Loaders from "../../Loaders";
import StyledDialogLoader from "./StyledDialogLoader";
const DialogLoader = ({ bodyHeight = "150px" }) => {
const DialogLoader = ({ isLarge, withFooterBorder }) => {
return (
<StyledDialogLoader>
<StyledDialogLoader withFooterBorder={withFooterBorder} isLarge={isLarge}>
<div className="dialog-loader-header">
<Loaders.Rectangle height="28px" width="470px" />
<Loaders.Rectangle
className="dialog-loader-icon"
height="28px"
width="28px"
/>
<Loaders.Rectangle height="29px" />
</div>
<div className="dialog-loader-body">
<Loaders.Rectangle height={bodyHeight} />
<Loaders.Rectangle height={isLarge ? "175px" : "73px"} />
</div>
<div className="dialog-loader-footer">
<Loaders.Rectangle height="30px" width="120px" />
<Loaders.Rectangle
className="dialog-loader-icon"
height="30px"
width="100px"
/>
<Loaders.Rectangle height="40px" />
<Loaders.Rectangle height="40px" />
</div>
</StyledDialogLoader>
);

View File

@ -1,27 +1,31 @@
import { Base } from "@appserver/components/themes";
import styled from "styled-components";
import { mobile } from "@appserver/components/utils/device";
const StyledDialogLoader = styled.div`
height: auto;
width: ${(props) => (props.isLarge ? "520px" : "400px")};
@media ${mobile} {
width: 100%;
}
.dialog-loader-header {
border-bottom: ${(props) => props.theme.dialogLoader.borderBottom};
display: flex;
padding: 12px 0;
border-bottom: ${(props) =>
`1px solid ${props.theme.modalDialog.headerBorderColor}`};
padding: 12px 16px;
}
.dialog-loader-body {
display: flex;
flex-direction: column;
justify-content: center;
padding-top: 12px;
padding: 12px 16px 8px;
}
.dialog-loader-footer {
${(props) =>
props.withFooterBorder &&
`border-top: 1px solid ${props.theme.modalDialog.headerBorderColor}`};
display: flex;
padding-top: 12px;
}
.dialog-loader-icon {
margin-left: auto;
gap: 10px;
padding: 16px;
}
`;

View File

@ -36,6 +36,9 @@ class SettingsStore {
: Base;
trustedDomains = [];
trustedDomainsType = 0;
ipRestrictionEnable = false;
ipRestrictions = [];
sessionLifetime = "1440";
timezone = "UTC";
timezones = [];
tenantAlias = "";
@ -474,6 +477,47 @@ class SettingsStore {
this.tenantAlias = tenantAlias;
};
getIpRestrictions = async () => {
const res = await api.settings.getIpRestrictions();
this.ipRestrictions = res?.map((el) => el.ip);
};
setIpRestrictions = async (ips) => {
const data = {
ips: ips,
};
const res = await api.settings.setIpRestrictions(data);
this.ipRestrictions = res;
};
getIpRestrictionsEnable = async () => {
const res = await api.settings.getIpRestrictionsEnable();
this.ipRestrictionEnable = res.enable;
};
setIpRestrictionsEnable = async (enable) => {
const data = {
enable: enable,
};
const res = await api.settings.setIpRestrictionsEnable(data);
this.ipRestrictionEnable = res.enable;
};
setMessageSettings = async (turnOn) => {
await api.settings.setMessageSettings(turnOn);
this.enableAdmMess = turnOn;
};
getSessionLifetime = async () => {
const res = await api.settings.getCookieSettings();
this.sessionLifetime = res;
};
setSessionLifetimeSettings = async (lifeTime) => {
const res = await api.settings.setCookieSettings(lifeTime);
this.sessionLifetime = lifeTime;
};
setIsBurgerLoading = (isBurgerLoading) => {
this.isBurgerLoading = isBurgerLoading;
};

View File

@ -9,7 +9,6 @@ import {
} from "./styled-aside";
const Aside = React.memo((props) => {
//console.log("Aside render");
const {
visible,
children,
@ -29,6 +28,7 @@ const Aside = React.memo((props) => {
contentPaddingBottom={contentPaddingBottom}
className={`${className} not-selectable aside`}
>
{/* <CloseButton displayType="aside" zIndex={zIndex}/> */}
{withoutBodyScroll ? (
children
) : (

View File

@ -135,7 +135,7 @@ class AvatarEditor extends React.Component {
return useModalDialog ? (
<ModalDialog
visible={this.state.visible}
displayType={displayType}
displayType="aside"
scale={false}
contentHeight="initial"
contentWidth="initial"
@ -174,8 +174,16 @@ class AvatarEditor extends React.Component {
isLoading={saveButtonLoading}
primary={true}
size="normal"
scale
onClick={this.onSaveButtonClick}
/>
<Button
key="CancelBtn"
label={cancelButtonLabel}
size="normal"
scale
onClick={this.onCancelButtonClick}
/>
</ModalDialog.Footer>
</ModalDialog>
) : (

View File

@ -127,7 +127,7 @@ const StyledAvatarContainer = styled.div`
.preview-container {
display: grid;
grid-template-columns: 1fr;
grid-column-gap: 16px;
grid-column-gap: 44px;
.custom-range {
width: 100%;
@ -165,7 +165,7 @@ const StyledAvatarContainer = styled.div`
display: grid;
@media ${desktop} {
width: 224px;
width: 216px;
}
@media ${tablet} {

View File

@ -7,11 +7,13 @@ import DropDownItem from "../drop-down-item";
import {
StyledSpan,
StyledText,
StyledTextWithExpander,
StyledLinkWithDropdown,
Caret,
} from "./styled-link-with-dropdown";
import { isMobileOnly } from "react-device-detect";
import Scrollbar from "@appserver/components/scrollbar";
import { ReactSVG } from "react-svg";
class LinkWithDropdown extends React.Component {
constructor(props) {
@ -101,6 +103,7 @@ class LinkWithDropdown extends React.Component {
directionY,
theme,
hasScroll,
withExpander,
...rest
} = this.props;
@ -118,6 +121,24 @@ class LinkWithDropdown extends React.Component {
/>
));
const styledText = (
<StyledText
className="text"
isTextOverflow={isTextOverflow}
truncate={isTextOverflow}
fontSize={fontSize}
fontWeight={fontWeight}
color={color}
isBold={isBold}
title={title}
dropdownType={dropdownType}
isDisabled={isDisabled}
withTriangle
>
{this.props.children}
</StyledText>
);
return (
<StyledSpan className={className} id={id} style={style} ref={this.ref}>
<span onClick={this.onOpen}>
@ -127,26 +148,17 @@ class LinkWithDropdown extends React.Component {
color={color}
isDisabled={isDisabled}
>
<StyledText
className="text"
isTextOverflow={isTextOverflow}
truncate={isTextOverflow}
fontSize={fontSize}
fontWeight={fontWeight}
color={color}
isBold={isBold}
title={title}
dropdownType={dropdownType}
isDisabled={isDisabled}
>
{this.props.children}
</StyledText>
<Caret
color={color}
dropdownType={dropdownType}
isOpen={this.state.isOpen}
isDisabled={isDisabled}
/>
{withExpander ? (
<StyledTextWithExpander isOpen={this.state.isOpen}>
{styledText}
<ReactSVG
className="expander"
src={"/static/images/expander-down.react.svg"}
/>
</StyledTextWithExpander>
) : (
styledText
)}
</StyledLinkWithDropdown>
</span>
<DropDown
@ -156,6 +168,7 @@ class LinkWithDropdown extends React.Component {
withArrow={false}
forwardedRef={this.ref}
directionY={directionY}
isDropdown={false}
clickOutsideAction={this.onClose}
{...rest}
>
@ -185,6 +198,7 @@ LinkWithDropdown.propTypes = {
/** Type of dropdown: alwaysDashed is always show dotted style and icon of arrow,
* appearDashedAfterHover is show dotted style and icon arrow only after hover */
dropdownType: PropTypes.oneOf(["alwaysDashed", "appearDashedAfterHover"]),
withExpander: PropTypes.bool,
/** Font size of link */
fontSize: PropTypes.string,
/** Font weight of link */
@ -225,6 +239,7 @@ LinkWithDropdown.defaultProps = {
className: "",
isDisabled: false,
hasScroll: false,
withExpander: false,
};
export default LinkWithDropdown;

View File

@ -5,6 +5,7 @@ import PropTypes from "prop-types";
import Text from "../text";
import Base from "../themes/base";
import ExpanderDownIcon from "../../../public/images/expander-down.react.svg";
import { transform } from "lodash";
// eslint-disable-next-line no-unused-vars
const SimpleLinkWithDropdown = ({
isBold,
@ -123,6 +124,27 @@ const StyledLinkWithDropdown = styled(SimpleLinkWithDropdown)`
}
`;
StyledLinkWithDropdown.defaultProps = { theme: Base };
const StyledTextWithExpander = styled.div`
display: flex;
gap: 4px;
.expander {
display: flex;
align-items: center;
justify-content: center;
width: 6.35px;
svg {
transform: ${(props) => (props.isOpen ? "rotate(180deg)" : "rotate(0)")};
width: 6.35px;
height: auto;
path {
fill: ${(props) => props.theme.linkWithDropdown.expander.iconColor};
}
}
}
`;
// eslint-disable-next-line react/prop-types, no-unused-vars
const SimpleText = ({ color, ...props }) => <Text as="span" {...props} />;
const StyledText = styled(SimpleText)`
@ -150,4 +172,10 @@ const StyledSpan = styled.span`
`;
StyledSpan.defaultProps = { theme: Base };
export { StyledSpan, StyledText, StyledLinkWithDropdown, Caret };
export {
StyledSpan,
StyledTextWithExpander,
StyledText,
StyledLinkWithDropdown,
Caret,
};

View File

@ -0,0 +1,71 @@
import React from "react";
import PropTypes from "prop-types";
import styled, { css } from "styled-components";
import { smallTablet } from "../../utils/device";
import IconButton from "../../icon-button";
import Base from "../../themes/base";
const StyledCloseButtonWrapper = styled.div`
width: 17px;
height: 17px;
display: flex;
align-items: center;
justify-content: center;
cursor: pointer;
position: absolute;
${(props) =>
props.currentDisplayType === "modal"
? css`
top: 0;
right: -34px;
@media ${smallTablet} {
right: 10px;
top: -27px;
}
`
: css`
top: 10px;
left: -27px;
@media ${smallTablet} {
top: -27px;
left: auto;
right: 10px;
}
`}
.close-button, .close-button:hover {
cursor: pointer;
path {
fill: ${(props) => props.theme.modalDialog.closeButton.fillColor};
}
}
`;
StyledCloseButtonWrapper.defaultProps = { theme: Base };
const CloseButton = ({ currentDisplayType, zIndex, onClick }) => {
return (
<StyledCloseButtonWrapper
zIndex={zIndex}
onClick={onClick}
currentDisplayType={currentDisplayType}
>
<IconButton
size="17px"
className="close-button"
iconName="/static/images/cross.react.svg"
/>
</StyledCloseButtonWrapper>
);
};
CloseButton.propTypes = {
currentDisplayType: PropTypes.oneOf(["modal", "aside"]),
onClick: PropTypes.func,
};
export default CloseButton;

View File

@ -0,0 +1,64 @@
import React from "react";
import styled from "styled-components";
import PropTypes from "prop-types";
const StyledModalBackdrop = styled.div.attrs((props) => ({
style: {
backdropFilter: `${
props.modalSwipeOffset
? `blur(${
props.modalSwipeOffset < 0 && 8 - props.modalSwipeOffset * -0.0667
}px)`
: "blur(8px)"
}`,
background: `${
props.modalSwipeOffset
? `rgba(6, 22, 38, ${
props.modalSwipeOffset < 0 && 0.2 - props.modalSwipeOffset * -0.002
})`
: `rgba(6, 22, 38, 0.2)`
}`,
},
}))`
display: block;
height: 100%;
min-height: fill-available;
max-height: 100vh;
width: 100vw;
position: fixed;
left: 0;
top: 0;
z-index: ${(props) => props.zIndex};
transition: 0.2s;
opacity: 0;
&.modal-backdrop-active {
opacity: 1;
}
`;
const ModalBackdrop = ({ className, zIndex, modalSwipeOffset, children }) => {
return (
<StyledModalBackdrop
zIndex={zIndex}
className={className}
modalSwipeOffset={modalSwipeOffset}
>
{children}
</StyledModalBackdrop>
);
};
ModalBackdrop.propTypes = {
id: PropTypes.string,
className: PropTypes.string,
children: PropTypes.any,
zIndex: PropTypes.number,
visible: PropTypes.bool,
modalSwipeOffset: PropTypes.number,
};
export default ModalBackdrop;

View File

@ -0,0 +1,30 @@
export const parseChildren = (
children,
headerDisplayName,
bodyDisplayName,
footerDisplayName
) => {
let header = null,
body = null,
footer = null;
children.forEach((child) => {
const childType =
child && child.type && (child.type.displayName || child.type.name);
switch (childType) {
case headerDisplayName:
header = child;
break;
case bodyDisplayName:
body = child;
break;
case footerDisplayName:
footer = child;
break;
default:
break;
}
});
return [header, body, footer];
};

View File

@ -0,0 +1,24 @@
import { size } from "../../utils/device";
const getCurrentSizeName = () => {
const innerWidth = window.innerWidth;
return innerWidth > size.tablet
? "desktop"
: innerWidth <= size.tablet && innerWidth > size.smallTablet
? "tablet"
: innerWidth <= size.smallTablet && innerWidth > size.mobile
? "smallTablet"
: "mobile";
};
export const getCurrentDisplayType = (
propsDisplayType,
propsDisplayTypeDetailed
) => {
if (!propsDisplayTypeDetailed) return propsDisplayType;
const detailedDisplayType = propsDisplayTypeDetailed[getCurrentSizeName()];
if (detailedDisplayType) return detailedDisplayType;
return propsDisplayType;
};

View File

@ -0,0 +1,27 @@
import { isSmallTablet, isTouchDevice } from "../../utils/device";
let y1 = null;
export const handleTouchStart = (e) => {
if (!(isTouchDevice && isSmallTablet())) {
y1 = null;
return false;
}
const firstTouch = e.touches[0];
if (firstTouch.target.id !== "modal-header-swipe") {
y1 = null;
return false;
}
y1 = firstTouch.clientY;
};
export const handleTouchMove = (e, onClose) => {
if (!y1) return 0;
let y2 = e.touches[0].clientY;
if (y2 - y1 > 120) onClose();
return y1 - y2;
};

View File

@ -1,299 +1,164 @@
import React from "react";
import React, { useEffect, useState } from "react";
import PropTypes from "prop-types";
import Backdrop from "../backdrop";
import Aside from "../aside";
import Heading from "../heading";
import { getModalType } from "../utils/device";
import throttle from "lodash/throttle";
import Box from "../box";
import {
CloseButton,
StyledHeader,
Content,
Dialog,
BodyBox,
} from "./styled-modal-dialog";
import Portal from "../portal";
import Loaders from "@appserver/common/components/Loaders";
function Header() {
return null;
}
import Portal from "../portal";
import ModalAside from "./views/modal-aside";
import { handleTouchMove, handleTouchStart } from "./handlers/swipeHandler";
import { getCurrentDisplayType } from "./handlers/resizeHandler";
import { parseChildren } from "./handlers/childrenParseHandler";
const Header = () => null;
Header.displayName = "DialogHeader";
function Body() {
return null;
}
const Body = () => null;
Body.displayName = "DialogBody";
function Footer() {
return null;
}
const Footer = () => null;
Footer.displayName = "DialogFooter";
class ModalDialog extends React.Component {
static Header = Header;
static Body = Body;
constructor(props) {
super(props);
const ModalDialog = ({
id,
style,
children,
visible,
onClose,
isLarge,
zIndex,
className,
displayType,
displayTypeDetailed,
isLoading,
autoMaxHeight,
autoMaxWidth,
withBodyScroll,
modalLoaderBodyHeight,
withFooterBorder,
}) => {
const [currentDisplayType, setCurrentDisplayType] = useState(
getCurrentDisplayType(displayType, displayTypeDetailed)
);
const [modalSwipeOffset, setModalSwipeOffset] = useState(0);
this.state = { displayType: this.getTypeByWidth() };
this.getTypeByWidth = this.getTypeByWidth.bind(this);
this.resize = this.resize.bind(this);
this.popstate = this.popstate.bind(this);
this.throttledResize = throttle(this.resize, 300);
}
getTypeByWidth() {
if (this.props.displayType !== "auto") return this.props.displayType;
return getModalType();
}
resize() {
if (this.props.displayType !== "auto") return;
const type = this.getTypeByWidth();
if (type === this.state.displayType) return;
this.setState({ displayType: type });
this.props.onResize && this.props.onResize(type);
}
popstate() {
window.removeEventListener("popstate", this.popstate, false);
this.props.onClose();
window.history.go(1);
}
componentDidUpdate(prevProps) {
if (this.props.displayType !== prevProps.displayType) {
this.setState({ displayType: this.getTypeByWidth() });
}
if (this.props.visible && this.state.displayType === "aside") {
window.addEventListener("popstate", this.popstate, false);
}
}
componentDidMount() {
window.addEventListener("resize", this.throttledResize);
window.addEventListener("keyup", this.onKeyPress);
window.onpopstate = () => {
this.props.onClose();
};
}
componentWillUnmount() {
window.removeEventListener("resize", this.throttledResize);
window.removeEventListener("keyup", this.onKeyPress);
window.onpopstate = null;
}
onKeyPress = (event) => {
if (event.key === "Esc" || event.key === "Escape") {
this.props.onClose();
}
};
render() {
const {
visible,
scale,
onClose,
zIndex,
asideBodyPadding,
modalBodyPadding,
contentHeight,
contentWidth,
className,
id,
style,
children,
isLoading,
contentPaddingBottom,
withoutBodyScroll,
modalLoaderBodyHeight,
withoutCloseButton,
theme,
width,
} = this.props;
let header = null;
let body = null;
let footer = null;
React.Children.forEach(children, (child) => {
const childType =
child && child.type && (child.type.displayName || child.type.name);
switch (childType) {
case Header.displayName:
header = child;
break;
case Body.displayName:
body = child;
break;
case Footer.displayName:
footer = child;
break;
default:
break;
}
});
const renderModal = () => {
return this.state.displayType === "modal" ? (
<Backdrop
visible={visible}
zIndex={zIndex}
withBackground={true}
isModalDialog
>
<Dialog
width={width}
className={`${className} not-selectable`}
id={id}
style={style}
>
<Content
contentHeight={contentHeight}
contentWidth={contentWidth}
displayType={this.state.displayType}
className="modal-dialog-content"
>
{isLoading ? (
<Loaders.DialogLoader bodyHeight={modalLoaderBodyHeight} />
) : (
<>
{header && (
<StyledHeader>
<Heading
className="heading"
size="medium"
truncate={true}
>
{header ? header.props.children : null}
</Heading>
{!withoutCloseButton && (
<CloseButton
className="modal-dialog-button_close"
onClick={onClose}
></CloseButton>
)}
</StyledHeader>
)}
<BodyBox paddingProp={modalBodyPadding}>
{body ? body.props.children : null}
</BodyBox>
<Box className="modal-dialog-modal-footer">
{footer ? footer.props.children : null}
</Box>
</>
)}
</Content>
</Dialog>
</Backdrop>
) : (
<Box className={className} id={id} style={style}>
<Backdrop
visible={visible}
onClick={onClose}
zIndex={zIndex}
isAside={true}
/>
<Aside
visible={visible}
scale={scale}
zIndex={zIndex}
onClose={onClose}
contentPaddingBottom={contentPaddingBottom}
className="modal-dialog-aside not-selectable"
withoutBodyScroll={withoutBodyScroll}
>
<Content
contentHeight={contentHeight}
contentWidth={contentWidth}
withoutBodyScroll={withoutBodyScroll}
displayType={this.state.displayType}
className="modal-dialog-content"
>
{isLoading ? (
<Loaders.DialogAsideLoader withoutAside />
) : (
<>
<StyledHeader className="modal-dialog-aside-header">
<Heading className="heading" size="medium" truncate={true}>
{header ? header.props.children : null}
</Heading>
{scale ? <CloseButton onClick={onClose}></CloseButton> : ""}
</StyledHeader>
<BodyBox
className="modal-dialog-aside-body"
paddingProp={asideBodyPadding}
withoutBodyScroll={withoutBodyScroll}
>
{body ? body.props.children : null}
</BodyBox>
<Box className="modal-dialog-aside-footer">
{footer ? footer.props.children : null}
</Box>
</>
)}
</Content>
</Aside>
</Box>
useEffect(() => {
const onResize = throttle(() => {
setCurrentDisplayType(
getCurrentDisplayType(displayType, displayTypeDetailed)
);
}, 300);
const onSwipe = (e) => setModalSwipeOffset(handleTouchMove(e, onClose));
const onSwipeEnd = () => setModalSwipeOffset(0);
const onKeyPress = (e) => {
if ((e.key === "Esc" || e.key === "Escape") && visible) onClose();
};
const modalDialog = renderModal();
window.addEventListener("resize", onResize);
window.addEventListener("keyup", onKeyPress);
window.addEventListener("touchstart", handleTouchStart);
window.addEventListener("touchmove", onSwipe);
window.addEventListener("touchend", onSwipeEnd);
return () => {
window.removeEventListener("resize", onResize);
window.removeEventListener("keyup", onKeyPress);
window.removeEventListener("touchstart", handleTouchStart);
window.removeEventListener("touchmove", onSwipe);
window.addEventListener("touchend", onSwipeEnd);
};
}, []);
return <Portal element={modalDialog} />;
}
}
const [header, body, footer] = parseChildren(
children,
Header.displayName,
Body.displayName,
Footer.displayName
);
return (
<Portal
element={
<ModalAside
id={id}
style={style}
className={className}
currentDisplayType={currentDisplayType}
withBodyScroll={withBodyScroll}
isLarge={isLarge}
zIndex={zIndex}
autoMaxHeight={autoMaxHeight}
autoMaxWidth={autoMaxWidth}
withFooterBorder={withFooterBorder}
onClose={onClose}
isLoading={isLoading}
header={header}
body={body}
footer={footer}
visible={visible}
modalSwipeOffset={modalSwipeOffset}
/>
}
/>
);
};
ModalDialog.propTypes = {
id: PropTypes.string,
className: PropTypes.string,
zIndex: PropTypes.number,
style: PropTypes.oneOfType([PropTypes.object, PropTypes.array]),
children: PropTypes.any,
/** Display dialog or not */
visible: PropTypes.bool,
/** Display type */
displayType: PropTypes.oneOf(["auto", "modal", "aside"]),
/** Indicates the side panel has scale */
scale: PropTypes.bool,
/** Will be triggered when a close button is clicked */
onClose: PropTypes.func,
onResize: PropTypes.func,
/**Display close button or not */
withoutCloseButton: PropTypes.bool,
/** CSS z-index */
zIndex: PropTypes.number,
/** CSS padding props for body section */
asideBodyPadding: PropTypes.string,
modalBodyPadding: PropTypes.string,
contentHeight: PropTypes.string,
contentWidth: PropTypes.string,
/** Display type */
displayType: PropTypes.oneOf(["modal", "aside"]),
/** Detailed display type for each dimension */
displayTypeDetailed: PropTypes.object,
/** Show loader in body */
isLoading: PropTypes.bool,
withoutBodyScroll: PropTypes.bool,
className: PropTypes.string,
id: PropTypes.string,
style: PropTypes.oneOfType([PropTypes.object, PropTypes.array]),
contentPaddingBottom: PropTypes.string,
modalLoaderBodyHeight: PropTypes.string,
width: PropTypes.string,
/** **`MODAL-ONLY`**
Sets `width: 520px` and `max-hight: 400px`*/
isLarge: PropTypes.bool,
/** **`MODAL-ONLY`**
Sets `max-width: auto`*/
autoMaxWidth: PropTypes.bool,
/** **`MODAL-ONLY`**
Sets `max-height: auto`*/
autoMaxHeight: PropTypes.bool,
/** **`MODAL-ONLY`**
Displays border betweeen body and footer`*/
withFooterBorder: PropTypes.bool,
/** **`ASIDE-ONLY`**
Enables Body scroll */
withBodyScroll: PropTypes.bool,
/** **`ASIDE-ONLY`**
Sets modal dialog size equal to window */
scale: PropTypes.bool,
};
ModalDialog.defaultProps = {
displayType: "auto",
displayType: "modal",
zIndex: 310,
asideBodyPadding: "16px 0",
modalBodyPadding: "12px 0",
contentWidth: "100%",
isLarge: false,
isLoading: false,
withoutCloseButton: false,
withoutBodyScroll: false,
withBodyScroll: false,
withFooterBorder: false,
};
ModalDialog.Header = Header;

View File

@ -1,6 +1,7 @@
import React, { useState } from "react";
import ModalDialog from ".";
import ModalDialog from "./index.js";
import Button from "../button";
import PropTypes from "prop-types";
export default {
title: "Components/ModalDialog",
@ -13,64 +14,63 @@ export default {
},
},
argTypes: {
onClick: { action: "onClick" },
onClose: { action: "onClose" },
onOk: { action: "onOk", table: { disable: true } },
onOk: { action: "onOk" },
},
};
const Template = ({ onClick, onClose, onOk, ...args }) => {
const [isVisible, setIsVisible] = useState(args.visible);
const Template = ({ onOk, ...args }) => {
const [isVisible, setIsVisible] = useState(false);
const toggleVisible = (e) => {
setIsVisible(!isVisible);
onClick(e);
};
const openModal = () => setIsVisible(true);
const closeModal = () => setIsVisible(false);
return (
<div>
<Button
label="Show"
primary={true}
size="small"
onClick={toggleVisible}
/>
<ModalDialog
{...args}
visible={isVisible}
onClose={(e) => {
onClose(e);
setIsVisible(!isVisible);
}}
>
<ModalDialog.Header>{"Change password"}</ModalDialog.Header>
<>
<Button label="Show" primary={true} size="medium" onClick={openModal} />
<ModalDialog {...args} visible={isVisible} onClose={closeModal}>
<ModalDialog.Header>Change password</ModalDialog.Header>
<ModalDialog.Body>
<div>
<span>
Send the password change instruction to the{" "}
<a href="mailto:asc@story.book">asc@story.book</a> email address
</div>
</span>
</ModalDialog.Body>
<ModalDialog.Footer>
<Button
key="SendBtn"
label="Send"
primary={true}
size="small"
onClick={(e) => {
onOk(e);
setIsVisible(!isVisible);
scale
size="normal"
onClick={() => {
onOk();
closeModal();
}}
/>
<Button
key="CloseBtn"
label="Cancel"
scale
size="normal"
onClick={closeModal}
/>
</ModalDialog.Footer>
</ModalDialog>
</div>
</>
);
};
Template.propTypes = {
onOk: PropTypes.func,
};
export const Default = Template.bind({});
Default.args = {
scale: false,
displayType: "auto",
zIndex: 310,
headerContent: "Change password",
displayType: "aside",
displayTypeDetailed: {
desktop: "modal",
tablet: "aside",
smallTablet: "modal",
mobile: "aside",
},
};

View File

@ -1,99 +1,135 @@
import styled, { css } from "styled-components";
import Base from "../themes/base";
import Box from "../box";
import CrossSidebarIcon from "../../../public/images/cross.sidebar.react.svg";
import { smallTablet, tablet } from "../utils/device";
const StyledModal = styled.div`
pointer-events: none;
&.modal-active {
pointer-events: all;
}
.loader-wrapper {
padding: 0 16px 16px;
}
`;
const Dialog = styled.div`
position: relative;
display: flex;
cursor: default;
align-items: center;
width: ${(props) => props.width || props.theme.modalDialog.width};
max-width: ${(props) => props.theme.modalDialog.maxwidth};
margin: ${(props) => props.theme.modalDialog.margin};
min-height: ${(props) => props.theme.modalDialog.minHeight};
justify-content: center;
width: auto;
margin: 0 auto;
min-height: 100%;
`;
Dialog.defaultProps = { theme: Base };
const Content = styled.div`
position: relative;
const Content = styled.div.attrs((props) => ({
style: {
marginBottom:
props.modalSwipeOffset < 0 ? `${props.modalSwipeOffset * 1.1}px` : "0px",
},
}))`
box-sizing: border-box;
height: ${(props) => props.contentHeight};
width: ${(props) => props.contentWidth};
background-color: ${(props) =>
props.theme.modalDialog.content.backgroundColor};
position: relative;
background-color: ${(props) => props.theme.modalDialog.backgroundColor};
color: ${(props) => props.theme.modalDialog.textColor};
padding: ${(props) =>
props.displayType === "modal"
? props.theme.modalDialog.content.modalPadding
: props.theme.modalDialog.content.asidePadding};
border-radius: ${(props) =>
props.theme.modalDialog.content.modalBorderRadius};
.modal-dialog-aside-header {
margin: 0 -16px;
padding: 0 16px;
}
.heading {
max-width: ${(props) => props.theme.modalDialog.content.heading.maxWidth};
margin: ${(props) => props.theme.modalDialog.content.heading.margin};
line-height: ${(props) =>
props.displayType === "modal"
? props.theme.modalDialog.content.heading.modalLineHeight
: props.theme.modalDialog.content.heading.asideLineHeight};
font-weight: ${(props) =>
props.theme.modalDialog.content.heading.fontWeight};
font-size: ${(props) =>
props.displayType === "modal"
? props.theme.modalDialog.content.heading.modalFontSize
: props.theme.modalDialog.content.heading.asideFontSize};
}
props.currentDisplayType === "modal" ? "0" : "0 0 -16px"};
${(props) =>
props.withoutBodyScroll &&
css`
overflow: hidden;
`}
props.currentDisplayType === "modal"
? css`
height: auto;
max-height: ${(props) =>
props.autoMaxHeight ? "auto" : props.isLarge ? "400px" : "280px"};
width: ${(props) =>
props.autoMaxWidth ? "auto" : props.isLarge ? "520px" : "400px"};
border-radius: 6px;
@media ${smallTablet} {
transform: translateY(${(props) => (props.visible ? "0" : "100%")});
transition: transform 0.3s ease-in-out;
position: absolute;
bottom: 0;
width: 100%;
height: auto;
border-radius: 6px 6px 0 0;
}
`
: css`
width: 480px;
display: flex;
flex-direction: column;
position: absolute;
top: 0;
right: 0;
bottom: 0;
transform: translateX(${(props) => (props.visible ? "0" : "100%")});
transition: transform 0.3s ease-in-out;
@media ${smallTablet} {
transform: translateY(${(props) => (props.visible ? "0" : "100%")});
height: calc(100% - 64px);
width: 100%;
left: 0;
top: auto;
bottom: 0;
}
`}
`;
Content.defaultProps = { theme: Base };
const StyledHeader = styled.div`
display: flex;
align-items: center;
border-bottom: ${(props) => props.theme.modalDialog.header.borderBottom};
`;
StyledHeader.defaultProps = { theme: Base };
border-bottom: ${(props) =>
`1px solid ${props.theme.modalDialog.headerBorderColor}`};
margin-bottom: 16px;
height: 52px;
const CloseButton = styled(CrossSidebarIcon)`
cursor: pointer;
position: absolute;
display: flex;
align-items: center;
padding: 0 16px 0;
width: ${(props) => props.theme.modalDialog.closeButton.width};
height: ${(props) => props.theme.modalDialog.closeButton.height};
min-width: ${(props) => props.theme.modalDialog.closeButton.minWidth};
min-height: ${(props) => props.theme.modalDialog.closeButton.minHeight};
right: ${(props) => props.theme.modalDialog.closeButton.right};
top: ${(props) => props.theme.modalDialog.closeButton.top};
&:hover {
path {
stroke: ${(props) => props.theme.modalDialog.closeButton.hoverColor};
}
.heading {
font-family: "Open Sans";
color: ${(props) => props.theme.modalDialog.textColor};
font-weight: 700;
font-size: ${(props) =>
props.currentDisplayType === "modal" ? "18px" : "21px"};
}
`;
CloseButton.defaultProps = { theme: Base };
const BodyBox = styled(Box)`
const StyledBody = styled(Box)`
position: relative;
padding: 0 16px;
padding-bottom: ${(props) =>
props.currentDisplayType === "aside" || props.hasFooter ? "8px" : "16px"};
margin-right: ${(props) => (props.withBodyScroll ? "-16px" : "0")};
${(props) =>
props.withoutBodyScroll &&
props.currentDisplayType === "aside" &&
css`
padding-bottom: 8px;
height: 100%;
min-height: auto;
`}
`;
export { CloseButton, StyledHeader, Content, Dialog, BodyBox };
const StyledFooter = styled.div`
display: flex;
flex-direction: row;
${(props) =>
props.withFooterBorder &&
`border-top: 1px solid ${props.theme.modalDialog.headerBorderColor}`};
padding: 16px;
gap: 8px;
@media ${tablet} {
gap: 10px;
}
`;
Dialog.defaultProps = { theme: Base };
StyledHeader.defaultProps = { theme: Base };
Content.defaultProps = { theme: Base };
export { StyledModal, StyledHeader, Content, Dialog, StyledBody, StyledFooter };

View File

@ -0,0 +1,156 @@
import React from "react";
import PropTypes from "prop-types";
import Loaders from "@appserver/common/components/Loaders";
import Heading from "../../heading";
import {
StyledModal,
StyledHeader,
Content,
Dialog,
StyledBody,
StyledFooter,
} from "../styled-modal-dialog";
import CloseButton from "../components/CloseButton";
import ModalBackdrop from "../components/ModalBackdrop";
import Scrollbar from "../../scrollbar";
const Modal = ({
id,
style,
className,
currentDisplayType,
withBodyScroll,
isLarge,
zIndex,
autoMaxHeight,
autoMaxWidth,
onClose,
isLoading,
header,
body,
footer,
visible,
withFooterBorder,
modalSwipeOffset,
}) => {
const headerComponent = header ? header.props.children : null;
const bodyComponent = body ? body.props.children : null;
const footerComponent = footer ? footer.props.children : null;
return (
<StyledModal
className={visible ? "modal-active" : ""}
modalSwipeOffset={modalSwipeOffset}
>
<ModalBackdrop
className={visible ? "modal-backdrop-active" : ""}
visible={true}
zIndex={zIndex}
modalSwipeOffset={modalSwipeOffset}
>
<Dialog
className={`${className} dialog not-selectable`}
currentDisplayType={currentDisplayType}
id={id}
style={style}
onClick={onClose}
>
<Content
id="modal-dialog"
visible={visible}
isLarge={isLarge}
currentDisplayType={currentDisplayType}
autoMaxHeight={autoMaxHeight}
autoMaxWidth={autoMaxWidth}
modalSwipeOffset={modalSwipeOffset}
onClick={(e) => e.stopPropagation()}
>
<CloseButton
currentDisplayType={currentDisplayType}
onClick={onClose}
/>
{isLoading ? (
currentDisplayType === "modal" ? (
<Loaders.DialogLoader
isLarge={isLarge}
withFooterBorder={withFooterBorder}
/>
) : (
<Loaders.DialogAsideLoader
withoutAside
withFooterBorder={withFooterBorder}
/>
)
) : (
<>
{header && (
<StyledHeader
id="modal-header-swipe"
currentDisplayType={currentDisplayType}
{...header.props}
>
<Heading
level={1}
className={"heading"}
size="medium"
truncate={true}
>
{headerComponent}
</Heading>
</StyledHeader>
)}
{body && (
<StyledBody
withBodyScroll={withBodyScroll}
hasFooter={1 && footer}
currentDisplayType={currentDisplayType}
{...body.props}
>
{currentDisplayType === "aside" && withBodyScroll ? (
<Scrollbar stype="mediumBlack">{bodyComponent}</Scrollbar>
) : (
bodyComponent
)}
</StyledBody>
)}
{footer && (
<StyledFooter
withFooterBorder={withFooterBorder}
currentDisplayType={currentDisplayType}
{...footer.props}
>
{footerComponent}
</StyledFooter>
)}
</>
)}
</Content>
</Dialog>
</ModalBackdrop>
</StyledModal>
);
};
Modal.propTypes = {
id: PropTypes.string,
className: PropTypes.string,
zIndex: PropTypes.number,
style: PropTypes.oneOfType([PropTypes.object, PropTypes.array]),
onClose: PropTypes.func,
visible: PropTypes.bool,
modalSwipeOffset: PropTypes.number,
isLoading: PropTypes.bool,
modalLoaderBodyHeight: PropTypes.string,
currentDisplayType: PropTypes.oneOf(["auto", "modal", "aside"]),
isLarge: PropTypes.bool,
header: PropTypes.object,
body: PropTypes.object,
footer: PropTypes.object,
};
export default Modal;

View File

@ -570,6 +570,10 @@ const Base = {
},
modalDialog: {
backgroundColor: white,
textColor: black,
headerBorderColor: globalColors.grayLightMid,
footerBorderColor: globalColors.grayLightMid,
width: "auto",
maxwidth: "560px",
margin: " 0 auto",
@ -598,14 +602,8 @@ const Base = {
},
closeButton: {
width: "14px",
height: "14px",
minWidth: "14px",
minHeight: "14px",
right: "16px",
top: "13px",
hoverColor: grayMain,
//backgroundColor: "#9a9ea3",
fillColor: white,
},
},
@ -868,6 +866,10 @@ const Base = {
span: { maxWidth: "300px" },
expander: {
iconColor: black,
},
caret: {
width: "5px",
minWidth: "5px",
@ -1926,7 +1928,7 @@ const Base = {
header: {
backgroundColor: "#0F4071",
recoveryColor: "#27537F",
linkColor: "#7a95b0",
productColor: white,
},
@ -2233,6 +2235,14 @@ const Base = {
},
},
connectCloud: {
connectBtnContent: black,
connectBtnTextBg: white,
connectBtnIconBg: white,
connectBtnTextBorder: grayMid,
connectBtnIconBorder: grayMid,
},
filesThirdPartyDialog: {
border: "1px solid #d1d1d1",
},

View File

@ -567,6 +567,10 @@ const Dark = {
},
modalDialog: {
backgroundColor: black,
textColor: white,
headerBorderColor: "#474747",
footerBorderColor: "#474747",
width: "auto",
maxwidth: "560px",
margin: " 0 auto",
@ -596,14 +600,8 @@ const Dark = {
},
closeButton: {
width: "14px",
height: "14px",
minWidth: "14px",
minHeight: "14px",
right: "16px",
top: "13px",
hoverColor: grayMaxLight,
//backgroundColor: "#9A9EA3",
fillColor: "#9A9EA3",
},
},
@ -865,6 +863,10 @@ const Dark = {
span: { maxWidth: "300px" },
expander: {
iconColor: white,
},
caret: {
width: "5px",
minWidth: "5px",
@ -1926,7 +1928,7 @@ const Dark = {
header: {
backgroundColor: "#1f1f1f ",
recoveryColor: "#4C4C4C",
linkColor: "#606060",
productColor: "#eeeeee",
},
@ -2241,6 +2243,14 @@ const Dark = {
},
},
connectCloud: {
connectBtnContent: silver,
connectBtnTextBg: "none",
connectBtnIconBg: "#none",
connectBtnTextBorder: silver,
connectBtnIconBorder: "#474747",
},
filesThirdPartyDialog: {
border: "1px solid #474747",
},

View File

@ -1,6 +1,6 @@
export const size = {
mobile: 375,
hugeMobile: 414,
hugeMobile: 428,
smallTablet: 600,
tablet: 1024,
desktop: 1025,

View File

@ -4,8 +4,8 @@
<AppendTargetFrameworkToOutputPath>false</AppendTargetFrameworkToOutputPath>
</PropertyGroup>
<ItemGroup>
<PackageReference Include="StackExchange.Redis.Extensions.AspNetCore" Version="7.2.1" />
<PackageReference Include="StackExchange.Redis.Extensions.Newtonsoft" Version="7.2.1" />
<PackageReference Include="StackExchange.Redis.Extensions.AspNetCore" Version="8.0.4" />
<PackageReference Include="StackExchange.Redis.Extensions.Newtonsoft" Version="8.0.4" />
</ItemGroup>
<ItemGroup>
<ProjectReference Include="..\Server\ASC.CRM.csproj" />

View File

@ -1,4 +1,30 @@
using System.Collections.Generic;
// (c) Copyright Ascensio System SIA 2010-2022
//
// This program is a free software product.
// You can redistribute it and/or modify it under the terms
// of the GNU Affero General Public License (AGPL) version 3 as published by the Free Software
// Foundation. In accordance with Section 7(a) of the GNU AGPL its Section 15 shall be amended
// to the effect that Ascensio System SIA expressly excludes the warranty of non-infringement of
// any third-party rights.
//
// This program is distributed WITHOUT ANY WARRANTY, without even the implied warranty
// of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. For details, see
// the GNU AGPL at: http://www.gnu.org/licenses/agpl-3.0.html
//
// You can contact Ascensio System SIA at Lubanas st. 125a-25, Riga, Latvia, EU, LV-1021.
//
// The interactive user interfaces in modified source and object code versions of the Program must
// display Appropriate Legal Notices, as required under Section 5 of the GNU AGPL version 3.
//
// Pursuant to Section 7(b) of the License you must retain the original Product logo when
// distributing the program. Pursuant to Section 7(e) we decline to grant you any rights under
// trademark law for use of our trademarks.
//
// All the Product's GUI elements, including illustrations and icon sets, as well as technical writing
// content are licensed under the terms of the Creative Commons Attribution-ShareAlike 4.0
// International. See the License terms at http://creativecommons.org/licenses/by-sa/4.0/legalcode
using System.Collections.Generic;
using System.IO;
using System.Threading.Tasks;
@ -7,7 +33,6 @@ using ASC.Common;
using ASC.Common.Caching;
using ASC.Common.DependencyInjection;
using ASC.Common.Utils;
using ASC.ElasticSearch;
using ASC.Web.CRM.Core.Search;
using Autofac;
@ -24,7 +49,7 @@ namespace ASC.CRM.BackgroundTasks
{
class Program
{
public async static Task Main(string[] args)
public static async Task Main(string[] args)
{
var host = CreateHostBuilder(args).Build();
@ -79,7 +104,7 @@ namespace ASC.CRM.BackgroundTasks
if (kafkaConfiguration != null)
{
diHelper.TryAdd(typeof(ICacheNotify<>), typeof(KafkaCache<>));
diHelper.TryAdd(typeof(ICacheNotify<>), typeof(KafkaCacheNotify<>));
}
else if (rabbitMQConfiguration != null)
{
@ -87,7 +112,7 @@ namespace ASC.CRM.BackgroundTasks
}
else if (redisConfiguration != null)
{
diHelper.TryAdd(typeof(ICacheNotify<>), typeof(RedisCache<>));
diHelper.TryAdd(typeof(ICacheNotify<>), typeof(RedisCacheNotify<>));
services.AddStackExchangeRedisExtensions<NewtonsoftSerializer>(redisConfiguration);
}
@ -98,8 +123,8 @@ namespace ASC.CRM.BackgroundTasks
diHelper.RegisterProducts(hostContext.Configuration, hostContext.HostingEnvironment.ContentRootPath);
services.AddHostedService<ServiceLauncher>();
diHelper.TryAdd<ServiceLauncher>();
//services.AddHostedService<ServiceLauncher>();
//diHelper.TryAdd<ServiceLauncher>();
diHelper.TryAdd<FactoryIndexerCase>();
diHelper.TryAdd<FactoryIndexerContact>();
diHelper.TryAdd<FactoryIndexerContactInfo>();

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