Removed the old REST model.

This includes the following endpoints:
* `/status`
* `/v2/players/read`
* `/v2/server/rawcmd`
This commit is contained in:
White 2016-10-23 21:40:09 +10:30
parent 28cd87cea0
commit 6151c86630
4 changed files with 17 additions and 116 deletions

View file

@ -11,6 +11,10 @@ This is the rolling changelog for TShock for Terraria. Use past tense when addin
* Fixed butterfly statues spawning catchable butterflies (@DogooFalchion).
* Implemented some missing balance changes lost in prior version patches (@DogooFalchion).
* Added alias for server shutdown command: stop (@nicatronTg).
* Removed the old REST model. This includes the following endpoints:
* `/status`
* `/v2/players/read`
* `/v2/server/rawcmd` (@WhiteXZ).
## TShock 4.3.20
* Security improvement: The auth system is now automatically disabled if a superadmin exists in the database (@Enerdy).

View file

@ -443,10 +443,6 @@ namespace TShockAPI
[Description("#.#.# = Red/Blue/Green - RGB Colors for broadcasts. Max value: 255.")]
public int[] BroadcastRGB = { 127, 255, 212 };
// TODO: Get rid of this when the old REST permission model is removed.
[Description("Whether the REST API should use the new permission model. Note: The old permission model will become depracted in the future.")]
public bool RestUseNewPermissionModel = true;
/// <summary>ApplicationRestTokens - A dictionary of REST tokens that external applications may use to make queries to your server.</summary>
[Description("A dictionary of REST tokens that external applications may use to make queries to your server.")]
public Dictionary<string, SecureRest.TokenData> ApplicationRestTokens = new Dictionary<string, SecureRest.TokenData>();

View file

