Wednesday, March 28, 2007

Create Groups Programmatically

Reza Alirezaei has posted a helpful article on creating SharePoint sites with unique role assignments. The following simple demo class puts some of these ideas together. Like Reza's example, the code below changes the built in associated groups by using the spWeb property bag directly, rather than the properties exposed by spWeb - e.g. spWeb.AssociatedGroups.Add(group), or spWeb.AssociatedOwnerGroup = group.

using Microsoft.SharePoint;
 
namespace DevHoleDemo
{
    public static class GroupsHelper
    {
        public enum AssociatedGroupTypeEnum { Owners, Members, Vistors };
 
        public static void AddGroups(SPWeb spWeb, bool copyUsersFromParent)
        {
            spWeb.BreakRoleInheritance(false);
            SPGroup owners = AddGroup(spWeb, AssociatedGroupTypeEnum.Owners, copyUsersFromParent);
            SPGroup members = AddGroup(spWeb, AssociatedGroupTypeEnum.Members, copyUsersFromParent);
            SPGroup vistors = AddGroup(spWeb, AssociatedGroupTypeEnum.Vistors, copyUsersFromParent);
            SPGroup myGroup = AddGroup(spWeb, "My Group", "An example group.", null, null, null, false);
            SetAssociatedGroups(spWeb, new SPGroup[] { owners, members, vistors, myGroup });
        }
 
        public static void SetAssociatedGroups(SPWeb spWeb, SPGroup[] groups)
        {
            string formatString = "";
            object[] ids = new object[groups.Length];
            for (int i = 0; i < groups.Length; i++)
            {
                formatString += string.Format("{{{0}}};", i);
                ids[i] = groups[i].ID;
            }
            spWeb.Properties["vti_associategroups"] = string.Format(formatString.TrimEnd(new char[] { ';' }), ids);
            spWeb.Properties.Update();
        }
 
        public static SPGroup AddGroup(SPWeb spWeb, AssociatedGroupTypeEnum associateGroupType, bool copyUsersFromParent)
        {
            switch (associateGroupType)
            {
                case AssociatedGroupTypeEnum.Owners:
                    return AddGroup(spWeb, spWeb.Name + " Owners", "Use this group to give people full control permissions to the SharePoint site: {0}", "Full Control", "vti_associateownergroup", spWeb.ParentWeb.AssociatedOwnerGroup, copyUsersFromParent);
                case AssociatedGroupTypeEnum.Members:
                    return AddGroup(spWeb, spWeb.Name + " Members", "Use this group to give people contribute permissions to the SharePoint site: {0}", "Contribute", "vti_associatemembergroup", spWeb.ParentWeb.AssociatedMemberGroup, copyUsersFromParent);
                case AssociatedGroupTypeEnum.Vistors:
                    return AddGroup(spWeb, spWeb.Name + " Vistors", "Use this group to give people read permissions to the SharePoint site: {0}", "Read", "vti_associatevisitorgroup", spWeb.ParentWeb.AssociatedVisitorGroup, copyUsersFromParent);
                default:
                    return null;
            }
        }
 
        public static SPGroup AddGroup(SPWeb spWeb, string groupName, string descriptionFormatString, string roleDefinitionName, string associatedGroupName, SPGroup parentAssociatedGroup, bool copyUsersFromParent)
        {
            SPGroup owner = parentAssociatedGroup;
            if (associatedGroupName != "vti_associateownergroup")
                owner = spWeb.SiteGroups.GetByID(int.Parse(spWeb.Properties["vti_associateownergroup"]));
            spWeb.SiteGroups.Add(groupName, owner, null, string.Format(descriptionFormatString, spWeb.Name));
            SPGroup group = spWeb.SiteGroups[groupName];
            if (descriptionFormatString.IndexOf("{0}") != -1)
            {
                SPListItem item = spWeb.SiteUserInfoList.GetItemById(group.ID);
                item["Notes"] = string.Format(descriptionFormatString, string.Format("<a href=\"{0}\">{1}</a>", spWeb.Url, spWeb.Name));
                item.Update();
            }
            if (roleDefinitionName != null)
            {
                SPRoleAssignment roleAssignment = new SPRoleAssignment(group);
                SPRoleDefinition roleDefinition = spWeb.RoleDefinitions[roleDefinitionName];
                roleAssignment.RoleDefinitionBindings.Add(roleDefinition);
                spWeb.RoleAssignments.Add(roleAssignment);
            }
            if (copyUsersFromParent && parentAssociatedGroup != null)
                foreach (SPUser user in parentAssociatedGroup.Users)
                    group.AddUser(user);
            if (associatedGroupName != null)
            {
                spWeb.Properties[associatedGroupName] = group.ID.ToString();
                spWeb.Properties.Update();
            }
            spWeb.Update();
            return group;
        }
    }
}

10 comments:

Henrik Munk Rediin said...

Hi

I'm using the same code to create unique Groups on a site. I'm running in to the problem, that the groups not are deleted, when the site is deleted - as is the case, if you create unique groups through the web-interface.
Do you know of a solution this this problem ?
How does MS get around doing it ?

txs8311 said...

How about adding a class that inherits from SPWebEventReceiver to your web's EventReceivers? You could add code in the overriden web/site deleting methods to delete the groups.

Manu said...

Hi,

Thanks for the code.
I am using the same code, the issue I am facing is that apart from the users of the newly created groups, it allows the users of the groups at the site collection level. In fact those groups and users are also visible in 'People and Groups'.

txs8311 said...
This comment has been removed by the author.
txs8311 said...

One thing to check would be the site permissions of the web you're adding the groups to. The BreakRoleInheritance method in the code example should ensure that the web site doesn't inherit permissions (on the site permissions page for the web you should see "Use this page to assign permission levels to users and groups. This Web site does not inherit permissions from its parent." near the top of the page). Groups of users (spWeb.SiteGroups) are only manageable at the site collection level, which is why you’ll always see all the groups for the site collection on each web’s People and Groups page.

Manu said...

Hi,
Thanks for the post. I saw the message "This Web site does not inherit permissions from its parent". Actually, the site collection Administrators are able to login to the sub site. I created a site and groups manually and found that even in that case, the Site Collection Administrators are able to login. We didnt want that to happen and i doubt if we can change that.

Renato said...

Hi, this code works great, thanks! I need to add the user who created the site to the owners group, how can I do that?

Steve said...

Just saved me hours of work - works fine grate stuff.

Anonymous said...

While every thing works fine , i cannot see the permission added to the groups. All the site permission check boxes are unchecked, any ideas

Thomas said...

Hi,

nice code but it throws an error:
The following errors have occurred:
Value does not fall within the expected range.
at Microsoft.SharePoint.SPGroupCollection.Add(String name, SPMember owner, SPUser defaultUser, String description)
at UTi_SharePoint_Utilities.WebPartCode.GroupsHelper.AddGroup(SPWeb spWeb, String groupName, String descriptionFormatString, String roleDefinitionName, String associatedGroupName, SPGroup parentAssociatedGroup, Boolean copyUsersFromParent)
at UTi_SharePoint_Utilities.WebPartCode.GroupsHelper.AddGroup(SPWeb spWeb, AssociatedGroupTypeEnum associateGroupType, Boolean copyUsersFromParent)
at UTi_SharePoint_Utilities.WebPartCode.GroupsHelper.AddGroups(SPWeb spWeb, Boolean copyUsersFromParent)

Any clue how to solve this?

Thanks,

Thomas