Common, db: moved from 08a01422

This commit is contained in:
pavelbannov 2021-05-17 14:35:00 +03:00
parent 31752e64b4
commit a5c6ba5dcc
62 changed files with 1225 additions and 1288 deletions

View File

@ -25,39 +25,24 @@
using System;
using System.IO;
using System.IO;
using ASC.Data.Storage;
public static class StreamExtension
{
// public const int BufferSize = 2048; //NOTE: set to 2048 to fit in minimum tcp window
public const int BufferSize = 2048; //NOTE: set to 2048 to fit in minimum tcp window
public static void StreamCopyTo(this Stream srcStream, Stream dstStream, int length)
{
if (srcStream == null) throw new ArgumentNullException("srcStream");
if (dstStream == null) throw new ArgumentNullException("dstStream");
public static Stream GetBuffered(this Stream srcStream)
{
if (srcStream == null) throw new ArgumentNullException(nameof(srcStream));
if (!srcStream.CanSeek || srcStream.CanTimeout)
{
//Buffer it
var memStream = TempStream.Create();
srcStream.CopyTo(memStream);
memStream.Position = 0;
return memStream;
}
return srcStream;
}
public static byte[] GetCorrectBuffer(this Stream stream)
{
if (stream == null)
{
throw new ArgumentNullException(nameof(stream));
}
using var mem = stream.GetBuffered();
var buffer = new byte[mem.Length];
mem.Position = 0;
mem.Read(buffer, 0, buffer.Length);
return buffer;
var buffer = new byte[BufferSize];
int totalRead = 0;
int readed;
while ((readed = srcStream.Read(buffer, 0, length - totalRead > BufferSize ? BufferSize : length - totalRead)) > 0 && totalRead < length)
{
dstStream.Write(buffer, 0, readed);
totalRead += readed;
}
}
}

View File

@ -1,39 +1,52 @@
/*
*
* (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.IO;
namespace ASC.Data.Storage
{
public static class TempStream
{
public static Stream Create()
{
//Return temporary stream
return new FileStream(Path.GetTempFileName(), FileMode.Open, FileAccess.ReadWrite, FileShare.Read, 2048, FileOptions.DeleteOnClose);
}
}
/*
*
* (c) Copyright Ascensio System Limited 2010-2021
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
* http://www.apache.org/licenses/LICENSE-2.0
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*
*/
using System;
using System.IO;
namespace ASC.Common
{
[Singletone]
public class TempStream
{
private TempPath TempPath { get; }
public TempStream(TempPath tempPath)
{
TempPath = tempPath;
}
public Stream GetBuffered(Stream srcStream)
{
if (srcStream == null) throw new ArgumentNullException("srcStream");
if (!srcStream.CanSeek || srcStream.CanTimeout)
{
//Buffer it
var memStream = Create();
srcStream.CopyTo(memStream);
memStream.Position = 0;
return memStream;
}
return srcStream;
}
public Stream Create()
{
return new FileStream(TempPath.GetTempFileName(), FileMode.OpenOrCreate, FileAccess.ReadWrite, FileShare.Read, 4096, FileOptions.DeleteOnClose);
}
}
}

View File

@ -30,6 +30,7 @@ using System.Reflection;
using Microsoft.AspNetCore.Http;
using Microsoft.AspNetCore.Http.Extensions;
using Microsoft.AspNetCore.Http.Features;
using Microsoft.Net.Http.Headers;
using HttpContext = Microsoft.AspNetCore.Http.HttpContext;
@ -163,15 +164,17 @@ namespace System.Web
}
public static bool DesktopApp(this HttpRequest request)
{
return request != null && !string.IsNullOrEmpty(request.Headers["desktop"]);
{
return request != null
&& (!string.IsNullOrEmpty(request.Query["desktop"])
|| !string.IsNullOrEmpty(request.Headers[HeaderNames.UserAgent]) && request.Headers[HeaderNames.UserAgent].ToString().Contains("AscDesktopEditor"));
}
public static bool SailfishApp(this HttpRequest request)
{
return request != null
&& (!string.IsNullOrEmpty(request.Headers["sailfish"])
|| !string.IsNullOrEmpty(request.Headers["User-Agent"]) && request.Headers["User-Agent"].ToString().Contains("SailfishOS"));
|| !string.IsNullOrEmpty(request.Headers[HeaderNames.UserAgent]) && request.Headers[HeaderNames.UserAgent].ToString().Contains("SailfishOS"));
}

View File

@ -238,10 +238,10 @@ namespace ASC.Core.Common
return baseUri.ToString().TrimEnd('/');
}
public void Initialize(string serverUri)
public void Initialize(string serverUri, bool localhost = true)
{
var uri = new Uri(serverUri.Replace('*', 'x').Replace('+', 'x'));
_serverRoot = new UriBuilder(uri.Scheme, LOCALHOST, uri.Port);
_serverRoot = new UriBuilder(uri.Scheme, localhost ? LOCALHOST : uri.Host, uri.Port);
_vpath = "/" + uri.AbsolutePath.Trim('/');
}
}

View File

@ -26,249 +26,271 @@
using System;
using System.Collections.Generic;
using System.Globalization;
using System.IO;
using System.Linq;
using System.Net;
using System.Runtime.Serialization;
using System.Security.Cryptography;
using System.ServiceModel;
using System.Web;
using System.Xml.Linq;
using System.Xml.XPath;
using ASC.Common.Logging;
using System.Text;
using System.Text.Json;
using ASC.Common;
using Microsoft.AspNetCore.WebUtilities;
using Microsoft.Extensions.Configuration;
using Microsoft.Extensions.Options;
namespace ASC.Core.Billing
{
public class BillingClient : ClientBase<IService>, IDisposable
{
private readonly ILog log;
private readonly bool test;
private string Security { get; set; }
private string PartnersProduct { get; set; }
public BillingClient(IConfiguration configuration, IOptionsMonitor<ILog> option)
: this(false, configuration, option)
{
}
public BillingClient(bool test, IConfiguration configuration, IOptionsMonitor<ILog> option)
{
this.test = test;
Security = configuration["core:payment:security"];
PartnersProduct = configuration["core:payment:partners-product"];
log = option.CurrentValue;
}
public PaymentLast GetLastPayment(string portalId)
{
var result = Request("GetLatestActiveResourceEx", portalId);
var xelement = ToXElement("<root>" + result + "</root>");
var dedicated = xelement.Element("dedicated-resource");
var payment = xelement.Element("payment");
if (!test && GetValueString(payment.Element("status")) == "4")
{
throw new BillingException("Can not accept test payment.", new { PortalId = portalId });
}
var autorenewal = string.Empty;
try
{
autorenewal = Request("GetLatestAvangateLicenseRecurringStatus", portalId);
}
catch (BillingException err)
{
log.Debug(err); // ignore
}
return new PaymentLast
{
[Singletone]
public class BillingClient
{
public readonly bool Configured = false;
private readonly string _billingDomain;
private readonly string _billingKey;
private readonly string _billingSecret;
private readonly bool _test;
private const int AvangatePaymentSystemId = 1;
public BillingClient(IConfiguration configuration)
: this(false, configuration)
{
}
public BillingClient(bool test, IConfiguration configuration)
{
_test = test;
var billingDomain = configuration["core:payment-url"];
_billingDomain = (billingDomain ?? "").Trim().TrimEnd('/');
if (!string.IsNullOrEmpty(_billingDomain))
{
ProductId = GetValueString(dedicated.Element("product-id")),
EndDate = GetValueDateTime(dedicated.Element("end-date")),
Autorenewal = "enabled".Equals(autorenewal, StringComparison.InvariantCultureIgnoreCase),
};
}
public IEnumerable<PaymentInfo> GetPayments(string portalId, DateTime from, DateTime to)
{
string result;
if (from == DateTime.MinValue && to == DateTime.MaxValue)
{
result = Request("GetPayments", portalId);
}
else
{
result = Request("GetListOfPaymentsByTimeSpan", portalId, Tuple.Create("StartDate", from.ToString("yyyy-MM-dd HH:mm:ss")), Tuple.Create("EndDate", to.ToString("yyyy-MM-dd HH:mm:ss")));
}
var xelement = ToXElement(result);
return xelement.Elements("payment").Select(ToPaymentInfo);
}
public IDictionary<string, Tuple<Uri, Uri>> GetPaymentUrls(string portalId, string[] products, string affiliateId = null, string campaign = null, string currency = null, string language = null, string customerId = null)
{
var urls = new Dictionary<string, Tuple<Uri, Uri>>();
var additionalParameters = new List<Tuple<string, string>>(2) { Tuple.Create("PaymentSystemId", "1") };
if (!string.IsNullOrEmpty(affiliateId))
{
additionalParameters.Add(Tuple.Create("AffiliateId", affiliateId));
_billingDomain += "/billing/";
_billingKey = configuration["core:payment-key"];
_billingSecret = configuration["core:payment-secret"];
Configured = true;
}
}
public PaymentLast GetLastPayment(string portalId)
{
var result = Request("GetActiveResource", portalId);
var paymentLast = JsonSerializer.Deserialize<PaymentLast>(result);
if (!_test && paymentLast.PaymentStatus == 4)
{
throw new BillingException("Can not accept test payment.", new { PortalId = portalId });
}
return paymentLast;
}
public IEnumerable<PaymentInfo> GetPayments(string portalId)
{
string result = Request("GetPayments", portalId);
var payments = JsonSerializer.Deserialize<List<PaymentInfo>>(result);
return payments;
}
public IDictionary<string, Tuple<Uri, Uri>> GetPaymentUrls(string portalId, string[] products, string affiliateId = null, string campaign = null, string currency = null, string language = null, string customerId = null, string quantity = null)
{
var urls = new Dictionary<string, Tuple<Uri, Uri>>();
var additionalParameters = new List<Tuple<string, string>>() { Tuple.Create("PaymentSystemId", AvangatePaymentSystemId.ToString()) };
if (!string.IsNullOrEmpty(affiliateId))
{
additionalParameters.Add(Tuple.Create("AffiliateId", affiliateId));
}
if (!string.IsNullOrEmpty(campaign))
{
additionalParameters.Add(Tuple.Create("campaign", campaign));
}
if (!string.IsNullOrEmpty(currency))
{
additionalParameters.Add(Tuple.Create("Currency", currency));
}
if (!string.IsNullOrEmpty(language))
{
additionalParameters.Add(Tuple.Create("Language", language));
}
if (!string.IsNullOrEmpty(customerId))
{
additionalParameters.Add(Tuple.Create("CustomerID", customerId));
}
var parameters = products
.Distinct()
.Select(p => Tuple.Create("ProductId", p))
.Concat(additionalParameters)
.ToArray();
//max 100 products
var paymentUrls = ToXElement(Request("GetBatchPaymentSystemUrl", portalId, parameters))
.Elements()
.ToDictionary(e => e.Attribute("id").Value, e => ToUrl(e.Attribute("value").Value));
var upgradeUrls = new Dictionary<string, string>();
if (!string.IsNullOrEmpty(portalId))
{
try
{
//max 100 products
upgradeUrls = ToXElement(Request("GetBatchPaymentSystemUpgradeUrl", portalId, parameters))
.Elements()
.ToDictionary(e => e.Attribute("id").Value, e => ToUrl(e.Attribute("value").Value));
}
catch (BillingException)
{
}
}
foreach (var p in products)
{
var paymentUrl = (Uri)null;
var upgradeUrl = (Uri)null;
if (paymentUrls.TryGetValue(p, out var url) && !string.IsNullOrEmpty(url))
{
paymentUrl = new Uri(url);
}
if (upgradeUrls.TryGetValue(p, out url) && !string.IsNullOrEmpty(url))
{
upgradeUrl = new Uri(url);
}
urls[p] = Tuple.Create(paymentUrl, upgradeUrl);
}
return urls;
}
public Invoice GetInvoice(string paymentId)
{
var result = Request("GetInvoice", null, Tuple.Create("PaymentId", paymentId));
var xelement = ToXElement(result);
return new Invoice
{
Sale = GetValueString(xelement.Element("sale")),
Refund = GetValueString(xelement.Element("refund")),
};
}
if (!string.IsNullOrEmpty(currency))
{
additionalParameters.Add(Tuple.Create("Currency", currency));
}
if (!string.IsNullOrEmpty(language))
{
additionalParameters.Add(Tuple.Create("Language", language));
}
if (!string.IsNullOrEmpty(customerId))
{
additionalParameters.Add(Tuple.Create("CustomerID", customerId));
}
if (!string.IsNullOrEmpty(quantity))
{
additionalParameters.Add(Tuple.Create("Quantity", quantity));
}
var parameters = products
.Distinct()
.Select(p => Tuple.Create("ProductId", p))
.Concat(additionalParameters)
.ToArray();
//max 100 products
var result = Request("GetPaymentUrl", portalId, parameters);
var paymentUrls = JsonSerializer.Deserialize<Dictionary<string, string>>(result);
var upgradeUrls = new Dictionary<string, string>();
if (!string.IsNullOrEmpty(portalId)
//TODO: remove
&& false)
{
try
{
//max 100 products
result = Request("GetPaymentUpgradeUrl", portalId, parameters);
upgradeUrls = JsonSerializer.Deserialize<Dictionary<string, string>>(result);
}
catch (BillingNotFoundException)
{
}
}
foreach (var p in products)
{
string url;
var paymentUrl = (Uri)null;
var upgradeUrl = (Uri)null;
if (paymentUrls.TryGetValue(p, out url) && !string.IsNullOrEmpty(url = ToUrl(url)))
{
paymentUrl = new Uri(url);
}
if (upgradeUrls.TryGetValue(p, out url) && !string.IsNullOrEmpty(url = ToUrl(url)))
{
upgradeUrl = new Uri(url);
}
urls[p] = Tuple.Create(paymentUrl, upgradeUrl);
}
return urls;
}
public IDictionary<string, IEnumerable<Tuple<string, decimal>>> GetProductPriceInfo(params string[] productIds)
public IDictionary<string, Dictionary<string, decimal>> GetProductPriceInfo(params string[] productIds)
{
if (productIds == null)
{
throw new ArgumentNullException("productIds");
}
var responce = Request("GetBatchAvangateProductPriceInfo", null, productIds.Select(pid => Tuple.Create("ProductId", pid)).ToArray());
var xelement = ToXElement(responce);
return productIds
.Select(p =>
var parameters = productIds.Select(pid => Tuple.Create("ProductId", pid)).ToList();
parameters.Add(Tuple.Create("PaymentSystemId", AvangatePaymentSystemId.ToString()));
var result = Request("GetProductsPrices", null, parameters.ToArray());
var prices = JsonSerializer.Deserialize<Dictionary<int, Dictionary<string, Dictionary<string, decimal>>>>(result);
if (prices.ContainsKey(AvangatePaymentSystemId))
{
var pricesPaymentSystem = prices[AvangatePaymentSystemId];
return productIds.Select(productId =>
{
var prices = Enumerable.Empty<Tuple<string, decimal>>();
var product = xelement.XPathSelectElement(string.Format("/avangate-product/internal-id[text()=\"{0}\"]", p));
if (product != null)
if (pricesPaymentSystem.ContainsKey(productId))
{
prices = product.Parent.Element("prices").Elements("price-item")
.Select(e => Tuple.Create(e.Element("currency").Value, decimal.Parse(e.Element("amount").Value)));
return new { ProductId = productId, Prices = pricesPaymentSystem[productId] };
}
return new { ProductId = p, Prices = prices, };
return new { ProductId = productId, Prices = new Dictionary<string, decimal>() };
})
.ToDictionary(e => e.ProductId, e => e.Prices);
.ToDictionary(e => e.ProductId, e => e.Prices);
}
return new Dictionary<string, Dictionary<string, decimal>>();
}
private string CreateAuthToken(string pkey, string machinekey)
{
using (var hasher = new HMACSHA1(Encoding.UTF8.GetBytes(machinekey)))
{
var now = DateTime.UtcNow.ToString("yyyyMMddHHmmss");
var hash = WebEncoders.Base64UrlEncode(hasher.ComputeHash(Encoding.UTF8.GetBytes(string.Join("\n", now, pkey))));
return string.Format("ASC {0}:{1}:{2}", pkey, now, hash);
}
}
private string Request(string method, string portalId, params Tuple<string, string>[] parameters)
{
var request = new XElement(method);
var url = _billingDomain + method;
var request = WebRequest.Create(url);
request.Method = "POST";
request.Timeout = 60000;
request.ContentType = "application/json";
if (!string.IsNullOrEmpty(_billingKey))
{
request.Headers.Add("Authorization", CreateAuthToken(_billingKey, _billingSecret));
}
var data = new Dictionary<string, List<string>>();
if (!string.IsNullOrEmpty(portalId))
{
request.Add(new XElement("PortalId", portalId));
data.Add("PortalId", new List<string>() { portalId });
}
request.Add(parameters.Select(p => new XElement(p.Item1, p.Item2)).ToArray());
foreach (var parameter in parameters)
{
if (!data.ContainsKey(parameter.Item1))
{
data.Add(parameter.Item1, new List<string>() { parameter.Item2 });
}
else
{
data[parameter.Item1].Add(parameter.Item2);
}
}
var body = JsonSerializer.Serialize(data);
var responce = Channel.Request(new Message { Type = MessageType.Data, Content = request.ToString(SaveOptions.DisableFormatting), });
if (responce.Content == null)
var bytes = Encoding.UTF8.GetBytes(body ?? "");
request.ContentLength = bytes.Length;
using (var stream = request.GetRequestStream())
{
stream.Write(bytes, 0, bytes.Length);
}
string result;
try
{
using (var response = request.GetResponse())
using (var stream = response.GetResponseStream())
{
if (stream == null)
{
throw new BillingNotConfiguredException("Billing response is null");
}
using (var readStream = new StreamReader(stream))
{
result = readStream.ReadToEnd();
}
}
}
catch (WebException)
{
request.Abort();
throw;
}
if (string.IsNullOrEmpty(result))
{
throw new BillingNotConfiguredException("Billing response is null");
}
if (responce.Type == MessageType.Data)
if (!result.StartsWith("{\"Message\":\"error"))
{
var result = responce.Content;
var invalidChar = ((char)65279).ToString();
return result.Contains(invalidChar) ? result.Replace(invalidChar, string.Empty) : result;
return result;
}
var @params = (parameters ?? Enumerable.Empty<Tuple<string, string>>()).Select(p => string.Format("{0}: {1}", p.Item1, p.Item2));
var info = new { Method = method, PortalId = portalId, Params = string.Join(", ", @params) };
if (responce.Content.Contains("error: cannot find "))
if (result.Contains("{\"Message\":\"error: cannot find "))
{
throw new BillingNotFoundException(responce.Content, info);
throw new BillingNotFoundException(result, info);
}
throw new BillingException(responce.Content, info);
}
private static XElement ToXElement(string xml)
{
return XElement.Parse(xml);
}
private static PaymentInfo ToPaymentInfo(XElement x)
{
return new PaymentInfo
{
ID = (int)GetValueDecimal(x.Element("id")),
Status = (int)GetValueDecimal(x.Element("status")),
PaymentType = GetValueString(x.Element("reserved-str-2")),
ExchangeRate = (double)GetValueDecimal(x.Element("exch-rate")),
GrossSum = (double)GetValueDecimal(x.Element("gross-sum")),
Name = (GetValueString(x.Element("fname")) + " " + GetValueString(x.Element("lname"))).Trim(),
Email = GetValueString(x.Element("email")),
Date = GetValueDateTime(x.Element("payment-date")),
Price = GetValueDecimal(x.Element("price")),
Currency = GetValueString(x.Element("payment-currency")),
Method = GetValueString(x.Element("payment-method")),
CartId = GetValueString(x.Element("cart-id")),
ProductId = GetValueString(x.Element("product-ref")),
TenantID = GetValueString(x.Element("customer-id")),
Country = GetValueString(x.Element("country")),
DiscountSum = GetValueDecimal(x.Element("discount-sum"))
};
throw new BillingException(result, info);
}
private string ToUrl(string s)
@ -278,55 +300,12 @@ namespace ASC.Core.Billing
{
return string.Empty;
}
if (test && !s.Contains("&DOTEST = 1"))
if (_test && !s.Contains("&DOTEST = 1"))
{
s += "&DOTEST=1";
}
return s;
}
private static string GetValueString(XElement xelement)
{
return xelement != null ? HttpUtility.HtmlDecode(xelement.Value) : default;
}
private static DateTime GetValueDateTime(XElement xelement)
{
return xelement != null ?
DateTime.ParseExact(xelement.Value, "yyyy-MM-dd HH:mm:ss", CultureInfo.InvariantCulture) :
default;
}
private static decimal GetValueDecimal(XElement xelement)
{
if (xelement == null || string.IsNullOrEmpty(xelement.Value))
{
return default;
}
var sep = CultureInfo.InvariantCulture.NumberFormat.CurrencyDecimalSeparator;
return decimal.TryParse(xelement.Value.Replace(".", sep).Replace(",", sep), NumberStyles.Currency, CultureInfo.InvariantCulture, out var value) ? value : default;
}
void IDisposable.Dispose()
{
try
{
Close();
}
catch (CommunicationException)
{
Abort();
}
catch (TimeoutException)
{
Abort();
}
catch (Exception)
{
Abort();
throw;
}
}
}

View File

@ -34,24 +34,22 @@ namespace ASC.Core.Billing
[Scope(typeof(ConfigureTariffService))]
public interface ITariffService
{
Tariff GetTariff(int tenantId, bool withRequestToPaymentSystem = true);
void SetTariff(int tenantId, Tariff tariff);
void DeleteDefaultBillingInfo();
void ClearCache(int tenantId);
IEnumerable<PaymentInfo> GetPayments(int tenantId, DateTime from, DateTime to);
Uri GetShoppingUri(int? tenant, int quotaId, string affiliateId, string currency = null, string language = null, string customerId = null);
IDictionary<string, IEnumerable<Tuple<string, decimal>>> GetProductPriceInfo(params string[] productIds);
Invoice GetInvoice(string paymentId);
string GetButton(int tariffId, string partnerId);
Tariff GetTariff(int tenantId, bool withRequestToPaymentSystem = true);
void SetTariff(int tenantId, Tariff tariff);
void DeleteDefaultBillingInfo();
void ClearCache(int tenantId);
IEnumerable<PaymentInfo> GetPayments(int tenantId);
Uri GetShoppingUri(int? tenant, int quotaId, string affiliateId, string currency = null, string language = null, string customerId = null, string quantity = null);
IDictionary<string, Dictionary<string, decimal>> GetProductPriceInfo(params string[] productIds);
string GetButton(int tariffId, string partnerId);
void SaveButton(int tariffId, string partnerId, string buttonUrl);
}
}

View File

@ -1,40 +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.Collections.Generic;
using System.ServiceModel;
using ASC.Core.Tenants;
namespace ASC.Core.Billing
{
[ServiceContract]
public interface ITariffSyncService
{
[OperationContract]
IEnumerable<TenantQuota> GetTariffs(int version, string key);
}
}

View File

@ -1,43 +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.
*
*/
namespace ASC.Core.Billing
{
public class Invoice
{
public string Sale
{
get;
set;
}
public string Refund
{
get;
set;
}
}
}

View File

@ -229,6 +229,8 @@ namespace ASC.Core.Billing
CountPortals = license.PortalCount,
DiscEncryption = true,
PrivacyRoom = true,
Restore = true,
ContentSearch = true
};
if (defaultQuota.Name != "overdue" && !defaultQuota.Trial)

View File

@ -48,5 +48,17 @@ namespace ASC.Core.Billing
get;
set;
}
public int PaymentStatus
{
get;
set;
}
public int Quantity
{
get;
set;
}
}
}

