Merge branch 'develop' into feature/branding

This commit is contained in:
pavelbannov 2022-06-24 18:51:33 +03:00
commit b58422cfee
132 changed files with 7609 additions and 1243 deletions

View File

@ -47,7 +47,8 @@ global using ASC.Api.Core.Core;
global using ASC.Api.Core.Extensions;
global using ASC.Api.Core.Log;
global using ASC.Api.Core.Middleware;
global using ASC.Api.Core.Routing;
global using ASC.Api.Core.Routing;
global using ASC.Api.Core.Security;
global using ASC.Common;
global using ASC.Common.Caching;
global using ASC.Common.DependencyInjection;
@ -67,7 +68,10 @@ global using ASC.Core.Users;
global using ASC.EventBus;
global using ASC.EventBus.Abstractions;
global using ASC.EventBus.RabbitMQ;
global using ASC.IPSecurity;
global using ASC.IPSecurity;
global using ASC.MessagingSystem.Data;
global using ASC.MessagingSystem.Core;
global using ASC.MessagingSystem.Models;
global using ASC.Security.Cryptography;
global using ASC.Web.Api.Routing;
global using ASC.Web.Core;
@ -100,7 +104,8 @@ global using Microsoft.AspNetCore.Mvc.Routing;
global using Microsoft.AspNetCore.Routing;
global using Microsoft.AspNetCore.Routing.Constraints;
global using Microsoft.AspNetCore.Routing.Patterns;
global using Microsoft.AspNetCore.Server.Kestrel.Core;
global using Microsoft.AspNetCore.Server.Kestrel.Core;
global using Microsoft.AspNetCore.WebUtilities;
global using Microsoft.Extensions.Configuration;
global using Microsoft.Extensions.DependencyInjection;
global using Microsoft.Extensions.Diagnostics.HealthChecks;
@ -116,7 +121,9 @@ global using NLog;
global using NLog.Config;
global using NLog.Extensions.Logging;
global using RabbitMQ.Client;
global using RabbitMQ.Client;
global using AutoMapper;
global using StackExchange.Redis.Extensions.Core.Configuration;
global using StackExchange.Redis.Extensions.Newtonsoft;

View File

@ -0,0 +1,175 @@
// (c) Copyright Ascensio System SIA 2010-2022
//
// This program is a free software product.
// You can redistribute it and/or modify it under the terms
// of the GNU Affero General Public License (AGPL) version 3 as published by the Free Software
// Foundation. In accordance with Section 7(a) of the GNU AGPL 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 details, see
// the GNU AGPL at: http://www.gnu.org/licenses/agpl-3.0.html
//
// You can contact Ascensio System SIA at Lubanas st. 125a-25, Riga, Latvia, EU, LV-1021.
//
// The interactive user interfaces in modified source and object code versions of the Program must
// display Appropriate Legal Notices, as required under Section 5 of the GNU AGPL version 3.
//
// Pursuant to Section 7(b) of the License you must retain the original Product logo when
// distributing the program. Pursuant to Section 7(e) we decline to grant you any rights under
// trademark law for use of our trademarks.
//
// All the Product's GUI elements, including illustrations and icon sets, as well as technical writing
// content are licensed under the terms of the Creative Commons Attribution-ShareAlike 4.0
// International. See the License terms at http://creativecommons.org/licenses/by-sa/4.0/legalcode
using static ASC.Security.Cryptography.EmailValidationKeyProvider;
namespace ASC.Api.Core.Security;
[Transient]
public class EmailValidationKeyModelHelper
{
private readonly IHttpContextAccessor _httpContextAccessor;
private readonly EmailValidationKeyProvider _provider;
private readonly AuthContext _authContext;
private readonly UserManager _userManager;
private readonly AuthManager _authentication;
private readonly RoomInvitationLinksService _roomLinksService;
public EmailValidationKeyModelHelper(
IHttpContextAccessor httpContextAccessor,
EmailValidationKeyProvider provider,
AuthContext authContext,
UserManager userManager,
AuthManager authentication,
RoomInvitationLinksService roomLinksService)
{
_httpContextAccessor = httpContextAccessor;
_provider = provider;
_authContext = authContext;
_userManager = userManager;
_authentication = authentication;
_roomLinksService = roomLinksService;
}
public EmailValidationKeyModel GetModel()
{
var request = QueryHelpers.ParseQuery(_httpContextAccessor.HttpContext.Request.Headers["confirm"]);
request.TryGetValue("type", out var type);
ConfirmType? cType = null;
if (Enum.TryParse<ConfirmType>(type, out var confirmType))
{
cType = confirmType;
}
request.TryGetValue("key", out var key);
request.TryGetValue("emplType", out var emplType);
Enum.TryParse<EmployeeType>(emplType, out var employeeType);
request.TryGetValue("email", out var _email);
request.TryGetValue("uid", out var userIdKey);
Guid.TryParse(userIdKey, out var userId);
request.TryGetValue("access", out var fileShareRaw);
int.TryParse(fileShareRaw, out var fileShare);
request.TryGetValue("roomId", out var roomId);
return new EmailValidationKeyModel
{
Email = _email,
EmplType = employeeType,
Key = key,
Type = cType,
UiD = userId,
RoomAccess = fileShare,
RoomId = roomId
};
}
public ValidationResult Validate(EmailValidationKeyModel inDto)
{
var (key, emplType, email, uiD, type, fileShare, roomId) = inDto;
ValidationResult checkKeyResult;
switch (type)
{
case ConfirmType.EmpInvite:
checkKeyResult = _provider.ValidateEmailKey(email + type + (int)emplType, key, _provider.ValidEmailKeyInterval);
break;
case ConfirmType.LinkInvite:
if (fileShare != default && !string.IsNullOrEmpty(roomId))
{
checkKeyResult = _provider.ValidateEmailKey(email + type + ((int)emplType + (int)fileShare + roomId), key, _provider.ValidEmailKeyInterval);
if (checkKeyResult == ValidationResult.Ok &&
!_roomLinksService.VisitProcess(roomId, email, key, _provider.ValidVisitLinkInterval))
{
checkKeyResult = ValidationResult.Expired;
}
break;
}
checkKeyResult = _provider.ValidateEmailKey(type.ToString() + (int)emplType, key, _provider.ValidEmailKeyInterval);
break;
case ConfirmType.PortalOwnerChange:
checkKeyResult = _provider.ValidateEmailKey(email + type + uiD.HasValue, key, _provider.ValidEmailKeyInterval);
break;
case ConfirmType.EmailChange:
checkKeyResult = _provider.ValidateEmailKey(email + type + _authContext.CurrentAccount.ID, key, _provider.ValidEmailKeyInterval);
break;
case ConfirmType.PasswordChange:
var hash = _authentication.GetUserPasswordStamp(_userManager.GetUserByEmail(email).Id).ToString("s");
checkKeyResult = _provider.ValidateEmailKey(email + type + hash, key, _provider.ValidEmailKeyInterval);
break;
case ConfirmType.Activation:
checkKeyResult = _provider.ValidateEmailKey(email + type + uiD, key, _provider.ValidEmailKeyInterval);
break;
case ConfirmType.ProfileRemove:
// validate UiD
var user = _userManager.GetUsers(uiD.GetValueOrDefault());
if (user == null || user.Status == EmployeeStatus.Terminated || _authContext.IsAuthenticated && _authContext.CurrentAccount.ID != uiD)
{
return ValidationResult.Invalid;
}
checkKeyResult = _provider.ValidateEmailKey(email + type + uiD, key, _provider.ValidEmailKeyInterval);
break;
case ConfirmType.Wizard:
checkKeyResult = _provider.ValidateEmailKey("" + type, key, _provider.ValidEmailKeyInterval);
break;
case ConfirmType.PhoneActivation:
case ConfirmType.PhoneAuth:
case ConfirmType.TfaActivation:
case ConfirmType.TfaAuth:
case ConfirmType.Auth:
checkKeyResult = _provider.ValidateEmailKey(email + type, key, _provider.ValidAuthKeyInterval);
break;
case ConfirmType.PortalContinue:
checkKeyResult = _provider.ValidateEmailKey(email + type, key);
break;
default:
checkKeyResult = _provider.ValidateEmailKey(email + type, key, _provider.ValidEmailKeyInterval);
break;
}
return checkKeyResult;
}
}

View File

@ -0,0 +1,124 @@
// (c) Copyright Ascensio System SIA 2010-2022
//
// This program is a free software product.
// You can redistribute it and/or modify it under the terms
// of the GNU Affero General Public License (AGPL) version 3 as published by the Free Software
// Foundation. In accordance with Section 7(a) of the GNU AGPL 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 details, see
// the GNU AGPL at: http://www.gnu.org/licenses/agpl-3.0.html
//
// You can contact Ascensio System SIA at Lubanas st. 125a-25, Riga, Latvia, EU, LV-1021.
//
// The interactive user interfaces in modified source and object code versions of the Program must
// display Appropriate Legal Notices, as required under Section 5 of the GNU AGPL version 3.
//
// Pursuant to Section 7(b) of the License you must retain the original Product logo when
// distributing the program. Pursuant to Section 7(e) we decline to grant you any rights under
// trademark law for use of our trademarks.
//
// All the Product's GUI elements, including illustrations and icon sets, as well as technical writing
// content are licensed under the terms of the Creative Commons Attribution-ShareAlike 4.0
// International. See the License terms at http://creativecommons.org/licenses/by-sa/4.0/legalcode
namespace ASC.Api.Core.Security;
[Scope]
public class RoomInvitationLinksService
{
private readonly CommonLinkUtility _commonLinkUtility;
private readonly IHttpContextAccessor _httpContextAccessor;
private readonly MessageTarget _messageTarget;
private readonly UserManager _userManager;
private readonly Lazy<MessagesContext> _messagesContext;
private readonly MessageService _messageService;
public RoomInvitationLinksService(
CommonLinkUtility commonLinkUtility,
IHttpContextAccessor httpContextAccessor,
MessageTarget messageTarget,
UserManager userManager,
DbContextManager<MessagesContext> dbContextManager,
MessageService messageService)
{
_commonLinkUtility = commonLinkUtility;
_httpContextAccessor = httpContextAccessor;
_messageTarget = messageTarget;
_userManager = userManager;
_messagesContext = new Lazy<MessagesContext>(() => dbContextManager.Value);
_messageService = messageService;
}
public string GenerateLink<T>(T id, int fileShare, EmployeeType employeeType, Guid guid)
{
return GenerateLink(id, string.Empty, fileShare, employeeType, guid);
}
public string GenerateLink<T>(T id, string email, int fileShare, EmployeeType employeeType, Guid guid)
{
var user = _userManager.GetUserByEmail(email);
if (user != ASC.Core.Users.Constants.LostUser)
{
throw new Exception("The user with this email already exists");
}
var postifx = (int)employeeType + fileShare + id.ToString();
var link = _commonLinkUtility.GetConfirmationUrl(email, ConfirmType.LinkInvite, postifx, guid)
+ $"&emplType={employeeType:d}&roomId={id}&access={fileShare}";
return link;
}
public bool VisitProcess(string id, string email, string key, TimeSpan interval)
{
if (!string.IsNullOrEmpty(email))
{
var user = _userManager.GetUserByEmail(email);
if (user != ASC.Core.Users.Constants.LostUser)
{
return false;
}
}
var message = GetLinkInfo(id, email, key);
if (message == null)
{
SaveVisitLinkInfo(id, email, key);
return true;
}
return message.Date + interval > DateTime.UtcNow;
}
private void SaveVisitLinkInfo(string id, string email, string key)
{
var headers = _httpContextAccessor?.HttpContext?.Request?.Headers;
var target = _messageTarget.CreateFromGroupValues(email != null ? new[] { id, email } : new[] { id });
_messageService.Send(headers, MessageAction.RoomInviteLinkUsed, target, key);
}
private AuditEvent GetLinkInfo(string id, string email, string key)
{
var context = _messagesContext.Value;
var target = _messageTarget.CreateFromGroupValues(email != null ? new[] { id, email } : new[] { id });
var description = JsonConvert.SerializeObject(new[] { key },
new JsonSerializerSettings
{
DateTimeZoneHandling = DateTimeZoneHandling.Utc
});
var message = context.AuditEvents.Where(a => a.Target == target.ToString() &&
a.DescriptionRaw == description).FirstOrDefault();
return message;
}
}

View File

@ -33,6 +33,7 @@ public class CoreBaseSettings
private string _basedomain;
private bool? _personal;
private bool? _customMode;
private bool? _disableDocSpace;
private IConfiguration Configuration { get; }
@ -61,6 +62,8 @@ public class CoreBaseSettings
_personal ?? (bool)(_personal = string.Equals(Configuration["core:personal"], "true", StringComparison.OrdinalIgnoreCase));
public bool CustomMode => _customMode ?? (bool)(_customMode = string.Equals(Configuration["core:custom-mode"], "true", StringComparison.OrdinalIgnoreCase));
public bool DisableDocSpace => _disableDocSpace ?? (bool)(_disableDocSpace = string.Equals(Configuration["core:disableDocspace"], "true", StringComparison.OrdinalIgnoreCase));
}
class ConfigureCoreSettings : IConfigureNamedOptions<CoreSettings>

View File

@ -718,6 +718,11 @@ public class UserManager
group = ToGroup(Constants.BuildinGroups.FirstOrDefault(r => r.ID == groupID) ?? Constants.LostGroupInfo);
}
if (group == null)
{
return Constants.LostGroupInfo;
}
return new GroupInfo
{
ID = group.Id,

View File

@ -32,17 +32,26 @@ public class RegisterInstanceWorkerService<T> : BackgroundService where T : IHos
private readonly ILogger _logger;
private readonly IHostApplicationLifetime _applicationLifetime;
private readonly IServiceProvider _serviceProvider;
private readonly int _intervalCheckRegisterInstanceInSeconds;
public static readonly string InstanceId =
$"{typeof(T).GetFormattedName()}_{DateTime.UtcNow.Ticks}";
public RegisterInstanceWorkerService(
ILogger<RegisterInstanceWorkerService<T>> logger,
IServiceProvider serviceProvider,
IHostApplicationLifetime applicationLifetime)
IHostApplicationLifetime applicationLifetime,
IConfiguration configuration)
{
_logger = logger;
_serviceProvider = serviceProvider;
_applicationLifetime = applicationLifetime;
_applicationLifetime = applicationLifetime;
if (!int.TryParse(configuration["core:hosting:intervalCheckRegisterInstanceInSeconds"], out _intervalCheckRegisterInstanceInSeconds))
{
_intervalCheckRegisterInstanceInSeconds = 1;
}
_intervalCheckRegisterInstanceInSeconds = _intervalCheckRegisterInstanceInSeconds*1000;
}
protected override async Task ExecuteAsync(CancellationToken stoppingToken)
@ -50,7 +59,7 @@ public class RegisterInstanceWorkerService<T> : BackgroundService where T : IHos
while (!stoppingToken.IsCancellationRequested)
{
try
{
{
using var scope = _serviceProvider.CreateScope();
var registerInstanceService = scope.ServiceProvider.GetService<IRegisterInstanceManager<T>>();
@ -60,7 +69,7 @@ public class RegisterInstanceWorkerService<T> : BackgroundService where T : IHos
_logger.TraceWorkingRunnging(DateTimeOffset.Now);
await Task.Delay(1000, stoppingToken);
await Task.Delay(_intervalCheckRegisterInstanceInSeconds, stoppingToken);
}
catch (Exception ex)
{

View File

@ -33,6 +33,7 @@ public class AuditEvent : MessageEvent, IMapFrom<EventMessage>
public void Mapping(Profile profile)
{
profile.CreateMap<MessageEvent, AuditEvent>();
profile.CreateMap<EventMessage, AuditEvent>()
.ConvertUsing<EventTypeConverter>();
}

File diff suppressed because it is too large Load Diff

View File

@ -53,7 +53,7 @@ public class MessageTarget
};
}
public MessageTarget Create(IEnumerable<string> value)
public MessageTarget CreateFromGroupValues(IEnumerable<string> value)
{
var res = new MessageTarget(_option)
{

View File

@ -35,11 +35,13 @@ public class EmailValidationKeyProvider
Invalid,
Expired
}
public TimeSpan ValidEmailKeyInterval { get; }
public TimeSpan ValidAuthKeyInterval { get; }
public TimeSpan ValidVisitLinkInterval { get; }
private readonly ILogger<EmailValidationKeyProvider> _logger;
private static readonly DateTime _from = new DateTime(2010, 01, 01, 0, 0, 0, DateTimeKind.Utc);
internal readonly TimeSpan _validEmailKeyInterval;
internal readonly TimeSpan _validAuthKeyInterval;
private readonly MachinePseudoKeys _machinePseudoKeys;
private readonly TenantManager _tenantManager;
@ -55,9 +57,13 @@ public class EmailValidationKeyProvider
{
authValidInterval = TimeSpan.FromHours(1);
}
_validEmailKeyInterval = validInterval;
_validAuthKeyInterval = authValidInterval;
if (!TimeSpan.TryParse(configuration["visit:validinterval"], out var validVisitLinkInterval))
{
ValidVisitLinkInterval = TimeSpan.FromMinutes(15);
}
ValidEmailKeyInterval = validInterval;
ValidAuthKeyInterval = authValidInterval;
_logger = logger;
}
@ -162,133 +168,11 @@ public class EmailValidationKeyModel
public string Email { get; set; }
public Guid? UiD { get; set; }
public ConfirmType? Type { get; set; }
public int RoomAccess { get; set; }
public string RoomId { get; set; }
public void Deconstruct(out string key, out EmployeeType? emplType, out string email, out Guid? uiD, out ConfirmType? type)
public void Deconstruct(out string key, out EmployeeType? emplType, out string email, out Guid? uiD, out ConfirmType? type, out int roomAccess, out string roomId)
{
(key, emplType, email, uiD, type) = (Key, EmplType, Email, UiD, Type);
(key, emplType, email, uiD, type, roomAccess, roomId) = (Key, EmplType, Email, UiD, Type, RoomAccess, RoomId);
}
}
[Transient]
public class EmailValidationKeyModelHelper
{
private readonly IHttpContextAccessor _httpContextAccessor;
private readonly EmailValidationKeyProvider _provider;
private readonly AuthContext _authContext;
private readonly UserManager _userManager;
private readonly AuthManager _authentication;
public EmailValidationKeyModelHelper(
IHttpContextAccessor httpContextAccessor,
EmailValidationKeyProvider provider,
AuthContext authContext,
UserManager userManager,
AuthManager authentication)
{
_httpContextAccessor = httpContextAccessor;
_provider = provider;
_authContext = authContext;
_userManager = userManager;
_authentication = authentication;
}
public EmailValidationKeyModel GetModel()
{
var request = QueryHelpers.ParseQuery(_httpContextAccessor.HttpContext.Request.Headers["confirm"]);
request.TryGetValue("type", out var type);
ConfirmType? cType = null;
if (Enum.TryParse<ConfirmType>(type, out var confirmType))
{
cType = confirmType;
}
request.TryGetValue("key", out var key);
request.TryGetValue("emplType", out var emplType);
Enum.TryParse<EmployeeType>(emplType, out var employeeType);
request.TryGetValue("email", out var _email);
request.TryGetValue("uid", out var userIdKey);
Guid.TryParse(userIdKey, out var userId);
return new EmailValidationKeyModel
{
Email = _email,
EmplType = employeeType,
Key = key,
Type = cType,
UiD = userId
};
}
public ValidationResult Validate(EmailValidationKeyModel inDto)
{
var (key, emplType, email, uiD, type) = inDto;
ValidationResult checkKeyResult;
switch (type)
{
case ConfirmType.EmpInvite:
checkKeyResult = _provider.ValidateEmailKey(email + type + (int)emplType, key, _provider._validEmailKeyInterval);
break;
case ConfirmType.LinkInvite:
checkKeyResult = _provider.ValidateEmailKey(type.ToString() + (int)emplType, key, _provider._validEmailKeyInterval);
break;
case ConfirmType.PortalOwnerChange:
checkKeyResult = _provider.ValidateEmailKey(email + type + uiD.HasValue, key, _provider._validEmailKeyInterval);
break;
case ConfirmType.EmailChange:
checkKeyResult = _provider.ValidateEmailKey(email + type + _authContext.CurrentAccount.ID, key, _provider._validEmailKeyInterval);
break;
case ConfirmType.PasswordChange:
var hash = _authentication.GetUserPasswordStamp(_userManager.GetUserByEmail(email).Id).ToString("s");
checkKeyResult = _provider.ValidateEmailKey(email + type + hash, key, _provider._validEmailKeyInterval);
break;
case ConfirmType.Activation:
checkKeyResult = _provider.ValidateEmailKey(email + type + uiD, key, _provider._validEmailKeyInterval);
break;
case ConfirmType.ProfileRemove:
// validate UiD
var user = _userManager.GetUsers(uiD.GetValueOrDefault());
if (user == null || user.Status == EmployeeStatus.Terminated || _authContext.IsAuthenticated && _authContext.CurrentAccount.ID != uiD)
{
return ValidationResult.Invalid;
}
checkKeyResult = _provider.ValidateEmailKey(email + type + uiD, key, _provider._validEmailKeyInterval);
break;
case ConfirmType.Wizard:
checkKeyResult = _provider.ValidateEmailKey("" + type, key, _provider._validEmailKeyInterval);
break;
case ConfirmType.PhoneActivation:
case ConfirmType.PhoneAuth:
case ConfirmType.TfaActivation:
case ConfirmType.TfaAuth:
case ConfirmType.Auth:
checkKeyResult = _provider.ValidateEmailKey(email + type, key, _provider._validAuthKeyInterval);
break;
case ConfirmType.PortalContinue:
checkKeyResult = _provider.ValidateEmailKey(email + type, key);
break;
default:
checkKeyResult = _provider.ValidateEmailKey(email + type, key, _provider._validEmailKeyInterval);
break;
}
return checkKeyResult;
}
}
}

View File

@ -54,5 +54,5 @@ public enum ConfirmType
Auth,
TfaActivation,
TfaAuth,
Wizard
Wizard,
}

View File

@ -24,22 +24,6 @@
// content are licensed under the terms of the Creative Commons Attribution-ShareAlike 4.0
// International. See the License terms at http://creativecommons.org/licenses/by-sa/4.0/legalcode
/*
*
* (c) Copyright Ascensio System Limited 2010-2021
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
* http://www.apache.org/licenses/LICENSE-2.0
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*
*/
namespace ASC.FederatedLogin.LoginProviders;
[Scope]
@ -130,23 +114,25 @@ public class AppleIdLoginProvider : BaseLoginProvider<AppleIdLoginProvider>
}
private string GenerateSecret()
{
using (var cngKey = CngKey.Import(Convert.FromBase64String(PrivateKey), CngKeyBlobFormat.Pkcs8PrivateBlob))
{
var handler = new JwtSecurityTokenHandler();
var token = handler.CreateJwtSecurityToken(
issuer: TeamId,
audience: "https://appleid.apple.com",
subject: new ClaimsIdentity(new List<Claim> { new Claim("sub", ClientID) }),
issuedAt: DateTime.UtcNow,
notBefore: DateTime.UtcNow,
expires: DateTime.UtcNow.AddMinutes(5),
signingCredentials: new SigningCredentials(new ECDsaSecurityKey(new ECDsaCng(cngKey)), SecurityAlgorithms.EcdsaSha256)
);
token.Header.Add("kid", KeyId);
return handler.WriteToken(token);
}
{
using var ecdsa = ECDsa.Create();
ecdsa.ImportPkcs8PrivateKey(Convert.FromBase64String(PrivateKey), out _);
var handler = new JwtSecurityTokenHandler();
var token = handler.CreateJwtSecurityToken(
issuer: TeamId,
audience: "https://appleid.apple.com",
subject: new ClaimsIdentity(new List<Claim> { new Claim("sub", ClientID) }),
issuedAt: DateTime.UtcNow,
notBefore: DateTime.UtcNow,
expires: DateTime.UtcNow.AddMinutes(5),
signingCredentials: new SigningCredentials(new ECDsaSecurityKey(ecdsa), SecurityAlgorithms.EcdsaSha256)
);
token.Header.Add("kid", KeyId);
return handler.WriteToken(token);
}
private ClaimsPrincipal ValidateIdToken(string idToken)

View File

@ -88,9 +88,11 @@ public class GosUslugiLoginProvider : BaseLoginProvider<GosUslugiLoginProvider>
public override LoginProfile GetLoginProfile(string accessToken)
{
#pragma warning disable CS0618 // Type or member is obsolete
var tokenPayloadString = JwtBuilder.Create()
.WithAlgorithm(new HMACSHA256Algorithm())
.Decode(accessToken);
#pragma warning restore CS0618 // Type or member is obsolete
var tokenPayload = JObject.Parse(tokenPayloadString);
if (tokenPayload == null)
{

View File

@ -24,22 +24,6 @@
// content are licensed under the terms of the Creative Commons Attribution-ShareAlike 4.0
// International. See the License terms at http://creativecommons.org/licenses/by-sa/4.0/legalcode
/*
*
* (c) Copyright Ascensio System Limited 2010-2021
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
* http://www.apache.org/licenses/LICENSE-2.0
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*
*/
namespace ASC.FederatedLogin.LoginProviders;
public class MicrosoftLoginProvider : BaseLoginProvider<MicrosoftLoginProvider>

View File

@ -38,8 +38,10 @@ public class MessagesRepository : IDisposable
private readonly IServiceScopeFactory _serviceScopeFactory;
private readonly IMapper _mapper;
private readonly ILogger<MessagesRepository> _logger;
private readonly Timer _timer;
private readonly Timer _timer;
private readonly int _cacheLimit;
private readonly HashSet<MessageAction> _forceSaveAuditActions = new HashSet<MessageAction>
{ MessageAction.RoomInviteLinkUsed, MessageAction.UserSentPasswordChangeInstructions };
public MessagesRepository(IServiceScopeFactory serviceScopeFactory, ILogger<MessagesRepository> logger, IMapper mapper, IConfiguration configuration)
{
@ -52,28 +54,29 @@ public class MessagesRepository : IDisposable
_timer = new Timer(FlushCache);
_mapper = mapper;
_mapper = mapper;
var minutes = configuration["messaging:CacheTimeFromMinutes"];
var limit = configuration["messaging:CacheLimit"];
_cacheTime = int.TryParse(minutes, out var cacheTime) ? TimeSpan.FromMinutes(cacheTime) : TimeSpan.FromMinutes(1);
_cacheLimit = int.TryParse(limit, out var cacheLimit) ? cacheLimit : 100;
}
}
~MessagesRepository()
{
{
FlushCache(true);
}
private bool ForseSave(EventMessage message)
{
// messages with action code < 2000 are related to login-history
if ((int)message.Action < 2000)
{
// messages with action code < 2000 are related to login-history
if ((int)message.Action < 2000)
{
return true;
}
return message.Action == MessageAction.UserSentPasswordChangeInstructions;
return _forceSaveAuditActions.Contains(message.Action);
}
public int Add(EventMessage message)
@ -94,8 +97,8 @@ public class MessagesRepository : IDisposable
}
using var scope = _serviceScopeFactory.CreateScope();
using var ef = scope.ServiceProvider.GetService<DbContextManager<MessagesContext>>().Get("messages");
using var ef = scope.ServiceProvider.GetService<DbContextManager<MessagesContext>>().Get("messages");
if ((int)message.Action < 2000)
{
id = AddLoginEvent(message, ef);
@ -125,12 +128,12 @@ public class MessagesRepository : IDisposable
private void FlushCache(object state)
{
FlushCache(false);
}
}
private void FlushCache(bool isDisposed = false)
{
List<EventMessage> events = null;
if (DateTime.UtcNow > _lastSave.Add(_cacheTime) || _cache.Count > _cacheLimit || isDisposed)
{
lock (_cache)
@ -149,15 +152,15 @@ public class MessagesRepository : IDisposable
return;
}
using var scope = _serviceScopeFactory.CreateScope();
using var ef = scope.ServiceProvider.GetService<DbContextManager<MessagesContext>>().Get("messages");
using var scope = _serviceScopeFactory.CreateScope();
using var ef = scope.ServiceProvider.GetService<DbContextManager<MessagesContext>>().Get("messages");
var strategy = ef.Database.CreateExecutionStrategy();
strategy.Execute(() =>
{
using var tx = ef.Database.BeginTransaction(IsolationLevel.ReadUncommitted);
var dict = new Dictionary<string, ClientInfo>();
foreach (var message in events)
{
if (!string.IsNullOrEmpty(message.UAHeader))
@ -183,9 +186,9 @@ public class MessagesRepository : IDisposable
{
AddAuditEvent(message, ef);
}
}
}
}
tx.Commit();
});
}
@ -195,7 +198,7 @@ public class MessagesRepository : IDisposable
var loginEvent = _mapper.Map<EventMessage, LoginEvent>(message);
dbContext.LoginEvents.Add(loginEvent);
dbContext.SaveChanges();
dbContext.SaveChanges();
return loginEvent.Id;
}
@ -205,8 +208,8 @@ public class MessagesRepository : IDisposable
var auditEvent = _mapper.Map<EventMessage, AuditEvent>(message);
dbContext.AuditEvents.Add(auditEvent);
dbContext.SaveChanges();
dbContext.SaveChanges();
return auditEvent.Id;
}

View File

@ -24,22 +24,6 @@
// content are licensed under the terms of the Creative Commons Attribution-ShareAlike 4.0
// International. See the License terms at http://creativecommons.org/licenses/by-sa/4.0/legalcode
/*
*
* (c) Copyright Ascensio System Limited 2010-2021
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
* http://www.apache.org/licenses/LICENSE-2.0
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*
*/
namespace ASC.Notify.Textile;
public class MarkDownStyler : IPatternStyler

View File

@ -24,22 +24,6 @@
// content are licensed under the terms of the Creative Commons Attribution-ShareAlike 4.0
// International. See the License terms at http://creativecommons.org/licenses/by-sa/4.0/legalcode
/*
*
* (c) Copyright Ascensio System Limited 2010-2021
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
* http://www.apache.org/licenses/LICENSE-2.0
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*
*/
namespace ASC.AuditTrail.Mappers;
internal class LoginActionsMapper : IProductActionMapper

View File

@ -24,22 +24,6 @@
// content are licensed under the terms of the Creative Commons Attribution-ShareAlike 4.0
// International. See the License terms at http://creativecommons.org/licenses/by-sa/4.0/legalcode
/*
*
* (c) Copyright Ascensio System Limited 2010-2021
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
* http://www.apache.org/licenses/LICENSE-2.0
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*
*/
namespace ASC.AuditTrail.Mappers;
internal class OthersActionsMapper : IProductActionMapper

View File

@ -24,22 +24,6 @@
// content are licensed under the terms of the Creative Commons Attribution-ShareAlike 4.0
// International. See the License terms at http://creativecommons.org/licenses/by-sa/4.0/legalcode
/*
*
* (c) Copyright Ascensio System Limited 2010-2021
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
* http://www.apache.org/licenses/LICENSE-2.0
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*
*/
namespace ASC.AuditTrail.Mappers;
internal class SettingsActionsMapper : IProductActionMapper

View File

@ -25,11 +25,16 @@
"test": true
},
"personal": false,
"disableDocspace": false,
"products": {
"folder": "../../products",
"subfolder": "Server"
},
"search-by-content": false
"search-by-content": false,
"hosting": {
"intervalCheckRegisterInstanceInSeconds": "1",
"timeUntilUnregisterInSeconds": "15"
}
},
"license": {
"file": {
@ -42,7 +47,7 @@
"server-mailbox-limit-per-user": 2
},
"messaging": {
"enabled": "enabled"
"enabled": "true"
},
"version": {
"number": "11.5.0",

View File

@ -180,14 +180,13 @@ server {
proxy_pass http://localhost:5034;
proxy_set_header X-REWRITER-URL $X_REWRITER_URL;
}
location ~* /sso {
rewrite api/2.0/sso/(.*) /$1 break;
proxy_pass http://localhost:9834;
proxy_set_header X-REWRITER-URL $X_REWRITER_URL;
}
}
location /sso {
rewrite sso/(.*) /$1 break;
proxy_pass http://localhost:9834;
proxy_set_header X-REWRITER-URL $X_REWRITER_URL;
}
location ~* /(ssologin.ashx|login.ashx|storage) {
proxy_pass http://localhost:5003;
proxy_set_header X-REWRITER-URL $X_REWRITER_URL;

View File

@ -68,6 +68,21 @@
}
]
},
{
"name": "room_logos",
"data": "00000000-0000-0000-0000-000000000000",
"type": "disc",
"path": "$STORAGE_ROOT\\Products\\Files\\logos\\{0}",
"domain": [
{
"name": "logos_temp",
"data": "00000000-0000-0000-0000-000000000000",
"type": "disc",
"path": "$STORAGE_ROOT\\Products\\Files\\logos\\{0}\\temp",
"expires": "0:10:0"
}
]
},
{
"name": "files_template",
"visible": false,

View File

@ -32,6 +32,7 @@
<ItemGroup>
<ProjectReference Include="..\..\..\common\ASC.Api.Core\ASC.Api.Core.csproj" />
<ProjectReference Include="..\..\..\common\services\ASC.ElasticSearch\ASC.ElasticSearch.csproj" />
<ProjectReference Include="..\..\..\web\ASC.Web.Core\ASC.Web.Core.csproj" />
</ItemGroup>
<ItemGroup>
<Protobuf Include="proto\box_cache_item.proto" />

View File

@ -0,0 +1,32 @@
// (c) Copyright Ascensio System SIA 2010-2022
//
// This program is a free software product.
// You can redistribute it and/or modify it under the terms
// of the GNU Affero General Public License (AGPL) version 3 as published by the Free Software
// Foundation. In accordance with Section 7(a) of the GNU AGPL 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 details, see
// the GNU AGPL at: http://www.gnu.org/licenses/agpl-3.0.html
//
// You can contact Ascensio System SIA at Lubanas st. 125a-25, Riga, Latvia, EU, LV-1021.
//
// The interactive user interfaces in modified source and object code versions of the Program must
// display Appropriate Legal Notices, as required under Section 5 of the GNU AGPL version 3.
//
// Pursuant to Section 7(b) of the License you must retain the original Product logo when
// distributing the program. Pursuant to Section 7(e) we decline to grant you any rights under
// trademark law for use of our trademarks.
//
// All the Product's GUI elements, including illustrations and icon sets, as well as technical writing
// content are licensed under the terms of the Creative Commons Attribution-ShareAlike 4.0
// International. See the License terms at http://creativecommons.org/licenses/by-sa/4.0/legalcode
namespace ASC.Files.Core.ApiModels.RequestDto;
public class BatchTagsRequestDto
{
public IEnumerable<string> Names { get; set; }
}

View File

@ -0,0 +1,42 @@
// (c) Copyright Ascensio System SIA 2010-2022
//
// This program is a free software product.
// You can redistribute it and/or modify it under the terms
// of the GNU Affero General Public License (AGPL) version 3 as published by the Free Software
// Foundation. In accordance with Section 7(a) of the GNU AGPL 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 details, see
// the GNU AGPL at: http://www.gnu.org/licenses/agpl-3.0.html
//
// You can contact Ascensio System SIA at Lubanas st. 125a-25, Riga, Latvia, EU, LV-1021.
//
// The interactive user interfaces in modified source and object code versions of the Program must
// display Appropriate Legal Notices, as required under Section 5 of the GNU AGPL version 3.
//
// Pursuant to Section 7(b) of the License you must retain the original Product logo when
// distributing the program. Pursuant to Section 7(e) we decline to grant you any rights under
// trademark law for use of our trademarks.
//
// All the Product's GUI elements, including illustrations and icon sets, as well as technical writing
// content are licensed under the terms of the Creative Commons Attribution-ShareAlike 4.0
// International. See the License terms at http://creativecommons.org/licenses/by-sa/4.0/legalcode
namespace ASC.Files.Core.ApiModels.RequestDto;
public enum RoomType
{
FillingFormsRoom = 1,
EditingRoom = 2,
ReviewRoom = 3,
ReadOnlyRoom = 4,
CustomRoom = 5
}
public class CreateRoomRequestDto
{
public string Title { get; set; }
public RoomType RoomType { get; set; }
}

View File

@ -0,0 +1,32 @@
// (c) Copyright Ascensio System SIA 2010-2022
//
// This program is a free software product.
// You can redistribute it and/or modify it under the terms
// of the GNU Affero General Public License (AGPL) version 3 as published by the Free Software
// Foundation. In accordance with Section 7(a) of the GNU AGPL 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 details, see
// the GNU AGPL at: http://www.gnu.org/licenses/agpl-3.0.html
//
// You can contact Ascensio System SIA at Lubanas st. 125a-25, Riga, Latvia, EU, LV-1021.
//
// The interactive user interfaces in modified source and object code versions of the Program must
// display Appropriate Legal Notices, as required under Section 5 of the GNU AGPL version 3.
//
// Pursuant to Section 7(b) of the License you must retain the original Product logo when
// distributing the program. Pursuant to Section 7(e) we decline to grant you any rights under
// trademark law for use of our trademarks.
//
// All the Product's GUI elements, including illustrations and icon sets, as well as technical writing
// content are licensed under the terms of the Creative Commons Attribution-ShareAlike 4.0
// International. See the License terms at http://creativecommons.org/licenses/by-sa/4.0/legalcode
namespace ASC.Files.Core.ApiModels.RequestDto;
public class CreateTagRequestDto
{
public string Name { get; set; }
}

View File

@ -0,0 +1,32 @@
// (c) Copyright Ascensio System SIA 2010-2022
//
// This program is a free software product.
// You can redistribute it and/or modify it under the terms
// of the GNU Affero General Public License (AGPL) version 3 as published by the Free Software
// Foundation. In accordance with Section 7(a) of the GNU AGPL 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 details, see
// the GNU AGPL at: http://www.gnu.org/licenses/agpl-3.0.html
//
// You can contact Ascensio System SIA at Lubanas st. 125a-25, Riga, Latvia, EU, LV-1021.
//
// The interactive user interfaces in modified source and object code versions of the Program must
// display Appropriate Legal Notices, as required under Section 5 of the GNU AGPL version 3.
//
// Pursuant to Section 7(b) of the License you must retain the original Product logo when
// distributing the program. Pursuant to Section 7(e) we decline to grant you any rights under
// trademark law for use of our trademarks.
//
// All the Product's GUI elements, including illustrations and icon sets, as well as technical writing
// content are licensed under the terms of the Creative Commons Attribution-ShareAlike 4.0
// International. See the License terms at http://creativecommons.org/licenses/by-sa/4.0/legalcode
namespace ASC.Files.Core.ApiModels.RequestDto;
public class InviteLinkDto
{
public FileShare Access { get; set; }
}

View File

@ -0,0 +1,34 @@
// (c) Copyright Ascensio System SIA 2010-2022
//
// This program is a free software product.
// You can redistribute it and/or modify it under the terms
// of the GNU Affero General Public License (AGPL) version 3 as published by the Free Software
// Foundation. In accordance with Section 7(a) of the GNU AGPL 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 details, see
// the GNU AGPL at: http://www.gnu.org/licenses/agpl-3.0.html
//
// You can contact Ascensio System SIA at Lubanas st. 125a-25, Riga, Latvia, EU, LV-1021.
//
// The interactive user interfaces in modified source and object code versions of the Program must
// display Appropriate Legal Notices, as required under Section 5 of the GNU AGPL version 3.
//
// Pursuant to Section 7(b) of the License you must retain the original Product logo when
// distributing the program. Pursuant to Section 7(e) we decline to grant you any rights under
// trademark law for use of our trademarks.
//
// All the Product's GUI elements, including illustrations and icon sets, as well as technical writing
// content are licensed under the terms of the Creative Commons Attribution-ShareAlike 4.0
// International. See the License terms at http://creativecommons.org/licenses/by-sa/4.0/legalcode
namespace ASC.Files.Core.ApiModels.RequestDto;
public class InviteUsersByEmailRequestDto
{
public IEnumerable<string> Emails { get; set; }
public EmployeeType EmployeeType { get; set; }
public FileShare Access { get; set; }
}

View File

@ -0,0 +1,36 @@
// (c) Copyright Ascensio System SIA 2010-2022
//
// This program is a free software product.
// You can redistribute it and/or modify it under the terms
// of the GNU Affero General Public License (AGPL) version 3 as published by the Free Software
// Foundation. In accordance with Section 7(a) of the GNU AGPL 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 details, see
// the GNU AGPL at: http://www.gnu.org/licenses/agpl-3.0.html
//
// You can contact Ascensio System SIA at Lubanas st. 125a-25, Riga, Latvia, EU, LV-1021.
//
// The interactive user interfaces in modified source and object code versions of the Program must
// display Appropriate Legal Notices, as required under Section 5 of the GNU AGPL version 3.
//
// Pursuant to Section 7(b) of the License you must retain the original Product logo when
// distributing the program. Pursuant to Section 7(e) we decline to grant you any rights under
// trademark law for use of our trademarks.
//
// All the Product's GUI elements, including illustrations and icon sets, as well as technical writing
// content are licensed under the terms of the Creative Commons Attribution-ShareAlike 4.0
// International. See the License terms at http://creativecommons.org/licenses/by-sa/4.0/legalcode
namespace ASC.Files.Core.ApiModels.RequestDto;
public class LogoRequestDto
{
public string TmpFile { get; set; }
public int X { get; set; }
public int Y { get; set; }
public int Width { get; set; }
public int Height { get; set; }
}

View File

@ -31,4 +31,6 @@ public class SecurityInfoRequestDto : BaseBatchRequestDto
public IEnumerable<FileShareParams> Share { get; set; }
public bool Notify { get; set; }
public string SharingMessage { get; set; }
public FileShare Access { get; set; }
public string Key { get; set; }
}

