Compare commits

...

4 Commits

Author SHA1 Message Date
fiatjaf
31128ebd18 filter policy: MustAuth() 2025-02-02 14:30:28 -03:00
k.
414867e62c feat(blossom): add bud-09 reporting handler. (#29) 2025-02-01 18:03:17 -03:00
Kay
65383d6d65 making it a little better, so compiler wont complain. 2025-01-28 15:26:38 -03:00
Anthony Accioly
c4d9ef1025 fix(blossom): respond with 401 on missing Auth 2025-01-26 17:23:29 -03:00
6 changed files with 60 additions and 13 deletions

1
.gitignore vendored
View File

@@ -1,2 +1,3 @@
*.env
.idea/
knowledge.md

View File

@@ -43,7 +43,7 @@ func (rl *Relay) AddEvent(ctx context.Context, evt *nostr.Event) (skipBroadcast
case eventstore.ErrDupEvent:
return true, nil
default:
return false, fmt.Errorf(nostr.NormalizeOKMessage(err.Error(), "error"))
return false, fmt.Errorf("%s", nostr.NormalizeOKMessage(err.Error(), "error"))
}
}
}
@@ -56,7 +56,7 @@ func (rl *Relay) AddEvent(ctx context.Context, evt *nostr.Event) (skipBroadcast
case eventstore.ErrDupEvent:
return true, nil
default:
return false, fmt.Errorf(nostr.NormalizeOKMessage(err.Error(), "error"))
return false, fmt.Errorf("%s", nostr.NormalizeOKMessage(err.Error(), "error"))
}
}
}
@@ -95,7 +95,7 @@ func (rl *Relay) AddEvent(ctx context.Context, evt *nostr.Event) (skipBroadcast
case eventstore.ErrDupEvent:
return true, nil
default:
return false, fmt.Errorf(nostr.NormalizeOKMessage(saveErr.Error(), "error"))
return false, fmt.Errorf("%s", nostr.NormalizeOKMessage(saveErr.Error(), "error"))
}
}
}

View File

@@ -22,7 +22,7 @@ func (bs BlossomServer) handleUploadCheck(w http.ResponseWriter, r *http.Request
return
}
if auth == nil {
blossomError(w, "missing \"Authorization\" header", 400)
blossomError(w, "missing \"Authorization\" header", 401)
return
}
if auth.Tags.GetFirst([]string{"t", "upload"}) == nil {
@@ -52,11 +52,11 @@ func (bs BlossomServer) handleUploadCheck(w http.ResponseWriter, r *http.Request
func (bs BlossomServer) handleUpload(w http.ResponseWriter, r *http.Request) {
auth, err := readAuthorization(r)
if err != nil {
blossomError(w, "invalid \"Authorization\": "+err.Error(), 400)
blossomError(w, "invalid \"Authorization\": "+err.Error(), 404)
return
}
if auth == nil {
blossomError(w, "missing \"Authorization\" header", 400)
blossomError(w, "missing \"Authorization\" header", 401)
return
}
if auth.Tags.GetFirst([]string{"t", "upload"}) == nil {
@@ -206,7 +206,6 @@ func (bs BlossomServer) handleGetBlob(w http.ResponseWriter, r *http.Request) {
}
blossomError(w, "file not found", 404)
return
}
func (bs BlossomServer) handleHasBlob(w http.ResponseWriter, r *http.Request) {
@@ -228,8 +227,6 @@ func (bs BlossomServer) handleHasBlob(w http.ResponseWriter, r *http.Request) {
blossomError(w, "file not found", 404)
return
}
return
}
func (bs BlossomServer) handleList(w http.ResponseWriter, r *http.Request) {
@@ -331,6 +328,38 @@ func (bs BlossomServer) handleDelete(w http.ResponseWriter, r *http.Request) {
}
}
func (bs BlossomServer) handleReport(w http.ResponseWriter, r *http.Request) {
var body []byte
_, err := r.Body.Read(body)
if err != nil {
blossomError(w, "can't read request body", 400)
return
}
var evt *nostr.Event
if err := json.Unmarshal(body, evt); err != nil {
blossomError(w, "can't parse event", 400)
return
}
if isValid, _ := evt.CheckSignature(); !isValid {
blossomError(w, "invalid report event is provided", 400)
return
}
if evt.Kind != nostr.KindReporting {
blossomError(w, "invalid report event is provided", 400)
return
}
for _, rr := range bs.ReceiveReport {
if err := rr(r.Context(), evt); err != nil {
blossomError(w, "failed to receive report: "+err.Error(), 500)
return
}
}
}
func (bs BlossomServer) handleMirror(w http.ResponseWriter, r *http.Request) {
}

View File

@@ -14,9 +14,10 @@ type BlossomServer struct {
ServiceURL string
Store BlobIndex
StoreBlob []func(ctx context.Context, sha256 string, body []byte) error
LoadBlob []func(ctx context.Context, sha256 string) (io.ReadSeeker, error)
DeleteBlob []func(ctx context.Context, sha256 string) error
StoreBlob []func(ctx context.Context, sha256 string, body []byte) error
LoadBlob []func(ctx context.Context, sha256 string) (io.ReadSeeker, error)
DeleteBlob []func(ctx context.Context, sha256 string) error
ReceiveReport []func(ctx context.Context, reportEvt *nostr.Event) error
RejectUpload []func(ctx context.Context, auth *nostr.Event, size int, ext string) (bool, string, int)
RejectGet []func(ctx context.Context, auth *nostr.Event, sha256 string) (bool, string, int)
@@ -61,6 +62,13 @@ func New(rl *khatru.Relay, serviceURL string) *BlossomServer {
}
}
if r.URL.Path == "/report" {
if r.Method == "PUT" {
bs.handleReport(w, r)
return
}
}
base.ServeHTTP(w, r)
})

View File

@@ -4,6 +4,7 @@ import (
"context"
"slices"
"github.com/fiatjaf/khatru"
"github.com/nbd-wtf/go-nostr"
)
@@ -18,6 +19,14 @@ func NoComplexFilters(ctx context.Context, filter nostr.Filter) (reject bool, ms
return false, ""
}
// MustAuth requires all subscribers to be authenticated
func MustAuth(ctx context.Context, filter nostr.Filter) (reject bool, msg string) {
if khatru.GetAuthed(ctx) == "" {
return true, "auth-required: all requests must be authenticated"
}
return false, ""
}
// NoEmptyFilters disallows filters that don't have at least a tag, a kind, an author or an id.
func NoEmptyFilters(ctx context.Context, filter nostr.Filter) (reject bool, msg string) {
c := len(filter.Kinds) + len(filter.IDs) + len(filter.Authors)

View File

@@ -131,7 +131,7 @@ func (rl *Relay) getBaseURL(r *http.Request) string {
if proto == "" {
if host == "localhost" {
proto = "http"
} else if strings.Index(host, ":") != -1 {
} else if strings.Contains(host, ":") {
// has a port number
proto = "http"
} else if _, err := strconv.Atoi(strings.ReplaceAll(host, ".", "")); err == nil {