View File

@ -35,34 +35,28 @@ namespace ASC.Core.Billing
public int Status { get; set; }
public string PaymentType { get; set; }
public double ExchangeRate { get; set; }
public double GrossSum { get; set; }
public int PaymentSystemId { get; set; }
public string CartId { get; set; }
public string Name { get; set; }
public string FName { get; set; }
public string LName { get; set; }
public string Email { get; set; }
public DateTime Date { get; set; }
public DateTime PaymentDate { get; set; }
public decimal Price { get; set; }
public Decimal Price { get; set; }
public string Currency { get; set; }
public string PaymentCurrency { get; set; }
public string Method { get; set; }
public string PaymentMethod { get; set; }
public int QuotaId { get; set; }
public string ProductId { get; set; }
public string ProductRef { get; set; }
public string TenantID { get; set; }
public string Country { get; set; }
public decimal DiscountSum { get; set; }
public string CustomerId { get; set; }
}
}

View File

@ -47,8 +47,9 @@ namespace ASC.Core.Billing
public bool Autorenewal { get; set; }
public bool Prolongable { get; set; }
public bool Prolongable { get; set; }
public int Quantity { get; set; }
public static Tariff CreateDefault()
{
@ -59,6 +60,7 @@ namespace ASC.Core.Billing
DueDate = DateTime.MaxValue,
DelayDueDate = DateTime.MaxValue,
LicenseDate = DateTime.MaxValue,
Quantity = 1
};
}
@ -71,6 +73,14 @@ namespace ASC.Core.Billing
public override bool Equals(object obj)
{
return obj is Tariff t && t.QuotaId == QuotaId;
}
public bool EqualsByParams(Tariff t)
{
return t != null
&& t.QuotaId == QuotaId
&& t.DueDate == DueDate
&& t.Quantity == Quantity;
}
}
}

View File

