forked from wgroeneveld/go-jamming
add domain authentication handling, start wm PUT
This commit is contained in:
parent
f74c0c6e5b
commit
9f6450e367
|
@ -3,18 +3,20 @@ package app
|
||||||
|
|
||||||
import (
|
import (
|
||||||
"github.com/wgroeneveld/go-jamming/app/index"
|
"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/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
|
// 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
|
// 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
|
// https://blog.questionable.services/article/http-handler-error-handling-revisited/ is the better idea, but more work
|
||||||
func (s *server) routes() {
|
func (s *server) routes() {
|
||||||
s.router.HandleFunc("/", index.Handle(s.conf)).Methods("GET")
|
cnf := s.conf
|
||||||
s.router.HandleFunc("/pingback", pingback.HandlePost(s.conf)).Methods("POST")
|
|
||||||
s.router.HandleFunc("/webmention", webmention.HandlePost(s.conf)).Methods("POST")
|
s.router.HandleFunc("/", index.Handle(cnf)).Methods("GET")
|
||||||
s.router.HandleFunc("/webmention/{domain}/{token}", s.authorizedOnly(webmention.HandleGet(s.conf))).Methods("GET")
|
s.router.HandleFunc("/pingback", pingback.HandlePost(cnf)).Methods("POST")
|
||||||
s.router.HandleFunc("/webmention/{domain}/{token}", s.authorizedOnly(webmention.HandlePut(s.conf))).Methods("PUT")
|
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")
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -2,13 +2,13 @@
|
||||||
package app
|
package app
|
||||||
|
|
||||||
import (
|
import (
|
||||||
"strconv"
|
|
||||||
"net/http"
|
"net/http"
|
||||||
|
"strconv"
|
||||||
|
|
||||||
"github.com/wgroeneveld/go-jamming/common"
|
"github.com/wgroeneveld/go-jamming/common"
|
||||||
|
|
||||||
"github.com/gorilla/mux"
|
"github.com/gorilla/mux"
|
||||||
"github.com/rs/zerolog/log"
|
"github.com/rs/zerolog/log"
|
||||||
)
|
)
|
||||||
|
|
||||||
type server struct {
|
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 {
|
func (s *server) authorizedOnly(h http.HandlerFunc) http.HandlerFunc {
|
||||||
return func(w http.ResponseWriter, r *http.Request) {
|
return func(w http.ResponseWriter, r *http.Request) {
|
||||||
vars := mux.Vars(r)
|
vars := mux.Vars(r)
|
||||||
if vars["token"] != s.conf.Token {
|
if vars["token"] != s.conf.Token || !s.conf.IsAnAllowedDomain(vars["domain"]) {
|
||||||
unauthorized(w, r)
|
unauthorized(w, r)
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
|
|
@ -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!")
|
||||||
|
}
|
|
@ -2,15 +2,19 @@
|
||||||
package webmention
|
package webmention
|
||||||
|
|
||||||
import (
|
import (
|
||||||
|
"fmt"
|
||||||
|
"github.com/gorilla/mux"
|
||||||
"github.com/wgroeneveld/go-jamming/app/mf"
|
"github.com/wgroeneveld/go-jamming/app/mf"
|
||||||
"github.com/wgroeneveld/go-jamming/app/webmention/receive"
|
"github.com/wgroeneveld/go-jamming/app/webmention/receive"
|
||||||
|
"github.com/wgroeneveld/go-jamming/app/webmention/send"
|
||||||
"net/http"
|
"net/http"
|
||||||
"fmt"
|
|
||||||
|
|
||||||
"github.com/wgroeneveld/go-jamming/common"
|
"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 {
|
func HandleGet(conf *common.Config) http.HandlerFunc {
|
||||||
return func(w http.ResponseWriter, r *http.Request) {
|
return func(w http.ResponseWriter, r *http.Request) {
|
||||||
fmt.Println("handling get")
|
fmt.Println("handling get")
|
||||||
|
@ -19,13 +23,28 @@ func HandleGet(conf *common.Config) http.HandlerFunc {
|
||||||
|
|
||||||
func HandlePut(conf *common.Config) http.HandlerFunc {
|
func HandlePut(conf *common.Config) http.HandlerFunc {
|
||||||
return func(w http.ResponseWriter, r *http.Request) {
|
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 {
|
func HandlePost(conf *common.Config) http.HandlerFunc {
|
||||||
httpClient := &rest.HttpClient{}
|
|
||||||
|
|
||||||
return func(w http.ResponseWriter, r *http.Request) {
|
return func(w http.ResponseWriter, r *http.Request) {
|
||||||
r.ParseForm()
|
r.ParseForm()
|
||||||
if !validate(r, r.Header, conf) {
|
if !validate(r, r.Header, conf) {
|
||||||
|
|
|
@ -1,6 +1,7 @@
|
||||||
package send
|
package send
|
||||||
|
|
||||||
import (
|
import (
|
||||||
|
"github.com/rs/zerolog/log"
|
||||||
"github.com/wgroeneveld/go-jamming/app/mf"
|
"github.com/wgroeneveld/go-jamming/app/mf"
|
||||||
"github.com/wgroeneveld/go-jamming/app/pingback/send"
|
"github.com/wgroeneveld/go-jamming/app/pingback/send"
|
||||||
"github.com/wgroeneveld/go-jamming/common"
|
"github.com/wgroeneveld/go-jamming/common"
|
||||||
|
@ -12,6 +13,10 @@ type Sender struct {
|
||||||
Conf *common.Config
|
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() {
|
func mention() {
|
||||||
pingbackSender := &send.Sender{
|
pingbackSender := &send.Sender{
|
||||||
RestClient: nil,
|
RestClient: nil,
|
||||||
|
|
|
@ -2,9 +2,9 @@
|
||||||
package common
|
package common
|
||||||
|
|
||||||
import (
|
import (
|
||||||
|
"errors"
|
||||||
"os"
|
"os"
|
||||||
"strconv"
|
"strconv"
|
||||||
"errors"
|
|
||||||
"strings"
|
"strings"
|
||||||
|
|
||||||
"github.com/rs/zerolog/log"
|
"github.com/rs/zerolog/log"
|
||||||
|
@ -19,6 +19,15 @@ type Config struct {
|
||||||
DisallowedWebmentionDomains []string
|
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) {
|
func (c *Config) FetchDomain(url string) (string, error) {
|
||||||
for _, domain := range c.AllowedWebmentionSources {
|
for _, domain := range c.AllowedWebmentionSources {
|
||||||
if strings.Contains(url, domain) {
|
if strings.Contains(url, domain) {
|
||||||
|
|
|
@ -2,5 +2,6 @@ package common
|
||||||
|
|
||||||
import "time"
|
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
|
var Now = time.Now
|
||||||
|
|
Loading…
Reference in New Issue