Skip to content

Commit

Permalink
Merge hotfix/v2.0.4 into master
Browse files Browse the repository at this point in the history
  • Loading branch information
agolybev authored Mar 4, 2024
2 parents c87994d + 28a2084 commit 8cbc434
Show file tree
Hide file tree
Showing 17 changed files with 134 additions and 22 deletions.
5 changes: 3 additions & 2 deletions common/ASC.Api.Core/Core/BaseStartup.cs
Original file line number Diff line number Diff line change
Expand Up @@ -236,7 +236,8 @@ bool EnableNoLimiter(IPAddress address)
{
var userId = httpContext?.User?.Claims.FirstOrDefault(x => x.Type == ClaimTypes.Sid)?.Value;
var permitLimit = 5;
var partitionKey = $"sensitive_api_{userId}";
var path = httpContext.Request.Path.ToString();
var partitionKey = $"sensitive_api_{userId}|{path}";
var remoteIpAddress = httpContext?.Connection.RemoteIpAddress;

if (EnableNoLimiter(remoteIpAddress))
Expand All @@ -247,7 +248,7 @@ bool EnableNoLimiter(IPAddress address)
return RedisRateLimitPartition.GetSlidingWindowRateLimiter(partitionKey, _ => new RedisSlidingWindowRateLimiterOptions
{
PermitLimit = permitLimit,
Window = TimeSpan.FromMinutes(1),
Window = TimeSpan.FromMinutes(15),
ConnectionMultiplexerFactory = () => connectionMultiplexer
});
});
Expand Down
5 changes: 5 additions & 0 deletions common/ASC.Core.Common/Caching/CachedTenantService.cs
Original file line number Diff line number Diff line change
Expand Up @@ -190,6 +190,11 @@ public async Task ValidateDomainAsync(string domain)
await _service.ValidateDomainAsync(domain);
}

public void ValidateTenantName(string name)
{
_service.ValidateTenantName(name);
}

public async Task<IEnumerable<Tenant>> GetTenantsAsync(string login, string passwordHash)
{
return await _service.GetTenantsAsync(login, passwordHash);
Expand Down
5 changes: 5 additions & 0 deletions common/ASC.Core.Common/Context/Impl/TenantManager.cs
Original file line number Diff line number Diff line change
Expand Up @@ -445,4 +445,9 @@ public async Task<List<TenantQuotaRow>> FindTenantQuotaRowsAsync(int tenantId)
{
return (await QuotaService.FindTenantQuotaRowsAsync(tenantId)).ToList();
}

public void ValidateTenantName(string name)
{
TenantService.ValidateTenantName(name);
}
}
1 change: 1 addition & 0 deletions common/ASC.Core.Common/Core/ITenantService.cs
Original file line number Diff line number Diff line change
Expand Up @@ -48,4 +48,5 @@ public interface ITenantService
Task PermanentlyRemoveTenantAsync(int id);
void SetTenantSettings(int tenant, string key, byte[] data);
Task ValidateDomainAsync(string domain);
void ValidateTenantName(string name);
}
7 changes: 6 additions & 1 deletion common/ASC.Core.Common/Data/DbTenantService.cs
Original file line number Diff line number Diff line change
Expand Up @@ -59,7 +59,12 @@ public async Task ValidateDomainAsync(string domain)
// using var tr = TenantDbContext.Database.BeginTransaction();
await ValidateDomainAsync(domain, Tenant.DefaultTenant, true);
}


public void ValidateTenantName(string name)
{
_tenantDomainValidator.ValidateTenantName(name);
}