View File

@ -33,6 +33,7 @@ public class ThirdPartyRequestDto
public string Password { get; set; }
public string Token { get; set; }
public bool IsCorporate { get; set; }
public bool IsRoomsStorage { get; set; }
public string CustomerTitle { get; set; }
public string ProviderKey { get; set; }
public string ProviderId { get; set; }

View File

@ -0,0 +1,32 @@
// (c) Copyright Ascensio System SIA 2010-2022
//
// This program is a free software product.
// You can redistribute it and/or modify it under the terms
// of the GNU Affero General Public License (AGPL) version 3 as published by the Free Software
// Foundation. In accordance with Section 7(a) of the GNU AGPL 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 details, see
// the GNU AGPL at: http://www.gnu.org/licenses/agpl-3.0.html
//
// You can contact Ascensio System SIA at Lubanas st. 125a-25, Riga, Latvia, EU, LV-1021.
//
// The interactive user interfaces in modified source and object code versions of the Program must
// display Appropriate Legal Notices, as required under Section 5 of the GNU AGPL version 3.
//
// Pursuant to Section 7(b) of the License you must retain the original Product logo when
// distributing the program. Pursuant to Section 7(e) we decline to grant you any rights under
// trademark law for use of our trademarks.
//
// All the Product's GUI elements, including illustrations and icon sets, as well as technical writing
// content are licensed under the terms of the Creative Commons Attribution-ShareAlike 4.0
// International. See the License terms at http://creativecommons.org/licenses/by-sa/4.0/legalcode
namespace ASC.Files.Core.ApiModels.RequestDto;
public class UpdateRoomRequestDto
{
public string Title { get; set; }
}

View File

@ -103,6 +103,7 @@ public class FolderContentDtoHelper
}
var folderEntries = folderItems.Entries.Where(r => r.FileEntryType == FileEntryType.Folder);
foreach (var r in folderEntries)
{
FileEntryDto wrapper = null;

View File

@ -34,6 +34,9 @@ public class FolderDto<T> : FileEntryDto<T>
public bool? IsShareable { get; set; }
public bool? IsFavorite { get; set; }
public int New { get; set; }
public IEnumerable<string> Tags { get; set; }
public Logo Logo { get; set; }
public bool Pinned { get; set; }
public FolderDto() { }
@ -65,6 +68,7 @@ public class FolderDtoHelper : FileEntryDtoHelper
private readonly AuthContext _authContext;
private readonly IDaoFactory _daoFactory;
private readonly GlobalFolderHelper _globalFolderHelper;
private readonly RoomLogoManager _roomLogoManager;
public FolderDtoHelper(
ApiDateTimeHelper apiDateTimeHelper,
@ -73,12 +77,14 @@ public class FolderDtoHelper : FileEntryDtoHelper
IDaoFactory daoFactory,
FileSecurity fileSecurity,
GlobalFolderHelper globalFolderHelper,
FileSharingHelper fileSharingHelper)
FileSharingHelper fileSharingHelper,
RoomLogoManager roomLogoManager)
: base(apiDateTimeHelper, employeeWrapperHelper, fileSharingHelper, fileSecurity)
{
_authContext = authContext;
_daoFactory = daoFactory;
_globalFolderHelper = globalFolderHelper;
_roomLogoManager = roomLogoManager;
}
public async Task<FolderDto<T>> GetAsync<T>(Folder<T> folder, List<Tuple<FileEntry<T>, bool>> folders = null)
@ -87,6 +93,24 @@ public class FolderDtoHelper : FileEntryDtoHelper
result.ParentId = folder.ParentId;
if (DocSpaceHelper.IsRoom(folder.FolderType))
{
if (folder.Tags == null)
{
var tagDao = _daoFactory.GetTagDao<T>();
var tags = await tagDao.GetTagsAsync(TagType.Custom, new[] { folder }).ToListAsync();
result.Tags = tags.Select(t => t.Name);
}
else
{
result.Tags = folder.Tags.Select(t => t.Name);
}
result.Logo = await _roomLogoManager.GetLogo(folder.Id);
}
if (folder.RootFolderType == FolderType.USER
&& !Equals(folder.RootCreateBy, _authContext.CurrentAccount.ID))
{
@ -125,6 +149,7 @@ public class FolderDtoHelper : FileEntryDtoHelper
result.IsShareable = folder.Shareable.NullIfDefault();
result.IsFavorite = folder.IsFavorite.NullIfDefault();
result.New = folder.NewForMe;
result.Pinned = folder.Pinned;
return result;
}

View File

@ -0,0 +1,34 @@
// (c) Copyright Ascensio System SIA 2010-2022
//
// This program is a free software product.
// You can redistribute it and/or modify it under the terms
// of the GNU Affero General Public License (AGPL) version 3 as published by the Free Software
// Foundation. In accordance with Section 7(a) of the GNU AGPL 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 details, see
// the GNU AGPL at: http://www.gnu.org/licenses/agpl-3.0.html
//
// You can contact Ascensio System SIA at Lubanas st. 125a-25, Riga, Latvia, EU, LV-1021.
//
// The interactive user interfaces in modified source and object code versions of the Program must
// display Appropriate Legal Notices, as required under Section 5 of the GNU AGPL version 3.
//
// Pursuant to Section 7(b) of the License you must retain the original Product logo when
// distributing the program. Pursuant to Section 7(e) we decline to grant you any rights under
// trademark law for use of our trademarks.
//
// All the Product's GUI elements, including illustrations and icon sets, as well as technical writing
// content are licensed under the terms of the Creative Commons Attribution-ShareAlike 4.0
// International. See the License terms at http://creativecommons.org/licenses/by-sa/4.0/legalcode
namespace ASC.Files.Core.ApiModels.ResponseDto;
public class InviteResultDto
{
public string Email { get; set; }
public bool Success { get; set; }
public string Message { get; set; }
}

View File

@ -0,0 +1,34 @@
// (c) Copyright Ascensio System SIA 2010-2022
//
// This program is a free software product.
// You can redistribute it and/or modify it under the terms
// of the GNU Affero General Public License (AGPL) version 3 as published by the Free Software
// Foundation. In accordance with Section 7(a) of the GNU AGPL 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 details, see
// the GNU AGPL at: http://www.gnu.org/licenses/agpl-3.0.html
//
// You can contact Ascensio System SIA at Lubanas st. 125a-25, Riga, Latvia, EU, LV-1021.
//
// The interactive user interfaces in modified source and object code versions of the Program must
// display Appropriate Legal Notices, as required under Section 5 of the GNU AGPL version 3.
//
// Pursuant to Section 7(b) of the License you must retain the original Product logo when
// distributing the program. Pursuant to Section 7(e) we decline to grant you any rights under
// trademark law for use of our trademarks.
//
// All the Product's GUI elements, including illustrations and icon sets, as well as technical writing
// content are licensed under the terms of the Creative Commons Attribution-ShareAlike 4.0
// International. See the License terms at http://creativecommons.org/licenses/by-sa/4.0/legalcode
namespace ASC.Files.Core.ApiModels.ResponseDto;
public class UploadResultDto
{
public bool Success { get; set; }
public object Data { get; set; }
public string Message { get; set; }
}

View File

@ -62,18 +62,50 @@ public interface IFolderDao<T>
/// </summary>
/// <param name="parentId"></param>
IAsyncEnumerable<Folder<T>> GetFoldersAsync(T parentId);
/// <summary>
/// Get a list of folders.
/// </summary>
/// <param name="parentId"></param>
/// <param name="orderBy"></param>
/// <param name="filterType"></param>
/// <param name="subjectGroup"></param>
/// <param name="subjectID"></param>
/// <param name="searchText"></param>
/// <param name="withSubfolders"></param>
/// <param name="tagIds"></param>
/// <returns></returns>
IAsyncEnumerable<Folder<T>> GetFoldersAsync(T parentId, OrderBy orderBy, FilterType filterType, bool subjectGroup, Guid subjectID, string searchText, bool withSubfolders = false,
IEnumerable<string> tagNames = null);
/// <summary>
/// Get a list of folders.
/// </summary>
/// <param name="parentId"></param>
/// <param name="orderBy"></param>
/// <param name="filterType"></param>
/// <param name="filterTypes"></param>
/// <param name="subjectGroup"></param>
/// <param name="subjectID"></param>
/// <param name="searchText"></param>
/// <param name="withSubfolders"></param>
/// <returns></returns>
IAsyncEnumerable<Folder<T>> GetFoldersAsync(T parentId, OrderBy orderBy, FilterType filterType, bool subjectGroup, Guid subjectID, string searchText, bool withSubfolders = false);
IAsyncEnumerable<Folder<T>> GetFoldersAsync(T parentId, OrderBy orderBy, IEnumerable<FilterType> filterTypes, bool subjectGroup, Guid subjectID, string searchText, bool withSubfolders = false,
IEnumerable<string> tagNames = null);
/// <summary>
/// Gets the folder (s) by ID (s)
/// </summary>
/// <param name="folderIds"></param>
/// <param name="filterTypes"></param>
/// <param name="subjectGroup"></param>
/// <param name="subjectID"></param>
/// <param name="searchText"></param>
/// <param name="searchSubfolders"></param>
/// <param name="checkShare"></param>
/// <param name="tagIds"></param>
/// <returns></returns>
IAsyncEnumerable<Folder<T>> GetFoldersAsync(IEnumerable<T> folderIds, FilterType filterTypes = FilterType.None, bool subjectGroup = false, Guid? subjectID = null, string searchText = "", bool searchSubfolders = false, bool checkShare = true,
IEnumerable<string> tagNames = null);
/// <summary>
/// Gets the folder (s) by ID (s)
@ -86,7 +118,8 @@ public interface IFolderDao<T>
/// <param name="searchSubfolders"></param>
/// <param name="checkShare"></param>
/// <returns></returns>
IAsyncEnumerable<Folder<T>> GetFoldersAsync(IEnumerable<T> folderIds, FilterType filterType = FilterType.None, bool subjectGroup = false, Guid? subjectID = null, string searchText = "", bool searchSubfolders = false, bool checkShare = true);
IAsyncEnumerable<Folder<T>> GetFoldersAsync(IEnumerable<T> folderIds, IEnumerable<FilterType> filterTypes, bool subjectGroup = false, Guid? subjectID = null, string searchText = "", bool searchSubfolders = false, bool checkShare = true,
IEnumerable<string> tagNames = null);
/// <summary>
/// Get folder, contains folder with id
@ -301,6 +334,21 @@ public interface IFolderDao<T>
/// <returns></returns>
Task<T> GetFolderIDProjectsAsync(bool createIfNotExists);
/// <summary>
/// Returns id folder "VirtualRooms"
/// Only in TMFolderDao
/// </summary>
/// <param name="createIfNotExists"></param>
/// <returns></returns>
Task<T> GetFolderIDVirtualRooms(bool createIfNotExists);
/// <summary>
/// Returns id folder "Archive"
/// Only in TMFolderDao
/// </summary>
/// <param name="createIfNotExists"></param>
/// <returns></returns>
Task<T> GetFolderIDArchive(bool createIfNotExists);
/// <summary>
/// Return id of related object

View File

@ -34,6 +34,8 @@ public interface IProviderDao
IAsyncEnumerable<IProviderInfo> GetProvidersInfoAsync(FolderType folderType, string searchText = null);
IAsyncEnumerable<IProviderInfo> GetProvidersInfoAsync(Guid userId);
Task<int> SaveProviderInfoAsync(string providerKey, string customerTitle, AuthData authData, FolderType folderType);
Task<bool> UpdateProviderInfoAsync(int linkId, FolderType rootFolderType);
Task<bool> UpdateProviderInfoAsync(int linkId, string folderId, FolderType folderType);
Task<int> UpdateProviderInfoAsync(int linkId, string customerTitle, AuthData authData, FolderType folderType, Guid? userId = null);
Task RemoveProviderInfoAsync(int linkId);
}

View File

@ -32,9 +32,11 @@ public interface IProviderInfo : IDisposable
string ProviderKey { get; }
Guid Owner { get; }
FolderType RootFolderType { get; }
FolderType FolderType { get; }
DateTime CreateOn { get; }
string CustomerTitle { get; }
string RootFolderId { get; }
string FolderId { get; }
Task<bool> CheckAccessAsync();
Task InvalidateStorageAsync();

View File

@ -39,10 +39,15 @@ public interface ITagDao<T>
IAsyncEnumerable<Tag> GetTagsAsync(Guid owner, TagType tagType);
IAsyncEnumerable<Tag> GetTagsAsync(string name, TagType tagType);
IAsyncEnumerable<Tag> GetTagsAsync(string[] names, TagType tagType);
IAsyncEnumerable<TagInfo> GetTagsInfoAsync(string searchText, TagType tagType, bool byName, int from = 0, int count = 0);
IAsyncEnumerable<TagInfo> GetTagsInfoAsync(IEnumerable<string> names);
IEnumerable<Tag> SaveTags(IEnumerable<Tag> tag);
IEnumerable<Tag> SaveTags(Tag tag);
Task<TagInfo> SaveTagInfoAsync(TagInfo tagInfo);
void UpdateNewTags(IEnumerable<Tag> tag);
void UpdateNewTags(Tag tag);
Task RemoveTagsAsync(IEnumerable<int> tagsIds);
Task RemoveTagsAsync(FileEntry<T> entry, IEnumerable<int> tagsIds);
void RemoveTags(IEnumerable<Tag> tag);
void RemoveTags(Tag tag);
}

View File

@ -38,6 +38,8 @@ internal class FolderDao : AbstractDao, IFolderDao<int>
private const string Privacy = "privacy";
private const string Trash = "trash";
private const string Projects = "projects";
private const string VirtualRooms = "virtualrooms";
private const string Archive = "archive";
private readonly FactoryIndexerFolder _factoryIndexer;
private readonly GlobalSpace _globalSpace;
@ -46,6 +48,10 @@ internal class FolderDao : AbstractDao, IFolderDao<int>
private readonly CrossDao _crossDao;
private readonly IMapper _mapper;
private static readonly List<FilterType> _constraintFolderFilters =
new List<FilterType> { FilterType.FilesOnly, FilterType.ByExtension, FilterType.DocumentsOnly, FilterType.ImagesOnly,
FilterType.PresentationsOnly, FilterType.SpreadsheetsOnly, FilterType.ArchiveOnly, FilterType.MediaOnly };
public FolderDao(
FactoryIndexerFolder factoryIndexer,
UserManager userManager,
@ -154,15 +160,19 @@ internal class FolderDao : AbstractDao, IFolderDao<int>
public IAsyncEnumerable<Folder<int>> GetFoldersAsync(int parentId)
{
return GetFoldersAsync(parentId, default, default, false, default, string.Empty);
return GetFoldersAsync(parentId, default, FilterType.None, false, default, string.Empty);
}
public IAsyncEnumerable<Folder<int>> GetFoldersAsync(int parentId, OrderBy orderBy, FilterType filterType, bool subjectGroup, Guid subjectID, string searchText, bool withSubfolders = false)
public IAsyncEnumerable<Folder<int>> GetFoldersAsync(int parentId, OrderBy orderBy, FilterType filterType, bool subjectGroup, Guid subjectID, string searchText, bool withSubfolders = false,
IEnumerable<string> tagNames = null)
{
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 GetFoldersAsync(parentId, orderBy, new[] { filterType }, subjectGroup, subjectID, searchText, withSubfolders, tagNames);
}
public IAsyncEnumerable<Folder<int>> GetFoldersAsync(int parentId, OrderBy orderBy, IEnumerable<FilterType> filterTypes, bool subjectGroup, Guid subjectID, string searchText, bool withSubfolders = false,
IEnumerable<string> tagNames = null)
{
if (!CheckForInvalidFilters(filterTypes))
{
return AsyncEnumerable.Empty<Folder<int>>();
}
@ -174,6 +184,8 @@ internal class FolderDao : AbstractDao, IFolderDao<int>
var q = GetFolderQuery(r => r.ParentId == parentId).AsNoTracking();
q = SetFilterByTypes(q, filterTypes);
if (withSubfolders)
{
q = GetFolderQuery().AsNoTracking()
@ -215,23 +227,37 @@ internal class FolderDao : AbstractDao, IFolderDao<int>
}
}
if (tagNames != null && tagNames.Any())
{
q = q.Join(FilesDbContext.TagLink, f => f.Id.ToString(), t => t.EntryId, (folder, tag) => new { folder, tag.TagId })
.Join(FilesDbContext.Tag, r => r.TagId, t => t.Id, (result, tagInfo) => new { result.folder, result.TagId, tagInfo.Name })
.Where(r => tagNames.Contains(r.Name))
.Select(r => r.folder).Distinct();
}
var dbFolders = FromQueryWithShared(q).AsAsyncEnumerable();
return dbFolders.Select(_mapper.Map<DbFolderQuery, Folder<int>>);
}
public IAsyncEnumerable<Folder<int>> GetFoldersAsync(IEnumerable<int> folderIds, FilterType filterType = FilterType.None, bool subjectGroup = false, Guid? subjectID = null, string searchText = "", bool searchSubfolders = false, bool checkShare = true)
public IAsyncEnumerable<Folder<int>> GetFoldersAsync(IEnumerable<int> folderIds, FilterType filterType = FilterType.None, bool subjectGroup = false, Guid? subjectID = null, string searchText = "", bool searchSubfolders = false, bool checkShare = true,
IEnumerable<string> tagNames = null)
{
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 GetFoldersAsync(folderIds, new[] { filterType }, subjectGroup, subjectID, searchText, searchSubfolders, checkShare, tagNames);
}
public IAsyncEnumerable<Folder<int>> GetFoldersAsync(IEnumerable<int> folderIds, IEnumerable<FilterType> filterTypes, bool subjectGroup = false, Guid? subjectID = null, string searchText = "", bool searchSubfolders = false, bool checkShare = true,
IEnumerable<string> tagNames = null)
{
if (!CheckForInvalidFilters(filterTypes))
{
return AsyncEnumerable.Empty<Folder<int>>();
}
var q = GetFolderQuery(r => folderIds.Contains(r.Id)).AsNoTracking();
q = SetFilterByTypes(q, filterTypes);
if (searchSubfolders)
{
q = GetFolderQuery()
@ -271,6 +297,14 @@ internal class FolderDao : AbstractDao, IFolderDao<int>
}
}
if (tagNames != null && tagNames.Any())
{
q = q.Join(FilesDbContext.TagLink, f => f.Id.ToString(), t => t.EntryId, (folder, tag) => new { folder, tag.TagId })
.Join(FilesDbContext.Tag, r => r.TagId, t => t.Id, (result, tagInfo) => new { result.folder, result.TagId, tagInfo.Name })
.Where(r => tagNames.Contains(r.Name))
.Select(r => r.folder).Distinct();
}
var dbFolders = (checkShare ? FromQueryWithShared(q) : FromQuery(q)).AsAsyncEnumerable();
return dbFolders.Select(_mapper.Map<DbFolderQuery, Folder<int>>).Distinct();
@ -543,7 +577,7 @@ internal class FolderDao : AbstractDao, IFolderDao<int>
{
var folder = await GetFolderAsync(folderId).ConfigureAwait(false);
if (folder.FolderType != FolderType.DEFAULT)
if (folder.FolderType != FolderType.DEFAULT && !DocSpaceHelper.IsRoom(folder.FolderType))
{
throw new ArgumentException("It is forbidden to move the System folder.", nameof(folderId));
}
@ -990,6 +1024,14 @@ internal class FolderDao : AbstractDao, IFolderDao<int>
folder.FolderType = FolderType.Projects;
folder.Title = Projects;
break;
case VirtualRooms:
folder.FolderType = FolderType.VirtualRooms;
folder.Title = VirtualRooms;
break;
case Archive:
folder.FolderType = FolderType.Archive;
folder.Title = Archive;
break;
default:
folder.FolderType = FolderType.BUNCH;
folder.Title = key;
@ -1092,6 +1134,14 @@ internal class FolderDao : AbstractDao, IFolderDao<int>
folder.FolderType = FolderType.Projects;
folder.Title = Projects;
break;
case VirtualRooms:
folder.FolderType = FolderType.VirtualRooms;
folder.Title = VirtualRooms;
break;
case Archive:
folder.FolderType = FolderType.Archive;
folder.Title = Archive;
break;
default:
folder.FolderType = FolderType.BUNCH;
folder.Title = key;
@ -1166,6 +1216,16 @@ internal class FolderDao : AbstractDao, IFolderDao<int>
return (this as IFolderDao<int>).GetFolderIDAsync(FileConstant.ModuleId, Privacy, (userId ?? _authContext.CurrentAccount.ID).ToString(), createIfNotExists);
}
public Task<int> GetFolderIDVirtualRooms(bool createIfNotExists)
{
return (this as IFolderDao<int>).GetFolderIDAsync(FileConstant.ModuleId, VirtualRooms, null, createIfNotExists);
}
public Task<int> GetFolderIDArchive(bool createIfNotExists)
{
return (this as IFolderDao<int>).GetFolderIDAsync(FileConstant.ModuleId, Archive, null, createIfNotExists);
}
#endregion
protected internal IQueryable<DbFolder> GetFolderQuery(Expression<Func<DbFolder, bool>> where = null)
@ -1296,6 +1356,33 @@ internal class FolderDao : AbstractDao, IFolderDao<int>
return q1.Union(q2);
}
private bool CheckForInvalidFilters(IEnumerable<FilterType> filterTypes)
{
var intersection = filterTypes.Intersect(_constraintFolderFilters);
return !intersection.Any();
}
private IQueryable<DbFolder> SetFilterByTypes(IQueryable<DbFolder> q, IEnumerable<FilterType> filterTypes)
{
if (filterTypes.Any() && !filterTypes.Contains(FilterType.None))
{
var filter = filterTypes.Select(f => f switch
{
FilterType.FillingFormsRooms => FolderType.FillingFormsRoom,
FilterType.EditingRooms => FolderType.EditingRoom,
FilterType.ReviewRooms => FolderType.ReviewRoom,
FilterType.ReadOnlyRooms => FolderType.ReadOnlyRoom,
FilterType.CustomRooms => FolderType.CustomRoom,
_ => FolderType.CustomRoom
}).ToHashSet();
q = q.Where(r => filter.Contains(r.FolderType));
}
return q;
}
private string GetProjectTitle(object folderID)
{
return "";

View File

@ -215,6 +215,54 @@ internal class TagDao<T> : AbstractDao, ITagDao<T>
}
}
public async IAsyncEnumerable<TagInfo> GetTagsInfoAsync(string searchText, TagType tagType, bool byName, int from = 0, int count = 0)
{
var q = Query(FilesDbContext.Tag).AsNoTracking().Where(r => r.Type == tagType);
if (byName)
{
q = q.Where(r => r.Name == searchText);
}
else if (!string.IsNullOrEmpty(searchText))
{
var lowerText = searchText.ToLower().Trim().Replace("%", "\\%").Replace("_", "\\_");
q = q.Where(r => r.Name.ToLower().Contains(lowerText));
}
if (count != 0)
{
q = q.Take(count);
}
q = q.Skip(from);
await foreach (var tag in FromQueryAsync(q).ConfigureAwait(false))
{
yield return tag;
}
}
public async IAsyncEnumerable<TagInfo> GetTagsInfoAsync(IEnumerable<string> names)
{
var q = Query(FilesDbContext.Tag).AsNoTracking().Where(r => names.Contains(r.Name));
await foreach (var tag in FromQueryAsync(q).ConfigureAwait(false))
{
yield return tag;
}
}
public async Task<TagInfo> SaveTagInfoAsync(TagInfo tagInfo)
{
var tagDb = _mapper.Map<TagInfo, DbFilesTag>(tagInfo);
tagDb.TenantId = TenantID;
var tag = await FilesDbContext.Tag.AddAsync(tagDb).ConfigureAwait(false);
await FilesDbContext.SaveChangesAsync().ConfigureAwait(false);
return _mapper.Map<DbFilesTag, TagInfo>(tag.Entity);
}
public IEnumerable<Tag> SaveTags(IEnumerable<Tag> tags)
{
var result = new List<Tag>();
@ -485,6 +533,40 @@ internal class TagDao<T> : AbstractDao, ITagDao<T>
}
}
public async Task RemoveTagsAsync(FileEntry<T> entry, IEnumerable<int> tagsIds)
{
var entryId = (await MappingIDAsync(entry.Id).ConfigureAwait(false)).ToString();
var toDelete = await Query(FilesDbContext.TagLink)
.Where(r => tagsIds.Contains(r.TagId) && r.EntryId == entryId && r.EntryType == entry.FileEntryType)
.ToListAsync().ConfigureAwait(false);
FilesDbContext.TagLink.RemoveRange(toDelete);
await FilesDbContext.SaveChangesAsync().ConfigureAwait(false);
}
public async Task RemoveTagsAsync(IEnumerable<int> tagsIds)
{
var toDeleteTags = await Query(FilesDbContext.Tag)
.Where(r => tagsIds.Contains(r.Id)).ToListAsync().ConfigureAwait(false);
var toDeleteLinks = await Query(FilesDbContext.TagLink)
.Where(r => toDeleteTags.Select(t => t.Id).Contains(r.TagId)).ToListAsync().ConfigureAwait(false);
var strategy = FilesDbContext.Database.CreateExecutionStrategy();
await strategy.ExecuteAsync(async () =>
{
using var tx = await FilesDbContext.Database.BeginTransactionAsync().ConfigureAwait(false);
FilesDbContext.RemoveRange(toDeleteTags);
FilesDbContext.RemoveRange(toDeleteLinks);
await FilesDbContext.SaveChangesAsync().ConfigureAwait(false);
await tx.CommitAsync().ConfigureAwait(false);
});
}
private Task RemoveTagInDbAsync(Tag tag)
{
if (tag == null)
@ -703,6 +785,26 @@ internal class TagDao<T> : AbstractDao, ITagDao<T>
.Distinct()
);
static readonly Func<FilesDbContext, int, Guid, IAsyncEnumerable<TagLinkData>> _newTagsThirdpartyRoomsQuery =
Microsoft.EntityFrameworkCore.EF.CompileAsyncQuery((FilesDbContext ctx, int tenantId, Guid subject) =>
ctx.Tag
.AsNoTracking()
.Where(r => r.TenantId == tenantId)
.Where(r => subject == Guid.Empty || r.Owner == subject)
.Where(r => r.Type == TagType.New)
.Join(ctx.TagLink, r => r.Id, l => l.TagId, (tag, link) => new TagLinkData
{
Tag = tag,
Link = link
})
.Where(r => r.Link.TenantId == r.Tag.TenantId)
.Join(ctx.ThirdpartyIdMapping, r => r.Link.EntryId, r => r.HashId, (tagLink, mapping) => new { tagLink, mapping })
.Where(r => r.mapping.TenantId == tenantId && r.tagLink.Tag.Owner == subject && r.tagLink.Link.EntryType == FileEntryType.Folder)
.Join(ctx.ThirdpartyAccount, r => r.mapping.Id, r => r.FolderId, (tagLinkData, account) => new { tagLinkData, account })
.Where(r => r.tagLinkData.mapping.Id == r.account.FolderId && r.account.FolderType == FolderType.VirtualRooms)
.Select(r => r.tagLinkData.tagLink).Distinct()
);
static readonly Func<FilesDbContext, List<int>, bool, IAsyncEnumerable<int>> _getFolderQuery = Microsoft.EntityFrameworkCore.EF.CompileAsyncQuery((FilesDbContext ctx, List<int> monitorFolderIdsInt, bool deepSearch) =>
ctx.Tree
.AsNoTracking()
@ -853,6 +955,10 @@ internal class TagDao<T> : AbstractDao, ITagDao<T>
result = result.Concat(FromQueryAsync(_newTagsForSBoxQuery(FilesDbContext, tenantId, subject, thirdpartyFolderIds)));
}
}
if (parentFolder.FolderType == FolderType.VirtualRooms)
{
result = result.Concat(FromQueryAsync(_newTagsThirdpartyRoomsQuery(FilesDbContext, tenantId, subject)));
}
await foreach (var e in result)
{
@ -872,6 +978,18 @@ internal class TagDao<T> : AbstractDao, ITagDao<T>
}
}
protected async IAsyncEnumerable<TagInfo> FromQueryAsync(IQueryable<DbFilesTag> dbFilesTags)
{
var tags = await dbFilesTags
.ToListAsync()
.ConfigureAwait(false);
foreach (var tag in tags)
{
yield return _mapper.Map<DbFilesTag, TagInfo>(tag);
}
}
protected async IAsyncEnumerable<Tag> FromQueryAsync(IAsyncEnumerable<TagLinkData> dbFilesTags)
{
var files = await dbFilesTags

View File

@ -26,7 +26,7 @@
namespace ASC.Files.Core.EF;
public class DbFilesTag : IDbFile
public class DbFilesTag : IDbFile, IMapFrom<TagInfo>
{
public int TenantId { get; set; }
public int Id { get; set; }

View File

@ -36,9 +36,11 @@ public class DbFilesThirdpartyAccount : BaseEntity, IDbFile, IDbSearch
public string Token { get; set; }
public Guid UserId { get; set; }
public FolderType FolderType { get; set; }
public FolderType RoomType { get; set; }
public DateTime CreateOn { get; set; }
public string Url { get; set; }
public int TenantId { get; set; }
public string FolderId { get; set; }
public override object[] GetKeys()
{
@ -79,6 +81,7 @@ public static class DbFilesThirdpartyAccountExtension
.UseCollation("utf8_general_ci");
entity.Property(e => e.FolderType).HasColumnName("folder_type");
entity.Property(e => e.RoomType).HasColumnName("room_type");
entity.Property(e => e.Password)
.IsRequired()
@ -122,6 +125,12 @@ public static class DbFilesThirdpartyAccountExtension
.HasColumnType("varchar(100)")
.HasCharSet("utf8")
.UseCollation("utf8_general_ci");
entity.Property(e => e.FolderId)
.HasColumnName("folder_id")
.HasColumnType("text")
.HasCharSet("utf8")
.UseCollation("utf8_general_ci");
});
}
public static void PgSqlAddDbFilesThirdpartyAccount(this ModelBuilder modelBuilder)
@ -141,7 +150,8 @@ public static class DbFilesThirdpartyAccountExtension
.HasColumnName("customer_title")
.HasMaxLength(400);
entity.Property(e => e.FolderType).HasColumnName("folder_type");
entity.Property(e => e.FolderType).HasColumnName("root_folder_type");
entity.Property(e => e.RoomType).HasColumnType("folder_type");
entity.Property(e => e.Password)
.IsRequired()

View File

@ -24,22 +24,6 @@
// content are licensed under the terms of the Creative Commons Attribution-ShareAlike 4.0
// International. See the License terms at http://creativecommons.org/licenses/by-sa/4.0/legalcode
/*
*
* (c) Copyright Ascensio System Limited 2010-2021
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
* http://www.apache.org/licenses/LICENSE-2.0
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*
*/
namespace ASC.Files.Core;
public enum DateToAutoCleanUp

View File

@ -24,22 +24,6 @@
// content are licensed under the terms of the Creative Commons Attribution-ShareAlike 4.0
// International. See the License terms at http://creativecommons.org/licenses/by-sa/4.0/legalcode
/*
*
* (c) Copyright Ascensio System Limited 2010-2020
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
* http://www.apache.org/licenses/LICENSE-2.0
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*
*/
namespace ASC.Files.Core;

View File

@ -83,6 +83,7 @@ public abstract class FileEntry : ICloneable
public Guid RootCreateBy { get; set; }
public abstract bool IsNew { get; set; }
public FileEntryType FileEntryType { get; set; }
public IEnumerable<Tag> Tags { get; set; }
private string _modifiedByString;
private string _createByString;

View File

