September 20, 2014
Hot Topics:
RSS RSS feed Download our iPhone app

Simple Custom Group Assignments in SharePoint

  • August 19, 2009
  • By Joe Mack
  • Send Email »
  • More Articles »

Many of my clients ask for ways to give certain, very specific rights to their users without giving other rights within the same standard SharePoint role. For instance, it would be nice if distributed site/content managers could add users to SharePoint security groups on their site without actually giving them explicit rights via SharePoint roles and permissions to add users to groups within their site.

Out-of-the-box, in order to be able to add and remove users from a group, you need to be the Group Owner, have Full Control rights to the site, be the Site Administrator, or be the Site Collection Administrator. In many cases, none of those options are acceptable, as they all potentially bring along other rights that clients are not willing to give a content or site manager within the construct of their corporate and/or SharePoint governance policies. They simply want a user to be able to add other users to existing SharePoint groups on their site and that's it. They don't want that user to have any rights whatsoever to change the groups on the site, other than adding new users to them.

This article presents a simple solution I have found to allow this functionality.

Step 1: Create and Configure the Project

In your Visual Studio product of choice, create a new Class Library project. Please note that I am not using the SharePoint Web Part templates provided by Microsoft; I'm just creating my own Class Library from scratch and implementing the SharePoint Web Part class. If you are comfortable with using the SharePoint templates for your version of Visual Studio, please feel free to do so.

So, create a Class Library project. In my case, I am calling it “CustomGroupAssignment”. Once you have created the project, you will need to add references to System.Web and Microsoft.SharePoint. Now, add the following "using" directives if they do not exist already:

using System.Web;
using System.Web.UI;
using System.Web.UI.WebControls;
using System.Web.UI.WebControls.WebParts;
using Microsoft.SharePoint;
using Microsoft.SharePoint.WebControls;
using Microsoft.SharePoint.WebPartPages;
using System.Collections;

Step 2: Setting up the Class

At this point, go ahead and set up the class. Please note that I am inheriting from Microsoft.SharePoint.WebPartPages.WebPart and not from System.Web.UI.WebControls.WebParts.WebPart. You are going to override the two core web part methods, CreateChildControls and RenderWebPart, so you will add some placeholders in the code as well. Please add the placeholders like so:

namespace TPG.WebParts
{
    public class CustomGroupAssignment : Microsoft.SharePoint.WebPartPages.WebPart
    {
        protected override void CreateChildControls()
        {
   base.CreateChildControls();
        }
        protected override void RenderWebPart(HtmlTextWriter writer)
        {
        }
    }
}

Once you have the shell for your class in place, go ahead and add in some class-level variables for the child controls that you will use in the web part.

        //People Picker UI controls
        Label lblPplPicker;
        PeopleEditor pplPicker;
        Label lblPplPickerDesc;
        //Groups UI controls
        Label lblGroups;
        CheckBoxList cblGroups;
        Label lblGroupsDesc;
        //Button controls
        Button btnSubmit;
        Button btnCancel;
        //Status "window"
        TextBox txtStatus;

Basically, what you are going to do is incorporate a few controls into your web part that will allow you to provide the user with some guidance about what to do, require the user to choose one or more users, assign them to groups via checkboxes and click the "Submit" button.

Step 3: CreateChildControls

The next thing you need to do is add all of your custom controls into the CreateChildControls method. First, implement a base method. In case it was not included when you typed in your shell earlier, or you deleted it by accident, here is the statement to do so:

            base.CreateChildControls();

Then, put in the PeoplePicker section.

            //Create People Picker Label
            lblPplPicker = new Label();
            lblPplPicker.Text = "Users:";
            this.Controls.Add(lblPplPicker);
            //Create People Picker Control
            pplPicker = new PeopleEditor();
            pplPicker.AllowEmpty = false;
            pplPicker.ValidatorEnabled = true;
            pplPicker.SelectionSet = "User";
            this.Controls.Add(pplPicker);
            //Create People Picker Description
            lblPplPickerDesc = new Label();
            lblPplPickerDesc.Text = "Please select the users you would like to add to the current site.";
            this.Controls.Add(lblPplPickerDesc);

Now, add in the section for the Group controls.

            //Create Groups Label
            lblGroups = new Label();
            lblGroups.Text = "Groups:";
            this.Controls.Add(lblGroups);
            //Create Groups Control
            cblGroups = new CheckBoxList();
            cblGroups.ID = "groupsList";
            
            using (SPWeb oWebSite = SPContext.Current.Web)
            {
                SPGroupCollection collGroups = oWebSite.Groups;
                foreach (SPGroup oGroup in collGroups)
                {
                    cblGroups.Items.Add(oGroup.Name.ToString());
                }
            }
            this.Controls.Add(cblGroups);
            //Create Groups Description
            lblGroupsDesc = new Label();
            lblGroupsDesc.Text = "Please select the groups to which you would like to add the selected user(s).";
            this.Controls.Add(lblGroupsDesc);

As you may have noticed, the main actionable Groups control is built by grabbing the current site’s groups, storing them in an SPGroupCollection object, and then iterating through that collection, creating a check box for each group, using the actual group name, which will serve you well in the next step.