@ -30,6 +30,7 @@ using System.Linq;
using System.Reflection;
using System.Text;
using System.Threading.Tasks;
using System.Web;
using ASC.Common;
using ASC.Common.Caching;
@ -37,7 +38,8 @@ using ASC.Common.Logging;
using ASC.Core.Caching;
using ASC.Core.Common.EF;
using ASC.Core.Tenants;
using ASC.Core.Users;
using Microsoft.Extensions.Configuration;
using Microsoft.Extensions.Options;
@ -57,7 +59,7 @@ namespace ASC.Core.Billing
{
Cache.Remove(TariffService.GetTariffCacheKey(i.TenantId));
Cache.Remove(TariffService.GetBillingUrlCacheKey(i.TenantId));
Cache.Remove(TariffService.GetBillingPaymentCacheKey(i.TenantId, DateTime.MinValue, DateTime.MaxValue)); // clear all payments
Cache.Remove(TariffService.GetBillingPaymentCacheKey(i.TenantId)); // clear all payments
}, CacheNotifyAction.Remove);
//TODO: Change code of WCF -> not supported in .NET standard/.Net Core
@ -143,8 +145,6 @@ namespace ASC.Core.Billing
private static readonly TimeSpan DEFAULT_CACHE_EXPIRATION = TimeSpan.FromMinutes(5);
private static readonly TimeSpan STANDALONE_CACHE_EXPIRATION = TimeSpan.FromMinutes(15);
private readonly static bool billingConfigured = false;
internal ICache Cache { get; set; }
internal ICacheNotify<TariffCacheItem> Notify { get; set; }
internal ILog Log { get; set; }
@ -161,6 +161,10 @@ namespace ASC.Core.Billing
internal Lazy<CoreDbContext> LazyCoreDbContext { get; set; }
internal TariffServiceStorage TariffServiceStorage { get; set; }
internal IOptionsMonitor<ILog> Options { get; set; }
public BillingClient BillingClient { get; }
public readonly int ACTIVE_USERS_MIN;
public readonly int ACTIVE_USERS_MAX;
public TariffService()
{
@ -175,7 +179,9 @@ namespace ASC.Core.Billing
IConfiguration configuration,
DbContextManager<CoreDbContext> coreDbContextManager,
TariffServiceStorage tariffServiceStorage,
IOptionsMonitor<ILog> options)
IOptionsMonitor<ILog> options,
Constants constants,
BillingClient billingClient)
: this()
{
@ -185,7 +191,8 @@ namespace ASC.Core.Billing
CoreSettings = coreSettings;
Configuration = configuration;
TariffServiceStorage = tariffServiceStorage;
Options = options;
Options = options;
BillingClient = billingClient;
CoreBaseSettings = coreBaseSettings;
Test = configuration["core:payment:test"] == "true";
int.TryParse(configuration["core:payment:delay"], out var paymentDelay);
@ -194,7 +201,16 @@ namespace ASC.Core.Billing
Cache = TariffServiceStorage.Cache;
Notify = TariffServiceStorage.Notify;
LazyCoreDbContext = new Lazy<CoreDbContext>(() => coreDbContextManager.Value);
LazyCoreDbContext = new Lazy<CoreDbContext>(() => coreDbContextManager.Value);
var range = (Configuration["core.payment-user-range"] ?? "").Split('-');
if (!int.TryParse(range[0], out ACTIVE_USERS_MIN))
{
ACTIVE_USERS_MIN = 0;
}
if (range.Length < 2 || !int.TryParse(range[1], out ACTIVE_USERS_MAX))
{
ACTIVE_USERS_MAX = constants.MaxEveryoneCount;
}
}
public Tariff GetTariff(int tenantId, bool withRequestToPaymentSystem = true)
@ -207,46 +223,50 @@ namespace ASC.Core.Billing
var tariff = Cache.Get<Tariff>(key);
if (tariff == null)
{
tariff = Tariff.CreateDefault();
var cached = GetBillingInfo(tenantId);
if (cached != null)
{
tariff.QuotaId = cached.Item1;
tariff.DueDate = cached.Item2;
}
tariff = GetBillingInfo(tenantId);
tariff = CalculateTariff(tenantId, tariff);
Cache.Insert(key, tariff, DateTime.UtcNow.Add(GetCacheExpiration()));
if (billingConfigured && withRequestToPaymentSystem)
if (BillingClient.Configured && withRequestToPaymentSystem)
{
Task.Run(() =>
{
try
{
using var client = GetBillingClient();
var p = client.GetLastPayment(GetPortalId(tenantId));
var quota = QuotaService.GetTenantQuotas().SingleOrDefault(q => q.AvangateId == p.ProductId);
var client = GetBillingClient();
var lastPayment = client.GetLastPayment(GetPortalId(tenantId));
var quota = QuotaService.GetTenantQuotas().SingleOrDefault(q => q.AvangateId == lastPayment.ProductId);
if (quota == null)
{
throw new InvalidOperationException(string.Format("Quota with id {0} not found for portal {1}.", p.ProductId, GetPortalId(tenantId)));
throw new InvalidOperationException(string.Format("Quota with id {0} not found for portal {1}.", lastPayment.ProductId, GetPortalId(tenantId)));
}
var asynctariff = Tariff.CreateDefault();
asynctariff.QuotaId = quota.Id;
asynctariff.Autorenewal = p.Autorenewal;
asynctariff.DueDate = 9999 <= p.EndDate.Year ? DateTime.MaxValue : p.EndDate;
asynctariff.Autorenewal = lastPayment.Autorenewal;
asynctariff.DueDate = 9999 <= lastPayment.EndDate.Year ? DateTime.MaxValue : lastPayment.EndDate;
if (SaveBillingInfo(tenantId, Tuple.Create(asynctariff.QuotaId, asynctariff.DueDate), false))
if (quota.ActiveUsers == -1
&& lastPayment.Quantity < ACTIVE_USERS_MIN)
{
throw new BillingException(string.Format("The portal {0} is paid for {1} users", tenantId, lastPayment.Quantity));
}
asynctariff.Quantity = lastPayment.Quantity;
if (SaveBillingInfo(tenantId, asynctariff, false))
{
asynctariff = CalculateTariff(tenantId, asynctariff);
ClearCache(tenantId);
Cache.Insert(key, asynctariff, DateTime.UtcNow.Add(GetCacheExpiration()));
}
}
catch (BillingNotFoundException)
{
}
catch (Exception error)
{
LogError(error);
LogError(error, tenantId.ToString());
}
});
}
@ -264,7 +284,7 @@ namespace ASC.Core.Billing
var q = QuotaService.GetTenantQuota(tariff.QuotaId);
if (q == null) return;
SaveBillingInfo(tenantId, Tuple.Create(tariff.QuotaId, tariff.DueDate));
SaveBillingInfo(tenantId, tariff);
if (q.Trial)
{
// reset trial date
@ -289,9 +309,9 @@ namespace ASC.Core.Billing
return string.Format("{0}:{1}", tenantId, "billing:urls");
}
internal static string GetBillingPaymentCacheKey(int tenantId, DateTime from, DateTime to)
{
return string.Format("{0}:{1}:{2}-{3}", tenantId, "billing:payments", from.ToString("yyyyMMddHHmmss"), to.ToString("yyyyMMddHHmmss"));
internal static string GetBillingPaymentCacheKey(int tenantId)
{
return string.Format("{0}:{1}", tenantId, "billing:payments");
}
@ -299,45 +319,43 @@ namespace ASC.Core.Billing
{
Notify.Publish(new TariffCacheItem { TenantId = tenantId }, CacheNotifyAction.Remove);
}
public IEnumerable<PaymentInfo> GetPayments(int tenantId)
{
var key = GetBillingPaymentCacheKey(tenantId);
var payments = Cache.Get<List<PaymentInfo>>(key);
if (payments == null)
{
payments = new List<PaymentInfo>();
if (BillingClient.Configured)
{
try
{
var quotas = QuotaService.GetTenantQuotas();
var client = GetBillingClient();
foreach (var pi in client.GetPayments(GetPortalId(tenantId)))
{
var quota = quotas.SingleOrDefault(q => q.AvangateId == pi.ProductRef);
if (quota != null)
{
pi.QuotaId = quota.Id;
}
payments.Add(pi);
}
}
catch (Exception error)
{
LogError(error, tenantId.ToString());
}
}
Cache.Insert(key, payments, DateTime.UtcNow.Add(TimeSpan.FromMinutes(10)));
}
return payments;
}
public IEnumerable<PaymentInfo> GetPayments(int tenantId, DateTime from, DateTime to)
{
from = from.Date;
to = to.Date.AddTicks(TimeSpan.TicksPerDay - 1);
var key = GetBillingPaymentCacheKey(tenantId, from, to);
var payments = Cache.Get<List<PaymentInfo>>(key);
if (payments == null)
{
payments = new List<PaymentInfo>();
if (billingConfigured)
{
try
{
var quotas = QuotaService.GetTenantQuotas();
using var client = GetBillingClient();
foreach (var pi in client.GetPayments(GetPortalId(tenantId), from, to))
{
var quota = quotas.SingleOrDefault(q => q.AvangateId == pi.ProductId);
if (quota != null)
{
pi.QuotaId = quota.Id;
}
payments.Add(pi);
}
}
catch (Exception error)
{
LogError(error);
}
}
Cache.Insert(key, payments, DateTime.UtcNow.Add(TimeSpan.FromMinutes(10)));
}
return payments;
}
public Uri GetShoppingUri(int? tenant, int quotaId, string affiliateId, string currency = null, string language = null, string customerId = null)
public Uri GetShoppingUri(int? tenant, int quotaId, string affiliateId, string currency = null, string language = null, string customerId = null, string quantity = null)
{
var quota = QuotaService.GetTenantQuota(quotaId);
if (quota == null) return null;
@ -349,19 +367,27 @@ namespace ASC.Core.Billing
if (!(Cache.Get<Dictionary<string, Tuple<Uri, Uri>>>(key) is IDictionary<string, Tuple<Uri, Uri>> urls))
{
urls = new Dictionary<string, Tuple<Uri, Uri>>();
if (billingConfigured)
if (BillingClient.Configured)
{
try
{
var products = QuotaService.GetTenantQuotas()
.Where(q => !string.IsNullOrEmpty(q.AvangateId) && q.Visible == quota.Visible)
.Select(q => q.AvangateId)
.ToArray();
using var client = GetBillingClient();
urls = tenant.HasValue ?
client.GetPaymentUrls(GetPortalId(tenant.Value), products, GetAffiliateId(tenant.Value), GetCampaign(tenant.Value), "__Currency__", "__Language__", "__CustomerID__") :
client.GetPaymentUrls(null, products, !string.IsNullOrEmpty(affiliateId) ? affiliateId : null, null, "__Currency__", "__Language__", "__CustomerID__");
.ToArray();
var client = GetBillingClient();
urls =
client.GetPaymentUrls(
tenant.HasValue ? GetPortalId(tenant.Value) : null,
products,
tenant.HasValue ? GetAffiliateId(tenant.Value) : affiliateId,
tenant.HasValue ? GetCampaign(tenant.Value) : null,
!string.IsNullOrEmpty(currency) ? "__Currency__" : null,
!string.IsNullOrEmpty(language) ? "__Language__" : null,
!string.IsNullOrEmpty(customerId) ? "__CustomerID__" : null,
!string.IsNullOrEmpty(quantity) ? "__Quantity__" : null
);
}
catch (Exception error)
{
@ -373,71 +399,60 @@ namespace ASC.Core.Billing
ResetCacheExpiration();
if (!string.IsNullOrEmpty(quota.AvangateId) && urls.TryGetValue(quota.AvangateId, out var tuple))
{
var result = tuple.Item2;
if (!string.IsNullOrEmpty(quota.AvangateId) && urls.TryGetValue(quota.AvangateId, out var tuple))
{
var result = tuple.Item2;
var tariff = tenant.HasValue ? GetTariff(tenant.Value) : null;
if (result == null || tariff == null || tariff.QuotaId == quotaId || tariff.State >= TariffState.Delay)
{
result = tuple.Item1;
}
result = new Uri(result.ToString()
.Replace("__Currency__", currency ?? "")
.Replace("__Language__", (language ?? "").ToLower())
.Replace("__CustomerID__", customerId ?? ""));
return result;
if (result == null)
{
result = tuple.Item1;
}
else
{
var tariff = tenant.HasValue ? GetTariff(tenant.Value) : null;
if (tariff == null || tariff.QuotaId == quotaId || tariff.State >= TariffState.Delay)
{
result = tuple.Item1;
}
}
if (result == null) return null;
result = new Uri(result.ToString()
.Replace("__Currency__", HttpUtility.UrlEncode(currency ?? ""))
.Replace("__Language__", HttpUtility.UrlEncode((language ?? "").ToLower()))
.Replace("__CustomerID__", HttpUtility.UrlEncode(customerId ?? ""))
.Replace("__Quantity__", HttpUtility.UrlEncode(quantity ?? "")));
return result;
}
return null;
}
public IDictionary<string, IEnumerable<Tuple<string, decimal>>> GetProductPriceInfo(params string[] productIds)
{
if (productIds == null)
{
throw new ArgumentNullException("productIds");
}
try
{
var key = "biling-prices" + string.Join(",", productIds);
var result = Cache.Get<IDictionary<string, IEnumerable<Tuple<string, decimal>>>>(key);
if (result == null)
{
using (var client = GetBillingClient())
{
result = client.GetProductPriceInfo(productIds);
}
Cache.Insert(key, result, DateTime.Now.AddHours(1));
}
return result;
}
catch (Exception error)
{
LogError(error);
return productIds
.Select(p => new { ProductId = p, Prices = Enumerable.Empty<Tuple<string, decimal>>() })
.ToDictionary(e => e.ProductId, e => e.Prices);
}
}
public Invoice GetInvoice(string paymentId)
{
var result = new Invoice();
if (billingConfigured)
{
try
{
using var client = GetBillingClient();
result = client.GetInvoice(paymentId);
}
catch (Exception error)
{
LogError(error);
}
}
return result;
public IDictionary<string, Dictionary<string, decimal>> GetProductPriceInfo(params string[] productIds)
{
if (productIds == null)
{
throw new ArgumentNullException("productIds");
}
try
{
var key = "biling-prices" + string.Join(",", productIds);
var result = Cache.Get<IDictionary<string, Dictionary<string, decimal>>>(key);
if (result == null)
{
var client = GetBillingClient();
result = client.GetProductPriceInfo(productIds);
Cache.Insert(key, result, DateTime.Now.AddHours(1));
}
return result;
}
catch (Exception error)
{
LogError(error);
return productIds
.Select(p => new { ProductId = p, Prices = new Dictionary<string, decimal>() })
.ToDictionary(e => e.ProductId, e => e.Prices);
}
}
@ -463,34 +478,42 @@ namespace ASC.Core.Billing
}
private Tuple<int, DateTime> GetBillingInfo(int tenant)
private Tariff GetBillingInfo(int tenant)
{
var r = CoreDbContext.Tariffs
.Where(r => r.Tenant == tenant)
.OrderByDescending(r => r.Id)
.FirstOrDefault();
return r != null ? Tuple.Create(r.Tariff, r.Stamp.Year < 9999 ? r.Stamp : DateTime.MaxValue) : null;
.SingleOrDefault();
if (r == null) return Tariff.CreateDefault();
var tariff = Tariff.CreateDefault();
tariff.QuotaId = r.Tariff;
tariff.DueDate = r.Stamp.Year < 9999 ? r.Stamp : DateTime.MaxValue;
tariff.Quantity = r.Quantity;
return tariff;
}
private bool SaveBillingInfo(int tenant, Tuple<int, DateTime> bi, bool renewal = true)
private bool SaveBillingInfo(int tenant, Tariff tariffInfo, bool renewal = true)
{
var inserted = false;
if (!Equals(bi, GetBillingInfo(tenant)))
var inserted = false;
var currentTariff = GetBillingInfo(tenant);
if (!tariffInfo.EqualsByParams(currentTariff))
{
using var tx = CoreDbContext.Database.BeginTransaction();
// last record is not the same
var count = CoreDbContext.Tariffs
.Count(r => r.Tenant == tenant && r.Tariff == bi.Item1 && r.Stamp == bi.Item2);
if (bi.Item2 == DateTime.MaxValue || renewal || count == 0)
.Count(r => r.Tenant == tenant && r.Tariff == tariffInfo.QuotaId && r.Stamp == tariffInfo.DueDate && r.Quantity == tariffInfo.Quantity);
if (tariffInfo.DueDate == DateTime.MaxValue || renewal || count == 0)
{
var efTariff = new DbTariff
{
Tenant = tenant,
Tariff = bi.Item1,
Stamp = bi.Item2,
Tariff = tariffInfo.QuotaId,
Stamp = tariffInfo.DueDate,
Quantity = tariffInfo.Quantity,
CreateOn = DateTime.UtcNow
};
@ -617,7 +640,7 @@ namespace ASC.Core.Billing
{
try
{
return new BillingClient(Test, Configuration, Options);
return new BillingClient(Test, Configuration);
}
catch (InvalidOperationException ioe)
{
@ -665,27 +688,28 @@ namespace ASC.Core.Billing
}
}
private void LogError(Exception error)
{
if (error is BillingNotFoundException)
{
Log.DebugFormat("Payment not found: {0}", error.Message);
}
else if (error is BillingNotConfiguredException)
{
Log.DebugFormat("Billing not configured: {0}", error.Message);
}
else
{
if (Log.IsDebugEnabled)
{
Log.Error(error);
}
else
{
Log.Error(error.Message);
}
}
private void LogError(Exception error, string tenantId = null)
{
if (error is BillingNotFoundException)
{
Log.DebugFormat("Payment tenant {0} not found: {1}", tenantId, error.Message);
}
else if (error is BillingNotConfiguredException)
{
Log.DebugFormat("Billing tenant {0} not configured: {1}", tenantId, error.Message);
}
else
{
if (Log.IsDebugEnabled)
{
Log.Error("Billing tenant " + tenantId);
Log.Error(error);
}
else
{
Log.ErrorFormat("Billing tenant {0}: {1}", tenantId, error.Message);
}
}
}
}
}

View File

@ -1,41 +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.Collections.Generic;
using ASC.Common.Module;
using ASC.Core.Tenants;
namespace ASC.Core.Billing
{
public class TariffSyncClient : BaseWcfClient<ITariffSyncService>, ITariffSyncService
{
public IEnumerable<TenantQuota> GetTariffs(int version, string key)
{
return Channel.GetTariffs(version, key);
}
}
}

View File

@ -1,163 +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 System.Threading;
using ASC.Common.Logging;
using ASC.Common.Module;
using ASC.Common.Utils;
using ASC.Core.Data;
using ASC.Core.Tenants;
using Microsoft.Extensions.DependencyInjection;
using Microsoft.Extensions.Options;
namespace ASC.Core.Billing
{
class TariffSyncService : ITariffSyncService, IServiceController
{
private readonly ILog log;
private readonly TariffSyncServiceSection config;
private readonly IDictionary<int, IEnumerable<TenantQuota>> quotaServices = new Dictionary<int, IEnumerable<TenantQuota>>();
private Timer timer;
public TariffSyncService(
IServiceProvider serviceProvider,
ConfigurationExtension configuration,
DbQuotaService dbQuotaService,
IOptionsMonitor<ILog> options)
{
config = TariffSyncServiceSection.GetSection();
ServiceProvider = serviceProvider;
Configuration = configuration;
DbQuotaService = dbQuotaService;
log = options.CurrentValue;
}
// server part of service
public IEnumerable<TenantQuota> GetTariffs(int version, string key)
{
lock (quotaServices)
{
if (!quotaServices.ContainsKey(version))
{
var cs = Configuration.GetConnectionStrings(config.ConnectionStringName + version) ??
Configuration.GetConnectionStrings(config.ConnectionStringName);
quotaServices[version] = DbQuotaService.GetTenantQuotas();
}
return quotaServices[version];
}
}
// client part of service
public string ServiceName
{
get { return "Tariffs synchronizer"; }
}
private IServiceProvider ServiceProvider { get; }
private ConfigurationExtension Configuration { get; }
private DbQuotaService DbQuotaService { get; }
public void Start()
{
if (timer == null)
{
timer = new Timer(Sync, null, TimeSpan.Zero, config.Period);
}
}
public void Stop()
{
if (timer != null)
{
timer.Change(Timeout.Infinite, Timeout.Infinite);
timer.Dispose();
timer = null;
}
}
private void Sync(object _)
{
try
{
using var scope = ServiceProvider.CreateScope();
var tariffSync = scope.ServiceProvider.GetService<TariffSync>();
tariffSync.Sync();
}
catch (Exception error)
{
log.Error(error);
}
}
}
class TariffSync
{
public TariffSync(TenantManager tenantManager, CoreSettings coreSettings, DbQuotaService dbQuotaService)
{
TenantManager = tenantManager;
CoreSettings = coreSettings;
DbQuotaService = dbQuotaService;
}
private TenantManager TenantManager { get; }
private CoreSettings CoreSettings { get; }
private DbQuotaService DbQuotaService { get; }
public void Sync()
{
var tenant = TenantManager.GetTenants(false).OrderByDescending(t => t.Version).FirstOrDefault();
if (tenant != null)
{
using var wcfClient = new TariffSyncClient();
var quotaService = DbQuotaService;
var oldtariffs = quotaService.GetTenantQuotas().ToDictionary(t => t.Id);
// save new
foreach (var tariff in wcfClient.GetTariffs(tenant.Version, CoreSettings.GetKey(tenant.TenantId)))
{
quotaService.SaveTenantQuota(tariff);
oldtariffs.Remove(tariff.Id);
}
// remove old
foreach (var tariff in oldtariffs.Values)
{
tariff.Visible = false;
quotaService.SaveTenantQuota(tariff);
}
}
}
}
}

View File

@ -1,53 +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.Configuration;
namespace ASC.Core.Billing
{
class TariffSyncServiceSection : ConfigurationSection
{
[ConfigurationProperty("period", DefaultValue = "4:0:0")]
public TimeSpan Period
{
get { return (TimeSpan)this["period"]; }
set { this["period"] = value; }
}
[ConfigurationProperty("connectionStringName", DefaultValue = "core")]
public string ConnectionStringName
{
get { return (string)this["connectionStringName"]; }
set { this["connectionStringName"] = value; }
}
public static TariffSyncServiceSection GetSection()
{
return (TariffSyncServiceSection)ConfigurationManager.GetSection("tariffs") ?? new TariffSyncServiceSection();
}
}
}

View File

@ -82,37 +82,23 @@ namespace ASC.Core
public IEnumerable<PaymentInfo> GetTariffPayments(int tenant)
{
return GetTariffPayments(tenant, DateTime.MinValue, DateTime.MaxValue);
}
public IEnumerable<PaymentInfo> GetTariffPayments(int tenant, DateTime from, DateTime to)
{
return tariffService.GetPayments(tenant, from, to);
}
public Invoice GetPaymentInvoice(string paymentId)
{
return tariffService.GetInvoice(paymentId);
return tariffService.GetPayments(tenant);
}
public IDictionary<string, IEnumerable<Tuple<string, decimal>>> GetProductPriceInfo(params string[] productIds)
public IDictionary<string, Dictionary<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)
public Uri GetShoppingUri(int quotaId, bool forCurrentTenant = true, string affiliateId = null, string currency = null, string language = null, string customerId = null, string quantity = null)
{
return tariffService.GetShoppingUri(tenant, quotaId, null, currency, language, customerId);
return tariffService.GetShoppingUri(forCurrentTenant ? TenantManager.GetCurrentTenant().TenantId : (int?)null, quotaId, affiliateId, currency, language, customerId, quantity);
}
public Uri GetShoppingUri(int quotaId, bool forCurrentTenant = true, string affiliateId = null, string currency = null, string language = null, string customerId = null)
public Uri GetShoppingUri(int quotaId, string affiliateId, string currency = null, string language = null, string customerId = null, string quantity = null)
{
return tariffService.GetShoppingUri(forCurrentTenant ? TenantManager.GetCurrentTenant().TenantId : (int?)null, quotaId, affiliateId, currency, language, customerId);
}
public Uri GetShoppingUri(int quotaId, string affiliateId, string currency = null, string language = null, string customerId = null)
{
return tariffService.GetShoppingUri(null, quotaId, affiliateId, currency, language, customerId);
return tariffService.GetShoppingUri(null, quotaId, affiliateId, currency, language, customerId, quantity);
}
public void ActivateKey(string key)

View File

@ -312,23 +312,31 @@ namespace ASC.Core
{
return QuotaService.GetTenantQuotas().Where(q => q.Id < 0 && (all || q.Visible)).OrderByDescending(q => q.Id).ToList();
}
public TenantQuota GetTenantQuota(int tenant)
{
var defaultQuota = QuotaService.GetTenantQuota(tenant) ?? QuotaService.GetTenantQuota(Tenant.DEFAULT_TENANT) ?? TenantQuota.Default;
if (defaultQuota.Id != tenant && TariffService != null)
{
var tariff = TariffService.GetTariff(tenant);
var currentQuota = QuotaService.GetTenantQuota(tariff.QuotaId);
if (currentQuota != null)
{
currentQuota = (TenantQuota)currentQuota.Clone();
if (currentQuota.ActiveUsers == -1)
{
currentQuota.ActiveUsers = tariff.Quantity;
currentQuota.MaxTotalSize *= currentQuota.ActiveUsers;
}
return currentQuota;
}
}
return defaultQuota;
}
public TenantQuota GetTenantQuota(int tenant)
{
// если в tenants_quota есть строка, с данным идентификатором портала, то в качестве квоты берется именно она
var q = QuotaService.GetTenantQuota(tenant) ?? QuotaService.GetTenantQuota(Tenant.DEFAULT_TENANT) ?? TenantQuota.Default;
if (q.Id != tenant && TariffService != null)
{
var tariffQuota = QuotaService.GetTenantQuota(TariffService.GetTariff(tenant).QuotaId);
if (tariffQuota != null)
{
return tariffQuota;
}
}
return q;
}
public IDictionary<string, IEnumerable<Tuple<string, decimal>>> GetProductPriceInfo(bool all = true)
public IDictionary<string, Dictionary<string, decimal>> GetProductPriceInfo(bool all = true)
{
var productIds = GetTenantQuotas(all)
.Select(p => p.AvangateId)

View File

@ -66,7 +66,7 @@ namespace ASC.Core
private TenantManager TenantManager { get; }
private PermissionContext PermissionContext { get; }
private UserManagerConstants UserManagerConstants { get; }
public CoreBaseSettings CoreBaseSettings { get; }
private CoreBaseSettings CoreBaseSettings { get; }
private Constants Constants { get; }
private Tenant tenant;
@ -310,7 +310,52 @@ namespace ASC.Core
var newUser = UserService.SaveUser(Tenant.TenantId, u);
return newUser;
}
}
public UserInfo SaveUserInfo(UserInfo u, bool isVisitor = false)
{
if (IsSystemUser(u.ID)) return SystemUsers[u.ID];
if (u.ID == Guid.Empty) PermissionContext.DemandPermissions(Constants.Action_AddRemoveUser);
else PermissionContext.DemandPermissions(new UserSecurityProvider(u.ID), Constants.Action_EditUser);
if (!CoreBaseSettings.Personal)
{
if (Constants.MaxEveryoneCount <= GetUsersByGroup(Constants.GroupEveryone.ID).Length)
{
throw new TenantQuotaException("Maximum number of users exceeded");
}
if (u.Status == EmployeeStatus.Active)
{
if (isVisitor)
{
var maxUsers = TenantManager.GetTenantQuota(TenantManager.GetCurrentTenant().TenantId).ActiveUsers;
var visitors = TenantManager.GetTenantQuota(TenantManager.GetCurrentTenant().TenantId).Free ? 0 : Constants.CoefficientOfVisitors;
if (!CoreBaseSettings.Standalone && GetUsersByGroup(Constants.GroupVisitor.ID).Length > visitors * maxUsers)
{
throw new TenantQuotaException("Maximum number of visitors exceeded");
}
}
else
{
var q = TenantManager.GetTenantQuota(TenantManager.GetCurrentTenant().TenantId);
if (q.ActiveUsers < GetUsersByGroup(Constants.GroupUser.ID).Length)
{
throw new TenantQuotaException(string.Format("Exceeds the maximum active users ({0})", q.ActiveUsers));
}
}
}
}
if (u.Status == EmployeeStatus.Terminated && u.ID == TenantManager.GetCurrentTenant().OwnerId)
{
throw new InvalidOperationException("Can not disable tenant owner.");
}
var newUser = UserService.SaveUser(TenantManager.GetCurrentTenant().TenantId, u);
return newUser;
}
public void DeleteUser(Guid id)
{

View File

@ -224,7 +224,7 @@ namespace ASC.Core.Data
var passwordHashs = usersQuery.Select(r => GetPasswordHash(r, passwordHash)).ToList();
q = query()
.Where(r => passwordHashs.Any(p => r.UserSecurity.PwdHash == p));
.Where(r => passwordHashs.Any(p => r.UserSecurity.PwdHash == p) && r.DbTenant.Status == TenantStatus.Active);
//new password
result = result.Concat(q.Select(FromTenantUserToTenant)).ToList();

View File

@ -54,6 +54,11 @@ namespace ASC.Core.Common.EF.Model
new FilesConverts { Input = ".epub", Output = ".pdf" },
new FilesConverts { Input = ".epub", Output = ".rtf" },
new FilesConverts { Input = ".epub", Output = ".txt" },
new FilesConverts { Input = ".fb2", Output = ".docx" },
new FilesConverts { Input = ".fb2", Output = ".odt" },
new FilesConverts { Input = ".fb2", Output = ".pdf" },
new FilesConverts { Input = ".fb2", Output = ".rtf" },
new FilesConverts { Input = ".fb2", Output = ".txt" },
new FilesConverts { Input = ".fodp", Output = ".odp" },
new FilesConverts { Input = ".fodp", Output = ".pdf" },
new FilesConverts { Input = ".fodp", Output = ".pptx" },

View File

@ -1,4 +1,5 @@
using ASC.Core.Common.EF.Model;
using Microsoft.EntityFrameworkCore;
namespace ASC.Core.Common.EF
@ -29,7 +30,7 @@ namespace ASC.Core.Common.EF
.Add(MySqlAddDbQuota, Provider.MySql)
.Add(PgSqlAddDbQuota, Provider.Postgre)
.HasData(
new DbQuota { Tenant = -1, Name = "default", Description = null, MaxFileSize = 102400, MaxTotalSize = 10995116277760, ActiveUsers = 10000, Features = "docs,domain,audit,controlpanel,healthcheck,ldap,sso,whitelabel,branding,ssbranding,update,support,portals:10000,discencryption", Price = decimal.Parse("0,00"), Price2 = decimal.Parse("0,00"), AvangateId = "0", Visible = false }
new DbQuota { Tenant = -1, Name = "default", Description = null, MaxFileSize = 102400, MaxTotalSize = 10995116277760, ActiveUsers = 10000, Features = "domain,audit,controlpanel,healthcheck,ldap,sso,whitelabel,branding,ssbranding,update,support,portals:10000,discencryption,privacyroom,restore", Price = decimal.Parse("0,00"), Price2 = decimal.Parse("0,00"), AvangateId = "0", Visible = false }
);
return modelBuilder;

View File

@ -1,5 +1,4 @@
using System;
using System.ComponentModel.DataAnnotations.Schema;
using ASC.Core.Common.EF.Model;
@ -13,6 +12,7 @@ namespace ASC.Core.Common.EF
public int Tenant { get; set; }
public int Tariff { get; set; }
public DateTime Stamp { get; set; }
public int Quantity { get; set; }
public string Comment { get; set; }
public DateTime CreateOn { get; set; }
}
@ -48,6 +48,10 @@ namespace ASC.Core.Common.EF
.HasDefaultValueSql("CURRENT_TIMESTAMP")
.ValueGeneratedOnAddOrUpdate();
entity.Property(e => e.Quantity)
.HasColumnName("stamp")
.HasColumnType("int");
entity.Property(e => e.Stamp)
.HasColumnName("stamp")
.HasColumnType("datetime");
@ -79,6 +83,8 @@ namespace ASC.Core.Common.EF
entity.Property(e => e.Stamp).HasColumnName("stamp");
entity.Property(e => e.Quantity).HasColumnName("quantity");
entity.Property(e => e.Tariff).HasColumnName("tariff");
entity.Property(e => e.Tenant).HasColumnName("tenant");

View File

@ -676,7 +676,7 @@ namespace ASC.Core.Common.Migrations.MySql.CoreDbContextMySql
Tenant = -1,
ActiveUsers = 10000,
AvangateId = "0",
Features = "docs,domain,audit,controlpanel,healthcheck,ldap,sso,whitelabel,branding,ssbranding,update,support,portals:10000,discencryption",
Features = "domain,audit,controlpanel,healthcheck,ldap,sso,whitelabel,branding,ssbranding,update,support,portals:10000,discencryption,privacyroom,restore",
MaxFileSize = 102400L,
MaxTotalSize = 10995116277760L,
Name = "default",
@ -744,13 +744,16 @@ namespace ASC.Core.Common.Migrations.MySql.CoreDbContextMySql
b.Property<DateTime>("Stamp")
.HasColumnType("datetime")
.HasColumnName("stamp");
.HasColumnName("stamp");
b.Property<int>("Quantity")
.HasColumnType("int")
.HasColumnName("quantity");
b.Property<int>("Tariff")
.HasColumnType("int")
.HasColumnName("tariff");
b.Property<int>("Tenant")
.HasColumnType("int")
.HasColumnName("tenant");

View File

@ -1,4 +1,5 @@
using System;
using System;
using Microsoft.EntityFrameworkCore.Metadata;
using Microsoft.EntityFrameworkCore.Migrations;
@ -92,7 +93,8 @@ namespace ASC.Core.Common.Migrations.MySql.CoreDbContextMySql
.Annotation("MySql:ValueGenerationStrategy", MySqlValueGenerationStrategy.IdentityColumn),
tenant = table.Column<int>(type: "int", nullable: false),
tariff = table.Column<int>(type: "int", nullable: false),
stamp = table.Column<DateTime>(type: "datetime", nullable: false),
stamp = table.Column<DateTime>(type: "datetime", nullable: false),
quantity = table.Column<int>(type: "int", nullable: false),
tariff_key = table.Column<string>(type: "varchar(64)", nullable: true, collation: "utf8_general_ci")
.Annotation("MySql:CharSet", "utf8"),
comment = table.Column<string>(type: "varchar(255)", nullable: true, collation: "utf8_general_ci")
@ -180,7 +182,7 @@ namespace ASC.Core.Common.Migrations.MySql.CoreDbContextMySql
migrationBuilder.InsertData(
table: "tenants_quota",
columns: new[] { "tenant", "active_users", "avangate_id", "description", "features", "max_file_size", "max_total_size", "name", "price", "price2", "visible" },
values: new object[] { -1, 10000, "0", null, "docs,domain,audit,controlpanel,healthcheck,ldap,sso,whitelabel,branding,ssbranding,update,support,portals:10000,discencryption", 102400L, 10995116277760L, "default", 0.00m, 0.00m, false });
values: new object[] { -1, 10000, "0", null, "domain,audit,controlpanel,healthcheck,ldap,sso,whitelabel,branding,ssbranding,update,support,portals:10000,discencryption,privacyroom,restore", 102400L, 10995116277760L, "default", 0.00m, 0.00m, false });
migrationBuilder.CreateIndex(
name: "last_modified",

View File

@ -674,7 +674,7 @@ namespace ASC.Core.Common.Migrations.MySql.CoreDbContextMySql
Tenant = -1,
ActiveUsers = 10000,
AvangateId = "0",
Features = "docs,domain,audit,controlpanel,healthcheck,ldap,sso,whitelabel,branding,ssbranding,update,support,portals:10000,discencryption",
Features = "domain,audit,controlpanel,healthcheck,ldap,sso,whitelabel,branding,ssbranding,update,support,portals:10000,discencryption,privacyroom,restore",
MaxFileSize = 102400L,
MaxTotalSize = 10995116277760L,
Name = "default",
@ -742,7 +742,11 @@ namespace ASC.Core.Common.Migrations.MySql.CoreDbContextMySql
b.Property<DateTime>("Stamp")
.HasColumnType("datetime")
.HasColumnName("stamp");
.HasColumnName("stamp");
b.Property<int>("Quantity")
.HasColumnType("int")
.HasColumnName("quantity");
b.Property<int>("Tariff")
.HasColumnType("int")

View File

@ -229,6 +229,31 @@ namespace ASC.Core.Common.Migrations.MySql.FilesDbContextMySql
Output = ".txt"
},
new
{
Input = ".fb2",
Output = ".docx"
},
new
{
Input = ".fb2",
Output = ".odt"
},
new
{
Input = ".fb2",
Output = ".pdf"
},
new
{
Input = ".fb2",
Output = ".rtf"
},
new
{
Input = ".fb2",
Output = ".txt"
},
new
{
Input = ".fodp",
Output = ".odp"

View File

@ -167,7 +167,12 @@ namespace ASC.Core.Common.Migrations.MySql.FilesDbContextMySql
{ ".fodt", ".txt" },
{ ".html", ".docx" },
{ ".fods", ".xlsx" },
{ ".xps", ".pdf" }
{ ".xps", ".pdf" },
{ ".fb2", ".docx" },
{ ".fb2", ".odt" },
{ ".fb2", ".pdf" },
{ ".fb2", ".rtf" },
{ ".fb2", ".txt" }
});
}

View File

@ -227,6 +227,31 @@ namespace ASC.Core.Common.Migrations.MySql.FilesDbContextMySql
Output = ".txt"
},
new
{
Input = ".fb2",
Output = ".docx"
},
new
{
Input = ".fb2",
Output = ".odt"
},
new
{
Input = ".fb2",
Output = ".pdf"
},
new
{
Input = ".fb2",
Output = ".rtf"
},
new
{
Input = ".fb2",
Output = ".txt"
},
new
{
Input = ".fodp",
Output = ".odp"

View File

@ -730,7 +730,11 @@ namespace ASC.Core.Common.Migrations.Npgsql.CoreDbContextNpgsql
b.Property<DateTime>("Stamp")
.HasColumnName("stamp")
.HasColumnType("timestamp without time zone");
.HasColumnType("timestamp without time zone");
b.Property<int>("Quantity")
.HasColumnType("int")
.HasColumnName("quantity");
b.Property<int>("Tariff")
.HasColumnName("tariff")

View File

@ -69,7 +69,7 @@ namespace ASC.Core.Common.Migrations.Npgsql.CoreDbContextNpgsql
schema: "onlyoffice",
table: "tenants_quota",
columns: new[] { "tenant", "active_users", "avangate_id", "description", "features", "max_file_size", "max_total_size", "name", "visible" },
values: new object[] { -1, 10000, "0", null, "docs,domain,audit,controlpanel,healthcheck,ldap,sso,whitelabel,branding,ssbranding,update,support,portals:10000,discencryption", 102400L, 10995116277760L, "default", false });
values: new object[] { -1, 10000, "0", null, "domain,audit,controlpanel,healthcheck,ldap,sso,whitelabel,branding,ssbranding,update,support,portals:10000,discencryption,privacyroom,restore", 102400L, 10995116277760L, "default", false });
migrationBuilder.CreateTable(
name: "tenants_quotarow",
@ -96,7 +96,8 @@ namespace ASC.Core.Common.Migrations.Npgsql.CoreDbContextNpgsql
.Annotation("Npgsql:ValueGenerationStrategy", NpgsqlValueGenerationStrategy.IdentityByDefaultColumn),
tenant = table.Column<int>(nullable: false),
tariff = table.Column<int>(nullable: false),
stamp = table.Column<DateTime>(nullable: false),
stamp = table.Column<DateTime>(nullable: false),
quantity = table.Column<int>(type: "int", nullable: false),
comment = table.Column<string>(maxLength: 255, nullable: true, defaultValueSql: "NULL"),
create_on = table.Column<DateTime>(nullable: false, defaultValueSql: "CURRENT_TIMESTAMP")
},

View File

@ -671,7 +671,7 @@ namespace ASC.Core.Common.Migrations.Npgsql.CoreDbContextNpgsql
Tenant = -1,
ActiveUsers = 10000,
AvangateId = "0",
Features = "docs,domain,audit,controlpanel,healthcheck,ldap,sso,whitelabel,branding,ssbranding,update,support,portals:10000,discencryption",
Features = "domain,audit,controlpanel,healthcheck,ldap,sso,whitelabel,branding,ssbranding,update,support,portals:10000,discencryption,privacyroom,restore",
MaxFileSize = 102400L,
MaxTotalSize = 10995116277760L,
Name = "default",
@ -743,7 +743,11 @@ namespace ASC.Core.Common.Migrations.Npgsql.CoreDbContextNpgsql
b.Property<DateTime>("Stamp")
.HasColumnName("stamp")
.HasColumnType("timestamp without time zone");
.HasColumnType("timestamp without time zone");
b.Property<int>("Quantity")
.HasColumnType("int")
.HasColumnName("quantity");
b.Property<int>("Tariff")
.HasColumnName("tariff")

View File

@ -228,6 +228,31 @@ namespace ASC.Core.Common.Migrations.Npgsql.FilesDbContextNpgsql
Ouput = ".txt"
},
new
{
Input = ".fb2",
Ouput = ".docx"
},
new
{
Input = ".fb2",
Ouput = ".odt"
},
new
{
Input = ".fb2",
Ouput = ".pdf"
},
new
{
Input = ".fb2",
Ouput = ".rtf"
},
new
{
Input = ".fb2",
Ouput = ".txt"
},
new
{
Input = ".fodp",
Ouput = ".odp"

View File

@ -170,7 +170,12 @@ namespace ASC.Core.Common.Migrations.Npgsql.FilesDbContextNpgsql
{ ".fodt", ".txt" },
{ ".html", ".docx" },
{ ".fods", ".xlsx" },
{ ".xps", ".pdf" }
{ ".xps", ".pdf" },
{ ".fb2", ".docx" },
{ ".fb2", ".odt" },
{ ".fb2", ".pdf" },
{ ".fb2", ".rtf" },
{ ".fb2", ".txt" }
});
}

