Browse Source

Optional services and improved plugin loading.

pull/349/head
Sebastian Stehle 7 years ago
parent
commit
4b80525d92
  1. 3
      extensions/Squidex.Extensions/Actions/Twitter/TwitterPlugin.cs
  2. 16
      extensions/Squidex.Extensions/SquidexExtensions.cs
  3. 8
      src/Squidex.Infrastructure/Log/SemanticLogExtensions.cs
  4. 2
      src/Squidex.Infrastructure/Plugins/IWebPlugin.cs
  5. 67
      src/Squidex.Infrastructure/Plugins/PluginManager.cs
  6. 69
      src/Squidex/Areas/Api/Controllers/Rules/TwitterController.cs
  7. 7
      src/Squidex/Areas/Api/Controllers/UI/UIController.cs
  8. 8
      src/Squidex/Config/Domain/AssetServices.cs
  9. 2
      src/Squidex/Config/Domain/EntitiesServices.cs
  10. 4
      src/Squidex/Config/Domain/EventStoreServices.cs
  11. 4
      src/Squidex/Config/Domain/InfrastructureServices.cs
  12. 2
      src/Squidex/Config/Domain/LoggingServices.cs
  13. 24
      src/Squidex/Config/Domain/StoreServices.cs
  14. 6
      src/Squidex/Config/Domain/SubscriptionServices.cs
  15. 84
      src/Squidex/Pipeline/Plugins/PluginExtensions.cs
  16. 3
      src/Squidex/Squidex.csproj
  17. 5
      src/Squidex/WebStartup.cs
  18. 20
      src/Squidex/appsettings.json

3
extensions/Squidex.Extensions/Actions/Twitter/TwitterPlugin.cs

@ -16,6 +16,9 @@ namespace Squidex.Extensions.Actions.Twitter
{ {
public void ConfigureServices(IServiceCollection services, IConfiguration configuration) public void ConfigureServices(IServiceCollection services, IConfiguration configuration)
{ {
services.Configure<TwitterOptions>(
configuration.GetSection("twitter"));
RuleActionRegistry.Add<TweetAction>(); RuleActionRegistry.Add<TweetAction>();
} }
} }

16
extensions/Squidex.Extensions/SquidexExtensions.cs

@ -1,16 +0,0 @@
// ==========================================================================
// Squidex Headless CMS
// ==========================================================================
// Copyright (c) Squidex UG (haftungsbeschraenkt)
// All rights reserved. Licensed under the MIT license.
// ==========================================================================
using System.Reflection;
namespace Squidex.Extensions
{
public static class SquidexExtensions
{
public static readonly Assembly Assembly = typeof(SquidexExtensions).Assembly;
}
}

8
src/Squidex.Infrastructure/Log/SemanticLogExtensions.cs

@ -126,8 +126,16 @@ namespace Squidex.Infrastructure.Log
return writer.WriteObject(nameof(exception), exception, (ctx, w) => return writer.WriteObject(nameof(exception), exception, (ctx, w) =>
{ {
w.WriteProperty("type", ctx.GetType().FullName); w.WriteProperty("type", ctx.GetType().FullName);
if (ctx.Message != null)
{
w.WriteProperty("message", ctx.Message); w.WriteProperty("message", ctx.Message);
}
if (ctx.StackTrace != null)
{
w.WriteProperty("stackTrace", ctx.StackTrace); w.WriteProperty("stackTrace", ctx.StackTrace);
}
}); });
} }

2
src/Squidex.Infrastructure/Plugins/IWebPlugin.cs

