diff --git a/config.go b/config.go index ef69c98..26b3654 100644 --- a/config.go +++ b/config.go @@ -19,6 +19,7 @@ type config struct { Micropub *configMicropub `mapstructure:"micropub"` PathRedirects []*configRegexRedirect `mapstructure:"pathRedirects"` ActivityPub *configActivityPub `mapstructure:"activityPub"` + Webmention *configWebmention `mapstructure:"webmention"` Notifications *configNotifications `mapstructure:"notifications"` PrivateMode *configPrivateMode `mapstructure:"privateMode"` } @@ -205,6 +206,11 @@ type configPrivateMode struct { Enabled bool `mapstructure:"enabled"` } +type configWebmention struct { + DisableSending bool `mapstructure:"disableSending"` + DisableReceiving bool `mapstructure:"disableReceiving"` +} + var appConfig = &config{} func initConfig() error { @@ -235,6 +241,8 @@ func initConfig() error { viper.SetDefault("micropub.photoDescriptionParam", "imagealts") viper.SetDefault("activityPub.keyPath", "data/private.pem") viper.SetDefault("activityPub.tagsTaxonomies", []string{"tags"}) + viper.SetDefault("webmention.disableSending", false) + viper.SetDefault("webmention.disableReceiving", false) // Unmarshal config err = viper.Unmarshal(appConfig) if err != nil { @@ -274,6 +282,12 @@ func initConfig() error { if pm := appConfig.PrivateMode; pm != nil && pm.Enabled { appConfig.ActivityPub = &configActivityPub{Enabled: false} } + if wm := appConfig.Webmention; wm != nil && wm.DisableReceiving { + // Disable comments for all blogs + for _, b := range appConfig.Blogs { + b.Comments = &comments{Enabled: false} + } + } return nil } diff --git a/example-config.yml b/example-config.yml index b703b7b..6b9e47b 100644 --- a/example-config.yml +++ b/example-config.yml @@ -70,6 +70,11 @@ hooks: activityPub: enabled: true # Enable ActivityPub +# Webmention +webmention: + disableSending: true # Disable sending of webmentions (also happens when private mode enabled and external target) + disableReceiving: true # Disable receiving of webmentions, disables comments for all blogs, disables replies via ActivityPub + # MicroPub micropub: # Media configuration diff --git a/http.go b/http.go index f17d606..64143d2 100644 --- a/http.go +++ b/http.go @@ -193,15 +193,17 @@ func buildStaticHandlersRouters() error { indieAuthRouter.Post("/token", indieAuthToken) webmentionsRouter = chi.NewRouter() - webmentionsRouter.Post("/", handleWebmention) - webmentionsRouter.Group(func(r chi.Router) { - // Authenticated routes - r.Use(authMiddleware) - r.Get("/", webmentionAdmin) - r.Get(paginationPath, webmentionAdmin) - r.Post("/delete", webmentionAdminDelete) - r.Post("/approve", webmentionAdminApprove) - }) + if wm := appConfig.Webmention; wm != nil && !wm.DisableReceiving { + webmentionsRouter.Post("/", handleWebmention) + webmentionsRouter.Group(func(r chi.Router) { + // Authenticated routes + r.Use(authMiddleware) + r.Get("/", webmentionAdmin) + r.Get(paginationPath, webmentionAdmin) + r.Post("/delete", webmentionAdminDelete) + r.Post("/approve", webmentionAdminApprove) + }) + } notificationsRouter = chi.NewRouter() notificationsRouter.Use(authMiddleware) diff --git a/render.go b/render.go index 31e9126..65a3778 100644 --- a/render.go +++ b/render.go @@ -190,12 +190,13 @@ func initRendering() error { } type renderData struct { - BlogString string - Canonical string - Blog *configBlog - Data interface{} - LoggedIn bool - CommentsEnabled bool + BlogString string + Canonical string + Blog *configBlog + Data interface{} + LoggedIn bool + CommentsEnabled bool + WebmentionReceivingEnabled bool } func render(w http.ResponseWriter, r *http.Request, template string, data *renderData) { @@ -225,6 +226,8 @@ func render(w http.ResponseWriter, r *http.Request, template string, data *rende } // Check if comments enabled data.CommentsEnabled = data.Blog.Comments != nil && data.Blog.Comments.Enabled + // Check if able to receive webmentions + data.WebmentionReceivingEnabled = appConfig.Webmention == nil || !appConfig.Webmention.DisableReceiving // Minify and write response mw := minifier.Writer(contentTypeHTML, w) defer func() { diff --git a/templates/header.gohtml b/templates/header.gohtml index f72adb3..e49df00 100644 --- a/templates/header.gohtml +++ b/templates/header.gohtml @@ -11,7 +11,7 @@ diff --git a/webmention.go b/webmention.go index b222b12..a9090a7 100644 --- a/webmention.go +++ b/webmention.go @@ -64,7 +64,7 @@ func handleWebmention(w http.ResponseWriter, r *http.Request) { func extractMention(r *http.Request) (*mention, error) { if !strings.Contains(r.Header.Get(contentType), contentTypeWWWForm) { - return nil, errors.New("Unsupported Content-Type") + return nil, errors.New("unsupported Content-Type") } err := r.ParseForm() if err != nil { @@ -73,7 +73,7 @@ func extractMention(r *http.Request) (*mention, error) { source := r.Form.Get("source") target := unescapedPath(r.Form.Get("target")) if source == "" || target == "" || !isAbsoluteURL(source) || !isAbsoluteURL(target) { - return nil, errors.New("Invalid request") + return nil, errors.New("invalid request") } return &mention{ Source: source, diff --git a/webmentionSending.go b/webmentionSending.go index e1fd67e..aa2f5c4 100644 --- a/webmentionSending.go +++ b/webmentionSending.go @@ -14,6 +14,10 @@ import ( ) func (p *post) sendWebmentions() error { + if wm := appConfig.Webmention; wm != nil && wm.DisableSending { + // Just ignore the mentions + return nil + } links := []string{} contentLinks, err := allLinksFromHTML(strings.NewReader(string(p.html())), p.fullURL()) if err != nil { @@ -42,8 +46,7 @@ func (p *post) sendWebmentions() error { if endpoint == "" { continue } - _, err = sendWebmention(endpoint, p.fullURL(), link) - if err != nil { + if err = sendWebmention(endpoint, p.fullURL(), link); err != nil { log.Println("Sending webmention to " + link + " failed") continue } @@ -52,26 +55,30 @@ func (p *post) sendWebmentions() error { return nil } -func sendWebmention(endpoint, source, target string) (*http.Response, error) { +func sendWebmention(endpoint, source, target string) error { + if wm := appConfig.Webmention; wm != nil && wm.DisableSending { + // Just ignore the mention + return nil + } req, err := http.NewRequest(http.MethodPost, endpoint, strings.NewReader(url.Values{ "source": []string{source}, "target": []string{target}, }.Encode())) if err != nil { - return nil, err + return err } req.Header.Set(contentType, contentTypeWWWForm) req.Header.Set(userAgent, appUserAgent) res, err := appHttpClient.Do(req) if err != nil { - return res, err + return err } defer res.Body.Close() _, _ = io.Copy(io.Discard, res.Body) if code := res.StatusCode; code < 200 || 300 <= code { - return res, fmt.Errorf("response error: %v", res.StatusCode) + return fmt.Errorf("response error: %v", res.StatusCode) } - return res, nil + return nil } func discoverEndpoint(urlStr string) string { diff --git a/webmentionVerification.go b/webmentionVerification.go index 39fd8ea..5f17aba 100644 --- a/webmentionVerification.go +++ b/webmentionVerification.go @@ -66,6 +66,9 @@ func startWebmentionQueue() { } func queueMention(m *mention) error { + if wm := appConfig.Webmention; wm != nil && wm.DisableReceiving { + return errors.New("webmention receiving disabled") + } return wmQueue.Enqueue(m) }