Merge branch 'master' into feature/files

# Conflicts:
#	products/ASC.Files/Core/Core/Dao/TeamlabDao/FileDao.cs
#	products/ASC.Files/Core/Core/Dao/TeamlabDao/FolderDao.cs
#	products/ASC.Files/Core/Core/FileStorageService.cs
#	products/ASC.Files/Server/Controllers/FilesController.cs
This commit is contained in:
pavelbannov 2020-09-28 12:29:33 +03:00
commit 2c1d473314
231 changed files with 11840 additions and 5121 deletions

View File

@ -66,6 +66,8 @@ Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "ASC.Data.Storage.Migration"
EndProject
Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "ASC.Data.Storage.Encryption", "common\services\ASC.Data.Storage.Encryption\ASC.Data.Storage.Encryption.csproj", "{17A05AE2-21C8-4C1C-B422-6AB80F13F63E}"
EndProject
Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "ASC.TelegramService", "common\services\ASC.TelegramService\ASC.TelegramService.csproj", "{95CE7371-17B6-4EEE-8E38-2FDE6347E955}"
EndProject
Global
GlobalSection(SolutionConfigurationPlatforms) = preSolution
Debug|Any CPU = Debug|Any CPU
@ -192,6 +194,10 @@ Global
{17A05AE2-21C8-4C1C-B422-6AB80F13F63E}.Debug|Any CPU.Build.0 = Debug|Any CPU
{17A05AE2-21C8-4C1C-B422-6AB80F13F63E}.Release|Any CPU.ActiveCfg = Release|Any CPU
{17A05AE2-21C8-4C1C-B422-6AB80F13F63E}.Release|Any CPU.Build.0 = Release|Any CPU
{95CE7371-17B6-4EEE-8E38-2FDE6347E955}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
{95CE7371-17B6-4EEE-8E38-2FDE6347E955}.Debug|Any CPU.Build.0 = Debug|Any CPU
{95CE7371-17B6-4EEE-8E38-2FDE6347E955}.Release|Any CPU.ActiveCfg = Release|Any CPU
{95CE7371-17B6-4EEE-8E38-2FDE6347E955}.Release|Any CPU.Build.0 = Release|Any CPU
EndGlobalSection
GlobalSection(SolutionProperties) = preSolution
HideSolutionNode = FALSE

View File

@ -0,0 +1,2 @@
echo "RUN ASC.TelegramService"
call dotnet run --project ..\..\common\services\ASC.TelegramService\ASC.TelegramService.csproj --no-build --$STORAGE_ROOT=..\..\Data --log__dir=..\..\Logs --log__name=telegram

View File

@ -40,6 +40,7 @@
</PackageReference>
<PackageReference Include="JWT" Version="6.1.4" />
<PackageReference Include="log4net" Version="2.0.8" />
<PackageReference Include="Microsoft.AspNetCore.Cryptography.KeyDerivation" Version="3.1.8" />
<PackageReference Include="Microsoft.AspNetCore.Http" Version="2.2.2" />
<PackageReference Include="Microsoft.AspNetCore.Http.Abstractions" Version="2.2.0" />
<PackageReference Include="Microsoft.AspNetCore.Http.Extensions" Version="2.2.0" />

View File

@ -121,9 +121,19 @@ namespace ASC.Common.Logging
{
_lastCleanDate = DateTime.UtcNow.Date;
Clean();
}
base.Write(logEvents);
}
var buffer = new List<AsyncLogEventInfo>();
foreach (var logEvent in logEvents)
{
buffer.Add(logEvent);
if (buffer.Count < 10) continue;
base.Write(buffer);
buffer.Clear();
}
base.Write(buffer);
}
protected override void Write(LogEventInfo logEvent)

View File

@ -0,0 +1,108 @@
/*
*
* (c) Copyright Ascensio System Limited 2010-2018
*
* This program is freeware. You can redistribute it and/or modify it under the terms of the GNU
* General Public License (GPL) version 3 as published by the Free Software Foundation (https://www.gnu.org/copyleft/gpl.html).
* In accordance with Section 7(a) of the GNU GPL its Section 15 shall be amended to the effect that
* Ascensio System SIA expressly excludes the warranty of non-infringement of any third-party rights.
*
* THIS PROGRAM IS DISTRIBUTED WITHOUT ANY WARRANTY; WITHOUT EVEN THE IMPLIED WARRANTY OF MERCHANTABILITY OR
* FITNESS FOR A PARTICULAR PURPOSE. For more details, see GNU GPL at https://www.gnu.org/copyleft/gpl.html
*
* You can contact Ascensio System SIA by email at sales@onlyoffice.com
*
* The interactive user interfaces in modified source and object code versions of ONLYOFFICE must display
* Appropriate Legal Notices, as required under Section 5 of the GNU GPL version 3.
*
* Pursuant to Section 7 § 3(b) of the GNU GPL you must retain the original ONLYOFFICE logo which contains
* relevant author attributions when distributing the software. If the display of the logo in its graphic
* form is not reasonably feasible for technical reasons, you must include the words "Powered by ONLYOFFICE"
* in every copy of the program you distribute.
* Pursuant to Section 7 § 3(e) we decline to grant you any rights under trademark law for use of our trademarks.
*
*/
using System;
using System.Text;
using ASC.Common;
using Microsoft.AspNetCore.Cryptography.KeyDerivation;
using Microsoft.Extensions.Configuration;
namespace ASC.Security.Cryptography
{
public class PasswordHasher
{
public PasswordHasher(IConfiguration configuration, MachinePseudoKeys machinePseudoKeys)
{
if (!int.TryParse(configuration["core:password:size"], out var size)) size = 256;
PasswordHashSize = size;
if (!int.TryParse(configuration["core.password.iterations"], out var iterations)) iterations = 100000;
PasswordHashIterations = iterations;
PasswordHashSalt = (configuration["core:password:salt"] ?? "").Trim();
if (string.IsNullOrEmpty(PasswordHashSalt))
{
var salt = Hasher.Hash("{9450BEF7-7D9F-4E4F-A18A-971D8681722D}", HashAlg.SHA256);
var PasswordHashSaltBytes = KeyDerivation.Pbkdf2(
Encoding.UTF8.GetString(machinePseudoKeys.GetMachineConstant()),
salt,
KeyDerivationPrf.HMACSHA256,
PasswordHashIterations,
PasswordHashSize / 8);
PasswordHashSalt = BitConverter.ToString(PasswordHashSaltBytes).Replace("-", string.Empty).ToLower();
}
}
public int PasswordHashSize
{
get;
private set;
}
public int PasswordHashIterations
{
get;
private set;
}
public string PasswordHashSalt
{
get;
private set;
}
public string GetClientPassword(string password)
{
if (string.IsNullOrWhiteSpace(password)) password = Guid.NewGuid().ToString();
var salt = new UTF8Encoding(false).GetBytes(PasswordHashSalt);
var hashBytes = KeyDerivation.Pbkdf2(
password,
salt,
KeyDerivationPrf.HMACSHA256,
PasswordHashIterations,
PasswordHashSize / 8);
var hash = BitConverter.ToString(hashBytes).Replace("-", string.Empty).ToLower();
return hash;
}
}
public static class PasswordHasherExtension
{
public static DIHelper AddPasswordHasherService(this DIHelper services)
{
services.TryAddSingleton<PasswordHasher>();
return services.AddMachinePseudoKeysService();
}
}
}

View File

@ -63,18 +63,11 @@ namespace ASC.Common.Utils
}
public static T Read<T>(string signature, string secret)
{
return Read<T>(signature, secret, true);
}
public static T Read<T>(string signature, string secret, bool useSecret)
{
try
{
var payloadParts = Encoding.UTF8.GetString(WebEncoders.Base64UrlDecode(signature)).Split('?');
if (!useSecret || GetHashBase64(payloadParts[1] + secret) == payloadParts[0]
|| GetHashBase64MD5(payloadParts[1] + secret) == payloadParts[0] //todo: delete
)
if (GetHashBase64(payloadParts[1] + secret) == payloadParts[0])
{
//Sig correct
return JsonConvert.DeserializeObject<T>(payloadParts[1]);

View File

@ -700,7 +700,8 @@ namespace ASC.Common.Web
AddMimeMapping(".wcm", "application/vnd.ms-works");
AddMimeMapping(".wdb", "application/vnd.ms-works");
AddMimeMapping(".web", "application/vnd.xara");
AddMimeMapping(".webm", "video/webm");
AddMimeMapping(".webm", "video/webm");
AddMimeMapping(".webp", "image/webp");
AddMimeMapping(".wiz", "application/msword");
AddMimeMapping(".wk1", "application/x-123");
AddMimeMapping(".wks", "application/vnd.ms-works");

View File

@ -30,10 +30,13 @@
<ItemGroup>
<None Remove="protos\AzRecordCache.proto" />
<None Remove="protos\ConsumerCacheItem.proto" />
<None Remove="protos\CreateClientProto.proto" />
<None Remove="protos\DisableClientProto.proto" />
<None Remove="protos\GroupCacheItem.proto" />
<None Remove="protos\NotifyInvoke.proto" />
<None Remove="protos\NotifyMessage.proto" />
<None Remove="protos\QuotaCacheItem.proto" />
<None Remove="protos\RegisterUserProto.proto" />
<None Remove="protos\SettingsCacheItem.proto" />
<None Remove="protos\SubscriptionMethodCache.proto" />
<None Remove="protos\SubscriptionRecord.proto" />
@ -57,10 +60,14 @@
<PackageReference Include="Microsoft.EntityFrameworkCore.Relational" Version="3.1.5" />
<PackageReference Include="Pomelo.EntityFrameworkCore.MySql" Version="3.1.1" />
<PackageReference Include="System.Text.Json" Version="4.7.2" />
<PackageReference Include="Telegram.Bot" Version="15.7.1" />
</ItemGroup>
<ItemGroup>
<Protobuf Include="protos\CreateClientProto.proto" />
<Protobuf Include="protos\NotifyInvoke.proto" />
<Protobuf Include="protos\NotifyMessage.proto" />
<Protobuf Include="protos\DisableClientProto.proto" />
<Protobuf Include="protos\RegisterUserProto.proto" />
<Protobuf Include="protos\SettingsCacheItem.proto" />
<Protobuf Include="protos\ConsumerCacheItem.proto" />
<Protobuf Include="protos\TenantCacheItem.proto" />

View File

@ -223,6 +223,10 @@ namespace ASC.Core.Common
//--remove redundant slashes
var uri = new Uri(url);
if (uri.Scheme == "mailto")
return uri.OriginalString;
var baseUri = new UriBuilder(uri.Scheme, uri.Host, uri.Port).Uri;
baseUri = uri.Segments.Aggregate(baseUri, (current, segment) => new Uri(current, segment));
//--

View File

@ -43,7 +43,11 @@ namespace ASC.Core.Billing
//[Obsolete]
public bool WhiteLabel { get; set; }
public bool Customization { get; set; }
public bool Customization { get; set; }
public bool Branding { get; set; }
public bool SSBranding { get; set; }
[JsonPropertyName("end_date")]
public DateTime DueDate { get; set; }
@ -60,7 +64,8 @@ namespace ASC.Core.Billing
public string CustomerId { get; set; }
public string Signature { get; set; }
public bool? DiscEncryption { get; set; }
public static License Parse(string licenseString)
{

View File

@ -41,7 +41,7 @@ namespace ASC.Core.Billing
public class LicenseReader
{
private readonly ILog Log;
private readonly string LicensePath;
public readonly string LicensePath;
private readonly string LicensePathTemp;
public const string CustomerIdKey = "CustomerId";
@ -60,7 +60,7 @@ namespace ASC.Core.Billing
PaymentManager = paymentManager;
CoreSettings = coreSettings;
Configuration = configuration;
LicensePath = Configuration["license:file:path"];
LicensePath = Configuration["license:file:path"] ?? "";
LicensePathTemp = LicensePath + ".tmp";
Log = options.CurrentValue;
}
@ -199,52 +199,62 @@ namespace ASC.Core.Billing
private void LicenseToDB(License license)
{
Validate(license);
CustomerId = license.CustomerId;
var defaultQuota = TenantManager.GetTenantQuota(Tenant.DEFAULT_TENANT);
var quota = new TenantQuota(-1000)
{
ActiveUsers = license.ActiveUsers,
MaxFileSize = defaultQuota.MaxFileSize,
MaxTotalSize = defaultQuota.MaxTotalSize,
Name = "license",
HasDomain = true,
Audit = true,
ControlPanel = true,
HealthCheck = true,
Ldap = true,
Sso = true,
WhiteLabel = license.WhiteLabel || license.Customization,
Update = true,
Support = true,
Trial = license.Trial,
CountPortals = license.PortalCount,
};
TenantManager.SaveTenantQuota(quota);
if (defaultQuota.CountPortals != license.PortalCount)
{
defaultQuota.CountPortals = license.PortalCount;
TenantManager.SaveTenantQuota(defaultQuota);
}
var tariff = new Tariff
{
QuotaId = quota.Id,
DueDate = license.DueDate,
};
PaymentManager.SetTariff(-1, tariff);
if (!string.IsNullOrEmpty(license.AffiliateId))
{
var tenant = TenantManager.GetCurrentTenant();
tenant.AffiliateId = license.AffiliateId;
TenantManager.SaveTenant(tenant);
Validate(license);
CustomerId = license.CustomerId;
var defaultQuota = TenantManager.GetTenantQuota(Tenant.DEFAULT_TENANT);
var quota = new TenantQuota(-1000)
{
ActiveUsers = license.ActiveUsers,
MaxFileSize = defaultQuota.MaxFileSize,
MaxTotalSize = defaultQuota.MaxTotalSize,
Name = "license",
DocsEdition = true,
HasDomain = true,
Audit = true,
ControlPanel = true,
HealthCheck = true,
Ldap = true,
Sso = true,
Customization = license.Customization,
WhiteLabel = license.WhiteLabel || license.Customization,
Branding = license.Branding,
SSBranding = license.SSBranding,
Update = true,
Support = true,
Trial = license.Trial,
CountPortals = license.PortalCount,
DiscEncryption = license.DiscEncryption ?? !license.Trial,
PrivacyRoom = !license.Trial,
};
if (defaultQuota.Name != "overdue" && !defaultQuota.Trial)
{
quota.WhiteLabel |= defaultQuota.WhiteLabel;
quota.Branding |= defaultQuota.Branding;
quota.SSBranding |= defaultQuota.SSBranding;
quota.DiscEncryption |= defaultQuota.DiscEncryption;
quota.CountPortals = Math.Max(defaultQuota.CountPortals, quota.CountPortals);
}
TenantManager.SaveTenantQuota(quota);
var tariff = new Tariff
{
QuotaId = quota.Id,
DueDate = license.DueDate,
};
PaymentManager.SetTariff(-1, tariff);
if (!string.IsNullOrEmpty(license.AffiliateId))
{
var tenant = TenantManager.GetCurrentTenant();
tenant.AffiliateId = license.AffiliateId;
TenantManager.SaveTenant(tenant);
}
}
@ -275,52 +285,52 @@ namespace ASC.Core.Billing
{
// release sign is not longer requered
return _date;
//if (_date != DateTime.MinValue) return _date;
//_date = DateTime.MaxValue;
//try
//{
// var versionDate = Configuration["version:release:date"];
// var sign = Configuration["version:release:sign"];
// if (!sign.StartsWith("ASC "))
// {
// throw new Exception("sign without ASC");
// }
// var splitted = sign.Substring(4).Split(':');
// var pkey = splitted[0];
// if (pkey != versionDate)
// {
// throw new Exception("sign with different date");
// }
// var date = splitted[1];
// var orighash = splitted[2];
// var skey = Configuration["core:machinekey"];
// using (var hasher = new HMACSHA1(Encoding.UTF8.GetBytes(skey)))
// {
// var data = string.Join("\n", date, pkey);
// var hash = hasher.ComputeHash(Encoding.UTF8.GetBytes(data));
// if (WebEncoders.Base64UrlEncode(hash) != orighash && Convert.ToBase64String(hash) != orighash)
// {
// throw new Exception("incorrect hash");
// }
// }
// var year = int.Parse(versionDate.Substring(0, 4));
// var month = int.Parse(versionDate.Substring(4, 2));
// var day = int.Parse(versionDate.Substring(6, 2));
// _date = new DateTime(year, month, day);
//}
//catch (Exception ex)
//{
// Log.Error("VersionReleaseDate", ex);
//}
//return _date;
//if (_date != DateTime.MinValue) return _date;
//_date = DateTime.MaxValue;
//try
//{
// var versionDate = Configuration["version:release:date"];
// var sign = Configuration["version:release:sign"];
// if (!sign.StartsWith("ASC "))
// {
// throw new Exception("sign without ASC");
// }
// var splitted = sign.Substring(4).Split(':');
// var pkey = splitted[0];
// if (pkey != versionDate)
// {
// throw new Exception("sign with different date");
// }
// var date = splitted[1];
// var orighash = splitted[2];
//var skey = MachinePseudoKeys.GetMachineConstant();
//using (var hasher = new HMACSHA1(skey))
// {
// var data = string.Join("\n", date, pkey);
// var hash = hasher.ComputeHash(Encoding.UTF8.GetBytes(data));
// if (WebEncoders.Base64UrlEncode(hash) != orighash && Convert.ToBase64String(hash) != orighash)
// {
// throw new Exception("incorrect hash");
// }
// }
// var year = int.Parse(versionDate.Substring(0, 4));
// var month = int.Parse(versionDate.Substring(4, 2));
// var day = int.Parse(versionDate.Substring(6, 2));
// _date = new DateTime(year, month, day);
//}
//catch (Exception ex)
//{
// Log.Error("VersionReleaseDate", ex);
//}
//return _date;
}
}

View File

@ -577,16 +577,17 @@ namespace ASC.Core.Billing
{
tariff.State = TariffState.NotPaid;
if ((q == null || !q.Trial) && CoreBaseSettings.Standalone)
{
if (q != null)
{
var defaultQuota = QuotaService.GetTenantQuota(Tenant.DEFAULT_TENANT);
if (defaultQuota.CountPortals != q.CountPortals)
{
defaultQuota.CountPortals = q.CountPortals;
QuotaService.SaveTenantQuota(defaultQuota);
}
if (CoreBaseSettings.Standalone)
{
if (q != null)
{
var defaultQuota = QuotaService.GetTenantQuota(Tenant.DEFAULT_TENANT);
defaultQuota.Name = "overdue";
defaultQuota.Features = q.Features;
defaultQuota.Support = false;
QuotaService.SaveTenantQuota(defaultQuota);
}
var unlimTariff = Tariff.CreateDefault();

View File

@ -37,6 +37,7 @@ using ASC.Core.Common.EF;
using ASC.Core.Data;
using ASC.Core.Tenants;
using ASC.Core.Users;
using ASC.Security.Cryptography;
using Microsoft.Extensions.Options;
@ -283,9 +284,9 @@ namespace ASC.Core.Caching
return user;
}
public UserInfo GetUser(int tenant, string login, string passwordHash)
{
return Service.GetUser(tenant, login, passwordHash);
public UserInfo GetUserByPasswordHash(int tenant, string login, string passwordHash)
{
return Service.GetUserByPasswordHash(tenant, login, passwordHash);
}
public UserInfo SaveUser(int tenant, UserInfo user)
@ -318,15 +319,16 @@ namespace ASC.Core.Caching
CacheUserPhotoItem.Publish(new UserPhotoCacheItem { Key = UserServiceCache.GetUserPhotoCacheKey(tenant, id) }, CacheNotifyAction.Remove);
}
public string GetUserPassword(int tenant, Guid id)
{
return Service.GetUserPassword(tenant, id);
}
public DateTime GetUserPasswordStamp(int tenant, Guid id)
{
return Service.GetUserPasswordStamp(tenant, id);
}
public void SetUserPasswordHash(int tenant, Guid id, string passwordHash)
{
Service.SetUserPasswordHash(tenant, id, passwordHash);
}
public void SetUserPassword(int tenant, Guid id, string password)
{
Service.SetUserPassword(tenant, id, password);
}
public IDictionary<Guid, Group> GetGroups(int tenant, DateTime from)
@ -535,7 +537,8 @@ namespace ASC.Core.Caching
services
.AddCoreSettingsService()
.AddLoggerService()
.AddUserDbContextService();
.AddUserDbContextService()
.AddPasswordHasherService();
}
return services;

View File

@ -39,6 +39,8 @@ namespace ASC.Core.Configuration
public static readonly string NotifyMessengerSenderSysName = "messanger.sender";
public static readonly string NotifyPushSenderSysName = "push.sender";
public static readonly string NotifyTelegramSenderSysName = "telegram.sender";
public static readonly ISystemAccount CoreSystem = new SystemAccount(new Guid("A37EE56E-3302-4a7b-B67E-DDBEA64CD032"), "asc system", true);

View File

@ -41,13 +41,15 @@ namespace ASC.Core
private readonly IUserService userService;
private UserManager UserManager { get; }
private UserFormatter UserFormatter { get; }
public AuthManager(IUserService service, UserManager userManager, UserFormatter userFormatter)
private UserFormatter UserFormatter { get; }
private TenantManager TenantManager { get; }
public AuthManager(IUserService service, UserManager userManager, UserFormatter userFormatter, TenantManager tenantManager)
{
userService = service;
UserManager = userManager;
UserFormatter = userFormatter;
UserFormatter = userFormatter;
TenantManager = tenantManager;
}
@ -56,14 +58,14 @@ namespace ASC.Core
return UserManager.GetUsers(EmployeeStatus.Active).Select(u => ToAccount(tenant.TenantId, u)).ToArray();
}
public void SetUserPassword(int tenantId, Guid userID, string password)
{
userService.SetUserPassword(tenantId, userID, password);
}
public string GetUserPasswordHash(int tenantId, Guid userID)
{
return userService.GetUserPassword(tenantId, userID);
public void SetUserPasswordHash(Guid userID, string passwordHash)
{
userService.SetUserPasswordHash(TenantManager.GetCurrentTenant().TenantId, userID, passwordHash);
}
public DateTime GetUserPasswordStamp(Guid userID)
{
return userService.GetUserPasswordStamp(TenantManager.GetCurrentTenant().TenantId, userID);
}
public IAccount GetAccountByID(int tenantId, Guid id)

View File

@ -93,7 +93,12 @@ namespace ASC.Core
public Invoice GetPaymentInvoice(string paymentId)
{
return tariffService.GetInvoice(paymentId);
}
}
public IDictionary<string, IEnumerable<Tuple<string, decimal>>> GetProductPriceInfo(params string[] productIds)
{
return tariffService.GetProductPriceInfo(productIds);
}
public Uri GetShoppingUri(int tenant, int quotaId, string currency = null, string language = null, string customerId = null)
{

View File

@ -205,9 +205,9 @@ namespace ASC.Core
return u != null && !u.Removed ? u : Constants.LostUser;
}
public UserInfo GetUsers(int tenant, string login, string passwordHash)
{
var u = UserService.GetUser(tenant, login, passwordHash);
public UserInfo GetUsersByPasswordHash(int tenant, string login, string passwordHash)
{
var u = UserService.GetUserByPasswordHash(tenant, login, passwordHash);
return u != null && !u.Removed ? u : Constants.LostUser;
}

View File

@ -44,7 +44,6 @@ using ASC.Core.Security.Authentication;
using ASC.Core.Security.Authorizing;
using ASC.Core.Tenants;
using ASC.Core.Users;
using ASC.Security.Cryptography;
using Microsoft.AspNetCore.Http;
using Microsoft.Extensions.Options;
@ -112,13 +111,13 @@ namespace ASC.Core
}
public string AuthenticateMe(string login, string password)
public string AuthenticateMe(string login, string passwordHash)
{
if (login == null) throw new ArgumentNullException("login");
if (password == null) throw new ArgumentNullException("password");
if (passwordHash == null) throw new ArgumentNullException("passwordHash");
var tenantid = TenantManager.GetCurrentTenant().TenantId;
var u = UserManager.GetUsers(tenantid, login, Hasher.Base64Hash(password, HashAlg.SHA256));
var u = UserManager.GetUsersByPasswordHash(tenantid, login, passwordHash);
return AuthenticateMe(new UserAccount(u, tenantid, UserFormatter));
}
@ -140,7 +139,7 @@ namespace ASC.Core
}
log.InfoFormat("Empty Bearer cookie: {0} {1}", ipFrom, address);
}
else if (CookieStorage.DecryptCookie(cookie, out var tenant, out var userid, out var login, out var password, out var indexTenant, out var expire, out var indexUser))
else if (CookieStorage.DecryptCookie(cookie, out var tenant, out var userid, out var indexTenant, out var expire, out var indexUser))
{
if (tenant != TenantManager.GetCurrentTenant().TenantId)
{
@ -160,36 +159,27 @@ namespace ASC.Core
try
{
if (userid != Guid.Empty)
var settingsUser = TenantCookieSettingsHelper.GetForUser(userid);
if (indexUser != settingsUser.Index)
{
var settingsUser = TenantCookieSettingsHelper.GetForUser(userid);
if (indexUser != settingsUser.Index)
{
return false;
}
return false;
}
AuthenticateMe(new UserAccount(new UserInfo { ID = userid }, tenant, UserFormatter));
AuthenticateMe(new UserAccount(new UserInfo { ID = userid }, tenant, UserFormatter));
}
else
{
AuthenticateMe(login, password);
}
return true;
}
catch (InvalidCredentialException ice)
{
log.DebugFormat("{0}: cookie {1}, tenant {2}, userid {3}, login {4}, pass {5}",
ice.Message, cookie, tenant, userid, login, password);
log.DebugFormat("{0}: cookie {1}, tenant {2}, userid {3}", ice.Message, cookie, tenant, userid);
}
catch (SecurityException se)
{
log.DebugFormat("{0}: cookie {1}, tenant {2}, userid {3}, login {4}, pass {5}",
se.Message, cookie, tenant, userid, login, password);
log.DebugFormat("{0}: cookie {1}, tenant {2}, userid {3}", se.Message, cookie, tenant, userid);
}
catch (Exception err)
{
log.ErrorFormat("Authenticate error: cookie {0}, tenant {1}, userid {2}, login {3}, pass {4}: {5}",
cookie, tenant, userid, login, password, err);
log.ErrorFormat("Authenticate error: cookie {0}, tenant {1}, userid {2}, : {3}", cookie, tenant, userid, err);
}
}
else
@ -280,9 +270,23 @@ namespace ASC.Core
AuthContext.Logout();
}
public void SetUserPassword(Guid userID, string password)
public void SetUserPasswordHash(Guid userID, string passwordHash)
{
Authentication.SetUserPassword(TenantManager.GetCurrentTenant().TenantId, userID, password);
var tenantid = TenantManager.GetCurrentTenant().TenantId;
var u = UserManager.GetUsersByPasswordHash(tenantid, userID.ToString(), passwordHash);
if (!Equals(u, Users.Constants.LostUser))
{
throw new PasswordException("A new password must be used");
}
Authentication.SetUserPasswordHash(userID, passwordHash);
}
public class PasswordException : Exception
{
public PasswordException(string message) : base(message)
{
}
}
}

View File

@ -30,6 +30,7 @@ using System.Reflection;
using ASC.Common.Caching;
using ASC.Common.Logging;
using ASC.Core.Common.Notify;
using ASC.Core.Notify;
using ASC.Core.Notify.Senders;
using ASC.Core.Tenants;
@ -102,12 +103,14 @@ namespace ASC.Core
var configuration = serviceProvider.GetService<IConfiguration>();
var cacheNotify = serviceProvider.GetService<ICacheNotify<NotifyMessage>>();
var cacheInvoke = serviceProvider.GetService<ICacheNotify<NotifyInvoke>>();
var options = serviceProvider.GetService<IOptionsMonitor<ILog>>();
var options = serviceProvider.GetService<IOptionsMonitor<ILog>>();
var telegramHelper = serviceProvider.GetService<TelegramHelper>();
NotifyContext = new NotifyContext(serviceProvider);
INotifySender jabberSender = new NotifyServiceSender(cacheNotify, cacheInvoke);
INotifySender emailSender = new NotifyServiceSender(cacheNotify, cacheInvoke);
INotifySender telegramSender = new TelegramSender(options, telegramHelper);
var postman = configuration["core:notify:postman"];
@ -133,8 +136,9 @@ namespace ASC.Core
emailSender.Init(properties);
}
NotifyContext.NotifyService.RegisterSender(Constants.NotifyEMailSenderSysName, new EmailSenderSink(emailSender, serviceProvider));
NotifyContext.NotifyService.RegisterSender(Constants.NotifyEMailSenderSysName, new EmailSenderSink(emailSender, serviceProvider, options));
NotifyContext.NotifyService.RegisterSender(Constants.NotifyMessengerSenderSysName, new JabberSenderSink(jabberSender, serviceProvider));
NotifyContext.NotifyService.RegisterSender(Constants.NotifyTelegramSenderSysName, new TelegramSenderSink(telegramSender, serviceProvider));
NotifyContext.NotifyEngine.BeforeTransferRequest += NotifyEngine_BeforeTransferRequest;
NotifyContext.NotifyEngine.AfterTransferRequest += NotifyEngine_AfterTransferRequest;

