Well, I told you before about the challenge I was faced with (migrating users from a foreign domain to an existing domain in Sharepoint) The luck I had was that the usernames were the same, so that only the domainnames were different.
First I had to discover if a user existed on a site and if so, what is the role that this user has. Then I had to add the new user to the site.
So I designed four functions :
1. GetAllWebs (loop through all the portals and sites)
2. GetUser (look for the user)
3. GetGroups (get's the role from the users (eg. reader/contributor)
4. MigrateUser (add the new account with the same securitysettings)
Since I don't have the rights on the frontend server, I could only use webservices. Thus I was confronted by the lack of support to enumerate through all the sites that belong to a portal. The "Webs" webservice only collects the area's from a portal.
So if anyone knows how to get the webs from a portal, I'm all ears ;)
GetAllWebs
private void GetAllWebs(string url)
{
ArrayList list = new ArrayList();
Webs.Webs web = new WebApplication5.Webs.Webs();
web.Url = url + "/_vti_bin/webs.asmx";
web.Credentials = new System.Net.NetworkCredential("username", "password", "domain");
try
{
XmlNode subwebs = web.GetAllSubWebCollection();
foreach(XmlElement item in subwebs.SelectNodes("*"))
{
GetUsers(item.Attributes["Url"].Value.ToString());
}
}
catch(Exception)
{
Response.Write(url + " does not exist");
}
}
GetUsers
private void GetUsers(string url)
{
ArrayList users = new ArrayList();
UserGroup.UserGroup usgrp = new WebApplication5.UserGroup.UserGroup();
usgrp.Url = url + "/_vti_bin/usergroup.asmx";
usgrp.Credentials = new System.Net.NetworkCredential("username", "password", "domain");
XmlNode node = usgrp.GetUserCollectionFromWeb();
foreach(XmlElement item in node.SelectNodes("*"))
{
foreach (XmlElement items in item.SelectNodes("*"))
{
if (items.Attributes["LoginName"].Value.IndexOf("OLDDOMAIN") > -1)
{
Response.Write("" + url + "
");
Response.Write("
" + items.Attributes["Name"].Value.ToString());
Response.Write(" " + items.Attributes["LoginName"].Value.ToString());
Response.Write(" " + items.Attributes["Email"].Value.ToString());
GetGroups(items.Attributes["LoginName"].Value.ToString(), url, items.Attributes["Name"].Value.ToString(), items.Attributes["Email"].Value.ToString());
}
}
}
}
GetGroups
private void GetGroups(string loginname, string url, string username, string email)
{
UserGroup.UserGroup usgrp = new WebApplication5.UserGroup.UserGroup();
usgrp.Url = url + "/_vti_bin/usergroup.asmx";
usgrp.Credentials = new System.Net.NetworkCredential("username", "password", "domain");
try
{
XmlNode node = usgrp.GetRoleCollectionFromUser(loginname);
foreach(XmlElement item in node.SelectNodes("*"))
{
foreach (XmlElement items in item.SelectNodes("*"))
{
Response.Write(" " + items.Attributes["Name"].Value.ToString());
MigrateUser(items.Attributes["Name"].Value.ToString(), username, loginname, email, url);
//users.Add(items.Attributes["LoginName"].Value.ToString());
}
}
}
catch(Exception error)
{
Response.Write("
" + error.Message.ToString());
}
}
MigrateUser
private void MigrateUser(string role, string username, string loginname, string email, string url)
{
UserGroup.UserGroup usgrp = new WebApplication5.UserGroup.UserGroup();
usgrp.Url = url + "/_vti_bin/usergroup.asmx";
usgrp.Credentials = new System.Net.NetworkCredential("username", "password", "domain");
if (loginname.IndexOf("OLDDDOMAIN") > -1)
{
loginname = loginname.Replace("OLDDOMAIN","NEWDOMAIN");
try
{
usgrp.AddUserToRole(role, username, loginname, email, "");
Response.Write(username + " is added with " + role + " right");
}
// catch (Microsoft.SharePoint.SoapServer.SoapServerException soaperr)
// {
// //Response.Write("User cannot be added to the site");
// Response.Write("
" + soaperr.InnerException.Message.ToString());
// }
catch (Exception error)
{
Response.Write("
" + error.Message.ToString());
}
}
}
If all the users are migrated succesfully then I have to write another function to remove the old accounts.
Btw if you are wondering why I haven't used the SPUserUtilSuite from
Keith Richie, it required (although I think it did) to execute the files on the front-end server of the farm. Unfortunatly I did not have that luxury..
Btw.. todo's are : instead of using Response.Write's is to write the results in a nice xml file and have a webservice that collects all the webs from a portal (instead of the areas) :)
Hey - Great code, thank you. I am having an issue using the UserGroup webservice with the NetworkCredentials - works with DefaultCredentials, but not NetworkCredentials. Any thoughts?
ReplyDelete-morna@highstream.net
Excellent! Thanks for this - I've been looking at this feature for ages. Followed your instructions and it works a treat!
ReplyDelete