Ejemplo n.º 1
0
func BenchmarkGraphQLQuery(b *testing.B) {
	rec = httptest.NewRecorder()
	server = handle.BuildHandler()

	db.Erase()
	db.Start()
	populateDB()

	for i := 0; i < b.N; i++ {
		/* BENCHMARK CODE */
		r, _ = http.NewRequest("POST", "/_graphql", bytes.NewReader([]byte(`query {
              root:_val
              vehicles {
                desc:_val
                car { land, water }
                airplane { land, air }
              }
            }`)))
		r.Header.Set("Content-Type", "application/graphql")
		server.ServeHTTP(rec, r)
		/* END BENCHMARK CODE */
	}

	db.End()
}
Ejemplo n.º 2
0
func main() {
	usage := `SummaDB ` + settings.VERSION + `

Usage:
  summadb [--reset] [--debug] [--cors=<domains>] [--port=<port>] [--db=<dbfile>]

Options:
  -h --help        Show this screen.
  --version        Show version.
  --db=<dbfile>    The path of the underlying LevelDB [default: /tmp/summa.db]
  --port=<port>    Choose the port in which the HTTP server will listen [default: 5000]
  --cors=<domains> Specify a list of comma-separated domains [default: *]
  --reset          Before starting, erase all database contents and start from zero.
  --debug          Force debug. Overrides DEBUG and LOGLEVEL environment variable.
    `
	arguments, _ := docopt.Parse(usage, nil, true, settings.VERSION, false)
	settings.HandleArgs(arguments)

	log.WithFields(log.Fields{
		"DBFILE":       settings.DBFILE,
		"PORT":         settings.PORT,
		"CORS_ORIGINS": settings.CORS_ORIGINS,
		"LOGLEVEL":     settings.LOGLEVEL,
	}).Info("starting database server.")

	if reset, _ := arguments["--reset"]; reset != nil && reset.(bool) {
		db.Erase()
	}
	db.Start()

	handler := handle.BuildHandler()
	server := &graceful.Server{
		Timeout: 2 * time.Second,
		Server: &http.Server{
			Addr:    ":" + settings.PORT,
			Handler: handler,
		},
	}
	stop := server.StopChan()
	server.ListenAndServe()

	<-stop
	log.Info("Exiting...")
	db.End()
}
Ejemplo n.º 3
0
func TestCouchDBSpecialEndpoints(t *testing.T) {
	g := Goblin(t)
	RegisterFailHandler(func(m string, _ ...int) { g.Fail(m) })

	g.Describe("couchdb db special endpoints", func() {
		g.BeforeEach(func() {
			rec = httptest.NewRecorder()
			server = handle.BuildHandler()
		})

		g.Before(func() {
			db.Erase()
			db.Start()
			populateDB()
		})

		g.After(func() {
			db.End()
		})

		var rev string
		var oldrev string
		var id string

		g.It("_all_docs for a sub db", func() {
			r, _ = http.NewRequest("GET", "/vehicles/_all_docs", nil)
			server.ServeHTTP(rec, r)

			var res responses.AllDocs
			json.Unmarshal(rec.Body.Bytes(), &res)
			Expect(res.Rows).To(HaveLen(3))
			Expect(res.Rows[2].Id).To(Equal(res.Rows[2].Key))
			rev, _ := res.Rows[2].Value.(map[string]interface{})["rev"]
			Expect(rev).To(HavePrefix("1-"))

			keys := []string{res.Rows[0].Id, res.Rows[1].Key, res.Rows[2].Id}
			Expect(keys).To(ConsistOf("airplane", "boat", "car"))
		})

		g.It("_all_docs with selected keys", func() {
			r, _ = http.NewRequest("GET", "/vehicles/_all_docs?keys=%5B%22airplane%22,%22boat%22%5D", nil)
			server.ServeHTTP(rec, r)

			var res responses.AllDocs
			json.Unmarshal(rec.Body.Bytes(), &res)
			Expect(res.Rows).To(HaveLen(2))

			keys := []string{res.Rows[0].Id, res.Rows[1].Key}
			Expect(keys).To(ConsistOf("airplane", "boat"))
		})

		g.It("all_docs with include_docs -- for another sub db", func() {
			r, _ = http.NewRequest("GET", "/vehicles/airplane/_all_docs?include_docs=true", nil)
			server.ServeHTTP(rec, r)

			var res responses.AllDocs
			json.Unmarshal(rec.Body.Bytes(), &res)
			Expect(res.Rows).To(HaveLen(3))

			docid, _ := res.Rows[1].Doc["_id"]
			Expect(res.Rows[1].Key).To(Equal(docid))

			rev, _ := res.Rows[1].Value.(map[string]interface{})["rev"]
			docrev, _ := res.Rows[1].Doc["_rev"]
			Expect(rev).To(Equal(docrev))

			keys := []string{res.Rows[0].Id, res.Rows[1].Key, res.Rows[2].Id}
			sort.Strings(keys)
			Expect(keys).To(Equal([]string{"air", "land", "water"}))

			docs := map[string]interface{}{
				res.Rows[0].Key: res.Rows[0].Doc,
				res.Rows[1].Key: res.Rows[1].Doc,
				res.Rows[2].Key: res.Rows[2].Doc,
			}
			Expect(docs).To(HaveKey("air"))
			Expect(res.Rows[0].Doc).To(HaveKey("_rev"))
			Expect(res.Rows[0].Doc).To(HaveKeyWithValue("_id", res.Rows[0].Id))
		})

		g.It("_bulk_get", func() {
			r, _ = http.NewRequest("POST", "/vehicles/_bulk_get", bytes.NewReader([]byte(`{
                "docs": [
                    {"id": "nonexisting-doc"},
                    {"id": "car"},
                    {"_id": "airplane"}
                ]
            }`)))
			server.ServeHTTP(rec, r)

			var res responses.BulkGet
			json.Unmarshal(rec.Body.Bytes(), &res)
			Expect(res.Results[0].Docs[0].Ok).To(BeNil())
			Expect(res.Results[0].Docs[0].Error).ToNot(BeNil())
			Expect(res.Results[1].Docs[0].Ok).ToNot(BeNil())
			Expect(res.Results[1].Docs[0].Error).To(BeNil())
			doc := *res.Results[1].Docs[0].Ok
			id, _ := doc["_id"]
			irev, _ := doc["_rev"]
			rev = irev.(string)
			water, _ := doc["water"]
			Expect(id.(string)).To(Equal("car"))
			Expect(res.Results[1].Id).To(Equal(id))
			Expect(water).To(BeEquivalentTo(value(false)))
			Expect(res.Results[2].Docs[0].Ok).To(BeNil())
			Expect(res.Results[0].Docs[0].Error).ToNot(BeNil())
		})

		g.It("_bulk_docs", func() {
			r, _ = http.NewRequest("POST", "/vehicles/_bulk_docs", bytes.NewReader([]byte(`{
                "docs": [
                    {"everywhere": true},
                    {"_id": "car", "_rev": "`+rev+`", "space": false, "land": true},
                    {"_id": "airplane", "nowhere": false},
                    {"_id": "_local/.abchtru", "replication+data": "k"},
                    {"_id": "empty-doc"},
                    {"_id": "doc-with-a-rev-already-set", "_rev": "4-sa98hsa3i4", "val": 33}
                ]
            }`)))
			server.ServeHTTP(rec, r)

			Expect(rec.Code).To(Equal(201))
			var res []responses.BulkDocsResult
			json.Unmarshal(rec.Body.Bytes(), &res)

			Expect(res).To(HaveLen(6))
			Expect(res[0].Error).To(Equal(""))
			Expect(res[0].Ok).To(Equal(true))
			Expect(res[0].Rev).To(HavePrefix("1-"))
			id = res[0].Id
			Expect(res[1].Id).To(Equal("car"))
			prevn, _ := strconv.Atoi(strings.Split(rev, "-")[0])
			Expect(res[1].Rev).To(HavePrefix(fmt.Sprintf("%d-", prevn+1)))
			oldrev = rev
			rev = res[1].Rev
			cfe := responses.ConflictError()
			Expect(res[2].Error).To(Equal(cfe.Error))
			Expect(res[3].Id).To(Equal("_local/.abchtru"))
			Expect(res[3].Ok).To(Equal(true))
			Expect(res[4].Ok).To(Equal(true))
			Expect(res[4].Rev).To(HavePrefix("1-"))
			Expect(res[5].Ok).To(Equal(true))
			Expect(res[5].Rev).To(HavePrefix("5-"))
		})

		g.It("_bulk_docs with new_edits=false", func() {
			r, _ = http.NewRequest("POST", "/animals/_bulk_docs", bytes.NewReader([]byte(`{
                "docs": [
                    {"_id": "0", "_rev": "34-83fsop4", "name": "albatroz"},
                    {"_id": "1", "_rev": "0-a0a0a0a0", "name": "puppy"},
                    {"_id": "2"}
                ],
                "new_edits": false
            }`)))
			server.ServeHTTP(rec, r)

			Expect(rec.Code).To(Equal(201))
			var res []responses.BulkDocsResult
			json.Unmarshal(rec.Body.Bytes(), &res)

			Expect(res).To(HaveLen(3))
			Expect(res[0].Ok).To(Equal(true))
			Expect(res[1].Ok).To(Equal(true))
			Expect(res[2].Ok).To(Equal(false))

			Expect(db.GetRev("/animals/0")).To(BeEquivalentTo("34-83fsop4"))
			Expect(db.GetRev("/animals/1")).ToNot(BeEquivalentTo("0-a0a0a0a0"))
			Expect(db.GetValueAt("/animals/0/name")).To(BeEquivalentTo(`"albatroz"`))
			Expect(db.GetValueAt("/animals/1/name")).To(BeEquivalentTo(`"dog"`))
		})

		g.It("should have the correct docs saved", func() {
			Expect(db.GetValueAt("/vehicles/" + id + "/everywhere")).To(BeEquivalentTo("true"))
			Expect(db.GetLocalDocJsonAt("/vehicles/_local/.abchtru")).To(MatchJSON(`{
                "_id": "_local/.abchtru",
                "_rev": "0-1",
                "replication+data": "k"
            }`))
		})

		g.It("shouldn't show _local docs on _all_docs", func() {
			r, _ = http.NewRequest("GET", "/vehicles/_all_docs", nil)
			server.ServeHTTP(rec, r)
			var res responses.AllDocs
			json.Unmarshal(rec.Body.Bytes(), &res)
			Expect(res.Rows).To(HaveLen(5))
		})

		g.It("_revs_diff", func() {
			r, _ = http.NewRequest("POST", "/vehicles/_revs_diff", bytes.NewReader([]byte(`{
                "everywhere": ["2-invalidrev"],
                "car": ["`+oldrev+`", "`+rev+`", "1-invalidrev"],
                "airplane": ["1-nonexisting"]
            }`)))
			server.ServeHTTP(rec, r)

			Expect(rec.Code).To(Equal(200))
			var res map[string]responses.RevsDiffResult
			json.Unmarshal(rec.Body.Bytes(), &res)

			everywhere, _ := res["everywhere"]
			car, _ := res["car"]
			airplane, _ := res["airplane"]
			Expect(everywhere.Missing).To(Equal([]string{"2-invalidrev"}))
			Expect(car.Missing).To(Equal([]string{oldrev, "1-invalidrev"}))
			Expect(airplane.Missing).To(Equal([]string{"1-nonexisting"}))
		})
	})
}
Ejemplo n.º 4
0
func TestCouchDBDocsSpecial(t *testing.T) {
	g := Goblin(t)
	RegisterFailHandler(func(m string, _ ...int) { g.Fail(m) })

	g.Describe("couchdb documents special endpoints", func() {
		g.BeforeEach(func() {
			rec = httptest.NewRecorder()
			server = handle.BuildHandler()
		})

		g.Before(func() {
			db.Erase()
			db.Start()
			populateDB()
		})

		g.After(func() {
			db.End()
		})

		var rev string

		g.It("should change some values to generate revs", func() {
			brev, _ := db.GetValueAt("/vehicles/boat/air/_rev")
			r, _ = http.NewRequest("PUT", "/vehicles/boat/air/_val", bytes.NewReader([]byte("true")))
			r.Header.Add("If-Match", string(brev))
			server.ServeHTTP(rec, r)
			Expect(rec.Code).To(Equal(201))

			var res responses.Success
			json.Unmarshal(rec.Body.Bytes(), &res)
			rev = res.Rev
		})

		g.It("once more:", func() {
			r, _ = http.NewRequest("PATCH", "/vehicles/boat/air", bytes.NewReader([]byte(`{
                "_rev": "`+rev+`",
                "really?": false
            }`)))
			server.ServeHTTP(rec, r)
			Expect(rec.Code).To(Equal(200))
		})

		g.It("should fetch some key with the _revisions special field", func() {
			r, _ = http.NewRequest("GET", "/vehicles?revs=true", nil)
			server.ServeHTTP(rec, r)

			var res map[string]interface{}
			json.Unmarshal(rec.Body.Bytes(), &res)

			irevisions, ok := res["_revisions"]
			Expect(ok).To(Equal(true))
			revisions := irevisions.(map[string]interface{})
			start, _ := revisions["start"]
			ids, _ := revisions["ids"]
			Expect(start).To(BeEquivalentTo(1))
			Expect(ids).To(HaveLen(3))
		})

		g.It("should fetch some key with the _revs_info special field", func() {
			r, _ = http.NewRequest("GET", "/vehicles/boat?revs_info=true", nil)
			server.ServeHTTP(rec, r)

			var res map[string]interface{}
			json.Unmarshal(rec.Body.Bytes(), &res)

			irevsinfo, ok := res["_revs_info"]
			Expect(ok).To(Equal(true))
			revsinfo := irevsinfo.([]interface{})
			Expect(revsinfo).To(HaveLen(3))

			first := revsinfo[0].(map[string]interface{})
			second := revsinfo[1].(map[string]interface{})
			status, _ := first["status"]
			Expect(status).To(BeEquivalentTo("available"))
			status, _ = second["status"]
			Expect(status).To(BeEquivalentTo("missing"))
		})
	})
}
Ejemplo n.º 5
0
func TestGraphQL(t *testing.T) {
	g := Goblin(t)
	RegisterFailHandler(func(m string, _ ...int) { g.Fail(m) })

	g.Describe("simple graphql queries", func() {
		g.BeforeEach(func() {
			rec = httptest.NewRecorder()
			server = handle.BuildHandler()
		})

		g.Before(func() {
			db.Erase()
			db.Start()
			populateDB()
		})

		g.After(func() {
			db.End()
		})

		g.It("should query with type application/graphql", func() {
			r, _ = http.NewRequest("POST", "/_graphql", bytes.NewReader([]byte(`query {
              _val
              vehicles {
                _val
                car { land, water }
                airplane { land, air }
              }
            }`)))
			r.Header.Set("Content-Type", "application/graphql")
			server.ServeHTTP(rec, r)
			Expect(rec.Body.String()).To(MatchJSON(`{
              "data": {
                "_val": "root",
                "vehicles": {
                  "_val": "things that move",
                  "car": {
                    "land": true,
                    "water": false
                  },
                  "airplane": {
                    "land": true,
                    "air": true
                  }
                }
              }
            }`))
			Expect(rec.Code).To(Equal(200))
		})

		g.It("should query with type application/json", func() {
			r, _ = http.NewRequest("POST", "/_graphql", bytes.NewReader([]byte(`{
              "query": "query { vehicles { runs:car { land, water }, flies:airplane { land, air } }, rootValue:_val }"
            }`)))
			r.Header.Set("Content-Type", "application/json")
			server.ServeHTTP(rec, r)
			Expect(rec.Body.String()).To(MatchJSON(`{
              "data": {
                "rootValue": "root",
                "vehicles": {
                  "runs": {
                    "land": true,
                    "water": false
                  },
                  "flies": {
                    "land": true,
                    "air": true
                  }
                }
              }
            }`))
			Expect(rec.Code).To(Equal(200))
		})

		g.It("should query with type application/x-www-form-urlencoded", func() {
			form := url.Values{}
			form.Add("query", `
              query {
                v : vehicles {
                  rocket:flyingtorpedo { land }
                  car { land, air, water }
                  boat {
                    land {
                      _val
                      w:wot
                    }
                  }
                }
              }
            `)

			r, _ = http.NewRequest("POST", "/_graphql", strings.NewReader(form.Encode()))
			r.Header.Set("Content-Type", "application/x-www-form-urlencoded")
			server.ServeHTTP(rec, r)
			Expect(rec.Body.String()).To(MatchJSON(`{
              "data": {
                "v": {
                  "rocket": {
                    "land": null
                  },
                  "car": {
                    "land": true,
                    "air": false,
                    "water": false
                  },
                  "boat": {
                    "land": {
                      "_val": false,
                      "w": null
                    }
                  }
                }
              }
            }`))
			Expect(rec.Code).To(Equal(200))
		})

		g.It("graphql query on a subdb", func() {
			r, _ = http.NewRequest("POST", "/vehicles/_graphql", strings.NewReader(`query {
              desc:_val
              car { land, water }
              airplane { land, air }
            }`))
			r.Header.Set("Content-Type", "application/graphql")
			server.ServeHTTP(rec, r)
			Expect(rec.Body.String()).To(MatchJSON(`{
              "data": {
                "desc": "things that move",
                "car": {
                  "land": true,
                  "water": false
                },
                "airplane": {
                  "land": true,
                  "air": true
                }
              }
            }`))
			Expect(rec.Code).To(Equal(200))
		})
	})

	g.Describe("authorized and restricted graphql queries", func() {
		g.BeforeEach(func() {
			rec = httptest.NewRecorder()
			server = handle.BuildHandler()
		})

		g.Before(func() {
			db.Erase()
			db.Start()
			populateDB()
		})

		g.After(func() {
			db.End()
		})

		g.It("should create some users and rules", func() {
			r, _ = http.NewRequest("POST", "/_users", bytes.NewReader([]byte(`{
				"name": "vehicles_user",
				"password": "******"
			}`)))
			server.ServeHTTP(rec, r)
			Expect(rec.Code).To(Equal(201))
			rec = httptest.NewRecorder()

			r, _ = http.NewRequest("POST", "/_users", bytes.NewReader([]byte(`{
				"name": "boat_user",
				"password": "******"
			}`)))
			server.ServeHTTP(rec, r)
			Expect(rec.Code).To(Equal(201))
			rec = httptest.NewRecorder()

			r, _ = http.NewRequest("PUT", "/vehicles/_security", bytes.NewReader([]byte(`{
				"_read": "vehicles_user"
			}`)))
			server.ServeHTTP(rec, r)
			Expect(rec.Code).To(Equal(200))
			rec = httptest.NewRecorder()

			r, _ = http.NewRequest("PUT", "/vehicles/boat/_security", bytes.NewReader([]byte(`{
				"_read": "boat_user"
			}`)))
			server.ServeHTTP(rec, r)
			Expect(rec.Code).To(Equal(200))
			rec = httptest.NewRecorder()

			r, _ = http.NewRequest("PUT", "/_security", bytes.NewReader([]byte(`{
				"_read": "no-one",
				"_write": "no-one",
				"_admin": "no-one"
			}`)))
			server.ServeHTTP(rec, r)
			Expect(rec.Code).To(Equal(200))
		})

		g.It("should be authorized for the paths where the user has immediate access", func() {
			r, _ = http.NewRequest("POST", "/vehicles/_graphql", strings.NewReader(`query {
              car { land, water }
            }`))
			r.Header.Set("Content-Type", "application/graphql")
			r.SetBasicAuth("vehicles_user", "12345678")
			server.ServeHTTP(rec, r)
			Expect(rec.Body.String()).To(MatchJSON(`{
              "data": {
                "car": {
                  "land": true,
                  "water": false
                }
              }
            }`))
			Expect(rec.Code).To(Equal(200))
			rec = httptest.NewRecorder()

			r, _ = http.NewRequest("POST", "/vehicles/boat/_graphql", strings.NewReader(`query {
              air
            }`))
			r.Header.Set("Content-Type", "application/graphql")
			r.SetBasicAuth("boat_user", "12345678")
			server.ServeHTTP(rec, r)
			Expect(rec.Body.String()).To(MatchJSON(`{
              "data": {
                "air": false
              }
            }`))
			Expect(rec.Code).To(Equal(200))
		})

		g.It("should be authorized for all paths below", func() {
			r, _ = http.NewRequest("POST", "/vehicles/boat/_graphql", strings.NewReader(`query {
              land
              water
            }`))
			r.Header.Set("Content-Type", "application/graphql")
			r.SetBasicAuth("vehicles_user", "12345678")
			server.ServeHTTP(rec, r)
			Expect(rec.Body.String()).To(MatchJSON(`{
              "data": {
                "land": false,
                "water": true
              }
            }`))
			Expect(rec.Code).To(Equal(200))
			rec = httptest.NewRecorder()

			r, _ = http.NewRequest("POST", "/vehicles/boat/air/_graphql", strings.NewReader(`query {
              flies: _val
            }`))
			r.Header.Set("Content-Type", "application/graphql")
			r.SetBasicAuth("boat_user", "12345678")
			server.ServeHTTP(rec, r)
			Expect(rec.Body.String()).To(MatchJSON(`{
              "data": {
                "flies": false
              }
            }`))
			Expect(rec.Code).To(Equal(200))
		})

		g.It("should be unauthorized for all paths above", func() {
			r, _ = http.NewRequest("POST", "/_graphql", strings.NewReader(`query {
              root: _val
              vehicles {
                car { land }
              }
            }`))
			r.Header.Set("Content-Type", "application/graphql")
			r.SetBasicAuth("vehicles_user", "12345678")
			server.ServeHTTP(rec, r)
			Expect(rec.Body.String()).To(MatchJSON(`{
              "errors": [{
                "message": "_read permission for this path needed."
              }]
            }`))
			rec = httptest.NewRecorder()

			r, _ = http.NewRequest("POST", "/vehicles/_graphql", strings.NewReader(`query {
              boat { land, air }
            }`))
			r.Header.Set("Content-Type", "application/graphql")
			r.SetBasicAuth("boat_user", "12345678")
			server.ServeHTTP(rec, r)
			Expect(rec.Body.String()).To(MatchJSON(`{
              "errors": [{
                "message": "_read permission for this path needed."
              }]
            }`))
		})

		g.It("should be unauthorized for neighbour paths also", func() {
			r, _ = http.NewRequest("POST", "/vehicles/car/_graphql", strings.NewReader(`query {
              land
              water
            }`))
			r.Header.Set("Content-Type", "application/graphql")
			r.SetBasicAuth("boat_user", "12345678")
			server.ServeHTTP(rec, r)
			Expect(rec.Body.String()).To(MatchJSON(`{
              "errors": [{
                "message": "_read permission for this path needed."
              }]
            }`))
		})
	})
}
Ejemplo n.º 6
0
func TestAuthUsersACL(t *testing.T) {
	g := Goblin(t)
	RegisterFailHandler(func(m string, _ ...int) { g.Fail(m) })

	g.Describe("auth", func() {
		g.BeforeEach(func() {
			rec = httptest.NewRecorder()
			server = handle.BuildHandler()
		})

		g.Before(func() {
			db.Erase()
			db.Start()
		})

		g.After(func() {
			db.End()
		})

		g.It("database should be in admin party", func() {
			r, _ = http.NewRequest("GET", "/_security", nil)
			server.ServeHTTP(rec, r)

			Expect(rec.Code).To(Equal(200))

			var res responses.Security
			json.Unmarshal(rec.Body.Bytes(), &res)
			Expect(res).To(BeEquivalentTo(responses.Security{"*", "*", "*"}))
		})

		g.It("should set some rules for database", func() {
			r, _ = http.NewRequest("PUT", "/_security", bytes.NewReader([]byte(`{
				"_read": "*",
				"_write": "myself",
				"_admin": "myself"
			}`)))
			server.ServeHTTP(rec, r)

			Expect(rec.Code).To(Equal(200))
			Expect(db.GetReadRuleAt("/")).To(Equal("*"))
			Expect(db.GetWriteRuleAt("/")).To(Equal("myself"))
			Expect(db.GetAdminRuleAt("/")).To(Equal("myself"))
		})

		g.It("should fail to set other rules (since _admin is a user)", func() {
			r, _ = http.NewRequest("PUT", "/_security", bytes.NewReader([]byte(`{
				"_read": "*",
				"_write": "myself, others",
				"_admin": "myself"
			}`)))
			server.ServeHTTP(rec, r)

			Expect(rec.Code).To(Equal(401))
			Expect(db.GetReadRuleAt("/")).To(Equal("*"))
			Expect(db.GetWriteRuleAt("/")).To(Equal("myself"))
			Expect(db.GetAdminRuleAt("/")).To(Equal("myself"))
		})

		g.It("should fail to create accounts due to the security policy", func() {
			r, _ = http.NewRequest("POST", "/_users", bytes.NewReader([]byte(`{
				"name": "myself",
				"password": "******"
			}`)))
			server.ServeHTTP(rec, r)

			Expect(rec.Code).To(Equal(401))
		})

		g.It("should change the security policy by cheating, then create accounts", func() {
			db.SetRulesAt("/", map[string]interface{}{"_write": "*"})

			r, _ = http.NewRequest("POST", "/_users", bytes.NewReader([]byte(`{
				"name": "myself",
				"password": "******"
			}`)))
			server.ServeHTTP(rec, r)

			Expect(rec.Code).To(Equal(201))
			db.SetRulesAt("/", map[string]interface{}{"_write": "myself, others"})
		})

		g.It("should create accounts, now using the recently created and authorized user", func() {
			r, _ = http.NewRequest("POST", "/_users", bytes.NewReader([]byte(`{
				"name": "others",
				"password": "******"
			}`)))
			r.SetBasicAuth("myself", "12345678")
			server.ServeHTTP(rec, r)

			Expect(rec.Code).To(Equal(201))
		})

		g.It("another account created", func() {
			r, _ = http.NewRequest("POST", "/_users", bytes.NewReader([]byte(`{
				"name": "bob",
				"password": "******"
			}`)))
			r.SetBasicAuth("myself", "12345678")
			server.ServeHTTP(rec, r)

			Expect(rec.Code).To(Equal(201))
		})

		g.It("should fail to create document without a user", func() {
			r, _ = http.NewRequest("PUT", "/a/b/c", bytes.NewReader([]byte(`{
				"doc": "iuiwebsd",
				"val": "woiernhoq234"
			}`)))
			server.ServeHTTP(rec, r)

			Expect(rec.Code).To(Equal(401))
		})

		g.It("should fail to create document with an unallowed user", func() {
			r, _ = http.NewRequest("PUT", "/a/b/c", bytes.NewReader([]byte(`{
				"doc": "iuiwebsd",
				"val": "woiernhoq234"
			}`)))
			r.SetBasicAuth("bob", "gki48dh3w")
			server.ServeHTTP(rec, r)

			Expect(rec.Code).To(Equal(401))
		})

		g.It("should succeed to created document with a correct user", func() {
			r, _ = http.NewRequest("PUT", "/a/b/c", bytes.NewReader([]byte(`{
				"doc": "iuiwebsd",
				"val": "woiernhoq234"
			}`)))
			r.SetBasicAuth("others", "qwerty")
			server.ServeHTTP(rec, r)

			Expect(rec.Code).To(Equal(201))
		})

		g.It("should change only read permission for a subpath", func() {
			r, _ = http.NewRequest("PUT", "/a/b/_security", bytes.NewReader([]byte(`{
				"_read": "bob"
			}`)))
			r.SetBasicAuth("myself", "12345678")
			server.ServeHTTP(rec, r)

			Expect(rec.Code).To(Equal(200))
		})

		g.It("should be able to read with wrong user because of upper rule", func() {
			r, _ = http.NewRequest("GET", "/a/b/c", nil)
			r.SetBasicAuth("myself", "12345678")
			server.ServeHTTP(rec, r)

			Expect(rec.Code).To(Equal(200))
		})

		g.It("remove upper rule that allowed everybody", func() {
			r, _ = http.NewRequest("PUT", "/_security", bytes.NewReader([]byte(`{
				"_read": ""
			}`)))
			r.SetBasicAuth("myself", "12345678")
			server.ServeHTTP(rec, r)

			Expect(rec.Code).To(Equal(200))
		})

		g.It("shouldn't be able to read with wrong user", func() {
			r, _ = http.NewRequest("GET", "/a/b/c", nil)
			r.SetBasicAuth("myself", "12345678")
			server.ServeHTTP(rec, r)

			Expect(rec.Code).To(Equal(401))
		})

		g.It("should be able to read with correct user", func() {
			r, _ = http.NewRequest("GET", "/a/b/c", nil)
			r.SetBasicAuth("bob", "gki48dh3w")
			server.ServeHTTP(rec, r)

			Expect(rec.Code).To(Equal(200))
		})

		g.It("change the rule again, now a lower rule will allow a different user", func() {
			r, _ = http.NewRequest("PUT", "/a/b/c/_security", bytes.NewReader([]byte(`{
				"_read": "others"
			}`)))
			r.SetBasicAuth("myself", "12345678")
			server.ServeHTTP(rec, r)

			Expect(rec.Code).To(Equal(200))
		})

		g.It("should be able to read with this different user", func() {
			r, _ = http.NewRequest("GET", "/a/b/c", nil)
			r.SetBasicAuth("others", "qwerty")
			server.ServeHTTP(rec, r)

			Expect(rec.Code).To(Equal(200))
		})

		g.It("and again with the same user that was allowed first", func() {
			r, _ = http.NewRequest("GET", "/a/b/c", nil)
			r.SetBasicAuth("bob", "gki48dh3w")
			server.ServeHTTP(rec, r)

			Expect(rec.Code).To(Equal(200))
		})
	})
}
Ejemplo n.º 7
0
func TestBasics(t *testing.T) {
	g := Goblin(t)
	RegisterFailHandler(func(m string, _ ...int) { g.Fail(m) })

	g.Describe("basics", func() {
		g.BeforeEach(func() {
			rec = httptest.NewRecorder()
			server = handle.BuildHandler()
		})

		g.Before(func() {
			db.Erase()
			db.Start()
			populateDB()
		})

		g.After(func() {
			db.End()
		})

		var rev string

		g.It("should get an empty doc", func() {
			r, _ = http.NewRequest("GET", "/nothing/here", nil)
			server.ServeHTTP(rec, r)
			Expect(rec.Body.String()).To(MatchJSON(`{
              "error": "not_found",
              "reason": "missing"
            }`))
			Expect(rec.Code).To(Equal(404))
		})

		g.It("should create a new doc", func() {
			body := `{"a": "one", "dfg": {"many": 3, "which": ["d", "f", "g"]}}`
			jsonbody := []byte(body)
			r, _ = http.NewRequest("PUT", "/something/here", bytes.NewReader(jsonbody))
			server.ServeHTTP(rec, r)
			Expect(rec.Code).To(Equal(201))
			var resp responses.Success
			Expect(json.Unmarshal(rec.Body.Bytes(), &resp)).To(Succeed())
			Expect(resp.Ok).To(BeTrue())
			Expect(resp.Id).To(Equal("here"))
			Expect(resp.Rev).To(HavePrefix("1-"))
			rev = resp.Rev
		})

		g.It("should fetch a subfield", func() {
			r, _ = http.NewRequest("GET", "/something/here/a/_val", nil)
			server.ServeHTTP(rec, r)
			Expect(rec.Code).To(Equal(200))
			Expect(rec.Body.String()).To(Equal(`"one"`))
		})

		g.It("should fetch a subrev", func() {
			r, _ = http.NewRequest("GET", "/something/here/dfg/_rev", nil)
			server.ServeHTTP(rec, r)
			Expect(rec.Code).To(Equal(200))
			rev = rec.Body.String()
			Expect(rev).To(HavePrefix(`1-`))
		})

		g.It("should fetch a subtree", func() {
			r, _ = http.NewRequest("GET", "/something/here/dfg", nil)
			server.ServeHTTP(rec, r)
			Expect(rec.Code).To(Equal(200))
			Expect(rec.Body.String()).To(MatchJSON(`{
              "_id": "dfg",
              "_rev": "` + rev + `",
              "many": {"_val": 3},
              "which": {
                "0": {"_val": "d"},
                "1": {"_val": "f"},
                "2": {"_val": "g"}
              }
            }`))
		})

		g.It("should get the newest _rev for a path", func() {
			r, _ = http.NewRequest("GET", "/something/here/dfg/many/_rev", nil)
			server.ServeHTTP(rec, r)
			Expect(rec.Code).To(Equal(200))
			rev = rec.Body.String()
		})

		g.It("should delete a key (providing rev)", func() {
			r, _ = http.NewRequest("DELETE", "/something/here/dfg/many", nil)
			r.Header.Set("If-Match", rev)
			server.ServeHTTP(rec, r)
			Expect(rec.Code).To(Equal(200))
			var resp responses.Success
			Expect(json.Unmarshal(rec.Body.Bytes(), &resp)).To(Succeed())
			Expect(resp.Ok).To(BeTrue())
			Expect(resp.Id).To(Equal("many"))
			Expect(resp.Rev).To(HavePrefix("2-"))
		})

		g.It("should fail to fetch deleted key", func() {
			r, _ = http.NewRequest("GET", "/something/here/dfg/many", nil)
			server.ServeHTTP(rec, r)
			Expect(rec.Code).To(Equal(404))
		})

		g.It("should fail to delete a special key", func() {
			r, _ = http.NewRequest("DELETE", "/something/here/_rev", nil)
			server.ServeHTTP(rec, r)
			Expect(rec.Code).To(Equal(400))
		})

		g.It("should fail to update a special key", func() {
			body := `{"a": "one", "dfg": {"many": 3, "which": ["d", "f", "g"]}}`
			jsonbody := []byte(body)
			r, _ = http.NewRequest("PATCH", "/something/_rev", bytes.NewReader(jsonbody))
			server.ServeHTTP(rec, r)
			Expect(rec.Code).To(Equal(400))
		})

		g.It("should fail to update a key without providing a _rev", func() {
			body := `{"was": "another thing"}`
			jsonbody := []byte(body)
			r, _ = http.NewRequest("PATCH", "/something", bytes.NewReader(jsonbody))
			server.ServeHTTP(rec, r)
			Expect(rec.Code).To(Equal(409))
		})

		g.It("should fail to update a key providing a wrong _rev", func() {
			body := `{"_rev": "2-389247isdbf", "was": "another thing"}`
			jsonbody := []byte(body)
			r, _ = http.NewRequest("PATCH", "/something/here/dfg", bytes.NewReader(jsonbody))
			server.ServeHTTP(rec, r)
			Expect(rec.Code).To(Equal(409))
		})

		g.It("should fail to update a deleted key when providing a mismatching revs", func() {
			body := `{"_rev": "3-1asd623a5", "was": "another thing"}`
			jsonbody := []byte(body)
			r, _ = http.NewRequest("PATCH", "/something/here/dfg?rev=7-sdf98h435", bytes.NewReader(jsonbody))
			r.Header.Set("If-Match", rev)
			server.ServeHTTP(rec, r)
			Expect(rec.Code).To(Equal(400))
		})

		g.It("should fail to patch an untouched path", func() {
			jsonbody := []byte(`{"1": 2}`)
			r, _ = http.NewRequest("PATCH", "/nowhere", bytes.NewReader(jsonbody))
			server.ServeHTTP(rec, r)
			Expect(rec.Code).To(Equal(404))
		})

		g.It("should get the newest _rev for a path", func() {
			r, _ = http.NewRequest("GET", "/something/here/_rev", nil)
			server.ServeHTTP(rec, r)
			Expect(rec.Code).To(Equal(200))
			rev = rec.Body.String()
		})

		g.It("should delete a path providing the correct rev", func() {
			r, _ = http.NewRequest("DELETE", "/something/here?rev="+rev, nil)
			server.ServeHTTP(rec, r)
			Expect(rec.Code).To(Equal(200))
		})

		g.It("should fail to patch a deleted path", func() {
			jsonbody := []byte(`{"1": 2}`)
			r, _ = http.NewRequest("PATCH", "/something/here", bytes.NewReader(jsonbody))
			server.ServeHTTP(rec, r)
			Expect(rec.Code).To(Equal(404))
		})

		g.It("should put a tree on a deleted path without providing any rev", func() {
			body := `{"was": {"before": "another thing", "long_before": "a different thing"}}`
			jsonbody := []byte(body)
			r, _ = http.NewRequest("PUT", "/something/here", bytes.NewReader(jsonbody))
			server.ServeHTTP(rec, r)
			Expect(rec.Code).To(Equal(201))

			var resp responses.Success
			json.Unmarshal(rec.Body.Bytes(), &resp)
			rev = resp.Rev
		})

		g.It("should update a subpath with the rev of a parent", func() {
			body := `{"was": {"before": "still another thing"}}`
			jsonbody := []byte(body)
			r, _ = http.NewRequest("PATCH", "/something/here?rev="+rev, bytes.NewReader(jsonbody))
			server.ServeHTTP(rec, r)
			Expect(rec.Code).To(Equal(200))

			var resp responses.Success
			json.Unmarshal(rec.Body.Bytes(), &resp)
			rev = resp.Rev
		})

		g.It("should delete a subpath with the rev of a parent (using a tree)", func() {
			body := `{"was": {"long_before": null}, "_rev": "` + rev + `"}`
			jsonbody := []byte(body)
			r, _ = http.NewRequest("PATCH", "/something/here", bytes.NewReader(jsonbody))
			server.ServeHTTP(rec, r)
			Expect(rec.Code).To(Equal(200))
		})

		g.It("should get the rev of the something path", func() {
			r, _ = http.NewRequest("GET", "/something/_rev", nil)
			server.ServeHTTP(rec, r)
			rev = rec.Body.String()
		})

		g.It("should have the correct tree in the end", func() {
			r, _ = http.NewRequest("GET", "/something", nil)
			server.ServeHTTP(rec, r)
			Expect(rec.Code).To(Equal(200))
			Expect(rec.Body.String()).To(MatchJSON(`{
              "_id": "something",
              "_rev": "` + rev + `",
              "here": {
                "was": {
                  "before": {
                    "_val": "still another thing"
                  }
                }
              }
            }`))
		})
	})
}