Managing SharePoint Site User Memberships in Multiple Groups Using SPServices

I got an email yesterday from Geoff Oliver. He said he had done something pretty useful with SPServices and wondered if I would be interested in seeing it.

I manage about 115 groups in a single site collection…and that number is expected to grow.  I found that when a new user came on board or changed duty positions, getting them into the right SP groups was slow and cumbersome through the SP interface.

Using the SPServices libraries, I was able to create a simple interface to add/remove a single user to/from multiple groups at once.  When you identify/select a user, it will show you two select lists. The right side will list all of the groups the current user is a member of while the left box shows all the groups the user is NOT a member of.  Between the two select lists are buttons to ‘move’ the groups from one side to the other for the identified user (while modifying their memberships appropriately in the process).  The select boxes are configured to allow multiple select so you can usually perform the maintenance in just a couple clicks.  The code fits neatly into a CEWP.

Of course I wanted to see it. Geoff’s code sounded exactly like the kind of thing that I think SPServices is good for: a useful solution that solves a business problem better than SharePoint out of the box without needing to deploy anything to the server.

Geoff describes himself as:

…a Civilian Project Manager for the Air Force, developing a SharePoint site to assist a large organization with information management and integration with Microsoft Office (sharing/synchronizing data between SharePoint sites and Word/Excel/Access files).  I’ve been doing MS Office automation (using VBA) for about 15 years now and SharePoint site development for 7.

The code uses a number of Users and Groups Web Service operations that are wrapped in SPServices:

  • GetUserCollectionFromSite
  • GetGroupCollectionFromUser
  • GetGroupCollectionFromSite
  • AddUserToGroup
  • RemoveUserFromGroup

Here’s Geoff’s code. It’s amazingly compact and gets the job done well.

$(document).ready(function() {
  //Populate the users pick list
  var strHTMLSiteUsers = "";
  $().SPServices({
      operation: "GetUserCollectionFromSite",
      async: false,
      completefunc: function(xData, Status) {
        $(xData.responseXML).find("User").each(function() {
          strHTMLSiteUsers += "<option value='" + $(this).attr("LoginName") + "'>" + $(this).attr("Name") + "</option>";
        });
        $("#my_SiteUsers").append(strHTMLSiteUsers);
      }
  });
  RefreshGroupLists();
});

function RefreshGroupLists(){
  var strHTMLAvailable = "";
  var strHTMLAssigned = "";
  var arrOptionsAssigned = new Array();
  var intOpts = 0;
  var booMatch;
  var booErr = "false";

  $("#my_SPGroupsAssigned").html("");
  $("#my_SPGroupsAvailable").html("");

  if($("#my_SiteUsers").attr("value") == 0){
    alert("You must select a user");
    return;
  }

  //Populate the Groups Assigned
  $().SPServices({
      operation: "GetGroupCollectionFromUser",
      userLoginName: $("#my_SiteUsers").attr("value"),
      async: false,
      completefunc: function(xData, Status) {
        $(xData.responseXML).find("errorstring").each(function() {
          alert("User not found");
          booErr = "true";
          return;
        });
        $(xData.responseXML).find("Group").each(function() {
          strHTMLAvailable += "<option value='" + $(this).attr("Name") + "'>" + $(this).attr("Name") + "</option>";
          arrOptionsAssigned[intOpts] = $(this).attr("Name");
          intOpts = intOpts + 1;
        });
        $("#my_SPGroupsAssigned").append(strHTMLAvailable);
      }
  });

  //Populate available site groups
  if(booErr == "false"){
    $().SPServices({
        operation: "GetGroupCollectionFromSite",
        async: false,
        completefunc: function(xData, Status) {
          $(xData.responseXML).find("Group").each(function() {
            booMatch = "false";
            for (var i=0;i<=arrOptionsAssigned.length;i++){
              if($(this).attr("Name") == arrOptionsAssigned[i]){
                booMatch = "true";
                break;
              }
            }
            if(booMatch == "false"){
              strHTMLAssigned += "<option value='" + $(this).attr("Name") + "'>" + $(this).attr("Name") + "</option>";
            }
          });
          $("#my_SPGroupsAvailable").append(strHTMLAssigned);
        }
    });
  }
}

function AddGroupsToUser(){
  var i;

  if($("#my_SiteUsers").attr("value") == 0){
    alert("You must select a user");
    return;
  }

  if($("#my_SPGroupsAvailable").val() == null){
    alert("You haven't selected any groups to add");
    return;
  }
  else{
    var arrGroups = $("#my_SPGroupsAvailable").val();
    for (i=0;i<arrGroups.length;i++){
      $().SPServices({
          operation: "AddUserToGroup",
          groupName: arrGroups[i],
          userLoginName: $("#my_SiteUsers").attr("value"),
          async: false,
          completefunc: null
      });
    }
    RefreshGroupLists();
  }
}

function RemoveGroupsFromUser(){
  var i

  if($("#my_SiteUsers").attr("value") == 0){
    alert("You must select a user");
    return;
  }

  if($("#my_SPGroupsAssigned").val() == null){
    alert("You haven't selected any groups to remove");
    return;
  }
  else{
    var arrGroups = $("#my_SPGroupsAssigned").val();
    for (i=0;i<arrGroups.length;i++){
      $().SPServices({
          operation: "RemoveUserFromGroup",
          groupName: arrGroups[i],
          userLoginName: $("#my_SiteUsers").attr("value"),
          async: false,
          completefunc: null
      });
    }
    RefreshGroupLists();
  }
}

