Merge branch 'release/v1.2' of github.com:ONLYOFFICE/AppServer into release/v1.2

This commit is contained in:
Vlada Gazizova 2022-05-05 18:49:58 +03:00
commit 5445e0b4a7
23 changed files with 293 additions and 165 deletions

View File

@ -101,7 +101,14 @@ namespace ASC.FederatedLogin
if (string.IsNullOrEmpty(json)) return null;
try
{
return JsonSerializer.Deserialize<OAuth20Token>(json);
var result = JsonSerializer.Deserialize<OAuth20Token>(json);
if (result.Timestamp == default)
{
result.Timestamp = DateTime.UtcNow;
}
return result;
}
catch (Exception)
{

View File

@ -24,7 +24,7 @@ map $request_uri $header_x_frame_options {
map $request_uri $cache_control {
default "no-cache, no-store, must-revalidate";
~*\/(api\/2\.0.*|storage|login\.ashx|products\/.+\/httphandlers\/filehandler\.ashx|ChunkedUploader.ashx|apisystem|sh|remoteEntry\.js|debuginfo\.md) "no-cache, no-store, must-revalidate";
~*\/(api\/2\.0.*|storage|login\.ashx|products\/.+\/httphandlers\/filehandler\.ashx|ChunkedUploader.ashx|ThirdPartyAppHandler|apisystem|sh|remoteEntry\.js|debuginfo\.md) "no-cache, no-store, must-revalidate";
~*\/(locales.*\.json) "public, no-transform";
~*\.(ogg|ogv|svg|svgz|eot|otf|woff|mp4|ttf|rss|atom|jpg|jpeg|gif|png|ico|zip|tgz|gz|rar|bz2|doc|xls|exe|ppt|tar|mid|midi|wav|bmp|rtf|md|css|js)$ "public, no-transform";
}
@ -204,6 +204,11 @@ server {
location /backupFileUpload.ashx {
proxy_pass http://localhost:5012;
proxy_set_header X-REWRITER-URL $X_REWRITER_URL;
}
location /ThirdPartyApp {
proxy_pass http://localhost:5007;
proxy_set_header X-REWRITER-URL $X_REWRITER_URL;
}
location /products {

View File

@ -28,7 +28,7 @@ const EmptyScreenContainer = (props) => {
<Text
as="span"
fontSize="19px"
fontWeight="600"
fontWeight="700"
className="ec-header"
noSelect
>

View File

@ -1,5 +1,5 @@
import styled from "styled-components";
import { mobile } from "../utils/device";
import { mobile, tablet } from "../utils/device";
import NoUserSelect from "../utils/commonStyles";
const EmptyContentBody = styled.div`
@ -7,6 +7,10 @@ const EmptyContentBody = styled.div`
padding: 64px 0;
grid-template-columns: 150px 1fr;
@media ${tablet} {
grid-template-columns: none;
}
display: grid;
grid-template-areas:
"img headerText"
@ -76,6 +80,7 @@ const EmptyContentBody = styled.div`
.ec-header,
.ec-subheading,
.ec-desc,
.ec-image,
.ec-buttons {
padding-left: 16px;
}

View File

@ -0,0 +1,24 @@
<svg width="100" height="100" viewBox="0 0 100 100" fill="none" xmlns="http://www.w3.org/2000/svg">
<g clip-path="url(#clip0_22900_255424)">
<path fill-rule="evenodd" clip-rule="evenodd" d="M80 6.667C80 4.45786 78.2091 2.66699 76 2.66699H48.5424H17.5003C17.2343 2.66699 16.9792 2.77296 16.7916 2.96145L2.958 16.8562C2.77142 17.0436 2.66666 17.2973 2.66666 17.5617V93.3337C2.66666 95.5428 4.45752 97.3337 6.66666 97.3337H76C78.2091 97.3337 80 95.5428 80 93.3337V62.0003V37.667V13.3337V6.667Z" fill="white"/>
<path d="M79.667 55.6668L79.667 93.0002C79.667 95.2093 77.8761 97.0002 75.667 97.0002L6.33366 97.0002C4.12452 97.0002 2.33366 95.2093 2.33366 93.0002L2.33366 17.7477C2.33366 17.4825 2.43901 17.2281 2.62655 17.0406L17.0408 2.62639C17.2283 2.43885 17.4827 2.3335 17.7479 2.3335L75.667 2.3335C77.8761 2.3335 79.667 4.12435 79.667 6.33349V14.1668" stroke="#333333" stroke-linecap="round" stroke-linejoin="round"/>
<path d="M16.9795 2.31344C17.1225 2.17044 17.3375 2.12766 17.5243 2.20505C17.7112 2.28244 17.833 2.46476 17.833 2.66699V14.3337C17.833 16.2667 16.266 17.8337 14.333 17.8337H2.66634C2.46411 17.8337 2.28179 17.7118 2.2044 17.525C2.12701 17.3382 2.16979 17.1231 2.31279 16.9801L16.9795 2.31344Z" fill="url(#paint0_linear_22900_255424)" stroke="#333333" stroke-linejoin="round"/>
<path fill-rule="evenodd" clip-rule="evenodd" d="M29.473 24.3359C29.473 24.0598 29.2491 23.8359 28.973 23.8359H23.7933C23.5172 23.8359 23.2933 24.0598 23.2933 24.3359C23.2933 24.6121 23.5172 24.8359 23.7933 24.8359H28.973C29.2491 24.8359 29.473 24.6121 29.473 24.3359ZM52.167 44.3316C52.167 44.0554 51.9431 43.8316 51.667 43.8316H37.0003C36.7242 43.8316 36.5003 44.0554 36.5003 44.3316C36.5003 44.6077 36.7242 44.8316 37.0003 44.8316H51.667C51.9431 44.8316 52.167 44.6077 52.167 44.3316ZM30.8337 44.3316C30.8337 44.0554 30.6098 43.8316 30.3337 43.8316H15.667C15.3909 43.8316 15.167 44.0554 15.167 44.3316C15.167 44.6077 15.3909 44.8316 15.667 44.8316H30.3337C30.6098 44.8316 30.8337 44.6077 30.8337 44.3316ZM56.0003 53.8324C56.2765 53.8324 56.5003 54.0562 56.5003 54.3324C56.5003 54.6085 56.2765 54.8324 56.0003 54.8324H15.3337C15.0575 54.8324 14.8337 54.6085 14.8337 54.3324C14.8337 54.0562 15.0575 53.8324 15.3337 53.8324H56.0003ZM44.8337 34.3367C44.8337 34.0606 44.6098 33.8367 44.3337 33.8367H15.6696C15.3935 33.8367 15.1696 34.0606 15.1696 34.3367C15.1696 34.6129 15.3935 34.8367 15.6696 34.8367H44.3337C44.6098 34.8367 44.8337 34.6129 44.8337 34.3367ZM34.3337 63.8327C34.6098 63.8327 34.8337 64.0565 34.8337 64.3327C34.8337 64.6088 34.6098 64.8327 34.3337 64.8327H15.3046C15.0285 64.8327 14.8046 64.6088 14.8046 64.3327C14.8046 64.0565 15.0285 63.8327 15.3046 63.8327H34.3337ZM42.8337 84.3285C42.8337 84.0523 42.6098 83.8285 42.3337 83.8285H15.0519C14.7758 83.8285 14.5519 84.0523 14.5519 84.3285C14.5519 84.6046 14.7758 84.8285 15.0519 84.8285H42.3337C42.6098 84.8285 42.8337 84.6046 42.8337 84.3285ZM57.667 73.8336C57.9431 73.8336 58.167 74.0575 58.167 74.3336C58.167 74.6097 57.9431 74.8336 57.667 74.8336H15.4776C15.2015 74.8336 14.9776 74.6097 14.9776 74.3336C14.9776 74.0575 15.2015 73.8336 15.4776 73.8336H57.667Z" fill="#333333"/>
<path d="M56.667 64.3325H41.9713" stroke="#333333" stroke-linecap="round"/>
<path d="M61.333 14H34.6663" stroke="url(#paint1_linear_22900_255424)" stroke-width="2" stroke-linecap="round"/>
<path d="M74.6085 50.54L74.5008 50.6763V50.85V77.1281C74.5008 77.157 74.4918 77.2141 74.4613 77.2879C74.4375 77.3456 74.4067 77.3987 74.3749 77.4408L66.9144 71.576C66.9141 71.5757 66.9137 71.5755 66.9134 71.5753C66.7972 71.4832 66.6775 71.4112 66.5833 71.356C66.5656 71.3456 66.549 71.3359 66.5334 71.3268C66.4569 71.2822 66.4043 71.2515 66.3567 71.218C66.3312 71.2 66.3147 71.1863 66.3041 71.1762C66.3001 71.1724 66.2972 71.1693 66.2952 71.1671C66.2952 71.1658 66.2951 71.1643 66.2951 71.1625V50.8441V50.6704L66.1874 50.5341L46.9854 26.2369C46.9854 26.2369 46.9854 26.2368 46.9853 26.2368C46.3784 25.4682 45.8421 24.2693 45.8331 23.3161C45.8287 22.8516 45.9486 22.502 46.1805 22.267C46.4112 22.0332 46.8314 21.8335 47.5962 21.8335H48.5404H93.4417C94.1199 21.8335 94.4692 22.0319 94.6573 22.2574C94.8569 22.4967 94.9573 22.8646 94.9353 23.3542C94.8907 24.3447 94.3548 25.5474 93.8219 26.2258C93.8218 26.2259 93.8217 26.226 93.8216 26.2261L74.6085 50.54ZM66.2914 71.1624C66.2914 71.1624 66.2914 71.1625 66.2914 71.1625L66.2914 71.1624Z" fill="#BDECFF" stroke="#333333"/>
</g>
<defs>
<linearGradient id="paint0_linear_22900_255424" x1="17.333" y1="2.09408" x2="2.66631" y2="17.3337" gradientUnits="userSpaceOnUse">
<stop stop-color="#FF8E3D"/>
<stop offset="1" stop-color="#FF6F3D"/>
</linearGradient>
<linearGradient id="paint1_linear_22900_255424" x1="61.333" y1="13.9609" x2="61.2608" y2="15.9598" gradientUnits="userSpaceOnUse">
<stop stop-color="#FF8E3D"/>
<stop offset="1" stop-color="#FF6F3D"/>
</linearGradient>
<clipPath id="clip0_22900_255424">
<rect width="100" height="100" fill="white"/>
</clipPath>
</defs>
</svg>

After

Width:  |  Height:  |  Size: 4.8 KiB

View File

@ -43,6 +43,7 @@
"NewPresentation": "New presentation",
"NewSpreadsheet": "New spreadsheet",
"NoSubfolders": "No subfolders",
"NotFoundFilterTitle": "Nothing found",
"Open": "Open",
"OpenLocation": "Open location",
"Presentation": "Presentation",

View File

@ -31,21 +31,20 @@ const EmptyFilterContainer = ({
className="empty-folder_container-icon"
size="12"
onClick={onResetFilter}
iconName="/static/images/cross.react.svg"
iconName="/static/images/clear.empty.filter.svg"
isFill
/>
<Link onClick={onResetFilter} {...linkStyles}>
{t("Common:ClearButton")}
{t("Common:ClearFilter")}
</Link>
</div>
);
return (
<EmptyContainer
headerText={t("Filter")}
subheadingText={subheadingText}
headerText={t("NotFoundFilterTitle")}
descriptionText={descriptionText}
imageSrc="images/empty_screen_filter.png"
imageSrc="images/empty_screen_filter_alt.svg"
buttons={buttons}
/>
);

View File

@ -82,6 +82,7 @@ namespace ASC.Web.Files.Services.WCFService
{
private static readonly FileEntrySerializer serializer = new FileEntrySerializer();
private readonly OFormRequestManager _oFormRequestManager;
private readonly ThirdPartySelector _thirdPartySelector;
private Global Global { get; }
private GlobalStore GlobalStore { get; }
@ -171,7 +172,8 @@ namespace ASC.Web.Files.Services.WCFService
ICacheNotify<ThumbnailRequest> thumbnailNotify,
EntryStatusManager entryStatusManager,
CompressToArchive compressToArchive,
OFormRequestManager oFormRequestManager)
OFormRequestManager oFormRequestManager,
ThirdPartySelector thirdPartySelector)
{
Global = global;
GlobalStore = globalStore;
@ -217,6 +219,7 @@ namespace ASC.Web.Files.Services.WCFService
EntryStatusManager = entryStatusManager;
CompressToArchive = compressToArchive;
_oFormRequestManager = oFormRequestManager;
_thirdPartySelector = thirdPartySelector;
}
public async Task<Folder<T>> GetFolderAsync(T folderId)
@ -838,7 +841,7 @@ namespace ASC.Web.Files.Services.WCFService
{
ErrorIf(FileTracker.IsEditing(fileId), FilesCommonResource.ErrorMassage_SecurityException_EditFileTwice);
app = ThirdPartySelector.GetAppByFileId(fileId.ToString());
app = _thirdPartySelector.GetAppByFileId(fileId.ToString());
if (app == null)
{
await EntryManager.TrackEditingAsync(fileId, Guid.Empty, AuthContext.CurrentAccount.ID, doc, true);
@ -850,7 +853,7 @@ namespace ASC.Web.Files.Services.WCFService
(File<string> File, Configuration<string> Configuration) fileOptions;
app = ThirdPartySelector.GetAppByFileId(fileId.ToString());
app = _thirdPartySelector.GetAppByFileId(fileId.ToString());
if (app == null)
{
fileOptions = await DocumentServiceHelper.GetParamsAsync(fileId.ToString(), -1, doc, true, true, false);

View File

@ -131,7 +131,7 @@ namespace ASC.Web.Files.Classes
CustomNamingPeople = customNamingPeople;
FileSecurityCommon = fileSecurityCommon;
ThumbnailExtension = configuration["files:thumbnail:exts"] ?? "jpg";
ThumbnailExtension = configuration["files:thumbnail:exts"] ?? "png";
}
#region Property

View File

@ -40,34 +40,32 @@ using ASC.Web.Studio.Utility;
using Microsoft.AspNetCore.Builder;
using Microsoft.AspNetCore.Http;
using Microsoft.Extensions.DependencyInjection;
using Microsoft.Extensions.Options;
namespace ASC.Web.Files.HttpHandlers
{
public class ThirdPartyAppHandler
{
private RequestDelegate Next { get; }
private IServiceProvider ServiceProvider { get; }
private RequestDelegate Next { get; }
public static string HandlerPath = "~/ThirdPartyApp";
public ThirdPartyAppHandler(RequestDelegate next, IServiceProvider serviceProvider)
public ThirdPartyAppHandler(RequestDelegate next)
{
Next = next;
ServiceProvider = serviceProvider;
}
public async Task Invoke(HttpContext context)
public async Task Invoke(HttpContext context, ThirdPartyAppHandlerService thirdPartyAppHandlerService)
{
using var scope = ServiceProvider.CreateScope();
var thirdPartyAppHandlerService = scope.ServiceProvider.GetService<ThirdPartyAppHandlerService>();
await thirdPartyAppHandlerService.InvokeAsync(context);
await Next.Invoke(context);
//await Next.Invoke(context);
}
}
[Scope]
public class ThirdPartyAppHandlerService
{
{
private readonly ThirdPartySelector _thirdPartySelector;
private AuthContext AuthContext { get; }
private CommonLinkUtility CommonLinkUtility { get; }
private ILog Log { get; set; }
@ -78,12 +76,14 @@ namespace ASC.Web.Files.HttpHandlers
IOptionsMonitor<ILog> optionsMonitor,
AuthContext authContext,
BaseCommonLinkUtility baseCommonLinkUtility,
CommonLinkUtility commonLinkUtility)
CommonLinkUtility commonLinkUtility,
ThirdPartySelector thirdPartySelector)
{
AuthContext = authContext;
CommonLinkUtility = commonLinkUtility;
CommonLinkUtility = commonLinkUtility;
_thirdPartySelector = thirdPartySelector;
Log = optionsMonitor.CurrentValue;
HandlerPath = baseCommonLinkUtility.ToAbsolute("~/thirdpartyapp");
HandlerPath = baseCommonLinkUtility.ToAbsolute(ThirdPartyAppHandler.HandlerPath);
}
public async Task InvokeAsync(HttpContext context)
@ -94,7 +94,7 @@ namespace ASC.Web.Files.HttpHandlers
try
{
var app = ThirdPartySelector.GetApp(context.Request.Query[ThirdPartySelector.AppAttr]);
var app = _thirdPartySelector.GetApp(context.Request.Query[ThirdPartySelector.AppAttr]);
Log.Debug("ThirdPartyApp: app - " + app);
if (await app.RequestAsync(context))

View File

@ -31,7 +31,6 @@ using System.IO;
using System.Linq;
using System.Text.Json;
using System.Text.Json.Serialization;
using System.Threading.Tasks;
using System.Web;
using ASC.Common;
@ -214,14 +213,22 @@ namespace ASC.Web.Files.Services.DocumentService
UserManager = userManager;
}
private bool? _favorite;
private bool _favoriteIsSet;
public bool? Favorite
{
get
{
if (_favoriteIsSet) return _favorite;
if (!SecurityContext.IsAuthenticated || UserManager.GetUsers(SecurityContext.CurrentAccount.ID).IsVisitor(UserManager)) return null;
if (File.Encrypted) return null;
return File.IsFavorite;
}
set
{
_favoriteIsSet = true;
_favorite = value;
}
}
public string Folder
@ -657,7 +664,8 @@ namespace ASC.Web.Files.Services.DocumentService
PathProvider pathProvider,
CustomerConfig<T> customerConfig,
LogoConfig<T> logoConfig,
FileSharing fileSharing)
FileSharing fileSharing,
ThirdPartySelector thirdPartySelector)
{
CoreBaseSettings = coreBaseSettings;
SettingsManager = settingsManager;
@ -671,9 +679,11 @@ namespace ASC.Web.Files.Services.DocumentService
Customer = customerConfig;
Logo = logoConfig;
FileSharing = fileSharing;
_thirdPartySelector = thirdPartySelector;
}
private Configuration<T> _configuration;
private readonly ThirdPartySelector _thirdPartySelector;
internal void SetConfiguration(Configuration<T> configuration)
{
@ -682,7 +692,8 @@ namespace ASC.Web.Files.Services.DocumentService
Logo.SetConfiguration(_configuration);
}
//private string _gobackUrl;
[JsonIgnore]
public string GobackUrl;
public bool IsRetina { get; set; } = false;
@ -716,7 +727,7 @@ namespace ASC.Web.Files.Services.DocumentService
{
return FileUtility.CanForcesave
&& !_configuration.Document.Info.GetFile().ProviderEntry
&& ThirdPartySelector.GetAppByFileId(_configuration.Document.Info.GetFile().ID.ToString()) == null
&& _thirdPartySelector.GetAppByFileId(_configuration.Document.Info.GetFile().ID.ToString()) == null
&& FilesSettingsHelper.Forcesave;
}
}
@ -727,13 +738,13 @@ namespace ASC.Web.Files.Services.DocumentService
{
if (_configuration.EditorType == EditorType.Embedded || _configuration.EditorType == EditorType.External) return null;
if (!AuthContext.IsAuthenticated) return null;
//if (_gobackUrl != null)
//{
// return new GobackConfig
// {
// Url = _gobackUrl,
// };
//}
if (GobackUrl != null)
{
return new GobackConfig
{
Url = GobackUrl,
};
}
var folderDao = DaoFactory.GetFolderDao<T>();
try

View File

@ -164,7 +164,9 @@ namespace ASC.Web.Files.Services.DocumentService
[Scope]
public class DocumentServiceTrackerHelper
{
{
private readonly ThirdPartySelector _thirdPartySelector;
private SecurityContext SecurityContext { get; }
private UserManager UserManager { get; }
private TenantManager TenantManager { get; }
@ -206,7 +208,8 @@ namespace ASC.Web.Files.Services.DocumentService
NotifyClient notifyClient,
MailMergeTaskRunner mailMergeTaskRunner,
FileTrackerHelper fileTracker,
IHttpClientFactory clientFactory)
IHttpClientFactory clientFactory,
ThirdPartySelector thirdPartySelector)
{
SecurityContext = securityContext;
UserManager = userManager;
@ -228,6 +231,7 @@ namespace ASC.Web.Files.Services.DocumentService
FileTracker = fileTracker;
Logger = options.CurrentValue;
ClientFactory = clientFactory;
_thirdPartySelector = thirdPartySelector;
}
public string GetCallbackUrl<T>(T fileId)
@ -275,7 +279,7 @@ namespace ASC.Web.Files.Services.DocumentService
private async Task ProcessEditAsync<T>(T fileId, TrackerData fileData)
{
if (ThirdPartySelector.GetAppByFileId(fileId.ToString()) != null)
if (_thirdPartySelector.GetAppByFileId(fileId.ToString()) != null)
{
return;
}
@ -284,7 +288,7 @@ namespace ASC.Web.Files.Services.DocumentService
var usersDrop = new List<string>();
string docKey;
var app = ThirdPartySelector.GetAppByFileId(fileId.ToString());
var app = _thirdPartySelector.GetAppByFileId(fileId.ToString());
if (app == null)
{
File<T> fileStable;
@ -356,7 +360,7 @@ namespace ASC.Web.Files.Services.DocumentService
userId = Guid.Empty;
}
var app = ThirdPartySelector.GetAppByFileId(fileId.ToString());
var app = _thirdPartySelector.GetAppByFileId(fileId.ToString());
if (app == null)
{
File<T> fileStable;

View File

@ -30,13 +30,12 @@ using System.IO;
using System.Linq;
using System.Net;
using System.Net.Http;
using System.Net.Http.Headers;
using System.Security;
using System.Text;
using System.Threading;
using System.Threading.Tasks;
using System.Web;
using System.Web;
using ASC.Common;
using ASC.Common.Caching;
using ASC.Common.Logging;
using ASC.Common.Web;
@ -73,7 +72,8 @@ using Newtonsoft.Json.Linq;
using SecurityContext = ASC.Core.SecurityContext;
namespace ASC.Web.Files.ThirdPartyApp
{
{
[Scope]
public class BoxApp : Consumer, IThirdPartyApp, IOAuthProvider
{
public const string AppAttr = "box";
@ -329,43 +329,35 @@ namespace ASC.Web.Files.ThirdPartyApp
var httpClient = _clientFactory.CreateClient();
var request = new HttpRequestMessage();
request.RequestUri = new Uri(BoxUrlUpload.Replace("{fileId}", fileId));
using (var tmpStream = new MemoryStream())
{
var boundary = DateTime.UtcNow.Ticks.ToString("x");
var metadata = $"Content-Disposition: form-data; name=\"filename\"; filename=\"{title}\"\r\nContent-Type: application/octet-stream\r\n\r\n";
var metadataPart = $"--{boundary}\r\n{metadata}";
var bytes = Encoding.UTF8.GetBytes(metadataPart);
await tmpStream.WriteAsync(bytes, 0, bytes.Length);
if (stream != null)
{
await stream.CopyToAsync(tmpStream);
}
else
{
var downloadRequest = new HttpRequestMessage();
downloadRequest.RequestUri = new Uri(downloadUrl);
using var response = await httpClient.SendAsync(request);
using var downloadStream = new ResponseStream(response);
await downloadStream.CopyToAsync(tmpStream);
}
var mediaPartEnd = $"\r\n--{boundary}--\r\n";
bytes = Encoding.UTF8.GetBytes(mediaPartEnd);
await tmpStream.WriteAsync(bytes, 0, bytes.Length);
request.Method = HttpMethod.Post;
request.Headers.Add("Authorization", "Bearer " + token);
request.Content.Headers.ContentType = new MediaTypeHeaderValue("multipart/form-data; boundary=" + boundary);
Logger.Debug("BoxApp: save file totalSize - " + tmpStream.Length);
tmpStream.Seek(0, SeekOrigin.Begin);
request.Content = new StreamContent(tmpStream);
}
request.RequestUri = new Uri(BoxUrlUpload.Replace("{fileId}", fileId));
StreamContent streamContent;
using var multipartFormContent = new MultipartFormDataContent();
if (stream != null)
{
streamContent = new StreamContent(stream);
}
else
{
var downloadRequest = new HttpRequestMessage();
downloadRequest.RequestUri = new Uri(downloadUrl);
var response = await httpClient.SendAsync(downloadRequest);
var downloadStream = new ResponseStream(response);
streamContent = new StreamContent(downloadStream);
}
streamContent.Headers.TryAddWithoutValidation("Content-Type", MimeMapping.GetMimeMapping(title));
multipartFormContent.Add(streamContent, name: "filename", fileName: title);
request.Content = multipartFormContent;
request.Method = HttpMethod.Post;
request.Headers.Add("Authorization", "Bearer " + token);
//request.Content.Headers.ContentType = new MediaTypeHeaderValue("multipart/form-data; boundary=" + boundary);
//Logger.Debug("BoxApp: save file totalSize - " + tmpStream.Length);
try
{
using var response = await httpClient.SendAsync(request);

View File

@ -31,12 +31,13 @@ using System.Linq;
using System.Net;
using System.Net.Http;
using System.Net.Http.Headers;
using System.Net.Http.Json;
using System.Security;
using System.Text;
using System.Threading;
using System.Threading.Tasks;
using System.Web;
using System.Web;
using ASC.Common;
using ASC.Common.Caching;
using ASC.Common.Logging;
using ASC.Common.Web;
@ -75,7 +76,8 @@ using MimeMapping = ASC.Common.Web.MimeMapping;
using SecurityContext = ASC.Core.SecurityContext;
namespace ASC.Web.Files.ThirdPartyApp
{
{
[Scope]
public class GoogleDriveApp : Consumer, IThirdPartyApp, IOAuthProvider
{
public const string AppAttr = "gdrive";
@ -123,7 +125,7 @@ namespace ASC.Web.Files.ThirdPartyApp
private IServiceProvider ServiceProvider { get; }
private readonly RequestHelper _requestHelper;
private readonly ThirdPartySelector _thirdPartySelector;
private readonly IHttpClientFactory _clientFactory;
private readonly OAuth20TokenHelper _oAuth20TokenHelper;
@ -166,7 +168,8 @@ namespace ASC.Web.Files.ThirdPartyApp
ConsumerFactory consumerFactory,
IHttpClientFactory clientFactory,
OAuth20TokenHelper oAuth20TokenHelper,
RequestHelper requestHelper,
RequestHelper requestHelper,
ThirdPartySelector thirdPartySelector,
string name, int order, Dictionary<string, string> additional)
: base(tenantManager, coreBaseSettings, coreSettings, configuration, cache, consumerFactory, name, order, additional)
{
@ -198,6 +201,7 @@ namespace ASC.Web.Files.ThirdPartyApp
_clientFactory = clientFactory;
_oAuth20TokenHelper = oAuth20TokenHelper;
_requestHelper = requestHelper;
_thirdPartySelector = thirdPartySelector;
}
public async Task<bool> RequestAsync(HttpContext context)
@ -338,7 +342,7 @@ namespace ASC.Web.Files.ThirdPartyApp
request.RequestUri = new Uri(GoogleLoginProvider.GoogleUrlFileUpload + "/{fileId}?uploadType=media".Replace("{fileId}", fileId));
request.Method = HttpMethod.Patch;
request.Headers.Add("Authorization", "Bearer " + token);
request.Content.Headers.ContentType = new MediaTypeHeaderValue(MimeMapping.GetMimeMapping(currentType));
if (stream != null)
{
@ -346,14 +350,16 @@ namespace ASC.Web.Files.ThirdPartyApp
}
else
{
using var response = await httpClient.SendAsync(request);
using var downloadStream = new ResponseStream(response);
var response = await httpClient.GetAsync(downloadUrl);
var downloadStream = new ResponseStream(response);
request.Content = new StreamContent(downloadStream);
}
}
request.Content.Headers.ContentType = new MediaTypeHeaderValue(MimeMapping.GetMimeMapping(currentType));
try
{
{
httpClient = _clientFactory.CreateClient();
using var response = await httpClient.SendAsync(request);
using var responseStream = await response.Content.ReadAsStreamAsync();
string result = null;
@ -470,15 +476,21 @@ namespace ASC.Web.Files.ThirdPartyApp
{
Logger.Debug("GoogleDriveApp: file must be converted");
if (FilesSettingsHelper.ConvertNotify)
{
//context.Response.Redirect(App.Location + "?" + FilesLinkUtility.FileId + "=" + HttpUtility.UrlEncode(fileId), true);
{
context.Response.Redirect(
BaseCommonLinkUtility.ToAbsolute(ThirdPartyAppHandler.HandlerPath)
+ "?" + FilesLinkUtility.Action + "=convert"
+ "&" + FilesLinkUtility.FileId + "=" + HttpUtility.UrlEncode(fileId)
+ "&" + ThirdPartySelector.AppAttr + "=" + AppAttr,
false);
return;
}
fileId = await CreateConvertedFileAsync(driveFile, token);
}
context.Response.Redirect(FilesLinkUtility.GetFileWebEditorUrl(ThirdPartySelector.BuildAppFileId(AppAttr, fileId)), true);
context.Response.Redirect(FilesLinkUtility.GetFileWebEditorUrl(ThirdPartySelector.BuildAppFileId(AppAttr, fileId)), false);
await context.Response.CompleteAsync();
return;
}
Logger.Error("GoogleDriveApp: Action not identified");
@ -528,10 +540,13 @@ namespace ASC.Web.Files.ThirdPartyApp
{
Logger.Error("GoogleDriveApp: downloadUrl is null");
throw new Exception("downloadUrl is null");
}
}
var contentLength = jsonFile.Value<string>("size");
Logger.Debug("GoogleDriveApp: get file stream contentLength - " + contentLength);
context.Response.Headers.Add("Content-Length", contentLength);
Logger.Debug("GoogleDriveApp: get file stream downloadUrl - " + downloadUrl);
var request = new HttpRequestMessage();
request.RequestUri = new Uri(downloadUrl);
request.Method = HttpMethod.Get;
@ -541,10 +556,6 @@ namespace ASC.Web.Files.ThirdPartyApp
using var response = await httpClient.SendAsync(request);
using var stream = new ResponseStream(response);
await stream.CopyToAsync(context.Response.Body);
var contentLength = jsonFile.Value<string>("size");
Logger.Debug("GoogleDriveApp: get file stream contentLength - " + contentLength);
context.Response.Headers.Add("Content-Length", contentLength);
}
catch (Exception ex)
{
@ -663,7 +674,7 @@ namespace ASC.Web.Files.ThirdPartyApp
LoginProfile loginProfile = null;
try
{
loginProfile = GoogleLoginProvider.Instance.GetLoginProfile(token.GetRefreshedToken(TokenHelper, _oAuth20TokenHelper));
loginProfile = GoogleLoginProvider.Instance.GetLoginProfile(token.GetRefreshedToken(TokenHelper, _oAuth20TokenHelper, _thirdPartySelector));
}
catch (Exception ex)
{
@ -761,36 +772,28 @@ namespace ASC.Web.Files.ThirdPartyApp
var request = new HttpRequestMessage();
request.RequestUri = new Uri(GoogleLoginProvider.GoogleUrlFileUpload + "?uploadType=multipart");
using (var tmpStream = new MemoryStream())
{
var boundary = DateTime.UtcNow.Ticks.ToString("x");
var folderdata = string.IsNullOrEmpty(folderId) ? "" : $",\"parents\":[\"{folderId}\"]";
var metadata = "{{\"name\":\"" + fileName + "\"" + folderdata + "}}";
var metadataPart = $"\r\n--{boundary}\r\nContent-Type: application/json; charset=UTF-8\r\n\r\n{metadata}";
var bytes = Encoding.UTF8.GetBytes(metadataPart);
await tmpStream.WriteAsync(bytes, 0, bytes.Length);
var mediaPartStart = $"\r\n--{boundary}\r\nContent-Type: {MimeMapping.GetMimeMapping(fileName)}\r\n\r\n";
bytes = Encoding.UTF8.GetBytes(mediaPartStart);
await tmpStream.WriteAsync(bytes, 0, bytes.Length);
await content.CopyToAsync(tmpStream);
var mediaPartEnd = $"\r\n--{boundary}--\r\n";
bytes = Encoding.UTF8.GetBytes(mediaPartEnd);
await tmpStream.WriteAsync(bytes, 0, bytes.Length);
request.Method = HttpMethod.Post;
request.Headers.Add("Authorization", "Bearer " + token);
request.Content.Headers.ContentType = new MediaTypeHeaderValue("multipart/related; boundary=" + boundary);
Logger.Debug("GoogleDriveApp: create file totalSize - " + tmpStream.Length);
request.Content = new StreamContent(tmpStream);
}
var boundary = DateTime.UtcNow.Ticks.ToString("x");
request.Method = HttpMethod.Post;
request.Headers.Add("Authorization", "Bearer " + token);
var stringContent = new { name = fileName, parents = new List<string>() };
if (!string.IsNullOrEmpty(folderId))
{
stringContent.parents.Add(folderId);
}
var streamContent = new StreamContent(content);
streamContent.Headers.TryAddWithoutValidation("Content-Type", MimeMapping.GetMimeMapping(fileName));
var multipartContent = new MultipartContent("related", boundary);
multipartContent.Add(JsonContent.Create(stringContent));
multipartContent.Add(streamContent);
request.Content = multipartContent;
//Logger.Debug("GoogleDriveApp: create file totalSize - " + tmpStream.Length);
try
{
using var response = await httpClient.SendAsync(request);

View File

@ -26,8 +26,10 @@
using System.IO;
using System.Text.RegularExpressions;
using System.Threading.Tasks;
using System.Threading.Tasks;
using ASC.Common;
using ASC.Core.Common.Configuration;
using ASC.Files.Core;
using Microsoft.AspNetCore.Http;
@ -45,11 +47,18 @@ namespace ASC.Web.Files.ThirdPartyApp
string GetFileStreamUrl(File<string> file);
Task SaveFileAsync(string fileId, string fileType, string downloadUrl, Stream stream);
}
public static class ThirdPartySelector
[Scope(Additional = typeof(ThirdPartySelectorExtension))]
public class ThirdPartySelector
{
public const string AppAttr = "app";
public static readonly Regex AppRegex = new Regex("^" + AppAttr + @"-(\S+)\|(\S+)$", RegexOptions.Singleline | RegexOptions.Compiled);
public static readonly Regex AppRegex = new Regex("^" + AppAttr + @"-(\S+)\|(\S+)$", RegexOptions.Singleline | RegexOptions.Compiled);
private readonly ConsumerFactory _consumerFactory;
public ThirdPartySelector(ConsumerFactory consumerFactory)
{
_consumerFactory = consumerFactory;
}
public static string BuildAppFileId(string app, object fileId)
{
@ -61,7 +70,7 @@ namespace ASC.Web.Files.ThirdPartyApp
return AppRegex.Match(appFileId).Groups[2].Value;
}
public static IThirdPartyApp GetAppByFileId(string fileId)
public IThirdPartyApp GetAppByFileId(string fileId)
{
if (string.IsNullOrEmpty(fileId)) return null;
var match = AppRegex.Match(fileId);
@ -70,14 +79,23 @@ namespace ASC.Web.Files.ThirdPartyApp
: null;
}
public static IThirdPartyApp GetApp(string app)
public IThirdPartyApp GetApp(string app)
{
return app switch
{
GoogleDriveApp.AppAttr => new GoogleDriveApp(),
BoxApp.AppAttr => new BoxApp(),
_ => new GoogleDriveApp(),
GoogleDriveApp.AppAttr => _consumerFactory.Get<GoogleDriveApp>(),
BoxApp.AppAttr => _consumerFactory.Get<BoxApp>(),
_ => _consumerFactory.Get<GoogleDriveApp>(),
};
}
}
public class ThirdPartySelectorExtension
{
public static void Register(DIHelper services)
{
services.TryAdd<GoogleDriveApp>();
services.TryAdd<BoxApp>();
}
}
}

View File

@ -53,11 +53,11 @@ namespace ASC.Web.Files.ThirdPartyApp
App = app;
}
public string GetRefreshedToken(TokenHelper tokenHelper, OAuth20TokenHelper oAuth20TokenHelper)
public string GetRefreshedToken(TokenHelper tokenHelper, OAuth20TokenHelper oAuth20TokenHelper, ThirdPartySelector thirdPartySelector)
{
if (IsExpired)
{
var app = ThirdPartySelector.GetApp(App);
var app = thirdPartySelector.GetApp(App);
try
{
tokenHelper.Logger.Debug("Refresh token for app: " + App);

View File

@ -60,19 +60,22 @@ namespace ASC.Web.Files.Utils
{
[Scope]
public class LockerManager
{
{
private readonly ThirdPartySelector _thirdPartySelector;
private AuthContext AuthContext { get; }
private IDaoFactory DaoFactory { get; }
public LockerManager(AuthContext authContext, IDaoFactory daoFactory)
public LockerManager(AuthContext authContext, IDaoFactory daoFactory, ThirdPartySelector thirdPartySelector)
{
AuthContext = authContext;
DaoFactory = daoFactory;
DaoFactory = daoFactory;
_thirdPartySelector = thirdPartySelector;
}
public bool FileLockedForMe<T>(T fileId, Guid userId = default)
{
var app = ThirdPartySelector.GetAppByFileId(fileId.ToString());
var app = _thirdPartySelector.GetAppByFileId(fileId.ToString());
if (app != null)
{
return false;
@ -86,7 +89,7 @@ namespace ASC.Web.Files.Utils
public async Task<bool> FileLockedForMeAsync<T>(T fileId, Guid userId = default)
{
var app = ThirdPartySelector.GetAppByFileId(fileId.ToString());
var app = _thirdPartySelector.GetAppByFileId(fileId.ToString());
if (app != null)
{
return false;
@ -260,7 +263,8 @@ namespace ASC.Web.Files.Utils
[Scope]
public class EntryManager
{
private const string UPDATE_LIST = "filesUpdateList";
private const string UPDATE_LIST = "filesUpdateList";
private readonly ThirdPartySelector _thirdPartySelector;
private ICache Cache { get; set; }
private FileTrackerHelper FileTracker { get; }
@ -315,7 +319,8 @@ namespace ASC.Web.Files.Utils
ICache cache,
FileTrackerHelper fileTracker,
EntryStatusManager entryStatusManager,
IHttpClientFactory clientFactory)
IHttpClientFactory clientFactory,
ThirdPartySelector thirdPartySelector)
{
DaoFactory = daoFactory;
FileSecurity = fileSecurity;
@ -342,7 +347,8 @@ namespace ASC.Web.Files.Utils
Cache = cache;
FileTracker = fileTracker;
EntryStatusManager = entryStatusManager;
ClientFactory = clientFactory;
ClientFactory = clientFactory;
_thirdPartySelector = thirdPartySelector;
}
public async Task<(IEnumerable<FileEntry> Entries, int Total)> GetEntriesAsync<T>(Folder<T> parent, int from, int count, FilterType filter, bool subjectGroup, Guid subjectId, string searchText, bool searchInContent, bool withSubfolders, OrderBy orderBy)
@ -1008,7 +1014,7 @@ namespace ASC.Web.Files.Utils
? FileUtility.GetFileExtension(downloadUri)
: fileExtension;
var app = ThirdPartySelector.GetAppByFileId(fileId.ToString());
var app = _thirdPartySelector.GetAppByFileId(fileId.ToString());
if (app != null)
{
await app.SaveFileAsync(fileId.ToString(), newExtension, downloadUri, stream);

View File

@ -43,6 +43,7 @@ using ASC.FederatedLogin.Helpers;
using ASC.FederatedLogin.LoginProviders;
using ASC.Files.Core;
using ASC.Files.Core.Model;
using ASC.Files.Core.Security;
using ASC.Files.Helpers;
using ASC.Files.Model;
using ASC.MessagingSystem;
@ -55,6 +56,7 @@ using ASC.Web.Files.Helpers;
using ASC.Web.Files.Services.DocumentService;
using ASC.Web.Files.Services.WCFService;
using ASC.Web.Files.Services.WCFService.FileOperations;
using ASC.Web.Files.ThirdPartyApp;
using ASC.Web.Files.Utils;
using ASC.Web.Studio.Core;
using ASC.Web.Studio.Utility;
@ -77,6 +79,8 @@ namespace ASC.Api.Documents
{
private readonly FileStorageService<string> FileStorageService;
private readonly RequestHelper _requestHelper;
private readonly ThirdPartySelector _thirdPartySelector;
private readonly DocumentServiceHelper _documentServiceHelper;
private FilesControllerHelper<string> FilesControllerHelperString { get; }
private FilesControllerHelper<int> FilesControllerHelperInt { get; }
@ -131,6 +135,8 @@ namespace ASC.Api.Documents
FileUtility fileUtility,
ConsumerFactory consumerFactory,
RequestHelper requestHelper,
ThirdPartySelector thirdPartySelector,
DocumentServiceHelper documentServiceHelper,
IServiceProvider serviceProvider)
{
FilesControllerHelperString = filesControllerHelperString;
@ -156,7 +162,9 @@ namespace ASC.Api.Documents
ProductEntryPoint = productEntryPoint;
TenantManager = tenantManager;
FileUtility = fileUtility;
this._requestHelper = requestHelper;
_requestHelper = requestHelper;
_thirdPartySelector = thirdPartySelector;
_documentServiceHelper = documentServiceHelper;
ServiceProvider = serviceProvider;
}
@ -687,6 +695,22 @@ namespace ASC.Api.Documents
return FilesControllerHelperString.OpenEditAsync(fileId, version, doc, view);
}
[AllowAnonymous]
[Read("file/app-{fileId}/openedit", Check = false)]
public async Task<Configuration<string>> OpenEditThirdPartyAsync(string fileId, int version, string doc, bool view)
{
fileId = "app-" + fileId;
var app = _thirdPartySelector.GetAppByFileId(fileId?.ToString());
bool editable;
var file = app.GetFile(fileId?.ToString(), out editable);
var docParams = await _documentServiceHelper.GetParamsAsync(file, true, editable ? FileShare.ReadWrite : FileShare.Read, false, editable, editable, editable, false);
var configuration = docParams.Configuration;
configuration.Document.Url = app.GetFileStreamUrl(file);
configuration.Document.Info.Favorite = null;
configuration.EditorConfig.Customization.GobackUrl = string.Empty;
return FilesControllerHelperString.OpenEditAsync(configuration);
}
[AllowAnonymous]
[Read("file/{fileId:int}/openedit", Check = false)]
public Task<Configuration<int>> OpenEditAsync(int fileId, int version, string doc, bool view)
@ -1141,6 +1165,16 @@ namespace ASC.Api.Documents
return FilesControllerHelperString.GetFileInfoAsync(fileId, version);
}
[Read("file/app-{fileId}", order: int.MaxValue, DisableFormat = true)]
public async Task<FileEntryWrapper> GetFileInfoThirdPartyAsync(string fileId, int version = -1)
{
fileId = "app-" + fileId;
var app = _thirdPartySelector.GetAppByFileId(fileId?.ToString());
var file = app.GetFile(fileId?.ToString(), out var editable);
var docParams = await _documentServiceHelper.GetParamsAsync(file, true, editable ? FileShare.ReadWrite : FileShare.Read, false, editable, editable, editable, false);
return await FilesControllerHelperString.GetFileEntryWrapperAsync(docParams.File);
}
[Read("file/{fileId:int}")]
public Task<FileWrapper<int>> GetFileInfoAsync(int fileId, int version = -1)
{

View File

@ -248,8 +248,11 @@ namespace ASC.Files.Helpers
public async Task<Configuration<T>> OpenEditAsync(T fileId, int version, string doc, bool view)
{
var docParams = await DocumentServiceHelper.GetParamsAsync(fileId, version, doc, true, !view, true);
var configuration = docParams.Configuration;
return OpenEditAsync(docParams.Configuration);
}
public Configuration<T> OpenEditAsync(Configuration<T> configuration)
{
configuration.EditorType = EditorType.External;
if (configuration.EditorConfig.ModeWrite)
{

View File

@ -1,3 +1,4 @@
using System;
using System.Text;
using System.Text.Json.Serialization;
@ -58,28 +59,28 @@ namespace ASC.Files
base.Configure(app, env);
app.MapWhen(
context => context.Request.Path.ToString().EndsWith("httphandlers/filehandler.ashx"),
context => context.Request.Path.ToString().EndsWith("httphandlers/filehandler.ashx", StringComparison.OrdinalIgnoreCase),
appBranch =>
{
appBranch.UseFileHandler();
});
app.MapWhen(
context => context.Request.Path.ToString().EndsWith("ChunkedUploader.ashx"),
context => context.Request.Path.ToString().EndsWith("ChunkedUploader.ashx", StringComparison.OrdinalIgnoreCase),
appBranch =>
{
appBranch.UseChunkedUploaderHandler();
});
app.MapWhen(
context => context.Request.Path.ToString().EndsWith("ThirdPartyAppHandler.ashx"),
context => context.Request.Path.ToString().EndsWith("ThirdPartyApp", StringComparison.OrdinalIgnoreCase),
appBranch =>
{
appBranch.UseThirdPartyAppHandler();
});
app.MapWhen(
context => context.Request.Path.ToString().EndsWith("DocuSignHandler.ashx"),
context => context.Request.Path.ToString().EndsWith("httphandlers/DocuSignHandler.ashx", StringComparison.OrdinalIgnoreCase),
appBranch =>
{
appBranch.UseDocuSignHandler();

View File

@ -0,0 +1,11 @@
<svg width="12" height="12" viewBox="0 0 12 12" fill="none" xmlns="http://www.w3.org/2000/svg">
<g clip-path="url(#clip0_14585_305514)">
<path d="M12.25 -1.58252L8.85833 1.80797L10.1748 3.12445L13.5659 -0.266645L12.25 -1.58252Z" fill="#657077"/>
<path fill-rule="evenodd" clip-rule="evenodd" d="M0.371284 4.80045L2.3017 6.73087L4.49309 4.53949L4.97459 5.02099L2.78321 7.21237L4.78734 9.2165L6.97872 7.02512L7.47584 7.52224L5.28446 9.71363L7.19926 11.6284C7.70108 12.1302 8.55137 11.9642 8.82754 11.3105L10.406 7.9441L4.0285 1.56658L0.689239 3.17217C0.0355012 3.44834 -0.130535 4.29863 0.371284 4.80045ZM4.5308 1.07654L4.92206 0.700129C5.70311 -0.08092 6.96944 -0.0809195 7.75049 0.700129L8.85833 1.80797L10.1748 3.12445L11.2996 4.24922C12.0806 5.03026 12.0806 6.29659 11.2996 7.07764L10.9083 7.45405L4.5308 1.07654Z" fill="#657077"/>
</g>
<defs>
<clipPath id="clip0_14585_305514">
<rect width="12" height="12" fill="white"/>
</clipPath>
</defs>
</svg>

After

Width:  |  Height:  |  Size: 952 B

View File

@ -14,6 +14,7 @@
"Sorting": "Sorting",
"CancelButton": "Cancel",
"ClearButton": "Reset filter",
"ClearFilter": "Clear search",
"CloseButton": "Close",
"ComingSoon": "Coming soon",
"CommunityProduct": "Community",

View File

@ -216,7 +216,7 @@
<PrivateAssets>all</PrivateAssets>
<IncludeAssets>runtime; build; native; contentfiles; analyzers; buildtransitive</IncludeAssets>
</PackageReference>
<PackageReference Include="SixLabors.ImageSharp.Drawing" Version="1.0.0-beta0008" />
<PackageReference Include="SixLabors.ImageSharp.Drawing" Version="1.0.0-beta14" />
</ItemGroup>
</Project>