Merge pull request #6 from oqtane/master

11-14-2019 changes
This commit is contained in:
ADefWebserver 2019-11-14 05:27:19 -08:00 committed by GitHub
commit f636ffcdba
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
12 changed files with 177 additions and 19 deletions

View File

@ -139,19 +139,19 @@ else
switch (function) switch (function)
{ {
case "Create": case "Create":
classname = "table-primary"; classname = "table-success";
break; break;
case "Read": case "Read":
classname = "table-secondary"; classname = "table-primary";
break; break;
case "Update": case "Update":
classname = "table-success"; classname = "table-warning";
break; break;
case "Delete": case "Delete":
classname = "table-danger"; classname = "table-danger";
break; break;
case "Security": case "Security":
classname = "table-warning"; classname = "table-secondary";
break; break;
default: default:
classname = ""; classname = "";

View File

@ -51,7 +51,7 @@ namespace Oqtane.Services
log.Level = Enum.GetName(typeof(LogLevel), level); log.Level = Enum.GetName(typeof(LogLevel), level);
if (exception != null) if (exception != null)
{ {
log.Exception = JsonSerializer.Serialize(exception); log.Exception = exception.ToString();
} }
log.Message = message; log.Message = message;
log.MessageTemplate = ""; log.MessageTemplate = "";

View File

@ -0,0 +1,92 @@
using System;
using System.Collections.Generic;
using System.Linq;
using System.Threading;
using System.Threading.Tasks;
using Microsoft.Extensions.DependencyInjection;
using Microsoft.Extensions.Hosting;
using Oqtane.Models;
using Oqtane.Repository;
using Oqtane.Shared;
namespace Oqtane.Infrastructure
{
public abstract class HostedServiceBase : IHostedService, IDisposable
{
private Task ExecutingTask;
private readonly CancellationTokenSource CancellationTokenSource = new CancellationTokenSource();
private readonly IServiceScopeFactory ServiceScopeFactory;
public HostedServiceBase(IServiceScopeFactory ServiceScopeFactory)
{
this.ServiceScopeFactory = ServiceScopeFactory;
}
// abstract method must be overridden by job
public abstract void ExecuteJob(IServiceProvider provider);
protected async Task ExecuteAsync(CancellationToken stoppingToken)
{
try
{
while (!stoppingToken.IsCancellationRequested)
{
// allows consumption of scoped services
using (var scope = ServiceScopeFactory.CreateScope())
{
string JobType = Utilities.GetFullTypeName(this.GetType().AssemblyQualifiedName);
IScheduleRepository ScheduleRepository = scope.ServiceProvider.GetRequiredService<IScheduleRepository>();
List<Schedule> schedules = ScheduleRepository.GetSchedules().ToList();
Schedule schedule = schedules.Where(item => item.JobType == JobType).FirstOrDefault();
if (schedule != null && schedule.IsActive)
{
ExecuteJob(scope.ServiceProvider);
}
}
await Task.Delay(TimeSpan.FromMinutes(1), stoppingToken);
}
}
catch
{
// can occur during the initial installation as there is no DBContext
}
}
public Task StartAsync(CancellationToken cancellationToken)
{
ExecutingTask = ExecuteAsync(CancellationTokenSource.Token);
if (ExecutingTask.IsCompleted)
{
return ExecutingTask;
}
return Task.CompletedTask;
}
public async Task StopAsync(CancellationToken CancellationToken)
{
if (ExecutingTask == null)
{
return;
}
try
{
CancellationTokenSource.Cancel();
}
finally
{
await Task.WhenAny(ExecutingTask, Task.Delay(Timeout.Infinite, CancellationToken));
}
}
public void Dispose()
{
CancellationTokenSource.Cancel();
}
}
}

View File

@ -62,11 +62,18 @@ namespace Oqtane.Infrastructure
log.Level = Enum.GetName(typeof(LogLevel), Level); log.Level = Enum.GetName(typeof(LogLevel), Level);
if (Exception != null) if (Exception != null)
{ {
log.Exception = JsonSerializer.Serialize(Exception.ToString()); log.Exception = Exception.ToString();
} }
log.Message = Message; log.Message = Message;
log.MessageTemplate = ""; log.MessageTemplate = "";
log.Properties = JsonSerializer.Serialize(Args); try
{
log.Properties = JsonSerializer.Serialize(Args);
}
catch // serialization error occurred
{
log.Properties = "";
}
Log(log); Log(log);
} }

View File

