Tuesday, February 13, 2007

InfoPath Browser Enabled Forms with Event Handled Security Control

After installing MOSS 2007 and the forms server I came upon the need to have custom item level security. This depended on the type of form as well as the content within the form. For example, human resources might have confidential documents which need to be signed by some users but not accessible by others. This would be possible if I had a library for each department and each form. Then there are medical situations which only the director of human resources is legally allowed to view. There seem to be little slight workarounds to get you just a little further only to run into something else. This drove me to want to control everything in code. I was aiming for a slightly generic event and didn't want a separate event to register for Medical forms so I just added it in here. I know this could be broken up better but everything seems so touchy and my current setup doesn't allow for debugging.

To register this event I suggest using the Event Handler Explorer which is a free tool that works great. If you want to hook in the event yourself here is a great quick article to do so. I tried to comment the code heavily so it would be fairly simple to customize to your needs. If you want to read a good article about user roles check this out.


 

Public
Overrides
Sub ItemAdded(ByVal properties As Microsoft.SharePoint.SPItemEventProperties)


MyBase.ItemAdded(properties)



'Create a SPWeb object

Dim web As Microsoft.SharePoint.SPWeb = properties.OpenWeb()




'Create an object for the SPListItem.


Dim ListItem As Microsoft.SharePoint.SPListItem = properties.ListItem




'The InfoPath form library has a column Employee Name which is created


'with the publish wizard. In my case it holds the domain\username of


'the user who created the form.


Dim UserName As
String = ListItem("Employee Name").ToString()




'Create a blank SPUser to hold the info for the person in the Employee Name


'column.


Dim User As Microsoft.SharePoint.SPUser




Try


'Must try to pull the user from the SiteUsers property.


'If the user is not in the SharePoint users it will


'throw an exception. Take that time to add the user.

User = web.SiteUsers(UserName)


Catch ex As Exception


Dim UserGroup As
New ucintranet.UserGroup


Dim Email As
String = MyWebService.GetEmail(UserName)


Dim FullName As
String = MyWebService.GetFullName(UserName)






'Somehow you must find the users email and fullname from


'the username. I did it with a web service which reads from


'Active Directory.


'Add the user to the SiteUsers property.

web.SiteUsers.Add(UserName, Email, FullName, String.Empty)


'Update the web object.

web.Update()




'Might not be nessisary but just making sure


'that the SP user collection is reloaded with


'the addition.

web.Close()

web = properties.OpenWeb()


End
Try


Try


'Try again to load the user.

User = web.SiteUsers(UserName)


Catch ex As Exception


Throw
New Exception("User failed to add to site collection.", ex)


End
Try




'Get a Contributor Role Definition from SPWeb (or whatever role you needed)


Dim ContributorRoleDefinition As Microsoft.SharePoint.SPRoleDefinition = web.RoleDefinitions.GetByType(Microsoft.SharePoint.SPRoleType.Contributor)




'Create new Role Assignment


'Add Role Definition to Role Assignment's Role Definition Binding. If you


'had multiple users you needed to give access to, you would just add more


'RoleAssignment objects with the specific SPUser object.


Dim UserRoleAssignment As
New Microsoft.SharePoint.SPRoleAssignment(User)

UserRoleAssignment.RoleDefinitionBindings.Add(ContributorRoleDefinition)








'This section is less than optimal but I just finished it


'and it works.


'Check for medial information, if present then don't use


'existing permissions as template (This strips all of the


'current site users and groups out of the item).




'Create a boolean object to determine if this form even deals


'with medical info. If it doesn't than the try will fail setting


'the EvalMedical object to false.


Dim EvalMedical As
Boolean = True


Dim Medical As
String = String.Empty


Try


'Contains Medical Information is the column name for the second


'field published as a column (T/F) through the publish wizard.

Medical = ListItem("Contains Medical Information").ToString()


Catch ex As Exception


'If it failed then there was no Contains Medical Information


'column present.

EvalMedical = False


End
Try




'If the column was present, this doesn't mean that it needs to


'apply the strict rules.


If EvalMedical Then


'If the Medical object is true than the RoleAssignments


'will not be copied therefore leaving an empty permission


'set for the item.

ListItem.BreakRoleInheritance(Not
CBool(Medical))




'This next object will hold the SPGroup of the HRDirector who needs


'access to the form. We create a new SPRoleAssignment object to hold


'the access level for the group and then add it to the SPListItem.


Dim Group As Microsoft.SharePoint.SPGroup = web.SiteGroups("HR Director")


Dim HRRoleAssignment As
New Microsoft.SharePoint.SPRoleAssignment(Group)

HRRoleAssignment.RoleDefinitionBindings.Add(ContributorRoleDefinition)

ListItem.RoleAssignments.Add(HRRoleAssignment)


ElseIf
Not ListItem.HasUniqueRoleAssignments Then


'Regardless, if the SPListItem has unique role assignments


'than they need to be broken, the RoleAssignments will be


'inherited though.

ListItem.BreakRoleInheritance(True)


End
If




'Add Role Assignment to SPListItem's Role Assignment Collection

ListItem.RoleAssignments.Add(UserRoleAssignment)




'One final update to the SPListItem.

ListItem.Update()


End
Sub

1 comment:

Susannah said...

You write very well.