Line ending normalization to CRLF (Windows)
This commit is contained in:
parent
f82bff1b17
commit
9470e20423
16 changed files with 1859 additions and 1854 deletions
|
|
@ -36,13 +36,13 @@ namespace Rests
|
|||
/// <param name="parameters">Parameters in the url</param>
|
||||
/// <param name="verbs">{x} in urltemplate</param>
|
||||
/// <returns>Response object or null to not handle request</returns>
|
||||
public delegate object RestCommandD(RestVerbs verbs, IParameterCollection parameters);
|
||||
|
||||
public delegate object RestCommandD(RestVerbs verbs, IParameterCollection parameters);
|
||||
|
||||
/// <summary>
|
||||
/// Secure Rest command delegate including token data.
|
||||
/// </summary>
|
||||
/// <param name="parameters">Parameters in the url</param>
|
||||
/// <param name="verbs">{x} in urltemplate</param>
|
||||
/// <param name="verbs">{x} in urltemplate</param>
|
||||
/// <param name="tokenData">The data of stored for the provided token.</param>
|
||||
/// <returns>Response object or null to not handle request</returns>
|
||||
public delegate object SecureRestCommandD(RestVerbs verbs, IParameterCollection parameters, SecureRest.TokenData tokenData);
|
||||
|
|
@ -189,32 +189,32 @@ namespace Rests
|
|||
|
||||
protected virtual object ExecuteCommand(RestCommand cmd, RestVerbs verbs, IParameterCollection parms)
|
||||
{
|
||||
object result = cmd.Execute(verbs, parms);
|
||||
if (cmd.DoLog)
|
||||
Log.ConsoleInfo("Anonymous requested REST endpoint: " + BuildRequestUri(cmd, verbs, parms, false));
|
||||
|
||||
object result = cmd.Execute(verbs, parms);
|
||||
if (cmd.DoLog)
|
||||
Log.ConsoleInfo("Anonymous requested REST endpoint: " + BuildRequestUri(cmd, verbs, parms, false));
|
||||
|
||||
return result;
|
||||
}
|
||||
|
||||
protected virtual string BuildRequestUri(
|
||||
RestCommand cmd, RestVerbs verbs, IParameterCollection parms, bool includeToken = true
|
||||
) {
|
||||
StringBuilder requestBuilder = new StringBuilder(cmd.UriTemplate);
|
||||
char separator = '?';
|
||||
foreach (IParameter paramImpl in parms)
|
||||
{
|
||||
Parameter param = (paramImpl as Parameter);
|
||||
if (param == null || (!includeToken && param.Name.Equals("token", StringComparison.InvariantCultureIgnoreCase)))
|
||||
continue;
|
||||
|
||||
requestBuilder.Append(separator);
|
||||
requestBuilder.Append(param.Name);
|
||||
requestBuilder.Append('=');
|
||||
requestBuilder.Append(param.Value);
|
||||
separator = '&';
|
||||
}
|
||||
|
||||
return requestBuilder.ToString();
|
||||
}
|
||||
|
||||
protected virtual string BuildRequestUri(
|
||||
RestCommand cmd, RestVerbs verbs, IParameterCollection parms, bool includeToken = true
|
||||
) {
|
||||
StringBuilder requestBuilder = new StringBuilder(cmd.UriTemplate);
|
||||
char separator = '?';
|
||||
foreach (IParameter paramImpl in parms)
|
||||
{
|
||||
Parameter param = (paramImpl as Parameter);
|
||||
if (param == null || (!includeToken && param.Name.Equals("token", StringComparison.InvariantCultureIgnoreCase)))
|
||||
continue;
|
||||
|
||||
requestBuilder.Append(separator);
|
||||
requestBuilder.Append(param.Name);
|
||||
requestBuilder.Append('=');
|
||||
requestBuilder.Append(param.Value);
|
||||
separator = '&';
|
||||
}
|
||||
|
||||
return requestBuilder.ToString();
|
||||
}
|
||||
|
||||
#region Dispose
|
||||
|
|
|
|||
|
|
@ -16,9 +16,9 @@ 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.Linq;
|
||||
using System.Text.RegularExpressions;
|
||||
using HttpServer;
|
||||
|
||||
using System.Text.RegularExpressions;
|
||||
using HttpServer;
|
||||
|
||||
namespace Rests
|
||||
{
|
||||
public class RestCommand
|
||||
|
|
@ -27,10 +27,10 @@ namespace Rests
|
|||
public string UriTemplate { get; protected set; }
|
||||
public string UriVerbMatch { get; protected set; }
|
||||
public string[] UriVerbs { get; protected set; }
|
||||
public virtual bool RequiresToken { get { return false; } }
|
||||
public virtual bool RequiresToken { get { return false; } }
|
||||
public bool DoLog { get; set; }
|
||||
|
||||
private RestCommandD callback;
|
||||
|
||||
private RestCommandD callback;
|
||||
|
||||
/// <summary>
|
||||
///
|
||||
|
|
@ -45,7 +45,7 @@ namespace Rests
|
|||
UriVerbMatch = string.Format("^{0}$", string.Join("([^/]*)", Regex.Split(uritemplate, "\\{[^\\{\\}]*\\}")));
|
||||
var matches = Regex.Matches(uritemplate, "\\{([^\\{\\}]*)\\}");
|
||||
UriVerbs = (from Match match in matches select match.Groups[1].Value).ToArray();
|
||||
this.callback = callback;
|
||||
this.callback = callback;
|
||||
DoLog = true;
|
||||
}
|
||||
|
||||
|
|
@ -62,44 +62,44 @@ namespace Rests
|
|||
public bool HasVerbs
|
||||
{
|
||||
get { return UriVerbs.Length > 0; }
|
||||
}
|
||||
|
||||
public virtual object Execute(RestVerbs verbs, IParameterCollection parameters)
|
||||
{
|
||||
return callback(verbs, parameters);
|
||||
}
|
||||
}
|
||||
|
||||
public class SecureRestCommand: RestCommand
|
||||
{
|
||||
public override bool RequiresToken { get { return true; } }
|
||||
public string[] Permissions { get; set; }
|
||||
|
||||
private SecureRestCommandD callback;
|
||||
|
||||
public SecureRestCommand(string name, string uritemplate, SecureRestCommandD callback, params string[] permissions)
|
||||
|
||||
public virtual object Execute(RestVerbs verbs, IParameterCollection parameters)
|
||||
{
|
||||
return callback(verbs, parameters);
|
||||
}
|
||||
}
|
||||
|
||||
public class SecureRestCommand: RestCommand
|
||||
{
|
||||
public override bool RequiresToken { get { return true; } }
|
||||
public string[] Permissions { get; set; }
|
||||
|
||||
private SecureRestCommandD callback;
|
||||
|
||||
public SecureRestCommand(string name, string uritemplate, SecureRestCommandD callback, params string[] permissions)
|
||||
: base(name, uritemplate, null)
|
||||
{
|
||||
this.callback = callback;
|
||||
{
|
||||
this.callback = callback;
|
||||
Permissions = permissions;
|
||||
}
|
||||
|
||||
public SecureRestCommand(string uritemplate, SecureRestCommandD callback, params string[] permissions)
|
||||
: this(string.Empty, uritemplate, callback, permissions)
|
||||
{
|
||||
}
|
||||
|
||||
public override object Execute(RestVerbs verbs, IParameterCollection parameters)
|
||||
{
|
||||
return new RestObject("401") { Error = "Not authorized. The specified API endpoint requires a token." };
|
||||
}
|
||||
|
||||
public object Execute(RestVerbs verbs, IParameterCollection parameters, SecureRest.TokenData tokenData)
|
||||
{
|
||||
if (tokenData.Equals(SecureRest.TokenData.None))
|
||||
return new RestObject("401") { Error = "Not authorized. The specified API endpoint requires a token." };
|
||||
|
||||
return callback(verbs, parameters, tokenData);
|
||||
}
|
||||
}
|
||||
|
||||
public override object Execute(RestVerbs verbs, IParameterCollection parameters)
|
||||
{
|
||||
return new RestObject("401") { Error = "Not authorized. The specified API endpoint requires a token." };
|
||||
}
|
||||
|
||||
public object Execute(RestVerbs verbs, IParameterCollection parameters, SecureRest.TokenData tokenData)
|
||||
{
|
||||
if (tokenData.Equals(SecureRest.TokenData.None))
|
||||
return new RestObject("401") { Error = "Not authorized. The specified API endpoint requires a token." };
|
||||
|
||||
return callback(verbs, parameters, tokenData);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
@ -17,8 +17,8 @@ along with this program. If not, see <http://www.gnu.org/licenses/>.
|
|||
*/
|
||||
using System;
|
||||
using System.Collections;
|
||||
using System.Collections.Generic;
|
||||
using System.IO;
|
||||
using System.Collections.Generic;
|
||||
using System.IO;
|
||||
using System.Linq;
|
||||
using HttpServer;
|
||||
using Rests;
|
||||
|
|
@ -38,27 +38,27 @@ namespace TShockAPI
|
|||
|
||||
public void RegisterRestfulCommands()
|
||||
{
|
||||
// Server Commands
|
||||
if (TShock.Config.EnableTokenEndpointAuthentication)
|
||||
{
|
||||
// Server Commands
|
||||
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 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, b) => this.ServerStatusV2(a, b, SecureRest.TokenData.None)));
|
||||
Rest.Register(new RestCommand("/status", (a, b) => this.ServerStatusV2(a, b, SecureRest.TokenData.None)));
|
||||
Rest.Register(new RestCommand("/v3/server/motd", (a, b) => this.ServerMotd(a, b, SecureRest.TokenData.None)));
|
||||
Rest.Register(new RestCommand("/v3/server/rules", (a, b) => this.ServerRules(a, b, SecureRest.TokenData.None)));
|
||||
}
|
||||
Rest.Register(new RestCommand("/status", (a, b) => this.ServerStatusV2(a, b, SecureRest.TokenData.None)));
|
||||
Rest.Register(new RestCommand("/v3/server/motd", (a, b) => this.ServerMotd(a, b, SecureRest.TokenData.None)));
|
||||
Rest.Register(new RestCommand("/v3/server/rules", (a, b) => this.ServerRules(a, b, SecureRest.TokenData.None)));
|
||||
}
|
||||
|
||||
Rest.Register(new SecureRestCommand("/v2/server/broadcast", ServerBroadcast));
|
||||
Rest.Register(new SecureRestCommand("/v3/server/reload", ServerReload, RestPermissions.restcfg));
|
||||
Rest.Register(new SecureRestCommand("/v2/server/off", ServerOff, RestPermissions.restmaintenance));
|
||||
Rest.Register(new SecureRestCommand("/v2/server/broadcast", ServerBroadcast));
|
||||
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("/v2/server/rawcmd", ServerCommand, RestPermissions.restrawcommand));
|
||||
Rest.Register(new SecureRestCommand("/v3/server/rawcmd", ServerCommandV3, RestPermissions.restrawcommand));
|
||||
Rest.Register(new SecureRestCommand("/tokentest", ServerTokenTest));
|
||||
|
||||
|
|
@ -107,35 +107,35 @@ namespace TShockAPI
|
|||
private object ServerCommand(RestVerbs verbs, IParameterCollection parameters, SecureRest.TokenData tokenData)
|
||||
{
|
||||
if (string.IsNullOrWhiteSpace(parameters["cmd"]))
|
||||
return RestMissingParam("cmd");
|
||||
|
||||
Group restPlayerGroup;
|
||||
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(tokenData.UserGroupName);
|
||||
else
|
||||
restPlayerGroup = new SuperAdminGroup();
|
||||
if (TShock.Config.RestUseNewPermissionModel)
|
||||
restPlayerGroup = TShock.Groups.GetGroupByName(tokenData.UserGroupName);
|
||||
else
|
||||
restPlayerGroup = new SuperAdminGroup();
|
||||
|
||||
TSRestPlayer tr = new TSRestPlayer(tokenData.Username, restPlayerGroup);
|
||||
Commands.HandleCommand(tr, parameters["cmd"]);
|
||||
return RestResponse(string.Join("\n", tr.GetCommandOutput()));
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
private object ServerCommandV3(RestVerbs verbs, IParameterCollection parameters, SecureRest.TokenData tokenData)
|
||||
{
|
||||
if (string.IsNullOrWhiteSpace(parameters["cmd"]))
|
||||
return RestMissingParam("cmd");
|
||||
return RestMissingParam("cmd");
|
||||
|
||||
Group restPlayerGroup;
|
||||
Group restPlayerGroup;
|
||||
// TODO: Get rid of this when the old REST permission model is removed.
|
||||
if (TShock.Config.RestUseNewPermissionModel)
|
||||
restPlayerGroup = TShock.Groups.GetGroupByName(tokenData.UserGroupName);
|
||||
else
|
||||
restPlayerGroup = new SuperAdminGroup();
|
||||
|
||||
if (TShock.Config.RestUseNewPermissionModel)
|
||||
restPlayerGroup = TShock.Groups.GetGroupByName(tokenData.UserGroupName);
|
||||
else
|
||||
restPlayerGroup = new SuperAdminGroup();
|
||||
|
||||
TSRestPlayer tr = new TSRestPlayer(tokenData.Username, restPlayerGroup);
|
||||
Commands.HandleCommand(tr, parameters["cmd"]);
|
||||
return new RestObject()
|
||||
return new RestObject()
|
||||
{
|
||||
{"response", tr.GetCommandOutput()}
|
||||
};
|
||||
|
|
@ -151,8 +151,8 @@ namespace TShockAPI
|
|||
TShock.Utils.StopServer(!GetBool(parameters["nosave"], false), reason);
|
||||
|
||||
return RestResponse("The server is shutting down");
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
private object ServerRestart(RestVerbs verbs, IParameterCollection parameters, SecureRest.TokenData tokenData)
|
||||
{
|
||||
if (!GetBool(parameters["confirm"], false))
|
||||
|
|
@ -163,10 +163,10 @@ namespace TShockAPI
|
|||
TShock.Utils.RestartServer(!GetBool(parameters["nosave"], false), reason);
|
||||
|
||||
return RestResponse("The server is shutting down and will attempt to restart");
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
private object ServerReload(RestVerbs verbs, IParameterCollection parameters, SecureRest.TokenData tokenData)
|
||||
{
|
||||
{
|
||||
TShock.Utils.Reload(new TSRestPlayer(tokenData.Username, TShock.Groups.GetGroupByName(tokenData.UserGroupName)));
|
||||
|
||||
return RestResponse("Configuration, permissions, and regions reload complete. Some changes may require a server restart.");
|
||||
|
|
@ -179,29 +179,29 @@ namespace TShockAPI
|
|||
return RestMissingParam("msg");
|
||||
TShock.Utils.Broadcast(msg);
|
||||
return RestResponse("The message was broadcasted successfully");
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
private object ServerMotd(RestVerbs verbs, IParameterCollection parameters, SecureRest.TokenData tokenData)
|
||||
{
|
||||
string motdFilePath = Path.Combine(TShock.SavePath, "motd.txt");
|
||||
if (!File.Exists(motdFilePath))
|
||||
return this.RestError("The motd.txt was not found.", "500");
|
||||
{
|
||||
string motdFilePath = Path.Combine(TShock.SavePath, "motd.txt");
|
||||
if (!File.Exists(motdFilePath))
|
||||
return this.RestError("The motd.txt was not found.", "500");
|
||||
|
||||
return new RestObject()
|
||||
{
|
||||
{"motd", File.ReadAllLines(motdFilePath)}
|
||||
return new RestObject()
|
||||
{
|
||||
{"motd", File.ReadAllLines(motdFilePath)}
|
||||
};
|
||||
}
|
||||
|
||||
private object ServerRules(RestVerbs verbs, IParameterCollection parameters, SecureRest.TokenData tokenData)
|
||||
{
|
||||
string rulesFilePath = Path.Combine(TShock.SavePath, "rules.txt");
|
||||
if (!File.Exists(rulesFilePath))
|
||||
return this.RestError("The rules.txt was not found.", "500");
|
||||
}
|
||||
|
||||
return new RestObject()
|
||||
{
|
||||
{"rules", File.ReadAllLines(rulesFilePath)}
|
||||
private object ServerRules(RestVerbs verbs, IParameterCollection parameters, SecureRest.TokenData tokenData)
|
||||
{
|
||||
string rulesFilePath = Path.Combine(TShock.SavePath, "rules.txt");
|
||||
if (!File.Exists(rulesFilePath))
|
||||
return this.RestError("The rules.txt was not found.", "500");
|
||||
|
||||
return new RestObject()
|
||||
{
|
||||
{"rules", File.ReadAllLines(rulesFilePath)}
|
||||
};
|
||||
}
|
||||
|
||||
|
|
@ -225,8 +225,8 @@ namespace TShockAPI
|
|||
{"port", TShock.Config.ServerPort},
|
||||
{"playercount", Main.player.Where(p => null != p && p.active).Count()},
|
||||
{"maxplayers", TShock.Config.MaxSlots},
|
||||
{"world", Main.worldName},
|
||||
{"uptime", (DateTime.Now - System.Diagnostics.Process.GetCurrentProcess().StartTime).ToString(@"d'.'hh':'mm':'ss")},
|
||||
{"world", Main.worldName},
|
||||
{"uptime", (DateTime.Now - System.Diagnostics.Process.GetCurrentProcess().StartTime).ToString(@"d'.'hh':'mm':'ss")},
|
||||
{"serverpassword", !string.IsNullOrEmpty(TShock.Config.ServerPassword)}
|
||||
};
|
||||
|
||||
|
|
@ -256,7 +256,7 @@ namespace TShockAPI
|
|||
rules.Add("HardcoreOnly", TShock.Config.HardcoreOnly);
|
||||
rules.Add("PvPMode", TShock.Config.PvPMode);
|
||||
rules.Add("SpawnProtection", TShock.Config.SpawnProtection);
|
||||
rules.Add("SpawnProtectionRadius", TShock.Config.SpawnProtectionRadius);
|
||||
rules.Add("SpawnProtectionRadius", TShock.Config.SpawnProtectionRadius);
|
||||
rules.Add("ServerSideInventory", TShock.Config.ServerSideInventory);
|
||||
|
||||
ret.Add("rules", rules);
|
||||
|
|
@ -265,10 +265,10 @@ namespace TShockAPI
|
|||
}
|
||||
|
||||
private object ServerTokenTest(RestVerbs verbs, IParameterCollection parameters, SecureRest.TokenData tokenData)
|
||||
{
|
||||
return new RestObject()
|
||||
{
|
||||
return new RestObject()
|
||||
{
|
||||
{"response", "Token is valid and was passed through correctly."},
|
||||
{"response", "Token is valid and was passed through correctly."},
|
||||
{"associateduser", tokenData.Username}
|
||||
};
|
||||
}
|
||||
|
|
|
|||
|
|
@ -14,80 +14,80 @@ GNU General Public License for more details.
|
|||
|
||||
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;
|
||||
using System.ComponentModel;
|
||||
using System.Linq;
|
||||
|
||||
namespace Rests
|
||||
{
|
||||
public static class RestPermissions
|
||||
{
|
||||
*/
|
||||
using System;
|
||||
using System.ComponentModel;
|
||||
using System.Linq;
|
||||
|
||||
namespace Rests
|
||||
{
|
||||
public static class RestPermissions
|
||||
{
|
||||
[Description("User can create REST tokens.")]
|
||||
public static readonly string restapi;
|
||||
|
||||
public static readonly string restapi;
|
||||
|
||||
[Description("User or REST user can destroy all REST tokens.")]
|
||||
public static readonly string restmanage;
|
||||
|
||||
|
||||
[Description("REST user can turn off / restart the server.")]
|
||||
public static readonly string restmaintenance;
|
||||
|
||||
[Description("REST user can reload configurations, save the world and set auto save settings.")]
|
||||
public static readonly string restcfg;
|
||||
|
||||
|
||||
[Description("REST user can list and get detailed information about users.")]
|
||||
public static readonly string restviewusers;
|
||||
|
||||
[Description("REST user can alter users.")]
|
||||
public static readonly string restmanageusers;
|
||||
|
||||
[Description("REST user can list and get detailed information about bans.")]
|
||||
public static readonly string restviewbans;
|
||||
|
||||
[Description("REST user can alter bans.")]
|
||||
public static readonly string restmanagebans;
|
||||
|
||||
[Description("REST user can list and get detailed information about groups.")]
|
||||
public static readonly string restviewgroups;
|
||||
|
||||
[Description("REST user can alter groups.")]
|
||||
public static readonly string restmanagegroups;
|
||||
|
||||
|
||||
[Description("REST user can get user information.")]
|
||||
public static readonly string restuserinfo;
|
||||
|
||||
[Description("REST user can kick players.")]
|
||||
public static readonly string restkick;
|
||||
|
||||
[Description("REST user can ban players.")]
|
||||
public static readonly string restban;
|
||||
|
||||
[Description("REST user can mute and unmute players.")]
|
||||
public static readonly string restmute;
|
||||
|
||||
[Description("REST user can kill players.")]
|
||||
public static readonly string restkill;
|
||||
|
||||
|
||||
[Description("REST user can drop meteors or change bloodmoon.")]
|
||||
public static readonly string restcauseevents;
|
||||
|
||||
[Description("REST user can butcher npcs.")]
|
||||
public static readonly string restbutcher;
|
||||
|
||||
|
||||
[Description("REST user can run raw TShock commands (the raw command permissions are also checked though).")]
|
||||
public static readonly string restrawcommand;
|
||||
|
||||
public static readonly string restmanage;
|
||||
|
||||
|
||||
[Description("REST user can turn off / restart the server.")]
|
||||
public static readonly string restmaintenance;
|
||||
|
||||
[Description("REST user can reload configurations, save the world and set auto save settings.")]
|
||||
public static readonly string restcfg;
|
||||
|
||||
|
||||
[Description("REST user can list and get detailed information about users.")]
|
||||
public static readonly string restviewusers;
|
||||
|
||||
[Description("REST user can alter users.")]
|
||||
public static readonly string restmanageusers;
|
||||
|
||||
[Description("REST user can list and get detailed information about bans.")]
|
||||
public static readonly string restviewbans;
|
||||
|
||||
[Description("REST user can alter bans.")]
|
||||
public static readonly string restmanagebans;
|
||||
|
||||
[Description("REST user can list and get detailed information about groups.")]
|
||||
public static readonly string restviewgroups;
|
||||
|
||||
[Description("REST user can alter groups.")]
|
||||
public static readonly string restmanagegroups;
|
||||
|
||||
|
||||
[Description("REST user can get user information.")]
|
||||
public static readonly string restuserinfo;
|
||||
|
||||
[Description("REST user can kick players.")]
|
||||
public static readonly string restkick;
|
||||
|
||||
[Description("REST user can ban players.")]
|
||||
public static readonly string restban;
|
||||
|
||||
[Description("REST user can mute and unmute players.")]
|
||||
public static readonly string restmute;
|
||||
|
||||
[Description("REST user can kill players.")]
|
||||
public static readonly string restkill;
|
||||
|
||||
|
||||
[Description("REST user can drop meteors or change bloodmoon.")]
|
||||
public static readonly string restcauseevents;
|
||||
|
||||
[Description("REST user can butcher npcs.")]
|
||||
public static readonly string restbutcher;
|
||||
|
||||
|
||||
[Description("REST user can run raw TShock commands (the raw command permissions are also checked though).")]
|
||||
public static readonly string restrawcommand;
|
||||
|
||||
static RestPermissions()
|
||||
{
|
||||
foreach (var field in typeof (RestPermissions).GetFields())
|
||||
{
|
||||
field.SetValue(null, field.Name);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -18,35 +18,35 @@ along with this program. If not, see <http://www.gnu.org/licenses/>.
|
|||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Linq;
|
||||
using System.Net;
|
||||
using System.Text;
|
||||
using HttpServer;
|
||||
using TShockAPI;
|
||||
using TShockAPI.DB;
|
||||
|
||||
using System.Net;
|
||||
using System.Text;
|
||||
using HttpServer;
|
||||
using TShockAPI;
|
||||
using TShockAPI.DB;
|
||||
|
||||
namespace Rests
|
||||
{
|
||||
public class SecureRest : Rest
|
||||
{
|
||||
public struct TokenData
|
||||
{
|
||||
public static readonly TokenData None = default(TokenData);
|
||||
|
||||
public string Username { get; set; }
|
||||
public string UserGroupName { get; set; }
|
||||
}
|
||||
{
|
||||
public struct TokenData
|
||||
{
|
||||
public static readonly TokenData None = default(TokenData);
|
||||
|
||||
public string Username { get; set; }
|
||||
public string UserGroupName { get; set; }
|
||||
}
|
||||
|
||||
public Dictionary<string,TokenData> Tokens { get; protected set; }
|
||||
|
||||
public SecureRest(IPAddress ip, int port)
|
||||
: base(ip, port)
|
||||
{
|
||||
Tokens = new Dictionary<string, TokenData>();
|
||||
Tokens = new Dictionary<string, TokenData>();
|
||||
|
||||
Register(new RestCommand("/token/create/{username}/{password}", NewToken) { DoLog = false });
|
||||
Register(new RestCommand("/v2/token/create/{password}", NewTokenV2) { DoLog = false });
|
||||
Register(new SecureRestCommand("/token/destroy/{token}", DestroyToken));
|
||||
Register(new SecureRestCommand("/v3/token/destroy/all", DestroyAllTokens, RestPermissions.restmanage));
|
||||
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)
|
||||
{
|
||||
|
|
@ -55,7 +55,7 @@ namespace Rests
|
|||
|
||||
// TODO: Get rid of this when the old REST permission model is removed.
|
||||
if (!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, ",
|
||||
|
|
@ -64,16 +64,16 @@ namespace Rests
|
|||
Log.Warn(warningMessage);
|
||||
Console.ForegroundColor = ConsoleColor.Red;
|
||||
Console.WriteLine(warningMessage);
|
||||
Console.ForegroundColor = ConsoleColor.Gray;
|
||||
Console.ForegroundColor = ConsoleColor.Gray;
|
||||
}
|
||||
else
|
||||
{
|
||||
{
|
||||
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."
|
||||
);
|
||||
Log.ConsoleInfo(warningMessage);
|
||||
Log.ConsoleInfo(warningMessage);
|
||||
}
|
||||
}
|
||||
|
||||
|
|
@ -91,11 +91,11 @@ namespace Rests
|
|||
}
|
||||
return new RestObject()
|
||||
{ Response = "Requested token was successfully destroyed." };
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
private object DestroyAllTokens(RestVerbs verbs, IParameterCollection parameters, SecureRest.TokenData tokenData)
|
||||
{
|
||||
Tokens.Clear();
|
||||
Tokens.Clear();
|
||||
|
||||
return new RestObject()
|
||||
{ Response = "All tokens were successfully destroyed." };
|
||||
|
|
@ -114,13 +114,13 @@ namespace Rests
|
|||
var user = verbs["username"];
|
||||
var pass = verbs["password"];
|
||||
|
||||
RestObject response = this.NewTokenInternal(user, pass);
|
||||
response["deprecated"] = "This endpoint is depracted and will be removed in the future.";
|
||||
RestObject response = this.NewTokenInternal(user, pass);
|
||||
response["deprecated"] = "This endpoint is depracted and will be removed in the future.";
|
||||
return response;
|
||||
}
|
||||
|
||||
private RestObject NewTokenInternal(string username, string password)
|
||||
{
|
||||
|
||||
private RestObject NewTokenInternal(string username, string password)
|
||||
{
|
||||
User userAccount = TShock.Users.GetUserByName(username);
|
||||
if (userAccount == null || !string.IsNullOrWhiteSpace(userAccount.Address))
|
||||
return new RestObject("401")
|
||||
|
|
@ -129,12 +129,12 @@ namespace Rests
|
|||
if (!TShock.Utils.HashPassword(password).Equals(userAccount.Password, StringComparison.InvariantCultureIgnoreCase))
|
||||
return new RestObject("401")
|
||||
{ Error = "Invalid username/password combination provided. Please re-submit your query with a correct pair." };
|
||||
|
||||
|
||||
Group userGroup = TShock.Utils.GetGroup(userAccount.Group);
|
||||
if (!userGroup.HasPermission(RestPermissions.restapi) && userAccount.Group != "superadmin")
|
||||
return new RestObject("403")
|
||||
{ Error = "Although your account was successfully found and identified, your account lacks the permission required to use the API. (restapi)" };
|
||||
|
||||
{ Error = "Although your account was successfully found and identified, your account lacks the permission required to use the API. (restapi)" };
|
||||
|
||||
string tokenHash;
|
||||
var rand = new Random();
|
||||
var randbytes = new byte[32];
|
||||
|
|
@ -145,53 +145,53 @@ namespace Rests
|
|||
} while (Tokens.ContainsKey(tokenHash));
|
||||
|
||||
Tokens.Add(tokenHash, new TokenData { Username = userAccount.Name, UserGroupName = userGroup.Name });
|
||||
|
||||
|
||||
RestObject response = new RestObject() { Response = "Successful login" };
|
||||
response["token"] = tokenHash;
|
||||
return response;
|
||||
return response;
|
||||
}
|
||||
|
||||
protected override object ExecuteCommand(RestCommand cmd, RestVerbs verbs, IParameterCollection parms)
|
||||
{
|
||||
if (!cmd.RequiresToken)
|
||||
if (!cmd.RequiresToken)
|
||||
return base.ExecuteCommand(cmd, verbs, parms);
|
||||
|
||||
var token = parms["token"];
|
||||
if (token == null)
|
||||
return new RestObject("401")
|
||||
{ Error = "Not authorized. The specified API endpoint requires a token." };
|
||||
|
||||
|
||||
SecureRestCommand secureCmd = (SecureRestCommand)cmd;
|
||||
TokenData tokenData;
|
||||
if (!Tokens.TryGetValue(token, out tokenData))
|
||||
return new RestObject("403")
|
||||
{ Error = "Not authorized. The specified API endpoint requires a token, but the provided token was not valid." };
|
||||
|
||||
{ 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)
|
||||
{
|
||||
Tokens.Remove(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) };
|
||||
}
|
||||
}
|
||||
|
||||
object result = secureCmd.Execute(verbs, parms, tokenData);
|
||||
if (cmd.DoLog)
|
||||
TShock.Utils.SendLogs(string.Format(
|
||||
"\"{0}\" requested REST endpoint: {1}", tokenData.Username, this.BuildRequestUri(cmd, verbs, parms, false)),
|
||||
Color.PaleVioletRed);
|
||||
|
||||
return result;
|
||||
if (TShock.Config.RestUseNewPermissionModel) {
|
||||
Group userGroup = TShock.Groups.GetGroupByName(tokenData.UserGroupName);
|
||||
if (userGroup == null)
|
||||
{
|
||||
Tokens.Remove(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) };
|
||||
}
|
||||
}
|
||||
|
||||
object result = secureCmd.Execute(verbs, parms, tokenData);
|
||||
if (cmd.DoLog)
|
||||
TShock.Utils.SendLogs(string.Format(
|
||||
"\"{0}\" requested REST endpoint: {1}", tokenData.Username, this.BuildRequestUri(cmd, verbs, parms, false)),
|
||||
Color.PaleVioletRed);
|
||||
|
||||
return result;
|
||||
}
|
||||
}
|
||||
}
|
||||
Loading…
Add table
Add a link
Reference in a new issue