diff --git a/Serenity b/Serenity index cfc6e380..f1cf48d6 160000 --- a/Serenity +++ b/Serenity @@ -1 +1 @@ -Subproject commit cfc6e38053d07c081c14212a5ff105490cde5d44 +Subproject commit f1cf48d6316c624d104e0d232dc005696b368c2c diff --git a/common-features b/common-features index 237433cc..509b4685 160000 --- a/common-features +++ b/common-features @@ -1 +1 @@ -Subproject commit 237433ccb7938628d0a3c9731c3b843cd914d3c3 +Subproject commit 509b46850bb677b3a184c9aaad2d8c511123c0c0 diff --git a/src/Serene.Web/.config/dotnet-tools.json b/src/Serene.Web/.config/dotnet-tools.json index 31a34328..504652e9 100644 --- a/src/Serene.Web/.config/dotnet-tools.json +++ b/src/Serene.Web/.config/dotnet-tools.json @@ -3,10 +3,11 @@ "isRoot": true, "tools": { "sergen": { - "version": "8.4.8", + "version": "8.6.0", "commands": [ "sergen" - ] + ], + "rollForward": false } } } \ No newline at end of file diff --git a/src/Serene.Web/Initialization/Startup.cs b/src/Serene.Web/Initialization/Startup.cs index b57a1885..260262da 100644 --- a/src/Serene.Web/Initialization/Startup.cs +++ b/src/Serene.Web/Initialization/Startup.cs @@ -99,8 +99,9 @@ public void ConfigureServices(IServiceCollection services) services.AddSingleton(); services.AddSingleton(); services.AddSingleton(); - services.AddSingleton(); - services.AddSingleton(); + services.AddSingleton(); + services.AddSingleton(); + services.AddSingleton(); services.AddSingleton(); services.AddSingleton(); services.AddSingleton(); diff --git a/src/Serene.Web/Modules/Administration/Translation/TranslationGrid.ts b/src/Serene.Web/Modules/Administration/Translation/TranslationGrid.ts index 7a549c19..a6c30b8f 100644 --- a/src/Serene.Web/Modules/Administration/Translation/TranslationGrid.ts +++ b/src/Serene.Web/Modules/Administration/Translation/TranslationGrid.ts @@ -1,7 +1,6 @@ -import { Decorators, EntityGrid, Fluent, GridUtils, LookupEditor, LookupEditorOptions, ToolButton, Widget } from "@serenity-is/corelib"; -import { confirm, isEmptyOrNull, isTrimmedEmpty, notifySuccess, outerHtml, localText, trimToEmpty, trimToNull } from "@serenity-is/corelib"; -import { Column } from "@serenity-is/sleekgrid"; -import { TranslationItem, TranslationService } from "../"; +import { confirmDialog, Decorators, EntityGrid, Fluent, GridUtils, isEmptyOrNull, isTrimmedEmpty, localText, LookupEditor, LookupEditorOptions, notifySuccess, outerHtml, stripDiacritics, ToolButton, trimToEmpty, trimToNull, Widget } from "@serenity-is/corelib"; +import { Column } from "@serenity-is/sleekgrid"; +import { TranslationItem, TranslationService } from "../"; @Decorators.registerClass() export class TranslationGrid extends EntityGrid { @@ -55,7 +54,7 @@ export class TranslationGrid extends EntityGrid { return; } - confirm(localText('Db.Administration.Translation.OverrideConfirmation'), done); + confirmDialog(localText('Db.Administration.Translation.OverrideConfirmation'), done); return; } @@ -74,7 +73,7 @@ export class TranslationGrid extends EntityGrid { return; } - confirm(localText('Db.Administration.Translation.OverrideConfirmation'), done); + confirmDialog(localText('Db.Administration.Translation.OverrideConfirmation'), done); return; } } @@ -210,7 +209,7 @@ export class TranslationGrid extends EntityGrid { return true; } - var sd = Select2.util.stripDiacritics; + var sd = stripDiacritics; var searching = sd(this.searchText).toLowerCase(); function match(str: string) { diff --git a/src/Serene.Web/Modules/Administration/User/Authentication/UserAccessor.cs b/src/Serene.Web/Modules/Administration/User/Authentication/UserAccessor.cs deleted file mode 100644 index 0ace3fab..00000000 --- a/src/Serene.Web/Modules/Administration/User/Authentication/UserAccessor.cs +++ /dev/null @@ -1,27 +0,0 @@ -using Microsoft.AspNetCore.Http; -using System.Security.Claims; - -namespace Serene.AppServices; - -public class UserAccessor : IUserAccessor, IImpersonator -{ - private readonly ImpersonatingUserAccessor impersonator; - - public UserAccessor(IHttpContextAccessor httpContextAccessor) - { - impersonator = new ImpersonatingUserAccessor(new HttpContextUserAccessor(httpContextAccessor), - new HttpContextItemsAccessor(httpContextAccessor)); - } - - public ClaimsPrincipal User => impersonator.User; - - public void Impersonate(ClaimsPrincipal user) - { - impersonator.Impersonate(user); - } - - public void UndoImpersonate() - { - impersonator.UndoImpersonate(); - } -} \ No newline at end of file diff --git a/src/Serene.Web/Modules/Administration/User/UserDataScript.cs b/src/Serene.Web/Modules/Administration/User/UserDataScript.cs index 32e2db6c..f31a0b04 100644 --- a/src/Serene.Web/Modules/Administration/User/UserDataScript.cs +++ b/src/Serene.Web/Modules/Administration/User/UserDataScript.cs @@ -10,16 +10,16 @@ public class UserDataScript : DataScript { private readonly ITwoLevelCache cache; private readonly IPermissionService permissions; - private readonly ITypeSource typeSource; + private readonly IPermissionKeyLister permissionKeyLister; private readonly IUserAccessor userAccessor; private readonly IUserRetrieveService userRetriever; public UserDataScript(ITwoLevelCache cache, IPermissionService permissions, - ITypeSource typeSource, IUserAccessor userAccessor, IUserRetrieveService userRetriever) + IPermissionKeyLister permissionKeyLister, IUserAccessor userAccessor, IUserRetrieveService userRetriever) { this.cache = cache ?? throw new ArgumentNullException(nameof(cache)); this.permissions = permissions ?? throw new ArgumentNullException(nameof(permissions)); - this.typeSource = typeSource ?? throw new ArgumentNullException(nameof(typeSource)); + this.permissionKeyLister = permissionKeyLister ?? throw new ArgumentNullException(nameof(permissionKeyLister)); this.userAccessor = userAccessor ?? throw new ArgumentNullException(nameof(userAccessor)); this.userRetriever = userRetriever ?? throw new ArgumentNullException(nameof(userRetriever)); } @@ -46,8 +46,7 @@ protected override ScriptUserDefinition GetData() var permissionsUsedFromScript = cache.GetLocalStoreOnly("PermissionsUsedFromScript", TimeSpan.Zero, RoleRow.Fields.GenerationKey, () => { - return UserPermissionRepository.ListPermissionKeys( - cache, typeSource) + return permissionKeyLister.ListPermissionKeys(includeRoles: false) .Where(permissionKey => { // this sends permission information for all permission keys to client side. diff --git a/src/Serene.Web/Modules/Administration/UserPermission/PermissionCheckEditor.ts b/src/Serene.Web/Modules/Administration/UserPermission/PermissionCheckEditor.ts index 5a30d90d..3b2801ca 100644 --- a/src/Serene.Web/Modules/Administration/UserPermission/PermissionCheckEditor.ts +++ b/src/Serene.Web/Modules/Administration/UserPermission/PermissionCheckEditor.ts @@ -1,4 +1,4 @@ -import { DataGrid, Decorators, Dictionary, Fluent, GridUtils, Grouping, IGetEditValue, ISetEditValue, SlickFormatting, SlickTreeHelper, ToolButton, WidgetProps, any, count, getRemoteData, htmlEncode, localText, toGrouping, trimToNull, tryGetText, turkishLocaleCompare } from "@serenity-is/corelib"; +import { DataGrid, Decorators, Dictionary, Fluent, GridUtils, Grouping, IGetEditValue, ISetEditValue, SlickFormatting, SlickTreeHelper, ToolButton, WidgetProps, any, count, getRemoteData, htmlEncode, localText, stripDiacritics, toGrouping, trimToNull, tryGetText, turkishLocaleCompare } from "@serenity-is/corelib"; import { Column } from "@serenity-is/sleekgrid"; import { UserPermissionRow } from "../"; @@ -157,8 +157,8 @@ export class PermissionCheckEditor extends DataGrid= 0 || - Select2.util.stripDiacritics(item.Key || '').toLowerCase().indexOf(this.searchText) >= 0; + return stripDiacritics(item.Title || '').toLowerCase().indexOf(this.searchText) >= 0 || + stripDiacritics(item.Key || '').toLowerCase().indexOf(this.searchText) >= 0; } private getDescendants(item: PermissionCheckItem, excludeGroups: boolean): PermissionCheckItem[] { @@ -240,7 +240,7 @@ export class PermissionCheckEditor extends DataGrid { - this.searchText = Select2.util.stripDiacritics(trimToNull(text) || '').toLowerCase(); + this.searchText = stripDiacritics(trimToNull(text) || '').toLowerCase(); this.view.setItems(this.view.getItems(), true); }); } @@ -256,7 +256,7 @@ export class PermissionCheckEditor extends DataGrid> { - private readonly ITwoLevelCache cache; - private readonly ITypeSource typeSource; - - public PermissionKeysDataScript(ITwoLevelCache cache, ITypeSource typeSource) + private readonly IPermissionKeyLister permissionKeyLister; + + public PermissionKeysDataScript(IPermissionKeyLister permissionKeyLister) { GroupKey = RoleRow.Fields.GenerationKey; - this.cache = cache ?? throw new ArgumentNullException(nameof(cache)); - this.typeSource = typeSource ?? throw new ArgumentNullException(nameof(typeSource)); + this.permissionKeyLister = permissionKeyLister ?? throw new ArgumentNullException(nameof(permissionKeyLister)); } protected override IEnumerable GetData() { - return UserPermissionRepository.ListPermissionKeys(cache, typeSource); + return permissionKeyLister.ListPermissionKeys(includeRoles: false); } } \ No newline at end of file diff --git a/src/Serene.Web/Modules/Administration/UserPermission/UserPermissionEndpoint.cs b/src/Serene.Web/Modules/Administration/UserPermission/UserPermissionEndpoint.cs index 87328beb..2d22e96d 100644 --- a/src/Serene.Web/Modules/Administration/UserPermission/UserPermissionEndpoint.cs +++ b/src/Serene.Web/Modules/Administration/UserPermission/UserPermissionEndpoint.cs @@ -1,4 +1,4 @@ -using MyRepository = Serene.Administration.Repositories.UserPermissionRepository; +using MyRepository = Serene.Administration.Repositories.UserPermissionRepository; using MyRow = Serene.Administration.UserPermissionRow; namespace Serene.Administration.Endpoints; @@ -24,11 +24,11 @@ public ListResponse ListRolePermissions(IDbConnection connection, UserPe } public ListResponse ListPermissionKeys( - [FromServices] ITypeSource typeSource) + [FromServices] IPermissionKeyLister permissionKeyLister) { return new ListResponse { - Entities = MyRepository.ListPermissionKeys(Cache, typeSource).ToList() + Entities = permissionKeyLister.ListPermissionKeys(includeRoles: false).ToList() }; } } \ No newline at end of file diff --git a/src/Serene.Web/Modules/Administration/UserPermission/UserPermissionRepository.cs b/src/Serene.Web/Modules/Administration/UserPermission/UserPermissionRepository.cs index bc3b8069..78893687 100644 --- a/src/Serene.Web/Modules/Administration/UserPermission/UserPermissionRepository.cs +++ b/src/Serene.Web/Modules/Administration/UserPermission/UserPermissionRepository.cs @@ -128,100 +128,4 @@ public ListResponse ListRolePermissions(IDbConnection connection, UserPe Entities = connection.Query(query).ToList() }; } - - private static readonly string[] emptyPermissions = Array.Empty(); - private static readonly char[] splitChar = new char[] { '|', '&' }; - - private static string[] SplitPermissions(string permission) - { - if (string.IsNullOrEmpty(permission)) - return emptyPermissions; - - return permission.Split(splitChar, StringSplitOptions.RemoveEmptyEntries); - } - - private static void ProcessAttributes(HashSet hash, - MemberInfo member, Func getPermission) - where TAttr : Attribute - { - try - { - foreach (var attr in member.GetCustomAttributes(false)) - { - var permission = getPermission(attr); - hash.AddRange(SplitPermissions(permission)); - } - } - catch - { - // GetCustomAttributes might fail before .NET 4.6 - } - } - - private static void ProcessAttributes(HashSet hash, - Type member, Func getPermission) - where TAttr : Attribute - { - try - { - foreach (var attr in member.GetCustomAttributes(false)) - { - var permission = getPermission(attr); - hash.AddRange(SplitPermissions(permission)); - } - } - catch - { - // GetCustomAttributes might fail before .NET 4.6 - } - } - - public static IEnumerable ListPermissionKeys(ITwoLevelCache cache, - ITypeSource typeSource, bool includeRoles = false) - { - if (typeSource is null) - throw new ArgumentNullException(nameof(typeSource)); - - return cache.GetLocalStoreOnly("Administration:PermissionKeys:" + - (includeRoles ? "IR" : "XR"), TimeSpan.Zero, RoleRow.Fields.GenerationKey, () => - { - var result = new HashSet(StringComparer.OrdinalIgnoreCase); - - result.AddRange(NestedPermissionKeyRegistration.AddNestedPermissions(registry: null, typeSource)); - - foreach (var attr in typeSource.GetAssemblyAttributes()) - if (!attr.Permission.IsEmptyOrNull()) - result.AddRange(SplitPermissions(attr.Permission)); - - foreach (var type in typeSource.GetTypes()) - { - ProcessAttributes(result, type, x => x.Permission); - ProcessAttributes(result, type, x => x.Permission); - ProcessAttributes(result, type, x => x.Permission); - - foreach (var member in type.GetMethods(BindingFlags.Instance | BindingFlags.Public)) - { - ProcessAttributes(result, member, x => x.Permission); - ProcessAttributes(result, member, x => x.Permission); - ProcessAttributes(result, member, x => x.Permission); - } - - foreach (var member in type.GetProperties(BindingFlags.Instance | BindingFlags.Public)) - if (member.GetIndexParameters().Length == 0) - ProcessAttributes(result, member, x => x.Permission); - } - - result.Remove("ImpersonateAs"); - result.Remove("*"); - result.Remove("?"); - - foreach (var perm in result.Where(x => - x.StartsWith("Role:", StringComparison.OrdinalIgnoreCase)).ToList()) - { - result.Remove(perm); - } - - return result; - }); - } } \ No newline at end of file diff --git a/src/Serene.Web/Modules/Administration/UserRole/RoleCheckEditor.ts b/src/Serene.Web/Modules/Administration/UserRole/RoleCheckEditor.ts index 828bc530..d9435549 100644 --- a/src/Serene.Web/Modules/Administration/UserRole/RoleCheckEditor.ts +++ b/src/Serene.Web/Modules/Administration/UserRole/RoleCheckEditor.ts @@ -1,4 +1,4 @@ -import { CheckTreeEditor, CheckTreeItem, Decorators, GridUtils } from "@serenity-is/corelib"; +import { CheckTreeEditor, CheckTreeItem, Decorators, GridUtils, stripDiacritics } from "@serenity-is/corelib"; import { isEmptyOrNull } from "@serenity-is/corelib"; import { RoleRow } from "../"; @@ -15,7 +15,7 @@ export class RoleCheckEditor extends CheckTreeEditor, any> { super.createToolbarExtensions(); GridUtils.addQuickSearchInputCustom(this.toolbar.element, (field, text) => { - this.searchText = Select2.util.stripDiacritics(text || '').toUpperCase(); + this.searchText = stripDiacritics(text || '').toUpperCase(); this.view.setItems(this.view.getItems(), true); }); } @@ -34,7 +34,7 @@ export class RoleCheckEditor extends CheckTreeEditor, any> { protected onViewFilter(item) { return super.onViewFilter(item) && (isEmptyOrNull(this.searchText) || - Select2.util.stripDiacritics(item.text || '') + stripDiacritics(item.text || '') .toUpperCase().indexOf(this.searchText) >= 0); } } diff --git a/src/Serene.Web/Initialization/IDataMigrations.cs b/src/Serene.Web/Modules/Common/AppServices/Abstractions/IDataMigrations.cs similarity index 93% rename from src/Serene.Web/Initialization/IDataMigrations.cs rename to src/Serene.Web/Modules/Common/AppServices/Abstractions/IDataMigrations.cs index 6ae36278..6281fe90 100644 --- a/src/Serene.Web/Initialization/IDataMigrations.cs +++ b/src/Serene.Web/Modules/Common/AppServices/Abstractions/IDataMigrations.cs @@ -1,6 +1,6 @@ -namespace Serene; - -public interface IDataMigrations -{ - void Initialize(); +namespace Serene; + +public interface IDataMigrations +{ + void Initialize(); } \ No newline at end of file diff --git a/src/Serene.Web/Modules/Administration/User/Authentication/IDirectoryService.cs b/src/Serene.Web/Modules/Common/AppServices/Abstractions/IDirectoryService.cs similarity index 97% rename from src/Serene.Web/Modules/Administration/User/Authentication/IDirectoryService.cs rename to src/Serene.Web/Modules/Common/AppServices/Abstractions/IDirectoryService.cs index ec43394c..e08cf723 100644 --- a/src/Serene.Web/Modules/Administration/User/Authentication/IDirectoryService.cs +++ b/src/Serene.Web/Modules/Common/AppServices/Abstractions/IDirectoryService.cs @@ -1,4 +1,4 @@ - + namespace Serene; public interface IDirectoryService diff --git a/src/Serene.Web/Initialization/DataMigrations.cs b/src/Serene.Web/Modules/Common/AppServices/DataMigrations.cs similarity index 80% rename from src/Serene.Web/Initialization/DataMigrations.cs rename to src/Serene.Web/Modules/Common/AppServices/DataMigrations.cs index e86d49a2..2414b057 100644 --- a/src/Serene.Web/Initialization/DataMigrations.cs +++ b/src/Serene.Web/Modules/Common/AppServices/DataMigrations.cs @@ -9,27 +9,20 @@ namespace Serene.AppServices; -public class DataMigrations : IDataMigrations +public class DataMigrations(ITypeSource typeSource, + ISqlConnections sqlConnections, + IWebHostEnvironment hostEnvironment) : IDataMigrations { - private static readonly string[] databaseKeys = new[] { - "Default" + private static readonly string[] databaseKeys = [ + "Default" #if (Northwind) - , "Northwind" + , "Northwind" #endif -}; + ]; - private readonly ITypeSource typeSource; - private readonly ISqlConnections sqlConnections; - private readonly IWebHostEnvironment hostEnvironment; - - public DataMigrations(ITypeSource typeSource, - ISqlConnections sqlConnections, - IWebHostEnvironment hostEnvironment) - { - this.typeSource = typeSource ?? throw new ArgumentNullException(nameof(typeSource)); - this.sqlConnections = sqlConnections ?? throw new ArgumentNullException(nameof(sqlConnections)); - this.hostEnvironment = hostEnvironment ?? throw new ArgumentNullException(nameof(hostEnvironment)); - } + private readonly ITypeSource typeSource = typeSource ?? throw new ArgumentNullException(nameof(typeSource)); + private readonly ISqlConnections sqlConnections = sqlConnections ?? throw new ArgumentNullException(nameof(sqlConnections)); + private readonly IWebHostEnvironment hostEnvironment = hostEnvironment ?? throw new ArgumentNullException(nameof(hostEnvironment)); public void Initialize() { @@ -46,14 +39,14 @@ public void Initialize() /// private void EnsureDatabase(string databaseKey) { - MigrationUtils.EnsureDatabase(databaseKey, + MigrationUtils.EnsureDatabase(databaseKey, hostEnvironment.ContentRootPath, sqlConnections); Microsoft.Data.SqlClient.SqlConnection.ClearAllPools(); } private void RunMigrations(string databaseKey) { - var cs = sqlConnections.TryGetConnectionString(databaseKey) ?? + var cs = sqlConnections.TryGetConnectionString(databaseKey) ?? throw new ArgumentOutOfRangeException(nameof(databaseKey)); string serverType = cs.Dialect.ServerType; bool isOracle = serverType.StartsWith("Oracle", StringComparison.OrdinalIgnoreCase); @@ -74,7 +67,7 @@ private void RunMigrations(string databaseKey) }) .Configure(options => { - options.Tags = new[] { databaseKey + "DB" }; + options.Tags = [databaseKey + "DB"]; options.IncludeUntaggedMigrations = databaseKey == "Default"; }) .ConfigureRunner(builder => diff --git a/src/Serene.Web/Modules/Administration/User/Authentication/DirectoryEntry.cs b/src/Serene.Web/Modules/Common/AppServices/Models/DirectoryEntry.cs similarity index 98% rename from src/Serene.Web/Modules/Administration/User/Authentication/DirectoryEntry.cs rename to src/Serene.Web/Modules/Common/AppServices/Models/DirectoryEntry.cs index a651af72..ed495790 100644 --- a/src/Serene.Web/Modules/Administration/User/Authentication/DirectoryEntry.cs +++ b/src/Serene.Web/Modules/Common/AppServices/Models/DirectoryEntry.cs @@ -1,4 +1,4 @@ - + namespace Serene.AppServices; public class DirectoryEntry diff --git a/src/Serene.Web/Modules/Administration/User/Authentication/ScriptUserDefinition.cs b/src/Serene.Web/Modules/Common/AppServices/Models/ScriptUserDefinition.cs similarity index 97% rename from src/Serene.Web/Modules/Administration/User/Authentication/ScriptUserDefinition.cs rename to src/Serene.Web/Modules/Common/AppServices/Models/ScriptUserDefinition.cs index 2088fc2c..59e44dc7 100644 --- a/src/Serene.Web/Modules/Administration/User/Authentication/ScriptUserDefinition.cs +++ b/src/Serene.Web/Modules/Common/AppServices/Models/ScriptUserDefinition.cs @@ -1,14 +1,14 @@ -namespace Serene; - -/// -/// This data will be available from script code using a dynamic script. -/// Add properties you need from script code and set them in UserEndpoint.GetUserData. -/// -[ScriptInclude] -public class ScriptUserDefinition -{ - public string Username { get; set; } - public string DisplayName { get; set; } - public bool IsAdmin { get; set; } - public Dictionary Permissions { get; set; } +namespace Serene; + +/// +/// This data will be available from script code using a dynamic script. +/// Add properties you need from script code and set them in UserEndpoint.GetUserData. +/// +[ScriptInclude] +public class ScriptUserDefinition +{ + public string Username { get; set; } + public string DisplayName { get; set; } + public bool IsAdmin { get; set; } + public Dictionary Permissions { get; set; } } \ No newline at end of file diff --git a/src/Serene.Web/Modules/Administration/User/Authentication/UserDefinition.cs b/src/Serene.Web/Modules/Common/AppServices/Models/UserDefinition.cs similarity index 76% rename from src/Serene.Web/Modules/Administration/User/Authentication/UserDefinition.cs rename to src/Serene.Web/Modules/Common/AppServices/Models/UserDefinition.cs index bef81879..5d9fd30f 100644 --- a/src/Serene.Web/Modules/Administration/User/Authentication/UserDefinition.cs +++ b/src/Serene.Web/Modules/Common/AppServices/Models/UserDefinition.cs @@ -1,18 +1,21 @@ -namespace Serene; - -[Serializable] -public class UserDefinition : IUserDefinition -{ - public string Id { get { return UserId.ToInvariant(); } } - public string DisplayName { get; set; } - public string Email { get; set; } - public string UserImage { get; set; } - public short IsActive { get; set; } - public int UserId { get; set; } - public string Username { get; set; } - public string PasswordHash { get; set; } - public string PasswordSalt { get; set; } - public string Source { get; set; } - public DateTime? UpdateDate { get; set; } - public DateTime? LastDirectoryUpdate { get; set; } +using Serene.Administration; + +namespace Serene; + +[Serializable] +public class UserDefinition : IUserDefinition, IHasPassword +{ + public string Id { get { return UserId.ToInvariant(); } } + public string DisplayName { get; set; } + public string Email { get; set; } + public string UserImage { get; set; } + public short IsActive { get; set; } + public int UserId { get; set; } + public string Username { get; set; } + public string PasswordHash { get; set; } + public string PasswordSalt { get; set; } + public string Source { get; set; } + public DateTime? UpdateDate { get; set; } + public DateTime? LastDirectoryUpdate { get; set; } + public bool HasPassword => PasswordSalt != "unassigned"; } \ No newline at end of file diff --git a/src/Serene.Web/Modules/Common/AppServices/PermissionKeyLister.cs b/src/Serene.Web/Modules/Common/AppServices/PermissionKeyLister.cs new file mode 100644 index 00000000..7d3206b3 --- /dev/null +++ b/src/Serene.Web/Modules/Common/AppServices/PermissionKeyLister.cs @@ -0,0 +1,106 @@ + +using Serenity.Localization; +using Serene.Administration; +using System.Reflection; + +namespace Serene.AppServices; + +public class PermissionKeyLister(ISqlConnections sqlConnections, ITwoLevelCache cache, ITypeSource typeSource) : IPermissionKeyLister +{ + private readonly ISqlConnections sqlConnections = sqlConnections ?? throw new ArgumentNullException(nameof(sqlConnections)); + private readonly ITwoLevelCache cache = cache ?? throw new ArgumentNullException(nameof(cache)); + private readonly ITypeSource typeSource = typeSource ?? throw new ArgumentNullException(nameof(typeSource)); + + public IEnumerable ListPermissionKeys(bool includeRoles) + { + + return cache.GetLocalStoreOnly("Administration:PermissionKeys:" + + (includeRoles ? "IR" : "XR"), TimeSpan.Zero, RoleRow.Fields.GenerationKey, () => + { + var result = new HashSet(StringComparer.OrdinalIgnoreCase); + + result.AddRange(NestedPermissionKeyRegistration.AddNestedPermissions(registry: null, typeSource)); + + foreach (var attr in typeSource.GetAssemblyAttributes()) + if (!string.IsNullOrEmpty(attr.Permission)) + result.AddRange(SplitPermissions(attr.Permission)); + + foreach (var type in typeSource.GetTypes()) + { + ProcessAttributes(result, type, x => x.Permission); + ProcessAttributes(result, type, x => x.Permission); + ProcessAttributes(result, type, x => x.Permission); + + foreach (var member in type.GetMethods(BindingFlags.Instance | BindingFlags.Public)) + { + ProcessAttributes(result, member, x => x.Permission); + ProcessAttributes(result, member, x => x.Permission); + ProcessAttributes(result, member, x => x.Permission); + } + + foreach (var member in type.GetProperties(BindingFlags.Instance | BindingFlags.Public)) + if (member.GetIndexParameters().Length == 0) + ProcessAttributes(result, member, x => x.Permission); + } + + result.Remove("ImpersonateAs"); + result.Remove("*"); + result.Remove("?"); + + foreach (var perm in result.Where(x => + x.StartsWith("Role:", StringComparison.OrdinalIgnoreCase)).ToList()) + { + result.Remove(perm); + } + + return result; + }); + } + + private static readonly string[] emptyPermissions = []; + private static readonly char[] splitChar = ['|', '&']; + + private static string[] SplitPermissions(string permission) + { + if (string.IsNullOrEmpty(permission)) + return emptyPermissions; + + return permission.Split(splitChar, StringSplitOptions.RemoveEmptyEntries); + } + + private static void ProcessAttributes(HashSet hash, + MemberInfo member, Func getPermission) + where TAttr : Attribute + { + try + { + foreach (var attr in member.GetCustomAttributes(false)) + { + var permission = getPermission(attr); + hash.AddRange(SplitPermissions(permission)); + } + } + catch + { + // GetCustomAttributes might fail before .NET 4.6 + } + } + + private static void ProcessAttributes(HashSet hash, + Type member, Func getPermission) + where TAttr : Attribute + { + try + { + foreach (var attr in member.GetCustomAttributes(false)) + { + var permission = getPermission(attr); + hash.AddRange(SplitPermissions(permission)); + } + } + catch + { + // GetCustomAttributes might fail before .NET 4.6 + } + } +} \ No newline at end of file diff --git a/src/Serene.Web/Modules/Administration/User/Authentication/PermissionService.cs b/src/Serene.Web/Modules/Common/AppServices/PermissionService.cs similarity index 69% rename from src/Serene.Web/Modules/Administration/User/Authentication/PermissionService.cs rename to src/Serene.Web/Modules/Common/AppServices/PermissionService.cs index 0fa5b0c6..0c0e2629 100644 --- a/src/Serene.Web/Modules/Administration/User/Authentication/PermissionService.cs +++ b/src/Serene.Web/Modules/Common/AppServices/PermissionService.cs @@ -1,37 +1,30 @@ -using Microsoft.Extensions.Caching.Memory; -using Serene.Administration; -using System.Globalization; +using Microsoft.Extensions.Caching.Memory; +using Serene.Administration; +using System.Globalization; using System.Reflection; namespace Serene.AppServices; -public class PermissionService : IPermissionService +public class PermissionService(ITwoLevelCache cache, + ISqlConnections sqlConnections, + ITypeSource typeSource, + IUserAccessor userAccessor, + IRolePermissionService rolePermissions, + IHttpContextItemsAccessor httpContextItemsAccessor = null) : IPermissionService, ITransientGrantor { - private readonly ITwoLevelCache cache; - private readonly IRolePermissionService rolePermissions; - private readonly ISqlConnections sqlConnections; - private readonly ITypeSource typeSource; - private readonly IUserAccessor userAccessor; - - public PermissionService(ITwoLevelCache cache, - ISqlConnections sqlConnections, - ITypeSource typeSource, - IUserAccessor userAccessor, - IRolePermissionService rolePermissions) - { - this.cache = cache ?? throw new ArgumentNullException(nameof(cache)); - this.sqlConnections = sqlConnections ?? throw new ArgumentNullException(nameof(sqlConnections)); - this.typeSource = typeSource ?? throw new ArgumentNullException(nameof(typeSource)); - this.userAccessor = userAccessor ?? throw new ArgumentNullException(nameof(userAccessor)); - this.rolePermissions = rolePermissions ?? throw new ArgumentNullException(nameof(rolePermissions)); - } + private readonly ITwoLevelCache cache = cache ?? throw new ArgumentNullException(nameof(cache)); + private readonly IRolePermissionService rolePermissions = rolePermissions ?? throw new ArgumentNullException(nameof(rolePermissions)); + private readonly ISqlConnections sqlConnections = sqlConnections ?? throw new ArgumentNullException(nameof(sqlConnections)); + private readonly ITypeSource typeSource = typeSource ?? throw new ArgumentNullException(nameof(typeSource)); + private readonly IUserAccessor userAccessor = userAccessor ?? throw new ArgumentNullException(nameof(userAccessor)); + private readonly TransientGrantingPermissionService transientGrantor = new(permissionService: null, httpContextItemsAccessor); public bool HasPermission(string permission) { if (string.IsNullOrEmpty(permission)) return false; - if (permission == "*") + if (permission == "*" || transientGrantor.HasPermission(permission)) return true; var isLoggedIn = userAccessor.IsLoggedIn(); @@ -79,7 +72,7 @@ private Dictionary GetUserPermissions(int userId) .Where(new Criteria(fld.UserId) == userId)) .ForEach(x => result[x.PermissionKey] = x.Granted ?? true); - var implicitPermissions = GetImplicitPermissions(cache.Memory, typeSource); + var implicitPermissions = PermissionService.GetImplicitPermissions(cache.Memory, typeSource); foreach (var pair in result.ToArray()) { if (pair.Value && implicitPermissions.TryGetValue(pair.Key, out HashSet list)) @@ -109,53 +102,76 @@ private HashSet GetUserRoles(int userId) }); } - public static IDictionary> GetImplicitPermissions( - IMemoryCache memoryCache, ITypeSource typeSource) - { - if (memoryCache is null) - throw new ArgumentNullException(nameof(memoryCache)); - - if (typeSource is null) - throw new ArgumentNullException(nameof(typeSource)); - - return memoryCache.Get>>("ImplicitPermissions", TimeSpan.Zero, () => - { - var result = new Dictionary>(StringComparer.OrdinalIgnoreCase); - - void addFrom(Type type) - { - foreach (var member in type.GetFields(BindingFlags.Static | BindingFlags.DeclaredOnly | - BindingFlags.Public | BindingFlags.NonPublic)) - { - if (member.FieldType != typeof(string)) - continue; - - if (member.GetValue(null) is not string key) - continue; - - foreach (var attr in member.GetCustomAttributes()) - { - if (!result.TryGetValue(key, out HashSet list)) - { - list = new HashSet(StringComparer.OrdinalIgnoreCase); - result[key] = list; - } - - list.Add(attr.Value); - } - } - - foreach (var nested in type.GetNestedTypes(BindingFlags.Public | BindingFlags.DeclaredOnly)) - addFrom(nested); - } - - foreach (var type in typeSource.GetTypesWithAttribute( - typeof(NestedPermissionKeysAttribute))) - { - addFrom(type); - } - - return result; - }); - } + public static IDictionary> GetImplicitPermissions(IMemoryCache memoryCache, + ITypeSource typeSource) + { + ArgumentNullException.ThrowIfNull(memoryCache); + + ArgumentNullException.ThrowIfNull(typeSource); + + return memoryCache.Get>>("ImplicitPermissions", TimeSpan.Zero, () => + { + var result = new Dictionary>(StringComparer.OrdinalIgnoreCase); + + void addFrom(Type type) + { + foreach (var member in type.GetFields(BindingFlags.Static | BindingFlags.DeclaredOnly | + BindingFlags.Public | BindingFlags.NonPublic)) + { + if (member.FieldType != typeof(string)) + continue; + + if (member.GetValue(null) is not string key) + continue; + + foreach (var attr in member.GetCustomAttributes()) + { + if (!result.TryGetValue(key, out HashSet list)) + { + list = new HashSet(StringComparer.OrdinalIgnoreCase); + result[key] = list; + } + + list.Add(attr.Value); + } + } + + foreach (var nested in type.GetNestedTypes(BindingFlags.Public | BindingFlags.DeclaredOnly)) + addFrom(nested); + } + + foreach (var type in typeSource.GetTypesWithAttribute( + typeof(NestedPermissionKeysAttribute))) + { + addFrom(type); + } + + return result; + }); + } + + /// + public void Grant(params string[] permissions) + { + transientGrantor.Grant(permissions); + } + + /// + public void GrantAll() + { + transientGrantor.GrantAll(); + } + + /// + public void UndoGrant() + { + transientGrantor.UndoGrant(); + } + + /// + public bool IsAllGranted() => transientGrantor.IsAllGranted(); + + /// + public IEnumerable GetGranted() => transientGrantor.GetGranted(); + } \ No newline at end of file diff --git a/src/Serene.Web/Modules/Administration/User/Authentication/RolePermissionService.cs b/src/Serene.Web/Modules/Common/AppServices/RolePermissionService.cs similarity index 55% rename from src/Serene.Web/Modules/Administration/User/Authentication/RolePermissionService.cs rename to src/Serene.Web/Modules/Common/AppServices/RolePermissionService.cs index 91777654..eb2ab0b9 100644 --- a/src/Serene.Web/Modules/Administration/User/Authentication/RolePermissionService.cs +++ b/src/Serene.Web/Modules/Common/AppServices/RolePermissionService.cs @@ -2,28 +2,21 @@ namespace Serene.AppServices; -public class RolePermissionService : IRolePermissionService +public class RolePermissionService(ITwoLevelCache cache, ISqlConnections sqlConnections, + ITypeSource typeSource) : IRolePermissionService { - private readonly ITwoLevelCache cache; - private readonly ISqlConnections sqlConnections; - private readonly ITypeSource typeSource; - - public RolePermissionService(ITwoLevelCache cache, ISqlConnections sqlConnections, - ITypeSource typeSource) - { - this.cache = cache ?? throw new ArgumentNullException(nameof(cache)); - this.sqlConnections = sqlConnections ?? throw new ArgumentNullException(nameof(sqlConnections)); - this.typeSource = typeSource ?? throw new ArgumentNullException(nameof(typeSource)); - } + private readonly ITwoLevelCache cache = cache ?? throw new ArgumentNullException(nameof(cache)); + private readonly ISqlConnections sqlConnections = sqlConnections ?? throw new ArgumentNullException(nameof(sqlConnections)); + private readonly ITypeSource typeSource = typeSource ?? throw new ArgumentNullException(nameof(typeSource)); public bool HasPermission(string role, string permission) { return GetRolePermissions(role).Contains(permission); } - private ISet GetRolePermissions(string role) + private HashSet GetRolePermissions(string role) { - if (role == null) throw new ArgumentNullException(nameof(role)); + ArgumentNullException.ThrowIfNull(role); var fld = RolePermissionRow.Fields; @@ -39,7 +32,7 @@ private ISet GetRolePermissions(string role) result.Add("Role:" + role); - var implicitPermissions = PermissionService.GetImplicitPermissions(cache.Memory, typeSource); + var implicitPermissions = AppServices.PermissionService.GetImplicitPermissions(cache.Memory, typeSource); foreach (var key in result.ToArray()) { if (implicitPermissions.TryGetValue(key, out HashSet list)) diff --git a/src/Serene.Web/Initialization/TypeSource.cs b/src/Serene.Web/Modules/Common/AppServices/TypeSource.cs similarity index 93% rename from src/Serene.Web/Initialization/TypeSource.cs rename to src/Serene.Web/Modules/Common/AppServices/TypeSource.cs index 144cb453..8b0f9342 100644 --- a/src/Serene.Web/Initialization/TypeSource.cs +++ b/src/Serene.Web/Modules/Common/AppServices/TypeSource.cs @@ -12,8 +12,8 @@ public TypeSource() private static Assembly[] GetAssemblyList() { - return new Assembly[] - { + return + [ typeof(LocalTextRegistry).Assembly, typeof(ISqlConnections).Assembly, typeof(IRow).Assembly, @@ -27,6 +27,6 @@ private static Assembly[] GetAssemblyList() typeof(Serenity.Demo.BasicSamples.BasicSamplesPage).Assembly, #endif typeof(Startup).Assembly - }; + ]; } } \ No newline at end of file diff --git a/src/Serene.Web/Modules/Common/AppServices/UserAccessor.cs b/src/Serene.Web/Modules/Common/AppServices/UserAccessor.cs new file mode 100644 index 00000000..3623b28f --- /dev/null +++ b/src/Serene.Web/Modules/Common/AppServices/UserAccessor.cs @@ -0,0 +1,23 @@ +using Microsoft.AspNetCore.Http; +using System.Security.Claims; + +namespace Serene.AppServices; + +public class UserAccessor(IHttpContextAccessor httpContextAccessor) : IUserAccessor, IImpersonator +{ + private readonly ImpersonatingUserAccessor impersonator = new( + new HttpContextUserAccessor(httpContextAccessor), + new HttpContextItemsAccessor(httpContextAccessor)); + + public ClaimsPrincipal User => impersonator.User; + + public void Impersonate(ClaimsPrincipal user) + { + impersonator.Impersonate(user); + } + + public void UndoImpersonate() + { + impersonator.UndoImpersonate(); + } +} \ No newline at end of file diff --git a/src/Serene.Web/Initialization/UserCultureProvider.cs b/src/Serene.Web/Modules/Common/AppServices/UserCultureProvider.cs similarity index 96% rename from src/Serene.Web/Initialization/UserCultureProvider.cs rename to src/Serene.Web/Modules/Common/AppServices/UserCultureProvider.cs index 9469d0c9..e52f414d 100644 --- a/src/Serene.Web/Initialization/UserCultureProvider.cs +++ b/src/Serene.Web/Modules/Common/AppServices/UserCultureProvider.cs @@ -1,67 +1,67 @@ -using Microsoft.AspNetCore.Http; -using Microsoft.AspNetCore.Localization; -using System.Globalization; -using System.Threading.Tasks; - -namespace Serene.AppServices; - -public class UserCultureProvider : RequestCultureProvider -{ - public override Task DetermineProviderCultureResult(HttpContext httpContext) - { - var culture = httpContext.Request.Cookies["LanguagePreference"]; +using Microsoft.AspNetCore.Http; +using Microsoft.AspNetCore.Localization; +using System.Globalization; +using System.Threading.Tasks; + +namespace Serene.AppServices; + +public class UserCultureProvider : RequestCultureProvider +{ + public override Task DetermineProviderCultureResult(HttpContext httpContext) + { + var culture = httpContext.Request.Cookies["LanguagePreference"]; if (string.IsNullOrEmpty(culture) || culture.Length > 5) return NullProviderCultureResult; - - if (culture.Length == 2) - { - if (TwoLetterToFourLetter.TryGetValue(culture, out string code)) - culture = code; - else - culture = culture + "-" + culture.ToUpperInvariant(); - } - - return Task.FromResult(new ProviderCultureResult(culture)); + + if (culture.Length == 2) + { + if (TwoLetterToFourLetter.TryGetValue(culture, out string code)) + culture = code; + else + culture = culture + "-" + culture.ToUpperInvariant(); + } + + return Task.FromResult(new ProviderCultureResult(culture)); } private static readonly Dictionary TwoLetterToFourLetter = - new(StringComparer.OrdinalIgnoreCase) - { - { "en", "en-US" }, + new(StringComparer.OrdinalIgnoreCase) + { + { "en", "en-US" }, { "zh", "zh-CN" }, - { "vi", "vi-VN" }, + { "vi", "vi-VN" }, { "fa", "fa-IR" } - }; - - private static List supportedCultures; + }; + + private static List supportedCultures; private static readonly string[] supportedCultureIdentifiers = new string[] { - "de-DE", - "en-US", - "en-GB", - "es-ES", - "fa-IR", - "it-IT", - "pt-PT", - "pt-BR", - "ru-RU", - "tr-TR", - "vi-VN", + "de-DE", + "en-US", + "en-GB", + "es-ES", + "fa-IR", + "it-IT", + "pt-PT", + "pt-BR", + "ru-RU", + "tr-TR", + "vi-VN", "zh-CN" }; - public static IList SupportedCultures - { - get => supportedCultures ??= supportedCultureIdentifiers.Select(x => - { - try - { - return new CultureInfo(x); - } - catch - { - return null; - } - }).Where(x => x != null).ToList(); - } + public static IList SupportedCultures + { + get => supportedCultures ??= supportedCultureIdentifiers.Select(x => + { + try + { + return new CultureInfo(x); + } + catch + { + return null; + } + }).Where(x => x != null).ToList(); + } } \ No newline at end of file diff --git a/src/Serene.Web/Modules/Administration/User/Authentication/UserPasswordValidator.cs b/src/Serene.Web/Modules/Common/AppServices/UserPasswordValidator.cs similarity index 85% rename from src/Serene.Web/Modules/Administration/User/Authentication/UserPasswordValidator.cs rename to src/Serene.Web/Modules/Common/AppServices/UserPasswordValidator.cs index 038db7fb..51a655bc 100644 --- a/src/Serene.Web/Modules/Administration/User/Authentication/UserPasswordValidator.cs +++ b/src/Serene.Web/Modules/Common/AppServices/UserPasswordValidator.cs @@ -1,32 +1,23 @@ -using Microsoft.Extensions.Logging; +using Microsoft.Extensions.Logging; using Serene.Administration; namespace Serene.AppServices; -public class UserPasswordValidator : IUserPasswordValidator +public class UserPasswordValidator(ITwoLevelCache cache, ISqlConnections sqlConnections, IUserRetrieveService userRetriever, + ILogger log = null, IDirectoryService directoryService = null) : IUserPasswordValidator { - public UserPasswordValidator(ITwoLevelCache cache, ISqlConnections sqlConnections, IUserRetrieveService userRetriever, - ILogger log = null, IDirectoryService directoryService = null) - { - Cache = cache ?? throw new ArgumentNullException(nameof(cache)); - SqlConnections = sqlConnections ?? throw new ArgumentNullException(nameof(sqlConnections)); - UserRetriever = userRetriever ?? throw new ArgumentNullException(nameof(userRetriever)); - DirectoryService = directoryService; - Log = log; - } - - protected ITwoLevelCache Cache { get; } - public ISqlConnections SqlConnections { get; } - protected IUserRetrieveService UserRetriever { get; } - protected IDirectoryService DirectoryService { get; } - protected ILogger Log { get; } + protected ITwoLevelCache Cache { get; } = cache ?? throw new ArgumentNullException(nameof(cache)); + public ISqlConnections SqlConnections { get; } = sqlConnections ?? throw new ArgumentNullException(nameof(sqlConnections)); + protected IUserRetrieveService UserRetriever { get; } = userRetriever ?? throw new ArgumentNullException(nameof(userRetriever)); + protected IDirectoryService DirectoryService { get; } = directoryService; + protected ILogger Log { get; } = log; public PasswordValidationResult Validate(ref string username, string password) { - if (username.IsTrimmedEmpty()) + if (string.IsNullOrWhiteSpace(username)) return PasswordValidationResult.EmptyUsername; - if (password.IsEmptyOrNull()) + if (string.IsNullOrEmpty(password)) return PasswordValidationResult.EmptyPassword; username = username.TrimToEmpty(); @@ -96,7 +87,7 @@ bool validatePassword() => UserHelper.CalculateHash(password, user.PasswordSalt) Log?.LogError(ex, "Error on directory access"); // couldn't access directory. allow user to login with cached password - if (!user.PasswordHash.IsTrimmedEmpty()) + if (!string.IsNullOrWhiteSpace(user.PasswordHash)) { if (validatePassword()) { diff --git a/src/Serene.Web/Modules/Administration/User/Authentication/UserRetrieveService.cs b/src/Serene.Web/Modules/Common/AppServices/UserRetrieveService.cs similarity index 82% rename from src/Serene.Web/Modules/Administration/User/Authentication/UserRetrieveService.cs rename to src/Serene.Web/Modules/Common/AppServices/UserRetrieveService.cs index 766d0109..865c948b 100644 --- a/src/Serene.Web/Modules/Administration/User/Authentication/UserRetrieveService.cs +++ b/src/Serene.Web/Modules/Common/AppServices/UserRetrieveService.cs @@ -1,71 +1,65 @@ -using System.Globalization; -using MyRow = Serene.Administration.UserRow; - -namespace Serene.AppServices; - -public class UserRetrieveService : IUserRetrieveService -{ - private static MyRow.RowFields Fld { get { return MyRow.Fields; } } - - protected ITwoLevelCache Cache { get; } - protected ISqlConnections SqlConnections { get; } - - public UserRetrieveService(ITwoLevelCache cache, ISqlConnections sqlConnections) - { - Cache = cache; - SqlConnections = sqlConnections; - } - - private static UserDefinition GetFirst(IDbConnection connection, BaseCriteria criteria) - { - var user = connection.TrySingle(criteria); - if (user != null) - return new UserDefinition - { - UserId = user.UserId.Value, - Username = user.Username, - Email = user.Email, - UserImage = user.UserImage, - DisplayName = user.DisplayName, - IsActive = user.IsActive.Value, - Source = user.Source, - PasswordHash = user.PasswordHash, - PasswordSalt = user.PasswordSalt, - UpdateDate = user.UpdateDate, - LastDirectoryUpdate = user.LastDirectoryUpdate - }; - - return null; - } - - public IUserDefinition ById(string id) - { - return Cache.Get("UserByID_" + id, TimeSpan.Zero, TimeSpan.FromDays(1), Fld.GenerationKey, () => - { - using var connection = SqlConnections.NewByKey("Default"); - return GetFirst(connection, new Criteria(Fld.UserId) == int.Parse(id, CultureInfo.InvariantCulture)); - }); - } - - public IUserDefinition ByUsername(string username) - { - if (username.IsEmptyOrNull()) - return null; - - return Cache.Get("UserByName_" + username.ToLowerInvariant(), - TimeSpan.Zero, TimeSpan.FromDays(1), Fld.GenerationKey, () => - { - using var connection = SqlConnections.NewByKey("Default"); - return GetFirst(connection, new Criteria(Fld.Username) == username); - }); - } - - public static void RemoveCachedUser(ITwoLevelCache cache, int? userId, string username) - { - if (userId != null) - cache.Remove("UserByID_" + userId); - - if (username != null) - cache.Remove("UserByName_" + username.ToLowerInvariant()); - } +using System.Globalization; +using MyRow = Serene.Administration.UserRow; + +namespace Serene.AppServices; + +public class UserRetrieveService(ITwoLevelCache cache, ISqlConnections sqlConnections) : IUserRetrieveService +{ + private static MyRow.RowFields Fld { get { return MyRow.Fields; } } + + protected ITwoLevelCache Cache { get; } = cache; + protected ISqlConnections SqlConnections { get; } = sqlConnections; + + private static UserDefinition GetFirst(IDbConnection connection, BaseCriteria criteria) + { + var user = connection.TrySingle(criteria); + if (user != null) + return new UserDefinition + { + UserId = user.UserId.Value, + Username = user.Username, + Email = user.Email, + UserImage = user.UserImage, + DisplayName = user.DisplayName, + IsActive = user.IsActive.Value, + Source = user.Source, + PasswordHash = user.PasswordHash, + PasswordSalt = user.PasswordSalt, + UpdateDate = user.UpdateDate, + LastDirectoryUpdate = user.LastDirectoryUpdate + }; + + return null; + } + + public IUserDefinition ById(string id) + { + return Cache.Get("UserByID_" + id, TimeSpan.Zero, TimeSpan.FromDays(1), Fld.GenerationKey, () => + { + using var connection = SqlConnections.NewByKey("Default"); + return GetFirst(connection, new Criteria(Fld.UserId) == int.Parse(id, CultureInfo.InvariantCulture)); + }); + } + + public IUserDefinition ByUsername(string username) + { + if (string.IsNullOrEmpty(username)) + return null; + + return Cache.Get("UserByName_" + username.ToLowerInvariant(), + TimeSpan.Zero, TimeSpan.FromDays(1), Fld.GenerationKey, () => + { + using var connection = SqlConnections.NewByKey("Default"); + return GetFirst(connection, new Criteria(Fld.Username) == username); + }); + } + + public static void RemoveCachedUser(ITwoLevelCache cache, int? userId, string username) + { + if (userId != null) + cache.Remove("UserByID_" + userId); + + if (username != null) + cache.Remove("UserByName_" + username.ToLowerInvariant()); + } } \ No newline at end of file diff --git a/src/Serene.Web/Modules/Common/File/FilePage.cs b/src/Serene.Web/Modules/Common/File/FilePage.cs index c8329b8c..2579064f 100644 --- a/src/Serene.Web/Modules/Common/File/FilePage.cs +++ b/src/Serene.Web/Modules/Common/File/FilePage.cs @@ -75,30 +75,16 @@ private UploadResponse HandleUploadRequest(HttpContext context) var uploadInfo = uploadProcessor.Process(file.OpenReadStream(), file.FileName, uploadOptions); - if (uploadInfo.Success) - { - uploadStorage.SetOriginalName(uploadInfo.TemporaryFile, file.FileName); + uploadStorage.SetOriginalName(uploadInfo.TemporaryFile, file.FileName); - return new UploadResponse() - { - TemporaryFile = uploadInfo.TemporaryFile, - Size = uploadInfo.FileSize, - IsImage = uploadInfo.IsImage, - Width = uploadInfo.ImageWidth, - Height = uploadInfo.ImageHeight - }; - } - else + return new UploadResponse() { - return new UploadResponse() - { - Error = new ServiceError() - { - Code = "Exception", - Message = uploadInfo.ErrorMessage - } - }; - } + TemporaryFile = uploadInfo.TemporaryFile, + Size = uploadInfo.FileSize, + IsImage = uploadInfo.IsImage, + Width = uploadInfo.ImageWidth, + Height = uploadInfo.ImageHeight + }; } private class UploadResponse : ServiceResponse diff --git a/src/Serene.Web/Modules/Common/ScriptInit.ts b/src/Serene.Web/Modules/Common/ScriptInit.ts index 4a5aec7a..25555feb 100644 --- a/src/Serene.Web/Modules/Common/ScriptInit.ts +++ b/src/Serene.Web/Modules/Common/ScriptInit.ts @@ -1,12 +1,12 @@ -import { EntityDialog, HtmlContentEditor, getjQuery } from "@serenity-is/corelib"; -import { Authorization, Config, ErrorHandling } from "@serenity-is/corelib"; -import { siteLanguageList } from "./Helpers/LanguageList"; -import { Grid, gridDefaults } from "@serenity-is/sleekgrid"; +import { Config, EntityDialog, ErrorHandling, HtmlContentEditor, getjQuery } from "@serenity-is/corelib"; +import { gridDefaults } from "@serenity-is/sleekgrid"; +import { siteLanguageList } from "./Helpers/LanguageList"; Config.rootNamespaces.push('Serene'); EntityDialog.defaultLanguageList = siteLanguageList; HtmlContentEditor.CKEditorBasePath = "~/Serenity.Assets/Scripts/ckeditor/"; gridDefaults.useCssVars = false; +gridDefaults.useLegacyUI = true; let $ = getjQuery(); if ($?.fn?.['colorbox']) { diff --git a/src/Serene.Web/Modules/Membership/Account/SignUp/AccountPage.SignUp.cs b/src/Serene.Web/Modules/Membership/Account/SignUp/AccountPage.SignUp.cs index 9f56e558..2237a6a2 100644 --- a/src/Serene.Web/Modules/Membership/Account/SignUp/AccountPage.SignUp.cs +++ b/src/Serene.Web/Modules/Membership/Account/SignUp/AccountPage.SignUp.cs @@ -17,7 +17,7 @@ public ActionResult SignUp() public Result SignUp(SignUpRequest request, [FromServices] IEmailSender emailSender, [FromServices] IOptions environmentOptions, - [FromServices] ITypeSource typeSource) + [FromServices] IPermissionKeyLister permissionKeyLister) { return this.UseConnection("Default", connection => { @@ -112,7 +112,7 @@ public Result SignUp(SignUpRequest request, RoleName = "Demo Users", })); - foreach (var permissionKey in UserPermissionRepository.ListPermissionKeys(Cache, typeSource)) + foreach (var permissionKey in permissionKeyLister.ListPermissionKeys(includeRoles: false)) { connection.Insert(new RolePermissionRow { diff --git a/src/Serene.Web/Modules/_ViewImports.cshtml b/src/Serene.Web/Modules/_ViewImports.cshtml index b43ee149..842b8395 100644 --- a/src/Serene.Web/Modules/_ViewImports.cshtml +++ b/src/Serene.Web/Modules/_ViewImports.cshtml @@ -1,4 +1,5 @@ -@using Serenity +@using Serenity +@using Serenity.Abstractions @using Serenity.Web @using Serene @using Microsoft.AspNetCore.Html diff --git a/src/Serene.Web/Serene.Web.csproj b/src/Serene.Web/Serene.Web.csproj index 03446c85..af670bc5 100644 --- a/src/Serene.Web/Serene.Web.csproj +++ b/src/Serene.Web/Serene.Web.csproj @@ -28,19 +28,19 @@ - + - - - - + + + + - + - + @@ -53,10 +53,22 @@ - + + + + + + + + + + + + + @@ -64,18 +76,9 @@ - - - - - - - - + + + - - - - - + \ No newline at end of file diff --git a/src/Serene.Web/appsettings.bundles.json b/src/Serene.Web/appsettings.bundles.json index 4bc2a5d4..b1b46d34 100644 --- a/src/Serene.Web/appsettings.bundles.json +++ b/src/Serene.Web/appsettings.bundles.json @@ -34,11 +34,8 @@ "~/Serenity.Assets/Scripts/jquery-ui.js", "~/Serenity.Assets/Scripts/jquery-ui-i18n.js", "~/Serenity.Assets/bootstrap/js/bootstrap.bundle.js", - "~/Serenity.Assets/Scripts/jquery.autoNumeric.js", "~/Serenity.Assets/Scripts/jquery.colorbox.js", "~/Serenity.Assets/Scripts/jquery.maskedinput.js", - "~/Serenity.Assets/Scripts/jquery.validate.js", - "~/Serenity.Assets/Scripts/select2.js", "~/Serenity.SleekGrid/index.global.js", "~/Serenity.Assets/Scripts/sortable.js", "~/Serenity.Assets/preact/preact.umd.js", diff --git a/src/Serene.Web/package-lock.json b/src/Serene.Web/package-lock.json index 3c135aaf..3b28d4ea 100644 --- a/src/Serene.Web/package-lock.json +++ b/src/Serene.Web/package-lock.json @@ -11,11 +11,11 @@ "@serenity-is/demo.northwind": "./node_modules/.dotnet/serenity.demo.northwind", "@serenity-is/extensions": "./node_modules/.dotnet/serenity.extensions", "@serenity-is/sleekgrid": "./node_modules/.dotnet/serenity.sleekgrid", - "jsx-dom": "8.1.2", - "preact": "10.15.0" + "jsx-dom": "8.1.4", + "preact": "10.23.1" }, "devDependencies": { - "@serenity-is/tsbuild": "8.0.1" + "@serenity-is/tsbuild": "8.6.0" } }, "../../Serenity/packages/corelib": { @@ -63,356 +63,412 @@ "node_modules/.dotnet/serenity.sleekgrid": { "name": "@serenity-is/sleekgrid" }, + "node_modules/@esbuild/aix-ppc64": { + "version": "0.23.0", + "resolved": "https://registry.npmjs.org/@esbuild/aix-ppc64/-/aix-ppc64-0.23.0.tgz", + "integrity": "sha512-3sG8Zwa5fMcA9bgqB8AfWPQ+HFke6uD3h1s3RIwUNK8EG7a4buxvuFTs3j1IMs2NXAk9F30C/FF4vxRgQCcmoQ==", + "cpu": [ + "ppc64" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "aix" + ], + "engines": { + "node": ">=18" + } + }, "node_modules/@esbuild/android-arm": { - "version": "0.19.5", - "resolved": "https://registry.npmjs.org/@esbuild/android-arm/-/android-arm-0.19.5.tgz", - "integrity": "sha512-bhvbzWFF3CwMs5tbjf3ObfGqbl/17ict2/uwOSfr3wmxDE6VdS2GqY/FuzIPe0q0bdhj65zQsvqfArI9MY6+AA==", + "version": "0.23.0", + "resolved": "https://registry.npmjs.org/@esbuild/android-arm/-/android-arm-0.23.0.tgz", + "integrity": "sha512-+KuOHTKKyIKgEEqKbGTK8W7mPp+hKinbMBeEnNzjJGyFcWsfrXjSTNluJHCY1RqhxFurdD8uNXQDei7qDlR6+g==", "cpu": [ "arm" ], "dev": true, + "license": "MIT", "optional": true, "os": [ "android" ], "engines": { - "node": ">=12" + "node": ">=18" } }, "node_modules/@esbuild/android-arm64": { - "version": "0.19.5", - "resolved": "https://registry.npmjs.org/@esbuild/android-arm64/-/android-arm64-0.19.5.tgz", - "integrity": "sha512-5d1OkoJxnYQfmC+Zd8NBFjkhyCNYwM4n9ODrycTFY6Jk1IGiZ+tjVJDDSwDt77nK+tfpGP4T50iMtVi4dEGzhQ==", + "version": "0.23.0", + "resolved": "https://registry.npmjs.org/@esbuild/android-arm64/-/android-arm64-0.23.0.tgz", + "integrity": "sha512-EuHFUYkAVfU4qBdyivULuu03FhJO4IJN9PGuABGrFy4vUuzk91P2d+npxHcFdpUnfYKy0PuV+n6bKIpHOB3prQ==", "cpu": [ "arm64" ], "dev": true, + "license": "MIT", "optional": true, "os": [ "android" ], "engines": { - "node": ">=12" + "node": ">=18" } }, "node_modules/@esbuild/android-x64": { - "version": "0.19.5", - "resolved": "https://registry.npmjs.org/@esbuild/android-x64/-/android-x64-0.19.5.tgz", - "integrity": "sha512-9t+28jHGL7uBdkBjL90QFxe7DVA+KGqWlHCF8ChTKyaKO//VLuoBricQCgwhOjA1/qOczsw843Fy4cbs4H3DVA==", + "version": "0.23.0", + "resolved": "https://registry.npmjs.org/@esbuild/android-x64/-/android-x64-0.23.0.tgz", + "integrity": "sha512-WRrmKidLoKDl56LsbBMhzTTBxrsVwTKdNbKDalbEZr0tcsBgCLbEtoNthOW6PX942YiYq8HzEnb4yWQMLQuipQ==", "cpu": [ "x64" ], "dev": true, + "license": "MIT", "optional": true, "os": [ "android" ], "engines": { - "node": ">=12" + "node": ">=18" } }, "node_modules/@esbuild/darwin-arm64": { - "version": "0.19.5", - "resolved": "https://registry.npmjs.org/@esbuild/darwin-arm64/-/darwin-arm64-0.19.5.tgz", - "integrity": "sha512-mvXGcKqqIqyKoxq26qEDPHJuBYUA5KizJncKOAf9eJQez+L9O+KfvNFu6nl7SCZ/gFb2QPaRqqmG0doSWlgkqw==", + "version": "0.23.0", + "resolved": "https://registry.npmjs.org/@esbuild/darwin-arm64/-/darwin-arm64-0.23.0.tgz", + "integrity": "sha512-YLntie/IdS31H54Ogdn+v50NuoWF5BDkEUFpiOChVa9UnKpftgwzZRrI4J132ETIi+D8n6xh9IviFV3eXdxfow==", "cpu": [ "arm64" ], "dev": true, + "license": "MIT", "optional": true, "os": [ "darwin" ], "engines": { - "node": ">=12" + "node": ">=18" } }, "node_modules/@esbuild/darwin-x64": { - "version": "0.19.5", - "resolved": "https://registry.npmjs.org/@esbuild/darwin-x64/-/darwin-x64-0.19.5.tgz", - "integrity": "sha512-Ly8cn6fGLNet19s0X4unjcniX24I0RqjPv+kurpXabZYSXGM4Pwpmf85WHJN3lAgB8GSth7s5A0r856S+4DyiA==", + "version": "0.23.0", + "resolved": "https://registry.npmjs.org/@esbuild/darwin-x64/-/darwin-x64-0.23.0.tgz", + "integrity": "sha512-IMQ6eme4AfznElesHUPDZ+teuGwoRmVuuixu7sv92ZkdQcPbsNHzutd+rAfaBKo8YK3IrBEi9SLLKWJdEvJniQ==", "cpu": [ "x64" ], "dev": true, + "license": "MIT", "optional": true, "os": [ "darwin" ], "engines": { - "node": ">=12" + "node": ">=18" } }, "node_modules/@esbuild/freebsd-arm64": { - "version": "0.19.5", - "resolved": "https://registry.npmjs.org/@esbuild/freebsd-arm64/-/freebsd-arm64-0.19.5.tgz", - "integrity": "sha512-GGDNnPWTmWE+DMchq1W8Sd0mUkL+APvJg3b11klSGUDvRXh70JqLAO56tubmq1s2cgpVCSKYywEiKBfju8JztQ==", + "version": "0.23.0", + "resolved": "https://registry.npmjs.org/@esbuild/freebsd-arm64/-/freebsd-arm64-0.23.0.tgz", + "integrity": "sha512-0muYWCng5vqaxobq6LB3YNtevDFSAZGlgtLoAc81PjUfiFz36n4KMpwhtAd4he8ToSI3TGyuhyx5xmiWNYZFyw==", "cpu": [ "arm64" ], "dev": true, + "license": "MIT", "optional": true, "os": [ "freebsd" ], "engines": { - "node": ">=12" + "node": ">=18" } }, "node_modules/@esbuild/freebsd-x64": { - "version": "0.19.5", - "resolved": "https://registry.npmjs.org/@esbuild/freebsd-x64/-/freebsd-x64-0.19.5.tgz", - "integrity": "sha512-1CCwDHnSSoA0HNwdfoNY0jLfJpd7ygaLAp5EHFos3VWJCRX9DMwWODf96s9TSse39Br7oOTLryRVmBoFwXbuuQ==", + "version": "0.23.0", + "resolved": "https://registry.npmjs.org/@esbuild/freebsd-x64/-/freebsd-x64-0.23.0.tgz", + "integrity": "sha512-XKDVu8IsD0/q3foBzsXGt/KjD/yTKBCIwOHE1XwiXmrRwrX6Hbnd5Eqn/WvDekddK21tfszBSrE/WMaZh+1buQ==", "cpu": [ "x64" ], "dev": true, + "license": "MIT", "optional": true, "os": [ "freebsd" ], "engines": { - "node": ">=12" + "node": ">=18" } }, "node_modules/@esbuild/linux-arm": { - "version": "0.19.5", - "resolved": "https://registry.npmjs.org/@esbuild/linux-arm/-/linux-arm-0.19.5.tgz", - "integrity": "sha512-lrWXLY/vJBzCPC51QN0HM71uWgIEpGSjSZZADQhq7DKhPcI6NH1IdzjfHkDQws2oNpJKpR13kv7/pFHBbDQDwQ==", + "version": "0.23.0", + "resolved": "https://registry.npmjs.org/@esbuild/linux-arm/-/linux-arm-0.23.0.tgz", + "integrity": "sha512-SEELSTEtOFu5LPykzA395Mc+54RMg1EUgXP+iw2SJ72+ooMwVsgfuwXo5Fn0wXNgWZsTVHwY2cg4Vi/bOD88qw==", "cpu": [ "arm" ], "dev": true, + "license": "MIT", "optional": true, "os": [ "linux" ], "engines": { - "node": ">=12" + "node": ">=18" } }, "node_modules/@esbuild/linux-arm64": { - "version": "0.19.5", - "resolved": "https://registry.npmjs.org/@esbuild/linux-arm64/-/linux-arm64-0.19.5.tgz", - "integrity": "sha512-o3vYippBmSrjjQUCEEiTZ2l+4yC0pVJD/Dl57WfPwwlvFkrxoSO7rmBZFii6kQB3Wrn/6GwJUPLU5t52eq2meA==", + "version": "0.23.0", + "resolved": "https://registry.npmjs.org/@esbuild/linux-arm64/-/linux-arm64-0.23.0.tgz", + "integrity": "sha512-j1t5iG8jE7BhonbsEg5d9qOYcVZv/Rv6tghaXM/Ug9xahM0nX/H2gfu6X6z11QRTMT6+aywOMA8TDkhPo8aCGw==", "cpu": [ "arm64" ], "dev": true, + "license": "MIT", "optional": true, "os": [ "linux" ], "engines": { - "node": ">=12" + "node": ">=18" } }, "node_modules/@esbuild/linux-ia32": { - "version": "0.19.5", - "resolved": "https://registry.npmjs.org/@esbuild/linux-ia32/-/linux-ia32-0.19.5.tgz", - "integrity": "sha512-MkjHXS03AXAkNp1KKkhSKPOCYztRtK+KXDNkBa6P78F8Bw0ynknCSClO/ztGszILZtyO/lVKpa7MolbBZ6oJtQ==", + "version": "0.23.0", + "resolved": "https://registry.npmjs.org/@esbuild/linux-ia32/-/linux-ia32-0.23.0.tgz", + "integrity": "sha512-P7O5Tkh2NbgIm2R6x1zGJJsnacDzTFcRWZyTTMgFdVit6E98LTxO+v8LCCLWRvPrjdzXHx9FEOA8oAZPyApWUA==", "cpu": [ "ia32" ], "dev": true, + "license": "MIT", "optional": true, "os": [ "linux" ], "engines": { - "node": ">=12" + "node": ">=18" } }, "node_modules/@esbuild/linux-loong64": { - "version": "0.19.5", - "resolved": "https://registry.npmjs.org/@esbuild/linux-loong64/-/linux-loong64-0.19.5.tgz", - "integrity": "sha512-42GwZMm5oYOD/JHqHska3Jg0r+XFb/fdZRX+WjADm3nLWLcIsN27YKtqxzQmGNJgu0AyXg4HtcSK9HuOk3v1Dw==", + "version": "0.23.0", + "resolved": "https://registry.npmjs.org/@esbuild/linux-loong64/-/linux-loong64-0.23.0.tgz", + "integrity": "sha512-InQwepswq6urikQiIC/kkx412fqUZudBO4SYKu0N+tGhXRWUqAx+Q+341tFV6QdBifpjYgUndV1hhMq3WeJi7A==", "cpu": [ "loong64" ], "dev": true, + "license": "MIT", "optional": true, "os": [ "linux" ], "engines": { - "node": ">=12" + "node": ">=18" } }, "node_modules/@esbuild/linux-mips64el": { - "version": "0.19.5", - "resolved": "https://registry.npmjs.org/@esbuild/linux-mips64el/-/linux-mips64el-0.19.5.tgz", - "integrity": "sha512-kcjndCSMitUuPJobWCnwQ9lLjiLZUR3QLQmlgaBfMX23UEa7ZOrtufnRds+6WZtIS9HdTXqND4yH8NLoVVIkcg==", + "version": "0.23.0", + "resolved": "https://registry.npmjs.org/@esbuild/linux-mips64el/-/linux-mips64el-0.23.0.tgz", + "integrity": "sha512-J9rflLtqdYrxHv2FqXE2i1ELgNjT+JFURt/uDMoPQLcjWQA5wDKgQA4t/dTqGa88ZVECKaD0TctwsUfHbVoi4w==", "cpu": [ "mips64el" ], "dev": true, + "license": "MIT", "optional": true, "os": [ "linux" ], "engines": { - "node": ">=12" + "node": ">=18" } }, "node_modules/@esbuild/linux-ppc64": { - "version": "0.19.5", - "resolved": "https://registry.npmjs.org/@esbuild/linux-ppc64/-/linux-ppc64-0.19.5.tgz", - "integrity": "sha512-yJAxJfHVm0ZbsiljbtFFP1BQKLc8kUF6+17tjQ78QjqjAQDnhULWiTA6u0FCDmYT1oOKS9PzZ2z0aBI+Mcyj7Q==", + "version": "0.23.0", + "resolved": "https://registry.npmjs.org/@esbuild/linux-ppc64/-/linux-ppc64-0.23.0.tgz", + "integrity": "sha512-cShCXtEOVc5GxU0fM+dsFD10qZ5UpcQ8AM22bYj0u/yaAykWnqXJDpd77ublcX6vdDsWLuweeuSNZk4yUxZwtw==", "cpu": [ "ppc64" ], "dev": true, + "license": "MIT", "optional": true, "os": [ "linux" ], "engines": { - "node": ">=12" + "node": ">=18" } }, "node_modules/@esbuild/linux-riscv64": { - "version": "0.19.5", - "resolved": "https://registry.npmjs.org/@esbuild/linux-riscv64/-/linux-riscv64-0.19.5.tgz", - "integrity": "sha512-5u8cIR/t3gaD6ad3wNt1MNRstAZO+aNyBxu2We8X31bA8XUNyamTVQwLDA1SLoPCUehNCymhBhK3Qim1433Zag==", + "version": "0.23.0", + "resolved": "https://registry.npmjs.org/@esbuild/linux-riscv64/-/linux-riscv64-0.23.0.tgz", + "integrity": "sha512-HEtaN7Y5UB4tZPeQmgz/UhzoEyYftbMXrBCUjINGjh3uil+rB/QzzpMshz3cNUxqXN7Vr93zzVtpIDL99t9aRw==", "cpu": [ "riscv64" ], "dev": true, + "license": "MIT", "optional": true, "os": [ "linux" ], "engines": { - "node": ">=12" + "node": ">=18" } }, "node_modules/@esbuild/linux-s390x": { - "version": "0.19.5", - "resolved": "https://registry.npmjs.org/@esbuild/linux-s390x/-/linux-s390x-0.19.5.tgz", - "integrity": "sha512-Z6JrMyEw/EmZBD/OFEFpb+gao9xJ59ATsoTNlj39jVBbXqoZm4Xntu6wVmGPB/OATi1uk/DB+yeDPv2E8PqZGw==", + "version": "0.23.0", + "resolved": "https://registry.npmjs.org/@esbuild/linux-s390x/-/linux-s390x-0.23.0.tgz", + "integrity": "sha512-WDi3+NVAuyjg/Wxi+o5KPqRbZY0QhI9TjrEEm+8dmpY9Xir8+HE/HNx2JoLckhKbFopW0RdO2D72w8trZOV+Wg==", "cpu": [ "s390x" ], "dev": true, + "license": "MIT", "optional": true, "os": [ "linux" ], "engines": { - "node": ">=12" + "node": ">=18" } }, "node_modules/@esbuild/linux-x64": { - "version": "0.19.5", - "resolved": "https://registry.npmjs.org/@esbuild/linux-x64/-/linux-x64-0.19.5.tgz", - "integrity": "sha512-psagl+2RlK1z8zWZOmVdImisMtrUxvwereIdyJTmtmHahJTKb64pAcqoPlx6CewPdvGvUKe2Jw+0Z/0qhSbG1A==", + "version": "0.23.0", + "resolved": "https://registry.npmjs.org/@esbuild/linux-x64/-/linux-x64-0.23.0.tgz", + "integrity": "sha512-a3pMQhUEJkITgAw6e0bWA+F+vFtCciMjW/LPtoj99MhVt+Mfb6bbL9hu2wmTZgNd994qTAEw+U/r6k3qHWWaOQ==", "cpu": [ "x64" ], "dev": true, + "license": "MIT", "optional": true, "os": [ "linux" ], "engines": { - "node": ">=12" + "node": ">=18" } }, "node_modules/@esbuild/netbsd-x64": { - "version": "0.19.5", - "resolved": "https://registry.npmjs.org/@esbuild/netbsd-x64/-/netbsd-x64-0.19.5.tgz", - "integrity": "sha512-kL2l+xScnAy/E/3119OggX8SrWyBEcqAh8aOY1gr4gPvw76la2GlD4Ymf832UCVbmuWeTf2adkZDK+h0Z/fB4g==", + "version": "0.23.0", + "resolved": "https://registry.npmjs.org/@esbuild/netbsd-x64/-/netbsd-x64-0.23.0.tgz", + "integrity": "sha512-cRK+YDem7lFTs2Q5nEv/HHc4LnrfBCbH5+JHu6wm2eP+d8OZNoSMYgPZJq78vqQ9g+9+nMuIsAO7skzphRXHyw==", "cpu": [ "x64" ], "dev": true, + "license": "MIT", "optional": true, "os": [ "netbsd" ], "engines": { - "node": ">=12" + "node": ">=18" + } + }, + "node_modules/@esbuild/openbsd-arm64": { + "version": "0.23.0", + "resolved": "https://registry.npmjs.org/@esbuild/openbsd-arm64/-/openbsd-arm64-0.23.0.tgz", + "integrity": "sha512-suXjq53gERueVWu0OKxzWqk7NxiUWSUlrxoZK7usiF50C6ipColGR5qie2496iKGYNLhDZkPxBI3erbnYkU0rQ==", + "cpu": [ + "arm64" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "openbsd" + ], + "engines": { + "node": ">=18" } }, "node_modules/@esbuild/openbsd-x64": { - "version": "0.19.5", - "resolved": "https://registry.npmjs.org/@esbuild/openbsd-x64/-/openbsd-x64-0.19.5.tgz", - "integrity": "sha512-sPOfhtzFufQfTBgRnE1DIJjzsXukKSvZxloZbkJDG383q0awVAq600pc1nfqBcl0ice/WN9p4qLc39WhBShRTA==", + "version": "0.23.0", + "resolved": "https://registry.npmjs.org/@esbuild/openbsd-x64/-/openbsd-x64-0.23.0.tgz", + "integrity": "sha512-6p3nHpby0DM/v15IFKMjAaayFhqnXV52aEmv1whZHX56pdkK+MEaLoQWj+H42ssFarP1PcomVhbsR4pkz09qBg==", "cpu": [ "x64" ], "dev": true, + "license": "MIT", "optional": true, "os": [ "openbsd" ], "engines": { - "node": ">=12" + "node": ">=18" } }, "node_modules/@esbuild/sunos-x64": { - "version": "0.19.5", - "resolved": "https://registry.npmjs.org/@esbuild/sunos-x64/-/sunos-x64-0.19.5.tgz", - "integrity": "sha512-dGZkBXaafuKLpDSjKcB0ax0FL36YXCvJNnztjKV+6CO82tTYVDSH2lifitJ29jxRMoUhgkg9a+VA/B03WK5lcg==", + "version": "0.23.0", + "resolved": "https://registry.npmjs.org/@esbuild/sunos-x64/-/sunos-x64-0.23.0.tgz", + "integrity": "sha512-BFelBGfrBwk6LVrmFzCq1u1dZbG4zy/Kp93w2+y83Q5UGYF1d8sCzeLI9NXjKyujjBBniQa8R8PzLFAUrSM9OA==", "cpu": [ "x64" ], "dev": true, + "license": "MIT", "optional": true, "os": [ "sunos" ], "engines": { - "node": ">=12" + "node": ">=18" } }, "node_modules/@esbuild/win32-arm64": { - "version": "0.19.5", - "resolved": "https://registry.npmjs.org/@esbuild/win32-arm64/-/win32-arm64-0.19.5.tgz", - "integrity": "sha512-dWVjD9y03ilhdRQ6Xig1NWNgfLtf2o/STKTS+eZuF90fI2BhbwD6WlaiCGKptlqXlURVB5AUOxUj09LuwKGDTg==", + "version": "0.23.0", + "resolved": "https://registry.npmjs.org/@esbuild/win32-arm64/-/win32-arm64-0.23.0.tgz", + "integrity": "sha512-lY6AC8p4Cnb7xYHuIxQ6iYPe6MfO2CC43XXKo9nBXDb35krYt7KGhQnOkRGar5psxYkircpCqfbNDB4uJbS2jQ==", "cpu": [ "arm64" ], "dev": true, + "license": "MIT", "optional": true, "os": [ "win32" ], "engines": { - "node": ">=12" + "node": ">=18" } }, "node_modules/@esbuild/win32-ia32": { - "version": "0.19.5", - "resolved": "https://registry.npmjs.org/@esbuild/win32-ia32/-/win32-ia32-0.19.5.tgz", - "integrity": "sha512-4liggWIA4oDgUxqpZwrDhmEfAH4d0iljanDOK7AnVU89T6CzHon/ony8C5LeOdfgx60x5cnQJFZwEydVlYx4iw==", + "version": "0.23.0", + "resolved": "https://registry.npmjs.org/@esbuild/win32-ia32/-/win32-ia32-0.23.0.tgz", + "integrity": "sha512-7L1bHlOTcO4ByvI7OXVI5pNN6HSu6pUQq9yodga8izeuB1KcT2UkHaH6118QJwopExPn0rMHIseCTx1CRo/uNA==", "cpu": [ "ia32" ], "dev": true, + "license": "MIT", "optional": true, "os": [ "win32" ], "engines": { - "node": ">=12" + "node": ">=18" } }, "node_modules/@esbuild/win32-x64": { - "version": "0.19.5", - "resolved": "https://registry.npmjs.org/@esbuild/win32-x64/-/win32-x64-0.19.5.tgz", - "integrity": "sha512-czTrygUsB/jlM8qEW5MD8bgYU2Xg14lo6kBDXW6HdxKjh8M5PzETGiSHaz9MtbXBYDloHNUAUW2tMiKW4KM9Mw==", + "version": "0.23.0", + "resolved": "https://registry.npmjs.org/@esbuild/win32-x64/-/win32-x64-0.23.0.tgz", + "integrity": "sha512-Arm+WgUFLUATuoxCJcahGuk6Yj9Pzxd6l11Zb/2aAuv5kWWvvfhLFo2fni4uSK5vzlUdCGZ/BdV5tH8klj8p8g==", "cpu": [ "x64" ], "dev": true, + "license": "MIT", "optional": true, "os": [ "win32" ], "engines": { - "node": ">=12" + "node": ">=18" } }, "node_modules/@isaacs/cliui": { @@ -420,6 +476,7 @@ "resolved": "https://registry.npmjs.org/@isaacs/cliui/-/cliui-8.0.2.tgz", "integrity": "sha512-O8jcjabXaleOG9DQ0+ARXWZBTfnP4WNAqzuiJK7ll44AmxGKv/J2M4TPjxjY3znBCfvBXFzucm1twdyFybFqEA==", "dev": true, + "license": "ISC", "dependencies": { "string-width": "^5.1.2", "string-width-cjs": "npm:string-width@^4.2.0", @@ -437,6 +494,7 @@ "resolved": "https://registry.npmjs.org/@pkgjs/parseargs/-/parseargs-0.11.0.tgz", "integrity": "sha512-+1VkjdD0QBLPodGrJUeqarH8VAIvQODIbwh9XpP5Syisf7YoQgsJKPNFoqqLQlu+VQ/tVSshMR6loPMn8U+dPg==", "dev": true, + "license": "MIT", "optional": true, "engines": { "node": ">=14" @@ -459,13 +517,14 @@ "link": true }, "node_modules/@serenity-is/tsbuild": { - "version": "8.0.1", - "resolved": "https://registry.npmjs.org/@serenity-is/tsbuild/-/tsbuild-8.0.1.tgz", - "integrity": "sha512-dAoI+wyzA2Z+M0jKyVy+WMm86vMmTMqINkZV614zwpQMM2WCmpyxO7UwfxEIchyX8MdBciJPh9WjIXwprQJbUw==", + "version": "8.6.0", + "resolved": "https://registry.npmjs.org/@serenity-is/tsbuild/-/tsbuild-8.6.0.tgz", + "integrity": "sha512-NoY/A34FHGRvUMUeKNSsryf7Eqh125rkR07xIbI0O/K/nybVoteMGCX3cWbsb2M9czBdmzWBKtXny7Mx9ZoyAQ==", "dev": true, + "license": "MIT", "dependencies": { - "esbuild": "0.19.5", - "glob": "10.3.10" + "esbuild": "0.23.0", + "glob": "10.4.1" } }, "node_modules/ansi-regex": { @@ -473,6 +532,7 @@ "resolved": "https://registry.npmjs.org/ansi-regex/-/ansi-regex-6.0.1.tgz", "integrity": "sha512-n5M855fKb2SsfMIiFFoVrABHJC8QtHwVx+mHWP3QcEqBHYienj5dHSgjbxtC0WEZXYt4wcD6zrQElDPhFuZgfA==", "dev": true, + "license": "MIT", "engines": { "node": ">=12" }, @@ -485,6 +545,7 @@ "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-6.2.1.tgz", "integrity": "sha512-bN798gFfQX+viw3R7yrGWRqnrN2oRkEkUjjl4JNn4E8GxxbjtG3FbrEIIY3l8/hrwUwIeCZvi4QuOTP4MErVug==", "dev": true, + "license": "MIT", "engines": { "node": ">=12" }, @@ -496,13 +557,15 @@ "version": "1.0.2", "resolved": "https://registry.npmjs.org/balanced-match/-/balanced-match-1.0.2.tgz", "integrity": "sha512-3oSeUO0TMV67hN1AmbXsK4yaqU7tjiHlbxRDZOpH0KW9+CeX4bRAaX0Anxt0tx2MrpRpWwQaPwIlISEJhYU5Pw==", - "dev": true + "dev": true, + "license": "MIT" }, "node_modules/brace-expansion": { "version": "2.0.1", "resolved": "https://registry.npmjs.org/brace-expansion/-/brace-expansion-2.0.1.tgz", "integrity": "sha512-XnAIvQ8eM+kC6aULx6wuQiwVsnzsi9d3WxzV3FpWTGA19F621kwdbsAcFKXgKUHZWsy+mY6iL1sHTxWEFCytDA==", "dev": true, + "license": "MIT", "dependencies": { "balanced-match": "^1.0.0" } @@ -512,6 +575,7 @@ "resolved": "https://registry.npmjs.org/color-convert/-/color-convert-2.0.1.tgz", "integrity": "sha512-RRECPsj7iu/xb5oKYcsFHSppFNnsj/52OVTRKb4zP5onXwVF3zVmmToNcOfGC+CRDpfK/U584fMg38ZHCaElKQ==", "dev": true, + "license": "MIT", "dependencies": { "color-name": "~1.1.4" }, @@ -523,13 +587,15 @@ "version": "1.1.4", "resolved": "https://registry.npmjs.org/color-name/-/color-name-1.1.4.tgz", "integrity": "sha512-dOy+3AuW3a2wNbZHIuMZpTcgjGuLU/uBL/ubcZF9OXbDo8ff4O8yVp5Bf0efS8uEoYo5q4Fx7dY9OgQGXgAsQA==", - "dev": true + "dev": true, + "license": "MIT" }, "node_modules/cross-spawn": { "version": "7.0.3", "resolved": "https://registry.npmjs.org/cross-spawn/-/cross-spawn-7.0.3.tgz", "integrity": "sha512-iRDPJKUPVEND7dHPO8rkbOnPpyDygcDFtWjpeWNCgy8WP2rXcxXL8TskReQl6OrB2G7+UJrags1q15Fudc7G6w==", "dev": true, + "license": "MIT", "dependencies": { "path-key": "^3.1.0", "shebang-command": "^2.0.0", @@ -548,56 +614,62 @@ "version": "0.2.0", "resolved": "https://registry.npmjs.org/eastasianwidth/-/eastasianwidth-0.2.0.tgz", "integrity": "sha512-I88TYZWc9XiYHRQ4/3c5rjjfgkjhLyW2luGIheGERbNQ6OY7yTybanSpDXZa8y7VUP9YmDcYa+eyq4ca7iLqWA==", - "dev": true + "dev": true, + "license": "MIT" }, "node_modules/emoji-regex": { "version": "9.2.2", "resolved": "https://registry.npmjs.org/emoji-regex/-/emoji-regex-9.2.2.tgz", "integrity": "sha512-L18DaJsXSUk2+42pv8mLs5jJT2hqFkFE4j21wOmgbUqsZ2hL72NsUU785g9RXgo3s0ZNgVl42TiHp3ZtOv/Vyg==", - "dev": true + "dev": true, + "license": "MIT" }, "node_modules/esbuild": { - "version": "0.19.5", - "resolved": "https://registry.npmjs.org/esbuild/-/esbuild-0.19.5.tgz", - "integrity": "sha512-bUxalY7b1g8vNhQKdB24QDmHeY4V4tw/s6Ak5z+jJX9laP5MoQseTOMemAr0gxssjNcH0MCViG8ONI2kksvfFQ==", + "version": "0.23.0", + "resolved": "https://registry.npmjs.org/esbuild/-/esbuild-0.23.0.tgz", + "integrity": "sha512-1lvV17H2bMYda/WaFb2jLPeHU3zml2k4/yagNMG8Q/YtfMjCwEUZa2eXXMgZTVSL5q1n4H7sQ0X6CdJDqqeCFA==", "dev": true, "hasInstallScript": true, + "license": "MIT", "bin": { "esbuild": "bin/esbuild" }, "engines": { - "node": ">=12" + "node": ">=18" }, "optionalDependencies": { - "@esbuild/android-arm": "0.19.5", - "@esbuild/android-arm64": "0.19.5", - "@esbuild/android-x64": "0.19.5", - "@esbuild/darwin-arm64": "0.19.5", - "@esbuild/darwin-x64": "0.19.5", - "@esbuild/freebsd-arm64": "0.19.5", - "@esbuild/freebsd-x64": "0.19.5", - "@esbuild/linux-arm": "0.19.5", - "@esbuild/linux-arm64": "0.19.5", - "@esbuild/linux-ia32": "0.19.5", - "@esbuild/linux-loong64": "0.19.5", - "@esbuild/linux-mips64el": "0.19.5", - "@esbuild/linux-ppc64": "0.19.5", - "@esbuild/linux-riscv64": "0.19.5", - "@esbuild/linux-s390x": "0.19.5", - "@esbuild/linux-x64": "0.19.5", - "@esbuild/netbsd-x64": "0.19.5", - "@esbuild/openbsd-x64": "0.19.5", - "@esbuild/sunos-x64": "0.19.5", - "@esbuild/win32-arm64": "0.19.5", - "@esbuild/win32-ia32": "0.19.5", - "@esbuild/win32-x64": "0.19.5" + "@esbuild/aix-ppc64": "0.23.0", + "@esbuild/android-arm": "0.23.0", + "@esbuild/android-arm64": "0.23.0", + "@esbuild/android-x64": "0.23.0", + "@esbuild/darwin-arm64": "0.23.0", + "@esbuild/darwin-x64": "0.23.0", + "@esbuild/freebsd-arm64": "0.23.0", + "@esbuild/freebsd-x64": "0.23.0", + "@esbuild/linux-arm": "0.23.0", + "@esbuild/linux-arm64": "0.23.0", + "@esbuild/linux-ia32": "0.23.0", + "@esbuild/linux-loong64": "0.23.0", + "@esbuild/linux-mips64el": "0.23.0", + "@esbuild/linux-ppc64": "0.23.0", + "@esbuild/linux-riscv64": "0.23.0", + "@esbuild/linux-s390x": "0.23.0", + "@esbuild/linux-x64": "0.23.0", + "@esbuild/netbsd-x64": "0.23.0", + "@esbuild/openbsd-arm64": "0.23.0", + "@esbuild/openbsd-x64": "0.23.0", + "@esbuild/sunos-x64": "0.23.0", + "@esbuild/win32-arm64": "0.23.0", + "@esbuild/win32-ia32": "0.23.0", + "@esbuild/win32-x64": "0.23.0" } }, "node_modules/foreground-child": { - "version": "3.1.1", - "resolved": "https://registry.npmjs.org/foreground-child/-/foreground-child-3.1.1.tgz", - "integrity": "sha512-TMKDUnIte6bfb5nWv7V/caI169OHgvwjb7V4WkeUvbQQdjr5rWKqHFiKWb/fcOwB+CzBT+qbWjvj+DVwRskpIg==", + "version": "3.2.1", + "resolved": "https://registry.npmjs.org/foreground-child/-/foreground-child-3.2.1.tgz", + "integrity": "sha512-PXUUyLqrR2XCWICfv6ukppP96sdFwWbNEnfEMt7jNsISjMsvaLNinAHNDYyvkyU+SZG2BTSbT5NjG+vZslfGTA==", "dev": true, + "license": "ISC", "dependencies": { "cross-spawn": "^7.0.0", "signal-exit": "^4.0.1" @@ -610,22 +682,23 @@ } }, "node_modules/glob": { - "version": "10.3.10", - "resolved": "https://registry.npmjs.org/glob/-/glob-10.3.10.tgz", - "integrity": "sha512-fa46+tv1Ak0UPK1TOy/pZrIybNNt4HCv7SDzwyfiOZkvZLEbjsZkJBPtDHVshZjbecAoAGSC20MjLDG/qr679g==", + "version": "10.4.1", + "resolved": "https://registry.npmjs.org/glob/-/glob-10.4.1.tgz", + "integrity": "sha512-2jelhlq3E4ho74ZyVLN03oKdAZVUa6UDZzFLVH1H7dnoax+y9qyaq8zBkfDIggjniU19z0wU18y16jMB2eyVIw==", "dev": true, + "license": "ISC", "dependencies": { "foreground-child": "^3.1.0", - "jackspeak": "^2.3.5", - "minimatch": "^9.0.1", - "minipass": "^5.0.0 || ^6.0.2 || ^7.0.0", - "path-scurry": "^1.10.1" + "jackspeak": "^3.1.2", + "minimatch": "^9.0.4", + "minipass": "^7.1.2", + "path-scurry": "^1.11.1" }, "bin": { "glob": "dist/esm/bin.mjs" }, "engines": { - "node": ">=16 || 14 >=14.17" + "node": ">=16 || 14 >=14.18" }, "funding": { "url": "https://github.com/sponsors/isaacs" @@ -636,6 +709,7 @@ "resolved": "https://registry.npmjs.org/is-fullwidth-code-point/-/is-fullwidth-code-point-3.0.0.tgz", "integrity": "sha512-zymm5+u+sCsSWyD9qNaejV3DFvhCKclKdizYaJUuHA83RLjb7nSuGnddCHGv0hk+KY7BMAlsWeK4Ueg6EV6XQg==", "dev": true, + "license": "MIT", "engines": { "node": ">=8" } @@ -644,19 +718,18 @@ "version": "2.0.0", "resolved": "https://registry.npmjs.org/isexe/-/isexe-2.0.0.tgz", "integrity": "sha512-RHxMLp9lnKHGHRng9QFhRCMbYAcVpn69smSGcq3f36xjgVVWThj4qqLbTLlq7Ssj8B+fIQ1EuCEGI2lKsyQeIw==", - "dev": true + "dev": true, + "license": "ISC" }, "node_modules/jackspeak": { - "version": "2.3.6", - "resolved": "https://registry.npmjs.org/jackspeak/-/jackspeak-2.3.6.tgz", - "integrity": "sha512-N3yCS/NegsOBokc8GAdM8UcmfsKiSS8cipheD/nivzr700H+nsMOxJjQnvwOcRYVuFkdH0wGUvW2WbXGmrZGbQ==", + "version": "3.4.3", + "resolved": "https://registry.npmjs.org/jackspeak/-/jackspeak-3.4.3.tgz", + "integrity": "sha512-OGlZQpz2yfahA/Rd1Y8Cd9SIEsqvXkLVoSw/cgwhnhFMDbsQFeZYoJJ7bIZBS9BcamUW96asq/npPWugM+RQBw==", "dev": true, + "license": "BlueOak-1.0.0", "dependencies": { "@isaacs/cliui": "^8.0.2" }, - "engines": { - "node": ">=14" - }, "funding": { "url": "https://github.com/sponsors/isaacs" }, @@ -665,27 +738,27 @@ } }, "node_modules/jsx-dom": { - "version": "8.1.2", - "resolved": "https://registry.npmjs.org/jsx-dom/-/jsx-dom-8.1.2.tgz", - "integrity": "sha512-0hBsob3UwWlm5wD0S7sNFxAUrWAPzrt/r/K+AGzlRaCrPNu40+px77U7kgG+NS022nWjhOso+dZhqu1XFR7eXg==", + "version": "8.1.4", + "resolved": "https://registry.npmjs.org/jsx-dom/-/jsx-dom-8.1.4.tgz", + "integrity": "sha512-Wcv5iuOvB5SeF/tj3/sa+B0kqWb22WnlfPg8k64SmHOa/E+2M+cOruke+Dqr0GK2FY5xp0gEj4quWZM8quQN2w==", + "license": "BSD-3-Clause", "dependencies": { "csstype": "^3.1.3" } }, "node_modules/lru-cache": { - "version": "10.1.0", - "resolved": "https://registry.npmjs.org/lru-cache/-/lru-cache-10.1.0.tgz", - "integrity": "sha512-/1clY/ui8CzjKFyjdvwPWJUYKiFVXG2I2cY0ssG7h4+hwk+XOIX7ZSG9Q7TW8TW3Kp3BUSqgFWBLgL4PJ+Blag==", + "version": "10.4.3", + "resolved": "https://registry.npmjs.org/lru-cache/-/lru-cache-10.4.3.tgz", + "integrity": "sha512-JNAzZcXrCt42VGLuYz0zfAzDfAvJWW6AfYlDBQyDV5DClI2m5sAmK+OIO7s59XfsRsWHp02jAJrRadPRGTt6SQ==", "dev": true, - "engines": { - "node": "14 || >=16.14" - } + "license": "ISC" }, "node_modules/minimatch": { - "version": "9.0.3", - "resolved": "https://registry.npmjs.org/minimatch/-/minimatch-9.0.3.tgz", - "integrity": "sha512-RHiac9mvaRw0x3AYRgDC1CxAP7HTcNrrECeA8YYJeWnpo+2Q5CegtZjaotWTWxDG3UeGA1coE05iH1mPjT/2mg==", + "version": "9.0.5", + "resolved": "https://registry.npmjs.org/minimatch/-/minimatch-9.0.5.tgz", + "integrity": "sha512-G6T0ZX48xgozx7587koeX9Ys2NYy6Gmv//P89sEte9V9whIapMNF4idKxnW2QtCcLiTWlb/wfCabAtAFWhhBow==", "dev": true, + "license": "ISC", "dependencies": { "brace-expansion": "^2.0.1" }, @@ -697,10 +770,11 @@ } }, "node_modules/minipass": { - "version": "7.0.4", - "resolved": "https://registry.npmjs.org/minipass/-/minipass-7.0.4.tgz", - "integrity": "sha512-jYofLM5Dam9279rdkWzqHozUo4ybjdZmCsDHePy5V/PbBcVMiSZR97gmAy45aqi8CK1lG2ECd356FU86avfwUQ==", + "version": "7.1.2", + "resolved": "https://registry.npmjs.org/minipass/-/minipass-7.1.2.tgz", + "integrity": "sha512-qOOzS1cBTWYF4BH8fVePDBOO9iptMnGUEZwNc/cMWnTV2nVLZ7VoNWEPHkYczZA0pdoA7dl6e7FL659nX9S2aw==", "dev": true, + "license": "ISC", "engines": { "node": ">=16 || 14 >=14.17" } @@ -710,30 +784,33 @@ "resolved": "https://registry.npmjs.org/path-key/-/path-key-3.1.1.tgz", "integrity": "sha512-ojmeN0qd+y0jszEtoY48r0Peq5dwMEkIlCOu6Q5f41lfkswXuKtYrhgoTpLnyIcHm24Uhqx+5Tqm2InSwLhE6Q==", "dev": true, + "license": "MIT", "engines": { "node": ">=8" } }, "node_modules/path-scurry": { - "version": "1.10.1", - "resolved": "https://registry.npmjs.org/path-scurry/-/path-scurry-1.10.1.tgz", - "integrity": "sha512-MkhCqzzBEpPvxxQ71Md0b1Kk51W01lrYvlMzSUaIzNsODdd7mqhiimSZlr+VegAz5Z6Vzt9Xg2ttE//XBhH3EQ==", + "version": "1.11.1", + "resolved": "https://registry.npmjs.org/path-scurry/-/path-scurry-1.11.1.tgz", + "integrity": "sha512-Xa4Nw17FS9ApQFJ9umLiJS4orGjm7ZzwUrwamcGQuHSzDyth9boKDaycYdDcZDuqYATXw4HFXgaqWTctW/v1HA==", "dev": true, + "license": "BlueOak-1.0.0", "dependencies": { - "lru-cache": "^9.1.1 || ^10.0.0", + "lru-cache": "^10.2.0", "minipass": "^5.0.0 || ^6.0.2 || ^7.0.0" }, "engines": { - "node": ">=16 || 14 >=14.17" + "node": ">=16 || 14 >=14.18" }, "funding": { "url": "https://github.com/sponsors/isaacs" } }, "node_modules/preact": { - "version": "10.15.0", - "resolved": "https://registry.npmjs.org/preact/-/preact-10.15.0.tgz", - "integrity": "sha512-nZSa8M2R2m1n7nJSBlzDpxRJaIsejrTO1vlFbdpFvyC8qM1iU+On2y0otfoUm6SRB5o0lF0CKDFxg6grEFU0iQ==", + "version": "10.23.1", + "resolved": "https://registry.npmjs.org/preact/-/preact-10.23.1.tgz", + "integrity": "sha512-O5UdRsNh4vdZaTieWe3XOgSpdMAmkIYBCT3VhQDlKrzyCm8lUYsk0fmVEvoQQifoOjFRTaHZO69ylrzTW2BH+A==", + "license": "MIT", "funding": { "type": "opencollective", "url": "https://opencollective.com/preact" @@ -744,6 +821,7 @@ "resolved": "https://registry.npmjs.org/shebang-command/-/shebang-command-2.0.0.tgz", "integrity": "sha512-kHxr2zZpYtdmrN1qDjrrX/Z1rR1kG8Dx+gkpK1G4eXmvXswmcE1hTWBWYUzlraYw1/yZp6YuDY77YtvbN0dmDA==", "dev": true, + "license": "MIT", "dependencies": { "shebang-regex": "^3.0.0" }, @@ -756,6 +834,7 @@ "resolved": "https://registry.npmjs.org/shebang-regex/-/shebang-regex-3.0.0.tgz", "integrity": "sha512-7++dFhtcx3353uBaq8DDR4NuxBetBzC7ZQOhmTQInHEd6bSrXdiEyzCvG07Z44UYdLShWUyXt5M/yhz8ekcb1A==", "dev": true, + "license": "MIT", "engines": { "node": ">=8" } @@ -765,6 +844,7 @@ "resolved": "https://registry.npmjs.org/signal-exit/-/signal-exit-4.1.0.tgz", "integrity": "sha512-bzyZ1e88w9O1iNJbKnOlvYTrWPDl46O1bG0D3XInv+9tkPrxrN8jUUTiFlDkkmKWgn1M6CfIA13SuGqOa9Korw==", "dev": true, + "license": "ISC", "engines": { "node": ">=14" }, @@ -777,6 +857,7 @@ "resolved": "https://registry.npmjs.org/string-width/-/string-width-5.1.2.tgz", "integrity": "sha512-HnLOCR3vjcY8beoNLtcjZ5/nxn2afmME6lhrDrebokqMap+XbeW8n9TXpPDOqdGK5qcI3oT0GKTW6wC7EMiVqA==", "dev": true, + "license": "MIT", "dependencies": { "eastasianwidth": "^0.2.0", "emoji-regex": "^9.2.2", @@ -795,6 +876,7 @@ "resolved": "https://registry.npmjs.org/string-width/-/string-width-4.2.3.tgz", "integrity": "sha512-wKyQRQpjJ0sIp62ErSZdGsjMJWsap5oRNihHhu6G7JVO/9jIB6UyevL+tXuOqrng8j/cxKTWyWUwvSTriiZz/g==", "dev": true, + "license": "MIT", "dependencies": { "emoji-regex": "^8.0.0", "is-fullwidth-code-point": "^3.0.0", @@ -809,6 +891,7 @@ "resolved": "https://registry.npmjs.org/ansi-regex/-/ansi-regex-5.0.1.tgz", "integrity": "sha512-quJQXlTSUGL2LH9SUXo8VwsY4soanhgo6LNSm84E1LBcE8s3O0wpdiRzyR9z/ZZJMlMWv37qOOb9pdJlMUEKFQ==", "dev": true, + "license": "MIT", "engines": { "node": ">=8" } @@ -817,13 +900,15 @@ "version": "8.0.0", "resolved": "https://registry.npmjs.org/emoji-regex/-/emoji-regex-8.0.0.tgz", "integrity": "sha512-MSjYzcWNOA0ewAHpz0MxpYFvwg6yjy1NG3xteoqz644VCo/RPgnr1/GGt+ic3iJTzQ8Eu3TdM14SawnVUmGE6A==", - "dev": true + "dev": true, + "license": "MIT" }, "node_modules/string-width-cjs/node_modules/strip-ansi": { "version": "6.0.1", "resolved": "https://registry.npmjs.org/strip-ansi/-/strip-ansi-6.0.1.tgz", "integrity": "sha512-Y38VPSHcqkFrCpFnQ9vuSXmquuv5oXOKpGeT6aGrr3o3Gc9AlVa6JBfUSOCnbxGGZF+/0ooI7KrPuUSztUdU5A==", "dev": true, + "license": "MIT", "dependencies": { "ansi-regex": "^5.0.1" }, @@ -836,6 +921,7 @@ "resolved": "https://registry.npmjs.org/strip-ansi/-/strip-ansi-7.1.0.tgz", "integrity": "sha512-iq6eVVI64nQQTRYq2KtEg2d2uU7LElhTJwsH4YzIHZshxlgZms/wIc4VoDQTlG/IvVIrBKG06CrZnp0qv7hkcQ==", "dev": true, + "license": "MIT", "dependencies": { "ansi-regex": "^6.0.1" }, @@ -852,6 +938,7 @@ "resolved": "https://registry.npmjs.org/strip-ansi/-/strip-ansi-6.0.1.tgz", "integrity": "sha512-Y38VPSHcqkFrCpFnQ9vuSXmquuv5oXOKpGeT6aGrr3o3Gc9AlVa6JBfUSOCnbxGGZF+/0ooI7KrPuUSztUdU5A==", "dev": true, + "license": "MIT", "dependencies": { "ansi-regex": "^5.0.1" }, @@ -864,6 +951,7 @@ "resolved": "https://registry.npmjs.org/ansi-regex/-/ansi-regex-5.0.1.tgz", "integrity": "sha512-quJQXlTSUGL2LH9SUXo8VwsY4soanhgo6LNSm84E1LBcE8s3O0wpdiRzyR9z/ZZJMlMWv37qOOb9pdJlMUEKFQ==", "dev": true, + "license": "MIT", "engines": { "node": ">=8" } @@ -873,6 +961,7 @@ "resolved": "https://registry.npmjs.org/which/-/which-2.0.2.tgz", "integrity": "sha512-BLI3Tl1TW3Pvl70l3yq3Y64i+awpwXqsGBYWkkqMtnbXgrMD+yj7rhW0kuEDxzJaYXGjEW5ogapKNMEKNMjibA==", "dev": true, + "license": "ISC", "dependencies": { "isexe": "^2.0.0" }, @@ -888,6 +977,7 @@ "resolved": "https://registry.npmjs.org/wrap-ansi/-/wrap-ansi-8.1.0.tgz", "integrity": "sha512-si7QWI6zUMq56bESFvagtmzMdGOtoxfR+Sez11Mobfc7tm+VkUckk9bW2UeffTGVUbOksxmSw0AA2gs8g71NCQ==", "dev": true, + "license": "MIT", "dependencies": { "ansi-styles": "^6.1.0", "string-width": "^5.0.1", @@ -906,6 +996,7 @@ "resolved": "https://registry.npmjs.org/wrap-ansi/-/wrap-ansi-7.0.0.tgz", "integrity": "sha512-YVGIj2kamLSTxw6NsZjoBxfSwsn0ycdesmc4p+Q21c5zPuZ1pl+NfxVdxPtdHvmNVOQ6XSYG4AUtyt/Fi7D16Q==", "dev": true, + "license": "MIT", "dependencies": { "ansi-styles": "^4.0.0", "string-width": "^4.1.0", @@ -923,6 +1014,7 @@ "resolved": "https://registry.npmjs.org/ansi-regex/-/ansi-regex-5.0.1.tgz", "integrity": "sha512-quJQXlTSUGL2LH9SUXo8VwsY4soanhgo6LNSm84E1LBcE8s3O0wpdiRzyR9z/ZZJMlMWv37qOOb9pdJlMUEKFQ==", "dev": true, + "license": "MIT", "engines": { "node": ">=8" } @@ -932,6 +1024,7 @@ "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-4.3.0.tgz", "integrity": "sha512-zbB9rCJAT1rbjiVDb2hqKFHNYLxgtk8NURxZ3IZwD3F6NtxbXZQCnnSi1Lkx+IDohdPlFp222wVALIheZJQSEg==", "dev": true, + "license": "MIT", "dependencies": { "color-convert": "^2.0.1" }, @@ -946,13 +1039,15 @@ "version": "8.0.0", "resolved": "https://registry.npmjs.org/emoji-regex/-/emoji-regex-8.0.0.tgz", "integrity": "sha512-MSjYzcWNOA0ewAHpz0MxpYFvwg6yjy1NG3xteoqz644VCo/RPgnr1/GGt+ic3iJTzQ8Eu3TdM14SawnVUmGE6A==", - "dev": true + "dev": true, + "license": "MIT" }, "node_modules/wrap-ansi-cjs/node_modules/string-width": { "version": "4.2.3", "resolved": "https://registry.npmjs.org/string-width/-/string-width-4.2.3.tgz", "integrity": "sha512-wKyQRQpjJ0sIp62ErSZdGsjMJWsap5oRNihHhu6G7JVO/9jIB6UyevL+tXuOqrng8j/cxKTWyWUwvSTriiZz/g==", "dev": true, + "license": "MIT", "dependencies": { "emoji-regex": "^8.0.0", "is-fullwidth-code-point": "^3.0.0", @@ -967,6 +1062,7 @@ "resolved": "https://registry.npmjs.org/strip-ansi/-/strip-ansi-6.0.1.tgz", "integrity": "sha512-Y38VPSHcqkFrCpFnQ9vuSXmquuv5oXOKpGeT6aGrr3o3Gc9AlVa6JBfUSOCnbxGGZF+/0ooI7KrPuUSztUdU5A==", "dev": true, + "license": "MIT", "dependencies": { "ansi-regex": "^5.0.1" }, @@ -976,157 +1072,171 @@ } }, "dependencies": { + "@esbuild/aix-ppc64": { + "version": "0.23.0", + "resolved": "https://registry.npmjs.org/@esbuild/aix-ppc64/-/aix-ppc64-0.23.0.tgz", + "integrity": "sha512-3sG8Zwa5fMcA9bgqB8AfWPQ+HFke6uD3h1s3RIwUNK8EG7a4buxvuFTs3j1IMs2NXAk9F30C/FF4vxRgQCcmoQ==", + "dev": true, + "optional": true + }, "@esbuild/android-arm": { - "version": "0.19.5", - "resolved": "https://registry.npmjs.org/@esbuild/android-arm/-/android-arm-0.19.5.tgz", - "integrity": "sha512-bhvbzWFF3CwMs5tbjf3ObfGqbl/17ict2/uwOSfr3wmxDE6VdS2GqY/FuzIPe0q0bdhj65zQsvqfArI9MY6+AA==", + "version": "0.23.0", + "resolved": "https://registry.npmjs.org/@esbuild/android-arm/-/android-arm-0.23.0.tgz", + "integrity": "sha512-+KuOHTKKyIKgEEqKbGTK8W7mPp+hKinbMBeEnNzjJGyFcWsfrXjSTNluJHCY1RqhxFurdD8uNXQDei7qDlR6+g==", "dev": true, "optional": true }, "@esbuild/android-arm64": { - "version": "0.19.5", - "resolved": "https://registry.npmjs.org/@esbuild/android-arm64/-/android-arm64-0.19.5.tgz", - "integrity": "sha512-5d1OkoJxnYQfmC+Zd8NBFjkhyCNYwM4n9ODrycTFY6Jk1IGiZ+tjVJDDSwDt77nK+tfpGP4T50iMtVi4dEGzhQ==", + "version": "0.23.0", + "resolved": "https://registry.npmjs.org/@esbuild/android-arm64/-/android-arm64-0.23.0.tgz", + "integrity": "sha512-EuHFUYkAVfU4qBdyivULuu03FhJO4IJN9PGuABGrFy4vUuzk91P2d+npxHcFdpUnfYKy0PuV+n6bKIpHOB3prQ==", "dev": true, "optional": true }, "@esbuild/android-x64": { - "version": "0.19.5", - "resolved": "https://registry.npmjs.org/@esbuild/android-x64/-/android-x64-0.19.5.tgz", - "integrity": "sha512-9t+28jHGL7uBdkBjL90QFxe7DVA+KGqWlHCF8ChTKyaKO//VLuoBricQCgwhOjA1/qOczsw843Fy4cbs4H3DVA==", + "version": "0.23.0", + "resolved": "https://registry.npmjs.org/@esbuild/android-x64/-/android-x64-0.23.0.tgz", + "integrity": "sha512-WRrmKidLoKDl56LsbBMhzTTBxrsVwTKdNbKDalbEZr0tcsBgCLbEtoNthOW6PX942YiYq8HzEnb4yWQMLQuipQ==", "dev": true, "optional": true }, "@esbuild/darwin-arm64": { - "version": "0.19.5", - "resolved": "https://registry.npmjs.org/@esbuild/darwin-arm64/-/darwin-arm64-0.19.5.tgz", - "integrity": "sha512-mvXGcKqqIqyKoxq26qEDPHJuBYUA5KizJncKOAf9eJQez+L9O+KfvNFu6nl7SCZ/gFb2QPaRqqmG0doSWlgkqw==", + "version": "0.23.0", + "resolved": "https://registry.npmjs.org/@esbuild/darwin-arm64/-/darwin-arm64-0.23.0.tgz", + "integrity": "sha512-YLntie/IdS31H54Ogdn+v50NuoWF5BDkEUFpiOChVa9UnKpftgwzZRrI4J132ETIi+D8n6xh9IviFV3eXdxfow==", "dev": true, "optional": true }, "@esbuild/darwin-x64": { - "version": "0.19.5", - "resolved": "https://registry.npmjs.org/@esbuild/darwin-x64/-/darwin-x64-0.19.5.tgz", - "integrity": "sha512-Ly8cn6fGLNet19s0X4unjcniX24I0RqjPv+kurpXabZYSXGM4Pwpmf85WHJN3lAgB8GSth7s5A0r856S+4DyiA==", + "version": "0.23.0", + "resolved": "https://registry.npmjs.org/@esbuild/darwin-x64/-/darwin-x64-0.23.0.tgz", + "integrity": "sha512-IMQ6eme4AfznElesHUPDZ+teuGwoRmVuuixu7sv92ZkdQcPbsNHzutd+rAfaBKo8YK3IrBEi9SLLKWJdEvJniQ==", "dev": true, "optional": true }, "@esbuild/freebsd-arm64": { - "version": "0.19.5", - "resolved": "https://registry.npmjs.org/@esbuild/freebsd-arm64/-/freebsd-arm64-0.19.5.tgz", - "integrity": "sha512-GGDNnPWTmWE+DMchq1W8Sd0mUkL+APvJg3b11klSGUDvRXh70JqLAO56tubmq1s2cgpVCSKYywEiKBfju8JztQ==", + "version": "0.23.0", + "resolved": "https://registry.npmjs.org/@esbuild/freebsd-arm64/-/freebsd-arm64-0.23.0.tgz", + "integrity": "sha512-0muYWCng5vqaxobq6LB3YNtevDFSAZGlgtLoAc81PjUfiFz36n4KMpwhtAd4he8ToSI3TGyuhyx5xmiWNYZFyw==", "dev": true, "optional": true }, "@esbuild/freebsd-x64": { - "version": "0.19.5", - "resolved": "https://registry.npmjs.org/@esbuild/freebsd-x64/-/freebsd-x64-0.19.5.tgz", - "integrity": "sha512-1CCwDHnSSoA0HNwdfoNY0jLfJpd7ygaLAp5EHFos3VWJCRX9DMwWODf96s9TSse39Br7oOTLryRVmBoFwXbuuQ==", + "version": "0.23.0", + "resolved": "https://registry.npmjs.org/@esbuild/freebsd-x64/-/freebsd-x64-0.23.0.tgz", + "integrity": "sha512-XKDVu8IsD0/q3foBzsXGt/KjD/yTKBCIwOHE1XwiXmrRwrX6Hbnd5Eqn/WvDekddK21tfszBSrE/WMaZh+1buQ==", "dev": true, "optional": true }, "@esbuild/linux-arm": { - "version": "0.19.5", - "resolved": "https://registry.npmjs.org/@esbuild/linux-arm/-/linux-arm-0.19.5.tgz", - "integrity": "sha512-lrWXLY/vJBzCPC51QN0HM71uWgIEpGSjSZZADQhq7DKhPcI6NH1IdzjfHkDQws2oNpJKpR13kv7/pFHBbDQDwQ==", + "version": "0.23.0", + "resolved": "https://registry.npmjs.org/@esbuild/linux-arm/-/linux-arm-0.23.0.tgz", + "integrity": "sha512-SEELSTEtOFu5LPykzA395Mc+54RMg1EUgXP+iw2SJ72+ooMwVsgfuwXo5Fn0wXNgWZsTVHwY2cg4Vi/bOD88qw==", "dev": true, "optional": true }, "@esbuild/linux-arm64": { - "version": "0.19.5", - "resolved": "https://registry.npmjs.org/@esbuild/linux-arm64/-/linux-arm64-0.19.5.tgz", - "integrity": "sha512-o3vYippBmSrjjQUCEEiTZ2l+4yC0pVJD/Dl57WfPwwlvFkrxoSO7rmBZFii6kQB3Wrn/6GwJUPLU5t52eq2meA==", + "version": "0.23.0", + "resolved": "https://registry.npmjs.org/@esbuild/linux-arm64/-/linux-arm64-0.23.0.tgz", + "integrity": "sha512-j1t5iG8jE7BhonbsEg5d9qOYcVZv/Rv6tghaXM/Ug9xahM0nX/H2gfu6X6z11QRTMT6+aywOMA8TDkhPo8aCGw==", "dev": true, "optional": true }, "@esbuild/linux-ia32": { - "version": "0.19.5", - "resolved": "https://registry.npmjs.org/@esbuild/linux-ia32/-/linux-ia32-0.19.5.tgz", - "integrity": "sha512-MkjHXS03AXAkNp1KKkhSKPOCYztRtK+KXDNkBa6P78F8Bw0ynknCSClO/ztGszILZtyO/lVKpa7MolbBZ6oJtQ==", + "version": "0.23.0", + "resolved": "https://registry.npmjs.org/@esbuild/linux-ia32/-/linux-ia32-0.23.0.tgz", + "integrity": "sha512-P7O5Tkh2NbgIm2R6x1zGJJsnacDzTFcRWZyTTMgFdVit6E98LTxO+v8LCCLWRvPrjdzXHx9FEOA8oAZPyApWUA==", "dev": true, "optional": true }, "@esbuild/linux-loong64": { - "version": "0.19.5", - "resolved": "https://registry.npmjs.org/@esbuild/linux-loong64/-/linux-loong64-0.19.5.tgz", - "integrity": "sha512-42GwZMm5oYOD/JHqHska3Jg0r+XFb/fdZRX+WjADm3nLWLcIsN27YKtqxzQmGNJgu0AyXg4HtcSK9HuOk3v1Dw==", + "version": "0.23.0", + "resolved": "https://registry.npmjs.org/@esbuild/linux-loong64/-/linux-loong64-0.23.0.tgz", + "integrity": "sha512-InQwepswq6urikQiIC/kkx412fqUZudBO4SYKu0N+tGhXRWUqAx+Q+341tFV6QdBifpjYgUndV1hhMq3WeJi7A==", "dev": true, "optional": true }, "@esbuild/linux-mips64el": { - "version": "0.19.5", - "resolved": "https://registry.npmjs.org/@esbuild/linux-mips64el/-/linux-mips64el-0.19.5.tgz", - "integrity": "sha512-kcjndCSMitUuPJobWCnwQ9lLjiLZUR3QLQmlgaBfMX23UEa7ZOrtufnRds+6WZtIS9HdTXqND4yH8NLoVVIkcg==", + "version": "0.23.0", + "resolved": "https://registry.npmjs.org/@esbuild/linux-mips64el/-/linux-mips64el-0.23.0.tgz", + "integrity": "sha512-J9rflLtqdYrxHv2FqXE2i1ELgNjT+JFURt/uDMoPQLcjWQA5wDKgQA4t/dTqGa88ZVECKaD0TctwsUfHbVoi4w==", "dev": true, "optional": true }, "@esbuild/linux-ppc64": { - "version": "0.19.5", - "resolved": "https://registry.npmjs.org/@esbuild/linux-ppc64/-/linux-ppc64-0.19.5.tgz", - "integrity": "sha512-yJAxJfHVm0ZbsiljbtFFP1BQKLc8kUF6+17tjQ78QjqjAQDnhULWiTA6u0FCDmYT1oOKS9PzZ2z0aBI+Mcyj7Q==", + "version": "0.23.0", + "resolved": "https://registry.npmjs.org/@esbuild/linux-ppc64/-/linux-ppc64-0.23.0.tgz", + "integrity": "sha512-cShCXtEOVc5GxU0fM+dsFD10qZ5UpcQ8AM22bYj0u/yaAykWnqXJDpd77ublcX6vdDsWLuweeuSNZk4yUxZwtw==", "dev": true, "optional": true }, "@esbuild/linux-riscv64": { - "version": "0.19.5", - "resolved": "https://registry.npmjs.org/@esbuild/linux-riscv64/-/linux-riscv64-0.19.5.tgz", - "integrity": "sha512-5u8cIR/t3gaD6ad3wNt1MNRstAZO+aNyBxu2We8X31bA8XUNyamTVQwLDA1SLoPCUehNCymhBhK3Qim1433Zag==", + "version": "0.23.0", + "resolved": "https://registry.npmjs.org/@esbuild/linux-riscv64/-/linux-riscv64-0.23.0.tgz", + "integrity": "sha512-HEtaN7Y5UB4tZPeQmgz/UhzoEyYftbMXrBCUjINGjh3uil+rB/QzzpMshz3cNUxqXN7Vr93zzVtpIDL99t9aRw==", "dev": true, "optional": true }, "@esbuild/linux-s390x": { - "version": "0.19.5", - "resolved": "https://registry.npmjs.org/@esbuild/linux-s390x/-/linux-s390x-0.19.5.tgz", - "integrity": "sha512-Z6JrMyEw/EmZBD/OFEFpb+gao9xJ59ATsoTNlj39jVBbXqoZm4Xntu6wVmGPB/OATi1uk/DB+yeDPv2E8PqZGw==", + "version": "0.23.0", + "resolved": "https://registry.npmjs.org/@esbuild/linux-s390x/-/linux-s390x-0.23.0.tgz", + "integrity": "sha512-WDi3+NVAuyjg/Wxi+o5KPqRbZY0QhI9TjrEEm+8dmpY9Xir8+HE/HNx2JoLckhKbFopW0RdO2D72w8trZOV+Wg==", "dev": true, "optional": true }, "@esbuild/linux-x64": { - "version": "0.19.5", - "resolved": "https://registry.npmjs.org/@esbuild/linux-x64/-/linux-x64-0.19.5.tgz", - "integrity": "sha512-psagl+2RlK1z8zWZOmVdImisMtrUxvwereIdyJTmtmHahJTKb64pAcqoPlx6CewPdvGvUKe2Jw+0Z/0qhSbG1A==", + "version": "0.23.0", + "resolved": "https://registry.npmjs.org/@esbuild/linux-x64/-/linux-x64-0.23.0.tgz", + "integrity": "sha512-a3pMQhUEJkITgAw6e0bWA+F+vFtCciMjW/LPtoj99MhVt+Mfb6bbL9hu2wmTZgNd994qTAEw+U/r6k3qHWWaOQ==", "dev": true, "optional": true }, "@esbuild/netbsd-x64": { - "version": "0.19.5", - "resolved": "https://registry.npmjs.org/@esbuild/netbsd-x64/-/netbsd-x64-0.19.5.tgz", - "integrity": "sha512-kL2l+xScnAy/E/3119OggX8SrWyBEcqAh8aOY1gr4gPvw76la2GlD4Ymf832UCVbmuWeTf2adkZDK+h0Z/fB4g==", + "version": "0.23.0", + "resolved": "https://registry.npmjs.org/@esbuild/netbsd-x64/-/netbsd-x64-0.23.0.tgz", + "integrity": "sha512-cRK+YDem7lFTs2Q5nEv/HHc4LnrfBCbH5+JHu6wm2eP+d8OZNoSMYgPZJq78vqQ9g+9+nMuIsAO7skzphRXHyw==", + "dev": true, + "optional": true + }, + "@esbuild/openbsd-arm64": { + "version": "0.23.0", + "resolved": "https://registry.npmjs.org/@esbuild/openbsd-arm64/-/openbsd-arm64-0.23.0.tgz", + "integrity": "sha512-suXjq53gERueVWu0OKxzWqk7NxiUWSUlrxoZK7usiF50C6ipColGR5qie2496iKGYNLhDZkPxBI3erbnYkU0rQ==", "dev": true, "optional": true }, "@esbuild/openbsd-x64": { - "version": "0.19.5", - "resolved": "https://registry.npmjs.org/@esbuild/openbsd-x64/-/openbsd-x64-0.19.5.tgz", - "integrity": "sha512-sPOfhtzFufQfTBgRnE1DIJjzsXukKSvZxloZbkJDG383q0awVAq600pc1nfqBcl0ice/WN9p4qLc39WhBShRTA==", + "version": "0.23.0", + "resolved": "https://registry.npmjs.org/@esbuild/openbsd-x64/-/openbsd-x64-0.23.0.tgz", + "integrity": "sha512-6p3nHpby0DM/v15IFKMjAaayFhqnXV52aEmv1whZHX56pdkK+MEaLoQWj+H42ssFarP1PcomVhbsR4pkz09qBg==", "dev": true, "optional": true }, "@esbuild/sunos-x64": { - "version": "0.19.5", - "resolved": "https://registry.npmjs.org/@esbuild/sunos-x64/-/sunos-x64-0.19.5.tgz", - "integrity": "sha512-dGZkBXaafuKLpDSjKcB0ax0FL36YXCvJNnztjKV+6CO82tTYVDSH2lifitJ29jxRMoUhgkg9a+VA/B03WK5lcg==", + "version": "0.23.0", + "resolved": "https://registry.npmjs.org/@esbuild/sunos-x64/-/sunos-x64-0.23.0.tgz", + "integrity": "sha512-BFelBGfrBwk6LVrmFzCq1u1dZbG4zy/Kp93w2+y83Q5UGYF1d8sCzeLI9NXjKyujjBBniQa8R8PzLFAUrSM9OA==", "dev": true, "optional": true }, "@esbuild/win32-arm64": { - "version": "0.19.5", - "resolved": "https://registry.npmjs.org/@esbuild/win32-arm64/-/win32-arm64-0.19.5.tgz", - "integrity": "sha512-dWVjD9y03ilhdRQ6Xig1NWNgfLtf2o/STKTS+eZuF90fI2BhbwD6WlaiCGKptlqXlURVB5AUOxUj09LuwKGDTg==", + "version": "0.23.0", + "resolved": "https://registry.npmjs.org/@esbuild/win32-arm64/-/win32-arm64-0.23.0.tgz", + "integrity": "sha512-lY6AC8p4Cnb7xYHuIxQ6iYPe6MfO2CC43XXKo9nBXDb35krYt7KGhQnOkRGar5psxYkircpCqfbNDB4uJbS2jQ==", "dev": true, "optional": true }, "@esbuild/win32-ia32": { - "version": "0.19.5", - "resolved": "https://registry.npmjs.org/@esbuild/win32-ia32/-/win32-ia32-0.19.5.tgz", - "integrity": "sha512-4liggWIA4oDgUxqpZwrDhmEfAH4d0iljanDOK7AnVU89T6CzHon/ony8C5LeOdfgx60x5cnQJFZwEydVlYx4iw==", + "version": "0.23.0", + "resolved": "https://registry.npmjs.org/@esbuild/win32-ia32/-/win32-ia32-0.23.0.tgz", + "integrity": "sha512-7L1bHlOTcO4ByvI7OXVI5pNN6HSu6pUQq9yodga8izeuB1KcT2UkHaH6118QJwopExPn0rMHIseCTx1CRo/uNA==", "dev": true, "optional": true }, "@esbuild/win32-x64": { - "version": "0.19.5", - "resolved": "https://registry.npmjs.org/@esbuild/win32-x64/-/win32-x64-0.19.5.tgz", - "integrity": "sha512-czTrygUsB/jlM8qEW5MD8bgYU2Xg14lo6kBDXW6HdxKjh8M5PzETGiSHaz9MtbXBYDloHNUAUW2tMiKW4KM9Mw==", + "version": "0.23.0", + "resolved": "https://registry.npmjs.org/@esbuild/win32-x64/-/win32-x64-0.23.0.tgz", + "integrity": "sha512-Arm+WgUFLUATuoxCJcahGuk6Yj9Pzxd6l11Zb/2aAuv5kWWvvfhLFo2fni4uSK5vzlUdCGZ/BdV5tH8klj8p8g==", "dev": true, "optional": true }, @@ -1164,13 +1274,13 @@ "version": "file:node_modules/.dotnet/serenity.sleekgrid" }, "@serenity-is/tsbuild": { - "version": "8.0.1", - "resolved": "https://registry.npmjs.org/@serenity-is/tsbuild/-/tsbuild-8.0.1.tgz", - "integrity": "sha512-dAoI+wyzA2Z+M0jKyVy+WMm86vMmTMqINkZV614zwpQMM2WCmpyxO7UwfxEIchyX8MdBciJPh9WjIXwprQJbUw==", + "version": "8.6.0", + "resolved": "https://registry.npmjs.org/@serenity-is/tsbuild/-/tsbuild-8.6.0.tgz", + "integrity": "sha512-NoY/A34FHGRvUMUeKNSsryf7Eqh125rkR07xIbI0O/K/nybVoteMGCX3cWbsb2M9czBdmzWBKtXny7Mx9ZoyAQ==", "dev": true, "requires": { - "esbuild": "0.19.5", - "glob": "10.3.10" + "esbuild": "0.23.0", + "glob": "10.4.1" } }, "ansi-regex": { @@ -1244,39 +1354,41 @@ "dev": true }, "esbuild": { - "version": "0.19.5", - "resolved": "https://registry.npmjs.org/esbuild/-/esbuild-0.19.5.tgz", - "integrity": "sha512-bUxalY7b1g8vNhQKdB24QDmHeY4V4tw/s6Ak5z+jJX9laP5MoQseTOMemAr0gxssjNcH0MCViG8ONI2kksvfFQ==", + "version": "0.23.0", + "resolved": "https://registry.npmjs.org/esbuild/-/esbuild-0.23.0.tgz", + "integrity": "sha512-1lvV17H2bMYda/WaFb2jLPeHU3zml2k4/yagNMG8Q/YtfMjCwEUZa2eXXMgZTVSL5q1n4H7sQ0X6CdJDqqeCFA==", "dev": true, "requires": { - "@esbuild/android-arm": "0.19.5", - "@esbuild/android-arm64": "0.19.5", - "@esbuild/android-x64": "0.19.5", - "@esbuild/darwin-arm64": "0.19.5", - "@esbuild/darwin-x64": "0.19.5", - "@esbuild/freebsd-arm64": "0.19.5", - "@esbuild/freebsd-x64": "0.19.5", - "@esbuild/linux-arm": "0.19.5", - "@esbuild/linux-arm64": "0.19.5", - "@esbuild/linux-ia32": "0.19.5", - "@esbuild/linux-loong64": "0.19.5", - "@esbuild/linux-mips64el": "0.19.5", - "@esbuild/linux-ppc64": "0.19.5", - "@esbuild/linux-riscv64": "0.19.5", - "@esbuild/linux-s390x": "0.19.5", - "@esbuild/linux-x64": "0.19.5", - "@esbuild/netbsd-x64": "0.19.5", - "@esbuild/openbsd-x64": "0.19.5", - "@esbuild/sunos-x64": "0.19.5", - "@esbuild/win32-arm64": "0.19.5", - "@esbuild/win32-ia32": "0.19.5", - "@esbuild/win32-x64": "0.19.5" + "@esbuild/aix-ppc64": "0.23.0", + "@esbuild/android-arm": "0.23.0", + "@esbuild/android-arm64": "0.23.0", + "@esbuild/android-x64": "0.23.0", + "@esbuild/darwin-arm64": "0.23.0", + "@esbuild/darwin-x64": "0.23.0", + "@esbuild/freebsd-arm64": "0.23.0", + "@esbuild/freebsd-x64": "0.23.0", + "@esbuild/linux-arm": "0.23.0", + "@esbuild/linux-arm64": "0.23.0", + "@esbuild/linux-ia32": "0.23.0", + "@esbuild/linux-loong64": "0.23.0", + "@esbuild/linux-mips64el": "0.23.0", + "@esbuild/linux-ppc64": "0.23.0", + "@esbuild/linux-riscv64": "0.23.0", + "@esbuild/linux-s390x": "0.23.0", + "@esbuild/linux-x64": "0.23.0", + "@esbuild/netbsd-x64": "0.23.0", + "@esbuild/openbsd-arm64": "0.23.0", + "@esbuild/openbsd-x64": "0.23.0", + "@esbuild/sunos-x64": "0.23.0", + "@esbuild/win32-arm64": "0.23.0", + "@esbuild/win32-ia32": "0.23.0", + "@esbuild/win32-x64": "0.23.0" } }, "foreground-child": { - "version": "3.1.1", - "resolved": "https://registry.npmjs.org/foreground-child/-/foreground-child-3.1.1.tgz", - "integrity": "sha512-TMKDUnIte6bfb5nWv7V/caI169OHgvwjb7V4WkeUvbQQdjr5rWKqHFiKWb/fcOwB+CzBT+qbWjvj+DVwRskpIg==", + "version": "3.2.1", + "resolved": "https://registry.npmjs.org/foreground-child/-/foreground-child-3.2.1.tgz", + "integrity": "sha512-PXUUyLqrR2XCWICfv6ukppP96sdFwWbNEnfEMt7jNsISjMsvaLNinAHNDYyvkyU+SZG2BTSbT5NjG+vZslfGTA==", "dev": true, "requires": { "cross-spawn": "^7.0.0", @@ -1284,16 +1396,16 @@ } }, "glob": { - "version": "10.3.10", - "resolved": "https://registry.npmjs.org/glob/-/glob-10.3.10.tgz", - "integrity": "sha512-fa46+tv1Ak0UPK1TOy/pZrIybNNt4HCv7SDzwyfiOZkvZLEbjsZkJBPtDHVshZjbecAoAGSC20MjLDG/qr679g==", + "version": "10.4.1", + "resolved": "https://registry.npmjs.org/glob/-/glob-10.4.1.tgz", + "integrity": "sha512-2jelhlq3E4ho74ZyVLN03oKdAZVUa6UDZzFLVH1H7dnoax+y9qyaq8zBkfDIggjniU19z0wU18y16jMB2eyVIw==", "dev": true, "requires": { "foreground-child": "^3.1.0", - "jackspeak": "^2.3.5", - "minimatch": "^9.0.1", - "minipass": "^5.0.0 || ^6.0.2 || ^7.0.0", - "path-scurry": "^1.10.1" + "jackspeak": "^3.1.2", + "minimatch": "^9.0.4", + "minipass": "^7.1.2", + "path-scurry": "^1.11.1" } }, "is-fullwidth-code-point": { @@ -1309,9 +1421,9 @@ "dev": true }, "jackspeak": { - "version": "2.3.6", - "resolved": "https://registry.npmjs.org/jackspeak/-/jackspeak-2.3.6.tgz", - "integrity": "sha512-N3yCS/NegsOBokc8GAdM8UcmfsKiSS8cipheD/nivzr700H+nsMOxJjQnvwOcRYVuFkdH0wGUvW2WbXGmrZGbQ==", + "version": "3.4.3", + "resolved": "https://registry.npmjs.org/jackspeak/-/jackspeak-3.4.3.tgz", + "integrity": "sha512-OGlZQpz2yfahA/Rd1Y8Cd9SIEsqvXkLVoSw/cgwhnhFMDbsQFeZYoJJ7bIZBS9BcamUW96asq/npPWugM+RQBw==", "dev": true, "requires": { "@isaacs/cliui": "^8.0.2", @@ -1319,32 +1431,32 @@ } }, "jsx-dom": { - "version": "8.1.2", - "resolved": "https://registry.npmjs.org/jsx-dom/-/jsx-dom-8.1.2.tgz", - "integrity": "sha512-0hBsob3UwWlm5wD0S7sNFxAUrWAPzrt/r/K+AGzlRaCrPNu40+px77U7kgG+NS022nWjhOso+dZhqu1XFR7eXg==", + "version": "8.1.4", + "resolved": "https://registry.npmjs.org/jsx-dom/-/jsx-dom-8.1.4.tgz", + "integrity": "sha512-Wcv5iuOvB5SeF/tj3/sa+B0kqWb22WnlfPg8k64SmHOa/E+2M+cOruke+Dqr0GK2FY5xp0gEj4quWZM8quQN2w==", "requires": { "csstype": "^3.1.3" } }, "lru-cache": { - "version": "10.1.0", - "resolved": "https://registry.npmjs.org/lru-cache/-/lru-cache-10.1.0.tgz", - "integrity": "sha512-/1clY/ui8CzjKFyjdvwPWJUYKiFVXG2I2cY0ssG7h4+hwk+XOIX7ZSG9Q7TW8TW3Kp3BUSqgFWBLgL4PJ+Blag==", + "version": "10.4.3", + "resolved": "https://registry.npmjs.org/lru-cache/-/lru-cache-10.4.3.tgz", + "integrity": "sha512-JNAzZcXrCt42VGLuYz0zfAzDfAvJWW6AfYlDBQyDV5DClI2m5sAmK+OIO7s59XfsRsWHp02jAJrRadPRGTt6SQ==", "dev": true }, "minimatch": { - "version": "9.0.3", - "resolved": "https://registry.npmjs.org/minimatch/-/minimatch-9.0.3.tgz", - "integrity": "sha512-RHiac9mvaRw0x3AYRgDC1CxAP7HTcNrrECeA8YYJeWnpo+2Q5CegtZjaotWTWxDG3UeGA1coE05iH1mPjT/2mg==", + "version": "9.0.5", + "resolved": "https://registry.npmjs.org/minimatch/-/minimatch-9.0.5.tgz", + "integrity": "sha512-G6T0ZX48xgozx7587koeX9Ys2NYy6Gmv//P89sEte9V9whIapMNF4idKxnW2QtCcLiTWlb/wfCabAtAFWhhBow==", "dev": true, "requires": { "brace-expansion": "^2.0.1" } }, "minipass": { - "version": "7.0.4", - "resolved": "https://registry.npmjs.org/minipass/-/minipass-7.0.4.tgz", - "integrity": "sha512-jYofLM5Dam9279rdkWzqHozUo4ybjdZmCsDHePy5V/PbBcVMiSZR97gmAy45aqi8CK1lG2ECd356FU86avfwUQ==", + "version": "7.1.2", + "resolved": "https://registry.npmjs.org/minipass/-/minipass-7.1.2.tgz", + "integrity": "sha512-qOOzS1cBTWYF4BH8fVePDBOO9iptMnGUEZwNc/cMWnTV2nVLZ7VoNWEPHkYczZA0pdoA7dl6e7FL659nX9S2aw==", "dev": true }, "path-key": { @@ -1354,19 +1466,19 @@ "dev": true }, "path-scurry": { - "version": "1.10.1", - "resolved": "https://registry.npmjs.org/path-scurry/-/path-scurry-1.10.1.tgz", - "integrity": "sha512-MkhCqzzBEpPvxxQ71Md0b1Kk51W01lrYvlMzSUaIzNsODdd7mqhiimSZlr+VegAz5Z6Vzt9Xg2ttE//XBhH3EQ==", + "version": "1.11.1", + "resolved": "https://registry.npmjs.org/path-scurry/-/path-scurry-1.11.1.tgz", + "integrity": "sha512-Xa4Nw17FS9ApQFJ9umLiJS4orGjm7ZzwUrwamcGQuHSzDyth9boKDaycYdDcZDuqYATXw4HFXgaqWTctW/v1HA==", "dev": true, "requires": { - "lru-cache": "^9.1.1 || ^10.0.0", + "lru-cache": "^10.2.0", "minipass": "^5.0.0 || ^6.0.2 || ^7.0.0" } }, "preact": { - "version": "10.15.0", - "resolved": "https://registry.npmjs.org/preact/-/preact-10.15.0.tgz", - "integrity": "sha512-nZSa8M2R2m1n7nJSBlzDpxRJaIsejrTO1vlFbdpFvyC8qM1iU+On2y0otfoUm6SRB5o0lF0CKDFxg6grEFU0iQ==" + "version": "10.23.1", + "resolved": "https://registry.npmjs.org/preact/-/preact-10.23.1.tgz", + "integrity": "sha512-O5UdRsNh4vdZaTieWe3XOgSpdMAmkIYBCT3VhQDlKrzyCm8lUYsk0fmVEvoQQifoOjFRTaHZO69ylrzTW2BH+A==" }, "shebang-command": { "version": "2.0.0", diff --git a/src/Serene.Web/package.json b/src/Serene.Web/package.json index bcf9ccb3..b39de245 100644 --- a/src/Serene.Web/package.json +++ b/src/Serene.Web/package.json @@ -5,11 +5,11 @@ "@serenity-is/demo.northwind": "./node_modules/.dotnet/serenity.demo.northwind", "@serenity-is/extensions": "./node_modules/.dotnet/serenity.extensions", "@serenity-is/sleekgrid": "./node_modules/.dotnet/serenity.sleekgrid", - "jsx-dom": "8.1.2", - "preact": "10.15.0" + "jsx-dom": "8.1.4", + "preact": "10.23.1" }, "devDependencies": { - "@serenity-is/tsbuild": "8.0.1" + "@serenity-is/tsbuild": "8.6.0" }, "scripts": { "build": "npm run tsbuild", diff --git a/src/Serene.Web/tsconfig.json b/src/Serene.Web/tsconfig.json index d9add866..28c0cffa 100644 --- a/src/Serene.Web/tsconfig.json +++ b/src/Serene.Web/tsconfig.json @@ -2,23 +2,21 @@ "compileOnSave": true, "compilerOptions": { "allowJs": false, - "baseUrl": ".", "declaration": false, "emitBOM": true, "esModuleInterop": true, - "experimentalDecorators": true, "forceConsistentCasingInFileNames": true, "isolatedModules": true, "jsx": "react-jsx", "jsxImportSource": "jsx-dom/min", "module": "ESNext", "moduleResolution": "Node", + "newLine": "lf", "noEmit": true, - "noEmitHelpers": false, "noEmitOnError": false, "outDir": "./wwwroot/esm", "paths": { - "@/*": [ "Modules/*" ], + "@/*": [ "./Modules/*" ], "@serenity-is/*": [ "./node_modules/@serenity-is/*/dist/index", "./node_modules/.dotnet/serenity.*/dist/index" ], "react": [ "./node_modules/preact/compat/" ], "react-dom": [ "./node_modules/preact/compat/" ] @@ -28,13 +26,16 @@ "skipDefaultLibCheck": true, "skipLibCheck": true, "sourceMap": false, - "target": "ES6", + "target": "ES2017", "typeRoots": [ "./node_modules/@types" - ] + ], + "types": [ + ], + "useDefineForClassFields": false }, "include": [ - "./Modules/**/*" + "Modules" ], "typeAcquisition": { "enable": false diff --git a/src/Serene.Web/wwwroot/Content/site/site.css b/src/Serene.Web/wwwroot/Content/site/site.css index 4e24d272..bdc783d7 100644 --- a/src/Serene.Web/wwwroot/Content/site/site.css +++ b/src/Serene.Web/wwwroot/Content/site/site.css @@ -36,11 +36,11 @@ min-height: 450px; height: 450px; } -.s-UserPermissionDialog .s-DataGrid, -.s-RolePermissionDialog .s-DataGrid, -.s-UserRoleDialog .s-DataGrid { - height: 100%; + +.s-PermissionCheckEditor { + min-height: 450px; } + .s-UserPermissionDialog .ui-dialog-content, .s-RolePermissionDialog .ui-dialog-content, .s-UserRoleDialog .ui-dialog-content {