Conditionally disabling 'Publish' button in Edit mode

Vote:
 

Client has need to prevent a user form Approving/Publishing any page they have themselves created.

Checking if the current user = page creator seems simple enough. However... I'm struggling to find way to access the relevant control from the page's master page code-behind? ... as page seems to be bundled up into the container of Edit mode by black magic...

Any ideas...??

p.s. I'd prefer not to fiddle with code of the epiServer application (in C:\Program Files..), but rather (override something?) in the website code (C\Episerver\Sites...) for simplicity of deployment.

#89929
Aug 28, 2014 17:44
Vote:
 

I would suggest something like the following:

  • Use an EPiServer Initialisation module and hook into the LoadedContent event
  • From there check if the user is in edit mode (RequestSegmentContext.CurrentContextMode != ContextMode.Edit)
  • Get the content item from ContentEventArgs.Content and check if the user was the original creator
  • Finally get the AccessControlList (ACL) for the content item, duplicate it, remove Publish rights and add back to the content item

However this does mean some code...

#89930
Edited, Aug 28, 2014 18:07
Vote:
 

Had a very similar request, much easier in episerver 6:

in episerver.config add:



Copy the user control from the episerver program files install, then grab the code behind by using reflector or ilspy etc. It is in episerver.ui.dll then Episerver.UI.Edit then EditPageButtonControl.

Then change the code as required.

Make sure you secure the "yourOverrides" path in web.config as per the existing edit mode pages.

It was the easiest way I found.

Cheers,

Paul

#89995
Sep 01, 2014 1:10
Vote:
 

Paul

Thanks, that seems like a really useful approach.

One problem I'm running into with this though is the confilct of this 'new' version of 'Button control' with the existing one...

Warning The type 'EPiServer.UI.Edit.EditPageButtonControl' in 'C:\EPiServer\Sites\Wesleyan\Templates\Wesleyan\overrides\EditPageButtonControl.ascx.cs' conflicts with the imported type 'EPiServer.UI.Edit.EditPageButtonControl' in 'C:\EPiServer\Sites\Wesleyan\bin\EPiServer.UI.dll'. Using the type defined in 'C:\EPiServer\Sites\Wesleyan\Templates\Wesleyan\overrides\EditPageButtonControl.ascx.cs'.C:\EPiServer\Sites\Wesleyan\Templates\Wesleyan\overrides\EditPageButtonControl.ascx.cs92221EPiServer.Templates.RelatePlus

...sorry if I'm being a bit thick, but trying to change namespace just makes other issues appear...? 

#90027
Sep 01, 2014 12:42
Vote:
 

...removed GAC assembly (EPiServer.UI.dll), and now get: 

The type 'EPiServer.UI.Edit.EditPageButtonControl' is ambiguous: it could come from assembly 'C:\EPiServer\Sites\Wesleyan\bin\EPiServer.Templates.RelatePlus.DLL' or from assembly 'C:\EPiServer\Sites\Wesleyan\bin\EPiServer.UI.DLL'. Please specify the assembly explicitly in the type name

#90031
Sep 01, 2014 12:59
Vote:
 

Hi,
You can simply hook up publishing event in data factory and do your checks there.
Like this:

            DataFactory.Instance.PublishingPage += Instance_PublishingPage;



        static void Instance_PublishingPage(object sender, PageEventArgs e)
        {
            e.CancelReason = "Not allowed to publish";
            e.CancelAction = true;

        }

Regards,

Giedrius

#90033
Edited, Sep 01, 2014 13:02
Vote:
 

Giedrius, come to think of it that would certainly be the easiest option. I think I was thinking of ways of conditioning the publish button :)!

#90045
Edited, Sep 01, 2014 13:22
Vote:
 

Giedrius - thanks very much.

Ideally I'd have liked option to disable the button that would have been possible with Paul's approach... but your idea is much simpler, and it works straight away.  :)

#90049
Sep 01, 2014 13:35
Vote:
 

Hi David,

Is it possible to get ACL list in intlization module in cms9,

I am using Bellow code,

PageData pg = DataFactory.Instance.GetPage(new PageReference((e.ContentLink).ID));


PageAccessControlList acl = new PageAccessControlList(pg.PageLink);
acl.Add(new AccessControlEntry("Administrators", AccessLevel.NoAccess, SecurityEntityType.Role));
acl.Save();


//pg.IsPendingPublish = true; --> got readonly unable to set sagar
var events = e.RequiredAccess;
e.CancelAction = true;
e.CancelReason = "Approved no need publish";

But i am getting ACL count is Zero.

#151902
Aug 10, 2016 8:33
Vote:
 

Hello Sagar

You will need to cast the current IContent item as IContentSecurable then get hold of the IContentSecurityDescriptor from the securable entity. I've written the (untested) code below to get the current ACL list from a IContent item as part of an initialisation module:

private IEnumerable<AccessControlEntry> GetEffectiveACL(IContent content)
{
    IEnumerable<AccessControlEntry> aclEntries = null;

    // Check if the content type can have access restrictions
    IContentSecurable securable = content as IContentSecurable;
    if (securable != null)
    {
        // Get hold of the security descriptor
        IContentSecurityDescriptor contentSecurityDescriptor = securable.GetContentSecurityDescriptor();

        if (contentSecurityDescriptor.IsInherited)
        {
            // Need to ensure the LoadedContent event is not fired when we get the ACL Entries when the ACL list
            // is inherited. This is because accessing .Entries on a content item that has an inherited ACL will  
            // load parent content items until a parent item that is not inherierd is found. However the loading 
            // of parents will cause the LoadedContent event to be fired so would cause a recursive loop.
            lock (this)
            {
                var contentEvents = EPiServer.ServiceLocation.ServiceLocator.Current.GetInstance<IContentEvents>();
                contentEvents.LoadedContent -= Instance_LoadedContent;

                aclEntries = GetACLEntries(contentSecurityDescriptor);

                contentEvents.LoadedContent += Instance_LoadedContent;
            }
        }
        else
        {
            //Safe to access .Entries directly as it will not cause up a recursive load up through the parent content items
            aclEntries = GetACLEntries(contentSecurityDescriptor);
        }

    }
    return aclEntries;
}
 private IEnumerable<AccessControlEntry> GetACLEntries(IContentSecurityDescriptor contentSecurityDescriptor)
        {
            if (contentSecurityDescriptor != null && contentSecurityDescriptor.Entries != null)
            {
                return contentSecurityDescriptor.Entries;
            }
            return null;
        }



#151916
Edited, Aug 10, 2016 11:02
Vote:
 

Hi David,

Thanks for your reply.

I alrady somehow achieved to get the access list by using Pagedata instance.ACL.Entries property.

But i struck in the way to find a way for the restriction page publishing for a user who has rights to publish the page.
Tried with e.CancelAction = True, but it is not satisfying my requirement.

Can you suggest me any ideas to achieve changing accessrights for a particular user dynamically for a particular page?

Best Regards,
Sagar

#151958
Aug 11, 2016 7:34
This thread is locked and should be used for reference only. Please use the Episerver CMS 7 and earlier versions forum to open new discussions.