Now, for the Submit Button, the Cancel Button and our “Status” Window. Please note the treatment of the Click events for the two buttons.

            //Create Submit Button
            btnSubmit = new Button();
            btnSubmit.Text = "Submit";
            btnSubmit.Click += new EventHandler(btnSubmit_Click);
            this.Controls.Add(btnSubmit);
            //Create Cancel Button
            btnCancel = new Button();
            btnCancel.Text = "Cancel";
            btnCancel.Attributes.Add("onClick", "history.back(); return false;");
            this.Controls.Add(btnCancel);
            //Create “Status” Window
            txtStatus = new TextBox();
            txtStatus.TextMode = TextBoxMode.MultiLine;
            txtStatus.Width = 500;
            txtStatus.Rows = 10;
            txtStatus.Visible = false;
            this.Controls.Add(txtStatus);

Hopefully you noticed the way the Click events were handled. For the Cancel button, you merely send it to the previous page in the browser’s history by adding an onClick attribute through code, and then assigning some JavaScript as the value for that attribute. The Submit button is using the .NET EventHandler, which will be explored next.

Step 4: Submit Button

Now it’s time for the heavy lifting of this web part—adding the users to the groups. Here is the basic code to do that, and we will walk through it briefly below.

void btnSubmit_Click(object sender, EventArgs e)
{
   try
   {
       SPSecurity.RunWithElevatedPrivileges(delegate
       {
           using (SPSite spSite = new SPSite(Page.Request.Url.ToString()))
           {
               using (SPWeb spWeb = spSite.OpenWeb())
               {
                   try
                   {
                       //Temporarily allow unsafe updates
                       spWeb.AllowUnsafeUpdates = true;
                       SPGroup spGroup;
                       string userLogin = "";
                       string userEmail = "";
                       string userDisplayName = "";
                       foreach (ListItem cblItem in cblGroups.Items)
                       {
                          if (cblItem.Selected)
                          {
                              spGroup = spWeb.Groups[cblItem.Text];
                              txtStatus.Text += "Found Group:  " + spGroup.Name.ToString() + 
                                  " ... Adding Usersrn------------rn";
                              foreach (PickerEntity pe in pplPicker.Entities)
                              {
                                 userLogin = pe.Key;
                                 Hashtable userData = pe.EntityData;
                                 if (userData.ContainsKey("Email"))
                                     userEmail = userData["Email"].ToString();
                                 if (userData.ContainsKey("DisplayName"))
                                     userDisplayName = userData["DisplayName"].ToString();
                                 txtStatus.Text += "Found user: " + userLogin.ToString() + "rn";
                                 spGroup.AddUser(userLogin, userEmail, userDisplayName, "");
                                 txtStatus.Text += "Added user:  " + userLogin + "rn";
                              }
                              txtStatus.Text += "============rn";
                          }
                       }
                   }
                   catch (Exception ex)
                   {
                        txtStatus.Text += ex.Message;
                   }
                   finally
                   {
                       spWeb.AllowUnsafeUpdates = false;
                   }
               }
           }
       });
   }
   catch (Exception exception)
   {
       txtStatus.Text += exception.Message;
   }
   txtStatus.Visible = true;
}

First things first — the SPSecurity.RunWithElevatedPrivileges method is being used to make sure that the code is going to run as a user with the proper rights. You could just as easily have explicitly declared some credentials, but the SPSecurity class has provided us with this excellent alternative.

The next thing that jumps out is the AllowUnsafeUpdates property. In order for the code to be able to add users to groups within the site, this property must first be set to “true” temporarily.

After that, it is just a simple nested loop wherein each checkbox is inspected to see if it is checked, and if it is, each user is retrieved from the Entities collection of the People Picker control in the web part, and added to the group. A few things are also written to the “Status” window so that you can see what is happening. Obviously this status updating is removed before being put into production, where you would send the user to a follow-on page that lets them know if the users were successfully added to the groups or not. I would highly encourage you to do something similar if you implement this kind of functionality in your SharePoint environment.

You also have the clean-up action of setting the AllowUnsafeUpdates property back to “false” on your way out of this function. Hopefully, I do not need to remind you how crucial this one line of code could be to your happiness and career longevity as a SharePoint developer.

Step 5: Rendering the Web Part

The final thing to do is to render the content of the web part, which is accomplished through the code below. As you will notice, an ever-so-simple HTML table is created to house the controls in an easy way for the user to interact with the controls and meet our expectation of choosing one or more users using the People Picker, selecting one or more groups to which they want to add the user(s) and clicking the Submit button.

        protected override void RenderWebPart(HtmlTextWriter writer)
        {
            EnsureChildControls();
            writer.Write("<TABLE><TR><TD>");
            this.lblPplPicker.RenderControl(writer);
            writer.Write("</td><td>");
            this.pplPicker.RenderControl(writer);
            writer.Write("<BR />");
            this.lblPplPickerDesc.RenderControl(writer);
            writer.Write("</td></tr>");
            writer.Write("<tr><td>");
            this.lblGroups.RenderControl(writer);
            writer.Write("</td><td>");
            this.cblGroups.RenderControl(writer);
            writer.Write("<BR />");
            this.lblGroupsDesc.RenderControl(writer);
            writer.Write("</td></tr>");
            writer.Write("<tr><td colspan="2" align="center">");
            btnSubmit.RenderControl(writer);
            btnCancel.RenderControl(writer);
            writer.Write("</td></tr></table>");
            writer.Write("<BR/><BR/>");
            this.txtStatus.RenderControl(writer);
        }

Once again, this is a very simple treatment of the RenderWebPart method. You may want to provide additional detail to your users in this method or in the CreateChildControls method.


Tags: security, Microsoft, SharePoint Server, SharePoint



Page 1 of 2



Comment and Contribute

 


(Maximum characters: 1200). You have characters left.

 

 


Sitemap | Contact Us

Rocket Fuel