View File

@ -226,6 +226,31 @@ namespace ASC.Core.Common.Migrations.Npgsql.FilesDbContextNpgsql
Ouput = ".txt"
},
new
{
Input = ".fb2",
Ouput = ".docx"
},
new
{
Input = ".fb2",
Ouput = ".odt"
},
new
{
Input = ".fb2",
Ouput = ".pdf"
},
new
{
Input = ".fb2",
Ouput = ".rtf"
},
new
{
Input = ".fb2",
Ouput = ".txt"
},
new
{
Input = ".fodp",
Ouput = ".odp"

View File

@ -33,9 +33,8 @@ using ASC.Common;
using ASC.Common.Logging;
using ASC.Common.Utils;
using ASC.Notify.Messages;
using ASC.Notify.Patterns;
using ASC.Notify.Patterns;
using MailKit;
using MailKit.Security;
using Microsoft.Extensions.Configuration;
@ -287,10 +286,11 @@ namespace ASC.Core.Notify.Senders
var smtpClient = new MailKit.Net.Smtp.SmtpClient
{
ServerCertificateValidationCallback = (sender, certificate, chain, errors) =>
sslCertificatePermit || MailService.DefaultServerCertificateValidationCallback(sender, certificate, chain, errors),
Timeout = NETWORK_TIMEOUT
};
};
if (sslCertificatePermit)
smtpClient.ServerCertificateValidationCallback = (sender, certificate, chain, errors) => true;
return smtpClient;
}

