Sharepoint: web part programmatically changing permissions, cannot get the changes to persist - sharepoint

I'm writing a visual web part in visual studio for sharepoint 2010. The whole point of this web part is to change permissions around at the click of a button. I am able to access the permissions and output them to the screen. I'm able to change the permissions in the objects that I have, and then show the changed permissions on the screen. My problem is, after everything is done, no actual permissions have been changed.
webpart.TargetLibrary is a text field, inputted elsewhere as the name of the library I wish to investigate.
SPListCollection docLibs = m_SharePointWeb.GetListsOfType(SPBaseType.DocumentLibrary);
SPDocumentLibrary targetLib = (SPDocumentLibrary)(docLibs[webPart.TargetLibrary]);
SPListItemCollection libFolders = targetLib.Folders;
SPListItem folderItem = libFolders[0];
SPRoleAssignmentCollection folderRoles = folderItem.RoleAssignments;
SPRoleAssignment roleAssign = folderRoles[0];
SPRoleDefinitionBindingCollection spRDBC = roleAssign.RoleDefinitionBindings;
SPRoleDefinition Contribute = spRDBC[0].ParentWeb.RoleDefinitions["Contribute"];
folderItem.RoleAssignments[0].RoleDefinitionBindings.Add(Contribute);
folderItem.Update();
This is a somewhat simplified version - the original had some for loops and various bits of other code doing other things. Regardless, by everything I've been able to piece together from looking online, this code should add "Contribute" privs to the first role on the list in the first folder. As I mentioned, it does so to the local objects, but has no permanent effect. The Update() call appears to do nothing, and I'm not certain it's meant to be there in this case. I tried UpdateOverwriteVersion() - that doesn't do anything either. Any suggestions on what I might be doing wrong would be appreciated.
As a side note, it's not nearly so much of an issue, but I can't help the feeling that there's a more efficient and straightforward way to get a web object so that I can acquire role definitions by name. Any advice on that matter would also be appreciated.
Edit: solution moved to answer, below.

I have found answers to both the base and the side note.
For the side note, the following looks like it's the intended way to get an appropriate SPWeb object.
SPContext.Current.Web.RoleDefinitions["Contribute"];
For the base, the problem is that Sharepoint apparently does not save changing roles inside a SPRoleAssignment - only granting or removing permissions to the folder as a whole. This may or may not have to do with the fact that I was working inside a folder. In any case, in order to get it to save, you have to remove the person from SPRoleAssignmentCollection, make changes to their SPRoleAssignment, and then re-add the changed version. The correct version of the above code (integrating both answers) is as below.
SPRoleDefinition Contribute = SPContext.Current.Web.RoleDefinitions["Contribute"];
SPListCollection docLibs = m_SharePointWeb.GetListsOfType(SPBaseType.DocumentLibrary);
SPDocumentLibrary targetLib = (SPDocumentLibrary)(docLibs[webPart.TargetLibrary]);
SPListItemCollection libFolders = targetLib.Folders;
SPListItem folderItem = libFolders[0];
SPRoleAssignmentCollection folderRoles = folderItem.RoleAssignments;
SPRoleAssignment roleAssign = folderRoles[0];
folderRoles.Remove(roleAssign.Member);
roleAssign.RoleDefinitionBindings.Add(Contribute);
folderRoles.Add(roleAssign);

Related

Why is this considered an "Unsafe Update" in Sharepoint?

