Implemented RestObject to enforce status/error keys.

This commit is contained in:
high 2011-09-05 13:59:07 -04:00
parent c97ff36b73
commit 866a4c9932
3 changed files with 106 additions and 22 deletions

View file

@ -52,10 +52,15 @@ namespace TShockAPI
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);
}
@ -65,6 +70,7 @@ namespace TShockAPI
var obj = ProcessRequest(sender, e);
if (obj == null)
throw new NullReferenceException("obj");
var str = JsonConvert.SerializeObject(obj, Formatting.Indented);
e.Response.Connection.Type = ConnectionType.Close;
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 string Name { get; protected set; }

View file

@ -7,7 +7,13 @@ using HttpServer;
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 Dictionary<string, object> Tokens { get; protected set; }
@ -39,26 +45,17 @@ namespace TShockAPI
var user = verbs["username"];
var pass = verbs["password"];
if (Verify != null && !Verify(user, pass))
return new Dictionary<string, string> { { "status", "401" } , { "error", "Invalid username/password combination provided. Please re-submit your query with a correct pair." } };
RestObject obj = null;
if (Verify != null)
obj = Verify(user, pass);
var userAccount = TShock.Users.GetUserByName(user);
if (userAccount == null)
{
return new Dictionary<string, string> { { "status", "401" }, { "error", "Invalid username/password combination provided. Please re-submit your query with a correct pair." } };
}
if (obj == null)
obj = new RestObject("401", "Invalid username/password combination provided. Please re-submit your query with a correct pair.");
if (Tools.HashPassword(pass).ToUpper() != userAccount.Password.ToUpper())
{
return new Dictionary<string, string> { { "status", "401" }, { "error", "Invalid username/password combination provided. Please re-submit your query with a correct pair." } };
}
if (obj.Error != null)
return obj;
if (!Tools.GetGroup(userAccount.Group).HasPermission("api") && userAccount.Group != "superadmin")
{
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;
string hash;
var rand = new Random();
var randbytes = new byte[20];
do
@ -69,7 +66,8 @@ namespace TShockAPI
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)

View file

@ -69,7 +69,7 @@ namespace TShockAPI
public static bool OverridePort;
public static PacketBufferer PacketBuffer;
public static MaxMind.GeoIPCountry Geo;
public static Rest RestApi;
public static SecureRest RestApi;
public static RestManager RestManager;
/// <summary>
@ -177,6 +177,7 @@ namespace TShockAPI
Itembans = new ItemManager(DB);
RememberedPos = new RemeberedPosManager(DB);
RestApi = new SecureRest(IPAddress.Any, 8080);
RestApi.Verify += RestApi_Verify;
RestManager = new RestManager(RestApi);
RestManager.RegisterRestfulCommands();
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()
{
GameHooks.PostInitialize -= OnPostInit;