PageRenderTime 54ms CodeModel.GetById 20ms RepoModel.GetById 1ms app.codeStats 0ms

/RobustMigration/0.7.0/UserMigration.cs

https://github.com/openmetaversefoundation/simiangrid
C# | 286 lines | 210 code | 42 blank | 34 comment | 35 complexity | e6a9cdc5405840810a3d5c4e3aa8db89 MD5 | raw file
  1. /*
  2. * Copyright (c) 2010 Open Metaverse Foundation
  3. * All rights reserved.
  4. *
  5. * - Redistribution and use in source and binary forms, with or without
  6. * modification, are permitted provided that the following conditions are met:
  7. *
  8. * - Redistributions of source code must retain the above copyright notice, this
  9. * list of conditions and the following disclaimer.
  10. * - Neither the name of the openmetaverse.org nor the names
  11. * of its contributors may be used to endorse or promote products derived from
  12. * this software without specific prior written permission.
  13. *
  14. * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
  15. * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
  16. * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
  17. * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE
  18. * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
  19. * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
  20. * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
  21. * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
  22. * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
  23. * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
  24. * POSSIBILITY OF SUCH DAMAGE.
  25. */
  26. using System;
  27. using System.Collections.Generic;
  28. using System.Collections.Specialized;
  29. using System.Linq;
  30. using MySql.Data.MySqlClient;
  31. using OpenMetaverse;
  32. using OpenMetaverse.StructuredData;
  33. namespace RobustMigration.v070
  34. {
  35. public class UserMigration
  36. {
  37. private const string USER_ACCOUNT_TYPE = "UserAccount";
  38. private const string AP_PREFIX = "_ap_";
  39. private static readonly HashSet<string> ALLOWED_APPEARANCE_ENTRIES = new HashSet<string>
  40. {
  41. "Height",
  42. "ShapeAsset",
  43. "ShapeItem",
  44. "EyesAsset",
  45. "EyesItem",
  46. "GlovesAsset",
  47. "GlovesItem",
  48. "HairAsset",
  49. "HairItem",
  50. "JacketAsset",
  51. "JacketItem",
  52. "PantsAsset",
  53. "PantsItem",
  54. "ShirtAsset",
  55. "ShirtItem",
  56. "ShoesAsset",
  57. "ShoesItem",
  58. "SkinAsset",
  59. "SkinItem",
  60. "SkirtAsset",
  61. "SkirtItem",
  62. "SocksAsset",
  63. "SocksItem",
  64. "UnderpantsAsset",
  65. "UnderpantsItem",
  66. "UndershirtAsset",
  67. "UndershirtItem"
  68. };
  69. private MySqlConnection m_connection;
  70. private opensim m_db;
  71. private string m_userUrl;
  72. private bool m_masterUserSet;
  73. public UserMigration(string connectString, string userServiceUrl, string gridOwner)
  74. {
  75. using (m_connection = new MySqlConnection(connectString))
  76. {
  77. using (m_db = new opensim(m_connection))
  78. {
  79. m_userUrl = userServiceUrl;
  80. m_userUrl = userServiceUrl;
  81. var users = from u in m_db.useraccounts
  82. select u;
  83. foreach (var user in users)
  84. {
  85. CreateUser(user, gridOwner);
  86. Console.Write("+");
  87. }
  88. }
  89. }
  90. if (!m_masterUserSet)
  91. Console.WriteLine("No grid owner set. You should manually assign one user to have an access level of 255 in the database");
  92. }
  93. private void CreateUser(useraccounts user, string gridOwner)
  94. {
  95. // Create this user
  96. string name = user.FirstName + " " + user.LastName;
  97. string email = user.Email;
  98. // If this is the grid owner set them to the maximum AccessLevel. Otherwise, make sure
  99. // their AccessLevel is at least 1 (representing a verified, non-anonymous account)
  100. int accessLevel = (!String.IsNullOrEmpty(gridOwner) && name.Equals(gridOwner, StringComparison.InvariantCultureIgnoreCase))
  101. ? 255
  102. : user.UserLevel;
  103. accessLevel = Utils.Clamp(accessLevel, 1, 255);
  104. if (accessLevel == 255)
  105. m_masterUserSet = true;
  106. // Cannot have an empty e-mail address
  107. if (String.IsNullOrEmpty(email))
  108. email = "INVALID " + UUID.Random().ToString();
  109. NameValueCollection requestArgs = new NameValueCollection
  110. {
  111. { "RequestMethod", "AddUser" },
  112. { "UserID", user.PrincipalID },
  113. { "Name", name },
  114. { "Email", email },
  115. { "AccessLevel", accessLevel.ToString() }
  116. };
  117. OSDMap response = WebUtil.PostToService(m_userUrl, requestArgs);
  118. if (response["Success"].AsBoolean())
  119. {
  120. Dictionary<string, string> userData = new Dictionary<string,string>
  121. {
  122. { "CreationDate", (user.Created.HasValue ? user.Created.Value : (int)Utils.DateTimeToUnixTime(DateTime.UtcNow)).ToString() },
  123. { "UserFlags", user.UserFlags.ToString() },
  124. { "UserTitle", user.UserTitle }
  125. };
  126. AddUserData(user.PrincipalID, userData);
  127. }
  128. else
  129. {
  130. Console.WriteLine("Failed to store user account for " + name + ": " + response["Message"].AsString());
  131. }
  132. AddLocations(user);
  133. AddAppearance(user);
  134. AddIdentity(user);
  135. }
  136. private void AddLocations(useraccounts user)
  137. {
  138. // Home and last location
  139. var locations = m_db.griduser.SingleOrDefault(g => g.UserID == user.PrincipalID);
  140. if (locations != null)
  141. {
  142. Vector3 homePosition, homeLookAt, lastPosition, lastLookAt;
  143. UUID homeRegionID, lastRegionID;
  144. Vector3.TryParse(locations.HomePosition, out homePosition);
  145. Vector3.TryParse(locations.HomeLookAt, out homeLookAt);
  146. UUID.TryParse(locations.HomeRegionID, out homeRegionID);
  147. Vector3.TryParse(locations.LastPosition, out lastPosition);
  148. Vector3.TryParse(locations.LastLookAt, out lastLookAt);
  149. UUID.TryParse(locations.LastRegionID, out lastRegionID);
  150. Dictionary<string, string> userData = new Dictionary<string,string>();
  151. if (homeRegionID != UUID.Zero)
  152. userData["HomeLocation"] = SerializeLocation(homeRegionID, homePosition, homeLookAt);
  153. if (lastRegionID != UUID.Zero)
  154. userData["LastLocation"] = SerializeLocation(lastRegionID, lastPosition, lastLookAt);
  155. if (userData.Count > 0)
  156. AddUserData(user.PrincipalID, userData);
  157. }
  158. }
  159. private void AddAppearance(useraccounts user)
  160. {
  161. // Avatar appearance
  162. var metadata = from a in m_db.avatars
  163. where a.PrincipalID == user.PrincipalID
  164. select a;
  165. OSDMap appearance = new OSDMap();
  166. OSDMap attachments = new OSDMap();
  167. foreach (var entry in metadata)
  168. {
  169. if (entry.Name.StartsWith(AP_PREFIX))
  170. {
  171. attachments[entry.Name] = OSD.FromString(entry.Value);
  172. }
  173. else
  174. {
  175. string name = entry.Name;
  176. if (name == "AvatarHeight") name = "Height";
  177. if (name == "BodyItem") name = "ShapeItem";
  178. if (name == "BodyAsset") name = "ShapeAsset";
  179. if (ALLOWED_APPEARANCE_ENTRIES.Contains(name))
  180. appearance[name] = OSD.FromString(entry.Value);
  181. }
  182. }
  183. Dictionary<string, string> userData = new Dictionary<string, string>();
  184. if (appearance.Count > 0)
  185. userData["LLAppearance"] = OSDParser.SerializeJsonString(appearance);
  186. if (attachments.Count > 0)
  187. userData["LLAttachments"] = OSDParser.SerializeJsonString(attachments);
  188. if (userData.Count > 0)
  189. AddUserData(user.PrincipalID, userData);
  190. }
  191. private void AddIdentity(useraccounts user)
  192. {
  193. string name = user.FirstName + " " + user.LastName;
  194. // Create the user identity
  195. var auth = m_db.auth.SingleOrDefault(a => a.UUID == user.PrincipalID);
  196. if (auth != null && auth.accountType == USER_ACCOUNT_TYPE)
  197. {
  198. string credential = auth.passwordHash;
  199. // If the password is actually salted store "hash:salt"
  200. if (!String.IsNullOrEmpty(auth.passwordSalt))
  201. credential += ":" + auth.passwordSalt;
  202. // Make sure $1$ is prepended (our md5hash format in SimianGrid requires this)
  203. if (!credential.StartsWith("$1$"))
  204. credential = "$1$" + credential;
  205. NameValueCollection requestArgs = new NameValueCollection
  206. {
  207. { "RequestMethod", "AddIdentity" },
  208. { "Identifier", name },
  209. { "Credential", credential },
  210. { "Type", "md5hash" },
  211. { "UserID", user.PrincipalID }
  212. };
  213. OSDMap response = WebUtil.PostToService(m_userUrl, requestArgs);
  214. bool success = response["Success"].AsBoolean();
  215. Console.Write(".");
  216. if (!success)
  217. Console.WriteLine("Failed to set password for {0} ({1})", name, user.PrincipalID);
  218. }
  219. else
  220. {
  221. Console.WriteLine("No authorization info found for " + name);
  222. }
  223. }
  224. private void AddUserData(string userID, Dictionary<string, string> data)
  225. {
  226. NameValueCollection requestArgs = new NameValueCollection
  227. {
  228. { "RequestMethod", "AddUserData" },
  229. { "UserID", userID }
  230. };
  231. foreach (KeyValuePair<string, string> kvp in data)
  232. requestArgs[kvp.Key] = kvp.Value;
  233. OSDMap response = WebUtil.PostToService(m_userUrl, requestArgs);
  234. bool success = response["Success"].AsBoolean();
  235. Console.Write(".");
  236. if (!success)
  237. Console.WriteLine("Failed to store user data for " + userID + ": " + response["Message"].AsString());
  238. }
  239. private static string SerializeLocation(UUID regionID, Vector3 position, Vector3 lookAt)
  240. {
  241. return "{" + String.Format("\"SceneID\":\"{0}\",\"Position\":\"{1}\",\"LookAt\":\"{2}\"", regionID, position, lookAt) + "}";
  242. }
  243. }
  244. }