// HTTP handler for writing security metadata func WriteSecurity(w http.ResponseWriter, r *http.Request) { ctx := getContext(r) path := db.CleanPath(ctx.path) if !db.AdminAllowedAt(path, ctx.user) { res := responses.Unauthorized() w.WriteHeader(res.Code) json.NewEncoder(w).Encode(res) return } err := db.SetRulesAt(path, ctx.jsonBody) if err != nil { res := responses.UnknownError() w.WriteHeader(res.Code) json.NewEncoder(w).Encode(res) return } res := responses.Success{Ok: true} w.Header().Add("Content-Type", "application/json") w.WriteHeader(200) json.NewEncoder(w).Encode(res) }
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)) }) }) }
func TestAuthUsersACL(t *testing.T) { g := Goblin(t) RegisterFailHandler(func(m string, _ ...int) { g.Fail(m) }) g.Describe("users and permissions", func() { g.Before(func() { db.Erase() db.Start() }) g.After(func() { db.End() }) g.It("should start with a * permission on root", func() { Expect(db.GetWriteRuleAt("/")).To(Equal("*")) Expect(db.GetReadRuleAt("/")).To(Equal("*")) Expect(db.GetAdminRuleAt("")).To(Equal("*")) // "/" should equal "" }) g.It("which means everybody is allowed to do anything anywhere", func() { Expect(db.WriteAllowedAt("/", "bob")).To(Equal(true)) Expect(db.ReadAllowedAt("/articles", "maria")).To(Equal(true)) Expect(db.AdminAllowedAt("/somewhere/down/on/the/path", "anyone")).To(Equal(true)) Expect(db.WriteAllowedAt("/x/r/e/ws/sd/f/t/r/e/d/g/y", "")).To(Equal(true)) Expect(db.ReadAllowedAt("/recipes", "anna")).To(Equal(true)) Expect(db.AdminAllowedAt("/", "bob")).To(Equal(true)) }) g.It("should modify permissions arbitrarily", func() { Expect(db.SetRulesAt("/paper", map[string]interface{}{ "_read": "drawer,romancist, reader", "_write": "drawer, romancist", "_admin": "romancist", })).To(Succeed()) Expect(db.SetRulesAt("/", map[string]interface{}{ "_read": "myself", "_write": "myself", "_admin": "myself", })).To(Succeed()) }) g.It("and allowability should reflect that", func() { Expect(db.WriteAllowedAt("/", "bob")).To(Equal(false)) Expect(db.ReadAllowedAt("/articles", "maria")).To(Equal(false)) Expect(db.AdminAllowedAt("/somewhere/down/on/the/path", "anyone")).To(Equal(false)) Expect(db.ReadAllowedAt("/recipes", "anna")).To(Equal(false)) Expect(db.WriteAllowedAt("/x/r/e/ws/sd/f/t/r/e/d/g/y", "")).To(Equal(false)) Expect(db.AdminAllowedAt("/", "bob")).To(Equal(false)) Expect(db.WriteAllowedAt("/", "myself")).To(Equal(true)) Expect(db.WriteAllowedAt("/paper", "myself")).To(Equal(true)) Expect(db.WriteAllowedAt("/rock", "myself")).To(Equal(true)) Expect(db.WriteAllowedAt("/paper/planes", "myself")).To(Equal(true)) Expect(db.WriteAllowedAt("/paper", "romancist")).To(Equal(true)) Expect(db.WriteAllowedAt("/paper/planes", "romancist")).To(Equal(true)) Expect(db.WriteAllowedAt("/", "romancist")).To(Equal(false)) Expect(db.WriteAllowedAt("/paperless", "romancist")).To(Equal(false)) Expect(db.ReadAllowedAt("/paper", "drawer")).To(Equal(true)) Expect(db.ReadAllowedAt("/paperless", "drawer")).To(Equal(false)) Expect(db.ReadAllowedAt("/paper/origami", "drawer")).To(Equal(true)) Expect(db.ReadAllowedAt("/paper", "reader")).To(Equal(true)) Expect(db.ReadAllowedAt("/paperless", "reader")).To(Equal(false)) Expect(db.ReadAllowedAt("/paper/origami", "reader")).To(Equal(true)) Expect(db.AdminAllowedAt("/", "myself")).To(Equal(true)) Expect(db.AdminAllowedAt("/anywhere", "myself")).To(Equal(true)) Expect(db.AdminAllowedAt("/paper", "myself")).To(Equal(true)) Expect(db.AdminAllowedAt("/", "romancist")).To(Equal(false)) Expect(db.AdminAllowedAt("/anywhere", "romancist")).To(Equal(false)) Expect(db.AdminAllowedAt("/paper", "romancist")).To(Equal(true)) Expect(db.AdminAllowedAt("/paper/origami", "romancist")).To(Equal(true)) Expect(db.AdminAllowedAt("/", "reader")).To(Equal(false)) Expect(db.AdminAllowedAt("/anywhere", "reader")).To(Equal(false)) Expect(db.AdminAllowedAt("/paper", "reader")).To(Equal(false)) }) g.It("should create users", func() { Expect(db.SaveUser("isaiah", "12345678")).To(Succeed()) Expect(db.SaveUser("samuel", "87654321")).To(Succeed()) Expect(db.SaveUser("isaiah", "qwertyuu")).ToNot(Succeed()) Expect(db.SaveUser("israel", "")).To(Succeed()) Expect(db.SaveUser("", "asdfghjh")).ToNot(Succeed()) }) g.It("should validate user logins", func() { Expect(db.ValidUser("samuel", "87654321")).To(Equal(true)) Expect(db.ValidUser("isaiah", "12345678")).To(Equal(true)) Expect(db.ValidUser("isaiah", "qwertyuu")).To(Equal(false)) Expect(db.ValidUser("israel", "")).To(Equal(true)) Expect(db.ValidUser("", "asdfghjh")).To(Equal(false)) Expect(db.ValidUser("", "")).To(Equal(false)) Expect(db.ValidUser("q", "a")).To(Equal(false)) Expect(db.ValidUser("weq", "")).To(Equal(false)) Expect(db.ValidUser("", "ssdds")).To(Equal(false)) }) }) }