1

I have a SharePoint 2013 (on-premises) document library named “Reports”. It inherits the parent site’s permissions (by default). It has a column named “AssignedTo” of type People or Groups (mandatory & multiple selections enabled). So whenever anyone is uploading a new document in that library, he has to input minimum one username in that field. I need a Client-object model (C#) code that would do the following for each List Item in the “Reports” document library –

  1. Remove all permissions from the list item which were granted access by default (inheritance) while adding the item to the library.
  2. Only the Owner (i.e. the alias under Created By column) should have “Full Control” level of access to the list item.
  3. Only the users added to the corresponding “AssignedTo” column for that list item should have “Edit” access to that list item.

Any kind of help is highly appreciated.

  • 2
    Why use CSOM and not a SharePoint 2010 workflow with an Impersonation Step? – Mihail-Florin Popa Sep 18 '14 at 14:12
  • :) That is because they (the client) wants it like that. Also I have very minimal knowledge in workflows. If possible, can you share any document(s)/blog that can help me? It'll be good for learning. Thanks in advance. – Koushik Sep 18 '14 at 14:48
1

a PowerShell script using the Client Side Object Model – the script is executed every night.

  • The script iterates through a couple of lists each night a performs a couple of actions: Checks for new items
  • Based on the list item data, find the column ‘EmployeeId’ and query active directory to find the User Principle Name (UPN) (EmployeID is stored against each user in AD).
  • If the above action finds a user from AD the script removes all permissions on the list item and sets unique permissions so only the employee and a management group have access to that list item.

The following code snippets assume a connection to SharePoint is open (ClientContext), and the current web is loaded into context.

To find the SharePoint group the following was used:

   # Load in list of groups on the current web.
$groups = $web.SiteGroups
$ctx.Load($groups)
$ctx.ExecuteQuery()

# Find the group called HR. Note - using GetGroupByName was not working, therefore I had to iterate through the groups.

foreach($group in $groups)
{

if($group.Title -eq "hr")
{
$hrGrp = $group.Id
}
}

# Get the group and load into context to be used.
$spGrp = $groups.GetById($hrGrp)
$ctx.Load($spGrp);
$ctx.ExecuteQuery();

To set item level permission on each list item:

