Microsoft Knowledge Base Email Alertz

Site groups are not maintained, and users are assigned to roles after you upgrade from SharePoint Portal Server 2003 to SharePoint Server 2007

Search KbAlertz

Advanced Search

Receive Microsoft Knowledge Base articles by E-Mail?

Every night we scan the Microsoft Knowledge Base. If technologies you're interested in are updated, we'll send you an e-mail. You only get one e-mail a day, and only when new articles are added.

Click here to create a
FREE account
Already have an account?
[Click here to Login]











Microsoft Knowledge Base Article

This article contents is Microsoft Copyrighted material.
©2005-©2007 Microsoft Corporation. All rights reserved. Terms of Use | Trademarks

Article ID: 938110 - Last Review: June 26, 2007 - Revision: 1.1

Site groups are not maintained, and users are assigned to roles after you upgrade from SharePoint Portal Server 2003 to SharePoint Server 2007

SYMPTOMS

After you upgrade from Microsoft Office SharePoint Portal Server 2003 to Microsoft Office SharePoint Server 2007, site groups that were present in SharePoint Portal Server 2003 are not maintained in SharePoint Server 2007. Instead, individual users are assigned to roles (also known as permission levels). For example, when you view the Site Permissions list, you see a list of users and the roles to which the users are assigned. You do not see site groups. This can sometimes clutter the Site Permissions list.

CAUSE

By design, SharePoint Server 2007 works in this manner. When you upgrade to SharePoint Server 2007, SharePoint Portal Server 2003 site groups are converted to SharePoint Server 2007 roles. Additionally, SharePoint Portal Server 2003 cross-site groups are converted to SharePoint Server 2007 groups.

WORKAROUND

Microsoft provides programming examples for illustration only, without warranty either expressed or implied. This includes, but is not limited to, the implied warranties of merchantability or fitness for a particular purpose. This article assumes that you are familiar with the programming language that is being demonstrated and with the tools that are used to create and to debug procedures. Microsoft support engineers can help explain the functionality of a particular procedure. However, they will not modify these examples to provide added functionality or construct procedures to meet your specific requirements.

To work around this behavior, modify the structure of groups in SharePoint Portal Server 2003 so that the upgrade operation creates site groups instead of roles in SharePoint Server 2007. To do this, populate SharePoint Portal Server 2003 cross-site groups based on existing SharePoint Portal Server 2003 site groups. Do this in a way that site groups are created in SharePoint Server 2007 during the upgrade operation.

The following is an example of code that performs these actions.
using System;
using System.Collections;
using System.Collections.Generic;
using System.Text;
using Microsoft.SharePoint;
using Microsoft.SharePoint.Administration;

/*
 
 * 
 * Usage
 *
 * 	Role2Group.exe -url foo -url bar [-fix]
 * 
 * Parameters
 * 
 *   1. A list of urls that specifies which SharePoint 
 *      virtual server to process.
 *   2. An optional flag (fix) to indicate whether 
 *      we should execute the code to move members that are 
 *      assigned to SPRoles or that are assigned to SPGroup. 
 *		By default, this is off to prevent any accidental updates to the database.
 * 
 * Details
 *
 *   The program will examine each Web that has unique permissions within each site 
 *   collection on each virtual server. It will examine each Role 
 *   and each site group within those Webs. This program will do the following: 
 *   1. Create a new cross-site group.
 *   2. Assign the new group to the role that is to be processed. 
 *   3. Move all the users who are assigned to the Role into the newly created group.
 * 
 *  	The following are the exceptions:
 *
 *      	- If no user is assigned to that role, no action is taken.
 *      	- If only one user is assigned to the admin role, no action is taken.
 *      	- If groups are assigned to that role, those groups will be warned
 *            because those groups cannot be assigned to another cross-site group.
 *      	- If domain groups are assigned to that role, the domain groups will 
 *            be warned because domain groups cannot be assigned to a cross-site group.
 */
namespace ConsoleApplication1
{
    static class Program
    {
        static int cWarning = 0;
        static int cError = 0;

