install/upgrade refactoring to consolidate all use cases and implement IInstallable interface for modules, moved tenant creation to site management UI, fixed z-order issues in Blazor theme, enhanced JS Interop methods to support integrity and crossorigin
This commit is contained in:
		| @ -62,7 +62,8 @@ else | ||||
| - Repository\I[Module]Repository.cs - interface for defining repository methods<br /> | ||||
| - Repository\[Module]Respository.cs - implements repository interface methods for data access using EF Core<br /> | ||||
| - Repository\[Module]Context.cs - provides a DB Context for data access<br /> | ||||
| - Scripts\01.00.00.sql - database schema definition<br /><br /> | ||||
| - Scripts\[Module].1.0.0.sql - database schema definition script<br /><br /> | ||||
| - Scripts\[Module].Uninstall.sql - database uninstall script<br /><br /> | ||||
| [RootPath]Shared\<br /> | ||||
| - [Owner].[Module]s.Module.Shared.csproj - shared project<br /> | ||||
| - Models\[Module].cs - model definition<br /><br /> | ||||
|  | ||||
| @ -11,7 +11,8 @@ namespace [Owner].[Module]s.Modules | ||||
|             Description = "[Module]", | ||||
|             Version = "1.0.0", | ||||
|             Dependencies = "[Owner].[Module]s.Module.Shared", | ||||
|             ServerManagerType = "[ServerManagerType]" | ||||
|             ServerManagerType = "[ServerManagerType]", | ||||
|             ReleaseVersions = "1.0.0" | ||||
|         }; | ||||
|     } | ||||
| } | ||||
|  | ||||
| @ -3,18 +3,32 @@ using System.Linq; | ||||
| using System.Text.Json; | ||||
| using Oqtane.Modules; | ||||
| using Oqtane.Models; | ||||
| using Oqtane.Infrastructure; | ||||
| using Oqtane.Repository; | ||||
| using [Owner].[Module]s.Models; | ||||
| using [Owner].[Module]s.Repository; | ||||
|  | ||||
| namespace [Owner].[Module]s.Manager | ||||
| { | ||||
|     public class [Module]Manager : IPortable | ||||
|     public class [Module]Manager : IInstallable, IPortable | ||||
|     { | ||||
|         private I[Module]Repository _[Module]s; | ||||
|         private ISqlRepository _sql; | ||||
|  | ||||
|         public [Module]Manager(I[Module]Repository [Module]s) | ||||
|         public [Module]Manager(I[Module]Repository [Module]s, ISqlRepository sql) | ||||
|         { | ||||
|             _[Module]s = [Module]s; | ||||
|             _sql = sql; | ||||
|         } | ||||
|  | ||||
|         public bool Install(Tenant tenant, string version) | ||||
|         { | ||||
|             return _sql.ExecuteScript(tenant, GetType().Assembly, "[Owner].[Module]." + version + ".sql"); | ||||
|         } | ||||
|  | ||||
|         public bool Uninstall(Tenant tenant) | ||||
|         { | ||||
|             return _sql.ExecuteScript(tenant, GetType().Assembly, "[Owner].[Module].Uninstall.sql"); | ||||
|         } | ||||
|  | ||||
|         public string ExportModule(Module module) | ||||
|  | ||||
| @ -13,13 +13,13 @@ | ||||
|   </PropertyGroup> | ||||
|  | ||||
|   <ItemGroup> | ||||
|     <None Remove="Scripts\01.00.00.sql" /> | ||||
|     <None Remove="Scripts\Uninstall.sql" /> | ||||
|     <None Remove="Scripts\[Module].1.0.0.sql" /> | ||||
|     <None Remove="Scripts\[Module].Uninstall.sql" /> | ||||
|   </ItemGroup> | ||||
|  | ||||
|   <ItemGroup> | ||||
|     <EmbeddedResource Include="Scripts\01.00.00.sql" /> | ||||
|     <EmbeddedResource Include="Scripts\Uninstall.sql" /> | ||||
|     <EmbeddedResource Include="Scripts\[Module].1.0.0.sql" /> | ||||
|     <EmbeddedResource Include="Scripts\[Module].Uninstall.sql" /> | ||||
|   </ItemGroup> | ||||
|  | ||||
|   <ItemGroup> | ||||
|  | ||||
| @ -54,7 +54,8 @@ else | ||||
| - Repository\I[Module]Repository.cs - interface for defining repository methods<br /> | ||||
| - Repository\[Module]Respository.cs - implements repository interface methods for data access using EF Core<br /> | ||||
| - Repository\[Module]Context.cs - provides a DB Context for data access<br /> | ||||
| - Scripts\01.00.00.sql - database schema definition<br /><br /> | ||||
| - Scripts\[Module].1.0.0.sql - database schema definition script<br /><br /> | ||||
| - Scripts\[Module].Uninstall.sql - database uninstall script<br /><br /> | ||||
| [RootPath]Oqtane.Shared\Modules\[Module]\<br /> | ||||
| - Models\[Module].cs - model definition<br /><br /> | ||||
|  | ||||
|  | ||||
| @ -11,7 +11,8 @@ namespace [Owner].[Module]s.Modules | ||||
|             Description = "[Module]", | ||||
|             Version = "1.0.0", | ||||
|             Dependencies = "[Owner].[Module]s.Module.Shared", | ||||
|             ServerManagerType = "[ServerManagerType]" | ||||
|             ServerManagerType = "[ServerManagerType]", | ||||
|             ReleaseVersions = "1.0.0" | ||||
|         }; | ||||
|     } | ||||
| } | ||||
|  | ||||
| @ -3,18 +3,32 @@ using System.Linq; | ||||
| using System.Text.Json; | ||||
| using Oqtane.Modules; | ||||
| using Oqtane.Models; | ||||
| using Oqtane.Infrastructure; | ||||
| using Oqtane.Repository; | ||||
| using [Owner].[Module]s.Models; | ||||
| using [Owner].[Module]s.Repository; | ||||
|  | ||||
| namespace [Owner].[Module]s.Manager | ||||
| { | ||||
|     public class [Module]Manager : IPortable | ||||
|     public class [Module]Manager : IInstallable, IPortable | ||||
|     { | ||||
|         private I[Module]Repository _[Module]s; | ||||
|         private ISqlRepository _sql; | ||||
|  | ||||
|         public [Module]Manager(I[Module]Repository [Module]s) | ||||
|         public [Module]Manager(I[Module]Repository [Module]s, ISqlRepository sql) | ||||
|         { | ||||
|             _[Module]s = [Module]s; | ||||
|             _sql = sql; | ||||
|         } | ||||
|  | ||||
|         public bool Install(Tenant tenant, string version) | ||||
|         { | ||||
|             return _sql.ExecuteScript(tenant, GetType().Assembly, "[Owner].[Module]." + version + ".sql"); | ||||
|         } | ||||
|  | ||||
|         public bool Uninstall(Tenant tenant) | ||||
|         { | ||||
|             return _sql.ExecuteScript(tenant, GetType().Assembly, "[Owner].[Module].Uninstall.sql"); | ||||
|         } | ||||
|  | ||||
|         public string ExportModule(Module module) | ||||
|  | ||||
| @ -5,8 +5,9 @@ | ||||
| @inject IAliasService AliasService | ||||
| @inject ISiteService SiteService | ||||
| @inject IThemeService  ThemeService | ||||
| @inject ISiteTemplateService SiteTemplateService  | ||||
| @inject ISiteTemplateService SiteTemplateService | ||||
| @inject IUserService UserService | ||||
| @inject IInstallationService InstallationService | ||||
|  | ||||
| @if (_tenants == null) | ||||
| { | ||||
| @ -17,21 +18,7 @@ else | ||||
| <table class="table table-borderless"> | ||||
|     <tr> | ||||
|         <td> | ||||
|             <Label For="tenant" HelpText="Select the tenant for the site">Tenant: </Label> | ||||
|         </td> | ||||
|         <td> | ||||
|             <select id="tenant" class="form-control" @onchange="(e => TenantChanged(e))"> | ||||
|                 <option value="-1"><Select Tenant></option> | ||||
|                 @foreach (Tenant tenant in _tenants) | ||||
|                 { | ||||
|                     <option value="@tenant.TenantId">@tenant.Name</option> | ||||
|                 } | ||||
|             </select> | ||||
|         </td> | ||||
|     </tr> | ||||
|     <tr> | ||||
|         <td> | ||||
|             <Label For="name" HelpText="Enter the name of the site">Name: </Label> | ||||
|             <Label For="name" HelpText="Enter the name of the site">Site Name: </Label> | ||||
|         </td> | ||||
|         <td> | ||||
|             <input id="name" class="form-control" @bind="@_name" /> | ||||
| @ -101,14 +88,99 @@ else | ||||
|             </select> | ||||
|         </td> | ||||
|     </tr> | ||||
|     @if (!_isinitialized) | ||||
|     <tr> | ||||
|         <td> | ||||
|             <Label For="tenant" HelpText="Select the tenant for the site">Tenant: </Label> | ||||
|         </td> | ||||
|         <td> | ||||
|             <select id="tenant" class="form-control" @onchange="(e => TenantChanged(e))"> | ||||
|                 <option value="-"><Select Tenant></option> | ||||
|                 <option value="+"><Create New Tenant></option> | ||||
|                 @foreach (Tenant tenant in _tenants) | ||||
|                 { | ||||
|                     <option value="@tenant.TenantId">@tenant.Name</option> | ||||
|                 } | ||||
|             </select> | ||||
|         </td> | ||||
|     </tr> | ||||
|     @if (_tenantid == "+") | ||||
|     { | ||||
|         <tr> | ||||
|             <td colspan="2"> | ||||
|                 <hr class="app-rule" /> | ||||
|             </td> | ||||
|         </tr> | ||||
|         <tr> | ||||
|             <td> | ||||
|                 <Label For="name" HelpText="Enter the name for the tenant">Tenant Name: </Label> | ||||
|             </td> | ||||
|             <td> | ||||
|                 <input id="name" class="form-control" @bind="@_tenantname" /> | ||||
|             </td> | ||||
|         </tr> | ||||
|         <tr> | ||||
|             <td> | ||||
|                 <Label For="databaseType" HelpText="Select the database type for the tenant">Database Type: </Label> | ||||
|             </td> | ||||
|             <td> | ||||
|                 <select id="databaseType" class="custom-select" @bind="@_databasetype"> | ||||
|                     <option value="LocalDB">Local Database</option> | ||||
|                     <option value="SQLServer">SQL Server</option> | ||||
|                 </select> | ||||
|             </td> | ||||
|         </tr> | ||||
|         <tr> | ||||
|             <td> | ||||
|                 <Label For="server" HelpText="Enter the server for the tenant">Server: </Label> | ||||
|             </td> | ||||
|             <td> | ||||
|                 <input id="server" type="text" class="form-control" @bind="@_server" /> | ||||
|             </td> | ||||
|         </tr> | ||||
|         <tr> | ||||
|             <td> | ||||
|                 <Label For="database" HelpText="Enter the database for the tenant">Database: </Label> | ||||
|             </td> | ||||
|             <td> | ||||
|                 <input id="database" type="text" class="form-control" @bind="@_database" /> | ||||
|             </td> | ||||
|         </tr> | ||||
|         <tr> | ||||
|             <td> | ||||
|                 <Label For="integratedSecurity" HelpText="Select if you want integrated security or not">Integrated Security: </Label> | ||||
|             </td> | ||||
|             <td> | ||||
|                 <select id="integratedSecurity" class="custom-select" @onchange="SetIntegratedSecurity"> | ||||
|                     <option value="true" selected>True</option> | ||||
|                     <option value="false">False</option> | ||||
|                 </select> | ||||
|             </td> | ||||
|         </tr> | ||||
|         @if (!_integratedsecurity) | ||||
|         { | ||||
|             <tr> | ||||
|                 <td> | ||||
|                     <Label For="username" HelpText="Enter the username for the integrated security">Database Username: </Label> | ||||
|                 </td> | ||||
|                 <td> | ||||
|                     <input id="username" type="text" class="form-control" @bind="@_username" /> | ||||
|                 </td> | ||||
|             </tr> | ||||
|             <tr> | ||||
|                 <td> | ||||
|                     <Label For="password" HelpText="Enter the password for the integrated security">Database Password: </Label> | ||||
|                 </td> | ||||
|                 <td> | ||||
|                     <input id="password" type="password" class="form-control" @bind="@_password" /> | ||||
|                 </td> | ||||
|             </tr> | ||||
|         } | ||||
|         <tr> | ||||
|             <td> | ||||
|                 <Label For="hostUsername" HelpText="Enter the username of the host for this site">Host Username:</Label> | ||||
|             </td> | ||||
|             <td> | ||||
|                 <input id="hostUsername" class="form-control" @bind="@_username" readonly /> | ||||
|                 <input id="hostUsername" class="form-control" @bind="@_hostusername" readonly /> | ||||
|             </td> | ||||
|         </tr> | ||||
|         <tr> | ||||
| @ -116,7 +188,7 @@ else | ||||
|                 <Label For="hostPassword" HelpText="Enter the password for the host of this site">Host Password:</Label> | ||||
|             </td> | ||||
|             <td> | ||||
|                 <input id="hostPassword" type="password" class="form-control" @bind="@_password" /> | ||||
|                 <input id="hostPassword" type="password" class="form-control" @bind="@_hostpassword" /> | ||||
|             </td> | ||||
|         </tr> | ||||
|     } | ||||
| @ -132,16 +204,24 @@ else | ||||
|     private List<SiteTemplate> _siteTemplates; | ||||
|     private List<Theme> _themeList; | ||||
|     private List<Tenant> _tenants; | ||||
|     private string _tenantid = "-1"; | ||||
|     private string _tenantid = "-"; | ||||
|  | ||||
|     private string _tenantname = string.Empty; | ||||
|     private string _databasetype = "LocalDB"; | ||||
|     private string _server = "(LocalDb)\\MSSQLLocalDB"; | ||||
|     private string _database = "Oqtane-" + DateTime.UtcNow.ToString("yyyyMMddHHmm"); | ||||
|     private string _username = string.Empty; | ||||
|     private string _password = string.Empty; | ||||
|     private bool _integratedsecurity = true; | ||||
|     private string _hostusername = Constants.HostUser; | ||||
|     private string _hostpassword = string.Empty; | ||||
|  | ||||
|     private string _name = string.Empty; | ||||
|     private string _urls = string.Empty; | ||||
|     private string _themetype = string.Empty; | ||||
|     private string _layouttype = string.Empty; | ||||
|     private string _containertype = string.Empty; | ||||
|     private string _sitetemplatetype = string.Empty; | ||||
|     private bool _isinitialized = true; | ||||
|     private string _username = string.Empty; | ||||
|     private string _password = string.Empty; | ||||
|  | ||||
|     public override SecurityAccessLevel SecurityAccessLevel => SecurityAccessLevel.Host; | ||||
|  | ||||
| @ -153,29 +233,29 @@ else | ||||
|         _themes = ThemeService.GetThemeTypes(_themeList); | ||||
|         _containers = ThemeService.GetContainerTypes(_themeList); | ||||
|         _siteTemplates = await SiteTemplateService.GetSiteTemplatesAsync(); | ||||
|         _username = Constants.HostUser; | ||||
|     } | ||||
|  | ||||
|     private async void TenantChanged(ChangeEventArgs e) | ||||
|     private void TenantChanged(ChangeEventArgs e) | ||||
|     { | ||||
|         try | ||||
|         _tenantid = (string)e.Value; | ||||
|         if (string.IsNullOrEmpty(_tenantname)) | ||||
|         { | ||||
|             _tenantid = (string)e.Value; | ||||
|             if (_tenantid != "-1") | ||||
|             { | ||||
|                 var tenant = _tenants.FirstOrDefault(item => item.TenantId == int.Parse(_tenantid)); | ||||
|                 if (tenant != null) | ||||
|                 { | ||||
|                     _isinitialized = tenant.IsInitialized; | ||||
|                     StateHasChanged(); | ||||
|                 } | ||||
|             } | ||||
|             _tenantname = _name; | ||||
|         } | ||||
|         catch (Exception ex) | ||||
|         StateHasChanged(); | ||||
|     } | ||||
|  | ||||
|     private void SetIntegratedSecurity(ChangeEventArgs e) | ||||
|     { | ||||
|         if (Convert.ToBoolean((string)e.Value)) | ||||
|         { | ||||
|             await logger.LogError(ex, "Error Loading Tenant {TenantId} {Error}", _tenantid, ex.Message); | ||||
|             AddModuleMessage("Error Loading Tenant", MessageType.Error); | ||||
|             _integratedsecurity = true; | ||||
|         } | ||||
|         else | ||||
|         { | ||||
|             _integratedsecurity = false; | ||||
|         } | ||||
|         StateHasChanged(); | ||||
|     } | ||||
|  | ||||
|     private async void ThemeChanged(ChangeEventArgs e) | ||||
| @ -191,7 +271,7 @@ else | ||||
|             { | ||||
|                 _panelayouts = new Dictionary<string, string>(); | ||||
|             } | ||||
|              | ||||
|  | ||||
|             StateHasChanged(); | ||||
|         } | ||||
|         catch (Exception ex) | ||||
| @ -203,105 +283,116 @@ else | ||||
|  | ||||
|     private async Task SaveSite() | ||||
|     { | ||||
|         if (_tenantid != "-1" && _name != string.Empty && _urls != string.Empty && !string.IsNullOrEmpty(_themetype) && (_panelayouts.Count == 0 || !string.IsNullOrEmpty(_layouttype)) && !string.IsNullOrEmpty(_containertype) && !string.IsNullOrEmpty(_sitetemplatetype)) | ||||
|         if (_tenantid != "-" && _name != string.Empty && _urls != string.Empty && !string.IsNullOrEmpty(_themetype) && (_panelayouts.Count == 0 || !string.IsNullOrEmpty(_layouttype)) && !string.IsNullOrEmpty(_containertype) && !string.IsNullOrEmpty(_sitetemplatetype)) | ||||
|         { | ||||
|             var unique = true; | ||||
|             var duplicates = new List<string>(); | ||||
|             var aliases = await AliasService.GetAliasesAsync(); | ||||
|             foreach (string name in _urls.Split(new[] { ',' }, StringSplitOptions.RemoveEmptyEntries)) | ||||
|             { | ||||
|                 if (aliases.Exists(item => item.Name == name)) | ||||
|                 { | ||||
|                     unique = false; | ||||
|                     duplicates.Add(name); | ||||
|                 } | ||||
|             } | ||||
|              | ||||
|             if (unique) | ||||
|  | ||||
|             if (duplicates.Count == 0) | ||||
|             { | ||||
|                 var isvalid = true; | ||||
|                 InstallConfig config = new InstallConfig(); | ||||
|  | ||||
|                 if (!_isinitialized) | ||||
|                 if (_tenantid == "+") | ||||
|                 { | ||||
|                     var user = new User(); | ||||
|                     user.SiteId = PageState.Site.SiteId; | ||||
|                     user.Username = _username; | ||||
|                     user.Password = _password; | ||||
|                     user = await UserService.LoginUserAsync(user, false, false); | ||||
|                     isvalid = user.IsAuthenticated; | ||||
|                 } | ||||
|  | ||||
|                 if (isvalid) | ||||
|                 { | ||||
|                     ShowProgressIndicator(); | ||||
|  | ||||
|                     aliases = new List<Alias>(); | ||||
|                     _urls = _urls.Replace("\n", ","); | ||||
|                      | ||||
|                     foreach (string name in _urls.Split(new[] { ',' }, StringSplitOptions.RemoveEmptyEntries)) | ||||
|                     { | ||||
|                         var alias = new Alias(); | ||||
|                         alias.Name = name; | ||||
|                         alias.TenantId = int.Parse(_tenantid); | ||||
|                         alias.SiteId = -1; | ||||
|                         alias = await AliasService.AddAliasAsync(alias); | ||||
|                         aliases.Add(alias); | ||||
|                     } | ||||
|  | ||||
|                     var site = new Site(); | ||||
|                     site.TenantId = int.Parse(_tenantid); | ||||
|                     site.Name = _name; | ||||
|                     site.LogoFileId = null; | ||||
|                     site.FaviconFileId = null; | ||||
|                     site.DefaultThemeType = _themetype; | ||||
|                     site.DefaultLayoutType = (_layouttype == null ? string.Empty : _layouttype); | ||||
|                     site.DefaultContainerType = _containertype; | ||||
|                     site.PwaIsEnabled = false; | ||||
|                     site.PwaAppIconFileId = null; | ||||
|                     site.PwaSplashIconFileId = null; | ||||
|                     site.AllowRegistration = false; | ||||
|                     site.SiteTemplateType = _sitetemplatetype; | ||||
|                     site = await SiteService.AddSiteAsync(site, aliases[0]); | ||||
|  | ||||
|                     foreach (Alias alias in aliases) | ||||
|                     { | ||||
|                         alias.SiteId = site.SiteId; | ||||
|                         await AliasService.UpdateAliasAsync(alias); | ||||
|                     } | ||||
|  | ||||
|                     if (!_isinitialized) | ||||
|                     if (!string.IsNullOrEmpty(_tenantname) && _tenants.FirstOrDefault(item => item.Name == _tenantname) == null) | ||||
|                     { | ||||
|                         // validate host credentials | ||||
|                         var user = new User(); | ||||
|                         user.SiteId = site.SiteId; | ||||
|                         user.Username = _username; | ||||
|                         user.Password = _password; | ||||
|                         user.Email = PageState.User.Email; | ||||
|                         user.DisplayName = PageState.User.DisplayName; | ||||
|                         user = await UserService.AddUserAsync(user, aliases[0]); | ||||
|  | ||||
|                         if (user != null) | ||||
|                         user.SiteId = PageState.Site.SiteId; | ||||
|                         user.Username = Constants.HostUser; | ||||
|                         user.Password = _hostpassword; | ||||
|                         user = await UserService.LoginUserAsync(user, false, false); | ||||
|                         if (user.IsAuthenticated) | ||||
|                         { | ||||
|                             var tenant = _tenants.FirstOrDefault(item => item.TenantId == int.Parse(_tenantid)); | ||||
|                             if (tenant != null) | ||||
|                             if (!string.IsNullOrEmpty(_server) && !string.IsNullOrEmpty(_database)) | ||||
|                             { | ||||
|                                 tenant.IsInitialized = true; | ||||
|                                 await TenantService.UpdateTenantAsync(tenant); | ||||
|                                 var connectionString = string.Empty; | ||||
|                                 if (_databasetype == "LocalDB") | ||||
|                                 { | ||||
|                                     connectionString = "Data Source=" + _server + ";AttachDbFilename=|DataDirectory|\\" + _database + ".mdf;Initial Catalog=" + _database + ";Integrated Security=SSPI;"; | ||||
|                                 } | ||||
|                                 else | ||||
|                                 { | ||||
|                                     connectionString = "Data Source=" + _server + ";Initial Catalog=" + _database + ";"; | ||||
|  | ||||
|                                     if (_integratedsecurity) | ||||
|                                     { | ||||
|                                         connectionString += "Integrated Security=SSPI;"; | ||||
|                                     } | ||||
|                                     else | ||||
|                                     { | ||||
|                                         connectionString += "User ID=" + _username + ";Password=" + _password; | ||||
|                                     } | ||||
|                                 } | ||||
|  | ||||
|                                 config.ConnectionString = connectionString; | ||||
|                                 config.HostPassword = _hostpassword; | ||||
|                                 config.HostEmail = user.Email; | ||||
|                                 config.HostName = user.DisplayName; | ||||
|                                 config.TenantName = _tenantname; | ||||
|                                 config.IsNewTenant = true; | ||||
|                             } | ||||
|                             else | ||||
|                             { | ||||
|                                 AddModuleMessage("You Must Specify A Server And Database", MessageType.Error); | ||||
|                             } | ||||
|                         } | ||||
|                         else | ||||
|                         { | ||||
|                             AddModuleMessage("Invalid Host Password", MessageType.Error); | ||||
|                         } | ||||
|                     } | ||||
|                     else | ||||
|                     { | ||||
|                         AddModuleMessage("Tenant Name Is Missing Or Already Exists", MessageType.Error); | ||||
|                     } | ||||
|                      | ||||
|                     await Log(aliases[0], LogLevel.Information, string.Empty, null, "Site Created {Site}", site); | ||||
|  | ||||
|                     var uri = new Uri(NavigationManager.Uri); | ||||
|                     NavigationManager.NavigateTo(uri.Scheme + "://" + aliases[0].Name, true); | ||||
|                 } | ||||
|                 else | ||||
|                 { | ||||
|                     await logger.LogError("Invalid Password Entered For Host {Username}", _username); | ||||
|                     AddModuleMessage("Invalid Host Password", MessageType.Error); | ||||
|                     var tenant = _tenants.FirstOrDefault(item => item.TenantId == int.Parse(_tenantid)); | ||||
|                     if (tenant != null) | ||||
|                     { | ||||
|                         config.TenantName = tenant.Name; | ||||
|                         config.ConnectionString= tenant.DBConnectionString; | ||||
|                         config.IsNewTenant = false; | ||||
|                     } | ||||
|                 } | ||||
|  | ||||
|                 if  (!string.IsNullOrEmpty(config.TenantName)) | ||||
|                 { | ||||
|                     config.SiteName = _name; | ||||
|                     config.Aliases = _urls.Replace("\n", ","); | ||||
|                     config.DefaultTheme = _themetype; | ||||
|                     config.DefaultLayout = _layouttype; | ||||
|                     config.DefaultContainer = _containertype; | ||||
|                     config.SiteTemplate = _sitetemplatetype; | ||||
|  | ||||
|                     ShowProgressIndicator(); | ||||
|  | ||||
|                     var installation = await InstallationService.Install(config); | ||||
|                     if (installation.Success) | ||||
|                     { | ||||
|                         var aliasname = config.Aliases.Split(new char[] { ',' }, StringSplitOptions.RemoveEmptyEntries)[0]; | ||||
|                         var uri = new Uri(NavigationManager.Uri); | ||||
|                         NavigationManager.NavigateTo(uri.Scheme + "://" + aliasname, true); | ||||
|                     } | ||||
|                     else | ||||
|                     { | ||||
|                         await logger.LogError("Error Creating Site {Error}", installation.Message); | ||||
|                         AddModuleMessage(installation.Message, MessageType.Error); | ||||
|                     } | ||||
|                 } | ||||
|             } | ||||
|             else | ||||
|             { | ||||
|                 AddModuleMessage("An Alias Specified Has Already Been Used For Another Site", MessageType.Warning); | ||||
|                 AddModuleMessage(string.Join(", ", duplicates.ToArray()) + " Already Used For Another Site", MessageType.Warning); | ||||
|             } | ||||
|         } | ||||
|         else | ||||
|  | ||||
| @ -1,156 +0,0 @@ | ||||
| @namespace Oqtane.Modules.Admin.Tenants | ||||
| @inherits ModuleBase | ||||
| @inject NavigationManager NavigationManager | ||||
| @inject ITenantService TenantService | ||||
| @inject IInstallationService InstallationService | ||||
|  | ||||
|     <table class="table table-borderless"> | ||||
|         <tr> | ||||
|             <td> | ||||
|                 <Label For="name" HelpText="Enter the name for the tenant">Name: </Label> | ||||
|             </td> | ||||
|             <td> | ||||
|                 <input id="name" class="form-control" @bind="@name" /> | ||||
|             </td> | ||||
|         </tr> | ||||
|         <tr> | ||||
|             <td> | ||||
|                 <Label For="databaseType" HelpText="Select the database type for the tenant">Database Type: </Label> | ||||
|             </td> | ||||
|             <td> | ||||
|                 <select id="databaseType" class="custom-select" @bind="@type"> | ||||
|                     <option value="LocalDB">Local Database</option> | ||||
|                     <option value="SQLServer">SQL Server</option> | ||||
|                 </select> | ||||
|             </td> | ||||
|         </tr> | ||||
|         <tr> | ||||
|             <td> | ||||
|                 <Label For="server" HelpText="Enter the server for the tenant">Server: </Label> | ||||
|             </td> | ||||
|             <td> | ||||
|                 <input id="server" type="text" class="form-control" @bind="@server" /> | ||||
|             </td> | ||||
|         </tr> | ||||
|         <tr> | ||||
|             <td> | ||||
|                 <Label For="database" HelpText="Enter the database for the tenant">Database: </Label> | ||||
|             </td> | ||||
|             <td> | ||||
|                 <input id="database" type="text" class="form-control" @bind="@database" /> | ||||
|             </td> | ||||
|         </tr> | ||||
|         <tr> | ||||
|             <td> | ||||
|                 <Label For="integratedSecurity" HelpText="Select if you want integrated security or not">Integrated Security: </Label> | ||||
|             </td> | ||||
|             <td> | ||||
|                 <select id="integratedSecurity" class="custom-select" @onchange="SetIntegratedSecurity"> | ||||
|                     <option value="true" selected>True</option> | ||||
|                     <option value="false">False</option> | ||||
|                 </select> | ||||
|             </td> | ||||
|         </tr> | ||||
|         <tr style="@integratedsecurity"> | ||||
|             <td> | ||||
|                 <Label For="username" HelpText="Enter the username for the integrated security">Username: </Label> | ||||
|             </td> | ||||
|             <td> | ||||
|                 <input id="username" type="text" class="form-control" @bind="@username" /> | ||||
|             </td> | ||||
|         </tr> | ||||
|         <tr style="@integratedsecurity"> | ||||
|             <td> | ||||
|                 <Label For="password" HelpText="Enter the password for the integrated security">Password: </Label> | ||||
|             </td> | ||||
|             <td> | ||||
|                 <input id="password" type="password" class="form-control" @bind="@password" /> | ||||
|             </td> | ||||
|         </tr> | ||||
|     </table> | ||||
| <button type="button" class="btn btn-success" @onclick="SaveTenant">Save</button> | ||||
| <NavLink class="btn btn-secondary" href="@NavigateUrl()">Cancel</NavLink> | ||||
|  | ||||
| @code { | ||||
|     private string name = string.Empty; | ||||
|     private string type = "LocalDB"; | ||||
|     private string server = "(LocalDb)\\MSSQLLocalDB"; | ||||
|     private string database = "Oqtane-" + DateTime.UtcNow.ToString("yyyyMMddHHmm"); | ||||
|     private string username = string.Empty; | ||||
|     private string password = string.Empty; | ||||
|     private string schema = string.Empty; | ||||
|     private string integratedsecurity = "display: none;"; | ||||
|  | ||||
|     public override SecurityAccessLevel SecurityAccessLevel => SecurityAccessLevel.Host; | ||||
|  | ||||
|     private void SetIntegratedSecurity(ChangeEventArgs e) | ||||
|     { | ||||
|         if (Convert.ToBoolean((string)e.Value)) | ||||
|         { | ||||
|             integratedsecurity = "display: none;"; | ||||
|         } | ||||
|         else | ||||
|         { | ||||
|             integratedsecurity = string.Empty; | ||||
|         } | ||||
|     } | ||||
|  | ||||
|     private async Task SaveTenant() | ||||
|     { | ||||
|         if (!string.IsNullOrEmpty(name)) | ||||
|         { | ||||
|             ShowProgressIndicator(); | ||||
|  | ||||
|             var connectionString = string.Empty; | ||||
|             if (type == "LocalDB") | ||||
|             { | ||||
|                 connectionString = "Data Source=" + server + ";AttachDbFilename=|DataDirectory|\\" + database + ".mdf;Initial Catalog=" + database + ";Integrated Security=SSPI;"; | ||||
|             } | ||||
|             else | ||||
|             { | ||||
|                 connectionString = "Data Source=" + server + ";Initial Catalog=" + database + ";"; | ||||
|                  | ||||
|                 if (integratedsecurity == "display: none;") | ||||
|                 { | ||||
|                     connectionString += "Integrated Security=SSPI;"; | ||||
|                 } | ||||
|                 else | ||||
|                 { | ||||
|                     connectionString += "User ID=" + username + ";Password=" + password; | ||||
|  | ||||
|                 } | ||||
|             } | ||||
|  | ||||
|             var config = new InstallConfig | ||||
|             { | ||||
|                 IsMaster = false, | ||||
|                 ConnectionString = connectionString, | ||||
|             }; | ||||
|              | ||||
|             var installation = await InstallationService.Install(config); | ||||
|             if (installation.Success) | ||||
|             { | ||||
|                 //TODO : Move to Database Manager | ||||
|                 var tenant = new Tenant | ||||
|                 { | ||||
|                     Name = name, | ||||
|                     DBConnectionString = connectionString, | ||||
|                     IsInitialized = false | ||||
|                 }; | ||||
|                 await TenantService.AddTenantAsync(tenant); | ||||
|                 await logger.LogInformation("Tenant Created {Tenant}", tenant); | ||||
|  | ||||
|                 NavigationManager.NavigateTo(NavigateUrl()); | ||||
|             } | ||||
|             else | ||||
|             { | ||||
|                 await logger.LogError("Error Creating Tenant {Error}", installation.Message); | ||||
|                 AddModuleMessage(installation.Message, MessageType.Error); | ||||
|             } | ||||
|         } | ||||
|         else | ||||
|         { | ||||
|             AddModuleMessage("You Must Provide A Name For The Tenant", MessageType.Warning); | ||||
|         } | ||||
|     } | ||||
| } | ||||
| @ -6,7 +6,7 @@ | ||||
| <table class="table table-borderless"> | ||||
|     <tr> | ||||
|         <td> | ||||
|             <Label For="name" HelpText="Enter the nameof the tenant">Name: </Label> | ||||
|             <Label For="name" HelpText="The name of the tenant">Name: </Label> | ||||
|         </td> | ||||
|         <td> | ||||
|             @if (name == Constants.MasterTenant) | ||||
| @ -21,10 +21,10 @@ | ||||
|     </tr> | ||||
|     <tr> | ||||
|         <td> | ||||
|             <Label For="connectionString" HelpText="Enter the connection string for the tenant">Connection String: </Label> | ||||
|             <Label For="connectionstring" HelpText="The database connection string">Connection String: </Label> | ||||
|         </td> | ||||
|         <td> | ||||
|             <input id="integratedSecurity" class="form-control" @bind="@connectionstring" /> | ||||
|             <textarea id="connectionstring" class="form-control" @bind="@connectionstring" rows="3" readonly></textarea> | ||||
|         </td> | ||||
|     </tr> | ||||
|  | ||||
|  | ||||
| @ -1,6 +1,7 @@ | ||||
| @namespace Oqtane.Modules.Admin.Tenants | ||||
| @inherits ModuleBase | ||||
| @inject ITenantService TenantService | ||||
| @inject IAliasService AliasService | ||||
|  | ||||
| @if (tenants == null) | ||||
| { | ||||
| @ -8,8 +9,6 @@ | ||||
| } | ||||
| else | ||||
| { | ||||
|     <ActionLink Action="Add" Text="Add Tenant" /> | ||||
|  | ||||
|     <Pager Items="@tenants"> | ||||
|         <Header> | ||||
|             <th> </th> | ||||
| @ -39,9 +38,25 @@ else | ||||
|     { | ||||
|         try | ||||
|         { | ||||
|             await TenantService.DeleteTenantAsync(Tenant.TenantId); | ||||
|             await logger.LogInformation("Tenant Deleted {Tenant}", Tenant); | ||||
|             StateHasChanged(); | ||||
|             string message = string.Empty; | ||||
|             var aliases = await AliasService.GetAliasesAsync(); | ||||
|             foreach (var alias in aliases) | ||||
|             { | ||||
|                 if (alias.TenantId == Tenant.TenantId) | ||||
|                 { | ||||
|                     message += ", " + alias.Name; | ||||
|                 } | ||||
|             } | ||||
|             if (string.IsNullOrEmpty(message)) | ||||
|             { | ||||
|                 await TenantService.DeleteTenantAsync(Tenant.TenantId); | ||||
|                 await logger.LogInformation("Tenant Deleted {Tenant}", Tenant); | ||||
|                 StateHasChanged(); | ||||
|             } | ||||
|             else | ||||
|             { | ||||
|                 AddModuleMessage("Tenant Cannot Be Deleted Until The Following Sites Are Deleted: " + message.Substring(2), MessageType.Warning); | ||||
|             } | ||||
|         } | ||||
|         catch (Exception ex) | ||||
|         { | ||||
|  | ||||
		Reference in New Issue
	
	Block a user
	 Shaun Walker
					Shaun Walker