From 9d7adf128baf6aa613e2d0fe185e5e9710c418cd Mon Sep 17 00:00:00 2001 From: Georg von Kries Date: Tue, 21 Jan 2025 14:05:41 +0100 Subject: [PATCH 1/9] Throws an exception if the permission names are not unique. --- .../OrchardCore.Roles/Controllers/AdminController.cs | 6 ++++++ .../Security/Permissions/DefaultPermissionService.cs | 7 +++++-- 2 files changed, 11 insertions(+), 2 deletions(-) diff --git a/src/OrchardCore.Modules/OrchardCore.Roles/Controllers/AdminController.cs b/src/OrchardCore.Modules/OrchardCore.Roles/Controllers/AdminController.cs index e61517c8c73..a05553e323f 100644 --- a/src/OrchardCore.Modules/OrchardCore.Roles/Controllers/AdminController.cs +++ b/src/OrchardCore.Modules/OrchardCore.Roles/Controllers/AdminController.cs @@ -263,6 +263,7 @@ public async Task Delete(string id) private async Task>> GetInstalledPermissionsAsync() { + var allPermissions = new HashSet(StringComparer.OrdinalIgnoreCase); var installedPermissions = new Dictionary>(); var enabledFeatures = await _shellFeaturesManager.GetEnabledFeaturesAsync(); @@ -277,6 +278,11 @@ private async Task>> Get foreach (var permission in permissions) { + if (!allPermissions.Add(permission.Name)) + { + throw new InvalidOperationException($"The permission {permission.Name} already exists. Ambiguous permission names are not allowed."); + } + var groupKey = GetGroupKey(feature, permission.Category); if (installedPermissions.TryGetValue(groupKey, out var value)) diff --git a/src/OrchardCore/OrchardCore.Infrastructure.Abstractions/Security/Permissions/DefaultPermissionService.cs b/src/OrchardCore/OrchardCore.Infrastructure.Abstractions/Security/Permissions/DefaultPermissionService.cs index d3e350d774a..65b2ca5bcc6 100644 --- a/src/OrchardCore/OrchardCore.Infrastructure.Abstractions/Security/Permissions/DefaultPermissionService.cs +++ b/src/OrchardCore/OrchardCore.Infrastructure.Abstractions/Security/Permissions/DefaultPermissionService.cs @@ -41,7 +41,7 @@ public async ValueTask> GetPermissionsAsync() private async Task LoadPermissionsAsync() { - _permissions = []; + _permissions = new Dictionary(StringComparer.OrdinalIgnoreCase); foreach (var permissionProvider in _permissionProviders) { @@ -49,7 +49,10 @@ private async Task LoadPermissionsAsync() foreach (var permission in permissions) { - _permissions[permission.Name] = permission; + if (!_permissions.TryAdd(permission.Name, permission)) + { + throw new InvalidOperationException($"The permission {permission.Name} already exists. Ambiguous permission names are not allowed."); + } } } } From 7f90273a50addeb431517efc43f5d8524101f4a7 Mon Sep 17 00:00:00 2001 From: Georg von Kries Date: Tue, 21 Jan 2025 14:48:27 +0100 Subject: [PATCH 2/9] Register permissions only once. --- .../OrchardCore.Microsoft.Authentication/AzureADStartup.cs | 5 ++++- .../MicrosoftAccountStartup.cs | 5 ++++- 2 files changed, 8 insertions(+), 2 deletions(-) diff --git a/src/OrchardCore.Modules/OrchardCore.Microsoft.Authentication/AzureADStartup.cs b/src/OrchardCore.Modules/OrchardCore.Microsoft.Authentication/AzureADStartup.cs index a7f963ad9b9..8fa96d65122 100644 --- a/src/OrchardCore.Modules/OrchardCore.Microsoft.Authentication/AzureADStartup.cs +++ b/src/OrchardCore.Modules/OrchardCore.Microsoft.Authentication/AzureADStartup.cs @@ -23,7 +23,10 @@ public sealed class AzureADStartup : StartupBase { public override void ConfigureServices(IServiceCollection services) { - services.AddPermissionProvider(); + if (!services.Any(s => s.ImplementationType == typeof(Permissions))) + { + services.AddPermissionProvider(); + } services.AddSingleton(); services.AddRecipeExecutionStep(); diff --git a/src/OrchardCore.Modules/OrchardCore.Microsoft.Authentication/MicrosoftAccountStartup.cs b/src/OrchardCore.Modules/OrchardCore.Microsoft.Authentication/MicrosoftAccountStartup.cs index 9270d9ca2b9..077c8df1e75 100644 --- a/src/OrchardCore.Modules/OrchardCore.Microsoft.Authentication/MicrosoftAccountStartup.cs +++ b/src/OrchardCore.Modules/OrchardCore.Microsoft.Authentication/MicrosoftAccountStartup.cs @@ -22,7 +22,10 @@ public sealed class MicrosoftAccountStartup : StartupBase { public override void ConfigureServices(IServiceCollection services) { - services.AddPermissionProvider(); + if (!services.Any(s => s.ImplementationType == typeof(Permissions))) + { + services.AddPermissionProvider(); + } services.AddSingleton(); services.AddSiteDisplayDriver(); From 7f128e9ea77b4a955b6bd9dd02a0b2c039735f08 Mon Sep 17 00:00:00 2001 From: Georg von Kries Date: Tue, 21 Jan 2025 14:58:58 +0100 Subject: [PATCH 3/9] Ensure permission providers are registered only once in DI. --- .../OrchardCore.Microsoft.Authentication/AzureADStartup.cs | 5 +---- .../MicrosoftAccountStartup.cs | 5 +---- .../Permissions/PermissionsServiceCollectionExtensions.cs | 7 ++++++- 3 files changed, 8 insertions(+), 9 deletions(-) diff --git a/src/OrchardCore.Modules/OrchardCore.Microsoft.Authentication/AzureADStartup.cs b/src/OrchardCore.Modules/OrchardCore.Microsoft.Authentication/AzureADStartup.cs index 8fa96d65122..a7f963ad9b9 100644 --- a/src/OrchardCore.Modules/OrchardCore.Microsoft.Authentication/AzureADStartup.cs +++ b/src/OrchardCore.Modules/OrchardCore.Microsoft.Authentication/AzureADStartup.cs @@ -23,10 +23,7 @@ public sealed class AzureADStartup : StartupBase { public override void ConfigureServices(IServiceCollection services) { - if (!services.Any(s => s.ImplementationType == typeof(Permissions))) - { - services.AddPermissionProvider(); - } + services.AddPermissionProvider(); services.AddSingleton(); services.AddRecipeExecutionStep(); diff --git a/src/OrchardCore.Modules/OrchardCore.Microsoft.Authentication/MicrosoftAccountStartup.cs b/src/OrchardCore.Modules/OrchardCore.Microsoft.Authentication/MicrosoftAccountStartup.cs index 077c8df1e75..9270d9ca2b9 100644 --- a/src/OrchardCore.Modules/OrchardCore.Microsoft.Authentication/MicrosoftAccountStartup.cs +++ b/src/OrchardCore.Modules/OrchardCore.Microsoft.Authentication/MicrosoftAccountStartup.cs @@ -22,10 +22,7 @@ public sealed class MicrosoftAccountStartup : StartupBase { public override void ConfigureServices(IServiceCollection services) { - if (!services.Any(s => s.ImplementationType == typeof(Permissions))) - { - services.AddPermissionProvider(); - } + services.AddPermissionProvider(); services.AddSingleton(); services.AddSiteDisplayDriver(); diff --git a/src/OrchardCore/OrchardCore.Infrastructure.Abstractions/Security/Permissions/PermissionsServiceCollectionExtensions.cs b/src/OrchardCore/OrchardCore.Infrastructure.Abstractions/Security/Permissions/PermissionsServiceCollectionExtensions.cs index ecef453aa25..0291da6c00c 100644 --- a/src/OrchardCore/OrchardCore.Infrastructure.Abstractions/Security/Permissions/PermissionsServiceCollectionExtensions.cs +++ b/src/OrchardCore/OrchardCore.Infrastructure.Abstractions/Security/Permissions/PermissionsServiceCollectionExtensions.cs @@ -7,6 +7,11 @@ public static class PermissionsServiceCollectionExtensions public static IServiceCollection AddPermissionProvider(this IServiceCollection services) where TProvider : class, IPermissionProvider { - return services.AddScoped(); + if (!services.Any(s => s.ImplementationType == typeof(TProvider))) + { + services.AddScoped(); + } + + return services; } } From f021704ea616a4357a121dea4015e6b9095db5c9 Mon Sep 17 00:00:00 2001 From: Georg von Kries Date: Wed, 22 Jan 2025 11:00:29 +0100 Subject: [PATCH 4/9] Show an error message in the admin instead of throwing an exception. --- .../Controllers/AdminController.cs | 18 +++++++++--------- .../OrchardCore.Roles/Views/Admin/Edit.cshtml | 14 ++++++++++++++ .../Permissions/DefaultPermissionService.cs | 5 +---- 3 files changed, 24 insertions(+), 13 deletions(-) diff --git a/src/OrchardCore.Modules/OrchardCore.Roles/Controllers/AdminController.cs b/src/OrchardCore.Modules/OrchardCore.Roles/Controllers/AdminController.cs index a05553e323f..68cb2918bcc 100644 --- a/src/OrchardCore.Modules/OrchardCore.Roles/Controllers/AdminController.cs +++ b/src/OrchardCore.Modules/OrchardCore.Roles/Controllers/AdminController.cs @@ -167,11 +167,17 @@ public async Task Edit(string id) IsAdminRole = await _roleService.IsAdminRoleAsync(role.RoleName), }; + var installedPermissions = await GetInstalledPermissionsAsync(); + var allPermissions = installedPermissions.SelectMany(x => x.Value); + + ViewData["DuplicatedPermissions"] = allPermissions + .GroupBy(p => p.Name.ToUpperInvariant()) + .Where(g => g.Count() > 1) + .Select(g => g.First().Name) + .ToArray(); + if (!await _roleService.IsAdminRoleAsync(role.RoleName)) { - var installedPermissions = await GetInstalledPermissionsAsync(); - var allPermissions = installedPermissions.SelectMany(x => x.Value); - model.EffectivePermissions = await GetEffectivePermissions(role, allPermissions); model.RoleCategoryPermissions = installedPermissions; } @@ -263,7 +269,6 @@ public async Task Delete(string id) private async Task>> GetInstalledPermissionsAsync() { - var allPermissions = new HashSet(StringComparer.OrdinalIgnoreCase); var installedPermissions = new Dictionary>(); var enabledFeatures = await _shellFeaturesManager.GetEnabledFeaturesAsync(); @@ -278,11 +283,6 @@ private async Task>> Get foreach (var permission in permissions) { - if (!allPermissions.Add(permission.Name)) - { - throw new InvalidOperationException($"The permission {permission.Name} already exists. Ambiguous permission names are not allowed."); - } - var groupKey = GetGroupKey(feature, permission.Category); if (installedPermissions.TryGetValue(groupKey, out var value)) diff --git a/src/OrchardCore.Modules/OrchardCore.Roles/Views/Admin/Edit.cshtml b/src/OrchardCore.Modules/OrchardCore.Roles/Views/Admin/Edit.cshtml index 93aa0c4c5cb..1fe85165bea 100644 --- a/src/OrchardCore.Modules/OrchardCore.Roles/Views/Admin/Edit.cshtml +++ b/src/OrchardCore.Modules/OrchardCore.Roles/Views/Admin/Edit.cshtml @@ -3,6 +3,20 @@

@RenderTitleSegments(T["Edit '{0}' Role", Model.Name])

+@if (ViewData["DuplicatedPermissions"] is string[] duplicatedPermissions && duplicatedPermissions.Length > 0) +{ + +} +
diff --git a/src/OrchardCore/OrchardCore.Infrastructure.Abstractions/Security/Permissions/DefaultPermissionService.cs b/src/OrchardCore/OrchardCore.Infrastructure.Abstractions/Security/Permissions/DefaultPermissionService.cs index 65b2ca5bcc6..9c96ba03b85 100644 --- a/src/OrchardCore/OrchardCore.Infrastructure.Abstractions/Security/Permissions/DefaultPermissionService.cs +++ b/src/OrchardCore/OrchardCore.Infrastructure.Abstractions/Security/Permissions/DefaultPermissionService.cs @@ -49,10 +49,7 @@ private async Task LoadPermissionsAsync() foreach (var permission in permissions) { - if (!_permissions.TryAdd(permission.Name, permission)) - { - throw new InvalidOperationException($"The permission {permission.Name} already exists. Ambiguous permission names are not allowed."); - } + _permissions[permission.Name] = permission; } } } From a80d7a7789f28195efbccc330061f68c3ede6ff5 Mon Sep 17 00:00:00 2001 From: Georg von Kries Date: Thu, 23 Jan 2025 10:14:23 +0100 Subject: [PATCH 5/9] Log an error on startup, if permissions are ambiguous. --- .../Security/OrchardCoreBuilderExtensions.cs | 28 +++++++++++++++++++ 1 file changed, 28 insertions(+) diff --git a/src/OrchardCore/OrchardCore.Infrastructure/Security/OrchardCoreBuilderExtensions.cs b/src/OrchardCore/OrchardCore.Infrastructure/Security/OrchardCoreBuilderExtensions.cs index 1b43d450587..90f8f1b0449 100644 --- a/src/OrchardCore/OrchardCore.Infrastructure/Security/OrchardCoreBuilderExtensions.cs +++ b/src/OrchardCore/OrchardCore.Infrastructure/Security/OrchardCoreBuilderExtensions.cs @@ -1,5 +1,8 @@ using Microsoft.AspNetCore.Authentication; using Microsoft.AspNetCore.Authorization; +using Microsoft.AspNetCore.Builder; +using Microsoft.AspNetCore.Routing; +using Microsoft.Extensions.Logging; using OrchardCore.Security; using OrchardCore.Security.AuthorizationHandlers; using OrchardCore.Security.Permissions; @@ -30,6 +33,31 @@ public static OrchardCoreBuilder AddSecurity(this OrchardCoreBuilder builder) services.AddScoped(); }); + builder.Configure(ValidatePermissionsAsync); + return builder; } + + private static async ValueTask ValidatePermissionsAsync(IApplicationBuilder builder, IEndpointRouteBuilder routeBuilder, IServiceProvider serviceProvider) + { + // Make sure registered permissions are valid, i.e. they must be unique. + var permissionProviders = serviceProvider.GetServices(); + var permissionNames = new HashSet(StringComparer.OrdinalIgnoreCase); + ILogger logger = null; + + foreach (var permissionProvider in permissionProviders) + { + var permissions = await permissionProvider.GetPermissionsAsync(); + + foreach (var permission in permissions) + { + if(!permissionNames.Add(permission.Name)) + { + logger ??= serviceProvider.GetRequiredService>(); + + logger.LogError("The permission '{PermissionName}' created by the permission provider '{PermissionProvider}' is already registered. Each permission must have a unique name across all modules.", permission.Name, permissionProvider.GetType()); + } + } + } + } } From 7de9d0ca0f6da228dd5b0f7bf01e3c8e845531c3 Mon Sep 17 00:00:00 2001 From: Georg von Kries Date: Fri, 24 Jan 2025 10:01:28 +0100 Subject: [PATCH 6/9] Added some code documentation. --- .../Security/Permissions/Permission.cs | 60 +++++++++++++++++++ 1 file changed, 60 insertions(+) diff --git a/src/OrchardCore/OrchardCore.Infrastructure.Abstractions/Security/Permissions/Permission.cs b/src/OrchardCore/OrchardCore.Infrastructure.Abstractions/Security/Permissions/Permission.cs index 7610b7f3961..bafe5659a75 100644 --- a/src/OrchardCore/OrchardCore.Infrastructure.Abstractions/Security/Permissions/Permission.cs +++ b/src/OrchardCore/OrchardCore.Infrastructure.Abstractions/Security/Permissions/Permission.cs @@ -2,10 +2,24 @@ namespace OrchardCore.Security.Permissions; +/// +/// Represents a permission within the system. +/// +/// +/// The permission name must be unique across the system. +/// public class Permission { public const string ClaimType = "Permission"; + /// + /// Initializes a new instance of the class. + /// + /// The name of the permission. + /// Thrown when the name is null. + /// + /// The permission name must be unique across the system. + /// public Permission(string name) { ArgumentNullException.ThrowIfNull(name); @@ -13,23 +27,69 @@ public Permission(string name) Name = name; } + /// + /// Initializes a new instance of the class with a description and security flag. + /// + /// The name of the permission. + /// The description of the permission. + /// Indicates whether the permission is security critical. + /// + /// The permission name must be unique across the system. + /// public Permission(string name, string description, bool isSecurityCritical = false) : this(name) { Description = description; IsSecurityCritical = isSecurityCritical; } + /// + /// Initializes a new instance of the class with a description, implying permissions, and security flag. + /// + /// The name of the permission. + /// The description of the permission. + /// The permissions implying this permission. + /// Indicates whether the permission is security critical. + /// + /// The permission name must be unique across the system. + /// public Permission(string name, string description, IEnumerable impliedBy, bool isSecurityCritical = false) : this(name, description, isSecurityCritical) { ImpliedBy = impliedBy; } + /// + /// Gets the name of the permission. + /// + /// + /// The permission name must be unique across the system. + /// public string Name { get; } + + /// + /// Gets or sets the description of the permission. + /// public string Description { get; set; } + + /// + /// Gets or sets the category of the permission. + /// public string Category { get; set; } + + /// + /// Gets the permissions implying this permission. + /// public IEnumerable ImpliedBy { get; } + + /// + /// Gets a value indicating whether the permission is security critical. + /// public bool IsSecurityCritical { get; } + /// + /// Converts a to a . + /// + /// The permission to convert. + /// A claim representing the permission. public static implicit operator Claim(Permission p) { return new Claim(ClaimType, p.Name); From 03f03715e2a6efeb6ef2b55baeecfbc3e08511bb Mon Sep 17 00:00:00 2001 From: Georg von Kries Date: Fri, 24 Jan 2025 11:18:27 +0100 Subject: [PATCH 7/9] Added a basic documentation page for permissions. --- src/docs/topics/security/Permissions.md | 149 ++++++++++++++++++++++++ src/docs/topics/security/README.md | 2 +- 2 files changed, 150 insertions(+), 1 deletion(-) create mode 100644 src/docs/topics/security/Permissions.md diff --git a/src/docs/topics/security/Permissions.md b/src/docs/topics/security/Permissions.md new file mode 100644 index 00000000000..a00dc956a47 --- /dev/null +++ b/src/docs/topics/security/Permissions.md @@ -0,0 +1,149 @@ +# Orchard Core Permissions + +Orchard Core provides a comprehensive set of permissions to manage various aspects of the system. Below is a list of permissions along with their descriptions. Note that security critical permissions allow users to elevate their permissions and should be assigned with caution. + + +| Permission Group | Permission | Description | +|------------------|------------|-------------| +| Admin (OrchardCore.Admin) | AccessAdminPanel | Access admin panel | +| | ManageAdminSettings | Manage Admin Settings | +| Admin Menu (OrchardCore.AdminMenu) | ManageAdminMenu | Manage the admin menu | +| | ViewAdminMenu_[MenuName] | View Admin Menu - [MenuName] | +| | ViewAdminMenuAll | View Admin Menu - View All | +| Amazon Media Storage (OrchardCore.Media.AmazonS3) | ViewAmazonS3MediaOptions | View Amazon S3 Media Options | +| Audit Trail (OrchardCore.AuditTrail) | ManageAuditTrailSettings | Manage audit trail settings | +| | ViewAuditTrail | View audit trail | +| Autoroute (OrchardCore.Autoroute) | SetHomepage | Set homepage | +| Azure Media ImageSharp Image Cache (OrchardCore.Media.Azure.ImageSharpImageCache) | ViewAzureMediaOptions | View Azure Media Options | +| Background Tasks (OrchardCore.BackgroundTasks) | ManageBackgroundTasks | Manage background tasks | +| Permissions for each Content Type | Clone_[ContentType] | Clone [ContentType] by others | +| | CloneOwn_[ContentType] | Clone own [ContentType] | +| | DeleteOwn_[ContentType] | Delete [ContentType] | +| | Delete_[ContentType] | Delete [ContentType] for others | +| | EditOwn_[ContentType] | Edit [ContentType] | +| | Edit_[ContentType] | Edit [ContentType] for others | +| | EditContentOwner_[ContentType] | Edit the owner of a [ContentType] content item | +| | ListContent_[ContentType] | List [ContentType] content items | +| | Preview_[ContentType] | Preview [ContentType] by others | +| | PreviewOwn_[ContentType] | Preview own [ContentType] | +| | PublishOwn_[ContentType] | Publish or unpublish [ContentType] | +| | Publish_[ContentType] | Publish or unpublish [ContentType] for others | +| | View_[ContentType] | View [ContentType] by others | +| | ViewOwn_[ContentType] | View own [ContentType] | +| Content Localization (OrchardCore.ContentLocalization) | LocalizeContent | Localize content for others | +| | LocalizeOwnContent | Localize own content | +| | ManageContentCulturePicker | Manage ContentCulturePicker settings | +| Content Types (OrchardCore.ContentTypes) | EditContentTypes (security critical) | Edit content types | +| | ViewContentTypes | View content types | +| Contents (OrchardCore.Contents) | AccessContentApi | Access content via the api | +| | ApiViewContent | Access view content endpoints | +| | CloneContent | Clone content | +| | CloneOwnContent | Clone own content | +| | DeleteContent | Delete content for others | +| | DeleteOwnContent | Delete own content | +| | EditContent | Edit content for others | +| | EditOwnContent | Edit own content | +| | EditContentOwner | Edit the owner of a content item | +| | ListContent | List content items | +| | PreviewContent | Preview content | +| | PreviewOwnContent | Preview own content | +| | PublishContent | Publish or unpublish content for others | +| | PublishOwnContent | Publish or unpublish own content | +| | ViewContent | View all content | +| | ViewOwnContent | View own content | +| Custom Settings (OrchardCore.CustomSettings) | ManageCustomSettings_[CustomSettingsType] | Manage Custom Settings | +| Deployment (OrchardCore.Deployment) | Export | Export Data | +| | Import (security critical) | Import Data | +| | ManageDeploymentPlan | Manage deployment plans | +| Elasticsearch (OrchardCore.Search.Elasticsearch) | ManageElasticIndexes | Manage Elasticsearch Indexes | +| | QueryElasticsearchApi | Query Elasticsearch Api | +| Email (OrchardCore.Email) | ManageEmailSettings | Manage Email Settings | +| Features (OrchardCore.Features) | ManageFeatures | Manage Features | +| GitHub Authentication (OrchardCore.GitHub.Authentication) | ManageGitHubAuthentication | Manage GitHub Authentication settings | +| Google Tag Manager (OrchardCore.Google.TagManager) | ManageGoogleAnalytics | Manage Google Analytics settings | +| | ManageGoogleAuthentication | Manage Google Authentication settings | +| | ManageGoogleTagManager | Manage Google Tag Manager settings | +| GraphQL (OrchardCore.Apis.GraphQL) | ExecuteGraphQLMutations | Execute GraphQL Mutations | +| | ExecuteGraphQL | Execute GraphQL | +| HTTPS (OrchardCore.Https) | ManageHttps | Manage HTTPS | +| Layers (OrchardCore.Layers) | ManageLayers | Manage layers | +| Localization (OrchardCore.Localization) | ManageCultures | Manage supported culture | +| Media (OrchardCore.Media) | ManageMediaFolder | Manage All Media Folders | +| | ManageAttachedMediaFieldsFolder | Manage Attached Media Fields Folder | +| | ManageMediaContent | Manage Media | +| | ManageOthersMediaContent | Manage Media For Others | +| | ManageMediaProfiles | Manage Media Profiles | +| | ManageOwnMediaContent | Manage Own Media | +| | ViewMediaOptions | View Media Options | +| Media Cache (OrchardCore.Media.Cache) | ManageAssetCache | Manage Asset Cache Folder | +| Menu (OrchardCore.Menu) | ManageMenu | Manage menus | +| Meta Core Components (OrchardCore.Facebook) | ManageFacebookApp | View and edit the Facebook app | +| Meta Pixel (OrchardCore.Facebook.Pixel) | ManageFacebookPixel | Manage Facebook Pixel settings | +| Microsoft Entra ID (Azure Active Directory) Authentication (OrchardCore.Microsoft.Authentication.AzureAD) | ManageMicrosoftAuthentication | Manage Microsoft Authentication settings | +| Notifications (OrchardCore.Notifications) | ManageNotifications | Manage notifications | +| OpenID Connect Core Services (OrchardCore.OpenId) | ManageClientSettings | View and edit the OpenID Connect client settings | +| | ManageServerSettings | View and edit the OpenID Connect server settings | +| | ManageValidationSettings | View and edit the OpenID Connect validation settings | +| | ManageApplications | View, add, edit and remove the OpenID Connect applications | +| | ManageScopes | View, add, edit and remove the OpenID Connect scopes | +| Placements (OrchardCore.Placements) | ManagePlacements | Manage placements | +| Queries (OrchardCore.Queries) | ExecuteApiAll | Execute Api - All queries | +| | ExecuteApi_RecentBlogPosts | Execute Api - RecentBlogPosts | +| | ManageQueries | Manage queries | +| ReCaptcha (OrchardCore.ReCaptcha) | ManageReCaptchaSettings | Manage ReCaptcha Settings | +| Recipes (OrchardCore.Recipes) | ManageRecipes (security critical) | Manage Recipes | +| Remote Deployment (OrchardCore.Deployment.Remote) | ExportRemoteInstances | Export to remote instances | +| | ManageRemoteClients | Manage remote clients | +| | ManageRemoteInstances | Manage remote instances | +| Reverse Proxy Configuration (OrchardCore.ReverseProxy) | ManageReverseProxySettings | Manage Reverse Proxy Settings | +| Roles (OrchardCore.Roles) | ManageRoles (security critical) | Managing Roles | +| Search (OrchardCore.Search) | ManageSearchSettings | Manage Search Settings | +| | QuerySearchIndex | Query any index | +| Secure Media (OrchardCore.Media.Security) | ViewMediaContent | View media content in all folders | +| | ViewRootMediaContent | View media content in the root folder | +| | ViewOthersMediaContent | View others media content | +| | ViewOwnMediaContent | View own media content | +| | ViewMediaContent_[FolderName] | View media content in folder '[FolderName]' | +| Security (OrchardCore.Security) | ManageSecurityHeadersSettings | Manage Security Headers Settings | +| SEO (OrchardCore.Seo) | ManageSeoSettings | Manage SEO related settings | +| Settings (OrchardCore.Settings) | ManageSettings | Manage settings | +| Shortcode Templates (OrchardCore.Shortcodes.Templates) | ManageShortcodeTemplates (security critical) | Manage shortcode templates | +| Sitemaps (OrchardCore.Sitemaps) | ManageSitemaps | Manage sitemaps | +| SMS (OrchardCore.Sms) | ManageSmsSettings | Manage SMS Settings | +| SQL Queries (OrchardCore.Queries.Sql) | ManageSqlQueries | Manage SQL Queries | +| Taxonomies (OrchardCore.Taxonomies) | ManageTaxonomy | Manage taxonomies | +| Templates (OrchardCore.Templates) | ManageAdminTemplates (security critical) | Manage admin templates | +| | ManageTemplates (security critical) | Manage templates | +| Themes (OrchardCore.Themes) | ApplyTheme | Apply a Theme | +| Two-Factor Authentication Services (OrchardCore.Users.2FA) | DisableTwoFactorAuthenticationForUsers (security critical) | Disable two-factor authentication for any user | +| URL Rewriting (OrchardCore.UrlRewriting) | ManageUrlRewritingRules | Manage URLs rewriting rules | +| Users (OrchardCore.Users) | AssignRoleToUsers (security critical) | Assign any role to users | +| | AssignRoleToUsers_[RoleName] (security critical) | Assign [RoleName] role to users | +| | DeleteUsers (security critical) | Delete any user | +| | DeleteUsersInRole_[RoleName] (security critical) | Delete users in [RoleName] role | +| | EditUsers (security critical) | Edit any user | +| | ManageOwnUserInformation | Edit own user information | +| | EditUsersInRole_[RoleName] (security critical) | Edit users in [RoleName] role | +| | ListUsers | List all users | +| | ListUsersInRole_[RoleName] | List users in [RoleName] role | +| | ManageUsers (security critical) | Manage security settings and all users | +| | ManageUsersInRole_[RoleName] (security critical) | Manage users in [RoleName] role | +| | View Users | View user profiles | +| Workflows (OrchardCore.Workflows) | ExecuteWorkflows (security critical) | Execute workflows | +| | ManageWorkflowSettings | Manage workflow settings | +| | ManageWorkflows (security critical) | Manage workflows | +| X (Twitter) Integration (OrchardCore.Twitter) | ManageTwitterSignin | Manage Sign in with X (Twitter) settings | +| | ManageTwitter | Manage X (Twitter) settings | + +### Writing New Permissions + +When creating new permissions in Orchard Core, it is crucial to ensure that each permission name is unique across the system. This helps maintain clarity and prevents conflicts that could arise from duplicate permission names. + +#### Steps to Create a New Permission: +1. **Define the Permission**: Clearly define the purpose and scope of the new permission. +2. **Check for Uniqueness**: Before finalizing the permission name, check it against the list of existing permissions to ensure it is unique. This can be done by reviewing the current permissions documentation or querying the system. +3. **Implement the Permission**: Once the name is confirmed to be unique, proceed with implementing the permission in the codebase. + +**Note**: Always document new permissions thoroughly, including their descriptions and any security implications, especially if they are security critical permissions that allow users to elevate their permissions. + +By following these steps, you can help maintain a well-organized and secure permissions system in Orchard Core. diff --git a/src/docs/topics/security/README.md b/src/docs/topics/security/README.md index 0f5fda5deea..dc241016c47 100644 --- a/src/docs/topics/security/README.md +++ b/src/docs/topics/security/README.md @@ -12,6 +12,6 @@ Orchard Core provides many security features to give an authenticated access to - [OpenId](../../reference/modules/OpenId/README.md) - [Roles](../../reference/modules/Roles/README.md) - [DataProtection (Azure Storage)](../../reference/modules/DataProtection.Azure/README.md) +- [Permissions](Permissions.md) - TBD Users -- TBD Permissions - TBD Login, Registration From 51a977a8376c89259bb2a735e74ffdd85a8644d4 Mon Sep 17 00:00:00 2001 From: Georg von Kries Date: Fri, 24 Jan 2025 11:27:52 +0100 Subject: [PATCH 8/9] Fix docs --- mkdocs.yml | 1 + .../security => reference/modules/Security}/Permissions.md | 0 src/docs/topics/security/README.md | 2 +- 3 files changed, 2 insertions(+), 1 deletion(-) rename src/docs/{topics/security => reference/modules/Security}/Permissions.md (100%) diff --git a/mkdocs.yml b/mkdocs.yml index bdd2ff2adfc..b0344ce6ff4 100644 --- a/mkdocs.yml +++ b/mkdocs.yml @@ -265,6 +265,7 @@ nav: - Mini Profiler: reference/modules/MiniProfiler/README.md - Modules: reference/modules/Modules/README.md - OpenId: reference/modules/OpenId/README.md + - Permissions: reference/modules/Security/Permission.md - Razor Helpers: reference/modules/Razor/README.md - Recipes: reference/modules/Recipes/README.md - Redis: reference/modules/Redis/README.md diff --git a/src/docs/topics/security/Permissions.md b/src/docs/reference/modules/Security/Permissions.md similarity index 100% rename from src/docs/topics/security/Permissions.md rename to src/docs/reference/modules/Security/Permissions.md diff --git a/src/docs/topics/security/README.md b/src/docs/topics/security/README.md index dc241016c47..bc14bd84e38 100644 --- a/src/docs/topics/security/README.md +++ b/src/docs/topics/security/README.md @@ -12,6 +12,6 @@ Orchard Core provides many security features to give an authenticated access to - [OpenId](../../reference/modules/OpenId/README.md) - [Roles](../../reference/modules/Roles/README.md) - [DataProtection (Azure Storage)](../../reference/modules/DataProtection.Azure/README.md) -- [Permissions](Permissions.md) +- [Permissions](../../reference/modules/Security/Permissions.md) - TBD Users - TBD Login, Registration From 61ebfc70a24b9ceaf0290812e2f113ee3eb4ffa8 Mon Sep 17 00:00:00 2001 From: Georg von Kries Date: Fri, 24 Jan 2025 11:31:01 +0100 Subject: [PATCH 9/9] Fix typo --- mkdocs.yml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/mkdocs.yml b/mkdocs.yml index b0344ce6ff4..a24d87adc1f 100644 --- a/mkdocs.yml +++ b/mkdocs.yml @@ -265,7 +265,7 @@ nav: - Mini Profiler: reference/modules/MiniProfiler/README.md - Modules: reference/modules/Modules/README.md - OpenId: reference/modules/OpenId/README.md - - Permissions: reference/modules/Security/Permission.md + - Permissions: reference/modules/Security/Permissions.md - Razor Helpers: reference/modules/Razor/README.md - Recipes: reference/modules/Recipes/README.md - Redis: reference/modules/Redis/README.md