go-jamming/app/admin/handler.go

163 lines
4.4 KiB
Go

package admin
import (
"brainbaking.com/go-jamming/app/mf"
"brainbaking.com/go-jamming/common"
"brainbaking.com/go-jamming/db"
"brainbaking.com/go-jamming/rest"
"fmt"
"github.com/gorilla/mux"
"github.com/rs/zerolog/log"
"net/http"
"text/template"
)
import _ "embed"
//go:embed dashboard.html
var dashboardTemplate []byte
//go:embed moderated.html
var moderatedTemplate []byte
type dashboardMention struct {
Source string
Target string
Content string
ApproveURL string
RejectURL string
}
type domainMention struct {
Name string
MentionsURL string
}
type dashboardData struct {
Config string
Mentions map[domainMention][]dashboardMention
}
type dashboardModerated struct {
Action string
Item string
RedirectURL string
}
func indiewebDataToDashboardMention(c *common.Config, dbMentions []*mf.IndiewebData) []dashboardMention {
var mentions []dashboardMention
for _, dbMention := range dbMentions {
wm := dbMention.AsMention()
// TODO move this to somewhere else? the wm? duplicate in notifier.go
approveUrl := fmt.Sprintf("%sadmin/approve/%s/%s", c.BaseURL, c.Token, wm.Key())
rejectUrl := fmt.Sprintf("%sadmin/reject/%s/%s", c.BaseURL, c.Token, wm.Key())
mentions = append(mentions, dashboardMention{
Source: dbMention.Source,
Target: dbMention.Target,
Content: dbMention.Content,
ApproveURL: approveUrl,
RejectURL: rejectUrl,
})
}
return mentions
}
func getDashboardData(c *common.Config, repo db.MentionRepo) *dashboardData {
data := &dashboardData{
Config: c.String(),
Mentions: map[domainMention][]dashboardMention{},
}
for _, domain := range c.AllowedWebmentionSources {
domainKey := domainMention{
Name: domain,
MentionsURL: fmt.Sprintf("%swebmention/%s/%s", c.BaseURL, domain, c.Token),
}
data.Mentions[domainKey] = indiewebDataToDashboardMention(c, repo.GetAllToModerate(domain).Data)
}
return data
}
func asTemplate(name string, data []byte) *template.Template {
tmpl, err := template.New(name).Parse(string(data))
if err != nil {
log.Fatal().Err(err).Str("name", name).Msg("Template invalid")
}
return tmpl
}
func HandleGet(c *common.Config, repo db.MentionRepo) http.HandlerFunc {
tmpl := asTemplate("dashboard", dashboardTemplate)
return func(w http.ResponseWriter, r *http.Request) {
err := tmpl.Execute(w, getDashboardData(c, repo))
if err != nil {
w.WriteHeader(http.StatusInternalServerError)
log.Error().Err(err).Msg("Unable to fill in dashboard template")
}
}
}
func HandleGetToApprove(repo db.MentionRepo) http.HandlerFunc {
return func(w http.ResponseWriter, r *http.Request) {
domain := mux.Vars(r)["domain"]
rest.Json(w, repo.GetAllToModerate(domain))
}
}
// HandleApprove approves the Mention (by key in URL) and adds to the allowlist.
// Returns 200 OK with approved source/target or 404 if key is invalid.
func HandleApprove(c *common.Config, repo db.MentionRepo) http.HandlerFunc {
tmpl := asTemplate("moderated", moderatedTemplate)
return func(w http.ResponseWriter, r *http.Request) {
key := mux.Vars(r)["key"]
approved := repo.Approve(key)
if approved == nil {
http.NotFound(w, r)
return
}
c.AddToAllowlist(approved.AsMention().SourceDomain())
err := tmpl.Execute(w, asDashboardModerated("Approved", approved, c))
if err != nil {
w.WriteHeader(http.StatusInternalServerError)
log.Error().Err(err).Msg("Unable to fill in dashboard template")
}
}
}
// HandleReject rejects the Mention (by key in URL) and adds to the denylist.
// Returns 200 OK with rejected source/target or 404 if key is invalid.
func HandleReject(c *common.Config, repo db.MentionRepo) http.HandlerFunc {
tmpl := asTemplate("moderated", moderatedTemplate)
return func(w http.ResponseWriter, r *http.Request) {
key := mux.Vars(r)["key"]
rejected := repo.Reject(key)
if rejected == nil {
http.NotFound(w, r)
return
}
c.AddToDenylist(rejected.AsMention().SourceDomain())
err := tmpl.Execute(w, asDashboardModerated("Rejected", rejected, c))
if err != nil {
w.WriteHeader(http.StatusInternalServerError)
log.Error().Err(err).Msg("Unable to fill in dashboard template")
}
}
}
func asDashboardModerated(action string, mention *mf.IndiewebData, c *common.Config) dashboardModerated {
return dashboardModerated{
Action: action,
Item: mention.AsMention().String(),
RedirectURL: fmt.Sprintf("%sadmin/%s", c.BaseURL, c.Token),
}
}