add domain authentication handling, start wm PUT

This commit is contained in:
Wouter Groeneveld 2021-04-09 18:00:40 +02:00
parent f74c0c6e5b
commit 9f6450e367
7 changed files with 130 additions and 19 deletions

View File

@ -3,18 +3,20 @@ package app
import (
"github.com/wgroeneveld/go-jamming/app/index"
"github.com/wgroeneveld/go-jamming/app/webmention"
"github.com/wgroeneveld/go-jamming/app/pingback"
"github.com/wgroeneveld/go-jamming/app/webmention"
)
// stole ideas from https://pace.dev/blog/2018/05/09/how-I-write-http-services-after-eight-years.html
// not that contempt with passing conf, but can't create receivers on non-local types, and won't move specifics into package app
// https://blog.questionable.services/article/http-handler-error-handling-revisited/ is the better idea, but more work
func (s *server) routes() {
s.router.HandleFunc("/", index.Handle(s.conf)).Methods("GET")
s.router.HandleFunc("/pingback", pingback.HandlePost(s.conf)).Methods("POST")
s.router.HandleFunc("/webmention", webmention.HandlePost(s.conf)).Methods("POST")
s.router.HandleFunc("/webmention/{domain}/{token}", s.authorizedOnly(webmention.HandleGet(s.conf))).Methods("GET")
s.router.HandleFunc("/webmention/{domain}/{token}", s.authorizedOnly(webmention.HandlePut(s.conf))).Methods("PUT")
cnf := s.conf
s.router.HandleFunc("/", index.Handle(cnf)).Methods("GET")
s.router.HandleFunc("/pingback", pingback.HandlePost(cnf)).Methods("POST")
s.router.HandleFunc("/webmention", webmention.HandlePost(cnf)).Methods("POST")
s.router.HandleFunc("/webmention/{domain}/{token}", s.authorizedOnly(webmention.HandleGet(cnf))).Methods("GET")
s.router.HandleFunc("/webmention/{domain}/{token}", s.authorizedOnly(webmention.HandlePut(cnf))).Methods("PUT")
}

View File

