Skip to content
This repository has been archived by the owner on Mar 28, 2023. It is now read-only.

Commit

Permalink
Merge pull request #1501 from OpenBazaar/modpanic
Browse files Browse the repository at this point in the history
Fix NotifyModerators panic if node is not yet bootstrapped
  • Loading branch information
cpacia committed Mar 15, 2019
2 parents bd6a206 + d738a00 commit c489832
Show file tree
Hide file tree
Showing 9 changed files with 79 additions and 32 deletions.
4 changes: 2 additions & 2 deletions api/endpoints.go
Expand Up @@ -98,7 +98,7 @@ func post(i *jsonAPIHandler, path string, w http.ResponseWriter, r *http.Request
case strings.HasPrefix(path, "/ob/purchases"):
i.POSTPurchases(w, r)
case strings.HasPrefix(path, "/ob/purchase"):
i.POSTPurchase(w, r)
blockingStartupMiddleware(i, w, r, i.POSTPurchase)
case strings.HasPrefix(path, "/ob/cases"):
i.POSTCases(w, r)
case strings.HasPrefix(path, "/ob/publish"):
Expand Down Expand Up @@ -258,6 +258,6 @@ func gatewayAllowedPath(path, method string) bool {
}

func blockingStartupMiddleware(i *jsonAPIHandler, w http.ResponseWriter, r *http.Request, requestFunc func(w http.ResponseWriter, r *http.Request)) {
<-i.node.DHT.BootstrapChan
i.node.Service.WaitForReady()
requestFunc(w, r)
}
17 changes: 12 additions & 5 deletions api/jsonapi.go
Expand Up @@ -8,7 +8,6 @@ import (
"encoding/hex"
"encoding/json"
"fmt"

"gx/ipfs/QmPSQnBKM9g7BaUcZCvswUJVscQ1ipjmwxN5PXCjkp9EQ7/go-cid"
mh "gx/ipfs/QmPnFwZ2JXKnXgMw8CdBPxn7FWh6LLdjUjxV1fKHuJnkr8/go-multihash"
"gx/ipfs/QmTRhk7cgjUf2gfQ3p2M9KPECNZEW9XUrmHcFCgog4cPgB/go-libp2p-peer"
Expand Down Expand Up @@ -857,7 +856,8 @@ func (i *jsonAPIHandler) POSTSettings(w http.ResponseWriter, r *http.Request) {
i.node.BanManager.SetBlockedIds(blockedIds)
}
if settings.StoreModerators != nil {
go i.node.NotifyModerators(*settings.StoreModerators)
modsToAdd, modsToDelete := extractModeratorChanges(*settings.StoreModerators, nil)
go i.node.NotifyModerators(modsToAdd, modsToDelete)
if err := i.node.SetModeratorsOnListings(*settings.StoreModerators); err != nil {
ErrorResponse(w, http.StatusInternalServerError, err.Error())
}
Expand Down Expand Up @@ -895,7 +895,7 @@ func (i *jsonAPIHandler) PUTSettings(w http.ResponseWriter, r *http.Request) {
ErrorResponse(w, http.StatusBadRequest, err.Error())
return
}
_, err = i.node.Datastore.Settings().Get()
currentSettings, err := i.node.Datastore.Settings().Get()
if err != nil {
ErrorResponse(w, http.StatusNotFound, "Settings is not yet set. Use POST.")
return
Expand All @@ -912,7 +912,8 @@ func (i *jsonAPIHandler) PUTSettings(w http.ResponseWriter, r *http.Request) {
i.node.BanManager.SetBlockedIds(blockedIds)
}
if settings.StoreModerators != nil {
go i.node.NotifyModerators(*settings.StoreModerators)
modsToAdd, modsToDelete := extractModeratorChanges(*settings.StoreModerators, currentSettings.StoreModerators)
go i.node.NotifyModerators(modsToAdd, modsToDelete)
if err := i.node.SetModeratorsOnListings(*settings.StoreModerators); err != nil {
ErrorResponse(w, http.StatusInternalServerError, err.Error())
}
Expand Down Expand Up @@ -957,6 +958,11 @@ func (i *jsonAPIHandler) PATCHSettings(w http.ResponseWriter, r *http.Request) {
}
return
}
currentSettings, err := i.node.Datastore.Settings().Get()
if err != nil {
ErrorResponse(w, http.StatusNotFound, "Settings is not yet set. Use POST.")
return
}
if err = validateSMTPSettings(settings); err != nil {
ErrorResponse(w, http.StatusBadRequest, err.Error())
return
Expand All @@ -966,7 +972,8 @@ func (i *jsonAPIHandler) PATCHSettings(w http.ResponseWriter, r *http.Request) {
return
}
if settings.StoreModerators != nil {
go i.node.NotifyModerators(*settings.StoreModerators)
modsToAdd, modsToDelete := extractModeratorChanges(*settings.StoreModerators, currentSettings.StoreModerators)
go i.node.NotifyModerators(modsToAdd, modsToDelete)
if err := i.node.SetModeratorsOnListings(*settings.StoreModerators); err != nil {
ErrorResponse(w, http.StatusInternalServerError, err.Error())
}
Expand Down
28 changes: 28 additions & 0 deletions api/utils.go
Expand Up @@ -59,3 +59,31 @@ func convertOrderStates(states []int) []pb.OrderState {
}
return orderStates
}

func extractModeratorChanges(newModList []string, currentModList *[]string) (toAdd, toDelete []string) {
currentModMap := make(map[string]bool)
if currentModList != nil {
for _, mod := range *currentModList {
currentModMap[mod] = true
}
}

newModMap := make(map[string]bool)
for _, mod := range newModList {
newModMap[mod] = true
}

for _, mod := range newModList {
if !currentModMap[mod] {
toAdd = append(toAdd, mod)
}
}

for mod := range currentModMap {
if !newModMap[mod] {
toDelete = append(toDelete, mod)
}
}

return toAdd, toDelete
}
25 changes: 25 additions & 0 deletions api/utils_test.go
@@ -0,0 +1,25 @@
package api

import (
"testing"
)

func Test_extractModeratorChanges(t *testing.T) {
currentModList := []string{"a", "b", "c"}
newModList := []string{"a", "x", "c"}

toAdd, toDelete := extractModeratorChanges(newModList, &currentModList)
if len(toAdd) != 1 {
t.Errorf("Returned incorrect number of additions: expected %d got %d", 1, len(toAdd))
}
if len(toDelete) != 1 {
t.Errorf("Returned incorrect number of deletions: expected %d got %d", 1, len(toDelete))
}

if toAdd[0] != "x" {
t.Errorf("Returned incorrect addition: expected a got %s", toAdd[0])
}
if toDelete[0] != "b" {
t.Errorf("Returned incorrect deletion: expected b got %s", toDelete[0])
}
}
2 changes: 1 addition & 1 deletion cmd/start.go
Expand Up @@ -713,8 +713,8 @@ func (x *Start) Execute(args []string) error {
}()
}
}
<-core.Node.DHT.BootstrapChan
core.Node.Service = service.New(core.Node, sqliteDB)
core.Node.Service.WaitForReady()

core.Node.StartMessageRetriever()
core.Node.StartPointerRepublisher()
Expand Down
26 changes: 3 additions & 23 deletions core/moderation.go
Expand Up @@ -262,32 +262,12 @@ func (n *OpenBazaarNode) SetModeratorsOnListings(moderators []string) error {
}

// NotifyModerators - notify moderators(peers)
func (n *OpenBazaarNode) NotifyModerators(moderators []string) error {
settings, err := n.Datastore.Settings().Get()
if err != nil {
return err
}
currentMods := make(map[string]bool)
if settings.StoreModerators != nil {
for _, mod := range *settings.StoreModerators {
currentMods[mod] = true
}
}
var addedMods []string
for _, mod := range moderators {
if !currentMods[mod] {
addedMods = append(addedMods, mod)
} else {
delete(currentMods, mod)
}
}

removedMods := currentMods

func (n *OpenBazaarNode) NotifyModerators(addedMods, removedMods []string) error {
n.Service.WaitForReady()
for _, mod := range addedMods {
go n.SendModeratorAdd(mod)
}
for mod := range removedMods {
for _, mod := range removedMods {
go n.SendModeratorRemove(mod)
}
return nil
Expand Down
2 changes: 1 addition & 1 deletion mobile/node.go
Expand Up @@ -383,8 +383,8 @@ func (n *Node) Start() error {
}()
}
}
<-n.OpenBazaarNode.DHT.BootstrapChan
n.OpenBazaarNode.Service = service.New(n.OpenBazaarNode, n.OpenBazaarNode.Datastore)
n.OpenBazaarNode.Service.WaitForReady()
MR := ret.NewMessageRetriever(ret.MRConfig{
Db: n.OpenBazaarNode.Datastore,
IPFSNode: n.OpenBazaarNode.IpfsNode,
Expand Down
3 changes: 3 additions & 0 deletions net/networkservice.go
Expand Up @@ -30,4 +30,7 @@ type NetworkService interface {

// Disconnect from the given peer
DisconnectFromPeer(p peer.ID) error

// Block until the service is available
WaitForReady()
}
4 changes: 4 additions & 0 deletions net/service/service.go
Expand Up @@ -54,6 +54,10 @@ func New(node *core.OpenBazaarNode, datastore repo.Datastore) *OpenBazaarService
return service
}

func (service *OpenBazaarService) WaitForReady() {
<-service.node.DHT.BootstrapChan
}

func (service *OpenBazaarService) DisconnectFromPeer(p peer.ID) error {
log.Debugf("Disconnecting from %s", p.Pretty())
service.senderlk.Lock()
Expand Down

0 comments on commit c489832

Please sign in to comment.