dex/server/client_resource.go
2015-08-18 11:26:57 -07:00

110 lines
3.1 KiB
Go

package server
import (
"encoding/json"
"fmt"
"net/http"
"path"
"github.com/coreos/dex/client"
phttp "github.com/coreos/dex/pkg/http"
"github.com/coreos/dex/pkg/log"
schema "github.com/coreos/dex/schema/workerschema"
"github.com/coreos/go-oidc/oidc"
)
type clientResource struct {
repo client.ClientIdentityRepo
}
func registerClientResource(prefix string, repo client.ClientIdentityRepo) (string, http.Handler) {
mux := http.NewServeMux()
c := &clientResource{
repo: repo,
}
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.repo.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.MapClientIdentityToSchemaClient(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.MapSchemaClientToClientIdentity(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
}
clientID, err := oidc.GenClientID(ci.Metadata.RedirectURLs[0].Host)
if err != nil {
log.Errorf("Failed generating ID for new client: %v", err)
writeAPIError(w, http.StatusInternalServerError, newAPIError(errorServerError, "unable to generate client ID"))
return
}
creds, err := c.repo.New(clientID, ci.Metadata)
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.MapClientIdentityToSchemaClientWithSecret(ci)
w.Header().Add("Location", phttp.NewResourceLocation(r.URL, ci.Credentials.ID))
writeResponseWithBody(w, http.StatusCreated, ssc)
}