SharePoint Config

Ari Bakker's thoughts on customising and configuring SharePoint

Returning approved SharePoint list items from a console application

with 2 comments

If you are using the SharePoint object model to return list items, the items are security trimmed based on the rights of the user running the code. In most cases this is great, you don’t have to do any manipulation of the items returned from CAML queries to ensure users only see what they have access to.

If you are running object model code from within a console/windows application, however, the code must be running with some serious permissions including being a site collection administrator. I recently had a situation where I wanted to return only approved items in queries from lists within the site (i.e. only items an anonymous user would see). Thankfully it wasn’t too difficult, but there are a couple of steps to get this going.

The first is to ensure permissions on the lists are set appropriately. This can be done by navigating to Settings > List Settings > Versioning Settings from a list. You will need to ensure content approval is on, and draft item security is restricted to either editors or approvers. This will ensure draft versions do not appear in public views.

The second thing to do is to impersonate a user with reduced privileges while you run the object model queries from within the console/windows application. An example is given below:

Impersonation code:

public class Impersonation

{

public Impersonation()

{

}

private const int LOGON32_LOGON_INTERACTIVE = 2;

private const int LOGON32_PROVIDER_DEFAULT = 0;

WindowsImpersonationContext impersonationContext;

[DllImport(“advapi32.dll”)]

private static extern int LogonUserA(String lpszUserName,

String lpszDomain,

String lpszPassword,

int dwLogonType,

int dwLogonProvider,

ref IntPtr phToken);

[DllImport(“advapi32.dll”, CharSet = CharSet.Auto, SetLastError = true)]

private static extern int DuplicateToken(IntPtr hToken,

int impersonationLevel,

ref IntPtr hNewToken);

[DllImport(“advapi32.dll”, CharSet = CharSet.Auto, SetLastError = true)]

private static extern bool RevertToSelf();

[DllImport(“kernel32.dll”, CharSet = CharSet.Auto)]

private static extern bool CloseHandle(IntPtr handle);

/// impersonateValidUser

public bool impersonateValidUser(String userName, String domain, String password)

{

WindowsIdentity tempWindowsIdentity;

IntPtr token = IntPtr.Zero;

IntPtr tokenDuplicate = IntPtr.Zero;

if (RevertToSelf())

{

if (LogonUserA(userName, domain, password, LOGON32_LOGON_INTERACTIVE, LOGON32_PROVIDER_DEFAULT, ref token) != 0)

{

if (DuplicateToken(token, 2, ref tokenDuplicate) != 0)

{

tempWindowsIdentity = new WindowsIdentity(tokenDuplicate);

impersonationContext = tempWindowsIdentity.Impersonate();

if (impersonationContext != null)

{

CloseHandle(token);

CloseHandle(tokenDuplicate);

return true;

}

}

}

}

if (token != IntPtr.Zero)

{

CloseHandle(token);

}

if (tokenDuplicate != IntPtr.Zero)

{

CloseHandle(tokenDuplicate);

}

return false;

}

/// impersonates the reward search user

public bool impersonateSearchUser()

{

Dictionary<string, string> accountSettings = LoadConfiguration(“SearchUser”);

// impersonate user

return impersonateValidUser(

accountSettings[“Username”],

accountSettings[“Domain”],

accountSettings[“Password”]);

}

/// Loads a connection string as key/value pairs

private Dictionary<string, string> LoadConfiguration(string connectionString)

{

string accountString = ConfigurationManager.ConnectionStrings[connectionString].ConnectionString;

Dictionary<string, string> config = new Dictionary<string, string>();

foreach (string setting in accountString.Split(“;”.ToCharArray()))

{

string[] pairs = setting.Split(“=”.ToCharArray());

config.Add(pairs[0], pairs[1]);

}

return config;

}

/// undoImpersonation

public void undoImpersonation()

{

impersonationContext.Undo();

}

}

Then you can use the impersonation code to return list items as the specified user as shown below:

SPListItemCollection items;

Impersonation impersonationContext = new Impersonation();

impersonationContext.impersonateDocsShareUser();

using (SPSite site = new SPSite(“http://moss.co.nz”))

{

using (SPWeb web = site.OpenWeb())

{

SPList list = web.Lists[“Category”];

SPQuery q = new SPQuery();

q.ViewFields = “”;

items = list.GetItems(q);

}

}

As the impersonation account details are stored in a configuration file you can easily encrypt these using RSA.

Post to Twitter Post to Delicious Post to Digg Post to Reddit Post to StumbleUpon

Written by Ari Bakker

November 8th, 2007 at 12:41 pm

Posted in Development,Lists,MOSS

2 Responses to 'Returning approved SharePoint list items from a console application'

Subscribe to comments with RSS or TrackBack to 'Returning approved SharePoint list items from a console application'.

  1. Becky,

    I believe he's using impersonation to replicate the security trimming that you get by default with the web UI.

    I've been working on this via web services and I just throw this in my CAML query — no impersonation necessary:

    <Where>
    <Eq>
    <FieldRef Name="_ModerationStatus" />
    <Value Type="ModStat">Approved</Value>
    </Eq>
    </Where>

    Corey Cole

    8 Nov 07 at 4:31 pm

  2. If you run the console application off of Windows Scheduler as the Site Administrator, then you don't need to use impersonation. I guess it all depends on what you want to do with the console app.

    Becky Isserman

    8 Nov 07 at 2:35 pm

Leave a Reply

*