From 5bb7c63d44d042952502dc81378f118f57e80c7c Mon Sep 17 00:00:00 2001 From: hishamco Date: Mon, 19 Oct 2020 11:16:46 +0300 Subject: [PATCH 1/9] Introduce LocalizableComponent --- .../Modules/Controls/LocalizableComponent.cs | 34 +++++++++++++++++++ 1 file changed, 34 insertions(+) create mode 100644 Oqtane.Client/Modules/Controls/LocalizableComponent.cs diff --git a/Oqtane.Client/Modules/Controls/LocalizableComponent.cs b/Oqtane.Client/Modules/Controls/LocalizableComponent.cs new file mode 100644 index 00000000..e442c152 --- /dev/null +++ b/Oqtane.Client/Modules/Controls/LocalizableComponent.cs @@ -0,0 +1,34 @@ +using System; +using Microsoft.AspNetCore.Components; +using Microsoft.Extensions.Localization; +using Oqtane.Shared; + +namespace Oqtane.Modules.Controls +{ + public class LocalizableComponent : ModuleControlBase + { + [Parameter] + public string ResourceKey { get; set; } + + protected IStringLocalizer Localizer { get; private set; } + + 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); + } + } + } + } + } +} From fd5d777d3ad833f1de8255d8d36d77563f26a4ff Mon Sep 17 00:00:00 2001 From: hishamco Date: Mon, 19 Oct 2020 11:17:34 +0300 Subject: [PATCH 2/9] Label should use LocalizableComponent --- Oqtane.Client/Modules/Controls/Label.razor | 27 +++++----------------- 1 file changed, 6 insertions(+), 21 deletions(-) diff --git a/Oqtane.Client/Modules/Controls/Label.razor b/Oqtane.Client/Modules/Controls/Label.razor index 0d32a14b..8bde0ce7 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 =@@Localizer[$"{ResourceKey}.Text"]; + HelpText = Localizer[$"{ResourceKey}.{nameof(HelpText)}"]; } } } From fed56098a01ae983579b48211987c3c2f85ec758 Mon Sep 17 00:00:00 2001 From: hishamco Date: Mon, 19 Oct 2020 11:36:05 +0300 Subject: [PATCH 3/9] Avoid resource check in child components --- Oqtane.Client/Modules/Controls/Label.razor | 7 ++----- .../Modules/Controls/LocalizableComponent.cs | 11 +++++++++-- 2 files changed, 11 insertions(+), 7 deletions(-) diff --git a/Oqtane.Client/Modules/Controls/Label.razor b/Oqtane.Client/Modules/Controls/Label.razor index 8bde0ce7..c54ccc41 100644 --- a/Oqtane.Client/Modules/Controls/Label.razor +++ b/Oqtane.Client/Modules/Controls/Label.razor @@ -43,10 +43,7 @@ else _openLabel += ">"; - if (!string.IsNullOrEmpty(ResourceKey)) - { - ChildContent =@@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 index e442c152..328ba8d5 100644 --- a/Oqtane.Client/Modules/Controls/LocalizableComponent.cs +++ b/Oqtane.Client/Modules/Controls/LocalizableComponent.cs @@ -7,10 +7,17 @@ namespace Oqtane.Modules.Controls { public class LocalizableComponent : ModuleControlBase { + private IStringLocalizer _localizer; + [Parameter] public string ResourceKey { get; set; } - protected IStringLocalizer Localizer { get; private set; } + protected string Localize(string name) + { + var key = $"{ResourceKey}.{name}"; + + return _localizer?[key] ?? key; + } protected override void OnParametersSet() { @@ -25,7 +32,7 @@ namespace Oqtane.Modules.Controls // 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); + _localizer = (IStringLocalizer)scope.ServiceProvider.GetService(localizerType); } } } From 34b9903b15daa9520b558d52e5e0530d4d28a456 Mon Sep 17 00:00:00 2001 From: hishamco Date: Mon, 19 Oct 2020 12:16:35 +0300 Subject: [PATCH 4/9] Localize ActionLink --- Oqtane.Client/Modules/Controls/ActionLink.razor | 7 +++++-- 1 file changed, 5 insertions(+), 2 deletions(-) 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(); } From 1315e0382ed758748524e137fb56650b8372fdf0 Mon Sep 17 00:00:00 2001 From: Mike Casas Date: Mon, 19 Oct 2020 09:26:28 -0400 Subject: [PATCH 5/9] Update template to use the new constants. --- .../Server/Controllers/[Module]Controller.cs | 12 ++++++------ 1 file changed, 6 insertions(+), 6 deletions(-) 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); From 79b584f268ca155c85af929e52bad7e72179afc5 Mon Sep 17 00:00:00 2001 From: hishamco Date: Mon, 19 Oct 2020 21:47:59 +0300 Subject: [PATCH 6/9] Check needed if the component is localizable --- Oqtane.Client/Modules/Controls/Label.razor | 7 +++++-- .../Modules/Controls/LocalizableComponent.cs | 15 ++++++++++++++- 2 files changed, 19 insertions(+), 3 deletions(-) diff --git a/Oqtane.Client/Modules/Controls/Label.razor b/Oqtane.Client/Modules/Controls/Label.razor index c54ccc41..3869d8b4 100644 --- a/Oqtane.Client/Modules/Controls/Label.razor +++ b/Oqtane.Client/Modules/Controls/Label.razor @@ -43,7 +43,10 @@ else _openLabel += ">"; - ChildContent =@@Localize("Text"); - HelpText = Localize(nameof(HelpText)); + if (IsLocalizable) + { + ChildContent =@@Localize("Text"); + HelpText = Localize(nameof(HelpText)); + } } } diff --git a/Oqtane.Client/Modules/Controls/LocalizableComponent.cs b/Oqtane.Client/Modules/Controls/LocalizableComponent.cs index 328ba8d5..19e1aa46 100644 --- a/Oqtane.Client/Modules/Controls/LocalizableComponent.cs +++ b/Oqtane.Client/Modules/Controls/LocalizableComponent.cs @@ -12,10 +12,17 @@ namespace Oqtane.Modules.Controls [Parameter] public string ResourceKey { get; set; } + protected bool IsLocalizable { get; private set; } + protected string Localize(string name) { - var key = $"{ResourceKey}.{name}"; + if (!IsLocalizable) + { + return null; + } + var key = $"{ResourceKey}.{name}"; + return _localizer?[key] ?? key; } @@ -35,6 +42,12 @@ namespace Oqtane.Modules.Controls _localizer = (IStringLocalizer)scope.ServiceProvider.GetService(localizerType); } } + + IsLocalizable = true; + } + else + { + IsLocalizable = false; } } } From 70a345d2a907a5366b83c8032fafeae6b5153534 Mon Sep 17 00:00:00 2001 From: hishamco Date: Mon, 19 Oct 2020 22:11:51 +0300 Subject: [PATCH 7/9] Remove LangVersion --- Oqtane.Client/Oqtane.Client.csproj | 1 - .../Templates/External/Shared/[Owner].[Module].Shared.csproj | 1 - Oqtane.Shared/Oqtane.Shared.csproj | 1 - Oqtane.Test/Oqtane.Test.csproj | 1 - Oqtane.Upgrade/Oqtane.Upgrade.csproj | 1 - 5 files changed, 5 deletions(-) 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/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.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 From 8cf846ba904170dd2d099d0dafcb0c2495e37ad1 Mon Sep 17 00:00:00 2001 From: Tony Valenti Date: Mon, 19 Oct 2020 20:04:13 -0500 Subject: [PATCH 8/9] Factor out Policy Names Change AppDomain to AppContext --- Oqtane.Server/Startup.cs | 18 +++++++++--------- Oqtane.Shared/Shared/PolicyNames.cs | 15 ++++++++++++--- 2 files changed, 21 insertions(+), 12 deletions(-) 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.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"; } } From 17a9710c14463b40e1863ec66eed9d7228b8277c Mon Sep 17 00:00:00 2001 From: Mike Casas Date: Tue, 20 Oct 2020 07:31:24 -0400 Subject: [PATCH 9/9] Delete white space. --- .../External/Server/Scripts/[Owner].[Module].1.0.0.sql | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) 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