Restrict sitecore publishing - security

I am trying to set up some restrictions within my Sitecore instance so that users who only have permission to create items within a subsection of a site also have the publish permission, but only have the ability to publish items where they have create content permission.
For example I have the content similar to the following:
Sitecore
|- Content
|- Home
| - WhatWeDo
| - Infrastructure
| - Training
| - Locations
| - Europe
| - North America
I have set up the Everyone role to have read permission to all items within the content tree, and I have specifically specified that they are denied write, rename, create, and delete permission
I have set up a role, "WhatWeDo" and has been granted write, rename, create, and delete permission to item WhatWeDo and its descendants.
Now if I add the "WhatWeDo" role to the Client Publishing role, then the users who have been granted "WhatWeDo" role, also have the ability to publish, but they have the ability to publish any item within the content tree. i.e. The Publish button on the Publish ribbon is displayed.
Mostly when I have tried googling this, they are talking about publishing restrictions. i.e the Publishing Settings dialog, but this is of no use to me in this scenario.
I have found this https://stackoverflow.com/a/6351649/1442308 but I cannot seem to get this working and I suspect that it is related to very old version of Sitecore and no longer applies.
I have also updated my config so that the publishing should only publish if have read and write permission
<setting name="Publishing.CheckSecurity" >
<patch:attribute name="value" value="true" />
</setting>
But this has had no effect on restricting users publishing content tree items that they should not as the user is still able to publish items within the Locations section of the content tree. i.e. The publish button is still visible on the Publish ribbon.
I need to restrict this so that those users who have been granted the "WhatWeDo" role can only publish item WhatWeDo and its descendants, and do not have the ability to publish any other item within the content tree. i.e They should only have the publish button visible when they are in the WhatWeDo item or any of its descendants.
Update
Updated question to make it clearer that I want to make sure that the publishing button is not visible on the ribbon bar.

The Publishing.CheckSecurity setting is used durring the execution of the publish, so only items that the user has access to are actually published. It does not affect access to the publish ribbon button.
Typically, people use workflow to achieve what you are looking for. Set up a workflow with a publish action. The sample workflow provided with the initial install gives an example of this. Then you can restrict access to the workflow command.
Update
The Sample Workflow that is provided out-of-the-box has everything you need to get this to work. It has the commands and the auto-publish action as well as the security settings applied for the Sitecore Client Authoring role.
Since you have already applied security to your content items, all you would need to do is assign those items to the sample workflow. You could duplicate it and rename it if you wanted. You could also rename the Approve command to Publish.
To ensure that the standard publish button does not appear in the ribbon, make sure that these users are not members of the Sitecore Client Publishing role.

