draft: refactor project so it sits on top of a standalone app

This commit is contained in:
2020-05-11 15:34:47 +02:00
parent a9ee5acc1c
commit f97e8455fc
13068 changed files with 1735502 additions and 866 deletions
+7 -5
View File
@@ -7,12 +7,12 @@ namespace zero.Core.Api
{
public class PermissionsApi : IPermissionsApi
{
protected ZeroOptions Options { get; set; }
protected IZeroOptions Options { get; set; }
public PermissionsApi (IOptionsMonitor<ZeroOptions> options)
public PermissionsApi (IZeroOptions options)
{
Options = options.CurrentValue;
Options = options;
}
@@ -35,7 +35,9 @@ namespace zero.Core.Api
result.Add(permissionSections);
if (Options.Spaces.Count > 0)
// TODO add back spaces
if (Options.Backoffice.Spaces.Count > 0)
{
PermissionCollection permissionSpaces = new PermissionCollection()
{
@@ -43,7 +45,7 @@ namespace zero.Core.Api
Description = "@permission.collections.spaces_description"
};
foreach (Space space in Options.Spaces)
foreach (Space space in Options.Backoffice.Spaces)
{
permissionSpaces.Items.Add(new Permission(Permissions.Spaces.PREFIX + space.Alias, space.Name, null, PermissionValueType.ReadWrite));
}
+5 -5
View File
@@ -7,26 +7,26 @@ namespace zero.Core.Api
{
public class SectionsApi : ISectionsApi
{
protected ZeroOptions Options { get; private set; }
protected IZeroOptions Options { get; private set; }
public SectionsApi(IOptionsMonitor<ZeroOptions> options)
public SectionsApi(IZeroOptions options)
{
Options = options.CurrentValue;
Options = options;
}
/// <inheritdoc />
public SectionCollection GetAll()
{
return Options.Sections;
return Options.Backoffice.Sections;
}
/// <inheritdoc />
public ISection GetByAlias(string alias)
{
return Options.Sections.FirstOrDefault(section => section.Alias.Equals(alias, StringComparison.InvariantCultureIgnoreCase));
return Options.Backoffice.Sections.FirstOrDefault(section => section.Alias.Equals(alias, StringComparison.InvariantCultureIgnoreCase));
}
}
+5 -7
View File
@@ -1,25 +1,23 @@
using Microsoft.Extensions.Options;
using System.Collections.Generic;
using System.Collections.Generic;
using zero.Core.Entities;
using zero.Core.Identity;
namespace zero.Core.Api
{
public class SettingsApi : ISettingsApi
{
protected ZeroOptions Options { get; private set; }
protected IZeroOptions Options { get; private set; }
public SettingsApi(IOptionsMonitor<ZeroOptions> options)
public SettingsApi(IZeroOptions options)
{
Options = options.CurrentValue;
Options = options;
}
/// <inheritdoc />
public IList<SettingsGroup> GetAreas()
{
return Options.SettingsAreas;
return Options.Backoffice.Settings;
}
}
+18 -15
View File
@@ -19,14 +19,14 @@ namespace zero.Core.Api
{
public class SetupApi : ISetupApi
{
protected IZeroConfiguration Config { get; private set; }
protected IZeroOptions Options { get; private set; }
protected UserManager<User> UserManager { get; private set; }
public SetupApi(IZeroConfiguration config, UserManager<User> userManager)
public SetupApi(IZeroOptions options, UserManager<User> userManager)
{
Config = config;
Options = options;
UserManager = userManager;
}
@@ -80,7 +80,7 @@ namespace zero.Core.Api
Email = model.User.Email,
Name = model.User.Name,
IsActive = true,
LanguageId = Config.DefaultLanguage,
LanguageId = Options.DefaultLanguage,
Alias = Alias.Generate(model.User.Name),
IsEmailConfirmed = true
};
@@ -170,22 +170,25 @@ namespace zero.Core.Api
/// </summary>
void UpdateSettingsFile(SetupModel model)
{
var filePath = Path.Combine(model.ContentRootPath, "zeroSettings.json");
string json = File.ReadAllText(filePath);
// TODO should we write this into appSettings.json now?
// or let the user do it in the code editor?
ZeroConfiguration config = JsonConvert.DeserializeObject<ZeroConfiguration>(json);
//var filePath = Path.Combine(model.ContentRootPath, "zeroSettings.json");
//string json = File.ReadAllText(filePath);
config.Raven = new RavenConfig()
{
Database = model.Database.Name,
Url = model.Database.Url
};
//ZeroConfiguration config = JsonConvert.DeserializeObject<ZeroConfiguration>(json);
config.ZeroVersion = System.Reflection.Assembly.GetEntryAssembly().GetName().Version.ToString();
//config.Raven = new RavenOptions()
//{
// Database = model.Database.Name,
// Url = model.Database.Url
//};
json = JsonConvert.SerializeObject(config, Formatting.Indented);
//config.ZeroVersion = System.Reflection.Assembly.GetEntryAssembly().GetName().Version.ToString();
File.WriteAllText(filePath, json);
//json = JsonConvert.SerializeObject(config, Formatting.Indented);
//File.WriteAllText(filePath, json);
}
+7 -7
View File
@@ -19,28 +19,28 @@ namespace zero.Core.Api
protected IPermissionsApi PermissionsApi { get; private set; }
protected ZeroOptions Options { get; private set; }
protected IZeroOptions Options { get; private set; }
public SpacesApi(IDocumentStore raven, IPermissionsApi permissionsApi, IOptionsMonitor<ZeroOptions> options)
public SpacesApi(IDocumentStore raven, IPermissionsApi permissionsApi, IZeroOptions options)
{
Raven = raven;
PermissionsApi = permissionsApi;
Options = options.CurrentValue;
Options = options;
}
/// <inheritdoc />
public Space GetByAlias(string alias)
{
return Options.Spaces.FirstOrDefault(x => x.Alias.Equals(alias, StringComparison.InvariantCultureIgnoreCase));
return Options.Backoffice.Spaces.FirstOrDefault(x => x.Alias.Equals(alias, StringComparison.InvariantCultureIgnoreCase));
}
/// <inheritdoc />
public SpaceCollection GetAll()
{
return Options.Spaces;
return Options.Backoffice.Spaces;
}
@@ -54,7 +54,7 @@ namespace zero.Core.Api
return null;
}
AbstractGenericRenderer renderer = Options.Renderers.FirstOrDefault(x => x.TargetType == space.Type);
AbstractGenericRenderer renderer = Options.Backoffice.Renderers.FirstOrDefault(x => x.TargetType == space.Type);
if (renderer == null)
{
@@ -122,7 +122,7 @@ namespace zero.Core.Api
/// <inheritdoc />
public async Task<EntityResult<T>> Save<T>(string alias, T model) where T : SpaceContent
{
Space space = Options.Spaces.GetByAlias(alias);
Space space = Options.Backoffice.Spaces.GetByAlias(alias);
RendererConfig config = GetEditorConfig(alias);
if (config.Validator != null)
+4 -4
View File
@@ -11,15 +11,15 @@ namespace zero.Core.Api
{
protected IDocumentStore Raven { get; private set; }
protected IZeroConfiguration Config { get; private set; }
protected IZeroOptions Options { get; private set; }
private const string PREFIX = "ChangeTokens.";
public Token(IDocumentStore raven, IZeroConfiguration config)
public Token(IDocumentStore raven, IZeroOptions options)
{
Raven = raven;
Config = config;
Options = options;
}
@@ -74,7 +74,7 @@ namespace zero.Core.Api
using (IAsyncDocumentSession session = Raven.OpenAsyncSession())
{
await session.StoreAsync(token);
session.Advanced.GetMetadataFor(token)[Constants.Database.Expires] = DateTime.UtcNow.AddMinutes(Config.TokenExpiration);
session.Advanced.GetMetadataFor(token)[Constants.Database.Expires] = DateTime.UtcNow.AddMinutes(Options.TokenExpiration);
await session.SaveChangesAsync();
}
+7 -7
View File
@@ -9,19 +9,19 @@ namespace zero.Core.Plugins
{
public abstract class ZeroPlugin
{
protected SectionCollection Sections { get; private set; }
public SectionCollection Sections { get; private set; } = new SectionCollection();
protected SpaceCollection Spaces { get; private set; }
public SpaceCollection Spaces { get; private set; } = new SpaceCollection();
protected RendererCollection Renderers { get; private set; }
public RendererCollection Renderers { get; private set; } = new RendererCollection();
protected IList<SettingsGroup> Settings { get; private set; }
public IList<SettingsGroup> Settings { get; private set; } = new List<SettingsGroup>();
protected PermissionGroupCollection Permissions { get; private set; }
public PermissionGroupCollection Permissions { get; private set; } = new PermissionGroupCollection();
protected FeatureCollection Features { get; private set; }
public FeatureCollection Features { get; private set; } = new FeatureCollection();
protected IMapper Mapper { get; private set; }
public IMapper Mapper { get; private set; }
protected virtual IServiceCollection ConfigureServices(IServiceCollection services)
{
-81
View File
@@ -1,81 +0,0 @@
namespace zero.Core
{
public class ZeroConfiguration : IZeroConfiguration
{
/// <inheritdoc />
public string ZeroVersion { get; set; }
/// <inheritdoc />
public string DefaultLanguage { get; set; }
/// <inheritdoc />
public string[] SupportedLanguages { get; private set; } = new string[] { "en-US", "de-DE" };
/// <inheritdoc />
public int TokenExpiration { get; set; }
/// <inheritdoc />
public RavenConfig Raven { get; set; }
/// <inheritdoc />
public LoggingConfig Logging { get; set; }
}
public interface IZeroConfiguration
{
/// <summary>
/// The currently active version
/// This should not be set manually, as it is used for setup and migrations and incremented automatically
/// </summary>
string ZeroVersion { get; set; }
/// <summary>
/// Default language ISO code
/// </summary>
string DefaultLanguage { get; set; }
/// <summary>
/// Language ISO codes which are supported by the zero backoffice
/// </summary>
string[] SupportedLanguages { get; }
/// <summary>
/// Expiration in minutes of a generated change token for an entity
/// </summary>
int TokenExpiration { get; set; }
/// <summary>
/// RavenDB configuration data
/// </summary>
RavenConfig Raven { get; set; }
/// <summary>
/// Logging
/// </summary>
LoggingConfig Logging { get; set; }
}
public class FoldersConfig
{
public string Temp { get; set; }
}
public class LoggingConfig
{
public bool IncludeScopes { get; set; }
public LogLevel LogLevel { get; set; }
}
public class LogLevel
{
public string Default { get; set; }
public string System { get; set; }
public string Microsoft { get; set; }
}
public class RavenConfig
{
public string Url { get; set; }
public string Database { get; set; }
}
}
+72 -17
View File
@@ -1,29 +1,84 @@
using System.Collections.Generic;
using zero.Core.Entities;
using zero.Core.Identity;
using zero.Core.Plugins;
namespace zero.Core
{
public class ZeroOptions
public class ZeroOptions : IZeroOptions
{
public ZeroOptions()
{
SupportedLanguages = new string[2] { "en-US", "de-DE" };
DefaultLanguage = SupportedLanguages[0];
TokenExpiration = 60;
BackofficePath = "/zero";
}
/// <inheritdoc />
public string ZeroVersion { get; set; }
/// <inheritdoc />
public string DefaultLanguage { get; set; }
/// <inheritdoc />
public string[] SupportedLanguages { get; private set; }
/// <inheritdoc />
public int TokenExpiration { get; set; }
/// <inheritdoc />
public RavenOptions Raven { get; set; }
/// <inheritdoc />
public string BackofficePath { get; set; }
public SectionCollection Sections { get; private set; } = new SectionCollection();
public SpaceCollection Spaces { get; private set; } = new SpaceCollection();
public RendererCollection Renderers { get; private set; } = new RendererCollection();
public IList<SettingsGroup> SettingsAreas { get; private set; } = new List<SettingsGroup>();
public ZeroAuthorizationOptions Authorization { get; private set; } = new ZeroAuthorizationOptions();
public FeatureCollection Features { get; private set; } = new FeatureCollection();
/// <inheritdoc />
public ZeroPlugin Backoffice { get; set; }
}
public class ZeroAuthorizationOptions
public class RavenOptions
{
public IList<PermissionCollection> Permissions { get; private set; } = new List<PermissionCollection>();
public string Url { get; set; }
public string Database { get; set; }
}
public interface IZeroOptions
{
/// <summary>
/// The currently active version
/// This should not be set manually, as it is used for setup and migrations and incremented automatically
/// </summary>
string ZeroVersion { get; set; }
/// <summary>
/// Default language ISO code
/// </summary>
string DefaultLanguage { get; set; }
/// <summary>
/// Language ISO codes which are supported by the zero backoffice
/// </summary>
string[] SupportedLanguages { get; }
/// <summary>
/// Expiration in minutes of a generated change token for an entity
/// </summary>
int TokenExpiration { get; set; }
/// <summary>
/// RavenDB configuration data
/// </summary>
RavenOptions Raven { get; set; }
/// <summary>
/// URL path to the backoffice (defaults to /zero)
/// </summary>
string BackofficePath { get; set; }
/// <summary>
/// Default settings for the backoffice
/// </summary>
ZeroPlugin Backoffice { get; set; }
}
}
+9 -8
View File
@@ -1,5 +1,7 @@
using Microsoft.AspNetCore.Hosting;
using Microsoft.Extensions.Hosting;
using System;
using System.Diagnostics;
namespace zero.Debug
{
@@ -7,19 +9,18 @@ namespace zero.Debug
{
public static void Main(string[] args)
{
Console.WriteLine("Process ID: " + Process.GetCurrentProcess().Id);
CreateHostBuilder(args).Build().Run();
}
public static IHostBuilder CreateHostBuilder(string[] args)
{
IHostBuilder builder = Host.CreateDefaultBuilder(args);
builder.ConfigureWebHostDefaults(webBuilder =>
{
webBuilder.UseStartup<Startup>();
});
return builder;
return Host
.CreateDefaultBuilder(args)
.ConfigureWebHostDefaults(webBuilder =>
{
webBuilder.UseStartup<Startup>();
});
}
}
}
+4 -4
View File
@@ -3,22 +3,22 @@
"windowsAuthentication": false,
"anonymousAuthentication": true,
"iisExpress": {
"applicationUrl": "http://localhost:60790",
"applicationUrl": "http://localhost:2300",
"sslPort": 0
}
},
"profiles": {
"IIS Express": {
"commandName": "IISExpress",
"launchBrowser": true,
"launchBrowser": false,
"environmentVariables": {
"ASPNETCORE_ENVIRONMENT": "Development"
}
},
"zero.Debug": {
"commandName": "Project",
"launchBrowser": true,
"applicationUrl": "http://localhost:5000",
"launchBrowser": false,
"applicationUrl": "http://localhost:2300",
"environmentVariables": {
"ASPNETCORE_ENVIRONMENT": "Development"
}
+18 -5
View File
@@ -1,33 +1,46 @@
using System;
using System.Collections.Generic;
using System.Linq;
using System.Threading.Tasks;
using Microsoft.AspNetCore.Builder;
using Microsoft.AspNetCore.Hosting;
using Microsoft.AspNetCore.Http;
using Microsoft.Extensions.Configuration;
using Microsoft.Extensions.DependencyInjection;
using Microsoft.Extensions.Hosting;
using zero.Web;
namespace zero.Debug
{
public class Startup
{
IConfiguration Configuration;
public Startup(IConfiguration configuration)
{
Configuration = configuration;
}
// This method gets called by the runtime. Use this method to add services to the container.
// For more information on how to configure your application, visit https://go.microsoft.com/fwlink/?LinkID=398940
public void ConfigureServices(IServiceCollection services)
{
services.AddZero(Configuration);
services.Configure<IISOptions>(opts => opts.AutomaticAuthentication = false);
}
// This method gets called by the runtime. Use this method to configure the HTTP request pipeline.
public void Configure(IApplicationBuilder app, IWebHostEnvironment env)
{
if (env.IsDevelopment())
{
app.UseDeveloperExceptionPage();
app.UseZeroDevEnvironment();
}
app.UseRouting();
app.UseZero();
app.UseEndpoints(endpoints =>
{
endpoints.MapGet("/", async context =>
+9
View File
@@ -0,0 +1,9 @@
using zero.Core.Entities;
namespace zero.TestData
{
public class News : SpaceContent
{
}
}
@@ -0,0 +1,49 @@
using System.Collections.Generic;
using zero.Core.Entities;
namespace zero.TestData
{
public class SocialContent : SpaceContent
{
public bool IsVisible { get; set; }
public string Twitter { get; set; }
public string Facebook { get; set; }
public string Youtube { get; set; }
public string xRte { get; set; }
public string xTextarea { get; set; }
public string xState { get; set; }
public string xMedia { get; set; }
public string xIconPicker { get; set; }
public string xCustom { get; set; }
public List<SocialAddress> Addresses { get; set; } = new List<SocialAddress>();
}
public class SocialAddress
{
public string City { get; set; }
public string Street { get; set; }
public string No { get; set; }
public List<SocialAddressCountry> Countries { get; set; } = new List<SocialAddressCountry>();
}
public class SocialAddressCountry
{
public string Name { get; set; }
public string Iso { get; set; }
}
}
@@ -0,0 +1,89 @@
using FluentValidation;
using zero.Core.Renderer;
namespace zero.TestData.Lists
{
public class SocialContentRenderer : AbstractRenderer<SocialContent>
{
public SocialContentRenderer()
{
LabelTemplate = "@_test.fields.{0}";
DescriptionTemplate = "@_test.fields.{0}_text";
Validator = new SocialContentValidator();
Field(x => x.IsVisible).Toggle();
Field(x => x.xIconPicker).IconPicker();
Field(x => x.xTextarea).Textarea();
//Field(x => x.Addresses, required: true).Nested(new SocialAddressRenderer(), opts =>
//{
// opts.Limit = 5;
// opts.AddLabel = "Add address";
//});
Field(x => x.xRte).Rte();
Field(x => x.xMedia).Media(opts => opts.Type = MediaOptionsType.Image);
Field(x => x.xTextarea).Output();
Field(x => x.xState).State(opts =>
{
opts.Add("Image", "image");
opts.Add("Video" , "video");
opts.Add("Other", "other");
});
Field(x => x.xCustom).Custom("MyPlugin/myplugineditor.vue", () => new
{
enabled = true,
name = "tobi"
});
Tab("Networks", () => {
Field(x => x.Facebook, required: true).Text(opts => opts.Placeholder = "Enter your facebook URL");
Field(x => x.Youtube).Text();
Field(x => x.Twitter).Text(opts => opts.Classes.Add("is-short"));
});
}
}
public class SocialAddressRenderer : AbstractRenderer<SocialAddress>
{
public SocialAddressRenderer()
{
LabelTemplate = "@_test.fields.address.{0}";
DescriptionTemplate = "@{0}";
Field(x => x.City, required: true).Text();
Field(x => x.Street).Text();
Field(x => x.No).Text(opts => opts.Classes.Add("is-short"));
Field(x => x.Countries, required: true).Nested(new SocialAddressCountryRenderer(), opts =>
{
opts.Limit = 1;
});
//Field(x => x.CountryId).Custom("plugins/countryPicker/countrypicker", () => new
//{
// startId = 107
//});
}
}
public class SocialAddressCountryRenderer : AbstractRenderer<SocialAddressCountry>
{
public SocialAddressCountryRenderer()
{
LabelTemplate = "@_test.fields.address.{0}";
DescriptionTemplate = "@{0}";
Field(x => x.Name, required: true).Text();
Field(x => x.Iso, required: true).Text();
}
}
public class SocialContentValidator : AbstractValidator<SocialContent>
{
public SocialContentValidator()
{
RuleFor(x => x.Facebook).NotEmpty().MaximumLength(120);
}
}
}
+30
View File
@@ -0,0 +1,30 @@
using System.Collections.Generic;
using zero.Core.Entities;
namespace zero.TestData
{
public class TeamMember : SpaceContent
{
public string Position { get; set; }
public Media Image { get; set; }
public string Email { get; set; }
public string VideoUri { get; set; }
public List<TeamMemberAddress> Addresses { get; set; } = new List<TeamMemberAddress>();
}
public class TeamMemberAddress
{
public string City { get; set; }
public string Street { get; set; }
public string No { get; set; }
public string CountryId { get; set; }
}
}
@@ -0,0 +1,56 @@
using FluentValidation;
using zero.Core.Renderer;
namespace zero.TestData.Lists
{
public class TeamMemberRenderer : AbstractRenderer<TeamMember>
{
public TeamMemberRenderer()
{
LabelTemplate = "@_test.fields.{0}";
DescriptionTemplate = "@_test.fields.{0}_text";
Validator = new TeamMemberValidator();
Field(x => x.Name, required: true).Text(opts => opts.Placeholder = "Enter your name");
Field(x => x.Position, required: true).Text();
Field(x => x.Image).Media(opts => opts.Type = MediaOptionsType.Image);
Field(x => x.Email, required: true).Text(opts => opts.Classes.Add("email-field"));
Field(x => x.VideoUri).Text();
//Field(x => x.Addresses, required: true).Nested(new AddressRenderer(), opts =>
//{
// opts.Limit = 5;
// opts.AddLabel = "Add address";
//});
}
}
public class AddressRenderer : AbstractRenderer<TeamMemberAddress>
{
public AddressRenderer()
{
LabelTemplate = "@_test.fields.address.{0}";
DescriptionTemplate = "@{0}";
Field(x => x.City, required: true).Text();
Field(x => x.Street).Text();
Field(x => x.No).Text(opts => opts.Classes.Add("is-short"));
//Field(x => x.CountryId).Custom("plugins/countryPicker/countrypicker", () => new
//{
// startId = 107
//});
}
}
public class TeamMemberValidator : AbstractValidator<TeamMember>
{
public TeamMemberValidator()
{
RuleFor(x => x.Name).NotEmpty().MaximumLength(120);
RuleFor(x => x.Position).NotEmpty().Length(3, 60);
RuleFor(x => x.Email).NotEmpty().EmailAddress();
}
}
}
@@ -0,0 +1,15 @@
using System;
using System.Collections.Generic;
using System.Text;
using zero.Core.Entities;
namespace zero.TestData.Spaces
{
//public class TeamMemberSpace : Space
//{
// public TeamMemberSpace()
// {
// }
//}
}
+9
View File
@@ -0,0 +1,9 @@
namespace zero.TestData
{
public static class TestFeatures
{
public const string Wishlist = "testdata.wishlist";
public const string SocialShopping = "testdata.socialshopping";
}
}
+29
View File
@@ -0,0 +1,29 @@
using Microsoft.Extensions.DependencyInjection;
using System;
using System.Collections.Generic;
using System.Text;
using zero.Core;
using zero.Core.Entities;
using zero.Core.Identity;
using zero.Core.Plugins;
using zero.TestData.Lists;
namespace zero.TestData
{
public class TestPlugin : ZeroPlugin
{
public TestPlugin()
{
Spaces.AddList<TeamMember>("team", "Team", "Our team members", "fth-users");
Spaces.AddList<News>("news", "News", "Articles about the company", "fth-edit");
Spaces.AddSeparator();
Spaces.AddEditor<SocialContent>("social", "Social", "Links to social media", "fth-twitter");
Features.Add(TestFeatures.Wishlist, "Wishlist", "Frontend wishlist for logged-in users");
Features.Add(TestFeatures.SocialShopping, "Social shopping", "Integrate products into social media portals");
Renderers.Add<TeamMember, TeamMemberRenderer>();
Renderers.Add<SocialContent, SocialContentRenderer>();
}
}
}
+6
View File
@@ -1,4 +1,10 @@
{
"Zero": {
"Raven": {
"Url": "http://127.0.0.1:9800",
"Database": "zero"
}
},
"Logging": {
"LogLevel": {
"Default": "Information",
+5
View File
@@ -4,4 +4,9 @@
<TargetFramework>netcoreapp3.1</TargetFramework>
</PropertyGroup>
<ItemGroup>
<ProjectReference Include="..\zero.Core\zero.Core.csproj" />
<ProjectReference Include="..\zero.Web\zero.Web.csproj" />
</ItemGroup>
</Project>
@@ -55,7 +55,7 @@
{
if (this.view === 'custom')
{
return import('@/Plugins/' + this.component.params.componentPath);
//return import('@/Plugins/' + this.component.params.componentPath);
}
else if (this.view === 'nested')
{

Some files were not shown because too many files have changed in this diff Show More