Пример #1
0
 public RegistrationController(
     CommonMethods commonMethods,
     CommonConstants commonConstants,
     IOptionsSnapshot <HostedSolution> hostedSolution,
     TimeZonesProvider timeZonesProvider,
     TimeZoneConverter timeZoneConverter,
     ApiSystemHelper apiSystemHelper,
     SecurityContext securityContext,
     TenantManager tenantManager,
     SettingsManager settingsManager,
     CoreSettings coreSettings,
     TenantDomainValidator tenantDomainValidator,
     UserFormatter userFormatter,
     UserManagerWrapper userManagerWrapper,
     IConfiguration configuration,
     IOptionsMonitor <ILog> option,
     PasswordHasher passwordHasher)
 {
     CommonMethods         = commonMethods;
     CommonConstants       = commonConstants;
     HostedSolution        = hostedSolution.Value;
     TimeZonesProvider     = timeZonesProvider;
     TimeZoneConverter     = timeZoneConverter;
     ApiSystemHelper       = apiSystemHelper;
     SecurityContext       = securityContext;
     TenantManager         = tenantManager;
     SettingsManager       = settingsManager;
     CoreSettings          = coreSettings;
     TenantDomainValidator = tenantDomainValidator;
     UserFormatter         = userFormatter;
     UserManagerWrapper    = userManagerWrapper;
     Configuration         = configuration;
     PasswordHasher        = passwordHasher;
     Log = option.Get("ASC.ApiSystem");
 }
Пример #2
0
 public PortalController(
     IConfiguration configuration,
     Core.SecurityContext securityContext,
     TenantManager tenantManager,
     SettingsManager settingsManager,
     ApiSystemHelper apiSystemHelper,
     CommonMethods commonMethods,
     HostedSolution hostedSolution,
     CoreSettings coreSettings,
     TenantDomainValidator tenantDomainValidator,
     UserFormatter userFormatter,
     UserManagerWrapper userManagerWrapper,
     CommonConstants commonConstants,
     IOptionsMonitor <ILog> option,
     TimeZonesProvider timeZonesProvider,
     TimeZoneConverter timeZoneConverter)
 {
     Configuration         = configuration;
     SecurityContext       = securityContext;
     TenantManager         = tenantManager;
     SettingsManager       = settingsManager;
     ApiSystemHelper       = apiSystemHelper;
     CommonMethods         = commonMethods;
     HostedSolution        = hostedSolution;
     CoreSettings          = coreSettings;
     TenantDomainValidator = tenantDomainValidator;
     UserFormatter         = userFormatter;
     UserManagerWrapper    = userManagerWrapper;
     CommonConstants       = commonConstants;
     TimeZonesProvider     = timeZonesProvider;
     TimeZoneConverter     = timeZoneConverter;
     Log = option.Get("ASC.ApiSystem");
 }
Пример #3
0
        private void ValidateDomain(string domain)
        {
            // size
            TenantDomainValidator.ValidateDomainLength(domain);
            // characters
            TenantDomainValidator.ValidateDomainCharacters(domain);

            var sameAliasTenants = ApiSystemHelper.FindTenantsInCache(domain, SecurityContext.CurrentAccount.ID);

            if (sameAliasTenants != null)
            {
                throw new TenantAlreadyExistsException("Address busy.", sameAliasTenants);
            }
        }
Пример #4
0
        public AuthHandler(
            IOptionsMonitor <AuthenticationSchemeOptions> options,
            ILoggerFactory logger,
            UrlEncoder encoder,
            ISystemClock clock,
            IConfiguration configuration,
            IOptionsMonitor <ILog> option,
            ApiSystemHelper apiSystemHelper) :
            base(options, logger, encoder, clock)
        {
            Configuration = configuration;

            Log = option.Get("ASC.ApiSystem");

            ApiSystemHelper = apiSystemHelper;
        }
