In Depth: SharePoint Security Configuration – Part 1

The source code for this article is available on CodePlex

Introduction

If you’ve been developing applications for SharePoint for any length of time you’ll undoubtedly have come into contact with the security model. Based on the asp.net provider model, SharePoint itself does not authenticate users, it merely provides authorisation. That is to say that SharePoint does not verify that users are who they claim to be, it simply makes use of the users identity to determine what resources should be available to the user. Of course this does not mean that user identities are not verified, just that this job is left to the underlying asp.net platform.

By making use of the asp.net provider model, SharePoint frees up system designers and architects to choose whichever authentication mechanism best meets their requirements. For example, an intranet application will most likely make use of Active Directory as a user store, providing authentication via Kerberos or NTLM, whereas an extranet application or a public facing web application may make use of forms based authentication to authenticate users against a custom database. The real power of the provider model is in its extensibility, it’s possible to create a provider to allow users to authenticate against practically any user data store.

Since SharePoint provides authorisation services only, configuring custom applications is simply a case of defining the users and groups that should have access to a particular resource. Before we delve into the code that’s required to programmatically configure access control, it’s worthwhile having an in depth look at how SharePoint implements security.

You will no doubt be familiar with the notion of users and groups and how these two objects are used together to control access to resources within an application or on a corporate network. A user typically represents a single individual or process whereas groups contain many users and are often used to grant permissions to a collection of users. It’ll come as no surprise that SharePoint extends this metaphor for controlling access to its objects.

However, there’s one thing to be aware of: SharePoint groups are not the same as Active Directory Groups and SharePoint Users are not necessarily the same as Active Directory users.

Both Active Directly Users and Active Directory groups are represented by SPUser objects in the SharePoint object model. The reason for this goes back to the asp.net provider model, since the actual implementation of the authentication and authorisation mechanism is abstracted, it’s necessary to have an abstract notion of the user that should be granted permissions on a resource. This is done via the abstract SPPrincipal object and it’s descendants, SPUser and SPGroup in SharePoint. The benefit of this abstraction is that SPUser object can represent Active Directory users or groups or custom users authenticated via forms authentication and by extension the SPGroup object which represents a collection of SPUser object can contain a heterogeneous collection of SPUser objects, allowing permissions to be defined regardless of the authentication mechanism.

The Nuts and Bolts

Now that we’ve covered how users and user groups are represented in the SharePoint security object model, the next thing to consider is access control. Many of the objects in a SharePoint application can have access control lists (ACLs) attached to them. An ACL is a binary data structure that contains details of the SPPrincipal objects that have permissions defined for the object together with information on the permissions. Each principal/permission mapping is represented by an SPRoleAssignment object. You’ll notice from the name, that a SPRoleAssignment doesn’t actually map permissions to principals directly, in fact there’s a further level of grouping that’s represented by the SPRoleDefinition object. An SPRoleDefintion object is a collection of bits that represent the status of a number of pre-defined permission flags. The individual flags are listed in the SPBasePermissions enumeration. While actual permissions are hardcoded into the SharePoint platform, SPRoleDefinitions are user-defined and the system-defined permissions are fine-grained enough to allow users to create roles that encompass practically any security requirement.

SPRoleDefintions are stored at the SPWeb level and are accessible through the Roles property of the SPWeb object.

The three main objects that can be secured in SharePoint implement the ISecurableObject interface. These objects are:

  • SPWeb, which represents an entire web site. Permissions defined at this level are inherited by all lists contained within the web unless inheritance has been explicitly turned off. Sub-web’s also inherit permissions defined here unless inheritance has been turned off.
  • SPList, which represents all lists and document libraries within a web site. Permissions defined at this level automatically apply to all items contained within the list or library unless inheritance has been explicitly turned off.
  • SPListItem, which represents the lowest level of access control available in SharePoint. Permissions defined at this level apply to a single document or data item.

You’ll no doubt be aware that these are some of the most fundamental objects used when building applications with SharePoint, so much so that many of the other objects that are commonly used either inherit from these types or have methods that can return an associated instance of these types. For example the SPFolder object has a ParentListId property that can be used to get a reference to the containing list, or the SPFile object has an Item property that returns an SPListItem object that represents the file. Since it is our aim to create a utility that will allow declarative configuration of security in SharePoint, it is vital that we can manage ACL’s on all objects that implement the ISecurableObject interface, particularly those described above.

