Esempio n. 1
0
        private ShellSettings BuildShellSettings(TenantSetUpContext context)
        {
            var shellSettings = new ShellSettings()
            {
                Name     = context.SiteName,
                Location = !string.IsNullOrEmpty(context.Location)
                    ? context.Location
                    : context.SiteName.ToSafeFileName(),
                RequestedUrlHost   = context.RequestedUrlHost,
                RequestedUrlPrefix = context.RequestedUrlPrefix,
                State   = context.State,
                OwnerId = context.OwnerId
            };

            if (string.IsNullOrEmpty(shellSettings.DatabaseProvider))
            {
                var tablePrefix = context.DatabaseTablePrefix;
                if (!tablePrefix.EndsWith(ShellHelper.TablePrefixSeparator))
                {
                    tablePrefix += ShellHelper.TablePrefixSeparator;
                }
                shellSettings.DatabaseProvider = context.DatabaseProvider;
                shellSettings.ConnectionString = context.DatabaseConnectionString;
                shellSettings.TablePrefix      = tablePrefix;
            }

            shellSettings.CreatedDate  = context.CreatedDate;
            shellSettings.ModifiedDate = context.ModifiedDate;

            return(shellSettings);
        }
Esempio n. 2
0
        public async Task <ICommandResult <TenantSetUpContext> > InstallAsync(TenantSetUpContext context)
        {
            if (context == null)
            {
                throw new ArgumentNullException(nameof(context));
            }

            var result = new CommandResult <TenantSetUpContext>();

            try
            {
                // Validate tenant

                var shells = _shellSettingsManager.LoadSettings();
                if (shells != null)
                {
                    // Ensure a unique shell name
                    var shell = shells.FirstOrDefault(s => s.Name.Equals(context.SiteName, StringComparison.OrdinalIgnoreCase));
                    if (shell != null)
                    {
                        return(result.Failed($"A tenant with the name \"{shell.Name}\" already exists! Consider renaming the tenant."));
                    }

                    // Ensure a unique shell location
                    shell = shells.FirstOrDefault(s => s.Location.Equals(context.SiteName.ToSafeFileName(), StringComparison.OrdinalIgnoreCase));
                    if (shell != null)
                    {
                        return(result.Failed($"A tenant with the same location \"{shell.Location}\" already exists! Consider renaming the tenant."));
                    }

                    // Ensure a unique connection string & table prefix
                    shell = shells.FirstOrDefault(s =>
                                                  s.ConnectionString.Equals(context.DatabaseConnectionString, StringComparison.OrdinalIgnoreCase) &&
                                                  s.TablePrefix.Equals(context.DatabaseTablePrefix, StringComparison.OrdinalIgnoreCase));
                    if (shell != null)
                    {
                        return(result.Failed($"A tenant with the same connection string and table prefix already exists! Tenant name: \"{shell.Name}\"."));
                    }
                }

                // Install tenant

                return(await InstallInternalAsync(context));
            }
            catch (Exception ex)
            {
                return(result.Failed(ex.Message));
            }
        }
Esempio n. 3
0
        private Task <ICommandResult <TenantSetUpContext> > UpdateInternalAsync(TenantSetUpContext context)
        {
            var result = new CommandResult <TenantSetUpContext>();

            var shellSettings = BuildShellSettings(context);

            shellSettings.ModifiedDate = DateTimeOffset.Now;

            // Update & recycle shell
            _platoHost
            .UpdateShell(shellSettings)
            .RecycleShell(shellSettings);

            return(Task.FromResult(result.Success(context)));
        }
Esempio n. 4
0
        // --------------------------

        private async Task <ICommandResult <TenantSetUpContext> > InstallInternalAsync(TenantSetUpContext context)
        {
            var result = new CommandResult <TenantSetUpContext>();

            var shellSettings = BuildShellSettings(context);

            using (var shellContext = _shellContextFactory.CreateMinimalShellContext(shellSettings))
            {
                using (var scope = shellContext.ServiceProvider.CreateScope())
                {
                    var hasErrors = false;
                    void ReportError(string key, string message)
                    {
                        hasErrors           = true;
                        context.Errors[key] = message;
                    }

                    // Invoke set-up event handlers
                    var logger             = scope.ServiceProvider.GetRequiredService <ILogger <TenantSetUpService> >();
                    var setupEventHandlers = scope.ServiceProvider.GetServices <ISetUpEventHandler>();
                    await setupEventHandlers.InvokeAsync(x => x.SetUp(context, ReportError), logger);

                    // Return early if we encountered any errors
                    if (hasErrors)
                    {
                        return(result.Failed(context.Errors.Select(e => e.Value).ToArray()));
                    }

                    // Activate message broker subscriptions for tenant
                    var subscribers = scope.ServiceProvider.GetServices <IBrokerSubscriber>();
                    foreach (var subscriber in subscribers)
                    {
                        subscriber.Subscribe();
                    }

                    // Update tenant email settings
                    var emailSettingsManager = scope.ServiceProvider.GetService <IEmailSettingsManager>();
                    await emailSettingsManager.SaveAsync(context.EmailSettings);
                }
            }

            // Report any errors
            if (context.Errors.Count > 0)
            {
                return(result.Failed(context.Errors.Select(e => e.Value).ToArray()));
            }

            // Set shell defaults
            shellSettings.CreatedDate  = DateTimeOffset.Now;
            shellSettings.ModifiedDate = DateTimeOffset.Now;
            shellSettings.State        = TenantState.Running;

            // Update & recycle shell
            _platoHost
            .UpdateShell(shellSettings)
            .RecycleShell(shellSettings);

            return(result.Success(context));
        }
