diff --git a/main.go b/main.go index f07d20c..8f691d3 100644 --- a/main.go +++ b/main.go @@ -2,6 +2,7 @@ package main import ( "local/dndex/config" + "local/dndex/server" "local/dndex/storage" "local/dndex/view" "log" @@ -14,6 +15,7 @@ func main() { log.Println(c) g := storage.NewRateLimitedGraph() view.GitCommit = GitCommit + server.GitCommit = GitCommit if err := view.JSON(g); err != nil { panic(err) } diff --git a/server/auth/generate.go b/server/auth/generate.go index e1cc8a6..46df2f1 100644 --- a/server/auth/generate.go +++ b/server/auth/generate.go @@ -2,6 +2,7 @@ package auth import ( "context" + "errors" "local/dndex/storage" "local/dndex/storage/entity" "net/http" @@ -27,6 +28,9 @@ func Generate(g storage.RateLimitedGraph, r *http.Request, salt string) (string, func generateToken(g storage.RateLimitedGraph, r *http.Request) (Token, string, error) { namespaceRequested := readRequestedNamespace(r) + if namespaceRequested == "" { + return Token{}, "", errors.New("no namespace found") + } key, err := getKeyForNamespace(r.Context(), g, namespaceRequested) if err != nil { return Token{}, "", err diff --git a/server/middleware.go b/server/middleware.go index be9c188..b0ad32a 100644 --- a/server/middleware.go +++ b/server/middleware.go @@ -47,3 +47,14 @@ func (rest *REST) auth(foo http.HandlerFunc) http.HandlerFunc { foo(w, r) } } + +func (rest *REST) shift(foo http.HandlerFunc) http.HandlerFunc { + return func(w http.ResponseWriter, r *http.Request) { + i := 1 + for i < len(r.URL.Path) && r.URL.Path[i] != '/' { + i++ + } + r.URL.Path = r.URL.Path[i:] + foo(w, r) + } +} diff --git a/server/rest.go b/server/rest.go index ef18786..a154d16 100644 --- a/server/rest.go +++ b/server/rest.go @@ -6,6 +6,7 @@ import ( "local/dndex/server/auth" "local/dndex/storage" "local/router" + "log" "net/http" ) @@ -35,14 +36,15 @@ func NewREST(g storage.RateLimitedGraph) (*REST, error) { _, _ = param, params paths := map[string]http.HandlerFunc{ - fmt.Sprintf("version"): rest.version, - fmt.Sprintf("files/%s/%s", config.New().FilePrefix, params): rest.files, - fmt.Sprintf("users"): rest.users, - fmt.Sprintf("entities/%s", params): rest.entities, + fmt.Sprintf("version"): rest.version, + fmt.Sprintf("%s/%s", config.New().FilePrefix, params): rest.files, + fmt.Sprintf("users"): rest.users, + fmt.Sprintf("entities/%s", params): rest.entities, } for path, foo := range paths { bar := foo + bar = rest.shift(bar) bar = rest.auth(bar) bar = rest.defend(bar) bar = rest.delay(bar) @@ -58,14 +60,17 @@ func (rest *REST) scope(r *http.Request) auth.Scope { return auth.GetScope(r) } -func (rest *REST) files(w http.ResponseWriter, _ *http.Request) { +func (rest *REST) files(w http.ResponseWriter, r *http.Request) { + log.Println("files: SCOPE:", rest.scope(r), r.URL.Path) http.Error(w, "not impl", http.StatusNotImplemented) } -func (rest *REST) users(w http.ResponseWriter, _ *http.Request) { +func (rest *REST) users(w http.ResponseWriter, r *http.Request) { + log.Println("users: SCOPE:", rest.scope(r), r.URL.Path) http.Error(w, "not impl", http.StatusNotImplemented) } -func (rest *REST) entities(w http.ResponseWriter, _ *http.Request) { +func (rest *REST) entities(w http.ResponseWriter, r *http.Request) { + log.Println("entities: SCOPE:", rest.scope(r), r.URL.Path) http.Error(w, "not impl", http.StatusNotImplemented) } diff --git a/server/rest_test.go b/server/rest_test.go index a1daff9..1f5870c 100644 --- a/server/rest_test.go +++ b/server/rest_test.go @@ -5,6 +5,7 @@ import ( "fmt" "io/ioutil" "local/dndex/config" + "local/dndex/server/auth" "local/dndex/storage" "local/dndex/storage/entity" "net/http" @@ -19,16 +20,15 @@ import ( ) var ( - testNamespaceName = "col-name-" + uuid.New().String()[:10] - testNamespaceID = "col-id-" + uuid.New().String()[:10] - testEntityName = "ent-name-" + uuid.New().String()[:10] - testEntityID = "ent-id-" + uuid.New().String()[:10] - testFilename = "filename-" + uuid.New().String()[:10] - testContent = "content-" + uuid.New().String()[:10] + testNamespace = "col-" + uuid.New().String()[:10] + testEntityName = "ent-name-" + uuid.New().String()[:10] + testEntityID = "ent-id-" + uuid.New().String()[:10] + testFilename = "filename-" + uuid.New().String()[:10] + testContent = "content-" + uuid.New().String()[:10] ) func TestRESTRouter(t *testing.T) { - rest, clean := testREST(t) + rest, setAuth, clean := testREST(t) defer clean() cases := map[string]struct { method string @@ -52,11 +52,11 @@ func TestRESTRouter(t *testing.T) { method: http.MethodGet, is404: true, }, - fmt.Sprintf("/users/%s", testNamespaceID): { + fmt.Sprintf("/users/%s", testNamespace): { method: http.MethodGet, is404: true, }, - fmt.Sprintf("/users/%s", testNamespaceID): { + fmt.Sprintf("/users/%s", testNamespace): { method: http.MethodPost, is404: true, }, @@ -148,6 +148,7 @@ func TestRESTRouter(t *testing.T) { path := name t.Run(name, func(t *testing.T) { r := httptest.NewRequest(c.method, path, strings.NewReader(``)) + setAuth(r) w := httptest.NewRecorder() rest.router.ServeHTTP(w, r) if (w.Code == http.StatusNotFound) != c.is404 { @@ -157,7 +158,7 @@ func TestRESTRouter(t *testing.T) { } } -func testREST(t *testing.T) (*REST, func()) { +func testREST(t *testing.T) (*REST, func(r *http.Request), func()) { d, err := ioutil.TempDir(os.TempDir(), "tempdir.*") if err != nil { t.Fatal(err) @@ -179,26 +180,25 @@ func testREST(t *testing.T) (*REST, func()) { one := randomOne() one.Name = testEntityName one.ID = testEntityID - if err := rest.g.Insert(ctx, testNamespaceID, one); err != nil { + if err := rest.g.Insert(ctx, testNamespace, one); err != nil { t.Fatal(err) } - if err := rest.g.Insert(ctx, testNamespaceID+"."+AuthKey, entity.One{ - Name: testNamespaceName, - ID: testNamespaceID, - Title: "title", - }); err != nil { + register := httptest.NewRequest(http.MethodPost, "/", strings.NewReader(fmt.Sprintf("%s=%s&%s=%s", auth.UserKey, testNamespace, auth.AuthKey, "password"))) + register.Header.Set("Content-Type", "application/x-www-form-urlencoded") + if err := auth.Register(rest.g, register); err != nil { t.Fatal(err) } - if err := rest.g.Insert(ctx, testNamespaceID+"."+AuthKey, entity.One{ - Name: UserKey, - ID: UserKey, - Title: "", - }); err != nil { + login := httptest.NewRequest(http.MethodPost, "/", strings.NewReader(auth.UserKey+"="+testNamespace)) + login.Header.Set("Content-Type", "application/x-www-form-urlencoded") + token, err := auth.GeneratePlain(rest.g, login) + if err != nil { t.Fatal(err) } - return rest, func() { - os.RemoveAll(d) - } + return rest, func(r *http.Request) { + r.AddCookie(&http.Cookie{Name: auth.AuthKey, Value: token}) + }, func() { + os.RemoveAll(d) + } } func randomOne() entity.One {