View File

@ -191,7 +191,65 @@ namespace ASC.Core.Tenants
{
get { return GetFeature("privacyroom"); }
set { SetFeature("privacyroom", value); }
}
}
public bool EnableMailServer
{
get { return GetFeature("mailserver"); }
set { SetFeature("mailserver", value); }
}
public int CountAdmin
{
get
{
var features = (Features ?? string.Empty).Split(' ', ',', ';').ToList();
var admin = features.FirstOrDefault(f => f.StartsWith("admin:"));
int countAdmin;
if (admin == null || !int.TryParse(admin.Replace("admin:", ""), out countAdmin))
{
countAdmin = int.MaxValue;
}
return countAdmin;
}
set
{
var features = (Features ?? string.Empty).Split(' ', ',', ';').ToList();
var admin = features.FirstOrDefault(f => f.StartsWith("admin:"));
features.Remove(admin);
if (value > 0)
{
features.Add("admin:" + value);
}
Features = string.Join(",", features.ToArray());
}
}
public bool Restore
{
get { return GetFeature("restore"); }
set { SetFeature("restore", value); }
}
public bool AutoBackup
{
get { return GetFeature("autobackup"); }
set { SetFeature("autobackup", value); }
}
public bool Oauth
{
get { return GetFeature("oauth"); }
set { SetFeature("oauth", value); }
}
public bool ContentSearch
{
get { return GetFeature("contentsearch"); }
set { SetFeature("contentsearch", value); }
}
public int CountPortals
{
get
@ -215,8 +273,13 @@ namespace ASC.Core.Tenants
}
Features = string.Join(",", features.ToArray());
}
}
}
public bool ThirdParty
{
get { return GetFeature("thirdparty"); }
set { SetFeature("thirdparty", value); }
}
public TenantQuota()
{

View File

@ -1,143 +1,143 @@
/*
*
* (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.
*
*/
///*
// *
// * (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.
// *
//*/
#if DEBUG
namespace ASC.Core.Common.Tests
{
using System.Linq;
using System.Text.Json;
//#if DEBUG
//namespace ASC.Core.Common.Tests
//{
// using System.Linq;
// using System.Text.Json;
using ASC.Core.Billing;
using ASC.Core.Data;
using ASC.Core.Tenants;
// using ASC.Core.Billing;
// using ASC.Core.Data;
// using ASC.Core.Tenants;
using NUnit.Framework;
// using NUnit.Framework;
[TestFixture]
class DbQuotaServiceTest : DbBaseTest<DbQuotaService>
{
public DbQuotaServiceTest()
{
}
// [TestFixture]
// class DbQuotaServiceTest : DbBaseTest<DbQuotaService>
// {
// public DbQuotaServiceTest()
// {
// }
[OneTimeSetUp]
public void ClearData()
{
Service.RemoveTenantQuota(Tenant);
foreach (var row in Service.FindTenantQuotaRows(Tenant))
{
//DeleteQuotaRow(row);
}
}
// [OneTimeSetUp]
// public void ClearData()
// {
// Service.RemoveTenantQuota(Tenant);
// foreach (var row in Service.FindTenantQuotaRows(Tenant))
// {
// //DeleteQuotaRow(row);
// }
// }
[Test]
public void QuotaMethod()
{
var quota1 = new TenantQuota(Tenant)
{
MaxFileSize = 3,
MaxTotalSize = 4,
ActiveUsers = 30,
};
Service.SaveTenantQuota(quota1);
CompareQuotas(quota1, Service.GetTenantQuota(quota1.Id));
// [Test]
// public void QuotaMethod()
// {
// var quota1 = new TenantQuota(Tenant)
// {
// MaxFileSize = 3,
// MaxTotalSize = 4,
// ActiveUsers = 30,
// };
// Service.SaveTenantQuota(quota1);
// CompareQuotas(quota1, Service.GetTenantQuota(quota1.Id));
Service.RemoveTenantQuota(Tenant);
Assert.IsNull(Service.GetTenantQuota(quota1.Id));
// Service.RemoveTenantQuota(Tenant);
// Assert.IsNull(Service.GetTenantQuota(quota1.Id));
var row = new TenantQuotaRow { Tenant = this.Tenant, Path = "path", Counter = 1000, Tag = "tag" };
Service.SetTenantQuotaRow(row, false);
// var row = new TenantQuotaRow { Tenant = this.Tenant, Path = "path", Counter = 1000, Tag = "tag" };
// Service.SetTenantQuotaRow(row, false);
var rows = Service.FindTenantQuotaRows(Tenant).ToList();
CompareQuotaRows(row, rows.Find(r => r.Tenant == row.Tenant && r.Tag == row.Tag));
// var rows = Service.FindTenantQuotaRows(Tenant).ToList();
// CompareQuotaRows(row, rows.Find(r => r.Tenant == row.Tenant && r.Tag == row.Tag));
Service.SetTenantQuotaRow(row, true);
row.Counter += 1000;
rows = Service.FindTenantQuotaRows(Tenant).ToList();
CompareQuotaRows(row, rows.Find(r => r.Tenant == row.Tenant && r.Tag == row.Tag));
// Service.SetTenantQuotaRow(row, true);
// row.Counter += 1000;
// rows = Service.FindTenantQuotaRows(Tenant).ToList();
// CompareQuotaRows(row, rows.Find(r => r.Tenant == row.Tenant && r.Tag == row.Tag));
//DeleteQuotaRow(row);
}
// //DeleteQuotaRow(row);
// }
[Test]
public void SerializeTest()
{
var quota1 = new TenantQuota(Tenant)
{
AvangateId = "1",
Features = "trial,year",
Name = "quota1",
Price = 12.5m,
Price2 = 45.23m,
Visible = true,
MaxFileSize = 3,
MaxTotalSize = 4,
ActiveUsers = 30,
};
// [Test]
// public void SerializeTest()
// {
// var quota1 = new TenantQuota(Tenant)
// {
// AvangateId = "1",
// Features = "trial,year",
// Name = "quota1",
// Price = 12.5m,
// Price2 = 45.23m,
// Visible = true,
// MaxFileSize = 3,
// MaxTotalSize = 4,
// ActiveUsers = 30,
// };
var json = JsonSerializer.Serialize(quota1);
Assert.AreEqual("{\"Id\":1024,\"Name\":\"quota1\",\"MaxFileSize\":3,\"MaxTotalSize\":4,\"ActiveUsers\":30,\"Features\":\"trial,year\",\"Price\":12.5,\"Price2\":45.23,\"AvangateId\":\"1\",\"Visible\":true}", json);
}
// var json = JsonSerializer.Serialize(quota1);
// Assert.AreEqual("{\"Id\":1024,\"Name\":\"quota1\",\"MaxFileSize\":3,\"MaxTotalSize\":4,\"ActiveUsers\":30,\"Features\":\"trial,year\",\"Price\":12.5,\"Price2\":45.23,\"AvangateId\":\"1\",\"Visible\":true}", json);
// }
[Test]
public void SyncTest()
{
using var client = new TariffSyncClient();
var quotas = client.GetTariffs(1, "key");
Assert.AreNotEqual(0, quotas.Count());
}
// [Test]
// public void SyncTest()
// {
// using var client = new TariffSyncClient();
// var quotas = client.GetTariffs(1, "key");
// Assert.AreNotEqual(0, quotas.Count());
// }
private void CompareQuotas(TenantQuota q1, TenantQuota q2)
{
Assert.AreEqual(q1.Id, q2.Id);
Assert.AreEqual(q1.Name, q2.Name);
Assert.AreEqual(q1.MaxFileSize, q2.MaxFileSize);
Assert.AreEqual(q1.MaxTotalSize, q2.MaxTotalSize);
Assert.AreEqual(q1.ActiveUsers, q2.ActiveUsers);
Assert.AreEqual(q1.Features, q2.Features);
Assert.AreEqual(q1.Price, q2.Price);
Assert.AreEqual(q1.Price2, q2.Price2);
Assert.AreEqual(q1.AvangateId, q2.AvangateId);
Assert.AreEqual(q1.Visible, q2.Visible);
}
// private void CompareQuotas(TenantQuota q1, TenantQuota q2)
// {
// Assert.AreEqual(q1.Id, q2.Id);
// Assert.AreEqual(q1.Name, q2.Name);
// Assert.AreEqual(q1.MaxFileSize, q2.MaxFileSize);
// Assert.AreEqual(q1.MaxTotalSize, q2.MaxTotalSize);
// Assert.AreEqual(q1.ActiveUsers, q2.ActiveUsers);
// Assert.AreEqual(q1.Features, q2.Features);
// Assert.AreEqual(q1.Price, q2.Price);
// Assert.AreEqual(q1.Price2, q2.Price2);
// Assert.AreEqual(q1.AvangateId, q2.AvangateId);
// Assert.AreEqual(q1.Visible, q2.Visible);
// }
private void CompareQuotaRows(TenantQuotaRow r1, TenantQuotaRow r2)
{
Assert.AreEqual(r1.Path, r2.Path);
Assert.AreEqual(r1.Tag, r2.Tag);
Assert.AreEqual(r1.Tenant, r2.Tenant);
Assert.AreEqual(r1.Counter, r2.Counter);
}
// private void CompareQuotaRows(TenantQuotaRow r1, TenantQuotaRow r2)
// {
// Assert.AreEqual(r1.Path, r2.Path);
// Assert.AreEqual(r1.Tag, r2.Tag);
// Assert.AreEqual(r1.Tenant, r2.Tenant);
// Assert.AreEqual(r1.Counter, r2.Counter);
// }
//private void DeleteQuotaRow(TenantQuotaRow row)
//{
// var d = new SqlDelete(DbQuotaService.tenants_quotarow).Where("tenant", row.Tenant).Where("path", row.Path);
// var dbManager = DbOptionsManager.Value;
// dbManager.ExecuteNonQuery(d);
//}
}
}
#endif
// //private void DeleteQuotaRow(TenantQuotaRow row)
// //{
// // var d = new SqlDelete(DbQuotaService.tenants_quotarow).Where("tenant", row.Tenant).Where("path", row.Path);
// // var dbManager = DbOptionsManager.Value;
// // dbManager.ExecuteNonQuery(d);
// //}
// }
//}
//#endif

View File

@ -1,92 +1,92 @@
/*
*
* (c) Copyright Ascensio System Limited 2010-2018
*
* This program is freeware. You can redistribute it and/or modify it under the terms of the GNU
* General Public License (GPL) version 3 as published by the Free Software Foundation (https://www.gnu.org/copyleft/gpl.html).
* In accordance with Section 7(a) of the GNU GPL its Section 15 shall be amended to the effect that
* Ascensio System SIA expressly excludes the warranty of non-infringement of any third-party rights.
*
* THIS PROGRAM IS DISTRIBUTED WITHOUT ANY WARRANTY; WITHOUT EVEN THE IMPLIED WARRANTY OF MERCHANTABILITY OR
* FITNESS FOR A PARTICULAR PURPOSE. For more details, see GNU GPL at https://www.gnu.org/copyleft/gpl.html
*
* You can contact Ascensio System SIA by email at sales@onlyoffice.com
*
* The interactive user interfaces in modified source and object code versions of ONLYOFFICE must display
* Appropriate Legal Notices, as required under Section 5 of the GNU GPL version 3.
*
* Pursuant to Section 7 § 3(b) of the GNU GPL you must retain the original ONLYOFFICE logo which contains
* relevant author attributions when distributing the software. If the display of the logo in its graphic
* form is not reasonably feasible for technical reasons, you must include the words "Powered by ONLYOFFICE"
* in every copy of the program you distribute.
* Pursuant to Section 7 § 3(e) we decline to grant you any rights under trademark law for use of our trademarks.
*
*/
///*
// *
// * (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.
// *
//*/
#if DEBUG
namespace ASC.Core.Common.Tests
{
using System;
//#if DEBUG
//namespace ASC.Core.Common.Tests
//{
// using System;
using ASC.Core.Billing;
// using ASC.Core.Billing;
using NUnit.Framework;
// using NUnit.Framework;
[TestFixture]
public class TariffServiceTest
{
private readonly ITariffService tariffService;
// [TestFixture]
// public class TariffServiceTest
// {
// private readonly ITariffService tariffService;
public TariffServiceTest()
{
tariffService = new TariffService();
}
// public TariffServiceTest()
// {
// tariffService = new TariffService();
// }
[Test]
public void TestShoppingUriBatch()
{
using var bc = new BillingClient(true, null, null);
var result = bc.GetPaymentUrls("0", new[] { "12", "13", "14", "0", "-2" });
Assert.AreEqual(5, result.Count);
}
// [Test]
// public void TestShoppingUriBatch()
// {
// using var bc = new BillingClient(true, null, null);
// var result = bc.GetPaymentUrls("0", new[] { "12", "13", "14", "0", "-2" });
// Assert.AreEqual(5, result.Count);
// }
[Test]
public void TestPaymentInfo()
{
var payments = tariffService.GetPayments(918, DateTime.MinValue, DateTime.MaxValue);
Assert.IsNotNull(payments);
}
// [Test]
// public void TestPaymentInfo()
// {
// var payments = tariffService.GetPayments(918, DateTime.MinValue, DateTime.MaxValue);
// Assert.IsNotNull(payments);
// }
[Test]
public void TestTariff()
{
var tariff = tariffService.GetTariff(918);
Assert.IsNotNull(tariff);
}
// [Test]
// public void TestTariff()
// {
// var tariff = tariffService.GetTariff(918);
// Assert.IsNotNull(tariff);
// }
[Test]
public void TestSetTariff()
{
var duedate = DateTime.UtcNow.AddMonths(1);
tariffService.SetTariff(0, new Tariff { QuotaId = -1, DueDate = DateTime.MaxValue });
tariffService.SetTariff(0, new Tariff { QuotaId = -21, DueDate = duedate });
tariffService.SetTariff(0, new Tariff { QuotaId = -21, DueDate = duedate });
tariffService.SetTariff(0, new Tariff { QuotaId = -1, DueDate = DateTime.MaxValue });
}
// [Test]
// public void TestSetTariff()
// {
// var duedate = DateTime.UtcNow.AddMonths(1);
// tariffService.SetTariff(0, new Tariff { QuotaId = -1, DueDate = DateTime.MaxValue });
// tariffService.SetTariff(0, new Tariff { QuotaId = -21, DueDate = duedate });
// tariffService.SetTariff(0, new Tariff { QuotaId = -21, DueDate = duedate });
// tariffService.SetTariff(0, new Tariff { QuotaId = -1, DueDate = DateTime.MaxValue });
// }
[Test]
public void TestInvoice()
{
var payments = tariffService.GetPayments(918, DateTime.MinValue, DateTime.MaxValue);
foreach (var p in payments)
{
var invoice = tariffService.GetInvoice(p.CartId);
Assert.IsNotNull(invoice);
}
}
}
}
#endif
// [Test]
// public void TestInvoice()
// {
// var payments = tariffService.GetPayments(918, DateTime.MinValue, DateTime.MaxValue);
// foreach (var p in payments)
// {
// var invoice = tariffService.GetInvoice(p.CartId);
// Assert.IsNotNull(invoice);
// }
// }
// }
//}
//#endif

View File

@ -1,73 +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.
*
*/
#if DEBUG
namespace ASC.Core.Common.Tests
{
using System;
using System.Linq;
using ASC.Common.Logging;
using ASC.Core.Billing;
using Microsoft.Extensions.Configuration;
using Microsoft.Extensions.Options;
using NUnit.Framework;
[TestFixture]
public class TariffSyncServiceTest
{
private readonly ITariffSyncService tariffSyncService;
public IServiceProvider ServiceProvider { get; set; }
public IConfiguration Configuration { get; set; }
public IOptionsMonitor<ILog> Options { get; set; }
public TariffSyncServiceTest()
{
tariffSyncService = new TariffSyncService(null, null, null, null);
}
[Test]
public void GetTeriffsTest()
{
var tariff = tariffSyncService.GetTariffs(70, null).FirstOrDefault(t => t.Id == -38);
Assert.AreEqual(1024 * 1024 * 1024, tariff.MaxFileSize);
tariff = tariffSyncService.GetTariffs(74, null).FirstOrDefault(t => t.Id == -38);
Assert.AreEqual(100 * 1024 * 1024, tariff.MaxFileSize);
}
[Test]
public void SyncTest()
{
using var wcfClient = new TariffSyncClient();
var tariffs = wcfClient.GetTariffs(74, null);
Assert.IsTrue(tariffs.Any());
}
}
}
#endif

View File

@ -60,6 +60,19 @@ namespace ASC.Core.Users
}
return count;
}
}
public int CoefficientOfVisitors
{
get
{
int count;
if (!int.TryParse(Configuration["core:coefficient-of-visitors"], out count))
{
count = 2;
}
return count;
}
}
private IConfiguration Configuration { get; }

