DocSpace-client/common/services/ASC.ApiSystem/Classes/CommonMethods.cs
2022-10-14 12:26:02 +03:00

329 lines
12 KiB
C#

// (c) Copyright Ascensio System SIA 2010-2022
//
// This program is a free software product.
// You can redistribute it and/or modify it under the terms
// of the GNU Affero General Public License (AGPL) version 3 as published by the Free Software
// Foundation. In accordance with Section 7(a) of the GNU AGPL its Section 15 shall be amended
// to the effect that Ascensio System SIA expressly excludes the warranty of non-infringement of
// any third-party rights.
//
// This program is distributed WITHOUT ANY WARRANTY, without even the implied warranty
// of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. For details, see
// the GNU AGPL at: http://www.gnu.org/licenses/agpl-3.0.html
//
// You can contact Ascensio System SIA at Lubanas st. 125a-25, Riga, Latvia, EU, LV-1021.
//
// The interactive user interfaces in modified source and object code versions of the Program must
// display Appropriate Legal Notices, as required under Section 5 of the GNU AGPL version 3.
//
// Pursuant to Section 7(b) of the License you must retain the original Product logo when
// distributing the program. Pursuant to Section 7(e) we decline to grant you any rights under
// trademark law for use of our trademarks.
//
// All the Product's GUI elements, including illustrations and icon sets, as well as technical writing
// content are licensed under the terms of the Creative Commons Attribution-ShareAlike 4.0
// International. See the License terms at http://creativecommons.org/licenses/by-sa/4.0/legalcode
namespace ASC.ApiSystem.Controllers;
[Scope]
public class CommonMethods
{
private IHttpContextAccessor HttpContextAccessor { get; }
private IConfiguration Configuration { get; }
private ILogger<CommonMethods> Log { get; }
private CoreSettings CoreSettings { get; }
private CommonLinkUtility CommonLinkUtility { get; }
private EmailValidationKeyProvider EmailValidationKeyProvider { get; }
private TimeZoneConverter TimeZoneConverter { get; }
private CommonConstants CommonConstants { get; }
private HostedSolution HostedSolution { get; }
private IMemoryCache MemoryCache { get; }
private CoreBaseSettings CoreBaseSettings { get; }
private TenantManager TenantManager { get; }
private IHttpClientFactory ClientFactory { get; }
public CommonMethods(
IHttpContextAccessor httpContextAccessor,
IConfiguration configuration,
ILogger<CommonMethods> log,
CoreSettings coreSettings,
CommonLinkUtility commonLinkUtility,
EmailValidationKeyProvider emailValidationKeyProvider,
TimeZoneConverter timeZoneConverter, CommonConstants commonConstants,
IMemoryCache memoryCache,
HostedSolution hostedSolution,
CoreBaseSettings coreBaseSettings,
TenantManager tenantManager,
IHttpClientFactory clientFactory)
{
HttpContextAccessor = httpContextAccessor;
Configuration = configuration;
Log = log;
CoreSettings = coreSettings;
CommonLinkUtility = commonLinkUtility;
EmailValidationKeyProvider = emailValidationKeyProvider;
TimeZoneConverter = timeZoneConverter;
CommonConstants = commonConstants;
MemoryCache = memoryCache;
CoreBaseSettings = coreBaseSettings;
TenantManager = tenantManager;
ClientFactory = clientFactory;
HostedSolution = hostedSolution;
HostedSolution.Init(CommonConstants.BaseDbConnKeyString);
}
public object ToTenantWrapper(Tenant t)
{
return new
{
created = t.CreationDateTime,
domain = t.GetTenantDomain(CoreSettings),
hostedRegion = t.HostedRegion,
industry = t.Industry,
language = t.Language,
name = t.Name == "" ? Resource.PortalName : t.Name,
ownerId = t.OwnerId,
paymentId = t.PaymentId,
portalName = t.Alias,
status = t.Status.ToString(),
tenantId = t.Id,
timeZoneName = TimeZoneConverter.GetTimeZone(t.TimeZone).DisplayName,
};
}
public string CreateReference(string requestUriScheme, string tenantDomain, string email, bool first = false, string module = "", bool sms = false)
{
var url = CommonLinkUtility.GetConfirmationUrlRelative(email, ConfirmType.Auth, (first ? "true" : "") + module + (sms ? "true" : ""));
return $"{requestUriScheme}{Uri.SchemeDelimiter}{tenantDomain}/{url}{(first ? "&first=true" : "")}{(string.IsNullOrEmpty(module) ? "" : "&module=" + module)}{(sms ? "&sms=true" : "")}";
}
public bool SendCongratulations(string requestUriScheme, Tenant tenant, bool skipWelcome, out string url)
{
var validationKey = EmailValidationKeyProvider.GetEmailKey(tenant.Id, tenant.OwnerId.ToString() + ConfirmType.Auth);
url = string.Format("{0}{1}{2}{3}{4}?userid={5}&key={6}",
requestUriScheme,
Uri.SchemeDelimiter,
tenant.GetTenantDomain(CoreSettings),
CommonConstants.WebApiBaseUrl,
"portal/sendcongratulations",
tenant.OwnerId,
validationKey);
if (skipWelcome)
{
Log.LogDebug("congratulations skiped");
return false;
}
var request = new HttpRequestMessage();
request.Method = HttpMethod.Post;
request.RequestUri = new Uri(url);
request.Headers.Accept.Add(MediaTypeWithQualityHeaderValue.Parse("application/x-www-form-urlencoded"));
try
{
var httpClient = ClientFactory.CreateClient();
using var response = httpClient.Send(request);
using var stream = response.Content.ReadAsStream();
using var reader = new StreamReader(stream, Encoding.UTF8);
var result = reader.ReadToEnd();
Log.LogDebug("congratulations result = {0}", result);
var resObj = JObject.Parse(result);
if (resObj["errors"] != null && resObj["errors"].HasValues)
{
throw new Exception(result);
}
}
catch (Exception ex)
{
Log.LogError(ex, "SendCongratulations error");
return false;
}
url = null;
return true;
}
public bool GetTenant(IModel model, out Tenant tenant)
{
if (CoreBaseSettings.Standalone && model != null && !string.IsNullOrWhiteSpace((model.PortalName ?? "")))
{
tenant = TenantManager.GetTenant((model.PortalName ?? "").Trim());
return true;
}
if (model != null && model.TenantId.HasValue)
{
tenant = HostedSolution.GetTenant(model.TenantId.Value);
return true;
}
if (model != null && !string.IsNullOrWhiteSpace((model.PortalName ?? "")))
{
tenant = HostedSolution.GetTenant((model.PortalName ?? "").Trim());
return true;
}
tenant = null;
return false;
}
public bool IsTestEmail(string email)
{
//the point is not needed in gmail.com
email = Regex.Replace(email ?? "", "\\.*(?=\\S*(@gmail.com$))", "").ToLower();
if (string.IsNullOrEmpty(email) || string.IsNullOrEmpty(CommonConstants.AutotestSecretEmails))
return false;
var regex = new Regex(CommonConstants.AutotestSecretEmails, RegexOptions.IgnoreCase | RegexOptions.Singleline | RegexOptions.Compiled);
return regex.IsMatch(email);
}
public bool CheckMuchRegistration(TenantModel model, string clientIP, Stopwatch sw)
{
if (IsTestEmail(model.Email)) return false;
Log.LogDebug("clientIP = {0}", clientIP);
var cacheKey = "ip_" + clientIP;
if (MemoryCache.TryGetValue(cacheKey, out int ipAttemptsCount))
{
MemoryCache.Remove(cacheKey);
}
ipAttemptsCount++;
MemoryCache.Set(
// String that represents the name of the cache item,
// could be any string
cacheKey,
// Something to store in the cache
ipAttemptsCount,
new MemoryCacheEntryOptions
{
// Will not use absolute cache expiration
AbsoluteExpiration = DateTime.MaxValue,
// Cache will expire after one hour
// You can change this time interval according
// to your requriements
SlidingExpiration = CommonConstants.MaxAttemptsTimeInterval,
// Cache will not be removed before expired
Priority = CacheItemPriority.NeverRemove
});
if (ipAttemptsCount <= CommonConstants.MaxAttemptsCount) return false;
Log.LogDebug("PortalName = {0}; Too much reqests from ip: {1}", model.PortalName, clientIP);
sw.Stop();
return true;
}
public string GetClientIp()
{
return HttpContextAccessor.HttpContext.Connection.RemoteIpAddress.ToString();
//TODO: check old version
//if (request.Properties.ContainsKey("MS_HttpContext"))
//{
// return ((HttpContextWrapper)request.Properties["MS_HttpContext"]).Request.UserHostAddress;
//}
//if (request.Properties.ContainsKey(RemoteEndpointMessageProperty.Name))
//{
// var prop = (RemoteEndpointMessageProperty)request.Properties[RemoteEndpointMessageProperty.Name];
// return prop.Address;
//}
//return null;
}
public bool ValidateRecaptcha(string response, RecaptchaType recaptchaType, string ip)
{
try
{
string privateKey;
switch (recaptchaType)
{
case RecaptchaType.AndroidV2:
privateKey = Configuration["recaptcha:private-key:android"];
break;
case RecaptchaType.iOSV2:
privateKey = Configuration["recaptcha:private-key:ios"];
break;
default:
privateKey = Configuration["recaptcha:private-key"];
break;
}
var data = $"secret={privateKey}&remoteip={ip}&response={response}";
var url = Configuration["recaptcha:verify-url"] ?? "https://www.recaptcha.net/recaptcha/api/siteverify";
var request = new HttpRequestMessage();
request.RequestUri = new Uri(url);
request.Method = HttpMethod.Post;
request.Content = new StringContent(data, Encoding.UTF8, "application/x-www-form-urlencoded");
var httpClient = ClientFactory.CreateClient();
using var httpClientResponse = httpClient.Send(request);
using var stream = httpClientResponse.Content.ReadAsStream();
using var reader = new StreamReader(stream);
var resp = reader.ReadToEnd();
var resObj = JObject.Parse(resp);
if (resObj["success"] != null && resObj.Value<bool>("success"))
{
return true;
}
else
{
Log.LogDebug("Recaptcha error: {0}", resp);
}
if (resObj["error-codes"] != null && resObj["error-codes"].HasValues)
{
Log.LogDebug("Recaptcha api returns errors: {0}", resp);
}
}
catch (Exception ex)
{
Log.LogError(ex, "ValidateRecaptcha");
}
return false;
}
}