Adding Securable metadata

This commit is contained in:
Sebastien Ros
2014-08-19 11:37:15 -07:00
parent 288d1cb8ad
commit 651175c499
20 changed files with 416 additions and 145 deletions

View File

@@ -38,11 +38,11 @@ namespace Orchard.Core.Contents {
}
public IEnumerable<Permission> GetPermissions() {
// manage rights only for Creatable types
var creatableTypes = _contentDefinitionManager.ListTypeDefinitions()
.Where(ctd => ctd.Settings.GetModel<ContentTypeSettings>().Creatable);
// manage rights only for Securable types
var securableTypes = _contentDefinitionManager.ListTypeDefinitions()
.Where(ctd => ctd.Settings.GetModel<ContentTypeSettings>().Securable);
foreach (var typeDefinition in creatableTypes) {
foreach (var typeDefinition in securableTypes) {
foreach (var permissionTemplate in PermissionTemplates.Values) {
yield return CreateDynamicPermission(permissionTemplate, typeDefinition);
}

View File

@@ -15,6 +15,10 @@ namespace Orchard.Core.Contents.Extensions {
return builder.WithSetting("ContentTypeSettings.Draftable", draftable.ToString());
}
public static ContentTypeDefinitionBuilder Securable(this ContentTypeDefinitionBuilder builder, bool securable = true) {
return builder.WithSetting("ContentTypeSettings.Securable", securable.ToString());
}
public static ContentPartDefinitionBuilder Attachable(this ContentPartDefinitionBuilder builder, bool attachable = true) {
return builder.WithSetting("ContentPartSettings.Attachable", attachable.ToString());
}

View File

@@ -25,7 +25,7 @@ namespace Orchard.Core.Contents.Security {
var typeDefinition = context.Content.ContentItem.TypeDefinition;
// replace permission if a content type specific version exists
if (typeDefinition.Settings.GetModel<ContentTypeSettings>().Creatable) {
if (typeDefinition.Settings.GetModel<ContentTypeSettings>().Securable) {
var permission = GetContentTypeVariation(context.Permission);
if (permission != null) {

View File

@@ -16,5 +16,9 @@
/// Defines the stereotype of the type
/// </summary>
public string Stereotype { get; set; }
/// <summary>
/// Used to determine if this content type supports custom permissions
/// </summary>
public bool Securable { get; set; }
}
}

View File

@@ -18,5 +18,11 @@ namespace Orchard.ContentPermissions {
return 2;
}
public int UpdateFrom2() {
// auto-upgrade to 3 as UpdateFrom1 is incorrectly returning 2
return 3;
}
}
}

View File

@@ -10,4 +10,4 @@ Features:
Name: Content Item Permissions
Description: Allows item-level front end view permissions.
Dependencies: Orchard.Roles
Category: Security
Category: Security

View File

@@ -71,6 +71,7 @@
<Reference Include="System.Xml.Linq" />
</ItemGroup>
<ItemGroup>
<Compile Include="ViewModels\SecurableContentItemsSettingsViewModel.cs" />
<Content Include="Styles\Images\lock.gif" />
<Content Include="Styles\orchard-contentpermissions-admin.css" />
<Content Include="Web.config" />
@@ -95,9 +96,13 @@
<Compile Include="Drivers\ContentPermissionsPartDriver.cs" />
<Compile Include="Models\ContentPermissionsPart.cs" />
<Compile Include="Permissions.cs" />
<Compile Include="Security\AuthorizationEventHandler.cs" />
<Compile Include="Security\SecurableContentItemsAuthorizationEventHandler.cs" />
<Compile Include="Security\ContentPermissionsPartAuthorizationEventHandler.cs" />
<Compile Include="Migrations.cs" />
<Compile Include="Services\DynamicPermissions.cs" />
<Compile Include="Settings\ContentPermissionsPartSettings.cs" />
<Compile Include="Settings\ContentPermissionsTypeSettings.cs" />
<Compile Include="Settings\SecurableContentItemsEditorEvents.cs" />
<Compile Include="ViewModels\ContentPermissionsPartViewModel.cs" />
</ItemGroup>
<ItemGroup>
@@ -120,6 +125,9 @@
<ItemGroup>
<Folder Include="Handlers\" />
</ItemGroup>
<ItemGroup>
<Content Include="Views\DefinitionTemplates\SecurableContentItemsSettingsViewModel.cshtml" />
</ItemGroup>
<PropertyGroup>
<VisualStudioVersion Condition="'$(VisualStudioVersion)' == ''">10.0</VisualStudioVersion>
<VSToolsPath Condition="'$(VSToolsPath)' == ''">$(MSBuildExtensionsPath32)\Microsoft\VisualStudio\v$(VisualStudioVersion)</VSToolsPath>

View File

@@ -1,137 +1,137 @@
using System;
using System.Collections.Generic;
using System.Linq;
using Orchard.ContentManagement;
using Orchard.ContentManagement.Aspects;
using Orchard.Roles.Models;
using Orchard.Security;
using Orchard.ContentPermissions.Models;
using Orchard.Security.Permissions;
namespace Orchard.ContentPermissions.Security {
public class AuthorizationEventHandler : IAuthorizationServiceEventHandler {
private readonly IWorkContextAccessor _workContextAccessor;
private static readonly string[] AnonymousRole = new[] { "Anonymous" };
private static readonly string[] AuthenticatedRole = new[] { "Authenticated" };
public AuthorizationEventHandler(IWorkContextAccessor workContextAccessor) {
_workContextAccessor = workContextAccessor;
}
public void Checking(CheckAccessContext context) { }
public void Adjust(CheckAccessContext context) { }
public void Complete(CheckAccessContext context) {
if (!String.IsNullOrEmpty(_workContextAccessor.GetContext().CurrentSite.SuperUser)
&& context.User != null
&& String.Equals(context.User.UserName, _workContextAccessor.GetContext().CurrentSite.SuperUser, StringComparison.Ordinal)) {
context.Granted = true;
return;
}
if (context.Content == null) {
return;
}
var part = context.Content.As<ContentPermissionsPart>();
// if the content item has no right attached, check on the container
if (part == null || !part.Enabled) {
var commonPart = context.Content.As<ICommonPart>();
if(commonPart != null && commonPart.Container != null) {
part = commonPart.Container.As<ContentPermissionsPart>();
}
}
if (part == null || !part.Enabled) {
return;
}
var hasOwnership = HasOwnership(context.User, context.Content);
IEnumerable<string> authorizedRoles;
var grantingPermissions = PermissionNames(context.Permission, Enumerable.Empty<string>()).Distinct().ToArray();
if (grantingPermissions.Any(grantingPermission => String.Equals(Core.Contents.Permissions.ViewContent.Name, grantingPermission, StringComparison.OrdinalIgnoreCase)))
{
authorizedRoles = (hasOwnership ? part.ViewOwnContent : part.ViewContent).Split(new[] { ',' }, StringSplitOptions.RemoveEmptyEntries);
}
else if (grantingPermissions.Any(grantingPermission => String.Equals(Core.Contents.Permissions.EditContent.Name, grantingPermission, StringComparison.OrdinalIgnoreCase)))
{
authorizedRoles = (hasOwnership ? part.EditOwnContent : part.EditContent).Split(new[] { ',' }, StringSplitOptions.RemoveEmptyEntries);
}
else if (grantingPermissions.Any(grantingPermission => String.Equals(Core.Contents.Permissions.PublishContent.Name, grantingPermission, StringComparison.OrdinalIgnoreCase)))
{
authorizedRoles = (hasOwnership ? part.PublishOwnContent : part.PublishContent).Split(new[] { ',' }, StringSplitOptions.RemoveEmptyEntries);
}
else if (grantingPermissions.Any(grantingPermission => String.Equals(Core.Contents.Permissions.DeleteContent.Name, grantingPermission, StringComparison.OrdinalIgnoreCase)))
{
authorizedRoles = (hasOwnership ? part.DeleteOwnContent : part.DeleteContent).Split(new[] { ',' }, StringSplitOptions.RemoveEmptyEntries);
}
else
{
return;
}
// determine what set of roles should be examined by the access check
IEnumerable<string> rolesToExamine;
if (context.User == null) {
rolesToExamine = AnonymousRole;
}
else if (context.User.Has<IUserRoles>()) {
// the current user is not null, so get his roles and add "Authenticated" to it
rolesToExamine = context.User.As<IUserRoles>().Roles;
// when it is a simulated anonymous user in the admin
if (!rolesToExamine.Contains(AnonymousRole[0])) {
rolesToExamine = rolesToExamine.Concat(AuthenticatedRole);
}
}
else {
// the user is not null and has no specific role, then it's just "Authenticated"
rolesToExamine = AuthenticatedRole;
}
context.Granted = rolesToExamine.Any(x => authorizedRoles.Contains(x, StringComparer.OrdinalIgnoreCase));
context.Adjusted = true;
}
private static bool HasOwnership(IUser user, IContent content) {
if (user == null || content == null)
return false;
var common = content.As<ICommonPart>();
if (common == null || common.Owner == null)
return false;
return user.Id == common.Owner.Id;
}
private static IEnumerable<string> PermissionNames(Permission permission, IEnumerable<string> stack)
{
// the given name is tested
yield return permission.Name;
// iterate implied permissions to grant, it present
if (permission.ImpliedBy != null && permission.ImpliedBy.Any())
{
foreach (var impliedBy in permission.ImpliedBy)
{
// avoid potential recursion
if (stack.Contains(impliedBy.Name))
continue;
// otherwise accumulate the implied permission names recursively
foreach (var impliedName in PermissionNames(impliedBy, stack.Concat(new[] { permission.Name })))
{
yield return impliedName;
}
}
}
yield return StandardPermissions.SiteOwner.Name;
}
}
using System;
using System.Collections.Generic;
using System.Linq;
using Orchard.ContentManagement;
using Orchard.ContentManagement.Aspects;
using Orchard.Roles.Models;
using Orchard.Security;
using Orchard.ContentPermissions.Models;
using Orchard.Security.Permissions;
namespace Orchard.ContentPermissions.Security {
public class ContentPermissionsPartAuthorizationEventHandler : IAuthorizationServiceEventHandler {
private readonly IWorkContextAccessor _workContextAccessor;
private static readonly string[] AnonymousRole = new[] { "Anonymous" };
private static readonly string[] AuthenticatedRole = new[] { "Authenticated" };
public ContentPermissionsPartAuthorizationEventHandler(IWorkContextAccessor workContextAccessor) {
_workContextAccessor = workContextAccessor;
}
public void Checking(CheckAccessContext context) { }
public void Adjust(CheckAccessContext context) { }
public void Complete(CheckAccessContext context) {
if (!String.IsNullOrEmpty(_workContextAccessor.GetContext().CurrentSite.SuperUser)
&& context.User != null
&& String.Equals(context.User.UserName, _workContextAccessor.GetContext().CurrentSite.SuperUser, StringComparison.Ordinal)) {
context.Granted = true;
return;
}
if (context.Content == null) {
return;
}
var part = context.Content.As<ContentPermissionsPart>();
// if the content item has no right attached, check on the container
if (part == null || !part.Enabled) {
var commonPart = context.Content.As<ICommonPart>();
if(commonPart != null && commonPart.Container != null) {
part = commonPart.Container.As<ContentPermissionsPart>();
}
}
if (part == null || !part.Enabled) {
return;
}
var hasOwnership = HasOwnership(context.User, context.Content);
IEnumerable<string> authorizedRoles;
var grantingPermissions = PermissionNames(context.Permission, Enumerable.Empty<string>()).Distinct().ToArray();
if (grantingPermissions.Any(grantingPermission => String.Equals(Core.Contents.Permissions.ViewContent.Name, grantingPermission, StringComparison.OrdinalIgnoreCase)))
{
authorizedRoles = (hasOwnership ? part.ViewOwnContent : part.ViewContent).Split(new[] { ',' }, StringSplitOptions.RemoveEmptyEntries);
}
else if (grantingPermissions.Any(grantingPermission => String.Equals(Core.Contents.Permissions.EditContent.Name, grantingPermission, StringComparison.OrdinalIgnoreCase)))
{
authorizedRoles = (hasOwnership ? part.EditOwnContent : part.EditContent).Split(new[] { ',' }, StringSplitOptions.RemoveEmptyEntries);
}
else if (grantingPermissions.Any(grantingPermission => String.Equals(Core.Contents.Permissions.PublishContent.Name, grantingPermission, StringComparison.OrdinalIgnoreCase)))
{
authorizedRoles = (hasOwnership ? part.PublishOwnContent : part.PublishContent).Split(new[] { ',' }, StringSplitOptions.RemoveEmptyEntries);
}
else if (grantingPermissions.Any(grantingPermission => String.Equals(Core.Contents.Permissions.DeleteContent.Name, grantingPermission, StringComparison.OrdinalIgnoreCase)))
{
authorizedRoles = (hasOwnership ? part.DeleteOwnContent : part.DeleteContent).Split(new[] { ',' }, StringSplitOptions.RemoveEmptyEntries);
}
else
{
return;
}
// determine what set of roles should be examined by the access check
IEnumerable<string> rolesToExamine;
if (context.User == null) {
rolesToExamine = AnonymousRole;
}
else if (context.User.Has<IUserRoles>()) {
// the current user is not null, so get his roles and add "Authenticated" to it
rolesToExamine = context.User.As<IUserRoles>().Roles;
// when it is a simulated anonymous user in the admin
if (!rolesToExamine.Contains(AnonymousRole[0])) {
rolesToExamine = rolesToExamine.Concat(AuthenticatedRole);
}
}
else {
// the user is not null and has no specific role, then it's just "Authenticated"
rolesToExamine = AuthenticatedRole;
}
context.Granted = rolesToExamine.Any(x => authorizedRoles.Contains(x, StringComparer.OrdinalIgnoreCase));
context.Adjusted = true;
}
private static bool HasOwnership(IUser user, IContent content) {
if (user == null || content == null)
return false;
var common = content.As<ICommonPart>();
if (common == null || common.Owner == null)
return false;
return user.Id == common.Owner.Id;
}
private static IEnumerable<string> PermissionNames(Permission permission, IEnumerable<string> stack)
{
// the given name is tested
yield return permission.Name;
// iterate implied permissions to grant, it present
if (permission.ImpliedBy != null && permission.ImpliedBy.Any())
{
foreach (var impliedBy in permission.ImpliedBy)
{
// avoid potential recursion
if (stack.Contains(impliedBy.Name))
continue;
// otherwise accumulate the implied permission names recursively
foreach (var impliedName in PermissionNames(impliedBy, stack.Concat(new[] { permission.Name })))
{
yield return impliedName;
}
}
}
yield return StandardPermissions.SiteOwner.Name;
}
}
}

View File

@@ -0,0 +1,82 @@
using System;
using Orchard.ContentManagement;
using Orchard.ContentManagement.Aspects;
using Orchard.ContentManagement.MetaData.Models;
using Orchard.Localization;
using Orchard.Security;
using Orchard.Security.Permissions;
using System.Linq;
using Orchard.ContentPermissions.Settings;
using Orchard.ContentPermissions.Services;
namespace Orchard.ContentPermissions.Security {
public class SecurableContentItemsAuthorizationEventHandler : IAuthorizationServiceEventHandler {
private readonly IContentManager _contentManager;
public SecurableContentItemsAuthorizationEventHandler(IContentManager contentManager) {
_contentManager = contentManager;
}
public Localizer T { get; set; }
public void Checking(CheckAccessContext context) { }
public void Complete(CheckAccessContext context) { }
public void Adjust(CheckAccessContext context) {
if (!context.Granted &&
context.Content.Is<ICommonPart>()) {
if (OwnerVariationExists(context.Permission) &&
HasOwnership(context.User, context.Content)) {
context.Adjusted = true;
context.Permission = GetOwnerVariation(context.Permission);
}
var typeDefinition = context.Content.ContentItem.TypeDefinition;
if (typeDefinition.Settings.GetModel<ContentPermissionsTypeSettings>().SecurableContentItems) {
// replace permission if a content item specific version exists
var permission = GetContentTypeVariation(context.Permission);
if (permission != null) {
context.Adjusted = true;
context.Permission = DynamicPermissions.CreateItemPermission(permission, context.Content, T, _contentManager);
}
}
}
}
private static bool HasOwnership(IUser user, IContent content) {
if (user == null || content == null)
return false;
var common = content.As<ICommonPart>();
if (common == null || common.Owner == null)
return false;
return user.Id == common.Owner.Id;
}
private static bool OwnerVariationExists(Permission permission) {
return GetOwnerVariation(permission) != null;
}
private static Permission GetOwnerVariation(Permission permission) {
if (permission.Name == Orchard.Core.Contents.Permissions.PublishContent.Name)
return Orchard.Core.Contents.Permissions.PublishOwnContent;
if (permission.Name == Orchard.Core.Contents.Permissions.EditContent.Name)
return Orchard.Core.Contents.Permissions.EditOwnContent;
if (permission.Name == Orchard.Core.Contents.Permissions.DeleteContent.Name)
return Orchard.Core.Contents.Permissions.DeleteOwnContent;
if (permission.Name == Orchard.Core.Contents.Permissions.ViewContent.Name)
return Orchard.Core.Contents.Permissions.ViewOwnContent;
return null;
}
private static Permission GetContentTypeVariation(Permission permission) {
return DynamicPermissions.ConvertToDynamicPermission(permission);
}
}
}

View File

@@ -0,0 +1,94 @@
using System;
using System.Linq;
using System.Collections.Generic;
using Orchard.ContentManagement.MetaData;
using Orchard.ContentPermissions.Settings;
using Orchard.Environment.Extensions.Models;
using Orchard.Security.Permissions;
using Orchard.ContentManagement;
using Orchard.Localization;
namespace Orchard.ContentPermissions.Services {
public class DynamicPermissions : IPermissionProvider {
private static readonly Permission PublishContent = new Permission { Description = "Publish or unpublish {0} for others", Name = "Publish_{0}", ImpliedBy = new[] { Orchard.Core.Contents.Permissions.PublishContent } };
private static readonly Permission PublishOwnContent = new Permission { Description = "Publish or unpublish {0}", Name = "PublishOwn_{0}", ImpliedBy = new[] { PublishContent, Orchard.Core.Contents.Permissions.PublishOwnContent } };
private static readonly Permission EditContent = new Permission { Description = "Edit {0} for others", Name = "Edit_{0}", ImpliedBy = new[] { PublishContent, Orchard.Core.Contents.Permissions.EditContent } };
private static readonly Permission EditOwnContent = new Permission { Description = "Edit {0}", Name = "EditOwn_{0}", ImpliedBy = new[] { EditContent, PublishOwnContent, Orchard.Core.Contents.Permissions.EditOwnContent } };
private static readonly Permission DeleteContent = new Permission { Description = "Delete {0} for others", Name = "Delete_{0}", ImpliedBy = new[] { Orchard.Core.Contents.Permissions.DeleteContent } };
private static readonly Permission DeleteOwnContent = new Permission { Description = "Delete {0}", Name = "DeleteOwn_{0}", ImpliedBy = new[] { DeleteContent, Orchard.Core.Contents.Permissions.DeleteOwnContent } };
private static readonly Permission ViewContent = new Permission { Description = "View {0} by others", Name = "View_{0}", ImpliedBy = new[] { EditContent, Orchard.Core.Contents.Permissions.ViewContent } };
private static readonly Permission ViewOwnContent = new Permission { Description = "View own {0}", Name = "ViewOwn_{0}", ImpliedBy = new[] { ViewContent, Orchard.Core.Contents.Permissions.ViewOwnContent } };
public static readonly Dictionary<string, Permission> PermissionTemplates = new Dictionary<string, Permission> {
{Orchard.Core.Contents.Permissions.PublishContent.Name, PublishContent},
{Orchard.Core.Contents.Permissions.PublishOwnContent.Name, PublishOwnContent},
{Orchard.Core.Contents.Permissions.EditContent.Name, EditContent},
{Orchard.Core.Contents.Permissions.EditOwnContent.Name, EditOwnContent},
{Orchard.Core.Contents.Permissions.DeleteContent.Name, DeleteContent},
{Orchard.Core.Contents.Permissions.DeleteOwnContent.Name, DeleteOwnContent},
{Orchard.Core.Contents.Permissions.ViewContent.Name, ViewContent},
{Orchard.Core.Contents.Permissions.ViewOwnContent.Name, ViewOwnContent}
};
private readonly IContentDefinitionManager _contentDefinitionManager;
private readonly IContentManager _contentManager;
public virtual Feature Feature { get; set; }
public Localizer T { get; set; }
public DynamicPermissions(IContentDefinitionManager contentDefinitionManager, IContentManager contentManager) {
_contentDefinitionManager = contentDefinitionManager;
_contentManager = contentManager;
T = NullLocalizer.Instance;
}
public IEnumerable<Permission> GetPermissions() {
// manage rights only for Securable types
var securableTypes = _contentDefinitionManager.ListTypeDefinitions()
.Where(ctd => ctd.Settings.GetModel<ContentPermissionsTypeSettings>().SecurableContentItems)
.ToList();
foreach (var typeDefinition in securableTypes) {
foreach (var content in _contentManager.Query(typeDefinition.Name).List()) {
foreach (var permissionTemplate in PermissionTemplates.Values) {
yield return CreateItemPermission(permissionTemplate, content, T, _contentManager);
}
}
}
}
public IEnumerable<PermissionStereotype> GetDefaultStereotypes() {
return Enumerable.Empty<PermissionStereotype>();
}
/// <summary>
/// Generates a permission dynamically for a content item
/// </summary>
public static Permission CreateItemPermission(Permission template, IContent content, Localizer T, IContentManager contentManager) {
var identity = contentManager.GetItemMetadata(content).Identity.ToString();
var displayText = contentManager.GetItemMetadata(content).DisplayText;
var typeDefinition = content.ContentItem.TypeDefinition;
return new Permission {
Name = String.Format(template.Name, identity),
Description = String.Format(template.Description, typeDefinition.DisplayName),
Category = T("{0} - {1}", typeDefinition.DisplayName, displayText).ToString(),
ImpliedBy = (template.ImpliedBy ?? new Permission[0]).Select(t => CreateItemPermission(t, content, T, contentManager))
};
}
/// <summary>
/// Returns a dynamic permission for a content type, based on a global content permission template
/// </summary>
public static Permission ConvertToDynamicPermission(Permission permission) {
if (PermissionTemplates.ContainsKey(permission.Name)) {
return PermissionTemplates[permission.Name];
}
return null;
}
}
}

View File

@@ -0,0 +1,8 @@
namespace Orchard.ContentPermissions.Settings {
public class ContentPermissionsTypeSettings {
/// <summary>
/// Used to determine if instances of this content type supports custom permissions
/// </summary>
public bool SecurableContentItems { get; set; }
}
}

View File

@@ -0,0 +1,30 @@
using System.Collections.Generic;
using Orchard.ContentManagement;
using Orchard.ContentManagement.MetaData;
using Orchard.ContentManagement.MetaData.Builders;
using Orchard.ContentManagement.MetaData.Models;
using Orchard.ContentManagement.ViewModels;
using Orchard.ContentPermissions.ViewModels;
namespace Orchard.ContentPermissions.Settings {
public class SecurableContentItemsEditorEvents : ContentDefinitionEditorEventsBase {
public override IEnumerable<TemplateViewModel> TypeEditor(ContentTypeDefinition definition) {
var settings = definition.Settings.GetModel<ContentPermissionsTypeSettings>();
var model = new SecurableContentItemsSettingsViewModel {
SecurableContentItems = settings.SecurableContentItems,
};
yield return DefinitionTemplate(model);
}
public override IEnumerable<TemplateViewModel> TypeEditorUpdate(ContentTypeDefinitionBuilder builder, IUpdateModel updateModel) {
var model = new SecurableContentItemsSettingsViewModel();
updateModel.TryUpdateModel(model, "SecurableContentItemsSettingsViewModel", null, null);
builder.WithSetting("ContentPermissionsTypeSettings.SecurableContentItems", model.SecurableContentItems.ToString());
yield return DefinitionTemplate(model);
}
}
}

View File

@@ -0,0 +1,5 @@
namespace Orchard.ContentPermissions.ViewModels {
public class SecurableContentItemsSettingsViewModel {
public bool SecurableContentItems { get; set; }
}
}

View File

@@ -0,0 +1,8 @@
@model Orchard.ContentPermissions.ViewModels.SecurableContentItemsSettingsViewModel
<fieldset>
@Html.EditorFor(m => m.SecurableContentItems)
<label for="@Html.FieldIdFor(m => m.SecurableContentItems)" class="forcheckbox">@T("Securable Content Items")</label>
@Html.ValidationMessageFor(m => m.SecurableContentItems)
<span class="hint">@T("Determines if an instance of this content type can have custom permissions.")</span>
</fieldset>

View File

@@ -22,5 +22,15 @@ namespace Orchard.ContentTypes {
return 1;
}
public int UpgradeFrom1() {
foreach (var typeDefinition in _contentDefinitionManager.ListTypeDefinitions()) {
if (typeDefinition.Settings.ContainsKey("ContentTypeSettings.Creatable") && Convert.ToBoolean(typeDefinition.Settings["ContentTypeSettings.Creatable"], CultureInfo.InvariantCulture)) {
typeDefinition.Settings["ContentTypeSettings.Securable"] = "True";
_contentDefinitionManager.StoreTypeDefinition(typeDefinition);
}
}
return 2;
}
}
}

View File

@@ -87,7 +87,7 @@ namespace Orchard.ContentTypes.Services {
var contentTypeDefinition = new ContentTypeDefinition(name, displayName);
_contentDefinitionManager.StoreTypeDefinition(contentTypeDefinition);
_contentDefinitionManager.AlterTypeDefinition(name, cfg => cfg.Creatable().Draftable().Listable());
_contentDefinitionManager.AlterTypeDefinition(name, cfg => cfg.Creatable().Draftable().Listable().Securable());
_contentDefinitionEventHandlers.ContentTypeCreated(new ContentTypeCreatedContext { ContentTypeDefinition = contentTypeDefinition});
return contentTypeDefinition;

View File

@@ -18,6 +18,7 @@ namespace Orchard.ContentTypes.Settings {
Creatable = settings.Creatable,
Listable = settings.Listable,
Draftable = settings.Draftable,
Securable = settings.Securable,
};
if(definition.Settings.ContainsKey("Stereotype")) {
@@ -34,6 +35,7 @@ namespace Orchard.ContentTypes.Settings {
builder.Creatable(model.Creatable);
builder.Listable(model.Listable);
builder.Draftable(model.Draftable);
builder.Securable(model.Securable);
builder.WithSetting("Stereotype", model.Stereotype);
yield return DefinitionTemplate(model);

View File

@@ -3,6 +3,7 @@
public bool Creatable { get; set; }
public bool Listable { get; set; }
public bool Draftable { get; set; }
public bool Securable { get; set; }
public string Stereotype { get; set; }
}
}

View File

@@ -21,6 +21,13 @@
<span class="hint">@T("Determines if this content type supports draft versions.")</span>
</fieldset>
<fieldset>
@Html.EditorFor(m => m.Securable)
<label for="@Html.FieldIdFor(m => m.Securable)" class="forcheckbox">@T("Securable")</label>
@Html.ValidationMessageFor(m => m.Securable)
<span class="hint">@T("Determines if this content type can have custom permissions.")</span>
</fieldset>
<fieldset>
<label for="@Html.FieldIdFor(m => m.Stereotype)">@T("Stereotype")</label>
@Html.TextBoxFor(m => m.Stereotype, new { @class = "text medium"})

View File

@@ -17,7 +17,9 @@ namespace Orchard.Pages {
.WithSetting("AutorouteSettings.PatternDefinitions", "[{\"Name\":\"Title\",\"Pattern\":\"{Content.Slug}\",\"Description\":\"my-page\"}]")
.WithSetting("AutorouteSettings.DefaultPatternIndex", "0"))
.WithPart("BodyPart")
.Creatable());
.Creatable()
.Listable()
.Securable());
return 3;
}