View File

@ -31,6 +31,7 @@ using System.IO;
using System.Linq;
using System.Web;
using ASC.Common;
using ASC.Common.Logging;
using ASC.Common.Utils;
using ASC.Core;
@ -45,13 +46,21 @@ namespace ASC.Data.Storage
public abstract class BaseStorage : IDataStore
{
protected ILog Log { get; set; }
protected TempStream TempStream { get; }
protected TenantManager TenantManager { get; }
protected PathUtils PathUtils { get; }
protected EmailValidationKeyProvider EmailValidationKeyProvider { get; }
protected IHttpContextAccessor HttpContextAccessor { get; }
protected IOptionsMonitor<ILog> Options { get; }
public BaseStorage(
TempStream tempStream,
TenantManager tenantManager,
PathUtils pathUtils,
EmailValidationKeyProvider emailValidationKeyProvider,
IOptionsMonitor<ILog> options)
{
TempStream = tempStream;
TenantManager = tenantManager;
PathUtils = pathUtils;
EmailValidationKeyProvider = emailValidationKeyProvider;
@ -60,11 +69,14 @@ namespace ASC.Data.Storage
}
public BaseStorage(
TempStream tempStream,
TenantManager tenantManager,
PathUtils pathUtils,
EmailValidationKeyProvider emailValidationKeyProvider,
IHttpContextAccessor httpContextAccessor,
IOptionsMonitor<ILog> options) : this(tenantManager,
IOptionsMonitor<ILog> options) : this(
tempStream,
tenantManager,
pathUtils,
emailValidationKeyProvider,
options)
@ -228,12 +240,6 @@ namespace ASC.Data.Storage
public virtual bool IsSupportChunking { get { return false; } }
protected TenantManager TenantManager { get; }
protected PathUtils PathUtils { get; }
protected EmailValidationKeyProvider EmailValidationKeyProvider { get; }
protected IHttpContextAccessor HttpContextAccessor { get; }
protected IOptionsMonitor<ILog> Options { get; }
#endregion
public abstract void Delete(string domain, string path);

View File

@ -25,8 +25,9 @@
using System;
using System.IO;
using System.IO;
using ASC.Common;
using ASC.Common.Logging;
using ASC.Core.ChunkedUploader;
@ -40,20 +41,21 @@ namespace ASC.Data.Storage
private readonly IDataStore source;
private readonly IDataStore destination;
private readonly long maxChunkUploadSize;
private readonly int chunksize;
private readonly int chunksize;
private IOptionsMonitor<ILog> Option { get; }
private TempStream TempStream { get; }
public CrossModuleTransferUtility(IOptionsMonitor<ILog> option, IDataStore source, IDataStore destination)
public CrossModuleTransferUtility(IOptionsMonitor<ILog> option, TempStream tempStream, IDataStore source, IDataStore destination)
{
Log = option.Get("ASC.CrossModuleTransferUtility");
Option = option;
Option = option;
TempStream = tempStream;
this.source = source ?? throw new ArgumentNullException("source");
this.destination = destination ?? throw new ArgumentNullException("destination");
maxChunkUploadSize = 10 * 1024 * 1024;
chunksize = 5 * 1024 * 1024;
}
private IOptionsMonitor<ILog> Option { get; }
}
public void CopyFile(string srcDomain, string srcPath, string destDomain, string destPath)
{
if (srcDomain == null) throw new ArgumentNullException("srcDomain");

View File

@ -77,19 +77,21 @@ namespace ASC.Data.Storage.DiscStorage
}
public DiscDataStore(
TenantManager tenantManager,
PathUtils pathUtils,
EmailValidationKeyProvider emailValidationKeyProvider,
IOptionsMonitor<ILog> options,
EncryptionSettingsHelper encryptionSettingsHelper,
EncryptionFactory encryptionFactory)
: base(tenantManager, pathUtils, emailValidationKeyProvider, options)
TempStream tempStream,
TenantManager tenantManager,
PathUtils pathUtils,
EmailValidationKeyProvider emailValidationKeyProvider,
IOptionsMonitor<ILog> options,
EncryptionSettingsHelper encryptionSettingsHelper,
EncryptionFactory encryptionFactory)
: base(tempStream, tenantManager, pathUtils, emailValidationKeyProvider, options)
{
EncryptionSettingsHelper = encryptionSettingsHelper;
EncryptionFactory = encryptionFactory;
}
public DiscDataStore(
TempStream tempStream,
TenantManager tenantManager,
PathUtils pathUtils,
EmailValidationKeyProvider emailValidationKeyProvider,
@ -97,7 +99,7 @@ namespace ASC.Data.Storage.DiscStorage
IOptionsMonitor<ILog> options,
EncryptionSettingsHelper encryptionSettingsHelper,
EncryptionFactory encryptionFactory)
: base(tenantManager, pathUtils, emailValidationKeyProvider, httpContextAccessor, options)
: base(tempStream, tenantManager, pathUtils, emailValidationKeyProvider, httpContextAccessor, options)
{
EncryptionSettingsHelper = encryptionSettingsHelper;
EncryptionFactory = encryptionFactory;
@ -171,7 +173,7 @@ namespace ASC.Data.Storage.DiscStorage
public override Uri Save(string domain, string path, Stream stream)
{
Log.Debug("Save " + path);
var buffered = stream.GetBuffered();
var buffered = TempStream.GetBuffered(stream);
if (QuotaController != null)
{
QuotaController.QuotaUsedCheck(buffered.Length);

View File

@ -28,15 +28,17 @@ using System;
using System.IO;
using System.Threading;
using ASC.Common;
namespace ASC.Data.Storage
{
public static class Extensions
{
private const int BufferSize = 2048;//NOTE: set to 2048 to fit in minimum tcp window
public static Stream IronReadStream(this IDataStore store, string domain, string path, int tryCount)
public static Stream IronReadStream(this IDataStore store, TempStream tempStream, string domain, string path, int tryCount)
{
var ms = TempStream.Create();
var ms = tempStream.Create();
IronReadToStream(store, domain, path, tryCount, ms);
ms.Seek(0, SeekOrigin.Begin);
return ms;

View File

@ -72,19 +72,21 @@ namespace ASC.Data.Storage.GoogleCloud
private bool _lowerCasing = true;
public GoogleCloudStorage(
TempStream tempStream,
TenantManager tenantManager,
PathUtils pathUtils,
EmailValidationKeyProvider emailValidationKeyProvider,
IOptionsMonitor<ILog> options) : base(tenantManager, pathUtils, emailValidationKeyProvider, options)
IOptionsMonitor<ILog> options) : base(tempStream, tenantManager, pathUtils, emailValidationKeyProvider, options)
{
}
public GoogleCloudStorage(
TempStream tempStream,
TenantManager tenantManager,
PathUtils pathUtils,
EmailValidationKeyProvider emailValidationKeyProvider,
IHttpContextAccessor httpContextAccessor,
IOptionsMonitor<ILog> options) : base(tenantManager, pathUtils, emailValidationKeyProvider, httpContextAccessor, options)
IOptionsMonitor<ILog> options) : base(tempStream, tenantManager, pathUtils, emailValidationKeyProvider, httpContextAccessor, options)
{
}
@ -273,7 +275,7 @@ namespace ASC.Data.Storage.GoogleCloud
string contentDisposition, ACL acl, string contentEncoding = null, int cacheDays = 5)
{
var buffered = stream.GetBuffered();
var buffered = TempStream.GetBuffered(stream);
if (QuotaController != null)
{
@ -662,7 +664,7 @@ namespace ASC.Data.Storage.GoogleCloud
using var storage = GetStorage();
var objectKey = MakePath(domain, path);
var buffered = stream.GetBuffered();
var buffered = TempStream.GetBuffered(stream);
var uploadObjectOptions = new UploadObjectOptions
{

View File

@ -65,22 +65,24 @@ namespace ASC.Data.Storage.RackspaceCloud
private readonly ILog _logger;
public RackspaceCloudStorage(
TempStream tempStream,
TenantManager tenantManager,
PathUtils pathUtils,
EmailValidationKeyProvider emailValidationKeyProvider,
IOptionsMonitor<ILog> options)
: base(tenantManager, pathUtils, emailValidationKeyProvider, options)
: base(tempStream, tenantManager, pathUtils, emailValidationKeyProvider, options)
{
_logger = options.Get("ASC.Data.Storage.Rackspace.RackspaceCloudStorage");
}
public RackspaceCloudStorage(
TempStream tempStream,
TenantManager tenantManager,
PathUtils pathUtils,
EmailValidationKeyProvider emailValidationKeyProvider,
IHttpContextAccessor httpContextAccessor,
IOptionsMonitor<ILog> options)
: base(tenantManager, pathUtils, emailValidationKeyProvider, httpContextAccessor, options)
: base(tempStream, tenantManager, pathUtils, emailValidationKeyProvider, httpContextAccessor, options)
{
_logger = options.Get("ASC.Data.Storage.Rackspace.RackspaceCloudStorage");
}
@ -283,7 +285,7 @@ namespace ASC.Data.Storage.RackspaceCloud
string contentDisposition, ACL acl, string contentEncoding = null, int cacheDays = 5,
DateTime? deleteAt = null, long? deleteAfter = null)
{
var buffered = stream.GetBuffered();
var buffered = TempStream.GetBuffered(stream);
if (QuotaController != null)
{

View File

@ -78,21 +78,23 @@ namespace ASC.Data.Storage.S3
private string _subDir = string.Empty;
public S3Storage(
TempStream tempStream,
TenantManager tenantManager,
PathUtils pathUtils,
EmailValidationKeyProvider emailValidationKeyProvider,
IOptionsMonitor<ILog> options)
: base(tenantManager, pathUtils, emailValidationKeyProvider, options)
: base(tempStream, tenantManager, pathUtils, emailValidationKeyProvider, options)
{
}
public S3Storage(
TempStream tempStream,
TenantManager tenantManager,
PathUtils pathUtils,
EmailValidationKeyProvider emailValidationKeyProvider,
IHttpContextAccessor httpContextAccessor,
IOptionsMonitor<ILog> options)
: base(tenantManager, pathUtils, emailValidationKeyProvider, httpContextAccessor, options)
: base(tempStream, tenantManager, pathUtils, emailValidationKeyProvider, httpContextAccessor, options)
{
}
@ -218,7 +220,7 @@ namespace ASC.Data.Storage.S3
public Uri Save(string domain, string path, Stream stream, string contentType,
string contentDisposition, ACL acl, string contentEncoding = null, int cacheDays = 5)
{
var buffered = stream.GetBuffered();
var buffered = TempStream.GetBuffered(stream);
if (QuotaController != null)
{
QuotaController.QuotaUsedCheck(buffered.Length);
@ -618,7 +620,7 @@ namespace ASC.Data.Storage.S3
using var client = GetClient();
using var uploader = new TransferUtility(client);
var objectKey = MakePath(domain, path);
var buffered = stream.GetBuffered();
var buffered = TempStream.GetBuffered(stream);
var request = new TransferUtilityUploadRequest
{
BucketName = _bucket,

View File

@ -54,7 +54,8 @@ namespace ASC.Data.Storage
private ICache Cache { get; set; }
private static readonly object Locker;
private IServiceProvider ServiceProvider { get; }
private IServiceProvider ServiceProvider { get; }
private TempStream TempStream { get; }
private ICacheNotify<MigrationProgress> CacheMigrationNotify { get; }
static StorageUploader()
@ -64,9 +65,10 @@ namespace ASC.Data.Storage
Locker = new object();
}
public StorageUploader(IServiceProvider serviceProvider, ICacheNotify<MigrationProgress> cacheMigrationNotify, ICache cache)
public StorageUploader(IServiceProvider serviceProvider, TempStream tempStream, ICacheNotify<MigrationProgress> cacheMigrationNotify, ICache cache)
{
ServiceProvider = serviceProvider;
ServiceProvider = serviceProvider;
TempStream = tempStream;
CacheMigrationNotify = cacheMigrationNotify;
Cache = cache;
}
@ -82,7 +84,7 @@ namespace ASC.Data.Storage
migrateOperation = Cache.Get<MigrateOperation>(GetCacheKey(tenantId));
if (migrateOperation != null) return;
migrateOperation = new MigrateOperation(ServiceProvider, CacheMigrationNotify, tenantId, newStorageSettings, storageFactoryConfig);
migrateOperation = new MigrateOperation(ServiceProvider, CacheMigrationNotify, tenantId, newStorageSettings, storageFactoryConfig, TempStream);
Cache.Insert(GetCacheKey(tenantId), migrateOperation, DateTime.MaxValue);
}
@ -133,20 +135,28 @@ namespace ASC.Data.Storage
ConfigPath = "";
}
public MigrateOperation(IServiceProvider serviceProvider, ICacheNotify<MigrationProgress> cacheMigrationNotify, int tenantId, StorageSettings settings, StorageFactoryConfig storageFactoryConfig)
public MigrateOperation(
IServiceProvider serviceProvider,
ICacheNotify<MigrationProgress> cacheMigrationNotify,
int tenantId,
StorageSettings settings,
StorageFactoryConfig storageFactoryConfig,
TempStream tempStream)
{
ServiceProvider = serviceProvider;
CacheMigrationNotify = cacheMigrationNotify;
this.tenantId = tenantId;
this.settings = settings;
StorageFactoryConfig = storageFactoryConfig;
StorageFactoryConfig = storageFactoryConfig;
TempStream = tempStream;
Modules = storageFactoryConfig.GetModuleList(ConfigPath, true);
StepCount = Modules.Count();
Log = serviceProvider.GetService<IOptionsMonitor<ILog>>().CurrentValue;
}
private IServiceProvider ServiceProvider { get; }
private StorageFactoryConfig StorageFactoryConfig { get; }
private StorageFactoryConfig StorageFactoryConfig { get; }
private TempStream TempStream { get; }
private ICacheNotify<MigrationProgress> CacheMigrationNotify { get; }
protected override void DoJob()
@ -168,7 +178,7 @@ namespace ASC.Data.Storage
var store = storageFactory.GetStorageFromConsumer(ConfigPath, tenantId.ToString(), module, storageSettingsHelper.DataStoreConsumer(settings));
var domains = StorageFactoryConfig.GetDomainList(ConfigPath, module).ToList();
var crossModuleTransferUtility = new CrossModuleTransferUtility(options, oldStore, store);
var crossModuleTransferUtility = new CrossModuleTransferUtility(options, TempStream, oldStore, store);
string[] files;
foreach (var domain in domains)

View File

@ -17,7 +17,9 @@ namespace ASC.Data.Backup.EF.Model
[Column("is_scheduled")]
public bool IsScheduled { get; set; }
public string Name { get; set; }
public string Name { get; set; }
public string Hash { get; set; }
[Column("storage_type")]
public BackupStorageType StorageType { get; set; }

View File

@ -53,18 +53,27 @@ namespace ASC.Data.Backup.Tasks
public bool DeleteBackupFileAfterCompletion { get; set; }
public bool BlockOldPortalAfterStart { get; set; }
public bool DeleteOldPortalAfterCompletion { get; set; }
private IOptionsMonitor<ILog> Options { get; set; }
private IOptionsMonitor<ILog> Options { get; set; }
private TempStream TempStream { get; }
private IServiceProvider ServiceProvider { get; set; }
public int Limit { get; private set; }
public TransferPortalTask(DbFactory dbFactory, IServiceProvider serviceProvider, IOptionsMonitor<ILog> options, StorageFactory storageFactory, StorageFactoryConfig storageFactoryConfig, ModuleProvider moduleProvider)
public TransferPortalTask(
DbFactory dbFactory,
IServiceProvider serviceProvider,
IOptionsMonitor<ILog> options,
StorageFactory storageFactory,
StorageFactoryConfig storageFactoryConfig,
ModuleProvider moduleProvider,
TempStream tempStream)
: base(dbFactory, options, storageFactory, storageFactoryConfig, moduleProvider)
{
DeleteBackupFileAfterCompletion = true;
BlockOldPortalAfterStart = true;
DeleteOldPortalAfterCompletion = true;
Options = options;
Options = options;
TempStream = tempStream;
ServiceProvider = serviceProvider;
}
@ -163,7 +172,7 @@ namespace ASC.Data.Backup.Tasks
{
var baseStorage = StorageFactory.GetStorage(ConfigPath, TenantId.ToString(), group.Key);
var destStorage = StorageFactory.GetStorage(ToConfigPath, columnMapper.GetTenantMapping().ToString(), group.Key);
var utility = new CrossModuleTransferUtility(Options, baseStorage, destStorage);
var utility = new CrossModuleTransferUtility(Options, TempStream, baseStorage, destStorage);
foreach (var file in group)
{

View File

@ -70,7 +70,8 @@ namespace ASC.Files.Core.Data
private IDaoFactory DaoFactory { get; }
private ChunkedUploadSessionHolder ChunkedUploadSessionHolder { get; }
private ProviderFolderDao ProviderFolderDao { get; }
private CrossDao CrossDao { get; }
private CrossDao CrossDao { get; }
public TempStream TempStream { get; }
public FileDao(
FactoryIndexerFile factoryIndexer,
@ -1424,10 +1425,14 @@ namespace ASC.Files.Core.Data
using var stream = GetFileStream(file);
if (stream == null) return dbFile;
dbFile.Document = new Document
using (var ms = new MemoryStream())
{
Data = Convert.ToBase64String(stream.GetCorrectBuffer())
};
stream.CopyTo(ms);
dbFile.Document = new Document
{
Data = Convert.ToBase64String(ms.GetBuffer())
};
}
return dbFile;
}

View File

@ -44,7 +44,8 @@ namespace ASC.Files.Core.EF
public string Comment { get; set; }
public string Changes { get; set; }
public bool Encrypted { get; set; }
public ForcesaveType Forcesave { get; set; }
public ForcesaveType Forcesave { get; set; }
public bool Thumb { get; set; }
[Nested]
@ -140,7 +141,9 @@ namespace ASC.Files.Core.EF
.HasColumnName("create_on")
.HasColumnType("datetime");
entity.Property(e => e.CurrentVersion).HasColumnName("current_version");
entity.Property(e => e.CurrentVersion).HasColumnName("current_version");
entity.Property(e => e.Thumb).HasColumnName("thumb");
entity.Property(e => e.Encrypted).HasColumnName("encrypted");
@ -228,7 +231,9 @@ namespace ASC.Files.Core.EF
entity.Property(e => e.CreateOn).HasColumnName("create_on");
entity.Property(e => e.CurrentVersion).HasColumnName("current_version");
entity.Property(e => e.CurrentVersion).HasColumnName("current_version");
entity.Property(e => e.Thumb).HasColumnName("thumb");
entity.Property(e => e.Encrypted).HasColumnName("encrypted");

View File

@ -52,13 +52,15 @@ namespace ASC.Files.Thirdparty.Sharpbox
{
[Scope]
internal class SharpBoxFileDao : SharpBoxDaoBase, IFileDao<string>
{
{
private TempStream TempStream { get; }
private CrossDao CrossDao { get; }
private SharpBoxDaoSelector SharpBoxDaoSelector { get; }
private IFileDao<int> FileDao { get; }
public SharpBoxFileDao(
IServiceProvider serviceProvider,
IServiceProvider serviceProvider,
TempStream tempStream,
UserManager userManager,
TenantManager tenantManager,
TenantUtil tenantUtil,
@ -70,7 +72,8 @@ namespace ASC.Files.Thirdparty.Sharpbox
SharpBoxDaoSelector sharpBoxDaoSelector,
IFileDao<int> fileDao)
: base(serviceProvider, userManager, tenantManager, tenantUtil, dbContextManager, setupInfo, monitor, fileUtility)
{
{
TempStream = tempStream;
CrossDao = crossDao;
SharpBoxDaoSelector = sharpBoxDaoSelector;
FileDao = fileDao;
@ -303,7 +306,7 @@ namespace ASC.Files.Thirdparty.Sharpbox
try
{
entry.GetDataTransferAccessor().Transfer(fileStream.GetBuffered(), nTransferDirection.nUpload);
entry.GetDataTransferAccessor().Transfer(TempStream.GetBuffered(fileStream), nTransferDirection.nUpload);
}
catch (SharpBoxException e)
{

View File

@ -264,7 +264,11 @@ namespace ASC.Files.Core.Migrations.MySql.FilesDbContextMySql
.ValueGeneratedOnAdd()
.HasColumnType("int")
.HasColumnName("version_group")
.HasDefaultValueSql("'1'");
.HasDefaultValueSql("'1'");
b.Property<bool>("Thumb")
.HasColumnType("tinyint(1)")
.HasColumnName("thumb");
b.HasKey("TenantId", "Id", "Version")
.HasName("PRIMARY");
@ -460,7 +464,7 @@ namespace ASC.Files.Core.Migrations.MySql.FilesDbContextMySql
b.Property<string>("Password")
.IsRequired()
.HasColumnType("varchar(100)")
.HasColumnType("varchar(512)")
.HasColumnName("password")
.UseCollation("utf8_general_ci")
.HasCharSet("utf8");

View File

@ -1,4 +1,5 @@
using System;
using System;
using Microsoft.EntityFrameworkCore.Metadata;
using Microsoft.EntityFrameworkCore.Migrations;
@ -51,7 +52,8 @@ namespace ASC.Files.Core.Migrations.MySql.FilesDbContextMySql
changes = table.Column<string>(type: "mediumtext", nullable: true, collation: "utf8_general_ci")
.Annotation("MySql:CharSet", "utf8"),
encrypted = table.Column<bool>(type: "tinyint(1)", nullable: false),
forcesave = table.Column<int>(type: "int", nullable: false)
forcesave = table.Column<int>(type: "int", nullable: false),
thumb = table.Column<bool>(type: "tinyint(1)", nullable: false)
},
constraints: table =>
{
@ -165,7 +167,7 @@ namespace ASC.Files.Core.Migrations.MySql.FilesDbContextMySql
.Annotation("MySql:CharSet", "utf8"),
user_name = table.Column<string>(type: "varchar(100)", nullable: false, collation: "utf8_general_ci")
.Annotation("MySql:CharSet", "utf8"),
password = table.Column<string>(type: "varchar(100)", nullable: false, collation: "utf8_general_ci")
password = table.Column<string>(type: "varchar(512)", nullable: false, collation: "utf8_general_ci")
.Annotation("MySql:CharSet", "utf8"),
token = table.Column<string>(type: "text", nullable: true, collation: "utf8_general_ci")
.Annotation("MySql:CharSet", "utf8"),

View File

@ -262,7 +262,11 @@ namespace ASC.Files.Core.Migrations.MySql.FilesDbContextMySql
.ValueGeneratedOnAdd()
.HasColumnType("int")
.HasColumnName("version_group")
.HasDefaultValueSql("'1'");
.HasDefaultValueSql("'1'");
b.Property<bool>("Thumb")
.HasColumnType("tinyint(1)")
.HasColumnName("thumb");
b.HasKey("TenantId", "Id", "Version")
.HasName("PRIMARY");
@ -458,7 +462,7 @@ namespace ASC.Files.Core.Migrations.MySql.FilesDbContextMySql
b.Property<string>("Password")
.IsRequired()
.HasColumnType("varchar(100)")
.HasColumnType("varchar(512)")
.HasColumnName("password")
.UseCollation("utf8_general_ci")
.HasCharSet("utf8");

View File

@ -322,6 +322,10 @@ namespace ASC.Files.Core.Migrations.Npgsql.FilesDbContextNpgsql
.HasColumnName("version_group")
.HasColumnType("integer")
.HasDefaultValueSql("1");
b.Property<bool>("Thumb")
.HasColumnName("thumb")
.HasColumnType("boolean");
b.HasKey("Id", "TenantId", "Version")
.HasName("files_file_pkey");
@ -515,7 +519,7 @@ namespace ASC.Files.Core.Migrations.Npgsql.FilesDbContextNpgsql
.IsRequired()
.HasColumnName("password")
.HasColumnType("character varying(100)")
.HasMaxLength(100);
.HasMaxLength(512);
b.Property<string>("Provider")
.IsRequired()

View File

@ -66,7 +66,8 @@ namespace ASC.Files.Core.Migrations.Npgsql.FilesDbContextNpgsql
comment = table.Column<string>(maxLength: 255, nullable: true, defaultValueSql: "NULL::character varying"),
changes = table.Column<string>(nullable: true),
encrypted = table.Column<bool>(nullable: false),
forcesave = table.Column<int>(nullable: false)
forcesave = table.Column<int>(nullable: false),
thumb = table.Column<bool>(nullable: false)
},
constraints: table =>
{
@ -173,7 +174,7 @@ namespace ASC.Files.Core.Migrations.Npgsql.FilesDbContextNpgsql
provider = table.Column<string>(maxLength: 50, nullable: false, defaultValueSql: "'0'::character varying"),
customer_title = table.Column<string>(maxLength: 400, nullable: false),
user_name = table.Column<string>(maxLength: 100, nullable: false),
password = table.Column<string>(maxLength: 100, nullable: false),
password = table.Column<string>(maxLength: 512, nullable: false),
token = table.Column<string>(nullable: true),
user_id = table.Column<Guid>(maxLength: 38, nullable: false),
folder_type = table.Column<int>(nullable: false),

View File

@ -150,7 +150,11 @@ namespace ASC.Files.Core.Migrations.Npgsql.FilesDbContextNpgsql
.ValueGeneratedOnAdd()
.HasColumnName("version_group")
.HasColumnType("integer")
.HasDefaultValueSql("1");
.HasDefaultValueSql("1");
b.Property<bool>("Thumb")
.HasColumnName("thumb")
.HasColumnType("boolean");
b.HasKey("Id", "TenantId", "Version")
.HasName("files_file_pkey");
@ -344,7 +348,7 @@ namespace ASC.Files.Core.Migrations.Npgsql.FilesDbContextNpgsql
.IsRequired()
.HasColumnName("password")
.HasColumnType("character varying(100)")
.HasMaxLength(100);
.HasMaxLength(512);
b.Property<string>("Provider")
.IsRequired()

View File

@ -35,7 +35,6 @@ using ASC.Common;
using ASC.Common.Security.Authentication;
using ASC.Common.Threading;
using ASC.Core.Tenants;
using ASC.Data.Storage;
using ASC.Files.Core;
using ASC.Files.Core.Resources;
using ASC.MessagingSystem;
@ -69,16 +68,19 @@ namespace ASC.Web.Files.Services.WCFService.FileOperations
class FileDownloadOperation : ComposeFileOperation<FileDownloadOperationData<string>, FileDownloadOperationData<int>>
{
public FileDownloadOperation(IServiceProvider serviceProvider, FileOperation<FileDownloadOperationData<string>, string> f1, FileOperation<FileDownloadOperationData<int>, int> f2)
public FileDownloadOperation(IServiceProvider serviceProvider, TempStream tempStream, FileOperation<FileDownloadOperationData<string>, string> f1, FileOperation<FileDownloadOperationData<int>, int> f2)
: base(serviceProvider, f1, f2)
{
{
TempStream = tempStream;
}
public override FileOperationType OperationType
{
get { return FileOperationType.Download; }
}
}
private TempStream TempStream { get; }
public override void RunJob(DistributedTask distributedTask, CancellationToken cancellationToken)
{
base.RunJob(distributedTask, cancellationToken);

View File

@ -42,13 +42,15 @@ namespace ASC.Web.Files.Services.WCFService.FileOperations
[Singletone(Additional = typeof(FileOperationsManagerHelperExtention))]
public class FileOperationsManager
{
private readonly DistributedTaskQueue tasks;
private readonly DistributedTaskQueue tasks;
private TempStream TempStream { get; }
private IServiceProvider ServiceProvider { get; }
public FileOperationsManager(DistributedTaskCacheNotify distributedTaskCacheNotify, IServiceProvider serviceProvider)
public FileOperationsManager(TempStream tempStream, DistributedTaskCacheNotify distributedTaskCacheNotify, IServiceProvider serviceProvider)
{
tasks = new DistributedTaskQueue(distributedTaskCacheNotify, "fileOperations", 10);
tasks = new DistributedTaskQueue(distributedTaskCacheNotify, "fileOperations", 10);
TempStream = tempStream;
ServiceProvider = serviceProvider;
}
@ -127,7 +129,7 @@ namespace ASC.Web.Files.Services.WCFService.FileOperations
var op1 = new FileDownloadOperation<int>(ServiceProvider, new FileDownloadOperationData<int>(folders.Where(r => r.Key.ValueKind == JsonValueKind.Number).ToDictionary(r => r.Key.GetInt32(), r => r.Value), files.Where(r => r.Key.ValueKind == JsonValueKind.Number).ToDictionary(r => r.Key.GetInt32(), r => r.Value), tenant, headers));
var op2 = new FileDownloadOperation<string>(ServiceProvider, new FileDownloadOperationData<string>(folders.Where(r => r.Key.ValueKind == JsonValueKind.String).ToDictionary(r => r.Key.GetString(), r => r.Value), files.Where(r => r.Key.ValueKind == JsonValueKind.String).ToDictionary(r => r.Key.GetString(), r => r.Value), tenant, headers));
var op = new FileDownloadOperation(ServiceProvider, op2, op1);
var op = new FileDownloadOperation(ServiceProvider, TempStream, op2, op1);
return QueueTask(userId, op);
}