diff --git a/view/who.go b/view/who.go index 63c72bf..ce8b255 100644 --- a/view/who.go +++ b/view/who.go @@ -1,9 +1,11 @@ package view import ( + "bytes" "encoding/json" "errors" "fmt" + "io" "io/ioutil" "local/dndex/storage" "local/dndex/storage/entity" @@ -14,9 +16,15 @@ import ( "strings" "github.com/buger/jsonparser" + "github.com/iancoleman/orderedmap" "go.mongodb.org/mongo-driver/bson" ) +const ( + querySort = "sort" + queryOrder = "order" +) + func who(g storage.Graph, w http.ResponseWriter, r *http.Request) error { namespace, err := getNamespace(r) if err != nil { @@ -74,9 +82,30 @@ func whoGet(namespace string, g storage.Graph, w http.ResponseWriter, r *http.Re } } - enc := json.NewEncoder(w) - enc.SetIndent("", " ") - return enc.Encode(one) + b, err := json.MarshalIndent(one, "", " ") + if err != nil { + return err + } + if _, ok := r.URL.Query()[querySort]; ok { + m := bson.M{} + if err := json.Unmarshal(b, &m); err != nil { + return err + } + ones := make([]entity.One, len(one.Connections)) + i := 0 + for _, v := range one.Connections { + ones[i] = v + i++ + } + m[entity.Connections] = sortOnesObject(ones, r) + b, err = json.MarshalIndent(m, "", " ") + if err != nil { + return err + } + } + + _, err = io.Copy(w, bytes.NewReader(b)) + return err } func whoPut(namespace string, g storage.Graph, w http.ResponseWriter, r *http.Request) error { @@ -245,12 +274,21 @@ func getID(r *http.Request) (string, error) { return id, nil } +func sortOnesObject(ones []entity.One, r *http.Request) interface{} { + ones = sortOnes(ones, r) + m := orderedmap.New() + for _, one := range ones { + m.Set(one.Name, one) + } + return m +} + func sortOnes(ones []entity.One, r *http.Request) []entity.One { - sorting := sanitize(r.URL.Query().Get("sort")) + sorting := sanitize(r.URL.Query().Get(querySort)) if sorting == "" { sorting = entity.Modified } - order := sanitize(r.URL.Query().Get("order")) + order := sanitize(r.URL.Query().Get(queryOrder)) if order == "" { order = "-1" } diff --git a/view/who_test.go b/view/who_test.go index 578ddce..0a6e852 100644 --- a/view/who_test.go +++ b/view/who_test.go @@ -13,6 +13,8 @@ import ( "net/http/httptest" "net/url" "os" + "regexp" + "sort" "strings" "testing" "time" @@ -165,6 +167,49 @@ func TestWho(t *testing.T) { t.Logf("POST GET:\n%s", b) }) + t.Run("get sorted type asc/desc", func(t *testing.T) { + for _, order := range []string{"1", "-1"} { + reset() + want := ones[len(ones)-1] + r := httptest.NewRequest(http.MethodGet, "/who?namespace=col&light&sort=type&order="+order+"&id="+want.Name, nil) + w := httptest.NewRecorder() + handler.ServeHTTP(w, r) + if w.Code != http.StatusOK { + t.Fatalf("%d: %s", w.Code, w.Body.Bytes()) + } + o := entity.One{} + if err := json.Unmarshal(w.Body.Bytes(), &o); err != nil { + t.Fatal(err) + } + if len(o.Connections) < 5 { + t.Fatal(len(o.Connections)) + } + if len(o.Connections) != len(want.Connections) { + t.Fatal(len(want.Connections), len(o.Connections)) + } + titles := []string{} + for _, v := range want.Connections { + if len(v.Type) == 0 { + t.Fatal(v.Type) + } + titles = append(titles, v.Type) + } + sort.Strings(titles) + if order == "-1" { + for i := 0; i < len(titles)/2; i++ { + tmp := titles[len(titles)-1-i] + titles[len(titles)-1-i] = titles[i] + titles[i] = tmp + } + } + pattern := strings.Join(titles, ".*") + pattern = strings.Replace(pattern, "-", ".", -1) + if !regexp.MustCompile(pattern).Match(bytes.Replace(w.Body.Bytes(), []byte("\n"), []byte(" "), -1)) { + t.Fatal(order, pattern, string(w.Body.Bytes())) + } + } + }) + t.Run("put fake", func(t *testing.T) { reset() iwant := want @@ -486,7 +531,8 @@ func TestWho(t *testing.T) { t.Run("delete connection 1 of 1 ok", func(t *testing.T) { reset() - r := httptest.NewRequest(http.MethodDelete, fmt.Sprintf("/who?namespace=col&id=%s&connection=%s", want.Name, want.Peers()[0]), nil) + deleted := want.Peers()[0] + r := httptest.NewRequest(http.MethodDelete, fmt.Sprintf("/who?namespace=col&id=%s&connection=%s", want.Name, deleted), nil) w := httptest.NewRecorder() handler.ServeHTTP(w, r) if w.Code != http.StatusOK { @@ -503,8 +549,8 @@ func TestWho(t *testing.T) { if err := json.Unmarshal(w.Body.Bytes(), &o); err != nil { t.Fatal(err) } - if _, ok := o.Connections[want.Peers()[0]]; ok { - t.Fatal(want.Peers()[0], o.Connections) + if _, ok := o.Connections[deleted]; ok { + t.Fatal(deleted, o.Connections) } }) @@ -590,9 +636,10 @@ func fillDB(t *testing.T, g storage.Graph) []entity.One { ones := make([]entity.One, 13) for i := range ones { ones[i] = randomOne() - if i > 0 { - ones[i].Connections[ones[i-1].Name] = entity.One{ - Name: ones[i-1].Name, + for j := 0; j < i; j++ { + ones[i].Connections[ones[j].Name] = entity.One{ + Name: ones[j].Name, + Type: ones[j].Type, Relationship: ":D", } }