SQL maanager, Module Creator, module settings enhancements
This commit is contained in:
@ -11,6 +11,7 @@ using Oqtane.Enums;
|
||||
using Oqtane.Infrastructure.Interfaces;
|
||||
using Oqtane.Repository;
|
||||
using Oqtane.Security;
|
||||
using System;
|
||||
// ReSharper disable StringIndexOfIsCultureSpecific.1
|
||||
|
||||
namespace Oqtane.Controllers
|
||||
@ -19,17 +20,23 @@ namespace Oqtane.Controllers
|
||||
public class ModuleDefinitionController : Controller
|
||||
{
|
||||
private readonly IModuleDefinitionRepository _moduleDefinitions;
|
||||
private readonly IModuleRepository _modules;
|
||||
private readonly IUserPermissions _userPermissions;
|
||||
private readonly IInstallationManager _installationManager;
|
||||
private readonly IWebHostEnvironment _environment;
|
||||
private readonly ITenantResolver _resolver;
|
||||
private readonly ISqlRepository _sql;
|
||||
private readonly ILogManager _logger;
|
||||
|
||||
public ModuleDefinitionController(IModuleDefinitionRepository moduleDefinitions, IUserPermissions userPermissions, IInstallationManager installationManager, IWebHostEnvironment environment, ILogManager logger)
|
||||
public ModuleDefinitionController(IModuleDefinitionRepository moduleDefinitions, IModuleRepository modules, IUserPermissions userPermissions, IInstallationManager installationManager, IWebHostEnvironment environment, ITenantResolver resolver, ISqlRepository sql, ILogManager logger)
|
||||
{
|
||||
_moduleDefinitions = moduleDefinitions;
|
||||
_modules = modules;
|
||||
_userPermissions = userPermissions;
|
||||
_installationManager = installationManager;
|
||||
_environment = environment;
|
||||
_resolver = resolver;
|
||||
_sql = sql;
|
||||
_logger = logger;
|
||||
}
|
||||
|
||||
@ -124,5 +131,69 @@ namespace Oqtane.Controllers
|
||||
return File(file, "application/octet-stream", assemblyname);
|
||||
}
|
||||
|
||||
// POST api/<controller>?moduleid=x
|
||||
[HttpPost]
|
||||
[Authorize(Roles = Constants.HostRole)]
|
||||
public void Post([FromBody] ModuleDefinition moduleDefinition, string moduleid)
|
||||
{
|
||||
if (ModelState.IsValid)
|
||||
{
|
||||
string rootPath = Directory.GetParent(_environment.ContentRootPath).FullName;
|
||||
string templatePath = Path.Combine(rootPath, "Oqtane.Client\\Modules\\Admin\\ModuleCreator\\Templates\\");
|
||||
ProcessTemplatesRecursively(new DirectoryInfo(templatePath), rootPath, moduleDefinition);
|
||||
moduleDefinition.ModuleDefinitionName = "Oqtane.Modules." + moduleDefinition.Name + "s, Oqtane.Client";
|
||||
_logger.Log(LogLevel.Information, this, LogFunction.Create, "Module Definition Created {ModuleDefinition}", moduleDefinition);
|
||||
Models.Module module = _modules.GetModule(int.Parse(moduleid));
|
||||
module.ModuleDefinitionName = moduleDefinition.ModuleDefinitionName;
|
||||
_modules.UpdateModule(module);
|
||||
_installationManager.RestartApplication();
|
||||
}
|
||||
}
|
||||
|
||||
private void ProcessTemplatesRecursively(DirectoryInfo current, string rootPath, ModuleDefinition moduleDefinition)
|
||||
{
|
||||
// process folder
|
||||
string folderPath = current.FullName.Replace("Oqtane.Client\\Modules\\Admin\\ModuleCreator\\Templates\\", "");
|
||||
folderPath = folderPath.Replace("[Module]", moduleDefinition.Name);
|
||||
if (!Directory.Exists(folderPath))
|
||||
{
|
||||
Directory.CreateDirectory(folderPath);
|
||||
}
|
||||
|
||||
FileInfo[] files = current.GetFiles("*.*");
|
||||
if (files != null)
|
||||
{
|
||||
foreach (FileInfo file in files)
|
||||
{
|
||||
// process file
|
||||
string filePath = Path.Combine(folderPath, file.Name);
|
||||
filePath = filePath.Replace("[Module]", moduleDefinition.Name);
|
||||
|
||||
string text = System.IO.File.ReadAllText(file.FullName);
|
||||
text = text.Replace("[Module]", moduleDefinition.Name);
|
||||
text = text.Replace("[Description]", moduleDefinition.Description);
|
||||
text = text.Replace("[RootPath]", rootPath);
|
||||
text = text.Replace("[Folder]", folderPath);
|
||||
text = text.Replace("[File]", Path.GetFileName(filePath));
|
||||
System.IO.File.WriteAllText(filePath, text);
|
||||
|
||||
if (Path.GetExtension(filePath) == ".sql")
|
||||
{
|
||||
// execute script
|
||||
foreach (string query in text.Split("GO", StringSplitOptions.RemoveEmptyEntries))
|
||||
{
|
||||
_sql.ExecuteNonQuery(_resolver.GetTenant(), query);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
DirectoryInfo[] folders = current.GetDirectories();
|
||||
|
||||
foreach (DirectoryInfo folder in folders.Reverse())
|
||||
{
|
||||
ProcessTemplatesRecursively(folder, rootPath, moduleDefinition);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
65
Oqtane.Server/Controllers/SqlController.cs
Normal file
65
Oqtane.Server/Controllers/SqlController.cs
Normal file
@ -0,0 +1,65 @@
|
||||
using Microsoft.AspNetCore.Mvc;
|
||||
using Microsoft.AspNetCore.Authorization;
|
||||
using Oqtane.Models;
|
||||
using System.Collections.Generic;
|
||||
using Oqtane.Shared;
|
||||
using Oqtane.Infrastructure.Interfaces;
|
||||
using Oqtane.Repository;
|
||||
using Oqtane.Enums;
|
||||
using System.Data.SqlClient;
|
||||
using System.Data;
|
||||
using System.Dynamic;
|
||||
using Newtonsoft.Json;
|
||||
using System;
|
||||
|
||||
namespace Oqtane.Controllers
|
||||
{
|
||||
[Route("{site}/api/[controller]")]
|
||||
public class SqlController : Controller
|
||||
{
|
||||
private readonly ITenantRepository _tenants;
|
||||
private readonly ISqlRepository _sql;
|
||||
private readonly ILogManager _logger;
|
||||
|
||||
public SqlController(ITenantRepository tenants, ISqlRepository sql, ILogManager logger)
|
||||
{
|
||||
_tenants = tenants;
|
||||
_sql = sql;
|
||||
_logger = logger;
|
||||
}
|
||||
|
||||
// POST: api/<controller>
|
||||
[HttpPost]
|
||||
[Authorize(Roles = Constants.HostRole)]
|
||||
public SqlQuery Post([FromBody] SqlQuery sqlquery)
|
||||
{
|
||||
var results = new List<Dictionary<string, string>>();
|
||||
Dictionary<string, string> row;
|
||||
Tenant tenant = _tenants.GetTenant(sqlquery.TenantId);
|
||||
try
|
||||
{
|
||||
foreach (string query in sqlquery.Query.Split("GO", StringSplitOptions.RemoveEmptyEntries))
|
||||
{
|
||||
SqlDataReader dr = _sql.ExecuteReader(tenant, query);
|
||||
_logger.Log(LogLevel.Information, this, LogFunction.Other, "Sql Query {Query} Executed on Tenant {TenantId}", query, sqlquery.TenantId);
|
||||
while (dr.Read())
|
||||
{
|
||||
row = new Dictionary<string, string>();
|
||||
for (var field = 0; field < dr.FieldCount; field++)
|
||||
{
|
||||
row[dr.GetName(field)] = dr.IsDBNull(field) ? "" : dr.GetValue(field).ToString();
|
||||
}
|
||||
results.Add(row);
|
||||
}
|
||||
}
|
||||
}
|
||||
catch (Exception ex)
|
||||
{
|
||||
_logger.Log(LogLevel.Error, this, LogFunction.Other, "Sql Query {Query} Executed on Tenant {TenantId} Results In An Error {Error}", sqlquery.Query, sqlquery.TenantId, ex.Message);
|
||||
}
|
||||
sqlquery.Results = results;
|
||||
return sqlquery;
|
||||
}
|
||||
|
||||
}
|
||||
}
|
11
Oqtane.Server/Repository/Interfaces/ISqlRepository.cs
Normal file
11
Oqtane.Server/Repository/Interfaces/ISqlRepository.cs
Normal file
@ -0,0 +1,11 @@
|
||||
using System.Data.SqlClient;
|
||||
using Oqtane.Models;
|
||||
|
||||
namespace Oqtane.Repository
|
||||
{
|
||||
public interface ISqlRepository
|
||||
{
|
||||
int ExecuteNonQuery(Tenant tenant, string query);
|
||||
SqlDataReader ExecuteReader(Tenant tenant, string query);
|
||||
}
|
||||
}
|
@ -361,6 +361,34 @@ namespace Oqtane.Repository
|
||||
}
|
||||
});
|
||||
pageTemplates.Add(new PageTemplate
|
||||
{
|
||||
Name = "Sql Management",
|
||||
Parent = "Admin",
|
||||
Path = "admin/sql",
|
||||
Icon = "spreadsheet",
|
||||
IsNavigation = false,
|
||||
IsPersonalizable = false,
|
||||
EditMode = true,
|
||||
PagePermissions = _permissionRepository.EncodePermissions(new List<Permission>
|
||||
{
|
||||
new Permission(PermissionNames.View, Constants.AdminRole, true),
|
||||
new Permission(PermissionNames.Edit, Constants.AdminRole, true)
|
||||
}),
|
||||
PageTemplateModules = new List<PageTemplateModule>
|
||||
{
|
||||
new PageTemplateModule
|
||||
{
|
||||
ModuleDefinitionName = "Oqtane.Modules.Admin.Sql, Oqtane.Client", Title = "Sql Management", Pane = "Content",
|
||||
ModulePermissions = _permissionRepository.EncodePermissions(new List<Permission>
|
||||
{
|
||||
new Permission(PermissionNames.View, Constants.AdminRole, true),
|
||||
new Permission(PermissionNames.Edit, Constants.AdminRole, true)
|
||||
}),
|
||||
Content = ""
|
||||
}
|
||||
}
|
||||
});
|
||||
pageTemplates.Add(new PageTemplate
|
||||
{
|
||||
Name = "Upgrade Service", Parent = "Admin", Path = "admin/upgrade", Icon = "aperture", IsNavigation = false, IsPersonalizable = false, EditMode = true,
|
||||
PagePermissions = _permissionRepository.EncodePermissions(new List<Permission>
|
||||
|
48
Oqtane.Server/Repository/SqlRepository.cs
Normal file
48
Oqtane.Server/Repository/SqlRepository.cs
Normal file
@ -0,0 +1,48 @@
|
||||
using System;
|
||||
using System.Data;
|
||||
using System.Data.SqlClient;
|
||||
using Oqtane.Models;
|
||||
|
||||
namespace Oqtane.Repository
|
||||
{
|
||||
public class SqlRepository : ISqlRepository
|
||||
{
|
||||
|
||||
public int ExecuteNonQuery(Tenant tenant, string query)
|
||||
{
|
||||
SqlConnection conn = new SqlConnection(FormatConnectionString(tenant.DBConnectionString));
|
||||
SqlCommand cmd = conn.CreateCommand();
|
||||
using (conn)
|
||||
{
|
||||
PrepareCommand(conn, cmd, query);
|
||||
int val = cmd.ExecuteNonQuery();
|
||||
return val;
|
||||
}
|
||||
}
|
||||
|
||||
public SqlDataReader ExecuteReader(Tenant tenant, string query)
|
||||
{
|
||||
SqlConnection conn = new SqlConnection(FormatConnectionString(tenant.DBConnectionString));
|
||||
SqlCommand cmd = conn.CreateCommand();
|
||||
PrepareCommand(conn, cmd, query);
|
||||
var dr = cmd.ExecuteReader(CommandBehavior.CloseConnection);
|
||||
return dr;
|
||||
}
|
||||
|
||||
private void PrepareCommand(SqlConnection conn, SqlCommand cmd, string query)
|
||||
{
|
||||
if (conn.State != ConnectionState.Open)
|
||||
{
|
||||
conn.Open();
|
||||
}
|
||||
cmd.Connection = conn;
|
||||
cmd.CommandText = query;
|
||||
cmd.CommandType = CommandType.Text;
|
||||
}
|
||||
|
||||
private string FormatConnectionString(string connectionString)
|
||||
{
|
||||
return connectionString.Replace("|DataDirectory|", AppDomain.CurrentDomain.GetData("DataDirectory").ToString());
|
||||
}
|
||||
}
|
||||
}
|
@ -107,6 +107,7 @@ namespace Oqtane
|
||||
services.AddScoped<IFolderService, FolderService>();
|
||||
services.AddScoped<IFileService, FileService>();
|
||||
services.AddScoped<ISiteTemplateService, SiteTemplateService>();
|
||||
services.AddScoped<ISqlService, SqlService>();
|
||||
|
||||
services.AddSingleton<IHttpContextAccessor, HttpContextAccessor>();
|
||||
|
||||
@ -185,6 +186,7 @@ namespace Oqtane
|
||||
services.AddTransient<IFolderRepository, FolderRepository>();
|
||||
services.AddTransient<IFileRepository, FileRepository>();
|
||||
services.AddTransient<ISiteTemplateRepository, SiteTemplateRepository>();
|
||||
services.AddTransient<ISqlRepository, SqlRepository>();
|
||||
|
||||
services.AddOqtaneModules();
|
||||
services.AddOqtaneThemes();
|
||||
@ -338,6 +340,7 @@ namespace Oqtane
|
||||
services.AddTransient<IFolderRepository, FolderRepository>();
|
||||
services.AddTransient<IFileRepository, FileRepository>();
|
||||
services.AddTransient<ISiteTemplateRepository, SiteTemplateRepository>();
|
||||
services.AddTransient<ISqlRepository, SqlRepository>();
|
||||
|
||||
services.AddOqtaneModules();
|
||||
services.AddOqtaneThemes();
|
||||
|
Reference in New Issue
Block a user