@ -9,7 +9,7 @@ using Microsoft.AspNetCore.Builder;
namespace Squidex.Infrastructure.Plugins namespace Squidex.Infrastructure.Plugins
{ {
public interface IWebPlugin public interface IWebPlugin : I
{ {
void Configure(IApplicationBuilder app); void Configure(IApplicationBuilder app);
} }

67
src/Squidex.Infrastructure/Plugins/PluginManager.cs

@ -12,35 +12,59 @@ using System.Reflection;
using Microsoft.AspNetCore.Builder; using Microsoft.AspNetCore.Builder;
using Microsoft.Extensions.Configuration; using Microsoft.Extensions.Configuration;
using Microsoft.Extensions.DependencyInjection; using Microsoft.Extensions.DependencyInjection;
using Squidex.Infrastructure.Log;
namespace Squidex.Infrastructure.Plugins namespace Squidex.Infrastructure.Plugins
{ {
public sealed class PluginManager public sealed class PluginManager
{ {
private readonly HashSet<IPlugin> plugins = new HashSet<IPlugin>(); private readonly HashSet<IPlugin> loadedPlugins = new HashSet<IPlugin>();
private readonly List<(string Plugin, string Action, Exception Exception)> exceptions = new List<(string, string, Exception)>();
public void Add(Assembly assembly) public IReadOnlyCollection<IPlugin> Plugins
{
get { return loadedPlugins; }
}
public void Add(string name, Assembly assembly)
{ {
Guard.NotNull(assembly, nameof(assembly)); Guard.NotNull(assembly, nameof(assembly));
var pluginTypes = var pluginTypes =
assembly.GetTypes() assembly.GetTypes()
.Where(t => typeof(IPlugin).IsAssignableFrom(t) && !t.IsAbstract); .Where(t => typeof(IPlugin).IsAssignableFrom(t))
.Where(t => !t.IsAbstract);
foreach (var pluginType in pluginTypes) foreach (var pluginType in pluginTypes)
{
try
{ {
var plugin = (IPlugin)Activator.CreateInstance(pluginType); var plugin = (IPlugin)Activator.CreateInstance(pluginType);
plugins.Add(plugin); loadedPlugins.Add(plugin);
}
catch (Exception ex)
{
LogException(name, "Instantiating", ex);
} }
} }
}
public void LogException(string plugin, string action, Exception exception)
{
Guard.NotNull(plugin, nameof(plugin));
Guard.NotNull(action, nameof(action));
Guard.NotNull(exception, nameof(exception));
exceptions.Add((plugin, action, exception));
}
public void ConfigureServices(IServiceCollection services, IConfiguration configuration) public void ConfigureServices(IServiceCollection services, IConfiguration configuration)
{ {
Guard.NotNull(services, nameof(services)); Guard.NotNull(services, nameof(services));
Guard.NotNull(configuration, nameof(configuration)); Guard.NotNull(configuration, nameof(configuration));
foreach (var plugin in plugins) foreach (var plugin in loadedPlugins)
{ {
plugin.ConfigureServices(services, configuration); plugin.ConfigureServices(services, configuration);
} }
@ -50,10 +74,41 @@ namespace Squidex.Infrastructure.Plugins
{ {
Guard.NotNull(app, nameof(app)); Guard.NotNull(app, nameof(app));
foreach (var plugin in plugins.OfType<IWebPlugin>()) foreach (var plugin in loadedPlugins.OfType<IWebPlugin>())
{ {
plugin.Configure(app); plugin.Configure(app);
} }
} }
public void Log(ISemanticLog log)
{
Guard.NotNull(log, nameof(log));
if (loadedPlugins.Count > 0 || exceptions.Count > 0)
{
var status = exceptions.Count > 0 ? "CompletedWithErrors" : "Completed";
log.LogInformation(w => w
.WriteProperty("action", "pluginsLoaded")
.WriteProperty("status", status)
.WriteArray("errors", e =>
{
foreach (var error in exceptions)
{
e.WriteObject(x => x
.WriteProperty("plugin", error.Plugin)
.WriteProperty("action", error.Action)
.WriteException(error.Exception));
}
})
.WriteArray("plugins", a =>
{
foreach (var plugin in loadedPlugins)
{
a.WriteValue(plugin.GetType().ToString());
}
}));
}
}
} }
} }

69
src/Squidex/Areas/Api/Controllers/Rules/TwitterController.cs

@ -1,69 +0,0 @@
// ==========================================================================
// Squidex Headless CMS
// ==========================================================================
// Copyright (c) Squidex UG (haftungsbeschraenkt)
// All rights reserved. Licensed under the MIT license.
// ==========================================================================
using System.Threading.Tasks;
using CoreTweet;
using Microsoft.AspNetCore.Mvc;
using Microsoft.Extensions.Options;
using Squidex.Extensions.Actions.Twitter;
namespace Squidex.Areas.Api.Controllers.Rules
{
public sealed class TwitterController : Controller
{
private readonly TwitterOptions twitterOptions;
public TwitterController(IOptions<TwitterOptions> twitterOptions)
{
this.twitterOptions = twitterOptions.Value;
}
public sealed class TokenRequest
{
public string PinCode { get; set; }
public string RequestToken { get; set; }
public string RequestTokenSecret { get; set; }
}
[HttpGet]
[Route("rules/twitter/auth")]
public async Task<IActionResult> Auth()
{
var session = await OAuth.AuthorizeAsync(twitterOptions.ClientId, twitterOptions.ClientSecret);
return Ok(new
{
session.AuthorizeUri,
session.RequestToken,
session.RequestTokenSecret
});
}
[HttpPost]
[Route("rules/twitter/token")]
public async Task<IActionResult> AuthComplete([FromBody] TokenRequest request)
{
var session = new OAuth.OAuthSession
{
ConsumerKey = twitterOptions.ClientId,
ConsumerSecret = twitterOptions.ClientSecret,
RequestToken = request.RequestToken,
RequestTokenSecret = request.RequestTokenSecret
};
var tokens = await session.GetTokensAsync(request.PinCode);
return Ok(new
{
tokens.AccessToken,
tokens.AccessTokenSecret
});
}
}
}

7
src/Squidex/Areas/Api/Controllers/UI/UIController.cs

@ -12,7 +12,6 @@ using Orleans;
using Squidex.Areas.Api.Controllers.UI.Models; using Squidex.Areas.Api.Controllers.UI.Models;
using Squidex.Config; using Squidex.Config;
using Squidex.Domain.Apps.Entities.Apps; using Squidex.Domain.Apps.Entities.Apps;
using Squidex.Extensions.Actions.Twitter;
using Squidex.Infrastructure.Commands; using Squidex.Infrastructure.Commands;
using Squidex.Infrastructure.Orleans; using Squidex.Infrastructure.Orleans;
using Squidex.Pipeline; using Squidex.Pipeline;
@ -22,18 +21,16 @@ namespace Squidex.Areas.Api.Controllers.UI
public sealed class UIController : ApiController public sealed class UIController : ApiController
{ {
private readonly MyUIOptions uiOptions; private readonly MyUIOptions uiOptions;
private readonly TwitterOptions twitterOptions;
private readonly IGrainFactory grainFactory; private readonly IGrainFactory grainFactory;
public UIController(ICommandBus commandBus, public UIController(ICommandBus commandBus,
IOptions<MyUIOptions> uiOptions, IOptions<MyUIOptions> uiOptions,
IOptions<TwitterOptions> twitterOptions,
IGrainFactory grainFactory) IGrainFactory grainFactory)
: base(commandBus) : base(commandBus)
{ {
this.uiOptions = uiOptions.Value; this.uiOptions = uiOptions.Value;
this.grainFactory = grainFactory; this.grainFactory = grainFactory;
this.twitterOptions = twitterOptions.Value;
} }
/// <summary> /// <summary>
@ -55,8 +52,6 @@ namespace Squidex.Areas.Api.Controllers.UI
result.Value.Add("mapType", uiOptions.Map?.Type ?? "OSM"); result.Value.Add("mapType", uiOptions.Map?.Type ?? "OSM");
result.Value.Add("mapKey", uiOptions.Map?.GoogleMaps?.Key); result.Value.Add("mapKey", uiOptions.Map?.GoogleMaps?.Key);
result.Value.Add("supportTwitterAction", twitterOptions.IsConfigured());
return Ok(result.Value); return Ok(result.Value);
} }

8
src/Squidex/Config/Domain/AssetServices.cs

@ -29,14 +29,14 @@ namespace Squidex.Config.Domain
var path = config.GetRequiredValue("assetStore:folder:path"); var path = config.GetRequiredValue("assetStore:folder:path");
services.AddSingletonAs(c => new FolderAssetStore(path, c.GetRequiredService<ISemanticLog>())) services.AddSingletonAs(c => new FolderAssetStore(path, c.GetRequiredService<ISemanticLog>()))
.As<IAssetStore>(); .AsOptional<IAssetStore>();
}, },
["GoogleCloud"] = () => ["GoogleCloud"] = () =>
{ {
var bucketName = config.GetRequiredValue("assetStore:googleCloud:bucket"); var bucketName = config.GetRequiredValue("assetStore:googleCloud:bucket");
services.AddSingletonAs(c => new GoogleCloudAssetStore(bucketName)) services.AddSingletonAs(c => new GoogleCloudAssetStore(bucketName))
.As<IAssetStore>(); .AsOptional<IAssetStore>();
}, },
["AzureBlob"] = () => ["AzureBlob"] = () =>
{ {
@ -44,7 +44,7 @@ namespace Squidex.Config.Domain
var containerName = config.GetRequiredValue("assetStore:azureBlob:containerName"); var containerName = config.GetRequiredValue("assetStore:azureBlob:containerName");
services.AddSingletonAs(c => new AzureBlobAssetStore(connectionString, containerName)) services.AddSingletonAs(c => new AzureBlobAssetStore(connectionString, containerName))
.As<IAssetStore>(); .AsOptional<IAssetStore>();
}, },
["MongoDb"] = () => ["MongoDb"] = () =>
{ {
@ -64,7 +64,7 @@ namespace Squidex.Config.Domain
return new MongoGridFsAssetStore(gridFsbucket); return new MongoGridFsAssetStore(gridFsbucket);
}) })
.As<IAssetStore>(); .AsOptional<IAssetStore>();
} }
}); });

