mirror of https://github.com/velour/catbase.git
Merge pull request #187 from velour/password
web: use secret instead of human test
This commit is contained in:
commit
834c089696
18
bot/bot.go
18
bot/bot.go
|
@ -3,9 +3,12 @@
|
|||
package bot
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
"math/rand"
|
||||
"net/http"
|
||||
"reflect"
|
||||
"strings"
|
||||
"time"
|
||||
|
||||
"github.com/jmoiron/sqlx"
|
||||
"github.com/rs/zerolog/log"
|
||||
|
@ -43,6 +46,9 @@ type bot struct {
|
|||
filters map[string]func(string) string
|
||||
|
||||
callbacks CallbackMap
|
||||
|
||||
password string
|
||||
passwordCreated time.Time
|
||||
}
|
||||
|
||||
type EndPoint struct {
|
||||
|
@ -231,3 +237,15 @@ func (b *bot) Register(p Plugin, kind Kind, cb Callback) {
|
|||
func (b *bot) RegisterWeb(root, name string) {
|
||||
b.httpEndPoints = append(b.httpEndPoints, EndPoint{name, root})
|
||||
}
|
||||
|
||||
func (b *bot) GetPassword() string {
|
||||
if b.passwordCreated.Before(time.Now().Add(-24 * time.Hour)) {
|
||||
adjs := b.config.GetArray("bot.passwordAdjectives", []string{"very"})
|
||||
nouns := b.config.GetArray("bot.passwordNouns", []string{"noun"})
|
||||
verbs := b.config.GetArray("bot.passwordVerbs", []string{"do"})
|
||||
a, n, v := adjs[rand.Intn(len(adjs))], nouns[rand.Intn(len(nouns))], verbs[rand.Intn(len(verbs))]
|
||||
b.passwordCreated = time.Now()
|
||||
b.password = fmt.Sprintf("%s-%s-%s", a, n, v)
|
||||
}
|
||||
return b.password
|
||||
}
|
||||
|
|
|
@ -67,6 +67,7 @@ type Bot interface {
|
|||
RegisterWeb(string, string)
|
||||
DefaultConnector() Connector
|
||||
GetWebNavigation() []EndPoint
|
||||
GetPassword() string
|
||||
}
|
||||
|
||||
// Connector represents a server connection to a chat service
|
||||
|
|
|
@ -32,6 +32,7 @@ func (mb *MockBot) DB() *sqlx.DB { return mb.Cfg.DB }
|
|||
func (mb *MockBot) Who(string) []user.User { return []user.User{} }
|
||||
func (mb *MockBot) WhoAmI() string { return "tester" }
|
||||
func (mb *MockBot) DefaultConnector() Connector { return nil }
|
||||
func (mb *MockBot) GetPassword() string { return "12345" }
|
||||
func (mb *MockBot) Send(c Connector, kind Kind, args ...interface{}) (string, error) {
|
||||
switch kind {
|
||||
case Message:
|
||||
|
|
|
@ -81,6 +81,11 @@ func (p *AdminPlugin) message(conn bot.Connector, k bot.Kind, message msg.Messag
|
|||
return true
|
||||
}
|
||||
|
||||
if strings.ToLower(body) == "password" {
|
||||
p.bot.Send(conn, bot.Message, message.Channel, p.bot.GetPassword())
|
||||
return true
|
||||
}
|
||||
|
||||
parts := strings.Split(body, " ")
|
||||
if parts[0] == "set" && len(parts) > 2 && forbiddenKeys[parts[1]] {
|
||||
p.bot.Send(conn, bot.Message, message.Channel, "You cannot access that key")
|
||||
|
|
|
@ -42,8 +42,9 @@ func (p *CliPlugin) handleWebAPI(w http.ResponseWriter, r *http.Request) {
|
|||
return
|
||||
}
|
||||
info := struct {
|
||||
User string `json:"user"`
|
||||
Payload string `json:"payload"`
|
||||
User string `json:"user"`
|
||||
Payload string `json:"payload"`
|
||||
Password string `json:"password"`
|
||||
}{}
|
||||
decoder := json.NewDecoder(r.Body)
|
||||
err := decoder.Decode(&info)
|
||||
|
@ -55,6 +56,12 @@ func (p *CliPlugin) handleWebAPI(w http.ResponseWriter, r *http.Request) {
|
|||
log.Debug().
|
||||
Interface("postbody", info).
|
||||
Msg("Got a POST")
|
||||
if info.Password != p.bot.GetPassword() {
|
||||
w.WriteHeader(http.StatusForbidden)
|
||||
j, _ := json.Marshal(struct{ Err string }{Err: "Invalid Password"})
|
||||
w.Write(j)
|
||||
return
|
||||
}
|
||||
|
||||
p.bot.Receive(p, bot.Message, msg.Message{
|
||||
User: &user.User{
|
||||
|
|
|
@ -30,20 +30,14 @@ var indexHTML = `
|
|||
<b-alert
|
||||
dismissable
|
||||
variant="error"
|
||||
v-if="err"
|
||||
@dismissed="err = ''">
|
||||
:show="err">
|
||||
{{ "{{ err }}" }}
|
||||
</b-alert>
|
||||
<b-container>
|
||||
<b-row>
|
||||
<b-form-group
|
||||
:label="humanTest"
|
||||
label-for="input-1"
|
||||
label-cols="8"
|
||||
autofocus>
|
||||
<b-input v-model="answer" id="input-1" autocomplete="off"></b-input>
|
||||
</b-form-group>
|
||||
</b-row>
|
||||
<b-row>
|
||||
<b-col cols="5">Password:</b-col>
|
||||
<b-col><b-input v-model="answer"></b-col>
|
||||
</b-row>
|
||||
<b-row>
|
||||
<b-form-textarea
|
||||
v-sticky-scroll
|
||||
|
@ -95,21 +89,10 @@ var indexHTML = `
|
|||
},
|
||||
computed: {
|
||||
authenticated: function() {
|
||||
if (Number(this.answer) === this.correct && this.user !== '')
|
||||
if (this.user !== '')
|
||||
return true;
|
||||
return false;
|
||||
},
|
||||
humanTest: function() {
|
||||
const x = Math.floor(Math.random() * 100);
|
||||
const y = Math.floor(Math.random() * 100);
|
||||
const z = Math.floor(Math.random() * 100);
|
||||
const ops = ['+', '-', '*'];
|
||||
const op1 = ops[Math.floor(Math.random()*3)];
|
||||
const op2 = ops[Math.floor(Math.random()*3)];
|
||||
const eq = ""+x+op1+y+op2+z;
|
||||
this.correct = eval(eq);
|
||||
return "Human test: What is " + eq + "?";
|
||||
},
|
||||
text: function() {
|
||||
return this.textarea.join('\n');
|
||||
}
|
||||
|
@ -125,18 +108,16 @@ var indexHTML = `
|
|||
evt.preventDefault();
|
||||
evt.stopPropagation()
|
||||
if (!this.authenticated) {
|
||||
console.log("User is a bot.");
|
||||
this.err = "User appears to be a bot.";
|
||||
return;
|
||||
}
|
||||
const payload = {user: this.user, payload: this.input};
|
||||
const payload = {user: this.user, payload: this.input, password: this.answer};
|
||||
this.addText(this.user, this.input);
|
||||
this.input = "";
|
||||
axios.post('/cli/api', payload)
|
||||
.then(resp => {
|
||||
console.log(JSON.stringify(resp.data));
|
||||
const data = resp.data;
|
||||
this.addText(data.user, data.payload.trim());
|
||||
this.err = '';
|
||||
})
|
||||
.catch(err => (this.err = err));
|
||||
}
|
||||
|
|
|
@ -566,9 +566,10 @@ func (p *CounterPlugin) handleCounter(w http.ResponseWriter, r *http.Request) {
|
|||
func (p *CounterPlugin) handleCounterAPI(w http.ResponseWriter, r *http.Request) {
|
||||
if r.Method == http.MethodPost {
|
||||
info := struct {
|
||||
User string
|
||||
Thing string
|
||||
Action string
|
||||
User string
|
||||
Thing string
|
||||
Action string
|
||||
Password string
|
||||
}{}
|
||||
decoder := json.NewDecoder(r.Body)
|
||||
err := decoder.Decode(&info)
|
||||
|
@ -580,6 +581,12 @@ func (p *CounterPlugin) handleCounterAPI(w http.ResponseWriter, r *http.Request)
|
|||
log.Debug().
|
||||
Interface("postbody", info).
|
||||
Msg("Got a POST")
|
||||
if info.Password != p.Bot.GetPassword() {
|
||||
w.WriteHeader(http.StatusForbidden)
|
||||
j, _ := json.Marshal(struct{ Err string }{Err: "Invalid Password"})
|
||||
w.Write(j)
|
||||
return
|
||||
}
|
||||
item, err := GetItem(p.DB, info.User, info.Thing)
|
||||
if err != nil {
|
||||
log.Error().
|
||||
|
|
|
@ -27,14 +27,13 @@ var html = `
|
|||
</b-navbar>
|
||||
<b-alert
|
||||
dismissable
|
||||
variant="error"
|
||||
v-if="err"
|
||||
@dismissed="err = ''">
|
||||
:show="err"
|
||||
variant="error">
|
||||
{{ "{{ err }}" }}
|
||||
</b-alert>
|
||||
<b-container>
|
||||
<b-row>
|
||||
<b-col cols="5">Human test: What is {{ "{{ equation }}" }}?</b-col>
|
||||
<b-col cols="5">Password:</b-col>
|
||||
<b-col><b-input v-model="answer"></b-col>
|
||||
</b-row>
|
||||
<b-row v-for="(counter, user) in counters">
|
||||
|
@ -48,8 +47,8 @@ var html = `
|
|||
{{ "{{ count }}" }}
|
||||
</b-col>
|
||||
<b-col cols="2">
|
||||
<button :disabled="!authenticated" @click="subtract(user,thing,count)">-</button>
|
||||
<button :disabled="!authenticated" @click="add(user,thing,count)">+</button>
|
||||
<button @click="subtract(user,thing,count)">-</button>
|
||||
<button @click="add(user,thing,count)">+</button>
|
||||
</b-col>
|
||||
</b-row>
|
||||
</b-container>
|
||||
|
@ -76,56 +75,25 @@ var html = `
|
|||
nav: {{ .Nav }},
|
||||
answer: '',
|
||||
correct: 0,
|
||||
counters: {
|
||||
stk5: {
|
||||
beer: 12,
|
||||
tea: 84,
|
||||
coffee: 127
|
||||
},
|
||||
flyngpngn: {
|
||||
beer: 123,
|
||||
mead: 1,
|
||||
tea: 130
|
||||
}
|
||||
}
|
||||
counters: {}
|
||||
},
|
||||
mounted() {
|
||||
axios.get('/counter/api')
|
||||
.then(resp => (this.counters = convertData(resp.data)))
|
||||
.catch(err => (this.err = err));
|
||||
},
|
||||
computed: {
|
||||
authenticated: function() {
|
||||
if (Number(this.answer) === this.correct)
|
||||
return true;
|
||||
return false;
|
||||
},
|
||||
equation: function() {
|
||||
const x = Math.floor(Math.random() * 100);
|
||||
const y = Math.floor(Math.random() * 100);
|
||||
const z = Math.floor(Math.random() * 100);
|
||||
const ops = ['+', '-', '*'];
|
||||
const op1 = ops[Math.floor(Math.random()*3)];
|
||||
const op2 = ops[Math.floor(Math.random()*3)];
|
||||
const eq = ""+x+op1+y+op2+z;
|
||||
this.correct = eval(eq);
|
||||
return eq
|
||||
}
|
||||
},
|
||||
methods: {
|
||||
add(user, thing, count) {
|
||||
this.counters[user][thing]++;
|
||||
axios.post('/counter/api',
|
||||
{user: user, thing: thing, action: '++'})
|
||||
.then(resp => (this.counters = convertData(resp.data)))
|
||||
.catch(err => (this.err = err));
|
||||
{user: user, thing: thing, action: '++', password: this.answer})
|
||||
.then(resp => {this.counters = convertData(resp.data); this.err = '';})
|
||||
.catch(err => this.err = err);
|
||||
},
|
||||
subtract(user, thing, count) {
|
||||
this.counters[user][thing]--;
|
||||
axios.post('/counter/api',
|
||||
{user: user, thing: thing, action: '--'})
|
||||
.then(resp => (this.counters = convertData(resp.data)))
|
||||
.catch(err => (this.err = err));
|
||||
{user: user, thing: thing, action: '--', password: this.answer})
|
||||
.then(resp => {this.counters = convertData(resp.data); this.err = '';})
|
||||
.catch(err => this.err = err);
|
||||
}
|
||||
}
|
||||
})
|
||||
|
|
Loading…
Reference in New Issue