diff --git a/build/install/docker/Dockerfile.app b/build/install/docker/Dockerfile.app index 729a574c6e..ebbfa661c8 100644 --- a/build/install/docker/Dockerfile.app +++ b/build/install/docker/Dockerfile.app @@ -169,17 +169,21 @@ RUN chown nginx:nginx /etc/nginx/* -R && \ ## Doceditor ## FROM noderun as doceditor -WORKDIR ${BUILD_PATH}/products/ASC.Files/editor +WORKDIR ${BUILD_PATH}/products/ASC.Editors/editor +COPY --chown=onlyoffice:onlyoffice docker-entrypoint.py ./docker-entrypoint.py COPY --from=base --chown=onlyoffice:onlyoffice ${SRC_PATH}/build/deploy/editor/ . -ENTRYPOINT ["node", "server.js"] + +CMD ["server.js", "ASC.Editors"] ## Login ## FROM noderun as login WORKDIR ${BUILD_PATH}/products/ASC.Login/login +COPY --chown=onlyoffice:onlyoffice docker-entrypoint.py ./docker-entrypoint.py COPY --from=base --chown=onlyoffice:onlyoffice ${SRC_PATH}/build/deploy/login/ . -ENTRYPOINT ["node", "server.js"] + +CMD ["server.js", "ASC.Login"] ## ASC.Data.Backup.BackgroundTasks ## FROM dotnetrun AS backup_background diff --git a/common/ASC.ActiveDirectory/Base/LdapUserImporter.cs b/common/ASC.ActiveDirectory/Base/LdapUserImporter.cs index 2350874841..ea41fe2f09 100644 --- a/common/ASC.ActiveDirectory/Base/LdapUserImporter.cs +++ b/common/ASC.ActiveDirectory/Base/LdapUserImporter.cs @@ -364,7 +364,7 @@ public class LdapUserImporter : IDisposable return result; } - public bool TrySyncUserGroupMembership(Tuple ldapUserInfo) + public async Task TrySyncUserGroupMembership(Tuple ldapUserInfo) { if (ldapUserInfo == null || !Settings.GroupMembership) @@ -401,12 +401,12 @@ public class LdapUserImporter : IDisposable groupInfo = UserManager.SaveGroupInfo(_ldapObjectExtension.ToGroupInfo(ldapUserGroup, Settings)); _logger.DebugTrySyncUserGroupMembershipAddingUserToGroup(userInfo.UserName, ldapUser.Sid, groupInfo.Name, groupInfo.Sid); - UserManager.AddUserIntoGroup(userInfo.Id, groupInfo.ID); + await UserManager.AddUserIntoGroup(userInfo.Id, groupInfo.ID); } else if (!portalUserLdapGroups.Contains(groupInfo)) { _logger.DebugTrySyncUserGroupMembershipAddingUserToGroup(userInfo.UserName, ldapUser.Sid, groupInfo.Name, groupInfo.Sid); - UserManager.AddUserIntoGroup(userInfo.Id, groupInfo.ID); + await UserManager.AddUserIntoGroup(userInfo.Id, groupInfo.ID); } actualPortalLdapGroups.Add(groupInfo); diff --git a/common/ASC.ActiveDirectory/ComplexOperations/LdapOperationJob.cs b/common/ASC.ActiveDirectory/ComplexOperations/LdapOperationJob.cs index e9ac29f963..4d4a24c410 100644 --- a/common/ASC.ActiveDirectory/ComplexOperations/LdapOperationJob.cs +++ b/common/ASC.ActiveDirectory/ComplexOperations/LdapOperationJob.cs @@ -136,7 +136,7 @@ public class LdapOperationJob : DistributedTaskProgress InitDisturbedTask(); } - protected override void DoJob() + protected override async Task DoJob() { try { @@ -206,7 +206,7 @@ public class LdapOperationJob : DistributedTaskProgress default: throw new ArgumentOutOfRangeException(); } - Do(); + await Do(); } catch (AuthorizingException authError) { @@ -247,7 +247,7 @@ public class LdapOperationJob : DistributedTaskProgress } } - private void Do() + private async Task Do() { try { @@ -288,7 +288,7 @@ public class LdapOperationJob : DistributedTaskProgress _logger.DebugLdapSettings(sb.ToString()); } - SyncLDAP(); + await SyncLDAP(); if (!string.IsNullOrEmpty(Error)) { @@ -380,7 +380,7 @@ public class LdapOperationJob : DistributedTaskProgress _logger.DebugSaveUserInfo(existingLDAPUser.GetUserInfoString()); - _userManager.SaveUserInfo(existingLDAPUser); + _userManager.UpdateUserInfo(existingLDAPUser); break; case LdapOperationType.SaveTest: case LdapOperationType.SyncTest: @@ -394,7 +394,7 @@ public class LdapOperationJob : DistributedTaskProgress } } - private void SyncLDAP() + private async Task SyncLDAP() { var currentDomainSettings = _settingsManager.Load(); @@ -408,21 +408,21 @@ public class LdapOperationJob : DistributedTaskProgress { _logger.DebugSyncLDAPUsers(); - SyncLDAPUsers(); + await SyncLDAPUsers(); } else { _logger.DebugSyncLDAPUsersInGroups(); - SyncLDAPUsersInGroups(); + await SyncLDAPUsersInGroups(); } - SyncLdapAvatar(); + await SyncLdapAvatar(); - SyncLdapAccessRights(); + await SyncLdapAccessRights(); } - private void SyncLdapAvatar() + private async Task SyncLdapAvatar() { SetProgress(90, Resource.LdapSettingsStatusUpdatingUserPhotos); @@ -438,7 +438,7 @@ public class LdapOperationJob : DistributedTaskProgress foreach (var guid in ph.CurrentPhotos.Keys) { _logger.InfoSyncLdapAvatarsRemovingPhoto(guid); - _userPhotoManager.RemovePhoto(guid); + await _userPhotoManager.RemovePhoto(guid); _userPhotoManager.ResetThumbnailSettings(guid); } @@ -511,16 +511,16 @@ public class LdapOperationJob : DistributedTaskProgress _settingsManager.Save(photoSettings); } - private void SyncLdapAccessRights() + private async Task SyncLdapAccessRights() { SetProgress(95, Resource.LdapSettingsStatusUpdatingAccessRights); var currentUserRights = new List(); - TakeUsersRights(_currentUser != null ? currentUserRights : null); + await TakeUsersRights(_currentUser != null ? currentUserRights : null); if (LDAPSettings.GroupMembership && LDAPSettings.AccessRights != null && LDAPSettings.AccessRights.Count > 0) { - GiveUsersRights(LDAPSettings.AccessRights, _currentUser != null ? currentUserRights : null); + await GiveUsersRights(LDAPSettings.AccessRights, _currentUser != null ? currentUserRights : null); } if (currentUserRights.Count > 0) @@ -531,7 +531,7 @@ public class LdapOperationJob : DistributedTaskProgress _settingsManager.Save(LDAPSettings); } - private void TakeUsersRights(List currentUserRights) + private async Task TakeUsersRights(List currentUserRights) { var current = _settingsManager.Load(); @@ -558,7 +558,7 @@ public class LdapOperationJob : DistributedTaskProgress else { _logger.DebugTakingAdminRights(right.Key, user); - _webItemSecurity.SetProductAdministrator(LdapSettings.AccessRightsGuids[right.Key], userId, false); + await _webItemSecurity.SetProductAdministrator(LdapSettings.AccessRightsGuids[right.Key], userId, false); } } } @@ -567,7 +567,7 @@ public class LdapOperationJob : DistributedTaskProgress _settingsManager.Save(current); } - private void GiveUsersRights(Dictionary accessRightsSettings, List currentUserRights) + private async Task GiveUsersRights(Dictionary accessRightsSettings, List currentUserRights) { var current = _settingsManager.Load(); var currentAccessRights = new Dictionary>(); @@ -618,7 +618,7 @@ public class LdapOperationJob : DistributedTaskProgress if (_webItemSecurity.IsProductAdministrator(prodId, user.Id)) { cleared = true; - _webItemSecurity.SetProductAdministrator(prodId, user.Id, false); + await _webItemSecurity.SetProductAdministrator(prodId, user.Id, false); } } @@ -636,7 +636,7 @@ public class LdapOperationJob : DistributedTaskProgress SetProgress((int)currentPercent, string.Format(Resource.LdapSettingsStatusGivingRights, _userFormatter.GetUserName(user, DisplayUserNameFormat.Default), access.Key)); - _webItemSecurity.SetProductAdministrator(LdapSettings.AccessRightsGuids[access.Key], user.Id, true); + await _webItemSecurity.SetProductAdministrator(LdapSettings.AccessRightsGuids[access.Key], user.Id, true); if (currentUserRights != null && currentUserRights.Contains(access.Key)) { @@ -651,7 +651,7 @@ public class LdapOperationJob : DistributedTaskProgress _settingsManager.Save(current); } - private void SyncLDAPUsers() + private async Task SyncLDAPUsers() { SetProgress(15, Resource.LdapSettingsStatusGettingUsersFromLdap); @@ -675,14 +675,14 @@ public class LdapOperationJob : DistributedTaskProgress : Resource.LdapSettingsStatusSyncingUsers, ""); - SyncDbUsers(ldapUsers); + await SyncDbUsers(ldapUsers); SetProgress(70, Resource.LdapSettingsStatusRemovingOldGroups, ""); RemoveOldDbGroups(new List()); // Remove all db groups with sid } - private void SyncLDAPUsersInGroups() + private async Task SyncLDAPUsersInGroups() { SetProgress(15, Resource.LdapSettingsStatusGettingGroupsFromLdap); @@ -717,11 +717,11 @@ public class LdapOperationJob : DistributedTaskProgress : Resource.LdapSettingsStatusSyncingUsers, ""); - var newUniqueLdapGroupUsers = SyncGroupsUsers(uniqueLdapGroupUsers); + var newUniqueLdapGroupUsers = await SyncGroupsUsers(uniqueLdapGroupUsers); SetProgress(60, Resource.LdapSettingsStatusSavingGroups, ""); - SyncDbGroups(ldapGroupsUsers); + await SyncDbGroups(ldapGroupsUsers); SetProgress(80, Resource.LdapSettingsStatusRemovingOldGroups, ""); @@ -732,7 +732,7 @@ public class LdapOperationJob : DistributedTaskProgress RemoveOldDbUsers(newUniqueLdapGroupUsers); } - private void SyncDbGroups(Dictionary> ldapGroupsWithUsers) + private async Task SyncDbGroups(Dictionary> ldapGroupsWithUsers) { const double percents = 20; @@ -765,18 +765,18 @@ public class LdapOperationJob : DistributedTaskProgress if (Equals(dbLdapGroup, Constants.LostGroupInfo)) { - AddNewGroup(ldapGroup, ldapGroupUsers, gIndex, gCount); + await AddNewGroup(ldapGroup, ldapGroupUsers, gIndex, gCount); } else { - UpdateDbGroup(dbLdapGroup, ldapGroup, ldapGroupUsers, gIndex, gCount); + await UpdateDbGroup(dbLdapGroup, ldapGroup, ldapGroupUsers, gIndex, gCount); } percentage += step; } } - private void AddNewGroup(GroupInfo ldapGroup, List ldapGroupUsers, int gIndex, int gCount) + private async Task AddNewGroup(GroupInfo ldapGroup, List ldapGroupUsers, int gIndex, int gCount) { if (!ldapGroupUsers.Any()) // Skip empty groups { @@ -815,7 +815,7 @@ public class LdapOperationJob : DistributedTaskProgress ++index, count, _userFormatter.GetUserName(userBySid, DisplayUserNameFormat.Default))); - _userManager.AddUserIntoGroup(userBySid.Id, ldapGroup.ID); + await _userManager.AddUserIntoGroup(userBySid.Id, ldapGroup.ID); } break; case LdapOperationType.SaveTest: @@ -846,7 +846,7 @@ public class LdapOperationJob : DistributedTaskProgress return needUpdate; } - private void UpdateDbGroup(GroupInfo dbLdapGroup, GroupInfo ldapGroup, List ldapGroupUsers, int gIndex, + private async Task UpdateDbGroup(GroupInfo dbLdapGroup, GroupInfo ldapGroup, List ldapGroupUsers, int gIndex, int gCount) { SetProgress(currentSource: @@ -911,7 +911,7 @@ public class LdapOperationJob : DistributedTaskProgress ++index, count, _userFormatter.GetUserName(userInfo, DisplayUserNameFormat.Default))); - _userManager.AddUserIntoGroup(userInfo.Id, dbLdapGroup.ID); + await _userManager.AddUserIntoGroup(userInfo.Id, dbLdapGroup.ID); } if (dbGroupMembers.All(dbUser => groupMembersToRemove.Exists(u => u.Id.Equals(dbUser.Id))) @@ -965,7 +965,7 @@ public class LdapOperationJob : DistributedTaskProgress return foundUser; } - private void SyncDbUsers(List ldapUsers) + private async Task SyncDbUsers(List ldapUsers) { const double percents = 35; @@ -992,12 +992,11 @@ public class LdapOperationJob : DistributedTaskProgress { case LdapOperationType.Save: case LdapOperationType.Sync: - _lDAPUserManager.SyncLDAPUser(userInfo, ldapUsers); + await _lDAPUserManager.SyncLDAPUser(userInfo, ldapUsers); break; case LdapOperationType.SaveTest: case LdapOperationType.SyncTest: - LdapChangeCollection changes; - _lDAPUserManager.GetLDAPSyncUserChange(userInfo, ldapUsers, out changes); + var changes = (await _lDAPUserManager.GetLDAPSyncUserChange(userInfo, ldapUsers)).LdapChangeCollection; _ldapChanges.AddRange(changes); break; default: @@ -1065,7 +1064,7 @@ public class LdapOperationJob : DistributedTaskProgress _logger.DebugSaveUserInfo(removedUser.GetUserInfoString()); - _userManager.SaveUserInfo(removedUser); + _userManager.UpdateUserInfo(removedUser); break; case LdapOperationType.SaveTest: case LdapOperationType.SyncTest: @@ -1129,7 +1128,7 @@ public class LdapOperationJob : DistributedTaskProgress } } - private List SyncGroupsUsers(List uniqueLdapGroupUsers) + private async Task> SyncGroupsUsers(List uniqueLdapGroupUsers) { const double percents = 30; @@ -1157,7 +1156,7 @@ public class LdapOperationJob : DistributedTaskProgress { case LdapOperationType.Save: case LdapOperationType.Sync: - user = _lDAPUserManager.SyncLDAPUser(ldapGroupUser, uniqueLdapGroupUsers); + user = await _lDAPUserManager.SyncLDAPUser(ldapGroupUser, uniqueLdapGroupUsers); if (!Equals(user, Constants.LostUser)) { newUniqueLdapGroupUsers.Add(user); @@ -1165,8 +1164,9 @@ public class LdapOperationJob : DistributedTaskProgress break; case LdapOperationType.SaveTest: case LdapOperationType.SyncTest: - LdapChangeCollection changes; - user = _lDAPUserManager.GetLDAPSyncUserChange(ldapGroupUser, uniqueLdapGroupUsers, out changes); + var wrapper = await _lDAPUserManager.GetLDAPSyncUserChange(ldapGroupUser, uniqueLdapGroupUsers); + user = wrapper.UserInfo; + var changes = wrapper.LdapChangeCollection; if (!Equals(user, Constants.LostUser)) { newUniqueLdapGroupUsers.Add(user); diff --git a/common/ASC.ActiveDirectory/GlobalUsings.cs b/common/ASC.ActiveDirectory/GlobalUsings.cs index 1503894d34..16c92eaa7c 100644 --- a/common/ASC.ActiveDirectory/GlobalUsings.cs +++ b/common/ASC.ActiveDirectory/GlobalUsings.cs @@ -51,6 +51,7 @@ global using ASC.ActiveDirectory.Novell; global using ASC.ActiveDirectory.Novell.Data; global using ASC.ActiveDirectory.Novell.Exceptions; global using ASC.ActiveDirectory.Novell.Extensions; +global using ASC.ActiveDirectory.Wrapper; global using ASC.Common; global using ASC.Common.Security.Authorizing; global using ASC.Common.Threading; diff --git a/common/ASC.ActiveDirectory/LdapUserManager.cs b/common/ASC.ActiveDirectory/LdapUserManager.cs index 5c61c010d8..de24a712e0 100644 --- a/common/ASC.ActiveDirectory/LdapUserManager.cs +++ b/common/ASC.ActiveDirectory/LdapUserManager.cs @@ -1,30 +1,31 @@ -// (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 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 Constants = ASC.Core.Users.Constants; using Mapping = ASC.ActiveDirectory.Base.Settings.LdapSettings.MappingFields; using SecurityContext = ASC.Core.SecurityContext; @@ -43,8 +44,8 @@ public class LdapUserManager private readonly DisplayUserSettingsHelper _displayUserSettingsHelper; private readonly UserFormatter _userFormatter; private readonly IServiceProvider _serviceProvider; - private readonly NovellLdapUserImporter _novellLdapUserImporter; - private readonly CountRoomAdminChecker _countRoomAdminChecker; + private readonly NovellLdapUserImporter _novellLdapUserImporter; + private readonly CountRoomAdminChecker _countRoomAdminChecker; private LdapLocalization _resource; public LdapUserManager( @@ -58,7 +59,7 @@ public class LdapUserManager SettingsManager settingsManager, DisplayUserSettingsHelper displayUserSettingsHelper, UserFormatter userFormatter, - NovellLdapUserImporter novellLdapUserImporter, + NovellLdapUserImporter novellLdapUserImporter, CountRoomAdminChecker countRoomAdminChecker) { _logger = logger; @@ -71,8 +72,8 @@ public class LdapUserManager _displayUserSettingsHelper = displayUserSettingsHelper; _userFormatter = userFormatter; _serviceProvider = serviceProvider; - _novellLdapUserImporter = novellLdapUserImporter; - _countRoomAdminChecker = countRoomAdminChecker; + _novellLdapUserImporter = novellLdapUserImporter; + _countRoomAdminChecker = countRoomAdminChecker; } public void Init(LdapLocalization resource = null) @@ -108,9 +109,9 @@ public class LdapUserManager return Equals(foundUser, Constants.LostUser) || foundUser.Id == userId; } - public bool TryAddLDAPUser(UserInfo ldapUserInfo, bool onlyGetChanges, out UserInfo portalUserInfo) + public async Task TryAddLDAPUser(UserInfo ldapUserInfo, bool onlyGetChanges) { - portalUserInfo = Constants.LostUser; + var portalUserInfo = Constants.LostUser; try { @@ -125,24 +126,14 @@ public class LdapUserManager { _logger.DebugUserAlredyExistsForEmail(ldapUserInfo.Sid, ldapUserInfo.Email); - return false; + return portalUserInfo; } if (!TryChangeExistingUserName(ldapUserInfo.UserName, onlyGetChanges)) { _logger.DebugUserAlredyExistsForUserName(ldapUserInfo.Sid, ldapUserInfo.UserName); - return false; - } - - try - { - _countRoomAdminChecker.CheckAppend().Wait(); - } - catch (Exception) - { - _logger.DebugExceedQuota(ldapUserInfo.Sid, ldapUserInfo.UserName); - throw; + return portalUserInfo; } if (!ldapUserInfo.WorkFromDate.HasValue) @@ -153,12 +144,12 @@ public class LdapUserManager if (onlyGetChanges) { portalUserInfo = ldapUserInfo; - return true; + return portalUserInfo; } _logger.DebugSaveUserInfo(ldapUserInfo.GetUserInfoString()); - portalUserInfo = _userManager.SaveUserInfo(ldapUserInfo); + portalUserInfo = await _userManager.SaveUserInfo(ldapUserInfo); var quotaSettings = _settingsManager.Load(); if (quotaSettings.EnableUserQuota) @@ -172,8 +163,6 @@ public class LdapUserManager _logger.DebugSetUserPassword(portalUserInfo.Id); _securityContext.SetUserPasswordHash(portalUserInfo.Id, passwordHash); - - return true; } catch (TenantQuotaException ex) { @@ -188,7 +177,7 @@ public class LdapUserManager } } - return false; + return portalUserInfo; } private bool TryChangeExistingUserName(string ldapUserName, bool onlyGetChanges) @@ -223,7 +212,7 @@ public class LdapUserManager _logger.DebugSaveUserInfo(otherUser.GetUserInfoString()); - _userManager.SaveUserInfo(otherUser); + _userManager.UpdateUserInfo(otherUser); return true; } @@ -235,25 +224,26 @@ public class LdapUserManager return false; } - public UserInfo GetLDAPSyncUserChange(UserInfo ldapUserInfo, List ldapUsers, out LdapChangeCollection changes) + public async Task GetLDAPSyncUserChange(UserInfo ldapUserInfo, List ldapUsers) { - return SyncLDAPUser(ldapUserInfo, ldapUsers, out changes, true); + return await SyncLDAPUser(ldapUserInfo, ldapUsers, true); } - public UserInfo SyncLDAPUser(UserInfo ldapUserInfo, List ldapUsers = null) + public async Task SyncLDAPUser(UserInfo ldapUserInfo, List ldapUsers = null) { - LdapChangeCollection changes; - return SyncLDAPUser(ldapUserInfo, ldapUsers, out changes); + return (await SyncLDAPUser(ldapUserInfo, ldapUsers, false)).UserInfo; } - private UserInfo SyncLDAPUser(UserInfo ldapUserInfo, List ldapUsers, out LdapChangeCollection changes, bool onlyGetChanges = false) + private async Task SyncLDAPUser(UserInfo ldapUserInfo, List ldapUsers, bool onlyGetChanges = false) { - UserInfo result; - - changes = new LdapChangeCollection(_userFormatter); - UserInfo userToUpdate; + var wrapper = new UserInfoAndLdapChangeCollectionWrapper() + { + LdapChangeCollection = new LdapChangeCollection(_userFormatter), + UserInfo = Constants.LostUser + }; + var userBySid = _userManager.GetUserBySid(ldapUserInfo.Sid); if (Equals(userBySid, Constants.LostUser)) @@ -266,28 +256,28 @@ public class LdapUserManager { if (onlyGetChanges) { - changes.SetSkipUserChange(ldapUserInfo); + wrapper.LdapChangeCollection.SetSkipUserChange(ldapUserInfo); } _logger.DebugSyncUserLdapFailedWithStatus(ldapUserInfo.Sid, ldapUserInfo.UserName, Enum.GetName(typeof(EmployeeStatus), ldapUserInfo.Status)); - return Constants.LostUser; + return wrapper; } - - if (!TryAddLDAPUser(ldapUserInfo, onlyGetChanges, out result)) + wrapper.UserInfo = await TryAddLDAPUser(ldapUserInfo, onlyGetChanges); + if (wrapper.UserInfo == Constants.LostUser) { if (onlyGetChanges) { - changes.SetSkipUserChange(ldapUserInfo); + wrapper.LdapChangeCollection.SetSkipUserChange(ldapUserInfo); } - return Constants.LostUser; + return wrapper; } if (onlyGetChanges) { - changes.SetAddUserChange(result, _logger); + wrapper.LdapChangeCollection.SetAddUserChange(wrapper.UserInfo, _logger); } if (!onlyGetChanges && _settingsManager.Load().SendWelcomeEmail && @@ -317,7 +307,7 @@ public class LdapUserManager new TagValue(NotifyCommonTags.WithoutUnsubscribe, true)); } - return result; + return wrapper; } if (userByEmail.IsLDAP()) @@ -326,13 +316,13 @@ public class LdapUserManager { if (onlyGetChanges) { - changes.SetSkipUserChange(ldapUserInfo); + wrapper.LdapChangeCollection.SetSkipUserChange(ldapUserInfo); } _logger.DebugSyncUserLdapFailedWithEmail( ldapUserInfo.Sid, ldapUserInfo.UserName, ldapUserInfo.Email); - return Constants.LostUser; + return wrapper; } } @@ -350,29 +340,30 @@ public class LdapUserManager _logger.DebugSyncUserLdapSkipping(ldapUserInfo.Sid, ldapUserInfo.UserName); if (onlyGetChanges) { - changes.SetNoneUserChange(ldapUserInfo); + wrapper.LdapChangeCollection.SetNoneUserChange(ldapUserInfo); } - - return userBySid; + wrapper.UserInfo = userBySid; + return wrapper; } _logger.DebugSyncUserLdapUpdaiting(ldapUserInfo.Sid, ldapUserInfo.UserName); - if (!TryUpdateUserWithLDAPInfo(userToUpdate, ldapUserInfo, onlyGetChanges, out result)) + UserInfo uf; + if (!TryUpdateUserWithLDAPInfo(userToUpdate, ldapUserInfo, onlyGetChanges, out uf)) { if (onlyGetChanges) { - changes.SetSkipUserChange(ldapUserInfo); + wrapper.LdapChangeCollection.SetSkipUserChange(ldapUserInfo); } - return Constants.LostUser; + return wrapper; } if (onlyGetChanges) { - changes.SetUpdateUserChange(ldapUserInfo, result, _logger); + wrapper.LdapChangeCollection.SetUpdateUserChange(ldapUserInfo, uf, _logger); } - - return result; + wrapper.UserInfo = uf; + return wrapper; } private const string EXT_MOB_PHONE = "extmobphone"; @@ -601,7 +592,7 @@ public class LdapUserManager { _logger.DebugSaveUserInfo(userToUpdate.GetUserInfoString()); - portlaUserInfo = _userManager.SaveUserInfo(userToUpdate); + portlaUserInfo = _userManager.UpdateUserInfo(userToUpdate); } return true; @@ -615,9 +606,9 @@ public class LdapUserManager return false; } - public bool TryGetAndSyncLdapUserInfo(string login, string password, out UserInfo userInfo) + public async Task TryGetAndSyncLdapUserInfo(string login, string password) { - userInfo = Constants.LostUser; + var userInfo = Constants.LostUser; try @@ -626,7 +617,7 @@ public class LdapUserManager if (!settings.EnableLdapAuthentication) { - return false; + return userInfo; } _logger.DebugTryGetAndSyncLdapUserInfo(login); @@ -638,7 +629,7 @@ public class LdapUserManager if (ldapUserInfo == null || ldapUserInfo.Item1.Equals(Constants.LostUser)) { _logger.DebugNovellLdapUserImporterLoginFailed(login); - return false; + return userInfo; } var portalUser = _userManager.GetUserBySid(ldapUserInfo.Item1.Sid); @@ -648,16 +639,16 @@ public class LdapUserManager if (!ldapUserInfo.Item2.IsDisabled) { _logger.DebugTryCheckAndSyncToLdapUser(ldapUserInfo.Item1.UserName, ldapUserInfo.Item1.Email, ldapUserInfo.Item2.DistinguishedName); - - if (!TryCheckAndSyncToLdapUser(ldapUserInfo, _novellLdapUserImporter, out userInfo)) + userInfo = await TryCheckAndSyncToLdapUser(ldapUserInfo, _novellLdapUserImporter); + if (Equals(userInfo, Constants.LostUser)) { _logger.DebugTryCheckAndSyncToLdapUserFailed(); - return false; + return userInfo; } } else { - return false; + return userInfo; } } else @@ -679,18 +670,18 @@ public class LdapUserManager tenantManager.SetCurrentTenant(tenant); securityContext.AuthenticateMe(Core.Configuration.Constants.CoreSystem); - var uInfo = SyncLDAPUser(ldapUserInfo.Item1); + var uInfo = await SyncLDAPUser(ldapUserInfo.Item1); var newLdapUserInfo = new Tuple(uInfo, ldapUserInfo.Item2); if (novellLdapUserImporter.Settings.GroupMembership) { - if (!novellLdapUserImporter.TrySyncUserGroupMembership(newLdapUserInfo)) + if (!(await novellLdapUserImporter.TrySyncUserGroupMembership(newLdapUserInfo))) { log.DebugTryGetAndSyncLdapUserInfoDisablingUser(login, uInfo); uInfo.Status = EmployeeStatus.Terminated; uInfo.Sid = null; - userManager.SaveUserInfo(uInfo); + userManager.UpdateUserInfo(uInfo); await cookiesManager.ResetUserCookie(uInfo.Id); } } @@ -699,7 +690,7 @@ public class LdapUserManager if (ldapUserInfo.Item2.IsDisabled) { _logger.DebugTryGetAndSyncLdapUserInfo(login); - return false; + return userInfo; } else { @@ -707,24 +698,24 @@ public class LdapUserManager } } - return true; + return userInfo; } catch (Exception ex) { _logger.ErrorTryGetLdapUserInfoFailed(login, ex); userInfo = Constants.LostUser; - return false; + return userInfo; } } - private bool TryCheckAndSyncToLdapUser(Tuple ldapUserInfo, LdapUserImporter importer, - out UserInfo userInfo) + private async Task TryCheckAndSyncToLdapUser(Tuple ldapUserInfo, LdapUserImporter importer) { + UserInfo userInfo; try { _securityContext.AuthenticateMe(Core.Configuration.Constants.CoreSystem); - userInfo = SyncLDAPUser(ldapUserInfo.Item1); + userInfo = await SyncLDAPUser(ldapUserInfo.Item1); if (userInfo == null || userInfo.Equals(Constants.LostUser)) { @@ -735,18 +726,18 @@ public class LdapUserManager if (!importer.Settings.GroupMembership) { - return true; + return userInfo; } - if (!importer.TrySyncUserGroupMembership(newLdapUserInfo)) + if (!(await importer.TrySyncUserGroupMembership(newLdapUserInfo))) { userInfo.Sid = null; userInfo.Status = EmployeeStatus.Terminated; - _userManager.SaveUserInfo(userInfo); + _userManager.UpdateUserInfo(userInfo); throw new Exception("The user did not pass the configuration check by ldap group settings"); } - return true; + return userInfo; } catch (Exception ex) { @@ -759,6 +750,6 @@ public class LdapUserManager } userInfo = Constants.LostUser; - return false; + return userInfo; } } diff --git a/common/ASC.ActiveDirectory/Wrapper/UserInfoAndLdapChangeCollectionWrapper.cs b/common/ASC.ActiveDirectory/Wrapper/UserInfoAndLdapChangeCollectionWrapper.cs new file mode 100644 index 0000000000..cb11b525c4 --- /dev/null +++ b/common/ASC.ActiveDirectory/Wrapper/UserInfoAndLdapChangeCollectionWrapper.cs @@ -0,0 +1,32 @@ +// (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.ActiveDirectory.Wrapper; +public class UserInfoAndLdapChangeCollectionWrapper +{ + public UserInfo UserInfo { get; set; } + public LdapChangeCollection LdapChangeCollection { get; set; } +} diff --git a/common/ASC.Api.Core/Auth/CookieAuthHandler.cs b/common/ASC.Api.Core/Auth/CookieAuthHandler.cs index 33b81fdf1b..123e122c8f 100644 --- a/common/ASC.Api.Core/Auth/CookieAuthHandler.cs +++ b/common/ASC.Api.Core/Auth/CookieAuthHandler.cs @@ -57,7 +57,7 @@ public class CookieAuthHandler : AuthenticationHandler HandleAuthenticateAsync() + protected override async Task HandleAuthenticateAsync() { try { @@ -75,7 +75,7 @@ public class CookieAuthHandler : AuthenticationHandler("log"); @@ -56,10 +56,18 @@ public static class ISetupBuilderExtension { awsTarget.LogGroup = awsTarget.LogGroup.Replace("${var:name}", settings.Name); } + + + var awsAccessKeyId = string.IsNullOrEmpty(settings.AWSAccessKeyId) ? configuration["aws:cloudWatch:accessKeyId"] : settings.AWSAccessKeyId; + var awsSecretAccessKey = string.IsNullOrEmpty(settings.AWSSecretAccessKey) ? configuration["aws:cloudWatch:secretAccessKey"] : settings.AWSSecretAccessKey; - if (!string.IsNullOrEmpty(settings.AWSSecretAccessKey)) - { - awsTarget.Credentials = new Amazon.Runtime.BasicAWSCredentials(settings.AWSAccessKeyId, settings.AWSSecretAccessKey); + if (!string.IsNullOrEmpty(awsAccessKeyId)) + { + + awsTarget.LogGroup = String.IsNullOrEmpty(configuration["aws:cloudWatch:logGroupName"]) ? awsTarget.LogGroup : configuration["aws:cloudWatch:logGroupName"]; + awsTarget.Region = String.IsNullOrEmpty(configuration["aws:cloudWatch:region"]) ? awsTarget.Region : configuration["aws:cloudWatch:region"]; + + awsTarget.Credentials = new Amazon.Runtime.BasicAWSCredentials(awsAccessKeyId, awsSecretAccessKey); } } diff --git a/common/ASC.Api.Core/Model/EmployeeFullDto.cs b/common/ASC.Api.Core/Model/EmployeeFullDto.cs index 7117d94077..2536efb2bc 100644 --- a/common/ASC.Api.Core/Model/EmployeeFullDto.cs +++ b/common/ASC.Api.Core/Model/EmployeeFullDto.cs @@ -157,7 +157,7 @@ public class EmployeeFullDtoHelper : EmployeeDtoHelper return lambda; } - public EmployeeFullDto GetSimple(UserInfo userInfo) + public async Task GetSimple(UserInfo userInfo) { var result = new EmployeeFullDto { @@ -167,7 +167,7 @@ public class EmployeeFullDtoHelper : EmployeeDtoHelper FillGroups(result, userInfo); - var photoData = _userPhotoManager.GetUserPhotoData(userInfo.Id, UserPhotoManager.BigFotoSize); + var photoData = await _userPhotoManager.GetUserPhotoData(userInfo.Id, UserPhotoManager.BigFotoSize); if (photoData != null) { diff --git a/common/ASC.Common/Caching/KafkaCacheNotify.cs b/common/ASC.Common/Caching/KafkaCacheNotify.cs index 5b1e47ba76..45c6886170 100644 --- a/common/ASC.Common/Caching/KafkaCacheNotify.cs +++ b/common/ASC.Common/Caching/KafkaCacheNotify.cs @@ -145,7 +145,7 @@ public class KafkaCacheNotify : IDisposable, ICacheNotify where T : IMessa _cancelationToken[channelName] = new CancellationTokenSource(); _actions[channelName] = onchange; - void action() + async void action() { var conf = new ConsumerConfig(_clientConfig) { @@ -160,7 +160,7 @@ public class KafkaCacheNotify : IDisposable, ICacheNotify where T : IMessa try { //TODO: must add checking exist - adminClient.CreateTopicsAsync( + await adminClient.CreateTopicsAsync( new TopicSpecification[] { new TopicSpecification @@ -169,7 +169,7 @@ public class KafkaCacheNotify : IDisposable, ICacheNotify where T : IMessa NumPartitions = 1, ReplicationFactor = 1 } - }).Wait(); + }); } catch (AggregateException) { } } diff --git a/common/ASC.Common/Threading/DistributedTask.cs b/common/ASC.Common/Threading/DistributedTask.cs index ff3ab2caa7..c405d4cd1f 100644 --- a/common/ASC.Common/Threading/DistributedTask.cs +++ b/common/ASC.Common/Threading/DistributedTask.cs @@ -24,8 +24,6 @@ // 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 JsonSerializer = System.Text.Json.JsonSerializer; - namespace ASC.Common.Threading; [ProtoContract(IgnoreUnknownSubTypes = true)] @@ -77,21 +75,6 @@ public class DistributedTask Publication(this); } - public T GetProperty(string propName) - { - if (!_props.TryGetValue(propName, out var propValue)) - { - return default; - } - - return JsonSerializer.Deserialize(propValue); - } - - public void SetProperty(string propName, T propValue) - { - _props[propName] = JsonSerializer.Serialize(propValue); - } - public dynamic this[string propName] { get diff --git a/common/ASC.Common/Threading/DistributedTaskProgress.cs b/common/ASC.Common/Threading/DistributedTaskProgress.cs index 2b5e7d6721..04d8124ae5 100644 --- a/common/ASC.Common/Threading/DistributedTaskProgress.cs +++ b/common/ASC.Common/Threading/DistributedTaskProgress.cs @@ -45,15 +45,15 @@ public class DistributedTaskProgress : DistributedTask [ProtoMember(3)] protected int StepCount { get; set; } - public void RunJob() + public virtual async Task RunJob(DistributedTask _, CancellationToken cancellationToken) { Percentage = 0; Status = DistributedTaskStatus.Running; - DoJob(); + await DoJob(); } - protected virtual void DoJob() { } + protected virtual Task DoJob() { return Task.CompletedTask; } protected void StepDone() { diff --git a/common/ASC.Common/Threading/DistributedTaskQueue.cs b/common/ASC.Common/Threading/DistributedTaskQueue.cs index edb3f6cb83..854558f4bc 100644 --- a/common/ASC.Common/Threading/DistributedTaskQueue.cs +++ b/common/ASC.Common/Threading/DistributedTaskQueue.cs @@ -121,41 +121,7 @@ public class DistributedTaskQueue public void EnqueueTask(DistributedTaskProgress taskProgress) { - EnqueueTask((a, b) => taskProgress.RunJob(), taskProgress); - } - - public void EnqueueTask(Action action, DistributedTask distributedTask = null) - { - if (distributedTask == null) - { - distributedTask = new DistributedTask(); - } - - distributedTask.InstanceId = INSTANCE_ID; - - var cancelation = new CancellationTokenSource(); - var token = cancelation.Token; - _cancelations[distributedTask.Id] = cancelation; - - var task = new Task(() => { action(distributedTask, token); }, token, TaskCreationOptions.LongRunning); - - task.ConfigureAwait(false) - .GetAwaiter() - .OnCompleted(() => OnCompleted(task, distributedTask.Id)); - - distributedTask.Status = DistributedTaskStatus.Running; - - if (distributedTask.Publication == null) - { - distributedTask.Publication = GetPublication(); - } - - distributedTask.PublishChanges(); - - task.Start(Scheduler); - - _logger.TraceEnqueueTask(distributedTask.Id, INSTANCE_ID); - + EnqueueTask(taskProgress.RunJob, taskProgress); } public void EnqueueTask(Func action, DistributedTask distributedTask = null) @@ -393,5 +359,4 @@ public class DistributedTaskQueue return destination; } - } \ No newline at end of file diff --git a/common/ASC.Core.Common/Context/Impl/UserManager.cs b/common/ASC.Core.Common/Context/Impl/UserManager.cs index 7747ff6401..356944490f 100644 --- a/common/ASC.Core.Common/Context/Impl/UserManager.cs +++ b/common/ASC.Core.Common/Context/Impl/UserManager.cs @@ -61,7 +61,7 @@ public class UserManager private readonly CardDavAddressbook _cardDavAddressbook; private readonly ILogger _log; private readonly ICache _cache; - private readonly TenantQuotaFeatureCheckerCount _tenantQuotaFeatureChecker; + private readonly TenantQuotaFeatureCheckerCount _countRoomAdminChecker; private readonly TenantQuotaFeatureCheckerCount _activeUsersFeatureChecker; private readonly Constants _constants; @@ -85,7 +85,7 @@ public class UserManager CardDavAddressbook cardDavAddressbook, ILogger log, ICache cache, - TenantQuotaFeatureCheckerCount tenantQuotaFeatureChecker, + TenantQuotaFeatureCheckerCount countRoomAdrminChecker, TenantQuotaFeatureCheckerCount activeUsersFeatureChecker ) { @@ -100,7 +100,7 @@ public class UserManager _cardDavAddressbook = cardDavAddressbook; _log = log; _cache = cache; - _tenantQuotaFeatureChecker = tenantQuotaFeatureChecker; + _countRoomAdminChecker = countRoomAdrminChecker; _activeUsersFeatureChecker = activeUsersFeatureChecker; _constants = _userManagerConstants.Constants; } @@ -135,7 +135,7 @@ public class UserManager } - #region Users + #region Users public UserInfo[] GetUsers() { @@ -198,7 +198,7 @@ public class UserManager public UserInfo GetUserBySid(string sid) { return GetUsersInternal() - .FirstOrDefault(u => u.Sid != null && string.Equals(u.Sid, sid, StringComparison.CurrentCultureIgnoreCase)) ?? Constants.LostUser; + .FirstOrDefault(u => u.Sid != null && string.Equals(u.Sid, sid, StringComparison.CurrentCultureIgnoreCase)) ?? Constants.LostUser; } public UserInfo GetSsoUserByNameId(string nameId) @@ -296,11 +296,11 @@ public class UserManager foreach (var user in users) { var properties = new string[] - { - user.LastName ?? string.Empty, - user.FirstName ?? string.Empty, - user.Title ?? string.Empty, - user.Location ?? string.Empty, + { + user.LastName ?? string.Empty, + user.FirstName ?? string.Empty, + user.Title ?? string.Empty, + user.Location ?? string.Empty, user.Email ?? string.Empty, }; if (IsPropertiesContainsWords(properties, words)) @@ -312,22 +312,49 @@ public class UserManager return findUsers.ToArray(); } - public UserInfo SaveUserInfo(UserInfo u, bool isUser = false, bool syncCardDav = false) + public UserInfo UpdateUserInfo(UserInfo u) { if (IsSystemUser(u.Id)) { return SystemUsers[u.Id]; } - if (u.Id == Guid.Empty) + _permissionContext.DemandPermissions(new UserSecurityProvider(u.Id), Constants.Action_EditUser); + + if (u.Status == EmployeeStatus.Terminated && u.Id == _tenantManager.GetCurrentTenant().OwnerId) { - _permissionContext.DemandPermissions(Constants.Action_AddRemoveUser); + throw new InvalidOperationException("Can not disable tenant owner."); } - else + + var oldUserData = _userService.GetUserByUserName(_tenantManager.GetCurrentTenant().Id, u.UserName); + + if (oldUserData == null || Equals(oldUserData, Constants.LostUser)) { - _permissionContext.DemandPermissions(new UserSecurityProvider(u.Id), Constants.Action_EditUser); + throw new InvalidOperationException("User not found."); } + return _userService.SaveUser(_tenantManager.GetCurrentTenant().Id, u); + } + + public async Task UpdateUserInfoWithSyncCardDavAsync(UserInfo u) + { + var oldUserData = _userService.GetUserByUserName(_tenantManager.GetCurrentTenant().Id, u.UserName); + + var newUser = UpdateUserInfo(u); + await SyncCardDavAsync(u, oldUserData, newUser); + + return newUser; + } + + public async Task SaveUserInfo(UserInfo u, bool isVisitor = false, bool syncCardDav = false) + { + if (IsSystemUser(u.Id)) + { + return SystemUsers[u.Id]; + } + + _permissionContext.DemandPermissions(Constants.Action_AddRemoveUser); + if (!_coreBaseSettings.Personal) { if (_constants.MaxEveryoneCount <= GetUsersByGroup(Constants.GroupEveryone.ID).Length) @@ -336,97 +363,96 @@ public class UserManager } } - if (u.Status == EmployeeStatus.Terminated && u.Id == _tenantManager.GetCurrentTenant().OwnerId) - { - throw new InvalidOperationException("Can not disable tenant owner."); - } - var oldUserData = _userService.GetUserByUserName(_tenantManager.GetCurrentTenant().Id, u.UserName); - if (Equals(oldUserData, Constants.LostUser)) + if (oldUserData != null && !Equals(oldUserData, Constants.LostUser)) { - if (isUser) - { - _activeUsersFeatureChecker.CheckAppend().Wait(); - } - else - { - _tenantQuotaFeatureChecker.CheckAppend().Wait(); - } + throw new InvalidOperationException("User already exist."); + } + + if (isVisitor) + { + await _activeUsersFeatureChecker.CheckAppend(); + } + else + { + await _countRoomAdminChecker.CheckAppend(); } var newUser = _userService.SaveUser(_tenantManager.GetCurrentTenant().Id, u); - if (syncCardDav) { - var tenant = _tenantManager.GetCurrentTenant(); - var myUri = (_accessor?.HttpContext != null) ? _accessor.HttpContext.Request.GetUrlRewriter().ToString() : - (_cache.Get("REWRITE_URL" + tenant.Id) != null) ? - new Uri(_cache.Get("REWRITE_URL" + tenant.Id)).ToString() : tenant.GetTenantDomain(_coreSettings); + await SyncCardDavAsync(u, oldUserData, newUser); + } - var rootAuthorization = _cardDavAddressbook.GetSystemAuthorization(); - var allUserEmails = GetDavUserEmails().ToList(); + return newUser; + } - if (oldUserData != null && oldUserData.Status != newUser.Status && newUser.Status == EmployeeStatus.Terminated) + private async Task SyncCardDavAsync(UserInfo u, UserInfo oldUserData, UserInfo newUser) + { + var tenant = _tenantManager.GetCurrentTenant(); + var myUri = (_accessor?.HttpContext != null) ? _accessor.HttpContext.Request.GetUrlRewriter().ToString() : + (_cache.Get("REWRITE_URL" + tenant.Id) != null) ? + new Uri(_cache.Get("REWRITE_URL" + tenant.Id)).ToString() : tenant.GetTenantDomain(_coreSettings); + + var rootAuthorization = _cardDavAddressbook.GetSystemAuthorization(); + var allUserEmails = GetDavUserEmails().ToList(); + + if (oldUserData != null && oldUserData.Status != newUser.Status && newUser.Status == EmployeeStatus.Terminated) + { + var userAuthorization = oldUserData.Email.ToLower() + ":" + _instanceCrypto.Encrypt(oldUserData.Email); + var requestUrlBook = _cardDavAddressbook.GetRadicaleUrl(myUri, newUser.Email.ToLower(), true, true); + var collection = await _cardDavAddressbook.GetCollection(requestUrlBook, userAuthorization, myUri.ToString()); + if (collection.Completed && collection.StatusCode != 404) { - var userAuthorization = oldUserData.Email.ToLower() + ":" + _instanceCrypto.Encrypt(oldUserData.Email); - var requestUrlBook = _cardDavAddressbook.GetRadicaleUrl(myUri, newUser.Email.ToLower(), true, true); - var collection = _cardDavAddressbook.GetCollection(requestUrlBook, userAuthorization, myUri.ToString()).Result; - if (collection.Completed && collection.StatusCode != 404) - { - _cardDavAddressbook.Delete(myUri, newUser.Id, newUser.Email, tenant.Id).Wait();//TODO - } - foreach (var email in allUserEmails) - { - var requestUrlItem = _cardDavAddressbook.GetRadicaleUrl(myUri.ToString(), email.ToLower(), true, true, itemID: newUser.Id.ToString()); - try - { - var davItemRequest = new DavRequest() - { - Url = requestUrlItem, - Authorization = rootAuthorization, - Header = myUri - }; - _radicaleClient.RemoveAsync(davItemRequest).ConfigureAwait(false); - } - catch (Exception ex) - { - _log.ErrorWithException(ex); - } - } + await _cardDavAddressbook.Delete(myUri, newUser.Id, newUser.Email, tenant.Id); } - else + foreach (var email in allUserEmails) { - + var requestUrlItem = _cardDavAddressbook.GetRadicaleUrl(myUri.ToString(), email.ToLower(), true, true, itemID: newUser.Id.ToString()); try { - var cardDavUser = new CardDavItem(u.Id, u.FirstName, u.LastName, u.UserName, u.BirthDate, u.Sex, u.Title, u.Email, u.ContactsList, u.MobilePhone); - - try + var davItemRequest = new DavRequest() { - _cardDavAddressbook.UpdateItemForAllAddBooks(allUserEmails, myUri, cardDavUser, _tenantManager.GetCurrentTenant().Id, oldUserData != null && oldUserData.Email != newUser.Email ? oldUserData.Email : null).Wait(); // todo - } - catch (Exception ex) - { - _log.ErrorWithException(ex); - } - + Url = requestUrlItem, + Authorization = rootAuthorization, + Header = myUri + }; + await _radicaleClient.RemoveAsync(davItemRequest).ConfigureAwait(false); } catch (Exception ex) { _log.ErrorWithException(ex); } } - } - return newUser; + else + { + try + { + var cardDavUser = new CardDavItem(u.Id, u.FirstName, u.LastName, u.UserName, u.BirthDate, u.Sex, u.Title, u.Email, u.ContactsList, u.MobilePhone); + try + { + await _cardDavAddressbook.UpdateItemForAllAddBooks(allUserEmails, myUri, cardDavUser, _tenantManager.GetCurrentTenant().Id, oldUserData != null && oldUserData.Email != newUser.Email ? oldUserData.Email : null); + } + catch (Exception ex) + { + _log.ErrorWithException(ex); + } + } + catch (Exception ex) + { + _log.ErrorWithException(ex); + } + } } + public IEnumerable GetDavUserEmails() { return _userService.GetDavUserEmails(_tenantManager.GetCurrentTenant().Id); } - public void DeleteUser(Guid id) + public async Task DeleteUser(Guid id) { if (IsSystemUser(id)) { @@ -454,7 +480,7 @@ public class UserManager new Uri(_cache.Get("REWRITE_URL" + tenant.Id)).ToString() : tenant.GetTenantDomain(_coreSettings); var davUsersEmails = GetDavUserEmails(); var requestUrlBook = _cardDavAddressbook.GetRadicaleUrl(myUri, delUser.Email.ToLower(), true, true); - var addBookCollection = _cardDavAddressbook.GetCollection(requestUrlBook, userAuthorization, myUri.ToString()).Result; + var addBookCollection = await _cardDavAddressbook.GetCollection(requestUrlBook, userAuthorization, myUri.ToString()); if (addBookCollection.Completed && addBookCollection.StatusCode != 404) @@ -465,7 +491,7 @@ public class UserManager Authorization = rootAuthorization, Header = myUri }; - _radicaleClient.RemoveAsync(davbookRequest).ConfigureAwait(false); + await _radicaleClient.RemoveAsync(davbookRequest).ConfigureAwait(false); } foreach (var email in davUsersEmails) @@ -479,14 +505,13 @@ public class UserManager Authorization = rootAuthorization, Header = myUri }; - _radicaleClient.RemoveAsync(davItemRequest).ConfigureAwait(false); + await _radicaleClient.RemoveAsync(davItemRequest).ConfigureAwait(false); } catch (Exception ex) { _log.ErrorWithException(ex); } } - } catch (Exception ex) { @@ -600,7 +625,7 @@ public class UserManager return GetUsers(employeeStatus).Where(u => IsUserInGroupInternal(u.Id, groupId, refs)).ToArray(); } - public void AddUserIntoGroup(Guid userId, Guid groupId, bool dontClearAddressBook = false) + public async Task AddUserIntoGroup(Guid userId, Guid groupId, bool dontClearAddressBook = false) { if (Constants.LostUser.Id == userId || Constants.LostGroupInfo.ID == groupId) { @@ -618,10 +643,10 @@ public class UserManager var myUri = (_accessor?.HttpContext != null) ? _accessor.HttpContext.Request.GetUrlRewriter().ToString() : (_cache.Get("REWRITE_URL" + tenant.Id) != null) ? new Uri(_cache.Get("REWRITE_URL" + tenant.Id)).ToString() : tenant.GetTenantDomain(_coreSettings); - + if (!dontClearAddressBook) { - _cardDavAddressbook.Delete(myUri, user.Id, user.Email, tenant.Id).Wait(); //todo + await _cardDavAddressbook.Delete(myUri, user.Id, user.Email, tenant.Id); } } } @@ -646,10 +671,10 @@ public class UserManager new HttpRequestDictionary>(_accessor?.HttpContext, "GroupInfoID").Reset(userID.ToString()); } - #endregion Users + #endregion Users - #region Company + #region Company public GroupInfo[] GetDepartments() { @@ -697,10 +722,10 @@ public class UserManager SetDepartmentManager(Guid.Empty, userId); } - #endregion Company + #endregion Company - #region Groups + #region Groups public GroupInfo[] GetGroups() { @@ -779,7 +804,7 @@ public class UserManager _userService.RemoveGroup(Tenant.Id, id); } - #endregion Groups + #endregion Groups private bool IsPropertiesContainsWords(IEnumerable properties, IEnumerable words) @@ -873,4 +898,4 @@ public class UserManager Sid = g.Sid }; } -} +} diff --git a/common/ASC.Core.Common/Context/SecurityContext.cs b/common/ASC.Core.Common/Context/SecurityContext.cs index 48a3fe1d31..209ce050ca 100644 --- a/common/ASC.Core.Common/Context/SecurityContext.cs +++ b/common/ASC.Core.Common/Context/SecurityContext.cs @@ -95,7 +95,7 @@ public class SecurityContext return AuthenticateMe(new UserAccount(u, tenantid, _userFormatter), funcLoginEvent); } - public bool AuthenticateMe(string cookie) + public async Task AuthenticateMe(string cookie) { if (string.IsNullOrEmpty(cookie)) return false; @@ -161,7 +161,7 @@ public class SecurityContext return false; } - var settingLoginEvents = _dbLoginEventsManager.GetLoginEventIds(tenant, userid).Result; // remove Result + var settingLoginEvents = await _dbLoginEventsManager.GetLoginEventIds(tenant, userid); if (loginEventId != 0 && !settingLoginEvents.Contains(loginEventId)) { return false; diff --git a/common/ASC.Core.Common/Notify/Channels/ISenderChannel.cs b/common/ASC.Core.Common/Notify/Channels/ISenderChannel.cs index 7eb617eb18..4e8c030265 100644 --- a/common/ASC.Core.Common/Notify/Channels/ISenderChannel.cs +++ b/common/ASC.Core.Common/Notify/Channels/ISenderChannel.cs @@ -29,6 +29,6 @@ namespace ASC.Notify.Channels; public interface ISenderChannel { string SenderName { get; } - SendResponse DirectSend(INoticeMessage message); - void SendAsync(INoticeMessage message); + Task DirectSend(INoticeMessage message); + Task SendAsync(INoticeMessage message); } diff --git a/common/ASC.Core.Common/Notify/Channels/SenderChannel.cs b/common/ASC.Core.Common/Notify/Channels/SenderChannel.cs index 2774094ce7..9d68f6c8a1 100644 --- a/common/ASC.Core.Common/Notify/Channels/SenderChannel.cs +++ b/common/ASC.Core.Common/Notify/Channels/SenderChannel.cs @@ -45,16 +45,16 @@ public class SenderChannel : ISenderChannel _firstSink = AddSink(_firstSink, dispatcherSink); } - public void SendAsync(INoticeMessage message) + public async Task SendAsync(INoticeMessage message) { ArgumentNullException.ThrowIfNull(message); - _firstSink.ProcessMessageAsync(message); + await _firstSink.ProcessMessageAsync(message); } - public SendResponse DirectSend(INoticeMessage message) + public async Task DirectSend(INoticeMessage message) { - return _senderSink.ProcessMessage(message); + return await _senderSink.ProcessMessage(message); } private ISink AddSink(ISink firstSink, ISink addedSink) diff --git a/common/ASC.Core.Common/Notify/EmailSenderSink.cs b/common/ASC.Core.Common/Notify/EmailSenderSink.cs index 1de76fdd16..277158948b 100644 --- a/common/ASC.Core.Common/Notify/EmailSenderSink.cs +++ b/common/ASC.Core.Common/Notify/EmailSenderSink.cs @@ -38,7 +38,7 @@ public class EmailSenderSink : Sink _serviceProvider = serviceProvider; } - public override SendResponse ProcessMessage(INoticeMessage message) + public override async Task ProcessMessage(INoticeMessage message) { if (message.Recipient.Addresses == null || message.Recipient.Addresses.Length == 0) { @@ -50,7 +50,7 @@ public class EmailSenderSink : Sink { using var scope = _serviceProvider.CreateScope(); var m = scope.ServiceProvider.GetRequiredService().CreateNotifyMessage(message, _senderName); - var result = _sender.Send(m); + var result = await _sender.Send(m); responce.Result = result switch { diff --git a/common/ASC.Core.Common/Notify/Engine/DispatchEngine.cs b/common/ASC.Core.Common/Notify/Engine/DispatchEngine.cs index f7b82edce8..1c75a09765 100644 --- a/common/ASC.Core.Common/Notify/Engine/DispatchEngine.cs +++ b/common/ASC.Core.Common/Notify/Engine/DispatchEngine.cs @@ -43,7 +43,7 @@ public class DispatchEngine _logger.LogOnly(_logOnly); } - public SendResponse Dispatch(INoticeMessage message, string senderName) + public async Task Dispatch(INoticeMessage message, string senderName) { var response = new SendResponse(message, senderName, SendResult.OK); if (!_logOnly) @@ -51,7 +51,7 @@ public class DispatchEngine var sender = _context.GetSender(senderName); if (sender != null) { - response = sender.DirectSend(message); + response = await sender.DirectSend(message); } else { diff --git a/common/ASC.Core.Common/Notify/Engine/NotifyEngine.cs b/common/ASC.Core.Common/Notify/Engine/NotifyEngine.cs index 2a087b86ee..4ccd41b77f 100644 --- a/common/ASC.Core.Common/Notify/Engine/NotifyEngine.cs +++ b/common/ASC.Core.Common/Notify/Engine/NotifyEngine.cs @@ -110,7 +110,7 @@ public class NotifyEngine : INotifyEngine, IDisposable } } - private void NotifyScheduler(object state) + private async void NotifyScheduler(object state) { try { @@ -124,8 +124,9 @@ public class NotifyEngine : INotifyEngine, IDisposable copy = _sendMethods.ToList(); } - foreach (var w in copy) + for (var i = 0; i < copy.Count; i++) { + using var w = copy[i]; if (!w.ScheduleDate.HasValue) { lock (_sendMethods) @@ -138,7 +139,7 @@ public class NotifyEngine : INotifyEngine, IDisposable { try { - w.InvokeSendMethod(now); + await w.InvokeSendMethod(now); } catch (Exception error) { @@ -177,7 +178,7 @@ public class NotifyEngine : INotifyEngine, IDisposable } - private void NotifySender(object state) + private async void NotifySender(object state) { try { @@ -201,7 +202,7 @@ public class NotifyEngine : INotifyEngine, IDisposable try { - SendNotify(request, scope); + await SendNotify(request, scope); } catch (Exception e) { @@ -225,7 +226,7 @@ public class NotifyEngine : INotifyEngine, IDisposable } - private NotifyResult SendNotify(NotifyRequest request, IServiceScope serviceScope) + private async Task SendNotify(NotifyRequest request, IServiceScope serviceScope) { var sendResponces = new List(); @@ -236,7 +237,7 @@ public class NotifyEngine : INotifyEngine, IDisposable } else { - sendResponces.AddRange(SendGroupNotify(request, serviceScope)); + sendResponces.AddRange(await SendGroupNotify(request, serviceScope)); } NotifyResult result; @@ -258,15 +259,15 @@ public class NotifyEngine : INotifyEngine, IDisposable return request.Intercept(place, serviceScope) ? new SendResponse(request.NotifyAction, sender, request.Recipient, SendResult.Prevented) : null; } - private List SendGroupNotify(NotifyRequest request, IServiceScope serviceScope) + private async Task> SendGroupNotify(NotifyRequest request, IServiceScope serviceScope) { var responces = new List(); - SendGroupNotify(request, responces, serviceScope); + await SendGroupNotify(request, responces, serviceScope); return responces; } - private void SendGroupNotify(NotifyRequest request, List responces, IServiceScope serviceScope) + private async Task SendGroupNotify(NotifyRequest request, List responces, IServiceScope serviceScope) { if (request.Recipient is IDirectRecipient) { @@ -276,7 +277,7 @@ public class NotifyEngine : INotifyEngine, IDisposable var directresponses = new List(1); try { - directresponses = SendDirectNotify(request, serviceScope); + directresponses = await SendDirectNotify(request, serviceScope); } catch (Exception exc) { @@ -308,7 +309,7 @@ public class NotifyEngine : INotifyEngine, IDisposable try { var newRequest = request.Split(recipient); - SendGroupNotify(newRequest, responces, serviceScope); + await SendGroupNotify(newRequest, responces, serviceScope); } catch (Exception exc) { @@ -334,7 +335,7 @@ public class NotifyEngine : INotifyEngine, IDisposable } } - private List SendDirectNotify(NotifyRequest request, IServiceScope serviceScope) + private async Task> SendDirectNotify(NotifyRequest request, IServiceScope serviceScope) { if (request.Recipient is not IDirectRecipient) { @@ -371,7 +372,7 @@ public class NotifyEngine : INotifyEngine, IDisposable { try { - response = SendDirectNotify(request, channel, serviceScope); + response = await SendDirectNotify(request, channel, serviceScope); } catch (Exception exc) { @@ -396,7 +397,7 @@ public class NotifyEngine : INotifyEngine, IDisposable return responses; } - private SendResponse SendDirectNotify(NotifyRequest request, ISenderChannel channel, IServiceScope serviceScope) + private async Task SendDirectNotify(NotifyRequest request, ISenderChannel channel, IServiceScope serviceScope) { if (request.Recipient is not IDirectRecipient) { @@ -418,7 +419,7 @@ public class NotifyEngine : INotifyEngine, IDisposable return preventresponse; } - channel.SendAsync(noticeMessage); + await channel.SendAsync(noticeMessage); return new SendResponse(noticeMessage, channel.SenderName, SendResult.Inprogress); } @@ -585,19 +586,21 @@ public class NotifyEngine : INotifyEngine, IDisposable } - private sealed class SendMethodWrapper + private sealed class SendMethodWrapper : IDisposable { - private readonly object _locker = new object(); + private readonly SemaphoreSlim _semaphore; private readonly CronExpression _cronExpression; private readonly Action _method; + private readonly ILogger _logger; public DateTime? ScheduleDate { get; private set; } - public ILogger Logger { get; } public SendMethodWrapper(Action method, string cron, ILogger log) { + _semaphore = new SemaphoreSlim(1); _method = method; - Logger = log; + _logger = log; + if (!string.IsNullOrEmpty(cron)) { _cronExpression = new CronExpression(cron); @@ -617,26 +620,25 @@ public class NotifyEngine : INotifyEngine, IDisposable } catch (Exception e) { - Logger.ErrorUpdateScheduleDate(e); + _logger.ErrorUpdateScheduleDate(e); } } - public void InvokeSendMethod(DateTime d) + public async Task InvokeSendMethod(DateTime d) { - lock (_locker) + await _semaphore.WaitAsync(); + await Task.Run(() => { - Task.Run(() => + try { - try - { - _method(d); - } - catch (Exception e) - { - Logger.ErrorInvokeSendMethod(e); - } - }).Wait(); - } + _method(d); + } + catch (Exception e) + { + _logger.ErrorInvokeSendMethod(e); + } + }); + _semaphore.Release(); } public override bool Equals(object obj) @@ -648,6 +650,11 @@ public class NotifyEngine : INotifyEngine, IDisposable { return _method.GetHashCode(); } + + public void Dispose() + { + _semaphore.Dispose(); + } } public void Dispose() diff --git a/common/ASC.Core.Common/Notify/JabberSenderSink.cs b/common/ASC.Core.Common/Notify/JabberSenderSink.cs index 650fb5bb22..f129bf75a2 100644 --- a/common/ASC.Core.Common/Notify/JabberSenderSink.cs +++ b/common/ASC.Core.Common/Notify/JabberSenderSink.cs @@ -39,7 +39,7 @@ class JabberSenderSink : Sink private readonly IServiceProvider _serviceProvider; - public override SendResponse ProcessMessage(INoticeMessage message) + public override async Task ProcessMessage(INoticeMessage message) { try { @@ -53,7 +53,7 @@ class JabberSenderSink : Sink } else { - _sender.Send(m); + await _sender.Send(m); } return new SendResponse(message, _senderName, result); diff --git a/common/ASC.Core.Common/Notify/PushSenderSink.cs b/common/ASC.Core.Common/Notify/PushSenderSink.cs index ec7da31a74..4374e21c44 100644 --- a/common/ASC.Core.Common/Notify/PushSenderSink.cs +++ b/common/ASC.Core.Common/Notify/PushSenderSink.cs @@ -43,7 +43,7 @@ class PushSenderSink : Sink private readonly IServiceProvider _serviceProvider; - public override SendResponse ProcessMessage(INoticeMessage message) + public override async Task ProcessMessage(INoticeMessage message) { try { @@ -58,7 +58,7 @@ class PushSenderSink : Sink } else { - _sender.Send(m); + await _sender.Send(m); } return new SendResponse(message, Constants.NotifyPushSenderSysName, result); diff --git a/common/ASC.Core.Common/Notify/Senders/AWSSender.cs b/common/ASC.Core.Common/Notify/Senders/AWSSender.cs index 7f50afa544..9cae5dd614 100644 --- a/common/ASC.Core.Common/Notify/Senders/AWSSender.cs +++ b/common/ASC.Core.Common/Notify/Senders/AWSSender.cs @@ -31,7 +31,7 @@ namespace ASC.Core.Notify.Senders; [Singletone] public class AWSSender : SmtpSender, IDisposable { - private readonly object _locker = new object(); + private readonly SemaphoreSlim _semaphore = new SemaphoreSlim(1); private AmazonSimpleEmailServiceClient _amazonEmailServiceClient; private TimeSpan _refreshTimeout; private DateTime _lastRefresh; @@ -56,7 +56,7 @@ public class AWSSender : SmtpSender, IDisposable _lastRefresh = DateTime.UtcNow - _refreshTimeout; //set to refresh on first send } - public override NoticeSendResult Send(NotifyMessage m) + public override async Task Send(NotifyMessage m) { NoticeSendResult result; try @@ -71,11 +71,11 @@ public class AWSSender : SmtpSender, IDisposable var configuration = scope.ServiceProvider.GetService(); if (!configuration.SmtpSettings.IsDefaultSettings) { - result = base.Send(m); + result = await base.Send(m); } else { - result = SendMessage(m); + result = await SendMessage(m); } _logger.Debug(result.ToString()); @@ -106,29 +106,28 @@ public class AWSSender : SmtpSender, IDisposable if (result == NoticeSendResult.MessageIncorrect || result == NoticeSendResult.SendingImpossible) { _logger.DebugAmazonSendingFailed(result); - result = base.Send(m); + result = await base.Send(m); } return result; } - private NoticeSendResult SendMessage(NotifyMessage m) + private async Task SendMessage(NotifyMessage m) { //Check if we need to query stats - RefreshQuotaIfNeeded(); + await RefreshQuotaIfNeeded(); if (_quota != null) { - lock (_locker) + await _semaphore.WaitAsync(); + if (_quota.Max24HourSend <= _quota.SentLast24Hours) { - if (_quota.Max24HourSend <= _quota.SentLast24Hours) - { - //Quota exceeded, queue next refresh to +24 hours - _lastRefresh = DateTime.UtcNow.AddHours(24); - _logger.WarningQuotaLimit(_lastRefresh); + //Quota exceeded, queue next refresh to +24 hours + _lastRefresh = DateTime.UtcNow.AddHours(24); + _logger.WarningQuotaLimit(_lastRefresh); - return NoticeSendResult.SendingImpossible; - } + return NoticeSendResult.SendingImpossible; } + _semaphore.Release(); } var dest = new Destination @@ -160,7 +159,7 @@ public class AWSSender : SmtpSender, IDisposable ThrottleIfNeeded(); - var response = _amazonEmailServiceClient.SendEmailAsync(request).Result; + var response = await _amazonEmailServiceClient.SendEmailAsync(request); _lastSend = DateTime.UtcNow; return response != null ? NoticeSendResult.OK : NoticeSendResult.TryOnceAgain; @@ -182,34 +181,33 @@ public class AWSSender : SmtpSender, IDisposable } } - private void RefreshQuotaIfNeeded() + private async Task RefreshQuotaIfNeeded() { if (!IsRefreshNeeded()) { return; } - lock (_locker) + await _semaphore.WaitAsync(); + if (IsRefreshNeeded())//Double check { - if (IsRefreshNeeded())//Double check - { - _logger.DebugRefreshingQuota(_refreshTimeout, _lastRefresh); + _logger.DebugRefreshingQuota(_refreshTimeout, _lastRefresh); - //Do quota refresh - _lastRefresh = DateTime.UtcNow.AddMinutes(1); - try - { - var r = new GetSendQuotaRequest(); - _quota = _amazonEmailServiceClient.GetSendQuotaAsync(r).Result; - _sendWindow = TimeSpan.FromSeconds(1.0 / _quota.MaxSendRate); - _logger.DebugQuota(_quota.SentLast24Hours, _quota.Max24HourSend, _quota.MaxSendRate, _sendWindow); - } - catch (Exception e) - { - _logger.ErrorRefreshingQuota(e); - } + //Do quota refresh + _lastRefresh = DateTime.UtcNow.AddMinutes(1); + try + { + var r = new GetSendQuotaRequest(); + _quota = await _amazonEmailServiceClient.GetSendQuotaAsync(r); + _sendWindow = TimeSpan.FromSeconds(1.0 / _quota.MaxSendRate); + _logger.DebugQuota(_quota.SentLast24Hours, _quota.Max24HourSend, _quota.MaxSendRate, _sendWindow); + } + catch (Exception e) + { + _logger.ErrorRefreshingQuota(e); } } + _semaphore.Release(); } private bool IsRefreshNeeded() diff --git a/common/ASC.Core.Common/Notify/Senders/INotifySender.cs b/common/ASC.Core.Common/Notify/Senders/INotifySender.cs index 99b5c3a615..2713a971ff 100644 --- a/common/ASC.Core.Common/Notify/Senders/INotifySender.cs +++ b/common/ASC.Core.Common/Notify/Senders/INotifySender.cs @@ -29,5 +29,5 @@ namespace ASC.Core.Notify.Senders; public interface INotifySender { void Init(IDictionary properties); - NoticeSendResult Send(NotifyMessage m); + Task Send(NotifyMessage m); } diff --git a/common/ASC.Core.Common/Notify/Senders/JabberSender.cs b/common/ASC.Core.Common/Notify/Senders/JabberSender.cs index 4a3a33bfc6..ba8e9d4944 100644 --- a/common/ASC.Core.Common/Notify/Senders/JabberSender.cs +++ b/common/ASC.Core.Common/Notify/Senders/JabberSender.cs @@ -40,7 +40,7 @@ public class JabberSender : INotifySender public void Init(IDictionary properties) { } - public NoticeSendResult Send(NotifyMessage m) + public Task Send(NotifyMessage m) { var text = m.Content; if (!string.IsNullOrEmpty(text)) @@ -59,7 +59,7 @@ public class JabberSender : INotifySender _logger.ErrorUnexpected(e); } - return NoticeSendResult.OK; + return Task.FromResult(NoticeSendResult.OK); } } diff --git a/common/ASC.Core.Common/Notify/Senders/NotifyServiceSender.cs b/common/ASC.Core.Common/Notify/Senders/NotifyServiceSender.cs index 3a4c214477..956c9bc783 100644 --- a/common/ASC.Core.Common/Notify/Senders/NotifyServiceSender.cs +++ b/common/ASC.Core.Common/Notify/Senders/NotifyServiceSender.cs @@ -38,10 +38,10 @@ public class NotifyServiceSender : INotifySender public void Init(IDictionary properties) { } - public NoticeSendResult Send(NotifyMessage m) + public Task Send(NotifyMessage m) { _notifyServiceClient.SendNotifyMessage(m); - return NoticeSendResult.OK; + return Task.FromResult(NoticeSendResult.OK); } } diff --git a/common/ASC.Core.Common/Notify/Senders/PushSender.cs b/common/ASC.Core.Common/Notify/Senders/PushSender.cs index 427abc673a..466582bb5c 100644 --- a/common/ASC.Core.Common/Notify/Senders/PushSender.cs +++ b/common/ASC.Core.Common/Notify/Senders/PushSender.cs @@ -41,7 +41,7 @@ public class PushSender : INotifySender public void Init(IDictionary properties) { } - public NoticeSendResult Send(NotifyMessage m) + public Task Send(NotifyMessage m) { if (!string.IsNullOrEmpty(m.Content)) { @@ -59,7 +59,7 @@ public class PushSender : INotifySender _logger.ErrorUnexpected(e); } - return NoticeSendResult.OK; + return Task.FromResult(NoticeSendResult.OK); } } public static class FirebaseSenderExtension diff --git a/common/ASC.Core.Common/Notify/Senders/SmtpSender.cs b/common/ASC.Core.Common/Notify/Senders/SmtpSender.cs index 151002f581..72e6d244cc 100644 --- a/common/ASC.Core.Common/Notify/Senders/SmtpSender.cs +++ b/common/ASC.Core.Common/Notify/Senders/SmtpSender.cs @@ -57,7 +57,7 @@ public class SmtpSender : INotifySender _initProperties = properties; } - public virtual NoticeSendResult Send(NotifyMessage m) + public virtual Task Send(NotifyMessage m) { using var scope = _serviceProvider.CreateScope(); var tenantManager = scope.ServiceProvider.GetService(); @@ -149,7 +149,7 @@ public class SmtpSender : INotifySender smtpClient.Dispose(); } - return result; + return Task.FromResult(result); } private void BuildSmtpSettings(CoreConfiguration configuration) diff --git a/common/ASC.Core.Common/Notify/Senders/TelegramSender.cs b/common/ASC.Core.Common/Notify/Senders/TelegramSender.cs index 5677ae55aa..5889b1c10d 100644 --- a/common/ASC.Core.Common/Notify/Senders/TelegramSender.cs +++ b/common/ASC.Core.Common/Notify/Senders/TelegramSender.cs @@ -41,7 +41,7 @@ public class TelegramSender : INotifySender public void Init(IDictionary properties) { } - public NoticeSendResult Send(NotifyMessage m) + public Task Send(NotifyMessage m) { if (!string.IsNullOrEmpty(m.Content)) { @@ -59,6 +59,6 @@ public class TelegramSender : INotifySender _logger.ErrorUnexpected(e); } - return NoticeSendResult.OK; + return Task.FromResult(NoticeSendResult.OK); } } diff --git a/common/ASC.Core.Common/Notify/Sinks/DispatchSink.cs b/common/ASC.Core.Common/Notify/Sinks/DispatchSink.cs index 729e06f4d7..8c1e1d6098 100644 --- a/common/ASC.Core.Common/Notify/Sinks/DispatchSink.cs +++ b/common/ASC.Core.Common/Notify/Sinks/DispatchSink.cs @@ -37,13 +37,13 @@ class DispatchSink : Sink _senderName = senderName; } - public override SendResponse ProcessMessage(INoticeMessage message) + public override Task ProcessMessage(INoticeMessage message) { return _dispatcher.Dispatch(message, _senderName); } - public override void ProcessMessageAsync(INoticeMessage message) + public override async Task ProcessMessageAsync(INoticeMessage message) { - _dispatcher.Dispatch(message, _senderName); + await _dispatcher.Dispatch(message, _senderName); } } diff --git a/common/ASC.Core.Common/Notify/Sinks/ISink.cs b/common/ASC.Core.Common/Notify/Sinks/ISink.cs index 1e6d7a6536..ffb68fdbb7 100644 --- a/common/ASC.Core.Common/Notify/Sinks/ISink.cs +++ b/common/ASC.Core.Common/Notify/Sinks/ISink.cs @@ -29,6 +29,6 @@ namespace ASC.Notify.Sinks; public interface ISink { ISink NextSink { get; set; } - SendResponse ProcessMessage(INoticeMessage message); - void ProcessMessageAsync(INoticeMessage message); + Task ProcessMessage(INoticeMessage message); + Task ProcessMessageAsync(INoticeMessage message); } diff --git a/common/ASC.Core.Common/Notify/Sinks/Sink.cs b/common/ASC.Core.Common/Notify/Sinks/Sink.cs index 8301ab1dc2..c77a456f8b 100644 --- a/common/ASC.Core.Common/Notify/Sinks/Sink.cs +++ b/common/ASC.Core.Common/Notify/Sinks/Sink.cs @@ -35,10 +35,10 @@ public abstract class Sink : ISink { public ISink NextSink { get; set; } - public abstract SendResponse ProcessMessage(INoticeMessage message); + public abstract Task ProcessMessage(INoticeMessage message); - public virtual void ProcessMessageAsync(INoticeMessage message) + public virtual async Task ProcessMessageAsync(INoticeMessage message) { - NextSink.ProcessMessageAsync(message); + await NextSink.ProcessMessageAsync(message); } } diff --git a/common/ASC.Core.Common/Notify/Telegram/TelegramSenderSink.cs b/common/ASC.Core.Common/Notify/Telegram/TelegramSenderSink.cs index 5ab58c91b0..39409a3d4b 100644 --- a/common/ASC.Core.Common/Notify/Telegram/TelegramSenderSink.cs +++ b/common/ASC.Core.Common/Notify/Telegram/TelegramSenderSink.cs @@ -39,7 +39,7 @@ class TelegramSenderSink : Sink } - public override SendResponse ProcessMessage(INoticeMessage message) + public override async Task ProcessMessage(INoticeMessage message) { try { @@ -47,7 +47,7 @@ class TelegramSenderSink : Sink using var scope = _serviceProvider.CreateScope(); var m = scope.ServiceProvider.GetRequiredService().CreateNotifyMessage(message, _senderName); - _sender.Send(m); + await _sender.Send(m); return new SendResponse(message, _senderName, result); } diff --git a/common/ASC.Data.Backup.Core/ActionInvoker.cs b/common/ASC.Data.Backup.Core/ActionInvoker.cs index 22310f3597..d4b54d5869 100644 --- a/common/ASC.Data.Backup.Core/ActionInvoker.cs +++ b/common/ASC.Data.Backup.Core/ActionInvoker.cs @@ -76,4 +76,42 @@ public static class ActionInvoker } } } + + public static async Task Try( + Func action, + object state, + int maxAttempts, + Action onFailure = null, + Action onAttemptFailure = null, + int sleepMs = 1000, + bool isSleepExponential = true) + { + ArgumentNullException.ThrowIfNull(action); + + var countAttempts = 0; + while (countAttempts++ < maxAttempts) + { + try + { + await action(state); + return; + } + catch (Exception error) + { + if (countAttempts < maxAttempts) + { + onAttemptFailure?.Invoke(error); + + if (sleepMs > 0) + { + await Task.Delay(isSleepExponential ? sleepMs * countAttempts : sleepMs); + } + } + else + { + onFailure?.Invoke(error); + } + } + } + } } diff --git a/common/ASC.Data.Backup.Core/BackupAjaxHandler.cs b/common/ASC.Data.Backup.Core/BackupAjaxHandler.cs index c40c43d08d..f0e6b64200 100644 --- a/common/ASC.Data.Backup.Core/BackupAjaxHandler.cs +++ b/common/ASC.Data.Backup.Core/BackupAjaxHandler.cs @@ -122,25 +122,25 @@ public class BackupAjaxHandler return _backupService.GetBackupProgress(tenantId); } - public void DeleteBackup(Guid id) + public async Task DeleteBackup(Guid id) { DemandPermissionsBackup(); - _backupService.DeleteBackup(id); + await _backupService.DeleteBackup(id); } - public void DeleteAllBackups() + public async Task DeleteAllBackups() { DemandPermissionsBackup(); - _backupService.DeleteAllBackups(GetCurrentTenantId()); + await _backupService.DeleteAllBackups(GetCurrentTenantId()); } - public List GetBackupHistory() + public async Task> GetBackupHistory() { DemandPermissionsBackup(); - return _backupService.GetBackupHistory(GetCurrentTenantId()); + return await _backupService.GetBackupHistory(GetCurrentTenantId()); } public void CreateSchedule(BackupStorageType storageType, Dictionary storageParams, int backupsStored, CronParams cronParams) diff --git a/common/ASC.Data.Backup.Core/Contracts/IBackupService.cs b/common/ASC.Data.Backup.Core/Contracts/IBackupService.cs index 0b2913c10b..83d1771722 100644 --- a/common/ASC.Data.Backup.Core/Contracts/IBackupService.cs +++ b/common/ASC.Data.Backup.Core/Contracts/IBackupService.cs @@ -32,13 +32,13 @@ public interface IBackupService BackupProgress GetBackupProgress(int tenantId); BackupProgress GetRestoreProgress(int tenantId); BackupProgress GetTransferProgress(int tenantId); - List GetBackupHistory(int tenantId); + Task> GetBackupHistory(int tenantId); List GetTransferRegions(); ScheduleResponse GetSchedule(int tenantId); string GetTmpFolder(); void CreateSchedule(CreateScheduleRequest request); - void DeleteAllBackups(int tenantId); - void DeleteBackup(Guid backupId); + Task DeleteAllBackups(int tenantId); + Task DeleteBackup(Guid backupId); void DeleteSchedule(int tenantId); void StartBackup(StartBackupRequest request); void StartRestore(StartRestoreRequest request); diff --git a/common/ASC.Data.Backup.Core/Core/DbBackupProvider.cs b/common/ASC.Data.Backup.Core/Core/DbBackupProvider.cs index a50e93372d..7188c1df49 100644 --- a/common/ASC.Data.Backup.Core/Core/DbBackupProvider.cs +++ b/common/ASC.Data.Backup.Core/Core/DbBackupProvider.cs @@ -45,7 +45,7 @@ public class DbBackupProvider : IBackupProvider public event EventHandler ProgressChanged; - public IEnumerable GetElements(int tenant, string[] configs, IDataWriteOperator writer) + public Task> GetElements(int tenant, string[] configs, IDataWriteOperator writer) { _processedTables.Clear(); var xml = new List(); @@ -69,18 +69,19 @@ public class DbBackupProvider : IBackupProvider node.Add(BackupDatabase(tenant, connectionString, writer)); } } - - return xml; + + return Task.FromResult(xml.AsEnumerable()); } - public void LoadFrom(IEnumerable elements, int tenant, string[] configs, IDataReadOperator reader) + public Task LoadFrom(IEnumerable elements, int tenant, string[] configs, IDataReadOperator reader) { _processedTables.Clear(); foreach (var connectionString in GetConnectionStrings(configs)) { RestoreDatabase(connectionString, elements, reader); - } + } + return Task.CompletedTask; } public IEnumerable GetConnectionStrings(string[] configs) diff --git a/common/ASC.Data.Backup.Core/Core/FileBackupProvider.cs b/common/ASC.Data.Backup.Core/Core/FileBackupProvider.cs index 8cc7bc6577..e331e29044 100644 --- a/common/ASC.Data.Backup.Core/Core/FileBackupProvider.cs +++ b/common/ASC.Data.Backup.Core/Core/FileBackupProvider.cs @@ -50,12 +50,12 @@ public class FileBackupProvider : IBackupProvider public event EventHandler ProgressChanged; - public IEnumerable GetElements(int tenant, string[] configs, IDataWriteOperator writer) + public async Task> GetElements(int tenant, string[] configs, IDataWriteOperator writer) { InvokeProgressChanged("Saving files...", 0); var config = GetWebConfig(configs); - var files = ComposeFiles(tenant, config); + var files = await ComposeFiles(tenant, config); var elements = new List(); var backupKeys = new List(); @@ -74,7 +74,7 @@ public class FileBackupProvider : IBackupProvider { try { - using var stream = storage.GetReadStreamAsync(file.Domain, file.Path).Result; + using var stream = await storage.GetReadStreamAsync(file.Domain, file.Path); writer.WriteEntry(backupPath, stream); break; } @@ -97,7 +97,7 @@ public class FileBackupProvider : IBackupProvider return elements; } - public void LoadFrom(IEnumerable elements, int tenant, string[] configs, IDataReadOperator dataOperator) + public async Task LoadFrom(IEnumerable elements, int tenant, string[] configs, IDataReadOperator dataOperator) { InvokeProgressChanged("Restoring files...", 0); @@ -114,7 +114,7 @@ public class FileBackupProvider : IBackupProvider var storage = _storageFactory.GetStorage(config, tenant, backupInfo.Module, null); try { - storage.SaveAsync(backupInfo.Domain, backupInfo.Path, entry).Wait(); + await storage.SaveAsync(backupInfo.Domain, backupInfo.Path, entry); } catch (Exception error) { @@ -126,7 +126,7 @@ public class FileBackupProvider : IBackupProvider } } - private IEnumerable ComposeFiles(int tenant, string config) + private async Task> ComposeFiles(int tenant, string config) { var files = new List(); foreach (var module in _storageFactoryConfig.GetModuleList(config)) @@ -138,13 +138,13 @@ public class FileBackupProvider : IBackupProvider foreach (var domain in domainList) { - files.AddRange(store - .ListFilesRelativeAsync(domain, "\\", "*.*", true).ToArrayAsync().Result + files.AddRange((await store + .ListFilesRelativeAsync(domain, "\\", "*.*", true).ToArrayAsync()) .Select(x => new FileBackupInfo(domain, module, x))); } - files.AddRange(store - .ListFilesRelativeAsync(string.Empty, "\\", "*.*", true).ToArrayAsync().Result + files.AddRange((await store + .ListFilesRelativeAsync(string.Empty, "\\", "*.*", true).ToArrayAsync()) .Where(x => domainList.All(domain => x.IndexOf($"{domain}/") == -1)) .Select(x => new FileBackupInfo(string.Empty, module, x))); } diff --git a/common/ASC.Data.Backup.Core/Core/IBackupProvider.cs b/common/ASC.Data.Backup.Core/Core/IBackupProvider.cs index cf041cb31c..5bfac934bb 100644 --- a/common/ASC.Data.Backup.Core/Core/IBackupProvider.cs +++ b/common/ASC.Data.Backup.Core/Core/IBackupProvider.cs @@ -31,8 +31,8 @@ public interface IBackupProvider string Name { get; } event EventHandler ProgressChanged; - IEnumerable GetElements(int tenant, string[] configs, IDataWriteOperator writer); - void LoadFrom(IEnumerable elements, int tenant, string[] configs, IDataReadOperator reader); + Task> GetElements(int tenant, string[] configs, IDataWriteOperator writer); + Task LoadFrom(IEnumerable elements, int tenant, string[] configs, IDataReadOperator reader); } public class ProgressChangedEventArgs : EventArgs diff --git a/common/ASC.Data.Backup.Core/Service/BackupService.cs b/common/ASC.Data.Backup.Core/Service/BackupService.cs index f857b33dea..24c4b27171 100644 --- a/common/ASC.Data.Backup.Core/Service/BackupService.cs +++ b/common/ASC.Data.Backup.Core/Service/BackupService.cs @@ -58,7 +58,7 @@ public class BackupService : IBackupService } } - public void DeleteBackup(Guid id) + public async Task DeleteBackup(Guid id) { var backupRecord = _backupRepository.GetBackupRecord(id); _backupRepository.DeleteBackupRecord(backupRecord.Id); @@ -69,10 +69,10 @@ public class BackupService : IBackupService return; } - storage.Delete(backupRecord.StoragePath); + await storage.Delete(backupRecord.StoragePath); } - public void DeleteAllBackups(int tenantId) + public async Task DeleteAllBackups(int tenantId) { foreach (var backupRecord in _backupRepository.GetBackupRecordsByTenantId(tenantId)) { @@ -85,7 +85,7 @@ public class BackupService : IBackupService continue; } - storage.Delete(backupRecord.StoragePath); + await storage.Delete(backupRecord.StoragePath); } catch (Exception error) { @@ -94,7 +94,7 @@ public class BackupService : IBackupService } } - public List GetBackupHistory(int tenantId) + public async Task> GetBackupHistory(int tenantId) { var backupHistory = new List(); foreach (var record in _backupRepository.GetBackupRecordsByTenantId(tenantId)) @@ -105,7 +105,7 @@ public class BackupService : IBackupService continue; } - if (storage.IsExists(record.StoragePath)) + if (await storage.IsExists(record.StoragePath)) { backupHistory.Add(new BackupHistoryRecord { diff --git a/common/ASC.Data.Backup.Core/Service/ProgressItems/BackupProgressItem.cs b/common/ASC.Data.Backup.Core/Service/ProgressItems/BackupProgressItem.cs index dbb4b898e7..e790ae4666 100644 --- a/common/ASC.Data.Backup.Core/Service/ProgressItems/BackupProgressItem.cs +++ b/common/ASC.Data.Backup.Core/Service/ProgressItems/BackupProgressItem.cs @@ -115,7 +115,7 @@ public class BackupProgressItem : BaseBackupProgressItem _configPaths = configPaths; } - protected override void DoJob() + protected override async Task DoJob() { if (ThreadPriority.BelowNormal < Thread.CurrentThread.Priority) { @@ -147,13 +147,13 @@ public class BackupProgressItem : BaseBackupProgressItem PublishChanges(); }; - backupTask.RunJob(); + await backupTask.RunJob(); var backupStorage = _backupStorageFactory.GetBackupStorage(_storageType, TenantId, StorageParams); if (backupStorage != null) { - storagePath = backupStorage.Upload(_storageBasePath, tempFile, _userId); - Link = backupStorage.GetPublicLink(storagePath); + storagePath = await backupStorage.Upload(_storageBasePath, tempFile, _userId); + Link = await backupStorage.GetPublicLink(storagePath); } var repo = _backupRepository; diff --git a/common/ASC.Data.Backup.Core/Service/ProgressItems/RestoreProgressItem.cs b/common/ASC.Data.Backup.Core/Service/ProgressItems/RestoreProgressItem.cs index 4472b64374..e7ffdbead8 100644 --- a/common/ASC.Data.Backup.Core/Service/ProgressItems/RestoreProgressItem.cs +++ b/common/ASC.Data.Backup.Core/Service/ProgressItems/RestoreProgressItem.cs @@ -104,7 +104,7 @@ public class RestoreProgressItem : BaseBackupProgressItem _configPaths = configPaths; } - protected override void DoJob() + protected override async Task DoJob() { Tenant tenant = null; @@ -129,7 +129,7 @@ public class RestoreProgressItem : BaseBackupProgressItem var storage = _backupStorageFactory.GetBackupStorage(StorageType, TenantId, StorageParams); - storage.Download(StoragePath, tempFile); + await storage.Download(StoragePath, tempFile); if (!_coreBaseSettings.Standalone) { @@ -156,7 +156,7 @@ public class RestoreProgressItem : BaseBackupProgressItem Percentage = Percentage = 10d + 0.65 * args.Progress; PublishChanges(); }; - restoreTask.RunJob(); + await restoreTask.RunJob(); Tenant restoredTenant = null; diff --git a/common/ASC.Data.Backup.Core/Service/ProgressItems/TransferProgressItem.cs b/common/ASC.Data.Backup.Core/Service/ProgressItems/TransferProgressItem.cs index c579208999..3fda60a178 100644 --- a/common/ASC.Data.Backup.Core/Service/ProgressItems/TransferProgressItem.cs +++ b/common/ASC.Data.Backup.Core/Service/ProgressItems/TransferProgressItem.cs @@ -99,7 +99,7 @@ public class TransferProgressItem : BaseBackupProgressItem } - protected override void DoJob() + protected override async Task DoJob() { var tempFile = PathHelper.GetTempFileName(TempFolder); var tenant = _tenantManager.GetTenant(TenantId); @@ -121,7 +121,7 @@ public class TransferProgressItem : BaseBackupProgressItem PublishChanges(); }; - transferProgressItem.RunJob(); + await transferProgressItem.RunJob(); Link = GetLink(alias, false); _notifyHelper.SendAboutTransferComplete(tenant, TargetRegion, Link, !Notify, transferProgressItem.ToTenantId); diff --git a/common/ASC.Data.Backup.Core/Storage/ConsumerBackupStorage.cs b/common/ASC.Data.Backup.Core/Storage/ConsumerBackupStorage.cs index bf2e0e6001..635c8f4305 100644 --- a/common/ASC.Data.Backup.Core/Storage/ConsumerBackupStorage.cs +++ b/common/ASC.Data.Backup.Core/Storage/ConsumerBackupStorage.cs @@ -43,36 +43,36 @@ public class ConsumerBackupStorage : IBackupStorage { var settings = new StorageSettings { Module = storageParams["module"], Props = storageParams.Where(r => r.Key != "module").ToDictionary(r => r.Key, r => r.Value) }; _store = _storageSettingsHelper.DataStore(settings); - } - - public string Upload(string storageBasePath, string localPath, Guid userId) + } + + public async Task Upload(string storageBasePath, string localPath, Guid userId) { using var stream = File.OpenRead(localPath); var storagePath = Path.GetFileName(localPath); - _store.SaveAsync(Domain, storagePath, stream, ACL.Private).Wait(); + await _store.SaveAsync(Domain, storagePath, stream, ACL.Private); return storagePath; } - public void Download(string storagePath, string targetLocalPath) + public async Task Download(string storagePath, string targetLocalPath) { - using var source = _store.GetReadStreamAsync(Domain, storagePath).Result; + using var source = await _store.GetReadStreamAsync(Domain, storagePath); using var destination = File.OpenWrite(targetLocalPath); - source.CopyTo(destination); + await source.CopyToAsync(destination); } - public void Delete(string storagePath) + public async Task Delete(string storagePath) { - if (_store.IsFileAsync(Domain, storagePath).Result) + if (await _store.IsFileAsync(Domain, storagePath)) { - _store.DeleteAsync(Domain, storagePath).Wait(); + await _store.DeleteAsync(Domain, storagePath); } } - public bool IsExists(string storagePath) + public async Task IsExists(string storagePath) { if (_store != null) { - return _store.IsFileAsync(Domain, storagePath).Result; + return await _store.IsFileAsync(Domain, storagePath); } else { @@ -80,8 +80,8 @@ public class ConsumerBackupStorage : IBackupStorage } } - public string GetPublicLink(string storagePath) + public async Task GetPublicLink(string storagePath) { - return _store.GetInternalUriAsync(Domain, storagePath, TimeSpan.FromDays(1), null).Result.AbsoluteUri; + return (await _store.GetInternalUriAsync(Domain, storagePath, TimeSpan.FromDays(1), null)).AbsoluteUri; } } diff --git a/common/ASC.Data.Backup.Core/Storage/DataStoreBackupStorage.cs b/common/ASC.Data.Backup.Core/Storage/DataStoreBackupStorage.cs index 225ca35b91..96af8ca2fe 100644 --- a/common/ASC.Data.Backup.Core/Storage/DataStoreBackupStorage.cs +++ b/common/ASC.Data.Backup.Core/Storage/DataStoreBackupStorage.cs @@ -42,41 +42,41 @@ public class DataStoreBackupStorage : IBackupStorage { _webConfigPath = webConfigPath; _tenant = tenant; - } - - public string Upload(string storageBasePath, string localPath, Guid userId) + } + + public async Task Upload(string storageBasePath, string localPath, Guid userId) { using var stream = File.OpenRead(localPath); var storagePath = Path.GetFileName(localPath); - GetDataStore().SaveAsync("", storagePath, stream).Wait(); + await GetDataStore().SaveAsync("", storagePath, stream); return storagePath; } - public void Download(string storagePath, string targetLocalPath) + public async Task Download(string storagePath, string targetLocalPath) { - using var source = GetDataStore().GetReadStreamAsync("", storagePath).Result; + using var source = await GetDataStore().GetReadStreamAsync("", storagePath); using var destination = File.OpenWrite(targetLocalPath); source.CopyTo(destination); } - public void Delete(string storagePath) + public async Task Delete(string storagePath) { var dataStore = GetDataStore(); - if (dataStore.IsFileAsync("", storagePath).Result) + if (await dataStore.IsFileAsync("", storagePath)) { - dataStore.DeleteAsync("", storagePath).Wait(); + await dataStore.DeleteAsync("", storagePath); } } - public bool IsExists(string storagePath) + public async Task IsExists(string storagePath) { - return GetDataStore().IsFileAsync("", storagePath).Result; + return await GetDataStore().IsFileAsync("", storagePath); } - public string GetPublicLink(string storagePath) + public async Task GetPublicLink(string storagePath) { - return GetDataStore().GetPreSignedUriAsync("", storagePath, TimeSpan.FromDays(1), null).Result.ToString(); + return (await GetDataStore().GetPreSignedUriAsync("", storagePath, TimeSpan.FromDays(1), null)).ToString(); } protected virtual IDataStore GetDataStore() diff --git a/common/ASC.Data.Backup.Core/Storage/DocumentsBackupStorage.cs b/common/ASC.Data.Backup.Core/Storage/DocumentsBackupStorage.cs index 64c8d8bda3..1070dc0f27 100644 --- a/common/ASC.Data.Backup.Core/Storage/DocumentsBackupStorage.cs +++ b/common/ASC.Data.Backup.Core/Storage/DocumentsBackupStorage.cs @@ -58,9 +58,9 @@ public class DocumentsBackupStorage : IBackupStorage { _tenantId = tenantId; _webConfigPath = webConfigPath; - } - - public string Upload(string folderId, string localPath, Guid userId) + } + + public async Task Upload(string folderId, string localPath, Guid userId) { _tenantManager.SetCurrentTenant(_tenantId); if (!userId.Equals(Guid.Empty)) @@ -75,62 +75,62 @@ public class DocumentsBackupStorage : IBackupStorage if (int.TryParse(folderId, out var fId)) { - return Upload(fId, localPath).ToString(); + return (await Upload(fId, localPath)).ToString(); } - return Upload(folderId, localPath); + return await Upload(folderId, localPath); } - public void Download(string fileId, string targetLocalPath) + public async Task Download(string fileId, string targetLocalPath) { _tenantManager.SetCurrentTenant(_tenantId); if (int.TryParse(fileId, out var fId)) { - DownloadDao(fId, targetLocalPath); + await DownloadDao(fId, targetLocalPath); return; } - DownloadDao(fileId, targetLocalPath); + await DownloadDao(fileId, targetLocalPath); } - public void Delete(string fileId) + public async Task Delete(string fileId) { _tenantManager.SetCurrentTenant(_tenantId); if (int.TryParse(fileId, out var fId)) { - DeleteDao(fId); + await DeleteDao(fId); return; } - DeleteDao(fileId); + await DeleteDao(fileId); } - public bool IsExists(string fileId) + public async Task IsExists(string fileId) { _tenantManager.SetCurrentTenant(_tenantId); if (int.TryParse(fileId, out var fId)) { - return IsExistsDao(fId); + return await IsExistsDao(fId); } - return IsExistsDao(fileId); + return await IsExistsDao(fileId); } - public string GetPublicLink(string fileId) + public Task GetPublicLink(string fileId) { - return string.Empty; + return Task.FromResult(String.Empty); } - private T Upload(T folderId, string localPath) + private async Task Upload(T folderId, string localPath) { var folderDao = GetFolderDao(); var fileDao = GetFileDao(); - var folder = folderDao.GetFolderAsync(folderId).Result; + var folder = await folderDao.GetFolderAsync(folderId); if (folder == null) { throw new FileNotFoundException("Folder not found."); @@ -144,52 +144,52 @@ public class DocumentsBackupStorage : IBackupStorage File file = null; var buffer = new byte[_setupInfo.ChunkUploadSize]; - var chunkedUploadSession = fileDao.CreateUploadSessionAsync(newFile, source.Length).Result; + var chunkedUploadSession = await fileDao.CreateUploadSessionAsync(newFile, source.Length); chunkedUploadSession.CheckQuota = false; int bytesRead; - while ((bytesRead = source.Read(buffer, 0, (int)_setupInfo.ChunkUploadSize)) > 0) + while ((bytesRead = await source.ReadAsync(buffer, 0, (int)_setupInfo.ChunkUploadSize)) > 0) { using (var theMemStream = new MemoryStream()) { - theMemStream.Write(buffer, 0, bytesRead); + await theMemStream.WriteAsync(buffer, 0, bytesRead); theMemStream.Position = 0; - file = fileDao.UploadChunkAsync(chunkedUploadSession, theMemStream, bytesRead).Result; + file = await fileDao.UploadChunkAsync(chunkedUploadSession, theMemStream, bytesRead); } } return file.Id; } - private void DownloadDao(T fileId, string targetLocalPath) + private async Task DownloadDao(T fileId, string targetLocalPath) { _tenantManager.SetCurrentTenant(_tenantId); var fileDao = GetFileDao(); - var file = fileDao.GetFileAsync(fileId).Result; + var file = await fileDao.GetFileAsync(fileId); if (file == null) { throw new FileNotFoundException("File not found."); } - using var source = fileDao.GetFileStreamAsync(file).Result; + using var source = await fileDao.GetFileStreamAsync(file); using var destination = File.OpenWrite(targetLocalPath); - source.CopyTo(destination); + await source.CopyToAsync(destination); } - private void DeleteDao(T fileId) + private async Task DeleteDao(T fileId) { var fileDao = GetFileDao(); - fileDao.DeleteFileAsync(fileId).Wait(); + await fileDao.DeleteFileAsync(fileId); } - private bool IsExistsDao(T fileId) + private async Task IsExistsDao(T fileId) { var fileDao = GetFileDao(); try { - var file = fileDao.GetFileAsync(fileId).Result; + var file = await fileDao.GetFileAsync(fileId); return file != null && file.RootFolderType != FolderType.TRASH; } diff --git a/common/ASC.Data.Backup.Core/Storage/IBackupStorage.cs b/common/ASC.Data.Backup.Core/Storage/IBackupStorage.cs index 26fba39459..16917e0241 100644 --- a/common/ASC.Data.Backup.Core/Storage/IBackupStorage.cs +++ b/common/ASC.Data.Backup.Core/Storage/IBackupStorage.cs @@ -28,9 +28,9 @@ namespace ASC.Data.Backup.Storage; public interface IBackupStorage { - bool IsExists(string storagePath); - string GetPublicLink(string storagePath); - string Upload(string storageBasePath, string localPath, Guid userId); - void Delete(string storagePath); - void Download(string storagePath, string targetLocalPath); + Task IsExists(string storagePath); + Task GetPublicLink(string storagePath); + Task Upload(string storageBasePath, string localPath, Guid userId); + Task Delete(string storagePath); + Task Download(string storagePath, string targetLocalPath); } diff --git a/common/ASC.Data.Backup.Core/Storage/LocalBackupStorage.cs b/common/ASC.Data.Backup.Core/Storage/LocalBackupStorage.cs index f7d71c6a4a..c0d341ccc9 100644 --- a/common/ASC.Data.Backup.Core/Storage/LocalBackupStorage.cs +++ b/common/ASC.Data.Backup.Core/Storage/LocalBackupStorage.cs @@ -29,7 +29,7 @@ namespace ASC.Data.Backup.Storage; [Scope] public class LocalBackupStorage : IBackupStorage { - public string Upload(string storageBasePath, string localPath, Guid userId) + public Task Upload(string storageBasePath, string localPath, Guid userId) { if (!Directory.Exists(storageBasePath)) { @@ -42,26 +42,28 @@ public class LocalBackupStorage : IBackupStorage File.Copy(localPath, storagePath, true); } - return storagePath; + return Task.FromResult(storagePath); } - public void Download(string storagePath, string targetLocalPath) + public Task Download(string storagePath, string targetLocalPath) { File.Copy(storagePath, targetLocalPath, true); + return Task.CompletedTask; } - public void Delete(string storagePath) + public Task Delete(string storagePath) { File.Delete(storagePath); + return Task.CompletedTask; } - public bool IsExists(string storagePath) + public Task IsExists(string storagePath) { - return File.Exists(storagePath); + return Task.FromResult(File.Exists(storagePath)); } - public string GetPublicLink(string storagePath) + public Task GetPublicLink(string storagePath) { - return string.Empty; + return Task.FromResult(string.Empty); } } diff --git a/common/ASC.Data.Backup.Core/Storage/S3BackupStorage.cs b/common/ASC.Data.Backup.Core/Storage/S3BackupStorage.cs index 50e764db6e..6fdad25a10 100644 --- a/common/ASC.Data.Backup.Core/Storage/S3BackupStorage.cs +++ b/common/ASC.Data.Backup.Core/Storage/S3BackupStorage.cs @@ -43,7 +43,7 @@ internal class S3BackupStorage : IBackupStorage _region = region; } - public string Upload(string storageBasePath, string localPath, Guid userId) + public async Task Upload(string storageBasePath, string localPath, Guid userId) { string key; @@ -58,7 +58,7 @@ internal class S3BackupStorage : IBackupStorage using (var fileTransferUtility = new TransferUtility(_accessKeyId, _secretAccessKey, RegionEndpoint.GetBySystemName(_region))) { - fileTransferUtility.Upload( + await fileTransferUtility.UploadAsync( new TransferUtilityUploadRequest { BucketName = _bucket, @@ -73,7 +73,7 @@ internal class S3BackupStorage : IBackupStorage return key; } - public void Download(string storagePath, string targetLocalPath) + public async Task Download(string storagePath, string targetLocalPath) { var request = new GetObjectRequest { @@ -82,27 +82,27 @@ internal class S3BackupStorage : IBackupStorage }; using var s3 = GetClient(); - using var response = s3.GetObjectAsync(request).Result; - response.WriteResponseStreamToFileAsync(targetLocalPath, true, new CancellationToken()); + using var response = await s3.GetObjectAsync(request); + await response.WriteResponseStreamToFileAsync(targetLocalPath, true, new CancellationToken()); } - public void Delete(string storagePath) + public async Task Delete(string storagePath) { using var s3 = GetClient(); - s3.DeleteObjectAsync(new DeleteObjectRequest + await s3.DeleteObjectAsync(new DeleteObjectRequest { BucketName = _bucket, Key = GetKey(storagePath) }); } - public bool IsExists(string storagePath) + public async Task IsExists(string storagePath) { using var s3 = GetClient(); try { var request = new ListObjectsRequest { BucketName = _bucket, Prefix = GetKey(storagePath) }; - var response = s3.ListObjectsAsync(request).Result; + var response = await s3.ListObjectsAsync(request); return response.S3Objects.Count > 0; } @@ -114,18 +114,18 @@ internal class S3BackupStorage : IBackupStorage } } - public string GetPublicLink(string storagePath) + public Task GetPublicLink(string storagePath) { - using var s3 = GetClient(); - - return s3.GetPreSignedURL( + using var s3 = GetClient(); + + return Task.FromResult(s3.GetPreSignedURL( new GetPreSignedUrlRequest { BucketName = _bucket, Key = GetKey(storagePath), Expires = DateTime.UtcNow.AddDays(1), Verb = HttpVerb.GET - }); + })); } private string GetKey(string fileName) diff --git a/common/ASC.Data.Backup.Core/Tasks/BackupPortalTask.cs b/common/ASC.Data.Backup.Core/Tasks/BackupPortalTask.cs index b3c9f3e20b..c8c5186198 100644 --- a/common/ASC.Data.Backup.Core/Tasks/BackupPortalTask.cs +++ b/common/ASC.Data.Backup.Core/Tasks/BackupPortalTask.cs @@ -70,7 +70,7 @@ public class BackupPortalTask : PortalTaskBase } - public override void RunJob() + public override async Task RunJob() { _logger.DebugBeginBackup(TenantId); _tenantManager.SetCurrentTenant(TenantId); @@ -80,13 +80,13 @@ public class BackupPortalTask : PortalTaskBase { if (_dump) { - DoDump(writer); + await DoDump(writer); } else { var modulesToProcess = GetModulesToProcess().ToList(); - var fileGroups = GetFilesGroup(); + var fileGroups = await GetFilesGroup(); var stepscount = ProcessStorage ? fileGroups.Count : 0; SetStepsCount(modulesToProcess.Count + stepscount); @@ -97,7 +97,7 @@ public class BackupPortalTask : PortalTaskBase } if (ProcessStorage) { - DoBackupStorage(writer, fileGroups); + await DoBackupStorage(writer, fileGroups); } } } @@ -121,7 +121,7 @@ public class BackupPortalTask : PortalTaskBase return list; } - private void DoDump(IDataWriteOperator writer) + private async Task DoDump(IDataWriteOperator writer) { var databases = new Dictionary, List>(); @@ -173,7 +173,7 @@ public class BackupPortalTask : PortalTaskBase var tenants = _tenantManager.GetTenants(false).Select(r => r.Id); foreach (var t in tenants) { - files.AddRange(GetFiles(t)); + files.AddRange(await GetFiles(t)); } stepscount += files.Count * 2 + 1; @@ -258,9 +258,9 @@ public class BackupPortalTask : PortalTaskBase } } - private IEnumerable GetFiles(int tenantId) + private async Task> GetFiles(int tenantId) { - var files = GetFilesToProcess(tenantId).ToList(); + var files = (await GetFilesToProcess(tenantId)).ToList(); using var backupRecordContext = _dbContextFactory.CreateDbContext(); var exclude = backupRecordContext.Backups.AsQueryable().Where(b => b.TenantId == tenantId && b.StorageType == 0 && b.StoragePath != null).ToList(); files = files.Where(f => !exclude.Any(e => f.Path.Replace('\\', '/').Contains($"/file_{e.StoragePath}/"))).ToList(); @@ -621,9 +621,9 @@ public class BackupPortalTask : PortalTaskBase _logger.DebugArchiveDirEnd(subDir); } - private List> GetFilesGroup() + private async Task>> GetFilesGroup() { - var files = GetFilesToProcess(TenantId).ToList(); + var files = (await GetFilesToProcess(TenantId)).ToList(); using var backupRecordContext = _dbContextFactory.CreateDbContext(); var exclude = backupRecordContext.Backups.AsQueryable().Where(b => b.TenantId == TenantId && b.StorageType == 0 && b.StoragePath != null).ToList(); @@ -697,7 +697,7 @@ public class BackupPortalTask : PortalTaskBase _logger.DebugEndSavingDataForModule(module.ModuleName); } - private void DoBackupStorage(IDataWriteOperator writer, List> fileGroups) + private async Task DoBackupStorage(IDataWriteOperator writer, List> fileGroups) { _logger.DebugBeginBackupStorage(); @@ -710,10 +710,10 @@ public class BackupPortalTask : PortalTaskBase { var storage = StorageFactory.GetStorage(ConfigPath, TenantId, group.Key); var file1 = file; - ActionInvoker.Try(state => + await ActionInvoker.Try(async state => { var f = (BackupFileInfo)state; - using var fileStream = storage.GetReadStreamAsync(f.Domain, f.Path).Result; + using var fileStream = await storage.GetReadStreamAsync(f.Domain, f.Path); writer.WriteEntry(file1.GetZipKey(), fileStream); }, file, 5, error => _logger.WarningCanNotBackupFile(file1.Module, file1.Path, error)); diff --git a/common/ASC.Data.Backup.Core/Tasks/DeletePortalTask.cs b/common/ASC.Data.Backup.Core/Tasks/DeletePortalTask.cs index 6ead8fd57d..5382981056 100644 --- a/common/ASC.Data.Backup.Core/Tasks/DeletePortalTask.cs +++ b/common/ASC.Data.Backup.Core/Tasks/DeletePortalTask.cs @@ -44,7 +44,7 @@ public class DeletePortalTask : PortalTaskBase _logger = logger; } - public override void RunJob() + public override async Task RunJob() { _logger.DebugBeginDelete(TenantId); var modulesToProcess = GetModulesToProcess().Reverse().ToList(); @@ -57,7 +57,7 @@ public class DeletePortalTask : PortalTaskBase if (ProcessStorage) { - DoDeleteStorage(); + await DoDeleteStorage(); } _logger.DebugEndDelete(TenantId); @@ -84,7 +84,7 @@ public class DeletePortalTask : PortalTaskBase _logger.DebugEndDeleteDataForModule(module.ModuleName); } - private void DoDeleteStorage() + private async Task DoDeleteStorage() { _logger.DebugBeginDeleteStorage(); var storageModules = StorageFactoryConfig.GetModuleList(ConfigPath).Where(IsStorageModuleAllowed).ToList(); @@ -95,10 +95,10 @@ public class DeletePortalTask : PortalTaskBase var domains = StorageFactoryConfig.GetDomainList(ConfigPath, module); foreach (var domain in domains) { - ActionInvoker.Try(state => storage.DeleteFilesAsync((string)state, "\\", "*.*", true).Wait(), domain, 5, + await ActionInvoker.Try(async state => await storage.DeleteFilesAsync((string)state, "\\", "*.*", true), domain, 5, onFailure: error => _logger.WarningCanNotDeleteFilesForDomain(domain, error)); } - storage.DeleteFilesAsync("\\", "*.*", true).Wait(); + await storage.DeleteFilesAsync("\\", "*.*", true); SetCurrentStepProgress((int)(++modulesProcessed * 100 / (double)storageModules.Count)); } diff --git a/common/ASC.Data.Backup.Core/Tasks/PortalTaskBase.cs b/common/ASC.Data.Backup.Core/Tasks/PortalTaskBase.cs index 0f532d6199..a9c4612a4a 100644 --- a/common/ASC.Data.Backup.Core/Tasks/PortalTaskBase.cs +++ b/common/ASC.Data.Backup.Core/Tasks/PortalTaskBase.cs @@ -85,14 +85,14 @@ public abstract class PortalTaskBase } } - public abstract void RunJob(); + public abstract Task RunJob(); internal virtual IEnumerable GetModulesToProcess() { return ModuleProvider.AllModules.Where(module => !_ignoredModules.Contains(module.ModuleName)); } - protected IEnumerable GetFilesToProcess(int tenantId) + protected async Task> GetFilesToProcess(int tenantId) { var files = new List(); foreach (var module in StorageFactoryConfig.GetModuleList(ConfigPath).Where(IsStorageModuleAllowed)) @@ -103,12 +103,12 @@ public abstract class PortalTaskBase foreach (var domain in domains) { files.AddRange( - store.ListFilesRelativeAsync(domain, "\\", "*.*", true).ToArrayAsync().Result + (await store.ListFilesRelativeAsync(domain, "\\", "*.*", true).ToArrayAsync()) .Select(path => new BackupFileInfo(domain, module, path, tenantId))); } files.AddRange( - store.ListFilesRelativeAsync(string.Empty, "\\", "*.*", true).ToArrayAsync().Result + (await store.ListFilesRelativeAsync(string.Empty, "\\", "*.*", true).ToArrayAsync()) .Where(path => domains.All(domain => !path.Contains(domain + "/"))) .Select(path => new BackupFileInfo(string.Empty, module, path, tenantId))); } diff --git a/common/ASC.Data.Backup.Core/Tasks/RestoreDbModuleTask.cs b/common/ASC.Data.Backup.Core/Tasks/RestoreDbModuleTask.cs index 90b7ce4190..9165dfa54b 100644 --- a/common/ASC.Data.Backup.Core/Tasks/RestoreDbModuleTask.cs +++ b/common/ASC.Data.Backup.Core/Tasks/RestoreDbModuleTask.cs @@ -60,7 +60,7 @@ public class RestoreDbModuleTask : PortalTaskBase Init(-1, null); } - public override void RunJob() + public override Task RunJob() { _logger.DebugBeginRestoreDataForModule(_module.ModuleName); SetStepsCount(_module.Tables.Count(t => !_ignoredTables.Contains(t.Name))); @@ -85,7 +85,8 @@ public class RestoreDbModuleTask : PortalTaskBase } } - _logger.DebugEndRestoreDataForModule(_module.ModuleName); + _logger.DebugEndRestoreDataForModule(_module.ModuleName); + return Task.CompletedTask; } public string[] ExecuteArray(DbCommand command) diff --git a/common/ASC.Data.Backup.Core/Tasks/RestorePortalTask.cs b/common/ASC.Data.Backup.Core/Tasks/RestorePortalTask.cs index 68fc1f2e09..e72d93e85e 100644 --- a/common/ASC.Data.Backup.Core/Tasks/RestorePortalTask.cs +++ b/common/ASC.Data.Backup.Core/Tasks/RestorePortalTask.cs @@ -79,7 +79,7 @@ public class RestorePortalTask : PortalTaskBase Init(tenantId, toConfigPath); } - public override void RunJob() + public override async Task RunJob() { _options.DebugBeginRestorePortal(); @@ -94,7 +94,7 @@ public class RestorePortalTask : PortalTaskBase if (Dump) { - RestoreFromDump(dataReader); + await RestoreFromDump(dataReader); } else { @@ -111,7 +111,7 @@ public class RestorePortalTask : PortalTaskBase restoreTask.IgnoreTable(tableName); } - restoreTask.RunJob(); + await restoreTask.RunJob(); } } @@ -125,7 +125,7 @@ public class RestorePortalTask : PortalTaskBase _ascCacheNotify.ClearCache(); } - DoRestoreStorage(dataReader); + await DoRestoreStorage(dataReader); } if (UnblockPortalAfterCompleted) @@ -153,7 +153,7 @@ public class RestorePortalTask : PortalTaskBase _options.DebugEndRestorePortal(); } - private void RestoreFromDump(IDataReadOperator dataReader) + private async Task RestoreFromDump(IDataReadOperator dataReader) { var keyBase = KeyHelper.GetDatabaseSchema(); var keys = dataReader.GetEntries(keyBase).Select(r => Path.GetFileName(r)).ToList(); @@ -187,7 +187,7 @@ public class RestorePortalTask : PortalTaskBase SetStepsCount(stepscount + 1); - DoDeleteStorage(storageModules, tenants); + await DoDeleteStorage(storageModules, tenants); } else { @@ -343,7 +343,7 @@ public class RestorePortalTask : PortalTaskBase } } - private void DoRestoreStorage(IDataReadOperator dataReader) + private async Task DoRestoreStorage(IDataReadOperator dataReader) { _options.DebugBeginRestoreStorage(); @@ -371,7 +371,7 @@ public class RestorePortalTask : PortalTaskBase using var stream = dataReader.GetEntry(key); try { - storage.SaveAsync(file.Domain, adjustedPath, module != null ? module.PrepareData(key, stream, _columnMapper) : stream).Wait(); + await storage.SaveAsync(file.Domain, adjustedPath, module != null ? module.PrepareData(key, stream, _columnMapper) : stream); } catch (Exception error) { @@ -399,7 +399,7 @@ public class RestorePortalTask : PortalTaskBase _options.DebugEndRestoreStorage(); } - private void DoDeleteStorage(IEnumerable storageModules, IEnumerable tenants) + private async Task DoDeleteStorage(IEnumerable storageModules, IEnumerable tenants) { _options.DebugBeginDeleteStorage(); @@ -414,12 +414,12 @@ public class RestorePortalTask : PortalTaskBase foreach (var domain in domains) { - ActionInvoker.Try( - state => + await ActionInvoker.Try( + async state => { - if (storage.IsDirectoryAsync((string)state).Result) + if (await storage.IsDirectoryAsync((string)state)) { - storage.DeleteFilesAsync((string)state, "\\", "*.*", true).Wait(); + await storage.DeleteFilesAsync((string)state, "\\", "*.*", true); } }, domain, diff --git a/common/ASC.Data.Backup.Core/Tasks/TransferPortalTask.cs b/common/ASC.Data.Backup.Core/Tasks/TransferPortalTask.cs index 27a953ae04..d3929317e4 100644 --- a/common/ASC.Data.Backup.Core/Tasks/TransferPortalTask.cs +++ b/common/ASC.Data.Backup.Core/Tasks/TransferPortalTask.cs @@ -74,7 +74,7 @@ public class TransferPortalTask : PortalTaskBase BackupDirectory = backupDirectory; } - public override void RunJob() + public override async Task RunJob() { _logger.DebugBeginTransfer(TenantId); var fromDbFactory = new DbFactory(null, null); @@ -103,7 +103,7 @@ public class TransferPortalTask : PortalTaskBase { backupTask.IgnoreModule(moduleName); } - backupTask.RunJob(); + await backupTask.RunJob(); //restore db data from temporary file var restoreTask = _serviceProvider.GetService(); @@ -114,12 +114,12 @@ public class TransferPortalTask : PortalTaskBase { restoreTask.IgnoreModule(moduleName); } - restoreTask.RunJob(); + await restoreTask.RunJob(); //transfer files if (ProcessStorage) { - DoTransferStorage(columnMapper); + await DoTransferStorage(columnMapper); } SaveTenant(toDbFactory, tenantAlias, TenantStatus.Active); @@ -153,10 +153,10 @@ public class TransferPortalTask : PortalTaskBase } } - private void DoTransferStorage(ColumnMapper columnMapper) + private async Task DoTransferStorage(ColumnMapper columnMapper) { _logger.DebugBeginTransferStorage(); - var fileGroups = GetFilesToProcess(TenantId).GroupBy(file => file.Module).ToList(); + var fileGroups = (await GetFilesToProcess(TenantId)).GroupBy(file => file.Module).ToList(); var groupsProcessed = 0; foreach (var group in fileGroups) { @@ -173,7 +173,7 @@ public class TransferPortalTask : PortalTaskBase { try { - utility.CopyFileAsync(file.Domain, file.Path, file.Domain, adjustedPath).Wait(); + await utility.CopyFileAsync(file.Domain, file.Path, file.Domain, adjustedPath); } catch (Exception error) { diff --git a/common/ASC.Data.Reassigns/ReassignProgressItem.cs b/common/ASC.Data.Reassigns/ReassignProgressItem.cs index f1e42e4690..488419d76c 100644 --- a/common/ASC.Data.Reassigns/ReassignProgressItem.cs +++ b/common/ASC.Data.Reassigns/ReassignProgressItem.cs @@ -68,7 +68,7 @@ public class ReassignProgressItem : DistributedTaskProgress IsCompleted = false; } - protected override void DoJob() + protected override async Task DoJob() { using var scope = _serviceScopeFactory.CreateScope(); var scopeClass = scope.ServiceProvider.GetService(); @@ -122,7 +122,7 @@ public class ReassignProgressItem : DistributedTaskProgress if (_deleteProfile) { - DeleteUserProfile(userManager, userPhotoManager, messageService, messageTarget, displayUserSettingsHelper, queueWorkerRemove); + await DeleteUserProfile(userManager, userPhotoManager, messageService, messageTarget, displayUserSettingsHelper, queueWorkerRemove); } } catch (Exception ex) @@ -174,13 +174,13 @@ public class ReassignProgressItem : DistributedTaskProgress studioNotifyService.SendMsgReassignsFailed(_currentUserId, fromUser, toUser, errorMessage); } - private void DeleteUserProfile(UserManager userManager, UserPhotoManager userPhotoManager, MessageService messageService, MessageTarget messageTarget, DisplayUserSettingsHelper displayUserSettingsHelper, QueueWorkerRemove queueWorkerRemove) + private async Task DeleteUserProfile(UserManager userManager, UserPhotoManager userPhotoManager, MessageService messageService, MessageTarget messageTarget, DisplayUserSettingsHelper displayUserSettingsHelper, QueueWorkerRemove queueWorkerRemove) { var user = userManager.GetUsers(FromUser); var userName = user.DisplayUserName(false, displayUserSettingsHelper); - userPhotoManager.RemovePhoto(user.Id); - userManager.DeleteUser(user.Id); + await userPhotoManager.RemovePhoto(user.Id); + await userManager.DeleteUser(user.Id); queueWorkerRemove.Start(_tenantId, user, _currentUserId, false); if (_httpHeaders != null) diff --git a/common/ASC.Data.Reassigns/RemoveProgressItem.cs b/common/ASC.Data.Reassigns/RemoveProgressItem.cs index b3185b4ea8..4183b53018 100644 --- a/common/ASC.Data.Reassigns/RemoveProgressItem.cs +++ b/common/ASC.Data.Reassigns/RemoveProgressItem.cs @@ -65,7 +65,7 @@ public class RemoveProgressItem : DistributedTaskProgress IsCompleted = false; } - protected override void DoJob() + protected override async Task DoJob() { using var scope = _serviceScopeFactory.CreateScope(); var scopeClass = scope.ServiceProvider.GetService(); @@ -82,7 +82,7 @@ public class RemoveProgressItem : DistributedTaskProgress securityContext.AuthenticateMeWithoutCookie(_currentUserId); long crmSpace; - GetUsageSpace(webItemManagerSecurity, out var docsSpace, out var mailSpace, out var talkSpace); + var wrapper = await GetUsageSpace(webItemManagerSecurity); logger.LogInformation("deleting user data for {fromUser} ", FromUser); @@ -119,11 +119,11 @@ public class RemoveProgressItem : DistributedTaskProgress PublishChanges(); logger.LogInformation("deleting of data from talk"); - DeleteTalkStorage(storageFactory); + await DeleteTalkStorage(storageFactory); Percentage = 99; PublishChanges(); - SendSuccessNotify(studioNotifyService, messageService, messageTarget, userName, docsSpace, crmSpace, mailSpace, talkSpace); + SendSuccessNotify(studioNotifyService, messageService, messageTarget, userName, wrapper.DocsSpace, crmSpace, wrapper.MailSpace, wrapper.TalkSpace); Percentage = 100; Status = DistributedTaskStatus.Completed; @@ -148,9 +148,9 @@ public class RemoveProgressItem : DistributedTaskProgress return MemberwiseClone(); } - private void GetUsageSpace(WebItemManagerSecurity webItemManagerSecurity, out long docsSpace, out long mailSpace, out long talkSpace) + private async Task GetUsageSpace(WebItemManagerSecurity webItemManagerSecurity) { - docsSpace = mailSpace = talkSpace = 0; + var usageSpaceWrapper = new UsageSpaceWrapper(); var webItems = webItemManagerSecurity.GetItems(Web.Core.WebZones.WebZoneType.All, ItemAvailableState.All); @@ -166,7 +166,7 @@ public class RemoveProgressItem : DistributedTaskProgress continue; } - docsSpace = manager.GetUserSpaceUsageAsync(FromUser).Result; + usageSpaceWrapper.DocsSpace = await manager.GetUserSpaceUsageAsync(FromUser); } if (item.ID == WebItemManager.MailProductID) @@ -177,7 +177,7 @@ public class RemoveProgressItem : DistributedTaskProgress continue; } - mailSpace = manager.GetUserSpaceUsageAsync(FromUser).Result; + usageSpaceWrapper.MailSpace = await manager.GetUserSpaceUsageAsync(FromUser); } if (item.ID == WebItemManager.TalkProductID) @@ -188,12 +188,13 @@ public class RemoveProgressItem : DistributedTaskProgress continue; } - talkSpace = manager.GetUserSpaceUsageAsync(FromUser).Result; + usageSpaceWrapper.TalkSpace = await manager.GetUserSpaceUsageAsync(FromUser); } } + return usageSpaceWrapper; } - private void DeleteTalkStorage(StorageFactory storageFactory) + private async Task DeleteTalkStorage(StorageFactory storageFactory) { using var md5 = MD5.Create(); var data = md5.ComputeHash(Encoding.Default.GetBytes(FromUser.ToString())); @@ -209,9 +210,9 @@ public class RemoveProgressItem : DistributedTaskProgress var storage = storageFactory.GetStorage(_tenantId, "talk"); - if (storage != null && storage.IsDirectoryAsync(md5Hash).Result) + if (storage != null && await storage.IsDirectoryAsync(md5Hash)) { - storage.DeleteDirectoryAsync(md5Hash).Wait(); + await storage.DeleteDirectoryAsync(md5Hash); } } @@ -309,6 +310,13 @@ public class RemoveProgressItemScope optionsMonitor = _options; } } + +class UsageSpaceWrapper +{ + public long DocsSpace { get; set; } + public long MailSpace { get; set; } + public long TalkSpace { get; set; } +} public static class RemoveProgressItemExtension { diff --git a/common/ASC.Data.Storage/Encryption/EncryptionOperation.cs b/common/ASC.Data.Storage/Encryption/EncryptionOperation.cs index aeb74dfb1c..d209db1d93 100644 --- a/common/ASC.Data.Storage/Encryption/EncryptionOperation.cs +++ b/common/ASC.Data.Storage/Encryption/EncryptionOperation.cs @@ -56,7 +56,7 @@ public class EncryptionOperation : DistributedTaskProgress _serverRootPath = serverRootPath; } - protected override void DoJob() + protected override async Task DoJob() { using var scope = _serviceScopeFactory.CreateScope(); var scopeClass = scope.ServiceProvider.GetService(); @@ -95,9 +95,9 @@ public class EncryptionOperation : DistributedTaskProgress dictionary.Add(module, (DiscDataStore)storageFactory.GetStorage(ConfigPath, tenant.Id, module)); } - Parallel.ForEach(dictionary, (elem) => + await Parallel.ForEachAsync(dictionary, async (elem, token) => { - EncryptStoreAsync(tenant, elem.Key, elem.Value, storageFactoryConfig, log).Wait(); + await EncryptStoreAsync(tenant, elem.Key, elem.Value, storageFactoryConfig, log); }); } @@ -106,7 +106,7 @@ public class EncryptionOperation : DistributedTaskProgress if (!_hasErrors) { - DeleteProgressFilesAsync(storageFactory).Wait(); + await DeleteProgressFilesAsync(storageFactory); SaveNewSettings(encryptionSettingsHelper, log); } diff --git a/common/ASC.Data.Storage/S3/S3Storage.cs b/common/ASC.Data.Storage/S3/S3Storage.cs index 7240e8ad3e..f3d26d5840 100644 --- a/common/ASC.Data.Storage/S3/S3Storage.cs +++ b/common/ASC.Data.Storage/S3/S3Storage.cs @@ -316,7 +316,7 @@ public class S3Storage : BaseStorage try { using var s3 = GetClient(); - var response = s3.UploadPartAsync(request).Result; + var response = await s3.UploadPartAsync(request); return response.ETag; } diff --git a/common/ASC.Data.Storage/StaticUploader.cs b/common/ASC.Data.Storage/StaticUploader.cs index a0186acb73..af26d4d55a 100644 --- a/common/ASC.Data.Storage/StaticUploader.cs +++ b/common/ASC.Data.Storage/StaticUploader.cs @@ -253,7 +253,7 @@ public class UploadOperationProgress : DistributedTaskProgress StepCount = _directoryFiles.Count(); } - protected override void DoJob() + protected override async Task DoJob() { using var scope = _serviceProvider.CreateScope(); var tenantManager = scope.ServiceProvider.GetService(); @@ -268,7 +268,7 @@ public class UploadOperationProgress : DistributedTaskProgress foreach (var file in _directoryFiles) { var filePath = file.Substring(_mappedPath.TrimEnd('/').Length); - staticUploader.UploadFileAsync(CrossPlatform.PathCombine(_relativePath, filePath), file, (res) => StepDone()).Wait(); + await staticUploader.UploadFileAsync(CrossPlatform.PathCombine(_relativePath, filePath), file, (res) => StepDone()); } tenant.SetStatus(TenantStatus.Active); diff --git a/common/ASC.Data.Storage/StorageUploader.cs b/common/ASC.Data.Storage/StorageUploader.cs index bd231c8b99..6269c9b776 100644 --- a/common/ASC.Data.Storage/StorageUploader.cs +++ b/common/ASC.Data.Storage/StorageUploader.cs @@ -141,7 +141,7 @@ public class MigrateOperation : DistributedTaskProgress return MemberwiseClone(); } - protected override void DoJob() + protected override async Task DoJob() { try { @@ -170,23 +170,23 @@ public class MigrateOperation : DistributedTaskProgress { //Status = module + domain; _logger.DebugDomain(domain); - files = oldStore.ListFilesRelativeAsync(domain, "\\", "*.*", true).ToArrayAsync().Result; + files = await oldStore.ListFilesRelativeAsync(domain, "\\", "*.*", true).ToArrayAsync(); foreach (var file in files) { _logger.DebugFile(file); - crossModuleTransferUtility.CopyFileAsync(domain, file, domain, file).Wait(); + await crossModuleTransferUtility.CopyFileAsync(domain, file, domain, file); } } - files = oldStore.ListFilesRelativeAsync(string.Empty, "\\", "*.*", true).ToArrayAsync().Result + files = (await oldStore.ListFilesRelativeAsync(string.Empty, "\\", "*.*", true).ToArrayAsync()) .Where(path => domains.All(domain => !path.Contains(domain + "/"))) .ToArray(); foreach (var file in files) { _logger.DebugFile(file); - crossModuleTransferUtility.CopyFileAsync("", file, "", file).Wait(); + await crossModuleTransferUtility.CopyFileAsync("", file, "", file); } StepDone(); diff --git a/common/ASC.Migration/Api/MigrationController.cs b/common/ASC.Migration/Api/MigrationController.cs index 89f6808941..3a5fd71c15 100644 --- a/common/ASC.Migration/Api/MigrationController.cs +++ b/common/ASC.Migration/Api/MigrationController.cs @@ -139,7 +139,7 @@ public class MigrationController : ControllerBase /// /// [HttpGet("status")] - public object Status() + public async Task Status() { if (!_coreBaseSettings.Standalone || !_userManager.IsDocSpaceAdmin(_authContext.CurrentAccount.ID)) { @@ -160,7 +160,7 @@ public class MigrationController : ControllerBase var result = new MigrationStatus() { - ParseResult = ongoingMigration.ParseTask.IsCompleted ? ongoingMigration.ParseTask.Result : null, + ParseResult = ongoingMigration.ParseTask.IsCompleted ? await ongoingMigration.ParseTask : null, MigrationEnded = ongoingMigration.MigrationEnded, Progress = ongoingMigration.Migration.GetProgress(), ProgressStatus = ongoingMigration.Migration.GetProgressStatus() diff --git a/common/ASC.Migration/Core/ImportableEntity.cs b/common/ASC.Migration/Core/ImportableEntity.cs index d36928ce5b..36aea10853 100644 --- a/common/ASC.Migration/Core/ImportableEntity.cs +++ b/common/ASC.Migration/Core/ImportableEntity.cs @@ -32,7 +32,7 @@ public abstract class ImportableEntity public abstract void Parse(); - public abstract void Migrate(); + public abstract Task Migrate(); protected Action Log { get; set; } diff --git a/common/ASC.Migration/Core/Providers/GoogleWorkspace/GoogleWorkspaceMigration.cs b/common/ASC.Migration/Core/Providers/GoogleWorkspace/GoogleWorkspaceMigration.cs index 5c20a42bea..35b383bf93 100644 --- a/common/ASC.Migration/Core/Providers/GoogleWorkspace/GoogleWorkspaceMigration.cs +++ b/common/ASC.Migration/Core/Providers/GoogleWorkspace/GoogleWorkspaceMigration.cs @@ -131,7 +131,7 @@ namespace ASC.Migration.GoogleWorkspace return Task.FromResult(_migrationInfo.ToApiInfo()); } - public override Task Migrate(MigrationApiInfo migrationApiInfo) + public override async Task Migrate(MigrationApiInfo migrationApiInfo) { ReportProgress(0, MigrationResource.PreparingForMigration); _migrationInfo.Merge(migrationApiInfo); @@ -148,12 +148,12 @@ namespace ASC.Migration.GoogleWorkspace var i = 1; foreach (var user in usersForImport) { - if (_cancellationToken.IsCancellationRequested) { ReportProgress(100, MigrationResource.MigrationCanceled); return null; } + if (_cancellationToken.IsCancellationRequested) { ReportProgress(100, MigrationResource.MigrationCanceled); return; } ReportProgress(GetProgress() + progressStep, string.Format(MigrationResource.UserMigration, user.DisplayName, i++, usersCount)); try { user.DataСhange(migrationApiInfo.Users.Find(element => element.Key == user.Key)); - user.Migrate(); + await user.Migrate(); _importedUsers.Add(user.Guid); } catch (Exception ex) @@ -173,11 +173,11 @@ namespace ASC.Migration.GoogleWorkspace i = 1; foreach (var group in groupsForImport) { - if (_cancellationToken.IsCancellationRequested) { ReportProgress(100, MigrationResource.MigrationCanceled); return null; } + if (_cancellationToken.IsCancellationRequested) { ReportProgress(100, MigrationResource.MigrationCanceled); return; } ReportProgress(GetProgress() + progressStep, string.Format(MigrationResource.GroupMigration, group.GroupName, i++, groupsCount)); try { - group.Migrate(); + await group.Migrate(); } catch (Exception ex) { @@ -190,7 +190,7 @@ namespace ASC.Migration.GoogleWorkspace i = 1; foreach (var user in usersForImport) { - if (_cancellationToken.IsCancellationRequested) { ReportProgress(100, MigrationResource.MigrationCanceled); return null; } + if (_cancellationToken.IsCancellationRequested) { ReportProgress(100, MigrationResource.MigrationCanceled); return; } if (failedUsers.Contains(user)) { ReportProgress(GetProgress() + progressStep, string.Format(MigrationResource.UserSkipped, user.DisplayName, i, usersCount)); @@ -201,7 +201,7 @@ namespace ASC.Migration.GoogleWorkspace try { - user.MigratingContacts.Migrate(); + await user.MigratingContacts.Migrate(); } catch (Exception ex) { @@ -231,7 +231,7 @@ namespace ASC.Migration.GoogleWorkspace _securityContext.AuthenticateMe(user.Guid); user.MigratingFiles.SetUsersDict(usersForImport.Except(failedUsers)); user.MigratingFiles.SetGroupsDict(groupsForImport); - user.MigratingFiles.Migrate(); + await user.MigratingFiles.Migrate(); _securityContext.AuthenticateMe(currentUser.ID); } catch (Exception ex) @@ -251,7 +251,6 @@ namespace ASC.Migration.GoogleWorkspace } ReportProgress(100, MigrationResource.MigrationCompleted); - return Task.CompletedTask; } } } diff --git a/common/ASC.Migration/Core/Providers/GoogleWorkspace/Models/GWSMigratingCalendar.cs b/common/ASC.Migration/Core/Providers/GoogleWorkspace/Models/GWSMigratingCalendar.cs index 34669b3ee6..5f7a841242 100644 --- a/common/ASC.Migration/Core/Providers/GoogleWorkspace/Models/GWSMigratingCalendar.cs +++ b/common/ASC.Migration/Core/Providers/GoogleWorkspace/Models/GWSMigratingCalendar.cs @@ -48,11 +48,11 @@ public class GwsMigratingCalendar : MigratingCalendar //} } - public override void Migrate() + public override Task Migrate() { if (!ShouldImport) { - return; + return Task.CompletedTask; } // \portals\module\ASC.Api\ASC.Api.Calendar\CalendarApi.cs#L2311 diff --git a/common/ASC.Migration/Core/Providers/GoogleWorkspace/Models/GWSMigratingContacts.cs b/common/ASC.Migration/Core/Providers/GoogleWorkspace/Models/GWSMigratingContacts.cs index e7b0bbb243..eacfc1d14d 100644 --- a/common/ASC.Migration/Core/Providers/GoogleWorkspace/Models/GWSMigratingContacts.cs +++ b/common/ASC.Migration/Core/Providers/GoogleWorkspace/Models/GWSMigratingContacts.cs @@ -89,7 +89,7 @@ public class GwsMigratingContacts : MigratingContacts }*/ } - public override void Migrate() + public override Task Migrate() {/* if (!ShouldImport) { @@ -107,7 +107,8 @@ public class GwsMigratingContacts : MigratingContacts { Log($"Couldn't save contactCard {card.ContactInfo.ContactName}", ex); } - }*/ + }*/ + return Task.CompletedTask; } public GwsMigratingContacts(string rootFolder, GwsMigratingUser user, Action log) : base(log) diff --git a/common/ASC.Migration/Core/Providers/GoogleWorkspace/Models/GWSMigratingFiles.cs b/common/ASC.Migration/Core/Providers/GoogleWorkspace/Models/GWSMigratingFiles.cs index 2c2b8ec8fb..0b6c4617d1 100644 --- a/common/ASC.Migration/Core/Providers/GoogleWorkspace/Models/GWSMigratingFiles.cs +++ b/common/ASC.Migration/Core/Providers/GoogleWorkspace/Models/GWSMigratingFiles.cs @@ -119,7 +119,7 @@ public class GwsMigratingFiles : MigratingFiles _user = user; } - public override void Migrate() + public override async Task Migrate() { if (!ShouldImport) { @@ -150,7 +150,7 @@ public class GwsMigratingFiles : MigratingFiles var parentId = i == 0 ? _globalFolderHelper.FolderMy : foldersDict[string.Join(Path.DirectorySeparatorChar.ToString(), split.Take(i))].Id; try { - var createdFolder = _fileStorageService.CreateNewFolderAsync(parentId, split[i]).Result; + var createdFolder = await _fileStorageService.CreateNewFolderAsync(parentId, split[i]); path = path.Contains(_newParentFolder + Path.DirectorySeparatorChar.ToString()) ? path.Replace(_newParentFolder + Path.DirectorySeparatorChar.ToString(), "") : path; foldersDict.Add(path, createdFolder); } @@ -165,7 +165,7 @@ public class GwsMigratingFiles : MigratingFiles if ((_folders == null || _folders.Count == 0) && (_files != null && _files.Count != 0)) { var parentId = _globalFolderHelper.FolderMy; - var createdFolder = _fileStorageService.CreateNewFolderAsync(parentId, _newParentFolder).Result; + var createdFolder = await _fileStorageService.CreateNewFolderAsync(parentId, _newParentFolder); foldersDict.Add(_newParentFolder, createdFolder); } @@ -196,7 +196,7 @@ public class GwsMigratingFiles : MigratingFiles Title = Path.GetFileName(file), ContentLength = fs.Length }; - newFile = fileDao.SaveFileAsync(newFile, fs).Result; + newFile = await fileDao.SaveFileAsync(newFile, fs); realPath = realPath.Contains(Path.DirectorySeparatorChar.ToString() + _newParentFolder) ? realPath.Replace(Path.DirectorySeparatorChar.ToString() + _newParentFolder, "") : realPath; filesDict.Add(realPath, newFile); @@ -263,7 +263,7 @@ public class GwsMigratingFiles : MigratingFiles } var entryGuid = userToShare == null ? groupToShare.Guid : userToShare.Guid; - if (checkRights != null && checkRights(kv.Value, entryGuid).Result) + if (checkRights != null && await checkRights(kv.Value, entryGuid)) { continue; // already have rights, skip } @@ -301,7 +301,7 @@ public class GwsMigratingFiles : MigratingFiles try { - _fileStorageService.SetAceObjectAsync(aceCollection, false).Wait(); + await _fileStorageService.SetAceObjectAsync(aceCollection, false); } catch (Exception ex) { @@ -312,7 +312,7 @@ public class GwsMigratingFiles : MigratingFiles if (favFolders.Any() || favFiles.Any()) { - _fileStorageService.AddToFavoritesAsync(favFolders, favFiles).Wait(); + await _fileStorageService.AddToFavoritesAsync(favFolders, favFiles); } } catch diff --git a/common/ASC.Migration/Core/Providers/GoogleWorkspace/Models/GWSMigratingGroups.cs b/common/ASC.Migration/Core/Providers/GoogleWorkspace/Models/GWSMigratingGroups.cs index e360e7cf52..05626c0b9e 100644 --- a/common/ASC.Migration/Core/Providers/GoogleWorkspace/Models/GWSMigratingGroups.cs +++ b/common/ASC.Migration/Core/Providers/GoogleWorkspace/Models/GWSMigratingGroups.cs @@ -86,7 +86,7 @@ public class GWSMigratingGroups : MigratingGroup } } - public override void Migrate() + public override async Task Migrate() { var existingGroups = _userManager.GetGroups().ToList(); var oldGroup = existingGroups.Find(g => g.Name == _groupinfo.Name); @@ -110,7 +110,7 @@ public class GWSMigratingGroups : MigratingGroup } if (!_userManager.IsUserInGroup(user.Id, _groupinfo.ID)) { - _userManager.AddUserIntoGroup(user.Id, _groupinfo.ID); + await _userManager.AddUserIntoGroup(user.Id, _groupinfo.ID); } } catch (Exception ex) diff --git a/common/ASC.Migration/Core/Providers/GoogleWorkspace/Models/GWSMigratingMail.cs b/common/ASC.Migration/Core/Providers/GoogleWorkspace/Models/GWSMigratingMail.cs index 64fee4790c..f85a440dbb 100644 --- a/common/ASC.Migration/Core/Providers/GoogleWorkspace/Models/GWSMigratingMail.cs +++ b/common/ASC.Migration/Core/Providers/GoogleWorkspace/Models/GWSMigratingMail.cs @@ -42,7 +42,7 @@ public class GwsMigratingMail : MigratingMail _user = user; } - public override void Migrate() + public override Task Migrate() { throw new NotImplementedException(); } diff --git a/common/ASC.Migration/Core/Providers/GoogleWorkspace/Models/GWSMigratingUser.cs b/common/ASC.Migration/Core/Providers/GoogleWorkspace/Models/GWSMigratingUser.cs index e760b76add..6e485a159c 100644 --- a/common/ASC.Migration/Core/Providers/GoogleWorkspace/Models/GWSMigratingUser.cs +++ b/common/ASC.Migration/Core/Providers/GoogleWorkspace/Models/GWSMigratingUser.cs @@ -109,7 +109,7 @@ public class GwsMigratingUser : MigratingUser(); var folderDao = _daoFactory.GetFolderDao(); { - var parentFolder = string.IsNullOrWhiteSpace(parentPath) ? folderDao.GetFolderAsync(_globalFolderHelper.FolderMy).Result : foldersDict[parentPath]; + var parentFolder = string.IsNullOrWhiteSpace(parentPath) ? await folderDao.GetFolderAsync(_globalFolderHelper.FolderMy) : foldersDict[parentPath]; var newFile = new File { @@ -188,7 +187,7 @@ public class NCMigratingFiles : MigratingFiles Title = Path.GetFileName(file.Path), ContentLength = fs.Length }; - newFile = fileDao.SaveFileAsync(newFile, fs).Result; + newFile = await fileDao.SaveFileAsync(newFile, fs); _matchingFileId.Add(newFile.Id, file.FileId); } } @@ -255,7 +254,7 @@ public class NCMigratingFiles : MigratingFiles try { - _fileStorageService.SetAceObjectAsync(aceCollection, false).Wait(); + await _fileStorageService.SetAceObjectAsync(aceCollection, false); } catch (Exception ex) { diff --git a/common/ASC.Migration/Core/Providers/NextcloudWorkspace/Models/NCMigratingGroups.cs b/common/ASC.Migration/Core/Providers/NextcloudWorkspace/Models/NCMigratingGroups.cs index 92c9fa5a2f..cbd7a823cb 100644 --- a/common/ASC.Migration/Core/Providers/NextcloudWorkspace/Models/NCMigratingGroups.cs +++ b/common/ASC.Migration/Core/Providers/NextcloudWorkspace/Models/NCMigratingGroups.cs @@ -56,7 +56,7 @@ public class NCMigratingGroups : MigratingGroup Module = new MigrationModules(ModuleName, MigrationResource.OnlyofficeModuleNamePeople); } - public override void Migrate() + public override async Task Migrate() { var existingGroups = _userManager.GetGroups().ToList(); var oldGroup = existingGroups.Find(g => g.Name == _groupinfo.Name); @@ -80,7 +80,7 @@ public class NCMigratingGroups : MigratingGroup } if (!_userManager.IsUserInGroup(user.Id, _groupinfo.ID)) { - _userManager.AddUserIntoGroup(user.Id, _groupinfo.ID); + await _userManager.AddUserIntoGroup(user.Id, _groupinfo.ID); } } catch (Exception ex) diff --git a/common/ASC.Migration/Core/Providers/NextcloudWorkspace/Models/NCMigratingMail.cs b/common/ASC.Migration/Core/Providers/NextcloudWorkspace/Models/NCMigratingMail.cs index fe4eabda92..902a85e5c0 100644 --- a/common/ASC.Migration/Core/Providers/NextcloudWorkspace/Models/NCMigratingMail.cs +++ b/common/ASC.Migration/Core/Providers/NextcloudWorkspace/Models/NCMigratingMail.cs @@ -32,7 +32,7 @@ public class NCMigratingMail : MigratingMail public override int MessagesCount => messagesCount; public override string ModuleName => MigrationResource.ModuleNameMail; - public override void Migrate() + public override Task Migrate() { throw new NotImplementedException(); } diff --git a/common/ASC.Migration/Core/Providers/NextcloudWorkspace/Models/NCMigratingUser.cs b/common/ASC.Migration/Core/Providers/NextcloudWorkspace/Models/NCMigratingUser.cs index d992f4057b..67e4abcd81 100644 --- a/common/ASC.Migration/Core/Providers/NextcloudWorkspace/Models/NCMigratingUser.cs +++ b/common/ASC.Migration/Core/Providers/NextcloudWorkspace/Models/NCMigratingUser.cs @@ -177,7 +177,7 @@ public class NCMigratingUser : MigratingUser m.Groups[1].Value.Trim(new[] { '(', ')' })); } - public override Task Migrate(MigrationApiInfo migrationApiInfo) + public override async Task Migrate(MigrationApiInfo migrationApiInfo) { ReportProgress(0, MigrationResource.PreparingForMigration); _migrationInfo.Merge(migrationApiInfo); @@ -471,12 +471,12 @@ public class NextcloudWorkspaceMigration : AbstractMigration element.Key == user.Key)); - user.Migrate(); + await user.Migrate(); _importedUsers.Add(user.Guid); } catch (Exception ex) @@ -497,7 +497,7 @@ public class NextcloudWorkspaceMigration : AbstractMigration group.UserUidList.Exists(u => user.Key == u)) .Select(u => u) .ToDictionary(k => k.Key, v => v.Value.Guid); - group.Migrate(); + await group.Migrate(); } catch (Exception ex) { @@ -517,7 +517,7 @@ public class NextcloudWorkspaceMigration : AbstractMigration(); var folderDao = _daoFactory.GetFolderDao(); - var parentFolder = string.IsNullOrWhiteSpace(parentPath) ? folderDao.GetFolderAsync(_globalFolderHelper.FolderMy).Result : foldersDict[parentPath]; + var parentFolder = string.IsNullOrWhiteSpace(parentPath) ? await folderDao.GetFolderAsync(_globalFolderHelper.FolderMy) : foldersDict[parentPath]; var newFile = new File { @@ -188,7 +187,7 @@ public class OCMigratingFiles : MigratingFiles Title = Path.GetFileName(file.Path), ContentLength = fs.Length }; - newFile = fileDao.SaveFileAsync(newFile, fs).Result; + newFile = await fileDao.SaveFileAsync(newFile, fs); _matchingFileId.Add(newFile.Id, file.FileId); } @@ -255,7 +254,7 @@ public class OCMigratingFiles : MigratingFiles try { - _fileStorageService.SetAceObjectAsync(aceCollection, false).Wait(); + await _fileStorageService.SetAceObjectAsync(aceCollection, false); } catch (Exception ex) { diff --git a/common/ASC.Migration/Core/Providers/OwnCloud/Models/OCMigratingGroups.cs b/common/ASC.Migration/Core/Providers/OwnCloud/Models/OCMigratingGroups.cs index 44b79a86cc..cc34c04865 100644 --- a/common/ASC.Migration/Core/Providers/OwnCloud/Models/OCMigratingGroups.cs +++ b/common/ASC.Migration/Core/Providers/OwnCloud/Models/OCMigratingGroups.cs @@ -56,7 +56,7 @@ public class OCMigratingGroups : MigratingGroup Module = new MigrationModules(ModuleName, MigrationResource.OnlyofficeModuleNamePeople); } - public override void Migrate() + public override async Task Migrate() { var existingGroups = _userManager.GetGroups().ToList(); var oldGroup = existingGroups.Find(g => g.Name == _groupinfo.Name); @@ -80,7 +80,7 @@ public class OCMigratingGroups : MigratingGroup } if (!_userManager.IsUserInGroup(user.Id, _groupinfo.ID)) { - _userManager.AddUserIntoGroup(user.Id, _groupinfo.ID); + await _userManager.AddUserIntoGroup(user.Id, _groupinfo.ID); } } catch (Exception ex) diff --git a/common/ASC.Migration/Core/Providers/OwnCloud/Models/OCMigratingMail.cs b/common/ASC.Migration/Core/Providers/OwnCloud/Models/OCMigratingMail.cs index eefc96dcc1..0d5f1cfc4c 100644 --- a/common/ASC.Migration/Core/Providers/OwnCloud/Models/OCMigratingMail.cs +++ b/common/ASC.Migration/Core/Providers/OwnCloud/Models/OCMigratingMail.cs @@ -32,7 +32,7 @@ public class OCMigratingMail : MigratingMail public override int MessagesCount => messagesCount; public override string ModuleName => MigrationResource.ModuleNameMail; - public override void Migrate() + public override Task Migrate() { throw new NotImplementedException(); } diff --git a/common/ASC.Migration/Core/Providers/OwnCloud/Models/OCMigratingUser.cs b/common/ASC.Migration/Core/Providers/OwnCloud/Models/OCMigratingUser.cs index eb8ff0fa52..95fb8bd228 100644 --- a/common/ASC.Migration/Core/Providers/OwnCloud/Models/OCMigratingUser.cs +++ b/common/ASC.Migration/Core/Providers/OwnCloud/Models/OCMigratingUser.cs @@ -152,7 +152,7 @@ public class OCMigratingUser : MigratingUser m.Groups[1].Value.Trim(new[] { '(', ')' })); } - public override Task Migrate(MigrationApiInfo migrationApiInfo) + public override async Task Migrate(MigrationApiInfo migrationApiInfo) { ReportProgress(0, MigrationResource.PreparingForMigration); _migrationInfo.Merge(migrationApiInfo); @@ -445,12 +445,12 @@ public class OwnCloudMigration : AbstractMigration element.Key == user.Key)); - user.Migrate(); + await user.Migrate(); _importedUsers.Add(user.Guid); } catch (Exception ex) @@ -471,7 +471,7 @@ public class OwnCloudMigration : AbstractMigration group.UserUidList.Exists(u => user.Key == u)) .Select(u => u) .ToDictionary(k => k.Key, v => v.Value.Guid); - group.Migrate(); + await group.Migrate(); } catch (Exception ex) { @@ -491,7 +491,7 @@ public class OwnCloudMigration : AbstractMigration { const now = new Date(); @@ -105,7 +102,6 @@ const customFormat = winston.format(info => { })(); module.exports = new winston.createLogger({ - //defaultMeta: { component: "socket.io-server" }, format: winston.format.combine( customFormat, winston.format.json() diff --git a/common/ASC.Socket.IO/config/config.json b/common/ASC.Socket.IO/config/config.json index 1c81876e59..8922ebd921 100644 --- a/common/ASC.Socket.IO/config/config.json +++ b/common/ASC.Socket.IO/config/config.json @@ -3,12 +3,5 @@ "port": 9899, "appsettings": "../../../config", "environment": "Development" - }, - "aws":{ - "accessKeyId": "", - "secretAccessKey": "", - "region": "", - "logGroupName": "/asc/docspace/cluster/cluster_name/general", - "logStreamName": "${hostname} - ${applicationContext} - ${date} - ${guid}" } } diff --git a/common/ASC.Socket.IO/config/index.js b/common/ASC.Socket.IO/config/index.js index bad3f38510..f8a83975cb 100644 --- a/common/ASC.Socket.IO/config/index.js +++ b/common/ASC.Socket.IO/config/index.js @@ -17,25 +17,15 @@ function getAndSaveAppsettings(){ } var env = nconf.get("app").environment; - var valueEnv = nconf.get(env); - var fileWithEnv = path.join(appsettings, 'appsettings.' + valueEnv + '.json'); - if(fs.existsSync(fileWithEnv)){ - nconf.file("appsettings", fileWithEnv); - } - else{ - nconf.file("appsettings", path.join(appsettings, 'appsettings.json')); - } + console.log('environment: ' + env); + nconf.file("appsettingsWithEnv", path.join(appsettings, 'appsettings.' + env + '.json')); + nconf.file("appsettings", path.join(appsettings, 'appsettings.json')); nconf.file("appsettingsServices", path.join(appsettings, 'appsettings.services.json')); - var redisWithEnv = path.join(appsettings, 'redis.' + valueEnv + '.json'); - if(fs.existsSync(fileWithEnv)){ - nconf.file("redis", redisWithEnv); - } - else{ - nconf.file("redis", path.join(__dirname, appsettings, 'redis.json')); - } + nconf.file("redisWithEnv", path.join(appsettings, 'redis.' + env + '.json')); + nconf.file("redis", path.join(appsettings, 'redis.json')); var redis = nconf.get("Redis"); if(redis != null) diff --git a/common/ASC.SsoAuth/app.js b/common/ASC.SsoAuth/app.js index 6cae1704f6..49f3b43014 100644 --- a/common/ASC.SsoAuth/app.js +++ b/common/ASC.SsoAuth/app.js @@ -52,7 +52,7 @@ if(logpath != null) fs.existsSync(logpath) || fs.mkdirSync(logpath); } -const aws = config["aws"]; +const aws = config["aws"].cloudWatch; const accessKeyId = aws.accessKeyId; const secretAccessKey = aws.secretAccessKey; @@ -88,6 +88,7 @@ if (aws != null && aws.accessKeyId !== '') .replace("${guid}", guid) .replace("${date}", dateAsString); }, + logGroupName: logGroupName, awsRegion: awsRegion, jsonMessage: true, awsOptions: { diff --git a/common/ASC.SsoAuth/config/config.json b/common/ASC.SsoAuth/config/config.json index e969ef751f..540364fb9e 100644 --- a/common/ASC.SsoAuth/config/config.json +++ b/common/ASC.SsoAuth/config/config.json @@ -63,12 +63,5 @@ "image-path": "images", "rebranding": "rebranding", "https":"certs" - }, - "aws":{ - "accessKeyId": "", - "secretAccessKey": "", - "region": "", - "logGroupName": "/asc/docspace/cluster/cluster_name/general", - "logStreamName": "${hostname} - ${applicationContext} - ${date} - ${guid}" - } + } } \ No newline at end of file diff --git a/common/ASC.SsoAuth/config/index.js b/common/ASC.SsoAuth/config/index.js index 4865550202..0a5372a44a 100644 --- a/common/ASC.SsoAuth/config/index.js +++ b/common/ASC.SsoAuth/config/index.js @@ -22,6 +22,8 @@ const nconf = require("nconf"), nconf.argv() .env() .file("config",path.join(__dirname, "config.json")); + +console.log("NODE_ENV: " + nconf.get("NODE_ENV")); if (nconf.get("NODE_ENV") !== "development" && fs.existsSync(path.join(__dirname, nconf.get("NODE_ENV") + ".json"))) { nconf.file("config", path.join(__dirname, nconf.get("NODE_ENV") + ".json")); @@ -38,14 +40,9 @@ function getAndSaveAppsettings(){ appsettings =path.join(__dirname, appsettings); } var env = nconf.get("app").environment; - var valueEnv = nconf.get(env); - var fileWithEnv = path.join(appsettings, 'appsettings.' + valueEnv + '.json'); + console.log('environment: ' + env); - if(fs.existsSync(fileWithEnv)){ - nconf.file("appsettings", fileWithEnv); - } - else{ - nconf.file("appsettings", path.join(appsettings, 'appsettings.json')); - } + nconf.file("appsettingsWithEnv", path.join(appsettings, 'appsettings.' + env + '.json')); + nconf.file("appsettings", path.join(appsettings, 'appsettings.json')); nconf.file("appsettingsServices", path.join(appsettings, 'appsettings.services.json')); } \ No newline at end of file diff --git a/common/ASC.UrlShortener/app/log.js b/common/ASC.UrlShortener/app/log.js index d0fdb6093f..269282b9a1 100644 --- a/common/ASC.UrlShortener/app/log.js +++ b/common/ASC.UrlShortener/app/log.js @@ -22,7 +22,7 @@ if(logpath != null) const fileName = logpath ? path.join(logpath, "web.shorturl.%DATE%.log") : path.join(__dirname, "..", "..", "..", "Logs", "web.shorturl.%DATE%.log"); const dirName = path.dirname(fileName); -const aws = config.get("aws"); +const aws = config.get("aws").cloudWatch; const accessKeyId = aws.accessKeyId; const secretAccessKey = aws.secretAccessKey; @@ -65,6 +65,7 @@ var options = { .replace("${guid}", guid) .replace("${date}", dateAsString); }, + logGroupName: logGroupName, awsRegion: awsRegion, jsonMessage: true, awsOptions: { diff --git a/common/ASC.UrlShortener/config/config.json b/common/ASC.UrlShortener/config/config.json index 992264a4bf..f5a2b308df 100644 --- a/common/ASC.UrlShortener/config/config.json +++ b/common/ASC.UrlShortener/config/config.json @@ -3,12 +3,5 @@ "port": 9999, "appsettings": "../../../config", "environment": "Development" - }, - "aws":{ - "accessKeyId": "", - "secretAccessKey": "", - "region": "", - "logGroupName": "/asc/docspace/cluster/cluster_name/general", - "logStreamName": "${hostname} - ${applicationContext} - ${date} - ${guid}" } } \ No newline at end of file diff --git a/common/ASC.UrlShortener/config/index.js b/common/ASC.UrlShortener/config/index.js index 0f2cb7ad49..52a336f002 100644 --- a/common/ASC.UrlShortener/config/index.js +++ b/common/ASC.UrlShortener/config/index.js @@ -45,15 +45,10 @@ function getAndSaveAppsettings(){ } var env = nconf.get("app").environment; - var valueEnv = nconf.get(env); - var fileWithEnv = path.join(appsettings, 'appsettings.' + valueEnv + '.json'); - - if(fs.existsSync(fileWithEnv)){ - nconf.file("appsettings", fileWithEnv); - } - else{ - nconf.file("appsettings", path.join(appsettings, 'appsettings.json')); - } + console.log('environment: ' + env); + + nconf.file("appsettingsWithEnv", path.join(appsettings, 'appsettings.' + env + '.json')); + nconf.file("appsettings", path.join(appsettings, 'appsettings.json')); nconf.file("appsettingsServices", path.join(appsettings, 'appsettings.services.json')); } diff --git a/common/ASC.WebDav/helper/logger.js b/common/ASC.WebDav/helper/logger.js index 41718a9469..9a2d9439e1 100644 --- a/common/ASC.WebDav/helper/logger.js +++ b/common/ASC.WebDav/helper/logger.js @@ -21,6 +21,7 @@ const winston = require("winston"), date = require('date-and-time'), os = require("os"); + const { format } = require("winston"); require("winston-daily-rotate-file"); @@ -45,7 +46,27 @@ const fileTransport = new (winston.transports.DailyRotateFile)({ maxFiles: "30d" }); -const aws = config["aws"]; +const nconf = require("nconf"); + +nconf.argv() + .env(); + +var appsettings = config.appsettings; + +if(!path.isAbsolute(appsettings)){ + appsettings = path.join(__dirname, appsettings); +} + +var fileWithEnv = path.join(appsettings, 'appsettings.' + config.environment + '.json'); + +if(fs.existsSync(fileWithEnv)){ + nconf.file("appsettings", fileWithEnv); +} +else{ + nconf.file("appsettings", path.join(appsettings, 'appsettings.json')); +} + +const aws = nconf.get("aws").cloudWatch; const accessKeyId = aws.accessKeyId; const secretAccessKey = aws.secretAccessKey; @@ -75,6 +96,7 @@ if (aws != null && aws.accessKeyId !== '') .replace("${guid}", guid) .replace("${date}", dateAsString); }, + logGroupName: logGroupName, awsRegion: awsRegion, jsonMessage: true, awsOptions: { diff --git a/common/ASC.WebDav/package.json b/common/ASC.WebDav/package.json index 8218cda561..2ceb15b9ff 100644 --- a/common/ASC.WebDav/package.json +++ b/common/ASC.WebDav/package.json @@ -18,6 +18,7 @@ "form-data": "^3.0.0", "get-byte": "0.0.0", "help": "^3.0.2", + "nconf": "^0.10.0", "patch-package": "^6.4.7", "postinstall-postinstall": "^2.1.0", "request": "^2.88.0", diff --git a/common/ASC.WebDav/server/config.js b/common/ASC.WebDav/server/config.js index 04e35100cf..2475afb904 100644 --- a/common/ASC.WebDav/server/config.js +++ b/common/ASC.WebDav/server/config.js @@ -19,7 +19,9 @@ module.exports = { // Port listener WebDav Server - port: 1900, + port: 1900, + appsettings: "../../../config", + environment: "Development", // Path to pfx key pfxKeyPath: null, // Pass phrase for pfx key @@ -53,14 +55,6 @@ module.exports = { // Path to read the file fileHandlerPath: "/Products/Files/HttpHandlers/filehandler.ashx?action=stream&fileid={0}", - aws: { - "accessKeyId": "", - "secretAccessKey": "", - "region": "", - "logGroupName": "/asc/docspace/cluster/cluster_name/general", - "logStreamName": "${hostname} - ${applicationContext} - ${date} - ${guid}" - }, - method: { // Get root directory in "Root" pathRootDirectory: "@root", diff --git a/common/ASC.WebDav/yarn.lock b/common/ASC.WebDav/yarn.lock index 3f93ef4514..4b7c379aa0 100644 --- a/common/ASC.WebDav/yarn.lock +++ b/common/ASC.WebDav/yarn.lock @@ -872,6 +872,13 @@ __metadata: languageName: node linkType: hard +"ansi-regex@npm:^2.0.0": + version: 2.1.1 + resolution: "ansi-regex@npm:2.1.1" + checksum: 190abd03e4ff86794f338a31795d262c1dfe8c91f7e01d04f13f646f1dcb16c5800818f886047876f1272f065570ab86b24b99089f8b68a0e11ff19aed4ca8f1 + languageName: node + linkType: hard + "ansi-styles@npm:^3.2.1": version: 3.2.1 resolution: "ansi-styles@npm:3.2.1" @@ -922,6 +929,13 @@ __metadata: languageName: node linkType: hard +"async@npm:^1.4.0": + version: 1.5.2 + resolution: "async@npm:1.5.2" + checksum: fe5d6214d8f15bd51eee5ae8ec5079b228b86d2d595f47b16369dec2e11b3ff75a567bb5f70d12d79006665fbbb7ee0a7ec0e388524eefd454ecbe651c124ebd + languageName: node + linkType: hard + "async@npm:^3.1.0, async@npm:^3.2.3": version: 3.2.4 resolution: "async@npm:3.2.4" @@ -1045,6 +1059,13 @@ __metadata: languageName: node linkType: hard +"camelcase@npm:^2.0.1": + version: 2.1.1 + resolution: "camelcase@npm:2.1.1" + checksum: 20a3ef08f348de832631d605362ffe447d883ada89617144a82649363ed5860923b021f8e09681624ef774afb93ff3597cfbcf8aaf0574f65af7648f1aea5e50 + languageName: node + linkType: hard + "caseless@npm:~0.12.0": version: 0.12.0 resolution: "caseless@npm:0.12.0" @@ -1080,6 +1101,24 @@ __metadata: languageName: node linkType: hard +"cliui@npm:^3.0.3": + version: 3.2.0 + resolution: "cliui@npm:3.2.0" + dependencies: + string-width: ^1.0.1 + strip-ansi: ^3.0.1 + wrap-ansi: ^2.0.0 + checksum: c68d1dbc3e347bfe79ed19cc7f48007d5edd6cd8438342e32073e0b4e311e3c44e1f4f19221462bc6590de56c2df520e427533a9dde95dee25710bec322746ad + languageName: node + linkType: hard + +"code-point-at@npm:^1.0.0": + version: 1.1.0 + resolution: "code-point-at@npm:1.1.0" + checksum: 17d5666611f9b16d64fdf48176d9b7fb1c7d1c1607a189f7e600040a11a6616982876af148230336adb7d8fe728a559f743a4e29db3747e3b1a32fa7f4529681 + languageName: node + linkType: hard + "color-convert@npm:^1.9.0, color-convert@npm:^1.9.3": version: 1.9.3 resolution: "color-convert@npm:1.9.3" @@ -1259,6 +1298,13 @@ __metadata: languageName: node linkType: hard +"decamelize@npm:^1.1.1": + version: 1.2.0 + resolution: "decamelize@npm:1.2.0" + checksum: ad8c51a7e7e0720c70ec2eeb1163b66da03e7616d7b98c9ef43cce2416395e84c1e9548dd94f5f6ffecfee9f8b94251fc57121a8b021f2ff2469b2bae247b8aa + languageName: node + linkType: hard + "deep-is@npm:~0.1.3": version: 0.1.4 resolution: "deep-is@npm:0.1.4" @@ -1842,6 +1888,20 @@ __metadata: languageName: node linkType: hard +"ini@npm:^1.3.0": + version: 1.3.8 + resolution: "ini@npm:1.3.8" + checksum: dfd98b0ca3a4fc1e323e38a6c8eb8936e31a97a918d3b377649ea15bdb15d481207a0dda1021efbd86b464cae29a0d33c1d7dcaf6c5672bee17fa849bc50a1b3 + languageName: node + linkType: hard + +"invert-kv@npm:^1.0.0": + version: 1.0.0 + resolution: "invert-kv@npm:1.0.0" + checksum: aebeee31dda3b3d25ffd242e9a050926e7fe5df642d60953ab183aca1a7d1ffb39922eb2618affb0e850cf2923116f0da1345367759d88d097df5da1f1e1590e + languageName: node + linkType: hard + "ip@npm:^1.1.5": version: 1.1.8 resolution: "ip@npm:1.1.8" @@ -1897,6 +1957,15 @@ __metadata: languageName: node linkType: hard +"is-fullwidth-code-point@npm:^1.0.0": + version: 1.0.0 + resolution: "is-fullwidth-code-point@npm:1.0.0" + dependencies: + number-is-nan: ^1.0.0 + checksum: 4d46a7465a66a8aebcc5340d3b63a56602133874af576a9ca42c6f0f4bd787a743605771c5f246db77da96605fefeffb65fc1dbe862dcc7328f4b4d03edf5a57 + languageName: node + linkType: hard + "is-number@npm:^7.0.0": version: 7.0.0 resolution: "is-number@npm:7.0.0" @@ -2016,6 +2085,15 @@ __metadata: languageName: node linkType: hard +"lcid@npm:^1.0.0": + version: 1.0.0 + resolution: "lcid@npm:1.0.0" + dependencies: + invert-kv: ^1.0.0 + checksum: e8c7a4db07663068c5c44b650938a2bc41aa992037eebb69376214320f202c1250e70b50c32f939e28345fd30c2d35b8e8cd9a19d5932c398246a864ce54843d + languageName: node + linkType: hard + "levn@npm:~0.3.0": version: 0.3.0 resolution: "levn@npm:0.3.0" @@ -2176,6 +2254,18 @@ __metadata: languageName: node linkType: hard +"nconf@npm:^0.10.0": + version: 0.10.0 + resolution: "nconf@npm:0.10.0" + dependencies: + async: ^1.4.0 + ini: ^1.3.0 + secure-keys: ^1.0.0 + yargs: ^3.19.0 + checksum: 14052553bcde03dbdf11bc3ee95b8cdb7fe776ada550763df75c9683335a937545f62e96972ad2fd4bcc85f928d9880fc74b8c5f93eaddef58d6e0f46c0c836f + languageName: node + linkType: hard + "negotiator@npm:0.6.3": version: 0.6.3 resolution: "negotiator@npm:0.6.3" @@ -2197,6 +2287,13 @@ __metadata: languageName: node linkType: hard +"number-is-nan@npm:^1.0.0": + version: 1.0.1 + resolution: "number-is-nan@npm:1.0.1" + checksum: 13656bc9aa771b96cef209ffca31c31a03b507ca6862ba7c3f638a283560620d723d52e626d57892c7fff475f4c36ac07f0600f14544692ff595abff214b9ffb + languageName: node + linkType: hard + "oauth-sign@npm:~0.9.0": version: 0.9.0 resolution: "oauth-sign@npm:0.9.0" @@ -2269,6 +2366,15 @@ __metadata: languageName: node linkType: hard +"os-locale@npm:^1.4.0": + version: 1.4.0 + resolution: "os-locale@npm:1.4.0" + dependencies: + lcid: ^1.0.0 + checksum: 0161a1b6b5a8492f99f4b47fe465df9fc521c55ba5414fce6444c45e2500487b8ed5b40a47a98a2363fe83ff04ab033785300ed8df717255ec4c3b625e55b1fb + languageName: node + linkType: hard + "os-tmpdir@npm:~1.0.2": version: 1.0.2 resolution: "os-tmpdir@npm:1.0.2" @@ -2555,6 +2661,13 @@ __metadata: languageName: node linkType: hard +"secure-keys@npm:^1.0.0": + version: 1.0.0 + resolution: "secure-keys@npm:1.0.0" + checksum: 3dd4e64e6717fe6e2dc4c70e172982fcbad87b853e96566ab1cfaec540587f737bac106853ae469cb32d4a6413cfe80a28176cfe7dfcf7ddd35c9f92e58dffed + languageName: node + linkType: hard + "semver@npm:^5.5.0, semver@npm:^5.6.0": version: 5.7.1 resolution: "semver@npm:5.7.1" @@ -2717,6 +2830,17 @@ __metadata: languageName: node linkType: hard +"string-width@npm:^1.0.1": + version: 1.0.2 + resolution: "string-width@npm:1.0.2" + dependencies: + code-point-at: ^1.0.0 + is-fullwidth-code-point: ^1.0.0 + strip-ansi: ^3.0.0 + checksum: 5c79439e95bc3bd7233a332c5f5926ab2ee90b23816ed4faa380ce3b2576d7800b0a5bb15ae88ed28737acc7ea06a518c2eef39142dd727adad0e45c776cd37e + languageName: node + linkType: hard + "string_decoder@npm:^1.1.1": version: 1.3.0 resolution: "string_decoder@npm:1.3.0" @@ -2733,6 +2857,15 @@ __metadata: languageName: node linkType: hard +"strip-ansi@npm:^3.0.0, strip-ansi@npm:^3.0.1": + version: 3.0.1 + resolution: "strip-ansi@npm:3.0.1" + dependencies: + ansi-regex: ^2.0.0 + checksum: 9b974de611ce5075c70629c00fa98c46144043db92ae17748fb780f706f7a789e9989fd10597b7c2053ae8d1513fd707816a91f1879b2f71e6ac0b6a863db465 + languageName: node + linkType: hard + "strnum@npm:^1.0.5": version: 1.0.5 resolution: "strnum@npm:1.0.5" @@ -2972,6 +3105,7 @@ __metadata: form-data: ^3.0.0 get-byte: 0.0.0 help: ^3.0.2 + nconf: ^0.10.0 patch-package: ^6.4.7 postinstall-postinstall: ^2.1.0 request: ^2.88.0 @@ -2994,6 +3128,15 @@ __metadata: languageName: node linkType: hard +"window-size@npm:^0.1.4": + version: 0.1.4 + resolution: "window-size@npm:0.1.4" + bin: + window-size: cli.js + checksum: 409accca0b1373c69897400e3cc6a56a2acc8a6ba9009f0cd8e4adda4ebf308e50425d3bd375c0c08efb803c8f0b09d84d7266faa05422b3fadfe6ee422d0aef + languageName: node + linkType: hard + "winston-cloudwatch@npm:^6.1.1": version: 6.1.1 resolution: "winston-cloudwatch@npm:6.1.1" @@ -3064,6 +3207,16 @@ __metadata: languageName: node linkType: hard +"wrap-ansi@npm:^2.0.0": + version: 2.1.0 + resolution: "wrap-ansi@npm:2.1.0" + dependencies: + string-width: ^1.0.1 + strip-ansi: ^3.0.1 + checksum: 2dacd4b3636f7a53ee13d4d0fe7fa2ed9ad81e9967e17231924ea88a286ec4619a78288de8d41881ee483f4449ab2c0287cde8154ba1bd0126c10271101b2ee3 + languageName: node + linkType: hard + "wrappy@npm:1": version: 1.0.2 resolution: "wrappy@npm:1.0.2" @@ -3098,9 +3251,31 @@ __metadata: languageName: node linkType: hard +"y18n@npm:^3.2.0": + version: 3.2.2 + resolution: "y18n@npm:3.2.2" + checksum: 6154fd7544f8bbf5b18cdf77692ed88d389be49c87238ecb4e0d6a5276446cd2a5c29cc4bdbdddfc7e4e498b08df9d7e38df4a1453cf75eecfead392246ea74a + languageName: node + linkType: hard + "yallist@npm:^3.0.2": version: 3.1.1 resolution: "yallist@npm:3.1.1" checksum: 48f7bb00dc19fc635a13a39fe547f527b10c9290e7b3e836b9a8f1ca04d4d342e85714416b3c2ab74949c9c66f9cebb0473e6bc353b79035356103b47641285d languageName: node linkType: hard + +"yargs@npm:^3.19.0": + version: 3.32.0 + resolution: "yargs@npm:3.32.0" + dependencies: + camelcase: ^2.0.1 + cliui: ^3.0.3 + decamelize: ^1.1.1 + os-locale: ^1.4.0 + string-width: ^1.0.1 + window-size: ^0.1.4 + y18n: ^3.2.0 + checksum: 3e0f7fc1bc2052bcaaa7354cbd33d05a86fc0f236432d107ecd088989fbd175174c562d17e762727acbf25d04e8520d43625f7581b2a6ce55ce10034e80675fc + languageName: node + linkType: hard diff --git a/common/ASC.WebPlugins/config/config.json b/common/ASC.WebPlugins/config/config.json index c9d2e3e1cc..a49748f81d 100644 --- a/common/ASC.WebPlugins/config/config.json +++ b/common/ASC.WebPlugins/config/config.json @@ -3,12 +3,5 @@ "port": 5014, "appsettings": "../../../../config", "environment": "Development" - }, - "aws":{ - "accessKeyId": "", - "secretAccessKey": "", - "region": "", - "logGroupName": "/asc/docspace/cluster/cluster_name/general", - "logStreamName": "${hostname} - ${applicationContext} - ${date} - ${guid}" - } + } } diff --git a/common/ASC.WebPlugins/config/index.ts b/common/ASC.WebPlugins/config/index.ts index 04c3bde996..717142a267 100644 --- a/common/ASC.WebPlugins/config/index.ts +++ b/common/ASC.WebPlugins/config/index.ts @@ -18,16 +18,9 @@ function getAndSaveAppsettings() { } var env = nconf.get("app").environment; - - var valueEnv = nconf.get(env); - - var fileWithEnv = path.join(appsettings, "appsettings." + valueEnv + ".json"); - - if (fs.existsSync(fileWithEnv)) { - nconf.file("appsettings", fileWithEnv); - } else { - nconf.file("appsettings", path.join(appsettings, "appsettings.json")); - } - + console.log('environment: ' + env); + + nconf.file("appsettingsWithEnv", path.join(appsettings, 'appsettings.' + env + '.json')); + nconf.file("appsettings", path.join(appsettings, 'appsettings.json')); nconf.file("pluginsConf", path.join(appsettings, "plugins.json")); } diff --git a/common/ASC.WebPlugins/src/log.ts b/common/ASC.WebPlugins/src/log.ts index 9922473eb6..b3b3a08610 100644 --- a/common/ASC.WebPlugins/src/log.ts +++ b/common/ASC.WebPlugins/src/log.ts @@ -26,7 +26,7 @@ if (!fs.existsSync(dirName)) { fs.mkdirSync(dirName); } -const aws = config.default.get("aws"); +const aws = config.default.get("aws").cloudWatch; const accessKeyId = aws.accessKeyId; const secretAccessKey = aws.secretAccessKey; @@ -65,6 +65,7 @@ const options = { .replace("${guid}", guid) .replace("${date}", dateAsString); }, + logGroupName:logGroupName, awsRegion: awsRegion, jsonMessage: true, awsOptions: { diff --git a/common/services/ASC.Data.Backup.BackgroundTasks/Services/BackupCleanerService.cs b/common/services/ASC.Data.Backup.BackgroundTasks/Services/BackupCleanerService.cs index ccd97b1d43..a906d8e818 100644 --- a/common/services/ASC.Data.Backup.BackgroundTasks/Services/BackupCleanerService.cs +++ b/common/services/ASC.Data.Backup.BackgroundTasks/Services/BackupCleanerService.cs @@ -66,7 +66,7 @@ internal sealed class BackupCleanerService : BackgroundService continue; } - ExecuteBackupCleaner(stoppingToken); + await ExecuteBackupCleaner(stoppingToken); await Task.Delay(_backupCleanerPeriod, stoppingToken); } @@ -74,7 +74,7 @@ internal sealed class BackupCleanerService : BackgroundService _logger.DebugBackupCleanerServiceStopping(); } - private void ExecuteBackupCleaner(CancellationToken stoppingToken) + private async Task ExecuteBackupCleaner(CancellationToken stoppingToken) { using var serviceScope = _scopeFactory.CreateScope(); @@ -126,7 +126,7 @@ internal sealed class BackupCleanerService : BackgroundService continue; } - backupStorage.Delete(backupRecord.StoragePath); + await backupStorage.Delete(backupRecord.StoragePath); backupRepository.DeleteBackupRecord(backupRecord.Id); } diff --git a/common/services/ASC.Data.Backup/Api/BackupController.cs b/common/services/ASC.Data.Backup/Api/BackupController.cs index d1ec3f4614..6bfcc441c7 100644 --- a/common/services/ASC.Data.Backup/Api/BackupController.cs +++ b/common/services/ASC.Data.Backup/Api/BackupController.cs @@ -142,9 +142,9 @@ public class BackupController : ControllerBase /// Backup /// Backup History [HttpGet("getbackuphistory")] - public List GetBackupHistory() + public async Task> GetBackupHistory() { - return _backupHandler.GetBackupHistory(); + return await _backupHandler.GetBackupHistory(); } /// @@ -152,9 +152,9 @@ public class BackupController : ControllerBase /// /// Backup [HttpDelete("deletebackup/{id}")] - public bool DeleteBackup(Guid id) + public async Task DeleteBackup(Guid id) { - _backupHandler.DeleteBackup(id); + await _backupHandler.DeleteBackup(id); return true; } @@ -164,9 +164,9 @@ public class BackupController : ControllerBase /// Backup /// Backup History [HttpDelete("deletebackuphistory")] - public bool DeleteBackupHistory() + public async Task DeleteBackupHistory() { - _backupHandler.DeleteAllBackups(); + await _backupHandler.DeleteAllBackups(); return true; } diff --git a/common/services/ASC.ElasticSearch/Engine/BaseIndexer.cs b/common/services/ASC.ElasticSearch/Engine/BaseIndexer.cs index a082362000..8ff0de6475 100644 --- a/common/services/ASC.ElasticSearch/Engine/BaseIndexer.cs +++ b/common/services/ASC.ElasticSearch/Engine/BaseIndexer.cs @@ -208,9 +208,9 @@ public class BaseIndexer where T : class, ISearchItem _client.Instance.Indices.Refresh(new RefreshRequest(IndexName)); } - internal void Index(T data, bool immediately = true) + internal async Task Index(T data, bool immediately = true) { - if (!BeforeIndex(data)) + if (!(await BeforeIndex(data))) { return; } @@ -218,7 +218,7 @@ public class BaseIndexer where T : class, ISearchItem _client.Instance.Index(data, idx => GetMeta(idx, data, immediately)); } - internal void Index(List data, bool immediately = true) + internal async Task Index(List data, bool immediately = true) { if (data.Count == 0) { @@ -241,7 +241,7 @@ public class BaseIndexer where T : class, ISearchItem var t = data[i]; var runBulk = i == data.Count - 1; - BeforeIndex(t); + await BeforeIndex(t); if (t is not ISearchItemDocument wwd || wwd.Document == null || string.IsNullOrEmpty(wwd.Document.Data)) { @@ -254,7 +254,7 @@ public class BaseIndexer where T : class, ISearchItem { try { - Index(t, immediately); + await Index(t, immediately); } catch (ElasticsearchClientException e) { @@ -316,7 +316,7 @@ public class BaseIndexer where T : class, ISearchItem { foreach (var item in data) { - BeforeIndex(item); + await BeforeIndex(item); } _client.Instance.Bulk(r => r.IndexMany(data, GetMeta)); @@ -356,7 +356,7 @@ public class BaseIndexer where T : class, ISearchItem { try { - Index(t, immediately); + await Index(t, immediately); } catch (ElasticsearchClientException e) { @@ -523,9 +523,9 @@ public class BaseIndexer where T : class, ISearchItem return result.Documents; } - protected virtual bool BeforeIndex(T data) + protected virtual Task BeforeIndex(T data) { - return CheckExist(data); + return Task.FromResult(CheckExist(data)); } protected virtual Task BeforeIndexAsync(T data) diff --git a/common/services/ASC.ElasticSearch/Engine/FactoryIndexer.cs b/common/services/ASC.ElasticSearch/Engine/FactoryIndexer.cs index fac33f56ae..0d2cab10bc 100644 --- a/common/services/ASC.ElasticSearch/Engine/FactoryIndexer.cs +++ b/common/services/ASC.ElasticSearch/Engine/FactoryIndexer.cs @@ -49,7 +49,7 @@ public interface IFactoryIndexer { string IndexName { get; } string SettingsTitle { get; } - void IndexAll(); + Task IndexAll(); void ReIndex(); } @@ -170,7 +170,7 @@ public class FactoryIndexer : IFactoryIndexer where T : class, ISearchItem return Support(t) && _searchSettingsHelper.CanIndexByContent(_tenantManager.GetCurrentTenant().Id); } - public bool Index(T data, bool immediately = true) + public async Task Index(T data, bool immediately = true) { var t = _serviceProvider.GetService(); if (!Support(t)) @@ -180,7 +180,7 @@ public class FactoryIndexer : IFactoryIndexer where T : class, ISearchItem try { - _indexer.Index(data, immediately); + await _indexer.Index(data, immediately); return true; } @@ -192,7 +192,7 @@ public class FactoryIndexer : IFactoryIndexer where T : class, ISearchItem return false; } - public void Index(List data, bool immediately = true, int retry = 0) + public async Task Index(List data, bool immediately = true, int retry = 0) { var t = _serviceProvider.GetService(); if (!Support(t) || data.Count == 0) @@ -202,7 +202,7 @@ public class FactoryIndexer : IFactoryIndexer where T : class, ISearchItem try { - _indexer.Index(data, immediately); + await _indexer.Index(data, immediately); } catch (ElasticsearchClientException e) { @@ -214,14 +214,17 @@ public class FactoryIndexer : IFactoryIndexer where T : class, ISearchItem if (e.Response.HttpStatusCode == 413 || e.Response.HttpStatusCode == 403 || e.Response.HttpStatusCode == 408) { - data.Where(r => r != null).ToList().ForEach(r => Index(r, immediately)); + foreach (var r in data.Where(r => r != null)) + { + await Index(r, immediately); + } } else if (e.Response.HttpStatusCode == 429) { Thread.Sleep(60000); if (retry < 10) { - Index(data.Where(r => r != null).ToList(), immediately, retry + 1); + await Index(data.Where(r => r != null).ToList(), immediately, retry + 1); return; } @@ -246,14 +249,17 @@ public class FactoryIndexer : IFactoryIndexer where T : class, ISearchItem if (inner.Response.HttpStatusCode == 413 || inner.Response.HttpStatusCode == 403) { Logger.Error(inner.Response.HttpStatusCode.ToString()); - data.Where(r => r != null).ToList().ForEach(r => Index(r, immediately)); + foreach (var r in data.Where(r => r != null)) + { + await Index(r, immediately); + } } else if (inner.Response.HttpStatusCode == 429) { Thread.Sleep(60000); if (retry < 10) { - Index(data.Where(r => r != null).ToList(), immediately, retry + 1); + await Index(data.Where(r => r != null).ToList(), immediately, retry + 1); return; } @@ -294,7 +300,10 @@ public class FactoryIndexer : IFactoryIndexer where T : class, ISearchItem if (e.Response.HttpStatusCode == 413 || e.Response.HttpStatusCode == 403 || e.Response.HttpStatusCode == 408) { - data.Where(r => r != null).ToList().ForEach(r => Index(r, immediately)); + foreach (var r in data.Where(r => r != null)) + { + await Index(r, immediately); + } } else if (e.Response.HttpStatusCode == 429) { @@ -326,7 +335,10 @@ public class FactoryIndexer : IFactoryIndexer where T : class, ISearchItem if (inner.Response.HttpStatusCode == 413 || inner.Response.HttpStatusCode == 403) { Logger.Error(inner.Response.HttpStatusCode.ToString()); - data.Where(r => r != null).ToList().ForEach(r => Index(r, immediately)); + foreach (var r in data.Where(r => r != null)) + { + await Index(r, immediately); + } } else if (inner.Response.HttpStatusCode == 429) { @@ -459,7 +471,7 @@ public class FactoryIndexer : IFactoryIndexer where T : class, ISearchItem } } - public Task IndexAsync(T data, bool immediately = true) + public Task IndexAsync(T data, bool immediately = true) { var t = _serviceProvider.GetService(); @@ -521,9 +533,9 @@ public class FactoryIndexer : IFactoryIndexer where T : class, ISearchItem _indexer.Refresh(); } - public virtual void IndexAll() + public virtual Task IndexAll() { - return; + return Task.CompletedTask; } public void ReIndex() @@ -590,7 +602,31 @@ public class FactoryIndexer : IFactoryIndexer where T : class, ISearchItem throw; } + }, TaskCreationOptions.LongRunning); + task.ConfigureAwait(false); + task.Start(_scheduler); + + return task; + } + + private Task Queue(Func actionData) + { + var task = new Task(async () => + { + try + { + await actionData(); + } + catch (AggregateException agg) + { + foreach (var e in agg.InnerExceptions) + { + Logger.ErrorQueue(e); + } + + throw; + } }, TaskCreationOptions.LongRunning); task.ConfigureAwait(false); diff --git a/common/services/ASC.ElasticSearch/Service/ElasticSearchIndexService.cs b/common/services/ASC.ElasticSearch/Service/ElasticSearchIndexService.cs index ad3d3c4bff..5ff42fd3f5 100644 --- a/common/services/ASC.ElasticSearch/Service/ElasticSearchIndexService.cs +++ b/common/services/ASC.ElasticSearch/Service/ElasticSearchIndexService.cs @@ -61,7 +61,7 @@ public class ElasticSearchIndexService : BackgroundService { await Task.Delay(10000); } - IndexAll(true); + await IndexAll(true); }, CacheNotifyAction.Any); } catch (Exception e) @@ -87,13 +87,13 @@ public class ElasticSearchIndexService : BackgroundService while (!stoppingToken.IsCancellationRequested) { - IndexAll(); + await IndexAll(); await Task.Delay(_period, stoppingToken); } } - public void IndexProduct(IFactoryIndexer product, bool reindex) + public async Task IndexProduct(IFactoryIndexer product, bool reindex) { if (reindex) { @@ -122,7 +122,7 @@ public class ElasticSearchIndexService : BackgroundService _logger.DebugProduct(product.IndexName); _indexNotify.Publish(new IndexAction() { Indexing = product.IndexName, LastIndexed = 0 }, CacheNotifyAction.Any); - product.IndexAll(); + await product.IndexAll(); } catch (Exception e) { @@ -130,7 +130,7 @@ public class ElasticSearchIndexService : BackgroundService } } - private void IndexAll(bool reindex = false) + private async Task IndexAll(bool reindex = false) { try { @@ -143,11 +143,11 @@ public class ElasticSearchIndexService : BackgroundService wrappers = scope.ServiceProvider.GetService>().Select(r => r.GetType()).ToList(); } - Parallel.ForEach(wrappers, wrapper => + await Parallel.ForEachAsync(wrappers, async (wrapper, token) => { using (var scope = _serviceScopeFactory.CreateScope()) { - IndexProduct((IFactoryIndexer)scope.ServiceProvider.GetRequiredService(wrapper), reindex); + await IndexProduct((IFactoryIndexer)scope.ServiceProvider.GetRequiredService(wrapper), reindex); } }); diff --git a/common/services/ASC.Feed.Aggregator/Modules/FeedModule.cs b/common/services/ASC.Feed.Aggregator/Modules/FeedModule.cs index 4a2a3ffd09..473d167c70 100644 --- a/common/services/ASC.Feed.Aggregator/Modules/FeedModule.cs +++ b/common/services/ASC.Feed.Aggregator/Modules/FeedModule.cs @@ -43,15 +43,15 @@ public abstract class FeedModule : IFeedModule _webItemSecurity = webItemSecurity; } - public abstract IEnumerable> GetFeeds(FeedFilter filter); + public abstract Task>> GetFeeds(FeedFilter filter); - public abstract IEnumerable GetTenantsWithFeeds(DateTime fromTime); + public abstract Task> GetTenantsWithFeeds(DateTime fromTime); - public virtual void VisibleFor(List> feed, Guid userId) + public virtual Task VisibleFor(List> feed, Guid userId) { if (!_webItemSecurity.IsAvailableForUser(ProductID, userId)) { - return; + return Task.CompletedTask; } foreach (var tuple in feed) @@ -61,6 +61,7 @@ public abstract class FeedModule : IFeedModule tuple.Item1.Users.Add(userId); } } + return Task.CompletedTask; } public virtual bool VisibleFor(Feed feed, object data, Guid userId) diff --git a/common/services/ASC.Feed.Aggregator/Modules/IFeedModule.cs b/common/services/ASC.Feed.Aggregator/Modules/IFeedModule.cs index fed1dd7149..bb33f5aab0 100644 --- a/common/services/ASC.Feed.Aggregator/Modules/IFeedModule.cs +++ b/common/services/ASC.Feed.Aggregator/Modules/IFeedModule.cs @@ -32,11 +32,11 @@ public interface IFeedModule string Product { get; } - IEnumerable GetTenantsWithFeeds(DateTime fromTime); + Task> GetTenantsWithFeeds(DateTime fromTime); - IEnumerable> GetFeeds(FeedFilter filter); + Task>> GetFeeds(FeedFilter filter); bool VisibleFor(Feed feed, object data, Guid userId); - void VisibleFor(List> feed, Guid userId); + Task VisibleFor(List> feed, Guid userId); } diff --git a/common/services/ASC.Feed.Aggregator/Service/FeedAggregatorService.cs b/common/services/ASC.Feed.Aggregator/Service/FeedAggregatorService.cs index 6e47b3f7f5..ba96443d0f 100644 --- a/common/services/ASC.Feed.Aggregator/Service/FeedAggregatorService.cs +++ b/common/services/ASC.Feed.Aggregator/Service/FeedAggregatorService.cs @@ -51,7 +51,7 @@ public class FeedAggregatorService : FeedBaseService while (!stoppingToken.IsCancellationRequested) { - AggregateFeeds(cfg.AggregateInterval); + await AggregateFeeds(cfg.AggregateInterval); await Task.Delay(cfg.AggregatePeriod, stoppingToken); } @@ -59,14 +59,14 @@ public class FeedAggregatorService : FeedBaseService _logger.InformationAggregatorServiceStopping(); } - private static T Attempt(int count, Func action) + private static async Task Attempt(int count, Func> action) { var counter = 0; while (true) { try { - return action(); + return await action(); } catch { @@ -91,7 +91,7 @@ public class FeedAggregatorService : FeedBaseService } } - private void AggregateFeeds(object interval) + private async Task AggregateFeeds(object interval) { try { @@ -124,7 +124,7 @@ public class FeedAggregatorService : FeedBaseService var toTime = DateTime.UtcNow; - var tenants = Attempt(10, () => module.GetTenantsWithFeeds(fromTime)).ToList(); + var tenants = (await Attempt(10, async () => await module.GetTenantsWithFeeds(fromTime))).ToList(); _logger.DebugFindCountTenants(tenants.Count, module.GetType().Name); foreach (var tenant in tenants) @@ -145,7 +145,7 @@ public class FeedAggregatorService : FeedBaseService tenantManager.SetCurrentTenant(tenant); var users = userManager.GetUsers(); - var feeds = Attempt(10, () => module.GetFeeds(new FeedFilter(fromTime, toTime) { Tenant = tenant }).Where(r => r.Item1 != null).ToList()); + var feeds = await Attempt(10, async () => (await module.GetFeeds(new FeedFilter(fromTime, toTime) { Tenant = tenant })).Where(r => r.Item1 != null).ToList()); _logger.DebugCountFeeds(feeds.Count, tenant); var tenant1 = tenant; @@ -165,7 +165,7 @@ public class FeedAggregatorService : FeedBaseService continue; } - module.VisibleFor(feedsRow, u.Id); + await module.VisibleFor(feedsRow, u.Id); } result.AddRange(feedsRow.Select(r => r.Item1)); diff --git a/config/appsettings.json b/config/appsettings.json index 0b28a0da74..2883f8a616 100644 --- a/config/appsettings.json +++ b/config/appsettings.json @@ -240,5 +240,14 @@ "plugins": { "enabled": "false", "allow": ["upload", "delete"] - } + }, + "aws": { + "cloudWatch": { + "accessKeyId": "", + "secretAccessKey": "", + "region": "us-east-1", + "logGroupName": "/asc/docspace/cluster/cluster_name/general", + "logStreamName": "${hostname} - ${applicationContext} - ${date} - ${guid}" + } + } } \ No newline at end of file diff --git a/config/redis.test.json b/config/redis.test.json deleted file mode 100644 index fb4f128368..0000000000 --- a/config/redis.test.json +++ /dev/null @@ -1,14 +0,0 @@ -{ - "Redis": { - "Ssl": false, - "ConnectTimeout": 5000, - "SyncTimeout": 60000, - "ConnectRetry": 2, - "Database": 0, - "Hosts": [ - { - "Host": "127.0.0.1", - "Port": "6379" - }] - } -} \ No newline at end of file diff --git a/packages/client/package.json b/packages/client/package.json index 57e48abf7e..6495afb7cd 100644 --- a/packages/client/package.json +++ b/packages/client/package.json @@ -8,7 +8,7 @@ "clean": "shx rm -rf dist", "deploy": "shx --silent mkdir -p ../../build/deploy/client && shx cp -r dist/* ../../build/deploy/client", "start": "NODE_OPTIONS=--openssl-legacy-provider webpack-cli serve", - "start-prod": "NODE_OPTIONS=--openssl-legacy-provider webpack --mode production && serve dist -p 5001" + "start-prod": "serve dist -s -p 5001" }, "old-scripts": { "build:test": "webpack --env minimize=false --mode production", @@ -71,7 +71,7 @@ "playwright": "^1.18.1", "sass": "^1.39.2", "sass-loader": "^12.1.0", - "serve": "12.0.1", + "serve": "14.1.1", "shx": "^0.3.3", "source-map-loader": "^3.0.0", "style-loader": "3.2.1", diff --git a/packages/client/public/locales/en/Files.json b/packages/client/public/locales/en/Files.json index 4c5a979884..c91453f6f2 100644 --- a/packages/client/public/locales/en/Files.json +++ b/packages/client/public/locales/en/Files.json @@ -1,4 +1,5 @@ { + "AddMembersDescription": "You can add new team members manually or invite them via link.", "All": "All", "Archived": "Move to archive", "ArchiveAction": "Empty archive", @@ -7,6 +8,7 @@ "AllFiles": "All files", "Archives": "Archives", "ArchiveEmptyScreen": "You can archive rooms you don’t use and restore them in your DocSpace at any moment or delete them permanently. These rooms will appear here.", + "ArchiveEmptyScreenUser": "Rooms that have been archived will appear here.", "ArchiveEmptyScreenHeader": "No archived rooms here yet", "BackToParentFolderButton": "Back to parent folder", "ByAuthor": "Author", @@ -50,6 +52,7 @@ "GoToPersonal": "Go to Personal", "Images": "Images", "InviteUsers": "Invite users", + "InviteUsersInRoom": "Invite users in room", "LinkForPortalUsers": "Link for portal users", "MarkAsFavorite": "Mark as favorite", "MarkRead": "Mark as read", @@ -89,6 +92,7 @@ "RemovedFromFavorites": "Removed from favorites", "Rename": "Rename", "ReviewRooms": "Review", + "RoomCreated": "Room created!", "RoomEmptyContainerDescription": "Please create the first room.", "RoomEmptyContainerDescriptionUser": "Rooms shared with you will appear here", "RoomRemoved": "Room removed", diff --git a/packages/client/src/HOCs/withBadges.js b/packages/client/src/HOCs/withBadges.js index 0a57219265..b89ba00db1 100644 --- a/packages/client/src/HOCs/withBadges.js +++ b/packages/client/src/HOCs/withBadges.js @@ -12,6 +12,12 @@ import config from "PACKAGE_FILE"; export default function withBadges(WrappedComponent) { class WithBadges extends React.Component { + constructor(props) { + super(props); + + this.state = { disableBadgeClick: false, disableUnpinClick: false }; + } + onShowVersionHistory = () => { const { homepage, @@ -28,22 +34,42 @@ export default function withBadges(WrappedComponent) { }; onBadgeClick = () => { + if (this.state.disableBadgeClick) return; + const { item, markAsRead, setNewFilesPanelVisible } = this.props; + this.setState(() => ({ + disableBadgeClick: true, + })); + + const enableBadgeClick = () => { + this.setState({ disableBadgeClick: false }); + }; + if (item.fileExst) { - markAsRead([], [item.id], item); + markAsRead([], [item.id], item).then(() => { + enableBadgeClick(); + }); } else { - setNewFilesPanelVisible(true, null, item); + setNewFilesPanelVisible(true, null, item).then(() => { + enableBadgeClick(); + }); } }; onUnpinClick = (e) => { + if (this.state.disableUnpinClick) return; + + this.setState({ disableUnpinClick: true }); + const { t, setPinAction } = this.props; const { action, id } = e.target.closest(".is-pinned").dataset; if (!action && !id) return; - setPinAction(action, id, t); + setPinAction(action, id, t).then(() => { + this.setState({ disableUnpinClick: false }); + }); }; setConvertDialogVisible = () => { diff --git a/packages/client/src/components/Article/Body/Items.js b/packages/client/src/components/Article/Body/Items.js index 2e2bb0b23b..168613c6e9 100644 --- a/packages/client/src/components/Article/Body/Items.js +++ b/packages/client/src/components/Article/Body/Items.js @@ -11,11 +11,17 @@ import { import { withTranslation } from "react-i18next"; import DragAndDrop from "@docspace/components/drag-and-drop"; import { isMobile } from "react-device-detect"; +import SettingsItem from "./SettingsItem"; +import AccountsItem from "./AccountsItem"; const StyledDragAndDrop = styled(DragAndDrop)` display: contents; `; +const CatalogDivider = styled.div` + height: 16px; +`; + const Item = ({ t, item, @@ -152,6 +158,7 @@ const Items = ({ trashIsEmpty, onHide, + firstLoad, }) => { useEffect(() => { data.forEach((elem) => { @@ -329,44 +336,11 @@ const Items = ({ ); }); - const roomsHeader = ( - - ); + if (!firstLoad) items.splice(3, 0, ); + if (!isVisitor) items.splice(3, 0, ); - const filesHeader = ( - - ); - - const otherHeader = ( - - ); - - if (isVisitor) { - items.length > 2 && items.splice(2, 0, filesHeader); - } else { - items.splice(3, 0, filesHeader); - } - - items.unshift(roomsHeader); - items.push(otherHeader); + if (!isVisitor) items.splice(3, 0, ); + else items.splice(2, 0, ); return items; }, @@ -386,6 +360,8 @@ const Items = ({ uploadEmptyFolders, trashIsEmpty, isAdmin, + isVisitor, + firstLoad, ] ); @@ -417,6 +393,7 @@ export default inject( setDragging, setStartDrag, trashIsEmpty, + firstLoad, } = filesStore; const { startUpload } = uploadDataStore; @@ -455,6 +432,7 @@ export default inject( setEmptyTrashDialogVisible, trashIsEmpty, rootFolderType, + firstLoad, }; } )(withTranslation(["Files", "Common", "Translations"])(observer(Items))); diff --git a/packages/client/src/components/Article/Body/index.js b/packages/client/src/components/Article/Body/index.js index 36576126b7..179b43318b 100644 --- a/packages/client/src/components/Article/Body/index.js +++ b/packages/client/src/components/Article/Body/index.js @@ -9,8 +9,6 @@ import Items from "./Items"; import { isMobile, tablet } from "@docspace/components/utils/device"; import FilesFilter from "@docspace/common/api/files/filter"; import RoomsFilter from "@docspace/common/api/rooms/filter"; -import SettingsItem from "./SettingsItem"; -import AccountsItem from "./AccountsItem"; import { combineUrl } from "@docspace/common/utils"; import { isDesktop, isTablet, isMobileOnly } from "react-device-detect"; //import ThirdPartyList from "./ThirdPartyList"; @@ -51,6 +49,8 @@ const ArticleBodyContent = (props) => { archiveFolderId, } = props; + const [disableBadgeClick, setDisableBadgeClick] = React.useState(false); + const campaigns = (localStorage.getItem("campaigns") || "") .split(",") .filter((campaign) => campaign.length > 0); @@ -150,9 +150,18 @@ const ArticleBodyContent = (props) => { [categoryType, roomsFolderId, archiveFolderId] ); - const onShowNewFilesPanel = React.useCallback((folderId) => { - props.setNewFilesPanelVisible(true, [`${folderId}`]); - }, []); + const onShowNewFilesPanel = React.useCallback( + async (folderId) => { + if (disableBadgeClick) return; + + setDisableBadgeClick(true); + + await props.setNewFilesPanelVisible(true, [`${folderId}`]); + + setDisableBadgeClick(false); + }, + [disableBadgeClick] + ); return ( <> @@ -162,8 +171,7 @@ const ArticleBodyContent = (props) => { showText={showText} onHide={toggleArticleOpen} /> - {!personal && !isVisitor && } - {!personal && !firstLoad && } + {!isDesktopClient && showText && !docSpace && ( {/* {enableThirdParty && !isVisitor && } */} diff --git a/packages/client/src/components/Article/MainButton/index.js b/packages/client/src/components/Article/MainButton/index.js index 1eb403aaba..b8a3d9237d 100644 --- a/packages/client/src/components/Article/MainButton/index.js +++ b/packages/client/src/components/Article/MainButton/index.js @@ -124,7 +124,6 @@ const ArticleMainButtonContent = (props) => { ); const onCreateRoom = React.useCallback(() => { - console.log("click"); const event = new Event(Events.ROOM_CREATE); window.dispatchEvent(event); }, []); diff --git a/packages/client/src/components/EmptyContainer/EmptyContainer.js b/packages/client/src/components/EmptyContainer/EmptyContainer.js index b54150f166..d573229a70 100644 --- a/packages/client/src/components/EmptyContainer/EmptyContainer.js +++ b/packages/client/src/components/EmptyContainer/EmptyContainer.js @@ -53,9 +53,18 @@ const EmptyFolderWrapper = styled.div` grid-column-gap: 8px; } + .second-description { + display: grid; + grid-template-columns: 1fr; + + margin: 32px 0 26px !important; + } + .flex-wrapper_container { display: flex; flex-wrap: wrap; + + row-gap: 16px; } .empty-folder_container-image { diff --git a/packages/client/src/components/EmptyContainer/EmptyFolderContainer.js b/packages/client/src/components/EmptyContainer/EmptyFolderContainer.js index a6479d97a5..cab1bd199c 100644 --- a/packages/client/src/components/EmptyContainer/EmptyFolderContainer.js +++ b/packages/client/src/components/EmptyContainer/EmptyFolderContainer.js @@ -4,6 +4,7 @@ import { withTranslation } from "react-i18next"; import EmptyContainer from "./EmptyContainer"; import Link from "@docspace/components/link"; import Box from "@docspace/components/box"; +import { Text } from "@docspace/components"; const EmptyFolderContainer = ({ t, @@ -16,6 +17,10 @@ const EmptyFolderContainer = ({ isRooms, sectionWidth, canCreateFiles, + canInviteUsers, + setIsEmptyPage, + onClickInviteUsers, + folderId, }) => { const onBackToParentFolder = () => { setIsLoading(true); @@ -25,6 +30,18 @@ const EmptyFolderContainer = ({ : fetchFiles(parentId).finally(() => setIsLoading(false)); }; + React.useEffect(() => { + setIsEmptyPage(true); + + return () => setIsEmptyPage(false); + }, []); + + const onInviteUsersClick = () => { + if (!isRooms) return; + + onClickInviteUsers && onClickInviteUsers(folderId); + }; + const buttons = canCreateFiles ? ( <>
@@ -63,18 +80,45 @@ const EmptyFolderContainer = ({
-
- up_icon + {isRooms ? ( + canInviteUsers ? ( + <> +
+ + {t("AddMembersDescription")} + +
- - {t("BackToParentFolderButton")} - -
+
+ up_icon + + + {t("InviteUsersInRoom")} + +
+ + ) : ( + <> + ) + ) : ( +
+ up_icon + + + {t("BackToParentFolderButton")} + +
+ )} ) : ( <> @@ -82,14 +126,18 @@ const EmptyFolderContainer = ({ return ( { - const { fetchFiles, fetchRooms } = filesStore; - const { navigationPath, parentId } = selectedFolderStore; + ({ + accessRightsStore, + filesStore, + selectedFolderStore, + contextOptionsStore, + }) => { + const { fetchFiles, fetchRooms, setIsEmptyPage } = filesStore; + const { + navigationPath, + parentId, + access, + id: folderId, + } = selectedFolderStore; let isRootRoom, isRoom, id; if (navigationPath && navigationPath.length) { @@ -111,7 +169,11 @@ export default inject( id = elem.id; } - const { canCreateFiles } = accessRightsStore; + const { canCreateFiles, canInviteUserInRoom } = accessRightsStore; + + const { onClickInviteUsers } = contextOptionsStore; + + const canInviteUsers = canInviteUserInRoom({ access }); return { fetchFiles, @@ -120,6 +182,10 @@ export default inject( parentId: id ?? parentId, isRooms: isRoom || isRootRoom, canCreateFiles, + canInviteUsers, + setIsEmptyPage, + onClickInviteUsers, + folderId, }; } )(withTranslation(["Files", "Translations"])(observer(EmptyFolderContainer))); diff --git a/packages/client/src/components/EmptyContainer/RootFolderContainer.js b/packages/client/src/components/EmptyContainer/RootFolderContainer.js index 73cb33da20..b923797be2 100644 --- a/packages/client/src/components/EmptyContainer/RootFolderContainer.js +++ b/packages/client/src/components/EmptyContainer/RootFolderContainer.js @@ -63,7 +63,9 @@ const RootFolderContainer = (props) => { const roomsDescription = isVisitor ? t("RoomEmptyContainerDescriptionUser") : t("RoomEmptyContainerDescription"); - const archiveRoomsDescription = t("ArchiveEmptyScreen"); + const archiveRoomsDescription = isVisitor + ? t("ArchiveEmptyScreenUser") + : t("ArchiveEmptyScreen"); const privateRoomHeader = t("PrivateRoomHeader"); const privacyIcon = ; @@ -289,7 +291,7 @@ const RootFolderContainer = (props) => { ); - const archiveButtons = ( + const archiveButtons = !isVisitor && (
{ const { t } = useTranslation(["CreateEditRoomDialog", "Common", "Files"]); const [fetchedTags, setFetchedTags] = useState([]); @@ -50,7 +54,7 @@ const CreateRoomEvent = ({ setIsLoading(true); // create room - const room = + let room = isThirdparty && storageFolderId ? await createRoomInThirdpary(storageFolderId, createRoomData) : await createRoom(createRoomData); @@ -64,7 +68,7 @@ const CreateRoomEvent = ({ await createTag(createTagsData[i]); // add new tags to room - await addTagsToRoom(room.id, addTagsData); + room = await addTagsToRoom(room.id, addTagsData); // calculate and upload logo to room if (roomParams.icon.uploadedFile) @@ -73,19 +77,26 @@ const CreateRoomEvent = ({ const img = new Image(); img.onload = async () => { const { x, y, zoom } = roomParams.icon; - await addLogoToRoom(room.id, { + room = await addLogoToRoom(room.id, { tmpFile: response.data, ...calculateRoomLogoParams(img, x, y, zoom), }); + + !withPaging && addFile(room, true); + URL.revokeObjectURL(img.src); }; img.src = url; }); + else !withPaging && addFile(room, true); } catch (err) { toastr.error(err); console.log(err); } finally { - await updateCurrentFolder(null, currrentFolderId); + if (withPaging) { + await updateCurrentFolder(null, currrentFolderId); + } + setIsLoading(false); onClose(); } @@ -96,6 +107,12 @@ const CreateRoomEvent = ({ setFetchedTags(tags); }, []); + useEffect(() => { + setCreateRoomDialogVisible(true); + + return () => setCreateRoomDialogVisible(false); + }, []); + return ( { const { t } = useTranslation(["CreateEditRoomDialog", "Common", "Files"]); @@ -72,14 +75,14 @@ const EditRoomEvent = ({ try { setIsLoading(true); - const room = await editRoom(item.id, editRoomParams); + let room = await editRoom(item.id, editRoomParams); for (let i = 0; i < newTags.length; i++) await createTag(newTags[i]); - await addTagsToRoom(room.id, tags); - await removeTagsFromRoom(room.id, removedTags); + room = await addTagsToRoom(room.id, tags); + room = await removeTagsFromRoom(room.id, removedTags); if (!!item.logo.original && !roomParams.icon.uploadedFile) - await removeLogoFromRoom(room.id); + room = await removeLogoFromRoom(room.id); if (roomParams.icon.uploadedFile) { await setFolder({ @@ -91,19 +94,24 @@ const EditRoomEvent = ({ const img = new Image(); img.onload = async () => { const { x, y, zoom } = roomParams.icon; - await addLogoToRoom(room.id, { + room = await addLogoToRoom(room.id, { tmpFile: response.data, ...calculateRoomLogoParams(img, x, y, zoom), }); + + !withPaging && setFolder(room); + URL.revokeObjectURL(img.src); }; img.src = url; }); - } + } else !withPaging && setFolder(room); } catch (err) { console.log(err); } finally { - await updateCurrentFolder(null, currentFolderId); + if (withPaging) { + await updateCurrentFolder(null, currentFolderId); + } setIsLoading(false); onClose(); } @@ -129,6 +137,12 @@ const EditRoomEvent = ({ setFetchedTags(tags); }, []); + useEffect(() => { + setCreateRoomDialogVisible(true); + + return () => setCreateRoomDialogVisible(false); + }, []); + return ( { const { @@ -166,6 +182,8 @@ export default inject( const { id: currentFolderId } = selectedFolderStore; const { updateCurrentFolder } = filesActionsStore; const { getThirdPartyIcon } = settingsStore.thirdPartyStore; + const { setCreateRoomDialogVisible } = dialogsStore; + const { withPaging } = auth.settingsStore; return { editRoom, @@ -185,6 +203,9 @@ export default inject( currentFolderId, updateCurrentFolder, + + withPaging, + setCreateRoomDialogVisible, }; } )(observer(EditRoomEvent)); diff --git a/packages/client/src/components/MainBar/ConfirmEmailBar.js b/packages/client/src/components/MainBar/ConfirmEmailBar.js index 1dd3ea50f3..83cd6fb7a6 100644 --- a/packages/client/src/components/MainBar/ConfirmEmailBar.js +++ b/packages/client/src/components/MainBar/ConfirmEmailBar.js @@ -14,21 +14,23 @@ const StyledLink = styled(Link)` color: #316daa; `; -const ConfirmEmailBar = ({ t, onClick, onClose, onLoad }) => { +const ConfirmEmailBar = ({ t, tReady, onClick, onClose, onLoad }) => { return ( - - {t("ConfirmEmailDescription")}{" "} - {t("RequestActivation")} - - } - isCampaigns={false} - opacity={1} - onLoad={onLoad} - clickAction={onClose} - /> + tReady && ( + + {t("ConfirmEmailDescription")}{" "} + {t("RequestActivation")} + + } + isCampaigns={false} + opacity={1} + onLoad={onLoad} + clickAction={onClose} + /> + ) ); }; diff --git a/packages/client/src/components/MainBar/QuotasBar.js b/packages/client/src/components/MainBar/QuotasBar.js index 4520a7db31..16a46648e2 100644 --- a/packages/client/src/components/MainBar/QuotasBar.js +++ b/packages/client/src/components/MainBar/QuotasBar.js @@ -16,6 +16,7 @@ const StyledLink = styled(Link)` const QuotasBar = ({ t, + tReady, isRoomQuota, currentValue, maxValue, @@ -57,24 +58,28 @@ const QuotasBar = ({ ), }; - return isRoomQuota ? ( - + return tReady ? ( + isRoomQuota ? ( + + ) : ( + + ) ) : ( - + <> ); }; diff --git a/packages/client/src/components/MainBar/index.js b/packages/client/src/components/MainBar/index.js index 6b90d71bb7..289c39138b 100644 --- a/packages/client/src/components/MainBar/index.js +++ b/packages/client/src/components/MainBar/index.js @@ -11,8 +11,8 @@ const StyledContainer = styled.div` ${isMobileOnly && css` - width: calc(100% + 8px); - max-width: calc(100% + 8px); + width: calc(100% + 16px); + max-width: calc(100% + 16px); margin-right: -16px; margin-top: 48px; diff --git a/packages/client/src/components/QuickButtons.js b/packages/client/src/components/QuickButtons.js index 3ed2c82050..5d257f5c5c 100644 --- a/packages/client/src/components/QuickButtons.js +++ b/packages/client/src/components/QuickButtons.js @@ -83,7 +83,7 @@ const QuickButtons = (props) => { hoverColor={theme.filesQuickButtons.sharedColor} /> )} - {fileExst && !isTrashFolder && displayBadges && ( + {/* {fileExst && !isTrashFolder && displayBadges && ( { onClick={setFavorite} hoverColor={theme.filesQuickButtons.hoverColor} /> - )} + )} */}
); }; diff --git a/packages/client/src/components/dialogs/ArchiveDialog/index.js b/packages/client/src/components/dialogs/ArchiveDialog/index.js index cf500671f3..b3bab75d72 100644 --- a/packages/client/src/components/dialogs/ArchiveDialog/index.js +++ b/packages/client/src/components/dialogs/ArchiveDialog/index.js @@ -128,7 +128,7 @@ const ArchiveDialog = withTranslation(["Files", "ArchiveDialog", "Common"])( ); export default inject(({ filesStore, filesActionsStore, dialogsStore }) => { - const { folders, selection, bufferSelection } = filesStore; + const { roomsForRestore, selection, bufferSelection } = filesStore; const { setArchiveAction } = filesActionsStore; const { @@ -142,7 +142,7 @@ export default inject(({ filesStore, filesActionsStore, dialogsStore }) => { } = dialogsStore; const items = restoreAll - ? folders + ? roomsForRestore : selection.length > 0 ? selection : [bufferSelection]; diff --git a/packages/client/src/components/dialogs/CreateEditRoomDialog/sub-components/StyledDropdown.js b/packages/client/src/components/dialogs/CreateEditRoomDialog/sub-components/StyledDropdown.js index c1228ff776..15c69e923f 100644 --- a/packages/client/src/components/dialogs/CreateEditRoomDialog/sub-components/StyledDropdown.js +++ b/packages/client/src/components/dialogs/CreateEditRoomDialog/sub-components/StyledDropdown.js @@ -45,6 +45,13 @@ const StyledDropDown = styled(DropDown)` font-weight: 400; font-size: 13px; line-height: 20px; + + display: block; + + white-space: nowrap; + overflow: hidden; + text-overflow: ellipsis; + &:hover { background: ${(props) => props.theme.createEditRoomDialog.dropdown.item.hoverBackground}; diff --git a/packages/client/src/components/dialogs/CreateEditRoomDialog/sub-components/TagInput/TagDropdown.js b/packages/client/src/components/dialogs/CreateEditRoomDialog/sub-components/TagInput/TagDropdown.js index d935aca2be..e23592a156 100644 --- a/packages/client/src/components/dialogs/CreateEditRoomDialog/sub-components/TagInput/TagDropdown.js +++ b/packages/client/src/components/dialogs/CreateEditRoomDialog/sub-components/TagInput/TagDropdown.js @@ -18,6 +18,14 @@ const TagDropdown = ({ const [dropdownMaxHeight, setDropdownMaxHeight] = useState(0); + useEffect(() => { + document.getElementById("tags-input").addEventListener("keyup", onKeyPress); + + return () => document.removeEventListener("keyup", onKeyPress); + }); + + const onKeyPress = (e) => e.key === "Enter" && addNewTag(); + const chosenTags = tagHandler.tags.map((tag) => tag.name); const tagsForDropdown = tagHandler.fetchedTags.filter( diff --git a/packages/client/src/components/panels/NewFilesPanel/index.js b/packages/client/src/components/panels/NewFilesPanel/index.js index 524f18e532..9ffbd5db43 100644 --- a/packages/client/src/components/panels/NewFilesPanel/index.js +++ b/packages/client/src/components/panels/NewFilesPanel/index.js @@ -33,6 +33,7 @@ class NewFilesPanel extends React.Component { state = { readingFiles: [], inProgress: false }; onClose = () => { + if (this.state.inProgress) return; this.props.setNewFilesPanelVisible(false); }; @@ -52,16 +53,27 @@ class NewFilesPanel extends React.Component { }; onMarkAsRead = () => { - const fileIds = []; - const folderIds = []; - - for (let item of this.props.newFiles) { - if (item.fileExst) fileIds.push(item.id); - else folderIds.push(item.id); - } + const { inProgress, readingFiles } = this.state; + if (inProgress) return; this.setState({ inProgress: true }); + const files = []; + const folders = []; + + for (let item of this.props.newFiles) { + if (item.fileExst) files.push(item); + else folders.push(item); + } + + const fileIds = files + .filter((f) => !readingFiles.includes(f.id.toString())) + .map((f) => f.id); + + const folderIds = folders + .filter((f) => !readingFiles.includes(f.id.toString())) + .map((f) => f.id); + this.props .markAsRead(folderIds, fileIds) .then(() => this.setNewBadgeCount()) @@ -78,6 +90,10 @@ class NewFilesPanel extends React.Component { }; onNewFileClick = (e) => { + if (this.state.inProgress) return; + + this.setState({ inProgress: true }); + const { id, extension: fileExst } = e.target.dataset; const { @@ -92,16 +108,23 @@ class NewFilesPanel extends React.Component { const item = newFiles.find((file) => file.id.toString() === id); - if (readingFiles.includes(id)) return this.onFileClick(item); + if (readingFiles.includes(id)) { + this.setState({ inProgress: false }); + return this.onFileClick(item); + } + markAsRead(folderIds, fileIds, item) .then(() => { //updateFolderBadge(folderId, 1); readingFiles.push(id); - this.setState({ readingFiles }); + this.setState({ readingFiles, inProgress: false }); + this.onFileClick(item); }) - .then(() => refreshFiles()) + .then(() => { + refreshFiles(); + }) .catch((err) => toastr.error(err)); }; @@ -159,7 +182,11 @@ class NewFilesPanel extends React.Component { newFiles, } = this.props; - const filesCount = newFiles.length; + const { readingFiles } = this.state; + + const filesCount = newFiles.filter( + (f) => !readingFiles.includes(f.id.toString()) + ).length; updateRootBadge(+newFilesIds[0], filesCount); if (newFilesIds.length <= 1) { @@ -175,6 +202,7 @@ class NewFilesPanel extends React.Component { render() { //console.log("NewFiles panel render"); const { t, visible, isLoading, newFiles, theme } = this.props; + const { inProgress } = this.state; const zIndex = 310; return ( @@ -244,12 +272,13 @@ class NewFilesPanel extends React.Component { size="normal" primary onClick={this.onMarkAsRead} - isLoading={this.state.inProgress} + isLoading={inProgress} />