@ -41,6 +41,13 @@ public enum FolderType
Recent = 11,
Templates = 12,
Privacy = 13,
VirtualRooms = 14,
FillingFormsRoom = 15,
EditingRoom = 16,
ReviewRoom = 17,
ReadOnlyRoom = 18,
CustomRoom = 19,
Archive = 20,
}
public interface IFolder
@ -51,6 +58,7 @@ public interface IFolder
public bool Shareable { get; set; }
public int NewForMe { get; set; }
public string FolderUrl { get; set; }
public bool Pinned { get; set; }
}
[DebuggerDisplay("{Title} ({Id})")]
@ -63,6 +71,7 @@ public class Folder<T> : FileEntry<T>, IFolder, IMapFrom<DbFolder>
public bool Shareable { get; set; }
public int NewForMe { get; set; }
public string FolderUrl { get; set; }
public bool Pinned { get; set; }
public override bool IsNew
{
get => Convert.ToBoolean(NewForMe);
@ -127,6 +136,12 @@ public class Folder<T> : FileEntry<T>, IFolder, IMapFrom<DbFolder>
case FolderType.Projects:
result.Title = FilesUCResource.ProjectFiles;
break;
case FolderType.VirtualRooms:
result.Title = FilesUCResource.VirtualRooms;
break;
case FolderType.Archive:
result.Title = FilesUCResource.Archive;
break;
case FolderType.BUNCH:
try
{

View File

@ -37,6 +37,8 @@ public enum TagType
Locked = 8,
Recent = 16,
Template = 32,
Custom = 64,
Pin = 128,
}
[Serializable]
@ -102,13 +104,24 @@ public sealed class Tag : IMapFrom<DbFilesTag>
return new Tag("template", TagType.Template, owner, 0).AddEntry(entry);
}
public static Tag Custom<T>(Guid owner, FileEntry<T> entry, string name)
{
return new Tag(name, TagType.Custom, owner, 0).AddEntry(entry);
}
public static Tag Pin<T>(Guid owner, FileEntry<T> entry)
{
return new Tag("pin", TagType.Pin, owner, 0).AddEntry(entry);
}
public override bool Equals(object obj)
{
return obj is Tag f && Equals(f);
}
public bool Equals(Tag f)
{
return f.Id == Id && f.EntryType == EntryType && Equals(f.EntryId, EntryId);
return f != null && f.Id == Id && f.EntryType == EntryType && Equals(f.EntryId, EntryId);
}
public override int GetHashCode()

View File

@ -0,0 +1,35 @@
// (c) Copyright Ascensio System SIA 2010-2022
//
// This program is a free software product.
// You can redistribute it and/or modify it under the terms
// of the GNU Affero General Public License (AGPL) version 3 as published by the Free Software
// Foundation. In accordance with Section 7(a) of the GNU AGPL 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 details, see
// the GNU AGPL at: http://www.gnu.org/licenses/agpl-3.0.html
//
// You can contact Ascensio System SIA at Lubanas st. 125a-25, Riga, Latvia, EU, LV-1021.
//
// The interactive user interfaces in modified source and object code versions of the Program must
// display Appropriate Legal Notices, as required under Section 5 of the GNU AGPL version 3.
//
// Pursuant to Section 7(b) of the License you must retain the original Product logo when
// distributing the program. Pursuant to Section 7(e) we decline to grant you any rights under
// trademark law for use of our trademarks.
//
// All the Product's GUI elements, including illustrations and icon sets, as well as technical writing
// content are licensed under the terms of the Creative Commons Attribution-ShareAlike 4.0
// International. See the License terms at http://creativecommons.org/licenses/by-sa/4.0/legalcode
namespace ASC.Files.Core.Entries;
public class TagInfo : IMapFrom<DbFilesTag>
{
public int Id { get; set; }
public string Name { get; set; }
public Guid Owner { get; set; }
public TagType Type { get; set; }
}

View File

@ -237,7 +237,14 @@ public class FileStorageService<T> //: IFileStorageService
}));
}
public async Task<DataWrapper<T>> GetFolderItemsAsync(T parentId, int from, int count, FilterType filter, bool subjectGroup, string ssubject, string searchText, bool searchInContent, bool withSubfolders, OrderBy orderBy)
public async Task<DataWrapper<T>> GetFolderItemsAsync(T parentId, int from, int count, FilterType filter, bool subjectGroup, string ssubject, string searchText, bool searchInContent, bool withSubfolders, OrderBy orderBy,
SearchArea searchArea = SearchArea.Active, IEnumerable<string> tagNames = null)
{
return await GetFolderItemsAsync(parentId, from, count, new[] { filter }, subjectGroup, ssubject, searchText, searchInContent, withSubfolders, orderBy, searchArea, tagNames);
}
public async Task<DataWrapper<T>> GetFolderItemsAsync(T parentId, int from, int count, IEnumerable<FilterType> filterTypes, bool subjectGroup, string ssubject, string searchText, bool searchInContent, bool withSubfolders, OrderBy orderBy,
SearchArea searchArea = SearchArea.Active, IEnumerable<string> tagNames = null)
{
var subjectId = string.IsNullOrEmpty(ssubject) ? Guid.Empty : new Guid(ssubject);
@ -284,7 +291,7 @@ public class FileStorageService<T> //: IFileStorageService
IEnumerable<FileEntry> entries;
try
{
(entries, total) = await _entryManager.GetEntriesAsync(parent, from, count, filter, subjectGroup, subjectId, searchText, searchInContent, withSubfolders, orderBy);
(entries, total) = await _entryManager.GetEntriesAsync(parent, from, count, filterTypes, subjectGroup, subjectId, searchText, searchInContent, withSubfolders, orderBy, searchArea, tagNames);
}
catch (Exception e)
{
@ -410,26 +417,128 @@ public class FileStorageService<T> //: IFileStorageService
throw new ArgumentException();
}
return InternalCreateNewFolderAsync(parentId, title);
return InternalCreateNewFolderAsync(parentId, title, FolderType.DEFAULT);
}
public async Task<Folder<T>> InternalCreateNewFolderAsync(T parentId, string title)
public async Task<Folder<T>> CreateRoomAsync(string title, RoomType roomType)
{
ArgumentNullException.ThrowIfNull(title, nameof(title));
var parentId = await _globalFolderHelper.GetFolderVirtualRooms<T>();
return roomType switch
{
RoomType.CustomRoom => await CreateCustomRoomAsync(title, parentId),
RoomType.FillingFormsRoom => await CreateFillingFormsRoom(title, parentId),
RoomType.EditingRoom => await CreateEditingRoom(title, parentId),
RoomType.ReviewRoom => await CreateReviewRoom(title, parentId),
RoomType.ReadOnlyRoom => await CreateReadOnlyRoom(title, parentId),
_ => await CreateCustomRoomAsync(title, parentId),
};
}
public async Task<Folder<T>> CreateThirdpartyRoomAsync(string title, RoomType roomType, T parentId)
{
ArgumentNullException.ThrowIfNull(title, nameof(title));
ArgumentNullException.ThrowIfNull(parentId, nameof(parentId));
var folderDao = GetFolderDao();
var providerDao = GetProviderDao();
var parent = await folderDao.GetFolderAsync(parentId);
var providerInfo = await providerDao.GetProviderInfoAsync(parent.ProviderId);
if (providerInfo.RootFolderType != FolderType.VirtualRooms)
{
throw new InvalidOperationException("Invalid provider type");
}
if (providerInfo.FolderId != null)
{
throw new InvalidOperationException("This provider already corresponds to the virtual room");
}
var room = roomType switch
{
RoomType.CustomRoom => await CreateCustomRoomAsync(title, parentId),
RoomType.FillingFormsRoom => await CreateFillingFormsRoom(title, parentId),
RoomType.EditingRoom => await CreateEditingRoom(title, parentId),
RoomType.ReviewRoom => await CreateReviewRoom(title, parentId),
RoomType.ReadOnlyRoom => await CreateReadOnlyRoom(title, parentId),
_ => await CreateCustomRoomAsync(title, parentId),
};
var folderType = roomType switch
{
RoomType.CustomRoom => FolderType.CustomRoom,
RoomType.ReviewRoom => FolderType.ReviewRoom,
RoomType.EditingRoom => FolderType.EditingRoom,
RoomType.FillingFormsRoom => FolderType.FillingFormsRoom,
RoomType.ReadOnlyRoom => FolderType.ReadOnlyRoom,
_ => FolderType.CustomRoom
};
await providerDao.UpdateProviderInfoAsync(providerInfo.ID, room.Id.ToString(), folderType);
return room;
}
private async Task<Folder<T>> CreateCustomRoomAsync(string title, T parentId)
{
return await InternalCreateNewFolderAsync(parentId, title, FolderType.CustomRoom);
}
private async Task<Folder<T>> CreateFillingFormsRoom(string title, T parentId)
{
return await InternalCreateNewFolderAsync(parentId, title, FolderType.FillingFormsRoom);
}
private async Task<Folder<T>> CreateReviewRoom(string title, T parentId)
{
return await InternalCreateNewFolderAsync(parentId, title, FolderType.ReviewRoom);
}
private async Task<Folder<T>> CreateReadOnlyRoom(string title, T parentId)
{
return await InternalCreateNewFolderAsync(parentId, title, FolderType.ReadOnlyRoom);
}
private async Task<Folder<T>> CreateEditingRoom(string title, T parentId)
{
return await InternalCreateNewFolderAsync(parentId, title, FolderType.EditingRoom);
}
public async Task<Folder<T>> InternalCreateNewFolderAsync(T parentId, string title, FolderType folderType = FolderType.DEFAULT)
{
var folderDao = GetFolderDao();
var parent = await folderDao.GetFolderAsync(parentId);
var isRoom = DocSpaceHelper.IsRoom(folderType);
ErrorIf(parent == null, FilesCommonResource.ErrorMassage_FolderNotFound);
ErrorIf(!await _fileSecurity.CanCreateAsync(parent), FilesCommonResource.ErrorMassage_SecurityException_Create);
ErrorIf(parent.RootFolderType == FolderType.Archive, FilesCommonResource.ErrorMessage_UpdateArchivedRoom);
ErrorIf(parent.FolderType == FolderType.Archive, FilesCommonResource.ErrorMassage_SecurityException);
ErrorIf(!isRoom && parent.FolderType == FolderType.VirtualRooms, FilesCommonResource.ErrorMassage_SecurityException_Create);
try
{
var newFolder = _serviceProvider.GetService<Folder<T>>();
newFolder.Title = title;
newFolder.ParentId = parent.Id;
newFolder.FolderType = folderType;
var folderId = await folderDao.SaveFolderAsync(newFolder);
var folder = await folderDao.GetFolderAsync(folderId);
_filesMessageService.Send(folder, GetHttpHeaders(), MessageAction.FolderCreated, folder.Title);
if (isRoom)
{
_filesMessageService.Send(folder, GetHttpHeaders(), MessageAction.RoomCreated, folder.Title);
}
else
{
_filesMessageService.Send(folder, GetHttpHeaders(), MessageAction.FolderCreated, folder.Title);
}
return folder;
}
@ -445,13 +554,19 @@ public class FileStorageService<T> //: IFileStorageService
var folderDao = GetFolderDao();
var folder = await folderDao.GetFolderAsync(folderId);
ErrorIf(folder == null, FilesCommonResource.ErrorMassage_FolderNotFound);
ErrorIf(!await _fileSecurity.CanEditAsync(folder), FilesCommonResource.ErrorMassage_SecurityException_RenameFolder);
if (!await _fileSecurity.CanDeleteAsync(folder) && _userManager.GetUsers(_authContext.CurrentAccount.ID).IsVisitor(_userManager))
var canEdit = (folder.FolderType == FolderType.FillingFormsRoom || folder.FolderType == FolderType.EditingRoom
|| folder.FolderType == FolderType.ReviewRoom || folder.FolderType == FolderType.ReadOnlyRoom || folder.FolderType == FolderType.CustomRoom)
? await _fileSecurity.CanEditRoomAsync(folder) : await _fileSecurity.CanRenameAsync(folder);
ErrorIf(!canEdit, FilesCommonResource.ErrorMassage_SecurityException_RenameFolder);
if (!canEdit && _userManager.GetUsers(_authContext.CurrentAccount.ID).IsVisitor(_userManager))
{
throw new SecurityException(FilesCommonResource.ErrorMassage_SecurityException_RenameFolder);
}
ErrorIf(folder.RootFolderType == FolderType.TRASH, FilesCommonResource.ErrorMassage_ViewTrashItem);
ErrorIf(folder.RootFolderType == FolderType.Archive, FilesCommonResource.ErrorMessage_UpdateArchivedRoom);
var folderAccess = folder.Access;
@ -461,7 +576,14 @@ public class FileStorageService<T> //: IFileStorageService
folder = await folderDao.GetFolderAsync(newFolderID);
folder.Access = folderAccess;
_filesMessageService.Send(folder, GetHttpHeaders(), MessageAction.FolderRenamed, folder.Title);
if (DocSpaceHelper.IsRoom(folder.FolderType))
{
_filesMessageService.Send(folder, GetHttpHeaders(), MessageAction.RoomRenamed, folder.Title);
}
else
{
_filesMessageService.Send(folder, GetHttpHeaders(), MessageAction.FolderRenamed, folder.Title);
}
//if (!folder.ProviderEntry)
//{
@ -598,7 +720,9 @@ public class FileStorageService<T> //: IFileStorageService
if (!EqualityComparer<T>.Default.Equals(fileWrapper.ParentId, default(T)))
{
folder = await folderDao.GetFolderAsync(fileWrapper.ParentId);
var canCreate = await _fileSecurity.CanCreateAsync(folder);
var canCreate = await _fileSecurity.CanCreateAsync(folder) && folder.FolderType != FolderType.VirtualRooms
&& folder.FolderType != FolderType.Archive;
if (!canCreate)
{
folder = null;
@ -1482,12 +1606,17 @@ public class FileStorageService<T> //: IFileStorageService
var folderDao = GetFolderDao();
ErrorIf(thirdPartyParams == null, FilesCommonResource.ErrorMassage_BadRequest);
var parentFolder = await folderDaoInt.GetFolderAsync(thirdPartyParams.Corporate && !_coreBaseSettings.Personal ? await _globalFolderHelper.FolderCommonAsync : _globalFolderHelper.FolderMy);
var folderId = thirdPartyParams.Corporate && !_coreBaseSettings.Personal ? await _globalFolderHelper.FolderCommonAsync
: thirdPartyParams.RoomsStorage && !_coreBaseSettings.DisableDocSpace ? await _globalFolderHelper.FolderVirtualRoomsAsync : _globalFolderHelper.FolderMy;
var parentFolder = await folderDaoInt.GetFolderAsync(folderId);
ErrorIf(!await _fileSecurity.CanCreateAsync(parentFolder), FilesCommonResource.ErrorMassage_SecurityException_Create);
ErrorIf(!_filesSettingsHelper.EnableThirdParty, FilesCommonResource.ErrorMassage_SecurityException_Create);
var lostFolderType = FolderType.USER;
var folderType = thirdPartyParams.Corporate ? FolderType.COMMON : FolderType.USER;
var folderType = thirdPartyParams.Corporate ? FolderType.COMMON : thirdPartyParams.RoomsStorage ? FolderType.VirtualRooms : FolderType.USER;
int curProviderId;
@ -2174,9 +2303,9 @@ public class FileStorageService<T> //: IFileStorageService
#endregion
public Task<List<AceWrapper>> GetSharedInfoAsync(IEnumerable<T> fileIds, IEnumerable<T> folderIds)
public Task<List<AceWrapper>> GetSharedInfoAsync(IEnumerable<T> fileIds, IEnumerable<T> folderIds, bool invite = false)
{
return _fileSharing.GetSharedInfoAsync(fileIds, folderIds);
return _fileSharing.GetSharedInfoAsync(fileIds, folderIds, invite);
}
public Task<List<AceShortWrapper>> GetSharedInfoShortFileAsync(T fileId)
@ -2189,7 +2318,7 @@ public class FileStorageService<T> //: IFileStorageService
return _fileSharing.GetSharedInfoShortFolderAsync(folderId);
}
public async Task<List<T>> SetAceObjectAsync(AceCollection<T> aceCollection, bool notify)
public async Task<List<T>> SetAceObjectAsync(AceCollection<T> aceCollection, bool notify, bool invite = false)
{
var fileDao = GetFileDao();
var folderDao = GetFolderDao();
@ -2211,15 +2340,24 @@ public class FileStorageService<T> //: IFileStorageService
{
try
{
var changed = await _fileSharingAceHelper.SetAceObjectAsync(aceCollection.Aces, entry, notify, aceCollection.Message, aceCollection.AdvancedSettings);
var changed = await _fileSharingAceHelper.SetAceObjectAsync(aceCollection.Aces, entry, notify, aceCollection.Message, aceCollection.AdvancedSettings, !_coreBaseSettings.DisableDocSpace, invite);
if (changed)
{
foreach (var ace in aceCollection.Aces)
{
var name = ace.SubjectGroup ? _userManager.GetGroupInfo(ace.SubjectId).Name : _userManager.GetUsers(ace.SubjectId).DisplayUserName(false, _displayUserSettingsHelper);
_filesMessageService.Send(entry, GetHttpHeaders(),
entry.FileEntryType == FileEntryType.Folder ? MessageAction.FolderUpdatedAccessFor : MessageAction.FileUpdatedAccessFor,
entry.Title, name, GetAccessString(ace.Share));
if (entry.FileEntryType == FileEntryType.Folder && DocSpaceHelper.IsRoom(((Folder<T>)entry).FolderType))
{
_filesMessageService.Send(entry, GetHttpHeaders(), MessageAction.RoomUpdateAccess, entry.Title, name, GetAccessString(ace.Share));
}
else
{
_filesMessageService.Send(entry, GetHttpHeaders(),
entry.FileEntryType == FileEntryType.Folder ? MessageAction.FolderUpdatedAccessFor : MessageAction.FileUpdatedAccessFor,
entry.Title, name, GetAccessString(ace.Share));
}
}
}
}
@ -2360,6 +2498,32 @@ public class FileStorageService<T> //: IFileStorageService
return new List<MentionWrapper>(users);
}
public async Task<Folder<T>> SetPinnedStatusAsync(T folderId, bool pin)
{
var folderDao = GetFolderDao();
var room = await folderDao.GetFolderAsync(folderId);
ErrorIf(room == null, FilesCommonResource.ErrorMassage_FolderNotFound);
ErrorIf(!await _fileSecurity.CanReadAsync(room), FilesCommonResource.ErrorMassage_SecurityException_ReadFolder);
var tagDao = GetTagDao();
var tag = Tag.Pin(_authContext.CurrentAccount.ID, room);
if (pin)
{
tagDao.SaveTags(tag);
}
else
{
tagDao.RemoveTags(tag);
}
room.Pinned = pin;
return room;
}
public async Task<List<AceShortWrapper>> SendEditorNotifyAsync(T fileId, MentionMessageWrapper mentionMessage)
{
ErrorIf(!_authContext.IsAuthenticated, FilesCommonResource.ErrorMassage_SecurityException);
@ -2465,7 +2629,7 @@ public class FileStorageService<T> //: IFileStorageService
return new List<EncryptionKeyPairDto>(fileKeyPair);
}
public bool ChangeExternalShareSettings(bool enable)
{
ErrorIf(!_global.IsAdministrator, FilesCommonResource.ErrorMassage_SecurityException);

View File

@ -40,4 +40,9 @@ public enum FilterType
[EnumMember] ArchiveOnly = 10,
[EnumMember] ByExtension = 11,
[EnumMember] MediaOnly = 12,
[EnumMember] FillingFormsRooms = 13,
[EnumMember] EditingRooms = 14,
[EnumMember] ReviewRooms = 15,
[EnumMember] ReadOnlyRooms = 16,
[EnumMember] CustomRooms = 17,
}

View File

@ -62,7 +62,7 @@ public class FileSecurity : IFileSecurity
private readonly GlobalFolder _globalFolder;
private readonly FileSecurityCommon _fileSecurityCommon;
private readonly FilesSettingsHelper _filesSettingsHelper;
public FileSecurity(
IDaoFactory daoFactory,
UserManager userManager,
@ -132,7 +132,17 @@ public class FileSecurity : IFileSecurity
{
return CanAsync(entry, userId, FilesSecurityActions.Delete);
}
public Task<bool> CanEditRoomAsync<T>(FileEntry<T> entry, Guid userId)
{
return CanAsync(entry, userId, FilesSecurityActions.RoomEdit);
}
public Task<bool> CanRenameAsync<T>(FileEntry<T> entry, Guid userId)
{
return CanAsync(entry, userId, FilesSecurityActions.Rename);
}
public Task<bool> CanDownloadAsync<T>(FileEntry<T> entry)
{
return CanDownloadAsync(entry, _authContext.CurrentAccount.ID);
@ -193,6 +203,11 @@ public class FileSecurity : IFileSecurity
return CanEditAsync(entry, _authContext.CurrentAccount.ID);
}
public Task<bool> CanRenameAsync<T>(FileEntry<T> entry)
{
return CanRenameAsync(entry, _authContext.CurrentAccount.ID);
}
public Task<bool> CanDeleteAsync<T>(FileEntry<T> entry)
{
return CanDeleteAsync(entry, _authContext.CurrentAccount.ID);
@ -201,7 +216,12 @@ public class FileSecurity : IFileSecurity
{
return CanDownloadAsync(entry, _authContext.CurrentAccount.ID);
}
public Task<bool> CanEditRoomAsync<T>(FileEntry<T> entry)
{
return CanEditRoomAsync(entry, _authContext.CurrentAccount.ID);
}
public Task<bool> CanShare<T>(FileEntry<T> entry)
{
return CanShareAsync(entry, _authContext.CurrentAccount.ID);
@ -312,6 +332,32 @@ public class FileSecurity : IFileSecurity
defaultShareRecord = null;
break;
case FolderType.VirtualRooms:
defaultShareRecord = new FileShareRecord
{
Level = int.MaxValue,
EntryId = entry.Id,
EntryType = entry.FileEntryType,
Share = FileShare.Read,
Subject = WebItemManager.DocumentsProductID,
TenantId = _tenantManager.GetCurrentTenant().Id,
Owner = entry.RootCreateBy
};
if (!shares.Any())
{
if ((defaultShareRecord.Share == FileShare.Read && action == FilesSecurityActions.Read) ||
(defaultShareRecord.Share == FileShare.ReadWrite))
{
return _userManager.GetUsersByGroup(defaultShareRecord.Subject)
.Where(x => x.Status == EmployeeStatus.Active).Select(y => y.Id).Distinct();
}
return Enumerable.Empty<Guid>();
}
break;
default:
defaultShareRecord = null;
break;
@ -374,7 +420,7 @@ public class FileSecurity : IFileSecurity
{
return (await FilterAsync(new[] { entry }, action, userId, shares)).Any();
}
public async Task<IEnumerable<File<T>>> FilterDownloadAsync<T>(IEnumerable<File<T>> entries)
{
return (await FilterReadAsync(entries)).Where(CheckDenyDownload).ToList();
@ -446,7 +492,9 @@ public class FileSecurity : IFileSecurity
f.RootFolderType == FolderType.Favorites ||
f.RootFolderType == FolderType.Templates ||
f.RootFolderType == FolderType.Privacy ||
f.RootFolderType == FolderType.Projects;
f.RootFolderType == FolderType.Projects ||
f.RootFolderType == FolderType.VirtualRooms ||
f.RootFolderType == FolderType.Archive;
var isVisitor = user.IsVisitor(_userManager);
@ -526,6 +574,11 @@ public class FileSecurity : IFileSecurity
// Templates folder read-only
continue;
}
if (folder.FolderType == FolderType.Archive)
{
continue;
}
}
if (isVisitor && e.ProviderEntry)
@ -610,6 +663,19 @@ public class FileSecurity : IFileSecurity
continue;
}
if (e.RootFolderType == FolderType.VirtualRooms && _fileSecurityCommon.IsAdministrator(userId))
{
// administrator in VirtualRooms has all right
result.Add(e);
continue;
}
if (action == FilesSecurityActions.Delete && e.RootFolderType == FolderType.Archive && _fileSecurityCommon.IsAdministrator(userId))
{
result.Add(e);
continue;
}
if (subjects == null)
{
subjects = GetUserSubjects(userId);
@ -663,30 +729,49 @@ public class FileSecurity : IFileSecurity
{
result.Add(e);
}
else if (action == FilesSecurityActions.Comment && (e.Access == FileShare.Comment || e.Access == FileShare.Review || e.Access == FileShare.CustomFilter || e.Access == FileShare.ReadWrite))
else if (action == FilesSecurityActions.Comment && (e.Access == FileShare.Comment || e.Access == FileShare.Review || e.Access == FileShare.CustomFilter || e.Access == FileShare.ReadWrite || e.Access == FileShare.RoomManager || e.Access == FileShare.Editing))
{
result.Add(e);
}
else if (action == FilesSecurityActions.FillForms && (e.Access == FileShare.FillForms || e.Access == FileShare.Review || e.Access == FileShare.ReadWrite))
else if (action == FilesSecurityActions.FillForms && (e.Access == FileShare.FillForms || e.Access == FileShare.Review || e.Access == FileShare.ReadWrite || e.Access == FileShare.RoomManager || e.Access == FileShare.Editing))
{
result.Add(e);
}
else if (action == FilesSecurityActions.Review && (e.Access == FileShare.Review || e.Access == FileShare.ReadWrite))
else if (action == FilesSecurityActions.Review && (e.Access == FileShare.Review || e.Access == FileShare.ReadWrite || e.Access == FileShare.RoomManager || e.Access == FileShare.Editing))
{
result.Add(e);
}
else if (action == FilesSecurityActions.CustomFilter && (e.Access == FileShare.CustomFilter || e.Access == FileShare.ReadWrite))
else if (action == FilesSecurityActions.CustomFilter && (e.Access == FileShare.CustomFilter || e.Access == FileShare.ReadWrite || e.Access == FileShare.RoomManager || e.Access == FileShare.Editing))
{
result.Add(e);
}
else if (action == FilesSecurityActions.Edit && e.Access == FileShare.ReadWrite)
else if (action == FilesSecurityActions.Edit && (e.Access == FileShare.ReadWrite || e.Access == FileShare.RoomManager || e.Access == FileShare.Editing))
{
result.Add(e);
}
else if (action == FilesSecurityActions.Create && e.Access == FileShare.ReadWrite)
else if (action == FilesSecurityActions.Rename && (e.Access == FileShare.ReadWrite || e.Access == FileShare.RoomManager))
{
result.Add(e);
}
else if (action == FilesSecurityActions.RoomEdit && e.Access == FileShare.RoomManager)
{
result.Add(e);
}
else if (action == FilesSecurityActions.Create && (e.Access == FileShare.ReadWrite || e.Access == FileShare.RoomManager))
{
result.Add(e);
}
else if (action == FilesSecurityActions.Delete && (e.Access == FileShare.RoomManager || e.Access == FileShare.ReadWrite))
{
if (file != null && (file.RootFolderType == FolderType.VirtualRooms || file.RootFolderType == FolderType.Archive))
{
result.Add(e);
}
else if (folder != null && folder.FolderType == FolderType.DEFAULT)
{
result.Add(e);
}
}
else if (e.Access != FileShare.Restrict && e.CreateBy == userId && (e.FileEntryType == FileEntryType.File || folder.FolderType != FolderType.COMMON))
{
result.Add(e);
@ -965,6 +1050,194 @@ public class FileSecurity : IFileSecurity
return entries.Where(x => string.IsNullOrEmpty(x.Error)).Cast<FileEntry>().ToList();
}
public async Task<List<FileEntry>> GetVirtualRoomsAsync(IEnumerable<FilterType> filterTypes, Guid subjectId, string searchText, bool searchInContent, bool withSubfolders,
OrderBy orderBy, SearchArea searchArea, IEnumerable<string> tagNames)
{
if (_fileSecurityCommon.IsAdministrator(_authContext.CurrentAccount.ID))
{
return await GetVirtualRoomsForAdminAsync(filterTypes, subjectId, searchText, searchInContent, withSubfolders, searchArea, orderBy, tagNames);
}
else
{
var securityDao = _daoFactory.GetSecurityDao<int>();
var subjects = GetUserSubjects(_authContext.CurrentAccount.ID);
var records = await securityDao.GetSharesAsync(subjects);
var entries = new List<FileEntry>();
var rooms = await GetVirtualRoomsForUserAsync<int>(records.Where(r => r.EntryId is int), subjects, filterTypes, subjectId, searchText, searchInContent, withSubfolders, searchArea, tagNames);
var thirdPartyRooms = await GetVirtualRoomsForUserAsync<string>(records.Where(r => r.EntryId is string), subjects, filterTypes, subjectId, searchText, searchInContent, withSubfolders, searchArea, tagNames);
entries.AddRange(rooms);
entries.AddRange(thirdPartyRooms);
return entries;
}
}
private async Task<List<FileEntry>> GetVirtualRoomsForAdminAsync(IEnumerable<FilterType> filterTypes, Guid subjectId, string search, bool searchInContent, bool withSubfolders, SearchArea searchArea,
OrderBy orderBy, IEnumerable<string> tagNames)
{
var folderDao = _daoFactory.GetFolderDao<int>();
var folderThirdpartyDao = _daoFactory.GetFolderDao<string>();
var fileDao = _daoFactory.GetFileDao<int>();
var fileThidpartyDao = _daoFactory.GetFileDao<string>();
var providerDao = _daoFactory.ProviderDao;
var entries = new List<FileEntry>();
var foldersInt = new List<FileEntry<int>>();
var foldersString = new List<FileEntry<string>>();
if (searchArea == SearchArea.Any || searchArea == SearchArea.Active)
{
var roomsFolderId = await _globalFolder.GetFolderVirtualRoomsAsync<int>(_daoFactory);
var thirdpartyFoldersId = await providerDao.GetProvidersInfoAsync(FolderType.VirtualRooms).Select(p => p.FolderId).ToListAsync();
var rooms = await folderDao.GetFoldersAsync(roomsFolderId, orderBy, filterTypes, false, subjectId, search, withSubfolders, tagNames).ToListAsync();
var thirdpartyRooms = await folderThirdpartyDao.GetFoldersAsync(thirdpartyFoldersId, filterTypes, false, subjectId, search, withSubfolders, false, tagNames)
.ToListAsync();
foldersInt.AddRange(rooms);
foldersString.AddRange(thirdpartyRooms);
if (withSubfolders)
{
var files = await fileDao.GetFilesAsync(roomsFolderId, orderBy, FilterType.None, false, subjectId, search, searchInContent, withSubfolders).ToListAsync();
var thidpartyFiles = await fileThidpartyDao.GetFilesAsync(thirdpartyFoldersId, FilterType.None, false, subjectId, search, searchInContent);
entries.AddRange(files);
entries.AddRange(thidpartyFiles);
}
}
if (searchArea == SearchArea.Any || searchArea == SearchArea.Archive)
{
var archiveFolderId = await _globalFolder.GetFolderArchive<int>(_daoFactory);
var thirdpartyFoldersId = await providerDao.GetProvidersInfoAsync(FolderType.Archive).Select(p => p.FolderId).ToListAsync();
var rooms = await folderDao.GetFoldersAsync(archiveFolderId, orderBy, filterTypes, false, subjectId, search, withSubfolders, tagNames).ToListAsync();
var thirdpartyRooms = await folderThirdpartyDao.GetFoldersAsync(thirdpartyFoldersId, filterTypes, false, subjectId, search, withSubfolders, false, tagNames)
.ToListAsync();
foldersInt.AddRange(rooms);
foldersString.AddRange(thirdpartyRooms);
if (withSubfolders)
{
var files = await fileDao.GetFilesAsync(archiveFolderId, orderBy, FilterType.None, false, subjectId, search, searchInContent, withSubfolders).ToListAsync();
var thidpartyFiles = await fileThidpartyDao.GetFilesAsync(thirdpartyFoldersId, FilterType.None, false, subjectId, search, searchInContent);
entries.AddRange(files);
entries.AddRange(thidpartyFiles);
}
}
await SetTagsAsync(foldersInt);
await SetTagsAsync(foldersString);
await SetPinAsync(foldersInt);
await SetPinAsync(foldersString);
entries.AddRange(foldersInt);
entries.AddRange(foldersString);
return entries;
}
private async Task<List<FileEntry>> GetVirtualRoomsForUserAsync<T>(IEnumerable<FileShareRecord> records, List<Guid> subjects, IEnumerable<FilterType> filterTypes, Guid subjectId, string search,
bool searchInContent, bool withSubfolders, SearchArea searchArea, IEnumerable<string> tagNames)
{
var folderDao = _daoFactory.GetFolderDao<T>();
var fileDao = _daoFactory.GetFileDao<T>();
var entries = new List<FileEntry>();
var folderIds = new Dictionary<T, FileShare>();
var recordGroup = records.GroupBy(r => new { r.EntryId, r.EntryType }, (key, group) => new
{
firstRecord = group.OrderBy(r => r, new SubjectComparer(subjects))
.ThenByDescending(r => r.Share, new FileShareRecord.ShareComparer())
.First()
});
foreach (var record in recordGroup.Where(r => r.firstRecord.Share != FileShare.Restrict))
{
if (!folderIds.ContainsKey((T)record.firstRecord.EntryId))
{
folderIds.Add((T)record.firstRecord.EntryId, record.firstRecord.Share);
}
}
Func<FileEntry<T>, bool> filter = f =>
{
var id = f.FileEntryType == FileEntryType.Folder ? f.Id : f.ParentId;
if (searchArea == SearchArea.Archive && f.RootFolderType == FolderType.Archive && folderIds[id] == FileShare.RoomManager)
{
return true;
}
if (searchArea == SearchArea.Active && f.RootFolderType == FolderType.VirtualRooms)
{
return true;
}
if (searchArea == SearchArea.Any && (f.RootFolderType == FolderType.VirtualRooms || (f.RootFolderType == FolderType.Archive && folderIds[id] == FileShare.RoomManager)))
{
return true;
}
return false;
};
var rooms = await folderDao.GetFoldersAsync(folderIds.Keys, filterTypes, false, subjectId, search, withSubfolders, false, tagNames)
.Where(filter).ToListAsync();
await SetTagsAsync(rooms);
await SetPinAsync(rooms);
entries.AddRange(rooms);
if (withSubfolders)
{
var files = await fileDao.GetFilesAsync(folderIds.Keys, FilterType.None, false, subjectId, search, searchInContent);
entries.AddRange(files.Where(filter));
}
return entries;
}
private async Task SetTagsAsync<T>(IEnumerable<FileEntry<T>> entries)
{
if (!entries.Any())
{
return;
}
var tagDao = _daoFactory.GetTagDao<T>();
var tags = await tagDao.GetTagsAsync(TagType.Custom, entries).ToLookupAsync(f => (T)f.EntryId);
foreach (var room in entries)
{
room.Tags = tags[room.Id];
}
}
private async Task SetPinAsync<T>(IEnumerable<FileEntry<T>> entries)
{
if (!entries.Any())
{
return;
}
var tagDao = _daoFactory.GetTagDao<T>();
var tags = await tagDao.GetTagsAsync(_authContext.CurrentAccount.ID, TagType.Pin, entries).ToDictionaryAsync(t => (T)t.EntryId);
foreach (Folder<T> room in entries.Where(e => e.FileEntryType == FileEntryType.Folder))
{
if (tags.ContainsKey(room.Id))
{
room.Pinned = true;
}
}
}
public async Task<List<FileEntry>> GetPrivacyForMeAsync(FilterType filterType, bool subjectGroup, Guid subjectID, string searchText = "", bool searchInContent = false, bool withSubfolders = false)
{
var securityDao = _daoFactory.GetSecurityDao<int>();
@ -1134,6 +1407,8 @@ public class FileSecurity : IFileSecurity
Create,
Edit,
Delete,
CustomFilter
CustomFilter,
RoomEdit,
Rename
}
}

View File

@ -36,7 +36,9 @@ public enum FileShare
Review,
Comment,
FillForms,
CustomFilter
CustomFilter,
RoomManager,
Editing
}
public class FileShareConverter : System.Text.Json.Serialization.JsonConverter<FileShare>

View File

@ -122,6 +122,7 @@ internal abstract class BoxDaoBase : ThirdPartyProviderDao<BoxProviderInfo>
folder.Title = MakeFolderTitle(boxFolder);
folder.FilesCount = boxFolder.ItemCollection != null ? boxFolder.ItemCollection.Entries.Count(item => item is BoxFile) : 0;
folder.FoldersCount = boxFolder.ItemCollection != null ? boxFolder.ItemCollection.Entries.Count(item => item is BoxFolder) : 0;
SetFolderType(folder, isRoot);
if (folder.CreateOn != DateTime.MinValue && folder.CreateOn.Kind == DateTimeKind.Utc)
{

View File

@ -83,18 +83,24 @@ internal class BoxFolderDao : BoxDaoBase, IFolderDao<string>
}
}
public IAsyncEnumerable<Folder<string>> GetFoldersAsync(string parentId, OrderBy orderBy, FilterType filterType, bool subjectGroup, Guid subjectID, string searchText, bool withSubfolders = false)
public IAsyncEnumerable<Folder<string>> GetFoldersAsync(string parentId, OrderBy orderBy, FilterType filterType, bool subjectGroup, Guid subjectID, string searchText, bool withSubfolders = false,
IEnumerable<string> tagName = null)
{
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 GetFoldersAsync(parentId, orderBy, new[] { filterType }, subjectGroup, subjectID, searchText, withSubfolders, tagName);
}
public IAsyncEnumerable<Folder<string>> GetFoldersAsync(string parentId, OrderBy orderBy, IEnumerable<FilterType> filterTypes, bool subjectGroup, Guid subjectID, string searchText, bool withSubfolders = false,
IEnumerable<string> tagNames = null)
{
if (!CheckForInvalidFilters(filterTypes))
{
return AsyncEnumerable.Empty<Folder<string>>();
}
var folders = GetFoldersAsync(parentId); //TODO:!!!
folders = SetFilterByTypes(folders, filterTypes);
if (subjectID != Guid.Empty)
{
folders = folders.Where(x => subjectGroup
@ -107,6 +113,8 @@ internal class BoxFolderDao : BoxDaoBase, IFolderDao<string>
folders = folders.Where(x => x.Title.IndexOf(searchText, StringComparison.OrdinalIgnoreCase) != -1);
}
folders = FilterByTags(folders, tagNames);
if (orderBy == null)
{
orderBy = new OrderBy(SortedByType.DateAndTime, false);
@ -124,18 +132,24 @@ internal class BoxFolderDao : BoxDaoBase, IFolderDao<string>
return folders;
}
public IAsyncEnumerable<Folder<string>> GetFoldersAsync(IEnumerable<string> folderIds, FilterType filterType = FilterType.None, bool subjectGroup = false, Guid? subjectID = null, string searchText = "", bool searchSubfolders = false, bool checkShare = true)
public IAsyncEnumerable<Folder<string>> GetFoldersAsync(IEnumerable<string> folderIds, FilterType filterType = FilterType.None, bool subjectGroup = false, Guid? subjectID = null, string searchText = "", bool searchSubfolders = false, bool checkShare = true,
IEnumerable<string> tagNames = null)
{
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 GetFoldersAsync(folderIds, new[] { filterType }, subjectGroup, subjectID, searchText, searchSubfolders, checkShare, tagNames);
}
public IAsyncEnumerable<Folder<string>> GetFoldersAsync(IEnumerable<string> folderIds, IEnumerable<FilterType> filterTypes, bool subjectGroup = false, Guid? subjectID = null, string searchText = "", bool searchSubfolders = false, bool checkShare = true,
IEnumerable<string> tagNames = null)
{
if (!CheckForInvalidFilters(filterTypes))
{
return AsyncEnumerable.Empty<Folder<string>>();
}
var folders = folderIds.ToAsyncEnumerable().SelectAwait(async e => await GetFolderAsync(e).ConfigureAwait(false));
folders = SetFilterByTypes(folders, filterTypes);
if (subjectID.HasValue && subjectID != Guid.Empty)
{
folders = folders.Where(x => subjectGroup
@ -148,6 +162,8 @@ internal class BoxFolderDao : BoxDaoBase, IFolderDao<string>
folders = folders.Where(x => x.Title.IndexOf(searchText, StringComparison.OrdinalIgnoreCase) != -1);
}
folders = FilterByTags(folders, tagNames);
return folders;
}

View File

@ -54,6 +54,8 @@ internal class BoxProviderInfo : IProviderInfo
public string RootFolderId => "box-" + ID;
public string ProviderKey { get; set; }
public FolderType RootFolderType { get; set; }
public FolderType FolderType { get; set; }
public string FolderId { get; set; }
public string BoxRootId
{

View File

@ -126,6 +126,7 @@ internal abstract class DropboxDaoBase : ThirdPartyProviderDao<DropboxProviderIn
folder.CreateOn = isRoot ? ProviderInfo.CreateOn : default;
folder.ModifiedOn = isRoot ? ProviderInfo.CreateOn : default;
folder.Title = MakeFolderTitle(dropboxFolder);
SetFolderType(folder, isRoot);
if (folder.CreateOn != DateTime.MinValue && folder.CreateOn.Kind == DateTimeKind.Utc)
{

View File

@ -85,18 +85,24 @@ internal class DropboxFolderDao : DropboxDaoBase, IFolderDao<string>
}
}
public IAsyncEnumerable<Folder<string>> GetFoldersAsync(string parentId, OrderBy orderBy, FilterType filterType, bool subjectGroup, Guid subjectID, string searchText, bool withSubfolders = false)
public IAsyncEnumerable<Folder<string>> GetFoldersAsync(string parentId, OrderBy orderBy, FilterType filterType, bool subjectGroup, Guid subjectID, string searchText, bool withSubfolders = false,
IEnumerable<string> tagNames = null)
{
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 GetFoldersAsync(parentId, orderBy, new[] { filterType }, subjectGroup, subjectID, searchText, withSubfolders, tagNames);
}
public IAsyncEnumerable<Folder<string>> GetFoldersAsync(string parentId, OrderBy orderBy, IEnumerable<FilterType> filterTypes, bool subjectGroup, Guid subjectID, string searchText, bool withSubfolders = false,
IEnumerable<string> tagNames = null)
{
if (!CheckForInvalidFilters(filterTypes))
{
return AsyncEnumerable.Empty<Folder<string>>();
}
var folders = GetFoldersAsync(parentId); //TODO:!!!
folders = SetFilterByTypes(folders, filterTypes);
if (subjectID != Guid.Empty)
{
folders = folders.Where(x => subjectGroup
@ -109,6 +115,8 @@ internal class DropboxFolderDao : DropboxDaoBase, IFolderDao<string>
folders = folders.Where(x => x.Title.IndexOf(searchText, StringComparison.OrdinalIgnoreCase) != -1);
}
folders = FilterByTags(folders, tagNames);
if (orderBy == null)
{
orderBy = new OrderBy(SortedByType.DateAndTime, false);
@ -126,18 +134,24 @@ internal class DropboxFolderDao : DropboxDaoBase, IFolderDao<string>
return folders;
}
public IAsyncEnumerable<Folder<string>> GetFoldersAsync(IEnumerable<string> folderIds, FilterType filterType = FilterType.None, bool subjectGroup = false, Guid? subjectID = null, string searchText = "", bool searchSubfolders = false, bool checkShare = true)
public IAsyncEnumerable<Folder<string>> GetFoldersAsync(IEnumerable<string> folderIds, FilterType filterType = FilterType.None, bool subjectGroup = false, Guid? subjectID = null, string searchText = "", bool searchSubfolders = false, bool checkShare = true,
IEnumerable<string> tagNames = null)
{
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 GetFoldersAsync(folderIds, new[] { filterType }, subjectGroup, subjectID, searchText, searchSubfolders, checkShare, tagNames);
}
public IAsyncEnumerable<Folder<string>> GetFoldersAsync(IEnumerable<string> folderIds, IEnumerable<FilterType> filterTypes, bool subjectGroup = false, Guid? subjectID = null, string searchText = "", bool searchSubfolders = false, bool checkShare = true,
IEnumerable<string> tagNames = null)
{
if (!CheckForInvalidFilters(filterTypes))
{
return AsyncEnumerable.Empty<Folder<string>>();
}
var folders = folderIds.ToAsyncEnumerable().SelectAwait(async e => await GetFolderAsync(e).ConfigureAwait(false));
folders = SetFilterByTypes(folders, filterTypes);
if (subjectID.HasValue && subjectID != Guid.Empty)
{
folders = folders.Where(x => subjectGroup
@ -150,6 +164,8 @@ internal class DropboxFolderDao : DropboxDaoBase, IFolderDao<string>
folders = folders.Where(x => x.Title.IndexOf(searchText, StringComparison.OrdinalIgnoreCase) != -1);
}
folders = FilterByTags(folders, tagNames);
return folders;
}

View File

@ -53,6 +53,8 @@ internal class DropboxProviderInfo : IProviderInfo
public string RootFolderId => "dropbox-" + ID;
public string ProviderKey { get; set; }
public FolderType RootFolderType { get; set; }
public FolderType FolderType { get; set; }
public string FolderId { get; set; }
private readonly DropboxStorageDisposableWrapper _wrapper;
private readonly DropboxProviderInfoHelper _dropboxProviderInfoHelper;

View File

@ -138,6 +138,7 @@ internal abstract class GoogleDriveDaoBase : ThirdPartyProviderDao<GoogleDrivePr
folder.ParentId = isRoot ? null : MakeId(GetParentDriveId(driveEntry));
folder.CreateOn = isRoot ? ProviderInfo.CreateOn : (driveEntry.CreatedTime ?? default);
folder.ModifiedOn = isRoot ? ProviderInfo.CreateOn : (driveEntry.ModifiedTime ?? default);
SetFolderType(folder, isRoot);
folder.Title = MakeFolderTitle(driveEntry);

View File

@ -83,18 +83,24 @@ internal class GoogleDriveFolderDao : GoogleDriveDaoBase, IFolderDao<string>
}
}
public IAsyncEnumerable<Folder<string>> GetFoldersAsync(string parentId, OrderBy orderBy, FilterType filterType, bool subjectGroup, Guid subjectID, string searchText, bool withSubfolders = false)
public IAsyncEnumerable<Folder<string>> GetFoldersAsync(string parentId, OrderBy orderBy, FilterType filterType, bool subjectGroup, Guid subjectID, string searchText, bool withSubfolders = false,
IEnumerable<string> tagNames = null)
{
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 GetFoldersAsync(parentId, orderBy, new[] { filterType }, subjectGroup, subjectID, searchText, withSubfolders, tagNames);
}
public IAsyncEnumerable<Folder<string>> GetFoldersAsync(string parentId, OrderBy orderBy, IEnumerable<FilterType> filterTypes, bool subjectGroup, Guid subjectID, string searchText, bool withSubfolders = false,
IEnumerable<string> tagNames = null)
{
if (!CheckForInvalidFilters(filterTypes))
{
return AsyncEnumerable.Empty<Folder<string>>();
}
var folders = GetFoldersAsync(parentId); //TODO:!!!
folders = SetFilterByTypes(folders, filterTypes);
if (subjectID != Guid.Empty)
{
folders = folders.Where(x => subjectGroup
@ -107,6 +113,8 @@ internal class GoogleDriveFolderDao : GoogleDriveDaoBase, IFolderDao<string>
folders = folders.Where(x => x.Title.IndexOf(searchText, StringComparison.OrdinalIgnoreCase) != -1);
}
folders = FilterByTags(folders, tagNames);
if (orderBy == null)
{
orderBy = new OrderBy(SortedByType.DateAndTime, false);
@ -124,18 +132,24 @@ internal class GoogleDriveFolderDao : GoogleDriveDaoBase, IFolderDao<string>
return folders;
}
public IAsyncEnumerable<Folder<string>> GetFoldersAsync(IEnumerable<string> folderIds, FilterType filterType = FilterType.None, bool subjectGroup = false, Guid? subjectID = null, string searchText = "", bool searchSubfolders = false, bool checkShare = true)
public IAsyncEnumerable<Folder<string>> GetFoldersAsync(IEnumerable<string> folderIds, FilterType filterType, bool subjectGroup = false, Guid? subjectID = null, string searchText = "", bool searchSubfolders = false, bool checkShare = true,
IEnumerable<string> tagNames = null)
{
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 GetFoldersAsync(folderIds, new[] { filterType }, subjectGroup, subjectID, searchText, searchSubfolders, checkShare, tagNames);
}
public IAsyncEnumerable<Folder<string>> GetFoldersAsync(IEnumerable<string> folderIds, IEnumerable<FilterType> filterTypes, bool subjectGroup = false, Guid? subjectID = null, string searchText = "", bool searchSubfolders = false, bool checkShare = true,
IEnumerable<string> tagNames = null)
{
if (!CheckForInvalidFilters(filterTypes))
{
return AsyncEnumerable.Empty<Folder<string>>();
}
var folders = folderIds.ToAsyncEnumerable().SelectAwait(async e => await GetFolderAsync(e).ConfigureAwait(false));
folders = SetFilterByTypes(folders, filterTypes);
if (subjectID.HasValue && subjectID != Guid.Empty)
{
folders = folders.Where(x => subjectGroup
@ -148,6 +162,8 @@ internal class GoogleDriveFolderDao : GoogleDriveDaoBase, IFolderDao<string>
folders = folders.Where(x => x.Title.IndexOf(searchText, StringComparison.OrdinalIgnoreCase) != -1);
}
folders = FilterByTags(folders, tagNames);
return folders;
}

View File

@ -57,6 +57,8 @@ internal class GoogleDriveProviderInfo : IProviderInfo
public string RootFolderId => "drive-" + ID;
public string ProviderKey { get; set; }
public FolderType RootFolderType { get; set; }
public FolderType FolderType { get; set; }
public string FolderId { get; set; }
public string DriveRootId
{
get

View File

@ -189,6 +189,16 @@ internal abstract class ThirdPartyProviderDao
return null;
}
public Task<string> GetFolderIDVirtualRooms(bool createIfNotExists)
{
return null;
}
public Task<string> GetFolderIDArchive(bool createIfNotExists)
{
return null;
}
public Task<string> GetBunchObjectIDAsync(string folderID)
{
return null;
@ -227,6 +237,9 @@ internal abstract class ThirdPartyProviderDao<T> : ThirdPartyProviderDao, IDispo
protected RegexDaoSelectorBase<T> DaoSelector { get; set; }
protected T ProviderInfo { get; set; }
protected string PathPrefix { get; private set; }
protected List<FilterType> _constraintFolderFilters =
new List<FilterType> { FilterType.FilesOnly, FilterType.ByExtension, FilterType.DocumentsOnly, FilterType.ImagesOnly,
FilterType.PresentationsOnly, FilterType.SpreadsheetsOnly, FilterType.ArchiveOnly, FilterType.MediaOnly };
protected abstract string Id { get; }
@ -371,6 +384,61 @@ internal abstract class ThirdPartyProviderDao<T> : ThirdPartyProviderDao, IDispo
fileEntry.Error = entry.Error;
}
protected void SetFolderType(Folder<string> folder, bool isRoot)
{
if (isRoot && (ProviderInfo.RootFolderType == FolderType.VirtualRooms ||
ProviderInfo.RootFolderType == FolderType.Archive))
{
folder.FolderType = ProviderInfo.RootFolderType;
}
else if (ProviderInfo.FolderId == folder.Id)
{
folder.FolderType = ProviderInfo.FolderType;
}
}
protected IAsyncEnumerable<Folder<string>> FilterByTags(IAsyncEnumerable<Folder<string>> folders, IEnumerable<string> tagNames)
{
if (tagNames == null || !tagNames.Any())
{
return folders;
}
var filtered = folders.Join(FilesDbContext.ThirdpartyIdMapping.ToAsyncEnumerable(), f => f.Id, m => m.Id, (folder, map) => new { folder, map.HashId })
.Join(FilesDbContext.TagLink.ToAsyncEnumerable(), r => r.HashId, t => t.EntryId, (result, tag) => new { result.folder, tag.TagId })
.Join(FilesDbContext.Tag.ToAsyncEnumerable(), r => r.TagId, t => t.Id, (result, tagInfo) => new {result.folder, tagInfo.Name })
.Where(r => tagNames.Contains(r.Name))
.Select(r => r.folder);
return filtered;
}
protected IAsyncEnumerable<Folder<string>> SetFilterByTypes(IAsyncEnumerable<Folder<string>> folders, IEnumerable<FilterType> filterTypes)
{
if (filterTypes.Any() && !filterTypes.Contains(FilterType.None))
{
var filter = filterTypes.Select(f => f switch
{
FilterType.FillingFormsRooms => FolderType.FillingFormsRoom,
FilterType.EditingRooms => FolderType.EditingRoom,
FilterType.ReviewRooms => FolderType.ReviewRoom,
FilterType.ReadOnlyRooms => FolderType.ReadOnlyRoom,
FilterType.CustomRooms => FolderType.CustomRoom,
_ => FolderType.CustomRoom
}).ToHashSet();
return folders.Where(f => filter.Contains(f.FolderType));
}
return folders;
}
protected bool CheckForInvalidFilters(IEnumerable<FilterType> filterTypes)
{
var intersection = filterTypes.Intersect(_constraintFolderFilters);
return !intersection.Any();
}
protected abstract string MakeId(string path = null);
@ -465,6 +533,21 @@ internal abstract class ThirdPartyProviderDao<T> : ThirdPartyProviderDao, IDispo
{
return AsyncEnumerable.Empty<Tag>();
}
public IAsyncEnumerable<TagInfo> GetTagsInfoAsync(string searchText, TagType tagType, bool byName, int from = 0, int count = 0)
{
return AsyncEnumerable.Empty<TagInfo>();
}
public IAsyncEnumerable<TagInfo> GetTagsInfoAsync(IEnumerable<string> names)
{
return AsyncEnumerable.Empty<TagInfo>();
}
public Task<TagInfo> SaveTagInfoAsync(TagInfo tagInfo)
{
return Task.FromResult(tagInfo);
}
public IEnumerable<Tag> SaveTags(IEnumerable<Tag> tag)
{
@ -483,6 +566,16 @@ internal abstract class ThirdPartyProviderDao<T> : ThirdPartyProviderDao, IDispo
public void UpdateNewTags(Tag tag)
{
}
public Task RemoveTagsAsync(FileEntry<string> entry, IEnumerable<int> tagsIds)
{
return Task.CompletedTask;
}
public Task RemoveTagsAsync(IEnumerable<int> tagsIds)
{
return Task.CompletedTask;
}
public void RemoveTags(IEnumerable<Tag> tag)
{

View File

@ -125,6 +125,7 @@ internal abstract class OneDriveDaoBase : ThirdPartyProviderDao<OneDriveProvider
folder.ParentId = 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);
SetFolderType(folder, isRoot);
folder.Title = MakeItemTitle(onedriveFolder);

View File

@ -83,18 +83,25 @@ internal class OneDriveFolderDao : OneDriveDaoBase, IFolderDao<string>
}
}
public IAsyncEnumerable<Folder<string>> GetFoldersAsync(string parentId, OrderBy orderBy, FilterType filterType, bool subjectGroup, Guid subjectID, string searchText, bool withSubfolders = false)
public IAsyncEnumerable<Folder<string>> GetFoldersAsync(string parentId, OrderBy orderBy, FilterType filterType, bool subjectGroup, Guid subjectID, string searchText, bool withSubfolders = false,
IEnumerable<string> tagNames = null)
{
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 GetFoldersAsync(parentId, orderBy, new[] { filterType }, subjectGroup, subjectID, searchText, withSubfolders, tagNames);
}
public IAsyncEnumerable<Folder<string>> GetFoldersAsync(string parentId, OrderBy orderBy, IEnumerable<FilterType> filterTypes, bool subjectGroup, Guid subjectID, string searchText, bool withSubfolders = false,
IEnumerable<string> tagNames = null)
{
if (!CheckForInvalidFilters(filterTypes))
{
return AsyncEnumerable.Empty<Folder<string>>();
}
var folders = GetFoldersAsync(parentId); //TODO:!!!
//Filter
folders = SetFilterByTypes(folders, filterTypes);
//Filter
if (subjectID != Guid.Empty)
{
folders = folders.Where(x => subjectGroup
@ -107,6 +114,8 @@ internal class OneDriveFolderDao : OneDriveDaoBase, IFolderDao<string>
folders = folders.Where(x => x.Title.IndexOf(searchText, StringComparison.OrdinalIgnoreCase) != -1);
}
folders = FilterByTags(folders, tagNames);
if (orderBy == null)
{
orderBy = new OrderBy(SortedByType.DateAndTime, false);
@ -124,18 +133,24 @@ internal class OneDriveFolderDao : OneDriveDaoBase, IFolderDao<string>
return folders;
}
public IAsyncEnumerable<Folder<string>> GetFoldersAsync(IEnumerable<string> folderIds, FilterType filterType = FilterType.None, bool subjectGroup = false, Guid? subjectID = null, string searchText = "", bool searchSubfolders = false, bool checkShare = true)
public IAsyncEnumerable<Folder<string>> GetFoldersAsync(IEnumerable<string> folderIds, FilterType filterType = FilterType.None, bool subjectGroup = false, Guid? subjectID = null, string searchText = "", bool searchSubfolders = false, bool checkShare = true,
IEnumerable<string> tagNames = null)
{
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 GetFoldersAsync(folderIds, new[] { filterType }, subjectGroup, subjectID, searchText, searchSubfolders, checkShare, tagNames);
}
public IAsyncEnumerable<Folder<string>> GetFoldersAsync(IEnumerable<string> folderIds, IEnumerable<FilterType> filterTypes, bool subjectGroup = false, Guid? subjectID = null, string searchText = "", bool searchSubfolders = false, bool checkShare = true,
IEnumerable<string> tagNames = null)
{
if (!CheckForInvalidFilters(filterTypes))
{
return AsyncEnumerable.Empty<Folder<string>>();
}
var folders = folderIds.ToAsyncEnumerable().SelectAwait(async e => await GetFolderAsync(e).ConfigureAwait(false));
folders = SetFilterByTypes(folders, filterTypes);
if (subjectID.HasValue && subjectID != Guid.Empty)
{
folders = folders.Where(x => subjectGroup
@ -148,6 +163,8 @@ internal class OneDriveFolderDao : OneDriveDaoBase, IFolderDao<string>
folders = folders.Where(x => x.Title.IndexOf(searchText, StringComparison.OrdinalIgnoreCase) != -1);
}
folders = FilterByTags(folders, tagNames);
return folders;
}

View File

@ -54,6 +54,8 @@ internal class OneDriveProviderInfo : IProviderInfo
public string RootFolderId => "onedrive-" + ID;
public string ProviderKey { get; set; }
public FolderType RootFolderType { get; set; }
public FolderType FolderType { get; set; }
public string FolderId { get; set; }
private readonly OneDriveStorageDisposableWrapper _wrapper;
private readonly OneDriveProviderInfoHelper _oneDriveProviderInfoHelper;

View File

@ -203,6 +203,45 @@ internal class ProviderAccountDao : IProviderDao
{
return providerInfo != null && await providerInfo.CheckAccessAsync();
}
public async Task<bool> UpdateProviderInfoAsync(int linkId, FolderType rootFolderType)
{
var forUpdate = await FilesDbContext.ThirdpartyAccount
.Where(r => r.Id == linkId)
.Where(r => r.TenantId == TenantID)
.FirstOrDefaultAsync().ConfigureAwait(false);
if (forUpdate == null)
{
return false;
}
forUpdate.FolderType = rootFolderType;
await FilesDbContext.SaveChangesAsync().ConfigureAwait(false);
return true;
}
public async Task<bool> UpdateProviderInfoAsync(int linkId, string folderId, FolderType folderType)
{
var forUpdate = await FilesDbContext.ThirdpartyAccount
.Where(r => r.Id == linkId)
.Where(r => r.TenantId == TenantID)
.FirstOrDefaultAsync().ConfigureAwait(false);
if (forUpdate == null)
{
return false;
}
forUpdate.RoomType = folderType;
forUpdate.FolderId = folderId;
await FilesDbContext.SaveChangesAsync().ConfigureAwait(false);
return true;
}
public virtual async Task<int> UpdateProviderInfoAsync(int linkId, AuthData authData)
{
@ -389,7 +428,9 @@ internal class ProviderAccountDao : IProviderDao
var providerTitle = input.Title ?? string.Empty;
var token = DecryptToken(input.Token, id);
var owner = input.UserId;
var folderType = input.FolderType;
var rootFolderType = input.FolderType;
var folderType = input.RoomType;
var folderId = input.FolderId;
var createOn = _tenantUtil.DateTimeFromUtc(input.CreateOn);
var authData = new AuthData(input.Url, input.UserName, DecryptPassword(input.Password, id), token);
@ -405,9 +446,11 @@ internal class ProviderAccountDao : IProviderDao
box.CustomerTitle = providerTitle;
box.Owner = owner == Guid.Empty ? _securityContext.CurrentAccount.ID : owner;
box.ProviderKey = input.Provider;
box.RootFolderType = folderType;
box.RootFolderType = rootFolderType;
box.CreateOn = createOn;
box.Token = OAuth20Token.FromJson(token);
box.FolderType = folderType;
box.FolderId = folderId;
return box;
}
@ -424,9 +467,11 @@ internal class ProviderAccountDao : IProviderDao
drop.CustomerTitle = providerTitle;
drop.Owner = owner == Guid.Empty ? _securityContext.CurrentAccount.ID : owner;
drop.ProviderKey = input.Provider;
drop.RootFolderType = folderType;
drop.RootFolderType = rootFolderType;
drop.CreateOn = createOn;
drop.Token = OAuth20Token.FromJson(token);
drop.FolderType = folderType;
drop.FolderId = folderId;
return drop;
}
@ -443,9 +488,11 @@ internal class ProviderAccountDao : IProviderDao
sh.CustomerTitle = providerTitle;
sh.Owner = owner == Guid.Empty ? _securityContext.CurrentAccount.ID : owner;
sh.ProviderKey = input.Provider;
sh.RootFolderType = folderType;
sh.RootFolderType = rootFolderType;
sh.CreateOn = createOn;
sh.InitClientContext(authData);
sh.FolderType = folderType;
sh.FolderId = folderId;
return sh;
}
@ -462,9 +509,11 @@ internal class ProviderAccountDao : IProviderDao
gd.CustomerTitle = providerTitle;
gd.Owner = owner == Guid.Empty ? _securityContext.CurrentAccount.ID : owner;
gd.ProviderKey = input.Provider;
gd.RootFolderType = folderType;
gd.RootFolderType = rootFolderType;
gd.CreateOn = createOn;
gd.Token = OAuth20Token.FromJson(token);
gd.FolderType = folderType;
gd.FolderId = folderId;
return gd;
}
@ -481,9 +530,11 @@ internal class ProviderAccountDao : IProviderDao
od.CustomerTitle = providerTitle;
od.Owner = owner == Guid.Empty ? _securityContext.CurrentAccount.ID : owner;
od.ProviderKey = input.Provider;
od.RootFolderType = folderType;
od.RootFolderType = rootFolderType;
od.CreateOn = createOn;
od.Token = OAuth20Token.FromJson(token);
od.FolderType = folderType;
od.FolderId = folderId;
return od;
}
@ -508,9 +559,11 @@ internal class ProviderAccountDao : IProviderDao
sharpBoxProviderInfo.CustomerTitle = providerTitle;
sharpBoxProviderInfo.Owner = owner == Guid.Empty ? _securityContext.CurrentAccount.ID : owner;
sharpBoxProviderInfo.ProviderKey = input.Provider;
sharpBoxProviderInfo.RootFolderType = folderType;
sharpBoxProviderInfo.RootFolderType = rootFolderType;
sharpBoxProviderInfo.CreateOn = createOn;
sharpBoxProviderInfo.AuthData = authData;
sharpBoxProviderInfo.FolderType = folderType;
sharpBoxProviderInfo.FolderId = folderId;
return sharpBoxProviderInfo;
}

View File

@ -99,7 +99,8 @@ internal class ProviderFolderDao : ProviderDaoBase, IFolderDao<string>
return folders.Where(r => r != null);
}
public async IAsyncEnumerable<Folder<string>> GetFoldersAsync(string parentId, OrderBy orderBy, FilterType filterType, bool subjectGroup, Guid subjectID, string searchText, bool withSubfolders = false)
public async IAsyncEnumerable<Folder<string>> GetFoldersAsync(string parentId, OrderBy orderBy, FilterType filterType, bool subjectGroup, Guid subjectID, string searchText, bool withSubfolders = false,
IEnumerable<string> tagNames = null)
{
var selector = GetSelector(parentId);
var folderDao = selector.GetFolderDao(parentId);
@ -114,7 +115,24 @@ internal class ProviderFolderDao : ProviderDaoBase, IFolderDao<string>
}
}
public IAsyncEnumerable<Folder<string>> GetFoldersAsync(IEnumerable<string> folderIds, FilterType filterType = FilterType.None, bool subjectGroup = false, Guid? subjectID = null, string searchText = "", bool searchSubfolders = false, bool checkShare = true)
public async IAsyncEnumerable<Folder<string>> GetFoldersAsync(string parentId, OrderBy orderBy, IEnumerable<FilterType> filterTypes, bool subjectGroup, Guid subjectID, string searchText, bool withSubfolders = false,
IEnumerable<string> tagNames = null)
{
var selector = GetSelector(parentId);
var folderDao = selector.GetFolderDao(parentId);
var folders = folderDao.GetFoldersAsync(selector.ConvertId(parentId), orderBy, filterTypes, subjectGroup, subjectID, searchText, withSubfolders);
var result = folders.Where(r => r != null);
await SetSharedPropertyAsync(result).ConfigureAwait(false);
await foreach (var r in result.ConfigureAwait(false))
{
yield return r;
}
}
public IAsyncEnumerable<Folder<string>> GetFoldersAsync(IEnumerable<string> folderIds, FilterType filterType = FilterType.None, bool subjectGroup = false, Guid? subjectID = null, string searchText = "", bool searchSubfolders = false, bool checkShare = true,
IEnumerable<string> tagNames = null)
{
var result = AsyncEnumerable.Empty<Folder<string>>();
@ -135,7 +153,37 @@ internal class ProviderFolderDao : ProviderDaoBase, IFolderDao<string>
var folderDao = selectorLocal.GetFolderDao(matchedId.FirstOrDefault());
return folderDao.GetFoldersAsync(matchedId.Select(selectorLocal.ConvertId).ToList(),
filterType, subjectGroup, subjectID, searchText, searchSubfolders, checkShare);
filterType, subjectGroup, subjectID, searchText, searchSubfolders, checkShare, tagNames);
})
.Where(r => r != null));
}
return result.Distinct();
}
public IAsyncEnumerable<Folder<string>> GetFoldersAsync(IEnumerable<string> folderIds, IEnumerable<FilterType> filterTypes, bool subjectGroup = false, Guid? subjectID = null, string searchText = "", bool searchSubfolders = false, bool checkShare = true,
IEnumerable<string> tagNames = null)
{
var result = AsyncEnumerable.Empty<Folder<string>>();
foreach (var selector in GetSelectors())
{
var selectorLocal = selector;
var matchedIds = folderIds.Where(selectorLocal.IsMatch).ToList();
if (matchedIds.Count == 0)
{
continue;
}
result = result.Concat(matchedIds.GroupBy(selectorLocal.GetIdCode)
.ToAsyncEnumerable()
.SelectMany(matchedId =>
{
var folderDao = selectorLocal.GetFolderDao(matchedId.FirstOrDefault());
return folderDao.GetFoldersAsync(matchedId.Select(selectorLocal.ConvertId).ToList(),
filterTypes, subjectGroup, subjectID, searchText, searchSubfolders, checkShare, tagNames);
})
.Where(r => r != null));
}

View File

@ -152,9 +152,9 @@ internal class ProviderSecurityDao : ProviderDaoBase, ISecurityDao<string>
private Task<List<FileShareRecord>> GetShareForFoldersAsync(IReadOnlyCollection<FileEntry<string>> folders)
{
if (folders.Count == 0)
{
return Task.FromResult(new List<FileShareRecord>());
}
{
return Task.FromResult(new List<FileShareRecord>());
}
return InternalGetShareForFoldersAsync(folders);
}
@ -172,11 +172,11 @@ internal class ProviderSecurityDao : ProviderDaoBase, ISecurityDao<string>
continue;
}
var parentFolders = await folderDao.GetParentFoldersAsync(selector.ConvertId(folder.Id));
var parentFolders = await folderDao.GetParentFoldersAsync(selector.ConvertId(folder.Id));
if (parentFolders == null || parentFolders.Count == 0)
{
continue;
}
{
continue;
}
parentFolders.Reverse();
var pureShareRecords = await GetPureShareRecordsAsync(parentFolders);

