#17051: Correcting a few wrong handlers Loaded -> Loading. Adding handlers to hook loaders on Versioning.

Fixing small permissions issue on live writter so that the user only gets the blogs that he can edit.

--HG--
branch : 1.x
This commit is contained in:
andrerod
2010-12-17 17:40:30 -08:00
parent 022230d38a
commit 9838c67424
13 changed files with 139 additions and 92 deletions

View File

@@ -34,12 +34,13 @@ namespace Orchard.Core.Common.Handlers {
Filters.Add(StorageFilter.For(commonRepository));
Filters.Add(StorageFilter.For(commonVersionRepository));
OnInitializing<CommonPart>(PropertySetHandlers);
OnActivated<CommonPart>(PropertySetHandlers);
OnInitializing<CommonPart>(AssignCreatingOwner);
OnInitializing<CommonPart>(AssignCreatingDates);
OnInitializing<ContentPart<CommonPartVersionRecord>>(AssignCreatingDates);
OnLoaded<CommonPart>(LazyLoadHandlers);
OnLoading<CommonPart>((context, part) => LazyLoadHandlers(part));
OnVersioning<CommonPart>((context, part, newVersionPart) => LazyLoadHandlers(newVersionPart));
OnVersioned<CommonPart>(AssignVersioningDates);
OnVersioned<ContentPart<CommonPartVersionRecord>>(AssignVersioningDates);
@@ -65,7 +66,7 @@ namespace Orchard.Core.Common.Handlers {
context.Builder.Weld<ContentPart<CommonPartVersionRecord>>();
}
bool ContentTypeWithACommonPart(string typeName) {
protected bool ContentTypeWithACommonPart(string typeName) {
//Note: What about content type handlers which activate "CommonPart" in code?
var contentTypeDefinition = _contentDefinitionManager.GetTypeDefinition(typeName);
@@ -75,26 +76,26 @@ namespace Orchard.Core.Common.Handlers {
return false;
}
void AssignCreatingOwner(InitializingContentContext context, CommonPart part) {
protected void AssignCreatingOwner(InitializingContentContext context, CommonPart part) {
// and use the current user as Owner
if (part.Record.OwnerId == 0) {
part.Owner = _authenticationService.GetAuthenticatedUser();
}
}
void AssignCreatingDates(InitializingContentContext context, CommonPart part) {
protected void AssignCreatingDates(InitializingContentContext context, CommonPart part) {
// assign default create/modified dates
part.CreatedUtc = _clock.UtcNow;
part.ModifiedUtc = _clock.UtcNow;
}
void AssignCreatingDates(InitializingContentContext context, ContentPart<CommonPartVersionRecord> part) {
protected void AssignCreatingDates(InitializingContentContext context, ContentPart<CommonPartVersionRecord> part) {
// assign default create/modified dates
part.Record.CreatedUtc = _clock.UtcNow;
part.Record.ModifiedUtc = _clock.UtcNow;
}
void AssignVersioningDates(VersionContentContext context, CommonPart existing, CommonPart building) {
protected void AssignVersioningDates(VersionContentContext context, CommonPart existing, CommonPart building) {
// assign the created
building.CreatedUtc = existing.CreatedUtc ?? _clock.UtcNow;
// persist and published dates
@@ -103,7 +104,7 @@ namespace Orchard.Core.Common.Handlers {
building.ModifiedUtc = _clock.UtcNow;
}
void AssignVersioningDates(VersionContentContext context, ContentPart<CommonPartVersionRecord> existing, ContentPart<CommonPartVersionRecord> building) {
protected void AssignVersioningDates(VersionContentContext context, ContentPart<CommonPartVersionRecord> existing, ContentPart<CommonPartVersionRecord> building) {
// assign the created date
building.Record.CreatedUtc = _clock.UtcNow;
// assign modified date for the new version
@@ -112,7 +113,7 @@ namespace Orchard.Core.Common.Handlers {
building.Record.PublishedUtc = null;
}
void AssignPublishingDates(PublishContentContext context, CommonPart part) {
protected void AssignPublishingDates(PublishContentContext context, CommonPart part) {
// don't assign dates when unpublishing
if (context.PublishingItemVersionRecord == null)
return;
@@ -121,7 +122,7 @@ namespace Orchard.Core.Common.Handlers {
part.PublishedUtc = part.PublishedUtc ?? _clock.UtcNow;
}
void AssignPublishingDates(PublishContentContext context, ContentPart<CommonPartVersionRecord> part) {
protected void AssignPublishingDates(PublishContentContext context, ContentPart<CommonPartVersionRecord> part) {
// don't assign dates when unpublishing
if (context.PublishingItemVersionRecord == null)
return;
@@ -130,13 +131,13 @@ namespace Orchard.Core.Common.Handlers {
part.Record.PublishedUtc = part.Record.PublishedUtc ?? _clock.UtcNow;
}
void LazyLoadHandlers(LoadContentContext context, CommonPart part) {
protected void LazyLoadHandlers(CommonPart part) {
// add handlers that will load content for id's just-in-time
part.OwnerField.Loader(() => _contentManager.Get<IUser>(part.Record.OwnerId));
part.ContainerField.Loader(() => part.Record.Container == null ? null : _contentManager.Get(part.Record.Container.Id));
part.ContainerField.Loader(() => part.Record.Container == null ? null : _contentManager.Get(part.Record.Container.Id));
}
static void PropertySetHandlers(InitializingContentContext context, CommonPart part) {
protected static void PropertySetHandlers(ActivatedContentContext context, CommonPart part) {
// add handlers that will update records when part properties are set
part.OwnerField.Setter(user => {
@@ -162,4 +163,4 @@ namespace Orchard.Core.Common.Handlers {
part.ContainerField.Value = part.ContainerField.Value;
}
}
}
}

View File

@@ -1,6 +1,5 @@
using Orchard.ArchiveLater.Models;
using Orchard.ArchiveLater.Services;
using Orchard.ContentManagement;
using Orchard.ContentManagement.Handlers;
namespace Orchard.ArchiveLater.Handlers {
@@ -10,7 +9,12 @@ namespace Orchard.ArchiveLater.Handlers {
public ArchiveLaterPartHandler(IArchiveLaterService archiveLaterService) {
_archiveLaterService = archiveLaterService;
OnLoaded<ArchiveLaterPart>((context, archiveLater) => archiveLater.ScheduledArchiveUtc.Loader(delegate { return _archiveLaterService.GetScheduledArchiveUtc(archiveLater.As<ArchiveLaterPart>()); }));
OnLoading<ArchiveLaterPart>((context, part) => LazyLoadHandlers(part));
OnVersioning<ArchiveLaterPart>((context, part, newVersionPart) => LazyLoadHandlers(newVersionPart));
}
protected void LazyLoadHandlers(ArchiveLaterPart part) {
part.ScheduledArchiveUtc.Loader((value) => _archiveLaterService.GetScheduledArchiveUtc(part));
}
}
}

View File

@@ -10,8 +10,6 @@ using Orchard.Core.Contents.Settings;
using Orchard.Localization;
using Orchard.Mvc.AntiForgery;
using Orchard.Mvc.Extensions;
using Orchard.Security;
using Orchard.Security.Permissions;
using Orchard.UI.Admin;
using Orchard.UI.Notify;
@@ -31,14 +29,17 @@ namespace Orchard.Blogs.Controllers {
public IOrchardServices Services { get; set; }
public Localizer T { get; set; }
public ActionResult Create() {
public ActionResult Create(int blogId) {
if (!Services.Authorizer.Authorize(Permissions.EditOwnBlogPost, T("Not allowed to create blog post")))
return new HttpUnauthorizedResult();
var blogPost = Services.ContentManager.New<BlogPostPart>("BlogPost");
if (blogPost.BlogPart == null)
var blog = _blogService.Get(blogId, VersionOptions.Latest).As<BlogPart>();
if (blog == null)
return HttpNotFound();
var blogPost = Services.ContentManager.New<BlogPostPart>("BlogPost");
blogPost.BlogPart = blog;
dynamic model = Services.ContentManager.BuildEditor(blogPost);
// Casting to avoid invalid (under medium trust) reflection over the protected View method and force a static invocation.
return View((object)model);
@@ -46,8 +47,8 @@ namespace Orchard.Blogs.Controllers {
[HttpPost, ActionName("Create")]
[FormValueRequired("submit.Save")]
public ActionResult CreatePOST() {
return CreatePOST(contentItem => {
public ActionResult CreatePOST(int blogId) {
return CreatePOST(blogId, contentItem => {
if (!contentItem.Has<IPublishingControlAspect>() && !contentItem.TypeDefinition.Settings.GetModel<ContentTypeSettings>().Draftable)
Services.ContentManager.Publish(contentItem);
});
@@ -55,21 +56,24 @@ namespace Orchard.Blogs.Controllers {
[HttpPost, ActionName("Create")]
[FormValueRequired("submit.Publish")]
public ActionResult CreateAndPublishPOST() {
public ActionResult CreateAndPublishPOST(int blogId) {
if (!Services.Authorizer.Authorize(Permissions.PublishOwnBlogPost, T("Couldn't create blog post")))
return new HttpUnauthorizedResult();
return CreatePOST(contentItem => Services.ContentManager.Publish(contentItem));
return CreatePOST(blogId, contentItem => Services.ContentManager.Publish(contentItem));
}
public ActionResult CreatePOST(Action<ContentItem> conditionallyPublish) {
private ActionResult CreatePOST(int blogId, Action<ContentItem> conditionallyPublish) {
if (!Services.Authorizer.Authorize(Permissions.EditOwnBlogPost, T("Couldn't create blog post")))
return new HttpUnauthorizedResult();
var blogPost = Services.ContentManager.New<BlogPostPart>("BlogPost");
if (blogPost.BlogPart == null)
var blog = _blogService.Get(blogId, VersionOptions.Latest).As<BlogPart>();
if (blog == null)
return HttpNotFound();
var blogPost = Services.ContentManager.New<BlogPostPart>("BlogPost");
blogPost.BlogPart = blog;
Services.ContentManager.Create(blogPost, VersionOptions.Draft);
var model = Services.ContentManager.UpdateEditor(blogPost, this);

View File

@@ -6,7 +6,7 @@ using Orchard.Core.Feeds;
using Orchard.Localization;
namespace Orchard.Blogs.Drivers {
[UsedImplicitly]
[UsedImplicitly]
public class BlogPostPartDriver : ContentPartDriver<BlogPostPart> {
private readonly IFeedManager _feedManager;
public IOrchardServices Services { get; set; }

View File

@@ -1,4 +1,3 @@
using System;
using System.Linq;
using System.Web.Routing;
using JetBrains.Annotations;
@@ -6,53 +5,28 @@ using Orchard.Blogs.Models;
using Orchard.Blogs.Services;
using Orchard.ContentManagement;
using Orchard.ContentManagement.Handlers;
using Orchard.Core.Common.Models;
using Orchard.Core.Routable.Models;
namespace Orchard.Blogs.Handlers {
[UsedImplicitly]
public class BlogPostPartHandler : ContentHandler {
private readonly IBlogService _blogService;
private readonly IBlogPostService _blogPostService;
public BlogPostPartHandler(IBlogService blogService, IBlogPostService blogPostService, RequestContext requestContext) {
_blogService = blogService;
_blogPostService = blogPostService;
Action<BlogPart> updateBlogPostCount =
(blog => {
// Ensure we get the "right" set of published posts for the blog
blog.ContentItem.ContentManager.Flush();
var postsCount = _blogPostService.Get(blog, VersionOptions.Published).Count();
blog.PostCount = postsCount;
});
OnGetDisplayShape<BlogPostPart>(SetModelProperties);
OnGetEditorShape<BlogPostPart>(SetModelProperties);
OnUpdateEditorShape<BlogPostPart>(SetModelProperties);
OnInitializing<BlogPostPart>((context, bp) => {
var blogId = requestContext.RouteData.Values.ContainsKey("blogId") ? requestContext.RouteData.Values["blogId"] as string : null;
if (!string.IsNullOrEmpty(blogId)) {
var blog = blogService.Get(int.Parse(blogId), VersionOptions.Latest);
bp.BlogPart = blog.As<BlogPart>();
return;
}
//todo: don't get at the container form data directly. right now the container is set in the common driver editor (updater)
//todo: which is too late for what's needed (currently) in this handler
var containerId = requestContext.HttpContext.Request.Form["CommonPart.containerId"];
if (!string.IsNullOrEmpty(containerId)) {
int cId;
if (int.TryParse(containerId, out cId)) {
bp.BlogPart = context.ContentItem.ContentManager.Get(cId).As<BlogPart>();
return;
}
}
});
OnCreated<BlogPostPart>((context, bp) => updateBlogPostCount(bp.BlogPart));
OnPublished<BlogPostPart>((context, bp) => updateBlogPostCount(bp.BlogPart));
OnUnpublished<BlogPostPart>((context, bp) => updateBlogPostCount(bp.BlogPart));
OnVersioned<BlogPostPart>((context, bp1, bp2) => updateBlogPostCount(bp1.BlogPart));
OnRemoved<BlogPostPart>((context, bp) => updateBlogPostCount(bp.BlogPart));
OnCreated<BlogPostPart>((context, part) => UpdateBlogPostCount(part));
OnPublished<BlogPostPart>((context, part) => UpdateBlogPostCount(part));
OnUnpublished<BlogPostPart>((context, part) => UpdateBlogPostCount(part));
OnVersioned<BlogPostPart>((context, part, newVersionPart) => UpdateBlogPostCount(newVersionPart));
OnRemoved<BlogPostPart>((context, part) => UpdateBlogPostCount(part));
OnRemoved<BlogPart>(
(context, b) =>
@@ -60,6 +34,20 @@ namespace Orchard.Blogs.Handlers {
blogPost => context.ContentManager.Remove(blogPost.ContentItem)));
}
private void UpdateBlogPostCount(BlogPostPart blogPostPart) {
CommonPart commonPart = blogPostPart.As<CommonPart>();
if (commonPart != null &&
commonPart.Record.Container != null) {
BlogPart blogPart = blogPostPart.BlogPart ??
_blogService.Get(commonPart.Record.Container.Id, VersionOptions.Published).As<BlogPart>();
// Ensure the "right" set of published posts for the blog is obtained
blogPart.ContentItem.ContentManager.Flush();
blogPart.PostCount = _blogPostService.Get(blogPart, VersionOptions.Published).Count();
}
}
private static void SetModelProperties(BuildShapeContext context, BlogPostPart blogPost) {
context.Shape.Blog = blogPost.BlogPart;
}

View File

@@ -4,7 +4,7 @@ using Orchard.ContentManagement;
namespace Orchard.Blogs.Services {
public interface IBlogService : IDependency {
BlogPart Get(string slug);
BlogPart Get(string path);
ContentItem Get(int id, VersionOptions versionOptions);
IEnumerable<BlogPart> Get();
IEnumerable<BlogPart> Get(VersionOptions versionOptions);

View File

@@ -58,7 +58,6 @@ namespace Orchard.Blogs.Services {
if (context.Request.MethodName == "blogger.getUsersBlogs") {
var result = MetaWeblogGetUserBlogs(urlHelper,
Convert.ToString(context.Request.Params[0].Value),
Convert.ToString(context.Request.Params[1].Value),
Convert.ToString(context.Request.Params[2].Value));
@@ -111,33 +110,30 @@ namespace Orchard.Blogs.Services {
if (context.Request.MethodName == "blogger.deletePost") {
var result = MetaWeblogDeletePost(
Convert.ToString(context.Request.Params[0].Value),
Convert.ToString(context.Request.Params[1].Value),
Convert.ToString(context.Request.Params[2].Value),
Convert.ToString(context.Request.Params[3].Value),
Convert.ToBoolean(context.Request.Params[4].Value),
context._drivers);
context.Response = new XRpcMethodResponse().Add(result);
}
}
private XRpcArray MetaWeblogGetUserBlogs(UrlHelper urlHelper,
string appkey,
string userName,
string password) {
IUser user = ValidateUser(userName, password);
// User needs to at least have permission to edit its own blog posts to access the service
_authorizationService.CheckAccess(Permissions.EditOwnBlogPost, user, null);
XRpcArray array = new XRpcArray();
foreach (BlogPart blog in _blogService.Get()) {
BlogPart blogPart = blog;
array.Add(new XRpcStruct()
.Set("url", urlHelper.AbsoluteAction(() => urlHelper.Blog(blogPart)))
.Set("blogid", blog.Id)
.Set("blogName", blog.Name));
// Check if user has permissions for each specific blog
if (_authorizationService.TryCheckAccess(Permissions.EditOthersBlogPost, user, blog)) {
BlogPart blogPart = blog;
array.Add(new XRpcStruct()
.Set("url", urlHelper.AbsoluteAction(() => urlHelper.Blog(blogPart)))
.Set("blogid", blog.Id)
.Set("blogName", blog.Name));
}
}
return array;
@@ -215,7 +211,7 @@ namespace Orchard.Blogs.Services {
blogPost.As<RoutePart>().Path = blogPost.As<RoutePart>().GetPathWithSlug(blogPost.As<RoutePart>().Slug);
}
_contentManager.Create(blogPost.ContentItem, VersionOptions.Draft);
_contentManager.Create(blogPost, VersionOptions.Draft);
var publishedUtc = content.Optional<DateTime?>("dateCreated");
if (publish && (publishedUtc == null || publishedUtc <= DateTime.UtcNow))
@@ -249,7 +245,14 @@ namespace Orchard.Blogs.Services {
return postStruct;
}
private bool MetaWeblogEditPost(int postId, string userName, string password, XRpcStruct content, bool publish, IEnumerable<IXmlRpcDriver> drivers) {
private bool MetaWeblogEditPost(
int postId,
string userName,
string password,
XRpcStruct content,
bool publish,
IEnumerable<IXmlRpcDriver> drivers) {
IUser user = ValidateUser(userName, password);
var blogPost = _blogPostService.Get(postId, VersionOptions.DraftRequired);
if (blogPost == null)
@@ -284,7 +287,12 @@ namespace Orchard.Blogs.Services {
return true;
}
private bool MetaWeblogDeletePost(string appkey, string postId, string userName, string password, bool publish, IEnumerable<IXmlRpcDriver> drivers) {
private bool MetaWeblogDeletePost(
string postId,
string userName,
string password,
IEnumerable<IXmlRpcDriver> drivers) {
IUser user = ValidateUser(userName, password);
var blogPost = _blogPostService.Get(Convert.ToInt32(postId), VersionOptions.Latest);
if (blogPost == null)
@@ -308,7 +316,10 @@ namespace Orchard.Blogs.Services {
return user;
}
private static XRpcStruct CreateBlogStruct(BlogPostPart blogPostPart, UrlHelper urlHelper) {
private static XRpcStruct CreateBlogStruct(
BlogPostPart blogPostPart,
UrlHelper urlHelper) {
var url = urlHelper.AbsoluteAction(() => urlHelper.BlogPost(blogPostPart));
var blogStruct = new XRpcStruct()
.Set("postid", blogPostPart.Id)

View File

@@ -13,9 +13,9 @@
<Place Parts_Comments="Content:10" />
</Match>
<Match DisplayType="Summary">
<Place Parts_Comments_Count="Meta:5"/>
<Place Parts_Comments_Count="Meta:5" />
</Match>
<Match DisplayType="SummaryAdmin">
<Place Parts_Comments_Count_SummaryAdmin="Sidebar"/>
<Place Parts_Comments_Count_SummaryAdmin="Sidebar" />
</Match>
</Placement>

View File

@@ -19,7 +19,10 @@ namespace Orchard.Localization.Handlers {
Filters.Add(StorageFilter.For(localizedRepository));
OnInitializing<LocalizationPart>(InitializePart);
OnActivated<LocalizationPart>(PropertySetHandlers);
OnLoading<LocalizationPart>((context, part) => LazyLoadHandlers(part));
OnVersioning<LocalizationPart>((context, part, versionedPart) => LazyLoadHandlers(versionedPart));
OnIndexed<LocalizationPart>((context, localized) => context.DocumentIndex
.Add("culture", CultureInfo.GetCultureInfo(localized.Culture != null ? localized.Culture.Culture : _cultureManager.GetSiteCulture()).LCID)
@@ -29,18 +32,24 @@ namespace Orchard.Localization.Handlers {
public Localizer T { get; set; }
void InitializePart(InitializingContentContext context, LocalizationPart localizationPart) {
protected static void PropertySetHandlers(ActivatedContentContext context, LocalizationPart localizationPart) {
localizationPart.CultureField.Setter(cultureRecord => {
localizationPart.Record.CultureId = cultureRecord.Id;
return cultureRecord;
});
localizationPart.MasterContentItemField.Setter(masterContentItem => {
localizationPart.Record.MasterContentItemId = masterContentItem.ContentItem.Id;
return masterContentItem;
});
localizationPart.CultureField.Loader(ctx => _cultureManager.GetCultureById(localizationPart.Record.CultureId));
});
}
protected void LazyLoadHandlers(LocalizationPart localizationPart) {
localizationPart.CultureField.Loader(ctx =>
_cultureManager.GetCultureById(localizationPart.Record.CultureId));
localizationPart.MasterContentItemField.Loader(ctx =>
_contentManager.Get(localizationPart.Record.MasterContentItemId, localizationPart.IsPublished() ? VersionOptions.Published : VersionOptions.Latest));
}
}
}
}

View File

@@ -1,5 +1,4 @@
using Orchard.ContentManagement;
using Orchard.ContentManagement.Handlers;
using Orchard.ContentManagement.Handlers;
using Orchard.PublishLater.Models;
using Orchard.PublishLater.Services;
@@ -10,7 +9,12 @@ namespace Orchard.PublishLater.Handlers {
public PublishLaterPartHandler(IPublishLaterService publishLaterService) {
_publishLaterService = publishLaterService;
OnLoaded<PublishLaterPart>((context, publishLater) => publishLater.ScheduledPublishUtc.Loader(delegate { return _publishLaterService.GetScheduledPublishUtc(publishLater.As<PublishLaterPart>()); }));
OnLoading<PublishLaterPart>((context, part) => LazyLoadHandlers(part));
OnVersioning<PublishLaterPart>((context, part, newVersionPart) => LazyLoadHandlers(newVersionPart));
}
protected void LazyLoadHandlers(PublishLaterPart part) {
part.ScheduledPublishUtc.Loader((value) => _publishLaterService.GetScheduledPublishUtc(part));
}
}
}

View File

@@ -19,6 +19,5 @@ namespace Orchard.Roles.Handlers {
.Select(x => x.Role.Name).ToList();
});
}
}
}

View File

@@ -17,7 +17,7 @@ namespace Orchard.Caching {
.Any(xx => xx.ParameterType == typeof(ICacheManager)));
if (needsCacheManager) {
registration.Preparing += (sender, e) => {
registration.Preparing += (sender, e) => {
var parameter = new TypedParameter(
typeof(ICacheManager),
e.Context.Resolve<ICacheManager>(new TypedParameter(typeof(Type), registration.Activator.LimitType)));

View File

@@ -38,12 +38,39 @@ namespace Orchard.ContentManagement {
}
public class VersionOptions {
/// <summary>
/// Gets the latest version.
/// </summary>
public static VersionOptions Latest { get { return new VersionOptions { IsLatest = true }; } }
/// <summary>
/// Gets the latest published version.
/// </summary>
public static VersionOptions Published { get { return new VersionOptions { IsPublished = true }; } }
/// <summary>
/// Gets the latest draft version.
/// </summary>
public static VersionOptions Draft { get { return new VersionOptions { IsDraft = true }; } }
/// <summary>
/// Gets the latest version and creates a new version draft based on it.
/// </summary>
public static VersionOptions DraftRequired { get { return new VersionOptions { IsDraft = true, IsDraftRequired = true }; } }
/// <summary>
/// Gets all versions.
/// </summary>
public static VersionOptions AllVersions { get { return new VersionOptions { IsAllVersions = true }; } }
/// <summary>
/// Gets a specific version based on its number.
/// </summary>
public static VersionOptions Number(int version) { return new VersionOptions { VersionNumber = version }; }
/// <summary>
/// Gets a specific version based on the version record identifier.
/// </summary>
public static VersionOptions VersionRecord(int id) { return new VersionOptions { VersionRecordId = id }; }
public bool IsLatest { get; private set; }