Esempio n. 5
0
        public async Task <ICommandResult <TenantSetUpContext> > UpdateAsync(TenantSetUpContext context)
        {
            if (context == null)
            {
                throw new ArgumentNullException(nameof(context));
            }

            var result = new CommandResult <TenantSetUpContext>();

            try
            {
                // Validate tenant

                var shells = _shellSettingsManager.LoadSettings();
                if (shells != null)
                {
                    bool connStringExists = false,
                         hostExists       = false,
                         prefixExists     = false;
                    foreach (var shell in shells)
                    {
                        // Ensure we are checking other shells
                        if (!shell.Name.Equals(context.SiteName, StringComparison.OrdinalIgnoreCase))
                        {
                            if (shell.ConnectionString.Equals(context.DatabaseConnectionString, StringComparison.OrdinalIgnoreCase) &&
                                shell.TablePrefix.Equals(context.DatabaseTablePrefix, StringComparison.OrdinalIgnoreCase))
                            {
                                connStringExists = true;
                            }

                            if (!string.IsNullOrEmpty(shell.RequestedUrlHost))
                            {
                                if (shell.RequestedUrlHost.Equals(context.RequestedUrlHost, StringComparison.OrdinalIgnoreCase))
                                {
                                    hostExists = true;
                                }
                            }

                            if (!string.IsNullOrEmpty(shell.RequestedUrlPrefix))
                            {
                                if (shell.RequestedUrlPrefix.Equals(context.RequestedUrlPrefix, StringComparison.OrdinalIgnoreCase))
                                {
                                    prefixExists = true;
                                }
                            }

                            if (connStringExists)
                            {
                                return(result.Failed($"A tenant with the same connection string and table prefix already exists! Tenant name: \"{shell.Name}\"."));
                            }

                            // If we have a host check host and prefix
                            // Else just check the prefix
                            if (hostExists)
                            {
                                if (hostExists && prefixExists)
                                {
                                    return(result.Failed($"A tenant with the same host name and prefix already exists! Tenant name: \"{shell.Name}\"."));
                                }
                            }
                            else
                            {
                                if (prefixExists)
                                {
                                    return(result.Failed($"A tenant with the same prefix already exists! Tenant name: \"{shell.Name}\"."));
                                }
                            }
                        }
                    }
                }

                // Update tenant

                return(await UpdateInternalAsync(context));
            }
            catch (Exception ex)
            {
                return(result.Failed(ex.Message));
            }
        }
