tags:

views:

29

answers:

1

Say you have two lists in Sharepoint, let's call them "house" and "region".

Each house is assigned to a region via a lookup field.

List item permissions are set on regions.

Now I want the users only to only see the houses which belong to the regions they have read access to. I reckon it should be relatively simple I see no easy way of doing this. Am I over looking something.

+1  A: 

If you want an automated process that occurs when a new house is added, then there's a simple enough method for this using EventReceivers. If you don't have experience with EventReceivers, check out this article for the basics. You'll need to create ItemAdded and ItemUpdated events with pretty much identical contents - one for when the house is first made, and one for if the region for a house is ever changed. First, the house must break role inheritence if it doesn't already have unique assignments. Now, if the region hasn't changed in an update, there is no need to proceed. Otherwise, you need clear the current permission set, then retrieve the region in the lookup value by looking up the list and then the item ID. Iterate across the permissions in the region for anyone who has at least Read permissions, and add those users to the house. When it's done, update, and now the only people who will see that house are those who can read that particular region. Below is a general gist of what the code might look like in your event receiver.

using (SPSite site = new SPSite(properties.WebUrl))
{ 
    using (SPWeb web = site.OpenWeb())
    {
        SPListItem houseItem = properties.ListItem;
        SPList regionList = web.Lists["Region"];
        if (houseItem.HasUniqueRoleAssignments)
        {
            houseItem.BreakRoleInheritance(false); //Clears all
        }

        //After confirming that the region has changed and is not empty/null...
        SPFieldLookupValue regionLookup = houseItem["RegionLookup"] as SPFieldLookupValue;
        SPListItem regionItem = regionList.GetItemById(regionLookup.LookupId);
        SPRoleDefinition readAccess = web.RoleDefinitions["Read"];
        foreach (SPRoleAssignment userRole in regionItem.RoleAssignments)
        {
            //READ CHECK
            if (userRole.RoleDefinitionBindings.Contains(readAccess))
            {
                houseItem.RoleAssignments.Add(userRole);
            }
        }
        this.DisableEventFiring();
        houseItem.SystemUpdate(false);
        this.EnableEventFiring();
    }
}

Note that for the point marked //READ CHECK, all this code snippet does is check if the "Read" role definition is assigned to that user for the region. If you want to check for the "ViewItem" permission specifically, you would have to iterate across all RoleDefinitionBindings in that RoleAssignment and check the BasePermissions to see if it contains "ViewItem".

ccomet
I guess I was hoping for an easier way :) but now you've pretty much told how the hard way is done. Cheers!
Dan Sydner
@Dan Yeah, permissions are a wonky bunch like that. You can imagine the "fun" I had with setting up time-based permission workflows on my SharePoint application.
ccomet