WSS v3 has very powerful item level security features that were completely non-existent in previous versions of SharePoint. This wiki discusses how to take advantage of those features for custom lists.
There are several ways to implement item-level security depending on your needs:
- Manual Item Security - simple, but cumbersome
- Manual Folder Security - easy with some flexibility, but requires some maintenance
- Item Owner Security - easy and low maintenance, but limited
- Programmatic Security - completely flexible, but requires developer implementation and testing
Ideally we would be able to add one more item to the list above for modifying permissions through SharePoint Designer workflows, but the out of the box activities with SPD workflows do not currently have this capability.
A last option not mentioned above is separating your data out into multiple lists and then just managing the permissions on the lists instead of managing item level permissions.
Manual Item Security
This solution is good if you don't need to manage permissions on very many items and you need some flexibility in how they are managed.
This is simply the act of managing the permissions on an individual list item. This must be done by an individual who has Full Control permission for the list. This is cumbersome because it must be done manually for each and every item in the list. One could set up alerts to know when an item is added or updated, then go in and modify the permissions, but this would be very cumbersome if it was needed on many items.
Manual Folder Security
This solution is good if you don't need to manage permissions for large number of folders, but you need to provide flexibility where subsets of individuals need access to certain items. This works well in the scenario where managers need access to their direct reports, but not those of other managers. It can even go multiple levels with regional managers, etc. This breaks down the quickest if folders are being added regularly that need permissions set on them.
This is simply the act of managing permissions on folders within a list. The list must first be set to allow for folders to be created from within the advanced settings of the custom list (Settings->List Settings->Advanced Settings).

As folders are created you can click on drop down to the right of the folder and choose Manage Permissions to grant or deny permissions to other individuals/groups. You must have full control to be able to manage permissions and you must have designer permissions to be able to add folders.
The nice part about this approach is that you can show the list as a hierarchical list with folders or you can show it as a flat list without folders. In either case, you only see what you are allowed to see. The hierarchical vs. flat setting is done within each view.

Item Owner Security
This solution is good if your requirements are such that individuals can only see (or edit) only the items they created or if they can see/edit all items. It does not work well if individuals need to view/edit entries they did not create such as a manager seeing their direct reports' entries, but not other managers' entries.
By default, contributors and readers for a list have access to all items within the list. However, within the advanced settings of a custom list (Settings->List Settings->Advanced Settings) you can specify that users can read "All items" (the default) or "Only their own". In addition, you can specify that users can edit "All items" (the default), "Only their own", or "None". These settings apply to individuals with contributor or reader permission for the list. Users with designer or full control will be able to read and edit all items regardless of these settings.