View File

@ -103,6 +103,11 @@ internal class ProviderTagDao : ProviderDaoBase, ITagDao<string>
_tagDao.UpdateNewTags(tag);
}
public async Task RemoveTagsAsync(FileEntry<string> entry, IEnumerable<int> tagsIds)
{
await _tagDao.RemoveTagsAsync(entry, tagsIds);
}
public void RemoveTags(IEnumerable<Tag> tag)
{
_tagDao.RemoveTags(tag);
@ -123,5 +128,25 @@ internal class ProviderTagDao : ProviderDaoBase, ITagDao<string>
return _tagDao.GetTagsAsync(subject, tagType, fileEntries);
}
public IAsyncEnumerable<TagInfo> GetTagsInfoAsync(string searchText, TagType tagType, bool byName, int from = 0, int count = 0)
{
return _tagDao.GetTagsInfoAsync(searchText, tagType, byName, from, count);
}
public IAsyncEnumerable<TagInfo> GetTagsInfoAsync(IEnumerable<string> names)
{
return _tagDao.GetTagsInfoAsync(names);
}
public Task<TagInfo> SaveTagInfoAsync(TagInfo tagInfo)
{
return _tagDao.SaveTagInfoAsync(tagInfo);
}
public Task RemoveTagsAsync(IEnumerable<int> tagsIds)
{
return _tagDao.RemoveTagsAsync(tagsIds);
}
#endregion
}

View File