View File

@ -55,7 +55,7 @@ namespace ASC.Core
UserInfo GetUser(int tenant, Guid id, Expression<Func<User, UserInfo>> exp);
UserInfo GetUser(int tenant, string login, string passwordHash);
UserInfo GetUserByPasswordHash(int tenant, string login, string passwordHash);
UserInfo SaveUser(int tenant, UserInfo user);
@ -65,9 +65,9 @@ namespace ASC.Core
void SetUserPhoto(int tenant, Guid id, byte[] photo);
string GetUserPassword(int tenant, Guid id);
void SetUserPassword(int tenant, Guid id, string password);
DateTime GetUserPasswordStamp(int tenant, Guid id);
void SetUserPasswordHash(int tenant, Guid id, string passwordHash);
IDictionary<Guid, Group> GetGroups(int tenant, DateTime from);

View File

@ -37,7 +37,8 @@ using ASC.Core.Common.EF.Model;
using ASC.Core.Common.Settings;
using ASC.Core.Tenants;
using Microsoft.Extensions.Options;
using Microsoft.Extensions.DependencyInjection;
using Microsoft.Extensions.Options;
namespace ASC.Core.Data
{
@ -148,7 +149,7 @@ namespace ASC.Core.Data
private Guid? currentUserID;
private Guid CurrentUserID
{
get { return (currentUserID ?? (currentUserID = AuthContext.CurrentAccount.ID)).Value; }
get { return ((Guid?)(currentUserID ??= AuthContext.CurrentAccount.ID)).Value; }
}
public bool SaveSettings<T>(T settings, int tenantId) where T : ISettings
@ -227,7 +228,7 @@ namespace ASC.Core.Data
internal T LoadSettingsFor<T>(int tenantId, Guid userId) where T : class, ISettings
{
var settingsInstance = Activator.CreateInstance<T>();
var settingsInstance = ActivatorUtilities.CreateInstance<T>(ServiceProvider);
var key = settingsInstance.ID.ToString() + tenantId + userId;
var def = (T)settingsInstance.GetDefault(ServiceProvider);

View File

@ -28,12 +28,14 @@ using System;
using System.Collections.Generic;
using System.Linq;
using System.Linq.Expressions;
using System.Text;
using ASC.Core.Common.EF;
using ASC.Core.Common.EF.Context;
using ASC.Core.Common.EF.Model;
using ASC.Core.Tenants;
using ASC.Core.Users;
using ASC.Security.Cryptography;
using Microsoft.EntityFrameworkCore;
using Microsoft.Extensions.Options;
@ -71,7 +73,7 @@ namespace ASC.Core.Data
private List<string> forbiddenDomains;
internal TenantDomainValidator TenantDomainValidator { get; set; }
public MachinePseudoKeys MachinePseudoKeys { get; }
internal TenantDbContext TenantDbContext { get; set; }
public Expression<Func<DbTenant, Tenant>> FromDbTenantToTenant { get; set; }
@ -109,10 +111,15 @@ namespace ASC.Core.Data
FromTenantUserToTenant = r => fromDbTenantToTenant(r.DbTenant);
}
public DbTenantService(DbContextManager<TenantDbContext> dbContextManager, TenantDomainValidator tenantDomainValidator) : this()
public DbTenantService(
DbContextManager<TenantDbContext> dbContextManager,
TenantDomainValidator tenantDomainValidator,
MachinePseudoKeys machinePseudoKeys)
: this()
{
TenantDbContext = dbContextManager.Value;
TenantDomainValidator = tenantDomainValidator;
MachinePseudoKeys = machinePseudoKeys;
}
public void ValidateDomain(string domain)
@ -141,32 +148,82 @@ namespace ASC.Core.Data
public IEnumerable<Tenant> GetTenants(string login, string passwordHash)
{
if (string.IsNullOrEmpty(login)) throw new ArgumentNullException("login");
var q = TenantsQuery()
.Where(r => r.Status == TenantStatus.Active)
.Join(TenantDbContext.Users, r => r.Id, r => r.Tenant, (tenant, user) => new
{
tenant,
user
})
.Join(TenantDbContext.UserSecurity, r => r.user.Id, r => r.UserId, (tenantUser, security) => new TenantUserSecurity
{
DbTenant = tenantUser.tenant,
User = tenantUser.user,
UserSecurity = security
})
.Where(r => r.User.Status == EmployeeStatus.Active)
.Where(r => r.User.Removed == false)
.Where(r => login.Contains('@') ? r.User.Email == login : r.User.Id.ToString() == login);
Func<IQueryable<TenantUserSecurity>> query = () => TenantsQuery()
.Where(r => r.Status == TenantStatus.Active)
.Join(TenantDbContext.Users, r => r.Id, r => r.Tenant, (tenant, user) => new
{
tenant,
user
})
.Join(TenantDbContext.UserSecurity, r => r.user.Id, r => r.UserId, (tenantUser, security) => new TenantUserSecurity
{
DbTenant = tenantUser.tenant,
User = tenantUser.user,
UserSecurity = security
})
.Where(r => r.User.Status == EmployeeStatus.Active)
.Where(r => r.DbTenant.Status == TenantStatus.Active)
.Where(r => r.User.Removed == false);
if (passwordHash != null)
if (passwordHash == null)
{
q.Where(r => r.UserSecurity.PwdHash == passwordHash);
var q = query()
.Where(r => login.Contains('@') ? r.User.Email == login : r.User.Id.ToString() == login);
return q.Select(FromTenantUserToTenant).ToList();
}
return q.Select(FromTenantUserToTenant).ToList();
if (Guid.TryParse(login, out var userId))
{
var pwdHash = GetPasswordHash(userId, passwordHash);
var oldHash = Hasher.Base64Hash(passwordHash, HashAlg.SHA256);
var q = query()
.Where(r => r.User.Id == userId)
.Where(r => r.UserSecurity.PwdHash == pwdHash || r.UserSecurity.PwdHash == oldHash) //todo: remove old scheme
;
return q.Select(FromTenantUserToTenant).ToList();
}
else
{
var oldHash = Hasher.Base64Hash(passwordHash, HashAlg.SHA256);
var q =
query()
.Where(r => r.UserSecurity.PwdHash == oldHash);
if (login.Contains('@'))
{
q = q.Where(r => r.User.Email == login);
}
else if (Guid.TryParse(login, out var uId))
{
q = q.Where(r => r.User.Id == uId);
}
//old password
var result = q.Select(FromTenantUserToTenant).ToList();
var usersQuery = TenantDbContext.Users
.Where(r => r.Email == login)
.Where(r => r.Status == EmployeeStatus.Active)
.Where(r => !r.Removed)
.Select(r => r.Id)
.ToList();
var passwordHashs = usersQuery.Select(r => GetPasswordHash(r, passwordHash)).ToList();
q = query()
.Where(r => passwordHashs.Any(p => r.UserSecurity.PwdHash == p));
//new password
result = result.Concat(q.Select(FromTenantUserToTenant)).ToList();
result.Distinct();
return result;
}
}
public Tenant GetTenant(int id)
@ -450,6 +507,11 @@ namespace ASC.Core.Data
throw new TenantAlreadyExistsException("Address busy.", existsTenants);
}
}
protected string GetPasswordHash(Guid userId, string password)
{
return Hasher.Base64Hash(password + userId + Encoding.UTF8.GetString(MachinePseudoKeys.GetMachineConstant()), HashAlg.SHA512);
}
}

View File

@ -28,6 +28,7 @@ using System;
using System.Collections.Generic;
using System.Linq;
using System.Linq.Expressions;
using System.Text;
using ASC.Core.Common.EF;
using ASC.Core.Tenants;
@ -66,6 +67,7 @@ namespace ASC.Core.Data
public class EFUserService : IUserService
{
public Expression<Func<User, UserInfo>> FromUserToUserInfo { get; set; }
public Expression<Func<DbUserSecurity, UserInfo>> FromDbUserSecurityToUserInfo { get; set; }
public Func<UserInfo, User> FromUserInfoToUser { get; set; }
public Expression<Func<DbGroup, Group>> FromDbGroupToGroup { get; set; }
public Func<Group, DbGroup> FromGroupToDbGroup { get; set; }
@ -74,7 +76,8 @@ namespace ASC.Core.Data
internal UserDbContext UserDbContext { get; set; }
internal DbContextManager<UserDbContext> UserDbContextManager { get; set; }
private PasswordHasher PasswordHasher { get; }
public MachinePseudoKeys MachinePseudoKeys { get; }
internal string DbId { get; set; }
public EFUserService()
@ -108,6 +111,9 @@ namespace ASC.Core.Data
Contacts = user.Contacts
};
var fromUserToUserInfo = FromUserToUserInfo.Compile();
FromDbUserSecurityToUserInfo = r => fromUserToUserInfo(r.User);
FromUserInfoToUser = user => new User
{
ActivationStatus = user.ActivationStatus,
@ -141,8 +147,8 @@ namespace ASC.Core.Data
{
Id = group.Id,
Name = group.Name,
CategoryId = group.CategoryId.HasValue ? group.CategoryId.Value : Guid.Empty,
ParentId = group.ParentId.HasValue ? group.ParentId.Value : Guid.Empty,
CategoryId = group.CategoryId ?? Guid.Empty,
ParentId = group.ParentId ?? Guid.Empty,
Sid = group.Sid,
Removed = group.Removed,
LastModified = group.LastModified,
@ -182,9 +188,11 @@ namespace ASC.Core.Data
};
}
public EFUserService(DbContextManager<UserDbContext> userDbContextManager) : this()
public EFUserService(DbContextManager<UserDbContext> userDbContextManager, PasswordHasher passwordHasher, MachinePseudoKeys machinePseudoKeys) : this()
{
UserDbContextManager = userDbContextManager;
PasswordHasher = passwordHasher;
MachinePseudoKeys = machinePseudoKeys;
UserDbContext = UserDbContextManager.Value;
}
@ -211,28 +219,78 @@ namespace ASC.Core.Data
.FirstOrDefault();
}
public UserInfo GetUser(int tenant, string login, string passwordHash)
public UserInfo GetUserByPasswordHash(int tenant, string login, string passwordHash)
{
if (string.IsNullOrEmpty(login)) throw new ArgumentNullException("login");
var q = UserDbContext.Users
.Where(r => !r.Removed)
.Where(r => r.UserSecurity.PwdHash == passwordHash);
if (login.Contains('@'))
if (Guid.TryParse(login, out var userId))
{
q = q.Where(r => r.Email == login);
RegeneratePassword(tenant, userId);
var pwdHash = GetPasswordHash(userId, passwordHash);
var oldHash = Hasher.Base64Hash(passwordHash, HashAlg.SHA256);
var q = UserDbContext.Users
.Where(r => !r.Removed)
.Where(r => r.Id == userId)
.Join(UserDbContext.UserSecurity, r => r.Id, r => r.UserId, (user, security) => new DbUserSecurity
{
User = user,
UserSecurity = security
})
.Where(r => r.UserSecurity.PwdHash == pwdHash || r.UserSecurity.PwdHash == oldHash) //todo: remove old scheme
;
if (tenant != Tenant.DEFAULT_TENANT)
{
q = q.Where(r => r.User.Tenant == tenant);
}
return q.Select(FromDbUserSecurityToUserInfo).FirstOrDefault();
}
else if (Guid.TryParse(login, out var userId))
else
{
q = q.Where(r => r.Id == userId);
}
var q = UserDbContext.Users
.Where(r => !r.Removed)
.Where(r => r.Email == login)
;
if (tenant != Tenant.DEFAULT_TENANT)
{
q = q.Where(r => r.Tenant == tenant);
}
var user = q.Select(FromUserToUserInfo).FirstOrDefault();
if (user != null)
{
RegeneratePassword(tenant, user.ID);
if (tenant != Tenant.DEFAULT_TENANT)
{
q = q.Where(r => r.Tenant == tenant);
}
var pwdHash = GetPasswordHash(user.ID, passwordHash);
var oldHash = Hasher.Base64Hash(passwordHash, HashAlg.SHA256);
return q.Select(FromUserToUserInfo).FirstOrDefault();
var count = UserDbContext.UserSecurity
.Where(r => r.UserId == user.ID)
.Where(r => r.PwdHash == pwdHash || r.PwdHash == oldHash)
.Count();//todo: remove old scheme
if (count > 0) return user;
}
return null;
}
}
//todo: remove
private void RegeneratePassword(int tenant, Guid userId)
{
var h2 = UserDbContext.UserSecurity
.Where(r => r.Tenant == tenant)
.Where(r => r.UserId == userId)
.Select(r => r.PwdHashSha512)
.FirstOrDefault();
if (string.IsNullOrEmpty(h2)) return;
var password = Crypto.GetV(h2, 1, false);
var passwordHash = PasswordHasher.GetClientPassword(password);
SetUserPasswordHash(tenant, userId, passwordHash);
}
public IDictionary<string, UserGroupRef> GetUserGroupRefs(int tenant, DateTime from)
@ -252,14 +310,15 @@ namespace ASC.Core.Data
return q.Select(FromUserGroupToUserGroupRef).ToDictionary(r => r.CreateKey(), r => r);
}
public string GetUserPassword(int tenant, Guid id)
public DateTime GetUserPasswordStamp(int tenant, Guid id)
{
var h2 = UserDbContext.UserSecurity
var stamp = UserDbContext.UserSecurity
.Where(r => r.Tenant == tenant)
.Select(r => r.PwdHashSha512)
.Where(r => r.UserId == id)
.Select(r => r.LastModified)
.FirstOrDefault();
return !string.IsNullOrEmpty(h2) ? Crypto.GetV(h2, 1, false) : null;
return stamp ?? DateTime.MinValue;
}
public byte[] GetUserPhoto(int tenant, Guid id)
@ -508,16 +567,16 @@ namespace ASC.Core.Data
return r;
}
public void SetUserPassword(int tenant, Guid id, string password)
public void SetUserPasswordHash(int tenant, Guid id, string passwordHash)
{
var h1 = !string.IsNullOrEmpty(password) ? Hasher.Base64Hash(password, HashAlg.SHA256) : null;
var h2 = !string.IsNullOrEmpty(password) ? Crypto.GetV(password, 1, true) : null;
var h1 = GetPasswordHash(id, passwordHash);
var us = new UserSecurity
{
Tenant = tenant,
UserId = id,
PwdHash = h1,
PwdHashSha512 = h2
PwdHashSha512 = null //todo: remove
};
UserDbContext.AddOrUpdate(r => r.UserSecurity, us);
@ -693,5 +752,16 @@ namespace ASC.Core.Data
.Select(exp ?? FromUserToUserInfo)
.FirstOrDefault();
}
protected string GetPasswordHash(Guid userId, string password)
{
return Hasher.Base64Hash(password + userId + Encoding.UTF8.GetString(MachinePseudoKeys.GetMachineConstant()), HashAlg.SHA512);
}
}
public class DbUserSecurity
{
public User User { get; set; }
public UserSecurity UserSecurity { get; set; }
}
}

View File

@ -0,0 +1,32 @@

using ASC.Common;
using ASC.Core.Common.EF.Model;
using Microsoft.EntityFrameworkCore;
namespace ASC.Core.Common.EF.Context
{
public class TelegramDbContext : BaseDbContext
{
public DbSet<TelegramUser> Users { get; set; }
public TelegramDbContext() { }
public TelegramDbContext(DbContextOptions<TelegramDbContext> options)
: base(options)
{
}
protected override void OnModelCreating(ModelBuilder modelBuilder)
{
modelBuilder.AddTelegramUsers();
}
}
public static class TelegramDbContextExtension
{
public static DIHelper AddTelegramDbContextService(this DIHelper services)
{
return services.AddDbContextManagerService<TelegramDbContext>();
}
}
}

View File

@ -30,5 +30,6 @@ namespace ASC.Core.Common.EF.Model
[Column("creation_date")]
public DateTime CreationDate { get; set; }
public string Attachments { get; set; }
public string AutoSubmitted { get; set; }
}
}

View File

@ -0,0 +1,36 @@
using System;
using System.ComponentModel.DataAnnotations.Schema;
using Microsoft.EntityFrameworkCore;
namespace ASC.Core.Common.EF.Model
{
[Table("telegram_users")]
public class TelegramUser : BaseEntity
{
[Column("portal_user_id")]
public Guid PortalUserId { get; set; }
[Column("tenant_id")]
public int TenantId { get; set; }
[Column("telegram_user_id")]
public int TelegramUserId { get; set; }
public override object[] GetKeys()
{
return new object[] { TenantId, PortalUserId };
}
}
public static class TelegramUsersExtension
{
public static ModelBuilder AddTelegramUsers(this ModelBuilder modelBuilder)
{
modelBuilder.Entity<TelegramUser>()
.HasKey(c => new { c.TenantId, c.PortalUserId });
return modelBuilder;
}
}
}

View File