Esempio n. 6
0
        public async Task <IActionResult> SetUpConffirmationPost(SetUpConfirmationViewModel model)
        {
            // Ensure default shell, We cannot sign-up from tenants
            if (!_shellSettings.IsDefaultShell())
            {
                return(Unauthorized());
            }

            // Validate
            if (model == null)
            {
                throw new ArgumentNullException(nameof(model));
            }

            if (string.IsNullOrEmpty(model.SessionId))
            {
                throw new ArgumentOutOfRangeException(nameof(model.SessionId));
            }

            if (string.IsNullOrEmpty(model.UserName))
            {
                throw new ArgumentOutOfRangeException(nameof(model.UserName));
            }

            if (string.IsNullOrEmpty(model.Password))
            {
                throw new ArgumentOutOfRangeException(nameof(model.Password));
            }

            if (!ModelState.IsValid)
            {
                return(View(model));
            }

            // Get the sign-up
            var signUp = await _signUpStore.GetBySessionIdAsync(model.SessionId);

            // Ensure we found the sign-up
            if (signUp == null)
            {
                return(NotFound());
            }

            // Email must be confirmed
            if (!signUp.EmailConfirmed)
            {
                return(Unauthorized());
            }

            // Set sign-up email address as default sender for tenant emails
            if (_defaultTenantSettings.SmtpSettings != null)
            {
                _defaultTenantSettings.SmtpSettings.DefaultFrom = signUp.Email;
            }

            // Create tenant context
            var setupContext = new TenantSetUpContext()
            {
                SiteName                 = signUp.CompanyName,
                Location                 = $"tenant{signUp.Id.ToString()}",
                DatabaseProvider         = "SqlClient",
                DatabaseConnectionString = _defaultTenantSettings.ConnectionString,
                DatabaseTablePrefix      = $"tenant{signUp.Id.ToString()}",
                AdminUsername            = model.UserName,
                AdminEmail               = signUp.Email,
                AdminPassword            = model.Password,
                RequestedUrlPrefix       = signUp.CompanyNameAlias,
                OwnerId       = signUp.Email,
                CreatedDate   = DateTimeOffset.Now,
                EmailSettings = new EmailSettings()
                {
                    SmtpSettings = _defaultTenantSettings.SmtpSettings
                },
                Errors = new Dictionary <string, string>()
            };

            // Attempt to create tenant
            var result = await _tenantSetUpService.InstallAsync(setupContext);

            // Report any errors
            if (!result.Succeeded)
            {
                foreach (var error in result.Errors)
                {
                    ViewData.ModelState.AddModelError(error.Code, error.Description);
                }
                return(await SetUp(signUp.SessionId));
            }

            // Redirect to set-up complete
            return(RedirectToAction(nameof(SetUpComplete), new RouteValueDictionary()
            {
                ["sessionId"] = signUp.SessionId
            }));
        }
Esempio n. 7
0
        public override async Task <IViewProviderResult> BuildUpdateAsync(ShellSettings settings, IViewProviderContext context)
        {
            var model = new EditTenantViewModel();

            if (!await context.Updater.TryUpdateModelAsync(model))
            {
                return(await BuildEditAsync(settings, context));
            }

            if (context.Updater.ModelState.IsValid)
            {
                // Ensure password
                if (model.SmtpSettings != null)
                {
                    if (!string.IsNullOrWhiteSpace(model.SmtpSettings.Password))
                    {
                        try
                        {
                            model.SmtpSettings.Password = _encrypter.Encrypt(model.SmtpSettings.Password);
                        }
                        catch (Exception e)
                        {
                            if (_logger.IsEnabled(LogLevel.Error))
                            {
                                _logger.LogError($"There was a problem encrypting the SMTP server password. {e.Message}");
                            }
                        }
                    }
                }

                var setupContext = new TenantSetUpContext()
                {
                    SiteName                 = model.SiteName,
                    Location                 = model.Location,
                    DatabaseProvider         = "SqlClient",
                    DatabaseConnectionString = model.ConnectionString,
                    AdminUsername            = model.UserName,
                    AdminEmail               = model.Email,
                    AdminPassword            = model.Password,
                    RequestedUrlHost         = model.RequestedUrlHost,
                    RequestedUrlPrefix       = model.RequestedUrlPrefix,
                    State         = model.State,
                    OwnerId       = model.OwnerId,
                    CreatedDate   = model.IsNewTenant ? DateTimeOffset.Now : model.CreatedDate,
                    ModifiedDate  = model.IsNewTenant ? model.ModifiedDate : DateTimeOffset.Now,
                    EmailSettings = new EmailSettings()
                    {
                        SmtpSettings = model.SmtpSettings
                    },
                    Errors = new Dictionary <string, string>()
                };

                if (!model.TablePrefixPreset)
                {
                    setupContext.DatabaseTablePrefix = model.TablePrefix;
                }

                // Install or update tenant
                var result = model.IsNewTenant
                    ? await _tenantSetUpService.InstallAsync(setupContext)
                    : await _tenantSetUpService.UpdateAsync(setupContext);

                // Report any errors
                if (!result.Succeeded)
                {
                    if (_logger.IsEnabled(LogLevel.Information))
                    {
                        if (model.IsNewTenant)
                        {
                            _logger.LogInformation($"Set-up of tenant '{setupContext.SiteName}' failed with the following errors...");
                        }
                        else
                        {
                            _logger.LogInformation($"Update of tenant '{setupContext.SiteName}' failed with the following errors...");
                        }
                    }

                    foreach (var error in result.Errors)
                    {
                        if (_logger.IsEnabled(LogLevel.Information))
                        {
                            _logger.LogInformation(error.Code + " " + error.Description);
                        }
                        context.Updater.ModelState.AddModelError(error.Code, error.Description);
                    }
                }
            }

            return(await BuildEditAsync(settings, context));
        }