Merge branch 'develop' into feature/doceditor-ssr

This commit is contained in:
Artem Tarasov 2022-04-13 11:42:49 +03:00
commit 0b19cf90f2
19 changed files with 281 additions and 106 deletions

View File

@ -1,5 +1,5 @@
REM echo ######## Set variables ########
set "msbuild4="C:\Windows\Microsoft.NET\Framework\v4.0.30319\MSBuild.exe""
set "publisher="Ascensio System SIA""
REM echo ######## Extracting and preparing files to build ########
%sevenzip% x build\install\win\nginx-1.21.1.zip -o"build\install\win\Files" -y
@ -29,7 +29,7 @@ del /f /q "build\install\win\kafka-zookeeper\zookeeper\conf\zoo_sample.cfg"
rmdir build\install\win\publish /s /q
REM echo ######## Build Utils ########
%msbuild4% build\install\win\CustomActions\C#\Utils\Utils.csproj
%msbuild% build\install\win\CustomActions\C#\Utils\Utils.csproj
copy build\install\win\CustomActions\C#\Utils\bin\Debug\Utils.CA.dll build\install\win\Utils.CA.dll /y
rmdir build\install\win\CustomActions\C#\Utils\bin /s /q
rmdir build\install\win\CustomActions\C#\Utils\obj /s /q
@ -80,7 +80,7 @@ copy "build\install\win\publish\Apache ZooKeeper.msi" "build\install\win\Apache
copy "build\install\win\publish\Apache Kafka.msi" "build\install\win\Apache Kafka.msi" /y
REM echo ######## Build MySQL Server Installer ########
iscc "build\install\win\MySQL Server Installer Runner.iss"
iscc /Qp /S"byparam="signtool" sign /a /n "%publisher%" /t http://timestamp.digicert.com $f" "build\install\win\MySQL Server Installer Runner.iss"
REM echo ######## Build AppServer package ########
%AdvancedInstaller% /edit build\install\win\AppServer.aip /SetVersion %BUILD_VERSION%.%BUILD_NUMBER%

View File

@ -3,6 +3,7 @@
using ASC.Common;
using ASC.Common.Logging;
using ASC.Core;
using ASC.Core.Common.Settings;
using ASC.IPSecurity;
using Microsoft.AspNetCore.Mvc;
@ -19,16 +20,18 @@ namespace ASC.Api.Core.Middleware
public IpSecurityFilter(
IOptionsMonitor<ILog> options,
AuthContext authContext,
IPSecurity.IPSecurity IPSecurity)
IPSecurity.IPSecurity IPSecurity,
SettingsManager settingsManager)
{
log = options.CurrentValue;
AuthContext = authContext;
this.IPSecurity = IPSecurity;
SettingsManager = settingsManager;
}
private AuthContext AuthContext { get; }
public IPRestrictionsSettings IPRestrictionsSettings { get; }
private IPSecurity.IPSecurity IPSecurity { get; }
private SettingsManager SettingsManager { get; }
public void OnResourceExecuted(ResourceExecutedContext context)
{
@ -36,11 +39,17 @@ namespace ASC.Api.Core.Middleware
public void OnResourceExecuting(ResourceExecutingContext context)
{
if (AuthContext.IsAuthenticated && !IPSecurity.Verify())
if (AuthContext.IsAuthenticated)
{
context.Result = new StatusCodeResult((int)HttpStatusCode.Forbidden);
log.WarnFormat("IPSecurity: user {0}", AuthContext.CurrentAccount.ID);
return;
var enable = SettingsManager.Load<IPRestrictionsSettings>().Enable;
if (enable && !IPSecurity.Verify())
{
context.Result = new StatusCodeResult((int)HttpStatusCode.Forbidden);
log.WarnFormat("IPSecurity: user {0}", AuthContext.CurrentAccount.ID);
return;
}
}
}
}

View File

@ -175,7 +175,7 @@ namespace ASC.Core
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)
@ -518,6 +518,11 @@ namespace ASC.Core
{
var group = UserService.GetGroup(Tenant.TenantId, groupID);
if (group == null)
{
group = ToGroup(Constants.BuildinGroups.FirstOrDefault(r => r.ID == groupID));
}
return new GroupInfo
{
ID = group.Id,

View File

@ -275,6 +275,7 @@ namespace ASC.Security.Cryptography
case ConfirmType.PhoneAuth:
case ConfirmType.TfaActivation:
case ConfirmType.TfaAuth:
case ConfirmType.Auth:
checkKeyResult = Provider.ValidateEmailKey(email + type, key, Provider.ValidAuthKeyInterval);
break;

View File

@ -25,8 +25,10 @@
using System;
using System.Collections.Generic;
using System.Linq;
using System.Net;
using System.Net.Sockets;
using System.Web;
using ASC.Common;
@ -55,6 +57,7 @@ namespace ASC.IPSecurity
private SettingsManager SettingsManager { get; }
private readonly string CurrentIpForTest;
private readonly string MyNetworks;
public IPSecurity(
IConfiguration configuration,
@ -72,6 +75,7 @@ namespace ASC.IPSecurity
IPRestrictionsService = iPRestrictionsService;
SettingsManager = settingsManager;
CurrentIpForTest = configuration["ipsecurity:test"];
MyNetworks = configuration["ipsecurity:mynetworks"];
var hideSettings = (configuration["web:hide-settings"] ?? "").Split(new[] { ',', ';', ' ' });
IpSecurityEnabled = !hideSettings.Contains("IpSecurity", StringComparer.CurrentCultureIgnoreCase);
}
@ -109,6 +113,10 @@ namespace ASC.IPSecurity
{
return true;
}
if (IsMyNetwork(ips))
{
return true;
}
}
catch (Exception ex)
{
@ -140,5 +148,42 @@ namespace ASC.IPSecurity
var portIdx = ip.IndexOf(':');
return portIdx > 0 ? ip.Substring(0, portIdx) : ip;
}
private bool IsMyNetwork(string[] ips)
{
try
{
if (!string.IsNullOrEmpty(MyNetworks))
{
var myNetworkIps = MyNetworks.Split(new[] { ",", " " }, StringSplitOptions.RemoveEmptyEntries);
if (ips.Any(requestIp => myNetworkIps.Any(ipAddress => MatchIPs(GetIpWithoutPort(requestIp), ipAddress))))
{
return true;
}
}
var hostName = Dns.GetHostName();
var hostAddresses = Dns.GetHostAddresses(Dns.GetHostName());
var localIPs = new List<IPAddress> { IPAddress.IPv6Loopback, IPAddress.Loopback };
localIPs.AddRange(hostAddresses.Where(ip => ip.AddressFamily == AddressFamily.InterNetwork || ip.AddressFamily == AddressFamily.InterNetworkV6));
foreach (var ipAddress in localIPs)
{
if (ips.Contains(ipAddress.ToString()))
{
return true;
}
}
}
catch (Exception ex)
{
Log.ErrorFormat("Can't verify local network from request with IP-address: {0}", string.Join(",", ips), ex);
}
return false;
}
}
}