@ -2,13 +2,13 @@
package app
import (
"strconv"
"net/http"
"strconv"
"github.com/wgroeneveld/go-jamming/common"
"github.com/wgroeneveld/go-jamming/common"
"github.com/gorilla/mux"
"github.com/rs/zerolog/log"
"github.com/gorilla/mux"
"github.com/rs/zerolog/log"
)
type server struct {
@ -22,7 +22,7 @@ func unauthorized(w http.ResponseWriter, r *http.Request) { http.Error(w, "401 u
func (s *server) authorizedOnly(h http.HandlerFunc) http.HandlerFunc {
return func(w http.ResponseWriter, r *http.Request) {
vars := mux.Vars(r)
if vars["token"] != s.conf.Token {
if vars["token"] != s.conf.Token || !s.conf.IsAnAllowedDomain(vars["domain"]) {
unauthorized(w, r)
return
}

75
app/server_test.go Normal file
View File

@ -0,0 +1,75 @@
package app
import (
"github.com/gorilla/mux"
"github.com/stretchr/testify/assert"
"github.com/wgroeneveld/go-jamming/common"
"net/http"
"net/http/httptest"
"testing"
)
var conf = &common.Config{
Token: "boemsjakkalakka",
AllowedWebmentionSources: []string{ "http://ewelja.be" },
}
func TestAuthorizedOnlyUnauthorizedWithWrongToken(t *testing.T) {
srv := &server{
conf: conf,
}
passed := false
handler := srv.authorizedOnly(func(writer http.ResponseWriter, request *http.Request) {
passed = true
})
r, _ := http.NewRequest("PUT", "/whatever", nil)
w := httptest.NewRecorder()
r = mux.SetURLVars(r, map[string]string{
"token": "invalid",
"domain": conf.AllowedWebmentionSources[0],
})
handler(w, r)
assert.False(t, passed, "should not have called unauthorized func")
}
func TestAuthorizedOnlyUnauthorizedWithWrongDomain(t *testing.T) {
srv := &server{
conf: conf,
}
passed := false
handler := srv.authorizedOnly(func(writer http.ResponseWriter, request *http.Request) {
passed = true
})
r, _ := http.NewRequest("PUT", "/whatever", nil)
w := httptest.NewRecorder()
r = mux.SetURLVars(r, map[string]string{
"token": conf.Token,
"domain": "https://sexymoddafokkas.be",
})
handler(w, r)
assert.False(t, passed, "should not have called unauthorized func")
}
func TestAuthorizedOnlyOkIfTokenAndDomainMatch(t *testing.T) {
srv := &server{
conf: conf,
}
passed := false
handler := srv.authorizedOnly(func(writer http.ResponseWriter, request *http.Request) {
passed = true
})
r, _ := http.NewRequest("PUT", "/whatever", nil)
w := httptest.NewRecorder()
r = mux.SetURLVars(r, map[string]string{
"token": conf.Token,
"domain": conf.AllowedWebmentionSources[0],
})
handler(w, r)
assert.True(t, passed, "should have passed authentication!")
}

View File

@ -2,15 +2,19 @@
package webmention
import (
"fmt"
"github.com/gorilla/mux"
"github.com/wgroeneveld/go-jamming/app/mf"
"github.com/wgroeneveld/go-jamming/app/webmention/receive"
"github.com/wgroeneveld/go-jamming/app/webmention/send"
"net/http"
"fmt"
"github.com/wgroeneveld/go-jamming/common"
"github.com/wgroeneveld/go-jamming/rest"
"github.com/wgroeneveld/go-jamming/rest"
)
var httpClient = &rest.HttpClient{}
func HandleGet(conf *common.Config) http.HandlerFunc {
return func(w http.ResponseWriter, r *http.Request) {
fmt.Println("handling get")
@ -19,13 +23,28 @@ func HandleGet(conf *common.Config) http.HandlerFunc {
func HandlePut(conf *common.Config) http.HandlerFunc {
return func(w http.ResponseWriter, r *http.Request) {
fmt.Println("handling put")
}
since := getSinceQueryParam(r)
domain := mux.Vars(r)["domain"]
snder := send.Sender{
RestClient: httpClient,
Conf: conf,
}
go snder.Send(domain, since)
rest.Accept(w)
}
}
func getSinceQueryParam(r *http.Request) string {
sinceParam, _ := r.URL.Query()["since"]
since := ""
if len(sinceParam) > 0 {
since = sinceParam[0]
}
return since
}
func HandlePost(conf *common.Config) http.HandlerFunc {
httpClient := &rest.HttpClient{}
return func(w http.ResponseWriter, r *http.Request) {
r.ParseForm()
if !validate(r, r.Header, conf) {

View File

@ -1,6 +1,7 @@
package send
import (
"github.com/rs/zerolog/log"
"github.com/wgroeneveld/go-jamming/app/mf"
"github.com/wgroeneveld/go-jamming/app/pingback/send"
"github.com/wgroeneveld/go-jamming/common"
@ -12,6 +13,10 @@ type Sender struct {
Conf *common.Config
}
func (snder *Sender) Send(domain string, since string) {
log.Info().Str("domain", domain).Str("since", since).Msg(` OK: someone wants to send mentions`)
}
func mention() {
pingbackSender := &send.Sender{
RestClient: nil,

View File

@ -2,9 +2,9 @@
package common
import (
"errors"
"os"
"strconv"
"errors"
"strings"
"github.com/rs/zerolog/log"
@ -19,6 +19,15 @@ type Config struct {
DisallowedWebmentionDomains []string
}
func (c *Config) IsAnAllowedDomain(url string) bool {
for _, domain := range c.AllowedWebmentionSources {
if domain == url {
return true
}
}
return false
}
func (c *Config) FetchDomain(url string) (string, error) {
for _, domain := range c.AllowedWebmentionSources {
if strings.Contains(url, domain) {

View File

@ -2,5 +2,6 @@ package common
import "time"
// I know it's public. Not sure how to handle this in tests, package-independent
// https://labs.yulrizka.com/en/stubbing-time-dot-now-in-golang/
// None of the above are very appealing. For now, just use the lazy way.
var Now = time.Now