@ -0,0 +1,21 @@
using System;
using Microsoft.Extensions.DependencyInjection;
using Oqtane.Models;
using Oqtane.Repository;
namespace Oqtane.Infrastructure
{
public class TestJob : HostedServiceBase
{
public TestJob(IServiceScopeFactory ServiceScopeFactory) : base(ServiceScopeFactory) {}
public override void ExecuteJob(IServiceProvider provider)
{
var Tenants = provider.GetRequiredService<ITenantRepository>();
foreach(Tenant tenant in Tenants.GetTenants())
{
// is it possible to set the HttpContext so that DbContextBase will resolve properly for tenants?
}
}
}
}

View File

@ -44,6 +44,10 @@ namespace Oqtane.Repository
moduledef = new ModuleDefinition { ModuleDefinitionName = moduledefinition.ModuleDefinitionName }; moduledef = new ModuleDefinition { ModuleDefinitionName = moduledefinition.ModuleDefinitionName };
db.ModuleDefinition.Add(moduledef); db.ModuleDefinition.Add(moduledef);
db.SaveChanges(); db.SaveChanges();
if (moduledefinition.Permissions != "")
{
Permissions.UpdatePermissions(SiteId, "ModuleDefinition", moduledef.ModuleDefinitionId, moduledefinition.Permissions);
}
} }
else else
{ {
@ -123,7 +127,8 @@ namespace Oqtane.Repository
ServerAssemblyName = GetProperty(properties, "ServerAssemblyName"), ServerAssemblyName = GetProperty(properties, "ServerAssemblyName"),
ControlTypeTemplate = ModuleType + "." + Constants.ActionToken + ", " + typename[1], ControlTypeTemplate = ModuleType + "." + Constants.ActionToken + ", " + typename[1],
ControlTypeRoutes = "", ControlTypeRoutes = "",
AssemblyName = assembly.FullName.Split(",")[0] AssemblyName = assembly.FullName.Split(",")[0],
Permissions = ""
}; };
} }
else else
@ -144,7 +149,8 @@ namespace Oqtane.Repository
ServerAssemblyName = "", ServerAssemblyName = "",
ControlTypeTemplate = ModuleType + "." + Constants.ActionToken + ", " + typename[1], ControlTypeTemplate = ModuleType + "." + Constants.ActionToken + ", " + typename[1],
ControlTypeRoutes = "", ControlTypeRoutes = "",
AssemblyName = assembly.FullName.Split(",")[0] AssemblyName = assembly.FullName.Split(",")[0],
Permissions = ((QualifiedModuleType.StartsWith("Oqtane.Modules.Admin.")) ? "[{\"PermissionName\":\"Utilize\",\"Permissions\":\"Administrators\"}]" : "")
}; };
} }
moduledefinitions.Add(moduledefinition); moduledefinitions.Add(moduledefinition);

View File