Пример #5
0
        public AuthHandler(
            IOptionsMonitor <AuthenticationSchemeOptions> options,
            ILoggerFactory logger,
            UrlEncoder encoder,
            ISystemClock clock,
            IConfiguration configuration,
            IOptionsMonitor <ILog> option,
            ApiSystemHelper apiSystemHelper,
            MachinePseudoKeys machinePseudoKeys,
            IHttpContextAccessor httpContextAccessor) :
            base(options, logger, encoder, clock)
        {
            Configuration = configuration;

            Log = option.Get("ASC.ApiSystem");

            ApiSystemHelper     = apiSystemHelper;
            MachinePseudoKeys   = machinePseudoKeys;
            HttpContextAccessor = httpContextAccessor;
        }
        public object UpdatePortalName(string alias)
        {
            var enabled = SetupInfo.IsVisibleSettings("PortalRename");

            if (!enabled)
            {
                throw new SecurityException(Resource.PortalAccessSettingsTariffException);
            }

            if (CoreContext.Configuration.Personal)
            {
                throw new Exception(Resource.ErrorAccessDenied);
            }

            SecurityContext.DemandPermissions(SecutiryConstants.EditPortalSettings);

            if (String.IsNullOrEmpty(alias))
            {
                throw new ArgumentException();
            }


            var tenant = CoreContext.TenantManager.GetCurrentTenant();
            var user   = CoreContext.UserManager.GetUsers(SecurityContext.CurrentAccount.ID);

            var localhost = CoreContext.Configuration.BaseDomain == "localhost" || tenant.TenantAlias == "localhost";

            var newAlias           = alias.ToLowerInvariant();
            var oldAlias           = tenant.TenantAlias;
            var oldVirtualRootPath = CommonLinkUtility.GetFullAbsolutePath("~").TrimEnd('/');

            if (!String.Equals(newAlias, oldAlias, StringComparison.InvariantCultureIgnoreCase))
            {
                if (!String.IsNullOrEmpty(ApiSystemHelper.ApiSystemUrl))
                {
                    ApiSystemHelper.ValidatePortalName(newAlias);
                }
                else
                {
                    CoreContext.TenantManager.CheckTenantAddress(newAlias.Trim());
                }


                if (!String.IsNullOrEmpty(ApiSystemHelper.ApiCacheUrl))
                {
                    ApiSystemHelper.AddTenantToCache(newAlias);
                }

                tenant.TenantAlias = alias;
                tenant             = CoreContext.TenantManager.SaveTenant(tenant);


                if (!String.IsNullOrEmpty(ApiSystemHelper.ApiCacheUrl))
                {
                    ApiSystemHelper.RemoveTenantFromCache(oldAlias);
                }

                if (!localhost || string.IsNullOrEmpty(tenant.MappedDomain))
                {
                    StudioNotifyService.Instance.PortalRenameNotify(oldVirtualRootPath);
                }
            }
            else
            {
                throw new Exception(ResourceJS.ErrorPortalNameWasNotChanged);
            }

            var reference = CreateReference(Request, tenant.TenantDomain, tenant.TenantId, user.Email);

            return(new {
                message = Resource.SuccessfullyPortalRenameMessage,
                reference = reference
            });
        }
