SimianGroupsServicesConnectorModule.cs 59 KB

1234567891011121314151617181920212223242526272829303132333435363738394041424344454647484950515253545556575859606162636465666768697071727374757677787980818283848586878889909192939495969798991001011021031041051061071081091101111121131141151161171181191201211221231241251261271281291301311321331341351361371381391401411421431441451461471481491501511521531541551561571581591601611621631641651661671681691701711721731741751761771781791801811821831841851861871881891901911921931941951961971981992002012022032042052062072082092102112122132142152162172182192202212222232242252262272282292302312322332342352362372382392402412422432442452462472482492502512522532542552562572582592602612622632642652662672682692702712722732742752762772782792802812822832842852862872882892902912922932942952962972982993003013023033043053063073083093103113123133143153163173183193203213223233243253263273283293303313323333343353363373383393403413423433443453463473483493503513523533543553563573583593603613623633643653663673683693703713723733743753763773783793803813823833843853863873883893903913923933943953963973983994004014024034044054064074084094104114124134144154164174184194204214224234244254264274284294304314324334344354364374384394404414424434444454464474484494504514524534544554564574584594604614624634644654664674684694704714724734744754764774784794804814824834844854864874884894904914924934944954964974984995005015025035045055065075085095105115125135145155165175185195205215225235245255265275285295305315325335345355365375385395405415425435445455465475485495505515525535545555565575585595605615625635645655665675685695705715725735745755765775785795805815825835845855865875885895905915925935945955965975985996006016026036046056066076086096106116126136146156166176186196206216226236246256266276286296306316326336346356366376386396406416426436446456466476486496506516526536546556566576586596606616626636646656666676686696706716726736746756766776786796806816826836846856866876886896906916926936946956966976986997007017027037047057067077087097107117127137147157167177187197207217227237247257267277287297307317327337347357367377387397407417427437447457467477487497507517527537547557567577587597607617627637647657667677687697707717727737747757767777787797807817827837847857867877887897907917927937947957967977987998008018028038048058068078088098108118128138148158168178188198208218228238248258268278288298308318328338348358368378388398408418428438448458468478488498508518528538548558568578588598608618628638648658668678688698708718728738748758768778788798808818828838848858868878888898908918928938948958968978988999009019029039049059069079089099109119129139149159169179189199209219229239249259269279289299309319329339349359369379389399409419429439449459469479489499509519529539549559569579589599609619629639649659669679689699709719729739749759769779789799809819829839849859869879889899909919929939949959969979989991000100110021003100410051006100710081009101010111012101310141015101610171018101910201021102210231024102510261027102810291030103110321033103410351036103710381039104010411042104310441045104610471048104910501051105210531054105510561057105810591060106110621063106410651066106710681069107010711072107310741075107610771078107910801081108210831084108510861087108810891090109110921093109410951096109710981099110011011102110311041105110611071108110911101111111211131114111511161117111811191120112111221123112411251126112711281129113011311132113311341135113611371138113911401141114211431144114511461147114811491150115111521153115411551156115711581159116011611162116311641165116611671168116911701171117211731174117511761177117811791180118111821183118411851186118711881189119011911192119311941195119611971198119912001201120212031204120512061207120812091210121112121213121412151216121712181219122012211222122312241225122612271228122912301231123212331234123512361237123812391240124112421243124412451246124712481249125012511252125312541255125612571258125912601261126212631264126512661267126812691270127112721273127412751276127712781279128012811282128312841285128612871288128912901291129212931294129512961297129812991300130113021303130413051306130713081309131013111312131313141315131613171318131913201321132213231324132513261327132813291330133113321333133413351336133713381339134013411342134313441345134613471348134913501351135213531354135513561357135813591360136113621363136413651366136713681369137013711372137313741375137613771378137913801381138213831384138513861387138813891390139113921393139413951396139713981399140014011402140314041405140614071408140914101411141214131414141514161417141814191420142114221423142414251426142714281429143014311432143314341435143614371438143914401441
  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;
  29. using System.Collections.Generic;
  30. using System.Collections.Specialized;
  31. using System.Reflection;
  32. using System.Threading;
  33. using Nwc.XmlRpc;
  34. using log4net;
  35. using Mono.Addins;
  36. using Nini.Config;
  37. using OpenMetaverse;
  38. using OpenMetaverse.StructuredData;
  39. using OpenSim.Framework;
  40. using OpenSim.Framework.Communications;
  41. using OpenSim.Region.Framework.Interfaces;
  42. using OpenSim.Services.Interfaces;
  43. /***************************************************************************
  44. * Simian Data Map
  45. * ===============
  46. *
  47. * OwnerID -> Type -> Key
  48. * -----------------------
  49. *
  50. * UserID -> Group -> ActiveGroup
  51. * + GroupID
  52. *
  53. * UserID -> GroupSessionDropped -> GroupID
  54. * UserID -> GroupSessionInvited -> GroupID
  55. *
  56. * UserID -> GroupMember -> GroupID
  57. * + SelectedRoleID [UUID]
  58. * + AcceptNotices [bool]
  59. * + ListInProfile [bool]
  60. * + Contribution [int]
  61. *
  62. * UserID -> GroupRole[GroupID] -> RoleID
  63. *
  64. *
  65. * GroupID -> Group -> GroupName
  66. * + Charter
  67. * + ShowInList
  68. * + InsigniaID
  69. * + MembershipFee
  70. * + OpenEnrollment
  71. * + AllowPublish
  72. * + MaturePublish
  73. * + FounderID
  74. * + EveryonePowers
  75. * + OwnerRoleID
  76. * + OwnersPowers
  77. *
  78. * GroupID -> GroupRole -> RoleID
  79. * + Name
  80. * + Description
  81. * + Title
  82. * + Powers
  83. *
  84. * GroupID -> GroupMemberInvite -> InviteID
  85. * + AgentID
  86. * + RoleID
  87. *
  88. * GroupID -> GroupNotice -> NoticeID
  89. * + TimeStamp [uint]
  90. * + FromName [string]
  91. * + Subject [string]
  92. * + Message [string]
  93. * + BinaryBucket [byte[]]
  94. *
  95. * */
  96. namespace OpenSim.Region.OptionalModules.Avatar.XmlRpcGroups
  97. {
  98. [Extension(Path = "/OpenSim/RegionModules", NodeName = "RegionModule", Id = "SimianGroupsServicesConnectorModule")]
  99. public class SimianGroupsServicesConnectorModule : ISharedRegionModule, IGroupsServicesConnector
  100. {
  101. private static readonly ILog m_log = LogManager.GetLogger(MethodBase.GetCurrentMethod().DeclaringType);
  102. public const GroupPowers m_DefaultEveryonePowers = GroupPowers.AllowSetHome |
  103. GroupPowers.Accountable |
  104. GroupPowers.JoinChat |
  105. GroupPowers.AllowVoiceChat |
  106. GroupPowers.ReceiveNotices |
  107. GroupPowers.StartProposal |
  108. GroupPowers.VoteOnProposal;
  109. // Would this be cleaner as (GroupPowers)ulong.MaxValue;
  110. public const GroupPowers m_DefaultOwnerPowers = GroupPowers.Accountable
  111. | GroupPowers.AllowEditLand
  112. | GroupPowers.AllowFly
  113. | GroupPowers.AllowLandmark
  114. | GroupPowers.AllowRez
  115. | GroupPowers.AllowSetHome
  116. | GroupPowers.AllowVoiceChat
  117. | GroupPowers.AssignMember
  118. | GroupPowers.AssignMemberLimited
  119. | GroupPowers.ChangeActions
  120. | GroupPowers.ChangeIdentity
  121. | GroupPowers.ChangeMedia
  122. | GroupPowers.ChangeOptions
  123. | GroupPowers.CreateRole
  124. | GroupPowers.DeedObject
  125. | GroupPowers.DeleteRole
  126. | GroupPowers.Eject
  127. | GroupPowers.FindPlaces
  128. | GroupPowers.Invite
  129. | GroupPowers.JoinChat
  130. | GroupPowers.LandChangeIdentity
  131. | GroupPowers.LandDeed
  132. | GroupPowers.LandDivideJoin
  133. | GroupPowers.LandEdit
  134. | GroupPowers.LandEjectAndFreeze
  135. | GroupPowers.LandGardening
  136. | GroupPowers.LandManageAllowed
  137. | GroupPowers.LandManageBanned
  138. | GroupPowers.LandManagePasses
  139. | GroupPowers.LandOptions
  140. | GroupPowers.LandRelease
  141. | GroupPowers.LandSetSale
  142. | GroupPowers.ModerateChat
  143. | GroupPowers.ObjectManipulate
  144. | GroupPowers.ObjectSetForSale
  145. | GroupPowers.ReceiveNotices
  146. | GroupPowers.RemoveMember
  147. | GroupPowers.ReturnGroupOwned
  148. | GroupPowers.ReturnGroupSet
  149. | GroupPowers.ReturnNonGroup
  150. | GroupPowers.RoleProperties
  151. | GroupPowers.SendNotices
  152. | GroupPowers.SetLandingPoint
  153. | GroupPowers.StartProposal
  154. | GroupPowers.VoteOnProposal;
  155. private bool m_connectorEnabled = false;
  156. private string m_groupsServerURI = string.Empty;
  157. private bool m_debugEnabled = false;
  158. private Dictionary<string, bool> m_pendingRequests = new Dictionary<string,bool>();
  159. private ExpiringCache<string, OSDMap> m_memoryCache;
  160. private int m_cacheTimeout = 30;
  161. // private IUserAccountService m_accountService = null;
  162. #region Region Module interfaceBase Members
  163. public string Name
  164. {
  165. get { return "SimianGroupsServicesConnector"; }
  166. }
  167. // this module is not intended to be replaced, but there should only be 1 of them.
  168. public Type ReplaceableInterface
  169. {
  170. get { return null; }
  171. }
  172. public void Initialise(IConfigSource config)
  173. {
  174. IConfig groupsConfig = config.Configs["Groups"];
  175. if (groupsConfig == null)
  176. {
  177. // Do not run this module by default.
  178. return;
  179. }
  180. else
  181. {
  182. // if groups aren't enabled, we're not needed.
  183. // if we're not specified as the connector to use, then we're not wanted
  184. if ((groupsConfig.GetBoolean("Enabled", false) == false)
  185. || (groupsConfig.GetString("ServicesConnectorModule", "XmlRpcGroupsServicesConnector") != Name))
  186. {
  187. m_connectorEnabled = false;
  188. return;
  189. }
  190. m_log.InfoFormat("[SIMIAN-GROUPS-CONNECTOR]: Initializing {0}", this.Name);
  191. m_groupsServerURI = groupsConfig.GetString("GroupsServerURI", string.Empty);
  192. if (string.IsNullOrEmpty(m_groupsServerURI))
  193. {
  194. m_log.ErrorFormat("Please specify a valid Simian Server for GroupsServerURI in OpenSim.ini, [Groups]");
  195. m_connectorEnabled = false;
  196. return;
  197. }
  198. m_cacheTimeout = groupsConfig.GetInt("GroupsCacheTimeout", 30);
  199. if (m_cacheTimeout == 0)
  200. {
  201. m_log.WarnFormat("[SIMIAN-GROUPS-CONNECTOR] Groups Cache Disabled.");
  202. }
  203. else
  204. {
  205. m_log.InfoFormat("[SIMIAN-GROUPS-CONNECTOR] Groups Cache Timeout set to {0}.", m_cacheTimeout);
  206. }
  207. m_memoryCache = new ExpiringCache<string,OSDMap>();
  208. // If we got all the config options we need, lets start'er'up
  209. m_connectorEnabled = true;
  210. m_debugEnabled = groupsConfig.GetBoolean("DebugEnabled", true);
  211. }
  212. }
  213. public void Close()
  214. {
  215. m_log.InfoFormat("[SIMIAN-GROUPS-CONNECTOR]: Closing {0}", this.Name);
  216. }
  217. public void AddRegion(OpenSim.Region.Framework.Scenes.Scene scene)
  218. {
  219. if (m_connectorEnabled)
  220. {
  221. scene.RegisterModuleInterface<IGroupsServicesConnector>(this);
  222. }
  223. }
  224. public void RemoveRegion(OpenSim.Region.Framework.Scenes.Scene scene)
  225. {
  226. if (scene.RequestModuleInterface<IGroupsServicesConnector>() == this)
  227. {
  228. scene.UnregisterModuleInterface<IGroupsServicesConnector>(this);
  229. }
  230. }
  231. public void RegionLoaded(OpenSim.Region.Framework.Scenes.Scene scene)
  232. {
  233. // TODO: May want to consider listenning for Agent Connections so we can pre-cache group info
  234. // scene.EventManager.OnNewClient += OnNewClient;
  235. }
  236. #endregion
  237. #region ISharedRegionModule Members
  238. public void PostInitialise()
  239. {
  240. // NoOp
  241. }
  242. #endregion
  243. #region IGroupsServicesConnector Members
  244. /// <summary>
  245. /// Create a Group, including Everyone and Owners Role, place FounderID in both groups, select Owner as selected role, and newly created group as agent's active role.
  246. /// </summary>
  247. public UUID CreateGroup(UUID requestingAgentID, string name, string charter, bool showInList, UUID insigniaID,
  248. int membershipFee, bool openEnrollment, bool allowPublish,
  249. bool maturePublish, UUID founderID)
  250. {
  251. if (m_debugEnabled) m_log.InfoFormat("[SIMIAN-GROUPS-CONNECTOR] {0} called", System.Reflection.MethodBase.GetCurrentMethod().Name);
  252. UUID GroupID = UUID.Random();
  253. UUID OwnerRoleID = UUID.Random();
  254. OSDMap GroupInfoMap = new OSDMap();
  255. GroupInfoMap["Charter"] = OSD.FromString(charter);
  256. GroupInfoMap["ShowInList"] = OSD.FromBoolean(showInList);
  257. GroupInfoMap["InsigniaID"] = OSD.FromUUID(insigniaID);
  258. GroupInfoMap["MembershipFee"] = OSD.FromInteger(0);
  259. GroupInfoMap["OpenEnrollment"] = OSD.FromBoolean(openEnrollment);
  260. GroupInfoMap["AllowPublish"] = OSD.FromBoolean(allowPublish);
  261. GroupInfoMap["MaturePublish"] = OSD.FromBoolean(maturePublish);
  262. GroupInfoMap["FounderID"] = OSD.FromUUID(founderID);
  263. GroupInfoMap["EveryonePowers"] = OSD.FromULong((ulong)m_DefaultEveryonePowers);
  264. GroupInfoMap["OwnerRoleID"] = OSD.FromUUID(OwnerRoleID);
  265. GroupInfoMap["OwnersPowers"] = OSD.FromULong((ulong)m_DefaultOwnerPowers);
  266. if (SimianAddGeneric(GroupID, "Group", name, GroupInfoMap))
  267. {
  268. AddGroupRole(requestingAgentID, GroupID, UUID.Zero, "Everyone", "Members of " + name, "Member of " + name, (ulong)m_DefaultEveryonePowers);
  269. AddGroupRole(requestingAgentID, GroupID, OwnerRoleID, "Owners", "Owners of " + name, "Owner of " + name, (ulong)m_DefaultOwnerPowers);
  270. AddAgentToGroup(requestingAgentID, requestingAgentID, GroupID, OwnerRoleID);
  271. return GroupID;
  272. }
  273. else
  274. {
  275. return UUID.Zero;
  276. }
  277. }
  278. public void UpdateGroup(UUID requestingAgentID, UUID groupID, string charter, bool showInList,
  279. UUID insigniaID, int membershipFee, bool openEnrollment,
  280. bool allowPublish, bool maturePublish)
  281. {
  282. if (m_debugEnabled) m_log.InfoFormat("[SIMIAN-GROUPS-CONNECTOR] {0} called", System.Reflection.MethodBase.GetCurrentMethod().Name);
  283. // TODO: Check to make sure requestingAgentID has permission to update group
  284. string GroupName;
  285. OSDMap GroupInfoMap;
  286. if (SimianGetFirstGenericEntry(groupID, "GroupInfo", out GroupName, out GroupInfoMap))
  287. {
  288. GroupInfoMap["Charter"] = OSD.FromString(charter);
  289. GroupInfoMap["ShowInList"] = OSD.FromBoolean(showInList);
  290. GroupInfoMap["InsigniaID"] = OSD.FromUUID(insigniaID);
  291. GroupInfoMap["MembershipFee"] = OSD.FromInteger(0);
  292. GroupInfoMap["OpenEnrollment"] = OSD.FromBoolean(openEnrollment);
  293. GroupInfoMap["AllowPublish"] = OSD.FromBoolean(allowPublish);
  294. GroupInfoMap["MaturePublish"] = OSD.FromBoolean(maturePublish);
  295. SimianAddGeneric(groupID, "Group", GroupName, GroupInfoMap);
  296. }
  297. }
  298. public void AddGroupRole(UUID requestingAgentID, UUID groupID, UUID roleID, string name, string description,
  299. string title, ulong powers)
  300. {
  301. if (m_debugEnabled) m_log.InfoFormat("[SIMIAN-GROUPS-CONNECTOR] {0} called", System.Reflection.MethodBase.GetCurrentMethod().Name);
  302. OSDMap GroupRoleInfo = new OSDMap();
  303. GroupRoleInfo["Name"] = OSD.FromString(name);
  304. GroupRoleInfo["Description"] = OSD.FromString(description);
  305. GroupRoleInfo["Title"] = OSD.FromString(title);
  306. GroupRoleInfo["Powers"] = OSD.FromULong((ulong)powers);
  307. // TODO: Add security, make sure that requestingAgentID has permision to add roles
  308. SimianAddGeneric(groupID, "GroupRole", roleID.ToString(), GroupRoleInfo);
  309. }
  310. public void RemoveGroupRole(UUID requestingAgentID, UUID groupID, UUID roleID)
  311. {
  312. if (m_debugEnabled) m_log.InfoFormat("[SIMIAN-GROUPS-CONNECTOR] {0} called", System.Reflection.MethodBase.GetCurrentMethod().Name);
  313. // TODO: Add security
  314. // Can't delete the Everyone Role
  315. if (roleID != UUID.Zero)
  316. {
  317. // Remove all GroupRole Members from Role
  318. Dictionary<UUID, OSDMap> GroupRoleMembers;
  319. string GroupRoleMemberType = "GroupRole" + groupID.ToString();
  320. if (SimianGetGenericEntries(GroupRoleMemberType, roleID.ToString(), out GroupRoleMembers))
  321. {
  322. foreach (UUID UserID in GroupRoleMembers.Keys)
  323. {
  324. EnsureRoleNotSelectedByMember(groupID, roleID, UserID);
  325. SimianRemoveGenericEntry(UserID, GroupRoleMemberType, roleID.ToString());
  326. }
  327. }
  328. // Remove role
  329. SimianRemoveGenericEntry(groupID, "GroupRole", roleID.ToString());
  330. }
  331. }
  332. public void UpdateGroupRole(UUID requestingAgentID, UUID groupID, UUID roleID, string name, string description,
  333. string title, ulong powers)
  334. {
  335. if (m_debugEnabled) m_log.InfoFormat("[SIMIAN-GROUPS-CONNECTOR] {0} called", System.Reflection.MethodBase.GetCurrentMethod().Name);
  336. // TODO: Security, check that requestingAgentID is allowed to update group roles
  337. OSDMap GroupRoleInfo;
  338. if (SimianGetGenericEntry(groupID, "GroupRole", roleID.ToString(), out GroupRoleInfo))
  339. {
  340. if (name != null)
  341. {
  342. GroupRoleInfo["Name"] = OSD.FromString(name);
  343. }
  344. if (description != null)
  345. {
  346. GroupRoleInfo["Description"] = OSD.FromString(description);
  347. }
  348. if (title != null)
  349. {
  350. GroupRoleInfo["Title"] = OSD.FromString(title);
  351. }
  352. GroupRoleInfo["Powers"] = OSD.FromULong((ulong)powers);
  353. }
  354. SimianAddGeneric(groupID, "GroupRole", roleID.ToString(), GroupRoleInfo);
  355. }
  356. public GroupRecord GetGroupRecord(UUID requestingAgentID, UUID groupID, string groupName)
  357. {
  358. if (m_debugEnabled) m_log.InfoFormat("[SIMIAN-GROUPS-CONNECTOR] {0} called", System.Reflection.MethodBase.GetCurrentMethod().Name);
  359. OSDMap GroupInfoMap = null;
  360. if (groupID != UUID.Zero)
  361. {
  362. if (!SimianGetFirstGenericEntry(groupID, "Group", out groupName, out GroupInfoMap))
  363. {
  364. return null;
  365. }
  366. }
  367. else if (!string.IsNullOrEmpty(groupName))
  368. {
  369. if (!SimianGetFirstGenericEntry("Group", groupName, out groupID, out GroupInfoMap))
  370. {
  371. return null;
  372. }
  373. }
  374. GroupRecord GroupInfo = new GroupRecord();
  375. GroupInfo.GroupID = groupID;
  376. GroupInfo.GroupName = groupName;
  377. GroupInfo.Charter = GroupInfoMap["Charter"].AsString();
  378. GroupInfo.ShowInList = GroupInfoMap["ShowInList"].AsBoolean();
  379. GroupInfo.GroupPicture = GroupInfoMap["InsigniaID"].AsUUID();
  380. GroupInfo.MembershipFee = GroupInfoMap["MembershipFee"].AsInteger();
  381. GroupInfo.OpenEnrollment = GroupInfoMap["OpenEnrollment"].AsBoolean();
  382. GroupInfo.AllowPublish = GroupInfoMap["AllowPublish"].AsBoolean();
  383. GroupInfo.MaturePublish = GroupInfoMap["MaturePublish"].AsBoolean();
  384. GroupInfo.FounderID = GroupInfoMap["FounderID"].AsUUID();
  385. GroupInfo.OwnerRoleID = GroupInfoMap["OwnerRoleID"].AsUUID();
  386. return GroupInfo;
  387. }
  388. public GroupProfileData GetMemberGroupProfile(UUID requestingAgentID, UUID groupID, UUID memberID)
  389. {
  390. if (m_debugEnabled) m_log.InfoFormat("[SIMIAN-GROUPS-CONNECTOR] {0} called", System.Reflection.MethodBase.GetCurrentMethod().Name);
  391. OSDMap groupProfile;
  392. string groupName;
  393. if (!SimianGetFirstGenericEntry(groupID, "Group", out groupName, out groupProfile))
  394. {
  395. // GroupProfileData is not nullable
  396. return new GroupProfileData();
  397. }
  398. GroupProfileData MemberGroupProfile = new GroupProfileData();
  399. MemberGroupProfile.GroupID = groupID;
  400. MemberGroupProfile.Name = groupName;
  401. if (groupProfile["Charter"] != null)
  402. {
  403. MemberGroupProfile.Charter = groupProfile["Charter"].AsString();
  404. }
  405. MemberGroupProfile.ShowInList = groupProfile["ShowInList"].AsString() == "1";
  406. MemberGroupProfile.InsigniaID = groupProfile["InsigniaID"].AsUUID();
  407. MemberGroupProfile.MembershipFee = groupProfile["MembershipFee"].AsInteger();
  408. MemberGroupProfile.OpenEnrollment = groupProfile["OpenEnrollment"].AsBoolean();
  409. MemberGroupProfile.AllowPublish = groupProfile["AllowPublish"].AsBoolean();
  410. MemberGroupProfile.MaturePublish = groupProfile["MaturePublish"].AsBoolean();
  411. MemberGroupProfile.FounderID = groupProfile["FounderID"].AsUUID();;
  412. MemberGroupProfile.OwnerRole = groupProfile["OwnerRoleID"].AsUUID();
  413. Dictionary<UUID, OSDMap> Members;
  414. if (SimianGetGenericEntries("GroupMember",groupID.ToString(), out Members))
  415. {
  416. MemberGroupProfile.GroupMembershipCount = Members.Count;
  417. }
  418. Dictionary<string, OSDMap> Roles;
  419. if (SimianGetGenericEntries(groupID, "GroupRole", out Roles))
  420. {
  421. MemberGroupProfile.GroupRolesCount = Roles.Count;
  422. }
  423. // TODO: Get Group Money balance from somewhere
  424. // group.Money = 0;
  425. GroupMembershipData MemberInfo = GetAgentGroupMembership(requestingAgentID, memberID, groupID);
  426. MemberGroupProfile.MemberTitle = MemberInfo.GroupTitle;
  427. MemberGroupProfile.PowersMask = MemberInfo.GroupPowers;
  428. return MemberGroupProfile;
  429. }
  430. public void SetAgentActiveGroup(UUID requestingAgentID, UUID agentID, UUID groupID)
  431. {
  432. if (m_debugEnabled) m_log.InfoFormat("[SIMIAN-GROUPS-CONNECTOR] {0} called", System.Reflection.MethodBase.GetCurrentMethod().Name);
  433. OSDMap ActiveGroup = new OSDMap();
  434. ActiveGroup.Add("GroupID", OSD.FromUUID(groupID));
  435. SimianAddGeneric(agentID, "Group", "ActiveGroup", ActiveGroup);
  436. }
  437. public void SetAgentActiveGroupRole(UUID requestingAgentID, UUID agentID, UUID groupID, UUID roleID)
  438. {
  439. if (m_debugEnabled) m_log.InfoFormat("[SIMIAN-GROUPS-CONNECTOR] {0} called", System.Reflection.MethodBase.GetCurrentMethod().Name);
  440. OSDMap GroupMemberInfo;
  441. if (!SimianGetGenericEntry(agentID, "GroupMember", groupID.ToString(), out GroupMemberInfo))
  442. {
  443. GroupMemberInfo = new OSDMap();
  444. }
  445. GroupMemberInfo["SelectedRoleID"] = OSD.FromUUID(roleID);
  446. SimianAddGeneric(agentID, "GroupMember", groupID.ToString(), GroupMemberInfo);
  447. }
  448. public void SetAgentGroupInfo(UUID requestingAgentID, UUID agentID, UUID groupID, bool acceptNotices, bool listInProfile)
  449. {
  450. if (m_debugEnabled) m_log.InfoFormat("[SIMIAN-GROUPS-CONNECTOR] {0} called", System.Reflection.MethodBase.GetCurrentMethod().Name);
  451. OSDMap GroupMemberInfo;
  452. if (!SimianGetGenericEntry(agentID, "GroupMember", groupID.ToString(), out GroupMemberInfo))
  453. {
  454. GroupMemberInfo = new OSDMap();
  455. }
  456. GroupMemberInfo["AcceptNotices"] = OSD.FromBoolean(acceptNotices);
  457. GroupMemberInfo["ListInProfile"] = OSD.FromBoolean(listInProfile);
  458. GroupMemberInfo["Contribution"] = OSD.FromInteger(0);
  459. GroupMemberInfo["SelectedRole"] = OSD.FromUUID(UUID.Zero);
  460. SimianAddGeneric(agentID, "GroupMember", groupID.ToString(), GroupMemberInfo);
  461. }
  462. public void AddAgentToGroupInvite(UUID requestingAgentID, UUID inviteID, UUID groupID, UUID roleID, UUID agentID)
  463. {
  464. if (m_debugEnabled) m_log.InfoFormat("[SIMIAN-GROUPS-CONNECTOR] {0} called", System.Reflection.MethodBase.GetCurrentMethod().Name);
  465. OSDMap Invite = new OSDMap();
  466. Invite["AgentID"] = OSD.FromUUID(agentID);
  467. Invite["RoleID"] = OSD.FromUUID(roleID);
  468. SimianAddGeneric(groupID, "GroupMemberInvite", inviteID.ToString(), Invite);
  469. }
  470. public GroupInviteInfo GetAgentToGroupInvite(UUID requestingAgentID, UUID inviteID)
  471. {
  472. if (m_debugEnabled) m_log.InfoFormat("[SIMIAN-GROUPS-CONNECTOR] {0} called", System.Reflection.MethodBase.GetCurrentMethod().Name);
  473. OSDMap GroupMemberInvite;
  474. UUID GroupID;
  475. if (!SimianGetFirstGenericEntry("GroupMemberInvite", inviteID.ToString(), out GroupID, out GroupMemberInvite))
  476. {
  477. return null;
  478. }
  479. GroupInviteInfo inviteInfo = new GroupInviteInfo();
  480. inviteInfo.InviteID = inviteID;
  481. inviteInfo.GroupID = GroupID;
  482. inviteInfo.AgentID = GroupMemberInvite["AgentID"].AsUUID();
  483. inviteInfo.RoleID = GroupMemberInvite["RoleID"].AsUUID();
  484. return inviteInfo;
  485. }
  486. public void RemoveAgentToGroupInvite(UUID requestingAgentID, UUID inviteID)
  487. {
  488. if (m_debugEnabled) m_log.InfoFormat("[SIMIAN-GROUPS-CONNECTOR] {0} called", System.Reflection.MethodBase.GetCurrentMethod().Name);
  489. GroupInviteInfo invite = GetAgentToGroupInvite(requestingAgentID, inviteID);
  490. SimianRemoveGenericEntry(invite.GroupID, "GroupMemberInvite", inviteID.ToString());
  491. }
  492. public void AddAgentToGroup(UUID requestingAgentID, UUID AgentID, UUID GroupID, UUID RoleID)
  493. {
  494. if (m_debugEnabled) m_log.InfoFormat("[SIMIAN-GROUPS-CONNECTOR] {0} called", System.Reflection.MethodBase.GetCurrentMethod().Name);
  495. // Setup Agent/Group information
  496. SetAgentGroupInfo(requestingAgentID, AgentID, GroupID, true, true);
  497. // Add agent to Everyone Group
  498. AddAgentToGroupRole(requestingAgentID, AgentID, GroupID, UUID.Zero);
  499. // Add agent to Specified Role
  500. AddAgentToGroupRole(requestingAgentID, AgentID, GroupID, RoleID);
  501. // Set selected role in this group to specified role
  502. SetAgentActiveGroupRole(requestingAgentID, AgentID, GroupID, RoleID);
  503. }
  504. public void RemoveAgentFromGroup(UUID requestingAgentID, UUID agentID, UUID groupID)
  505. {
  506. if (m_debugEnabled) m_log.InfoFormat("[SIMIAN-GROUPS-CONNECTOR] {0} called", System.Reflection.MethodBase.GetCurrentMethod().Name);
  507. // If current active group is the group the agent is being removed from, change their group to UUID.Zero
  508. GroupMembershipData memberActiveMembership = GetAgentActiveMembership(requestingAgentID, agentID);
  509. if (memberActiveMembership.GroupID == groupID)
  510. {
  511. SetAgentActiveGroup(agentID, agentID, UUID.Zero);
  512. }
  513. // Remove Group Member information for this group
  514. SimianRemoveGenericEntry(agentID, "GroupMember", groupID.ToString());
  515. // By using a Simian Generics Type consisting of a prefix and a groupID,
  516. // combined with RoleID as key allows us to get a list of roles a particular member
  517. // of a group is assigned to.
  518. string GroupRoleMemberType = "GroupRole" + groupID.ToString();
  519. // Take Agent out of all other group roles
  520. Dictionary<string, OSDMap> GroupRoles;
  521. if (SimianGetGenericEntries(agentID, GroupRoleMemberType, out GroupRoles))
  522. {
  523. foreach (string roleID in GroupRoles.Keys)
  524. {
  525. SimianRemoveGenericEntry(agentID, GroupRoleMemberType, roleID);
  526. }
  527. }
  528. }
  529. public void AddAgentToGroupRole(UUID requestingAgentID, UUID agentID, UUID groupID, UUID roleID)
  530. {
  531. if (m_debugEnabled) m_log.InfoFormat("[SIMIAN-GROUPS-CONNECTOR] {0} called", System.Reflection.MethodBase.GetCurrentMethod().Name);
  532. SimianAddGeneric(agentID, "GroupRole" + groupID.ToString(), roleID.ToString(), new OSDMap());
  533. }
  534. public void RemoveAgentFromGroupRole(UUID requestingAgentID, UUID agentID, UUID groupID, UUID roleID)
  535. {
  536. if (m_debugEnabled) m_log.InfoFormat("[SIMIAN-GROUPS-CONNECTOR] {0} called", System.Reflection.MethodBase.GetCurrentMethod().Name);
  537. // Cannot remove members from the Everyone Role
  538. if (roleID != UUID.Zero)
  539. {
  540. EnsureRoleNotSelectedByMember(groupID, roleID, agentID);
  541. string GroupRoleMemberType = "GroupRole" + groupID.ToString();
  542. SimianRemoveGenericEntry(agentID, GroupRoleMemberType, roleID.ToString());
  543. }
  544. }
  545. public List<DirGroupsReplyData> FindGroups(UUID requestingAgentID, string search)
  546. {
  547. if (m_debugEnabled) m_log.InfoFormat("[SIMIAN-GROUPS-CONNECTOR] {0} called", System.Reflection.MethodBase.GetCurrentMethod().Name);
  548. List<DirGroupsReplyData> findings = new List<DirGroupsReplyData>();
  549. NameValueCollection requestArgs = new NameValueCollection
  550. {
  551. { "RequestMethod", "GetGenerics" },
  552. { "Type", "Group" },
  553. { "Key", search },
  554. { "Fuzzy", "1" }
  555. };
  556. OSDMap response = CachedPostRequest(requestArgs);
  557. if (response["Success"].AsBoolean() && response["Entries"] is OSDArray)
  558. {
  559. OSDArray entryArray = (OSDArray)response["Entries"];
  560. foreach (OSDMap entryMap in entryArray)
  561. {
  562. DirGroupsReplyData data = new DirGroupsReplyData();
  563. data.groupID = entryMap["OwnerID"].AsUUID();
  564. data.groupName = entryMap["Key"].AsString();
  565. // TODO: is there a better way to do this?
  566. Dictionary<UUID, OSDMap> Members;
  567. if (SimianGetGenericEntries("GroupMember", data.groupID.ToString(), out Members))
  568. {
  569. data.members = Members.Count;
  570. }
  571. else
  572. {
  573. data.members = 0;
  574. }
  575. // TODO: sort results?
  576. // data.searchOrder = order;
  577. findings.Add(data);
  578. }
  579. }
  580. return findings;
  581. }
  582. public GroupMembershipData GetAgentGroupMembership(UUID requestingAgentID, UUID agentID, UUID groupID)
  583. {
  584. if (m_debugEnabled) m_log.InfoFormat("[SIMIAN-GROUPS-CONNECTOR] {0} called", System.Reflection.MethodBase.GetCurrentMethod().Name);
  585. GroupMembershipData data = null;
  586. // bool foundData = false;
  587. OSDMap UserGroupMemberInfo;
  588. if (SimianGetGenericEntry(agentID, "GroupMember", groupID.ToString(), out UserGroupMemberInfo))
  589. {
  590. data = new GroupMembershipData();
  591. data.AcceptNotices = UserGroupMemberInfo["AcceptNotices"].AsBoolean();
  592. data.Contribution = UserGroupMemberInfo["Contribution"].AsInteger();
  593. data.ListInProfile = UserGroupMemberInfo["ListInProfile"].AsBoolean();
  594. data.ActiveRole = UserGroupMemberInfo["SelectedRoleID"].AsUUID();
  595. ///////////////////////////////
  596. // Agent Specific Information:
  597. //
  598. OSDMap UserActiveGroup;
  599. if (SimianGetGenericEntry(agentID, "Group", "ActiveGroup", out UserActiveGroup))
  600. {
  601. data.Active = UserActiveGroup["GroupID"].AsUUID().Equals(groupID);
  602. }
  603. ///////////////////////////////
  604. // Role Specific Information:
  605. //
  606. OSDMap GroupRoleInfo;
  607. if (SimianGetGenericEntry(groupID, "GroupRole", data.ActiveRole.ToString(), out GroupRoleInfo))
  608. {
  609. data.GroupTitle = GroupRoleInfo["Title"].AsString();
  610. data.GroupPowers = GroupRoleInfo["Powers"].AsULong();
  611. }
  612. ///////////////////////////////
  613. // Group Specific Information:
  614. //
  615. OSDMap GroupInfo;
  616. string GroupName;
  617. if (SimianGetFirstGenericEntry(groupID, "Group", out GroupName, out GroupInfo))
  618. {
  619. data.GroupID = groupID;
  620. data.AllowPublish = GroupInfo["AllowPublish"].AsBoolean();
  621. data.Charter = GroupInfo["Charter"].AsString();
  622. data.FounderID = GroupInfo["FounderID"].AsUUID();
  623. data.GroupName = GroupName;
  624. data.GroupPicture = GroupInfo["InsigniaID"].AsUUID();
  625. data.MaturePublish = GroupInfo["MaturePublish"].AsBoolean();
  626. data.MembershipFee = GroupInfo["MembershipFee"].AsInteger();
  627. data.OpenEnrollment = GroupInfo["OpenEnrollment"].AsBoolean();
  628. data.ShowInList = GroupInfo["ShowInList"].AsBoolean();
  629. }
  630. }
  631. return data;
  632. }
  633. public GroupMembershipData GetAgentActiveMembership(UUID requestingAgentID, UUID agentID)
  634. {
  635. if (m_debugEnabled) m_log.InfoFormat("[SIMIAN-GROUPS-CONNECTOR] {0} called", System.Reflection.MethodBase.GetCurrentMethod().Name);
  636. UUID GroupID = UUID.Zero;
  637. OSDMap UserActiveGroup;
  638. if (SimianGetGenericEntry(agentID, "Group", "ActiveGroup", out UserActiveGroup))
  639. {
  640. GroupID = UserActiveGroup["GroupID"].AsUUID();
  641. }
  642. if (m_debugEnabled) m_log.InfoFormat("[SIMIAN-GROUPS-CONNECTOR] Active GroupID : {0}", GroupID.ToString());
  643. return GetAgentGroupMembership(requestingAgentID, agentID, GroupID);
  644. }
  645. public List<GroupMembershipData> GetAgentGroupMemberships(UUID requestingAgentID, UUID agentID)
  646. {
  647. if (m_debugEnabled) m_log.InfoFormat("[SIMIAN-GROUPS-CONNECTOR] {0} called", System.Reflection.MethodBase.GetCurrentMethod().Name);
  648. List<GroupMembershipData> memberships = new List<GroupMembershipData>();
  649. Dictionary<string,OSDMap> GroupMemberShips;
  650. if (SimianGetGenericEntries(agentID, "GroupMember", out GroupMemberShips))
  651. {
  652. foreach (string key in GroupMemberShips.Keys)
  653. {
  654. memberships.Add(GetAgentGroupMembership(requestingAgentID, agentID, UUID.Parse(key)));
  655. }
  656. }
  657. return memberships;
  658. }
  659. public List<GroupRolesData> GetAgentGroupRoles(UUID requestingAgentID, UUID agentID, UUID groupID)
  660. {
  661. if (m_debugEnabled) m_log.InfoFormat("[SIMIAN-GROUPS-CONNECTOR] {0} called", System.Reflection.MethodBase.GetCurrentMethod().Name);
  662. List<GroupRolesData> Roles = new List<GroupRolesData>();
  663. Dictionary<string, OSDMap> GroupRoles;
  664. if (SimianGetGenericEntries(groupID, "GroupRole", out GroupRoles))
  665. {
  666. Dictionary<string, OSDMap> MemberRoles;
  667. if (SimianGetGenericEntries(agentID, "GroupRole" + groupID.ToString(), out MemberRoles))
  668. {
  669. foreach (KeyValuePair<string, OSDMap> kvp in MemberRoles)
  670. {
  671. GroupRolesData data = new GroupRolesData();
  672. data.RoleID = UUID.Parse(kvp.Key);
  673. data.Name = GroupRoles[kvp.Key]["Name"].AsString();
  674. data.Description = GroupRoles[kvp.Key]["Description"].AsString();
  675. data.Title = GroupRoles[kvp.Key]["Title"].AsString();
  676. data.Powers = GroupRoles[kvp.Key]["Powers"].AsULong();
  677. Roles.Add(data);
  678. }
  679. }
  680. }
  681. return Roles;
  682. }
  683. public List<GroupRolesData> GetGroupRoles(UUID requestingAgentID, UUID groupID)
  684. {
  685. if (m_debugEnabled) m_log.InfoFormat("[SIMIAN-GROUPS-CONNECTOR] {0} called", System.Reflection.MethodBase.GetCurrentMethod().Name);
  686. List<GroupRolesData> Roles = new List<GroupRolesData>();
  687. Dictionary<string, OSDMap> GroupRoles;
  688. if (SimianGetGenericEntries(groupID, "GroupRole", out GroupRoles))
  689. {
  690. foreach (KeyValuePair<string, OSDMap> role in GroupRoles)
  691. {
  692. GroupRolesData data = new GroupRolesData();
  693. data.RoleID = UUID.Parse(role.Key);
  694. data.Name = role.Value["Name"].AsString();
  695. data.Description = role.Value["Description"].AsString();
  696. data.Title = role.Value["Title"].AsString();
  697. data.Powers = role.Value["Powers"].AsULong();
  698. Dictionary<UUID, OSDMap> GroupRoleMembers;
  699. if (SimianGetGenericEntries("GroupRole" + groupID.ToString(), role.Key, out GroupRoleMembers))
  700. {
  701. data.Members = GroupRoleMembers.Count;
  702. }
  703. else
  704. {
  705. data.Members = 0;
  706. }
  707. Roles.Add(data);
  708. }
  709. }
  710. return Roles;
  711. }
  712. public List<GroupMembersData> GetGroupMembers(UUID requestingAgentID, UUID GroupID)
  713. {
  714. if (m_debugEnabled) m_log.InfoFormat("[SIMIAN-GROUPS-CONNECTOR] {0} called", System.Reflection.MethodBase.GetCurrentMethod().Name);
  715. List<GroupMembersData> members = new List<GroupMembersData>();
  716. OSDMap GroupInfo;
  717. string GroupName;
  718. UUID GroupOwnerRoleID = UUID.Zero;
  719. if (!SimianGetFirstGenericEntry(GroupID, "Group", out GroupName, out GroupInfo))
  720. {
  721. return members;
  722. }
  723. GroupOwnerRoleID = GroupInfo["OwnerRoleID"].AsUUID();
  724. // Locally cache group roles, since we'll be needing this data for each member
  725. Dictionary<string,OSDMap> GroupRoles;
  726. SimianGetGenericEntries(GroupID, "GroupRole", out GroupRoles);
  727. // Locally cache list of group owners
  728. Dictionary<UUID, OSDMap> GroupOwners;
  729. SimianGetGenericEntries("GroupRole" + GroupID.ToString(), GroupOwnerRoleID.ToString(), out GroupOwners);
  730. Dictionary<UUID, OSDMap> GroupMembers;
  731. if (SimianGetGenericEntries("GroupMember", GroupID.ToString(), out GroupMembers))
  732. {
  733. foreach (KeyValuePair<UUID, OSDMap> member in GroupMembers)
  734. {
  735. GroupMembersData data = new GroupMembersData();
  736. data.AgentID = member.Key;
  737. UUID SelectedRoleID = member.Value["SelectedRoleID"].AsUUID();
  738. data.AcceptNotices = member.Value["AcceptNotices"].AsBoolean();
  739. data.ListInProfile = member.Value["ListInProfile"].AsBoolean();
  740. data.Contribution = member.Value["Contribution"].AsInteger();
  741. data.IsOwner = GroupOwners.ContainsKey(member.Key);
  742. OSDMap GroupRoleInfo = GroupRoles[SelectedRoleID.ToString()];
  743. data.Title = GroupRoleInfo["Title"].AsString();
  744. data.AgentPowers = GroupRoleInfo["Powers"].AsULong();
  745. members.Add(data);
  746. }
  747. }
  748. return members;
  749. }
  750. public List<GroupRoleMembersData> GetGroupRoleMembers(UUID requestingAgentID, UUID groupID)
  751. {
  752. if (m_debugEnabled) m_log.InfoFormat("[SIMIAN-GROUPS-CONNECTOR] {0} called", System.Reflection.MethodBase.GetCurrentMethod().Name);
  753. List<GroupRoleMembersData> members = new List<GroupRoleMembersData>();
  754. Dictionary<string, OSDMap> GroupRoles;
  755. if (SimianGetGenericEntries(groupID, "GroupRole", out GroupRoles))
  756. {
  757. foreach (KeyValuePair<string, OSDMap> Role in GroupRoles)
  758. {
  759. Dictionary<UUID, OSDMap> GroupRoleMembers;
  760. if (SimianGetGenericEntries("GroupRole"+groupID.ToString(), Role.Key, out GroupRoleMembers))
  761. {
  762. foreach (KeyValuePair<UUID, OSDMap> GroupRoleMember in GroupRoleMembers)
  763. {
  764. GroupRoleMembersData data = new GroupRoleMembersData();
  765. data.MemberID = GroupRoleMember.Key;
  766. data.RoleID = UUID.Parse(Role.Key);
  767. members.Add(data);
  768. }
  769. }
  770. }
  771. }
  772. return members;
  773. }
  774. public List<GroupNoticeData> GetGroupNotices(UUID requestingAgentID, UUID GroupID)
  775. {
  776. if (m_debugEnabled) m_log.InfoFormat("[SIMIAN-GROUPS-CONNECTOR] {0} called", System.Reflection.MethodBase.GetCurrentMethod().Name);
  777. List<GroupNoticeData> values = new List<GroupNoticeData>();
  778. Dictionary<string, OSDMap> Notices;
  779. if (SimianGetGenericEntries(GroupID, "GroupNotice", out Notices))
  780. {
  781. foreach (KeyValuePair<string, OSDMap> Notice in Notices)
  782. {
  783. GroupNoticeData data = new GroupNoticeData();
  784. data.NoticeID = UUID.Parse(Notice.Key);
  785. data.Timestamp = Notice.Value["TimeStamp"].AsUInteger();
  786. data.FromName = Notice.Value["FromName"].AsString();
  787. data.Subject = Notice.Value["Subject"].AsString();
  788. data.HasAttachment = Notice.Value["BinaryBucket"].AsBinary().Length > 0;
  789. //TODO: Figure out how to get this
  790. data.AssetType = 0;
  791. values.Add(data);
  792. }
  793. }
  794. return values;
  795. }
  796. public GroupNoticeInfo GetGroupNotice(UUID requestingAgentID, UUID noticeID)
  797. {
  798. if (m_debugEnabled) m_log.InfoFormat("[SIMIAN-GROUPS-CONNECTOR] {0} called", System.Reflection.MethodBase.GetCurrentMethod().Name);
  799. OSDMap GroupNotice;
  800. UUID GroupID;
  801. if (SimianGetFirstGenericEntry("GroupNotice", noticeID.ToString(), out GroupID, out GroupNotice))
  802. {
  803. GroupNoticeInfo data = new GroupNoticeInfo();
  804. data.GroupID = GroupID;
  805. data.Message = GroupNotice["Message"].AsString();
  806. data.BinaryBucket = GroupNotice["BinaryBucket"].AsBinary();
  807. data.noticeData.NoticeID = noticeID;
  808. data.noticeData.Timestamp = GroupNotice["TimeStamp"].AsUInteger();
  809. data.noticeData.FromName = GroupNotice["FromName"].AsString();
  810. data.noticeData.Subject = GroupNotice["Subject"].AsString();
  811. data.noticeData.HasAttachment = data.BinaryBucket.Length > 0;
  812. data.noticeData.AssetType = 0;
  813. if (data.Message == null)
  814. {
  815. data.Message = string.Empty;
  816. }
  817. return data;
  818. }
  819. return null;
  820. }
  821. public void AddGroupNotice(UUID requestingAgentID, UUID groupID, UUID noticeID, string fromName, string subject, string message, byte[] binaryBucket)
  822. {
  823. if (m_debugEnabled) m_log.InfoFormat("[SIMIAN-GROUPS-CONNECTOR] {0} called", System.Reflection.MethodBase.GetCurrentMethod().Name);
  824. OSDMap Notice = new OSDMap();
  825. Notice["TimeStamp"] = OSD.FromUInteger((uint)Util.UnixTimeSinceEpoch());
  826. Notice["FromName"] = OSD.FromString(fromName);
  827. Notice["Subject"] = OSD.FromString(subject);
  828. Notice["Message"] = OSD.FromString(message);
  829. Notice["BinaryBucket"] = OSD.FromBinary(binaryBucket);
  830. SimianAddGeneric(groupID, "GroupNotice", noticeID.ToString(), Notice);
  831. }
  832. #endregion
  833. #region GroupSessionTracking
  834. public void ResetAgentGroupChatSessions(UUID agentID)
  835. {
  836. Dictionary<string, OSDMap> agentSessions;
  837. if (SimianGetGenericEntries(agentID, "GroupSessionDropped", out agentSessions))
  838. {
  839. foreach (string GroupID in agentSessions.Keys)
  840. {
  841. SimianRemoveGenericEntry(agentID, "GroupSessionDropped", GroupID);
  842. }
  843. }
  844. if (SimianGetGenericEntries(agentID, "GroupSessionInvited", out agentSessions))
  845. {
  846. foreach (string GroupID in agentSessions.Keys)
  847. {
  848. SimianRemoveGenericEntry(agentID, "GroupSessionInvited", GroupID);
  849. }
  850. }
  851. }
  852. public bool hasAgentDroppedGroupChatSession(UUID agentID, UUID groupID)
  853. {
  854. OSDMap session;
  855. return SimianGetGenericEntry(agentID, "GroupSessionDropped", groupID.ToString(), out session);
  856. }
  857. public void AgentDroppedFromGroupChatSession(UUID agentID, UUID groupID)
  858. {
  859. SimianAddGeneric(agentID, "GroupSessionDropped", groupID.ToString(), new OSDMap());
  860. }
  861. public void AgentInvitedToGroupChatSession(UUID agentID, UUID groupID)
  862. {
  863. SimianAddGeneric(agentID, "GroupSessionInvited", groupID.ToString(), new OSDMap());
  864. }
  865. public bool hasAgentBeenInvitedToGroupChatSession(UUID agentID, UUID groupID)
  866. {
  867. OSDMap session;
  868. return SimianGetGenericEntry(agentID, "GroupSessionDropped", groupID.ToString(), out session);
  869. }
  870. #endregion
  871. private void EnsureRoleNotSelectedByMember(UUID groupID, UUID roleID, UUID userID)
  872. {
  873. if (m_debugEnabled) m_log.InfoFormat("[SIMIAN-GROUPS-CONNECTOR] {0} called", System.Reflection.MethodBase.GetCurrentMethod().Name);
  874. // If member's SelectedRole is roleID, change their selected role to Everyone
  875. // before removing them from the role
  876. OSDMap UserGroupInfo;
  877. if (SimianGetGenericEntry(userID, "GroupMember", groupID.ToString(), out UserGroupInfo))
  878. {
  879. if (UserGroupInfo["SelectedRoleID"].AsUUID() == roleID)
  880. {
  881. UserGroupInfo["SelectedRoleID"] = OSD.FromUUID(UUID.Zero);
  882. }
  883. SimianAddGeneric(userID, "GroupMember", groupID.ToString(), UserGroupInfo);
  884. }
  885. }
  886. #region Simian Util Methods
  887. private bool SimianAddGeneric(UUID ownerID, string type, string key, OSDMap map)
  888. {
  889. if (m_debugEnabled) m_log.InfoFormat("[SIMIAN-GROUPS-CONNECTOR] {0} called ({1},{2},{3})", System.Reflection.MethodBase.GetCurrentMethod().Name, ownerID, type, key);
  890. string value = OSDParser.SerializeJsonString(map);
  891. if (m_debugEnabled) m_log.InfoFormat("[SIMIAN-GROUPS-CONNECTOR] value: {0}", value);
  892. NameValueCollection RequestArgs = new NameValueCollection
  893. {
  894. { "RequestMethod", "AddGeneric" },
  895. { "OwnerID", ownerID.ToString() },
  896. { "Type", type },
  897. { "Key", key },
  898. { "Value", value}
  899. };
  900. OSDMap Response = CachedPostRequest(RequestArgs);
  901. if (Response["Success"].AsBoolean())
  902. {
  903. return true;
  904. }
  905. else
  906. {
  907. m_log.WarnFormat("[SIMIAN GROUPS CONNECTOR]: Error {0}, {1}, {2}, {3}", ownerID, type, key, Response["Message"]);
  908. return false;
  909. }
  910. }
  911. /// <summary>
  912. /// Returns the first of possibly many entries for Owner/Type pair
  913. /// </summary>
  914. private bool SimianGetFirstGenericEntry(UUID ownerID, string type, out string key, out OSDMap map)
  915. {
  916. if (m_debugEnabled) m_log.InfoFormat("[SIMIAN-GROUPS-CONNECTOR] {0} called ({1},{2})", System.Reflection.MethodBase.GetCurrentMethod().Name, ownerID, type);
  917. NameValueCollection RequestArgs = new NameValueCollection
  918. {
  919. { "RequestMethod", "GetGenerics" },
  920. { "OwnerID", ownerID.ToString() },
  921. { "Type", type }
  922. };
  923. OSDMap Response = CachedPostRequest(RequestArgs);
  924. if (Response["Success"].AsBoolean() && Response["Entries"] is OSDArray)
  925. {
  926. OSDArray entryArray = (OSDArray)Response["Entries"];
  927. if (entryArray.Count >= 1)
  928. {
  929. OSDMap entryMap = entryArray[0] as OSDMap;
  930. key = entryMap["Key"].AsString();
  931. map = (OSDMap)OSDParser.DeserializeJson(entryMap["Value"].AsString());
  932. if (m_debugEnabled) m_log.InfoFormat("[SIMIAN-GROUPS-CONNECTOR] Generics Result {0}", entryMap["Value"].AsString());
  933. return true;
  934. }
  935. else
  936. {
  937. if (m_debugEnabled) m_log.InfoFormat("[SIMIAN-GROUPS-CONNECTOR] No Generics Results");
  938. }
  939. }
  940. else
  941. {
  942. m_log.WarnFormat("[SIMIAN GROUPS CONNECTOR]: Error retrieving group info ({0})", Response["Message"]);
  943. }
  944. key = null;
  945. map = null;
  946. return false;
  947. }
  948. private bool SimianGetFirstGenericEntry(string type, string key, out UUID ownerID, out OSDMap map)
  949. {
  950. if (m_debugEnabled) m_log.InfoFormat("[SIMIAN-GROUPS-CONNECTOR] {0} called ({1},{2})", System.Reflection.MethodBase.GetCurrentMethod().Name, type, key);
  951. NameValueCollection RequestArgs = new NameValueCollection
  952. {
  953. { "RequestMethod", "GetGenerics" },
  954. { "Type", type },
  955. { "Key", key}
  956. };
  957. OSDMap Response = CachedPostRequest(RequestArgs);
  958. if (Response["Success"].AsBoolean() && Response["Entries"] is OSDArray)
  959. {
  960. OSDArray entryArray = (OSDArray)Response["Entries"];
  961. if (entryArray.Count >= 1)
  962. {
  963. OSDMap entryMap = entryArray[0] as OSDMap;
  964. ownerID = entryMap["OwnerID"].AsUUID();
  965. map = (OSDMap)OSDParser.DeserializeJson(entryMap["Value"].AsString());
  966. if (m_debugEnabled) m_log.InfoFormat("[SIMIAN-GROUPS-CONNECTOR] Generics Result {0}", entryMap["Value"].AsString());
  967. return true;
  968. }
  969. else
  970. {
  971. if (m_debugEnabled) m_log.InfoFormat("[SIMIAN-GROUPS-CONNECTOR] No Generics Results");
  972. }
  973. }
  974. else
  975. {
  976. m_log.WarnFormat("[SIMIAN GROUPS CONNECTOR]: Error retrieving group info ({0})", Response["Message"]);
  977. }
  978. ownerID = UUID.Zero;
  979. map = null;
  980. return false;
  981. }
  982. private bool SimianGetGenericEntry(UUID ownerID, string type, string key, out OSDMap map)
  983. {
  984. if (m_debugEnabled) m_log.InfoFormat("[SIMIAN-GROUPS-CONNECTOR] {0} called ({1},{2},{3})", System.Reflection.MethodBase.GetCurrentMethod().Name, ownerID, type, key);
  985. NameValueCollection RequestArgs = new NameValueCollection
  986. {
  987. { "RequestMethod", "GetGenerics" },
  988. { "OwnerID", ownerID.ToString() },
  989. { "Type", type },
  990. { "Key", key}
  991. };
  992. OSDMap Response = CachedPostRequest(RequestArgs);
  993. if (Response["Success"].AsBoolean() && Response["Entries"] is OSDArray)
  994. {
  995. OSDArray entryArray = (OSDArray)Response["Entries"];
  996. if (entryArray.Count == 1)
  997. {
  998. OSDMap entryMap = entryArray[0] as OSDMap;
  999. key = entryMap["Key"].AsString();
  1000. map = (OSDMap)OSDParser.DeserializeJson(entryMap["Value"].AsString());
  1001. if (m_debugEnabled) m_log.InfoFormat("[SIMIAN-GROUPS-CONNECTOR] Generics Result {0}", entryMap["Value"].AsString());
  1002. return true;
  1003. }
  1004. else
  1005. {
  1006. if (m_debugEnabled) m_log.InfoFormat("[SIMIAN-GROUPS-CONNECTOR] No Generics Results");
  1007. }
  1008. }
  1009. else
  1010. {
  1011. m_log.WarnFormat("[SIMIAN GROUPS CONNECTOR]: Error retrieving group info ({0})", Response["Message"]);
  1012. }
  1013. map = null;
  1014. return false;
  1015. }
  1016. private bool SimianGetGenericEntries(UUID ownerID, string type, out Dictionary<string, OSDMap> maps)
  1017. {
  1018. if (m_debugEnabled) m_log.InfoFormat("[SIMIAN-GROUPS-CONNECTOR] {0} called ({1},{2})", System.Reflection.MethodBase.GetCurrentMethod().Name,ownerID, type);
  1019. NameValueCollection requestArgs = new NameValueCollection
  1020. {
  1021. { "RequestMethod", "GetGenerics" },
  1022. { "OwnerID", ownerID.ToString() },
  1023. { "Type", type }
  1024. };
  1025. OSDMap response = CachedPostRequest(requestArgs);
  1026. if (response["Success"].AsBoolean() && response["Entries"] is OSDArray)
  1027. {
  1028. maps = new Dictionary<string, OSDMap>();
  1029. OSDArray entryArray = (OSDArray)response["Entries"];
  1030. foreach (OSDMap entryMap in entryArray)
  1031. {
  1032. if (m_debugEnabled) m_log.InfoFormat("[SIMIAN-GROUPS-CONNECTOR] Generics Result {0}", entryMap["Value"].AsString());
  1033. maps.Add(entryMap["Key"].AsString(), (OSDMap)OSDParser.DeserializeJson(entryMap["Value"].AsString()));
  1034. }
  1035. if (maps.Count == 0)
  1036. {
  1037. if (m_debugEnabled) m_log.InfoFormat("[SIMIAN-GROUPS-CONNECTOR] No Generics Results");
  1038. }
  1039. return true;
  1040. }
  1041. else
  1042. {
  1043. maps = null;
  1044. m_log.WarnFormat("[SIMIAN GROUPS CONNECTOR]: Error retrieving group info ({0})", response["Message"]);
  1045. }
  1046. return false;
  1047. }
  1048. private bool SimianGetGenericEntries(string type, string key, out Dictionary<UUID, OSDMap> maps)
  1049. {
  1050. if (m_debugEnabled) m_log.InfoFormat("[SIMIAN-GROUPS-CONNECTOR] {0} called ({1},{2})", System.Reflection.MethodBase.GetCurrentMethod().Name, type, key);
  1051. NameValueCollection requestArgs = new NameValueCollection
  1052. {
  1053. { "RequestMethod", "GetGenerics" },
  1054. { "Type", type },
  1055. { "Key", key }
  1056. };
  1057. OSDMap response = CachedPostRequest(requestArgs);
  1058. if (response["Success"].AsBoolean() && response["Entries"] is OSDArray)
  1059. {
  1060. maps = new Dictionary<UUID, OSDMap>();
  1061. OSDArray entryArray = (OSDArray)response["Entries"];
  1062. foreach (OSDMap entryMap in entryArray)
  1063. {
  1064. if (m_debugEnabled) m_log.InfoFormat("[SIMIAN-GROUPS-CONNECTOR] Generics Result {0}", entryMap["Value"].AsString());
  1065. maps.Add(entryMap["OwnerID"].AsUUID(), (OSDMap)OSDParser.DeserializeJson(entryMap["Value"].AsString()));
  1066. }
  1067. if (maps.Count == 0)
  1068. {
  1069. if (m_debugEnabled) m_log.InfoFormat("[SIMIAN-GROUPS-CONNECTOR] No Generics Results");
  1070. }
  1071. return true;
  1072. }
  1073. else
  1074. {
  1075. maps = null;
  1076. m_log.WarnFormat("[SIMIAN-GROUPS-CONNECTOR]: Error retrieving group info ({0})", response["Message"]);
  1077. }
  1078. return false;
  1079. }
  1080. private bool SimianRemoveGenericEntry(UUID ownerID, string type, string key)
  1081. {
  1082. if (m_debugEnabled) m_log.InfoFormat("[SIMIAN-GROUPS-CONNECTOR] {0} called ({1},{2},{3})", System.Reflection.MethodBase.GetCurrentMethod().Name, ownerID, type, key);
  1083. NameValueCollection requestArgs = new NameValueCollection
  1084. {
  1085. { "RequestMethod", "RemoveGeneric" },
  1086. { "OwnerID", ownerID.ToString() },
  1087. { "Type", type },
  1088. { "Key", key }
  1089. };
  1090. OSDMap response = CachedPostRequest(requestArgs);
  1091. if (response["Success"].AsBoolean())
  1092. {
  1093. return true;
  1094. }
  1095. else
  1096. {
  1097. m_log.WarnFormat("[SIMIAN GROUPS CONNECTOR]: Error {0}, {1}, {2}, {3}", ownerID, type, key, response["Message"]);
  1098. return false;
  1099. }
  1100. }
  1101. #endregion
  1102. #region CheesyCache
  1103. OSDMap CachedPostRequest(NameValueCollection requestArgs)
  1104. {
  1105. // Immediately forward the request if the cache is disabled.
  1106. if (m_cacheTimeout == 0)
  1107. {
  1108. m_log.WarnFormat("[SIMIAN GROUPS CONNECTOR]: cache is disabled");
  1109. return WebUtil.PostToService(m_groupsServerURI, requestArgs);
  1110. }
  1111. // Check if this is an update or a request
  1112. if (requestArgs["RequestMethod"] == "RemoveGeneric"
  1113. || requestArgs["RequestMethod"] == "AddGeneric")
  1114. {
  1115. m_log.WarnFormat("[SIMIAN GROUPS CONNECTOR]: clearing generics cache");
  1116. // Any and all updates cause the cache to clear
  1117. m_memoryCache.Clear();
  1118. // Send update to server, return the response without caching it
  1119. return WebUtil.PostToService(m_groupsServerURI, requestArgs);
  1120. }
  1121. // If we're not doing an update, we must be requesting data
  1122. // Create the cache key for the request and see if we have it cached
  1123. string CacheKey = WebUtil.BuildQueryString(requestArgs);
  1124. // This code uses a leader/follower pattern. On a cache miss, the request is added
  1125. // to a queue; the first thread to add it to the queue completes the request while
  1126. // follow on threads busy wait for the results, this situation seems to happen
  1127. // often when checking permissions
  1128. while (true)
  1129. {
  1130. OSDMap response = null;
  1131. bool firstRequest = false;
  1132. lock (m_memoryCache)
  1133. {
  1134. if (m_memoryCache.TryGetValue(CacheKey, out response))
  1135. return response;
  1136. if (! m_pendingRequests.ContainsKey(CacheKey))
  1137. {
  1138. m_pendingRequests.Add(CacheKey,true);
  1139. firstRequest = true;
  1140. }
  1141. }
  1142. if (firstRequest)
  1143. {
  1144. // if it wasn't in the cache, pass the request to the Simian Grid Services
  1145. try
  1146. {
  1147. response = WebUtil.PostToService(m_groupsServerURI, requestArgs);
  1148. }
  1149. catch (Exception)
  1150. {
  1151. m_log.ErrorFormat("[SIMIAN GROUPS CONNECTOR]: request failed {0}", CacheKey);
  1152. }
  1153. // and cache the response
  1154. lock (m_memoryCache)
  1155. {
  1156. m_memoryCache.AddOrUpdate(CacheKey, response, TimeSpan.FromSeconds(m_cacheTimeout));
  1157. m_pendingRequests.Remove(CacheKey);
  1158. }
  1159. return response;
  1160. }
  1161. Thread.Sleep(50); // waiting for a web request to complete, 50msecs is reasonable
  1162. }
  1163. // if (!m_memoryCache.TryGetValue(CacheKey, out response))
  1164. // {
  1165. // m_log.WarnFormat("[SIMIAN GROUPS CONNECTOR]: query not in the cache");
  1166. // Util.PrintCallStack();
  1167. // // if it wasn't in the cache, pass the request to the Simian Grid Services
  1168. // response = WebUtil.PostToService(m_groupsServerURI, requestArgs);
  1169. // // and cache the response
  1170. // m_memoryCache.AddOrUpdate(CacheKey, response, TimeSpan.FromSeconds(m_cacheTimeout));
  1171. // }
  1172. // // return cached response
  1173. // return response;
  1174. }
  1175. #endregion
  1176. }
  1177. }