Tuesday, October 30, 2012

Enumerating SharePoint 2007 user permissions

As part of another project, I recently needed to enumerate through all the sites, subwebs, lists and items to determine which users had been assigned what rights.

Originally I came across this post by Roger Cormier, which provided a great base, but had a few issues:
  1. It was SP2010 based (SP2007 doesn't have Get-SPWeb)
  2. It didn't handle Items
  3. It didn't handle sub-site/web/list/items of parent site/web/lists that didn't have unique permissions.
  4. It didn't handle membershipproviders
So after some mangling, I submitted this back to Roger.

I then distilled it down to the following script, which is cruder, but outputs a CSV that I can then use for various automated tasks.

Feel free to do what you like with it.

[void][System.Reflection.Assembly]::LoadWithPartialName("Microsoft.SharePoint")
function stripProvider([string]$userName)
{
    if($userName.split("\").count -gt 1)
    {
        $userName.split("\")[1]
    }
    elseif ($userName.split(":").count -gt 1)
    {
        $userName.split(":")[1]
    }
    else
    {
        $userName
    }
}

#This function determines the source of the user AD/Local NT vs Membership provider
Function UserSource([string]$userName)
{
    if($userName.split("\").count -gt 1)
    {
        $userName.split("\")[0]
    }
    elseif ($userName.split(":").count -gt 1)
    {
        $userName.split(":")[0]
    }
    else
    {
        ""
    }
}


$farm = [Microsoft.SharePoint.Administration.SPFarm]::Local
$farmWebServices = $farm.Services | where -FilterScript {$_.GetType() -eq [Microsoft.SharePoint.Administration.SPWebService]}
foreach ($farmWebService in $farmWebServices) {
  foreach ($webApplication in $farmWebService.WebApplications) {
    foreach ($site in $webApplication.Sites)
    {
        foreach ($web in $site.AllWebs)
        {
          # Write-Host "Site Collection: ID:" $site.ID " - URL: " $site.Url
          if ($web.HasUniqueRoleAssignments)
          {
            foreach ($RoleAssignment in $aList.RoleAssignments)
            {
                if(UserSource($RoleAssignment.Member.LoginName) -ne "")
                {
                    "web,direct," + (stripProvider($RoleAssignment.Member.LoginName)) + "," + (UserSource($RoleAssignment.Member.LoginName)) + "," + $web.Url + "," + ($RoleAssignment.RoleDefinitionBindings | select name).name
                }
                else
                {
                    $allUsers = $Roleassignment.member.users
                               
                    #Perform some action against all members returned.
                    foreach($User in $AllUsers)
                    {
                        "web,role," + (stripProvider($User.LoginName)) + "," + (UserSource($user.LoginName)) + "," + $web.Url + "," + $RoleAssignment.member.name
                    }
                }
            }
          }
         
          foreach ($aList in $Web.lists)
          {
              if ($aList.HasUniqueRoleAssignments)
              {
                  foreach ($RoleAssignment in $aList.RoleAssignments)
                  {
                      if(UserSource($RoleAssignment.Member.LoginName) -ne "")
                      {
                          "list,direct," + (stripProvider($RoleAssignment.Member.LoginName)) + "," + (UserSource($RoleAssignment.Member.LoginName)) + "," + $web.Url + $aList.DefaultViewUrl + "," + ($RoleAssignment.RoleDefinitionBindings | select name).name
                      }
                      else
                      {
                          $allUsers = $Roleassignment.member.users
                         
                          #Perform some action against all members returned.
                          foreach($User in $AllUsers)
                          {
                              "list,role," + (stripProvider($User.LoginName)) + "," + (UserSource($user.LoginName)) + "," + $web.Url + $aList.DefaultViewUrl + "," + $RoleAssignment.member.name
                          }
                      }
                  }
              }
              foreach ($anItem in $aList.Items)
              {
                  if ($anItem.HasUniqueRoleAssignments)
                  {
                      foreach ($RoleAssignment in $anItem.RoleAssignments)
                      {
                          if(UserSource($RoleAssignment.Member.LoginName) -ne "")
                          {
                              "item,direct," + (stripProvider($RoleAssignment.Member.LoginName)) + "," + (UserSource($RoleAssignment.Member.LoginName)) + "," + $Web.Url + "/" + $anItem.URL + "," + ($RoleAssignment.RoleDefinitionBindings | select name).name
                          }
                          else
                          {
                              $allUsers = $Roleassignment.member.users
                         
                              #Perform some action against all members returned.
                              foreach($User in $AllUsers)
                              {
                                  "item,role," + (stripProvider($User.LoginName)) + "," + (UserSource($user.LoginName)) + "," + $Web.Url + "/" + $anItem.URL + "," + $RoleAssignment.member.name
                              }
                          }
                      }
                  }
              }
          }
       }
       $site.Dispose()
    }
  }
}

Wednesday, May 16, 2012

SharePoint on mobile: HTML vs Generic App vs Custom App

Here at work we've been working with SharePoint since mid 2006 (SP2007 beta) and most of what we do is based around SharePoint 2010 these days. So with the influx of smartphones and tablets (OK, to be honest, it's largely iPhones and iPads, with a very small sprinkle of Android and WM7 devices) we've been looking at what our corporate response is and how to combat the likes of DropBox.


Given that we already use SharePoint for our Intranet, Internet and Extranet sites, it seems fairly logical to find a way of leveraging it to deliver content, securely, to mobile devices.  Currently there are three main approaches to supporting mobile devices:

I'm not going to say which approach is best for you, as every situation is different. But I will say you need to look closely at what you're trying to achieve and how you expect your users to interact with your content.

For example, here's our WWW site in Safari on iOS 5.1.1 on my iPhone 4s:
It's nicely branded, looks basically the same as it does on a desktop browser.  The content is largely HTML based with the odd PDF.  It's also basically a read-only site as we use SharePoint's content deployment to push the content from an internal staging farm to the DMZ based external facing farm.

Now here's the same thing in Filament Lite:
OK, so we're now looking at the "raw" SharePoint content, with Sites and Lists. But no branding, no wazy animations and mouse-overs, no neat menu structure and no whole-site search (Filament Lite only supports searching within a list). Not such a great story for consuming our WWW site then.

On the other hand, what about something more collaborative.  Here's part of one of our Extranet sites in Safari, again on my iPhone 4s:
So, now we've got a more vanilla branding and the site is farm more out-of-the-box SharePoint.  We've got a bunch of document libraries, each with various Word, PDF, Excel, PowerPoint and Project files. Safari is more than happy to navigate the site and open/view most of the documents, it's pretty much a read-only experience (you could do something around download/upload, but that's quite cumbersome). Lists however have the full read-write capabilities thanks to being simple HTML forms and fairly standard bits of JavaScript and CSS.

OK, how about Filament Lite:
Yup, we've got our document libraries and lists.  It's more than happy to drill into these:
Unfortunately, the Lite version doesn't support editing list items or documents, but I know the full/paid versions of the SP Apps listed, often support editing and I've seen editing on the iPad equivalents.

So what about Custom Apps?  A custom app has the potential to provide both branding and target the functionality that your users need, but at what cost? And how many platforms do you need to support?

So that's my 2c on the matter currently, no real answers, just more questions :)
We're still looking for a solution that fits our needs and a process that is simple enough for our staff to follow...

I look forward to seeing what the App vendors come up with and what MS do with the next version of SharePoint...