@ -52,12 +52,14 @@ GO
CREATE TABLE [dbo].[Schedule] ( CREATE TABLE [dbo].[Schedule] (
[ScheduleId] [int] IDENTITY(1,1) NOT NULL, [ScheduleId] [int] IDENTITY(1,1) NOT NULL,
[Name] [nvarchar](200) NULL, [Name] [nvarchar](200) NOT NULL,
[JobType] [nvarchar](200) NOT NULL, [JobType] [nvarchar](200) NOT NULL,
[Period] [int] NOT NULL, [Period] [int] NOT NULL,
[Frequency] [char](1) NOT NULL, [Frequency] [char](1) NOT NULL,
[StartDate] [datetime] NULL, [StartDate] [datetime] NULL,
[IsActive] [bit] NOT NULL, [IsActive] [bit] NOT NULL,
[IsExecuting] [bit] NOT NULL,
[NextExecution] [datetime] NULL,
[RetentionHistory] [int] NOT NULL, [RetentionHistory] [int] NOT NULL,
[CreatedBy] [nvarchar](256) NULL, [CreatedBy] [nvarchar](256) NULL,
[CreatedOn] [datetime] NULL, [CreatedOn] [datetime] NULL,
@ -77,7 +79,6 @@ CREATE TABLE [dbo].[ScheduleLog] (
[FinishDate] [datetime] NULL, [FinishDate] [datetime] NULL,
[Succeeded] [bit] NULL, [Succeeded] [bit] NULL,
[Notes] [nvarchar](max) NULL, [Notes] [nvarchar](max) NULL,
[NextExecution] [datetime] NULL,
CONSTRAINT [PK_ScheduleLog] PRIMARY KEY CLUSTERED CONSTRAINT [PK_ScheduleLog] PRIMARY KEY CLUSTERED
( (
[ScheduleLogId] ASC [ScheduleLogId] ASC

View File

@ -38,10 +38,17 @@ namespace Oqtane.Security
foreach (UserRole userrole in userroles) foreach (UserRole userrole in userroles)
{ {
id.AddClaim(new Claim(options.ClaimsIdentity.RoleClaimType, userrole.Role.Name)); id.AddClaim(new Claim(options.ClaimsIdentity.RoleClaimType, userrole.Role.Name));
// host users are admins of every site // host users are members of every site
if (userrole.Role.Name == Constants.HostRole && userroles.Where(item => item.Role.Name == Constants.AdminRole).FirstOrDefault() == null) if (userrole.Role.Name == Constants.HostRole)
{ {
id.AddClaim(new Claim(options.ClaimsIdentity.RoleClaimType, Constants.AdminRole)); if (userroles.Where(item => item.Role.Name == Constants.RegisteredRole).FirstOrDefault() == null)
{
id.AddClaim(new Claim(options.ClaimsIdentity.RoleClaimType, Constants.RegisteredRole));
}
if (userroles.Where(item => item.Role.Name == Constants.AdminRole).FirstOrDefault() == null)
{
id.AddClaim(new Claim(options.ClaimsIdentity.RoleClaimType, Constants.AdminRole));
}
} }
} }
} }

View File

@ -154,10 +154,6 @@ namespace Oqtane.Server
services.AddSingleton<IConfigurationRoot>(Configuration); services.AddSingleton<IConfigurationRoot>(Configuration);
services.AddSingleton<IInstallationManager, InstallationManager>(); services.AddSingleton<IInstallationManager, InstallationManager>();
//ServiceProvider sp = services.BuildServiceProvider();
//var InstallationManager = sp.GetRequiredService<IInstallationManager>();
//InstallationManager.InstallPackages("Modules,Themes");
// register transient scoped core services // register transient scoped core services
services.AddTransient<IModuleDefinitionRepository, ModuleDefinitionRepository>(); services.AddTransient<IModuleDefinitionRepository, ModuleDefinitionRepository>();
services.AddTransient<IThemeRepository, ThemeRepository>(); services.AddTransient<IThemeRepository, ThemeRepository>();
@ -235,6 +231,21 @@ namespace Oqtane.Server
} }
} }
// dynamically register hosted services
foreach (Assembly assembly in assemblies)
{
Type[] servicetypes = assembly.GetTypes()
.Where(item => item.GetInterfaces().Contains(typeof(IHostedService)))
.ToArray();
foreach (Type servicetype in servicetypes)
{
if (servicetype.Name != "HostedServiceBase")
{
services.AddSingleton(typeof(IHostedService), servicetype);
}
}
}
services.AddSwaggerGen(c => services.AddSwaggerGen(c =>
{ {
c.SwaggerDoc("v1", new OpenApiInfo { Title = "Oqtane", Version = "v1" }); c.SwaggerDoc("v1", new OpenApiInfo { Title = "Oqtane", Version = "v1" });

View File

@ -11,6 +11,8 @@ namespace Oqtane.Models
public string Frequency { get; set; } public string Frequency { get; set; }
public DateTime? StartDate { get; set; } public DateTime? StartDate { get; set; }
public bool IsActive { get; set; } public bool IsActive { get; set; }
public bool IsExecuting { get; set; }
public DateTime? NextExecution { get; set; }
public int RetentionHistory { get; set; } public int RetentionHistory { get; set; }
public string CreatedBy { get; set; } public string CreatedBy { get; set; }

View File

@ -10,6 +10,5 @@ namespace Oqtane.Models
public DateTime? FinishDate { get; set; } public DateTime? FinishDate { get; set; }
public bool? Succeeded { get; set; } public bool? Succeeded { get; set; }
public string Notes { get; set; } public string Notes { get; set; }
public DateTime? NextExecution { get; set; }
} }
} }

View File

@ -70,6 +70,18 @@ namespace Oqtane.Shared
} }
} }
public static string GetFullTypeName(string fullyqualifiedtypename)
{
if (fullyqualifiedtypename.Contains(", Version="))
{
return fullyqualifiedtypename.Substring(0, fullyqualifiedtypename.IndexOf(", Version="));
}
else
{
return fullyqualifiedtypename;
}
}
public static string GetTypeNameLastSegment(string typename, int segment) public static string GetTypeNameLastSegment(string typename, int segment)
{ {
if (typename.Contains(",")) if (typename.Contains(","))