Skip to content

Commit

Permalink
Merge pull request #2947 from AgaSpace/accountgroupcupdate-hook
Browse files Browse the repository at this point in the history
Added AccountGroupUpdate hook, when trying to change a user group.
  • Loading branch information
hakusaro authored Jan 26, 2025
2 parents 846ccb4 + 4cab985 commit faf7854
Show file tree
Hide file tree
Showing 5 changed files with 105 additions and 4 deletions.
6 changes: 5 additions & 1 deletion TShockAPI/Commands.cs
Original file line number Diff line number Diff line change
Expand Up @@ -1176,7 +1176,7 @@ private static void ManageUsers(CommandArgs args)

try
{
TShock.UserAccounts.SetUserGroup(account, args.Parameters[2]);
TShock.UserAccounts.SetUserGroup(args.Player, account, args.Parameters[2]);
TShock.Log.ConsoleInfo(GetString("{0} changed account {1} to group {2}.", args.Player.Name, account.Name, args.Parameters[2]));
args.Player.SendSuccessMessage(GetString("Account {0} has been changed to group {1}.", account.Name, args.Parameters[2]));

Expand All @@ -1193,6 +1193,10 @@ private static void ManageUsers(CommandArgs args)
{
args.Player.SendErrorMessage(GetString($"User {account.Name} does not exist."));
}
catch (UserGroupUpdateLockedException)
{
args.Player.SendErrorMessage(GetString("Hook blocked the attempt to change the user group."));
}
catch (UserAccountManagerException e)
{
args.Player.SendErrorMessage(GetString($"User {account.Name} could not be added. Check console for details."));
Expand Down
53 changes: 51 additions & 2 deletions TShockAPI/DB/UserManager.cs
Original file line number Diff line number Diff line change
Expand Up @@ -25,6 +25,7 @@ You should have received a copy of the GNU General Public License
using System.Text.RegularExpressions;
using BCrypt.Net;
using System.Security.Cryptography;
using TShockAPI.Hooks;

namespace TShockAPI.DB
{
Expand Down Expand Up @@ -166,7 +167,41 @@ public void SetUserGroup(UserAccount account, string group)
if (null == grp)
throw new GroupNotExistsException(group);

if (_database.Query("UPDATE Users SET UserGroup = @0 WHERE Username = @1;", group, account.Name) == 0)
if (AccountHooks.OnAccountGroupUpdate(account, ref grp))
throw new UserGroupUpdateLockedException(account.Name);

if (_database.Query("UPDATE Users SET UserGroup = @0 WHERE Username = @1;", grp.Name, account.Name) == 0)
throw new UserAccountNotExistException(account.Name);

try
{
// Update player group reference for any logged in player
foreach (var player in TShock.Players.Where(p => p != null && p.Account != null && p.Account.Name == account.Name))
{
player.Group = grp;
}
}
catch (Exception ex)
{
throw new UserAccountManagerException(GetString("SetUserGroup SQL returned an error"), ex);
}
}
/// <summary>
/// Sets the group for a given username
/// </summary>
/// <param name="author">Who changes the group</param>
/// <param name="account">The user account</param>
/// <param name="group">The user account group to be set</param>
public void SetUserGroup(TSPlayer author, UserAccount account, string group)
{
Group grp = TShock.Groups.GetGroupByName(group);
if (null == grp)
throw new GroupNotExistsException(group);

if (AccountHooks.OnAccountGroupUpdate(account, author, ref grp))
throw new UserGroupUpdateLockedException(account.Name);

if (_database.Query("UPDATE Users SET UserGroup = @0 WHERE Username = @1;", grp.Name, account.Name) == 0)
throw new UserAccountNotExistException(account.Name);

try
Expand Down Expand Up @@ -619,14 +654,28 @@ public UserAccountExistsException(string name)
public class UserAccountNotExistException : UserAccountManagerException
{
/// <summary>Creates a new UserAccountNotExistException object, with the user account name in the message.</summary>
/// <param name="name">The user account name to be pasesd in the message.</param>
/// <param name="name">The user account name to be passed in the message.</param>
/// <returns>A new UserAccountNotExistException object with a message containing the user account name that does not exist.</returns>
public UserAccountNotExistException(string name)
: base(GetString($"User account {name} does not exist"))
{
}
}

/// <summary>The UserGroupUpdateLockedException used when the user group update failed and the request failed as a result.</summary>.
[Serializable]
public class UserGroupUpdateLockedException : UserAccountManagerException
{
/// <summary>Creates a new UserGroupUpdateLockedException object.</summary>
/// <param name="name">The name of the user who failed to change the group.</param>
/// <returns>New UserGroupUpdateLockedException object with a message containing the name of the user account that failed to change the group.</returns>
public UserGroupUpdateLockedException(string name) :
base(GetString($"Unable to update group of user {name}."))
{
}
}


/// <summary>A GroupNotExistsException, used when a group does not exist.</summary>
[Serializable]
public class GroupNotExistsException : UserAccountManagerException
Expand Down
46 changes: 46 additions & 0 deletions TShockAPI/Hooks/AccountHooks.cs
Original file line number Diff line number Diff line change
Expand Up @@ -16,6 +16,7 @@ You should have received a copy of the GNU General Public License
along with this program. If not, see <http://www.gnu.org/licenses/>.
*/

using System.ComponentModel;
using TShockAPI.DB;
namespace TShockAPI.Hooks
{
Expand All @@ -39,6 +40,31 @@ public AccountCreateEventArgs(UserAccount account)
}
}

public class AccountGroupUpdateEventArgs : HandledEventArgs
{
public string AccountName { get; private set; }
public Group Group { get; set; }

public AccountGroupUpdateEventArgs(string accountName, Group group)
{
this.AccountName = accountName;
this.Group = group;
}
}

public class AccountGroupUpdateByPlayerEventArgs : AccountGroupUpdateEventArgs
{
/// <summary>
/// The player who updated the user's group
/// </summary>
public TSPlayer Player { get; private set; }

public AccountGroupUpdateByPlayerEventArgs(TSPlayer player, string accountName, Group group) : base(accountName, group)
{
this.Player = player;
}
}

public class AccountHooks
{
public delegate void AccountCreateD(AccountCreateEventArgs e);
Expand All @@ -62,5 +88,25 @@ public static void OnAccountDelete(UserAccount u)

AccountDelete(new AccountDeleteEventArgs(u));
}

public delegate void AccountGroupUpdateD(AccountGroupUpdateEventArgs e);
public static event AccountGroupUpdateD AccountGroupUpdate;

public static bool OnAccountGroupUpdate(UserAccount account, TSPlayer author, ref Group group)
{
AccountGroupUpdateEventArgs args = new AccountGroupUpdateByPlayerEventArgs(author, account.Name, group);
AccountGroupUpdate?.Invoke(args);
group = args.Group;

return args.Handled;
}
public static bool OnAccountGroupUpdate(UserAccount account, ref Group group)
{
AccountGroupUpdateEventArgs args = new AccountGroupUpdateEventArgs(account.Name, group);
AccountGroupUpdate?.Invoke(args);
group = args.Group;

return args.Handled;
}
}
}
3 changes: 2 additions & 1 deletion TShockAPI/Rest/RestManager.cs
Original file line number Diff line number Diff line change
Expand Up @@ -555,7 +555,8 @@ private object UserUpdateV2(RestRequestArgs args)
{
try
{
TShock.UserAccounts.SetUserGroup(account, group);
TShock.UserAccounts.SetUserGroup(new TSRestPlayer(args.TokenData.Username, TShock.Groups.GetGroupByName(args.TokenData.UserGroupName)),
account, group);
response.Add("group-response", "Group updated successfully");
}
catch (Exception e)
Expand Down
1 change: 1 addition & 0 deletions docs/changelog.md
Original file line number Diff line number Diff line change
Expand Up @@ -89,6 +89,7 @@ Use past tense when adding new entries; sign your name off when you add or chang
* Fixed unable to transfer long response body for REST API. (@sgkoishi, #2925)
* Fixed the `/wind` command not being very helpful. (@punchready)
* Fixed /help, /me, and /p commands can't work in non-English languages. (@ACaiCat)
* Added a hook `AccountHooks.AccountGroupUpdate`, which is called when you change the user group. (@AgaSpace)

## TShock 5.2.1
* Updated `TSPlayer.GodMode`. (@AgaSpace)
Expand Down

0 comments on commit faf7854

Please sign in to comment.