View File

@ -554,7 +554,8 @@ namespace ASC.ElasticSearch
while (!string.IsNullOrEmpty(name = TryGetName(expression, out var member)))
{
sourceExprText = "." + name + sourceExprText;
sourceExprText = "." + name + sourceExprText;
expression = member.Expression;
}
if (isList)

View File

@ -1401,11 +1401,11 @@ namespace ASC.Files.Core.Data
{
if (withSubfolders)
{
result.In(a => a.Folders.Select(r => r.ParentId), new[] { parentId });
result.In(a => a.Folders.Select(r => r.FolderId), new[] { parentId });
}
else
{
result.InAll(a => a.Folders.Select(r => r.ParentId), new[] { parentId });
result.InAll(a => a.Folders.Select(r => r.FolderId), new[] { parentId });
}
}

View File

@ -777,7 +777,7 @@ ctx.Tag
}
monitorFolderIds = monitorFolderIds.Concat(tempTags.Where(x => x.EntryType == FileEntryType.Folder).Select(x => x.EntryId));
result.Concat(tempTags);
result = result.Concat(tempTags);
}
var monitorFolderIdsInt = await monitorFolderIds.OfType<int>().ToListAsync();
@ -787,13 +787,13 @@ ctx.Tag
var monitorFolderIdsStrings = await monitorFolderIds.Select(r => r.ToString()).ToListAsync();
result.Concat(FromQueryAsync(newTagsForFoldersQuery(FilesDbContext, tenantId, subject, monitorFolderIdsStrings)));
result = result.Concat(FromQueryAsync(newTagsForFoldersQuery(FilesDbContext, tenantId, subject, monitorFolderIdsStrings)));
var where = (deepSearch ? await monitorFolderIds.ToArrayAsync().ConfigureAwait(false) : new object[] { parentFolder.ID })
.Select(r => r.ToString())
.ToList();
result.Concat(FromQueryAsync(newTagsForFilesQuery(FilesDbContext, tenantId, subject, where)));
result = result.Concat(FromQueryAsync(newTagsForFilesQuery(FilesDbContext, tenantId, subject, where)));
if (parentFolder.FolderType == FolderType.USER || parentFolder.FolderType == FolderType.COMMON)
{
@ -809,7 +809,7 @@ ctx.Tag
if (thirdpartyFolderIds.Count > 0)
{
result.Concat(FromQueryAsync(newTagsForSBoxQuery(FilesDbContext, tenantId, subject, thirdpartyFolderIds)));
result = result.Concat(FromQueryAsync(newTagsForSBoxQuery(FilesDbContext, tenantId, subject, thirdpartyFolderIds)));
}
}

View File