2
src/Squidex/Config/Domain/EntitiesServices.cs

@ -114,7 +114,7 @@ namespace Squidex.Config.Domain
.As<ITagGenerator<CreateAsset>>(); .As<ITagGenerator<CreateAsset>>();
services.AddSingletonAs<JintScriptEngine>() services.AddSingletonAs<JintScriptEngine>()
.As<IScriptEngine>(); .AsOptional<IScriptEngine>();
services.AddCommandPipeline(); services.AddCommandPipeline();
services.AddBackupHandlers(); services.AddBackupHandlers();

4
src/Squidex/Config/Domain/EventStoreServices.cs

@ -39,7 +39,7 @@ namespace Squidex.Config.Domain
return new MongoEventStore(mongDatabase, c.GetRequiredService<IEventNotifier>()); return new MongoEventStore(mongDatabase, c.GetRequiredService<IEventNotifier>());
}) })
.As<IEventStore>(); .AsOptional<IEventStore>();
}, },
["GetEventStore"] = () => ["GetEventStore"] = () =>
{ {
@ -53,7 +53,7 @@ namespace Squidex.Config.Domain
.As<IEventStoreConnection>(); .As<IEventStoreConnection>();
services.AddSingletonAs(c => new GetEventStore(connection, c.GetRequiredService<IJsonSerializer>(), eventStorePrefix, eventStoreProjectionHost)) services.AddSingletonAs(c => new GetEventStore(connection, c.GetRequiredService<IJsonSerializer>(), eventStorePrefix, eventStoreProjectionHost))
.As<IEventStore>(); .AsOptional<IEventStore>();
services.AddHealthChecks() services.AddHealthChecks()
.AddCheck<GetEventStoreHealthCheck>("EventStore", tags: new[] { "node" }); .AddCheck<GetEventStoreHealthCheck>("EventStore", tags: new[] { "node" });

4
src/Squidex/Config/Domain/InfrastructureServices.cs

@ -62,10 +62,10 @@ namespace Squidex.Config.Domain
.As<IActionContextAccessor>(); .As<IActionContextAccessor>();
services.AddSingletonAs<DefaultUserResolver>() services.AddSingletonAs<DefaultUserResolver>()
.As<IUserResolver>(); .AsOptional<IUserResolver>();
services.AddSingletonAs<AssetUserPictureStore>() services.AddSingletonAs<AssetUserPictureStore>()
.As<IUserPictureStore>(); .AsOptional<IUserPictureStore>();
services.AddSingletonAs<DefaultXmlRepository>() services.AddSingletonAs<DefaultXmlRepository>()
.As<IXmlRepository>(); .As<IXmlRepository>();

2
src/Squidex/Config/Domain/LoggingServices.cs

@ -62,7 +62,7 @@ namespace Squidex.Config.Domain
.As<IAppLogStore>(); .As<IAppLogStore>();
services.AddSingletonAs<NoopLogStore>() services.AddSingletonAs<NoopLogStore>()
.As<ILogStore>(); .AsOptional<ILogStore>();
} }
} }
} }

