SimianGroupsServicesConnectorModule.cs 59 KB

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