@ -1601,7 +1601,7 @@ namespace ASC.Web.Files.Services.WCFService
{
if (sync)
{
results.Append(await FileConverter.ExecSynchronouslyAsync(file, fileInfo.Password));
results = results.Append(await FileConverter.ExecSynchronouslyAsync(file, fileInfo.Password));
}
else
{
@ -1999,8 +1999,8 @@ namespace ASC.Web.Files.Services.WCFService
var fileDao = GetFileDao();
var folderDao = GetFolderDao();
entries.Concat(filesId.ToAsyncEnumerable().SelectAwait(async fileId => await fileDao.GetFileAsync(fileId)));
entries.Concat(foldersId.ToAsyncEnumerable().SelectAwait(async e => await folderDao.GetFolderAsync(e)));
entries = entries.Concat(filesId.ToAsyncEnumerable().SelectAwait(async fileId => await fileDao.GetFileAsync(fileId)));
entries = entries.Concat(foldersId.ToAsyncEnumerable().SelectAwait(async e => await folderDao.GetFolderAsync(e)));
return FileSharingAceHelper.RemoveAceAsync(entries);
@ -2234,16 +2234,16 @@ namespace ASC.Web.Files.Services.WCFService
//return new List<string>(accounts);
}
public async IAsyncEnumerable<FileEntry> ChangeOwnerAsync(IEnumerable<T> foldersId, IEnumerable<T> filesId, Guid userId)
public async Task<IEnumerable<FileEntry>> ChangeOwnerAsync(IEnumerable<T> foldersId, IEnumerable<T> filesId, Guid userId)
{
var userInfo = UserManager.GetUsers(userId);
ErrorIf(Equals(userInfo, Constants.LostUser) || userInfo.IsVisitor(UserManager), FilesCommonResource.ErrorMassage_ChangeOwner);
var entries = AsyncEnumerable.Empty<FileEntry>();
var entries = new List<FileEntry>();
var folderDao = GetFolderDao();
var folders = folderDao.GetFoldersAsync(foldersId);
await foreach (var folder in folders)
var folders = await folderDao.GetFoldersAsync(foldersId).ToListAsync();
foreach (var folder in folders)
{
ErrorIf(!await FileSecurity.CanEditAsync(folder), FilesCommonResource.ErrorMassage_SecurityException);
ErrorIf(folder.RootFolderType != FolderType.COMMON, FilesCommonResource.ErrorMassage_SecurityException);
@ -2262,13 +2262,13 @@ namespace ASC.Web.Files.Services.WCFService
FilesMessageService.Send(newFolder, GetHttpHeaders(), MessageAction.FileChangeOwner, new[] { newFolder.Title, userInfo.DisplayUserName(false, DisplayUserSettingsHelper) });
}
entries.Append(newFolder);
entries.Add(newFolder);
}
var fileDao = GetFileDao();
var files = fileDao.GetFilesAsync(filesId);
var files = await fileDao.GetFilesAsync(filesId).ToListAsync();
await foreach (var file in files)
foreach (var file in files)
{
ErrorIf(!await FileSecurity.CanEditAsync(file), FilesCommonResource.ErrorMassage_SecurityException);
ErrorIf(await EntryManager.FileLockedForMeAsync(file.ID), FilesCommonResource.ErrorMassage_LockedFile);
@ -2313,13 +2313,10 @@ namespace ASC.Web.Files.Services.WCFService
FilesMessageService.Send(newFile, GetHttpHeaders(), MessageAction.FileChangeOwner, new[] { newFile.Title, userInfo.DisplayUserName(false, DisplayUserSettingsHelper) });
}
entries.Append(newFile);
entries.Add(newFile);
}
await foreach (var entrie in entries)
{
yield return entrie;
}
return entries;
}
public bool StoreOriginal(bool set)

View File

@ -75,17 +75,13 @@ namespace ASC.Web.Files
{
public class FileHandler
{
private IServiceProvider ServiceProvider { get; }
public FileHandler(RequestDelegate next, IServiceProvider serviceProvider)
public FileHandler(RequestDelegate next)
{
ServiceProvider = serviceProvider;
}
public async Task Invoke(HttpContext context)
public async Task Invoke(HttpContext context, FileHandlerService fileHandlerService)
{
using var scope = ServiceProvider.CreateScope();
var fileHandlerService = scope.ServiceProvider.GetService<FileHandlerService>();
await fileHandlerService.Invoke(context).ConfigureAwait(false);
}
}

View File

@ -663,7 +663,7 @@ namespace ASC.Web.Files.Utils
public Task<Stream> ExecAsync<T>(File<T> file)
{
return ExecAsync(file, FileUtility.GetInternalExtension(file.Title));
}
}
public async Task<Stream> ExecAsync<T>(File<T> file, string toExtension, string password = null)
{
@ -687,8 +687,8 @@ namespace ASC.Web.Files.Utils
var request = new HttpRequestMessage();
request.RequestUri = new Uri(convertUri);
using var httpClient = ClientFactory.CreateClient();
using var response = await httpClient.SendAsync(request);
var httpClient = ClientFactory.CreateClient();
var response = await httpClient.SendAsync(request);
return new ResponseStream(response);
}

View File

