163 lines
4.4 KiB
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),
|
|
}
|
|
}
|