(Sorry but I don't have the comments option enabled yet.)
I would definitely go for the workflows option. As mentionned in the comments, the Publish button will be enabled through the security permissions, but as a general ability, not dependent on the items permissions. If you don't want the Publish button to show up without going into fancy customizations, you should forget this option.
Instead of the classical Publish button, users would have the workflow button triggering the publish action, under the Review tab. It wouldn't change that much for your end-users. It will even get them used to the workflow actions, that you could further use and refine, later in your project. You could take this opportunity to introduce them in your project, moreover it's perfectly suiting your needs.
Don't hesitate to ask if you want more detailed explanations on how to set up such a workflow.

It's not possible hide the publish button in the ribbon out of the box for items that the user does not have access to, but it is quite simple to use the Rules Engine to control whether the button is shown or not. It will require some coding though, there is no way around that.
You can find more information in these blog posts, but there are some differences for Sitecore 7.1+ due to changes in the Rules Engine:
Rule-Based User Interface Components for the Sitecore Client
How to create a custom ribbon in Sitecore Content Editor
Limiting Conditions and Actions with Sitecore 7.1+
1. Create the rule action class
In your Visual Studio Project create the CommandRuleContext and SetCommandState classes as specified in first blog post.
2. Create the Rule in Sitecore
This is where there have been a lot of updates in Sitecore 7.1+, the third blog post explains the new structure of the rules engine:
Under /sitecore/system/Settings/Rules/Definitions/Tags create a new tag called Command State
Under /sitecore/system/Settings/Rules/Definitions create a new folder called Command States and add the 4 states shown in Step 1.14
Create a new Element Folder under /sitecore/system/Settings/Rules/Definitions/Elements called Command Rules
Insert a new Action under this folder. Set the field values as:
Text: set command state to [commandstateid,Tree,root=/sitecore/system/Settings/Rules/Definitions/Command States,specific command state]
Type: MyProject.Custom.Commands.SetCommandState, MyProject.Custom
Select the Tags/Default item and select Command State from the list of tags. This is the tag we defined earlier.
Now under /sitecore/system/Settings/Rules insert a new "Rules Context Folder" called Command Rules and then add a new rule in the Rules folder.
Before we create the rule we need to associate tags to show the conditions and actions. Select the "Tags/Default" item again and this time select Command State and Item Security. You can select different tags if you want to use different conditions (e.g. Item Hierarchy, Item Information, Security etc)
Now create the rule with condition you need, e.g.
3. Update the command to use the Rules
We need to update the code for the Publish button command to use the Rules we have defined.
Create a new command class inheriting from the existing Publish command:
using Sitecore.Data.Items;
using Sitecore.Diagnostics;
using Sitecore.Rules;
using Sitecore.SecurityModel;
using Sitecore.Shell.Framework.Commands;
namespace MyProject.Custom.Commands
{
public class PermissionBasedPublish : Sitecore.Shell.Framework.Commands.PublishNow
{
public override CommandState QueryState(CommandContext context)
{
Assert.ArgumentNotNull(context, "context");
var state = base.QueryState(context);
if (state != CommandState.Enabled)
return state;
return RunRules(context);
}
private CommandState RunRules(CommandContext context)
{
Item parentRuleItem;
var ruleContext = new CommandRuleContext();
ruleContext.Item = context.Items[0];
using (new SecurityDisabler())
{
parentRuleItem = ruleContext.Item.Database.GetItem("/sitecore/system/Settings/Rules/Command Rules/Rules");
if (parentRuleItem == null)
return CommandState.Enabled;
}
RuleList<CommandRuleContext> rules = RuleFactory.GetRules<CommandRuleContext>(parentRuleItem, "Rule");
if (rules == null)
return CommandState.Enabled;
rules.Run(ruleContext);
return ruleContext.CommandState;
}
}
}
And now we can patch in this command instead of the default one:
<configuration xmlns:patch="http://www.sitecore.net/xmlconfig/" xmlns:set="http://www.sitecore.net/xmlconfig/set/">
<sitecore>
<commands>
<command name="item:publishnow">
<patch:attribute name="type">MyProject.Custom.Commands.PermissionBasedPublish, MyProject.Custom</patch:attribute>
</command>
</commands>
</sitecore>
</configuration>
The visibility of the publish button is now based on defined rules. With the rule defined above, the button will only be visible if the user has write access to the current item they are one.
The user will still need publish permission using the appropriate roles. Note that using out of the box roles means the user will have access to the Publish Site option from the drop down as well. You need to restrict access to /sitecore/content/Applications/Content Editor/Menues/Publish/Publish Site in the Core database and the shortcut from the desktop as appropriate.
You may also want to combine this with the Publishing.CheckSecurity setting by setting it to true.
I'll add that giving users Publish rights as a general rule is a bad idea IMO since every publish, even of a single item (and this includes Auto-Publish with Workflow) will clear the HTML caches and may lead to performance issues.

Related

SharePoint Hosted App 2013: Customize List/AllItems.aspx page

I'm trying to implement permission levels in SharePoint hosted app. I've created a custom list "Permissions" where I'm adding different users with their roles.
I have created a page List.aspx where I'm showing my custom list "Products" as a list view web part. Page List.aspx checks the user's role against "Permissions" list, and page can show or hide content in regards to this role. The problem is, when user tries to navigate to "Lists/Products/Allitems.aspx" or "Lists/Permissions/Allitems.aspx" he can see the list items.
All code check is done in JavaScript and I know there is a security risk, but this will work for my users. I just need to find a way to inject custom JavaScript code to Allitems.aspx, and to check if user has permissions to see it or not.
Everything here is done on App web and there's nothing that I use on host web.
I've found a workaround for this. Basically what I did is that I just hide the list view from direct access. To achieve this, open the Schema.xml of the list and replace "JSLink":
from
<JSLink>clienttemplates.js</JSLink>
to
<JSLink>~site/Scripts/OverrideListView.js</JSLink>
Now, create a new file Scripts/OverrideListView.js and add following code to it:
document.write("<style>body {display:none; };</style>");
Try now to access Lists/Permissions/Allitems.aspx directly. You will get a blank page.
This is basically idea how to insert custom JS code into list view. You could add additional code for checking current user's permissions on site level and in regards to it to unhide this view, or even to redirect him to the homepage if he does not have right role or permissions.

Setting dynamic author_id on Safecracker form as non Super Admin group

I have a project where I need a member group called Staff Admin (slightly less privileges than Super Admin) to be able to public entry data on behalf of a site Member via a Safecracker form. Now I am able to successfully set an 'author_id' on the form (using a hidden input) and a user logged in under the Super Admin group can successfully publish the new entry and have the specified author_id set on the entry.
The problem is that even though I have the 'Staff Admin' group settings allow to edit and change authors on entries, I'm unable to do it on a Safecracker form and the specified 'author_id' is ignored and I'm getting an error triggered for 'invalid_author' (The selected author is invalid.)
Think the line in the Api_channel_entries.php is around 1246 (under EE 2.4) where it’s looking to authenticate against Super Admin group only as the exception:
if ($data['author_id'] != $this->EE->session->userdata('member_id') && $this->EE->session->userdata('group_id') != 1)
Any ideas how I might circumvent this problem I have?
That error is being triggered because the author ID that you're trying to reassign the entry to is not one of the designated valid authors for the channel. To fix this you'll need to edit the member group (of the user you're trying to assign the entry to) and enable the 'Include Members in PUBLISH page multi-author list?' setting.
You may also need to enable that setting for each individual user via Member Administration > Edit Member > Member Preferences > "Include user in PUBLISH page multi-author list?"

Disallow viewing list items

Suppose there's a top-secret list (inherits its permissions from its parent) that contains records that were created earlier by different users. There are several groups with rights to administer, read, write-constrainted.
There is a group of authors of top-secret items. Author can only create a 'secret-item'. But the item shouldn't be viewed by other participants of the group (Authors).
I can't access/change site programmatically. And I'm curious how come I do this manually.
First, keep in mind that you cannot do "top-secret" in SharePoint. The site collection administrator will always have access to all content.
Manually, there are two features that come close to your request:
under advanced options in the list settings: user can only read/write his/her own items
under the same advanced options: activate approval. Content in draft state will remain hidden (except from approvers and site owners)
In addition to the answers from #Christophe, you can also modify the permissions of individual List Items.
If you were able to make programmatic changes, I would suggest attaching an ItemAdded event receiver to a custom Content Type named "Top Secret." But in this case, the permissions changes can be made as a manual step after adding the item.
The risk, of course, is if the author forgets to change the permissions, changes the permissions incorrectly, or changes the permissions very slowly (allowing others to see it before permissions are changed).
For more information on changing the permissions of a List Item, see Break permission inheritance on a folder, document, or list item.

SharePoint - Adding users from Active Directory in a custom administration form

I have a project where I need to add users to a SharePoint portal, but when I add them, I also need to set addition parameters inside a separate database.
I want to add a custom administration screen where the administration can set these values when they add the user rather than forcing them to first add the user then go to a separate interface page where they set the values.
Does anyone know of any good articles that will explain how to accomplish this?
Thanks.
It would be easier to create a custom asp.net form that would get all the information required about the user.
the submit could then add the information to the database that is needed and use the object model to add the users.
SPRoleAssignment MyRoleAssign = new SPRoleAssignment(”domain/alias”, “email address”, “User Name”, “Description”);
SPRoleDefinition MyRoleDef = newSubWeb.RoleDefinitions["Contribute"];
MyRoleAssign.RoleDefinitionBindings.Add(MyRoleDef);
site.RoleAssignments.Add(MyRoleAssign);
Code from farhanfaiz.wordpress.com here
Otherwise the SharePoint webservices may do.
Examples here

What are some decent ways to prevent users from creating meeting workspaces?

I have an Events list in sharepoint and need to disallow users from having the ability to create meeting workspaces in the new event form. Shy of customizing the new event form (which breaks attachment support), how can this be done?
By default, in order for users to create a meeting workspace, they will need to be an administrator or Site Owner (specifically they will need the Create Sites permission). If you don't give them this permission, they won't be able to create a meeting workspace.
This will disallow the user to create any site under the site where these permissions are set. I'm not aware of a way to restrict access to a specific site definition but still allow users to create a different one.
I don't think there is a supported way of doing this. One option is to edit the WEBTEMP.XML file in C:\Program Files\Common Files\Microsoft Shared\web server extensions\12\TEMPLATE\1033\XML\WEBTEMP.XML (make a backup first of course). Comment out the lines as follows:
<!-- <Template Name="MPS" ID="2">
...
</Template> -->
After editing this file and executing IISRESET on every server in the farm, you shouldn't be able to create a meeting workspace any longer.
If you can get some javascript into the masterpage, I came up with this little hack.
It does have a couple downsides in that MS could potentially releaase a hotfix or service pack that either:
changes the name of the "Use a Meeting Workspace to organize attendees, agendas, documents, minutes, and other details for this event" checkbox such that the string "CrossProjectLinkField" is no longer in the name, or...
they could use that same string in the name of some other input element on some other OOTB markup
In the ladder case (which I'm not entirely certain is false right now), these inputs would get disabled if they were sporting a masterpage that ran this script.
But this is a risk I can deal with. You run these risks anytime you depend upon client ids and names being emitted by someone else's control.
<script type="text/javascript">
var anchors = document.getElementsByTagName('input');
for(var i=0;i<anchors.length;i++)
{
var anchorName = anchors[i].name.match('CrossProjectLinkField');
if(anchorName != null)
{
anchors[i].disabled = true;
break;
}
}
</script>
What this does is find the checkbox that allows users to create meeting workspaces and disables it so that they cannot check it. Problem solved!
Create a web scoped feature with a feature receiver that deletes the current web the feature is activated on and have it throw an SPException stating that the template cannot be used. Then create a web application or farm scoped feature stapler that staples the previous feature to the site definitions you want to prevent. Activate that feature on the web application or farm. Then when someone creates a site from one of the site definitions the site will be deleted and the user will be presented with an error page displaying the text of the SPException thrown.

Resources