From 9ea1ba68f54562c7129ee4f364b5ffa1dd0af827 Mon Sep 17 00:00:00 2001 From: Chris Sexton Date: Mon, 21 Jan 2019 16:26:54 -0500 Subject: [PATCH] admin: add ability to get/set config values * Users cannot get/set sensitive values * Removed example lua config file --- example_config.lua | 123 ------------------------------------ plugins/admin/admin.go | 41 +++++++++--- plugins/admin/admin_test.go | 69 ++++++++++++++++++++ 3 files changed, 102 insertions(+), 131 deletions(-) delete mode 100644 example_config.lua create mode 100644 plugins/admin/admin_test.go diff --git a/example_config.lua b/example_config.lua deleted file mode 100644 index b1a2ea3..0000000 --- a/example_config.lua +++ /dev/null @@ -1,123 +0,0 @@ -config = { - Channels = { - "#CatBaseTest" - }, - TwitterConsumerSecret = "", - Reminder = { - MaxBatchAdd = 10 - }, - Nick = "CatBaseTest", - IconURL = "http://placekitten.com/g/200/300", - LeftPad = { - Who = "person", - MaxLen = 50 - }, - Factoid = { - StartupFact = "speed test", - QuoteTime = 1, - QuoteChance = 0.99, - MinLen = 5 - }, - CommandChar = { - "!", - "ยก" - }, - FullName = "CatBase", - Your = { - MaxLength = 140, - DuckingChance = 0.5, - FuckingChance = 0.15, - YourChance = 0.4 - }, - Emojify = { - Chance = 0.02, - Scoreless = { - "a", - "it" - } - }, - DB = { - File = "catbase.db", - Server = "127.0.0.1" - }, - Plugins = { - }, - Untappd = { - Freq = 3600, - Channels = { - }, - Token = "" - }, - LogLength = 50, - RatePerSec = 10, - Reaction = { - HarrassChance = 0.05, - GeneralChance = 0.01, - NegativeHarrassmentMultiplier = 2, - HarrassList = { - "msherms" - }, - NegativeReactions = { - "bullshit", - "fake", - "tableflip", - "vomit" - }, - PositiveReactions = { - "+1", - "authorized", - "aw_yea", - "joy" - } - }, - TwitterUserKey = "", - MainChannel = "#CatBaseTest", - TwitterUserSecret = "", - WelcomeMsgs = { - "Real men use screen, %s.", - "Joins upset the hivemind's OCD, %s.", - "Joins upset the hivemind's CDO, %s.", - "%s, I WILL CUT YOU!" - }, - Bad = { - Msgs = { - }, - Hosts = { - }, - Nicks = { - } - }, - Irc = { - Server = "ircserver:6697", - Pass = "CatBaseTest:test" - }, - Slack = { - Token = "" - }, - TwitterConsumerKey = "", - Babbler = { - DefaultUsers = { - "seabass" - } - }, - Type = "slack", - Admins = { - "" - }, - Stats = { - Sightings = { - "user" - }, - DBPath = "stats.db" - }, - HttpAddr = "127.0.0.1:1337", - Inventory = { - Max = 5 - }, - Sisyphus = { - MinDecrement = 10, - MinPush = 1 - } -} - -} diff --git a/plugins/admin/admin.go b/plugins/admin/admin.go index ae624b2..6543930 100644 --- a/plugins/admin/admin.go +++ b/plugins/admin/admin.go @@ -3,12 +3,14 @@ package admin import ( + "fmt" "log" "strings" "github.com/jmoiron/sqlx" "github.com/velour/catbase/bot" "github.com/velour/catbase/bot/msg" + "github.com/velour/catbase/config" ) // This is a admin plugin to serve as an example and quick copy/paste for new plugins. @@ -16,6 +18,7 @@ import ( type AdminPlugin struct { Bot bot.Bot db *sqlx.DB + cfg *config.Config } // NewAdminPlugin creates a new AdminPlugin with the Plugin interface @@ -23,11 +26,18 @@ func New(bot bot.Bot) *AdminPlugin { p := &AdminPlugin{ Bot: bot, db: bot.DB(), + cfg: bot.Config(), } - p.LoadData() return p } +var forbiddenKeys = map[string]bool{ + "twitch.authorization": true, + "twitch.clientid": true, + "untappd.token": true, + "slack.token": true, +} + // Message responds to the bot hook on recieving messages. // This function returns true if the plugin responds in a meaningful way to the users message. // Otherwise, the function returns false and the bot continues execution of other plugins. @@ -38,6 +48,28 @@ func (p *AdminPlugin) Message(message msg.Message) bool { return p.handleVariables(message) } + if !message.Command { + return false + } + + parts := strings.Split(body, " ") + if parts[0] == "set" && len(parts) > 2 && forbiddenKeys[parts[1]] { + p.Bot.SendMessage(message.Channel, "You cannot access that key") + return true + } else if parts[0] == "set" && len(parts) > 2 { + p.cfg.Set(parts[1], strings.Join(parts[2:], " ")) + p.Bot.SendMessage(message.Channel, fmt.Sprintf("Set %s", parts[1])) + return true + } + if parts[0] == "get" && len(parts) == 2 && forbiddenKeys[parts[1]] { + p.Bot.SendMessage(message.Channel, "You cannot access that key") + return true + } else if parts[0] == "get" && len(parts) == 2 { + v := p.cfg.Get(parts[1]) + p.Bot.SendMessage(message.Channel, fmt.Sprintf("%s: %s", parts[1], v)) + return true + } + return false } @@ -88,13 +120,6 @@ func (p *AdminPlugin) handleVariables(message msg.Message) bool { return true } -// LoadData imports any configuration data into the plugin. This is not strictly necessary other -// than the fact that the Plugin interface demands it exist. This may be deprecated at a later -// date. -func (p *AdminPlugin) LoadData() { - // This bot has no data to load -} - // Help responds to help requests. Every plugin must implement a help function. func (p *AdminPlugin) Help(channel string, parts []string) { p.Bot.SendMessage(channel, "This does super secret things that you're not allowed to know about.") diff --git a/plugins/admin/admin_test.go b/plugins/admin/admin_test.go new file mode 100644 index 0000000..8df6b0d --- /dev/null +++ b/plugins/admin/admin_test.go @@ -0,0 +1,69 @@ +package admin + +import ( + "strings" + "testing" + + "github.com/stretchr/testify/assert" + "github.com/velour/catbase/bot" + "github.com/velour/catbase/bot/msg" + "github.com/velour/catbase/bot/user" +) + +var ( + a *AdminPlugin + mb *bot.MockBot +) + +func setup(t *testing.T) (*AdminPlugin, *bot.MockBot) { + mb = bot.NewMockBot() + a = New(mb) + mb.DB().MustExec(`delete from config`) + return a, mb +} + +func makeMessage(payload string) msg.Message { + isCmd := strings.HasPrefix(payload, "!") + if isCmd { + payload = payload[1:] + } + return msg.Message{ + User: &user.User{Name: "tester"}, + Channel: "test", + Body: payload, + Command: isCmd, + } +} + +func TestSet(t *testing.T) { + a, mb := setup(t) + expected := "test value" + a.Message(makeMessage("!set test.key " + expected)) + actual := mb.Config().Get("test.key") + assert.Equal(t, expected, actual) +} + +func TestGetValue(t *testing.T) { + a, mb := setup(t) + expected := "value" + mb.Config().Set("test.key", "value") + a.Message(makeMessage("!get test.key")) + assert.Len(t, mb.Messages, 1) + assert.Contains(t, mb.Messages[0], expected) +} + +func TestGetEmpty(t *testing.T) { + a, mb := setup(t) + expected := "test.key: " + a.Message(makeMessage("!get test.key")) + assert.Len(t, mb.Messages, 1) + assert.Equal(t, expected, mb.Messages[0]) +} + +func TestGetForbidden(t *testing.T) { + a, mb := setup(t) + expected := "cannot access" + a.Message(makeMessage("!get slack.token")) + assert.Len(t, mb.Messages, 1) + assert.Contains(t, mb.Messages[0], expected) +}