Пример #7
0
        protected override Task <AuthenticateResult> HandleAuthenticateAsync()
        {
            if (Convert.ToBoolean(Configuration[Scheme.Name] ?? "false"))
            {
                Log.DebugFormat("Auth for {0} skipped", Scheme.Name);

                return(Task.FromResult(AuthenticateResult.Success(new AuthenticationTicket(Context.User, new AuthenticationProperties(), Scheme.Name))));
            }

            try
            {
                Context.Request.Headers.TryGetValue("Authorization", out var headers);

                var header = headers.FirstOrDefault();

                if (string.IsNullOrEmpty(header))
                {
                    Log.Debug("Auth header is NULL");

                    return(Task.FromResult(AuthenticateResult.Fail(new AuthenticationException(HttpStatusCode.Unauthorized.ToString()))));
                }

                var substring = "ASC";

                if (header.StartsWith(substring, StringComparison.InvariantCultureIgnoreCase))
                {
                    var splitted = header.Substring(substring.Length).Trim().Split(':', StringSplitOptions.RemoveEmptyEntries);

                    if (splitted.Length < 3)
                    {
                        Log.DebugFormat("Auth failed: invalid token {0}.", header);

                        return(Task.FromResult(AuthenticateResult.Fail(new AuthenticationException(HttpStatusCode.Unauthorized.ToString()))));
                    }

                    var pkey     = splitted[0];
                    var date     = splitted[1];
                    var orighash = splitted[2];

                    Log.Debug("Variant of correct auth:" + ApiSystemHelper.CreateAuthToken(pkey));

                    if (!string.IsNullOrWhiteSpace(date))
                    {
                        var timestamp = DateTime.ParseExact(date, "yyyyMMddHHmmss", CultureInfo.InvariantCulture);

                        var trustInterval = TimeSpan.FromMinutes(Convert.ToDouble(Configuration["auth:trust-interval"] ?? "5"));

                        if (DateTime.UtcNow > timestamp.Add(trustInterval))
                        {
                            Log.DebugFormat("Auth failed: invalid timesatmp {0}, now {1}.", timestamp, DateTime.UtcNow);

                            return(Task.FromResult(AuthenticateResult.Fail(new AuthenticationException(HttpStatusCode.Forbidden.ToString()))));
                        }
                    }

                    var skey = MachinePseudoKeys.GetMachineConstant();
                    using var hasher = new HMACSHA1(skey);
                    var data = string.Join("\n", date, pkey);
                    var hash = hasher.ComputeHash(Encoding.UTF8.GetBytes(data));

                    if (WebEncoders.Base64UrlEncode(hash) != orighash && Convert.ToBase64String(hash) != orighash)
                    {
                        Log.DebugFormat("Auth failed: invalid token {0}, expect {1} or {2}.", orighash, WebEncoders.Base64UrlEncode(hash), Convert.ToBase64String(hash));

                        return(Task.FromResult(AuthenticateResult.Fail(new AuthenticationException(HttpStatusCode.Forbidden.ToString()))));
                    }
                }
                else
                {
                    Log.DebugFormat("Auth failed: invalid auth header. Sheme: {0}, parameter: {1}.", Scheme.Name, header);

                    return(Task.FromResult(AuthenticateResult.Fail(new AuthenticationException(HttpStatusCode.Forbidden.ToString()))));
                }
            }
            catch (Exception ex)
            {
                Log.Error(ex);

                return(Task.FromResult(AuthenticateResult.Fail(new AuthenticationException(HttpStatusCode.InternalServerError.ToString()))));
            }
            var identity = new ClaimsIdentity(Scheme.Name);

            Log.InfoFormat("Auth success {0}", Scheme.Name);
            if (HttpContextAccessor?.HttpContext != null)
            {
                HttpContextAccessor.HttpContext.User = new CustomClaimsPrincipal(new ClaimsIdentity(Scheme.Name), identity);
            }
            return(Task.FromResult(AuthenticateResult.Success(new AuthenticationTicket(Context.User, new AuthenticationProperties(), Scheme.Name))));
        }