@ -89,18 +89,24 @@ internal class SharePointFolderDao : SharePointDaoBase, IFolderDao<string>
}
}
public IAsyncEnumerable<Folder<string>> GetFoldersAsync(string parentId, OrderBy orderBy, FilterType filterType, bool subjectGroup, Guid subjectID, string searchText, bool withSubfolders = false)
public IAsyncEnumerable<Folder<string>> GetFoldersAsync(string parentId, OrderBy orderBy, FilterType filterType, bool subjectGroup, Guid subjectID, string searchText, bool withSubfolders = false,
IEnumerable<string> tagNames = null)
{
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 GetFoldersAsync(parentId, orderBy, new[] { filterType }, subjectGroup, subjectID, searchText, withSubfolders, tagNames);
}
public IAsyncEnumerable<Folder<string>> GetFoldersAsync(string parentId, OrderBy orderBy, IEnumerable<FilterType> filterTypes, bool subjectGroup, Guid subjectID, string searchText, bool withSubfolders = false,
IEnumerable<string> tagNames = null)
{
if (!CheckForInvalidFilters(filterTypes))
{
return AsyncEnumerable.Empty<Folder<string>>();
}
var folders = GetFoldersAsync(parentId);
folders = SetFilterByTypes(folders, filterTypes);
//Filter
if (subjectID != Guid.Empty)
{
@ -114,6 +120,8 @@ internal class SharePointFolderDao : SharePointDaoBase, IFolderDao<string>
folders = folders.Where(x => x.Title.IndexOf(searchText, StringComparison.OrdinalIgnoreCase) != -1);
}
folders = FilterByTags(folders, tagNames);
if (orderBy == null)
{
orderBy = new OrderBy(SortedByType.DateAndTime, false);
@ -131,18 +139,24 @@ internal class SharePointFolderDao : SharePointDaoBase, IFolderDao<string>
return folders;
}
public IAsyncEnumerable<Folder<string>> GetFoldersAsync(IEnumerable<string> folderIds, FilterType filterType = FilterType.None, bool subjectGroup = false, Guid? subjectID = null, string searchText = "", bool searchSubfolders = false, bool checkShare = true)
public IAsyncEnumerable<Folder<string>> GetFoldersAsync(IEnumerable<string> folderIds, FilterType filterType = FilterType.None, bool subjectGroup = false, Guid? subjectID = null, string searchText = "", bool searchSubfolders = false, bool checkShare = true,
IEnumerable<string> tagNames = null)
{
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 GetFoldersAsync(folderIds, new[] { filterType }, subjectGroup, subjectID, searchText, searchSubfolders, checkShare, tagNames);
}
public IAsyncEnumerable<Folder<string>> GetFoldersAsync(IEnumerable<string> folderIds, IEnumerable<FilterType> filterTypes, bool subjectGroup = false, Guid? subjectID = null, string searchText = "", bool searchSubfolders = false, bool checkShare = true,
IEnumerable<string> tagNames = null)
{
if (!CheckForInvalidFilters(filterTypes))
{
return AsyncEnumerable.Empty<Folder<string>>();
}
var folders = folderIds.ToAsyncEnumerable().SelectAwait(async e => await GetFolderAsync(e).ConfigureAwait(false));
folders = SetFilterByTypes(folders, filterTypes);
if (subjectID.HasValue && subjectID != Guid.Empty)
{
folders = folders.Where(x => subjectGroup
@ -155,6 +169,8 @@ internal class SharePointFolderDao : SharePointDaoBase, IFolderDao<string>
folders = folders.Where(x => x.Title.IndexOf(searchText, StringComparison.OrdinalIgnoreCase) != -1);
}
folders = FilterByTags(folders, tagNames);
return folders;
}

View File

@ -24,6 +24,8 @@
// content are licensed under the terms of the Creative Commons Attribution-ShareAlike 4.0
// International. See the License terms at http://creativecommons.org/licenses/by-sa/4.0/legalcode
using ASC.Files.Core;
using File = Microsoft.SharePoint.Client.File;
using Folder = Microsoft.SharePoint.Client.Folder;
@ -38,10 +40,12 @@ public class SharePointProviderInfo : IProviderInfo
public string ProviderKey { get; set; }
public Guid Owner { get; set; }
public FolderType RootFolderType { get; set; }
public FolderType FolderType { get; set; }
public DateTime CreateOn { get; set; }
public string CustomerTitle { get; set; }
public string RootFolderId => "spoint-" + ID;
public string SpRootFolderId { get; set; } = "/Shared Documents";
public string FolderId { get; set; }
public SharePointProviderInfo(
ILogger<SharePointProviderInfo> logger,
@ -557,7 +561,7 @@ public class SharePointProviderInfo : IProviderInfo
result.ParentId = null;
result.CreateBy = Owner;
result.CreateOn = DateTime.UtcNow;
result.FolderType = FolderType.DEFAULT;
result.FolderType = Core.FolderType.DEFAULT;
result.ModifiedBy = Owner;
result.ModifiedOn = DateTime.UtcNow;
result.ProviderId = ID;
@ -580,7 +584,7 @@ public class SharePointProviderInfo : IProviderInfo
result.ParentId = isRoot ? null : MakeId(GetParentFolderId(folder.ServerRelativeUrl));
result.CreateBy = Owner;
result.CreateOn = CreateOn;
result.FolderType = FolderType.DEFAULT;
result.FolderType = Core.FolderType.DEFAULT;
result.ModifiedBy = Owner;
result.ModifiedOn = CreateOn;
result.ProviderId = ID;
@ -593,6 +597,8 @@ public class SharePointProviderInfo : IProviderInfo
result.FilesCount = 0;
result.FoldersCount = 0;
SetFolderType(result, isRoot);
return result;
}
@ -637,6 +643,19 @@ public class SharePointProviderInfo : IProviderInfo
{
_clientContext.Dispose();
}
private void SetFolderType(Folder<string> folder, bool isRoot)
{
if (isRoot && (RootFolderType == FolderType.VirtualRooms ||
RootFolderType == FolderType.Archive))
{
folder.FolderType = RootFolderType;
}
else if (FolderId == folder.Id)
{
folder.FolderType = FolderType;
}
}
}
[Singletone]

View File

@ -284,6 +284,7 @@ internal abstract class SharpBoxDaoBase : ThirdPartyProviderDao<SharpBoxProvider
folder.Title = MakeTitle(fsEntry);
folder.FilesCount = 0; /*fsEntry.Count - childFoldersCount NOTE: Removed due to performance isssues*/
folder.FoldersCount = 0; /*childFoldersCount NOTE: Removed due to performance isssues*/
SetFolderType(folder, isRoot);
if (folder.CreateOn != DateTime.MinValue && folder.CreateOn.Kind == DateTimeKind.Utc)
{

View File

@ -85,19 +85,25 @@ internal class SharpBoxFolderDao : SharpBoxDaoBase, IFolderDao<string>
return parentFolder.OfType<ICloudDirectoryEntry>().Select(ToFolder).ToAsyncEnumerable();
}
public IAsyncEnumerable<Folder<string>> GetFoldersAsync(string parentId, OrderBy orderBy, FilterType filterType, bool subjectGroup, Guid subjectID, string searchText, bool withSubfolders = false)
public IAsyncEnumerable<Folder<string>> GetFoldersAsync(string parentId, OrderBy orderBy, FilterType filterType, bool subjectGroup, Guid subjectID, string searchText, bool withSubfolders = false,
IEnumerable<string> tagNames = null)
{
return GetFoldersAsync(parentId, orderBy, new[] { filterType }, subjectGroup, subjectID, searchText, withSubfolders, tagNames);
}
public IAsyncEnumerable<Folder<string>> GetFoldersAsync(string parentId, OrderBy orderBy, IEnumerable<FilterType> filterTypes, bool subjectGroup, Guid subjectID, string searchText, bool withSubfolders = false,
IEnumerable<string> tagNames = null)
{
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)
if (!CheckForInvalidFilters(filterTypes))
{
return AsyncEnumerable.Empty<Folder<string>>();
}
var folders = GetFoldersAsync(parentId); //TODO:!!!
folders = SetFilterByTypes(folders, filterTypes);
//Filter
if (subjectID != Guid.Empty)
{
@ -111,6 +117,8 @@ internal class SharpBoxFolderDao : SharpBoxDaoBase, IFolderDao<string>
folders = folders.Where(x => x.Title.IndexOf(searchText, StringComparison.OrdinalIgnoreCase) != -1);
}
folders = FilterByTags(folders, tagNames);
if (orderBy == null)
{
orderBy = new OrderBy(SortedByType.DateAndTime, false);
@ -128,18 +136,24 @@ internal class SharpBoxFolderDao : SharpBoxDaoBase, IFolderDao<string>
return folders;
}
public IAsyncEnumerable<Folder<string>> GetFoldersAsync(IEnumerable<string> folderIds, FilterType filterType = FilterType.None, bool subjectGroup = false, Guid? subjectID = null, string searchText = "", bool searchSubfolders = false, bool checkShare = true)
public IAsyncEnumerable<Folder<string>> GetFoldersAsync(IEnumerable<string> folderIds, FilterType filterType = FilterType.None, bool subjectGroup = false, Guid? subjectID = null, string searchText = "", bool searchSubfolders = false, bool checkShare = true,
IEnumerable<string> tagNames = null)
{
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 GetFoldersAsync(folderIds, new[] { filterType }, subjectGroup, subjectID, searchText, searchSubfolders, checkShare, tagNames);
}
public IAsyncEnumerable<Folder<string>> GetFoldersAsync(IEnumerable<string> folderIds, IEnumerable<FilterType> filterTypes, bool subjectGroup = false, Guid? subjectID = null, string searchText = "", bool searchSubfolders = false, bool checkShare = true,
IEnumerable<string> tagNames = null)
{
if (!CheckForInvalidFilters(filterTypes))
{
return AsyncEnumerable.Empty<Folder<string>>();
}
var folders = folderIds.ToAsyncEnumerable().SelectAwait(async e => await GetFolderAsync(e).ConfigureAwait(false));
folders = SetFilterByTypes(folders, filterTypes);
if (subjectID.HasValue && subjectID != Guid.Empty)
{
folders = folders.Where(x => subjectGroup
@ -152,6 +166,8 @@ internal class SharpBoxFolderDao : SharpBoxDaoBase, IFolderDao<string>
folders = folders.Where(x => x.Title.IndexOf(searchText, StringComparison.OrdinalIgnoreCase) != -1);
}
folders = FilterByTags(folders, tagNames);
return folders;
}

View File

@ -109,6 +109,8 @@ internal class SharpBoxProviderInfo : IProviderInfo
}
public FolderType RootFolderType { get; set; }
public FolderType FolderType { get; set; }
public string FolderId { get; set; }
private readonly SharpBoxStorageDisposableWrapper _wrapper;
}

View File

@ -0,0 +1,166 @@
// (c) Copyright Ascensio System SIA 2010-2022
//
// This program is a free software product.
// You can redistribute it and/or modify it under the terms
// of the GNU Affero General Public License (AGPL) version 3 as published by the Free Software
// Foundation. In accordance with Section 7(a) of the GNU AGPL 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 details, see
// the GNU AGPL at: http://www.gnu.org/licenses/agpl-3.0.html
//
// You can contact Ascensio System SIA at Lubanas st. 125a-25, Riga, Latvia, EU, LV-1021.
//
// The interactive user interfaces in modified source and object code versions of the Program must
// display Appropriate Legal Notices, as required under Section 5 of the GNU AGPL version 3.
//
// Pursuant to Section 7(b) of the License you must retain the original Product logo when
// distributing the program. Pursuant to Section 7(e) we decline to grant you any rights under
// trademark law for use of our trademarks.
//
// All the Product's GUI elements, including illustrations and icon sets, as well as technical writing
// content are licensed under the terms of the Creative Commons Attribution-ShareAlike 4.0
// International. See the License terms at http://creativecommons.org/licenses/by-sa/4.0/legalcode
namespace ASC.Files.Core.VirtualRooms;
[Scope]
public class CustomTagsService<T>
{
private readonly IDaoFactory _daoFactory;
private readonly FileSecurity _fileSecurity;
private readonly AuthContext _authContext;
private readonly FileSecurityCommon _fileSecurityCommon;
private readonly FilesMessageService _filesMessageService;
private readonly IHttpContextAccessor _httpContextAccessor;
private readonly IMapper _mapper;
public CustomTagsService(IDaoFactory daoFactory, FileSecurity fileSecurity, AuthContext authContext, FileSecurityCommon fileSecurityCommon,
FilesMessageService filesMessageService, IHttpContextAccessor httpContextAccessor, IMapper mapper)
{
_daoFactory = daoFactory;
_fileSecurity = fileSecurity;
_authContext = authContext;
_fileSecurityCommon = fileSecurityCommon;
_filesMessageService = filesMessageService;
_httpContextAccessor = httpContextAccessor;
_mapper = mapper;
}
private ITagDao<T> TagDao => _daoFactory.GetTagDao<T>();
private IFolderDao<T> FolderDao => _daoFactory.GetFolderDao<T>();
private IDictionary<string, StringValues> Headers => _httpContextAccessor?.HttpContext?.Request?.Headers;
public async Task<object> CreateTagAsync(string name)
{
if (!_fileSecurityCommon.IsAdministrator(_authContext.CurrentAccount.ID))
{
throw new SecurityException("You do not have permission to create tags");
}
ArgumentNullOrEmptyException.ThrowIfNullOrEmpty(name);
var tags = await TagDao.GetTagsInfoAsync(name, TagType.Custom, true).ToListAsync();
if (tags.Any())
{
throw new Exception("The tag already exists");
}
var tagInfo = new TagInfo
{
Name = name,
Owner = _authContext.CurrentAccount.ID,
Type = TagType.Custom
};
var savedTag = await TagDao.SaveTagInfoAsync(tagInfo);
_filesMessageService.Send(Headers, MessageAction.TagCreated, savedTag.Name);
return savedTag.Name;
}
public async Task DeleteTagsAsync(IEnumerable<string> names)
{
if (!_fileSecurityCommon.IsAdministrator(_authContext.CurrentAccount.ID))
{
throw new SecurityException("You do not have permission to remove tags");
}
if (!names.Any())
{
return;
}
var tagDao = TagDao;
var tags = await tagDao.GetTagsInfoAsync(names).ToListAsync();
await tagDao.RemoveTagsAsync(tags.Select(t => t.Id));
_filesMessageService.Send(Headers, MessageAction.TagsDeleted, tags.Select(t => t.Name).ToArray());
}
public async Task<Folder<T>> AddRoomTagsAsync(T folderId, IEnumerable<string> names)
{
var folder = await FolderDao.GetFolderAsync(folderId);
if (!await _fileSecurity.CanEditRoomAsync(folder))
{
throw new SecurityException("You do not have permission to edit the room");
}
if (!names.Any())
{
return folder;
}
var tagDao = TagDao;
var tagsInfos = await tagDao.GetTagsInfoAsync(names).ToListAsync();
var tags = tagsInfos.Select(tagInfo => Tag.Custom(_authContext.CurrentAccount.ID, folder, tagInfo.Name));
tagDao.SaveTags(tags);
_filesMessageService.Send(folder, Headers, MessageAction.AddedRoomTags, tagsInfos.Select(t => t.Name).ToArray());
return folder;
}
public async Task<Folder<T>> DeleteRoomTagsAsync(T folderId, IEnumerable<string> names)
{
var folder = await FolderDao.GetFolderAsync(folderId);
if (!await _fileSecurity.CanEditRoomAsync(folder))
{
throw new SecurityException("You do not have permission to edit the room");
}
if (!names.Any())
{
return folder;
}
var tagDao = TagDao;
var tagsInfos = await tagDao.GetTagsInfoAsync(names).ToListAsync();
await tagDao.RemoveTagsAsync(folder, tagsInfos.Select(t => t.Id));
_filesMessageService.Send(folder, Headers, MessageAction.DeletedRoomTags, tagsInfos.Select(t => t.Name).ToArray());
return folder;
}
public async IAsyncEnumerable<object> GetTagsInfoAsync(string searchText, TagType tagType, int from, int count)
{
await foreach (var tagInfo in TagDao.GetTagsInfoAsync(searchText, tagType, false, from, count))
{
yield return tagInfo.Name;
}
}
}

View File

@ -0,0 +1,34 @@
// (c) Copyright Ascensio System SIA 2010-2022
//
// This program is a free software product.
// You can redistribute it and/or modify it under the terms
// of the GNU Affero General Public License (AGPL) version 3 as published by the Free Software
// Foundation. In accordance with Section 7(a) of the GNU AGPL 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 details, see
// the GNU AGPL at: http://www.gnu.org/licenses/agpl-3.0.html
//
// You can contact Ascensio System SIA at Lubanas st. 125a-25, Riga, Latvia, EU, LV-1021.
//
// The interactive user interfaces in modified source and object code versions of the Program must
// display Appropriate Legal Notices, as required under Section 5 of the GNU AGPL version 3.
//
// Pursuant to Section 7(b) of the License you must retain the original Product logo when
// distributing the program. Pursuant to Section 7(e) we decline to grant you any rights under
// trademark law for use of our trademarks.
//
// All the Product's GUI elements, including illustrations and icon sets, as well as technical writing
// content are licensed under the terms of the Creative Commons Attribution-ShareAlike 4.0
// International. See the License terms at http://creativecommons.org/licenses/by-sa/4.0/legalcode
namespace ASC.Files.Core.VirtualRooms;
public class Logo
{
public string Original { get; set; }
public string Big { get; set; }
public string Small { get; set; }
}

View File

@ -0,0 +1,315 @@
// (c) Copyright Ascensio System SIA 2010-2022
//
// This program is a free software product.
// You can redistribute it and/or modify it under the terms
// of the GNU Affero General Public License (AGPL) version 3 as published by the Free Software
// Foundation. In accordance with Section 7(a) of the GNU AGPL 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 details, see
// the GNU AGPL at: http://www.gnu.org/licenses/agpl-3.0.html
//
// You can contact Ascensio System SIA at Lubanas st. 125a-25, Riga, Latvia, EU, LV-1021.
//
// The interactive user interfaces in modified source and object code versions of the Program must
// display Appropriate Legal Notices, as required under Section 5 of the GNU AGPL version 3.
//
// Pursuant to Section 7(b) of the License you must retain the original Product logo when
// distributing the program. Pursuant to Section 7(e) we decline to grant you any rights under
// trademark law for use of our trademarks.
//
// All the Product's GUI elements, including illustrations and icon sets, as well as technical writing
// content are licensed under the terms of the Creative Commons Attribution-ShareAlike 4.0
// International. See the License terms at http://creativecommons.org/licenses/by-sa/4.0/legalcode
using Image = SixLabors.ImageSharp.Image;
namespace ASC.Files.Core.VirtualRooms;
[Scope]
public class RoomLogoManager
{
private const string LogosPath = "{0}_size_{1}-{2}.{3}";
private const string ModuleName = "room_logos";
private const string TempDomainPath = "logos_temp";
private static Size _originalLogoSize = new Size(1280, 1280);
private static Size _bigLogoSize = new Size(32, 32);
private static Size _smallLogoSize = new Size(16, 16);
private readonly IDaoFactory _daoFactory;
private readonly FileSecurity _fileSecurity;
private readonly ILogger<RoomLogoManager> _logger;
private readonly StorageFactory _storageFactory;
private readonly TenantManager _tenantManager;
private IDataStore _dataStore;
private readonly ICache _cache;
private readonly FilesMessageService _filesMessageService;
private static readonly Regex _pattern = new Regex(@"\d+-\d+", RegexOptions.Compiled);
private static readonly Regex _cachePattern = new Regex(@"\d+\/\S+\/\d+\/\d+", RegexOptions.Compiled);
private static readonly TimeSpan _cacheLifeTime = TimeSpan.FromMinutes(30);
private readonly IHttpContextAccessor _httpContextAccessor;
public RoomLogoManager(StorageFactory storageFactory, TenantManager tenantManager, IDaoFactory daoFactory, FileSecurity fileSecurity, ILogger<RoomLogoManager> logger, AscCache cache, FilesMessageService filesMessageService, IHttpContextAccessor httpContextAccessor)
{
_storageFactory = storageFactory;
_tenantManager = tenantManager;
_daoFactory = daoFactory;
_fileSecurity = fileSecurity;
_logger = logger;
_cache = cache;
_filesMessageService = filesMessageService;
_httpContextAccessor = httpContextAccessor;
}
public bool EnableAudit { get; set; } = true;
private IDataStore DataStore => _dataStore ??= _storageFactory.GetStorage(TenantId.ToString(), ModuleName);
private int TenantId => _tenantManager.GetCurrentTenant().Id;
private IDictionary<string, StringValues> Headers => _httpContextAccessor?.HttpContext?.Request?.Headers;
public async Task<Folder<T>> CreateAsync<T>(T id, string tempFile, int x, int y, int width, int height)
{
var folderDao = _daoFactory.GetFolderDao<T>();
var room = await folderDao.GetFolderAsync(id);
if (string.IsNullOrEmpty(tempFile))
{
return room;
}
if (room == null || !DocSpaceHelper.IsRoom(room.FolderType))
{
throw new ItemNotFoundException("Virtual room not found");
}
if (room.RootFolderType == FolderType.Archive || !await _fileSecurity.CanEditRoomAsync(room))
{
throw new InvalidOperationException("You don't have permission to edit the room");
}
var fileName = Path.GetFileName(tempFile);
var data = await GetTempAsync(fileName);
await SaveWithProcessAsync(id, data, -1, new Point(x, y), new Size(width, height));
if (EnableAudit)
{
_filesMessageService.Send(room, Headers, MessageAction.RoomLogoCreated);
}
return room;
}
public async Task<Folder<T>> DeleteAsync<T>(T id)
{
var folderDao = _daoFactory.GetFolderDao<T>();
var room = await folderDao.GetFolderAsync(id);
if (!await _fileSecurity.CanEditRoomAsync(room))
{
throw new InvalidOperationException("You don't have permission to edit the room");
}
try
{
await DataStore.DeleteFilesAsync(string.Empty, $"{ProcessFolderId(id)}*.*", false);
if (EnableAudit)
{
_filesMessageService.Send(room, Headers, MessageAction.RoomLogoDeleted);
}
_cache.Remove(_cachePattern);
_cache.Remove(GetKey(id));
}
catch (DirectoryNotFoundException e)
{
_logger.ErrorRemoveRoomLogo(e);
}
return room;
}
public async Task<Logo> GetLogo<T>(T id)
{
return new Logo
{
Original = await GetOriginalLogoPath(id),
Big = await GetBigLogoPath(id),
Small = await GetSmallLogoPath(id),
};
}
public async Task<byte[]> GetTempAsync(string fileName)
{
using var stream = await DataStore.GetReadStreamAsync(TempDomainPath, fileName);
var data = new MemoryStream();
var buffer = new byte[1024 * 10];
while (true)
{
var count = await stream.ReadAsync(buffer, 0, buffer.Length);
if (count == 0)
{
break;
}
data.Write(buffer, 0, count);
}
return data.ToArray();
}
public async Task<string> SaveTempAsync(byte[] data, long maxFileSize)
{
data = UserPhotoThumbnailManager.TryParseImage(data, maxFileSize, _originalLogoSize, out var imgFormat, out _, out _);
var fileName = Guid.NewGuid() + "." + CommonPhotoManager.GetImgFormatName(imgFormat);
using var stream = new MemoryStream(data);
var path = await DataStore.SaveAsync(TempDomainPath, fileName, stream);
return path.ToString();
}
public async Task<string> SaveWithProcessAsync<T>(T id, byte[] imageData, long maxFileSize, Point position, Size cropSize)
{
imageData = UserPhotoThumbnailManager.TryParseImage(imageData, maxFileSize, _originalLogoSize, out var imageFormat, out var width, out var height);
var imageExtension = CommonPhotoManager.GetImgFormatName(imageFormat);
var fileName = $"{ProcessFolderId(id)}_orig_{width}-{height}.{imageExtension}";
if (imageData == null || imageData.Length == 0)
{
return string.Empty;
}
using var stream = new MemoryStream(imageData);
var path = await DataStore.SaveAsync(fileName, stream);
await ResizeAndSaveAsync(id, imageData, maxFileSize, _bigLogoSize, position, cropSize);
await ResizeAndSaveAsync(id, imageData, maxFileSize, _smallLogoSize, position, cropSize);
return path.ToString();
}
private async Task ResizeAndSaveAsync<T>(T id, byte[] data, long maxFileSize, Size size, Point position, Size cropSize)
{
if (data == null || data.Length <= 0)
{
throw new Web.Core.Users.UnknownImageFormatException();
}
if (maxFileSize != -1 && data.Length > maxFileSize)
{
throw new ImageWeightLimitException();
}
try
{
using var stream = new MemoryStream(data);
using var img = Image.Load(stream, out var format);
var imgFormat = format;
if (size != img.Size())
{
using var img2 = UserPhotoThumbnailManager.GetImage(img, size, new UserPhotoThumbnailSettings(position, cropSize));
data = CommonPhotoManager.SaveToBytes(img2);
}
else
{
data = CommonPhotoManager.SaveToBytes(img);
}
var extension = CommonPhotoManager.GetImgFormatName(imgFormat);
var fileName = string.Format(LogosPath, ProcessFolderId(id), size.Width, size.Height, extension);
using var stream2 = new MemoryStream(data);
await DataStore.SaveAsync(fileName, stream2);
}
catch (ArgumentException error)
{
throw new Web.Core.Users.UnknownImageFormatException(error);
}
}
public async ValueTask<string> GetOriginalLogoPath<T>(T id)
{
var path = _cache.Get<string>(GetKey(id));
if (!string.IsNullOrEmpty(path))
{
return await ValueTask.FromResult(path);
}
await LoadPathToCache(id);
path = _cache.Get<string>(GetKey(id));
return path ?? string.Empty;
}
public async ValueTask<string> GetBigLogoPath<T>(T id)
{
return await GetLogoPath(id, _bigLogoSize);
}
public async ValueTask<string> GetSmallLogoPath<T>(T id)
{
return await GetLogoPath(id, _smallLogoSize);
}
public async ValueTask<string> GetLogoPath<T>(T id, Size size)
{
var key = GetKey(id, size);
var path = _cache.Get<string>(key);
if (!string.IsNullOrEmpty(path))
{
return await ValueTask.FromResult(path);
}
await LoadPathToCache(id);
path = _cache.Get<string>(key);
return path ?? string.Empty;
}
public async Task LoadPathToCache<T>(T id)
{
var logoPath = await DataStore.ListFilesAsync(string.Empty, $"{ProcessFolderId(id)}*", false)
.Select(u => u.ToString()).ToListAsync();
var original = logoPath.Where(u => u.Contains("orig")).FirstOrDefault();
_cache.Insert(GetKey(id), original, _cacheLifeTime);
logoPath.Remove(original);
foreach (var (k, v) in logoPath.ToDictionary(p => _pattern.Match(p).Value.Split('-')))
{
_cache.Insert(GetKey(id, new Size(int.Parse(k[0]), int.Parse(k[1]))), v, _cacheLifeTime);
}
}
private string ProcessFolderId<T>(T id)
{
ArgumentNullException.ThrowIfNull(id, nameof(id));
return id.GetType() != typeof(string)
? id.ToString()
: id.ToString()?.Replace("-", "").Replace("|", "");
}
private string GetKey<T>(T id, Size size)
{
return $"{TenantId}/{id}/{size.Width}/{size.Height}";
}
private string GetKey<T>(T id)
{
return $"{TenantId}/{id}/orig";
}
}

View File

@ -0,0 +1,34 @@
// (c) Copyright Ascensio System SIA 2010-2022
//
// This program is a free software product.
// You can redistribute it and/or modify it under the terms
// of the GNU Affero General Public License (AGPL) version 3 as published by the Free Software
// Foundation. In accordance with Section 7(a) of the GNU AGPL 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 details, see
// the GNU AGPL at: http://www.gnu.org/licenses/agpl-3.0.html
//
// You can contact Ascensio System SIA at Lubanas st. 125a-25, Riga, Latvia, EU, LV-1021.
//
// The interactive user interfaces in modified source and object code versions of the Program must
// display Appropriate Legal Notices, as required under Section 5 of the GNU AGPL version 3.
//
// Pursuant to Section 7(b) of the License you must retain the original Product logo when
// distributing the program. Pursuant to Section 7(e) we decline to grant you any rights under
// trademark law for use of our trademarks.
//
// All the Product's GUI elements, including illustrations and icon sets, as well as technical writing
// content are licensed under the terms of the Creative Commons Attribution-ShareAlike 4.0
// International. See the License terms at http://creativecommons.org/licenses/by-sa/4.0/legalcode
namespace ASC.Files.Core.VirtualRooms;
public enum SearchArea
{
Active,
Archive,
Any
}

View File

@ -41,7 +41,7 @@ global using System.Text;
global using System.Text.Json;
global using System.Text.Json.Serialization;
global using System.Text.RegularExpressions;
global using System.Web;
global using System.Web;
global using System.Xml;
global using AppLimit.CloudComputing.SharpBox;
@ -83,6 +83,7 @@ global using ASC.FederatedLogin.Helpers;
global using ASC.FederatedLogin.LoginProviders;
global using ASC.FederatedLogin.Profile;
global using ASC.Files.Core;
global using ASC.Files.Core.VirtualRooms;
global using ASC.Files.Core.ApiModels.RequestDto;
global using ASC.Files.Core.ApiModels.ResponseDto;
global using ASC.Files.Core.Core.Entries;
@ -90,7 +91,9 @@ global using ASC.Files.Core.Data;
global using ASC.Files.Core.EF;
global using ASC.Files.Core.IntegrationEvents.Events;
global using ASC.Files.Core.Log;
global using ASC.Files.Core.Entries;
global using ASC.Files.Core.Mapping;
global using ASC.Files.Core.Helpers;
global using ASC.Files.Core.Resources;
global using ASC.Files.Core.Security;
global using ASC.Files.Core.Services.NotifyService;
@ -197,6 +200,10 @@ global using Newtonsoft.Json.Linq;
global using ProtoBuf;
global using SixLabors.ImageSharp;
global using StackExchange.Redis;
global using static ASC.Files.Core.Data.AbstractDao;
global using static ASC.Web.Core.Files.DocumentService;
global using static ASC.Web.Files.Services.DocumentService.DocumentServiceTracker;
@ -223,3 +230,4 @@ global using JsonTokenType = System.Text.Json.JsonTokenType;
global using JsonConverter = System.Text.Json.Serialization.JsonConverter;
global using JsonConverterAttribute = System.Text.Json.Serialization.JsonConverterAttribute;
global using JsonIgnoreAttribute = System.Text.Json.Serialization.JsonIgnoreAttribute;
global using SocketManager = ASC.Web.Files.Utils.SocketManager;

View File

@ -0,0 +1,59 @@
// (c) Copyright Ascensio System SIA 2010-2022
//
// This program is a free software product.
// You can redistribute it and/or modify it under the terms
// of the GNU Affero General Public License (AGPL) version 3 as published by the Free Software
// Foundation. In accordance with Section 7(a) of the GNU AGPL 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 details, see
// the GNU AGPL at: http://www.gnu.org/licenses/agpl-3.0.html
//
// You can contact Ascensio System SIA at Lubanas st. 125a-25, Riga, Latvia, EU, LV-1021.
//
// The interactive user interfaces in modified source and object code versions of the Program must
// display Appropriate Legal Notices, as required under Section 5 of the GNU AGPL version 3.
//
// Pursuant to Section 7(b) of the License you must retain the original Product logo when
// distributing the program. Pursuant to Section 7(e) we decline to grant you any rights under
// trademark law for use of our trademarks.
//
// All the Product's GUI elements, including illustrations and icon sets, as well as technical writing
// content are licensed under the terms of the Creative Commons Attribution-ShareAlike 4.0
// International. See the License terms at http://creativecommons.org/licenses/by-sa/4.0/legalcode
namespace ASC.Files.Core.Helpers;
public static class DocSpaceHelper
{
private static readonly HashSet<FileShare> _fillingFormRoomConstraints
= new HashSet<FileShare> { FileShare.RoomManager, FileShare.ReadWrite, FileShare.FillForms, FileShare.Read };
private static readonly HashSet<FileShare> _editingRoomConstraints
= new HashSet<FileShare> { FileShare.RoomManager, FileShare.ReadWrite, FileShare.Editing, FileShare.Read };
private static readonly HashSet<FileShare> _reviewRoomConstraints
= new HashSet<FileShare> { FileShare.RoomManager, FileShare.ReadWrite, FileShare.Review, FileShare.Comment, FileShare.Read };
private static readonly HashSet<FileShare> _readOnlyRoomConstraints
= new HashSet<FileShare> { FileShare.RoomManager, FileShare.ReadWrite, FileShare.Read };
public static bool IsRoom(FolderType folderType)
{
return folderType == FolderType.CustomRoom || folderType == FolderType.EditingRoom
|| folderType == FolderType.ReviewRoom || folderType == FolderType.ReadOnlyRoom
|| folderType == FolderType.FillingFormsRoom;
}
public static bool ValidateShare(FolderType folderType, FileShare fileShare)
{
return folderType switch
{
FolderType.CustomRoom => true,
FolderType.FillingFormsRoom => _fillingFormRoomConstraints.Contains(fileShare),
FolderType.EditingRoom => _editingRoomConstraints.Contains(fileShare),
FolderType.ReviewRoom => _reviewRoomConstraints.Contains(fileShare),
FolderType.ReadOnlyRoom => _readOnlyRoomConstraints.Contains(fileShare),
_ => false
};
}
}

View File

