UserManagementModule.cs 36 KB

12345678910111213141516171819202122232425262728293031323334353637383940414243444546474849505152535455565758596061626364656667686970717273747576777879808182838485868788899091929394959697989910010110210310410510610710810911011111211311411511611711811912012112212312412512612712812913013113213313413513613713813914014114214314414514614714814915015115215315415515615715815916016116216316416516616716816917017117217317417517617717817918018118218318418518618718818919019119219319419519619719819920020120220320420520620720820921021121221321421521621721821922022122222322422522622722822923023123223323423523623723823924024124224324424524624724824925025125225325425525625725825926026126226326426526626726826927027127227327427527627727827928028128228328428528628728828929029129229329429529629729829930030130230330430530630730830931031131231331431531631731831932032132232332432532632732832933033133233333433533633733833934034134234334434534634734834935035135235335435535635735835936036136236336436536636736836937037137237337437537637737837938038138238338438538638738838939039139239339439539639739839940040140240340440540640740840941041141241341441541641741841942042142242342442542642742842943043143243343443543643743843944044144244344444544644744844945045145245345445545645745845946046146246346446546646746846947047147247347447547647747847948048148248348448548648748848949049149249349449549649749849950050150250350450550650750850951051151251351451551651751851952052152252352452552652752852953053153253353453553653753853954054154254354454554654754854955055155255355455555655755855956056156256356456556656756856957057157257357457557657757857958058158258358458558658758858959059159259359459559659759859960060160260360460560660760860961061161261361461561661761861962062162262362462562662762862963063163263363463563663763863964064164264364464564664764864965065165265365465565665765865966066166266366466566666766866967067167267367467567667767867968068168268368468568668768868969069169269369469569669769869970070170270370470570670770870971071171271371471571671771871972072172272372472572672772872973073173273373473573673773873974074174274374474574674774874975075175275375475575675775875976076176276376476576676776876977077177277377477577677777877978078178278378478578678778878979079179279379479579679779879980080180280380480580680780880981081181281381481581681781881982082182282382482582682782882983083183283383483583683783883984084184284384484584684784884985085185285385485585685785885986086186286386486586686786886987087187287387487587687787887988088188288388488588688788888989089189289389489589689789889990090190290390490590690790890991091191291391491591691791891992092192292392492592692792892993093193293393493593693793893994094194294394494594694794894995095195295395495595695795895996096196296396496596696796896997097197297397497597697797897998098198298398498598698798898999099199299399499599699799899910001001100210031004100510061007100810091010101110121013101410151016101710181019102010211022102310241025102610271028102910301031103210331034
  1. /*
  2. * Copyright (c) Contributors, http://opensimulator.org/
  3. * See CONTRIBUTORS.TXT for a full list of copyright holders.
  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. * * Redistributions of source code must retain the above copyright
  8. * notice, this list of conditions and the following disclaimer.
  9. * * Redistributions in binary form must reproduce the above copyright
  10. * notice, this list of conditions and the following disclaimer in the
  11. * documentation and/or other materials provided with the distribution.
  12. * * Neither the name of the OpenSimulator Project nor the
  13. * names of its contributors may be used to endorse or promote products
  14. * derived from this software without specific prior written permission.
  15. *
  16. * THIS SOFTWARE IS PROVIDED BY THE DEVELOPERS ``AS IS'' AND ANY
  17. * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
  18. * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
  19. * DISCLAIMED. IN NO EVENT SHALL THE CONTRIBUTORS BE LIABLE FOR ANY
  20. * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
  21. * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
  22. * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
  23. * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
  24. * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
  25. * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
  26. */
  27. using System;
  28. using System.Collections.Generic;
  29. using System.Collections.Concurrent;
  30. using System.IO;
  31. using System.Reflection;
  32. using System.Threading;
  33. using OpenSim.Framework;
  34. using OpenSim.Framework.Console;
  35. using OpenSim.Region.Framework.Interfaces;
  36. using OpenSim.Region.Framework.Scenes;
  37. using OpenSim.Services.Interfaces;
  38. using OpenSim.Services.Connectors.Hypergrid;
  39. using OpenMetaverse;
  40. using log4net;
  41. using Nini.Config;
  42. using Mono.Addins;
  43. namespace OpenSim.Region.CoreModules.Framework.UserManagement
  44. {
  45. [Extension(Path = "/OpenSim/RegionModules", NodeName = "RegionModule", Id = "UserManagementModule")]
  46. public class UserManagementModule : ISharedRegionModule, IUserManagement, IPeople
  47. {
  48. private const int BADURLEXPIRE = 2 * 60;
  49. private static readonly ILog m_log = LogManager.GetLogger(MethodBase.GetCurrentMethod().DeclaringType);
  50. protected bool m_Enabled;
  51. protected List<Scene> m_Scenes = new List<Scene>();
  52. protected IServiceThrottleModule m_ServiceThrottle;
  53. protected IUserAccountService m_userAccountService = null;
  54. protected IGridUserService m_gridUserService = null;
  55. protected GridInfo m_thisGridInfo;
  56. // The cache
  57. protected ExpiringCacheOS<UUID, UserData> m_userCacheByID = new ExpiringCacheOS<UUID, UserData>(60000);
  58. protected bool m_DisplayChangingHomeURI = false;
  59. UUID m_scopeID = UUID.Zero;
  60. ~UserManagementModule()
  61. {
  62. Dispose(false);
  63. }
  64. private bool disposed = false;
  65. public void Dispose()
  66. {
  67. Dispose(true);
  68. GC.SuppressFinalize(this);
  69. }
  70. private void Dispose(bool disposing)
  71. {
  72. if (!disposed)
  73. {
  74. disposed = true;
  75. m_userCacheByID.Dispose();
  76. m_userCacheByID = null;
  77. }
  78. }
  79. #region ISharedRegionModule
  80. public virtual void Initialise(IConfigSource config)
  81. {
  82. string umanmod = config.Configs["Modules"].GetString("UserManagementModule", Name);
  83. if (umanmod == Name)
  84. {
  85. m_Enabled = true;
  86. Init(config);
  87. m_log.DebugFormat("[USER MANAGEMENT MODULE]: {0} is enabled", Name);
  88. }
  89. }
  90. public virtual bool IsSharedModule
  91. {
  92. get { return true; }
  93. }
  94. public virtual string Name
  95. {
  96. get { return "BasicUserManagementModule"; }
  97. }
  98. public virtual Type ReplaceableInterface
  99. {
  100. get { return null; }
  101. }
  102. public virtual void AddRegion(Scene scene)
  103. {
  104. if (m_Enabled)
  105. {
  106. lock (m_Scenes)
  107. {
  108. m_Scenes.Add(scene);
  109. }
  110. if(m_thisGridInfo == null)
  111. m_thisGridInfo = scene.SceneGridInfo;
  112. scene.RegisterModuleInterface<IUserManagement>(this);
  113. scene.RegisterModuleInterface<IPeople>(this);
  114. scene.EventManager.OnNewClient += EventManager_OnNewClient;
  115. scene.EventManager.OnPrimsLoaded += EventManager_OnPrimsLoaded;
  116. }
  117. }
  118. public virtual void RemoveRegion(Scene scene)
  119. {
  120. if (m_Enabled)
  121. {
  122. scene.UnregisterModuleInterface<IUserManagement>(this);
  123. lock (m_Scenes)
  124. {
  125. m_Scenes.Remove(scene);
  126. }
  127. }
  128. }
  129. public virtual void RegionLoaded(Scene s)
  130. {
  131. if (!m_Enabled)
  132. return;
  133. if(m_ServiceThrottle == null)
  134. m_ServiceThrottle = s.RequestModuleInterface<IServiceThrottleModule>();
  135. if(m_userAccountService == null)
  136. m_userAccountService = s.UserAccountService;
  137. if(m_gridUserService == null)
  138. m_gridUserService = s.GridUserService;
  139. if (s.RegionInfo.ScopeID != UUID.Zero)
  140. m_scopeID = s.RegionInfo.ScopeID;
  141. }
  142. public virtual void PostInitialise()
  143. {
  144. }
  145. public virtual void Close()
  146. {
  147. m_Enabled = false;
  148. lock (m_Scenes)
  149. {
  150. m_Scenes.Clear();
  151. }
  152. m_thisGridInfo = null;
  153. Dispose(false);
  154. }
  155. #endregion ISharedRegionModule
  156. #region Event Handlers
  157. protected virtual void EventManager_OnPrimsLoaded(Scene s)
  158. {
  159. // let's sniff all the user names referenced by objects in the scene
  160. m_log.DebugFormat("[USER MANAGEMENT MODULE]: Caching creators' data from {0} ({1} objects)...", s.RegionInfo.RegionName, s.GetEntities().Length);
  161. s.ForEachSOG(delegate(SceneObjectGroup sog) { CacheCreators(sog); });
  162. }
  163. protected virtual void EventManager_OnNewClient(IClientAPI client)
  164. {
  165. client.OnConnectionClosed += HandleConnectionClosed;
  166. client.OnNameFromUUIDRequest += HandleUUIDNameRequest;
  167. client.OnAvatarPickerRequest += HandleAvatarPickerRequest;
  168. }
  169. protected virtual void HandleConnectionClosed(IClientAPI client)
  170. {
  171. client.OnNameFromUUIDRequest -= HandleUUIDNameRequest;
  172. client.OnAvatarPickerRequest -= HandleAvatarPickerRequest;
  173. client.OnConnectionClosed -= HandleConnectionClosed;
  174. }
  175. protected virtual void HandleUUIDNameRequest(UUID uuid, IClientAPI client)
  176. {
  177. // m_log.DebugFormat(
  178. // "[USER MANAGEMENT MODULE]: Handling request for name binding of UUID {0} from {1}",
  179. // uuid, remote_client.Name);
  180. if(m_Scenes.Count <= 0)
  181. return;
  182. if (m_userCacheByID.TryGetValue(uuid, out UserData user))
  183. {
  184. if (user.HasGridUserTried)
  185. {
  186. client.SendNameReply(uuid, user.FirstName, user.LastName);
  187. return;
  188. }
  189. }
  190. if(m_ServiceThrottle == null)
  191. return;
  192. IClientAPI deferedcli = client;
  193. // Not found in cache, queue continuation
  194. m_ServiceThrottle.Enqueue("uuidname", uuid.ToString(), delegate
  195. {
  196. if(deferedcli.IsActive)
  197. {
  198. if (GetUser(uuid, deferedcli.ScopeId, out UserData defuser))
  199. {
  200. if(deferedcli.IsActive)
  201. deferedcli.SendNameReply(uuid, defuser.FirstName, defuser.LastName);
  202. }
  203. }
  204. deferedcli = null;
  205. });
  206. }
  207. public virtual void HandleAvatarPickerRequest(IClientAPI client, UUID avatarID, UUID RequestID, string query)
  208. {
  209. //EventManager.TriggerAvatarPickerRequest();
  210. m_log.DebugFormat("[USER MANAGEMENT MODULE]: HandleAvatarPickerRequest for {0}", query);
  211. List<UserData> users = GetUserData(query, 500, 1);
  212. client.SendAvatarPickerReply(RequestID, users);
  213. }
  214. public bool CheckUrl(string url, out bool islocal, out Uri uri)
  215. {
  216. islocal = false;
  217. if (string.IsNullOrWhiteSpace(url))
  218. {
  219. uri = null;
  220. islocal = true;
  221. return true;
  222. }
  223. try
  224. {
  225. uri = new Uri(url, UriKind.Absolute);
  226. }
  227. catch
  228. {
  229. uri = null;
  230. islocal = true;
  231. return false;
  232. }
  233. string host = uri.DnsSafeHost.ToLower();
  234. islocal = m_thisGridInfo.IsLocalHome(host) == 1;
  235. return true;
  236. }
  237. protected virtual void AddAdditionalUsers(string query, List<UserData> users, HashSet<UUID> found)
  238. {
  239. }
  240. #endregion Event Handlers
  241. #region IPeople
  242. public virtual UserData GetUserData(UUID id)
  243. {
  244. if(GetUser(id, out UserData u))
  245. return u;
  246. return null;
  247. }
  248. public virtual List<UserData> GetUserData(string query, int page_size, int page_number)
  249. {
  250. if(m_Scenes.Count <= 0 || m_userAccountService == null)
  251. return new List<UserData>();;
  252. var users = new List<UserData>();
  253. var found = new HashSet<UUID>();
  254. // search the user accounts service
  255. if (m_userAccountService != null)
  256. {
  257. List<UserAccount> accs = m_userAccountService.GetUserAccounts(m_scopeID, query);
  258. if (accs != null)
  259. {
  260. for(int i = 0; i < accs.Count; ++i)
  261. {
  262. UserAccount acc = accs[i];
  263. UUID id = acc.PrincipalID;
  264. UserData ud = new UserData();
  265. ud.FirstName = acc.FirstName;
  266. ud.LastName = acc.LastName;
  267. ud.Id = id;
  268. ud.HasGridUserTried = true;
  269. ud.IsUnknownUser = false;
  270. ud.IsLocal = acc.LocalToGrid;
  271. users.Add(ud);
  272. found.Add(id);
  273. }
  274. }
  275. }
  276. // search the local cache
  277. string q = query.ToLower();
  278. foreach (UserData data in m_userCacheByID.Values)
  279. {
  280. if (found.Contains(data.Id))
  281. continue;
  282. if (data.Id == UUID.Zero || data.IsUnknownUser)
  283. continue;
  284. if (data.FirstName.ToLower().StartsWith(q) || data.LastName.ToLower().StartsWith(q))
  285. users.Add(data);
  286. }
  287. AddAdditionalUsers(query, users, found);
  288. return users;
  289. }
  290. #endregion IPeople
  291. protected virtual void CacheCreators(SceneObjectGroup sog)
  292. {
  293. //m_log.DebugFormat("[USER MANAGEMENT MODULE]: processing {0} {1}; {2}", sog.RootPart.Name, sog.RootPart.CreatorData, sog.RootPart.CreatorIdentification);
  294. AddUser(sog.RootPart.CreatorID, sog.RootPart.CreatorData);
  295. foreach (SceneObjectPart sop in sog.Parts)
  296. {
  297. AddUser(sop.CreatorID, sop.CreatorData);
  298. foreach (TaskInventoryItem item in sop.TaskInventory.Values)
  299. AddUser(item.CreatorID, item.CreatorData);
  300. }
  301. }
  302. /// <summary>
  303. ///
  304. /// </summary>
  305. /// <param name="uuid"></param>
  306. /// <param name="names">Caller please provide a properly instantiated array for names, string[2]</param>
  307. /// <returns></returns>
  308. protected virtual bool TryGetUserNames(UUID uuid, string[] names)
  309. {
  310. if (names == null)
  311. names = new string[2];
  312. if(GetUser(uuid, out UserData u))
  313. {
  314. names[0] = u.FirstName;
  315. names[1] = u.LastName;
  316. return true;
  317. }
  318. names[0] = "UnknownUMM3";
  319. names[1] = uuid.ToString();
  320. return false;
  321. }
  322. #region IUserManagement
  323. public virtual UUID GetUserIdByName(string name)
  324. {
  325. string[] parts = name.Split(new string[] { " " }, StringSplitOptions.RemoveEmptyEntries);
  326. if (parts.Length < 2)
  327. throw new Exception("Name must have 2 components");
  328. return GetUserIdByName(parts[0], parts[1]);
  329. }
  330. public virtual UUID GetUserIdByName(string firstName, string lastName)
  331. {
  332. if(m_Scenes.Count <= 0)
  333. return UUID.Zero;
  334. // TODO: Optimize for reverse lookup if this gets used by non-console commands.
  335. foreach (UserData user in m_userCacheByID.Values)
  336. {
  337. if (user.FirstName.Equals(firstName, StringComparison.InvariantCultureIgnoreCase) &&
  338. user.LastName.Equals(lastName, StringComparison.InvariantCultureIgnoreCase))
  339. return user.Id;
  340. }
  341. if(m_userAccountService != null)
  342. {
  343. UserAccount account = m_userAccountService.GetUserAccount(UUID.Zero, firstName, lastName);
  344. if (account != null)
  345. {
  346. AddUser(account);
  347. return account.PrincipalID;
  348. }
  349. }
  350. return UUID.Zero;
  351. }
  352. public virtual string GetUserName(UUID uuid)
  353. {
  354. if(GetUser(uuid, out UserData user))
  355. return user.FirstName + " " + user.LastName;
  356. return "UnknownUMM2 " + uuid.ToString();
  357. }
  358. public virtual Dictionary<UUID,string> GetUsersNames(string[] ids, UUID scopeID)
  359. {
  360. Dictionary<UUID,string> ret = new Dictionary<UUID,string>();
  361. if(m_Scenes.Count <= 0)
  362. return ret;
  363. UserData userdata = new UserData();
  364. UUID uuid = UUID.Zero;
  365. foreach(string id in ids)
  366. {
  367. if(UUID.TryParse(id, out uuid))
  368. {
  369. if (GetUser(uuid, out userdata))
  370. ret[uuid] = userdata.FirstName + " " + userdata.LastName;
  371. else
  372. ret[uuid] = "Unknown " + uuid.ToString() + "UMM1";
  373. }
  374. }
  375. return ret;
  376. }
  377. public virtual string GetUserHomeURL(UUID userID)
  378. {
  379. if (GetUser(userID, out UserData user) && user != null)
  380. {
  381. if (user.LastWebFail > 0 && Util.GetTimeStamp() - user.LastWebFail > BADURLEXPIRE)
  382. user.LastWebFail = -1;
  383. return user.HomeURL;
  384. }
  385. return string.Empty;
  386. }
  387. public virtual string GetUserHomeURL(UUID userID, out bool recentFail)
  388. {
  389. recentFail = false;
  390. if (GetUser(userID, out UserData user))
  391. {
  392. if (user.LastWebFail > 0)
  393. {
  394. if (Util.GetTimeStamp() - user.LastWebFail > BADURLEXPIRE)
  395. user.LastWebFail = -1;
  396. else
  397. recentFail = true;
  398. }
  399. return user.HomeURL;
  400. }
  401. return string.Empty;
  402. }
  403. public virtual string GetUserServerURL(UUID userID, string serverType)
  404. {
  405. UserData userdata;
  406. if(!GetUser(userID, out userdata))
  407. return string.Empty;
  408. if(userdata.IsLocal)
  409. return string.Empty;
  410. if(userdata.LastWebFail > 0)
  411. {
  412. if(Util.GetTimeStamp() - userdata.LastWebFail > BADURLEXPIRE) // 5 minutes
  413. return string.Empty;
  414. userdata.LastWebFail = -1;
  415. }
  416. if (userdata.ServerURLs != null)
  417. {
  418. if(userdata.ServerURLs.ContainsKey(serverType) && userdata.ServerURLs[serverType] != null)
  419. return userdata.ServerURLs[serverType].ToString();
  420. else
  421. return string.Empty;
  422. }
  423. if (!string.IsNullOrEmpty(userdata.HomeURL))
  424. {
  425. string homeuri = userdata.HomeURL.ToLower();
  426. if (!WebUtil.GlobalExpiringBadURLs.ContainsKey(homeuri))
  427. {
  428. //m_log.DebugFormat("[USER MANAGEMENT MODULE]: Requested url type {0} for {1}", serverType, userID);
  429. UserAgentServiceConnector uConn = new UserAgentServiceConnector(homeuri);
  430. try
  431. {
  432. userdata.ServerURLs = uConn.GetServerURLs(userID);
  433. }
  434. catch(System.Net.WebException e)
  435. {
  436. m_log.DebugFormat("[USER MANAGEMENT MODULE]: GetServerURLs call failed {0}", e.Message);
  437. WebUtil.GlobalExpiringBadURLs.Add(homeuri, BADURLEXPIRE * 1000);
  438. userdata.ServerURLs = new Dictionary<string, object>();
  439. }
  440. catch (Exception e)
  441. {
  442. m_log.Debug("[USER MANAGEMENT MODULE]: GetServerURLs call failed ", e);
  443. userdata.ServerURLs = new Dictionary<string, object>();
  444. }
  445. if (userdata.ServerURLs != null && userdata.ServerURLs.TryGetValue(serverType, out object ourl) && ourl != null)
  446. return ourl.ToString();
  447. }
  448. }
  449. return string.Empty;
  450. }
  451. public void UserWebFailed(UUID id)
  452. {
  453. if(m_userCacheByID.TryGetValue(id, out UserData u))
  454. u.LastWebFail = Util.GetTimeStamp();
  455. }
  456. public virtual string GetUserServerURL(UUID userID, string serverType, out bool recentFail)
  457. {
  458. recentFail = false;
  459. if (!GetUser(userID, out UserData userdata))
  460. return string.Empty;
  461. if (userdata.IsLocal)
  462. return string.Empty;
  463. if (userdata.LastWebFail > 0)
  464. {
  465. if (Util.GetTimeStamp() - userdata.LastWebFail > BADURLEXPIRE)
  466. recentFail = true;
  467. else
  468. userdata.LastWebFail = -1;
  469. }
  470. if (userdata.ServerURLs != null)
  471. {
  472. if (userdata.ServerURLs.ContainsKey(serverType) && userdata.ServerURLs[serverType] != null)
  473. return userdata.ServerURLs[serverType].ToString();
  474. else
  475. return string.Empty;
  476. }
  477. if (!recentFail && !string.IsNullOrEmpty(userdata.HomeURL))
  478. {
  479. string homeurl = userdata.HomeURL.ToLower();
  480. if(!WebUtil.GlobalExpiringBadURLs.ContainsKey(homeurl))
  481. {
  482. //m_log.DebugFormat("[USER MANAGEMENT MODULE]: Requested url type {0} for {1}", serverType, userID);
  483. UserAgentServiceConnector uConn = new UserAgentServiceConnector(homeurl);
  484. try
  485. {
  486. userdata.ServerURLs = uConn.GetServerURLs(userID);
  487. }
  488. catch (System.Net.WebException e)
  489. {
  490. m_log.DebugFormat("[USER MANAGEMENT MODULE]: GetServerURLs call failed {0}", e.Message);
  491. userdata.ServerURLs = new Dictionary<string, object>();
  492. userdata.LastWebFail = Util.GetTimeStamp();
  493. WebUtil.GlobalExpiringBadURLs.Add(homeurl, BADURLEXPIRE * 1000);
  494. recentFail = true;
  495. }
  496. catch (Exception e)
  497. {
  498. m_log.Debug("[USER MANAGEMENT MODULE]: GetServerURLs call failed ", e);
  499. userdata.ServerURLs = new Dictionary<string, object>();
  500. userdata.LastWebFail = Util.GetTimeStamp();
  501. recentFail = true;
  502. }
  503. if (userdata.ServerURLs != null && userdata.ServerURLs.ContainsKey(serverType) && userdata.ServerURLs[serverType] != null)
  504. return userdata.ServerURLs[serverType].ToString();
  505. }
  506. }
  507. return string.Empty;
  508. }
  509. public virtual string GetUserUUI(UUID userID)
  510. {
  511. string uui;
  512. GetUserUUI(userID, out uui);
  513. return uui;
  514. }
  515. public virtual bool GetUserUUI(UUID userID, out string uui)
  516. {
  517. bool result = GetUser(userID, out UserData ud);
  518. if (ud != null)
  519. {
  520. string homeURL = ud.HomeURL;
  521. string first = ud.FirstName, last = ud.LastName;
  522. if (ud.LastName.StartsWith("@"))
  523. {
  524. string[] parts = ud.FirstName.Split('.');
  525. if (parts.Length >= 2)
  526. {
  527. first = parts[0];
  528. last = parts[1];
  529. }
  530. uui = userID + ";" + homeURL + ";" + first + " " + last;
  531. return result;
  532. }
  533. }
  534. uui = userID.ToString();
  535. return result;
  536. }
  537. #region Cache Management
  538. public virtual bool GetUser(UUID uuid, out UserData userdata)
  539. {
  540. return GetUser(uuid, m_scopeID, out userdata);
  541. }
  542. public virtual bool GetUser(UUID uuid, UUID scopeID, out UserData userdata)
  543. {
  544. if (m_Scenes.Count <= 0)
  545. {
  546. userdata = new UserData();
  547. return false;
  548. }
  549. if (m_userCacheByID.TryGetValue(uuid, out userdata))
  550. {
  551. if (userdata.HasGridUserTried)
  552. return true;
  553. }
  554. else
  555. {
  556. userdata = new UserData();
  557. userdata.Id = uuid;
  558. userdata.FirstName = "Unknown";
  559. userdata.LastName = uuid.ToString();
  560. userdata.HomeURL = string.Empty;
  561. userdata.IsUnknownUser = true;
  562. userdata.HasGridUserTried = false;
  563. }
  564. if (!userdata.HasGridUserTried)
  565. {
  566. /* rewrite here */
  567. UserAccount account = m_userAccountService.GetUserAccount(scopeID, uuid);
  568. if (account != null)
  569. {
  570. userdata.FirstName = account.FirstName;
  571. userdata.LastName = account.LastName;
  572. userdata.HomeURL = string.Empty;
  573. userdata.IsUnknownUser = false;
  574. userdata.IsLocal = true;
  575. userdata.HasGridUserTried = true;
  576. AddUser(account);
  577. }
  578. }
  579. if (!userdata.HasGridUserTried)
  580. {
  581. GridUserInfo uInfo = null;
  582. if (null != m_gridUserService)
  583. {
  584. uInfo = m_gridUserService.GetGridUserInfo(uuid.ToString());
  585. }
  586. if (uInfo != null)
  587. {
  588. string url, first, last, tmp;
  589. UUID u;
  590. if (uInfo.UserID.Length >= 36 && Util.ParseUniversalUserIdentifier(uInfo.UserID, out u, out url, out first, out last, out tmp))
  591. {
  592. bool islocal;
  593. Uri uri;
  594. bool isvalid = CheckUrl(url, out islocal, out uri);
  595. if (isvalid)
  596. {
  597. if(islocal)
  598. {
  599. userdata.FirstName = first;
  600. userdata.LastName = last;
  601. userdata.HomeURL = string.Empty;
  602. userdata.IsLocal = true;
  603. userdata.IsUnknownUser = false;
  604. }
  605. else
  606. {
  607. userdata.FirstName = first.Replace(" ", ".") + "." + last.Replace(" ", ".");
  608. userdata.HomeURL = uri.AbsoluteUri;
  609. userdata.LastName = "@" + uri.Authority;
  610. userdata.IsLocal = false;
  611. userdata.IsUnknownUser = false;
  612. }
  613. }
  614. }
  615. else
  616. m_log.DebugFormat("[USER MANAGEMENT MODULE]: Unable to parse UUI {0}", uInfo.UserID);
  617. }
  618. userdata.HasGridUserTried = true;
  619. }
  620. /* END: do not wrap this code in any lock here */
  621. return !userdata.IsUnknownUser;
  622. }
  623. public void AddUser(UserAccount account)
  624. {
  625. UUID id = account.PrincipalID;
  626. if (!m_userCacheByID.ContainsKey(id))
  627. {
  628. UserData user = new UserData();
  629. user.Id = id;
  630. user.FirstName = account.FirstName;
  631. user.LastName = account.LastName;
  632. user.HomeURL = string.Empty;
  633. user.IsUnknownUser = false;
  634. user.HasGridUserTried = true;
  635. user.IsLocal = account.LocalToGrid;
  636. m_userCacheByID.Add(id, user, 1800000);
  637. }
  638. }
  639. public virtual void AddUser(UUID uuid, string first, string last, bool isNPC = false, int expire = 1800000)
  640. {
  641. if (!m_userCacheByID.ContainsKey(uuid))
  642. {
  643. UserData user = new UserData();
  644. user.Id = uuid;
  645. user.FirstName = first;
  646. user.LastName = last;
  647. user.HasGridUserTried = isNPC;
  648. if (!isNPC && last.StartsWith("@"))
  649. {
  650. string url = last.Substring(1);
  651. bool local;
  652. Uri uri;
  653. if(CheckUrl(url, out local, out uri))
  654. {
  655. if(local)
  656. {
  657. user.IsLocal = true;
  658. user.HomeURL = string.Empty;
  659. user.HasGridUserTried = true;
  660. }
  661. else
  662. {
  663. user.IsLocal = false;
  664. user.HomeURL = uri.AbsoluteUri;
  665. user.HasGridUserTried = false;
  666. }
  667. user.IsUnknownUser = false;
  668. }
  669. }
  670. else
  671. {
  672. user.IsUnknownUser = false;
  673. user.IsLocal = true;
  674. user.HasGridUserTried = true;
  675. }
  676. m_userCacheByID.Add(uuid, user, isNPC ? int.MaxValue / 16 : expire);
  677. }
  678. }
  679. public virtual void AddUser(UUID uuid, string first, string last, string homeURL)
  680. {
  681. //m_log.DebugFormat("[USER MANAGEMENT MODULE]: Adding user with id {0}, first {1}, last {2}, url {3}", uuid, first, last, homeURL);
  682. UserData oldUser;
  683. if (m_userCacheByID.TryGetValue(uuid, out oldUser))
  684. {
  685. if (!oldUser.IsUnknownUser)
  686. {
  687. if (homeURL != oldUser.HomeURL && m_DisplayChangingHomeURI)
  688. {
  689. m_log.DebugFormat("[USER MANAGEMENT MODULE]: Different HomeURI for {0} {1} ({2}): {3} and {4}",
  690. first, last, uuid.ToString(), homeURL, oldUser.HomeURL);
  691. }
  692. /* no update needed */
  693. return;
  694. }
  695. }
  696. oldUser = new UserData();
  697. oldUser.Id = uuid;
  698. oldUser.HasGridUserTried = false;
  699. oldUser.IsUnknownUser = false;
  700. bool local;
  701. Uri uri;
  702. if (CheckUrl(homeURL, out local, out uri))
  703. {
  704. if (local)
  705. {
  706. oldUser.FirstName = first;
  707. oldUser.LastName = last;
  708. oldUser.IsLocal = true;
  709. oldUser.HomeURL = string.Empty;
  710. oldUser.HasGridUserTried = true;
  711. }
  712. else
  713. {
  714. oldUser.FirstName = first.Replace(" ", ".") + "." + last.Replace(" ", ".");
  715. oldUser.LastName = "@" + uri.Authority;
  716. oldUser.HomeURL = uri.AbsoluteUri;
  717. oldUser.IsLocal = false;
  718. }
  719. }
  720. else
  721. {
  722. oldUser.FirstName = first.Replace(" ", ".") + "." + last.Replace(" ", ".");
  723. oldUser.LastName = "UMMM0Unknown";
  724. oldUser.IsLocal = true;
  725. oldUser.HomeURL = string.Empty;
  726. oldUser.HasGridUserTried = true;
  727. oldUser.IsUnknownUser = true;
  728. }
  729. m_userCacheByID.Add(uuid, oldUser, 300000);
  730. }
  731. public virtual void AddUser(UUID id, string creatorData)
  732. {
  733. // m_log.InfoFormat("[USER MANAGEMENT MODULE]: Adding user with id {0}, creatorData {1}", id, creatorData);
  734. if(string.IsNullOrEmpty(creatorData))
  735. return;
  736. if(m_userCacheByID.ContainsKey(id))
  737. return;
  738. string homeURL;
  739. string firstname = string.Empty;
  740. string lastname = string.Empty;
  741. //creatorData = <endpoint>;<name>
  742. string[] parts = creatorData.Split(';');
  743. if(parts.Length > 1)
  744. {
  745. string[] nameparts = parts[1].Split(' ');
  746. if(nameparts.Length < 2)
  747. return;
  748. firstname = nameparts[0];
  749. for(int xi = 1; xi < nameparts.Length; ++xi)
  750. {
  751. if(xi != 1)
  752. {
  753. lastname += " ";
  754. }
  755. lastname += nameparts[xi];
  756. }
  757. if (string.IsNullOrWhiteSpace(firstname))
  758. return;
  759. if (string.IsNullOrWhiteSpace(lastname))
  760. return;
  761. }
  762. else
  763. return;
  764. homeURL = parts[0];
  765. if(homeURL.Length > 10)
  766. {
  767. string test = homeURL.Substring(10);
  768. int indx = test.IndexOf("/");
  769. if(indx > 0 && indx != test.Length - 1)
  770. homeURL = homeURL.Substring(0, indx + 10);
  771. }
  772. bool local;
  773. Uri uri;
  774. var oldUser = new UserData();
  775. oldUser.Id = id;
  776. oldUser.HasGridUserTried = false;
  777. oldUser.IsUnknownUser = false;
  778. if (CheckUrl(homeURL, out local, out uri))
  779. {
  780. if (local)
  781. {
  782. oldUser.FirstName = firstname;
  783. oldUser.LastName = lastname;
  784. oldUser.IsLocal = true;
  785. oldUser.HomeURL = string.Empty;
  786. oldUser.HasGridUserTried = true;
  787. }
  788. else
  789. {
  790. oldUser.FirstName = firstname + "." + lastname.Replace(" ", ".");
  791. oldUser.LastName = "@" + uri.Authority;
  792. oldUser.HomeURL = uri.AbsoluteUri;
  793. oldUser.IsLocal = false;
  794. }
  795. }
  796. else
  797. {
  798. oldUser.FirstName = firstname + "." + lastname.Replace(" ", ".");
  799. oldUser.LastName = "UMMM1Unknown";
  800. oldUser.IsLocal = true;
  801. oldUser.HomeURL = string.Empty;
  802. oldUser.HasGridUserTried = true;
  803. oldUser.IsUnknownUser = true;
  804. }
  805. m_userCacheByID.Add(id, oldUser, int.MaxValue / 16);
  806. }
  807. public bool RemoveUser(UUID uuid)
  808. {
  809. return m_userCacheByID.Remove(uuid);
  810. }
  811. #endregion
  812. public virtual bool IsLocalGridUser(UUID uuid)
  813. {
  814. if (m_Scenes.Count <= 0)
  815. return true;
  816. if (m_userCacheByID.TryGetValue(uuid, out UserData u))
  817. {
  818. if (u.HasGridUserTried)
  819. return u.IsLocal;
  820. }
  821. if(m_userAccountService == null)
  822. return true;
  823. UserAccount account = m_userAccountService.GetUserAccount(m_Scenes[0].RegionInfo.ScopeID, uuid);
  824. if (account == null)
  825. return false;
  826. if(u == null)
  827. AddUser(account);
  828. else
  829. u.HasGridUserTried = true;
  830. return true;
  831. }
  832. #endregion IUserManagement
  833. protected virtual void Init(IConfigSource config)
  834. {
  835. AddUser(UUID.Zero, "Unknown", "User", false, int.MaxValue / 16);
  836. AddUser(Constants.m_MrOpenSimID, "Mr", "Opensim", false, int.MaxValue / 16);
  837. RegisterConsoleCmds();
  838. IConfig userManagementConfig = config.Configs["UserManagement"];
  839. if (userManagementConfig != null)
  840. m_DisplayChangingHomeURI = userManagementConfig.GetBoolean("DisplayChangingHomeURI", false);
  841. }
  842. protected virtual void RegisterConsoleCmds()
  843. {
  844. MainConsole.Instance.Commands.AddCommand("Users", true,
  845. "show name",
  846. "show name <uuid>",
  847. "Show the bindings between a single user UUID and a user name",
  848. String.Empty,
  849. HandleShowUser);
  850. MainConsole.Instance.Commands.AddCommand("Users", true,
  851. "show names",
  852. "show names",
  853. "Show the bindings between user UUIDs and user names",
  854. String.Empty,
  855. HandleShowUsers);
  856. MainConsole.Instance.Commands.AddCommand("Users", true,
  857. "reset user cache",
  858. "reset user cache",
  859. "reset user cache to allow changed settings to be applied",
  860. String.Empty,
  861. HandleResetUserCache);
  862. }
  863. protected virtual void HandleResetUserCache(string module, string[] cmd)
  864. {
  865. lock(m_userCacheByID)
  866. {
  867. m_userCacheByID.Clear();
  868. }
  869. }
  870. protected virtual void HandleShowUser(string module, string[] cmd)
  871. {
  872. if (cmd.Length < 3)
  873. {
  874. MainConsole.Instance.Output("Usage: show name <uuid>");
  875. return;
  876. }
  877. UUID userId;
  878. if (!ConsoleUtil.TryParseConsoleUuid(MainConsole.Instance, cmd[2], out userId))
  879. return;
  880. UserData ud;
  881. if(!GetUser(userId, out ud))
  882. {
  883. MainConsole.Instance.Output("No name known for user with id {0}", userId);
  884. return;
  885. }
  886. ConsoleDisplayTable cdt = new ConsoleDisplayTable();
  887. cdt.AddColumn("UUID", 36);
  888. cdt.AddColumn("Name", 30);
  889. cdt.AddColumn("HomeURL", 40);
  890. cdt.AddRow(userId, string.Format("{0} {1}", ud.FirstName, ud.LastName), ud.HomeURL);
  891. MainConsole.Instance.Output(cdt.ToString());
  892. }
  893. protected virtual void HandleShowUsers(string module, string[] cmd)
  894. {
  895. ConsoleDisplayTable cdt = new ConsoleDisplayTable();
  896. cdt.AddColumn("UUID", 36);
  897. cdt.AddColumn("Name", 30);
  898. cdt.AddColumn("HomeURL", 40);
  899. cdt.AddColumn("Checked", 10);
  900. ICollection<UserData> copy = m_userCacheByID.Values;
  901. foreach(UserData u in copy)
  902. {
  903. cdt.AddRow(u.Id, string.Format("{0} {1}", u.FirstName, u.LastName), u.HomeURL, u.HasGridUserTried ? "yes" : "no");
  904. }
  905. MainConsole.Instance.Output(cdt.ToString());
  906. }
  907. }
  908. }