@ -558,9 +558,9 @@ namespace ASC.Web.Files.Utils
var tagDao = DaoFactory.GetTagDao<T>();
var providerFolderDao = DaoFactory.GetFolderDao<string>();
var providerTagDao = DaoFactory.GetTagDao<string>();
var tags = (tagDao.GetNewTagsAsync(AuthContext.CurrentAccount.ID, folder, true) ?? AsyncEnumerable.Empty<Tag>());
var tags = await (tagDao.GetNewTagsAsync(AuthContext.CurrentAccount.ID, folder, true) ?? AsyncEnumerable.Empty<Tag>()).ToListAsync();
if (!(await tags.CountAsync() == 0)) return new List<FileEntry>();
if (!tags.Any()) return new List<FileEntry>();
if (Equals(folder.ID, GlobalFolder.GetFolderMy(this, DaoFactory)) ||
Equals(folder.ID, await GlobalFolder.GetFolderCommonAsync(this, DaoFactory)) ||
@ -568,25 +568,33 @@ namespace ASC.Web.Files.Utils
{
var folderTags = tags.Where(tag => tag.EntryType == FileEntryType.Folder && (tag.EntryId is string));
var providerFolderTags = folderTags
.SelectAwait(async tag => new KeyValuePair<Tag, Folder<string>>(tag, await providerFolderDao.GetFolderAsync(tag.EntryId.ToString())))
.Where(pair => pair.Value != null && pair.Value.ProviderEntry);
var providerFolderTags = new List<KeyValuePair<Tag, Folder<string>>>();
foreach (var tag in folderTags)
{
var pair = new KeyValuePair<Tag, Folder<string>>(tag, await providerFolderDao.GetFolderAsync(tag.EntryId.ToString()));
if (pair.Value != null && pair.Value.ProviderEntry)
{
providerFolderTags.Add(pair);
}
}
providerFolderTags = providerFolderTags.Reverse();
providerFolderTags.Reverse();
await foreach (var providerFolderTag in providerFolderTags)
foreach (var providerFolderTag in providerFolderTags)
{
tags.Concat(providerTagDao.GetNewTagsAsync(AuthContext.CurrentAccount.ID, providerFolderTag.Value, true));
tags.AddRange(await providerTagDao.GetNewTagsAsync(AuthContext.CurrentAccount.ID, providerFolderTag.Value, true).ToListAsync());
}
}
tags = tags
.Where(r => !Equals(r.EntryId, folder.ID))
.Distinct();
.Distinct()
.ToList();
//TODO: refactoring
var entryTagsProvider = await GetEntryTagsAsync<string>(tags.Where(r => r.EntryId is string));
var entryTagsInternal = await GetEntryTagsAsync<int>(tags.Where(r => r.EntryId is int));
var entryTagsProvider = await GetEntryTagsAsync<string>(tags.Where(r => r.EntryId is string).ToAsyncEnumerable());
var entryTagsInternal = await GetEntryTagsAsync<int>(tags.Where(r => r.EntryId is int).ToAsyncEnumerable());
foreach (var entryTag in entryTagsInternal)
{

View File

@ -168,7 +168,7 @@ namespace ASC.Api.Documents
}
[Read("@root")]
public async Task<IEnumerable<FolderContentWrapper<int>>> GetRootFoldersAsync(Guid userIdOrGroupId, FilterType filterType, bool withsubfolders, bool withoutTrash, bool withoutAdditionalFolder)
public async Task<IEnumerable<FolderContentWrapper<int>>> GetRootFoldersAsync(Guid userIdOrGroupId, FilterType filterType, bool searchInContent, bool withsubfolders, bool withoutTrash, bool withoutAdditionalFolder)
{
var IsVisitor = UserManager.GetUsers(SecurityContext.CurrentAccount.ID).IsVisitor(UserManager);
var IsOutsider = UserManager.GetUsers(SecurityContext.CurrentAccount.ID).IsOutsider(UserManager);
@ -229,22 +229,22 @@ namespace ASC.Api.Documents
var result = new List<FolderContentWrapper<int>>();
foreach (var folder in folders)
{
result.Add(await FilesControllerHelperInt.GetFolderAsync(folder, userIdOrGroupId, filterType, withsubfolders));
result.Add(await FilesControllerHelperInt.GetFolderAsync(folder, userIdOrGroupId, filterType, searchInContent, withsubfolders));
}
return result;
}
[Read("@privacy")]
public Task<FolderContentWrapper<int>> GetPrivacyFolderAsync(Guid userIdOrGroupId, FilterType filterType, bool withsubfolders)
public Task<FolderContentWrapper<int>> GetPrivacyFolderAsync(Guid userIdOrGroupId, FilterType filterType, bool searchInContent, bool withsubfolders)
{
if (!IsAvailablePrivacyRoomSettings()) throw new System.Security.SecurityException();
return InternalGetPrivacyFolderAsync(userIdOrGroupId, filterType, withsubfolders);
return InternalGetPrivacyFolderAsync(userIdOrGroupId, filterType, searchInContent, withsubfolders);
}
private async Task<FolderContentWrapper<int>> InternalGetPrivacyFolderAsync(Guid userIdOrGroupId, FilterType filterType, bool withsubfolders)
private async Task<FolderContentWrapper<int>> InternalGetPrivacyFolderAsync(Guid userIdOrGroupId, FilterType filterType, bool searchInContent, bool withsubfolders)
{
return await FilesControllerHelperInt.GetFolderAsync(await GlobalFolderHelper.FolderPrivacyAsync, userIdOrGroupId, filterType, withsubfolders);
return await FilesControllerHelperInt.GetFolderAsync(await GlobalFolderHelper.FolderPrivacyAsync, userIdOrGroupId, filterType, searchInContent, withsubfolders);
}
[Read("@privacy/available")]
@ -262,9 +262,9 @@ namespace ASC.Api.Documents
/// <category>Folders</category>
/// <returns>My folder contents</returns>
[Read("@my")]
public Task<FolderContentWrapper<int>> GetMyFolderAsync(Guid userIdOrGroupId, FilterType filterType, bool withsubfolders)
public Task<FolderContentWrapper<int>> GetMyFolderAsync(Guid userIdOrGroupId, FilterType filterType, bool searchInContent, bool withsubfolders)
{
return FilesControllerHelperInt.GetFolderAsync(GlobalFolderHelper.FolderMy, userIdOrGroupId, filterType, withsubfolders);
return FilesControllerHelperInt.GetFolderAsync(GlobalFolderHelper.FolderMy, userIdOrGroupId, filterType, searchInContent, withsubfolders);
}
/// <summary>
@ -276,9 +276,9 @@ namespace ASC.Api.Documents
/// <category>Folders</category>
/// <returns>Projects folder contents</returns>
[Read("@projects")]
public async Task<FolderContentWrapper<string>> GetProjectsFolderAsync(Guid userIdOrGroupId, FilterType filterType, bool withsubfolders)
public async Task<FolderContentWrapper<string>> GetProjectsFolderAsync(Guid userIdOrGroupId, FilterType filterType, bool searchInContent, bool withsubfolders)
{
return await FilesControllerHelperString.GetFolderAsync(await GlobalFolderHelper.GetFolderProjectsAsync<string>(), userIdOrGroupId, filterType, withsubfolders);
return await FilesControllerHelperString.GetFolderAsync(await GlobalFolderHelper.GetFolderProjectsAsync<string>(), userIdOrGroupId, filterType, searchInContent, withsubfolders);
}
@ -291,9 +291,9 @@ namespace ASC.Api.Documents
/// <category>Folders</category>
/// <returns>Common folder contents</returns>
[Read("@common")]
public async Task<FolderContentWrapper<int>> GetCommonFolderAsync(Guid userIdOrGroupId, FilterType filterType, bool withsubfolders)
public async Task<FolderContentWrapper<int>> GetCommonFolderAsync(Guid userIdOrGroupId, FilterType filterType, bool searchInContent, bool withsubfolders)
{
return await FilesControllerHelperInt.GetFolderAsync(await GlobalFolderHelper.FolderCommonAsync, userIdOrGroupId, filterType, withsubfolders);
return await FilesControllerHelperInt.GetFolderAsync(await GlobalFolderHelper.FolderCommonAsync, userIdOrGroupId, filterType, searchInContent, withsubfolders);
}
/// <summary>
@ -305,9 +305,9 @@ namespace ASC.Api.Documents
/// <category>Folders</category>
/// <returns>Shared folder contents</returns>
[Read("@share")]
public async Task<FolderContentWrapper<int>> GetShareFolderAsync(Guid userIdOrGroupId, FilterType filterType, bool withsubfolders)
public async Task<FolderContentWrapper<int>> GetShareFolderAsync(Guid userIdOrGroupId, FilterType filterType, bool searchInContent, bool withsubfolders)
{
return await FilesControllerHelperInt.GetFolderAsync(await GlobalFolderHelper.FolderShareAsync, userIdOrGroupId, filterType, withsubfolders);
return await FilesControllerHelperInt.GetFolderAsync(await GlobalFolderHelper.FolderShareAsync, userIdOrGroupId, filterType, searchInContent, withsubfolders);
}
/// <summary>
@ -317,9 +317,9 @@ namespace ASC.Api.Documents
/// <category>Folders</category>
/// <returns>Recent contents</returns>
[Read("@recent")]
public async Task<FolderContentWrapper<int>> GetRecentFolderAsync(Guid userIdOrGroupId, FilterType filterType, bool withsubfolders)
public async Task<FolderContentWrapper<int>> GetRecentFolderAsync(Guid userIdOrGroupId, FilterType filterType, bool searchInContent, bool withsubfolders)
{
return await FilesControllerHelperInt.GetFolderAsync(await GlobalFolderHelper.FolderRecentAsync, userIdOrGroupId, filterType, withsubfolders);
return await FilesControllerHelperInt.GetFolderAsync(await GlobalFolderHelper.FolderRecentAsync, userIdOrGroupId, filterType, searchInContent, withsubfolders);
}
[Create("file/{fileId}/recent", order: int.MaxValue)]
@ -341,9 +341,9 @@ namespace ASC.Api.Documents
/// <category>Folders</category>
/// <returns>Favorites contents</returns>
[Read("@favorites")]
public async Task<FolderContentWrapper<int>> GetFavoritesFolderAsync(Guid userIdOrGroupId, FilterType filterType, bool withsubfolders)
public async Task<FolderContentWrapper<int>> GetFavoritesFolderAsync(Guid userIdOrGroupId, FilterType filterType, bool searchInContent, bool withsubfolders)
{
return await FilesControllerHelperInt.GetFolderAsync(await GlobalFolderHelper.FolderFavoritesAsync, userIdOrGroupId, filterType, withsubfolders);
return await FilesControllerHelperInt.GetFolderAsync(await GlobalFolderHelper.FolderFavoritesAsync, userIdOrGroupId, filterType, searchInContent, withsubfolders);
}
/// <summary>
@ -353,9 +353,9 @@ namespace ASC.Api.Documents
/// <category>Folders</category>
/// <returns>Templates contents</returns>
[Read("@templates")]
public async Task<FolderContentWrapper<int>> GetTemplatesFolderAsync(Guid userIdOrGroupId, FilterType filterType, bool withsubfolders)
public async Task<FolderContentWrapper<int>> GetTemplatesFolderAsync(Guid userIdOrGroupId, FilterType filterType, bool searchInContent, bool withsubfolders)
{
return await FilesControllerHelperInt.GetFolderAsync(await GlobalFolderHelper.FolderTemplatesAsync, userIdOrGroupId, filterType, withsubfolders);
return await FilesControllerHelperInt.GetFolderAsync(await GlobalFolderHelper.FolderTemplatesAsync, userIdOrGroupId, filterType, searchInContent, withsubfolders);
}
/// <summary>
@ -367,9 +367,9 @@ namespace ASC.Api.Documents
/// <category>Folders</category>
/// <returns>Trash folder contents</returns>
[Read("@trash")]
public Task<FolderContentWrapper<int>> GetTrashFolderAsync(Guid userIdOrGroupId, FilterType filterType, bool withsubfolders)
public Task<FolderContentWrapper<int>> GetTrashFolderAsync(Guid userIdOrGroupId, FilterType filterType, bool searchInContent, bool withsubfolders)
{
return FilesControllerHelperInt.GetFolderAsync(Convert.ToInt32(GlobalFolderHelper.FolderTrash), userIdOrGroupId, filterType, withsubfolders);
return FilesControllerHelperInt.GetFolderAsync(Convert.ToInt32(GlobalFolderHelper.FolderTrash), userIdOrGroupId, filterType, searchInContent, withsubfolders);
}
/// <summary>
@ -384,16 +384,16 @@ namespace ASC.Api.Documents
/// <param name="filterType" optional="true" remark="Allowed values: None (0), FilesOnly (1), FoldersOnly (2), DocumentsOnly (3), PresentationsOnly (4), SpreadsheetsOnly (5) or ImagesOnly (7)">Filter type</param>
/// <returns>Folder contents</returns>
[Read("{folderId}", order: int.MaxValue, DisableFormat = true)]
public async Task<FolderContentWrapper<string>> GetFolderAsync(string folderId, Guid userIdOrGroupId, FilterType filterType, bool withsubfolders)
public async Task<FolderContentWrapper<string>> GetFolderAsync(string folderId, Guid userIdOrGroupId, FilterType filterType, bool searchInContent, bool withsubfolders)
{
var folder = await FilesControllerHelperString.GetFolderAsync(folderId, userIdOrGroupId, filterType, withsubfolders);
var folder = await FilesControllerHelperString.GetFolderAsync(folderId, userIdOrGroupId, filterType, searchInContent, withsubfolders);
return folder.NotFoundIfNull();
}
[Read("{folderId:int}", order: int.MaxValue - 1, DisableFormat = true)]
public Task<FolderContentWrapper<int>> GetFolderAsync(int folderId, Guid userIdOrGroupId, FilterType filterType, bool withsubfolders)
public Task<FolderContentWrapper<int>> GetFolderAsync(int folderId, Guid userIdOrGroupId, FilterType filterType, bool searchInContent, bool withsubfolders)
{
return FilesControllerHelperInt.GetFolderAsync(folderId, userIdOrGroupId, filterType, withsubfolders);
return FilesControllerHelperInt.GetFolderAsync(folderId, userIdOrGroupId, filterType, searchInContent, withsubfolders);
}
[Read("{folderId}/subfolders")]
@ -1058,31 +1058,35 @@ namespace ASC.Api.Documents
}
[Create("owner")]
public IAsyncEnumerable<FileEntryWrapper> ChangeOwnerFromBodyAsync([FromBody] ChangeOwnerModel model)
public async Task<IEnumerable<FileEntryWrapper>> ChangeOwnerFromBodyAsync([FromBody] ChangeOwnerModel model)
{
return ChangeOwnerAsync(model);
return await ChangeOwnerAsync(model);
}
[Create("owner")]
[Consumes("application/x-www-form-urlencoded")]
public IAsyncEnumerable<FileEntryWrapper> ChangeOwnerFromFormAsync([FromForm] ChangeOwnerModel model)
public async Task<IEnumerable<FileEntryWrapper>> ChangeOwnerFromFormAsync([FromForm] ChangeOwnerModel model)
{
return ChangeOwnerAsync(model);
return await ChangeOwnerAsync(model);
}
public async IAsyncEnumerable<FileEntryWrapper> ChangeOwnerAsync(ChangeOwnerModel model)
public async Task<IEnumerable<FileEntryWrapper>> ChangeOwnerAsync(ChangeOwnerModel model)
{
var (folderIntIds, folderStringIds) = FileOperationsManager.GetIds(model.FolderIds);
var (fileIntIds, fileStringIds) = FileOperationsManager.GetIds(model.FileIds);
var result = AsyncEnumerable.Empty<FileEntry>();
result.Concat(FileStorageServiceInt.ChangeOwnerAsync(folderIntIds, fileIntIds, model.UserId));
result.Concat(FileStorageService.ChangeOwnerAsync(folderStringIds, fileStringIds, model.UserId));
var data = Enumerable.Empty<FileEntry>();
data = data.Concat(await FileStorageServiceInt.ChangeOwnerAsync(folderIntIds, fileIntIds, model.UserId));
data = data.Concat(await FileStorageService.ChangeOwnerAsync(folderStringIds, fileStringIds, model.UserId));
await foreach (var e in result)
var result = new List<FileEntryWrapper>();
foreach (var e in data)
{
yield return await FilesControllerHelperInt.GetFileEntryWrapperAsync(e);
result.Add(await FilesControllerHelperInt.GetFileEntryWrapperAsync(e));
}
return result;
}
/// <summary>
@ -1144,41 +1148,41 @@ namespace ASC.Api.Documents
}
[Create("file/{fileId:int}/copyas", order: int.MaxValue - 1)]
public object CopyFileAsFromBody(int fileId, [FromBody] CopyAsModel<JsonElement> model)
public Task<FileEntryWrapper> CopyFileAsFromBody(int fileId, [FromBody] CopyAsModel<JsonElement> model)
{
return CopyFile(fileId, model);
}
[Create("file/{fileId:int}/copyas", order: int.MaxValue - 1)]
[Consumes("application/x-www-form-urlencoded")]
public object CopyFileAsFromForm(int fileId, [FromForm] CopyAsModel<JsonElement> model)
public Task<FileEntryWrapper> CopyFileAsFromForm(int fileId, [FromForm] CopyAsModel<JsonElement> model)
{
return CopyFile(fileId, model);
}
[Create("file/{fileId}/copyas", order: int.MaxValue)]
public object CopyFileAsFromBody(string fileId, [FromBody] CopyAsModel<JsonElement> model)
public Task<FileEntryWrapper> CopyFileAsFromBody(string fileId, [FromBody] CopyAsModel<JsonElement> model)
{
return CopyFile(fileId, model);
}
[Create("file/{fileId}/copyas", order: int.MaxValue)]
[Consumes("application/x-www-form-urlencoded")]
public object CopyFileAsFromForm(string fileId, [FromForm] CopyAsModel<JsonElement> model)
public Task<FileEntryWrapper> CopyFileAsFromForm(string fileId, [FromForm] CopyAsModel<JsonElement> model)
{
return CopyFile(fileId, model);
}
private object CopyFile<T>(T fileId, CopyAsModel<JsonElement> model)
private async Task<FileEntryWrapper> CopyFile<T>(T fileId, CopyAsModel<JsonElement> model)
{
var helper = ServiceProvider.GetService<FilesControllerHelper<T>>();
if (model.DestFolderId.ValueKind == JsonValueKind.Number)
{
return helper.CopyFileAsAsync(fileId, model.DestFolderId.GetInt32(), model.DestTitle, model.Password);
return await helper.CopyFileAsAsync(fileId, model.DestFolderId.GetInt32(), model.DestTitle, model.Password);
}
else if (model.DestFolderId.ValueKind == JsonValueKind.String)
{
return helper.CopyFileAsAsync(fileId, model.DestFolderId.GetString(), model.DestTitle, model.Password);
return await helper.CopyFileAsAsync(fileId, model.DestFolderId.GetString(), model.DestTitle, model.Password);
}
return null;

View File

@ -141,9 +141,9 @@ namespace ASC.Files.Helpers
ClientFactory = clientFactory;
}
public async Task<FolderContentWrapper<T>> GetFolderAsync(T folderId, Guid userIdOrGroupId, FilterType filterType, bool withSubFolders)
public async Task<FolderContentWrapper<T>> GetFolderAsync(T folderId, Guid userIdOrGroupId, FilterType filterType, bool searchInContent, bool withSubFolders)
{
var folderContentWrapper = await ToFolderContentWrapperAsync(folderId, userIdOrGroupId, filterType, withSubFolders);
var folderContentWrapper = await ToFolderContentWrapperAsync(folderId, userIdOrGroupId, filterType, searchInContent, withSubFolders);
return folderContentWrapper.NotFoundIfNull();
}
@ -402,7 +402,6 @@ namespace ASC.Files.Helpers
public async Task<FileWrapper<TTemplate>> CopyFileAsAsync<TTemplate>(T fileId, TTemplate destFolderId, string destTitle, string password = null)
{
var service = ServiceProvider.GetService<FileStorageService<TTemplate>>();
var controller = ServiceProvider.GetService<FilesControllerHelper<TTemplate>>();
var file = await FileStorageService.GetFileAsync(fileId, -1);
var ext = FileUtility.GetFileExtension(file.Title);
var destExt = FileUtility.GetFileExtension(destTitle);
@ -415,6 +414,7 @@ namespace ASC.Files.Helpers
using (var fileStream = await FileConverter.ExecAsync(file, destExt, password))
{
var controller = ServiceProvider.GetService<FilesControllerHelper<TTemplate>>();
return await controller.InsertFileAsync(destFolderId, fileStream, destTitle, true);
}
}
@ -823,7 +823,7 @@ namespace ASC.Files.Helpers
// return files.Concat(folders);
//}
private async Task<FolderContentWrapper<T>> ToFolderContentWrapperAsync(T folderId, Guid userIdOrGroupId, FilterType filterType, bool withSubFolders)
private async Task<FolderContentWrapper<T>> ToFolderContentWrapperAsync(T folderId, Guid userIdOrGroupId, FilterType filterType, bool searchInContent, bool withSubFolders)
{
OrderBy orderBy = null;
if (Enum.TryParse(ApiContext.SortBy, true, out SortedByType sortBy))
@ -839,7 +839,7 @@ namespace ASC.Files.Helpers
filterType == FilterType.ByUser,
userIdOrGroupId.ToString(),
ApiContext.FilterValue,
false,
searchInContent,
withSubFolders,
orderBy);
return await FolderContentWrapperHelper.GetAsync(items, startIndex);

