auth
143:3aeadd2201e9 Browse Files
Add GetEndpoint method, add RemoveEndpoint handler. Add a method to our clientStore and Context types for retrieving an Endpoint from the clientStore. We need this to tell if someone is trying to delete an Endpoint that doesn't exist. Add a handler for removing Endpoints from a Client.
1.1 --- a/client.go Sat Mar 07 20:45:34 2015 -0500 1.2 +++ b/client.go Sat Mar 07 23:06:52 2015 -0500 1.3 @@ -37,6 +37,8 @@ 1.4 // ErrClientAlreadyExists is returned when a Client is added to a clientStore, but another Client with 1.5 // the same ID already exists in the clientStore. 1.6 ErrClientAlreadyExists = errors.New("client already exists in clientStore") 1.7 + // ErrEndpointNotFound is returned when an Endpoint is requested but not found in a clientSTore. 1.8 + ErrEndpointNotFound = errors.New("endpoint not found in clientStore") 1.9 1.10 // ErrEmptyChange is returned when a Change has all its properties set to nil. 1.11 ErrEmptyChange = errors.New("change must have at least one property set") 1.12 @@ -258,6 +260,7 @@ 1.13 1.14 addEndpoints(client uuid.ID, endpoint []Endpoint) error 1.15 removeEndpoint(client, endpoint uuid.ID) error 1.16 + getEndpoint(client, endpoint uuid.ID) (Endpoint, error) 1.17 checkEndpoint(client uuid.ID, endpoint string) (bool, error) 1.18 listEndpoints(client uuid.ID, num, offset int) ([]Endpoint, error) 1.19 countEndpoints(client uuid.ID) (int64, error) 1.20 @@ -344,6 +347,17 @@ 1.21 return nil 1.22 } 1.23 1.24 +func (m *memstore) getEndpoint(client, endpoint uuid.ID) (Endpoint, error) { 1.25 + m.endpointLock.Lock() 1.26 + defer m.endpointLock.Unlock() 1.27 + for _, item := range m.endpoints[client.String()] { 1.28 + if item.ID.Equal(endpoint) { 1.29 + return item, nil 1.30 + } 1.31 + } 1.32 + return Endpoint{}, ErrEndpointNotFound 1.33 +} 1.34 + 1.35 func (m *memstore) removeEndpoint(client, endpoint uuid.ID) error { 1.36 m.endpointLock.Lock() 1.37 defer m.endpointLock.Unlock() 1.38 @@ -763,7 +777,7 @@ 1.39 } 1.40 return 1.41 } 1.42 - client, err = c.GetClient(id) 1.43 + client, err := c.GetClient(id) 1.44 if err != nil { 1.45 if err == ErrClientNotFound { 1.46 errors = append(errors, requestError{Slug: requestErrNotFound, Param: "id"}) 1.47 @@ -869,6 +883,87 @@ 1.48 encode(w, r, http.StatusOK, resp) 1.49 } 1.50 1.51 +func RemoveEndpointHandler(w http.ResponseWriter, r *http.Request, c Context) { 1.52 + errors := []requestError{} 1.53 + vars := mux.Vars(r) 1.54 + if vars["client_id"] == "" { 1.55 + errors = append(errors, requestError{Slug: requestErrMissing, Param: "client_id"}) 1.56 + encode(w, r, http.StatusBadRequest, response{Errors: errors}) 1.57 + return 1.58 + } 1.59 + clientID, err := uuid.Parse(vars["client_id"]) 1.60 + if err != nil { 1.61 + errors = append(errors, requestError{Slug: requestErrInvalidFormat, Param: "client_id"}) 1.62 + encode(w, r, http.StatusBadRequest, response{Errors: errors}) 1.63 + return 1.64 + } 1.65 + if vars["id"] == "" { 1.66 + errors = append(errors, requestError{Slug: requestErrMissing, Param: "id"}) 1.67 + encode(w, r, http.StatusBadRequest, response{Errors: errors}) 1.68 + return 1.69 + } 1.70 + id, err := uuid.Parse(vars["id"]) 1.71 + if err != nil { 1.72 + errors = append(errors, requestError{Slug: requestErrInvalidFormat, Param: "id"}) 1.73 + encode(w, r, http.StatusBadRequest, response{Errors: errors}) 1.74 + return 1.75 + } 1.76 + username, password, ok := r.BasicAuth() 1.77 + if !ok { 1.78 + errors = append(errors, requestError{Slug: requestErrAccessDenied}) 1.79 + encode(w, r, http.StatusUnauthorized, response{Errors: errors}) 1.80 + return 1.81 + } 1.82 + profile, err := authenticate(username, password, c) 1.83 + if err != nil { 1.84 + if isAuthError(err) { 1.85 + errors = append(errors, requestError{Slug: requestErrAccessDenied}) 1.86 + encode(w, r, http.StatusUnauthorized, response{Errors: errors}) 1.87 + } else { 1.88 + errors = append(errors, requestError{Slug: requestErrActOfGod}) 1.89 + encode(w, r, http.StatusInternalServerError, response{Errors: errors}) 1.90 + } 1.91 + return 1.92 + } 1.93 + client, err := c.GetClient(clientID) 1.94 + if err != nil { 1.95 + if err == ErrClientNotFound { 1.96 + errors = append(errors, requestError{Slug: requestErrNotFound, Param: "client_id"}) 1.97 + encode(w, r, http.StatusBadRequest, response{Errors: errors}) 1.98 + return 1.99 + } 1.100 + errors = append(errors, requestError{Slug: requestErrActOfGod}) 1.101 + encode(w, r, http.StatusInternalServerError, response{Errors: errors}) 1.102 + return 1.103 + } 1.104 + if !client.OwnerID.Equal(profile.ID) { 1.105 + errors = append(errors, requestError{Slug: requestErrAccessDenied}) 1.106 + encode(w, r, http.StatusUnauthorized, response{Errors: errors}) 1.107 + return 1.108 + } 1.109 + endpoint, err := c.GetEndpoint(clientID, id) 1.110 + if err != nil { 1.111 + if err == ErrEndpointNotFound { 1.112 + errors = append(errors, requestError{Slug: requestErrNotFound, Param: "id"}) 1.113 + encode(w, r, http.StatusBadRequest, response{Errors: errors}) 1.114 + return 1.115 + } 1.116 + errors = append(errors, requestError{Slug: requestErrActOfGod}) 1.117 + encode(w, r, http.StatusInternalServerError, response{Errors: errors}) 1.118 + return 1.119 + } 1.120 + err = c.RemoveEndpoint(clientID, id) 1.121 + if err != nil { 1.122 + encode(w, r, http.StatusInternalServerError, actOfGodResponse) 1.123 + return 1.124 + } 1.125 + resp := response{ 1.126 + Errors: errors, 1.127 + Endpoints: []Endpoint{endpoint}, 1.128 + } 1.129 + encode(w, r, http.StatusCreated, resp) 1.130 +} 1.131 + 1.132 func clientCredentialsValidate(w http.ResponseWriter, r *http.Request, context Context) (scopes []string, profileID uuid.ID, valid bool) { 1.133 scopes = strings.Split(r.PostFormValue("scope"), " ") 1.134 valid = true
2.1 --- a/context.go Sat Mar 07 20:45:34 2015 -0500 2.2 +++ b/context.go Sat Mar 07 23:06:52 2015 -0500 2.3 @@ -126,6 +126,15 @@ 2.4 return c.clients.addEndpoints(client, endpoints) 2.5 } 2.6 2.7 +// GetEndpoint retrieves the Endpoint with the specified ID from the clientStore associated 2.8 +// with the Context, if and only if it belongs to the Client with the specified ID. 2.9 +func (c Context) GetEndpoint(client, endpoint uuid.ID) (Endpoint, error) { 2.10 + if c.clients == nil { 2.11 + return Endpoint{}, ErrNoClientStore 2.12 + } 2.13 + return c.clients.getEndpoint(client, endpoint) 2.14 +} 2.15 + 2.16 // RemoveEndpoint deletes the Endpoint with the specified ID from the clientStore associated 2.17 // with the Context, and disassociates the Endpoint from the specified Client. 2.18 func (c Context) RemoveEndpoint(client, endpoint uuid.ID) error {