diff options
Diffstat (limited to 'OpenSim/Region/CoreModules/Framework/UserManagement')
3 files changed, 351 insertions, 132 deletions
diff --git a/OpenSim/Region/CoreModules/Framework/UserManagement/HGUserManagementModule.cs b/OpenSim/Region/CoreModules/Framework/UserManagement/HGUserManagementModule.cs index 8ce20e9..245c808 100644 --- a/OpenSim/Region/CoreModules/Framework/UserManagement/HGUserManagementModule.cs +++ b/OpenSim/Region/CoreModules/Framework/UserManagement/HGUserManagementModule.cs | |||
@@ -54,11 +54,11 @@ namespace OpenSim.Region.CoreModules.Framework.UserManagement | |||
54 | 54 | ||
55 | public new void Initialise(IConfigSource config) | 55 | public new void Initialise(IConfigSource config) |
56 | { | 56 | { |
57 | string umanmod = config.Configs["Modules"].GetString("UserManagementModule", Name); | 57 | string umanmod = config.Configs["Modules"].GetString("UserManagementModule", null); |
58 | if (umanmod == Name) | 58 | if (umanmod == Name) |
59 | { | 59 | { |
60 | m_Enabled = true; | 60 | m_Enabled = true; |
61 | RegisterConsoleCmds(); | 61 | Init(); |
62 | m_log.DebugFormat("[USER MANAGEMENT MODULE]: {0} is enabled", Name); | 62 | m_log.DebugFormat("[USER MANAGEMENT MODULE]: {0} is enabled", Name); |
63 | } | 63 | } |
64 | } | 64 | } |
@@ -70,7 +70,7 @@ namespace OpenSim.Region.CoreModules.Framework.UserManagement | |||
70 | 70 | ||
71 | #endregion ISharedRegionModule | 71 | #endregion ISharedRegionModule |
72 | 72 | ||
73 | protected override void AddAdditionalUsers(UUID avatarID, string query, List<UserData> users) | 73 | protected override void AddAdditionalUsers(string query, List<UserData> users) |
74 | { | 74 | { |
75 | if (query.Contains("@")) // First.Last@foo.com, maybe? | 75 | if (query.Contains("@")) // First.Last@foo.com, maybe? |
76 | { | 76 | { |
diff --git a/OpenSim/Region/CoreModules/Framework/UserManagement/Tests/HGUserManagementModuleTests.cs b/OpenSim/Region/CoreModules/Framework/UserManagement/Tests/HGUserManagementModuleTests.cs new file mode 100644 index 0000000..9d36aa5 --- /dev/null +++ b/OpenSim/Region/CoreModules/Framework/UserManagement/Tests/HGUserManagementModuleTests.cs | |||
@@ -0,0 +1,76 @@ | |||
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 | |||
28 | using System; | ||
29 | using Nini.Config; | ||
30 | using NUnit.Framework; | ||
31 | using OpenMetaverse; | ||
32 | using OpenSim.Framework; | ||
33 | using OpenSim.Region.CoreModules.Framework.UserManagement; | ||
34 | using OpenSim.Tests.Common; | ||
35 | using OpenSim.Tests.Common.Mock; | ||
36 | |||
37 | namespace OpenSim.Region.CoreModules.Framework.UserManagement.Tests | ||
38 | { | ||
39 | [TestFixture] | ||
40 | public class HGUserManagementModuleTests : OpenSimTestCase | ||
41 | { | ||
42 | /// <summary> | ||
43 | /// Test that a new HG agent (i.e. one without a user account) has their name cached in the UMM upon creation. | ||
44 | /// </summary> | ||
45 | [Test] | ||
46 | public void TestCachedUserNameForNewAgent() | ||
47 | { | ||
48 | TestHelpers.InMethod(); | ||
49 | // TestHelpers.EnableLogging(); | ||
50 | |||
51 | HGUserManagementModule hgumm = new HGUserManagementModule(); | ||
52 | UUID userId = TestHelpers.ParseStem("11"); | ||
53 | string firstName = "Fred"; | ||
54 | string lastName = "Astaire"; | ||
55 | string homeUri = "example.com"; | ||
56 | |||
57 | IConfigSource config = new IniConfigSource(); | ||
58 | config.AddConfig("Modules"); | ||
59 | config.Configs["Modules"].Set("UserManagementModule", hgumm.Name); | ||
60 | |||
61 | SceneHelpers sceneHelpers = new SceneHelpers(); | ||
62 | TestScene scene = sceneHelpers.SetupScene(); | ||
63 | SceneHelpers.SetupSceneModules(scene, config, hgumm); | ||
64 | |||
65 | AgentCircuitData acd = SceneHelpers.GenerateAgentData(userId); | ||
66 | acd.firstname = firstName; | ||
67 | acd.lastname = lastName; | ||
68 | acd.ServiceURLs["HomeURI"] = "http://" + homeUri; | ||
69 | |||
70 | SceneHelpers.AddScenePresence(scene, acd); | ||
71 | |||
72 | string name = hgumm.GetUserName(userId); | ||
73 | Assert.That(name, Is.EqualTo(string.Format("{0}.{1} @{2}", firstName, lastName, homeUri))); | ||
74 | } | ||
75 | } | ||
76 | } \ No newline at end of file | ||
diff --git a/OpenSim/Region/CoreModules/Framework/UserManagement/UserManagementModule.cs b/OpenSim/Region/CoreModules/Framework/UserManagement/UserManagementModule.cs index 77e8b00..3fb5195 100644 --- a/OpenSim/Region/CoreModules/Framework/UserManagement/UserManagementModule.cs +++ b/OpenSim/Region/CoreModules/Framework/UserManagement/UserManagementModule.cs | |||
@@ -28,9 +28,11 @@ using System; | |||
28 | using System.Collections.Generic; | 28 | using System.Collections.Generic; |
29 | using System.IO; | 29 | using System.IO; |
30 | using System.Reflection; | 30 | using System.Reflection; |
31 | using System.Threading; | ||
31 | 32 | ||
32 | using OpenSim.Framework; | 33 | using OpenSim.Framework; |
33 | using OpenSim.Framework.Console; | 34 | using OpenSim.Framework.Console; |
35 | using OpenSim.Framework.Monitoring; | ||
34 | using OpenSim.Region.ClientStack.LindenUDP; | 36 | using OpenSim.Region.ClientStack.LindenUDP; |
35 | using OpenSim.Region.Framework; | 37 | using OpenSim.Region.Framework; |
36 | using OpenSim.Region.Framework.Interfaces; | 38 | using OpenSim.Region.Framework.Interfaces; |
@@ -44,25 +46,19 @@ using log4net; | |||
44 | using Nini.Config; | 46 | using Nini.Config; |
45 | using Mono.Addins; | 47 | using Mono.Addins; |
46 | 48 | ||
49 | using DirFindFlags = OpenMetaverse.DirectoryManager.DirFindFlags; | ||
50 | |||
47 | namespace OpenSim.Region.CoreModules.Framework.UserManagement | 51 | namespace OpenSim.Region.CoreModules.Framework.UserManagement |
48 | { | 52 | { |
49 | public class UserData | ||
50 | { | ||
51 | public UUID Id { get; set; } | ||
52 | public string FirstName { get; set; } | ||
53 | public string LastName { get; set; } | ||
54 | public string HomeURL { get; set; } | ||
55 | public Dictionary<string, object> ServerURLs { get; set; } | ||
56 | } | ||
57 | |||
58 | [Extension(Path = "/OpenSim/RegionModules", NodeName = "RegionModule", Id = "UserManagementModule")] | 53 | [Extension(Path = "/OpenSim/RegionModules", NodeName = "RegionModule", Id = "UserManagementModule")] |
59 | public class UserManagementModule : ISharedRegionModule, IUserManagement | 54 | public class UserManagementModule : ISharedRegionModule, IUserManagement, IPeople |
60 | { | 55 | { |
61 | private static readonly ILog m_log = LogManager.GetLogger(MethodBase.GetCurrentMethod().DeclaringType); | 56 | private static readonly ILog m_log = LogManager.GetLogger(MethodBase.GetCurrentMethod().DeclaringType); |
62 | 57 | ||
63 | protected bool m_Enabled; | 58 | protected bool m_Enabled; |
64 | protected List<Scene> m_Scenes = new List<Scene>(); | 59 | protected List<Scene> m_Scenes = new List<Scene>(); |
65 | 60 | ||
61 | protected IServiceThrottleModule m_ServiceThrottle; | ||
66 | // The cache | 62 | // The cache |
67 | protected Dictionary<UUID, UserData> m_UserCache = new Dictionary<UUID, UserData>(); | 63 | protected Dictionary<UUID, UserData> m_UserCache = new Dictionary<UUID, UserData>(); |
68 | 64 | ||
@@ -74,7 +70,7 @@ namespace OpenSim.Region.CoreModules.Framework.UserManagement | |||
74 | if (umanmod == Name) | 70 | if (umanmod == Name) |
75 | { | 71 | { |
76 | m_Enabled = true; | 72 | m_Enabled = true; |
77 | RegisterConsoleCmds(); | 73 | Init(); |
78 | m_log.DebugFormat("[USER MANAGEMENT MODULE]: {0} is enabled", Name); | 74 | m_log.DebugFormat("[USER MANAGEMENT MODULE]: {0} is enabled", Name); |
79 | } | 75 | } |
80 | } | 76 | } |
@@ -101,6 +97,7 @@ namespace OpenSim.Region.CoreModules.Framework.UserManagement | |||
101 | m_Scenes.Add(scene); | 97 | m_Scenes.Add(scene); |
102 | 98 | ||
103 | scene.RegisterModuleInterface<IUserManagement>(this); | 99 | scene.RegisterModuleInterface<IUserManagement>(this); |
100 | scene.RegisterModuleInterface<IPeople>(this); | ||
104 | scene.EventManager.OnNewClient += new EventManager.OnNewClientDelegate(EventManager_OnNewClient); | 101 | scene.EventManager.OnNewClient += new EventManager.OnNewClientDelegate(EventManager_OnNewClient); |
105 | scene.EventManager.OnPrimsLoaded += new EventManager.PrimsLoaded(EventManager_OnPrimsLoaded); | 102 | scene.EventManager.OnPrimsLoaded += new EventManager.PrimsLoaded(EventManager_OnPrimsLoaded); |
106 | } | 103 | } |
@@ -117,6 +114,8 @@ namespace OpenSim.Region.CoreModules.Framework.UserManagement | |||
117 | 114 | ||
118 | public void RegionLoaded(Scene s) | 115 | public void RegionLoaded(Scene s) |
119 | { | 116 | { |
117 | if (m_Enabled && m_ServiceThrottle == null) | ||
118 | m_ServiceThrottle = s.RequestModuleInterface<IServiceThrottleModule>(); | ||
120 | } | 119 | } |
121 | 120 | ||
122 | public void PostInitialise() | 121 | public void PostInitialise() |
@@ -143,7 +142,6 @@ namespace OpenSim.Region.CoreModules.Framework.UserManagement | |||
143 | s.ForEachSOG(delegate(SceneObjectGroup sog) { CacheCreators(sog); }); | 142 | s.ForEachSOG(delegate(SceneObjectGroup sog) { CacheCreators(sog); }); |
144 | } | 143 | } |
145 | 144 | ||
146 | |||
147 | void EventManager_OnNewClient(IClientAPI client) | 145 | void EventManager_OnNewClient(IClientAPI client) |
148 | { | 146 | { |
149 | client.OnConnectionClosed += new Action<IClientAPI>(HandleConnectionClosed); | 147 | client.OnConnectionClosed += new Action<IClientAPI>(HandleConnectionClosed); |
@@ -157,21 +155,43 @@ namespace OpenSim.Region.CoreModules.Framework.UserManagement | |||
157 | client.OnAvatarPickerRequest -= new AvatarPickerRequest(HandleAvatarPickerRequest); | 155 | client.OnAvatarPickerRequest -= new AvatarPickerRequest(HandleAvatarPickerRequest); |
158 | } | 156 | } |
159 | 157 | ||
160 | void HandleUUIDNameRequest(UUID uuid, IClientAPI remote_client) | 158 | void HandleUUIDNameRequest(UUID uuid, IClientAPI client) |
161 | { | 159 | { |
160 | // m_log.DebugFormat( | ||
161 | // "[USER MANAGEMENT MODULE]: Handling request for name binding of UUID {0} from {1}", | ||
162 | // uuid, remote_client.Name); | ||
163 | |||
162 | if (m_Scenes[0].LibraryService != null && (m_Scenes[0].LibraryService.LibraryRootFolder.Owner == uuid)) | 164 | if (m_Scenes[0].LibraryService != null && (m_Scenes[0].LibraryService.LibraryRootFolder.Owner == uuid)) |
163 | { | 165 | { |
164 | remote_client.SendNameReply(uuid, "Mr", "OpenSim"); | 166 | client.SendNameReply(uuid, "Mr", "OpenSim"); |
165 | } | 167 | } |
166 | else | 168 | else |
167 | { | 169 | { |
168 | string[] names = GetUserNames(uuid); | 170 | string[] names = new string[2]; |
169 | if (names.Length == 2) | 171 | if (TryGetUserNamesFromCache(uuid, names)) |
170 | { | 172 | { |
171 | //m_log.DebugFormat("[XXX] HandleUUIDNameRequest {0} is {1} {2}", uuid, names[0], names[1]); | 173 | client.SendNameReply(uuid, names[0], names[1]); |
172 | remote_client.SendNameReply(uuid, names[0], names[1]); | 174 | return; |
173 | } | 175 | } |
174 | 176 | ||
177 | // Not found in cache, queue continuation | ||
178 | m_ServiceThrottle.Enqueue("name", uuid.ToString(), delegate | ||
179 | { | ||
180 | //m_log.DebugFormat("[YYY]: Name request {0}", uuid); | ||
181 | |||
182 | // As least upto September 2013, clients permanently cache UUID -> Name bindings. Some clients | ||
183 | // appear to clear this when the user asks it to clear the cache, but others may not. | ||
184 | // | ||
185 | // So to avoid clients | ||
186 | // (particularly Hypergrid clients) permanently binding "Unknown User" to a given UUID, we will | ||
187 | // instead drop the request entirely. | ||
188 | if (TryGetUserNames(uuid, names)) | ||
189 | client.SendNameReply(uuid, names[0], names[1]); | ||
190 | // else | ||
191 | // m_log.DebugFormat( | ||
192 | // "[USER MANAGEMENT MODULE]: No bound name for {0} found, ignoring request from {1}", | ||
193 | // uuid, client.Name); | ||
194 | }); | ||
175 | } | 195 | } |
176 | } | 196 | } |
177 | 197 | ||
@@ -181,29 +201,7 @@ namespace OpenSim.Region.CoreModules.Framework.UserManagement | |||
181 | 201 | ||
182 | m_log.DebugFormat("[USER MANAGEMENT MODULE]: HandleAvatarPickerRequest for {0}", query); | 202 | m_log.DebugFormat("[USER MANAGEMENT MODULE]: HandleAvatarPickerRequest for {0}", query); |
183 | 203 | ||
184 | // searhc the user accounts service | 204 | List<UserData> users = GetUserData(query, 500, 1); |
185 | List<UserAccount> accs = m_Scenes[0].UserAccountService.GetUserAccounts(m_Scenes[0].RegionInfo.ScopeID, query); | ||
186 | |||
187 | List<UserData> users = new List<UserData>(); | ||
188 | if (accs != null) | ||
189 | { | ||
190 | foreach (UserAccount acc in accs) | ||
191 | { | ||
192 | UserData ud = new UserData(); | ||
193 | ud.FirstName = acc.FirstName; | ||
194 | ud.LastName = acc.LastName; | ||
195 | ud.Id = acc.PrincipalID; | ||
196 | users.Add(ud); | ||
197 | } | ||
198 | } | ||
199 | |||
200 | // search the local cache | ||
201 | foreach (UserData data in m_UserCache.Values) | ||
202 | if (users.Find(delegate(UserData d) { return d.Id == data.Id; }) == null && | ||
203 | (data.FirstName.StartsWith(query) || data.LastName.StartsWith(query))) | ||
204 | users.Add(data); | ||
205 | |||
206 | AddAdditionalUsers(avatarID, query, users); | ||
207 | 205 | ||
208 | AvatarPickerReplyPacket replyPacket = (AvatarPickerReplyPacket)PacketPool.Instance.GetPacket(PacketType.AvatarPickerReply); | 206 | AvatarPickerReplyPacket replyPacket = (AvatarPickerReplyPacket)PacketPool.Instance.GetPacket(PacketType.AvatarPickerReply); |
209 | // TODO: don't create new blocks if recycling an old packet | 207 | // TODO: don't create new blocks if recycling an old packet |
@@ -249,12 +247,51 @@ namespace OpenSim.Region.CoreModules.Framework.UserManagement | |||
249 | client.SendAvatarPickerReply(agent_data, data_args); | 247 | client.SendAvatarPickerReply(agent_data, data_args); |
250 | } | 248 | } |
251 | 249 | ||
252 | protected virtual void AddAdditionalUsers(UUID avatarID, string query, List<UserData> users) | 250 | protected virtual void AddAdditionalUsers(string query, List<UserData> users) |
253 | { | 251 | { |
254 | } | 252 | } |
255 | 253 | ||
256 | #endregion Event Handlers | 254 | #endregion Event Handlers |
257 | 255 | ||
256 | #region IPeople | ||
257 | |||
258 | public List<UserData> GetUserData(string query, int page_size, int page_number) | ||
259 | { | ||
260 | // search the user accounts service | ||
261 | List<UserAccount> accs = m_Scenes[0].UserAccountService.GetUserAccounts(m_Scenes[0].RegionInfo.ScopeID, query); | ||
262 | |||
263 | List<UserData> users = new List<UserData>(); | ||
264 | if (accs != null) | ||
265 | { | ||
266 | foreach (UserAccount acc in accs) | ||
267 | { | ||
268 | UserData ud = new UserData(); | ||
269 | ud.FirstName = acc.FirstName; | ||
270 | ud.LastName = acc.LastName; | ||
271 | ud.Id = acc.PrincipalID; | ||
272 | users.Add(ud); | ||
273 | } | ||
274 | } | ||
275 | |||
276 | // search the local cache | ||
277 | lock (m_UserCache) | ||
278 | { | ||
279 | foreach (UserData data in m_UserCache.Values) | ||
280 | { | ||
281 | if (users.Find(delegate(UserData d) { return d.Id == data.Id; }) == null && | ||
282 | (data.FirstName.ToLower().StartsWith(query.ToLower()) || data.LastName.ToLower().StartsWith(query.ToLower()))) | ||
283 | users.Add(data); | ||
284 | } | ||
285 | } | ||
286 | |||
287 | AddAdditionalUsers(query, users); | ||
288 | |||
289 | return users; | ||
290 | |||
291 | } | ||
292 | |||
293 | #endregion IPeople | ||
294 | |||
258 | private void CacheCreators(SceneObjectGroup sog) | 295 | private void CacheCreators(SceneObjectGroup sog) |
259 | { | 296 | { |
260 | //m_log.DebugFormat("[USER MANAGEMENT MODULE]: processing {0} {1}; {2}", sog.RootPart.Name, sog.RootPart.CreatorData, sog.RootPart.CreatorIdentification); | 297 | //m_log.DebugFormat("[USER MANAGEMENT MODULE]: processing {0} {1}; {2}", sog.RootPart.Name, sog.RootPart.CreatorData, sog.RootPart.CreatorIdentification); |
@@ -268,26 +305,56 @@ namespace OpenSim.Region.CoreModules.Framework.UserManagement | |||
268 | } | 305 | } |
269 | } | 306 | } |
270 | 307 | ||
271 | private string[] GetUserNames(UUID uuid) | 308 | /// <summary> |
309 | /// | ||
310 | /// </summary> | ||
311 | /// <param name="uuid"></param> | ||
312 | /// <param name="names">Caller please provide a properly instantiated array for names, string[2]</param> | ||
313 | /// <returns></returns> | ||
314 | private bool TryGetUserNames(UUID uuid, string[] names) | ||
272 | { | 315 | { |
273 | string[] returnstring = new string[2]; | 316 | if (names == null) |
317 | names = new string[2]; | ||
318 | |||
319 | if (TryGetUserNamesFromCache(uuid, names)) | ||
320 | return true; | ||
321 | |||
322 | if (TryGetUserNamesFromServices(uuid, names)) | ||
323 | return true; | ||
324 | |||
325 | return false; | ||
326 | } | ||
274 | 327 | ||
328 | private bool TryGetUserNamesFromCache(UUID uuid, string[] names) | ||
329 | { | ||
275 | lock (m_UserCache) | 330 | lock (m_UserCache) |
276 | { | 331 | { |
277 | if (m_UserCache.ContainsKey(uuid)) | 332 | if (m_UserCache.ContainsKey(uuid)) |
278 | { | 333 | { |
279 | returnstring[0] = m_UserCache[uuid].FirstName; | 334 | names[0] = m_UserCache[uuid].FirstName; |
280 | returnstring[1] = m_UserCache[uuid].LastName; | 335 | names[1] = m_UserCache[uuid].LastName; |
281 | return returnstring; | 336 | |
337 | return true; | ||
282 | } | 338 | } |
283 | } | 339 | } |
284 | 340 | ||
341 | return false; | ||
342 | } | ||
343 | |||
344 | /// <summary> | ||
345 | /// Try to get the names bound to the given uuid, from the services. | ||
346 | /// </summary> | ||
347 | /// <returns>True if the name was found, false if not.</returns> | ||
348 | /// <param name='uuid'></param> | ||
349 | /// <param name='names'>The array of names if found. If not found, then names[0] = "Unknown" and names[1] = "User"</param> | ||
350 | private bool TryGetUserNamesFromServices(UUID uuid, string[] names) | ||
351 | { | ||
285 | UserAccount account = m_Scenes[0].UserAccountService.GetUserAccount(UUID.Zero, uuid); | 352 | UserAccount account = m_Scenes[0].UserAccountService.GetUserAccount(UUID.Zero, uuid); |
286 | 353 | ||
287 | if (account != null) | 354 | if (account != null) |
288 | { | 355 | { |
289 | returnstring[0] = account.FirstName; | 356 | names[0] = account.FirstName; |
290 | returnstring[1] = account.LastName; | 357 | names[1] = account.LastName; |
291 | 358 | ||
292 | UserData user = new UserData(); | 359 | UserData user = new UserData(); |
293 | user.FirstName = account.FirstName; | 360 | user.FirstName = account.FirstName; |
@@ -295,14 +362,42 @@ namespace OpenSim.Region.CoreModules.Framework.UserManagement | |||
295 | 362 | ||
296 | lock (m_UserCache) | 363 | lock (m_UserCache) |
297 | m_UserCache[uuid] = user; | 364 | m_UserCache[uuid] = user; |
365 | |||
366 | return true; | ||
298 | } | 367 | } |
299 | else | 368 | else |
300 | { | 369 | { |
301 | returnstring[0] = "Unknown"; | 370 | // Let's try the GridUser service |
302 | returnstring[1] = "User"; | 371 | GridUserInfo uInfo = m_Scenes[0].GridUserService.GetGridUserInfo(uuid.ToString()); |
303 | } | 372 | if (uInfo != null) |
373 | { | ||
374 | string url, first, last, tmp; | ||
375 | UUID u; | ||
376 | if (Util.ParseUniversalUserIdentifier(uInfo.UserID, out u, out url, out first, out last, out tmp)) | ||
377 | { | ||
378 | AddUser(uuid, first, last, url); | ||
379 | |||
380 | if (m_UserCache.ContainsKey(uuid)) | ||
381 | { | ||
382 | names[0] = m_UserCache[uuid].FirstName; | ||
383 | names[1] = m_UserCache[uuid].LastName; | ||
384 | |||
385 | return true; | ||
386 | } | ||
387 | } | ||
388 | else | ||
389 | m_log.DebugFormat("[USER MANAGEMENT MODULE]: Unable to parse UUI {0}", uInfo.UserID); | ||
390 | } | ||
391 | else | ||
392 | { | ||
393 | m_log.DebugFormat("[USER MANAGEMENT MODULE]: No grid user found for {0}", uuid); | ||
394 | } | ||
304 | 395 | ||
305 | return returnstring; | 396 | names[0] = "Unknown"; |
397 | names[1] = "UserUMMTGUN9"; | ||
398 | |||
399 | return false; | ||
400 | } | ||
306 | } | 401 | } |
307 | 402 | ||
308 | #region IUserManagement | 403 | #region IUserManagement |
@@ -338,16 +433,11 @@ namespace OpenSim.Region.CoreModules.Framework.UserManagement | |||
338 | 433 | ||
339 | public string GetUserName(UUID uuid) | 434 | public string GetUserName(UUID uuid) |
340 | { | 435 | { |
341 | string[] names = GetUserNames(uuid); | 436 | string[] names = new string[2]; |
342 | if (names.Length == 2) | 437 | TryGetUserNames(uuid, names); |
343 | { | ||
344 | string firstname = names[0]; | ||
345 | string lastname = names[1]; | ||
346 | 438 | ||
347 | return firstname + " " + lastname; | 439 | return names[0] + " " + names[1]; |
348 | 440 | ||
349 | } | ||
350 | return "(hippos)"; | ||
351 | } | 441 | } |
352 | 442 | ||
353 | public string GetUserHomeURL(UUID userID) | 443 | public string GetUserHomeURL(UUID userID) |
@@ -376,7 +466,7 @@ namespace OpenSim.Region.CoreModules.Framework.UserManagement | |||
376 | return userdata.ServerURLs[serverType].ToString(); | 466 | return userdata.ServerURLs[serverType].ToString(); |
377 | } | 467 | } |
378 | 468 | ||
379 | if (userdata.HomeURL != null && userdata.HomeURL != string.Empty) | 469 | if (!string.IsNullOrEmpty(userdata.HomeURL)) |
380 | { | 470 | { |
381 | //m_log.DebugFormat( | 471 | //m_log.DebugFormat( |
382 | // "[USER MANAGEMENT MODULE]: Did not find url type {0} so requesting urls from '{1}' for {2}", | 472 | // "[USER MANAGEMENT MODULE]: Did not find url type {0} so requesting urls from '{1}' for {2}", |
@@ -394,14 +484,20 @@ namespace OpenSim.Region.CoreModules.Framework.UserManagement | |||
394 | 484 | ||
395 | public string GetUserUUI(UUID userID) | 485 | public string GetUserUUI(UUID userID) |
396 | { | 486 | { |
397 | UserAccount account = m_Scenes[0].UserAccountService.GetUserAccount(m_Scenes[0].RegionInfo.ScopeID, userID); | ||
398 | if (account != null) | ||
399 | return userID.ToString(); | ||
400 | |||
401 | UserData ud; | 487 | UserData ud; |
402 | lock (m_UserCache) | 488 | lock (m_UserCache) |
403 | m_UserCache.TryGetValue(userID, out ud); | 489 | m_UserCache.TryGetValue(userID, out ud); |
404 | 490 | ||
491 | if (ud == null) // It's not in the cache | ||
492 | { | ||
493 | string[] names = new string[2]; | ||
494 | // This will pull the data from either UserAccounts or GridUser | ||
495 | // and stick it into the cache | ||
496 | TryGetUserNamesFromServices(userID, names); | ||
497 | lock (m_UserCache) | ||
498 | m_UserCache.TryGetValue(userID, out ud); | ||
499 | } | ||
500 | |||
405 | if (ud != null) | 501 | if (ud != null) |
406 | { | 502 | { |
407 | string homeURL = ud.HomeURL; | 503 | string homeURL = ud.HomeURL; |
@@ -446,77 +542,81 @@ namespace OpenSim.Region.CoreModules.Framework.UserManagement | |||
446 | AddUser(uuid, homeURL + ";" + first + " " + last); | 542 | AddUser(uuid, homeURL + ";" + first + " " + last); |
447 | } | 543 | } |
448 | 544 | ||
449 | public void AddUser (UUID id, string creatorData) | 545 | public void AddUser(UUID id, string creatorData) |
450 | { | 546 | { |
451 | //m_log.DebugFormat("[USER MANAGEMENT MODULE]: Adding user with id {0}, creatorData {1}", id, creatorData); | 547 | //m_log.DebugFormat("[USER MANAGEMENT MODULE]: Adding user with id {0}, creatorData {1}", id, creatorData); |
452 | 548 | ||
453 | UserData oldUser; | 549 | UserData oldUser; |
454 | //lock the whole block - prevent concurrent update | ||
455 | lock (m_UserCache) | 550 | lock (m_UserCache) |
551 | m_UserCache.TryGetValue(id, out oldUser); | ||
552 | |||
553 | if (oldUser != null) | ||
456 | { | 554 | { |
457 | m_UserCache.TryGetValue (id, out oldUser); | 555 | if (string.IsNullOrEmpty(creatorData)) |
458 | if (oldUser != null) | ||
459 | { | 556 | { |
460 | if (creatorData == null || creatorData == String.Empty) | 557 | //ignore updates without creator data |
461 | { | 558 | return; |
462 | //ignore updates without creator data | ||
463 | return; | ||
464 | } | ||
465 | //try update unknown users | ||
466 | //and creator's home URL's | ||
467 | if ((oldUser.FirstName == "Unknown" && !creatorData.Contains ("Unknown")) || (oldUser.HomeURL != null && !creatorData.StartsWith (oldUser.HomeURL))) | ||
468 | { | ||
469 | m_UserCache.Remove (id); | ||
470 | // m_log.DebugFormat("[USER MANAGEMENT MODULE]: Re-adding user with id {0}, creatorData [{1}] and old HomeURL {2}", id, creatorData,oldUser.HomeURL); | ||
471 | } | ||
472 | else | ||
473 | { | ||
474 | //we have already a valid user within the cache | ||
475 | return; | ||
476 | } | ||
477 | } | 559 | } |
478 | 560 | ||
479 | UserAccount account = m_Scenes[0].UserAccountService.GetUserAccount (m_Scenes [0].RegionInfo.ScopeID, id); | 561 | //try update unknown users, but don't update anyone else |
480 | 562 | if (oldUser.FirstName == "Unknown" && !creatorData.Contains("Unknown")) | |
481 | if (account != null) | ||
482 | { | 563 | { |
483 | AddUser (id, account.FirstName, account.LastName); | 564 | lock (m_UserCache) |
565 | m_UserCache.Remove(id); | ||
566 | m_log.DebugFormat("[USER MANAGEMENT MODULE]: Re-adding user with id {0}, creatorData [{1}] and old HomeURL {2}", id, creatorData, oldUser.HomeURL); | ||
484 | } | 567 | } |
485 | else | 568 | else |
486 | { | 569 | { |
487 | UserData user = new UserData (); | 570 | //we have already a valid user within the cache |
488 | user.Id = id; | 571 | return; |
572 | } | ||
573 | } | ||
489 | 574 | ||
490 | if (creatorData != null && creatorData != string.Empty) | 575 | UserAccount account = m_Scenes[0].UserAccountService.GetUserAccount(m_Scenes[0].RegionInfo.ScopeID, id); |
491 | { | ||
492 | //creatorData = <endpoint>;<name> | ||
493 | 576 | ||
494 | string[] parts = creatorData.Split (';'); | 577 | if (account != null) |
495 | if (parts.Length >= 1) | 578 | { |
579 | AddUser(id, account.FirstName, account.LastName); | ||
580 | } | ||
581 | else | ||
582 | { | ||
583 | UserData user = new UserData(); | ||
584 | user.Id = id; | ||
585 | |||
586 | if (!string.IsNullOrEmpty(creatorData)) | ||
587 | { | ||
588 | //creatorData = <endpoint>;<name> | ||
589 | |||
590 | string[] parts = creatorData.Split(';'); | ||
591 | if (parts.Length >= 1) | ||
592 | { | ||
593 | user.HomeURL = parts[0]; | ||
594 | try | ||
496 | { | 595 | { |
497 | user.HomeURL = parts [0]; | 596 | Uri uri = new Uri(parts[0]); |
498 | try | 597 | user.LastName = "@" + uri.Authority; |
499 | { | 598 | } |
500 | Uri uri = new Uri (parts [0]); | 599 | catch (UriFormatException) |
501 | user.LastName = "@" + uri.Authority; | 600 | { |
502 | } | 601 | m_log.DebugFormat("[SCENE]: Unable to parse Uri {0}", parts[0]); |
503 | catch (UriFormatException) | 602 | user.LastName = "@unknown"; |
504 | { | ||
505 | m_log.DebugFormat ("[SCENE]: Unable to parse Uri {0}", parts [0]); | ||
506 | user.LastName = "@unknown"; | ||
507 | } | ||
508 | } | 603 | } |
509 | if (parts.Length >= 2) | ||
510 | user.FirstName = parts [1].Replace (' ', '.'); | ||
511 | } | ||
512 | else | ||
513 | { | ||
514 | user.FirstName = "Unknown"; | ||
515 | user.LastName = "User"; | ||
516 | } | 604 | } |
517 | 605 | ||
518 | AddUserInternal (user); | 606 | if (parts.Length >= 2) |
607 | user.FirstName = parts[1].Replace(' ', '.'); | ||
608 | } | ||
609 | else | ||
610 | { | ||
611 | // Temporarily add unknown user entries of this type into the cache so that we can distinguish | ||
612 | // this source from other recent (hopefully resolved) bugs that fail to retrieve a user name binding | ||
613 | // TODO: Can be removed when GUN* unknown users have definitely dropped significantly or | ||
614 | // disappeared. | ||
615 | user.FirstName = "Unknown"; | ||
616 | user.LastName = "UserUMMAU4"; | ||
519 | } | 617 | } |
618 | |||
619 | AddUserInternal(user); | ||
520 | } | 620 | } |
521 | } | 621 | } |
522 | 622 | ||
@@ -541,9 +641,22 @@ namespace OpenSim.Region.CoreModules.Framework.UserManagement | |||
541 | 641 | ||
542 | #endregion IUserManagement | 642 | #endregion IUserManagement |
543 | 643 | ||
644 | protected void Init() | ||
645 | { | ||
646 | AddUser(UUID.Zero, "Unknown", "User"); | ||
647 | RegisterConsoleCmds(); | ||
648 | } | ||
649 | |||
544 | protected void RegisterConsoleCmds() | 650 | protected void RegisterConsoleCmds() |
545 | { | 651 | { |
546 | MainConsole.Instance.Commands.AddCommand("Users", true, | 652 | MainConsole.Instance.Commands.AddCommand("Users", true, |
653 | "show name", | ||
654 | "show name <uuid>", | ||
655 | "Show the bindings between a single user UUID and a user name", | ||
656 | String.Empty, | ||
657 | HandleShowUser); | ||
658 | |||
659 | MainConsole.Instance.Commands.AddCommand("Users", true, | ||
547 | "show names", | 660 | "show names", |
548 | "show names", | 661 | "show names", |
549 | "Show the bindings between user UUIDs and user names", | 662 | "Show the bindings between user UUIDs and user names", |
@@ -551,26 +664,56 @@ namespace OpenSim.Region.CoreModules.Framework.UserManagement | |||
551 | HandleShowUsers); | 664 | HandleShowUsers); |
552 | } | 665 | } |
553 | 666 | ||
554 | private void HandleShowUsers(string module, string[] cmd) | 667 | private void HandleShowUser(string module, string[] cmd) |
555 | { | 668 | { |
669 | if (cmd.Length < 3) | ||
670 | { | ||
671 | MainConsole.Instance.OutputFormat("Usage: show name <uuid>"); | ||
672 | return; | ||
673 | } | ||
674 | |||
675 | UUID userId; | ||
676 | if (!ConsoleUtil.TryParseConsoleUuid(MainConsole.Instance, cmd[2], out userId)) | ||
677 | return; | ||
678 | |||
679 | string[] names; | ||
680 | |||
681 | UserData ud; | ||
682 | |||
556 | lock (m_UserCache) | 683 | lock (m_UserCache) |
557 | { | 684 | { |
558 | if (m_UserCache.Count == 0) | 685 | if (!m_UserCache.TryGetValue(userId, out ud)) |
559 | { | 686 | { |
560 | MainConsole.Instance.Output("No users found"); | 687 | MainConsole.Instance.OutputFormat("No name known for user with id {0}", userId); |
561 | return; | 688 | return; |
562 | } | 689 | } |
563 | 690 | } | |
564 | MainConsole.Instance.Output("UUID User Name"); | 691 | |
565 | MainConsole.Instance.Output("-----------------------------------------------------------------------------"); | 692 | ConsoleDisplayTable cdt = new ConsoleDisplayTable(); |
693 | cdt.AddColumn("UUID", 36); | ||
694 | cdt.AddColumn("Name", 30); | ||
695 | cdt.AddColumn("HomeURL", 40); | ||
696 | cdt.AddRow(userId, string.Format("{0} {1}", ud.FirstName, ud.LastName), ud.HomeURL); | ||
697 | |||
698 | MainConsole.Instance.Output(cdt.ToString()); | ||
699 | } | ||
700 | |||
701 | private void HandleShowUsers(string module, string[] cmd) | ||
702 | { | ||
703 | ConsoleDisplayTable cdt = new ConsoleDisplayTable(); | ||
704 | cdt.AddColumn("UUID", 36); | ||
705 | cdt.AddColumn("Name", 30); | ||
706 | cdt.AddColumn("HomeURL", 40); | ||
707 | |||
708 | lock (m_UserCache) | ||
709 | { | ||
566 | foreach (KeyValuePair<UUID, UserData> kvp in m_UserCache) | 710 | foreach (KeyValuePair<UUID, UserData> kvp in m_UserCache) |
567 | { | 711 | cdt.AddRow(kvp.Key, string.Format("{0} {1}", kvp.Value.FirstName, kvp.Value.LastName), kvp.Value.HomeURL); |
568 | MainConsole.Instance.Output(String.Format("{0} {1} {2} ({3})", | ||
569 | kvp.Key, kvp.Value.FirstName, kvp.Value.LastName, kvp.Value.HomeURL)); | ||
570 | } | ||
571 | |||
572 | return; | ||
573 | } | 712 | } |
713 | |||
714 | MainConsole.Instance.Output(cdt.ToString()); | ||
574 | } | 715 | } |
716 | |||
575 | } | 717 | } |
718 | |||
576 | } \ No newline at end of file | 719 | } \ No newline at end of file |