Access denied error while creating SPAlert programatically - sharepoint

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);
}
}
});

Related

Add/update item with users information Sharepoint Client C#

Using Microsoft.Sharepoint.CLient & .Runtime.dll ver.16.0.0.0
I have a Item list (Lost packages) with Tracking number(title),Description(currier),MailTo(Type: Person, Show Field: E-Mail)
I also have another list (buyers) of available User to pick up from
So from my C# client program I want to add or update an item from Lost packages and with the MailTo -Email- of an user. Right now I can only get the Name as String of the Author of a ListItem. How do I get the user information from a ListItem so I can change the MailTo to a specific user
public Package(ListItem _package) {
this.item = _package;
if (this.item != null) {
this.exist = true;
this.id = this.item["ID"].ToString();
this.trackNo = (String)this.item["Title"];
this.currier = (String)this.item["Description"];
this.status = (String)this.item["Status"];
FieldUserValue userAuthor = (FieldUserValue)this.item["Author"];
this.Owner = userAuthor.LookupValue.ToString();
Here is a sample code for your reference, just need to set the User Id to FieldUserValue class, then set to MailTo field:
ClientContext clientContext = new ClientContext("http://sp/sites/dev");
Web web = clientContext.Web;
Microsoft.SharePoint.Client.List spList = clientContext.Web.Lists.GetByTitle("JerryList4");
clientContext.Load(spList);
clientContext.ExecuteQuery();
ListItem item = spList.GetItemById(3);
clientContext.Load(item);
clientContext.ExecuteQuery();
FieldUserValue userValue = new FieldUserValue();
userValue.LookupId = 19; //set user Id here
item["MailTo"] = userValue;
item.Update();
clientContext.ExecuteQuery();
For the user id, you can get it from this Rest EndPoint:
http://siteurl/_api/web/siteusers?$select=Id,LoginName

How I can get all themes and set specific theme of SharePoint online

I have tried to get all themes of SharePoint online using
ClientObjectList themes = tenant.GetAllTenantThemes(); but failed.
I have tried this code but failed to get
using System.Security;
using Microsoft.SharePoint.Client;
using Microsoft.Online.SharePoint.TenantAdministration;
using Microsoft.Online.SharePoint.TenantManagement;
...
ClientContext ctx = new ClientContext("https://mysite-admin.sharepoint.com/");
var pwd = "mypassword";
var passWord = new SecureString();
foreach (char c in pwd.ToCharArray()) passWord.AppendChar(c);
ctx.Credentials = new SharePointOnlineCredentials("admin#mydomain.com", passWord);
Tenant tenant = new Tenant(ctx);
ClientObjectList<ThemeProperties> themes = tenant.GetAllTenantThemes();
Error is:
The collection has not been initialized. It has not been requested or the request has not been executed. It may need to be explicitly requested.
Use the code below to get all themes in tenant. Note: add ctx.load and ctx.ExecuteQuery methods.
string siteUrl = "https://tenant-admin.sharepoint.com";
string userName = "lz#tenant.onmicrosoft.com";
string password = "xxx";
var securePassword = new SecureString();
foreach (char c in password.ToCharArray()) securePassword.AppendChar(c);
using (ClientContext ctx = new ClientContext(siteUrl))
{
ctx.Credentials = new SharePointOnlineCredentials(userName, securePassword);
Tenant tenant = new Tenant(ctx);
ClientObjectList<ThemeProperties> themes = tenant.GetAllTenantThemes();
ctx.Load(themes);
ctx.ExecuteQuery();
foreach(ThemeProperties pres in themes)
{
Console.WriteLine(pres.Name);
}
}
We can also use Pnp PowerShell to achieve it.
Get-PnPTenantTheme
Add-PnPTenantTheme
Set Theme for a site using this.
tenant.SetWebTheme("Custom Black", "http://tenant.sharepoint.com/sites/TestModernTeamSite6");
ctx.ExecuteQueryRetry();

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.

Sharepoint 2013 users which are programmatically added using Client Object Model cannot contribute to document library

I have a problem with user permission of users which are programmatically added to Sharepoint 2013 group using Client Object Model. The web application allows anonymous, but I also have a document library "Teacher Documents" with contribute permission only to a certain group (let's say "Teachers"), and I have added the user to the site's default member too (let's say "School Members"). The code works fine and the user was successfully added to both groups.
While it did look OK and the username was listed as the member of the groups, they still cannot contribute. When I checked, they do have the anonymous access on the document library but not the Contribute permission. Here's my code:
public static string AddUserToGroup(string siteURL, string groupName, string userName, string name, string email, NetworkCredential impersonateCredential)
{
try
{
ClientContext context = new ClientContext(siteURL);
context.Credentials = impersonateCredential;
Group oGroup = null;
oGroup = context.Web.SiteGroups.GetByName(groupName);
context.Load(oGroup);
bool groupExists = false;
try
{
context.ExecuteQuery();
groupExists = true;
}
catch { }
if (groupExists)
{
UserCreationInformation userCreationInfo = new UserCreationInformation();
userCreationInfo.Email = email;
userCreationInfo.LoginName = userName;
userCreationInfo.Title = name;
bool userExists = false;
try
{
User checkUser = oGroup.Users.GetByLoginName(userName);
context.Load(checkUser);
context.ExecuteQuery();
userExists = true;
}
catch { }
if (!userExists)
{
User oUser = oGroup.Users.Add(userCreationInfo);
context.ExecuteQuery();
}
}
else
{
return "No associated group assigned";
}
return "Member " + userName + " has been added to group.";
}
catch (Exception ex)
{
return ex.Message.ToString();
}
}
And here's how I call it:
string siteURL = "http://spfe01.gilang.com/";
string username = "spfe01\\budi.utomo";
string name = "Budi Utomo";
string email = "budi.utomo#spfe01.gilang.com";
NetworkCredential impersonateCredential = new NetworkCredential("username", "password", "spfe01");
AddUserToGroup(siteURL, "Teachers", username, name, email, impersonateCredential));
(You can test it on a console application)
It worked, the user was added to "Teachers", but no permission on "Teacher Documents" document library. Adding the user to the admin group "School Owners" with full control on the site did not work either.
EDIT:
In my case, I have added the group manually to the document library, and users that are added manually to the group are granted permissions and allowed to contribute. By manually I mean using the standard "Permissions" function of the Sharepoint on the web browser.
Actually, did you break the inheritance?
Most probably, the folder and file inherit the permission of the main folder
Here is my code:
caml = new Microsoft.SharePoint.Client.CamlQuery();
caml.ViewXml = #"Caml to get the file";
items = objList.GetItems(caml);
clientContext.Load(items);
clientContext.Credentials = new NetworkCredential("LoginID", "LoginPW", "LoginDomain");
clientContext.ExecuteQuery();
item = items[0];
item.BreakRoleInheritance(true, true);
clientContext.ExecuteQuery();

Change permission level for groups programmatically in SharePoint 2010?

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

Resources