and the associated markup:

<table align="center">
  <tr>
    <td colspan="3" style="text-align:center">
      <font style="font-weight:bold">Select a User:&nbsp;&nbsp;&nbsp;</font>
      <select id="my_SiteUsers" style="width:350px;" onchange="RefreshGroupLists()"></select>
    </td>
  </tr>
  <tr>
    <th class='ms-vh2'>Available Groups</th>
    <th></th>
    <th class='ms-vh2'>Assigned Groups</th>
  </tr>
  <tr>
    <td class='ms-vb2'>
      <select id="my_SPGroupsAvailable" style="width:250px;height:450px;" multiple="multiple"></select>
    </td>
    <td>
      <button id="my_AddGroupsToUser" style="width:80px;" onclick="AddGroupsToUser()">&gt;&gt;</button><br><br>
      <button id="my_RemoveGroupsFromUser" style="width:80px;" onclick="RemoveGroupsFromUser()">&lt;&lt;</button></td>
    <td class='ms-vb2'>
      <select id="my_SPGroupsAssigned" style="width:250px;height:450px;" multiple="multiple"></select>
    </td>
  </tr>
</table>

And here’s the net result. It’s a simple little form that does exactly what Geoff said it would. All I had to do to get it running in my environment was to change the references to the script files to point where I have them stored. Otherwise, it worked with no modification whatsoever.

image

This is the sort of thing that may belong in SPServices. Of course, you can simply copy and use the code above, but perhaps some more options and additional functionality would make it even more useful.  What do you think? Is this something you’d use?

And thanks for sharing, Geoff.

Similar Posts

58 Comments

  1. This is really awesome. This works, as advertised, until I attempt to add or remove membership for a user. IE throws the following error:

    Webpage error details

    User Agent: Mozilla/4.0 (compatible; MSIE 8.0; Windows NT 5.1; Trident/4.0; .NET CLR 1.1.4322; .NET CLR 2.0.50727; .NET CLR 3.0.4506.2152; .NET CLR 3.5.30729; .NET4.0C; .NET4.0E; MS-RTC LM 8; InfoPath.3)
    Timestamp: Thu, 21 Feb 2013 18:22:26 UTC

    Message: Object expected
    Line: 19
    Char: 26661
    Code: 0
    URI: https://URL/usermgt/jquery.SPServices-0.7.2.min.js

    I saw a previous comment about the version is jQuery so I’ve tried 1.8.3 and even tried using 1.6.4 with no luck. Any ideas? Maybe role back SPServices to 0.7.0?

    Many thanks!

  2. Hi Marc,
    I am new to Spservices, I have a one question. how to find whether the user has joined the community using spservices that would be great help for me. Thanks in advance.

        1. Ah, you’re talking about SharePoint 2013. I haven’t looked into any of the new Web Services in 2013 for SPServices. However, none of the new ones are SOAP Web Services. They would be exposed via REST. You’ll have to figure that one out.

          M.

            1. Hmm. I’m really not sure then. What Site Template are you using for those communities?

              I expect that all you would need to do is check whether the user is in a particular SharePoint group.

              M.

  3. Hi Marc,

    I was wondering if there was anyway this could work with SP 2010 Foundation? I’ve added the code to the CEWP and the drop down does generate a list of users for me, however I get a message saying “User not found” and no groups show up.

    1. Kc:

      This ought to work with Foundation, as the Web Services operations are available. I’d suggest doing some debugging, as it may be a permissions issue.

      M.

      1. HI Marc,

        Thanks for the reply. I’m not sure why, but it worked when I used a variable. So instead of doing: userLoginName: $(“#my_SiteUsers”).attr(“value”)

        I did:
        var user = $(“#my_SiteUsers”).attr(“value”);
        userLoginName: user,

        I don’t really know what the difference is, there really isn’t any, but it works. I’m actually really happy I came across this. It’s going to make user and group management significantly simpler.

        On another note, I posted a question on Codeplex discussion, I was hoping you might have some time to take a look at it whenever you get the chance: http://spservices.codeplex.com/discussions/459741

        Anyways, Thanks again for sharing this.

        1. Hi KC / Marc,

          I am getting the same error – “User Not found”, but it does pick up the user list, and the groups etc. are empty. And if I make the changes you (KC) mentioned regarding userLoginName in all the three places in the java script, then it does not even pick up the users.
          I would also like to point out that I am not at all a programmer, I am just trying to create this functionality as it will help me manage the users for SharePoint site. So any help will be greatly appreciated!

  4. I am now in charge of managing permissions on over 500+ different groups over 17 different site collections. Would there be a way to implement this on one site to pull all information for each of the others?

  5. Hi, I am using newer JQuery and line 36 UserLoginName needed to be changed from attr to prop to get this to work. It tooks some debugging to find, but wanted to share for folks who are just finding this. This will be much faster to use then the clunky infopath form that I developed to manage permissions. Many thanks!

Leave a Reply

Your email address will not be published. Required fields are marked *

This site uses Akismet to reduce spam. Learn how your comment data is processed.