View File

@ -18,9 +18,12 @@ using ASC.Web.Api.Models;
using ASC.Web.Api.Routing;
using ASC.Web.Core;
using ASC.Web.Core.Files;
using ASC.Web.Core.Helpers;
using ASC.Web.Core.Mobile;
using ASC.Web.Core.PublicResources;
using ASC.Web.Core.Utility;
using ASC.Web.Studio.Core;
using ASC.Web.Studio.Core.Notify;
using ASC.Web.Studio.UserControls.Management;
using ASC.Web.Studio.Utility;
@ -37,6 +40,10 @@ namespace ASC.Web.Api.Controllers
[ApiController]
public class PortalController : ControllerBase
{
private readonly ApiSystemHelper _apiSystemHelper;
private readonly CoreSettings _coreSettings;
private readonly StudioNotifyService _studioNotifyService;
private readonly PermissionContext _permissionContext;
private Tenant Tenant { get { return ApiContext.Tenant; } }
@ -80,7 +87,11 @@ namespace ASC.Web.Api.Controllers
LicenseReader licenseReader,
SetupInfo setupInfo,
DocumentServiceLicense documentServiceLicense,
IHttpClientFactory clientFactory
IHttpClientFactory clientFactory,
ApiSystemHelper apiSystemHelper,
CoreSettings coreSettings,
PermissionContext permissionContext,
StudioNotifyService studioNotifyService
)
{
Log = options.CurrentValue;
@ -102,6 +113,10 @@ namespace ASC.Web.Api.Controllers
DocumentServiceLicense = documentServiceLicense;
TenantExtra = tenantExtra;
ClientFactory = clientFactory;
_apiSystemHelper = apiSystemHelper;
_coreSettings = coreSettings;
_studioNotifyService = studioNotifyService;
_permissionContext = permissionContext;
}
[Read("")]
@ -280,5 +295,77 @@ namespace ASC.Web.Api.Controllers
var currentUser = UserManager.GetUsers(SecurityContext.CurrentAccount.ID);
MobileAppInstallRegistrator.RegisterInstall(currentUser.Email, type);
}
/// <summary>
/// Updates a portal name with a new one specified in the request.
/// </summary>
/// <short>Update a portal name</short>
/// <param name="alias">New portal name</param>
/// <returns>Message about renaming a portal</returns>
///<visible>false</visible>
[Update("portalrename")]
public async Task<object> UpdatePortalName(PortalRenameModel model)
{
if (!SetupInfo.IsVisibleSettings(nameof(ManagementType.PortalSecurity)))
{
throw new BillingException(Resource.ErrorNotAllowedOption);
}
if (CoreBaseSettings.Personal)
{
throw new Exception(Resource.ErrorAccessDenied);
}
_permissionContext.DemandPermissions(SecutiryConstants.EditPortalSettings);
var alias = model.Alias;
if (string.IsNullOrEmpty(alias)) throw new ArgumentException(nameof(alias));
var tenant = TenantManager.GetCurrentTenant();
var user = UserManager.GetUsers(SecurityContext.CurrentAccount.ID);
var localhost = _coreSettings.BaseDomain == "localhost" || tenant.TenantAlias == "localhost";
var newAlias = alias.ToLowerInvariant();
var oldAlias = tenant.TenantAlias;
var oldVirtualRootPath = CommonLinkUtility.GetFullAbsolutePath("~").TrimEnd('/');
if (!string.Equals(newAlias, oldAlias, StringComparison.InvariantCultureIgnoreCase))
{
if (!string.IsNullOrEmpty(_apiSystemHelper.ApiSystemUrl))
{
await _apiSystemHelper.ValidatePortalNameAsync(newAlias, user.ID);
}
else
{
TenantManager.CheckTenantAddress(newAlias.Trim());
}
if (!string.IsNullOrEmpty(_apiSystemHelper.ApiCacheUrl))
{
await _apiSystemHelper.AddTenantToCacheAsync(newAlias, user.ID);
}
tenant.TenantAlias = alias;
tenant = TenantManager.SaveTenant(tenant);
if (!string.IsNullOrEmpty(_apiSystemHelper.ApiCacheUrl))
{
await _apiSystemHelper.RemoveTenantFromCacheAsync(oldAlias, user.ID);
}
if (!localhost || string.IsNullOrEmpty(tenant.MappedDomain))
{
_studioNotifyService.PortalRenameNotify(tenant, oldVirtualRootPath);
}
}
else
{
return string.Empty;
}
return CommonLinkUtility.GetConfirmationUrl(user.Email, ConfirmType.Auth);
}
}
}