24
src/Squidex/Config/Domain/StoreServices.cs

@ -78,32 +78,32 @@ namespace Squidex.Config.Domain
.As<IMigration>(); .As<IMigration>();
services.AddSingletonAs<MongoUsageRepository>() services.AddSingletonAs<MongoUsageRepository>()
.As<IUsageRepository>(); .AsOptional<IUsageRepository>();
services.AddSingletonAs<MongoRuleEventRepository>() services.AddSingletonAs<MongoRuleEventRepository>()
.As<IRuleEventRepository>(); .AsOptional<IRuleEventRepository>();
services.AddSingletonAs<MongoHistoryEventRepository>() services.AddSingletonAs<MongoHistoryEventRepository>()
.As<IHistoryEventRepository>(); .AsOptional<IHistoryEventRepository>();
services.AddSingletonAs<MongoPersistedGrantStore>() services.AddSingletonAs<MongoPersistedGrantStore>()
.As<IPersistedGrantStore>(); .AsOptional<IPersistedGrantStore>();
services.AddSingletonAs<MongoRoleStore>() services.AddSingletonAs<MongoRoleStore>()
.As<IRoleStore<IdentityRole>>(); .AsOptional<IRoleStore<IdentityRole>>();
services.AddSingletonAs<MongoUserStore>() services.AddSingletonAs<MongoUserStore>()
.As<IUserStore<IdentityUser>>() .AsOptional<IUserStore<IdentityUser>>()
.As<IUserFactory>(); .AsOptional<IUserFactory>();
services.AddSingletonAs<MongoAssetRepository>() services.AddSingletonAs<MongoAssetRepository>()
.As<IAssetRepository>() .AsOptional<IAssetRepository>()
.As<ISnapshotStore<AssetState, Guid>>(); .AsOptional<ISnapshotStore<AssetState, Guid>>();
services.AddSingletonAs(c => new MongoContentRepository(mongoContentDatabase, c.GetRequiredService<IAppProvider>(), c.GetRequiredService<IJsonSerializer>())) services.AddSingletonAs(c => new MongoContentRepository(mongoContentDatabase, c.GetRequiredService<IAppProvider>(), c.GetRequiredService<IJsonSerializer>()))
.As<IContentRepository>() .AsOptional<IContentRepository>()
.As<ISnapshotStore<ContentState, Guid>>() .AsOptional<ISnapshotStore<ContentState, Guid>>()
.As<IEventConsumer>(); .AsOptional<IEventConsumer>();
} }
}); });

