Impl import export endpoint
parent
3701479b5f
commit
acb3c93ead
|
|
@ -0,0 +1,62 @@
|
||||||
|
package server
|
||||||
|
|
||||||
|
import (
|
||||||
|
"encoding/json"
|
||||||
|
"local/dndex/server/auth"
|
||||||
|
"local/dndex/storage/entity"
|
||||||
|
"local/dndex/storage/operator"
|
||||||
|
"net/http"
|
||||||
|
|
||||||
|
"gopkg.in/mgo.v2/bson"
|
||||||
|
)
|
||||||
|
|
||||||
|
func (rest *REST) dump(w http.ResponseWriter, r *http.Request) {
|
||||||
|
switch r.Method {
|
||||||
|
case http.MethodGet:
|
||||||
|
rest.dumpOut(w, r)
|
||||||
|
case http.MethodPost:
|
||||||
|
rest.dumpIn(w, r)
|
||||||
|
default:
|
||||||
|
rest.respNotFound(w)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
func (rest *REST) dumpOut(w http.ResponseWriter, r *http.Request) {
|
||||||
|
scope := rest.scope(r)
|
||||||
|
entities, err := rest.g.List(r.Context(), scope.Namespace)
|
||||||
|
if err != nil {
|
||||||
|
rest.respError(w, err)
|
||||||
|
}
|
||||||
|
for i := len(entities) - 1; i >= 0; i-- {
|
||||||
|
if entities[i].ID == auth.UserKey {
|
||||||
|
if i < len(entities)-1 {
|
||||||
|
entities = append(entities[:i], entities[i+1:]...)
|
||||||
|
} else {
|
||||||
|
entities = entities[:i]
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
rest.respMap(w, scope.Namespace, entities)
|
||||||
|
}
|
||||||
|
|
||||||
|
func (rest *REST) dumpIn(w http.ResponseWriter, r *http.Request) {
|
||||||
|
scope := rest.scope(r)
|
||||||
|
var request map[string][]entity.One
|
||||||
|
if err := json.NewDecoder(r.Body).Decode(&request); err != nil {
|
||||||
|
rest.respBadRequest(w, err.Error())
|
||||||
|
return
|
||||||
|
}
|
||||||
|
for namespace, ones := range request {
|
||||||
|
if namespace == scope.Namespace {
|
||||||
|
for _, one := range ones {
|
||||||
|
if err := rest.g.Insert(r.Context(), scope.Namespace, one); err != nil {
|
||||||
|
if err := rest.g.Update(r.Context(), scope.Namespace, bson.M{entity.ID: one.ID}, operator.SetMany{Value: one}); err != nil {
|
||||||
|
rest.respError(w, err)
|
||||||
|
return
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
rest.entitiesGetN(w, r)
|
||||||
|
}
|
||||||
|
|
@ -0,0 +1,93 @@
|
||||||
|
package server
|
||||||
|
|
||||||
|
import (
|
||||||
|
"bytes"
|
||||||
|
"encoding/json"
|
||||||
|
"fmt"
|
||||||
|
"local/dndex/storage/entity"
|
||||||
|
"net/http"
|
||||||
|
"net/http/httptest"
|
||||||
|
"testing"
|
||||||
|
)
|
||||||
|
|
||||||
|
func TestDump(t *testing.T) {
|
||||||
|
cases := map[string]func(*testing.T, *REST, func(*http.Request)){
|
||||||
|
"dump out": func(t *testing.T, rest *REST, scope func(r *http.Request)) {
|
||||||
|
r := httptest.NewRequest(http.MethodGet, "/dump", nil)
|
||||||
|
w := httptest.NewRecorder()
|
||||||
|
scope(r)
|
||||||
|
rest.dump(w, r)
|
||||||
|
|
||||||
|
if w.Code != http.StatusOK {
|
||||||
|
t.Fatal(w.Code)
|
||||||
|
}
|
||||||
|
var dump map[string][]entity.One
|
||||||
|
if err := json.Unmarshal(w.Body.Bytes(), &dump); err != nil {
|
||||||
|
t.Fatal(err)
|
||||||
|
}
|
||||||
|
if len(dump) == 0 {
|
||||||
|
t.Fatal(dump)
|
||||||
|
}
|
||||||
|
for _, ones := range dump {
|
||||||
|
for _, one := range ones {
|
||||||
|
if fmt.Sprint(one) == fmt.Sprint(entity.One{}) {
|
||||||
|
t.Fatal(one)
|
||||||
|
}
|
||||||
|
if len(one.Attachments) == 0 {
|
||||||
|
t.Fatal(one)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
t.Logf("%d: %s: %+v", w.Code, w.Body.Bytes(), dump)
|
||||||
|
},
|
||||||
|
"dump in": func(t *testing.T, rest *REST, scope func(r *http.Request)) {
|
||||||
|
oneA := randomOne()
|
||||||
|
oneB := randomOne()
|
||||||
|
b, err := json.MarshalIndent(
|
||||||
|
map[string][]entity.One{testNamespace: []entity.One{oneA, oneB}},
|
||||||
|
"",
|
||||||
|
" ",
|
||||||
|
)
|
||||||
|
if err != nil {
|
||||||
|
t.Fatal(err)
|
||||||
|
}
|
||||||
|
t.Logf("dumping in %s", b)
|
||||||
|
r := httptest.NewRequest(http.MethodPost, "/dump", bytes.NewReader(b))
|
||||||
|
w := httptest.NewRecorder()
|
||||||
|
scope(r)
|
||||||
|
rest.dump(w, r)
|
||||||
|
if w.Code != http.StatusOK {
|
||||||
|
t.Fatal(w.Code)
|
||||||
|
}
|
||||||
|
foundA := false
|
||||||
|
foundB := false
|
||||||
|
b = w.Body.Bytes()
|
||||||
|
testEntitiesGetNResponse(t, w.Body, func(one shortEntity) bool {
|
||||||
|
foundA = foundA || one.ID == oneA.ID
|
||||||
|
foundB = foundB || one.ID == oneB.ID
|
||||||
|
return foundA && foundB
|
||||||
|
})
|
||||||
|
for _, one := range []entity.One{oneA, oneB} {
|
||||||
|
t.Logf("looking for %s", one.Name)
|
||||||
|
w = testEntitiesMethod(t, scope, rest, http.MethodGet, "/"+one.ID, ``)
|
||||||
|
if w.Code != http.StatusOK {
|
||||||
|
t.Fatal(w.Code, ":", string(w.Body.Bytes()))
|
||||||
|
}
|
||||||
|
testEntitiesGetOneResponse(t, w.Body, func(got entity.One) bool {
|
||||||
|
got.Modified = 0
|
||||||
|
one.Modified = 0
|
||||||
|
return fmt.Sprint(one) == fmt.Sprint(got)
|
||||||
|
})
|
||||||
|
}
|
||||||
|
},
|
||||||
|
}
|
||||||
|
|
||||||
|
for name, foo := range cases {
|
||||||
|
bar := foo
|
||||||
|
t.Run(name, func(t *testing.T) {
|
||||||
|
rest, scope, clean := testREST(t)
|
||||||
|
bar(t, rest, scope)
|
||||||
|
defer clean()
|
||||||
|
})
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
@ -39,13 +39,17 @@ func NewREST(g storage.RateLimitedGraph) (*REST, error) {
|
||||||
fmt.Sprintf("%s/%s", config.New().FilePrefix, params): rest.files,
|
fmt.Sprintf("%s/%s", config.New().FilePrefix, params): rest.files,
|
||||||
fmt.Sprintf("users/%s", param): rest.users,
|
fmt.Sprintf("users/%s", param): rest.users,
|
||||||
fmt.Sprintf("entities/%s", params): rest.entities,
|
fmt.Sprintf("entities/%s", params): rest.entities,
|
||||||
|
fmt.Sprintf("dump"): rest.dump,
|
||||||
}
|
}
|
||||||
|
|
||||||
for path, foo := range paths {
|
for path, foo := range paths {
|
||||||
bar := foo
|
bar := foo
|
||||||
bar = rest.shift(bar)
|
bar = rest.shift(bar)
|
||||||
bar = rest.scoped(bar)
|
bar = rest.scoped(bar)
|
||||||
if !strings.HasPrefix(path, "users/") && path != "version" {
|
switch strings.Split(path, "/")[0] {
|
||||||
|
case "users":
|
||||||
|
case "version":
|
||||||
|
default:
|
||||||
bar = rest.auth(bar)
|
bar = rest.auth(bar)
|
||||||
}
|
}
|
||||||
bar = rest.defend(bar)
|
bar = rest.defend(bar)
|
||||||
|
|
|
||||||
Loading…
Reference in New Issue