SimianGroupsServicesConnectorModule.cs 59 KB

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