6
src/Squidex/Config/Domain/SubscriptionServices.cs

@ -23,13 +23,13 @@ namespace Squidex.Config.Domain
services.AddSingletonAs(c => c.GetRequiredService<IOptions<MyUsageOptions>>()?.Value?.Plans.OrEmpty()); services.AddSingletonAs(c => c.GetRequiredService<IOptions<MyUsageOptions>>()?.Value?.Plans.OrEmpty());
services.AddSingletonAs<ConfigAppPlansProvider>() services.AddSingletonAs<ConfigAppPlansProvider>()
.As<IAppPlansProvider>(); .AsOptional<IAppPlansProvider>();
services.AddSingletonAs<NoopAppPlanBillingManager>() services.AddSingletonAs<NoopAppPlanBillingManager>()
.As<IAppPlanBillingManager>(); .AsOptional<IAppPlanBillingManager>();
services.AddSingletonAs<NoopUserEvents>() services.AddSingletonAs<NoopUserEvents>()
.As<IUserEvents>(); .AsOptional<IUserEvents>();
} }
} }
} }

84
src/Squidex/Pipeline/Plugins/PluginExtensions.cs

@ -6,13 +6,15 @@
// ========================================================================== // ==========================================================================
using System; using System;
using System.Collections.Generic;
using System.IO;
using System.Reflection; using System.Reflection;
using McMaster.NETCore.Plugins; using McMaster.NETCore.Plugins;
using Microsoft.AspNetCore.Builder; using Microsoft.AspNetCore.Builder;
using Microsoft.AspNetCore.Mvc.ApplicationParts; using Microsoft.AspNetCore.Mvc.ApplicationParts;
using Microsoft.Extensions.Configuration; using Microsoft.Extensions.Configuration;
using Microsoft.Extensions.DependencyInjection; using Microsoft.Extensions.DependencyInjection;
using Squidex.Extensions; using Squidex.Infrastructure.Log;
using Squidex.Infrastructure.Plugins; using Squidex.Infrastructure.Plugins;
namespace Squidex.Pipeline.Plugins namespace Squidex.Pipeline.Plugins
@ -29,43 +31,80 @@ namespace Squidex.Pipeline.Plugins
if (options.Plugins != null) if (options.Plugins != null)
{ {
foreach (var pluginPath in options.Plugins) foreach (var path in options.Plugins)
{ {
PluginLoader plugin = null; var plugin = LoadPlugin(path);
if (pluginPath.EndsWith(".dll", StringComparison.OrdinalIgnoreCase)) if (plugin != null)
{ {
plugin = PluginLoader.CreateFromAssemblyFile(pluginPath, SharedTypes); try
}
else
{ {
plugin = PluginLoader.CreateFromConfigFile(pluginPath, SharedTypes); var pluginAssembly = plugin.LoadDefaultAssembly();
AddParts(mvcBuilder, pluginAssembly);
foreach (var relatedAssembly in RelatedAssemblyAttribute.GetRelatedAssemblies(pluginAssembly, false))
{
AddParts(mvcBuilder, relatedAssembly);
} }
if (plugin != null) pluginManager.Add(path, pluginAssembly);
}
catch (Exception ex)
{ {
var pluginAssembly = plugin.LoadDefaultAssembly(); pluginManager.LogException(path, "LoadingAssembly", ex);
}
}
else
{
pluginManager.LogException(path, "LoadingPlugin", new FileNotFoundException($"Cannot find plugin at {path}"));
}
}
}
AddParts(mvcBuilder, pluginAssembly); pluginManager.ConfigureServices(mvcBuilder.Services, configuration);
var relatedAssemblies = pluginAssembly.GetCustomAttributes<RelatedAssemblyAttribute>(); mvcBuilder.Services.AddSingleton(pluginManager);
}
foreach (var relatedAssembly in relatedAssemblies) private static PluginLoader LoadPlugin(string pluginPath)
{ {
var assembly = plugin.LoadAssembly(relatedAssembly.AssemblyFileName); var fullPath = GetPaths(pluginPath);
AddParts(mvcBuilder, assembly); foreach (var candidate in GetPaths(pluginPath))
{
if (candidate.Extension.Equals(".dll", StringComparison.OrdinalIgnoreCase))
{
return PluginLoader.CreateFromAssemblyFile(candidate.FullName, SharedTypes);
} }
pluginManager.Add(pluginAssembly); if (candidate.Extension.Equals(".json", StringComparison.OrdinalIgnoreCase))
{
return PluginLoader.CreateFromConfigFile(candidate.FullName, SharedTypes);
} }
} }
return null;
} }
pluginManager.Add(SquidexExtensions.Assembly); private static IEnumerable<FileInfo> GetPaths(string pluginPath)
pluginManager.ConfigureServices(mvcBuilder.Services, configuration); {
var candidate = new FileInfo(Path.GetFullPath(pluginPath));
mvcBuilder.Services.AddSingleton(pluginManager); if (candidate.Exists)
{
yield return candidate;
}
if (!Path.IsPathRooted(pluginPath))
{
candidate = new FileInfo(Path.Combine(Path.GetDirectoryName(Assembly.GetEntryAssembly().Location), pluginPath));
if (candidate.Exists)
{
yield return candidate;
}
}
} }
public static void UsePlugins(this IApplicationBuilder app) public static void UsePlugins(this IApplicationBuilder app)
@ -73,6 +112,13 @@ namespace Squidex.Pipeline.Plugins
var pluginManager = app.ApplicationServices.GetRequiredService<PluginManager>(); var pluginManager = app.ApplicationServices.GetRequiredService<PluginManager>();
pluginManager.Configure(app); pluginManager.Configure(app);
var log = app.ApplicationServices.GetService<ISemanticLog>();
if (log != null)
{
pluginManager.Log(log);
}
} }
private static void AddParts(IMvcBuilder mvcBuilder, Assembly assembly) private static void AddParts(IMvcBuilder mvcBuilder, Assembly assembly)