@ -103,14 +103,12 @@ namespace TShockAPI
if (TShock.Config.EnableTokenEndpointAuthentication)
{
Rest.Register(new SecureRestCommand("/v2/server/status", ServerStatusV2));
Rest.Register(new SecureRestCommand("/status", ServerStatus));
Rest.Register(new SecureRestCommand("/v3/server/motd", ServerMotd));
Rest.Register(new SecureRestCommand("/v3/server/rules", ServerRules));
}
else
{
Rest.Register(new RestCommand("/v2/server/status", (a) => this.ServerStatusV2(new RestRequestArgs(a.Verbs, a.Parameters, a.Request, SecureRest.TokenData.None, a.Context))));
Rest.Register(new RestCommand("/status", (a) => this.ServerStatus(new RestRequestArgs(a.Verbs, a.Parameters, a.Request, SecureRest.TokenData.None, a.Context))));
Rest.Register(new RestCommand("/v3/server/motd", (a) => this.ServerMotd(new RestRequestArgs(a.Verbs, a.Parameters, a.Request, SecureRest.TokenData.None, a.Context))));
Rest.Register(new RestCommand("/v3/server/rules", (a) => this.ServerRules(new RestRequestArgs(a.Verbs, a.Parameters, a.Request, SecureRest.TokenData.None, a.Context))));
}
@ -119,7 +117,6 @@ namespace TShockAPI
Rest.Register(new SecureRestCommand("/v3/server/reload", ServerReload, RestPermissions.restcfg));
Rest.Register(new SecureRestCommand("/v2/server/off", ServerOff, RestPermissions.restmaintenance));
Rest.Register(new SecureRestCommand("/v3/server/restart", ServerRestart, RestPermissions.restmaintenance));
Rest.Register(new SecureRestCommand("/v2/server/rawcmd", ServerCommand, RestPermissions.restrawcommand));
Rest.Register(new SecureRestCommand("/v3/server/rawcmd", ServerCommandV3, RestPermissions.restrawcommand));
Rest.Register(new SecureRestCommand("/tokentest", ServerTokenTest));
@ -148,7 +145,6 @@ namespace TShockAPI
// Player Commands
Rest.Register(new SecureRestCommand("/lists/players", PlayerList));
Rest.Register(new SecureRestCommand("/v2/players/list", PlayerListV2));
Rest.Register(new SecureRestCommand("/v2/players/read", PlayerReadV2, RestPermissions.restuserinfo));
Rest.Register(new SecureRestCommand("/v3/players/read", PlayerReadV3, RestPermissions.restuserinfo));
Rest.Register(new SecureRestCommand("/v2/players/kick", PlayerKickV2, RestPermissions.restkick));
Rest.Register(new SecureRestCommand("/v2/players/ban", PlayerBanV2, RestPermissions.restban, RestPermissions.restmanagebans));
@ -166,28 +162,6 @@ namespace TShockAPI
#region RestServerMethods
[Description("Executes a remote command on the server, and returns the output of the command.")]
[RouteAttribute("/v2/server/rawcmd")]
[Permission(RestPermissions.restrawcommand)]
[Noun("cmd", true, "The command and arguments to execute.", typeof(String))]
[Token]
private object ServerCommand(RestRequestArgs args)
{
if (string.IsNullOrWhiteSpace(args.Parameters["cmd"]))
return RestMissingParam("cmd");
Group restPlayerGroup;
// TODO: Get rid of this when the old REST permission model is removed.
if (TShock.Config.RestUseNewPermissionModel)
restPlayerGroup = TShock.Groups.GetGroupByName(args.TokenData.UserGroupName);
else
restPlayerGroup = new SuperAdminGroup();
TSRestPlayer tr = new TSRestPlayer(args.TokenData.Username, restPlayerGroup);
Commands.HandleCommand(tr, args.Parameters["cmd"]);
return RestResponse(string.Join("\n", tr.GetCommandOutput()));
}
[Description("Executes a remote command on the server, and returns the output of the command.")]
[RouteAttribute("/v3/server/rawcmd")]
[Permission(RestPermissions.restrawcommand)]
@ -198,12 +172,7 @@ namespace TShockAPI
if (string.IsNullOrWhiteSpace(args.Parameters["cmd"]))
return RestMissingParam("cmd");
Group restPlayerGroup;
// TODO: Get rid of this when the old REST permission model is removed.
if (TShock.Config.RestUseNewPermissionModel)
restPlayerGroup = TShock.Groups.GetGroupByName(args.TokenData.UserGroupName);
else
restPlayerGroup = new SuperAdminGroup();
Group restPlayerGroup = TShock.Groups.GetGroupByName(args.TokenData.UserGroupName);
TSRestPlayer tr = new TSRestPlayer(args.TokenData.Username, restPlayerGroup);
Commands.HandleCommand(tr, args.Parameters["cmd"]);
@ -305,21 +274,6 @@ namespace TShockAPI
};
}
[Description("Returns the current status of the server.")]
[Route("/status")]
[Token]
private object ServerStatus(RestRequestArgs args)
{
var activeplayers = Main.player.Where(p => null != p && p.active).ToList();
return new RestObject()
{
{"name", TShock.Config.ServerName},
{"port", Convert.ToString(Netplay.ListenPort)},
{"playercount", Convert.ToString(activeplayers.Count())},
{"players", string.Join(", ", activeplayers.Select(p => p.name))},
};
}
[Description("Get a list of information about the current TShock server.")]
[Route("/v2/server/status")]
[Token]
@ -791,32 +745,6 @@ namespace TShockAPI
return new RestObject() { { "players", playerList } };
}
[Description("Get information for a user.")]
[Route("/v2/players/read")]
[Permission(RestPermissions.restuserinfo)]
[Noun("player", true, "The player to lookup", typeof(String))]
[Token]
private object PlayerReadV2(RestRequestArgs args)
{
var ret = PlayerFind(args.Parameters);
if (ret is RestObject)
return ret;
TSPlayer player = (TSPlayer)ret;
var activeItems = player.TPlayer.inventory.Where(p => p.active).ToList();
return new RestObject()
{
{"nickname", player.Name},
{"username", null == player.User ? "" : player.User.Name},
{"ip", player.IP},
{"group", player.Group.Name},
{"registered", null == player.User ? "" : player.User.Registered},
{"position", player.TileX + "," + player.TileY},
{"inventory", string.Join(", ", activeItems.Select(p => (p.name + ":" + p.stack)))},
{"buffs", string.Join(", ", player.TPlayer.buffType)}
};
}
[Description("Get information for a user.")]
[Route("/v3/players/read")]
[Permission(RestPermissions.restuserinfo)]