@ -16,6 +16,8 @@ namespace ASC.Core.Common.EF
public string PwdHashSha512 { get; set; }
public DateTime? LastModified { get; set; }
public override object[] GetKeys()
{
return new object[] { UserId };

View File

@ -36,7 +36,6 @@ using ASC.Core.Data;
using ASC.Core.Security.Authentication;
using ASC.Core.Tenants;
using ASC.Core.Users;
using ASC.Security.Cryptography;
using Microsoft.Extensions.Options;
@ -134,14 +133,13 @@ namespace ASC.Core
return FindTenants(login, null);
}
public List<Tenant> FindTenants(string login, string password)
{
var hash = !string.IsNullOrEmpty(password) ? Hasher.Base64Hash(password, HashAlg.SHA256) : null;
if (hash != null && UserService.GetUser(Tenant.DEFAULT_TENANT, login, hash) == null)
public List<Tenant> FindTenants(string login, string passwordHash)
{
if (!string.IsNullOrEmpty(passwordHash) && UserService.GetUserByPasswordHash(Tenant.DEFAULT_TENANT, login, passwordHash) == null)
{
throw new SecurityException("Invalid login or password.");
}
return TenantService.GetTenants(login, hash).Select(AddRegion).ToList();
return TenantService.GetTenants(login, passwordHash).Select(AddRegion).ToList();
}
public Tenant GetTenant(string domain)
@ -167,9 +165,9 @@ namespace ASC.Core
if (string.IsNullOrEmpty(ri.Email)) throw new Exception("Account email can not be empty");
if (ri.FirstName == null) throw new Exception("Account firstname can not be empty");
if (ri.LastName == null) throw new Exception("Account lastname can not be empty");
if (!UserFormatter.IsValidUserName(ri.FirstName, ri.LastName)) throw new Exception("Incorrect firstname or lastname");
if (string.IsNullOrEmpty(ri.Password)) ri.Password = Crypto.GeneratePassword(6);
if (!UserFormatter.IsValidUserName(ri.FirstName, ri.LastName)) throw new Exception("Incorrect firstname or lastname");
if (string.IsNullOrEmpty(ri.PasswordHash)) ri.PasswordHash = Guid.NewGuid().ToString();
// create tenant
tenant = new Tenant(ri.Address.ToLowerInvariant())
@ -200,14 +198,15 @@ namespace ASC.Core
ActivationStatus = ri.ActivationStatus
};
user = UserService.SaveUser(tenant.TenantId, user);
UserService.SetUserPassword(tenant.TenantId, user.ID, ri.Password);
UserService.SetUserPasswordHash(tenant.TenantId, user.ID, ri.PasswordHash);
UserService.SaveUserGroupRef(tenant.TenantId, new UserGroupRef(user.ID, Constants.GroupAdmin.ID, UserGroupRefType.Contains));
// save tenant owner
tenant.OwnerId = user.ID;
tenant = TenantService.SaveTenant(CoreSettings, tenant);
SettingsManager.SaveSettings(new TenantAnalyticsSettings() { Analytics = ri.Analytics }, tenant.TenantId);
SettingsManager.SaveSettings(new TenantAnalyticsSettings() { Analytics = ri.Analytics }, tenant.TenantId);
SettingsManager.SaveSettings(new TenantControlPanelSettings { LimitedAccess = ri.LimitedControlPanel }, tenant.TenantId);
}
public Tenant SaveTenant(Tenant tenant)
@ -220,27 +219,20 @@ namespace ASC.Core
TenantService.RemoveTenant(tenant.TenantId);
}
public string CreateAuthenticationCookie(CookieStorage cookieStorage, int tenantId, string login, string password)
{
var passwordhash = Hasher.Base64Hash(password, HashAlg.SHA256);
var u = UserService.GetUser(tenantId, login, passwordhash);
return u != null ? CreateAuthenticationCookie(cookieStorage, tenantId, u.ID, login, passwordhash) : null;
}
public string CreateAuthenticationCookie(CookieStorage cookieStorage, int tenantId, Guid userId)
{
var u = UserService.GetUser(tenantId, userId);
var password = UserService.GetUserPassword(tenantId, userId);
var passwordhash = Hasher.Base64Hash(password, HashAlg.SHA256);
return u != null ? CreateAuthenticationCookie(cookieStorage, tenantId, userId, u.Email, passwordhash) : null;
var u = UserService.GetUser(tenantId, userId);
return CreateAuthenticationCookie(cookieStorage, tenantId, u);
}
private string CreateAuthenticationCookie(CookieStorage cookieStorage, int tenantId, Guid userId, string login, string passwordhash)
{
private string CreateAuthenticationCookie(CookieStorage cookieStorage, int tenantId, UserInfo user)
{
if (user == null) return null;
var tenantSettings = SettingsManager.LoadSettingsFor<TenantCookieSettings>(tenantId, Guid.Empty);
var expires = tenantSettings.IsDefault() ? DateTime.UtcNow.AddYears(1) : DateTime.UtcNow.AddMinutes(tenantSettings.LifeTime);
var userSettings = SettingsManager.LoadSettingsFor<TenantCookieSettings>(tenantId, userId);
return cookieStorage.EncryptCookie(tenantId, userId, login, passwordhash, tenantSettings.Index, expires, userSettings.Index);
var userSettings = SettingsManager.LoadSettingsFor<TenantCookieSettings>(tenantId, user.ID);
return cookieStorage.EncryptCookie(tenantId, user.ID, tenantSettings.Index, expires, userSettings.Index);
}
public Tariff GetTariff(int tenant, bool withRequestToPaymentSystem = true)

View File

@ -35,6 +35,7 @@ using ASC.Common.Utils;
using ASC.Core.Billing;
using ASC.Core.Security.Authentication;
using ASC.Core.Tenants;
using ASC.Security.Cryptography;
using Microsoft.EntityFrameworkCore;
using Microsoft.Extensions.Configuration;
@ -52,18 +53,21 @@ namespace ASC.Core
private IConfiguration Configuraion { get; }
private CookieStorage CookieStorage { get; }
private EFLoggerFactory LoggerFactory { get; }
private PasswordHasher PasswordHasher { get; }
private IOptionsSnapshot<HostedSolution> HostedSolutionOptions { get; }
public MultiRegionHostedSolution(string dbid,
IConfiguration configuraion,
CookieStorage cookieStorage,
EFLoggerFactory loggerFactory,
PasswordHasher passwordHasher,
IOptionsSnapshot<HostedSolution> hostedSolutionOptions)
{
this.dbid = dbid;
Configuraion = configuraion;
CookieStorage = cookieStorage;
LoggerFactory = loggerFactory;
PasswordHasher = passwordHasher;
HostedSolutionOptions = hostedSolutionOptions;
Initialize();
}
@ -80,7 +84,7 @@ namespace ASC.Core
return FindTenants(login, null);
}
public List<Tenant> FindTenants(string login, string password)
public List<Tenant> FindTenants(string login, string password, string passwordHash = null)
{
var result = new List<Tenant>();
Exception error = null;
@ -88,8 +92,12 @@ namespace ASC.Core
foreach (var service in GetRegionServices())
{
try
{
result.AddRange(service.FindTenants(login, password));
{
if (string.IsNullOrEmpty(passwordHash) && !string.IsNullOrEmpty(password))
{
passwordHash = PasswordHasher.GetClientPassword(password);
}
result.AddRange(service.FindTenants(login, passwordHash));
}
catch (SecurityException exception)
{
@ -133,11 +141,6 @@ namespace ASC.Core
}
public string CreateAuthenticationCookie(string region, int tenantId, string login, string password)
{
return GetRegionService(region).CreateAuthenticationCookie(CookieStorage, tenantId, login, password);
}
public string CreateAuthenticationCookie(string region, int tenantId, Guid userId)
{
return GetRegionService(region).CreateAuthenticationCookie(CookieStorage, tenantId, userId);

View File

@ -47,14 +47,16 @@ namespace ASC.Core.Notify
private readonly INotifySender sender;
public EmailSenderSink(INotifySender sender, IServiceProvider serviceProvider)
public EmailSenderSink(INotifySender sender, IServiceProvider serviceProvider, IOptionsMonitor<ILog> options)
{
this.sender = sender ?? throw new ArgumentNullException("sender");
ServiceProvider = serviceProvider;
ServiceProvider = serviceProvider;
Log = options.Get("ASC.Notify");
}
private IServiceProvider ServiceProvider { get; }
private IServiceProvider ServiceProvider { get; }
private ILog Log { get; }
public override SendResponse ProcessMessage(INoticeMessage message)
{
if (message.Recipient.Addresses == null || message.Recipient.Addresses.Length == 0)
@ -146,6 +148,19 @@ namespace ASC.Core.Notify
if (attachmentTag != null && attachmentTag.Value != null)
{
m.EmbeddedAttachments.AddRange(attachmentTag.Value as NotifyMessageAttachment[]);
}
var autoSubmittedTag = message.Arguments.FirstOrDefault(x => x.Tag == "AutoSubmitted");
if (autoSubmittedTag != null && autoSubmittedTag.Value is string)
{
try
{
m.AutoSubmitted = autoSubmittedTag.Value.ToString();
}
catch (Exception e)
{
Log.Error("Error creating AutoSubmitted tag for: " + autoSubmittedTag.Value, e);
}
}
return m;

View File

@ -109,7 +109,8 @@ namespace ASC.Core.Notify
{
if (senderName == ASC.Core.Configuration.Constants.NotifyEMailSenderSysName) return new[] { user.Email };
if (senderName == ASC.Core.Configuration.Constants.NotifyMessengerSenderSysName) return new[] { user.UserName };
if (senderName == ASC.Core.Configuration.Constants.NotifyPushSenderSysName) return new[] { user.UserName };
if (senderName == ASC.Core.Configuration.Constants.NotifyPushSenderSysName) return new[] { user.UserName };
if (senderName == ASC.Core.Configuration.Constants.NotifyTelegramSenderSysName) return new[] { user.ID.ToString() };
}
}
return new string[0];

View File

@ -267,9 +267,9 @@ namespace ASC.Core.Notify.Senders
if (!string.IsNullOrEmpty(m.ReplyTo))
{
mimeMessage.ReplyTo.Add(MailboxAddress.Parse(ParserOptions.Default, m.ReplyTo));
}
mimeMessage.Headers.Add("Auto-Submitted", "auto-generated");
}
mimeMessage.Headers.Add("Auto-Submitted", string.IsNullOrEmpty(m.AutoSubmitted) ? "auto-generated" : m.AutoSubmitted);
return mimeMessage;
}

View File

@ -0,0 +1,73 @@
/*
*
* (c) Copyright Ascensio System Limited 2010-2018
*
* This program is freeware. You can redistribute it and/or modify it under the terms of the GNU
* General Public License (GPL) version 3 as published by the Free Software Foundation (https://www.gnu.org/copyleft/gpl.html).
* In accordance with Section 7(a) of the GNU GPL its Section 15 shall be amended to the effect that
* Ascensio System SIA expressly excludes the warranty of non-infringement of any third-party rights.
*
* THIS PROGRAM IS DISTRIBUTED WITHOUT ANY WARRANTY; WITHOUT EVEN THE IMPLIED WARRANTY OF MERCHANTABILITY OR
* FITNESS FOR A PARTICULAR PURPOSE. For more details, see GNU GPL at https://www.gnu.org/copyleft/gpl.html
*
* You can contact Ascensio System SIA by email at sales@onlyoffice.com
*
* The interactive user interfaces in modified source and object code versions of ONLYOFFICE must display
* Appropriate Legal Notices, as required under Section 5 of the GNU GPL version 3.
*
* Pursuant to Section 7 § 3(b) of the GNU GPL you must retain the original ONLYOFFICE logo which contains
* relevant author attributions when distributing the software. If the display of the logo in its graphic
* form is not reasonably feasible for technical reasons, you must include the words "Powered by ONLYOFFICE"
* in every copy of the program you distribute.
* Pursuant to Section 7 § 3(e) we decline to grant you any rights under trademark law for use of our trademarks.
*
*/
using System;
using System.Collections.Generic;
using System.Text.RegularExpressions;
using ASC.Common.Logging;
using ASC.Core.Common.Notify;
using ASC.Notify.Messages;
using Microsoft.Extensions.Options;
namespace ASC.Core.Notify.Senders
{
public class TelegramSender : INotifySender
{
private readonly ILog log;
private TelegramHelper TelegramHelper { get; }
public TelegramSender(IOptionsMonitor<ILog> options, TelegramHelper telegramHelper)
{
log = options.Get("ASC");
TelegramHelper = telegramHelper;
}
public void Init(IDictionary<string, string> properties)
{
}
public NoticeSendResult Send(NotifyMessage m)
{
if (!string.IsNullOrEmpty(m.Content))
{
m.Content = m.Content.Replace("\r\n", "\n").Trim('\n', '\r', ' ');
m.Content = Regex.Replace(m.Content, "\n{3,}", "\n\n");
}
try
{
TelegramHelper.SendMessage(m);
}
catch (Exception e)
{
log.ErrorFormat("Unexpected error, {0}, {1}, {2}",
e.Message, e.StackTrace, e.InnerException != null ? e.InnerException.Message : string.Empty);
}
return NoticeSendResult.OK;
}
}
}

View File

@ -35,7 +35,8 @@ using System.Text;
using ASC.Common;
using ASC.Common.Logging;
using ASC.Core.Common.Notify.Jabber;
using ASC.Security.Cryptography;
using Microsoft.Extensions.Configuration;
using Microsoft.Extensions.Options;
@ -46,18 +47,21 @@ namespace ASC.Core.Notify.Signalr
public class ConfigureSignalrServiceClient : IConfigureNamedOptions<SignalrServiceClient>
{
internal TenantManager TenantManager { get; }
internal CoreSettings CoreSettings { get; }
internal CoreSettings CoreSettings { get; }
internal MachinePseudoKeys MachinePseudoKeys { get; }
internal IConfiguration Configuration { get; }
internal IOptionsMonitor<ILog> Options { get; }
public ConfigureSignalrServiceClient(
TenantManager tenantManager,
CoreSettings coreSettings,
CoreSettings coreSettings,
MachinePseudoKeys machinePseudoKeys,
IConfiguration configuration,
IOptionsMonitor<ILog> options)
{
TenantManager = tenantManager;
CoreSettings = coreSettings;
CoreSettings = coreSettings;
MachinePseudoKeys = machinePseudoKeys;
Configuration = configuration;
Options = options;
}
@ -68,7 +72,7 @@ namespace ASC.Core.Notify.Signalr
options.hub = name.Trim('/');
options.TenantManager = TenantManager;
options.CoreSettings = CoreSettings;
options.CoreMachineKey = Configuration["core:machinekey"];
options.SKey = MachinePseudoKeys.GetMachineConstant();
options.Url = Configuration["web:hub:internal"];
options.EnableSignalr = !string.IsNullOrEmpty(options.Url);
@ -103,7 +107,7 @@ namespace ASC.Core.Notify.Signalr
internal ILog Log;
private static DateTime lastErrorTime;
public bool EnableSignalr;
internal string CoreMachineKey;
internal byte[] SKey;
internal string Url;
internal bool JabberReplaceDomain;
internal string JabberReplaceFromDomain;
@ -384,7 +388,7 @@ namespace ASC.Core.Notify.Signalr
public string CreateAuthToken(string pkey = "socketio")
{
using var hasher = new HMACSHA1(Encoding.UTF8.GetBytes(CoreMachineKey));
using var hasher = new HMACSHA1(SKey);
var now = DateTime.UtcNow.ToString("yyyyMMddHHmmss");
var hash = Convert.ToBase64String(hasher.ComputeHash(Encoding.UTF8.GetBytes(string.Join("\n", now, pkey))));
return string.Format("ASC {0}:{1}:{2}", pkey, now, hash);
@ -401,7 +405,8 @@ namespace ASC.Core.Notify.Signalr
return services
.AddTenantManagerService()
.AddCoreSettingsService();
.AddCoreSettingsService()
.AddMachinePseudoKeysService();
}
return services;

View File

@ -0,0 +1,139 @@
/*
*
* (c) Copyright Ascensio System Limited 2010-2018
*
* This program is freeware. You can redistribute it and/or modify it under the terms of the GNU
* General Public License (GPL) version 3 as published by the Free Software Foundation (https://www.gnu.org/copyleft/gpl.html).
* In accordance with Section 7(a) of the GNU GPL its Section 15 shall be amended to the effect that
* Ascensio System SIA expressly excludes the warranty of non-infringement of any third-party rights.
*
* THIS PROGRAM IS DISTRIBUTED WITHOUT ANY WARRANTY; WITHOUT EVEN THE IMPLIED WARRANTY OF MERCHANTABILITY OR
* FITNESS FOR A PARTICULAR PURPOSE. For more details, see GNU GPL at https://www.gnu.org/copyleft/gpl.html
*
* You can contact Ascensio System SIA by email at sales@onlyoffice.com
*
* The interactive user interfaces in modified source and object code versions of ONLYOFFICE must display
* Appropriate Legal Notices, as required under Section 5 of the GNU GPL version 3.
*
* Pursuant to Section 7 § 3(b) of the GNU GPL you must retain the original ONLYOFFICE logo which contains
* relevant author attributions when distributing the software. If the display of the logo in its graphic
* form is not reasonably feasible for technical reasons, you must include the words "Powered by ONLYOFFICE"
* in every copy of the program you distribute.
* Pursuant to Section 7 § 3(e) we decline to grant you any rights under trademark law for use of our trademarks.
*
*/
using System;
using System.Collections.Generic;
using System.Linq;
using ASC.Common;
using ASC.Common.Caching;
using ASC.Core.Common.EF.Context;
using ASC.Core.Common.EF.Model;
using Microsoft.Extensions.Options;
namespace ASC.Core.Common.Notify.Telegram
{
class ConfigureCachedTelegramDao : IConfigureNamedOptions<CachedTelegramDao>
{
private IOptionsSnapshot<TelegramDao> Service { get; }
public ConfigureCachedTelegramDao(IOptionsSnapshot<TelegramDao> service)
{
Service = service;
}
public void Configure(string name, CachedTelegramDao options)
{
Configure(options);
options.tgDao = Service.Get(name);
}
public void Configure(CachedTelegramDao options)
{
options.tgDao = Service.Value;
options.cache = AscCache.Memory;
options.Expiration = TimeSpan.FromMinutes(20);
options.PairKeyFormat = "tgUser:{0}:{1}";
options.SingleKeyFormat = "tgUser:{0}";
}
}
public class CachedTelegramDao
{
public TelegramDao tgDao { get; set; }
public ICache cache { get; set; }
public TimeSpan Expiration { get; set; }
public string PairKeyFormat { get; set; }
public string SingleKeyFormat { get; set; }
public void Delete(Guid userId, int tenantId)
{
cache.Remove(string.Format(PairKeyFormat, userId, tenantId));
tgDao.Delete(userId, tenantId);
}
public void Delete(int telegramId)
{
cache.Remove(string.Format(SingleKeyFormat, telegramId));
tgDao.Delete(telegramId);
}
public TelegramUser GetUser(Guid userId, int tenantId)
{
var key = string.Format(PairKeyFormat, userId, tenantId);
var user = cache.Get<TelegramUser>(key);
if (user != null) return user;
user = tgDao.GetUser(userId, tenantId);
if (user != null) cache.Insert(key, user, Expiration);
return user;
}
public List<TelegramUser> GetUser(int telegramId)
{
var key = string.Format(SingleKeyFormat, telegramId);
var users = cache.Get<List<TelegramUser>>(key);
if (users != null) return users;
users = tgDao.GetUser(telegramId);
if (users.Any()) cache.Insert(key, users, Expiration);
return users;
}
public void RegisterUser(Guid userId, int tenantId, int telegramId)
{
tgDao.RegisterUser(userId, tenantId, telegramId);
var key = string.Format(PairKeyFormat, userId, tenantId);
cache.Insert(key, new TelegramUser { PortalUserId = userId, TenantId = tenantId, TelegramUserId = telegramId }, Expiration);
}
}
public static class CachedTelegramDaoExtension
{
public static DIHelper AddCachedTelegramDaoService(this DIHelper services)
{
if (services.TryAddScoped<TelegramDao>())
{
services.TryAddScoped<IConfigureOptions<TelegramDao>, ConfigureTelegramDaoService>();
services.TryAddScoped<IConfigureOptions<CachedTelegramDao>, ConfigureCachedTelegramDao>();
services.TryAddSingleton(typeof(ICacheNotify<>), typeof(KafkaCache<>));
return services.AddTelegramDbContextService();
}
return services;
}
}
}

View File

@ -0,0 +1,125 @@
/*
*
* (c) Copyright Ascensio System Limited 2010-2018
*
* This program is freeware. You can redistribute it and/or modify it under the terms of the GNU
* General Public License (GPL) version 3 as published by the Free Software Foundation (https://www.gnu.org/copyleft/gpl.html).
* In accordance with Section 7(a) of the GNU GPL its Section 15 shall be amended to the effect that
* Ascensio System SIA expressly excludes the warranty of non-infringement of any third-party rights.
*
* THIS PROGRAM IS DISTRIBUTED WITHOUT ANY WARRANTY; WITHOUT EVEN THE IMPLIED WARRANTY OF MERCHANTABILITY OR
* FITNESS FOR A PARTICULAR PURPOSE. For more details, see GNU GPL at https://www.gnu.org/copyleft/gpl.html
*
* You can contact Ascensio System SIA by email at sales@onlyoffice.com
*
* The interactive user interfaces in modified source and object code versions of ONLYOFFICE must display
* Appropriate Legal Notices, as required under Section 5 of the GNU GPL version 3.
*
* Pursuant to Section 7 § 3(b) of the GNU GPL you must retain the original ONLYOFFICE logo which contains
* relevant author attributions when distributing the software. If the display of the logo in its graphic
* form is not reasonably feasible for technical reasons, you must include the words "Powered by ONLYOFFICE"
* in every copy of the program you distribute.
* Pursuant to Section 7 § 3(e) we decline to grant you any rights under trademark law for use of our trademarks.
*
*/
using System;
using System.Collections.Generic;
using System.Linq;
using ASC.Core.Common.EF;
using ASC.Core.Common.EF.Context;
using ASC.Core.Common.EF.Model;
using Microsoft.EntityFrameworkCore;
using Microsoft.Extensions.Options;
namespace ASC.Core.Common.Notify.Telegram
{
public class ConfigureTelegramDaoService : IConfigureNamedOptions<TelegramDao>
{
private DbContextManager<TelegramDbContext> DbContextManager { get; }
public ConfigureTelegramDaoService(DbContextManager<TelegramDbContext> dbContextManager)
{
DbContextManager = dbContextManager;
}
public void Configure(string name, TelegramDao options)
{
Configure(options);
options.TelegramDbContext = DbContextManager.Get(name);
}
public void Configure(TelegramDao options)
{
options.TelegramDbContext = DbContextManager.Value;
}
}
public class TelegramDao
{
public TelegramDbContext TelegramDbContext { get; set; }
public TelegramDao()
{
}
public TelegramDao(DbContextManager<TelegramDbContext> dbContextManager)
{
TelegramDbContext = dbContextManager.Value;
}
public void RegisterUser(Guid userId, int tenantId, int telegramId)
{
var user = new TelegramUser
{
PortalUserId = userId,
TenantId = tenantId,
TelegramUserId = telegramId
};
TelegramDbContext.AddOrUpdate(r => r.Users, user);
TelegramDbContext.SaveChanges();
}
public TelegramUser GetUser(Guid userId, int tenantId)
{
return TelegramDbContext.Users
.AsNoTracking()
.Where(r => r.PortalUserId == userId)
.Where(r => r.TenantId == tenantId)
.FirstOrDefault();
}
public List<TelegramUser> GetUser(int telegramId)
{
return TelegramDbContext.Users
.AsNoTracking()
.Where(r => r.TelegramUserId == telegramId)
.ToList();
}
public void Delete(Guid userId, int tenantId)
{
var toRemove = TelegramDbContext.Users
.Where(r => r.PortalUserId == userId)
.Where(r => r.TenantId == tenantId)
.ToList();
TelegramDbContext.Users.RemoveRange(toRemove);
TelegramDbContext.SaveChanges();
}
public void Delete(int telegramId)
{
var toRemove = TelegramDbContext.Users
.Where(r => r.TelegramUserId == telegramId)
.ToList();
TelegramDbContext.Users.RemoveRange(toRemove);
TelegramDbContext.SaveChanges();
}
}
}

View File

@ -1,4 +1,4 @@
/*
/*
*
* (c) Copyright Ascensio System Limited 2010-2018
*
@ -23,14 +23,16 @@
*
*/
namespace ASC.Web.Files.Core.Entries
namespace ASC.Core.Common.Notify.Telegram
{
public class EncryptedData
public interface ITelegramLoginProvider
{
public string PublicKey { get; set; }
string TelegramBotToken { get; }
public string FileHash { get; set; }
string TelegramBotName { get; }
public string Data { get; set; }
int TelegramAuthTokenLifespan { get; }
string TelegramProxy { get; }
}
}
}

View File

@ -1,60 +1,42 @@
/*
*
* (c) Copyright Ascensio System Limited 2010-2018
*
* This program is freeware. You can redistribute it and/or modify it under the terms of the GNU
* General Public License (GPL) version 3 as published by the Free Software Foundation (https://www.gnu.org/copyleft/gpl.html).
* In accordance with Section 7(a) of the GNU GPL its Section 15 shall be amended to the effect that
* Ascensio System SIA expressly excludes the warranty of non-infringement of any third-party rights.
*
* THIS PROGRAM IS DISTRIBUTED WITHOUT ANY WARRANTY; WITHOUT EVEN THE IMPLIED WARRANTY OF MERCHANTABILITY OR
* FITNESS FOR A PARTICULAR PURPOSE. For more details, see GNU GPL at https://www.gnu.org/copyleft/gpl.html
*
* You can contact Ascensio System SIA by email at sales@onlyoffice.com
*
* The interactive user interfaces in modified source and object code versions of ONLYOFFICE must display
* Appropriate Legal Notices, as required under Section 5 of the GNU GPL version 3.
*
* Pursuant to Section 7 § 3(b) of the GNU GPL you must retain the original ONLYOFFICE logo which contains
* relevant author attributions when distributing the software. If the display of the logo in its graphic
* form is not reasonably feasible for technical reasons, you must include the words "Powered by ONLYOFFICE"
* in every copy of the program you distribute.
* Pursuant to Section 7 § 3(e) we decline to grant you any rights under trademark law for use of our trademarks.
*
*/
namespace ASC.Data.Storage.Configuration
{
static class Schema
{
public const string SECTION_NAME = "storage";
public const string FILE_PATH = "file";
public const string APPENDERS = "appender";
public const string APPEND = "append";
public const string APPENDSECURE = "appendssl";
public const string EXTs = "exts";
public const string HANDLERS = "handler";
public const string PROPERTIES = "properties";
public const string PROPERTY = "property";
public const string MODULES = "module";
public const string TYPE = "type";
public const string NAME = "name";
public const string VALUE = "value";
public const string PATH = "path";
public const string DATA = "data";
public const string VIRTUALPATH = "virtualpath";
public const string VISIBLE = "visible";
public const string COUNT_QUOTA = "count";
public const string APPEND_TENANT_ID = "appendTenantId";
public const string ACL = "acl";
public const string EXPIRES = "expires";
public const string DOMAINS = "domain";
public const string PUBLIC = "public";
public const string DISABLEDMIGRATE = "disableMigrate";
}
}
/*
*
* (c) Copyright Ascensio System Limited 2010-2018
*
* This program is freeware. You can redistribute it and/or modify it under the terms of the GNU
* General Public License (GPL) version 3 as published by the Free Software Foundation (https://www.gnu.org/copyleft/gpl.html).
* In accordance with Section 7(a) of the GNU GPL its Section 15 shall be amended to the effect that
* Ascensio System SIA expressly excludes the warranty of non-infringement of any third-party rights.
*
* THIS PROGRAM IS DISTRIBUTED WITHOUT ANY WARRANTY; WITHOUT EVEN THE IMPLIED WARRANTY OF MERCHANTABILITY OR
* FITNESS FOR A PARTICULAR PURPOSE. For more details, see GNU GPL at https://www.gnu.org/copyleft/gpl.html
*
* You can contact Ascensio System SIA by email at sales@onlyoffice.com
*
* The interactive user interfaces in modified source and object code versions of ONLYOFFICE must display
* Appropriate Legal Notices, as required under Section 5 of the GNU GPL version 3.
*
* Pursuant to Section 7 § 3(b) of the GNU GPL you must retain the original ONLYOFFICE logo which contains
* relevant author attributions when distributing the software. If the display of the logo in its graphic
* form is not reasonably feasible for technical reasons, you must include the words "Powered by ONLYOFFICE"
* in every copy of the program you distribute.
* Pursuant to Section 7 § 3(e) we decline to grant you any rights under trademark law for use of our trademarks.
*
*/
using ASC.Notify.Messages;
namespace ASC.Core.Common.Notify
{
public interface ITelegramService
{
void SendMessage(NotifyMessage m);
void RegisterUser(string userId, int tenantId, string token);
void CreateOrUpdateClient(int tenantId, string token, int tokenLifespan, string proxy);
void DisableClient(int tenantId);
}
}

View File

@ -0,0 +1,188 @@
/*
*
* (c) Copyright Ascensio System Limited 2010-2020
*
* This program is freeware. You can redistribute it and/or modify it under the terms of the GNU
* General Public License (GPL) version 3 as published by the Free Software Foundation (https://www.gnu.org/copyleft/gpl.html).
* In accordance with Section 7(a) of the GNU GPL its Section 15 shall be amended to the effect that
* Ascensio System SIA expressly excludes the warranty of non-infringement of any third-party rights.
*
* THIS PROGRAM IS DISTRIBUTED WITHOUT ANY WARRANTY; WITHOUT EVEN THE IMPLIED WARRANTY OF MERCHANTABILITY OR
* FITNESS FOR A PARTICULAR PURPOSE. For more details, see GNU GPL at https://www.gnu.org/copyleft/gpl.html
*
* You can contact Ascensio System SIA by email at sales@onlyoffice.com
*
* The interactive user interfaces in modified source and object code versions of ONLYOFFICE must display
* Appropriate Legal Notices, as required under Section 5 of the GNU GPL version 3.
*
* Pursuant to Section 7 § 3(b) of the GNU GPL you must retain the original ONLYOFFICE logo which contains
* relevant author attributions when distributing the software. If the display of the logo in its graphic
* form is not reasonably feasible for technical reasons, you must include the words "Powered by ONLYOFFICE"
* in every copy of the program you distribute.
* Pursuant to Section 7 § 3(e) we decline to grant you any rights under trademark law for use of our trademarks.
*
*/
using System;
using System.Linq;
using System.Net;
using System.Security.Cryptography;
using ASC.Common;
using ASC.Common.Logging;
using ASC.Core.Common.Configuration;
using ASC.Core.Common.Notify.Telegram;
using ASC.Notify.Messages;
using Microsoft.Extensions.Options;
using Telegram.Bot;
namespace ASC.Core.Common.Notify
{
public class TelegramHelper
{
public enum RegStatus
{
NotRegistered,
Registered,
AwaitingConfirmation
}
private ConsumerFactory ConsumerFactory { get; }
private CachedTelegramDao CachedTelegramDao { get; }
private TelegramServiceClient TelegramServiceClient { get; }
private ILog Log { get; }
public TelegramHelper(
ConsumerFactory consumerFactory,
IOptionsSnapshot<CachedTelegramDao> cachedTelegramDao,
TelegramServiceClient telegramServiceClient,
IOptionsMonitor<ILog> options)
{
ConsumerFactory = consumerFactory;
CachedTelegramDao = cachedTelegramDao.Value;
TelegramServiceClient = telegramServiceClient;
Log = options.CurrentValue;
}
public string RegisterUser(Guid userId, int tenantId)
{
var token = GenerateToken(userId);
TelegramServiceClient.RegisterUser(userId.ToString(), tenantId, token);
return GetLink(token);
}
public void SendMessage(NotifyMessage msg)
{
TelegramServiceClient.SendMessage(msg);
}
public bool CreateClient(int tenantId, string token, int tokenLifespan, string proxy)
{
var client = InitClient(token, proxy);
if (TestingClient(client))
{
TelegramServiceClient.CreateOrUpdateClient(tenantId, token, tokenLifespan, proxy);
return true;
}
else
{
return false;
}
}
public RegStatus UserIsConnected(Guid userId, int tenantId)
{
if (CachedTelegramDao.GetUser(userId, tenantId) != null) return RegStatus.Registered;
return IsAwaitingRegistration(userId, tenantId) ? RegStatus.AwaitingConfirmation : RegStatus.NotRegistered;
}
public string CurrentRegistrationLink(Guid userId, int tenantId)
{
var token = GetCurrentToken(userId, tenantId);
if (token == null || token == "") return "";
return GetLink(token);
}
public void DisableClient(int tenantId)
{
TelegramServiceClient.DisableClient(tenantId);
}
public void Disconnect(Guid userId, int tenantId)
{
CachedTelegramDao.Delete(userId, tenantId);
}
private bool IsAwaitingRegistration(Guid userId, int tenantId)
{
return GetCurrentToken(userId, tenantId) == null ? false : true;
}
private string GetCurrentToken(Guid userId, int tenantId)
{
return TelegramServiceClient.RegistrationToken(userId.ToString(), tenantId);
}
private string GenerateToken(Guid userId)
{
var id = userId.ToByteArray();
var d = BitConverter.GetBytes(DateTime.Now.Ticks);
var buf = id.Concat(d).ToArray();
using (var sha = new SHA256CryptoServiceProvider())
{
return Convert.ToBase64String(sha.ComputeHash(buf))
.Replace('+', '-').Replace('/', '_').Replace("=", ""); // make base64 url safe
}
}
private string GetLink(string token)
{
var tgProvider = (ITelegramLoginProvider)ConsumerFactory.GetByKey("Telegram");
var botname = tgProvider == null ? default(string) : tgProvider.TelegramBotName;
if (string.IsNullOrEmpty(botname)) return null;
return string.Format("t.me/{0}?start={1}", botname, token);
}
public bool TestingClient(TelegramBotClient telegramBotClient)
{
try
{
if (!telegramBotClient.TestApiAsync().GetAwaiter().GetResult()) return false;
}
catch (Exception e)
{
Log.DebugFormat("Couldn't test api connection: {0}", e);
return false;
}
return true;
}
public TelegramBotClient InitClient(string token, string proxy)
{
return string.IsNullOrEmpty(proxy) ? new TelegramBotClient(token) : new TelegramBotClient(token, new WebProxy(proxy));
}
}
public static class TelegramHelperExtension
{
public static DIHelper AddTelegramHelperSerivce(this DIHelper services)
{
if (services.TryAddScoped<TelegramHelper>())
{
return services.AddTelegramServiceClient()
.AddCachedTelegramDaoService();
}
return services;
}
}
}

View File

@ -0,0 +1,82 @@
/*
*
* (c) Copyright Ascensio System Limited 2010-2018
*
* This program is freeware. You can redistribute it and/or modify it under the terms of the GNU
* General Public License (GPL) version 3 as published by the Free Software Foundation (https://www.gnu.org/copyleft/gpl.html).
* In accordance with Section 7(a) of the GNU GPL its Section 15 shall be amended to the effect that
* Ascensio System SIA expressly excludes the warranty of non-infringement of any third-party rights.
*
* THIS PROGRAM IS DISTRIBUTED WITHOUT ANY WARRANTY; WITHOUT EVEN THE IMPLIED WARRANTY OF MERCHANTABILITY OR
* FITNESS FOR A PARTICULAR PURPOSE. For more details, see GNU GPL at https://www.gnu.org/copyleft/gpl.html
*
* You can contact Ascensio System SIA by email at sales@onlyoffice.com
*
* The interactive user interfaces in modified source and object code versions of ONLYOFFICE must display
* Appropriate Legal Notices, as required under Section 5 of the GNU GPL version 3.
*
* Pursuant to Section 7 § 3(b) of the GNU GPL you must retain the original ONLYOFFICE logo which contains
* relevant author attributions when distributing the software. If the display of the logo in its graphic
* form is not reasonably feasible for technical reasons, you must include the words "Powered by ONLYOFFICE"
* in every copy of the program you distribute.
* Pursuant to Section 7 § 3(e) we decline to grant you any rights under trademark law for use of our trademarks.
*
*/
using System;
using ASC.Core.Notify.Senders;
using ASC.Core.Tenants;
using ASC.Notify.Messages;
using ASC.Notify.Sinks;
using Microsoft.Extensions.DependencyInjection;
namespace ASC.Core.Notify
{
class TelegramSenderSink : Sink
{
private string senderName = Configuration.Constants.NotifyTelegramSenderSysName;
private readonly INotifySender sender;
private readonly IServiceProvider serviceProvider;
public TelegramSenderSink(INotifySender sender, IServiceProvider serviceProvider)
{
this.sender = sender ?? throw new ArgumentNullException("sender");
this.serviceProvider = serviceProvider;
}
public override SendResponse ProcessMessage(INoticeMessage message)
{
try
{
var result = SendResult.OK;
var m = new NotifyMessage
{
To = message.Recipient.ID,
Subject = message.Subject,
ContentType = message.ContentType,
Content = message.Body,
Sender = senderName,
CreationDate = DateTime.UtcNow.Ticks,
};
using var scope = serviceProvider.CreateScope();
var tenantManager = scope.ServiceProvider.GetService<TenantManager>();
var tenant = tenantManager.GetCurrentTenant(false);
m.Tenant = tenant == null ? Tenant.DEFAULT_TENANT : tenant.TenantId;
sender.Send(m);
return new SendResponse(message, senderName, result);
}
catch (Exception ex)
{
return new SendResponse(message, senderName, ex);
}
}
}
}

View File

@ -0,0 +1,106 @@
/*
*
* (c) Copyright Ascensio System Limited 2010-2020
*
* This program is freeware. You can redistribute it and/or modify it under the terms of the GNU
* General Public License (GPL) version 3 as published by the Free Software Foundation (https://www.gnu.org/copyleft/gpl.html).
* In accordance with Section 7(a) of the GNU GPL its Section 15 shall be amended to the effect that
* Ascensio System SIA expressly excludes the warranty of non-infringement of any third-party rights.
*
* THIS PROGRAM IS DISTRIBUTED WITHOUT ANY WARRANTY; WITHOUT EVEN THE IMPLIED WARRANTY OF MERCHANTABILITY OR
* FITNESS FOR A PARTICULAR PURPOSE. For more details, see GNU GPL at https://www.gnu.org/copyleft/gpl.html
*
* You can contact Ascensio System SIA by email at sales@onlyoffice.com
*
* The interactive user interfaces in modified source and object code versions of ONLYOFFICE must display
* Appropriate Legal Notices, as required under Section 5 of the GNU GPL version 3.
*
* Pursuant to Section 7 § 3(b) of the GNU GPL you must retain the original ONLYOFFICE logo which contains
* relevant author attributions when distributing the software. If the display of the logo in its graphic
* form is not reasonably feasible for technical reasons, you must include the words "Powered by ONLYOFFICE"
* in every copy of the program you distribute.
* Pursuant to Section 7 § 3(e) we decline to grant you any rights under trademark law for use of our trademarks.
*
*/
using System;
using ASC.Common;
using ASC.Common.Caching;
using ASC.Notify.Messages;
namespace ASC.Core.Common.Notify
{
public class TelegramServiceClient : ITelegramService
{
private ICacheNotify<NotifyMessage> CacheMessage { get; }
private ICacheNotify<RegisterUserProto> CacheRegisterUser { get; }
private ICacheNotify<CreateClientProto> CacheCreateClient { get; }
private ICacheNotify<DisableClientProto> CacheDisableClient { get; }
private ICache Cache { get; }
public TelegramServiceClient(ICacheNotify<NotifyMessage> cacheMessage,
ICacheNotify<RegisterUserProto> cacheRegisterUser,
ICacheNotify<CreateClientProto> cacheCreateClient,
ICacheNotify<DisableClientProto> cacheDisableClient)
{
CacheMessage = cacheMessage;
CacheRegisterUser = cacheRegisterUser;
CacheCreateClient = cacheCreateClient;
CacheDisableClient = cacheDisableClient;
Cache = AscCache.Memory;
}
public void SendMessage(NotifyMessage m)
{
CacheMessage.Publish(m, CacheNotifyAction.Insert);
}
public void RegisterUser(string userId, int tenantId, string token)
{
Cache.Insert(GetCacheTokenKey(tenantId, userId), token, DateTime.MaxValue);
CacheRegisterUser.Publish(new RegisterUserProto() {
UserId = userId,
TenantId = tenantId,
Token = token
} , CacheNotifyAction.Insert);
}
public void CreateOrUpdateClient(int tenantId, string token, int tokenLifespan, string proxy)
{
CacheCreateClient.Publish(new CreateClientProto()
{
TenantId = tenantId,
Token = token,
TokenLifespan = tokenLifespan,
Proxy = proxy
}, CacheNotifyAction.Insert);
}
public void DisableClient(int tenantId)
{
CacheDisableClient.Publish(new DisableClientProto() { TenantId = tenantId }, CacheNotifyAction.Insert);
}
public string RegistrationToken(string userId, int tenantId)
{
return Cache.Get<string>(GetCacheTokenKey(tenantId, userId));
}
private string GetCacheTokenKey(int tenantId, string userId)
{
return "Token" + userId + tenantId;
}
}
public static class TelegramServiceClientExtension
{
public static DIHelper AddTelegramServiceClient(this DIHelper services)
{
services.TryAddSingleton<TelegramServiceClient>();
return services;
}
}
}

View File

@ -67,12 +67,10 @@ namespace ASC.Core.Security.Authentication
HttpContext = httpContextAccessor.HttpContext;
}
public bool DecryptCookie(string cookie, out int tenant, out Guid userid, out string login, out string password, out int indexTenant, out DateTime expire, out int indexUser)
public bool DecryptCookie(string cookie, out int tenant, out Guid userid, out int indexTenant, out DateTime expire, out int indexUser)
{
tenant = Tenant.DEFAULT_TENANT;
userid = Guid.Empty;
login = null;
password = null;
indexTenant = 0;
expire = DateTime.MaxValue;
indexUser = 0;
@ -87,9 +85,7 @@ namespace ASC.Core.Security.Authentication
cookie = (HttpUtility.UrlDecode(cookie) ?? "").Replace(' ', '+');
var s = InstanceCrypto.Decrypt(cookie).Split('$');
if (0 < s.Length) login = s[0];
if (1 < s.Length) tenant = int.Parse(s[1]);
if (2 < s.Length) password = s[2];
if (4 < s.Length) userid = new Guid(s[4]);
if (5 < s.Length) indexTenant = int.Parse(s[5]);
if (6 < s.Length) expire = DateTime.ParseExact(s[6], DateTimeFormat, CultureInfo.InvariantCulture);
@ -99,27 +95,27 @@ namespace ASC.Core.Security.Authentication
}
catch (Exception err)
{
Log.ErrorFormat("Authenticate error: cookie {0}, tenant {1}, userid {2}, login {3}, pass {4}, indexTenant {5}, expire {6}: {7}",
cookie, tenant, userid, login, password, indexTenant, expire.ToString(DateTimeFormat), err);
Log.ErrorFormat("Authenticate error: cookie {0}, tenant {1}, userid {2}, indexTenant {3}, expire {4}: {5}",
cookie, tenant, userid, indexTenant, expire.ToString(DateTimeFormat), err);
}
return false;
}
public string EncryptCookie(int tenant, Guid userid, string login = null, string password = null)
public string EncryptCookie(int tenant, Guid userid)
{
var settingsTenant = TenantCookieSettingsHelper.GetForTenant(tenant);
var expires = TenantCookieSettingsHelper.GetExpiresTime(tenant);
var settingsUser = TenantCookieSettingsHelper.GetForUser(tenant, userid);
return EncryptCookie(tenant, userid, login, password, settingsTenant.Index, expires, settingsUser.Index);
return EncryptCookie(tenant, userid, settingsTenant.Index, expires, settingsUser.Index);
}
public string EncryptCookie(int tenant, Guid userid, string login, string password, int indexTenant, DateTime expires, int indexUser)
public string EncryptCookie(int tenant, Guid userid, int indexTenant, DateTime expires, int indexUser)
{
var s = string.Format("{0}${1}${2}${3}${4}${5}${6}${7}",
(login ?? string.Empty).ToLowerInvariant(),
string.Empty, //login
tenant,
password,
string.Empty, //password
GetUserDepenencySalt(),
userid.ToString("N"),
indexTenant,

View File

@ -121,14 +121,5 @@ namespace ASC.Core
return result;
}
public static string GeneratePassword(int length)
{
const string noise = "1234567890mnbasdflkjqwerpoiqweyuvcxnzhdkqpsdk";
var random = new AscRandom();
var pwd = string.Empty;
while (0 < length--) pwd += noise[random.Next(noise.Length)];
return pwd;
}
}
}