View File

@ -313,15 +313,20 @@ namespace ASC.Api.Settings
[AllowAnonymous]
public SettingsWrapper GetSettings(bool? withpassword)
{
var studioAdminMessageSettings = SettingsManager.Load<StudioAdminMessageSettings>();
var settings = new SettingsWrapper
{
Culture = Tenant.GetCulture().ToString(),
GreetingSettings = Tenant.Name,
Personal = CoreBaseSettings.Personal,
Version = Configuration["version:number"] ?? "",
TenantStatus = TenantManager.GetCurrentTenant().Status
TenantStatus = Tenant.Status,
TenantAlias = Tenant.TenantAlias,
EnableAdmMess = studioAdminMessageSettings.Enable || TenantExtra.IsNotPaid()
};
if (AuthContext.IsAuthenticated)
{
settings.TrustedDomains = Tenant.TrustedDomains;
@ -370,9 +375,7 @@ namespace ASC.Api.Settings
settings.TrustedDomains = Tenant.TrustedDomains;
}
var studioAdminMessageSettings = SettingsManager.Load<StudioAdminMessageSettings>();
settings.EnableAdmMess = studioAdminMessageSettings.Enable || TenantExtra.IsNotPaid();
settings.ThirdpartyEnable = SetupInfo.ThirdPartyAuthEnabled && ProviderManager.IsNotEmpty;
@ -1117,7 +1120,7 @@ namespace ASC.Api.Settings
{
var logoDict = new Dictionary<int, string>();
foreach(var l in model.Logo)
foreach (var l in model.Logo)
{
logoDict.Add(Int32.Parse(l.Key), l.Value);
}
@ -1341,6 +1344,13 @@ namespace ASC.Api.Settings
return IPRestrictionsService.Save(model.Ips, Tenant.TenantId);
}
[Read("iprestrictions/settings")]
public IPRestrictionsSettings GetIpRestrictionsSettings()
{
PermissionContext.DemandPermissions(SecutiryConstants.EditPortalSettings);
return SettingsManager.Load<IPRestrictionsSettings>();
}
[Update("iprestrictions/settings")]
public IPRestrictionsSettings UpdateIpRestrictionsSettingsFromBody([FromBody] IpRestrictionsModel model)
{

View File

@ -0,0 +1,7 @@
namespace ASC.Web.Api.Models
{
public class PortalRenameModel
{
public string Alias { get; set; }
}
}

View File

@ -77,6 +77,8 @@ namespace ASC.Api.Settings
public TenantStatus TenantStatus { get; set; }
public string TenantAlias { get; set; }
public static SettingsWrapper GetSample()
{
return new SettingsWrapper

View File

@ -36,6 +36,7 @@ using ASC.Core;
using ASC.Core.Common.Settings;
using ASC.Core.Tenants;
using ASC.Core.Users;
using ASC.IPSecurity;
using ASC.MessagingSystem;
using ASC.Web.Core.PublicResources;
using ASC.Web.Core.Utility;
@ -259,7 +260,9 @@ namespace ASC.Web.Core.Users
email = (email ?? "").Trim();
if (!email.TestEmailRegex()) throw new ArgumentNullException(nameof(email), Resource.ErrorNotCorrectEmail);
if (!IPSecurity.Verify())
var settings = SettingsManager.Load<IPRestrictionsSettings>();
if (settings.Enable && !IPSecurity.Verify())
{
throw new Exception(Resource.ErrorAccessRestricted);
}