2021-05-20 13:59:28 +00:00
|
|
|
package secrets
|
|
|
|
|
|
|
|
import (
|
2021-07-29 16:33:03 +00:00
|
|
|
"embed"
|
2021-05-20 13:59:28 +00:00
|
|
|
"encoding/json"
|
|
|
|
"fmt"
|
2021-12-20 17:40:10 +00:00
|
|
|
bh "github.com/timshannon/bolthold"
|
2021-05-20 13:59:28 +00:00
|
|
|
"net/http"
|
|
|
|
|
2021-07-21 18:52:45 +00:00
|
|
|
"github.com/go-chi/chi/v5"
|
2021-05-20 13:59:28 +00:00
|
|
|
"github.com/rs/zerolog/log"
|
|
|
|
"github.com/velour/catbase/bot"
|
|
|
|
"github.com/velour/catbase/config"
|
|
|
|
)
|
|
|
|
|
2021-07-29 16:33:03 +00:00
|
|
|
//go:embed *.html
|
|
|
|
var embeddedFS embed.FS
|
|
|
|
|
2021-05-20 13:59:28 +00:00
|
|
|
type SecretsPlugin struct {
|
2021-12-20 17:40:10 +00:00
|
|
|
b bot.Bot
|
|
|
|
c *config.Config
|
|
|
|
store *bh.Store
|
2021-05-20 13:59:28 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
func New(b bot.Bot) *SecretsPlugin {
|
|
|
|
p := &SecretsPlugin{
|
2021-12-20 17:40:10 +00:00
|
|
|
b: b,
|
|
|
|
c: b.Config(),
|
|
|
|
store: b.Store(),
|
2021-05-20 13:59:28 +00:00
|
|
|
}
|
|
|
|
p.registerWeb()
|
|
|
|
return p
|
|
|
|
}
|
|
|
|
|
|
|
|
func (p *SecretsPlugin) registerWeb() {
|
2021-07-21 18:52:45 +00:00
|
|
|
r := chi.NewRouter()
|
|
|
|
r.HandleFunc("/add", p.handleRegister)
|
|
|
|
r.HandleFunc("/remove", p.handleRemove)
|
|
|
|
r.HandleFunc("/all", p.handleAll)
|
|
|
|
r.HandleFunc("/test", func(w http.ResponseWriter, r *http.Request) {
|
2021-05-20 13:59:28 +00:00
|
|
|
value := r.URL.Query().Get("test")
|
|
|
|
j, _ := json.Marshal(map[string]string{"value": value})
|
|
|
|
w.Write(j)
|
|
|
|
})
|
2021-07-21 18:52:45 +00:00
|
|
|
r.HandleFunc("/", p.handleIndex)
|
2021-07-28 15:32:59 +00:00
|
|
|
p.b.RegisterWebName(r, "/secrets", "Secrets")
|
2021-05-20 13:59:28 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
func (p *SecretsPlugin) registerSecret(key, value string) error {
|
2021-12-20 17:40:10 +00:00
|
|
|
err := p.store.Insert(key, config.Secret{key, value})
|
2021-05-20 13:59:28 +00:00
|
|
|
if err != nil {
|
|
|
|
return err
|
|
|
|
}
|
|
|
|
return p.c.RefreshSecrets()
|
|
|
|
}
|
|
|
|
|
|
|
|
func (p *SecretsPlugin) removeSecret(key string) error {
|
2021-12-20 17:40:10 +00:00
|
|
|
err := p.store.Delete(key, config.Secret{})
|
2021-05-20 13:59:28 +00:00
|
|
|
if err != nil {
|
|
|
|
return err
|
|
|
|
}
|
|
|
|
return p.c.RefreshSecrets()
|
|
|
|
}
|
|
|
|
|
|
|
|
func (p *SecretsPlugin) updateSecret(key, value string) error {
|
2021-12-20 17:40:10 +00:00
|
|
|
err := p.store.Update(key, config.Secret{key, value})
|
2021-05-20 13:59:28 +00:00
|
|
|
if err != nil {
|
|
|
|
return err
|
|
|
|
}
|
|
|
|
return p.c.RefreshSecrets()
|
|
|
|
}
|
|
|
|
|
|
|
|
func mkCheckError(w http.ResponseWriter) func(error) bool {
|
|
|
|
return func(err error) bool {
|
|
|
|
if err != nil {
|
|
|
|
log.Error().Stack().Err(err).Msgf("secret failed")
|
|
|
|
w.WriteHeader(500)
|
|
|
|
e, _ := json.Marshal(err)
|
|
|
|
w.Write(e)
|
|
|
|
return true
|
|
|
|
}
|
|
|
|
return false
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
func checkMethod(method string, w http.ResponseWriter, r *http.Request) bool {
|
|
|
|
if r.Method != method {
|
|
|
|
w.WriteHeader(405)
|
|
|
|
fmt.Fprintf(w, "Incorrect HTTP method")
|
|
|
|
return true
|
|
|
|
}
|
|
|
|
return false
|
|
|
|
}
|
|
|
|
|
|
|
|
func (p *SecretsPlugin) sendKeys(w http.ResponseWriter, r *http.Request) {
|
|
|
|
checkError := mkCheckError(w)
|
|
|
|
log.Debug().Msgf("Keys before refresh: %v", p.c.SecretKeys())
|
|
|
|
err := p.c.RefreshSecrets()
|
|
|
|
log.Debug().Msgf("Keys after refresh: %v", p.c.SecretKeys())
|
|
|
|
if checkError(err) {
|
|
|
|
return
|
|
|
|
}
|
|
|
|
keys, err := json.Marshal(p.c.SecretKeys())
|
|
|
|
if checkError(err) {
|
|
|
|
return
|
|
|
|
}
|
|
|
|
w.WriteHeader(200)
|
|
|
|
w.Write(keys)
|
|
|
|
}
|
|
|
|
|
|
|
|
func (p *SecretsPlugin) handleAll(w http.ResponseWriter, r *http.Request) {
|
|
|
|
p.sendKeys(w, r)
|
|
|
|
}
|
|
|
|
|
|
|
|
func (p *SecretsPlugin) handleRegister(w http.ResponseWriter, r *http.Request) {
|
|
|
|
log.Debug().Msgf("handleRegister")
|
|
|
|
if checkMethod(http.MethodPost, w, r) {
|
|
|
|
log.Debug().Msgf("failed post %s", r.Method)
|
|
|
|
return
|
|
|
|
}
|
|
|
|
checkError := mkCheckError(w)
|
|
|
|
decoder := json.NewDecoder(r.Body)
|
|
|
|
secret := config.Secret{}
|
|
|
|
err := decoder.Decode(&secret)
|
|
|
|
log.Debug().Msgf("decoding: %s", err)
|
|
|
|
if checkError(err) {
|
|
|
|
return
|
|
|
|
}
|
|
|
|
log.Debug().Msgf("Secret: %s", secret)
|
|
|
|
err = p.registerSecret(secret.Key, secret.Value)
|
|
|
|
if checkError(err) {
|
|
|
|
return
|
|
|
|
}
|
|
|
|
p.sendKeys(w, r)
|
|
|
|
}
|
|
|
|
|
|
|
|
func (p *SecretsPlugin) handleRemove(w http.ResponseWriter, r *http.Request) {
|
|
|
|
if checkMethod(http.MethodDelete, w, r) {
|
|
|
|
return
|
|
|
|
}
|
|
|
|
checkError := mkCheckError(w)
|
|
|
|
decoder := json.NewDecoder(r.Body)
|
|
|
|
secret := config.Secret{}
|
|
|
|
err := decoder.Decode(&secret)
|
|
|
|
if checkError(err) {
|
|
|
|
return
|
|
|
|
}
|
|
|
|
err = p.removeSecret(secret.Key)
|
|
|
|
if checkError(err) {
|
|
|
|
return
|
|
|
|
}
|
|
|
|
p.sendKeys(w, r)
|
|
|
|
}
|
|
|
|
|
|
|
|
func (p *SecretsPlugin) handleIndex(w http.ResponseWriter, r *http.Request) {
|
2021-07-29 16:33:03 +00:00
|
|
|
index, _ := embeddedFS.ReadFile("index.html")
|
|
|
|
w.Write(index)
|
2021-05-20 13:59:28 +00:00
|
|
|
}
|