Пример #8
0
        public IActionResult Register(TenantModel model)
        {
            if (model == null)
            {
                return(BadRequest(new
                {
                    errors = "Tenant data is required."
                }));
            }

            if (!ModelState.IsValid)
            {
                var errors = new JArray();

                foreach (var k in ModelState.Keys)
                {
                    errors.Add(ModelState[k].Errors.FirstOrDefault().ErrorMessage);
                }

                return(Ok(new
                {
                    errors
                }));
            }

            var sw = Stopwatch.StartNew();

            object error;

            if (string.IsNullOrEmpty(model.PasswordHash) && !string.IsNullOrEmpty(model.Password))
            {
                if (!CheckPasswordPolicy(model.Password, out error))
                {
                    sw.Stop();

                    return(BadRequest(error));
                }
                model.PasswordHash = PasswordHasher.GetClientPassword(model.Password);
            }

            if (!CheckValidName(model.FirstName.Trim() + model.LastName.Trim(), out error))
            {
                sw.Stop();

                return(BadRequest(error));
            }

            var checkTenantBusyPesp = CheckExistingNamePortal(model.PortalName.Trim());

            if (checkTenantBusyPesp != null)
            {
                sw.Stop();

                return(checkTenantBusyPesp);
            }

            Log.DebugFormat("PortalName = {0}; Elapsed ms. CheckExistingNamePortal: {1}", model.PortalName, sw.ElapsedMilliseconds);

            var clientIP = CommonMethods.GetClientIp();

            Log.DebugFormat("clientIP = {0}", clientIP);

            if (CommonMethods.CheckMuchRegistration(model, clientIP, sw))
            {
                return(BadRequest(new
                {
                    errors = new[] { "tooMuchAttempts" }
                }));
            }

            if (CommonConstants.RecaptchaRequired && !CommonMethods.IsTestEmail(model.Email))
            {
                /*** validate recaptcha ***/
                if (!CommonMethods.ValidateRecaptcha(model.RecaptchaResponse, clientIP))
                {
                    Log.DebugFormat("PortalName = {0}; Elapsed ms. ValidateRecaptcha: {1}", model.PortalName, sw.ElapsedMilliseconds);

                    sw.Stop();

                    return(BadRequest(new
                    {
                        errors = new[] { "recaptchaInvalid" },
                        message = "Recaptcha is invalid"
                    }));
                }

                Log.DebugFormat("PortalName = {0}; Elapsed ms. ValidateRecaptcha: {1}", model.PortalName, sw.ElapsedMilliseconds);
            }

            //check payment portal count
            if (Configuration["core:base-domain"] == "localhost")
            {
                var tenants     = HostedSolution.GetTenants(DateTime.MinValue);
                var firstTenant = tenants.FirstOrDefault();

                if (firstTenant != null)
                {
                    var activePortals = tenants.Count(r => r.Status != TenantStatus.Suspended && r.Status != TenantStatus.RemovePending);

                    var quota = HostedSolution.GetTenantQuota(firstTenant.TenantId);

                    if (quota.CountPortals > 0 && quota.CountPortals <= activePortals)
                    {
                        return(BadRequest(new
                        {
                            errors = new[] { "portalsCountTooMuch" },
                            message = "Too much portals registered already",
                        }));
                    }
                }
            }

            var language = model.Language ?? string.Empty;

            var tz = TimeZonesProvider.GetCurrentTimeZoneInfo(language);

            Log.DebugFormat("PortalName = {0}; Elapsed ms. TimeZonesProvider.GetCurrentTimeZoneInfo: {1}", model.PortalName, sw.ElapsedMilliseconds);

            if (!string.IsNullOrEmpty(model.TimeZoneName))
            {
                tz = TimeZoneConverter.GetTimeZone(model.TimeZoneName.Trim(), false) ?? tz;

                Log.DebugFormat("PortalName = {0}; Elapsed ms. TimeZonesProvider.OlsonTimeZoneToTimeZoneInfo: {1}", model.PortalName, sw.ElapsedMilliseconds);
            }

            var lang = TimeZonesProvider.GetCurrentCulture(language);

            Log.DebugFormat("PortalName = {0}; model.Language = {1}, resultLang.DisplayName = {2}", model.PortalName, language, lang.DisplayName);

            var info = new TenantRegistrationInfo
            {
                Name                = Configuration["web:portal-name"] ?? "Cloud Office Applications",
                Address             = model.PortalName,
                Culture             = lang,
                FirstName           = model.FirstName.Trim(),
                LastName            = model.LastName.Trim(),
                PasswordHash        = String.IsNullOrEmpty(model.PasswordHash) ? null : model.PasswordHash,
                Email               = model.Email.Trim(),
                TimeZoneInfo        = tz,
                MobilePhone         = string.IsNullOrEmpty(model.Phone) ? null : model.Phone.Trim(),
                Industry            = (TenantIndustry)model.Industry,
                Spam                = model.Spam,
                Calls               = model.Calls,
                Analytics           = model.Analytics,
                LimitedControlPanel = model.LimitedControlPanel
            };

            if (!string.IsNullOrEmpty(model.PartnerId))
            {
                if (Guid.TryParse(model.PartnerId, out Guid guid))
                {
                    // valid guid
                    info.PartnerId = model.PartnerId;
                }
            }

            if (!string.IsNullOrEmpty(model.AffiliateId))
            {
                info.AffiliateId = model.AffiliateId;
            }

            Tenant t;

            try
            {
                /****REGISTRATION!!!*****/
                if (!string.IsNullOrEmpty(ApiSystemHelper.ApiCacheUrl))
                {
                    ApiSystemHelper.AddTenantToCache(info.Address, SecurityContext.CurrentAccount.ID);

                    Log.DebugFormat("PortalName = {0}; Elapsed ms. CacheController.AddTenantToCache: {1}", model.PortalName, sw.ElapsedMilliseconds);
                }

                HostedSolution.RegisterTenant(info, out t);

                /*********/

                Log.DebugFormat("PortalName = {0}; Elapsed ms. HostedSolution.RegisterTenant: {1}", model.PortalName, sw.ElapsedMilliseconds);
            }
            catch (Exception e)
            {
                sw.Stop();

                Log.Error(e);

                return(StatusCode(StatusCodes.Status500InternalServerError, new
                {
                    errors = new[] { "registerNewTenantError" },
                    message = e.Message,
                    stacktrace = e.StackTrace
                }));
            }

            var isFirst = true;

            string sendCongratulationsAddress = null;

            if (!String.IsNullOrEmpty(model.PasswordHash))
            {
                isFirst = !CommonMethods.SendCongratulations(Request.Scheme, t, model.SkipWelcome, out sendCongratulationsAddress);
            }
            else if (Configuration["core:base-domain"] == "localhost")
            {
                try
                {
                    /* set wizard not completed*/
                    TenantManager.SetCurrentTenant(t);

                    var settings = SettingsManager.Load <WizardSettings>();

                    settings.Completed = false;

                    SettingsManager.Save(settings);
                }
                catch (Exception e)
                {
                    Log.Error(e);
                }
            }

            var reference = CommonMethods.CreateReference(Request.Scheme, t.GetTenantDomain(CoreSettings), info.Email, isFirst, model.Module);

            Log.DebugFormat("PortalName = {0}; Elapsed ms. CreateReferenceByCookie...: {1}", model.PortalName, sw.ElapsedMilliseconds);

            sw.Stop();

            return(Ok(new
            {
                errors = "",
                reference,
                tenant = ToTenantWrapper(t),
                referenceWelcome = sendCongratulationsAddress,
            }));
        }