So to recap, the key objects and interfaces that will be required for our configuration utility are:

  • SPPrincipal – an abstract class that provides the base for SPUser and SPGroup. This class allows permissions to be set based on group membership or on a per-user basis (subject to the caveat that an SPUser isn’t necessarily only a single user)
  • SPUser – represents a discrete security entity in SharePoint. This can be a user, a local user group or an Active Directory group.
  • SPGroup – represents a group of SPUser objects
  • SPRoleAssignment – represents an entry in the ACL for a particular role
  • SPRoleDefintion – represents the combination of permissions that should be applied for a particular user on a particular resource
  • SPBasePermission – an enumeration that lists the system level permissions that can be used when creating SPRoleDefinitions
  • ISecurableObject – represents a resource that can be secured via an access control list

Figure 1.1 shows the various objects and how they relate to each other.

image

The Design

Now that we have a clear understanding of the SharePoint security object model, let’s produce a class diagram that shows how our utility will hang together.

Figure 1.2 shows the classes that comprise our utility and the relationships between them.

image

As shown in figure 1.2, our SecureObject class implements most of the functionality of our utility and in fact this object directly maps to an object implementing ISecurableObject in the SharePoint security object model. SecureObject has been implemented as an abstract class with concrete classes Web, List, and ListItem derived from it. This pattern allows additional functionality to be added for each type of object. For example the Web object is the container for all SPRoleDefinition objects as well as being a securable object in its own right, so our pattern allows us to add additional code to manage role definitions as well as making use of the base implementation for managing security on the object itself.

Another thing worth mentioning is that all objects derive from the DeployableItem class. In the previous section we discussed the need to have different configurations for development and production environments. The DeployableItem base class adds a DeploymentMode property to each object in our model. In practical terms this equates to an additional optional attribute on each one of the objects in our configuration file that can be used to determine whether the item will be deployed by our utility.

From our class diagram we can derive a schema that we’ll use when creating configuration files for our utility:

<?xml version="1.0" encoding="utf-8"?>
<xs:schema attributeFormDefault="unqualified" elementFormDefault="qualified" xmlns:xs="http://www.w3.org/2001/XMLSchema">
  <xs:element name="Web">
    <xs:complexType>
      <xs:complexContent>
        <xs:extension base="SecurableObject">
          <xs:sequence>
            <xs:element name="Roles" type="RoleDefinitions" maxOccurs="1" minOccurs="0"/>
          </xs:sequence>
        </xs:extension>
      </xs:complexContent>
    </xs:complexType>
  </xs:element>
  <xs:complexType name="RoleAssignment" id="RoleAssignment">
    <xs:complexContent>
      <xs:extension base="DeployableItem">
        <xs:sequence>
          <xs:element minOccurs="1" maxOccurs="unbounded" name="Role" type="Role"/>
        </xs:sequence>
        <xs:attribute name="loginname" type="xs:string" use="optional" />
        <xs:attribute name="email" type="xs:string" use="optional"/>
        <xs:attribute name="name" type="xs:string" use="required" />
        <xs:attribute name="owner" type="xs:string" use="optional" />
        <xs:attribute name="defaultuser" type="xs:string" use="optional" />
        <xs:attribute name="notes" type="xs:string" use="optional" />
      </xs:extension>
    </xs:complexContent>
  </xs:complexType>
  <xs:complexType name="Role">
    <xs:complexContent>
      <xs:extension base="DeployableItem">
        <xs:attribute name="name" type="xs:string" use="required" />
      </xs:extension>
    </xs:complexContent>
  </xs:complexType>
  <xs:complexType name="RoleDefinitions">
    <xs:complexContent>
      <xs:extension base="DeployableItem">
        <xs:sequence>
          <xs:element minOccurs="1" maxOccurs="unbounded" name="RoleDefinition">
            <xs:complexType>
              <xs:attribute name="name" type="xs:string" use="required" />
              <xs:attribute name="description" type="xs:string" use="optional" />
              <xs:attribute name="basepermissions" type="xs:string" use="required" />
            </xs:complexType>
          </xs:element>
        </xs:sequence>
      </xs:extension>
    </xs:complexContent>
  </xs:complexType>
  <xs:complexType name="SecurableObject">
    <xs:complexContent>
      <xs:extension base="DeployableItem">
        <xs:sequence>
          <xs:element name="RoleAssignments" minOccurs="0" maxOccurs="1">
            <xs:complexType>
              <xs:choice>
                <xs:element name="RoleAssignment" type="RoleAssignment" minOccurs="1" maxOccurs="unbounded"/>
              </xs:choice>
            </xs:complexType>
          </xs:element>
          <xs:choice maxOccurs="unbounded" minOccurs="0">
            <xs:element name="List" type="SecurableObject"/>
            <xs:element name="ListItem" type="SecurableObject"/>
            <xs:element name="Web" type="SecurableObject"/>
          </xs:choice>
        </xs:sequence>
        <xs:attribute name="url" type="xs:string" use="required" />
        <xs:attribute name="clearexisting" type="xs:boolean" use="optional" default="true" />
        <xs:attribute name="inheritpermissions" type="xs:boolean" use="optional" default="false" />
      </xs:extension>
    </xs:complexContent>
  </xs:complexType>
  <xs:complexType name="DeployableItem" abstract="true">
    <xs:attribute name="deploymentmode" type="DeploymentMode" use="optional" default="Both" />
  </xs:complexType>
  <xs:simpleType name="DeploymentMode">
    <xs:restriction base="xs:string">
      <xs:enumeration value="Both"/>
      <xs:enumeration value="DebugOnly"/>
      <xs:enumeration value="NonDebugOnly"/>
    </xs:restriction>
  </xs:simpleType>
