only store the last AUTH challenge and allow user to perform auth only whenever they want instead of automatically.
This commit is contained in:
@@ -51,7 +51,7 @@ type Relay struct {
|
|||||||
connectionContext context.Context // will be canceled when the connection closes
|
connectionContext context.Context // will be canceled when the connection closes
|
||||||
connectionContextCancel context.CancelFunc
|
connectionContextCancel context.CancelFunc
|
||||||
|
|
||||||
challenges chan string // NIP-42 challenges
|
challenge string // NIP-42 challenge, we only keep the last
|
||||||
notices chan string // NIP-01 NOTICEs
|
notices chan string // NIP-01 NOTICEs
|
||||||
okCallbacks *xsync.MapOf[string, func(bool, string)]
|
okCallbacks *xsync.MapOf[string, func(bool, string)]
|
||||||
writeQueue chan writeRequest
|
writeQueue chan writeRequest
|
||||||
@@ -89,24 +89,6 @@ func NewRelay(ctx context.Context, url string, opts ...RelayOption) *Relay {
|
|||||||
o(notice)
|
o(notice)
|
||||||
}
|
}
|
||||||
}()
|
}()
|
||||||
case WithAuthHandler:
|
|
||||||
r.challenges = make(chan string)
|
|
||||||
go func() {
|
|
||||||
for challenge := range r.challenges {
|
|
||||||
authEvent := Event{
|
|
||||||
CreatedAt: Now(),
|
|
||||||
Kind: KindClientAuthentication,
|
|
||||||
Tags: Tags{
|
|
||||||
Tag{"relay", url},
|
|
||||||
Tag{"challenge", challenge},
|
|
||||||
},
|
|
||||||
Content: "",
|
|
||||||
}
|
|
||||||
if ok := o(r.connectionContext, &authEvent); ok {
|
|
||||||
r.Auth(r.connectionContext, authEvent)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}()
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -137,14 +119,6 @@ func (_ WithNoticeHandler) IsRelayOption() {}
|
|||||||
|
|
||||||
var _ RelayOption = (WithNoticeHandler)(nil)
|
var _ RelayOption = (WithNoticeHandler)(nil)
|
||||||
|
|
||||||
// WithAuthHandler takes an auth event and expects it to be signed.
|
|
||||||
// when not given, AUTH messages from relays are ignored.
|
|
||||||
type WithAuthHandler func(ctx context.Context, authEvent *Event) (ok bool)
|
|
||||||
|
|
||||||
func (_ WithAuthHandler) IsRelayOption() {}
|
|
||||||
|
|
||||||
var _ RelayOption = (WithAuthHandler)(nil)
|
|
||||||
|
|
||||||
// String just returns the relay URL.
|
// String just returns the relay URL.
|
||||||
func (r *Relay) String() string {
|
func (r *Relay) String() string {
|
||||||
return r.URL
|
return r.URL
|
||||||
@@ -193,9 +167,6 @@ func (r *Relay) Connect(ctx context.Context) error {
|
|||||||
go func() {
|
go func() {
|
||||||
<-r.connectionContext.Done()
|
<-r.connectionContext.Done()
|
||||||
// close these things when the connection is closed
|
// close these things when the connection is closed
|
||||||
if r.challenges != nil {
|
|
||||||
close(r.challenges)
|
|
||||||
}
|
|
||||||
if r.notices != nil {
|
if r.notices != nil {
|
||||||
close(r.notices)
|
close(r.notices)
|
||||||
}
|
}
|
||||||
@@ -263,10 +234,7 @@ func (r *Relay) Connect(ctx context.Context) error {
|
|||||||
if env.Challenge == nil {
|
if env.Challenge == nil {
|
||||||
continue
|
continue
|
||||||
}
|
}
|
||||||
// see WithAuthHandler
|
r.challenge = *env.Challenge
|
||||||
if r.challenges != nil {
|
|
||||||
r.challenges <- *env.Challenge
|
|
||||||
}
|
|
||||||
case *EventEnvelope:
|
case *EventEnvelope:
|
||||||
if env.SubscriptionID == nil {
|
if env.SubscriptionID == nil {
|
||||||
continue
|
continue
|
||||||
@@ -393,8 +361,22 @@ func (r *Relay) Publish(ctx context.Context, event Event) (Status, error) {
|
|||||||
|
|
||||||
// Auth sends an "AUTH" command client -> relay as in NIP-42.
|
// Auth sends an "AUTH" command client -> relay as in NIP-42.
|
||||||
// Status can be: success, failed, or sent (no response from relay before ctx times out).
|
// Status can be: success, failed, or sent (no response from relay before ctx times out).
|
||||||
func (r *Relay) Auth(ctx context.Context, event Event) (Status, error) {
|
func (r *Relay) Auth(ctx context.Context, sign func(event *Event) error) (Status, error) {
|
||||||
status := PublishStatusFailed
|
status := PublishStatusFailed
|
||||||
|
|
||||||
|
authEvent := Event{
|
||||||
|
CreatedAt: Now(),
|
||||||
|
Kind: KindClientAuthentication,
|
||||||
|
Tags: Tags{
|
||||||
|
Tag{"relay", r.URL},
|
||||||
|
Tag{"challenge", r.challenge},
|
||||||
|
},
|
||||||
|
Content: "",
|
||||||
|
}
|
||||||
|
if err := sign(&authEvent); err != nil {
|
||||||
|
return status, fmt.Errorf("error signing auth event: %w", err)
|
||||||
|
}
|
||||||
|
|
||||||
var err error
|
var err error
|
||||||
|
|
||||||
// data races on status variable without this mutex
|
// data races on status variable without this mutex
|
||||||
@@ -413,7 +395,7 @@ func (r *Relay) Auth(ctx context.Context, event Event) (Status, error) {
|
|||||||
defer cancel()
|
defer cancel()
|
||||||
|
|
||||||
// listen for an OK callback
|
// listen for an OK callback
|
||||||
r.okCallbacks.Store(event.ID, func(ok bool, reason string) {
|
r.okCallbacks.Store(authEvent.ID, func(ok bool, reason string) {
|
||||||
mu.Lock()
|
mu.Lock()
|
||||||
if ok {
|
if ok {
|
||||||
status = PublishStatusSucceeded
|
status = PublishStatusSucceeded
|
||||||
@@ -424,10 +406,10 @@ func (r *Relay) Auth(ctx context.Context, event Event) (Status, error) {
|
|||||||
mu.Unlock()
|
mu.Unlock()
|
||||||
cancel()
|
cancel()
|
||||||
})
|
})
|
||||||
defer r.okCallbacks.Delete(event.ID)
|
defer r.okCallbacks.Delete(authEvent.ID)
|
||||||
|
|
||||||
// send AUTH
|
// send AUTH
|
||||||
authResponse, _ := AuthEnvelope{Event: event}.MarshalJSON()
|
authResponse, _ := AuthEnvelope{Event: authEvent}.MarshalJSON()
|
||||||
debugLogf("{%s} sending %v\n", r.URL, authResponse)
|
debugLogf("{%s} sending %v\n", r.URL, authResponse)
|
||||||
if err := <-r.Write(authResponse); err != nil {
|
if err := <-r.Write(authResponse); err != nil {
|
||||||
// status will be "failed"
|
// status will be "failed"
|
||||||
|
|||||||
Reference in New Issue
Block a user