Пример #9
0
        public string PortalRemove(string email, string key)
        {
            email = (email ?? "").Trim();
            if (!string.IsNullOrEmpty(email) && !email.TestEmailRegex())
            {
                throw new ArgumentException(Resource.ErrorNotCorrectEmail);
            }

            var checkKeyResult = EmailValidationKeyProvider.ValidateEmailKey(email + ConfirmType.PortalRemove, key, SetupInfo.ValidEmailKeyInterval);

            if (checkKeyResult == EmailValidationKeyProvider.ValidationResult.Expired)
            {
                throw new ExpiredTokenException(Resource.ErrorExpiredActivationLink);
            }

            if (checkKeyResult == EmailValidationKeyProvider.ValidationResult.Invalid)
            {
                throw new SecurityAccessDeniedException(Resource.ErrorConfirmURLError);
            }

            var curTenant = CoreContext.TenantManager.GetCurrentTenant();
            var tariff    = CoreContext.TenantManager.GetTenantQuota(curTenant.TenantId);

            CoreContext.TenantManager.RemoveTenant(curTenant.TenantId);

            if (!String.IsNullOrEmpty(ApiSystemHelper.ApiCacheUrl))
            {
                ApiSystemHelper.RemoveTenantFromCache(curTenant.TenantAlias);
            }

            var currentUser  = CoreContext.UserManager.GetUsers(curTenant.OwnerId);
            var redirectLink = SetupInfo.TeamlabSiteRedirect + "/remove-portal-feedback-form.aspx#" +
                               Convert.ToBase64String(System.Text.Encoding.UTF8.GetBytes("{\"firstname\":\"" + currentUser.FirstName +
                                                                                         "\",\"lastname\":\"" + currentUser.LastName +
                                                                                         "\",\"alias\":\"" + curTenant.TenantAlias +
                                                                                         "\",\"email\":\"" + currentUser.Email + "\"}"));

            var authed = false;

            try
            {
                if (!SecurityContext.IsAuthenticated)
                {
                    SecurityContext.AuthenticateMe(ASC.Core.Configuration.Constants.CoreSystem);
                    authed = true;
                }

                MessageService.Send(HttpContext.Current.Request, MessageAction.PortalDeleted);
            }
            finally
            {
                if (authed)
                {
                    SecurityContext.Logout();
                }
            }

            _successMessage = string.Format(Resource.DeletePortalSuccessMessage, "<br/>", "<a href=\"{0}\">", "</a>");
            _successMessage = string.Format(_successMessage, redirectLink);

            StudioNotifyService.Instance.SendMsgPortalDeletionSuccess(curTenant, tariff, redirectLink);

            return(JsonConvert.SerializeObject(
                       new {
                successMessage = _successMessage,
                redirectLink = redirectLink
            }
                       ));
        }
