UserManagementModule.cs 50 KB

1234567891011121314151617181920212223242526272829303132333435363738394041424344454647484950515253545556575859606162636465666768697071727374757677787980818283848586878889909192939495969798991001011021031041051061071081091101111121131141151161171181191201211221231241251261271281291301311321331341351361371381391401411421431441451461471481491501511521531541551561571581591601611621631641651661671681691701711721731741751761771781791801811821831841851861871881891901911921931941951961971981992002012022032042052062072082092102112122132142152162172182192202212222232242252262272282292302312322332342352362372382392402412422432442452462472482492502512522532542552562572582592602612622632642652662672682692702712722732742752762772782792802812822832842852862872882892902912922932942952962972982993003013023033043053063073083093103113123133143153163173183193203213223233243253263273283293303313323333343353363373383393403413423433443453463473483493503513523533543553563573583593603613623633643653663673683693703713723733743753763773783793803813823833843853863873883893903913923933943953963973983994004014024034044054064074084094104114124134144154164174184194204214224234244254264274284294304314324334344354364374384394404414424434444454464474484494504514524534544554564574584594604614624634644654664674684694704714724734744754764774784794804814824834844854864874884894904914924934944954964974984995005015025035045055065075085095105115125135145155165175185195205215225235245255265275285295305315325335345355365375385395405415425435445455465475485495505515525535545555565575585595605615625635645655665675685695705715725735745755765775785795805815825835845855865875885895905915925935945955965975985996006016026036046056066076086096106116126136146156166176186196206216226236246256266276286296306316326336346356366376386396406416426436446456466476486496506516526536546556566576586596606616626636646656666676686696706716726736746756766776786796806816826836846856866876886896906916926936946956966976986997007017027037047057067077087097107117127137147157167177187197207217227237247257267277287297307317327337347357367377387397407417427437447457467477487497507517527537547557567577587597607617627637647657667677687697707717727737747757767777787797807817827837847857867877887897907917927937947957967977987998008018028038048058068078088098108118128138148158168178188198208218228238248258268278288298308318328338348358368378388398408418428438448458468478488498508518528538548558568578588598608618628638648658668678688698708718728738748758768778788798808818828838848858868878888898908918928938948958968978988999009019029039049059069079089099109119129139149159169179189199209219229239249259269279289299309319329339349359369379389399409419429439449459469479489499509519529539549559569579589599609619629639649659669679689699709719729739749759769779789799809819829839849859869879889899909919929939949959969979989991000100110021003100410051006100710081009101010111012101310141015101610171018101910201021102210231024102510261027102810291030103110321033103410351036103710381039104010411042104310441045104610471048104910501051105210531054105510561057105810591060106110621063106410651066106710681069107010711072107310741075107610771078107910801081108210831084108510861087108810891090109110921093109410951096109710981099110011011102110311041105110611071108110911101111111211131114111511161117111811191120112111221123112411251126112711281129113011311132113311341135113611371138113911401141114211431144114511461147114811491150115111521153115411551156115711581159116011611162116311641165116611671168116911701171117211731174117511761177117811791180118111821183118411851186118711881189119011911192119311941195119611971198119912001201120212031204120512061207120812091210121112121213121412151216121712181219122012211222122312241225122612271228122912301231123212331234123512361237123812391240124112421243124412451246124712481249125012511252125312541255125612571258125912601261126212631264126512661267126812691270127112721273127412751276127712781279128012811282128312841285128612871288128912901291129212931294129512961297129812991300130113021303130413051306130713081309131013111312131313141315131613171318131913201321132213231324132513261327132813291330133113321333133413351336133713381339134013411342134313441345134613471348134913501351135213531354135513561357135813591360136113621363136413651366136713681369137013711372
  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 const int NOEXPIRE = int.MinValue;
  50. private const int LOCALEXPIRE = 3600000;
  51. private const int HGEXPIRE = 3600000;
  52. private const int BADEXPIRE = 3600000;
  53. private const int BADHGEXPIRE =600000;
  54. private static readonly ILog m_log = LogManager.GetLogger(MethodBase.GetCurrentMethod().DeclaringType);
  55. protected bool m_Enabled;
  56. protected List<Scene> m_Scenes = new List<Scene>();
  57. protected IServiceThrottleModule m_ServiceThrottle;
  58. protected IUserAccountService m_userAccountService = null;
  59. protected IGridUserService m_gridUserService = null;
  60. protected GridInfo m_thisGridInfo;
  61. // The cache
  62. protected ExpiringCacheOS<UUID, UserData> m_userCacheByID = new ExpiringCacheOS<UUID, UserData>(120000);
  63. protected bool m_DisplayChangingHomeURI = false;
  64. UUID m_scopeID = UUID.Zero;
  65. ~UserManagementModule()
  66. {
  67. Dispose(false);
  68. }
  69. private bool disposed = false;
  70. public void Dispose()
  71. {
  72. Dispose(true);
  73. GC.SuppressFinalize(this);
  74. }
  75. private void Dispose(bool disposing)
  76. {
  77. if (!disposed)
  78. {
  79. disposed = true;
  80. m_userCacheByID.Dispose();
  81. m_userCacheByID = null;
  82. }
  83. }
  84. #region ISharedRegionModule
  85. public virtual void Initialise(IConfigSource config)
  86. {
  87. string umanmod = config.Configs["Modules"].GetString("UserManagementModule", Name);
  88. if (umanmod == Name)
  89. {
  90. m_Enabled = true;
  91. Init(config);
  92. m_log.DebugFormat("[USER MANAGEMENT MODULE]: {0} is enabled", Name);
  93. }
  94. }
  95. public virtual bool IsSharedModule
  96. {
  97. get { return true; }
  98. }
  99. public virtual string Name
  100. {
  101. get { return "BasicUserManagementModule"; }
  102. }
  103. public virtual Type ReplaceableInterface
  104. {
  105. get { return null; }
  106. }
  107. public virtual void AddRegion(Scene scene)
  108. {
  109. if (m_Enabled)
  110. {
  111. lock (m_Scenes)
  112. {
  113. m_Scenes.Add(scene);
  114. }
  115. if(m_thisGridInfo == null)
  116. m_thisGridInfo = scene.SceneGridInfo;
  117. scene.RegisterModuleInterface<IUserManagement>(this);
  118. scene.RegisterModuleInterface<IPeople>(this);
  119. scene.EventManager.OnNewClient += EventManager_OnNewClient;
  120. scene.EventManager.OnPrimsLoaded += EventManager_OnPrimsLoaded;
  121. }
  122. }
  123. public virtual void RemoveRegion(Scene scene)
  124. {
  125. if (m_Enabled)
  126. {
  127. scene.UnregisterModuleInterface<IUserManagement>(this);
  128. lock (m_Scenes)
  129. {
  130. m_Scenes.Remove(scene);
  131. }
  132. }
  133. }
  134. public virtual void RegionLoaded(Scene s)
  135. {
  136. if (!m_Enabled)
  137. return;
  138. if(m_ServiceThrottle == null)
  139. m_ServiceThrottle = s.RequestModuleInterface<IServiceThrottleModule>();
  140. if(m_userAccountService == null)
  141. m_userAccountService = s.UserAccountService;
  142. if(m_gridUserService == null)
  143. m_gridUserService = s.GridUserService;
  144. if (!s.RegionInfo.ScopeID.IsZero())
  145. m_scopeID = s.RegionInfo.ScopeID;
  146. }
  147. public virtual void PostInitialise()
  148. {
  149. }
  150. public virtual void Close()
  151. {
  152. m_Enabled = false;
  153. lock (m_Scenes)
  154. {
  155. m_Scenes.Clear();
  156. }
  157. m_thisGridInfo = null;
  158. Dispose(false);
  159. }
  160. #endregion ISharedRegionModule
  161. #region Event Handlers
  162. protected virtual void EventManager_OnPrimsLoaded(Scene s)
  163. {
  164. // let's sniff all the user names referenced by objects in the scene
  165. m_log.DebugFormat("[USER MANAGEMENT MODULE]: Caching creators' data from {0} ({1} objects)...", s.RegionInfo.RegionName, s.GetEntities().Length);
  166. s.ForEachSOG(delegate(SceneObjectGroup sog) { CacheCreators(sog); });
  167. }
  168. protected virtual void EventManager_OnNewClient(IClientAPI client)
  169. {
  170. client.OnConnectionClosed += HandleConnectionClosed;
  171. client.OnNameFromUUIDRequest += HandleUUIDNameRequest;
  172. client.OnAvatarPickerRequest += HandleAvatarPickerRequest;
  173. }
  174. protected virtual void HandleConnectionClosed(IClientAPI client)
  175. {
  176. client.OnNameFromUUIDRequest -= HandleUUIDNameRequest;
  177. client.OnAvatarPickerRequest -= HandleAvatarPickerRequest;
  178. client.OnConnectionClosed -= HandleConnectionClosed;
  179. }
  180. protected virtual void HandleUUIDNameRequest(UUID uuid, IClientAPI client)
  181. {
  182. // m_log.DebugFormat(
  183. // "[USER MANAGEMENT MODULE]: Handling request for name binding of UUID {0} from {1}",
  184. // uuid, remote_client.Name);
  185. if(!m_Enabled || m_Scenes.Count <= 0)
  186. return;
  187. if (m_userCacheByID.TryGetValue(uuid, out UserData user))
  188. {
  189. if (user.HasGridUserTried)
  190. {
  191. client.SendNameReply(uuid, user.FirstName, user.LastName);
  192. return;
  193. }
  194. }
  195. if(m_ServiceThrottle == null)
  196. return;
  197. IClientAPI deferedcli = client;
  198. // Not found in cache, queue continuation
  199. m_ServiceThrottle.Enqueue("uuidname", uuid.ToString(), delegate
  200. {
  201. if(deferedcli.IsActive)
  202. {
  203. if (GetUser(uuid, deferedcli.ScopeId, out UserData defuser))
  204. {
  205. if(deferedcli.IsActive)
  206. deferedcli.SendNameReply(uuid, defuser.FirstName, defuser.LastName);
  207. }
  208. }
  209. deferedcli = null;
  210. });
  211. }
  212. public virtual void HandleAvatarPickerRequest(IClientAPI client, UUID avatarID, UUID RequestID, string query)
  213. {
  214. //EventManager.TriggerAvatarPickerRequest();
  215. m_log.DebugFormat("[USER MANAGEMENT MODULE]: HandleAvatarPickerRequest for {0}", query);
  216. List<UserData> users = GetUserData(query, 500, 1);
  217. client.SendAvatarPickerReply(RequestID, users);
  218. }
  219. public bool CheckUrl(string url, out bool islocal, out OSHHTPHost host)
  220. {
  221. host = new OSHHTPHost(url);
  222. int type = m_thisGridInfo.IsLocalGrid(host);
  223. if(type < 0 )
  224. {
  225. islocal = false;
  226. return false;
  227. }
  228. islocal = type == 1;
  229. return true;
  230. }
  231. protected virtual void AddAdditionalUsers(string query, List<UserData> users, HashSet<UUID> found)
  232. {
  233. }
  234. #endregion Event Handlers
  235. #region IPeople
  236. public virtual UserData GetUserData(UUID id)
  237. {
  238. if(GetUser(id, out UserData u))
  239. return u;
  240. return null;
  241. }
  242. public virtual List<UserData> GetUserData(string query, int page_size, int page_number)
  243. {
  244. if(m_Scenes.Count <= 0 || m_userAccountService == null)
  245. return new List<UserData>();
  246. var users = new List<UserData>();
  247. var found = new HashSet<UUID>();
  248. // search the user accounts service
  249. if (m_userAccountService != null)
  250. {
  251. List<UserAccount> accs = m_userAccountService.GetUserAccounts(m_scopeID, query);
  252. if (accs != null)
  253. {
  254. for(int i = 0; i < accs.Count; ++i)
  255. {
  256. UserAccount acc = accs[i];
  257. UUID id = acc.PrincipalID;
  258. UserData ud = new UserData();
  259. ud.FirstName = acc.FirstName;
  260. ud.LastName = acc.LastName;
  261. ud.Id = id;
  262. ud.HasGridUserTried = true;
  263. ud.IsUnknownUser = false;
  264. ud.IsLocal = acc.LocalToGrid;
  265. users.Add(ud);
  266. found.Add(id);
  267. }
  268. }
  269. }
  270. // search the local cache
  271. string q = query.ToLower();
  272. foreach (UserData data in m_userCacheByID.Values)
  273. {
  274. if (found.Contains(data.Id))
  275. continue;
  276. if (data.Id.IsZero() || data.IsUnknownUser)
  277. continue;
  278. if (data.FirstName.ToLower().StartsWith(q) || data.LastName.ToLower().StartsWith(q))
  279. users.Add(data);
  280. }
  281. AddAdditionalUsers(query, users, found);
  282. return users;
  283. }
  284. #endregion IPeople
  285. protected virtual void CacheCreators(SceneObjectGroup sog)
  286. {
  287. //m_log.DebugFormat("[USER MANAGEMENT MODULE]: processing {0} {1}; {2}", sog.RootPart.Name, sog.RootPart.CreatorData, sog.RootPart.CreatorIdentification);
  288. AddCreatorUser(sog.RootPart.CreatorID, sog.RootPart.CreatorData);
  289. foreach (SceneObjectPart sop in sog.Parts)
  290. {
  291. AddCreatorUser(sop.CreatorID, sop.CreatorData);
  292. foreach (TaskInventoryItem item in sop.TaskInventory.Values)
  293. AddCreatorUser(item.CreatorID, item.CreatorData);
  294. }
  295. }
  296. /// <summary>
  297. ///
  298. /// </summary>
  299. /// <param name="uuid"></param>
  300. /// <param name="names">Caller please provide a properly instantiated array for names, string[2]</param>
  301. /// <returns></returns>
  302. protected virtual bool TryGetUserNames(UUID uuid, string[] names)
  303. {
  304. if (names == null)
  305. names = new string[2];
  306. if(GetUser(uuid, out UserData u))
  307. {
  308. names[0] = u.FirstName;
  309. names[1] = u.LastName;
  310. return true;
  311. }
  312. names[0] = "UnknownUMM3";
  313. names[1] = uuid.ToString();
  314. return false;
  315. }
  316. #region IUserManagement
  317. public virtual UUID GetUserIdByName(string name)
  318. {
  319. string[] parts = name.Split(new string[] { " " }, StringSplitOptions.RemoveEmptyEntries);
  320. if (parts.Length < 2)
  321. throw new Exception("Name must have 2 components");
  322. return GetUserIdByName(parts[0], parts[1]);
  323. }
  324. public virtual UUID GetUserIdByName(string firstName, string lastName)
  325. {
  326. if(m_Scenes.Count <= 0)
  327. return UUID.Zero;
  328. // TODO: Optimize for reverse lookup if this gets used by non-console commands.
  329. foreach (UserData user in m_userCacheByID.Values)
  330. {
  331. if (user.FirstName.Equals(firstName, StringComparison.InvariantCultureIgnoreCase) &&
  332. user.LastName.Equals(lastName, StringComparison.InvariantCultureIgnoreCase))
  333. return user.Id;
  334. }
  335. if(m_userAccountService != null)
  336. {
  337. UserAccount account = m_userAccountService.GetUserAccount(UUID.Zero, firstName, lastName);
  338. if (account != null)
  339. {
  340. AddUser(account);
  341. return account.PrincipalID;
  342. }
  343. }
  344. return UUID.Zero;
  345. }
  346. public virtual string GetUserName(UUID uuid)
  347. {
  348. if(GetUser(uuid, out UserData user))
  349. return user.FirstName + " " + user.LastName;
  350. return "UnknownUMM2 " + uuid.ToString();
  351. }
  352. public bool GetUserName(UUID uuid, out string FirstName, out string LastName)
  353. {
  354. if (GetUser(uuid, out UserData user))
  355. {
  356. FirstName = user.FirstName;
  357. LastName = user.LastName;
  358. return true;
  359. }
  360. FirstName = string.Empty;
  361. LastName = string.Empty;
  362. return false;
  363. }
  364. public virtual Dictionary<UUID,string> GetUsersNames(string[] ids, UUID scopeID)
  365. {
  366. var ret = new Dictionary<UUID,string>();
  367. if(m_Scenes.Count <= 0)
  368. return ret;
  369. List<string> missing = new List<string>(ids.Length);
  370. var untried = new Dictionary<UUID, UserData>();
  371. foreach (string id in ids)
  372. {
  373. if(!UUID.TryParse(id, out UUID uuid) || uuid.IsZero())
  374. continue;
  375. if (m_userCacheByID.TryGetValue(uuid, out UserData userdata))
  376. {
  377. if (userdata.HasGridUserTried)
  378. {
  379. ret[uuid] = userdata.FirstName + " " + userdata.LastName;
  380. continue;
  381. }
  382. untried[uuid] = userdata;
  383. }
  384. missing.Add(id);
  385. }
  386. if(missing.Count == 0)
  387. return ret;
  388. ids = null;
  389. List<UserAccount> accounts = m_userAccountService.GetUserAccounts(scopeID, missing);
  390. if (accounts.Count != 0)
  391. {
  392. foreach (UserAccount uac in accounts)
  393. {
  394. if (uac != null)
  395. {
  396. UUID id = uac.PrincipalID;
  397. var userdata = new UserData();
  398. userdata.Id = id;
  399. userdata.FirstName = uac.FirstName;
  400. userdata.LastName = uac.LastName;
  401. userdata.HomeURL = string.Empty;
  402. userdata.IsUnknownUser = false;
  403. userdata.IsLocal = true;
  404. userdata.HasGridUserTried = true;
  405. m_userCacheByID.Add(id, userdata, 1800000);
  406. ret[id] = uac.FirstName + " " + uac.LastName;
  407. missing.Remove(id.ToString()); // slowww
  408. untried.Remove(id);
  409. }
  410. }
  411. }
  412. if (missing.Count == 0 || m_gridUserService == null)
  413. return ret;
  414. GridUserInfo[] pinfos = m_gridUserService.GetGridUserInfo(missing.ToArray());
  415. if (pinfos.Length > 0)
  416. {
  417. foreach (GridUserInfo uInfo in pinfos)
  418. {
  419. if (uInfo != null && uInfo.UserID.Length > 36)
  420. {
  421. if (Util.ParseFullUniversalUserIdentifier(uInfo.UserID, out UUID u, out string url, out string first, out string last))
  422. {
  423. bool isvalid = CheckUrl(url, out bool islocal, out OSHHTPHost host);
  424. var userdata = new UserData();
  425. userdata.Id = u;
  426. if (isvalid)
  427. {
  428. if (islocal)
  429. {
  430. userdata.FirstName = first;
  431. userdata.LastName = last;
  432. userdata.HomeURL = string.Empty;
  433. userdata.IsLocal = true;
  434. }
  435. else
  436. {
  437. userdata.FirstName = first.Replace(" ", ".") + "." + last.Replace(" ", ".");
  438. userdata.HomeURL = host.URI;
  439. userdata.LastName = "@" + host.HostAndPort;
  440. userdata.IsLocal = false;
  441. }
  442. userdata.IsUnknownUser = false;
  443. userdata.HasGridUserTried = true;
  444. m_userCacheByID.Add(u, userdata, 1800000);
  445. ret[u] = userdata.FirstName + " " + userdata.LastName;
  446. missing.Remove(u.ToString());
  447. untried.Remove(u);
  448. }
  449. }
  450. else
  451. m_log.DebugFormat("[USER MANAGEMENT MODULE]: Unable to parse UUI {0}", uInfo.UserID);
  452. }
  453. }
  454. }
  455. // add the untried in cache
  456. if (untried.Count > 0)
  457. {
  458. foreach (UserData ud in untried.Values)
  459. {
  460. UUID id = ud.Id;
  461. ud.HasGridUserTried = true;
  462. m_userCacheByID.Add(id, ud, 1800000);
  463. ret[id] = ud.FirstName + " " + ud.LastName;
  464. missing.Remove(id.ToString());
  465. }
  466. }
  467. // add the UMMthings ( not sure we should)
  468. if (missing.Count > 0)
  469. {
  470. foreach (string id in missing)
  471. {
  472. if (UUID.TryParse(id, out UUID uuid))
  473. ret[uuid] = "Unknown UserUMMAU43";
  474. }
  475. }
  476. return ret;
  477. }
  478. public virtual Dictionary<UUID, string> GetKnownUserNames(string[] ids, UUID scopeID)
  479. {
  480. var ret = new Dictionary<UUID, string>();
  481. if (m_Scenes.Count <= 0)
  482. return ret;
  483. List<string> missing = new List<string>(ids.Length);
  484. var untried = new Dictionary<UUID, UserData>();
  485. foreach (string id in ids)
  486. {
  487. if (!UUID.TryParse(id, out UUID uuid) || uuid.IsZero())
  488. continue;
  489. if (m_userCacheByID.TryGetValue(uuid, out UserData userdata))
  490. {
  491. if (userdata.HasGridUserTried)
  492. {
  493. if(!userdata.IsUnknownUser)
  494. ret[uuid] = userdata.FirstName + " " + userdata.LastName;
  495. continue;
  496. }
  497. else
  498. untried[uuid] = userdata;
  499. }
  500. missing.Add(id);
  501. }
  502. if (missing.Count == 0)
  503. return ret;
  504. ids = null;
  505. List<UserAccount> accounts = m_userAccountService.GetUserAccounts(scopeID, missing);
  506. if (accounts.Count != 0)
  507. {
  508. foreach (UserAccount uac in accounts)
  509. {
  510. if (uac != null)
  511. {
  512. UUID id = uac.PrincipalID;
  513. var userdata = new UserData();
  514. userdata.Id = id;
  515. userdata.FirstName = uac.FirstName;
  516. userdata.LastName = uac.LastName;
  517. userdata.HomeURL = string.Empty;
  518. userdata.IsUnknownUser = false;
  519. userdata.IsLocal = true;
  520. userdata.HasGridUserTried = true;
  521. m_userCacheByID.Add(id, userdata, 1800000);
  522. ret[id] = uac.FirstName + " " + uac.LastName;
  523. missing.Remove(id.ToString()); // slowww
  524. untried.Remove(id);
  525. }
  526. }
  527. }
  528. if (missing.Count == 0 || m_gridUserService == null)
  529. return ret;
  530. GridUserInfo[] pinfos = m_gridUserService.GetGridUserInfo(missing.ToArray());
  531. missing = null;
  532. if (pinfos.Length > 0)
  533. {
  534. foreach (GridUserInfo uInfo in pinfos)
  535. {
  536. if (uInfo != null && uInfo.UserID.Length > 36)
  537. {
  538. if (Util.ParseFullUniversalUserIdentifier(uInfo.UserID, out UUID uuid, out string url, out string first, out string last))
  539. {
  540. bool isvalid = CheckUrl(url, out bool islocal, out OSHHTPHost host);
  541. var userdata = new UserData();
  542. userdata.Id = uuid;
  543. if (isvalid)
  544. {
  545. if (islocal)
  546. {
  547. userdata.FirstName = first;
  548. userdata.LastName = last;
  549. userdata.HomeURL = string.Empty;
  550. userdata.IsLocal = true;
  551. }
  552. else
  553. {
  554. userdata.FirstName = first.Replace(" ", ".") + "." + last.Replace(" ", ".");
  555. userdata.HomeURL = host.URI;
  556. userdata.LastName = "@" + host.HostAndPort;
  557. userdata.IsLocal = false;
  558. }
  559. userdata.IsUnknownUser = false;
  560. userdata.HasGridUserTried = true;
  561. m_userCacheByID.Add(uuid, userdata, 1800000);
  562. string name = userdata.FirstName + " " + userdata.LastName;
  563. untried.Remove(uuid);
  564. ret[uuid] = name;
  565. }
  566. }
  567. else
  568. m_log.DebugFormat("[USER MANAGEMENT MODULE]: Unable to parse UUI {0}", uInfo.UserID);
  569. }
  570. }
  571. }
  572. foreach(UserData ud in untried.Values)
  573. {
  574. ud.HasGridUserTried = true;
  575. m_userCacheByID.Add(ud.Id, ud, 1800000);
  576. if(!ud.IsUnknownUser)
  577. ret[ud.Id] = ud.FirstName + " " + ud.LastName;
  578. }
  579. return ret;
  580. }
  581. public List<UserData> GetKnownUsers(string[] ids, UUID scopeID)
  582. {
  583. if (m_Scenes.Count <= 0)
  584. return new List<UserData>();
  585. var ret = new List<UserData>(ids.Length);
  586. List<string> missing = new List<string>(ids.Length);
  587. var untried = new Dictionary<UUID, UserData>();
  588. foreach (string id in ids)
  589. {
  590. if (!UUID.TryParse(id, out UUID uuid) || uuid.IsZero())
  591. continue;
  592. if (m_userCacheByID.TryGetValue(uuid, out UserData userdata))
  593. {
  594. if (userdata.HasGridUserTried)
  595. {
  596. if (!userdata.IsUnknownUser)
  597. ret.Add(userdata);
  598. continue;
  599. }
  600. else
  601. untried[uuid] = userdata;
  602. }
  603. missing.Add(id);
  604. }
  605. if (missing.Count == 0)
  606. return ret;
  607. ids = null;
  608. List<UserAccount> accounts = m_userAccountService.GetUserAccounts(scopeID, missing);
  609. if (accounts.Count != 0)
  610. {
  611. foreach (UserAccount uac in accounts)
  612. {
  613. if (uac != null)
  614. {
  615. UUID id = uac.PrincipalID;
  616. var userdata = new UserData();
  617. userdata.Id = id;
  618. userdata.FirstName = uac.FirstName;
  619. userdata.LastName = uac.LastName;
  620. userdata.HomeURL = string.Empty;
  621. userdata.IsUnknownUser = false;
  622. userdata.IsLocal = true;
  623. userdata.HasGridUserTried = true;
  624. m_userCacheByID.Add(id, userdata, 1800000);
  625. ret.Add(userdata);
  626. missing.Remove(id.ToString()); // slowww
  627. untried.Remove(id);
  628. }
  629. }
  630. }
  631. if (missing.Count == 0 || m_gridUserService == null)
  632. return ret;
  633. GridUserInfo[] pinfos = m_gridUserService.GetGridUserInfo(missing.ToArray());
  634. missing = null;
  635. if (pinfos.Length > 0)
  636. {
  637. foreach (GridUserInfo uInfo in pinfos)
  638. {
  639. if (uInfo != null && uInfo.UserID.Length > 36)
  640. {
  641. if (Util.ParseFullUniversalUserIdentifier(uInfo.UserID, out UUID uuid, out string url, out string first, out string last))
  642. {
  643. bool isvalid = CheckUrl(url, out bool islocal, out OSHHTPHost host);
  644. var userdata = new UserData();
  645. userdata.Id = uuid;
  646. if (isvalid)
  647. {
  648. if (islocal)
  649. {
  650. userdata.FirstName = first;
  651. userdata.LastName = last;
  652. userdata.HomeURL = string.Empty;
  653. userdata.IsLocal = true;
  654. }
  655. else
  656. {
  657. userdata.FirstName = first.Replace(" ", ".") + "." + last.Replace(" ", ".");
  658. userdata.HomeURL = host.URI;
  659. userdata.LastName = "@" + host.HostAndPort;
  660. userdata.IsLocal = false;
  661. }
  662. userdata.IsUnknownUser = false;
  663. userdata.HasGridUserTried = true;
  664. m_userCacheByID.Add(uuid, userdata, 1800000);
  665. untried.Remove(uuid);
  666. ret.Add(userdata);
  667. }
  668. }
  669. else
  670. m_log.DebugFormat("[USER MANAGEMENT MODULE]: Unable to parse UUI {0}", uInfo.UserID);
  671. }
  672. }
  673. }
  674. foreach (UserData ud in untried.Values)
  675. {
  676. ud.HasGridUserTried = true;
  677. m_userCacheByID.Add(ud.Id, ud, 1800000);
  678. if (!ud.IsUnknownUser)
  679. ret.Add(ud);
  680. }
  681. return ret;
  682. }
  683. public virtual string GetUserHomeURL(UUID userID)
  684. {
  685. if (GetUser(userID, out UserData user) && user != null)
  686. {
  687. if (user.LastWebFail > 0 && Util.GetTimeStamp() - user.LastWebFail > BADURLEXPIRE)
  688. user.LastWebFail = -1;
  689. return user.HomeURL;
  690. }
  691. return string.Empty;
  692. }
  693. public virtual string GetUserHomeURL(UUID userID, out bool recentFail)
  694. {
  695. recentFail = false;
  696. if (GetUser(userID, out UserData user))
  697. {
  698. if (user.LastWebFail > 0)
  699. {
  700. if (Util.GetTimeStamp() - user.LastWebFail > BADURLEXPIRE)
  701. user.LastWebFail = -1;
  702. else
  703. recentFail = true;
  704. }
  705. return user.HomeURL;
  706. }
  707. return string.Empty;
  708. }
  709. public virtual string GetUserServerURL(UUID userID, string serverType)
  710. {
  711. UserData userdata;
  712. if(!GetUser(userID, out userdata))
  713. return string.Empty;
  714. if(userdata.IsLocal)
  715. return string.Empty;
  716. if(userdata.LastWebFail > 0)
  717. {
  718. if(Util.GetTimeStamp() - userdata.LastWebFail < BADURLEXPIRE)
  719. return string.Empty;
  720. userdata.LastWebFail = -1;
  721. }
  722. if (userdata.ServerURLs != null)
  723. {
  724. if(userdata.ServerURLs.TryGetValue(serverType, out object ourl) && ourl != null)
  725. {
  726. string turl = ourl as string;
  727. OSHHTPHost otmp = new OSHHTPHost(turl);
  728. if (otmp.IsValidHost)
  729. return otmp.URI;
  730. }
  731. return string.Empty;
  732. }
  733. if (!string.IsNullOrEmpty(userdata.HomeURL))
  734. {
  735. string homeuri = userdata.HomeURL.ToLower();
  736. if (!WebUtil.GlobalExpiringBadURLs.ContainsKey(homeuri))
  737. {
  738. //m_log.DebugFormat("[USER MANAGEMENT MODULE]: Requested url type {0} for {1}", serverType, userID);
  739. UserAgentServiceConnector uConn = new UserAgentServiceConnector(homeuri);
  740. try
  741. {
  742. userdata.ServerURLs = uConn.GetServerURLs(userID);
  743. }
  744. catch (System.Net.Http.HttpRequestException e)
  745. {
  746. m_log.DebugFormat("[USER MANAGEMENT MODULE]: GetServerURLs call failed {0}", e.Message);
  747. WebUtil.GlobalExpiringBadURLs.Add(homeuri, BADURLEXPIRE * 1000);
  748. userdata.ServerURLs = new Dictionary<string, object>();
  749. }
  750. catch (Exception e)
  751. {
  752. m_log.Debug($"[USER MANAGEMENT MODULE]: GetServerURLs call failed {e.Message}");
  753. userdata.ServerURLs = new Dictionary<string, object>();
  754. }
  755. if (userdata.ServerURLs != null && userdata.ServerURLs.TryGetValue(serverType, out object ourl) && ourl != null)
  756. {
  757. string turl = ourl as string;
  758. OSHHTPHost otmp = new OSHHTPHost(turl);
  759. if (otmp.IsValidHost)
  760. return otmp.URI;
  761. }
  762. }
  763. }
  764. return string.Empty;
  765. }
  766. public void UserWebFailed(UUID id)
  767. {
  768. if(m_userCacheByID.TryGetValue(id, out UserData u))
  769. u.LastWebFail = Util.GetTimeStamp();
  770. }
  771. public virtual string GetUserServerURL(UUID userID, string serverType, out bool recentFail)
  772. {
  773. recentFail = false;
  774. if (!GetUser(userID, out UserData userdata))
  775. return string.Empty;
  776. if (userdata.IsLocal)
  777. return string.Empty;
  778. if (userdata.LastWebFail > 0)
  779. {
  780. if (Util.GetTimeStamp() - userdata.LastWebFail > BADURLEXPIRE)
  781. userdata.LastWebFail = -1;
  782. else
  783. recentFail = true;
  784. }
  785. if (userdata.ServerURLs != null)
  786. {
  787. if (userdata.ServerURLs.TryGetValue(serverType, out object ourl) && ourl != null)
  788. {
  789. string turl = ourl as string;
  790. OSHHTPHost otmp = new OSHHTPHost(turl);
  791. if (otmp.IsValidHost)
  792. return otmp.URI;
  793. }
  794. return string.Empty;
  795. }
  796. if (!recentFail && !string.IsNullOrEmpty(userdata.HomeURL))
  797. {
  798. string homeurl = userdata.HomeURL.ToLower();
  799. if(!WebUtil.GlobalExpiringBadURLs.ContainsKey(homeurl))
  800. {
  801. //m_log.DebugFormat("[USER MANAGEMENT MODULE]: Requested url type {0} for {1}", serverType, userID);
  802. UserAgentServiceConnector uConn = new UserAgentServiceConnector(homeurl);
  803. try
  804. {
  805. userdata.ServerURLs = uConn.GetServerURLs(userID);
  806. }
  807. catch (System.Net.Http.HttpRequestException e)
  808. {
  809. m_log.DebugFormat("[USER MANAGEMENT MODULE]: GetServerURLs call failed {0}", e.Message);
  810. userdata.ServerURLs = new Dictionary<string, object>();
  811. userdata.LastWebFail = Util.GetTimeStamp();
  812. WebUtil.GlobalExpiringBadURLs.Add(homeurl, BADURLEXPIRE * 1000);
  813. recentFail = true;
  814. }
  815. catch (Exception e)
  816. {
  817. m_log.Debug($"[USER MANAGEMENT MODULE]: GetServerURLs call failed {e.Message}");
  818. userdata.ServerURLs = new Dictionary<string, object>();
  819. userdata.LastWebFail = Util.GetTimeStamp();
  820. recentFail = true;
  821. }
  822. if (userdata.ServerURLs != null && userdata.ServerURLs.TryGetValue(serverType, out object ourl) && ourl != null)
  823. {
  824. string turl = ourl as string;
  825. OSHHTPHost otmp = new OSHHTPHost(turl);
  826. if (otmp.IsValidHost)
  827. return otmp.URI;
  828. }
  829. }
  830. }
  831. return string.Empty;
  832. }
  833. public virtual string GetUserUUI(UUID userID)
  834. {
  835. string uui;
  836. GetUserUUI(userID, out uui);
  837. return uui;
  838. }
  839. public virtual bool GetUserUUI(UUID userID, out string uui)
  840. {
  841. if (GetUser(userID, out UserData ud) && ud != null)
  842. {
  843. if (ud.LastName.StartsWith("@"))
  844. {
  845. string[] parts = ud.FirstName.Split('.');
  846. if (parts.Length >= 2)
  847. uui = userID.ToString() + ";" + ud.HomeURL + ";" + parts[0] + " " + parts[1];
  848. else
  849. uui = userID.ToString() + ";" + ud.HomeURL + ";" + ud.FirstName + " " + ud.LastName;
  850. }
  851. else
  852. uui = userID.ToString();
  853. return true;
  854. }
  855. uui = userID.ToString();
  856. return false;
  857. }
  858. #region Cache Management
  859. public virtual bool GetUser(UUID uuid, out UserData userdata)
  860. {
  861. return GetUser(uuid, m_scopeID, out userdata);
  862. }
  863. public virtual bool GetUser(UUID uuid, UUID scopeID, out UserData userdata)
  864. {
  865. if (m_Scenes.Count <= 0)
  866. {
  867. userdata = new UserData();
  868. return false;
  869. }
  870. if (m_userCacheByID.TryGetValue(uuid, out userdata))
  871. {
  872. if (userdata.HasGridUserTried)
  873. return true;
  874. }
  875. else
  876. {
  877. userdata = new UserData();
  878. userdata.Id = uuid;
  879. userdata.FirstName = "Unknown";
  880. userdata.LastName = uuid.ToString();
  881. userdata.HomeURL = string.Empty;
  882. userdata.IsUnknownUser = true;
  883. userdata.HasGridUserTried = false;
  884. }
  885. if (!userdata.HasGridUserTried)
  886. {
  887. /* rewrite here */
  888. UserAccount account = m_userAccountService.GetUserAccount(scopeID, uuid);
  889. if (account != null)
  890. {
  891. userdata.FirstName = account.FirstName;
  892. userdata.LastName = account.LastName;
  893. userdata.HomeURL = string.Empty;
  894. userdata.IsUnknownUser = false;
  895. userdata.IsLocal = true;
  896. userdata.HasGridUserTried = true;
  897. }
  898. }
  899. if (!userdata.HasGridUserTried)
  900. {
  901. GridUserInfo uInfo = null;
  902. if (null != m_gridUserService)
  903. {
  904. uInfo = m_gridUserService.GetGridUserInfo(uuid.ToString());
  905. }
  906. if (uInfo != null)
  907. {
  908. if (Util.ParseFullUniversalUserIdentifier(uInfo.UserID, out UUID u, out string url, out string first, out string last))
  909. {
  910. bool isvalid = CheckUrl(url, out bool islocal, out OSHHTPHost host);
  911. if (isvalid)
  912. {
  913. if(islocal)
  914. {
  915. userdata.FirstName = first;
  916. userdata.LastName = last;
  917. userdata.HomeURL = string.Empty;
  918. userdata.IsLocal = true;
  919. userdata.IsUnknownUser = false;
  920. }
  921. else
  922. {
  923. userdata.FirstName = first.Replace(" ", ".") + "." + last.Replace(" ", ".");
  924. userdata.HomeURL = host.URI;
  925. userdata.LastName = "@" + host.HostAndPort;
  926. userdata.IsLocal = false;
  927. userdata.IsUnknownUser = false;
  928. }
  929. }
  930. }
  931. else
  932. m_log.DebugFormat("[USER MANAGEMENT MODULE]: Unable to parse UUI {0}", uInfo.UserID);
  933. }
  934. userdata.HasGridUserTried = true;
  935. }
  936. /* END: do not wrap this code in any lock here */
  937. m_userCacheByID.Add(uuid, userdata, 1800000);
  938. return !userdata.IsUnknownUser;
  939. }
  940. public void AddUser(UserAccount account)
  941. {
  942. UUID id = account.PrincipalID;
  943. bool local = account.LocalToGrid;
  944. UserData user = new UserData();
  945. user.Id = id;
  946. user.FirstName = account.FirstName;
  947. user.LastName = account.LastName;
  948. user.HomeURL = string.Empty;
  949. user.IsUnknownUser = false;
  950. user.HasGridUserTried = true;
  951. user.IsLocal = local;
  952. m_userCacheByID.Add(id, user, local ? LOCALEXPIRE : HGEXPIRE);
  953. }
  954. public void AddSystemUser(UUID uuid, string first, string last)
  955. {
  956. UserData user = new UserData()
  957. {
  958. Id = uuid,
  959. FirstName = first,
  960. LastName = last,
  961. IsLocal = true,
  962. HasGridUserTried = true,
  963. HomeURL = string.Empty,
  964. IsUnknownUser = false
  965. };
  966. m_userCacheByID.Add(uuid, user, NOEXPIRE);
  967. }
  968. public void AddNPCUser(UUID uuid, string first, string last)
  969. {
  970. UserData user = new UserData()
  971. {
  972. Id = uuid,
  973. FirstName = first,
  974. LastName = last,
  975. HasGridUserTried = true,
  976. IsLocal = true,
  977. HomeURL = string.Empty,
  978. IsUnknownUser = false
  979. };
  980. m_userCacheByID.Add(uuid, user, NOEXPIRE);
  981. }
  982. public virtual void AddUser(UUID uuid, string first, string last, string homeURL)
  983. {
  984. //m_log.DebugFormat("[USER MANAGEMENT MODULE]: Adding user with id {0}, first {1}, last {2}, url {3}", uuid, first, last, homeURL);
  985. UserData oldUser;
  986. if (m_userCacheByID.TryGetValue(uuid, out oldUser))
  987. {
  988. if (!oldUser.IsUnknownUser)
  989. {
  990. if (!homeURL.Equals(oldUser.HomeURL) && m_DisplayChangingHomeURI)
  991. {
  992. m_log.DebugFormat("[USER MANAGEMENT MODULE]: Different HomeURI for {0} {1} ({2}): {3} and {4}",
  993. first, last, uuid.ToString(), homeURL, oldUser.HomeURL);
  994. }
  995. /* no update needed */
  996. return;
  997. }
  998. }
  999. oldUser = new UserData();
  1000. oldUser.Id = uuid;
  1001. oldUser.HasGridUserTried = false;
  1002. oldUser.IsUnknownUser = false;
  1003. bool local;
  1004. if (CheckUrl(homeURL, out local, out OSHHTPHost host))
  1005. {
  1006. if (local)
  1007. {
  1008. oldUser.FirstName = first;
  1009. oldUser.LastName = last;
  1010. oldUser.IsLocal = true;
  1011. oldUser.HomeURL = string.Empty;
  1012. oldUser.HasGridUserTried = true;
  1013. m_userCacheByID.Add(uuid, oldUser, LOCALEXPIRE);
  1014. }
  1015. else
  1016. {
  1017. oldUser.FirstName = first.Replace(" ", ".") + "." + last.Replace(" ", ".");
  1018. oldUser.LastName = "@" + host.HostAndPort;
  1019. oldUser.HomeURL = host.URI;
  1020. oldUser.IsLocal = false;
  1021. m_userCacheByID.Add(uuid, oldUser, HGEXPIRE);
  1022. }
  1023. }
  1024. else
  1025. {
  1026. oldUser.FirstName = first.Replace(" ", ".") + "." + last.Replace(" ", ".");
  1027. oldUser.LastName = "UMMM0Unknown";
  1028. oldUser.IsLocal = true;
  1029. oldUser.HomeURL = string.Empty;
  1030. oldUser.HasGridUserTried = true;
  1031. oldUser.IsUnknownUser = true;
  1032. m_userCacheByID.Add(uuid, oldUser, BADEXPIRE);
  1033. }
  1034. }
  1035. public virtual void AddCreatorUser(UUID id, string creatorData)
  1036. {
  1037. // m_log.InfoFormat("[USER MANAGEMENT MODULE]: Adding user with id {0}, creatorData {1}", id, creatorData);
  1038. if(string.IsNullOrEmpty(creatorData))
  1039. return;
  1040. if(m_userCacheByID.ContainsKey(id))
  1041. return;
  1042. string homeURL;
  1043. string firstname = string.Empty;
  1044. string lastname = string.Empty;
  1045. //creatorData = <endpoint>;<name>
  1046. string[] parts = creatorData.Split(';');
  1047. if(parts.Length > 1)
  1048. {
  1049. string[] nameparts = parts[1].Split(' ');
  1050. if(nameparts.Length < 2)
  1051. return;
  1052. firstname = nameparts[0];
  1053. for(int xi = 1; xi < nameparts.Length; ++xi)
  1054. lastname += nameparts[xi];
  1055. if (string.IsNullOrWhiteSpace(firstname))
  1056. return;
  1057. if (string.IsNullOrWhiteSpace(lastname))
  1058. return;
  1059. }
  1060. else
  1061. return;
  1062. homeURL = parts[0];
  1063. var oldUser = new UserData();
  1064. oldUser.Id = id;
  1065. oldUser.HasGridUserTried = false;
  1066. oldUser.IsUnknownUser = false;
  1067. OSHTTPURI homeuri = new OSHTTPURI(homeURL);
  1068. if (homeuri.IsValidHost)
  1069. {
  1070. if (m_thisGridInfo.IsLocalGrid(homeuri.URL) == 1) // local
  1071. {
  1072. oldUser.FirstName = firstname;
  1073. oldUser.LastName = lastname;
  1074. oldUser.IsLocal = true;
  1075. oldUser.HomeURL = string.Empty;
  1076. oldUser.HasGridUserTried = true;
  1077. }
  1078. else
  1079. {
  1080. oldUser.FirstName = firstname + "." + lastname.Replace(" ", ".");
  1081. oldUser.LastName = "@" + homeuri.HostAndPort;
  1082. oldUser.HomeURL = homeuri.URL;
  1083. oldUser.IsLocal = false;
  1084. }
  1085. }
  1086. else
  1087. {
  1088. if (string.IsNullOrEmpty(homeuri.Host)) // take this as local
  1089. {
  1090. oldUser.FirstName = firstname;
  1091. oldUser.LastName = lastname;
  1092. oldUser.IsLocal = true;
  1093. oldUser.HomeURL = string.Empty;
  1094. oldUser.HasGridUserTried = true;
  1095. }
  1096. else
  1097. {
  1098. oldUser.FirstName = firstname + "." + lastname.Replace(" ", ".");
  1099. oldUser.LastName = "UMMM1Unknown";
  1100. oldUser.IsLocal = true;
  1101. oldUser.HomeURL = string.Empty;
  1102. oldUser.HasGridUserTried = true;
  1103. oldUser.IsUnknownUser = true;
  1104. }
  1105. }
  1106. m_userCacheByID.Add(id, oldUser, NOEXPIRE);
  1107. }
  1108. public bool RemoveUser(UUID uuid)
  1109. {
  1110. return m_userCacheByID.Remove(uuid);
  1111. }
  1112. #endregion
  1113. public virtual bool IsLocalGridUser(UUID uuid)
  1114. {
  1115. if (m_Scenes.Count <= 0)
  1116. return true;
  1117. if (m_userCacheByID.TryGetValue(uuid, out UserData u))
  1118. {
  1119. if (u.HasGridUserTried)
  1120. return u.IsLocal;
  1121. }
  1122. if(m_userAccountService == null)
  1123. return true;
  1124. UserAccount account = m_userAccountService.GetUserAccount(m_Scenes[0].RegionInfo.ScopeID, uuid);
  1125. if (account == null)
  1126. return false;
  1127. if(u == null)
  1128. AddUser(account);
  1129. else
  1130. u.HasGridUserTried = true;
  1131. return true;
  1132. }
  1133. #endregion IUserManagement
  1134. protected virtual void Init(IConfigSource config)
  1135. {
  1136. AddSystemUser(UUID.Zero, "Unknown", "User");
  1137. AddSystemUser(Constants.m_MrOpenSimID, "Mr", "Opensim");
  1138. RegisterConsoleCmds();
  1139. IConfig userManagementConfig = config.Configs["UserManagement"];
  1140. if (userManagementConfig != null)
  1141. m_DisplayChangingHomeURI = userManagementConfig.GetBoolean("DisplayChangingHomeURI", false);
  1142. }
  1143. protected virtual void RegisterConsoleCmds()
  1144. {
  1145. MainConsole.Instance.Commands.AddCommand("Users", true,
  1146. "show name",
  1147. "show name <uuid>",
  1148. "Show the bindings between a single user UUID and a user name",
  1149. String.Empty,
  1150. HandleShowUser);
  1151. MainConsole.Instance.Commands.AddCommand("Users", true,
  1152. "show names",
  1153. "show names",
  1154. "Show the bindings between user UUIDs and user names",
  1155. String.Empty,
  1156. HandleShowUsers);
  1157. MainConsole.Instance.Commands.AddCommand("Users", true,
  1158. "reset user cache",
  1159. "reset user cache",
  1160. "reset user cache to allow changed settings to be applied",
  1161. String.Empty,
  1162. HandleResetUserCache);
  1163. }
  1164. protected virtual void HandleResetUserCache(string module, string[] cmd)
  1165. {
  1166. m_userCacheByID.Clear();
  1167. }
  1168. protected virtual void HandleShowUser(string module, string[] cmd)
  1169. {
  1170. if (cmd.Length < 3)
  1171. {
  1172. MainConsole.Instance.Output("Usage: show name <uuid>");
  1173. return;
  1174. }
  1175. UUID userId;
  1176. if (!ConsoleUtil.TryParseConsoleUuid(MainConsole.Instance, cmd[2], out userId))
  1177. return;
  1178. UserData ud;
  1179. if(!GetUser(userId, out ud))
  1180. {
  1181. MainConsole.Instance.Output("No name known for user with id {0}", userId);
  1182. return;
  1183. }
  1184. ConsoleDisplayTable cdt = new ConsoleDisplayTable();
  1185. cdt.AddColumn("UUID", 36);
  1186. cdt.AddColumn("Name", 30);
  1187. cdt.AddColumn("HomeURL", 40);
  1188. cdt.AddRow(userId, string.Format("{0} {1}", ud.FirstName, ud.LastName), ud.HomeURL);
  1189. MainConsole.Instance.Output(cdt.ToString());
  1190. }
  1191. protected virtual void HandleShowUsers(string module, string[] cmd)
  1192. {
  1193. ConsoleDisplayTable cdt = new ConsoleDisplayTable();
  1194. cdt.AddColumn("UUID", 36);
  1195. cdt.AddColumn("Name", 30);
  1196. cdt.AddColumn("HomeURL", 40);
  1197. cdt.AddColumn("Checked", 10);
  1198. foreach(UserData u in m_userCacheByID.Values)
  1199. {
  1200. cdt.AddRow(u.Id, string.Format("{0} {1}", u.FirstName, u.LastName), u.HomeURL, u.HasGridUserTried ? "yes" : "no");
  1201. }
  1202. MainConsole.Instance.Output(cdt.ToString());
  1203. }
  1204. }
  1205. }