# Get the list by Title and load.
$list = $web.Lists.GetByTitle("MyListcctx.Load($list)
$ctx.ExecuteQuery()
$listTitle = $list.Title

# Simple query - purely used to ensure all data is returned.
$camlQuery = New-Object microsoft.SharePoint.Client.CamlQuery
$camlQuery.ViewXml = "10000"

# Load in the items.
$collListItem = $list.GetItems($camlQuery)
$ctx.Load($collListItem)
$ctx.ExecuteQuery()

# Iterate through each item.
foreach ($item in $collListItem)
{   
    # reset variable to ensure no false positives.
    $upn = $null
    $user = $null
    $roleAssignment = $null 
    $continue = $false

    # Set a couple of variable, get the user from AD based on employee number.
    $recordId = $item.Id
    $upn = Get-Upn -eid $item["EmployeeID"]
    $continue = $false

    if($upn -ne $null)
    {
        $continue = $true
    }
    else
    {
        Add-LogMessage "ERROR: Missing employee number on record '$recordId' "
    }   

    if($continue)
    {
        # Break inheritance on the list item and remove existing permissons.
        $item.BreakRoleInheritance($false, $true)

        # Get the permissions role for 'Read' and 'Edit'.
        $reader = $web.RoleDefinitions.GetByName("Read");
        $Editor = $web.RoleDefinitions.GetByName("Edit");

        # Create a role assignment and apply the 'read' role.
        $roleAssignment = New-Object microsoft.SharePoint.Client.RoleDefinitionBindingCollection($ctx)
        $roleAssignment.Add($reader)

        # Create a role assignment for editors - applying the 'edit' role.
        $roleAssignmentEditor = New-Object microsoft.SharePoint.Client.RoleDefinitionBindingCollection($ctx)
        $roleAssignmentEditor.Add($Editor)

        # Ensure the user exists on the site level, using EnsureUser.
        $user = $ctx.Site.RootWeb.EnsureUser($upn)
        $ctx.Load($user)

        # Apply the two permission roles to the list item.
        # $user is a SharePoint user.
        $ctx.Load($item.RoleAssignments.Add($user, $roleAssignment))    
        # spGrp is the HR group returned in the above snippet.
        $ctx.Load($item.RoleAssignments.Add($spGrp, $roleAssignmentEditor))

        # Update field on the list item to show it has ben processed.
        $item["A001"] = "PROCESSED"
        $item.Update()
    }

    # Execute changes.
    $ctx.ExecuteQuery();
}

http://dhendry.wordpress.com/2014/08/14/sharepoint-item-level-permissions-using-powershell-and-csom/

But if you want a workflow to set the item level permission check the below

http://www.sharepointbriefing.com/spcode/article.php/3911751/Implementing-ItemLevel-Security-in-SharePoint-2010-and-2007.htm

http://johnliu.net/blog/2010/7/13/sharepoint-2010-configuring-list-item-permissions-with-workf.html

0

It have to be something like this:

    string siteUrl = "http://MyServer/sites/MySiteCollection";

    ClientContext clientContext = new ClientContext(siteUrl);
    SP.List oList = clientContext.Web.Lists.GetByTitle("Reports");

    CamlQuery camlQuery = new CamlQuery();
    ListItemCollection collListItem = oList.GetItems(camlQuery);
    clientContext.Load(collListItem);
    clientContext.ExecuteQuery();
    foreach (ListItem oListItem in collListItem)
    {               
        clientContext.Load(oListItem,item => item["AssignedTo"]);               
        clientContext.ExecuteQuery();               

        oListItem.BreakRoleInheritance(false);              
        clientContext.ExecuteQuery();

        FieldUserValue authorsValue = (FieldUserValue)oListItem["Author"];                              
        User authorUser = clientContext.Web.EnsureUser(authorValue.LookupValue);
        clientContext.Load(authorUser);

        FieldUserValue[] assignedValues = ((FieldUserValue[])oListItem["AssignedTo"])[0];               
        foreach (FieldUserValue assignedValue in assignedValues)
        {
            User assignedUser = clientContext.Web.EnsureUser(assignedValue.LookupValue);
            clientContext.Load(assignedUser);
            clientContext.ExecuteQuery();
            RoleDefinitionBindingCollection collRoleDefinitionBindingAssignee = new RoleDefinitionBindingCollection(clientContext);
            collRoleDefinitionBindingAssignee.Add(clientContext.Web.RoleDefinitions.GetByType(RoleType.Contributor)); //Set permission type
            oListItem.RoleAssignments.Add(authorUser, collRoleDefinitionBindingAssignee);               
        }

        RoleDefinitionBindingCollection collRoleDefinitionBindingAuthor = new RoleDefinitionBindingCollection(clientContext);
        collRoleDefinitionBindingAuthor.Add(clientContext.Web.RoleDefinitions.GetByType(RoleType.Administrator)); //Set permission type
        oListItem.RoleAssignments.Add(authorUser, collRoleDefinitionBindingAuthor);             

        clientContext.ExecuteQuery();           
    }
  • Hi Ruslan, I was trying to work with your code and got the following error: "Unable to cast object of type 'Microsoft.SharePoint.Client.FieldUserValue[]' to type 'Microsoft.SharePoint.Client.FieldUserValue'" at the line "FieldUserValue assignedValue = (FieldUserValue)oListItem["AssignedTo"];". This is maybe because AssignedTo column is "multiple selections" enabled and more than one username can be provided. So I think you have to use an array. Can you please modify the code accordingly? Thanks in advance. – Koushik Sep 18 '14 at 15:11
0
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using Microsoft.SharePoint;
using Microsoft.SharePoint.Client;
using SP = Microsoft.SharePoint.Client;

namespace CustomReportsPermission
 {
class Program
{
    public static void Main(string[] args)
    {
        Program p = new Program();
        string siteUrl = "THE_FULL_SITE_URL";
        string docLibName = "Test";
        string accessToUsers = "Assigned"; 
        string author = "Author";

        p.ModifyPermissions(siteUrl, docLibName, accessToUsers, author);

        //Exit with Sucess code
        Console.WriteLine("Permissions modified successfully!");
        Environment.Exit(2000);
    }

    private void ModifyPermissions(String site, string docLib, string accessToUsers, string author)
    {
        try
        {
                ClientContext clientContext = new ClientContext(site);
                SP.List oList = clientContext.Web.Lists.GetByTitle(docLib);

                CamlQuery camlQuery = new CamlQuery();
                ListItemCollection collListItem = oList.GetItems(camlQuery);
                clientContext.Load(collListItem);
                clientContext.ExecuteQuery();

                foreach (ListItem oListItem in collListItem)
                    {               
                            clientContext.Load(oListItem,item => item[accessToUsers]);               
                            clientContext.ExecuteQuery();               

                            oListItem.BreakRoleInheritance(false,false);              
                            clientContext.ExecuteQuery();

                            string authorName = ((FieldUserValue)oListItem.FieldValues["Author"]).LookupValue.ToString();
                            User authorUser = clientContext.Web.EnsureUser(authorName);
                            clientContext.Load(authorUser);

                            if (oListItem["Assigned"] != null)

                            foreach (FieldUserValue userValue in oListItem["Assigned"]as FieldUserValue[])
                               {
                                string assignedName = userValue.LookupValue.ToString();
                                User assignedUser = clientContext.Web.EnsureUser(assignedName);
                                clientContext.Load(assignedUser);
                                clientContext.ExecuteQuery();

                                RoleDefinitionBindingCollection collRoleDefinitionBindingAssignee = new RoleDefinitionBindingCollection(clientContext);
                                collRoleDefinitionBindingAssignee.Add(clientContext.Web.RoleDefinitions.GetByType(RoleType.Contributor)); //Set permission type
                                oListItem.RoleAssignments.Add(assignedUser, collRoleDefinitionBindingAssignee); 
                               }

                            RoleDefinitionBindingCollection collRoleDefinitionBindingAuthor = new RoleDefinitionBindingCollection(clientContext);
                            collRoleDefinitionBindingAuthor.Add(clientContext.Web.RoleDefinitions.GetByType(RoleType.Administrator)); //Set permission type
                            oListItem.RoleAssignments.Add(authorUser, collRoleDefinitionBindingAuthor); 
                            clientContext.ExecuteQuery();
                    }
        }


        catch (Exception ex)
        {
            ex.Message.ToString();
        }
    }
}

}

  • This is the full working code. Made a small change to the code suggested by Ruslan. :) – Koushik Sep 18 '14 at 17:04

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

Not the answer you're looking for? Browse other questions tagged or ask your own question.