-
-
Notifications
You must be signed in to change notification settings - Fork 471
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
fix: removing the use of username field in searching for users (#297)
- Loading branch information
1 parent
146229d
commit f50cb07
Showing
4 changed files
with
43 additions
and
55 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
|
@@ -1598,15 +1598,14 @@ func TestIssueService_DeprecatedGetWatchers(t *testing.T) { | |
testMethod(t, r, "GET") | ||
testRequestURL(t, r, "/rest/api/2/issue/10002/watchers") | ||
|
||
fmt.Fprint(w, `{"self":"http://www.example.com/jira/rest/api/2/issue/EX-1/watchers","isWatching":false,"watchCount":1,"watchers":[{"self":"http://www.example.com/jira/rest/api/2/user?username=fred","name":"fred","displayName":"Fred F. User","active":false}]}`) | ||
fmt.Fprint(w, `{"self":"http://www.example.com/jira/rest/api/2/issue/EX-1/watchers","isWatching":false,"watchCount":1,"watchers":[{"self":"http://www.example.com/jira/rest/api/2/user?accountId=000000000000000000000000", "accountId": "000000000000000000000000", "displayName":"Fred F. User","active":false}]}`) | ||
}) | ||
|
||
testMux.HandleFunc("/rest/api/2/user", func(w http.ResponseWriter, r *http.Request) { | ||
testMethod(t, r, "GET") | ||
testRequestURL(t, r, "/rest/api/2/user?username=fred") | ||
testRequestURL(t, r, "/rest/api/2/user?accountId=000000000000000000000000") | ||
|
||
fmt.Fprint(w, `{"self":"http://www.example.com/jira/rest/api/2/user?username=fred","key":"fred", | ||
"name":"fred","emailAddress":"[email protected]","avatarUrls":{"48x48":"http://www.example.com/jira/secure/useravatar?size=large&ownerId=fred", | ||
fmt.Fprint(w, `{"self":"http://www.example.com/jira/rest/api/2/user?accountId=000000000000000000000000", "accountId": "000000000000000000000000", "key": "", "name": "", "emailAddress":"[email protected]","avatarUrls":{"48x48":"http://www.example.com/jira/secure/useravatar?size=large&ownerId=fred", | ||
"24x24":"http://www.example.com/jira/secure/useravatar?size=small&ownerId=fred","16x16":"http://www.example.com/jira/secure/useravatar?size=xsmall&ownerId=fred", | ||
"32x32":"http://www.example.com/jira/secure/useravatar?size=medium&ownerId=fred"},"displayName":"Fred F. User","active":true,"timeZone":"Australia/Sydney","groups":{"size":3,"items":[ | ||
{"name":"jira-user","self":"http://www.example.com/jira/rest/api/2/group?groupname=jira-user"},{"name":"jira-admin", | ||
|
@@ -1627,8 +1626,8 @@ func TestIssueService_DeprecatedGetWatchers(t *testing.T) { | |
t.Errorf("Expected 1 watcher, got: %d", len(*watchers)) | ||
return | ||
} | ||
if (*watchers)[0].Name != "fred" { | ||
t.Error("Expected watcher name fred") | ||
if (*watchers)[0].AccountID != "000000000000000000000000" { | ||
t.Error("Expected accountId 000000000000000000000000") | ||
} | ||
} | ||
|
||
|
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
|
@@ -9,18 +9,16 @@ import ( | |
|
||
// UserService handles users for the Jira instance / API. | ||
// | ||
// Jira API docs: https://docs.atlassian.com/jira/REST/cloud/#api/2/user | ||
// Jira API docs: https://developer.atlassian.com/cloud/jira/platform/rest/v2/#api-group-Users | ||
type UserService struct { | ||
client *Client | ||
} | ||
|
||
// User represents a Jira user. | ||
type User struct { | ||
Self string `json:"self,omitempty" structs:"self,omitempty"` | ||
AccountID string `json:"accountId,omitempty" structs:"accountId,omitempty"` | ||
AccountType string `json:"accountType,omitempty" structs:"accountType,omitempty"` | ||
// TODO: name & key are deprecated, see: | ||
// https://developer.atlassian.com/cloud/jira/platform/api-changes-for-user-privacy-announcement/ | ||
Self string `json:"self,omitempty" structs:"self,omitempty"` | ||
AccountID string `json:"accountId,omitempty" structs:"accountId,omitempty"` | ||
AccountType string `json:"accountType,omitempty" structs:"accountType,omitempty"` | ||
Name string `json:"name,omitempty" structs:"name,omitempty"` | ||
Key string `json:"key,omitempty" structs:"key,omitempty"` | ||
Password string `json:"-"` | ||
|
@@ -48,15 +46,11 @@ type userSearch []userSearchParam | |
|
||
type userSearchF func(userSearch) userSearch | ||
|
||
// GetWithContext gets user info from Jira | ||
// GetWithContext gets user info from Jira using its Account Id | ||
// | ||
// Jira API docs: https://docs.atlassian.com/jira/REST/cloud/#api/2/user-getUser | ||
// | ||
// /!\ Deprecation notice: https://developer.atlassian.com/cloud/jira/platform/deprecation-notice-user-privacy-api-migration-guide/ | ||
// By 29 April 2019, we will remove personal data from the API that is used to identify users, | ||
// such as username and userKey, and instead use the Atlassian account ID (accountId). | ||
func (s *UserService) GetWithContext(ctx context.Context, username string) (*User, *Response, error) { | ||
apiEndpoint := fmt.Sprintf("/rest/api/2/user?username=%s", username) | ||
// Jira API docs: https://developer.atlassian.com/cloud/jira/platform/rest/v2/#api-rest-api-2-user-get | ||
func (s *UserService) GetWithContext(ctx context.Context, accountId string) (*User, *Response, error) { | ||
apiEndpoint := fmt.Sprintf("/rest/api/2/user?accountId=%s", accountId) | ||
req, err := s.client.NewRequestWithContext(ctx, "GET", apiEndpoint, nil) | ||
if err != nil { | ||
return nil, nil, err | ||
|
@@ -71,12 +65,13 @@ func (s *UserService) GetWithContext(ctx context.Context, username string) (*Use | |
} | ||
|
||
// Get wraps GetWithContext using the background context. | ||
func (s *UserService) Get(username string) (*User, *Response, error) { | ||
return s.GetWithContext(context.Background(), username) | ||
func (s *UserService) Get(accountId string) (*User, *Response, error) { | ||
return s.GetWithContext(context.Background(), accountId) | ||
} | ||
|
||
// GetByAccountIDWithContext gets user info from Jira | ||
// | ||
// Searching by another parameter that is not accountId is deprecated, | ||
// but this method is kept for backwards compatibility | ||
// Jira API docs: https://docs.atlassian.com/jira/REST/cloud/#api/2/user-getUser | ||
func (s *UserService) GetByAccountIDWithContext(ctx context.Context, accountID string) (*User, *Response, error) { | ||
apiEndpoint := fmt.Sprintf("/rest/api/2/user?accountId=%s", accountID) | ||
|
@@ -136,9 +131,9 @@ func (s *UserService) Create(user *User) (*User, *Response, error) { | |
// DeleteWithContext deletes an user from Jira. | ||
// Returns http.StatusNoContent on success. | ||
// | ||
// Jira API docs: https://developer.atlassian.com/cloud/jira/platform/rest/#api-api-2-user-delete | ||
func (s *UserService) DeleteWithContext(ctx context.Context, username string) (*Response, error) { | ||
apiEndpoint := fmt.Sprintf("/rest/api/2/user?username=%s", username) | ||
// Jira API docs: https://developer.atlassian.com/cloud/jira/platform/rest/v2/#api-rest-api-2-user-delete | ||
func (s *UserService) DeleteWithContext(ctx context.Context, accountId string) (*Response, error) { | ||
apiEndpoint := fmt.Sprintf("/rest/api/2/user?accountId=%s", accountId) | ||
req, err := s.client.NewRequestWithContext(ctx, "DELETE", apiEndpoint, nil) | ||
if err != nil { | ||
return nil, err | ||
|
@@ -152,15 +147,15 @@ func (s *UserService) DeleteWithContext(ctx context.Context, username string) (* | |
} | ||
|
||
// Delete wraps DeleteWithContext using the background context. | ||
func (s *UserService) Delete(username string) (*Response, error) { | ||
return s.DeleteWithContext(context.Background(), username) | ||
func (s *UserService) Delete(accountId string) (*Response, error) { | ||
return s.DeleteWithContext(context.Background(), accountId) | ||
} | ||
|
||
// GetGroupsWithContext returns the groups which the user belongs to | ||
// | ||
// Jira API docs: https://docs.atlassian.com/jira/REST/cloud/#api/2/user-getUserGroups | ||
func (s *UserService) GetGroupsWithContext(ctx context.Context, username string) (*[]UserGroup, *Response, error) { | ||
apiEndpoint := fmt.Sprintf("/rest/api/2/user/groups?username=%s", username) | ||
// Jira API docs: https://developer.atlassian.com/cloud/jira/platform/rest/v2/#api-rest-api-2-user-groups-get | ||
func (s *UserService) GetGroupsWithContext(ctx context.Context, accountId string) (*[]UserGroup, *Response, error) { | ||
apiEndpoint := fmt.Sprintf("/rest/api/2/user/groups?accountId=%s", accountId) | ||
req, err := s.client.NewRequestWithContext(ctx, "GET", apiEndpoint, nil) | ||
if err != nil { | ||
return nil, nil, err | ||
|
@@ -175,13 +170,13 @@ func (s *UserService) GetGroupsWithContext(ctx context.Context, username string) | |
} | ||
|
||
// GetGroups wraps GetGroupsWithContext using the background context. | ||
func (s *UserService) GetGroups(username string) (*[]UserGroup, *Response, error) { | ||
return s.GetGroupsWithContext(context.Background(), username) | ||
func (s *UserService) GetGroups(accountId string) (*[]UserGroup, *Response, error) { | ||
return s.GetGroupsWithContext(context.Background(), accountId) | ||
} | ||
|
||
// GetSelfWithContext information about the current logged-in user | ||
// | ||
// Jira API docs: https://developer.atlassian.com/cloud/jira/platform/rest/#api-api-2-myself-get | ||
// Jira API docs: https://developer.atlassian.com/cloud/jira/platform/rest/v2/#api-rest-api-2-myself-get | ||
func (s *UserService) GetSelfWithContext(ctx context.Context) (*User, *Response, error) { | ||
const apiEndpoint = "rest/api/2/myself" | ||
req, err := s.client.NewRequestWithContext(ctx, "GET", apiEndpoint, nil) | ||
|
@@ -234,13 +229,13 @@ func WithInactive(inactive bool) userSearchF { | |
} | ||
|
||
// FindWithContext searches for user info from Jira: | ||
// It can find users by email, username or name | ||
// It can find users by email or display name using the query parameter | ||
// | ||
// Jira API docs: https://docs.atlassian.com/jira/REST/cloud/#api/2/user-findUsers | ||
// Jira API docs: https://developer.atlassian.com/cloud/jira/platform/rest/v2/#api-rest-api-2-user-search-get | ||
func (s *UserService) FindWithContext(ctx context.Context, property string, tweaks ...userSearchF) ([]User, *Response, error) { | ||
search := []userSearchParam{ | ||
{ | ||
name: "username", | ||
name: "query", | ||
This comment has been minimized.
Sorry, something went wrong.
This comment has been minimized.
Sorry, something went wrong.
cynthiabaran
Author
Contributor
|
||
value: property, | ||
}, | ||
} | ||
|
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
|
@@ -11,7 +11,7 @@ func TestUserService_Get_Success(t *testing.T) { | |
defer teardown() | ||
testMux.HandleFunc("/rest/api/2/user", func(w http.ResponseWriter, r *http.Request) { | ||
testMethod(t, r, "GET") | ||
testRequestURL(t, r, "/rest/api/2/user?username=fred") | ||
testRequestURL(t, r, "/rest/api/2/user?accountId=000000000000000000000000") | ||
|
||
fmt.Fprint(w, `{"self":"http://www.example.com/jira/rest/api/2/user?username=fred","key":"fred", | ||
"name":"fred","emailAddress":"[email protected]","avatarUrls":{"48x48":"http://www.example.com/jira/secure/useravatar?size=large&ownerId=fred", | ||
|
@@ -22,7 +22,7 @@ func TestUserService_Get_Success(t *testing.T) { | |
}]},"applicationRoles":{"size":1,"items":[]},"expand":"groups,applicationRoles"}`) | ||
}) | ||
|
||
if user, _, err := testClient.User.Get("fred"); err != nil { | ||
if user, _, err := testClient.User.Get("000000000000000000000000"); err != nil { | ||
t.Errorf("Error given: %s", err) | ||
} else if user == nil { | ||
t.Error("Expected user. User is nil") | ||
|
@@ -84,12 +84,12 @@ func TestUserService_Delete(t *testing.T) { | |
defer teardown() | ||
testMux.HandleFunc("/rest/api/2/user", func(w http.ResponseWriter, r *http.Request) { | ||
testMethod(t, r, "DELETE") | ||
testRequestURL(t, r, "/rest/api/2/user?username=fred") | ||
testRequestURL(t, r, "/rest/api/2/user?accountId=000000000000000000000000") | ||
|
||
w.WriteHeader(http.StatusNoContent) | ||
}) | ||
|
||
resp, err := testClient.User.Delete("fred") | ||
resp, err := testClient.User.Delete("000000000000000000000000") | ||
if err != nil { | ||
t.Errorf("Error given: %s", err) | ||
} | ||
|
@@ -104,13 +104,13 @@ func TestUserService_GetGroups(t *testing.T) { | |
defer teardown() | ||
testMux.HandleFunc("/rest/api/2/user/groups", func(w http.ResponseWriter, r *http.Request) { | ||
testMethod(t, r, "GET") | ||
testRequestURL(t, r, "/rest/api/2/user/groups?username=fred") | ||
testRequestURL(t, r, "/rest/api/2/user/groups?accountId=000000000000000000000000") | ||
|
||
w.WriteHeader(http.StatusCreated) | ||
fmt.Fprint(w, `[{"name":"jira-software-users","self":"http://www.example.com/jira/rest/api/2/user?username=fred"}]`) | ||
fmt.Fprint(w, `[{"name":"jira-software-users","self":"http://www.example.com/jira/rest/api/2/user?accountId=000000000000000000000000"}]`) | ||
}) | ||
|
||
if groups, _, err := testClient.User.GetGroups("fred"); err != nil { | ||
if groups, _, err := testClient.User.GetGroups("000000000000000000000000"); err != nil { | ||
t.Errorf("Error given: %s", err) | ||
} else if groups == nil { | ||
t.Error("Expected user groups. []UserGroup is nil") | ||
|
@@ -125,7 +125,7 @@ func TestUserService_GetSelf(t *testing.T) { | |
testRequestURL(t, r, "/rest/api/2/myself") | ||
|
||
w.WriteHeader(http.StatusCreated) | ||
fmt.Fprint(w, `{"self":"http://www.example.com/jira/rest/api/2/user?username=fred","key":"fred", | ||
fmt.Fprint(w, `{"self":"http://www.example.com/jira/rest/api/2/user?accountId=000000000000000000000000","key":"fred", | ||
"name":"fred","emailAddress":"[email protected]","avatarUrls":{"48x48":"http://www.example.com/jira/secure/useravatar?size=large&ownerId=fred", | ||
"24x24":"http://www.example.com/jira/secure/useravatar?size=small&ownerId=fred","16x16":"http://www.example.com/jira/secure/useravatar?size=xsmall&ownerId=fred", | ||
"32x32":"http://www.example.com/jira/secure/useravatar?size=medium&ownerId=fred"},"displayName":"Fred F. User","active":true,"timeZone":"Australia/Sydney","groups":{"size":3,"items":[ | ||
|
@@ -150,9 +150,9 @@ func TestUserService_Find_Success(t *testing.T) { | |
defer teardown() | ||
testMux.HandleFunc("/rest/api/2/user/search", func(w http.ResponseWriter, r *http.Request) { | ||
testMethod(t, r, "GET") | ||
testRequestURL(t, r, "/rest/api/2/user/search?username[email protected]") | ||
testRequestURL(t, r, "/rest/api/2/user/search?query[email protected]") | ||
|
||
fmt.Fprint(w, `[{"self":"http://www.example.com/jira/rest/api/2/user?username=fred","key":"fred", | ||
fmt.Fprint(w, `[{"self":"http://www.example.com/jira/rest/api/2/user?accountId=000000000000000000000000","key":"fred", | ||
"name":"fred","emailAddress":"[email protected]","avatarUrls":{"48x48":"http://www.example.com/jira/secure/useravatar?size=large&ownerId=fred", | ||
"24x24":"http://www.example.com/jira/secure/useravatar?size=small&ownerId=fred","16x16":"http://www.example.com/jira/secure/useravatar?size=xsmall&ownerId=fred", | ||
"32x32":"http://www.example.com/jira/secure/useravatar?size=medium&ownerId=fred"},"displayName":"Fred F. User","active":true,"timeZone":"Australia/Sydney","groups":{"size":3,"items":[ | ||
|
@@ -173,9 +173,9 @@ func TestUserService_Find_SuccessParams(t *testing.T) { | |
defer teardown() | ||
testMux.HandleFunc("/rest/api/2/user/search", func(w http.ResponseWriter, r *http.Request) { | ||
testMethod(t, r, "GET") | ||
testRequestURL(t, r, "/rest/api/2/user/search?username[email protected]&startAt=100&maxResults=1000") | ||
testRequestURL(t, r, "/rest/api/2/user/search?query[email protected]&startAt=100&maxResults=1000") | ||
|
||
fmt.Fprint(w, `[{"self":"http://www.example.com/jira/rest/api/2/user?username=fred","key":"fred", | ||
fmt.Fprint(w, `[{"self":"http://www.example.com/jira/rest/api/2/user?query=fred","key":"fred", | ||
"name":"fred","emailAddress":"[email protected]","avatarUrls":{"48x48":"http://www.example.com/jira/secure/useravatar?size=large&ownerId=fred", | ||
"24x24":"http://www.example.com/jira/secure/useravatar?size=small&ownerId=fred","16x16":"http://www.example.com/jira/secure/useravatar?size=xsmall&ownerId=fred", | ||
"32x32":"http://www.example.com/jira/secure/useravatar?size=medium&ownerId=fred"},"displayName":"Fred F. User","active":true,"timeZone":"Australia/Sydney","groups":{"size":3,"items":[ | ||
|
Hello @andygrunwald @cynthiabaran,
this change causing an issue on v2 api.
(Response) 400 Bad Request - Body: {"errorMessages":["The username query parameter was not provided"],"errors":{}}
It seems to perform this type of search "username" param is still required(you can put as value jira user name or email, both works fine), is there any chance to have this updated quickly or maybe have an option to specify property name to be used in search query?
If i use param "query" and use as value user name or email i get error saying that username param is to be provided.
Thanks a lot in advance!
Ihor