public IEnumerable<Tenant> GetTenantsWithCsp()
{
var cspSettingsId = new CspSettings().ID;
Expand Down
6 changes: 5 additions & 1 deletion common/ASC.Core.Common/GeolocationHelper.cs
Original file line number Diff line number Diff line change
Expand Up @@ -67,7 +67,11 @@ public async Task<string[]> GetGeolocationAsync(string ip)
{
try
{
var location = await GetIPGeolocationAsync(IPAddress.Parse(ip));
if (!IPAddress.TryParse(ip, out var address))
{
return new[] { string.Empty, string.Empty };
}
var location = await GetIPGeolocationAsync(address);
if (string.IsNullOrEmpty(location.Key) || (location.Key == "ZZ"))
{
return new[] { string.Empty, string.Empty };
Expand Down
2 changes: 2 additions & 0 deletions common/ASC.Core.Common/HostedSolution.cs
Original file line number Diff line number Diff line change
Expand Up @@ -128,6 +128,8 @@ public async Task<Tenant> RegisterTenantAsync(TenantRegistrationInfo registratio
registrationInfo.PasswordHash = Guid.NewGuid().ToString();
}

TenantService.ValidateTenantName(registrationInfo.Name);

// create tenant
var tenant = new Tenant(registrationInfo.Address.ToLowerInvariant())
{
Expand Down
17 changes: 16 additions & 1 deletion common/ASC.Core.Common/Tenants/TenantDomainValidator.cs
Original file line number Diff line number Diff line change
Expand Up @@ -30,12 +30,13 @@ namespace ASC.Core.Tenants;
public class TenantDomainValidator
{
private readonly Regex _validDomain;
private readonly Regex _validName;

public string Regex { get; }
public int MinLength { get; }
public int MaxLength { get; }

public TenantDomainValidator(IConfiguration configuration)
public TenantDomainValidator(IConfiguration configuration, CoreBaseSettings coreBaseSettings)
{
MaxLength = 100;

Expand All @@ -60,6 +61,12 @@ public TenantDomainValidator(IConfiguration configuration)
}

_validDomain = new Regex(Regex, RegexOptions.Compiled | RegexOptions.CultureInvariant | RegexOptions.IgnoreCase);

var nameRegexpFromConfig = configuration["core:tenantname:regex"];
if (!coreBaseSettings.Standalone && !string.IsNullOrEmpty(nameRegexpFromConfig))
{
_validName = new Regex(nameRegexpFromConfig, RegexOptions.Compiled | RegexOptions.CultureInvariant | RegexOptions.IgnoreCase);
}
}

public void ValidateDomainLength(string domain)
Expand All @@ -78,4 +85,12 @@ public void ValidateDomainCharacters(string domain)
throw new TenantIncorrectCharsException("Domain contains invalid characters.");
}
}

public void ValidateTenantName(string name)
{
if (!string.IsNullOrEmpty(name) && _validName != null && !_validName.IsMatch(name))
{
throw new TenantIncorrectCharsException("Name contains invalid characters.");
}
}
}
2 changes: 1 addition & 1 deletion common/ASC.MessagingSystem/Core/MessageSettings.cs
Original file line number Diff line number Diff line change
Expand Up @@ -67,7 +67,7 @@ public static string GetReferer(IDictionary<string, StringValues> headers)

public static string GetIP(HttpRequest request)
{
return request.HttpContext.Connection.RemoteIpAddress?.ToString();
return request?.HttpContext?.Connection.RemoteIpAddress?.ToString();
}

public static void AddInfoMessage(EventMessage message, Dictionary<string, ClientInfo> dict = null)
Expand Down
25 changes: 20 additions & 5 deletions common/ASC.MessagingSystem/Data/MessagesRepository.cs
Original file line number Diff line number Diff line change
Expand Up @@ -81,6 +81,8 @@ public async Task<int> AddAsync(EventMessage message)
{
if (ForseSave(message))
{
_logger.LogDebug("ForseSave: {action}", message.Action.ToStringFast());

int id;
if (!string.IsNullOrEmpty(message.UAHeader))
{
Expand Down Expand Up @@ -109,12 +111,13 @@ public async Task<int> AddAsync(EventMessage message)
}

var now = DateTime.UtcNow;
var key = string.Format("{0}|{1}|{2}|{3}", message.TenantId, message.UserId, message.Id, now.Ticks);

await _semaphore.WaitAsync();
var key = $"{message.TenantId}|{message.UserId}|{message.Id}|{now.Ticks}";
_logger.LogDebug("AddToCache: {key}, semaphore current {CurrentCount}", key, _semaphore.CurrentCount);

try
{
await _semaphore.WaitAsync();
_cache[key] = message;

if (!_timerStarted)
Expand All @@ -140,21 +143,28 @@ private async Task FlushCacheAsync()

if (DateTime.UtcNow > _lastSave.Add(_cacheTime) || _cache.Count > _cacheLimit)
{
lock (_cache)
try
{
await _semaphore.WaitAsync();
_timer.Change(-1, -1);
_timerStarted = false;

events = new List<EventMessage>(_cache.Values);
_cache.Clear();
_lastSave = DateTime.UtcNow;
}
finally
{
_semaphore.Release();
}
}

if (events == null)
{
return;
}

_logger.LogDebug("FlushCache: events count {Count}", events.Count);

using var scope = _serviceScopeFactory.CreateScope();
await using var ef = await scope.ServiceProvider.GetService<IDbContextFactory<MessagesContext>>().CreateDbContextAsync();
Expand Down Expand Up @@ -209,15 +219,20 @@ private void FlushCache()
{
List<EventMessage> events;

lock (_cache)
try
{
_semaphore.Wait();
_timer.Change(-1, -1);
_timerStarted = false;

events = new List<EventMessage>(_cache.Values);
_cache.Clear();
_lastSave = DateTime.UtcNow;
}
finally
{
_semaphore.Release();
}

using var scope = _serviceScopeFactory.CreateScope();
using var ef = scope.ServiceProvider.GetService<IDbContextFactory<MessagesContext>>().CreateDbContext();
Expand Down
18 changes: 15 additions & 3 deletions products/ASC.Files/Core/Configuration/ProductEntryPoint.cs
Original file line number Diff line number Diff line change
Expand Up @@ -45,6 +45,7 @@ public class ProductEntryPoint : Product
private readonly CommonLinkUtility _commonLinkUtility;
private readonly FileSecurity _fileSecurity;
private readonly GlobalFolder _globalFolder;
private readonly ILogger<ProductEntryPoint> _logger;

//public SubscriptionManager SubscriptionManager { get; }

Expand All @@ -64,7 +65,8 @@ public ProductEntryPoint(
FilesLinkUtility filesLinkUtility,
FileSecurity fileSecurity,
GlobalFolder globalFolder,
CommonLinkUtility commonLinkUtility
CommonLinkUtility commonLinkUtility,
ILogger<ProductEntryPoint> logger
// SubscriptionManager subscriptionManager
)
{
Expand All @@ -82,6 +84,7 @@ CommonLinkUtility commonLinkUtility
_fileSecurity = fileSecurity;
_globalFolder = globalFolder;
_commonLinkUtility = commonLinkUtility;
_logger = logger;
//SubscriptionManager = subscriptionManager;
}

Expand Down Expand Up @@ -203,8 +206,17 @@ public override async Task<IEnumerable<ActivityInfo>> GetAuditEventsAsync(DateTi
activityInfo.FileUrl = _commonLinkUtility.GetFullAbsolutePath(_filesLinkUtility.GetFileWebEditorUrl(e.Target.GetItems().FirstOrDefault()));
}

var obj = e.Description.LastOrDefault();
var additionalInfo = JsonSerializer.Deserialize<AdditionalNotificationInfo>(obj);
AdditionalNotificationInfo additionalInfo;

try
{
additionalInfo = JsonSerializer.Deserialize<AdditionalNotificationInfo>(e.Description.LastOrDefault());
}
catch (Exception ex)
{
_logger.ErrorDeserializingAuditEvent(e.Id, ex);
continue;
}

activityInfo.TargetUsers = additionalInfo.UserIds;

Expand Down
2 changes: 1 addition & 1 deletion products/ASC.Files/Core/Core/FileStorageService.cs
Original file line number Diff line number Diff line change
Expand Up @@ -1221,7 +1221,7 @@ public async Task<string> UpdateCommentAsync<T>(T fileId, int version, string co

comment = await fileDao.UpdateCommentAsync(fileId, version, comment);

await _filesMessageService.SendAsync(MessageAction.FileUpdatedRevisionComment, file, file.Title, version.ToString(CultureInfo.InvariantCulture));
await _filesMessageService.SendAsync(MessageAction.FileUpdatedRevisionComment, file, new[] { file.Title, version.ToString(CultureInfo.InvariantCulture) });

return comment;
}
Expand Down
32 changes: 32 additions & 0 deletions products/ASC.Files/Core/Log/ProductEntryPointLogger.cs
Original file line number Diff line number Diff line change
@@ -0,0 +1,32 @@
// (c) Copyright Ascensio System SIA 2010-2023
//
// 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.Files.Core.Log;
internal static partial class ProductEntryPointLogger
{
[LoggerMessage(Level = LogLevel.Error, Message = "Error while deserializing audit event: {eventId}")]
public static partial void ErrorDeserializingAuditEvent(this ILogger<ProductEntryPoint> logger, int eventId, Exception exception);
}
6 changes: 4 additions & 2 deletions products/ASC.Files/Server/ProductEntryPoint.cs
Original file line number Diff line number Diff line change
Expand Up @@ -51,7 +51,8 @@ public ApiProductEntryPoint(
FilesLinkUtility filesLinkUtility,
FileSecurity fileSecurity,
GlobalFolder globalFolder,
CommonLinkUtility commonLinkUtility
CommonLinkUtility commonLinkUtility,
ILogger<ProductEntryPoint> logger
//SubscriptionManager subscriptionManager
) : base(filesSpaceUsageStatManager,
coreBaseSettings,
Expand All @@ -66,7 +67,8 @@ CommonLinkUtility commonLinkUtility
filesLinkUtility,
fileSecurity,
globalFolder,
commonLinkUtility)
commonLinkUtility,
logger)
{

}
Expand Down
2 changes: 1 addition & 1 deletion products/ASC.People/Server/Api/UserController.cs
Original file line number Diff line number Diff line change
Expand Up @@ -412,7 +412,6 @@ public async Task<List<EmployeeDto>> InviteUsersAsync(InviteUsersRequestDto inDt
/// <path>api/2.0/people/{userid}/password</path>
/// <httpMethod>PUT</httpMethod>
[HttpPut("{userid}/password")]
[EnableRateLimiting("sensitive_api")]
[Authorize(AuthenticationSchemes = "confirm", Roles = "PasswordChange,EmailChange,Activation,EmailActivation,Everyone")]
public async Task<EmployeeFullDto> ChangeUserPassword(Guid userid, MemberRequestDto inDto)
{
Expand Down Expand Up @@ -1183,6 +1182,7 @@ public async Task<EmployeeFullDto> SelfAsync()
/// <httpMethod>POST</httpMethod>
[AllowNotPayment]
[HttpPost("email")]
[EnableRateLimiting("sensitive_api")]
public async Task<object> SendEmailChangeInstructionsAsync(UpdateMemberRequestDto inDto)
{
Guid.TryParse(inDto.UserId, out var userid);
Expand Down
13 changes: 13 additions & 0 deletions web/ASC.Web.Api/Api/Settings/GreetingSettingsController.cs
Original file line number Diff line number Diff line change
Expand Up @@ -32,6 +32,7 @@ public class GreetingSettingsController : BaseSettingsController
private readonly TenantManager _tenantManager;
private readonly PermissionContext _permissionContext;
private readonly TenantInfoSettingsHelper _tenantInfoSettingsHelper;
private readonly CoreBaseSettings _coreBaseSettings;

public GreetingSettingsController(
TenantInfoSettingsHelper tenantInfoSettingsHelper,
Expand All @@ -41,12 +42,14 @@ public GreetingSettingsController(
PermissionContext permissionContext,
WebItemManager webItemManager,
IMemoryCache memoryCache,
CoreBaseSettings coreBaseSettings,
IHttpContextAccessor httpContextAccessor) : base(apiContext, memoryCache, webItemManager, httpContextAccessor)
{
_tenantInfoSettingsHelper = tenantInfoSettingsHelper;
_messageService = messageService;
_tenantManager = tenantManager;
_permissionContext = permissionContext;
_coreBaseSettings = coreBaseSettings;
}

/// <summary>
Expand Down Expand Up @@ -94,6 +97,16 @@ public async Task<object> SaveGreetingSettingsAsync(GreetingSettingsRequestsDto
await _permissionContext.DemandPermissionsAsync(SecurityConstants.EditPortalSettings);

var tenant = await _tenantManager.GetCurrentTenantAsync();

if (!_coreBaseSettings.Standalone)
{
var quota = await _tenantManager.GetTenantQuotaAsync(tenant.Id);
if (quota.Free || quota.Trial)
{
_tenantManager.ValidateTenantName(inDto.Title);
}
}

tenant.Name = inDto.Title;
await _tenantManager.SaveTenantAsync(tenant);

Expand Down
8 changes: 4 additions & 4 deletions web/ASC.Web.Core/Notify/StudioPeriodicNotify.cs
Original file line number Diff line number Diff line change
Expand Up @@ -379,8 +379,8 @@ await client.SendNoticeToAsync(
new TagValue(Tags.ActiveUsers, (await _userManager.GetUsersAsync()).Length),
new TagValue(Tags.Price, rquota.Price),
new TagValue(Tags.PricePeriod, UserControlsCommonResource.TariffPerMonth),
new TagValue(Tags.DueDate, dueDate.ToLongDateString()),
new TagValue(Tags.DelayDueDate, (delayDueDateIsNotMax ? delayDueDate : dueDate).ToLongDateString()),
//new TagValue(Tags.DueDate, dueDate.ToLongDateString()),
//new TagValue(Tags.DelayDueDate, (delayDueDateIsNotMax ? delayDueDate : dueDate).ToLongDateString()),
TagValues.OrangeButton(orangeButtonText(culture), orangeButtonUrl),
TagValues.TrulyYours(_studioNotifyHelper, txtTrulyYours(culture)),
new TagValue("IMG1", img1),
Expand Down Expand Up @@ -525,8 +525,8 @@ await client.SendNoticeToAsync(
new TagValue(Tags.ActiveUsers, (await _userManager.GetUsersAsync()).Length),
new TagValue(Tags.Price, rquota.Price),
new TagValue(Tags.PricePeriod, UserControlsCommonResource.TariffPerMonth),
new TagValue(Tags.DueDate, dueDate.ToLongDateString()),
new TagValue(Tags.DelayDueDate, (delayDueDateIsNotMax ? delayDueDate : dueDate).ToLongDateString()),
//new TagValue(Tags.DueDate, dueDate.ToLongDateString()),
//new TagValue(Tags.DelayDueDate, (delayDueDateIsNotMax ? delayDueDate : dueDate).ToLongDateString()),
TagValues.OrangeButton(orangeButtonText(culture), orangeButtonUrl),
TagValues.TrulyYours(_studioNotifyHelper, txtTrulyYours(culture)),
new TagValue("IMG1", img1),
Expand Down

0 comments on commit 8cbc434

Please sign in to comment.