Merge branch 'master' into feature/crm-migrate

This commit is contained in:
Alexey Bannov 2020-04-02 22:43:10 +03:00
commit bbb4997f20
277 changed files with 38758 additions and 3280 deletions

View File

@ -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

View File

@ -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()

View File

@ -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}" : "")}")

View File

@ -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; }

View File

@ -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));
}
}

View File

@ -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;

View File

@ -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)
{
}

View File

@ -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)
{
}
}

View File

@ -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)
{
}

View File

@ -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()

View File

@ -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)
{

View File

@ -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)
{

View File

@ -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)
{
}

View File

@ -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)
{

View File

@ -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)
{
}

View File

@ -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)
{
}
}

View File

@ -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)
{
}

View File

@ -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)
{
}

View File

@ -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)
{

View File

@ -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)
{
}

View File

@ -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;

View File

@ -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"
}
},

View File

@ -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"
}
]
}

View File

@ -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

View File

@ -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; }
}

View File

@ -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
}

View File

@ -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
}

View File

@ -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);
}
}

View File

@ -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);
}
}

View File

@ -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);

View File

@ -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()
;
}
}

View File

@ -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()

View File

@ -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()

View File

@ -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()

View File

@ -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()

View File

@ -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 };
};
}

View File

@ -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
{

View File

@ -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;

View File

@ -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))
{

View 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;
}
}
}

View File

@ -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)
{

View File

@ -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

View File

@ -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;

View File

@ -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;

View File

@ -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
};

View File

@ -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)

View File

@ -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);
}
}

View File

@ -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);

View 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; }
}
}

View 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);
}
}
}

View 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();
}
}
}

View 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;
}
}
}

View 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;
}
}
}

View 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;
}
}
}

View 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;
}
}
}

View 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);
}
}
}

View 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;
}
}
}

View 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();
}
}
}

View 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));
}
}
}

View 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);
}
}
}

View 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();
}
}
}

View 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;
}
}
}

View 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;
}
}
}

View 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;
}
}
}

View 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;
}
}
}

View 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;
}
}
}

View 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;
}
}
}

View 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;
}
}
}
}
}

View 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();
}
}
}

View 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;
}
}
}

View 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;
}
}
}

View 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;
}
}
}

View 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;
}
}
}

View 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;
}
}
}

View 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;
}
}
}

View 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);
}
}

View 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;
}
}
}

View 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);
}
}
}

View 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();
}
}
}

View 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;
}
}
}

View 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;
}
}
}

View 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;
}
}
}

View 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;
}
}
}

View 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;
}
}
}

View 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;
}
}
}

View 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>();
}
}
}

View 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();
}
}
}

View 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();
}
}
}

View 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();
}
}
}

View 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();
}
}
}

View 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();
}
}
}

View 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();
}
}
}
}

View 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;
}
}
}

View 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();
}
}
}

View 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; }
}
}

View 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;
}
}
}

View 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;
}
}
}

View 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