~tsileo/blobstash

bc315003dfb2b15fcbe03b3ee5630b7ed0d3e91d — Thomas Sileo 8 months ago 1cb820d
perms,docstore: tweak the docstore permissions
2 files changed, 102 insertions(+), 17 deletions(-)

M pkg/docstore/docstore.go
M pkg/perms/perms.go
M pkg/docstore/docstore.go => pkg/docstore/docstore.go +91 -9
@@ 504,6 504,16 @@ func (docstore *DocStore) storedQueriesHandler() func(http.ResponseWriter, *http
	return func(w http.ResponseWriter, r *http.Request) {
		switch r.Method {
		case "GET":
			if !auth.Can(
				w,
				r,
				perms.Action(perms.Admin, perms.JSONCollection),
				perms.Resource(perms.DocStore, perms.JSONCollection),
			) {
				auth.Forbidden(w)
				return
			}

			httputil.WriteJSON(w, docstore.storedQueries)
			return
		default:


@@ 518,8 528,15 @@ func (docstore *DocStore) collectionsHandler() func(http.ResponseWriter, *http.R
	return func(w http.ResponseWriter, r *http.Request) {
		switch r.Method {
		case "GET":
			// Ensure the client has the needed permissions
			// permissions.CheckPerms(r, PermCollectionName)
			if !auth.Can(
				w,
				r,
				perms.Action(perms.List, perms.JSONCollection),
				perms.Resource(perms.DocStore, perms.JSONCollection),
			) {
				auth.Forbidden(w)
				return
			}

			collections, err := docstore.Collections()
			if err != nil {


@@ 1041,9 1058,8 @@ func (docstore *DocStore) reindexDocsHandler() func(http.ResponseWriter, *http.R
			if !auth.Can(
				w,
				r,
				// TODO(tsileo): tweak the perms
				perms.Action(perms.List, perms.JSONDocument),
				perms.Resource(perms.DocStore, perms.JSONDocument),
				perms.Action(perms.Admin, perms.JSONCollection),
				perms.Resource(perms.DocStore, perms.JSONCollection),
			) {
				auth.Forbidden(w)
				return


@@ 1075,8 1091,8 @@ func (docstore *DocStore) docsHandler() func(http.ResponseWriter, *http.Request)
			if !auth.Can(
				w,
				r,
				perms.Action(perms.List, perms.JSONDocument),
				perms.Resource(perms.DocStore, perms.JSONDocument),
				perms.Action(perms.Read, perms.JSONCollection),
				perms.ResourceWithID(perms.DocStore, perms.JSONCollection, collection),
			) {
				auth.Forbidden(w)
				return


@@ 1169,7 1185,16 @@ func (docstore *DocStore) docsHandler() func(http.ResponseWriter, *http.Request)
				},
			})
		case "POST":
			// permissions.CheckPerms(r, PermCollectionName, collection, PermWrite)
			if !auth.Can(
				w,
				r,
				perms.Action(perms.Write, perms.JSONCollection),
				perms.ResourceWithID(perms.DocStore, perms.JSONCollection, collection),
			) {
				auth.Forbidden(w)
				return
			}

			// Read the whole body
			blob, err := ioutil.ReadAll(r.Body)
			if err != nil {


@@ 1242,6 1267,16 @@ func (docstore *DocStore) mapReduceHandler() func(http.ResponseWriter, *http.Req
		}
		switch r.Method {
		case "POST":
			if !auth.Can(
				w,
				r,
				perms.Action(perms.List, perms.JSONCollection),
				perms.ResourceWithID(perms.DocStore, perms.JSONCollection, collection),
			) {
				auth.Forbidden(w)
				return
			}

			input := &mapReduceInput{}
			if err := json.NewDecoder(r.Body).Decode(input); err != nil {
				panic(httputil.NewPublicErrorFmt("Invalid JSON input"))


@@ 1556,7 1591,16 @@ func (docstore *DocStore) docHandler() func(http.ResponseWriter, *http.Request) 
		switch r.Method {
		case "GET", "HEAD":
			// Serve the document JSON encoded
			// permissions.CheckPerms(r, PermCollectionName, collection, PermRead)
			if !auth.Can(
				w,
				r,
				perms.Action(perms.Read, perms.JSONCollection),
				perms.ResourceWithID(perms.DocStore, perms.JSONCollection, collection),
			) {
				auth.Forbidden(w)
				return
			}

			// js := []byte{}
			var doc, pointers map[string]interface{}



@@ 1595,6 1639,15 @@ func (docstore *DocStore) docHandler() func(http.ResponseWriter, *http.Request) 
			}
			return
		case "PATCH":
			if !auth.Can(
				w,
				r,
				perms.Action(perms.Write, perms.JSONCollection),
				perms.ResourceWithID(perms.DocStore, perms.JSONCollection, collection),
			) {
				auth.Forbidden(w)
				return
			}
			// Patch the document (JSON-Patch/RFC6902)

			// Lock the document before making any change to it, this way the PATCH operation is *truly* atomic/safe


@@ 1677,6 1730,15 @@ func (docstore *DocStore) docHandler() func(http.ResponseWriter, *http.Request) 

			return
		case "POST":
			if !auth.Can(
				w,
				r,
				perms.Action(perms.Write, perms.JSONCollection),
				perms.ResourceWithID(perms.DocStore, perms.JSONCollection, collection),
			) {
				auth.Forbidden(w)
				return
			}
			// Update the whole document

			// Parse the update query


@@ 1711,6 1773,16 @@ func (docstore *DocStore) docHandler() func(http.ResponseWriter, *http.Request) 

			return
		case "DELETE":
			if !auth.Can(
				w,
				r,
				perms.Action(perms.Delete, perms.JSONCollection),
				perms.ResourceWithID(perms.DocStore, perms.JSONCollection, collection),
			) {
				auth.Forbidden(w)
				return
			}

			_, err := docstore.Remove(collection, sid)
			switch err {
			case nil:


@@ 1740,6 1812,16 @@ func (docstore *DocStore) docVersionsHandler() func(http.ResponseWriter, *http.R
		var _id *id.ID
		switch r.Method {
		case "GET", "HEAD":
			if !auth.Can(
				w,
				r,
				perms.Action(perms.Read, perms.JSONCollection),
				perms.ResourceWithID(perms.DocStore, perms.JSONCollection, collection),
			) {
				auth.Forbidden(w)
				return
			}

			q := httputil.NewQuery(r.URL.Query())
			limit, err := q.GetIntDefault("limit", 50)
			if err != nil {

M pkg/perms/perms.go => pkg/perms/perms.go +11 -8
@@ 18,24 18,27 @@ type ServiceName string
const (
	Read     ActionType = "read"
	Stat     ActionType = "stat"
	Delete   ActionType = "delete"
	Write    ActionType = "write"
	List     ActionType = "list"
	Snapshot ActionType = "snapshot"
	Search   ActionType = "search"
	GC       ActionType = "gc"
	Destroy  ActionType = "destroy"
	Admin    ActionType = "admin" // Catch-all action for admin/advanced feature
)

// Object types
const (
	Blob         ObjectType = "blob"
	KVEntry      ObjectType = "kv"
	FS           ObjectType = "fs"
	Node         ObjectType = "node"
	GitRepo      ObjectType = "git-repo"
	GitNs        ObjectType = "git-ns"
	Namespace    ObjectType = "namespace"
	JSONDocument ObjectType = "json-doc"
	Blob           ObjectType = "blob"
	KVEntry        ObjectType = "kv"
	FS             ObjectType = "fs"
	Node           ObjectType = "node"
	GitRepo        ObjectType = "git-repo"
	GitNs          ObjectType = "git-ns"
	Namespace      ObjectType = "namespace"
	JSONDocument   ObjectType = "json-doc"
	JSONCollection ObjectType = "json-col"
)

// Services