From 3a69fad9f7f0457d4c37b7f8a9f070e2c0d92082 Mon Sep 17 00:00:00 2001 From: Bel LaPointe Date: Fri, 24 Jul 2020 15:06:49 -0600 Subject: [PATCH] registration --- view/auth_test.go | 17 +------ view/json.go | 5 ++ view/register.go | 43 ++++++++++++++++ view/register_test.go | 113 ++++++++++++++++++++++++++++++++++++++++++ 4 files changed, 163 insertions(+), 15 deletions(-) create mode 100644 view/register.go create mode 100644 view/register_test.go diff --git a/view/auth_test.go b/view/auth_test.go index 032ad41..7454bf3 100644 --- a/view/auth_test.go +++ b/view/auth_test.go @@ -9,7 +9,6 @@ import ( "net/http" "net/http/httptest" "os" - "strings" "testing" "time" @@ -114,23 +113,11 @@ func TestAuth(t *testing.T) { if w.Code != http.StatusSeeOther { t.Fatalf("%d: %s", w.Code, w.Body.Bytes()) } - cookies := w.Header()["Set-Cookie"] - if len(cookies) == 0 { - t.Fatal(w.Header()) - } - var rawtoken string - for i := range cookies { - value := strings.Split(cookies[i], ";")[0] - key := value[:strings.Index(value, "=")] - value = value[strings.Index(value, "=")+1:] - if key == NewAuthKey { - rawtoken = value - } - } + + rawtoken := getCookie(NewAuthKey, w.Header()) if rawtoken == "" { t.Fatal(w.Header()) } - token, err := aesDec("password", rawtoken) if err != nil { t.Fatal(err) diff --git a/view/json.go b/view/json.go index 0333301..5c41a5d 100644 --- a/view/json.go +++ b/view/json.go @@ -31,6 +31,11 @@ func jsonHandler(g storage.Graph) http.Handler { path: "/who", foo: who, }, + { + path: "/register", + foo: register, + noauth: true, + }, { path: config.New().FilePrefix + "/", foo: files, diff --git a/view/register.go b/view/register.go new file mode 100644 index 0000000..fc262a2 --- /dev/null +++ b/view/register.go @@ -0,0 +1,43 @@ +package view + +import ( + "encoding/json" + "local/dndex/storage" + "local/dndex/storage/entity" + "net/http" +) + +func register(g storage.Graph, w http.ResponseWriter, r *http.Request) error { + switch r.Method { + case http.MethodPost: + return registerPost(g, w, r) + default: + http.NotFound(w, r) + return nil + } +} + +func registerPost(g storage.Graph, w http.ResponseWriter, r *http.Request) error { + namespace, err := getAuthNamespace(r) + if err != nil { + http.Error(w, err.Error(), http.StatusBadRequest) + return nil + } + if err := r.ParseForm(); err != nil { + http.Error(w, err.Error(), http.StatusBadRequest) + return nil + } + password := r.FormValue("password") + if len(password) == 0 { + http.Error(w, `{"error": "password required"}`, http.StatusBadRequest) + return nil + } + one := entity.One{ + Name: UserKey, + Title: password, + } + if err := g.Insert(r.Context(), namespace, one); err != nil { + return err + } + return json.NewEncoder(w).Encode(map[string]string{"status": "ok"}) +} diff --git a/view/register_test.go b/view/register_test.go new file mode 100644 index 0000000..48cdbdc --- /dev/null +++ b/view/register_test.go @@ -0,0 +1,113 @@ +package view + +import ( + "fmt" + "io/ioutil" + "local/dndex/storage" + "net/http" + "net/http/httptest" + "os" + "strings" + "testing" + + "github.com/google/uuid" +) + +func TestRegister(t *testing.T) { + os.Args = os.Args[:1] + f, err := ioutil.TempFile(os.TempDir(), "pattern*") + if err != nil { + t.Fatal(err) + } + f.Close() + defer os.Remove(f.Name()) + os.Setenv("DBURI", f.Name()) + + os.Setenv("AUTH", "true") + defer os.Setenv("AUTH", "false") + + g := storage.NewGraph() + handler := jsonHandler(g) + + t.Run("register: wrong method", func(t *testing.T) { + r := httptest.NewRequest(http.MethodGet, "/register", nil) + r.Header.Set("Content-Type", "application/x-www-form-urlencoded") + w := httptest.NewRecorder() + handler.ServeHTTP(w, r) + if w.Code != http.StatusNotFound { + t.Fatalf("%d: %s", w.Code, w.Body.Bytes()) + } + }) + + t.Run("register: no namespace", func(t *testing.T) { + r := httptest.NewRequest(http.MethodPost, "/register", strings.NewReader("")) + r.Header.Set("Content-Type", "application/x-www-form-urlencoded") + w := httptest.NewRecorder() + handler.ServeHTTP(w, r) + if w.Code != http.StatusBadRequest { + t.Fatalf("%d: %s", w.Code, w.Body.Bytes()) + } + }) + + t.Run("register: no password", func(t *testing.T) { + r := httptest.NewRequest(http.MethodPost, "/register?namespace="+uuid.New().String(), strings.NewReader("")) + r.Header.Set("Content-Type", "application/x-www-form-urlencoded") + w := httptest.NewRecorder() + handler.ServeHTTP(w, r) + if w.Code != http.StatusBadRequest { + t.Fatalf("%d: %s", w.Code, w.Body.Bytes()) + } + }) + + t.Run("register", func(t *testing.T) { + ns := uuid.New().String() + + r := httptest.NewRequest(http.MethodPost, "/register?namespace="+ns, strings.NewReader(`password=123`)) + r.Header.Set("Content-Type", "application/x-www-form-urlencoded") + w := httptest.NewRecorder() + handler.ServeHTTP(w, r) + if w.Code != http.StatusOK { + t.Fatalf("%d: %s", w.Code, w.Body.Bytes()) + } + t.Logf("/register: %s", w.Body.Bytes()) + + r = httptest.NewRequest(http.MethodTrace, "/who?namespace="+ns, nil) + w = httptest.NewRecorder() + handler.ServeHTTP(w, r) + if w.Code != http.StatusSeeOther { + t.Fatalf("%d: %s", w.Code, w.Body.Bytes()) + } + t.Logf("noauth /who: %s", w.Body.Bytes()) + + rawtoken := getCookie(NewAuthKey, w.Header()) + token, err := aesDec("123", rawtoken) + if err != nil { + t.Fatal(err) + } + + r = httptest.NewRequest(http.MethodTrace, "/who?namespace="+ns, nil) + r.Header.Set("Cookie", fmt.Sprintf("%s=%s", AuthKey, token)) + w = httptest.NewRecorder() + handler.ServeHTTP(w, r) + if w.Code != http.StatusOK { + t.Fatalf("%d: %s", w.Code, w.Body.Bytes()) + } + t.Logf("auth /who: %s", w.Body.Bytes()) + }) +} + +func getCookie(key string, header http.Header) string { + cookies, _ := header["Set-Cookie"] + if len(cookies) == 0 { + cookies, _ = header["Cookie"] + } + for i := range cookies { + value := strings.Split(cookies[i], ";")[0] + k := value[:strings.Index(value, "=")] + v := value[strings.Index(value, "=")+1:] + if k == key { + return v + } + } + return "" +}