</xs:schema>

Using this schema a sample configuration file might look like this:

<?xml version="1.0" encoding="utf-8" ?>
<Web url="http://baseimage" inheritpermissions="true">
  <RoleAssignments>
    <RoleAssignment loginname="baseimage\user1"
email="user1@contoso.com" name="myuser" notes="mynotes">
      <Role name="myrole"/>
      <Role name="myrole2"/>
    </RoleAssignment>
    <RoleAssignment loginname="baseimage\user2" email="test2@contoso.com" name="myuser2" notes="mynotes2">
      <Role name="myrole"/>
      <Role name="myrole2"/>
    </RoleAssignment>
    <RoleAssignment email="test2@contoso.com" name="mygroup" notes="mynotes2">
      <Role name="myrole"/>
      <Role name="myrole2"/>
    </RoleAssignment>
  </RoleAssignments>
  <Web url="http://BaseImage/MySubSite" inheritpermissions="false" deploymentmode="NonDebugOnly">
    <List url="http://baseimage/MySubSite/Lists/Tasks" clearexisting="true" inheritpermissions="false">
    </List>
  </Web>
  <List url="http://baseimage/Lists/Tasks" clearexisting="true" inheritpermissions="false">
  </List>
  <ListItem url="http://baseimage/Shared%20Documents/This%20is%20my%20test%20document.docx" clearexisting="true" inheritpermissions="false"/>
  <Roles>
    <RoleDefinition name="myrole" basepermissions="ViewListItems EditListItems ApproveItems Open"/>
    <RoleDefinition name="myrole2" basepermissions="ViewListItems EditListItems ApproveItems Open ViewPages ViewVersions ViewFormPages"/>
  </Roles>
</Web>
 

The Code

Now that we’ve clarified what our parser needs to do and what data we’ll have to work with, we’re ready to make a start on writing some code. Follow these steps to create a project to house our utility:

Step 1: Create a blank project

In Visual Studio 2008, Select File > New Project. In the dialog that appears select Windows > Class Library. Call the project SecurityParser.

Figure 1.3 shows the New Project dialog

SecurityFig3

When the project has been created, delete the Class1.cs file that is added automatically. Add a reference to “Windows SharePoint Services” by right-clicking on the References node then selecting “Add Reference”.

Step 2: Setup code signing for the project

Right-click on the SecurityParser node in Solution Explorer, select Properties. In the Properties page, select the Signing tab. Check the ‘Sign the assembly’ checkbox and in the ‘Choose a string name key file’ drop down, select “<New..>”. In the dialog that pops up enter ‘Key’ as the key file name and uncheck the “Protect my key with a password” checkbox.

Save the project to apply the changes. (Ctrl-Shift-S)

