diff --git a/zero.Backoffice.UI/app/account/login.vue b/zero.Backoffice.UI/app/account/login.vue index 7a8966f3..79063a30 100644 --- a/zero.Backoffice.UI/app/account/login.vue +++ b/zero.Backoffice.UI/app/account/login.vue @@ -23,7 +23,7 @@
- +
@@ -114,7 +114,7 @@ grid-template-rows: 1fr auto; align-items: stretch; max-width: 100%; - width: 520px; + width: 420px; background: var(--color-box); box-shadow: var(--shadow-short); border-radius: var(--radius); @@ -135,7 +135,7 @@ .app-auth-image { - height: 15px; + height: 16px; } .app-auth .ui-property + .ui-property @@ -147,7 +147,13 @@ .app-auth-bottom { + margin: calc(-1 * var(--padding)); margin-top: 3rem; + padding: var(--padding); + background: var(--color-box-nested); + border-top: 1px solid var(--color-line-onbg); + border-bottom-left-radius: var(--radius); + border-bottom-right-radius: var(--radius); } .app-auth .ui-message diff --git a/zero.Core/Applications/ApplicationResolver.cs b/zero.Core/Applications/ApplicationResolver.cs index b871060e..e920fc08 100644 --- a/zero.Core/Applications/ApplicationResolver.cs +++ b/zero.Core/Applications/ApplicationResolver.cs @@ -41,14 +41,15 @@ public class ApplicationResolver : IApplicationResolver Application app; - if (context.IsBackofficeRequest(Options.ZeroPath)) - { - app = await ResolveFromUser(user); - } - else - { - app = await ResolveFromRequest(context); - } + //if (context.IsBackofficeRequest(Options.ZeroPath)) + //{ + // app = await ResolveFromUser(user); + //} + //else + //{ + // app = await ResolveFromRequest(context); + //} + app = await ResolveFromRequest(context); if (app == null) { @@ -109,10 +110,10 @@ public class ApplicationResolver : IApplicationResolver /// public async Task ResolveFromRequest(HttpContext context) { - if (Options.Applications.Count < 2) - { - return (await GetApplications()).FirstOrDefault(); - } + //if (Options.Applications.Count < 2) + //{ + // return (await GetApplications()).FirstOrDefault(); + //} IApplicationResolverHandler handler = Handler.Get(); Application app = handler?.Resolve(context.Request, await GetApplications()); diff --git a/zero.Core/Context/ZeroContext.cs b/zero.Core/Context/ZeroContext.cs index 5ae618ef..10d1b846 100644 --- a/zero.Core/Context/ZeroContext.cs +++ b/zero.Core/Context/ZeroContext.cs @@ -37,6 +37,9 @@ public class ZeroContext : IZeroContext /// public IServiceProvider Services { get; private set; } + /// + public ZeroContextScope Scope { get; private set; } + protected IApplicationResolver AppResolver { get; private set; } @@ -107,27 +110,16 @@ public class ZeroContext : IZeroContext Application = await AppResolver.Resolve(context, BackofficeUser); AppId = Application.Id; + Logger.LogDebug("Resolved {appId} for request {uri}", AppId, context.Request.Host.ToString() + context.Request.Path.Value.EnsureStartsWith('/')); + // set default database for document store Store.ResolvedDatabase = Application.Database; // set current culture await CultureResolver.Resolve(this); - } - - /// - public void Override(Application app) - { - Application = app; - AppId = app?.Id; - Store.ResolvedDatabase = app?.Database; - } - - - /// - public ZeroContextScope CreateScope(Application app) - { - return new(this, app, Application); + // set context scope + Scope = new(Store, Store.ResolvedDatabase, Application); } @@ -141,37 +133,69 @@ public class ZeroContext : IZeroContext /// public void Remove() => ValueCollection.Remove(); + + + /// + public ZeroContextScope CreateScope(Application app) + { + ApplyScope(app.Database, app); + return new ZeroContextScope(Store, app.Database, app, Scope, scope => + { + Scope = scope.Previous; + ApplyScope(Scope.Database, Scope.Application); + }); + } + + + /// + public ZeroContextScope CreateScope(string database) + { + ApplyScope(database); + return new ZeroContextScope(Store, database, null, Scope, scope => + { + Scope = scope.Previous; + ApplyScope(Scope.Database, Scope.Application); + }); + } + + + /// + /// Apply a database scope + /// + void ApplyScope(string database, Application app = null) + { + Application = app; + AppId = app?.Id; + Store.ResolvedDatabase = database; + } } public class ZeroContextScope : IDisposable { - public IZeroContext Context { get; } - - public Application App { get; set; } - - public string Database { get; set; } + public ZeroContextScope(IZeroStore store, string database, Application application, ZeroContextScope previous = null, Action onDispose = null) + { + Store = store; + Database = database; + Application = application; + Previous = previous; + _onDispose = onDispose; + } public IZeroStore Store { get; set; } - readonly Application _originalApp = null; + public Application Application { get; private set; } + public string Database { get; private set; } - internal ZeroContextScope(IZeroContext context, Application app, Application originalApp) - { - Context = context; - App = app; - Database = app.Database; - Store = context.Store; - _originalApp = originalApp; - Context.Override(app); - } + public ZeroContextScope Previous { get; private set; } + + Action _onDispose = null; - /// public void Dispose() { - Context.Override(_originalApp); + _onDispose?.Invoke(this); } } @@ -219,6 +243,11 @@ public interface IZeroContext /// IServiceProvider Services { get; } + /// + /// Current context scope + /// + ZeroContextScope Scope { get; } + /// /// Matching (frontend) path route /// @@ -235,16 +264,6 @@ public interface IZeroContext /// Task Resolve(HttpContext context); - /// - /// Overrides the resolved application for this context instance - /// - void Override(Application app); - - /// - /// SCOPE - /// - ZeroContextScope CreateScope(Application app); - /// /// Get a custom property from this scoped context /// @@ -259,4 +278,14 @@ public interface IZeroContext /// Remove a custom property from this scoped context /// void Remove(); + + /// + /// Scope the current context to a specific application database + /// + ZeroContextScope CreateScope(Application app); + + /// + /// Scope the current context to a specific database + /// + ZeroContextScope CreateScope(string database); } \ No newline at end of file diff --git a/zero.Core/Routing/RouteBulkRefresher.cs b/zero.Core/Routing/RouteBulkRefresher.cs index 6684b957..dbc2ebce 100644 --- a/zero.Core/Routing/RouteBulkRefresher.cs +++ b/zero.Core/Routing/RouteBulkRefresher.cs @@ -33,7 +33,7 @@ public class RouteBulkRefresher await scope.Store.Raven.PurgeAsync(scope.Database); - RoutingContext context = new(scope.Store, scope.Context, session); + RoutingContext context = new(scope.Store, Context, session); foreach (IRouteProvider provider in Providers.OrderByDescending(x => x.Priority)) { diff --git a/zero.Core/Stores/StoreOperations.cs b/zero.Core/Stores/StoreOperations.cs index dc6800e2..7ae76b9b 100644 --- a/zero.Core/Stores/StoreOperations.cs +++ b/zero.Core/Stores/StoreOperations.cs @@ -10,11 +10,11 @@ public partial class StoreOperations : IStoreOperations /// public IZeroDocumentSession Session => Context.Store.Session(); - protected record EntityCollectionOptions(bool IncludeInactive); + protected record OperationOptions(bool IncludeInactive); protected IZeroContext Context { get; private set; } - protected EntityCollectionOptions Options { get; set; } + protected OperationOptions Options { get; set; } protected IInterceptors Interceptors { get; private set; } diff --git a/zero.Demo/DevApplicationResolverHandler.cs b/zero.Demo/DevApplicationResolverHandler.cs index 5f588e4d..f69ed5ea 100644 --- a/zero.Demo/DevApplicationResolverHandler.cs +++ b/zero.Demo/DevApplicationResolverHandler.cs @@ -9,6 +9,7 @@ public class DevApplicationResolverHandler : IApplicationResolverHandler static Dictionary PortMap = new() { { 2310, "app.hofbauer" }, + { 2100, "app.hofbauer" }, { 2300, "app.brothers" }, { 2320, "app.sporthuber" } }; @@ -21,8 +22,6 @@ public class DevApplicationResolverHandler : IApplicationResolverHandler public Application Resolve(HttpRequest request, IEnumerable applications) { - return applications.First(x => x.Id == "app.hofbauer"); - //if (!Env.IsDevelopment()) //{ // return null; diff --git a/zero.Demo/TestController.cs b/zero.Demo/TestController.cs new file mode 100644 index 00000000..1976b7ca --- /dev/null +++ b/zero.Demo/TestController.cs @@ -0,0 +1,41 @@ +using Microsoft.AspNetCore.Mvc; +using zero.Context; +using zero.Identity; +using zero.Stores; + +namespace zero.Demo.Controllers; + +public class TestController : Controller +{ + [HttpGet] + public async Task Scoping([FromServices] IZeroContext ctx, [FromServices] IStoreOperations ops) + { + string scopeA = null; + string scopeB = null; + string scopeC = null; + List usersA = new(); + List usersB = new(); + + scopeA = ctx.Store.ResolvedDatabase; + + using (var scope = ctx.CreateScope("laola")) + { + scopeB = ctx.Store.ResolvedDatabase; + usersA = await ops.LoadAll(); + } + + scopeC = ctx.Store.ResolvedDatabase; + usersB = await ops.LoadAll(); + + + + return Json(new + { + scopeA, + scopeB, + scopeC, + usersA, + usersB + }); + } +} \ No newline at end of file diff --git a/zero.Demo/appsettings.json b/zero.Demo/appsettings.json index 1deadf15..37a3db0e 100644 --- a/zero.Demo/appsettings.json +++ b/zero.Demo/appsettings.json @@ -11,6 +11,7 @@ "Logging": { "LogLevel": { "Default": "Information", + "zero": "Debug", "Microsoft.AspNetCore": "Warning" } },