Take the 2-minute tour ×
SharePoint Stack Exchange is a question and answer site for SharePoint enthusiasts. It's 100% free, no registration required.

* *Clarification. Application == Site Definition. Direct Database access is out the window ** I've created an application for SharePoint that utilizes some new approaches to coding List Access. I've structured things in a way that allows me to control data interaction in a precise manner.

For example, I have a class called Post, which has some typical metadata like Title, Summary, etc...

Inside Post is a static method called NewPost which returns a pre-formatted SPListItem for use in creating new posts.

public static SPListItem NewPost(string Title,string Summary)
{
   Posts = CoreLists.Posts();
   var item = Posts.AddItem();
   var item["Alias"] = SPContext.Current.Web.CurrentUser.LoginName;
   return item;
}

You'll notice I'm getting the SPList through a helper class called CoreLists

public static class CoreLists
{
   public static SPList Posts()
   {
      return SPContext.Current.Web.GetList(SPContext.Current.Web.ServerRelativeUrl + "/lists/Posts");
   }
}

This makes for some nice clean data methods. What I'm running in to, is that I cannot find a decent way to call these methods with SPSecurity.RunWithElevatedPrivileges

SPSecurity.RunWithElevatedPrivileges cannot function with a return block, so when I try to create a new list item, it fails every time.

I'm doing this because I'm making my lists hidden. I want people to only access them through the UI I'm creating. I want to further lock the system down from URL hacking by allowing only admins to create items, and use SecurityBits to lock down item editing only to the creators of list items.

Therefore, all List Items are created by System Account, and then they have a field called Alias which allows me to match the item to a user.

Do I need to rethink my entire Data Access Layer? Does the decision to restrict List Access conflict absolutely with the desire for a cleaner Data Access Layer?

share|improve this question
add comment

4 Answers 4

up vote 1 down vote accepted

You use SPContext.Current.Web inside the SPSecurity.RunWithElevatedPrivileges delegate?

That is not going to work. Getting stuff with SPContext gives you objects that has the context of the currently logged on user, not the elevated one. That means that if you create a new list entry using objects that comes from SPContext, they will be created in the security context of the user currently logged on, and not the elevated user you think is creating them.

If you want to create list entries using sharepoint\system, you need to open up new SPSite/SPWeb objects inside the SPSecurity.RunWithElevatedPrivileges delegate and work with those instead.

Try changing this:

   public static SPList Posts() 
   { 
      return SPContext.Current.Web.GetList(SPContext.Current.Web.ServerRelativeUrl + "/lists/Posts"); 
   } 

to this:

   public static SPList Posts() 
   { 
        using( var s = new SPSite(SPContext.Current.Site.ID)
        {
            using( var w = SPSite.OpenWeb(SPContext.Current.Web.ID)
            {
                 var postsList = w.Lists.TryGetList("Posts"); 
                 if( postsList != null )
                      return postsList;
                 else
                    /* do proper error handling */
            }
        }
    }

Now your posts.AddItem() should create list entries with the correctly elevated context.

Read more about privilege elevation on MSDN: http://msdn.microsoft.com/en-us/library/microsoft.sharepoint.spsecurity.runwithelevatedprivileges.aspx

share|improve this answer
1  
NEVER EVER do like this. First you should never return a SPList or SPListItem from a disposed SPWeb as almost any operation against the item needs to revitalize the SPWeb which you then will leak. Secondly you should NEVER expose an SharePoint item allocated inside RWEP to the outside as this has been reported to be the cause of corrupted content databases. –  Per Jakobsen Jul 6 '12 at 18:56
add comment

Do not use RWEP. You do not need it.

Hidden lists do not require special coding to access. If the current user has permissions to the list, then just access the hidden list as you would any other list.

If the current user does not have permissions to the list, and you wish to proxy the update via code, you should impersonate the System Account. Furthermore, you should not pass an object across security boundaries. I suggest creating data transfer object that you pass into your data layer.

share|improve this answer
    
It's not that I mistake hiding for restriction. Even if you set a list to high security permissions, certain users can still mess with them. Hiding the list from the UI just keeps curious people out. –  Wesley Jul 3 '12 at 3:38
add comment

Vedrans points re UI/Security are quite right - if you're rewriting the security system, you're working against the grain as it were. But you might still want to leverage the security (and other SharePoint benefits), so it's not completely mental to build an app on SharePoint.

For a more SharePoint based architecture - use a publishing site. This gives you:

  1. the standard sharepoint UI for lists etc. - this is the admin 'backstage' view.
  2. pages library with separate master page/UI - this is the 'application' interface.

Default (all authenticated users) get viewer access to the site. 'admin' users get contributer/explicit permissions to lists, whatever.

Punters can only access site data through custom web parts/code in the application interface.

share|improve this answer
add comment

Your whole concept is wrong.

If you are developing your own UI and security then why are you using SharePoint? Using SQL is much cleaner.

Every time you use SPSecurity.RunWithElevatedPrivileges in code Sharepoint security is compromised because you are allowing current user to act as SHAREPOINT\System and have access to everything.

Btw you can set 'creator' when running under SPSecurity.RunWithElevatedPrivileges

//First store current user
SPUser currentUser = SPContext.Current.Web.CurrentUser;

SPSecurity.RunWithElevatedPrivileges(delegate 
{
    using (SPSite elevatedSite = new SPSite(SPContext.Current.Site.Url))
    using (SPWeb targetWeb = elevatedSite.OpenWeb(webUrl))
    {
       //Code to get your item or to add a new one

       // Replace 'System Account' with current user
       item["Author"] = currentUser;
       item["Editor"] = currentUser;
       item.SystemUpdate();
    }
});

ADDITION:

To avoid any further misinterpretation: by using SQL I didn't meant SharePoint database but some other different SQL database. Why? Since you are using custom UI, custom security checks, your list are hidden (so users cannot use SP OOTB features like sorting, filtering etc.), search is also not an option -> I really don't see any advantage of using SharePoint as data storage.

share|improve this answer
    
As an application for SharePoint, I have no access to or control over the database. The application is a site definition, Lists are the only data storage I have. –  Wesley Jul 3 '12 at 0:10
    
Good point re setting the creator to the current user when running with elevated privileges. –  marcus.greasly Jul 3 '12 at 0:55
    
@Wesley - check my answer for some additional clarification. Btw I don't agree with down vote on fact that I don't approve your approach. In my answer I didn't write anything wrong. –  Vedran Rasol Jul 3 '12 at 7:28
add comment

Your Answer

 
discard

By posting your answer, you agree to the privacy policy and terms of service.

Not the answer you're looking for? Browse other questions tagged or ask your own question.