@ -54,6 +54,11 @@ public class FilesMessageService
_httpContextAccessor = httpContextAccessor;
}
public void Send(IDictionary<string, StringValues> headers, MessageAction action, params string[] description)
{
SendHeadersMessage(headers, action, null, description);
}
public void Send<T>(FileEntry<T> entry, IDictionary<string, StringValues> headers, MessageAction action, params string[] description)
{
if (entry == null)

View File

@ -330,7 +330,7 @@ public class GlobalFolder
if (!ProjectsRootFolderCache.TryGetValue(_tenantManager.GetCurrentTenant().Id, out var result))
{
result = await folderDao.GetFolderIDProjectsAsync(true);
ProjectsRootFolderCache[_tenantManager.GetCurrentTenant().Id] = result;
}
@ -342,6 +342,57 @@ public class GlobalFolder
return (T)Convert.ChangeType(await GetFolderProjectsAsync(daoFactory), typeof(T));
}
internal static readonly ConcurrentDictionary<string, int> DocSpaceFolderCache =
new ConcurrentDictionary<string, int>();
public async ValueTask<int> GetFolderVirtualRoomsAsync(IDaoFactory daoFactory)
{
if (_coreBaseSettings.DisableDocSpace)
{
return default;
}
var key = $"vrooms/{_tenantManager.GetCurrentTenant().Id}";
if (!DocSpaceFolderCache.TryGetValue(key, out var result))
{
result = await daoFactory.GetFolderDao<int>().GetFolderIDVirtualRooms(true);
DocSpaceFolderCache[key] = result;
}
return result;
}
public async ValueTask<T> GetFolderVirtualRoomsAsync<T>(IDaoFactory daoFactory)
{
return (T)Convert.ChangeType(await GetFolderVirtualRoomsAsync(daoFactory), typeof(T));
}
public async ValueTask<int> GetFolderArchiveAsync(IDaoFactory daoFactory)
{
if (_coreBaseSettings.DisableDocSpace)
{
return default;
}
var key = $"archive/{_tenantManager.GetCurrentTenant().Id}";
if (!DocSpaceFolderCache.TryGetValue(key, out var result))
{
result = await daoFactory.GetFolderDao<int>().GetFolderIDArchive(true);
DocSpaceFolderCache[key] = result;
}
return result;
}
public async ValueTask<T> GetFolderArchive<T>(IDaoFactory daoFactory)
{
return (T)Convert.ChangeType(await GetFolderArchiveAsync(daoFactory), typeof(T));
}
internal static readonly ConcurrentDictionary<string, Lazy<int>> UserRootFolderCache =
new ConcurrentDictionary<string, Lazy<int>>(); /*Use SYNCHRONIZED for cross thread blocks*/
@ -368,7 +419,7 @@ public class GlobalFolder
return myFolderId.Value;
}
protected internal void SetFolderMy(object value)
{
var cacheKey = string.Format("my/{0}/{1}", _tenantManager.GetCurrentTenant().Id, value);
@ -407,7 +458,7 @@ public class GlobalFolder
{
return default;
}
if (!CommonFolderCache.TryGetValue(_tenantManager.GetCurrentTenant().Id, out var commonFolderId))
{
commonFolderId = await GetFolderIdAndProccessFirstVisitAsync(fileMarker, daoFactory, false);
@ -603,7 +654,7 @@ public class GlobalFolder
return trashFolderId;
}
protected internal void SetFolderTrash(object value)
{
var cacheKey = string.Format("trash/{0}/{1}", _tenantManager.GetCurrentTenant().Id, value);
@ -739,6 +790,8 @@ public class GlobalFolderHelper
public ValueTask<int> FolderRecentAsync => _globalFolder.GetFolderRecentAsync(_daoFactory);
public ValueTask<int> FolderFavoritesAsync => _globalFolder.GetFolderFavoritesAsync(_daoFactory);
public ValueTask<int> FolderTemplatesAsync => _globalFolder.GetFolderTemplatesAsync(_daoFactory);
public ValueTask<int> FolderVirtualRoomsAsync => _globalFolder.GetFolderVirtualRoomsAsync(_daoFactory);
public ValueTask<int> FolderArchiveAsync => _globalFolder.GetFolderArchiveAsync(_daoFactory);
public T GetFolderMy<T>()
{
@ -765,6 +818,16 @@ public class GlobalFolderHelper
return (T)Convert.ChangeType(await FolderPrivacyAsync, typeof(T));
}
public async ValueTask<T> GetFolderVirtualRooms<T>()
{
return (T)Convert.ChangeType(await FolderVirtualRoomsAsync, typeof(T));
}
public async ValueTask<T> GetFolderArchive<T>()
{
return (T)Convert.ChangeType(await FolderArchiveAsync, typeof(T));
}
public void SetFolderMy<T>(T val)
{
_globalFolder.SetFolderMy(val);

View File

@ -655,12 +655,14 @@ public class FileHandlerService
header = header.Substring("Bearer ".Length);
#pragma warning disable CS0618 // Type or member is obsolete
var stringPayload = JwtBuilder.Create()
.WithAlgorithm(new HMACSHA256Algorithm())
.WithSerializer(new JwtSerializer())
.WithSecret(_fileUtility.SignatureSecret)
.MustVerifySignature()
.Decode(header);
#pragma warning restore CS0618 // Type or member is obsolete
_logger.DebugDocServiceStreamFilePayload(stringPayload);
//var data = JObject.Parse(stringPayload);
@ -767,12 +769,14 @@ public class FileHandlerService
header = header.Substring("Bearer ".Length);
#pragma warning disable CS0618 // Type or member is obsolete
var stringPayload = JwtBuilder.Create()
.WithAlgorithm(new HMACSHA256Algorithm())
.WithSerializer(new JwtSerializer())
.WithSecret(_fileUtility.SignatureSecret)
.MustVerifySignature()
.Decode(header);
#pragma warning restore CS0618 // Type or member is obsolete
_logger.DebugDocServiceStreamFilePayload(stringPayload);
//var data = JObject.Parse(stringPayload);
@ -1428,12 +1432,14 @@ public class FileHandlerService
{
try
{
#pragma warning disable CS0618 // Type or member is obsolete
var dataString = JwtBuilder.Create()
.WithAlgorithm(new HMACSHA256Algorithm())
.WithSerializer(new JwtSerializer())
.WithSecret(_fileUtility.SignatureSecret)
.MustVerifySignature()
.Decode(fileData.Token);
#pragma warning restore CS0618 // Type or member is obsolete
var data = JObject.Parse(dataString);
if (data == null)
@ -1461,12 +1467,14 @@ public class FileHandlerService
try
{
#pragma warning disable CS0618 // Type or member is obsolete
var stringPayload = JwtBuilder.Create()
.WithAlgorithm(new HMACSHA256Algorithm())
.WithSerializer(new JwtSerializer())
.WithSecret(_fileUtility.SignatureSecret)
.MustVerifySignature()
.Decode(header);
#pragma warning restore CS0618 // Type or member is obsolete
_logger.DebugDocServiceTrackPayload(stringPayload);
var jsonPayload = JObject.Parse(stringPayload);

View File

@ -0,0 +1,33 @@
// (c) Copyright Ascensio System SIA 2010-2022
//
// This program is a free software product.
// You can redistribute it and/or modify it under the terms
// of the GNU Affero General Public License (AGPL) version 3 as published by the Free Software
// Foundation. In accordance with Section 7(a) of the GNU AGPL 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 details, see
// the GNU AGPL at: http://www.gnu.org/licenses/agpl-3.0.html
//
// You can contact Ascensio System SIA at Lubanas st. 125a-25, Riga, Latvia, EU, LV-1021.
//
// The interactive user interfaces in modified source and object code versions of the Program must
// display Appropriate Legal Notices, as required under Section 5 of the GNU AGPL version 3.
//
// Pursuant to Section 7(b) of the License you must retain the original Product logo when
// distributing the program. Pursuant to Section 7(e) we decline to grant you any rights under
// trademark law for use of our trademarks.
//
// All the Product's GUI elements, including illustrations and icon sets, as well as technical writing
// content are licensed under the terms of the Creative Commons Attribution-ShareAlike 4.0
// International. See the License terms at http://creativecommons.org/licenses/by-sa/4.0/legalcode
namespace ASC.Files.Core.Log;
public static partial class RoomLogoManagerLogger
{
[LoggerMessage(Level = LogLevel.Error, Message = "RemoveRoomLogo")]
public static partial void ErrorRemoveRoomLogo(this ILogger<RoomLogoManager> logger, Exception exception);
}

View File

@ -0,0 +1,827 @@
// <auto-generated />
using System;
using ASC.Files.Core.EF;
using Microsoft.EntityFrameworkCore;
using Microsoft.EntityFrameworkCore.Infrastructure;
using Microsoft.EntityFrameworkCore.Migrations;
using Microsoft.EntityFrameworkCore.Storage.ValueConversion;
#nullable disable
namespace ASC.Files.Core.Migrations.MySql.FilesDbContextMySql
{
[DbContext(typeof(MySqlFilesDbContext))]
[Migration("20220526143057_FilesDbContextMySql_Upgrade2")]
partial class FilesDbContextMySql_Upgrade2
{
protected override void BuildTargetModel(ModelBuilder modelBuilder)
{
#pragma warning disable 612, 618
modelBuilder
.HasAnnotation("ProductVersion", "6.0.4")
.HasAnnotation("Relational:MaxIdentifierLength", 64);
modelBuilder.Entity("ASC.Core.Common.EF.DbQuota", b =>
{
b.Property<int>("Tenant")
.ValueGeneratedOnAdd()
.HasColumnType("int")
.HasColumnName("tenant");
b.Property<int>("ActiveUsers")
.HasColumnType("int")
.HasColumnName("active_users");
b.Property<string>("AvangateId")
.HasColumnType("varchar(128)")
.HasColumnName("avangate_id")
.UseCollation("utf8_general_ci")
.HasAnnotation("MySql:CharSet", "utf8");
b.Property<string>("Description")
.HasColumnType("varchar(128)")
.HasColumnName("description")
.UseCollation("utf8_general_ci")
.HasAnnotation("MySql:CharSet", "utf8");
b.Property<string>("Features")
.HasColumnType("text")
.HasColumnName("features")
.UseCollation("utf8_general_ci")
.HasAnnotation("MySql:CharSet", "utf8");
b.Property<long>("MaxFileSize")
.HasColumnType("bigint")
.HasColumnName("max_file_size");
b.Property<long>("MaxTotalSize")
.HasColumnType("bigint")
.HasColumnName("max_total_size");
b.Property<string>("Name")
.HasColumnType("varchar(128)")
.HasColumnName("name")
.UseCollation("utf8_general_ci")
.HasAnnotation("MySql:CharSet", "utf8");
b.Property<decimal>("Price")
.HasColumnType("decimal(10,2)")
.HasColumnName("price");
b.Property<bool>("Visible")
.HasColumnType("tinyint(1)")
.HasColumnName("visible");
b.HasKey("Tenant")
.HasName("PRIMARY");
b.ToTable("tenants_quota", (string)null);
b.HasData(
new
{
Tenant = -1,
ActiveUsers = 10000,
AvangateId = "0",
Features = "domain,audit,controlpanel,healthcheck,ldap,sso,whitelabel,branding,ssbranding,update,support,portals:10000,discencryption,privacyroom,restore",
MaxFileSize = 102400L,
MaxTotalSize = 10995116277760L,
Name = "default",
Price = 0.00m,
Visible = false
});
});
modelBuilder.Entity("ASC.Core.Common.EF.DbTariff", b =>
{
b.Property<int>("Id")
.ValueGeneratedOnAdd()
.HasColumnType("int")
.HasColumnName("id");
b.Property<string>("Comment")
.HasColumnType("varchar(255)")
.HasColumnName("comment")
.UseCollation("utf8_general_ci")
.HasAnnotation("MySql:CharSet", "utf8");
b.Property<DateTime>("CreateOn")
.ValueGeneratedOnAddOrUpdate()
.HasColumnType("timestamp")
.HasColumnName("create_on")
.HasDefaultValueSql("CURRENT_TIMESTAMP");
b.Property<int>("Quantity")
.HasColumnType("int")
.HasColumnName("quantity");
b.Property<DateTime>("Stamp")
.HasColumnType("datetime")
.HasColumnName("stamp");
b.Property<int>("Tariff")
.HasColumnType("int")
.HasColumnName("tariff");
b.Property<int>("Tenant")
.HasColumnType("int")
.HasColumnName("tenant");
b.HasKey("Id");
b.HasIndex("Tenant")
.HasDatabaseName("tenant");
b.ToTable("tenants_tariff", (string)null);
});
modelBuilder.Entity("ASC.Core.Common.EF.Model.DbTenant", b =>
{
b.Property<int>("Id")
.ValueGeneratedOnAdd()
.HasColumnType("int")
.HasColumnName("id");
b.Property<string>("Alias")
.IsRequired()
.HasColumnType("varchar(100)")
.HasColumnName("alias")
.UseCollation("utf8_general_ci")
.HasAnnotation("MySql:CharSet", "utf8");
b.Property<bool>("Calls")
.ValueGeneratedOnAdd()
.HasColumnType("tinyint(1)")
.HasColumnName("calls")
.HasDefaultValueSql("true");
b.Property<DateTime>("CreationDateTime")
.HasColumnType("datetime")
.HasColumnName("creationdatetime");
b.Property<int?>("Industry")
.HasColumnType("int")
.HasColumnName("industry");
b.Property<string>("Language")
.IsRequired()
.ValueGeneratedOnAdd()
.HasColumnType("char(10)")
.HasColumnName("language")
.HasDefaultValueSql("'en-US'")
.UseCollation("utf8_general_ci")
.HasAnnotation("MySql:CharSet", "utf8");
b.Property<DateTime>("LastModified")
.ValueGeneratedOnAdd()
.HasColumnType("timestamp")
.HasColumnName("last_modified")
.HasDefaultValueSql("CURRENT_TIMESTAMP");
b.Property<string>("MappedDomain")
.HasColumnType("varchar(100)")
.HasColumnName("mappeddomain")
.UseCollation("utf8_general_ci")
.HasAnnotation("MySql:CharSet", "utf8");
b.Property<string>("Name")
.IsRequired()
.HasColumnType("varchar(255)")
.HasColumnName("name")
.UseCollation("utf8_general_ci")
.HasAnnotation("MySql:CharSet", "utf8");
b.Property<string>("OwnerId")
.IsRequired()
.HasColumnType("varchar(38)")
.HasColumnName("owner_id")
.UseCollation("utf8_general_ci")
.HasAnnotation("MySql:CharSet", "utf8");
b.Property<string>("PaymentId")
.HasColumnType("varchar(38)")
.HasColumnName("payment_id")
.UseCollation("utf8_general_ci")
.HasAnnotation("MySql:CharSet", "utf8");
b.Property<bool>("Spam")
.ValueGeneratedOnAdd()
.HasColumnType("tinyint(1)")
.HasColumnName("spam")
.HasDefaultValueSql("true");
b.Property<int>("Status")
.HasColumnType("int")
.HasColumnName("status");
b.Property<DateTime?>("StatusChanged")
.HasColumnType("datetime")
.HasColumnName("statuschanged");
b.Property<string>("TimeZone")
.HasColumnType("varchar(50)")
.HasColumnName("timezone")
.UseCollation("utf8_general_ci")
.HasAnnotation("MySql:CharSet", "utf8");
b.Property<int>("TrustedDomainsEnabled")
.ValueGeneratedOnAdd()
.HasColumnType("int")
.HasColumnName("trusteddomainsenabled")
.HasDefaultValueSql("'1'");
b.Property<string>("TrustedDomainsRaw")
.HasColumnType("varchar(1024)")
.HasColumnName("trusteddomains")
.UseCollation("utf8_general_ci")
.HasAnnotation("MySql:CharSet", "utf8");
b.Property<int>("Version")
.ValueGeneratedOnAdd()
.HasColumnType("int")
.HasColumnName("version")
.HasDefaultValueSql("'2'");
b.Property<DateTime?>("Version_Changed")
.HasColumnType("datetime")
.HasColumnName("version_changed");
b.HasKey("Id");
b.HasIndex("LastModified")
.HasDatabaseName("last_modified");
b.HasIndex("MappedDomain")
.HasDatabaseName("mappeddomain");
b.HasIndex("Version")
.HasDatabaseName("version");
b.ToTable("tenants_tenants", (string)null);
b.HasData(
new
{
Id = 1,
Alias = "localhost",
Calls = false,
CreationDateTime = new DateTime(2021, 3, 9, 17, 46, 59, 97, DateTimeKind.Utc).AddTicks(4317),
LastModified = new DateTime(1, 1, 1, 0, 0, 0, 0, DateTimeKind.Unspecified),
Name = "Web Office",
OwnerId = "66faa6e4-f133-11ea-b126-00ffeec8b4ef",
Spam = false,
Status = 0,
TrustedDomainsEnabled = 0,
Version = 0
});
});
modelBuilder.Entity("ASC.Files.Core.EF.DbFile", b =>
{
b.Property<int>("TenantId")
.HasColumnType("int")
.HasColumnName("tenant_id");
b.Property<int>("Id")
.HasColumnType("int")
.HasColumnName("id");
b.Property<int>("Version")
.HasColumnType("int")
.HasColumnName("version");
b.Property<int>("Category")
.HasColumnType("int")
.HasColumnName("category");
b.Property<string>("Changes")
.HasColumnType("mediumtext")
.HasColumnName("changes")
.UseCollation("utf8_general_ci")
.HasAnnotation("MySql:CharSet", "utf8");
b.Property<string>("Comment")
.HasColumnType("varchar(255)")
.HasColumnName("comment")
.UseCollation("utf8_general_ci")
.HasAnnotation("MySql:CharSet", "utf8");
b.Property<long>("ContentLength")
.HasColumnType("bigint")
.HasColumnName("content_length");
b.Property<string>("ConvertedType")
.HasColumnType("varchar(10)")
.HasColumnName("converted_type")
.UseCollation("utf8_general_ci")
.HasAnnotation("MySql:CharSet", "utf8");
b.Property<string>("CreateBy")
.IsRequired()
.HasColumnType("char(38)")
.HasColumnName("create_by")
.UseCollation("utf8_general_ci")
.HasAnnotation("MySql:CharSet", "utf8");
b.Property<DateTime>("CreateOn")
.HasColumnType("datetime")
.HasColumnName("create_on");
b.Property<bool>("CurrentVersion")
.HasColumnType("tinyint(1)")
.HasColumnName("current_version");
b.Property<bool>("Encrypted")
.HasColumnType("tinyint(1)")
.HasColumnName("encrypted");
b.Property<int>("FileStatus")
.HasColumnType("int")
.HasColumnName("file_status");
b.Property<int>("Forcesave")
.HasColumnType("int")
.HasColumnName("forcesave");
b.Property<string>("ModifiedBy")
.IsRequired()
.HasColumnType("char(38)")
.HasColumnName("modified_by")
.UseCollation("utf8_general_ci")
.HasAnnotation("MySql:CharSet", "utf8");
b.Property<DateTime>("ModifiedOn")
.HasColumnType("datetime")
.HasColumnName("modified_on");
b.Property<int>("ParentId")
.HasColumnType("int")
.HasColumnName("folder_id");
b.Property<int>("ThumbnailStatus")
.HasColumnType("int")
.HasColumnName("thumb");
b.Property<string>("Title")
.IsRequired()
.HasColumnType("varchar(400)")
.HasColumnName("title")
.UseCollation("utf8_general_ci")
.HasAnnotation("MySql:CharSet", "utf8");
b.Property<int>("VersionGroup")
.ValueGeneratedOnAdd()
.HasColumnType("int")
.HasColumnName("version_group")
.HasDefaultValueSql("'1'");
b.HasKey("TenantId", "Id", "Version")
.HasName("PRIMARY");
b.HasIndex("Id")
.HasDatabaseName("id");
b.HasIndex("ModifiedOn")
.HasDatabaseName("modified_on");
b.HasIndex("ParentId")
.HasDatabaseName("folder_id");
b.ToTable("files_file", (string)null);
});
modelBuilder.Entity("ASC.Files.Core.EF.DbFilesBunchObjects", b =>
{
b.Property<int>("TenantId")
.HasColumnType("int")
.HasColumnName("tenant_id");
b.Property<string>("RightNode")
.HasColumnType("varchar(255)")
.HasColumnName("right_node")
.UseCollation("utf8_general_ci")
.HasAnnotation("MySql:CharSet", "utf8");
b.Property<string>("LeftNode")
.IsRequired()
.HasColumnType("varchar(255)")
.HasColumnName("left_node")
.UseCollation("utf8_general_ci")
.HasAnnotation("MySql:CharSet", "utf8");
b.HasKey("TenantId", "RightNode")
.HasName("PRIMARY");
b.HasIndex("LeftNode")
.HasDatabaseName("left_node");
b.ToTable("files_bunch_objects", (string)null);
});
modelBuilder.Entity("ASC.Files.Core.EF.DbFilesLink", b =>
{
b.Property<int>("TenantId")
.HasColumnType("int")
.HasColumnName("tenant_id");
b.Property<string>("SourceId")
.HasColumnType("varchar(32)")
.HasColumnName("source_id")
.UseCollation("utf8_general_ci")
.HasAnnotation("MySql:CharSet", "utf8");
b.Property<string>("LinkedId")
.HasColumnType("varchar(32)")
.HasColumnName("linked_id")
.UseCollation("utf8_general_ci")
.HasAnnotation("MySql:CharSet", "utf8");
b.Property<string>("LinkedFor")
.IsRequired()
.HasColumnType("char(38)")
.HasColumnName("linked_for")
.UseCollation("utf8_general_ci")
.HasAnnotation("MySql:CharSet", "utf8");
b.HasKey("TenantId", "SourceId", "LinkedId")
.HasName("PRIMARY");
b.HasIndex("TenantId", "SourceId", "LinkedId", "LinkedFor")
.HasDatabaseName("linked_for");
b.ToTable("files_link", (string)null);
});
modelBuilder.Entity("ASC.Files.Core.EF.DbFilesSecurity", b =>
{
b.Property<int>("TenantId")
.HasColumnType("int")
.HasColumnName("tenant_id");
b.Property<string>("EntryId")
.HasColumnType("varchar(50)")
.HasColumnName("entry_id")
.UseCollation("utf8_general_ci")
.HasAnnotation("MySql:CharSet", "utf8");
b.Property<int>("EntryType")
.HasColumnType("int")
.HasColumnName("entry_type");
b.Property<string>("Subject")
.HasColumnType("char(38)")
.HasColumnName("subject")
.UseCollation("utf8_general_ci")
.HasAnnotation("MySql:CharSet", "utf8");
b.Property<string>("Owner")
.IsRequired()
.HasColumnType("char(38)")
.HasColumnName("owner")
.UseCollation("utf8_general_ci")
.HasAnnotation("MySql:CharSet", "utf8");
b.Property<int>("Share")
.HasColumnType("int")
.HasColumnName("security");
b.Property<DateTime>("TimeStamp")
.ValueGeneratedOnAddOrUpdate()
.HasColumnType("timestamp")
.HasColumnName("timestamp")
.HasDefaultValueSql("CURRENT_TIMESTAMP");
b.HasKey("TenantId", "EntryId", "EntryType", "Subject")
.HasName("PRIMARY");
b.HasIndex("Owner")
.HasDatabaseName("owner");
b.HasIndex("TenantId", "EntryType", "EntryId", "Owner")
.HasDatabaseName("tenant_id");
b.ToTable("files_security", (string)null);
});
modelBuilder.Entity("ASC.Files.Core.EF.DbFilesTag", b =>
{
b.Property<int>("Id")
.ValueGeneratedOnAdd()
.HasColumnType("int")
.HasColumnName("id");
b.Property<string>("Name")
.IsRequired()
.HasColumnType("varchar(255)")
.HasColumnName("name")
.UseCollation("utf8_general_ci")
.HasAnnotation("MySql:CharSet", "utf8");
b.Property<string>("Owner")
.IsRequired()
.HasColumnType("varchar(38)")
.HasColumnName("owner")
.UseCollation("utf8_general_ci")
.HasAnnotation("MySql:CharSet", "utf8");
b.Property<int>("TenantId")
.HasColumnType("int")
.HasColumnName("tenant_id");
b.Property<int>("Type")
.HasColumnType("int")
.HasColumnName("flag");
b.HasKey("Id");
b.HasIndex("TenantId", "Owner", "Name", "Type")
.HasDatabaseName("name");
b.ToTable("files_tag", (string)null);
});
modelBuilder.Entity("ASC.Files.Core.EF.DbFilesTagLink", b =>
{
b.Property<int>("TenantId")
.HasColumnType("int")
.HasColumnName("tenant_id");
b.Property<int>("TagId")
.HasColumnType("int")
.HasColumnName("tag_id");
b.Property<string>("EntryId")
.HasColumnType("varchar(32)")
.HasColumnName("entry_id")
.UseCollation("utf8_general_ci")
.HasAnnotation("MySql:CharSet", "utf8");
b.Property<int>("EntryType")
.HasColumnType("int")
.HasColumnName("entry_type");
b.Property<int>("Count")
.HasColumnType("int")
.HasColumnName("tag_count");
b.Property<string>("CreateBy")
.HasColumnType("char(38)")
.HasColumnName("create_by")
.UseCollation("utf8_general_ci")
.HasAnnotation("MySql:CharSet", "utf8");
b.Property<DateTime?>("CreateOn")
.HasColumnType("datetime")
.HasColumnName("create_on");
b.HasKey("TenantId", "TagId", "EntryId", "EntryType")
.HasName("PRIMARY");
b.HasIndex("CreateOn")
.HasDatabaseName("create_on");
b.HasIndex("TenantId", "EntryId", "EntryType")
.HasDatabaseName("entry_id");
b.ToTable("files_tag_link", (string)null);
});
modelBuilder.Entity("ASC.Files.Core.EF.DbFilesThirdpartyAccount", b =>
{
b.Property<int>("Id")
.ValueGeneratedOnAdd()
.HasColumnType("int")
.HasColumnName("id");
b.Property<DateTime>("CreateOn")
.HasColumnType("datetime")
.HasColumnName("create_on");
b.Property<string>("FolderId")
.HasColumnType("text")
.HasColumnName("folder_id")
.UseCollation("utf8_general_ci")
.HasAnnotation("MySql:CharSet", "utf8");
b.Property<int>("FolderType")
.HasColumnType("folder_type");
b.Property<string>("Password")
.IsRequired()
.HasColumnType("varchar(100)")
.HasColumnName("password")
.UseCollation("utf8_general_ci")
.HasAnnotation("MySql:CharSet", "utf8");
b.Property<string>("Provider")
.IsRequired()
.ValueGeneratedOnAdd()
.HasColumnType("varchar(50)")
.HasColumnName("provider")
.HasDefaultValueSql("'0'")
.UseCollation("utf8_general_ci")
.HasAnnotation("MySql:CharSet", "utf8");
b.Property<int>("RootFolderType")
.HasColumnType("int")
.HasColumnName("root_folder_type");
b.Property<int>("TenantId")
.HasColumnType("int")
.HasColumnName("tenant_id");
b.Property<string>("Title")
.IsRequired()
.HasColumnType("varchar(400)")
.HasColumnName("customer_title")
.UseCollation("utf8_general_ci")
.HasAnnotation("MySql:CharSet", "utf8");
b.Property<string>("Token")
.HasColumnType("text")
.HasColumnName("token")
.UseCollation("utf8_general_ci")
.HasAnnotation("MySql:CharSet", "utf8");
b.Property<string>("Url")
.HasColumnType("text")
.HasColumnName("url")
.UseCollation("utf8_general_ci")
.HasAnnotation("MySql:CharSet", "utf8");
b.Property<string>("UserId")
.IsRequired()
.HasColumnType("varchar(38)")
.HasColumnName("user_id")
.UseCollation("utf8_general_ci")
.HasAnnotation("MySql:CharSet", "utf8");
b.Property<string>("UserName")
.IsRequired()
.HasColumnType("varchar(100)")
.HasColumnName("user_name")
.UseCollation("utf8_general_ci")
.HasAnnotation("MySql:CharSet", "utf8");
b.HasKey("Id");
b.ToTable("files_thirdparty_account", (string)null);
});
modelBuilder.Entity("ASC.Files.Core.EF.DbFilesThirdpartyApp", b =>
{
b.Property<string>("UserId")
.HasColumnType("varchar(38)")
.HasColumnName("user_id")
.UseCollation("utf8_general_ci")
.HasAnnotation("MySql:CharSet", "utf8");
b.Property<string>("App")
.HasColumnType("varchar(50)")
.HasColumnName("app")
.UseCollation("utf8_general_ci")
.HasAnnotation("MySql:CharSet", "utf8");
b.Property<DateTime>("ModifiedOn")
.ValueGeneratedOnAddOrUpdate()
.HasColumnType("timestamp")
.HasColumnName("modified_on")
.HasDefaultValueSql("CURRENT_TIMESTAMP");
b.Property<int>("TenantId")
.HasColumnType("int")
.HasColumnName("tenant_id");
b.Property<string>("Token")
.HasColumnType("text")
.HasColumnName("token")
.UseCollation("utf8_general_ci")
.HasAnnotation("MySql:CharSet", "utf8");
b.HasKey("UserId", "App")
.HasName("PRIMARY");
b.ToTable("files_thirdparty_app", (string)null);
});
modelBuilder.Entity("ASC.Files.Core.EF.DbFilesThirdpartyIdMapping", b =>
{
b.Property<string>("HashId")
.HasColumnType("char(32)")
.HasColumnName("hash_id")
.UseCollation("utf8_general_ci")
.HasAnnotation("MySql:CharSet", "utf8");
b.Property<string>("Id")
.IsRequired()
.HasColumnType("text")
.HasColumnName("id")
.UseCollation("utf8_general_ci")
.HasAnnotation("MySql:CharSet", "utf8");
b.Property<int>("TenantId")
.HasColumnType("int")
.HasColumnName("tenant_id");
b.HasKey("HashId")
.HasName("PRIMARY");
b.HasIndex("TenantId", "HashId")
.HasDatabaseName("index_1");
b.ToTable("files_thirdparty_id_mapping", (string)null);
});
modelBuilder.Entity("ASC.Files.Core.EF.DbFolder", b =>
{
b.Property<int>("Id")
.ValueGeneratedOnAdd()
.HasColumnType("int")
.HasColumnName("id");
b.Property<string>("CreateBy")
.IsRequired()
.HasColumnType("char(38)")
.HasColumnName("create_by")
.UseCollation("utf8_general_ci")
.HasAnnotation("MySql:CharSet", "utf8");
b.Property<DateTime>("CreateOn")
.HasColumnType("datetime")
.HasColumnName("create_on");
b.Property<int>("FilesCount")
.HasColumnType("int")
.HasColumnName("filesCount");
b.Property<int>("FolderType")
.HasColumnType("int")
.HasColumnName("folder_type");
b.Property<int>("FoldersCount")
.HasColumnType("int")
.HasColumnName("foldersCount");
b.Property<string>("ModifiedBy")
.IsRequired()
.HasColumnType("char(38)")
.HasColumnName("modified_by")
.UseCollation("utf8_general_ci")
.HasAnnotation("MySql:CharSet", "utf8");
b.Property<DateTime>("ModifiedOn")
.HasColumnType("datetime")
.HasColumnName("modified_on");
b.Property<int>("ParentId")
.HasColumnType("int")
.HasColumnName("parent_id");
b.Property<int>("TenantId")
.HasColumnType("int")
.HasColumnName("tenant_id");
b.Property<string>("Title")
.IsRequired()
.HasColumnType("varchar(400)")
.HasColumnName("title")
.UseCollation("utf8_general_ci")
.HasAnnotation("MySql:CharSet", "utf8");
b.HasKey("Id");
b.HasIndex("ModifiedOn")
.HasDatabaseName("modified_on");
b.HasIndex("TenantId", "ParentId")
.HasDatabaseName("parent_id");
b.ToTable("files_folder", (string)null);
});
modelBuilder.Entity("ASC.Files.Core.EF.DbFolderTree", b =>
{
b.Property<int>("ParentId")
.HasColumnType("int")
.HasColumnName("parent_id");
b.Property<int>("FolderId")
.HasColumnType("int")
.HasColumnName("folder_id");
b.Property<int>("Level")
.HasColumnType("int")
.HasColumnName("level");
b.HasKey("ParentId", "FolderId")
.HasName("PRIMARY");
b.HasIndex("FolderId")
.HasDatabaseName("folder_id");
b.ToTable("files_folder_tree", (string)null);
});
#pragma warning restore 612, 618
}
}
}

View File

@ -0,0 +1,190 @@
using System;
using Microsoft.EntityFrameworkCore.Metadata;
using Microsoft.EntityFrameworkCore.Migrations;
#nullable disable
namespace ASC.Files.Core.Migrations.MySql.FilesDbContextMySql
{
public partial class FilesDbContextMySql_Upgrade2 : Migration
{
protected override void Up(MigrationBuilder migrationBuilder)
{
migrationBuilder.RenameColumn(
name: "folder_type",
table: "files_thirdparty_account",
newName: "FolderType");
migrationBuilder.AlterColumn<int>(
name: "FolderType",
table: "files_thirdparty_account",
type: "folder_type",
nullable: false,
oldClrType: typeof(int),
oldType: "int");
migrationBuilder.AddColumn<string>(
name: "folder_id",
table: "files_thirdparty_account",
type: "text",
nullable: true,
collation: "utf8_general_ci")
.Annotation("MySql:CharSet", "utf8");
migrationBuilder.AddColumn<int>(
name: "root_folder_type",
table: "files_thirdparty_account",
type: "int",
nullable: false,
defaultValue: 0);
migrationBuilder.CreateTable(
name: "tenants_quota",
columns: table => new
{
tenant = table.Column<int>(type: "int", nullable: false)
.Annotation("MySql:ValueGenerationStrategy", MySqlValueGenerationStrategy.IdentityColumn),
name = table.Column<string>(type: "varchar(128)", nullable: true, collation: "utf8_general_ci")
.Annotation("MySql:CharSet", "utf8"),
description = table.Column<string>(type: "varchar(128)", nullable: true, collation: "utf8_general_ci")
.Annotation("MySql:CharSet", "utf8"),
max_file_size = table.Column<long>(type: "bigint", nullable: false),
max_total_size = table.Column<long>(type: "bigint", nullable: false),
active_users = table.Column<int>(type: "int", nullable: false),
features = table.Column<string>(type: "text", nullable: true, collation: "utf8_general_ci")
.Annotation("MySql:CharSet", "utf8"),
price = table.Column<decimal>(type: "decimal(10,2)", nullable: false),
avangate_id = table.Column<string>(type: "varchar(128)", nullable: true, collation: "utf8_general_ci")
.Annotation("MySql:CharSet", "utf8"),
visible = table.Column<bool>(type: "tinyint(1)", nullable: false)
},
constraints: table =>
{
table.PrimaryKey("PRIMARY", x => x.tenant);
})
.Annotation("MySql:CharSet", "utf8mb4");
migrationBuilder.CreateTable(
name: "tenants_tariff",
columns: table => new
{
id = table.Column<int>(type: "int", nullable: false)
.Annotation("MySql:ValueGenerationStrategy", MySqlValueGenerationStrategy.IdentityColumn),
tenant = table.Column<int>(type: "int", nullable: false),
tariff = table.Column<int>(type: "int", nullable: false),
stamp = table.Column<DateTime>(type: "datetime", nullable: false),
quantity = table.Column<int>(type: "int", nullable: false),
comment = table.Column<string>(type: "varchar(255)", nullable: true, collation: "utf8_general_ci")
.Annotation("MySql:CharSet", "utf8"),
create_on = table.Column<DateTime>(type: "timestamp", nullable: false, defaultValueSql: "CURRENT_TIMESTAMP")
},
constraints: table =>
{
table.PrimaryKey("PK_tenants_tariff", x => x.id);
})
.Annotation("MySql:CharSet", "utf8mb4");
migrationBuilder.CreateTable(
name: "tenants_tenants",
columns: table => new
{
id = table.Column<int>(type: "int", nullable: false)
.Annotation("MySql:ValueGenerationStrategy", MySqlValueGenerationStrategy.IdentityColumn),
name = table.Column<string>(type: "varchar(255)", nullable: false, collation: "utf8_general_ci")
.Annotation("MySql:CharSet", "utf8"),
alias = table.Column<string>(type: "varchar(100)", nullable: false, collation: "utf8_general_ci")
.Annotation("MySql:CharSet", "utf8"),
mappeddomain = table.Column<string>(type: "varchar(100)", nullable: true, collation: "utf8_general_ci")
.Annotation("MySql:CharSet", "utf8"),
version = table.Column<int>(type: "int", nullable: false, defaultValueSql: "'2'"),
version_changed = table.Column<DateTime>(type: "datetime", nullable: true),
language = table.Column<string>(type: "char(10)", nullable: false, defaultValueSql: "'en-US'", collation: "utf8_general_ci")
.Annotation("MySql:CharSet", "utf8"),
timezone = table.Column<string>(type: "varchar(50)", nullable: true, collation: "utf8_general_ci")
.Annotation("MySql:CharSet", "utf8"),
trusteddomains = table.Column<string>(type: "varchar(1024)", nullable: true, collation: "utf8_general_ci")
.Annotation("MySql:CharSet", "utf8"),
trusteddomainsenabled = table.Column<int>(type: "int", nullable: false, defaultValueSql: "'1'"),
status = table.Column<int>(type: "int", nullable: false),
statuschanged = table.Column<DateTime>(type: "datetime", nullable: true),
creationdatetime = table.Column<DateTime>(type: "datetime", nullable: false),
owner_id = table.Column<string>(type: "varchar(38)", nullable: false, collation: "utf8_general_ci")
.Annotation("MySql:CharSet", "utf8"),
payment_id = table.Column<string>(type: "varchar(38)", nullable: true, collation: "utf8_general_ci")
.Annotation("MySql:CharSet", "utf8"),
industry = table.Column<int>(type: "int", nullable: true),
last_modified = table.Column<DateTime>(type: "timestamp", nullable: false, defaultValueSql: "CURRENT_TIMESTAMP"),
spam = table.Column<bool>(type: "tinyint(1)", nullable: false, defaultValueSql: "true"),
calls = table.Column<bool>(type: "tinyint(1)", nullable: false, defaultValueSql: "true")
},
constraints: table =>
{
table.PrimaryKey("PK_tenants_tenants", x => x.id);
})
.Annotation("MySql:CharSet", "utf8mb4");
migrationBuilder.InsertData(
table: "tenants_quota",
columns: new[] { "tenant", "active_users", "avangate_id", "description", "features", "max_file_size", "max_total_size", "name", "price", "visible" },
values: new object[] { -1, 10000, "0", null, "domain,audit,controlpanel,healthcheck,ldap,sso,whitelabel,branding,ssbranding,update,support,portals:10000,discencryption,privacyroom,restore", 102400L, 10995116277760L, "default", 0.00m, false });
migrationBuilder.InsertData(
table: "tenants_tenants",
columns: new[] { "id", "alias", "creationdatetime", "industry", "mappeddomain", "name", "owner_id", "payment_id", "status", "statuschanged", "timezone", "trusteddomains", "version_changed" },
values: new object[] { 1, "localhost", new DateTime(2021, 3, 9, 17, 46, 59, 97, DateTimeKind.Utc).AddTicks(4317), null, null, "Web Office", "66faa6e4-f133-11ea-b126-00ffeec8b4ef", null, 0, null, null, null, null });
migrationBuilder.CreateIndex(
name: "tenant",
table: "tenants_tariff",
column: "tenant");
migrationBuilder.CreateIndex(
name: "last_modified",
table: "tenants_tenants",
column: "last_modified");
migrationBuilder.CreateIndex(
name: "mappeddomain",
table: "tenants_tenants",
column: "mappeddomain");
migrationBuilder.CreateIndex(
name: "version",
table: "tenants_tenants",
column: "version");
}
protected override void Down(MigrationBuilder migrationBuilder)
{
migrationBuilder.DropTable(
name: "tenants_quota");
migrationBuilder.DropTable(
name: "tenants_tariff");
migrationBuilder.DropTable(
name: "tenants_tenants");
migrationBuilder.DropColumn(
name: "folder_id",
table: "files_thirdparty_account");
migrationBuilder.DropColumn(
name: "root_folder_type",
table: "files_thirdparty_account");
migrationBuilder.RenameColumn(
name: "FolderType",
table: "files_thirdparty_account",
newName: "folder_type");
migrationBuilder.AlterColumn<int>(
name: "folder_type",
table: "files_thirdparty_account",
type: "int",
nullable: false,
oldClrType: typeof(int),
oldType: "folder_type");
}
}
}

View File

@ -1,8 +1,12 @@
// <auto-generated />
using System;
using ASC.Files.Core.EF;
using Microsoft.EntityFrameworkCore;
using Microsoft.EntityFrameworkCore.Infrastructure;
using Microsoft.EntityFrameworkCore.Storage.ValueConversion;
#nullable disable
namespace ASC.Files.Core.Migrations.MySql.FilesDbContextMySql
{
[DbContext(typeof(MySqlFilesDbContext))]
@ -12,8 +16,263 @@ namespace ASC.Files.Core.Migrations.MySql.FilesDbContextMySql
{
#pragma warning disable 612, 618
modelBuilder
.HasAnnotation("Relational:MaxIdentifierLength", 64)
.HasAnnotation("ProductVersion", "5.0.10");
.HasAnnotation("ProductVersion", "6.0.4")
.HasAnnotation("Relational:MaxIdentifierLength", 64);
modelBuilder.Entity("ASC.Core.Common.EF.DbQuota", b =>
{
b.Property<int>("Tenant")
.ValueGeneratedOnAdd()
.HasColumnType("int")
.HasColumnName("tenant");
b.Property<int>("ActiveUsers")
.HasColumnType("int")
.HasColumnName("active_users");
b.Property<string>("AvangateId")
.HasColumnType("varchar(128)")
.HasColumnName("avangate_id")
.UseCollation("utf8_general_ci")
.HasAnnotation("MySql:CharSet", "utf8");
b.Property<string>("Description")
.HasColumnType("varchar(128)")
.HasColumnName("description")
.UseCollation("utf8_general_ci")
.HasAnnotation("MySql:CharSet", "utf8");
b.Property<string>("Features")
.HasColumnType("text")
.HasColumnName("features")
.UseCollation("utf8_general_ci")
.HasAnnotation("MySql:CharSet", "utf8");
b.Property<long>("MaxFileSize")
.HasColumnType("bigint")
.HasColumnName("max_file_size");
b.Property<long>("MaxTotalSize")
.HasColumnType("bigint")
.HasColumnName("max_total_size");
b.Property<string>("Name")
.HasColumnType("varchar(128)")
.HasColumnName("name")
.UseCollation("utf8_general_ci")
.HasAnnotation("MySql:CharSet", "utf8");
b.Property<decimal>("Price")
.HasColumnType("decimal(10,2)")
.HasColumnName("price");
b.Property<bool>("Visible")
.HasColumnType("tinyint(1)")
.HasColumnName("visible");
b.HasKey("Tenant")
.HasName("PRIMARY");
b.ToTable("tenants_quota", (string)null);
b.HasData(
new
{
Tenant = -1,
ActiveUsers = 10000,
AvangateId = "0",
Features = "domain,audit,controlpanel,healthcheck,ldap,sso,whitelabel,branding,ssbranding,update,support,portals:10000,discencryption,privacyroom,restore",
MaxFileSize = 102400L,
MaxTotalSize = 10995116277760L,
Name = "default",
Price = 0.00m,
Visible = false
});
});
modelBuilder.Entity("ASC.Core.Common.EF.DbTariff", b =>
{
b.Property<int>("Id")
.ValueGeneratedOnAdd()
.HasColumnType("int")
.HasColumnName("id");
b.Property<string>("Comment")
.HasColumnType("varchar(255)")
.HasColumnName("comment")
.UseCollation("utf8_general_ci")
.HasAnnotation("MySql:CharSet", "utf8");
b.Property<DateTime>("CreateOn")
.ValueGeneratedOnAddOrUpdate()
.HasColumnType("timestamp")
.HasColumnName("create_on")
.HasDefaultValueSql("CURRENT_TIMESTAMP");
b.Property<int>("Quantity")
.HasColumnType("int")
.HasColumnName("quantity");
b.Property<DateTime>("Stamp")
.HasColumnType("datetime")
.HasColumnName("stamp");
b.Property<int>("Tariff")
.HasColumnType("int")
.HasColumnName("tariff");
b.Property<int>("Tenant")
.HasColumnType("int")
.HasColumnName("tenant");
b.HasKey("Id");
b.HasIndex("Tenant")
.HasDatabaseName("tenant");
b.ToTable("tenants_tariff", (string)null);
});
modelBuilder.Entity("ASC.Core.Common.EF.Model.DbTenant", b =>
{
b.Property<int>("Id")
.ValueGeneratedOnAdd()
.HasColumnType("int")
.HasColumnName("id");
b.Property<string>("Alias")
.IsRequired()
.HasColumnType("varchar(100)")
.HasColumnName("alias")
.UseCollation("utf8_general_ci")
.HasAnnotation("MySql:CharSet", "utf8");
b.Property<bool>("Calls")
.ValueGeneratedOnAdd()
.HasColumnType("tinyint(1)")
.HasColumnName("calls")
.HasDefaultValueSql("true");
b.Property<DateTime>("CreationDateTime")
.HasColumnType("datetime")
.HasColumnName("creationdatetime");
b.Property<int?>("Industry")
.HasColumnType("int")
.HasColumnName("industry");
b.Property<string>("Language")
.IsRequired()
.ValueGeneratedOnAdd()
.HasColumnType("char(10)")
.HasColumnName("language")
.HasDefaultValueSql("'en-US'")
.UseCollation("utf8_general_ci")
.HasAnnotation("MySql:CharSet", "utf8");
b.Property<DateTime>("LastModified")
.ValueGeneratedOnAdd()
.HasColumnType("timestamp")
.HasColumnName("last_modified")
.HasDefaultValueSql("CURRENT_TIMESTAMP");
b.Property<string>("MappedDomain")
.HasColumnType("varchar(100)")
.HasColumnName("mappeddomain")
.UseCollation("utf8_general_ci")
.HasAnnotation("MySql:CharSet", "utf8");
b.Property<string>("Name")
.IsRequired()
.HasColumnType("varchar(255)")
.HasColumnName("name")
.UseCollation("utf8_general_ci")
.HasAnnotation("MySql:CharSet", "utf8");
b.Property<string>("OwnerId")
.IsRequired()
.HasColumnType("varchar(38)")
.HasColumnName("owner_id")
.UseCollation("utf8_general_ci")
.HasAnnotation("MySql:CharSet", "utf8");
b.Property<string>("PaymentId")
.HasColumnType("varchar(38)")
.HasColumnName("payment_id")
.UseCollation("utf8_general_ci")
.HasAnnotation("MySql:CharSet", "utf8");
b.Property<bool>("Spam")
.ValueGeneratedOnAdd()
.HasColumnType("tinyint(1)")
.HasColumnName("spam")
.HasDefaultValueSql("true");
b.Property<int>("Status")
.HasColumnType("int")
.HasColumnName("status");
b.Property<DateTime?>("StatusChanged")
.HasColumnType("datetime")
.HasColumnName("statuschanged");
b.Property<string>("TimeZone")
.HasColumnType("varchar(50)")
.HasColumnName("timezone")
.UseCollation("utf8_general_ci")
.HasAnnotation("MySql:CharSet", "utf8");
b.Property<int>("TrustedDomainsEnabled")
.ValueGeneratedOnAdd()
.HasColumnType("int")
.HasColumnName("trusteddomainsenabled")
.HasDefaultValueSql("'1'");
b.Property<string>("TrustedDomainsRaw")
.HasColumnType("varchar(1024)")
.HasColumnName("trusteddomains")
.UseCollation("utf8_general_ci")
.HasAnnotation("MySql:CharSet", "utf8");
b.Property<int>("Version")
.ValueGeneratedOnAdd()
.HasColumnType("int")
.HasColumnName("version")
.HasDefaultValueSql("'2'");
b.Property<DateTime?>("Version_Changed")
.HasColumnType("datetime")
.HasColumnName("version_changed");
b.HasKey("Id");
b.HasIndex("LastModified")
.HasDatabaseName("last_modified");
b.HasIndex("MappedDomain")
.HasDatabaseName("mappeddomain");
b.HasIndex("Version")
.HasDatabaseName("version");
b.ToTable("tenants_tenants", (string)null);
b.HasData(
new
{
Id = 1,
Alias = "localhost",
Calls = false,
CreationDateTime = new DateTime(2021, 3, 9, 17, 46, 59, 97, DateTimeKind.Utc).AddTicks(4317),
LastModified = new DateTime(1, 1, 1, 0, 0, 0, 0, DateTimeKind.Unspecified),
Name = "Web Office",
OwnerId = "66faa6e4-f133-11ea-b126-00ffeec8b4ef",
Spam = false,
Status = 0,
TrustedDomainsEnabled = 0,
Version = 0
});
});
modelBuilder.Entity("ASC.Files.Core.EF.DbFile", b =>
{
@ -78,10 +337,6 @@ namespace ASC.Files.Core.Migrations.MySql.FilesDbContextMySql
.HasColumnType("int")
.HasColumnName("file_status");
b.Property<int>("FolderId")
.HasColumnType("int")
.HasColumnName("folder_id");
b.Property<int>("Forcesave")
.HasColumnType("int")
.HasColumnName("forcesave");
@ -97,7 +352,11 @@ namespace ASC.Files.Core.Migrations.MySql.FilesDbContextMySql
.HasColumnType("datetime")
.HasColumnName("modified_on");
b.Property<int>("Thumb")
b.Property<int>("ParentId")
.HasColumnType("int")
.HasColumnName("folder_id");
b.Property<int>("ThumbnailStatus")
.HasColumnType("int")
.HasColumnName("thumb");
@ -117,16 +376,16 @@ namespace ASC.Files.Core.Migrations.MySql.FilesDbContextMySql
b.HasKey("TenantId", "Id", "Version")
.HasName("PRIMARY");
b.HasIndex("FolderId")
.HasDatabaseName("folder_id");
b.HasIndex("Id")
.HasDatabaseName("id");
b.HasIndex("ModifiedOn")
.HasDatabaseName("modified_on");
b.ToTable("files_file");
b.HasIndex("ParentId")
.HasDatabaseName("folder_id");
b.ToTable("files_file", (string)null);
});
modelBuilder.Entity("ASC.Files.Core.EF.DbFilesBunchObjects", b =>
@ -154,7 +413,7 @@ namespace ASC.Files.Core.Migrations.MySql.FilesDbContextMySql
b.HasIndex("LeftNode")
.HasDatabaseName("left_node");
b.ToTable("files_bunch_objects");
b.ToTable("files_bunch_objects", (string)null);
});
modelBuilder.Entity("ASC.Files.Core.EF.DbFilesLink", b =>
@ -220,7 +479,7 @@ namespace ASC.Files.Core.Migrations.MySql.FilesDbContextMySql
.UseCollation("utf8_general_ci")
.HasAnnotation("MySql:CharSet", "utf8");
b.Property<int>("Security")
b.Property<int>("Share")
.HasColumnType("int")
.HasColumnName("security");
@ -239,7 +498,7 @@ namespace ASC.Files.Core.Migrations.MySql.FilesDbContextMySql
b.HasIndex("TenantId", "EntryType", "EntryId", "Owner")
.HasDatabaseName("tenant_id");
b.ToTable("files_security");
b.ToTable("files_security", (string)null);
});
modelBuilder.Entity("ASC.Files.Core.EF.DbFilesTag", b =>
@ -249,10 +508,6 @@ namespace ASC.Files.Core.Migrations.MySql.FilesDbContextMySql
.HasColumnType("int")
.HasColumnName("id");
b.Property<int>("Flag")
.HasColumnType("int")
.HasColumnName("flag");
b.Property<string>("Name")
.IsRequired()
.HasColumnType("varchar(255)")
@ -271,12 +526,16 @@ namespace ASC.Files.Core.Migrations.MySql.FilesDbContextMySql
.HasColumnType("int")
.HasColumnName("tenant_id");
b.Property<int>("Type")
.HasColumnType("int")
.HasColumnName("flag");
b.HasKey("Id");
b.HasIndex("TenantId", "Owner", "Name", "Flag")
b.HasIndex("TenantId", "Owner", "Name", "Type")
.HasDatabaseName("name");
b.ToTable("files_tag");
b.ToTable("files_tag", (string)null);
});
modelBuilder.Entity("ASC.Files.Core.EF.DbFilesTagLink", b =>
@ -299,6 +558,10 @@ namespace ASC.Files.Core.Migrations.MySql.FilesDbContextMySql
.HasColumnType("int")
.HasColumnName("entry_type");
b.Property<int>("Count")
.HasColumnType("int")
.HasColumnName("tag_count");
b.Property<string>("CreateBy")
.HasColumnType("char(38)")
.HasColumnName("create_by")
@ -309,10 +572,6 @@ namespace ASC.Files.Core.Migrations.MySql.FilesDbContextMySql
.HasColumnType("datetime")
.HasColumnName("create_on");
b.Property<int>("TagCount")
.HasColumnType("int")
.HasColumnName("tag_count");
b.HasKey("TenantId", "TagId", "EntryId", "EntryType")
.HasName("PRIMARY");
@ -322,7 +581,7 @@ namespace ASC.Files.Core.Migrations.MySql.FilesDbContextMySql
b.HasIndex("TenantId", "EntryId", "EntryType")
.HasDatabaseName("entry_id");
b.ToTable("files_tag_link");
b.ToTable("files_tag_link", (string)null);
});
modelBuilder.Entity("ASC.Files.Core.EF.DbFilesThirdpartyAccount", b =>
@ -336,9 +595,14 @@ namespace ASC.Files.Core.Migrations.MySql.FilesDbContextMySql
.HasColumnType("datetime")
.HasColumnName("create_on");
b.Property<string>("FolderId")
.HasColumnType("text")
.HasColumnName("folder_id")
.UseCollation("utf8_general_ci")
.HasAnnotation("MySql:CharSet", "utf8");
b.Property<int>("FolderType")
.HasColumnType("int")
.HasColumnName("folder_type");
.HasColumnType("folder_type");
b.Property<string>("Password")
.IsRequired()
@ -356,6 +620,10 @@ namespace ASC.Files.Core.Migrations.MySql.FilesDbContextMySql
.UseCollation("utf8_general_ci")
.HasAnnotation("MySql:CharSet", "utf8");
b.Property<int>("RootFolderType")
.HasColumnType("int")
.HasColumnName("root_folder_type");
b.Property<int>("TenantId")
.HasColumnType("int")
.HasColumnName("tenant_id");
@ -395,7 +663,7 @@ namespace ASC.Files.Core.Migrations.MySql.FilesDbContextMySql
b.HasKey("Id");
b.ToTable("files_thirdparty_account");
b.ToTable("files_thirdparty_account", (string)null);
});
modelBuilder.Entity("ASC.Files.Core.EF.DbFilesThirdpartyApp", b =>
@ -431,7 +699,7 @@ namespace ASC.Files.Core.Migrations.MySql.FilesDbContextMySql
b.HasKey("UserId", "App")
.HasName("PRIMARY");
b.ToTable("files_thirdparty_app");
b.ToTable("files_thirdparty_app", (string)null);
});
modelBuilder.Entity("ASC.Files.Core.EF.DbFilesThirdpartyIdMapping", b =>
@ -459,7 +727,7 @@ namespace ASC.Files.Core.Migrations.MySql.FilesDbContextMySql
b.HasIndex("TenantId", "HashId")
.HasDatabaseName("index_1");
b.ToTable("files_thirdparty_id_mapping");
b.ToTable("files_thirdparty_id_mapping", (string)null);
});
modelBuilder.Entity("ASC.Files.Core.EF.DbFolder", b =>
@ -526,7 +794,7 @@ namespace ASC.Files.Core.Migrations.MySql.FilesDbContextMySql
b.HasIndex("TenantId", "ParentId")
.HasDatabaseName("parent_id");
b.ToTable("files_folder");
b.ToTable("files_folder", (string)null);
});
modelBuilder.Entity("ASC.Files.Core.EF.DbFolderTree", b =>
@ -549,7 +817,7 @@ namespace ASC.Files.Core.Migrations.MySql.FilesDbContextMySql
b.HasIndex("FolderId")
.HasDatabaseName("folder_id");
b.ToTable("files_folder_tree");
b.ToTable("files_folder_tree", (string)null);
});
#pragma warning restore 612, 618
}

