mirror of https://github.com/velour/catbase.git
apppass: add password generation page
This commit is contained in:
parent
64bce99455
commit
31fe84b0ba
21
bot/bot.go
21
bot/bot.go
|
@ -17,6 +17,7 @@ import (
|
||||||
"github.com/velour/catbase/bot/msglog"
|
"github.com/velour/catbase/bot/msglog"
|
||||||
"github.com/velour/catbase/bot/user"
|
"github.com/velour/catbase/bot/user"
|
||||||
"github.com/velour/catbase/config"
|
"github.com/velour/catbase/config"
|
||||||
|
"golang.org/x/crypto/bcrypt"
|
||||||
)
|
)
|
||||||
|
|
||||||
// bot type provides storage for bot-wide information, configs, and database connections
|
// bot type provides storage for bot-wide information, configs, and database connections
|
||||||
|
@ -370,3 +371,23 @@ func PluginName(p Plugin) string {
|
||||||
t := reflect.TypeOf(p).String()
|
t := reflect.TypeOf(p).String()
|
||||||
return t
|
return t
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func (b *bot) CheckPassword(secret, password string) bool {
|
||||||
|
if b.password == password {
|
||||||
|
return true
|
||||||
|
}
|
||||||
|
parts := strings.SplitN(password, ":", 2)
|
||||||
|
if len(parts) == 2 {
|
||||||
|
secret = parts[0]
|
||||||
|
password = parts[1]
|
||||||
|
}
|
||||||
|
q := `select encoded_pass from apppass where secret = ?`
|
||||||
|
encodedPasswords := [][]byte{}
|
||||||
|
b.DB().Select(&encodedPasswords, q, secret)
|
||||||
|
for _, p := range encodedPasswords {
|
||||||
|
if err := bcrypt.CompareHashAndPassword(p, []byte(password)); err == nil {
|
||||||
|
return true
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return false
|
||||||
|
}
|
||||||
|
|
|
@ -162,6 +162,9 @@ type Bot interface {
|
||||||
|
|
||||||
// Check if a particular plugin is blacklisted
|
// Check if a particular plugin is blacklisted
|
||||||
OnBlacklist(string, string) bool
|
OnBlacklist(string, string) bool
|
||||||
|
|
||||||
|
// Check valid password
|
||||||
|
CheckPassword(secret, password string) bool
|
||||||
}
|
}
|
||||||
|
|
||||||
// Connector represents a server connection to a chat service
|
// Connector represents a server connection to a chat service
|
||||||
|
|
|
@ -123,3 +123,4 @@ func (mb *MockBot) RefreshPluginWhitelist() error { return nil }
|
||||||
func (mb *MockBot) GetWhitelist() []string { return []string{} }
|
func (mb *MockBot) GetWhitelist() []string { return []string{} }
|
||||||
func (mb *MockBot) OnBlacklist(ch, p string) bool { return false }
|
func (mb *MockBot) OnBlacklist(ch, p string) bool { return false }
|
||||||
func (mb *MockBot) URLFormat(title, url string) string { return title + url }
|
func (mb *MockBot) URLFormat(title, url string) string { return title + url }
|
||||||
|
func (mb *MockBot) CheckPassword(secret, password string) bool { return true }
|
||||||
|
|
|
@ -54,7 +54,7 @@ var rootIndex = `
|
||||||
<script src="https://unpkg.com/vue-router"></script>
|
<script src="https://unpkg.com/vue-router"></script>
|
||||||
<script src="https://unpkg.com/axios/dist/axios.min.js"></script>
|
<script src="https://unpkg.com/axios/dist/axios.min.js"></script>
|
||||||
<meta charset="UTF-8">
|
<meta charset="UTF-8">
|
||||||
<title>Factoids</title>
|
<title>catbase</title>
|
||||||
</head>
|
</head>
|
||||||
<body>
|
<body>
|
||||||
|
|
||||||
|
|
2
go.mod
2
go.mod
|
@ -16,7 +16,6 @@ require (
|
||||||
github.com/azr/backoff v0.0.0-20160115115103-53511d3c7330 // indirect
|
github.com/azr/backoff v0.0.0-20160115115103-53511d3c7330 // indirect
|
||||||
github.com/bwmarrin/discordgo v0.22.0
|
github.com/bwmarrin/discordgo v0.22.0
|
||||||
github.com/cdipaolo/goml v0.0.0-20190412180403-e1f51f713598
|
github.com/cdipaolo/goml v0.0.0-20190412180403-e1f51f713598
|
||||||
github.com/chrissexton/gofuck v1.0.0
|
|
||||||
github.com/chrissexton/leftpad v0.0.0-20181207133115-1e93189d2fff
|
github.com/chrissexton/leftpad v0.0.0-20181207133115-1e93189d2fff
|
||||||
github.com/chrissexton/sentiment v0.0.0-20190927141846-d69c422ba035
|
github.com/chrissexton/sentiment v0.0.0-20190927141846-d69c422ba035
|
||||||
github.com/dustin/go-jsonpointer v0.0.0-20160814072949-ba0abeacc3dc // indirect
|
github.com/dustin/go-jsonpointer v0.0.0-20160814072949-ba0abeacc3dc // indirect
|
||||||
|
@ -60,6 +59,7 @@ require (
|
||||||
github.com/ttacon/libphonenumber v1.1.0 // indirect
|
github.com/ttacon/libphonenumber v1.1.0 // indirect
|
||||||
github.com/velour/chat v0.0.0-20180713122344-fd1d1606cb89
|
github.com/velour/chat v0.0.0-20180713122344-fd1d1606cb89
|
||||||
github.com/velour/velour v0.0.0-20160303155839-8e090e68d158
|
github.com/velour/velour v0.0.0-20160303155839-8e090e68d158
|
||||||
|
golang.org/x/crypto v0.0.0-20190510104115-cbcb75029529
|
||||||
golang.org/x/exp v0.0.0-20191014171548-69215a2ee97e // indirect
|
golang.org/x/exp v0.0.0-20191014171548-69215a2ee97e // indirect
|
||||||
golang.org/x/net v0.0.0-20191014212845-da9a3fd4c582 // indirect
|
golang.org/x/net v0.0.0-20191014212845-da9a3fd4c582 // indirect
|
||||||
gonum.org/v1/gonum v0.6.0 // indirect
|
gonum.org/v1/gonum v0.6.0 // indirect
|
||||||
|
|
11
go.sum
11
go.sum
|
@ -1,7 +1,6 @@
|
||||||
code.chrissexton.org/cws/getaoc v0.0.0-20191201043947-d5417d4b618d h1:XS13tP+cMAvXYHQiYqcst64wQ854pueMRZSU4+6puU4=
|
code.chrissexton.org/cws/getaoc v0.0.0-20191201043947-d5417d4b618d h1:XS13tP+cMAvXYHQiYqcst64wQ854pueMRZSU4+6puU4=
|
||||||
code.chrissexton.org/cws/getaoc v0.0.0-20191201043947-d5417d4b618d/go.mod h1:rEpfJR9MplF2TUj2Oy+u4XAaLve2kwB8I2zlzeIQxl8=
|
code.chrissexton.org/cws/getaoc v0.0.0-20191201043947-d5417d4b618d/go.mod h1:rEpfJR9MplF2TUj2Oy+u4XAaLve2kwB8I2zlzeIQxl8=
|
||||||
dmitri.shuralyov.com/gpu/mtl v0.0.0-20190408044501-666a987793e9/go.mod h1:H6x//7gZCb22OMCxBHrMx7a5I7Hp++hsVxbQ4BYO7hU=
|
dmitri.shuralyov.com/gpu/mtl v0.0.0-20190408044501-666a987793e9/go.mod h1:H6x//7gZCb22OMCxBHrMx7a5I7Hp++hsVxbQ4BYO7hU=
|
||||||
github.com/AlekSi/pointer v1.0.0 h1:KWCWzsvFxNLcmM5XmiqHsGTTsuwZMsLFwWF9Y+//bNE=
|
|
||||||
github.com/AlekSi/pointer v1.0.0/go.mod h1:1kjywbfcPFCmncIxtk6fIEub6LKrfMz3gc5QKVOSOA8=
|
github.com/AlekSi/pointer v1.0.0/go.mod h1:1kjywbfcPFCmncIxtk6fIEub6LKrfMz3gc5QKVOSOA8=
|
||||||
github.com/AlekSi/pointer v1.1.0 h1:SSDMPcXD9jSl8FPy9cRzoRaMJtm9g9ggGTxecRUbQoI=
|
github.com/AlekSi/pointer v1.1.0 h1:SSDMPcXD9jSl8FPy9cRzoRaMJtm9g9ggGTxecRUbQoI=
|
||||||
github.com/AlekSi/pointer v1.1.0/go.mod h1:y7BvfRI3wXPWKXEBhU71nbnIEEZX0QTSB2Bj48UJIZE=
|
github.com/AlekSi/pointer v1.1.0/go.mod h1:y7BvfRI3wXPWKXEBhU71nbnIEEZX0QTSB2Bj48UJIZE=
|
||||||
|
@ -13,7 +12,6 @@ github.com/ChimeraCoder/tokenbucket v0.0.0-20131201223612-c5a927568de7/go.mod h1
|
||||||
github.com/PuerkitoBio/goquery v1.5.0 h1:uGvmFXOA73IKluu/F84Xd1tt/z07GYm8X49XKHP7EJk=
|
github.com/PuerkitoBio/goquery v1.5.0 h1:uGvmFXOA73IKluu/F84Xd1tt/z07GYm8X49XKHP7EJk=
|
||||||
github.com/PuerkitoBio/goquery v1.5.0/go.mod h1:qD2PgZ9lccMbQlc7eEOjaeRlFQON7xY8kdmcsrnKqMg=
|
github.com/PuerkitoBio/goquery v1.5.0/go.mod h1:qD2PgZ9lccMbQlc7eEOjaeRlFQON7xY8kdmcsrnKqMg=
|
||||||
github.com/ajstarks/svgo v0.0.0-20180226025133-644b8db467af/go.mod h1:K08gAheRH3/J6wwsYMMT4xOr94bZjxIelGM0+d/wbFw=
|
github.com/ajstarks/svgo v0.0.0-20180226025133-644b8db467af/go.mod h1:K08gAheRH3/J6wwsYMMT4xOr94bZjxIelGM0+d/wbFw=
|
||||||
github.com/andybalholm/cascadia v1.0.0 h1:hOCXnnZ5A+3eVDX8pvgl4kofXv2ELss0bKcqRySc45o=
|
|
||||||
github.com/andybalholm/cascadia v1.0.0/go.mod h1:GsXiBklL0woXo1j/WYWtSYYC4ouU9PqHO0sqidkEA4Y=
|
github.com/andybalholm/cascadia v1.0.0/go.mod h1:GsXiBklL0woXo1j/WYWtSYYC4ouU9PqHO0sqidkEA4Y=
|
||||||
github.com/andybalholm/cascadia v1.1.0 h1:BuuO6sSfQNFRu1LppgbD25Hr2vLYW25JvxHs5zzsLTo=
|
github.com/andybalholm/cascadia v1.1.0 h1:BuuO6sSfQNFRu1LppgbD25Hr2vLYW25JvxHs5zzsLTo=
|
||||||
github.com/andybalholm/cascadia v1.1.0/go.mod h1:GsXiBklL0woXo1j/WYWtSYYC4ouU9PqHO0sqidkEA4Y=
|
github.com/andybalholm/cascadia v1.1.0/go.mod h1:GsXiBklL0woXo1j/WYWtSYYC4ouU9PqHO0sqidkEA4Y=
|
||||||
|
@ -31,8 +29,6 @@ github.com/bwmarrin/discordgo v0.22.0 h1:uBxY1HmlVCsW1IuaPjpCGT6A2DBwRn0nvOguQIx
|
||||||
github.com/bwmarrin/discordgo v0.22.0/go.mod h1:c1WtWUGN6nREDmzIpyTp/iD3VYt4Fpx+bVyfBG7JE+M=
|
github.com/bwmarrin/discordgo v0.22.0/go.mod h1:c1WtWUGN6nREDmzIpyTp/iD3VYt4Fpx+bVyfBG7JE+M=
|
||||||
github.com/cdipaolo/goml v0.0.0-20190412180403-e1f51f713598 h1:j2XRGH5Y5uWtBYXGwmrjKeM/kfu/jh7ZcnrGvyN5Ttk=
|
github.com/cdipaolo/goml v0.0.0-20190412180403-e1f51f713598 h1:j2XRGH5Y5uWtBYXGwmrjKeM/kfu/jh7ZcnrGvyN5Ttk=
|
||||||
github.com/cdipaolo/goml v0.0.0-20190412180403-e1f51f713598/go.mod h1:sduMkaHcXDIWurl/Bd/z0rNEUHw5tr6LUA9IO8E9o0o=
|
github.com/cdipaolo/goml v0.0.0-20190412180403-e1f51f713598/go.mod h1:sduMkaHcXDIWurl/Bd/z0rNEUHw5tr6LUA9IO8E9o0o=
|
||||||
github.com/chrissexton/gofuck v1.0.0 h1:vxg/tIfI2HunJOErSotmMqMRNfLRVO+BTjSKpFoAizA=
|
|
||||||
github.com/chrissexton/gofuck v1.0.0/go.mod h1:voOFh7xp5oNB4N516blAUT0Vh2JQq/cFX9autdChv9o=
|
|
||||||
github.com/chrissexton/leftpad v0.0.0-20181207133115-1e93189d2fff h1:+TEqaP0eO1unI7XHHFeMDhsxhLDIb0x8KYuZbqbAmxA=
|
github.com/chrissexton/leftpad v0.0.0-20181207133115-1e93189d2fff h1:+TEqaP0eO1unI7XHHFeMDhsxhLDIb0x8KYuZbqbAmxA=
|
||||||
github.com/chrissexton/leftpad v0.0.0-20181207133115-1e93189d2fff/go.mod h1:QCRjR0b4qiJiNjuP7RFM89bh4UExGJalcWmYeSvlnRc=
|
github.com/chrissexton/leftpad v0.0.0-20181207133115-1e93189d2fff/go.mod h1:QCRjR0b4qiJiNjuP7RFM89bh4UExGJalcWmYeSvlnRc=
|
||||||
github.com/chrissexton/sentiment v0.0.0-20190927141846-d69c422ba035 h1:3+eJGFTbUgOMDCpa8PTmJABs1Z3EDHRrcz6d3oXfZm0=
|
github.com/chrissexton/sentiment v0.0.0-20190927141846-d69c422ba035 h1:3+eJGFTbUgOMDCpa8PTmJABs1Z3EDHRrcz6d3oXfZm0=
|
||||||
|
@ -73,7 +69,6 @@ github.com/gonum/internal v0.0.0-20181124074243-f884aa714029/go.mod h1:Pu4dmpkhS
|
||||||
github.com/google/go-cmp v0.5.4/go.mod h1:v8dTdLbMG2kIc/vJvl+f65V22dbkXbowE6jgT/gNBxE=
|
github.com/google/go-cmp v0.5.4/go.mod h1:v8dTdLbMG2kIc/vJvl+f65V22dbkXbowE6jgT/gNBxE=
|
||||||
github.com/google/uuid v1.1.1 h1:Gkbcsh/GbpXz7lPftLA3P6TYMwjCLYm83jiFQZF/3gY=
|
github.com/google/uuid v1.1.1 h1:Gkbcsh/GbpXz7lPftLA3P6TYMwjCLYm83jiFQZF/3gY=
|
||||||
github.com/google/uuid v1.1.1/go.mod h1:TIyPZe4MgqvfeYDBFedMoGGpEw/LqOeaOT+nhxU+yHo=
|
github.com/google/uuid v1.1.1/go.mod h1:TIyPZe4MgqvfeYDBFedMoGGpEw/LqOeaOT+nhxU+yHo=
|
||||||
github.com/gorilla/websocket v1.4.0 h1:WDFjx/TMzVgy9VdMMQi2K2Emtwi2QcUQsztZ/zLaH/Q=
|
|
||||||
github.com/gorilla/websocket v1.4.0/go.mod h1:E7qHFY5m1UJ88s3WnNqhKjPHQ0heANvMoAMk2YaljkQ=
|
github.com/gorilla/websocket v1.4.0/go.mod h1:E7qHFY5m1UJ88s3WnNqhKjPHQ0heANvMoAMk2YaljkQ=
|
||||||
github.com/gorilla/websocket v1.4.2 h1:+/TMaTYc4QFitKJxsQ7Yye35DkWvkdLcvGKqM+x0Ufc=
|
github.com/gorilla/websocket v1.4.2 h1:+/TMaTYc4QFitKJxsQ7Yye35DkWvkdLcvGKqM+x0Ufc=
|
||||||
github.com/gorilla/websocket v1.4.2/go.mod h1:YR8l580nyteQvAITg2hZ9XVh4b55+EU/adAjf1fMHhE=
|
github.com/gorilla/websocket v1.4.2/go.mod h1:YR8l580nyteQvAITg2hZ9XVh4b55+EU/adAjf1fMHhE=
|
||||||
|
@ -120,7 +115,6 @@ github.com/nfnt/resize v0.0.0-20180221191011-83c6a9932646/go.mod h1:jpp1/29i3P1S
|
||||||
github.com/olebedev/when v0.0.0-20190311101825-c3b538a97254 h1:JYoQR67E1vv1WGoeW8DkdFs7vrIEe/5wP+qJItd5tUE=
|
github.com/olebedev/when v0.0.0-20190311101825-c3b538a97254 h1:JYoQR67E1vv1WGoeW8DkdFs7vrIEe/5wP+qJItd5tUE=
|
||||||
github.com/olebedev/when v0.0.0-20190311101825-c3b538a97254/go.mod h1:DPucAeQGDPUzYUt+NaWw6qsF5SFapWWToxEiVDh2aV0=
|
github.com/olebedev/when v0.0.0-20190311101825-c3b538a97254/go.mod h1:DPucAeQGDPUzYUt+NaWw6qsF5SFapWWToxEiVDh2aV0=
|
||||||
github.com/pkg/errors v0.8.0/go.mod h1:bwawxfHBFNV+L2hUp1rHADufV3IMtnDRdf1r5NINEl0=
|
github.com/pkg/errors v0.8.0/go.mod h1:bwawxfHBFNV+L2hUp1rHADufV3IMtnDRdf1r5NINEl0=
|
||||||
github.com/pkg/errors v0.8.1 h1:iURUrRGxPUNPdy5/HRSm+Yj6okJ6UtLINN0Q9M4+h3I=
|
|
||||||
github.com/pkg/errors v0.8.1/go.mod h1:bwawxfHBFNV+L2hUp1rHADufV3IMtnDRdf1r5NINEl0=
|
github.com/pkg/errors v0.8.1/go.mod h1:bwawxfHBFNV+L2hUp1rHADufV3IMtnDRdf1r5NINEl0=
|
||||||
github.com/pkg/errors v0.9.1 h1:FEBLx1zS214owpjy7qsBeixbURkuhQAwrK5UwLGTwt4=
|
github.com/pkg/errors v0.9.1 h1:FEBLx1zS214owpjy7qsBeixbURkuhQAwrK5UwLGTwt4=
|
||||||
github.com/pkg/errors v0.9.1/go.mod h1:bwawxfHBFNV+L2hUp1rHADufV3IMtnDRdf1r5NINEl0=
|
github.com/pkg/errors v0.9.1/go.mod h1:bwawxfHBFNV+L2hUp1rHADufV3IMtnDRdf1r5NINEl0=
|
||||||
|
@ -137,7 +131,6 @@ github.com/slack-go/slack v0.7.2 h1:oLy2a2YqrtoHSSxbjRhrtLDGbCKcZJwgbuQ826BWxaI=
|
||||||
github.com/slack-go/slack v0.7.2/go.mod h1:FGqNzJBmxIsZURAxh2a8D21AnOVvvXZvGligs4npPUM=
|
github.com/slack-go/slack v0.7.2/go.mod h1:FGqNzJBmxIsZURAxh2a8D21AnOVvvXZvGligs4npPUM=
|
||||||
github.com/spaolacci/murmur3 v1.1.0 h1:7c1g84S4BPRrfL5Xrdp6fOJ206sU9y293DDHaoy0bLI=
|
github.com/spaolacci/murmur3 v1.1.0 h1:7c1g84S4BPRrfL5Xrdp6fOJ206sU9y293DDHaoy0bLI=
|
||||||
github.com/spaolacci/murmur3 v1.1.0/go.mod h1:JwIasOWyU6f++ZhiEuf87xNszmSA2myDM2Kzu9HwQUA=
|
github.com/spaolacci/murmur3 v1.1.0/go.mod h1:JwIasOWyU6f++ZhiEuf87xNszmSA2myDM2Kzu9HwQUA=
|
||||||
github.com/stretchr/objx v0.1.0 h1:4G4v2dO3VZwixGIRoQ5Lfboy6nUhCyYzaqnIAPPhYs4=
|
|
||||||
github.com/stretchr/objx v0.1.0/go.mod h1:HFkY916IF+rwdDfMAkV7OtwuqBVzrE8GR6GFx+wExME=
|
github.com/stretchr/objx v0.1.0/go.mod h1:HFkY916IF+rwdDfMAkV7OtwuqBVzrE8GR6GFx+wExME=
|
||||||
github.com/stretchr/objx v0.2.0 h1:Hbg2NidpLE8veEBkEZTL3CvlkUIVzuU9jDplZO54c48=
|
github.com/stretchr/objx v0.2.0 h1:Hbg2NidpLE8veEBkEZTL3CvlkUIVzuU9jDplZO54c48=
|
||||||
github.com/stretchr/objx v0.2.0/go.mod h1:qt09Ya8vawLte6SNmTgCsAVtYtaKzEcn8ATUoHMkEqE=
|
github.com/stretchr/objx v0.2.0/go.mod h1:qt09Ya8vawLte6SNmTgCsAVtYtaKzEcn8ATUoHMkEqE=
|
||||||
|
@ -176,11 +169,9 @@ golang.org/x/mobile v0.0.0-20190719004257-d2bd2a29d028/go.mod h1:E/iHnbuqvinMTCc
|
||||||
golang.org/x/mod v0.1.0/go.mod h1:0QHyrYULN0/3qlju5TqG8bIK38QM8yzMo5ekMj3DlcY=
|
golang.org/x/mod v0.1.0/go.mod h1:0QHyrYULN0/3qlju5TqG8bIK38QM8yzMo5ekMj3DlcY=
|
||||||
golang.org/x/net v0.0.0-20180218175443-cbe0f9307d01/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4=
|
golang.org/x/net v0.0.0-20180218175443-cbe0f9307d01/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4=
|
||||||
golang.org/x/net v0.0.0-20181114220301-adae6a3d119a/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4=
|
golang.org/x/net v0.0.0-20181114220301-adae6a3d119a/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4=
|
||||||
golang.org/x/net v0.0.0-20190311183353-d8887717615a h1:oWX7TPOiFAMXLq8o0ikBYfCJVlRHBcsciT5bXOrH628=
|
|
||||||
golang.org/x/net v0.0.0-20190311183353-d8887717615a/go.mod h1:t9HGtf8HONx5eT2rtn7q6eTqICYqUVnKs3thJo3Qplg=
|
golang.org/x/net v0.0.0-20190311183353-d8887717615a/go.mod h1:t9HGtf8HONx5eT2rtn7q6eTqICYqUVnKs3thJo3Qplg=
|
||||||
golang.org/x/net v0.0.0-20190404232315-eb5bcb51f2a3/go.mod h1:t9HGtf8HONx5eT2rtn7q6eTqICYqUVnKs3thJo3Qplg=
|
golang.org/x/net v0.0.0-20190404232315-eb5bcb51f2a3/go.mod h1:t9HGtf8HONx5eT2rtn7q6eTqICYqUVnKs3thJo3Qplg=
|
||||||
golang.org/x/net v0.0.0-20190603091049-60506f45cf65/go.mod h1:HSz+uSET+XFnRR8LxR5pz3Of3rY3CfYBVs4xY44aLks=
|
golang.org/x/net v0.0.0-20190603091049-60506f45cf65/go.mod h1:HSz+uSET+XFnRR8LxR5pz3Of3rY3CfYBVs4xY44aLks=
|
||||||
golang.org/x/net v0.0.0-20190620200207-3b0461eec859 h1:R/3boaszxrf1GEUWTVDzSKVwLmSJpwZ1yqXm8j0v2QI=
|
|
||||||
golang.org/x/net v0.0.0-20190620200207-3b0461eec859/go.mod h1:z5CRVTTTmAJ677TzLLGU+0bjPO0LkuOLi4/5GtJWs/s=
|
golang.org/x/net v0.0.0-20190620200207-3b0461eec859/go.mod h1:z5CRVTTTmAJ677TzLLGU+0bjPO0LkuOLi4/5GtJWs/s=
|
||||||
golang.org/x/net v0.0.0-20191014212845-da9a3fd4c582 h1:p9xBe/w/OzkeYVKm234g55gMdD1nSIooTir5kV11kfA=
|
golang.org/x/net v0.0.0-20191014212845-da9a3fd4c582 h1:p9xBe/w/OzkeYVKm234g55gMdD1nSIooTir5kV11kfA=
|
||||||
golang.org/x/net v0.0.0-20191014212845-da9a3fd4c582/go.mod h1:z5CRVTTTmAJ677TzLLGU+0bjPO0LkuOLi4/5GtJWs/s=
|
golang.org/x/net v0.0.0-20191014212845-da9a3fd4c582/go.mod h1:z5CRVTTTmAJ677TzLLGU+0bjPO0LkuOLi4/5GtJWs/s=
|
||||||
|
@ -191,7 +182,6 @@ golang.org/x/sys v0.0.0-20190312061237-fead79001313/go.mod h1:h1NjWce9XRLGQEsW7w
|
||||||
golang.org/x/sys v0.0.0-20190412213103-97732733099d/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
|
golang.org/x/sys v0.0.0-20190412213103-97732733099d/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
|
||||||
golang.org/x/sys v0.0.0-20200116001909-b77594299b42/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
|
golang.org/x/sys v0.0.0-20200116001909-b77594299b42/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
|
||||||
golang.org/x/sys v0.0.0-20200212091648-12a6c2dcc1e4/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
|
golang.org/x/sys v0.0.0-20200212091648-12a6c2dcc1e4/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
|
||||||
golang.org/x/sys v0.0.0-20200223170610-d5e6a3e2c0ae h1:/WDfKMnPU+m5M4xB+6x4kaepxRw6jWvR5iDRdvjHgy8=
|
|
||||||
golang.org/x/sys v0.0.0-20200223170610-d5e6a3e2c0ae/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
|
golang.org/x/sys v0.0.0-20200223170610-d5e6a3e2c0ae/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
|
||||||
golang.org/x/sys v0.0.0-20210301091718-77cc2087c03b h1:kHlr0tATeLRMEiZJu5CknOw/E8V6h69sXXQFGoPtjcc=
|
golang.org/x/sys v0.0.0-20210301091718-77cc2087c03b h1:kHlr0tATeLRMEiZJu5CknOw/E8V6h69sXXQFGoPtjcc=
|
||||||
golang.org/x/sys v0.0.0-20210301091718-77cc2087c03b/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
|
golang.org/x/sys v0.0.0-20210301091718-77cc2087c03b/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
|
||||||
|
@ -219,7 +209,6 @@ gopkg.in/go-playground/webhooks.v5 v5.13.0 h1:e9vtkQZK464+UdL3YjRox2yR8JSmh2094P
|
||||||
gopkg.in/go-playground/webhooks.v5 v5.13.0/go.mod h1:LZbya/qLVdbqDR1aKrGuWV6qbia2zCYSR5dpom2SInQ=
|
gopkg.in/go-playground/webhooks.v5 v5.13.0/go.mod h1:LZbya/qLVdbqDR1aKrGuWV6qbia2zCYSR5dpom2SInQ=
|
||||||
gopkg.in/sourcemap.v1 v1.0.5 h1:inv58fC9f9J3TK2Y2R1NPntXEn3/wjWHkonhIUODNTI=
|
gopkg.in/sourcemap.v1 v1.0.5 h1:inv58fC9f9J3TK2Y2R1NPntXEn3/wjWHkonhIUODNTI=
|
||||||
gopkg.in/sourcemap.v1 v1.0.5/go.mod h1:2RlvNNSMglmRrcvhfuzp4hQHwOtjxlbjX7UPY/GXb78=
|
gopkg.in/sourcemap.v1 v1.0.5/go.mod h1:2RlvNNSMglmRrcvhfuzp4hQHwOtjxlbjX7UPY/GXb78=
|
||||||
gopkg.in/yaml.v2 v2.2.2 h1:ZCJp+EgiOT7lHqUV2J862kp8Qj64Jo6az82+3Td9dZw=
|
|
||||||
gopkg.in/yaml.v2 v2.2.2/go.mod h1:hI93XBmqTisBFMUTm0b8Fm+jr3Dg1NNxqwp+5A1VGuI=
|
gopkg.in/yaml.v2 v2.2.2/go.mod h1:hI93XBmqTisBFMUTm0b8Fm+jr3Dg1NNxqwp+5A1VGuI=
|
||||||
gopkg.in/yaml.v2 v2.2.4 h1:/eiJrUcujPVeJ3xlSWaiNi3uSVmDGBK1pDHUHAnao1I=
|
gopkg.in/yaml.v2 v2.2.4 h1:/eiJrUcujPVeJ3xlSWaiNi3uSVmDGBK1pDHUHAnao1I=
|
||||||
gopkg.in/yaml.v2 v2.2.4/go.mod h1:hI93XBmqTisBFMUTm0b8Fm+jr3Dg1NNxqwp+5A1VGuI=
|
gopkg.in/yaml.v2 v2.2.4/go.mod h1:hI93XBmqTisBFMUTm0b8Fm+jr3Dg1NNxqwp+5A1VGuI=
|
||||||
|
|
|
@ -3,9 +3,7 @@
|
||||||
package admin
|
package admin
|
||||||
|
|
||||||
import (
|
import (
|
||||||
"encoding/json"
|
|
||||||
"fmt"
|
"fmt"
|
||||||
"net/http"
|
|
||||||
"os"
|
"os"
|
||||||
"regexp"
|
"regexp"
|
||||||
"strings"
|
"strings"
|
||||||
|
@ -38,6 +36,8 @@ func New(b bot.Bot) *AdminPlugin {
|
||||||
cfg: b.Config(),
|
cfg: b.Config(),
|
||||||
}
|
}
|
||||||
|
|
||||||
|
p.mkDB()
|
||||||
|
|
||||||
b.RegisterRegex(p, bot.Message, comeBackRegex, p.comeBackCmd)
|
b.RegisterRegex(p, bot.Message, comeBackRegex, p.comeBackCmd)
|
||||||
b.RegisterRegexCmd(p, bot.Message, shutupRegex, p.shutupCmd)
|
b.RegisterRegexCmd(p, bot.Message, shutupRegex, p.shutupCmd)
|
||||||
b.RegisterRegexCmd(p, bot.Message, addBlacklistRegex, p.isAdmin(p.addBlacklistCmd))
|
b.RegisterRegexCmd(p, bot.Message, addBlacklistRegex, p.isAdmin(p.addBlacklistCmd))
|
||||||
|
@ -72,6 +72,16 @@ var forbiddenKeys = map[string]bool{
|
||||||
"meme.memes": true,
|
"meme.memes": true,
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func (p *AdminPlugin) mkDB() {
|
||||||
|
q := `create table if not exists apppass (
|
||||||
|
id integer primary key autoincrement,
|
||||||
|
secret string not null,
|
||||||
|
encoded_pass string not null,
|
||||||
|
cost integer default 10
|
||||||
|
)`
|
||||||
|
p.db.MustExec(q)
|
||||||
|
}
|
||||||
|
|
||||||
var shutupRegex = regexp.MustCompile(`(?i)^shut up$`)
|
var shutupRegex = regexp.MustCompile(`(?i)^shut up$`)
|
||||||
var comeBackRegex = regexp.MustCompile(`(?i)^come back$`)
|
var comeBackRegex = regexp.MustCompile(`(?i)^come back$`)
|
||||||
|
|
||||||
|
@ -351,42 +361,6 @@ func (p *AdminPlugin) help(conn bot.Connector, kind bot.Kind, m msg.Message, arg
|
||||||
return true
|
return true
|
||||||
}
|
}
|
||||||
|
|
||||||
func (p *AdminPlugin) registerWeb() {
|
|
||||||
http.HandleFunc("/vars/api", p.handleWebAPI)
|
|
||||||
http.HandleFunc("/vars", p.handleWeb)
|
|
||||||
p.bot.RegisterWeb("/vars", "Variables")
|
|
||||||
}
|
|
||||||
|
|
||||||
func (p *AdminPlugin) handleWeb(w http.ResponseWriter, r *http.Request) {
|
|
||||||
fmt.Fprint(w, varIndex)
|
|
||||||
}
|
|
||||||
|
|
||||||
func (p *AdminPlugin) handleWebAPI(w http.ResponseWriter, r *http.Request) {
|
|
||||||
var configEntries []struct {
|
|
||||||
Key string `json:"key"`
|
|
||||||
Value string `json:"value"`
|
|
||||||
}
|
|
||||||
q := `select key, value from config`
|
|
||||||
err := p.db.Select(&configEntries, q)
|
|
||||||
if err != nil {
|
|
||||||
log.Error().
|
|
||||||
Err(err).
|
|
||||||
Msg("Error getting config entries.")
|
|
||||||
w.WriteHeader(500)
|
|
||||||
fmt.Fprint(w, err)
|
|
||||||
return
|
|
||||||
}
|
|
||||||
for i, e := range configEntries {
|
|
||||||
if strings.Contains(e.Value, ";;") {
|
|
||||||
e.Value = strings.ReplaceAll(e.Value, ";;", ", ")
|
|
||||||
e.Value = fmt.Sprintf("[%s]", e.Value)
|
|
||||||
configEntries[i] = e
|
|
||||||
}
|
|
||||||
}
|
|
||||||
j, _ := json.Marshal(configEntries)
|
|
||||||
fmt.Fprintf(w, "%s", j)
|
|
||||||
}
|
|
||||||
|
|
||||||
func (p *AdminPlugin) addWhitelist(plugin string) error {
|
func (p *AdminPlugin) addWhitelist(plugin string) error {
|
||||||
return p.modList(`insert or replace into pluginWhitelist values (?)`, "", plugin)
|
return p.modList(`insert or replace into pluginWhitelist values (?)`, "", plugin)
|
||||||
}
|
}
|
||||||
|
|
|
@ -78,3 +78,164 @@ var varIndex = `
|
||||||
</body>
|
</body>
|
||||||
</html>
|
</html>
|
||||||
`
|
`
|
||||||
|
|
||||||
|
var apppassIndex = `
|
||||||
|
<!DOCTYPE html>
|
||||||
|
<!DOCTYPE html>
|
||||||
|
<html lang="en">
|
||||||
|
<head>
|
||||||
|
<!-- Load required Bootstrap and BootstrapVue CSS -->
|
||||||
|
<link type="text/css" rel="stylesheet" href="//unpkg.com/bootstrap/dist/css/bootstrap.min.css"/>
|
||||||
|
<link type="text/css" rel="stylesheet" href="//unpkg.com/bootstrap-vue@latest/dist/bootstrap-vue.min.css"/>
|
||||||
|
|
||||||
|
<!-- Load polyfills to support older browsers -->
|
||||||
|
<script src="//polyfill.io/v3/polyfill.min.js?features=es2015%2CMutationObserver"></script>
|
||||||
|
|
||||||
|
<!-- Load Vue followed by BootstrapVue -->
|
||||||
|
<script src="//unpkg.com/vue@latest/dist/vue.min.js"></script>
|
||||||
|
<script src="//unpkg.com/bootstrap-vue@latest/dist/bootstrap-vue.min.js"></script>
|
||||||
|
<script src="//unpkg.com/axios/dist/axios.min.js"></script>
|
||||||
|
<meta charset="UTF-8">
|
||||||
|
<title>Vars</title>
|
||||||
|
</head>
|
||||||
|
<body>
|
||||||
|
|
||||||
|
<div id="app">
|
||||||
|
<b-navbar>
|
||||||
|
<b-navbar-brand>App Pass</b-navbar-brand>
|
||||||
|
<b-navbar-nav>
|
||||||
|
<b-nav-item v-for="item in nav" :href="item.url" :active="item.name === 'App Pass'">{{ item.name }}
|
||||||
|
</b-nav-item>
|
||||||
|
</b-navbar-nav>
|
||||||
|
</b-navbar>
|
||||||
|
<div class="alert alert-warning alert-dismissible fade show" role="alert" v-if="err != ''">
|
||||||
|
<b-button type="link" class="close" data-dismiss="alert" aria-label="Close" @click="err = ''">
|
||||||
|
<span aria-hidden="true">×</span>
|
||||||
|
</b-button>
|
||||||
|
{{ err }}
|
||||||
|
</div>
|
||||||
|
<b-form>
|
||||||
|
<b-container>
|
||||||
|
<b-row>
|
||||||
|
<b-col cols="5">Password:</b-col>
|
||||||
|
<b-col>
|
||||||
|
<b-input v-model="password"/>
|
||||||
|
</b-col>
|
||||||
|
</b-row>
|
||||||
|
<b-row>
|
||||||
|
<b-col cols="5">Secret:</b-col>
|
||||||
|
<b-col>
|
||||||
|
<b-input v-model="entry.secret"/>
|
||||||
|
</b-col>
|
||||||
|
</b-row>
|
||||||
|
<b-row>
|
||||||
|
<b-col>
|
||||||
|
<b-button @click="list">List</b-button>
|
||||||
|
</b-col>
|
||||||
|
<b-col>
|
||||||
|
<b-button @click="newPass">New</b-button>
|
||||||
|
</b-col>
|
||||||
|
</b-row>
|
||||||
|
</b-container>
|
||||||
|
</b-form>
|
||||||
|
<b-container v-show="showPassword" style="padding: 2em">
|
||||||
|
<b-row align-h="center">
|
||||||
|
<b-col align-self="center" cols="1">ID:</b-col>
|
||||||
|
<b-col align-self="center" cols="3">{{ entry.id }}</b-col>
|
||||||
|
</b-row>
|
||||||
|
<b-row align-h="center">
|
||||||
|
<b-col align-self="center" cols="1">Password:</b-col>
|
||||||
|
<b-col align-self="center" cols="3">{{ entry.secret }}:{{ showPassword }}</b-col>
|
||||||
|
</b-row>
|
||||||
|
<b-row align-h="center">
|
||||||
|
<b-col align-self="center" class="text-center" cols="6">Note: this password will only be displayed once. For single-field entry passwords, use the secret:password format.</b-col>
|
||||||
|
</b-row>
|
||||||
|
</b-container>
|
||||||
|
<b-container>
|
||||||
|
<b-row style="padding-top: 2em;">
|
||||||
|
<b-col>
|
||||||
|
<ul>
|
||||||
|
<li v-for="entry in entries" key="id">
|
||||||
|
<a @click="rm(entry)" href="#">X</a> {{entry.id}}</li>
|
||||||
|
</ul>
|
||||||
|
</b-col>
|
||||||
|
</b-row>
|
||||||
|
</b-container>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<script>
|
||||||
|
var app = new Vue({
|
||||||
|
el: '#app',
|
||||||
|
data: {
|
||||||
|
err: '',
|
||||||
|
entry: {
|
||||||
|
secret: '',
|
||||||
|
},
|
||||||
|
password: '',
|
||||||
|
showPassword: '',
|
||||||
|
nav: [],
|
||||||
|
entries: [],
|
||||||
|
},
|
||||||
|
mounted() {
|
||||||
|
axios.get('/nav')
|
||||||
|
.then(resp => {
|
||||||
|
this.nav = resp.data;
|
||||||
|
})
|
||||||
|
.catch(err => console.log(err))
|
||||||
|
},
|
||||||
|
methods: {
|
||||||
|
rm: function (data) {
|
||||||
|
this.showPassword = '';
|
||||||
|
this.entry.id = data.id
|
||||||
|
axios.delete('/apppass/api', {
|
||||||
|
data: {
|
||||||
|
password: this.password,
|
||||||
|
passEntry: this.entry
|
||||||
|
}
|
||||||
|
})
|
||||||
|
.then(() => {
|
||||||
|
this.getData()
|
||||||
|
})
|
||||||
|
.catch(({response}) => {
|
||||||
|
console.log('error: ' + response.data.err)
|
||||||
|
this.err = response.data.err
|
||||||
|
})
|
||||||
|
},
|
||||||
|
list: function () {
|
||||||
|
this.showPassword = '';
|
||||||
|
this.getData();
|
||||||
|
},
|
||||||
|
newPass: function () {
|
||||||
|
axios.put('/apppass/api', {
|
||||||
|
password: this.password,
|
||||||
|
passEntry: this.entry
|
||||||
|
})
|
||||||
|
.then(resp => {
|
||||||
|
this.getData()
|
||||||
|
this.showPassword = resp.data.pass
|
||||||
|
this.entry.id = resp.data.id
|
||||||
|
})
|
||||||
|
.catch(({response}) => {
|
||||||
|
console.log('error: ' + response.data.err)
|
||||||
|
this.err = response.data.err
|
||||||
|
})
|
||||||
|
},
|
||||||
|
getData: function () {
|
||||||
|
axios.post('/apppass/api', {
|
||||||
|
password: this.password,
|
||||||
|
passEntry: this.entry
|
||||||
|
})
|
||||||
|
.then(resp => {
|
||||||
|
this.entries = resp.data;
|
||||||
|
})
|
||||||
|
.catch(({response}) => {
|
||||||
|
console.log('error: ' + response.data.err)
|
||||||
|
this.err = response.data.err
|
||||||
|
})
|
||||||
|
}
|
||||||
|
}
|
||||||
|
})
|
||||||
|
</script>
|
||||||
|
</body>
|
||||||
|
</html>
|
||||||
|
`
|
||||||
|
|
|
@ -0,0 +1,189 @@
|
||||||
|
package admin
|
||||||
|
|
||||||
|
import (
|
||||||
|
"crypto/md5"
|
||||||
|
"crypto/rand"
|
||||||
|
"encoding/json"
|
||||||
|
"fmt"
|
||||||
|
"io/ioutil"
|
||||||
|
"net/http"
|
||||||
|
"strings"
|
||||||
|
|
||||||
|
"github.com/rs/zerolog/log"
|
||||||
|
"golang.org/x/crypto/bcrypt"
|
||||||
|
)
|
||||||
|
|
||||||
|
func (p *AdminPlugin) registerWeb() {
|
||||||
|
http.HandleFunc("/vars/api", p.handleVarsAPI)
|
||||||
|
http.HandleFunc("/vars", p.handleVars)
|
||||||
|
p.bot.RegisterWeb("/vars", "Variables")
|
||||||
|
http.HandleFunc("/apppass/verify", p.handleAppPassCheck)
|
||||||
|
http.HandleFunc("/apppass/api", p.handleAppPassAPI)
|
||||||
|
http.HandleFunc("/apppass", p.handleAppPass)
|
||||||
|
p.bot.RegisterWeb("/apppass", "App Pass")
|
||||||
|
}
|
||||||
|
|
||||||
|
func (p *AdminPlugin) handleAppPass(w http.ResponseWriter, r *http.Request) {
|
||||||
|
fmt.Fprint(w, apppassIndex)
|
||||||
|
}
|
||||||
|
|
||||||
|
type PassEntry struct {
|
||||||
|
ID int64 `json:"id"`
|
||||||
|
Secret string `json:"secret"`
|
||||||
|
|
||||||
|
// Should be null unless inserting a new entry
|
||||||
|
Pass string `json:"pass"`
|
||||||
|
encodedPass []byte `json:"encodedPass"`
|
||||||
|
Cost int `json:"cost"`
|
||||||
|
}
|
||||||
|
|
||||||
|
func (p *PassEntry) EncodePass() {
|
||||||
|
encoded, err := bcrypt.GenerateFromPassword([]byte(p.Pass), p.Cost)
|
||||||
|
if err != nil {
|
||||||
|
log.Error().Err(err).Msg("could not hash password")
|
||||||
|
}
|
||||||
|
p.encodedPass = encoded
|
||||||
|
}
|
||||||
|
|
||||||
|
func (p *PassEntry) Compare(pass string) bool {
|
||||||
|
if err := bcrypt.CompareHashAndPassword(p.encodedPass, []byte(pass)); err != nil {
|
||||||
|
log.Error().Err(err).Msg("failure to match password")
|
||||||
|
return false
|
||||||
|
}
|
||||||
|
return true
|
||||||
|
}
|
||||||
|
|
||||||
|
func (p *AdminPlugin) handleAppPassCheck(w http.ResponseWriter, r *http.Request) {
|
||||||
|
req := struct {
|
||||||
|
Secret string `json:"secret"`
|
||||||
|
Password string `json:"password"`
|
||||||
|
}{}
|
||||||
|
body, _ := ioutil.ReadAll(r.Body)
|
||||||
|
_ = json.Unmarshal(body, &req)
|
||||||
|
if p.bot.CheckPassword(req.Secret, req.Password) {
|
||||||
|
w.WriteHeader(204)
|
||||||
|
} else {
|
||||||
|
w.WriteHeader(403)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
func (p *AdminPlugin) handleAppPassAPI(w http.ResponseWriter, r *http.Request) {
|
||||||
|
req := struct {
|
||||||
|
Password string `json:"password"`
|
||||||
|
PassEntry PassEntry `json:"passEntry"`
|
||||||
|
}{}
|
||||||
|
body, _ := ioutil.ReadAll(r.Body)
|
||||||
|
_ = json.Unmarshal(body, &req)
|
||||||
|
if req.PassEntry.Secret == "" {
|
||||||
|
writeErr(w, fmt.Errorf("missing secret"))
|
||||||
|
return
|
||||||
|
}
|
||||||
|
if req.Password == "" || !p.bot.CheckPassword(req.PassEntry.Secret, req.Password) {
|
||||||
|
writeErr(w, fmt.Errorf("missing or incorrect password"))
|
||||||
|
return
|
||||||
|
}
|
||||||
|
switch r.Method {
|
||||||
|
case http.MethodPut:
|
||||||
|
if req.PassEntry.Secret == "" {
|
||||||
|
writeErr(w, fmt.Errorf("missing secret"))
|
||||||
|
return
|
||||||
|
}
|
||||||
|
if string(req.PassEntry.Pass) == "" {
|
||||||
|
c := 10
|
||||||
|
b := make([]byte, c)
|
||||||
|
_, err := rand.Read(b)
|
||||||
|
if err != nil {
|
||||||
|
fmt.Println("error:", err)
|
||||||
|
return
|
||||||
|
}
|
||||||
|
req.PassEntry.Pass = fmt.Sprintf("%x", md5.Sum(b))
|
||||||
|
}
|
||||||
|
q := `insert into apppass (secret, encoded_pass, cost) values (?, ?, ?)`
|
||||||
|
req.PassEntry.EncodePass()
|
||||||
|
|
||||||
|
check := bcrypt.CompareHashAndPassword(req.PassEntry.encodedPass, []byte(req.PassEntry.Pass))
|
||||||
|
|
||||||
|
log.Debug().
|
||||||
|
Str("secret", req.PassEntry.Secret).
|
||||||
|
Str("encoded", string(req.PassEntry.encodedPass)).
|
||||||
|
Str("password", string(req.PassEntry.Pass)).
|
||||||
|
Interface("check", check).
|
||||||
|
Msg("debug pass creation")
|
||||||
|
|
||||||
|
res, err := p.db.Exec(q, req.PassEntry.Secret, req.PassEntry.encodedPass, req.PassEntry.Cost)
|
||||||
|
if err != nil {
|
||||||
|
writeErr(w, err)
|
||||||
|
return
|
||||||
|
}
|
||||||
|
id, err := res.LastInsertId()
|
||||||
|
if err != nil {
|
||||||
|
writeErr(w, err)
|
||||||
|
return
|
||||||
|
}
|
||||||
|
req.PassEntry.ID = id
|
||||||
|
j, _ := json.Marshal(req.PassEntry)
|
||||||
|
fmt.Fprint(w, string(j))
|
||||||
|
return
|
||||||
|
case http.MethodDelete:
|
||||||
|
if req.PassEntry.ID <= 0 {
|
||||||
|
writeErr(w, fmt.Errorf("missing ID"))
|
||||||
|
return
|
||||||
|
}
|
||||||
|
q := `delete from apppass where id = ?`
|
||||||
|
_, err := p.db.Exec(q, req.PassEntry.ID)
|
||||||
|
if err != nil {
|
||||||
|
writeErr(w, err)
|
||||||
|
return
|
||||||
|
}
|
||||||
|
}
|
||||||
|
q := `select id,secret from apppass where secret = ?`
|
||||||
|
passEntries := []PassEntry{}
|
||||||
|
err := p.db.Select(&passEntries, q, req.PassEntry.Secret)
|
||||||
|
if err != nil {
|
||||||
|
writeErr(w, err)
|
||||||
|
return
|
||||||
|
}
|
||||||
|
j, _ := json.Marshal(passEntries)
|
||||||
|
_, _ = fmt.Fprint(w, string(j))
|
||||||
|
}
|
||||||
|
|
||||||
|
func writeErr(w http.ResponseWriter, err error) {
|
||||||
|
log.Error().Err(err).Msg("apppass error")
|
||||||
|
j, _ := json.Marshal(struct {
|
||||||
|
Err string `json:"err"`
|
||||||
|
}{
|
||||||
|
err.Error(),
|
||||||
|
})
|
||||||
|
w.WriteHeader(400)
|
||||||
|
fmt.Fprint(w, string(j))
|
||||||
|
}
|
||||||
|
|
||||||
|
func (p *AdminPlugin) handleVars(w http.ResponseWriter, r *http.Request) {
|
||||||
|
fmt.Fprint(w, varIndex)
|
||||||
|
}
|
||||||
|
|
||||||
|
func (p *AdminPlugin) handleVarsAPI(w http.ResponseWriter, r *http.Request) {
|
||||||
|
var configEntries []struct {
|
||||||
|
Key string `json:"key"`
|
||||||
|
Value string `json:"value"`
|
||||||
|
}
|
||||||
|
q := `select key, value from config`
|
||||||
|
err := p.db.Select(&configEntries, q)
|
||||||
|
if err != nil {
|
||||||
|
log.Error().
|
||||||
|
Err(err).
|
||||||
|
Msg("Error getting config entries.")
|
||||||
|
w.WriteHeader(500)
|
||||||
|
fmt.Fprint(w, err)
|
||||||
|
return
|
||||||
|
}
|
||||||
|
for i, e := range configEntries {
|
||||||
|
if strings.Contains(e.Value, ";;") {
|
||||||
|
e.Value = strings.ReplaceAll(e.Value, ";;", ", ")
|
||||||
|
e.Value = fmt.Sprintf("[%s]", e.Value)
|
||||||
|
configEntries[i] = e
|
||||||
|
}
|
||||||
|
}
|
||||||
|
j, _ := json.Marshal(configEntries)
|
||||||
|
fmt.Fprintf(w, "%s", j)
|
||||||
|
}
|
|
@ -57,7 +57,7 @@ func (p *CliPlugin) handleWebAPI(w http.ResponseWriter, r *http.Request) {
|
||||||
log.Debug().
|
log.Debug().
|
||||||
Interface("postbody", info).
|
Interface("postbody", info).
|
||||||
Msg("Got a POST")
|
Msg("Got a POST")
|
||||||
if info.Password != p.bot.GetPassword() {
|
if !p.bot.CheckPassword("", info.Password) {
|
||||||
w.WriteHeader(http.StatusForbidden)
|
w.WriteHeader(http.StatusForbidden)
|
||||||
j, _ := json.Marshal(struct{ Err string }{Err: "Invalid Password"})
|
j, _ := json.Marshal(struct{ Err string }{Err: "Invalid Password"})
|
||||||
w.Write(j)
|
w.Write(j)
|
||||||
|
|
|
@ -745,7 +745,7 @@ func (p *CounterPlugin) handleCounterAPI(w http.ResponseWriter, r *http.Request)
|
||||||
log.Debug().
|
log.Debug().
|
||||||
Interface("postbody", info).
|
Interface("postbody", info).
|
||||||
Msg("Got a POST")
|
Msg("Got a POST")
|
||||||
if info.Password != p.Bot.GetPassword() {
|
if p.Bot.CheckPassword("", info.Password) {
|
||||||
w.WriteHeader(http.StatusForbidden)
|
w.WriteHeader(http.StatusForbidden)
|
||||||
j, _ := json.Marshal(struct{ Err string }{Err: "Invalid Password"})
|
j, _ := json.Marshal(struct{ Err string }{Err: "Invalid Password"})
|
||||||
w.Write(j)
|
w.Write(j)
|
||||||
|
|
|
@ -150,7 +150,7 @@ func (p *FirstPlugin) isNotToday(f *FirstEntry) bool {
|
||||||
t := f.time
|
t := f.time
|
||||||
t0 := Midnight(t)
|
t0 := Midnight(t)
|
||||||
jitter := time.Duration(p.config.GetInt("first.jitter", 0))
|
jitter := time.Duration(p.config.GetInt("first.jitter", 0))
|
||||||
t0 = t0.Add(jitter * time.Second)
|
t0 = t0.Add(jitter * time.Millisecond)
|
||||||
return t0.Before(Midnight(time.Now()))
|
return t0.Before(Midnight(time.Now()))
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
Loading…
Reference in New Issue