Step 3: Create files for each object

Right-click on the SecurityParser node, select Add > Class. In the “Add New Item” dialog that appears, name the file DeployableItem.cs.

Repeat this process creating files named: List.cs, ListItem.cs, Role.cs, RoleAssignment.cs, RoleMapping.cs, SecurableObject.cs, SecurityParser.cs and Web.cs

Step 4: Add code to each file

In DeployableItem.cs add the following:

using System.ComponentModel;
using System.Xml.Serialization;

namespace SecurityParser
{
    public abstract class DeployableItem
    {
        public enum DeploymentModes
        {
            Both = 0,
            DebugOnly = 1,
            NonDebugOnly = 2
        }

        [XmlAttribute("deploymentmode")]
        [DefaultValue(0)]
        public DeploymentModes DeploymentMode
        {
            get;
            set;
        }

        internal bool ShouldDeploy()
        {
            if (DeploymentMode == DeploymentModes.Both || DeploymentMode == DeploymentModes.NonDebugOnly)
            {
                return true;
            }
#if DEBUG
            if (DeploymentMode == DeploymentModes.DebugOnly)
            {
                return true;
            }
#endif
            return false;
        }
    }
}

In List.cs, enter the following:

namespace SecurityReceiver
{
    public class List : SecurableObject
    {

    }
}

In ListItem.cs, enter the following:

namespace SecurityReceiver
{
    public class ListItem : SecurableObject
    {

    }
}

In Role.cs, enter the following:

using System;
using System.Xml.Serialization;
using Microsoft.SharePoint;

namespace SecurityParser
{
    public class RoleDefinition : DeployableItem
    {
        [XmlAttribute("name")]
        public string Name
        {
            get;
            set;
        }

        [XmlAttribute("description")]
        public string Description
        {
            get;
            set;
        }

        [XmlAttribute("basepermissions")]
        public SPBasePermissions BasePermissions
        {
            get;
            set;
        }

        public void Attach(SPWeb web)
        {
            //if this role should be applied in the current configuration
            if (this.ShouldDeploy())
            {
                //Find the role
                SPRoleDefinition roleDefinition;

                try
                {
                    roleDefinition = web.RoleDefinitions[Name];

                    //role definition already exists

                    //Update it
                    roleDefinition.BasePermissions = BasePermissions;
                    roleDefinition.Description = Description;

                    //Save the changes
                    roleDefinition.Update();
                }
                catch (Exception)
                {
                    //if role definition doesn't exist
                    SPRoleDefinition newRole = new SPRoleDefinition()
                    {
                        BasePermissions = BasePermissions,
                        Name = Name,
                        Description = Description
                    };

                    //add it
                    web.RoleDefinitions.Add(newRole);

                    //Update the web to save the changes
                    web.Update();
                }

            }
        }
    }
}

In RoleAssignment.cs, enter the following:

using System;
using System.Collections.Generic;
using System.Xml.Serialization;
using Microsoft.SharePoint;

namespace SecurityParser
{
    public class RoleAssignment : DeployableItem
    {
        [XmlElement("Role")]
        public List<RoleMapping> Roles
        {
            get;
            set;
        }

        [XmlAttribute("loginname")]
        public string LoginName
        {
            get;
            set;
        }

        [XmlAttribute("email")]
        public string EmailAddress
        {
            get;
            set;
        }

        [XmlAttribute("defaultuser")]
        public string DefaultUser
        {
            get;
            set;
        }

        [XmlAttribute("owner")]
        public string Owner
        {
            get;
            set;
        }

        [XmlAttribute("name")]
        public string Name
        {
            get;
            set;
        }

        [XmlAttribute("notes")]
        public string Notes
        {
            get;
            set;
        }

        internal void Apply(ISecurableObject item, SPWeb web)
        {
            //if this item should be depoloyed
            if (this.ShouldDeploy())
            {
                //Get a reference to the SPPrincipal thats represented by this object
                SPPrincipal principal = GetPrincipal(web);

                //Create a new SPRoleAssignment
                SPRoleAssignment newAssignment = CreateAssignment(principal);

                //Attach the roles to the new assignment
                AttachRoles(web, newAssignment);

                //Add the role assignment to the web
                web.RoleAssignments.Add(newAssignment);
            }
        }