View File

@ -0,0 +1,827 @@
// <auto-generated />
using System;
using ASC.Files.Core.EF;
using Microsoft.EntityFrameworkCore;
using Microsoft.EntityFrameworkCore.Infrastructure;
using Microsoft.EntityFrameworkCore.Migrations;
using Microsoft.EntityFrameworkCore.Storage.ValueConversion;
#nullable disable
namespace ASC.Files.Core.Migrations.PostgreSql.FilesDbContextPostgreSql
{
[DbContext(typeof(PostgreSqlFilesDbContext))]
[Migration("20220526143058_FilesDbContextPostgreSql_Upgrade1")]
partial class FilesDbContextPostgreSql_Upgrade1
{
protected override void BuildTargetModel(ModelBuilder modelBuilder)
{
#pragma warning disable 612, 618
modelBuilder
.HasAnnotation("ProductVersion", "6.0.4")
.HasAnnotation("Relational:MaxIdentifierLength", 64);
modelBuilder.Entity("ASC.Core.Common.EF.DbQuota", b =>
{
b.Property<int>("Tenant")
.ValueGeneratedOnAdd()
.HasColumnType("int")
.HasColumnName("tenant");
b.Property<int>("ActiveUsers")
.HasColumnType("int")
.HasColumnName("active_users");
b.Property<string>("AvangateId")
.HasColumnType("varchar(128)")
.HasColumnName("avangate_id")
.UseCollation("utf8_general_ci")
.HasAnnotation("MySql:CharSet", "utf8");
b.Property<string>("Description")
.HasColumnType("varchar(128)")
.HasColumnName("description")
.UseCollation("utf8_general_ci")
.HasAnnotation("MySql:CharSet", "utf8");
b.Property<string>("Features")
.HasColumnType("text")
.HasColumnName("features")
.UseCollation("utf8_general_ci")
.HasAnnotation("MySql:CharSet", "utf8");
b.Property<long>("MaxFileSize")
.HasColumnType("bigint")
.HasColumnName("max_file_size");
b.Property<long>("MaxTotalSize")
.HasColumnType("bigint")
.HasColumnName("max_total_size");
b.Property<string>("Name")
.HasColumnType("varchar(128)")
.HasColumnName("name")
.UseCollation("utf8_general_ci")
.HasAnnotation("MySql:CharSet", "utf8");
b.Property<decimal>("Price")
.HasColumnType("decimal(10,2)")
.HasColumnName("price");
b.Property<bool>("Visible")
.HasColumnType("tinyint(1)")
.HasColumnName("visible");
b.HasKey("Tenant")
.HasName("PRIMARY");
b.ToTable("tenants_quota", (string)null);
b.HasData(
new
{
Tenant = -1,
ActiveUsers = 10000,
AvangateId = "0",
Features = "domain,audit,controlpanel,healthcheck,ldap,sso,whitelabel,branding,ssbranding,update,support,portals:10000,discencryption,privacyroom,restore",
MaxFileSize = 102400L,
MaxTotalSize = 10995116277760L,
Name = "default",
Price = 0.00m,
Visible = false
});
});
modelBuilder.Entity("ASC.Core.Common.EF.DbTariff", b =>
{
b.Property<int>("Id")
.ValueGeneratedOnAdd()
.HasColumnType("int")
.HasColumnName("id");
b.Property<string>("Comment")
.HasColumnType("varchar(255)")
.HasColumnName("comment")
.UseCollation("utf8_general_ci")
.HasAnnotation("MySql:CharSet", "utf8");
b.Property<DateTime>("CreateOn")
.ValueGeneratedOnAddOrUpdate()
.HasColumnType("timestamp")
.HasColumnName("create_on")
.HasDefaultValueSql("CURRENT_TIMESTAMP");
b.Property<int>("Quantity")
.HasColumnType("int")
.HasColumnName("quantity");
b.Property<DateTime>("Stamp")
.HasColumnType("datetime")
.HasColumnName("stamp");
b.Property<int>("Tariff")
.HasColumnType("int")
.HasColumnName("tariff");
b.Property<int>("Tenant")
.HasColumnType("int")
.HasColumnName("tenant");
b.HasKey("Id");
b.HasIndex("Tenant")
.HasDatabaseName("tenant");
b.ToTable("tenants_tariff", (string)null);
});
modelBuilder.Entity("ASC.Core.Common.EF.Model.DbTenant", b =>
{
b.Property<int>("Id")
.ValueGeneratedOnAdd()
.HasColumnType("int")
.HasColumnName("id");
b.Property<string>("Alias")
.IsRequired()
.HasColumnType("varchar(100)")
.HasColumnName("alias")
.UseCollation("utf8_general_ci")
.HasAnnotation("MySql:CharSet", "utf8");
b.Property<bool>("Calls")
.ValueGeneratedOnAdd()
.HasColumnType("tinyint(1)")
.HasColumnName("calls")
.HasDefaultValueSql("true");
b.Property<DateTime>("CreationDateTime")
.HasColumnType("datetime")
.HasColumnName("creationdatetime");
b.Property<int?>("Industry")
.HasColumnType("int")
.HasColumnName("industry");
b.Property<string>("Language")
.IsRequired()
.ValueGeneratedOnAdd()
.HasColumnType("char(10)")
.HasColumnName("language")
.HasDefaultValueSql("'en-US'")
.UseCollation("utf8_general_ci")
.HasAnnotation("MySql:CharSet", "utf8");
b.Property<DateTime>("LastModified")
.ValueGeneratedOnAdd()
.HasColumnType("timestamp")
.HasColumnName("last_modified")
.HasDefaultValueSql("CURRENT_TIMESTAMP");
b.Property<string>("MappedDomain")
.HasColumnType("varchar(100)")
.HasColumnName("mappeddomain")
.UseCollation("utf8_general_ci")
.HasAnnotation("MySql:CharSet", "utf8");
b.Property<string>("Name")
.IsRequired()
.HasColumnType("varchar(255)")
.HasColumnName("name")
.UseCollation("utf8_general_ci")
.HasAnnotation("MySql:CharSet", "utf8");
b.Property<string>("OwnerId")
.IsRequired()
.HasColumnType("varchar(38)")
.HasColumnName("owner_id")
.UseCollation("utf8_general_ci")
.HasAnnotation("MySql:CharSet", "utf8");
b.Property<string>("PaymentId")
.HasColumnType("varchar(38)")
.HasColumnName("payment_id")
.UseCollation("utf8_general_ci")
.HasAnnotation("MySql:CharSet", "utf8");
b.Property<bool>("Spam")
.ValueGeneratedOnAdd()
.HasColumnType("tinyint(1)")
.HasColumnName("spam")
.HasDefaultValueSql("true");
b.Property<int>("Status")
.HasColumnType("int")
.HasColumnName("status");
b.Property<DateTime?>("StatusChanged")
.HasColumnType("datetime")
.HasColumnName("statuschanged");
b.Property<string>("TimeZone")
.HasColumnType("varchar(50)")
.HasColumnName("timezone")
.UseCollation("utf8_general_ci")
.HasAnnotation("MySql:CharSet", "utf8");
b.Property<int>("TrustedDomainsEnabled")
.ValueGeneratedOnAdd()
.HasColumnType("int")
.HasColumnName("trusteddomainsenabled")
.HasDefaultValueSql("'1'");
b.Property<string>("TrustedDomainsRaw")
.HasColumnType("varchar(1024)")
.HasColumnName("trusteddomains")
.UseCollation("utf8_general_ci")
.HasAnnotation("MySql:CharSet", "utf8");
b.Property<int>("Version")
.ValueGeneratedOnAdd()
.HasColumnType("int")
.HasColumnName("version")
.HasDefaultValueSql("'2'");
b.Property<DateTime?>("Version_Changed")
.HasColumnType("datetime")
.HasColumnName("version_changed");
b.HasKey("Id");
b.HasIndex("LastModified")
.HasDatabaseName("last_modified");
b.HasIndex("MappedDomain")
.HasDatabaseName("mappeddomain");
b.HasIndex("Version")
.HasDatabaseName("version");
b.ToTable("tenants_tenants", (string)null);
b.HasData(
new
{
Id = 1,
Alias = "localhost",
Calls = false,
CreationDateTime = new DateTime(2021, 3, 9, 17, 46, 59, 97, DateTimeKind.Utc).AddTicks(4317),
LastModified = new DateTime(1, 1, 1, 0, 0, 0, 0, DateTimeKind.Unspecified),
Name = "Web Office",
OwnerId = "66faa6e4-f133-11ea-b126-00ffeec8b4ef",
Spam = false,
Status = 0,
TrustedDomainsEnabled = 0,
Version = 0
});
});
modelBuilder.Entity("ASC.Files.Core.EF.DbFile", b =>
{
b.Property<int>("TenantId")
.HasColumnType("int")
.HasColumnName("tenant_id");
b.Property<int>("Id")
.HasColumnType("int")
.HasColumnName("id");
b.Property<int>("Version")
.HasColumnType("int")
.HasColumnName("version");
b.Property<int>("Category")
.HasColumnType("int")
.HasColumnName("category");
b.Property<string>("Changes")
.HasColumnType("mediumtext")
.HasColumnName("changes")
.UseCollation("utf8_general_ci")
.HasAnnotation("MySql:CharSet", "utf8");
b.Property<string>("Comment")
.HasColumnType("varchar(255)")
.HasColumnName("comment")
.UseCollation("utf8_general_ci")
.HasAnnotation("MySql:CharSet", "utf8");
b.Property<long>("ContentLength")
.HasColumnType("bigint")
.HasColumnName("content_length");
b.Property<string>("ConvertedType")
.HasColumnType("varchar(10)")
.HasColumnName("converted_type")
.UseCollation("utf8_general_ci")
.HasAnnotation("MySql:CharSet", "utf8");
b.Property<string>("CreateBy")
.IsRequired()
.HasColumnType("char(38)")
.HasColumnName("create_by")
.UseCollation("utf8_general_ci")
.HasAnnotation("MySql:CharSet", "utf8");
b.Property<DateTime>("CreateOn")
.HasColumnType("datetime")
.HasColumnName("create_on");
b.Property<bool>("CurrentVersion")
.HasColumnType("tinyint(1)")
.HasColumnName("current_version");
b.Property<bool>("Encrypted")
.HasColumnType("tinyint(1)")
.HasColumnName("encrypted");
b.Property<int>("FileStatus")
.HasColumnType("int")
.HasColumnName("file_status");
b.Property<int>("Forcesave")
.HasColumnType("int")
.HasColumnName("forcesave");
b.Property<string>("ModifiedBy")
.IsRequired()
.HasColumnType("char(38)")
.HasColumnName("modified_by")
.UseCollation("utf8_general_ci")
.HasAnnotation("MySql:CharSet", "utf8");
b.Property<DateTime>("ModifiedOn")
.HasColumnType("datetime")
.HasColumnName("modified_on");
b.Property<int>("ParentId")
.HasColumnType("int")
.HasColumnName("folder_id");
b.Property<int>("ThumbnailStatus")
.HasColumnType("int")
.HasColumnName("thumb");
b.Property<string>("Title")
.IsRequired()
.HasColumnType("varchar(400)")
.HasColumnName("title")
.UseCollation("utf8_general_ci")
.HasAnnotation("MySql:CharSet", "utf8");
b.Property<int>("VersionGroup")
.ValueGeneratedOnAdd()
.HasColumnType("int")
.HasColumnName("version_group")
.HasDefaultValueSql("'1'");
b.HasKey("TenantId", "Id", "Version")
.HasName("PRIMARY");
b.HasIndex("Id")
.HasDatabaseName("id");
b.HasIndex("ModifiedOn")
.HasDatabaseName("modified_on");
b.HasIndex("ParentId")
.HasDatabaseName("folder_id");
b.ToTable("files_file", (string)null);
});
modelBuilder.Entity("ASC.Files.Core.EF.DbFilesBunchObjects", b =>
{
b.Property<int>("TenantId")
.HasColumnType("int")
.HasColumnName("tenant_id");
b.Property<string>("RightNode")
.HasColumnType("varchar(255)")
.HasColumnName("right_node")
.UseCollation("utf8_general_ci")
.HasAnnotation("MySql:CharSet", "utf8");
b.Property<string>("LeftNode")
.IsRequired()
.HasColumnType("varchar(255)")
.HasColumnName("left_node")
.UseCollation("utf8_general_ci")
.HasAnnotation("MySql:CharSet", "utf8");
b.HasKey("TenantId", "RightNode")
.HasName("PRIMARY");
b.HasIndex("LeftNode")
.HasDatabaseName("left_node");
b.ToTable("files_bunch_objects", (string)null);
});
modelBuilder.Entity("ASC.Files.Core.EF.DbFilesLink", b =>
{
b.Property<int>("TenantId")
.HasColumnType("int")
.HasColumnName("tenant_id");
b.Property<string>("SourceId")
.HasColumnType("varchar(32)")
.HasColumnName("source_id")
.UseCollation("utf8_general_ci")
.HasAnnotation("MySql:CharSet", "utf8");
b.Property<string>("LinkedId")
.HasColumnType("varchar(32)")
.HasColumnName("linked_id")
.UseCollation("utf8_general_ci")
.HasAnnotation("MySql:CharSet", "utf8");
b.Property<string>("LinkedFor")
.IsRequired()
.HasColumnType("char(38)")
.HasColumnName("linked_for")
.UseCollation("utf8_general_ci")
.HasAnnotation("MySql:CharSet", "utf8");
b.HasKey("TenantId", "SourceId", "LinkedId")
.HasName("PRIMARY");
b.HasIndex("TenantId", "SourceId", "LinkedId", "LinkedFor")
.HasDatabaseName("linked_for");
b.ToTable("files_link", (string)null);
});
modelBuilder.Entity("ASC.Files.Core.EF.DbFilesSecurity", b =>
{
b.Property<int>("TenantId")
.HasColumnType("int")
.HasColumnName("tenant_id");
b.Property<string>("EntryId")
.HasColumnType("varchar(50)")
.HasColumnName("entry_id")
.UseCollation("utf8_general_ci")
.HasAnnotation("MySql:CharSet", "utf8");
b.Property<int>("EntryType")
.HasColumnType("int")
.HasColumnName("entry_type");
b.Property<string>("Subject")
.HasColumnType("char(38)")
.HasColumnName("subject")
.UseCollation("utf8_general_ci")
.HasAnnotation("MySql:CharSet", "utf8");
b.Property<string>("Owner")
.IsRequired()
.HasColumnType("char(38)")
.HasColumnName("owner")
.UseCollation("utf8_general_ci")
.HasAnnotation("MySql:CharSet", "utf8");
b.Property<int>("Share")
.HasColumnType("int")
.HasColumnName("security");
b.Property<DateTime>("TimeStamp")
.ValueGeneratedOnAddOrUpdate()
.HasColumnType("timestamp")
.HasColumnName("timestamp")
.HasDefaultValueSql("CURRENT_TIMESTAMP");
b.HasKey("TenantId", "EntryId", "EntryType", "Subject")
.HasName("PRIMARY");
b.HasIndex("Owner")
.HasDatabaseName("owner");
b.HasIndex("TenantId", "EntryType", "EntryId", "Owner")
.HasDatabaseName("tenant_id");
b.ToTable("files_security", (string)null);
});
modelBuilder.Entity("ASC.Files.Core.EF.DbFilesTag", b =>
{
b.Property<int>("Id")
.ValueGeneratedOnAdd()
.HasColumnType("int")
.HasColumnName("id");
b.Property<string>("Name")
.IsRequired()
.HasColumnType("varchar(255)")
.HasColumnName("name")
.UseCollation("utf8_general_ci")
.HasAnnotation("MySql:CharSet", "utf8");
b.Property<string>("Owner")
.IsRequired()
.HasColumnType("varchar(38)")
.HasColumnName("owner")
.UseCollation("utf8_general_ci")
.HasAnnotation("MySql:CharSet", "utf8");
b.Property<int>("TenantId")
.HasColumnType("int")
.HasColumnName("tenant_id");
b.Property<int>("Type")
.HasColumnType("int")
.HasColumnName("flag");
b.HasKey("Id");
b.HasIndex("TenantId", "Owner", "Name", "Type")
.HasDatabaseName("name");
b.ToTable("files_tag", (string)null);
});
modelBuilder.Entity("ASC.Files.Core.EF.DbFilesTagLink", b =>
{
b.Property<int>("TenantId")
.HasColumnType("int")
.HasColumnName("tenant_id");
b.Property<int>("TagId")
.HasColumnType("int")
.HasColumnName("tag_id");
b.Property<string>("EntryId")
.HasColumnType("varchar(32)")
.HasColumnName("entry_id")
.UseCollation("utf8_general_ci")
.HasAnnotation("MySql:CharSet", "utf8");
b.Property<int>("EntryType")
.HasColumnType("int")
.HasColumnName("entry_type");
b.Property<int>("Count")
.HasColumnType("int")
.HasColumnName("tag_count");
b.Property<string>("CreateBy")
.HasColumnType("char(38)")
.HasColumnName("create_by")
.UseCollation("utf8_general_ci")
.HasAnnotation("MySql:CharSet", "utf8");
b.Property<DateTime?>("CreateOn")
.HasColumnType("datetime")
.HasColumnName("create_on");
b.HasKey("TenantId", "TagId", "EntryId", "EntryType")
.HasName("PRIMARY");
b.HasIndex("CreateOn")
.HasDatabaseName("create_on");
b.HasIndex("TenantId", "EntryId", "EntryType")
.HasDatabaseName("entry_id");
b.ToTable("files_tag_link", (string)null);
});
modelBuilder.Entity("ASC.Files.Core.EF.DbFilesThirdpartyAccount", b =>
{
b.Property<int>("Id")
.ValueGeneratedOnAdd()
.HasColumnType("int")
.HasColumnName("id");
b.Property<DateTime>("CreateOn")
.HasColumnType("datetime")
.HasColumnName("create_on");
b.Property<string>("FolderId")
.HasColumnType("text")
.HasColumnName("folder_id")
.UseCollation("utf8_general_ci")
.HasAnnotation("MySql:CharSet", "utf8");
b.Property<int>("FolderType")
.HasColumnType("folder_type");
b.Property<string>("Password")
.IsRequired()
.HasColumnType("varchar(100)")
.HasColumnName("password")
.UseCollation("utf8_general_ci")
.HasAnnotation("MySql:CharSet", "utf8");
b.Property<string>("Provider")
.IsRequired()
.ValueGeneratedOnAdd()
.HasColumnType("varchar(50)")
.HasColumnName("provider")
.HasDefaultValueSql("'0'")
.UseCollation("utf8_general_ci")
.HasAnnotation("MySql:CharSet", "utf8");
b.Property<int>("RootFolderType")
.HasColumnType("int")
.HasColumnName("root_folder_type");
b.Property<int>("TenantId")
.HasColumnType("int")
.HasColumnName("tenant_id");
b.Property<string>("Title")
.IsRequired()
.HasColumnType("varchar(400)")
.HasColumnName("customer_title")
.UseCollation("utf8_general_ci")
.HasAnnotation("MySql:CharSet", "utf8");
b.Property<string>("Token")
.HasColumnType("text")
.HasColumnName("token")
.UseCollation("utf8_general_ci")
.HasAnnotation("MySql:CharSet", "utf8");
b.Property<string>("Url")
.HasColumnType("text")
.HasColumnName("url")
.UseCollation("utf8_general_ci")
.HasAnnotation("MySql:CharSet", "utf8");
b.Property<string>("UserId")
.IsRequired()
.HasColumnType("varchar(38)")
.HasColumnName("user_id")
.UseCollation("utf8_general_ci")
.HasAnnotation("MySql:CharSet", "utf8");
b.Property<string>("UserName")
.IsRequired()
.HasColumnType("varchar(100)")
.HasColumnName("user_name")
.UseCollation("utf8_general_ci")
.HasAnnotation("MySql:CharSet", "utf8");
b.HasKey("Id");
b.ToTable("files_thirdparty_account", (string)null);
});
modelBuilder.Entity("ASC.Files.Core.EF.DbFilesThirdpartyApp", b =>
{
b.Property<string>("UserId")
.HasColumnType("varchar(38)")
.HasColumnName("user_id")
.UseCollation("utf8_general_ci")
.HasAnnotation("MySql:CharSet", "utf8");
b.Property<string>("App")
.HasColumnType("varchar(50)")
.HasColumnName("app")
.UseCollation("utf8_general_ci")
.HasAnnotation("MySql:CharSet", "utf8");
b.Property<DateTime>("ModifiedOn")
.ValueGeneratedOnAddOrUpdate()
.HasColumnType("timestamp")
.HasColumnName("modified_on")
.HasDefaultValueSql("CURRENT_TIMESTAMP");
b.Property<int>("TenantId")
.HasColumnType("int")
.HasColumnName("tenant_id");
b.Property<string>("Token")
.HasColumnType("text")
.HasColumnName("token")
.UseCollation("utf8_general_ci")
.HasAnnotation("MySql:CharSet", "utf8");
b.HasKey("UserId", "App")
.HasName("PRIMARY");
b.ToTable("files_thirdparty_app", (string)null);
});
modelBuilder.Entity("ASC.Files.Core.EF.DbFilesThirdpartyIdMapping", b =>
{
b.Property<string>("HashId")
.HasColumnType("char(32)")
.HasColumnName("hash_id")
.UseCollation("utf8_general_ci")
.HasAnnotation("MySql:CharSet", "utf8");
b.Property<string>("Id")
.IsRequired()
.HasColumnType("text")
.HasColumnName("id")
.UseCollation("utf8_general_ci")
.HasAnnotation("MySql:CharSet", "utf8");
b.Property<int>("TenantId")
.HasColumnType("int")
.HasColumnName("tenant_id");
b.HasKey("HashId")
.HasName("PRIMARY");
b.HasIndex("TenantId", "HashId")
.HasDatabaseName("index_1");
b.ToTable("files_thirdparty_id_mapping", (string)null);
});
modelBuilder.Entity("ASC.Files.Core.EF.DbFolder", b =>
{
b.Property<int>("Id")
.ValueGeneratedOnAdd()
.HasColumnType("int")
.HasColumnName("id");
b.Property<string>("CreateBy")
.IsRequired()
.HasColumnType("char(38)")
.HasColumnName("create_by")
.UseCollation("utf8_general_ci")
.HasAnnotation("MySql:CharSet", "utf8");
b.Property<DateTime>("CreateOn")
.HasColumnType("datetime")
.HasColumnName("create_on");
b.Property<int>("FilesCount")
.HasColumnType("int")
.HasColumnName("filesCount");
b.Property<int>("FolderType")
.HasColumnType("int")
.HasColumnName("folder_type");
b.Property<int>("FoldersCount")
.HasColumnType("int")
.HasColumnName("foldersCount");
b.Property<string>("ModifiedBy")
.IsRequired()
.HasColumnType("char(38)")
.HasColumnName("modified_by")
.UseCollation("utf8_general_ci")
.HasAnnotation("MySql:CharSet", "utf8");
b.Property<DateTime>("ModifiedOn")
.HasColumnType("datetime")
.HasColumnName("modified_on");
b.Property<int>("ParentId")
.HasColumnType("int")
.HasColumnName("parent_id");
b.Property<int>("TenantId")
.HasColumnType("int")
.HasColumnName("tenant_id");
b.Property<string>("Title")
.IsRequired()
.HasColumnType("varchar(400)")
.HasColumnName("title")
.UseCollation("utf8_general_ci")
.HasAnnotation("MySql:CharSet", "utf8");
b.HasKey("Id");
b.HasIndex("ModifiedOn")
.HasDatabaseName("modified_on");
b.HasIndex("TenantId", "ParentId")
.HasDatabaseName("parent_id");
b.ToTable("files_folder", (string)null);
});
modelBuilder.Entity("ASC.Files.Core.EF.DbFolderTree", b =>
{
b.Property<int>("ParentId")
.HasColumnType("int")
.HasColumnName("parent_id");
b.Property<int>("FolderId")
.HasColumnType("int")
.HasColumnName("folder_id");
b.Property<int>("Level")
.HasColumnType("int")
.HasColumnName("level");
b.HasKey("ParentId", "FolderId")
.HasName("PRIMARY");
b.HasIndex("FolderId")
.HasDatabaseName("folder_id");
b.ToTable("files_folder_tree", (string)null);
});
#pragma warning restore 612, 618
}
}
}

View File

