Implemented RestObject to enforce status/error keys.
This commit is contained in:
parent
c97ff36b73
commit
866a4c9932
3 changed files with 106 additions and 22 deletions
|
|
@ -52,10 +52,15 @@ namespace TShockAPI
|
||||||
|
|
||||||
public void Register(string path, RestCommandD callback)
|
public void Register(string path, RestCommandD callback)
|
||||||
{
|
{
|
||||||
Register(new RestCommand(path, callback));
|
AddCommand(new RestCommand(path, callback));
|
||||||
}
|
}
|
||||||
|
|
||||||
public virtual void Register(RestCommand com)
|
public void Register(RestCommand com)
|
||||||
|
{
|
||||||
|
AddCommand(com);
|
||||||
|
}
|
||||||
|
|
||||||
|
protected void AddCommand(RestCommand com)
|
||||||
{
|
{
|
||||||
commands.Add(com);
|
commands.Add(com);
|
||||||
}
|
}
|
||||||
|
|
@ -65,6 +70,7 @@ namespace TShockAPI
|
||||||
var obj = ProcessRequest(sender, e);
|
var obj = ProcessRequest(sender, e);
|
||||||
if (obj == null)
|
if (obj == null)
|
||||||
throw new NullReferenceException("obj");
|
throw new NullReferenceException("obj");
|
||||||
|
|
||||||
var str = JsonConvert.SerializeObject(obj, Formatting.Indented);
|
var str = JsonConvert.SerializeObject(obj, Formatting.Indented);
|
||||||
e.Response.Connection.Type = ConnectionType.Close;
|
e.Response.Connection.Type = ConnectionType.Close;
|
||||||
e.Response.Body.Write(Encoding.ASCII.GetBytes(str), 0, str.Length);
|
e.Response.Body.Write(Encoding.ASCII.GetBytes(str), 0, str.Length);
|
||||||
|
|
@ -136,6 +142,64 @@ namespace TShockAPI
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public class RestObject : Dictionary<string, string>
|
||||||
|
{
|
||||||
|
public string Status
|
||||||
|
{
|
||||||
|
get { return SafeGet("status"); }
|
||||||
|
set { SafeSet("status", value); }
|
||||||
|
}
|
||||||
|
public string Error
|
||||||
|
{
|
||||||
|
get { return SafeGet("error"); }
|
||||||
|
set { SafeSet("error", value); }
|
||||||
|
}
|
||||||
|
|
||||||
|
public RestObject(string status)
|
||||||
|
{
|
||||||
|
Status = status;
|
||||||
|
}
|
||||||
|
public RestObject(string status, string error)
|
||||||
|
: this(status)
|
||||||
|
{
|
||||||
|
Error = error;
|
||||||
|
}
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Gets value safely.
|
||||||
|
/// </summary>
|
||||||
|
/// <param name="key"></param>
|
||||||
|
/// <returns>Returns null if key does not exist.</returns>
|
||||||
|
public string SafeGet(string key)
|
||||||
|
{
|
||||||
|
string ret;
|
||||||
|
if (TryGetValue(key, out ret))
|
||||||
|
return ret;
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
/// <summary>
|
||||||
|
/// Sets/Adds value safely. If null it will remove.
|
||||||
|
/// </summary>
|
||||||
|
/// <param name="key"></param>
|
||||||
|
/// <param name="value"></param>
|
||||||
|
public void SafeSet(string key, string value)
|
||||||
|
{
|
||||||
|
if (!ContainsKey(key))
|
||||||
|
{
|
||||||
|
if (value == null)
|
||||||
|
return;
|
||||||
|
Add(key, value);
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
if (value != null)
|
||||||
|
this[key] = value;
|
||||||
|
else
|
||||||
|
Remove(key);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
public class RestCommand
|
public class RestCommand
|
||||||
{
|
{
|
||||||
public string Name { get; protected set; }
|
public string Name { get; protected set; }
|
||||||
|
|
|
||||||
|
|
@ -7,7 +7,13 @@ using HttpServer;
|
||||||
|
|
||||||
namespace TShockAPI
|
namespace TShockAPI
|
||||||
{
|
{
|
||||||
public delegate bool VerifyD(string username, string password);
|
/// <summary>
|
||||||
|
///
|
||||||
|
/// </summary>
|
||||||
|
/// <param name="username">Username to verify</param>
|
||||||
|
/// <param name="password">Password to verify</param>
|
||||||
|
/// <returns>Returning a restobject with a null error means a successful verification.</returns>
|
||||||
|
public delegate RestObject VerifyD(string username, string password);
|
||||||
public class SecureRest : Rest
|
public class SecureRest : Rest
|
||||||
{
|
{
|
||||||
public Dictionary<string, object> Tokens { get; protected set; }
|
public Dictionary<string, object> Tokens { get; protected set; }
|
||||||
|
|
@ -39,26 +45,17 @@ namespace TShockAPI
|
||||||
var user = verbs["username"];
|
var user = verbs["username"];
|
||||||
var pass = verbs["password"];
|
var pass = verbs["password"];
|
||||||
|
|
||||||
if (Verify != null && !Verify(user, pass))
|
RestObject obj = null;
|
||||||
return new Dictionary<string, string> { { "status", "401" } , { "error", "Invalid username/password combination provided. Please re-submit your query with a correct pair." } };
|
if (Verify != null)
|
||||||
|
obj = Verify(user, pass);
|
||||||
|
|
||||||
var userAccount = TShock.Users.GetUserByName(user);
|
if (obj == null)
|
||||||
if (userAccount == null)
|
obj = new RestObject("401", "Invalid username/password combination provided. Please re-submit your query with a correct pair.");
|
||||||
{
|
|
||||||
return new Dictionary<string, string> { { "status", "401" }, { "error", "Invalid username/password combination provided. Please re-submit your query with a correct pair." } };
|
|
||||||
}
|
|
||||||
|
|
||||||
if (Tools.HashPassword(pass).ToUpper() != userAccount.Password.ToUpper())
|
if (obj.Error != null)
|
||||||
{
|
return obj;
|
||||||
return new Dictionary<string, string> { { "status", "401" }, { "error", "Invalid username/password combination provided. Please re-submit your query with a correct pair." } };
|
|
||||||
}
|
|
||||||
|
|
||||||
if (!Tools.GetGroup(userAccount.Group).HasPermission("api") && userAccount.Group != "superadmin")
|
string hash;
|
||||||
{
|
|
||||||
return new Dictionary<string, string> { { "status", "403" }, { "error", "Although your account was successfully found and identified, your account lacks the permission required to use the API. (api)" } };
|
|
||||||
}
|
|
||||||
|
|
||||||
string hash = string.Empty;
|
|
||||||
var rand = new Random();
|
var rand = new Random();
|
||||||
var randbytes = new byte[20];
|
var randbytes = new byte[20];
|
||||||
do
|
do
|
||||||
|
|
@ -69,7 +66,8 @@ namespace TShockAPI
|
||||||
|
|
||||||
Tokens.Add(hash, user);
|
Tokens.Add(hash, user);
|
||||||
|
|
||||||
return new Dictionary<string, string> { { "status", "200" } , { "token", hash } }; ;
|
obj.SafeSet("token", hash);
|
||||||
|
return obj;
|
||||||
}
|
}
|
||||||
|
|
||||||
protected override object ExecuteCommand(RestCommand cmd, RestVerbs verbs, IParameterCollection parms)
|
protected override object ExecuteCommand(RestCommand cmd, RestVerbs verbs, IParameterCollection parms)
|
||||||
|
|
|
||||||
|
|
@ -69,7 +69,7 @@ namespace TShockAPI
|
||||||
public static bool OverridePort;
|
public static bool OverridePort;
|
||||||
public static PacketBufferer PacketBuffer;
|
public static PacketBufferer PacketBuffer;
|
||||||
public static MaxMind.GeoIPCountry Geo;
|
public static MaxMind.GeoIPCountry Geo;
|
||||||
public static Rest RestApi;
|
public static SecureRest RestApi;
|
||||||
public static RestManager RestManager;
|
public static RestManager RestManager;
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
|
|
@ -177,6 +177,7 @@ namespace TShockAPI
|
||||||
Itembans = new ItemManager(DB);
|
Itembans = new ItemManager(DB);
|
||||||
RememberedPos = new RemeberedPosManager(DB);
|
RememberedPos = new RemeberedPosManager(DB);
|
||||||
RestApi = new SecureRest(IPAddress.Any, 8080);
|
RestApi = new SecureRest(IPAddress.Any, 8080);
|
||||||
|
RestApi.Verify += RestApi_Verify;
|
||||||
RestManager = new RestManager(RestApi);
|
RestManager = new RestManager(RestApi);
|
||||||
RestManager.RegisterRestfulCommands();
|
RestManager.RegisterRestfulCommands();
|
||||||
if (Config.EnableGeoIP)
|
if (Config.EnableGeoIP)
|
||||||
|
|
@ -216,6 +217,27 @@ namespace TShockAPI
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
RestObject RestApi_Verify(string username, string password)
|
||||||
|
{
|
||||||
|
var userAccount = TShock.Users.GetUserByName(username);
|
||||||
|
if (userAccount == null)
|
||||||
|
{
|
||||||
|
return new RestObject("401", "Invalid username/password combination provided. Please re-submit your query with a correct pair.");
|
||||||
|
}
|
||||||
|
|
||||||
|
if (Tools.HashPassword(password).ToUpper() != userAccount.Password.ToUpper())
|
||||||
|
{
|
||||||
|
return new RestObject("401", "Invalid username/password combination provided. Please re-submit your query with a correct pair.");
|
||||||
|
}
|
||||||
|
|
||||||
|
if (!Tools.GetGroup(userAccount.Group).HasPermission("api") && userAccount.Group != "superadmin")
|
||||||
|
{
|
||||||
|
return new RestObject("403", "Although your account was successfully found and identified, your account lacks the permission required to use the API. (api)");
|
||||||
|
}
|
||||||
|
|
||||||
|
return new RestObject("200"); //Maybe return some user info too?
|
||||||
|
}
|
||||||
|
|
||||||
public override void DeInitialize()
|
public override void DeInitialize()
|
||||||
{
|
{
|
||||||
GameHooks.PostInitialize -= OnPostInit;
|
GameHooks.PostInitialize -= OnPostInit;
|
||||||
|
|
|
||||||
Loading…
Add table
Add a link
Reference in a new issue