View File

@ -53,15 +53,15 @@ namespace ASC.Security.Cryptography
private readonly ILog log;
private static readonly DateTime _from = new DateTime(2010, 01, 01, 0, 0, 0, DateTimeKind.Utc);
internal readonly TimeSpan ValidInterval;
internal readonly TimeSpan ValidInterval;
private MachinePseudoKeys MachinePseudoKeys { get; }
private TenantManager TenantManager { get; }
private IConfiguration Configuration { get; }
public EmailValidationKeyProvider(TenantManager tenantManager, IConfiguration configuration, IOptionsMonitor<ILog> options)
{
public EmailValidationKeyProvider(MachinePseudoKeys machinePseudoKeys, TenantManager tenantManager, IConfiguration configuration, IOptionsMonitor<ILog> options)
{
MachinePseudoKeys = machinePseudoKeys;
TenantManager = tenantManager;
Configuration = configuration;
if (!TimeSpan.TryParse(configuration["email:validinterval"], out var validInterval))
{
validInterval = TimeSpan.FromDays(7);
@ -92,7 +92,7 @@ namespace ASC.Security.Cryptography
if (email == null) throw new ArgumentNullException("email");
try
{
return string.Format("{0}|{1}|{2}", email.ToLowerInvariant(), tenantId, Configuration["core:machinekey"]);
return string.Format("{0}|{1}|{2}", email.ToLowerInvariant(), tenantId, Encoding.UTF8.GetString(MachinePseudoKeys.GetMachineConstant()));
}
catch (Exception e)
{
@ -225,16 +225,11 @@ namespace ASC.Security.Cryptography
case ConfirmType.EmailChange:
checkKeyResult = Provider.ValidateEmailKey(Email + Type + AuthContext.CurrentAccount.ID, Key, Provider.ValidInterval);
break;
case ConfirmType.PasswordChange:
var hash = string.Empty;
if (P == 1)
{
var tenantId = TenantManager.GetCurrentTenant().TenantId;
hash = Authentication.GetUserPasswordHash(tenantId, UiD.Value);
}
checkKeyResult = Provider.ValidateEmailKey(Email + Type + (string.IsNullOrEmpty(hash) ? string.Empty : Hasher.Base64Hash(hash)) + UiD, Key, Provider.ValidInterval);
case ConfirmType.PasswordChange:
var hash = Authentication.GetUserPasswordStamp(UserManager.GetUserByEmail(Email).ID).ToString("s");
checkKeyResult = Provider.ValidateEmailKey(Email + Type + hash, Key, Provider.ValidInterval);
break;
case ConfirmType.Activation:
checkKeyResult = Provider.ValidateEmailKey(Email + Type + UiD, Key, Provider.ValidInterval);
@ -268,12 +263,17 @@ namespace ASC.Security.Cryptography
public static class EmailValidationKeyProviderExtension
{
public static DIHelper AddEmailValidationKeyProviderService(this DIHelper services)
{
services.TryAddTransient<EmailValidationKeyModel>();
services.TryAddScoped<EmailValidationKeyProvider>();
return services
.AddTenantManagerService();
{
if (services.TryAddScoped<EmailValidationKeyProvider>())
{
services.TryAddTransient<EmailValidationKeyModel>();
return services
.AddTenantManagerService()
.AddMachinePseudoKeysService();
}
return services;
}
}
}

View File

@ -1,124 +1,124 @@
/*
*
* (c) Copyright Ascensio System Limited 2010-2018
*
* This program is freeware. You can redistribute it and/or modify it under the terms of the GNU
* General Public License (GPL) version 3 as published by the Free Software Foundation (https://www.gnu.org/copyleft/gpl.html).
* In accordance with Section 7(a) of the GNU GPL its Section 15 shall be amended to the effect that
* Ascensio System SIA expressly excludes the warranty of non-infringement of any third-party rights.
*
* THIS PROGRAM IS DISTRIBUTED WITHOUT ANY WARRANTY; WITHOUT EVEN THE IMPLIED WARRANTY OF MERCHANTABILITY OR
* FITNESS FOR A PARTICULAR PURPOSE. For more details, see GNU GPL at https://www.gnu.org/copyleft/gpl.html
*
* You can contact Ascensio System SIA by email at sales@onlyoffice.com
*
* The interactive user interfaces in modified source and object code versions of ONLYOFFICE must display
* Appropriate Legal Notices, as required under Section 5 of the GNU GPL version 3.
*
* Pursuant to Section 7 § 3(b) of the GNU GPL you must retain the original ONLYOFFICE logo which contains
* relevant author attributions when distributing the software. If the display of the logo in its graphic
* form is not reasonably feasible for technical reasons, you must include the words "Powered by ONLYOFFICE"
* in every copy of the program you distribute.
* Pursuant to Section 7 § 3(e) we decline to grant you any rights under trademark law for use of our trademarks.
*
*/
using System;
using System.Diagnostics;
using System.Linq;
namespace ASC.Core.Tenants
{
[DebuggerDisplay("{Name}")]
public class TenantQuota : ICloneable
{
/*
*
* (c) Copyright Ascensio System Limited 2010-2018
*
* This program is freeware. You can redistribute it and/or modify it under the terms of the GNU
* General Public License (GPL) version 3 as published by the Free Software Foundation (https://www.gnu.org/copyleft/gpl.html).
* In accordance with Section 7(a) of the GNU GPL its Section 15 shall be amended to the effect that
* Ascensio System SIA expressly excludes the warranty of non-infringement of any third-party rights.
*
* THIS PROGRAM IS DISTRIBUTED WITHOUT ANY WARRANTY; WITHOUT EVEN THE IMPLIED WARRANTY OF MERCHANTABILITY OR
* FITNESS FOR A PARTICULAR PURPOSE. For more details, see GNU GPL at https://www.gnu.org/copyleft/gpl.html
*
* You can contact Ascensio System SIA by email at sales@onlyoffice.com
*
* The interactive user interfaces in modified source and object code versions of ONLYOFFICE must display
* Appropriate Legal Notices, as required under Section 5 of the GNU GPL version 3.
*
* Pursuant to Section 7 § 3(b) of the GNU GPL you must retain the original ONLYOFFICE logo which contains
* relevant author attributions when distributing the software. If the display of the logo in its graphic
* form is not reasonably feasible for technical reasons, you must include the words "Powered by ONLYOFFICE"
* in every copy of the program you distribute.
* Pursuant to Section 7 § 3(e) we decline to grant you any rights under trademark law for use of our trademarks.
*
*/
using System;
using System.Diagnostics;
using System.Linq;
namespace ASC.Core.Tenants
{
[DebuggerDisplay("{Name}")]
public class TenantQuota : ICloneable
{
public static readonly TenantQuota Default = new TenantQuota(Tenant.DEFAULT_TENANT)
{
Name = "Default",
MaxFileSize = 25 * 1024 * 1024, // 25Mb
MaxTotalSize = long.MaxValue,
ActiveUsers = int.MaxValue,
};
public int Id { get; set; }
public string Name { get; set; }
public long MaxFileSize { get; set; }
public long MaxTotalSize { get; set; }
public int ActiveUsers { get; set; }
public string Features { get; set; }
public decimal Price { get; set; }
public decimal Price2 { get; set; }
public string AvangateId { get; set; }
public bool Visible { get; set; }
public bool Year
{
get { return GetFeature("year"); }
set { SetFeature("year", value); }
}
public bool Year3
{
get { return GetFeature("year3"); }
set { SetFeature("year3", value); }
}
public bool NonProfit
{
get { return GetFeature("non-profit"); }
set { SetFeature("non-profit", value); }
}
public bool Trial
{
get { return GetFeature("trial"); }
set { SetFeature("trial", value); }
}
public bool Free
{
get { return GetFeature("free"); }
set { SetFeature("free", value); }
}
public bool Open
{
get { return GetFeature("open"); }
set { SetFeature("open", value); }
}
public bool ControlPanel
{
get { return GetFeature("controlpanel"); }
set { SetFeature("controlpanel", value); }
}
public bool Update
{
get { return GetFeature("update"); }
set { SetFeature("update", value); }
}
public bool Support
{
get { return GetFeature("support"); }
set { SetFeature("support", value); }
}
public bool Audit
{
get { return GetFeature("audit"); }
set { SetFeature("audit", value); }
};
public int Id { get; set; }
public string Name { get; set; }
public long MaxFileSize { get; set; }
public long MaxTotalSize { get; set; }
public int ActiveUsers { get; set; }
public string Features { get; set; }
public decimal Price { get; set; }
public decimal Price2 { get; set; }
public string AvangateId { get; set; }
public bool Visible { get; set; }
public bool Year
{
get { return GetFeature("year"); }
set { SetFeature("year", value); }
}
public bool Year3
{
get { return GetFeature("year3"); }
set { SetFeature("year3", value); }
}
public bool NonProfit
{
get { return GetFeature("non-profit"); }
set { SetFeature("non-profit", value); }
}
public bool Trial
{
get { return GetFeature("trial"); }
set { SetFeature("trial", value); }
}
public bool Free
{
get { return GetFeature("free"); }
set { SetFeature("free", value); }
}
public bool Open
{
get { return GetFeature("open"); }
set { SetFeature("open", value); }
}
public bool ControlPanel
{
get { return GetFeature("controlpanel"); }
set { SetFeature("controlpanel", value); }
}
public bool Update
{
get { return GetFeature("update"); }
set { SetFeature("update", value); }
}
public bool Support
{
get { return GetFeature("support"); }
set { SetFeature("support", value); }
}
public bool Audit
{
get { return GetFeature("audit"); }
set { SetFeature("audit", value); }
}
public bool DocsEdition
@ -126,35 +126,35 @@ namespace ASC.Core.Tenants
get { return GetFeature("docs"); }
set { SetFeature("docs", value); }
}
public bool HasDomain
{
get { return GetFeature("domain"); }
set { SetFeature("domain", value); }
}
public bool HealthCheck
{
get { return GetFeature("healthcheck"); }
set { SetFeature("healthcheck", value); }
}
public bool HasMigration
{
get { return GetFeature("migration"); }
set { SetFeature("migration", value); }
}
public bool Ldap
{
get { return GetFeature("ldap"); }
set { SetFeature("ldap", value); }
}
public bool Sso
{
get { return GetFeature("sso"); }
set { SetFeature("sso", value); }
public bool HasDomain
{
get { return GetFeature("domain"); }
set { SetFeature("domain", value); }
}
public bool HealthCheck
{
get { return GetFeature("healthcheck"); }
set { SetFeature("healthcheck", value); }
}
public bool HasMigration
{
get { return GetFeature("migration"); }
set { SetFeature("migration", value); }
}
public bool Ldap
{
get { return GetFeature("ldap"); }
set { SetFeature("ldap", value); }
}
public bool Sso
{
get { return GetFeature("sso"); }
set { SetFeature("sso", value); }
}
public bool Branding
@ -167,12 +167,12 @@ namespace ASC.Core.Tenants
{
get { return GetFeature("ssbranding"); }
set { SetFeature("ssbranding", value); }
}
public bool WhiteLabel
{
get { return GetFeature("whitelabel"); }
set { SetFeature("whitelabel", value); }
}
public bool WhiteLabel
{
get { return GetFeature("whitelabel"); }
set { SetFeature("whitelabel", value); }
}
public bool Customization
@ -191,77 +191,77 @@ namespace ASC.Core.Tenants
{
get { return GetFeature("privacyroom"); }
set { SetFeature("privacyroom", value); }
}
public int CountPortals
{
get
{
var features = (Features ?? string.Empty).Split(' ', ',', ';').ToList();
var portals = features.FirstOrDefault(f => f.StartsWith("portals:"));
if (portals == null || !int.TryParse(portals.Replace("portals:", ""), out var countPortals) || countPortals <= 0)
{
countPortals = 0;
}
return countPortals;
}
set
{
var features = (Features ?? string.Empty).Split(' ', ',', ';').ToList();
var portals = features.FirstOrDefault(f => f.StartsWith("portals:"));
features.Remove(portals);
if (value > 0)
{
features.Add("portals:" + value);
}
Features = string.Join(",", features.ToArray());
}
}
public TenantQuota()
{
}
public TenantQuota(int tenant)
{
Id = tenant;
}
public override int GetHashCode()
{
return Id.GetHashCode();
}
public override bool Equals(object obj)
{
return obj is TenantQuota q && q.Id == Id;
}
public bool GetFeature(string feature)
{
return !string.IsNullOrEmpty(Features) && Features.Split(' ', ',', ';').Contains(feature);
}
internal void SetFeature(string feature, bool set)
{
var features = (Features == null
? new string[] { }
: Features.Split(' ', ',', ';')).ToList();
if (set && !features.Contains(feature))
{
features.Add(feature);
}
else if (!set && features.Contains(feature))
{
features.Remove(feature);
}
Features = string.Join(",", features.ToArray());
}
public object Clone()
{
return MemberwiseClone();
}
}
}
public int CountPortals
{
get
{
var features = (Features ?? string.Empty).Split(' ', ',', ';').ToList();
var portals = features.FirstOrDefault(f => f.StartsWith("portals:"));
if (portals == null || !int.TryParse(portals.Replace("portals:", ""), out var countPortals) || countPortals <= 0)
{
countPortals = 0;
}
return countPortals;
}
set
{
var features = (Features ?? string.Empty).Split(' ', ',', ';').ToList();
var portals = features.FirstOrDefault(f => f.StartsWith("portals:"));
features.Remove(portals);
if (value > 0)
{
features.Add("portals:" + value);
}
Features = string.Join(",", features.ToArray());
}
}
public TenantQuota()
{
}
public TenantQuota(int tenant)
{
Id = tenant;
}
public override int GetHashCode()
{
return Id.GetHashCode();
}
public override bool Equals(object obj)
{
return obj is TenantQuota q && q.Id == Id;
}
public bool GetFeature(string feature)
{
return !string.IsNullOrEmpty(Features) && Features.Split(' ', ',', ';').Contains(feature);
}
internal void SetFeature(string feature, bool set)
{
var features = (Features == null
? new string[] { }
: Features.Split(' ', ',', ';')).ToList();
if (set && !features.Contains(feature))
{
features.Add(feature);
}
else if (!set && features.Contains(feature))
{
features.Remove(feature);
}
Features = string.Join(",", features.ToArray());
}
public object Clone()
{
return MemberwiseClone();
}
}
}

View File

@ -49,7 +49,7 @@ namespace ASC.Core.Tenants
public string MobilePhone { get; set; }
public string Password { get; set; }
public string PasswordHash { get; set; }
public EmployeeActivationStatus ActivationStatus { get; set; }
@ -69,6 +69,7 @@ namespace ASC.Core.Tenants
public string Campaign { get; set; }
public bool LimitedControlPanel { get; set; }
public TenantRegistrationInfo()
{

View File

@ -27,7 +27,6 @@
#if DEBUG
namespace ASC.Core.Common.Tests
{
using System;
using ASC.Core.Security.Authentication;
@ -39,26 +38,26 @@ namespace ASC.Core.Common.Tests
[Test]
public void Validate(CookieStorage cookieStorage)
{
var t1 = 1;
var id1 = Guid.NewGuid();
var login1 = "l1";
var pwd1 = "p1";
var it1 = 1;
var expire1 = DateTime.UtcNow;
var iu1 = 1;
//var t1 = 1;
//var id1 = Guid.NewGuid();
//var login1 = "l1";
//var pwd1 = "p1";
//var it1 = 1;
//var expire1 = DateTime.UtcNow;
//var iu1 = 1;
var cookie = cookieStorage.EncryptCookie(t1, id1, login1, pwd1, it1, expire1, iu1);
//var cookie = cookieStorage.EncryptCookie(t1, id1, login1, pwd1, it1, expire1, iu1);
cookieStorage.DecryptCookie(cookie, out var t2, out var id2, out var login2, out var pwd2, out var it2, out var expire2, out var iu2);
//cookieStorage.DecryptCookie(cookie, out var t2, out var id2, out var login2, out var pwd2, out var it2, out var expire2, out var iu2);
Assert.AreEqual(t1, t2);
Assert.AreEqual(id1, id2);
Assert.AreEqual(login1, login2);
Assert.AreEqual(pwd1, pwd2);
Assert.AreEqual(it1, it2);
Assert.AreEqual(expire1, expire2);
Assert.AreEqual(iu1, iu2);
//Assert.AreEqual(t1, t2);
//Assert.AreEqual(id1, id2);
//Assert.AreEqual(login1, login2);
//Assert.AreEqual(pwd1, pwd2);
//Assert.AreEqual(it1, it2);
//Assert.AreEqual(expire1, expire2);
//Assert.AreEqual(iu1, iu2);
}
}
}

View File

@ -111,7 +111,7 @@ namespace ASC.Core.Common.Tests
userService.SaveUser(t1.TenantId, user);
var password = "password";
userService.SetUserPassword(t1.TenantId, user.ID, password);
//userService.SetUserPassword(t1.TenantId, user.ID, password);
tenants = Service.GetTenants(user.Email, Hasher.Base64Hash(password, HashAlg.SHA256));
CollectionAssert.AreEqual(new[] { t1 }, tenants.ToList());

View File

@ -32,7 +32,6 @@ namespace ASC.Core.Common.Tests
using ASC.Core.Data;
using ASC.Core.Users;
using ASC.Security.Cryptography;
using NUnit.Framework;
@ -133,18 +132,18 @@ namespace ASC.Core.Common.Tests
CollectionAssert.AreEquivalent(new byte[] { 1, 2, 3 }, Service.GetUserPhoto(Tenant, user1.ID));
var password = "password";
Service.SetUserPassword(Tenant, user1.ID, password);
Assert.AreEqual(password, Service.GetUserPassword(Tenant, user1.ID));
//Service.SetUserPassword(Tenant, user1.ID, password);
//Assert.AreEqual(password, Service.GetUserPassword(Tenant, user1.ID));
CompareUsers(user1, Service.GetUser(Tenant, user1.Email, Hasher.Base64Hash(password, HashAlg.SHA256)));
//CompareUsers(user1, Service.GetUser(Tenant, user1.Email, Hasher.Base64Hash(password, HashAlg.SHA256)));
Service.RemoveUser(Tenant, user1.ID);
Assert.IsTrue(Service.GetUser(Tenant, user1.ID).Removed);
Service.RemoveUser(Tenant, user1.ID, true);
Assert.AreEqual(0, Service.GetUserPhoto(Tenant, user1.ID).Count());
Assert.IsNull(Service.GetUserPassword(Tenant, user1.ID));
Assert.AreEqual(0, Service.GetUserPhoto(Tenant, user1.ID).Count());
// Assert.IsNull(Service.GetUserPassword(Tenant, user1.ID));
}
[Test]

View File

@ -57,13 +57,13 @@ namespace ASC.Core.Common.Tests
[Test]
public void RegionsTest()
{
var regionSerice = new MultiRegionHostedSolution("site", null, null, null, null);
//var regionSerice = new MultiRegionHostedSolution("site", null, null, null, null);
var t1 = regionSerice.GetTenant("teamlab.com", 50001);
Assert.AreEqual("alias_test2.teamlab.com", t1.GetTenantDomain(null));
//var t1 = regionSerice.GetTenant("teamlab.com", 50001);
//Assert.AreEqual("alias_test2.teamlab.com", t1.GetTenantDomain(null));
var t2 = regionSerice.GetTenant("teamlab.eu.com", 50001);
Assert.AreEqual("tscherb.teamlab.eu.com", t2.GetTenantDomain(null));
//var t2 = regionSerice.GetTenant("teamlab.eu.com", 50001);
//Assert.AreEqual("tscherb.teamlab.eu.com", t2.GetTenantDomain(null));
}
}
}

View File

@ -25,6 +25,7 @@
using System;
using System.Reflection;
using System.Web;
using ASC.Common;
@ -32,6 +33,8 @@ using ASC.Core;
using ASC.Core.Common.Settings;
using ASC.Core.Users;
using Microsoft.Extensions.Configuration;
namespace ASC.Web.Core.Users
{
[Serializable]
@ -55,10 +58,12 @@ namespace ASC.Web.Core.Users
public class DisplayUserSettingsHelper
{
public DisplayUserSettingsHelper(UserManager userManager, UserFormatter userFormatter)
private string RemovedProfileName;
public DisplayUserSettingsHelper(UserManager userManager, UserFormatter userFormatter, IConfiguration configuration)
{
UserManager = userManager;
UserFormatter = userFormatter;
RemovedProfileName = configuration["web:removed-profile-name"] ?? "profile removed";
}
private UserManager UserManager { get; }
@ -82,7 +87,18 @@ namespace ASC.Web.Core.Users
}
if (!userInfo.ID.Equals(Guid.Empty) && !UserManager.UserExists(userInfo))
{
return "profile removed";
try
{
var resourceType = Type.GetType("Resources.Resource, ASC.Web.Studio");
var resourceProperty = resourceType.GetProperty("ProfileRemoved", BindingFlags.Static | BindingFlags.Public);
var resourceValue = (string)resourceProperty.GetValue(null);
return string.IsNullOrEmpty(resourceValue) ? RemovedProfileName : resourceValue;
}
catch (Exception)
{
return RemovedProfileName;
}
}
var result = UserFormatter.GetUserName(userInfo, format);
return withHtmlEncode ? HtmlEncode(result) : result;

View File

@ -48,7 +48,7 @@ namespace ASC.Web.Core.WhiteLabel
public string SalesEmail { get; set; }
public string DemotUrl { get; set; }
public string DemoUrl { get; set; }
public string SiteUrl { get; set; }
@ -68,7 +68,7 @@ namespace ASC.Web.Core.WhiteLabel
SupportUrl = mailWhiteLabelSettingsHelper.DefaultMailSupportUrl,
SupportEmail = mailWhiteLabelSettingsHelper.DefaultMailSupportEmail,
SalesEmail = mailWhiteLabelSettingsHelper.DefaultMailSalesEmail,
DemotUrl = mailWhiteLabelSettingsHelper.DefaultMailDemotUrl,
DemoUrl = mailWhiteLabelSettingsHelper.DefaultMailDemoUrl,
SiteUrl = mailWhiteLabelSettingsHelper.DefaultMailSiteUrl
};
}
@ -82,7 +82,7 @@ namespace ASC.Web.Core.WhiteLabel
SupportUrl == defaultSettings.SupportUrl &&
SupportEmail == defaultSettings.SupportEmail &&
SalesEmail == defaultSettings.SalesEmail &&
DemotUrl == defaultSettings.DemotUrl &&
DemoUrl == defaultSettings.DemoUrl &&
SiteUrl == defaultSettings.SiteUrl;
}
@ -113,7 +113,7 @@ namespace ASC.Web.Core.WhiteLabel
get
{
var url = BaseCommonLinkUtility.GetRegionalUrl(Configuration["web:support-feedback"] ?? string.Empty, null);
return !string.IsNullOrEmpty(url) ? url : "http://support.onlyoffice.com";
return !string.IsNullOrEmpty(url) ? url : "http://helpdesk.onlyoffice.com";
}
}
@ -135,7 +135,7 @@ namespace ASC.Web.Core.WhiteLabel
}
}
public string DefaultMailDemotUrl
public string DefaultMailDemoUrl
{
get
{

View File

@ -0,0 +1,11 @@
syntax = "proto3";
package ASC.Core.Common.Notify;
message CreateClientProto {
int32 TenantId = 1;
string Token = 2;
int32 TokenLifespan = 3;
string Proxy = 4;
string Time = 5;
}

View File

@ -0,0 +1,7 @@
syntax = "proto3";
package ASC.Core.Common.Notify;
message DisableClientProto {
int32 TenantId= 1;
}

View File

@ -14,6 +14,7 @@ message NotifyMessage {
int64 CreationDate = 9;
int32 Priority = 10;
repeated NotifyMessageAttachment EmbeddedAttachments = 11;
string AutoSubmitted = 12;
}
message NotifyMessageAttachment {
string FileName = 1;

View File

@ -0,0 +1,9 @@
syntax = "proto3";
package ASC.Core.Common.Notify;
message RegisterUserProto {
string UserId= 1;
int32 TenantId= 2;
string Token= 3;
}

View File

@ -167,7 +167,7 @@ namespace ASC.Core.ChunkedUploader
if (uploadSession.BytesTotal == uploadSession.BytesUploaded)
{
return new FileStream(uploadSession.ChunksBuffer, FileMode.Open, FileAccess.Read, FileShare.ReadWrite,
return new FileStream(uploadSession.ChunksBuffer, FileMode.Open, FileAccess.ReadWrite, FileShare.ReadWrite,
4096, FileOptions.DeleteOnClose);
}
}

View File

@ -310,7 +310,7 @@ namespace ASC.Data.Storage.DiscStorage
var entries = Directory.GetFiles(targetDir, pattern, recursive ? SearchOption.AllDirectories : SearchOption.TopDirectoryOnly);
foreach (var entry in entries)
{
var size = new FileInfo(entry).Length;
var size = Crypt.GetFileSize(entry);
File.Delete(entry);
QuotaUsedDelete(domain, size);
}

View File

@ -26,8 +26,8 @@
using System;
using ASC.Common;
using ASC.Common;
using Microsoft.Extensions.DependencyInjection;
namespace ASC.Data.Storage.Encryption

View File

@ -30,8 +30,8 @@ using System.Security.Cryptography;
using ASC.Common;
using ASC.Common.Caching;
using ASC.Core;
using ASC.Security.Cryptography;
using ASC.Security.Cryptography;
namespace ASC.Data.Storage.Encryption
{
public class EncryptionSettings
@ -64,19 +64,19 @@ namespace ASC.Data.Storage.Encryption
}
}
public class EncryptionSettingsHelper
public class EncryptionSettingsHelper
{
private const string key = "EncryptionSettings";
private CoreConfiguration CoreConfiguration { get; }
private AscCacheNotify AscCacheNotify { get; }
private InstanceCrypto InstanceCrypto { get; }
private AscCacheNotify AscCacheNotify { get; }
private InstanceCrypto InstanceCrypto { get; }
public EncryptionSettingsHelper(CoreConfiguration coreConfiguration, AscCacheNotify ascCacheNotify, InstanceCrypto instanceCrypto)
{
CoreConfiguration = coreConfiguration;
AscCacheNotify = ascCacheNotify;
InstanceCrypto = instanceCrypto;
AscCacheNotify = ascCacheNotify;
InstanceCrypto = instanceCrypto;
}
public void Save(EncryptionSettings encryptionSettings)

View File

@ -1016,27 +1016,33 @@ namespace ASC.Data.Storage.S3
_recycleDir = props["recycleDir"];
}
if (props.ContainsKey("region"))
if (props.ContainsKey("region") && !string.IsNullOrEmpty(props["region"]))
{
_region = props["region"];
}
if (props.ContainsKey("serviceurl"))
if (props.ContainsKey("serviceurl") && !string.IsNullOrEmpty(props["serviceurl"]))
{
_serviceurl = props["serviceurl"];
}
if (props.ContainsKey("forcepathstyle"))
{
_forcepathstyle = bool.Parse(props["forcepathstyle"]);
if (bool.TryParse(props["forcepathstyle"], out var fps))
{
_forcepathstyle = fps;
}
}
if (props.ContainsKey("usehttp"))
{
_useHttp = bool.Parse(props["usehttp"]);
if (bool.TryParse(props["usehttp"], out var uh))
{
_useHttp = uh;
}
}
if (props.ContainsKey("sse"))
if (props.ContainsKey("sse") && !string.IsNullOrEmpty(props["sse"]))
{
switch (props["sse"].ToLower())
{

View File

@ -26,12 +26,10 @@
using System;
using System.Linq;
using System.Security;
using ASC.Common;
using ASC.Common.Utils;
using ASC.Core;
using ASC.Core.Users;
using ASC.FederatedLogin;
using ASC.FederatedLogin.Profile;
using ASC.Security.Cryptography;
@ -66,44 +64,36 @@ namespace ASC.Web.Studio.Core
InstanceCrypto = instanceCrypto;
Snapshot = snapshot;
}
public void UpdateAddress(string account)
{
var tenant = TenantManager.GetCurrentTenant();
var user = UserManager.GetUsers(SecurityContext.CurrentAccount.ID);
if (!SecurityContext.IsAuthenticated || user.IsVisitor(UserManager)) throw new SecurityException();
public void SetKeys(Guid userId, string keys)
{
if (string.IsNullOrEmpty(keys)) return;
var loginProfile = new LoginProfile(Signature, InstanceCrypto)
{
Provider = ProviderConstants.Encryption,
Provider = ProviderConstants.Encryption,
Name = InstanceCrypto.Encrypt(keys)
};
var linker = Snapshot.Get("webstudio");
if (string.IsNullOrEmpty(account))
{
linker.RemoveLink(user.ID.ToString(), loginProfile);
}
else
{
loginProfile.Name = Crypto.GetV(account, 1, true);
linker.AddLink(user.ID.ToString(), loginProfile);
}
var linker = Snapshot.Get("webstudio");
linker.AddLink(userId.ToString(), loginProfile);
}
public string GetAddress()
public string GetKeys()
{
return GetAddress(SecurityContext.CurrentAccount.ID);
return GetKeys(SecurityContext.CurrentAccount.ID);
}
public string GetAddress(Guid userId)
public string GetKeys(Guid userId)
{
var linker = Snapshot.Get("webstudio");
var profile = linker.GetLinkedProfiles(userId.ToString(), ProviderConstants.Encryption).FirstOrDefault();
if (profile == null) return null;
var account = Crypto.GetV(profile.Name, 1, false);
return account;
if (profile == null) return null;
var keys = InstanceCrypto.Decrypt(profile.Name);
return keys;
}
}
public static class EncryptionLoginProviderExtension

View File

@ -0,0 +1,109 @@
/*
*
* (c) Copyright Ascensio System Limited 2010-2018
*
* This program is freeware. You can redistribute it and/or modify it under the terms of the GNU
* General Public License (GPL) version 3 as published by the Free Software Foundation (https://www.gnu.org/copyleft/gpl.html).
* In accordance with Section 7(a) of the GNU GPL its Section 15 shall be amended to the effect that
* Ascensio System SIA expressly excludes the warranty of non-infringement of any third-party rights.
*
* THIS PROGRAM IS DISTRIBUTED WITHOUT ANY WARRANTY; WITHOUT EVEN THE IMPLIED WARRANTY OF MERCHANTABILITY OR
* FITNESS FOR A PARTICULAR PURPOSE. For more details, see GNU GPL at https://www.gnu.org/copyleft/gpl.html
*
* You can contact Ascensio System SIA by email at sales@onlyoffice.com
*
* The interactive user interfaces in modified source and object code versions of ONLYOFFICE must display
* Appropriate Legal Notices, as required under Section 5 of the GNU GPL version 3.
*
* Pursuant to Section 7 § 3(b) of the GNU GPL you must retain the original ONLYOFFICE logo which contains
* relevant author attributions when distributing the software. If the display of the logo in its graphic
* form is not reasonably feasible for technical reasons, you must include the words "Powered by ONLYOFFICE"
* in every copy of the program you distribute.
* Pursuant to Section 7 § 3(e) we decline to grant you any rights under trademark law for use of our trademarks.
*
*/
using System.Collections.Generic;
using ASC.Common;
using ASC.Common.Caching;
using ASC.Core;
using ASC.Core.Common.Configuration;
using ASC.Core.Common.Notify;
using ASC.Core.Common.Notify.Telegram;
using Microsoft.Extensions.Configuration;
namespace ASC.FederatedLogin.LoginProviders
{
public class TelegramLoginProvider : Consumer, IValidateKeysProvider, ITelegramLoginProvider
{
public string TelegramBotToken
{
get { return this["telegramBotToken"]; }
}
public string TelegramBotName
{
get { return this["telegramBotName"]; }
}
public int TelegramAuthTokenLifespan
{
get { return int.Parse(this["telegramAuthTokenLifespan"]); }
}
public string TelegramProxy
{
get { return this["telegramProxy"]; }
}
public bool IsEnabled()
{
return !string.IsNullOrEmpty(TelegramBotToken) && !string.IsNullOrEmpty(TelegramBotName);
}
private TelegramHelper TelegramHelper { get; }
public TelegramLoginProvider() { }
public TelegramLoginProvider(
TelegramHelper telegramHelper,
TenantManager tenantManager,
CoreBaseSettings coreBaseSettings,
CoreSettings coreSettings,
IConfiguration configuration,
ICacheNotify<ConsumerCacheItem> cache,
ConsumerFactory consumerFactory,
string name, int order, Dictionary<string, string> props, Dictionary<string, string> additional = null)
: base(tenantManager, coreBaseSettings, coreSettings, configuration, cache, consumerFactory, name, order, props, additional)
{
TelegramHelper = telegramHelper;
}
public bool ValidateKeys()
{
if (TelegramBotToken == "")
{
TelegramHelper.DisableClient(TenantManager.GetCurrentTenant().TenantId);
return true;
}
else
{
return TelegramHelper.CreateClient(TenantManager.GetCurrentTenant().TenantId, TelegramBotToken, TelegramAuthTokenLifespan, TelegramProxy);
}
}
}
public static class TelegramLoginProviderExtension
{
public static DIHelper AddTelegramLoginProviderService(this DIHelper services)
{
return services.AddTelegramHelperSerivce()
.AddTenantManagerService()
.AddCoreBaseSettingsService()
.AddCoreSettingsService();
}
}
}

View File

@ -38,6 +38,6 @@ namespace ASC.FederatedLogin
public const string MailRu = "mailru";
public const string VK = "vk";
public const string GosUslugi = "gosuslugi";
public const string Encryption = "blockchain";
public const string Encryption = "e2e";
}
}

View File

@ -508,6 +508,9 @@ namespace ASC.MessagingSystem
StartStorageEncryption = 5050,
PrivacyRoomEnable = 5051,
PrivacyRoomDisable = 5052,
StartStorageDecryption = 5053,
#endregion

View File

@ -242,7 +242,7 @@ namespace ASC.Notify.Textile
NotifyTemplateResource.FooterCommonV10
.Replace("%SUPPORTURL%", MailWhiteLabelSettingsHelper.DefaultMailSupportUrl)
.Replace("%SALESEMAIL%", MailWhiteLabelSettingsHelper.DefaultMailSalesEmail)
.Replace("%DEMOURL%", MailWhiteLabelSettingsHelper.DefaultMailDemotUrl);
.Replace("%DEMOURL%", MailWhiteLabelSettingsHelper.DefaultMailDemoUrl);
footerSocialContent = NotifyTemplateResource.SocialNetworksFooterV10;
}
@ -252,7 +252,7 @@ namespace ASC.Notify.Textile
NotifyTemplateResource.FooterCommonV10
.Replace("%SUPPORTURL%", string.IsNullOrEmpty(settings.SupportUrl) ? "mailto:" + settings.SalesEmail : settings.SupportUrl)
.Replace("%SALESEMAIL%", settings.SalesEmail)
.Replace("%DEMOURL%", string.IsNullOrEmpty(settings.DemotUrl) ? "mailto:" + settings.SalesEmail : settings.DemotUrl);
.Replace("%DEMOURL%", string.IsNullOrEmpty(settings.DemoUrl) ? "mailto:" + settings.SalesEmail : settings.DemoUrl);
footerSocialContent = settings.FooterSocialEnabled ? NotifyTemplateResource.SocialNetworksFooterV10 : string.Empty;
}
}