        private SPPrincipal CreateUserGroup(SPWeb web)
        {
            SPPrincipal principal;
            SPMember owner = null;
            SPUser defaultUser = null;

            if (string.IsNullOrEmpty(Owner))
            {
                try
                {
                    owner = web.SiteUsers[Owner];

                }
                catch (Exception)
                {
                    //Owner is not found in users collection. Try cross-site groups
                    try
                    {
                        owner = web.SiteGroups[Owner];
                    }
                    catch (Exception)
                    {
                        //specified owner does not exist
                    }
                }
            }

            if (owner == null)
            {
                owner = web.Site.Owner;
            }

            if (string.IsNullOrEmpty(DefaultUser))
            {
                try
                {
                    defaultUser = web.SiteUsers[DefaultUser];

                }
                catch (Exception)
                {
                    //specified user does not exist
                }
            }

            web.SiteGroups.Add(this.Name, owner, defaultUser, this.Notes);
            principal = web.SiteGroups[this.Name];

            return principal;
        }

        private void AttachRoles(SPWeb web, SPRoleAssignment newAssignment)
        {
            foreach (RoleMapping role in Roles)
            {
                //Apply the Role Definition
                role.Apply(newAssignment, web);
            }
        }

        private SPRoleAssignment CreateAssignment(SPPrincipal principal)
        {
            SPRoleAssignment newAssignment;

            //if we didn't find an existing principal
            if (principal == null)
            {
                //create a new one
                newAssignment = new SPRoleAssignment(LoginName, EmailAddress, Name, Notes);
            }
            else
            {
                //Use the existing principal
                newAssignment = new SPRoleAssignment(principal);
            }
            return newAssignment;
        }

        private SPPrincipal GetPrincipal(SPWeb web)
        {
            SPPrincipal principal;
            if (!string.IsNullOrEmpty(LoginName))
            {
                //try loginName
                try
                {
                    principal = web.SiteUsers[LoginName];

                }
                catch (Exception)
                {
                    return null;
                }

            }
            else
            {
                try
                {
                    //try name to search SPGroups
                    principal = web.SiteGroups[Name];
                }
                catch (Exception)
                {
                    //The user group does not exist. Groups must be created beforehand
                    principal = CreateUserGroup(web);
                }
            }
            return principal;
        }
    }
}

In RoleMapping.cs, enter the following:

using System.Xml.Serialization;
using Microsoft.SharePoint;

namespace SecurityParser
{
    public class RoleMapping : DeployableItem
    {
        [XmlAttribute("name")]
        public string Name
        {
            get;
            set;
        }

        internal void Apply(SPRoleAssignment newAssignment, SPWeb web)
        {
            //if this item shoudl be deployed
            if (this.ShouldDeploy())
            {
                //find the role definition
                SPRoleDefinition roleDefinition = web.RoleDefinitions[Name];

                //attach it to our assignment
                newAssignment.RoleDefinitionBindings.Add(roleDefinition);
            }
        }
    }
}

In SecurableObject.cs, enter the following:

using System;
using System.Collections.Generic;
using System.IO;
using System.Xml.Serialization;
using Microsoft.SharePoint;

namespace SecurityReceiver
{
    public abstract class SecurableObject : DeployableItem
    {
        [XmlArray("RoleAssignments")]
        [XmlArrayItem("RoleAssignment")]
        public List<RoleAssignment> RoleAssignments
        {
            get;
            set;
        }

        [XmlAttribute("url")]
        public string Url
        {
            get;
            set;
        }

        [XmlAttribute("clearexisting")]
        public bool ClearExisting
        {
            get;
            set;
        }

        [XmlAttribute("inheritpermissions")]
        public bool InheritPermissions
        {
            get;
            set;
        }

        [XmlElement("List")]
        public List<List> Lists
        {
            get;
            set;
        }

        [XmlElement("ListItem")]
        public List<ListItem> ListItems
        {
            get;
            set;
        }

        [XmlElement("Web")]
        public List<Web> Webs
        {
            get;
            set;
        }

