DocSpace-buildtools/common/ASC.Data.Storage/RackspaceCloud/RackspaceCloudStorage.cs

754 lines
27 KiB
C#
Raw Normal View History

2019-06-04 14:43:20 +00:00
/*
*
* (c) Copyright Ascensio System Limited 2010-2018
*
* This program is freeware. You can redistribute it and/or modify it under the terms of the GNU
* General Public License (GPL) version 3 as published by the Free Software Foundation (https://www.gnu.org/copyleft/gpl.html).
* In accordance with Section 7(a) of the GNU GPL its Section 15 shall be amended to the effect that
* Ascensio System SIA expressly excludes the warranty of non-infringement of any third-party rights.
*
* THIS PROGRAM IS DISTRIBUTED WITHOUT ANY WARRANTY; WITHOUT EVEN THE IMPLIED WARRANTY OF MERCHANTABILITY OR
* FITNESS FOR A PARTICULAR PURPOSE. For more details, see GNU GPL at https://www.gnu.org/copyleft/gpl.html
*
* You can contact Ascensio System SIA by email at sales@onlyoffice.com
*
* The interactive user interfaces in modified source and object code versions of ONLYOFFICE must display
* Appropriate Legal Notices, as required under Section 5 of the GNU GPL version 3.
*
* Pursuant to Section 7 § 3(b) of the GNU GPL you must retain the original ONLYOFFICE logo which contains
* relevant author attributions when distributing the software. If the display of the logo in its graphic
* form is not reasonably feasible for technical reasons, you must include the words "Powered by ONLYOFFICE"
* in every copy of the program you distribute.
* Pursuant to Section 7 § 3(e) we decline to grant you any rights under trademark law for use of our trademarks.
*
*/
using System;
using System.Collections.Generic;
2019-08-15 12:04:42 +00:00
using System.IO;
2019-06-04 14:43:20 +00:00
using System.Linq;
2022-01-13 11:19:39 +00:00
using System.Net.Http;
2021-05-21 13:26:42 +00:00
using System.Threading.Tasks;
2019-06-04 14:43:20 +00:00
using System.Web;
2020-12-04 10:52:07 +00:00
using ASC.Common;
2019-06-04 14:43:20 +00:00
using ASC.Common.Logging;
2019-09-20 14:04:06 +00:00
using ASC.Core;
2019-08-15 12:04:42 +00:00
using ASC.Data.Storage.Configuration;
2019-09-23 12:20:08 +00:00
using ASC.Security.Cryptography;
2019-10-18 08:48:27 +00:00
using Microsoft.AspNetCore.Http;
2019-10-17 15:55:35 +00:00
using Microsoft.Extensions.Options;
2019-06-04 14:43:20 +00:00
using net.openstack.Core.Domain;
using net.openstack.Providers.Rackspace;
2019-06-04 14:43:20 +00:00
using MimeMapping = ASC.Common.Web.MimeMapping;
namespace ASC.Data.Storage.RackspaceCloud
{
2020-12-04 10:52:07 +00:00
[Scope]
2019-06-04 14:43:20 +00:00
public class RackspaceCloudStorage : BaseStorage
{
private string _region;
private string _private_container;
2019-08-15 13:16:39 +00:00
private string _public_container;
2019-06-04 14:43:20 +00:00
private readonly List<string> _domains = new List<string>();
2019-09-20 14:04:06 +00:00
private Dictionary<string, ACL> _domainsAcl;
private ACL _moduleAcl;
2019-08-15 13:16:39 +00:00
private string _subDir;
2019-06-04 14:43:20 +00:00
private string _username;
private string _apiKey;
private bool _lowerCasing = true;
private Uri _cname;
2019-08-15 12:04:42 +00:00
private Uri _cnameSSL;
2019-06-04 14:43:20 +00:00
2019-10-17 15:55:35 +00:00
private readonly ILog _logger;
2020-12-22 12:51:04 +00:00
public RackspaceCloudStorage(
2021-05-21 13:26:42 +00:00
TempPath tempPath,
2021-05-17 11:35:00 +00:00
TempStream tempStream,
2020-12-22 12:51:04 +00:00
TenantManager tenantManager,
2019-10-17 15:55:35 +00:00
PathUtils pathUtils,
EmailValidationKeyProvider emailValidationKeyProvider,
2019-10-18 08:48:27 +00:00
IHttpContextAccessor httpContextAccessor,
2022-01-13 11:19:39 +00:00
IOptionsMonitor<ILog> options,
IHttpClientFactory httpClient)
: base(tempStream, tenantManager, pathUtils, emailValidationKeyProvider, httpContextAccessor, options, httpClient)
2019-06-04 14:43:20 +00:00
{
2019-10-17 15:55:35 +00:00
_logger = options.Get("ASC.Data.Storage.Rackspace.RackspaceCloudStorage");
2021-05-21 13:26:42 +00:00
TempPath = tempPath;
2019-06-04 14:43:20 +00:00
}
private string MakePath(string domain, string path)
{
string result;
path = path.TrimStart('\\', '/').TrimEnd('/').Replace('\\', '/');
2019-08-15 13:16:39 +00:00
if (!string.IsNullOrEmpty(_subDir))
2019-06-04 14:43:20 +00:00
{
if (_subDir.Length == 1 && (_subDir[0] == '/' || _subDir[0] == '\\'))
result = path;
else
2022-01-14 13:12:37 +00:00
result = $"{_subDir}/{path}"; // Ignory all, if _subDir is not null
2019-06-04 14:43:20 +00:00
}
else//Key combined from module+domain+filename
2022-01-14 13:12:37 +00:00
result = $"{_tenant}/{_modulename}/{domain}/{path}";
2019-06-04 14:43:20 +00:00
result = result.Replace("//", "/").TrimStart('/');
if (_lowerCasing)
{
result = result.ToLowerInvariant();
}
2019-08-15 12:04:42 +00:00
2019-06-04 14:43:20 +00:00
return result;
}
2019-08-15 12:04:42 +00:00
2019-06-04 14:43:20 +00:00
private CloudFilesProvider GetClient()
{
2019-08-15 13:03:57 +00:00
var cloudIdentity = new CloudIdentity()
2019-06-04 14:43:20 +00:00
{
Username = _username,
APIKey = _apiKey
};
2019-08-15 12:04:42 +00:00
2019-06-04 14:43:20 +00:00
return new CloudFilesProvider(cloudIdentity);
}
2019-09-20 14:04:06 +00:00
public override IDataStore Configure(string tenant, Handler handlerConfig, Module moduleConfig, IDictionary<string, string> props)
2019-06-04 14:43:20 +00:00
{
2019-09-20 14:04:06 +00:00
_tenant = tenant;
2019-10-17 15:55:35 +00:00
if (moduleConfig != null)
2019-09-20 14:04:06 +00:00
{
_modulename = moduleConfig.Name;
_dataList = new DataList(moduleConfig);
2022-01-14 13:12:37 +00:00
_domains.AddRange(moduleConfig.Domain.Select(x => $"{x.Name}/"));
2019-09-20 14:04:06 +00:00
_domainsExpires = moduleConfig.Domain.Where(x => x.Expires != TimeSpan.Zero).ToDictionary(x => x.Name, y => y.Expires);
_domainsExpires.Add(string.Empty, moduleConfig.Expires);
_domainsAcl = moduleConfig.Domain.ToDictionary(x => x.Name, y => y.Acl);
_moduleAcl = moduleConfig.Acl;
}
else
{
_modulename = string.Empty;
_dataList = null;
_domainsExpires = new Dictionary<string, TimeSpan> { { string.Empty, TimeSpan.Zero } };
_domainsAcl = new Dictionary<string, ACL>();
_moduleAcl = ACL.Auto;
}
2019-06-04 14:43:20 +00:00
_private_container = props["private_container"];
_region = props["region"];
_apiKey = props["apiKey"];
_username = props["username"];
2022-01-18 14:43:46 +00:00
if (props.TryGetValue("lower", out var value))
2019-06-04 14:43:20 +00:00
{
2022-01-18 14:43:46 +00:00
bool.TryParse(value, out _lowerCasing);
2019-06-04 14:43:20 +00:00
}
2022-01-18 14:43:46 +00:00
props.TryGetValue("subdir", out _subDir);
2019-06-04 14:43:20 +00:00
_public_container = props["public_container"];
2019-08-15 13:16:39 +00:00
if (string.IsNullOrEmpty(_public_container))
2019-06-04 14:43:20 +00:00
throw new ArgumentException("_public_container");
var client = GetClient();
var cdnHeaders = client.GetContainerCDNHeader(_public_container, _region);
_cname = props.ContainsKey("cname") && Uri.IsWellFormedUriString(props["cname"], UriKind.Absolute)
? new Uri(props["cname"], UriKind.Absolute)
: new Uri(cdnHeaders.CDNUri);
_cnameSSL = props.ContainsKey("cnamessl") &&
Uri.IsWellFormedUriString(props["cnamessl"], UriKind.Absolute)
? new Uri(props["cnamessl"], UriKind.Absolute)
: new Uri(cdnHeaders.CDNSslUri);
return this;
}
public override Task<Uri> GetInternalUriAsync(string domain, string path, TimeSpan expire, IEnumerable<string> headers)
2019-06-04 14:43:20 +00:00
{
if (expire == TimeSpan.Zero || expire == TimeSpan.MinValue || expire == TimeSpan.MaxValue)
{
expire = GetExpire(domain);
}
if (expire == TimeSpan.Zero || expire == TimeSpan.MinValue || expire == TimeSpan.MaxValue)
{
return Task.FromResult(GetUriShared(domain, path));
2019-06-04 14:43:20 +00:00
}
var client = GetClient();
var accounMetaData = client.GetAccountMetaData(_region);
2019-08-16 09:08:46 +00:00
string secretKey;
2022-01-18 14:43:46 +00:00
if (accounMetaData.TryGetValue("Temp-Url-Key", out secretKey))
2019-06-04 14:43:20 +00:00
{
2022-01-18 14:43:46 +00:00
2019-06-04 14:43:20 +00:00
}
else
{
2022-01-18 14:43:46 +00:00
secretKey = Common.Utils.RandomString.Generate(64);
2019-06-04 14:43:20 +00:00
accounMetaData.Add("Temp-Url-Key", secretKey);
client.UpdateAccountMetadata(accounMetaData, _region);
}
2019-08-15 12:04:42 +00:00
return Task.FromResult(client.CreateTemporaryPublicUri(
2019-06-04 14:43:20 +00:00
JSIStudios.SimpleRESTServices.Client.HttpMethod.GET,
_private_container,
MakePath(domain, path),
2019-08-15 12:04:42 +00:00
secretKey,
2019-06-04 14:43:20 +00:00
DateTime.UtcNow.Add(expire),
_region));
2019-06-04 14:43:20 +00:00
}
private Uri GetUriShared(string domain, string path)
{
2019-10-18 08:48:27 +00:00
return new Uri(string.Format("{0}{1}", SecureHelper.IsSecure(HttpContextAccessor?.HttpContext, Options) ? _cnameSSL : _cname, MakePath(domain, path)));
2019-06-04 14:43:20 +00:00
}
2022-01-25 09:29:11 +00:00
public override Task<Stream> GetReadStreamAsync(string domain, string path)
2019-06-04 14:43:20 +00:00
{
2022-01-25 09:29:11 +00:00
return GetReadStreamAsync(domain, path, 0);
2019-06-04 14:43:20 +00:00
}
2021-05-21 13:26:42 +00:00
public override Task<Stream> GetReadStreamAsync(string domain, string path, int offset)
{
2022-01-25 09:29:11 +00:00
return GetReadStreamAsync(domain, path, offset);
2021-05-21 13:26:42 +00:00
}
2022-01-25 09:29:11 +00:00
public override Task<Uri> SaveAsync(string domain, string path, Stream stream)
2019-06-04 14:43:20 +00:00
{
2022-01-25 09:29:11 +00:00
return SaveAsync(domain, path, stream, string.Empty, string.Empty);
2019-06-04 14:43:20 +00:00
}
2022-01-25 09:29:11 +00:00
public override Task<Uri> SaveAsync(string domain, string path, Stream stream, ACL acl)
2019-06-04 14:43:20 +00:00
{
2022-01-25 09:29:11 +00:00
return SaveAsync(domain, path, stream, null, null, acl);
2019-06-04 14:43:20 +00:00
}
2022-01-25 09:29:11 +00:00
protected override Task<Uri> SaveWithAutoAttachmentAsync(string domain, string path, Stream stream, string attachmentFileName)
2019-06-04 14:43:20 +00:00
{
2022-01-14 13:12:37 +00:00
var contentDisposition = $"attachment; filename={HttpUtility.UrlPathEncode(attachmentFileName)};";
2020-12-04 10:52:07 +00:00
if (attachmentFileName.Any(c => c >= 0 && c <= 127))
2019-06-04 14:43:20 +00:00
{
2022-01-14 13:12:37 +00:00
contentDisposition = $"attachment; filename*=utf-8''{HttpUtility.UrlPathEncode(attachmentFileName)};";
2019-06-04 14:43:20 +00:00
}
2022-01-25 09:29:11 +00:00
return SaveAsync(domain, path, stream, null, contentDisposition);
2019-06-04 14:43:20 +00:00
}
2022-01-25 09:29:11 +00:00
public override Task<Uri> SaveAsync(string domain, string path, Stream stream, string contentType, string contentDisposition)
2019-06-04 14:43:20 +00:00
{
2022-01-25 09:29:11 +00:00
return SaveAsync(domain, path, stream, contentType, contentDisposition, ACL.Auto);
2019-06-04 14:43:20 +00:00
}
2022-01-25 09:29:11 +00:00
public override Task<Uri> SaveAsync(string domain, string path, Stream stream, string contentEncoding, int cacheDays)
2019-06-04 14:43:20 +00:00
{
2022-01-25 09:29:11 +00:00
return SaveAsync(domain, path, stream, string.Empty, string.Empty, ACL.Auto, contentEncoding, cacheDays);
2019-06-04 14:43:20 +00:00
}
2022-01-25 09:29:11 +00:00
public Task<Uri> SaveAsync(string domain, string path, Stream stream, string contentType,
2019-08-15 12:04:42 +00:00
string contentDisposition, ACL acl, string contentEncoding = null, int cacheDays = 5,
2019-06-04 14:43:20 +00:00
DateTime? deleteAt = null, long? deleteAfter = null)
{
2021-05-17 11:35:00 +00:00
var buffered = TempStream.GetBuffered(stream);
2019-06-04 14:43:20 +00:00
if (QuotaController != null)
{
QuotaController.QuotaUsedCheck(buffered.Length);
}
var client = GetClient();
var mime = string.IsNullOrEmpty(contentType)
? MimeMapping.GetMimeMapping(Path.GetFileName(path))
: contentType;
2019-08-15 13:16:39 +00:00
var customHeaders = new Dictionary<string, string>();
2019-06-04 14:43:20 +00:00
if (cacheDays > 0)
{
2019-08-15 13:16:39 +00:00
customHeaders.Add("Cache-Control", string.Format("public, maxage={0}", (int)TimeSpan.FromDays(cacheDays).TotalSeconds));
2019-06-04 14:43:20 +00:00
customHeaders.Add("Expires", DateTime.UtcNow.Add(TimeSpan.FromDays(cacheDays)).ToString());
}
if (deleteAt.HasValue)
{
var ts = deleteAt.Value - new DateTime(1970, 1, 1, 0, 0, 0);
2019-08-15 12:04:42 +00:00
var unixTimestamp = (long)ts.TotalSeconds;
2019-06-04 14:43:20 +00:00
customHeaders.Add("X-Delete-At", unixTimestamp.ToString());
}
if (deleteAfter.HasValue)
{
customHeaders.Add("X-Delete-After", deleteAfter.ToString());
}
2019-08-15 13:16:39 +00:00
if (!string.IsNullOrEmpty(contentEncoding))
2019-06-04 14:43:20 +00:00
customHeaders.Add("Content-Encoding", contentEncoding);
var cannedACL = acl == ACL.Auto ? GetDomainACL(domain) : ACL.Read;
if (cannedACL == ACL.Read)
{
try
{
using (var emptyStream = TempStream.Create())
{
2019-08-15 13:56:54 +00:00
var headers = new Dictionary<string, string>
{
2022-01-14 13:12:37 +00:00
{ "X-Object-Manifest", $"{_private_container}/{MakePath(domain, path)}" }
2019-08-15 13:56:54 +00:00
};
2019-06-04 14:43:20 +00:00
// create symlink
client.CreateObject(_public_container,
emptyStream,
MakePath(domain, path),
mime,
4096,
headers,
_region
);
emptyStream.Close();
}
client.PurgeObjectFromCDN(_public_container, MakePath(domain, path));
}
catch (Exception exp)
{
_logger.InfoFormat("The invalidation {0} failed", _public_container + "/" + MakePath(domain, path));
_logger.Error(exp);
2019-08-15 12:04:42 +00:00
}
2019-06-04 14:43:20 +00:00
}
stream.Position = 0;
2019-08-15 12:04:42 +00:00
2019-06-04 14:43:20 +00:00
client.CreateObject(_private_container,
stream,
MakePath(domain, path),
mime,
4096,
customHeaders,
_region
2019-08-15 12:04:42 +00:00
);
2019-06-04 14:43:20 +00:00
QuotaUsedAdd(domain, buffered.Length);
2022-01-25 09:29:11 +00:00
return GetUriAsync(domain, path);
2019-06-04 14:43:20 +00:00
}
private ACL GetDomainACL(string domain)
{
if (GetExpire(domain) != TimeSpan.Zero)
{
return ACL.Auto;
}
2022-01-18 14:43:46 +00:00
if (_domainsAcl.TryGetValue(domain, out var value))
2019-06-04 14:43:20 +00:00
{
2022-01-18 14:43:46 +00:00
return value;
2019-06-04 14:43:20 +00:00
}
return _moduleAcl;
2019-08-15 12:04:42 +00:00
}
2019-06-04 14:43:20 +00:00
2022-01-25 09:29:11 +00:00
public override async Task DeleteAsync(string domain, string path)
2019-06-04 14:43:20 +00:00
{
var client = GetClient();
2020-10-12 19:39:23 +00:00
MakePath(domain, path);
2022-01-25 09:29:11 +00:00
var size = await GetFileSizeAsync(domain, path);
2019-06-04 14:43:20 +00:00
client.DeleteObject(_private_container, MakePath(domain, path));
QuotaUsedDelete(domain, size);
}
2022-01-25 09:29:11 +00:00
public override Task DeleteFilesAsync(string domain, string folderPath, string pattern, bool recursive)
2019-06-04 14:43:20 +00:00
{
var client = GetClient();
var files = client.ListObjects(_private_container, null, null, null, MakePath(domain, folderPath), _region)
.Where(x => Wildcard.IsMatch(pattern, Path.GetFileName(x.Name)));
2022-01-25 09:29:11 +00:00
if (!files.Any()) return Task.CompletedTask;
2022-01-18 15:29:46 +00:00
foreach(var file in files)
{
client.DeleteObject(_private_container, file.Name);
}
2019-06-04 14:43:20 +00:00
if (QuotaController != null)
{
QuotaUsedDelete(domain, files.Select(x => x.Bytes).Sum());
}
2022-01-25 09:29:11 +00:00
return Task.CompletedTask;
2019-06-04 14:43:20 +00:00
}
2022-02-16 12:57:37 +00:00
public override Task DeleteFilesAsync(string domain, List<string> paths)
2019-06-04 14:43:20 +00:00
{
2022-02-16 12:57:37 +00:00
if (paths.Count == 0) return Task.CompletedTask;
2019-06-04 14:43:20 +00:00
2022-02-16 12:57:37 +00:00
return InternalDeleteFilesAsync(domain, paths);
}
private async Task InternalDeleteFilesAsync(string domain, List<string> paths)
{
2019-08-15 13:16:39 +00:00
var keysToDel = new List<string>();
2019-06-04 14:43:20 +00:00
long quotaUsed = 0;
foreach (var path in paths)
{
try
{
var key = MakePath(domain, path);
if (QuotaController != null)
{
2022-01-25 09:29:11 +00:00
quotaUsed += await GetFileSizeAsync(domain, path);
2019-06-04 14:43:20 +00:00
}
keysToDel.Add(key);
}
catch (FileNotFoundException)
{
}
}
2022-01-18 13:54:24 +00:00
if (keysToDel.Count == 0) return;
2019-06-04 14:43:20 +00:00
var client = GetClient();
keysToDel.ForEach(x => client.DeleteObject(_private_container, x));
if (quotaUsed > 0)
{
QuotaUsedDelete(domain, quotaUsed);
}
}
2022-01-25 09:29:11 +00:00
public override Task DeleteFilesAsync(string domain, string folderPath, DateTime fromDate, DateTime toDate)
2019-06-04 14:43:20 +00:00
{
var client = GetClient();
var files = client.ListObjects(_private_container, null, null, null, MakePath(domain, folderPath), _region)
.Where(x => x.LastModified >= fromDate && x.LastModified <= toDate);
2022-01-25 09:29:11 +00:00
if (!files.Any()) return Task.CompletedTask;
2019-06-04 14:43:20 +00:00
2022-01-18 15:29:46 +00:00
foreach(var file in files)
{
client.DeleteObject(_private_container, file.Name);
}
2019-06-04 14:43:20 +00:00
if (QuotaController != null)
{
QuotaUsedDelete(domain, files.Select(x => x.Bytes).Sum());
}
2022-01-25 09:29:11 +00:00
return Task.CompletedTask;
2019-06-04 14:43:20 +00:00
}
2022-01-25 09:29:11 +00:00
public override Task MoveDirectoryAsync(string srcdomain, string srcdir, string newdomain, string newdir)
2019-06-04 14:43:20 +00:00
{
var client = GetClient();
var srckey = MakePath(srcdomain, srcdir);
var dstkey = MakePath(newdomain, newdir);
var paths = client.ListObjects(_private_container, null, null, srckey, _region).Select(x => x.Name);
foreach (var path in paths)
{
client.CopyObject(_private_container, path, _private_container, path.Replace(srckey, dstkey));
client.DeleteObject(_private_container, path);
}
2022-01-25 09:29:11 +00:00
return Task.CompletedTask;
2019-06-04 14:43:20 +00:00
}
2022-01-25 09:29:11 +00:00
public override async Task<Uri> MoveAsync(string srcdomain, string srcpath, string newdomain, string newpath, bool quotaCheckFileSize = true)
2019-06-04 14:43:20 +00:00
{
var srcKey = MakePath(srcdomain, srcpath);
var dstKey = MakePath(newdomain, newpath);
2022-01-25 09:29:11 +00:00
var size = await GetFileSizeAsync(srcdomain, srcpath);
2019-06-04 14:43:20 +00:00
var client = GetClient();
client.CopyObject(_private_container, srcKey, _private_container, dstKey);
2022-01-25 09:29:11 +00:00
await DeleteAsync(srcdomain, srcpath);
2019-06-04 14:43:20 +00:00
QuotaUsedDelete(srcdomain, size);
2021-05-21 13:26:42 +00:00
QuotaUsedAdd(newdomain, size, quotaCheckFileSize);
2019-06-04 14:43:20 +00:00
2022-01-25 09:29:11 +00:00
return await GetUriAsync(newdomain, newpath);
2019-06-04 14:43:20 +00:00
}
2022-01-25 09:29:11 +00:00
public override Task<Uri> SaveTempAsync(string domain, out string assignedPath, Stream stream)
2019-06-04 14:43:20 +00:00
{
assignedPath = Guid.NewGuid().ToString();
2022-01-25 09:29:11 +00:00
return SaveAsync(domain, assignedPath, stream);
2019-06-04 14:43:20 +00:00
}
2022-01-25 09:29:11 +00:00
public override IAsyncEnumerable<string> ListDirectoriesRelativeAsync(string domain, string path, bool recursive)
2019-06-04 14:43:20 +00:00
{
var client = GetClient();
return client.ListObjects(_private_container, null, null, null, MakePath(domain, path), _region)
2022-01-25 09:29:11 +00:00
.Select(x => x.Name.Substring(MakePath(domain, path + "/").Length)).ToAsyncEnumerable();
2019-06-04 14:43:20 +00:00
}
2022-01-25 09:29:11 +00:00
public override IAsyncEnumerable<string> ListFilesRelativeAsync(string domain, string path, string pattern, bool recursive)
2019-06-04 14:43:20 +00:00
{
var client = GetClient();
2022-01-12 12:34:58 +00:00
var paths = client.ListObjects(_private_container, null, null, null, MakePath(domain, path), _region).Select(x => x.Name);
2019-06-04 14:43:20 +00:00
return paths
.Where(x => Wildcard.IsMatch(pattern, Path.GetFileName(x)))
2022-01-25 09:29:11 +00:00
.Select(x => x.Substring(MakePath(domain, path + "/").Length).TrimStart('/')).ToAsyncEnumerable();
2019-06-04 14:43:20 +00:00
}
2022-01-25 09:29:11 +00:00
public override Task<bool> IsFileAsync(string domain, string path)
2019-06-04 14:43:20 +00:00
{
var client = GetClient();
var objects = client.ListObjects(_private_container, null, null, null, MakePath(domain, path), _region);
Merge branch 'develop' into feature/async # Conflicts: # common/ASC.Data.Backup.Core/Core/FileBackupProvider.cs # common/ASC.Data.Backup.Core/Storage/BackupRepository.cs # common/ASC.Data.Backup.Core/Storage/DocumentsBackupStorage.cs # common/ASC.Data.Backup.Core/Tasks/BackupPortalTask.cs # common/ASC.Data.Backup.Core/Tasks/DeletePortalTask.cs # common/ASC.Data.Storage/CrossModuleTransferUtility.cs # common/ASC.Data.Storage/DiscStorage/DiscDataStore.cs # common/ASC.Data.Storage/Extensions.cs # common/ASC.Data.Storage/GoogleCloud/GoogleCloudStorage.cs # common/ASC.Data.Storage/RackspaceCloud/RackspaceCloudStorage.cs # common/ASC.Data.Storage/S3/S3Storage.cs # common/ASC.Data.Storage/StorageHandler.cs # common/services/ASC.ApiSystem/Controllers/PortalController.cs # products/ASC.CRM/Server/Api/VoipController.cs # products/ASC.CRM/Server/Core/Dao/RelationshipEventDao.cs # products/ASC.CRM/Server/Utils/PdfCreator.cs # products/ASC.Files/Core/Core/Dao/TeamlabDao/FileDao.cs # products/ASC.Files/Core/Core/Dao/TeamlabDao/FolderDao.cs # products/ASC.Files/Core/Core/Dao/TeamlabDao/TagDao.cs # products/ASC.Files/Core/Core/FileStorageService.cs # products/ASC.Files/Core/Core/Security/FileSecurity.cs # products/ASC.Files/Core/Core/Thirdparty/Box/BoxFileDao.cs # products/ASC.Files/Core/Core/Thirdparty/Box/BoxFolderDao.cs # products/ASC.Files/Core/Core/Thirdparty/CrossDao.cs # products/ASC.Files/Core/Core/Thirdparty/Dropbox/DropboxFileDao.cs # products/ASC.Files/Core/Core/Thirdparty/Dropbox/DropboxFolderDao.cs # products/ASC.Files/Core/Core/Thirdparty/GoogleDrive/GoogleDriveFileDao.cs # products/ASC.Files/Core/Core/Thirdparty/GoogleDrive/GoogleDriveFolderDao.cs # products/ASC.Files/Core/Core/Thirdparty/GoogleDrive/GoogleDriveStorage.cs # products/ASC.Files/Core/Core/Thirdparty/IThirdPartyProviderDao.cs # products/ASC.Files/Core/Core/Thirdparty/OneDrive/OneDriveFileDao.cs # products/ASC.Files/Core/Core/Thirdparty/OneDrive/OneDriveFolderDao.cs # products/ASC.Files/Core/Core/Thirdparty/OneDrive/OneDriveStorage.cs # products/ASC.Files/Core/Core/Thirdparty/ProviderAccountDao.cs # products/ASC.Files/Core/Core/Thirdparty/ProviderDao/ProviderDaoBase.cs # products/ASC.Files/Core/Core/Thirdparty/ProviderDao/ProviderFileDao.cs # products/ASC.Files/Core/Core/Thirdparty/ProviderDao/ProviderFolderDao.cs # products/ASC.Files/Core/Core/Thirdparty/ProviderDao/ProviderSecutiryDao.cs # products/ASC.Files/Core/Core/Thirdparty/SharePoint/SharePointFileDao.cs # products/ASC.Files/Core/Core/Thirdparty/SharePoint/SharePointProviderInfo.cs # products/ASC.Files/Core/Core/Thirdparty/Sharpbox/SharpBoxFileDao.cs # products/ASC.Files/Core/Core/Thirdparty/Sharpbox/SharpBoxFolderDao.cs # products/ASC.Files/Core/HttpHandlers/FileHandler.ashx.cs # products/ASC.Files/Core/HttpHandlers/SearchHandler.cs # products/ASC.Files/Core/Services/DocumentService/Configuration.cs # products/ASC.Files/Core/Services/DocumentService/DocumentServiceConnector.cs # products/ASC.Files/Core/Services/DocumentService/DocumentServiceTracker.cs # products/ASC.Files/Core/Services/WCFService/FileOperations/FileDownloadOperation.cs # products/ASC.Files/Core/Services/WCFService/FileOperations/FileMarkAsReadOperation.cs # products/ASC.Files/Core/Services/WCFService/FileOperations/FileMoveCopyOperation.cs # products/ASC.Files/Core/ThirdPartyApp/BoxApp.cs # products/ASC.Files/Core/ThirdPartyApp/GoogleDriveApp.cs # products/ASC.Files/Core/Utils/EntryManager.cs # products/ASC.Files/Core/Utils/FileConverter.cs # products/ASC.Files/Core/Utils/FileMarker.cs # products/ASC.Files/Core/Utils/MailMergeTask.cs # products/ASC.Files/Server/Helpers/FilesControllerHelper.cs # web/ASC.Web.Core/Files/DocumentService.cs # web/ASC.Web.Core/Files/DocumentServiceLicense.cs # web/ASC.Web.Core/Helpers/ApiSystemHelper.cs # web/ASC.Web.Core/Recaptcha.cs # web/ASC.Web.Core/Utility/UrlShortener.cs
2022-02-11 21:51:48 +00:00
var result = objects.Any();
2022-01-25 09:29:11 +00:00
return Task.FromResult(result);
2021-05-21 13:26:42 +00:00
}
2022-01-25 09:29:11 +00:00
public override Task<bool> IsDirectoryAsync(string domain, string path)
2019-06-04 14:43:20 +00:00
{
2022-01-25 09:29:11 +00:00
return IsFileAsync(domain, path);
2019-06-04 14:43:20 +00:00
}
2022-01-25 09:29:11 +00:00
public override Task DeleteDirectoryAsync(string domain, string path)
2019-06-04 14:43:20 +00:00
{
var client = GetClient();
var objToDel = client.ListObjects(_private_container, null, null, null, MakePath(domain, path), _region);
foreach (var obj in objToDel)
{
client.DeleteObject(_private_container, obj.Name);
2022-01-11 15:37:10 +00:00
QuotaUsedDelete(domain, obj.Bytes);
2019-06-04 14:43:20 +00:00
}
2022-01-25 09:29:11 +00:00
return Task.CompletedTask;
2019-06-04 14:43:20 +00:00
}
2022-01-25 09:29:11 +00:00
public override Task<long> GetFileSizeAsync(string domain, string path)
2019-06-04 14:43:20 +00:00
{
var client = GetClient();
var obj = client
.ListObjects(_private_container, null, null, null, MakePath(domain, path));
if (obj.Any())
2022-01-25 09:29:11 +00:00
return Task.FromResult(obj.Single().Bytes);
2019-06-04 14:43:20 +00:00
2022-01-25 09:29:11 +00:00
return Task.FromResult<long>(0);
2019-06-04 14:43:20 +00:00
}
2022-01-25 09:29:11 +00:00
public override Task<long> GetDirectorySizeAsync(string domain, string path)
2019-06-04 14:43:20 +00:00
{
var client = GetClient();
var objToDel = client
.ListObjects(_private_container, null, null, null, MakePath(domain, path));
long result = 0;
foreach (var obj in objToDel)
{
result += obj.Bytes;
}
2022-01-25 09:29:11 +00:00
return Task.FromResult(result);
2019-06-04 14:43:20 +00:00
}
2022-01-25 09:29:11 +00:00
public override Task<long> ResetQuotaAsync(string domain)
2019-06-04 14:43:20 +00:00
{
var client = GetClient();
var objects = client
2019-08-15 13:16:39 +00:00
.ListObjects(_private_container, null, null, null, MakePath(domain, string.Empty), _region);
2019-06-04 14:43:20 +00:00
if (QuotaController != null)
{
long size = 0;
foreach (var obj in objects)
{
size += obj.Bytes;
}
QuotaController.QuotaUsedSet(_modulename, domain, _dataList.GetData(domain), size);
2022-01-25 09:29:11 +00:00
return Task.FromResult(size);
2019-06-04 14:43:20 +00:00
}
2022-01-25 09:29:11 +00:00
return Task.FromResult <long>(0);
2019-06-04 14:43:20 +00:00
}
2022-01-25 09:29:11 +00:00
public override Task<long> GetUsedQuotaAsync(string domain)
2019-06-04 14:43:20 +00:00
{
var client = GetClient();
var objects = client
2019-08-15 13:16:39 +00:00
.ListObjects(_private_container, null, null, null, MakePath(domain, string.Empty), _region);
2019-06-04 14:43:20 +00:00
long result = 0;
foreach (var obj in objects)
{
result += obj.Bytes;
}
2022-01-25 09:29:11 +00:00
return Task.FromResult(result);
2019-06-04 14:43:20 +00:00
}
2022-01-25 09:29:11 +00:00
public override async Task<Uri> CopyAsync(string srcdomain, string path, string newdomain, string newpath)
2019-06-04 14:43:20 +00:00
{
var srcKey = MakePath(srcdomain, path);
var dstKey = MakePath(newdomain, newpath);
2022-01-25 09:29:11 +00:00
var size = await GetFileSizeAsync(srcdomain, path);
2019-06-04 14:43:20 +00:00
var client = GetClient();
client.CopyObject(_private_container, srcKey, _private_container, dstKey);
QuotaUsedAdd(newdomain, size);
2022-01-25 09:29:11 +00:00
return await GetUriAsync(newdomain, newpath);
2019-06-04 14:43:20 +00:00
}
2022-01-25 09:29:11 +00:00
public override Task CopyDirectoryAsync(string srcdomain, string dir, string newdomain, string newdir)
2019-06-04 14:43:20 +00:00
{
var srckey = MakePath(srcdomain, dir);
var dstkey = MakePath(newdomain, newdir);
var client = GetClient();
var files = client.ListObjects(_private_container, null, null, null, srckey, _region);
foreach (var file in files)
{
client.CopyObject(_private_container, file.Name, _private_container, file.Name.Replace(srckey, dstkey));
QuotaUsedAdd(newdomain, file.Bytes);
}
2022-01-25 09:29:11 +00:00
return Task.CompletedTask;
2019-06-04 14:43:20 +00:00
}
2022-01-25 09:29:11 +00:00
public override async Task<string> SavePrivateAsync(string domain, string path, Stream stream, DateTime expires)
2019-06-04 14:43:20 +00:00
{
2022-01-25 09:29:11 +00:00
var uri = await SaveAsync(domain, path, stream, "application/octet-stream", "attachment", ACL.Auto, null, 5, expires);
2019-06-04 14:43:20 +00:00
return uri.ToString();
}
2022-01-25 09:29:11 +00:00
public override Task DeleteExpiredAsync(string domain, string path, TimeSpan oldThreshold)
2019-06-04 14:43:20 +00:00
{
2022-01-25 09:29:11 +00:00
return Task.CompletedTask;
2019-06-04 14:43:20 +00:00
// When the file is saved is specified life time
}
public override string GetUploadForm(string domain, string directoryPath, string redirectTo, long maxUploadSize, string contentType, string contentDisposition, string submitLabel)
{
throw new NotImplementedException();
}
2022-01-25 09:29:11 +00:00
public override Task<string> GetUploadedUrlAsync(string domain, string directoryPath)
2019-06-04 14:43:20 +00:00
{
throw new NotImplementedException();
}
public override string GetUploadUrl()
{
throw new NotImplementedException();
}
public override string GetPostParams(string domain, string directoryPath, long maxUploadSize, string contentType, string contentDisposition)
{
throw new NotImplementedException();
}
#region chunking
2022-01-25 09:29:11 +00:00
public override Task<string> InitiateChunkedUploadAsync(string domain, string path)
2019-06-04 14:43:20 +00:00
{
2022-01-25 09:29:11 +00:00
return Task.FromResult(TempPath.GetTempFileName());
2019-06-04 14:43:20 +00:00
}
2022-01-25 09:29:11 +00:00
public override async Task<string> UploadChunkAsync(string domain, string path, string filePath, Stream stream, long defaultChunkSize, int chunkNumber, long chunkLength)
2019-06-04 14:43:20 +00:00
{
2022-01-20 09:28:48 +00:00
const int BufferSize = 4096;
2019-06-04 14:43:20 +00:00
var mode = chunkNumber == 0 ? FileMode.Create : FileMode.Append;
using (var fs = new FileStream(filePath, mode))
{
var buffer = new byte[BufferSize];
int readed;
2022-01-25 09:29:11 +00:00
while ((readed = await stream.ReadAsync(buffer, 0, BufferSize)) != 0)
2019-06-04 14:43:20 +00:00
{
2022-01-25 09:29:11 +00:00
await fs.WriteAsync(buffer, 0, readed);
2019-06-04 14:43:20 +00:00
}
}
return string.Format("{0}_{1}", chunkNumber, filePath);
}
2022-01-25 09:29:11 +00:00
public override Task AbortChunkedUploadAsync(string domain, string path, string filePath)
2019-06-04 14:43:20 +00:00
{
if (File.Exists(filePath))
{
File.Delete(filePath);
}
2022-01-25 09:29:11 +00:00
return Task.CompletedTask;
2019-06-04 14:43:20 +00:00
}
2022-01-25 09:29:11 +00:00
public override async Task<Uri> FinalizeChunkedUploadAsync(string domain, string path, string filePath, Dictionary<int, string> eTags)
2019-06-04 14:43:20 +00:00
{
var client = GetClient();
client.CreateObjectFromFile(_private_container, filePath, MakePath(domain, path));
if (File.Exists(filePath))
{
File.Delete(filePath);
}
if (QuotaController != null)
{
2022-01-25 09:29:11 +00:00
var size = await GetFileSizeAsync(domain, path);
2019-06-04 14:43:20 +00:00
QuotaUsedAdd(domain, size);
}
2022-01-25 09:29:11 +00:00
return await GetUriAsync(domain, path);
2019-06-04 14:43:20 +00:00
}
public override bool IsSupportChunking { get { return true; } }
2021-05-21 13:26:42 +00:00
public TempPath TempPath { get; }
2019-06-04 14:43:20 +00:00
#endregion
}
}