Friday, 13 November 2009

Setting ModerationInformation.Status back to pending removes author/creator permissions

Here’s the scenario – I have a visual studio sequential workflow on a list (not document library) which has a 2 stage approval process.  The request was to use the standard OOB approve/reject mechanism rather than tasks, so for the first stage of approval, the approver would select Approve/Reject from a list item.  Once the first stage approver approves the item, the item should NOT be approved and live, but still pending and an email sent to the 2nd level approver to make the ultimate decision of making the item live.  Once the 2nd stage approver approves the item the item then becomes Approved and Published for all to see.
I created a Visual Studio Sequential Workflow and created separate routes through workflow based on who updated the List Item.

image
In code, if the item was approved by the 1st stage approver  i would reset the ModerationInformation.Status back to pending, my code was simple and as follows;
1: this.workflowProperties.Item.ModerationInformation.Status = SPModerationStatusType.Pending;
2: this.workflowProperties.Item.Update();
3: 
4: 



To troubleshoot this, i took to using Powershell and SharePoint Manager from codeplex to see what was happening to my list item.   Throughout, the creator and author field was not changed from the person that created, yet as soon as i set the moderationinformation.status back to pending, the creator of the item lost ALL permissions to even view the item.


I had tried the following to rectify this but none worked;


  1. I have tried all combinations of Update(), SystemUpdate(), SystemUpdate(false), SystemUpdate(true), UpdateOverwriteVersion() when saving the list item and none of them had any effect.
  2. I tried to up the version number so that the version of the list item that was being approved and set back to pending was version 2.0 to ensure that the Creator/Author was preserved.


I have only found one way in which to rectify this problem and that is to re-assign the roledefinitionsbinding for that user to a level which allows them to edit/update the item again.  I did this using the following code.   Just one more thing, i had also disabledeventfiring in my workflow so i can be sure that events dont keep firing and updating the item.   This is how i did that in code;


1: SPListItem currentItem = this.workflowProperties.Item;
2: //Get the Full Control Role Definition
3: SPRoleDefinitionCollection roleDefs = this.workflowProperties.Web.RoleDefinitions;
4: SPRoleDefinition roleFullControl = roleDefs["Full Control"];
5: //Get the current items role assignments
6: SPRoleAssignmentCollection rolesInList = currentItem.RoleAssignments;
7: //iterate through and find the creator users role assigment
8: foreach(SPRoleAssignment role in rolesInList)
9: {
10:   string createdByString = currentItem["Created By"].ToString();
11:   int indexOfSemiColon = createdByString.IndexOf(";");
12:   int createdById = Int32.Parse(createdByString.Substring(0, indexOfSemiColon));
13:   if(role.Member.ID == createdById)
14:   {
15:     try
16:     {
17:       //firstly remove any role bindings the add in whatever level you require
18:       role.RoleDefinitionBindings.RemoveAll();
19:       role.RoleDefinitionBingings.Add(roleFullControl);
20:       role.Update();
21:     }
22:     catch{}
23:   }
24: }


This solved my problem, but i am not saying this is the correct solution in all cases.


If anyone comes up with an answer as to why this happens, feel free to post a reply to this.

0 comments:

Post a Comment