        static void Main(string[] args)
        {
            if ((args.Length == 0) ||
                (args.Length == 1 && (args[0] == "-?" || args[0] == "-help")))
            {
                Console.WriteLine("");
                Console.WriteLine("Role2Group -url foo -url bar [-fix]");
                Console.WriteLine("");
                return;
            }

            ArrayList urls = new ArrayList();
            bool fix = false;

            for (int i = 0; i < args.Length; i++)
            {
                if (args[i] == "-url" && i + 1 < args.Length)
                {
                    urls.Add(args[i + 1]);
                    i++;
                    continue;
                }
                else if (args[i] == "-fix")
                {
                    fix = true;
                    continue;
                }
                else
                {
                    Console.WriteLine(String.Format("Unrecognized switch {0}", args[i]));
                    return;
                }
            }

            if (fix)
            {
                Console.WriteLine("You have specified the -fix option. This " + 
                    "will cause updates to your database");
                Console.WriteLine("Press [Enter] to continue, or [Ctrl+C] to exit...");
                Console.ReadLine();
            }

            SPGlobalAdmin globalAdmin = new SPGlobalAdmin();

            foreach (string url in urls)
            {
                Uri uri = new Uri(url);
                SPVirtualServer vs = globalAdmin.OpenVirtualServer(uri);

                if (vs == null)
                {
                    Console.WriteLine(String.Format(
                        "Cannot process virtual server at {0}.", url));
                    return;
                }

                if (vs.State != SPVirtualServerState.Ready)
                {
                    Console.WriteLine(String.Format(
                        "Skipping virtual server: {0}. Server state = {1}. " +
                        "Cannot process this virtual server.",
                        url, vs.State));
                    return;
                }

                try
                {
                    Console.WriteLine(String.Format("Processing virtual server {0}...", url));
                    ProcessOneVirtualServer(vs, fix);
                }
                catch (Exception e)
                {
                    cError++;
                    Console.WriteLine(String.Format("Error occured while " +
                        "processing virtual server {0}", url));
                    Console.WriteLine(e);
                }

                Console.WriteLine();
                Console.WriteLine("Finished. {0} Errors, {1} Warnings encountered", cError, cWarning);
            }
        }

        static private void WarnAboutDomainGroup(SPSite site, SPWeb web, SPRole role, SPUser user)
        {
            cWarning++;
            Console.WriteLine("WARNING: {0} is a domain group, which cannot " +
                "be assigned to a group", user, role.Name);
        }

        static private void WarnAboutGroup(SPSite site, SPWeb web, SPRole role, SPGroup group)
        {
            cWarning++;
            Console.WriteLine("WARNING: {0} is a cross site group, which " +
                "cannot be assigned to another cross site group ", 
                group.Name, role.Name);
        }

        static private SPGroup EnsureGroup(SPSite site, SPWeb web, SPUser user,
            string name, string description)
        {
            SPGroupCollection groups = web.SiteGroups;
            SPGroup group = null;
            int cTry = 0;
            string groupname = name;

            while (true)
            {
                try
                {
                    // if the group already exists, then modify 
                    // the original name with a number appendix
                    group = groups[groupname];
                    cTry++;
                    groupname = String.Format("{0}_{1}", name, cTry);
                }
                catch
                {
                    // break, if we have found a unique group name
                    break;
                }
            }

            groups.Add(groupname, user, user, description);
            group = groups[groupname];
            return group;
        }