Пример #10
0
        public IActionResult Register(TenantModel model)
        {
            if (model == null)
            {
                return BadRequest(new
                {
                    error = "portalNameEmpty",
                    message = "PortalName is required"
                });
            }

            if (!ModelState.IsValid)
            {
                var message = new JArray();

                foreach (var k in ModelState.Keys)
                {
                    message.Add(ModelState[k].Errors.FirstOrDefault().ErrorMessage);
                }

                return BadRequest(new
                {
                    error = "params",
                    message
                });
            }

            var sw = Stopwatch.StartNew();

            if (string.IsNullOrEmpty(model.PasswordHash))
            {
                if (!CheckPasswordPolicy(model.Password, out var error1))
                {
                    sw.Stop();
                    return BadRequest(error1);
                }

                if (!string.IsNullOrEmpty(model.Password))
                {
                    model.PasswordHash = PasswordHasher.GetClientPassword(model.Password);
                }

            }
            model.FirstName = (model.FirstName ?? "").Trim();
            model.LastName = (model.LastName ?? "").Trim();

            if (!CheckValidName(model.FirstName + model.LastName, out var error))
            {
                sw.Stop();

                return BadRequest(error);
            }

            model.PortalName = (model.PortalName ?? "").Trim();

            if (!CheckExistingNamePortal(model.PortalName, out error))
            {
                sw.Stop();

                return BadRequest(error);
            }

            Log.DebugFormat("PortalName = {0}; Elapsed ms. CheckExistingNamePortal: {1}", model.PortalName, sw.ElapsedMilliseconds);

            var clientIP = CommonMethods.GetClientIp();

            if (CommonMethods.CheckMuchRegistration(model, clientIP, sw))
            {
                return BadRequest(new
                {
                    error = "tooMuchAttempts",
                    message = "Too much attempts already"
                });
            }

            if (!CheckRecaptcha(model, clientIP, sw, out error))
            {
                return BadRequest(error);
            }

            if (!CheckRegistrationPayment(out error))
            {
                return BadRequest(error);
            }

            var language = model.Language ?? string.Empty;

            var tz = TimeZonesProvider.GetCurrentTimeZoneInfo(language);

            Log.DebugFormat("PortalName = {0}; Elapsed ms. TimeZonesProvider.GetCurrentTimeZoneInfo: {1}", model.PortalName, sw.ElapsedMilliseconds);

            if (!string.IsNullOrEmpty(model.TimeZoneName))
            {
                tz = TimeZoneConverter.GetTimeZone(model.TimeZoneName.Trim(), false) ?? tz;

                Log.DebugFormat("PortalName = {0}; Elapsed ms. TimeZonesProvider.OlsonTimeZoneToTimeZoneInfo: {1}", model.PortalName, sw.ElapsedMilliseconds);
            }

            var lang = TimeZonesProvider.GetCurrentCulture(language);

            Log.DebugFormat("PortalName = {0}; model.Language = {1}, resultLang.DisplayName = {2}", model.PortalName, language, lang.DisplayName);

            var info = new TenantRegistrationInfo
            {
                Name = Configuration["web:portal-name"] ?? "Cloud Office Applications",
                Address = model.PortalName,
                Culture = lang,
                FirstName = model.FirstName,
                LastName = model.LastName,
                PasswordHash = string.IsNullOrEmpty(model.PasswordHash) ? null : model.PasswordHash,
                Email = (model.Email ?? "").Trim(),
                TimeZoneInfo = tz,
                MobilePhone = string.IsNullOrEmpty(model.Phone) ? null : model.Phone.Trim(),
                Industry = (TenantIndustry)model.Industry,
                Spam = model.Spam,
                Calls = model.Calls,
                Analytics = model.Analytics,
                LimitedControlPanel = model.LimitedControlPanel
            };

            if (!string.IsNullOrEmpty(model.PartnerId))
            {
                if (Guid.TryParse(model.PartnerId, out _))
                {
                    // valid guid
                    info.PartnerId = model.PartnerId;
                }
            }

            if (!string.IsNullOrEmpty(model.AffiliateId))
            {
                info.AffiliateId = model.AffiliateId;
            }

            if (!string.IsNullOrEmpty(model.Campaign))
            {
                info.Campaign = model.Campaign;
            }

            Tenant t;

            try
            {
                /****REGISTRATION!!!*****/
                if (!string.IsNullOrEmpty(ApiSystemHelper.ApiCacheUrl))
                {
                    ApiSystemHelper.AddTenantToCache(info.Address, SecurityContext.CurrentAccount.ID);

                    Log.DebugFormat("PortalName = {0}; Elapsed ms. CacheController.AddTenantToCache: {1}", model.PortalName, sw.ElapsedMilliseconds);
                }

                HostedSolution.RegisterTenant(info, out t);

                /*********/

                Log.DebugFormat("PortalName = {0}; Elapsed ms. HostedSolution.RegisterTenant: {1}", model.PortalName, sw.ElapsedMilliseconds);
            }
            catch (Exception e)
            {
                sw.Stop();

                Log.Error(e);

                return StatusCode(StatusCodes.Status500InternalServerError, new
                {
                    error = "registerNewTenantError",
                    message = e.Message,
                    stacktrace = e.StackTrace
                });
            }

            var trialQuota = Configuration["trial-quota"];
            if (!string.IsNullOrEmpty(trialQuota))
            {
                if (int.TryParse(trialQuota, out var trialQuotaId))
                {
                    var dueDate = DateTime.MaxValue;
                    if (int.TryParse(Configuration["trial-due"], out var dueTrial))
                    {
                        dueDate = DateTime.UtcNow.AddDays(dueTrial);
                    }

                    var tariff = new Tariff
                    {
                        QuotaId = trialQuotaId,
                        DueDate = dueDate
                    };
                    HostedSolution.SetTariff(t.TenantId, tariff);
                }
            }


            var isFirst = true;
            string sendCongratulationsAddress = null;

            if (!string.IsNullOrEmpty(model.PasswordHash))
            {
                isFirst = !CommonMethods.SendCongratulations(Request.Scheme, t, model.SkipWelcome, out sendCongratulationsAddress);
            }
            else if (Configuration["core:base-domain"] == "localhost")
            {
                try
                {
                    /* set wizard not completed*/
                    TenantManager.SetCurrentTenant(t);

                    var settings = SettingsManager.Load<WizardSettings>();

                    settings.Completed = false;

                    SettingsManager.Save(settings);
                }
                catch (Exception e)
                {
                    Log.Error(e);
                }
            }

            var reference = CommonMethods.CreateReference(Request.Scheme, t.GetTenantDomain(CoreSettings), info.Email, isFirst);

            Log.DebugFormat("PortalName = {0}; Elapsed ms. CreateReferenceByCookie...: {1}", model.PortalName, sw.ElapsedMilliseconds);

            sw.Stop();

            return Ok(new
            {
                reference,
                tenant = CommonMethods.ToTenantWrapper(t),
                referenceWelcome = sendCongratulationsAddress
            });
        }