From 11e7d13cca0767582648a241b855dc9a7f38ada8 Mon Sep 17 00:00:00 2001 From: Bel LaPointe Date: Fri, 24 Jul 2020 12:42:42 -0600 Subject: [PATCH] Namespace is a query param --- config/config.go | 3 +++ view/auth.go | 51 ++++++++++++++++++++++++++++++++++++++++++++++++ view/json.go | 20 +++++++------------ view/who.go | 5 +---- view/who_test.go | 28 +++++++++++++------------- 5 files changed, 76 insertions(+), 31 deletions(-) create mode 100644 view/auth.go diff --git a/config/config.go b/config/config.go index 179c5f3..b976de7 100644 --- a/config/config.go +++ b/config/config.go @@ -13,6 +13,7 @@ type Config struct { DriverType string FilePrefix string FileRoot string + Auth bool } func New() Config { @@ -30,6 +31,7 @@ func New() Config { as.Append(args.STRING, "fileroot", "path to file hosting root", "/tmp/") as.Append(args.STRING, "database", "database name to use", "db") as.Append(args.STRING, "drivertype", "database driver to use", "boltdb") + as.Append(args.BOOL, "auth", "check for authorized access", false) if err := as.Parse(); err != nil { panic(err) @@ -42,5 +44,6 @@ func New() Config { FileRoot: as.GetString("fileroot"), Database: as.GetString("database"), DriverType: as.GetString("drivertype"), + Auth: as.GetBool("auth"), } } diff --git a/view/auth.go b/view/auth.go new file mode 100644 index 0000000..55a8a88 --- /dev/null +++ b/view/auth.go @@ -0,0 +1,51 @@ +package view + +import ( + "encoding/json" + "errors" + "local/dndex/config" + "local/dndex/storage" + "net/http" +) + +const ( + AuthKey = "DnDex-Auth" +) + +func Auth(g storage.Graph, w http.ResponseWriter, r *http.Request) error { + if !config.New().Auth { + return nil + } + if err := auth(g, w, r); err != nil { + json.NewEncoder(w).Encode(map[string]interface{}{"error": "error when authorizing: " + err.Error()}) + return err + } + return nil +} + +func auth(g storage.Graph, w http.ResponseWriter, r *http.Request) error { + if !hasAuth(r) { + if err := requestAuth(g, w, r); err != nil { + return err + } + return errors.New("auth requested") + } + return checkAuth(g, r) +} + +func hasAuth(r *http.Request) bool { + _, ok := r.Cookie(AuthKey) + return ok == nil +} + +func checkAuth(g storage.Graph, r *http.Request) error { + panic(nil) + /* + token, _ := r.Cookie(AuthKey) + return errors.New("not impl") + */ +} + +func requestAuth(g storage.Graph, w http.ResponseWriter, r *http.Request) error { + return errors.New("not impl") +} diff --git a/view/json.go b/view/json.go index 437c87f..14a1012 100644 --- a/view/json.go +++ b/view/json.go @@ -26,20 +26,18 @@ func jsonHandler(g storage.Graph) http.Handler { foo func(g storage.Graph, w http.ResponseWriter, r *http.Request) error }{ { - path: "/who/", + path: "/who", foo: who, }, { - path: config.New().FilePrefix, + path: config.New().FilePrefix + "/", foo: files, }, } for _, route := range routes { - nopath := strings.TrimRight(route.path, "/") - path := nopath + "/" foo := route.foo - mux.HandleFunc(path, func(w http.ResponseWriter, r *http.Request) { + mux.HandleFunc(route.path, func(w http.ResponseWriter, r *http.Request) { if err := foo(g, w, r); err != nil { status := http.StatusInternalServerError if strings.Contains(err.Error(), "collision") { @@ -49,17 +47,13 @@ func jsonHandler(g storage.Graph) http.Handler { http.Error(w, string(b), status) } }) - mux.HandleFunc(nopath, http.NotFound) } return http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) { - /* - w.Header().Set("Access-Control-Allow-Origin", "*") - w.Header().Set("Content-Type", "application/json") - w.Header().Set("Access-Control-Allow-Methods", "POST, GET, OPTIONS, PUT, DELETE, OPTIONS, TRACE") - w.Header().Set("Access-Control-Allow-Headers", "Accept, Content-Type, Content-Length, Accept-Encoding, X-CSRF-Token, Authorization") - */ - + if err := Auth(g, w, r); err != nil { + log.Println(err) + return + } if gziphttp.Can(r) { gz := gziphttp.New(w) defer gz.Close() diff --git a/view/who.go b/view/who.go index a377ef2..b352a7f 100644 --- a/view/who.go +++ b/view/who.go @@ -9,20 +9,17 @@ import ( "local/dndex/storage/entity" "local/dndex/storage/operator" "net/http" - "path" - "strings" "github.com/buger/jsonparser" "go.mongodb.org/mongo-driver/bson" ) func who(g storage.Graph, w http.ResponseWriter, r *http.Request) error { - namespace := strings.TrimLeft(r.URL.Path, path.Dir(r.URL.Path)) + namespace := r.URL.Query().Get("namespace") if len(namespace) == 0 { http.NotFound(w, r) return nil } - namespace = strings.Replace(namespace, "/", ".", -1) switch r.Method { case http.MethodGet: diff --git a/view/who_test.go b/view/who_test.go index 2cf042b..eab0a68 100644 --- a/view/who_test.go +++ b/view/who_test.go @@ -53,7 +53,7 @@ func TestWho(t *testing.T) { t.Run("get fake", func(t *testing.T) { iwant := want - r := httptest.NewRequest(http.MethodGet, "/who/col?id=FAKER"+iwant.Name, nil) + r := httptest.NewRequest(http.MethodGet, "/who?namespace=col&id=FAKER"+iwant.Name, nil) w := httptest.NewRecorder() handler.ServeHTTP(w, r) if w.Code != http.StatusNotFound { @@ -63,7 +63,7 @@ func TestWho(t *testing.T) { t.Run("get real", func(t *testing.T) { iwant := want - r := httptest.NewRequest(http.MethodGet, "/who/col?id="+iwant.Name, nil) + r := httptest.NewRequest(http.MethodGet, "/who?namespace=col&id="+iwant.Name, nil) w := httptest.NewRecorder() handler.ServeHTTP(w, r) if w.Code != http.StatusOK { @@ -91,7 +91,7 @@ func TestWho(t *testing.T) { t.Run("put fake", func(t *testing.T) { iwant := want - r := httptest.NewRequest(http.MethodPut, "/who/col?id=FAKER"+iwant.Name, strings.NewReader(`{"title":"this should fail to find someone"}`)) + r := httptest.NewRequest(http.MethodPut, "/who?namespace=col&id=FAKER"+iwant.Name, strings.NewReader(`{"title":"this should fail to find someone"}`)) w := httptest.NewRecorder() handler.ServeHTTP(w, r) if w.Code != http.StatusNotFound { @@ -101,7 +101,7 @@ func TestWho(t *testing.T) { t.Run("put real", func(t *testing.T) { iwant := want - r := httptest.NewRequest(http.MethodPut, "/who/col?id="+iwant.Name, strings.NewReader(`{"title":"this should work"}`)) + r := httptest.NewRequest(http.MethodPut, "/who?namespace=col&id="+iwant.Name, strings.NewReader(`{"title":"this should work"}`)) w := httptest.NewRecorder() handler.ServeHTTP(w, r) if w.Code != http.StatusOK { @@ -124,7 +124,7 @@ func TestWho(t *testing.T) { t.Run("post exists", func(t *testing.T) { iwant := want iwant.Name = "" - r := httptest.NewRequest(http.MethodPost, "/who/col?id="+want.Name, strings.NewReader(`{"title":"this should fail to insert"}`)) + r := httptest.NewRequest(http.MethodPost, "/who?namespace=col&id="+want.Name, strings.NewReader(`{"title":"this should fail to insert"}`)) w := httptest.NewRecorder() handler.ServeHTTP(w, r) if w.Code != http.StatusConflict { @@ -139,7 +139,7 @@ func TestWho(t *testing.T) { if err != nil { t.Fatal(err) } - r := httptest.NewRequest(http.MethodPost, "/who/col?id=NEWBIE"+want.Name, bytes.NewReader(b)) + r := httptest.NewRequest(http.MethodPost, "/who?namespace=col&id=NEWBIE"+want.Name, bytes.NewReader(b)) w := httptest.NewRecorder() handler.ServeHTTP(w, r) if w.Code != http.StatusOK { @@ -160,13 +160,13 @@ func TestWho(t *testing.T) { }) t.Run("delete real", func(t *testing.T) { - r := httptest.NewRequest(http.MethodDelete, "/who/col?id=NEWBIE"+want.Name, nil) + r := httptest.NewRequest(http.MethodDelete, "/who?namespace=col&id=NEWBIE"+want.Name, nil) w := httptest.NewRecorder() handler.ServeHTTP(w, r) if w.Code != http.StatusOK { t.Fatalf("%d: %s", w.Code, w.Body.Bytes()) } - r = httptest.NewRequest(http.MethodGet, "/who/col?id=NEWBIE"+want.Name, nil) + r = httptest.NewRequest(http.MethodGet, "/who?namespace=col&id=NEWBIE"+want.Name, nil) w = httptest.NewRecorder() handler.ServeHTTP(w, r) if w.Code != http.StatusNotFound { @@ -175,7 +175,7 @@ func TestWho(t *testing.T) { }) t.Run("delete fake", func(t *testing.T) { - r := httptest.NewRequest(http.MethodDelete, "/who/col?id=FAKER"+want.Name, nil) + r := httptest.NewRequest(http.MethodDelete, "/who?namespace=col&id=FAKER"+want.Name, nil) w := httptest.NewRecorder() handler.ServeHTTP(w, r) if w.Code != http.StatusOK { @@ -184,7 +184,7 @@ func TestWho(t *testing.T) { }) t.Run("patch fake", func(t *testing.T) { - r := httptest.NewRequest(http.MethodPatch, "/who/col?id=FAKER"+want.Name, nil) + r := httptest.NewRequest(http.MethodPatch, "/who?namespace=col&id=FAKER"+want.Name, nil) w := httptest.NewRecorder() handler.ServeHTTP(w, r) if w.Code == http.StatusOK { @@ -201,7 +201,7 @@ func TestWho(t *testing.T) { if err != nil { t.Fatal(err) } - r := httptest.NewRequest(http.MethodPatch, "/who/col?id="+want.Name, bytes.NewReader(b)) + r := httptest.NewRequest(http.MethodPatch, "/who?namespace=col&id="+want.Name, bytes.NewReader(b)) w := httptest.NewRecorder() handler.ServeHTTP(w, r) if w.Code != http.StatusOK { @@ -222,13 +222,13 @@ func TestWho(t *testing.T) { got.Modified = 0 want.Modified = 0 if fmt.Sprint(got) != fmt.Sprint(want) { - t.Fatalf("withotu connections and modified, got != want: want \n %+v, got \n %+v", want, got) + t.Fatalf("without connections and modified, got != want: want \n %+v, got \n %+v", want, got) } t.Logf("%s", w.Body.Bytes()) }) t.Run("trace fake", func(t *testing.T) { - r := httptest.NewRequest(http.MethodTrace, "/who/notcol", nil) + r := httptest.NewRequest(http.MethodTrace, "/who?namespace=notcol", nil) w := httptest.NewRecorder() handler.ServeHTTP(w, r) if w.Code != http.StatusOK { @@ -237,7 +237,7 @@ func TestWho(t *testing.T) { }) t.Run("trace real", func(t *testing.T) { - r := httptest.NewRequest(http.MethodTrace, "/who/col", nil) + r := httptest.NewRequest(http.MethodTrace, "/who?namespace=col", nil) w := httptest.NewRecorder() handler.ServeHTTP(w, r) if w.Code != http.StatusOK {