        public virtual void Parse(SPWeb web)
        {
            //if this item should be deployed in the current configration
            if (this.ShouldDeploy())
            {
                //pick up a reference to the underlying ISecurableObject refered to by URL
                ISecurableObject theObject = GetISecurableObject(web);

                if (theObject != null)
                {
                    //If the object is the root web then inheritance can't be changed
                    if (!IsRootWeb(web, theObject))
                    {
                        //Setup permission inheritance
                        if (InheritPermissions)
                        {
                            //If we're using unique permissions
                            if (theObject.HasUniqueRoleAssignments)
                            {
                                //Inherit from parent. Role Assignments for this item are ignored since they'll be inherited
                                theObject.ResetRoleInheritance();
                            }
                        }
                        else
                        {
                            BreakInheritance(web, theObject);

                            SetUpRoleAssignments(theObject, web);
                        }
                    }
                    else
                    {
                        //Since this is the root web. Everything inherits from here by default
                        //Therefore we need to apply any role assignments that are defined in the config file
                        SetUpRoleAssignments(theObject, web);
                    }

                    //Apply permissions on all child objects
                    ParseChildObjects(web);
                }
                else
                {
                    //Url in the configuration file didn't translate to a securable object
                    throw new InvalidOperationException(string.Format("Item at URL:{0} does not implement the ISecurableObject interface",this.Url));
                }
            }
        }

        private static bool IsRootWeb(SPWeb web, ISecurableObject theObject)
        {

            if (theObject is SPWeb)
            {
                SPWeb currentWeb = theObject as SPWeb;
                if (currentWeb == web.Site.RootWeb)
                {
                    return true;
                }
            }
            return false;
        }

        private ISecurableObject GetISecurableObject(SPWeb web)
        {
            ISecurableObject theObject;
            object obj;

            try
            {
                obj = web.GetObject(Url);
            }
            catch (FileNotFoundException ex)
            {
                //Object wasn't found.
                throw new FileNotFoundException("Object not found in SharePoint site", Url, ex);
            }

            if (obj is SPFolder)
            {
                SPFolder folder = obj as SPFolder;

                if (folder.ParentListId != new Guid())
                {
                    theObject = folder.ParentWeb.Lists[folder.ParentListId] as ISecurableObject;
                }
                else
                {
                    theObject = folder.ParentWeb as ISecurableObject;
                }
            }
            else if (obj is SPFile)
            {
                SPFile file = obj as SPFile;
                theObject = file.Item as ISecurableObject;
            }
            else
            {
                theObject = (ISecurableObject)web.GetObject(Url);
            }

            return theObject;
        }

        private void BreakInheritance(SPWeb web, ISecurableObject theObject)
        {
            web.AllowUnsafeUpdates = true;
            theObject.BreakRoleInheritance(!ClearExisting);
            //Breaking inheritance causes AllowUnsafeUpdates to revert
            web.AllowUnsafeUpdates = true;
        }

        private void ParseChildObjects(SPWeb web)
        {
            ParseWebs(web);
            ParseLists(web);
            ParseListItems(web);
        }

        private void ParseWebs(SPWeb web)
        {
            foreach (Web theWeb in Webs)
            {
                theWeb.Parse(web);
            }
        }

        private void ParseListItems(SPWeb web)
        {
            foreach (ListItem listItem in ListItems)
            {
                listItem.Parse(web);
            }
        }

        private void ParseLists(SPWeb web)
        {
            foreach (List list in Lists)
            {
                list.Parse(web);
            }
        }

        private void SetUpRoleAssignments(ISecurableObject item, SPWeb web)
        {
            //loop through our configured role assignments
            foreach (RoleAssignment assignment in RoleAssignments)
            {
                //Apply assignment to securable object
                assignment.Apply(item, web);
            }
        }
    }
}

In SecurityParser.cs, enter the following:

using System;
using System.Collections.Generic;
using System.Text;
using System.Xml.Serialization;
using System.IO;
using System.Xml;
using Microsoft.SharePoint;

namespace SecurityReceiver
{
    public class SecurityParser
    {

        public void Parse(string fileName, SPWeb web)
        {
            //Read in the 'elements' file
            //deserialize it using the embedded schema
            XmlSerializer s = new XmlSerializer(typeof(Web));
            Web rootWeb;

            if (File.Exists(fileName))
            {
                using (XmlReader rdr = XmlReader.Create(File.OpenRead(fileName)))
                {
                    rootWeb = (Web)s.Deserialize(rdr);
                }

                if (rootWeb != null)
                {
                    //Start parsing from the root
                    rootWeb.Parse(web);
                }

            }
            else
            {
                throw new FileNotFoundException("Unable to parse elements file");
            }

        }
    }
}

