SimianGroupsServicesConnectorModule.cs 59 KB

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