auth
auth/request.go
Implement handlers for retrieving clients. Create a GetClientHandler and ListClientsHandler for retrieving details about a client. Currently, we're not returning the client secret for these clients. We're also not doing any auth. We may want to restrict auth to the owner of the clients, and return secrets only when auth'd, and maybe even only when a special header is included. Alternatively, we could only return the secret when retrieving a single client. Still unsure how I want to handle that.
| paddy@99 | 1 package auth |
| paddy@99 | 2 |
| paddy@104 | 3 import ( |
| paddy@104 | 4 "encoding/json" |
| paddy@104 | 5 "log" |
| paddy@104 | 6 "net/http" |
| paddy@104 | 7 |
| paddy@104 | 8 "bitbucket.org/ww/goautoneg" |
| paddy@104 | 9 ) |
| paddy@104 | 10 |
| paddy@99 | 11 const ( |
| paddy@99 | 12 requestErrAccessDenied = "access_denied" |
| paddy@99 | 13 requestErrInsufficient = "insufficient" |
| paddy@99 | 14 requestErrOverflow = "overflow" |
| paddy@99 | 15 requestErrInvalidValue = "invalid_value" |
| paddy@99 | 16 requestErrInvalidFormat = "invalid_format" |
| paddy@99 | 17 requestErrMissing = "missing" |
| paddy@99 | 18 requestErrNotFound = "not_found" |
| paddy@104 | 19 requestErrConflict = "conflict" |
| paddy@99 | 20 requestErrActOfGod = "act_of_god" |
| paddy@99 | 21 ) |
| paddy@99 | 22 |
| paddy@104 | 23 var ( |
| paddy@104 | 24 actOfGodResponse = response{Errors: []requestError{requestError{Slug: requestErrActOfGod}}} |
| paddy@104 | 25 invalidFormatResponse = response{Errors: []requestError{requestError{Slug: requestErrInvalidFormat, Field: "/"}}} |
| paddy@104 | 26 |
| paddy@104 | 27 encoders = []string{"application/json"} |
| paddy@104 | 28 ) |
| paddy@104 | 29 |
| paddy@104 | 30 type response struct { |
| paddy@108 | 31 Errors []requestError `json:"errors,omitempty"` |
| paddy@108 | 32 Logins []Login `json:"logins,omitempty"` |
| paddy@108 | 33 Profiles []Profile `json:"profiles,omitempty"` |
| paddy@108 | 34 Clients []Client `json:"clients,omitempty"` |
| paddy@108 | 35 Endpoints []Endpoint `json:"endpoints,omitempty"` |
| paddy@104 | 36 } |
| paddy@104 | 37 |
| paddy@99 | 38 type requestError struct { |
| paddy@99 | 39 Slug string `json:"error,omitempty"` |
| paddy@99 | 40 Field string `json:"field,omitempty"` |
| paddy@99 | 41 Param string `json:"param,omitempty"` |
| paddy@99 | 42 Header string `json:"header,omitempty"` |
| paddy@99 | 43 } |
| paddy@104 | 44 |
| paddy@104 | 45 func negotiate(h http.Handler) http.Handler { |
| paddy@104 | 46 return http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) { |
| paddy@110 | 47 if r.Header.Get("Accept") != "" { |
| paddy@110 | 48 contentType := goautoneg.Negotiate(r.Header.Get("Accept"), encoders) |
| paddy@110 | 49 if contentType == "" { |
| paddy@110 | 50 w.WriteHeader(http.StatusNotAcceptable) |
| paddy@110 | 51 w.Write([]byte("Unsupported content type requested: " + r.Header.Get("Accept"))) |
| paddy@110 | 52 return |
| paddy@110 | 53 } |
| paddy@104 | 54 } |
| paddy@104 | 55 h.ServeHTTP(w, r) |
| paddy@104 | 56 }) |
| paddy@104 | 57 } |
| paddy@104 | 58 |
| paddy@104 | 59 func encode(w http.ResponseWriter, r *http.Request, status int, resp response) { |
| paddy@104 | 60 contentType := goautoneg.Negotiate(r.Header.Get("Accept"), encoders) |
| paddy@104 | 61 w.Header().Set("content-type", contentType) |
| paddy@104 | 62 w.WriteHeader(status) |
| paddy@104 | 63 var err error |
| paddy@104 | 64 switch contentType { |
| paddy@104 | 65 case "application/json": |
| paddy@104 | 66 enc := json.NewEncoder(w) |
| paddy@104 | 67 err = enc.Encode(resp) |
| paddy@110 | 68 default: |
| paddy@110 | 69 enc := json.NewEncoder(w) |
| paddy@110 | 70 err = enc.Encode(resp) |
| paddy@104 | 71 } |
| paddy@104 | 72 if err != nil { |
| paddy@104 | 73 log.Println(err) |
| paddy@104 | 74 } |
| paddy@104 | 75 } |
| paddy@104 | 76 |
| paddy@104 | 77 func wrap(context Context, f func(w http.ResponseWriter, r *http.Request, context Context)) http.Handler { |
| paddy@104 | 78 return negotiate(http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) { |
| paddy@104 | 79 f(w, r, context) |
| paddy@104 | 80 })) |
| paddy@104 | 81 } |