3
src/Squidex/Squidex.csproj

@ -61,9 +61,7 @@
</ItemGroup> </ItemGroup>
<ItemGroup> <ItemGroup>
<PackageReference Include="Algolia.Search" Version="5.3.1" />
<PackageReference Include="AspNet.Security.OAuth.GitHub" Version="2.0.1" /> <PackageReference Include="AspNet.Security.OAuth.GitHub" Version="2.0.1" />
<PackageReference Include="Ben.BlockingDetector" Version="0.0.3" />
<PackageReference Include="EventStore.ClientAPI.NetCore" Version="4.1.0.23" /> <PackageReference Include="EventStore.ClientAPI.NetCore" Version="4.1.0.23" />
<PackageReference Include="IdentityServer4" Version="2.3.2" /> <PackageReference Include="IdentityServer4" Version="2.3.2" />
<PackageReference Include="IdentityServer4.AccessTokenValidation" Version="2.7.0" /> <PackageReference Include="IdentityServer4.AccessTokenValidation" Version="2.7.0" />
@ -96,7 +94,6 @@
<PackageReference Include="RefactoringEssentials" Version="5.6.0" PrivateAssets="all" /> <PackageReference Include="RefactoringEssentials" Version="5.6.0" PrivateAssets="all" />
<PackageReference Include="ReportGenerator" Version="4.0.12" /> <PackageReference Include="ReportGenerator" Version="4.0.12" />
<PackageReference Include="Squidex.ClientLibrary" Version="2.8.0" /> <PackageReference Include="Squidex.ClientLibrary" Version="2.8.0" />
<PackageReference Include="StackExchange.Redis.StrongName" Version="1.2.6" />
<PackageReference Include="StyleCop.Analyzers" Version="1.0.2" PrivateAssets="all" /> <PackageReference Include="StyleCop.Analyzers" Version="1.0.2" PrivateAssets="all" />
<PackageReference Include="System.Linq" Version="4.3.0" /> <PackageReference Include="System.Linq" Version="4.3.0" />
<PackageReference Include="System.ValueTuple" Version="4.5.0" /> <PackageReference Include="System.ValueTuple" Version="4.5.0" />

