Restrict Access for block types

Vote:
 

Hi,

I need to restrict create/edit access for certain block types and can see it can be done using the Access attribute as documented here

https://world.episerver.com/documentation/developer-guides/CMS/Content/Attributes/

This seems to work for block creation but it does allow users to edit blocks that already exist.

Anyone seen this before and know how to resolve?

Thanks in advance

#221852
Apr 27, 2020 11:24
Vote:
 

Hello Mark

If I understand correctly you want to assign permissions by block type to stop blocks being edited after they have been created? If thats the case then it cannot be done out the box. But you can of course set folder level permissions once the blocks are created.

David

#221855
Apr 27, 2020 12:56
Vote:
 

Thanks David, so I guess we advise that the blocks of this type are always created in a certain 'place' which has permissions applied to prevent other users being able to edit?

#221859
Apr 27, 2020 13:07
Vote:
 

Hi Mark

If you wanted keep using out the box functionality then creating the blocks in certain folder(s) would be the most simple way of doing things.

David

#221866
Apr 27, 2020 14:37
Vote:
 

Thanks David

#221870
Apr 27, 2020 14:39
Vote:
 

Ok, using permissions and 'encouraging' a creation location isn't going to cut it unfortunately as we can't guarantee that editors will create the blocks in the correct location. So we need to enforce that only certain groups can edit these blocks.

I've been investigating the use of a custom attribute on the content type and passing in a list of groups that are allowed to edit and making the content read only if the user is not in one of the groups specified - as in this article but at the content type level rather than at property level. 

https://world.episerver.com/documentation/developer-guides/CMS/Content/Properties/built-in-property-types/Writing-custom-attributes/

However it doesn't seem to trigger at the content type level, has anyone done anything similar and have any hints/suggestions?

#222459
May 06, 2020 8:05
Vote:
 

Hey Mark

Option 1

You can always use a custom validator which may be the simpler way of doing it?

https://www.david-tec.com/2012/06/EPiServer-7-Preview---IValidator-interface/

Would mean the user gets a message as soon as they try and edit anything and prevent them editing?

Option 2

Another more complex/complete approach would be to:

  1. Hook into the content loading event
  2. Check the user permissions
  3. Update the Access Control List (ACL) to make it read only

I wrote some code for this years ago for CMS 6 in a project called security pack: https://www.david-tec.com/2012/04/Granular-Page-Type-security-in-EPiServer-using-PageTypeSecurityAddOn/

But the principle could still work on a CMS7+ but I have not tried it. This was webforms back in the day but shows the code to edit the ACL on a content object here: https://github.com/davidknipe/securitypack/blob/master/trunk/PageTypeSecurityAddOn/InitModules/SetPublishRightsForPageType.cs#L55

David

#222462
May 06, 2020 8:23
Vote:
 

Hi David,

I investigated using the content loading event and it didn't get fired, is there anything special that needs to be set up or enabled for this (content saving fires ok, content loaded gets fired multiple times!)?

We liked the custom attribute idea as it had the potential for re-use but I guess it doesn't work at the content type level?

Thanks,

Mark

#222467
May 06, 2020 8:34
Vote:
 

It looks like a IMetaDataExtender might come to the rescue. Just tried this and worked on my machine, you just need to add the logic to work out if the user has access: https://gist.github.com/davidknipe/14243810e1cb23096cee5b3c8d998059

You have access to the model defintion and data so can add an attribute using a similar approach to what I described here: https://www.david-tec.com/2017/07/hiding-required-properties-on-the-create-new-page-in-episerver/

#222474
Edited, May 06, 2020 13:11
Vote:
 

Hi David,

Thanks for that, the meta data extender approach was a great suggestion. On further investigation I was able to use this approach to actually get the Access attribute and check the roles defined so that I could make the properties read only for anyone not in any of the groups. So in the end I didn't need my custom attribute as I was able to make use of the built in one which makes it a lot cleaner and reusable.

Code for anyone that might find it useful, could probably be tidied up...

// Check it's a block
if (metadata.Model is BlockData)
{
    // Check if the block has the AccessAttribute applied
    var accessAttribute = metadata.Model.GetType().BaseType.CustomAttributes.Where(x => x.AttributeType == typeof(AccessAttribute));

    if (accessAttribute.Any())
    {
        // Get the roles defined for the AccessAttribute
        var allowedRoles = accessAttribute.First().NamedArguments.First(x => x.MemberName == "Roles").TypedValue;

        // Process based on roles and  loop through properties setting readonly if user does not have access
    }
}

Thanks again,

Mark

#222897
May 13, 2020 9:26
David Knipe - May 13, 2020 10:44
Great stuff, glad it solved your problem Mark!
* You are NOT allowed to include any hyperlinks in the post because your account hasn't associated to your company. User profile should be updated.