View File

@ -23,7 +23,7 @@ namespace ASC.Resource.Manager
{
Parser.Default.ParseArguments<Options>(args).WithParsed(Export);
}
public static void Export(Options options)
{
var services = new ServiceCollection();
@ -42,10 +42,11 @@ namespace ASC.Resource.Manager
{
var (project, module, filePath, exportPath, culture, format, key) = options;
//project = "Files";
//module = "JavaScript";
//filePath = "FilesJSResource.resx";
//exportPath = @"C:\Git\portals_core\products\ASC.Files\Server\Resources";
project = "Files";
module = "Common";
filePath = "FilesCommonResource.resx";
exportPath = @"C:\Git\portals_core\products\ASC.Files\Core\Resources";
key = "AceStatusEnum_CustomFilter";
if (format == "json")
{

View File

@ -25,11 +25,12 @@ namespace ASC.Resource.Manager
var diHelper = new DIHelper(services);
services.AddLogging();
diHelper.TryAddScoped<ResourceData>();
diHelper.TryAddScoped<Program.Scope>();
diHelper.TryAddScoped<ProgramScope>();
diHelper.AddDbContextManagerService<ResourceDbContext>();
diHelper.AddLoggerService();
diHelper.AddNLogManager();
diHelper.TryAddSingleton(Configuration); }
diHelper.TryAddSingleton(Configuration);
}
}
}

View File

@ -36,6 +36,7 @@ using System.Threading.Tasks;
using ASC.Common;
using ASC.Common.Logging;
using ASC.Security.Cryptography;
using ASC.Web.Core.Helpers;
using Microsoft.AspNetCore.Authentication;
@ -59,22 +60,25 @@ namespace ASC.ApiSystem.Classes
ISystemClock clock,
IConfiguration configuration,
IOptionsMonitor<ILog> option,
ApiSystemHelper apiSystemHelper) :
ApiSystemHelper apiSystemHelper,
MachinePseudoKeys machinePseudoKeys) :
base(options, logger, encoder, clock)
{
Configuration = configuration;
Log = option.Get("ASC.ApiSystem");
ApiSystemHelper = apiSystemHelper;
ApiSystemHelper = apiSystemHelper;
MachinePseudoKeys = machinePseudoKeys;
}
private ILog Log { get; }
private IConfiguration Configuration { get; }
private ApiSystemHelper ApiSystemHelper { get; }
private ApiSystemHelper ApiSystemHelper { get; }
private MachinePseudoKeys MachinePseudoKeys { get; }
protected override Task<AuthenticateResult> HandleAuthenticateAsync()
{
if (Convert.ToBoolean(Configuration[Scheme.Name] ?? "false"))
@ -130,8 +134,8 @@ namespace ASC.ApiSystem.Classes
}
}
var skey = Configuration["core:machinekey"];
using var hasher = new HMACSHA1(Encoding.UTF8.GetBytes(skey));
var skey = MachinePseudoKeys.GetMachineConstant();
using var hasher = new HMACSHA1(skey);
var data = string.Join("\n", date, pkey);
var hash = hasher.ComputeHash(Encoding.UTF8.GetBytes(data));

View File

