diff --git a/Oqtane.Client/Modules/Controls/ActionLink.razor b/Oqtane.Client/Modules/Controls/ActionLink.razor index a4bcba0f..da02221c 100644 --- a/Oqtane.Client/Modules/Controls/ActionLink.razor +++ b/Oqtane.Client/Modules/Controls/ActionLink.razor @@ -1,5 +1,5 @@ -@namespace Oqtane.Modules.Controls -@inherits ModuleControlBase +@namespace Oqtane.Modules.Controls +@inherits LocalizableComponent @inject IUserService UserService @if (_authorized) @@ -56,6 +56,8 @@ protected override void OnParametersSet() { + base.OnParametersSet(); + _text = Action; if (!string.IsNullOrEmpty(Text)) { @@ -93,6 +95,7 @@ } + _text = Localize(nameof(Text)); _url = EditUrl(Action, _parameters); _authorized = IsAuthorized(); } diff --git a/Oqtane.Client/Modules/Controls/Label.razor b/Oqtane.Client/Modules/Controls/Label.razor index 0d32a14b..3869d8b4 100644 --- a/Oqtane.Client/Modules/Controls/Label.razor +++ b/Oqtane.Client/Modules/Controls/Label.razor @@ -1,6 +1,5 @@ -@namespace Oqtane.Modules.Controls -@inherits ModuleControlBase -@using Microsoft.Extensions.Localization +@namespace Oqtane.Modules.Controls +@inherits LocalizableComponent @if (!string.IsNullOrEmpty(HelpText)) { @@ -27,11 +26,10 @@ else [Parameter] public string HelpText { get; set; } // optional - tooltip for this label - [Parameter] - public string ResourceKey { get; set; } - protected override void OnParametersSet() { + base.OnParametersSet(); + _openLabel = "@localizer[$"{ResourceKey}.Text"]; - HelpText = localizer[$"{ResourceKey}.{nameof(HelpText)}"]; - } - } + ChildContent =@@Localize("Text"); + HelpText = Localize(nameof(HelpText)); } } } diff --git a/Oqtane.Client/Modules/Controls/LocalizableComponent.cs b/Oqtane.Client/Modules/Controls/LocalizableComponent.cs new file mode 100644 index 00000000..19e1aa46 --- /dev/null +++ b/Oqtane.Client/Modules/Controls/LocalizableComponent.cs @@ -0,0 +1,54 @@ +using System; +using Microsoft.AspNetCore.Components; +using Microsoft.Extensions.Localization; +using Oqtane.Shared; + +namespace Oqtane.Modules.Controls +{ + public class LocalizableComponent : ModuleControlBase + { + private IStringLocalizer _localizer; + + [Parameter] + public string ResourceKey { get; set; } + + protected bool IsLocalizable { get; private set; } + + protected string Localize(string name) + { + if (!IsLocalizable) + { + return null; + } + + var key = $"{ResourceKey}.{name}"; + + return _localizer?[key] ?? key; + } + + protected override void OnParametersSet() + { + if (!String.IsNullOrEmpty(ResourceKey)) + { + if (ModuleState?.ModuleType != null) + { + var moduleType = Type.GetType(ModuleState.ModuleType); + var localizerTypeName = $"Microsoft.Extensions.Localization.IStringLocalizer`1[[{moduleType.AssemblyQualifiedName}]], Microsoft.Extensions.Localization.Abstractions"; + var localizerType = Type.GetType(localizerTypeName); + + // HACK: Use ServiceActivator instead of injecting IHttpContextAccessor, because HttpContext throws NRE in WebAssembly runtime + using (var scope = ServiceActivator.GetScope()) + { + _localizer = (IStringLocalizer)scope.ServiceProvider.GetService(localizerType); + } + } + + IsLocalizable = true; + } + else + { + IsLocalizable = false; + } + } + } +} diff --git a/Oqtane.Client/Oqtane.Client.csproj b/Oqtane.Client/Oqtane.Client.csproj index 2161151e..fb628f7c 100644 --- a/Oqtane.Client/Oqtane.Client.csproj +++ b/Oqtane.Client/Oqtane.Client.csproj @@ -3,7 +3,6 @@ net5.0 Exe - 7.3 3.0 Debug;Release 1.0.4 diff --git a/Oqtane.Server/Startup.cs b/Oqtane.Server/Startup.cs index 2cff1aa0..8671e0f7 100644 --- a/Oqtane.Server/Startup.cs +++ b/Oqtane.Server/Startup.cs @@ -45,7 +45,7 @@ namespace Oqtane _supportedCultures = localizationManager.GetSupportedCultures(); _runtime = (Configuration.GetSection("Runtime").Value == "WebAssembly") ? Runtime.WebAssembly : Runtime.Server; - + //add possibility to switch off swagger on production. _useSwagger = Configuration.GetSection("UseSwagger").Value != "false"; @@ -92,13 +92,13 @@ namespace Oqtane // register custom authorization policies services.AddAuthorizationCore(options => { - options.AddPolicy("ViewPage", policy => policy.Requirements.Add(new PermissionRequirement(EntityNames.Page, PermissionNames.View))); - options.AddPolicy("EditPage", policy => policy.Requirements.Add(new PermissionRequirement(EntityNames.Page, PermissionNames.Edit))); - options.AddPolicy("ViewModule", policy => policy.Requirements.Add(new PermissionRequirement(EntityNames.Module, PermissionNames.View))); - options.AddPolicy("EditModule", policy => policy.Requirements.Add(new PermissionRequirement(EntityNames.Module, PermissionNames.Edit))); - options.AddPolicy("ViewFolder", policy => policy.Requirements.Add(new PermissionRequirement(EntityNames.Folder, PermissionNames.View))); - options.AddPolicy("EditFolder", policy => policy.Requirements.Add(new PermissionRequirement(EntityNames.Folder, PermissionNames.Edit))); - options.AddPolicy("ListFolder", policy => policy.Requirements.Add(new PermissionRequirement(EntityNames.Folder, PermissionNames.Browse))); + options.AddPolicy(PolicyNames.ViewPage, policy => policy.Requirements.Add(new PermissionRequirement(EntityNames.Page, PermissionNames.View))); + options.AddPolicy(PolicyNames.EditPage, policy => policy.Requirements.Add(new PermissionRequirement(EntityNames.Page, PermissionNames.Edit))); + options.AddPolicy(PolicyNames.ViewModule, policy => policy.Requirements.Add(new PermissionRequirement(EntityNames.Module, PermissionNames.View))); + options.AddPolicy(PolicyNames.EditModule, policy => policy.Requirements.Add(new PermissionRequirement(EntityNames.Module, PermissionNames.Edit))); + options.AddPolicy(PolicyNames.ViewFolder, policy => policy.Requirements.Add(new PermissionRequirement(EntityNames.Folder, PermissionNames.View))); + options.AddPolicy(PolicyNames.EditFolder, policy => policy.Requirements.Add(new PermissionRequirement(EntityNames.Folder, PermissionNames.Edit))); + options.AddPolicy(PolicyNames.ListFolder, policy => policy.Requirements.Add(new PermissionRequirement(EntityNames.Folder, PermissionNames.Browse))); }); // register scoped core services @@ -133,7 +133,7 @@ namespace Oqtane services.AddDbContext(options => options.UseSqlServer(Configuration.GetConnectionString("DefaultConnection") - .Replace("|DataDirectory|", AppDomain.CurrentDomain.GetData("DataDirectory")?.ToString()) + .Replace("|DataDirectory|", AppContext.GetData("DataDirectory")?.ToString()) )); services.AddDbContext(options => { }); diff --git a/Oqtane.Server/wwwroot/Modules/Templates/External/Server/Controllers/[Module]Controller.cs b/Oqtane.Server/wwwroot/Modules/Templates/External/Server/Controllers/[Module]Controller.cs index c8fe7485..3e2fe7b8 100644 --- a/Oqtane.Server/wwwroot/Modules/Templates/External/Server/Controllers/[Module]Controller.cs +++ b/Oqtane.Server/wwwroot/Modules/Templates/External/Server/Controllers/[Module]Controller.cs @@ -10,7 +10,7 @@ using [Owner].[Module].Repository; namespace [Owner].[Module].Controllers { - [Route("{alias}/api/[controller]")] + [Route(ControllerRoutes.Default)] public class [Module]Controller : Controller { private readonly I[Module]Repository _[Module]Repository; @@ -30,7 +30,7 @@ namespace [Owner].[Module].Controllers // GET: api/?moduleid=x [HttpGet] - [Authorize(Policy = "ViewModule")] + [Authorize(Policy = PolicyNames.ViewModule)] public IEnumerable Get(string moduleid) { return _[Module]Repository.Get[Module]s(int.Parse(moduleid)); @@ -38,7 +38,7 @@ namespace [Owner].[Module].Controllers // GET api//5 [HttpGet("{id}")] - [Authorize(Policy = "ViewModule")] + [Authorize(Policy = PolicyNames.ViewModule)] public Models.[Module] Get(int id) { Models.[Module] [Module] = _[Module]Repository.Get[Module](id); @@ -51,7 +51,7 @@ namespace [Owner].[Module].Controllers // POST api/ [HttpPost] - [Authorize(Policy = "EditModule")] + [Authorize(Policy = PolicyNames.EditModule)] public Models.[Module] Post([FromBody] Models.[Module] [Module]) { if (ModelState.IsValid && [Module].ModuleId == _entityId) @@ -64,7 +64,7 @@ namespace [Owner].[Module].Controllers // PUT api//5 [HttpPut("{id}")] - [Authorize(Policy = "EditModule")] + [Authorize(Policy = PolicyNames.EditModule)] public Models.[Module] Put(int id, [FromBody] Models.[Module] [Module]) { if (ModelState.IsValid && [Module].ModuleId == _entityId) @@ -77,7 +77,7 @@ namespace [Owner].[Module].Controllers // DELETE api//5 [HttpDelete("{id}")] - [Authorize(Policy = "EditModule")] + [Authorize(Policy = PolicyNames.EditModule)] public void Delete(int id) { Models.[Module] [Module] = _[Module]Repository.Get[Module](id); diff --git a/Oqtane.Server/wwwroot/Modules/Templates/External/Server/Scripts/[Owner].[Module].1.0.0.sql b/Oqtane.Server/wwwroot/Modules/Templates/External/Server/Scripts/[Owner].[Module].1.0.0.sql index 7a1b99ea..ca9ba39d 100644 --- a/Oqtane.Server/wwwroot/Modules/Templates/External/Server/Scripts/[Owner].[Module].1.0.0.sql +++ b/Oqtane.Server/wwwroot/Modules/Templates/External/Server/Scripts/[Owner].[Module].1.0.0.sql @@ -20,7 +20,7 @@ GO /* Create foreign key relationships */ -ALTER TABLE [dbo].[[Owner][Module]] WITH CHECK ADD CONSTRAINT [FK_[Owner][Module]_Module] FOREIGN KEY([ModuleId]) +ALTER TABLE [dbo].[[Owner][Module]] WITH CHECK ADD CONSTRAINT [FK_[Owner][Module]_Module] FOREIGN KEY([ModuleId]) REFERENCES [dbo].Module ([ModuleId]) ON DELETE CASCADE GO \ No newline at end of file diff --git a/Oqtane.Server/wwwroot/Modules/Templates/External/Shared/[Owner].[Module].Shared.csproj b/Oqtane.Server/wwwroot/Modules/Templates/External/Shared/[Owner].[Module].Shared.csproj index 4e6e520c..bfe5c9c6 100644 --- a/Oqtane.Server/wwwroot/Modules/Templates/External/Shared/[Owner].[Module].Shared.csproj +++ b/Oqtane.Server/wwwroot/Modules/Templates/External/Shared/[Owner].[Module].Shared.csproj @@ -2,7 +2,6 @@ netstandard2.1 - 7.3 1.0.0 [Owner].[Module] [Owner] diff --git a/Oqtane.Shared/Oqtane.Shared.csproj b/Oqtane.Shared/Oqtane.Shared.csproj index 8b35fbf1..3b02e634 100644 --- a/Oqtane.Shared/Oqtane.Shared.csproj +++ b/Oqtane.Shared/Oqtane.Shared.csproj @@ -2,7 +2,6 @@ net5.0 - 7.3 Debug;Release 1.0.4 Oqtane diff --git a/Oqtane.Shared/Shared/PolicyNames.cs b/Oqtane.Shared/Shared/PolicyNames.cs index 71e27a8d..0e478fe6 100644 --- a/Oqtane.Shared/Shared/PolicyNames.cs +++ b/Oqtane.Shared/Shared/PolicyNames.cs @@ -1,10 +1,19 @@ -using System; +using System; using System.Collections.Generic; using System.Text; -namespace Oqtane.Shared { - public class PolicyNames { +namespace Oqtane.Shared +{ + public class PolicyNames + { + public const string ViewPage = "ViewPage"; + public const string EditPage = "EditPage"; + public const string ViewModule = "ViewModule"; public const string EditModule = "EditModule"; + + public const string ViewFolder = "ViewFolder"; + public const string EditFolder = "EditFolder"; + public const string ListFolder = "ListFolder"; } } diff --git a/Oqtane.Test/Oqtane.Test.csproj b/Oqtane.Test/Oqtane.Test.csproj index 5fb17674..5ee42828 100644 --- a/Oqtane.Test/Oqtane.Test.csproj +++ b/Oqtane.Test/Oqtane.Test.csproj @@ -2,7 +2,6 @@ net5.0 - 7.3 Debug;Release 1.0.4 Oqtane diff --git a/Oqtane.Upgrade/Oqtane.Upgrade.csproj b/Oqtane.Upgrade/Oqtane.Upgrade.csproj index 73f4bad0..39d1a04e 100644 --- a/Oqtane.Upgrade/Oqtane.Upgrade.csproj +++ b/Oqtane.Upgrade/Oqtane.Upgrade.csproj @@ -2,7 +2,6 @@ net5.0 - 7.3 Exe 1.0.4 Oqtane