Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

How can "Modified By" be changed when using RunWithElevatedPrivileges?

We have a web part that uploads a document to a document library. The user uploading the document may not have access to the destination location, so the code adding the file executes within a RunWithElevatedPrivileges block. This means the "Modified By" field is always set to System Account. Here is the code:

SPSecurity.RunWithElevatedPrivileges(
    delegate
    {
        using (SPSite elevatedSite = new SPSite(SPContext.Current.Site.Url))
        using (SPWeb targetWeb = elevatedSite.OpenWeb(webUrl))
        {
            targetWeb.AllowUnsafeUpdates = true;
            SPFile newFile = files.Add(filename, file);
            SPListItem item = newFile.Item;

            // TODO: Insert code to set Modified By

            item.SystemUpdate();
        }
    }
}

The "Modified By" field needs to be set to the name of the current user (at the TODO line above), but none of the following attempts have worked:

item["Modified By"] = SPContext.Current.Web.CurrentUser;

item["Author"] = SPContext.Current.Web.CurrentUser;

item["Modified By"] = new SPFieldUserValue(
SPContext.Current.Web, SPContext.Current.Web.CurrentUser.ID,
SPContext.Current.Web.CurrentUser.Name);

item["Author"] = new SPFieldUserValue(
SPContext.Current.Web, SPContext.Current.Web.CurrentUser.ID,
SPContext.Current.Web.CurrentUser.Name);

Does anyone know of a solution that allows the "Modified By" value to be changed?

like image 403
Alex Angas Avatar asked Apr 22 '09 10:04

Alex Angas


3 Answers

I did some more testing...

item["Editor"] = SPContext.Current.Web.CurrentUser;
item["Author"] = SPContext.Current.Web.CurrentUser;
item.SystemUpdate();

Created By is set to the current user but Modified By is set to System Account.

item["Editor"] = SPContext.Current.Web.CurrentUser;
item["Author"] = SPContext.Current.Web.CurrentUser;
item.Update();

Both Created By and Modified By are set to the current user.

The problem was using SPListItem.SystemUpdate() which does the exact opposite of what the API documentation states, at least when running with elevated privileges.

Note: SPContext.Current.Web.CurrentUser does pick up the current user and not the system account when running within SPSecurity.RunWithElevatedPrivileges. (Whether it should be used like this is another question.)

like image 184
Alex Angas Avatar answered Nov 01 '22 16:11

Alex Angas


One way to solve this is by storing the currently logged user in memory before elevating permissions. Later in the update request, replace the 'System account' with with your variable.

See below:

// Keep a reference of the Logged in user in memory
SPUser currentUser = SPContext.Current.Web.CurrentUser;

SPSecurity.RunWithElevatedPrivileges(
delegate
{
    using (SPSite elevatedSite = new SPSite(SPContext.Current.Site.Url))
    using (SPWeb targetWeb = elevatedSite.OpenWeb(webUrl))
    {
        targetWeb.AllowUnsafeUpdates = true;
        SPFile newFile = files.Add(filename, file);
        SPListItem item = newFile.Item;

        // Replace 'System Account' with current user
        item["Author"] = currentUser;
        item["Modified By"] = currentUser;

        item.SystemUpdate();
    }
});

I hope this helps.

like image 41
Henrique Zacchi Avatar answered Nov 01 '22 17:11

Henrique Zacchi


Do as (Henrique Zacchi) writes, but build a wrapper extension method that takes in SPUser as an additional param. Then use it.

like image 1
user866524 Avatar answered Nov 01 '22 15:11

user866524