You can change these settings at any time and the behavior works as expected. When adding this restriction to a list with existing data the behavior is based on who it is Created By, not by whom it is last Modified By.
Some caveats with this approach:
- Either you see or can edit all items or only the items you created. There is no middle ground.
- For users that need to see and/or edit all items, they must be given designer or full control permissions. This means that they can change the list settings such as columns, etc.
- Coupling this approach with folders (described above) is not recommended because it has some strange side effects:
- As a list designer or individual with full control, you can create a folder at the root level then give designer or full control permissions of that folder to a list contributor (or reader). However, the recipient of this permission will not be able to see the folder.
- If you provide the link to the folder, the recipient can access it to see the contents as well as create sub-folders.
- This issue can be avoided if you use a view that does not show folders, but this might negate the benefits of using folders in the first place.
- Even if an individual has full control on a sub-folder, they cannot manage permissions on a folder or item within that sub-folder unless they have full control on the list itself. The "Manage Permissions" item shows in the drop-down on the title, but give you an error when you try to access it. This is likely a bug.
Programmatic Security
The SharePoint object model allows you to programmatically update the security on a list item. There are several scenarios that this could cover, but I will demonstrate one example below. See the references further below for examples from others.
In this example I have a people picker field ("Technician") that can be set by contributors on the list. When this is set, the specified technician is given contributor access to the list item, but previously did not have access to the list item. Basically technicians do not have reader permissions on the list, but are programmatically given access to specific items. This code is initiated through an ItemUpdated event (see SharePoint Events for more details).
public override void ItemAdded(SPItemEventProperties properties)
{
base.ItemAdded(properties);
this.SetTechnicianSecurity(properties);
}
public override void ItemUpdated(SPItemEventProperties properties)
{
base.ItemUpdated(properties);
this.SetTechnicianSecurity(properties);
}
private void SetTechnicianSecurity(SPItemEventProperties properties)
{
// Get the list item from the event
SPListItem item = properties.ListItem;
// Get the SPUser object from the Technician field
string lookupUser = item["Technician"] as string;
SPUser user = null;
if (lookupUser != null && lookupUser.Length > 0)
{
int userId = ItemHelpers.GetLookupID(lookupUser);
user = item.Web.SiteUsers.GetByID(userId);
}
if (user != null)
{
// Create a role assignment for our user and give it contributor bindings
SPRoleAssignment roleAssignment = new SPRoleAssignment(user);
roleAssignment.RoleDefinitionBindings.Add(item.Web.RoleDefinitions.GetByType(SPRoleType.Contributor));
// If we are currently inheriting our security, we need to break this inheritance
if (!item.HasUniqueRoleAssignments)
{
item.BreakRoleInheritance(true);
}
// Add the role assignment to our list item
item.RoleAssignments.Add(roleAssignment);
}
}
To get an Id from a lookup field, you might want to use some helper code (see below). Note that what is stored in the lookup is different if you are using an item from an event or AfterProperties from an event. The two helpers below are used depending on the situation.
public class ItemHelpers
{
public static Int32 GetLookupID(string lookupValue)
{
int index = lookupValue.IndexOf(';');
int id = Int32.Parse(lookupValue.Substring(0, index));
return id;
}
public static String GetLookupValue(string lookupValue)
{
int index = lookupValue.IndexOf(";#");
String val = lookupValue.Substring(index + 2, lookupValue.Length - (index + 2));
return val;
}
}
Some notes on the code provided:
- The code above is just an example with error handling, constants, and other good practices removed to make the example smaller.
- You can lookup existing users via Web.SiteUsers, but there are other types of user collections as well (Web.AllUsers, Web.Users, Web.SiteUserInfoList). If you are trying to find a user that is already set from a people picker use SiteUsers or SiteUserInfoList.
- The Web.SiteUsers collection and the Web.SiteUserInfoList come from the UserInfo table in the database WSS v3 database. The drop-down on any people pickers for a datasheet view appears to read from here.
- If you want to run this code from an Updating event, be careful because the user may not already be in the SiteUsers collection.
- A user is placed in SiteUsers the first time that user is put in a people picker anywhere in the site collection. This includes using a people picker when editing a list item, but also includes using a people picker to give permissions to a site or list. Note that it does not include using a people picker to give permission to a group that the individual is in.
- During an Updating event, the picked user has not been committed yet so if this is the first time the user is entered, it will not be found in SiteUsers. This is not a problem with asynchronous events such as Added and Updated.
Other Item Level Security Notes
- If a list has a lookup to another list, the lookup value will not be seen by those who do not have access to the other list.
- For example, if a Product list has an OrderNumber that is a lookup to an Order list and the user has access to Product, but not Order, the following will occur. The user will not see any OrderNumber values in their Product list. If they edit the item, the drop down for OrderNumber will be empty. If they save this edited item, the OrderNumber field will now be blank. This is allowed even if the field is required (a flaw, in my opinion).
- Editing permissions on a list item does not change the modified date for the list item.
- Users with Full Control appear to have the ability to manage permissions within the list while users with Design rights cannot. This appears to be the only difference between these two permissions.
- You can have limited access to a list if you do not have reader access to the list, but have rights on at least one item.
- If you have limited access to a list, you cannot see the view drop down, but you go to the default view for it when trying to access the list. You can go to the views if you know the link (you just don't see the views listed in the drop down).
References