I have code like this to conditionally create a Sharepoint list (sort of an upsert):
private void ConditionallyCreateList()
{
SPWeb site = SPContext.Current.Web;
// Check to see if list already exists; if so, exit
if (site.Lists.TryGetList(listTitle) != null) return;
SPListCollection lists = site.Lists;
SPListTemplateType listTemplateType = new SPListTemplateType();
listTemplateType = SPListTemplateType.GenericList;
string listDescription = "This list retains vals inputted for the Post Travel form";
Guid ListId = lists.Add(listTitle, listDescription, listTemplateType);
. . .
This worked when first creating, and on subsequent execustions of the app.
However, I made some radical refactorings to the list structure and deleted the old one, so that (I hoped) a new one with the new structure would be created. However, instead of getting a refactored list, I got this on the last line shown above:
Microsoft.SharePoint.SPException was unhandled by user code
Message=Updates are currently disallowed on GET requests. To allow updates on a GET, set the 'AllowUnsafeUpdates' property on SPWeb.
I was able to resolve this by adding the indicated code:
site.AllowUnsafeUpdates = true;
...but why is this necessary? Why is the creation of a list which should no longer exist (I deleted it from the Sharepoint "All Site Content" bazaar) problematic (potentially an 'unsafe update')?
In an effort to protect itself from things like XSS and session hijacking, most updates to a SharePoint site are tied to a form digest control embedded on the same page from which the user makes the change. If the information from that form digest control isn't present when an update is triggered, SharePoint assumes the worst. This is especially important in cases where server-side code might execute with elevated privileges.
As you discovered, this is easily avoidable by switching the SPWeb object's AllowUnsafeUpdates property to true immediately before making any change.

Approving document library items from Object model in WSS 3.0

What is the correct way to approve an item in WSS 3.0 through the object model? I have some code that was recently modified to auto approve items that met certain criteria by another developer. That developer has left however, and now we are finding that ALL items are being approved, regardless of whether or not they meet that criteria.
I'm pouring through the literally thousands of lines of code looking for where this is happening.
Alternately, is there a permission group that grants approval rights? I know the users the code runs as, so I could alter those if such a thing exists. However, despite finding some mention of it in the MS docs, on our own installation I don't see the permission listed anywhere.
Thanks. Please let me know if I can provide more information - I'm not well versed in SP programming.
YOu should search something like this.
SPList oList = oWeb.Lists["Documents"];
SPFolder oFolder = oList.RootFolder;
foreach(SPFile oFile in oFolder.Files)
{
if (oFile.Level == SPFileLevel.Draft)
{
oFile.Approve("");
}
}

Sharepoint 2007 Webpart variables problem on reload

I'm having trouble with the webparts variables... I came from standard ASP language, so, to me, store variables in session and other parts is the common way to do everything =)
Now i had to create a webpart, the wp has to write a graph from parameter and i cannot understand HOW variables works: i cannot understand WHEN saved and WHEN erased and other thing like this!
Let me explain: i have a web part with the configuration toolbar on the right in which i put the values.. Everytime a button is pressed or a value in the dropdown list changes, it raises an event which causes the "CreateChild" function..
Many times the data is "stored", other time they are not!
That's the way i used to store value (in the ApplyChanges override function):
WPChartGenerator wpParent = (WPChartGenerator)this.ParentToolPane.SelectedWebPart;
wpParent.WebUrl = txtWebUrl.Text.Trim();
And in the CreateChild event i get the value like:
WPChartGenerator wpParent = (WPChartGenerator)this.ParentToolPane.SelectedWebPart;
this.ddlWeb = new DropDownList();
this.ddlWeb.ID = "ddlweb" + wpParent.ID;
ddlWeb.SelectedValue = wpParent.WebService;
Now.. Sometimes this works, for example, when i push a button I invoke in the code of the button and then the code to store every value.. In some case (like buttons) this works, in other (like dropdown list index changed event) this fails and i found every object in the wpParent equal to it's initial value.
Another thing i noticed, is that in certain cases when an event is triggered, the first thing to be executed (even first than the event's associated code) il CreateChild (even first than OnLoad!!!)
Can anybody tell me what I'm doing in the wrong way? Do anybody has a good tutoria for this matter?
Thanks & sorry 4 my School level English =)
Forget to say that every variable has been implemented as a Property, like that:
[WebBrowsable(false)]
[Personalizable(PersonalizationScope.Shared)]
[WebPartStorage(Storage.Shared)]
public string WebUrl
{
get
{
return this.webUrl;
}
set
{
this.webUrl = value;
}
}
I can't see all the code there so I don't really know what you're doing wrong (i.e. do you actually have an ApplyChanges method) but from the way you've worded your question it sounds like you really need to start at the beginning, follow one of these walkthrough tutorials and make sure you understand the basics and then start adding in the code for your project.
MSDN - Creating Web Parts for SharePoint (VS2010)
MSDN - Walkthrough: Creating a Basic SharePoint Web Part (WSS 3.0)
Developing SharePoint 2007 Web Parts

In Sharepoint, how do I update a task directly from a link in an email?

I'm just starting to use sharepoint designer and realised there's a lot that can be done to extend the basic features in sharepoint. We have an email alert sent out when a new task is created (by the user) and I want to customise the email so that it also includes a link called 'Assign'. When clicked, I want this link to automatically update the task with the assigned to field for the person that clicked it.
So I think the way to do this would be to hard-code the assign to value in the url behind this link, but I have no idea if this is possible or if there is an easier/better way to do this.
Any advice would be appreciated as I'm a complete beginner.
thanks.
I will not cover "How to modify the contents of an eamil alert" here as that is a seperate question and there are a lot of articles that cover that already.
For the Assigned link :-
You would need to create a custom page (or web part on an existing page) as the destination of your Assign link - this would take the Task ID as a query string param and then update the assigned to with the current user.
You could make this flexible by also taking the ListID but you may want to think about how this could be abused and put appropriate measures in place.
EDIT - in response to comment.
This is top of my head, not checked in compiler. This would have to sit on the same server as SharePoint to work as its using the OM - if you want to use a different server (why would you though) then look in the web services.
private void updateAssignedTo(Guid listId, int itemID)
{
SPWeb web = SPContent.Current.Web();
SPList list = web.Lists[listId];
SPListItem item = list.GetItemById(itemID);
item["Assigned To"] = web.CurrentUser;
item.Update();
}
You're going to have to work out how to get this code into to page or web part (SharePoint Designer is not going to cut it I think, you need Visual Studio) but its a starting point.

Problem finding Item List Id in WSS 3.0

I'm having a hard time figuring out how to refer to a specific Item List within a list in SharePoint. I looked up the page in SharePoint Designer and found that the listitem is inside a custom made webpart inside a custom made webpage. I'm coding an event receiver and need to read the information that the user types into that listitem which is a textbox. Does anyone know the code to do this or how to get the guid for the specific list item?
I would appreciate any help I can get. I have tried looking all over the web for the answer. Thanks.
It might be a good idea to edit your question with exactly what you'd like to do with the information you read. However from what you've said so far:
The ID of the item being edited will already be passed through to the event receiver via SPItemEventProperties so there is no need to look it up. If you need to look up a different item in the list (or indeed in a different list altogether), the Accessing list items using the object model page on SharePoint Dev Wiki gives you all of the options. A good general rule is use SPQuery to get best performance on the whole.
Note: There is a pretty good page on the SharePoint Dev Wiki demonstrating how to write an event receiver. It shows how to query and obtain a list item title.
Update after comments:
Once you have an SPListItem object, you can find its GUID through the UniqueId property. In the "Accessing lists" wiki link I've provided above the code samples show how to use the Title property.
Every piece of data you need to access within SharePoint should be available through the object model. This is a simplification, but generally the pages themselves are rendered from template files on the server and combined with data in the database to display to the user. So editing the page programmatically or through its source isn't going to work.
Apologies if I'm making an incorrect assumption but you sound fairly new to SharePoint development. I strongly recommend you read at least the first few chapters of Inside Windows SharePoint Services 3.0 as the inner workings of SharePoint are important to get a good understanding of and this book should help a lot. There is a section of event receivers in it as well.
Have you looked at SharePoint.ListsService Webservice?
string url = "WSS Site URL";
SharePoint.ListsService.Lists lists = SharePoint.ListsService.Lists(url);
XmlNode list = lists.GetList("ListName");
XmlNode xlists = lists.GetListCollection();

Resources