@ -77,8 +77,10 @@ namespace ASC.ApiSystem.Controllers
private HostedSolution HostedSolution { get; }
private IMemoryCache MemoryCache { get; }
private IMemoryCache MemoryCache { get; }
public CoreBaseSettings CoreBaseSettings { get; }
public TenantManager TenantManager { get; }
public CommonMethods(
IHttpContextAccessor httpContextAccessor,
IConfiguration configuration,
@ -88,7 +90,9 @@ namespace ASC.ApiSystem.Controllers
EmailValidationKeyProvider emailValidationKeyProvider,
TimeZoneConverter timeZoneConverter, CommonConstants commonConstants,
IMemoryCache memoryCache,
IOptionsSnapshot<HostedSolution> hostedSolutionOptions)
IOptionsSnapshot<HostedSolution> hostedSolutionOptions,
CoreBaseSettings coreBaseSettings,
TenantManager tenantManager)
{
HttpContextAccessor = httpContextAccessor;
@ -106,8 +110,9 @@ namespace ASC.ApiSystem.Controllers
CommonConstants = commonConstants;
MemoryCache = memoryCache;
MemoryCache = memoryCache;
CoreBaseSettings = coreBaseSettings;
TenantManager = tenantManager;
HostedSolution = hostedSolutionOptions.Get(CommonConstants.BaseDbConnKeyString);
}
@ -200,7 +205,13 @@ namespace ASC.ApiSystem.Controllers
}
public bool GetTenant(IModel model, out Tenant tenant)
{
{
if (CoreBaseSettings.Standalone && model != null && !string.IsNullOrEmpty((model.PortalName ?? "").Trim()))
{
tenant = TenantManager.GetTenant((model.PortalName ?? "").Trim());
return true;
}
if (model != null && model.TenantId.HasValue)
{
tenant = HostedSolution.GetTenant(model.TenantId.Value);
@ -218,9 +229,14 @@ namespace ASC.ApiSystem.Controllers
}
public bool IsTestEmail(string email)
{
var regex = new Regex(CommonConstants.AutotestSecretEmails, RegexOptions.IgnoreCase | RegexOptions.Singleline | RegexOptions.Compiled);
return regex.IsMatch((email ?? "").ToLower());
{
//the point is not needed in gmail.com
email = Regex.Replace(email ?? "", "\\.*(?=\\S*(@gmail.com$))", "").ToLower();
if (string.IsNullOrEmpty(email) || string.IsNullOrEmpty(CommonConstants.AutotestSecretEmails))
return false;
var regex = new Regex(CommonConstants.AutotestSecretEmails, RegexOptions.IgnoreCase | RegexOptions.Singleline | RegexOptions.Compiled);
return regex.IsMatch(email);
}
public bool CheckMuchRegistration(TenantModel model, string clientIP, Stopwatch sw)

View File

@ -44,8 +44,6 @@ using Microsoft.AspNetCore.Authorization;
using Microsoft.AspNetCore.Http;
using Microsoft.AspNetCore.Mvc;
using Microsoft.Extensions.Options;
using Newtonsoft.Json.Linq;
namespace ASC.ApiSystem.Controllers
{
@ -57,6 +55,7 @@ namespace ASC.ApiSystem.Controllers
private EmailValidationKeyProvider EmailValidationKeyProvider { get; }
private CoreSettings CoreSettings { get; }
private CommonConstants CommonConstants { get; }
public InstanceCrypto InstanceCrypto { get; }
private ILog Log { get; }
public CalDavController(
@ -64,12 +63,14 @@ namespace ASC.ApiSystem.Controllers
EmailValidationKeyProvider emailValidationKeyProvider,
CoreSettings coreSettings,
CommonConstants commonConstants,
InstanceCrypto instanceCrypto,
IOptionsMonitor<ILog> option)
{
CommonMethods = commonMethods;
EmailValidationKeyProvider = emailValidationKeyProvider;
CoreSettings = coreSettings;
CommonConstants = commonConstants;
InstanceCrypto = instanceCrypto;
Log = option.Get("ASC.ApiSystem");
}
@ -147,9 +148,9 @@ namespace ASC.ApiSystem.Controllers
[HttpPost("is_caldav_authenticated")]
[Authorize(AuthenticationSchemes = "auth.allowskip")]
public IActionResult IsCaldavAuthenticated(JObject data)
public IActionResult IsCaldavAuthenticated(UserPassword userPassword)
{
if (data == null)
if (userPassword == null || string.IsNullOrEmpty(userPassword.User) || string.IsNullOrEmpty(userPassword.Password))
{
Log.Error("CalDav authenticated data is null");
@ -161,10 +162,7 @@ namespace ASC.ApiSystem.Controllers
});
}
var username = data.Value<string>("User");
var password = data.Value<string>("Password");
if (!GetUserData(username, out string email, out Tenant tenant, out object error))
if (!GetUserData(userPassword.User, out var email, out var tenant, out var error))
{
return BadRequest(error);
}
@ -173,19 +171,19 @@ namespace ASC.ApiSystem.Controllers
{
Log.Info(string.Format("Caldav auth user: {0}, tenant: {1}", email, tenant.TenantId));
if (email == "admin@ascsystem" && Core.Configuration.Constants.CoreSystem.ID.ToString() == password)
if (InstanceCrypto.Encrypt(email) == userPassword.Password)
{
return Ok(new
{
value = "true"
});
}
var validationKey = EmailValidationKeyProvider.GetEmailKey(tenant.TenantId, email + password + ConfirmType.Auth);
}
var validationKey = EmailValidationKeyProvider.GetEmailKey(tenant.TenantId, email + userPassword.Password + ConfirmType.Auth);
var authData = string.Format("userName={0}&password={1}&key={2}",
HttpUtility.UrlEncode(email),
HttpUtility.UrlEncode(password),
HttpUtility.UrlEncode(userPassword.Password),
HttpUtility.UrlEncode(validationKey));
SendToApi(Request.Scheme, tenant, "authentication/login", null, WebRequestMethods.Http.Post, authData);
@ -357,9 +355,15 @@ namespace ASC.ApiSystem.Controllers
using (webRequest.GetResponse())
{
}
}
#endregion
public class UserPassword
{
public string User { get; set; }
public string Password { get; set; }
}
#endregion
}
public static class CalDavControllerExtention

View File

@ -40,6 +40,7 @@ using ASC.Core.Billing;
using ASC.Core.Common.Settings;
using ASC.Core.Tenants;
using ASC.Core.Users;
using ASC.Security.Cryptography;
using ASC.Web.Core.Helpers;
using ASC.Web.Core.Users;
using ASC.Web.Core.Utility;
@ -74,6 +75,7 @@ namespace ASC.ApiSystem.Controllers
private CommonConstants CommonConstants { get; }
private TimeZonesProvider TimeZonesProvider { get; }
private TimeZoneConverter TimeZoneConverter { get; }
public PasswordHasher PasswordHasher { get; }
private ILog Log { get; }
public PortalController(
@ -91,7 +93,8 @@ namespace ASC.ApiSystem.Controllers
CommonConstants commonConstants,
IOptionsMonitor<ILog> option,
TimeZonesProvider timeZonesProvider,
TimeZoneConverter timeZoneConverter)
TimeZoneConverter timeZoneConverter,
PasswordHasher passwordHasher)
{
Configuration = configuration;
SecurityContext = securityContext;
@ -107,6 +110,7 @@ namespace ASC.ApiSystem.Controllers
CommonConstants = commonConstants;
TimeZonesProvider = timeZonesProvider;
TimeZoneConverter = timeZoneConverter;
PasswordHasher = passwordHasher;
Log = option.Get("ASC.ApiSystem");
}
@ -156,18 +160,25 @@ namespace ASC.ApiSystem.Controllers
}
var sw = Stopwatch.StartNew();
if (!CheckPasswordPolicy(model.Password, out object error))
{
sw.Stop();
return BadRequest(error);
if (string.IsNullOrEmpty(model.PasswordHash))
{
if (!CheckPasswordPolicy(model.Password, out var error1))
{
sw.Stop();
return BadRequest(error1);
}
if (!string.IsNullOrEmpty(model.Password))
{
model.PasswordHash = PasswordHasher.GetClientPassword(model.Password);
}
}
model.FirstName = (model.FirstName ?? "").Trim();
model.LastName = (model.LastName ?? "").Trim();
if (!CheckValidName(model.FirstName + model.LastName, out error))
if (!CheckValidName(model.FirstName + model.LastName, out var error))
{
sw.Stop();
@ -230,14 +241,15 @@ namespace ASC.ApiSystem.Controllers
Culture = lang,
FirstName = model.FirstName,
LastName = model.LastName,
Password = string.IsNullOrEmpty(model.Password) ? null : model.Password,
PasswordHash = string.IsNullOrEmpty(model.PasswordHash) ? null : model.PasswordHash,
Email = (model.Email ?? "").Trim(),
TimeZoneInfo = tz,
MobilePhone = string.IsNullOrEmpty(model.Phone) ? null : model.Phone.Trim(),
Industry = (TenantIndustry)model.Industry,
Spam = model.Spam,
Calls = model.Calls,
Analytics = model.Analytics
Analytics = model.Analytics,
LimitedControlPanel = model.LimitedControlPanel
};
if (!string.IsNullOrEmpty(model.PartnerId))
@ -315,7 +327,7 @@ namespace ASC.ApiSystem.Controllers
var isFirst = true;
string sendCongratulationsAddress = null;
if (!string.IsNullOrEmpty(model.Password))
if (!string.IsNullOrEmpty(model.PasswordHash))
{
isFirst = !CommonMethods.SendCongratulations(Request.Scheme, t, model.SkipWelcome, out sendCongratulationsAddress);
}

View File

@ -38,6 +38,7 @@ using ASC.Core.Billing;
using ASC.Core.Common.Settings;
using ASC.Core.Tenants;
using ASC.Core.Users;
using ASC.Security.Cryptography;
using ASC.Web.Core.Helpers;
using ASC.Web.Core.Users;
using ASC.Web.Core.Utility;
@ -72,6 +73,7 @@ namespace ASC.ApiSystem.Controllers
private UserFormatter UserFormatter { get; }
private UserManagerWrapper UserManagerWrapper { get; }
private IConfiguration Configuration { get; }
public PasswordHasher PasswordHasher { get; }
private ILog Log { get; }
public RegistrationController(
@ -89,7 +91,8 @@ namespace ASC.ApiSystem.Controllers
UserFormatter userFormatter,
UserManagerWrapper userManagerWrapper,
IConfiguration configuration,
IOptionsMonitor<ILog> option)
IOptionsMonitor<ILog> option,
PasswordHasher passwordHasher)
{
CommonMethods = commonMethods;
CommonConstants = commonConstants;
@ -105,6 +108,7 @@ namespace ASC.ApiSystem.Controllers
UserFormatter = userFormatter;
UserManagerWrapper = userManagerWrapper;
Configuration = configuration;
PasswordHasher = passwordHasher;
Log = option.Get("ASC.ApiSystem");
}
@ -155,14 +159,15 @@ namespace ASC.ApiSystem.Controllers
object error;
if (!string.IsNullOrEmpty(model.Password))
if (string.IsNullOrEmpty(model.PasswordHash) && !string.IsNullOrEmpty(model.Password))
{
if (!CheckPasswordPolicy(model.Password, out error))
{
sw.Stop();
return BadRequest(error);
}
}
model.PasswordHash = PasswordHasher.GetClientPassword(model.Password);
}
if (!CheckValidName(model.FirstName.Trim() + model.LastName.Trim(), out error))
@ -262,14 +267,15 @@ namespace ASC.ApiSystem.Controllers
Culture = lang,
FirstName = model.FirstName.Trim(),
LastName = model.LastName.Trim(),
Password = string.IsNullOrEmpty(model.Password) ? null : model.Password,
PasswordHash = String.IsNullOrEmpty(model.PasswordHash) ? null : model.PasswordHash,
Email = model.Email.Trim(),
TimeZoneInfo = tz,
MobilePhone = string.IsNullOrEmpty(model.Phone) ? null : model.Phone.Trim(),
Industry = (TenantIndustry)model.Industry,
Spam = model.Spam,
Calls = model.Calls,
Analytics = model.Analytics
Analytics = model.Analytics,
LimitedControlPanel = model.LimitedControlPanel
};
if (!string.IsNullOrEmpty(model.PartnerId))
@ -322,7 +328,7 @@ namespace ASC.ApiSystem.Controllers
string sendCongratulationsAddress = null;
if (!string.IsNullOrEmpty(model.Password))
if (!String.IsNullOrEmpty(model.PasswordHash))
{
isFirst = !CommonMethods.SendCongratulations(Request.Scheme, t, model.SkipWelcome, out sendCongratulationsAddress);
}

View File

@ -61,9 +61,12 @@ namespace ASC.ApiSystem.Models
[StringLength(38)]
public string Module { get; set; }
//todo: delete after www update
[StringLength(Web.Core.Utility.PasswordSettings.MaxLength)]
public string Password { get; set; }
public string Password { get; set; }
public string PasswordHash { get; set; }
[StringLength(255)]
public string PartnerId { get; set; }
@ -89,6 +92,8 @@ namespace ASC.ApiSystem.Models
public bool Analytics { get; set; }
public string AppKey { get; set; }
public string AppKey { get; set; }
public bool LimitedControlPanel { get; set; }
}
}

View File

@ -4,9 +4,11 @@ using System.Collections.Generic;
using ASC.Api.Core.Middleware;
using ASC.Common;
using ASC.Core;
using ASC.Data.Backup.Contracts;
using ASC.Data.Backup.Models;
using ASC.Web.Api.Routing;
using ASC.Web.Studio.Utility;
using Microsoft.AspNetCore.Mvc;
@ -17,9 +19,17 @@ namespace ASC.Data.Backup.Controllers
public class BackupController
{
private BackupAjaxHandler BackupHandler { get; }
public BackupController(BackupAjaxHandler backupAjaxHandler)
private CoreBaseSettings CoreBaseSettings { get; }
private TenantExtra TenantExtra { get; }
public BackupController(
BackupAjaxHandler backupAjaxHandler,
CoreBaseSettings coreBaseSettings,
TenantExtra tenantExtra)
{
BackupHandler = backupAjaxHandler;
CoreBaseSettings = coreBaseSettings;
TenantExtra = tenantExtra;
}
/// <summary>
/// Returns the backup schedule of the current portal
@ -29,6 +39,11 @@ namespace ASC.Data.Backup.Controllers
[Read("getbackupschedule")]
public BackupAjaxHandler.Schedule GetBackupSchedule()
{
if (CoreBaseSettings.Standalone)
{
TenantExtra.DemandControlPanelPermission();
}
return BackupHandler.GetSchedule();
}
@ -44,6 +59,11 @@ namespace ASC.Data.Backup.Controllers
[Create("createbackupschedule")]
public void CreateBackupSchedule(BackupStorageType storageType, [FromQuery] Dictionary<string, string> storageParams, int backupsStored, [FromBody] BackupAjaxHandler.CronParams cronParams, bool backupMail)
{
if (CoreBaseSettings.Standalone)
{
TenantExtra.DemandControlPanelPermission();
}
BackupHandler.CreateSchedule(storageType, storageParams, backupsStored, cronParams, backupMail);
}
@ -54,6 +74,11 @@ namespace ASC.Data.Backup.Controllers
[Delete("deletebackupschedule")]
public void DeleteBackupSchedule()
{
if (CoreBaseSettings.Standalone)
{
TenantExtra.DemandControlPanelPermission();
}
BackupHandler.DeleteSchedule();
}
@ -68,6 +93,11 @@ namespace ASC.Data.Backup.Controllers
[Create("startbackup")]
public BackupProgress StartBackup(Models.Backup backup)
{
if (CoreBaseSettings.Standalone)
{
TenantExtra.DemandControlPanelPermission();
}
BackupHandler.StartBackup(backup.StorageType, backup.StorageParams ?? new Dictionary<string, string>(), backup.BackupMail);
return BackupHandler.GetBackupProgress();
}
@ -80,6 +110,11 @@ namespace ASC.Data.Backup.Controllers
[Read("getbackupprogress")]
public BackupProgress GetBackupProgress()
{
if (CoreBaseSettings.Standalone)
{
TenantExtra.DemandControlPanelPermission();
}
return BackupHandler.GetBackupProgress();
}
@ -91,6 +126,11 @@ namespace ASC.Data.Backup.Controllers
[Read("getbackuphistory")]
public List<BackupHistoryRecord> GetBackupHistory()
{
if (CoreBaseSettings.Standalone)
{
TenantExtra.DemandControlPanelPermission();
}
return BackupHandler.GetBackupHistory();
}
@ -101,6 +141,11 @@ namespace ASC.Data.Backup.Controllers
[Delete("deletebackup/{id}")]
public void DeleteBackup(Guid id)
{
if (CoreBaseSettings.Standalone)
{
TenantExtra.DemandControlPanelPermission();
}
BackupHandler.DeleteBackup(id);
}
@ -112,6 +157,11 @@ namespace ASC.Data.Backup.Controllers
[Delete("deletebackuphistory")]
public void DeleteBackupHistory()
{
if (CoreBaseSettings.Standalone)
{
TenantExtra.DemandControlPanelPermission();
}
BackupHandler.DeleteAllBackups();
}
@ -127,6 +177,11 @@ namespace ASC.Data.Backup.Controllers
[Create("startrestore")]
public BackupProgress StartBackupRestore(BackupRestore backupRestore)
{
if (CoreBaseSettings.Standalone)
{
TenantExtra.DemandControlPanelPermission();
}
BackupHandler.StartRestore(backupRestore.BackupId, backupRestore.StorageType, backupRestore.StorageParams, backupRestore.Notify);
return BackupHandler.GetBackupProgress();
}
@ -139,6 +194,11 @@ namespace ASC.Data.Backup.Controllers
[Read("getrestoreprogress", true)] //NOTE: this method doesn't check payment!!!
public BackupProgress GetRestoreProgress()
{
if (CoreBaseSettings.Standalone)
{
TenantExtra.DemandControlPanelPermission();
}
return BackupHandler.GetRestoreProgress();
}
@ -146,6 +206,11 @@ namespace ASC.Data.Backup.Controllers
[Read("backuptmp")]
public string GetTempPath()
{
if (CoreBaseSettings.Standalone)
{
TenantExtra.DemandControlPanelPermission();
}
return BackupHandler.GetTmpFolder();
}
}
@ -155,7 +220,9 @@ namespace ASC.Data.Backup.Controllers
{
return services
.AddBackupAjaxHandler()
.AddIpSecurityFilter();
.AddIpSecurityFilter()
.AddCoreBaseSettingsService()
.AddTenantExtraService();
}
}
}

View File

@ -370,10 +370,12 @@ namespace ASC.Data.Backup.Service
using var scope = ServiceProvider.CreateScope();
var scopeClass = scope.ServiceProvider.GetService<BackupWorkerScope>();
var (tenantManager, backupStorageFactory, notifyHelper, backupRepository, backupWorker, backupPortalTask, _, _) = scopeClass;
var (tenantManager, backupStorageFactory, notifyHelper, backupRepository, backupWorker, backupPortalTask, _, _, coreBaseSettings) = scopeClass;
var tenant = tenantManager.GetTenant(TenantId);
var backupName = string.Format("{0}_{1:yyyy-MM-dd_HH-mm-ss}.{2}", tenant.TenantAlias, DateTime.UtcNow, ArchiveFormat);
var dateTime = coreBaseSettings.Standalone ? DateTime.Now : DateTime.UtcNow;
var backupName = string.Format("{0}_{1:yyyy-MM-dd_HH-mm-ss}.{2}", tenantManager.GetTenant(TenantId).TenantAlias, dateTime, ArchiveFormat);
var tempFile = Path.Combine(TempFolder, backupName);
var storagePath = tempFile;
try
@ -502,7 +504,7 @@ namespace ASC.Data.Backup.Service
{
using var scope = ServiceProvider.CreateScope();
var scopeClass = scope.ServiceProvider.GetService<BackupWorkerScope>();
var (tenantManager, backupStorageFactory, notifyHelper, _, backupWorker, _, restorePortalTask, _) = scopeClass;
var (tenantManager, backupStorageFactory, notifyHelper, _, backupWorker, _, restorePortalTask, _, _) = scopeClass;
Tenant tenant = null;
var tempFile = PathHelper.GetTempFileName(TempFolder);
try
@ -661,7 +663,7 @@ namespace ASC.Data.Backup.Service
{
using var scope = ServiceProvider.CreateScope();
var scopeClass = scope.ServiceProvider.GetService<BackupWorkerScope>();
var (tenantManager, _, notifyHelper, _, backupWorker, _, _, transferPortalTask) = scopeClass;
var (tenantManager, _, notifyHelper, _, backupWorker, _, _, transferPortalTask, _) = scopeClass;
var tempFile = PathHelper.GetTempFileName(TempFolder);
var tenant = tenantManager.GetTenant(TenantId);
var alias = tenant.TenantAlias;
@ -800,6 +802,7 @@ namespace ASC.Data.Backup.Service
private BackupPortalTask BackupPortalTask { get; }
private RestorePortalTask RestorePortalTask { get; }
private TransferPortalTask TransferPortalTask { get; }
public CoreBaseSettings CoreBaseSettings { get; }
public BackupWorkerScope(TenantManager tenantManager,
BackupStorageFactory backupStorageFactory,
@ -808,7 +811,8 @@ namespace ASC.Data.Backup.Service
BackupWorker backupWorker,
BackupPortalTask backupPortalTask,
RestorePortalTask restorePortalTask,
TransferPortalTask transferPortalTask)
TransferPortalTask transferPortalTask,
CoreBaseSettings coreBaseSettings)
{
TenantManager = tenantManager;
BackupStorageFactory = backupStorageFactory;
@ -818,6 +822,7 @@ namespace ASC.Data.Backup.Service
BackupPortalTask = backupPortalTask;
RestorePortalTask = restorePortalTask;
TransferPortalTask = transferPortalTask;
CoreBaseSettings = coreBaseSettings;
}
public void Deconstruct(out TenantManager tenantManager,
@ -827,7 +832,8 @@ namespace ASC.Data.Backup.Service
out BackupWorker backupWorker,
out BackupPortalTask backupPortalTask,
out RestorePortalTask restorePortalTask,
out TransferPortalTask transferPortalTask)
out TransferPortalTask transferPortalTask,
out CoreBaseSettings coreBaseSettings)
{
tenantManager = TenantManager;
backupStorageFactory = BackupStorageFactory;
@ -837,6 +843,7 @@ namespace ASC.Data.Backup.Service
backupPortalTask = BackupPortalTask;
restorePortalTask = RestorePortalTask;
transferPortalTask = TransferPortalTask;
coreBaseSettings = CoreBaseSettings;
}
}

View File

