Finding the Elusive ‘Set Up Groups for this Site’ Page

When you create a new subsite In SharePoint 2013 or SharePoint Online (Office 365), you have the option to use the same permissions as the parent site or use unique permissions.

Use unique permissions

Use unique permissions

If you use unique permissions, you’re taken to a page where you can set up the special groups for the subsite.

Set Up Groups for this Site

Set Up Groups for this Site

Generally, this is a “set it and forget it” page; once you’ve done what you need to do here, you rarely need to go back to the page.

However, sometimes you may decide that you’ve been too granular or not granular enough when you set the groups up. In that case, you may want to go back to the page and change the settings.

Unfortunately, the page is hard to find unless you know exactly where it is. Unless I’m missing it, there’s no navigation option to get back there in the UI. The fact that I can’t find it says that it’s at least too obscure.

If you need to get back to the page, navigate to your subsite and append this to the end of the URL:

_layouts/15/permsetup.aspx

So, for example, if your URL is

https://host.sharepoint.com/test99/_layouts/15/start.aspx#/SitePages/Home.aspx

it would become

https://host.sharepoint.com/test99/_layouts/15/permsetup.aspx

This is another one of those posts I’m doing so I can find the answer on my own blog the next time. I hope it helps you, too!

Simple Rules for SharePoint Permissions

PermissionsI get questions all the time about how to set up permissions in SharePoint.

Permissions are hard. It’s not just you. And if you don’t do them right, they turn into a tangled ball of string in a drawer that no one can ever get untangled.

Here are some of my rules of thumb. They are intentionally broad brush and some of them may not apply directly to you, yadda, yadda. But time and time again, these rules seem to work.

KISS

First and foremost, keep it simple. Complexity is your enemy. The site topology and list structures should be driven partly as a way to keep “keep it simple” true.

Open Is Good

Collaboration is hard when permissions are tight. Yes, you’ll want to lock things down for some content. That’s normal. But if you create separate Site Collections for everything – Site Collections are a permissions barrier – then you will find that your collaborative goals may not come true.

Highest: Best

Apply permissions at the highest level and only break inheritance when you need to. Permissions can be applied at the Site, List/Library, and item levels. Whenever possible, you want to avoid item-level permissions. There are performance concerns, but they are tiny compared to the administrative nightmare they turn into.

Out of the Box

Use the out of the box permissions unless you need something else. You know what these are:

  • Read
  • Contribute
  • Full Control

90+% of the time, those three permissions levels cover things. Most of the other out of the box permission levels are too esoteric to be useful (e.g., Design).

Groups, Not Individuals

Always use permissions groups, never individuals. For instance, we should have an HR Department permission group and not just give permissions to a person directly. This is even true if there is just one person in a group. If someone leaves the organization, you simply swap them out of groups for their replacement and you’re all set.

Distribute

Let site owners manage their own permissions if you can. SharePoint has a distributed permission model, and you want to let it work. That means that teams should be allowed to mess up their own permissions and external sharing and also be able to fix it. You simply can’t do it all. But you absolutely should be available to help if things get out of hand.

Finally…

Following these simple rules can save you so many headaches. If you’ve had SharePoint up and running for more than a few months, your ball of string is probably already a bit snarled. Don’t let it get much worse before you take a pass through and clean the permissions up. It only gets worse.

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.

Active Directory Groups vs. SharePoint Groups for User Management: The Denouement

Last week I did a post about when you might decide to use Active Directory groups versus SharePoint groups. It was less about managing the security, and more about understanding the membership of the groups.

I got a *lot* of comments, emails, tweets, grumbles, and groans about the post. This seems to be a really common question, and while there are some possible answers, they aren’t all straightforward or cheap. Here are a few of the suggestions that I received:

And the warnings:

  • Watch out for performance
  • Nested Active Directory groups means that you could get into infinite loops in expanding them (This seems like it would be the developer’s fault for not handling the possibility to me, though.)
  • Issues with the information in SharePoint groups and Active Directory groups being out of synch
  • and on and on…

So what did we decide to do? We chucked the idea of using Active Directory groups in favor of the ease of use of SharePoint groups. No, we didn’t like this answer, either. I would posit that there needs to be a SIMPLE way to expand an Active Directory group within SharePoint that doesn’t involve custom coding. While there are many third party tools out there that sort of tackle this, they are mostly overkill and in most cases, it’s not even clear if they would do the simple thing we were looking for.

My client may at some later point decide to buy one or more of the third party tools for other reasons, which may give them a solution for this as well. It just didn’t make sense at this juncture.

So the score of the game for this one was SharePoint: 1, client requirements: 0. I feel that it was an unfortunate outcome, but one that we couldn’t improve upon.

p.s. At least I got to use the word denouement in a post about SharePoint. There’s always that.