Skip to content

Commit

Permalink
OrchardCore.Cors (#2682)
Browse files Browse the repository at this point in the history
  • Loading branch information
MatthijsKrempel authored Dec 27, 2020
1 parent 195b54b commit de5a011
Show file tree
Hide file tree
Showing 22 changed files with 864 additions and 1 deletion.
9 changes: 8 additions & 1 deletion OrchardCore.sln
Original file line number Diff line number Diff line change
@@ -1,4 +1,3 @@

Microsoft Visual Studio Solution File, Format Version 12.00
# Visual Studio Version 16
VisualStudioVersion = 16.0.28822.285
Expand Down Expand Up @@ -343,6 +342,8 @@ Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "OrchardCore.Application.Cms
EndProject
Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "OrchardCore.Media.Core", "src\OrchardCore\OrchardCore.Media.Core\OrchardCore.Media.Core.csproj", "{8BC282D3-B7AF-495A-A5B1-D175875EB90E}"
EndProject
Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "OrchardCore.Cors", "src\OrchardCore.Modules\OrchardCore.Cors\OrchardCore.Cors.csproj", "{854876B6-23C9-4400-8B79-D5097B6AE6BE}"
EndProject
Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "OrchardCore.Benchmarks", "test\OrchardCore.Benchmarks\OrchardCore.Benchmarks.csproj", "{85610AB6-07E8-45E3-9C48-34D952CC5DD2}"
EndProject
Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "OrchardCore.Sitemaps.Abstractions", "src\OrchardCore\OrchardCore.Sitemaps.Abstractions\OrchardCore.Sitemaps.Abstractions.csproj", "{5899FB03-AB3F-4113-A3F0-59096B48FA37}"
Expand All @@ -352,6 +353,7 @@ EndProject
Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "OrchardCore.Contents.TagHelpers", "src\OrchardCore\OrchardCore.Contents.TagHelpers\OrchardCore.Contents.TagHelpers.csproj", "{6236734E-507B-461B-8E92-068886058E84}"
EndProject
Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "OrchardCore.Search.Abstractions", "src\OrchardCore\OrchardCore.Search.Abstractions\OrchardCore.Search.Abstractions.csproj", "{5283A8BC-DFF4-436D-AA9C-EE2DBFC5D51A}"
>>>>>>> dev
EndProject
Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "OrchardCore.PublishLater", "src\OrchardCore.Modules\OrchardCore.PublishLater\OrchardCore.PublishLater.csproj", "{FADCA695-7A6C-40F1-B17C-8A011EBC6F10}"
EndProject
Expand Down Expand Up @@ -975,6 +977,10 @@ Global
{85610AB6-07E8-45E3-9C48-34D952CC5DD2}.Debug|Any CPU.Build.0 = Debug|Any CPU
{85610AB6-07E8-45E3-9C48-34D952CC5DD2}.Release|Any CPU.ActiveCfg = Release|Any CPU
{85610AB6-07E8-45E3-9C48-34D952CC5DD2}.Release|Any CPU.Build.0 = Release|Any CPU
{854876B6-23C9-4400-8B79-D5097B6AE6BE}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
{854876B6-23C9-4400-8B79-D5097B6AE6BE}.Debug|Any CPU.Build.0 = Debug|Any CPU
{854876B6-23C9-4400-8B79-D5097B6AE6BE}.Release|Any CPU.ActiveCfg = Release|Any CPU
{854876B6-23C9-4400-8B79-D5097B6AE6BE}.Release|Any CPU.Build.0 = Release|Any CPU
{5899FB03-AB3F-4113-A3F0-59096B48FA37}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
{5899FB03-AB3F-4113-A3F0-59096B48FA37}.Debug|Any CPU.Build.0 = Debug|Any CPU
{5899FB03-AB3F-4113-A3F0-59096B48FA37}.Release|Any CPU.ActiveCfg = Release|Any CPU
Expand Down Expand Up @@ -1208,6 +1214,7 @@ Global
{AEDB2C9D-938E-484A-8DD8-7429E2BBB2A2} = {3398AB60-2DB7-464C-B211-C4120BE75582}
{8BC282D3-B7AF-495A-A5B1-D175875EB90E} = {F23AC6C2-DE44-4699-999D-3C478EF3D691}
{85610AB6-07E8-45E3-9C48-34D952CC5DD2} = {B8D16C60-99B4-43D5-A3AD-4CD89AF39B25}
{854876B6-23C9-4400-8B79-D5097B6AE6BE} = {A066395F-6F73-45DC-B5A6-B4E306110DCE}
{5899FB03-AB3F-4113-A3F0-59096B48FA37} = {F23AC6C2-DE44-4699-999D-3C478EF3D691}
{D87557AF-668B-4A0F-B079-FA35F71D1C56} = {90030E85-0C4F-456F-B879-443E8A3F220D}
{6236734E-507B-461B-8E92-068886058E84} = {F23AC6C2-DE44-4699-999D-3C478EF3D691}
Expand Down
1 change: 1 addition & 0 deletions mkdocs.yml
Original file line number Diff line number Diff line change
Expand Up @@ -161,6 +161,7 @@ nav:
- Features: docs/reference/modules/Features/README.md
- Contents: docs/reference/modules/Contents/README.md
- Configuration: docs/reference/core/Configuration/README.md
- Cors: docs/reference/core/Cors/README.md
- Custom Settings: docs/reference/modules/CustomSettings/README.md
- Placement: docs/reference/core/Placement/README.md
- Data: docs/reference/core/Data/README.md
Expand Down
37 changes: 37 additions & 0 deletions src/OrchardCore.Modules/OrchardCore.Cors/AdminMenu.cs
Original file line number Diff line number Diff line change
@@ -0,0 +1,37 @@
using System;
using System.Threading.Tasks;
using Microsoft.Extensions.Localization;
using OrchardCore.Navigation;

namespace OrchardCore.Cors
{
public class AdminMenu : INavigationProvider
{
public AdminMenu(IStringLocalizer<AdminMenu> localizer)
{
T = localizer;
}

public IStringLocalizer T { get; set; }

public Task BuildNavigationAsync(string name, NavigationBuilder builder)
{
if (!String.Equals(name, "admin", StringComparison.OrdinalIgnoreCase))
{
return Task.CompletedTask;
}

builder
.Add(T["Configuration"], configuration => configuration
.Add(T["Settings"], settings => settings
.Add(T["Cors"], "100", entry => entry
.Action("Index", "Admin", new { area = "OrchardCore.Cors" })
.Permission(Permissions.ManageCorsSettings)
.LocalNav()
))
);

return Task.CompletedTask;
}
}
}
8 changes: 8 additions & 0 deletions src/OrchardCore.Modules/OrchardCore.Cors/Assets.json
Original file line number Diff line number Diff line change
@@ -0,0 +1,8 @@
[
{
"inputs": [
"Assets/Admin/cors-admin.js"
],
"output": "wwwroot/Scripts/cors-admin.js"
}
]
Original file line number Diff line number Diff line change
@@ -0,0 +1,83 @@
var optionsList = Vue.component('options-list',
{
props: ['options', 'optionType', 'title', 'subTitle'],
template: '#options-list',
data: function () {
return {
'newOption': ''
};
},
methods: {
addOption: function (value) {
this.options.push(value);
},
deleteOption: function (value) {
this.options.splice($.inArray(value[0], this.options), 1);
}
}
});

var policyDetails = Vue.component('policy-details',
{
components: { optionsList : optionsList },
props: ['policy'],
template: '#policy-details'
});

var corsApp = new Vue({
el: '#corsAdmin',
components: { policyDetails : policyDetails, optionsList : optionsList },
data: {
selectedPolicy: null,
policies: null,
defaultPolicyName: null
},
methods: {
newPolicy: function () {
this.selectedPolicy = {
Name: 'New policy',
AllowedOrigins: [],
AllowAnyOrigin: true,
AllowedMethods: [],
AllowAnyMethod: true,
AllowedHeaders: [],
AllowAnyHeader: true,
AllowCredentials: true,
IsDefaultPolicy: false
};
},
editPolicy: function (policy) {
this.selectedPolicy = Object.assign({}, policy);
this.selectedPolicy.OriginalName = this.selectedPolicy.Name;
},
deletePolicy: function (policy, event) {
this.selectedPolicy = null;
var policyToRemove = this.policies.filter(function (item) { return item.Name === policy.Name; });
if (policyToRemove.length > 0)
this.policies.splice($.inArray(policyToRemove[0], this.policies), 1);
event.stopPropagation();
this.save();
},
updatePolicy: function (policy, event) {
if (policy.IsDefaultPolicy) {
this.policies.forEach(p => p.IsDefaultPolicy = false);
}
if (policy.OriginalName) {
var policyIndex = this.policies.findIndex((oldPolicy) => oldPolicy.Name === policy.OriginalName);
this.policies[policyIndex] = policy;
}
else {
this.policies.push(policy);
}
this.save();
this.back();
},
save: function () {
document.getElementById('CorsSettings').value = JSON.stringify(this.policies);
document.getElementById('corsForm').submit();
},
back: function () {
this.selectedPolicy = null;
}
}
});
Original file line number Diff line number Diff line change
@@ -0,0 +1,127 @@
using System.Collections.Generic;
using System.Linq;
using System.Threading.Tasks;
using Microsoft.AspNetCore.Authorization;
using Microsoft.AspNetCore.Mvc;
using Microsoft.AspNetCore.Mvc.Localization;
using Microsoft.Extensions.Localization;
using Newtonsoft.Json;
using OrchardCore.Admin;
using OrchardCore.Cors.Services;
using OrchardCore.Cors.Settings;
using OrchardCore.Cors.ViewModels;
using OrchardCore.DisplayManagement.Notify;

namespace OrchardCore.Cors.Controllers
{
[Admin]
public class AdminController : Controller
{
private readonly IAuthorizationService _authorizationService;
private readonly CorsService _corsService;
private readonly INotifier _notifier;

private readonly IStringLocalizer T;
private readonly IHtmlLocalizer<AdminController> TH;

public AdminController(
IAuthorizationService authorizationService,
IStringLocalizer<AdminController> stringLocalizer,
IHtmlLocalizer<AdminController> htmlLocalizer,
CorsService corsService,
INotifier notifier
)
{
TH = htmlLocalizer;
_notifier = notifier;
_corsService = corsService;
T = stringLocalizer;
_authorizationService = authorizationService;
}

[HttpGet]
public async Task<ActionResult> Index()
{
if (!await _authorizationService.AuthorizeAsync(User, Permissions.ManageCorsSettings))
{
return Unauthorized();
}

var settings = await _corsService.GetSettingsAsync();

var list = new List<CorsPolicyViewModel>();

if (settings?.Policies != null)
{
foreach (var policySetting in settings.Policies)
{
var policyViewModel = new CorsPolicyViewModel()
{
Name = policySetting.Name,
AllowAnyHeader = policySetting.AllowAnyHeader,
AllowedHeaders = policySetting.AllowedHeaders,
AllowAnyMethod = policySetting.AllowAnyMethod,
AllowedMethods = policySetting.AllowedMethods,
AllowAnyOrigin = policySetting.AllowAnyOrigin,
AllowedOrigins = policySetting.AllowedOrigins,
AllowCredentials = policySetting.AllowCredentials,
IsDefaultPolicy = policySetting.IsDefaultPolicy
};

list.Add(policyViewModel);
}
}

var viewModel = new CorsSettingsViewModel
{
Policies = list.ToArray()
};

return View(viewModel);
}

[HttpPost]
[ActionName(nameof(Index))]
public async Task<ActionResult> IndexPOST()
{
if (!await _authorizationService.AuthorizeAsync(User, Permissions.ManageCorsSettings))
{
return Unauthorized();
}

var model = new CorsSettingsViewModel();
var configJson = Request.Form["CorsSettings"].First();
model.Policies = JsonConvert.DeserializeObject<CorsPolicyViewModel[]>(configJson);

var corsPolicies = new List<CorsPolicySetting>();

foreach (var settingViewModel in model.Policies)
{
corsPolicies.Add(new CorsPolicySetting
{
Name = settingViewModel.Name,
AllowAnyHeader = settingViewModel.AllowAnyHeader,
AllowAnyMethod = settingViewModel.AllowAnyMethod,
AllowAnyOrigin = settingViewModel.AllowAnyOrigin,
AllowCredentials = settingViewModel.AllowCredentials,
AllowedHeaders = settingViewModel.AllowedHeaders,
AllowedMethods = settingViewModel.AllowedMethods,
AllowedOrigins = settingViewModel.AllowedOrigins,
IsDefaultPolicy =settingViewModel.IsDefaultPolicy

});
}

var corsSettings = new CorsSettings()
{
Policies = corsPolicies
};

await _corsService.UpdateSettingsAsync(corsSettings);

_notifier.Success(TH["Cors settings are updated"]);

return View(model);
}
}
}
9 changes: 9 additions & 0 deletions src/OrchardCore.Modules/OrchardCore.Cors/Manifest.cs
Original file line number Diff line number Diff line change
@@ -0,0 +1,9 @@
using OrchardCore.Modules.Manifest;

[assembly: Module(
Name = "Cors Configuration",
Author = "The Orchard Team",
Website = "http://orchardproject.net",
Version = "2.0.0",
Description = "Enables configuration of Cors settings",
Category = "Security")]
20 changes: 20 additions & 0 deletions src/OrchardCore.Modules/OrchardCore.Cors/OrchardCore.Cors.csproj
Original file line number Diff line number Diff line change
@@ -0,0 +1,20 @@
<Project Sdk="Microsoft.NET.Sdk.Razor">

<PropertyGroup>
<TargetFramework>$(AspNetCoreTargetFramework)</TargetFramework>
<AddRazorSupportForMvc>true</AddRazorSupportForMvc>
</PropertyGroup>

<ItemGroup>
<FrameworkReference Include="Microsoft.AspNetCore.App" />
</ItemGroup>

<ItemGroup>
<ProjectReference Include="..\..\OrchardCore\OrchardCore.Module.Targets\OrchardCore.Module.Targets.csproj" />
<ProjectReference Include="..\..\OrchardCore\OrchardCore.Navigation.Core\OrchardCore.Navigation.Core.csproj" />
<ProjectReference Include="..\..\OrchardCore\OrchardCore.Admin.Abstractions\OrchardCore.Admin.Abstractions.csproj" />
<ProjectReference Include="..\..\OrchardCore\OrchardCore.DisplayManagement\OrchardCore.DisplayManagement.csproj" />
<ProjectReference Include="..\..\OrchardCore\OrchardCore.Users.Core\OrchardCore.Users.Core.csproj" />
</ItemGroup>

</Project>
32 changes: 32 additions & 0 deletions src/OrchardCore.Modules/OrchardCore.Cors/Permissions.cs
Original file line number Diff line number Diff line change
@@ -0,0 +1,32 @@
using System.Collections.Generic;
using System.Linq;
using System.Threading.Tasks;
using OrchardCore.Security.Permissions;

namespace OrchardCore.Cors
{
public class Permissions : IPermissionProvider
{
public static readonly Permission ManageCorsSettings = new Permission("ManageCorsSettings", "Managing Cors Settings", isSecurityCritical: true);

public Task<IEnumerable<Permission>> GetPermissionsAsync()
{
return Task.FromResult(new[]
{
ManageCorsSettings
}
.AsEnumerable());
}

public IEnumerable<PermissionStereotype> GetDefaultStereotypes()
{
return new[] {
new PermissionStereotype {
Name = "Administrator",
Permissions = new[] { ManageCorsSettings }
},
};
}

}
}
Loading

0 comments on commit de5a011

Please sign in to comment.