@ -261,7 +261,7 @@ namespace ASC.Data.Backup.Tasks.Modules
{
value = Regex.Replace(
Convert.ToString(value),
@"(?<=""message_id"":|/products/crm/httphandlers/filehandler\.ashx\?action=mailmessage&message_id=)\d+",
@"(?<=""message_id"":|/Products/CRM/HttpHandlers/filehandler\.ashx\?action=mailmessage&message_id=)\d+",
match =>
{
var mappedMessageId = Convert.ToString(columnMapper.GetMapping(relation.ParentTable, relation.ParentColumn, match.Value));

View File

@ -129,7 +129,7 @@ namespace ASC.Data.Backup.Tasks
return files.Distinct();
}
protected virtual bool IsStorageModuleAllowed(string storageModuleName)
protected bool IsStorageModuleAllowed(string storageModuleName)
{
var allowedStorageModules = new List<string>
{
@ -144,7 +144,9 @@ namespace ASC.Data.Backup.Tasks
"fckuploaders",
"talk",
"mailaggregator",
"whitelabel"
"whitelabel",
"customnavigation",
"userPhotos"
};
if (!allowedStorageModules.Contains(storageModuleName))

View File

@ -55,15 +55,26 @@ namespace ASC.Data.Backup.Tasks
public bool ReplaceDate { get; set; }
public bool Dump { get; set; }
private CoreBaseSettings CoreBaseSettings { get; set; }
private LicenseReader LicenseReader { get; set; }
private LicenseReader LicenseReader { get; set; }
public TenantManager TenantManager { get; }
private AscCacheNotify AscCacheNotify { get; set; }
private IOptionsMonitor<ILog> Options { get; set; }
public RestorePortalTask(DbFactory dbFactory, IOptionsMonitor<ILog> options, StorageFactory storageFactory, StorageFactoryConfig storageFactoryConfig, CoreBaseSettings coreBaseSettings, LicenseReader licenseReader, AscCacheNotify ascCacheNotify, ModuleProvider moduleProvider)
public RestorePortalTask(
DbFactory dbFactory,
IOptionsMonitor<ILog> options,
StorageFactory storageFactory,
StorageFactoryConfig storageFactoryConfig,
CoreBaseSettings coreBaseSettings,
LicenseReader licenseReader,
TenantManager tenantManager,
AscCacheNotify ascCacheNotify,
ModuleProvider moduleProvider)
: base(dbFactory, options, storageFactory, storageFactoryConfig, moduleProvider)
{
CoreBaseSettings = coreBaseSettings;
LicenseReader = licenseReader;
LicenseReader = licenseReader;
TenantManager = tenantManager;
AscCacheNotify = ascCacheNotify;
Options = options;
}
@ -119,7 +130,13 @@ namespace ASC.Data.Backup.Tasks
Logger.Debug("end restore data");
if (ProcessStorage)
{
{
if (CoreBaseSettings.Standalone)
{
Logger.Debug("clear cache");
AscCacheNotify.ClearCache();
}
DoRestoreStorage(dataReader);
}
if (UnblockPortalAfterCompleted)
@ -160,7 +177,23 @@ namespace ASC.Data.Backup.Tasks
var stepscount = keys.Count * 2 + upgrades.Count;
SetStepsCount(ProcessStorage ? stepscount + 1 : stepscount);
SetStepsCount(ProcessStorage ? stepscount + 1 : stepscount);
if (ProcessStorage)
{
var storageModules = StorageFactoryConfig.GetModuleList(ConfigPath).Where(IsStorageModuleAllowed);
var tenants = TenantManager.GetTenants(false);
stepscount += storageModules.Count() * tenants.Count;
SetStepsCount(stepscount + 1);
DoDeleteStorage(storageModules, tenants);
}
else
{
SetStepsCount(stepscount);
}
for (var i = 0; i < keys.Count; i += TasksLimit)
{
@ -284,6 +317,42 @@ namespace ASC.Data.Backup.Tasks
SetStepCompleted();
}
Logger.Debug("end restore storage");
}
private void DoDeleteStorage(IEnumerable<string> storageModules, IEnumerable<Tenant> tenants)
{
Logger.Debug("begin delete storage");
foreach (var tenant in tenants)
{
foreach (var module in storageModules)
{
var storage = StorageFactory.GetStorage(ConfigPath, tenant.TenantId.ToString(), module);
var domains = StorageFactoryConfig.GetDomainList(ConfigPath, module).ToList();
domains.Add(string.Empty); //instead storage.DeleteFiles("\\", "*.*", true);
foreach (var domain in domains)
{
ActionInvoker.Try(
state =>
{
if (storage.IsDirectory((string)state))
{
storage.DeleteFiles((string)state, "\\", "*.*", true);
}
},
domain,
5,
onFailure: error => Logger.WarnFormat("Can't delete files for domain {0}: \r\n{1}", domain, error)
);
}
SetStepCompleted();
}
}
Logger.Debug("end delete storage");
}
private IEnumerable<BackupFileInfo> GetFilesToProcess(IDataReadOperator dataReader)
@ -299,14 +368,6 @@ namespace ASC.Data.Backup.Tasks
}
}
protected override bool IsStorageModuleAllowed(string storageModuleName)
{
if (storageModuleName == "fckuploaders")
return false;
return base.IsStorageModuleAllowed(storageModuleName);
}
private void SetTenantActive(int tenantId)
{
using (var connection = DbFactory.OpenConnection())

View File

@ -79,7 +79,8 @@ namespace ASC.Notify
SenderType = m.Sender,
CreationDate = new DateTime(m.CreationDate),
ReplyTo = m.ReplyTo,
Attachments = m.EmbeddedAttachments.ToString()
Attachments = m.EmbeddedAttachments.ToString(),
AutoSubmitted = m.AutoSubmitted
};
notifyQueue = dbContext.NotifyQueue.Add(notifyQueue).Entity;
@ -135,7 +136,8 @@ namespace ASC.Notify
Content = r.queue.Content,
Sender = r.queue.SenderType,
CreationDate = r.queue.CreationDate.Ticks,
ReplyTo = r.queue.ReplyTo
ReplyTo = r.queue.ReplyTo,
AutoSubmitted = r.queue.AutoSubmitted
};
try
{

View File

@ -0,0 +1,30 @@
<Project Sdk="Microsoft.NET.Sdk.Web">
<PropertyGroup>
<TargetFramework>netcoreapp3.1</TargetFramework>
<ApplicationIcon />
<OutputType>Exe</OutputType>
</PropertyGroup>
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Release|AnyCPU'">
<DebugType>none</DebugType>
<DebugSymbols>false</DebugSymbols>
<NoWarn>1701;1702;NU1701</NoWarn>
</PropertyGroup>
<ItemGroup>
<PackageReference Include="Newtonsoft.Json" Version="12.0.3" />
<PackageReference Include="Telegram.Bot" Version="15.7.1" />
</ItemGroup>
<ItemGroup>
<ProjectReference Include="..\..\ASC.Api.Core\ASC.Api.Core.csproj" />
<ProjectReference Include="..\..\ASC.Common\ASC.Common.csproj" />
<ProjectReference Include="..\..\ASC.Core.Common\ASC.Core.Common.csproj" />
<ProjectReference Include="..\..\ASC.FederatedLogin\ASC.FederatedLogin.csproj" />
</ItemGroup>
<ItemGroup>
<Folder Include="Properties\" />
</ItemGroup>
</Project>

View File

@ -0,0 +1,82 @@
/*
*
* (c) Copyright Ascensio System Limited 2010-2020
*
* This program is freeware. You can redistribute it and/or modify it under the terms of the GNU
* General Public License (GPL) version 3 as published by the Free Software Foundation (https://www.gnu.org/copyleft/gpl.html).
* In accordance with Section 7(a) of the GNU GPL its Section 15 shall be amended to the effect that
* Ascensio System SIA expressly excludes the warranty of non-infringement of any third-party rights.
*
* THIS PROGRAM IS DISTRIBUTED WITHOUT ANY WARRANTY; WITHOUT EVEN THE IMPLIED WARRANTY OF MERCHANTABILITY OR
* FITNESS FOR A PARTICULAR PURPOSE. For more details, see GNU GPL at https://www.gnu.org/copyleft/gpl.html
*
* You can contact Ascensio System SIA by email at sales@onlyoffice.com
*
* The interactive user interfaces in modified source and object code versions of ONLYOFFICE must display
* Appropriate Legal Notices, as required under Section 5 of the GNU GPL version 3.
*
* Pursuant to Section 7 § 3(b) of the GNU GPL you must retain the original ONLYOFFICE logo which contains
* relevant author attributions when distributing the software. If the display of the logo in its graphic
* form is not reasonably feasible for technical reasons, you must include the words "Powered by ONLYOFFICE"
* in every copy of the program you distribute.
* Pursuant to Section 7 § 3(e) we decline to grant you any rights under trademark law for use of our trademarks.
*
*/
using System;
using System.Runtime.Caching;
using System.Threading.Tasks;
using ASC.Common;
using ASC.Core.Common.Notify.Telegram;
using ASC.TelegramService.Core;
using Microsoft.Extensions.Options;
namespace ASC.TelegramService.Commands
{
public class UserCommands : CommandContext
{
private CachedTelegramDao CachedTelegramDao { get; }
public UserCommands(IOptionsSnapshot<CachedTelegramDao> cachedTelegramDao)
{
CachedTelegramDao = cachedTelegramDao.Value;
}
[Command("start")]
public async Task StartCommand(string token)
{
if (string.IsNullOrEmpty(token)) return;
var user = MemoryCache.Default.Get(token);
if (user != null)
{
MemoryCache.Default.Remove(token);
MemoryCache.Default.Remove((string)user);
var split = ((string)user).Split(':');
var guid = Guid.Parse(split[0]);
var tenant = int.Parse(split[1]);
if (tenant == TenantId)
{
CachedTelegramDao.RegisterUser(guid, tenant, Context.User.Id);
await ReplyAsync("Ok!");
return;
}
}
await ReplyAsync("Error");
}
}
public static class UserCommandsExtension
{
public static DIHelper AddUserCommandsService(this DIHelper services)
{
services.TryAddScoped<UserCommands>();
return services.AddCachedTelegramDaoService();
}
}
}

View File

@ -0,0 +1,51 @@
/*
*
* (c) Copyright Ascensio System Limited 2010-2020
*
* This program is freeware. You can redistribute it and/or modify it under the terms of the GNU
* General Public License (GPL) version 3 as published by the Free Software Foundation (https://www.gnu.org/copyleft/gpl.html).
* In accordance with Section 7(a) of the GNU GPL its Section 15 shall be amended to the effect that
* Ascensio System SIA expressly excludes the warranty of non-infringement of any third-party rights.
*
* THIS PROGRAM IS DISTRIBUTED WITHOUT ANY WARRANTY; WITHOUT EVEN THE IMPLIED WARRANTY OF MERCHANTABILITY OR
* FITNESS FOR A PARTICULAR PURPOSE. For more details, see GNU GPL at https://www.gnu.org/copyleft/gpl.html
*
* You can contact Ascensio System SIA by email at sales@onlyoffice.com
*
* The interactive user interfaces in modified source and object code versions of ONLYOFFICE must display
* Appropriate Legal Notices, as required under Section 5 of the GNU GPL version 3.
*
* Pursuant to Section 7 § 3(b) of the GNU GPL you must retain the original ONLYOFFICE logo which contains
* relevant author attributions when distributing the software. If the display of the logo in its graphic
* form is not reasonably feasible for technical reasons, you must include the words "Powered by ONLYOFFICE"
* in every copy of the program you distribute.
* Pursuant to Section 7 § 3(e) we decline to grant you any rights under trademark law for use of our trademarks.
*
*/
using System;
namespace ASC.TelegramService.Core
{
[AttributeUsage(AttributeTargets.Method, Inherited = false, AllowMultiple = false)]
public class CommandAttribute : Attribute
{
public CommandAttribute(string name)
{
Name = name.ToLowerInvariant();
}
public string Name { get; private set; }
}
[AttributeUsage(AttributeTargets.Class, Inherited = false, AllowMultiple = false)]
public class ParamParserAttribute : Attribute
{
public ParamParserAttribute(Type type)
{
Type = type;
}
public Type Type { get; private set; }
}
}

View File

@ -0,0 +1,203 @@
/*
*
* (c) Copyright Ascensio System Limited 2010-2020
*
* This program is freeware. You can redistribute it and/or modify it under the terms of the GNU
* General Public License (GPL) version 3 as published by the Free Software Foundation (https://www.gnu.org/copyleft/gpl.html).
* In accordance with Section 7(a) of the GNU GPL its Section 15 shall be amended to the effect that
* Ascensio System SIA expressly excludes the warranty of non-infringement of any third-party rights.
*
* THIS PROGRAM IS DISTRIBUTED WITHOUT ANY WARRANTY; WITHOUT EVEN THE IMPLIED WARRANTY OF MERCHANTABILITY OR
* FITNESS FOR A PARTICULAR PURPOSE. For more details, see GNU GPL at https://www.gnu.org/copyleft/gpl.html
*
* You can contact Ascensio System SIA by email at sales@onlyoffice.com
*
* The interactive user interfaces in modified source and object code versions of ONLYOFFICE must display
* Appropriate Legal Notices, as required under Section 5 of the GNU GPL version 3.
*
* Pursuant to Section 7 § 3(b) of the GNU GPL you must retain the original ONLYOFFICE logo which contains
* relevant author attributions when distributing the software. If the display of the logo in its graphic
* form is not reasonably feasible for technical reasons, you must include the words "Powered by ONLYOFFICE"
* in every copy of the program you distribute.
* Pursuant to Section 7 § 3(e) we decline to grant you any rights under trademark law for use of our trademarks.
*
*/
using System;
using System.Collections.Generic;
using System.Linq;
using System.Reflection;
using System.Text.RegularExpressions;
using System.Threading.Tasks;
using ASC.Common;
using ASC.Common.Logging;
using ASC.TelegramService.Commands;
using Microsoft.Extensions.Options;
using Microsoft.Extensions.DependencyInjection;
using Telegram.Bot;
using Telegram.Bot.Types;
namespace ASC.TelegramService.Core
{
public class TelegramCommand
{
public string CommandName { get; private set; }
public string[] Args { get; private set; }
public Message Message { get; private set; }
public User User { get { return Message.From; } }
public Chat Chat { get { return Message.Chat; } }
public TelegramCommand(Message msg, string cmdName, string[] args = null)
{
Message = msg;
CommandName = cmdName;
Args = args;
}
}
public class CommandModule
{
private ILog Log { get; }
private readonly Regex cmdReg = new Regex(@"^\/([^\s]+)\s?(.*)");
private readonly Regex argsReg = new Regex(@"[^""\s]\S*|"".+?""");
private readonly Dictionary<string, MethodInfo> commands = new Dictionary<string, MethodInfo>();
private readonly Dictionary<string, Type> contexts = new Dictionary<string, Type>();
private readonly Dictionary<Type, ParamParser> parsers = new Dictionary<Type, ParamParser>();
private IServiceProvider ServiceProvider { get; }
public CommandModule(IOptionsMonitor<ILog> options, IServiceProvider serviceProvider)
{
ServiceProvider = serviceProvider;
Log = options.CurrentValue;
var assembly = Assembly.GetExecutingAssembly();
foreach (var t in assembly.GetExportedTypes())
{
if (t.IsAbstract) continue;
if (t.IsSubclassOf(typeof(CommandContext)))
{
foreach (var method in t.GetRuntimeMethods())
{
if (method.IsPublic && Attribute.IsDefined(method, typeof(CommandAttribute)))
{
var attr = method.GetCustomAttribute<CommandAttribute>();
commands.Add(attr.Name, method);
contexts.Add(attr.Name, t);
}
}
}
if (t.IsSubclassOf(typeof(ParamParser)) && Attribute.IsDefined(t, typeof(ParamParserAttribute)))
{
parsers.Add(t.GetCustomAttribute<ParamParserAttribute>().Type, (ParamParser)Activator.CreateInstance(t));
}
}
}
private TelegramCommand ParseCommand(Message msg)
{
var reg = cmdReg.Match(msg.Text);
var args = argsReg.Matches(reg.Groups[2].Value);
return new TelegramCommand(msg, reg.Groups[1].Value.ToLowerInvariant(), args.Count > 0 ? args.Cast<Match>().Select(a => a.Value).ToArray() : null);
}
private object[] ParseParams(MethodInfo cmd, string[] args)
{
List<object> parsedParams = new List<object>();
var cmdArgs = cmd.GetParameters();
if (cmdArgs.Any() && args == null || cmdArgs.Count() != args.Count()) throw new Exception("Wrong parameters count");
for (var i = 0; i < cmdArgs.Count(); i++)
{
var type = cmdArgs[i].ParameterType;
if (type == typeof(string))
{
parsedParams.Add(args[i]);
continue;
}
if (!parsers.ContainsKey(type)) throw new Exception(string.Format("No parser found for type '{0}'", type));
parsedParams.Add(parsers[cmdArgs[i].ParameterType].FromString(args[i]));
}
return parsedParams.ToArray();
}
public async Task HandleCommand(Message msg, TelegramBotClient client, int tenantId)
{
try
{
var cmd = ParseCommand(msg);
if (!commands.ContainsKey(cmd.CommandName)) throw new Exception(string.Format("No handler found for command '{0}'", cmd.CommandName));
var command = commands[cmd.CommandName];
var context = (CommandContext)ServiceProvider.CreateScope().ServiceProvider.GetService(contexts[cmd.CommandName]);
var param = ParseParams(command, cmd.Args);
context.Context = cmd;
context.Client = client;
context.TenantId = tenantId;
await Task.FromResult(command.Invoke(context, param));
}
catch (Exception ex)
{
Log.DebugFormat("Couldn't handle ({0}) message ({1})", msg.Text, ex.Message);
}
}
}
public abstract class CommandContext
{
public ITelegramBotClient Client { get; set; }
public TelegramCommand Context { get; set; }
public int TenantId { get; set; }
protected async Task ReplyAsync(string message)
{
await Client.SendTextMessageAsync(Context.Chat, message);
}
}
public abstract class ParamParser
{
protected Type type;
protected ParamParser(Type type)
{
this.type = type;
}
public abstract object FromString(string arg);
public abstract string ToString(object arg);
}
public abstract class ParamParser<T> : ParamParser
{
public ParamParser() : base(typeof(T)) { }
public override abstract object FromString(string arg);
public override abstract string ToString(object arg);
}
public static class CommandModuleExtension
{
public static DIHelper AddCommandModuleService(this DIHelper services)
{
services.TryAddSingleton<CommandModule>();
return services.AddUserCommandsService();
}
}
}

View File

@ -0,0 +1,42 @@
/*
*
* (c) Copyright Ascensio System Limited 2010-2020
*
* This program is freeware. You can redistribute it and/or modify it under the terms of the GNU
* General Public License (GPL) version 3 as published by the Free Software Foundation (https://www.gnu.org/copyleft/gpl.html).
* In accordance with Section 7(a) of the GNU GPL its Section 15 shall be amended to the effect that
* Ascensio System SIA expressly excludes the warranty of non-infringement of any third-party rights.
*
* THIS PROGRAM IS DISTRIBUTED WITHOUT ANY WARRANTY; WITHOUT EVEN THE IMPLIED WARRANTY OF MERCHANTABILITY OR
* FITNESS FOR A PARTICULAR PURPOSE. For more details, see GNU GPL at https://www.gnu.org/copyleft/gpl.html
*
* You can contact Ascensio System SIA by email at sales@onlyoffice.com
*
* The interactive user interfaces in modified source and object code versions of ONLYOFFICE must display
* Appropriate Legal Notices, as required under Section 5 of the GNU GPL version 3.
*
* Pursuant to Section 7 § 3(b) of the GNU GPL you must retain the original ONLYOFFICE logo which contains
* relevant author attributions when distributing the software. If the display of the logo in its graphic
* form is not reasonably feasible for technical reasons, you must include the words "Powered by ONLYOFFICE"
* in every copy of the program you distribute.
* Pursuant to Section 7 § 3(e) we decline to grant you any rights under trademark law for use of our trademarks.
*
*/
namespace ASC.TelegramService.Core.Parsers
{
[ParamParser(typeof(int))]
public class IntParser : ParamParser<int>
{
public override object FromString(string arg)
{
return int.Parse(arg);
}
public override string ToString(object arg)
{
return arg.ToString();
}
}
}

View File

@ -0,0 +1,37 @@
/*
*
* (c) Copyright Ascensio System Limited 2010-2020
*
* This program is freeware. You can redistribute it and/or modify it under the terms of the GNU
* General Public License (GPL) version 3 as published by the Free Software Foundation (https://www.gnu.org/copyleft/gpl.html).
* In accordance with Section 7(a) of the GNU GPL its Section 15 shall be amended to the effect that
* Ascensio System SIA expressly excludes the warranty of non-infringement of any third-party rights.
*
* THIS PROGRAM IS DISTRIBUTED WITHOUT ANY WARRANTY; WITHOUT EVEN THE IMPLIED WARRANTY OF MERCHANTABILITY OR
* FITNESS FOR A PARTICULAR PURPOSE. For more details, see GNU GPL at https://www.gnu.org/copyleft/gpl.html
*
* You can contact Ascensio System SIA by email at sales@onlyoffice.com
*
* The interactive user interfaces in modified source and object code versions of ONLYOFFICE must display
* Appropriate Legal Notices, as required under Section 5 of the GNU GPL version 3.
*
* Pursuant to Section 7 § 3(b) of the GNU GPL you must retain the original ONLYOFFICE logo which contains
* relevant author attributions when distributing the software. If the display of the logo in its graphic
* form is not reasonably feasible for technical reasons, you must include the words "Powered by ONLYOFFICE"
* in every copy of the program you distribute.
* Pursuant to Section 7 § 3(e) we decline to grant you any rights under trademark law for use of our trademarks.
*
*/
using Telegram.Bot;
namespace ASC.TelegramService.Core
{
public class TenantTgClient
{
public string Token { get; set; }
public TelegramBotClient Client { get; set; }
public string Proxy { get; set; }
public int TokenLifeSpan { get; set; }
public int TenantId { get; set; }
}
}

View File

@ -0,0 +1,73 @@
/*
*
* (c) Copyright Ascensio System Limited 2010-2020
*
* This program is freeware. You can redistribute it and/or modify it under the terms of the GNU
* General Public License (GPL) version 3 as published by the Free Software Foundation (https://www.gnu.org/copyleft/gpl.html).
* In accordance with Section 7(a) of the GNU GPL its Section 15 shall be amended to the effect that
* Ascensio System SIA expressly excludes the warranty of non-infringement of any third-party rights.
*
* THIS PROGRAM IS DISTRIBUTED WITHOUT ANY WARRANTY; WITHOUT EVEN THE IMPLIED WARRANTY OF MERCHANTABILITY OR
* FITNESS FOR A PARTICULAR PURPOSE. For more details, see GNU GPL at https://www.gnu.org/copyleft/gpl.html
*
* You can contact Ascensio System SIA by email at sales@onlyoffice.com
*
* The interactive user interfaces in modified source and object code versions of ONLYOFFICE must display
* Appropriate Legal Notices, as required under Section 5 of the GNU GPL version 3.
*
* Pursuant to Section 7 § 3(b) of the GNU GPL you must retain the original ONLYOFFICE logo which contains
* relevant author attributions when distributing the software. If the display of the logo in its graphic
* form is not reasonably feasible for technical reasons, you must include the words "Powered by ONLYOFFICE"
* in every copy of the program you distribute.
* Pursuant to Section 7 § 3(e) we decline to grant you any rights under trademark law for use of our trademarks.
*
*/
using System.Collections.Generic;
using System.IO;
using System.Threading.Tasks;
using Microsoft.AspNetCore.Hosting;
using Microsoft.Extensions.Configuration;
using Microsoft.Extensions.Hosting;
namespace ASC.TelegramService
{
public class Program
{
public static async Task Main(string[] args)
{
Host.CreateDefaultBuilder(args)
.ConfigureWebHostDefaults(webBuilder =>
{
webBuilder.UseStartup<Startup>();
})
.ConfigureAppConfiguration((hostContext, config) =>
{
var buided = config.Build();
var path = buided["pathToConf"];
if (!Path.IsPathRooted(path))
{
path = Path.GetFullPath(Path.Combine(hostContext.HostingEnvironment.ContentRootPath, path));
}
config.SetBasePath(path);
var env = hostContext.Configuration.GetValue("ENVIRONMENT", "Production");
config
.AddInMemoryCollection(new Dictionary<string, string>
{
{"pathToConf", path }
}
)
.AddJsonFile("appsettings.json")
.AddJsonFile($"appsettings.{env}.json", true)
.AddJsonFile("storage.json")
.AddJsonFile("notify.json")
.AddJsonFile("kafka.json")
.AddJsonFile($"kafka.{env}.json", true)
.AddEnvironmentVariables();
})
.UseConsoleLifetime()
.Build()
.Run();
}
}
}

View File

@ -0,0 +1,35 @@
{
"iisSettings": {
"windowsAuthentication": false,
"anonymousAuthentication": true,
"iisExpress": {
"applicationUrl": "http://localhost:51702/",
"sslPort": 0
}
},
"profiles": {
"IIS Express": {
"commandName": "IISExpress",
"launchBrowser": false,
"environmentVariables": {
"ASPNETCORE_ENVIRONMENT": "Development",
"$STORAGE_ROOT": "../../../Data",
"log__name": "telegram",
"log__dir": "../../../Logs",
"core__products__folder": "../../../products"
}
},
"ASC.TelegramService": {
"commandName": "Project",
"launchBrowser": false,
"environmentVariables": {
"ASPNETCORE_ENVIRONMENT": "Development",
"$STORAGE_ROOT": "../../../Data",
"log__name": "telegram",
"log__dir": "../../../Logs",
"core__products__folder": "../../../products"
},
"applicationUrl": "http://localhost:51702/"
}
}
}

View File

@ -0,0 +1,60 @@
/*
*
* (c) Copyright Ascensio System Limited 2010-2020
*
* This program is freeware. You can redistribute it and/or modify it under the terms of the GNU
* General Public License (GPL) version 3 as published by the Free Software Foundation (https://www.gnu.org/copyleft/gpl.html).
* In accordance with Section 7(a) of the GNU GPL its Section 15 shall be amended to the effect that
* Ascensio System SIA expressly excludes the warranty of non-infringement of any third-party rights.
*
* THIS PROGRAM IS DISTRIBUTED WITHOUT ANY WARRANTY; WITHOUT EVEN THE IMPLIED WARRANTY OF MERCHANTABILITY OR
* FITNESS FOR A PARTICULAR PURPOSE. For more details, see GNU GPL at https://www.gnu.org/copyleft/gpl.html
*
* You can contact Ascensio System SIA by email at sales@onlyoffice.com
*
* The interactive user interfaces in modified source and object code versions of ONLYOFFICE must display
* Appropriate Legal Notices, as required under Section 5 of the GNU GPL version 3.
*
* Pursuant to Section 7 § 3(b) of the GNU GPL you must retain the original ONLYOFFICE logo which contains
* relevant author attributions when distributing the software. If the display of the logo in its graphic
* form is not reasonably feasible for technical reasons, you must include the words "Powered by ONLYOFFICE"
* in every copy of the program you distribute.
* Pursuant to Section 7 § 3(e) we decline to grant you any rights under trademark law for use of our trademarks.
*
*/
using ASC.Api.Core;
using ASC.Common;
using Autofac.Extensions.DependencyInjection;
using Microsoft.Extensions.Configuration;
using Microsoft.Extensions.DependencyInjection;
using Microsoft.Extensions.Hosting;
using ASC.Common.DependencyInjection;
namespace ASC.TelegramService
{
public class Startup : BaseStartup
{
public override string[] LogParams { get => new string[] { "ASC.TelegramService" }; }
public Startup(IConfiguration configuration, IHostEnvironment hostEnvironment) : base(configuration, hostEnvironment)
{
}
public override void ConfigureServices(IServiceCollection services)
{
var diHelper = new DIHelper(services);
diHelper.AddTelegramLauncher();
services.AddHostedService<TelegramLauncher>();
base.ConfigureServices(services);
services.AddAutofac(Configuration, HostEnvironment.ContentRootPath);
}
}
}

View File

@ -0,0 +1,186 @@
/*
*
* (c) Copyright Ascensio System Limited 2010-2020
*
* This program is freeware. You can redistribute it and/or modify it under the terms of the GNU
* General Public License (GPL) version 3 as published by the Free Software Foundation (https://www.gnu.org/copyleft/gpl.html).
* In accordance with Section 7(a) of the GNU GPL its Section 15 shall be amended to the effect that
* Ascensio System SIA expressly excludes the warranty of non-infringement of any third-party rights.
*
* THIS PROGRAM IS DISTRIBUTED WITHOUT ANY WARRANTY; WITHOUT EVEN THE IMPLIED WARRANTY OF MERCHANTABILITY OR
* FITNESS FOR A PARTICULAR PURPOSE. For more details, see GNU GPL at https://www.gnu.org/copyleft/gpl.html
*
* You can contact Ascensio System SIA by email at sales@onlyoffice.com
*
* The interactive user interfaces in modified source and object code versions of ONLYOFFICE must display
* Appropriate Legal Notices, as required under Section 5 of the GNU GPL version 3.
*
* Pursuant to Section 7 § 3(b) of the GNU GPL you must retain the original ONLYOFFICE logo which contains
* relevant author attributions when distributing the software. If the display of the logo in its graphic
* form is not reasonably feasible for technical reasons, you must include the words "Powered by ONLYOFFICE"
* in every copy of the program you distribute.
* Pursuant to Section 7 § 3(e) we decline to grant you any rights under trademark law for use of our trademarks.
*
*/
using System;
using System.Collections.Generic;
using System.Net;
using System.Runtime.Caching;
using ASC.Common.Logging;
using ASC.Core.Common.Notify.Telegram;
using ASC.Notify.Messages;
using ASC.TelegramService.Core;
using Telegram.Bot;
using Telegram.Bot.Args;
using ASC.Common;
using Microsoft.Extensions.Options;
using Microsoft.Extensions.DependencyInjection;
using ASC.Core.Common.Notify;
namespace ASC.TelegramService
{
public class TelegramHandler
{
private Dictionary<int, TenantTgClient> Clients { get; set; }
private CommandModule Command { get; set; }
private ILog Log { get; set; }
private IServiceProvider ServiceProvider { get; set; }
public TelegramHandler(CommandModule command, IOptionsMonitor<ILog> option, IServiceProvider serviceProvider)
{
Command = command;
Log = option.CurrentValue;
ServiceProvider = serviceProvider;
Clients = new Dictionary<int, TenantTgClient>();
ServicePointManager.SecurityProtocol |= SecurityProtocolType.Tls12 | SecurityProtocolType.Tls13;
}
public async void SendMessage(NotifyMessage msg)
{
var scope = ServiceProvider.CreateScope();
var cachedTelegramDao = scope.ServiceProvider.GetService<IOptionsSnapshot<CachedTelegramDao>>().Value;
if (string.IsNullOrEmpty(msg.To)) return;
if (!Clients.ContainsKey(msg.Tenant)) return;
var client = Clients[msg.Tenant].Client;
try
{
var tgUser = cachedTelegramDao.GetUser(Guid.Parse(msg.To), msg.Tenant);
if (tgUser == null)
{
Log.DebugFormat("Couldn't find telegramId for user '{0}'", msg.To);
return;
}
var chat = await client.GetChatAsync(tgUser.TelegramUserId);
await client.SendTextMessageAsync(chat, msg.Content, Telegram.Bot.Types.Enums.ParseMode.Markdown);
}
catch (Exception e)
{
Log.DebugFormat("Couldn't send message for user '{0}' got an '{1}'", msg.To, e.Message);
}
}
public void DisableClient(int tenantId)
{
if (!Clients.ContainsKey(tenantId)) return;
var client = Clients[tenantId];
client.Client.StopReceiving();
Clients.Remove(tenantId);
}
public void CreateOrUpdateClientForTenant(int tenantId, string token, int tokenLifespan, string proxy, bool startTelegramService, bool force = false)
{
var scope = ServiceProvider.CreateScope();
var telegramHelper = scope.ServiceProvider.GetService<TelegramHelper>();
var newClient = telegramHelper.InitClient(token, proxy);
if (Clients.ContainsKey(tenantId))
{
var client = Clients[tenantId];
client.TokenLifeSpan = tokenLifespan;
if (token != client.Token || proxy != client.Proxy)
{
if (startTelegramService)
{
if (!telegramHelper.TestingClient(newClient)) return;
}
client.Client.StopReceiving();
BindClient(newClient, tenantId);
client.Client = newClient;
client.Token = token;
client.Proxy = proxy;
}
}
else
{
if (!force && startTelegramService)
{
if (!telegramHelper.TestingClient(newClient)) return;
}
BindClient(newClient, tenantId);
Clients.Add(tenantId, new TenantTgClient()
{
Token = token,
Client = newClient,
Proxy = proxy,
TenantId = tenantId,
TokenLifeSpan = tokenLifespan
});
}
}
public void RegisterUser(string userId, int tenantId, string token)
{
if (!Clients.ContainsKey(tenantId)) return;
var userKey = UserKey(userId, tenantId);
var dateExpires = DateTimeOffset.Now.AddMinutes(Clients[tenantId].TokenLifeSpan);
MemoryCache.Default.Set(token, userKey, dateExpires);
}
private async void OnMessage(object sender, MessageEventArgs e, TelegramBotClient client, int tenantId)
{
if (string.IsNullOrEmpty(e.Message.Text) || e.Message.Text[0] != '/') return;
await Command.HandleCommand(e.Message, client, tenantId);
}
private void BindClient(TelegramBotClient client, int tenantId)
{
client.OnMessage += (sender, e) => { OnMessage(sender, e, client, tenantId); };
client.StartReceiving();
}
private string UserKey(string userId, int tenantId)
{
return string.Format("{0}:{1}", userId, tenantId);
}
}
public static class TelegramHandlerExtension
{
public static DIHelper AddTelegramHandlerService(this DIHelper services)
{
services.TryAddSingleton<TelegramHandler>();
return services.AddCachedTelegramDaoService()
.AddCommandModuleService()
.AddTelegramHelperSerivce();
}
}
}

View File

@ -0,0 +1,120 @@
/*
*
* (c) Copyright Ascensio System Limited 2010-2020
*
* This program is freeware. You can redistribute it and/or modify it under the terms of the GNU
* General Public License (GPL) version 3 as published by the Free Software Foundation (https://www.gnu.org/copyleft/gpl.html).
* In accordance with Section 7(a) of the GNU GPL its Section 15 shall be amended to the effect that
* Ascensio System SIA expressly excludes the warranty of non-infringement of any third-party rights.
*
* THIS PROGRAM IS DISTRIBUTED WITHOUT ANY WARRANTY; WITHOUT EVEN THE IMPLIED WARRANTY OF MERCHANTABILITY OR
* FITNESS FOR A PARTICULAR PURPOSE. For more details, see GNU GPL at https://www.gnu.org/copyleft/gpl.html
*
* You can contact Ascensio System SIA by email at sales@onlyoffice.com
*
* The interactive user interfaces in modified source and object code versions of ONLYOFFICE must display
* Appropriate Legal Notices, as required under Section 5 of the GNU GPL version 3.
*
* Pursuant to Section 7 § 3(b) of the GNU GPL you must retain the original ONLYOFFICE logo which contains
* relevant author attributions when distributing the software. If the display of the logo in its graphic
* form is not reasonably feasible for technical reasons, you must include the words "Powered by ONLYOFFICE"
* in every copy of the program you distribute.
* Pursuant to Section 7 § 3(e) we decline to grant you any rights under trademark law for use of our trademarks.
*
*/
using System;
using System.Threading;
using System.Threading.Tasks;
using ASC.Common;
using ASC.Core;
using ASC.Core.Common.Configuration;
using ASC.Core.Common.Notify;
using ASC.FederatedLogin.LoginProviders;
using ASC.TelegramService.Commands;
using Microsoft.Extensions.DependencyInjection;
using Microsoft.Extensions.Hosting;
namespace ASC.TelegramService
{
public class TelegramLauncher : IHostedService
{
private TelegramListener TelegramListener { get; set; }
private IServiceProvider ServiceProvider { get; set; }
public TelegramLauncher(TelegramListener telegramListener, IServiceProvider serviceProvider)
{
TelegramListener = telegramListener;
ServiceProvider = serviceProvider;
}
public Task StartAsync(CancellationToken cancellationToken)
{
Task.Run(CreateClients);
TelegramListener.Start();
return Task.CompletedTask;
}
public Task StopAsync(CancellationToken cancellationToken)
{
TelegramListener.Stop();
return Task.CompletedTask;
}
private void CreateClients()
{
var scopeClass = ServiceProvider.CreateScope().ServiceProvider.GetService<ScopeTelegramLauncher>();
var (tenantManager, handler, telegramLoginProvider) = scopeClass;
var tenants = tenantManager.GetTenants();
foreach (var tenant in tenants)
{
tenantManager.SetCurrentTenant(tenant);
if (telegramLoginProvider.IsEnabled())
{
handler.CreateOrUpdateClientForTenant(tenant.TenantId, telegramLoginProvider.TelegramBotToken, telegramLoginProvider.TelegramAuthTokenLifespan, telegramLoginProvider.TelegramProxy, true, true);
}
}
}
}
public class ScopeTelegramLauncher
{
private TelegramHandler Handler { get; set; }
private TenantManager TenantManager { get; set; }
private TelegramLoginProvider TelegramLoginProvider { get; set; }
public ScopeTelegramLauncher(TenantManager tenantManager, TelegramHandler telegramHandler, ConsumerFactory consumerFactory)
{
TelegramLoginProvider = consumerFactory.Get<TelegramLoginProvider>();
TenantManager = tenantManager;
Handler = telegramHandler;
}
public void Deconstruct(out TenantManager tenantManager, out TelegramHandler handler, out TelegramLoginProvider telegramLoginProvider)
{
tenantManager = TenantManager;
handler = Handler;
telegramLoginProvider = TelegramLoginProvider;
}
}
public static class TelegramLauncherExtension
{
public static DIHelper AddTelegramLauncher(this DIHelper services)
{
services.TryAddSingleton<TelegramLauncher>();
services.TryAddScoped<ScopeTelegramLauncher>();
return services.AddTelegramService()
.AddTelegramListenerService()
.AddTelegramHandlerService()
.AddTenantManagerService()
.AddTelegramLoginProviderService()
.AddTelegramHelperSerivce()
.AddTelegramServiceClient()
.AddConsumerFactoryService()
.AddUserCommandsService();
}
}
}

View File

@ -0,0 +1,102 @@
/*
*
* (c) Copyright Ascensio System Limited 2010-2020
*
* This program is freeware. You can redistribute it and/or modify it under the terms of the GNU
* General Public License (GPL) version 3 as published by the Free Software Foundation (https://www.gnu.org/copyleft/gpl.html).
* In accordance with Section 7(a) of the GNU GPL its Section 15 shall be amended to the effect that
* Ascensio System SIA expressly excludes the warranty of non-infringement of any third-party rights.
*
* THIS PROGRAM IS DISTRIBUTED WITHOUT ANY WARRANTY; WITHOUT EVEN THE IMPLIED WARRANTY OF MERCHANTABILITY OR
* FITNESS FOR A PARTICULAR PURPOSE. For more details, see GNU GPL at https://www.gnu.org/copyleft/gpl.html
*
* You can contact Ascensio System SIA by email at sales@onlyoffice.com
*
* The interactive user interfaces in modified source and object code versions of ONLYOFFICE must display
* Appropriate Legal Notices, as required under Section 5 of the GNU GPL version 3.
*
* Pursuant to Section 7 § 3(b) of the GNU GPL you must retain the original ONLYOFFICE logo which contains
* relevant author attributions when distributing the software. If the display of the logo in its graphic
* form is not reasonably feasible for technical reasons, you must include the words "Powered by ONLYOFFICE"
* in every copy of the program you distribute.
* Pursuant to Section 7 § 3(e) we decline to grant you any rights under trademark law for use of our trademarks.
*
*/
using ASC.Common;
using ASC.Common.Caching;
using ASC.Core.Common.Notify;
using ASC.Notify.Messages;
namespace ASC.TelegramService
{
public class TelegramListener
{
private ICacheNotify<NotifyMessage> CacheMessage { get; }
private ICacheNotify<RegisterUserProto> CacheRegisterUser { get; }
private ICacheNotify<CreateClientProto> CacheCreateClient { get; }
private ICacheNotify<DisableClientProto> CacheDisableClient { get; }
private TelegramService TelegramService { get; set; }
public TelegramListener(ICacheNotify<NotifyMessage> cacheMessage,
ICacheNotify<RegisterUserProto> cacheRegisterUser,
ICacheNotify<CreateClientProto> cacheCreateClient,
TelegramService telegramService,
ICacheNotify<DisableClientProto> cacheDisableClient)
{
CacheMessage = cacheMessage;
CacheRegisterUser = cacheRegisterUser;
CacheCreateClient = cacheCreateClient;
CacheDisableClient = cacheDisableClient;
TelegramService = telegramService;
}
public void Start()
{
CacheMessage.Subscribe(n=> SendMessage(n), CacheNotifyAction.Insert);
CacheRegisterUser.Subscribe(n=> RegisterUser(n), CacheNotifyAction.Insert);
CacheCreateClient.Subscribe(n=> CreateOrUpdateClient(n), CacheNotifyAction.Insert);
CacheDisableClient.Subscribe(n=> DisableClient(n), CacheNotifyAction.Insert);
}
public void Stop()
{
CacheMessage.Unsubscribe(CacheNotifyAction.Insert);
CacheRegisterUser.Unsubscribe(CacheNotifyAction.Insert);
CacheCreateClient.Unsubscribe(CacheNotifyAction.Insert);
CacheDisableClient.Unsubscribe(CacheNotifyAction.Insert);
}
private void DisableClient(DisableClientProto n)
{
TelegramService.DisableClient(n.TenantId);
}
private void SendMessage(NotifyMessage notifyMessage)
{
TelegramService.SendMessage(notifyMessage);
}
private void RegisterUser(RegisterUserProto registerUserProto)
{
TelegramService.RegisterUser(registerUserProto.UserId, registerUserProto.TenantId, registerUserProto.Token);
}
private void CreateOrUpdateClient(CreateClientProto createClientProto)
{
TelegramService.CreateOrUpdateClient(createClientProto.TenantId, createClientProto.Token, createClientProto.TokenLifespan, createClientProto.Proxy);
}
}
public static class TelegramListenerExtension
{
public static DIHelper AddTelegramListenerService(this DIHelper services)
{
services.TryAddSingleton<TelegramListener>();
return services.AddTelegramService();
}
}
}

View File

@ -0,0 +1,71 @@
/*
*
* (c) Copyright Ascensio System Limited 2010-2020
*
* This program is freeware. You can redistribute it and/or modify it under the terms of the GNU
* General Public License (GPL) version 3 as published by the Free Software Foundation (https://www.gnu.org/copyleft/gpl.html).
* In accordance with Section 7(a) of the GNU GPL its Section 15 shall be amended to the effect that
* Ascensio System SIA expressly excludes the warranty of non-infringement of any third-party rights.
*
* THIS PROGRAM IS DISTRIBUTED WITHOUT ANY WARRANTY; WITHOUT EVEN THE IMPLIED WARRANTY OF MERCHANTABILITY OR
* FITNESS FOR A PARTICULAR PURPOSE. For more details, see GNU GPL at https://www.gnu.org/copyleft/gpl.html
*
* You can contact Ascensio System SIA by email at sales@onlyoffice.com
*
* The interactive user interfaces in modified source and object code versions of ONLYOFFICE must display
* Appropriate Legal Notices, as required under Section 5 of the GNU GPL version 3.
*
* Pursuant to Section 7 § 3(b) of the GNU GPL you must retain the original ONLYOFFICE logo which contains
* relevant author attributions when distributing the software. If the display of the logo in its graphic
* form is not reasonably feasible for technical reasons, you must include the words "Powered by ONLYOFFICE"
* in every copy of the program you distribute.
* Pursuant to Section 7 § 3(e) we decline to grant you any rights under trademark law for use of our trademarks.
*
*/
using ASC.Common;
using ASC.Core.Common.Notify;
using ASC.Notify.Messages;
namespace ASC.TelegramService
{
public class TelegramService : ITelegramService
{
private TelegramHandler TelegramHandler { get; set; }
public TelegramService(TelegramHandler telegramHandler)
{
TelegramHandler = telegramHandler;
}
public void SendMessage(NotifyMessage m)
{
TelegramHandler.SendMessage(m);
}
public void RegisterUser(string userId, int tenantId, string token)
{
TelegramHandler.RegisterUser(userId, tenantId, token);
}
public void DisableClient(int tenantId)
{
TelegramHandler.DisableClient(tenantId);
}
public void CreateOrUpdateClient(int tenantId, string token, int tokenLifespan, string proxy)
{
TelegramHandler.CreateOrUpdateClientForTenant(tenantId, token, tokenLifespan, proxy, false);
}
}
public static class TelegramServiceExtension
{
public static DIHelper AddTelegramService(this DIHelper services)
{
services.TryAddSingleton<TelegramService>();
return services.AddTelegramHandlerService();
}
}
}

View File

@ -0,0 +1,3 @@
{
"pathToConf": "..\\..\\..\\config"
}

View File

@ -54,6 +54,7 @@
"edited-docs" : [ ".pptx",".pptm",".ppt",".ppsx",".ppsm",".pps",".potx",".potm",".pot",".odp",".fodp",".otp",".xlsx",".xlsm",".xls",".xltx",".xltm",".xlt",".ods",".fods",".ots",".csv",".docx",".docm",".doc",".dotx",".dotm",".dot",".odt",".fodt",".ott",".txt",".rtf",".mht",".html",".htm" ],
"encrypted-docs" : [ ".docx",".xlsx",".pptx" ],
"formfilling-docs" : [ ".docx" ],
"customfilter-docs": [ ".xlsx" ],
"reviewed-docs" : [ ".docx" ],
"viewed-docs" : [ ".pptx",".pptm",".ppt",".ppsx",".ppsm",".pps",".potx",".potm",".pot",".odp",".fodp",".otp",".gslides",".xlsx",".xlsm",".xls",".xltx",".xltm",".xlt",".ods",".fods",".ots",".gsheet",".csv",".docx",".docm",".doc",".dotx",".dotm",".dot",".odt",".fodt",".ott",".gdoc",".txt",".rtf",".mht",".html",".htm",".epub",".pdf",".djvu",".xps" ],
"secret" :
@ -63,7 +64,7 @@
},
"url":
{
"public": "http://192.168.3.142/",
"public": "http://192.168.0.142/",
"internal": "",
"portal": ""
}

