From 5e4d6cab00cb29cd088ab7b62ab13aff103b64cb Mon Sep 17 00:00:00 2001 From: onefang Date: Sun, 19 May 2019 21:24:15 +1000 Subject: Dump OpenSim 0.9.0.1 into it's own branch. --- .../UserAccountService/UserAccountService.cs | 383 +++++++++++++++++++-- 1 file changed, 347 insertions(+), 36 deletions(-) (limited to 'OpenSim/Services/UserAccountService/UserAccountService.cs') diff --git a/OpenSim/Services/UserAccountService/UserAccountService.cs b/OpenSim/Services/UserAccountService/UserAccountService.cs index 2e19ece..48929ee 100644 --- a/OpenSim/Services/UserAccountService/UserAccountService.cs +++ b/OpenSim/Services/UserAccountService/UserAccountService.cs @@ -43,6 +43,7 @@ namespace OpenSim.Services.UserAccountService public class UserAccountService : UserAccountServiceBase, IUserAccountService { private static readonly ILog m_log = LogManager.GetLogger(MethodBase.GetCurrentMethod().DeclaringType); + private static readonly UUID UUID_GRID_GOD = new UUID("6571e388-6218-4574-87db-f9379718315e"); private static UserAccountService m_RootInstance; /// @@ -85,38 +86,63 @@ namespace OpenSim.Services.UserAccountService m_CreateDefaultAvatarEntries = userConfig.GetBoolean("CreateDefaultAvatarEntries", false); - // In case there are several instances of this class in the same process, - // the console commands are only registered for the root instance - if (m_RootInstance == null && MainConsole.Instance != null) + // create a system grid god account + UserAccount ggod = GetUserAccount(UUID.Zero, UUID_GRID_GOD); + if(ggod == null) + { + UserAccountData d = new UserAccountData(); + + d.FirstName = "GRID"; + d.LastName = "SERVICES"; + d.PrincipalID = UUID_GRID_GOD; + d.ScopeID = UUID.Zero; + d.Data = new Dictionary(); + d.Data["Email"] = string.Empty; + d.Data["Created"] = Util.UnixTimeSinceEpoch().ToString(); + d.Data["UserLevel"] = "240"; + d.Data["UserFlags"] = "0"; + d.Data["ServiceURLs"] = string.Empty; + + m_Database.Store(d); + } + + if (m_RootInstance == null) { m_RootInstance = this; - MainConsole.Instance.Commands.AddCommand("Users", false, - "create user", - "create user [ [ [ [ []]]]]", - "Create a new user", HandleCreateUser); - - MainConsole.Instance.Commands.AddCommand("Users", false, - "reset user password", - "reset user password [ [ []]]", - "Reset a user password", HandleResetUserPassword); - - MainConsole.Instance.Commands.AddCommand("Users", false, - "reset user email", - "reset user email [ [ []]]", - "Reset a user email address", HandleResetUserEmail); - - MainConsole.Instance.Commands.AddCommand("Users", false, - "set user level", - "set user level [ [ []]]", - "Set user level. If >= 200 and 'allow_grid_gods = true' in OpenSim.ini, " - + "this account will be treated as god-moded. " - + "It will also affect the 'login level' command. ", - HandleSetUserLevel); - - MainConsole.Instance.Commands.AddCommand("Users", false, - "show account", - "show account ", - "Show account details for the given user", HandleShowAccount); + + // In case there are several instances of this class in the same process, + // the console commands are only registered for the root instance + if (MainConsole.Instance != null) + { + + MainConsole.Instance.Commands.AddCommand("Users", false, + "create user", + "create user [ [ [ [ [ []]]]]]", + "Create a new user", HandleCreateUser); + + MainConsole.Instance.Commands.AddCommand("Users", false, + "reset user password", + "reset user password [ [ []]]", + "Reset a user password", HandleResetUserPassword); + + MainConsole.Instance.Commands.AddCommand("Users", false, + "reset user email", + "reset user email [ [ []]]", + "Reset a user email address", HandleResetUserEmail); + + MainConsole.Instance.Commands.AddCommand("Users", false, + "set user level", + "set user level [ [ []]]", + "Set user level. If >= 200 and 'allow_grid_gods = true' in OpenSim.ini, " + + "this account will be treated as god-moded. " + + "It will also affect the 'login level' command. ", + HandleSetUserLevel); + + MainConsole.Instance.Commands.AddCommand("Users", false, + "show account", + "show account ", + "Show account details for the given user", HandleShowAccount); + } } } @@ -176,6 +202,10 @@ namespace OpenSim.Services.UserAccountService Int32.TryParse(d.Data["UserLevel"], out u.UserLevel); if (d.Data.ContainsKey("UserFlags") && d.Data["UserFlags"] != null) Int32.TryParse(d.Data["UserFlags"], out u.UserFlags); + if (d.Data.ContainsKey("UserCountry") && d.Data["UserCountry"] != null) + u.UserCountry = d.Data["UserCountry"].ToString(); + else + u.UserCountry = string.Empty; if (d.Data.ContainsKey("ServiceURLs") && d.Data["ServiceURLs"] != null) { @@ -261,6 +291,19 @@ namespace OpenSim.Services.UserAccountService return MakeUserAccount(d[0]); } + public List GetUserAccounts(UUID scopeID, List IDs) + { + // do it one at a time db access should be fast, so no need to break its api + List accs = new List(); + UUID uuid = UUID.Zero; + foreach(string id in IDs) + { + if (UUID.TryParse(id, out uuid) && uuid != UUID.Zero) + accs.Add(GetUserAccount(scopeID, uuid)); + } + return accs; + } + public void InvalidateCache(UUID userID) { } @@ -301,7 +344,22 @@ namespace OpenSim.Services.UserAccountService public List GetUserAccounts(UUID scopeID, string query) { - UserAccountData[] d = m_Database.GetUsers(scopeID, query); + UserAccountData[] d = m_Database.GetUsers(scopeID, query.Trim()); + + if (d == null) + return new List(); + + List ret = new List(); + + foreach (UserAccountData data in d) + ret.Add(MakeUserAccount(data)); + + return ret; + } + + public List GetUserAccountsWhere(UUID scopeID, string where) + { + UserAccountData[] d = m_Database.GetUsersWhere(scopeID, where); if (d == null) return new List(); @@ -321,7 +379,7 @@ namespace OpenSim.Services.UserAccountService /// /// Handle the create user command from the console. /// - /// string array with parameters: firstname, lastname, password, locationX, locationY, email + /// string array with parameters: firstname, lastname, password, locationX, locationY, email, userID, model name protected void HandleCreateUser(string module, string[] cmdparams) { string firstName; @@ -329,6 +387,7 @@ namespace OpenSim.Services.UserAccountService string password; string email; string rawPrincipalId; + string model; List excluded = new List(new char[]{' '}); @@ -353,11 +412,16 @@ namespace OpenSim.Services.UserAccountService else rawPrincipalId = cmdparams[6]; + if (cmdparams.Length < 8) + model = MainConsole.Instance.CmdPrompt("Model name",""); + else + model = cmdparams[7]; + UUID principalId = UUID.Zero; if (!UUID.TryParse(rawPrincipalId, out principalId)) throw new Exception(string.Format("ID {0} is not a valid UUID", rawPrincipalId)); - CreateUser(UUID.Zero, principalId, firstName, lastName, password, email); + CreateUser(UUID.Zero, principalId, firstName, lastName, password, email, model); } protected void HandleShowAccount(string module, string[] cmdparams) @@ -512,7 +576,8 @@ namespace OpenSim.Services.UserAccountService /// /// /// - public UserAccount CreateUser(UUID scopeID, UUID principalID, string firstName, string lastName, string password, string email) + /// + public UserAccount CreateUser(UUID scopeID, UUID principalID, string firstName, string lastName, string password, string email, string model = "") { UserAccount account = GetUserAccount(UUID.Zero, firstName, lastName); if (null == account) @@ -571,7 +636,12 @@ namespace OpenSim.Services.UserAccountService } if (m_CreateDefaultAvatarEntries) - CreateDefaultAppearanceEntries(account.PrincipalID); + { + if (String.IsNullOrEmpty(model)) + CreateDefaultAppearanceEntries(account.PrincipalID); + else + EstablishAppearance(account.PrincipalID, model); + } } m_log.InfoFormat( @@ -596,9 +666,11 @@ namespace OpenSim.Services.UserAccountService m_log.DebugFormat("[USER ACCOUNT SERVICE]: Creating default appearance items for {0}", principalID); InventoryFolderBase bodyPartsFolder = m_InventoryService.GetFolderForType(principalID, FolderType.BodyPart); + // Get Current Outfit folder + InventoryFolderBase currentOutfitFolder = m_InventoryService.GetFolderForType(principalID, FolderType.CurrentOutfit); InventoryItemBase eyes = new InventoryItemBase(UUID.Random(), principalID); - eyes.AssetID = new UUID("4bb6fa4d-1cd2-498a-a84c-95c1a0e745a7"); + eyes.AssetID = AvatarWearable.DEFAULT_EYES_ASSET; eyes.Name = "Default Eyes"; eyes.CreatorId = principalID.ToString(); eyes.AssetType = (int)AssetType.Bodypart; @@ -611,6 +683,7 @@ namespace OpenSim.Services.UserAccountService eyes.NextPermissions = (uint)PermissionMask.All; eyes.Flags = (uint)WearableType.Eyes; m_InventoryService.AddItem(eyes); + CreateCurrentOutfitLink((int)InventoryType.Wearable, (uint)WearableType.Eyes, eyes.Name, eyes.ID, principalID, currentOutfitFolder.ID); InventoryItemBase shape = new InventoryItemBase(UUID.Random(), principalID); shape.AssetID = AvatarWearable.DEFAULT_BODY_ASSET; @@ -626,6 +699,7 @@ namespace OpenSim.Services.UserAccountService shape.NextPermissions = (uint)PermissionMask.All; shape.Flags = (uint)WearableType.Shape; m_InventoryService.AddItem(shape); + CreateCurrentOutfitLink((int)InventoryType.Wearable, (uint)WearableType.Shape, shape.Name, shape.ID, principalID, currentOutfitFolder.ID); InventoryItemBase skin = new InventoryItemBase(UUID.Random(), principalID); skin.AssetID = AvatarWearable.DEFAULT_SKIN_ASSET; @@ -641,6 +715,7 @@ namespace OpenSim.Services.UserAccountService skin.NextPermissions = (uint)PermissionMask.All; skin.Flags = (uint)WearableType.Skin; m_InventoryService.AddItem(skin); + CreateCurrentOutfitLink((int)InventoryType.Wearable, (uint)WearableType.Skin, skin.Name, skin.ID, principalID, currentOutfitFolder.ID); InventoryItemBase hair = new InventoryItemBase(UUID.Random(), principalID); hair.AssetID = AvatarWearable.DEFAULT_HAIR_ASSET; @@ -656,6 +731,7 @@ namespace OpenSim.Services.UserAccountService hair.NextPermissions = (uint)PermissionMask.All; hair.Flags = (uint)WearableType.Hair; m_InventoryService.AddItem(hair); + CreateCurrentOutfitLink((int)InventoryType.Wearable, (uint)WearableType.Hair, hair.Name, hair.ID, principalID, currentOutfitFolder.ID); InventoryFolderBase clothingFolder = m_InventoryService.GetFolderForType(principalID, FolderType.Clothing); @@ -673,6 +749,7 @@ namespace OpenSim.Services.UserAccountService shirt.NextPermissions = (uint)PermissionMask.All; shirt.Flags = (uint)WearableType.Shirt; m_InventoryService.AddItem(shirt); + CreateCurrentOutfitLink((int)InventoryType.Wearable, (uint)WearableType.Shirt, shirt.Name, shirt.ID, principalID, currentOutfitFolder.ID); InventoryItemBase pants = new InventoryItemBase(UUID.Random(), principalID); pants.AssetID = AvatarWearable.DEFAULT_PANTS_ASSET; @@ -688,6 +765,7 @@ namespace OpenSim.Services.UserAccountService pants.NextPermissions = (uint)PermissionMask.All; pants.Flags = (uint)WearableType.Pants; m_InventoryService.AddItem(pants); + CreateCurrentOutfitLink((int)InventoryType.Wearable, (uint)WearableType.Pants, pants.Name, pants.ID, principalID, currentOutfitFolder.ID); if (m_AvatarService != null) { @@ -702,6 +780,7 @@ namespace OpenSim.Services.UserAccountService wearables[AvatarWearable.PANTS] = new AvatarWearable(pants.ID, pants.AssetID); AvatarAppearance ap = new AvatarAppearance(); + // this loop works, but is questionable for (int i = 0; i < 6; i++) { ap.SetWearable(i, wearables[i]); @@ -710,5 +789,237 @@ namespace OpenSim.Services.UserAccountService m_AvatarService.SetAppearance(principalID, ap); } } + + protected void EstablishAppearance(UUID destinationAgent, string model) + { + m_log.DebugFormat("[USER ACCOUNT SERVICE]: Establishing new appearance for {0} - {1}", + destinationAgent.ToString(), model); + + string[] modelSpecifiers = model.Split(); + if (modelSpecifiers.Length != 2) + { + m_log.WarnFormat("[USER ACCOUNT SERVICE]: Invalid model name \'{0}\'. Falling back to Ruth for {1}", + model, destinationAgent); + CreateDefaultAppearanceEntries(destinationAgent); + return; + } + + // Does the source model exist? + UserAccount modelAccount = GetUserAccount(UUID.Zero, modelSpecifiers[0], modelSpecifiers[1]); + if (modelAccount == null) + { + m_log.WarnFormat("[USER ACCOUNT SERVICE]: Requested model \'{0}\' not found. Falling back to Ruth for {1}", + model, destinationAgent); + CreateDefaultAppearanceEntries(destinationAgent); + return; + } + + // Does the source model have an established appearance herself? + AvatarAppearance modelAppearance = m_AvatarService.GetAppearance(modelAccount.PrincipalID); + if (modelAppearance == null) + { + m_log.WarnFormat("USER ACCOUNT SERVICE]: Requested model \'{0}\' does not have an established appearance. Falling back to Ruth for {1}", + model, destinationAgent); + CreateDefaultAppearanceEntries(destinationAgent); + return; + } + + try + { + CopyWearablesAndAttachments(destinationAgent, modelAccount.PrincipalID, modelAppearance); + + m_AvatarService.SetAppearance(destinationAgent, modelAppearance); + } + catch (Exception e) + { + m_log.WarnFormat("[USER ACCOUNT SERVICE]: Error transferring appearance for {0} : {1}", + destinationAgent, e.Message); + } + + m_log.DebugFormat("[USER ACCOUNT SERVICE]: Finished establishing appearance for {0}", + destinationAgent.ToString()); + } + + /// + /// This method is called by EstablishAppearance to do a copy all inventory items + /// worn or attached to the Clothing inventory folder of the receiving avatar. + /// In parallel the avatar wearables and attachments are updated. + /// + private void CopyWearablesAndAttachments(UUID destination, UUID source, AvatarAppearance avatarAppearance) + { + // Get Clothing folder of receiver + InventoryFolderBase destinationFolder = m_InventoryService.GetFolderForType(destination, FolderType.Clothing); + // Get Current Outfit folder + InventoryFolderBase currentOutfitFolder = m_InventoryService.GetFolderForType(destination, FolderType.CurrentOutfit); + + if (destinationFolder == null) + throw new Exception("Cannot locate folder(s)"); + + // Missing destination folder? This should *never* be the case + if (destinationFolder.Type != (short)FolderType.Clothing) + { + destinationFolder = new InventoryFolderBase(); + + destinationFolder.ID = UUID.Random(); + destinationFolder.Name = "Clothing"; + destinationFolder.Owner = destination; + destinationFolder.Type = (short)AssetType.Clothing; + destinationFolder.ParentID = m_InventoryService.GetRootFolder(destination).ID; + destinationFolder.Version = 1; + m_InventoryService.AddFolder(destinationFolder); // store base record + m_log.ErrorFormat("[USER ACCOUNT SERVICE]: Created folder for destination {0}", source); + } + + // Wearables + AvatarWearable[] wearables = avatarAppearance.Wearables; + AvatarWearable wearable; + + for (int i = 0; i < wearables.Length; i++) + { + wearable = wearables[i]; + m_log.DebugFormat("[XXX]: Getting item {0} from avie {1}", wearable[0].ItemID, source); + if (wearable[0].ItemID != UUID.Zero) + { + // Get inventory item and copy it + InventoryItemBase item = m_InventoryService.GetItem(source, wearable[0].ItemID); + + if (item != null) + { + InventoryItemBase destinationItem = new InventoryItemBase(UUID.Random(), destination); + destinationItem.Name = item.Name; + destinationItem.Owner = destination; + destinationItem.Description = item.Description; + destinationItem.InvType = item.InvType; + destinationItem.CreatorId = item.CreatorId; + destinationItem.CreatorData = item.CreatorData; + destinationItem.NextPermissions = item.NextPermissions; + destinationItem.CurrentPermissions = item.CurrentPermissions; + destinationItem.BasePermissions = item.BasePermissions; + destinationItem.EveryOnePermissions = item.EveryOnePermissions; + destinationItem.GroupPermissions = item.GroupPermissions; + destinationItem.AssetType = item.AssetType; + destinationItem.AssetID = item.AssetID; + destinationItem.GroupID = item.GroupID; + destinationItem.GroupOwned = item.GroupOwned; + destinationItem.SalePrice = item.SalePrice; + destinationItem.SaleType = item.SaleType; + destinationItem.Flags = item.Flags; + destinationItem.CreationDate = item.CreationDate; + destinationItem.Folder = destinationFolder.ID; + ApplyNextOwnerPermissions(destinationItem); + + m_InventoryService.AddItem(destinationItem); + m_log.DebugFormat("[USER ACCOUNT SERVICE]: Added item {0} to folder {1}", destinationItem.ID, destinationFolder.ID); + + // Wear item + AvatarWearable newWearable = new AvatarWearable(); + newWearable.Wear(destinationItem.ID, wearable[0].AssetID); + avatarAppearance.SetWearable(i, newWearable); + + // Add to Current Outfit + CreateCurrentOutfitLink((int)InventoryType.Wearable, item.Flags, item.Name, destinationItem.ID, destination, currentOutfitFolder.ID); + } + else + { + m_log.WarnFormat("[USER ACCOUNT SERVICE]: Error transferring {0} to folder {1}", wearable[0].ItemID, destinationFolder.ID); + } + } + } + + // Attachments + List attachments = avatarAppearance.GetAttachments(); + + foreach (AvatarAttachment attachment in attachments) + { + int attachpoint = attachment.AttachPoint; + UUID itemID = attachment.ItemID; + + if (itemID != UUID.Zero) + { + // Get inventory item and copy it + InventoryItemBase item = m_InventoryService.GetItem(source, itemID); + + if (item != null) + { + InventoryItemBase destinationItem = new InventoryItemBase(UUID.Random(), destination); + destinationItem.Name = item.Name; + destinationItem.Owner = destination; + destinationItem.Description = item.Description; + destinationItem.InvType = item.InvType; + destinationItem.CreatorId = item.CreatorId; + destinationItem.CreatorData = item.CreatorData; + destinationItem.NextPermissions = item.NextPermissions; + destinationItem.CurrentPermissions = item.CurrentPermissions; + destinationItem.BasePermissions = item.BasePermissions; + destinationItem.EveryOnePermissions = item.EveryOnePermissions; + destinationItem.GroupPermissions = item.GroupPermissions; + destinationItem.AssetType = item.AssetType; + destinationItem.AssetID = item.AssetID; + destinationItem.GroupID = item.GroupID; + destinationItem.GroupOwned = item.GroupOwned; + destinationItem.SalePrice = item.SalePrice; + destinationItem.SaleType = item.SaleType; + destinationItem.Flags = item.Flags; + destinationItem.CreationDate = item.CreationDate; + destinationItem.Folder = destinationFolder.ID; + ApplyNextOwnerPermissions(destinationItem); + + m_InventoryService.AddItem(destinationItem); + m_log.DebugFormat("[USER ACCOUNT SERVICE]: Added item {0} to folder {1}", destinationItem.ID, destinationFolder.ID); + + // Attach item + avatarAppearance.SetAttachment(attachpoint, destinationItem.ID, destinationItem.AssetID); + m_log.DebugFormat("[USER ACCOUNT SERVICE]: Attached {0}", destinationItem.ID); + + // Add to Current Outfit + CreateCurrentOutfitLink(destinationItem.InvType, item.Flags, item.Name, destinationItem.ID, destination, currentOutfitFolder.ID); + } + else + { + m_log.WarnFormat("[USER ACCOUNT SERVICE]: Error transferring {0} to folder {1}", itemID, destinationFolder.ID); + } + } + } + } + + protected void CreateCurrentOutfitLink(int invType, uint itemType, string name, UUID itemID, UUID userID, UUID currentOutfitFolderUUID) + { + UUID LinkInvItem = UUID.Random(); + InventoryItemBase itembase = new InventoryItemBase(LinkInvItem, userID) + { + AssetID = itemID, + AssetType = (int)AssetType.Link, + CreatorId = userID.ToString(), + InvType = invType, + Description = "", + //Folder = m_InventoryService.GetFolderForType(userID, FolderType.CurrentOutfit).ID, + Folder = currentOutfitFolderUUID, + Flags = itemType, + Name = name, + BasePermissions = (uint)PermissionMask.Copy, + CurrentPermissions = (uint)PermissionMask.Copy, + EveryOnePermissions = (uint)PermissionMask.Copy, + GroupPermissions = (uint)PermissionMask.Copy, + NextPermissions = (uint)PermissionMask.Copy + }; + + m_InventoryService.AddItem(itembase); + } + + /// + /// Apply next owner permissions. + /// + private void ApplyNextOwnerPermissions(InventoryItemBase item) + { + if (item.InvType == (int)InventoryType.Object) + { + uint perms = item.CurrentPermissions; + item.CurrentPermissions = perms; + } + + item.CurrentPermissions &= item.NextPermissions; + item.BasePermissions &= item.NextPermissions; + item.EveryOnePermissions &= item.NextPermissions; + } } } -- cgit v1.1