From 8942a497021a95f5c52be57c21d659c508c120af Mon Sep 17 00:00:00 2001 From: Bobby Rullo Date: Wed, 15 Jun 2016 11:05:37 -0700 Subject: [PATCH] server: remove client_resource api ...and dependent code. --- integration/client_api_test.go | 91 ----------- schema/workerschema/mapper.go | 58 ------- server/client_resource.go | 102 ------------ server/client_resource_test.go | 284 --------------------------------- server/server.go | 3 - 5 files changed, 538 deletions(-) delete mode 100644 integration/client_api_test.go delete mode 100644 schema/workerschema/mapper.go delete mode 100644 server/client_resource.go delete mode 100644 server/client_resource_test.go diff --git a/integration/client_api_test.go b/integration/client_api_test.go deleted file mode 100644 index 4a3ad195..00000000 --- a/integration/client_api_test.go +++ /dev/null @@ -1,91 +0,0 @@ -package integration - -import ( - "encoding/base64" - "net/http" - "net/url" - "reflect" - "testing" - - "github.com/coreos/dex/client" - schema "github.com/coreos/dex/schema/workerschema" - "github.com/coreos/go-oidc/oidc" -) - -func TestClientCreate(t *testing.T) { - ci := client.Client{ - // Credentials are for reference, they are actually generated by the client manager - Credentials: oidc.ClientCredentials{ - ID: "authn.example.com", - Secret: base64.URLEncoding.EncodeToString([]byte("secret")), - }, - Metadata: oidc.ClientMetadata{ - RedirectURIs: []url.URL{ - {Scheme: "https://", Host: "authn.example.com", Path: "/callback"}, - }, - }, - } - cis := []client.LoadableClient{{Client: ci}} - - srv, err := mockServer(cis) - if err != nil { - t.Fatalf("Unexpected error setting up server: %v", err) - } - - oidcClient, err := mockClient(srv, ci) - if err != nil { - t.Fatalf("Unexpected error setting up OIDC client: %v", err) - } - - tok, err := oidcClient.ClientCredsToken([]string{"openid"}) - if err != nil { - t.Fatalf("Failed getting client token: %v", err) - } - - callbackURL := "http://example.com/oidc/callback" - trans := &tokenHandlerTransport{ - Handler: srv.HTTPHandler(), - Token: tok.Encode(), - } - hc := &http.Client{ - Transport: trans, - } - iss := srv.IssuerURL.String() - svc, err := schema.NewWithBasePath(hc, iss) - if err != nil { - t.Fatalf("Failed creating API service client: %v", err) - } - - newClientInput := &schema.Client{ - RedirectURIs: []string{callbackURL, "http://example.com"}, - } - - call := svc.Clients.Create(newClientInput) - newClient, err := call.Do() - if err != nil { - t.Fatalf("Call to create client API failed: %v", err) - } - - if newClient.Id == "" { - t.Error("Expected non-empty Client ID") - } - - if newClient.Secret == "" { - t.Error("Expected non-empty Client Secret") - } - - meta, err := srv.ClientManager.Metadata(newClient.Id) - if err != nil { - t.Errorf("Error looking up client metadata: %v", err) - } else if meta == nil { - t.Error("Expected new client to exist in repo") - } - - gotURLs := make([]string, len(meta.RedirectURIs)) - for i, u := range meta.RedirectURIs { - gotURLs[i] = u.String() - } - if !reflect.DeepEqual(newClientInput.RedirectURIs, gotURLs) { - t.Errorf("Callback URL mismatch, want=%s, got=%s", newClientInput.RedirectURIs, gotURLs) - } -} diff --git a/schema/workerschema/mapper.go b/schema/workerschema/mapper.go deleted file mode 100644 index 7cdf4ab3..00000000 --- a/schema/workerschema/mapper.go +++ /dev/null @@ -1,58 +0,0 @@ -package workerschema - -import ( - "errors" - "net/url" - - "github.com/coreos/dex/client" - "github.com/coreos/go-oidc/oidc" -) - -func MapSchemaClientToClient(sc Client) (client.Client, error) { - ci := client.Client{ - Credentials: oidc.ClientCredentials{ - ID: sc.Id, - }, - Metadata: oidc.ClientMetadata{ - RedirectURIs: make([]url.URL, len(sc.RedirectURIs)), - }, - } - - for i, ru := range sc.RedirectURIs { - if ru == "" { - return client.Client{}, errors.New("redirect URL empty") - } - - u, err := url.Parse(ru) - if err != nil { - return client.Client{}, errors.New("redirect URL invalid") - } - - ci.Metadata.RedirectURIs[i] = *u - } - - return ci, nil -} - -func MapClientToSchemaClient(c client.Client) Client { - cl := Client{ - Id: c.Credentials.ID, - RedirectURIs: make([]string, len(c.Metadata.RedirectURIs)), - } - for i, u := range c.Metadata.RedirectURIs { - cl.RedirectURIs[i] = u.String() - } - return cl -} - -func MapClientToSchemaClientWithSecret(c client.Client) ClientWithSecret { - cl := ClientWithSecret{ - Id: c.Credentials.ID, - Secret: c.Credentials.Secret, - RedirectURIs: make([]string, len(c.Metadata.RedirectURIs)), - } - for i, u := range c.Metadata.RedirectURIs { - cl.RedirectURIs[i] = u.String() - } - return cl -} diff --git a/server/client_resource.go b/server/client_resource.go deleted file mode 100644 index b4fad488..00000000 --- a/server/client_resource.go +++ /dev/null @@ -1,102 +0,0 @@ -package server - -import ( - "encoding/json" - "fmt" - "net/http" - "path" - - "github.com/coreos/dex/client/manager" - phttp "github.com/coreos/dex/pkg/http" - "github.com/coreos/dex/pkg/log" - schema "github.com/coreos/dex/schema/workerschema" -) - -type clientResource struct { - manager *manager.ClientManager -} - -func registerClientResource(prefix string, manager *manager.ClientManager) (string, http.Handler) { - mux := http.NewServeMux() - c := &clientResource{ - manager: manager, - } - relPath := "clients" - absPath := path.Join(prefix, relPath) - mux.Handle(absPath, c) - return relPath, mux -} - -func (c *clientResource) ServeHTTP(w http.ResponseWriter, r *http.Request) { - switch r.Method { - case "GET": - c.list(w, r) - case "POST": - c.create(w, r) - default: - msg := fmt.Sprintf("HTTP %s method not supported for this resource", r.Method) - writeAPIError(w, http.StatusMethodNotAllowed, newAPIError(errorInvalidRequest, msg)) - } -} - -func (c *clientResource) list(w http.ResponseWriter, r *http.Request) { - cs, err := c.manager.All() - if err != nil { - writeAPIError(w, http.StatusInternalServerError, newAPIError(errorServerError, "error listing clients")) - return - } - - scs := make([]*schema.Client, len(cs)) - for i, ci := range cs { - sc := schema.MapClientToSchemaClient(ci) - scs[i] = &sc - } - - page := schema.ClientPage{ - Clients: scs, - } - writeResponseWithBody(w, http.StatusOK, page) -} - -func (c *clientResource) create(w http.ResponseWriter, r *http.Request) { - ct := r.Header.Get("content-type") - if ct != "application/json" { - log.Debugf("Unsupported request content-type: %v", ct) - writeAPIError(w, http.StatusBadRequest, newAPIError(errorInvalidRequest, "unsupported content-type")) - return - } - - var sc schema.Client - dec := json.NewDecoder(r.Body) - err := dec.Decode(&sc) - if err != nil { - log.Debugf("Error decoding request body: %v", err) - writeAPIError(w, http.StatusBadRequest, newAPIError(errorInvalidRequest, "unable to decode request body")) - return - } - - ci, err := schema.MapSchemaClientToClient(sc) - if err != nil { - log.Debugf("Invalid request data: %v", err) - writeAPIError(w, http.StatusBadRequest, newAPIError(errorInvalidClientMetadata, "missing or invalid field: redirectURIs")) - return - } - - if err := ci.Metadata.Valid(); err != nil { - log.Debugf("ClientMetadata invalid: %v", err) - writeAPIError(w, http.StatusBadRequest, newAPIError(errorInvalidClientMetadata, err.Error())) - return - } - creds, err := c.manager.New(ci, nil) - - if err != nil { - log.Errorf("Failed creating client: %v", err) - writeAPIError(w, http.StatusInternalServerError, newAPIError(errorServerError, "unable to create client")) - return - } - ci.Credentials = *creds - - ssc := schema.MapClientToSchemaClientWithSecret(ci) - w.Header().Add("Location", phttp.NewResourceLocation(r.URL, ci.Credentials.ID)) - writeResponseWithBody(w, http.StatusCreated, ssc) -} diff --git a/server/client_resource_test.go b/server/client_resource_test.go deleted file mode 100644 index 7fffa78a..00000000 --- a/server/client_resource_test.go +++ /dev/null @@ -1,284 +0,0 @@ -package server - -import ( - "encoding/base64" - "encoding/json" - "fmt" - "io" - "io/ioutil" - "net/http" - "net/http/httptest" - "net/url" - "reflect" - "sort" - "strings" - "testing" - - "github.com/coreos/dex/client" - "github.com/coreos/dex/client/manager" - "github.com/coreos/dex/db" - schema "github.com/coreos/dex/schema/workerschema" - "github.com/coreos/go-oidc/oidc" - "github.com/kylelemons/godebug/pretty" -) - -func makeBody(s string) io.ReadCloser { - return ioutil.NopCloser(strings.NewReader(s)) -} - -func TestCreateInvalidRequest(t *testing.T) { - u := &url.URL{Scheme: "http", Host: "example.com", Path: "clients"} - h := http.Header{"Content-Type": []string{"application/json"}} - dbm := db.NewMemDB() - repo := db.NewClientRepo(dbm) - manager := manager.NewClientManager(repo, db.TransactionFactory(dbm), manager.ManagerOptions{}) - res := &clientResource{manager: manager} - tests := []struct { - req *http.Request - wantCode int - wantBody string - }{ - // invalid content-type - { - req: &http.Request{Method: "POST", URL: u, Header: http.Header{"Content-Type": []string{"application/xml"}}}, - wantCode: http.StatusBadRequest, - wantBody: `{"error":"invalid_request","error_description":"unsupported content-type"}`, - }, - // invalid method - { - req: &http.Request{Method: "DELETE", URL: u, Header: h}, - wantCode: http.StatusMethodNotAllowed, - wantBody: `{"error":"invalid_request","error_description":"HTTP DELETE method not supported for this resource"}`, - }, - // invalid method - { - req: &http.Request{Method: "PUT", URL: u, Header: h}, - wantCode: http.StatusMethodNotAllowed, - wantBody: `{"error":"invalid_request","error_description":"HTTP PUT method not supported for this resource"}`, - }, - // invalid method - { - req: &http.Request{Method: "HEAD", URL: u, Header: h}, - wantCode: http.StatusMethodNotAllowed, - wantBody: `{"error":"invalid_request","error_description":"HTTP HEAD method not supported for this resource"}`, - }, - // unserializable body - { - req: &http.Request{Method: "POST", URL: u, Header: h, Body: makeBody("asdf")}, - wantCode: http.StatusBadRequest, - wantBody: `{"error":"invalid_request","error_description":"unable to decode request body"}`, - }, - // empty body - { - req: &http.Request{Method: "POST", URL: u, Header: h, Body: makeBody("")}, - wantCode: http.StatusBadRequest, - wantBody: `{"error":"invalid_request","error_description":"unable to decode request body"}`, - }, - // missing url field - { - req: &http.Request{Method: "POST", URL: u, Header: h, Body: makeBody(`{"id":"foo"}`)}, - wantCode: http.StatusBadRequest, - wantBody: `{"error":"invalid_client_metadata","error_description":"zero redirect URLs"}`, - }, - // empty url array - { - req: &http.Request{Method: "POST", URL: u, Header: h, Body: makeBody(`{"redirectURIs":[]}`)}, - wantCode: http.StatusBadRequest, - wantBody: `{"error":"invalid_client_metadata","error_description":"zero redirect URLs"}`, - }, - // array with empty string - { - req: &http.Request{Method: "POST", URL: u, Header: h, Body: makeBody(`{"redirectURIs":[""]}`)}, - wantCode: http.StatusBadRequest, - wantBody: `{"error":"invalid_client_metadata","error_description":"missing or invalid field: redirectURIs"}`, - }, - // uri with unusable scheme - { - req: &http.Request{Method: "POST", URL: u, Header: h, Body: makeBody(`{"redirectURIs":["asdf.com"]}`)}, - wantCode: http.StatusBadRequest, - wantBody: `{"error":"invalid_client_metadata","error_description":"no host for uri field redirect_uris"}`, - }, - // uri missing host - { - req: &http.Request{Method: "POST", URL: u, Header: h, Body: makeBody(`{"redirectURIs":["http://"]}`)}, - wantCode: http.StatusBadRequest, - wantBody: `{"error":"invalid_client_metadata","error_description":"no host for uri field redirect_uris"}`, - }, - } - - for i, tt := range tests { - w := httptest.NewRecorder() - res.ServeHTTP(w, tt.req) - - if w.Code != tt.wantCode { - t.Errorf("case %d: invalid response code, want=%d, got=%d", i, tt.wantCode, w.Code) - } - - gotBody := w.Body.String() - if gotBody != tt.wantBody { - t.Errorf("case %d: invalid response body, want=%s, got=%s", i, tt.wantBody, gotBody) - } - } -} - -func TestCreate(t *testing.T) { - dbm := db.NewMemDB() - repo := db.NewClientRepo(dbm) - manager := manager.NewClientManager(repo, db.TransactionFactory(dbm), manager.ManagerOptions{}) - res := &clientResource{manager: manager} - tests := [][]string{ - []string{"http://example.com"}, - []string{"https://example.com"}, - []string{"http://example.com/foo"}, - []string{"http://example.com/bar", "http://example.com/foo"}, - } - endpoint := "http://example.com/clients" - - for i, tt := range tests { - body := strings.NewReader(fmt.Sprintf(`{"redirectURIs":["%s"]}`, strings.Join(tt, `","`))) - r, err := http.NewRequest("POST", endpoint, body) - if err != nil { - t.Fatalf("Failed creating http.Request: %v", err) - } - r.Header.Set("content-type", "application/json") - w := httptest.NewRecorder() - res.ServeHTTP(w, r) - - if w.Code != http.StatusCreated { - t.Errorf("case %d: invalid response code, want=%d, got=%d", i, http.StatusCreated, w.Code) - } - - var client schema.ClientWithSecret - if err := json.Unmarshal(w.Body.Bytes(), &client); err != nil { - t.Errorf("case %d: unexpected error=%v", i, err) - } - if len(client.RedirectURIs) != len(tt) { - t.Errorf("case %d: unexpected number of redirect URIs, want=%d, got=%d", i, len(tt), len(client.RedirectURIs)) - } - - if !reflect.DeepEqual(tt, client.RedirectURIs) { - t.Errorf("case %d: unexpected client redirect URIs: want=%v got=%v", i, tt, client.RedirectURIs) - } - - if client.Id == "" { - t.Errorf("case %d: empty client ID in response", i) - } - - if client.Secret == "" { - t.Errorf("case %d: empty client secret in response", i) - } - - wantLoc := fmt.Sprintf("%s/%s", endpoint, client.Id) - gotLoc := w.Header().Get("Location") - if gotLoc != wantLoc { - t.Errorf("case %d: invalid location header, want=%v, got=%v", i, wantLoc, gotLoc) - } - } -} - -func TestList(t *testing.T) { - - b64Encode := func(s string) string { - return base64.URLEncoding.EncodeToString([]byte(s)) - } - - tests := []struct { - cs []client.Client - want []*schema.Client - }{ - // empty repo - { - cs: []client.Client{}, - want: nil, - }, - // single client - { - cs: []client.Client{ - client.Client{ - Credentials: oidc.ClientCredentials{ID: "example.com", Secret: b64Encode("secret")}, - Metadata: oidc.ClientMetadata{ - RedirectURIs: []url.URL{ - url.URL{Scheme: "http", Host: "example.com"}, - }, - }, - }, - }, - want: []*schema.Client{ - &schema.Client{ - Id: "example.com", - RedirectURIs: []string{"http://example.com"}, - }, - }, - }, - // multi client - { - cs: []client.Client{ - client.Client{ - Credentials: oidc.ClientCredentials{ID: "example.com", Secret: b64Encode("secret")}, - Metadata: oidc.ClientMetadata{ - RedirectURIs: []url.URL{ - url.URL{Scheme: "http", Host: "example.com"}, - }, - }, - }, - client.Client{ - Credentials: oidc.ClientCredentials{ID: "example2.com", Secret: b64Encode("secret")}, - Metadata: oidc.ClientMetadata{ - RedirectURIs: []url.URL{ - url.URL{Scheme: "https", Host: "example2.com", Path: "one/two/three"}, - }, - }, - }, - }, - want: []*schema.Client{ - &schema.Client{ - Id: "example2.com", - RedirectURIs: []string{"https://example2.com/one/two/three"}, - }, - &schema.Client{ - Id: "example.com", - RedirectURIs: []string{"http://example.com"}, - }, - }, - }, - } - - for i, tt := range tests { - f, err := makeTestFixturesWithOptions(testFixtureOptions{ - clients: clientsToLoadableClients(tt.cs), - }) - if err != nil { - t.Fatalf("error making test fixtures: %v", err) - } - - res := &clientResource{manager: f.clientManager} - - r, err := http.NewRequest("GET", "http://example.com/clients", nil) - if err != nil { - t.Fatalf("Failed creating http.Request: %v", err) - } - w := httptest.NewRecorder() - res.ServeHTTP(w, r) - - if w.Code != http.StatusOK { - t.Errorf("case %d: invalid response code, want=%d, got=%d", i, http.StatusOK, w.Code) - } - - var resp schema.ClientPage - if err := json.Unmarshal(w.Body.Bytes(), &resp); err != nil { - t.Errorf("case %d: unexpected error=%v", i, err) - } - sort.Sort(byClientId(tt.want)) - sort.Sort(byClientId(resp.Clients)) - - if diff := pretty.Compare(tt.want, resp.Clients); diff != "" { - t.Errorf("case %d: invalid response body: %s", i, diff) - } - } -} - -type byClientId []*schema.Client - -func (b byClientId) Len() int { return len(b) } -func (b byClientId) Less(i, j int) bool { return b[i].Id < b[j].Id } -func (b byClientId) Swap(i, j int) { b[i], b[j] = b[j], b[i] } diff --git a/server/server.go b/server/server.go index a151f0b3..22cf42d7 100644 --- a/server/server.go +++ b/server/server.go @@ -265,9 +265,6 @@ func (s *Server) HTTPHandler() http.Handler { apiBasePath := path.Join(httpPathAPI, APIVersion) registerDiscoveryResource(apiBasePath, mux) - clientPath, clientHandler := registerClientResource(apiBasePath, s.ClientManager) - mux.Handle(path.Join(apiBasePath, clientPath), s.NewClientTokenAuthHandler(clientHandler)) - usersAPI := usersapi.NewUsersAPI(s.UserManager, s.ClientManager, s.RefreshTokenRepo, s.UserEmailer, s.localConnectorID) handler := NewUserMgmtServer(usersAPI, s.JWTVerifierFactory(), s.UserManager, s.ClientManager).HTTPHandler()