Set Item Security based on Content Type

I’ve seen several queries asking how to limit the items or documents that a user can view.  Audiences can be used to filter views of List items and Library documents.  But Audiences aren’t and never have been security.  If a user wants access to all the items in a list or library all they need to do is create a custom view, no matter what audience they are part of.

So if you want to limit what a user has access to you need to set specific security on each item.  Item level security defaults to inheriting the security settings of the list or library in which they are created.  A user can implement specific security but it requires an additional step on each item created.  You could create items in folders with specific permissions and let the items inherit security from the folders, but then you can’t easily display items from diferent folders in a single view.

So the question is:  How can I set specific security rights automatically based on who the user is, content type, or the value of a metadata field?

In this post I’ll explain how to create an event handler that will automatically set security permissions based on the content type used to create the item.  First, lets look at the code of the event handler.

01: public class ItemSet : SPItemEventReceiver
02: {
03:   public override void ItemAdded(SPItemEventProperties properties)
04:   {
05:     base.ItemAdded(properties);
06:     SPWeb web = properties.OpenWeb();
07:     SPList list = web.Lists[properties.ListId];
08:     SPRoleAssignmentCollection roles = list.RoleAssignments;;
09:     SPListItem addedItem = properties.ListItem;
10:     addedItem.BreakRoleInheritance(false);
11:     foreach (SPRoleAssignment r in roles)
12:     {
13:       if (r.Member.Name.ToString().StartsWith(properties.ListItem.ContentType.Name
14:         .ToString(), StringComparison.CurrentCultureIgnoreCase))
15:       {
16:         addedItem.RoleAssignments.Add(r);
17:       }
18:     }
19:     this.DisableEventFiring();
20:     addedItem.Update();
21:     this.EnableEventFiring();
22:   }
23: }

In lines 6-8 the event handler instantiates the Sharepoint web holding the list and walks the heirarchy to get the list instance itself.  We’ll use this later to retrieve the groups that have permission to the list.  Line 9 retrieves the list item that was just added.  Line 10 calls the BreakRoleInteritance method to set the item up with its own security listing.  Passing ‘False’ as a parameter tells Sharepoint not to copy the security settings of the list when breaking inheritance.  The foreach loop in lines 11-18 compares the Name of each user/group who has permissions in the list with the ContentType of the item being added.  If the name of the user/group begins with the name of the Content type it is added to the permissions list of the item.  For example, if the Content type of the item is named ‘TypeA’ then groups named ‘TypeAContribute’ and ‘TypeARead’ would be granted permissions on the item, but a group called ‘TypeBContribute’ would not.  Finally, in lines 19-21 the event handler temporarily suspends event processing and updates the item instance in the Sharepoint database.  Events are temporarily disabled to prevent recursive events like ItemModifying from firing as a result of the security change.

Once the event handler has been strong named, compiled, added to the GAC and activated using a Web scoped feature we are ready to test the results.  The steps are listed below:

  1. Create and add specific content types to the list/library being secured.
  2. Create Sharepoint groups in the top level site of the site collection whose names start with the name of the content type that they should have access to.  For example: TypeAContribute group would have Contribute permissions for TypeA content.
  3. Assign the Sharepoint groups appropriate permission levels to the list. 
  4. Now create a new item in the list and security will automatically be changed so that only groups whose names start with the name of the content type will have access to the item.  For example, when I created an announcement based on a content type called ‘TypeA’ the security was set as shown below:TypeA SecurityWhen a member of one of the TypeA groups logs in they see and can access only the annoncements created using the TypeA content type.�TypeA 

But when a user logs in who is a member of a group called ‘TypeBContribute’ they only see and can access announcements based on the TypeB content type.


You could modify the basic shell of this event handler in several ways to meet the requirements of other scenarios.  For example, you could compare the groups with defined permissions in the list to the groups that the author is a member of and only add groups that the author and the list share in common.  Or you could add a custom choice field to the list with the names of sharepoint groups and let the user choose which groups to grant access to when creating the item.  Once you’ve got the basic event handler the only limits on setting security to a local list item is your own creativity.

Group A List by Week Number

I’ve seen several requests recently for how to Group a Sharepoint list by Month.  I’ve also seen several Blog posts on how to do it.  But recently I saw a query about how to Group by the Week Number of the year and several responses stating that it couldn’t be done.  I’ve always liked a good challenge, especially one that someone else says is IMPOSSIBLE.  So I decided ot figure out how to do it.  The results are below.

To Group a List by Week Number do the following:
  1. Make sure the list has a column that contains the Date you wish to GroupBy.  I’ll use the Start Time column of a standard Event list but you can use any Date/Time column.  You don’t need to filter out the Time portion first, it will be ignored.
  2. Add a Calculated column to the list called ‘WeekNumber’ that uses the following formula:
          =INT(([Start Time]-DATE(2007,1,1))/7)
    where [Start Time] is the date column whose week you want to group by.
  3. Set the data type of the Calculated Column to Number with 0 decimal places
  4. Create the view that you want Grouped by Week.
  5. SORT the view by [Start Time] and GROUPBY the [WeekNumber] column.

You’ll get a view that looks something like this:

This will give you a grouped list with the week number from the first day of the year.  But January 1st is rarely a Sunday or Monday.  If you want to be more accurate substitute the date of the first Sunday prior to 1/1/2007 in place of Date(2007,1,1).  This will give you the week number counting from the First partial week of the year.
Of course you’ll need to redo the calculated column when January rolls around next year, but only to change the Calculated Column to point at the first day of next year.

VTI Shooting brings back bad memories

I wasn’t really planning for this to be the second post on my new Blog, but the events at Virginia Technical Institute bring back too many bad memories.  My prayers go out to the family and friends of the students and faculty at VTI.  I know a little of what they are going through. 

In May, 2003 I went through a similar attack while a professor in the Business school at Case Western Reserve University in Cleveland, OH.  Compared to VTI we were relatively lucky, only one student was killed and two people injured, but we certainly didn’t feel lucky at the time.  Three PhD students and I were trapped in my office on the 5th floor of the building from the time the shooting started at 4:00 PM until SWAT rescued us at 12:30 AM the next morning.  At one point while trying to FAX a phone list for the building to the local police I came face to face with the gunman.  It was a terrifying experience.

MSNBC has a good report of the attack at Case Here:

including some of my testimony at the gunman’s trial

Welcome to my BLOG

Well its been a long time coming, but I’ve finally decided to start a BLOG.  I’ve never been much for keeping Journals, but now its time.  I’ve spent the last couple years starting my own Consulting/Training business.  In that timeI have continually stumbled across technical "Nuggets" by listening to students or while researching student questions.  But I’ve never had anywhere to publish those "Nuggets".  A Blog seems to be the perfect place to store this kind of asynchronously acquired information in a categorized format. 

Now that I’ve decided to give up the “freelancing thing“ and go to work for Mindsharp fulltime I don’t even have the excuse that I’m too busy trying to build the business.  Since Mindsharp has their own Blog hosting site its finally time.

So watch this space and I’ll try to share the things I learn about SharePoint, CRM, and .NET development.  Hang on to your hats its liable to be a bumpy ride.

Paul Stork