scoped tokens support and readme update
This commit is contained in:
parent
b6ada34ed5
commit
9706a94f10
11 changed files with 331 additions and 44 deletions
|
|
@ -57,6 +57,16 @@ namespace BetterSecondBotShared.IO
|
||||||
{
|
{
|
||||||
serializer.Serialize(writer, commandsfile);
|
serializer.Serialize(writer, commandsfile);
|
||||||
}
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
public void WriteJsonTokens(JsonScopedTokens tokensfile, string targetfile)
|
||||||
|
{
|
||||||
|
JsonSerializer serializer = new JsonSerializer();
|
||||||
|
using (StreamWriter sw = new StreamWriter(@"" + root_folder + "" + targetfile))
|
||||||
|
using (JsonWriter writer = new JsonTextWriter(sw) { Formatting = Formatting.Indented })
|
||||||
|
{
|
||||||
|
serializer.Serialize(writer, tokensfile);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
public void makeOld(string targetfile)
|
public void makeOld(string targetfile)
|
||||||
|
|
|
||||||
|
|
@ -3,11 +3,19 @@ using System.Collections.Generic;
|
||||||
using System.Text;
|
using System.Text;
|
||||||
|
|
||||||
namespace BetterSecondBotShared.Json
|
namespace BetterSecondBotShared.Json
|
||||||
{
|
{
|
||||||
|
|
||||||
|
public class JsonScopedTokens
|
||||||
|
{
|
||||||
|
public string[] ScopedTokens { get; set; }
|
||||||
|
}
|
||||||
|
|
||||||
public class JsonCommandsfile
|
public class JsonCommandsfile
|
||||||
{
|
{
|
||||||
public string[] CustomCommands { get; set; }
|
public string[] CustomCommands { get; set; }
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
public class JsonConfig
|
public class JsonConfig
|
||||||
{
|
{
|
||||||
// Basics
|
// Basics
|
||||||
|
|
|
||||||
|
|
@ -53,7 +53,7 @@ namespace BetterSecondBot
|
||||||
*/
|
*/
|
||||||
new Thread(() =>
|
new Thread(() =>
|
||||||
{
|
{
|
||||||
new HttpAsService(Bot, Config);
|
new HttpAsService(Bot, Config, as_docker);
|
||||||
}).Start();
|
}).Start();
|
||||||
}
|
}
|
||||||
if(use_self_keep_alive == true)
|
if(use_self_keep_alive == true)
|
||||||
|
|
|
||||||
|
|
@ -20,7 +20,7 @@ namespace BetterSecondBot.HttpService
|
||||||
[Route(HttpVerbs.Get, "/localchathistory/{token}")]
|
[Route(HttpVerbs.Get, "/localchathistory/{token}")]
|
||||||
public object localchatHistory(string token)
|
public object localchatHistory(string token)
|
||||||
{
|
{
|
||||||
if (tokens.Allow(token, getClientIP()) == true)
|
if (tokens.Allow(token, "chat", "localchathistory", getClientIP()) == true)
|
||||||
{
|
{
|
||||||
return BasicReply(JsonConvert.SerializeObject(bot.getLocalChatHistory()));
|
return BasicReply(JsonConvert.SerializeObject(bot.getLocalChatHistory()));
|
||||||
}
|
}
|
||||||
|
|
@ -33,7 +33,7 @@ namespace BetterSecondBot.HttpService
|
||||||
[Route(HttpVerbs.Post, "/localchatsay/{token}")]
|
[Route(HttpVerbs.Post, "/localchatsay/{token}")]
|
||||||
public object localchatSay(string token, [FormField] string message)
|
public object localchatSay(string token, [FormField] string message)
|
||||||
{
|
{
|
||||||
if (tokens.Allow(token, getClientIP()) == true)
|
if (tokens.Allow(token, "chat", "localchatsay", getClientIP()) == true)
|
||||||
{
|
{
|
||||||
bot.GetCommandsInterface.Call("say", message);
|
bot.GetCommandsInterface.Call("say", message);
|
||||||
return BasicReply(JsonConvert.SerializeObject(bot.getLocalChatHistory()));
|
return BasicReply(JsonConvert.SerializeObject(bot.getLocalChatHistory()));
|
||||||
|
|
|
||||||
|
|
@ -59,7 +59,7 @@ namespace BetterSecondBot.HttpService
|
||||||
[Route(HttpVerbs.Get, "/friends/{token}")]
|
[Route(HttpVerbs.Get, "/friends/{token}")]
|
||||||
public object Friends(string token)
|
public object Friends(string token)
|
||||||
{
|
{
|
||||||
if (tokens.Allow(token, getClientIP()) == true)
|
if (tokens.Allow(token, "core", "friends", getClientIP()) == true)
|
||||||
{
|
{
|
||||||
return BasicReply(bot.getJsonFriendlist());
|
return BasicReply(bot.getJsonFriendlist());
|
||||||
}
|
}
|
||||||
|
|
@ -75,7 +75,7 @@ namespace BetterSecondBot.HttpService
|
||||||
[Route(HttpVerbs.Get, "/walkto/{x}/{y}/{z}/{token}")]
|
[Route(HttpVerbs.Get, "/walkto/{x}/{y}/{z}/{token}")]
|
||||||
public object WalkTo(string x, string y, string z, string token)
|
public object WalkTo(string x, string y, string z, string token)
|
||||||
{
|
{
|
||||||
if (tokens.Allow(token, getClientIP()) == true)
|
if (tokens.Allow(token, "core", "walkto", getClientIP()) == true)
|
||||||
{
|
{
|
||||||
bool status = bot.GetCommandsInterface.Call("AutoPilot", "<"+x+","+y+","+z+">");
|
bool status = bot.GetCommandsInterface.Call("AutoPilot", "<"+x+","+y+","+z+">");
|
||||||
if (status == true)
|
if (status == true)
|
||||||
|
|
@ -94,7 +94,7 @@ namespace BetterSecondBot.HttpService
|
||||||
[Route(HttpVerbs.Get, "/gesture/{gesture}/{token}")]
|
[Route(HttpVerbs.Get, "/gesture/{gesture}/{token}")]
|
||||||
public object Gesture(string gesture, string token)
|
public object Gesture(string gesture, string token)
|
||||||
{
|
{
|
||||||
if (tokens.Allow(token, getClientIP()) == true)
|
if (tokens.Allow(token, "core", "gesture", getClientIP()) == true)
|
||||||
{
|
{
|
||||||
bool status = bot.GetCommandsInterface.Call("PlayGesture", gesture);
|
bool status = bot.GetCommandsInterface.Call("PlayGesture", gesture);
|
||||||
if (status == true)
|
if (status == true)
|
||||||
|
|
@ -116,7 +116,7 @@ namespace BetterSecondBot.HttpService
|
||||||
[Route(HttpVerbs.Get, "/teleport/{region}/{x}/{y}/{z}/{token}")]
|
[Route(HttpVerbs.Get, "/teleport/{region}/{x}/{y}/{z}/{token}")]
|
||||||
public object Teleport(string region,string x, string y, string z, string token)
|
public object Teleport(string region,string x, string y, string z, string token)
|
||||||
{
|
{
|
||||||
if (tokens.Allow(token, getClientIP()) == true)
|
if (tokens.Allow(token, "core", "teleport", getClientIP()) == true)
|
||||||
{
|
{
|
||||||
bool status = bot.GetCommandsInterface.Call("Teleport", ""+region+"/" + x + "/" + y + "/" + z + "");
|
bool status = bot.GetCommandsInterface.Call("Teleport", ""+region+"/" + x + "/" + y + "/" + z + "");
|
||||||
if (status == true)
|
if (status == true)
|
||||||
|
|
@ -135,7 +135,7 @@ namespace BetterSecondBot.HttpService
|
||||||
[Route(HttpVerbs.Get, "/regiontile/{regionname}/{token}")]
|
[Route(HttpVerbs.Get, "/regiontile/{regionname}/{token}")]
|
||||||
public object Regiontile(string regionname, string token)
|
public object Regiontile(string regionname, string token)
|
||||||
{
|
{
|
||||||
if (tokens.Allow(token, getClientIP()) == true)
|
if (tokens.Allow(token, "core", "regiontile", getClientIP()) == true)
|
||||||
{
|
{
|
||||||
if (bot.GetClient.Grid.GetGridRegion(regionname, GridLayerType.Objects, out GridRegion region))
|
if (bot.GetClient.Grid.GetGridRegion(regionname, GridLayerType.Objects, out GridRegion region))
|
||||||
{
|
{
|
||||||
|
|
@ -155,7 +155,7 @@ namespace BetterSecondBot.HttpService
|
||||||
[Route(HttpVerbs.Get, "/nearmewithdetails/{token}")]
|
[Route(HttpVerbs.Get, "/nearmewithdetails/{token}")]
|
||||||
public object NearmeWithDetails(string token)
|
public object NearmeWithDetails(string token)
|
||||||
{
|
{
|
||||||
if (tokens.Allow(token, getClientIP()) == true)
|
if (tokens.Allow(token, "core", "nearmewithdetails", getClientIP()) == true)
|
||||||
{
|
{
|
||||||
if (bot.GetClient.Network.CurrentSim != null)
|
if (bot.GetClient.Network.CurrentSim != null)
|
||||||
{
|
{
|
||||||
|
|
@ -188,7 +188,7 @@ namespace BetterSecondBot.HttpService
|
||||||
[Route(HttpVerbs.Get, "/nearme/{token}")]
|
[Route(HttpVerbs.Get, "/nearme/{token}")]
|
||||||
public object Nearme(string token)
|
public object Nearme(string token)
|
||||||
{
|
{
|
||||||
if (tokens.Allow(token, getClientIP()) == true)
|
if (tokens.Allow(token, "core", "nearme", getClientIP()) == true)
|
||||||
{
|
{
|
||||||
if (bot.GetClient.Network.CurrentSim != null)
|
if (bot.GetClient.Network.CurrentSim != null)
|
||||||
{
|
{
|
||||||
|
|
@ -224,7 +224,7 @@ namespace BetterSecondBot.HttpService
|
||||||
[Route(HttpVerbs.Get, "/logout/{token}")]
|
[Route(HttpVerbs.Get, "/logout/{token}")]
|
||||||
public object Logout(string token)
|
public object Logout(string token)
|
||||||
{
|
{
|
||||||
if (tokens.Allow(token, getClientIP()) == true)
|
if (tokens.Allow(token, "core", "logout", getClientIP()) == true)
|
||||||
{
|
{
|
||||||
return tokens.Expire(token);
|
return tokens.Expire(token);
|
||||||
}
|
}
|
||||||
|
|
@ -238,7 +238,7 @@ namespace BetterSecondBot.HttpService
|
||||||
[Route(HttpVerbs.Get, "/version/{token}")]
|
[Route(HttpVerbs.Get, "/version/{token}")]
|
||||||
public object Version(string token)
|
public object Version(string token)
|
||||||
{
|
{
|
||||||
if (tokens.Allow(token, getClientIP()) == true)
|
if (tokens.Allow(token, "core", "version", getClientIP()) == true)
|
||||||
{
|
{
|
||||||
return BasicReply(bot.MyVersion);
|
return BasicReply(bot.MyVersion);
|
||||||
}
|
}
|
||||||
|
|
@ -250,7 +250,7 @@ namespace BetterSecondBot.HttpService
|
||||||
[Route(HttpVerbs.Get, "/name/{token}")]
|
[Route(HttpVerbs.Get, "/name/{token}")]
|
||||||
public object Name(string token)
|
public object Name(string token)
|
||||||
{
|
{
|
||||||
if (tokens.Allow(token, getClientIP()) == true)
|
if (tokens.Allow(token, "core", "name", getClientIP()) == true)
|
||||||
{
|
{
|
||||||
return BasicReply(bot.GetClient.Self.FirstName + " " + bot.GetClient.Self.LastName);
|
return BasicReply(bot.GetClient.Self.FirstName + " " + bot.GetClient.Self.LastName);
|
||||||
}
|
}
|
||||||
|
|
@ -263,7 +263,7 @@ namespace BetterSecondBot.HttpService
|
||||||
[Route(HttpVerbs.Get, "/regionname/{token}")]
|
[Route(HttpVerbs.Get, "/regionname/{token}")]
|
||||||
public object Regionname(string token)
|
public object Regionname(string token)
|
||||||
{
|
{
|
||||||
if (tokens.Allow(token, getClientIP()) == true)
|
if (tokens.Allow(token, "core", "regionname", getClientIP()) == true)
|
||||||
{
|
{
|
||||||
if(bot.GetClient.Network.CurrentSim != null)
|
if(bot.GetClient.Network.CurrentSim != null)
|
||||||
{
|
{
|
||||||
|
|
@ -280,7 +280,7 @@ namespace BetterSecondBot.HttpService
|
||||||
[Route(HttpVerbs.Get, "/location/{token}")]
|
[Route(HttpVerbs.Get, "/location/{token}")]
|
||||||
public object Location(string token)
|
public object Location(string token)
|
||||||
{
|
{
|
||||||
if (tokens.Allow(token, getClientIP()) == true)
|
if (tokens.Allow(token, "core", "location", getClientIP()) == true)
|
||||||
{
|
{
|
||||||
if (bot.GetClient.Network.CurrentSim != null)
|
if (bot.GetClient.Network.CurrentSim != null)
|
||||||
{
|
{
|
||||||
|
|
@ -302,7 +302,7 @@ namespace BetterSecondBot.HttpService
|
||||||
[Route(HttpVerbs.Post, "/command/{token}")]
|
[Route(HttpVerbs.Post, "/command/{token}")]
|
||||||
public async Task<object> command(string token)
|
public async Task<object> command(string token)
|
||||||
{
|
{
|
||||||
if (tokens.Allow(token, getClientIP()) == true)
|
if (tokens.Allow(token, "core", "command", getClientIP()) == true)
|
||||||
{
|
{
|
||||||
CommandLibCall data = await HttpContext.GetRequestDataAsync<CommandLibCall>();
|
CommandLibCall data = await HttpContext.GetRequestDataAsync<CommandLibCall>();
|
||||||
string compressedArgs = string.Join("~#~", data.Args);
|
string compressedArgs = string.Join("~#~", data.Args);
|
||||||
|
|
|
||||||
|
|
@ -26,7 +26,7 @@ namespace BetterSecondBot.HttpService
|
||||||
[Route(HttpVerbs.Get, "/ismember/{group}/{avatar}/{token}")]
|
[Route(HttpVerbs.Get, "/ismember/{group}/{avatar}/{token}")]
|
||||||
public object ismember(string group,string avatar,string token)
|
public object ismember(string group,string avatar,string token)
|
||||||
{
|
{
|
||||||
if (tokens.Allow(token, getClientIP()) == true)
|
if (tokens.Allow(token, "groups", "ismember", getClientIP()) == true)
|
||||||
{
|
{
|
||||||
if (UUID.TryParse(group, out UUID groupuuid) == true)
|
if (UUID.TryParse(group, out UUID groupuuid) == true)
|
||||||
{
|
{
|
||||||
|
|
@ -62,7 +62,7 @@ namespace BetterSecondBot.HttpService
|
||||||
[Route(HttpVerbs.Get, "/listgroups/{token}")]
|
[Route(HttpVerbs.Get, "/listgroups/{token}")]
|
||||||
public object listgroups(string token)
|
public object listgroups(string token)
|
||||||
{
|
{
|
||||||
if (tokens.Allow(token, getClientIP()) == true)
|
if (tokens.Allow(token, "groups", "listgroups", getClientIP()) == true)
|
||||||
{
|
{
|
||||||
Dictionary<string, string> grouppackage = new Dictionary<string, string>();
|
Dictionary<string, string> grouppackage = new Dictionary<string, string>();
|
||||||
foreach(KeyValuePair<UUID,Group> entry in bot.MyGroups)
|
foreach(KeyValuePair<UUID,Group> entry in bot.MyGroups)
|
||||||
|
|
@ -83,7 +83,7 @@ namespace BetterSecondBot.HttpService
|
||||||
[Route(HttpVerbs.Get, "/listgrouproles/{group}/{token}")]
|
[Route(HttpVerbs.Get, "/listgrouproles/{group}/{token}")]
|
||||||
public object listgrouproles(string group, string token)
|
public object listgrouproles(string group, string token)
|
||||||
{
|
{
|
||||||
if (tokens.Allow(token, getClientIP()) == true)
|
if (tokens.Allow(token, "groups", "listgrouproles", getClientIP()) == true)
|
||||||
{
|
{
|
||||||
if (UUID.TryParse(group, out UUID groupuuid) == true)
|
if (UUID.TryParse(group, out UUID groupuuid) == true)
|
||||||
{
|
{
|
||||||
|
|
@ -132,7 +132,7 @@ namespace BetterSecondBot.HttpService
|
||||||
[Route(HttpVerbs.Get, "/listgroupswithunread/{token}")]
|
[Route(HttpVerbs.Get, "/listgroupswithunread/{token}")]
|
||||||
public object listgroupswithunread(string token)
|
public object listgroupswithunread(string token)
|
||||||
{
|
{
|
||||||
if (tokens.Allow(token, getClientIP()) == true)
|
if (tokens.Allow(token, "groups", "listgroupswithunread", getClientIP()) == true)
|
||||||
{
|
{
|
||||||
return BasicReply(JsonConvert.SerializeObject(bot.UnreadGroupchatGroups()));
|
return BasicReply(JsonConvert.SerializeObject(bot.UnreadGroupchatGroups()));
|
||||||
}
|
}
|
||||||
|
|
@ -144,7 +144,7 @@ namespace BetterSecondBot.HttpService
|
||||||
[Route(HttpVerbs.Get, "/haveunreadgroupchat/{token}")]
|
[Route(HttpVerbs.Get, "/haveunreadgroupchat/{token}")]
|
||||||
public object haveunreadgroupchat(string token)
|
public object haveunreadgroupchat(string token)
|
||||||
{
|
{
|
||||||
if (tokens.Allow(token, getClientIP()) == true)
|
if (tokens.Allow(token, "groups", "haveunreadgroupchat", getClientIP()) == true)
|
||||||
{
|
{
|
||||||
return BasicReply(bot.HasUnreadGroupchats().ToString());
|
return BasicReply(bot.HasUnreadGroupchats().ToString());
|
||||||
}
|
}
|
||||||
|
|
@ -158,7 +158,7 @@ namespace BetterSecondBot.HttpService
|
||||||
[Route(HttpVerbs.Get, "/getgroupchat/{group}/{token}")]
|
[Route(HttpVerbs.Get, "/getgroupchat/{group}/{token}")]
|
||||||
public object getgroupchat(string group, string token)
|
public object getgroupchat(string group, string token)
|
||||||
{
|
{
|
||||||
if (tokens.Allow(token, getClientIP()) == true)
|
if (tokens.Allow(token, "groups", "getgroupchat", getClientIP()) == true)
|
||||||
{
|
{
|
||||||
if (UUID.TryParse(group, out UUID groupUUID) == true)
|
if (UUID.TryParse(group, out UUID groupUUID) == true)
|
||||||
{
|
{
|
||||||
|
|
@ -177,7 +177,7 @@ namespace BetterSecondBot.HttpService
|
||||||
[Route(HttpVerbs.Post, "/sendgroupchat/{group}/{token}")]
|
[Route(HttpVerbs.Post, "/sendgroupchat/{group}/{token}")]
|
||||||
public object sendgroupchat(string group, string token, [FormField] string message)
|
public object sendgroupchat(string group, string token, [FormField] string message)
|
||||||
{
|
{
|
||||||
if (tokens.Allow(token, getClientIP()) == true)
|
if (tokens.Allow(token, "groups", "sendgroupchat", getClientIP()) == true)
|
||||||
{
|
{
|
||||||
if (UUID.TryParse(group, out UUID groupUUID) == true)
|
if (UUID.TryParse(group, out UUID groupUUID) == true)
|
||||||
{
|
{
|
||||||
|
|
|
||||||
|
|
@ -11,6 +11,9 @@ using EmbedIO.Security;
|
||||||
using BetterSecondBotShared.Static;
|
using BetterSecondBotShared.Static;
|
||||||
using System.Net;
|
using System.Net;
|
||||||
using EmbedIO.Routing;
|
using EmbedIO.Routing;
|
||||||
|
using BetterSecondBotShared.logs;
|
||||||
|
using BetterSecondBotShared.IO;
|
||||||
|
using Newtonsoft.Json;
|
||||||
|
|
||||||
namespace BetterSecondBot.HttpService
|
namespace BetterSecondBot.HttpService
|
||||||
{
|
{
|
||||||
|
|
@ -19,11 +22,122 @@ namespace BetterSecondBot.HttpService
|
||||||
protected JsonConfig Config;
|
protected JsonConfig Config;
|
||||||
protected SecondBot Bot;
|
protected SecondBot Bot;
|
||||||
protected TokenStorage Tokens;
|
protected TokenStorage Tokens;
|
||||||
public HttpAsService(SecondBot MainBot, JsonConfig BotConfig)
|
|
||||||
|
protected void loadScopedTokensFromENV()
|
||||||
|
{
|
||||||
|
int loop = 1;
|
||||||
|
bool found = true;
|
||||||
|
while (found == true)
|
||||||
|
{
|
||||||
|
if (helpers.notempty(Environment.GetEnvironmentVariable("scoped_token_" + loop.ToString())) == true)
|
||||||
|
{
|
||||||
|
processScopedTokenRaw(Environment.GetEnvironmentVariable("scoped_token_" + loop.ToString()));
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
found = false;
|
||||||
|
}
|
||||||
|
loop++;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
protected void loadScopedTokensFromFile()
|
||||||
|
{
|
||||||
|
JsonScopedTokens LoadedTokens = new JsonScopedTokens
|
||||||
|
{
|
||||||
|
ScopedTokens = new string[] { "t:[XXX],ws:core" }
|
||||||
|
};
|
||||||
|
string targetfile = "scoped_tokens.json";
|
||||||
|
SimpleIO io = new SimpleIO();
|
||||||
|
if (SimpleIO.FileType(targetfile, "json") == false)
|
||||||
|
{
|
||||||
|
io.WriteJsonTokens(LoadedTokens, targetfile);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
if (io.Exists(targetfile) == false)
|
||||||
|
{
|
||||||
|
io.WriteJsonTokens(LoadedTokens, targetfile);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
string json = io.ReadFile(targetfile);
|
||||||
|
if (json.Length > 0)
|
||||||
|
{
|
||||||
|
try
|
||||||
|
{
|
||||||
|
LoadedTokens = JsonConvert.DeserializeObject<JsonScopedTokens>(json);
|
||||||
|
foreach (string loaded in LoadedTokens.ScopedTokens)
|
||||||
|
{
|
||||||
|
processScopedTokenRaw(loaded);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
catch
|
||||||
|
{
|
||||||
|
io.makeOld(targetfile);
|
||||||
|
io.WriteJsonTokens(LoadedTokens, targetfile);
|
||||||
|
}
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
protected void processScopedTokenRaw(string raw)
|
||||||
|
{
|
||||||
|
raw = raw.Replace(" ", "");
|
||||||
|
string[] bits = raw.Split(',');
|
||||||
|
string code = null;
|
||||||
|
int accessids = 0;
|
||||||
|
scopedTokenInfo stinfo = new scopedTokenInfo();
|
||||||
|
foreach(string bit in bits)
|
||||||
|
{
|
||||||
|
string[] subbits = bit.Split(':');
|
||||||
|
if(subbits[0] == "t")
|
||||||
|
{
|
||||||
|
code = subbits[1];
|
||||||
|
}
|
||||||
|
else if (subbits[0] == "cm")
|
||||||
|
{
|
||||||
|
stinfo.AllowCommands.Add(subbits[1]);
|
||||||
|
accessids++;
|
||||||
|
}
|
||||||
|
else if (subbits[0] == "cg")
|
||||||
|
{
|
||||||
|
stinfo.AllowAccessGroups.Add(subbits[1]);
|
||||||
|
accessids++;
|
||||||
|
}
|
||||||
|
else if (subbits[0] == "ws")
|
||||||
|
{
|
||||||
|
stinfo.AllowWorkgroups.Add(subbits[1]);
|
||||||
|
accessids++;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if((code != null) && (accessids > 0))
|
||||||
|
{
|
||||||
|
Tokens.AddScopedToken(code, stinfo);
|
||||||
|
LogFormater.Info("Adding scopped command " + code + " with: " + accessids.ToString() + " access types");
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
LogFormater.Warn("Scoped access code: "+raw+" did not pass checks");
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
public HttpAsService(SecondBot MainBot, JsonConfig BotConfig, bool running_in_docker)
|
||||||
{
|
{
|
||||||
Bot = MainBot;
|
Bot = MainBot;
|
||||||
Config = BotConfig;
|
Config = BotConfig;
|
||||||
|
|
||||||
|
Tokens = new TokenStorage();
|
||||||
|
// Load scoped tokens
|
||||||
|
if(running_in_docker == true)
|
||||||
|
{
|
||||||
|
// using ENV values
|
||||||
|
loadScopedTokensFromENV();
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
// from file
|
||||||
|
loadScopedTokensFromFile();
|
||||||
|
}
|
||||||
|
|
||||||
// Our web server is disposable
|
// Our web server is disposable
|
||||||
Logger.UnregisterLogger<ConsoleLogger>();
|
Logger.UnregisterLogger<ConsoleLogger>();
|
||||||
using (var server = CreateWebServer(Config.Http_Host))
|
using (var server = CreateWebServer(Config.Http_Host))
|
||||||
|
|
@ -39,7 +153,7 @@ namespace BetterSecondBot.HttpService
|
||||||
|
|
||||||
private WebServer CreateWebServer(string url)
|
private WebServer CreateWebServer(string url)
|
||||||
{
|
{
|
||||||
Tokens = new TokenStorage();
|
|
||||||
var server = new WebServer(o => o
|
var server = new WebServer(o => o
|
||||||
.WithUrlPrefix(url)
|
.WithUrlPrefix(url)
|
||||||
.WithMode(HttpListenerMode.EmbedIO))
|
.WithMode(HttpListenerMode.EmbedIO))
|
||||||
|
|
@ -123,8 +237,18 @@ namespace BetterSecondBot.HttpService
|
||||||
|
|
||||||
public class TokenStorage
|
public class TokenStorage
|
||||||
{
|
{
|
||||||
|
// global access tokens
|
||||||
protected Dictionary<string, tokenInfo> tokens = new Dictionary<string, tokenInfo>();
|
protected Dictionary<string, tokenInfo> tokens = new Dictionary<string, tokenInfo>();
|
||||||
|
|
||||||
|
// scoped access tokens
|
||||||
|
protected Dictionary<string, scopedTokenInfo> scopedtokens = new Dictionary<string, scopedTokenInfo>();
|
||||||
|
|
||||||
|
|
||||||
|
public void AddScopedToken(string code, scopedTokenInfo info)
|
||||||
|
{
|
||||||
|
scopedtokens.Add(code, info);
|
||||||
|
}
|
||||||
|
|
||||||
public void PurgeExpired()
|
public void PurgeExpired()
|
||||||
{
|
{
|
||||||
List<string> oldTokens = new List<string>();
|
List<string> oldTokens = new List<string>();
|
||||||
|
|
@ -154,7 +278,7 @@ namespace BetterSecondBot.HttpService
|
||||||
return "Failed to remove token";
|
return "Failed to remove token";
|
||||||
}
|
}
|
||||||
|
|
||||||
public bool Allow(string code, IPAddress IPaddress)
|
public bool Allow(string code, string workgroup, string command, IPAddress IPaddress)
|
||||||
{
|
{
|
||||||
if(tokens.ContainsKey(code) == true)
|
if(tokens.ContainsKey(code) == true)
|
||||||
{
|
{
|
||||||
|
|
@ -169,7 +293,35 @@ namespace BetterSecondBot.HttpService
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
return false;
|
return ScopeAllow(code, workgroup, command);
|
||||||
|
}
|
||||||
|
|
||||||
|
public bool ScopeAllow(string code, string workgroup, string command)
|
||||||
|
{
|
||||||
|
if (scopedtokens.ContainsKey(code) == false)
|
||||||
|
{
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
scopedTokenInfo info = scopedtokens[code];
|
||||||
|
string build = workgroup + "/" + command;
|
||||||
|
if (info.AllowWorkgroups.Contains(workgroup) == true)
|
||||||
|
{
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
else if(info.AllowCommands.Contains(build) == true)
|
||||||
|
{
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
bool allowed = false;
|
||||||
|
foreach(string A in info.AllowAccessGroups)
|
||||||
|
{
|
||||||
|
allowed = accessgroupcontrol.isAllowed(A, workgroup, command);
|
||||||
|
if(allowed == true)
|
||||||
|
{
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return allowed;
|
||||||
}
|
}
|
||||||
|
|
||||||
public string CreateToken(IPAddress IP)
|
public string CreateToken(IPAddress IP)
|
||||||
|
|
@ -237,4 +389,51 @@ namespace BetterSecondBot.HttpService
|
||||||
public IPAddress IP = null;
|
public IPAddress IP = null;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public class scopedTokenInfo
|
||||||
|
{
|
||||||
|
public List<string> AllowWorkgroups = new List<string>();
|
||||||
|
public List<string> AllowAccessGroups = new List<string>();
|
||||||
|
public List<string> AllowCommands = new List<string>();
|
||||||
|
}
|
||||||
|
|
||||||
|
public static class accessgroupcontrol
|
||||||
|
{
|
||||||
|
public static bool isAllowed(string permsgroupname, string workgroup, string command)
|
||||||
|
{
|
||||||
|
string build = workgroup + "/" + command;
|
||||||
|
List<string> allowed = new List<string>();
|
||||||
|
if (permsgroupname == "chat")
|
||||||
|
{
|
||||||
|
allowed = new List<string>(){
|
||||||
|
"chat/localchathistory",
|
||||||
|
"chat/localchatsay",
|
||||||
|
"groups/getgroupchat",
|
||||||
|
"groups/sendgroupchat",
|
||||||
|
"groups/listgroups",
|
||||||
|
"im/chatwindows",
|
||||||
|
"im/listwithunread",
|
||||||
|
"im/getimchat",
|
||||||
|
"im/sendimchat"
|
||||||
|
};
|
||||||
|
}
|
||||||
|
else if (permsgroupname == "giver")
|
||||||
|
{
|
||||||
|
allowed = new List<string>(){
|
||||||
|
"inventory/send",
|
||||||
|
"inventory/folders",
|
||||||
|
"inventory/contents"
|
||||||
|
};
|
||||||
|
}
|
||||||
|
else if (permsgroupname == "movement")
|
||||||
|
{
|
||||||
|
allowed = new List<string>(){
|
||||||
|
"core/walkto",
|
||||||
|
"core/teleport",
|
||||||
|
"core/gesture"
|
||||||
|
};
|
||||||
|
}
|
||||||
|
return allowed.Contains(build);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -21,7 +21,7 @@ namespace BetterSecondBot.HttpService
|
||||||
[Route(HttpVerbs.Get, "/chatwindows/{token}")]
|
[Route(HttpVerbs.Get, "/chatwindows/{token}")]
|
||||||
public object chatwindows(string token)
|
public object chatwindows(string token)
|
||||||
{
|
{
|
||||||
if (tokens.Allow(token, getClientIP()) == true)
|
if (tokens.Allow(token, "im", "chatwindows", getClientIP()) == true)
|
||||||
{
|
{
|
||||||
return BasicReply(JsonConvert.SerializeObject(bot.GetIMChatWindowKeyNames()));
|
return BasicReply(JsonConvert.SerializeObject(bot.GetIMChatWindowKeyNames()));
|
||||||
}
|
}
|
||||||
|
|
@ -33,7 +33,7 @@ namespace BetterSecondBot.HttpService
|
||||||
[Route(HttpVerbs.Get, "/listwithunread/{token}")]
|
[Route(HttpVerbs.Get, "/listwithunread/{token}")]
|
||||||
public object listwithunread(string group, string token)
|
public object listwithunread(string group, string token)
|
||||||
{
|
{
|
||||||
if (tokens.Allow(token, getClientIP()) == true)
|
if (tokens.Allow(token, "im", "listwithunread", getClientIP()) == true)
|
||||||
{
|
{
|
||||||
List<UUID> unreadimwindows = new List<UUID>();
|
List<UUID> unreadimwindows = new List<UUID>();
|
||||||
foreach (UUID window in bot.IMChatWindows())
|
foreach (UUID window in bot.IMChatWindows())
|
||||||
|
|
@ -53,7 +53,7 @@ namespace BetterSecondBot.HttpService
|
||||||
[Route(HttpVerbs.Get, "/haveunreadims/{token}")]
|
[Route(HttpVerbs.Get, "/haveunreadims/{token}")]
|
||||||
public object haveunreadims(string token)
|
public object haveunreadims(string token)
|
||||||
{
|
{
|
||||||
if (tokens.Allow(token, getClientIP()) == true)
|
if (tokens.Allow(token, "im", "haveunreadims", getClientIP()) == true)
|
||||||
{
|
{
|
||||||
bool reply = false;
|
bool reply = false;
|
||||||
foreach(UUID window in bot.IMChatWindows())
|
foreach(UUID window in bot.IMChatWindows())
|
||||||
|
|
@ -76,7 +76,7 @@ namespace BetterSecondBot.HttpService
|
||||||
[Route(HttpVerbs.Get, "/getimchat/{window}/{token}")]
|
[Route(HttpVerbs.Get, "/getimchat/{window}/{token}")]
|
||||||
public object getimchat(string window, string token)
|
public object getimchat(string window, string token)
|
||||||
{
|
{
|
||||||
if (tokens.Allow(token, getClientIP()) == true)
|
if (tokens.Allow(token, "im", "getimchat", getClientIP()) == true)
|
||||||
{
|
{
|
||||||
if (UUID.TryParse(window, out UUID windowUUID) == true)
|
if (UUID.TryParse(window, out UUID windowUUID) == true)
|
||||||
{
|
{
|
||||||
|
|
@ -94,7 +94,7 @@ namespace BetterSecondBot.HttpService
|
||||||
[Route(HttpVerbs.Post, "/sendimchat/{avatar}/{token}")]
|
[Route(HttpVerbs.Post, "/sendimchat/{avatar}/{token}")]
|
||||||
public object sendimchat(string avatar, string token, [FormField] string message)
|
public object sendimchat(string avatar, string token, [FormField] string message)
|
||||||
{
|
{
|
||||||
if (tokens.Allow(token, getClientIP()) == true)
|
if (tokens.Allow(token, "im", "sendimchat", getClientIP()) == true)
|
||||||
{
|
{
|
||||||
bot.GetCommandsInterface.Call("im", avatar + "~#~" + message, UUID.Zero, "~#~");
|
bot.GetCommandsInterface.Call("im", avatar + "~#~" + message, UUID.Zero, "~#~");
|
||||||
return BasicReply("ok");
|
return BasicReply("ok");
|
||||||
|
|
|
||||||
|
|
@ -20,7 +20,7 @@ namespace BetterSecondBot.HttpService
|
||||||
[Route(HttpVerbs.Get, "/rezobject/{item}/{token}")]
|
[Route(HttpVerbs.Get, "/rezobject/{item}/{token}")]
|
||||||
public object rezobject(string item, string token, [FormField] string newname)
|
public object rezobject(string item, string token, [FormField] string newname)
|
||||||
{
|
{
|
||||||
if (tokens.Allow(token, getClientIP()) == true)
|
if (tokens.Allow(token, "inventory", "rezobject", getClientIP()) == true)
|
||||||
{
|
{
|
||||||
bool status = bot.GetCommandsInterface.Call("RezObject", item);
|
bool status = bot.GetCommandsInterface.Call("RezObject", item);
|
||||||
return BasicReply(status.ToString());
|
return BasicReply(status.ToString());
|
||||||
|
|
@ -35,7 +35,7 @@ namespace BetterSecondBot.HttpService
|
||||||
[Route(HttpVerbs.Post, "/rename/{item}/{token}")]
|
[Route(HttpVerbs.Post, "/rename/{item}/{token}")]
|
||||||
public object rename(string item, string token, [FormField] string newname)
|
public object rename(string item, string token, [FormField] string newname)
|
||||||
{
|
{
|
||||||
if (tokens.Allow(token, getClientIP()) == true)
|
if (tokens.Allow(token, "inventory", "rename", getClientIP()) == true)
|
||||||
{
|
{
|
||||||
bool status = bot.GetCommandsInterface.Call("RenameInventory", "12~#~" + item + "~#~" + newname);
|
bool status = bot.GetCommandsInterface.Call("RenameInventory", "12~#~" + item + "~#~" + newname);
|
||||||
return BasicReply(status.ToString());
|
return BasicReply(status.ToString());
|
||||||
|
|
@ -50,7 +50,7 @@ namespace BetterSecondBot.HttpService
|
||||||
[Route(HttpVerbs.Get, "/realuuid/{item}/{token}")]
|
[Route(HttpVerbs.Get, "/realuuid/{item}/{token}")]
|
||||||
public object realuuid(string item, string token)
|
public object realuuid(string item, string token)
|
||||||
{
|
{
|
||||||
if (tokens.Allow(token, getClientIP()) == true)
|
if (tokens.Allow(token, "inventory", "realuuid", getClientIP()) == true)
|
||||||
{
|
{
|
||||||
if (UUID.TryParse(item, out UUID itemUUID) == true)
|
if (UUID.TryParse(item, out UUID itemUUID) == true)
|
||||||
{
|
{
|
||||||
|
|
@ -73,7 +73,7 @@ namespace BetterSecondBot.HttpService
|
||||||
[Route(HttpVerbs.Get, "/send/{item}/{avatar}/{token}")]
|
[Route(HttpVerbs.Get, "/send/{item}/{avatar}/{token}")]
|
||||||
public object send(string item, string avatar, string token)
|
public object send(string item, string avatar, string token)
|
||||||
{
|
{
|
||||||
if (tokens.Allow(token, getClientIP()) == true)
|
if (tokens.Allow(token, "inventory", "send", getClientIP()) == true)
|
||||||
{
|
{
|
||||||
if (UUID.TryParse(item, out UUID itemUUID) == true)
|
if (UUID.TryParse(item, out UUID itemUUID) == true)
|
||||||
{
|
{
|
||||||
|
|
@ -94,7 +94,7 @@ namespace BetterSecondBot.HttpService
|
||||||
[Route(HttpVerbs.Get, "/delete/{item}/{isfolder}/{token}")]
|
[Route(HttpVerbs.Get, "/delete/{item}/{isfolder}/{token}")]
|
||||||
public object delete(string item,string isfolder, string token)
|
public object delete(string item,string isfolder, string token)
|
||||||
{
|
{
|
||||||
if (tokens.Allow(token, getClientIP()) == true)
|
if (tokens.Allow(token, "inventory", "delete", getClientIP()) == true)
|
||||||
{
|
{
|
||||||
if (UUID.TryParse(item, out UUID itemUUID) == true)
|
if (UUID.TryParse(item, out UUID itemUUID) == true)
|
||||||
{
|
{
|
||||||
|
|
@ -118,7 +118,7 @@ namespace BetterSecondBot.HttpService
|
||||||
[Route(HttpVerbs.Get, "/folders/{token}")]
|
[Route(HttpVerbs.Get, "/folders/{token}")]
|
||||||
public object folders(string token)
|
public object folders(string token)
|
||||||
{
|
{
|
||||||
if(tokens.Allow(token, getClientIP()) == true)
|
if(tokens.Allow(token, "inventory", "folders", getClientIP()) == true)
|
||||||
{
|
{
|
||||||
string reply = HelperInventory.MapFolderJson(bot);
|
string reply = HelperInventory.MapFolderJson(bot);
|
||||||
if(reply != null) return BasicReply(reply);
|
if(reply != null) return BasicReply(reply);
|
||||||
|
|
@ -134,7 +134,7 @@ namespace BetterSecondBot.HttpService
|
||||||
[Route(HttpVerbs.Get, "/contents/{folderUUID}/{token}")]
|
[Route(HttpVerbs.Get, "/contents/{folderUUID}/{token}")]
|
||||||
public object Contents(string folderUUID, string token)
|
public object Contents(string folderUUID, string token)
|
||||||
{
|
{
|
||||||
if (tokens.Allow(token, getClientIP()) == true)
|
if (tokens.Allow(token, "inventory", "contents", getClientIP()) == true)
|
||||||
{
|
{
|
||||||
if (UUID.TryParse(folderUUID, out UUID folder) == true)
|
if (UUID.TryParse(folderUUID, out UUID folder) == true)
|
||||||
{
|
{
|
||||||
|
|
|
||||||
|
|
@ -23,7 +23,7 @@ namespace BetterSecondBot.HttpService
|
||||||
[Route(HttpVerbs.Get, "/parcelbanlist/{token}")]
|
[Route(HttpVerbs.Get, "/parcelbanlist/{token}")]
|
||||||
public object parcelbanlist(string token)
|
public object parcelbanlist(string token)
|
||||||
{
|
{
|
||||||
if (tokens.Allow(token, getClientIP()) == true)
|
if (tokens.Allow(token, "parcelestate", "parcelbanlist", getClientIP()) == true)
|
||||||
{
|
{
|
||||||
if (bot.GetClient.Network.CurrentSim != null)
|
if (bot.GetClient.Network.CurrentSim != null)
|
||||||
{
|
{
|
||||||
|
|
|
||||||
76
README.md
76
README.md
|
|
@ -25,9 +25,7 @@ Secondbot is a CommandLine based bot for SecondLife based on libremetaverse reta
|
||||||
## Releases
|
## Releases
|
||||||
These are pre compiled versions for the most upto date please use docker or compile it yourself.
|
These are pre compiled versions for the most upto date please use docker or compile it yourself.
|
||||||
|
|
||||||
[Windows x64](https://github.com/Madpeterz/SecondBot/releases/tag/windows-x64)
|
[View releases](https://github.com/Madpeterz/SecondBot/releases)
|
||||||
|
|
||||||
[Linux (Tested on Deb) x64](https://github.com/Madpeterz/SecondBot/releases/tag/linux-x64)
|
|
||||||
|
|
||||||
|
|
||||||
### Starting multiple bots from the same executable in windows
|
### Starting multiple bots from the same executable in windows
|
||||||
|
|
@ -66,5 +64,77 @@ and the command would look something like this
|
||||||
|
|
||||||
sayexample!!!say|||Hello [C_ARG_1]{-}delay|||2500{-}say|||Bye [C_ARG_2]
|
sayexample!!!say|||Hello [C_ARG_1]{-}delay|||2500{-}say|||Bye [C_ARG_2]
|
||||||
|
|
||||||
|
### HTTP web interface
|
||||||
|
|
||||||
|
by setting
|
||||||
|
|
||||||
|
> Http_Enable to true
|
||||||
|
> Http_Host to http://*:8080
|
||||||
|
> Security_WebUIKey to a vaild code (12 letters+numbers long or more)
|
||||||
|
|
||||||
|
you will be able to connect to the bot via HTTP and use the webUI
|
||||||
|
to control the bot!
|
||||||
|
|
||||||
|
[Dev server UI](http://webui.magicmadpeter.xyz/)
|
||||||
|
or
|
||||||
|
[Host it yourself](https://github.com/Madpeterz/secondbot_web_folders)
|
||||||
|
|
||||||
|
### HTTP scoped tokens
|
||||||
|
---
|
||||||
|
Scoped tokens allow you to hardcode access to the HTTP interface (if enabled)
|
||||||
|
and set more detailed control over what areas can be accessed
|
||||||
|
plus no need to give the full http
|
||||||
|
|
||||||
|
> Security_WebUIKey
|
||||||
|
|
||||||
|
You get set these tokens up by file or Environment Variables.
|
||||||
|
##### File
|
||||||
|
|
||||||
|
> {
|
||||||
|
> "ScopedTokens": [
|
||||||
|
> "t:[10charcode],ws:core,ws:group",
|
||||||
|
> "t:[10charcode],cm:chat/localchathistory",
|
||||||
|
> ]
|
||||||
|
> }
|
||||||
|
|
||||||
|
|
||||||
|
##### Environment Variables
|
||||||
|
|Name | Value|
|
||||||
|
|--|--|
|
||||||
|
| scoped_token_1 | "t:[10charcode],ws:core,ws:group" |
|
||||||
|
| scoped_token_2 | "t:[10charcode],cg:chat" |
|
||||||
|
| scoped_token_3 | "t:[10charcode],cm:chat/localchathistory" |
|
||||||
|
|
||||||
|
|
||||||
|
### HTTP scoped tokens (info)
|
||||||
|
---
|
||||||
|
|
||||||
|
command [cm] "example: `cm:chat/localchathistory`
|
||||||
|
|
||||||
|
workspaces [ws] "example: ws: core, ws: groups"
|
||||||
|
|
||||||
|
commandgroups [cg] "example: `cg:chat`"
|
||||||
|
chat
|
||||||
|
chat/localchathistory
|
||||||
|
chat/localchatsay
|
||||||
|
groups/getgroupchat
|
||||||
|
groups/sendgroupchat
|
||||||
|
groups/listgroups
|
||||||
|
im/chatwindows
|
||||||
|
im/listwithunread
|
||||||
|
im/getimchat
|
||||||
|
im/sendimchat
|
||||||
|
|
||||||
|
giver
|
||||||
|
inventory/send
|
||||||
|
inventory/folders
|
||||||
|
inventory/contents
|
||||||
|
|
||||||
|
|
||||||
|
groupinvite
|
||||||
|
[WIP]
|
||||||
|
|
||||||
|
movement
|
||||||
|
core/walkto
|
||||||
|
core/teleport
|
||||||
|
core/gesture
|
||||||
|
|
|
||||||
Loading…
Reference in a new issue