@ -0,0 +1,216 @@
using System;
using Microsoft.EntityFrameworkCore.Metadata;
using Microsoft.EntityFrameworkCore.Migrations;
#nullable disable
namespace ASC.Files.Core.Migrations.PostgreSql.FilesDbContextPostgreSql
{
public partial class FilesDbContextPostgreSql_Upgrade1 : Migration
{
protected override void Up(MigrationBuilder migrationBuilder)
{
migrationBuilder.RenameColumn(
name: "folder_type",
table: "files_thirdparty_account",
newName: "FolderType");
migrationBuilder.AlterColumn<int>(
name: "FolderType",
table: "files_thirdparty_account",
type: "folder_type",
nullable: false,
oldClrType: typeof(int),
oldType: "int");
migrationBuilder.AddColumn<string>(
name: "folder_id",
table: "files_thirdparty_account",
type: "text",
nullable: true,
collation: "utf8_general_ci")
.Annotation("MySql:CharSet", "utf8");
migrationBuilder.AddColumn<int>(
name: "root_folder_type",
table: "files_thirdparty_account",
type: "int",
nullable: false,
defaultValue: 0);
migrationBuilder.CreateTable(
name: "files_link",
columns: table => new
{
tenant_id = table.Column<int>(type: "int", nullable: false),
source_id = table.Column<string>(type: "varchar(32)", nullable: false, collation: "utf8_general_ci")
.Annotation("MySql:CharSet", "utf8"),
linked_id = table.Column<string>(type: "varchar(32)", nullable: false, collation: "utf8_general_ci")
.Annotation("MySql:CharSet", "utf8"),
linked_for = table.Column<string>(type: "char(38)", nullable: false, collation: "utf8_general_ci")
.Annotation("MySql:CharSet", "utf8")
},
constraints: table =>
{
table.PrimaryKey("PRIMARY", x => new { x.tenant_id, x.source_id, x.linked_id });
})
.Annotation("MySql:CharSet", "utf8mb4");
migrationBuilder.CreateTable(
name: "tenants_quota",
columns: table => new
{
tenant = table.Column<int>(type: "int", nullable: false)
.Annotation("MySql:ValueGenerationStrategy", MySqlValueGenerationStrategy.IdentityColumn),
name = table.Column<string>(type: "varchar(128)", nullable: true, collation: "utf8_general_ci")
.Annotation("MySql:CharSet", "utf8"),
description = table.Column<string>(type: "varchar(128)", nullable: true, collation: "utf8_general_ci")
.Annotation("MySql:CharSet", "utf8"),
max_file_size = table.Column<long>(type: "bigint", nullable: false),
max_total_size = table.Column<long>(type: "bigint", nullable: false),
active_users = table.Column<int>(type: "int", nullable: false),
features = table.Column<string>(type: "text", nullable: true, collation: "utf8_general_ci")
.Annotation("MySql:CharSet", "utf8"),
price = table.Column<decimal>(type: "decimal(10,2)", nullable: false),
avangate_id = table.Column<string>(type: "varchar(128)", nullable: true, collation: "utf8_general_ci")
.Annotation("MySql:CharSet", "utf8"),
visible = table.Column<bool>(type: "tinyint(1)", nullable: false)
},
constraints: table =>
{
table.PrimaryKey("PRIMARY", x => x.tenant);
})
.Annotation("MySql:CharSet", "utf8mb4");
migrationBuilder.CreateTable(
name: "tenants_tariff",
columns: table => new
{
id = table.Column<int>(type: "int", nullable: false)
.Annotation("MySql:ValueGenerationStrategy", MySqlValueGenerationStrategy.IdentityColumn),
tenant = table.Column<int>(type: "int", nullable: false),
tariff = table.Column<int>(type: "int", nullable: false),
stamp = table.Column<DateTime>(type: "datetime", nullable: false),
quantity = table.Column<int>(type: "int", nullable: false),
comment = table.Column<string>(type: "varchar(255)", nullable: true, collation: "utf8_general_ci")
.Annotation("MySql:CharSet", "utf8"),
create_on = table.Column<DateTime>(type: "timestamp", nullable: false, defaultValueSql: "CURRENT_TIMESTAMP")
},
constraints: table =>
{
table.PrimaryKey("PK_tenants_tariff", x => x.id);
})
.Annotation("MySql:CharSet", "utf8mb4");
migrationBuilder.CreateTable(
name: "tenants_tenants",
columns: table => new
{
id = table.Column<int>(type: "int", nullable: false)
.Annotation("MySql:ValueGenerationStrategy", MySqlValueGenerationStrategy.IdentityColumn),
name = table.Column<string>(type: "varchar(255)", nullable: false, collation: "utf8_general_ci")
.Annotation("MySql:CharSet", "utf8"),
alias = table.Column<string>(type: "varchar(100)", nullable: false, collation: "utf8_general_ci")
.Annotation("MySql:CharSet", "utf8"),
mappeddomain = table.Column<string>(type: "varchar(100)", nullable: true, collation: "utf8_general_ci")
.Annotation("MySql:CharSet", "utf8"),
version = table.Column<int>(type: "int", nullable: false, defaultValueSql: "'2'"),
version_changed = table.Column<DateTime>(type: "datetime", nullable: true),
language = table.Column<string>(type: "char(10)", nullable: false, defaultValueSql: "'en-US'", collation: "utf8_general_ci")
.Annotation("MySql:CharSet", "utf8"),
timezone = table.Column<string>(type: "varchar(50)", nullable: true, collation: "utf8_general_ci")
.Annotation("MySql:CharSet", "utf8"),
trusteddomains = table.Column<string>(type: "varchar(1024)", nullable: true, collation: "utf8_general_ci")
.Annotation("MySql:CharSet", "utf8"),
trusteddomainsenabled = table.Column<int>(type: "int", nullable: false, defaultValueSql: "'1'"),
status = table.Column<int>(type: "int", nullable: false),
statuschanged = table.Column<DateTime>(type: "datetime", nullable: true),
creationdatetime = table.Column<DateTime>(type: "datetime", nullable: false),
owner_id = table.Column<string>(type: "varchar(38)", nullable: false, collation: "utf8_general_ci")
.Annotation("MySql:CharSet", "utf8"),
payment_id = table.Column<string>(type: "varchar(38)", nullable: true, collation: "utf8_general_ci")
.Annotation("MySql:CharSet", "utf8"),
industry = table.Column<int>(type: "int", nullable: true),
last_modified = table.Column<DateTime>(type: "timestamp", nullable: false, defaultValueSql: "CURRENT_TIMESTAMP"),
spam = table.Column<bool>(type: "tinyint(1)", nullable: false, defaultValueSql: "true"),
calls = table.Column<bool>(type: "tinyint(1)", nullable: false, defaultValueSql: "true")
},
constraints: table =>
{
table.PrimaryKey("PK_tenants_tenants", x => x.id);
})
.Annotation("MySql:CharSet", "utf8mb4");
migrationBuilder.InsertData(
table: "tenants_quota",
columns: new[] { "tenant", "active_users", "avangate_id", "description", "features", "max_file_size", "max_total_size", "name", "price", "visible" },
values: new object[] { -1, 10000, "0", null, "domain,audit,controlpanel,healthcheck,ldap,sso,whitelabel,branding,ssbranding,update,support,portals:10000,discencryption,privacyroom,restore", 102400L, 10995116277760L, "default", 0.00m, false });
migrationBuilder.InsertData(
table: "tenants_tenants",
columns: new[] { "id", "alias", "creationdatetime", "industry", "mappeddomain", "name", "owner_id", "payment_id", "status", "statuschanged", "timezone", "trusteddomains", "version_changed" },
values: new object[] { 1, "localhost", new DateTime(2021, 3, 9, 17, 46, 59, 97, DateTimeKind.Utc).AddTicks(4317), null, null, "Web Office", "66faa6e4-f133-11ea-b126-00ffeec8b4ef", null, 0, null, null, null, null });
migrationBuilder.CreateIndex(
name: "linked_for",
table: "files_link",
columns: new[] { "tenant_id", "source_id", "linked_id", "linked_for" });
migrationBuilder.CreateIndex(
name: "tenant",
table: "tenants_tariff",
column: "tenant");
migrationBuilder.CreateIndex(
name: "last_modified",
table: "tenants_tenants",
column: "last_modified");
migrationBuilder.CreateIndex(
name: "mappeddomain",
table: "tenants_tenants",
column: "mappeddomain");
migrationBuilder.CreateIndex(
name: "version",
table: "tenants_tenants",
column: "version");
}
protected override void Down(MigrationBuilder migrationBuilder)
{
migrationBuilder.DropTable(
name: "files_link");
migrationBuilder.DropTable(
name: "tenants_quota");
migrationBuilder.DropTable(
name: "tenants_tariff");
migrationBuilder.DropTable(
name: "tenants_tenants");
migrationBuilder.DropColumn(
name: "folder_id",
table: "files_thirdparty_account");
migrationBuilder.DropColumn(
name: "root_folder_type",
table: "files_thirdparty_account");
migrationBuilder.RenameColumn(
name: "FolderType",
table: "files_thirdparty_account",
newName: "folder_type");
migrationBuilder.AlterColumn<int>(
name: "folder_type",
table: "files_thirdparty_account",
type: "int",
nullable: false,
oldClrType: typeof(int),
oldType: "folder_type");
}
}
}

View File

@ -1,4 +1,11 @@
// <auto-generated />
using System;
using ASC.Files.Core.EF;
using Microsoft.EntityFrameworkCore;
using Microsoft.EntityFrameworkCore.Infrastructure;
using Microsoft.EntityFrameworkCore.Storage.ValueConversion;
#nullable disable
namespace ASC.Files.Core.Migrations.PostgreSql.FilesDbContextPostgreSql
{
@ -9,8 +16,263 @@ namespace ASC.Files.Core.Migrations.PostgreSql.FilesDbContextPostgreSql
{
#pragma warning disable 612, 618
modelBuilder
.HasAnnotation("Relational:MaxIdentifierLength", 64)
.HasAnnotation("ProductVersion", "5.0.10");
.HasAnnotation("ProductVersion", "6.0.4")
.HasAnnotation("Relational:MaxIdentifierLength", 64);
modelBuilder.Entity("ASC.Core.Common.EF.DbQuota", b =>
{
b.Property<int>("Tenant")
.ValueGeneratedOnAdd()
.HasColumnType("int")
.HasColumnName("tenant");
b.Property<int>("ActiveUsers")
.HasColumnType("int")
.HasColumnName("active_users");
b.Property<string>("AvangateId")
.HasColumnType("varchar(128)")
.HasColumnName("avangate_id")
.UseCollation("utf8_general_ci")
.HasAnnotation("MySql:CharSet", "utf8");
b.Property<string>("Description")
.HasColumnType("varchar(128)")
.HasColumnName("description")
.UseCollation("utf8_general_ci")
.HasAnnotation("MySql:CharSet", "utf8");
b.Property<string>("Features")
.HasColumnType("text")
.HasColumnName("features")
.UseCollation("utf8_general_ci")
.HasAnnotation("MySql:CharSet", "utf8");
b.Property<long>("MaxFileSize")
.HasColumnType("bigint")
.HasColumnName("max_file_size");
b.Property<long>("MaxTotalSize")
.HasColumnType("bigint")
.HasColumnName("max_total_size");
b.Property<string>("Name")
.HasColumnType("varchar(128)")
.HasColumnName("name")
.UseCollation("utf8_general_ci")
.HasAnnotation("MySql:CharSet", "utf8");
b.Property<decimal>("Price")
.HasColumnType("decimal(10,2)")
.HasColumnName("price");
b.Property<bool>("Visible")
.HasColumnType("tinyint(1)")
.HasColumnName("visible");
b.HasKey("Tenant")
.HasName("PRIMARY");
b.ToTable("tenants_quota", (string)null);
b.HasData(
new
{
Tenant = -1,
ActiveUsers = 10000,
AvangateId = "0",
Features = "domain,audit,controlpanel,healthcheck,ldap,sso,whitelabel,branding,ssbranding,update,support,portals:10000,discencryption,privacyroom,restore",
MaxFileSize = 102400L,
MaxTotalSize = 10995116277760L,
Name = "default",
Price = 0.00m,
Visible = false
});
});
modelBuilder.Entity("ASC.Core.Common.EF.DbTariff", b =>
{
b.Property<int>("Id")
.ValueGeneratedOnAdd()
.HasColumnType("int")
.HasColumnName("id");
b.Property<string>("Comment")
.HasColumnType("varchar(255)")
.HasColumnName("comment")
.UseCollation("utf8_general_ci")
.HasAnnotation("MySql:CharSet", "utf8");
b.Property<DateTime>("CreateOn")
.ValueGeneratedOnAddOrUpdate()
.HasColumnType("timestamp")
.HasColumnName("create_on")
.HasDefaultValueSql("CURRENT_TIMESTAMP");
b.Property<int>("Quantity")
.HasColumnType("int")
.HasColumnName("quantity");
b.Property<DateTime>("Stamp")
.HasColumnType("datetime")
.HasColumnName("stamp");
b.Property<int>("Tariff")
.HasColumnType("int")
.HasColumnName("tariff");
b.Property<int>("Tenant")
.HasColumnType("int")
.HasColumnName("tenant");
b.HasKey("Id");
b.HasIndex("Tenant")
.HasDatabaseName("tenant");
b.ToTable("tenants_tariff", (string)null);
});
modelBuilder.Entity("ASC.Core.Common.EF.Model.DbTenant", b =>
{
b.Property<int>("Id")
.ValueGeneratedOnAdd()
.HasColumnType("int")
.HasColumnName("id");
b.Property<string>("Alias")
.IsRequired()
.HasColumnType("varchar(100)")
.HasColumnName("alias")
.UseCollation("utf8_general_ci")
.HasAnnotation("MySql:CharSet", "utf8");
b.Property<bool>("Calls")
.ValueGeneratedOnAdd()
.HasColumnType("tinyint(1)")
.HasColumnName("calls")
.HasDefaultValueSql("true");
b.Property<DateTime>("CreationDateTime")
.HasColumnType("datetime")
.HasColumnName("creationdatetime");
b.Property<int?>("Industry")
.HasColumnType("int")
.HasColumnName("industry");
b.Property<string>("Language")
.IsRequired()
.ValueGeneratedOnAdd()
.HasColumnType("char(10)")
.HasColumnName("language")
.HasDefaultValueSql("'en-US'")
.UseCollation("utf8_general_ci")
.HasAnnotation("MySql:CharSet", "utf8");
b.Property<DateTime>("LastModified")
.ValueGeneratedOnAdd()
.HasColumnType("timestamp")
.HasColumnName("last_modified")
.HasDefaultValueSql("CURRENT_TIMESTAMP");
b.Property<string>("MappedDomain")
.HasColumnType("varchar(100)")
.HasColumnName("mappeddomain")
.UseCollation("utf8_general_ci")
.HasAnnotation("MySql:CharSet", "utf8");
b.Property<string>("Name")
.IsRequired()
.HasColumnType("varchar(255)")
.HasColumnName("name")
.UseCollation("utf8_general_ci")
.HasAnnotation("MySql:CharSet", "utf8");
b.Property<string>("OwnerId")
.IsRequired()
.HasColumnType("varchar(38)")
.HasColumnName("owner_id")
.UseCollation("utf8_general_ci")
.HasAnnotation("MySql:CharSet", "utf8");
b.Property<string>("PaymentId")
.HasColumnType("varchar(38)")
.HasColumnName("payment_id")
.UseCollation("utf8_general_ci")
.HasAnnotation("MySql:CharSet", "utf8");
b.Property<bool>("Spam")
.ValueGeneratedOnAdd()
.HasColumnType("tinyint(1)")
.HasColumnName("spam")
.HasDefaultValueSql("true");
b.Property<int>("Status")
.HasColumnType("int")
.HasColumnName("status");
b.Property<DateTime?>("StatusChanged")
.HasColumnType("datetime")
.HasColumnName("statuschanged");
b.Property<string>("TimeZone")
.HasColumnType("varchar(50)")
.HasColumnName("timezone")
.UseCollation("utf8_general_ci")
.HasAnnotation("MySql:CharSet", "utf8");
b.Property<int>("TrustedDomainsEnabled")
.ValueGeneratedOnAdd()
.HasColumnType("int")
.HasColumnName("trusteddomainsenabled")
.HasDefaultValueSql("'1'");
b.Property<string>("TrustedDomainsRaw")
.HasColumnType("varchar(1024)")
.HasColumnName("trusteddomains")
.UseCollation("utf8_general_ci")
.HasAnnotation("MySql:CharSet", "utf8");
b.Property<int>("Version")
.ValueGeneratedOnAdd()
.HasColumnType("int")
.HasColumnName("version")
.HasDefaultValueSql("'2'");
b.Property<DateTime?>("Version_Changed")
.HasColumnType("datetime")
.HasColumnName("version_changed");
b.HasKey("Id");
b.HasIndex("LastModified")
.HasDatabaseName("last_modified");
b.HasIndex("MappedDomain")
.HasDatabaseName("mappeddomain");
b.HasIndex("Version")
.HasDatabaseName("version");
b.ToTable("tenants_tenants", (string)null);
b.HasData(
new
{
Id = 1,
Alias = "localhost",
Calls = false,
CreationDateTime = new DateTime(2021, 3, 9, 17, 46, 59, 97, DateTimeKind.Utc).AddTicks(4317),
LastModified = new DateTime(1, 1, 1, 0, 0, 0, 0, DateTimeKind.Unspecified),
Name = "Web Office",
OwnerId = "66faa6e4-f133-11ea-b126-00ffeec8b4ef",
Spam = false,
Status = 0,
TrustedDomainsEnabled = 0,
Version = 0
});
});
modelBuilder.Entity("ASC.Files.Core.EF.DbFile", b =>
{
@ -75,10 +337,6 @@ namespace ASC.Files.Core.Migrations.PostgreSql.FilesDbContextPostgreSql
.HasColumnType("int")
.HasColumnName("file_status");
b.Property<int>("FolderId")
.HasColumnType("int")
.HasColumnName("folder_id");
b.Property<int>("Forcesave")
.HasColumnType("int")
.HasColumnName("forcesave");
@ -94,7 +352,11 @@ namespace ASC.Files.Core.Migrations.PostgreSql.FilesDbContextPostgreSql
.HasColumnType("datetime")
.HasColumnName("modified_on");
b.Property<int>("Thumb")
b.Property<int>("ParentId")
.HasColumnType("int")
.HasColumnName("folder_id");
b.Property<int>("ThumbnailStatus")
.HasColumnType("int")
.HasColumnName("thumb");
@ -114,16 +376,16 @@ namespace ASC.Files.Core.Migrations.PostgreSql.FilesDbContextPostgreSql
b.HasKey("TenantId", "Id", "Version")
.HasName("PRIMARY");
b.HasIndex("FolderId")
.HasDatabaseName("folder_id");
b.HasIndex("Id")
.HasDatabaseName("id");
b.HasIndex("ModifiedOn")
.HasDatabaseName("modified_on");
b.ToTable("files_file");
b.HasIndex("ParentId")
.HasDatabaseName("folder_id");
b.ToTable("files_file", (string)null);
});
modelBuilder.Entity("ASC.Files.Core.EF.DbFilesBunchObjects", b =>
@ -151,7 +413,41 @@ namespace ASC.Files.Core.Migrations.PostgreSql.FilesDbContextPostgreSql
b.HasIndex("LeftNode")
.HasDatabaseName("left_node");
b.ToTable("files_bunch_objects");
b.ToTable("files_bunch_objects", (string)null);
});
modelBuilder.Entity("ASC.Files.Core.EF.DbFilesLink", b =>
{
b.Property<int>("TenantId")
.HasColumnType("int")
.HasColumnName("tenant_id");
b.Property<string>("SourceId")
.HasColumnType("varchar(32)")
.HasColumnName("source_id")
.UseCollation("utf8_general_ci")
.HasAnnotation("MySql:CharSet", "utf8");
b.Property<string>("LinkedId")
.HasColumnType("varchar(32)")
.HasColumnName("linked_id")
.UseCollation("utf8_general_ci")
.HasAnnotation("MySql:CharSet", "utf8");
b.Property<string>("LinkedFor")
.IsRequired()
.HasColumnType("char(38)")
.HasColumnName("linked_for")
.UseCollation("utf8_general_ci")
.HasAnnotation("MySql:CharSet", "utf8");
b.HasKey("TenantId", "SourceId", "LinkedId")
.HasName("PRIMARY");
b.HasIndex("TenantId", "SourceId", "LinkedId", "LinkedFor")
.HasDatabaseName("linked_for");
b.ToTable("files_link", (string)null);
});
modelBuilder.Entity("ASC.Files.Core.EF.DbFilesSecurity", b =>
@ -183,7 +479,7 @@ namespace ASC.Files.Core.Migrations.PostgreSql.FilesDbContextPostgreSql
.UseCollation("utf8_general_ci")
.HasAnnotation("MySql:CharSet", "utf8");
b.Property<int>("Security")
b.Property<int>("Share")
.HasColumnType("int")
.HasColumnName("security");
@ -202,7 +498,7 @@ namespace ASC.Files.Core.Migrations.PostgreSql.FilesDbContextPostgreSql
b.HasIndex("TenantId", "EntryType", "EntryId", "Owner")
.HasDatabaseName("tenant_id");
b.ToTable("files_security");
b.ToTable("files_security", (string)null);
});
modelBuilder.Entity("ASC.Files.Core.EF.DbFilesTag", b =>
@ -212,10 +508,6 @@ namespace ASC.Files.Core.Migrations.PostgreSql.FilesDbContextPostgreSql
.HasColumnType("int")
.HasColumnName("id");
b.Property<int>("Flag")
.HasColumnType("int")
.HasColumnName("flag");
b.Property<string>("Name")
.IsRequired()
.HasColumnType("varchar(255)")
@ -234,12 +526,16 @@ namespace ASC.Files.Core.Migrations.PostgreSql.FilesDbContextPostgreSql
.HasColumnType("int")
.HasColumnName("tenant_id");
b.Property<int>("Type")
.HasColumnType("int")
.HasColumnName("flag");
b.HasKey("Id");
b.HasIndex("TenantId", "Owner", "Name", "Flag")
b.HasIndex("TenantId", "Owner", "Name", "Type")
.HasDatabaseName("name");
b.ToTable("files_tag");
b.ToTable("files_tag", (string)null);
});
modelBuilder.Entity("ASC.Files.Core.EF.DbFilesTagLink", b =>
@ -262,6 +558,10 @@ namespace ASC.Files.Core.Migrations.PostgreSql.FilesDbContextPostgreSql
.HasColumnType("int")
.HasColumnName("entry_type");
b.Property<int>("Count")
.HasColumnType("int")
.HasColumnName("tag_count");
b.Property<string>("CreateBy")
.HasColumnType("char(38)")
.HasColumnName("create_by")
@ -272,10 +572,6 @@ namespace ASC.Files.Core.Migrations.PostgreSql.FilesDbContextPostgreSql
.HasColumnType("datetime")
.HasColumnName("create_on");
b.Property<int>("TagCount")
.HasColumnType("int")
.HasColumnName("tag_count");
b.HasKey("TenantId", "TagId", "EntryId", "EntryType")
.HasName("PRIMARY");
@ -285,7 +581,7 @@ namespace ASC.Files.Core.Migrations.PostgreSql.FilesDbContextPostgreSql
b.HasIndex("TenantId", "EntryId", "EntryType")
.HasDatabaseName("entry_id");
b.ToTable("files_tag_link");
b.ToTable("files_tag_link", (string)null);
});
modelBuilder.Entity("ASC.Files.Core.EF.DbFilesThirdpartyAccount", b =>
@ -299,9 +595,14 @@ namespace ASC.Files.Core.Migrations.PostgreSql.FilesDbContextPostgreSql
.HasColumnType("datetime")
.HasColumnName("create_on");
b.Property<string>("FolderId")
.HasColumnType("text")
.HasColumnName("folder_id")
.UseCollation("utf8_general_ci")
.HasAnnotation("MySql:CharSet", "utf8");
b.Property<int>("FolderType")
.HasColumnType("int")
.HasColumnName("folder_type");
.HasColumnType("folder_type");
b.Property<string>("Password")
.IsRequired()
@ -319,6 +620,10 @@ namespace ASC.Files.Core.Migrations.PostgreSql.FilesDbContextPostgreSql
.UseCollation("utf8_general_ci")
.HasAnnotation("MySql:CharSet", "utf8");
b.Property<int>("RootFolderType")
.HasColumnType("int")
.HasColumnName("root_folder_type");
b.Property<int>("TenantId")
.HasColumnType("int")
.HasColumnName("tenant_id");
@ -358,7 +663,7 @@ namespace ASC.Files.Core.Migrations.PostgreSql.FilesDbContextPostgreSql
b.HasKey("Id");
b.ToTable("files_thirdparty_account");
b.ToTable("files_thirdparty_account", (string)null);
});
modelBuilder.Entity("ASC.Files.Core.EF.DbFilesThirdpartyApp", b =>
@ -394,7 +699,7 @@ namespace ASC.Files.Core.Migrations.PostgreSql.FilesDbContextPostgreSql
b.HasKey("UserId", "App")
.HasName("PRIMARY");
b.ToTable("files_thirdparty_app");
b.ToTable("files_thirdparty_app", (string)null);
});
modelBuilder.Entity("ASC.Files.Core.EF.DbFilesThirdpartyIdMapping", b =>
@ -422,7 +727,7 @@ namespace ASC.Files.Core.Migrations.PostgreSql.FilesDbContextPostgreSql
b.HasIndex("TenantId", "HashId")
.HasDatabaseName("index_1");
b.ToTable("files_thirdparty_id_mapping");
b.ToTable("files_thirdparty_id_mapping", (string)null);
});
modelBuilder.Entity("ASC.Files.Core.EF.DbFolder", b =>
@ -489,7 +794,7 @@ namespace ASC.Files.Core.Migrations.PostgreSql.FilesDbContextPostgreSql
b.HasIndex("TenantId", "ParentId")
.HasDatabaseName("parent_id");
b.ToTable("files_folder");
b.ToTable("files_folder", (string)null);
});
modelBuilder.Entity("ASC.Files.Core.EF.DbFolderTree", b =>
@ -512,7 +817,7 @@ namespace ASC.Files.Core.Migrations.PostgreSql.FilesDbContextPostgreSql
b.HasIndex("FolderId")
.HasDatabaseName("folder_id");
b.ToTable("files_folder_tree");
b.ToTable("files_folder_tree", (string)null);
});
#pragma warning restore 612, 618
}

View File

@ -789,6 +789,33 @@ namespace ASC.Files.Core.Resources {
}
}
/// <summary>
/// Looks up a localized string similar to You don&apos;t have enough permission to archive the room.
/// </summary>
public static string ErrorMessage_ArchiveRoom {
get {
return ResourceManager.GetString("ErrorMessage_ArchiveRoom", resourceCulture);
}
}
/// <summary>
/// Looks up a localized string similar to You don&apos;t have enough permission to archive the room.
/// </summary>
public static string ErrorMessage_UnarchiveRoom {
get {
return ResourceManager.GetString("ErrorMessage_UnarchiveRoom", resourceCulture);
}
}
/// <summary>
/// Looks up a localized string similar to You cannot edit archived rooms.
/// </summary>
public static string ErrorMessage_UpdateArchivedRoom {
get {
return ResourceManager.GetString("ErrorMessage_UpdateArchivedRoom", resourceCulture);
}
}
/// <summary>
/// Looks up a localized string similar to Everyone.
/// </summary>

View File

@ -301,6 +301,15 @@
<data name="ErrorMassage_ViewTrashItem" xml:space="preserve">
<value>You are not allowed to preview the elements in the Trash</value>
</data>
<data name="ErrorMessage_ArchiveRoom" xml:space="preserve">
<value>You don't have enough permission to archive the room</value>
</data>
<data name="ErrorMessage_UnarchiveRoom" xml:space="preserve">
<value>You don't have enough permission to archive the room</value>
</data>
<data name="ErrorMessage_UpdateArchivedRoom" xml:space="preserve">
<value>You cannot edit archived rooms</value>
</data>
<data name="Everyone" xml:space="preserve">
<value>Everyone</value>
</data>

View File

@ -60,6 +60,15 @@ namespace ASC.Files.Core.Resources {
}
}
/// <summary>
/// Looks up a localized string similar to Archive.
/// </summary>
public static string Archive {
get {
return ResourceManager.GetString("Archive", resourceCulture);
}
}
/// <summary>
/// Looks up a localized string similar to Common.
/// </summary>
@ -149,5 +158,14 @@ namespace ASC.Files.Core.Resources {
return ResourceManager.GetString("Trash", resourceCulture);
}
}
/// <summary>
/// Looks up a localized string similar to VirtualRooms.
/// </summary>
public static string VirtualRooms {
get {
return ResourceManager.GetString("VirtualRooms", resourceCulture);
}
}
}
}

View File

@ -1,5 +1,64 @@
<?xml version="1.0" encoding="utf-8"?>
<root>
<!--
Microsoft ResX Schema
Version 2.0
The primary goals of this format is to allow a simple XML format
that is mostly human readable. The generation and parsing of the
various data types are done through the TypeConverter classes
associated with the data types.
Example:
... ado.net/XML headers & schema ...
<resheader name="resmimetype">text/microsoft-resx</resheader>
<resheader name="version">2.0</resheader>
<resheader name="reader">System.Resources.ResXResourceReader, System.Windows.Forms, ...</resheader>
<resheader name="writer">System.Resources.ResXResourceWriter, System.Windows.Forms, ...</resheader>
<data name="Name1"><value>this is my long string</value><comment>this is a comment</comment></data>
<data name="Color1" type="System.Drawing.Color, System.Drawing">Blue</data>
<data name="Bitmap1" mimetype="application/x-microsoft.net.object.binary.base64">
<value>[base64 mime encoded serialized .NET Framework object]</value>
</data>
<data name="Icon1" type="System.Drawing.Icon, System.Drawing" mimetype="application/x-microsoft.net.object.bytearray.base64">
<value>[base64 mime encoded string representing a byte array form of the .NET Framework object]</value>
<comment>This is a comment</comment>
</data>
There are any number of "resheader" rows that contain simple
name/value pairs.
Each data row contains a name, and value. The row also contains a
type or mimetype. Type corresponds to a .NET class that support
text/value conversion through the TypeConverter architecture.
Classes that don't support this are serialized and stored with the
mimetype set.
The mimetype is used for serialized objects, and tells the
ResXResourceReader how to depersist the object. This is currently not
extensible. For a given mimetype the value must be set accordingly:
Note - application/x-microsoft.net.object.binary.base64 is the format
that the ResXResourceWriter will generate, however the reader can
read any of the formats listed below.
mimetype: application/x-microsoft.net.object.binary.base64
value : The object must be serialized with
: System.Runtime.Serialization.Formatters.Binary.BinaryFormatter
: and then encoded with base64 encoding.
mimetype: application/x-microsoft.net.object.soap.base64
value : The object must be serialized with
: System.Runtime.Serialization.Formatters.Soap.SoapFormatter
: and then encoded with base64 encoding.
mimetype: application/x-microsoft.net.object.bytearray.base64
value : The object must be serialized into a byte array
: using a System.ComponentModel.TypeConverter
: and then encoded with base64 encoding.
-->
<xsd:schema id="root" xmlns="" xmlns:xsd="http://www.w3.org/2001/XMLSchema" xmlns:msdata="urn:schemas-microsoft-com:xml-msdata">
<xsd:import namespace="http://www.w3.org/XML/1998/namespace" />
<xsd:element name="root" msdata:IsDataSet="true">
@ -58,6 +117,9 @@
<resheader name="writer">
<value>System.Resources.ResXResourceWriter, System.Windows.Forms, Version=6.0.2.0, Culture=neutral, PublicKeyToken=b77a5c561934e089</value>
</resheader>
<data name="Archive" xml:space="preserve">
<value>Archive</value>
</data>
<data name="CorporateFiles" xml:space="preserve">
<value>Common</value>
</data>
@ -88,4 +150,7 @@
<data name="Trash" xml:space="preserve">
<value>Trash</value>
</data>
<data name="VirtualRooms" xml:space="preserve">
<value>VirtualRooms</value>
</data>
</root>

View File

@ -355,9 +355,11 @@ public class DocumentServiceHelper
return null;
}
#pragma warning disable CS0618 // Type or member is obsolete
var encoder = new JwtEncoder(new HMACSHA256Algorithm(),
new JwtSerializer(),
new JwtBase64UrlEncoder());
#pragma warning restore CS0618 // Type or member is obsolete
return encoder.Encode(payload, _fileUtility.SignatureSecret);

View File

@ -113,18 +113,23 @@ class FileDeleteOperation<T> : FileOperation<FileDeleteOperationData<T>, T>
private async Task DeleteFoldersAsync(IEnumerable<T> folderIds, IServiceScope scope, bool isNeedSendActions = false)
{
var scopeClass = scope.ServiceProvider.GetService<FileDeleteOperationScope>();
var (fileMarker, filesMessageService) = scopeClass;
var (fileMarker, filesMessageService, roomLogoManager) = scopeClass;
foreach (var folderId in folderIds)
{
CancellationToken.ThrowIfCancellationRequested();
var folder = await FolderDao.GetFolderAsync(folderId);
var isRoom = DocSpaceHelper.IsRoom(folder.FolderType);
T canCalculate = default;
if (folder == null)
{
Error = FilesCommonResource.ErrorMassage_FolderNotFound;
}
else if (folder.FolderType != FolderType.DEFAULT && folder.FolderType != FolderType.BUNCH)
else if (folder.FolderType != FolderType.DEFAULT && folder.FolderType != FolderType.BUNCH
&& folder.FolderType != FolderType.FillingFormsRoom && folder.FolderType != FolderType.EditingRoom
&& folder.FolderType != FolderType.ReviewRoom && folder.FolderType != FolderType.ReadOnlyRoom
&& folder.FolderType != FolderType.CustomRoom)
{
Error = FilesCommonResource.ErrorMassage_SecurityException_DeleteFolder;
}
@ -143,6 +148,16 @@ class FileDeleteOperation<T> : FileOperation<FileDeleteOperationData<T>, T>
{
if (ProviderDao != null)
{
if (folder.RootFolderType == FolderType.VirtualRooms || folder.RootFolderType == FolderType.Archive)
{
var providerInfo = await ProviderDao.GetProviderInfoAsync(folder.ProviderId);
if (providerInfo.FolderId != null)
{
await roomLogoManager.DeleteAsync(providerInfo.FolderId);
}
}
await ProviderDao.RemoveProviderInfoAsync(folder.ProviderId);
if (isNeedSendActions)
{
@ -165,8 +180,26 @@ class FileDeleteOperation<T> : FileOperation<FileDeleteOperationData<T>, T>
if (await FolderDao.IsEmptyAsync(folder.Id))
{
if (isRoom)
{
await roomLogoManager.DeleteAsync(folder.Id);
}
await FolderDao.DeleteFolderAsync(folder.Id);
filesMessageService.Send(folder, _headers, MessageAction.FolderDeleted, folder.Title);
if (isRoom)
{
if (folder.ProviderEntry)
{
await ProviderDao.UpdateProviderInfoAsync(folder.ProviderId, null, FolderType.DEFAULT);
}
filesMessageService.Send(folder, _headers, MessageAction.RoomDeleted, folder.Title);
}
else
{
filesMessageService.Send(folder, _headers, MessageAction.FolderDeleted, folder.Title);
}
ProcessedFolder(folderId);
}
@ -184,9 +217,18 @@ class FileDeleteOperation<T> : FileOperation<FileDeleteOperationData<T>, T>
if (immediately)
{
await FolderDao.DeleteFolderAsync(folder.Id);
if (isNeedSendActions)
{
filesMessageService.Send(folder, _headers, MessageAction.FolderDeleted, folder.Title);
if (isRoom)
{
await roomLogoManager.DeleteAsync(folder.Id);
filesMessageService.Send(folder, _headers, MessageAction.RoomDeleted, folder.Title);
}
else
{
filesMessageService.Send(folder, _headers, MessageAction.FolderDeleted, folder.Title);
}
}
}
else
@ -212,7 +254,7 @@ class FileDeleteOperation<T> : FileOperation<FileDeleteOperationData<T>, T>
var scopeClass = scope.ServiceProvider.GetService<FileDeleteOperationScope>();
var socketManager = scope.ServiceProvider.GetService<SocketManager>();
var (fileMarker, filesMessageService) = scopeClass;
var (fileMarker, filesMessageService, _) = scopeClass;
foreach (var fileId in fileIds)
{
CancellationToken.ThrowIfCancellationRequested();
@ -245,7 +287,7 @@ class FileDeleteOperation<T> : FileOperation<FileDeleteOperationData<T>, T>
{
await FileDao.SaveThumbnailAsync(file, null, size.Width, size.Height);
}
}
}
socketManager.DeleteFile(file);
}
@ -322,16 +364,20 @@ public class FileDeleteOperationScope
{
private readonly FileMarker _fileMarker;
private readonly FilesMessageService _filesMessageService;
private readonly RoomLogoManager _roomLogoManager;
public FileDeleteOperationScope(FileMarker fileMarker, FilesMessageService filesMessageService)
public FileDeleteOperationScope(FileMarker fileMarker, FilesMessageService filesMessageService, RoomLogoManager roomLogoManager)
{
_fileMarker = fileMarker;
_filesMessageService = filesMessageService;
_roomLogoManager = roomLogoManager;
_roomLogoManager.EnableAudit = false;
}
public void Deconstruct(out FileMarker fileMarker, out FilesMessageService filesMessageService)
public void Deconstruct(out FileMarker fileMarker, out FilesMessageService filesMessageService, out RoomLogoManager roomLogoManager)
{
fileMarker = _fileMarker;
filesMessageService = _filesMessageService;
roomLogoManager = _roomLogoManager;
}
}

View File

@ -164,7 +164,7 @@ class FileDownloadOperation<T> : FileOperation<FileDownloadOperationData<T>, T>
{
private readonly Dictionary<T, string> _files;
private readonly IDictionary<string, StringValues> _headers;
private readonly ItemNameValueCollection<T> _entriesPathId;
private ItemNameValueCollection<T> _entriesPathId;
public override FileOperationType OperationType => FileOperationType.Download;
public FileDownloadOperation(IServiceProvider serviceProvider, FileDownloadOperationData<T> fileDownloadOperationData)
@ -181,7 +181,7 @@ class FileDownloadOperation<T> : FileOperation<FileDownloadOperationData<T>, T>
return;
}
var (entriesPathId, filesForSend, folderForSend) = await GetEntriesPathIdAsync(scope);
(_entriesPathId, var filesForSend, var folderForSend) = await GetEntriesPathIdAsync(scope);
if (_entriesPathId == null || _entriesPathId.Count == 0)
{
@ -193,7 +193,7 @@ class FileDownloadOperation<T> : FileOperation<FileDownloadOperationData<T>, T>
throw new DirectoryNotFoundException(FilesCommonResource.ErrorMassage_FolderNotFound);
}
Total = entriesPathId.Count + 1;
Total = _entriesPathId.Count + 1;
ReplaceLongPath(_entriesPathId);

View File

@ -106,6 +106,7 @@ class FileMarkAsReadOperation<T> : FileOperation<FileMarkAsReadOperationData<T>,
await globalFolder.GetFolderCommonAsync(fileMarker, daoFactory),
await globalFolder.GetFolderShareAsync(daoFactory),
await globalFolder.GetFolderProjectsAsync(daoFactory),
await globalFolder.GetFolderVirtualRoomsAsync(daoFactory),
};
if (PrivacyRoomSettings.GetEnabled(settingsManager))

Some files were not shown because too many files have changed in this diff Show More