        static private void ProcessOneWeb(SPSite site, SPWeb web, bool fix)
        {
            Console.WriteLine(string.Format("Processing web {0} ...", web.Url));

            StringBuilder sbGroupId = new StringBuilder("");
            SPRoleCollection roles = web.Roles;

            foreach (SPRole role in roles)
            {
                Console.WriteLine(string.Format("Processing role {0} ...", role.Name));

                SPGroup newgroup = null;
                string groupname = String.Format("{0} Group from {1}", role.Name, web.Title);

                // Get rid the following invalid chars from group 
                // name: / \ [ ] : | < > + = ; , ? * ' @  
                groupname = groupname.Replace('/', '_');
                groupname = groupname.Replace('\\', '_');
                groupname = groupname.Replace('[', '_');
                groupname = groupname.Replace(']', '_');
                groupname = groupname.Replace(':', '_');
                groupname = groupname.Replace('|', '_');
                groupname = groupname.Replace('<', '_');
                groupname = groupname.Replace('>', '_');
                groupname = groupname.Replace('+', '_');
                groupname = groupname.Replace('=', '_');
                groupname = groupname.Replace(';', '_');
                groupname = groupname.Replace(',', '_');
                groupname = groupname.Replace('?', '_');
                groupname = groupname.Replace('*', '_');
                groupname = groupname.Replace('\'', '_');
                groupname = groupname.Replace('@', '_');

                string groupdesc = String.Format("{0} Group from {1}. This " +
                    "group is automatically generated.", role.Name, web.Title);

                // there is nothing to do, if there is no individual user
                if (role.Type == SPRoleType.Guest || role.Users == null || role.Users.Count == 0)
                    continue;

                foreach (SPGroup group in role.Groups)
                {
                    WarnAboutGroup(site, web, role, group);
                }

                foreach (SPUser user in role.Users)
                {
                    if (user.IsDomainGroup)
                    {
                        WarnAboutDomainGroup(site, web, role, user);
                    }
                    else if (fix)
                    {
                        if (newgroup == null)
                        {
                            newgroup = EnsureGroup(site, web, user, groupname, groupdesc);
                            role.AddGroup(newgroup);

                            if (sbGroupId.Length == 0)
                            {
                                sbGroupId.Append(String.Format("{0}", newgroup.ID));
                            }
                            else
                            {
                                sbGroupId.Append(String.Format(";{0}", newgroup.ID));
                            }

                        }

                        newgroup.AddUser(user);
                    }
                }

                if (newgroup != null && fix)
                {
                    foreach (SPUser user in newgroup.Users)
                    {
                        try
                        {
                            role.RemoveUser(user);
                        }
                        catch
                        {
                            // We sometimes will fail, because we cannot remove
                            // all users from the administrator role.
                        }
                    }
                }
            }

            if (fix && sbGroupId.Length > 0)
            {
                web.Properties["vti_associategroups"] = sbGroupId.ToString();
                web.Properties.Update();
            }

            return;
        }

        static private void ProcessOneVirtualServer(SPVirtualServer curVS, bool fix)
        {
            SPSiteCollection sites = curVS.Sites;

            if (sites != null)
            {
                foreach (SPSite site in sites)
                {
                    if (site != null)
                    {
                        try
                        {
                            foreach (SPWeb web in site.AllWebs)
                            {
                                int template = web.WebTemplateId;

                                // If we have a Web with a template ID that is
                                //      20, 21, 22, 30, 31, 32, 33, 34, 35, or 36,
                                //   this is an area Web or a bucket Web from
                                //   an SPS 2003 instalation.
                                //  We will be unable to process these Webs because they use 
                                //  an external security provider. The external
                                //  security provider will deliberately return
                                //  ACCESS_DENIED to the WSS security object model. 
                                //  However, it is also unnecessary to process these Webs because
                                //  the SPS 2003 upgrade logic already does the role-to-group conversion.                               if ((template >= 20 && template <= 22) ||
                                    (template >= 30 && template <= 36))
                                {
                                    Console.WriteLine(string.Format("Skipping SPS2003 web {0} ...", web.Url));
                                    continue;
                                }

                                if (web.HasUniquePerm)
                                    ProcessOneWeb(site, web, fix);
                            }
                        }
                        finally
                        {
                            site.Close();
                        }
                    }
                }
            }
        }
    }
}

MORE INFORMATION

For more information about how to upgrade to SharePoint Server 2007, visit the following Microsoft Web site:
http://technet2.microsoft.com/Office/en-us/library/396c85d9-4b86-484e-9cc5-f6c4d725c5781033.mspx?mfr=true (http://technet2.microsoft.com/Office/en-us/library/396c85d9-4b86-484e-9cc5-f6c4d725c5781033.mspx?mfr=true)

APPLIES TO
  • Microsoft Office SharePoint Server 2007
Keywords: 
kbtshoot kbexpertiseinter kbprb KB938110
       

Community Feedback System

Very often, it takes hours to solve a problem. Very often, you've looked high and low, and have tried a lot of solutions. When you finally found it, chances are, it was because someone else helped you. Here's your chance to give back. Use our community feedback tool to let others know what worked for you and what didn't.

Please also understand that the community feedback system is not warranted to be correct, it's simply a system that we've built to let people try and help each other. If something in a feedback response doesn't make sense to you, or you're not comfortable making changes that the feedback talks about (like registry edits), please consult a professional.

Thank you for using kbAlertz.com Feedback System.

-- Scott Cate