Skip to content

Commit

Permalink
Merge pull request #102 from imjaroiswebdev/enforce-existent-contact
Browse files Browse the repository at this point in the history
Enforce update when contact method already exists in configuration
  • Loading branch information
imjaroiswebdev authored Dec 6, 2022
2 parents 0dcec1f + 2c89c4e commit 2a3d8ee
Show file tree
Hide file tree
Showing 2 changed files with 107 additions and 5 deletions.
58 changes: 53 additions & 5 deletions pagerduty/user.go
Original file line number Diff line number Diff line change
Expand Up @@ -333,10 +333,10 @@ func (s *UserService) CreateContactMethod(userID string, contactMethod *ContactM

resp, err := s.client.newRequestDo("POST", u, nil, &ContactMethodPayload{ContactMethod: contactMethod}, &v)

return s.processContactMethod(userID, v, contactMethod, resp, err)
return s.processCreateContactMethodResponse(userID, v, contactMethod, resp, err)
}

func (s *UserService) processContactMethod(userID string, v *ContactMethodPayload, contactMethod *ContactMethod, resp *Response, err error) (*ContactMethod, *Response, error) {
func (s *UserService) processCreateContactMethodResponse(userID string, v *ContactMethodPayload, contactMethod *ContactMethod, resp *Response, err error) (*ContactMethod, *Response, error) {
if err != nil {
if e, ok := err.(*Error); !ok || strings.Compare(fmt.Sprintf("%v", e.Errors), "[User Contact method must be unique]") != 0 {
return nil, nil, err
Expand All @@ -358,6 +358,46 @@ func (s *UserService) processContactMethod(userID string, v *ContactMethodPayloa
return v.ContactMethod, resp, nil
}

func (s *UserService) processUpdateContactMethodResponse(userID, contactMethodId string, v *ContactMethodPayload, contactMethod *ContactMethod, resp *Response, err error) (*ContactMethod, *Response, error) {
if err != nil {
e, ok := err.(*Error)
isUniqueContactError := ok && strings.Compare(fmt.Sprintf("%v", e.Errors), "[User Contact method must be unique]") == 0
if !ok || !isUniqueContactError {
return nil, nil, err
}
sContact, sResp, sErr := s.findExistingContactMethod(userID, contactMethod)
if sErr != nil {
return nil, nil, sErr
}

if isUniqueContactError {
_, sErr = s.DeleteContactMethod(userID, sContact.ID)
if sErr != nil {
return nil, nil, sErr
}

sResp, sErr = s.updateContactMethodCall(userID, contactMethodId, contactMethod, v)
if sErr != nil {
return nil, nil, sErr
}

sContact, sResp, sErr = s.findExistingContactMethod(userID, contactMethod)
if sErr != nil {
return nil, nil, sErr
}
}
v.ContactMethod = sContact
resp = sResp
}

if err = cachePutContactMethod(v.ContactMethod); err != nil {
log.Printf("===== Error adding contact method %q to cache: %q", v.ContactMethod.ID, err)
} else {
log.Printf("===== Added contact method %q to cache", v.ContactMethod.ID)
}
return v.ContactMethod, resp, nil
}

func (s *UserService) findExistingContactMethod(userID string, contactMethod *ContactMethod) (*ContactMethod, *Response, error) {
lResp, _, lErr := s.ListContactMethods(userID)
if lErr != nil {
Expand Down Expand Up @@ -401,11 +441,19 @@ func (s *UserService) GetContactMethod(userID string, contactMethodID string) (*

// UpdateContactMethod updates a contact method for a user.
func (s *UserService) UpdateContactMethod(userID, contactMethodID string, contactMethod *ContactMethod) (*ContactMethod, *Response, error) {
u := fmt.Sprintf("/users/%s/contact_methods/%s", userID, contactMethodID)
// u := fmt.Sprintf("/users/%s/contact_methods/%s", userID, contactMethodID)
v := new(ContactMethodPayload)

resp, err := s.client.newRequestDo("PUT", u, nil, &ContactMethodPayload{ContactMethod: contactMethod}, &v)
return s.processContactMethod(userID, v, contactMethod, resp, err)
// resp, err := s.client.newRequestDo("PUT", u, nil, &ContactMethodPayload{ContactMethod: contactMethod}, &v)
resp, err := s.updateContactMethodCall(userID, contactMethodID, contactMethod, v)

return s.processUpdateContactMethodResponse(userID, contactMethodID, v, contactMethod, resp, err)
}

func (s *UserService) updateContactMethodCall(userID, contactMethodID string, contactMethod *ContactMethod, v interface{}) (*Response, error) {
u := fmt.Sprintf("/users/%s/contact_methods/%s", userID, contactMethodID)

return s.client.newRequestDo("PUT", u, nil, &ContactMethodPayload{ContactMethod: contactMethod}, &v)
}

// DeleteContactMethod deletes a contact method for a user.
Expand Down
54 changes: 54 additions & 0 deletions pagerduty/user_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -289,6 +289,60 @@ func TestUsersUpdateContactMethod(t *testing.T) {
}
}

func TestUsersUpdateExistentContactMethod(t *testing.T) {
setup()
defer teardown()

input := &ContactMethod{Address: "foo@bar.com", Type: "email_contact_method"}
// Counter to ensure that first call to PUT method returns unique contact
// error, but not the following calls.
var putReqCount int

mux.HandleFunc("/users/1/contact_methods/1", func(w http.ResponseWriter, r *http.Request) {
if r.Method == "PUT" {
v := new(ContactMethodPayload)
json.NewDecoder(r.Body).Decode(v)
if !reflect.DeepEqual(v.ContactMethod, input) {
t.Errorf("Request body = %+v, want %+v", v, input)
}
if putReqCount == 0 {
w.WriteHeader(http.StatusBadRequest)
w.Write([]byte(`{"error":{"errors":["User Contact method must be unique"],"code":2001,"message":"Invalid Input Provided"}}`))
putReqCount++
} else {
w.Write([]byte(`{"contact_method": { "address": "foo@bar.com", "id": "1", "type": "email_contact_method", "self":"api/users/1/contact_methods/1" }}`))
}
} else if r.Method == "DELETE" {
w.WriteHeader(http.StatusNoContent)
} else if r.Method == "GET" {
w.Write([]byte(`{"contact_method": { "address": "foo@bar.com", "id": "1", "type": "email_contact_method", "self":"api/users/1/contact_methods/1" }}`))
} else {
t.Errorf("Request method: %v is neither PUT or GET", r.Method)
}
})

mux.HandleFunc("/users/1/contact_methods", func(w http.ResponseWriter, r *http.Request) {
testMethod(t, r, "GET")
w.Write([]byte(`{"contact_methods": [{ "address": "foo@bar.com", "id": "1", "type": "email_contact_method", "self":"api/users/1/contact_methods/1" }] }`))
})

resp, _, err := client.Users.UpdateContactMethod("1", "1", input)
if err != nil {
t.Fatal(err)
}

want := &ContactMethod{
ID: "1",
Type: "email_contact_method",
Address: "foo@bar.com",
Self: "api/users/1/contact_methods/1",
}

if !reflect.DeepEqual(resp, want) {
t.Errorf("returned %#v; want %#v", resp, want)
}
}

func TestUsersDeleteContactMethod(t *testing.T) {
setup()
defer teardown()
Expand Down

0 comments on commit 2a3d8ee

Please sign in to comment.