func authMiddleware(next http.Handler) http.Handler { return http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) { ctx := getContext(r) var allow bool if r.Method[0] == 'P' { // PUT, POST, PATCH allow = db.WriteAllowedAt(ctx.path, ctx.user) } else { // otherwise allow = db.ReadAllowedAt(ctx.path, ctx.user) } if !allow { res := responses.Unauthorized() w.WriteHeader(res.Code) json.NewEncoder(w).Encode(res) return } next.ServeHTTP(w, r) }) }
func HandleGraphQL(w http.ResponseWriter, r *http.Request) { ctx := getContext(r) startPath := r.URL.Path[:len(r.URL.Path)-9] allow := db.ReadAllowedAt(startPath, ctx.user) if !allow { json.NewEncoder(w).Encode(GraphQLResponse{ Errors: []GraphQLError{GraphQLError{"_read permission for this path needed."}}, }) return } var gql string switch r.Header.Get("Content-Type") { case "application/json": jsonBody := struct { Query string `json:"query"` }{} err := json.NewDecoder(r.Body).Decode(&jsonBody) if err != nil { json.NewEncoder(w).Encode(GraphQLResponse{ Errors: []GraphQLError{GraphQLError{"failed to parse json: " + err.Error()}}, }) return } gql = jsonBody.Query break case "application/x-www-form-urlencoded": r.ParseForm() gql = r.FormValue("query") break // case "application/graphql": default: body, err := ioutil.ReadAll(r.Body) if err != nil { json.NewEncoder(w).Encode(GraphQLResponse{ Errors: []GraphQLError{GraphQLError{"couldn't read request body."}}, }) return } gql = string(body) } doc, err := parser.Parse(parser.ParseParams{ Source: gql, Options: parser.ParseOptions{true, true}, }) if err != nil || len(doc.Definitions) != 1 { message := "your graphql query must describe a 'query' operation." if err != nil { message = err.Error() } json.NewEncoder(w).Encode(GraphQLResponse{ Errors: []GraphQLError{GraphQLError{"failed to parse gql query: " + message}}, }) return } // we're just ignoring Args for now -- maybe we'll find an utility for them in the future topfields := doc.Definitions[0].(*ast.OperationDefinition).SelectionSet.Selections response := cmap.New() godeepAsyncMultiple(topfields, startPath, &response) w.WriteHeader(200) w.Header().Add("Content-Type", "application/json") json.NewEncoder(w).Encode(GraphQLResponse{ Data: response.Items(), }) }
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)) }) }) }