Change permission level for groups programmatically in SharePoint 2010? - sharepoint

I want to loop through all the sites in a site collection and change the permission for a certain site.
My code is:
SPSite oSiteCollection = SPContext.Current.Site;
SPWebCollection collWebsite = oSiteCollection.AllWebs;
foreach (SPWeb web in collWebsite)
{
web.AllowUnsafeUpdates = true;
if (web.Name == "SiteName")
{
web.BreakRoleInheritance(true);
string[] groups = new string[2] { "Group1", "Group2" };
foreach (string item in groups)
{
SPGroup removeGroup = web.SiteGroups[item];
web.RoleAssignments.Remove(removeGroup);
SPGroup addGroup = web.SiteGroups[item];
SPRoleDefinition roleDefinition = web.RoleDefinitions["Read"];
SPRoleAssignment roleAssignment = new SPRoleAssignment(addGroup);
roleAssignment.RoleDefinitionBindings.Add(roleDefinition);
web.RoleAssignments.Add(roleAssignment);
}
}
}
but it gives me an error
Error changing permissions, details: There are uncommitted changes on the SPWeb object, call SPWeb.Update() to commit the changes before calling this method.
The code works just fine if I want to do the same but for lists instead
SPListCollection collList = web.Lists;
foreach (SPList oList in collList)
{
//and so on
I have tried to put web.Update() in various places but without success. Any ideas?
Thanks in advance.
Edit:
I commented out most of the stuff and only left
if (web.Name == "SiteName")
{
web.BreakRoleInheritance(true);
web.Update();
}
but it still throws the same error.

I would try to do an SPWeb.Update and then
using(var newWeb = site.OpenWeb(web.ID))
{
web.BreakRoleInheritance(true);
web.Update();
}
Also, don't forget to do a SPWeb.Dispose on all the AllWebs opened in the foreach-loop.

If you are using this code in a Feature, then make sure that you use a Web level feature. Don't loop through AllWebs in a Site level feature.
Change the feature scope to Web and try the below code
using (SPWeb oWeb = SPContext.Current.Web)
{
web.AllowUnsafeUpdates = true;
web.BreakRoleInheritance(true);
string[] groups = new string[2] { "Group1", "Group2" };
foreach (string item in groups)
{
SPGroup removeGroup = web.SiteGroups[item];
web.RoleAssignments.Remove(removeGroup);
SPGroup addGroup = web.SiteGroups[item];
SPRoleDefinition roleDefinition = web.RoleDefinitions["Read"];
SPRoleAssignment roleAssignment = new SPRoleAssignment(addGroup);
roleAssignment.RoleDefinitionBindings.Add(roleDefinition);
web.RoleAssignments.Add(roleAssignment);
}
web.AllowUnsafeUpdates = false;
}
Activate this feature in the required website to apply the permissions.

I'm not sure what the problem is.
But it could happen that the DLL is not being updated. It happened to me several times.
Try to delete the DLL from x:/windows/assembly and then redeploy the solution to see if there is any change on the behaviour.
Also try to commit the changes before this (I'm sure you already tried it out)
Regards,
Pedro

Related

Change the "Make "New Folder" command available?" option with Sharepoint Client Object Model

I got a lot of sites with document libraries where the "Make "New Folder" command available" option is set to "no".
I would like to walk through these document libraries and change this to "yes".
How can I achieve this? After doing some search, I found that a lot of things can be done with the files in a document library, but did not find any example that shows how to change settings (advanced settings) of the library itself.
Thank you,
vm
Since you are looking for solution that utilizes CSOM API, the below example demonstrates how enable folders for document libraries:
using (var ctx = new ClientContext(webUri))
{
var result = ctx.LoadQuery(ctx.Web.Lists.Where(l => l.BaseType == BaseType.DocumentLibrary && !l.Hidden));
ctx.ExecuteQuery();
foreach (var list in result)
{
list.EnableFolderCreation = true;
list.Update();
}
ctx.ExecuteQuery();
}
VB.Net version
Using context As Microsoft.SharePoint.Client.ClientContext = New Microsoft.SharePoint.Client.ClientContext(webUri)
Dim qry = From l In context.Web.Lists
Where (CInt(l.BaseType) = 1) AndAlso Not l.Hidden
Select l
Dim result As IEnumerable(Of Microsoft.SharePoint.Client.List) = context.LoadQuery(qry)
context.ExecuteQuery()
Dim list As Microsoft.SharePoint.Client.List
For Each list In result
list.EnableFolderCreation = True
list.Update()
Next
context.ExecuteQuery()
End Using
Using powershell.
$list.EnableFolderCreation = $true;
$list.update();
put this inside a for loop that iterates through the lists/sites/webs of your farm. something like:
$sc = http://myweb.com/mysitecollection
$spsite = Get-SPsite $sc
foreach ($web in $spsite.AllWebs)
{
foreach ($list in $web.Lists)
{
$list.EnableFolderCreation = $true;
$list.update();
}
}
$spsite.dispose()
if you would rather do this using the client object model, throw this into a console app. (make sure you reference Microsoft.SharePoint.dll)
using System;
using Microsoft.SharePoint;
namespace SharepointModifier
{
class FolderEnabler
{
static void Main(string[] args)
{
string sitecollectionaddress = "Http://mysitecollection.com/";
using (SPSite mysites = new SPSite(sitecollectionaddress))
{
foreach (SPWeb web in mysites.AllWebs)
{
foreach (SPList list in web.Lists)
{
list.EnableFolderCreation = true;
//Make any other changes to list properties here
list.Update();
Console.WriteLine(list.Title + " Has been updated.");
}
}
}
}
}
}

Access is denied Exception when updating List items using SPUserToken

I try to do some actions on Sharepoint 2010 list using an unlowed user( having only read right) and i got Access denied exception.
Is it possible to do it whithout changing the user rights.
please find below my code:
public void StartWorkFlow(int itemID, int wfTemplateID, String entityName, String userShortname)
{
SPSecurity.RunWithElevatedPrivileges(delegate()
{
SPUser spUser;
using (site = new SPSite(siteUrl))
{
using (web = site.RootWeb)
{
spUser = web.EnsureUser(userShortname);
}
}
using (site = new SPSite(siteUrl, spUser.UserToken))
{
using (web = site.AllWebs["WPrs"])
{
list = web.Lists["Workflow Template"];
SPListItem item = list.Items.GetItemById(wfTemplateID);
SPList processList = web.Lists["List Process " + item["Template_x0020_Name"]];
SPListItem newInstance = processList.Items.Add();
newInstance["Template_x0020_Name"] = item["Template_x0020_Name"];
newInstance["Template_x0020_Description"] = item["Template_x0020_Description"];
newInstance["Date_x0020_De_x0020_Publication"] = item["Date_x0020_De_x0020_Publication"];
newInstance["Item_x0020_Id"] = itemID;
newInstance["Item_x0020_Extradata"] = entityName.ToLower() + "||Parameter||" + "";
newInstance["CTName"] = Utility.GetInstance().GetSuperItemNameBySubItemName(entityName);
web.AllowUnsafeUpdates = true;
newInstance.Update();
web.AllowUnsafeUpdates = false;
}
}
});
}
Thank you in advance.
To be able to use site.AllWebs the user must have Full Control to the site. Instead of using AllWebs try to get the sub sites using the following code -
SPWebCollection subwebs = CurrentSite.OpenWeb().GetSubwebsForCurrentUser();
http://msdn.microsoft.com/en-us/library/microsoft.sharepoint.spweb.getsubwebsforcurrentuser%28v=office.12%29.aspx
http://social.msdn.microsoft.com/Forums/sharepoint/en-US/e7ff284f-fe4b-42fb-8b21-a475e331a18c/access-denied-for-user-with-contribute-rights?forum=sharepointdevelopmentlegacy
Also you would not be able to update a listitem with read only rights.
If the only requirement is to set up the Created By/Modified By field - you should be able to overwrite default value by using SystemUpdate instead of Update. But still you need to run this RunWithElevatedPrivileges mode instead of UserToken
Although I'm not sure what will happen if have any other dependent actions after this update (event receivers or workflows) i'm not sure what context it will use (i.e. if SharePoint internally will use current SPWeb.CurrentUser object.

Access denied error while creating SPAlert programatically

We are using sharepoint 2007
We have created custom page for programatically creating alert.
The issue which we are facing is, If logged in user is Site Collection Administrators then only email is getting triggered.
The users other than Site Collection Administrators who has Full control or contribute access to the site they are getting Access Denied error.
We tried using SPSecurity.RunWithElevatedPrivileges but in that case also Access Denied error is getting.
For below code we are not getting Access Denied error but in this case email is not getting triggered,
SPSecurity.RunWithElevatedPrivileges(delegate()
{
Guid siteId = SPContext.Current.Site.ID;
Guid webId = SPContext.Current.Web.ID;
using (SPSite oSite = new SPSite(siteId))
{
using (SPWeb oWeb = oSite.OpenWeb(webId))
{
oWeb.AllowUnsafeUpdates = true;
SPUser oUser = oWeb.CurrentUser;
SPUser user = oWeb.EnsureUser(oUser.ToString());
SPList oList = oWeb.Lists[strLibraryName];
SPAlert oAlert = user.Alerts.Add();
oAlert.Filter ="<Eq><FieldRef Name="+strCol+"><Value type='Text'>" + strColValue + "</Value></Eq>";
oAlert.Title = "test alert";
oAlert.AlertType = SPAlertType.List;
oAlert.EventType = SPEventType.All;
oAlert.List = oList;
oAlert.AlertFrequency = SPAlertFrequency.Immediate;
oAlert.AlwaysNotify = true;
oAlert.Update(true);
}
}
});
Please let me know what is solution for this or how we can add/remove user to Site Collection Administrators programatically at run time
Move the declaration and assignment up above the using statements. I think an alert was being created successfully, but it was for the wrong account and therefore you didn't receive an email. If all this is inside an event receiver, you can use this line to get the actual user:
SPUser user = oWeb.Users.GetByID(properties.CurrentUserId);
The problem was with EnsureUser() method hence removing it and posting the working code below..
SPSecurity.RunWithElevatedPrivileges(delegate()
{
Guid siteId = SPContext.Current.Site.ID;
Guid webId = SPContext.Current.Web.ID;
using (SPSite oSite = new SPSite(siteId))
{
using (SPWeb oWeb = oSite.OpenWeb(webId))
{
oWeb.AllowUnsafeUpdates = true;
SPUser oUser = oWeb.CurrentUser;
SPList oList = oWeb.Lists[strLibraryName];
SPAlert oAlert = oUser.Alerts.Add();
oAlert.Filter ="<Eq><FieldRef Name="+strCol+"><Value type='Text'>" + strColValue + "</Value></Eq>";
oAlert.Title = "test alert";
oAlert.AlertType = SPAlertType.List;
oAlert.EventType = SPEventType.All;
oAlert.List = oList;
oAlert.AlertFrequency = SPAlertFrequency.Immediate;
oAlert.AlwaysNotify = true;
oAlert.Update(true);
}
}
});

How to add and remove group programmativally from list permissions in sharepoint 2010?

I have the following code to add a group with a permission level to a sharepoint list
SPGroup Contribute = web.SiteGroups["Staff"];
SPRoleDefinition ContributeDefinition = web.RoleDefinitions["Read"];
SPRoleAssignment ContributeRoleAssignment = new SPRoleAssignment(Contribute);
ContributeRoleAssignment.RoleDefinitionBindings.Add(ContributeDefinition);
list.RoleAssignments.Add(ContributeRoleAssignment);
which adds the group, but how would I do it if I want to revoke the permission to the list for this group?
thanks in advance
If you need to remove whole role assgnment you can do:
SPUser user = ...;
list.RoleAssignments.Remove(user);
If you need to revoke some definition binding you can do:
SPUser user = ...;
list.RoleAssignments.GetAssignmentByPrincipal(user).RoleDefinitionBindings.Remove(..);
If that is not you want, please describe in more details.
UPDATE:
Here is the sample code which I've tested and it works. It will remove Contribute role and add Read role to target group. Please note, that I have non-english Sharepoint version, so ensure the names of roles.
static void Main(string[] args)
{
using (SPSite site = new SPSite("site_url"))
{
using (SPWeb web = site.OpenWeb())
{
SPList list = web.GetList(web.Url + "/" + "list_url");
SPGroup group = web.SiteGroups["target_group_name"];
SPRoleDefinition contributeDef = web.RoleDefinitions["Contribute"];
SPRoleDefinition readDef = web.RoleDefinitions["Read"];
SPRoleAssignment contributeRole = new SPRoleAssignment(group);
contributeRole.RoleDefinitionBindings.Add(contributeDef);
if (!list.HasUniqueRoleAssignments) // required to make role change
list.BreakRoleInheritance(true);
var assignmentForGroup = list.RoleAssignments.GetAssignmentByPrincipal(group);
assignmentForGroup.RoleDefinitionBindings.Remove(contributeDef);
assignmentForGroup.RoleDefinitionBindings.Add(readDef);
assignmentForGroup.Update();
}
}
}

Is it possible to allow users of a SharePoint blog to comment, but not create posts?

By exploring the permissions, there seems to be no distinction between a comment and a blog post.
I can set users as contributers which allows them to comment and means their posts require apporval. But I would like to stop them from being able to create a post even as draft.
Many thanks
I've cracked it!
On the main page there is an option to manage posts. Within that page there is an option to set permissions. Perfect.
A blog within a My Site is created using the My Site Blogs feature (863DA2AC-3873-4930-8498-752886210911). Inside the feature receiver is the following code that modifies the Comments list by setting edit access to only their own, breaks role inheritance, and grants contribute access to the Visitors group:
int num2;
SPList list3;
SPRoleDefinition byType;
SPRoleAssignment assignment;
UserProfileManager manager;
string str2;
string[] strArray2;
int num3;
string str = parent.RootWeb.AllProperties["vti_associatevisitorgroup"] as string;
SPGroup principal = null;
if (!string.IsNullOrEmpty(str))
{
num2 = int.Parse(str, CultureInfo.InvariantCulture);
principal = parent.RootWeb.SiteGroups.GetByID(num2);
}
list3 = GetList(web, SPListTemplateType.Comments);
list3.WriteSecurity = 2;
byType = web.RoleDefinitions.GetByType(SPRoleType.Contributor);
list3.BreakRoleInheritance(true);
web.AllowUnsafeUpdates = true;
if (principal == null)
{
manager = new UserProfileManager(ServerContext.GetContext(parent));
strArray2 = manager.PersonalSiteReaders.Split(new char[] { ',', ';' }, StringSplitOptions.RemoveEmptyEntries);
num3 = 0;
while (num3 < strArray2.Length)
{
str2 = strArray2[num3];
try
{
SPRoleAssignment roleAssignment = new SPRoleAssignment(str2, null, null, null);
roleAssignment.RoleDefinitionBindings.Add(byType);
list3.RoleAssignments.Add(roleAssignment);
}
catch (Exception exception)
{
ULS.SendTraceTag(ULSTagID.tag_7otc, ULSCat.msoulscat_SPS_UserProfiles, ULSTraceLevel.Medium, "Ignored one invalid user for the personal site reader (%s): %s.", new object[] { str2, exception });
}
num3++;
}
}
else
{
assignment = new SPRoleAssignment(principal);
assignment.RoleDefinitionBindings.Add(byType);
list3.RoleAssignments.Add(assignment);
}
list3.Update();
ULS.SendTraceTag(ULSTagID.tag_6y3j, ULSCat.msoulscat_SPS_UserProfiles, ULSTraceLevel.Medium, "Successfully activated MySite Blog Feature");
I would probably write a custom Feature Receiver that does something similar. However, if I only needed a single blog in the site collection and a URL of Blog was acceptable, I might try creating the blog by activating the My Site Blogs feature.

Resources