Merge branch 'master' into feature/crm-migrate
This commit is contained in:
commit
bbb4997f20
@ -44,10 +44,12 @@ Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "ASC.Textile", "common\ASC.T
|
||||
EndProject
|
||||
Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "ASC.Notify.Textile", "common\ASC.Notify.Textile\ASC.Notify.Textile.csproj", "{DB50E2EF-B4D8-493A-8568-29CAC0DF9062}"
|
||||
EndProject
|
||||
Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "ASC.ElasticSearch", "common\services\ASC.ElasticSearch\ASC.ElasticSearch.csproj", "{AE1A0E06-6CD4-4E1D-8209-22BBBD6D5652}"
|
||||
Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "ASC.ElasticSearch", "common\services\ASC.ElasticSearch\ASC.ElasticSearch.csproj", "{AE1A0E06-6CD4-4E1D-8209-22BBBD6D5652}"
|
||||
EndProject
|
||||
Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "ASC.Files", "products\ASC.Files\Server\ASC.Files.csproj", "{77BA2F61-6155-4283-BB39-F8E42F46A0B0}"
|
||||
EndProject
|
||||
Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "AppLimit.CloudComputing.SharpBox", "thirdparty\AppLimit.CloudComputing.SharpBox\AppLimit.CloudComputing.SharpBox.csproj", "{5B53855C-4347-4402-B750-76C6295A35D3}"
|
||||
EndProject
|
||||
Global
|
||||
GlobalSection(SolutionConfigurationPlatforms) = preSolution
|
||||
Debug|Any CPU = Debug|Any CPU
|
||||
@ -138,6 +140,10 @@ Global
|
||||
{77BA2F61-6155-4283-BB39-F8E42F46A0B0}.Debug|Any CPU.Build.0 = Debug|Any CPU
|
||||
{77BA2F61-6155-4283-BB39-F8E42F46A0B0}.Release|Any CPU.ActiveCfg = Release|Any CPU
|
||||
{77BA2F61-6155-4283-BB39-F8E42F46A0B0}.Release|Any CPU.Build.0 = Release|Any CPU
|
||||
{5B53855C-4347-4402-B750-76C6295A35D3}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
|
||||
{5B53855C-4347-4402-B750-76C6295A35D3}.Debug|Any CPU.Build.0 = Debug|Any CPU
|
||||
{5B53855C-4347-4402-B750-76C6295A35D3}.Release|Any CPU.ActiveCfg = Release|Any CPU
|
||||
{5B53855C-4347-4402-B750-76C6295A35D3}.Release|Any CPU.Build.0 = Release|Any CPU
|
||||
EndGlobalSection
|
||||
GlobalSection(SolutionProperties) = preSolution
|
||||
HideSolutionNode = FALSE
|
||||
|
@ -1,5 +1,8 @@
|
||||
using System.Collections.Generic;
|
||||
using System.Linq;
|
||||
|
||||
using ASC.Web.Api.Routing;
|
||||
|
||||
using Microsoft.AspNetCore.Http;
|
||||
using Microsoft.AspNetCore.Routing;
|
||||
using Microsoft.AspNetCore.Routing.Patterns;
|
||||
@ -16,7 +19,14 @@ namespace ASC.Api.Core.Core
|
||||
{
|
||||
Source = source;
|
||||
var endpoints = Source.Endpoints.Cast<RouteEndpoint>();
|
||||
Endpoints = endpoints.Select(r => new RouteEndpoint(r.RequestDelegate, RoutePatternFactory.Parse(r.RoutePattern.RawText + ".{format}"), r.Order, r.Metadata, r.DisplayName)).ToList();
|
||||
Endpoints = endpoints
|
||||
.Where(r =>
|
||||
{
|
||||
var attr = r.Metadata.OfType<CustomHttpMethodAttribute>().FirstOrDefault();
|
||||
return attr == null || !attr.DisableFormat;
|
||||
})
|
||||
.Select(r => new RouteEndpoint(r.RequestDelegate, RoutePatternFactory.Parse(r.RoutePattern.RawText + ".{format}"), r.Order, r.Metadata, r.DisplayName))
|
||||
.ToList();
|
||||
}
|
||||
|
||||
public override IChangeToken GetChangeToken()
|
||||
|
@ -1,5 +1,6 @@
|
||||
using System.Collections.Generic;
|
||||
using System.Net.Http;
|
||||
|
||||
using Microsoft.AspNetCore.Mvc.Routing;
|
||||
|
||||
namespace ASC.Web.Api.Routing
|
||||
@ -7,6 +8,7 @@ namespace ASC.Web.Api.Routing
|
||||
public abstract class CustomHttpMethodAttribute : HttpMethodAttribute
|
||||
{
|
||||
public bool Check { get; set; }
|
||||
public bool DisableFormat { get; set; }
|
||||
|
||||
public CustomHttpMethodAttribute(string method, string template = null, bool check = true, int order = 1)
|
||||
: base(new List<string>() { method }, $"[controller]{(template != null ? $"/{template}" : "")}")
|
||||
|
@ -33,7 +33,7 @@ namespace ASC.Common.Threading
|
||||
{
|
||||
public class DistributedTask
|
||||
{
|
||||
internal Action<DistributedTask> Publication { get; set; }
|
||||
public Action<DistributedTask> Publication { get; set; }
|
||||
|
||||
public DistributedTaskCache DistributedTaskCache { get; internal set; }
|
||||
|
||||
|
@ -82,7 +82,7 @@ namespace ASC.Core.Common.Configuration
|
||||
public TenantManager TenantManager { get; set; }
|
||||
public CoreBaseSettings CoreBaseSettings { get; set; }
|
||||
public CoreSettings CoreSettings { get; set; }
|
||||
public ConsumerFactory ConsumerFactory { get; }
|
||||
public ConsumerFactory ConsumerFactory { get; set; }
|
||||
public IConfiguration Configuration { get; }
|
||||
public ICacheNotify<ConsumerCacheItem> Cache { get; }
|
||||
|
||||
@ -106,14 +106,12 @@ namespace ASC.Core.Common.Configuration
|
||||
TenantManager tenantManager,
|
||||
CoreBaseSettings coreBaseSettings,
|
||||
CoreSettings coreSettings,
|
||||
ConsumerFactory consumerFactory,
|
||||
IConfiguration configuration,
|
||||
ICacheNotify<ConsumerCacheItem> cache) : this()
|
||||
{
|
||||
TenantManager = tenantManager;
|
||||
CoreBaseSettings = coreBaseSettings;
|
||||
CoreSettings = coreSettings;
|
||||
ConsumerFactory = consumerFactory;
|
||||
Configuration = configuration;
|
||||
Cache = cache;
|
||||
OnlyDefault = configuration["core:default-consumers"] == "true";
|
||||
@ -125,11 +123,10 @@ namespace ASC.Core.Common.Configuration
|
||||
TenantManager tenantManager,
|
||||
CoreBaseSettings coreBaseSettings,
|
||||
CoreSettings coreSettings,
|
||||
ConsumerFactory consumerFactory,
|
||||
IConfiguration configuration,
|
||||
ICacheNotify<ConsumerCacheItem> cache,
|
||||
string name, int order, Dictionary<string, string> additional)
|
||||
: this(tenantManager, coreBaseSettings, coreSettings, consumerFactory, configuration, cache)
|
||||
: this(tenantManager, coreBaseSettings, coreSettings, configuration, cache)
|
||||
{
|
||||
Name = name;
|
||||
Order = order;
|
||||
@ -141,11 +138,10 @@ namespace ASC.Core.Common.Configuration
|
||||
TenantManager tenantManager,
|
||||
CoreBaseSettings coreBaseSettings,
|
||||
CoreSettings coreSettings,
|
||||
ConsumerFactory consumerFactory,
|
||||
IConfiguration configuration,
|
||||
ICacheNotify<ConsumerCacheItem> cache,
|
||||
string name, int order, Dictionary<string, string> props, Dictionary<string, string> additional)
|
||||
: this(tenantManager, coreBaseSettings, coreSettings, consumerFactory, configuration, cache)
|
||||
: this(tenantManager, coreBaseSettings, coreSettings, configuration, cache)
|
||||
{
|
||||
Name = name;
|
||||
Order = order;
|
||||
@ -303,10 +299,9 @@ namespace ASC.Core.Common.Configuration
|
||||
TenantManager tenantManager,
|
||||
CoreBaseSettings coreBaseSettings,
|
||||
CoreSettings coreSettings,
|
||||
ConsumerFactory consumerFactory,
|
||||
IConfiguration configuration,
|
||||
ICacheNotify<ConsumerCacheItem> cache)
|
||||
: base(tenantManager, coreBaseSettings, coreSettings, consumerFactory, configuration, cache)
|
||||
: base(tenantManager, coreBaseSettings, coreSettings, configuration, cache)
|
||||
{
|
||||
|
||||
}
|
||||
@ -315,11 +310,10 @@ namespace ASC.Core.Common.Configuration
|
||||
TenantManager tenantManager,
|
||||
CoreBaseSettings coreBaseSettings,
|
||||
CoreSettings coreSettings,
|
||||
ConsumerFactory consumerFactory,
|
||||
IConfiguration configuration,
|
||||
ICacheNotify<ConsumerCacheItem> cache,
|
||||
string name, int order, Dictionary<string, string> additional)
|
||||
: base(tenantManager, coreBaseSettings, coreSettings, consumerFactory, configuration, cache, name, order, additional)
|
||||
: base(tenantManager, coreBaseSettings, coreSettings, configuration, cache, name, order, additional)
|
||||
{
|
||||
Init(additional);
|
||||
}
|
||||
@ -328,11 +322,10 @@ namespace ASC.Core.Common.Configuration
|
||||
TenantManager tenantManager,
|
||||
CoreBaseSettings coreBaseSettings,
|
||||
CoreSettings coreSettings,
|
||||
ConsumerFactory consumerFactory,
|
||||
IConfiguration configuration,
|
||||
ICacheNotify<ConsumerCacheItem> cache,
|
||||
string name, int order, Dictionary<string, string> props, Dictionary<string, string> additional)
|
||||
: base(tenantManager, coreBaseSettings, coreSettings, consumerFactory, configuration, cache, name, order, props, additional)
|
||||
: base(tenantManager, coreBaseSettings, coreSettings, configuration, cache, name, order, props, additional)
|
||||
{
|
||||
Init(additional);
|
||||
}
|
||||
@ -368,12 +361,12 @@ namespace ASC.Core.Common.Configuration
|
||||
var additional = fromConfig.AdditionalKeys.ToDictionary(prop => prop, prop => fromConfig[prop]);
|
||||
additional.Add(HandlerTypeKey, HandlerType.AssemblyQualifiedName);
|
||||
|
||||
return new DataStoreConsumer(fromConfig.TenantManager, fromConfig.CoreBaseSettings, fromConfig.CoreSettings, fromConfig.ConsumerFactory, fromConfig.Configuration, fromConfig.Cache, fromConfig.Name, fromConfig.Order, props, additional);
|
||||
return new DataStoreConsumer(fromConfig.TenantManager, fromConfig.CoreBaseSettings, fromConfig.CoreSettings, fromConfig.Configuration, fromConfig.Cache, fromConfig.Name, fromConfig.Order, props, additional);
|
||||
}
|
||||
|
||||
public object Clone()
|
||||
{
|
||||
return new DataStoreConsumer(TenantManager, CoreBaseSettings, CoreSettings, ConsumerFactory, Configuration, Cache, Name, Order, Props.ToDictionary(r => r.Key, r => r.Value), Additional.ToDictionary(r => r.Key, r => r.Value));
|
||||
return new DataStoreConsumer(TenantManager, CoreBaseSettings, CoreSettings, Configuration, Cache, Name, Order, Props.ToDictionary(r => r.Key, r => r.Value), Additional.ToDictionary(r => r.Key, r => r.Value));
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -80,13 +80,12 @@ namespace ASC.FederatedLogin.LoginProviders
|
||||
TenantManager tenantManager,
|
||||
CoreBaseSettings coreBaseSettings,
|
||||
CoreSettings coreSettings,
|
||||
ConsumerFactory consumerFactory,
|
||||
IConfiguration configuration,
|
||||
ICacheNotify<ConsumerCacheItem> cache,
|
||||
Signature signature,
|
||||
InstanceCrypto instanceCrypto,
|
||||
string name, int order, Dictionary<string, string> props, Dictionary<string, string> additional = null)
|
||||
: base(tenantManager, coreBaseSettings, coreSettings, consumerFactory, configuration, cache, name, order, props, additional)
|
||||
: base(tenantManager, coreBaseSettings, coreSettings, configuration, cache, name, order, props, additional)
|
||||
{
|
||||
Signature = signature;
|
||||
InstanceCrypto = instanceCrypto;
|
||||
|
@ -45,22 +45,17 @@ namespace ASC.FederatedLogin.LoginProviders
|
||||
{
|
||||
private string BitlyClientId
|
||||
{
|
||||
get { return Instance["bitlyClientId"]; }
|
||||
get { return this["bitlyClientId"]; }
|
||||
}
|
||||
|
||||
private string BitlyClientSecret
|
||||
{
|
||||
get { return Instance["bitlyClientSecret"]; }
|
||||
get { return this["bitlyClientSecret"]; }
|
||||
}
|
||||
|
||||
private string BitlyUrl
|
||||
{
|
||||
get { return Instance["bitlyUrl"]; }
|
||||
}
|
||||
|
||||
private BitlyLoginProvider Instance
|
||||
{
|
||||
get { return ConsumerFactory.Get<BitlyLoginProvider>(); }
|
||||
get { return this["bitlyUrl"]; }
|
||||
}
|
||||
|
||||
public BitlyLoginProvider() { }
|
||||
@ -69,11 +64,10 @@ namespace ASC.FederatedLogin.LoginProviders
|
||||
TenantManager tenantManager,
|
||||
CoreBaseSettings coreBaseSettings,
|
||||
CoreSettings coreSettings,
|
||||
ConsumerFactory consumerFactory,
|
||||
IConfiguration configuration,
|
||||
ICacheNotify<ConsumerCacheItem> cache,
|
||||
string name, int order, Dictionary<string, string> props, Dictionary<string, string> additional = null)
|
||||
: base(tenantManager, coreBaseSettings, coreSettings, consumerFactory, configuration, cache, name, order, props, additional)
|
||||
: base(tenantManager, coreBaseSettings, coreSettings, configuration, cache, name, order, props, additional)
|
||||
{
|
||||
}
|
||||
|
||||
|
@ -37,14 +37,6 @@ namespace ASC.FederatedLogin.LoginProviders
|
||||
{
|
||||
public class BoxLoginProvider : Consumer, IOAuthProvider
|
||||
{
|
||||
public BoxLoginProvider Instance
|
||||
{
|
||||
get
|
||||
{
|
||||
return ConsumerFactory.Get<BoxLoginProvider>();
|
||||
}
|
||||
}
|
||||
|
||||
public string Scopes { get { return ""; } }
|
||||
public string CodeUrl { get { return "https://app.box.com/api/oauth2/authorize"; } }
|
||||
public string AccessTokenUrl { get { return "https://app.box.com/api/oauth2/token"; } }
|
||||
@ -68,11 +60,10 @@ namespace ASC.FederatedLogin.LoginProviders
|
||||
TenantManager tenantManager,
|
||||
CoreBaseSettings coreBaseSettings,
|
||||
CoreSettings coreSettings,
|
||||
ConsumerFactory consumerFactory,
|
||||
IConfiguration configuration,
|
||||
ICacheNotify<ConsumerCacheItem> cache,
|
||||
string name, int order, Dictionary<string, string> props, Dictionary<string, string> additional = null)
|
||||
: base(tenantManager, coreBaseSettings, coreSettings, consumerFactory, configuration, cache, name, order, props, additional)
|
||||
: base(tenantManager, coreBaseSettings, coreSettings, configuration, cache, name, order, props, additional)
|
||||
{
|
||||
}
|
||||
}
|
||||
|
@ -40,11 +40,6 @@ namespace ASC.FederatedLogin.LoginProviders
|
||||
{
|
||||
public class DocuSignLoginProvider : Consumer, IOAuthProvider
|
||||
{
|
||||
public DocuSignLoginProvider Instance
|
||||
{
|
||||
get { return ConsumerFactory.Get<DocuSignLoginProvider>(); }
|
||||
}
|
||||
|
||||
public string Scopes { get { return "signature"; } }
|
||||
public string CodeUrl { get { return DocuSignHost + "/oauth/auth"; } }
|
||||
public string AccessTokenUrl { get { return DocuSignHost + "/oauth/token"; } }
|
||||
@ -69,11 +64,10 @@ namespace ASC.FederatedLogin.LoginProviders
|
||||
TenantManager tenantManager,
|
||||
CoreBaseSettings coreBaseSettings,
|
||||
CoreSettings coreSettings,
|
||||
ConsumerFactory consumerFactory,
|
||||
IConfiguration configuration,
|
||||
ICacheNotify<ConsumerCacheItem> cache,
|
||||
string name, int order, Dictionary<string, string> props, Dictionary<string, string> additional = null)
|
||||
: base(tenantManager, coreBaseSettings, coreSettings, consumerFactory, configuration, cache, name, order, props, additional)
|
||||
: base(tenantManager, coreBaseSettings, coreSettings, configuration, cache, name, order, props, additional)
|
||||
{
|
||||
}
|
||||
|
||||
|
@ -37,11 +37,6 @@ namespace ASC.FederatedLogin.LoginProviders
|
||||
{
|
||||
public class DropboxLoginProvider : Consumer, IOAuthProvider
|
||||
{
|
||||
public DropboxLoginProvider Instance
|
||||
{
|
||||
get { return ConsumerFactory.Get<DropboxLoginProvider>(); }
|
||||
}
|
||||
|
||||
public string Scopes { get { return ""; } }
|
||||
public string CodeUrl { get { return "https://www.dropbox.com/oauth2/authorize"; } }
|
||||
public string AccessTokenUrl { get { return "https://api.dropboxapi.com/oauth2/token"; } }
|
||||
@ -65,11 +60,10 @@ namespace ASC.FederatedLogin.LoginProviders
|
||||
TenantManager tenantManager,
|
||||
CoreBaseSettings coreBaseSettings,
|
||||
CoreSettings coreSettings,
|
||||
ConsumerFactory consumerFactory,
|
||||
IConfiguration configuration,
|
||||
ICacheNotify<ConsumerCacheItem> cache,
|
||||
string name, int order, Dictionary<string, string> props, Dictionary<string, string> additional = null)
|
||||
: base(tenantManager, coreBaseSettings, coreSettings, consumerFactory, configuration, cache, name, order, props, additional)
|
||||
: base(tenantManager, coreBaseSettings, coreSettings, configuration, cache, name, order, props, additional)
|
||||
{
|
||||
}
|
||||
}
|
||||
@ -77,7 +71,7 @@ namespace ASC.FederatedLogin.LoginProviders
|
||||
{
|
||||
public static DIHelper AddDropboxLoginProviderService(this DIHelper services)
|
||||
{
|
||||
services.TryAddScoped<DropboxLoginProvider>();
|
||||
//services.TryAddScoped<DropboxLoginProvider>();
|
||||
return services
|
||||
.AddConsumerFactoryService()
|
||||
.AddKafkaService()
|
||||
|
@ -57,13 +57,12 @@ namespace ASC.FederatedLogin.LoginProviders
|
||||
TenantManager tenantManager,
|
||||
CoreBaseSettings coreBaseSettings,
|
||||
CoreSettings coreSettings,
|
||||
ConsumerFactory consumerFactory,
|
||||
IConfiguration configuration,
|
||||
ICacheNotify<ConsumerCacheItem> cache,
|
||||
Signature signature,
|
||||
InstanceCrypto instanceCrypto,
|
||||
string name, int order, Dictionary<string, string> props, Dictionary<string, string> additional = null)
|
||||
: base(tenantManager, coreBaseSettings, coreSettings, consumerFactory, configuration, cache, signature, instanceCrypto, name, order, props, additional) { }
|
||||
: base(tenantManager, coreBaseSettings, coreSettings, configuration, cache, signature, instanceCrypto, name, order, props, additional) { }
|
||||
|
||||
public override LoginProfile GetLoginProfile(string accessToken)
|
||||
{
|
||||
|
@ -72,13 +72,12 @@ namespace ASC.FederatedLogin.LoginProviders
|
||||
public GoogleLoginProvider(TenantManager tenantManager,
|
||||
CoreBaseSettings coreBaseSettings,
|
||||
CoreSettings coreSettings,
|
||||
ConsumerFactory consumerFactory,
|
||||
IConfiguration configuration,
|
||||
ICacheNotify<ConsumerCacheItem> cache,
|
||||
Signature signature,
|
||||
InstanceCrypto instanceCrypto,
|
||||
string name, int order, Dictionary<string, string> props, Dictionary<string, string> additional = null)
|
||||
: base(tenantManager, coreBaseSettings, coreSettings, consumerFactory, configuration, cache, signature, instanceCrypto, name, order, props, additional) { }
|
||||
: base(tenantManager, coreBaseSettings, coreSettings, configuration, cache, signature, instanceCrypto, name, order, props, additional) { }
|
||||
|
||||
public override LoginProfile GetLoginProfile(string accessToken)
|
||||
{
|
||||
|
@ -101,13 +101,12 @@ namespace ASC.FederatedLogin.LoginProviders
|
||||
TenantManager tenantManager,
|
||||
CoreBaseSettings coreBaseSettings,
|
||||
CoreSettings coreSettings,
|
||||
ConsumerFactory consumerFactory,
|
||||
IConfiguration configuration,
|
||||
ICacheNotify<ConsumerCacheItem> cache,
|
||||
Signature signature,
|
||||
InstanceCrypto instanceCrypto,
|
||||
string name, int order, Dictionary<string, string> props, Dictionary<string, string> additional = null)
|
||||
: base(tenantManager, coreBaseSettings, coreSettings, consumerFactory, configuration, cache, signature, instanceCrypto, name, order, props, additional)
|
||||
: base(tenantManager, coreBaseSettings, coreSettings, configuration, cache, signature, instanceCrypto, name, order, props, additional)
|
||||
{
|
||||
}
|
||||
|
||||
|
@ -80,13 +80,12 @@ namespace ASC.FederatedLogin.LoginProviders
|
||||
public LinkedInLoginProvider(TenantManager tenantManager,
|
||||
CoreBaseSettings coreBaseSettings,
|
||||
CoreSettings coreSettings,
|
||||
ConsumerFactory consumerFactory,
|
||||
IConfiguration configuration,
|
||||
ICacheNotify<ConsumerCacheItem> cache,
|
||||
Signature signature,
|
||||
InstanceCrypto instanceCrypto,
|
||||
string name, int order, Dictionary<string, string> props, Dictionary<string, string> additional = null)
|
||||
: base(tenantManager, coreBaseSettings, coreSettings, consumerFactory, configuration, cache, signature, instanceCrypto, name, order, props, additional) { }
|
||||
: base(tenantManager, coreBaseSettings, coreSettings, configuration, cache, signature, instanceCrypto, name, order, props, additional) { }
|
||||
|
||||
public override LoginProfile GetLoginProfile(string accessToken)
|
||||
{
|
||||
|
@ -83,13 +83,12 @@ namespace ASC.FederatedLogin.LoginProviders
|
||||
public MailRuLoginProvider(TenantManager tenantManager,
|
||||
CoreBaseSettings coreBaseSettings,
|
||||
CoreSettings coreSettings,
|
||||
ConsumerFactory consumerFactory,
|
||||
IConfiguration configuration,
|
||||
ICacheNotify<ConsumerCacheItem> cache,
|
||||
Signature signature,
|
||||
InstanceCrypto instanceCrypto,
|
||||
string name, int order, Dictionary<string, string> props, Dictionary<string, string> additional = null)
|
||||
: base(tenantManager, coreBaseSettings, coreSettings, consumerFactory, configuration, cache, signature, instanceCrypto, name, order, props, additional)
|
||||
: base(tenantManager, coreBaseSettings, coreSettings, configuration, cache, signature, instanceCrypto, name, order, props, additional)
|
||||
{
|
||||
}
|
||||
|
||||
|
@ -40,11 +40,6 @@ namespace ASC.FederatedLogin.LoginProviders
|
||||
private const string OneDriveOauthUrl = "https://login.live.com/";
|
||||
public const string OneDriveApiUrl = "https://api.onedrive.com";
|
||||
|
||||
public OneDriveLoginProvider Instance
|
||||
{
|
||||
get { return ConsumerFactory.Get<OneDriveLoginProvider>(); }
|
||||
}
|
||||
|
||||
public string Scopes { get { return "wl.signin wl.skydrive_update wl.offline_access"; } }
|
||||
public string CodeUrl { get { return OneDriveOauthUrl + "oauth20_authorize.srf"; } }
|
||||
public string AccessTokenUrl { get { return OneDriveOauthUrl + "oauth20_token.srf"; } }
|
||||
@ -68,11 +63,10 @@ namespace ASC.FederatedLogin.LoginProviders
|
||||
TenantManager tenantManager,
|
||||
CoreBaseSettings coreBaseSettings,
|
||||
CoreSettings coreSettings,
|
||||
ConsumerFactory consumerFactory,
|
||||
IConfiguration configuration,
|
||||
ICacheNotify<ConsumerCacheItem> cache,
|
||||
string name, int order, Dictionary<string, string> props, Dictionary<string, string> additional = null)
|
||||
: base(tenantManager, coreBaseSettings, coreSettings, consumerFactory, configuration, cache, name, order, props, additional)
|
||||
: base(tenantManager, coreBaseSettings, coreSettings, configuration, cache, name, order, props, additional)
|
||||
{
|
||||
}
|
||||
}
|
||||
|
@ -87,13 +87,12 @@ namespace ASC.FederatedLogin.LoginProviders
|
||||
public VKLoginProvider(TenantManager tenantManager,
|
||||
CoreBaseSettings coreBaseSettings,
|
||||
CoreSettings coreSettings,
|
||||
ConsumerFactory consumerFactory,
|
||||
IConfiguration configuration,
|
||||
ICacheNotify<ConsumerCacheItem> cache,
|
||||
Signature signature,
|
||||
InstanceCrypto instanceCrypto,
|
||||
string name, int order, Dictionary<string, string> props, Dictionary<string, string> additional = null)
|
||||
: base(tenantManager, coreBaseSettings, coreSettings, consumerFactory, configuration, cache, signature, instanceCrypto, name, order, props, additional)
|
||||
: base(tenantManager, coreBaseSettings, coreSettings, configuration, cache, signature, instanceCrypto, name, order, props, additional)
|
||||
{
|
||||
}
|
||||
|
||||
|
@ -52,13 +52,12 @@ namespace ASC.FederatedLogin.LoginProviders
|
||||
public WordpressLoginProvider(TenantManager tenantManager,
|
||||
CoreBaseSettings coreBaseSettings,
|
||||
CoreSettings coreSettings,
|
||||
ConsumerFactory consumerFactory,
|
||||
IConfiguration configuration,
|
||||
ICacheNotify<ConsumerCacheItem> cache,
|
||||
Signature signature,
|
||||
InstanceCrypto instanceCrypto,
|
||||
string name, int order, Dictionary<string, string> props, Dictionary<string, string> additional = null)
|
||||
: base(tenantManager, coreBaseSettings, coreSettings, consumerFactory, configuration, cache, signature, instanceCrypto, name, order, props, additional)
|
||||
: base(tenantManager, coreBaseSettings, coreSettings, configuration, cache, signature, instanceCrypto, name, order, props, additional)
|
||||
{
|
||||
}
|
||||
|
||||
|
@ -55,13 +55,12 @@ namespace ASC.FederatedLogin.LoginProviders
|
||||
public YahooLoginProvider(TenantManager tenantManager,
|
||||
CoreBaseSettings coreBaseSettings,
|
||||
CoreSettings coreSettings,
|
||||
ConsumerFactory consumerFactory,
|
||||
IConfiguration configuration,
|
||||
ICacheNotify<ConsumerCacheItem> cache,
|
||||
Signature signature,
|
||||
InstanceCrypto instanceCrypto,
|
||||
string name, int order, Dictionary<string, string> props, Dictionary<string, string> additional = null)
|
||||
: base(tenantManager, coreBaseSettings, coreSettings, consumerFactory, configuration, cache, signature, instanceCrypto, name, order, props, additional) { }
|
||||
: base(tenantManager, coreBaseSettings, coreSettings, configuration, cache, signature, instanceCrypto, name, order, props, additional) { }
|
||||
|
||||
public OAuth20Token Auth(HttpContext context)
|
||||
{
|
||||
|
@ -80,13 +80,12 @@ namespace ASC.FederatedLogin.LoginProviders
|
||||
public YandexLoginProvider(TenantManager tenantManager,
|
||||
CoreBaseSettings coreBaseSettings,
|
||||
CoreSettings coreSettings,
|
||||
ConsumerFactory consumerFactory,
|
||||
IConfiguration configuration,
|
||||
ICacheNotify<ConsumerCacheItem> cache,
|
||||
Signature signature,
|
||||
InstanceCrypto instanceCrypto,
|
||||
string name, int order, Dictionary<string, string> props, Dictionary<string, string> additional = null)
|
||||
: base(tenantManager, coreBaseSettings, coreSettings, consumerFactory, configuration, cache, signature, instanceCrypto, name, order, props, additional)
|
||||
: base(tenantManager, coreBaseSettings, coreSettings, configuration, cache, signature, instanceCrypto, name, order, props, additional)
|
||||
{
|
||||
}
|
||||
|
||||
|
@ -76,6 +76,22 @@ namespace ASC.MessagingSystem
|
||||
|
||||
}
|
||||
|
||||
public MessageTarget Create(IEnumerable<string> value)
|
||||
{
|
||||
try
|
||||
{
|
||||
return new MessageTarget(Option)
|
||||
{
|
||||
_items = value.Distinct()
|
||||
};
|
||||
}
|
||||
catch (Exception e)
|
||||
{
|
||||
Log.Error("EventMessageTarget exception", e);
|
||||
return null;
|
||||
}
|
||||
}
|
||||
|
||||
public MessageTarget Parse(string value)
|
||||
{
|
||||
if (string.IsNullOrEmpty(value)) return null;
|
||||
|
@ -9,7 +9,7 @@
|
||||
"ConnectionStrings": {
|
||||
"default": {
|
||||
"name": "default",
|
||||
"connectionString": "Server=172.18.0.5;Port=3306;Database=onlyoffice;User ID=onlyoffice_user;Password=onlyoffice_pass;Pooling=true;Character Set=utf8;AutoEnlist=false;SSL Mode=none;AllowPublicKeyRetrieval=True",
|
||||
"connectionString": "Server=172.18.0.5;Port=3306;Database=onlyoffice;User ID=onlyoffice_user;Password=onlyoffice_pass;Pooling=true;Character Set=utf8;AutoEnlist=false;SSL Mode=none",
|
||||
"providerName": "MySql.Data.MySqlClient"
|
||||
}
|
||||
},
|
||||
|
@ -8,6 +8,15 @@
|
||||
}
|
||||
],
|
||||
"instanceScope": "singleinstance"
|
||||
},
|
||||
{
|
||||
"type": "ASC.Web.Files.Configuration.ProductEntryPoint, ASC.Files",
|
||||
"services": [
|
||||
{
|
||||
"type": "ASC.Web.Core.IWebItem, ASC.Web.Core"
|
||||
}
|
||||
],
|
||||
"instanceScope": "singleinstance"
|
||||
}
|
||||
]
|
||||
}
|
||||
|
@ -19,10 +19,28 @@
|
||||
<TreatWarningsAsErrors>true</TreatWarningsAsErrors>
|
||||
</PropertyGroup>
|
||||
<ItemGroup>
|
||||
<None Remove="proto\BoxCacheItem.proto" />
|
||||
<None Remove="proto\DropboxCacheItem.proto" />
|
||||
<None Remove="proto\GoogleDriveCacheItem.proto" />
|
||||
<None Remove="proto\OneDriveCacheItem.proto" />
|
||||
<None Remove="proto\ProviderAccountCacheItem.proto" />
|
||||
<None Remove="proto\SharePointProviderCacheItem.proto" />
|
||||
</ItemGroup>
|
||||
<ItemGroup>
|
||||
<PackageReference Include="Box.V2.Core" Version="3.22.0" />
|
||||
<PackageReference Include="DocuSign.eSign.dll" Version="4.1.1" />
|
||||
<PackageReference Include="DotNetZip" Version="1.13.5" />
|
||||
<PackageReference Include="DotNetZip" Version="1.13.7" />
|
||||
<PackageReference Include="Dropbox.Api" Version="4.9.4" />
|
||||
<PackageReference Include="Google.Apis.Drive.v3" Version="1.44.1.1876" />
|
||||
<PackageReference Include="Grpc.Tools" Version="2.27.0">
|
||||
<PrivateAssets>all</PrivateAssets>
|
||||
<IncludeAssets>runtime; build; native; contentfiles; analyzers; buildtransitive</IncludeAssets>
|
||||
</PackageReference>
|
||||
<PackageReference Include="Microsoft.AspNet.WebApi.Core" Version="5.2.7" />
|
||||
<PackageReference Include="Microsoft.OneDriveSDK" Version="2.0.7" />
|
||||
<PackageReference Include="Microsoft.SharePoint.Client" Version="14.0.4762.1000" />
|
||||
<PackageReference Include="Microsoft.VisualStudio.Web.CodeGeneration.Design" Version="3.1.1" />
|
||||
<PackageReference Include="System.Text.Encoding.CodePages" Version="4.7.0" />
|
||||
</ItemGroup>
|
||||
<ItemGroup>
|
||||
<ProjectReference Include="..\..\..\common\ASC.Api.Core\ASC.Api.Core.csproj" />
|
||||
@ -32,8 +50,17 @@
|
||||
<ProjectReference Include="..\..\..\common\ASC.FederatedLogin\ASC.FederatedLogin.csproj" />
|
||||
<ProjectReference Include="..\..\..\common\ASC.MessagingSystem\ASC.MessagingSystem.csproj" />
|
||||
<ProjectReference Include="..\..\..\common\services\ASC.ElasticSearch\ASC.ElasticSearch.csproj" />
|
||||
<ProjectReference Include="..\..\..\thirdparty\AppLimit.CloudComputing.SharpBox\AppLimit.CloudComputing.SharpBox.csproj" />
|
||||
<ProjectReference Include="..\..\..\web\ASC.Web.Core\ASC.Web.Core.csproj" />
|
||||
</ItemGroup>
|
||||
<ItemGroup>
|
||||
<Protobuf Include="proto\SharePointProviderCacheItem.proto" />
|
||||
<Protobuf Include="proto\OneDriveCacheItem.proto" />
|
||||
<Protobuf Include="proto\GoogleDriveCacheItem.proto" />
|
||||
<Protobuf Include="proto\BoxCacheItem.proto" />
|
||||
<Protobuf Include="proto\ProviderAccountCacheItem.proto" />
|
||||
<Protobuf Include="proto\DropboxCacheItem.proto" />
|
||||
</ItemGroup>
|
||||
<ItemGroup>
|
||||
<Compile Update="Resources\FilesCommonResource.Designer.cs">
|
||||
<DesignTime>True</DesignTime>
|
||||
|
File diff suppressed because it is too large
Load Diff
@ -30,13 +30,13 @@ namespace ASC.Files.Core
|
||||
{
|
||||
public interface IDaoFactory
|
||||
{
|
||||
IFolderDao FolderDao { get; }
|
||||
IFolderDao<T> GetFolderDao<T>();
|
||||
|
||||
IFileDao FileDao { get; }
|
||||
IFileDao<T> GetFileDao<T>();
|
||||
|
||||
ITagDao TagDao { get; }
|
||||
ITagDao<T> GetTagDao<T>();
|
||||
|
||||
ISecurityDao SecurityDao { get; }
|
||||
ISecurityDao<T> GetSecurityDao<T>();
|
||||
|
||||
IProviderDao ProviderDao { get; }
|
||||
}
|
||||
|
@ -32,22 +32,19 @@ using ASC.Web.Files.Services.DocumentService;
|
||||
|
||||
namespace ASC.Files.Core
|
||||
{
|
||||
/// <summary>
|
||||
/// Interface encapsulates access toFolderId files
|
||||
/// </summary>
|
||||
public interface IFileDao
|
||||
public interface IFileDao<T>
|
||||
{
|
||||
/// <summary>
|
||||
/// Clear the application cache for the specific file
|
||||
/// </summary>
|
||||
void InvalidateCache(object fileId);
|
||||
void InvalidateCache(T fileId);
|
||||
|
||||
/// <summary>
|
||||
/// Receive file
|
||||
/// </summary>
|
||||
/// <param name="fileId">file id</param>
|
||||
/// <returns></returns>
|
||||
File GetFile(object fileId);
|
||||
File<T> GetFile(T fileId);
|
||||
|
||||
/// <summary>
|
||||
/// Receive file
|
||||
@ -55,7 +52,7 @@ namespace ASC.Files.Core
|
||||
/// <param name="fileId">file id</param>
|
||||
/// <param name="fileVersion">file version</param>
|
||||
/// <returns></returns>
|
||||
File GetFile(object fileId, int fileVersion);
|
||||
File<T> GetFile(T fileId, int fileVersion);
|
||||
|
||||
/// <summary>
|
||||
/// Receive file
|
||||
@ -65,7 +62,7 @@ namespace ASC.Files.Core
|
||||
/// <returns>
|
||||
/// file
|
||||
/// </returns>
|
||||
File GetFile(object parentId, string title);
|
||||
File<T> GetFile(T parentId, string title);
|
||||
|
||||
/// <summary>
|
||||
/// Receive last file without forcesave
|
||||
@ -73,21 +70,21 @@ namespace ASC.Files.Core
|
||||
/// <param name="fileId">file id</param>
|
||||
/// <param name="fileVersion"></param>
|
||||
/// <returns></returns>
|
||||
File GetFileStable(object fileId, int fileVersion = -1);
|
||||
File<T> GetFileStable(T fileId, int fileVersion = -1);
|
||||
|
||||
/// <summary>
|
||||
/// Returns all versions of the file
|
||||
/// </summary>
|
||||
/// <param name="fileId"></param>
|
||||
/// <returns></returns>
|
||||
List<File> GetFileHistory(object fileId);
|
||||
List<File<T>> GetFileHistory(T fileId);
|
||||
|
||||
/// <summary>
|
||||
/// Gets the file (s) by ID (s)
|
||||
/// </summary>
|
||||
/// <param name="fileIds">id file</param>
|
||||
/// <returns></returns>
|
||||
List<File> GetFiles(object[] fileIds);
|
||||
List<File<T>> GetFiles(T[] fileIds);
|
||||
|
||||
/// <summary>
|
||||
/// Gets the file (s) by ID (s) for share
|
||||
@ -99,14 +96,14 @@ namespace ASC.Files.Core
|
||||
/// <param name="searchText"></param>
|
||||
/// <param name="searchInContent"></param>
|
||||
/// <returns></returns>
|
||||
List<File> GetFilesForShare(object[] fileIds, FilterType filterType, bool subjectGroup, Guid subjectID, string searchText, bool searchInContent);
|
||||
List<File<T>> GetFilesForShare(T[] fileIds, FilterType filterType, bool subjectGroup, Guid subjectID, string searchText, bool searchInContent);
|
||||
|
||||
/// <summary>
|
||||
///
|
||||
/// </summary>
|
||||
/// <param name="parentId"></param>
|
||||
/// <returns></returns>
|
||||
List<object> GetFiles(object parentId);
|
||||
List<T> GetFiles(T parentId);
|
||||
|
||||
/// <summary>
|
||||
/// Get files in folder
|
||||
@ -123,14 +120,14 @@ namespace ASC.Files.Core
|
||||
/// <remarks>
|
||||
/// Return only the latest versions of files of a folder
|
||||
/// </remarks>
|
||||
List<File> GetFiles(object parentId, OrderBy orderBy, FilterType filterType, bool subjectGroup, Guid subjectID, string searchText, bool searchInContent, bool withSubfolders = false);
|
||||
List<File<T>> GetFiles(T parentId, OrderBy orderBy, FilterType filterType, bool subjectGroup, Guid subjectID, string searchText, bool searchInContent, bool withSubfolders = false);
|
||||
|
||||
/// <summary>
|
||||
/// Get stream of file
|
||||
/// </summary>
|
||||
/// <param name="file"></param>
|
||||
/// <returns>Stream</returns>
|
||||
Stream GetFileStream(File file);
|
||||
Stream GetFileStream(File<T> file);
|
||||
|
||||
/// <summary>
|
||||
/// Get stream of file
|
||||
@ -138,7 +135,7 @@ namespace ASC.Files.Core
|
||||
/// <param name="file"></param>
|
||||
/// <param name="offset"></param>
|
||||
/// <returns>Stream</returns>
|
||||
Stream GetFileStream(File file, long offset);
|
||||
Stream GetFileStream(File<T> file, long offset);
|
||||
|
||||
/// <summary>
|
||||
/// Get presigned uri
|
||||
@ -146,14 +143,14 @@ namespace ASC.Files.Core
|
||||
/// <param name="file"></param>
|
||||
/// <param name="expires"></param>
|
||||
/// <returns>Stream uri</returns>
|
||||
Uri GetPreSignedUri(File file, TimeSpan expires);
|
||||
Uri GetPreSignedUri(File<T> file, TimeSpan expires);
|
||||
|
||||
/// <summary>
|
||||
/// Check is supported PreSignedUri
|
||||
/// </summary>
|
||||
/// <param name="file"></param>
|
||||
/// <returns>Stream uri</returns>
|
||||
bool IsSupportedPreSignedUri(File file);
|
||||
bool IsSupportedPreSignedUri(File<T> file);
|
||||
|
||||
/// <summary>
|
||||
/// Saves / updates the version of the file
|
||||
@ -169,7 +166,7 @@ namespace ASC.Files.Core
|
||||
///
|
||||
/// Save in all other cases
|
||||
/// </remarks>
|
||||
File SaveFile(File file, Stream fileStream);
|
||||
File<T> SaveFile(File<T> file, Stream fileStream);
|
||||
|
||||
/// <summary>
|
||||
///
|
||||
@ -177,13 +174,13 @@ namespace ASC.Files.Core
|
||||
/// <param name="file"></param>
|
||||
/// <param name="fileStream"></param>
|
||||
/// <returns></returns>
|
||||
File ReplaceFileVersion(File file, Stream fileStream);
|
||||
File<T> ReplaceFileVersion(File<T> file, Stream fileStream);
|
||||
|
||||
/// <summary>
|
||||
/// Deletes a file including all previous versions
|
||||
/// </summary>
|
||||
/// <param name="fileId">file id</param>
|
||||
void DeleteFile(object fileId);
|
||||
void DeleteFile(T fileId);
|
||||
|
||||
/// <summary>
|
||||
/// Checks whether or not file
|
||||
@ -198,21 +195,27 @@ namespace ASC.Files.Core
|
||||
/// </summary>
|
||||
/// <param name="fileId">file id</param>
|
||||
/// <param name="toFolderId">The ID of the destination folder</param>
|
||||
object MoveFile(object fileId, object toFolderId);
|
||||
T MoveFile(T fileId, T toFolderId);
|
||||
TTo MoveFile<TTo>(T fileId, TTo toFolderId);
|
||||
string MoveFile(T fileId, string toFolderId);
|
||||
int MoveFile(T fileId, int toFolderId);
|
||||
|
||||
/// <summary>
|
||||
/// Copy the files in a folder
|
||||
/// </summary>
|
||||
/// <param name="fileId">file id</param>
|
||||
/// <param name="toFolderId">The ID of the destination folder</param>
|
||||
File CopyFile(object fileId, object toFolderId);
|
||||
File<T> CopyFile(T fileId, T toFolderId);
|
||||
File<TTo> CopyFile<TTo>(T fileId, TTo toFolderId);
|
||||
File<string> CopyFile(T fileId, string toFolderId);
|
||||
File<int> CopyFile(T fileId, int toFolderId);
|
||||
|
||||
/// <summary>
|
||||
/// Rename file
|
||||
/// </summary>
|
||||
/// <param name="file"></param>
|
||||
/// <param name="newTitle">new name</param>
|
||||
object FileRename(File file, string newTitle);
|
||||
T FileRename(File<T> file, string newTitle);
|
||||
|
||||
/// <summary>
|
||||
/// Update comment file
|
||||
@ -220,36 +223,38 @@ namespace ASC.Files.Core
|
||||
/// <param name="fileId">file id</param>
|
||||
/// <param name="fileVersion">file version</param>
|
||||
/// <param name="comment">new comment</param>
|
||||
string UpdateComment(object fileId, int fileVersion, string comment);
|
||||
string UpdateComment(T fileId, int fileVersion, string comment);
|
||||
|
||||
/// <summary>
|
||||
/// Complete file version
|
||||
/// </summary>
|
||||
/// <param name="fileId">file id</param>
|
||||
/// <param name="fileVersion">file version</param>
|
||||
void CompleteVersion(object fileId, int fileVersion);
|
||||
void CompleteVersion(T fileId, int fileVersion);
|
||||
|
||||
/// <summary>
|
||||
/// Continue file version
|
||||
/// </summary>
|
||||
/// <param name="fileId">file id</param>
|
||||
/// <param name="fileVersion">file version</param>
|
||||
void ContinueVersion(object fileId, int fileVersion);
|
||||
void ContinueVersion(T fileId, int fileVersion);
|
||||
|
||||
/// <summary>
|
||||
/// Check the need to use the trash before removing
|
||||
/// </summary>
|
||||
/// <param name="file"></param>
|
||||
/// <returns></returns>
|
||||
bool UseTrashForRemove(File file);
|
||||
bool UseTrashForRemove(File<T> file);
|
||||
|
||||
string GetUniqFilePath(File<T> file, string fileTitle);
|
||||
|
||||
#region chunking
|
||||
|
||||
ChunkedUploadSession CreateUploadSession(File file, long contentLength);
|
||||
ChunkedUploadSession<T> CreateUploadSession(File<T> file, long contentLength);
|
||||
|
||||
void UploadChunk(ChunkedUploadSession uploadSession, Stream chunkStream, long chunkLength);
|
||||
void UploadChunk(ChunkedUploadSession<T> uploadSession, Stream chunkStream, long chunkLength);
|
||||
|
||||
void AbortUploadSession(ChunkedUploadSession uploadSession);
|
||||
void AbortUploadSession(ChunkedUploadSession<T> uploadSession);
|
||||
|
||||
#endregion
|
||||
|
||||
@ -260,7 +265,7 @@ namespace ASC.Files.Core
|
||||
/// </summary>
|
||||
/// <param name="fileIds"></param>
|
||||
/// <param name="newOwnerId"></param>
|
||||
void ReassignFiles(object[] fileIds, Guid newOwnerId);
|
||||
void ReassignFiles(T[] fileIds, Guid newOwnerId);
|
||||
|
||||
/// <summary>
|
||||
/// Search files in SharedWithMe & Projects
|
||||
@ -272,7 +277,7 @@ namespace ASC.Files.Core
|
||||
/// <param name="searchText"></param>
|
||||
/// <param name="searchInContent"></param>
|
||||
/// <returns></returns>
|
||||
List<File> GetFiles(object[] parentIds, FilterType filterType, bool subjectGroup, Guid subjectID, string searchText, bool searchInContent);
|
||||
List<File<T>> GetFiles(T[] parentIds, FilterType filterType, bool subjectGroup, Guid subjectID, string searchText, bool searchInContent);
|
||||
|
||||
/// <summary>
|
||||
/// Search the list of files containing text
|
||||
@ -281,22 +286,22 @@ namespace ASC.Files.Core
|
||||
/// <param name="text">search text</param>
|
||||
/// <param name="bunch"></param>
|
||||
/// <returns>list of files</returns>
|
||||
IEnumerable<File> Search(string text, bool bunch = false);
|
||||
IEnumerable<File<T>> Search(string text, bool bunch = false);
|
||||
|
||||
/// <summary>
|
||||
/// Checks whether file exists on storage
|
||||
/// </summary>
|
||||
/// <param name="file">file</param>
|
||||
/// <returns></returns>
|
||||
bool IsExistOnStorage(File file);
|
||||
bool IsExistOnStorage(File<T> file);
|
||||
|
||||
void SaveEditHistory(File file, string changes, Stream differenceStream);
|
||||
void SaveEditHistory(File<T> file, string changes, Stream differenceStream);
|
||||
|
||||
List<EditHistory> GetEditHistory(DocumentServiceHelper documentServiceHelper, object fileId, int fileVersion = 0);
|
||||
List<EditHistory> GetEditHistory(DocumentServiceHelper documentServiceHelper, T fileId, int fileVersion = 0);
|
||||
|
||||
Stream GetDifferenceStream(File file);
|
||||
Stream GetDifferenceStream(File<T> file);
|
||||
|
||||
bool ContainChanges(object fileId, int fileVersion);
|
||||
bool ContainChanges(T fileId, int fileVersion);
|
||||
|
||||
#endregion
|
||||
}
|
||||
|
@ -30,14 +30,14 @@ using System.Threading;
|
||||
|
||||
namespace ASC.Files.Core
|
||||
{
|
||||
public interface IFolderDao
|
||||
public interface IFolderDao<T>
|
||||
{
|
||||
/// <summary>
|
||||
/// Get folder by id.
|
||||
/// </summary>
|
||||
/// <param name="folderId">folder id</param>
|
||||
/// <returns>folder</returns>
|
||||
Folder GetFolder(object folderId);
|
||||
Folder<T> GetFolder(T folderId);
|
||||
|
||||
/// <summary>
|
||||
/// Returns the folder with the given name and id of the root
|
||||
@ -45,27 +45,27 @@ namespace ASC.Files.Core
|
||||
/// <param name="title"></param>
|
||||
/// <param name="parentId"></param>
|
||||
/// <returns></returns>
|
||||
Folder GetFolder(string title, object parentId);
|
||||
Folder<T> GetFolder(string title, T parentId);
|
||||
|
||||
/// <summary>
|
||||
/// Gets the root folder
|
||||
/// </summary>
|
||||
/// <param name="folderId">folder id</param>
|
||||
/// <returns>root folder</returns>
|
||||
Folder GetRootFolder(object folderId);
|
||||
Folder<T> GetRootFolder(T folderId);
|
||||
|
||||
/// <summary>
|
||||
/// Gets the root folder
|
||||
/// </summary>
|
||||
/// <param name="fileId">file id</param>
|
||||
/// <returns>root folder</returns>
|
||||
Folder GetRootFolderByFile(object fileId);
|
||||
Folder<T> GetRootFolderByFile(T fileId);
|
||||
|
||||
/// <summary>
|
||||
/// Get a list of folders in current folder.
|
||||
/// </summary>
|
||||
/// <param name="parentId"></param>
|
||||
List<Folder> GetFolders(object parentId);
|
||||
List<Folder<T>> GetFolders(T parentId);
|
||||
|
||||
/// <summary>
|
||||
/// Get a list of folders.
|
||||
@ -78,7 +78,7 @@ namespace ASC.Files.Core
|
||||
/// <param name="searchText"></param>
|
||||
/// <param name="withSubfolders"></param>
|
||||
/// <returns></returns>
|
||||
List<Folder> GetFolders(object parentId, OrderBy orderBy, FilterType filterType, bool subjectGroup, Guid subjectID, string searchText, bool withSubfolders = false);
|
||||
List<Folder<T>> GetFolders(T parentId, OrderBy orderBy, FilterType filterType, bool subjectGroup, Guid subjectID, string searchText, bool withSubfolders = false);
|
||||
|
||||
/// <summary>
|
||||
/// Gets the folder (s) by ID (s)
|
||||
@ -91,27 +91,27 @@ namespace ASC.Files.Core
|
||||
/// <param name="searchSubfolders"></param>
|
||||
/// <param name="checkShare"></param>
|
||||
/// <returns></returns>
|
||||
List<Folder> GetFolders(object[] folderIds, FilterType filterType = FilterType.None, bool subjectGroup = false, Guid? subjectID = null, string searchText = "", bool searchSubfolders = false, bool checkShare = true);
|
||||
List<Folder<T>> GetFolders(T[] folderIds, FilterType filterType = FilterType.None, bool subjectGroup = false, Guid? subjectID = null, string searchText = "", bool searchSubfolders = false, bool checkShare = true);
|
||||
|
||||
/// <summary>
|
||||
/// Get folder, contains folder with id
|
||||
/// </summary>
|
||||
/// <param name="folderId">folder id</param>
|
||||
/// <returns></returns>
|
||||
List<Folder> GetParentFolders(object folderId);
|
||||
List<Folder<T>> GetParentFolders(T folderId);
|
||||
|
||||
/// <summary>
|
||||
/// save or update folder
|
||||
/// </summary>
|
||||
/// <param name="folder"></param>
|
||||
/// <returns></returns>
|
||||
object SaveFolder(Folder folder);
|
||||
T SaveFolder(Folder<T> folder);
|
||||
|
||||
/// <summary>
|
||||
/// delete folder
|
||||
/// </summary>
|
||||
/// <param name="folderId">folder id</param>
|
||||
void DeleteFolder(object folderId);
|
||||
void DeleteFolder(T folderId);
|
||||
|
||||
/// <summary>
|
||||
/// move folder
|
||||
@ -119,7 +119,10 @@ namespace ASC.Files.Core
|
||||
/// <param name="folderId">folder id</param>
|
||||
/// <param name="toFolderId">destination folder id</param>
|
||||
/// <param name="cancellationToken"></param>
|
||||
object MoveFolder(object folderId, object toFolderId, CancellationToken? cancellationToken);
|
||||
T MoveFolder(T folderId, T toFolderId, CancellationToken? cancellationToken);
|
||||
TTo MoveFolder<TTo>(T folderId, TTo toFolderId, CancellationToken? cancellationToken);
|
||||
string MoveFolder(T folderId, string toFolderId, CancellationToken? cancellationToken);
|
||||
int MoveFolder(T folderId, int toFolderId, CancellationToken? cancellationToken);
|
||||
|
||||
/// <summary>
|
||||
/// copy folder
|
||||
@ -129,7 +132,10 @@ namespace ASC.Files.Core
|
||||
/// <param name="cancellationToken"></param>
|
||||
/// <returns>
|
||||
/// </returns>
|
||||
Folder CopyFolder(object folderId, object toFolderId, CancellationToken? cancellationToken);
|
||||
Folder<T> CopyFolder(T folderId, T toFolderId, CancellationToken? cancellationToken);
|
||||
Folder<TTo> CopyFolder<TTo>(T folderId, TTo toFolderId, CancellationToken? cancellationToken);
|
||||
Folder<string> CopyFolder(T folderId, string toFolderId, CancellationToken? cancellationToken);
|
||||
Folder<int> CopyFolder(T folderId, int toFolderId, CancellationToken? cancellationToken);
|
||||
|
||||
/// <summary>
|
||||
/// Validate the transfer operation directory to another directory.
|
||||
@ -139,35 +145,38 @@ namespace ASC.Files.Core
|
||||
/// <returns>
|
||||
/// Returns pair of file ID, file name, in which the same name.
|
||||
/// </returns>
|
||||
IDictionary<object, string> CanMoveOrCopy(object[] folderIds, object to);
|
||||
IDictionary<T, string> CanMoveOrCopy(T[] folderIds, T to);
|
||||
IDictionary<T, string> CanMoveOrCopy<TTo>(T[] folderIds, TTo to);
|
||||
IDictionary<T, string> CanMoveOrCopy(T[] folderIds, string to);
|
||||
IDictionary<T, string> CanMoveOrCopy(T[] folderIds, int to);
|
||||
|
||||
/// <summary>
|
||||
/// Rename folder
|
||||
/// </summary>
|
||||
/// <param name="folder"></param>
|
||||
/// <param name="newTitle">new name</param>
|
||||
object RenameFolder(Folder folder, string newTitle);
|
||||
T RenameFolder(Folder<T> folder, string newTitle);
|
||||
|
||||
/// <summary>
|
||||
/// Gets the number of files and folders to the container in your
|
||||
/// </summary>
|
||||
/// <param name="folderId">folder id</param>
|
||||
/// <returns></returns>
|
||||
int GetItemsCount(object folderId);
|
||||
int GetItemsCount(T folderId);
|
||||
|
||||
/// <summary>
|
||||
/// Check folder on emptiness
|
||||
/// </summary>
|
||||
/// <param name="folderId">folder id</param>
|
||||
/// <returns></returns>
|
||||
bool IsEmpty(object folderId);
|
||||
bool IsEmpty(T folderId);
|
||||
|
||||
/// <summary>
|
||||
/// Check the need to use the trash before removing
|
||||
/// </summary>
|
||||
/// <param name="folder"></param>
|
||||
/// <returns></returns>
|
||||
bool UseTrashForRemove(Folder folder);
|
||||
bool UseTrashForRemove(Folder<T> folder);
|
||||
|
||||
/// <summary>
|
||||
/// Check the need to use recursion for operations
|
||||
@ -175,14 +184,17 @@ namespace ASC.Files.Core
|
||||
/// <param name="folderId"> </param>
|
||||
/// <param name="toRootFolderId"> </param>
|
||||
/// <returns></returns>
|
||||
bool UseRecursiveOperation(object folderId, object toRootFolderId);
|
||||
bool UseRecursiveOperation(T folderId, T toRootFolderId);
|
||||
bool UseRecursiveOperation<TTo>(T folderId, TTo toRootFolderId);
|
||||
bool UseRecursiveOperation(T folderId, string toRootFolderId);
|
||||
bool UseRecursiveOperation(T folderId, int toRootFolderId);
|
||||
|
||||
/// <summary>
|
||||
/// Check the possibility to calculate the number of subitems
|
||||
/// </summary>
|
||||
/// <param name="entryId"> </param>
|
||||
/// <returns></returns>
|
||||
bool CanCalculateSubitems(object entryId);
|
||||
bool CanCalculateSubitems(T entryId);
|
||||
|
||||
/// <summary>
|
||||
/// Returns maximum size of file which can be uploaded to specific folder
|
||||
@ -190,7 +202,7 @@ namespace ASC.Files.Core
|
||||
/// <param name="folderId">Id of the folder</param>
|
||||
/// <param name="chunkedUpload">Determines whenever supposed upload will be chunked (true) or not (false)</param>
|
||||
/// <returns>Maximum size of file which can be uploaded to folder</returns>
|
||||
long GetMaxUploadSize(object folderId, bool chunkedUpload = false);
|
||||
long GetMaxUploadSize(T folderId, bool chunkedUpload = false);
|
||||
|
||||
#region Only for TMFolderDao
|
||||
|
||||
@ -199,7 +211,7 @@ namespace ASC.Files.Core
|
||||
/// </summary>
|
||||
/// <param name="folderIds"></param>
|
||||
/// <param name="newOwnerId"></param>
|
||||
void ReassignFolders(object[] folderIds, Guid newOwnerId);
|
||||
void ReassignFolders(T[] folderIds, Guid newOwnerId);
|
||||
|
||||
/// <summary>
|
||||
/// Search the list of folders containing text in title
|
||||
@ -208,7 +220,7 @@ namespace ASC.Files.Core
|
||||
/// <param name="text"></param>
|
||||
/// <param name="bunch"></param>
|
||||
/// <returns></returns>
|
||||
IEnumerable<Folder> Search(string text, bool bunch = false);
|
||||
IEnumerable<Folder<T>> Search(string text, bool bunch = false);
|
||||
|
||||
/// <summary>
|
||||
/// Only in TMFolderDao
|
||||
@ -218,16 +230,16 @@ namespace ASC.Files.Core
|
||||
/// <param name="data"></param>
|
||||
/// <param name="createIfNotExists"></param>
|
||||
/// <returns></returns>
|
||||
object GetFolderID(string module, string bunch, string data, bool createIfNotExists);
|
||||
T GetFolderID(string module, string bunch, string data, bool createIfNotExists);
|
||||
|
||||
IEnumerable<object> GetFolderIDs(string module, string bunch, IEnumerable<string> data, bool createIfNotExists);
|
||||
IEnumerable<T> GetFolderIDs(string module, string bunch, IEnumerable<string> data, bool createIfNotExists);
|
||||
|
||||
/// <summary>
|
||||
/// Returns id folder "Shared Documents"
|
||||
/// Only in TMFolderDao
|
||||
/// </summary>
|
||||
/// <returns></returns>
|
||||
object GetFolderIDCommon(bool createIfNotExists);
|
||||
T GetFolderIDCommon(bool createIfNotExists);
|
||||
|
||||
/// <summary>
|
||||
/// Returns id folder "My Documents"
|
||||
@ -236,7 +248,7 @@ namespace ASC.Files.Core
|
||||
/// <param name="createIfNotExists"></param>
|
||||
/// <param name="userId"></param>
|
||||
/// <returns></returns>
|
||||
object GetFolderIDUser(bool createIfNotExists, Guid? userId = null);
|
||||
T GetFolderIDUser(bool createIfNotExists, Guid? userId = null);
|
||||
|
||||
/// <summary>
|
||||
/// Returns id folder "Shared with me"
|
||||
@ -244,7 +256,7 @@ namespace ASC.Files.Core
|
||||
/// </summary>
|
||||
/// <param name="createIfNotExists"></param>
|
||||
/// <returns></returns>
|
||||
object GetFolderIDShare(bool createIfNotExists);
|
||||
T GetFolderIDShare(bool createIfNotExists);
|
||||
|
||||
/// <summary>
|
||||
/// Returns id folder "Trash"
|
||||
@ -253,7 +265,7 @@ namespace ASC.Files.Core
|
||||
/// <param name="createIfNotExists"></param>
|
||||
/// <param name="userId"></param>
|
||||
/// <returns></returns>
|
||||
object GetFolderIDTrash(bool createIfNotExists, Guid? userId = null);
|
||||
T GetFolderIDTrash(bool createIfNotExists, Guid? userId = null);
|
||||
|
||||
/// <summary>
|
||||
/// Returns id folder "Projects"
|
||||
@ -261,7 +273,7 @@ namespace ASC.Files.Core
|
||||
/// </summary>
|
||||
/// <param name="createIfNotExists"></param>
|
||||
/// <returns></returns>
|
||||
object GetFolderIDProjects(bool createIfNotExists);
|
||||
T GetFolderIDProjects(bool createIfNotExists);
|
||||
|
||||
|
||||
/// <summary>
|
||||
@ -270,7 +282,7 @@ namespace ASC.Files.Core
|
||||
/// </summary>
|
||||
/// <param name="folderID"></param>
|
||||
/// <returns></returns>
|
||||
string GetBunchObjectID(object folderID);
|
||||
string GetBunchObjectID(T folderID);
|
||||
|
||||
/// <summary>
|
||||
/// Return ids of related objects
|
||||
@ -278,7 +290,7 @@ namespace ASC.Files.Core
|
||||
/// </summary>
|
||||
/// <param name="folderIDs"></param>
|
||||
/// <returns></returns>
|
||||
Dictionary<string, string> GetBunchObjectIDs(List<object> folderIDs);
|
||||
Dictionary<string, string> GetBunchObjectIDs(List<T> folderIDs);
|
||||
|
||||
#endregion
|
||||
}
|
||||
|
@ -28,7 +28,7 @@ using System;
|
||||
|
||||
namespace ASC.Files.Core
|
||||
{
|
||||
public interface IProviderInfo
|
||||
public interface IProviderInfo : IDisposable
|
||||
{
|
||||
int ID { get; set; }
|
||||
string ProviderKey { get; }
|
||||
@ -37,9 +37,10 @@ namespace ASC.Files.Core
|
||||
DateTime CreateOn { get; }
|
||||
string CustomerTitle { get; }
|
||||
|
||||
object RootFolderId { get; }
|
||||
string RootFolderId { get; }
|
||||
|
||||
bool CheckAccess();
|
||||
void InvalidateStorage();
|
||||
void UpdateTitle(string newtitle);
|
||||
}
|
||||
}
|
@ -29,9 +29,17 @@ using System.Collections.Generic;
|
||||
|
||||
namespace ASC.Files.Core
|
||||
{
|
||||
public interface ITagDao
|
||||
public interface ITagDao<T>
|
||||
{
|
||||
IEnumerable<Tag> GetTags(TagType tagType, IEnumerable<FileEntry> fileEntries);
|
||||
IEnumerable<Tag> GetNewTags(Guid subject, Folder<T> parentFolder, bool deepSearch);
|
||||
|
||||
IEnumerable<Tag> GetTags(T entryID, FileEntryType entryType, TagType tagType);
|
||||
|
||||
IEnumerable<Tag> GetTags(TagType tagType, IEnumerable<FileEntry<T>> fileEntries);
|
||||
|
||||
IEnumerable<Tag> GetNewTags(Guid subject, IEnumerable<FileEntry<T>> fileEntries);
|
||||
|
||||
IEnumerable<Tag> GetNewTags(Guid subject, FileEntry<T> fileEntry);
|
||||
|
||||
IEnumerable<Tag> GetTags(Guid owner, TagType tagType);
|
||||
|
||||
@ -39,12 +47,6 @@ namespace ASC.Files.Core
|
||||
|
||||
IEnumerable<Tag> GetTags(string[] names, TagType tagType);
|
||||
|
||||
IEnumerable<Tag> GetNewTags(Guid subject, Folder parentFolder, bool deepSearch);
|
||||
|
||||
IEnumerable<Tag> GetNewTags(Guid subject, IEnumerable<FileEntry> fileEntries);
|
||||
|
||||
IEnumerable<Tag> GetNewTags(Guid subject, FileEntry fileEntry);
|
||||
|
||||
IEnumerable<Tag> SaveTags(IEnumerable<Tag> tag);
|
||||
|
||||
IEnumerable<Tag> SaveTags(Tag tag);
|
||||
@ -56,7 +58,5 @@ namespace ASC.Files.Core
|
||||
void RemoveTags(IEnumerable<Tag> tag);
|
||||
|
||||
void RemoveTags(Tag tag);
|
||||
|
||||
IEnumerable<Tag> GetTags(object entryID, FileEntryType entryType, TagType tagType);
|
||||
}
|
||||
}
|
@ -169,6 +169,10 @@ namespace ASC.Files.Core.Data
|
||||
return result;
|
||||
}
|
||||
|
||||
protected int MappingID(int id)
|
||||
{
|
||||
return id;
|
||||
}
|
||||
protected object MappingID(object id)
|
||||
{
|
||||
return MappingID(id, false);
|
||||
|
@ -24,25 +24,45 @@
|
||||
*/
|
||||
|
||||
|
||||
using System;
|
||||
|
||||
using ASC.Common;
|
||||
using ASC.Files.Core.Security;
|
||||
using ASC.Files.Thirdparty;
|
||||
using ASC.Files.Thirdparty.ProviderDao;
|
||||
|
||||
using Microsoft.Extensions.DependencyInjection;
|
||||
|
||||
namespace ASC.Files.Core.Data
|
||||
{
|
||||
public class DaoFactory : IDaoFactory
|
||||
{
|
||||
public IFileDao FileDao { get; }
|
||||
public IFolderDao FolderDao { get; }
|
||||
public ITagDao TagDao { get; }
|
||||
public ISecurityDao SecurityDao { get; }
|
||||
public IServiceProvider ServiceProvider { get; }
|
||||
public IProviderDao ProviderDao { get; }
|
||||
|
||||
public DaoFactory(IFileDao fileDao, IFolderDao folderDao, ITagDao tagDao, ISecurityDao securityDao)
|
||||
public DaoFactory(IServiceProvider serviceProvider, IProviderDao providerDao)
|
||||
{
|
||||
FileDao = fileDao;
|
||||
FolderDao = folderDao;
|
||||
TagDao = tagDao;
|
||||
SecurityDao = securityDao;
|
||||
ServiceProvider = serviceProvider;
|
||||
ProviderDao = providerDao;
|
||||
}
|
||||
|
||||
public IFileDao<T> GetFileDao<T>()
|
||||
{
|
||||
return ServiceProvider.GetService<IFileDao<T>>();
|
||||
}
|
||||
|
||||
public IFolderDao<T> GetFolderDao<T>()
|
||||
{
|
||||
return ServiceProvider.GetService<IFolderDao<T>>();
|
||||
}
|
||||
public ITagDao<T> GetTagDao<T>()
|
||||
{
|
||||
return ServiceProvider.GetService<ITagDao<T>>();
|
||||
}
|
||||
|
||||
public ISecurityDao<T> GetSecurityDao<T>()
|
||||
{
|
||||
return ServiceProvider.GetService<ISecurityDao<T>>();
|
||||
}
|
||||
}
|
||||
|
||||
@ -56,6 +76,11 @@ namespace ASC.Files.Core.Data
|
||||
.AddFolderDaoService()
|
||||
.AddTagDaoService()
|
||||
.AddSecurityDaoService()
|
||||
.AddCachedProviderAccountDaoService()
|
||||
.AddProviderTagDaoService()
|
||||
.AddProviderSecurityDaoService()
|
||||
.AddProviderFileDaoService()
|
||||
.AddProviderFolderDaoService()
|
||||
;
|
||||
}
|
||||
}
|
||||
|
@ -37,7 +37,9 @@ using ASC.Core.Common.Settings;
|
||||
using ASC.Core.Tenants;
|
||||
using ASC.ElasticSearch;
|
||||
using ASC.Files.Core.EF;
|
||||
using ASC.Files.Core.Thirdparty;
|
||||
using ASC.Files.Resources;
|
||||
using ASC.Files.Thirdparty.ProviderDao;
|
||||
using ASC.Web.Core.Files;
|
||||
using ASC.Web.Files.Classes;
|
||||
using ASC.Web.Files.Core.Search;
|
||||
@ -51,15 +53,17 @@ using Microsoft.Extensions.DependencyInjection;
|
||||
|
||||
namespace ASC.Files.Core.Data
|
||||
{
|
||||
public class FileDao : AbstractDao, IFileDao
|
||||
internal class FileDao : AbstractDao, IFileDao<int>
|
||||
{
|
||||
private static readonly object syncRoot = new object();
|
||||
public FactoryIndexer<FilesWrapper> FactoryIndexer { get; }
|
||||
public GlobalStore GlobalStore { get; }
|
||||
public GlobalSpace GlobalSpace { get; }
|
||||
public GlobalFolder GlobalFolder { get; }
|
||||
public IFolderDao FolderDao { get; }
|
||||
public IDaoFactory DaoFactory { get; }
|
||||
public ChunkedUploadSessionHolder ChunkedUploadSessionHolder { get; }
|
||||
public ProviderFolderDao ProviderFolderDao { get; }
|
||||
public CrossDao CrossDao { get; }
|
||||
|
||||
public FileDao(
|
||||
FactoryIndexer<FilesWrapper> factoryIndexer,
|
||||
@ -78,8 +82,10 @@ namespace ASC.Files.Core.Data
|
||||
GlobalStore globalStore,
|
||||
GlobalSpace globalSpace,
|
||||
GlobalFolder globalFolder,
|
||||
IFolderDao folderDao,
|
||||
ChunkedUploadSessionHolder chunkedUploadSessionHolder)
|
||||
IDaoFactory daoFactory,
|
||||
ChunkedUploadSessionHolder chunkedUploadSessionHolder,
|
||||
ProviderFolderDao providerFolderDao,
|
||||
CrossDao crossDao)
|
||||
: base(
|
||||
dbContextManager,
|
||||
userManager,
|
||||
@ -98,43 +104,41 @@ namespace ASC.Files.Core.Data
|
||||
GlobalStore = globalStore;
|
||||
GlobalSpace = globalSpace;
|
||||
GlobalFolder = globalFolder;
|
||||
FolderDao = folderDao;
|
||||
DaoFactory = daoFactory;
|
||||
ChunkedUploadSessionHolder = chunkedUploadSessionHolder;
|
||||
ProviderFolderDao = providerFolderDao;
|
||||
CrossDao = crossDao;
|
||||
}
|
||||
|
||||
public void InvalidateCache(object fileId)
|
||||
public void InvalidateCache(int fileId)
|
||||
{
|
||||
}
|
||||
|
||||
public File GetFile(object fileId)
|
||||
public File<int> GetFile(int fileId)
|
||||
{
|
||||
var fileIdString = fileId.ToString();
|
||||
var query = GetFileQuery(r => r.Id.ToString() == fileIdString && r.CurrentVersion);
|
||||
var query = GetFileQuery(r => r.Id == fileId && r.CurrentVersion);
|
||||
return FromQueryWithShared(query).SingleOrDefault();
|
||||
}
|
||||
|
||||
public File GetFile(object fileId, int fileVersion)
|
||||
public File<int> GetFile(int fileId, int fileVersion)
|
||||
{
|
||||
var fileIdString = fileId.ToString();
|
||||
var query = GetFileQuery(r => r.Id.ToString() == fileIdString && r.Version == fileVersion);
|
||||
var query = GetFileQuery(r => r.Id == fileId && r.Version == fileVersion);
|
||||
return FromQueryWithShared(query).SingleOrDefault();
|
||||
}
|
||||
|
||||
public File GetFile(object parentId, string title)
|
||||
public File<int> GetFile(int parentId, string title)
|
||||
{
|
||||
if (string.IsNullOrEmpty(title)) throw new ArgumentNullException(title);
|
||||
|
||||
var parentIdString = parentId.ToString();
|
||||
var query = GetFileQuery(r => r.Title == title && r.CurrentVersion == true && r.FolderId.ToString() == parentIdString)
|
||||
var query = GetFileQuery(r => r.Title == title && r.CurrentVersion == true && r.FolderId == parentId)
|
||||
.OrderBy(r => r.CreateOn);
|
||||
|
||||
return FromQueryWithShared(query).FirstOrDefault();
|
||||
}
|
||||
|
||||
public File GetFileStable(object fileId, int fileVersion = -1)
|
||||
public File<int> GetFileStable(int fileId, int fileVersion = -1)
|
||||
{
|
||||
var fileIdString = fileId.ToString();
|
||||
var query = GetFileQuery(r => r.Id.ToString() == fileIdString && r.Forcesave == ForcesaveType.None);
|
||||
var query = GetFileQuery(r => r.Id == fileId && r.Forcesave == ForcesaveType.None);
|
||||
|
||||
if (fileVersion >= 0)
|
||||
{
|
||||
@ -146,30 +150,27 @@ namespace ASC.Files.Core.Data
|
||||
return FromQueryWithShared(query).SingleOrDefault();
|
||||
}
|
||||
|
||||
public List<File> GetFileHistory(object fileId)
|
||||
public List<File<int>> GetFileHistory(int fileId)
|
||||
{
|
||||
var fileIdString = fileId.ToString();
|
||||
var query = GetFileQuery(r => r.Id.ToString() == fileIdString).OrderByDescending(r => r.Version);
|
||||
var query = GetFileQuery(r => r.Id == fileId).OrderByDescending(r => r.Version);
|
||||
|
||||
return FromQueryWithShared(query);
|
||||
}
|
||||
|
||||
public List<File> GetFiles(object[] fileIds)
|
||||
public List<File<int>> GetFiles(int[] fileIds)
|
||||
{
|
||||
if (fileIds == null || fileIds.Length == 0) return new List<File>();
|
||||
if (fileIds == null || fileIds.Length == 0) return new List<File<int>>();
|
||||
|
||||
var fileIdsString = fileIds.Select(r => r.ToString()).ToList();
|
||||
var query = GetFileQuery(r => fileIdsString.Any(a => a == r.Id.ToString()) && r.CurrentVersion);
|
||||
var query = GetFileQuery(r => fileIds.Any(a => a == r.Id) && r.CurrentVersion);
|
||||
|
||||
return FromQueryWithShared(query);
|
||||
}
|
||||
|
||||
public List<File> GetFilesForShare(object[] fileIds, FilterType filterType, bool subjectGroup, Guid subjectID, string searchText, bool searchInContent)
|
||||
public List<File<int>> GetFilesForShare(int[] fileIds, FilterType filterType, bool subjectGroup, Guid subjectID, string searchText, bool searchInContent)
|
||||
{
|
||||
if (fileIds == null || fileIds.Length == 0 || filterType == FilterType.FoldersOnly) return new List<File>();
|
||||
if (fileIds == null || fileIds.Length == 0 || filterType == FilterType.FoldersOnly) return new List<File<int>>();
|
||||
|
||||
var fileIdsStrings = fileIds.Select(r => r.ToString()).ToList();
|
||||
var query = GetFileQuery(r => fileIdsStrings.Any(a => a == r.Id.ToString()) && r.CurrentVersion);
|
||||
var query = GetFileQuery(r => fileIds.Any(a => a == r.Id) && r.CurrentVersion);
|
||||
|
||||
if (!string.IsNullOrEmpty(searchText))
|
||||
{
|
||||
@ -219,33 +220,31 @@ namespace ASC.Files.Core.Data
|
||||
return FromQuery(query);
|
||||
}
|
||||
|
||||
public List<object> GetFiles(object parentId)
|
||||
|
||||
public List<int> GetFiles(int parentId)
|
||||
{
|
||||
var parentIdString = parentId.ToString();
|
||||
var query = GetFileQuery(r => r.FolderId.ToString() == parentIdString && r.CurrentVersion).Select(r => r.Id);
|
||||
var query = GetFileQuery(r => r.FolderId == parentId && r.CurrentVersion).Select(r => r.Id);
|
||||
|
||||
return Query(FilesDbContext.Files)
|
||||
.Where(r => r.FolderId.ToString() == parentIdString && r.CurrentVersion)
|
||||
.Where(r => r.FolderId == parentId && r.CurrentVersion)
|
||||
.Select(r => r.Id)
|
||||
.ToList()
|
||||
.ConvertAll(r => (object)r);
|
||||
.ToList();
|
||||
}
|
||||
|
||||
public List<File> GetFiles(object parentId, OrderBy orderBy, FilterType filterType, bool subjectGroup, Guid subjectID, string searchText, bool searchInContent, bool withSubfolders = false)
|
||||
public List<File<int>> GetFiles(int parentId, OrderBy orderBy, FilterType filterType, bool subjectGroup, Guid subjectID, string searchText, bool searchInContent, bool withSubfolders = false)
|
||||
{
|
||||
if (filterType == FilterType.FoldersOnly) return new List<File>();
|
||||
if (filterType == FilterType.FoldersOnly) return new List<File<int>>();
|
||||
|
||||
if (orderBy == null) orderBy = new OrderBy(SortedByType.DateAndTime, false);
|
||||
|
||||
var parentIdString = parentId.ToString();
|
||||
var q = GetFileQuery(r => r.FolderId.ToString() == parentIdString && r.CurrentVersion);
|
||||
var q = GetFileQuery(r => r.FolderId == parentId && r.CurrentVersion);
|
||||
|
||||
|
||||
if (withSubfolders)
|
||||
{
|
||||
q = GetFileQuery(r => r.CurrentVersion)
|
||||
.Join(FilesDbContext.Tree, r => r.FolderId, a => a.FolderId, (file, tree) => new { file, tree })
|
||||
.Where(r => r.tree.ParentId.ToString() == parentIdString)
|
||||
.Where(r => r.tree.ParentId == parentId)
|
||||
.Select(r => r.file);
|
||||
}
|
||||
|
||||
@ -321,12 +320,12 @@ namespace ASC.Files.Core.Data
|
||||
return FromQueryWithShared(q);
|
||||
}
|
||||
|
||||
public Stream GetFileStream(File file, long offset)
|
||||
public Stream GetFileStream(File<int> file, long offset)
|
||||
{
|
||||
return GlobalStore.GetStore().GetReadStream(string.Empty, GetUniqFilePath(file), (int)offset);
|
||||
}
|
||||
|
||||
public Uri GetPreSignedUri(File file, TimeSpan expires)
|
||||
public Uri GetPreSignedUri(File<int> file, TimeSpan expires)
|
||||
{
|
||||
return GlobalStore.GetStore().GetPreSignedUri(string.Empty, GetUniqFilePath(file), expires,
|
||||
new List<string>
|
||||
@ -335,17 +334,17 @@ namespace ASC.Files.Core.Data
|
||||
});
|
||||
}
|
||||
|
||||
public bool IsSupportedPreSignedUri(File file)
|
||||
public bool IsSupportedPreSignedUri(File<int> file)
|
||||
{
|
||||
return GlobalStore.GetStore().IsSupportedPreSignedUri;
|
||||
}
|
||||
|
||||
public Stream GetFileStream(File file)
|
||||
public Stream GetFileStream(File<int> file)
|
||||
{
|
||||
return GetFileStream(file, 0);
|
||||
}
|
||||
|
||||
public File SaveFile(File file, Stream fileStream)
|
||||
public File<int> SaveFile(File<int> file, Stream fileStream)
|
||||
{
|
||||
if (file == null)
|
||||
{
|
||||
@ -361,7 +360,7 @@ namespace ASC.Files.Core.Data
|
||||
if (CoreBaseSettings.Personal && SetupInfo.IsVisibleSettings("PersonalMaxSpace"))
|
||||
{
|
||||
var personalMaxSpace = CoreConfiguration.PersonalMaxSpace(SettingsManager);
|
||||
if (personalMaxSpace - GlobalSpace.GetUserUsedSpace(file.ID == null ? AuthContext.CurrentAccount.ID : file.CreateBy) < file.ContentLength)
|
||||
if (personalMaxSpace - GlobalSpace.GetUserUsedSpace(file.ID == default ? AuthContext.CurrentAccount.ID : file.CreateBy) < file.ContentLength)
|
||||
{
|
||||
throw FileSizeComment.GetPersonalFreeSpaceException(personalMaxSpace);
|
||||
}
|
||||
@ -373,7 +372,7 @@ namespace ASC.Files.Core.Data
|
||||
{
|
||||
using var tx = FilesDbContext.Database.BeginTransaction();
|
||||
|
||||
if (file.ID == null)
|
||||
if (file.ID == default)
|
||||
{
|
||||
file.ID = FilesDbContext.Files.Max(r => r.Id) + 1;
|
||||
file.Version = 1;
|
||||
@ -392,7 +391,7 @@ namespace ASC.Files.Core.Data
|
||||
|
||||
var fileIdString = file.ID.ToString();
|
||||
var toUpdate = FilesDbContext.Files
|
||||
.Where(r => r.Id.ToString() == fileIdString && r.CurrentVersion && r.TenantId == TenantID)
|
||||
.Where(r => r.Id == file.ID && r.CurrentVersion && r.TenantId == TenantID)
|
||||
.FirstOrDefault();
|
||||
|
||||
if (toUpdate != null)
|
||||
@ -403,11 +402,11 @@ namespace ASC.Files.Core.Data
|
||||
|
||||
var toInsert = new DbFile
|
||||
{
|
||||
Id = (int)file.ID,
|
||||
Id = file.ID,
|
||||
Version = file.Version,
|
||||
VersionGroup = file.VersionGroup,
|
||||
CurrentVersion = true,
|
||||
FolderId = (int)file.FolderID,
|
||||
FolderId = file.FolderID,
|
||||
Title = file.Title,
|
||||
ContentLength = file.ContentLength,
|
||||
Category = (int)file.FilterType,
|
||||
@ -431,7 +430,7 @@ namespace ASC.Files.Core.Data
|
||||
|
||||
parentFoldersIds =
|
||||
FilesDbContext.Tree
|
||||
.Where(r => r.FolderId == (int)file.FolderID)
|
||||
.Where(r => r.FolderId == file.FolderID)
|
||||
.OrderByDescending(r => r.Level)
|
||||
.Select(r => r.ParentId)
|
||||
.ToList();
|
||||
@ -482,10 +481,10 @@ namespace ASC.Files.Core.Data
|
||||
return GetFile(file.ID);
|
||||
}
|
||||
|
||||
public File ReplaceFileVersion(File file, Stream fileStream)
|
||||
public File<int> ReplaceFileVersion(File<int> file, Stream fileStream)
|
||||
{
|
||||
if (file == null) throw new ArgumentNullException("file");
|
||||
if (file.ID == null) throw new ArgumentException("No file id or folder id toFolderId determine provider");
|
||||
if (file.ID == default) throw new ArgumentException("No file id or folder id toFolderId determine provider");
|
||||
|
||||
var maxChunkedUploadSize = SetupInfo.MaxChunkedUploadSize(TenantExtra, TenantStatisticProvider);
|
||||
|
||||
@ -497,7 +496,7 @@ namespace ASC.Files.Core.Data
|
||||
if (CoreBaseSettings.Personal && SetupInfo.IsVisibleSettings("PersonalMaxSpace"))
|
||||
{
|
||||
var personalMaxSpace = CoreConfiguration.PersonalMaxSpace(SettingsManager);
|
||||
if (personalMaxSpace - GlobalSpace.GetUserUsedSpace(file.ID == null ? AuthContext.CurrentAccount.ID : file.CreateBy) < file.ContentLength)
|
||||
if (personalMaxSpace - GlobalSpace.GetUserUsedSpace(file.ID == default ? AuthContext.CurrentAccount.ID : file.CreateBy) < file.ContentLength)
|
||||
{
|
||||
throw FileSizeComment.GetPersonalFreeSpaceException(personalMaxSpace);
|
||||
}
|
||||
@ -518,12 +517,12 @@ namespace ASC.Files.Core.Data
|
||||
if (file.CreateOn == default) file.CreateOn = TenantUtil.DateTimeNow();
|
||||
|
||||
var toUpdate = FilesDbContext.Files
|
||||
.Where(r => r.Id.ToString() == file.ID.ToString() && r.Version == file.Version)
|
||||
.Where(r => r.Id == file.ID && r.Version == file.Version)
|
||||
.FirstOrDefault();
|
||||
|
||||
toUpdate.Version = file.Version;
|
||||
toUpdate.VersionGroup = file.VersionGroup;
|
||||
toUpdate.FolderId = (int)file.FolderID;
|
||||
toUpdate.FolderId = file.FolderID;
|
||||
toUpdate.Title = file.Title;
|
||||
toUpdate.ContentLength = file.ContentLength;
|
||||
toUpdate.Category = (int)file.FilterType;
|
||||
@ -543,7 +542,7 @@ namespace ASC.Files.Core.Data
|
||||
file.PureTitle = file.Title;
|
||||
|
||||
parentFoldersIds = FilesDbContext.Tree
|
||||
.Where(r => r.FolderId == (int)file.FolderID)
|
||||
.Where(r => r.FolderId == file.FolderID)
|
||||
.OrderByDescending(r => r.Level)
|
||||
.Select(r => r.ParentId)
|
||||
.ToList();
|
||||
@ -585,14 +584,14 @@ namespace ASC.Files.Core.Data
|
||||
return GetFile(file.ID);
|
||||
}
|
||||
|
||||
private void DeleteVersion(File file)
|
||||
private void DeleteVersion(File<int> file)
|
||||
{
|
||||
if (file == null
|
||||
|| file.ID == null
|
||||
|| file.ID == default
|
||||
|| file.Version <= 1) return;
|
||||
|
||||
var toDelete = Query(FilesDbContext.Files)
|
||||
.Where(r => r.Id == (int)file.ID)
|
||||
.Where(r => r.Id == file.ID)
|
||||
.Where(r => r.Version == file.Version)
|
||||
.FirstOrDefault();
|
||||
|
||||
@ -603,7 +602,7 @@ namespace ASC.Files.Core.Data
|
||||
FilesDbContext.SaveChanges();
|
||||
|
||||
var toUpdate = Query(FilesDbContext.Files)
|
||||
.Where(r => r.Id == (int)file.ID)
|
||||
.Where(r => r.Id == file.ID)
|
||||
.Where(r => r.Version == file.Version - 1)
|
||||
.FirstOrDefault();
|
||||
|
||||
@ -611,29 +610,29 @@ namespace ASC.Files.Core.Data
|
||||
FilesDbContext.SaveChanges();
|
||||
}
|
||||
|
||||
private void DeleteVersionStream(File file)
|
||||
private void DeleteVersionStream(File<int> file)
|
||||
{
|
||||
GlobalStore.GetStore().DeleteDirectory(GetUniqFileVersionPath(file.ID, file.Version));
|
||||
}
|
||||
|
||||
private void SaveFileStream(File file, Stream stream)
|
||||
private void SaveFileStream(File<int> file, Stream stream)
|
||||
{
|
||||
GlobalStore.GetStore().Save(string.Empty, GetUniqFilePath(file), stream, file.Title);
|
||||
}
|
||||
|
||||
public void DeleteFile(object fileId)
|
||||
public void DeleteFile(int fileId)
|
||||
{
|
||||
DeleteFile(fileId, true);
|
||||
}
|
||||
|
||||
private void DeleteFile(object fileId, bool deleteFolder)
|
||||
private void DeleteFile(int fileId, bool deleteFolder)
|
||||
{
|
||||
if (fileId == null) return;
|
||||
if (fileId == default) return;
|
||||
using var tx = FilesDbContext.Database.BeginTransaction();
|
||||
|
||||
var fromFolders = Query(FilesDbContext.Files).Where(r => r.Id == (int)fileId).GroupBy(r => r.Id).SelectMany(r => r.Select(a => a.FolderId)).Distinct().ToList();
|
||||
var fromFolders = Query(FilesDbContext.Files).Where(r => r.Id == fileId).GroupBy(r => r.Id).SelectMany(r => r.Select(a => a.FolderId)).Distinct().ToList();
|
||||
|
||||
var toDeleteFiles = Query(FilesDbContext.Files).Where(r => r.Id == (int)fileId);
|
||||
var toDeleteFiles = Query(FilesDbContext.Files).Where(r => r.Id == fileId);
|
||||
FilesDbContext.RemoveRange(toDeleteFiles);
|
||||
|
||||
var toDeleteLinks = Query(FilesDbContext.TagLink).Where(r => r.EntryId == fileId.ToString()).Where(r => r.EntryType == FileEntryType.File);
|
||||
@ -659,42 +658,60 @@ namespace ASC.Files.Core.Data
|
||||
DeleteFolder(fileId);
|
||||
|
||||
var wrapper = ServiceProvider.GetService<FilesWrapper>();
|
||||
wrapper.Id = (int)fileId;
|
||||
wrapper.Id = fileId;
|
||||
FactoryIndexer.DeleteAsync(wrapper);
|
||||
}
|
||||
|
||||
public bool IsExist(string title, object folderId)
|
||||
{
|
||||
var folderIdString = folderId.ToString();
|
||||
throw new NotImplementedException();
|
||||
}
|
||||
|
||||
public bool IsExist(string title, int folderId)
|
||||
{
|
||||
return Query(FilesDbContext.Files)
|
||||
.Where(r => r.Title == title)
|
||||
.Where(r => r.FolderId.ToString() == folderIdString)
|
||||
.Where(r => r.FolderId == folderId)
|
||||
.Where(r => r.CurrentVersion)
|
||||
.Any();
|
||||
}
|
||||
|
||||
public object MoveFile(object fileId, object toFolderId)
|
||||
public TTo MoveFile<TTo>(int fileId, TTo toFolderId)
|
||||
{
|
||||
if (fileId == null) return null;
|
||||
if (toFolderId is int tId)
|
||||
{
|
||||
return (TTo)Convert.ChangeType(MoveFile(fileId, tId), typeof(TTo));
|
||||
}
|
||||
|
||||
if (toFolderId is string tsId)
|
||||
{
|
||||
return (TTo)Convert.ChangeType(MoveFile(fileId, tsId), typeof(TTo));
|
||||
}
|
||||
|
||||
throw new NotImplementedException();
|
||||
}
|
||||
|
||||
public int MoveFile(int fileId, int toFolderId)
|
||||
{
|
||||
if (fileId == default) return default;
|
||||
|
||||
var fileIdString = fileId.ToString();
|
||||
using (var tx = FilesDbContext.Database.BeginTransaction())
|
||||
{
|
||||
var fromFolders = Query(FilesDbContext.Files)
|
||||
.Where(r => r.Id.ToString() == fileIdString)
|
||||
.Select(r => r.FolderId)
|
||||
.Where(r => r.Id == fileId)
|
||||
.Select(a => a.FolderId)
|
||||
.Distinct()
|
||||
.ToList();
|
||||
|
||||
var toUpdate = Query(FilesDbContext.Files)
|
||||
.Where(r => r.Id.ToString() == fileIdString)
|
||||
.Where(r => r.Id == fileId)
|
||||
.ToList();
|
||||
|
||||
foreach (var f in toUpdate)
|
||||
{
|
||||
f.FolderId = (int)toFolderId;
|
||||
f.FolderId = toFolderId;
|
||||
|
||||
if (GlobalFolder.GetFolderTrash(FolderDao).Equals(toFolderId))
|
||||
if (GlobalFolder.GetFolderTrash<int>(DaoFactory).Equals(toFolderId))
|
||||
{
|
||||
f.ModifiedBy = AuthContext.CurrentAccount.ID;
|
||||
f.ModifiedOn = DateTime.UtcNow;
|
||||
@ -708,16 +725,15 @@ namespace ASC.Files.Core.Data
|
||||
RecalculateFilesCount(toFolderId);
|
||||
}
|
||||
|
||||
var toFolderIdString = toFolderId.ToString();
|
||||
var parentFoldersIds =
|
||||
FilesDbContext.Tree
|
||||
.Where(r => r.FolderId.ToString() == toFolderIdString)
|
||||
.Where(r => r.FolderId == toFolderId)
|
||||
.OrderByDescending(r => r.Level)
|
||||
.Select(r => r.ParentId)
|
||||
.ToList();
|
||||
|
||||
var wrapper = ServiceProvider.GetService<FilesWrapper>();
|
||||
wrapper.Id = (int)fileId;
|
||||
wrapper.Id = fileId;
|
||||
wrapper.Folders = parentFoldersIds.Select(r => new FilesFoldersWrapper() { FolderId = r.ToString() }).ToList();
|
||||
|
||||
FactoryIndexer.Update(wrapper,
|
||||
@ -727,12 +743,39 @@ namespace ASC.Files.Core.Data
|
||||
return fileId;
|
||||
}
|
||||
|
||||
public File CopyFile(object fileId, object toFolderId)
|
||||
public string MoveFile(int fileId, string toFolderId)
|
||||
{
|
||||
var toSelector = ProviderFolderDao.GetSelector(toFolderId);
|
||||
|
||||
var moved = CrossDao.PerformCrossDaoFileCopy(
|
||||
fileId, this, r => r,
|
||||
toFolderId, toSelector.GetFileDao(toFolderId), toSelector.ConvertId,
|
||||
true);
|
||||
|
||||
return moved.ID;
|
||||
}
|
||||
|
||||
public File<TTo> CopyFile<TTo>(int fileId, TTo toFolderId)
|
||||
{
|
||||
if (toFolderId is int tId)
|
||||
{
|
||||
return CopyFile(fileId, tId) as File<TTo>;
|
||||
}
|
||||
|
||||
if (toFolderId is string tsId)
|
||||
{
|
||||
return CopyFile(fileId, tsId) as File<TTo>;
|
||||
}
|
||||
|
||||
throw new NotImplementedException();
|
||||
}
|
||||
|
||||
public File<int> CopyFile(int fileId, int toFolderId)
|
||||
{
|
||||
var file = GetFile(fileId);
|
||||
if (file != null)
|
||||
{
|
||||
var copy = ServiceProvider.GetService<File>();
|
||||
var copy = ServiceProvider.GetService<File<int>>();
|
||||
copy.FileStatus = file.FileStatus;
|
||||
copy.FolderID = toFolderId;
|
||||
copy.Title = file.Title;
|
||||
@ -751,12 +794,24 @@ namespace ASC.Files.Core.Data
|
||||
return null;
|
||||
}
|
||||
|
||||
public object FileRename(File file, string newTitle)
|
||||
public File<string> CopyFile(int fileId, string toFolderId)
|
||||
{
|
||||
var toSelector = ProviderFolderDao.GetSelector(toFolderId);
|
||||
|
||||
var moved = CrossDao.PerformCrossDaoFileCopy(
|
||||
fileId, this, r => r,
|
||||
toFolderId, toSelector.GetFileDao(toFolderId), toSelector.ConvertId,
|
||||
false);
|
||||
|
||||
return moved;
|
||||
}
|
||||
|
||||
public int FileRename(File<int> file, string newTitle)
|
||||
{
|
||||
var fileIdString = file.ID.ToString();
|
||||
newTitle = Global.ReplaceInvalidCharsAndTruncate(newTitle);
|
||||
var toUpdate = Query(FilesDbContext.Files)
|
||||
.Where(r => r.Id.ToString() == fileIdString)
|
||||
.Where(r => r.Id == file.ID)
|
||||
.Where(r => r.CurrentVersion)
|
||||
.FirstOrDefault();
|
||||
|
||||
@ -769,13 +824,13 @@ namespace ASC.Files.Core.Data
|
||||
return file.ID;
|
||||
}
|
||||
|
||||
public string UpdateComment(object fileId, int fileVersion, string comment)
|
||||
public string UpdateComment(int fileId, int fileVersion, string comment)
|
||||
{
|
||||
comment ??= string.Empty;
|
||||
comment = comment.Substring(0, Math.Min(comment.Length, 255));
|
||||
|
||||
var toUpdate = Query(FilesDbContext.Files)
|
||||
.Where(r => r.Id == (int)fileId)
|
||||
.Where(r => r.Id == fileId)
|
||||
.Where(r => r.Version == fileVersion)
|
||||
.FirstOrDefault();
|
||||
|
||||
@ -786,10 +841,10 @@ namespace ASC.Files.Core.Data
|
||||
return comment;
|
||||
}
|
||||
|
||||
public void CompleteVersion(object fileId, int fileVersion)
|
||||
public void CompleteVersion(int fileId, int fileVersion)
|
||||
{
|
||||
var toUpdate = Query(FilesDbContext.Files)
|
||||
.Where(r => r.Id == (int)fileId)
|
||||
.Where(r => r.Id == fileId)
|
||||
.Where(r => r.Version >= fileVersion);
|
||||
|
||||
foreach (var f in toUpdate)
|
||||
@ -800,18 +855,18 @@ namespace ASC.Files.Core.Data
|
||||
FilesDbContext.SaveChanges();
|
||||
}
|
||||
|
||||
public void ContinueVersion(object fileId, int fileVersion)
|
||||
public void ContinueVersion(int fileId, int fileVersion)
|
||||
{
|
||||
using var tx = FilesDbContext.Database.BeginTransaction();
|
||||
|
||||
var versionGroup = Query(FilesDbContext.Files)
|
||||
.Where(r => r.Id == (int)fileId)
|
||||
.Where(r => r.Id == fileId)
|
||||
.Where(r => r.Version == fileVersion)
|
||||
.Select(r => r.VersionGroup)
|
||||
.FirstOrDefault();
|
||||
|
||||
var toUpdate = Query(FilesDbContext.Files)
|
||||
.Where(r => r.Id == (int)fileId)
|
||||
.Where(r => r.Id == fileId)
|
||||
.Where(r => r.Version >= fileVersion)
|
||||
.Where(r => r.VersionGroup >= versionGroup);
|
||||
|
||||
@ -825,36 +880,35 @@ namespace ASC.Files.Core.Data
|
||||
tx.Commit();
|
||||
}
|
||||
|
||||
public bool UseTrashForRemove(File file)
|
||||
public bool UseTrashForRemove(File<int> file)
|
||||
{
|
||||
return file.RootFolderType != FolderType.TRASH;
|
||||
}
|
||||
|
||||
public static string GetUniqFileDirectory(object fileIdObject)
|
||||
public string GetUniqFileDirectory(int fileId)
|
||||
{
|
||||
if (fileIdObject == null) throw new ArgumentNullException("fileIdObject");
|
||||
var fileIdInt = Convert.ToInt32(Convert.ToString(fileIdObject));
|
||||
return string.Format("folder_{0}/file_{1}", (fileIdInt / 1000 + 1) * 1000, fileIdInt);
|
||||
if (fileId == 0) throw new ArgumentNullException("fileIdObject");
|
||||
return string.Format("folder_{0}/file_{1}", (Convert.ToInt32(fileId) / 1000 + 1) * 1000, fileId);
|
||||
}
|
||||
|
||||
public static string GetUniqFilePath(File file)
|
||||
public string GetUniqFilePath(File<int> file)
|
||||
{
|
||||
return file != null
|
||||
? GetUniqFilePath(file, "content" + FileUtility.GetFileExtension(file.PureTitle))
|
||||
: null;
|
||||
}
|
||||
|
||||
public static string GetUniqFilePath(File file, string fileTitle)
|
||||
public string GetUniqFilePath(File<int> file, string fileTitle)
|
||||
{
|
||||
return file != null
|
||||
? string.Format("{0}/{1}", GetUniqFileVersionPath(file.ID, file.Version), fileTitle)
|
||||
: null;
|
||||
}
|
||||
|
||||
public static string GetUniqFileVersionPath(object fileIdObject, int version)
|
||||
public string GetUniqFileVersionPath(int fileId, int version)
|
||||
{
|
||||
return fileIdObject != null
|
||||
? string.Format("{0}/v{1}", GetUniqFileDirectory(fileIdObject), version)
|
||||
return fileId != 0
|
||||
? string.Format("{0}/v{1}", GetUniqFileDirectory(fileId), version)
|
||||
: null;
|
||||
}
|
||||
|
||||
@ -865,12 +919,12 @@ namespace ASC.Files.Core.Data
|
||||
|
||||
#region chunking
|
||||
|
||||
public ChunkedUploadSession CreateUploadSession(File file, long contentLength)
|
||||
public ChunkedUploadSession<int> CreateUploadSession(File<int> file, long contentLength)
|
||||
{
|
||||
return ChunkedUploadSessionHolder.CreateUploadSession(file, contentLength);
|
||||
}
|
||||
|
||||
public void UploadChunk(ChunkedUploadSession uploadSession, Stream stream, long chunkLength)
|
||||
public void UploadChunk(ChunkedUploadSession<int> uploadSession, Stream stream, long chunkLength)
|
||||
{
|
||||
if (!uploadSession.UseChunks)
|
||||
{
|
||||
@ -893,7 +947,7 @@ namespace ASC.Files.Core.Data
|
||||
}
|
||||
}
|
||||
|
||||
private File FinalizeUploadSession(ChunkedUploadSession uploadSession)
|
||||
private File<int> FinalizeUploadSession(ChunkedUploadSession<int> uploadSession)
|
||||
{
|
||||
ChunkedUploadSessionHolder.FinalizeUploadSession(uploadSession);
|
||||
|
||||
@ -904,14 +958,14 @@ namespace ASC.Files.Core.Data
|
||||
return file;
|
||||
}
|
||||
|
||||
public void AbortUploadSession(ChunkedUploadSession uploadSession)
|
||||
public void AbortUploadSession(ChunkedUploadSession<int> uploadSession)
|
||||
{
|
||||
ChunkedUploadSessionHolder.AbortUploadSession(uploadSession);
|
||||
}
|
||||
|
||||
private File GetFileForCommit(ChunkedUploadSession uploadSession)
|
||||
private File<int> GetFileForCommit(ChunkedUploadSession<int> uploadSession)
|
||||
{
|
||||
if (uploadSession.File.ID != null)
|
||||
if (uploadSession.File.ID != default)
|
||||
{
|
||||
var file = GetFile(uploadSession.File.ID);
|
||||
file.Version++;
|
||||
@ -921,7 +975,7 @@ namespace ASC.Files.Core.Data
|
||||
file.Encrypted = uploadSession.Encrypted;
|
||||
return file;
|
||||
}
|
||||
var result = ServiceProvider.GetService<File>();
|
||||
var result = ServiceProvider.GetService<File<int>>();
|
||||
result.FolderID = uploadSession.File.FolderID;
|
||||
result.Title = uploadSession.File.Title;
|
||||
result.ContentLength = uploadSession.BytesTotal;
|
||||
@ -935,12 +989,12 @@ namespace ASC.Files.Core.Data
|
||||
|
||||
#region Only in TMFileDao
|
||||
|
||||
public void ReassignFiles(object[] fileIds, Guid newOwnerId)
|
||||
public void ReassignFiles(int[] fileIds, Guid newOwnerId)
|
||||
{
|
||||
var fileIdsStrings = fileIds.Select(r => r.ToString()).ToList();
|
||||
var toUpdate = Query(FilesDbContext.Files)
|
||||
.Where(r => r.CurrentVersion)
|
||||
.Where(r => fileIdsStrings.Any(a => a == r.Id.ToString()));
|
||||
.Where(r => fileIds.Any(a => a == r.Id));
|
||||
|
||||
foreach (var f in toUpdate)
|
||||
{
|
||||
@ -950,14 +1004,14 @@ namespace ASC.Files.Core.Data
|
||||
FilesDbContext.SaveChanges();
|
||||
}
|
||||
|
||||
public List<File> GetFiles(object[] parentIds, FilterType filterType, bool subjectGroup, Guid subjectID, string searchText, bool searchInContent)
|
||||
public List<File<int>> GetFiles(int[] parentIds, FilterType filterType, bool subjectGroup, Guid subjectID, string searchText, bool searchInContent)
|
||||
{
|
||||
if (parentIds == null || parentIds.Length == 0 || filterType == FilterType.FoldersOnly) return new List<File>();
|
||||
if (parentIds == null || parentIds.Length == 0 || filterType == FilterType.FoldersOnly) return new List<File<int>>();
|
||||
|
||||
var parentIdsStrings = parentIds.Select(r => r.ToString()).ToList();
|
||||
var q = GetFileQuery(r => r.CurrentVersion)
|
||||
.Join(FilesDbContext.Tree, a => a.FolderId, t => t.FolderId, (file, tree) => new { file, tree })
|
||||
.Where(r => parentIdsStrings.Any(a => a == r.tree.ParentId.ToString()))
|
||||
.Where(r => parentIds.Any(a => a == r.tree.ParentId))
|
||||
.Select(r => r.file);
|
||||
|
||||
if (!string.IsNullOrEmpty(searchText))
|
||||
@ -1008,7 +1062,7 @@ namespace ASC.Files.Core.Data
|
||||
return FromQueryWithShared(q);
|
||||
}
|
||||
|
||||
public IEnumerable<File> Search(string searchText, bool bunch)
|
||||
public IEnumerable<File<int>> Search(string searchText, bool bunch)
|
||||
{
|
||||
if (FactoryIndexer.TrySelectIds(s => s.MatchAll(searchText), out var ids))
|
||||
{
|
||||
@ -1033,19 +1087,19 @@ namespace ASC.Files.Core.Data
|
||||
}
|
||||
}
|
||||
|
||||
private void DeleteFolder(object fileId)
|
||||
private void DeleteFolder(int fileId)
|
||||
{
|
||||
GlobalStore.GetStore().DeleteDirectory(GetUniqFileDirectory(fileId));
|
||||
}
|
||||
|
||||
public bool IsExistOnStorage(File file)
|
||||
public bool IsExistOnStorage(File<int> file)
|
||||
{
|
||||
return GlobalStore.GetStore().IsFile(GetUniqFilePath(file));
|
||||
}
|
||||
|
||||
private const string DiffTitle = "diff.zip";
|
||||
|
||||
public void SaveEditHistory(File file, string changes, Stream differenceStream)
|
||||
public void SaveEditHistory(File<int> file, string changes, Stream differenceStream)
|
||||
{
|
||||
if (file == null) throw new ArgumentNullException("file");
|
||||
if (string.IsNullOrEmpty(changes)) throw new ArgumentNullException("changes");
|
||||
@ -1054,7 +1108,7 @@ namespace ASC.Files.Core.Data
|
||||
changes = changes.Trim();
|
||||
|
||||
var toUpdate = Query(FilesDbContext.Files)
|
||||
.Where(r => r.Id == (int)file.ID)
|
||||
.Where(r => r.Id == file.ID)
|
||||
.Where(r => r.Version == file.Version);
|
||||
|
||||
foreach (var f in toUpdate)
|
||||
@ -1067,10 +1121,10 @@ namespace ASC.Files.Core.Data
|
||||
GlobalStore.GetStore().Save(string.Empty, GetUniqFilePath(file, DiffTitle), differenceStream, DiffTitle);
|
||||
}
|
||||
|
||||
public List<EditHistory> GetEditHistory(DocumentServiceHelper documentServiceHelper, object fileId, int fileVersion = 0)
|
||||
public List<EditHistory> GetEditHistory(DocumentServiceHelper documentServiceHelper, int fileId, int fileVersion = 0)
|
||||
{
|
||||
var query = Query(FilesDbContext.Files)
|
||||
.Where(r => r.Id == (int)fileId)
|
||||
.Where(r => r.Id == fileId)
|
||||
.Where(r => r.Forcesave == ForcesaveType.None);
|
||||
|
||||
if (fileVersion > 0)
|
||||
@ -1101,15 +1155,15 @@ namespace ASC.Files.Core.Data
|
||||
.ToList();
|
||||
}
|
||||
|
||||
public Stream GetDifferenceStream(File file)
|
||||
public Stream GetDifferenceStream(File<int> file)
|
||||
{
|
||||
return GlobalStore.GetStore().GetReadStream(string.Empty, GetUniqFilePath(file, DiffTitle));
|
||||
}
|
||||
|
||||
public bool ContainChanges(object fileId, int fileVersion)
|
||||
public bool ContainChanges(int fileId, int fileVersion)
|
||||
{
|
||||
return Query(FilesDbContext.Files)
|
||||
.Where(r => r.Id == (int)fileId)
|
||||
.Where(r => r.Id == fileId)
|
||||
.Where(r => r.Version == fileVersion)
|
||||
.Where(r => r.Changes != null)
|
||||
.Any();
|
||||
@ -1163,7 +1217,7 @@ namespace ASC.Files.Core.Data
|
||||
{
|
||||
if (subjectGroup)
|
||||
{
|
||||
var users = UserManager.GetUsersByGroup(subjectID).Select(u => u.ID.ToString()).ToArray();
|
||||
var users = UserManager.GetUsersByGroup(subjectID).Select(u => u.ID).ToArray();
|
||||
result.In(r => r.CreateBy, users);
|
||||
}
|
||||
else
|
||||
@ -1188,7 +1242,7 @@ namespace ASC.Files.Core.Data
|
||||
};
|
||||
}
|
||||
|
||||
protected List<File> FromQueryWithShared(IQueryable<DbFile> dbFiles)
|
||||
protected List<File<int>> FromQueryWithShared(IQueryable<DbFile> dbFiles)
|
||||
{
|
||||
return dbFiles
|
||||
.Select(r => new DbFileQuery
|
||||
@ -1213,7 +1267,7 @@ namespace ASC.Files.Core.Data
|
||||
.ToList();
|
||||
}
|
||||
|
||||
protected List<File> FromQuery(IQueryable<DbFile> dbFiles)
|
||||
protected List<File<int>> FromQuery(IQueryable<DbFile> dbFiles)
|
||||
{
|
||||
return dbFiles
|
||||
.Select(r => new DbFileQuery
|
||||
@ -1233,9 +1287,9 @@ namespace ASC.Files.Core.Data
|
||||
.ToList();
|
||||
}
|
||||
|
||||
public File ToFile(DbFileQuery r)
|
||||
public File<int> ToFile(DbFileQuery r)
|
||||
{
|
||||
var file = ServiceProvider.GetService<File>();
|
||||
var file = ServiceProvider.GetService<File<int>>();
|
||||
file.ID = r.file.Id;
|
||||
file.Title = r.file.Title;
|
||||
file.FolderID = r.file.FolderId;
|
||||
@ -1269,8 +1323,8 @@ namespace ASC.Files.Core.Data
|
||||
{
|
||||
public static DIHelper AddFileDaoService(this DIHelper services)
|
||||
{
|
||||
services.TryAddScoped<IFileDao, FileDao>();
|
||||
services.TryAddTransient<File>();
|
||||
services.TryAddScoped<IFileDao<int>, FileDao>();
|
||||
services.TryAddTransient<File<int>>();
|
||||
|
||||
return services
|
||||
.AddFilesDbContextService()
|
||||
|
@ -31,14 +31,15 @@ using System.Linq.Expressions;
|
||||
using System.Threading;
|
||||
|
||||
using ASC.Common;
|
||||
using ASC.Common.Logging;
|
||||
using ASC.Core;
|
||||
using ASC.Core.Common.EF;
|
||||
using ASC.Core.Common.Settings;
|
||||
using ASC.Core.Tenants;
|
||||
using ASC.ElasticSearch;
|
||||
using ASC.Files.Core.EF;
|
||||
using ASC.Files.Core.Thirdparty;
|
||||
using ASC.Files.Resources;
|
||||
using ASC.Files.Thirdparty.ProviderDao;
|
||||
using ASC.Web.Files.Classes;
|
||||
using ASC.Web.Files.Core.Search;
|
||||
using ASC.Web.Studio.Core;
|
||||
@ -46,11 +47,10 @@ using ASC.Web.Studio.UserControls.Statistics;
|
||||
using ASC.Web.Studio.Utility;
|
||||
|
||||
using Microsoft.Extensions.DependencyInjection;
|
||||
using Microsoft.Extensions.Options;
|
||||
|
||||
namespace ASC.Files.Core.Data
|
||||
{
|
||||
public class FolderDao : AbstractDao, IFolderDao
|
||||
internal class FolderDao : AbstractDao, IFolderDao<int>
|
||||
{
|
||||
private const string my = "my";
|
||||
private const string common = "common";
|
||||
@ -60,7 +60,9 @@ namespace ASC.Files.Core.Data
|
||||
|
||||
public FactoryIndexer<FoldersWrapper> FactoryIndexer { get; }
|
||||
public GlobalSpace GlobalSpace { get; }
|
||||
public ILog Logger { get; }
|
||||
public IDaoFactory DaoFactory { get; }
|
||||
public ProviderFolderDao ProviderFolderDao { get; }
|
||||
public CrossDao CrossDao { get; }
|
||||
|
||||
public FolderDao(
|
||||
FactoryIndexer<FoldersWrapper> factoryIndexer,
|
||||
@ -77,7 +79,9 @@ namespace ASC.Files.Core.Data
|
||||
AuthContext authContext,
|
||||
IServiceProvider serviceProvider,
|
||||
GlobalSpace globalSpace,
|
||||
IOptionsMonitor<ILog> options)
|
||||
IDaoFactory daoFactory,
|
||||
ProviderFolderDao providerFolderDao,
|
||||
CrossDao crossDao)
|
||||
: base(
|
||||
dbContextManager,
|
||||
userManager,
|
||||
@ -94,30 +98,31 @@ namespace ASC.Files.Core.Data
|
||||
{
|
||||
FactoryIndexer = factoryIndexer;
|
||||
GlobalSpace = globalSpace;
|
||||
Logger = options.Get("ASC.Files");
|
||||
DaoFactory = daoFactory;
|
||||
ProviderFolderDao = providerFolderDao;
|
||||
CrossDao = crossDao;
|
||||
}
|
||||
|
||||
public Folder GetFolder(object folderId)
|
||||
public Folder<int> GetFolder(int folderId)
|
||||
{
|
||||
var query = GetFolderQuery(r => r.Id.ToString() == folderId.ToString());
|
||||
var query = GetFolderQuery(r => r.Id == folderId);
|
||||
return FromQueryWithShared(query).SingleOrDefault();
|
||||
}
|
||||
|
||||
public Folder GetFolder(string title, object parentId)
|
||||
public Folder<int> GetFolder(string title, int parentId)
|
||||
{
|
||||
if (string.IsNullOrEmpty(title)) throw new ArgumentNullException(title);
|
||||
|
||||
var query = GetFolderQuery(r => r.Title == title && r.ParentId.ToString() == parentId.ToString())
|
||||
var query = GetFolderQuery(r => r.Title == title && r.ParentId == parentId)
|
||||
.OrderBy(r => r.CreateOn);
|
||||
|
||||
return FromQueryWithShared(query).FirstOrDefault();
|
||||
}
|
||||
|
||||
public Folder GetRootFolder(object folderId)
|
||||
public Folder<int> GetRootFolder(int folderId)
|
||||
{
|
||||
var folderIdString = folderId.ToString();
|
||||
var id = FilesDbContext.Tree
|
||||
.Where(r => r.FolderId.ToString() == folderIdString)
|
||||
.Where(r => r.FolderId == folderId)
|
||||
.OrderByDescending(r => r.Level)
|
||||
.Select(r => r.ParentId)
|
||||
.FirstOrDefault();
|
||||
@ -127,11 +132,11 @@ namespace ASC.Files.Core.Data
|
||||
return FromQueryWithShared(query).SingleOrDefault();
|
||||
}
|
||||
|
||||
public Folder GetRootFolderByFile(object fileId)
|
||||
public Folder<int> GetRootFolderByFile(int fileId)
|
||||
{
|
||||
var fileIdString = fileId.ToString();
|
||||
var subq = Query(FilesDbContext.Files)
|
||||
.Where(r => r.Id.ToString() == fileIdString && r.CurrentVersion)
|
||||
.Where(r => r.Id == fileId && r.CurrentVersion)
|
||||
.Select(r => r.FolderId)
|
||||
.Distinct();
|
||||
|
||||
@ -145,29 +150,28 @@ namespace ASC.Files.Core.Data
|
||||
return FromQueryWithShared(query).SingleOrDefault();
|
||||
}
|
||||
|
||||
public List<Folder> GetFolders(object parentId)
|
||||
public List<Folder<int>> GetFolders(int parentId)
|
||||
{
|
||||
return GetFolders(parentId, default, default, false, default, string.Empty);
|
||||
}
|
||||
|
||||
public List<Folder> GetFolders(object parentId, OrderBy orderBy, FilterType filterType, bool subjectGroup, Guid subjectID, string searchText, bool withSubfolders = false)
|
||||
public List<Folder<int>> GetFolders(int parentId, OrderBy orderBy, FilterType filterType, bool subjectGroup, Guid subjectID, string searchText, bool withSubfolders = false)
|
||||
{
|
||||
if (filterType == FilterType.FilesOnly || filterType == FilterType.ByExtension
|
||||
|| filterType == FilterType.DocumentsOnly || filterType == FilterType.ImagesOnly
|
||||
|| filterType == FilterType.PresentationsOnly || filterType == FilterType.SpreadsheetsOnly
|
||||
|| filterType == FilterType.ArchiveOnly || filterType == FilterType.MediaOnly)
|
||||
return new List<Folder>();
|
||||
return new List<Folder<int>>();
|
||||
|
||||
if (orderBy == null) orderBy = new OrderBy(SortedByType.DateAndTime, false);
|
||||
|
||||
var parentIdString = parentId.ToString();
|
||||
var q = GetFolderQuery(r => r.ParentId.ToString() == parentIdString);
|
||||
var q = GetFolderQuery(r => r.ParentId == parentId);
|
||||
|
||||
if (withSubfolders)
|
||||
{
|
||||
q = GetFolderQuery()
|
||||
.Join(FilesDbContext.Tree, r => r.Id, a => a.FolderId, (folder, tree) => new { folder, tree })
|
||||
.Where(r => r.tree.ParentId.ToString() == parentIdString && r.tree.Level != 0)
|
||||
.Where(r => r.tree.ParentId == parentId && r.tree.Level != 0)
|
||||
.Select(r => r.folder);
|
||||
}
|
||||
|
||||
@ -218,22 +222,21 @@ namespace ASC.Files.Core.Data
|
||||
return FromQueryWithShared(q);
|
||||
}
|
||||
|
||||
public List<Folder> GetFolders(object[] folderIds, FilterType filterType = FilterType.None, bool subjectGroup = false, Guid? subjectID = null, string searchText = "", bool searchSubfolders = false, bool checkShare = true)
|
||||
public List<Folder<int>> GetFolders(int[] folderIds, FilterType filterType = FilterType.None, bool subjectGroup = false, Guid? subjectID = null, string searchText = "", bool searchSubfolders = false, bool checkShare = true)
|
||||
{
|
||||
if (filterType == FilterType.FilesOnly || filterType == FilterType.ByExtension
|
||||
|| filterType == FilterType.DocumentsOnly || filterType == FilterType.ImagesOnly
|
||||
|| filterType == FilterType.PresentationsOnly || filterType == FilterType.SpreadsheetsOnly
|
||||
|| filterType == FilterType.ArchiveOnly || filterType == FilterType.MediaOnly)
|
||||
return new List<Folder>();
|
||||
return new List<Folder<int>>();
|
||||
|
||||
var folderIdsStrings = folderIds.Select(r => r.ToString()).ToList();
|
||||
var q = GetFolderQuery(r => folderIdsStrings.Any(q => q == r.Id.ToString()));
|
||||
var q = GetFolderQuery(r => folderIds.Any(q => q == r.Id));
|
||||
|
||||
if (searchSubfolders)
|
||||
{
|
||||
q = GetFolderQuery()
|
||||
.Join(FilesDbContext.Tree, r => r.Id, a => a.FolderId, (folder, tree) => new { folder, tree })
|
||||
.Where(r => folderIdsStrings.Any(q => q == r.folder.ParentId.ToString()))
|
||||
.Where(r => folderIds.Any(q => q == r.folder.ParentId))
|
||||
.Select(r => r.folder);
|
||||
}
|
||||
|
||||
@ -270,19 +273,18 @@ namespace ASC.Files.Core.Data
|
||||
return checkShare ? FromQueryWithShared(q) : FromQuery(q);
|
||||
}
|
||||
|
||||
public List<Folder> GetParentFolders(object folderId)
|
||||
public List<Folder<int>> GetParentFolders(int folderId)
|
||||
{
|
||||
var folderIdString = folderId.ToString();
|
||||
var q = GetFolderQuery()
|
||||
.Join(FilesDbContext.Tree, r => r.Id, a => a.ParentId, (folder, tree) => new { folder, tree })
|
||||
.Where(r => r.tree.FolderId.ToString() == folderIdString)
|
||||
.Where(r => r.tree.FolderId == folderId)
|
||||
.OrderByDescending(r => r.tree.Level)
|
||||
.Select(r => r.folder);
|
||||
|
||||
return FromQueryWithShared(q);
|
||||
}
|
||||
|
||||
public object SaveFolder(Folder folder)
|
||||
public int SaveFolder(Folder<int> folder)
|
||||
{
|
||||
if (folder == null) throw new ArgumentNullException("folder");
|
||||
|
||||
@ -298,10 +300,10 @@ namespace ASC.Files.Core.Data
|
||||
|
||||
using (var tx = FilesDbContext.Database.BeginTransaction())
|
||||
{
|
||||
if (folder.ID != null && IsExist(folder.ID))
|
||||
if (folder.ID != default && IsExist(folder.ID))
|
||||
{
|
||||
var toUpdate = Query(FilesDbContext.Folders)
|
||||
.Where(r => r.Id == (int)folder.ID)
|
||||
.Where(r => r.Id == folder.ID)
|
||||
.FirstOrDefault();
|
||||
|
||||
toUpdate.Title = folder.Title;
|
||||
@ -317,7 +319,7 @@ namespace ASC.Files.Core.Data
|
||||
var newFolder = new DbFolder
|
||||
{
|
||||
Id = 0,
|
||||
ParentId = (int)folder.ParentFolderID,
|
||||
ParentId = folder.ParentFolderID,
|
||||
Title = folder.Title,
|
||||
CreateOn = TenantUtil.DateTimeToUtc(folder.CreateOn),
|
||||
CreateBy = folder.CreateBy,
|
||||
@ -334,8 +336,8 @@ namespace ASC.Files.Core.Data
|
||||
//itself link
|
||||
var newTree = new DbFolderTree
|
||||
{
|
||||
FolderId = (int)folder.ID,
|
||||
ParentId = (int)folder.ID,
|
||||
FolderId = folder.ID,
|
||||
ParentId = folder.ID,
|
||||
Level = 0
|
||||
};
|
||||
|
||||
@ -357,6 +359,7 @@ namespace ASC.Files.Core.Data
|
||||
|
||||
FilesDbContext.Tree.Add(treeToAdd);
|
||||
}
|
||||
|
||||
FilesDbContext.SaveChanges();
|
||||
}
|
||||
|
||||
@ -372,20 +375,16 @@ namespace ASC.Files.Core.Data
|
||||
return folder.ID;
|
||||
}
|
||||
|
||||
private bool IsExist(object folderId)
|
||||
private bool IsExist(int folderId)
|
||||
{
|
||||
return Query(FilesDbContext.Folders)
|
||||
.Where(r => r.Id == (int)folderId)
|
||||
.Where(r => r.Id == folderId)
|
||||
.Any();
|
||||
}
|
||||
|
||||
public void DeleteFolder(object folderId)
|
||||
public void DeleteFolder(int id)
|
||||
{
|
||||
if (folderId == null) throw new ArgumentNullException("folderId");
|
||||
|
||||
var id = int.Parse(Convert.ToString(folderId));
|
||||
|
||||
if (id == 0) return;
|
||||
if (id == default) throw new ArgumentNullException("folderId");
|
||||
|
||||
using (var tx = FilesDbContext.Database.BeginTransaction())
|
||||
{
|
||||
@ -437,10 +436,25 @@ namespace ASC.Files.Core.Data
|
||||
RecalculateFoldersCount(parent);
|
||||
}
|
||||
|
||||
FactoryIndexer.DeleteAsync(new FoldersWrapper { Id = (int)folderId });
|
||||
FactoryIndexer.DeleteAsync(new FoldersWrapper { Id = id });
|
||||
}
|
||||
|
||||
public object MoveFolder(object folderId, object toFolderId, CancellationToken? cancellationToken)
|
||||
public TTo MoveFolder<TTo>(int folderId, TTo toFolderId, CancellationToken? cancellationToken)
|
||||
{
|
||||
if (toFolderId is int tId)
|
||||
{
|
||||
return (TTo)Convert.ChangeType(MoveFolder(folderId, tId, cancellationToken), typeof(TTo));
|
||||
}
|
||||
|
||||
if (toFolderId is string tsId)
|
||||
{
|
||||
return (TTo)Convert.ChangeType(MoveFolder(folderId, tsId, cancellationToken), typeof(TTo));
|
||||
}
|
||||
|
||||
throw new NotImplementedException();
|
||||
}
|
||||
|
||||
public int MoveFolder(int folderId, int toFolderId, CancellationToken? cancellationToken)
|
||||
{
|
||||
using (var tx = FilesDbContext.Database.BeginTransaction())
|
||||
{
|
||||
@ -449,26 +463,26 @@ namespace ASC.Files.Core.Data
|
||||
if (folder.FolderType != FolderType.DEFAULT)
|
||||
throw new ArgumentException("It is forbidden to move the System folder.", "folderId");
|
||||
|
||||
var recalcFolders = new List<object> { toFolderId };
|
||||
var recalcFolders = new List<int> { toFolderId };
|
||||
var parent = FilesDbContext.Folders
|
||||
.Where(r => r.Id == (int)folderId)
|
||||
.Where(r => r.Id == folderId)
|
||||
.Select(r => r.ParentId)
|
||||
.FirstOrDefault();
|
||||
|
||||
if (parent != 0 && !recalcFolders.Contains(parent)) recalcFolders.Add(parent);
|
||||
|
||||
var toUpdate = Query(FilesDbContext.Folders)
|
||||
.Where(r => r.Id == (int)folderId)
|
||||
.Where(r => r.Id == folderId)
|
||||
.FirstOrDefault();
|
||||
|
||||
toUpdate.ParentId = (int)toFolderId;
|
||||
toUpdate.ParentId = toFolderId;
|
||||
toUpdate.ModifiedOn = DateTime.UtcNow;
|
||||
toUpdate.ModifiedBy = AuthContext.CurrentAccount.ID;
|
||||
|
||||
FilesDbContext.SaveChanges();
|
||||
|
||||
var subfolders = FilesDbContext.Tree
|
||||
.Where(r => r.ParentId == (int)folderId)
|
||||
.Where(r => r.ParentId == folderId)
|
||||
.ToDictionary(r => r.FolderId, r => r.Level);
|
||||
|
||||
var toDelete = FilesDbContext.Tree
|
||||
@ -478,7 +492,7 @@ namespace ASC.Files.Core.Data
|
||||
FilesDbContext.SaveChanges();
|
||||
|
||||
var toInsert = FilesDbContext.Tree
|
||||
.Where(r => r.FolderId == (int)toFolderId)
|
||||
.Where(r => r.FolderId == toFolderId)
|
||||
.ToList();
|
||||
|
||||
foreach (var subfolder in subfolders)
|
||||
@ -504,7 +518,35 @@ namespace ASC.Files.Core.Data
|
||||
return folderId;
|
||||
}
|
||||
|
||||
public Folder CopyFolder(object folderId, object toFolderId, CancellationToken? cancellationToken)
|
||||
public string MoveFolder(int folderId, string toFolderId, CancellationToken? cancellationToken)
|
||||
{
|
||||
var toSelector = ProviderFolderDao.GetSelector(toFolderId);
|
||||
|
||||
var moved = CrossDao.PerformCrossDaoFolderCopy(
|
||||
folderId, this, DaoFactory.GetFileDao<int>(), r => r,
|
||||
toFolderId, toSelector.GetFolderDao(toFolderId), toSelector.GetFileDao(toFolderId), toSelector.ConvertId,
|
||||
true, cancellationToken);
|
||||
|
||||
return moved.ID;
|
||||
}
|
||||
|
||||
|
||||
public Folder<TTo> CopyFolder<TTo>(int folderId, TTo toFolderId, CancellationToken? cancellationToken)
|
||||
{
|
||||
if (toFolderId is int tId)
|
||||
{
|
||||
return CopyFolder(folderId, tId, cancellationToken) as Folder<TTo>;
|
||||
}
|
||||
|
||||
if (toFolderId is string tsId)
|
||||
{
|
||||
return CopyFolder(folderId, tsId, cancellationToken) as Folder<TTo>;
|
||||
}
|
||||
|
||||
throw new NotImplementedException();
|
||||
}
|
||||
|
||||
public Folder<int> CopyFolder(int folderId, int toFolderId, CancellationToken? cancellationToken)
|
||||
{
|
||||
var folder = GetFolder(folderId);
|
||||
|
||||
@ -513,7 +555,7 @@ namespace ASC.Files.Core.Data
|
||||
if (folder.FolderType == FolderType.BUNCH)
|
||||
folder.FolderType = FolderType.DEFAULT;
|
||||
|
||||
var copy = ServiceProvider.GetService<Folder>();
|
||||
var copy = ServiceProvider.GetService<Folder<int>>();
|
||||
copy.ParentFolderID = toFolderId;
|
||||
copy.RootFolderId = toFolder.RootFolderId;
|
||||
copy.RootFolderCreator = toFolder.RootFolderCreator;
|
||||
@ -527,15 +569,47 @@ namespace ASC.Files.Core.Data
|
||||
return copy;
|
||||
}
|
||||
|
||||
public IDictionary<object, string> CanMoveOrCopy(object[] folderIds, object to)
|
||||
public Folder<string> CopyFolder(int folderId, string toFolderId, CancellationToken? cancellationToken)
|
||||
{
|
||||
var result = new Dictionary<object, string>();
|
||||
var toSelector = ProviderFolderDao.GetSelector(toFolderId);
|
||||
|
||||
var moved = CrossDao.PerformCrossDaoFolderCopy(
|
||||
folderId, this, DaoFactory.GetFileDao<int>(), r => r,
|
||||
toFolderId, toSelector.GetFolderDao(toFolderId), toSelector.GetFileDao(toFolderId), toSelector.ConvertId,
|
||||
false, cancellationToken);
|
||||
|
||||
return moved;
|
||||
}
|
||||
|
||||
public IDictionary<int, string> CanMoveOrCopy<TTo>(int[] folderIds, TTo to)
|
||||
{
|
||||
if (to is int tId)
|
||||
{
|
||||
return CanMoveOrCopy(folderIds, tId);
|
||||
}
|
||||
|
||||
if (to is string tsId)
|
||||
{
|
||||
return CanMoveOrCopy(folderIds, tsId);
|
||||
}
|
||||
|
||||
throw new NotImplementedException();
|
||||
}
|
||||
|
||||
public IDictionary<int, string> CanMoveOrCopy(int[] folderIds, string to)
|
||||
{
|
||||
return new Dictionary<int, string>();
|
||||
}
|
||||
|
||||
public IDictionary<int, string> CanMoveOrCopy(int[] folderIds, int to)
|
||||
{
|
||||
var result = new Dictionary<int, string>();
|
||||
|
||||
foreach (var folderId in folderIds)
|
||||
{
|
||||
var exists = FilesDbContext.Tree
|
||||
.Where(r => r.ParentId == (int)folderId)
|
||||
.Where(r => r.FolderId == (int)to)
|
||||
.Where(r => r.ParentId == folderId)
|
||||
.Where(r => r.FolderId == to)
|
||||
.Any();
|
||||
|
||||
if (exists)
|
||||
@ -544,13 +618,13 @@ namespace ASC.Files.Core.Data
|
||||
}
|
||||
|
||||
var title = Query(FilesDbContext.Folders)
|
||||
.Where(r => r.Id == (int)folderId)
|
||||
.Where(r => r.Id == folderId)
|
||||
.Select(r => r.Title.ToLower())
|
||||
.FirstOrDefault();
|
||||
|
||||
var conflict = Query(FilesDbContext.Folders)
|
||||
.Where(r => r.Title.ToLower() == title)
|
||||
.Where(r => r.ParentId == (int)to)
|
||||
.Where(r => r.ParentId == to)
|
||||
.Select(r => r.Id)
|
||||
.FirstOrDefault();
|
||||
|
||||
@ -558,15 +632,15 @@ namespace ASC.Files.Core.Data
|
||||
{
|
||||
FilesDbContext.Files
|
||||
.Join(FilesDbContext.Files, f1 => f1.Title.ToLower(), f2 => f2.Title.ToLower(), (f1, f2) => new { f1, f2 })
|
||||
.Where(r => r.f1.TenantId == TenantID && r.f1.CurrentVersion && r.f1.FolderId == (int)folderId)
|
||||
.Where(r => r.f2.TenantId == TenantID && r.f2.CurrentVersion && r.f2.FolderId == (int)conflict)
|
||||
.Where(r => r.f1.TenantId == TenantID && r.f1.CurrentVersion && r.f1.FolderId == folderId)
|
||||
.Where(r => r.f2.TenantId == TenantID && r.f2.CurrentVersion && r.f2.FolderId == conflict)
|
||||
.Select(r => r.f1)
|
||||
.ToList()
|
||||
.ForEach(r => result[r.Id] = r.Title);
|
||||
|
||||
var childs = Query(FilesDbContext.Folders)
|
||||
.Where(r => r.ParentId == (int)folderId)
|
||||
.Select(r => r.Id.ToString());
|
||||
.Where(r => r.ParentId == folderId)
|
||||
.Select(r => r.Id);
|
||||
|
||||
foreach (var pair in CanMoveOrCopy(childs.ToArray(), conflict))
|
||||
{
|
||||
@ -578,10 +652,10 @@ namespace ASC.Files.Core.Data
|
||||
return result;
|
||||
}
|
||||
|
||||
public object RenameFolder(Folder folder, string newTitle)
|
||||
public int RenameFolder(Folder<int> folder, string newTitle)
|
||||
{
|
||||
var toUpdate = Query(FilesDbContext.Folders)
|
||||
.Where(r => r.Id == (int)folder.ID)
|
||||
.Where(r => r.Id == folder.ID)
|
||||
.FirstOrDefault();
|
||||
|
||||
toUpdate.Title = Global.ReplaceInvalidCharsAndTruncate(newTitle);
|
||||
@ -593,55 +667,65 @@ namespace ASC.Files.Core.Data
|
||||
return folder.ID;
|
||||
}
|
||||
|
||||
public int GetItemsCount(object folderId)
|
||||
|
||||
public int GetItemsCount(int folderId)
|
||||
{
|
||||
return GetFoldersCount(folderId) +
|
||||
GetFilesCount(folderId);
|
||||
}
|
||||
|
||||
private int GetFoldersCount(object parentId)
|
||||
private int GetFoldersCount(int parentId)
|
||||
{
|
||||
var parentIdString = parentId.ToString();
|
||||
var count = FilesDbContext.Tree
|
||||
.Where(r => r.ParentId.ToString() == parentIdString)
|
||||
.Where(r => r.ParentId == parentId)
|
||||
.Where(r => r.Level > 0)
|
||||
.Count();
|
||||
|
||||
return count;
|
||||
}
|
||||
|
||||
private int GetFilesCount(object folderId)
|
||||
private int GetFilesCount(int folderId)
|
||||
{
|
||||
var folderIdString = folderId.ToString();
|
||||
var count = Query(FilesDbContext.Files)
|
||||
.Distinct()
|
||||
.Where(r => FilesDbContext.Tree.Where(r => r.ParentId.ToString() == folderIdString).Select(r => r.FolderId).Any(b => b == r.FolderId))
|
||||
.Where(r => FilesDbContext.Tree.Where(r => r.ParentId == folderId).Select(r => r.FolderId).Any(b => b == r.FolderId))
|
||||
.Count();
|
||||
|
||||
return count;
|
||||
}
|
||||
|
||||
public bool IsEmpty(object folderId)
|
||||
public bool IsEmpty(int folderId)
|
||||
{
|
||||
return GetItemsCount(folderId) == 0;
|
||||
}
|
||||
|
||||
public bool UseTrashForRemove(Folder folder)
|
||||
public bool UseTrashForRemove(Folder<int> folder)
|
||||
{
|
||||
return folder.RootFolderType != FolderType.TRASH && folder.FolderType != FolderType.BUNCH;
|
||||
}
|
||||
|
||||
public bool UseRecursiveOperation(object folderId, object toRootFolderId)
|
||||
public bool UseRecursiveOperation(int folderId, string toRootFolderId)
|
||||
{
|
||||
return true;
|
||||
}
|
||||
|
||||
public bool CanCalculateSubitems(object entryId)
|
||||
public bool UseRecursiveOperation(int folderId, int toRootFolderId)
|
||||
{
|
||||
return true;
|
||||
}
|
||||
|
||||
public long GetMaxUploadSize(object folderId, bool chunkedUpload)
|
||||
public bool UseRecursiveOperation<TTo>(int folderId, TTo toRootFolderId)
|
||||
{
|
||||
return true;
|
||||
}
|
||||
|
||||
public bool CanCalculateSubitems(int entryId)
|
||||
{
|
||||
return true;
|
||||
}
|
||||
|
||||
public long GetMaxUploadSize(int folderId, bool chunkedUpload)
|
||||
{
|
||||
var tmp = long.MaxValue;
|
||||
|
||||
@ -651,15 +735,15 @@ namespace ASC.Files.Core.Data
|
||||
return Math.Min(tmp, chunkedUpload ? SetupInfo.MaxChunkedUploadSize(TenantExtra, TenantStatisticProvider) : SetupInfo.MaxUploadSize(TenantExtra, TenantStatisticProvider));
|
||||
}
|
||||
|
||||
private void RecalculateFoldersCount(object id)
|
||||
private void RecalculateFoldersCount(int id)
|
||||
{
|
||||
var toUpdate = Query(FilesDbContext.Folders)
|
||||
.Where(r => FilesDbContext.Tree.Where(a => a.FolderId == (int)id).Select(a => a.ParentId).Any(a => a == r.Id))
|
||||
.Where(r => FilesDbContext.Tree.Where(a => a.FolderId == id).Select(a => a.ParentId).Any(a => a == r.Id))
|
||||
.ToList();
|
||||
|
||||
foreach (var f in toUpdate)
|
||||
{
|
||||
var count = FilesDbContext.Tree.Where(r => r.ParentId == f.Id).Count() - 1;
|
||||
var count = FilesDbContext.Tree.Where(r => r.ParentId == id).Count() - 1;
|
||||
f.FoldersCount = count;
|
||||
}
|
||||
|
||||
@ -668,10 +752,10 @@ namespace ASC.Files.Core.Data
|
||||
|
||||
#region Only for TMFolderDao
|
||||
|
||||
public void ReassignFolders(object[] folderIds, Guid newOwnerId)
|
||||
public void ReassignFolders(int[] folderIds, Guid newOwnerId)
|
||||
{
|
||||
var toUpdate = Query(FilesDbContext.Folders)
|
||||
.Where(r => folderIds.Any(a => r.Id == (int)a));
|
||||
.Where(r => folderIds.Any(a => r.Id == a));
|
||||
|
||||
foreach (var f in toUpdate)
|
||||
{
|
||||
@ -681,16 +765,17 @@ namespace ASC.Files.Core.Data
|
||||
FilesDbContext.SaveChanges();
|
||||
}
|
||||
|
||||
public IEnumerable<Folder> Search(string text, bool bunch)
|
||||
|
||||
public IEnumerable<Folder<int>> Search(string text, bool bunch)
|
||||
{
|
||||
return Search(text).Where(f => bunch
|
||||
? f.RootFolderType == FolderType.BUNCH
|
||||
: (f.RootFolderType == FolderType.USER || f.RootFolderType == FolderType.COMMON)).ToList();
|
||||
}
|
||||
|
||||
private IEnumerable<Folder> Search(string text)
|
||||
private IEnumerable<Folder<int>> Search(string text)
|
||||
{
|
||||
if (string.IsNullOrEmpty(text)) return new List<Folder>();
|
||||
if (string.IsNullOrEmpty(text)) return new List<Folder<int>>();
|
||||
|
||||
if (FactoryIndexer.TrySelectIds(s => s.MatchAll(text), out var ids))
|
||||
{
|
||||
@ -702,7 +787,7 @@ namespace ASC.Files.Core.Data
|
||||
return FromQueryWithShared(q);
|
||||
}
|
||||
|
||||
public virtual IEnumerable<object> GetFolderIDs(string module, string bunch, IEnumerable<string> data, bool createIfNotExists)
|
||||
public IEnumerable<int> GetFolderIDs(string module, string bunch, IEnumerable<string> data, bool createIfNotExists)
|
||||
{
|
||||
if (string.IsNullOrEmpty(module)) throw new ArgumentNullException("module");
|
||||
if (string.IsNullOrEmpty(bunch)) throw new ArgumentNullException("bunch");
|
||||
@ -713,14 +798,14 @@ namespace ASC.Files.Core.Data
|
||||
.Where(r => keys.Length > 1 ? keys.Any(a => a == r.RightNode) : r.RightNode == keys[0])
|
||||
.ToDictionary(r => r.RightNode, r => r.LeftNode);
|
||||
|
||||
var folderIds = new List<object>();
|
||||
var folderIds = new List<int>();
|
||||
|
||||
foreach (var key in keys)
|
||||
{
|
||||
string folderId = null;
|
||||
if (createIfNotExists && !folderIdsDictionary.TryGetValue(key, out folderId))
|
||||
int newFolderId = 0;
|
||||
if (createIfNotExists && !folderIdsDictionary.TryGetValue(key, out var folderId))
|
||||
{
|
||||
var folder = ServiceProvider.GetService<Folder>();
|
||||
var folder = ServiceProvider.GetService<Folder<int>>();
|
||||
switch (bunch)
|
||||
{
|
||||
case my:
|
||||
@ -743,81 +828,87 @@ namespace ASC.Files.Core.Data
|
||||
folder.FolderType = FolderType.Projects;
|
||||
folder.Title = projects;
|
||||
break;
|
||||
default:
|
||||
folder.FolderType = FolderType.BUNCH;
|
||||
folder.Title = (string)key;
|
||||
break;
|
||||
}
|
||||
using var tx = FilesDbContext.Database.BeginTransaction();//NOTE: Maybe we shouldn't start transaction here at all
|
||||
|
||||
folderId = (string)SaveFolder(folder); //Save using our db manager
|
||||
|
||||
var newBunch = new DbFilesBunchObjects
|
||||
{
|
||||
LeftNode = folderId,
|
||||
RightNode = key,
|
||||
TenantId = TenantID
|
||||
};
|
||||
|
||||
FilesDbContext.AddOrUpdate(r => r.BunchObjects, newBunch);
|
||||
FilesDbContext.SaveChanges();
|
||||
|
||||
tx.Commit(); //Commit changes
|
||||
}
|
||||
folderIds.Add(folderId);
|
||||
}
|
||||
return folderIds;
|
||||
}
|
||||
|
||||
public virtual object GetFolderID(string module, string bunch, string data, bool createIfNotExists)
|
||||
{
|
||||
if (string.IsNullOrEmpty(module)) throw new ArgumentNullException("module");
|
||||
if (string.IsNullOrEmpty(bunch)) throw new ArgumentNullException("bunch");
|
||||
|
||||
var key = string.Format("{0}/{1}/{2}", module, bunch, data);
|
||||
var folderId = Query(FilesDbContext.BunchObjects)
|
||||
.Where(r => r.RightNode == key)
|
||||
.Select(r => r.LeftNode)
|
||||
.FirstOrDefault();
|
||||
|
||||
if (createIfNotExists && folderId == null)
|
||||
{
|
||||
var folder = ServiceProvider.GetService<Folder>();
|
||||
folder.ParentFolderID = 0;
|
||||
switch (bunch)
|
||||
{
|
||||
case my:
|
||||
folder.FolderType = FolderType.USER;
|
||||
folder.Title = my;
|
||||
folder.CreateBy = new Guid(data);
|
||||
break;
|
||||
case common:
|
||||
folder.FolderType = FolderType.COMMON;
|
||||
folder.Title = common;
|
||||
break;
|
||||
case trash:
|
||||
folder.FolderType = FolderType.TRASH;
|
||||
folder.Title = trash;
|
||||
folder.CreateBy = new Guid(data);
|
||||
break;
|
||||
case share:
|
||||
folder.FolderType = FolderType.SHARE;
|
||||
folder.Title = share;
|
||||
break;
|
||||
case projects:
|
||||
folder.FolderType = FolderType.Projects;
|
||||
folder.Title = projects;
|
||||
break;
|
||||
default:
|
||||
folder.FolderType = FolderType.BUNCH;
|
||||
folder.Title = key;
|
||||
break;
|
||||
}
|
||||
using var tx = FilesDbContext.Database.BeginTransaction();//NOTE: Maybe we shouldn't start transaction here at all
|
||||
folderId = (string)SaveFolder(folder); //Save using our db manager
|
||||
|
||||
newFolderId = SaveFolder(folder); //Save using our db manager
|
||||
|
||||
var newBunch = new DbFilesBunchObjects
|
||||
{
|
||||
LeftNode = newFolderId.ToString(),
|
||||
RightNode = key,
|
||||
TenantId = TenantID
|
||||
};
|
||||
|
||||
FilesDbContext.AddOrUpdate(r => r.BunchObjects, newBunch);
|
||||
FilesDbContext.SaveChanges();
|
||||
|
||||
tx.Commit(); //Commit changes
|
||||
}
|
||||
folderIds.Add(newFolderId);
|
||||
}
|
||||
return folderIds;
|
||||
}
|
||||
|
||||
public int GetFolderID(string module, string bunch, string data, bool createIfNotExists)
|
||||
{
|
||||
if (string.IsNullOrEmpty(module)) throw new ArgumentNullException("module");
|
||||
if (string.IsNullOrEmpty(bunch)) throw new ArgumentNullException("bunch");
|
||||
|
||||
var key = string.Format("{0}/{1}/{2}", module, bunch, data);
|
||||
var folderId = Query(FilesDbContext.BunchObjects)
|
||||
.Where(r => r.RightNode == key)
|
||||
.Select(r => r.LeftNode)
|
||||
.FirstOrDefault();
|
||||
|
||||
if (folderId != null)
|
||||
{
|
||||
return Convert.ToInt32(folderId);
|
||||
}
|
||||
|
||||
var newFolderId = 0;
|
||||
if (createIfNotExists)
|
||||
{
|
||||
var folder = ServiceProvider.GetService<Folder<int>>();
|
||||
folder.ParentFolderID = 0;
|
||||
switch (bunch)
|
||||
{
|
||||
case my:
|
||||
folder.FolderType = FolderType.USER;
|
||||
folder.Title = my;
|
||||
folder.CreateBy = new Guid(data.ToString());
|
||||
break;
|
||||
case common:
|
||||
folder.FolderType = FolderType.COMMON;
|
||||
folder.Title = common;
|
||||
break;
|
||||
case trash:
|
||||
folder.FolderType = FolderType.TRASH;
|
||||
folder.Title = trash;
|
||||
folder.CreateBy = new Guid(data.ToString());
|
||||
break;
|
||||
case share:
|
||||
folder.FolderType = FolderType.SHARE;
|
||||
folder.Title = share;
|
||||
break;
|
||||
case projects:
|
||||
folder.FolderType = FolderType.Projects;
|
||||
folder.Title = projects;
|
||||
break;
|
||||
default:
|
||||
folder.FolderType = FolderType.BUNCH;
|
||||
folder.Title = key;
|
||||
break;
|
||||
}
|
||||
using var tx = FilesDbContext.Database.BeginTransaction(); //NOTE: Maybe we shouldn't start transaction here at all
|
||||
newFolderId = SaveFolder(folder); //Save using our db manager
|
||||
var toInsert = new DbFilesBunchObjects
|
||||
{
|
||||
LeftNode = folderId,
|
||||
LeftNode = newFolderId.ToString(),
|
||||
RightNode = key,
|
||||
TenantId = TenantID
|
||||
};
|
||||
@ -826,33 +917,32 @@ namespace ASC.Files.Core.Data
|
||||
tx.Commit(); //Commit changes
|
||||
}
|
||||
|
||||
return Convert.ToInt32(folderId);
|
||||
return newFolderId;
|
||||
}
|
||||
|
||||
|
||||
public object GetFolderIDProjects(bool createIfNotExists)
|
||||
int IFolderDao<int>.GetFolderIDProjects(bool createIfNotExists)
|
||||
{
|
||||
return GetFolderID(FileConstant.ModuleId, projects, null, createIfNotExists);
|
||||
return (this as IFolderDao<int>).GetFolderID(FileConstant.ModuleId, projects, null, createIfNotExists);
|
||||
}
|
||||
|
||||
public object GetFolderIDTrash(bool createIfNotExists, Guid? userId = null)
|
||||
public int GetFolderIDTrash(bool createIfNotExists, Guid? userId = null)
|
||||
{
|
||||
return GetFolderID(FileConstant.ModuleId, trash, (userId ?? AuthContext.CurrentAccount.ID).ToString(), createIfNotExists);
|
||||
return (this as IFolderDao<int>).GetFolderID(FileConstant.ModuleId, trash, (userId ?? AuthContext.CurrentAccount.ID).ToString(), createIfNotExists);
|
||||
}
|
||||
|
||||
public object GetFolderIDCommon(bool createIfNotExists)
|
||||
public int GetFolderIDCommon(bool createIfNotExists)
|
||||
{
|
||||
return GetFolderID(FileConstant.ModuleId, common, null, createIfNotExists);
|
||||
return (this as IFolderDao<int>).GetFolderID(FileConstant.ModuleId, common, null, createIfNotExists);
|
||||
}
|
||||
|
||||
public object GetFolderIDUser(bool createIfNotExists, Guid? userId = null)
|
||||
public int GetFolderIDUser(bool createIfNotExists, Guid? userId = null)
|
||||
{
|
||||
return GetFolderID(FileConstant.ModuleId, my, (userId ?? AuthContext.CurrentAccount.ID).ToString(), createIfNotExists);
|
||||
return (this as IFolderDao<int>).GetFolderID(FileConstant.ModuleId, my, (userId ?? AuthContext.CurrentAccount.ID).ToString(), createIfNotExists);
|
||||
}
|
||||
|
||||
public object GetFolderIDShare(bool createIfNotExists)
|
||||
public int GetFolderIDShare(bool createIfNotExists)
|
||||
{
|
||||
return GetFolderID(FileConstant.ModuleId, share, null, createIfNotExists);
|
||||
return (this as IFolderDao<int>).GetFolderID(FileConstant.ModuleId, share, null, createIfNotExists);
|
||||
}
|
||||
|
||||
#endregion
|
||||
@ -867,7 +957,7 @@ namespace ASC.Files.Core.Data
|
||||
return q;
|
||||
}
|
||||
|
||||
protected List<Folder> FromQueryWithShared(IQueryable<DbFolder> dbFiles)
|
||||
protected List<Folder<int>> FromQueryWithShared(IQueryable<DbFolder> dbFiles)
|
||||
{
|
||||
return dbFiles
|
||||
.Select(r => new DbFolderQuery
|
||||
@ -891,7 +981,7 @@ namespace ASC.Files.Core.Data
|
||||
.ToList();
|
||||
}
|
||||
|
||||
protected List<Folder> FromQuery(IQueryable<DbFolder> dbFiles)
|
||||
protected List<Folder<int>> FromQuery(IQueryable<DbFolder> dbFiles)
|
||||
{
|
||||
return dbFiles
|
||||
.Select(r => new DbFolderQuery
|
||||
@ -912,9 +1002,9 @@ namespace ASC.Files.Core.Data
|
||||
.ToList();
|
||||
}
|
||||
|
||||
public Folder ToFolder(DbFolderQuery r)
|
||||
public Folder<int> ToFolder(DbFolderQuery r)
|
||||
{
|
||||
var result = ServiceProvider.GetService<Folder>();
|
||||
var result = ServiceProvider.GetService<Folder<int>>();
|
||||
result.ID = r.folder.Id;
|
||||
result.ParentFolderID = r.folder.ParentId;
|
||||
result.Title = r.folder.Title;
|
||||
@ -966,15 +1056,15 @@ namespace ASC.Files.Core.Data
|
||||
return result;
|
||||
}
|
||||
|
||||
public string GetBunchObjectID(object folderID)
|
||||
public string GetBunchObjectID(int folderID)
|
||||
{
|
||||
return Query(FilesDbContext.BunchObjects)
|
||||
.Where(r => r.LeftNode == (folderID ?? string.Empty).ToString())
|
||||
.Where(r => r.LeftNode == (folderID).ToString())
|
||||
.Select(r => r.RightNode)
|
||||
.FirstOrDefault();
|
||||
}
|
||||
|
||||
public Dictionary<string, string> GetBunchObjectIDs(List<object> folderIDs)
|
||||
public Dictionary<string, string> GetBunchObjectIDs(List<int> folderIDs)
|
||||
{
|
||||
return Query(FilesDbContext.BunchObjects)
|
||||
.Where(r => folderIDs.Any(a => a.ToString() == r.LeftNode))
|
||||
@ -1033,6 +1123,8 @@ namespace ASC.Files.Core.Data
|
||||
//}
|
||||
//return projectTitle;
|
||||
}
|
||||
|
||||
|
||||
}
|
||||
|
||||
public class DbFolderQuery
|
||||
@ -1046,8 +1138,10 @@ namespace ASC.Files.Core.Data
|
||||
{
|
||||
public static DIHelper AddFolderDaoService(this DIHelper services)
|
||||
{
|
||||
services.TryAddScoped<IFolderDao, FolderDao>();
|
||||
services.TryAddTransient<Folder>();
|
||||
services.TryAddScoped<IFolderDao<int>, FolderDao>();
|
||||
services.TryAddTransient<Folder<int>>();
|
||||
services.TryAddTransient<Folder<string>>();
|
||||
|
||||
return services
|
||||
.AddFactoryIndexerService<FoldersWrapper>()
|
||||
.AddTenantManagerService()
|
||||
|
@ -42,7 +42,7 @@ using ASC.Web.Studio.Utility;
|
||||
|
||||
namespace ASC.Files.Core.Data
|
||||
{
|
||||
internal class SecurityDao : AbstractDao, ISecurityDao
|
||||
internal class SecurityDao<T> : AbstractDao, ISecurityDao<T>
|
||||
{
|
||||
public SecurityDao(UserManager userManager,
|
||||
DbContextManager<FilesDbContext> dbContextManager,
|
||||
@ -180,7 +180,7 @@ namespace ASC.Files.Core.Data
|
||||
return FromQuery(q);
|
||||
}
|
||||
|
||||
public IEnumerable<FileShareRecord> GetPureShareRecords(IEnumerable<FileEntry> entries)
|
||||
public IEnumerable<FileShareRecord> GetPureShareRecords(IEnumerable<FileEntry<T>> entries)
|
||||
{
|
||||
if (entries == null) return new List<FileShareRecord>();
|
||||
|
||||
@ -195,7 +195,7 @@ namespace ASC.Files.Core.Data
|
||||
return GetPureShareRecordsDb(files, folders);
|
||||
}
|
||||
|
||||
public IEnumerable<FileShareRecord> GetPureShareRecords(FileEntry entry)
|
||||
public IEnumerable<FileShareRecord> GetPureShareRecords(FileEntry<T> entry)
|
||||
{
|
||||
if (entry == null) return new List<FileShareRecord>();
|
||||
|
||||
@ -228,7 +228,7 @@ namespace ASC.Files.Core.Data
|
||||
/// </summary>
|
||||
/// <param name="entries"></param>
|
||||
/// <returns></returns>
|
||||
public IEnumerable<FileShareRecord> GetShares(IEnumerable<FileEntry> entries)
|
||||
public IEnumerable<FileShareRecord> GetShares(IEnumerable<FileEntry<T>> entries)
|
||||
{
|
||||
if (entries == null) return new List<FileShareRecord>();
|
||||
|
||||
@ -248,7 +248,7 @@ namespace ASC.Files.Core.Data
|
||||
/// </summary>
|
||||
/// <param name="entry"></param>
|
||||
/// <returns></returns>
|
||||
public IEnumerable<FileShareRecord> GetShares(FileEntry entry)
|
||||
public IEnumerable<FileShareRecord> GetShares(FileEntry<T> entry)
|
||||
{
|
||||
if (entry == null) return new List<FileShareRecord>();
|
||||
|
||||
@ -259,13 +259,13 @@ namespace ASC.Files.Core.Data
|
||||
return SaveFilesAndFoldersForShare(files, foldersInt);
|
||||
}
|
||||
|
||||
private void SelectFilesAndFoldersForShare(FileEntry entry, ICollection<string> files, ICollection<string> folders, ICollection<int> foldersInt)
|
||||
private void SelectFilesAndFoldersForShare(FileEntry<T> entry, ICollection<string> files, ICollection<string> folders, ICollection<int> foldersInt)
|
||||
{
|
||||
object folderId;
|
||||
T folderId;
|
||||
if (entry.FileEntryType == FileEntryType.File)
|
||||
{
|
||||
var fileId = MappingID(entry.ID);
|
||||
folderId = ((File)entry).FolderID;
|
||||
folderId = ((File<T>)entry).FolderID;
|
||||
if (!files.Contains(fileId.ToString())) files.Add(fileId.ToString());
|
||||
}
|
||||
else
|
||||
@ -369,7 +369,9 @@ namespace ASC.Files.Core.Data
|
||||
{
|
||||
public static DIHelper AddSecurityDaoService(this DIHelper services)
|
||||
{
|
||||
services.TryAddScoped<ISecurityDao, SecurityDao>();
|
||||
services.TryAddScoped<ISecurityDao<int>, SecurityDao<int>>();
|
||||
services.TryAddScoped<SecurityDao<int>>();
|
||||
services.TryAddScoped<SecurityDao<string>>();
|
||||
|
||||
return services
|
||||
.AddUserManagerService()
|
||||
|
@ -41,7 +41,7 @@ using ASC.Web.Studio.Utility;
|
||||
|
||||
namespace ASC.Files.Core.Data
|
||||
{
|
||||
internal class TagDao : AbstractDao, ITagDao
|
||||
internal class TagDao<T> : AbstractDao, ITagDao<T>
|
||||
{
|
||||
private static readonly object syncRoot = new object();
|
||||
|
||||
@ -73,7 +73,7 @@ namespace ASC.Files.Core.Data
|
||||
{
|
||||
}
|
||||
|
||||
public IEnumerable<Tag> GetTags(TagType tagType, IEnumerable<FileEntry> fileEntries)
|
||||
public IEnumerable<Tag> GetTags(TagType tagType, IEnumerable<FileEntry<T>> fileEntries)
|
||||
{
|
||||
var filesId = fileEntries.Where(e => e.FileEntryType == FileEntryType.File).Select(e => MappingID(e.ID).ToString()).ToList();
|
||||
var foldersId = fileEntries.Where(e => e.FileEntryType == FileEntryType.Folder).Select(e => MappingID(e.ID).ToString()).ToList();
|
||||
@ -88,7 +88,7 @@ namespace ASC.Files.Core.Data
|
||||
return FromQuery(q);
|
||||
}
|
||||
|
||||
public IEnumerable<Tag> GetTags(object entryID, FileEntryType entryType, TagType tagType)
|
||||
public IEnumerable<Tag> GetTags(T entryID, FileEntryType entryType, TagType tagType)
|
||||
{
|
||||
var q = Query(FilesDbContext.Tag)
|
||||
.Join(FilesDbContext.TagLink, r => r.Id, l => l.TagId, (tag, link) => new TagLinkData { Tag = tag, Link = link })
|
||||
@ -376,12 +376,12 @@ namespace ASC.Files.Core.Data
|
||||
}
|
||||
}
|
||||
|
||||
public IEnumerable<Tag> GetNewTags(Guid subject, FileEntry fileEntry)
|
||||
public IEnumerable<Tag> GetNewTags(Guid subject, FileEntry<T> fileEntry)
|
||||
{
|
||||
return GetNewTags(subject, new List<FileEntry>(1) { fileEntry });
|
||||
return GetNewTags(subject, new List<FileEntry<T>>(1) { fileEntry });
|
||||
}
|
||||
|
||||
public IEnumerable<Tag> GetNewTags(Guid subject, IEnumerable<FileEntry> fileEntries)
|
||||
public IEnumerable<Tag> GetNewTags(Guid subject, IEnumerable<FileEntry<T>> fileEntries)
|
||||
{
|
||||
List<Tag> result;
|
||||
|
||||
@ -414,14 +414,14 @@ namespace ASC.Files.Core.Data
|
||||
return result;
|
||||
}
|
||||
|
||||
public IEnumerable<Tag> GetNewTags(Guid subject, Folder parentFolder, bool deepSearch)
|
||||
public IEnumerable<Tag> GetNewTags(Guid subject, Folder<T> parentFolder, bool deepSearch)
|
||||
{
|
||||
if (parentFolder == null || parentFolder.ID == null)
|
||||
if (parentFolder == null || parentFolder.ID.Equals(default))
|
||||
throw new ArgumentException("folderId");
|
||||
|
||||
var result = new List<Tag>();
|
||||
|
||||
var monitorFolderIds = new[] { parentFolder.ID }.AsEnumerable();
|
||||
var monitorFolderIds = new object[] { parentFolder.ID }.AsEnumerable();
|
||||
|
||||
var getBaseSqlQuery = new Func<IQueryable<TagLinkData>>(() =>
|
||||
{
|
||||
@ -554,7 +554,7 @@ namespace ASC.Files.Core.Data
|
||||
|
||||
result.AddRange(FromQuery(newTagsForFolders));
|
||||
|
||||
var where = (deepSearch ? monitorFolderIds.ToArray() : new[] { parentFolder.ID })
|
||||
var where = (deepSearch ? monitorFolderIds.ToArray() : new object[] { parentFolder.ID })
|
||||
.Select(r => r.ToString())
|
||||
.ToList();
|
||||
|
||||
@ -613,7 +613,7 @@ namespace ASC.Files.Core.Data
|
||||
|
||||
private Tag ToTag(TagLinkData r)
|
||||
{
|
||||
var result = new Tag(r.Tag.Name, r.Tag.Flag, r.Tag.Owner, null, r.Link.TagCount)
|
||||
var result = new Tag(r.Tag.Name, r.Tag.Flag, r.Tag.Owner, r.Link.TagCount)
|
||||
{
|
||||
EntryId = MappingID(r.Link.EntryId),
|
||||
EntryType = r.Link.EntryType,
|
||||
@ -634,7 +634,8 @@ namespace ASC.Files.Core.Data
|
||||
{
|
||||
public static DIHelper AddTagDaoService(this DIHelper services)
|
||||
{
|
||||
services.TryAddScoped<ITagDao, TagDao>();
|
||||
services.TryAddScoped<ITagDao<int>, TagDao<int>>();
|
||||
services.TryAddScoped<TagDao<string>>();
|
||||
return services
|
||||
.AddUserManagerService()
|
||||
.AddFilesDbContextService()
|
||||
|
@ -1,17 +1,19 @@
|
||||
using System;
|
||||
using System.ComponentModel.DataAnnotations.Schema;
|
||||
|
||||
using ASC.Core.Common.EF;
|
||||
|
||||
namespace ASC.Files.Core.EF
|
||||
{
|
||||
[Table("files_thirdparty_account")]
|
||||
public class DbFilesThirdpartyAccount : IDbFile
|
||||
public class DbFilesThirdpartyAccount : BaseEntity, IDbFile, IDbSearch
|
||||
{
|
||||
public int Id { get; set; }
|
||||
|
||||
public string Provider { get; set; }
|
||||
|
||||
[Column("customer_title")]
|
||||
public string CustomerTitle { get; set; }
|
||||
public string Title { get; set; }
|
||||
|
||||
[Column("user_name")]
|
||||
public string UserName { get; set; }
|
||||
@ -33,5 +35,7 @@ namespace ASC.Files.Core.EF
|
||||
|
||||
[Column("tenant_id")]
|
||||
public int TenantId { get; set; }
|
||||
}
|
||||
|
||||
public override object[] GetKeys() => new object[] { Id };
|
||||
};
|
||||
}
|
||||
|
@ -40,23 +40,23 @@ namespace ASC.Files.Core
|
||||
{
|
||||
[DebuggerDisplay("{Id} into {FolderId}")]
|
||||
[Serializable]
|
||||
public class ChunkedUploadSession : CommonChunkedUploadSession
|
||||
public class ChunkedUploadSession<T> : CommonChunkedUploadSession
|
||||
{
|
||||
public string FolderId { get; set; }
|
||||
public T FolderId { get; set; }
|
||||
|
||||
public File File { get; set; }
|
||||
public File<T> File { get; set; }
|
||||
|
||||
public bool Encrypted { get; set; }
|
||||
|
||||
public ChunkedUploadSession(File file, long bytesTotal) : base(bytesTotal)
|
||||
public ChunkedUploadSession(File<T> file, long bytesTotal) : base(bytesTotal)
|
||||
{
|
||||
File = file;
|
||||
}
|
||||
|
||||
public override object Clone()
|
||||
{
|
||||
var clone = (ChunkedUploadSession)MemberwiseClone();
|
||||
clone.File = (File)File.Clone();
|
||||
var clone = (ChunkedUploadSession<T>)MemberwiseClone();
|
||||
clone.File = (File<T>)File.Clone();
|
||||
return clone;
|
||||
}
|
||||
}
|
||||
@ -73,7 +73,7 @@ namespace ASC.Files.Core
|
||||
}
|
||||
|
||||
|
||||
public object ToResponseObject(ChunkedUploadSession session, bool appendBreadCrumbs = false)
|
||||
public object ToResponseObject<T>(ChunkedUploadSession<T> session, bool appendBreadCrumbs = false)
|
||||
{
|
||||
var pathFolder = appendBreadCrumbs
|
||||
? EntryManager.GetBreadCrumbs(session.FolderId).Select(f =>
|
||||
@ -82,11 +82,11 @@ namespace ASC.Files.Core
|
||||
if (f == null)
|
||||
{
|
||||
Logger.ErrorFormat("GetBreadCrumbs {0} with null", session.FolderId);
|
||||
return string.Empty;
|
||||
return default;
|
||||
}
|
||||
return f.ID;
|
||||
})
|
||||
: new List<object> { session.FolderId };
|
||||
: new List<T> { session.FolderId };
|
||||
|
||||
return new
|
||||
{
|
||||
|
@ -58,9 +58,9 @@ namespace ASC.Web.Files.Core.Entries
|
||||
EncryptionLoginProvider = encryptionLoginProvider;
|
||||
}
|
||||
|
||||
public IEnumerable<string> GetAddresses(string fileId)
|
||||
public IEnumerable<string> GetAddresses<T>(T fileId)
|
||||
{
|
||||
var fileShares = FileSharing.GetSharedInfo(new ItemList<string> { string.Format("file_{0}", fileId) }).ToList();
|
||||
var fileShares = FileSharing.GetSharedInfo<T>(new ItemList<string> { string.Format("file_{0}", fileId) }).ToList();
|
||||
fileShares = fileShares.Where(share => !share.SubjectGroup && !share.SubjectId.Equals(FileConstant.ShareLinkId) && share.Share == FileShare.ReadWrite).ToList();
|
||||
var accountsString = fileShares.Select(share => EncryptionLoginProvider.GetAddress(share.SubjectId)).Where(address => !string.IsNullOrEmpty(address));
|
||||
return accountsString;
|
||||
|
@ -57,7 +57,7 @@ namespace ASC.Files.Core
|
||||
[Serializable]
|
||||
[DataContract(Name = "file", Namespace = "")]
|
||||
[DebuggerDisplay("{Title} ({ID} v{Version})")]
|
||||
public class File : FileEntry
|
||||
public class File<T> : FileEntry<T>
|
||||
{
|
||||
private FileStatus _status;
|
||||
|
||||
@ -75,7 +75,7 @@ namespace ASC.Files.Core
|
||||
FileConverter = fileConverter;
|
||||
}
|
||||
|
||||
public object FolderID { get; set; }
|
||||
public T FolderID { get; set; }
|
||||
|
||||
[DataMember(Name = "version")]
|
||||
public int Version { get; set; }
|
||||
@ -219,7 +219,21 @@ namespace ASC.Files.Core
|
||||
public FileUtility FileUtility { get; }
|
||||
public FileConverter FileConverter { get; }
|
||||
|
||||
public static string Serialize(File file)
|
||||
private T _folderIdDisplay;
|
||||
|
||||
[DataMember(Name = "folder_id")]
|
||||
public override T FolderIdDisplay
|
||||
{
|
||||
get
|
||||
{
|
||||
if (_folderIdDisplay != null) return _folderIdDisplay;
|
||||
|
||||
return FolderID;
|
||||
}
|
||||
set { _folderIdDisplay = value; }
|
||||
}
|
||||
|
||||
public static string Serialize(File<T> file)
|
||||
{
|
||||
using (var ms = new FileEntrySerializer().ToXml(file))
|
||||
{
|
||||
|
@ -32,10 +32,6 @@ using ASC.Web.Files.Classes;
|
||||
|
||||
namespace ASC.Files.Core
|
||||
{
|
||||
[DataContract(Name = "entry", Namespace = "")]
|
||||
[KnownType(typeof(Folder))]
|
||||
[KnownType(typeof(File))]
|
||||
[Serializable]
|
||||
public abstract class FileEntry : ICloneable
|
||||
{
|
||||
public FileEntry(Global global)
|
||||
@ -43,9 +39,6 @@ namespace ASC.Files.Core
|
||||
Global = global;
|
||||
}
|
||||
|
||||
[DataMember(Name = "id")]
|
||||
public object ID { get; set; }
|
||||
|
||||
[DataMember(Name = "title", IsRequired = true)]
|
||||
public virtual string Title { get; set; }
|
||||
|
||||
@ -97,25 +90,6 @@ namespace ASC.Files.Core
|
||||
|
||||
[DataMember(Name = "provider_key", EmitDefaultValue = false)]
|
||||
public string ProviderKey { get; set; }
|
||||
|
||||
[DataMember(Name = "folder_id")]
|
||||
public object FolderIdDisplay
|
||||
{
|
||||
get
|
||||
{
|
||||
if (_folderIdDisplay != null) return _folderIdDisplay;
|
||||
|
||||
var folder = this as Folder;
|
||||
if (folder != null) return folder.ParentFolderID;
|
||||
|
||||
var file = this as File;
|
||||
if (file != null) return file.FolderID;
|
||||
|
||||
return null;
|
||||
}
|
||||
set { _folderIdDisplay = value; }
|
||||
}
|
||||
|
||||
public bool ProviderEntry
|
||||
{
|
||||
get { return !string.IsNullOrEmpty(ProviderKey); }
|
||||
@ -129,33 +103,15 @@ namespace ASC.Files.Core
|
||||
|
||||
public Guid RootFolderCreator { get; set; }
|
||||
|
||||
public object RootFolderId { get; set; }
|
||||
|
||||
public abstract bool IsNew { get; set; }
|
||||
|
||||
public FileEntryType FileEntryType;
|
||||
|
||||
public string UniqID
|
||||
{
|
||||
get { return string.Format("{0}_{1}", GetType().Name.ToLower(), ID); }
|
||||
}
|
||||
|
||||
public Global Global { get; }
|
||||
|
||||
private string _modifiedByString;
|
||||
private string _createByString;
|
||||
private object _folderIdDisplay;
|
||||
|
||||
public override bool Equals(object obj)
|
||||
{
|
||||
var f = obj as FileEntry;
|
||||
return f != null && Equals(f.ID, ID);
|
||||
}
|
||||
|
||||
public override int GetHashCode()
|
||||
{
|
||||
return ID.GetHashCode();
|
||||
}
|
||||
|
||||
public override string ToString()
|
||||
{
|
||||
@ -167,4 +123,50 @@ namespace ASC.Files.Core
|
||||
return MemberwiseClone();
|
||||
}
|
||||
}
|
||||
|
||||
[DataContract(Name = "entry", Namespace = "")]
|
||||
[Serializable]
|
||||
public abstract class FileEntry<T> : FileEntry, ICloneable
|
||||
{
|
||||
public FileEntry(Global global) : base(global)
|
||||
{
|
||||
}
|
||||
|
||||
[DataMember(Name = "id")]
|
||||
public T ID { get; set; }
|
||||
|
||||
|
||||
[DataMember(Name = "folder_id")]
|
||||
public abstract T FolderIdDisplay
|
||||
{
|
||||
get;
|
||||
set;
|
||||
}
|
||||
|
||||
public T RootFolderId { get; set; }
|
||||
public string UniqID
|
||||
{
|
||||
get { return string.Format("{0}_{1}", GetType().Name.ToLower(), ID); }
|
||||
}
|
||||
|
||||
public override bool Equals(object obj)
|
||||
{
|
||||
return obj is FileEntry<T> f && Equals(f.ID, ID);
|
||||
}
|
||||
|
||||
public bool Equals(FileEntry<T> obj)
|
||||
{
|
||||
return Equals(obj.ID, ID);
|
||||
}
|
||||
|
||||
public override int GetHashCode()
|
||||
{
|
||||
return ID.GetHashCode();
|
||||
}
|
||||
|
||||
public override string ToString()
|
||||
{
|
||||
return Title;
|
||||
}
|
||||
}
|
||||
}
|
@ -52,11 +52,11 @@ namespace ASC.Files.Core
|
||||
|
||||
[DataContract(Name = "folder", Namespace = "")]
|
||||
[DebuggerDisplay("{Title} ({ID})")]
|
||||
public class Folder : FileEntry
|
||||
public class Folder<T> : FileEntry<T>
|
||||
{
|
||||
public FolderType FolderType { get; set; }
|
||||
|
||||
public object ParentFolderID { get; set; }
|
||||
public T ParentFolderID { get; set; }
|
||||
|
||||
[DataMember(Name = "total_files")]
|
||||
public int TotalFiles { get; set; }
|
||||
@ -79,6 +79,20 @@ namespace ASC.Files.Core
|
||||
set { NewForMe = Convert.ToInt32(value); }
|
||||
}
|
||||
|
||||
private T _folderIdDisplay;
|
||||
|
||||
[DataMember(Name = "folder_id")]
|
||||
public override T FolderIdDisplay
|
||||
{
|
||||
get
|
||||
{
|
||||
if (_folderIdDisplay != null) return _folderIdDisplay;
|
||||
|
||||
return ParentFolderID;
|
||||
}
|
||||
set { _folderIdDisplay = value; }
|
||||
}
|
||||
|
||||
public Folder(Global global)
|
||||
: base(global)
|
||||
{
|
||||
|
@ -60,38 +60,47 @@ namespace ASC.Files.Core
|
||||
}
|
||||
|
||||
public Tag(string name, TagType type, Guid owner)
|
||||
: this(name, type, owner, null, 0)
|
||||
: this(name, type, owner, 0)
|
||||
{
|
||||
}
|
||||
|
||||
public Tag(string name, TagType type, Guid owner, FileEntry entry, int count)
|
||||
public Tag(string name, TagType type, Guid owner, int count)
|
||||
{
|
||||
TagName = name;
|
||||
TagType = type;
|
||||
Owner = owner;
|
||||
Count = count;
|
||||
}
|
||||
|
||||
public Tag AddEntry<T>(FileEntry<T> entry)
|
||||
{
|
||||
if (entry != null)
|
||||
{
|
||||
EntryId = entry.ID;
|
||||
EntryType = entry.FileEntryType;
|
||||
}
|
||||
|
||||
return this;
|
||||
}
|
||||
|
||||
|
||||
public static Tag New(Guid owner, FileEntry entry)
|
||||
public static Tag New<T>(Guid owner, FileEntry<T> entry)
|
||||
{
|
||||
return New(owner, entry, 1);
|
||||
}
|
||||
|
||||
public static Tag New(Guid owner, FileEntry entry, int count)
|
||||
public static Tag New<T>(Guid owner, FileEntry<T> entry, int count)
|
||||
{
|
||||
return new Tag("new", TagType.New, owner, entry, count);
|
||||
return new Tag("new", TagType.New, owner, count).AddEntry(entry);
|
||||
}
|
||||
|
||||
public override bool Equals(object obj)
|
||||
{
|
||||
var f = obj as Tag;
|
||||
return f != null && f.Id == Id && f.EntryType == EntryType && Equals(f.EntryId, EntryId);
|
||||
return f != null && Equals(f);
|
||||
}
|
||||
public bool Equals(Tag f)
|
||||
{
|
||||
return f.Id == Id && f.EntryType == EntryType && Equals(f.EntryId, EntryId);
|
||||
}
|
||||
|
||||
public override int GetHashCode()
|
||||
|
File diff suppressed because it is too large
Load Diff
@ -29,7 +29,6 @@ using System.Collections.Generic;
|
||||
using System.Linq;
|
||||
|
||||
using ASC.Common;
|
||||
using ASC.Data.Storage;
|
||||
using ASC.Files.Core;
|
||||
using ASC.Files.Core.Data;
|
||||
using ASC.Files.Core.Security;
|
||||
@ -52,22 +51,24 @@ namespace ASC.Web.Files.Api
|
||||
GlobalStore = globalStore;
|
||||
}
|
||||
|
||||
public object RegisterBunch(string module, string bunch, string data)
|
||||
public T RegisterBunch<T>(string module, string bunch, string data)
|
||||
{
|
||||
var folderDao = GetFolderDao();
|
||||
var folderDao = DaoFactory.GetFolderDao<T>();
|
||||
return folderDao.GetFolderID(module, bunch, data, true);
|
||||
}
|
||||
|
||||
public IEnumerable<object> RegisterBunchFolders(string module, string bunch, IEnumerable<string> data)
|
||||
public IEnumerable<T> RegisterBunchFolders<T>(string module, string bunch, IEnumerable<string> data)
|
||||
{
|
||||
if (data == null)
|
||||
throw new ArgumentNullException("data");
|
||||
|
||||
data = data.ToList();
|
||||
if (!data.Any())
|
||||
return new List<object>();
|
||||
{
|
||||
return new List<T>();
|
||||
}
|
||||
|
||||
var folderDao = GetFolderDao();
|
||||
var folderDao = DaoFactory.GetFolderDao<T>();
|
||||
return folderDao.GetFolderIDs(module, bunch, data, true);
|
||||
}
|
||||
|
||||
@ -88,27 +89,6 @@ namespace ASC.Web.Files.Api
|
||||
}
|
||||
}
|
||||
|
||||
public IFileDao GetFileDao()
|
||||
{
|
||||
return DaoFactory.FileDao;
|
||||
}
|
||||
|
||||
public IFolderDao GetFolderDao()
|
||||
{
|
||||
return DaoFactory.FolderDao;
|
||||
}
|
||||
|
||||
public ITagDao TagDao()
|
||||
{
|
||||
return DaoFactory.TagDao;
|
||||
}
|
||||
|
||||
public IDataStore GetStore()
|
||||
{
|
||||
return GlobalStore.GetStore();
|
||||
}
|
||||
|
||||
|
||||
internal static IFileSecurity GetFileSecurity(string path)
|
||||
{
|
||||
if (string.IsNullOrEmpty(path)) return null;
|
||||
|
@ -40,8 +40,6 @@ using ASC.Web.Core.Files;
|
||||
|
||||
using Microsoft.Extensions.DependencyInjection;
|
||||
|
||||
using File = ASC.Files.Core.File;
|
||||
|
||||
namespace ASC.Web.Files.Core.Search
|
||||
{
|
||||
public sealed class FilesWrapper : WrapperWithDoc
|
||||
@ -93,12 +91,12 @@ namespace ASC.Web.Files.Core.Search
|
||||
DaoFactory = daoFactory;
|
||||
}
|
||||
|
||||
public static FilesWrapper GetFilesWrapper(IServiceProvider serviceProvider, File d, List<int> parentFolders = null)
|
||||
public static FilesWrapper GetFilesWrapper<T>(IServiceProvider serviceProvider, File<T> d, List<int> parentFolders = null)
|
||||
{
|
||||
var wrapper = serviceProvider.GetService<FilesWrapper>();
|
||||
var tenantManager = serviceProvider.GetService<TenantManager>();
|
||||
|
||||
wrapper.Id = (int)d.ID;
|
||||
wrapper.Id = Convert.ToInt32(d.ID);
|
||||
wrapper.Title = d.Title;
|
||||
wrapper.Version = d.Version;
|
||||
wrapper.Encrypted = d.Encrypted;
|
||||
@ -120,8 +118,8 @@ namespace ASC.Web.Files.Core.Search
|
||||
if (Encrypted) return null;
|
||||
if (!FileUtility.CanIndex(Title)) return null;
|
||||
|
||||
var fileDao = DaoFactory.FileDao;
|
||||
var file = ServiceProvider.GetService<File>();
|
||||
var fileDao = DaoFactory.GetFileDao<int>();
|
||||
var file = ServiceProvider.GetService<File<int>>();
|
||||
file.ID = Id;
|
||||
file.Title = Title;
|
||||
file.Version = Version;
|
||||
|
@ -45,13 +45,13 @@ namespace ASC.Web.Files.Core.Search
|
||||
|
||||
protected override string Table { get { return "files_folder"; } }
|
||||
|
||||
public static FoldersWrapper GetFolderWrapper(IServiceProvider serviceProvider, Folder d)
|
||||
public static FoldersWrapper GetFolderWrapper<T>(IServiceProvider serviceProvider, Folder<T> d)
|
||||
{
|
||||
var tenantManager = serviceProvider.GetService<TenantManager>();
|
||||
|
||||
return new FoldersWrapper
|
||||
{
|
||||
Id = (int)d.ID,
|
||||
Id = Convert.ToInt32(d.ID),
|
||||
Title = d.Title,
|
||||
TenantId = tenantManager.GetCurrentTenant().TenantId
|
||||
};
|
||||
|
@ -101,87 +101,87 @@ namespace ASC.Files.Core.Security
|
||||
FileSecurityCommon = fileSecurityCommon;
|
||||
}
|
||||
|
||||
public List<Tuple<FileEntry, bool>> CanRead(IEnumerable<FileEntry> entry, Guid userId)
|
||||
public List<Tuple<FileEntry<T>, bool>> CanRead<T>(IEnumerable<FileEntry<T>> entry, Guid userId)
|
||||
{
|
||||
return Can(entry, userId, FilesSecurityActions.Read);
|
||||
}
|
||||
|
||||
public bool CanRead(FileEntry entry, Guid userId)
|
||||
public bool CanRead<T>(FileEntry<T> entry, Guid userId)
|
||||
{
|
||||
return Can(entry, userId, FilesSecurityActions.Read);
|
||||
}
|
||||
|
||||
public bool CanComment(FileEntry entry, Guid userId)
|
||||
public bool CanComment<T>(FileEntry<T> entry, Guid userId)
|
||||
{
|
||||
return Can(entry, userId, FilesSecurityActions.Comment);
|
||||
}
|
||||
|
||||
public bool CanFillForms(FileEntry entry, Guid userId)
|
||||
public bool CanFillForms<T>(FileEntry<T> entry, Guid userId)
|
||||
{
|
||||
return Can(entry, userId, FilesSecurityActions.FillForms);
|
||||
}
|
||||
|
||||
public bool CanReview(FileEntry entry, Guid userId)
|
||||
public bool CanReview<T>(FileEntry<T> entry, Guid userId)
|
||||
{
|
||||
return Can(entry, userId, FilesSecurityActions.Review);
|
||||
}
|
||||
|
||||
public bool CanCreate(FileEntry entry, Guid userId)
|
||||
public bool CanCreate<T>(FileEntry<T> entry, Guid userId)
|
||||
{
|
||||
return Can(entry, userId, FilesSecurityActions.Create);
|
||||
}
|
||||
|
||||
public bool CanEdit(FileEntry entry, Guid userId)
|
||||
public bool CanEdit<T>(FileEntry<T> entry, Guid userId)
|
||||
{
|
||||
return Can(entry, userId, FilesSecurityActions.Edit);
|
||||
}
|
||||
|
||||
public bool CanDelete(FileEntry entry, Guid userId)
|
||||
public bool CanDelete<T>(FileEntry<T> entry, Guid userId)
|
||||
{
|
||||
return Can(entry, userId, FilesSecurityActions.Delete);
|
||||
}
|
||||
|
||||
public bool CanRead(FileEntry entry)
|
||||
public bool CanRead<T>(FileEntry<T> entry)
|
||||
{
|
||||
return CanRead(entry, AuthContext.CurrentAccount.ID);
|
||||
}
|
||||
|
||||
public bool CanComment(FileEntry entry)
|
||||
public bool CanComment<T>(FileEntry<T> entry)
|
||||
{
|
||||
return CanComment(entry, AuthContext.CurrentAccount.ID);
|
||||
}
|
||||
|
||||
public bool CanFillForms(FileEntry entry)
|
||||
public bool CanFillForms<T>(FileEntry<T> entry)
|
||||
{
|
||||
return CanFillForms(entry, AuthContext.CurrentAccount.ID);
|
||||
}
|
||||
|
||||
public bool CanReview(FileEntry entry)
|
||||
public bool CanReview<T>(FileEntry<T> entry)
|
||||
{
|
||||
return CanReview(entry, AuthContext.CurrentAccount.ID);
|
||||
}
|
||||
|
||||
public bool CanCreate(FileEntry entry)
|
||||
public bool CanCreate<T>(FileEntry<T> entry)
|
||||
{
|
||||
return CanCreate(entry, AuthContext.CurrentAccount.ID);
|
||||
}
|
||||
|
||||
public bool CanEdit(FileEntry entry)
|
||||
public bool CanEdit<T>(FileEntry<T> entry)
|
||||
{
|
||||
return CanEdit(entry, AuthContext.CurrentAccount.ID);
|
||||
}
|
||||
|
||||
public bool CanDelete(FileEntry entry)
|
||||
public bool CanDelete<T>(FileEntry<T> entry)
|
||||
{
|
||||
return CanDelete(entry, AuthContext.CurrentAccount.ID);
|
||||
}
|
||||
|
||||
public IEnumerable<Guid> WhoCanRead(FileEntry entry)
|
||||
public IEnumerable<Guid> WhoCanRead<T>(FileEntry<T> entry)
|
||||
{
|
||||
return WhoCan(entry, FilesSecurityActions.Read);
|
||||
}
|
||||
|
||||
private IEnumerable<Guid> WhoCan(FileEntry entry, FilesSecurityActions action)
|
||||
private IEnumerable<Guid> WhoCan<T>(FileEntry<T> entry, FilesSecurityActions action)
|
||||
{
|
||||
var shares = GetShares(entry);
|
||||
|
||||
@ -236,7 +236,7 @@ namespace ASC.Files.Core.Security
|
||||
case FolderType.BUNCH:
|
||||
if (action == FilesSecurityActions.Read)
|
||||
{
|
||||
var folderDao = daoFactory.FolderDao;
|
||||
var folderDao = daoFactory.GetFolderDao<T>();
|
||||
var root = folderDao.GetFolder(entry.RootFolderId);
|
||||
if (root != null)
|
||||
{
|
||||
@ -280,59 +280,54 @@ namespace ASC.Files.Core.Security
|
||||
.ToList();
|
||||
}
|
||||
|
||||
public IEnumerable<FileEntry> FilterRead(IEnumerable<FileEntry> entries)
|
||||
public IEnumerable<File<T>> FilterRead<T>(IEnumerable<File<T>> entries)
|
||||
{
|
||||
return Filter(entries, FilesSecurityActions.Read, AuthContext.CurrentAccount.ID);
|
||||
return Filter(entries.Cast<FileEntry<T>>(), FilesSecurityActions.Read, AuthContext.CurrentAccount.ID).Cast<File<T>>();
|
||||
}
|
||||
|
||||
public IEnumerable<File> FilterRead(IEnumerable<File> entries)
|
||||
public IEnumerable<Folder<T>> FilterRead<T>(IEnumerable<Folder<T>> entries)
|
||||
{
|
||||
return Filter(entries.Cast<FileEntry>(), FilesSecurityActions.Read, AuthContext.CurrentAccount.ID).Cast<File>();
|
||||
return Filter(entries.Cast<FileEntry<T>>(), FilesSecurityActions.Read, AuthContext.CurrentAccount.ID).Cast<Folder<T>>();
|
||||
}
|
||||
|
||||
public IEnumerable<Folder> FilterRead(IEnumerable<Folder> entries)
|
||||
public IEnumerable<File<T>> FilterEdit<T>(IEnumerable<File<T>> entries)
|
||||
{
|
||||
return Filter(entries.Cast<FileEntry>(), FilesSecurityActions.Read, AuthContext.CurrentAccount.ID).Cast<Folder>();
|
||||
return Filter(entries.Cast<FileEntry<T>>(), FilesSecurityActions.Edit, AuthContext.CurrentAccount.ID).Cast<File<T>>();
|
||||
}
|
||||
|
||||
public IEnumerable<File> FilterEdit(IEnumerable<File> entries)
|
||||
public IEnumerable<Folder<T>> FilterEdit<T>(IEnumerable<Folder<T>> entries)
|
||||
{
|
||||
return Filter(entries.Cast<FileEntry>(), FilesSecurityActions.Edit, AuthContext.CurrentAccount.ID).Cast<File>();
|
||||
return Filter(entries.Cast<FileEntry<T>>(), FilesSecurityActions.Edit, AuthContext.CurrentAccount.ID).Cast<Folder<T>>();
|
||||
}
|
||||
|
||||
public IEnumerable<Folder> FilterEdit(IEnumerable<Folder> entries)
|
||||
{
|
||||
return Filter(entries.Cast<FileEntry>(), FilesSecurityActions.Edit, AuthContext.CurrentAccount.ID).Cast<Folder>();
|
||||
}
|
||||
|
||||
private bool Can(FileEntry entry, Guid userId, FilesSecurityActions action)
|
||||
private bool Can<T>(FileEntry<T> entry, Guid userId, FilesSecurityActions action)
|
||||
{
|
||||
return Filter(new[] { entry }, action, userId).Any();
|
||||
}
|
||||
|
||||
private List<Tuple<FileEntry, bool>> Can(IEnumerable<FileEntry> entry, Guid userId, FilesSecurityActions action)
|
||||
private List<Tuple<FileEntry<T>, bool>> Can<T>(IEnumerable<FileEntry<T>> entry, Guid userId, FilesSecurityActions action)
|
||||
{
|
||||
var filtres = Filter(entry, action, userId);
|
||||
return entry.Select(r => new Tuple<FileEntry, bool>(r, filtres.Any(a => a.ID.Equals(r.ID)))).ToList();
|
||||
return entry.Select(r => new Tuple<FileEntry<T>, bool>(r, filtres.Any(a => a.ID.Equals(r.ID)))).ToList();
|
||||
}
|
||||
|
||||
private IEnumerable<FileEntry> Filter(IEnumerable<FileEntry> entries, FilesSecurityActions action, Guid userId)
|
||||
private IEnumerable<FileEntry<T>> Filter<T>(IEnumerable<FileEntry<T>> entries, FilesSecurityActions action, Guid userId)
|
||||
{
|
||||
if (entries == null || !entries.Any()) return Enumerable.Empty<FileEntry>();
|
||||
if (entries == null || !entries.Any()) return Enumerable.Empty<FileEntry<T>>();
|
||||
|
||||
var user = UserManager.GetUsers(userId);
|
||||
var isOutsider = user.IsOutsider(UserManager);
|
||||
|
||||
if (isOutsider && action != FilesSecurityActions.Read) return Enumerable.Empty<FileEntry>();
|
||||
if (isOutsider && action != FilesSecurityActions.Read) return Enumerable.Empty<FileEntry<T>>();
|
||||
|
||||
entries = entries.Where(f => f != null).ToList();
|
||||
var result = new List<FileEntry>(entries.Count());
|
||||
var result = new List<FileEntry<T>>(entries.Count());
|
||||
|
||||
// save entries order
|
||||
var order = entries.Select((f, i) => new { Id = f.UniqID, Pos = i }).ToDictionary(e => e.Id, e => e.Pos);
|
||||
|
||||
// common or my files
|
||||
Func<FileEntry, bool> filter =
|
||||
Func<FileEntry<T>, bool> filter =
|
||||
f => f.RootFolderType == FolderType.COMMON ||
|
||||
f.RootFolderType == FolderType.USER ||
|
||||
f.RootFolderType == FolderType.SHARE ||
|
||||
@ -358,13 +353,13 @@ namespace ASC.Files.Core.Security
|
||||
continue;
|
||||
}
|
||||
|
||||
if (action != FilesSecurityActions.Read && e.FileEntryType == FileEntryType.Folder && ((Folder)e).FolderType == FolderType.Projects)
|
||||
if (action != FilesSecurityActions.Read && e.FileEntryType == FileEntryType.Folder && ((Folder<T>)e).FolderType == FolderType.Projects)
|
||||
{
|
||||
// Root Projects folder read-only
|
||||
continue;
|
||||
}
|
||||
|
||||
if (action != FilesSecurityActions.Read && e.FileEntryType == FileEntryType.Folder && ((Folder)e).FolderType == FolderType.SHARE)
|
||||
if (action != FilesSecurityActions.Read && e.FileEntryType == FileEntryType.Folder && ((Folder<T>)e).FolderType == FolderType.SHARE)
|
||||
{
|
||||
// Root Share folder read-only
|
||||
continue;
|
||||
@ -383,7 +378,7 @@ namespace ASC.Files.Core.Security
|
||||
}
|
||||
|
||||
if (DefaultCommonShare == FileShare.Read && action == FilesSecurityActions.Read && e.FileEntryType == FileEntryType.Folder &&
|
||||
((Folder)e).FolderType == FolderType.COMMON)
|
||||
((Folder<T>)e).FolderType == FolderType.COMMON)
|
||||
{
|
||||
// all can read Common folder
|
||||
result.Add(e);
|
||||
@ -391,7 +386,7 @@ namespace ASC.Files.Core.Security
|
||||
}
|
||||
|
||||
if (action == FilesSecurityActions.Read && e.FileEntryType == FileEntryType.Folder &&
|
||||
((Folder)e).FolderType == FolderType.SHARE)
|
||||
((Folder<T>)e).FolderType == FolderType.SHARE)
|
||||
{
|
||||
// all can read Share folder
|
||||
result.Add(e);
|
||||
@ -421,7 +416,7 @@ namespace ASC.Files.Core.Security
|
||||
if (ace == null)
|
||||
{
|
||||
// share on parent folders
|
||||
ace = shares.Where(r => Equals(r.EntryId, ((File)e).FolderID) && r.EntryType == FileEntryType.Folder)
|
||||
ace = shares.Where(r => Equals(r.EntryId, ((File<T>)e).FolderID) && r.EntryType == FileEntryType.Folder)
|
||||
.OrderBy(r => r, new SubjectComparer(subjects))
|
||||
.ThenBy(r => r.Level)
|
||||
.ThenByDescending(r => r.Share, new FileShareRecord.ShareComparer())
|
||||
@ -445,7 +440,7 @@ namespace ASC.Files.Core.Security
|
||||
else if (action == FilesSecurityActions.Review && (e.Access == FileShare.Review || e.Access == FileShare.ReadWrite)) result.Add(e);
|
||||
else if (action == FilesSecurityActions.Edit && e.Access == FileShare.ReadWrite) result.Add(e);
|
||||
else if (action == FilesSecurityActions.Create && e.Access == FileShare.ReadWrite) result.Add(e);
|
||||
else if (e.Access != FileShare.Restrict && e.CreateBy == userId && (e.FileEntryType == FileEntryType.File || ((Folder)e).FolderType != FolderType.COMMON)) result.Add(e);
|
||||
else if (e.Access != FileShare.Restrict && e.CreateBy == userId && (e.FileEntryType == FileEntryType.File || ((Folder<T>)e).FolderType != FolderType.COMMON)) result.Add(e);
|
||||
|
||||
if (e.CreateBy == userId) e.Access = FileShare.None; //HACK: for client
|
||||
}
|
||||
@ -455,7 +450,7 @@ namespace ASC.Files.Core.Security
|
||||
filter = f => f.RootFolderType == FolderType.BUNCH;
|
||||
if (entries.Any(filter))
|
||||
{
|
||||
var folderDao = daoFactory.FolderDao;
|
||||
var folderDao = daoFactory.GetFolderDao<T>();
|
||||
var filteredEntries = entries.Where(filter).ToList();
|
||||
var roots = filteredEntries
|
||||
.Select(r => r.RootFolderId)
|
||||
@ -528,7 +523,7 @@ namespace ASC.Files.Core.Security
|
||||
filter = f => f.RootFolderType == FolderType.TRASH;
|
||||
if ((action == FilesSecurityActions.Read || action == FilesSecurityActions.Delete) && entries.Any(filter))
|
||||
{
|
||||
var folderDao = daoFactory.FolderDao;
|
||||
var folderDao = daoFactory.GetFolderDao<T>();
|
||||
var mytrashId = folderDao.GetFolderIDTrash(false, userId);
|
||||
if (!Equals(mytrashId, 0))
|
||||
{
|
||||
@ -548,9 +543,9 @@ namespace ASC.Files.Core.Security
|
||||
return result;
|
||||
}
|
||||
|
||||
public void Share(object entryId, FileEntryType entryType, Guid @for, FileShare share)
|
||||
public void Share<T>(T entryId, FileEntryType entryType, Guid @for, FileShare share)
|
||||
{
|
||||
var securityDao = daoFactory.SecurityDao;
|
||||
var securityDao = daoFactory.GetSecurityDao<T>();
|
||||
var r = new FileShareRecord
|
||||
{
|
||||
Tenant = TenantManager.GetCurrentTenant().TenantId,
|
||||
@ -563,21 +558,21 @@ namespace ASC.Files.Core.Security
|
||||
securityDao.SetShare(r);
|
||||
}
|
||||
|
||||
public IEnumerable<FileShareRecord> GetShares(IEnumerable<FileEntry> entries)
|
||||
public IEnumerable<FileShareRecord> GetShares<T>(IEnumerable<FileEntry<T>> entries)
|
||||
{
|
||||
return daoFactory.SecurityDao.GetShares(entries);
|
||||
return daoFactory.GetSecurityDao<T>().GetShares(entries);
|
||||
}
|
||||
|
||||
public IEnumerable<FileShareRecord> GetShares(FileEntry entry)
|
||||
public IEnumerable<FileShareRecord> GetShares<T>(FileEntry<T> entry)
|
||||
{
|
||||
return daoFactory.SecurityDao.GetShares(entry);
|
||||
return daoFactory.GetSecurityDao<T>().GetShares(entry);
|
||||
}
|
||||
|
||||
public List<FileEntry> GetSharesForMe(FilterType filterType, bool subjectGroup, Guid subjectID, string searchText = "", bool searchInContent = false, bool withSubfolders = false)
|
||||
public List<FileEntry<T>> GetSharesForMe<T>(FilterType filterType, bool subjectGroup, Guid subjectID, string searchText = "", bool searchInContent = false, bool withSubfolders = false)
|
||||
{
|
||||
var folderDao = daoFactory.FolderDao;
|
||||
var fileDao = daoFactory.FileDao;
|
||||
var securityDao = daoFactory.SecurityDao;
|
||||
var folderDao = daoFactory.GetFolderDao<T>();
|
||||
var fileDao = daoFactory.GetFileDao<T>();
|
||||
var securityDao = daoFactory.GetSecurityDao<T>();
|
||||
var subjects = GetUserSubjects(AuthContext.CurrentAccount.ID);
|
||||
|
||||
var records = securityDao.GetShares(subjects);
|
||||
@ -606,18 +601,18 @@ namespace ASC.Files.Core.Security
|
||||
}
|
||||
}
|
||||
|
||||
var entries = new List<FileEntry>();
|
||||
var entries = new List<FileEntry<T>>();
|
||||
|
||||
if (filterType != FilterType.FoldersOnly)
|
||||
{
|
||||
var files = fileDao.GetFilesForShare(fileIds.Keys.ToArray(), filterType, subjectGroup, subjectID, searchText, searchInContent);
|
||||
var files = fileDao.GetFilesForShare(fileIds.Keys.Select(r => (T)r).ToArray(), filterType, subjectGroup, subjectID, searchText, searchInContent);
|
||||
|
||||
files.ForEach(x =>
|
||||
{
|
||||
if (fileIds.ContainsKey(x.ID))
|
||||
{
|
||||
x.Access = fileIds[x.ID];
|
||||
x.FolderIdDisplay = GlobalFolder.GetFolderShare(folderDao);
|
||||
x.FolderIdDisplay = GlobalFolder.GetFolderShare<T>(daoFactory);
|
||||
}
|
||||
});
|
||||
|
||||
@ -626,7 +621,7 @@ namespace ASC.Files.Core.Security
|
||||
|
||||
if (filterType == FilterType.None || filterType == FilterType.FoldersOnly)
|
||||
{
|
||||
var folders = folderDao.GetFolders(folderIds.Keys.ToArray(), filterType, subjectGroup, subjectID, searchText, withSubfolders, false);
|
||||
var folders = folderDao.GetFolders(folderIds.Keys.Select(r => (T)r).ToArray(), filterType, subjectGroup, subjectID, searchText, withSubfolders, false);
|
||||
|
||||
if (withSubfolders)
|
||||
{
|
||||
@ -637,16 +632,16 @@ namespace ASC.Files.Core.Security
|
||||
if (folderIds.ContainsKey(x.ID))
|
||||
{
|
||||
x.Access = folderIds[x.ID];
|
||||
x.FolderIdDisplay = GlobalFolder.GetFolderShare(folderDao);
|
||||
x.FolderIdDisplay = GlobalFolder.GetFolderShare<T>(daoFactory);
|
||||
}
|
||||
});
|
||||
|
||||
entries.AddRange(folders.Cast<FileEntry>());
|
||||
entries.AddRange(folders.Cast<FileEntry<T>>());
|
||||
}
|
||||
|
||||
if (filterType != FilterType.FoldersOnly && withSubfolders)
|
||||
{
|
||||
var filesInSharedFolders = fileDao.GetFiles(folderIds.Keys.ToArray(), filterType, subjectGroup, subjectID, searchText, searchInContent);
|
||||
var filesInSharedFolders = fileDao.GetFiles(folderIds.Keys.Select(r => (T)r).ToArray(), filterType, subjectGroup, subjectID, searchText, searchInContent);
|
||||
filesInSharedFolders = FilterRead(filesInSharedFolders).ToList();
|
||||
entries.AddRange(filesInSharedFolders);
|
||||
entries = entries.Distinct().ToList();
|
||||
@ -684,9 +679,9 @@ namespace ASC.Files.Core.Security
|
||||
return entries.Where(x => string.IsNullOrEmpty(x.Error)).ToList();
|
||||
}
|
||||
|
||||
public void RemoveSubject(Guid subject)
|
||||
public void RemoveSubject<T>(Guid subject)
|
||||
{
|
||||
daoFactory.SecurityDao.RemoveSubject(subject);
|
||||
daoFactory.GetSecurityDao<T>().RemoveSubject(subject);
|
||||
}
|
||||
|
||||
public List<Guid> GetUserSubjects(Guid userId)
|
||||
|
@ -31,20 +31,20 @@ namespace ASC.Files.Core.Security
|
||||
{
|
||||
public interface IFileSecurity
|
||||
{
|
||||
bool CanRead(FileEntry entry, Guid userId);
|
||||
bool CanRead<T>(FileEntry<T> entry, Guid userId);
|
||||
|
||||
bool CanComment(FileEntry entry, Guid userId);
|
||||
bool CanComment<T>(FileEntry<T> entry, Guid userId);
|
||||
|
||||
bool CanReview(FileEntry entry, Guid userId);
|
||||
bool CanReview<T>(FileEntry<T> entry, Guid userId);
|
||||
|
||||
bool CanFillForms(FileEntry entry, Guid userId);
|
||||
bool CanFillForms<T>(FileEntry<T> entry, Guid userId);
|
||||
|
||||
bool CanCreate(FileEntry entry, Guid userId);
|
||||
bool CanCreate<T>(FileEntry<T> entry, Guid userId);
|
||||
|
||||
bool CanEdit(FileEntry entry, Guid userId);
|
||||
bool CanEdit<T>(FileEntry<T> entry, Guid userId);
|
||||
|
||||
bool CanDelete(FileEntry entry, Guid userId);
|
||||
bool CanDelete<T>(FileEntry<T> entry, Guid userId);
|
||||
|
||||
IEnumerable<Guid> WhoCanRead(FileEntry entry);
|
||||
IEnumerable<Guid> WhoCanRead<T>(FileEntry<T> entry);
|
||||
}
|
||||
}
|
@ -29,21 +29,21 @@ using System.Collections.Generic;
|
||||
|
||||
namespace ASC.Files.Core.Security
|
||||
{
|
||||
public interface ISecurityDao
|
||||
public interface ISecurityDao<T>
|
||||
{
|
||||
void SetShare(FileShareRecord r);
|
||||
|
||||
IEnumerable<FileShareRecord> GetShares(IEnumerable<Guid> subjects);
|
||||
|
||||
IEnumerable<FileShareRecord> GetShares(IEnumerable<FileEntry> entry);
|
||||
IEnumerable<FileShareRecord> GetShares(IEnumerable<FileEntry<T>> entry);
|
||||
|
||||
IEnumerable<FileShareRecord> GetShares(FileEntry entry);
|
||||
IEnumerable<FileShareRecord> GetShares(FileEntry<T> entry);
|
||||
|
||||
void RemoveSubject(Guid subject);
|
||||
|
||||
IEnumerable<FileShareRecord> GetPureShareRecords(IEnumerable<FileEntry> entries);
|
||||
IEnumerable<FileShareRecord> GetPureShareRecords(IEnumerable<FileEntry<T>> entries);
|
||||
|
||||
IEnumerable<FileShareRecord> GetPureShareRecords(FileEntry entry);
|
||||
IEnumerable<FileShareRecord> GetPureShareRecords(FileEntry<T> entry);
|
||||
|
||||
void DeleteShareRecords(IEnumerable<FileShareRecord> records);
|
||||
|
||||
|
9
products/ASC.Files/Server/Core/Thirdparty/BaseProviderInfo.cs
vendored
Normal file
9
products/ASC.Files/Server/Core/Thirdparty/BaseProviderInfo.cs
vendored
Normal file
@ -0,0 +1,9 @@
|
||||
namespace ASC.Files.Core.Thirdparty
|
||||
{
|
||||
public class BaseProviderInfo<T> where T : IProviderInfo
|
||||
{
|
||||
public T ProviderInfo { get; set; }
|
||||
public string Path { get; set; }
|
||||
public string PathPrefix { get; set; }
|
||||
}
|
||||
}
|
319
products/ASC.Files/Server/Core/Thirdparty/Box/BoxDaoBase.cs
vendored
Normal file
319
products/ASC.Files/Server/Core/Thirdparty/Box/BoxDaoBase.cs
vendored
Normal file
@ -0,0 +1,319 @@
|
||||
/*
|
||||
*
|
||||
* (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;
|
||||
using System.Globalization;
|
||||
using System.Linq;
|
||||
using System.Text.RegularExpressions;
|
||||
|
||||
using ASC.Common.Logging;
|
||||
using ASC.Core;
|
||||
using ASC.Core.Common.EF;
|
||||
using ASC.Core.Tenants;
|
||||
using ASC.Files.Core;
|
||||
using ASC.Files.Core.EF;
|
||||
using ASC.Web.Core.Files;
|
||||
using ASC.Web.Files.Classes;
|
||||
using ASC.Web.Studio.Core;
|
||||
|
||||
using Box.V2.Models;
|
||||
|
||||
using Microsoft.Extensions.Options;
|
||||
|
||||
namespace ASC.Files.Thirdparty.Box
|
||||
{
|
||||
internal abstract class BoxDaoBase : ThirdPartyProviderDao<BoxProviderInfo>
|
||||
{
|
||||
public override string Id { get => "box"; }
|
||||
|
||||
public BoxDaoBase(
|
||||
IServiceProvider serviceProvider,
|
||||
UserManager userManager,
|
||||
TenantManager tenantManager,
|
||||
TenantUtil tenantUtil,
|
||||
DbContextManager<FilesDbContext> dbContextManager,
|
||||
SetupInfo setupInfo,
|
||||
IOptionsMonitor<ILog> monitor,
|
||||
FileUtility fileUtility) : base(serviceProvider, userManager, tenantManager, tenantUtil, dbContextManager, setupInfo, monitor, fileUtility)
|
||||
{
|
||||
}
|
||||
|
||||
|
||||
protected static string MakeBoxId(object entryId)
|
||||
{
|
||||
var id = Convert.ToString(entryId, CultureInfo.InvariantCulture);
|
||||
return string.IsNullOrEmpty(id)
|
||||
? "0"
|
||||
: id.TrimStart('/');
|
||||
}
|
||||
|
||||
protected static string GetParentFolderId(BoxItem boxItem)
|
||||
{
|
||||
return boxItem == null || boxItem.Parent == null
|
||||
? null
|
||||
: boxItem.Parent.Id;
|
||||
}
|
||||
|
||||
protected string MakeId(BoxItem boxItem)
|
||||
{
|
||||
var path = string.Empty;
|
||||
if (boxItem != null)
|
||||
{
|
||||
path = boxItem.Id;
|
||||
}
|
||||
|
||||
return MakeId(path);
|
||||
}
|
||||
|
||||
protected override string MakeId(string path = null)
|
||||
{
|
||||
return string.Format("{0}{1}", PathPrefix, string.IsNullOrEmpty(path) || path == "0" ? "" : ("-|" + path.TrimStart('/')));
|
||||
}
|
||||
|
||||
protected string MakeFolderTitle(BoxFolder boxFolder)
|
||||
{
|
||||
if (boxFolder == null || IsRoot(boxFolder))
|
||||
{
|
||||
return ProviderInfo.CustomerTitle;
|
||||
}
|
||||
|
||||
return Global.ReplaceInvalidCharsAndTruncate(boxFolder.Name);
|
||||
}
|
||||
|
||||
protected string MakeFileTitle(BoxFile boxFile)
|
||||
{
|
||||
if (boxFile == null || string.IsNullOrEmpty(boxFile.Name))
|
||||
{
|
||||
return ProviderInfo.ProviderKey;
|
||||
}
|
||||
|
||||
return Global.ReplaceInvalidCharsAndTruncate(boxFile.Name);
|
||||
}
|
||||
|
||||
protected Folder<string> ToFolder(BoxFolder boxFolder)
|
||||
{
|
||||
if (boxFolder == null) return null;
|
||||
if (boxFolder is ErrorFolder)
|
||||
{
|
||||
//Return error entry
|
||||
return ToErrorFolder(boxFolder as ErrorFolder);
|
||||
}
|
||||
|
||||
var isRoot = IsRoot(boxFolder);
|
||||
|
||||
var folder = GetFolder();
|
||||
|
||||
folder.ID = MakeId(boxFolder.Id);
|
||||
folder.ParentFolderID = isRoot ? null : MakeId(GetParentFolderId(boxFolder));
|
||||
folder.CreateOn = isRoot ? ProviderInfo.CreateOn : (boxFolder.CreatedAt ?? default);
|
||||
folder.ModifiedOn = isRoot ? ProviderInfo.CreateOn : (boxFolder.ModifiedAt ?? default);
|
||||
|
||||
folder.Title = MakeFolderTitle(boxFolder);
|
||||
folder.TotalFiles = boxFolder.ItemCollection != null ? boxFolder.ItemCollection.Entries.Count(item => item is BoxFile) : 0;
|
||||
folder.TotalSubFolders = boxFolder.ItemCollection != null ? boxFolder.ItemCollection.Entries.Count(item => item is BoxFolder) : 0;
|
||||
|
||||
if (folder.CreateOn != DateTime.MinValue && folder.CreateOn.Kind == DateTimeKind.Utc)
|
||||
folder.CreateOn = TenantUtil.DateTimeFromUtc(folder.CreateOn);
|
||||
|
||||
if (folder.ModifiedOn != DateTime.MinValue && folder.ModifiedOn.Kind == DateTimeKind.Utc)
|
||||
folder.ModifiedOn = TenantUtil.DateTimeFromUtc(folder.ModifiedOn);
|
||||
|
||||
return folder;
|
||||
}
|
||||
|
||||
protected static bool IsRoot(BoxFolder boxFolder)
|
||||
{
|
||||
return boxFolder.Id == "0";
|
||||
}
|
||||
|
||||
private File<string> ToErrorFile(ErrorFile boxFile)
|
||||
{
|
||||
if (boxFile == null) return null;
|
||||
|
||||
var file = GetErrorFile(new ErrorEntry(boxFile.Error, boxFile.ErrorId));
|
||||
|
||||
file.Title = MakeFileTitle(boxFile);
|
||||
|
||||
return file;
|
||||
}
|
||||
|
||||
private Folder<string> ToErrorFolder(ErrorFolder boxFolder)
|
||||
{
|
||||
if (boxFolder == null) return null;
|
||||
|
||||
var folder = GetErrorFolder(new ErrorEntry(boxFolder.Error, boxFolder.ErrorId));
|
||||
|
||||
folder.Title = MakeFolderTitle(boxFolder);
|
||||
|
||||
return folder;
|
||||
}
|
||||
|
||||
public File<string> ToFile(BoxFile boxFile)
|
||||
{
|
||||
if (boxFile == null) return null;
|
||||
|
||||
if (boxFile is ErrorFile)
|
||||
{
|
||||
//Return error entry
|
||||
return ToErrorFile(boxFile as ErrorFile);
|
||||
}
|
||||
|
||||
var file = GetFile();
|
||||
|
||||
file.ID = MakeId(boxFile.Id);
|
||||
file.ContentLength = boxFile.Size.HasValue ? (long)boxFile.Size : 0;
|
||||
file.CreateOn = boxFile.CreatedAt.HasValue ? TenantUtil.DateTimeFromUtc(boxFile.CreatedAt.Value) : default;
|
||||
file.FolderID = MakeId(GetParentFolderId(boxFile));
|
||||
file.ModifiedOn = boxFile.ModifiedAt.HasValue ? TenantUtil.DateTimeFromUtc(boxFile.ModifiedAt.Value) : default;
|
||||
file.NativeAccessor = boxFile;
|
||||
file.Title = MakeFileTitle(boxFile);
|
||||
|
||||
return file;
|
||||
}
|
||||
|
||||
public Folder<string> GetRootFolder(string folderId)
|
||||
{
|
||||
return ToFolder(GetBoxFolder("0"));
|
||||
}
|
||||
|
||||
protected BoxFolder GetBoxFolder(string folderId)
|
||||
{
|
||||
var boxFolderId = MakeBoxId(folderId);
|
||||
try
|
||||
{
|
||||
var folder = ProviderInfo.GetBoxFolder(boxFolderId);
|
||||
return folder;
|
||||
}
|
||||
catch (Exception ex)
|
||||
{
|
||||
return new ErrorFolder(ex, boxFolderId);
|
||||
}
|
||||
}
|
||||
|
||||
protected BoxFile GetBoxFile(string fileId)
|
||||
{
|
||||
var boxFileId = MakeBoxId(fileId);
|
||||
try
|
||||
{
|
||||
var file = ProviderInfo.GetBoxFile(boxFileId);
|
||||
return file;
|
||||
}
|
||||
catch (Exception ex)
|
||||
{
|
||||
return new ErrorFile(ex, boxFileId);
|
||||
}
|
||||
}
|
||||
|
||||
protected IEnumerable<string> GetChildren(string folderId)
|
||||
{
|
||||
return GetBoxItems(folderId).Select(entry => MakeId(entry.Id));
|
||||
}
|
||||
|
||||
protected List<BoxItem> GetBoxItems(string parentId, bool? folder = null)
|
||||
{
|
||||
var boxFolderId = MakeBoxId(parentId);
|
||||
var items = ProviderInfo.GetBoxItems(boxFolderId);
|
||||
|
||||
if (folder.HasValue)
|
||||
{
|
||||
if (folder.Value)
|
||||
{
|
||||
return items.Where(i => i is BoxFolder).ToList();
|
||||
}
|
||||
|
||||
return items.Where(i => i is BoxFile).ToList();
|
||||
}
|
||||
|
||||
return items;
|
||||
}
|
||||
|
||||
protected sealed class ErrorFolder : BoxFolder
|
||||
{
|
||||
public string Error { get; set; }
|
||||
|
||||
public string ErrorId { get; private set; }
|
||||
|
||||
|
||||
public ErrorFolder(Exception e, object id)
|
||||
{
|
||||
ErrorId = id.ToString();
|
||||
if (e != null)
|
||||
{
|
||||
Error = e.Message;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
protected sealed class ErrorFile : BoxFile
|
||||
{
|
||||
public string Error { get; set; }
|
||||
|
||||
public string ErrorId { get; private set; }
|
||||
|
||||
|
||||
public ErrorFile(Exception e, object id)
|
||||
{
|
||||
ErrorId = id.ToString();
|
||||
if (e != null)
|
||||
{
|
||||
Error = e.Message;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
protected string GetAvailableTitle(string requestTitle, string parentFolderId, Func<string, string, bool> isExist)
|
||||
{
|
||||
if (!isExist(requestTitle, parentFolderId)) return requestTitle;
|
||||
|
||||
var re = new Regex(@"( \(((?<index>[0-9])+)\)(\.[^\.]*)?)$");
|
||||
var match = re.Match(requestTitle);
|
||||
|
||||
if (!match.Success)
|
||||
{
|
||||
var insertIndex = requestTitle.Length;
|
||||
if (requestTitle.LastIndexOf(".", StringComparison.InvariantCulture) != -1)
|
||||
{
|
||||
insertIndex = requestTitle.LastIndexOf(".", StringComparison.InvariantCulture);
|
||||
}
|
||||
requestTitle = requestTitle.Insert(insertIndex, " (1)");
|
||||
}
|
||||
|
||||
while (isExist(requestTitle, parentFolderId))
|
||||
{
|
||||
requestTitle = re.Replace(requestTitle, MatchEvaluator);
|
||||
}
|
||||
return requestTitle;
|
||||
}
|
||||
|
||||
private static string MatchEvaluator(Match match)
|
||||
{
|
||||
var index = Convert.ToInt32(match.Groups[2].Value);
|
||||
var staticText = match.Value.Substring(string.Format(" ({0})", index).Length);
|
||||
return string.Format(" ({0}){1}", index + 1, staticText);
|
||||
}
|
||||
}
|
||||
}
|
79
products/ASC.Files/Server/Core/Thirdparty/Box/BoxDaoSelector.cs
vendored
Normal file
79
products/ASC.Files/Server/Core/Thirdparty/Box/BoxDaoSelector.cs
vendored
Normal file
@ -0,0 +1,79 @@
|
||||
/*
|
||||
*
|
||||
* (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 ASC.Common;
|
||||
using ASC.Files.Core;
|
||||
using ASC.Files.Core.Security;
|
||||
|
||||
namespace ASC.Files.Thirdparty.Box
|
||||
{
|
||||
internal class BoxDaoSelector : RegexDaoSelectorBase<BoxProviderInfo>, IDaoSelector
|
||||
{
|
||||
protected internal override string Name { get => "Box"; }
|
||||
protected internal override string Id { get => "box"; }
|
||||
|
||||
public BoxDaoSelector(IServiceProvider serviceProvider, IDaoFactory daoFactory)
|
||||
: base(serviceProvider, daoFactory)
|
||||
{
|
||||
}
|
||||
|
||||
public IFileDao<string> GetFileDao(string id)
|
||||
{
|
||||
return base.GetFileDao<BoxFileDao>(id);
|
||||
}
|
||||
|
||||
public IFolderDao<string> GetFolderDao(string id)
|
||||
{
|
||||
return base.GetFolderDao<BoxFolderDao>(id);
|
||||
}
|
||||
|
||||
public ITagDao<string> GetTagDao(string id)
|
||||
{
|
||||
return base.GetTagDao<BoxTagDao>(id);
|
||||
}
|
||||
|
||||
public ISecurityDao<string> GetSecurityDao(string id)
|
||||
{
|
||||
return base.GetSecurityDao<BoxSecurityDao>(id);
|
||||
}
|
||||
}
|
||||
|
||||
public static class BoxDaoSelectorExtention
|
||||
{
|
||||
public static DIHelper AddBoxDaoSelectorService(this DIHelper services)
|
||||
{
|
||||
services.TryAddScoped<BoxDaoSelector>();
|
||||
|
||||
return services
|
||||
.AddBoxSecurityDaoService()
|
||||
.AddBoxTagDaoService()
|
||||
.AddBoxFolderDaoService()
|
||||
.AddBoxFileDaoService();
|
||||
}
|
||||
}
|
||||
}
|
621
products/ASC.Files/Server/Core/Thirdparty/Box/BoxFileDao.cs
vendored
Normal file
621
products/ASC.Files/Server/Core/Thirdparty/Box/BoxFileDao.cs
vendored
Normal file
@ -0,0 +1,621 @@
|
||||
/*
|
||||
*
|
||||
* (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;
|
||||
using System.IO;
|
||||
using System.Linq;
|
||||
|
||||
using ASC.Common;
|
||||
using ASC.Common.Logging;
|
||||
using ASC.Core;
|
||||
using ASC.Core.Common.EF;
|
||||
using ASC.Core.Tenants;
|
||||
using ASC.Files.Core;
|
||||
using ASC.Files.Core.EF;
|
||||
using ASC.Files.Core.Thirdparty;
|
||||
using ASC.Files.Resources;
|
||||
using ASC.Web.Core.Files;
|
||||
using ASC.Web.Files.Services.DocumentService;
|
||||
using ASC.Web.Studio.Core;
|
||||
|
||||
using Box.V2.Models;
|
||||
|
||||
using Microsoft.Extensions.Options;
|
||||
|
||||
namespace ASC.Files.Thirdparty.Box
|
||||
{
|
||||
internal class BoxFileDao : BoxDaoBase, IFileDao<string>
|
||||
{
|
||||
public CrossDao CrossDao { get; }
|
||||
public BoxDaoSelector BoxDaoSelector { get; }
|
||||
public IFileDao<int> FileDao { get; }
|
||||
|
||||
public BoxFileDao(
|
||||
IServiceProvider serviceProvider,
|
||||
UserManager userManager,
|
||||
TenantManager tenantManager,
|
||||
TenantUtil tenantUtil,
|
||||
DbContextManager<FilesDbContext> dbContextManager,
|
||||
SetupInfo setupInfo,
|
||||
IOptionsMonitor<ILog> monitor,
|
||||
FileUtility fileUtility,
|
||||
CrossDao crossDao,
|
||||
BoxDaoSelector boxDaoSelector,
|
||||
IFileDao<int> fileDao) : base(serviceProvider, userManager, tenantManager, tenantUtil, dbContextManager, setupInfo, monitor, fileUtility)
|
||||
{
|
||||
CrossDao = crossDao;
|
||||
BoxDaoSelector = boxDaoSelector;
|
||||
FileDao = fileDao;
|
||||
}
|
||||
|
||||
public void InvalidateCache(string fileId)
|
||||
{
|
||||
var boxFileId = MakeBoxId(fileId);
|
||||
ProviderInfo.CacheReset(boxFileId, true);
|
||||
|
||||
var boxFile = GetBoxFile(fileId);
|
||||
var parentPath = GetParentFolderId(boxFile);
|
||||
if (parentPath != null) ProviderInfo.CacheReset(parentPath);
|
||||
}
|
||||
|
||||
public File<string> GetFile(string fileId)
|
||||
{
|
||||
return GetFile(fileId, 1);
|
||||
}
|
||||
|
||||
public File<string> GetFile(string fileId, int fileVersion)
|
||||
{
|
||||
return ToFile(GetBoxFile(fileId));
|
||||
}
|
||||
|
||||
public File<string> GetFile(string parentId, string title)
|
||||
{
|
||||
return ToFile(GetBoxItems(parentId, false)
|
||||
.FirstOrDefault(item => item.Name.Equals(title, StringComparison.InvariantCultureIgnoreCase)) as BoxFile);
|
||||
}
|
||||
|
||||
public File<string> GetFileStable(string fileId, int fileVersion)
|
||||
{
|
||||
return ToFile(GetBoxFile(fileId));
|
||||
}
|
||||
|
||||
public List<File<string>> GetFileHistory(string fileId)
|
||||
{
|
||||
return new List<File<string>> { GetFile(fileId) };
|
||||
}
|
||||
|
||||
public List<File<string>> GetFiles(string[] fileIds)
|
||||
{
|
||||
if (fileIds == null || fileIds.Length == 0) return new List<File<string>>();
|
||||
return fileIds.Select(GetBoxFile).Select(ToFile).ToList();
|
||||
}
|
||||
|
||||
public List<File<string>> GetFilesForShare(string[] fileIds, FilterType filterType, bool subjectGroup, Guid subjectID, string searchText, bool searchInContent)
|
||||
{
|
||||
if (fileIds == null || fileIds.Length == 0 || filterType == FilterType.FoldersOnly) return new List<File<string>>();
|
||||
|
||||
var files = GetFiles(fileIds).AsEnumerable();
|
||||
|
||||
//Filter
|
||||
if (subjectID != Guid.Empty)
|
||||
{
|
||||
files = files.Where(x => subjectGroup
|
||||
? UserManager.IsUserInGroup(x.CreateBy, subjectID)
|
||||
: x.CreateBy == subjectID);
|
||||
}
|
||||
|
||||
switch (filterType)
|
||||
{
|
||||
case FilterType.FoldersOnly:
|
||||
return new List<File<string>>();
|
||||
case FilterType.DocumentsOnly:
|
||||
files = files.Where(x => FileUtility.GetFileTypeByFileName(x.Title) == FileType.Document);
|
||||
break;
|
||||
case FilterType.PresentationsOnly:
|
||||
files = files.Where(x => FileUtility.GetFileTypeByFileName(x.Title) == FileType.Presentation);
|
||||
break;
|
||||
case FilterType.SpreadsheetsOnly:
|
||||
files = files.Where(x => FileUtility.GetFileTypeByFileName(x.Title) == FileType.Spreadsheet);
|
||||
break;
|
||||
case FilterType.ImagesOnly:
|
||||
files = files.Where(x => FileUtility.GetFileTypeByFileName(x.Title) == FileType.Image);
|
||||
break;
|
||||
case FilterType.ArchiveOnly:
|
||||
files = files.Where(x => FileUtility.GetFileTypeByFileName(x.Title) == FileType.Archive);
|
||||
break;
|
||||
case FilterType.MediaOnly:
|
||||
files = files.Where(x =>
|
||||
{
|
||||
FileType fileType;
|
||||
return (fileType = FileUtility.GetFileTypeByFileName(x.Title)) == FileType.Audio || fileType == FileType.Video;
|
||||
});
|
||||
break;
|
||||
case FilterType.ByExtension:
|
||||
if (!string.IsNullOrEmpty(searchText))
|
||||
files = files.Where(x => FileUtility.GetFileExtension(x.Title).Contains(searchText));
|
||||
break;
|
||||
}
|
||||
|
||||
if (!string.IsNullOrEmpty(searchText))
|
||||
files = files.Where(x => x.Title.IndexOf(searchText, StringComparison.OrdinalIgnoreCase) != -1);
|
||||
|
||||
return files.ToList();
|
||||
}
|
||||
|
||||
public List<string> GetFiles(string parentId)
|
||||
{
|
||||
return GetBoxItems(parentId, false).Select(entry => MakeId(entry.Id)).ToList();
|
||||
}
|
||||
|
||||
public List<File<string>> GetFiles(string parentId, OrderBy orderBy, FilterType filterType, bool subjectGroup, Guid subjectID, string searchText, bool searchInContent, bool withSubfolders = false)
|
||||
{
|
||||
if (filterType == FilterType.FoldersOnly) return new List<File<string>>();
|
||||
|
||||
//Get only files
|
||||
var files = GetBoxItems(parentId, false).Select(item => ToFile(item as BoxFile));
|
||||
|
||||
//Filter
|
||||
if (subjectID != Guid.Empty)
|
||||
{
|
||||
files = files.Where(x => subjectGroup
|
||||
? UserManager.IsUserInGroup(x.CreateBy, subjectID)
|
||||
: x.CreateBy == subjectID);
|
||||
}
|
||||
|
||||
switch (filterType)
|
||||
{
|
||||
case FilterType.FoldersOnly:
|
||||
return new List<File<string>>();
|
||||
case FilterType.DocumentsOnly:
|
||||
files = files.Where(x => FileUtility.GetFileTypeByFileName(x.Title) == FileType.Document);
|
||||
break;
|
||||
case FilterType.PresentationsOnly:
|
||||
files = files.Where(x => FileUtility.GetFileTypeByFileName(x.Title) == FileType.Presentation);
|
||||
break;
|
||||
case FilterType.SpreadsheetsOnly:
|
||||
files = files.Where(x => FileUtility.GetFileTypeByFileName(x.Title) == FileType.Spreadsheet);
|
||||
break;
|
||||
case FilterType.ImagesOnly:
|
||||
files = files.Where(x => FileUtility.GetFileTypeByFileName(x.Title) == FileType.Image);
|
||||
break;
|
||||
case FilterType.ArchiveOnly:
|
||||
files = files.Where(x => FileUtility.GetFileTypeByFileName(x.Title) == FileType.Archive);
|
||||
break;
|
||||
case FilterType.MediaOnly:
|
||||
files = files.Where(x =>
|
||||
{
|
||||
FileType fileType;
|
||||
return (fileType = FileUtility.GetFileTypeByFileName(x.Title)) == FileType.Audio || fileType == FileType.Video;
|
||||
});
|
||||
break;
|
||||
case FilterType.ByExtension:
|
||||
if (!string.IsNullOrEmpty(searchText))
|
||||
files = files.Where(x => FileUtility.GetFileExtension(x.Title).Contains(searchText));
|
||||
break;
|
||||
}
|
||||
|
||||
if (!string.IsNullOrEmpty(searchText))
|
||||
files = files.Where(x => x.Title.IndexOf(searchText, StringComparison.OrdinalIgnoreCase) != -1);
|
||||
|
||||
if (orderBy == null) orderBy = new OrderBy(SortedByType.DateAndTime, false);
|
||||
|
||||
switch (orderBy.SortedBy)
|
||||
{
|
||||
case SortedByType.Author:
|
||||
files = orderBy.IsAsc ? files.OrderBy(x => x.CreateBy) : files.OrderByDescending(x => x.CreateBy);
|
||||
break;
|
||||
case SortedByType.AZ:
|
||||
files = orderBy.IsAsc ? files.OrderBy(x => x.Title) : files.OrderByDescending(x => x.Title);
|
||||
break;
|
||||
case SortedByType.DateAndTime:
|
||||
files = orderBy.IsAsc ? files.OrderBy(x => x.ModifiedOn) : files.OrderByDescending(x => x.ModifiedOn);
|
||||
break;
|
||||
case SortedByType.DateAndTimeCreation:
|
||||
files = orderBy.IsAsc ? files.OrderBy(x => x.CreateOn) : files.OrderByDescending(x => x.CreateOn);
|
||||
break;
|
||||
default:
|
||||
files = orderBy.IsAsc ? files.OrderBy(x => x.Title) : files.OrderByDescending(x => x.Title);
|
||||
break;
|
||||
}
|
||||
|
||||
return files.ToList();
|
||||
}
|
||||
|
||||
public Stream GetFileStream(File<string> file)
|
||||
{
|
||||
return GetFileStream(file, 0);
|
||||
}
|
||||
|
||||
public Stream GetFileStream(File<string> file, long offset)
|
||||
{
|
||||
var boxFileId = MakeBoxId(file.ID);
|
||||
ProviderInfo.CacheReset(boxFileId, true);
|
||||
|
||||
var boxFile = GetBoxFile(file.ID);
|
||||
if (boxFile == null) throw new ArgumentNullException("file", FilesCommonResource.ErrorMassage_FileNotFound);
|
||||
if (boxFile is ErrorFile) throw new Exception(((ErrorFile)boxFile).Error);
|
||||
|
||||
var fileStream = ProviderInfo.Storage.DownloadStream(boxFile, (int)offset);
|
||||
|
||||
return fileStream;
|
||||
}
|
||||
|
||||
public Uri GetPreSignedUri(File<string> file, TimeSpan expires)
|
||||
{
|
||||
throw new NotSupportedException();
|
||||
}
|
||||
|
||||
public bool IsSupportedPreSignedUri(File<string> file)
|
||||
{
|
||||
return false;
|
||||
}
|
||||
|
||||
public File<string> SaveFile(File<string> file, Stream fileStream)
|
||||
{
|
||||
if (file == null) throw new ArgumentNullException("file");
|
||||
if (fileStream == null) throw new ArgumentNullException("fileStream");
|
||||
|
||||
BoxFile newBoxFile = null;
|
||||
|
||||
if (file.ID != null)
|
||||
{
|
||||
var fileId = MakeBoxId(file.ID);
|
||||
newBoxFile = ProviderInfo.Storage.SaveStream(fileId, fileStream);
|
||||
|
||||
if (!newBoxFile.Name.Equals(file.Title))
|
||||
{
|
||||
var folderId = GetParentFolderId(GetBoxFile(fileId));
|
||||
file.Title = GetAvailableTitle(file.Title, folderId, IsExist);
|
||||
newBoxFile = ProviderInfo.Storage.RenameFile(fileId, file.Title);
|
||||
}
|
||||
}
|
||||
else if (file.FolderID != null)
|
||||
{
|
||||
var folderId = MakeBoxId(file.FolderID);
|
||||
file.Title = GetAvailableTitle(file.Title, folderId, IsExist);
|
||||
newBoxFile = ProviderInfo.Storage.CreateFile(fileStream, file.Title, folderId);
|
||||
}
|
||||
|
||||
ProviderInfo.CacheReset(newBoxFile);
|
||||
var parentId = GetParentFolderId(newBoxFile);
|
||||
if (parentId != null) ProviderInfo.CacheReset(parentId);
|
||||
|
||||
return ToFile(newBoxFile);
|
||||
}
|
||||
|
||||
public File<string> ReplaceFileVersion(File<string> file, Stream fileStream)
|
||||
{
|
||||
return SaveFile(file, fileStream);
|
||||
}
|
||||
|
||||
public void DeleteFile(string fileId)
|
||||
{
|
||||
var boxFile = GetBoxFile(fileId);
|
||||
if (boxFile == null) return;
|
||||
var id = MakeId(boxFile.Id);
|
||||
|
||||
using (var tx = FilesDbContext.Database.BeginTransaction())
|
||||
{
|
||||
var hashIDs = Query(FilesDbContext.ThirdpartyIdMapping)
|
||||
.Where(r => r.Id.StartsWith(id))
|
||||
.Select(r => r.HashId)
|
||||
.ToList();
|
||||
|
||||
var link = Query(FilesDbContext.TagLink)
|
||||
.Where(r => hashIDs.Any(h => h == r.EntryId))
|
||||
.ToList();
|
||||
|
||||
FilesDbContext.TagLink.RemoveRange(link);
|
||||
FilesDbContext.SaveChanges();
|
||||
|
||||
var tagsToRemove = Query(FilesDbContext.Tag)
|
||||
.Where(r => !Query(FilesDbContext.TagLink).Where(a => a.TagId == r.Id).Any());
|
||||
|
||||
FilesDbContext.Tag.RemoveRange(tagsToRemove);
|
||||
|
||||
var securityToDelete = Query(FilesDbContext.Security)
|
||||
.Where(r => hashIDs.Any(h => h == r.EntryId));
|
||||
|
||||
FilesDbContext.Security.RemoveRange(securityToDelete);
|
||||
FilesDbContext.SaveChanges();
|
||||
|
||||
var mappingToDelete = Query(FilesDbContext.ThirdpartyIdMapping)
|
||||
.Where(r => hashIDs.Any(h => h == r.HashId));
|
||||
|
||||
FilesDbContext.ThirdpartyIdMapping.RemoveRange(mappingToDelete);
|
||||
FilesDbContext.SaveChanges();
|
||||
|
||||
tx.Commit();
|
||||
}
|
||||
|
||||
if (!(boxFile is ErrorFile))
|
||||
{
|
||||
ProviderInfo.Storage.DeleteItem(boxFile);
|
||||
}
|
||||
|
||||
ProviderInfo.CacheReset(boxFile.Id, true);
|
||||
var parentFolderId = GetParentFolderId(boxFile);
|
||||
if (parentFolderId != null) ProviderInfo.CacheReset(parentFolderId);
|
||||
}
|
||||
|
||||
public bool IsExist(string title, object folderId)
|
||||
{
|
||||
return GetBoxItems(folderId.ToString(), false)
|
||||
.Any(item => item.Name.Equals(title, StringComparison.InvariantCultureIgnoreCase));
|
||||
}
|
||||
|
||||
public TTo MoveFile<TTo>(string fileId, TTo toFolderId)
|
||||
{
|
||||
if (toFolderId is int tId)
|
||||
{
|
||||
return (TTo)Convert.ChangeType(MoveFile(fileId, tId), typeof(TTo));
|
||||
}
|
||||
|
||||
if (toFolderId is string tsId)
|
||||
{
|
||||
return (TTo)Convert.ChangeType(MoveFile(fileId, tsId), typeof(TTo));
|
||||
}
|
||||
|
||||
throw new NotImplementedException();
|
||||
}
|
||||
|
||||
public int MoveFile(string fileId, int toFolderId)
|
||||
{
|
||||
var moved = CrossDao.PerformCrossDaoFileCopy(
|
||||
fileId, this, BoxDaoSelector.ConvertId,
|
||||
toFolderId, FileDao, r => r,
|
||||
true);
|
||||
|
||||
return moved.ID;
|
||||
}
|
||||
|
||||
public string MoveFile(string fileId, string toFolderId)
|
||||
{
|
||||
var boxFile = GetBoxFile(fileId);
|
||||
if (boxFile is ErrorFile) throw new Exception(((ErrorFile)boxFile).Error);
|
||||
|
||||
var toBoxFolder = GetBoxFolder(toFolderId);
|
||||
if (toBoxFolder is ErrorFolder) throw new Exception(((ErrorFolder)toBoxFolder).Error);
|
||||
|
||||
var fromFolderId = GetParentFolderId(boxFile);
|
||||
|
||||
var newTitle = GetAvailableTitle(boxFile.Name, toBoxFolder.Id, IsExist);
|
||||
boxFile = ProviderInfo.Storage.MoveFile(boxFile.Id, newTitle, toBoxFolder.Id);
|
||||
|
||||
ProviderInfo.CacheReset(boxFile.Id, true);
|
||||
ProviderInfo.CacheReset(fromFolderId);
|
||||
ProviderInfo.CacheReset(toBoxFolder.Id);
|
||||
|
||||
return MakeId(boxFile.Id);
|
||||
}
|
||||
|
||||
public File<TTo> CopyFile<TTo>(string fileId, TTo toFolderId)
|
||||
{
|
||||
if (toFolderId is int tId)
|
||||
{
|
||||
return CopyFile(fileId, tId) as File<TTo>;
|
||||
}
|
||||
|
||||
if (toFolderId is string tsId)
|
||||
{
|
||||
return CopyFile(fileId, tsId) as File<TTo>;
|
||||
}
|
||||
|
||||
throw new NotImplementedException();
|
||||
}
|
||||
|
||||
public File<string> CopyFile(string fileId, string toFolderId)
|
||||
{
|
||||
var boxFile = GetBoxFile(fileId);
|
||||
if (boxFile is ErrorFile) throw new Exception(((ErrorFile)boxFile).Error);
|
||||
|
||||
var toBoxFolder = GetBoxFolder(toFolderId);
|
||||
if (toBoxFolder is ErrorFolder) throw new Exception(((ErrorFolder)toBoxFolder).Error);
|
||||
|
||||
var newTitle = GetAvailableTitle(boxFile.Name, toBoxFolder.Id, IsExist);
|
||||
var newBoxFile = ProviderInfo.Storage.CopyFile(boxFile.Id, newTitle, toBoxFolder.Id);
|
||||
|
||||
ProviderInfo.CacheReset(newBoxFile);
|
||||
ProviderInfo.CacheReset(toBoxFolder.Id);
|
||||
|
||||
return ToFile(newBoxFile);
|
||||
}
|
||||
|
||||
public File<int> CopyFile(string fileId, int toFolderId)
|
||||
{
|
||||
var moved = CrossDao.PerformCrossDaoFileCopy(
|
||||
fileId, this, BoxDaoSelector.ConvertId,
|
||||
toFolderId, FileDao, r => r,
|
||||
false);
|
||||
|
||||
return moved;
|
||||
}
|
||||
|
||||
public string FileRename(File<string> file, string newTitle)
|
||||
{
|
||||
var boxFile = GetBoxFile(file.ID);
|
||||
newTitle = GetAvailableTitle(newTitle, GetParentFolderId(boxFile), IsExist);
|
||||
|
||||
boxFile = ProviderInfo.Storage.RenameFile(boxFile.Id, newTitle);
|
||||
|
||||
ProviderInfo.CacheReset(boxFile);
|
||||
var parentId = GetParentFolderId(boxFile);
|
||||
if (parentId != null) ProviderInfo.CacheReset(parentId);
|
||||
|
||||
return MakeId(boxFile.Id);
|
||||
}
|
||||
|
||||
public string UpdateComment(string fileId, int fileVersion, string comment)
|
||||
{
|
||||
return string.Empty;
|
||||
}
|
||||
|
||||
public void CompleteVersion(string fileId, int fileVersion)
|
||||
{
|
||||
}
|
||||
|
||||
public void ContinueVersion(string fileId, int fileVersion)
|
||||
{
|
||||
}
|
||||
|
||||
public bool UseTrashForRemove(File<string> file)
|
||||
{
|
||||
return false;
|
||||
}
|
||||
|
||||
#region chunking
|
||||
|
||||
private File<string> RestoreIds(File<string> file)
|
||||
{
|
||||
if (file == null) return null;
|
||||
|
||||
if (file.ID != null)
|
||||
file.ID = MakeId(file.ID);
|
||||
|
||||
if (file.FolderID != null)
|
||||
file.FolderID = MakeId(file.FolderID);
|
||||
|
||||
return file;
|
||||
}
|
||||
|
||||
public ChunkedUploadSession<string> CreateUploadSession(File<string> file, long contentLength)
|
||||
{
|
||||
if (SetupInfo.ChunkUploadSize > contentLength)
|
||||
return new ChunkedUploadSession<string>(RestoreIds(file), contentLength) { UseChunks = false };
|
||||
|
||||
var uploadSession = new ChunkedUploadSession<string>(file, contentLength);
|
||||
|
||||
uploadSession.Items["TempPath"] = Path.GetTempFileName();
|
||||
|
||||
uploadSession.File = RestoreIds(uploadSession.File);
|
||||
return uploadSession;
|
||||
}
|
||||
|
||||
public void UploadChunk(ChunkedUploadSession<string> uploadSession, Stream stream, long chunkLength)
|
||||
{
|
||||
if (!uploadSession.UseChunks)
|
||||
{
|
||||
if (uploadSession.BytesTotal == 0)
|
||||
uploadSession.BytesTotal = chunkLength;
|
||||
|
||||
uploadSession.File = SaveFile(uploadSession.File, stream);
|
||||
uploadSession.BytesUploaded = chunkLength;
|
||||
return;
|
||||
}
|
||||
|
||||
var tempPath = uploadSession.GetItemOrDefault<string>("TempPath");
|
||||
using (var fs = new FileStream(tempPath, FileMode.Append))
|
||||
{
|
||||
stream.CopyTo(fs);
|
||||
}
|
||||
|
||||
uploadSession.BytesUploaded += chunkLength;
|
||||
|
||||
if (uploadSession.BytesUploaded == uploadSession.BytesTotal)
|
||||
{
|
||||
using (var fs = new FileStream(uploadSession.GetItemOrDefault<string>("TempPath"),
|
||||
FileMode.Open, FileAccess.Read, FileShare.None, 4096, FileOptions.DeleteOnClose))
|
||||
{
|
||||
uploadSession.File = SaveFile(uploadSession.File, fs);
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
uploadSession.File = RestoreIds(uploadSession.File);
|
||||
}
|
||||
}
|
||||
|
||||
public void AbortUploadSession(ChunkedUploadSession<string> uploadSession)
|
||||
{
|
||||
if (uploadSession.Items.ContainsKey("TempPath"))
|
||||
{
|
||||
File.Delete(uploadSession.GetItemOrDefault<string>("TempPath"));
|
||||
}
|
||||
}
|
||||
|
||||
#endregion
|
||||
|
||||
|
||||
#region Only in TMFileDao
|
||||
|
||||
public void ReassignFiles(string[] fileIds, Guid newOwnerId)
|
||||
{
|
||||
}
|
||||
|
||||
public List<File<string>> GetFiles(string[] parentIds, FilterType filterType, bool subjectGroup, Guid subjectID, string searchText, bool searchInContent)
|
||||
{
|
||||
return new List<File<string>>();
|
||||
}
|
||||
|
||||
public IEnumerable<File<string>> Search(string text, bool bunch)
|
||||
{
|
||||
return null;
|
||||
}
|
||||
|
||||
public bool IsExistOnStorage(File<string> file)
|
||||
{
|
||||
return true;
|
||||
}
|
||||
|
||||
public void SaveEditHistory(File<string> file, string changes, Stream differenceStream)
|
||||
{
|
||||
//Do nothing
|
||||
}
|
||||
|
||||
public List<EditHistory> GetEditHistory(DocumentServiceHelper documentServiceHelper, string fileId, int fileVersion)
|
||||
{
|
||||
return null;
|
||||
}
|
||||
|
||||
public Stream GetDifferenceStream(File<string> file)
|
||||
{
|
||||
return null;
|
||||
}
|
||||
|
||||
public bool ContainChanges(string fileId, int fileVersion)
|
||||
{
|
||||
return false;
|
||||
}
|
||||
|
||||
public string GetUniqFilePath(File<string> file, string fileTitle)
|
||||
{
|
||||
throw new NotImplementedException();
|
||||
}
|
||||
|
||||
#endregion
|
||||
}
|
||||
|
||||
public static class BoxFileDaoExtention
|
||||
{
|
||||
public static DIHelper AddBoxFileDaoService(this DIHelper services)
|
||||
{
|
||||
services.TryAddScoped<BoxFileDao>();
|
||||
|
||||
return services;
|
||||
}
|
||||
}
|
||||
}
|
525
products/ASC.Files/Server/Core/Thirdparty/Box/BoxFolderDao.cs
vendored
Normal file
525
products/ASC.Files/Server/Core/Thirdparty/Box/BoxFolderDao.cs
vendored
Normal file
@ -0,0 +1,525 @@
|
||||
/*
|
||||
*
|
||||
* (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;
|
||||
using System.Linq;
|
||||
using System.Threading;
|
||||
|
||||
using ASC.Common;
|
||||
using ASC.Common.Logging;
|
||||
using ASC.Core;
|
||||
using ASC.Core.Common.EF;
|
||||
using ASC.Core.Tenants;
|
||||
using ASC.Files.Core;
|
||||
using ASC.Files.Core.EF;
|
||||
using ASC.Files.Core.Thirdparty;
|
||||
using ASC.Web.Core.Files;
|
||||
using ASC.Web.Studio.Core;
|
||||
|
||||
using Box.V2.Models;
|
||||
|
||||
using Microsoft.Extensions.Options;
|
||||
|
||||
namespace ASC.Files.Thirdparty.Box
|
||||
{
|
||||
internal class BoxFolderDao : BoxDaoBase, IFolderDao<string>
|
||||
{
|
||||
public CrossDao CrossDao { get; }
|
||||
public BoxDaoSelector BoxDaoSelector { get; }
|
||||
public IFileDao<int> FileDao { get; }
|
||||
public IFolderDao<int> FolderDao { get; }
|
||||
|
||||
public BoxFolderDao(
|
||||
IServiceProvider serviceProvider,
|
||||
UserManager userManager,
|
||||
TenantManager tenantManager,
|
||||
TenantUtil tenantUtil,
|
||||
DbContextManager<FilesDbContext> dbContextManager,
|
||||
SetupInfo setupInfo,
|
||||
IOptionsMonitor<ILog> monitor,
|
||||
FileUtility fileUtility,
|
||||
CrossDao crossDao,
|
||||
BoxDaoSelector boxDaoSelector,
|
||||
IFileDao<int> fileDao,
|
||||
IFolderDao<int> folderDao
|
||||
)
|
||||
: base(serviceProvider, userManager, tenantManager, tenantUtil, dbContextManager, setupInfo, monitor, fileUtility)
|
||||
{
|
||||
CrossDao = crossDao;
|
||||
BoxDaoSelector = boxDaoSelector;
|
||||
FileDao = fileDao;
|
||||
FolderDao = folderDao;
|
||||
}
|
||||
|
||||
public Folder<string> GetFolder(string folderId)
|
||||
{
|
||||
return ToFolder(GetBoxFolder(folderId));
|
||||
}
|
||||
|
||||
public Folder<string> GetFolder(string title, string parentId)
|
||||
{
|
||||
return ToFolder(GetBoxItems(parentId, true)
|
||||
.FirstOrDefault(item => item.Name.Equals(title, StringComparison.InvariantCultureIgnoreCase)) as BoxFolder);
|
||||
}
|
||||
|
||||
public Folder<string> GetRootFolderByFile(string fileId)
|
||||
{
|
||||
return GetRootFolder(fileId);
|
||||
}
|
||||
|
||||
public List<Folder<string>> GetFolders(string parentId)
|
||||
{
|
||||
return GetBoxItems(parentId, true).Select(item => ToFolder(item as BoxFolder)).ToList();
|
||||
}
|
||||
|
||||
public List<Folder<string>> GetFolders(string parentId, OrderBy orderBy, FilterType filterType, bool subjectGroup, Guid subjectID, string searchText, bool withSubfolders = false)
|
||||
{
|
||||
if (filterType == FilterType.FilesOnly || filterType == FilterType.ByExtension
|
||||
|| filterType == FilterType.DocumentsOnly || filterType == FilterType.ImagesOnly
|
||||
|| filterType == FilterType.PresentationsOnly || filterType == FilterType.SpreadsheetsOnly
|
||||
|| filterType == FilterType.ArchiveOnly || filterType == FilterType.MediaOnly)
|
||||
return new List<Folder<string>>();
|
||||
|
||||
var folders = GetFolders(parentId).AsEnumerable(); //TODO:!!!
|
||||
|
||||
if (subjectID != Guid.Empty)
|
||||
{
|
||||
folders = folders.Where(x => subjectGroup
|
||||
? UserManager.IsUserInGroup(x.CreateBy, subjectID)
|
||||
: x.CreateBy == subjectID);
|
||||
}
|
||||
|
||||
if (!string.IsNullOrEmpty(searchText))
|
||||
folders = folders.Where(x => x.Title.IndexOf(searchText, StringComparison.OrdinalIgnoreCase) != -1);
|
||||
|
||||
if (orderBy == null) orderBy = new OrderBy(SortedByType.DateAndTime, false);
|
||||
|
||||
switch (orderBy.SortedBy)
|
||||
{
|
||||
case SortedByType.Author:
|
||||
folders = orderBy.IsAsc ? folders.OrderBy(x => x.CreateBy) : folders.OrderByDescending(x => x.CreateBy);
|
||||
break;
|
||||
case SortedByType.AZ:
|
||||
folders = orderBy.IsAsc ? folders.OrderBy(x => x.Title) : folders.OrderByDescending(x => x.Title);
|
||||
break;
|
||||
case SortedByType.DateAndTime:
|
||||
folders = orderBy.IsAsc ? folders.OrderBy(x => x.ModifiedOn) : folders.OrderByDescending(x => x.ModifiedOn);
|
||||
break;
|
||||
case SortedByType.DateAndTimeCreation:
|
||||
folders = orderBy.IsAsc ? folders.OrderBy(x => x.CreateOn) : folders.OrderByDescending(x => x.CreateOn);
|
||||
break;
|
||||
default:
|
||||
folders = orderBy.IsAsc ? folders.OrderBy(x => x.Title) : folders.OrderByDescending(x => x.Title);
|
||||
break;
|
||||
}
|
||||
|
||||
return folders.ToList();
|
||||
}
|
||||
|
||||
public List<Folder<string>> GetFolders(string[] folderIds, FilterType filterType = FilterType.None, bool subjectGroup = false, Guid? subjectID = null, string searchText = "", bool searchSubfolders = false, bool checkShare = true)
|
||||
{
|
||||
if (filterType == FilterType.FilesOnly || filterType == FilterType.ByExtension
|
||||
|| filterType == FilterType.DocumentsOnly || filterType == FilterType.ImagesOnly
|
||||
|| filterType == FilterType.PresentationsOnly || filterType == FilterType.SpreadsheetsOnly
|
||||
|| filterType == FilterType.ArchiveOnly || filterType == FilterType.MediaOnly)
|
||||
return new List<Folder<string>>();
|
||||
|
||||
var folders = folderIds.Select(GetFolder);
|
||||
|
||||
if (subjectID.HasValue && subjectID != Guid.Empty)
|
||||
{
|
||||
folders = folders.Where(x => subjectGroup
|
||||
? UserManager.IsUserInGroup(x.CreateBy, subjectID.Value)
|
||||
: x.CreateBy == subjectID);
|
||||
}
|
||||
|
||||
if (!string.IsNullOrEmpty(searchText))
|
||||
folders = folders.Where(x => x.Title.IndexOf(searchText, StringComparison.OrdinalIgnoreCase) != -1);
|
||||
|
||||
return folders.ToList();
|
||||
}
|
||||
|
||||
public List<Folder<string>> GetParentFolders(string folderId)
|
||||
{
|
||||
var path = new List<Folder<string>>();
|
||||
|
||||
while (folderId != null)
|
||||
{
|
||||
var boxFolder = GetBoxFolder(folderId);
|
||||
|
||||
if (boxFolder is ErrorFolder)
|
||||
{
|
||||
folderId = null;
|
||||
}
|
||||
else
|
||||
{
|
||||
path.Add(ToFolder(boxFolder));
|
||||
folderId = GetParentFolderId(boxFolder);
|
||||
}
|
||||
}
|
||||
|
||||
path.Reverse();
|
||||
return path;
|
||||
}
|
||||
|
||||
public string SaveFolder(Folder<string> folder)
|
||||
{
|
||||
if (folder == null) throw new ArgumentNullException("folder");
|
||||
if (folder.ID != null)
|
||||
{
|
||||
return RenameFolder(folder, folder.Title);
|
||||
}
|
||||
|
||||
if (folder.ParentFolderID != null)
|
||||
{
|
||||
var boxFolderId = MakeBoxId(folder.ParentFolderID);
|
||||
|
||||
folder.Title = GetAvailableTitle(folder.Title, boxFolderId, IsExist);
|
||||
|
||||
var boxFolder = ProviderInfo.Storage.CreateFolder(folder.Title, boxFolderId);
|
||||
|
||||
ProviderInfo.CacheReset(boxFolder);
|
||||
var parentFolderId = GetParentFolderId(boxFolder);
|
||||
if (parentFolderId != null) ProviderInfo.CacheReset(parentFolderId);
|
||||
|
||||
return MakeId(boxFolder);
|
||||
}
|
||||
return null;
|
||||
}
|
||||
|
||||
public bool IsExist(string title, string folderId)
|
||||
{
|
||||
return GetBoxItems(folderId, true)
|
||||
.Any(item => item.Name.Equals(title, StringComparison.InvariantCultureIgnoreCase));
|
||||
}
|
||||
|
||||
public void DeleteFolder(string folderId)
|
||||
{
|
||||
var boxFolder = GetBoxFolder(folderId);
|
||||
var id = MakeId(boxFolder);
|
||||
|
||||
using (var tx = FilesDbContext.Database.BeginTransaction())
|
||||
{
|
||||
var hashIDs = Query(FilesDbContext.ThirdpartyIdMapping)
|
||||
.Where(r => r.Id.StartsWith(id))
|
||||
.Select(r => r.HashId)
|
||||
.ToList();
|
||||
|
||||
var link = Query(FilesDbContext.TagLink)
|
||||
.Where(r => hashIDs.Any(h => h == r.EntryId))
|
||||
.ToList();
|
||||
|
||||
FilesDbContext.TagLink.RemoveRange(link);
|
||||
FilesDbContext.SaveChanges();
|
||||
|
||||
var tagsToRemove = Query(FilesDbContext.Tag)
|
||||
.Where(r => !Query(FilesDbContext.TagLink).Where(a => a.TagId == r.Id).Any());
|
||||
|
||||
FilesDbContext.Tag.RemoveRange(tagsToRemove);
|
||||
|
||||
var securityToDelete = Query(FilesDbContext.Security)
|
||||
.Where(r => hashIDs.Any(h => h == r.EntryId));
|
||||
|
||||
FilesDbContext.Security.RemoveRange(securityToDelete);
|
||||
FilesDbContext.SaveChanges();
|
||||
|
||||
var mappingToDelete = Query(FilesDbContext.ThirdpartyIdMapping)
|
||||
.Where(r => hashIDs.Any(h => h == r.HashId));
|
||||
|
||||
FilesDbContext.ThirdpartyIdMapping.RemoveRange(mappingToDelete);
|
||||
FilesDbContext.SaveChanges();
|
||||
|
||||
tx.Commit();
|
||||
}
|
||||
|
||||
if (!(boxFolder is ErrorFolder))
|
||||
{
|
||||
ProviderInfo.Storage.DeleteItem(boxFolder);
|
||||
}
|
||||
|
||||
ProviderInfo.CacheReset(boxFolder.Id, true);
|
||||
var parentFolderId = GetParentFolderId(boxFolder);
|
||||
if (parentFolderId != null) ProviderInfo.CacheReset(parentFolderId);
|
||||
}
|
||||
|
||||
public string MoveFolder(string folderId, string toFolderId, CancellationToken? cancellationToken)
|
||||
{
|
||||
var boxFolder = GetBoxFolder(folderId);
|
||||
if (boxFolder is ErrorFolder) throw new Exception(((ErrorFolder)boxFolder).Error);
|
||||
|
||||
var toBoxFolder = GetBoxFolder(toFolderId);
|
||||
if (toBoxFolder is ErrorFolder) throw new Exception(((ErrorFolder)toBoxFolder).Error);
|
||||
|
||||
var fromFolderId = GetParentFolderId(boxFolder);
|
||||
|
||||
var newTitle = GetAvailableTitle(boxFolder.Name, toBoxFolder.Id, IsExist);
|
||||
boxFolder = ProviderInfo.Storage.MoveFolder(boxFolder.Id, newTitle, toBoxFolder.Id);
|
||||
|
||||
ProviderInfo.CacheReset(boxFolder.Id, false);
|
||||
ProviderInfo.CacheReset(fromFolderId);
|
||||
ProviderInfo.CacheReset(toBoxFolder.Id);
|
||||
|
||||
return MakeId(boxFolder.Id);
|
||||
}
|
||||
|
||||
public TTo MoveFolder<TTo>(string folderId, TTo toFolderId, CancellationToken? cancellationToken)
|
||||
{
|
||||
if (toFolderId is int tId)
|
||||
{
|
||||
return (TTo)Convert.ChangeType(MoveFolder(folderId, tId, cancellationToken), typeof(TTo));
|
||||
}
|
||||
|
||||
if (toFolderId is string tsId)
|
||||
{
|
||||
return (TTo)Convert.ChangeType(MoveFolder(folderId, tsId, cancellationToken), typeof(TTo));
|
||||
}
|
||||
|
||||
throw new NotImplementedException();
|
||||
}
|
||||
|
||||
public int MoveFolder(string folderId, int toFolderId, CancellationToken? cancellationToken)
|
||||
{
|
||||
var moved = CrossDao.PerformCrossDaoFolderCopy(
|
||||
folderId, this, BoxDaoSelector.GetFileDao(folderId), BoxDaoSelector.ConvertId,
|
||||
toFolderId, FolderDao, FileDao, r => r,
|
||||
true, cancellationToken);
|
||||
|
||||
return moved.ID;
|
||||
}
|
||||
|
||||
public Folder<TTo> CopyFolder<TTo>(string folderId, TTo toFolderId, CancellationToken? cancellationToken)
|
||||
{
|
||||
if (toFolderId is int tId)
|
||||
{
|
||||
return CopyFolder(folderId, tId, cancellationToken) as Folder<TTo>;
|
||||
}
|
||||
|
||||
if (toFolderId is string tsId)
|
||||
{
|
||||
return CopyFolder(folderId, tsId, cancellationToken) as Folder<TTo>;
|
||||
}
|
||||
|
||||
throw new NotImplementedException();
|
||||
}
|
||||
|
||||
public Folder<string> CopyFolder(string folderId, string toFolderId, CancellationToken? cancellationToken)
|
||||
{
|
||||
var boxFolder = GetBoxFolder(folderId);
|
||||
if (boxFolder is ErrorFolder) throw new Exception(((ErrorFolder)boxFolder).Error);
|
||||
|
||||
var toBoxFolder = GetBoxFolder(toFolderId);
|
||||
if (toBoxFolder is ErrorFolder) throw new Exception(((ErrorFolder)toBoxFolder).Error);
|
||||
|
||||
var newTitle = GetAvailableTitle(boxFolder.Name, toBoxFolder.Id, IsExist);
|
||||
var newBoxFolder = ProviderInfo.Storage.CopyFolder(boxFolder.Id, newTitle, toBoxFolder.Id);
|
||||
|
||||
ProviderInfo.CacheReset(newBoxFolder);
|
||||
ProviderInfo.CacheReset(newBoxFolder.Id, false);
|
||||
ProviderInfo.CacheReset(toBoxFolder.Id);
|
||||
|
||||
return ToFolder(newBoxFolder);
|
||||
}
|
||||
|
||||
public Folder<int> CopyFolder(string folderId, int toFolderId, CancellationToken? cancellationToken)
|
||||
{
|
||||
var moved = CrossDao.PerformCrossDaoFolderCopy(
|
||||
folderId, this, BoxDaoSelector.GetFileDao(folderId), BoxDaoSelector.ConvertId,
|
||||
toFolderId, FolderDao, FileDao, r => r,
|
||||
false, cancellationToken);
|
||||
|
||||
return moved;
|
||||
}
|
||||
|
||||
public IDictionary<string, string> CanMoveOrCopy<TTo>(string[] folderIds, TTo to)
|
||||
{
|
||||
if (to is int tId)
|
||||
{
|
||||
return CanMoveOrCopy(folderIds, tId);
|
||||
}
|
||||
|
||||
if (to is string tsId)
|
||||
{
|
||||
return CanMoveOrCopy(folderIds, tsId);
|
||||
}
|
||||
|
||||
throw new NotImplementedException();
|
||||
}
|
||||
|
||||
public IDictionary<string, string> CanMoveOrCopy(string[] folderIds, string to)
|
||||
{
|
||||
return new Dictionary<string, string>();
|
||||
}
|
||||
|
||||
public IDictionary<string, string> CanMoveOrCopy(string[] folderIds, int to)
|
||||
{
|
||||
return new Dictionary<string, string>();
|
||||
}
|
||||
|
||||
public string RenameFolder(Folder<string> folder, string newTitle)
|
||||
{
|
||||
var boxFolder = GetBoxFolder(folder.ID);
|
||||
var parentFolderId = GetParentFolderId(boxFolder);
|
||||
|
||||
if (IsRoot(boxFolder))
|
||||
{
|
||||
//It's root folder
|
||||
DaoSelector.RenameProvider(ProviderInfo, newTitle);
|
||||
//rename provider customer title
|
||||
}
|
||||
else
|
||||
{
|
||||
newTitle = GetAvailableTitle(newTitle, parentFolderId, IsExist);
|
||||
|
||||
//rename folder
|
||||
boxFolder = ProviderInfo.Storage.RenameFolder(boxFolder.Id, newTitle);
|
||||
}
|
||||
|
||||
ProviderInfo.CacheReset(boxFolder);
|
||||
if (parentFolderId != null) ProviderInfo.CacheReset(parentFolderId);
|
||||
|
||||
return MakeId(boxFolder.Id);
|
||||
}
|
||||
|
||||
public int GetItemsCount(string folderId)
|
||||
{
|
||||
throw new NotImplementedException();
|
||||
}
|
||||
|
||||
public bool IsEmpty(string folderId)
|
||||
{
|
||||
var boxFolderId = MakeBoxId(folderId);
|
||||
//note: without cache
|
||||
return ProviderInfo.Storage.GetItems(boxFolderId, 1).Count == 0;
|
||||
}
|
||||
|
||||
public bool UseTrashForRemove(Folder<string> folder)
|
||||
{
|
||||
return false;
|
||||
}
|
||||
|
||||
public bool UseRecursiveOperation(string folderId, string toRootFolderId)
|
||||
{
|
||||
return false;
|
||||
}
|
||||
|
||||
public bool UseRecursiveOperation<TTo>(string folderId, TTo toRootFolderId)
|
||||
{
|
||||
return false;
|
||||
}
|
||||
|
||||
public bool UseRecursiveOperation(string folderId, int toRootFolderId)
|
||||
{
|
||||
return false;
|
||||
}
|
||||
|
||||
public bool CanCalculateSubitems(string entryId)
|
||||
{
|
||||
return false;
|
||||
}
|
||||
|
||||
public long GetMaxUploadSize(string folderId, bool chunkedUpload)
|
||||
{
|
||||
var storageMaxUploadSize = ProviderInfo.Storage.GetMaxUploadSize();
|
||||
|
||||
return chunkedUpload ? storageMaxUploadSize : Math.Min(storageMaxUploadSize, SetupInfo.AvailableFileSize);
|
||||
}
|
||||
|
||||
#region Only for TMFolderDao
|
||||
|
||||
public void ReassignFolders(string[] folderIds, Guid newOwnerId)
|
||||
{
|
||||
}
|
||||
|
||||
public IEnumerable<Folder<string>> Search(string text, bool bunch)
|
||||
{
|
||||
return null;
|
||||
}
|
||||
|
||||
public string GetFolderID(string module, string bunch, string data, bool createIfNotExists)
|
||||
{
|
||||
return null;
|
||||
}
|
||||
|
||||
public IEnumerable<string> GetFolderIDs(string module, string bunch, IEnumerable<string> data, bool createIfNotExists)
|
||||
{
|
||||
return new List<string>();
|
||||
}
|
||||
|
||||
public string GetFolderIDCommon(bool createIfNotExists)
|
||||
{
|
||||
return null;
|
||||
}
|
||||
|
||||
public string GetFolderIDUser(bool createIfNotExists, Guid? userId)
|
||||
{
|
||||
return null;
|
||||
}
|
||||
|
||||
public string GetFolderIDShare(bool createIfNotExists)
|
||||
{
|
||||
return null;
|
||||
}
|
||||
|
||||
public string GetFolderIDTrash(bool createIfNotExists, Guid? userId)
|
||||
{
|
||||
return null;
|
||||
}
|
||||
|
||||
|
||||
public string GetFolderIDPhotos(bool createIfNotExists)
|
||||
{
|
||||
return null;
|
||||
}
|
||||
|
||||
public string GetFolderIDProjects(bool createIfNotExists)
|
||||
{
|
||||
return null;
|
||||
}
|
||||
|
||||
public string GetBunchObjectID(string folderID)
|
||||
{
|
||||
return null;
|
||||
}
|
||||
|
||||
public Dictionary<string, string> GetBunchObjectIDs(List<string> folderIDs)
|
||||
{
|
||||
return null;
|
||||
}
|
||||
|
||||
#endregion
|
||||
}
|
||||
|
||||
public static class BoxFolderDaoExtention
|
||||
{
|
||||
public static DIHelper AddBoxFolderDaoService(this DIHelper services)
|
||||
{
|
||||
services.TryAddScoped<BoxFolderDao>();
|
||||
|
||||
return services;
|
||||
}
|
||||
}
|
||||
}
|
330
products/ASC.Files/Server/Core/Thirdparty/Box/BoxProviderInfo.cs
vendored
Normal file
330
products/ASC.Files/Server/Core/Thirdparty/Box/BoxProviderInfo.cs
vendored
Normal file
@ -0,0 +1,330 @@
|
||||
/*
|
||||
*
|
||||
* (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;
|
||||
using System.Diagnostics;
|
||||
using System.Text.RegularExpressions;
|
||||
|
||||
using ASC.Common;
|
||||
using ASC.Common.Caching;
|
||||
using ASC.Core.Common.Configuration;
|
||||
using ASC.FederatedLogin;
|
||||
using ASC.FederatedLogin.Helpers;
|
||||
using ASC.FederatedLogin.LoginProviders;
|
||||
using ASC.Files.Core;
|
||||
|
||||
using Box.V2.Models;
|
||||
|
||||
using Microsoft.Extensions.DependencyInjection;
|
||||
|
||||
namespace ASC.Files.Thirdparty.Box
|
||||
{
|
||||
[DebuggerDisplay("{CustomerTitle}")]
|
||||
internal class BoxProviderInfo : IProviderInfo
|
||||
{
|
||||
public OAuth20Token Token { get; set; }
|
||||
|
||||
private string _rootId;
|
||||
|
||||
internal BoxStorage Storage
|
||||
{
|
||||
get
|
||||
{
|
||||
if (Wrapper.Storage == null || !Wrapper.Storage.IsOpened)
|
||||
{
|
||||
return Wrapper.CreateStorage(Token, ID);
|
||||
}
|
||||
return Wrapper.Storage;
|
||||
}
|
||||
}
|
||||
|
||||
internal bool StorageOpened
|
||||
{
|
||||
get => Wrapper.Storage != null && Wrapper.Storage.IsOpened;
|
||||
}
|
||||
|
||||
public int ID { get; set; }
|
||||
|
||||
public Guid Owner { get; set; }
|
||||
|
||||
public string CustomerTitle { get; set; }
|
||||
|
||||
public DateTime CreateOn { get; set; }
|
||||
|
||||
public string RootFolderId
|
||||
{
|
||||
get { return "box-" + ID; }
|
||||
}
|
||||
|
||||
public string ProviderKey { get; set; }
|
||||
|
||||
public FolderType RootFolderType { get; set; }
|
||||
|
||||
public string BoxRootId
|
||||
{
|
||||
get
|
||||
{
|
||||
if (string.IsNullOrEmpty(_rootId))
|
||||
{
|
||||
_rootId = Storage.GetRootFolderId();
|
||||
}
|
||||
return _rootId;
|
||||
}
|
||||
}
|
||||
|
||||
public BoxStorageDisposableWrapper Wrapper { get; private set; }
|
||||
public BoxProviderInfoHelper BoxProviderInfoHelper { get; }
|
||||
|
||||
public BoxProviderInfo(
|
||||
BoxStorageDisposableWrapper wrapper,
|
||||
BoxProviderInfoHelper boxProviderInfoHelper)
|
||||
{
|
||||
Wrapper = wrapper;
|
||||
BoxProviderInfoHelper = boxProviderInfoHelper;
|
||||
}
|
||||
|
||||
public void Dispose()
|
||||
{
|
||||
if (StorageOpened)
|
||||
Storage.Close();
|
||||
}
|
||||
|
||||
public bool CheckAccess()
|
||||
{
|
||||
try
|
||||
{
|
||||
return !string.IsNullOrEmpty(BoxRootId);
|
||||
}
|
||||
catch (UnauthorizedAccessException)
|
||||
{
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
public void InvalidateStorage()
|
||||
{
|
||||
if (Wrapper != null)
|
||||
{
|
||||
Wrapper.Dispose();
|
||||
Wrapper = null;
|
||||
}
|
||||
|
||||
CacheReset();
|
||||
}
|
||||
|
||||
public void UpdateTitle(string newtitle)
|
||||
{
|
||||
CustomerTitle = newtitle;
|
||||
}
|
||||
|
||||
internal BoxFolder GetBoxFolder(string dropboxFolderPath)
|
||||
{
|
||||
return BoxProviderInfoHelper.GetBoxFolder(Storage, ID, dropboxFolderPath);
|
||||
}
|
||||
|
||||
internal BoxFile GetBoxFile(string dropboxFilePath)
|
||||
{
|
||||
return BoxProviderInfoHelper.GetBoxFile(Storage, ID, dropboxFilePath);
|
||||
}
|
||||
|
||||
internal List<BoxItem> GetBoxItems(string dropboxFolderPath)
|
||||
{
|
||||
return BoxProviderInfoHelper.GetBoxItems(Storage, ID, dropboxFolderPath);
|
||||
}
|
||||
|
||||
internal void CacheReset(BoxItem boxItem)
|
||||
{
|
||||
BoxProviderInfoHelper.CacheReset(ID, boxItem);
|
||||
}
|
||||
|
||||
internal void CacheReset(string boxPath = null, bool? isFile = null)
|
||||
{
|
||||
BoxProviderInfoHelper.CacheReset(BoxRootId, ID, boxPath, isFile);
|
||||
}
|
||||
}
|
||||
|
||||
internal class BoxStorageDisposableWrapper : IDisposable
|
||||
{
|
||||
public BoxStorage Storage { get; private set; }
|
||||
public ConsumerFactory ConsumerFactory { get; }
|
||||
public IServiceProvider ServiceProvider { get; }
|
||||
|
||||
public BoxStorageDisposableWrapper(ConsumerFactory consumerFactory, IServiceProvider serviceProvider)
|
||||
{
|
||||
ConsumerFactory = consumerFactory;
|
||||
ServiceProvider = serviceProvider;
|
||||
}
|
||||
|
||||
internal BoxStorage CreateStorage(OAuth20Token token, int id)
|
||||
{
|
||||
if (Storage != null) return Storage;
|
||||
|
||||
var boxStorage = new BoxStorage();
|
||||
CheckToken(token, id);
|
||||
|
||||
boxStorage.Open(token);
|
||||
return boxStorage;
|
||||
}
|
||||
|
||||
private void CheckToken(OAuth20Token token, int id)
|
||||
{
|
||||
if (token == null) throw new UnauthorizedAccessException("Cannot create Box session with given token");
|
||||
if (token.IsExpired)
|
||||
{
|
||||
token = OAuth20TokenHelper.RefreshToken<BoxLoginProvider>(ConsumerFactory, token);
|
||||
|
||||
var dbDao = ServiceProvider.GetService<CachedProviderAccountDao>();
|
||||
dbDao.UpdateProviderInfo(id, new AuthData(token: token.ToJson()));
|
||||
}
|
||||
}
|
||||
|
||||
public void Dispose()
|
||||
{
|
||||
if (Storage != null)
|
||||
{
|
||||
Storage.Close();
|
||||
Storage = null;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
public class BoxProviderInfoHelper
|
||||
{
|
||||
private readonly TimeSpan CacheExpiration = TimeSpan.FromMinutes(1);
|
||||
private readonly ICache CacheFile = AscCache.Memory;
|
||||
private readonly ICache CacheFolder = AscCache.Memory;
|
||||
private readonly ICache CacheChildItems = AscCache.Memory;
|
||||
private readonly ICacheNotify<BoxCacheItem> CacheNotify;
|
||||
|
||||
public BoxProviderInfoHelper(ICacheNotify<BoxCacheItem> cacheNotify)
|
||||
{
|
||||
CacheNotify = cacheNotify;
|
||||
CacheNotify.Subscribe((i) =>
|
||||
{
|
||||
if (i.ResetAll)
|
||||
{
|
||||
CacheChildItems.Remove(new Regex("^box-" + i.Key + ".*"));
|
||||
CacheFile.Remove(new Regex("^boxf-" + i.Key + ".*"));
|
||||
CacheFolder.Remove(new Regex("^boxd-" + i.Key + ".*"));
|
||||
}
|
||||
|
||||
if (!i.IsFileExists)
|
||||
{
|
||||
CacheChildItems.Remove("box-" + i.Key);
|
||||
|
||||
CacheFolder.Remove("boxd-" + i.Key);
|
||||
}
|
||||
else
|
||||
{
|
||||
if (i.IsFileExists)
|
||||
{
|
||||
CacheFile.Remove("boxf-" + i.Key);
|
||||
}
|
||||
else
|
||||
{
|
||||
CacheFolder.Remove("boxd-" + i.Key);
|
||||
}
|
||||
}
|
||||
}, CacheNotifyAction.Remove);
|
||||
}
|
||||
|
||||
internal BoxFolder GetBoxFolder(BoxStorage storage, int id, string boxFolderId)
|
||||
{
|
||||
var folder = CacheFolder.Get<BoxFolder>("boxd-" + id + "-" + boxFolderId);
|
||||
if (folder == null)
|
||||
{
|
||||
folder = storage.GetFolder(boxFolderId);
|
||||
if (folder != null)
|
||||
CacheFolder.Insert("boxd-" + id + "-" + boxFolderId, folder, DateTime.UtcNow.Add(CacheExpiration));
|
||||
}
|
||||
return folder;
|
||||
}
|
||||
|
||||
internal BoxFile GetBoxFile(BoxStorage storage, int id, string boxFileId)
|
||||
{
|
||||
var file = CacheFile.Get<BoxFile>("boxf-" + id + "-" + boxFileId);
|
||||
if (file == null)
|
||||
{
|
||||
file = storage.GetFile(boxFileId);
|
||||
if (file != null)
|
||||
CacheFile.Insert("boxf-" + id + "-" + boxFileId, file, DateTime.UtcNow.Add(CacheExpiration));
|
||||
}
|
||||
return file;
|
||||
}
|
||||
|
||||
internal List<BoxItem> GetBoxItems(BoxStorage storage, int id, string boxFolderId)
|
||||
{
|
||||
var items = CacheChildItems.Get<List<BoxItem>>("box-" + id + "-" + boxFolderId);
|
||||
|
||||
if (items == null)
|
||||
{
|
||||
items = storage.GetItems(boxFolderId);
|
||||
CacheChildItems.Insert("box-" + id + "-" + boxFolderId, items, DateTime.UtcNow.Add(CacheExpiration));
|
||||
}
|
||||
return items;
|
||||
}
|
||||
|
||||
internal void CacheReset(int id, BoxItem boxItem)
|
||||
{
|
||||
if (boxItem != null)
|
||||
{
|
||||
CacheNotify.Publish(new BoxCacheItem { IsFile = boxItem is BoxFile, Key = id + "-" + boxItem.Id }, CacheNotifyAction.Remove);
|
||||
}
|
||||
}
|
||||
|
||||
internal void CacheReset(string boxRootId, int id, string boxId = null, bool? isFile = null)
|
||||
{
|
||||
var key = id + "-";
|
||||
if (boxId == null)
|
||||
{
|
||||
CacheNotify.Publish(new BoxCacheItem { ResetAll = true, Key = key }, CacheNotifyAction.Remove);
|
||||
}
|
||||
else
|
||||
{
|
||||
if (boxId == boxRootId)
|
||||
{
|
||||
boxId = "0";
|
||||
}
|
||||
key += boxId;
|
||||
|
||||
CacheNotify.Publish(new BoxCacheItem { IsFile = isFile ?? false, IsFileExists = isFile.HasValue, Key = key }, CacheNotifyAction.Remove);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
public static class BoxProviderInfoExtension
|
||||
{
|
||||
public static DIHelper AddBoxProviderInfoService(this DIHelper services)
|
||||
{
|
||||
services.TryAddScoped<BoxProviderInfo>();
|
||||
services.TryAddScoped<BoxStorageDisposableWrapper>();
|
||||
services.TryAddSingleton<BoxProviderInfoHelper>();
|
||||
|
||||
return services;
|
||||
}
|
||||
}
|
||||
}
|
103
products/ASC.Files/Server/Core/Thirdparty/Box/BoxSecurityDao.cs
vendored
Normal file
103
products/ASC.Files/Server/Core/Thirdparty/Box/BoxSecurityDao.cs
vendored
Normal file
@ -0,0 +1,103 @@
|
||||
/*
|
||||
*
|
||||
* (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;
|
||||
|
||||
using ASC.Common;
|
||||
using ASC.Common.Logging;
|
||||
using ASC.Core;
|
||||
using ASC.Core.Common.EF;
|
||||
using ASC.Core.Tenants;
|
||||
using ASC.Files.Core;
|
||||
using ASC.Files.Core.EF;
|
||||
using ASC.Files.Core.Security;
|
||||
using ASC.Web.Core.Files;
|
||||
using ASC.Web.Studio.Core;
|
||||
|
||||
using Microsoft.Extensions.Options;
|
||||
|
||||
namespace ASC.Files.Thirdparty.Box
|
||||
{
|
||||
internal class BoxSecurityDao : BoxDaoBase, ISecurityDao<string>
|
||||
{
|
||||
public BoxSecurityDao(IServiceProvider serviceProvider, UserManager userManager, TenantManager tenantManager, TenantUtil tenantUtil, DbContextManager<FilesDbContext> dbContextManager, SetupInfo setupInfo, IOptionsMonitor<ILog> monitor, FileUtility fileUtility) : base(serviceProvider, userManager, tenantManager, tenantUtil, dbContextManager, setupInfo, monitor, fileUtility)
|
||||
{
|
||||
}
|
||||
|
||||
public void SetShare(FileShareRecord r)
|
||||
{
|
||||
}
|
||||
|
||||
public IEnumerable<FileShareRecord> GetShares(IEnumerable<Guid> subjects)
|
||||
{
|
||||
return null;
|
||||
}
|
||||
|
||||
public IEnumerable<FileShareRecord> GetShares(IEnumerable<FileEntry<string>> entry)
|
||||
{
|
||||
return null;
|
||||
}
|
||||
|
||||
public IEnumerable<FileShareRecord> GetShares(FileEntry<string> entry)
|
||||
{
|
||||
return null;
|
||||
}
|
||||
|
||||
public void RemoveSubject(Guid subject)
|
||||
{
|
||||
}
|
||||
|
||||
public IEnumerable<FileShareRecord> GetPureShareRecords(IEnumerable<FileEntry<string>> entries)
|
||||
{
|
||||
return null;
|
||||
}
|
||||
|
||||
public IEnumerable<FileShareRecord> GetPureShareRecords(FileEntry<string> entry)
|
||||
{
|
||||
return null;
|
||||
}
|
||||
|
||||
public void DeleteShareRecords(IEnumerable<FileShareRecord> records)
|
||||
{
|
||||
}
|
||||
|
||||
public bool IsShared(object entryId, FileEntryType type)
|
||||
{
|
||||
throw new NotImplementedException();
|
||||
}
|
||||
}
|
||||
|
||||
public static class BoxSecurityDaoExtention
|
||||
{
|
||||
public static DIHelper AddBoxSecurityDaoService(this DIHelper services)
|
||||
{
|
||||
services.TryAddScoped<BoxSecurityDao>();
|
||||
|
||||
return services;
|
||||
}
|
||||
}
|
||||
}
|
266
products/ASC.Files/Server/Core/Thirdparty/Box/BoxStorage.cs
vendored
Normal file
266
products/ASC.Files/Server/Core/Thirdparty/Box/BoxStorage.cs
vendored
Normal file
@ -0,0 +1,266 @@
|
||||
/*
|
||||
*
|
||||
* (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;
|
||||
using System.IO;
|
||||
using System.Net;
|
||||
using ASC.FederatedLogin;
|
||||
using Box.V2;
|
||||
using Box.V2.Auth;
|
||||
using Box.V2.Config;
|
||||
using Box.V2.Models;
|
||||
using BoxSDK = Box.V2;
|
||||
|
||||
namespace ASC.Files.Thirdparty.Box
|
||||
{
|
||||
internal class BoxStorage
|
||||
{
|
||||
private OAuth20Token _token;
|
||||
|
||||
private BoxClient _boxClient;
|
||||
|
||||
private readonly List<string> _boxFields = new List<string> { "created_at", "modified_at", "name", "parent", "size" };
|
||||
|
||||
public bool IsOpened { get; private set; }
|
||||
|
||||
public long MaxChunkedUploadFileSize = 250L*1024L*1024L;
|
||||
|
||||
public void Open(OAuth20Token token)
|
||||
{
|
||||
if (IsOpened)
|
||||
return;
|
||||
|
||||
_token = token;
|
||||
|
||||
var config = new BoxConfig(_token.ClientID, _token.ClientSecret, new Uri(_token.RedirectUri));
|
||||
var session = new OAuthSession(_token.AccessToken, _token.RefreshToken, (int)_token.ExpiresIn, "bearer");
|
||||
_boxClient = new BoxClient(config, session);
|
||||
|
||||
IsOpened = true;
|
||||
}
|
||||
|
||||
public void Close()
|
||||
{
|
||||
IsOpened = false;
|
||||
}
|
||||
|
||||
|
||||
public string GetRootFolderId()
|
||||
{
|
||||
var root = GetFolder("0");
|
||||
|
||||
return root.Id;
|
||||
}
|
||||
|
||||
public BoxFolder GetFolder(string folderId)
|
||||
{
|
||||
try
|
||||
{
|
||||
return _boxClient.FoldersManager.GetInformationAsync(folderId, _boxFields).Result;
|
||||
}
|
||||
catch (Exception ex)
|
||||
{
|
||||
var boxException = (BoxSDK.Exceptions.BoxException)ex.InnerException;
|
||||
if (boxException != null && boxException.Error.Status == ((int)HttpStatusCode.NotFound).ToString())
|
||||
{
|
||||
return null;
|
||||
}
|
||||
throw;
|
||||
}
|
||||
}
|
||||
|
||||
public BoxFile GetFile(string fileId)
|
||||
{
|
||||
try
|
||||
{
|
||||
return _boxClient.FilesManager.GetInformationAsync(fileId, _boxFields).Result;
|
||||
}
|
||||
catch (Exception ex)
|
||||
{
|
||||
var boxException = (BoxSDK.Exceptions.BoxException)ex.InnerException;
|
||||
if (boxException != null && boxException.Error.Status == ((int)HttpStatusCode.NotFound).ToString())
|
||||
{
|
||||
return null;
|
||||
}
|
||||
throw;
|
||||
}
|
||||
}
|
||||
|
||||
public List<BoxItem> GetItems(string folderId, int limit = 500)
|
||||
{
|
||||
return _boxClient.FoldersManager.GetFolderItemsAsync(folderId, limit, 0, _boxFields).Result.Entries;
|
||||
}
|
||||
|
||||
public Stream DownloadStream(BoxFile file, int offset = 0)
|
||||
{
|
||||
if (file == null) throw new ArgumentNullException("file");
|
||||
|
||||
if (offset > 0 && file.Size.HasValue)
|
||||
{
|
||||
return _boxClient.FilesManager.DownloadStreamAsync(file.Id, startOffsetInBytes: offset, endOffsetInBytes: (int)file.Size - 1).Result;
|
||||
}
|
||||
|
||||
var str = _boxClient.FilesManager.DownloadStreamAsync(file.Id).Result;
|
||||
if (offset == 0)
|
||||
{
|
||||
return str;
|
||||
}
|
||||
|
||||
var tempBuffer = new FileStream(Path.GetTempFileName(), FileMode.OpenOrCreate, FileAccess.ReadWrite, FileShare.Read, 8096, FileOptions.DeleteOnClose);
|
||||
if (str != null)
|
||||
{
|
||||
str.CopyTo(tempBuffer);
|
||||
tempBuffer.Flush();
|
||||
tempBuffer.Seek(offset, SeekOrigin.Begin);
|
||||
|
||||
str.Dispose();
|
||||
}
|
||||
|
||||
return tempBuffer;
|
||||
}
|
||||
|
||||
public BoxFolder CreateFolder(string title, string parentId)
|
||||
{
|
||||
var boxFolderRequest = new BoxFolderRequest
|
||||
{
|
||||
Name = title,
|
||||
Parent = new BoxRequestEntity
|
||||
{
|
||||
Id = parentId
|
||||
}
|
||||
};
|
||||
return _boxClient.FoldersManager.CreateAsync(boxFolderRequest, _boxFields).Result;
|
||||
}
|
||||
|
||||
public BoxFile CreateFile(Stream fileStream, string title, string parentId)
|
||||
{
|
||||
var boxFileRequest = new BoxFileRequest
|
||||
{
|
||||
Name = title,
|
||||
Parent = new BoxRequestEntity
|
||||
{
|
||||
Id = parentId
|
||||
}
|
||||
};
|
||||
return _boxClient.FilesManager.UploadAsync(boxFileRequest, fileStream, _boxFields, setStreamPositionToZero: false).Result;
|
||||
}
|
||||
|
||||
public void DeleteItem(BoxItem boxItem)
|
||||
{
|
||||
if (boxItem is BoxFolder)
|
||||
{
|
||||
_boxClient.FoldersManager.DeleteAsync(boxItem.Id, true).Wait();
|
||||
}
|
||||
else
|
||||
{
|
||||
_boxClient.FilesManager.DeleteAsync(boxItem.Id).Wait();
|
||||
}
|
||||
}
|
||||
|
||||
public BoxFolder MoveFolder(string boxFolderId, string newFolderName, string toFolderId)
|
||||
{
|
||||
var boxFolderRequest = new BoxFolderRequest
|
||||
{
|
||||
Id = boxFolderId,
|
||||
Name = newFolderName,
|
||||
Parent = new BoxRequestEntity
|
||||
{
|
||||
Id = toFolderId
|
||||
}
|
||||
};
|
||||
return _boxClient.FoldersManager.UpdateInformationAsync(boxFolderRequest, _boxFields).Result;
|
||||
}
|
||||
|
||||
public BoxFile MoveFile(string boxFileId, string newFileName, string toFolderId)
|
||||
{
|
||||
var boxFileRequest = new BoxFileRequest
|
||||
{
|
||||
Id = boxFileId,
|
||||
Name = newFileName,
|
||||
Parent = new BoxRequestEntity
|
||||
{
|
||||
Id = toFolderId
|
||||
}
|
||||
};
|
||||
return _boxClient.FilesManager.UpdateInformationAsync(boxFileRequest, null, _boxFields).Result;
|
||||
}
|
||||
|
||||
public BoxFolder CopyFolder(string boxFolderId, string newFolderName, string toFolderId)
|
||||
{
|
||||
var boxFolderRequest = new BoxFolderRequest
|
||||
{
|
||||
Id = boxFolderId,
|
||||
Name = newFolderName,
|
||||
Parent = new BoxRequestEntity
|
||||
{
|
||||
Id = toFolderId
|
||||
}
|
||||
};
|
||||
return _boxClient.FoldersManager.CopyAsync(boxFolderRequest, _boxFields).Result;
|
||||
}
|
||||
|
||||
public BoxFile CopyFile(string boxFileId, string newFileName, string toFolderId)
|
||||
{
|
||||
var boxFileRequest = new BoxFileRequest
|
||||
{
|
||||
Id = boxFileId,
|
||||
Name = newFileName,
|
||||
Parent = new BoxRequestEntity
|
||||
{
|
||||
Id = toFolderId
|
||||
}
|
||||
};
|
||||
return _boxClient.FilesManager.CopyAsync(boxFileRequest, _boxFields).Result;
|
||||
}
|
||||
|
||||
public BoxFolder RenameFolder(string boxFolderId, string newName)
|
||||
{
|
||||
var boxFolderRequest = new BoxFolderRequest { Id = boxFolderId, Name = newName };
|
||||
return _boxClient.FoldersManager.UpdateInformationAsync(boxFolderRequest, _boxFields).Result;
|
||||
}
|
||||
|
||||
public BoxFile RenameFile(string boxFileId, string newName)
|
||||
{
|
||||
var boxFileRequest = new BoxFileRequest { Id = boxFileId, Name = newName };
|
||||
return _boxClient.FilesManager.UpdateInformationAsync(boxFileRequest, null, _boxFields).Result;
|
||||
}
|
||||
|
||||
public BoxFile SaveStream(string fileId, Stream fileStream)
|
||||
{
|
||||
return _boxClient.FilesManager.UploadNewVersionAsync(null, fileId, fileStream, fields: _boxFields, setStreamPositionToZero: false).Result;
|
||||
}
|
||||
|
||||
public long GetMaxUploadSize()
|
||||
{
|
||||
var boxUser = _boxClient.UsersManager.GetCurrentUserInformationAsync(new[] { "max_upload_size" }).Result;
|
||||
var max = boxUser.MaxUploadSize.HasValue ? boxUser.MaxUploadSize.Value : MaxChunkedUploadFileSize;
|
||||
|
||||
//todo: without chunked uploader:
|
||||
return Math.Min(max, MaxChunkedUploadFileSize);
|
||||
}
|
||||
}
|
||||
}
|
180
products/ASC.Files/Server/Core/Thirdparty/Box/BoxTagDao.cs
vendored
Normal file
180
products/ASC.Files/Server/Core/Thirdparty/Box/BoxTagDao.cs
vendored
Normal file
@ -0,0 +1,180 @@
|
||||
/*
|
||||
*
|
||||
* (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;
|
||||
using System.Linq;
|
||||
|
||||
using ASC.Common;
|
||||
using ASC.Common.Logging;
|
||||
using ASC.Core;
|
||||
using ASC.Core.Common.EF;
|
||||
using ASC.Core.Tenants;
|
||||
using ASC.Files.Core;
|
||||
using ASC.Files.Core.EF;
|
||||
using ASC.Files.Thirdparty.Dropbox;
|
||||
using ASC.Web.Core.Files;
|
||||
using ASC.Web.Studio.Core;
|
||||
|
||||
using Microsoft.Extensions.Options;
|
||||
|
||||
namespace ASC.Files.Thirdparty.Box
|
||||
{
|
||||
internal class BoxTagDao : BoxDaoBase, ITagDao<string>
|
||||
{
|
||||
public BoxTagDao(IServiceProvider serviceProvider, UserManager userManager, TenantManager tenantManager, TenantUtil tenantUtil, DbContextManager<FilesDbContext> dbContextManager, SetupInfo setupInfo, IOptionsMonitor<ILog> monitor, FileUtility fileUtility) : base(serviceProvider, userManager, tenantManager, tenantUtil, dbContextManager, setupInfo, monitor, fileUtility)
|
||||
{
|
||||
}
|
||||
|
||||
#region ITagDao Members
|
||||
|
||||
public IEnumerable<Tag> GetTags(TagType tagType, IEnumerable<FileEntry<string>> fileEntries)
|
||||
{
|
||||
return null;
|
||||
}
|
||||
|
||||
public IEnumerable<Tag> GetTags(Guid owner, TagType tagType)
|
||||
{
|
||||
return null;
|
||||
}
|
||||
|
||||
public IEnumerable<Tag> GetTags(string name, TagType tagType)
|
||||
{
|
||||
return null;
|
||||
}
|
||||
|
||||
public IEnumerable<Tag> GetTags(string[] names, TagType tagType)
|
||||
{
|
||||
return null;
|
||||
}
|
||||
|
||||
public IEnumerable<Tag> GetNewTags(Guid subject, Folder<string> parentFolder, bool deepSearch)
|
||||
{
|
||||
var folderId = DaoSelector.ConvertId(parentFolder.ID);
|
||||
var fakeFolderId = parentFolder.ID.ToString();
|
||||
|
||||
var entryIDs = FilesDbContext.ThirdpartyIdMapping
|
||||
.Where(r => r.Id.StartsWith(fakeFolderId))
|
||||
.Select(r => r.HashId)
|
||||
.ToList();
|
||||
|
||||
if (!entryIDs.Any()) return new List<Tag>();
|
||||
|
||||
var q = FilesDbContext.Tag
|
||||
.Join(FilesDbContext.TagLink.DefaultIfEmpty(),
|
||||
r => new TagLink { TenantId = r.TenantId, Id = r.Id },
|
||||
r => new TagLink { TenantId = r.TenantId, Id = r.TagId },
|
||||
(tag, tagLink) => new { tag, tagLink },
|
||||
new TagLinkComparer())
|
||||
.Where(r => r.tag.TenantId == TenantID)
|
||||
.Where(r => r.tag.Flag == TagType.New)
|
||||
.Where(r => r.tagLink.TenantId == TenantID)
|
||||
.Where(r => entryIDs.Any(a => a == r.tagLink.EntryId));
|
||||
|
||||
if (subject != Guid.Empty)
|
||||
{
|
||||
q = q.Where(r => r.tag.Owner == subject);
|
||||
}
|
||||
|
||||
var tags = q
|
||||
.ToList()
|
||||
.Select(r => new Tag
|
||||
{
|
||||
TagName = r.tag.Name,
|
||||
TagType = r.tag.Flag,
|
||||
Owner = r.tag.Owner,
|
||||
EntryId = MappingID(r.tagLink.EntryId),
|
||||
EntryType = r.tagLink.EntryType,
|
||||
Count = r.tagLink.TagCount,
|
||||
Id = r.tag.Id
|
||||
});
|
||||
|
||||
if (deepSearch) return tags;
|
||||
|
||||
var folderFileIds = new[] { fakeFolderId }
|
||||
.Concat(GetChildren(folderId));
|
||||
|
||||
return tags.Where(tag => folderFileIds.Contains(tag.EntryId.ToString()));
|
||||
}
|
||||
|
||||
public IEnumerable<Tag> GetNewTags(Guid subject, IEnumerable<FileEntry<string>> fileEntries)
|
||||
{
|
||||
return null;
|
||||
}
|
||||
|
||||
public IEnumerable<Tag> GetNewTags(Guid subject, FileEntry<string> fileEntry)
|
||||
{
|
||||
return null;
|
||||
}
|
||||
|
||||
public IEnumerable<Tag> SaveTags(IEnumerable<Tag> tag)
|
||||
{
|
||||
return null;
|
||||
}
|
||||
|
||||
public IEnumerable<Tag> SaveTags(Tag tag)
|
||||
{
|
||||
return null;
|
||||
}
|
||||
|
||||
public void UpdateNewTags(IEnumerable<Tag> tag)
|
||||
{
|
||||
}
|
||||
|
||||
public void UpdateNewTags(Tag tag)
|
||||
{
|
||||
}
|
||||
|
||||
public void RemoveTags(IEnumerable<Tag> tag)
|
||||
{
|
||||
}
|
||||
|
||||
public void RemoveTags(Tag tag)
|
||||
{
|
||||
}
|
||||
|
||||
public IEnumerable<Tag> GetTags(string entryID, FileEntryType entryType, TagType tagType)
|
||||
{
|
||||
return null;
|
||||
}
|
||||
|
||||
public void MarkAsNew(Guid subject, FileEntry fileEntry)
|
||||
{
|
||||
}
|
||||
|
||||
#endregion
|
||||
}
|
||||
|
||||
public static class BoxTagDaoExtention
|
||||
{
|
||||
public static DIHelper AddBoxTagDaoService(this DIHelper services)
|
||||
{
|
||||
services.TryAddScoped<BoxTagDao>();
|
||||
|
||||
return services;
|
||||
}
|
||||
}
|
||||
}
|
136
products/ASC.Files/Server/Core/Thirdparty/CachedProviderAccountDao.cs
vendored
Normal file
136
products/ASC.Files/Server/Core/Thirdparty/CachedProviderAccountDao.cs
vendored
Normal file
@ -0,0 +1,136 @@
|
||||
/*
|
||||
*
|
||||
* (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.Concurrent;
|
||||
using System.Globalization;
|
||||
|
||||
using ASC.Common;
|
||||
using ASC.Common.Caching;
|
||||
using ASC.Common.Logging;
|
||||
using ASC.Core;
|
||||
using ASC.Core.Common.Configuration;
|
||||
using ASC.Core.Common.EF;
|
||||
using ASC.Core.Tenants;
|
||||
using ASC.Files.Core;
|
||||
using ASC.Files.Core.EF;
|
||||
using ASC.Security.Cryptography;
|
||||
|
||||
using Microsoft.Extensions.Options;
|
||||
|
||||
namespace ASC.Files.Thirdparty
|
||||
{
|
||||
internal class CachedProviderAccountDaoNotify
|
||||
{
|
||||
public ConcurrentDictionary<string, IProviderInfo> Cache { get; private set; }
|
||||
public ICacheNotify<ProviderAccountCacheItem> CacheNotify { get; private set; }
|
||||
|
||||
public CachedProviderAccountDaoNotify(ICacheNotify<ProviderAccountCacheItem> cacheNotify)
|
||||
{
|
||||
Cache = new ConcurrentDictionary<string, IProviderInfo>();
|
||||
CacheNotify = cacheNotify;
|
||||
cacheNotify.Subscribe((i) => RemoveFromCache(i.Key), CacheNotifyAction.Any);
|
||||
}
|
||||
private void RemoveFromCache(string key)
|
||||
{
|
||||
Cache.TryRemove(key, out _);
|
||||
}
|
||||
}
|
||||
|
||||
internal class CachedProviderAccountDao : ProviderAccountDao
|
||||
{
|
||||
private readonly ConcurrentDictionary<string, IProviderInfo> cache;
|
||||
private readonly ICacheNotify<ProviderAccountCacheItem> cacheNotify;
|
||||
|
||||
private readonly string _rootKey;
|
||||
|
||||
public CachedProviderAccountDao(
|
||||
IServiceProvider serviceProvider,
|
||||
TenantUtil tenantUtil,
|
||||
TenantManager tenantManager,
|
||||
InstanceCrypto instanceCrypto,
|
||||
SecurityContext securityContext,
|
||||
ConsumerFactory consumerFactory,
|
||||
DbContextManager<FilesDbContext> dbContextManager,
|
||||
IOptionsMonitor<ILog> options,
|
||||
CachedProviderAccountDaoNotify cachedProviderAccountDaoNotify)
|
||||
: base(serviceProvider, tenantUtil, tenantManager, instanceCrypto, securityContext, consumerFactory, dbContextManager, options)
|
||||
{
|
||||
cache = cachedProviderAccountDaoNotify.Cache;
|
||||
cacheNotify = cachedProviderAccountDaoNotify.CacheNotify;
|
||||
_rootKey = tenantManager.GetCurrentTenant().TenantId.ToString(CultureInfo.InvariantCulture);
|
||||
}
|
||||
|
||||
public override IProviderInfo GetProviderInfo(int linkId)
|
||||
{
|
||||
var key = _rootKey + linkId.ToString(CultureInfo.InvariantCulture);
|
||||
if (!cache.TryGetValue(key, out var value))
|
||||
{
|
||||
value = base.GetProviderInfo(linkId);
|
||||
cache.TryAdd(key, value);
|
||||
}
|
||||
return value;
|
||||
}
|
||||
|
||||
public override void RemoveProviderInfo(int linkId)
|
||||
{
|
||||
base.RemoveProviderInfo(linkId);
|
||||
|
||||
var key = _rootKey + linkId.ToString(CultureInfo.InvariantCulture);
|
||||
cacheNotify.Publish(new ProviderAccountCacheItem { Key = key }, CacheNotifyAction.Any);
|
||||
}
|
||||
|
||||
public override int UpdateProviderInfo(int linkId, string customerTitle, AuthData authData, FolderType folderType, Guid? userId = null)
|
||||
{
|
||||
var result = base.UpdateProviderInfo(linkId, customerTitle, authData, folderType, userId);
|
||||
|
||||
var key = _rootKey + linkId.ToString(CultureInfo.InvariantCulture);
|
||||
cacheNotify.Publish(new ProviderAccountCacheItem { Key = key }, CacheNotifyAction.Any);
|
||||
return result;
|
||||
}
|
||||
|
||||
public override int UpdateProviderInfo(int linkId, AuthData authData)
|
||||
{
|
||||
var result = base.UpdateProviderInfo(linkId, authData);
|
||||
|
||||
var key = _rootKey + linkId.ToString(CultureInfo.InvariantCulture);
|
||||
cacheNotify.Publish(new ProviderAccountCacheItem { Key = key }, CacheNotifyAction.Any);
|
||||
return result;
|
||||
}
|
||||
}
|
||||
public static class CachedProviderAccountDaoExtention
|
||||
{
|
||||
public static DIHelper AddCachedProviderAccountDaoService(this DIHelper services)
|
||||
{
|
||||
services.TryAddScoped<IProviderDao, ProviderAccountDao>();
|
||||
|
||||
services.TryAddSingleton<CachedProviderAccountDaoNotify>();
|
||||
|
||||
return services
|
||||
.AddProviderAccountDaoService();
|
||||
}
|
||||
}
|
||||
}
|
176
products/ASC.Files/Server/Core/Thirdparty/CrossDao.cs
vendored
Normal file
176
products/ASC.Files/Server/Core/Thirdparty/CrossDao.cs
vendored
Normal file
@ -0,0 +1,176 @@
|
||||
using System;
|
||||
using System.Linq;
|
||||
using System.Threading;
|
||||
|
||||
using ASC.Files.Core.Data;
|
||||
using ASC.Files.Resources;
|
||||
using ASC.Web.Files.Utils;
|
||||
using ASC.Web.Studio.Core;
|
||||
|
||||
using Microsoft.Extensions.DependencyInjection;
|
||||
|
||||
namespace ASC.Files.Core.Thirdparty
|
||||
{
|
||||
internal class CrossDao
|
||||
{
|
||||
private IServiceProvider ServiceProvider { get; }
|
||||
private SetupInfo SetupInfo { get; }
|
||||
private FileConverter FileConverter { get; }
|
||||
|
||||
public CrossDao(
|
||||
IServiceProvider serviceProvider,
|
||||
SetupInfo setupInfo,
|
||||
FileConverter fileConverter)
|
||||
{
|
||||
ServiceProvider = serviceProvider;
|
||||
SetupInfo = setupInfo;
|
||||
FileConverter = fileConverter;
|
||||
}
|
||||
|
||||
public File<TTo> PerformCrossDaoFileCopy<TFrom, TTo>(
|
||||
TFrom fromFileId, IFileDao<TFrom> fromFileDao, Func<TFrom, TFrom> fromConverter,
|
||||
TTo toFolderId, IFileDao<TTo> toFileDao, Func<TTo, TTo> toConverter,
|
||||
bool deleteSourceFile)
|
||||
{
|
||||
//Get File from first dao
|
||||
var fromFile = fromFileDao.GetFile(fromConverter(fromFileId));
|
||||
|
||||
if (fromFile.ContentLength > SetupInfo.AvailableFileSize)
|
||||
{
|
||||
throw new Exception(string.Format(deleteSourceFile ? FilesCommonResource.ErrorMassage_FileSizeMove : FilesCommonResource.ErrorMassage_FileSizeCopy,
|
||||
FileSizeComment.FilesSizeToString(SetupInfo.AvailableFileSize)));
|
||||
}
|
||||
|
||||
var securityDao = ServiceProvider.GetService<SecurityDao<TFrom>>();
|
||||
var tagDao = ServiceProvider.GetService<TagDao<TFrom>>();
|
||||
|
||||
var fromFileShareRecords = securityDao.GetPureShareRecords(fromFile).Where(x => x.EntryType == FileEntryType.File);
|
||||
var fromFileNewTags = tagDao.GetNewTags(Guid.Empty, fromFile).ToList();
|
||||
var fromFileLockTag = tagDao.GetTags(fromFile.ID, FileEntryType.File, TagType.Locked).FirstOrDefault();
|
||||
|
||||
var toFile = ServiceProvider.GetService<File<TTo>>();
|
||||
|
||||
toFile.Title = fromFile.Title;
|
||||
toFile.Encrypted = fromFile.Encrypted;
|
||||
toFile.FolderID = toConverter(toFolderId);
|
||||
|
||||
fromFile.ID = fromConverter(fromFile.ID);
|
||||
|
||||
var mustConvert = !string.IsNullOrEmpty(fromFile.ConvertedType);
|
||||
using (var fromFileStream = mustConvert
|
||||
? FileConverter.Exec(fromFile)
|
||||
: fromFileDao.GetFileStream(fromFile))
|
||||
{
|
||||
toFile.ContentLength = fromFileStream.CanSeek ? fromFileStream.Length : fromFile.ContentLength;
|
||||
toFile = toFileDao.SaveFile(toFile, fromFileStream);
|
||||
}
|
||||
|
||||
if (deleteSourceFile)
|
||||
{
|
||||
if (fromFileShareRecords.Any())
|
||||
fromFileShareRecords.ToList().ForEach(x =>
|
||||
{
|
||||
x.EntryId = toFile.ID;
|
||||
securityDao.SetShare(x);
|
||||
});
|
||||
|
||||
var fromFileTags = fromFileNewTags;
|
||||
if (fromFileLockTag != null) fromFileTags.Add(fromFileLockTag);
|
||||
|
||||
if (fromFileTags.Any())
|
||||
{
|
||||
fromFileTags.ForEach(x => x.EntryId = toFile.ID);
|
||||
|
||||
tagDao.SaveTags(fromFileTags);
|
||||
}
|
||||
|
||||
//Delete source file if needed
|
||||
fromFileDao.DeleteFile(fromConverter(fromFileId));
|
||||
}
|
||||
return toFile;
|
||||
}
|
||||
|
||||
public Folder<TTo> PerformCrossDaoFolderCopy<TFrom, TTo>
|
||||
(TFrom fromFolderId, IFolderDao<TFrom> fromFolderDao, IFileDao<TFrom> fromFileDao, Func<TFrom, TFrom> fromConverter,
|
||||
TTo toRootFolderId, IFolderDao<TTo> toFolderDao, IFileDao<TTo> toFileDao, Func<TTo, TTo> toConverter,
|
||||
bool deleteSourceFolder, CancellationToken? cancellationToken)
|
||||
{
|
||||
var fromFolder = fromFolderDao.GetFolder(fromConverter(fromFolderId));
|
||||
|
||||
var toFolder1 = ServiceProvider.GetService<Folder<TTo>>();
|
||||
toFolder1.Title = fromFolder.Title;
|
||||
toFolder1.ParentFolderID = toConverter(toRootFolderId);
|
||||
|
||||
var toFolder = toFolderDao.GetFolder(fromFolder.Title, toConverter(toRootFolderId));
|
||||
var toFolderId = toFolder != null
|
||||
? toFolder.ID
|
||||
: toFolderDao.SaveFolder(toFolder1);
|
||||
|
||||
var foldersToCopy = fromFolderDao.GetFolders(fromConverter(fromFolderId));
|
||||
var fileIdsToCopy = fromFileDao.GetFiles(fromConverter(fromFolderId));
|
||||
Exception copyException = null;
|
||||
//Copy files first
|
||||
foreach (var fileId in fileIdsToCopy)
|
||||
{
|
||||
if (cancellationToken.HasValue) cancellationToken.Value.ThrowIfCancellationRequested();
|
||||
try
|
||||
{
|
||||
PerformCrossDaoFileCopy(fileId, fromFileDao, fromConverter,
|
||||
toFolderId, toFileDao, toConverter,
|
||||
deleteSourceFolder);
|
||||
}
|
||||
catch (Exception ex)
|
||||
{
|
||||
copyException = ex;
|
||||
}
|
||||
}
|
||||
foreach (var folder in foldersToCopy)
|
||||
{
|
||||
if (cancellationToken.HasValue) cancellationToken.Value.ThrowIfCancellationRequested();
|
||||
try
|
||||
{
|
||||
PerformCrossDaoFolderCopy(folder.ID, fromFolderDao, fromFileDao, fromConverter,
|
||||
toFolderId, toFolderDao, toFileDao, toConverter,
|
||||
deleteSourceFolder, cancellationToken);
|
||||
}
|
||||
catch (Exception ex)
|
||||
{
|
||||
copyException = ex;
|
||||
}
|
||||
}
|
||||
|
||||
if (deleteSourceFolder)
|
||||
{
|
||||
var securityDao = ServiceProvider.GetService<SecurityDao<TFrom>>();
|
||||
var fromFileShareRecords = securityDao.GetPureShareRecords(fromFolder)
|
||||
.Where(x => x.EntryType == FileEntryType.Folder);
|
||||
|
||||
if (fromFileShareRecords.Any())
|
||||
{
|
||||
fromFileShareRecords.ToList().ForEach(x =>
|
||||
{
|
||||
x.EntryId = toFolderId;
|
||||
securityDao.SetShare(x);
|
||||
});
|
||||
}
|
||||
|
||||
var tagDao = ServiceProvider.GetService<TagDao<TFrom>>();
|
||||
var fromFileNewTags = tagDao.GetNewTags(Guid.Empty, fromFolder).ToList();
|
||||
|
||||
if (fromFileNewTags.Any())
|
||||
{
|
||||
fromFileNewTags.ForEach(x => x.EntryId = toFolderId);
|
||||
|
||||
tagDao.SaveTags(fromFileNewTags);
|
||||
}
|
||||
|
||||
if (copyException == null)
|
||||
fromFolderDao.DeleteFolder(fromConverter(fromFolderId));
|
||||
}
|
||||
|
||||
if (copyException != null) throw copyException;
|
||||
|
||||
return toFolderDao.GetFolder(toConverter(toFolderId));
|
||||
}
|
||||
}
|
||||
}
|
311
products/ASC.Files/Server/Core/Thirdparty/Dropbox/DropboxDaoBase.cs
vendored
Normal file
311
products/ASC.Files/Server/Core/Thirdparty/Dropbox/DropboxDaoBase.cs
vendored
Normal file
@ -0,0 +1,311 @@
|
||||
/*
|
||||
*
|
||||
* (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;
|
||||
using System.Globalization;
|
||||
using System.Linq;
|
||||
using System.Text.RegularExpressions;
|
||||
|
||||
using ASC.Common.Logging;
|
||||
using ASC.Core;
|
||||
using ASC.Core.Common.EF;
|
||||
using ASC.Core.Tenants;
|
||||
using ASC.Files.Core;
|
||||
using ASC.Files.Core.EF;
|
||||
using ASC.Web.Core.Files;
|
||||
using ASC.Web.Files.Classes;
|
||||
using ASC.Web.Studio.Core;
|
||||
|
||||
using Dropbox.Api.Files;
|
||||
|
||||
using Microsoft.Extensions.Options;
|
||||
|
||||
namespace ASC.Files.Thirdparty.Dropbox
|
||||
{
|
||||
internal abstract class DropboxDaoBase : ThirdPartyProviderDao<DropboxProviderInfo>
|
||||
{
|
||||
public override string Id { get => "dropbox"; }
|
||||
|
||||
public DropboxDaoBase(IServiceProvider serviceProvider, UserManager userManager, TenantManager tenantManager, TenantUtil tenantUtil, DbContextManager<FilesDbContext> dbContextManager, SetupInfo setupInfo, IOptionsMonitor<ILog> monitor, FileUtility fileUtility) : base(serviceProvider, userManager, tenantManager, tenantUtil, dbContextManager, setupInfo, monitor, fileUtility)
|
||||
{
|
||||
}
|
||||
|
||||
protected static string GetParentFolderPath(Metadata dropboxItem)
|
||||
{
|
||||
if (dropboxItem == null || IsRoot(dropboxItem.AsFolder))
|
||||
return null;
|
||||
|
||||
var pathLength = dropboxItem.PathDisplay.Length - dropboxItem.Name.Length;
|
||||
return dropboxItem.PathDisplay.Substring(0, pathLength > 1 ? pathLength - 1 : 0);
|
||||
}
|
||||
|
||||
protected static string MakeDropboxPath(object entryId)
|
||||
{
|
||||
return Convert.ToString(entryId, CultureInfo.InvariantCulture);
|
||||
}
|
||||
|
||||
protected string MakeDropboxPath(Metadata dropboxItem)
|
||||
{
|
||||
string path = null;
|
||||
if (dropboxItem != null)
|
||||
{
|
||||
path = dropboxItem.PathDisplay;
|
||||
}
|
||||
|
||||
return path;
|
||||
}
|
||||
|
||||
protected string MakeId(Metadata dropboxItem)
|
||||
{
|
||||
return MakeId(MakeDropboxPath(dropboxItem));
|
||||
}
|
||||
|
||||
protected override string MakeId(string path = null)
|
||||
{
|
||||
return string.Format("{0}{1}", PathPrefix, string.IsNullOrEmpty(path) || path == "/" ? "" : ("-" + path.Replace('/', '|')));
|
||||
}
|
||||
|
||||
protected string MakeFolderTitle(FolderMetadata dropboxFolder)
|
||||
{
|
||||
if (dropboxFolder == null || IsRoot(dropboxFolder))
|
||||
{
|
||||
return ProviderInfo.CustomerTitle;
|
||||
}
|
||||
|
||||
return Global.ReplaceInvalidCharsAndTruncate(dropboxFolder.Name);
|
||||
}
|
||||
|
||||
protected string MakeFileTitle(FileMetadata dropboxFile)
|
||||
{
|
||||
if (dropboxFile == null || string.IsNullOrEmpty(dropboxFile.Name))
|
||||
{
|
||||
return ProviderInfo.ProviderKey;
|
||||
}
|
||||
|
||||
return Global.ReplaceInvalidCharsAndTruncate(dropboxFile.Name);
|
||||
}
|
||||
|
||||
protected Folder<string> ToFolder(FolderMetadata dropboxFolder)
|
||||
{
|
||||
if (dropboxFolder == null) return null;
|
||||
if (dropboxFolder is ErrorFolder)
|
||||
{
|
||||
//Return error entry
|
||||
return ToErrorFolder(dropboxFolder as ErrorFolder);
|
||||
}
|
||||
|
||||
var isRoot = IsRoot(dropboxFolder);
|
||||
|
||||
var folder = GetFolder();
|
||||
|
||||
folder.ID = MakeId(dropboxFolder);
|
||||
folder.ParentFolderID = isRoot ? null : MakeId(GetParentFolderPath(dropboxFolder));
|
||||
folder.CreateOn = isRoot ? ProviderInfo.CreateOn : default;
|
||||
folder.ModifiedOn = isRoot ? ProviderInfo.CreateOn : default;
|
||||
folder.Title = MakeFolderTitle(dropboxFolder);
|
||||
|
||||
if (folder.CreateOn != DateTime.MinValue && folder.CreateOn.Kind == DateTimeKind.Utc)
|
||||
folder.CreateOn = TenantUtil.DateTimeFromUtc(folder.CreateOn);
|
||||
|
||||
if (folder.ModifiedOn != DateTime.MinValue && folder.ModifiedOn.Kind == DateTimeKind.Utc)
|
||||
folder.ModifiedOn = TenantUtil.DateTimeFromUtc(folder.ModifiedOn);
|
||||
|
||||
return folder;
|
||||
}
|
||||
|
||||
protected static bool IsRoot(FolderMetadata dropboxFolder)
|
||||
{
|
||||
return dropboxFolder != null && dropboxFolder.Id == "/";
|
||||
}
|
||||
|
||||
private File<string> ToErrorFile(ErrorFile dropboxFile)
|
||||
{
|
||||
if (dropboxFile == null) return null;
|
||||
|
||||
var file = GetErrorFile(new ErrorEntry(dropboxFile.ErrorId, dropboxFile.Error));
|
||||
|
||||
file.Title = MakeFileTitle(dropboxFile);
|
||||
|
||||
return file;
|
||||
}
|
||||
|
||||
private Folder<string> ToErrorFolder(ErrorFolder dropboxFolder)
|
||||
{
|
||||
if (dropboxFolder == null) return null;
|
||||
|
||||
var folder = GetErrorFolder(new ErrorEntry(dropboxFolder.Error, dropboxFolder.ErrorId));
|
||||
|
||||
folder.Title = MakeFolderTitle(dropboxFolder);
|
||||
|
||||
return folder;
|
||||
}
|
||||
|
||||
public File<string> ToFile(FileMetadata dropboxFile)
|
||||
{
|
||||
if (dropboxFile == null) return null;
|
||||
|
||||
if (dropboxFile is ErrorFile)
|
||||
{
|
||||
//Return error entry
|
||||
return ToErrorFile(dropboxFile as ErrorFile);
|
||||
}
|
||||
|
||||
var file = GetFile();
|
||||
|
||||
file.ID = MakeId(dropboxFile);
|
||||
file.ContentLength = (long)dropboxFile.Size;
|
||||
file.CreateOn = TenantUtil.DateTimeFromUtc(dropboxFile.ServerModified);
|
||||
file.FolderID = MakeId(GetParentFolderPath(dropboxFile));
|
||||
file.ModifiedOn = TenantUtil.DateTimeFromUtc(dropboxFile.ServerModified);
|
||||
file.NativeAccessor = dropboxFile;
|
||||
file.Title = MakeFileTitle(dropboxFile);
|
||||
|
||||
return file;
|
||||
}
|
||||
|
||||
public Folder<string> GetRootFolder(string folderId)
|
||||
{
|
||||
return ToFolder(GetDropboxFolder(string.Empty));
|
||||
}
|
||||
|
||||
protected FolderMetadata GetDropboxFolder(string folderId)
|
||||
{
|
||||
var dropboxFolderPath = MakeDropboxPath(folderId);
|
||||
try
|
||||
{
|
||||
var folder = ProviderInfo.GetDropboxFolder(dropboxFolderPath);
|
||||
return folder;
|
||||
}
|
||||
catch (Exception ex)
|
||||
{
|
||||
return new ErrorFolder(ex, dropboxFolderPath);
|
||||
}
|
||||
}
|
||||
|
||||
protected FileMetadata GetDropboxFile(object fileId)
|
||||
{
|
||||
var dropboxFilePath = MakeDropboxPath(fileId);
|
||||
try
|
||||
{
|
||||
var file = ProviderInfo.GetDropboxFile(dropboxFilePath);
|
||||
return file;
|
||||
}
|
||||
catch (Exception ex)
|
||||
{
|
||||
return new ErrorFile(ex, dropboxFilePath);
|
||||
}
|
||||
}
|
||||
|
||||
protected IEnumerable<string> GetChildren(object folderId)
|
||||
{
|
||||
return GetDropboxItems(folderId).Select(MakeId);
|
||||
}
|
||||
|
||||
protected List<Metadata> GetDropboxItems(object parentId, bool? folder = null)
|
||||
{
|
||||
var dropboxFolderPath = MakeDropboxPath(parentId);
|
||||
var items = ProviderInfo.GetDropboxItems(dropboxFolderPath);
|
||||
|
||||
if (folder.HasValue)
|
||||
{
|
||||
if (folder.Value)
|
||||
{
|
||||
return items.Where(i => i.AsFolder != null).ToList();
|
||||
}
|
||||
|
||||
return items.Where(i => i.AsFile != null).ToList();
|
||||
}
|
||||
|
||||
return items;
|
||||
}
|
||||
|
||||
protected sealed class ErrorFolder : FolderMetadata
|
||||
{
|
||||
public string Error { get; set; }
|
||||
|
||||
public string ErrorId { get; private set; }
|
||||
|
||||
|
||||
public ErrorFolder(Exception e, object id)
|
||||
{
|
||||
ErrorId = id.ToString();
|
||||
if (e != null)
|
||||
{
|
||||
Error = e.Message;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
protected sealed class ErrorFile : FileMetadata
|
||||
{
|
||||
public string Error { get; set; }
|
||||
|
||||
public string ErrorId { get; private set; }
|
||||
|
||||
|
||||
public ErrorFile(Exception e, object id)
|
||||
{
|
||||
ErrorId = id.ToString();
|
||||
if (e != null)
|
||||
{
|
||||
Error = e.Message;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
protected string GetAvailableTitle(string requestTitle, string parentFolderPath, Func<string, string, bool> isExist)
|
||||
{
|
||||
if (!isExist(requestTitle, parentFolderPath)) return requestTitle;
|
||||
|
||||
var re = new Regex(@"( \(((?<index>[0-9])+)\)(\.[^\.]*)?)$");
|
||||
var match = re.Match(requestTitle);
|
||||
|
||||
if (!match.Success)
|
||||
{
|
||||
var insertIndex = requestTitle.Length;
|
||||
if (requestTitle.LastIndexOf(".", StringComparison.InvariantCulture) != -1)
|
||||
{
|
||||
insertIndex = requestTitle.LastIndexOf(".", StringComparison.InvariantCulture);
|
||||
}
|
||||
requestTitle = requestTitle.Insert(insertIndex, " (1)");
|
||||
}
|
||||
|
||||
while (isExist(requestTitle, parentFolderPath))
|
||||
{
|
||||
requestTitle = re.Replace(requestTitle, MatchEvaluator);
|
||||
}
|
||||
return requestTitle;
|
||||
}
|
||||
|
||||
private static string MatchEvaluator(Match match)
|
||||
{
|
||||
var index = Convert.ToInt32(match.Groups[2].Value);
|
||||
var staticText = match.Value.Substring(string.Format(" ({0})", index).Length);
|
||||
return string.Format(" ({0}){1}", index + 1, staticText);
|
||||
}
|
||||
}
|
||||
}
|
79
products/ASC.Files/Server/Core/Thirdparty/Dropbox/DropboxDaoSelector.cs
vendored
Normal file
79
products/ASC.Files/Server/Core/Thirdparty/Dropbox/DropboxDaoSelector.cs
vendored
Normal file
@ -0,0 +1,79 @@
|
||||
/*
|
||||
*
|
||||
* (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 ASC.Common;
|
||||
using ASC.Files.Core;
|
||||
using ASC.Files.Core.Security;
|
||||
|
||||
namespace ASC.Files.Thirdparty.Dropbox
|
||||
{
|
||||
internal class DropboxDaoSelector : RegexDaoSelectorBase<DropboxProviderInfo>, IDaoSelector
|
||||
{
|
||||
protected internal override string Name { get => "Dropbox"; }
|
||||
protected internal override string Id { get => "dropbox"; }
|
||||
|
||||
public DropboxDaoSelector(IServiceProvider serviceProvider, IDaoFactory daoFactory)
|
||||
: base(serviceProvider, daoFactory)
|
||||
{
|
||||
}
|
||||
|
||||
public IFileDao<string> GetFileDao(string id)
|
||||
{
|
||||
return base.GetFileDao<DropboxFileDao>(id);
|
||||
}
|
||||
|
||||
public IFolderDao<string> GetFolderDao(string id)
|
||||
{
|
||||
return base.GetFolderDao<DropboxFolderDao>(id);
|
||||
}
|
||||
|
||||
public ITagDao<string> GetTagDao(string id)
|
||||
{
|
||||
return base.GetTagDao<DropboxTagDao>(id);
|
||||
}
|
||||
|
||||
public ISecurityDao<string> GetSecurityDao(string id)
|
||||
{
|
||||
return base.GetSecurityDao<DropboxSecurityDao>(id);
|
||||
}
|
||||
}
|
||||
|
||||
public static class DropboxDaoSelectorExtention
|
||||
{
|
||||
public static DIHelper AddDropboxDaoSelectorService(this DIHelper services)
|
||||
{
|
||||
services.TryAddScoped<DropboxDaoSelector>();
|
||||
|
||||
return services
|
||||
.AddDropboxSecurityDaoService()
|
||||
.AddDropboxTagDaoService()
|
||||
.AddDropboxFolderDaoService()
|
||||
.AddDropboxFileDaoService();
|
||||
}
|
||||
}
|
||||
}
|
668
products/ASC.Files/Server/Core/Thirdparty/Dropbox/DropboxFileDao.cs
vendored
Normal file
668
products/ASC.Files/Server/Core/Thirdparty/Dropbox/DropboxFileDao.cs
vendored
Normal file
@ -0,0 +1,668 @@
|
||||
/*
|
||||
*
|
||||
* (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;
|
||||
using System.IO;
|
||||
using System.Linq;
|
||||
|
||||
using ASC.Common;
|
||||
using ASC.Common.Logging;
|
||||
using ASC.Core;
|
||||
using ASC.Core.Common.EF;
|
||||
using ASC.Core.Tenants;
|
||||
using ASC.Files.Core;
|
||||
using ASC.Files.Core.EF;
|
||||
using ASC.Files.Core.Thirdparty;
|
||||
using ASC.Files.Resources;
|
||||
using ASC.Web.Core.Files;
|
||||
using ASC.Web.Files.Services.DocumentService;
|
||||
using ASC.Web.Studio.Core;
|
||||
|
||||
using Dropbox.Api.Files;
|
||||
|
||||
using Microsoft.Extensions.Options;
|
||||
|
||||
namespace ASC.Files.Thirdparty.Dropbox
|
||||
{
|
||||
internal class DropboxFileDao : DropboxDaoBase, IFileDao<string>
|
||||
{
|
||||
public CrossDao CrossDao { get; }
|
||||
public DropboxDaoSelector DropboxDaoSelector { get; }
|
||||
public IFileDao<int> FileDao { get; }
|
||||
|
||||
public DropboxFileDao(
|
||||
IServiceProvider serviceProvider,
|
||||
UserManager userManager,
|
||||
TenantManager tenantManager,
|
||||
TenantUtil tenantUtil,
|
||||
DbContextManager<FilesDbContext> dbContextManager,
|
||||
SetupInfo setupInfo,
|
||||
IOptionsMonitor<ILog> monitor,
|
||||
FileUtility fileUtility,
|
||||
CrossDao crossDao,
|
||||
DropboxDaoSelector dropboxDaoSelector,
|
||||
IFileDao<int> fileDao)
|
||||
: base(serviceProvider, userManager, tenantManager, tenantUtil, dbContextManager, setupInfo, monitor, fileUtility)
|
||||
{
|
||||
CrossDao = crossDao;
|
||||
DropboxDaoSelector = dropboxDaoSelector;
|
||||
FileDao = fileDao;
|
||||
}
|
||||
|
||||
public void InvalidateCache(string fileId)
|
||||
{
|
||||
var dropboxFilePath = MakeDropboxPath(fileId);
|
||||
ProviderInfo.CacheReset(dropboxFilePath, true);
|
||||
|
||||
var dropboxFile = GetDropboxFile(fileId);
|
||||
var parentPath = GetParentFolderPath(dropboxFile);
|
||||
if (parentPath != null) ProviderInfo.CacheReset(parentPath);
|
||||
}
|
||||
|
||||
public File<string> GetFile(string fileId)
|
||||
{
|
||||
return GetFile(fileId, 1);
|
||||
}
|
||||
|
||||
public File<string> GetFile(string fileId, int fileVersion)
|
||||
{
|
||||
return ToFile(GetDropboxFile(fileId));
|
||||
}
|
||||
|
||||
public File<string> GetFile(string parentId, string title)
|
||||
{
|
||||
var metadata = GetDropboxItems(parentId, false)
|
||||
.FirstOrDefault(item => item.Name.Equals(title, StringComparison.InvariantCultureIgnoreCase));
|
||||
return metadata == null
|
||||
? null
|
||||
: ToFile(metadata.AsFile);
|
||||
}
|
||||
|
||||
public File<string> GetFileStable(string fileId, int fileVersion)
|
||||
{
|
||||
return ToFile(GetDropboxFile(fileId));
|
||||
}
|
||||
|
||||
public List<File<string>> GetFileHistory(string fileId)
|
||||
{
|
||||
return new List<File<string>> { GetFile(fileId) };
|
||||
}
|
||||
|
||||
public List<File<string>> GetFiles(string[] fileIds)
|
||||
{
|
||||
if (fileIds == null || fileIds.Length == 0) return new List<File<string>>();
|
||||
return fileIds.Select(GetDropboxFile).Select(ToFile).ToList();
|
||||
}
|
||||
|
||||
public List<File<string>> GetFilesForShare(string[] fileIds, FilterType filterType, bool subjectGroup, Guid subjectID, string searchText, bool searchInContent)
|
||||
{
|
||||
if (fileIds == null || fileIds.Length == 0 || filterType == FilterType.FoldersOnly) return new List<File<string>>();
|
||||
|
||||
var files = GetFiles(fileIds).AsEnumerable();
|
||||
|
||||
//Filter
|
||||
if (subjectID != Guid.Empty)
|
||||
{
|
||||
files = files.Where(x => subjectGroup
|
||||
? UserManager.IsUserInGroup(x.CreateBy, subjectID)
|
||||
: x.CreateBy == subjectID);
|
||||
}
|
||||
|
||||
switch (filterType)
|
||||
{
|
||||
case FilterType.FoldersOnly:
|
||||
return new List<File<string>>();
|
||||
case FilterType.DocumentsOnly:
|
||||
files = files.Where(x => FileUtility.GetFileTypeByFileName(x.Title) == FileType.Document);
|
||||
break;
|
||||
case FilterType.PresentationsOnly:
|
||||
files = files.Where(x => FileUtility.GetFileTypeByFileName(x.Title) == FileType.Presentation);
|
||||
break;
|
||||
case FilterType.SpreadsheetsOnly:
|
||||
files = files.Where(x => FileUtility.GetFileTypeByFileName(x.Title) == FileType.Spreadsheet);
|
||||
break;
|
||||
case FilterType.ImagesOnly:
|
||||
files = files.Where(x => FileUtility.GetFileTypeByFileName(x.Title) == FileType.Image);
|
||||
break;
|
||||
case FilterType.ArchiveOnly:
|
||||
files = files.Where(x => FileUtility.GetFileTypeByFileName(x.Title) == FileType.Archive);
|
||||
break;
|
||||
case FilterType.MediaOnly:
|
||||
files = files.Where(x =>
|
||||
{
|
||||
FileType fileType;
|
||||
return (fileType = FileUtility.GetFileTypeByFileName(x.Title)) == FileType.Audio || fileType == FileType.Video;
|
||||
});
|
||||
break;
|
||||
case FilterType.ByExtension:
|
||||
if (!string.IsNullOrEmpty(searchText))
|
||||
files = files.Where(x => FileUtility.GetFileExtension(x.Title).Contains(searchText));
|
||||
break;
|
||||
}
|
||||
|
||||
if (!string.IsNullOrEmpty(searchText))
|
||||
files = files.Where(x => x.Title.IndexOf(searchText, StringComparison.OrdinalIgnoreCase) != -1);
|
||||
|
||||
return files.ToList();
|
||||
}
|
||||
|
||||
public List<string> GetFiles(string parentId)
|
||||
{
|
||||
return GetDropboxItems(parentId, false).Select(entry => MakeId(entry)).ToList();
|
||||
}
|
||||
|
||||
public List<File<string>> GetFiles(string parentId, OrderBy orderBy, FilterType filterType, bool subjectGroup, Guid subjectID, string searchText, bool searchInContent, bool withSubfolders = false)
|
||||
{
|
||||
if (filterType == FilterType.FoldersOnly) return new List<File<string>>();
|
||||
|
||||
//Get only files
|
||||
var files = GetDropboxItems(parentId, false).Select(item => ToFile(item.AsFile));
|
||||
|
||||
//Filter
|
||||
if (subjectID != Guid.Empty)
|
||||
{
|
||||
files = files.Where(x => subjectGroup
|
||||
? UserManager.IsUserInGroup(x.CreateBy, subjectID)
|
||||
: x.CreateBy == subjectID);
|
||||
}
|
||||
|
||||
switch (filterType)
|
||||
{
|
||||
case FilterType.FoldersOnly:
|
||||
return new List<File<string>>();
|
||||
case FilterType.DocumentsOnly:
|
||||
files = files.Where(x => FileUtility.GetFileTypeByFileName(x.Title) == FileType.Document);
|
||||
break;
|
||||
case FilterType.PresentationsOnly:
|
||||
files = files.Where(x => FileUtility.GetFileTypeByFileName(x.Title) == FileType.Presentation);
|
||||
break;
|
||||
case FilterType.SpreadsheetsOnly:
|
||||
files = files.Where(x => FileUtility.GetFileTypeByFileName(x.Title) == FileType.Spreadsheet);
|
||||
break;
|
||||
case FilterType.ImagesOnly:
|
||||
files = files.Where(x => FileUtility.GetFileTypeByFileName(x.Title) == FileType.Image);
|
||||
break;
|
||||
case FilterType.ArchiveOnly:
|
||||
files = files.Where(x => FileUtility.GetFileTypeByFileName(x.Title) == FileType.Archive);
|
||||
break;
|
||||
case FilterType.MediaOnly:
|
||||
files = files.Where(x =>
|
||||
{
|
||||
FileType fileType;
|
||||
return (fileType = FileUtility.GetFileTypeByFileName(x.Title)) == FileType.Audio || fileType == FileType.Video;
|
||||
});
|
||||
break;
|
||||
case FilterType.ByExtension:
|
||||
if (!string.IsNullOrEmpty(searchText))
|
||||
files = files.Where(x => FileUtility.GetFileExtension(x.Title).Contains(searchText));
|
||||
break;
|
||||
}
|
||||
|
||||
if (!string.IsNullOrEmpty(searchText))
|
||||
files = files.Where(x => x.Title.IndexOf(searchText, StringComparison.OrdinalIgnoreCase) != -1);
|
||||
|
||||
if (orderBy == null) orderBy = new OrderBy(SortedByType.DateAndTime, false);
|
||||
|
||||
switch (orderBy.SortedBy)
|
||||
{
|
||||
case SortedByType.Author:
|
||||
files = orderBy.IsAsc ? files.OrderBy(x => x.CreateBy) : files.OrderByDescending(x => x.CreateBy);
|
||||
break;
|
||||
case SortedByType.AZ:
|
||||
files = orderBy.IsAsc ? files.OrderBy(x => x.Title) : files.OrderByDescending(x => x.Title);
|
||||
break;
|
||||
case SortedByType.DateAndTime:
|
||||
files = orderBy.IsAsc ? files.OrderBy(x => x.ModifiedOn) : files.OrderByDescending(x => x.ModifiedOn);
|
||||
break;
|
||||
case SortedByType.DateAndTimeCreation:
|
||||
files = orderBy.IsAsc ? files.OrderBy(x => x.CreateOn) : files.OrderByDescending(x => x.CreateOn);
|
||||
break;
|
||||
default:
|
||||
files = orderBy.IsAsc ? files.OrderBy(x => x.Title) : files.OrderByDescending(x => x.Title);
|
||||
break;
|
||||
}
|
||||
|
||||
return files.ToList();
|
||||
}
|
||||
|
||||
public Stream GetFileStream(File<string> file)
|
||||
{
|
||||
return GetFileStream(file, 0);
|
||||
}
|
||||
|
||||
public Stream GetFileStream(File<string> file, long offset)
|
||||
{
|
||||
var dropboxFilePath = MakeDropboxPath(file.ID);
|
||||
ProviderInfo.CacheReset(dropboxFilePath, true);
|
||||
|
||||
var dropboxFile = GetDropboxFile(file.ID);
|
||||
if (dropboxFile == null) throw new ArgumentNullException("file", FilesCommonResource.ErrorMassage_FileNotFound);
|
||||
if (dropboxFile is ErrorFile) throw new Exception(((ErrorFile)dropboxFile).Error);
|
||||
|
||||
var fileStream = ProviderInfo.Storage.DownloadStream(MakeDropboxPath(dropboxFile), (int)offset);
|
||||
|
||||
return fileStream;
|
||||
}
|
||||
|
||||
public Uri GetPreSignedUri(File<string> file, TimeSpan expires)
|
||||
{
|
||||
throw new NotSupportedException();
|
||||
}
|
||||
|
||||
public bool IsSupportedPreSignedUri(File<string> file)
|
||||
{
|
||||
return false;
|
||||
}
|
||||
|
||||
public File<string> SaveFile(File<string> file, Stream fileStream)
|
||||
{
|
||||
if (file == null) throw new ArgumentNullException("file");
|
||||
if (fileStream == null) throw new ArgumentNullException("fileStream");
|
||||
|
||||
FileMetadata newDropboxFile = null;
|
||||
|
||||
if (file.ID != null)
|
||||
{
|
||||
var filePath = MakeDropboxPath(file.ID);
|
||||
newDropboxFile = ProviderInfo.Storage.SaveStream(filePath, fileStream);
|
||||
if (!newDropboxFile.Name.Equals(file.Title))
|
||||
{
|
||||
var parentFolderPath = GetParentFolderPath(newDropboxFile);
|
||||
file.Title = GetAvailableTitle(file.Title, parentFolderPath, IsExist);
|
||||
newDropboxFile = ProviderInfo.Storage.MoveFile(filePath, parentFolderPath, file.Title);
|
||||
}
|
||||
}
|
||||
else if (file.FolderID != null)
|
||||
{
|
||||
var folderPath = MakeDropboxPath(file.FolderID);
|
||||
file.Title = GetAvailableTitle(file.Title, folderPath, IsExist);
|
||||
newDropboxFile = ProviderInfo.Storage.CreateFile(fileStream, file.Title, folderPath);
|
||||
}
|
||||
|
||||
ProviderInfo.CacheReset(newDropboxFile);
|
||||
var parentPath = GetParentFolderPath(newDropboxFile);
|
||||
if (parentPath != null) ProviderInfo.CacheReset(parentPath);
|
||||
|
||||
return ToFile(newDropboxFile);
|
||||
}
|
||||
|
||||
public File<string> ReplaceFileVersion(File<string> file, Stream fileStream)
|
||||
{
|
||||
return SaveFile(file, fileStream);
|
||||
}
|
||||
|
||||
public void DeleteFile(string fileId)
|
||||
{
|
||||
var dropboxFile = GetDropboxFile(fileId);
|
||||
if (dropboxFile == null) return;
|
||||
var id = MakeId(dropboxFile);
|
||||
|
||||
using (var tx = FilesDbContext.Database.BeginTransaction())
|
||||
{
|
||||
var hashIDs = Query(FilesDbContext.ThirdpartyIdMapping)
|
||||
.Where(r => r.Id.StartsWith(id))
|
||||
.Select(r => r.HashId)
|
||||
.ToList();
|
||||
|
||||
var link = Query(FilesDbContext.TagLink)
|
||||
.Where(r => hashIDs.Any(h => h == r.EntryId))
|
||||
.ToList();
|
||||
|
||||
FilesDbContext.TagLink.RemoveRange(link);
|
||||
FilesDbContext.SaveChanges();
|
||||
|
||||
var tagsToRemove = Query(FilesDbContext.Tag)
|
||||
.Where(r => !Query(FilesDbContext.TagLink).Where(a => a.TagId == r.Id).Any());
|
||||
|
||||
FilesDbContext.Tag.RemoveRange(tagsToRemove);
|
||||
|
||||
var securityToDelete = Query(FilesDbContext.Security)
|
||||
.Where(r => hashIDs.Any(h => h == r.EntryId));
|
||||
|
||||
FilesDbContext.Security.RemoveRange(securityToDelete);
|
||||
FilesDbContext.SaveChanges();
|
||||
|
||||
var mappingToDelete = Query(FilesDbContext.ThirdpartyIdMapping)
|
||||
.Where(r => hashIDs.Any(h => h == r.HashId));
|
||||
|
||||
FilesDbContext.ThirdpartyIdMapping.RemoveRange(mappingToDelete);
|
||||
FilesDbContext.SaveChanges();
|
||||
|
||||
tx.Commit();
|
||||
}
|
||||
|
||||
if (!(dropboxFile is ErrorFile))
|
||||
{
|
||||
ProviderInfo.Storage.DeleteItem(dropboxFile);
|
||||
}
|
||||
|
||||
ProviderInfo.CacheReset(MakeDropboxPath(dropboxFile), true);
|
||||
var parentFolderPath = GetParentFolderPath(dropboxFile);
|
||||
if (parentFolderPath != null) ProviderInfo.CacheReset(parentFolderPath);
|
||||
}
|
||||
|
||||
public bool IsExist(string title, object folderId)
|
||||
{
|
||||
return GetDropboxItems(folderId, false)
|
||||
.Any(item => item.Name.Equals(title, StringComparison.InvariantCultureIgnoreCase));
|
||||
}
|
||||
|
||||
public TTo MoveFile<TTo>(string fileId, TTo toFolderId)
|
||||
{
|
||||
if (toFolderId is int tId)
|
||||
{
|
||||
return (TTo)Convert.ChangeType(MoveFile(fileId, tId), typeof(TTo));
|
||||
}
|
||||
|
||||
if (toFolderId is string tsId)
|
||||
{
|
||||
return (TTo)Convert.ChangeType(MoveFile(fileId, tsId), typeof(TTo));
|
||||
}
|
||||
|
||||
throw new NotImplementedException();
|
||||
}
|
||||
|
||||
public string MoveFile(string fileId, string toFolderId)
|
||||
{
|
||||
var dropboxFile = GetDropboxFile(fileId);
|
||||
if (dropboxFile is ErrorFile) throw new Exception(((ErrorFile)dropboxFile).Error);
|
||||
|
||||
var toDropboxFolder = GetDropboxFolder(toFolderId);
|
||||
if (toDropboxFolder is ErrorFolder) throw new Exception(((ErrorFolder)toDropboxFolder).Error);
|
||||
|
||||
var fromFolderPath = GetParentFolderPath(dropboxFile);
|
||||
|
||||
dropboxFile = ProviderInfo.Storage.MoveFile(MakeDropboxPath(dropboxFile), MakeDropboxPath(toDropboxFolder), dropboxFile.Name);
|
||||
|
||||
ProviderInfo.CacheReset(MakeDropboxPath(dropboxFile), true);
|
||||
ProviderInfo.CacheReset(fromFolderPath);
|
||||
ProviderInfo.CacheReset(MakeDropboxPath(toDropboxFolder));
|
||||
|
||||
return MakeId(dropboxFile);
|
||||
}
|
||||
|
||||
public int MoveFile(string fileId, int toFolderId)
|
||||
{
|
||||
var moved = CrossDao.PerformCrossDaoFileCopy(
|
||||
fileId, this, DropboxDaoSelector.ConvertId,
|
||||
toFolderId, FileDao, r => r,
|
||||
true);
|
||||
|
||||
return moved.ID;
|
||||
}
|
||||
|
||||
public File<TTo> CopyFile<TTo>(string fileId, TTo toFolderId)
|
||||
{
|
||||
if (toFolderId is int tId)
|
||||
{
|
||||
return CopyFile(fileId, tId) as File<TTo>;
|
||||
}
|
||||
|
||||
if (toFolderId is string tsId)
|
||||
{
|
||||
return CopyFile(fileId, tsId) as File<TTo>;
|
||||
}
|
||||
|
||||
throw new NotImplementedException();
|
||||
}
|
||||
|
||||
public File<int> CopyFile(string fileId, int toFolderId)
|
||||
{
|
||||
var moved = CrossDao.PerformCrossDaoFileCopy(
|
||||
fileId, this, DropboxDaoSelector.ConvertId,
|
||||
toFolderId, FileDao, r => r,
|
||||
false);
|
||||
|
||||
return moved;
|
||||
}
|
||||
|
||||
public File<string> CopyFile(string fileId, string toFolderId)
|
||||
{
|
||||
var dropboxFile = GetDropboxFile(fileId);
|
||||
if (dropboxFile is ErrorFile) throw new Exception(((ErrorFile)dropboxFile).Error);
|
||||
|
||||
var toDropboxFolder = GetDropboxFolder(toFolderId);
|
||||
if (toDropboxFolder is ErrorFolder) throw new Exception(((ErrorFolder)toDropboxFolder).Error);
|
||||
|
||||
var newDropboxFile = ProviderInfo.Storage.CopyFile(MakeDropboxPath(dropboxFile), MakeDropboxPath(toDropboxFolder), dropboxFile.Name);
|
||||
|
||||
ProviderInfo.CacheReset(newDropboxFile);
|
||||
ProviderInfo.CacheReset(MakeDropboxPath(toDropboxFolder));
|
||||
|
||||
return ToFile(newDropboxFile);
|
||||
}
|
||||
|
||||
public string FileRename(File<string> file, string newTitle)
|
||||
{
|
||||
var dropboxFile = GetDropboxFile(file.ID);
|
||||
var parentFolderPath = GetParentFolderPath(dropboxFile);
|
||||
newTitle = GetAvailableTitle(newTitle, parentFolderPath, IsExist);
|
||||
|
||||
dropboxFile = ProviderInfo.Storage.MoveFile(MakeDropboxPath(dropboxFile), parentFolderPath, newTitle);
|
||||
|
||||
ProviderInfo.CacheReset(dropboxFile);
|
||||
var parentPath = GetParentFolderPath(dropboxFile);
|
||||
if (parentPath != null) ProviderInfo.CacheReset(parentPath);
|
||||
|
||||
return MakeId(dropboxFile);
|
||||
}
|
||||
|
||||
public string UpdateComment(string fileId, int fileVersion, string comment)
|
||||
{
|
||||
return string.Empty;
|
||||
}
|
||||
|
||||
public void CompleteVersion(string fileId, int fileVersion)
|
||||
{
|
||||
}
|
||||
|
||||
public void ContinueVersion(string fileId, int fileVersion)
|
||||
{
|
||||
}
|
||||
|
||||
public bool UseTrashForRemove(File<string> file)
|
||||
{
|
||||
return false;
|
||||
}
|
||||
|
||||
#region chunking
|
||||
|
||||
private File<string> RestoreIds(File<string> file)
|
||||
{
|
||||
if (file == null) return null;
|
||||
|
||||
if (file.ID != null)
|
||||
file.ID = MakeId(file.ID.ToString());
|
||||
|
||||
if (file.FolderID != null)
|
||||
file.FolderID = MakeId(file.FolderID.ToString());
|
||||
|
||||
return file;
|
||||
}
|
||||
|
||||
public ChunkedUploadSession<string> CreateUploadSession(File<string> file, long contentLength)
|
||||
{
|
||||
if (SetupInfo.ChunkUploadSize > contentLength)
|
||||
return new ChunkedUploadSession<string>(RestoreIds(file), contentLength) { UseChunks = false };
|
||||
|
||||
var uploadSession = new ChunkedUploadSession<string>(file, contentLength);
|
||||
|
||||
var dropboxSession = ProviderInfo.Storage.CreateResumableSession();
|
||||
if (dropboxSession != null)
|
||||
{
|
||||
uploadSession.Items["DropboxSession"] = dropboxSession;
|
||||
}
|
||||
else
|
||||
{
|
||||
uploadSession.Items["TempPath"] = Path.GetTempFileName();
|
||||
}
|
||||
|
||||
uploadSession.File = RestoreIds(uploadSession.File);
|
||||
return uploadSession;
|
||||
}
|
||||
|
||||
public void UploadChunk(ChunkedUploadSession<string> uploadSession, Stream stream, long chunkLength)
|
||||
{
|
||||
if (!uploadSession.UseChunks)
|
||||
{
|
||||
if (uploadSession.BytesTotal == 0)
|
||||
uploadSession.BytesTotal = chunkLength;
|
||||
|
||||
uploadSession.File = SaveFile(uploadSession.File, stream);
|
||||
uploadSession.BytesUploaded = chunkLength;
|
||||
return;
|
||||
}
|
||||
|
||||
if (uploadSession.Items.ContainsKey("DropboxSession"))
|
||||
{
|
||||
var dropboxSession = uploadSession.GetItemOrDefault<string>("DropboxSession");
|
||||
ProviderInfo.Storage.Transfer(dropboxSession, uploadSession.BytesUploaded, stream);
|
||||
}
|
||||
else
|
||||
{
|
||||
var tempPath = uploadSession.GetItemOrDefault<string>("TempPath");
|
||||
using (var fs = new FileStream(tempPath, FileMode.Append))
|
||||
{
|
||||
stream.CopyTo(fs);
|
||||
}
|
||||
}
|
||||
|
||||
uploadSession.BytesUploaded += chunkLength;
|
||||
|
||||
if (uploadSession.BytesUploaded == uploadSession.BytesTotal)
|
||||
{
|
||||
uploadSession.File = FinalizeUploadSession(uploadSession);
|
||||
}
|
||||
else
|
||||
{
|
||||
uploadSession.File = RestoreIds(uploadSession.File);
|
||||
}
|
||||
}
|
||||
|
||||
public File<string> FinalizeUploadSession(ChunkedUploadSession<string> uploadSession)
|
||||
{
|
||||
if (uploadSession.Items.ContainsKey("DropboxSession"))
|
||||
{
|
||||
var dropboxSession = uploadSession.GetItemOrDefault<string>("DropboxSession");
|
||||
|
||||
Metadata dropboxFile;
|
||||
var file = uploadSession.File;
|
||||
if (file.ID != null)
|
||||
{
|
||||
var dropboxFilePath = MakeDropboxPath(file.ID);
|
||||
dropboxFile = ProviderInfo.Storage.FinishResumableSession(dropboxSession, dropboxFilePath, uploadSession.BytesUploaded);
|
||||
}
|
||||
else
|
||||
{
|
||||
var folderPath = MakeDropboxPath(file.FolderID);
|
||||
var title = GetAvailableTitle(file.Title, folderPath, IsExist);
|
||||
dropboxFile = ProviderInfo.Storage.FinishResumableSession(dropboxSession, folderPath, title, uploadSession.BytesUploaded);
|
||||
}
|
||||
|
||||
ProviderInfo.CacheReset(MakeDropboxPath(dropboxFile));
|
||||
ProviderInfo.CacheReset(GetParentFolderPath(dropboxFile), false);
|
||||
|
||||
return ToFile(dropboxFile.AsFile);
|
||||
}
|
||||
|
||||
using (var fs = new FileStream(uploadSession.GetItemOrDefault<string>("TempPath"),
|
||||
FileMode.Open, FileAccess.Read, FileShare.None, 4096, FileOptions.DeleteOnClose))
|
||||
{
|
||||
return SaveFile(uploadSession.File, fs);
|
||||
}
|
||||
}
|
||||
|
||||
public void AbortUploadSession(ChunkedUploadSession<string> uploadSession)
|
||||
{
|
||||
if (uploadSession.Items.ContainsKey("TempPath"))
|
||||
{
|
||||
File.Delete(uploadSession.GetItemOrDefault<string>("TempPath"));
|
||||
}
|
||||
}
|
||||
|
||||
#endregion
|
||||
|
||||
|
||||
#region Only in TMFileDao
|
||||
|
||||
public void ReassignFiles(string[] fileIds, Guid newOwnerId)
|
||||
{
|
||||
}
|
||||
|
||||
public List<File<string>> GetFiles(string[] parentIds, FilterType filterType, bool subjectGroup, Guid subjectID, string searchText, bool searchInContent)
|
||||
{
|
||||
return new List<File<string>>();
|
||||
}
|
||||
|
||||
public IEnumerable<File<string>> Search(string text, bool bunch)
|
||||
{
|
||||
return null;
|
||||
}
|
||||
|
||||
public bool IsExistOnStorage(File<string> file)
|
||||
{
|
||||
return true;
|
||||
}
|
||||
|
||||
public void SaveEditHistory(File<string> file, string changes, Stream differenceStream)
|
||||
{
|
||||
//Do nothing
|
||||
}
|
||||
|
||||
public List<EditHistory> GetEditHistory(DocumentServiceHelper documentServiceHelper, string fileId, int fileVersion)
|
||||
{
|
||||
return null;
|
||||
}
|
||||
|
||||
public Stream GetDifferenceStream(File<string> file)
|
||||
{
|
||||
return null;
|
||||
}
|
||||
|
||||
public bool ContainChanges(string fileId, int fileVersion)
|
||||
{
|
||||
return false;
|
||||
}
|
||||
|
||||
public string GetUniqFilePath(File<string> file, string fileTitle)
|
||||
{
|
||||
throw new NotImplementedException();
|
||||
}
|
||||
|
||||
#endregion
|
||||
}
|
||||
|
||||
public static class DropboxFileDaoExtention
|
||||
{
|
||||
public static DIHelper AddDropboxFileDaoService(this DIHelper services)
|
||||
{
|
||||
services.TryAddScoped<DropboxFileDao>();
|
||||
|
||||
return services;
|
||||
}
|
||||
}
|
||||
}
|
522
products/ASC.Files/Server/Core/Thirdparty/Dropbox/DropboxFolderDao.cs
vendored
Normal file
522
products/ASC.Files/Server/Core/Thirdparty/Dropbox/DropboxFolderDao.cs
vendored
Normal file
@ -0,0 +1,522 @@
|
||||
/*
|
||||
*
|
||||
* (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;
|
||||
using System.Linq;
|
||||
using System.Threading;
|
||||
|
||||
using ASC.Common;
|
||||
using ASC.Common.Logging;
|
||||
using ASC.Core;
|
||||
using ASC.Core.Common.EF;
|
||||
using ASC.Core.Tenants;
|
||||
using ASC.Files.Core;
|
||||
using ASC.Files.Core.EF;
|
||||
using ASC.Files.Core.Thirdparty;
|
||||
using ASC.Web.Core.Files;
|
||||
using ASC.Web.Studio.Core;
|
||||
|
||||
using Microsoft.Extensions.Options;
|
||||
|
||||
namespace ASC.Files.Thirdparty.Dropbox
|
||||
{
|
||||
internal class DropboxFolderDao : DropboxDaoBase, IFolderDao<string>
|
||||
{
|
||||
public CrossDao CrossDao { get; }
|
||||
public DropboxDaoSelector DropboxDaoSelector { get; }
|
||||
public IFileDao<int> FileDao { get; }
|
||||
public IFolderDao<int> FolderDao { get; }
|
||||
|
||||
public DropboxFolderDao(
|
||||
IServiceProvider serviceProvider,
|
||||
UserManager userManager,
|
||||
TenantManager tenantManager,
|
||||
TenantUtil tenantUtil,
|
||||
DbContextManager<FilesDbContext> dbContextManager,
|
||||
SetupInfo setupInfo,
|
||||
IOptionsMonitor<ILog> monitor,
|
||||
FileUtility fileUtility,
|
||||
CrossDao crossDao,
|
||||
DropboxDaoSelector dropboxDaoSelector,
|
||||
IFileDao<int> fileDao,
|
||||
IFolderDao<int> folderDao)
|
||||
: base(serviceProvider, userManager, tenantManager, tenantUtil, dbContextManager, setupInfo, monitor, fileUtility)
|
||||
{
|
||||
CrossDao = crossDao;
|
||||
DropboxDaoSelector = dropboxDaoSelector;
|
||||
FileDao = fileDao;
|
||||
FolderDao = folderDao;
|
||||
}
|
||||
|
||||
public Folder<string> GetFolder(string folderId)
|
||||
{
|
||||
return ToFolder(GetDropboxFolder(folderId));
|
||||
}
|
||||
|
||||
public Folder<string> GetFolder(string title, string parentId)
|
||||
{
|
||||
var metadata = GetDropboxItems(parentId, true)
|
||||
.FirstOrDefault(item => item.Name.Equals(title, StringComparison.InvariantCultureIgnoreCase));
|
||||
|
||||
return metadata == null
|
||||
? null
|
||||
: ToFolder(metadata.AsFolder);
|
||||
}
|
||||
|
||||
public Folder<string> GetRootFolderByFile(string fileId)
|
||||
{
|
||||
return GetRootFolder(fileId);
|
||||
}
|
||||
|
||||
public List<Folder<string>> GetFolders(string parentId)
|
||||
{
|
||||
return GetDropboxItems(parentId, true).Select(item => ToFolder(item.AsFolder)).ToList();
|
||||
}
|
||||
|
||||
public List<Folder<string>> GetFolders(string parentId, OrderBy orderBy, FilterType filterType, bool subjectGroup, Guid subjectID, string searchText, bool withSubfolders = false)
|
||||
{
|
||||
if (filterType == FilterType.FilesOnly || filterType == FilterType.ByExtension
|
||||
|| filterType == FilterType.DocumentsOnly || filterType == FilterType.ImagesOnly
|
||||
|| filterType == FilterType.PresentationsOnly || filterType == FilterType.SpreadsheetsOnly
|
||||
|| filterType == FilterType.ArchiveOnly || filterType == FilterType.MediaOnly)
|
||||
return new List<Folder<string>>();
|
||||
|
||||
var folders = GetFolders(parentId).AsEnumerable(); //TODO:!!!
|
||||
|
||||
if (subjectID != Guid.Empty)
|
||||
{
|
||||
folders = folders.Where(x => subjectGroup
|
||||
? UserManager.IsUserInGroup(x.CreateBy, subjectID)
|
||||
: x.CreateBy == subjectID);
|
||||
}
|
||||
|
||||
if (!string.IsNullOrEmpty(searchText))
|
||||
folders = folders.Where(x => x.Title.IndexOf(searchText, StringComparison.OrdinalIgnoreCase) != -1);
|
||||
|
||||
if (orderBy == null) orderBy = new OrderBy(SortedByType.DateAndTime, false);
|
||||
|
||||
switch (orderBy.SortedBy)
|
||||
{
|
||||
case SortedByType.Author:
|
||||
folders = orderBy.IsAsc ? folders.OrderBy(x => x.CreateBy) : folders.OrderByDescending(x => x.CreateBy);
|
||||
break;
|
||||
case SortedByType.AZ:
|
||||
folders = orderBy.IsAsc ? folders.OrderBy(x => x.Title) : folders.OrderByDescending(x => x.Title);
|
||||
break;
|
||||
case SortedByType.DateAndTime:
|
||||
folders = orderBy.IsAsc ? folders.OrderBy(x => x.ModifiedOn) : folders.OrderByDescending(x => x.ModifiedOn);
|
||||
break;
|
||||
case SortedByType.DateAndTimeCreation:
|
||||
folders = orderBy.IsAsc ? folders.OrderBy(x => x.CreateOn) : folders.OrderByDescending(x => x.CreateOn);
|
||||
break;
|
||||
default:
|
||||
folders = orderBy.IsAsc ? folders.OrderBy(x => x.Title) : folders.OrderByDescending(x => x.Title);
|
||||
break;
|
||||
}
|
||||
|
||||
return folders.ToList();
|
||||
}
|
||||
|
||||
public List<Folder<string>> GetFolders(string[] folderIds, FilterType filterType = FilterType.None, bool subjectGroup = false, Guid? subjectID = null, string searchText = "", bool searchSubfolders = false, bool checkShare = true)
|
||||
{
|
||||
if (filterType == FilterType.FilesOnly || filterType == FilterType.ByExtension
|
||||
|| filterType == FilterType.DocumentsOnly || filterType == FilterType.ImagesOnly
|
||||
|| filterType == FilterType.PresentationsOnly || filterType == FilterType.SpreadsheetsOnly
|
||||
|| filterType == FilterType.ArchiveOnly || filterType == FilterType.MediaOnly)
|
||||
return new List<Folder<string>>();
|
||||
|
||||
var folders = folderIds.Select(GetFolder);
|
||||
|
||||
if (subjectID.HasValue && subjectID != Guid.Empty)
|
||||
{
|
||||
folders = folders.Where(x => subjectGroup
|
||||
? UserManager.IsUserInGroup(x.CreateBy, subjectID.Value)
|
||||
: x.CreateBy == subjectID);
|
||||
}
|
||||
|
||||
if (!string.IsNullOrEmpty(searchText))
|
||||
folders = folders.Where(x => x.Title.IndexOf(searchText, StringComparison.OrdinalIgnoreCase) != -1);
|
||||
|
||||
return folders.ToList();
|
||||
}
|
||||
|
||||
public List<Folder<string>> GetParentFolders(string folderId)
|
||||
{
|
||||
var path = new List<Folder<string>>();
|
||||
|
||||
while (folderId != null)
|
||||
{
|
||||
var dropboxFolder = GetDropboxFolder(folderId);
|
||||
|
||||
if (dropboxFolder is ErrorFolder)
|
||||
{
|
||||
folderId = null;
|
||||
}
|
||||
else
|
||||
{
|
||||
path.Add(ToFolder(dropboxFolder));
|
||||
folderId = GetParentFolderPath(dropboxFolder);
|
||||
}
|
||||
}
|
||||
|
||||
path.Reverse();
|
||||
return path;
|
||||
}
|
||||
|
||||
public string SaveFolder(Folder<string> folder)
|
||||
{
|
||||
if (folder == null) throw new ArgumentNullException("folder");
|
||||
if (folder.ID != null)
|
||||
{
|
||||
return RenameFolder(folder, folder.Title);
|
||||
}
|
||||
|
||||
if (folder.ParentFolderID != null)
|
||||
{
|
||||
var dropboxFolderPath = MakeDropboxPath(folder.ParentFolderID);
|
||||
|
||||
folder.Title = GetAvailableTitle(folder.Title, dropboxFolderPath, IsExist);
|
||||
|
||||
var dropboxFolder = ProviderInfo.Storage.CreateFolder(folder.Title, dropboxFolderPath);
|
||||
|
||||
ProviderInfo.CacheReset(dropboxFolder);
|
||||
var parentFolderPath = GetParentFolderPath(dropboxFolder);
|
||||
if (parentFolderPath != null) ProviderInfo.CacheReset(parentFolderPath);
|
||||
|
||||
return MakeId(dropboxFolder);
|
||||
}
|
||||
return null;
|
||||
}
|
||||
|
||||
public bool IsExist(string title, string folderId)
|
||||
{
|
||||
return GetDropboxItems(folderId, true)
|
||||
.Any(item => item.Name.Equals(title, StringComparison.InvariantCultureIgnoreCase));
|
||||
}
|
||||
|
||||
public void DeleteFolder(string folderId)
|
||||
{
|
||||
var dropboxFolder = GetDropboxFolder(folderId);
|
||||
var id = MakeId(dropboxFolder);
|
||||
|
||||
using (var tx = FilesDbContext.Database.BeginTransaction())
|
||||
{
|
||||
var hashIDs = Query(FilesDbContext.ThirdpartyIdMapping)
|
||||
.Where(r => r.Id.StartsWith(id))
|
||||
.Select(r => r.HashId)
|
||||
.ToList();
|
||||
|
||||
var link = Query(FilesDbContext.TagLink)
|
||||
.Where(r => hashIDs.Any(h => h == r.EntryId))
|
||||
.ToList();
|
||||
|
||||
FilesDbContext.TagLink.RemoveRange(link);
|
||||
FilesDbContext.SaveChanges();
|
||||
|
||||
var tagsToRemove = Query(FilesDbContext.Tag)
|
||||
.Where(r => !Query(FilesDbContext.TagLink).Where(a => a.TagId == r.Id).Any());
|
||||
|
||||
FilesDbContext.Tag.RemoveRange(tagsToRemove);
|
||||
|
||||
var securityToDelete = Query(FilesDbContext.Security)
|
||||
.Where(r => hashIDs.Any(h => h == r.EntryId));
|
||||
|
||||
FilesDbContext.Security.RemoveRange(securityToDelete);
|
||||
FilesDbContext.SaveChanges();
|
||||
|
||||
var mappingToDelete = Query(FilesDbContext.ThirdpartyIdMapping)
|
||||
.Where(r => hashIDs.Any(h => h == r.HashId));
|
||||
|
||||
FilesDbContext.ThirdpartyIdMapping.RemoveRange(mappingToDelete);
|
||||
FilesDbContext.SaveChanges();
|
||||
|
||||
tx.Commit();
|
||||
}
|
||||
|
||||
if (!(dropboxFolder is ErrorFolder))
|
||||
ProviderInfo.Storage.DeleteItem(dropboxFolder);
|
||||
|
||||
ProviderInfo.CacheReset(MakeDropboxPath(dropboxFolder), true);
|
||||
var parentFolderPath = GetParentFolderPath(dropboxFolder);
|
||||
if (parentFolderPath != null) ProviderInfo.CacheReset(parentFolderPath);
|
||||
}
|
||||
|
||||
public TTo MoveFolder<TTo>(string folderId, TTo toFolderId, CancellationToken? cancellationToken)
|
||||
{
|
||||
if (toFolderId is int tId)
|
||||
{
|
||||
return (TTo)Convert.ChangeType(MoveFolder(folderId, tId, cancellationToken), typeof(TTo));
|
||||
}
|
||||
|
||||
if (toFolderId is string tsId)
|
||||
{
|
||||
return (TTo)Convert.ChangeType(MoveFolder(folderId, tsId, cancellationToken), typeof(TTo));
|
||||
}
|
||||
|
||||
throw new NotImplementedException();
|
||||
}
|
||||
|
||||
public int MoveFolder(string folderId, int toFolderId, CancellationToken? cancellationToken)
|
||||
{
|
||||
var moved = CrossDao.PerformCrossDaoFolderCopy(
|
||||
folderId, this, DropboxDaoSelector.GetFileDao(folderId), DropboxDaoSelector.ConvertId,
|
||||
toFolderId, FolderDao, FileDao, r => r,
|
||||
true, cancellationToken);
|
||||
|
||||
return moved.ID;
|
||||
}
|
||||
|
||||
public string MoveFolder(string folderId, string toFolderId, CancellationToken? cancellationToken)
|
||||
{
|
||||
var dropboxFolder = GetDropboxFolder(folderId);
|
||||
if (dropboxFolder is ErrorFolder) throw new Exception(((ErrorFolder)dropboxFolder).Error);
|
||||
|
||||
var toDropboxFolder = GetDropboxFolder(toFolderId);
|
||||
if (toDropboxFolder is ErrorFolder) throw new Exception(((ErrorFolder)toDropboxFolder).Error);
|
||||
|
||||
var fromFolderPath = GetParentFolderPath(dropboxFolder);
|
||||
|
||||
dropboxFolder = ProviderInfo.Storage.MoveFolder(MakeDropboxPath(dropboxFolder), MakeDropboxPath(toDropboxFolder), dropboxFolder.Name);
|
||||
|
||||
ProviderInfo.CacheReset(MakeDropboxPath(dropboxFolder), false);
|
||||
ProviderInfo.CacheReset(fromFolderPath);
|
||||
ProviderInfo.CacheReset(MakeDropboxPath(toDropboxFolder));
|
||||
|
||||
return MakeId(dropboxFolder);
|
||||
}
|
||||
|
||||
public Folder<TTo> CopyFolder<TTo>(string folderId, TTo toFolderId, CancellationToken? cancellationToken)
|
||||
{
|
||||
if (toFolderId is int tId)
|
||||
{
|
||||
return CopyFolder(folderId, tId, cancellationToken) as Folder<TTo>;
|
||||
}
|
||||
|
||||
if (toFolderId is string tsId)
|
||||
{
|
||||
return CopyFolder(folderId, tsId, cancellationToken) as Folder<TTo>;
|
||||
}
|
||||
|
||||
throw new NotImplementedException();
|
||||
}
|
||||
|
||||
public Folder<int> CopyFolder(string folderId, int toFolderId, CancellationToken? cancellationToken)
|
||||
{
|
||||
var moved = CrossDao.PerformCrossDaoFolderCopy(
|
||||
folderId, this, DropboxDaoSelector.GetFileDao(folderId), DropboxDaoSelector.ConvertId,
|
||||
toFolderId, FolderDao, FileDao, r => r,
|
||||
false, cancellationToken);
|
||||
|
||||
return moved;
|
||||
}
|
||||
|
||||
public Folder<string> CopyFolder(string folderId, string toFolderId, CancellationToken? cancellationToken)
|
||||
{
|
||||
var dropboxFolder = GetDropboxFolder(folderId);
|
||||
if (dropboxFolder is ErrorFolder) throw new Exception(((ErrorFolder)dropboxFolder).Error);
|
||||
|
||||
var toDropboxFolder = GetDropboxFolder(toFolderId);
|
||||
if (toDropboxFolder is ErrorFolder) throw new Exception(((ErrorFolder)toDropboxFolder).Error);
|
||||
|
||||
var newDropboxFolder = ProviderInfo.Storage.CopyFolder(MakeDropboxPath(dropboxFolder), MakeDropboxPath(toDropboxFolder), dropboxFolder.Name);
|
||||
|
||||
ProviderInfo.CacheReset(newDropboxFolder);
|
||||
ProviderInfo.CacheReset(MakeDropboxPath(newDropboxFolder), false);
|
||||
ProviderInfo.CacheReset(MakeDropboxPath(toDropboxFolder));
|
||||
|
||||
return ToFolder(newDropboxFolder);
|
||||
}
|
||||
|
||||
public IDictionary<string, string> CanMoveOrCopy<TTo>(string[] folderIds, TTo to)
|
||||
{
|
||||
if (to is int tId)
|
||||
{
|
||||
return CanMoveOrCopy(folderIds, tId);
|
||||
}
|
||||
|
||||
if (to is string tsId)
|
||||
{
|
||||
return CanMoveOrCopy(folderIds, tsId);
|
||||
}
|
||||
|
||||
throw new NotImplementedException();
|
||||
}
|
||||
|
||||
public IDictionary<string, string> CanMoveOrCopy(string[] folderIds, string to)
|
||||
{
|
||||
return new Dictionary<string, string>();
|
||||
}
|
||||
|
||||
public IDictionary<string, string> CanMoveOrCopy(string[] folderIds, int to)
|
||||
{
|
||||
return new Dictionary<string, string>();
|
||||
}
|
||||
|
||||
public string RenameFolder(Folder<string> folder, string newTitle)
|
||||
{
|
||||
var dropboxFolder = GetDropboxFolder(folder.ID);
|
||||
var parentFolderPath = GetParentFolderPath(dropboxFolder);
|
||||
|
||||
if (IsRoot(dropboxFolder))
|
||||
{
|
||||
//It's root folder
|
||||
DaoSelector.RenameProvider(ProviderInfo, newTitle);
|
||||
//rename provider customer title
|
||||
}
|
||||
else
|
||||
{
|
||||
newTitle = GetAvailableTitle(newTitle, parentFolderPath, IsExist);
|
||||
|
||||
//rename folder
|
||||
dropboxFolder = ProviderInfo.Storage.MoveFolder(MakeDropboxPath(dropboxFolder), parentFolderPath, newTitle);
|
||||
}
|
||||
|
||||
ProviderInfo.CacheReset(dropboxFolder);
|
||||
if (parentFolderPath != null) ProviderInfo.CacheReset(parentFolderPath);
|
||||
|
||||
return MakeId(dropboxFolder);
|
||||
}
|
||||
|
||||
public int GetItemsCount(string folderId)
|
||||
{
|
||||
throw new NotImplementedException();
|
||||
}
|
||||
|
||||
public bool IsEmpty(string folderId)
|
||||
{
|
||||
var dropboxFolderPath = MakeDropboxPath(folderId);
|
||||
//note: without cache
|
||||
return ProviderInfo.Storage.GetItems(dropboxFolderPath).Count == 0;
|
||||
}
|
||||
|
||||
public bool UseTrashForRemove(Folder<string> folder)
|
||||
{
|
||||
return false;
|
||||
}
|
||||
|
||||
public bool UseRecursiveOperation<TTo>(string folderId, TTo toRootFolderId)
|
||||
{
|
||||
return false;
|
||||
}
|
||||
|
||||
public bool UseRecursiveOperation(string folderId, int toRootFolderId)
|
||||
{
|
||||
return false;
|
||||
}
|
||||
|
||||
public bool UseRecursiveOperation(string folderId, string toRootFolderId)
|
||||
{
|
||||
return false;
|
||||
}
|
||||
|
||||
public bool CanCalculateSubitems(string entryId)
|
||||
{
|
||||
return false;
|
||||
}
|
||||
|
||||
public long GetMaxUploadSize(string folderId, bool chunkedUpload)
|
||||
{
|
||||
var storageMaxUploadSize = ProviderInfo.Storage.MaxChunkedUploadFileSize;
|
||||
|
||||
return chunkedUpload ? storageMaxUploadSize : Math.Min(storageMaxUploadSize, SetupInfo.AvailableFileSize);
|
||||
}
|
||||
|
||||
#region Only for TMFolderDao
|
||||
|
||||
public void ReassignFolders(string[] folderIds, Guid newOwnerId)
|
||||
{
|
||||
}
|
||||
|
||||
public IEnumerable<Folder<string>> Search(string text, bool bunch)
|
||||
{
|
||||
return null;
|
||||
}
|
||||
|
||||
public string GetFolderID(string module, string bunch, string data, bool createIfNotExists)
|
||||
{
|
||||
return null;
|
||||
}
|
||||
|
||||
public IEnumerable<string> GetFolderIDs(string module, string bunch, IEnumerable<string> data, bool createIfNotExists)
|
||||
{
|
||||
return new List<string>();
|
||||
}
|
||||
|
||||
public string GetFolderIDCommon(bool createIfNotExists)
|
||||
{
|
||||
return null;
|
||||
}
|
||||
|
||||
public string GetFolderIDUser(bool createIfNotExists, Guid? userId)
|
||||
{
|
||||
return null;
|
||||
}
|
||||
|
||||
public string GetFolderIDShare(bool createIfNotExists)
|
||||
{
|
||||
return null;
|
||||
}
|
||||
|
||||
public string GetFolderIDTrash(bool createIfNotExists, Guid? userId)
|
||||
{
|
||||
return null;
|
||||
}
|
||||
|
||||
|
||||
public string GetFolderIDPhotos(bool createIfNotExists)
|
||||
{
|
||||
return null;
|
||||
}
|
||||
|
||||
public string GetFolderIDProjects(bool createIfNotExists)
|
||||
{
|
||||
return null;
|
||||
}
|
||||
|
||||
public string GetBunchObjectID(string folderID)
|
||||
{
|
||||
return null;
|
||||
}
|
||||
|
||||
public Dictionary<string, string> GetBunchObjectIDs(List<string> folderIDs)
|
||||
{
|
||||
return null;
|
||||
}
|
||||
|
||||
#endregion
|
||||
}
|
||||
|
||||
public static class DropboxFolderDaoExtention
|
||||
{
|
||||
public static DIHelper AddDropboxFolderDaoService(this DIHelper services)
|
||||
{
|
||||
services.TryAddScoped<DropboxFolderDao>();
|
||||
|
||||
return services;
|
||||
}
|
||||
}
|
||||
}
|
293
products/ASC.Files/Server/Core/Thirdparty/Dropbox/DropboxProviderInfo.cs
vendored
Normal file
293
products/ASC.Files/Server/Core/Thirdparty/Dropbox/DropboxProviderInfo.cs
vendored
Normal file
@ -0,0 +1,293 @@
|
||||
/*
|
||||
*
|
||||
* (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;
|
||||
using System.Diagnostics;
|
||||
using System.Text.RegularExpressions;
|
||||
|
||||
using ASC.Common;
|
||||
using ASC.Common.Caching;
|
||||
using ASC.FederatedLogin;
|
||||
using ASC.Files.Core;
|
||||
|
||||
using Dropbox.Api.Files;
|
||||
|
||||
namespace ASC.Files.Thirdparty.Dropbox
|
||||
{
|
||||
[DebuggerDisplay("{CustomerTitle}")]
|
||||
internal class DropboxProviderInfo : IProviderInfo
|
||||
{
|
||||
public OAuth20Token Token { get; set; }
|
||||
|
||||
internal DropboxStorage Storage
|
||||
{
|
||||
get
|
||||
{
|
||||
if (Wrapper.Storage == null || !Wrapper.Storage.IsOpened)
|
||||
{
|
||||
return Wrapper.CreateStorage(Token);
|
||||
}
|
||||
return Wrapper.Storage;
|
||||
}
|
||||
}
|
||||
|
||||
internal bool StorageOpened
|
||||
{
|
||||
get => Wrapper.Storage != null && Wrapper.Storage.IsOpened;
|
||||
}
|
||||
|
||||
public DropboxStorageDisposableWrapper Wrapper { get; }
|
||||
public DropboxProviderInfoHelper DropboxProviderInfoHelper { get; }
|
||||
public int ID { get; set; }
|
||||
|
||||
public Guid Owner { get; set; }
|
||||
|
||||
public string CustomerTitle { get; set; }
|
||||
|
||||
public DateTime CreateOn { get; set; }
|
||||
|
||||
public string RootFolderId
|
||||
{
|
||||
get { return "dropbox-" + ID; }
|
||||
}
|
||||
|
||||
public string ProviderKey { get; set; }
|
||||
|
||||
public FolderType RootFolderType { get; set; }
|
||||
|
||||
|
||||
public DropboxProviderInfo(
|
||||
DropboxStorageDisposableWrapper wrapper,
|
||||
DropboxProviderInfoHelper dropboxProviderInfoHelper
|
||||
)
|
||||
{
|
||||
Wrapper = wrapper;
|
||||
DropboxProviderInfoHelper = dropboxProviderInfoHelper;
|
||||
}
|
||||
|
||||
public void Dispose()
|
||||
{
|
||||
if (StorageOpened)
|
||||
Storage.Close();
|
||||
}
|
||||
|
||||
public bool CheckAccess()
|
||||
{
|
||||
try
|
||||
{
|
||||
Storage.GetUsedSpace();
|
||||
}
|
||||
catch (AggregateException)
|
||||
{
|
||||
return false;
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
public void InvalidateStorage()
|
||||
{
|
||||
if (Wrapper != null)
|
||||
{
|
||||
Wrapper.Dispose();
|
||||
}
|
||||
|
||||
CacheReset();
|
||||
}
|
||||
|
||||
public void UpdateTitle(string newtitle)
|
||||
{
|
||||
CustomerTitle = newtitle;
|
||||
}
|
||||
|
||||
internal FolderMetadata GetDropboxFolder(string dropboxFolderPath)
|
||||
{
|
||||
return DropboxProviderInfoHelper.GetDropboxFolder(Storage, ID, dropboxFolderPath);
|
||||
}
|
||||
|
||||
internal FileMetadata GetDropboxFile(string dropboxFilePath)
|
||||
{
|
||||
return DropboxProviderInfoHelper.GetDropboxFile(Storage, ID, dropboxFilePath);
|
||||
}
|
||||
|
||||
internal List<Metadata> GetDropboxItems(string dropboxFolderPath)
|
||||
{
|
||||
return DropboxProviderInfoHelper.GetDropboxItems(Storage, ID, dropboxFolderPath);
|
||||
}
|
||||
|
||||
internal void CacheReset(Metadata dropboxItem)
|
||||
{
|
||||
DropboxProviderInfoHelper.CacheReset(ID, dropboxItem);
|
||||
}
|
||||
|
||||
internal void CacheReset(string dropboxPath = null, bool? isFile = null)
|
||||
{
|
||||
DropboxProviderInfoHelper.CacheReset(ID, dropboxPath, isFile);
|
||||
}
|
||||
}
|
||||
|
||||
internal class DropboxStorageDisposableWrapper : IDisposable
|
||||
{
|
||||
public DropboxStorage Storage { get; private set; }
|
||||
|
||||
|
||||
public DropboxStorageDisposableWrapper()
|
||||
{
|
||||
}
|
||||
|
||||
public DropboxStorage CreateStorage(OAuth20Token token)
|
||||
{
|
||||
if (Storage != null) return Storage;
|
||||
|
||||
var dropboxStorage = new DropboxStorage();
|
||||
dropboxStorage.Open(token);
|
||||
return Storage = dropboxStorage;
|
||||
}
|
||||
|
||||
public void Dispose()
|
||||
{
|
||||
Storage?.Close();
|
||||
Storage = null;
|
||||
}
|
||||
}
|
||||
|
||||
public class DropboxProviderInfoHelper
|
||||
{
|
||||
private readonly TimeSpan CacheExpiration;
|
||||
private readonly ICache CacheFile;
|
||||
private readonly ICache CacheFolder;
|
||||
private readonly ICache CacheChildItems;
|
||||
private readonly ICacheNotify<DropboxCacheItem> CacheNotify;
|
||||
|
||||
public DropboxProviderInfoHelper(ICacheNotify<DropboxCacheItem> cacheNotify)
|
||||
{
|
||||
CacheExpiration = TimeSpan.FromMinutes(1);
|
||||
CacheFile = AscCache.Memory;
|
||||
CacheFolder = AscCache.Memory;
|
||||
CacheChildItems = AscCache.Memory;
|
||||
CacheNotify = cacheNotify;
|
||||
|
||||
CacheNotify.Subscribe((i) =>
|
||||
{
|
||||
if (i.ResetAll)
|
||||
{
|
||||
CacheFile.Remove(new Regex("^dropboxf-" + i.Key + ".*"));
|
||||
CacheFolder.Remove(new Regex("^dropboxd-" + i.Key + ".*"));
|
||||
CacheChildItems.Remove(new Regex("^dropbox-" + i.Key + ".*"));
|
||||
}
|
||||
|
||||
if (!i.IsFileExists)
|
||||
{
|
||||
CacheChildItems.Remove("dropbox-" + i.Key);
|
||||
|
||||
CacheFolder.Remove("dropboxd-" + i.Key);
|
||||
}
|
||||
else
|
||||
{
|
||||
if (i.IsFileExists)
|
||||
{
|
||||
CacheFile.Remove("dropboxf-" + i.Key);
|
||||
}
|
||||
else
|
||||
{
|
||||
CacheFolder.Remove("dropboxd-" + i.Key);
|
||||
}
|
||||
}
|
||||
}, CacheNotifyAction.Remove);
|
||||
}
|
||||
|
||||
internal FolderMetadata GetDropboxFolder(DropboxStorage storage, int id, string dropboxFolderPath)
|
||||
{
|
||||
var folder = CacheFolder.Get<FolderMetadata>("dropboxd-" + id + "-" + dropboxFolderPath);
|
||||
if (folder == null)
|
||||
{
|
||||
folder = storage.GetFolder(dropboxFolderPath);
|
||||
if (folder != null)
|
||||
CacheFolder.Insert("dropboxd-" + id + "-" + dropboxFolderPath, folder, DateTime.UtcNow.Add(CacheExpiration));
|
||||
}
|
||||
return folder;
|
||||
}
|
||||
|
||||
internal FileMetadata GetDropboxFile(DropboxStorage storage, int id, string dropboxFilePath)
|
||||
{
|
||||
var file = CacheFile.Get<FileMetadata>("dropboxf-" + id + "-" + dropboxFilePath);
|
||||
if (file == null)
|
||||
{
|
||||
file = storage.GetFile(dropboxFilePath);
|
||||
if (file != null)
|
||||
CacheFile.Insert("dropboxf-" + id + "-" + dropboxFilePath, file, DateTime.UtcNow.Add(CacheExpiration));
|
||||
}
|
||||
return file;
|
||||
}
|
||||
|
||||
internal List<Metadata> GetDropboxItems(DropboxStorage storage, int id, string dropboxFolderPath)
|
||||
{
|
||||
var items = CacheChildItems.Get<List<Metadata>>("dropbox-" + id + "-" + dropboxFolderPath);
|
||||
|
||||
if (items == null)
|
||||
{
|
||||
items = storage.GetItems(dropboxFolderPath);
|
||||
CacheChildItems.Insert("dropbox-" + id + "-" + dropboxFolderPath, items, DateTime.UtcNow.Add(CacheExpiration));
|
||||
}
|
||||
return items;
|
||||
}
|
||||
|
||||
internal void CacheReset(int id, Metadata dropboxItem)
|
||||
{
|
||||
if (dropboxItem != null)
|
||||
{
|
||||
CacheNotify.Publish(new DropboxCacheItem { IsFile = dropboxItem.AsFolder != null, Key = id + "-" + dropboxItem.PathDisplay }, CacheNotifyAction.Remove);
|
||||
}
|
||||
}
|
||||
|
||||
internal void CacheReset(int id, string dropboxPath = null, bool? isFile = null)
|
||||
{
|
||||
var key = id + "-";
|
||||
if (dropboxPath == null)
|
||||
{
|
||||
CacheNotify.Publish(new DropboxCacheItem { ResetAll = true, Key = key }, CacheNotifyAction.Remove);
|
||||
}
|
||||
else
|
||||
{
|
||||
key += dropboxPath;
|
||||
|
||||
CacheNotify.Publish(new DropboxCacheItem { IsFile = isFile ?? false, IsFileExists = isFile.HasValue, Key = key }, CacheNotifyAction.Remove);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
public static class DropboxProviderInfoExtension
|
||||
{
|
||||
public static DIHelper AddDropboxProviderInfoService(this DIHelper services)
|
||||
{
|
||||
services.TryAddScoped<DropboxProviderInfo>();
|
||||
services.TryAddScoped<DropboxStorageDisposableWrapper>();
|
||||
services.TryAddSingleton<DropboxProviderInfoHelper>();
|
||||
|
||||
return services;
|
||||
}
|
||||
}
|
||||
}
|
103
products/ASC.Files/Server/Core/Thirdparty/Dropbox/DropboxSecurityDao.cs
vendored
Normal file
103
products/ASC.Files/Server/Core/Thirdparty/Dropbox/DropboxSecurityDao.cs
vendored
Normal file
@ -0,0 +1,103 @@
|
||||
/*
|
||||
*
|
||||
* (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;
|
||||
|
||||
using ASC.Common;
|
||||
using ASC.Common.Logging;
|
||||
using ASC.Core;
|
||||
using ASC.Core.Common.EF;
|
||||
using ASC.Core.Tenants;
|
||||
using ASC.Files.Core;
|
||||
using ASC.Files.Core.EF;
|
||||
using ASC.Files.Core.Security;
|
||||
using ASC.Web.Core.Files;
|
||||
using ASC.Web.Studio.Core;
|
||||
|
||||
using Microsoft.Extensions.Options;
|
||||
|
||||
namespace ASC.Files.Thirdparty.Dropbox
|
||||
{
|
||||
internal class DropboxSecurityDao : DropboxDaoBase, ISecurityDao<string>
|
||||
{
|
||||
public DropboxSecurityDao(IServiceProvider serviceProvider, UserManager userManager, TenantManager tenantManager, TenantUtil tenantUtil, DbContextManager<FilesDbContext> dbContextManager, SetupInfo setupInfo, IOptionsMonitor<ILog> monitor, FileUtility fileUtility) : base(serviceProvider, userManager, tenantManager, tenantUtil, dbContextManager, setupInfo, monitor, fileUtility)
|
||||
{
|
||||
}
|
||||
|
||||
public void SetShare(FileShareRecord r)
|
||||
{
|
||||
}
|
||||
|
||||
public IEnumerable<FileShareRecord> GetShares(IEnumerable<Guid> subjects)
|
||||
{
|
||||
return null;
|
||||
}
|
||||
|
||||
public IEnumerable<FileShareRecord> GetShares(IEnumerable<FileEntry<string>> entry)
|
||||
{
|
||||
return null;
|
||||
}
|
||||
|
||||
public IEnumerable<FileShareRecord> GetShares(FileEntry<string> entry)
|
||||
{
|
||||
return null;
|
||||
}
|
||||
|
||||
public void RemoveSubject(Guid subject)
|
||||
{
|
||||
}
|
||||
|
||||
public IEnumerable<FileShareRecord> GetPureShareRecords(IEnumerable<FileEntry<string>> entries)
|
||||
{
|
||||
return null;
|
||||
}
|
||||
|
||||
public IEnumerable<FileShareRecord> GetPureShareRecords(FileEntry<string> entry)
|
||||
{
|
||||
return null;
|
||||
}
|
||||
|
||||
public void DeleteShareRecords(IEnumerable<FileShareRecord> records)
|
||||
{
|
||||
}
|
||||
|
||||
public bool IsShared(object entryId, FileEntryType type)
|
||||
{
|
||||
throw new NotImplementedException();
|
||||
}
|
||||
}
|
||||
|
||||
public static class DropboxSecurityDaoExtention
|
||||
{
|
||||
public static DIHelper AddDropboxSecurityDaoService(this DIHelper services)
|
||||
{
|
||||
services.TryAddScoped<DropboxSecurityDao>();
|
||||
|
||||
return services;
|
||||
}
|
||||
}
|
||||
}
|
219
products/ASC.Files/Server/Core/Thirdparty/Dropbox/DropboxStorage.cs
vendored
Normal file
219
products/ASC.Files/Server/Core/Thirdparty/Dropbox/DropboxStorage.cs
vendored
Normal file
@ -0,0 +1,219 @@
|
||||
/*
|
||||
*
|
||||
* (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;
|
||||
using System.IO;
|
||||
using ASC.FederatedLogin;
|
||||
using Dropbox.Api;
|
||||
using Dropbox.Api.Files;
|
||||
|
||||
namespace ASC.Files.Thirdparty.Dropbox
|
||||
{
|
||||
internal class DropboxStorage
|
||||
{
|
||||
private OAuth20Token _token;
|
||||
|
||||
private DropboxClient _dropboxClient;
|
||||
|
||||
public bool IsOpened { get; private set; }
|
||||
|
||||
public long MaxChunkedUploadFileSize = 20L*1024L*1024L*1024L;
|
||||
|
||||
public void Open(OAuth20Token token)
|
||||
{
|
||||
if (IsOpened)
|
||||
return;
|
||||
|
||||
_token = token;
|
||||
|
||||
_dropboxClient = new DropboxClient(_token.AccessToken);
|
||||
|
||||
IsOpened = true;
|
||||
}
|
||||
|
||||
public void Close()
|
||||
{
|
||||
_dropboxClient.Dispose();
|
||||
|
||||
IsOpened = false;
|
||||
}
|
||||
|
||||
|
||||
|
||||
public string MakeDropboxPath(string parentPath, string name)
|
||||
{
|
||||
return (parentPath ?? "") + "/" + (name ?? "");
|
||||
}
|
||||
|
||||
public long GetUsedSpace()
|
||||
{
|
||||
return (long)_dropboxClient.Users.GetSpaceUsageAsync().Result.Used;
|
||||
}
|
||||
|
||||
public FolderMetadata GetFolder(string folderPath)
|
||||
{
|
||||
if (string.IsNullOrEmpty(folderPath) || folderPath == "/")
|
||||
{
|
||||
return new FolderMetadata(string.Empty, "/");
|
||||
}
|
||||
try
|
||||
{
|
||||
return _dropboxClient.Files.GetMetadataAsync(folderPath).Result.AsFolder;
|
||||
}
|
||||
catch (AggregateException ex)
|
||||
{
|
||||
if (ex.InnerException is ApiException<GetMetadataError>
|
||||
&& ex.InnerException.Message.StartsWith("path/not_found/"))
|
||||
{
|
||||
return null;
|
||||
}
|
||||
throw;
|
||||
}
|
||||
}
|
||||
|
||||
public FileMetadata GetFile(string filePath)
|
||||
{
|
||||
if (string.IsNullOrEmpty(filePath) || filePath == "/")
|
||||
{
|
||||
return null;
|
||||
}
|
||||
try
|
||||
{
|
||||
return _dropboxClient.Files.GetMetadataAsync(filePath).Result.AsFile;
|
||||
}
|
||||
catch (AggregateException ex)
|
||||
{
|
||||
if (ex.InnerException is ApiException<GetMetadataError>
|
||||
&& ex.InnerException.Message.StartsWith("path/not_found/"))
|
||||
{
|
||||
return null;
|
||||
}
|
||||
throw;
|
||||
}
|
||||
}
|
||||
|
||||
public List<Metadata> GetItems(string folderPath)
|
||||
{
|
||||
return new List<Metadata>(_dropboxClient.Files.ListFolderAsync(folderPath).Result.Entries);
|
||||
}
|
||||
|
||||
public Stream DownloadStream(string filePath, int offset = 0)
|
||||
{
|
||||
if (string.IsNullOrEmpty(filePath)) throw new ArgumentNullException("file");
|
||||
|
||||
using (var response = _dropboxClient.Files.DownloadAsync(filePath).Result)
|
||||
{
|
||||
var tempBuffer = new FileStream(Path.GetTempFileName(), FileMode.OpenOrCreate, FileAccess.ReadWrite, FileShare.Read, 8096, FileOptions.DeleteOnClose);
|
||||
using (var str = response.GetContentAsStreamAsync().Result)
|
||||
{
|
||||
if (str != null)
|
||||
{
|
||||
str.CopyTo(tempBuffer);
|
||||
tempBuffer.Flush();
|
||||
tempBuffer.Seek(offset, SeekOrigin.Begin);
|
||||
}
|
||||
}
|
||||
return tempBuffer;
|
||||
}
|
||||
}
|
||||
|
||||
public FolderMetadata CreateFolder(string title, string parentPath)
|
||||
{
|
||||
var path = MakeDropboxPath(parentPath, title);
|
||||
var result = _dropboxClient.Files.CreateFolderV2Async(path, true).Result;
|
||||
return result.Metadata;
|
||||
}
|
||||
|
||||
public FileMetadata CreateFile(Stream fileStream, string title, string parentPath)
|
||||
{
|
||||
var path = MakeDropboxPath(parentPath, title);
|
||||
return _dropboxClient.Files.UploadAsync(path, WriteMode.Add.Instance, true, body: fileStream).Result;
|
||||
}
|
||||
|
||||
public void DeleteItem(Metadata dropboxItem)
|
||||
{
|
||||
_dropboxClient.Files.DeleteV2Async(dropboxItem.PathDisplay).Wait();
|
||||
}
|
||||
|
||||
public FolderMetadata MoveFolder(string dropboxFolderPath, string dropboxFolderPathTo, string folderName)
|
||||
{
|
||||
var pathTo = MakeDropboxPath(dropboxFolderPathTo, folderName);
|
||||
var result = _dropboxClient.Files.MoveV2Async(dropboxFolderPath, pathTo, autorename: true).Result;
|
||||
return (FolderMetadata)result.Metadata;
|
||||
}
|
||||
|
||||
public FileMetadata MoveFile(string dropboxFilePath, string dropboxFolderPathTo, string fileName)
|
||||
{
|
||||
var pathTo = MakeDropboxPath(dropboxFolderPathTo, fileName);
|
||||
var result = _dropboxClient.Files.MoveV2Async(dropboxFilePath, pathTo, autorename: true).Result;
|
||||
return (FileMetadata)result.Metadata;
|
||||
}
|
||||
|
||||
public FolderMetadata CopyFolder(string dropboxFolderPath, string dropboxFolderPathTo, string folderName)
|
||||
{
|
||||
var pathTo = MakeDropboxPath(dropboxFolderPathTo, folderName);
|
||||
var result = _dropboxClient.Files.CopyV2Async(dropboxFolderPath, pathTo, autorename: true).Result;
|
||||
return (FolderMetadata)result.Metadata;
|
||||
}
|
||||
|
||||
public FileMetadata CopyFile(string dropboxFilePath, string dropboxFolderPathTo, string fileName)
|
||||
{
|
||||
var pathTo = MakeDropboxPath(dropboxFolderPathTo, fileName);
|
||||
var result = _dropboxClient.Files.CopyV2Async(dropboxFilePath, pathTo, autorename: true).Result;
|
||||
return (FileMetadata)result.Metadata;
|
||||
}
|
||||
|
||||
public FileMetadata SaveStream(string filePath, Stream fileStream)
|
||||
{
|
||||
return _dropboxClient.Files.UploadAsync(filePath, WriteMode.Overwrite.Instance, body: fileStream).Result.AsFile;
|
||||
}
|
||||
|
||||
public string CreateResumableSession()
|
||||
{
|
||||
return _dropboxClient.Files.UploadSessionStartAsync(body: new MemoryStream()).Result.SessionId;
|
||||
}
|
||||
|
||||
public void Transfer(string dropboxSession, long offset, Stream stream)
|
||||
{
|
||||
_dropboxClient.Files.UploadSessionAppendV2Async(new UploadSessionCursor(dropboxSession, (ulong)offset), body: stream).Wait();
|
||||
}
|
||||
|
||||
public Metadata FinishResumableSession(string dropboxSession, string dropboxFolderPath, string fileName, long offset)
|
||||
{
|
||||
var dropboxFilePath = MakeDropboxPath(dropboxFolderPath, fileName);
|
||||
return FinishResumableSession(dropboxSession, dropboxFilePath, offset);
|
||||
}
|
||||
|
||||
public Metadata FinishResumableSession(string dropboxSession, string dropboxFilePath, long offset)
|
||||
{
|
||||
return _dropboxClient.Files.UploadSessionFinishAsync(
|
||||
new UploadSessionCursor(dropboxSession, (ulong)offset),
|
||||
new CommitInfo(dropboxFilePath, WriteMode.Overwrite.Instance),
|
||||
new MemoryStream()).Result;
|
||||
}
|
||||
}
|
||||
}
|
199
products/ASC.Files/Server/Core/Thirdparty/Dropbox/DropboxTagDao.cs
vendored
Normal file
199
products/ASC.Files/Server/Core/Thirdparty/Dropbox/DropboxTagDao.cs
vendored
Normal file
@ -0,0 +1,199 @@
|
||||
/*
|
||||
*
|
||||
* (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;
|
||||
using System.Diagnostics.CodeAnalysis;
|
||||
using System.Linq;
|
||||
|
||||
using ASC.Common;
|
||||
using ASC.Common.Logging;
|
||||
using ASC.Core;
|
||||
using ASC.Core.Common.EF;
|
||||
using ASC.Core.Tenants;
|
||||
using ASC.Files.Core;
|
||||
using ASC.Files.Core.EF;
|
||||
using ASC.Web.Core.Files;
|
||||
using ASC.Web.Studio.Core;
|
||||
|
||||
using Microsoft.Extensions.Options;
|
||||
|
||||
namespace ASC.Files.Thirdparty.Dropbox
|
||||
{
|
||||
internal class DropboxTagDao : DropboxDaoBase, ITagDao<string>
|
||||
{
|
||||
public DropboxTagDao(IServiceProvider serviceProvider, UserManager userManager, TenantManager tenantManager, TenantUtil tenantUtil, DbContextManager<FilesDbContext> dbContextManager, SetupInfo setupInfo, IOptionsMonitor<ILog> monitor, FileUtility fileUtility) : base(serviceProvider, userManager, tenantManager, tenantUtil, dbContextManager, setupInfo, monitor, fileUtility)
|
||||
{
|
||||
}
|
||||
|
||||
#region ITagDao Members
|
||||
|
||||
public IEnumerable<Tag> GetTags(TagType tagType, IEnumerable<FileEntry<string>> fileEntries)
|
||||
{
|
||||
return null;
|
||||
}
|
||||
|
||||
public IEnumerable<Tag> GetTags(Guid owner, TagType tagType)
|
||||
{
|
||||
return null;
|
||||
}
|
||||
|
||||
public IEnumerable<Tag> GetTags(string name, TagType tagType)
|
||||
{
|
||||
return null;
|
||||
}
|
||||
|
||||
public IEnumerable<Tag> GetTags(string[] names, TagType tagType)
|
||||
{
|
||||
return null;
|
||||
}
|
||||
|
||||
public IEnumerable<Tag> GetNewTags(Guid subject, Folder<string> parentFolder, bool deepSearch)
|
||||
{
|
||||
var folderId = DaoSelector.ConvertId(parentFolder.ID);
|
||||
var fakeFolderId = parentFolder.ID.ToString();
|
||||
|
||||
var entryIDs = FilesDbContext.ThirdpartyIdMapping
|
||||
.Where(r => r.Id.StartsWith(fakeFolderId))
|
||||
.Select(r => r.HashId)
|
||||
.ToList();
|
||||
|
||||
if (!entryIDs.Any()) return new List<Tag>();
|
||||
|
||||
var q = FilesDbContext.Tag
|
||||
.Join(FilesDbContext.TagLink.DefaultIfEmpty(),
|
||||
r => new TagLink { TenantId = r.TenantId, Id = r.Id },
|
||||
r => new TagLink { TenantId = r.TenantId, Id = r.TagId },
|
||||
(tag, tagLink) => new { tag, tagLink },
|
||||
new TagLinkComparer())
|
||||
.Where(r => r.tag.TenantId == TenantID)
|
||||
.Where(r => r.tag.Flag == TagType.New)
|
||||
.Where(r => r.tagLink.TenantId == TenantID)
|
||||
.Where(r => entryIDs.Any(a => a == r.tagLink.EntryId));
|
||||
|
||||
if (subject != Guid.Empty)
|
||||
{
|
||||
q = q.Where(r => r.tag.Owner == subject);
|
||||
}
|
||||
|
||||
var tags = q
|
||||
.ToList()
|
||||
.Select(r => new Tag
|
||||
{
|
||||
TagName = r.tag.Name,
|
||||
TagType = r.tag.Flag,
|
||||
Owner = r.tag.Owner,
|
||||
EntryId = MappingID(r.tagLink.EntryId),
|
||||
EntryType = r.tagLink.EntryType,
|
||||
Count = r.tagLink.TagCount,
|
||||
Id = r.tag.Id
|
||||
});
|
||||
|
||||
if (deepSearch) return tags;
|
||||
|
||||
var folderFileIds = new[] { fakeFolderId }
|
||||
.Concat(GetChildren(folderId));
|
||||
|
||||
return tags.Where(tag => folderFileIds.Contains(tag.EntryId.ToString()));
|
||||
}
|
||||
|
||||
public IEnumerable<Tag> GetNewTags(Guid subject, IEnumerable<FileEntry<string>> fileEntries)
|
||||
{
|
||||
return null;
|
||||
}
|
||||
|
||||
public IEnumerable<Tag> GetNewTags(Guid subject, FileEntry<string> fileEntry)
|
||||
{
|
||||
return null;
|
||||
}
|
||||
|
||||
public IEnumerable<Tag> SaveTags(IEnumerable<Tag> tag)
|
||||
{
|
||||
return null;
|
||||
}
|
||||
|
||||
public IEnumerable<Tag> SaveTags(Tag tag)
|
||||
{
|
||||
return null;
|
||||
}
|
||||
|
||||
public void UpdateNewTags(IEnumerable<Tag> tag)
|
||||
{
|
||||
}
|
||||
|
||||
public void UpdateNewTags(Tag tag)
|
||||
{
|
||||
}
|
||||
|
||||
public void RemoveTags(IEnumerable<Tag> tag)
|
||||
{
|
||||
}
|
||||
|
||||
public void RemoveTags(Tag tag)
|
||||
{
|
||||
}
|
||||
|
||||
public IEnumerable<Tag> GetTags(string entryID, FileEntryType entryType, TagType tagType)
|
||||
{
|
||||
return null;
|
||||
}
|
||||
|
||||
public void MarkAsNew(Guid subject, FileEntry<string> fileEntry)
|
||||
{
|
||||
}
|
||||
|
||||
#endregion
|
||||
}
|
||||
|
||||
public class TagLink
|
||||
{
|
||||
public int TenantId { get; set; }
|
||||
public int Id { get; set; }
|
||||
}
|
||||
|
||||
public class TagLinkComparer : IEqualityComparer<TagLink>
|
||||
{
|
||||
public bool Equals([AllowNull] TagLink x, [AllowNull] TagLink y)
|
||||
{
|
||||
return x.Id == y.Id && x.TenantId == y.TenantId;
|
||||
}
|
||||
|
||||
public int GetHashCode([DisallowNull] TagLink obj)
|
||||
{
|
||||
return obj.Id.GetHashCode() + obj.TenantId.GetHashCode();
|
||||
}
|
||||
}
|
||||
|
||||
public static class DropboxTagDaoExtention
|
||||
{
|
||||
public static DIHelper AddDropboxTagDaoService(this DIHelper services)
|
||||
{
|
||||
services.TryAddScoped<DropboxTagDao>();
|
||||
|
||||
return services;
|
||||
}
|
||||
}
|
||||
}
|
263
products/ASC.Files/Server/Core/Thirdparty/GoogleDrive/GoogleDriveDaoBase.cs
vendored
Normal file
263
products/ASC.Files/Server/Core/Thirdparty/GoogleDrive/GoogleDriveDaoBase.cs
vendored
Normal file
@ -0,0 +1,263 @@
|
||||
/*
|
||||
*
|
||||
* (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;
|
||||
using System.Globalization;
|
||||
using System.Linq;
|
||||
|
||||
using ASC.Common.Logging;
|
||||
using ASC.Common.Web;
|
||||
using ASC.Core;
|
||||
using ASC.Core.Common.EF;
|
||||
using ASC.Core.Tenants;
|
||||
using ASC.FederatedLogin.LoginProviders;
|
||||
using ASC.Files.Core;
|
||||
using ASC.Files.Core.EF;
|
||||
using ASC.Web.Core.Files;
|
||||
using ASC.Web.Files.Classes;
|
||||
using ASC.Web.Studio.Core;
|
||||
|
||||
using Microsoft.Extensions.Options;
|
||||
|
||||
using DriveFile = Google.Apis.Drive.v3.Data.File;
|
||||
|
||||
namespace ASC.Files.Thirdparty.GoogleDrive
|
||||
{
|
||||
internal abstract class GoogleDriveDaoBase : ThirdPartyProviderDao<GoogleDriveProviderInfo>
|
||||
{
|
||||
public override string Id { get => "drive"; }
|
||||
|
||||
public GoogleDriveDaoBase(IServiceProvider serviceProvider, UserManager userManager, TenantManager tenantManager, TenantUtil tenantUtil, DbContextManager<FilesDbContext> dbContextManager, SetupInfo setupInfo, IOptionsMonitor<ILog> monitor, FileUtility fileUtility) : base(serviceProvider, userManager, tenantManager, tenantUtil, dbContextManager, setupInfo, monitor, fileUtility)
|
||||
{
|
||||
}
|
||||
|
||||
protected static string MakeDriveId(object entryId)
|
||||
{
|
||||
var id = Convert.ToString(entryId, CultureInfo.InvariantCulture);
|
||||
return string.IsNullOrEmpty(id)
|
||||
? "root"
|
||||
: id.TrimStart('/');
|
||||
}
|
||||
|
||||
protected static string GetParentDriveId(DriveFile driveEntry)
|
||||
{
|
||||
return driveEntry == null || driveEntry.Parents == null || driveEntry.Parents.Count == 0
|
||||
? null
|
||||
: driveEntry.Parents[0];
|
||||
}
|
||||
|
||||
protected string MakeId(DriveFile driveEntry)
|
||||
{
|
||||
var path = string.Empty;
|
||||
if (driveEntry != null)
|
||||
{
|
||||
path = IsRoot(driveEntry) ? "root" : driveEntry.Id;
|
||||
}
|
||||
|
||||
return MakeId(path);
|
||||
}
|
||||
|
||||
protected override string MakeId(string path = null)
|
||||
{
|
||||
return string.Format("{0}{1}", PathPrefix, string.IsNullOrEmpty(path) || path == "root" || path == ProviderInfo.DriveRootId ? "" : ("-|" + path.TrimStart('/')));
|
||||
}
|
||||
|
||||
protected string MakeFolderTitle(DriveFile driveFolder)
|
||||
{
|
||||
if (driveFolder == null || IsRoot(driveFolder))
|
||||
{
|
||||
return ProviderInfo.CustomerTitle;
|
||||
}
|
||||
|
||||
return Global.ReplaceInvalidCharsAndTruncate(driveFolder.Name);
|
||||
}
|
||||
|
||||
protected string MakeFileTitle(DriveFile driveFile)
|
||||
{
|
||||
if (driveFile == null || string.IsNullOrEmpty(driveFile.Name))
|
||||
{
|
||||
return ProviderInfo.ProviderKey;
|
||||
}
|
||||
|
||||
var title = driveFile.Name;
|
||||
|
||||
var gExt = MimeMapping.GetExtention(driveFile.MimeType);
|
||||
if (GoogleLoginProvider.GoogleDriveExt.Contains(gExt))
|
||||
{
|
||||
var downloadableExtension = FileUtility.GetGoogleDownloadableExtension(gExt);
|
||||
if (!downloadableExtension.Equals(FileUtility.GetFileExtension(title)))
|
||||
{
|
||||
title += downloadableExtension;
|
||||
}
|
||||
}
|
||||
|
||||
return Global.ReplaceInvalidCharsAndTruncate(title);
|
||||
}
|
||||
|
||||
protected Folder<string> ToFolder(DriveFile driveEntry)
|
||||
{
|
||||
if (driveEntry == null) return null;
|
||||
if (driveEntry is ErrorDriveEntry)
|
||||
{
|
||||
//Return error entry
|
||||
return ToErrorFolder(driveEntry as ErrorDriveEntry);
|
||||
}
|
||||
|
||||
if (driveEntry.MimeType != GoogleLoginProvider.GoogleDriveMimeTypeFolder)
|
||||
{
|
||||
return null;
|
||||
}
|
||||
|
||||
var isRoot = IsRoot(driveEntry);
|
||||
|
||||
var folder = GetFolder();
|
||||
|
||||
folder.ID = MakeId(driveEntry);
|
||||
folder.ParentFolderID = isRoot ? null : MakeId(GetParentDriveId(driveEntry));
|
||||
folder.CreateOn = isRoot ? ProviderInfo.CreateOn : (driveEntry.CreatedTime ?? default);
|
||||
folder.ModifiedOn = isRoot ? ProviderInfo.CreateOn : (driveEntry.ModifiedTime ?? default);
|
||||
|
||||
folder.Title = MakeFolderTitle(driveEntry);
|
||||
|
||||
if (folder.CreateOn != DateTime.MinValue && folder.CreateOn.Kind == DateTimeKind.Utc)
|
||||
folder.CreateOn = TenantUtil.DateTimeFromUtc(folder.CreateOn);
|
||||
|
||||
if (folder.ModifiedOn != DateTime.MinValue && folder.ModifiedOn.Kind == DateTimeKind.Utc)
|
||||
folder.ModifiedOn = TenantUtil.DateTimeFromUtc(folder.ModifiedOn);
|
||||
|
||||
return folder;
|
||||
}
|
||||
|
||||
protected static bool IsRoot(DriveFile driveFolder)
|
||||
{
|
||||
return IsDriveFolder(driveFolder) && GetParentDriveId(driveFolder) == null;
|
||||
}
|
||||
|
||||
private static bool IsDriveFolder(DriveFile driveFolder)
|
||||
{
|
||||
return driveFolder != null && driveFolder.MimeType == GoogleLoginProvider.GoogleDriveMimeTypeFolder;
|
||||
}
|
||||
|
||||
private File<string> ToErrorFile(ErrorDriveEntry driveEntry)
|
||||
{
|
||||
if (driveEntry == null) return null;
|
||||
|
||||
var file = GetErrorFile(new ErrorEntry(driveEntry.Error, driveEntry.ErrorId));
|
||||
|
||||
file.Title = MakeFileTitle(driveEntry);
|
||||
|
||||
return file;
|
||||
}
|
||||
|
||||
private Folder<string> ToErrorFolder(ErrorDriveEntry driveEntry)
|
||||
{
|
||||
if (driveEntry == null) return null;
|
||||
|
||||
var folder = GetErrorFolder(new ErrorEntry(driveEntry.Error, driveEntry.ErrorId));
|
||||
|
||||
folder.Title = MakeFolderTitle(driveEntry);
|
||||
|
||||
return folder;
|
||||
}
|
||||
|
||||
public File<string> ToFile(DriveFile driveFile)
|
||||
{
|
||||
if (driveFile == null) return null;
|
||||
|
||||
if (driveFile is ErrorDriveEntry)
|
||||
{
|
||||
//Return error entry
|
||||
return ToErrorFile(driveFile as ErrorDriveEntry);
|
||||
}
|
||||
|
||||
var file = GetFile();
|
||||
|
||||
file.ID = MakeId(driveFile.Id);
|
||||
file.ContentLength = driveFile.Size.HasValue ? (long)driveFile.Size : 0;
|
||||
file.CreateOn = driveFile.CreatedTime.HasValue ? TenantUtil.DateTimeFromUtc(driveFile.CreatedTime.Value) : default;
|
||||
file.FolderID = MakeId(GetParentDriveId(driveFile));
|
||||
file.ModifiedOn = driveFile.ModifiedTime.HasValue ? TenantUtil.DateTimeFromUtc(driveFile.ModifiedTime.Value) : default;
|
||||
file.NativeAccessor = driveFile;
|
||||
file.Title = MakeFileTitle(driveFile);
|
||||
|
||||
return file;
|
||||
}
|
||||
|
||||
public Folder<string> GetRootFolder(string folderId)
|
||||
{
|
||||
return ToFolder(GetDriveEntry(""));
|
||||
}
|
||||
|
||||
protected DriveFile GetDriveEntry(string entryId)
|
||||
{
|
||||
var driveId = MakeDriveId(entryId);
|
||||
try
|
||||
{
|
||||
var entry = ProviderInfo.GetDriveEntry(driveId);
|
||||
return entry;
|
||||
}
|
||||
catch (Exception ex)
|
||||
{
|
||||
return new ErrorDriveEntry(ex, driveId);
|
||||
}
|
||||
}
|
||||
|
||||
protected IEnumerable<string> GetChildren(object folderId)
|
||||
{
|
||||
return GetDriveEntries(folderId).Select(entry => MakeId(entry.Id));
|
||||
}
|
||||
|
||||
protected List<DriveFile> GetDriveEntries(object parentId, bool? folder = null)
|
||||
{
|
||||
var parentDriveId = MakeDriveId(parentId);
|
||||
var entries = ProviderInfo.GetDriveEntries(parentDriveId, folder);
|
||||
return entries;
|
||||
}
|
||||
|
||||
|
||||
protected sealed class ErrorDriveEntry : DriveFile
|
||||
{
|
||||
public string Error { get; set; }
|
||||
|
||||
public string ErrorId { get; private set; }
|
||||
|
||||
|
||||
public ErrorDriveEntry(Exception e, object id)
|
||||
{
|
||||
ErrorId = id.ToString();
|
||||
if (id.ToString() == "root")
|
||||
{
|
||||
MimeType = GoogleLoginProvider.GoogleDriveMimeTypeFolder;
|
||||
}
|
||||
if (e != null)
|
||||
{
|
||||
Error = e.Message;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
78
products/ASC.Files/Server/Core/Thirdparty/GoogleDrive/GoogleDriveDaoSelector.cs
vendored
Normal file
78
products/ASC.Files/Server/Core/Thirdparty/GoogleDrive/GoogleDriveDaoSelector.cs
vendored
Normal file
@ -0,0 +1,78 @@
|
||||
/*
|
||||
*
|
||||
* (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 ASC.Common;
|
||||
using ASC.Files.Core;
|
||||
using ASC.Files.Core.Security;
|
||||
|
||||
namespace ASC.Files.Thirdparty.GoogleDrive
|
||||
{
|
||||
internal class GoogleDriveDaoSelector : RegexDaoSelectorBase<GoogleDriveProviderInfo>, IDaoSelector
|
||||
{
|
||||
protected internal override string Name { get => "GoogleDrive"; }
|
||||
protected internal override string Id { get => "drive"; }
|
||||
public GoogleDriveDaoSelector(IServiceProvider serviceProvider, IDaoFactory daoFactory)
|
||||
: base(serviceProvider, daoFactory)
|
||||
{
|
||||
}
|
||||
|
||||
public IFileDao<string> GetFileDao(string id)
|
||||
{
|
||||
return base.GetFileDao<GoogleDriveFileDao>(id);
|
||||
}
|
||||
|
||||
public IFolderDao<string> GetFolderDao(string id)
|
||||
{
|
||||
return base.GetFolderDao<GoogleDriveFolderDao>(id);
|
||||
}
|
||||
|
||||
public ITagDao<string> GetTagDao(string id)
|
||||
{
|
||||
return base.GetTagDao<GoogleDriveTagDao>(id);
|
||||
}
|
||||
|
||||
public ISecurityDao<string> GetSecurityDao(string id)
|
||||
{
|
||||
return base.GetSecurityDao<GoogleDriveSecurityDao>(id);
|
||||
}
|
||||
}
|
||||
|
||||
public static class GoogleDriveDaoSelectorExtention
|
||||
{
|
||||
public static DIHelper AddGoogleDriveSelectorService(this DIHelper services)
|
||||
{
|
||||
services.TryAddScoped<GoogleDriveDaoSelector>();
|
||||
|
||||
return services
|
||||
.AddGoogleDriveSecurityDaoService()
|
||||
.AddGoogleDriveTagDaoService()
|
||||
.AddGoogleDriveFolderDaoService()
|
||||
.AddGoogleDriveFileDaoService();
|
||||
}
|
||||
}
|
||||
}
|
669
products/ASC.Files/Server/Core/Thirdparty/GoogleDrive/GoogleDriveFileDao.cs
vendored
Normal file
669
products/ASC.Files/Server/Core/Thirdparty/GoogleDrive/GoogleDriveFileDao.cs
vendored
Normal file
@ -0,0 +1,669 @@
|
||||
/*
|
||||
*
|
||||
* (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;
|
||||
using System.IO;
|
||||
using System.Linq;
|
||||
|
||||
using ASC.Common;
|
||||
using ASC.Common.Logging;
|
||||
using ASC.Core;
|
||||
using ASC.Core.Common.EF;
|
||||
using ASC.Core.Tenants;
|
||||
using ASC.Files.Core;
|
||||
using ASC.Files.Core.EF;
|
||||
using ASC.Files.Core.Thirdparty;
|
||||
using ASC.Files.Resources;
|
||||
using ASC.Web.Core.Files;
|
||||
using ASC.Web.Files.Services.DocumentService;
|
||||
using ASC.Web.Studio.Core;
|
||||
|
||||
using Microsoft.Extensions.Options;
|
||||
|
||||
using DriveFile = Google.Apis.Drive.v3.Data.File;
|
||||
|
||||
namespace ASC.Files.Thirdparty.GoogleDrive
|
||||
{
|
||||
internal class GoogleDriveFileDao : GoogleDriveDaoBase, IFileDao<string>
|
||||
{
|
||||
public CrossDao CrossDao { get; }
|
||||
public GoogleDriveDaoSelector GoogleDriveDaoSelector { get; }
|
||||
public IFileDao<int> FileDao { get; }
|
||||
|
||||
public GoogleDriveFileDao(
|
||||
IServiceProvider serviceProvider,
|
||||
UserManager userManager,
|
||||
TenantManager tenantManager,
|
||||
TenantUtil tenantUtil,
|
||||
DbContextManager<FilesDbContext> dbContextManager,
|
||||
SetupInfo setupInfo,
|
||||
IOptionsMonitor<ILog> monitor,
|
||||
FileUtility fileUtility,
|
||||
CrossDao crossDao,
|
||||
GoogleDriveDaoSelector googleDriveDaoSelector,
|
||||
IFileDao<int> fileDao)
|
||||
: base(serviceProvider, userManager, tenantManager, tenantUtil, dbContextManager, setupInfo, monitor, fileUtility)
|
||||
{
|
||||
CrossDao = crossDao;
|
||||
GoogleDriveDaoSelector = googleDriveDaoSelector;
|
||||
FileDao = fileDao;
|
||||
}
|
||||
|
||||
public void InvalidateCache(string fileId)
|
||||
{
|
||||
var driveId = MakeDriveId(fileId);
|
||||
ProviderInfo.CacheReset(driveId, true);
|
||||
|
||||
var driveFile = GetDriveEntry(fileId);
|
||||
var parentDriveId = GetParentDriveId(driveFile);
|
||||
if (parentDriveId != null) ProviderInfo.CacheReset(parentDriveId);
|
||||
}
|
||||
|
||||
public File<string> GetFile(string fileId)
|
||||
{
|
||||
return GetFile(fileId, 1);
|
||||
}
|
||||
|
||||
public File<string> GetFile(string fileId, int fileVersion)
|
||||
{
|
||||
return ToFile(GetDriveEntry(fileId));
|
||||
}
|
||||
|
||||
public File<string> GetFile(string parentId, string title)
|
||||
{
|
||||
return ToFile(GetDriveEntries(parentId, false)
|
||||
.FirstOrDefault(file => file.Name.Equals(title, StringComparison.InvariantCultureIgnoreCase)));
|
||||
}
|
||||
|
||||
public File<string> GetFileStable(string fileId, int fileVersion)
|
||||
{
|
||||
return ToFile(GetDriveEntry(fileId));
|
||||
}
|
||||
|
||||
public List<File<string>> GetFileHistory(string fileId)
|
||||
{
|
||||
return new List<File<string>> { GetFile(fileId) };
|
||||
}
|
||||
|
||||
public List<File<string>> GetFiles(string[] fileIds)
|
||||
{
|
||||
if (fileIds == null || fileIds.Length == 0) return new List<File<string>>();
|
||||
return fileIds.Select(GetDriveEntry).Select(ToFile).ToList();
|
||||
}
|
||||
|
||||
public List<File<string>> GetFilesForShare(string[] fileIds, FilterType filterType, bool subjectGroup, Guid subjectID, string searchText, bool searchInContent)
|
||||
{
|
||||
if (fileIds == null || fileIds.Length == 0 || filterType == FilterType.FoldersOnly) return new List<File<string>>();
|
||||
|
||||
var files = GetFiles(fileIds).AsEnumerable();
|
||||
|
||||
//Filter
|
||||
if (subjectID != Guid.Empty)
|
||||
{
|
||||
files = files.Where(x => subjectGroup
|
||||
? UserManager.IsUserInGroup(x.CreateBy, subjectID)
|
||||
: x.CreateBy == subjectID);
|
||||
}
|
||||
|
||||
switch (filterType)
|
||||
{
|
||||
case FilterType.FoldersOnly:
|
||||
return new List<File<string>>();
|
||||
case FilterType.DocumentsOnly:
|
||||
files = files.Where(x => FileUtility.GetFileTypeByFileName(x.Title) == FileType.Document);
|
||||
break;
|
||||
case FilterType.PresentationsOnly:
|
||||
files = files.Where(x => FileUtility.GetFileTypeByFileName(x.Title) == FileType.Presentation);
|
||||
break;
|
||||
case FilterType.SpreadsheetsOnly:
|
||||
files = files.Where(x => FileUtility.GetFileTypeByFileName(x.Title) == FileType.Spreadsheet);
|
||||
break;
|
||||
case FilterType.ImagesOnly:
|
||||
files = files.Where(x => FileUtility.GetFileTypeByFileName(x.Title) == FileType.Image);
|
||||
break;
|
||||
case FilterType.ArchiveOnly:
|
||||
files = files.Where(x => FileUtility.GetFileTypeByFileName(x.Title) == FileType.Archive);
|
||||
break;
|
||||
case FilterType.MediaOnly:
|
||||
files = files.Where(x =>
|
||||
{
|
||||
FileType fileType;
|
||||
return (fileType = FileUtility.GetFileTypeByFileName(x.Title)) == FileType.Audio || fileType == FileType.Video;
|
||||
});
|
||||
break;
|
||||
case FilterType.ByExtension:
|
||||
if (!string.IsNullOrEmpty(searchText))
|
||||
files = files.Where(x => FileUtility.GetFileExtension(x.Title).Contains(searchText));
|
||||
break;
|
||||
}
|
||||
|
||||
if (!string.IsNullOrEmpty(searchText))
|
||||
files = files.Where(x => x.Title.IndexOf(searchText, StringComparison.OrdinalIgnoreCase) != -1);
|
||||
|
||||
return files.ToList();
|
||||
}
|
||||
|
||||
public List<string> GetFiles(string parentId)
|
||||
{
|
||||
return GetDriveEntries(parentId, false).Select(entry => MakeId(entry.Id)).ToList();
|
||||
}
|
||||
|
||||
public List<File<string>> GetFiles(string parentId, OrderBy orderBy, FilterType filterType, bool subjectGroup, Guid subjectID, string searchText, bool searchInContent, bool withSubfolders = false)
|
||||
{
|
||||
if (filterType == FilterType.FoldersOnly) return new List<File<string>>();
|
||||
|
||||
//Get only files
|
||||
var files = GetDriveEntries(parentId, false).Select(ToFile);
|
||||
|
||||
//Filter
|
||||
if (subjectID != Guid.Empty)
|
||||
{
|
||||
files = files.Where(x => subjectGroup
|
||||
? UserManager.IsUserInGroup(x.CreateBy, subjectID)
|
||||
: x.CreateBy == subjectID);
|
||||
}
|
||||
|
||||
switch (filterType)
|
||||
{
|
||||
case FilterType.FoldersOnly:
|
||||
return new List<File<string>>();
|
||||
case FilterType.DocumentsOnly:
|
||||
files = files.Where(x => FileUtility.GetFileTypeByFileName(x.Title) == FileType.Document);
|
||||
break;
|
||||
case FilterType.PresentationsOnly:
|
||||
files = files.Where(x => FileUtility.GetFileTypeByFileName(x.Title) == FileType.Presentation);
|
||||
break;
|
||||
case FilterType.SpreadsheetsOnly:
|
||||
files = files.Where(x => FileUtility.GetFileTypeByFileName(x.Title) == FileType.Spreadsheet);
|
||||
break;
|
||||
case FilterType.ImagesOnly:
|
||||
files = files.Where(x => FileUtility.GetFileTypeByFileName(x.Title) == FileType.Image);
|
||||
break;
|
||||
case FilterType.ArchiveOnly:
|
||||
files = files.Where(x => FileUtility.GetFileTypeByFileName(x.Title) == FileType.Archive);
|
||||
break;
|
||||
case FilterType.MediaOnly:
|
||||
files = files.Where(x =>
|
||||
{
|
||||
FileType fileType;
|
||||
return (fileType = FileUtility.GetFileTypeByFileName(x.Title)) == FileType.Audio || fileType == FileType.Video;
|
||||
});
|
||||
break;
|
||||
case FilterType.ByExtension:
|
||||
if (!string.IsNullOrEmpty(searchText))
|
||||
files = files.Where(x => FileUtility.GetFileExtension(x.Title).Contains(searchText));
|
||||
break;
|
||||
}
|
||||
|
||||
if (!string.IsNullOrEmpty(searchText))
|
||||
files = files.Where(x => x.Title.IndexOf(searchText, StringComparison.OrdinalIgnoreCase) != -1);
|
||||
|
||||
if (orderBy == null) orderBy = new OrderBy(SortedByType.DateAndTime, false);
|
||||
|
||||
switch (orderBy.SortedBy)
|
||||
{
|
||||
case SortedByType.Author:
|
||||
files = orderBy.IsAsc ? files.OrderBy(x => x.CreateBy) : files.OrderByDescending(x => x.CreateBy);
|
||||
break;
|
||||
case SortedByType.AZ:
|
||||
files = orderBy.IsAsc ? files.OrderBy(x => x.Title) : files.OrderByDescending(x => x.Title);
|
||||
break;
|
||||
case SortedByType.DateAndTime:
|
||||
files = orderBy.IsAsc ? files.OrderBy(x => x.ModifiedOn) : files.OrderByDescending(x => x.ModifiedOn);
|
||||
break;
|
||||
case SortedByType.DateAndTimeCreation:
|
||||
files = orderBy.IsAsc ? files.OrderBy(x => x.CreateOn) : files.OrderByDescending(x => x.CreateOn);
|
||||
break;
|
||||
default:
|
||||
files = orderBy.IsAsc ? files.OrderBy(x => x.Title) : files.OrderByDescending(x => x.Title);
|
||||
break;
|
||||
}
|
||||
|
||||
return files.ToList();
|
||||
}
|
||||
|
||||
public Stream GetFileStream(File<string> file)
|
||||
{
|
||||
return GetFileStream(file, 0);
|
||||
}
|
||||
|
||||
public Stream GetFileStream(File<string> file, long offset)
|
||||
{
|
||||
var driveId = MakeDriveId(file.ID);
|
||||
ProviderInfo.CacheReset(driveId, true);
|
||||
var driveFile = GetDriveEntry(file.ID);
|
||||
if (driveFile == null) throw new ArgumentNullException("file", FilesCommonResource.ErrorMassage_FileNotFound);
|
||||
if (driveFile is ErrorDriveEntry) throw new Exception(((ErrorDriveEntry)driveFile).Error);
|
||||
|
||||
var fileStream = ProviderInfo.Storage.DownloadStream(driveFile, (int)offset);
|
||||
|
||||
if (!driveFile.Size.HasValue && fileStream != null && fileStream.CanSeek)
|
||||
{
|
||||
file.ContentLength = fileStream.Length; // hack for google drive
|
||||
}
|
||||
|
||||
return fileStream;
|
||||
}
|
||||
|
||||
public Uri GetPreSignedUri(File<string> file, TimeSpan expires)
|
||||
{
|
||||
throw new NotSupportedException();
|
||||
}
|
||||
|
||||
public bool IsSupportedPreSignedUri(File<string> file)
|
||||
{
|
||||
return false;
|
||||
}
|
||||
|
||||
public File<string> SaveFile(File<string> file, Stream fileStream)
|
||||
{
|
||||
if (file == null) throw new ArgumentNullException("file");
|
||||
if (fileStream == null) throw new ArgumentNullException("fileStream");
|
||||
|
||||
DriveFile newDriveFile = null;
|
||||
|
||||
if (file.ID != null)
|
||||
{
|
||||
newDriveFile = ProviderInfo.Storage.SaveStream(MakeDriveId(file.ID), fileStream, file.Title);
|
||||
}
|
||||
else if (file.FolderID != null)
|
||||
{
|
||||
newDriveFile = ProviderInfo.Storage.InsertEntry(fileStream, file.Title, MakeDriveId(file.FolderID));
|
||||
}
|
||||
|
||||
ProviderInfo.CacheReset(newDriveFile);
|
||||
var parentDriveId = GetParentDriveId(newDriveFile);
|
||||
if (parentDriveId != null) ProviderInfo.CacheReset(parentDriveId, false);
|
||||
|
||||
return ToFile(newDriveFile);
|
||||
}
|
||||
|
||||
public File<string> ReplaceFileVersion(File<string> file, Stream fileStream)
|
||||
{
|
||||
return SaveFile(file, fileStream);
|
||||
}
|
||||
|
||||
public void DeleteFile(string fileId)
|
||||
{
|
||||
var driveFile = GetDriveEntry(fileId);
|
||||
if (driveFile == null) return;
|
||||
var id = MakeId(driveFile.Id);
|
||||
|
||||
using (var tx = FilesDbContext.Database.BeginTransaction())
|
||||
{
|
||||
var hashIDs = Query(FilesDbContext.ThirdpartyIdMapping)
|
||||
.Where(r => r.Id.StartsWith(id))
|
||||
.Select(r => r.HashId)
|
||||
.ToList();
|
||||
|
||||
var link = Query(FilesDbContext.TagLink)
|
||||
.Where(r => hashIDs.Any(h => h == r.EntryId))
|
||||
.ToList();
|
||||
|
||||
FilesDbContext.TagLink.RemoveRange(link);
|
||||
FilesDbContext.SaveChanges();
|
||||
|
||||
var tagsToRemove = Query(FilesDbContext.Tag)
|
||||
.Where(r => !Query(FilesDbContext.TagLink).Where(a => a.TagId == r.Id).Any());
|
||||
|
||||
FilesDbContext.Tag.RemoveRange(tagsToRemove);
|
||||
|
||||
var securityToDelete = Query(FilesDbContext.Security)
|
||||
.Where(r => hashIDs.Any(h => h == r.EntryId));
|
||||
|
||||
FilesDbContext.Security.RemoveRange(securityToDelete);
|
||||
FilesDbContext.SaveChanges();
|
||||
|
||||
var mappingToDelete = Query(FilesDbContext.ThirdpartyIdMapping)
|
||||
.Where(r => hashIDs.Any(h => h == r.HashId));
|
||||
|
||||
FilesDbContext.ThirdpartyIdMapping.RemoveRange(mappingToDelete);
|
||||
FilesDbContext.SaveChanges();
|
||||
|
||||
tx.Commit();
|
||||
}
|
||||
|
||||
if (!(driveFile is ErrorDriveEntry))
|
||||
{
|
||||
ProviderInfo.Storage.DeleteEntry(driveFile.Id);
|
||||
}
|
||||
|
||||
ProviderInfo.CacheReset(driveFile.Id);
|
||||
var parentDriveId = GetParentDriveId(driveFile);
|
||||
if (parentDriveId != null) ProviderInfo.CacheReset(parentDriveId, false);
|
||||
}
|
||||
|
||||
public bool IsExist(string title, object folderId)
|
||||
{
|
||||
return GetDriveEntries(folderId, false)
|
||||
.Any(file => file.Name.Equals(title, StringComparison.InvariantCultureIgnoreCase));
|
||||
}
|
||||
|
||||
public TTo MoveFile<TTo>(string fileId, TTo toFolderId)
|
||||
{
|
||||
if (toFolderId is int tId)
|
||||
{
|
||||
return (TTo)Convert.ChangeType(MoveFile(fileId, tId), typeof(TTo));
|
||||
}
|
||||
|
||||
if (toFolderId is string tsId)
|
||||
{
|
||||
return (TTo)Convert.ChangeType(MoveFile(fileId, tsId), typeof(TTo));
|
||||
}
|
||||
|
||||
throw new NotImplementedException();
|
||||
}
|
||||
|
||||
public int MoveFile(string fileId, int toFolderId)
|
||||
{
|
||||
var moved = CrossDao.PerformCrossDaoFileCopy(
|
||||
fileId, this, GoogleDriveDaoSelector.ConvertId,
|
||||
toFolderId, FileDao, r => r,
|
||||
true);
|
||||
|
||||
return moved.ID;
|
||||
}
|
||||
|
||||
public string MoveFile(string fileId, string toFolderId)
|
||||
{
|
||||
var driveFile = GetDriveEntry(fileId);
|
||||
if (driveFile is ErrorDriveEntry) throw new Exception(((ErrorDriveEntry)driveFile).Error);
|
||||
|
||||
var toDriveFolder = GetDriveEntry(toFolderId);
|
||||
if (toDriveFolder is ErrorDriveEntry) throw new Exception(((ErrorDriveEntry)toDriveFolder).Error);
|
||||
|
||||
var fromFolderDriveId = GetParentDriveId(driveFile);
|
||||
|
||||
driveFile = ProviderInfo.Storage.InsertEntryIntoFolder(driveFile, toDriveFolder.Id);
|
||||
if (fromFolderDriveId != null)
|
||||
{
|
||||
ProviderInfo.Storage.RemoveEntryFromFolder(driveFile, fromFolderDriveId);
|
||||
}
|
||||
|
||||
ProviderInfo.CacheReset(driveFile.Id);
|
||||
ProviderInfo.CacheReset(fromFolderDriveId, false);
|
||||
ProviderInfo.CacheReset(toDriveFolder.Id, false);
|
||||
|
||||
return MakeId(driveFile.Id);
|
||||
}
|
||||
|
||||
public File<TTo> CopyFile<TTo>(string fileId, TTo toFolderId)
|
||||
{
|
||||
if (toFolderId is int tId)
|
||||
{
|
||||
return CopyFile(fileId, tId) as File<TTo>;
|
||||
}
|
||||
|
||||
if (toFolderId is string tsId)
|
||||
{
|
||||
return CopyFile(fileId, tsId) as File<TTo>;
|
||||
}
|
||||
|
||||
throw new NotImplementedException();
|
||||
}
|
||||
|
||||
public File<int> CopyFile(string fileId, int toFolderId)
|
||||
{
|
||||
var moved = CrossDao.PerformCrossDaoFileCopy(
|
||||
fileId, this, GoogleDriveDaoSelector.ConvertId,
|
||||
toFolderId, FileDao, r => r,
|
||||
false);
|
||||
|
||||
return moved;
|
||||
}
|
||||
|
||||
public File<string> CopyFile(string fileId, string toFolderId)
|
||||
{
|
||||
var driveFile = GetDriveEntry(fileId);
|
||||
if (driveFile is ErrorDriveEntry) throw new Exception(((ErrorDriveEntry)driveFile).Error);
|
||||
|
||||
var toDriveFolder = GetDriveEntry(toFolderId);
|
||||
if (toDriveFolder is ErrorDriveEntry) throw new Exception(((ErrorDriveEntry)toDriveFolder).Error);
|
||||
|
||||
var newDriveFile = ProviderInfo.Storage.CopyEntry(toDriveFolder.Id, driveFile.Id);
|
||||
|
||||
ProviderInfo.CacheReset(newDriveFile);
|
||||
ProviderInfo.CacheReset(toDriveFolder.Id, false);
|
||||
|
||||
return ToFile(newDriveFile);
|
||||
}
|
||||
|
||||
public string FileRename(File<string> file, string newTitle)
|
||||
{
|
||||
var driveFile = GetDriveEntry(file.ID);
|
||||
driveFile.Name = newTitle;
|
||||
|
||||
driveFile = ProviderInfo.Storage.RenameEntry(driveFile.Id, driveFile.Name);
|
||||
|
||||
ProviderInfo.CacheReset(driveFile);
|
||||
var parentDriveId = GetParentDriveId(driveFile);
|
||||
if (parentDriveId != null) ProviderInfo.CacheReset(parentDriveId, false);
|
||||
|
||||
return MakeId(driveFile.Id);
|
||||
}
|
||||
|
||||
public string UpdateComment(string fileId, int fileVersion, string comment)
|
||||
{
|
||||
return string.Empty;
|
||||
}
|
||||
|
||||
public void CompleteVersion(string fileId, int fileVersion)
|
||||
{
|
||||
}
|
||||
|
||||
public void ContinueVersion(string fileId, int fileVersion)
|
||||
{
|
||||
}
|
||||
|
||||
public bool UseTrashForRemove(File<string> file)
|
||||
{
|
||||
return false;
|
||||
}
|
||||
|
||||
#region chunking
|
||||
|
||||
private File<string> RestoreIds(File<string> file)
|
||||
{
|
||||
if (file == null) return null;
|
||||
|
||||
if (file.ID != null)
|
||||
file.ID = MakeId(file.ID);
|
||||
|
||||
if (file.FolderID != null)
|
||||
file.FolderID = MakeId(file.FolderID);
|
||||
|
||||
return file;
|
||||
}
|
||||
|
||||
public ChunkedUploadSession<string> CreateUploadSession(File<string> file, long contentLength)
|
||||
{
|
||||
if (SetupInfo.ChunkUploadSize > contentLength)
|
||||
return new ChunkedUploadSession<string>(RestoreIds(file), contentLength) { UseChunks = false };
|
||||
|
||||
var uploadSession = new ChunkedUploadSession<string>(file, contentLength);
|
||||
|
||||
DriveFile driveFile;
|
||||
if (file.ID != null)
|
||||
{
|
||||
driveFile = GetDriveEntry(file.ID);
|
||||
}
|
||||
else
|
||||
{
|
||||
var folder = GetDriveEntry(file.FolderID);
|
||||
driveFile = ProviderInfo.Storage.FileConstructor(file.Title, null, folder.Id);
|
||||
}
|
||||
|
||||
var googleDriveSession = ProviderInfo.Storage.CreateResumableSession(driveFile, contentLength);
|
||||
if (googleDriveSession != null)
|
||||
{
|
||||
uploadSession.Items["GoogleDriveSession"] = googleDriveSession;
|
||||
}
|
||||
else
|
||||
{
|
||||
uploadSession.Items["TempPath"] = Path.GetTempFileName();
|
||||
}
|
||||
|
||||
uploadSession.File = RestoreIds(uploadSession.File);
|
||||
return uploadSession;
|
||||
}
|
||||
|
||||
public void UploadChunk(ChunkedUploadSession<string> uploadSession, Stream stream, long chunkLength)
|
||||
{
|
||||
if (!uploadSession.UseChunks)
|
||||
{
|
||||
if (uploadSession.BytesTotal == 0)
|
||||
uploadSession.BytesTotal = chunkLength;
|
||||
|
||||
uploadSession.File = SaveFile(uploadSession.File, stream);
|
||||
uploadSession.BytesUploaded = chunkLength;
|
||||
return;
|
||||
}
|
||||
|
||||
if (uploadSession.Items.ContainsKey("GoogleDriveSession"))
|
||||
{
|
||||
var googleDriveSession = uploadSession.GetItemOrDefault<ResumableUploadSession>("GoogleDriveSession");
|
||||
ProviderInfo.Storage.Transfer(googleDriveSession, stream, chunkLength);
|
||||
}
|
||||
else
|
||||
{
|
||||
var tempPath = uploadSession.GetItemOrDefault<string>("TempPath");
|
||||
using (var fs = new FileStream(tempPath, FileMode.Append))
|
||||
{
|
||||
stream.CopyTo(fs);
|
||||
}
|
||||
}
|
||||
|
||||
uploadSession.BytesUploaded += chunkLength;
|
||||
|
||||
if (uploadSession.BytesUploaded == uploadSession.BytesTotal)
|
||||
{
|
||||
uploadSession.File = FinalizeUploadSession(uploadSession);
|
||||
}
|
||||
else
|
||||
{
|
||||
uploadSession.File = RestoreIds(uploadSession.File);
|
||||
}
|
||||
}
|
||||
|
||||
public File<string> FinalizeUploadSession(ChunkedUploadSession<string> uploadSession)
|
||||
{
|
||||
if (uploadSession.Items.ContainsKey("GoogleDriveSession"))
|
||||
{
|
||||
var googleDriveSession = uploadSession.GetItemOrDefault<ResumableUploadSession>("GoogleDriveSession");
|
||||
|
||||
ProviderInfo.CacheReset(googleDriveSession.FileId);
|
||||
var parentDriveId = googleDriveSession.FolderId;
|
||||
if (parentDriveId != null) ProviderInfo.CacheReset(parentDriveId, false);
|
||||
|
||||
return ToFile(GetDriveEntry(googleDriveSession.FileId));
|
||||
}
|
||||
|
||||
using (var fs = new FileStream(uploadSession.GetItemOrDefault<string>("TempPath"), FileMode.Open, FileAccess.Read, FileShare.None, 4096, FileOptions.DeleteOnClose))
|
||||
{
|
||||
return SaveFile(uploadSession.File, fs);
|
||||
}
|
||||
}
|
||||
|
||||
public void AbortUploadSession(ChunkedUploadSession<string> uploadSession)
|
||||
{
|
||||
if (uploadSession.Items.ContainsKey("GoogleDriveSession"))
|
||||
{
|
||||
var googleDriveSession = uploadSession.GetItemOrDefault<ResumableUploadSession>("GoogleDriveSession");
|
||||
|
||||
if (googleDriveSession.Status != ResumableUploadSessionStatus.Completed)
|
||||
{
|
||||
googleDriveSession.Status = ResumableUploadSessionStatus.Aborted;
|
||||
}
|
||||
}
|
||||
else if (uploadSession.Items.ContainsKey("TempPath"))
|
||||
{
|
||||
File.Delete(uploadSession.GetItemOrDefault<string>("TempPath"));
|
||||
}
|
||||
}
|
||||
|
||||
#endregion
|
||||
|
||||
|
||||
#region Only in TMFileDao
|
||||
|
||||
public void ReassignFiles(string[] fileIds, Guid newOwnerId)
|
||||
{
|
||||
}
|
||||
|
||||
public List<File<string>> GetFiles(string[] parentIds, FilterType filterType, bool subjectGroup, Guid subjectID, string searchText, bool searchInContent)
|
||||
{
|
||||
return new List<File<string>>();
|
||||
}
|
||||
|
||||
public IEnumerable<File<string>> Search(string text, bool bunch)
|
||||
{
|
||||
return null;
|
||||
}
|
||||
|
||||
public bool IsExistOnStorage(File<string> file)
|
||||
{
|
||||
return true;
|
||||
}
|
||||
|
||||
public void SaveEditHistory(File<string> file, string changes, Stream differenceStream)
|
||||
{
|
||||
//Do nothing
|
||||
}
|
||||
|
||||
public List<EditHistory> GetEditHistory(DocumentServiceHelper documentServiceHelper, string fileId, int fileVersion)
|
||||
{
|
||||
return null;
|
||||
}
|
||||
|
||||
public Stream GetDifferenceStream(File<string> file)
|
||||
{
|
||||
return null;
|
||||
}
|
||||
|
||||
public bool ContainChanges(string fileId, int fileVersion)
|
||||
{
|
||||
return false;
|
||||
}
|
||||
|
||||
public string GetUniqFilePath(File<string> file, string fileTitle)
|
||||
{
|
||||
return null;
|
||||
}
|
||||
|
||||
#endregion
|
||||
}
|
||||
|
||||
public static class GoogleDriveFilrDaoExtention
|
||||
{
|
||||
public static DIHelper AddGoogleDriveFileDaoService(this DIHelper services)
|
||||
{
|
||||
services.TryAddScoped<GoogleDriveFileDao>();
|
||||
|
||||
return services;
|
||||
}
|
||||
}
|
||||
}
|
514
products/ASC.Files/Server/Core/Thirdparty/GoogleDrive/GoogleDriveFolderDao.cs
vendored
Normal file
514
products/ASC.Files/Server/Core/Thirdparty/GoogleDrive/GoogleDriveFolderDao.cs
vendored
Normal file
@ -0,0 +1,514 @@
|
||||
/*
|
||||
*
|
||||
* (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;
|
||||
using System.Linq;
|
||||
using System.Threading;
|
||||
|
||||
using ASC.Common;
|
||||
using ASC.Common.Logging;
|
||||
using ASC.Core;
|
||||
using ASC.Core.Common.EF;
|
||||
using ASC.Core.Tenants;
|
||||
using ASC.Files.Core;
|
||||
using ASC.Files.Core.EF;
|
||||
using ASC.Files.Core.Thirdparty;
|
||||
using ASC.Web.Core.Files;
|
||||
using ASC.Web.Studio.Core;
|
||||
|
||||
using Microsoft.Extensions.Options;
|
||||
|
||||
namespace ASC.Files.Thirdparty.GoogleDrive
|
||||
{
|
||||
internal class GoogleDriveFolderDao : GoogleDriveDaoBase, IFolderDao<string>
|
||||
{
|
||||
public CrossDao CrossDao { get; }
|
||||
public GoogleDriveDaoSelector GoogleDriveDaoSelector { get; }
|
||||
public IFileDao<int> FileDao { get; }
|
||||
public IFolderDao<int> FolderDao { get; }
|
||||
|
||||
public GoogleDriveFolderDao(
|
||||
IServiceProvider serviceProvider,
|
||||
UserManager userManager,
|
||||
TenantManager tenantManager,
|
||||
TenantUtil tenantUtil,
|
||||
DbContextManager<FilesDbContext> dbContextManager,
|
||||
SetupInfo setupInfo,
|
||||
IOptionsMonitor<ILog> monitor,
|
||||
FileUtility fileUtility,
|
||||
CrossDao crossDao,
|
||||
GoogleDriveDaoSelector googleDriveDaoSelector,
|
||||
IFileDao<int> fileDao,
|
||||
IFolderDao<int> folderDao
|
||||
) : base(serviceProvider, userManager, tenantManager, tenantUtil, dbContextManager, setupInfo, monitor, fileUtility)
|
||||
{
|
||||
CrossDao = crossDao;
|
||||
GoogleDriveDaoSelector = googleDriveDaoSelector;
|
||||
FileDao = fileDao;
|
||||
FolderDao = folderDao;
|
||||
}
|
||||
|
||||
public Folder<string> GetFolder(string folderId)
|
||||
{
|
||||
return ToFolder(GetDriveEntry(folderId));
|
||||
}
|
||||
|
||||
public Folder<string> GetFolder(string title, string parentId)
|
||||
{
|
||||
return ToFolder(GetDriveEntries(parentId, true)
|
||||
.FirstOrDefault(folder => folder.Name.Equals(title, StringComparison.InvariantCultureIgnoreCase)));
|
||||
}
|
||||
|
||||
public Folder<string> GetRootFolderByFile(string fileId)
|
||||
{
|
||||
return GetRootFolder("");
|
||||
}
|
||||
|
||||
public List<Folder<string>> GetFolders(string parentId)
|
||||
{
|
||||
return GetDriveEntries(parentId, true).Select(ToFolder).ToList();
|
||||
}
|
||||
|
||||
public List<Folder<string>> GetFolders(string parentId, OrderBy orderBy, FilterType filterType, bool subjectGroup, Guid subjectID, string searchText, bool withSubfolders = false)
|
||||
{
|
||||
if (filterType == FilterType.FilesOnly || filterType == FilterType.ByExtension
|
||||
|| filterType == FilterType.DocumentsOnly || filterType == FilterType.ImagesOnly
|
||||
|| filterType == FilterType.PresentationsOnly || filterType == FilterType.SpreadsheetsOnly
|
||||
|| filterType == FilterType.ArchiveOnly || filterType == FilterType.MediaOnly)
|
||||
return new List<Folder<string>>();
|
||||
|
||||
var folders = GetFolders(parentId).AsEnumerable(); //TODO:!!!
|
||||
|
||||
if (subjectID != Guid.Empty)
|
||||
{
|
||||
folders = folders.Where(x => subjectGroup
|
||||
? UserManager.IsUserInGroup(x.CreateBy, subjectID)
|
||||
: x.CreateBy == subjectID);
|
||||
}
|
||||
|
||||
if (!string.IsNullOrEmpty(searchText))
|
||||
folders = folders.Where(x => x.Title.IndexOf(searchText, StringComparison.OrdinalIgnoreCase) != -1);
|
||||
|
||||
if (orderBy == null) orderBy = new OrderBy(SortedByType.DateAndTime, false);
|
||||
|
||||
switch (orderBy.SortedBy)
|
||||
{
|
||||
case SortedByType.Author:
|
||||
folders = orderBy.IsAsc ? folders.OrderBy(x => x.CreateBy) : folders.OrderByDescending(x => x.CreateBy);
|
||||
break;
|
||||
case SortedByType.AZ:
|
||||
folders = orderBy.IsAsc ? folders.OrderBy(x => x.Title) : folders.OrderByDescending(x => x.Title);
|
||||
break;
|
||||
case SortedByType.DateAndTime:
|
||||
folders = orderBy.IsAsc ? folders.OrderBy(x => x.ModifiedOn) : folders.OrderByDescending(x => x.ModifiedOn);
|
||||
break;
|
||||
case SortedByType.DateAndTimeCreation:
|
||||
folders = orderBy.IsAsc ? folders.OrderBy(x => x.CreateOn) : folders.OrderByDescending(x => x.CreateOn);
|
||||
break;
|
||||
default:
|
||||
folders = orderBy.IsAsc ? folders.OrderBy(x => x.Title) : folders.OrderByDescending(x => x.Title);
|
||||
break;
|
||||
}
|
||||
|
||||
return folders.ToList();
|
||||
}
|
||||
|
||||
public List<Folder<string>> GetFolders(string[] folderIds, FilterType filterType = FilterType.None, bool subjectGroup = false, Guid? subjectID = null, string searchText = "", bool searchSubfolders = false, bool checkShare = true)
|
||||
{
|
||||
if (filterType == FilterType.FilesOnly || filterType == FilterType.ByExtension
|
||||
|| filterType == FilterType.DocumentsOnly || filterType == FilterType.ImagesOnly
|
||||
|| filterType == FilterType.PresentationsOnly || filterType == FilterType.SpreadsheetsOnly
|
||||
|| filterType == FilterType.ArchiveOnly || filterType == FilterType.MediaOnly)
|
||||
return new List<Folder<string>>();
|
||||
|
||||
var folders = folderIds.Select(GetFolder);
|
||||
|
||||
if (subjectID.HasValue && subjectID != Guid.Empty)
|
||||
{
|
||||
folders = folders.Where(x => subjectGroup
|
||||
? UserManager.IsUserInGroup(x.CreateBy, subjectID.Value)
|
||||
: x.CreateBy == subjectID);
|
||||
}
|
||||
|
||||
if (!string.IsNullOrEmpty(searchText))
|
||||
folders = folders.Where(x => x.Title.IndexOf(searchText, StringComparison.OrdinalIgnoreCase) != -1);
|
||||
|
||||
return folders.ToList();
|
||||
}
|
||||
|
||||
public List<Folder<string>> GetParentFolders(string folderId)
|
||||
{
|
||||
var path = new List<Folder<string>>();
|
||||
|
||||
while (folderId != null)
|
||||
{
|
||||
var driveFolder = GetDriveEntry(folderId);
|
||||
|
||||
if (driveFolder is ErrorDriveEntry)
|
||||
{
|
||||
folderId = null;
|
||||
}
|
||||
else
|
||||
{
|
||||
path.Add(ToFolder(driveFolder));
|
||||
folderId = GetParentDriveId(driveFolder);
|
||||
}
|
||||
}
|
||||
|
||||
path.Reverse();
|
||||
return path;
|
||||
}
|
||||
|
||||
public string SaveFolder(Folder<string> folder)
|
||||
{
|
||||
if (folder == null) throw new ArgumentNullException("folder");
|
||||
if (folder.ID != null)
|
||||
{
|
||||
return RenameFolder(folder, folder.Title);
|
||||
}
|
||||
|
||||
if (folder.ParentFolderID != null)
|
||||
{
|
||||
var driveFolderId = MakeDriveId(folder.ParentFolderID);
|
||||
|
||||
var driveFolder = ProviderInfo.Storage.InsertEntry(null, folder.Title, driveFolderId, true);
|
||||
|
||||
ProviderInfo.CacheReset(driveFolder);
|
||||
var parentDriveId = GetParentDriveId(driveFolder);
|
||||
if (parentDriveId != null) ProviderInfo.CacheReset(parentDriveId, true);
|
||||
|
||||
return MakeId(driveFolder);
|
||||
}
|
||||
return null;
|
||||
}
|
||||
|
||||
public void DeleteFolder(string folderId)
|
||||
{
|
||||
var driveFolder = GetDriveEntry(folderId);
|
||||
var id = MakeId(driveFolder);
|
||||
|
||||
using (var tx = FilesDbContext.Database.BeginTransaction())
|
||||
{
|
||||
var hashIDs = Query(FilesDbContext.ThirdpartyIdMapping)
|
||||
.Where(r => r.Id.StartsWith(id))
|
||||
.Select(r => r.HashId)
|
||||
.ToList();
|
||||
|
||||
var link = Query(FilesDbContext.TagLink)
|
||||
.Where(r => hashIDs.Any(h => h == r.EntryId))
|
||||
.ToList();
|
||||
|
||||
FilesDbContext.TagLink.RemoveRange(link);
|
||||
FilesDbContext.SaveChanges();
|
||||
|
||||
var tagsToRemove = Query(FilesDbContext.Tag)
|
||||
.Where(r => !Query(FilesDbContext.TagLink).Where(a => a.TagId == r.Id).Any());
|
||||
|
||||
FilesDbContext.Tag.RemoveRange(tagsToRemove);
|
||||
|
||||
var securityToDelete = Query(FilesDbContext.Security)
|
||||
.Where(r => hashIDs.Any(h => h == r.EntryId));
|
||||
|
||||
FilesDbContext.Security.RemoveRange(securityToDelete);
|
||||
FilesDbContext.SaveChanges();
|
||||
|
||||
var mappingToDelete = Query(FilesDbContext.ThirdpartyIdMapping)
|
||||
.Where(r => hashIDs.Any(h => h == r.HashId));
|
||||
|
||||
FilesDbContext.ThirdpartyIdMapping.RemoveRange(mappingToDelete);
|
||||
FilesDbContext.SaveChanges();
|
||||
|
||||
tx.Commit();
|
||||
}
|
||||
|
||||
if (!(driveFolder is ErrorDriveEntry))
|
||||
ProviderInfo.Storage.DeleteEntry(driveFolder.Id);
|
||||
|
||||
ProviderInfo.CacheReset(driveFolder.Id);
|
||||
var parentDriveId = GetParentDriveId(driveFolder);
|
||||
if (parentDriveId != null) ProviderInfo.CacheReset(parentDriveId, true);
|
||||
}
|
||||
|
||||
|
||||
public int MoveFolder(string folderId, int toFolderId, CancellationToken? cancellationToken)
|
||||
{
|
||||
var moved = CrossDao.PerformCrossDaoFolderCopy(
|
||||
folderId, this, GoogleDriveDaoSelector.GetFileDao(folderId), GoogleDriveDaoSelector.ConvertId,
|
||||
toFolderId, FolderDao, FileDao, r => r,
|
||||
true, cancellationToken);
|
||||
|
||||
return moved.ID;
|
||||
}
|
||||
|
||||
public TTo MoveFolder<TTo>(string folderId, TTo toFolderId, CancellationToken? cancellationToken)
|
||||
{
|
||||
if (toFolderId is int tId)
|
||||
{
|
||||
return (TTo)Convert.ChangeType(MoveFolder(folderId, tId, cancellationToken), typeof(TTo));
|
||||
}
|
||||
|
||||
if (toFolderId is string tsId)
|
||||
{
|
||||
return (TTo)Convert.ChangeType(MoveFolder(folderId, tsId, cancellationToken), typeof(TTo));
|
||||
}
|
||||
|
||||
throw new NotImplementedException();
|
||||
}
|
||||
|
||||
public string MoveFolder(string folderId, string toFolderId, CancellationToken? cancellationToken)
|
||||
{
|
||||
var driveFolder = GetDriveEntry(folderId);
|
||||
if (driveFolder is ErrorDriveEntry) throw new Exception(((ErrorDriveEntry)driveFolder).Error);
|
||||
|
||||
var toDriveFolder = GetDriveEntry(toFolderId);
|
||||
if (toDriveFolder is ErrorDriveEntry) throw new Exception(((ErrorDriveEntry)toDriveFolder).Error);
|
||||
|
||||
var fromFolderDriveId = GetParentDriveId(driveFolder);
|
||||
|
||||
driveFolder = ProviderInfo.Storage.InsertEntryIntoFolder(driveFolder, toDriveFolder.Id);
|
||||
if (fromFolderDriveId != null)
|
||||
{
|
||||
ProviderInfo.Storage.RemoveEntryFromFolder(driveFolder, fromFolderDriveId);
|
||||
}
|
||||
|
||||
ProviderInfo.CacheReset(driveFolder.Id);
|
||||
ProviderInfo.CacheReset(fromFolderDriveId, true);
|
||||
ProviderInfo.CacheReset(toDriveFolder.Id, true);
|
||||
|
||||
return MakeId(driveFolder.Id);
|
||||
}
|
||||
|
||||
public Folder<TTo> CopyFolder<TTo>(string folderId, TTo toFolderId, CancellationToken? cancellationToken)
|
||||
{
|
||||
if (toFolderId is int tId)
|
||||
{
|
||||
return CopyFolder(folderId, tId, cancellationToken) as Folder<TTo>;
|
||||
}
|
||||
|
||||
if (toFolderId is string tsId)
|
||||
{
|
||||
return CopyFolder(folderId, tsId, cancellationToken) as Folder<TTo>;
|
||||
}
|
||||
|
||||
throw new NotImplementedException();
|
||||
}
|
||||
|
||||
public Folder<int> CopyFolder(string folderId, int toFolderId, CancellationToken? cancellationToken)
|
||||
{
|
||||
var moved = CrossDao.PerformCrossDaoFolderCopy(
|
||||
folderId, this, GoogleDriveDaoSelector.GetFileDao(folderId), GoogleDriveDaoSelector.ConvertId,
|
||||
toFolderId, FolderDao, FileDao, r => r,
|
||||
false, cancellationToken);
|
||||
|
||||
return moved;
|
||||
}
|
||||
|
||||
public Folder<string> CopyFolder(string folderId, string toFolderId, CancellationToken? cancellationToken)
|
||||
{
|
||||
var driveFolder = GetDriveEntry(folderId);
|
||||
if (driveFolder is ErrorDriveEntry) throw new Exception(((ErrorDriveEntry)driveFolder).Error);
|
||||
|
||||
var toDriveFolder = GetDriveEntry(toFolderId);
|
||||
if (toDriveFolder is ErrorDriveEntry) throw new Exception(((ErrorDriveEntry)toDriveFolder).Error);
|
||||
|
||||
var newDriveFolder = ProviderInfo.Storage.InsertEntry(null, driveFolder.Name, toDriveFolder.Id, true);
|
||||
|
||||
ProviderInfo.CacheReset(newDriveFolder);
|
||||
ProviderInfo.CacheReset(toDriveFolder.Id, true);
|
||||
ProviderInfo.CacheReset(toDriveFolder.Id);
|
||||
|
||||
return ToFolder(newDriveFolder);
|
||||
}
|
||||
|
||||
public IDictionary<string, string> CanMoveOrCopy<TTo>(string[] folderIds, TTo to)
|
||||
{
|
||||
if (to is int tId)
|
||||
{
|
||||
return CanMoveOrCopy(folderIds, tId);
|
||||
}
|
||||
|
||||
if (to is string tsId)
|
||||
{
|
||||
return CanMoveOrCopy(folderIds, tsId);
|
||||
}
|
||||
|
||||
throw new NotImplementedException();
|
||||
}
|
||||
|
||||
public IDictionary<string, string> CanMoveOrCopy(string[] folderIds, string to)
|
||||
{
|
||||
return new Dictionary<string, string>();
|
||||
}
|
||||
|
||||
public IDictionary<string, string> CanMoveOrCopy(string[] folderIds, int to)
|
||||
{
|
||||
return new Dictionary<string, string>();
|
||||
}
|
||||
|
||||
public string RenameFolder(Folder<string> folder, string newTitle)
|
||||
{
|
||||
var driveFolder = GetDriveEntry(folder.ID);
|
||||
|
||||
if (IsRoot(driveFolder))
|
||||
{
|
||||
//It's root folder
|
||||
DaoSelector.RenameProvider(ProviderInfo, newTitle);
|
||||
//rename provider customer title
|
||||
}
|
||||
else
|
||||
{
|
||||
//rename folder
|
||||
driveFolder.Name = newTitle;
|
||||
driveFolder = ProviderInfo.Storage.RenameEntry(driveFolder.Id, driveFolder.Name);
|
||||
}
|
||||
|
||||
ProviderInfo.CacheReset(driveFolder);
|
||||
var parentDriveId = GetParentDriveId(driveFolder);
|
||||
if (parentDriveId != null) ProviderInfo.CacheReset(parentDriveId, true);
|
||||
|
||||
return MakeId(driveFolder.Id);
|
||||
}
|
||||
|
||||
public int GetItemsCount(string folderId)
|
||||
{
|
||||
throw new NotImplementedException();
|
||||
}
|
||||
|
||||
public bool IsEmpty(string folderId)
|
||||
{
|
||||
var driveId = MakeDriveId(folderId);
|
||||
//note: without cache
|
||||
return ProviderInfo.Storage.GetEntries(driveId).Count == 0;
|
||||
}
|
||||
|
||||
public bool UseTrashForRemove(Folder<string> folder)
|
||||
{
|
||||
return false;
|
||||
}
|
||||
|
||||
public bool UseRecursiveOperation(string folderId, string toRootFolderId)
|
||||
{
|
||||
return true;
|
||||
}
|
||||
|
||||
public bool UseRecursiveOperation<TTo>(string folderId, TTo toRootFolderId)
|
||||
{
|
||||
return true;
|
||||
}
|
||||
|
||||
public bool UseRecursiveOperation(string folderId, int toRootFolderId)
|
||||
{
|
||||
return true;
|
||||
}
|
||||
|
||||
public bool CanCalculateSubitems(string entryId)
|
||||
{
|
||||
return false;
|
||||
}
|
||||
|
||||
public long GetMaxUploadSize(string folderId, bool chunkedUpload)
|
||||
{
|
||||
var storageMaxUploadSize = ProviderInfo.Storage.GetMaxUploadSize();
|
||||
|
||||
return chunkedUpload ? storageMaxUploadSize : Math.Min(storageMaxUploadSize, SetupInfo.AvailableFileSize);
|
||||
}
|
||||
|
||||
#region Only for TMFolderDao
|
||||
|
||||
public void ReassignFolders(string[] folderIds, Guid newOwnerId)
|
||||
{
|
||||
}
|
||||
|
||||
public IEnumerable<Folder<string>> Search(string text, bool bunch)
|
||||
{
|
||||
return null;
|
||||
}
|
||||
|
||||
public string GetFolderID(string module, string bunch, string data, bool createIfNotExists)
|
||||
{
|
||||
return null;
|
||||
}
|
||||
|
||||
public IEnumerable<string> GetFolderIDs(string module, string bunch, IEnumerable<string> data, bool createIfNotExists)
|
||||
{
|
||||
return new List<string>();
|
||||
}
|
||||
|
||||
public string GetFolderIDCommon(bool createIfNotExists)
|
||||
{
|
||||
return null;
|
||||
}
|
||||
|
||||
public string GetFolderIDUser(bool createIfNotExists, Guid? userId)
|
||||
{
|
||||
return null;
|
||||
}
|
||||
|
||||
public string GetFolderIDShare(bool createIfNotExists)
|
||||
{
|
||||
return null;
|
||||
}
|
||||
|
||||
public string GetFolderIDTrash(bool createIfNotExists, Guid? userId)
|
||||
{
|
||||
return null;
|
||||
}
|
||||
|
||||
|
||||
public string GetFolderIDPhotos(bool createIfNotExists)
|
||||
{
|
||||
return null;
|
||||
}
|
||||
|
||||
public string GetFolderIDProjects(bool createIfNotExists)
|
||||
{
|
||||
return null;
|
||||
}
|
||||
|
||||
public string GetBunchObjectID(string folderID)
|
||||
{
|
||||
return null;
|
||||
}
|
||||
|
||||
public Dictionary<string, string> GetBunchObjectIDs(List<string> folderIDs)
|
||||
{
|
||||
return null;
|
||||
}
|
||||
|
||||
#endregion
|
||||
}
|
||||
|
||||
public static class GoogleDriveFolderDaoExtention
|
||||
{
|
||||
public static DIHelper AddGoogleDriveFolderDaoService(this DIHelper services)
|
||||
{
|
||||
services.TryAddScoped<GoogleDriveFolderDao>();
|
||||
|
||||
return services;
|
||||
}
|
||||
}
|
||||
}
|
379
products/ASC.Files/Server/Core/Thirdparty/GoogleDrive/GoogleDriveProviderInfo.cs
vendored
Normal file
379
products/ASC.Files/Server/Core/Thirdparty/GoogleDrive/GoogleDriveProviderInfo.cs
vendored
Normal file
@ -0,0 +1,379 @@
|
||||
/*
|
||||
*
|
||||
* (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;
|
||||
using System.Diagnostics;
|
||||
using System.Linq;
|
||||
using System.Text.RegularExpressions;
|
||||
|
||||
using ASC.Common;
|
||||
using ASC.Common.Caching;
|
||||
using ASC.Common.Logging;
|
||||
using ASC.Core.Common.Configuration;
|
||||
using ASC.FederatedLogin;
|
||||
using ASC.FederatedLogin.Helpers;
|
||||
using ASC.FederatedLogin.LoginProviders;
|
||||
using ASC.Files.Core;
|
||||
|
||||
using Microsoft.Extensions.DependencyInjection;
|
||||
using Microsoft.Extensions.Options;
|
||||
|
||||
using DriveFile = Google.Apis.Drive.v3.Data.File;
|
||||
|
||||
namespace ASC.Files.Thirdparty.GoogleDrive
|
||||
{
|
||||
[DebuggerDisplay("{CustomerTitle}")]
|
||||
internal class GoogleDriveProviderInfo : IProviderInfo
|
||||
{
|
||||
public OAuth20Token Token { get; set; }
|
||||
private string _driveRootId;
|
||||
|
||||
internal GoogleDriveStorage Storage
|
||||
{
|
||||
get
|
||||
{
|
||||
if (Wrapper.Storage == null || !Wrapper.Storage.IsOpened)
|
||||
{
|
||||
return Wrapper.CreateStorage(Token, ID);
|
||||
}
|
||||
return Wrapper.Storage;
|
||||
}
|
||||
}
|
||||
|
||||
internal bool StorageOpened
|
||||
{
|
||||
get => Wrapper.Storage != null && Wrapper.Storage.IsOpened;
|
||||
}
|
||||
|
||||
public int ID { get; set; }
|
||||
|
||||
public Guid Owner { get; set; }
|
||||
|
||||
public string CustomerTitle { get; set; }
|
||||
|
||||
public DateTime CreateOn { get; set; }
|
||||
|
||||
public string RootFolderId
|
||||
{
|
||||
get { return "drive-" + ID; }
|
||||
}
|
||||
|
||||
public string ProviderKey { get; set; }
|
||||
|
||||
public FolderType RootFolderType { get; set; }
|
||||
|
||||
public string DriveRootId
|
||||
{
|
||||
get
|
||||
{
|
||||
if (string.IsNullOrEmpty(_driveRootId))
|
||||
{
|
||||
try
|
||||
{
|
||||
_driveRootId = Storage.GetRootFolderId();
|
||||
}
|
||||
catch (Exception ex)
|
||||
{
|
||||
Log.Error("GoogleDrive error", ex);
|
||||
return null;
|
||||
}
|
||||
}
|
||||
return _driveRootId;
|
||||
}
|
||||
}
|
||||
|
||||
public GoogleDriveStorageDisposableWrapper Wrapper { get; set; }
|
||||
public GoogleDriveProviderInfoHelper GoogleDriveProviderInfoHelper { get; }
|
||||
public ILog Log { get; }
|
||||
|
||||
public GoogleDriveProviderInfo(
|
||||
GoogleDriveStorageDisposableWrapper storageDisposableWrapper,
|
||||
GoogleDriveProviderInfoHelper googleDriveProviderInfoHelper,
|
||||
IOptionsMonitor<ILog> options)
|
||||
{
|
||||
Wrapper = storageDisposableWrapper;
|
||||
GoogleDriveProviderInfoHelper = googleDriveProviderInfoHelper;
|
||||
Log = options.Get("ASC.Files");
|
||||
}
|
||||
|
||||
public void Dispose()
|
||||
{
|
||||
if (StorageOpened)
|
||||
Storage.Close();
|
||||
}
|
||||
|
||||
public bool CheckAccess()
|
||||
{
|
||||
try
|
||||
{
|
||||
return !string.IsNullOrEmpty(DriveRootId);
|
||||
}
|
||||
catch (UnauthorizedAccessException)
|
||||
{
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
public void InvalidateStorage()
|
||||
{
|
||||
if (Wrapper != null)
|
||||
{
|
||||
Wrapper.Dispose();
|
||||
Wrapper = null;
|
||||
}
|
||||
|
||||
CacheReset();
|
||||
}
|
||||
|
||||
public void UpdateTitle(string newtitle)
|
||||
{
|
||||
CustomerTitle = newtitle;
|
||||
}
|
||||
|
||||
internal DriveFile GetDriveEntry(string driveId)
|
||||
{
|
||||
return GoogleDriveProviderInfoHelper.GetDriveEntry(Storage, ID, driveId);
|
||||
}
|
||||
|
||||
internal List<DriveFile> GetDriveEntries(string parentDriveId, bool? folder = null)
|
||||
{
|
||||
return GoogleDriveProviderInfoHelper.GetDriveEntries(Storage, ID, parentDriveId, folder);
|
||||
}
|
||||
|
||||
internal void CacheReset(DriveFile driveEntry)
|
||||
{
|
||||
GoogleDriveProviderInfoHelper.CacheReset(driveEntry, ID);
|
||||
}
|
||||
|
||||
internal void CacheReset(string driveId = null, bool? childFolder = null)
|
||||
{
|
||||
GoogleDriveProviderInfoHelper.CacheReset(DriveRootId, ID, driveId, childFolder);
|
||||
}
|
||||
|
||||
internal void CacheResetChilds(string parentDriveId, bool? childFolder = null)
|
||||
{
|
||||
GoogleDriveProviderInfoHelper.CacheResetChilds(ID, parentDriveId, childFolder);
|
||||
}
|
||||
}
|
||||
|
||||
internal class GoogleDriveStorageDisposableWrapper : IDisposable
|
||||
{
|
||||
public GoogleDriveStorage Storage { get; private set; }
|
||||
public ConsumerFactory ConsumerFactory { get; }
|
||||
public IServiceProvider ServiceProvider { get; }
|
||||
|
||||
public GoogleDriveStorageDisposableWrapper(ConsumerFactory consumerFactory, IServiceProvider serviceProvider)
|
||||
{
|
||||
ConsumerFactory = consumerFactory;
|
||||
ServiceProvider = serviceProvider;
|
||||
}
|
||||
|
||||
public GoogleDriveStorage CreateStorage(OAuth20Token token, int id)
|
||||
{
|
||||
if (Storage != null) return Storage;
|
||||
|
||||
var driveStorage = ServiceProvider.GetService<GoogleDriveStorage>();
|
||||
|
||||
CheckToken(token, id);
|
||||
|
||||
driveStorage.Open(token);
|
||||
return Storage = driveStorage;
|
||||
}
|
||||
|
||||
private void CheckToken(OAuth20Token token, int id)
|
||||
{
|
||||
if (token == null) throw new UnauthorizedAccessException("Cannot create GoogleDrive session with given token");
|
||||
if (token.IsExpired)
|
||||
{
|
||||
token = OAuth20TokenHelper.RefreshToken<GoogleLoginProvider>(ConsumerFactory, token);
|
||||
|
||||
var dbDao = ServiceProvider.GetService<CachedProviderAccountDao>();
|
||||
var authData = new AuthData(token: token.ToJson());
|
||||
dbDao.UpdateProviderInfo(id, authData);
|
||||
}
|
||||
}
|
||||
|
||||
public void Dispose()
|
||||
{
|
||||
Storage?.Close();
|
||||
}
|
||||
}
|
||||
|
||||
public class GoogleDriveProviderInfoHelper
|
||||
{
|
||||
private readonly TimeSpan CacheExpiration;
|
||||
private readonly ICache CacheEntry;
|
||||
private readonly ICache CacheChildFiles;
|
||||
private readonly ICache CacheChildFolders;
|
||||
private readonly ICacheNotify<GoogleDriveCacheItem> CacheNotify;
|
||||
|
||||
public GoogleDriveProviderInfoHelper(ICacheNotify<GoogleDriveCacheItem> cacheNotify)
|
||||
{
|
||||
CacheExpiration = TimeSpan.FromMinutes(1);
|
||||
CacheEntry = AscCache.Memory;
|
||||
CacheChildFiles = AscCache.Memory;
|
||||
CacheChildFolders = AscCache.Memory;
|
||||
|
||||
CacheNotify = cacheNotify;
|
||||
CacheNotify.Subscribe((i) =>
|
||||
{
|
||||
if (i.ResetEntry)
|
||||
{
|
||||
CacheEntry.Remove("drive-" + i.Key);
|
||||
}
|
||||
if (i.ResetAll)
|
||||
{
|
||||
CacheEntry.Remove(new Regex("^drive-" + i.Key + ".*"));
|
||||
CacheChildFiles.Remove(new Regex("^drivef-" + i.Key + ".*"));
|
||||
CacheChildFolders.Remove(new Regex("^drived-" + i.Key + ".*"));
|
||||
}
|
||||
if (i.ResetChilds)
|
||||
{
|
||||
if (!i.ChildFolder || !i.ChildFolder)
|
||||
{
|
||||
CacheChildFiles.Remove("drivef-" + i.Key);
|
||||
}
|
||||
if (!i.ChildFolderExist || i.ChildFolder)
|
||||
{
|
||||
CacheChildFolders.Remove("drived-" + i.Key);
|
||||
}
|
||||
}
|
||||
}, CacheNotifyAction.Remove);
|
||||
}
|
||||
|
||||
internal DriveFile GetDriveEntry(GoogleDriveStorage storage, int id, string driveId)
|
||||
{
|
||||
var entry = CacheEntry.Get<DriveFile>("drive-" + id + "-" + driveId);
|
||||
if (entry == null)
|
||||
{
|
||||
entry = storage.GetEntry(driveId);
|
||||
if (entry != null)
|
||||
CacheEntry.Insert("drive-" + id + "-" + driveId, entry, DateTime.UtcNow.Add(CacheExpiration));
|
||||
}
|
||||
return entry;
|
||||
}
|
||||
|
||||
internal List<DriveFile> GetDriveEntries(GoogleDriveStorage storage, int id, string parentDriveId, bool? folder = null)
|
||||
{
|
||||
if (folder.HasValue)
|
||||
{
|
||||
if (folder.Value)
|
||||
{
|
||||
var value = CacheChildFolders.Get<List<DriveFile>>("drived-" + id + "-" + parentDriveId);
|
||||
if (value == null)
|
||||
{
|
||||
value = storage.GetEntries(parentDriveId, true);
|
||||
if (value != null)
|
||||
CacheChildFolders.Insert("drived-" + id + "-" + parentDriveId, value, DateTime.UtcNow.Add(CacheExpiration));
|
||||
}
|
||||
return value;
|
||||
}
|
||||
else
|
||||
{
|
||||
var value = CacheChildFiles.Get<List<DriveFile>>("drivef-" + id + "-" + parentDriveId);
|
||||
if (value == null)
|
||||
{
|
||||
value = storage.GetEntries(parentDriveId, false);
|
||||
if (value != null)
|
||||
CacheChildFiles.Insert("drivef-" + id + "-" + parentDriveId, value, DateTime.UtcNow.Add(CacheExpiration));
|
||||
}
|
||||
return value;
|
||||
}
|
||||
}
|
||||
|
||||
if (CacheChildFiles.Get<List<DriveFile>>("drivef-" + id + "-" + parentDriveId) == null &&
|
||||
CacheChildFolders.Get<List<DriveFile>>("drived-" + id + "-" + parentDriveId) == null)
|
||||
{
|
||||
var entries = storage.GetEntries(parentDriveId);
|
||||
|
||||
CacheChildFiles.Insert("drivef-" + id + "-" + parentDriveId, entries.Where(entry => entry.MimeType != GoogleLoginProvider.GoogleDriveMimeTypeFolder).ToList(), DateTime.UtcNow.Add(CacheExpiration));
|
||||
CacheChildFolders.Insert("drived-" + id + "-" + parentDriveId, entries.Where(entry => entry.MimeType == GoogleLoginProvider.GoogleDriveMimeTypeFolder).ToList(), DateTime.UtcNow.Add(CacheExpiration));
|
||||
|
||||
return entries;
|
||||
}
|
||||
|
||||
var folders = CacheChildFolders.Get<List<DriveFile>>("drived-" + id + "-" + parentDriveId);
|
||||
if (folders == null)
|
||||
{
|
||||
folders = storage.GetEntries(parentDriveId, true);
|
||||
CacheChildFolders.Insert("drived-" + id + "-" + parentDriveId, folders, DateTime.UtcNow.Add(CacheExpiration));
|
||||
}
|
||||
var files = CacheChildFiles.Get<List<DriveFile>>("drivef-" + id + "-" + parentDriveId);
|
||||
if (files == null)
|
||||
{
|
||||
files = storage.GetEntries(parentDriveId, false);
|
||||
CacheChildFiles.Insert("drivef-" + id + "-" + parentDriveId, files, DateTime.UtcNow.Add(CacheExpiration));
|
||||
}
|
||||
return folders.Concat(files).ToList();
|
||||
}
|
||||
|
||||
internal void CacheReset(DriveFile driveEntry, int id)
|
||||
{
|
||||
if (driveEntry != null)
|
||||
{
|
||||
CacheNotify.Publish(new GoogleDriveCacheItem { ResetEntry = true, Key = id + "-" + driveEntry.Id }, CacheNotifyAction.Remove);
|
||||
}
|
||||
}
|
||||
|
||||
internal void CacheReset(string driveRootId, int id, string driveId = null, bool? childFolder = null)
|
||||
{
|
||||
var key = id + "-";
|
||||
if (driveId == null)
|
||||
{
|
||||
CacheNotify.Publish(new GoogleDriveCacheItem { ResetAll = true, Key = key }, CacheNotifyAction.Remove);
|
||||
}
|
||||
else
|
||||
{
|
||||
if (driveId == driveRootId)
|
||||
{
|
||||
driveId = "root";
|
||||
}
|
||||
key += driveId;
|
||||
|
||||
CacheNotify.Publish(new GoogleDriveCacheItem { ResetEntry = true, ResetChilds = true, Key = key, ChildFolder = childFolder ?? false, ChildFolderExist = childFolder.HasValue }, CacheNotifyAction.Remove);
|
||||
}
|
||||
}
|
||||
|
||||
internal void CacheResetChilds(int id, string parentDriveId, bool? childFolder = null)
|
||||
{
|
||||
CacheNotify.Publish(new GoogleDriveCacheItem { ResetChilds = true, Key = id + "-" + parentDriveId, ChildFolder = childFolder ?? false, ChildFolderExist = childFolder.HasValue }, CacheNotifyAction.Remove);
|
||||
}
|
||||
}
|
||||
|
||||
public static class GoogleDriveProviderInfoExtension
|
||||
{
|
||||
public static DIHelper AddGoogleDriveProviderInfoService(this DIHelper services)
|
||||
{
|
||||
services.TryAddScoped<GoogleDriveProviderInfo>();
|
||||
services.TryAddScoped<GoogleDriveStorageDisposableWrapper>();
|
||||
services.TryAddScoped<GoogleDriveStorage>();
|
||||
services.TryAddSingleton<GoogleDriveProviderInfoHelper>();
|
||||
|
||||
return services;
|
||||
}
|
||||
}
|
||||
}
|
103
products/ASC.Files/Server/Core/Thirdparty/GoogleDrive/GoogleDriveSecurityDao.cs
vendored
Normal file
103
products/ASC.Files/Server/Core/Thirdparty/GoogleDrive/GoogleDriveSecurityDao.cs
vendored
Normal file
@ -0,0 +1,103 @@
|
||||
/*
|
||||
*
|
||||
* (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;
|
||||
|
||||
using ASC.Common;
|
||||
using ASC.Common.Logging;
|
||||
using ASC.Core;
|
||||
using ASC.Core.Common.EF;
|
||||
using ASC.Core.Tenants;
|
||||
using ASC.Files.Core;
|
||||
using ASC.Files.Core.EF;
|
||||
using ASC.Files.Core.Security;
|
||||
using ASC.Web.Core.Files;
|
||||
using ASC.Web.Studio.Core;
|
||||
|
||||
using Microsoft.Extensions.Options;
|
||||
|
||||
namespace ASC.Files.Thirdparty.GoogleDrive
|
||||
{
|
||||
internal class GoogleDriveSecurityDao : GoogleDriveDaoBase, ISecurityDao<string>
|
||||
{
|
||||
public GoogleDriveSecurityDao(IServiceProvider serviceProvider, UserManager userManager, TenantManager tenantManager, TenantUtil tenantUtil, DbContextManager<FilesDbContext> dbContextManager, SetupInfo setupInfo, IOptionsMonitor<ILog> monitor, FileUtility fileUtility) : base(serviceProvider, userManager, tenantManager, tenantUtil, dbContextManager, setupInfo, monitor, fileUtility)
|
||||
{
|
||||
}
|
||||
|
||||
public void SetShare(FileShareRecord r)
|
||||
{
|
||||
}
|
||||
|
||||
public IEnumerable<FileShareRecord> GetShares(IEnumerable<Guid> subjects)
|
||||
{
|
||||
return null;
|
||||
}
|
||||
|
||||
public IEnumerable<FileShareRecord> GetShares(IEnumerable<FileEntry<string>> entry)
|
||||
{
|
||||
return null;
|
||||
}
|
||||
|
||||
public IEnumerable<FileShareRecord> GetShares(FileEntry<string> entry)
|
||||
{
|
||||
return null;
|
||||
}
|
||||
|
||||
public void RemoveSubject(Guid subject)
|
||||
{
|
||||
}
|
||||
|
||||
public IEnumerable<FileShareRecord> GetPureShareRecords(IEnumerable<FileEntry<string>> entries)
|
||||
{
|
||||
return null;
|
||||
}
|
||||
|
||||
public IEnumerable<FileShareRecord> GetPureShareRecords(FileEntry<string> entry)
|
||||
{
|
||||
return null;
|
||||
}
|
||||
|
||||
public void DeleteShareRecords(IEnumerable<FileShareRecord> records)
|
||||
{
|
||||
}
|
||||
|
||||
public bool IsShared(object entryId, FileEntryType type)
|
||||
{
|
||||
throw new NotImplementedException();
|
||||
}
|
||||
}
|
||||
|
||||
public static class GoogleDriveSecurityDaoExtention
|
||||
{
|
||||
public static DIHelper AddGoogleDriveSecurityDaoService(this DIHelper services)
|
||||
{
|
||||
services.TryAddScoped<GoogleDriveSecurityDao>();
|
||||
|
||||
return services;
|
||||
}
|
||||
}
|
||||
}
|
514
products/ASC.Files/Server/Core/Thirdparty/GoogleDrive/GoogleDriveStorage.cs
vendored
Normal file
514
products/ASC.Files/Server/Core/Thirdparty/GoogleDrive/GoogleDriveStorage.cs
vendored
Normal file
@ -0,0 +1,514 @@
|
||||
/*
|
||||
*
|
||||
* (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;
|
||||
using System.Globalization;
|
||||
using System.IO;
|
||||
using System.Linq;
|
||||
using System.Net;
|
||||
using System.Security;
|
||||
using System.Text;
|
||||
using System.Web;
|
||||
|
||||
using ASC.Common.Logging;
|
||||
using ASC.Core.Common.Configuration;
|
||||
using ASC.FederatedLogin;
|
||||
using ASC.FederatedLogin.Helpers;
|
||||
using ASC.FederatedLogin.LoginProviders;
|
||||
using ASC.Web.Core.Files;
|
||||
using ASC.Web.Files.Core;
|
||||
|
||||
using Google;
|
||||
using Google.Apis.Auth.OAuth2;
|
||||
using Google.Apis.Auth.OAuth2.Flows;
|
||||
using Google.Apis.Auth.OAuth2.Responses;
|
||||
using Google.Apis.Drive.v3;
|
||||
using Google.Apis.Services;
|
||||
|
||||
using Microsoft.Extensions.Options;
|
||||
|
||||
using Newtonsoft.Json.Linq;
|
||||
|
||||
using DriveFile = Google.Apis.Drive.v3.Data.File;
|
||||
using MimeMapping = ASC.Common.Web.MimeMapping;
|
||||
|
||||
namespace ASC.Files.Thirdparty.GoogleDrive
|
||||
{
|
||||
internal class GoogleDriveStorage
|
||||
{
|
||||
public GoogleDriveStorage(
|
||||
ConsumerFactory consumerFactory,
|
||||
FileUtility fileUtility,
|
||||
IOptionsMonitor<ILog> monitor)
|
||||
{
|
||||
ConsumerFactory = consumerFactory;
|
||||
FileUtility = fileUtility;
|
||||
Log = monitor.Get("ASC.Files");
|
||||
}
|
||||
|
||||
private OAuth20Token _token;
|
||||
|
||||
private string AccessToken
|
||||
{
|
||||
get
|
||||
{
|
||||
if (_token == null) throw new Exception("Cannot create GoogleDrive session with given token");
|
||||
if (_token.IsExpired) _token = OAuth20TokenHelper.RefreshToken<GoogleLoginProvider>(ConsumerFactory, _token);
|
||||
return _token.AccessToken;
|
||||
}
|
||||
}
|
||||
|
||||
private DriveService _driveService;
|
||||
|
||||
public bool IsOpened { get; private set; }
|
||||
public ConsumerFactory ConsumerFactory { get; }
|
||||
public FileUtility FileUtility { get; }
|
||||
public ILog Log { get; }
|
||||
|
||||
public const long MaxChunkedUploadFileSize = 2L * 1024L * 1024L * 1024L;
|
||||
|
||||
public void Open(OAuth20Token token)
|
||||
{
|
||||
if (IsOpened)
|
||||
return;
|
||||
|
||||
if (token == null) throw new UnauthorizedAccessException("Cannot create GoogleDrive session with given token");
|
||||
_token = token;
|
||||
|
||||
var tokenResponse = new TokenResponse
|
||||
{
|
||||
AccessToken = _token.AccessToken,
|
||||
RefreshToken = _token.RefreshToken,
|
||||
IssuedUtc = _token.Timestamp,
|
||||
ExpiresInSeconds = _token.ExpiresIn,
|
||||
TokenType = "Bearer"
|
||||
};
|
||||
|
||||
var apiCodeFlow = new GoogleAuthorizationCodeFlow(new GoogleAuthorizationCodeFlow.Initializer
|
||||
{
|
||||
ClientSecrets = new ClientSecrets
|
||||
{
|
||||
ClientId = _token.ClientID,
|
||||
ClientSecret = _token.ClientSecret
|
||||
},
|
||||
Scopes = new[] { DriveService.Scope.Drive }
|
||||
});
|
||||
|
||||
_driveService = new DriveService(new BaseClientService.Initializer
|
||||
{
|
||||
HttpClientInitializer = new UserCredential(apiCodeFlow, string.Empty, tokenResponse)
|
||||
});
|
||||
|
||||
IsOpened = true;
|
||||
}
|
||||
|
||||
public void Close()
|
||||
{
|
||||
_driveService.Dispose();
|
||||
|
||||
IsOpened = false;
|
||||
}
|
||||
|
||||
|
||||
public string GetRootFolderId()
|
||||
{
|
||||
var rootFolder = _driveService.Files.Get("root").Execute();
|
||||
|
||||
return rootFolder.Id;
|
||||
}
|
||||
|
||||
public DriveFile GetEntry(string entryId)
|
||||
{
|
||||
try
|
||||
{
|
||||
var request = _driveService.Files.Get(entryId);
|
||||
|
||||
request.Fields = GoogleLoginProvider.FilesFields;
|
||||
|
||||
return request.Execute();
|
||||
}
|
||||
catch (GoogleApiException ex)
|
||||
{
|
||||
if (ex.HttpStatusCode == HttpStatusCode.NotFound)
|
||||
{
|
||||
return null;
|
||||
}
|
||||
throw;
|
||||
}
|
||||
}
|
||||
|
||||
public List<DriveFile> GetEntries(string folderId, bool? folders = null)
|
||||
{
|
||||
var request = _driveService.Files.List();
|
||||
|
||||
var query = "'" + folderId + "' in parents and trashed=false";
|
||||
|
||||
if (folders.HasValue)
|
||||
{
|
||||
query += " and mimeType " + (folders.Value ? "" : "!") + "= '" + GoogleLoginProvider.GoogleDriveMimeTypeFolder + "'";
|
||||
}
|
||||
|
||||
request.Q = query;
|
||||
|
||||
request.Fields = "nextPageToken, files(" + GoogleLoginProvider.FilesFields + ")";
|
||||
|
||||
var files = new List<DriveFile>();
|
||||
do
|
||||
{
|
||||
try
|
||||
{
|
||||
var fileList = request.Execute();
|
||||
|
||||
files.AddRange(fileList.Files);
|
||||
|
||||
request.PageToken = fileList.NextPageToken;
|
||||
}
|
||||
catch (Exception)
|
||||
{
|
||||
request.PageToken = null;
|
||||
}
|
||||
} while (!string.IsNullOrEmpty(request.PageToken));
|
||||
|
||||
return files;
|
||||
}
|
||||
|
||||
public Stream DownloadStream(DriveFile file, int offset = 0)
|
||||
{
|
||||
if (file == null) throw new ArgumentNullException("file");
|
||||
|
||||
var downloadArg = string.Format("{0}?alt=media", file.Id);
|
||||
|
||||
var ext = MimeMapping.GetExtention(file.MimeType);
|
||||
if (GoogleLoginProvider.GoogleDriveExt.Contains(ext))
|
||||
{
|
||||
var internalExt = FileUtility.GetGoogleDownloadableExtension(ext);
|
||||
var requiredMimeType = MimeMapping.GetMimeMapping(internalExt);
|
||||
|
||||
downloadArg = string.Format("{0}/export?mimeType={1}",
|
||||
file.Id,
|
||||
HttpUtility.UrlEncode(requiredMimeType));
|
||||
}
|
||||
|
||||
var request = WebRequest.Create(GoogleLoginProvider.GoogleUrlFile + downloadArg);
|
||||
request.Method = "GET";
|
||||
request.Headers.Add("Authorization", "Bearer " + AccessToken);
|
||||
|
||||
var response = (HttpWebResponse)request.GetResponse();
|
||||
|
||||
if (offset == 0 && file.Size.HasValue && file.Size > 0)
|
||||
{
|
||||
return new ResponseStream(response.GetResponseStream(), file.Size.Value);
|
||||
}
|
||||
|
||||
var tempBuffer = new FileStream(Path.GetTempFileName(), FileMode.OpenOrCreate, FileAccess.ReadWrite, FileShare.Read, 8096, FileOptions.DeleteOnClose);
|
||||
using (var str = response.GetResponseStream())
|
||||
{
|
||||
if (str != null)
|
||||
{
|
||||
str.CopyTo(tempBuffer);
|
||||
tempBuffer.Flush();
|
||||
tempBuffer.Seek(offset, SeekOrigin.Begin);
|
||||
}
|
||||
}
|
||||
|
||||
return tempBuffer;
|
||||
}
|
||||
|
||||
public DriveFile InsertEntry(Stream fileStream, string title, string parentId, bool folder = false)
|
||||
{
|
||||
var mimeType = folder ? GoogleLoginProvider.GoogleDriveMimeTypeFolder : MimeMapping.GetMimeMapping(title);
|
||||
|
||||
var body = FileConstructor(title, mimeType, parentId);
|
||||
|
||||
if (folder)
|
||||
{
|
||||
var requestFolder = _driveService.Files.Create(body);
|
||||
requestFolder.Fields = GoogleLoginProvider.FilesFields;
|
||||
return requestFolder.Execute();
|
||||
}
|
||||
|
||||
var request = _driveService.Files.Create(body, fileStream, mimeType);
|
||||
request.Fields = GoogleLoginProvider.FilesFields;
|
||||
|
||||
var result = request.Upload();
|
||||
if (result.Exception != null)
|
||||
{
|
||||
if (request.ResponseBody == null) throw result.Exception;
|
||||
Log.Error("Error while trying to insert entity. GoogleDrive insert returned an error.", result.Exception);
|
||||
}
|
||||
return request.ResponseBody;
|
||||
}
|
||||
|
||||
public void DeleteEntry(string entryId)
|
||||
{
|
||||
_driveService.Files.Delete(entryId).Execute();
|
||||
}
|
||||
|
||||
public DriveFile InsertEntryIntoFolder(DriveFile entry, string folderId)
|
||||
{
|
||||
var request = _driveService.Files.Update(FileConstructor(), entry.Id);
|
||||
request.AddParents = folderId;
|
||||
request.Fields = GoogleLoginProvider.FilesFields;
|
||||
return request.Execute();
|
||||
}
|
||||
|
||||
public DriveFile RemoveEntryFromFolder(DriveFile entry, string folderId)
|
||||
{
|
||||
var request = _driveService.Files.Update(FileConstructor(), entry.Id);
|
||||
request.RemoveParents = folderId;
|
||||
request.Fields = GoogleLoginProvider.FilesFields;
|
||||
return request.Execute();
|
||||
}
|
||||
|
||||
public DriveFile CopyEntry(string toFolderId, string originEntryId)
|
||||
{
|
||||
var body = FileConstructor(folderId: toFolderId);
|
||||
try
|
||||
{
|
||||
var request = _driveService.Files.Copy(body, originEntryId);
|
||||
request.Fields = GoogleLoginProvider.FilesFields;
|
||||
return request.Execute();
|
||||
}
|
||||
catch (GoogleApiException ex)
|
||||
{
|
||||
if (ex.HttpStatusCode == HttpStatusCode.Forbidden)
|
||||
{
|
||||
throw new SecurityException(ex.Error.Message);
|
||||
}
|
||||
throw;
|
||||
}
|
||||
}
|
||||
|
||||
public DriveFile RenameEntry(string fileId, string newTitle)
|
||||
{
|
||||
var request = _driveService.Files.Update(FileConstructor(newTitle), fileId);
|
||||
request.Fields = GoogleLoginProvider.FilesFields;
|
||||
return request.Execute();
|
||||
}
|
||||
|
||||
public DriveFile SaveStream(string fileId, Stream fileStream, string fileTitle)
|
||||
{
|
||||
var mimeType = MimeMapping.GetMimeMapping(fileTitle);
|
||||
var file = FileConstructor(fileTitle, mimeType);
|
||||
|
||||
var request = _driveService.Files.Update(file, fileId, fileStream, mimeType);
|
||||
request.Fields = GoogleLoginProvider.FilesFields;
|
||||
var result = request.Upload();
|
||||
if (result.Exception != null)
|
||||
{
|
||||
if (request.ResponseBody == null) throw result.Exception;
|
||||
Log.Error("Error while trying to insert entity. GoogleDrive save returned an error.", result.Exception);
|
||||
}
|
||||
|
||||
return request.ResponseBody;
|
||||
}
|
||||
|
||||
public DriveFile FileConstructor(string title = null, string mimeType = null, string folderId = null)
|
||||
{
|
||||
var file = new DriveFile();
|
||||
|
||||
if (!string.IsNullOrEmpty(title)) file.Name = title;
|
||||
if (!string.IsNullOrEmpty(mimeType)) file.MimeType = mimeType;
|
||||
if (!string.IsNullOrEmpty(folderId)) file.Parents = new List<string> { folderId };
|
||||
|
||||
return file;
|
||||
}
|
||||
|
||||
public ResumableUploadSession CreateResumableSession(DriveFile driveFile, long contentLength)
|
||||
{
|
||||
if (driveFile == null) throw new ArgumentNullException("driveFile");
|
||||
|
||||
var fileId = string.Empty;
|
||||
var method = "POST";
|
||||
var body = string.Empty;
|
||||
var folderId = driveFile.Parents.FirstOrDefault();
|
||||
|
||||
if (driveFile.Id != null)
|
||||
{
|
||||
fileId = "/" + driveFile.Id;
|
||||
method = "PATCH";
|
||||
}
|
||||
else
|
||||
{
|
||||
var titleData = !string.IsNullOrEmpty(driveFile.Name) ? string.Format("\"name\":\"{0}\"", driveFile.Name) : "";
|
||||
var parentData = !string.IsNullOrEmpty(folderId) ? string.Format(",\"parents\":[\"{0}\"]", folderId) : "";
|
||||
|
||||
body = !string.IsNullOrEmpty(titleData + parentData) ? string.Format("{{{0}{1}}}", titleData, parentData) : "";
|
||||
}
|
||||
|
||||
var request = WebRequest.Create(GoogleLoginProvider.GoogleUrlFileUpload + fileId + "?uploadType=resumable");
|
||||
request.Method = method;
|
||||
|
||||
var bytes = Encoding.UTF8.GetBytes(body);
|
||||
request.ContentLength = bytes.Length;
|
||||
request.ContentType = "application/json; charset=UTF-8";
|
||||
request.Headers.Add("X-Upload-Content-Type", MimeMapping.GetMimeMapping(driveFile.Name));
|
||||
request.Headers.Add("X-Upload-Content-Length", contentLength.ToString(CultureInfo.InvariantCulture));
|
||||
request.Headers.Add("Authorization", "Bearer " + AccessToken);
|
||||
|
||||
request.GetRequestStream().Write(bytes, 0, bytes.Length);
|
||||
|
||||
var uploadSession = new ResumableUploadSession(driveFile.Id, folderId, contentLength);
|
||||
using (var response = request.GetResponse())
|
||||
{
|
||||
uploadSession.Location = response.Headers["Location"];
|
||||
}
|
||||
uploadSession.Status = ResumableUploadSessionStatus.Started;
|
||||
|
||||
return uploadSession;
|
||||
}
|
||||
|
||||
public void Transfer(ResumableUploadSession googleDriveSession, Stream stream, long chunkLength)
|
||||
{
|
||||
if (stream == null)
|
||||
throw new ArgumentNullException("stream");
|
||||
|
||||
if (googleDriveSession.Status != ResumableUploadSessionStatus.Started)
|
||||
throw new InvalidOperationException("Can't upload chunk for given upload session.");
|
||||
|
||||
var request = WebRequest.Create(googleDriveSession.Location);
|
||||
request.Method = "PUT";
|
||||
request.ContentLength = chunkLength;
|
||||
request.Headers.Add("Authorization", "Bearer " + AccessToken);
|
||||
request.Headers.Add("Content-Range", string.Format("bytes {0}-{1}/{2}",
|
||||
googleDriveSession.BytesTransfered,
|
||||
googleDriveSession.BytesTransfered + chunkLength - 1,
|
||||
googleDriveSession.BytesToTransfer));
|
||||
|
||||
using (var requestStream = request.GetRequestStream())
|
||||
{
|
||||
stream.CopyTo(requestStream);
|
||||
}
|
||||
|
||||
HttpWebResponse response;
|
||||
try
|
||||
{
|
||||
response = (HttpWebResponse)request.GetResponse();
|
||||
}
|
||||
catch (WebException exception)
|
||||
{
|
||||
if (exception.Status == WebExceptionStatus.ProtocolError)
|
||||
{
|
||||
if (exception.Response != null && exception.Response.Headers.AllKeys.Contains("Range"))
|
||||
{
|
||||
response = (HttpWebResponse)exception.Response;
|
||||
}
|
||||
else if (exception.Message.Equals("Invalid status code: 308", StringComparison.InvariantCulture)) //response is null (unix)
|
||||
{
|
||||
response = null;
|
||||
}
|
||||
else
|
||||
{
|
||||
throw;
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
throw;
|
||||
}
|
||||
}
|
||||
|
||||
if (response == null || response.StatusCode != HttpStatusCode.Created && response.StatusCode != HttpStatusCode.OK)
|
||||
{
|
||||
var uplSession = googleDriveSession;
|
||||
uplSession.BytesTransfered += chunkLength;
|
||||
|
||||
if (response != null)
|
||||
{
|
||||
var locationHeader = response.Headers["Location"];
|
||||
if (!string.IsNullOrEmpty(locationHeader))
|
||||
{
|
||||
uplSession.Location = locationHeader;
|
||||
}
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
googleDriveSession.Status = ResumableUploadSessionStatus.Completed;
|
||||
|
||||
using (var responseStream = response.GetResponseStream())
|
||||
{
|
||||
if (responseStream == null) return;
|
||||
string responseString;
|
||||
using (var readStream = new StreamReader(responseStream))
|
||||
{
|
||||
responseString = readStream.ReadToEnd();
|
||||
}
|
||||
var responseJson = JObject.Parse(responseString);
|
||||
|
||||
googleDriveSession.FileId = responseJson.Value<string>("id");
|
||||
}
|
||||
}
|
||||
|
||||
if (response != null)
|
||||
{
|
||||
response.Close();
|
||||
}
|
||||
}
|
||||
|
||||
public long GetMaxUploadSize()
|
||||
{
|
||||
var request = _driveService.About.Get();
|
||||
request.Fields = "maxUploadSize";
|
||||
var about = request.Execute();
|
||||
|
||||
return about.MaxUploadSize.HasValue ? about.MaxUploadSize.Value : MaxChunkedUploadFileSize;
|
||||
}
|
||||
}
|
||||
|
||||
public enum ResumableUploadSessionStatus
|
||||
{
|
||||
None,
|
||||
Started,
|
||||
Completed,
|
||||
Aborted
|
||||
}
|
||||
|
||||
[Serializable]
|
||||
internal class ResumableUploadSession
|
||||
{
|
||||
public long BytesToTransfer { get; set; }
|
||||
|
||||
public long BytesTransfered { get; set; }
|
||||
|
||||
public string FileId { get; set; }
|
||||
|
||||
public string FolderId { get; set; }
|
||||
|
||||
public ResumableUploadSessionStatus Status { get; set; }
|
||||
|
||||
public string Location { get; set; }
|
||||
|
||||
public ResumableUploadSession(string fileId, string folderId, long bytesToTransfer)
|
||||
{
|
||||
FileId = fileId;
|
||||
FolderId = folderId;
|
||||
BytesToTransfer = bytesToTransfer;
|
||||
Status = ResumableUploadSessionStatus.None;
|
||||
}
|
||||
}
|
||||
}
|
180
products/ASC.Files/Server/Core/Thirdparty/GoogleDrive/GoogleDriveTagDao.cs
vendored
Normal file
180
products/ASC.Files/Server/Core/Thirdparty/GoogleDrive/GoogleDriveTagDao.cs
vendored
Normal file
@ -0,0 +1,180 @@
|
||||
/*
|
||||
*
|
||||
* (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;
|
||||
using System.Linq;
|
||||
|
||||
using ASC.Common;
|
||||
using ASC.Common.Logging;
|
||||
using ASC.Core;
|
||||
using ASC.Core.Common.EF;
|
||||
using ASC.Core.Tenants;
|
||||
using ASC.Files.Core;
|
||||
using ASC.Files.Core.EF;
|
||||
using ASC.Files.Thirdparty.Dropbox;
|
||||
using ASC.Web.Core.Files;
|
||||
using ASC.Web.Studio.Core;
|
||||
|
||||
using Microsoft.Extensions.Options;
|
||||
|
||||
namespace ASC.Files.Thirdparty.GoogleDrive
|
||||
{
|
||||
internal class GoogleDriveTagDao : GoogleDriveDaoBase, ITagDao<string>
|
||||
{
|
||||
public GoogleDriveTagDao(IServiceProvider serviceProvider, UserManager userManager, TenantManager tenantManager, TenantUtil tenantUtil, DbContextManager<FilesDbContext> dbContextManager, SetupInfo setupInfo, IOptionsMonitor<ILog> monitor, FileUtility fileUtility) : base(serviceProvider, userManager, tenantManager, tenantUtil, dbContextManager, setupInfo, monitor, fileUtility)
|
||||
{
|
||||
}
|
||||
|
||||
#region ITagDao Members
|
||||
|
||||
public IEnumerable<Tag> GetTags(TagType tagType, IEnumerable<FileEntry<string>> fileEntries)
|
||||
{
|
||||
return null;
|
||||
}
|
||||
|
||||
public IEnumerable<Tag> GetTags(Guid owner, TagType tagType)
|
||||
{
|
||||
return null;
|
||||
}
|
||||
|
||||
public IEnumerable<Tag> GetTags(string name, TagType tagType)
|
||||
{
|
||||
return null;
|
||||
}
|
||||
|
||||
public IEnumerable<Tag> GetTags(string[] names, TagType tagType)
|
||||
{
|
||||
return null;
|
||||
}
|
||||
|
||||
public IEnumerable<Tag> GetNewTags(Guid subject, Folder<string> parentFolder, bool deepSearch)
|
||||
{
|
||||
var folderId = DaoSelector.ConvertId(parentFolder.ID);
|
||||
var fakeFolderId = parentFolder.ID.ToString();
|
||||
|
||||
var entryIDs = FilesDbContext.ThirdpartyIdMapping
|
||||
.Where(r => r.Id.StartsWith(fakeFolderId))
|
||||
.Select(r => r.HashId)
|
||||
.ToList();
|
||||
|
||||
if (!entryIDs.Any()) return new List<Tag>();
|
||||
|
||||
var q = FilesDbContext.Tag
|
||||
.Join(FilesDbContext.TagLink.DefaultIfEmpty(),
|
||||
r => new TagLink { TenantId = r.TenantId, Id = r.Id },
|
||||
r => new TagLink { TenantId = r.TenantId, Id = r.TagId },
|
||||
(tag, tagLink) => new { tag, tagLink },
|
||||
new TagLinkComparer())
|
||||
.Where(r => r.tag.TenantId == TenantID)
|
||||
.Where(r => r.tag.Flag == TagType.New)
|
||||
.Where(r => r.tagLink.TenantId == TenantID)
|
||||
.Where(r => entryIDs.Any(a => a == r.tagLink.EntryId));
|
||||
|
||||
if (subject != Guid.Empty)
|
||||
{
|
||||
q = q.Where(r => r.tag.Owner == subject);
|
||||
}
|
||||
|
||||
var tags = q
|
||||
.ToList()
|
||||
.Select(r => new Tag
|
||||
{
|
||||
TagName = r.tag.Name,
|
||||
TagType = r.tag.Flag,
|
||||
Owner = r.tag.Owner,
|
||||
EntryId = MappingID(r.tagLink.EntryId),
|
||||
EntryType = r.tagLink.EntryType,
|
||||
Count = r.tagLink.TagCount,
|
||||
Id = r.tag.Id
|
||||
});
|
||||
|
||||
if (deepSearch) return tags;
|
||||
|
||||
var folderFileIds = new[] { fakeFolderId }
|
||||
.Concat(GetChildren(folderId));
|
||||
|
||||
return tags.Where(tag => folderFileIds.Contains(tag.EntryId.ToString()));
|
||||
}
|
||||
|
||||
public IEnumerable<Tag> GetNewTags(Guid subject, IEnumerable<FileEntry<string>> fileEntries)
|
||||
{
|
||||
return null;
|
||||
}
|
||||
|
||||
public IEnumerable<Tag> GetNewTags(Guid subject, FileEntry<string> fileEntry)
|
||||
{
|
||||
return null;
|
||||
}
|
||||
|
||||
public IEnumerable<Tag> SaveTags(IEnumerable<Tag> tag)
|
||||
{
|
||||
return null;
|
||||
}
|
||||
|
||||
public IEnumerable<Tag> SaveTags(Tag tag)
|
||||
{
|
||||
return null;
|
||||
}
|
||||
|
||||
public void UpdateNewTags(IEnumerable<Tag> tag)
|
||||
{
|
||||
}
|
||||
|
||||
public void UpdateNewTags(Tag tag)
|
||||
{
|
||||
}
|
||||
|
||||
public void RemoveTags(IEnumerable<Tag> tag)
|
||||
{
|
||||
}
|
||||
|
||||
public void RemoveTags(Tag tag)
|
||||
{
|
||||
}
|
||||
|
||||
public IEnumerable<Tag> GetTags(string entryID, FileEntryType entryType, TagType tagType)
|
||||
{
|
||||
return null;
|
||||
}
|
||||
|
||||
public void MarkAsNew(Guid subject, FileEntry<string> fileEntry)
|
||||
{
|
||||
}
|
||||
|
||||
#endregion
|
||||
}
|
||||
|
||||
public static class GoogleDriveTagDaoExtention
|
||||
{
|
||||
public static DIHelper AddGoogleDriveTagDaoService(this DIHelper services)
|
||||
{
|
||||
services.TryAddScoped<GoogleDriveTagDao>();
|
||||
|
||||
return services;
|
||||
}
|
||||
}
|
||||
}
|
57
products/ASC.Files/Server/Core/Thirdparty/IDaoSelector.cs
vendored
Normal file
57
products/ASC.Files/Server/Core/Thirdparty/IDaoSelector.cs
vendored
Normal file
@ -0,0 +1,57 @@
|
||||
/*
|
||||
*
|
||||
* (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 ASC.Files.Core;
|
||||
using ASC.Files.Core.Security;
|
||||
|
||||
namespace ASC.Files.Thirdparty
|
||||
{
|
||||
internal interface IDaoSelector : IDisposable
|
||||
{
|
||||
bool IsMatch(string id);
|
||||
IFileDao<string> GetFileDao(string id);
|
||||
IFolderDao<string> GetFolderDao(string id);
|
||||
ISecurityDao<string> GetSecurityDao(string id);
|
||||
ITagDao<string> GetTagDao(string id);
|
||||
|
||||
string ConvertId(string id);
|
||||
string GetIdCode(string id);
|
||||
}
|
||||
|
||||
internal interface IDaoSelector<T> where T : class, IProviderInfo
|
||||
{
|
||||
bool IsMatch(string id);
|
||||
IFileDao<string> GetFileDao<T1>(string id) where T1 : ThirdPartyProviderDao<T>, IFileDao<string>;
|
||||
IFolderDao<string> GetFolderDao<T1>(string id) where T1 : ThirdPartyProviderDao<T>, IFolderDao<string>;
|
||||
ISecurityDao<string> GetSecurityDao<T1>(string id) where T1 : ThirdPartyProviderDao<T>, ISecurityDao<string>;
|
||||
ITagDao<string> GetTagDao<T1>(string id) where T1 : ThirdPartyProviderDao<T>, ITagDao<string>;
|
||||
|
||||
string ConvertId(string id);
|
||||
string GetIdCode(string id);
|
||||
}
|
||||
}
|
192
products/ASC.Files/Server/Core/Thirdparty/IThirdPartyProviderDao.cs
vendored
Normal file
192
products/ASC.Files/Server/Core/Thirdparty/IThirdPartyProviderDao.cs
vendored
Normal file
@ -0,0 +1,192 @@
|
||||
using System;
|
||||
using System.Linq;
|
||||
using System.Text.RegularExpressions;
|
||||
|
||||
using ASC.Common.Logging;
|
||||
using ASC.Core;
|
||||
using ASC.Core.Common.EF;
|
||||
using ASC.Core.Tenants;
|
||||
using ASC.Files.Core;
|
||||
using ASC.Files.Core.EF;
|
||||
using ASC.Files.Core.Security;
|
||||
using ASC.Files.Core.Thirdparty;
|
||||
using ASC.Security.Cryptography;
|
||||
using ASC.Web.Core.Files;
|
||||
using ASC.Web.Studio.Core;
|
||||
|
||||
using Microsoft.EntityFrameworkCore;
|
||||
using Microsoft.Extensions.DependencyInjection;
|
||||
using Microsoft.Extensions.Options;
|
||||
|
||||
namespace ASC.Files.Thirdparty
|
||||
{
|
||||
internal abstract class ThirdPartyProviderDao<T> : IDisposable where T : class, IProviderInfo
|
||||
{
|
||||
public int TenantID { get; private set; }
|
||||
public IServiceProvider ServiceProvider { get; }
|
||||
public UserManager UserManager { get; }
|
||||
public TenantUtil TenantUtil { get; }
|
||||
public FilesDbContext FilesDbContext { get; }
|
||||
public SetupInfo SetupInfo { get; }
|
||||
public ILog Log { get; }
|
||||
public FileUtility FileUtility { get; }
|
||||
|
||||
public RegexDaoSelectorBase<T> DaoSelector { get; set; }
|
||||
public T ProviderInfo { get; set; }
|
||||
public string PathPrefix { get; private set; }
|
||||
|
||||
public abstract string Id { get; }
|
||||
|
||||
public ThirdPartyProviderDao(
|
||||
IServiceProvider serviceProvider,
|
||||
UserManager userManager,
|
||||
TenantManager tenantManager,
|
||||
TenantUtil tenantUtil,
|
||||
DbContextManager<FilesDbContext> dbContextManager,
|
||||
SetupInfo setupInfo,
|
||||
IOptionsMonitor<ILog> monitor,
|
||||
FileUtility fileUtility)
|
||||
{
|
||||
ServiceProvider = serviceProvider;
|
||||
UserManager = userManager;
|
||||
TenantUtil = tenantUtil;
|
||||
FilesDbContext = dbContextManager.Get(FileConstant.DatabaseId);
|
||||
SetupInfo = setupInfo;
|
||||
Log = monitor.CurrentValue;
|
||||
FileUtility = fileUtility;
|
||||
TenantID = tenantManager.GetCurrentTenant().TenantId;
|
||||
}
|
||||
|
||||
public void Init(BaseProviderInfo<T> providerInfo, RegexDaoSelectorBase<T> selectorBase)
|
||||
{
|
||||
ProviderInfo = providerInfo.ProviderInfo;
|
||||
PathPrefix = providerInfo.PathPrefix;
|
||||
DaoSelector = selectorBase;
|
||||
}
|
||||
|
||||
protected IQueryable<TSet> Query<TSet>(DbSet<TSet> set) where TSet : class, IDbFile
|
||||
{
|
||||
return set.Where(r => r.TenantId == TenantID);
|
||||
}
|
||||
|
||||
protected string MappingID(string id, bool saveIfNotExist = false)
|
||||
{
|
||||
if (id == null) return null;
|
||||
|
||||
string result;
|
||||
if (id.StartsWith(Id))
|
||||
{
|
||||
result = Regex.Replace(BitConverter.ToString(Hasher.Hash(id.ToString(), HashAlg.MD5)), "-", "").ToLower();
|
||||
}
|
||||
else
|
||||
{
|
||||
result = FilesDbContext.ThirdpartyIdMapping
|
||||
.Where(r => r.HashId == id)
|
||||
.Select(r => r.Id)
|
||||
.FirstOrDefault();
|
||||
}
|
||||
if (saveIfNotExist)
|
||||
{
|
||||
var newMapping = new DbFilesThirdpartyIdMapping
|
||||
{
|
||||
Id = id,
|
||||
HashId = result,
|
||||
TenantId = TenantID
|
||||
};
|
||||
|
||||
FilesDbContext.ThirdpartyIdMapping.Add(newMapping);
|
||||
FilesDbContext.SaveChanges();
|
||||
}
|
||||
return result;
|
||||
}
|
||||
|
||||
protected Folder<string> GetFolder()
|
||||
{
|
||||
var folder = ServiceProvider.GetService<Folder<string>>();
|
||||
|
||||
InitFileEntry(folder);
|
||||
|
||||
folder.FolderType = FolderType.DEFAULT;
|
||||
folder.Shareable = false;
|
||||
folder.TotalFiles = 0;
|
||||
folder.TotalSubFolders = 0;
|
||||
|
||||
return folder;
|
||||
}
|
||||
|
||||
protected Folder<string> GetErrorFolder(ErrorEntry entry)
|
||||
{
|
||||
var folder = GetFolder();
|
||||
|
||||
InitFileEntryError(folder, entry);
|
||||
|
||||
folder.ParentFolderID = null;
|
||||
|
||||
return folder;
|
||||
}
|
||||
|
||||
protected File<string> GetFile()
|
||||
{
|
||||
var file = ServiceProvider.GetService<File<string>>();
|
||||
|
||||
InitFileEntry(file);
|
||||
|
||||
file.Access = FileShare.None;
|
||||
file.FileStatus = FileStatus.None;
|
||||
file.Shared = false;
|
||||
file.Version = 1;
|
||||
|
||||
return file;
|
||||
}
|
||||
|
||||
protected File<string> GetErrorFile(ErrorEntry entry)
|
||||
{
|
||||
var file = GetFile();
|
||||
InitFileEntryError(file, entry);
|
||||
return file;
|
||||
}
|
||||
|
||||
protected void InitFileEntry(FileEntry<string> fileEntry)
|
||||
{
|
||||
fileEntry.CreateBy = ProviderInfo.Owner;
|
||||
fileEntry.ModifiedBy = ProviderInfo.Owner;
|
||||
fileEntry.ProviderId = ProviderInfo.ID;
|
||||
fileEntry.ProviderKey = ProviderInfo.ProviderKey;
|
||||
fileEntry.RootFolderCreator = ProviderInfo.Owner;
|
||||
fileEntry.RootFolderType = ProviderInfo.RootFolderType;
|
||||
fileEntry.RootFolderId = MakeId();
|
||||
}
|
||||
|
||||
protected void InitFileEntryError(FileEntry<string> fileEntry, ErrorEntry entry)
|
||||
{
|
||||
fileEntry.ID = MakeId(entry.ErrorId);
|
||||
fileEntry.CreateOn = TenantUtil.DateTimeNow();
|
||||
fileEntry.ModifiedOn = TenantUtil.DateTimeNow();
|
||||
fileEntry.Error = entry.Error;
|
||||
}
|
||||
|
||||
protected abstract string MakeId(string path = null);
|
||||
|
||||
public void Dispose()
|
||||
{
|
||||
if (ProviderInfo != null)
|
||||
{
|
||||
ProviderInfo.Dispose();
|
||||
ProviderInfo = null;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
internal class ErrorEntry
|
||||
{
|
||||
public string Error { get; set; }
|
||||
|
||||
public string ErrorId { get; set; }
|
||||
|
||||
public ErrorEntry(string error, string errorId)
|
||||
{
|
||||
Error = error;
|
||||
ErrorId = errorId;
|
||||
}
|
||||
}
|
||||
}
|
277
products/ASC.Files/Server/Core/Thirdparty/OneDrive/OneDriveDaoBase.cs
vendored
Normal file
277
products/ASC.Files/Server/Core/Thirdparty/OneDrive/OneDriveDaoBase.cs
vendored
Normal file
@ -0,0 +1,277 @@
|
||||
/*
|
||||
*
|
||||
* (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;
|
||||
using System.Linq;
|
||||
using System.Text.RegularExpressions;
|
||||
|
||||
using ASC.Common.Logging;
|
||||
using ASC.Core;
|
||||
using ASC.Core.Common.EF;
|
||||
using ASC.Core.Tenants;
|
||||
using ASC.Files.Core;
|
||||
using ASC.Files.Core.EF;
|
||||
using ASC.Web.Core.Files;
|
||||
using ASC.Web.Files.Classes;
|
||||
using ASC.Web.Studio.Core;
|
||||
|
||||
using Microsoft.Extensions.DependencyInjection;
|
||||
using Microsoft.Extensions.Options;
|
||||
using Microsoft.OneDrive.Sdk;
|
||||
|
||||
namespace ASC.Files.Thirdparty.OneDrive
|
||||
{
|
||||
internal abstract class OneDriveDaoBase : ThirdPartyProviderDao<OneDriveProviderInfo>
|
||||
{
|
||||
public override string Id { get => "onedrive"; }
|
||||
|
||||
public OneDriveDaoBase(IServiceProvider serviceProvider, UserManager userManager, TenantManager tenantManager, TenantUtil tenantUtil, DbContextManager<FilesDbContext> dbContextManager, SetupInfo setupInfo, IOptionsMonitor<ILog> monitor, FileUtility fileUtility) : base(serviceProvider, userManager, tenantManager, tenantUtil, dbContextManager, setupInfo, monitor, fileUtility)
|
||||
{
|
||||
}
|
||||
|
||||
protected static string MakeOneDriveId(string entryId)
|
||||
{
|
||||
var id = entryId;
|
||||
return string.IsNullOrEmpty(id)
|
||||
? string.Empty
|
||||
: id.TrimStart('/');
|
||||
}
|
||||
|
||||
protected static string GetParentFolderId(Item onedriveItem)
|
||||
{
|
||||
return onedriveItem == null || IsRoot(onedriveItem)
|
||||
? null
|
||||
: (onedriveItem.ParentReference.Path.Equals(OneDriveStorage.RootPath, StringComparison.InvariantCultureIgnoreCase)
|
||||
? string.Empty
|
||||
: onedriveItem.ParentReference.Id);
|
||||
}
|
||||
|
||||
protected string MakeId(Item onedriveItem)
|
||||
{
|
||||
var id = string.Empty;
|
||||
if (onedriveItem != null)
|
||||
{
|
||||
id = onedriveItem.Id;
|
||||
}
|
||||
|
||||
return MakeId(id);
|
||||
}
|
||||
|
||||
protected override string MakeId(string id = null)
|
||||
{
|
||||
return string.Format("{0}{1}", PathPrefix,
|
||||
string.IsNullOrEmpty(id) || id == ""
|
||||
? "" : ("-|" + id.TrimStart('/')));
|
||||
}
|
||||
|
||||
public string MakeOneDrivePath(Item onedriveItem)
|
||||
{
|
||||
return onedriveItem == null || IsRoot(onedriveItem)
|
||||
? string.Empty
|
||||
: (OneDriveStorage.MakeOneDrivePath(
|
||||
new Regex("^" + OneDriveStorage.RootPath).Replace(onedriveItem.ParentReference.Path, ""),
|
||||
onedriveItem.Name));
|
||||
}
|
||||
|
||||
protected string MakeItemTitle(Item onedriveItem)
|
||||
{
|
||||
if (onedriveItem == null || IsRoot(onedriveItem))
|
||||
{
|
||||
return ProviderInfo.CustomerTitle;
|
||||
}
|
||||
|
||||
return Global.ReplaceInvalidCharsAndTruncate(onedriveItem.Name);
|
||||
}
|
||||
|
||||
protected Folder<string> ToFolder(Item onedriveFolder)
|
||||
{
|
||||
if (onedriveFolder == null) return null;
|
||||
if (onedriveFolder is ErrorItem)
|
||||
{
|
||||
//Return error entry
|
||||
return ToErrorFolder(onedriveFolder as ErrorItem);
|
||||
}
|
||||
|
||||
if (onedriveFolder.Folder == null) return null;
|
||||
|
||||
var isRoot = IsRoot(onedriveFolder);
|
||||
|
||||
var folder = GetFolder();
|
||||
|
||||
folder.ID = MakeId(isRoot ? string.Empty : onedriveFolder.Id);
|
||||
folder.ParentFolderID = isRoot ? null : MakeId(GetParentFolderId(onedriveFolder));
|
||||
folder.CreateOn = isRoot ? ProviderInfo.CreateOn : (onedriveFolder.CreatedDateTime.HasValue ? TenantUtil.DateTimeFromUtc(onedriveFolder.CreatedDateTime.Value.DateTime) : default);
|
||||
folder.ModifiedOn = isRoot ? ProviderInfo.CreateOn : (onedriveFolder.LastModifiedDateTime.HasValue ? TenantUtil.DateTimeFromUtc(onedriveFolder.LastModifiedDateTime.Value.DateTime) : default);
|
||||
|
||||
folder.Title = MakeItemTitle(onedriveFolder);
|
||||
|
||||
return folder;
|
||||
}
|
||||
|
||||
protected static bool IsRoot(Item onedriveFolder)
|
||||
{
|
||||
return onedriveFolder.ParentReference == null || onedriveFolder.ParentReference.Id == null;
|
||||
}
|
||||
|
||||
private File<string> ToErrorFile(ErrorItem onedriveFile)
|
||||
{
|
||||
if (onedriveFile == null) return null;
|
||||
|
||||
var file = GetErrorFile(new ErrorEntry(onedriveFile.Error, onedriveFile.ErrorId));
|
||||
|
||||
file.Title = MakeItemTitle(onedriveFile);
|
||||
|
||||
return file;
|
||||
}
|
||||
|
||||
private Folder<string> ToErrorFolder(ErrorItem onedriveFolder)
|
||||
{
|
||||
if (onedriveFolder == null) return null;
|
||||
|
||||
var folder = GetErrorFolder(new ErrorEntry(onedriveFolder.Error, onedriveFolder.ErrorId));
|
||||
|
||||
folder.Title = MakeItemTitle(onedriveFolder);
|
||||
|
||||
return folder;
|
||||
}
|
||||
|
||||
public File<string> ToFile(Item onedriveFile)
|
||||
{
|
||||
if (onedriveFile == null) return null;
|
||||
|
||||
if (onedriveFile is ErrorItem)
|
||||
{
|
||||
//Return error entry
|
||||
return ToErrorFile(onedriveFile as ErrorItem);
|
||||
}
|
||||
|
||||
if (onedriveFile.File == null) return null;
|
||||
|
||||
var file = ServiceProvider.GetService<File<string>>();
|
||||
|
||||
file.ID = MakeId(onedriveFile.Id);
|
||||
file.ContentLength = onedriveFile.Size.HasValue ? (long)onedriveFile.Size : 0;
|
||||
file.CreateOn = onedriveFile.CreatedDateTime.HasValue ? TenantUtil.DateTimeFromUtc(onedriveFile.CreatedDateTime.Value.DateTime) : default;
|
||||
file.FolderID = MakeId(GetParentFolderId(onedriveFile));
|
||||
file.ModifiedOn = onedriveFile.LastModifiedDateTime.HasValue ? TenantUtil.DateTimeFromUtc(onedriveFile.LastModifiedDateTime.Value.DateTime) : default;
|
||||
file.NativeAccessor = onedriveFile;
|
||||
file.Title = MakeItemTitle(onedriveFile);
|
||||
|
||||
return file;
|
||||
}
|
||||
|
||||
public Folder<string> GetRootFolder(string folderId)
|
||||
{
|
||||
return ToFolder(GetOneDriveItem(""));
|
||||
}
|
||||
|
||||
protected Item GetOneDriveItem(string itemId)
|
||||
{
|
||||
var onedriveId = MakeOneDriveId(itemId);
|
||||
try
|
||||
{
|
||||
return ProviderInfo.GetOneDriveItem(onedriveId);
|
||||
}
|
||||
catch (Exception ex)
|
||||
{
|
||||
return new ErrorItem(ex, onedriveId);
|
||||
}
|
||||
}
|
||||
|
||||
protected IEnumerable<string> GetChildren(string folderId)
|
||||
{
|
||||
return GetOneDriveItems(folderId).Select(entry => MakeId(entry.Id));
|
||||
}
|
||||
|
||||
protected List<Item> GetOneDriveItems(string parentId, bool? folder = null)
|
||||
{
|
||||
var onedriveFolderId = MakeOneDriveId(parentId);
|
||||
var items = ProviderInfo.GetOneDriveItems(onedriveFolderId);
|
||||
|
||||
if (folder.HasValue)
|
||||
{
|
||||
if (folder.Value)
|
||||
{
|
||||
return items.Where(i => i.Folder != null).ToList();
|
||||
}
|
||||
|
||||
return items.Where(i => i.File != null).ToList();
|
||||
}
|
||||
|
||||
return items;
|
||||
}
|
||||
|
||||
protected sealed class ErrorItem : Item
|
||||
{
|
||||
public string Error { get; set; }
|
||||
|
||||
public string ErrorId { get; private set; }
|
||||
|
||||
|
||||
public ErrorItem(Exception e, object id)
|
||||
{
|
||||
ErrorId = id.ToString();
|
||||
if (e != null)
|
||||
{
|
||||
Error = e.Message;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
protected string GetAvailableTitle(string requestTitle, string parentFolderId, Func<string, string, bool> isExist)
|
||||
{
|
||||
requestTitle = new Regex("\\.$").Replace(requestTitle, "_");
|
||||
if (!isExist(requestTitle, parentFolderId)) return requestTitle;
|
||||
|
||||
var re = new Regex(@"( \(((?<index>[0-9])+)\)(\.[^\.]*)?)$");
|
||||
var match = re.Match(requestTitle);
|
||||
|
||||
if (!match.Success)
|
||||
{
|
||||
var insertIndex = requestTitle.Length;
|
||||
if (requestTitle.LastIndexOf(".", StringComparison.InvariantCulture) != -1)
|
||||
{
|
||||
insertIndex = requestTitle.LastIndexOf(".", StringComparison.InvariantCulture);
|
||||
}
|
||||
requestTitle = requestTitle.Insert(insertIndex, " (1)");
|
||||
}
|
||||
|
||||
while (isExist(requestTitle, parentFolderId))
|
||||
{
|
||||
requestTitle = re.Replace(requestTitle, MatchEvaluator);
|
||||
}
|
||||
return requestTitle;
|
||||
}
|
||||
|
||||
private static string MatchEvaluator(Match match)
|
||||
{
|
||||
var index = Convert.ToInt32(match.Groups[2].Value);
|
||||
var staticText = match.Value.Substring(string.Format(" ({0})", index).Length);
|
||||
return string.Format(" ({0}){1}", index + 1, staticText);
|
||||
}
|
||||
}
|
||||
}
|
79
products/ASC.Files/Server/Core/Thirdparty/OneDrive/OneDriveDaoSelector.cs
vendored
Normal file
79
products/ASC.Files/Server/Core/Thirdparty/OneDrive/OneDriveDaoSelector.cs
vendored
Normal file
@ -0,0 +1,79 @@
|
||||
/*
|
||||
*
|
||||
* (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 ASC.Common;
|
||||
using ASC.Files.Core;
|
||||
using ASC.Files.Core.Security;
|
||||
|
||||
namespace ASC.Files.Thirdparty.OneDrive
|
||||
{
|
||||
internal class OneDriveDaoSelector : RegexDaoSelectorBase<OneDriveProviderInfo>, IDaoSelector
|
||||
{
|
||||
protected internal override string Name { get => "OneDrive"; }
|
||||
protected internal override string Id { get => "onedrive"; }
|
||||
|
||||
public OneDriveDaoSelector(IServiceProvider serviceProvider, IDaoFactory daoFactory)
|
||||
: base(serviceProvider, daoFactory)
|
||||
{
|
||||
}
|
||||
|
||||
public IFileDao<string> GetFileDao(string id)
|
||||
{
|
||||
return base.GetFileDao<OneDriveFileDao>(id);
|
||||
}
|
||||
|
||||
public IFolderDao<string> GetFolderDao(string id)
|
||||
{
|
||||
return base.GetFolderDao<OneDriveFolderDao>(id);
|
||||
}
|
||||
|
||||
public ITagDao<string> GetTagDao(string id)
|
||||
{
|
||||
return base.GetTagDao<OneDriveTagDao>(id);
|
||||
}
|
||||
|
||||
public ISecurityDao<string> GetSecurityDao(string id)
|
||||
{
|
||||
return base.GetSecurityDao<OneDriveSecurityDao>(id);
|
||||
}
|
||||
}
|
||||
|
||||
public static class OneDriveDaoSelectorExtention
|
||||
{
|
||||
public static DIHelper AddOneDriveSelectorService(this DIHelper services)
|
||||
{
|
||||
services.TryAddScoped<OneDriveDaoSelector>();
|
||||
|
||||
return services
|
||||
.AddOneDriveSecurityDaoService()
|
||||
.AddOneDriveTagDaoService()
|
||||
.AddOneDriveFolderDaoService()
|
||||
.AddOneDriveFileDaoService();
|
||||
}
|
||||
}
|
||||
}
|
670
products/ASC.Files/Server/Core/Thirdparty/OneDrive/OneDriveFileDao.cs
vendored
Normal file
670
products/ASC.Files/Server/Core/Thirdparty/OneDrive/OneDriveFileDao.cs
vendored
Normal file
@ -0,0 +1,670 @@
|
||||
/*
|
||||
*
|
||||
* (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;
|
||||
using System.IO;
|
||||
using System.Linq;
|
||||
|
||||
using ASC.Common;
|
||||
using ASC.Common.Logging;
|
||||
using ASC.Core;
|
||||
using ASC.Core.Common.EF;
|
||||
using ASC.Core.Tenants;
|
||||
using ASC.Files.Core;
|
||||
using ASC.Files.Core.EF;
|
||||
using ASC.Files.Core.Thirdparty;
|
||||
using ASC.Files.Resources;
|
||||
using ASC.Web.Core.Files;
|
||||
using ASC.Web.Files.Services.DocumentService;
|
||||
using ASC.Web.Studio.Core;
|
||||
|
||||
using Microsoft.Extensions.Options;
|
||||
using Microsoft.OneDrive.Sdk;
|
||||
|
||||
namespace ASC.Files.Thirdparty.OneDrive
|
||||
{
|
||||
internal class OneDriveFileDao : OneDriveDaoBase, IFileDao<string>
|
||||
{
|
||||
public CrossDao CrossDao { get; }
|
||||
public OneDriveDaoSelector OneDriveDaoSelector { get; }
|
||||
public IFileDao<int> FileDao { get; }
|
||||
|
||||
public OneDriveFileDao(
|
||||
IServiceProvider serviceProvider,
|
||||
UserManager userManager,
|
||||
TenantManager tenantManager,
|
||||
TenantUtil tenantUtil,
|
||||
DbContextManager<FilesDbContext> dbContextManager,
|
||||
SetupInfo setupInfo,
|
||||
IOptionsMonitor<ILog> monitor,
|
||||
FileUtility fileUtility,
|
||||
CrossDao crossDao,
|
||||
OneDriveDaoSelector oneDriveDaoSelector,
|
||||
IFileDao<int> fileDao)
|
||||
: base(serviceProvider, userManager, tenantManager, tenantUtil, dbContextManager, setupInfo, monitor, fileUtility)
|
||||
{
|
||||
CrossDao = crossDao;
|
||||
OneDriveDaoSelector = oneDriveDaoSelector;
|
||||
FileDao = fileDao;
|
||||
}
|
||||
|
||||
public void InvalidateCache(string fileId)
|
||||
{
|
||||
var onedriveFileId = MakeOneDriveId(fileId);
|
||||
ProviderInfo.CacheReset(onedriveFileId);
|
||||
|
||||
var onedriveFile = GetOneDriveItem(fileId);
|
||||
var parentId = GetParentFolderId(onedriveFile);
|
||||
if (parentId != null) ProviderInfo.CacheReset(parentId);
|
||||
}
|
||||
|
||||
public File<string> GetFile(string fileId)
|
||||
{
|
||||
return GetFile(fileId, 1);
|
||||
}
|
||||
|
||||
public File<string> GetFile(string fileId, int fileVersion)
|
||||
{
|
||||
return ToFile(GetOneDriveItem(fileId));
|
||||
}
|
||||
|
||||
public File<string> GetFile(string parentId, string title)
|
||||
{
|
||||
return ToFile(GetOneDriveItems(parentId, false)
|
||||
.FirstOrDefault(item => item.Name.Equals(title, StringComparison.InvariantCultureIgnoreCase) && item.File != null));
|
||||
}
|
||||
|
||||
public File<string> GetFileStable(string fileId, int fileVersion)
|
||||
{
|
||||
return ToFile(GetOneDriveItem(fileId));
|
||||
}
|
||||
|
||||
public List<File<string>> GetFileHistory(string fileId)
|
||||
{
|
||||
return new List<File<string>> { GetFile(fileId) };
|
||||
}
|
||||
|
||||
public List<File<string>> GetFiles(string[] fileIds)
|
||||
{
|
||||
if (fileIds == null || fileIds.Length == 0) return new List<File<string>>();
|
||||
return fileIds.Select(GetOneDriveItem).Select(ToFile).ToList();
|
||||
}
|
||||
|
||||
public List<File<string>> GetFilesForShare(string[] fileIds, FilterType filterType, bool subjectGroup, Guid subjectID, string searchText, bool searchInContent)
|
||||
{
|
||||
if (fileIds == null || fileIds.Length == 0 || filterType == FilterType.FoldersOnly) return new List<File<string>>();
|
||||
|
||||
var files = GetFiles(fileIds).AsEnumerable();
|
||||
|
||||
//Filter
|
||||
if (subjectID != Guid.Empty)
|
||||
{
|
||||
files = files.Where(x => subjectGroup
|
||||
? UserManager.IsUserInGroup(x.CreateBy, subjectID)
|
||||
: x.CreateBy == subjectID);
|
||||
}
|
||||
|
||||
switch (filterType)
|
||||
{
|
||||
case FilterType.FoldersOnly:
|
||||
return new List<File<string>>();
|
||||
case FilterType.DocumentsOnly:
|
||||
files = files.Where(x => FileUtility.GetFileTypeByFileName(x.Title) == FileType.Document);
|
||||
break;
|
||||
case FilterType.PresentationsOnly:
|
||||
files = files.Where(x => FileUtility.GetFileTypeByFileName(x.Title) == FileType.Presentation);
|
||||
break;
|
||||
case FilterType.SpreadsheetsOnly:
|
||||
files = files.Where(x => FileUtility.GetFileTypeByFileName(x.Title) == FileType.Spreadsheet);
|
||||
break;
|
||||
case FilterType.ImagesOnly:
|
||||
files = files.Where(x => FileUtility.GetFileTypeByFileName(x.Title) == FileType.Image);
|
||||
break;
|
||||
case FilterType.ArchiveOnly:
|
||||
files = files.Where(x => FileUtility.GetFileTypeByFileName(x.Title) == FileType.Archive);
|
||||
break;
|
||||
case FilterType.MediaOnly:
|
||||
files = files.Where(x =>
|
||||
{
|
||||
FileType fileType;
|
||||
return (fileType = FileUtility.GetFileTypeByFileName(x.Title)) == FileType.Audio || fileType == FileType.Video;
|
||||
});
|
||||
break;
|
||||
case FilterType.ByExtension:
|
||||
if (!string.IsNullOrEmpty(searchText))
|
||||
files = files.Where(x => FileUtility.GetFileExtension(x.Title).Contains(searchText));
|
||||
break;
|
||||
}
|
||||
|
||||
if (!string.IsNullOrEmpty(searchText))
|
||||
files = files.Where(x => x.Title.IndexOf(searchText, StringComparison.OrdinalIgnoreCase) != -1);
|
||||
|
||||
return files.ToList();
|
||||
}
|
||||
|
||||
public List<string> GetFiles(string parentId)
|
||||
{
|
||||
return GetOneDriveItems(parentId, false).Select(entry => MakeId(entry.Id)).ToList();
|
||||
}
|
||||
|
||||
public List<File<string>> GetFiles(string parentId, OrderBy orderBy, FilterType filterType, bool subjectGroup, Guid subjectID, string searchText, bool searchInContent, bool withSubfolders = false)
|
||||
{
|
||||
if (filterType == FilterType.FoldersOnly) return new List<File<string>>();
|
||||
|
||||
//Get only files
|
||||
var files = GetOneDriveItems(parentId, false).Select(ToFile);
|
||||
|
||||
//Filter
|
||||
if (subjectID != Guid.Empty)
|
||||
{
|
||||
files = files.Where(x => subjectGroup
|
||||
? UserManager.IsUserInGroup(x.CreateBy, subjectID)
|
||||
: x.CreateBy == subjectID);
|
||||
}
|
||||
|
||||
switch (filterType)
|
||||
{
|
||||
case FilterType.FoldersOnly:
|
||||
return new List<File<string>>();
|
||||
case FilterType.DocumentsOnly:
|
||||
files = files.Where(x => FileUtility.GetFileTypeByFileName(x.Title) == FileType.Document);
|
||||
break;
|
||||
case FilterType.PresentationsOnly:
|
||||
files = files.Where(x => FileUtility.GetFileTypeByFileName(x.Title) == FileType.Presentation);
|
||||
break;
|
||||
case FilterType.SpreadsheetsOnly:
|
||||
files = files.Where(x => FileUtility.GetFileTypeByFileName(x.Title) == FileType.Spreadsheet);
|
||||
break;
|
||||
case FilterType.ImagesOnly:
|
||||
files = files.Where(x => FileUtility.GetFileTypeByFileName(x.Title) == FileType.Image);
|
||||
break;
|
||||
case FilterType.ArchiveOnly:
|
||||
files = files.Where(x => FileUtility.GetFileTypeByFileName(x.Title) == FileType.Archive);
|
||||
break;
|
||||
case FilterType.MediaOnly:
|
||||
files = files.Where(x =>
|
||||
{
|
||||
FileType fileType;
|
||||
return (fileType = FileUtility.GetFileTypeByFileName(x.Title)) == FileType.Audio || fileType == FileType.Video;
|
||||
});
|
||||
break;
|
||||
case FilterType.ByExtension:
|
||||
if (!string.IsNullOrEmpty(searchText))
|
||||
files = files.Where(x => FileUtility.GetFileExtension(x.Title).Contains(searchText));
|
||||
break;
|
||||
}
|
||||
|
||||
if (!string.IsNullOrEmpty(searchText))
|
||||
files = files.Where(x => x.Title.IndexOf(searchText, StringComparison.OrdinalIgnoreCase) != -1);
|
||||
|
||||
if (orderBy == null) orderBy = new OrderBy(SortedByType.DateAndTime, false);
|
||||
|
||||
switch (orderBy.SortedBy)
|
||||
{
|
||||
case SortedByType.Author:
|
||||
files = orderBy.IsAsc ? files.OrderBy(x => x.CreateBy) : files.OrderByDescending(x => x.CreateBy);
|
||||
break;
|
||||
case SortedByType.AZ:
|
||||
files = orderBy.IsAsc ? files.OrderBy(x => x.Title) : files.OrderByDescending(x => x.Title);
|
||||
break;
|
||||
case SortedByType.DateAndTime:
|
||||
files = orderBy.IsAsc ? files.OrderBy(x => x.ModifiedOn) : files.OrderByDescending(x => x.ModifiedOn);
|
||||
break;
|
||||
case SortedByType.DateAndTimeCreation:
|
||||
files = orderBy.IsAsc ? files.OrderBy(x => x.CreateOn) : files.OrderByDescending(x => x.CreateOn);
|
||||
break;
|
||||
default:
|
||||
files = orderBy.IsAsc ? files.OrderBy(x => x.Title) : files.OrderByDescending(x => x.Title);
|
||||
break;
|
||||
}
|
||||
|
||||
return files.ToList();
|
||||
}
|
||||
|
||||
public Stream GetFileStream(File<string> file)
|
||||
{
|
||||
return GetFileStream(file, 0);
|
||||
}
|
||||
|
||||
public Stream GetFileStream(File<string> file, long offset)
|
||||
{
|
||||
var onedriveFileId = MakeOneDriveId(file.ID);
|
||||
ProviderInfo.CacheReset(onedriveFileId);
|
||||
|
||||
var onedriveFile = GetOneDriveItem(file.ID);
|
||||
if (onedriveFile == null) throw new ArgumentNullException("file", FilesCommonResource.ErrorMassage_FileNotFound);
|
||||
if (onedriveFile is ErrorItem) throw new Exception(((ErrorItem)onedriveFile).Error);
|
||||
|
||||
var fileStream = ProviderInfo.Storage.DownloadStream(onedriveFile, (int)offset);
|
||||
|
||||
return fileStream;
|
||||
}
|
||||
|
||||
public Uri GetPreSignedUri(File<string> file, TimeSpan expires)
|
||||
{
|
||||
throw new NotSupportedException();
|
||||
}
|
||||
|
||||
public bool IsSupportedPreSignedUri(File<string> file)
|
||||
{
|
||||
return false;
|
||||
}
|
||||
|
||||
public File<string> SaveFile(File<string> file, Stream fileStream)
|
||||
{
|
||||
if (file == null) throw new ArgumentNullException("file");
|
||||
if (fileStream == null) throw new ArgumentNullException("fileStream");
|
||||
|
||||
Item newOneDriveFile = null;
|
||||
|
||||
if (file.ID != null)
|
||||
{
|
||||
newOneDriveFile = ProviderInfo.Storage.SaveStream(MakeOneDriveId(file.ID), fileStream);
|
||||
if (!newOneDriveFile.Name.Equals(file.Title))
|
||||
{
|
||||
file.Title = GetAvailableTitle(file.Title, GetParentFolderId(newOneDriveFile), IsExist);
|
||||
newOneDriveFile = ProviderInfo.Storage.RenameItem(newOneDriveFile.Id, file.Title);
|
||||
}
|
||||
}
|
||||
else if (file.FolderID != null)
|
||||
{
|
||||
var folderId = MakeOneDriveId(file.FolderID);
|
||||
var folder = GetOneDriveItem(folderId);
|
||||
file.Title = GetAvailableTitle(file.Title, folderId, IsExist);
|
||||
newOneDriveFile = ProviderInfo.Storage.CreateFile(fileStream, file.Title, MakeOneDrivePath(folder));
|
||||
}
|
||||
|
||||
if (newOneDriveFile != null) ProviderInfo.CacheReset(newOneDriveFile.Id);
|
||||
var parentId = GetParentFolderId(newOneDriveFile);
|
||||
if (parentId != null) ProviderInfo.CacheReset(parentId);
|
||||
|
||||
return ToFile(newOneDriveFile);
|
||||
}
|
||||
|
||||
public File<string> ReplaceFileVersion(File<string> file, Stream fileStream)
|
||||
{
|
||||
return SaveFile(file, fileStream);
|
||||
}
|
||||
|
||||
public void DeleteFile(string fileId)
|
||||
{
|
||||
var onedriveFile = GetOneDriveItem(fileId);
|
||||
if (onedriveFile == null) return;
|
||||
var id = MakeId(onedriveFile.Id);
|
||||
|
||||
using (var tx = FilesDbContext.Database.BeginTransaction())
|
||||
{
|
||||
var hashIDs = Query(FilesDbContext.ThirdpartyIdMapping)
|
||||
.Where(r => r.Id.StartsWith(id))
|
||||
.Select(r => r.HashId)
|
||||
.ToList();
|
||||
|
||||
var link = Query(FilesDbContext.TagLink)
|
||||
.Where(r => hashIDs.Any(h => h == r.EntryId))
|
||||
.ToList();
|
||||
|
||||
FilesDbContext.TagLink.RemoveRange(link);
|
||||
FilesDbContext.SaveChanges();
|
||||
|
||||
var tagsToRemove = Query(FilesDbContext.Tag)
|
||||
.Where(r => !Query(FilesDbContext.TagLink).Where(a => a.TagId == r.Id).Any());
|
||||
|
||||
FilesDbContext.Tag.RemoveRange(tagsToRemove);
|
||||
|
||||
var securityToDelete = Query(FilesDbContext.Security)
|
||||
.Where(r => hashIDs.Any(h => h == r.EntryId));
|
||||
|
||||
FilesDbContext.Security.RemoveRange(securityToDelete);
|
||||
FilesDbContext.SaveChanges();
|
||||
|
||||
var mappingToDelete = Query(FilesDbContext.ThirdpartyIdMapping)
|
||||
.Where(r => hashIDs.Any(h => h == r.HashId));
|
||||
|
||||
FilesDbContext.ThirdpartyIdMapping.RemoveRange(mappingToDelete);
|
||||
FilesDbContext.SaveChanges();
|
||||
|
||||
tx.Commit();
|
||||
}
|
||||
|
||||
if (!(onedriveFile is ErrorItem))
|
||||
ProviderInfo.Storage.DeleteItem(onedriveFile);
|
||||
|
||||
ProviderInfo.CacheReset(onedriveFile.Id);
|
||||
var parentFolderId = GetParentFolderId(onedriveFile);
|
||||
if (parentFolderId != null) ProviderInfo.CacheReset(parentFolderId);
|
||||
}
|
||||
|
||||
public bool IsExist(string title, object folderId)
|
||||
{
|
||||
return GetOneDriveItems(folderId.ToString(), false)
|
||||
.Any(item => item.Name.Equals(title, StringComparison.InvariantCultureIgnoreCase));
|
||||
}
|
||||
|
||||
public TTo MoveFile<TTo>(string fileId, TTo toFolderId)
|
||||
{
|
||||
if (toFolderId is int tId)
|
||||
{
|
||||
return (TTo)Convert.ChangeType(MoveFile(fileId, tId), typeof(TTo));
|
||||
}
|
||||
|
||||
if (toFolderId is string tsId)
|
||||
{
|
||||
return (TTo)Convert.ChangeType(MoveFile(fileId, tsId), typeof(TTo));
|
||||
}
|
||||
|
||||
throw new NotImplementedException();
|
||||
}
|
||||
|
||||
public int MoveFile(string fileId, int toFolderId)
|
||||
{
|
||||
var moved = CrossDao.PerformCrossDaoFileCopy(
|
||||
fileId, this, OneDriveDaoSelector.ConvertId,
|
||||
toFolderId, FileDao, r => r,
|
||||
true);
|
||||
|
||||
return moved.ID;
|
||||
}
|
||||
|
||||
public string MoveFile(string fileId, string toFolderId)
|
||||
{
|
||||
var onedriveFile = GetOneDriveItem(fileId);
|
||||
if (onedriveFile is ErrorItem) throw new Exception(((ErrorItem)onedriveFile).Error);
|
||||
|
||||
var toOneDriveFolder = GetOneDriveItem(toFolderId);
|
||||
if (toOneDriveFolder is ErrorItem) throw new Exception(((ErrorItem)toOneDriveFolder).Error);
|
||||
|
||||
var fromFolderId = GetParentFolderId(onedriveFile);
|
||||
|
||||
var newTitle = GetAvailableTitle(onedriveFile.Name, toOneDriveFolder.Id, IsExist);
|
||||
onedriveFile = ProviderInfo.Storage.MoveItem(onedriveFile.Id, newTitle, toOneDriveFolder.Id);
|
||||
|
||||
ProviderInfo.CacheReset(onedriveFile.Id);
|
||||
ProviderInfo.CacheReset(fromFolderId);
|
||||
ProviderInfo.CacheReset(toOneDriveFolder.Id);
|
||||
|
||||
return MakeId(onedriveFile.Id);
|
||||
}
|
||||
|
||||
public File<TTo> CopyFile<TTo>(string fileId, TTo toFolderId)
|
||||
{
|
||||
if (toFolderId is int tId)
|
||||
{
|
||||
return CopyFile(fileId, tId) as File<TTo>;
|
||||
}
|
||||
|
||||
if (toFolderId is string tsId)
|
||||
{
|
||||
return CopyFile(fileId, tsId) as File<TTo>;
|
||||
}
|
||||
|
||||
throw new NotImplementedException();
|
||||
}
|
||||
|
||||
public File<int> CopyFile(string fileId, int toFolderId)
|
||||
{
|
||||
var moved = CrossDao.PerformCrossDaoFileCopy(
|
||||
fileId, this, OneDriveDaoSelector.ConvertId,
|
||||
toFolderId, FileDao, r => r,
|
||||
false);
|
||||
|
||||
return moved;
|
||||
}
|
||||
|
||||
public File<string> CopyFile(string fileId, string toFolderId)
|
||||
{
|
||||
var onedriveFile = GetOneDriveItem(fileId);
|
||||
if (onedriveFile is ErrorItem) throw new Exception(((ErrorItem)onedriveFile).Error);
|
||||
|
||||
var toOneDriveFolder = GetOneDriveItem(toFolderId);
|
||||
if (toOneDriveFolder is ErrorItem) throw new Exception(((ErrorItem)toOneDriveFolder).Error);
|
||||
|
||||
var newTitle = GetAvailableTitle(onedriveFile.Name, toOneDriveFolder.Id, IsExist);
|
||||
var newOneDriveFile = ProviderInfo.Storage.CopyItem(onedriveFile.Id, newTitle, toOneDriveFolder.Id);
|
||||
|
||||
ProviderInfo.CacheReset(newOneDriveFile.Id);
|
||||
ProviderInfo.CacheReset(toOneDriveFolder.Id);
|
||||
|
||||
return ToFile(newOneDriveFile);
|
||||
}
|
||||
|
||||
public string FileRename(File<string> file, string newTitle)
|
||||
{
|
||||
var onedriveFile = GetOneDriveItem(file.ID);
|
||||
newTitle = GetAvailableTitle(newTitle, GetParentFolderId(onedriveFile), IsExist);
|
||||
|
||||
onedriveFile = ProviderInfo.Storage.RenameItem(onedriveFile.Id, newTitle);
|
||||
|
||||
ProviderInfo.CacheReset(onedriveFile.Id);
|
||||
var parentId = GetParentFolderId(onedriveFile);
|
||||
if (parentId != null) ProviderInfo.CacheReset(parentId);
|
||||
|
||||
return MakeId(onedriveFile.Id);
|
||||
}
|
||||
|
||||
public string UpdateComment(string fileId, int fileVersion, string comment)
|
||||
{
|
||||
return string.Empty;
|
||||
}
|
||||
|
||||
public void CompleteVersion(string fileId, int fileVersion)
|
||||
{
|
||||
}
|
||||
|
||||
public void ContinueVersion(string fileId, int fileVersion)
|
||||
{
|
||||
}
|
||||
|
||||
public bool UseTrashForRemove(File<string> file)
|
||||
{
|
||||
return false;
|
||||
}
|
||||
|
||||
#region chunking
|
||||
|
||||
private File<string> RestoreIds(File<string> file)
|
||||
{
|
||||
if (file == null) return null;
|
||||
|
||||
if (file.ID != null)
|
||||
file.ID = MakeId(file.ID.ToString());
|
||||
|
||||
if (file.FolderID != null)
|
||||
file.FolderID = MakeId(file.FolderID.ToString());
|
||||
|
||||
return file;
|
||||
}
|
||||
|
||||
public ChunkedUploadSession<string> CreateUploadSession(File<string> file, long contentLength)
|
||||
{
|
||||
if (SetupInfo.ChunkUploadSize > contentLength)
|
||||
return new ChunkedUploadSession<string>(RestoreIds(file), contentLength) { UseChunks = false };
|
||||
|
||||
var uploadSession = new ChunkedUploadSession<string>(file, contentLength);
|
||||
|
||||
Item onedriveFile;
|
||||
if (file.ID != null)
|
||||
{
|
||||
onedriveFile = GetOneDriveItem(file.ID);
|
||||
}
|
||||
else
|
||||
{
|
||||
var folder = GetOneDriveItem(file.FolderID);
|
||||
onedriveFile = new Item { Name = file.Title, ParentReference = new ItemReference { Id = folder.Id } };
|
||||
}
|
||||
|
||||
var onedriveSession = ProviderInfo.Storage.CreateResumableSession(onedriveFile, contentLength);
|
||||
if (onedriveSession != null)
|
||||
{
|
||||
uploadSession.Items["OneDriveSession"] = onedriveSession;
|
||||
}
|
||||
else
|
||||
{
|
||||
uploadSession.Items["TempPath"] = Path.GetTempFileName();
|
||||
}
|
||||
|
||||
uploadSession.File = RestoreIds(uploadSession.File);
|
||||
return uploadSession;
|
||||
}
|
||||
|
||||
public void UploadChunk(ChunkedUploadSession<string> uploadSession, Stream stream, long chunkLength)
|
||||
{
|
||||
if (!uploadSession.UseChunks)
|
||||
{
|
||||
if (uploadSession.BytesTotal == 0)
|
||||
uploadSession.BytesTotal = chunkLength;
|
||||
|
||||
uploadSession.File = SaveFile(uploadSession.File, stream);
|
||||
uploadSession.BytesUploaded = chunkLength;
|
||||
return;
|
||||
}
|
||||
|
||||
if (uploadSession.Items.ContainsKey("OneDriveSession"))
|
||||
{
|
||||
var oneDriveSession = uploadSession.GetItemOrDefault<ResumableUploadSession>("OneDriveSession");
|
||||
ProviderInfo.Storage.Transfer(oneDriveSession, stream, chunkLength);
|
||||
}
|
||||
else
|
||||
{
|
||||
var tempPath = uploadSession.GetItemOrDefault<string>("TempPath");
|
||||
using (var fs = new FileStream(tempPath, FileMode.Append))
|
||||
{
|
||||
stream.CopyTo(fs);
|
||||
}
|
||||
}
|
||||
|
||||
uploadSession.BytesUploaded += chunkLength;
|
||||
|
||||
if (uploadSession.BytesUploaded == uploadSession.BytesTotal)
|
||||
{
|
||||
uploadSession.File = FinalizeUploadSession(uploadSession);
|
||||
}
|
||||
else
|
||||
{
|
||||
uploadSession.File = RestoreIds(uploadSession.File);
|
||||
}
|
||||
}
|
||||
|
||||
private File<string> FinalizeUploadSession(ChunkedUploadSession<string> uploadSession)
|
||||
{
|
||||
if (uploadSession.Items.ContainsKey("OneDriveSession"))
|
||||
{
|
||||
var oneDriveSession = uploadSession.GetItemOrDefault<ResumableUploadSession>("OneDriveSession");
|
||||
|
||||
ProviderInfo.CacheReset(oneDriveSession.FileId);
|
||||
var parentDriveId = oneDriveSession.FolderId;
|
||||
if (parentDriveId != null) ProviderInfo.CacheReset(parentDriveId);
|
||||
|
||||
return ToFile(GetOneDriveItem(oneDriveSession.FileId));
|
||||
}
|
||||
|
||||
using (var fs = new FileStream(uploadSession.GetItemOrDefault<string>("TempPath"), FileMode.Open, FileAccess.Read, FileShare.None, 4096, FileOptions.DeleteOnClose))
|
||||
{
|
||||
return SaveFile(uploadSession.File, fs);
|
||||
}
|
||||
}
|
||||
|
||||
public void AbortUploadSession(ChunkedUploadSession<string> uploadSession)
|
||||
{
|
||||
if (uploadSession.Items.ContainsKey("OneDriveSession"))
|
||||
{
|
||||
var oneDriveSession = uploadSession.GetItemOrDefault<ResumableUploadSession>("OneDriveSession");
|
||||
|
||||
if (oneDriveSession.Status != ResumableUploadSessionStatus.Completed)
|
||||
{
|
||||
ProviderInfo.Storage.CancelTransfer(oneDriveSession);
|
||||
|
||||
oneDriveSession.Status = ResumableUploadSessionStatus.Aborted;
|
||||
}
|
||||
}
|
||||
else if (uploadSession.Items.ContainsKey("TempPath"))
|
||||
{
|
||||
System.IO.File.Delete(uploadSession.GetItemOrDefault<string>("TempPath"));
|
||||
}
|
||||
}
|
||||
|
||||
#endregion
|
||||
|
||||
|
||||
#region Only in TMFileDao
|
||||
|
||||
public void ReassignFiles(string[] fileIds, Guid newOwnerId)
|
||||
{
|
||||
}
|
||||
|
||||
public List<File<string>> GetFiles(string[] parentIds, FilterType filterType, bool subjectGroup, Guid subjectID, string searchText, bool searchInContent)
|
||||
{
|
||||
return new List<File<string>>();
|
||||
}
|
||||
|
||||
public IEnumerable<File<string>> Search(string text, bool bunch)
|
||||
{
|
||||
return null;
|
||||
}
|
||||
|
||||
public bool IsExistOnStorage(File<string> file)
|
||||
{
|
||||
return true;
|
||||
}
|
||||
|
||||
public void SaveEditHistory(File<string> file, string changes, Stream differenceStream)
|
||||
{
|
||||
//Do nothing
|
||||
}
|
||||
|
||||
public List<EditHistory> GetEditHistory(DocumentServiceHelper documentServiceHelper, string fileId, int fileVersion)
|
||||
{
|
||||
return null;
|
||||
}
|
||||
|
||||
public Stream GetDifferenceStream(File<string> file)
|
||||
{
|
||||
return null;
|
||||
}
|
||||
|
||||
public bool ContainChanges(string fileId, int fileVersion)
|
||||
{
|
||||
return false;
|
||||
}
|
||||
|
||||
public string GetUniqFilePath(File<string> file, string fileTitle)
|
||||
{
|
||||
throw new NotImplementedException();
|
||||
}
|
||||
|
||||
#endregion
|
||||
}
|
||||
|
||||
public static class OneDriveFileDaoExtention
|
||||
{
|
||||
public static DIHelper AddOneDriveFileDaoService(this DIHelper services)
|
||||
{
|
||||
services.TryAddScoped<OneDriveFileDao>();
|
||||
|
||||
return services;
|
||||
}
|
||||
}
|
||||
}
|
525
products/ASC.Files/Server/Core/Thirdparty/OneDrive/OneDriveFolderDao.cs
vendored
Normal file
525
products/ASC.Files/Server/Core/Thirdparty/OneDrive/OneDriveFolderDao.cs
vendored
Normal file
@ -0,0 +1,525 @@
|
||||
/*
|
||||
*
|
||||
* (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;
|
||||
using System.Linq;
|
||||
using System.Threading;
|
||||
|
||||
using ASC.Common;
|
||||
using ASC.Common.Logging;
|
||||
using ASC.Core;
|
||||
using ASC.Core.Common.EF;
|
||||
using ASC.Core.Tenants;
|
||||
using ASC.Files.Core;
|
||||
using ASC.Files.Core.EF;
|
||||
using ASC.Files.Core.Thirdparty;
|
||||
using ASC.Web.Core.Files;
|
||||
using ASC.Web.Studio.Core;
|
||||
|
||||
using Microsoft.Extensions.Options;
|
||||
|
||||
namespace ASC.Files.Thirdparty.OneDrive
|
||||
{
|
||||
internal class OneDriveFolderDao : OneDriveDaoBase, IFolderDao<string>
|
||||
{
|
||||
public CrossDao CrossDao { get; }
|
||||
public OneDriveDaoSelector OneDriveDaoSelector { get; }
|
||||
public IFileDao<int> FileDao { get; }
|
||||
public IFolderDao<int> FolderDao { get; }
|
||||
|
||||
public OneDriveFolderDao(
|
||||
IServiceProvider serviceProvider,
|
||||
UserManager userManager,
|
||||
TenantManager tenantManager,
|
||||
TenantUtil tenantUtil,
|
||||
DbContextManager<FilesDbContext> dbContextManager,
|
||||
SetupInfo setupInfo,
|
||||
IOptionsMonitor<ILog> monitor,
|
||||
FileUtility fileUtility,
|
||||
CrossDao crossDao,
|
||||
OneDriveDaoSelector oneDriveDaoSelector,
|
||||
IFileDao<int> fileDao,
|
||||
IFolderDao<int> folderDao)
|
||||
: base(serviceProvider, userManager, tenantManager, tenantUtil, dbContextManager, setupInfo, monitor, fileUtility)
|
||||
{
|
||||
CrossDao = crossDao;
|
||||
OneDriveDaoSelector = oneDriveDaoSelector;
|
||||
FileDao = fileDao;
|
||||
FolderDao = folderDao;
|
||||
}
|
||||
|
||||
public Folder<string> GetFolder(string folderId)
|
||||
{
|
||||
return ToFolder(GetOneDriveItem(folderId));
|
||||
}
|
||||
|
||||
public Folder<string> GetFolder(string title, string parentId)
|
||||
{
|
||||
return ToFolder(GetOneDriveItems(parentId, true)
|
||||
.FirstOrDefault(item => item.Name.Equals(title, StringComparison.InvariantCultureIgnoreCase) && item.Folder != null));
|
||||
}
|
||||
|
||||
public Folder<string> GetRootFolderByFile(string fileId)
|
||||
{
|
||||
return GetRootFolder(fileId);
|
||||
}
|
||||
|
||||
public List<Folder<string>> GetFolders(string parentId)
|
||||
{
|
||||
return GetOneDriveItems(parentId, true).Select(ToFolder).ToList();
|
||||
}
|
||||
|
||||
public List<Folder<string>> GetFolders(string parentId, OrderBy orderBy, FilterType filterType, bool subjectGroup, Guid subjectID, string searchText, bool withSubfolders = false)
|
||||
{
|
||||
if (filterType == FilterType.FilesOnly || filterType == FilterType.ByExtension
|
||||
|| filterType == FilterType.DocumentsOnly || filterType == FilterType.ImagesOnly
|
||||
|| filterType == FilterType.PresentationsOnly || filterType == FilterType.SpreadsheetsOnly
|
||||
|| filterType == FilterType.ArchiveOnly || filterType == FilterType.MediaOnly)
|
||||
return new List<Folder<string>>();
|
||||
|
||||
var folders = GetFolders(parentId).AsEnumerable(); //TODO:!!!
|
||||
//Filter
|
||||
if (subjectID != Guid.Empty)
|
||||
{
|
||||
folders = folders.Where(x => subjectGroup
|
||||
? UserManager.IsUserInGroup(x.CreateBy, subjectID)
|
||||
: x.CreateBy == subjectID);
|
||||
}
|
||||
|
||||
if (!string.IsNullOrEmpty(searchText))
|
||||
folders = folders.Where(x => x.Title.IndexOf(searchText, StringComparison.OrdinalIgnoreCase) != -1);
|
||||
|
||||
if (orderBy == null) orderBy = new OrderBy(SortedByType.DateAndTime, false);
|
||||
|
||||
switch (orderBy.SortedBy)
|
||||
{
|
||||
case SortedByType.Author:
|
||||
folders = orderBy.IsAsc ? folders.OrderBy(x => x.CreateBy) : folders.OrderByDescending(x => x.CreateBy);
|
||||
break;
|
||||
case SortedByType.AZ:
|
||||
folders = orderBy.IsAsc ? folders.OrderBy(x => x.Title) : folders.OrderByDescending(x => x.Title);
|
||||
break;
|
||||
case SortedByType.DateAndTime:
|
||||
folders = orderBy.IsAsc ? folders.OrderBy(x => x.ModifiedOn) : folders.OrderByDescending(x => x.ModifiedOn);
|
||||
break;
|
||||
case SortedByType.DateAndTimeCreation:
|
||||
folders = orderBy.IsAsc ? folders.OrderBy(x => x.CreateOn) : folders.OrderByDescending(x => x.CreateOn);
|
||||
break;
|
||||
default:
|
||||
folders = orderBy.IsAsc ? folders.OrderBy(x => x.Title) : folders.OrderByDescending(x => x.Title);
|
||||
break;
|
||||
}
|
||||
|
||||
return folders.ToList();
|
||||
}
|
||||
|
||||
public List<Folder<string>> GetFolders(string[] folderIds, FilterType filterType = FilterType.None, bool subjectGroup = false, Guid? subjectID = null, string searchText = "", bool searchSubfolders = false, bool checkShare = true)
|
||||
{
|
||||
if (filterType == FilterType.FilesOnly || filterType == FilterType.ByExtension
|
||||
|| filterType == FilterType.DocumentsOnly || filterType == FilterType.ImagesOnly
|
||||
|| filterType == FilterType.PresentationsOnly || filterType == FilterType.SpreadsheetsOnly
|
||||
|| filterType == FilterType.ArchiveOnly || filterType == FilterType.MediaOnly)
|
||||
return new List<Folder<string>>();
|
||||
|
||||
var folders = folderIds.Select(GetFolder);
|
||||
|
||||
if (subjectID.HasValue && subjectID != Guid.Empty)
|
||||
{
|
||||
folders = folders.Where(x => subjectGroup
|
||||
? UserManager.IsUserInGroup(x.CreateBy, subjectID.Value)
|
||||
: x.CreateBy == subjectID);
|
||||
}
|
||||
|
||||
if (!string.IsNullOrEmpty(searchText))
|
||||
folders = folders.Where(x => x.Title.IndexOf(searchText, StringComparison.OrdinalIgnoreCase) != -1);
|
||||
|
||||
return folders.ToList();
|
||||
}
|
||||
|
||||
public List<Folder<string>> GetParentFolders(string folderId)
|
||||
{
|
||||
var path = new List<Folder<string>>();
|
||||
|
||||
while (folderId != null)
|
||||
{
|
||||
var onedriveFolder = GetOneDriveItem(folderId);
|
||||
|
||||
if (onedriveFolder is ErrorItem)
|
||||
{
|
||||
folderId = null;
|
||||
}
|
||||
else
|
||||
{
|
||||
path.Add(ToFolder(onedriveFolder));
|
||||
folderId = GetParentFolderId(onedriveFolder);
|
||||
}
|
||||
}
|
||||
|
||||
path.Reverse();
|
||||
return path;
|
||||
}
|
||||
|
||||
public string SaveFolder(Folder<string> folder)
|
||||
{
|
||||
if (folder == null) throw new ArgumentNullException("folder");
|
||||
if (folder.ID != null)
|
||||
{
|
||||
return RenameFolder(folder, folder.Title);
|
||||
}
|
||||
|
||||
if (folder.ParentFolderID != null)
|
||||
{
|
||||
var onedriveFolderId = MakeOneDriveId(folder.ParentFolderID);
|
||||
|
||||
folder.Title = GetAvailableTitle(folder.Title, onedriveFolderId, IsExist);
|
||||
|
||||
var onedriveFolder = ProviderInfo.Storage.CreateFolder(folder.Title, onedriveFolderId);
|
||||
|
||||
ProviderInfo.CacheReset(onedriveFolder.Id);
|
||||
var parentFolderId = GetParentFolderId(onedriveFolder);
|
||||
if (parentFolderId != null) ProviderInfo.CacheReset(parentFolderId);
|
||||
|
||||
return MakeId(onedriveFolder);
|
||||
}
|
||||
return null;
|
||||
}
|
||||
|
||||
public bool IsExist(string title, string folderId)
|
||||
{
|
||||
return GetOneDriveItems(folderId, true)
|
||||
.Any(item => item.Name.Equals(title, StringComparison.InvariantCultureIgnoreCase));
|
||||
}
|
||||
|
||||
public void DeleteFolder(string folderId)
|
||||
{
|
||||
var onedriveFolder = GetOneDriveItem(folderId);
|
||||
var id = MakeId(onedriveFolder);
|
||||
|
||||
using (var tx = FilesDbContext.Database.BeginTransaction())
|
||||
{
|
||||
var hashIDs = Query(FilesDbContext.ThirdpartyIdMapping)
|
||||
.Where(r => r.Id.StartsWith(id))
|
||||
.Select(r => r.HashId)
|
||||
.ToList();
|
||||
|
||||
var link = Query(FilesDbContext.TagLink)
|
||||
.Where(r => hashIDs.Any(h => h == r.EntryId))
|
||||
.ToList();
|
||||
|
||||
FilesDbContext.TagLink.RemoveRange(link);
|
||||
FilesDbContext.SaveChanges();
|
||||
|
||||
var tagsToRemove = Query(FilesDbContext.Tag)
|
||||
.Where(r => !Query(FilesDbContext.TagLink).Where(a => a.TagId == r.Id).Any());
|
||||
|
||||
FilesDbContext.Tag.RemoveRange(tagsToRemove);
|
||||
|
||||
var securityToDelete = Query(FilesDbContext.Security)
|
||||
.Where(r => hashIDs.Any(h => h == r.EntryId));
|
||||
|
||||
FilesDbContext.Security.RemoveRange(securityToDelete);
|
||||
FilesDbContext.SaveChanges();
|
||||
|
||||
var mappingToDelete = Query(FilesDbContext.ThirdpartyIdMapping)
|
||||
.Where(r => hashIDs.Any(h => h == r.HashId));
|
||||
|
||||
FilesDbContext.ThirdpartyIdMapping.RemoveRange(mappingToDelete);
|
||||
FilesDbContext.SaveChanges();
|
||||
|
||||
tx.Commit();
|
||||
}
|
||||
|
||||
if (!(onedriveFolder is ErrorItem))
|
||||
ProviderInfo.Storage.DeleteItem(onedriveFolder);
|
||||
|
||||
ProviderInfo.CacheReset(onedriveFolder.Id);
|
||||
var parentFolderId = GetParentFolderId(onedriveFolder);
|
||||
if (parentFolderId != null) ProviderInfo.CacheReset(parentFolderId);
|
||||
}
|
||||
|
||||
public TTo MoveFolder<TTo>(string folderId, TTo toFolderId, CancellationToken? cancellationToken)
|
||||
{
|
||||
if (toFolderId is int tId)
|
||||
{
|
||||
return (TTo)Convert.ChangeType(MoveFolder(folderId, tId, cancellationToken), typeof(TTo));
|
||||
}
|
||||
|
||||
if (toFolderId is string tsId)
|
||||
{
|
||||
return (TTo)Convert.ChangeType(MoveFolder(folderId, tsId, cancellationToken), typeof(TTo));
|
||||
}
|
||||
|
||||
throw new NotImplementedException();
|
||||
}
|
||||
|
||||
public int MoveFolder(string folderId, int toFolderId, CancellationToken? cancellationToken)
|
||||
{
|
||||
var moved = CrossDao.PerformCrossDaoFolderCopy(
|
||||
folderId, this, OneDriveDaoSelector.GetFileDao(folderId), OneDriveDaoSelector.ConvertId,
|
||||
toFolderId, FolderDao, FileDao, r => r,
|
||||
true, cancellationToken);
|
||||
|
||||
return moved.ID;
|
||||
}
|
||||
|
||||
public string MoveFolder(string folderId, string toFolderId, CancellationToken? cancellationToken)
|
||||
{
|
||||
var onedriveFolder = GetOneDriveItem(folderId);
|
||||
if (onedriveFolder is ErrorItem) throw new Exception(((ErrorItem)onedriveFolder).Error);
|
||||
|
||||
var toOneDriveFolder = GetOneDriveItem(toFolderId);
|
||||
if (toOneDriveFolder is ErrorItem) throw new Exception(((ErrorItem)toOneDriveFolder).Error);
|
||||
|
||||
var fromFolderId = GetParentFolderId(onedriveFolder);
|
||||
|
||||
var newTitle = GetAvailableTitle(onedriveFolder.Name, toOneDriveFolder.Id, IsExist);
|
||||
onedriveFolder = ProviderInfo.Storage.MoveItem(onedriveFolder.Id, newTitle, toOneDriveFolder.Id);
|
||||
|
||||
ProviderInfo.CacheReset(onedriveFolder.Id);
|
||||
ProviderInfo.CacheReset(fromFolderId);
|
||||
ProviderInfo.CacheReset(toOneDriveFolder.Id);
|
||||
|
||||
return MakeId(onedriveFolder.Id);
|
||||
}
|
||||
|
||||
public Folder<TTo> CopyFolder<TTo>(string folderId, TTo toFolderId, CancellationToken? cancellationToken)
|
||||
{
|
||||
if (toFolderId is int tId)
|
||||
{
|
||||
return CopyFolder(folderId, tId, cancellationToken) as Folder<TTo>;
|
||||
}
|
||||
|
||||
if (toFolderId is string tsId)
|
||||
{
|
||||
return CopyFolder(folderId, tsId, cancellationToken) as Folder<TTo>;
|
||||
}
|
||||
|
||||
throw new NotImplementedException();
|
||||
}
|
||||
|
||||
public Folder<int> CopyFolder(string folderId, int toFolderId, CancellationToken? cancellationToken)
|
||||
{
|
||||
var moved = CrossDao.PerformCrossDaoFolderCopy(
|
||||
folderId, this, OneDriveDaoSelector.GetFileDao(folderId), OneDriveDaoSelector.ConvertId,
|
||||
toFolderId, FolderDao, FileDao, r => r,
|
||||
false, cancellationToken);
|
||||
|
||||
return moved;
|
||||
}
|
||||
|
||||
public Folder<string> CopyFolder(string folderId, string toFolderId, CancellationToken? cancellationToken)
|
||||
{
|
||||
var onedriveFolder = GetOneDriveItem(folderId);
|
||||
if (onedriveFolder is ErrorItem) throw new Exception(((ErrorItem)onedriveFolder).Error);
|
||||
|
||||
var toOneDriveFolder = GetOneDriveItem(toFolderId);
|
||||
if (toOneDriveFolder is ErrorItem) throw new Exception(((ErrorItem)toOneDriveFolder).Error);
|
||||
|
||||
var newTitle = GetAvailableTitle(onedriveFolder.Name, toOneDriveFolder.Id, IsExist);
|
||||
var newOneDriveFolder = ProviderInfo.Storage.CopyItem(onedriveFolder.Id, newTitle, toOneDriveFolder.Id);
|
||||
|
||||
ProviderInfo.CacheReset(newOneDriveFolder.Id);
|
||||
ProviderInfo.CacheReset(toOneDriveFolder.Id);
|
||||
|
||||
return ToFolder(newOneDriveFolder);
|
||||
}
|
||||
|
||||
public IDictionary<string, string> CanMoveOrCopy<TTo>(string[] folderIds, TTo to)
|
||||
{
|
||||
if (to is int tId)
|
||||
{
|
||||
return CanMoveOrCopy(folderIds, tId);
|
||||
}
|
||||
|
||||
if (to is string tsId)
|
||||
{
|
||||
return CanMoveOrCopy(folderIds, tsId);
|
||||
}
|
||||
|
||||
throw new NotImplementedException();
|
||||
}
|
||||
|
||||
public IDictionary<string, string> CanMoveOrCopy(string[] folderIds, string to)
|
||||
{
|
||||
return new Dictionary<string, string>();
|
||||
}
|
||||
|
||||
public IDictionary<string, string> CanMoveOrCopy(string[] folderIds, int to)
|
||||
{
|
||||
return new Dictionary<string, string>();
|
||||
}
|
||||
|
||||
public string RenameFolder(Folder<string> folder, string newTitle)
|
||||
{
|
||||
var onedriveFolder = GetOneDriveItem(folder.ID);
|
||||
var parentFolderId = GetParentFolderId(onedriveFolder);
|
||||
|
||||
if (IsRoot(onedriveFolder))
|
||||
{
|
||||
//It's root folder
|
||||
DaoSelector.RenameProvider(ProviderInfo, newTitle);
|
||||
//rename provider customer title
|
||||
}
|
||||
else
|
||||
{
|
||||
newTitle = GetAvailableTitle(newTitle, parentFolderId, IsExist);
|
||||
|
||||
//rename folder
|
||||
onedriveFolder = ProviderInfo.Storage.RenameItem(onedriveFolder.Id, newTitle);
|
||||
}
|
||||
|
||||
ProviderInfo.CacheReset(onedriveFolder.Id);
|
||||
if (parentFolderId != null) ProviderInfo.CacheReset(parentFolderId);
|
||||
|
||||
return MakeId(onedriveFolder.Id);
|
||||
}
|
||||
|
||||
public int GetItemsCount(string folderId)
|
||||
{
|
||||
var onedriveFolder = GetOneDriveItem(folderId);
|
||||
return (onedriveFolder == null
|
||||
|| onedriveFolder.Folder == null
|
||||
|| !onedriveFolder.Folder.ChildCount.HasValue)
|
||||
? 0
|
||||
: onedriveFolder.Folder.ChildCount.Value;
|
||||
}
|
||||
|
||||
public bool IsEmpty(string folderId)
|
||||
{
|
||||
var onedriveFolder = GetOneDriveItem(folderId);
|
||||
return onedriveFolder == null
|
||||
|| onedriveFolder.Folder == null
|
||||
|| onedriveFolder.Folder.ChildCount == 0;
|
||||
}
|
||||
|
||||
public bool UseTrashForRemove(Folder<string> folder)
|
||||
{
|
||||
return false;
|
||||
}
|
||||
|
||||
public bool UseRecursiveOperation(string folderId, string toRootFolderId)
|
||||
{
|
||||
return false;
|
||||
}
|
||||
|
||||
public bool UseRecursiveOperation<TTo>(string folderId, TTo toRootFolderId)
|
||||
{
|
||||
return false;
|
||||
}
|
||||
|
||||
public bool UseRecursiveOperation(string folderId, int toRootFolderId)
|
||||
{
|
||||
return false;
|
||||
}
|
||||
|
||||
public bool CanCalculateSubitems(string entryId)
|
||||
{
|
||||
return true;
|
||||
}
|
||||
|
||||
public long GetMaxUploadSize(string folderId, bool chunkedUpload)
|
||||
{
|
||||
var storageMaxUploadSize = ProviderInfo.Storage.MaxChunkedUploadFileSize;
|
||||
|
||||
return chunkedUpload ? storageMaxUploadSize : Math.Min(storageMaxUploadSize, SetupInfo.AvailableFileSize);
|
||||
}
|
||||
|
||||
#region Only for TMFolderDao
|
||||
|
||||
public void ReassignFolders(string[] folderIds, Guid newOwnerId)
|
||||
{
|
||||
}
|
||||
|
||||
public IEnumerable<Folder<string>> Search(string text, bool bunch)
|
||||
{
|
||||
return null;
|
||||
}
|
||||
|
||||
public string GetFolderID(string module, string bunch, string data, bool createIfNotExists)
|
||||
{
|
||||
return null;
|
||||
}
|
||||
|
||||
public IEnumerable<string> GetFolderIDs(string module, string bunch, IEnumerable<string> data, bool createIfNotExists)
|
||||
{
|
||||
return new List<string>();
|
||||
}
|
||||
|
||||
public string GetFolderIDCommon(bool createIfNotExists)
|
||||
{
|
||||
return null;
|
||||
}
|
||||
|
||||
public string GetFolderIDUser(bool createIfNotExists, Guid? userId)
|
||||
{
|
||||
return null;
|
||||
}
|
||||
|
||||
public string GetFolderIDShare(bool createIfNotExists)
|
||||
{
|
||||
return null;
|
||||
}
|
||||
|
||||
public string GetFolderIDTrash(bool createIfNotExists, Guid? userId)
|
||||
{
|
||||
return null;
|
||||
}
|
||||
|
||||
|
||||
public string GetFolderIDPhotos(bool createIfNotExists)
|
||||
{
|
||||
return null;
|
||||
}
|
||||
|
||||
public string GetFolderIDProjects(bool createIfNotExists)
|
||||
{
|
||||
return null;
|
||||
}
|
||||
|
||||
public string GetBunchObjectID(string folderID)
|
||||
{
|
||||
return null;
|
||||
}
|
||||
|
||||
public Dictionary<string, string> GetBunchObjectIDs(List<string> folderIDs)
|
||||
{
|
||||
return null;
|
||||
}
|
||||
|
||||
#endregion
|
||||
}
|
||||
|
||||
public static class OneDriveFolderDaoExtention
|
||||
{
|
||||
public static DIHelper AddOneDriveFolderDaoService(this DIHelper services)
|
||||
{
|
||||
services.TryAddScoped<OneDriveFolderDao>();
|
||||
|
||||
return services;
|
||||
}
|
||||
}
|
||||
}
|
272
products/ASC.Files/Server/Core/Thirdparty/OneDrive/OneDriveProviderInfo.cs
vendored
Normal file
272
products/ASC.Files/Server/Core/Thirdparty/OneDrive/OneDriveProviderInfo.cs
vendored
Normal file
@ -0,0 +1,272 @@
|
||||
/*
|
||||
*
|
||||
* (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;
|
||||
using System.Diagnostics;
|
||||
using System.Text.RegularExpressions;
|
||||
|
||||
using ASC.Common;
|
||||
using ASC.Common.Caching;
|
||||
using ASC.Core.Common.Configuration;
|
||||
using ASC.FederatedLogin;
|
||||
using ASC.FederatedLogin.Helpers;
|
||||
using ASC.FederatedLogin.LoginProviders;
|
||||
using ASC.Files.Core;
|
||||
|
||||
using Microsoft.Extensions.DependencyInjection;
|
||||
using Microsoft.OneDrive.Sdk;
|
||||
|
||||
namespace ASC.Files.Thirdparty.OneDrive
|
||||
{
|
||||
[DebuggerDisplay("{CustomerTitle}")]
|
||||
internal class OneDriveProviderInfo : IProviderInfo
|
||||
{
|
||||
public OAuth20Token Token { get; set; }
|
||||
|
||||
internal OneDriveStorage Storage
|
||||
{
|
||||
get
|
||||
{
|
||||
if (Wrapper.Storage == null || !Wrapper.Storage.IsOpened)
|
||||
{
|
||||
return Wrapper.CreateStorage(Token, ID);
|
||||
}
|
||||
return Wrapper.Storage;
|
||||
}
|
||||
}
|
||||
|
||||
internal bool StorageOpened
|
||||
{
|
||||
get => Wrapper.Storage != null && Wrapper.Storage.IsOpened;
|
||||
}
|
||||
|
||||
public int ID { get; set; }
|
||||
|
||||
public Guid Owner { get; set; }
|
||||
|
||||
public string CustomerTitle { get; set; }
|
||||
|
||||
public DateTime CreateOn { get; set; }
|
||||
|
||||
public string RootFolderId
|
||||
{
|
||||
get { return "onedrive-" + ID; }
|
||||
}
|
||||
|
||||
public string ProviderKey { get; set; }
|
||||
|
||||
public FolderType RootFolderType { get; set; }
|
||||
public OneDriveStorageDisposableWrapper Wrapper { get; private set; }
|
||||
public OneDriveProviderInfoHelper OneDriveProviderInfoHelper { get; }
|
||||
|
||||
public OneDriveProviderInfo(
|
||||
OneDriveStorageDisposableWrapper wrapper,
|
||||
OneDriveProviderInfoHelper oneDriveProviderInfoHelper)
|
||||
{
|
||||
Wrapper = wrapper;
|
||||
OneDriveProviderInfoHelper = oneDriveProviderInfoHelper;
|
||||
}
|
||||
|
||||
public void Dispose()
|
||||
{
|
||||
if (StorageOpened)
|
||||
Storage.Close();
|
||||
}
|
||||
|
||||
public bool CheckAccess()
|
||||
{
|
||||
try
|
||||
{
|
||||
return Storage.CheckAccess();
|
||||
}
|
||||
catch (AggregateException)
|
||||
{
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
public void InvalidateStorage()
|
||||
{
|
||||
if (Wrapper != null)
|
||||
{
|
||||
Wrapper.Dispose();
|
||||
Wrapper = null;
|
||||
}
|
||||
|
||||
CacheReset();
|
||||
}
|
||||
|
||||
public void UpdateTitle(string newtitle)
|
||||
{
|
||||
CustomerTitle = newtitle;
|
||||
}
|
||||
|
||||
internal Item GetOneDriveItem(string itemId)
|
||||
{
|
||||
return OneDriveProviderInfoHelper.GetOneDriveItem(Storage, ID, itemId);
|
||||
}
|
||||
|
||||
internal List<Item> GetOneDriveItems(string onedriveFolderId)
|
||||
{
|
||||
return OneDriveProviderInfoHelper.GetOneDriveItems(Storage, ID, onedriveFolderId);
|
||||
}
|
||||
|
||||
internal void CacheReset(string onedriveId = null)
|
||||
{
|
||||
OneDriveProviderInfoHelper.CacheReset(ID, onedriveId);
|
||||
}
|
||||
}
|
||||
|
||||
internal class OneDriveStorageDisposableWrapper : IDisposable
|
||||
{
|
||||
public OneDriveStorage Storage { get; private set; }
|
||||
public ConsumerFactory ConsumerFactory { get; }
|
||||
public IServiceProvider ServiceProvider { get; }
|
||||
|
||||
public OneDriveStorageDisposableWrapper(ConsumerFactory consumerFactory, IServiceProvider serviceProvider)
|
||||
{
|
||||
ConsumerFactory = consumerFactory;
|
||||
ServiceProvider = serviceProvider;
|
||||
}
|
||||
|
||||
public OneDriveStorage CreateStorage(OAuth20Token token, int id)
|
||||
{
|
||||
if (Storage != null) return Storage;
|
||||
|
||||
var onedriveStorage = ServiceProvider.GetService<OneDriveStorage>();
|
||||
|
||||
CheckToken(token, id);
|
||||
|
||||
onedriveStorage.Open(token);
|
||||
return Storage = onedriveStorage;
|
||||
}
|
||||
|
||||
private void CheckToken(OAuth20Token token, int id)
|
||||
{
|
||||
if (token == null) throw new UnauthorizedAccessException("Cannot create GoogleDrive session with given token");
|
||||
if (token.IsExpired)
|
||||
{
|
||||
token = OAuth20TokenHelper.RefreshToken<OneDriveLoginProvider>(ConsumerFactory, token);
|
||||
|
||||
var dbDao = ServiceProvider.GetService<CachedProviderAccountDao>();
|
||||
var authData = new AuthData(token: token.ToJson());
|
||||
dbDao.UpdateProviderInfo(id, authData);
|
||||
}
|
||||
}
|
||||
|
||||
public void Dispose()
|
||||
{
|
||||
if (Storage != null && Storage.IsOpened)
|
||||
{
|
||||
Storage.Close();
|
||||
Storage = null;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
public class OneDriveProviderInfoHelper
|
||||
{
|
||||
private readonly TimeSpan CacheExpiration;
|
||||
private readonly ICache CacheItem;
|
||||
private readonly ICache CacheChildItems;
|
||||
private readonly ICacheNotify<OneDriveCacheItem> CacheNotify;
|
||||
|
||||
public OneDriveProviderInfoHelper(ICacheNotify<OneDriveCacheItem> cacheNotify)
|
||||
{
|
||||
CacheExpiration = TimeSpan.FromMinutes(1);
|
||||
CacheItem = AscCache.Memory;
|
||||
CacheChildItems = AscCache.Memory;
|
||||
|
||||
CacheNotify = cacheNotify;
|
||||
CacheNotify.Subscribe((i) =>
|
||||
{
|
||||
if (i.ResetAll)
|
||||
{
|
||||
CacheChildItems.Remove(new Regex("^onedrivei-" + i.Key + ".*"));
|
||||
CacheItem.Remove(new Regex("^onedrive-" + i.Key + ".*"));
|
||||
}
|
||||
else
|
||||
{
|
||||
CacheChildItems.Remove(new Regex("onedrivei-" + i.Key));
|
||||
CacheItem.Remove("onedrive-" + i.Key);
|
||||
}
|
||||
}, CacheNotifyAction.Remove);
|
||||
}
|
||||
|
||||
internal Item GetOneDriveItem(OneDriveStorage storage, int id, string itemId)
|
||||
{
|
||||
var file = CacheItem.Get<Item>("onedrive-" + id + "-" + itemId);
|
||||
if (file == null)
|
||||
{
|
||||
file = storage.GetItem(itemId);
|
||||
if (file != null)
|
||||
CacheItem.Insert("onedrive-" + id + "-" + itemId, file, DateTime.UtcNow.Add(CacheExpiration));
|
||||
}
|
||||
return file;
|
||||
}
|
||||
|
||||
internal List<Item> GetOneDriveItems(OneDriveStorage storage, int id, string onedriveFolderId)
|
||||
{
|
||||
var items = CacheChildItems.Get<List<Item>>("onedrivei-" + id + "-" + onedriveFolderId);
|
||||
|
||||
if (items == null)
|
||||
{
|
||||
items = storage.GetItems(onedriveFolderId);
|
||||
CacheChildItems.Insert("onedrivei-" + id + "-" + onedriveFolderId, items, DateTime.UtcNow.Add(CacheExpiration));
|
||||
}
|
||||
return items;
|
||||
}
|
||||
|
||||
internal void CacheReset(int id, string onedriveId = null)
|
||||
{
|
||||
var key = id + "-";
|
||||
if (string.IsNullOrEmpty(onedriveId))
|
||||
{
|
||||
CacheNotify.Publish(new OneDriveCacheItem { ResetAll = true, Key = key }, CacheNotifyAction.Remove);
|
||||
}
|
||||
else
|
||||
{
|
||||
key += onedriveId;
|
||||
|
||||
CacheNotify.Publish(new OneDriveCacheItem { Key = key }, CacheNotifyAction.Remove);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
public static class OneDriveProviderInfoExtension
|
||||
{
|
||||
public static DIHelper AddOneDriveProviderInfoService(this DIHelper services)
|
||||
{
|
||||
services.TryAddScoped<OneDriveProviderInfo>();
|
||||
services.TryAddScoped<OneDriveStorageDisposableWrapper>();
|
||||
services.TryAddScoped<OneDriveStorage>();
|
||||
services.TryAddSingleton<OneDriveProviderInfoHelper>();
|
||||
|
||||
return services;
|
||||
}
|
||||
}
|
||||
}
|
103
products/ASC.Files/Server/Core/Thirdparty/OneDrive/OneDriveSecurityDao.cs
vendored
Normal file
103
products/ASC.Files/Server/Core/Thirdparty/OneDrive/OneDriveSecurityDao.cs
vendored
Normal file
@ -0,0 +1,103 @@
|
||||
/*
|
||||
*
|
||||
* (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;
|
||||
|
||||
using ASC.Common;
|
||||
using ASC.Common.Logging;
|
||||
using ASC.Core;
|
||||
using ASC.Core.Common.EF;
|
||||
using ASC.Core.Tenants;
|
||||
using ASC.Files.Core;
|
||||
using ASC.Files.Core.EF;
|
||||
using ASC.Files.Core.Security;
|
||||
using ASC.Web.Core.Files;
|
||||
using ASC.Web.Studio.Core;
|
||||
|
||||
using Microsoft.Extensions.Options;
|
||||
|
||||
namespace ASC.Files.Thirdparty.OneDrive
|
||||
{
|
||||
internal class OneDriveSecurityDao : OneDriveDaoBase, ISecurityDao<string>
|
||||
{
|
||||
public OneDriveSecurityDao(IServiceProvider serviceProvider, UserManager userManager, TenantManager tenantManager, TenantUtil tenantUtil, DbContextManager<FilesDbContext> dbContextManager, SetupInfo setupInfo, IOptionsMonitor<ILog> monitor, FileUtility fileUtility) : base(serviceProvider, userManager, tenantManager, tenantUtil, dbContextManager, setupInfo, monitor, fileUtility)
|
||||
{
|
||||
}
|
||||
|
||||
public void SetShare(FileShareRecord r)
|
||||
{
|
||||
}
|
||||
|
||||
public IEnumerable<FileShareRecord> GetShares(IEnumerable<Guid> subjects)
|
||||
{
|
||||
return null;
|
||||
}
|
||||
|
||||
public IEnumerable<FileShareRecord> GetShares(IEnumerable<FileEntry<string>> entry)
|
||||
{
|
||||
return null;
|
||||
}
|
||||
|
||||
public IEnumerable<FileShareRecord> GetShares(FileEntry<string> entry)
|
||||
{
|
||||
return null;
|
||||
}
|
||||
|
||||
public void RemoveSubject(Guid subject)
|
||||
{
|
||||
}
|
||||
|
||||
public IEnumerable<FileShareRecord> GetPureShareRecords(IEnumerable<FileEntry<string>> entries)
|
||||
{
|
||||
return null;
|
||||
}
|
||||
|
||||
public IEnumerable<FileShareRecord> GetPureShareRecords(FileEntry<string> entry)
|
||||
{
|
||||
return null;
|
||||
}
|
||||
|
||||
public void DeleteShareRecords(IEnumerable<FileShareRecord> records)
|
||||
{
|
||||
}
|
||||
|
||||
public bool IsShared(object entryId, FileEntryType type)
|
||||
{
|
||||
throw new NotImplementedException();
|
||||
}
|
||||
}
|
||||
|
||||
public static class OneDriveSecurityDaoExtention
|
||||
{
|
||||
public static DIHelper AddOneDriveSecurityDaoService(this DIHelper services)
|
||||
{
|
||||
services.TryAddScoped<OneDriveSecurityDao>();
|
||||
|
||||
return services;
|
||||
}
|
||||
}
|
||||
}
|
392
products/ASC.Files/Server/Core/Thirdparty/OneDrive/OneDriveStorage.cs
vendored
Normal file
392
products/ASC.Files/Server/Core/Thirdparty/OneDrive/OneDriveStorage.cs
vendored
Normal file
@ -0,0 +1,392 @@
|
||||
/*
|
||||
*
|
||||
* (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;
|
||||
using System.IO;
|
||||
using System.Net;
|
||||
using System.Net.Http;
|
||||
using System.Net.Http.Headers;
|
||||
using System.Threading;
|
||||
using System.Threading.Tasks;
|
||||
|
||||
using ASC.Core.Common.Configuration;
|
||||
using ASC.FederatedLogin;
|
||||
using ASC.FederatedLogin.Helpers;
|
||||
using ASC.FederatedLogin.LoginProviders;
|
||||
|
||||
using Microsoft.Graph;
|
||||
using Microsoft.OneDrive.Sdk;
|
||||
|
||||
using Newtonsoft.Json.Linq;
|
||||
|
||||
namespace ASC.Files.Thirdparty.OneDrive
|
||||
{
|
||||
internal class OneDriveStorage
|
||||
{
|
||||
public OneDriveStorage(ConsumerFactory consumerFactory)
|
||||
{
|
||||
ConsumerFactory = consumerFactory;
|
||||
}
|
||||
|
||||
private OAuth20Token _token;
|
||||
|
||||
private string AccessToken
|
||||
{
|
||||
get
|
||||
{
|
||||
if (_token == null) throw new Exception("Cannot create OneDrive session with given token");
|
||||
if (_token.IsExpired)
|
||||
{
|
||||
_token = OAuth20TokenHelper.RefreshToken<OneDriveLoginProvider>(ConsumerFactory, _token);
|
||||
_onedriveClientCache = null;
|
||||
}
|
||||
return _token.AccessToken;
|
||||
}
|
||||
}
|
||||
|
||||
private OneDriveClient _onedriveClientCache;
|
||||
|
||||
private OneDriveClient OnedriveClient
|
||||
{
|
||||
get { return _onedriveClientCache ?? (_onedriveClientCache = new OneDriveClient(new OneDriveAuthProvider(AccessToken))); }
|
||||
}
|
||||
|
||||
public bool IsOpened { get; private set; }
|
||||
public ConsumerFactory ConsumerFactory { get; }
|
||||
|
||||
public long MaxChunkedUploadFileSize = 10L * 1024L * 1024L * 1024L;
|
||||
|
||||
public void Open(OAuth20Token token)
|
||||
{
|
||||
if (IsOpened)
|
||||
return;
|
||||
|
||||
_token = token;
|
||||
|
||||
IsOpened = true;
|
||||
}
|
||||
|
||||
public void Close()
|
||||
{
|
||||
IsOpened = false;
|
||||
}
|
||||
|
||||
public bool CheckAccess()
|
||||
{
|
||||
return OnedriveClient
|
||||
.Drive
|
||||
.Request()
|
||||
.GetAsync()
|
||||
.Result != null;
|
||||
}
|
||||
|
||||
|
||||
public static string RootPath = "/drive/root:";
|
||||
public static string ApiVersion = "v1.0";
|
||||
|
||||
public static string MakeOneDrivePath(string parentPath, string name)
|
||||
{
|
||||
return (parentPath ?? "") + "/" + (name ?? "");
|
||||
}
|
||||
|
||||
public Item GetItem(string itemId)
|
||||
{
|
||||
try
|
||||
{
|
||||
return GetItemRequest(itemId).Request().GetAsync().Result;
|
||||
}
|
||||
catch (Exception ex)
|
||||
{
|
||||
var serviceException = (ServiceException)ex.InnerException;
|
||||
if (serviceException != null && serviceException.StatusCode == HttpStatusCode.NotFound)
|
||||
{
|
||||
return null;
|
||||
}
|
||||
throw;
|
||||
}
|
||||
}
|
||||
|
||||
public List<Item> GetItems(string folderId, int limit = 500)
|
||||
{
|
||||
return new List<Item>(GetItemRequest(folderId).Children.Request().GetAsync().Result);
|
||||
}
|
||||
|
||||
public Stream DownloadStream(Item file, int offset = 0)
|
||||
{
|
||||
if (file == null || file.File == null) throw new ArgumentNullException("file");
|
||||
|
||||
var fileStream = OnedriveClient
|
||||
.Drive
|
||||
.Items[file.Id]
|
||||
.Content
|
||||
.Request()
|
||||
.GetAsync()
|
||||
.Result;
|
||||
|
||||
if (fileStream != null && offset > 0)
|
||||
fileStream.Seek(offset, SeekOrigin.Begin);
|
||||
|
||||
return fileStream;
|
||||
}
|
||||
|
||||
public Item CreateFolder(string title, string parentId)
|
||||
{
|
||||
var newFolderItem = new Item
|
||||
{
|
||||
Folder = new Folder(),
|
||||
Name = title
|
||||
};
|
||||
|
||||
return GetItemRequest(parentId)
|
||||
.Children
|
||||
.Request()
|
||||
.AddAsync(newFolderItem)
|
||||
.Result;
|
||||
}
|
||||
|
||||
public Item CreateFile(Stream fileStream, string title, string parentPath)
|
||||
{
|
||||
return OnedriveClient
|
||||
.Drive
|
||||
.Root
|
||||
.ItemWithPath(MakeOneDrivePath(parentPath, title))
|
||||
.Content
|
||||
.Request()
|
||||
.PutAsync<Item>(fileStream)
|
||||
.Result;
|
||||
}
|
||||
|
||||
public void DeleteItem(Item item)
|
||||
{
|
||||
OnedriveClient
|
||||
.Drive
|
||||
.Items[item.Id]
|
||||
.Request()
|
||||
.DeleteAsync();
|
||||
}
|
||||
|
||||
public Item MoveItem(string itemId, string newItemName, string toFolderId)
|
||||
{
|
||||
var updateItem = new Item { ParentReference = new ItemReference { Id = toFolderId }, Name = newItemName };
|
||||
|
||||
return OnedriveClient
|
||||
.Drive
|
||||
.Items[itemId]
|
||||
.Request()
|
||||
.UpdateAsync(updateItem)
|
||||
.Result;
|
||||
}
|
||||
|
||||
public Item CopyItem(string itemId, string newItemName, string toFolderId)
|
||||
{
|
||||
var copyMonitor = OnedriveClient
|
||||
.Drive
|
||||
.Items[itemId]
|
||||
.Copy(newItemName, new ItemReference { Id = toFolderId })
|
||||
.Request()
|
||||
.PostAsync()
|
||||
.Result;
|
||||
|
||||
return copyMonitor.PollForOperationCompletionAsync(null, CancellationToken.None).Result;
|
||||
}
|
||||
|
||||
public Item RenameItem(string itemId, string newName)
|
||||
{
|
||||
var updateItem = new Item { Name = newName };
|
||||
return OnedriveClient
|
||||
.Drive
|
||||
.Items[itemId]
|
||||
.Request()
|
||||
.UpdateAsync(updateItem)
|
||||
.Result;
|
||||
}
|
||||
|
||||
public Item SaveStream(string fileId, Stream fileStream)
|
||||
{
|
||||
return OnedriveClient
|
||||
.Drive
|
||||
.Items[fileId]
|
||||
.Content
|
||||
.Request()
|
||||
.PutAsync<Item>(fileStream)
|
||||
.Result;
|
||||
}
|
||||
|
||||
private IItemRequestBuilder GetItemRequest(string itemId)
|
||||
{
|
||||
return string.IsNullOrEmpty(itemId)
|
||||
? OnedriveClient.Drive.Root
|
||||
: OnedriveClient.Drive.Items[itemId];
|
||||
}
|
||||
|
||||
|
||||
public ResumableUploadSession CreateResumableSession(Item onedriveFile, long contentLength)
|
||||
{
|
||||
if (onedriveFile == null) throw new ArgumentNullException("onedriveFile");
|
||||
|
||||
var folderId = onedriveFile.ParentReference.Id;
|
||||
var fileName = onedriveFile.Name;
|
||||
|
||||
var uploadUriBuilder = new UriBuilder(OneDriveLoginProvider.OneDriveApiUrl)
|
||||
{
|
||||
Path = "/" + ApiVersion + "/drive/items/" + folderId + ":/" + fileName + ":/oneDrive.createUploadSession"
|
||||
};
|
||||
|
||||
var request = WebRequest.Create(uploadUriBuilder.Uri);
|
||||
request.Method = "POST";
|
||||
request.ContentLength = 0;
|
||||
|
||||
request.ContentType = "application/json; charset=UTF-8";
|
||||
request.Headers.Add("Authorization", "Bearer " + AccessToken);
|
||||
|
||||
var uploadSession = new ResumableUploadSession(onedriveFile.Id, folderId, contentLength);
|
||||
using (var response = request.GetResponse())
|
||||
using (var responseStream = response.GetResponseStream())
|
||||
{
|
||||
if (responseStream != null)
|
||||
{
|
||||
using (var readStream = new StreamReader(responseStream))
|
||||
{
|
||||
var responseString = readStream.ReadToEnd();
|
||||
var responseJson = JObject.Parse(responseString);
|
||||
uploadSession.Location = responseJson.Value<string>("uploadUrl");
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
uploadSession.Status = ResumableUploadSessionStatus.Started;
|
||||
|
||||
return uploadSession;
|
||||
}
|
||||
|
||||
public void Transfer(ResumableUploadSession oneDriveSession, Stream stream, long chunkLength)
|
||||
{
|
||||
if (stream == null)
|
||||
throw new ArgumentNullException("stream");
|
||||
|
||||
if (oneDriveSession.Status != ResumableUploadSessionStatus.Started)
|
||||
throw new InvalidOperationException("Can't upload chunk for given upload session.");
|
||||
|
||||
var request = WebRequest.Create(oneDriveSession.Location);
|
||||
request.Method = "PUT";
|
||||
request.ContentLength = chunkLength;
|
||||
request.Headers.Add("Authorization", "Bearer " + AccessToken);
|
||||
request.Headers.Add("Content-Range", string.Format("bytes {0}-{1}/{2}",
|
||||
oneDriveSession.BytesTransfered,
|
||||
oneDriveSession.BytesTransfered + chunkLength - 1,
|
||||
oneDriveSession.BytesToTransfer));
|
||||
|
||||
using (var requestStream = request.GetRequestStream())
|
||||
{
|
||||
stream.CopyTo(requestStream);
|
||||
}
|
||||
|
||||
using (var response = (HttpWebResponse)request.GetResponse())
|
||||
{
|
||||
if (response.StatusCode != HttpStatusCode.Created && response.StatusCode != HttpStatusCode.OK)
|
||||
{
|
||||
oneDriveSession.BytesTransfered += chunkLength;
|
||||
}
|
||||
else
|
||||
{
|
||||
oneDriveSession.Status = ResumableUploadSessionStatus.Completed;
|
||||
|
||||
using (var responseStream = response.GetResponseStream())
|
||||
{
|
||||
if (responseStream == null) return;
|
||||
using (var readStream = new StreamReader(responseStream))
|
||||
{
|
||||
var responseString = readStream.ReadToEnd();
|
||||
var responseJson = JObject.Parse(responseString);
|
||||
|
||||
oneDriveSession.FileId = responseJson.Value<string>("id");
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
public void CancelTransfer(ResumableUploadSession oneDriveSession)
|
||||
{
|
||||
var request = WebRequest.Create(oneDriveSession.Location);
|
||||
request.Method = "DELETE";
|
||||
using (request.GetResponse())
|
||||
{
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
|
||||
public class OneDriveAuthProvider : IAuthenticationProvider
|
||||
{
|
||||
private readonly string _accessToken;
|
||||
|
||||
public OneDriveAuthProvider(string accessToken)
|
||||
{
|
||||
_accessToken = accessToken;
|
||||
}
|
||||
|
||||
public Task AuthenticateRequestAsync(HttpRequestMessage request)
|
||||
{
|
||||
request.Headers.Authorization = new AuthenticationHeaderValue("bearer", _accessToken);
|
||||
return Task.WhenAll();
|
||||
}
|
||||
}
|
||||
|
||||
public enum ResumableUploadSessionStatus
|
||||
{
|
||||
None,
|
||||
Started,
|
||||
Completed,
|
||||
Aborted
|
||||
}
|
||||
|
||||
[Serializable]
|
||||
internal class ResumableUploadSession
|
||||
{
|
||||
public long BytesToTransfer { get; set; }
|
||||
|
||||
public long BytesTransfered { get; set; }
|
||||
|
||||
public string FileId { get; set; }
|
||||
|
||||
public string FolderId { get; set; }
|
||||
|
||||
public ResumableUploadSessionStatus Status { get; set; }
|
||||
|
||||
public string Location { get; set; }
|
||||
|
||||
public ResumableUploadSession(string fileId, string folderId, long bytesToTransfer)
|
||||
{
|
||||
FileId = fileId;
|
||||
FolderId = folderId;
|
||||
BytesToTransfer = bytesToTransfer;
|
||||
Status = ResumableUploadSessionStatus.None;
|
||||
}
|
||||
}
|
||||
}
|
180
products/ASC.Files/Server/Core/Thirdparty/OneDrive/OneDriveTagDao.cs
vendored
Normal file
180
products/ASC.Files/Server/Core/Thirdparty/OneDrive/OneDriveTagDao.cs
vendored
Normal file
@ -0,0 +1,180 @@
|
||||
/*
|
||||
*
|
||||
* (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;
|
||||
using System.Linq;
|
||||
|
||||
using ASC.Common;
|
||||
using ASC.Common.Logging;
|
||||
using ASC.Core;
|
||||
using ASC.Core.Common.EF;
|
||||
using ASC.Core.Tenants;
|
||||
using ASC.Files.Core;
|
||||
using ASC.Files.Core.EF;
|
||||
using ASC.Files.Thirdparty.Dropbox;
|
||||
using ASC.Web.Core.Files;
|
||||
using ASC.Web.Studio.Core;
|
||||
|
||||
using Microsoft.Extensions.Options;
|
||||
|
||||
namespace ASC.Files.Thirdparty.OneDrive
|
||||
{
|
||||
internal class OneDriveTagDao : OneDriveDaoBase, ITagDao<string>
|
||||
{
|
||||
public OneDriveTagDao(IServiceProvider serviceProvider, UserManager userManager, TenantManager tenantManager, TenantUtil tenantUtil, DbContextManager<FilesDbContext> dbContextManager, SetupInfo setupInfo, IOptionsMonitor<ILog> monitor, FileUtility fileUtility) : base(serviceProvider, userManager, tenantManager, tenantUtil, dbContextManager, setupInfo, monitor, fileUtility)
|
||||
{
|
||||
}
|
||||
|
||||
#region ITagDao Members
|
||||
|
||||
public IEnumerable<Tag> GetTags(TagType tagType, IEnumerable<FileEntry<string>> fileEntries)
|
||||
{
|
||||
return null;
|
||||
}
|
||||
|
||||
public IEnumerable<Tag> GetTags(Guid owner, TagType tagType)
|
||||
{
|
||||
return null;
|
||||
}
|
||||
|
||||
public IEnumerable<Tag> GetTags(string name, TagType tagType)
|
||||
{
|
||||
return null;
|
||||
}
|
||||
|
||||
public IEnumerable<Tag> GetTags(string[] names, TagType tagType)
|
||||
{
|
||||
return null;
|
||||
}
|
||||
|
||||
public IEnumerable<Tag> GetNewTags(Guid subject, Folder<string> parentFolder, bool deepSearch)
|
||||
{
|
||||
var folderId = DaoSelector.ConvertId(parentFolder.ID);
|
||||
var fakeFolderId = parentFolder.ID.ToString();
|
||||
|
||||
var entryIDs = FilesDbContext.ThirdpartyIdMapping
|
||||
.Where(r => r.Id.StartsWith(fakeFolderId))
|
||||
.Select(r => r.HashId)
|
||||
.ToList();
|
||||
|
||||
if (!entryIDs.Any()) return new List<Tag>();
|
||||
|
||||
var q = FilesDbContext.Tag
|
||||
.Join(FilesDbContext.TagLink.DefaultIfEmpty(),
|
||||
r => new TagLink { TenantId = r.TenantId, Id = r.Id },
|
||||
r => new TagLink { TenantId = r.TenantId, Id = r.TagId },
|
||||
(tag, tagLink) => new { tag, tagLink },
|
||||
new TagLinkComparer())
|
||||
.Where(r => r.tag.TenantId == TenantID)
|
||||
.Where(r => r.tag.Flag == TagType.New)
|
||||
.Where(r => r.tagLink.TenantId == TenantID)
|
||||
.Where(r => entryIDs.Any(a => a == r.tagLink.EntryId));
|
||||
|
||||
if (subject != Guid.Empty)
|
||||
{
|
||||
q = q.Where(r => r.tag.Owner == subject);
|
||||
}
|
||||
|
||||
var tags = q
|
||||
.ToList()
|
||||
.Select(r => new Tag
|
||||
{
|
||||
TagName = r.tag.Name,
|
||||
TagType = r.tag.Flag,
|
||||
Owner = r.tag.Owner,
|
||||
EntryId = MappingID(r.tagLink.EntryId),
|
||||
EntryType = r.tagLink.EntryType,
|
||||
Count = r.tagLink.TagCount,
|
||||
Id = r.tag.Id
|
||||
});
|
||||
|
||||
if (deepSearch) return tags;
|
||||
|
||||
var folderFileIds = new[] { fakeFolderId }
|
||||
.Concat(GetChildren(folderId));
|
||||
|
||||
return tags.Where(tag => folderFileIds.Contains(tag.EntryId.ToString()));
|
||||
}
|
||||
|
||||
public IEnumerable<Tag> GetNewTags(Guid subject, IEnumerable<FileEntry<string>> fileEntries)
|
||||
{
|
||||
return null;
|
||||
}
|
||||
|
||||
public IEnumerable<Tag> GetNewTags(Guid subject, FileEntry<string> fileEntry)
|
||||
{
|
||||
return null;
|
||||
}
|
||||
|
||||
public IEnumerable<Tag> SaveTags(IEnumerable<Tag> tag)
|
||||
{
|
||||
return null;
|
||||
}
|
||||
|
||||
public IEnumerable<Tag> SaveTags(Tag tag)
|
||||
{
|
||||
return null;
|
||||
}
|
||||
|
||||
public void UpdateNewTags(IEnumerable<Tag> tag)
|
||||
{
|
||||
}
|
||||
|
||||
public void UpdateNewTags(Tag tag)
|
||||
{
|
||||
}
|
||||
|
||||
public void RemoveTags(IEnumerable<Tag> tag)
|
||||
{
|
||||
}
|
||||
|
||||
public void RemoveTags(Tag tag)
|
||||
{
|
||||
}
|
||||
|
||||
public IEnumerable<Tag> GetTags(string entryID, FileEntryType entryType, TagType tagType)
|
||||
{
|
||||
return null;
|
||||
}
|
||||
|
||||
public void MarkAsNew(Guid subject, FileEntry<string> fileEntry)
|
||||
{
|
||||
}
|
||||
|
||||
#endregion
|
||||
}
|
||||
|
||||
public static class OneDriveTagDaoExtention
|
||||
{
|
||||
public static DIHelper AddOneDriveTagDaoService(this DIHelper services)
|
||||
{
|
||||
services.TryAddScoped<OneDriveTagDao>();
|
||||
|
||||
return services;
|
||||
}
|
||||
}
|
||||
}
|
607
products/ASC.Files/Server/Core/Thirdparty/ProviderAccountDao.cs
vendored
Normal file
607
products/ASC.Files/Server/Core/Thirdparty/ProviderAccountDao.cs
vendored
Normal file
@ -0,0 +1,607 @@
|
||||
/*
|
||||
*
|
||||
* (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;
|
||||
using System.Linq;
|
||||
|
||||
using ASC.Common;
|
||||
using ASC.Common.Logging;
|
||||
using ASC.Core;
|
||||
using ASC.Core.Common.Configuration;
|
||||
using ASC.Core.Common.EF;
|
||||
using ASC.Core.Tenants;
|
||||
using ASC.FederatedLogin;
|
||||
using ASC.FederatedLogin.Helpers;
|
||||
using ASC.FederatedLogin.LoginProviders;
|
||||
using ASC.Files.Core;
|
||||
using ASC.Files.Core.EF;
|
||||
using ASC.Files.Resources;
|
||||
using ASC.Files.Thirdparty.Box;
|
||||
using ASC.Files.Thirdparty.Dropbox;
|
||||
using ASC.Files.Thirdparty.GoogleDrive;
|
||||
using ASC.Files.Thirdparty.OneDrive;
|
||||
using ASC.Files.Thirdparty.SharePoint;
|
||||
using ASC.Files.Thirdparty.Sharpbox;
|
||||
using ASC.Security.Cryptography;
|
||||
using ASC.Web.Files.Classes;
|
||||
|
||||
using Microsoft.Extensions.DependencyInjection;
|
||||
using Microsoft.Extensions.Options;
|
||||
|
||||
using static ASC.Files.Core.Data.AbstractDao;
|
||||
|
||||
namespace ASC.Files.Thirdparty
|
||||
{
|
||||
public enum ProviderTypes
|
||||
{
|
||||
Box,
|
||||
BoxNet,
|
||||
DropBox,
|
||||
DropboxV2,
|
||||
Google,
|
||||
GoogleDrive,
|
||||
OneDrive,
|
||||
SharePoint,
|
||||
SkyDrive,
|
||||
WebDav,
|
||||
Yandex,
|
||||
}
|
||||
|
||||
internal class ProviderAccountDao : IProviderDao
|
||||
{
|
||||
protected int TenantID { get; private set; }
|
||||
public FilesDbContext FilesDbContext { get; }
|
||||
public ILog Logger { get; }
|
||||
public IServiceProvider ServiceProvider { get; }
|
||||
public TenantUtil TenantUtil { get; }
|
||||
public InstanceCrypto InstanceCrypto { get; }
|
||||
public SecurityContext SecurityContext { get; }
|
||||
public ConsumerFactory ConsumerFactory { get; }
|
||||
|
||||
public ProviderAccountDao(
|
||||
IServiceProvider serviceProvider,
|
||||
TenantUtil tenantUtil,
|
||||
TenantManager tenantManager,
|
||||
InstanceCrypto instanceCrypto,
|
||||
SecurityContext securityContext,
|
||||
ConsumerFactory consumerFactory,
|
||||
DbContextManager<FilesDbContext> dbContextManager,
|
||||
IOptionsMonitor<ILog> options)
|
||||
{
|
||||
TenantID = tenantManager.GetCurrentTenant().TenantId;
|
||||
FilesDbContext = dbContextManager.Get(FileConstant.DatabaseId);
|
||||
Logger = options.Get("ASC.Files");
|
||||
ServiceProvider = serviceProvider;
|
||||
TenantUtil = tenantUtil;
|
||||
InstanceCrypto = instanceCrypto;
|
||||
SecurityContext = securityContext;
|
||||
ConsumerFactory = consumerFactory;
|
||||
}
|
||||
|
||||
public virtual IProviderInfo GetProviderInfo(int linkId)
|
||||
{
|
||||
return GetProvidersInfoInternal(linkId).Single();
|
||||
}
|
||||
|
||||
public virtual List<IProviderInfo> GetProvidersInfo()
|
||||
{
|
||||
return GetProvidersInfoInternal();
|
||||
}
|
||||
|
||||
public virtual List<IProviderInfo> GetProvidersInfo(FolderType folderType, string searchText = null)
|
||||
{
|
||||
return GetProvidersInfoInternal(folderType: folderType, searchText: searchText);
|
||||
}
|
||||
|
||||
public virtual List<IProviderInfo> GetProvidersInfo(Guid userId)
|
||||
{
|
||||
try
|
||||
{
|
||||
return FilesDbContext.ThirdpartyAccount
|
||||
.Where(r => r.TenantId == TenantID)
|
||||
.Where(r => r.UserId == userId)
|
||||
.ToList()
|
||||
.Select(ToProviderInfo)
|
||||
.ToList();
|
||||
}
|
||||
catch (Exception e)
|
||||
{
|
||||
Logger.Error(string.Format("GetProvidersInfoInternal: user = {0}", userId), e);
|
||||
return new List<IProviderInfo>();
|
||||
}
|
||||
}
|
||||
|
||||
private List<IProviderInfo> GetProvidersInfoInternal(int linkId = -1, FolderType folderType = FolderType.DEFAULT, string searchText = null)
|
||||
{
|
||||
var querySelect = FilesDbContext.ThirdpartyAccount.Where(r => r.TenantId == TenantID);
|
||||
|
||||
if (folderType == FolderType.USER || folderType == FolderType.DEFAULT && linkId == -1)
|
||||
{
|
||||
querySelect = querySelect.Where(r => r.UserId == SecurityContext.CurrentAccount.ID);
|
||||
}
|
||||
|
||||
if (linkId != -1)
|
||||
{
|
||||
querySelect = querySelect.Where(r => r.Id == linkId);
|
||||
}
|
||||
|
||||
if (folderType != FolderType.DEFAULT)
|
||||
{
|
||||
querySelect = querySelect.Where(r => r.FolderType == folderType);
|
||||
}
|
||||
|
||||
if (!string.IsNullOrEmpty(searchText))
|
||||
{
|
||||
querySelect = BuildSearch(querySelect, searchText, SearhTypeEnum.Any);
|
||||
}
|
||||
|
||||
try
|
||||
{
|
||||
return querySelect.ToList()
|
||||
.Select(ToProviderInfo)
|
||||
.ToList();
|
||||
}
|
||||
catch (Exception e)
|
||||
{
|
||||
Logger.Error(string.Format("GetProvidersInfoInternal: linkId = {0} , folderType = {1} , user = {2}",
|
||||
linkId, folderType, SecurityContext.CurrentAccount.ID), e);
|
||||
return new List<IProviderInfo>();
|
||||
}
|
||||
}
|
||||
|
||||
public virtual int SaveProviderInfo(string providerKey, string customerTitle, AuthData authData, FolderType folderType)
|
||||
{
|
||||
ProviderTypes prKey;
|
||||
try
|
||||
{
|
||||
prKey = (ProviderTypes)Enum.Parse(typeof(ProviderTypes), providerKey, true);
|
||||
}
|
||||
catch (Exception)
|
||||
{
|
||||
throw new ArgumentException("Unrecognize ProviderType");
|
||||
}
|
||||
|
||||
authData = GetEncodedAccesToken(authData, prKey);
|
||||
|
||||
if (!CheckProviderInfo(ToProviderInfo(0, prKey, customerTitle, authData, SecurityContext.CurrentAccount.ID, folderType, TenantUtil.DateTimeToUtc(TenantUtil.DateTimeNow()))))
|
||||
{
|
||||
throw new UnauthorizedAccessException(string.Format(FilesCommonResource.ErrorMassage_SecurityException_Auth, providerKey));
|
||||
}
|
||||
var dbFilesThirdpartyAccount = new DbFilesThirdpartyAccount
|
||||
{
|
||||
Id = 0,
|
||||
TenantId = TenantID,
|
||||
Provider = providerKey,
|
||||
Title = Global.ReplaceInvalidCharsAndTruncate(customerTitle),
|
||||
UserName = authData.Login ?? "",
|
||||
Password = EncryptPassword(authData.Password),
|
||||
FolderType = folderType,
|
||||
CreateOn = TenantUtil.DateTimeToUtc(TenantUtil.DateTimeNow()),
|
||||
UserId = SecurityContext.CurrentAccount.ID,
|
||||
Token = EncryptPassword(authData.Token ?? ""),
|
||||
Url = authData.Url ?? ""
|
||||
};
|
||||
|
||||
return FilesDbContext.AddOrUpdate(r => r.ThirdpartyAccount, dbFilesThirdpartyAccount).Id;
|
||||
}
|
||||
|
||||
public bool CheckProviderInfo(IProviderInfo providerInfo)
|
||||
{
|
||||
return providerInfo != null && providerInfo.CheckAccess();
|
||||
}
|
||||
|
||||
public virtual int UpdateProviderInfo(int linkId, AuthData authData)
|
||||
{
|
||||
var forUpdate = FilesDbContext.ThirdpartyAccount
|
||||
.Where(r => r.Id == linkId)
|
||||
.Where(r => r.TenantId == TenantID)
|
||||
.ToList();
|
||||
|
||||
foreach (var f in forUpdate)
|
||||
{
|
||||
f.UserName = authData.Login ?? "";
|
||||
f.Password = EncryptPassword(authData.Password);
|
||||
f.Token = EncryptPassword(authData.Token ?? "");
|
||||
f.Url = authData.Url ?? "";
|
||||
}
|
||||
|
||||
FilesDbContext.SaveChanges();
|
||||
|
||||
return forUpdate.Count == 1 ? linkId : default;
|
||||
}
|
||||
|
||||
public virtual int UpdateProviderInfo(int linkId, string customerTitle, AuthData newAuthData, FolderType folderType, Guid? userId = null)
|
||||
{
|
||||
var authData = new AuthData();
|
||||
if (newAuthData != null && !newAuthData.IsEmpty())
|
||||
{
|
||||
var querySelect =
|
||||
FilesDbContext.ThirdpartyAccount
|
||||
.Where(r => r.TenantId == TenantID)
|
||||
.Where(r => r.Id == linkId);
|
||||
|
||||
DbFilesThirdpartyAccount input;
|
||||
try
|
||||
{
|
||||
input = querySelect.Single();
|
||||
}
|
||||
catch (Exception e)
|
||||
{
|
||||
Logger.Error(string.Format("UpdateProviderInfo: linkId = {0} , user = {1}", linkId, SecurityContext.CurrentAccount.ID), e);
|
||||
throw;
|
||||
}
|
||||
|
||||
if (!Enum.TryParse(input.Provider, true, out ProviderTypes key))
|
||||
{
|
||||
throw new ArgumentException("Unrecognize ProviderType");
|
||||
}
|
||||
|
||||
authData = new AuthData(
|
||||
!string.IsNullOrEmpty(newAuthData.Url) ? newAuthData.Url : input.Url,
|
||||
input.UserName,
|
||||
!string.IsNullOrEmpty(newAuthData.Password) ? newAuthData.Password : DecryptPassword(input.Password),
|
||||
newAuthData.Token);
|
||||
|
||||
if (!string.IsNullOrEmpty(newAuthData.Token))
|
||||
{
|
||||
authData = GetEncodedAccesToken(authData, key);
|
||||
}
|
||||
|
||||
if (!CheckProviderInfo(ToProviderInfo(0, key, customerTitle, authData, SecurityContext.CurrentAccount.ID, folderType, TenantUtil.DateTimeToUtc(TenantUtil.DateTimeNow()))))
|
||||
throw new UnauthorizedAccessException(string.Format(FilesCommonResource.ErrorMassage_SecurityException_Auth, key));
|
||||
}
|
||||
|
||||
var toUpdate = FilesDbContext.ThirdpartyAccount
|
||||
.Where(r => r.Id == linkId)
|
||||
.Where(r => r.TenantId == TenantID)
|
||||
.ToList();
|
||||
|
||||
foreach (var t in toUpdate)
|
||||
{
|
||||
if (!string.IsNullOrEmpty(customerTitle))
|
||||
{
|
||||
t.Title = customerTitle;
|
||||
}
|
||||
|
||||
if (folderType != FolderType.DEFAULT)
|
||||
{
|
||||
t.FolderType = folderType;
|
||||
}
|
||||
|
||||
if (userId.HasValue)
|
||||
{
|
||||
t.UserId = userId.Value;
|
||||
}
|
||||
|
||||
if (!authData.IsEmpty())
|
||||
{
|
||||
t.UserName = authData.Login ?? "";
|
||||
t.Password = EncryptPassword(authData.Password);
|
||||
t.Token = EncryptPassword(authData.Token ?? "");
|
||||
t.Url = authData.Url ?? "";
|
||||
}
|
||||
}
|
||||
|
||||
FilesDbContext.SaveChanges();
|
||||
return toUpdate.Count == 1 ? linkId : default;
|
||||
}
|
||||
|
||||
public virtual void RemoveProviderInfo(int linkId)
|
||||
{
|
||||
using (var tx = FilesDbContext.Database.BeginTransaction())
|
||||
{
|
||||
var folderId = GetProviderInfo(linkId).RootFolderId.ToString();
|
||||
|
||||
var entryIDs = FilesDbContext.ThirdpartyIdMapping
|
||||
.Where(r => r.TenantId == TenantID)
|
||||
.Where(r => r.Id.StartsWith(folderId))
|
||||
.Select(r => r.HashId)
|
||||
.ToList();
|
||||
|
||||
var forDelete = FilesDbContext.Security
|
||||
.Where(r => r.TenantId == TenantID)
|
||||
.Where(r => entryIDs.Any(a => a == r.EntryId))
|
||||
.ToList();
|
||||
|
||||
FilesDbContext.Security.RemoveRange(forDelete);
|
||||
FilesDbContext.SaveChanges();
|
||||
|
||||
var linksForDelete = FilesDbContext.TagLink
|
||||
.Where(r => r.TenantId == TenantID)
|
||||
.Where(r => entryIDs.Any(e => e == r.EntryId))
|
||||
.ToList();
|
||||
|
||||
FilesDbContext.TagLink.RemoveRange(linksForDelete);
|
||||
FilesDbContext.SaveChanges();
|
||||
|
||||
var accountsForDelete = FilesDbContext.ThirdpartyAccount
|
||||
.Where(r => r.Id == linkId)
|
||||
.Where(r => r.TenantId == TenantID)
|
||||
.ToList();
|
||||
|
||||
FilesDbContext.ThirdpartyAccount.RemoveRange(accountsForDelete);
|
||||
FilesDbContext.SaveChanges();
|
||||
|
||||
tx.Commit();
|
||||
}
|
||||
}
|
||||
|
||||
private IProviderInfo ToProviderInfo(int id, ProviderTypes providerKey, string customerTitle, AuthData authData, Guid owner, FolderType type, DateTime createOn)
|
||||
{
|
||||
var dbFilesThirdpartyAccount = new DbFilesThirdpartyAccount
|
||||
{
|
||||
Id = id,
|
||||
Title = customerTitle,
|
||||
Token = EncryptPassword(authData.Token),
|
||||
Password = EncryptPassword(authData.Password),
|
||||
UserId = owner,
|
||||
FolderType = type,
|
||||
CreateOn = createOn,
|
||||
Provider = providerKey.ToString()
|
||||
};
|
||||
|
||||
return ToProviderInfo(dbFilesThirdpartyAccount);
|
||||
}
|
||||
|
||||
private IProviderInfo ToProviderInfo(DbFilesThirdpartyAccount input)
|
||||
{
|
||||
if (!Enum.TryParse(input.Provider, true, out ProviderTypes key)) return null;
|
||||
|
||||
var id = input.Id;
|
||||
var providerTitle = input.Title ?? string.Empty;
|
||||
var token = DecryptToken(input.Token);
|
||||
var owner = input.UserId;
|
||||
var folderType = input.FolderType;
|
||||
var createOn = TenantUtil.DateTimeFromUtc(input.CreateOn);
|
||||
var authData = new AuthData(input.Url, input.UserName, DecryptPassword(input.Password), token);
|
||||
|
||||
if (string.IsNullOrEmpty(token)) throw new ArgumentException("Token can't be null");
|
||||
|
||||
if (key == ProviderTypes.Box)
|
||||
{
|
||||
var box = ServiceProvider.GetService<BoxProviderInfo>();
|
||||
box.ID = id;
|
||||
box.CustomerTitle = providerTitle;
|
||||
box.Owner = owner == Guid.Empty ? SecurityContext.CurrentAccount.ID : owner;
|
||||
box.ProviderKey = input.Provider;
|
||||
box.RootFolderType = folderType;
|
||||
box.CreateOn = createOn;
|
||||
box.Token = OAuth20Token.FromJson(token);
|
||||
return box;
|
||||
}
|
||||
|
||||
if (key == ProviderTypes.DropboxV2)
|
||||
{
|
||||
var drop = ServiceProvider.GetService<DropboxProviderInfo>();
|
||||
drop.ID = id;
|
||||
drop.CustomerTitle = providerTitle;
|
||||
drop.Owner = owner == Guid.Empty ? SecurityContext.CurrentAccount.ID : owner;
|
||||
drop.ProviderKey = input.Provider;
|
||||
drop.RootFolderType = folderType;
|
||||
drop.CreateOn = createOn;
|
||||
drop.Token = OAuth20Token.FromJson(token);
|
||||
|
||||
return drop;
|
||||
}
|
||||
|
||||
if (key == ProviderTypes.SharePoint)
|
||||
{
|
||||
if (!string.IsNullOrEmpty(authData.Login) && string.IsNullOrEmpty(authData.Password))
|
||||
throw new ArgumentNullException("password", "Password can't be null");
|
||||
|
||||
var sh = ServiceProvider.GetService<SharePointProviderInfo>();
|
||||
sh.ID = id;
|
||||
sh.CustomerTitle = providerTitle;
|
||||
sh.Owner = owner == Guid.Empty ? SecurityContext.CurrentAccount.ID : owner;
|
||||
sh.ProviderKey = input.Provider;
|
||||
sh.RootFolderType = folderType;
|
||||
sh.CreateOn = createOn;
|
||||
sh.InitClientContext(authData);
|
||||
return sh;
|
||||
}
|
||||
|
||||
if (key == ProviderTypes.GoogleDrive)
|
||||
{
|
||||
var gd = ServiceProvider.GetService<GoogleDriveProviderInfo>();
|
||||
gd.ID = id;
|
||||
gd.CustomerTitle = providerTitle;
|
||||
gd.Owner = owner == Guid.Empty ? SecurityContext.CurrentAccount.ID : owner;
|
||||
gd.ProviderKey = input.Provider;
|
||||
gd.RootFolderType = folderType;
|
||||
gd.CreateOn = createOn;
|
||||
gd.Token = OAuth20Token.FromJson(token);
|
||||
|
||||
return gd;
|
||||
}
|
||||
|
||||
if (key == ProviderTypes.OneDrive)
|
||||
{
|
||||
var od = ServiceProvider.GetService<OneDriveProviderInfo>();
|
||||
od.ID = id;
|
||||
od.CustomerTitle = providerTitle;
|
||||
od.Owner = owner == Guid.Empty ? SecurityContext.CurrentAccount.ID : owner;
|
||||
od.ProviderKey = input.Provider;
|
||||
od.RootFolderType = folderType;
|
||||
od.CreateOn = createOn;
|
||||
od.Token = OAuth20Token.FromJson(token);
|
||||
|
||||
return od;
|
||||
}
|
||||
|
||||
if (string.IsNullOrEmpty(input.Provider))
|
||||
throw new ArgumentNullException("providerKey");
|
||||
if (string.IsNullOrEmpty(authData.Token) && string.IsNullOrEmpty(authData.Password))
|
||||
throw new ArgumentNullException("token", "Both token and password can't be null");
|
||||
if (!string.IsNullOrEmpty(authData.Login) && string.IsNullOrEmpty(authData.Password) && string.IsNullOrEmpty(authData.Token))
|
||||
throw new ArgumentNullException("password", "Password can't be null");
|
||||
|
||||
var sharpBoxProviderInfo = ServiceProvider.GetService<SharpBoxProviderInfo>();
|
||||
sharpBoxProviderInfo.ID = id;
|
||||
sharpBoxProviderInfo.CustomerTitle = providerTitle;
|
||||
sharpBoxProviderInfo.Owner = owner == Guid.Empty ? SecurityContext.CurrentAccount.ID : owner;
|
||||
sharpBoxProviderInfo.ProviderKey = input.Provider;
|
||||
sharpBoxProviderInfo.RootFolderType = folderType;
|
||||
sharpBoxProviderInfo.CreateOn = createOn;
|
||||
sharpBoxProviderInfo.AuthData = authData;
|
||||
|
||||
return sharpBoxProviderInfo;
|
||||
}
|
||||
|
||||
private AuthData GetEncodedAccesToken(AuthData authData, ProviderTypes provider)
|
||||
{
|
||||
switch (provider)
|
||||
{
|
||||
//case ProviderTypes.GoogleDrive:
|
||||
|
||||
// var code = authData.Token;
|
||||
|
||||
// var token = OAuth20TokenHelper.GetAccessToken<GoogleLoginProvider>(code);
|
||||
|
||||
// if (token == null) throw new UnauthorizedAccessException(string.Format(FilesCommonResource.ErrorMassage_SecurityException_Auth, provider));
|
||||
|
||||
// return new AuthData(token: token.ToJson());
|
||||
|
||||
//case ProviderTypes.Box:
|
||||
|
||||
// code = authData.Token;
|
||||
|
||||
// token = OAuth20TokenHelper.GetAccessToken<BoxLoginProvider>(code);
|
||||
|
||||
// if (token == null) throw new UnauthorizedAccessException(string.Format(FilesCommonResource.ErrorMassage_SecurityException_Auth, provider));
|
||||
|
||||
// return new AuthData(token: token.ToJson());
|
||||
|
||||
case ProviderTypes.DropboxV2:
|
||||
|
||||
var code = authData.Token;
|
||||
|
||||
var token = OAuth20TokenHelper.GetAccessToken<DropboxLoginProvider>(ConsumerFactory, code);
|
||||
|
||||
if (token == null) throw new UnauthorizedAccessException(string.Format(FilesCommonResource.ErrorMassage_SecurityException_Auth, provider));
|
||||
|
||||
return new AuthData(token: token.ToJson());
|
||||
|
||||
//case ProviderTypes.DropBox:
|
||||
|
||||
// var dropBoxRequestToken = DropBoxRequestToken.Parse(authData.Token);
|
||||
|
||||
// var config = CloudStorage.GetCloudConfigurationEasy(nSupportedCloudConfigurations.DropBox);
|
||||
// var accessToken = DropBoxStorageProviderTools.ExchangeDropBoxRequestTokenIntoAccessToken(config as DropBoxConfiguration,
|
||||
// ThirdpartyConfiguration.DropboxAppKey,
|
||||
// ThirdpartyConfiguration.DropboxAppSecret,
|
||||
// dropBoxRequestToken);
|
||||
|
||||
// var base64Token = new CloudStorage().SerializeSecurityTokenToBase64Ex(accessToken, config.GetType(), new Dictionary<string, string>());
|
||||
|
||||
// return new AuthData(token: base64Token);
|
||||
|
||||
//case ProviderTypes.OneDrive:
|
||||
|
||||
// code = authData.Token;
|
||||
|
||||
// token = OAuth20TokenHelper.GetAccessToken<OneDriveLoginProvider>(code);
|
||||
|
||||
// if (token == null) throw new UnauthorizedAccessException(string.Format(FilesCommonResource.ErrorMassage_SecurityException_Auth, provider));
|
||||
|
||||
// return new AuthData(token: token.ToJson());
|
||||
|
||||
//case ProviderTypes.SkyDrive:
|
||||
|
||||
// code = authData.Token;
|
||||
|
||||
// token = OAuth20TokenHelper.GetAccessToken<OneDriveLoginProvider>(code);
|
||||
|
||||
// if (token == null) throw new UnauthorizedAccessException(string.Format(FilesCommonResource.ErrorMassage_SecurityException_Auth, provider));
|
||||
|
||||
// accessToken = AppLimit.CloudComputing.SharpBox.Common.Net.oAuth20.OAuth20Token.FromJson(token.ToJson());
|
||||
|
||||
// if (accessToken == null) throw new UnauthorizedAccessException(string.Format(FilesCommonResource.ErrorMassage_SecurityException_Auth, provider));
|
||||
|
||||
// config = CloudStorage.GetCloudConfigurationEasy(nSupportedCloudConfigurations.SkyDrive);
|
||||
// var storage = new CloudStorage();
|
||||
// base64Token = storage.SerializeSecurityTokenToBase64Ex(accessToken, config.GetType(), new Dictionary<string, string>());
|
||||
|
||||
// return new AuthData(token: base64Token);
|
||||
|
||||
//case ProviderTypes.SharePoint:
|
||||
//case ProviderTypes.WebDav:
|
||||
// break;
|
||||
|
||||
default:
|
||||
authData.Url = null;
|
||||
break;
|
||||
}
|
||||
|
||||
return authData;
|
||||
}
|
||||
|
||||
private string EncryptPassword(string password)
|
||||
{
|
||||
return string.IsNullOrEmpty(password) ? string.Empty : InstanceCrypto.Encrypt(password);
|
||||
}
|
||||
|
||||
private string DecryptPassword(string password)
|
||||
{
|
||||
return string.IsNullOrEmpty(password) ? string.Empty : InstanceCrypto.Decrypt(password);
|
||||
}
|
||||
|
||||
private string DecryptToken(string token)
|
||||
{
|
||||
try
|
||||
{
|
||||
return DecryptPassword(token);
|
||||
}
|
||||
catch
|
||||
{
|
||||
//old token in base64 without encrypt
|
||||
return token ?? "";
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
public static class ProviderAccountDaoExtention
|
||||
{
|
||||
public static DIHelper AddProviderAccountDaoService(this DIHelper services)
|
||||
{
|
||||
//services.TryAddScoped<IProviderDao, ProviderAccountDao>();
|
||||
|
||||
return services
|
||||
.AddSharpBoxProviderInfoService()
|
||||
.AddSharePointProviderInfoService()
|
||||
.AddOneDriveProviderInfoService()
|
||||
.AddGoogleDriveProviderInfoService()
|
||||
.AddBoxProviderInfoService()
|
||||
.AddDropboxProviderInfoService()
|
||||
.AddTenantUtilService()
|
||||
.AddTenantManagerService()
|
||||
.AddInstanceCryptoService()
|
||||
.AddSecurityContextService()
|
||||
.AddConsumerFactoryService()
|
||||
.AddDbContextManagerService<FilesDbContext>();
|
||||
}
|
||||
}
|
||||
}
|
182
products/ASC.Files/Server/Core/Thirdparty/ProviderDao/ProviderDaoBase.cs
vendored
Normal file
182
products/ASC.Files/Server/Core/Thirdparty/ProviderDao/ProviderDaoBase.cs
vendored
Normal file
@ -0,0 +1,182 @@
|
||||
/*
|
||||
*
|
||||
* (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;
|
||||
using System.Linq;
|
||||
using System.Threading;
|
||||
|
||||
using ASC.Common;
|
||||
using ASC.Core;
|
||||
using ASC.Files.Core;
|
||||
using ASC.Files.Core.Data;
|
||||
using ASC.Files.Core.Thirdparty;
|
||||
using ASC.Files.Thirdparty.Box;
|
||||
using ASC.Files.Thirdparty.Dropbox;
|
||||
using ASC.Files.Thirdparty.GoogleDrive;
|
||||
using ASC.Files.Thirdparty.OneDrive;
|
||||
using ASC.Files.Thirdparty.SharePoint;
|
||||
using ASC.Files.Thirdparty.Sharpbox;
|
||||
|
||||
using Microsoft.Extensions.DependencyInjection;
|
||||
|
||||
namespace ASC.Files.Thirdparty.ProviderDao
|
||||
{
|
||||
internal class ProviderDaoBase : IDisposable
|
||||
{
|
||||
private readonly List<IDaoSelector> Selectors;
|
||||
|
||||
private int TenantID { get; set; }
|
||||
|
||||
public ProviderDaoBase(
|
||||
IServiceProvider serviceProvider,
|
||||
TenantManager tenantManager,
|
||||
SecurityDao<string> securityDao,
|
||||
TagDao<string> tagDao,
|
||||
CrossDao crossDao)
|
||||
{
|
||||
ServiceProvider = serviceProvider;
|
||||
SecurityDao = securityDao;
|
||||
TagDao = tagDao;
|
||||
CrossDao = crossDao;
|
||||
TenantID = tenantManager.GetCurrentTenant().TenantId;
|
||||
|
||||
Selectors = new List<IDaoSelector>
|
||||
{
|
||||
//Fill in selectors
|
||||
ServiceProvider.GetService<SharpBoxDaoSelector>(),
|
||||
ServiceProvider.GetService<SharePointDaoSelector>(),
|
||||
ServiceProvider.GetService<GoogleDriveDaoSelector>(),
|
||||
ServiceProvider.GetService<BoxDaoSelector>(),
|
||||
ServiceProvider.GetService<DropboxDaoSelector>(),
|
||||
ServiceProvider.GetService<OneDriveDaoSelector>()
|
||||
};
|
||||
}
|
||||
|
||||
public IServiceProvider ServiceProvider { get; }
|
||||
public SecurityDao<string> SecurityDao { get; }
|
||||
public TagDao<string> TagDao { get; }
|
||||
public CrossDao CrossDao { get; }
|
||||
|
||||
protected bool IsCrossDao(string id1, string id2)
|
||||
{
|
||||
if (id2 == null || id1 == null)
|
||||
return false;
|
||||
return !Equals(GetSelector(id1).GetIdCode(id1), GetSelector(id2).GetIdCode(id2));
|
||||
}
|
||||
|
||||
public IDaoSelector GetSelector(string id)
|
||||
{
|
||||
return Selectors.FirstOrDefault(selector => selector.IsMatch(id));
|
||||
}
|
||||
|
||||
protected void SetSharedProperty(IEnumerable<FileEntry<string>> entries)
|
||||
{
|
||||
SecurityDao.GetPureShareRecords(entries.ToArray())
|
||||
//.Where(x => x.Owner == SecurityContext.CurrentAccount.ID)
|
||||
.Select(x => x.EntryId).Distinct().ToList()
|
||||
.ForEach(id =>
|
||||
{
|
||||
var firstEntry = entries.FirstOrDefault(y => y.ID.Equals(id));
|
||||
|
||||
if (firstEntry != null)
|
||||
firstEntry.Shared = true;
|
||||
});
|
||||
}
|
||||
|
||||
protected IEnumerable<IDaoSelector> GetSelectors()
|
||||
{
|
||||
return Selectors;
|
||||
}
|
||||
|
||||
|
||||
protected internal File<string> PerformCrossDaoFileCopy(string fromFileId, string toFolderId, bool deleteSourceFile)
|
||||
{
|
||||
var fromSelector = GetSelector(fromFileId);
|
||||
var toSelector = GetSelector(toFolderId);
|
||||
|
||||
return CrossDao.PerformCrossDaoFileCopy(
|
||||
fromFileId, fromSelector.GetFileDao(fromFileId), fromSelector.ConvertId,
|
||||
toFolderId, toSelector.GetFileDao(toFolderId), toSelector.ConvertId,
|
||||
deleteSourceFile);
|
||||
}
|
||||
|
||||
protected File<int> PerformCrossDaoFileCopy(string fromFileId, int toFolderId, bool deleteSourceFile)
|
||||
{
|
||||
var fromSelector = GetSelector(fromFileId);
|
||||
using var scope = ServiceProvider.CreateScope();
|
||||
var tenantManager = scope.ServiceProvider.GetService<TenantManager>();
|
||||
tenantManager.SetCurrentTenant(TenantID);
|
||||
|
||||
return CrossDao.PerformCrossDaoFileCopy(
|
||||
fromFileId, fromSelector.GetFileDao(fromFileId), fromSelector.ConvertId,
|
||||
toFolderId, scope.ServiceProvider.GetService<IFileDao<int>>(), r => r,
|
||||
deleteSourceFile);
|
||||
}
|
||||
|
||||
protected Folder<string> PerformCrossDaoFolderCopy(string fromFolderId, string toRootFolderId, bool deleteSourceFolder, CancellationToken? cancellationToken)
|
||||
{
|
||||
var fromSelector = GetSelector(fromFolderId);
|
||||
var toSelector = GetSelector(toRootFolderId);
|
||||
|
||||
return CrossDao.PerformCrossDaoFolderCopy(
|
||||
fromFolderId, fromSelector.GetFolderDao(fromFolderId), fromSelector.GetFileDao(fromFolderId), fromSelector.ConvertId,
|
||||
toRootFolderId, toSelector.GetFolderDao(toRootFolderId), toSelector.GetFileDao(toRootFolderId), toSelector.ConvertId,
|
||||
deleteSourceFolder, cancellationToken);
|
||||
}
|
||||
|
||||
protected Folder<int> PerformCrossDaoFolderCopy(string fromFolderId, int toRootFolderId, bool deleteSourceFolder, CancellationToken? cancellationToken)
|
||||
{
|
||||
var fromSelector = GetSelector(fromFolderId);
|
||||
using var scope = ServiceProvider.CreateScope();
|
||||
|
||||
return CrossDao.PerformCrossDaoFolderCopy(
|
||||
fromFolderId, fromSelector.GetFolderDao(fromFolderId), fromSelector.GetFileDao(fromFolderId), fromSelector.ConvertId,
|
||||
toRootFolderId, scope.ServiceProvider.GetService<FolderDao>(), scope.ServiceProvider.GetService<IFileDao<int>>(), r => r,
|
||||
deleteSourceFolder, cancellationToken);
|
||||
}
|
||||
|
||||
public void Dispose()
|
||||
{
|
||||
Selectors.ForEach(r => r.Dispose());
|
||||
}
|
||||
}
|
||||
|
||||
public static class ProviderDaoBaseExtention
|
||||
{
|
||||
public static DIHelper AddProviderDaoBaseService(this DIHelper services)
|
||||
{
|
||||
services.TryAddScoped<CrossDao>();
|
||||
return services
|
||||
.AddSharpBoxDaoSelectorService()
|
||||
.AddSharePointSelectorService()
|
||||
.AddOneDriveSelectorService()
|
||||
.AddGoogleDriveSelectorService()
|
||||
.AddDropboxDaoSelectorService()
|
||||
.AddBoxDaoSelectorService();
|
||||
}
|
||||
}
|
||||
}
|
527
products/ASC.Files/Server/Core/Thirdparty/ProviderDao/ProviderFileDao.cs
vendored
Normal file
527
products/ASC.Files/Server/Core/Thirdparty/ProviderDao/ProviderFileDao.cs
vendored
Normal file
@ -0,0 +1,527 @@
|
||||
/*
|
||||
*
|
||||
* (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;
|
||||
using System.IO;
|
||||
using System.Linq;
|
||||
|
||||
using ASC.Common;
|
||||
using ASC.Core;
|
||||
using ASC.Files.Core;
|
||||
using ASC.Files.Core.Data;
|
||||
using ASC.Files.Core.Thirdparty;
|
||||
using ASC.Web.Files.Services.DocumentService;
|
||||
|
||||
namespace ASC.Files.Thirdparty.ProviderDao
|
||||
{
|
||||
internal class ProviderFileDao : ProviderDaoBase, IFileDao<string>
|
||||
{
|
||||
public ProviderFileDao(
|
||||
IServiceProvider serviceProvider,
|
||||
TenantManager tenantManager,
|
||||
SecurityDao<string> securityDao,
|
||||
TagDao<string> tagDao,
|
||||
CrossDao crossDao)
|
||||
: base(serviceProvider, tenantManager, securityDao, tagDao, crossDao)
|
||||
{
|
||||
|
||||
}
|
||||
|
||||
public void InvalidateCache(string fileId)
|
||||
{
|
||||
var selector = GetSelector(fileId);
|
||||
var fileDao = selector.GetFileDao(fileId);
|
||||
fileDao.InvalidateCache(selector.ConvertId(fileId));
|
||||
}
|
||||
|
||||
public File<string> GetFile(string fileId)
|
||||
{
|
||||
var selector = GetSelector(fileId);
|
||||
|
||||
var fileDao = selector.GetFileDao(fileId);
|
||||
var result = fileDao.GetFile(selector.ConvertId(fileId));
|
||||
|
||||
if (result != null)
|
||||
{
|
||||
SetSharedProperty(new[] { result });
|
||||
}
|
||||
|
||||
return result;
|
||||
}
|
||||
|
||||
public File<string> GetFile(string fileId, int fileVersion)
|
||||
{
|
||||
var selector = GetSelector(fileId);
|
||||
|
||||
var fileDao = selector.GetFileDao(fileId);
|
||||
var result = fileDao.GetFile(selector.ConvertId(fileId), fileVersion);
|
||||
|
||||
if (result != null)
|
||||
{
|
||||
SetSharedProperty(new[] { result });
|
||||
}
|
||||
|
||||
return result;
|
||||
}
|
||||
|
||||
public File<string> GetFile(string parentId, string title)
|
||||
{
|
||||
var selector = GetSelector(parentId);
|
||||
var fileDao = selector.GetFileDao(parentId);
|
||||
var result = fileDao.GetFile(selector.ConvertId(parentId), title);
|
||||
|
||||
if (result != null)
|
||||
{
|
||||
SetSharedProperty(new[] { result });
|
||||
}
|
||||
|
||||
return result;
|
||||
}
|
||||
|
||||
public File<string> GetFileStable(string fileId, int fileVersion = -1)
|
||||
{
|
||||
var selector = GetSelector(fileId);
|
||||
|
||||
var fileDao = selector.GetFileDao(fileId);
|
||||
var result = fileDao.GetFileStable(selector.ConvertId(fileId), fileVersion);
|
||||
|
||||
if (result != null)
|
||||
{
|
||||
SetSharedProperty(new[] { result });
|
||||
}
|
||||
|
||||
return result;
|
||||
}
|
||||
|
||||
public List<File<string>> GetFileHistory(string fileId)
|
||||
{
|
||||
var selector = GetSelector(fileId);
|
||||
var fileDao = selector.GetFileDao(fileId);
|
||||
return fileDao.GetFileHistory(selector.ConvertId(fileId));
|
||||
}
|
||||
|
||||
public List<File<string>> GetFiles(string[] fileIds)
|
||||
{
|
||||
var result = Enumerable.Empty<File<string>>();
|
||||
|
||||
foreach (var selector in GetSelectors())
|
||||
{
|
||||
var selectorLocal = selector;
|
||||
var matchedIds = fileIds.Where(selectorLocal.IsMatch);
|
||||
|
||||
if (!matchedIds.Any()) continue;
|
||||
|
||||
result = result.Concat(matchedIds.GroupBy(selectorLocal.GetIdCode)
|
||||
.SelectMany(matchedId =>
|
||||
{
|
||||
var fileDao = selectorLocal.GetFileDao(matchedId.FirstOrDefault());
|
||||
return fileDao.GetFiles(matchedId.Select(selectorLocal.ConvertId).ToArray());
|
||||
}
|
||||
)
|
||||
.Where(r => r != null));
|
||||
}
|
||||
|
||||
return result.ToList();
|
||||
}
|
||||
|
||||
public List<File<string>> GetFilesForShare(string[] fileIds, FilterType filterType, bool subjectGroup, Guid subjectID, string searchText, bool searchInContent)
|
||||
{
|
||||
var result = Enumerable.Empty<File<string>>();
|
||||
|
||||
foreach (var selector in GetSelectors())
|
||||
{
|
||||
var selectorLocal = selector;
|
||||
var matchedIds = fileIds.Where(selectorLocal.IsMatch);
|
||||
|
||||
if (!matchedIds.Any()) continue;
|
||||
|
||||
result = result.Concat(matchedIds.GroupBy(selectorLocal.GetIdCode)
|
||||
.SelectMany(matchedId =>
|
||||
{
|
||||
var fileDao = selectorLocal.GetFileDao(matchedId.FirstOrDefault());
|
||||
return fileDao.GetFilesForShare(matchedId.Select(selectorLocal.ConvertId).ToArray(),
|
||||
filterType, subjectGroup, subjectID, searchText, searchInContent);
|
||||
})
|
||||
.Where(r => r != null));
|
||||
}
|
||||
|
||||
return result.ToList();
|
||||
}
|
||||
|
||||
public List<string> GetFiles(string parentId)
|
||||
{
|
||||
var selector = GetSelector(parentId);
|
||||
var fileDao = selector.GetFileDao(parentId);
|
||||
return fileDao.GetFiles(selector.ConvertId(parentId)).Where(r => r != null).ToList();
|
||||
}
|
||||
|
||||
public List<File<string>> GetFiles(string parentId, OrderBy orderBy, FilterType filterType, bool subjectGroup, Guid subjectID, string searchText, bool searchInContent, bool withSubfolders = false)
|
||||
{
|
||||
var selector = GetSelector(parentId);
|
||||
|
||||
var fileDao = selector.GetFileDao(parentId);
|
||||
var result = fileDao
|
||||
.GetFiles(selector.ConvertId(parentId), orderBy, filterType, subjectGroup, subjectID, searchText, searchInContent, withSubfolders)
|
||||
.Where(r => r != null).ToList();
|
||||
|
||||
if (!result.Any()) return new List<File<string>>();
|
||||
|
||||
SetSharedProperty(result);
|
||||
|
||||
return result;
|
||||
}
|
||||
|
||||
public Stream GetFileStream(File<string> file)
|
||||
{
|
||||
return GetFileStream(file, 0);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Get stream of file
|
||||
/// </summary>
|
||||
/// <param name="file"></param>
|
||||
/// <param name="offset"></param>
|
||||
/// <returns>Stream</returns>
|
||||
public Stream GetFileStream(File<string> file, long offset)
|
||||
{
|
||||
if (file == null) throw new ArgumentNullException("file");
|
||||
var fileId = file.ID;
|
||||
var selector = GetSelector(fileId);
|
||||
file.ID = selector.ConvertId(fileId);
|
||||
|
||||
var fileDao = selector.GetFileDao(fileId);
|
||||
var stream = fileDao.GetFileStream(file, offset);
|
||||
file.ID = fileId; //Restore id
|
||||
return stream;
|
||||
}
|
||||
|
||||
public bool IsSupportedPreSignedUri(File<string> file)
|
||||
{
|
||||
if (file == null) throw new ArgumentNullException("file");
|
||||
var fileId = file.ID;
|
||||
var selector = GetSelector(fileId);
|
||||
file.ID = selector.ConvertId(fileId);
|
||||
|
||||
var fileDao = selector.GetFileDao(fileId);
|
||||
var isSupported = fileDao.IsSupportedPreSignedUri(file);
|
||||
file.ID = fileId; //Restore id
|
||||
return isSupported;
|
||||
}
|
||||
|
||||
public Uri GetPreSignedUri(File<string> file, TimeSpan expires)
|
||||
{
|
||||
if (file == null) throw new ArgumentNullException("file");
|
||||
var fileId = file.ID;
|
||||
var selector = GetSelector(fileId);
|
||||
file.ID = selector.ConvertId(fileId);
|
||||
|
||||
var fileDao = selector.GetFileDao(fileId);
|
||||
var streamUri = fileDao.GetPreSignedUri(file, expires);
|
||||
file.ID = fileId; //Restore id
|
||||
return streamUri;
|
||||
}
|
||||
|
||||
public File<string> SaveFile(File<string> file, Stream fileStream)
|
||||
{
|
||||
if (file == null) throw new ArgumentNullException("file");
|
||||
|
||||
var fileId = file.ID;
|
||||
var folderId = file.FolderID;
|
||||
|
||||
IDaoSelector selector;
|
||||
File<string> fileSaved = null;
|
||||
//Convert
|
||||
if (fileId != null)
|
||||
{
|
||||
selector = GetSelector(fileId);
|
||||
file.ID = selector.ConvertId(fileId);
|
||||
if (folderId != null)
|
||||
file.FolderID = selector.ConvertId(folderId);
|
||||
var fileDao = selector.GetFileDao(fileId);
|
||||
fileSaved = fileDao.SaveFile(file, fileStream);
|
||||
}
|
||||
else if (folderId != null)
|
||||
{
|
||||
selector = GetSelector(folderId);
|
||||
file.FolderID = selector.ConvertId(folderId);
|
||||
var fileDao = selector.GetFileDao(folderId);
|
||||
fileSaved = fileDao.SaveFile(file, fileStream);
|
||||
}
|
||||
|
||||
if (fileSaved != null)
|
||||
{
|
||||
return fileSaved;
|
||||
}
|
||||
throw new ArgumentException("No file id or folder id toFolderId determine provider");
|
||||
}
|
||||
|
||||
public File<string> ReplaceFileVersion(File<string> file, Stream fileStream)
|
||||
{
|
||||
if (file == null) throw new ArgumentNullException("file");
|
||||
if (file.ID == null) throw new ArgumentException("No file id or folder id toFolderId determine provider");
|
||||
|
||||
var fileId = file.ID;
|
||||
var folderId = file.FolderID;
|
||||
|
||||
//Convert
|
||||
var selector = GetSelector(fileId);
|
||||
|
||||
file.ID = selector.ConvertId(fileId);
|
||||
if (folderId != null) file.FolderID = selector.ConvertId(folderId);
|
||||
|
||||
var fileDao = selector.GetFileDao(fileId);
|
||||
return fileDao.ReplaceFileVersion(file, fileStream);
|
||||
}
|
||||
|
||||
public void DeleteFile(string fileId)
|
||||
{
|
||||
var selector = GetSelector(fileId);
|
||||
var fileDao = selector.GetFileDao(fileId);
|
||||
fileDao.DeleteFile(selector.ConvertId(fileId));
|
||||
}
|
||||
|
||||
public bool IsExist(string title, object folderId)
|
||||
{
|
||||
var selector = GetSelector(folderId.ToString());
|
||||
|
||||
var fileDao = selector.GetFileDao(folderId.ToString());
|
||||
return fileDao.IsExist(title, selector.ConvertId(folderId.ToString()));
|
||||
}
|
||||
|
||||
public TTo MoveFile<TTo>(string fileId, TTo toFolderId)
|
||||
{
|
||||
if (toFolderId is int tId)
|
||||
{
|
||||
return (TTo)Convert.ChangeType(MoveFile(fileId, tId), typeof(TTo));
|
||||
}
|
||||
|
||||
if (toFolderId is string tsId)
|
||||
{
|
||||
return (TTo)Convert.ChangeType(MoveFile(fileId, tsId), typeof(TTo));
|
||||
}
|
||||
|
||||
throw new NotImplementedException();
|
||||
}
|
||||
|
||||
public int MoveFile(string fileId, int toFolderId)
|
||||
{
|
||||
var movedFile = PerformCrossDaoFileCopy(fileId, toFolderId, true);
|
||||
return movedFile.ID;
|
||||
}
|
||||
|
||||
public string MoveFile(string fileId, string toFolderId)
|
||||
{
|
||||
var selector = GetSelector(fileId);
|
||||
if (IsCrossDao(fileId, toFolderId))
|
||||
{
|
||||
var movedFile = PerformCrossDaoFileCopy(fileId, toFolderId, true);
|
||||
return movedFile.ID;
|
||||
}
|
||||
|
||||
var fileDao = selector.GetFileDao(fileId);
|
||||
return fileDao.MoveFile(selector.ConvertId(fileId), selector.ConvertId(toFolderId));
|
||||
}
|
||||
|
||||
public File<TTo> CopyFile<TTo>(string fileId, TTo toFolderId)
|
||||
{
|
||||
if (toFolderId is int tId)
|
||||
{
|
||||
return CopyFile(fileId, tId) as File<TTo>;
|
||||
}
|
||||
|
||||
if (toFolderId is string tsId)
|
||||
{
|
||||
return CopyFile(fileId, tsId) as File<TTo>;
|
||||
}
|
||||
|
||||
throw new NotImplementedException();
|
||||
}
|
||||
|
||||
public File<int> CopyFile(string fileId, int toFolderId)
|
||||
{
|
||||
return PerformCrossDaoFileCopy(fileId, toFolderId, false);
|
||||
}
|
||||
|
||||
public File<string> CopyFile(string fileId, string toFolderId)
|
||||
{
|
||||
var selector = GetSelector(fileId);
|
||||
if (IsCrossDao(fileId, toFolderId))
|
||||
{
|
||||
return PerformCrossDaoFileCopy(fileId, toFolderId, false);
|
||||
}
|
||||
|
||||
var fileDao = selector.GetFileDao(fileId);
|
||||
return fileDao.CopyFile(selector.ConvertId(fileId), selector.ConvertId(toFolderId));
|
||||
}
|
||||
|
||||
public string FileRename(File<string> file, string newTitle)
|
||||
{
|
||||
var selector = GetSelector(file.ID);
|
||||
var fileDao = selector.GetFileDao(file.ID);
|
||||
return fileDao.FileRename(ConvertId(file), newTitle);
|
||||
}
|
||||
|
||||
public string UpdateComment(string fileId, int fileVersion, string comment)
|
||||
{
|
||||
var selector = GetSelector(fileId);
|
||||
|
||||
var fileDao = selector.GetFileDao(fileId);
|
||||
return fileDao.UpdateComment(selector.ConvertId(fileId), fileVersion, comment);
|
||||
}
|
||||
|
||||
public void CompleteVersion(string fileId, int fileVersion)
|
||||
{
|
||||
var selector = GetSelector(fileId);
|
||||
|
||||
var fileDao = selector.GetFileDao(fileId);
|
||||
fileDao.CompleteVersion(selector.ConvertId(fileId), fileVersion);
|
||||
}
|
||||
|
||||
public void ContinueVersion(string fileId, int fileVersion)
|
||||
{
|
||||
var selector = GetSelector(fileId);
|
||||
var fileDao = selector.GetFileDao(fileId);
|
||||
fileDao.ContinueVersion(selector.ConvertId(fileId), fileVersion);
|
||||
}
|
||||
|
||||
public bool UseTrashForRemove(File<string> file)
|
||||
{
|
||||
var selector = GetSelector(file.ID);
|
||||
var fileDao = selector.GetFileDao(file.ID);
|
||||
return fileDao.UseTrashForRemove(file);
|
||||
}
|
||||
|
||||
#region chunking
|
||||
|
||||
public ChunkedUploadSession<string> CreateUploadSession(File<string> file, long contentLength)
|
||||
{
|
||||
var fileDao = GetFileDao(file);
|
||||
return fileDao.CreateUploadSession(ConvertId(file), contentLength);
|
||||
}
|
||||
|
||||
public void UploadChunk(ChunkedUploadSession<string> uploadSession, Stream chunkStream, long chunkLength)
|
||||
{
|
||||
var fileDao = GetFileDao(uploadSession.File);
|
||||
uploadSession.File = ConvertId(uploadSession.File);
|
||||
fileDao.UploadChunk(uploadSession, chunkStream, chunkLength);
|
||||
}
|
||||
|
||||
public void AbortUploadSession(ChunkedUploadSession<string> uploadSession)
|
||||
{
|
||||
var fileDao = GetFileDao(uploadSession.File);
|
||||
uploadSession.File = ConvertId(uploadSession.File);
|
||||
fileDao.AbortUploadSession(uploadSession);
|
||||
}
|
||||
|
||||
private IFileDao<string> GetFileDao(File<string> file)
|
||||
{
|
||||
if (file.ID != null)
|
||||
return GetSelector(file.ID).GetFileDao(file.ID);
|
||||
|
||||
if (file.FolderID != null)
|
||||
return GetSelector(file.FolderID).GetFileDao(file.FolderID);
|
||||
|
||||
throw new ArgumentException("Can't create instance of dao for given file.", "file");
|
||||
}
|
||||
|
||||
private string ConvertId(string id)
|
||||
{
|
||||
return id != null ? GetSelector(id).ConvertId(id) : null;
|
||||
}
|
||||
|
||||
private File<string> ConvertId(File<string> file)
|
||||
{
|
||||
file.ID = ConvertId(file.ID);
|
||||
file.FolderID = ConvertId(file.FolderID);
|
||||
return file;
|
||||
}
|
||||
|
||||
#endregion
|
||||
|
||||
#region Only in TMFileDao
|
||||
|
||||
public void ReassignFiles(string[] fileIds, Guid newOwnerId)
|
||||
{
|
||||
throw new NotImplementedException();
|
||||
}
|
||||
|
||||
public List<File<string>> GetFiles(string[] parentIds, FilterType filterType, bool subjectGroup, Guid subjectID, string searchText, bool searchInContent)
|
||||
{
|
||||
throw new NotImplementedException();
|
||||
}
|
||||
|
||||
public IEnumerable<File<string>> Search(string text, bool bunch)
|
||||
{
|
||||
throw new NotImplementedException();
|
||||
}
|
||||
|
||||
public bool IsExistOnStorage(File<string> file)
|
||||
{
|
||||
throw new NotImplementedException();
|
||||
}
|
||||
|
||||
public void SaveEditHistory(File<string> file, string changes, Stream differenceStream)
|
||||
{
|
||||
throw new NotImplementedException();
|
||||
}
|
||||
|
||||
public List<EditHistory> GetEditHistory(DocumentServiceHelper documentServiceHelper, string fileId, int fileVersion)
|
||||
{
|
||||
throw new NotImplementedException();
|
||||
}
|
||||
|
||||
public Stream GetDifferenceStream(File<string> file)
|
||||
{
|
||||
throw new NotImplementedException();
|
||||
}
|
||||
|
||||
public bool ContainChanges(string fileId, int fileVersion)
|
||||
{
|
||||
throw new NotImplementedException();
|
||||
}
|
||||
|
||||
public string GetUniqFilePath(File<string> file, string fileTitle)
|
||||
{
|
||||
throw new NotImplementedException();
|
||||
}
|
||||
|
||||
#endregion
|
||||
}
|
||||
|
||||
public static class ProviderFileDaoExtention
|
||||
{
|
||||
public static DIHelper AddProviderFileDaoService(this DIHelper services)
|
||||
{
|
||||
services.TryAddScoped<IFileDao<string>, ProviderFileDao>();
|
||||
services.TryAddScoped<ProviderFileDao>();
|
||||
services.TryAddScoped<File<string>>();
|
||||
|
||||
return services
|
||||
.AddProviderDaoBaseService();
|
||||
}
|
||||
}
|
||||
}
|
429
products/ASC.Files/Server/Core/Thirdparty/ProviderDao/ProviderFolderDao.cs
vendored
Normal file
429
products/ASC.Files/Server/Core/Thirdparty/ProviderDao/ProviderFolderDao.cs
vendored
Normal file
@ -0,0 +1,429 @@
|
||||
/*
|
||||
*
|
||||
* (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;
|
||||
using System.Linq;
|
||||
using System.Threading;
|
||||
|
||||
using ASC.Common;
|
||||
using ASC.Core;
|
||||
using ASC.Files.Core;
|
||||
using ASC.Files.Core.Data;
|
||||
using ASC.Files.Core.Thirdparty;
|
||||
|
||||
namespace ASC.Files.Thirdparty.ProviderDao
|
||||
{
|
||||
internal class ProviderFolderDao : ProviderDaoBase, IFolderDao<string>
|
||||
{
|
||||
public ProviderFolderDao(
|
||||
IServiceProvider serviceProvider,
|
||||
TenantManager tenantManager,
|
||||
SecurityDao<string> securityDao,
|
||||
TagDao<string> tagDao,
|
||||
CrossDao crossDao)
|
||||
: base(serviceProvider, tenantManager, securityDao, tagDao, crossDao)
|
||||
{
|
||||
}
|
||||
|
||||
public Folder<string> GetFolder(string folderId)
|
||||
{
|
||||
var selector = GetSelector(folderId);
|
||||
var folderDao = selector.GetFolderDao(folderId);
|
||||
var result = folderDao.GetFolder(selector.ConvertId(folderId));
|
||||
|
||||
if (result != null)
|
||||
{
|
||||
SetSharedProperty(new[] { result });
|
||||
}
|
||||
|
||||
return result;
|
||||
}
|
||||
|
||||
public Folder<string> GetFolder(string title, string parentId)
|
||||
{
|
||||
var selector = GetSelector(parentId);
|
||||
return selector.GetFolderDao(parentId).GetFolder(title, selector.ConvertId(parentId));
|
||||
}
|
||||
|
||||
public Folder<string> GetRootFolder(string folderId)
|
||||
{
|
||||
var selector = GetSelector(folderId);
|
||||
var folderDao = selector.GetFolderDao(folderId);
|
||||
return folderDao.GetRootFolder(selector.ConvertId(folderId));
|
||||
}
|
||||
|
||||
public Folder<string> GetRootFolderByFile(string fileId)
|
||||
{
|
||||
var selector = GetSelector(fileId);
|
||||
var folderDao = selector.GetFolderDao(fileId);
|
||||
return folderDao.GetRootFolderByFile(selector.ConvertId(fileId));
|
||||
}
|
||||
|
||||
public List<Folder<string>> GetFolders(string parentId)
|
||||
{
|
||||
var selector = GetSelector(parentId);
|
||||
var folderDao = selector.GetFolderDao(parentId);
|
||||
return folderDao
|
||||
.GetFolders(selector.ConvertId(parentId))
|
||||
.Where(r => r != null)
|
||||
.ToList();
|
||||
}
|
||||
|
||||
public List<Folder<string>> GetFolders(string parentId, OrderBy orderBy, FilterType filterType, bool subjectGroup, Guid subjectID, string searchText, bool withSubfolders = false)
|
||||
{
|
||||
var selector = GetSelector(parentId);
|
||||
var folderDao = selector.GetFolderDao(parentId);
|
||||
var result = folderDao.GetFolders(selector.ConvertId(parentId), orderBy, filterType, subjectGroup, subjectID, searchText, withSubfolders)
|
||||
.Where(r => r != null).ToList();
|
||||
|
||||
if (!result.Any()) return new List<Folder<string>>();
|
||||
|
||||
SetSharedProperty(result);
|
||||
|
||||
return result;
|
||||
}
|
||||
|
||||
public List<Folder<string>> GetFolders(string[] folderIds, FilterType filterType = FilterType.None, bool subjectGroup = false, Guid? subjectID = null, string searchText = "", bool searchSubfolders = false, bool checkShare = true)
|
||||
{
|
||||
var result = Enumerable.Empty<Folder<string>>();
|
||||
|
||||
foreach (var selector in GetSelectors())
|
||||
{
|
||||
var selectorLocal = selector;
|
||||
var matchedIds = folderIds.Where(selectorLocal.IsMatch).ToList();
|
||||
|
||||
if (!matchedIds.Any()) continue;
|
||||
|
||||
result = result.Concat(matchedIds.GroupBy(selectorLocal.GetIdCode)
|
||||
.SelectMany(matchedId =>
|
||||
{
|
||||
var folderDao = selectorLocal.GetFolderDao(matchedId.FirstOrDefault());
|
||||
return folderDao
|
||||
.GetFolders(matchedId.Select(selectorLocal.ConvertId).ToArray(),
|
||||
filterType, subjectGroup, subjectID, searchText, searchSubfolders, checkShare);
|
||||
})
|
||||
.Where(r => r != null));
|
||||
}
|
||||
|
||||
return result.Distinct().ToList();
|
||||
}
|
||||
|
||||
public List<Folder<string>> GetParentFolders(string folderId)
|
||||
{
|
||||
var selector = GetSelector(folderId);
|
||||
var folderDao = selector.GetFolderDao(folderId);
|
||||
return folderDao.GetParentFolders(selector.ConvertId(folderId));
|
||||
}
|
||||
|
||||
public string SaveFolder(Folder<string> folder)
|
||||
{
|
||||
if (folder == null) throw new ArgumentNullException("folder");
|
||||
|
||||
if (folder.ID != null)
|
||||
{
|
||||
var folderId = folder.ID;
|
||||
var selector = GetSelector(folderId);
|
||||
folder.ID = selector.ConvertId(folderId);
|
||||
var folderDao = selector.GetFolderDao(folderId);
|
||||
var newFolderId = folderDao.SaveFolder(folder);
|
||||
folder.ID = folderId;
|
||||
return newFolderId;
|
||||
}
|
||||
if (folder.ParentFolderID != null)
|
||||
{
|
||||
var folderId = folder.ParentFolderID;
|
||||
var selector = GetSelector(folderId);
|
||||
folder.ParentFolderID = selector.ConvertId(folderId);
|
||||
var folderDao = selector.GetFolderDao(folderId);
|
||||
var newFolderId = folderDao.SaveFolder(folder);
|
||||
folder.ParentFolderID = folderId;
|
||||
return newFolderId;
|
||||
|
||||
}
|
||||
throw new ArgumentException("No folder id or parent folder id to determine provider");
|
||||
}
|
||||
|
||||
public void DeleteFolder(string folderId)
|
||||
{
|
||||
var selector = GetSelector(folderId);
|
||||
var folderDao = selector.GetFolderDao(folderId);
|
||||
folderDao.DeleteFolder(selector.ConvertId(folderId));
|
||||
}
|
||||
|
||||
public TTo MoveFolder<TTo>(string folderId, TTo toFolderId, CancellationToken? cancellationToken)
|
||||
{
|
||||
if (toFolderId is int tId)
|
||||
{
|
||||
return (TTo)Convert.ChangeType(MoveFolder(folderId, tId, cancellationToken), typeof(TTo));
|
||||
}
|
||||
|
||||
if (toFolderId is string tsId)
|
||||
{
|
||||
return (TTo)Convert.ChangeType(MoveFolder(folderId, tsId, cancellationToken), typeof(TTo));
|
||||
}
|
||||
|
||||
throw new NotImplementedException();
|
||||
}
|
||||
|
||||
public string MoveFolder(string folderId, string toFolderId, CancellationToken? cancellationToken)
|
||||
{
|
||||
var selector = GetSelector(folderId);
|
||||
if (IsCrossDao(folderId, toFolderId))
|
||||
{
|
||||
var newFolder = PerformCrossDaoFolderCopy(folderId, toFolderId, true, cancellationToken);
|
||||
return newFolder?.ID;
|
||||
}
|
||||
var folderDao = selector.GetFolderDao(folderId);
|
||||
return folderDao.MoveFolder(selector.ConvertId(folderId), selector.ConvertId(toFolderId), null);
|
||||
}
|
||||
|
||||
public int MoveFolder(string folderId, int toFolderId, CancellationToken? cancellationToken)
|
||||
{
|
||||
var newFolder = PerformCrossDaoFolderCopy(folderId, toFolderId, true, cancellationToken);
|
||||
return newFolder.ID;
|
||||
}
|
||||
|
||||
public Folder<TTo> CopyFolder<TTo>(string folderId, TTo toFolderId, CancellationToken? cancellationToken)
|
||||
{
|
||||
if (toFolderId is int tId)
|
||||
{
|
||||
return CopyFolder(folderId, tId, cancellationToken) as Folder<TTo>;
|
||||
}
|
||||
|
||||
if (toFolderId is string tsId)
|
||||
{
|
||||
return CopyFolder(folderId, tsId, cancellationToken) as Folder<TTo>;
|
||||
}
|
||||
|
||||
throw new NotImplementedException();
|
||||
}
|
||||
|
||||
public Folder<int> CopyFolder(string folderId, int toFolderId, CancellationToken? cancellationToken)
|
||||
{
|
||||
return PerformCrossDaoFolderCopy(folderId, toFolderId, false, cancellationToken);
|
||||
}
|
||||
|
||||
public Folder<string> CopyFolder(string folderId, string toFolderId, CancellationToken? cancellationToken)
|
||||
{
|
||||
var selector = GetSelector(folderId);
|
||||
var folderDao = selector.GetFolderDao(folderId);
|
||||
return IsCrossDao(folderId, toFolderId)
|
||||
? PerformCrossDaoFolderCopy(folderId, toFolderId, false, cancellationToken)
|
||||
: folderDao.CopyFolder(selector.ConvertId(folderId), selector.ConvertId(toFolderId), null);
|
||||
}
|
||||
|
||||
public IDictionary<string, string> CanMoveOrCopy<TTo>(string[] folderIds, TTo to)
|
||||
{
|
||||
if (to is int tId)
|
||||
{
|
||||
return CanMoveOrCopy(folderIds, tId);
|
||||
}
|
||||
|
||||
if (to is string tsId)
|
||||
{
|
||||
return CanMoveOrCopy(folderIds, tsId);
|
||||
}
|
||||
|
||||
throw new NotImplementedException();
|
||||
}
|
||||
|
||||
public IDictionary<string, string> CanMoveOrCopy(string[] folderIds, int to)
|
||||
{
|
||||
return new Dictionary<string, string>();
|
||||
}
|
||||
|
||||
public IDictionary<string, string> CanMoveOrCopy(string[] folderIds, string to)
|
||||
{
|
||||
if (!folderIds.Any()) return new Dictionary<string, string>();
|
||||
|
||||
var selector = GetSelector(to);
|
||||
var matchedIds = folderIds.Where(selector.IsMatch).ToArray();
|
||||
|
||||
if (!matchedIds.Any()) return new Dictionary<string, string>();
|
||||
|
||||
var folderDao = selector.GetFolderDao(matchedIds.FirstOrDefault());
|
||||
return folderDao.CanMoveOrCopy(matchedIds, to);
|
||||
}
|
||||
|
||||
public string RenameFolder(Folder<string> folder, string newTitle)
|
||||
{
|
||||
var folderId = folder.ID;
|
||||
var selector = GetSelector(folderId);
|
||||
folder.ID = selector.ConvertId(folderId);
|
||||
folder.ParentFolderID = selector.ConvertId(folder.ParentFolderID);
|
||||
var folderDao = selector.GetFolderDao(folderId);
|
||||
return folderDao.RenameFolder(folder, newTitle);
|
||||
}
|
||||
|
||||
public int GetItemsCount(string folderId)
|
||||
{
|
||||
var selector = GetSelector(folderId);
|
||||
var folderDao = selector.GetFolderDao(folderId);
|
||||
return folderDao.GetItemsCount(selector.ConvertId(folderId));
|
||||
}
|
||||
|
||||
public bool IsEmpty(string folderId)
|
||||
{
|
||||
var selector = GetSelector(folderId);
|
||||
var folderDao = selector.GetFolderDao(folderId);
|
||||
return folderDao.IsEmpty(selector.ConvertId(folderId));
|
||||
}
|
||||
|
||||
public bool UseTrashForRemove(Folder<string> folder)
|
||||
{
|
||||
var selector = GetSelector(folder.ID);
|
||||
var folderDao = selector.GetFolderDao(folder.ID);
|
||||
return folderDao.UseTrashForRemove(folder);
|
||||
}
|
||||
|
||||
public bool UseRecursiveOperation<TTo>(string folderId, TTo toRootFolderId)
|
||||
{
|
||||
return false;
|
||||
}
|
||||
|
||||
public bool UseRecursiveOperation(string folderId, int toRootFolderId)
|
||||
{
|
||||
return false;
|
||||
}
|
||||
|
||||
public bool UseRecursiveOperation(string folderId, string toRootFolderId)
|
||||
{
|
||||
var selector = GetSelector(folderId);
|
||||
bool useRecursive;
|
||||
|
||||
var folderDao = selector.GetFolderDao(folderId);
|
||||
useRecursive = folderDao.UseRecursiveOperation(folderId, null);
|
||||
|
||||
if (toRootFolderId != null)
|
||||
{
|
||||
var toFolderSelector = GetSelector(toRootFolderId);
|
||||
|
||||
var folderDao1 = toFolderSelector.GetFolderDao(toRootFolderId);
|
||||
useRecursive = useRecursive && folderDao1.UseRecursiveOperation(folderId, toFolderSelector.ConvertId(toRootFolderId));
|
||||
}
|
||||
return useRecursive;
|
||||
}
|
||||
|
||||
public bool CanCalculateSubitems(string entryId)
|
||||
{
|
||||
var selector = GetSelector(entryId);
|
||||
var folderDao = selector.GetFolderDao(entryId);
|
||||
return folderDao.CanCalculateSubitems(entryId);
|
||||
}
|
||||
|
||||
public long GetMaxUploadSize(string folderId, bool chunkedUpload)
|
||||
{
|
||||
var selector = GetSelector(folderId);
|
||||
var folderDao = selector.GetFolderDao(folderId);
|
||||
var storageMaxUploadSize = folderDao.GetMaxUploadSize(selector.ConvertId(folderId), chunkedUpload);
|
||||
|
||||
if (storageMaxUploadSize == -1 || storageMaxUploadSize == long.MaxValue)
|
||||
{
|
||||
storageMaxUploadSize = 1024L * 1024L * 1024L;
|
||||
}
|
||||
|
||||
return storageMaxUploadSize;
|
||||
}
|
||||
|
||||
#region Only for TMFolderDao
|
||||
|
||||
public void ReassignFolders(string[] folderIds, Guid newOwnerId)
|
||||
{
|
||||
throw new NotImplementedException();
|
||||
}
|
||||
|
||||
public IEnumerable<Folder<string>> Search(string text, bool bunch)
|
||||
{
|
||||
throw new NotImplementedException();
|
||||
}
|
||||
|
||||
public string GetFolderID(string module, string bunch, string data, bool createIfNotExists)
|
||||
{
|
||||
throw new NotImplementedException();
|
||||
}
|
||||
|
||||
public IEnumerable<string> GetFolderIDs(string module, string bunch, IEnumerable<string> data, bool createIfNotExists)
|
||||
{
|
||||
throw new NotImplementedException();
|
||||
}
|
||||
|
||||
public string GetFolderIDCommon(bool createIfNotExists)
|
||||
{
|
||||
throw new NotImplementedException();
|
||||
}
|
||||
|
||||
public string GetFolderIDProjects(bool createIfNotExists)
|
||||
{
|
||||
throw new NotImplementedException();
|
||||
}
|
||||
|
||||
public string GetFolderIDPhotos(bool createIfNotExists)
|
||||
{
|
||||
throw new NotImplementedException();
|
||||
}
|
||||
|
||||
public string GetBunchObjectID(string folderID)
|
||||
{
|
||||
throw new NotImplementedException();
|
||||
}
|
||||
|
||||
public Dictionary<string, string> GetBunchObjectIDs(List<string> folderIDs)
|
||||
{
|
||||
throw new NotImplementedException();
|
||||
}
|
||||
|
||||
public string GetFolderIDUser(bool createIfNotExists, Guid? userId = null)
|
||||
{
|
||||
throw new NotImplementedException();
|
||||
}
|
||||
|
||||
public string GetFolderIDShare(bool createIfNotExists)
|
||||
{
|
||||
throw new NotImplementedException();
|
||||
}
|
||||
|
||||
public string GetFolderIDTrash(bool createIfNotExists, Guid? userId = null)
|
||||
{
|
||||
throw new NotImplementedException();
|
||||
}
|
||||
|
||||
#endregion
|
||||
}
|
||||
|
||||
public static class ProviderFolderDaoExtention
|
||||
{
|
||||
public static DIHelper AddProviderFolderDaoService(this DIHelper services)
|
||||
{
|
||||
services.TryAddScoped<IFolderDao<string>, ProviderFolderDao>();
|
||||
services.TryAddScoped<ProviderFolderDao>();
|
||||
services.TryAddScoped<Folder<string>>();
|
||||
|
||||
return services
|
||||
.AddProviderDaoBaseService();
|
||||
}
|
||||
}
|
||||
}
|
210
products/ASC.Files/Server/Core/Thirdparty/ProviderDao/ProviderSecutiryDao.cs
vendored
Normal file
210
products/ASC.Files/Server/Core/Thirdparty/ProviderDao/ProviderSecutiryDao.cs
vendored
Normal file
@ -0,0 +1,210 @@
|
||||
/*
|
||||
*
|
||||
* (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;
|
||||
using System.Linq;
|
||||
|
||||
using ASC.Common;
|
||||
using ASC.Core;
|
||||
using ASC.Files.Core;
|
||||
using ASC.Files.Core.Data;
|
||||
using ASC.Files.Core.Security;
|
||||
using ASC.Files.Core.Thirdparty;
|
||||
|
||||
using Microsoft.Extensions.DependencyInjection;
|
||||
|
||||
namespace ASC.Files.Thirdparty.ProviderDao
|
||||
{
|
||||
internal class ProviderSecurityDao : ProviderDaoBase, ISecurityDao<string>
|
||||
{
|
||||
public ProviderSecurityDao(
|
||||
IServiceProvider serviceProvider,
|
||||
TenantManager tenantManager,
|
||||
SecurityDao<string> securityDao,
|
||||
TagDao<string> tagDao,
|
||||
CrossDao crossDao)
|
||||
: base(serviceProvider, tenantManager, securityDao, tagDao, crossDao)
|
||||
{
|
||||
}
|
||||
|
||||
public void SetShare(FileShareRecord r)
|
||||
{
|
||||
SecurityDao.SetShare(r);
|
||||
}
|
||||
|
||||
public IEnumerable<FileShareRecord> GetShares(IEnumerable<FileEntry<string>> entries)
|
||||
{
|
||||
var result = new List<FileShareRecord>();
|
||||
|
||||
var files = entries.Where(x => x.FileEntryType == FileEntryType.File).ToArray();
|
||||
var folders = entries.Where(x => x.FileEntryType == FileEntryType.Folder).ToList();
|
||||
|
||||
if (files.Any())
|
||||
{
|
||||
var folderIds = files.Select(x => ((File<string>)x).FolderID).Distinct();
|
||||
foreach (var folderId in folderIds)
|
||||
{
|
||||
GetFoldersForShare(folderId, folders);
|
||||
}
|
||||
|
||||
var pureShareRecords = SecurityDao.GetPureShareRecords(files);
|
||||
if (pureShareRecords != null)
|
||||
{
|
||||
foreach (var pureShareRecord in pureShareRecords)
|
||||
{
|
||||
if (pureShareRecord == null) continue;
|
||||
pureShareRecord.Level = -1;
|
||||
result.Add(pureShareRecord);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
result.AddRange(GetShareForFolders(folders));
|
||||
|
||||
return result;
|
||||
}
|
||||
|
||||
public IEnumerable<FileShareRecord> GetShares(FileEntry<string> entry)
|
||||
{
|
||||
var result = new List<FileShareRecord>();
|
||||
|
||||
if (entry == null) return result;
|
||||
|
||||
|
||||
var folders = new List<FileEntry<string>>();
|
||||
if (entry is Folder<string> entryFolder)
|
||||
{
|
||||
folders.Add(entryFolder);
|
||||
}
|
||||
|
||||
if (entry is File<string> file)
|
||||
{
|
||||
GetFoldersForShare(file.FolderID, folders);
|
||||
|
||||
var pureShareRecords = SecurityDao.GetPureShareRecords(entry);
|
||||
if (pureShareRecords != null)
|
||||
{
|
||||
foreach (var pureShareRecord in pureShareRecords)
|
||||
{
|
||||
if (pureShareRecord == null) continue;
|
||||
pureShareRecord.Level = -1;
|
||||
result.Add(pureShareRecord);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
result.AddRange(GetShareForFolders(folders));
|
||||
|
||||
return result;
|
||||
}
|
||||
|
||||
private void GetFoldersForShare(string folderId, ICollection<FileEntry<string>> folders)
|
||||
{
|
||||
var selector = GetSelector(folderId);
|
||||
var folderDao = selector.GetFolderDao(folderId);
|
||||
if (folderDao == null) return;
|
||||
|
||||
var folder = folderDao.GetFolder(selector.ConvertId(folderId));
|
||||
if (folder != null) folders.Add(folder);
|
||||
}
|
||||
|
||||
private List<FileShareRecord> GetShareForFolders(IReadOnlyCollection<FileEntry<string>> folders)
|
||||
{
|
||||
if (!folders.Any()) return new List<FileShareRecord>();
|
||||
|
||||
var result = new List<FileShareRecord>();
|
||||
|
||||
foreach (var folder in folders)
|
||||
{
|
||||
var selector = GetSelector(folder.ID);
|
||||
var folderDao = selector.GetFolderDao(folder.ID);
|
||||
if (folderDao == null) continue;
|
||||
|
||||
var parentFolders = folderDao.GetParentFolders(selector.ConvertId(folder.ID));
|
||||
if (parentFolders == null || !parentFolders.Any()) continue;
|
||||
|
||||
parentFolders.Reverse();
|
||||
var pureShareRecords = GetPureShareRecords(parentFolders);
|
||||
if (pureShareRecords == null) continue;
|
||||
|
||||
foreach (var pureShareRecord in pureShareRecords)
|
||||
{
|
||||
if (pureShareRecord == null) continue;
|
||||
var f = ServiceProvider.GetService<Folder<string>>();
|
||||
f.ID = pureShareRecord.EntryId.ToString();
|
||||
|
||||
pureShareRecord.Level = parentFolders.IndexOf(f);
|
||||
pureShareRecord.EntryId = folder.ID;
|
||||
result.Add(pureShareRecord);
|
||||
}
|
||||
}
|
||||
|
||||
return result;
|
||||
}
|
||||
|
||||
public void RemoveSubject(Guid subject)
|
||||
{
|
||||
SecurityDao.RemoveSubject(subject);
|
||||
}
|
||||
|
||||
public IEnumerable<FileShareRecord> GetShares(IEnumerable<Guid> subjects)
|
||||
{
|
||||
return SecurityDao.GetShares(subjects);
|
||||
}
|
||||
|
||||
public IEnumerable<FileShareRecord> GetPureShareRecords(IEnumerable<FileEntry<string>> entries)
|
||||
{
|
||||
return SecurityDao.GetPureShareRecords(entries);
|
||||
}
|
||||
|
||||
public IEnumerable<FileShareRecord> GetPureShareRecords(FileEntry<string> entry)
|
||||
{
|
||||
return SecurityDao.GetPureShareRecords(entry);
|
||||
}
|
||||
|
||||
public void DeleteShareRecords(IEnumerable<FileShareRecord> records)
|
||||
{
|
||||
SecurityDao.DeleteShareRecords(records);
|
||||
}
|
||||
|
||||
public bool IsShared(object entryId, FileEntryType type)
|
||||
{
|
||||
return SecurityDao.IsShared(entryId, type);
|
||||
}
|
||||
}
|
||||
|
||||
public static class ProviderSecurityDaoExtention
|
||||
{
|
||||
public static DIHelper AddProviderSecurityDaoService(this DIHelper services)
|
||||
{
|
||||
services.TryAddScoped<ISecurityDao<string>, ProviderSecurityDao>();
|
||||
|
||||
return services
|
||||
.AddProviderDaoBaseService();
|
||||
}
|
||||
}
|
||||
}
|
142
products/ASC.Files/Server/Core/Thirdparty/ProviderDao/ProviderTagDao.cs
vendored
Normal file
142
products/ASC.Files/Server/Core/Thirdparty/ProviderDao/ProviderTagDao.cs
vendored
Normal file
@ -0,0 +1,142 @@
|
||||
/*
|
||||
*
|
||||
* (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;
|
||||
|
||||
using ASC.Common;
|
||||
using ASC.Core;
|
||||
using ASC.Files.Core;
|
||||
using ASC.Files.Core.Data;
|
||||
using ASC.Files.Core.Thirdparty;
|
||||
|
||||
namespace ASC.Files.Thirdparty.ProviderDao
|
||||
{
|
||||
internal class ProviderTagDao : ProviderDaoBase, ITagDao<string>
|
||||
{
|
||||
public ProviderTagDao(
|
||||
IServiceProvider serviceProvider,
|
||||
TenantManager tenantManager,
|
||||
SecurityDao<string> securityDao,
|
||||
TagDao<string> tagDao,
|
||||
CrossDao crossDao)
|
||||
: base(serviceProvider, tenantManager, securityDao, tagDao, crossDao)
|
||||
{
|
||||
}
|
||||
|
||||
public IEnumerable<Tag> GetTags(TagType tagType, IEnumerable<FileEntry<string>> fileEntries)
|
||||
{
|
||||
return TagDao.GetTags(tagType, fileEntries);
|
||||
}
|
||||
|
||||
public IEnumerable<Tag> GetNewTags(Guid subject, Folder<string> parentFolder, bool deepSearch)
|
||||
{
|
||||
return GetSelector(parentFolder.ID)
|
||||
.GetTagDao(parentFolder.ID)
|
||||
.GetNewTags(subject, parentFolder, deepSearch);
|
||||
}
|
||||
|
||||
#region Only for Teamlab Documents
|
||||
|
||||
public IEnumerable<Tag> GetNewTags(Guid subject, IEnumerable<FileEntry<string>> fileEntries)
|
||||
{
|
||||
return TagDao.GetNewTags(subject, fileEntries);
|
||||
}
|
||||
|
||||
public IEnumerable<Tag> GetNewTags(Guid subject, FileEntry<string> fileEntry)
|
||||
{
|
||||
return TagDao.GetNewTags(subject, fileEntry);
|
||||
}
|
||||
|
||||
public IEnumerable<Tag> GetTags(Guid owner, TagType tagType)
|
||||
{
|
||||
return TagDao.GetTags(owner, tagType);
|
||||
}
|
||||
|
||||
public IEnumerable<Tag> GetTags(string name, TagType tagType)
|
||||
{
|
||||
return TagDao.GetTags(name, tagType);
|
||||
}
|
||||
|
||||
public IEnumerable<Tag> GetTags(string[] names, TagType tagType)
|
||||
{
|
||||
return TagDao.GetTags(names, tagType);
|
||||
}
|
||||
|
||||
|
||||
public IEnumerable<Tag> SaveTags(IEnumerable<Tag> tag)
|
||||
{
|
||||
return TagDao.SaveTags(tag);
|
||||
}
|
||||
|
||||
public IEnumerable<Tag> SaveTags(Tag tag)
|
||||
{
|
||||
return TagDao.SaveTags(tag);
|
||||
}
|
||||
|
||||
public void UpdateNewTags(IEnumerable<Tag> tag)
|
||||
{
|
||||
TagDao.UpdateNewTags(tag);
|
||||
}
|
||||
|
||||
public void UpdateNewTags(Tag tag)
|
||||
{
|
||||
TagDao.UpdateNewTags(tag);
|
||||
}
|
||||
|
||||
public void RemoveTags(IEnumerable<Tag> tag)
|
||||
{
|
||||
TagDao.RemoveTags(tag);
|
||||
}
|
||||
|
||||
public void RemoveTags(Tag tag)
|
||||
{
|
||||
TagDao.RemoveTags(tag);
|
||||
}
|
||||
|
||||
public IEnumerable<Tag> GetTags(string entryID, FileEntryType entryType, TagType tagType)
|
||||
{
|
||||
return TagDao.GetTags(entryID, entryType, tagType);
|
||||
}
|
||||
|
||||
#endregion
|
||||
|
||||
public void Dispose()
|
||||
{
|
||||
}
|
||||
}
|
||||
|
||||
public static class ProviderTagDaoExtention
|
||||
{
|
||||
public static DIHelper AddProviderTagDaoService(this DIHelper services)
|
||||
{
|
||||
services.TryAddScoped<ITagDao<string>, ProviderTagDao>();
|
||||
|
||||
return services
|
||||
.AddProviderDaoBaseService();
|
||||
}
|
||||
}
|
||||
}
|
178
products/ASC.Files/Server/Core/Thirdparty/RegexDaoSelectorBase.cs
vendored
Normal file
178
products/ASC.Files/Server/Core/Thirdparty/RegexDaoSelectorBase.cs
vendored
Normal file
@ -0,0 +1,178 @@
|
||||
/*
|
||||
*
|
||||
* (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;
|
||||
using System.Text.RegularExpressions;
|
||||
|
||||
using ASC.Files.Core;
|
||||
using ASC.Files.Core.Security;
|
||||
using ASC.Files.Core.Thirdparty;
|
||||
|
||||
using Microsoft.Extensions.DependencyInjection;
|
||||
|
||||
namespace ASC.Files.Thirdparty
|
||||
{
|
||||
internal abstract class RegexDaoSelectorBase<T> : IDaoSelector<T> where T : class, IProviderInfo
|
||||
{
|
||||
public IServiceProvider ServiceProvider { get; }
|
||||
public IDaoFactory DaoFactory { get; }
|
||||
public Regex Selector { get; set; }
|
||||
protected internal abstract string Name { get; }
|
||||
protected internal abstract string Id { get; }
|
||||
|
||||
private Dictionary<string, ThirdPartyProviderDao<T>> Providers { get; set; }
|
||||
|
||||
protected RegexDaoSelectorBase(
|
||||
IServiceProvider serviceProvider,
|
||||
IDaoFactory daoFactory)
|
||||
{
|
||||
ServiceProvider = serviceProvider;
|
||||
DaoFactory = daoFactory;
|
||||
Selector = new Regex(@"^" + Id + @"-(?'id'\d+)(-(?'path'.*)){0,1}$", RegexOptions.Singleline | RegexOptions.Compiled);
|
||||
Providers = new Dictionary<string, ThirdPartyProviderDao<T>>();
|
||||
}
|
||||
|
||||
public virtual string ConvertId(string id)
|
||||
{
|
||||
try
|
||||
{
|
||||
if (id == null) return null;
|
||||
|
||||
var match = Selector.Match(id);
|
||||
if (match.Success)
|
||||
{
|
||||
return match.Groups["path"].Value.Replace('|', '/');
|
||||
}
|
||||
throw new ArgumentException($"Id is not a {Name} id");
|
||||
}
|
||||
catch (Exception fe)
|
||||
{
|
||||
throw new FormatException("Can not convert id: " + id, fe);
|
||||
}
|
||||
}
|
||||
|
||||
public string GetIdCode(string id)
|
||||
{
|
||||
if (id != null)
|
||||
{
|
||||
var match = Selector.Match(id);
|
||||
if (match.Success)
|
||||
{
|
||||
return match.Groups["id"].Value;
|
||||
}
|
||||
}
|
||||
throw new ArgumentException($"Id is not a {Name} id");
|
||||
}
|
||||
|
||||
public virtual bool IsMatch(string id)
|
||||
{
|
||||
return id != null && Selector.IsMatch(id);
|
||||
}
|
||||
|
||||
public virtual ISecurityDao<string> GetSecurityDao<T1>(string id) where T1 : ThirdPartyProviderDao<T>, ISecurityDao<string>
|
||||
{
|
||||
return GetDao<T1>(id);
|
||||
}
|
||||
|
||||
public virtual IFileDao<string> GetFileDao<T1>(string id) where T1 : ThirdPartyProviderDao<T>, IFileDao<string>
|
||||
{
|
||||
return GetDao<T1>(id);
|
||||
}
|
||||
|
||||
public virtual ITagDao<string> GetTagDao<T1>(string id) where T1 : ThirdPartyProviderDao<T>, ITagDao<string>
|
||||
{
|
||||
return GetDao<T1>(id);
|
||||
}
|
||||
|
||||
public virtual IFolderDao<string> GetFolderDao<T1>(string id) where T1 : ThirdPartyProviderDao<T>, IFolderDao<string>
|
||||
{
|
||||
return GetDao<T1>(id);
|
||||
}
|
||||
|
||||
private T1 GetDao<T1>(string id) where T1 : ThirdPartyProviderDao<T>
|
||||
{
|
||||
var providerKey = $"{id}{typeof(T1)}";
|
||||
if (Providers.ContainsKey(providerKey)) return (T1)Providers[providerKey];
|
||||
|
||||
var res = ServiceProvider.GetService<T1>();
|
||||
|
||||
res.Init(GetInfo(id), this);
|
||||
|
||||
Providers.Add(providerKey, res);
|
||||
|
||||
return res;
|
||||
}
|
||||
|
||||
|
||||
internal BaseProviderInfo<T> GetInfo(string objectId)
|
||||
{
|
||||
if (objectId == null) throw new ArgumentNullException("objectId");
|
||||
var id = objectId;
|
||||
var match = Selector.Match(id);
|
||||
if (match.Success)
|
||||
{
|
||||
var providerInfo = GetProviderInfo(Convert.ToInt32(match.Groups["id"].Value));
|
||||
|
||||
return new BaseProviderInfo<T>
|
||||
{
|
||||
Path = match.Groups["path"].Value,
|
||||
ProviderInfo = providerInfo,
|
||||
PathPrefix = Id + "-" + match.Groups["id"].Value
|
||||
};
|
||||
}
|
||||
throw new ArgumentException($"Id is not {Name} id");
|
||||
}
|
||||
|
||||
public void RenameProvider(T provider, string newTitle)
|
||||
{
|
||||
var dbDao = ServiceProvider.GetService<CachedProviderAccountDao>();
|
||||
dbDao.UpdateProviderInfo(provider.ID, newTitle, null, provider.RootFolderType);
|
||||
provider.UpdateTitle(newTitle); //This will update cached version too
|
||||
}
|
||||
|
||||
protected virtual T GetProviderInfo(int linkId)
|
||||
{
|
||||
var dbDao = DaoFactory.ProviderDao;
|
||||
try
|
||||
{
|
||||
return dbDao.GetProviderInfo(linkId) as T;
|
||||
}
|
||||
catch (InvalidOperationException)
|
||||
{
|
||||
throw new ArgumentException("Provider id not found or you have no access");
|
||||
}
|
||||
}
|
||||
|
||||
public void Dispose()
|
||||
{
|
||||
foreach (var p in Providers)
|
||||
{
|
||||
p.Value.Dispose();
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
150
products/ASC.Files/Server/Core/Thirdparty/SharePoint/SharePointDaoBase.cs
vendored
Normal file
150
products/ASC.Files/Server/Core/Thirdparty/SharePoint/SharePointDaoBase.cs
vendored
Normal file
@ -0,0 +1,150 @@
|
||||
/*
|
||||
*
|
||||
* (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.Linq;
|
||||
using System.Text.RegularExpressions;
|
||||
|
||||
using ASC.Common.Logging;
|
||||
using ASC.Core;
|
||||
using ASC.Core.Common.EF;
|
||||
using ASC.Core.Tenants;
|
||||
using ASC.Files.Core.EF;
|
||||
using ASC.Web.Core.Files;
|
||||
using ASC.Web.Studio.Core;
|
||||
|
||||
using Microsoft.Extensions.Options;
|
||||
|
||||
using Folder = Microsoft.SharePoint.Client.Folder;
|
||||
|
||||
namespace ASC.Files.Thirdparty.SharePoint
|
||||
{
|
||||
internal class SharePointDaoBase : ThirdPartyProviderDao<SharePointProviderInfo>
|
||||
{
|
||||
public override string Id { get => "spoint"; }
|
||||
|
||||
public SharePointDaoBase(IServiceProvider serviceProvider, UserManager userManager, TenantManager tenantManager, TenantUtil tenantUtil, DbContextManager<FilesDbContext> dbContextManager, SetupInfo setupInfo, IOptionsMonitor<ILog> monitor, FileUtility fileUtility) : base(serviceProvider, userManager, tenantManager, tenantUtil, dbContextManager, setupInfo, monitor, fileUtility)
|
||||
{
|
||||
}
|
||||
|
||||
protected string GetAvailableTitle(string requestTitle, Folder parentFolderID, Func<string, Folder, bool> isExist)
|
||||
{
|
||||
if (!isExist(requestTitle, parentFolderID)) return requestTitle;
|
||||
|
||||
var re = new Regex(@"( \(((?<index>[0-9])+)\)(\.[^\.]*)?)$");
|
||||
var match = re.Match(requestTitle);
|
||||
|
||||
if (!match.Success)
|
||||
{
|
||||
var insertIndex = requestTitle.Length;
|
||||
if (requestTitle.LastIndexOf(".", StringComparison.Ordinal) != -1)
|
||||
{
|
||||
insertIndex = requestTitle.LastIndexOf(".", StringComparison.Ordinal);
|
||||
}
|
||||
requestTitle = requestTitle.Insert(insertIndex, " (1)");
|
||||
}
|
||||
|
||||
while (isExist(requestTitle, parentFolderID))
|
||||
{
|
||||
requestTitle = re.Replace(requestTitle, MatchEvaluator);
|
||||
}
|
||||
return requestTitle;
|
||||
}
|
||||
|
||||
private static string MatchEvaluator(Match match)
|
||||
{
|
||||
var index = Convert.ToInt32(match.Groups[2].Value);
|
||||
var staticText = match.Value.Substring(string.Format(" ({0})", index).Length);
|
||||
return string.Format(" ({0}){1}", index + 1, staticText);
|
||||
}
|
||||
|
||||
protected void UpdatePathInDB(string oldValue, string newValue)
|
||||
{
|
||||
if (oldValue.Equals(newValue)) return;
|
||||
|
||||
using (var tx = FilesDbContext.Database.BeginTransaction())
|
||||
{
|
||||
var oldIDs = Query(FilesDbContext.ThirdpartyIdMapping)
|
||||
.Where(r => r.Id.StartsWith(oldValue))
|
||||
.Select(r => r.Id)
|
||||
.ToList();
|
||||
|
||||
foreach (var oldID in oldIDs)
|
||||
{
|
||||
var oldHashID = MappingID(oldID);
|
||||
var newID = oldID.Replace(oldValue, newValue);
|
||||
var newHashID = MappingID(newID);
|
||||
|
||||
var mappingForUpdate = Query(FilesDbContext.ThirdpartyIdMapping)
|
||||
.Where(r => r.HashId == oldHashID)
|
||||
.ToList();
|
||||
|
||||
foreach (var m in mappingForUpdate)
|
||||
{
|
||||
m.Id = newID;
|
||||
m.HashId = newHashID;
|
||||
}
|
||||
|
||||
FilesDbContext.SaveChanges();
|
||||
|
||||
var securityForUpdate = Query(FilesDbContext.Security)
|
||||
.Where(r => r.EntryId == oldHashID)
|
||||
.ToList();
|
||||
|
||||
foreach (var s in securityForUpdate)
|
||||
{
|
||||
s.EntryId = newHashID;
|
||||
}
|
||||
|
||||
FilesDbContext.SaveChanges();
|
||||
|
||||
var linkForUpdate = Query(FilesDbContext.TagLink)
|
||||
.Where(r => r.EntryId == oldHashID)
|
||||
.ToList();
|
||||
|
||||
foreach (var l in linkForUpdate)
|
||||
{
|
||||
l.EntryId = newHashID;
|
||||
}
|
||||
|
||||
FilesDbContext.SaveChanges();
|
||||
}
|
||||
|
||||
tx.Commit();
|
||||
}
|
||||
}
|
||||
|
||||
protected string MappingID(string id)
|
||||
{
|
||||
return MappingID(id, false);
|
||||
}
|
||||
|
||||
protected override string MakeId(string path = null)
|
||||
{
|
||||
return path;
|
||||
}
|
||||
}
|
||||
}
|
92
products/ASC.Files/Server/Core/Thirdparty/SharePoint/SharePointDaoSelector.cs
vendored
Normal file
92
products/ASC.Files/Server/Core/Thirdparty/SharePoint/SharePointDaoSelector.cs
vendored
Normal file
@ -0,0 +1,92 @@
|
||||
/*
|
||||
*
|
||||
* (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 ASC.Common;
|
||||
using ASC.Files.Core;
|
||||
using ASC.Files.Core.Security;
|
||||
|
||||
namespace ASC.Files.Thirdparty.SharePoint
|
||||
{
|
||||
internal class SharePointDaoSelector : RegexDaoSelectorBase<SharePointProviderInfo>, IDaoSelector
|
||||
{
|
||||
protected internal override string Name { get => "sharepoint"; }
|
||||
protected internal override string Id { get => "spoint"; }
|
||||
public SharePointDaoSelector(IServiceProvider serviceProvider, IDaoFactory daoFactory)
|
||||
: base(serviceProvider, daoFactory)
|
||||
{
|
||||
}
|
||||
|
||||
public IFileDao<string> GetFileDao(string id)
|
||||
{
|
||||
return base.GetFileDao<SharePointFileDao>(id);
|
||||
}
|
||||
|
||||
public IFolderDao<string> GetFolderDao(string id)
|
||||
{
|
||||
return base.GetFolderDao<SharePointFolderDao>(id);
|
||||
}
|
||||
|
||||
public ITagDao<string> GetTagDao(string id)
|
||||
{
|
||||
return base.GetTagDao<SharePointTagDao>(id);
|
||||
}
|
||||
|
||||
public ISecurityDao<string> GetSecurityDao(string id)
|
||||
{
|
||||
return base.GetSecurityDao<SharePointSecurityDao>(id);
|
||||
}
|
||||
|
||||
public override string ConvertId(string id)
|
||||
{
|
||||
if (id != null)
|
||||
{
|
||||
var match = Selector.Match(id);
|
||||
if (match.Success)
|
||||
{
|
||||
return GetInfo(id).ProviderInfo.SpRootFolderId + match.Groups["path"].Value.Replace('|', '/');
|
||||
}
|
||||
throw new ArgumentException("Id is not a sharepoint id");
|
||||
}
|
||||
return base.ConvertId(null);
|
||||
}
|
||||
}
|
||||
|
||||
public static class SharePointDaoSelectorExtention
|
||||
{
|
||||
public static DIHelper AddSharePointSelectorService(this DIHelper services)
|
||||
{
|
||||
services.TryAddScoped<SharePointDaoSelector>();
|
||||
|
||||
return services
|
||||
.AddSharePointSecurityDaoService()
|
||||
.AddSharePointTagDaoService()
|
||||
.AddSharePointFolderDaoService()
|
||||
.AddSharePointFileDaoService();
|
||||
}
|
||||
}
|
||||
}
|
54
products/ASC.Files/Server/Core/Thirdparty/SharePoint/SharePointErrorEntry.cs
vendored
Normal file
54
products/ASC.Files/Server/Core/Thirdparty/SharePoint/SharePointErrorEntry.cs
vendored
Normal file
@ -0,0 +1,54 @@
|
||||
/*
|
||||
*
|
||||
* (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 Microsoft.SharePoint.Client;
|
||||
|
||||
namespace ASC.Files.Thirdparty.SharePoint
|
||||
{
|
||||
public class SharePointFileErrorEntry : File
|
||||
{
|
||||
public SharePointFileErrorEntry(ClientRuntimeContext cc, ObjectPath op)
|
||||
: base(cc, op)
|
||||
{
|
||||
}
|
||||
|
||||
public string Error { get; set; }
|
||||
|
||||
public object ID { get; set; }
|
||||
}
|
||||
|
||||
public class SharePointFolderErrorEntry : Folder
|
||||
{
|
||||
public SharePointFolderErrorEntry(ClientRuntimeContext cc, ObjectPath op)
|
||||
: base(cc, op)
|
||||
{
|
||||
}
|
||||
|
||||
public string Error { get; set; }
|
||||
|
||||
public object ID { get; set; }
|
||||
}
|
||||
}
|
499
products/ASC.Files/Server/Core/Thirdparty/SharePoint/SharePointFileDao.cs
vendored
Normal file
499
products/ASC.Files/Server/Core/Thirdparty/SharePoint/SharePointFileDao.cs
vendored
Normal file
@ -0,0 +1,499 @@
|
||||
/*
|
||||
*
|
||||
* (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;
|
||||
using System.IO;
|
||||
using System.Linq;
|
||||
|
||||
using ASC.Common;
|
||||
using ASC.Common.Logging;
|
||||
using ASC.Core;
|
||||
using ASC.Core.Common.EF;
|
||||
using ASC.Core.Tenants;
|
||||
using ASC.Files.Core;
|
||||
using ASC.Files.Core.EF;
|
||||
using ASC.Files.Core.Thirdparty;
|
||||
using ASC.Files.Resources;
|
||||
using ASC.Web.Core.Files;
|
||||
using ASC.Web.Files.Services.DocumentService;
|
||||
using ASC.Web.Studio.Core;
|
||||
|
||||
using Microsoft.Extensions.Options;
|
||||
|
||||
namespace ASC.Files.Thirdparty.SharePoint
|
||||
{
|
||||
internal class SharePointFileDao : SharePointDaoBase, IFileDao<string>
|
||||
{
|
||||
public CrossDao CrossDao { get; }
|
||||
public SharePointDaoSelector SharePointDaoSelector { get; }
|
||||
public IFileDao<int> FileDao { get; }
|
||||
|
||||
public SharePointFileDao(
|
||||
IServiceProvider serviceProvider,
|
||||
UserManager userManager,
|
||||
TenantManager tenantManager,
|
||||
TenantUtil tenantUtil,
|
||||
DbContextManager<FilesDbContext> dbContextManager,
|
||||
SetupInfo setupInfo,
|
||||
IOptionsMonitor<ILog> monitor,
|
||||
FileUtility fileUtility,
|
||||
CrossDao crossDao,
|
||||
SharePointDaoSelector sharePointDaoSelector,
|
||||
IFileDao<int> fileDao)
|
||||
: base(serviceProvider, userManager, tenantManager, tenantUtil, dbContextManager, setupInfo, monitor, fileUtility)
|
||||
{
|
||||
CrossDao = crossDao;
|
||||
SharePointDaoSelector = sharePointDaoSelector;
|
||||
FileDao = fileDao;
|
||||
}
|
||||
|
||||
public void InvalidateCache(string fileId)
|
||||
{
|
||||
ProviderInfo.InvalidateStorage();
|
||||
}
|
||||
|
||||
public File<string> GetFile(string fileId)
|
||||
{
|
||||
return GetFile(fileId, 1);
|
||||
}
|
||||
|
||||
public File<string> GetFile(string fileId, int fileVersion)
|
||||
{
|
||||
return ProviderInfo.ToFile(ProviderInfo.GetFileById(fileId));
|
||||
}
|
||||
|
||||
public File<string> GetFile(string parentId, string title)
|
||||
{
|
||||
return ProviderInfo.ToFile(ProviderInfo.GetFolderFiles(parentId).FirstOrDefault(item => item.Name.Equals(title, StringComparison.InvariantCultureIgnoreCase)));
|
||||
}
|
||||
|
||||
public File<string> GetFileStable(string fileId, int fileVersion)
|
||||
{
|
||||
return ProviderInfo.ToFile(ProviderInfo.GetFileById(fileId));
|
||||
}
|
||||
|
||||
public List<File<string>> GetFileHistory(string fileId)
|
||||
{
|
||||
return new List<File<string>> { GetFile(fileId) };
|
||||
}
|
||||
|
||||
public List<File<string>> GetFiles(string[] fileIds)
|
||||
{
|
||||
return fileIds.Select(fileId => ProviderInfo.ToFile(ProviderInfo.GetFileById(fileId))).ToList();
|
||||
}
|
||||
|
||||
public List<File<string>> GetFilesForShare(string[] fileIds, FilterType filterType, bool subjectGroup, Guid subjectID, string searchText, bool searchInContent)
|
||||
{
|
||||
if (fileIds == null || fileIds.Length == 0 || filterType == FilterType.FoldersOnly) return new List<File<string>>();
|
||||
|
||||
var files = GetFiles(fileIds).AsEnumerable();
|
||||
|
||||
//Filter
|
||||
if (subjectID != Guid.Empty)
|
||||
{
|
||||
files = files.Where(x => subjectGroup
|
||||
? UserManager.IsUserInGroup(x.CreateBy, subjectID)
|
||||
: x.CreateBy == subjectID);
|
||||
}
|
||||
|
||||
switch (filterType)
|
||||
{
|
||||
case FilterType.FoldersOnly:
|
||||
return new List<File<string>>();
|
||||
case FilterType.DocumentsOnly:
|
||||
files = files.Where(x => FileUtility.GetFileTypeByFileName(x.Title) == FileType.Document);
|
||||
break;
|
||||
case FilterType.PresentationsOnly:
|
||||
files = files.Where(x => FileUtility.GetFileTypeByFileName(x.Title) == FileType.Presentation);
|
||||
break;
|
||||
case FilterType.SpreadsheetsOnly:
|
||||
files = files.Where(x => FileUtility.GetFileTypeByFileName(x.Title) == FileType.Spreadsheet);
|
||||
break;
|
||||
case FilterType.ImagesOnly:
|
||||
files = files.Where(x => FileUtility.GetFileTypeByFileName(x.Title) == FileType.Image);
|
||||
break;
|
||||
case FilterType.ArchiveOnly:
|
||||
files = files.Where(x => FileUtility.GetFileTypeByFileName(x.Title) == FileType.Archive);
|
||||
break;
|
||||
case FilterType.MediaOnly:
|
||||
files = files.Where(x =>
|
||||
{
|
||||
FileType fileType;
|
||||
return (fileType = FileUtility.GetFileTypeByFileName(x.Title)) == FileType.Audio || fileType == FileType.Video;
|
||||
});
|
||||
break;
|
||||
case FilterType.ByExtension:
|
||||
if (!string.IsNullOrEmpty(searchText))
|
||||
files = files.Where(x => FileUtility.GetFileExtension(x.Title).Contains(searchText));
|
||||
break;
|
||||
}
|
||||
|
||||
if (!string.IsNullOrEmpty(searchText))
|
||||
files = files.Where(x => x.Title.IndexOf(searchText, StringComparison.OrdinalIgnoreCase) != -1);
|
||||
|
||||
return files.ToList();
|
||||
}
|
||||
|
||||
public List<string> GetFiles(string parentId)
|
||||
{
|
||||
return ProviderInfo.GetFolderFiles(parentId).Select(r => ProviderInfo.ToFile(r).ID).ToList();
|
||||
}
|
||||
|
||||
public List<File<string>> GetFiles(string parentId, OrderBy orderBy, FilterType filterType, bool subjectGroup, Guid subjectID, string searchText, bool searchInContent, bool withSubfolders = false)
|
||||
{
|
||||
if (filterType == FilterType.FoldersOnly) return new List<File<string>>();
|
||||
|
||||
//Get only files
|
||||
var files = ProviderInfo.GetFolderFiles(parentId).Select(r => ProviderInfo.ToFile(r));
|
||||
|
||||
//Filter
|
||||
if (subjectID != Guid.Empty)
|
||||
{
|
||||
files = files.Where(x => subjectGroup
|
||||
? UserManager.IsUserInGroup(x.CreateBy, subjectID)
|
||||
: x.CreateBy == subjectID);
|
||||
}
|
||||
|
||||
switch (filterType)
|
||||
{
|
||||
case FilterType.FoldersOnly:
|
||||
return new List<File<string>>();
|
||||
case FilterType.DocumentsOnly:
|
||||
files = files.Where(x => FileUtility.GetFileTypeByFileName(x.Title) == FileType.Document).ToList();
|
||||
break;
|
||||
case FilterType.PresentationsOnly:
|
||||
files = files.Where(x => FileUtility.GetFileTypeByFileName(x.Title) == FileType.Presentation).ToList();
|
||||
break;
|
||||
case FilterType.SpreadsheetsOnly:
|
||||
files = files.Where(x => FileUtility.GetFileTypeByFileName(x.Title) == FileType.Spreadsheet).ToList();
|
||||
break;
|
||||
case FilterType.ImagesOnly:
|
||||
files = files.Where(x => FileUtility.GetFileTypeByFileName(x.Title) == FileType.Image).ToList();
|
||||
break;
|
||||
case FilterType.ArchiveOnly:
|
||||
files = files.Where(x => FileUtility.GetFileTypeByFileName(x.Title) == FileType.Archive).ToList();
|
||||
break;
|
||||
case FilterType.MediaOnly:
|
||||
files = files.Where(x =>
|
||||
{
|
||||
FileType fileType;
|
||||
return (fileType = FileUtility.GetFileTypeByFileName(x.Title)) == FileType.Audio || fileType == FileType.Video;
|
||||
});
|
||||
break;
|
||||
case FilterType.ByExtension:
|
||||
if (!string.IsNullOrEmpty(searchText))
|
||||
files = files.Where(x => FileUtility.GetFileExtension(x.Title).Contains(searchText));
|
||||
break;
|
||||
}
|
||||
|
||||
if (!string.IsNullOrEmpty(searchText))
|
||||
files = files.Where(x => x.Title.IndexOf(searchText, StringComparison.OrdinalIgnoreCase) != -1).ToList();
|
||||
|
||||
if (orderBy == null) orderBy = new OrderBy(SortedByType.DateAndTime, false);
|
||||
|
||||
switch (orderBy.SortedBy)
|
||||
{
|
||||
case SortedByType.Author:
|
||||
files = orderBy.IsAsc ? files.OrderBy(x => x.CreateBy) : files.OrderByDescending(x => x.CreateBy);
|
||||
break;
|
||||
case SortedByType.AZ:
|
||||
files = orderBy.IsAsc ? files.OrderBy(x => x.Title) : files.OrderByDescending(x => x.Title);
|
||||
break;
|
||||
case SortedByType.DateAndTime:
|
||||
files = orderBy.IsAsc ? files.OrderBy(x => x.ModifiedOn) : files.OrderByDescending(x => x.ModifiedOn);
|
||||
break;
|
||||
case SortedByType.DateAndTimeCreation:
|
||||
files = orderBy.IsAsc ? files.OrderBy(x => x.CreateOn) : files.OrderByDescending(x => x.CreateOn);
|
||||
break;
|
||||
default:
|
||||
files = orderBy.IsAsc ? files.OrderBy(x => x.Title) : files.OrderByDescending(x => x.Title);
|
||||
break;
|
||||
}
|
||||
|
||||
return files.ToList();
|
||||
}
|
||||
|
||||
public Stream GetFileStream(File<string> file)
|
||||
{
|
||||
return GetFileStream(file, 0);
|
||||
}
|
||||
|
||||
public Stream GetFileStream(File<string> file, long offset)
|
||||
{
|
||||
var fileToDownload = ProviderInfo.GetFileById(file.ID);
|
||||
if (fileToDownload == null)
|
||||
throw new ArgumentNullException("file", FilesCommonResource.ErrorMassage_FileNotFound);
|
||||
|
||||
var fileStream = ProviderInfo.GetFileStream(fileToDownload.ServerRelativeUrl, (int)offset);
|
||||
|
||||
return fileStream;
|
||||
}
|
||||
|
||||
public Uri GetPreSignedUri(File<string> file, TimeSpan expires)
|
||||
{
|
||||
throw new NotSupportedException();
|
||||
}
|
||||
|
||||
public bool IsSupportedPreSignedUri(File<string> file)
|
||||
{
|
||||
return false;
|
||||
}
|
||||
|
||||
public File<string> SaveFile(File<string> file, Stream fileStream)
|
||||
{
|
||||
if (fileStream == null) throw new ArgumentNullException("fileStream");
|
||||
|
||||
if (file.ID != null)
|
||||
{
|
||||
var sharePointFile = ProviderInfo.CreateFile(file.ID, fileStream);
|
||||
|
||||
var resultFile = ProviderInfo.ToFile(sharePointFile);
|
||||
if (!sharePointFile.Name.Equals(file.Title))
|
||||
{
|
||||
var folder = ProviderInfo.GetFolderById(file.FolderID);
|
||||
file.Title = GetAvailableTitle(file.Title, folder, IsExist);
|
||||
|
||||
var id = ProviderInfo.RenameFile(DaoSelector.ConvertId(resultFile.ID).ToString(), file.Title);
|
||||
return GetFile(DaoSelector.ConvertId(id));
|
||||
}
|
||||
return resultFile;
|
||||
}
|
||||
|
||||
if (file.FolderID != null)
|
||||
{
|
||||
var folder = ProviderInfo.GetFolderById(file.FolderID);
|
||||
file.Title = GetAvailableTitle(file.Title, folder, IsExist);
|
||||
return ProviderInfo.ToFile(ProviderInfo.CreateFile(folder.ServerRelativeUrl + "/" + file.Title, fileStream));
|
||||
}
|
||||
|
||||
return null;
|
||||
}
|
||||
|
||||
public File<string> ReplaceFileVersion(File<string> file, Stream fileStream)
|
||||
{
|
||||
return SaveFile(file, fileStream);
|
||||
}
|
||||
|
||||
public void DeleteFile(string fileId)
|
||||
{
|
||||
ProviderInfo.DeleteFile(fileId);
|
||||
}
|
||||
|
||||
public bool IsExist(string title, object folderId)
|
||||
{
|
||||
return ProviderInfo.GetFolderFiles(folderId)
|
||||
.Any(item => item.Name.Equals(title, StringComparison.InvariantCultureIgnoreCase));
|
||||
}
|
||||
|
||||
public bool IsExist(string title, Microsoft.SharePoint.Client.Folder folder)
|
||||
{
|
||||
return ProviderInfo.GetFolderFiles(folder.ServerRelativeUrl)
|
||||
.Any(item => item.Name.Equals(title, StringComparison.InvariantCultureIgnoreCase));
|
||||
}
|
||||
|
||||
public TTo MoveFile<TTo>(string fileId, TTo toFolderId)
|
||||
{
|
||||
if (toFolderId is int tId)
|
||||
{
|
||||
return (TTo)Convert.ChangeType(MoveFile(fileId, tId), typeof(TTo));
|
||||
}
|
||||
|
||||
if (toFolderId is string tsId)
|
||||
{
|
||||
return (TTo)Convert.ChangeType(MoveFile(fileId, tsId), typeof(TTo));
|
||||
}
|
||||
|
||||
throw new NotImplementedException();
|
||||
}
|
||||
|
||||
public int MoveFile(string fileId, int toFolderId)
|
||||
{
|
||||
var moved = CrossDao.PerformCrossDaoFileCopy(
|
||||
fileId, this, SharePointDaoSelector.ConvertId,
|
||||
toFolderId, FileDao, r => r,
|
||||
true);
|
||||
|
||||
return moved.ID;
|
||||
}
|
||||
|
||||
public string MoveFile(string fileId, string toFolderId)
|
||||
{
|
||||
var newFileId = ProviderInfo.MoveFile(fileId, toFolderId);
|
||||
UpdatePathInDB(ProviderInfo.MakeId(fileId), newFileId);
|
||||
return newFileId;
|
||||
}
|
||||
|
||||
public File<TTo> CopyFile<TTo>(string fileId, TTo toFolderId)
|
||||
{
|
||||
if (toFolderId is int tId)
|
||||
{
|
||||
return CopyFile(fileId, tId) as File<TTo>;
|
||||
}
|
||||
|
||||
if (toFolderId is string tsId)
|
||||
{
|
||||
return CopyFile(fileId, tsId) as File<TTo>;
|
||||
}
|
||||
|
||||
throw new NotImplementedException();
|
||||
}
|
||||
|
||||
public File<int> CopyFile(string fileId, int toFolderId)
|
||||
{
|
||||
var moved = CrossDao.PerformCrossDaoFileCopy(
|
||||
fileId, this, SharePointDaoSelector.ConvertId,
|
||||
toFolderId, FileDao, r => r,
|
||||
false);
|
||||
|
||||
return moved;
|
||||
}
|
||||
|
||||
public File<string> CopyFile(string fileId, string toFolderId)
|
||||
{
|
||||
return ProviderInfo.ToFile(ProviderInfo.CopyFile(fileId, toFolderId));
|
||||
}
|
||||
|
||||
public string FileRename(File<string> file, string newTitle)
|
||||
{
|
||||
var newFileId = ProviderInfo.RenameFile(file.ID, newTitle);
|
||||
UpdatePathInDB(ProviderInfo.MakeId(file.ID), newFileId);
|
||||
return newFileId;
|
||||
}
|
||||
|
||||
public string UpdateComment(string fileId, int fileVersion, string comment)
|
||||
{
|
||||
return string.Empty;
|
||||
}
|
||||
|
||||
public void CompleteVersion(string fileId, int fileVersion)
|
||||
{
|
||||
}
|
||||
|
||||
public void ContinueVersion(string fileId, int fileVersion)
|
||||
{
|
||||
}
|
||||
|
||||
public bool UseTrashForRemove(File<string> file)
|
||||
{
|
||||
return false;
|
||||
}
|
||||
|
||||
public ChunkedUploadSession<string> CreateUploadSession(File<string> file, long contentLength)
|
||||
{
|
||||
return new ChunkedUploadSession<string>(FixId(file), contentLength) { UseChunks = false };
|
||||
}
|
||||
|
||||
public void UploadChunk(ChunkedUploadSession<string> uploadSession, Stream chunkStream, long chunkLength)
|
||||
{
|
||||
if (!uploadSession.UseChunks)
|
||||
{
|
||||
if (uploadSession.BytesTotal == 0)
|
||||
uploadSession.BytesTotal = chunkLength;
|
||||
|
||||
uploadSession.File = SaveFile(uploadSession.File, chunkStream);
|
||||
uploadSession.BytesUploaded = chunkLength;
|
||||
return;
|
||||
}
|
||||
|
||||
throw new NotImplementedException();
|
||||
}
|
||||
|
||||
public void AbortUploadSession(ChunkedUploadSession<string> uploadSession)
|
||||
{
|
||||
//throw new NotImplementedException();
|
||||
}
|
||||
|
||||
private File<string> FixId(File<string> file)
|
||||
{
|
||||
if (file.ID != null)
|
||||
file.ID = ProviderInfo.MakeId(file.ID);
|
||||
|
||||
if (file.FolderID != null)
|
||||
file.FolderID = ProviderInfo.MakeId(file.FolderID);
|
||||
|
||||
return file;
|
||||
}
|
||||
|
||||
#region Only in TMFileDao
|
||||
|
||||
public void ReassignFiles(string[] fileIds, Guid newOwnerId)
|
||||
{
|
||||
}
|
||||
|
||||
public List<File<string>> GetFiles(string[] parentIds, FilterType filterType, bool subjectGroup, Guid subjectID, string searchText, bool searchInContent)
|
||||
{
|
||||
return new List<File<string>>();
|
||||
}
|
||||
|
||||
public IEnumerable<File<string>> Search(string text, bool bunch)
|
||||
{
|
||||
return null;
|
||||
}
|
||||
|
||||
public bool IsExistOnStorage(File<string> file)
|
||||
{
|
||||
return true;
|
||||
}
|
||||
|
||||
public void SaveEditHistory(File<string> file, string changes, Stream differenceStream)
|
||||
{
|
||||
//Do nothing
|
||||
}
|
||||
|
||||
public List<EditHistory> GetEditHistory(DocumentServiceHelper documentServiceHelper, string fileId, int fileVersion)
|
||||
{
|
||||
return null;
|
||||
}
|
||||
|
||||
public Stream GetDifferenceStream(File<string> file)
|
||||
{
|
||||
return null;
|
||||
}
|
||||
|
||||
public bool ContainChanges(string fileId, int fileVersion)
|
||||
{
|
||||
return false;
|
||||
}
|
||||
|
||||
public string GetUniqFilePath(File<string> file, string fileTitle)
|
||||
{
|
||||
throw new NotImplementedException();
|
||||
}
|
||||
|
||||
#endregion
|
||||
}
|
||||
|
||||
public static class SharePointFileDaoExtention
|
||||
{
|
||||
public static DIHelper AddSharePointFileDaoService(this DIHelper services)
|
||||
{
|
||||
services.TryAddScoped<SharePointFileDao>();
|
||||
|
||||
return services;
|
||||
}
|
||||
}
|
||||
}
|
481
products/ASC.Files/Server/Core/Thirdparty/SharePoint/SharePointFolderDao.cs
vendored
Normal file
481
products/ASC.Files/Server/Core/Thirdparty/SharePoint/SharePointFolderDao.cs
vendored
Normal file
@ -0,0 +1,481 @@
|
||||
/*
|
||||
*
|
||||
* (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;
|
||||
using System.Linq;
|
||||
using System.Threading;
|
||||
|
||||
using ASC.Common;
|
||||
using ASC.Common.Logging;
|
||||
using ASC.Core;
|
||||
using ASC.Core.Common.EF;
|
||||
using ASC.Core.Tenants;
|
||||
using ASC.Files.Core;
|
||||
using ASC.Files.Core.EF;
|
||||
using ASC.Files.Core.Thirdparty;
|
||||
using ASC.Web.Core.Files;
|
||||
using ASC.Web.Studio.Core;
|
||||
|
||||
using Microsoft.Extensions.Options;
|
||||
|
||||
namespace ASC.Files.Thirdparty.SharePoint
|
||||
{
|
||||
internal class SharePointFolderDao : SharePointDaoBase, IFolderDao<string>
|
||||
{
|
||||
public CrossDao CrossDao { get; }
|
||||
public SharePointDaoSelector SharePointDaoSelector { get; }
|
||||
public IFileDao<int> FileDao { get; }
|
||||
public IFolderDao<int> FolderDao { get; }
|
||||
|
||||
public SharePointFolderDao(
|
||||
IServiceProvider serviceProvider,
|
||||
UserManager userManager,
|
||||
TenantManager tenantManager,
|
||||
TenantUtil tenantUtil,
|
||||
DbContextManager<FilesDbContext> dbContextManager,
|
||||
SetupInfo setupInfo,
|
||||
IOptionsMonitor<ILog> monitor,
|
||||
FileUtility fileUtility,
|
||||
CrossDao crossDao,
|
||||
SharePointDaoSelector sharePointDaoSelector,
|
||||
IFileDao<int> fileDao,
|
||||
IFolderDao<int> folderDao)
|
||||
: base(serviceProvider, userManager, tenantManager, tenantUtil, dbContextManager, setupInfo, monitor, fileUtility)
|
||||
{
|
||||
CrossDao = crossDao;
|
||||
SharePointDaoSelector = sharePointDaoSelector;
|
||||
FileDao = fileDao;
|
||||
FolderDao = folderDao;
|
||||
}
|
||||
|
||||
public Folder<string> GetFolder(string folderId)
|
||||
{
|
||||
return ProviderInfo.ToFolder(ProviderInfo.GetFolderById(folderId));
|
||||
}
|
||||
|
||||
public Folder<string> GetFolder(string title, string parentId)
|
||||
{
|
||||
return
|
||||
ProviderInfo.ToFolder(
|
||||
ProviderInfo.GetFolderFolders(parentId)
|
||||
.FirstOrDefault(item => item.Name.Equals(title, StringComparison.InvariantCultureIgnoreCase)));
|
||||
}
|
||||
|
||||
public Folder<string> GetRootFolder(string folderId)
|
||||
{
|
||||
return ProviderInfo.ToFolder(ProviderInfo.RootFolder);
|
||||
}
|
||||
|
||||
public Folder<string> GetRootFolderByFile(string fileId)
|
||||
{
|
||||
return ProviderInfo.ToFolder(ProviderInfo.RootFolder);
|
||||
}
|
||||
|
||||
public List<Folder<string>> GetFolders(string parentId)
|
||||
{
|
||||
return ProviderInfo.GetFolderFolders(parentId).Select(r => ProviderInfo.ToFolder(r)).ToList();
|
||||
}
|
||||
|
||||
public List<Folder<string>> GetFolders(string parentId, OrderBy orderBy, FilterType filterType, bool subjectGroup, Guid subjectID, string searchText, bool withSubfolders = false)
|
||||
{
|
||||
if (filterType == FilterType.FilesOnly || filterType == FilterType.ByExtension
|
||||
|| filterType == FilterType.DocumentsOnly || filterType == FilterType.ImagesOnly
|
||||
|| filterType == FilterType.PresentationsOnly || filterType == FilterType.SpreadsheetsOnly
|
||||
|| filterType == FilterType.ArchiveOnly || filterType == FilterType.MediaOnly)
|
||||
return new List<Folder<string>>();
|
||||
|
||||
var folders = GetFolders(parentId).AsEnumerable();
|
||||
|
||||
//Filter
|
||||
if (subjectID != Guid.Empty)
|
||||
{
|
||||
folders = folders.Where(x => subjectGroup
|
||||
? UserManager.IsUserInGroup(x.CreateBy, subjectID)
|
||||
: x.CreateBy == subjectID);
|
||||
}
|
||||
|
||||
if (!string.IsNullOrEmpty(searchText))
|
||||
folders = folders.Where(x => x.Title.IndexOf(searchText, StringComparison.OrdinalIgnoreCase) != -1);
|
||||
|
||||
if (orderBy == null) orderBy = new OrderBy(SortedByType.DateAndTime, false);
|
||||
|
||||
switch (orderBy.SortedBy)
|
||||
{
|
||||
case SortedByType.Author:
|
||||
folders = orderBy.IsAsc
|
||||
? folders.OrderBy(x => x.CreateBy)
|
||||
: folders.OrderByDescending(x => x.CreateBy);
|
||||
break;
|
||||
case SortedByType.AZ:
|
||||
folders = orderBy.IsAsc ? folders.OrderBy(x => x.Title) : folders.OrderByDescending(x => x.Title);
|
||||
break;
|
||||
case SortedByType.DateAndTime:
|
||||
folders = orderBy.IsAsc
|
||||
? folders.OrderBy(x => x.ModifiedOn)
|
||||
: folders.OrderByDescending(x => x.ModifiedOn);
|
||||
break;
|
||||
case SortedByType.DateAndTimeCreation:
|
||||
folders = orderBy.IsAsc
|
||||
? folders.OrderBy(x => x.CreateOn)
|
||||
: folders.OrderByDescending(x => x.CreateOn);
|
||||
break;
|
||||
default:
|
||||
folders = orderBy.IsAsc ? folders.OrderBy(x => x.Title) : folders.OrderByDescending(x => x.Title);
|
||||
break;
|
||||
}
|
||||
|
||||
return folders.ToList();
|
||||
}
|
||||
|
||||
public List<Folder<string>> GetFolders(string[] folderIds, FilterType filterType = FilterType.None, bool subjectGroup = false, Guid? subjectID = null, string searchText = "", bool searchSubfolders = false, bool checkShare = true)
|
||||
{
|
||||
if (filterType == FilterType.FilesOnly || filterType == FilterType.ByExtension
|
||||
|| filterType == FilterType.DocumentsOnly || filterType == FilterType.ImagesOnly
|
||||
|| filterType == FilterType.PresentationsOnly || filterType == FilterType.SpreadsheetsOnly
|
||||
|| filterType == FilterType.ArchiveOnly || filterType == FilterType.MediaOnly)
|
||||
return new List<Folder<string>>();
|
||||
|
||||
var folders = folderIds.Select(GetFolder);
|
||||
|
||||
if (subjectID.HasValue && subjectID != Guid.Empty)
|
||||
{
|
||||
folders = folders.Where(x => subjectGroup
|
||||
? UserManager.IsUserInGroup(x.CreateBy, subjectID.Value)
|
||||
: x.CreateBy == subjectID);
|
||||
}
|
||||
|
||||
if (!string.IsNullOrEmpty(searchText))
|
||||
folders = folders.Where(x => x.Title.IndexOf(searchText, StringComparison.OrdinalIgnoreCase) != -1);
|
||||
|
||||
return folders.ToList();
|
||||
}
|
||||
|
||||
public List<Folder<string>> GetParentFolders(string folderId)
|
||||
{
|
||||
var path = new List<Folder<string>>();
|
||||
var folder = ProviderInfo.GetFolderById(folderId);
|
||||
if (folder != null)
|
||||
{
|
||||
do
|
||||
{
|
||||
path.Add(ProviderInfo.ToFolder(folder));
|
||||
} while (folder != ProviderInfo.RootFolder && !(folder is SharePointFolderErrorEntry) &&
|
||||
(folder = ProviderInfo.GetParentFolder(folder.ServerRelativeUrl)) != null);
|
||||
}
|
||||
path.Reverse();
|
||||
return path;
|
||||
}
|
||||
|
||||
public string SaveFolder(Folder<string> folder)
|
||||
{
|
||||
if (folder.ID != null)
|
||||
{
|
||||
//Create with id
|
||||
var savedfolder = ProviderInfo.CreateFolder(folder.ID);
|
||||
return ProviderInfo.ToFolder(savedfolder).ID;
|
||||
}
|
||||
|
||||
if (folder.ParentFolderID != null)
|
||||
{
|
||||
var parentFolder = ProviderInfo.GetFolderById(folder.ParentFolderID);
|
||||
|
||||
folder.Title = GetAvailableTitle(folder.Title, parentFolder, IsExist);
|
||||
|
||||
var newFolder = ProviderInfo.CreateFolder(parentFolder.ServerRelativeUrl + "/" + folder.Title);
|
||||
return ProviderInfo.ToFolder(newFolder).ID;
|
||||
}
|
||||
|
||||
return null;
|
||||
}
|
||||
|
||||
public bool IsExist(string title, Microsoft.SharePoint.Client.Folder folder)
|
||||
{
|
||||
return ProviderInfo.GetFolderFolders(folder.ServerRelativeUrl)
|
||||
.Any(item => item.Name.Equals(title, StringComparison.InvariantCultureIgnoreCase));
|
||||
}
|
||||
|
||||
public void DeleteFolder(string folderId)
|
||||
{
|
||||
var folder = ProviderInfo.GetFolderById(folderId);
|
||||
|
||||
using (var tx = FilesDbContext.Database.BeginTransaction())
|
||||
{
|
||||
var hashIDs = Query(FilesDbContext.ThirdpartyIdMapping)
|
||||
.Where(r => r.Id.StartsWith(folder.ServerRelativeUrl))
|
||||
.Select(r => r.HashId)
|
||||
.ToList();
|
||||
|
||||
var link = Query(FilesDbContext.TagLink)
|
||||
.Where(r => hashIDs.Any(h => h == r.EntryId))
|
||||
.ToList();
|
||||
|
||||
FilesDbContext.TagLink.RemoveRange(link);
|
||||
FilesDbContext.SaveChanges();
|
||||
|
||||
var tagsToRemove = Query(FilesDbContext.Tag)
|
||||
.Where(r => !Query(FilesDbContext.TagLink).Where(a => a.TagId == r.Id).Any());
|
||||
|
||||
FilesDbContext.Tag.RemoveRange(tagsToRemove);
|
||||
|
||||
var securityToDelete = Query(FilesDbContext.Security)
|
||||
.Where(r => hashIDs.Any(h => h == r.EntryId));
|
||||
|
||||
FilesDbContext.Security.RemoveRange(securityToDelete);
|
||||
FilesDbContext.SaveChanges();
|
||||
|
||||
var mappingToDelete = Query(FilesDbContext.ThirdpartyIdMapping)
|
||||
.Where(r => hashIDs.Any(h => h == r.HashId));
|
||||
|
||||
FilesDbContext.ThirdpartyIdMapping.RemoveRange(mappingToDelete);
|
||||
FilesDbContext.SaveChanges();
|
||||
|
||||
tx.Commit();
|
||||
}
|
||||
ProviderInfo.DeleteFolder(folderId);
|
||||
}
|
||||
|
||||
public TTo MoveFolder<TTo>(string folderId, TTo toFolderId, CancellationToken? cancellationToken)
|
||||
{
|
||||
if (toFolderId is int tId)
|
||||
{
|
||||
return (TTo)Convert.ChangeType(MoveFolder(folderId, tId, cancellationToken), typeof(TTo));
|
||||
}
|
||||
|
||||
if (toFolderId is string tsId)
|
||||
{
|
||||
return (TTo)Convert.ChangeType(MoveFolder(folderId, tsId, cancellationToken), typeof(TTo));
|
||||
}
|
||||
|
||||
throw new NotImplementedException();
|
||||
}
|
||||
|
||||
public int MoveFolder(string folderId, int toFolderId, CancellationToken? cancellationToken)
|
||||
{
|
||||
var moved = CrossDao.PerformCrossDaoFolderCopy(
|
||||
folderId, this, SharePointDaoSelector.GetFileDao(folderId), SharePointDaoSelector.ConvertId,
|
||||
toFolderId, FolderDao, FileDao, r => r,
|
||||
true, cancellationToken);
|
||||
|
||||
return moved.ID;
|
||||
}
|
||||
|
||||
public string MoveFolder(string folderId, string toFolderId, CancellationToken? cancellationToken)
|
||||
{
|
||||
var newFolderId = ProviderInfo.MoveFolder(folderId, toFolderId);
|
||||
UpdatePathInDB(ProviderInfo.MakeId(folderId), newFolderId);
|
||||
return newFolderId;
|
||||
}
|
||||
|
||||
public Folder<TTo> CopyFolder<TTo>(string folderId, TTo toFolderId, CancellationToken? cancellationToken)
|
||||
{
|
||||
if (toFolderId is int tId)
|
||||
{
|
||||
return CopyFolder(folderId, tId, cancellationToken) as Folder<TTo>;
|
||||
}
|
||||
|
||||
if (toFolderId is string tsId)
|
||||
{
|
||||
return CopyFolder(folderId, tsId, cancellationToken) as Folder<TTo>;
|
||||
}
|
||||
|
||||
throw new NotImplementedException();
|
||||
}
|
||||
|
||||
public Folder<string> CopyFolder(string folderId, string toFolderId, CancellationToken? cancellationToken)
|
||||
{
|
||||
return ProviderInfo.ToFolder(ProviderInfo.CopyFolder(folderId, toFolderId));
|
||||
}
|
||||
|
||||
public Folder<int> CopyFolder(string folderId, int toFolderId, CancellationToken? cancellationToken)
|
||||
{
|
||||
var moved = CrossDao.PerformCrossDaoFolderCopy(
|
||||
folderId, this, SharePointDaoSelector.GetFileDao(folderId), SharePointDaoSelector.ConvertId,
|
||||
toFolderId, FolderDao, FileDao, r => r,
|
||||
false, cancellationToken);
|
||||
|
||||
return moved;
|
||||
}
|
||||
|
||||
public IDictionary<string, string> CanMoveOrCopy<TTo>(string[] folderIds, TTo to)
|
||||
{
|
||||
if (to is int tId)
|
||||
{
|
||||
return CanMoveOrCopy(folderIds, tId);
|
||||
}
|
||||
|
||||
if (to is string tsId)
|
||||
{
|
||||
return CanMoveOrCopy(folderIds, tsId);
|
||||
}
|
||||
|
||||
throw new NotImplementedException();
|
||||
}
|
||||
|
||||
public IDictionary<string, string> CanMoveOrCopy(string[] folderIds, string to)
|
||||
{
|
||||
return new Dictionary<string, string>();
|
||||
}
|
||||
|
||||
public IDictionary<string, string> CanMoveOrCopy(string[] folderIds, int to)
|
||||
{
|
||||
return new Dictionary<string, string>();
|
||||
}
|
||||
|
||||
public string RenameFolder(Folder<string> folder, string newTitle)
|
||||
{
|
||||
var oldId = ProviderInfo.MakeId(folder.ID);
|
||||
var newFolderId = oldId;
|
||||
if (ProviderInfo.SpRootFolderId.Equals(folder.ID))
|
||||
{
|
||||
//It's root folder
|
||||
DaoSelector.RenameProvider(ProviderInfo, newTitle);
|
||||
//rename provider customer title
|
||||
}
|
||||
else
|
||||
{
|
||||
newFolderId = (string)ProviderInfo.RenameFolder(folder.ID, newTitle);
|
||||
}
|
||||
UpdatePathInDB(oldId, newFolderId);
|
||||
return newFolderId;
|
||||
}
|
||||
|
||||
public int GetItemsCount(string folderId)
|
||||
{
|
||||
throw new NotImplementedException();
|
||||
}
|
||||
|
||||
public bool IsEmpty(string folderId)
|
||||
{
|
||||
return ProviderInfo.GetFolderById(folderId).ItemCount == 0;
|
||||
}
|
||||
|
||||
public bool UseTrashForRemove(Folder<string> folder)
|
||||
{
|
||||
return false;
|
||||
}
|
||||
|
||||
public bool UseRecursiveOperation<TTo>(string folderId, TTo toRootFolderId)
|
||||
{
|
||||
return false;
|
||||
}
|
||||
|
||||
public bool UseRecursiveOperation(string folderId, int toRootFolderId)
|
||||
{
|
||||
return false;
|
||||
}
|
||||
|
||||
public bool UseRecursiveOperation(string folderId, string toRootFolderId)
|
||||
{
|
||||
return false;
|
||||
}
|
||||
|
||||
public bool CanCalculateSubitems(string entryId)
|
||||
{
|
||||
return false;
|
||||
}
|
||||
|
||||
public long GetMaxUploadSize(string folderId, bool chunkedUpload = false)
|
||||
{
|
||||
return 2L * 1024L * 1024L * 1024L;
|
||||
}
|
||||
|
||||
#region Only for TMFolderDao
|
||||
|
||||
public void ReassignFolders(string[] folderIds, Guid newOwnerId)
|
||||
{
|
||||
}
|
||||
|
||||
public IEnumerable<Folder<string>> Search(string text, bool bunch)
|
||||
{
|
||||
return null;
|
||||
}
|
||||
|
||||
public string GetFolderID(string module, string bunch, string data, bool createIfNotExists)
|
||||
{
|
||||
return null;
|
||||
}
|
||||
|
||||
public IEnumerable<string> GetFolderIDs(string module, string bunch, IEnumerable<string> data,
|
||||
bool createIfNotExists)
|
||||
{
|
||||
return new List<string>();
|
||||
}
|
||||
|
||||
public string GetFolderIDCommon(bool createIfNotExists)
|
||||
{
|
||||
return null;
|
||||
}
|
||||
|
||||
public string GetFolderIDUser(bool createIfNotExists, Guid? userId)
|
||||
{
|
||||
return null;
|
||||
}
|
||||
|
||||
public string GetFolderIDShare(bool createIfNotExists)
|
||||
{
|
||||
return null;
|
||||
}
|
||||
|
||||
public string GetFolderIDTrash(bool createIfNotExists, Guid? userId)
|
||||
{
|
||||
return null;
|
||||
}
|
||||
|
||||
|
||||
public string GetFolderIDPhotos(bool createIfNotExists)
|
||||
{
|
||||
return null;
|
||||
}
|
||||
|
||||
public string GetFolderIDProjects(bool createIfNotExists)
|
||||
{
|
||||
return null;
|
||||
}
|
||||
|
||||
public string GetBunchObjectID(string folderID)
|
||||
{
|
||||
return null;
|
||||
}
|
||||
|
||||
public Dictionary<string, string> GetBunchObjectIDs(List<string> folderIDs)
|
||||
{
|
||||
return null;
|
||||
}
|
||||
|
||||
#endregion
|
||||
}
|
||||
|
||||
public static class SharePointFolderDaoExtention
|
||||
{
|
||||
public static DIHelper AddSharePointFolderDaoService(this DIHelper services)
|
||||
{
|
||||
services.TryAddScoped<SharePointFolderDao>();
|
||||
|
||||
return services;
|
||||
}
|
||||
}
|
||||
}
|
682
products/ASC.Files/Server/Core/Thirdparty/SharePoint/SharePointProviderInfo.cs
vendored
Normal file
682
products/ASC.Files/Server/Core/Thirdparty/SharePoint/SharePointProviderInfo.cs
vendored
Normal file
@ -0,0 +1,682 @@
|
||||
/*
|
||||
*
|
||||
* (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;
|
||||
using System.IO;
|
||||
using System.Linq;
|
||||
using System.Net;
|
||||
using System.Security;
|
||||
using System.Text.RegularExpressions;
|
||||
|
||||
using ASC.Common;
|
||||
using ASC.Common.Caching;
|
||||
using ASC.Common.Logging;
|
||||
using ASC.Core.Tenants;
|
||||
using ASC.Files.Core;
|
||||
using ASC.Web.Files.Classes;
|
||||
|
||||
using Microsoft.Extensions.DependencyInjection;
|
||||
using Microsoft.Extensions.Options;
|
||||
using Microsoft.SharePoint.Client;
|
||||
|
||||
using File = Microsoft.SharePoint.Client.File;
|
||||
using Folder = Microsoft.SharePoint.Client.Folder;
|
||||
|
||||
namespace ASC.Files.Thirdparty.SharePoint
|
||||
{
|
||||
public class SharePointProviderInfo : IProviderInfo
|
||||
{
|
||||
private ClientContext clientContext;
|
||||
|
||||
public int ID { get; set; }
|
||||
public string ProviderKey { get; set; }
|
||||
public Guid Owner { get; set; }
|
||||
public FolderType RootFolderType { get; set; }
|
||||
public DateTime CreateOn { get; set; }
|
||||
public string CustomerTitle { get; set; }
|
||||
public string RootFolderId { get { return "spoint-" + ID; } }
|
||||
|
||||
public string SpRootFolderId = "/Shared Documents";
|
||||
|
||||
public SharePointProviderInfo(
|
||||
IOptionsMonitor<ILog> options,
|
||||
IServiceProvider serviceProvider,
|
||||
TenantUtil tenantUtil,
|
||||
SharePointProviderInfoHelper sharePointProviderInfoHelper)
|
||||
{
|
||||
Log = options.CurrentValue;
|
||||
ServiceProvider = serviceProvider;
|
||||
TenantUtil = tenantUtil;
|
||||
SharePointProviderInfoHelper = sharePointProviderInfoHelper;
|
||||
}
|
||||
|
||||
public bool CheckAccess()
|
||||
{
|
||||
try
|
||||
{
|
||||
clientContext.Load(clientContext.Web);
|
||||
clientContext.ExecuteQuery();
|
||||
return true;
|
||||
}
|
||||
catch (Exception e)
|
||||
{
|
||||
Log.Warn("CheckAccess", e);
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
public void InvalidateStorage()
|
||||
{
|
||||
if (clientContext != null)
|
||||
{
|
||||
clientContext.Dispose();
|
||||
clientContext = null;
|
||||
}
|
||||
|
||||
SharePointProviderInfoHelper.Invalidate();
|
||||
}
|
||||
|
||||
public void UpdateTitle(string newtitle)
|
||||
{
|
||||
CustomerTitle = newtitle;
|
||||
}
|
||||
|
||||
public void InitClientContext(AuthData authData)
|
||||
{
|
||||
var authUrl = authData.Url;
|
||||
ICredentials credentials = new NetworkCredential(authData.Login, authData.Password);
|
||||
|
||||
if (authData.Login.EndsWith("onmicrosoft.com"))
|
||||
{
|
||||
var personalPath = string.Concat("/personal/", authData.Login.Replace("@", "_").Replace(".", "_").ToLower());
|
||||
SpRootFolderId = string.Concat(personalPath, "/Documents");
|
||||
|
||||
var ss = new SecureString();
|
||||
foreach (var p in authData.Password)
|
||||
{
|
||||
ss.AppendChar(p);
|
||||
}
|
||||
authUrl = string.Concat(authData.Url.TrimEnd('/'), personalPath);
|
||||
//TODO
|
||||
//credentials = new SharePointOnlineCredentials(authData.Login, ss);
|
||||
|
||||
}
|
||||
|
||||
clientContext = new ClientContext(authUrl)
|
||||
{
|
||||
AuthenticationMode = ClientAuthenticationMode.Default,
|
||||
Credentials = credentials
|
||||
};
|
||||
}
|
||||
|
||||
#region Files
|
||||
|
||||
public File GetFileById(object id)
|
||||
{
|
||||
var key = "spointf-" + MakeId(id);
|
||||
var file = SharePointProviderInfoHelper.GetFile(key);
|
||||
if (file == null)
|
||||
{
|
||||
file = GetFile(id);
|
||||
if (file != null)
|
||||
{
|
||||
SharePointProviderInfoHelper.AddFile(key, file);
|
||||
}
|
||||
}
|
||||
return file;
|
||||
}
|
||||
|
||||
private File GetFile(object id)
|
||||
{
|
||||
var file = clientContext.Web.GetFileByServerRelativeUrl((string)id);
|
||||
clientContext.Load(file);
|
||||
clientContext.Load(file.ListItemAllFields);
|
||||
|
||||
try
|
||||
{
|
||||
clientContext.ExecuteQuery();
|
||||
}
|
||||
catch (Exception ex)
|
||||
{
|
||||
SharePointProviderInfoHelper.PublishFolder(MakeId(GetParentFolderId(id)));
|
||||
var serverException = (ServerException)ex;
|
||||
if (serverException.ServerErrorTypeName == (typeof(FileNotFoundException)).ToString())
|
||||
{
|
||||
return null;
|
||||
}
|
||||
return new SharePointFileErrorEntry(file.Context, file.Path) { Error = ex.Message, ID = id };
|
||||
}
|
||||
|
||||
return file;
|
||||
}
|
||||
|
||||
public Stream GetFileStream(object id, int offset = 0)
|
||||
{
|
||||
var file = GetFileById(id);
|
||||
|
||||
if (file is SharePointFileErrorEntry) return null;
|
||||
var fileInfo = File.OpenBinaryDirect(clientContext, (string)id);
|
||||
clientContext.ExecuteQuery();
|
||||
|
||||
var tempBuffer = new FileStream(Path.GetTempFileName(), FileMode.OpenOrCreate, FileAccess.ReadWrite, FileShare.Read, 8096, FileOptions.DeleteOnClose);
|
||||
using (var str = fileInfo.Stream)
|
||||
{
|
||||
if (str != null)
|
||||
{
|
||||
str.CopyTo(tempBuffer);
|
||||
tempBuffer.Flush();
|
||||
tempBuffer.Seek(offset, SeekOrigin.Begin);
|
||||
}
|
||||
}
|
||||
|
||||
return tempBuffer;
|
||||
}
|
||||
|
||||
public File CreateFile(string id, Stream stream)
|
||||
{
|
||||
byte[] b;
|
||||
|
||||
using (var br = new BinaryReader(stream))
|
||||
{
|
||||
b = br.ReadBytes((int)stream.Length);
|
||||
}
|
||||
|
||||
var file = clientContext.Web.RootFolder.Files.Add(new FileCreationInformation { Content = b, Url = id, Overwrite = true });
|
||||
clientContext.Load(file);
|
||||
clientContext.Load(file.ListItemAllFields);
|
||||
clientContext.ExecuteQuery();
|
||||
|
||||
SharePointProviderInfoHelper.AddFile("spointf-" + MakeId(id), file);
|
||||
SharePointProviderInfoHelper.PublishFolder(MakeId(GetParentFolderId(id)));
|
||||
|
||||
return file;
|
||||
}
|
||||
|
||||
public void DeleteFile(string id)
|
||||
{
|
||||
SharePointProviderInfoHelper.PublishFile(MakeId(id), MakeId(GetParentFolderId(id)));
|
||||
|
||||
var file = GetFileById(id);
|
||||
|
||||
if (file is SharePointFileErrorEntry) return;
|
||||
|
||||
file.DeleteObject();
|
||||
clientContext.ExecuteQuery();
|
||||
}
|
||||
|
||||
public string RenameFile(string id, string newTitle)
|
||||
{
|
||||
SharePointProviderInfoHelper.PublishFile(MakeId(id), MakeId(GetParentFolderId(id)));
|
||||
|
||||
var file = GetFileById(id);
|
||||
|
||||
if (file is SharePointFileErrorEntry) return MakeId();
|
||||
|
||||
var newUrl = GetParentFolderId(file.ServerRelativeUrl) + "/" + newTitle;
|
||||
file.MoveTo(newUrl, MoveOperations.Overwrite);
|
||||
clientContext.ExecuteQuery();
|
||||
|
||||
return MakeId(newUrl);
|
||||
}
|
||||
|
||||
public string MoveFile(string id, string toFolderId)
|
||||
{
|
||||
SharePointProviderInfoHelper.PublishFile(MakeId(id), MakeId(GetParentFolderId(id)));
|
||||
SharePointProviderInfoHelper.PublishFolder(MakeId(toFolderId));
|
||||
|
||||
var file = GetFileById(id);
|
||||
|
||||
if (file is SharePointFileErrorEntry) return MakeId();
|
||||
|
||||
var newUrl = toFolderId + "/" + file.Name;
|
||||
file.MoveTo(newUrl, MoveOperations.Overwrite);
|
||||
clientContext.ExecuteQuery();
|
||||
|
||||
return MakeId(newUrl);
|
||||
}
|
||||
|
||||
public File CopyFile(string id, string toFolderId)
|
||||
{
|
||||
SharePointProviderInfoHelper.PublishFolder(MakeId(toFolderId), MakeId(GetParentFolderId(id)));
|
||||
|
||||
var file = GetFileById(id);
|
||||
|
||||
if (file is SharePointFileErrorEntry) return file;
|
||||
|
||||
var newUrl = toFolderId + "/" + file.Name;
|
||||
file.CopyTo(newUrl, false);
|
||||
clientContext.ExecuteQuery();
|
||||
|
||||
return file;
|
||||
}
|
||||
|
||||
public File<string> ToFile(File file)
|
||||
{
|
||||
if (file == null)
|
||||
return null;
|
||||
|
||||
var result = ServiceProvider.GetService<File<string>>();
|
||||
|
||||
if (file is SharePointFileErrorEntry errorFile)
|
||||
{
|
||||
result.ID = MakeId(errorFile.ID);
|
||||
result.FolderID = MakeId(GetParentFolderId(errorFile.ID));
|
||||
result.CreateBy = Owner;
|
||||
result.CreateOn = DateTime.UtcNow;
|
||||
result.ModifiedBy = Owner;
|
||||
result.ModifiedOn = DateTime.UtcNow;
|
||||
result.ProviderId = ID;
|
||||
result.ProviderKey = ProviderKey;
|
||||
result.RootFolderCreator = Owner;
|
||||
result.RootFolderId = MakeId(RootFolder.ServerRelativeUrl);
|
||||
result.RootFolderType = RootFolderType;
|
||||
result.Title = MakeTitle(GetTitleById(errorFile.ID));
|
||||
result.Error = errorFile.Error;
|
||||
|
||||
return result;
|
||||
}
|
||||
|
||||
result.ID = MakeId(file.ServerRelativeUrl);
|
||||
result.Access = Core.Security.FileShare.None;
|
||||
//ContentLength = file.Length,
|
||||
result.CreateBy = Owner;
|
||||
result.CreateOn = file.TimeCreated.Kind == DateTimeKind.Utc ? TenantUtil.DateTimeFromUtc(file.TimeCreated) : file.TimeCreated;
|
||||
result.FileStatus = FileStatus.None;
|
||||
result.FolderID = MakeId(GetParentFolderId(file.ServerRelativeUrl));
|
||||
result.ModifiedBy = Owner;
|
||||
result.ModifiedOn = file.TimeLastModified.Kind == DateTimeKind.Utc ? TenantUtil.DateTimeFromUtc(file.TimeLastModified) : file.TimeLastModified;
|
||||
result.NativeAccessor = file;
|
||||
result.ProviderId = ID;
|
||||
result.ProviderKey = ProviderKey;
|
||||
result.Title = MakeTitle(file.Name);
|
||||
result.RootFolderId = MakeId(SpRootFolderId);
|
||||
result.RootFolderType = RootFolderType;
|
||||
result.RootFolderCreator = Owner;
|
||||
result.Shared = false;
|
||||
result.Version = 1;
|
||||
|
||||
if (file.IsPropertyAvailable("Length"))
|
||||
{
|
||||
//TODO
|
||||
//result.ContentLength = file.Length;
|
||||
}
|
||||
else if (file.IsObjectPropertyInstantiated("ListItemAllFields"))
|
||||
{
|
||||
result.ContentLength = Convert.ToInt64(file.ListItemAllFields["File_x0020_Size"]);
|
||||
}
|
||||
|
||||
return result;
|
||||
}
|
||||
|
||||
#endregion
|
||||
|
||||
#region Folders
|
||||
|
||||
public Folder RootFolder
|
||||
{
|
||||
get
|
||||
{
|
||||
var key = "spointd-" + MakeId();
|
||||
var folder = SharePointProviderInfoHelper.GetFolder(key);
|
||||
if (folder == null)
|
||||
{
|
||||
folder = GetFolderById(SpRootFolderId);
|
||||
SharePointProviderInfoHelper.AddFolder(key, folder);
|
||||
}
|
||||
return folder;
|
||||
}
|
||||
}
|
||||
|
||||
public ILog Log { get; }
|
||||
public IServiceProvider ServiceProvider { get; }
|
||||
public TenantUtil TenantUtil { get; }
|
||||
public SharePointProviderInfoHelper SharePointProviderInfoHelper { get; }
|
||||
|
||||
public Folder GetFolderById(object id)
|
||||
{
|
||||
var key = "spointd-" + MakeId(id);
|
||||
var folder = SharePointProviderInfoHelper.GetFolder(key);
|
||||
if (folder == null)
|
||||
{
|
||||
folder = GetFolder(id);
|
||||
if (folder != null)
|
||||
{
|
||||
SharePointProviderInfoHelper.AddFolder(key, folder);
|
||||
}
|
||||
}
|
||||
return folder;
|
||||
}
|
||||
|
||||
private Folder GetFolder(object id)
|
||||
{
|
||||
if ((string)id == "") id = SpRootFolderId;
|
||||
var folder = clientContext.Web.GetFolderByServerRelativeUrl((string)id);
|
||||
clientContext.Load(folder);
|
||||
clientContext.Load(folder.Files, collection => collection.IncludeWithDefaultProperties(r => r.ListItemAllFields));
|
||||
clientContext.Load(folder.Folders);
|
||||
|
||||
try
|
||||
{
|
||||
clientContext.ExecuteQuery();
|
||||
}
|
||||
catch (Exception ex)
|
||||
{
|
||||
SharePointProviderInfoHelper.PublishFolder(MakeId(GetParentFolderId(id)));
|
||||
var serverException = (ServerException)ex;
|
||||
if (serverException.ServerErrorTypeName == (typeof(FileNotFoundException)).ToString())
|
||||
{
|
||||
return null;
|
||||
}
|
||||
return new SharePointFolderErrorEntry(folder.Context, folder.Path) { Error = ex.Message, ID = id };
|
||||
}
|
||||
|
||||
return folder;
|
||||
}
|
||||
|
||||
public Folder GetParentFolder(string serverRelativeUrl)
|
||||
{
|
||||
return GetFolderById(GetParentFolderId(serverRelativeUrl));
|
||||
}
|
||||
|
||||
public IEnumerable<File> GetFolderFiles(object id)
|
||||
{
|
||||
var folder = GetFolderById(id);
|
||||
if (folder is SharePointFolderErrorEntry) return new List<File>();
|
||||
|
||||
return GetFolderById(id).Files;
|
||||
}
|
||||
|
||||
public IEnumerable<Folder> GetFolderFolders(object id)
|
||||
{
|
||||
var folder = GetFolderById(id);
|
||||
if (folder is SharePointFolderErrorEntry) return new List<Folder>();
|
||||
|
||||
return folder.Folders.ToList().Where(r => r.ServerRelativeUrl != SpRootFolderId + "/" + "Forms");
|
||||
}
|
||||
|
||||
public object RenameFolder(object id, string newTitle)
|
||||
{
|
||||
SharePointProviderInfoHelper.PublishFolder(MakeId(id), MakeId(GetParentFolderId(id)));
|
||||
|
||||
var folder = GetFolderById(id);
|
||||
if (folder is SharePointFolderErrorEntry) return MakeId(id);
|
||||
|
||||
return MakeId(MoveFld(folder, GetParentFolderId(id) + "/" + newTitle).ServerRelativeUrl);
|
||||
}
|
||||
|
||||
public string MoveFolder(string id, string toFolderId)
|
||||
{
|
||||
SharePointProviderInfoHelper.PublishFolder(MakeId(id), MakeId(GetParentFolderId(id)), MakeId(toFolderId));
|
||||
|
||||
var folder = GetFolderById(id);
|
||||
if (folder is SharePointFolderErrorEntry) return MakeId(id);
|
||||
|
||||
return MakeId(MoveFld(folder, toFolderId + "/" + GetFolderById(id).Name).ServerRelativeUrl);
|
||||
}
|
||||
|
||||
public Folder CopyFolder(object id, object toFolderId)
|
||||
{
|
||||
SharePointProviderInfoHelper.PublishFolder(MakeId(toFolderId));
|
||||
|
||||
var folder = GetFolderById(id);
|
||||
if (folder is SharePointFolderErrorEntry) return folder;
|
||||
|
||||
return MoveFld(folder, toFolderId + "/" + GetFolderById(id).Name, false);
|
||||
}
|
||||
|
||||
private Folder MoveFld(Folder folder, string newUrl, bool delete = true)
|
||||
{
|
||||
var newFolder = CreateFolder(newUrl);
|
||||
|
||||
if (delete)
|
||||
{
|
||||
folder.Folders.ToList().ForEach(r => MoveFolder(r.ServerRelativeUrl, newUrl));
|
||||
folder.Files.ToList().ForEach(r => MoveFile(r.ServerRelativeUrl, newUrl));
|
||||
|
||||
folder.DeleteObject();
|
||||
clientContext.ExecuteQuery();
|
||||
}
|
||||
else
|
||||
{
|
||||
folder.Folders.ToList().ForEach(r => CopyFolder(r.ServerRelativeUrl, newUrl));
|
||||
folder.Files.ToList().ForEach(r => CopyFile(r.ServerRelativeUrl, newUrl));
|
||||
}
|
||||
|
||||
return newFolder;
|
||||
}
|
||||
|
||||
public Folder CreateFolder(string id)
|
||||
{
|
||||
var folder = clientContext.Web.RootFolder.Folders.Add(id);
|
||||
clientContext.Load(folder);
|
||||
clientContext.ExecuteQuery();
|
||||
|
||||
SharePointProviderInfoHelper.CreateFolder(id, MakeId(GetParentFolderId(id)), folder);
|
||||
return folder;
|
||||
}
|
||||
|
||||
public void DeleteFolder(string id)
|
||||
{
|
||||
SharePointProviderInfoHelper.PublishFolder(MakeId(id), MakeId(GetParentFolderId(id)));
|
||||
|
||||
var folder = GetFolderById(id);
|
||||
|
||||
if (folder is SharePointFolderErrorEntry) return;
|
||||
|
||||
folder.DeleteObject();
|
||||
clientContext.ExecuteQuery();
|
||||
}
|
||||
|
||||
public Folder<string> ToFolder(Folder folder)
|
||||
{
|
||||
if (folder == null) return null;
|
||||
|
||||
var result = ServiceProvider.GetService<Folder<string>>();
|
||||
|
||||
if (folder is SharePointFolderErrorEntry errorFolder)
|
||||
{
|
||||
result.ID = MakeId(errorFolder.ID);
|
||||
result.ParentFolderID = null;
|
||||
result.CreateBy = Owner;
|
||||
result.CreateOn = DateTime.UtcNow;
|
||||
result.FolderType = FolderType.DEFAULT;
|
||||
result.ModifiedBy = Owner;
|
||||
result.ModifiedOn = DateTime.UtcNow;
|
||||
result.ProviderId = ID;
|
||||
result.ProviderKey = ProviderKey;
|
||||
result.RootFolderCreator = Owner;
|
||||
result.RootFolderId = MakeId(SpRootFolderId);
|
||||
result.RootFolderType = RootFolderType;
|
||||
result.Shareable = false;
|
||||
result.Title = MakeTitle(GetTitleById(errorFolder.ID));
|
||||
result.TotalFiles = 0;
|
||||
result.TotalSubFolders = 0;
|
||||
result.Error = errorFolder.Error;
|
||||
|
||||
return result;
|
||||
}
|
||||
|
||||
var isRoot = folder.ServerRelativeUrl == SpRootFolderId;
|
||||
|
||||
result.ID = MakeId(isRoot ? "" : folder.ServerRelativeUrl);
|
||||
result.ParentFolderID = isRoot ? null : MakeId(GetParentFolderId(folder.ServerRelativeUrl));
|
||||
result.CreateBy = Owner;
|
||||
result.CreateOn = CreateOn;
|
||||
result.FolderType = FolderType.DEFAULT;
|
||||
result.ModifiedBy = Owner;
|
||||
result.ModifiedOn = CreateOn;
|
||||
result.ProviderId = ID;
|
||||
result.ProviderKey = ProviderKey;
|
||||
result.RootFolderCreator = Owner;
|
||||
result.RootFolderId = MakeId(RootFolder.ServerRelativeUrl);
|
||||
result.RootFolderType = RootFolderType;
|
||||
result.Shareable = false;
|
||||
result.Title = isRoot ? CustomerTitle : MakeTitle(folder.Name);
|
||||
result.TotalFiles = 0;
|
||||
result.TotalSubFolders = 0;
|
||||
|
||||
return result;
|
||||
}
|
||||
|
||||
#endregion
|
||||
|
||||
public string MakeId(string path = "")
|
||||
{
|
||||
path = path.Replace(SpRootFolderId, "");
|
||||
return string.Format("{0}{1}", "spoint-" + ID, string.IsNullOrEmpty(path) || path == "/" || path == SpRootFolderId ? "" : ("-" + path.Replace('/', '|')));
|
||||
}
|
||||
|
||||
private string MakeId(object path)
|
||||
{
|
||||
return MakeId((string)path);
|
||||
}
|
||||
|
||||
protected string MakeTitle(string name)
|
||||
{
|
||||
return Global.ReplaceInvalidCharsAndTruncate(name);
|
||||
}
|
||||
|
||||
protected string GetParentFolderId(string serverRelativeUrl)
|
||||
{
|
||||
var path = serverRelativeUrl.Split('/');
|
||||
|
||||
return string.Join("/", path.Take(path.Length - 1));
|
||||
}
|
||||
|
||||
protected string GetParentFolderId(object serverRelativeUrl)
|
||||
{
|
||||
return GetParentFolderId((string)serverRelativeUrl);
|
||||
}
|
||||
|
||||
protected string GetTitleById(object serverRelativeUrl)
|
||||
{
|
||||
return ((string)serverRelativeUrl).Split('/').Last();
|
||||
}
|
||||
|
||||
|
||||
public void Dispose()
|
||||
{
|
||||
clientContext.Dispose();
|
||||
}
|
||||
}
|
||||
|
||||
public class SharePointProviderInfoHelper
|
||||
{
|
||||
private readonly TimeSpan CacheExpiration;
|
||||
private readonly ICache FileCache;
|
||||
private readonly ICache FolderCache;
|
||||
private readonly ICacheNotify<SharePointProviderCacheItem> Notify;
|
||||
|
||||
public SharePointProviderInfoHelper(ICacheNotify<SharePointProviderCacheItem> notify)
|
||||
{
|
||||
CacheExpiration = TimeSpan.FromMinutes(1);
|
||||
FileCache = AscCache.Memory;
|
||||
FolderCache = AscCache.Memory;
|
||||
Notify = notify;
|
||||
|
||||
Notify.Subscribe((i) =>
|
||||
{
|
||||
if (!string.IsNullOrEmpty(i.FileKey))
|
||||
{
|
||||
FileCache.Remove("spointf-" + i.FileKey);
|
||||
}
|
||||
if (!string.IsNullOrEmpty(i.FolderKey))
|
||||
{
|
||||
FolderCache.Remove("spointd-" + i.FolderKey);
|
||||
}
|
||||
if (string.IsNullOrEmpty(i.FileKey) && string.IsNullOrEmpty(i.FolderKey))
|
||||
{
|
||||
FileCache.Remove(new Regex("^spointf-.*"));
|
||||
FolderCache.Remove(new Regex("^spointd-.*"));
|
||||
}
|
||||
}, CacheNotifyAction.Remove);
|
||||
}
|
||||
|
||||
public void Invalidate()
|
||||
{
|
||||
Notify.Publish(new SharePointProviderCacheItem { }, CacheNotifyAction.Remove);
|
||||
}
|
||||
public void PublishFolder(string id)
|
||||
{
|
||||
Notify.Publish(new SharePointProviderCacheItem { FolderKey = id }, CacheNotifyAction.Remove);
|
||||
}
|
||||
|
||||
public void PublishFolder(string id1, string id2)
|
||||
{
|
||||
PublishFolder(id1);
|
||||
PublishFolder(id2);
|
||||
}
|
||||
|
||||
public void PublishFolder(string id1, string id2, string id3)
|
||||
{
|
||||
PublishFolder(id1, id2);
|
||||
PublishFolder(id3);
|
||||
}
|
||||
|
||||
public void PublishFile(string fileId, string folderId)
|
||||
{
|
||||
Notify.Publish(new SharePointProviderCacheItem { FileKey = fileId, FolderKey = folderId }, CacheNotifyAction.Remove);
|
||||
}
|
||||
|
||||
public void CreateFolder(string id, string parentFolderId, Folder folder)
|
||||
{
|
||||
PublishFolder(parentFolderId);
|
||||
FolderCache.Insert("spointd-" + id, folder, DateTime.UtcNow.Add(CacheExpiration));
|
||||
}
|
||||
|
||||
public Folder GetFolder(string key)
|
||||
{
|
||||
return FolderCache.Get<Folder>(key);
|
||||
}
|
||||
|
||||
public void AddFolder(string key, Folder folder)
|
||||
{
|
||||
FolderCache.Insert(key, folder, DateTime.UtcNow.Add(CacheExpiration));
|
||||
}
|
||||
|
||||
public File GetFile(string key)
|
||||
{
|
||||
return FileCache.Get<File>(key);
|
||||
}
|
||||
|
||||
public void AddFile(string key, File file)
|
||||
{
|
||||
FileCache.Insert(key, file, DateTime.UtcNow.Add(CacheExpiration));
|
||||
}
|
||||
}
|
||||
|
||||
public static class SharePointProviderInfoExtension
|
||||
{
|
||||
public static DIHelper AddSharePointProviderInfoService(this DIHelper services)
|
||||
{
|
||||
services.TryAddScoped<SharePointProviderInfo>();
|
||||
services.TryAddSingleton<SharePointProviderInfoHelper>();
|
||||
|
||||
return services;
|
||||
}
|
||||
}
|
||||
}
|
Some files were not shown because too many files have changed in this diff Show More
Loading…
Reference in New Issue
Block a user