5
src/Squidex/WebStartup.cs

@ -78,8 +78,6 @@ namespace Squidex
config.GetSection("translations:deepL")); config.GetSection("translations:deepL"));
services.Configure<ReadonlyOptions>( services.Configure<ReadonlyOptions>(
config.GetSection("mode")); config.GetSection("mode"));
services.Configure<TwitterOptions>(
config.GetSection("twitter"));
services.Configure<RobotsTxtOptions>( services.Configure<RobotsTxtOptions>(
config.GetSection("robots")); config.GetSection("robots"));
services.Configure<GCHealthCheckOptions>( services.Configure<GCHealthCheckOptions>(
@ -100,9 +98,10 @@ namespace Squidex
services.Configure<MyNewsOptions>( services.Configure<MyNewsOptions>(
config.GetSection("news")); config.GetSection("news"));
services.AddHostedService<InitializerHost>();
var provider = services.AddAndBuildOrleans(configuration, afterServices => var provider = services.AddAndBuildOrleans(configuration, afterServices =>
{ {
afterServices.AddHostedService<InitializerHost>();
afterServices.AddHostedService<MigratorHost>(); afterServices.AddHostedService<MigratorHost>();
}); });

20
src/Squidex/appsettings.json

@ -12,12 +12,19 @@
*/ */
"baseUrl": "http://localhost:5000", "baseUrl": "http://localhost:5000",
/*7 /*
* Set it to true to redirect the user from http to https permanently. * Set it to true to redirect the user from http to https permanently.
*/ */
"enforceHttps": false "enforceHttps": false
}, },
/*
* Define optional paths to plugins.
*/
"plugins": [
"Squidex.Extensions.dll"
],
"etags": { "etags": {
/* /*
* Set to true, to use strong etags. * Set to true, to use strong etags.
@ -313,17 +320,6 @@
"privacyUrl": "https://squidex.io/privacy" "privacyUrl": "https://squidex.io/privacy"
}, },
"twitter": {
/*
* The client id for twitter.
*/
"clientId": "QZhb3HQcGCvE6G8yNNP9ksNet",
/*
* The client secret for twitter.
*/
"clientSecret": "Pdu9wdN72T33KJRFdFy1w4urBKDRzIyuKpc0OItQC2E616DuZD"
},
"news": { "news": {
/* /*
* The app name where the news are stored. * The app name where the news are stored.

Loading…
Cancel
Save