In Web.cs, enter the following:

using System;
using System.Collections.Generic;
using Microsoft.SharePoint;

namespace SecurityParser
{
    public class Web : SecurableObject
    {
        public List<RoleDefinition> Roles
        {
            get;
            set;
        }

        public override void Parse(SPWeb web)
        {
            //if this item should be deployed in the current configuration
            if (this.ShouldDeploy())
            {
                //Loop through the list of roles if there are any
                if (Roles != null)
                {
                    foreach (RoleDefinition role in Roles)
                    {
                        role.Attach(web);
                    }
                }

                //Call the base implementation of parse to parse the SecurableObject stuff

                //Since Web is a securable object with a url thats set in our elements file
                //the reference to the SPWeb object passed into this method may be incorrect
                //verify it using the Url property

                if (string.Compare(web.Url, this.Url, true) != 0)
                {
                    //We need to get a reference to a different web
                    //Since SPWeb object implements IDisposable, wrap the call in a using statement
                    //to ensure that resources get disposed when we're done
                    string relativeUrl;

                    Uri newurl = new Uri(this.Url);
                    Uri current = new Uri(web.Url);

                    relativeUrl = newurl.MakeRelativeUri(current).ToString();

                    using (SPWeb newWeb = web.Site.OpenWeb(relativeUrl, true))
                    {
                        base.Parse(newWeb);
                    }
                }
                else
                {
                    base.Parse(web);
                }
            }
        }

    }
}

Step 5: Build the project.

In Visual Studio 2008, select “Build Solution” from the “Build” menu. If everything has been setup correctly, the status bar at the bottom of the page will show ‘Build Succeeded”.

 

In the next part of this article we’ll look at how we can use this utility with a feature to automatically configure new sites on creation.

  • http://www.casino-a-lasvegas.com/ casino a Las Vegas

    Thanks for such a nice article.I really bookmark this one and now I will visit this site regularly…..

  • http://www.francepokerroom.com/ jeu de Poker gratuit en ligne

    This machine has a tremendous computing power.Bryce does not seem to use all the cores in any configuration. With Dual cores, both are used unequally, but not fully. With the Quad core only two cores are used. In both cases, Bryce uses only 50% of the available computing power.

  • http://www.bestepokerboni.com/ bester Pokerbonus

    I trying the query web service and running into som problems.. I get following error System.InvalidCastException when I try to use service.Query(queryXml);If I use service.QueryEx(queryXml); I’ll get a result. Has the Querypacket changed in some way that you cant use same query between query and queryex.

  • http://www.onlinecasinomatter.com/ Online Casino Gambling

    Thanks for the comphrensive guide on how to set up Sharepoint properly. It’s really helpful :)

  • http://www.newaj.com/ jordan shoes

    Recently, guo fucheng busy filming the magic in northeast China, the media

  • http://www.flashdevs.com/flash_game_programming/ flash game programming

    That is a wonderfully structed blog and the content is just awesome. I will get all my family soon to read your lovely posts altogether.

  • http://www.casinos-legaux.com/ sites de casinos legaux

    Thanks for such a beautifully composed, informative article.I think your work to this is really great .
    I really appreciate your work to this site.So thanks for it.I hope you can continue this type of hard work to this
    site in future also..Because this blog is really very informative and it helps me lot.

  • http://www.888sincity.com/ online casino

    SQL backups of the content databases for a Windows SharePoint Services farm can be used for data recovery, it’s usually a good idea to also perform backups through the stsadm.exe utility to facilitate site and object-level restores.

  • http://www.888sincity.com/ online casino

    Thanks to give this nice post.i think so his article is about treating drug addiction so i think so there are so many herbs to do something about this so its really informative article so i would appreciate to your work efforts.

  • http://blog.webtechy.co.uk/ Ben Weeks

    Great post – can’t find part 2 though. Have downloaded the solution from CodePlex … but where does the SecurityConfiguration.xml file live?

  • http://www.bestfinance-blog.com/ DIANNAWelch22

    If you are willing to buy real estate, you would have to receive the loans. Moreover, my father usually uses a credit loan, which occurs to be really rapid.