diff options
Diffstat (limited to '')
-rw-r--r-- | OpenSim/Region/CoreModules/Framework/UserManagement/UserManagementModule.cs | 619 |
1 files changed, 421 insertions, 198 deletions
diff --git a/OpenSim/Region/CoreModules/Framework/UserManagement/UserManagementModule.cs b/OpenSim/Region/CoreModules/Framework/UserManagement/UserManagementModule.cs index 77e8b00..7ecbd26 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,28 +46,24 @@ 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 | ||
65 | protected bool m_DisplayChangingHomeURI = false; | ||
66 | |||
69 | #region ISharedRegionModule | 67 | #region ISharedRegionModule |
70 | 68 | ||
71 | public void Initialise(IConfigSource config) | 69 | public void Initialise(IConfigSource config) |
@@ -74,9 +72,20 @@ namespace OpenSim.Region.CoreModules.Framework.UserManagement | |||
74 | if (umanmod == Name) | 72 | if (umanmod == Name) |
75 | { | 73 | { |
76 | m_Enabled = true; | 74 | m_Enabled = true; |
77 | RegisterConsoleCmds(); | 75 | Init(); |
78 | m_log.DebugFormat("[USER MANAGEMENT MODULE]: {0} is enabled", Name); | 76 | m_log.DebugFormat("[USER MANAGEMENT MODULE]: {0} is enabled", Name); |
79 | } | 77 | } |
78 | |||
79 | if(!m_Enabled) | ||
80 | { | ||
81 | return; | ||
82 | } | ||
83 | |||
84 | IConfig userManagementConfig = config.Configs["UserManagement"]; | ||
85 | if (userManagementConfig == null) | ||
86 | return; | ||
87 | |||
88 | m_DisplayChangingHomeURI = userManagementConfig.GetBoolean("DisplayChangingHomeURI", false); | ||
80 | } | 89 | } |
81 | 90 | ||
82 | public bool IsSharedModule | 91 | public bool IsSharedModule |
@@ -98,9 +107,13 @@ namespace OpenSim.Region.CoreModules.Framework.UserManagement | |||
98 | { | 107 | { |
99 | if (m_Enabled) | 108 | if (m_Enabled) |
100 | { | 109 | { |
101 | m_Scenes.Add(scene); | 110 | lock (m_Scenes) |
111 | { | ||
112 | m_Scenes.Add(scene); | ||
113 | } | ||
102 | 114 | ||
103 | scene.RegisterModuleInterface<IUserManagement>(this); | 115 | scene.RegisterModuleInterface<IUserManagement>(this); |
116 | scene.RegisterModuleInterface<IPeople>(this); | ||
104 | scene.EventManager.OnNewClient += new EventManager.OnNewClientDelegate(EventManager_OnNewClient); | 117 | scene.EventManager.OnNewClient += new EventManager.OnNewClientDelegate(EventManager_OnNewClient); |
105 | scene.EventManager.OnPrimsLoaded += new EventManager.PrimsLoaded(EventManager_OnPrimsLoaded); | 118 | scene.EventManager.OnPrimsLoaded += new EventManager.PrimsLoaded(EventManager_OnPrimsLoaded); |
106 | } | 119 | } |
@@ -111,12 +124,17 @@ namespace OpenSim.Region.CoreModules.Framework.UserManagement | |||
111 | if (m_Enabled) | 124 | if (m_Enabled) |
112 | { | 125 | { |
113 | scene.UnregisterModuleInterface<IUserManagement>(this); | 126 | scene.UnregisterModuleInterface<IUserManagement>(this); |
114 | m_Scenes.Remove(scene); | 127 | lock (m_Scenes) |
128 | { | ||
129 | m_Scenes.Remove(scene); | ||
130 | } | ||
115 | } | 131 | } |
116 | } | 132 | } |
117 | 133 | ||
118 | public void RegionLoaded(Scene s) | 134 | public void RegionLoaded(Scene s) |
119 | { | 135 | { |
136 | if (m_Enabled && m_ServiceThrottle == null) | ||
137 | m_ServiceThrottle = s.RequestModuleInterface<IServiceThrottleModule>(); | ||
120 | } | 138 | } |
121 | 139 | ||
122 | public void PostInitialise() | 140 | public void PostInitialise() |
@@ -125,7 +143,10 @@ namespace OpenSim.Region.CoreModules.Framework.UserManagement | |||
125 | 143 | ||
126 | public void Close() | 144 | public void Close() |
127 | { | 145 | { |
128 | m_Scenes.Clear(); | 146 | lock (m_Scenes) |
147 | { | ||
148 | m_Scenes.Clear(); | ||
149 | } | ||
129 | 150 | ||
130 | lock (m_UserCache) | 151 | lock (m_UserCache) |
131 | m_UserCache.Clear(); | 152 | m_UserCache.Clear(); |
@@ -133,7 +154,7 @@ namespace OpenSim.Region.CoreModules.Framework.UserManagement | |||
133 | 154 | ||
134 | #endregion ISharedRegionModule | 155 | #endregion ISharedRegionModule |
135 | 156 | ||
136 | 157 | ||
137 | #region Event Handlers | 158 | #region Event Handlers |
138 | 159 | ||
139 | void EventManager_OnPrimsLoaded(Scene s) | 160 | void EventManager_OnPrimsLoaded(Scene s) |
@@ -143,7 +164,6 @@ namespace OpenSim.Region.CoreModules.Framework.UserManagement | |||
143 | s.ForEachSOG(delegate(SceneObjectGroup sog) { CacheCreators(sog); }); | 164 | s.ForEachSOG(delegate(SceneObjectGroup sog) { CacheCreators(sog); }); |
144 | } | 165 | } |
145 | 166 | ||
146 | |||
147 | void EventManager_OnNewClient(IClientAPI client) | 167 | void EventManager_OnNewClient(IClientAPI client) |
148 | { | 168 | { |
149 | client.OnConnectionClosed += new Action<IClientAPI>(HandleConnectionClosed); | 169 | client.OnConnectionClosed += new Action<IClientAPI>(HandleConnectionClosed); |
@@ -157,21 +177,52 @@ namespace OpenSim.Region.CoreModules.Framework.UserManagement | |||
157 | client.OnAvatarPickerRequest -= new AvatarPickerRequest(HandleAvatarPickerRequest); | 177 | client.OnAvatarPickerRequest -= new AvatarPickerRequest(HandleAvatarPickerRequest); |
158 | } | 178 | } |
159 | 179 | ||
160 | void HandleUUIDNameRequest(UUID uuid, IClientAPI remote_client) | 180 | void HandleUUIDNameRequest(UUID uuid, IClientAPI client) |
161 | { | 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 | |||
162 | if (m_Scenes[0].LibraryService != null && (m_Scenes[0].LibraryService.LibraryRootFolder.Owner == uuid)) | 186 | if (m_Scenes[0].LibraryService != null && (m_Scenes[0].LibraryService.LibraryRootFolder.Owner == uuid)) |
163 | { | 187 | { |
164 | remote_client.SendNameReply(uuid, "Mr", "OpenSim"); | 188 | client.SendNameReply(uuid, "Mr", "OpenSim"); |
165 | } | 189 | } |
166 | else | 190 | else |
167 | { | 191 | { |
168 | string[] names = GetUserNames(uuid); | 192 | UserData user; |
169 | if (names.Length == 2) | 193 | /* bypass that continuation here when entry is already available */ |
194 | lock (m_UserCache) | ||
170 | { | 195 | { |
171 | //m_log.DebugFormat("[XXX] HandleUUIDNameRequest {0} is {1} {2}", uuid, names[0], names[1]); | 196 | if (m_UserCache.TryGetValue(uuid, out user)) |
172 | remote_client.SendNameReply(uuid, names[0], names[1]); | 197 | { |
198 | if (!user.IsUnknownUser && user.HasGridUserTried) | ||
199 | { | ||
200 | client.SendNameReply(uuid, user.FirstName, user.LastName); | ||
201 | return; | ||
202 | } | ||
203 | } | ||
173 | } | 204 | } |
174 | 205 | ||
206 | // Not found in cache, queue continuation | ||
207 | m_ServiceThrottle.Enqueue("name", uuid.ToString(), delegate | ||
208 | { | ||
209 | //m_log.DebugFormat("[YYY]: Name request {0}", uuid); | ||
210 | |||
211 | // As least upto September 2013, clients permanently cache UUID -> Name bindings. Some clients | ||
212 | // appear to clear this when the user asks it to clear the cache, but others may not. | ||
213 | // | ||
214 | // So to avoid clients | ||
215 | // (particularly Hypergrid clients) permanently binding "Unknown User" to a given UUID, we will | ||
216 | // instead drop the request entirely. | ||
217 | if (GetUser(uuid, out user)) | ||
218 | { | ||
219 | client.SendNameReply(uuid, user.FirstName, user.LastName); | ||
220 | } | ||
221 | // else | ||
222 | // m_log.DebugFormat( | ||
223 | // "[USER MANAGEMENT MODULE]: No bound name for {0} found, ignoring request from {1}", | ||
224 | // uuid, client.Name); | ||
225 | }); | ||
175 | } | 226 | } |
176 | } | 227 | } |
177 | 228 | ||
@@ -181,29 +232,7 @@ namespace OpenSim.Region.CoreModules.Framework.UserManagement | |||
181 | 232 | ||
182 | m_log.DebugFormat("[USER MANAGEMENT MODULE]: HandleAvatarPickerRequest for {0}", query); | 233 | m_log.DebugFormat("[USER MANAGEMENT MODULE]: HandleAvatarPickerRequest for {0}", query); |
183 | 234 | ||
184 | // searhc the user accounts service | 235 | 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 | 236 | ||
208 | AvatarPickerReplyPacket replyPacket = (AvatarPickerReplyPacket)PacketPool.Instance.GetPacket(PacketType.AvatarPickerReply); | 237 | AvatarPickerReplyPacket replyPacket = (AvatarPickerReplyPacket)PacketPool.Instance.GetPacket(PacketType.AvatarPickerReply); |
209 | // TODO: don't create new blocks if recycling an old packet | 238 | // TODO: don't create new blocks if recycling an old packet |
@@ -249,60 +278,62 @@ namespace OpenSim.Region.CoreModules.Framework.UserManagement | |||
249 | client.SendAvatarPickerReply(agent_data, data_args); | 278 | client.SendAvatarPickerReply(agent_data, data_args); |
250 | } | 279 | } |
251 | 280 | ||
252 | protected virtual void AddAdditionalUsers(UUID avatarID, string query, List<UserData> users) | 281 | protected virtual void AddAdditionalUsers(string query, List<UserData> users) |
253 | { | 282 | { |
254 | } | 283 | } |
255 | 284 | ||
256 | #endregion Event Handlers | 285 | #endregion Event Handlers |
257 | 286 | ||
258 | private void CacheCreators(SceneObjectGroup sog) | 287 | #region IPeople |
259 | { | ||
260 | //m_log.DebugFormat("[USER MANAGEMENT MODULE]: processing {0} {1}; {2}", sog.RootPart.Name, sog.RootPart.CreatorData, sog.RootPart.CreatorIdentification); | ||
261 | AddUser(sog.RootPart.CreatorID, sog.RootPart.CreatorData); | ||
262 | |||
263 | foreach (SceneObjectPart sop in sog.Parts) | ||
264 | { | ||
265 | AddUser(sop.CreatorID, sop.CreatorData); | ||
266 | foreach (TaskInventoryItem item in sop.TaskInventory.Values) | ||
267 | AddUser(item.CreatorID, item.CreatorData); | ||
268 | } | ||
269 | } | ||
270 | 288 | ||
271 | private string[] GetUserNames(UUID uuid) | 289 | public List<UserData> GetUserData(string query, int page_size, int page_number) |
272 | { | 290 | { |
273 | string[] returnstring = new string[2]; | 291 | // search the user accounts service |
292 | List<UserAccount> accs = m_Scenes[0].UserAccountService.GetUserAccounts(m_Scenes[0].RegionInfo.ScopeID, query); | ||
274 | 293 | ||
275 | lock (m_UserCache) | 294 | List<UserData> users = new List<UserData>(); |
295 | if (accs != null) | ||
276 | { | 296 | { |
277 | if (m_UserCache.ContainsKey(uuid)) | 297 | foreach (UserAccount acc in accs) |
278 | { | 298 | { |
279 | returnstring[0] = m_UserCache[uuid].FirstName; | 299 | UserData ud = new UserData(); |
280 | returnstring[1] = m_UserCache[uuid].LastName; | 300 | ud.FirstName = acc.FirstName; |
281 | return returnstring; | 301 | ud.LastName = acc.LastName; |
302 | ud.Id = acc.PrincipalID; | ||
303 | ud.HasGridUserTried = true; | ||
304 | ud.IsUnknownUser = false; | ||
305 | users.Add(ud); | ||
282 | } | 306 | } |
283 | } | 307 | } |
284 | 308 | ||
285 | UserAccount account = m_Scenes[0].UserAccountService.GetUserAccount(UUID.Zero, uuid); | 309 | // search the local cache |
286 | 310 | foreach (UserData data in m_UserCache.Values) | |
287 | if (account != null) | ||
288 | { | 311 | { |
289 | returnstring[0] = account.FirstName; | 312 | if (data.Id != UUID.Zero && !data.IsUnknownUser && |
290 | returnstring[1] = account.LastName; | 313 | users.Find(delegate(UserData d) { return d.Id == data.Id; }) == null && |
314 | (data.FirstName.ToLower().StartsWith(query.ToLower()) || data.LastName.ToLower().StartsWith(query.ToLower()))) | ||
315 | users.Add(data); | ||
316 | } | ||
291 | 317 | ||
292 | UserData user = new UserData(); | 318 | AddAdditionalUsers(query, users); |
293 | user.FirstName = account.FirstName; | ||
294 | user.LastName = account.LastName; | ||
295 | 319 | ||
296 | lock (m_UserCache) | 320 | return users; |
297 | m_UserCache[uuid] = user; | 321 | |
298 | } | 322 | } |
299 | else | 323 | |
324 | #endregion IPeople | ||
325 | |||
326 | private void CacheCreators(SceneObjectGroup sog) | ||
327 | { | ||
328 | //m_log.DebugFormat("[USER MANAGEMENT MODULE]: processing {0} {1}; {2}", sog.RootPart.Name, sog.RootPart.CreatorData, sog.RootPart.CreatorIdentification); | ||
329 | AddUser(sog.RootPart.CreatorID, sog.RootPart.CreatorData); | ||
330 | |||
331 | foreach (SceneObjectPart sop in sog.Parts) | ||
300 | { | 332 | { |
301 | returnstring[0] = "Unknown"; | 333 | AddUser(sop.CreatorID, sop.CreatorData); |
302 | returnstring[1] = "User"; | 334 | foreach (TaskInventoryItem item in sop.TaskInventory.Values) |
335 | AddUser(item.CreatorID, item.CreatorData); | ||
303 | } | 336 | } |
304 | |||
305 | return returnstring; | ||
306 | } | 337 | } |
307 | 338 | ||
308 | #region IUserManagement | 339 | #region IUserManagement |
@@ -338,55 +369,56 @@ namespace OpenSim.Region.CoreModules.Framework.UserManagement | |||
338 | 369 | ||
339 | public string GetUserName(UUID uuid) | 370 | public string GetUserName(UUID uuid) |
340 | { | 371 | { |
341 | string[] names = GetUserNames(uuid); | 372 | UserData user; |
342 | if (names.Length == 2) | 373 | GetUser(uuid, out user); |
343 | { | 374 | return user.FirstName + " " + user.LastName; |
344 | string firstname = names[0]; | ||
345 | string lastname = names[1]; | ||
346 | |||
347 | return firstname + " " + lastname; | ||
348 | |||
349 | } | ||
350 | return "(hippos)"; | ||
351 | } | 375 | } |
352 | 376 | ||
353 | public string GetUserHomeURL(UUID userID) | 377 | public string GetUserHomeURL(UUID userID) |
354 | { | 378 | { |
355 | lock (m_UserCache) | 379 | UserData user; |
380 | if(GetUser(userID, out user)) | ||
356 | { | 381 | { |
357 | if (m_UserCache.ContainsKey(userID)) | 382 | return user.HomeURL; |
358 | return m_UserCache[userID].HomeURL; | ||
359 | } | 383 | } |
360 | |||
361 | return string.Empty; | 384 | return string.Empty; |
362 | } | 385 | } |
363 | 386 | ||
364 | public string GetUserServerURL(UUID userID, string serverType) | 387 | public string GetUserServerURL(UUID userID, string serverType) |
365 | { | 388 | { |
366 | UserData userdata; | 389 | UserData userdata; |
367 | lock (m_UserCache) | 390 | if(!GetUser(userID, out userdata)) |
368 | m_UserCache.TryGetValue(userID, out userdata); | 391 | { |
392 | return string.Empty; | ||
393 | } | ||
394 | |||
395 | if (userdata.ServerURLs != null && userdata.ServerURLs.ContainsKey(serverType) && userdata.ServerURLs[serverType] != null) | ||
396 | { | ||
397 | return userdata.ServerURLs[serverType].ToString(); | ||
398 | } | ||
369 | 399 | ||
370 | if (userdata != null) | 400 | if (!string.IsNullOrEmpty(userdata.HomeURL)) |
371 | { | 401 | { |
372 | // m_log.DebugFormat("[USER MANAGEMENT MODULE]: Requested url type {0} for {1}", serverType, userID); | 402 | // m_log.DebugFormat("[USER MANAGEMENT MODULE]: Requested url type {0} for {1}", serverType, userID); |
373 | 403 | ||
374 | if (userdata.ServerURLs != null && userdata.ServerURLs.ContainsKey(serverType) && userdata.ServerURLs[serverType] != null) | 404 | UserAgentServiceConnector uConn = new UserAgentServiceConnector(userdata.HomeURL); |
405 | try | ||
375 | { | 406 | { |
376 | return userdata.ServerURLs[serverType].ToString(); | 407 | userdata.ServerURLs = uConn.GetServerURLs(userID); |
377 | } | 408 | } |
378 | 409 | catch(System.Net.WebException e) | |
379 | if (userdata.HomeURL != null && userdata.HomeURL != string.Empty) | ||
380 | { | 410 | { |
381 | //m_log.DebugFormat( | 411 | m_log.DebugFormat("[USER MANAGEMENT MODULE]: GetServerURLs call failed {0}", e.Message); |
382 | // "[USER MANAGEMENT MODULE]: Did not find url type {0} so requesting urls from '{1}' for {2}", | 412 | userdata.ServerURLs = new Dictionary<string, object>(); |
383 | // serverType, userdata.HomeURL, userID); | ||
384 | |||
385 | UserAgentServiceConnector uConn = new UserAgentServiceConnector(userdata.HomeURL); | ||
386 | userdata.ServerURLs = uConn.GetServerURLs(userID); | ||
387 | if (userdata.ServerURLs != null && userdata.ServerURLs.ContainsKey(serverType) && userdata.ServerURLs[serverType] != null) | ||
388 | return userdata.ServerURLs[serverType].ToString(); | ||
389 | } | 413 | } |
414 | catch (Exception e) | ||
415 | { | ||
416 | m_log.Debug("[USER MANAGEMENT MODULE]: GetServerURLs call failed ", e); | ||
417 | userdata.ServerURLs = new Dictionary<string, object>(); | ||
418 | } | ||
419 | |||
420 | if (userdata.ServerURLs != null && userdata.ServerURLs.ContainsKey(serverType) && userdata.ServerURLs[serverType] != null) | ||
421 | return userdata.ServerURLs[serverType].ToString(); | ||
390 | } | 422 | } |
391 | 423 | ||
392 | return string.Empty; | 424 | return string.Empty; |
@@ -394,13 +426,15 @@ namespace OpenSim.Region.CoreModules.Framework.UserManagement | |||
394 | 426 | ||
395 | public string GetUserUUI(UUID userID) | 427 | public string GetUserUUI(UUID userID) |
396 | { | 428 | { |
397 | UserAccount account = m_Scenes[0].UserAccountService.GetUserAccount(m_Scenes[0].RegionInfo.ScopeID, userID); | 429 | string uui; |
398 | if (account != null) | 430 | GetUserUUI(userID, out uui); |
399 | return userID.ToString(); | 431 | return uui; |
432 | } | ||
400 | 433 | ||
434 | public bool GetUserUUI(UUID userID, out string uui) | ||
435 | { | ||
401 | UserData ud; | 436 | UserData ud; |
402 | lock (m_UserCache) | 437 | bool result = GetUser(userID, out ud); |
403 | m_UserCache.TryGetValue(userID, out ud); | ||
404 | 438 | ||
405 | if (ud != null) | 439 | if (ud != null) |
406 | { | 440 | { |
@@ -414,121 +448,251 @@ namespace OpenSim.Region.CoreModules.Framework.UserManagement | |||
414 | first = parts[0]; | 448 | first = parts[0]; |
415 | last = parts[1]; | 449 | last = parts[1]; |
416 | } | 450 | } |
417 | return userID + ";" + homeURL + ";" + first + " " + last; | 451 | uui = userID + ";" + homeURL + ";" + first + " " + last; |
418 | } | 452 | } |
419 | } | 453 | } |
420 | 454 | ||
421 | return userID.ToString(); | 455 | uui = userID.ToString(); |
456 | return result; | ||
422 | } | 457 | } |
423 | 458 | ||
424 | public void AddUser(UUID uuid, string first, string last) | 459 | #region Cache Management |
460 | public bool GetUser(UUID uuid, out UserData userdata) | ||
425 | { | 461 | { |
426 | lock (m_UserCache) | 462 | lock (m_UserCache) |
427 | { | 463 | { |
428 | if (m_UserCache.ContainsKey(uuid)) | 464 | if (m_UserCache.TryGetValue(uuid, out userdata)) |
429 | return; | 465 | { |
466 | if (userdata.HasGridUserTried) | ||
467 | { | ||
468 | return true; | ||
469 | } | ||
470 | } | ||
471 | else | ||
472 | { | ||
473 | userdata = new UserData(); | ||
474 | userdata.HasGridUserTried = false; | ||
475 | userdata.Id = uuid; | ||
476 | userdata.FirstName = "Unknown"; | ||
477 | userdata.LastName = "UserUMMAU42"; | ||
478 | userdata.HomeURL = string.Empty; | ||
479 | userdata.IsUnknownUser = true; | ||
480 | userdata.HasGridUserTried = false; | ||
481 | } | ||
482 | } | ||
483 | |||
484 | /* BEGIN: do not wrap this code in any lock here | ||
485 | * There are HTTP calls in here. | ||
486 | */ | ||
487 | if (!userdata.HasGridUserTried) | ||
488 | { | ||
489 | /* rewrite here */ | ||
490 | UserAccount account = m_Scenes[0].UserAccountService.GetUserAccount(m_Scenes[0].RegionInfo.ScopeID, uuid); | ||
491 | if (account != null) | ||
492 | { | ||
493 | userdata.FirstName = account.FirstName; | ||
494 | userdata.LastName = account.LastName; | ||
495 | userdata.HomeURL = string.Empty; | ||
496 | userdata.IsUnknownUser = false; | ||
497 | userdata.HasGridUserTried = true; | ||
498 | } | ||
430 | } | 499 | } |
431 | 500 | ||
432 | UserData user = new UserData(); | 501 | if (!userdata.HasGridUserTried) |
433 | user.Id = uuid; | 502 | { |
434 | user.FirstName = first; | 503 | GridUserInfo uInfo = null; |
435 | user.LastName = last; | 504 | if (null != m_Scenes[0].GridUserService) |
505 | { | ||
506 | uInfo = m_Scenes[0].GridUserService.GetGridUserInfo(uuid.ToString()); | ||
507 | } | ||
508 | if (uInfo != null) | ||
509 | { | ||
510 | string url, first, last, tmp; | ||
511 | UUID u; | ||
512 | if(uInfo.UserID.Length <= 36) | ||
513 | { | ||
514 | /* not a UUI */ | ||
515 | } | ||
516 | else if (Util.ParseUniversalUserIdentifier(uInfo.UserID, out u, out url, out first, out last, out tmp)) | ||
517 | { | ||
518 | if (url != string.Empty) | ||
519 | { | ||
520 | userdata.FirstName = first.Replace(" ", ".") + "." + last.Replace(" ", "."); | ||
521 | userdata.HomeURL = url; | ||
522 | try | ||
523 | { | ||
524 | userdata.LastName = "@" + new Uri(url).Authority; | ||
525 | userdata.IsUnknownUser = false; | ||
526 | } | ||
527 | catch | ||
528 | { | ||
529 | userdata.LastName = "@unknown"; | ||
530 | } | ||
531 | userdata.HasGridUserTried = true; | ||
532 | } | ||
533 | } | ||
534 | else | ||
535 | m_log.DebugFormat("[USER MANAGEMENT MODULE]: Unable to parse UUI {0}", uInfo.UserID); | ||
536 | } | ||
537 | } | ||
538 | /* END: do not wrap this code in any lock here */ | ||
436 | 539 | ||
437 | AddUserInternal(user); | 540 | lock (m_UserCache) |
541 | { | ||
542 | m_UserCache[uuid] = userdata; | ||
543 | } | ||
544 | return !userdata.IsUnknownUser; | ||
438 | } | 545 | } |
439 | 546 | ||
440 | public void AddUser(UUID uuid, string first, string last, string homeURL) | 547 | public void AddUser(UUID uuid, string first, string last) |
441 | { | 548 | { |
442 | //m_log.DebugFormat("[USER MANAGEMENT MODULE]: Adding user with id {0}, first {1}, last {2}, url {3}", uuid, first, last, homeURL); | 549 | lock(m_UserCache) |
443 | if (homeURL == string.Empty) | 550 | { |
444 | return; | 551 | if(!m_UserCache.ContainsKey(uuid)) |
445 | 552 | { | |
446 | AddUser(uuid, homeURL + ";" + first + " " + last); | 553 | UserData user = new UserData(); |
554 | user.Id = uuid; | ||
555 | user.FirstName = first; | ||
556 | user.LastName = last; | ||
557 | user.IsUnknownUser = false; | ||
558 | user.HasGridUserTried = false; | ||
559 | m_UserCache.Add(uuid, user); | ||
560 | } | ||
561 | } | ||
447 | } | 562 | } |
448 | 563 | ||
449 | public void AddUser (UUID id, string creatorData) | 564 | public void AddUser(UUID uuid, string first, string last, string homeURL) |
450 | { | 565 | { |
451 | //m_log.DebugFormat("[USER MANAGEMENT MODULE]: Adding user with id {0}, creatorData {1}", id, creatorData); | 566 | //m_log.DebugFormat("[USER MANAGEMENT MODULE]: Adding user with id {0}, first {1}, last {2}, url {3}", uuid, first, last, homeURL); |
452 | 567 | ||
453 | UserData oldUser; | 568 | UserData oldUser; |
454 | //lock the whole block - prevent concurrent update | ||
455 | lock (m_UserCache) | 569 | lock (m_UserCache) |
456 | { | 570 | { |
457 | m_UserCache.TryGetValue (id, out oldUser); | 571 | if (m_UserCache.TryGetValue(uuid, out oldUser)) |
458 | if (oldUser != null) | ||
459 | { | 572 | { |
460 | if (creatorData == null || creatorData == String.Empty) | 573 | if (!oldUser.IsUnknownUser) |
461 | { | 574 | { |
462 | //ignore updates without creator data | 575 | if (homeURL != oldUser.HomeURL && m_DisplayChangingHomeURI) |
576 | { | ||
577 | m_log.DebugFormat("[USER MANAGEMENT MODULE]: Different HomeURI for {0} {1} ({2}): {3} and {4}", | ||
578 | first, last, uuid.ToString(), homeURL, oldUser.HomeURL); | ||
579 | } | ||
580 | /* no update needed */ | ||
463 | return; | 581 | return; |
464 | } | 582 | } |
465 | //try update unknown users | 583 | } |
466 | //and creator's home URL's | 584 | else if(!m_UserCache.ContainsKey(uuid)) |
467 | if ((oldUser.FirstName == "Unknown" && !creatorData.Contains ("Unknown")) || (oldUser.HomeURL != null && !creatorData.StartsWith (oldUser.HomeURL))) | 585 | { |
586 | oldUser = new UserData(); | ||
587 | oldUser.HasGridUserTried = false; | ||
588 | oldUser.IsUnknownUser = false; | ||
589 | if (homeURL != string.Empty) | ||
468 | { | 590 | { |
469 | m_UserCache.Remove (id); | 591 | oldUser.FirstName = first.Replace(" ", ".") + "." + last.Replace(" ", "."); |
470 | // m_log.DebugFormat("[USER MANAGEMENT MODULE]: Re-adding user with id {0}, creatorData [{1}] and old HomeURL {2}", id, creatorData,oldUser.HomeURL); | 592 | try |
593 | { | ||
594 | oldUser.LastName = "@" + new Uri(homeURL).Authority; | ||
595 | oldUser.IsUnknownUser = false; | ||
596 | } | ||
597 | catch | ||
598 | { | ||
599 | oldUser.LastName = "@unknown"; | ||
600 | } | ||
471 | } | 601 | } |
472 | else | 602 | else |
473 | { | 603 | { |
474 | //we have already a valid user within the cache | 604 | oldUser.FirstName = first; |
475 | return; | 605 | oldUser.LastName = last; |
476 | } | 606 | } |
607 | oldUser.HomeURL = homeURL; | ||
608 | oldUser.Id = uuid; | ||
609 | m_UserCache.Add(uuid, oldUser); | ||
477 | } | 610 | } |
611 | } | ||
612 | } | ||
478 | 613 | ||
479 | UserAccount account = m_Scenes[0].UserAccountService.GetUserAccount (m_Scenes [0].RegionInfo.ScopeID, id); | 614 | public void AddUser(UUID id, string creatorData) |
615 | { | ||
616 | // m_log.InfoFormat("[USER MANAGEMENT MODULE]: Adding user with id {0}, creatorData {1}", id, creatorData); | ||
480 | 617 | ||
481 | if (account != null) | 618 | if(string.IsNullOrEmpty(creatorData)) |
619 | { | ||
620 | AddUser(id, string.Empty, string.Empty, string.Empty); | ||
621 | } | ||
622 | else | ||
623 | { | ||
624 | string homeURL; | ||
625 | string firstname = string.Empty; | ||
626 | string lastname = string.Empty; | ||
627 | |||
628 | //creatorData = <endpoint>;<name> | ||
629 | |||
630 | string[] parts = creatorData.Split(';'); | ||
631 | if(parts.Length > 1) | ||
482 | { | 632 | { |
483 | AddUser (id, account.FirstName, account.LastName); | 633 | string[] nameparts = parts[1].Split(' '); |
634 | firstname = nameparts[0]; | ||
635 | for(int xi = 1; xi < nameparts.Length; ++xi) | ||
636 | { | ||
637 | if(xi != 1) | ||
638 | { | ||
639 | lastname += " "; | ||
640 | } | ||
641 | lastname += nameparts[xi]; | ||
642 | } | ||
484 | } | 643 | } |
485 | else | 644 | else |
486 | { | 645 | { |
487 | UserData user = new UserData (); | 646 | firstname = "Unknown"; |
488 | user.Id = id; | 647 | lastname = "UserUMMAU5"; |
489 | 648 | } | |
490 | if (creatorData != null && creatorData != string.Empty) | 649 | if (parts.Length >= 1) |
650 | { | ||
651 | homeURL = parts[0]; | ||
652 | if(Uri.IsWellFormedUriString(homeURL, UriKind.Absolute)) | ||
653 | { | ||
654 | AddUser(id, firstname, lastname, homeURL); | ||
655 | } | ||
656 | else | ||
491 | { | 657 | { |
492 | //creatorData = <endpoint>;<name> | 658 | m_log.DebugFormat("[SCENE]: Unable to parse Uri {0} for CreatorID {1}", parts[0], creatorData); |
493 | 659 | ||
494 | string[] parts = creatorData.Split (';'); | 660 | lock (m_UserCache) |
495 | if (parts.Length >= 1) | ||
496 | { | 661 | { |
497 | user.HomeURL = parts [0]; | 662 | if(!m_UserCache.ContainsKey(id)) |
498 | try | ||
499 | { | ||
500 | Uri uri = new Uri (parts [0]); | ||
501 | user.LastName = "@" + uri.Authority; | ||
502 | } | ||
503 | catch (UriFormatException) | ||
504 | { | 663 | { |
505 | m_log.DebugFormat ("[SCENE]: Unable to parse Uri {0}", parts [0]); | 664 | UserData newUser = new UserData(); |
506 | user.LastName = "@unknown"; | 665 | newUser.Id = id; |
666 | newUser.FirstName = firstname + "." + lastname.Replace(' ', '.'); | ||
667 | newUser.LastName = "@unknown"; | ||
668 | newUser.HomeURL = string.Empty; | ||
669 | newUser.HasGridUserTried = false; | ||
670 | newUser.IsUnknownUser = true; /* we mark those users as Unknown user so a re-retrieve may be activated */ | ||
671 | m_UserCache.Add(id, newUser); | ||
507 | } | 672 | } |
508 | } | 673 | } |
509 | if (parts.Length >= 2) | ||
510 | user.FirstName = parts [1].Replace (' ', '.'); | ||
511 | } | 674 | } |
512 | else | 675 | } |
676 | else | ||
677 | { | ||
678 | lock(m_UserCache) | ||
513 | { | 679 | { |
514 | user.FirstName = "Unknown"; | 680 | if(!m_UserCache.ContainsKey(id)) |
515 | user.LastName = "User"; | 681 | { |
682 | UserData newUser = new UserData(); | ||
683 | newUser.Id = id; | ||
684 | newUser.FirstName = "Unknown"; | ||
685 | newUser.LastName = "UserUMMAU4"; | ||
686 | newUser.HomeURL = string.Empty; | ||
687 | newUser.IsUnknownUser = true; | ||
688 | newUser.HasGridUserTried = false; | ||
689 | m_UserCache.Add(id, newUser); | ||
690 | } | ||
516 | } | 691 | } |
517 | |||
518 | AddUserInternal (user); | ||
519 | } | 692 | } |
520 | } | 693 | } |
521 | } | 694 | } |
522 | 695 | #endregion | |
523 | void AddUserInternal(UserData user) | ||
524 | { | ||
525 | lock (m_UserCache) | ||
526 | m_UserCache[user.Id] = user; | ||
527 | |||
528 | //m_log.DebugFormat( | ||
529 | // "[USER MANAGEMENT MODULE]: Added user {0} {1} {2} {3}", | ||
530 | // user.Id, user.FirstName, user.LastName, user.HomeURL); | ||
531 | } | ||
532 | 696 | ||
533 | public bool IsLocalGridUser(UUID uuid) | 697 | public bool IsLocalGridUser(UUID uuid) |
534 | { | 698 | { |
@@ -541,36 +705,95 @@ namespace OpenSim.Region.CoreModules.Framework.UserManagement | |||
541 | 705 | ||
542 | #endregion IUserManagement | 706 | #endregion IUserManagement |
543 | 707 | ||
708 | protected void Init() | ||
709 | { | ||
710 | AddUser(UUID.Zero, "Unknown", "User"); | ||
711 | RegisterConsoleCmds(); | ||
712 | } | ||
713 | |||
544 | protected void RegisterConsoleCmds() | 714 | protected void RegisterConsoleCmds() |
545 | { | 715 | { |
546 | MainConsole.Instance.Commands.AddCommand("Users", true, | 716 | MainConsole.Instance.Commands.AddCommand("Users", true, |
717 | "show name", | ||
718 | "show name <uuid>", | ||
719 | "Show the bindings between a single user UUID and a user name", | ||
720 | String.Empty, | ||
721 | HandleShowUser); | ||
722 | |||
723 | MainConsole.Instance.Commands.AddCommand("Users", true, | ||
547 | "show names", | 724 | "show names", |
548 | "show names", | 725 | "show names", |
549 | "Show the bindings between user UUIDs and user names", | 726 | "Show the bindings between user UUIDs and user names", |
550 | String.Empty, | 727 | String.Empty, |
551 | HandleShowUsers); | 728 | HandleShowUsers); |
729 | |||
730 | MainConsole.Instance.Commands.AddCommand("Users", true, | ||
731 | "reset user cache", | ||
732 | "reset user cache", | ||
733 | "reset user cache to allow changed settings to be applied", | ||
734 | String.Empty, | ||
735 | HandleResetUserCache); | ||
552 | } | 736 | } |
553 | 737 | ||
554 | private void HandleShowUsers(string module, string[] cmd) | 738 | private void HandleResetUserCache(string module, string[] cmd) |
555 | { | 739 | { |
556 | lock (m_UserCache) | 740 | lock(m_UserCache) |
557 | { | 741 | { |
558 | if (m_UserCache.Count == 0) | 742 | m_UserCache.Clear(); |
559 | { | 743 | } |
560 | MainConsole.Instance.Output("No users found"); | 744 | } |
561 | return; | 745 | |
562 | } | 746 | private void HandleShowUser(string module, string[] cmd) |
563 | 747 | { | |
564 | MainConsole.Instance.Output("UUID User Name"); | 748 | if (cmd.Length < 3) |
565 | MainConsole.Instance.Output("-----------------------------------------------------------------------------"); | 749 | { |
566 | foreach (KeyValuePair<UUID, UserData> kvp in m_UserCache) | 750 | MainConsole.Instance.OutputFormat("Usage: show name <uuid>"); |
567 | { | ||
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; | 751 | return; |
573 | } | 752 | } |
753 | |||
754 | UUID userId; | ||
755 | if (!ConsoleUtil.TryParseConsoleUuid(MainConsole.Instance, cmd[2], out userId)) | ||
756 | return; | ||
757 | |||
758 | UserData ud; | ||
759 | |||
760 | if(!GetUser(userId, out ud)) | ||
761 | { | ||
762 | MainConsole.Instance.OutputFormat("No name known for user with id {0}", userId); | ||
763 | return; | ||
764 | } | ||
765 | |||
766 | ConsoleDisplayTable cdt = new ConsoleDisplayTable(); | ||
767 | cdt.AddColumn("UUID", 36); | ||
768 | cdt.AddColumn("Name", 30); | ||
769 | cdt.AddColumn("HomeURL", 40); | ||
770 | cdt.AddRow(userId, string.Format("{0} {1}", ud.FirstName, ud.LastName), ud.HomeURL); | ||
771 | |||
772 | MainConsole.Instance.Output(cdt.ToString()); | ||
574 | } | 773 | } |
774 | |||
775 | private void HandleShowUsers(string module, string[] cmd) | ||
776 | { | ||
777 | ConsoleDisplayTable cdt = new ConsoleDisplayTable(); | ||
778 | cdt.AddColumn("UUID", 36); | ||
779 | cdt.AddColumn("Name", 30); | ||
780 | cdt.AddColumn("HomeURL", 40); | ||
781 | cdt.AddColumn("Checked", 10); | ||
782 | |||
783 | Dictionary<UUID, UserData> copyDict; | ||
784 | lock(m_UserCache) | ||
785 | { | ||
786 | copyDict = new Dictionary<UUID, UserData>(m_UserCache); | ||
787 | } | ||
788 | |||
789 | foreach(KeyValuePair<UUID, UserData> kvp in copyDict) | ||
790 | { | ||
791 | cdt.AddRow(kvp.Key, string.Format("{0} {1}", kvp.Value.FirstName, kvp.Value.LastName), kvp.Value.HomeURL, kvp.Value.HasGridUserTried ? "yes" : "no"); | ||
792 | } | ||
793 | |||
794 | MainConsole.Instance.Output(cdt.ToString()); | ||
795 | } | ||
796 | |||
575 | } | 797 | } |
576 | } \ No newline at end of file | 798 | |
799 | } | ||