also notify when received from whitelist

This commit is contained in:
Wouter Groeneveld 2022-04-28 09:28:16 +02:00
parent bf018eafe8
commit 45ff736001
8 changed files with 104 additions and 31 deletions

View File

@ -4,7 +4,7 @@ import (
"brainbaking.com/go-jamming/app/mf"
"brainbaking.com/go-jamming/common"
"encoding/base64"
"github.com/rs/zerolog/log"
"fmt"
"net/mail"
"net/smtp"
)
@ -53,15 +53,28 @@ func sendMail(from, subject, body, toName, toAddress string) error {
return c.Quit()
}
func (mn *MailNotifier) NotifyReceived(wm mf.Mention, indieweb *mf.IndiewebData) {
err := sendMail(
func (mn *MailNotifier) NotifyReceived(wm mf.Mention, indieweb *mf.IndiewebData) error {
if len(mn.Conf.AdminEmail) == 0 {
return fmt.Errorf("no adminEmail provided")
}
return sendMail(
mn.Conf.AdminEmail,
"Webmention in moderation from "+wm.SourceDomain(),
BuildNotification(wm, indieweb, mn.Conf),
"Webmention received from "+wm.SourceDomain(),
buildReceivedMsg(wm, indieweb, mn.Conf),
"Go-Jamming User",
mn.Conf.AdminEmail)
}
func (mn *MailNotifier) NotifyInModeration(wm mf.Mention, indieweb *mf.IndiewebData) error {
if len(mn.Conf.AdminEmail) == 0 {
return fmt.Errorf("no adminEmail provided")
}
return sendMail(
mn.Conf.AdminEmail,
"Webmention in moderation from "+wm.SourceDomain(),
buildInModerationMsg(wm, indieweb, mn.Conf),
"Go-Jamming User",
mn.Conf.AdminEmail)
if err != nil {
log.Err(err).Msg("Unable to send notification mail, check localhost postfix settings?")
}
}

View File

@ -2,7 +2,7 @@
<html lang="en">
<head>
<meta charset="UTF-8">
<title>Webmention in moderation from {{ .SourceDomain }}</title>
<title>Webmention {{ .Action }} from {{ .SourceDomain }}</title>
<style>
body {
font-family: 'Helvetica Neue', Helvetica, Arial, sans-serif;
@ -12,7 +12,7 @@
</head>
<body>
<h1>🥞 Webmention in moderation from {{ .SourceDomain }}</h1>
<h1>🥞 Webmention {{ .Action }} from {{ .SourceDomain }}</h1>
<p>Hi Admin, a webmention was received:</p>
@ -23,8 +23,8 @@
</p>
<p>
<a href="{{ .ApproveURL }}">✅ Accept!</a><br/>
<a href="{{ .RejectURL }}">❌ Reject!</a>
{{ with .ApproveURL}}<a href="{{ . }}">✅ Accept!</a><br/>{{ end }}
{{ with .RejectURL }}<a href="{{ . }}">❌ Reject!</a>{{ end }}
</p>
<p>

View File

@ -24,6 +24,7 @@ func init() {
}
type notificationData struct {
Action string
SourceDomain string
Source string
Content string
@ -34,17 +35,34 @@ type notificationData struct {
}
type Notifier interface {
NotifyReceived(wm mf.Mention, data *mf.IndiewebData)
NotifyInModeration(wm mf.Mention, data *mf.IndiewebData) error
NotifyReceived(wm mf.Mention, data *mf.IndiewebData) error
}
// BuildNotification returns a HTML (string template) representation of the Mention to notify the admin.
func BuildNotification(wm mf.Mention, data *mf.IndiewebData, cnf *common.Config) string {
acceptUrl := fmt.Sprintf("%sadmin/approve/%s/%s", cnf.BaseURL, cnf.Token, wm.Key())
rejectUrl := fmt.Sprintf("%sadmin/reject/%s/%s", cnf.BaseURL, cnf.Token, wm.Key())
adminUrl := fmt.Sprintf("%sadmin/%s", cnf.BaseURL, cnf.Token)
// buildReceivedMsg returns a HTML (string template) representation of the approved mention to notify the admin.
func buildReceivedMsg(wm mf.Mention, data *mf.IndiewebData, cnf *common.Config) string {
adminUrl := adminUrl(cnf)
var buff bytes.Buffer
notificationTmpl.Execute(&buff, notificationData{
Action: "approved",
Source: wm.Source,
Target: wm.Target,
Content: data.Content,
SourceDomain: wm.SourceDomain(),
AdminURL: adminUrl,
})
return buff.String()
}
// buildInModerationMsg returns a HTML (string template) representation of the in moderation mention to notify the admin.
func buildInModerationMsg(wm mf.Mention, data *mf.IndiewebData, cnf *common.Config) string {
acceptUrl := acceptUrl(wm, cnf)
rejectUrl := rejectUrl(wm, cnf)
adminUrl := adminUrl(cnf)
var buff bytes.Buffer
notificationTmpl.Execute(&buff, notificationData{
Action: "in moderation",
Source: wm.Source,
Target: wm.Target,
Content: data.Content,
@ -55,3 +73,15 @@ func BuildNotification(wm mf.Mention, data *mf.IndiewebData, cnf *common.Config)
})
return buff.String()
}
func rejectUrl(wm mf.Mention, cnf *common.Config) string {
return fmt.Sprintf("%sadmin/reject/%s/%s", cnf.BaseURL, cnf.Token, wm.Key())
}
func acceptUrl(wm mf.Mention, cnf *common.Config) string {
return fmt.Sprintf("%sadmin/approve/%s/%s", cnf.BaseURL, cnf.Token, wm.Key())
}
func adminUrl(cnf *common.Config) string {
return fmt.Sprintf("%sadmin/%s", cnf.BaseURL, cnf.Token)
}

View File

@ -7,7 +7,7 @@ import (
"testing"
)
func TestBuildNotification(t *testing.T) {
func TestBuildReceivedMsgDoesNotContainApproveLink(t *testing.T) {
wm := mf.Mention{
Source: "https://brainbaking.com/valid-indieweb-source.html",
Target: "https://brainbaking.com/valid-indieweb-target.html",
@ -22,7 +22,30 @@ func TestBuildNotification(t *testing.T) {
Whitelist: []string{},
}
result := BuildNotification(wm, &mf.IndiewebData{Content: "somecontent"}, cnf)
result := buildReceivedMsg(wm, &mf.IndiewebData{Content: "somecontent"}, cnf)
assert.Contains(t, result, `Webmention approved from`)
assert.Contains(t, result, `<em>Source:</em> <a href="https://brainbaking.com/valid-indieweb-source.html">https://brainbaking.com/valid-indieweb-source.html</a><br/>`)
assert.Contains(t, result, `<em>Target:</em> <a href="https://brainbaking.com/valid-indieweb-target.html">https://brainbaking.com/valid-indieweb-target.html</a><br/>`)
assert.NotContains(t, result, `<a href="https://jam.brainbaking.com/admin/approve/mytoken/19d462ddff3c3322c662dac3461324bb:brainbaking.com`)
}
func TestBuildInModerationMsgContainsApproveLink(t *testing.T) {
wm := mf.Mention{
Source: "https://brainbaking.com/valid-indieweb-source.html",
Target: "https://brainbaking.com/valid-indieweb-target.html",
}
cnf := &common.Config{
AllowedWebmentionSources: []string{
"brainbaking.com",
},
BaseURL: "https://jam.brainbaking.com/",
Token: "mytoken",
Blacklist: []string{},
Whitelist: []string{},
}
result := buildInModerationMsg(wm, &mf.IndiewebData{Content: "somecontent"}, cnf)
assert.Contains(t, result, `Webmention in moderation from`)
assert.Contains(t, result, `<em>Source:</em> <a href="https://brainbaking.com/valid-indieweb-source.html">https://brainbaking.com/valid-indieweb-source.html</a><br/>`)
assert.Contains(t, result, `<em>Target:</em> <a href="https://brainbaking.com/valid-indieweb-target.html">https://brainbaking.com/valid-indieweb-target.html</a><br/>`)
assert.Contains(t, result, `<a href="https://jam.brainbaking.com/admin/approve/mytoken/19d462ddff3c3322c662dac3461324bb:brainbaking.com`)

View File

@ -89,11 +89,9 @@ func HandlePost(conf *common.Config, repo db.MentionRepo) http.HandlerFunc {
RestClient: httpClient,
Conf: conf,
Repo: repo,
}
if len(conf.AdminEmail) > 0 {
recv.Notifier = &notifier.MailNotifier{
Notifier: &notifier.MailNotifier{
Conf: conf,
}
},
}
go recv.Receive(wm)

View File

@ -76,8 +76,9 @@ func (recv *Receiver) processMentionInModeration(wm mf.Mention, indieweb *mf.Ind
if err != nil {
log.Error().Err(err).Stringer("wm", wm).Msg("Failed to save new mention to in moderation db")
}
if recv.Notifier != nil {
recv.Notifier.NotifyReceived(wm, indieweb)
err = recv.Notifier.NotifyInModeration(wm, indieweb)
if err != nil {
log.Error().Err(err).Msg("Failed to notify")
}
log.Info().Str("key", key).Msg("OK: Webmention processed, in moderation.")
}
@ -87,6 +88,10 @@ func (recv *Receiver) processWhitelistedMention(wm mf.Mention, indieweb *mf.Indi
if err != nil {
log.Error().Err(err).Stringer("wm", wm).Msg("Failed to save new mention to db")
}
err = recv.Notifier.NotifyReceived(wm, indieweb)
if err != nil {
log.Error().Err(err).Msg("Failed to notify")
}
log.Info().Str("key", key).Msg("OK: Webmention processed, in whitelist.")
}

View File

@ -269,7 +269,7 @@ func TestReceiveFromNotInWhitelistSavesInModerationAndNotifies(t *testing.T) {
receiver.Receive(wm)
assert.Empty(t, repo.GetAll("brainbaking.com").Data)
assert.Equal(t, 1, len(repo.GetAllToModerate("brainbaking.com").Data))
assert.Contains(t, notifierMock.Output, "✅ Accept!")
assert.Contains(t, notifierMock.Output, "in moderation!")
}
func TestReceiveFromBlacklistedDomainDoesNothing(t *testing.T) {

View File

@ -2,7 +2,6 @@ package mocks
import (
"brainbaking.com/go-jamming/app/mf"
"brainbaking.com/go-jamming/app/notifier"
"brainbaking.com/go-jamming/common"
)
@ -11,6 +10,11 @@ type StringNotifier struct {
Conf *common.Config
}
func (sn *StringNotifier) NotifyReceived(wm mf.Mention, indieweb *mf.IndiewebData) {
sn.Output = notifier.BuildNotification(wm, indieweb, sn.Conf)
func (sn *StringNotifier) NotifyInModeration(wm mf.Mention, data *mf.IndiewebData) error {
sn.Output = "in moderation!"
return nil
}
func (sn *StringNotifier) NotifyReceived(wm mf.Mention, data *mf.IndiewebData) error {
sn.Output = "received!"
return nil
}