View file

@ -44,12 +44,12 @@ namespace Rests
{
Tokens = new Dictionary<string, TokenData>();
AppTokens = new Dictionary<string, TokenData>();
Register(new RestCommand("/v2/token/create", NewTokenV2) { DoLog = false });
Register(new SecureRestCommand("/token/destroy/{token}", DestroyToken));
Register(new SecureRestCommand("/v3/token/destroy/all", DestroyAllTokens, RestPermissions.restmanage));
foreach (KeyValuePair<string, TokenData> t in TShockAPI.TShock.RESTStartupTokens)
foreach (KeyValuePair<string, TokenData> t in TShock.RESTStartupTokens)
{
AppTokens.Add(t.Key, t.Value);
}
@ -58,29 +58,6 @@ namespace Rests
{
AppTokens.Add(t.Key, t.Value);
}
// TODO: Get rid of this when the old REST permission model is removed.
if (TShock.Config.RestApiEnabled && !TShock.Config.RestUseNewPermissionModel)
{
string warningMessage = string.Concat(
"You're using the old REST permission model which is highly vulnerable in matter of security. ",
"The old model will be removed with the next maintenance release of TShock. In order to switch to the new model, ",
"change the config setting \"RestUseNewPermissionModel\" to true."
);
TShock.Log.Warn(warningMessage);
Console.ForegroundColor = ConsoleColor.Red;
Console.WriteLine(warningMessage);
Console.ForegroundColor = ConsoleColor.Gray;
}
else if (TShock.Config.RestApiEnabled)
{
string warningMessage = string.Concat(
"You're using the new more secure REST permission model which can lead to compatibility problems ",
"with existing REST services. If compatibility problems occur, you can switch back to the unsecure permission ",
"model by changing the config setting \"RestUseNewPermissionModel\" to false, which is not recommended."
);
TShock.Log.ConsoleInfo(warningMessage);
}
}
private void AddTokenToBucket(string ip)
@ -206,23 +183,19 @@ namespace Rests
return new RestObject("403")
{ Error = "Not authorized. The specified API endpoint requires a token, but the provided token was not valid." };
// TODO: Get rid of this when the old REST permission model is removed.
if (TShock.Config.RestUseNewPermissionModel)
Group userGroup = TShock.Groups.GetGroupByName(tokenData.UserGroupName);
if (userGroup == null)
{
Group userGroup = TShock.Groups.GetGroupByName(tokenData.UserGroupName);
if (userGroup == null)
{
Tokens.Remove(token);
Tokens.Remove(token);
return new RestObject("403")
{ Error = "Not authorized. The provided token became invalid due to group changes, please create a new token." };
}
return new RestObject("403")
{ Error = "Not authorized. The provided token became invalid due to group changes, please create a new token." };
}
if (secureCmd.Permissions.Length > 0 && secureCmd.Permissions.All(perm => !userGroup.HasPermission(perm)))
{
return new RestObject("403")
{ Error = string.Format("Not authorized. User \"{0}\" has no access to use the specified API endpoint.", tokenData.Username) };
}
if (secureCmd.Permissions.Length > 0 && secureCmd.Permissions.All(perm => !userGroup.HasPermission(perm)))
{
return new RestObject("403")
{ Error = string.Format("Not authorized. User \"{0}\" has no access to use the specified API endpoint.", tokenData.Username) };
}
object result = secureCmd.Execute(verbs, parms, tokenData, request, context);