View File

@ -30,6 +30,38 @@
"bitlyUrl" : "https://api-ssl.bitly.com/v3/shorten?format=xml&amp;login={0}&amp;apiKey={1}&amp;longUrl={2}"
}
}
},
{
"type": "ASC.FederatedLogin.LoginProviders.TelegramLoginProvider, ASC.FederatedLogin",
"services": [
{
"type": "ASC.Core.Common.Configuration.Consumer, ASC.Core.Common"
},
{
"type": "ASC.FederatedLogin.LoginProviders.TelegramLoginProvider, ASC.FederatedLogin"
},
{
"key": "Telegram",
"type": "ASC.Core.Common.Configuration.Consumer, ASC.Core.Common"
},
{
"key": "Telegram",
"type": "ASC.FederatedLogin.LoginProviders.TelegramLoginProvider, ASC.FederatedLogin"
}
],
"instanceScope": "perlifetimescope",
"parameters": {
"name": "Telegram",
"order": "13",
"props": {
"telegramBotToken": "",
"telegramBotName": ""
},
"additional": {
"telegramAuthTokenLifespan" : 20,
"telegramProxy": ""
}
}
},
{
"type": "ASC.FederatedLogin.LoginProviders.BoxLoginProvider, ASC.FederatedLogin",
@ -613,7 +645,12 @@
"additional": {
"handlerType" : "ASC.Data.Storage.S3.S3Storage, ASC.Data.Storage",
"bucket" : "",
"region" : ""
"region" : "",
"serviceurl": "",
"forcepathstyle": "",
"usehttp": "",
"sse": "",
"cdn": "S3Cdn"
}
}
},

View File

@ -68,7 +68,17 @@ namespace ASC.Web.Files.Classes
public bool ForcesaveSetting { get; set; }
[JsonPropertyName("StoreForcesave")]
public bool StoreForcesaveSetting { get; set; }
public bool StoreForcesaveSetting { get; set; }
[JsonPropertyName("HideRecent")]
public bool HideRecentSetting { get; set; }
[JsonPropertyName("HideFavorites")]
public bool HideFavoritesSetting { get; set; }
[JsonPropertyName("HideTemplates")]
public bool HideTemplatesSetting { get; set; }
public ISettings GetDefault(IServiceProvider serviceProvider)
{
@ -84,7 +94,10 @@ namespace ASC.Web.Files.Classes
HideConfirmConvertSaveSetting = false,
HideConfirmConvertOpenSetting = false,
ForcesaveSetting = false,
StoreForcesaveSetting = false
StoreForcesaveSetting = false,
HideRecentSetting = false,
HideFavoritesSetting = false,
HideTemplatesSetting = false
};
}
@ -109,11 +122,11 @@ namespace ASC.Web.Files.Classes
{
set
{
var setting = SettingsManager.LoadForCurrentUser<FilesSettings>();
var setting = LoadForCurrentUser();
setting.FastDeleteSetting = !value;
SettingsManager.SaveForCurrentUser(setting);
SaveForCurrentUser(setting);
}
get { return !SettingsManager.LoadForCurrentUser<FilesSettings>().FastDeleteSetting; }
get { return !LoadForCurrentUser().FastDeleteSetting; }
}
public bool EnableThirdParty
@ -131,69 +144,69 @@ namespace ASC.Web.Files.Classes
{
set
{
var setting = SettingsManager.LoadForCurrentUser<FilesSettings>();
var setting = LoadForCurrentUser();
setting.StoreOriginalFilesSetting = value;
SettingsManager.SaveForCurrentUser(setting);
SaveForCurrentUser(setting);
}
get { return SettingsManager.LoadForCurrentUser<FilesSettings>().StoreOriginalFilesSetting; }
get { return LoadForCurrentUser().StoreOriginalFilesSetting; }
}
public bool UpdateIfExist
{
set
{
var setting = SettingsManager.LoadForCurrentUser<FilesSettings>();
var setting = LoadForCurrentUser();
setting.UpdateIfExistSetting = value;
SettingsManager.SaveForCurrentUser(setting);
SaveForCurrentUser(setting);
}
get { return SettingsManager.LoadForCurrentUser<FilesSettings>().UpdateIfExistSetting; }
get { return LoadForCurrentUser().UpdateIfExistSetting; }
}
public bool ConvertNotify
{
set
{
var setting = SettingsManager.LoadForCurrentUser<FilesSettings>();
var setting = LoadForCurrentUser();
setting.ConvertNotifySetting = value;
SettingsManager.SaveForCurrentUser(setting);
SaveForCurrentUser(setting);
}
get { return SettingsManager.LoadForCurrentUser<FilesSettings>().ConvertNotifySetting; }
get { return LoadForCurrentUser().ConvertNotifySetting; }
}
public bool HideConfirmConvertSave
{
set
{
var setting = SettingsManager.LoadForCurrentUser<FilesSettings>();
var setting = LoadForCurrentUser();
setting.HideConfirmConvertSaveSetting = value;
SettingsManager.SaveForCurrentUser(setting);
SaveForCurrentUser(setting);
}
get { return SettingsManager.LoadForCurrentUser<FilesSettings>().HideConfirmConvertSaveSetting; }
get { return LoadForCurrentUser().HideConfirmConvertSaveSetting; }
}
public bool HideConfirmConvertOpen
{
set
{
var setting = SettingsManager.LoadForCurrentUser<FilesSettings>();
var setting = LoadForCurrentUser();
setting.HideConfirmConvertOpenSetting = value;
SettingsManager.SaveForCurrentUser(setting);
SaveForCurrentUser(setting);
}
get { return SettingsManager.LoadForCurrentUser<FilesSettings>().HideConfirmConvertOpenSetting; }
get { return LoadForCurrentUser().HideConfirmConvertOpenSetting; }
}
public OrderBy DefaultOrder
{
set
{
var setting = SettingsManager.LoadForCurrentUser<FilesSettings>();
var setting = LoadForCurrentUser();
setting.DefaultSortedBySetting = value.SortedBy;
setting.DefaultSortedAscSetting = value.IsAsc;
SettingsManager.SaveForCurrentUser(setting);
SaveForCurrentUser(setting);
}
get
{
var setting = SettingsManager.LoadForCurrentUser<FilesSettings>();
var setting = LoadForCurrentUser();
return new OrderBy(setting.DefaultSortedBySetting, setting.DefaultSortedAscSetting);
}
}
@ -202,11 +215,11 @@ namespace ASC.Web.Files.Classes
{
set
{
var setting = SettingsManager.LoadForCurrentUser<FilesSettings>();
var setting = LoadForCurrentUser();
setting.ForcesaveSetting = value;
SettingsManager.SaveForCurrentUser(setting);
SaveForCurrentUser(setting);
}
get { return SettingsManager.LoadForCurrentUser<FilesSettings>().ForcesaveSetting; }
get { return LoadForCurrentUser().ForcesaveSetting; }
}
public bool StoreForcesave
@ -219,8 +232,52 @@ namespace ASC.Web.Files.Classes
SettingsManager.Save(setting);
}
get { return !CoreBaseSettings.Personal && SettingsManager.Load<FilesSettings>().StoreForcesaveSetting; }
}
public bool RecentSection
{
set
{
var setting = LoadForCurrentUser();
setting.HideRecentSetting = !value;
SaveForCurrentUser(setting);
}
get { return !LoadForCurrentUser().HideRecentSetting; }
}
public bool FavoritesSection
{
set
{
var setting = LoadForCurrentUser();
setting.HideFavoritesSetting = !value;
SaveForCurrentUser(setting);
}
get { return !LoadForCurrentUser().HideFavoritesSetting; }
}
public bool TemplatesSection
{
set
{
var setting = LoadForCurrentUser();
setting.HideTemplatesSetting = !value;
SaveForCurrentUser(setting);
}
get { return !LoadForCurrentUser().HideTemplatesSetting; }
}
private FilesSettings LoadForCurrentUser()
{
return SettingsManager.LoadForCurrentUser<FilesSettings>();
}
private void SaveForCurrentUser(FilesSettings settings)
{
_ = SettingsManager.SaveForCurrentUser(settings);
}
}
}
public static class FilesSettingsHelperExtention
{
public static DIHelper AddFilesSettingsHelperService(this DIHelper services)

View File

@ -1,148 +0,0 @@
/*
*
* (c) Copyright Ascensio System Limited 2010-2018
*
* This program is freeware. You can redistribute it and/or modify it under the terms of the GNU
* General Public License (GPL) version 3 as published by the Free Software Foundation (https://www.gnu.org/copyleft/gpl.html).
* In accordance with Section 7(a) of the GNU GPL its Section 15 shall be amended to the effect that
* Ascensio System SIA expressly excludes the warranty of non-infringement of any third-party rights.
*
* THIS PROGRAM IS DISTRIBUTED WITHOUT ANY WARRANTY; WITHOUT EVEN THE IMPLIED WARRANTY OF MERCHANTABILITY OR
* FITNESS FOR A PARTICULAR PURPOSE. For more details, see GNU GPL at https://www.gnu.org/copyleft/gpl.html
*
* You can contact Ascensio System SIA by email at sales@onlyoffice.com
*
* The interactive user interfaces in modified source and object code versions of ONLYOFFICE must display
* Appropriate Legal Notices, as required under Section 5 of the GNU GPL version 3.
*
* Pursuant to Section 7 § 3(b) of the GNU GPL you must retain the original ONLYOFFICE logo which contains
* relevant author attributions when distributing the software. If the display of the logo in its graphic
* form is not reasonably feasible for technical reasons, you must include the words "Powered by ONLYOFFICE"
* in every copy of the program you distribute.
* Pursuant to Section 7 § 3(e) we decline to grant you any rights under trademark law for use of our trademarks.
*
*/
using System;
using System.Collections.Generic;
using System.Linq;
using ASC.Common;
using ASC.Core;
using ASC.Core.Common.EF;
using ASC.Core.Common.Settings;
using ASC.Core.Tenants;
using ASC.Files.Core.EF;
using ASC.Web.Files.Core.Entries;
using ASC.Web.Studio.Core;
using ASC.Web.Studio.UserControls.Statistics;
using ASC.Web.Studio.Utility;
namespace ASC.Files.Core.Data
{
public class EncryptedDataDao : AbstractDao
{
private static readonly object SyncRoot = new object();
public EncryptedDataDao(
DbContextManager<FilesDbContext> dbContextManager,
UserManager userManager,
TenantManager tenantManager,
TenantUtil tenantUtil,
SetupInfo setupInfo,
TenantExtra tenantExtra,
TenantStatisticsProvider tenantStatisticProvider,
CoreBaseSettings coreBaseSettings,
CoreConfiguration coreConfiguration,
SettingsManager settingsManager,
AuthContext authContext,
IServiceProvider serviceProvider
)
: base(dbContextManager,
userManager,
tenantManager,
tenantUtil,
setupInfo,
tenantExtra,
tenantStatisticProvider,
coreBaseSettings,
coreConfiguration,
settingsManager,
authContext,
serviceProvider)
{
}
public bool SaveEncryptedData(IEnumerable<EncryptedData> ecnryptedDatas)
{
if (ecnryptedDatas == null)
{
throw new ArgumentNullException("ecnryptedDatas");
}
lock (SyncRoot)
{
using var tx = FilesDbContext.Database.BeginTransaction();
foreach (var test in ecnryptedDatas)
{
if (string.IsNullOrEmpty(test.PublicKey)
|| string.IsNullOrEmpty(test.FileHash)
|| string.IsNullOrEmpty(test.Data))
{
continue;
}
var encryptedData = new DbEncryptedData
{
PublicKey = test.PublicKey,
FileHash = test.FileHash,
Data = test.Data
};
FilesDbContext.AddOrUpdate(r => r.EncryptedData, encryptedData);
}
tx.Commit();
}
return true;
}
public string GetData(string publicKey, string fileHash)
{
if (string.IsNullOrEmpty(publicKey)) throw new ArgumentException("publicKey is empty", "publicKey");
if (string.IsNullOrEmpty(fileHash)) throw new ArgumentException("fileHash is empty", "hash");
lock (SyncRoot)
{
return FilesDbContext.EncryptedData
.Where(r => r.PublicKey == publicKey)
.Where(r => r.FileHash == fileHash)
.Select(r => r.Data)
.SingleOrDefault();
}
}
}
public static class EncryptedDataDaoExtention
{
public static DIHelper AddEncryptedDataDaoService(this DIHelper services)
{
if (services.TryAddScoped<EncryptedDataDao>())
{
return services
.AddFilesDbContextService()
.AddUserManagerService()
.AddTenantManagerService()
.AddTenantUtilService()
.AddSetupInfo()
.AddTenantExtraService()
.AddTenantStatisticsProviderService()
.AddCoreBaseSettingsService()
.AddCoreConfigurationService()
.AddSettingsManagerService()
.AddAuthContextService();
}
return services;
}
}
}

View File

@ -97,7 +97,7 @@ namespace ASC.Files.Core
/// <param name="searchText"></param>
/// <param name="searchInContent"></param>
/// <returns></returns>
List<File<T>> GetFilesForShare(T[] fileIds, FilterType filterType, bool subjectGroup, Guid subjectID, string searchText, bool searchInContent);
List<File<T>> GetFilesFiltered(T[] fileIds, FilterType filterType, bool subjectGroup, Guid subjectID, string searchText, bool searchInContent);
/// <summary>
///

View File

@ -258,7 +258,41 @@ namespace ASC.Files.Core
/// </summary>
/// <param name="createIfNotExists"></param>
/// <returns></returns>
T GetFolderIDShare(bool createIfNotExists);
T GetFolderIDShare(bool createIfNotExists);
/// <summary>
/// Returns id folder "Recent"
/// Only in TMFolderDao
/// </summary>
/// <param name="createIfNotExists"></param>
/// <returns></returns>
T GetFolderIDRecent(bool createIfNotExists);
/// <summary>
/// <summary>
/// Returns id folder "Favorites"
/// Only in TMFolderDao
/// </summary>
/// <param name="createIfNotExists"></param>
/// <returns></returns>
T GetFolderIDFavorites(bool createIfNotExists);
/// <summary>
/// Returns id folder "Templates"
/// Only in TMFolderDao
/// </summary>
/// <param name="createIfNotExists"></param>
/// <returns></returns>
T GetFolderIDTemplates(bool createIfNotExists);
/// <summary>
/// Returns id folder "Privacy"
/// Only in TMFolderDao
/// </summary>
/// <param name="createIfNotExists"></param>
/// <returns></returns>
T GetFolderIDPrivacy(bool createIfNotExists, Guid? userId = null);
/// <summary>
/// Returns id folder "Trash"

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