diff --git a/cloud/group.go b/cloud/group.go
index 38736fae..1b589ae7 100644
--- a/cloud/group.go
+++ b/cloud/group.go
@@ -21,8 +21,19 @@ type groupMembersResult struct {
Members []GroupMember `json:"values"`
}
+// Response body of https://developer.atlassian.com/cloud/jira/platform/rest/v2/api-group-groups/#api-rest-api-2-group-member-get
+type getGroupMembersResult struct {
+ IsLast bool `json:"isLast"`
+ MaxResults int `json:"maxResults"`
+ NextPage string `json:"nextPage"`
+ Total int `json:"total"`
+ StartAt int `json:"startAt"`
+ Values []GroupMember `json:"values"`
+}
+
// Group represents a Jira group
type Group struct {
+ ID string `json:"groupId,omitempty" structs:"groupId,omitempty"`
Name string `json:"name,omitempty" structs:"name,omitempty"`
Self string `json:"self,omitempty" structs:"self,omitempty"`
Users GroupMembers `json:"users,omitempty" structs:"users,omitempty"`
@@ -58,6 +69,12 @@ type GroupSearchOptions struct {
IncludeInactiveUsers bool
}
+type Groups struct {
+ Groups []Group `json:"groups,omitempty"`
+ Header string `json:"header,omitempty"`
+ Total int `json:"total,omitempty"`
+}
+
// Get returns a paginated list of members of the specified group and its subgroups.
// Users in the page are ordered by user names.
// User of this resource is required to have sysadmin or admin permissions.
@@ -68,6 +85,7 @@ type GroupSearchOptions struct {
//
// TODO Double check this method if this works as expected, is using the latest API and the response is complete
// This double check effort is done for v2 - Remove this two lines if this is completed.
+// Deprecated: Use GetGroupMembers instead
func (s *GroupService) Get(ctx context.Context, name string, options *GroupSearchOptions) ([]GroupMember, *Response, error) {
var apiEndpoint string
if options == nil {
@@ -144,3 +162,120 @@ func (s *GroupService) RemoveUserByGroupName(ctx context.Context, groupName stri
return resp, nil
}
+
+// Sets case insensitive search
+func WithCaseInsensitive() searchF {
+ return func(s search) search {
+ s = append(s, searchParam{name: "caseInsensitive", value: "true"})
+ return s
+ }
+}
+
+// Sets query string for filtering group names.
+func WithGroupNameContains(contains string) searchF {
+ return func(s search) search {
+ s = append(s, searchParam{name: "query", value: contains})
+ return s
+ }
+}
+
+// Sets excluded group names.
+func WithExcludedGroupNames(excluded []string) searchF {
+ return func(s search) search {
+ for _, name := range excluded {
+ s = append(s, searchParam{name: "exclude", value: name})
+ }
+
+ return s
+ }
+}
+
+// Sets excluded group ids.
+func WithExcludedGroupsIds(excluded []string) searchF {
+ return func(s search) search {
+ for _, id := range excluded {
+ s = append(s, searchParam{name: "excludeId", value: id})
+ }
+
+ return s
+ }
+}
+
+// Search for the groups
+// It can search by groupId, accountId or userName
+// Apart from returning groups it also returns total number of groups
+//
+// Jira API docs: https://developer.atlassian.com/cloud/jira/platform/rest/v3/api-group-groups/#api-rest-api-3-groups-picker-get
+func (s *GroupService) Find(ctx context.Context, tweaks ...searchF) ([]Group, *Response, error) {
+ search := []searchParam{}
+ for _, f := range tweaks {
+ search = f(search)
+ }
+
+ apiEndpoint := "/rest/api/3/groups/picker"
+
+ queryString := ""
+ for _, param := range search {
+ queryString += fmt.Sprintf("%s=%s&", param.name, param.value)
+ }
+
+ if queryString != "" {
+ apiEndpoint += "?" + queryString
+ }
+
+ req, err := s.client.NewRequest(ctx, http.MethodGet, apiEndpoint, nil)
+ if err != nil {
+ return nil, nil, err
+ }
+
+ groups := Groups{}
+ resp, err := s.client.Do(req, &groups)
+ if err != nil {
+ return nil, resp, NewJiraError(resp, err)
+ }
+
+ return groups.Groups, resp, nil
+}
+
+func WithInactiveUsers() searchF {
+ return func(s search) search {
+ s = append(s, searchParam{name: "includeInactiveUsers", value: "true"})
+ return s
+ }
+}
+
+// Search for the group members
+// It can filter out inactive users
+// Apart from returning group members it also returns total number of group members
+//
+// Jira API docs: https://developer.atlassian.com/cloud/jira/platform/rest/v3/api-group-groups/#api-rest-api-3-group-member-get
+func (s *GroupService) GetGroupMembers(ctx context.Context, groupId string, tweaks ...searchF) ([]GroupMember, *Response, error) {
+ search := []searchParam{}
+ for _, f := range tweaks {
+ search = f(search)
+ }
+
+ apiEndpoint := fmt.Sprintf("/rest/api/3/group/member?groupId=%s", groupId)
+
+ queryString := ""
+ for _, param := range search {
+ queryString += fmt.Sprintf("%s=%s&", param.name, param.value)
+ }
+
+ if queryString != "" {
+ apiEndpoint += "&" + queryString
+ }
+
+ req, err := s.client.NewRequest(ctx, http.MethodGet, apiEndpoint, nil)
+ if err != nil {
+ return nil, nil, err
+ }
+
+ group := new(getGroupMembersResult)
+ resp, err := s.client.Do(req, group)
+ if err != nil {
+ return nil, resp, NewJiraError(resp, err)
+ }
+
+ return group.Values, resp, nil
+}
diff --git a/cloud/group_test.go b/cloud/group_test.go
index e37f79e5..690bafc7 100644
--- a/cloud/group_test.go
+++ b/cloud/group_test.go
@@ -95,3 +95,123 @@ func TestGroupService_Remove(t *testing.T) {
t.Errorf("Error given: %s", err)
}
}
+
+func TestGroupService_Find_Success(t *testing.T) {
+ setup()
+ defer teardown()
+ testMux.HandleFunc("/rest/api/3/groups/picker", func(w http.ResponseWriter, r *http.Request) {
+ testMethod(t, r, http.MethodGet)
+ testRequestURL(t, r, "/rest/api/3/groups/picker")
+
+ fmt.Fprint(w, `{"header": "Showing 2 of 2 matching groups",
+ "total": 2,
+ "groups": [{
+ "name": "jdog-developers",
+ "html": "jdog-developers",
+ "groupId": "276f955c-63d7-42c8-9520-92d01dca0625"
+ },
+ {
+ "name": "juvenal-bot",
+ "html": "juvenal-bot",
+ "groupId": "6e87dc72-4f1f-421f-9382-2fee8b652487"
+ }]}`)
+ })
+
+ if group, _, err := testClient.Group.Find(context.Background()); err != nil {
+ t.Errorf("Error given: %s", err)
+ } else if group == nil {
+ t.Error("Expected group. Group is nil")
+ } else if len(group) != 2 {
+ t.Errorf("Expected 2 groups. Group is %d", len(group))
+ }
+}
+
+func TestGroupService_Find_SuccessParams(t *testing.T) {
+ setup()
+ defer teardown()
+ testMux.HandleFunc("/rest/api/3/groups/picker", func(w http.ResponseWriter, r *http.Request) {
+ testMethod(t, r, http.MethodGet)
+ testRequestURL(t, r, "/rest/api/3/groups/picker?maxResults=2&caseInsensitive=true&excludeId=1&excludeId=2&exclude=test&query=test&accountId=123")
+
+ fmt.Fprint(w, `{"header": "Showing 2 of 2 matching groups",
+ "total": 2,
+ "groups": [{
+ "name": "jdog-developers",
+ "html": "jdog-developers",
+ "groupId": "276f955c-63d7-42c8-9520-92d01dca0625"
+ },
+ {
+ "name": "juvenal-bot",
+ "html": "juvenal-bot",
+ "groupId": "6e87dc72-4f1f-421f-9382-2fee8b652487"
+ }]}`)
+ })
+
+ if group, _, err := testClient.Group.Find(
+ context.Background(),
+ WithMaxResults(2),
+ WithCaseInsensitive(),
+ WithExcludedGroupsIds([]string{"1", "2"}),
+ WithExcludedGroupNames([]string{"test"}),
+ WithGroupNameContains("test"),
+ WithAccountId("123"),
+ ); err != nil {
+ t.Errorf("Error given: %s", err)
+ } else if group == nil {
+ t.Error("Expected group. Group is nil")
+ } else if len(group) != 2 {
+ t.Errorf("Expected 2 groups. Group is %d", len(group))
+ }
+}
+
+func TestGroupService_GetGroupMembers_Success(t *testing.T) {
+ setup()
+ defer teardown()
+ testMux.HandleFunc("/rest/api/3/group/member", func(w http.ResponseWriter, r *http.Request) {
+ testMethod(t, r, http.MethodGet)
+ testRequestURL(t, r, "/rest/api/3/group/member?groupId=1&startAt=0&maxResults=2&includeInactiveUsers=true")
+
+ fmt.Fprint(w, `{
+ "self": "https://your-domain.atlassian.net/rest/api/3/group/member?groupname=jira-administrators&includeInactiveUsers=false&startAt=2&maxResults=2",
+ "nextPage": "https://your-domain.atlassian.net/rest/api/3/group/member?groupname=jira-administrators&includeInactiveUsers=false&startAt=4&maxResults=2",
+ "maxResults": 2,
+ "startAt": 3,
+ "total": 5,
+ "isLast": false,
+ "values": [
+ {
+ "self": "https://your-domain.atlassian.net/rest/api/3/user?accountId=5b10a2844c20165700ede21g",
+ "name": "",
+ "key": "",
+ "accountId": "5b10a2844c20165700ede21g",
+ "emailAddress": "mia@example.com",
+ "avatarUrls": {},
+ "displayName": "Mia",
+ "active": true,
+ "timeZone": "Australia/Sydney",
+ "accountType": "atlassian"
+ },
+ {
+ "self": "https://your-domain.atlassian.net/rest/api/3/user?accountId=5b10a0effa615349cb016cd8",
+ "name": "",
+ "key": "",
+ "accountId": "5b10a0effa615349cb016cd8",
+ "emailAddress": "will@example.com",
+ "avatarUrls": {},
+ "displayName": "Will",
+ "active": false,
+ "timeZone": "Australia/Sydney",
+ "accountType": "atlassian"
+ }
+ ]
+ }`)
+ })
+
+ if members, _, err := testClient.Group.GetGroupMembers(context.Background(), "1", WithStartAt(0), WithMaxResults(2), WithInactiveUsers()); err != nil {
+ t.Errorf("Error given: %s", err)
+ } else if len(members) != 2 {
+ t.Errorf("Expected 2 members. Members is %d", len(members))
+ } else if members[0].AccountID != "5b10a2844c20165700ede21g" {
+ t.Errorf("Expected 5b10a2844c20165700ede21g. Members[0].AccountId is %s", members[0].AccountID)
+ }
+}
diff --git a/cloud/project.go b/cloud/project.go
index add12bf9..ecc7c4a9 100644
--- a/cloud/project.go
+++ b/cloud/project.go
@@ -26,6 +26,17 @@ type ProjectList []struct {
IssueTypes []IssueType `json:"issueTypes,omitempty" structs:"issueTypes,omitempty"`
}
+// Response body of https://developer.atlassian.com/cloud/jira/platform/rest/v2/api-group-projects/#api-rest-api-2-project-search-get
+type searchProjectsResponse struct {
+ Self string `json:"self,omitempty" structs:"self,omitempty"`
+ NextPage string `json:"nextPage,omitempty" structs:"nextPage,omitempty"`
+ MaxResults int `json:"maxResult,omitempty" structs:"maxResults,omitempty"`
+ StartAt int `json:"startAt,omitempty" structs:"startAt,omitempty"`
+ Total int `json:"total,omitempty" structs:"total,omitempty"`
+ IsLast bool `json:"isLast,omitempty" structs:"isLast,omitempty"`
+ Values []Project `json:"values,omitempty" structs:"values,omitempty"`
+}
+
// ProjectCategory represents a single project category
type ProjectCategory struct {
Self string `json:"self" structs:"self,omitempty"`
@@ -52,6 +63,7 @@ type Project struct {
Roles map[string]string `json:"roles,omitempty" structs:"roles,omitempty"`
AvatarUrls AvatarUrls `json:"avatarUrls,omitempty" structs:"avatarUrls,omitempty"`
ProjectCategory ProjectCategory `json:"projectCategory,omitempty" structs:"projectCategory,omitempty"`
+ IsPrivate bool `json:"isPrivate,omitempty" structs:"isPrivate,omitempty"`
}
// ProjectComponent represents a single component of a project
@@ -87,6 +99,7 @@ type PermissionScheme struct {
//
// TODO Double check this method if this works as expected, is using the latest API and the response is complete
// This double check effort is done for v2 - Remove this two lines if this is completed.
+// DEPRECATED: use Find instead
func (s *ProjectService) GetAll(ctx context.Context, options *GetQueryOptions) (*ProjectList, *Response, error) {
apiEndpoint := "rest/api/2/project"
req, err := s.client.NewRequest(ctx, http.MethodGet, apiEndpoint, nil)
@@ -161,3 +174,38 @@ func (s *ProjectService) GetPermissionScheme(ctx context.Context, projectID stri
return ps, resp, nil
}
+
+// Find searches for project paginated info from Jira
+//
+// Jira API docs: https://developer.atlassian.com/cloud/jira/platform/rest/v2/api-group-projects/#api-rest-api-2-project-search-get
+func (s *ProjectService) Find(ctx context.Context, tweaks ...searchF) ([]Project, *Response, error) {
+ apiEndpoint := "rest/api/2/project/search"
+
+ search := []searchParam{}
+ for _, f := range tweaks {
+ search = f(search)
+ }
+
+ queryString := ""
+ for _, param := range search {
+ queryString += fmt.Sprintf("%s=%s&", param.name, param.value)
+ }
+
+ if queryString != "" {
+ apiEndpoint += "?" + queryString
+ }
+
+ req, err := s.client.NewRequest(ctx, http.MethodGet, apiEndpoint, nil)
+ if err != nil {
+ return nil, nil, err
+ }
+
+ response := new(searchProjectsResponse)
+ resp, err := s.client.Do(req, response)
+ if err != nil {
+ jerr := NewJiraError(resp, err)
+ return nil, resp, jerr
+ }
+
+ return response.Values, resp, nil
+}
diff --git a/cloud/project_test.go b/cloud/project_test.go
index d3c877cf..121a9245 100644
--- a/cloud/project_test.go
+++ b/cloud/project_test.go
@@ -137,3 +137,80 @@ func TestProjectService_GetPermissionScheme_Success(t *testing.T) {
t.Errorf("Error given: %s", err)
}
}
+
+func TestProjectService_Find_Success(t *testing.T) {
+ setup()
+ defer teardown()
+ testapiEndpoint := "/rest/api/2/project/search"
+
+ testMux.HandleFunc(testapiEndpoint, func(w http.ResponseWriter, r *http.Request) {
+ testMethod(t, r, http.MethodGet)
+ testRequestURL(t, r, testapiEndpoint+"?startAt=0&maxResults=2")
+ fmt.Fprint(w, `{
+ "self": "https://your-domain.atlassian.net/rest/api/2/project/search?startAt=0&maxResults=2",
+ "nextPage": "https://your-domain.atlassian.net/rest/api/2/project/search?startAt=2&maxResults=2",
+ "maxResults": 2,
+ "startAt": 0,
+ "total": 7,
+ "isLast": false,
+ "values": [
+ {
+ "self": "https://your-domain.atlassian.net/rest/api/2/project/EX",
+ "id": "10000",
+ "key": "EX",
+ "name": "Example",
+ "avatarUrls": {
+ "48x48": "https://your-domain.atlassian.net/secure/projectavatar?size=large&pid=10000",
+ "24x24": "https://your-domain.atlassian.net/secure/projectavatar?size=small&pid=10000",
+ "16x16": "https://your-domain.atlassian.net/secure/projectavatar?size=xsmall&pid=10000",
+ "32x32": "https://your-domain.atlassian.net/secure/projectavatar?size=medium&pid=10000"
+ },
+ "projectCategory": {
+ "self": "https://your-domain.atlassian.net/rest/api/2/projectCategory/10000",
+ "id": "10000",
+ "name": "FIRST",
+ "description": "First Project Category"
+ },
+ "simplified": false,
+ "style": "classic",
+ "insight": {
+ "totalIssueCount": 100,
+ "lastIssueUpdateTime": "2023-10-27T00:46:39.889+0000"
+ }
+ },
+ {
+ "self": "https://your-domain.atlassian.net/rest/api/2/project/ABC",
+ "id": "10001",
+ "key": "ABC",
+ "name": "Alphabetical",
+ "avatarUrls": {
+ "48x48": "https://your-domain.atlassian.net/secure/projectavatar?size=large&pid=10001",
+ "24x24": "https://your-domain.atlassian.net/secure/projectavatar?size=small&pid=10001",
+ "16x16": "https://your-domain.atlassian.net/secure/projectavatar?size=xsmall&pid=10001",
+ "32x32": "https://your-domain.atlassian.net/secure/projectavatar?size=medium&pid=10001"
+ },
+ "projectCategory": {
+ "self": "https://your-domain.atlassian.net/rest/api/2/projectCategory/10000",
+ "id": "10000",
+ "name": "FIRST",
+ "description": "First Project Category"
+ },
+ "simplified": false,
+ "style": "classic",
+ "insight": {
+ "totalIssueCount": 100,
+ "lastIssueUpdateTime": "2023-10-27T00:46:39.889+0000"
+ }
+ }
+ ]
+ }`)
+ })
+
+ if projects, _, err := testClient.Project.Find(context.Background(), WithStartAt(0), WithMaxResults(2)); err != nil {
+ t.Errorf("Error given: %s", err)
+ } else if len(projects) != 2 {
+ t.Errorf("Expected 2 projects. Projects is %d", len(projects))
+ } else if projects[0].ID != "10000" {
+ t.Errorf("Expected 10000. Projects[0].ID is %s", projects[0].ID)
+ }
+}
diff --git a/cloud/role.go b/cloud/role.go
index 3fd18d83..6c4d020c 100644
--- a/cloud/role.go
+++ b/cloud/role.go
@@ -22,12 +22,13 @@ type Role struct {
// Actor represents a Jira actor
type Actor struct {
- ID int `json:"id" structs:"id"`
- DisplayName string `json:"displayName" structs:"displayName"`
- Type string `json:"type" structs:"type"`
- Name string `json:"name" structs:"name"`
- AvatarURL string `json:"avatarUrl" structs:"avatarUrl"`
- ActorUser *ActorUser `json:"actorUser" structs:"actoruser"`
+ ID int `json:"id" structs:"id"`
+ DisplayName string `json:"displayName" structs:"displayName"`
+ Type string `json:"type" structs:"type"`
+ Name string `json:"name" structs:"name"`
+ AvatarURL string `json:"avatarUrl" structs:"avatarUrl"`
+ ActorUser *ActorUser `json:"actorUser" structs:"actoruser"`
+ ActorGroup *ActorGroup `json:"actorGroup" structs:"actorGroup"`
}
// ActorUser contains the account id of the actor/user
@@ -35,6 +36,12 @@ type ActorUser struct {
AccountID string `json:"accountId" structs:"accountId"`
}
+type ActorGroup struct {
+ DisplayName string `json:"displayName" structs:"displayName"`
+ GroupID string `json:"groupId" structs:"groupId"`
+ Name string `json:"name" structs:"name"`
+}
+
// GetList returns a list of all available project roles
//
// Jira API docs: https://developer.atlassian.com/cloud/jira/platform/rest/v3/#api-api-3-role-get
@@ -80,3 +87,21 @@ func (s *RoleService) Get(ctx context.Context, roleID int) (*Role, *Response, er
return role, resp, err
}
+
+// Get role actors for project
+//
+// Jira API docs: https://developer.atlassian.com/cloud/jira/platform/rest/v3/api-group-project-roles/#api-rest-api-3-project-projectidorkey-role-id-get
+func (s *RoleService) GetRoleActorsForProject(ctx context.Context, projectID string, roleID int) ([]*Actor, *Response, error) {
+ apiEndpoint := fmt.Sprintf("rest/api/3/project/%s/role/%d", projectID, roleID)
+ req, err := s.client.NewRequest(ctx, http.MethodGet, apiEndpoint, nil)
+ if err != nil {
+ return nil, nil, err
+ }
+ role := new(Role)
+ resp, err := s.client.Do(req, role)
+ if err != nil {
+ jerr := NewJiraError(resp, err)
+ return nil, resp, jerr
+ }
+ return role.Actors, resp, err
+}
diff --git a/cloud/role_test.go b/cloud/role_test.go
index 20f7e8db..45baf84b 100644
--- a/cloud/role_test.go
+++ b/cloud/role_test.go
@@ -106,3 +106,32 @@ func TestRoleService_Get(t *testing.T) {
t.Errorf("Error given: %s", err)
}
}
+
+func TestRoleService_GetRoleActorsForProject(t *testing.T) {
+ setup()
+ defer teardown()
+ rawResponseBody, err := os.ReadFile("../testing/mock-data/role_actors.json")
+ if err != nil {
+ t.Error(err.Error())
+ }
+ testapiEndpoint := "/rest/api/3/project/10002/role/10006"
+ testMux.HandleFunc(testapiEndpoint, func(writer http.ResponseWriter, request *http.Request) {
+ testMethod(t, request, http.MethodGet)
+ testRequestURL(t, request, testapiEndpoint)
+ fmt.Fprint(writer, string(rawResponseBody))
+ })
+
+ actors, _, err := testClient.Role.GetRoleActorsForProject(context.Background(), "10002", 10006)
+ if err != nil {
+ t.Errorf("Error given: %s", err)
+ }
+ if len(actors) != 2 {
+ t.Errorf("Expected 2 actors, got %d", len(actors))
+ }
+ if actors[0].DisplayName != "jira-developers" {
+ t.Errorf("Expected jira-developers, got %s", actors[0].DisplayName)
+ }
+ if actors[1].DisplayName != "Mia Krystof" {
+ t.Errorf("Expected Mia Krystof, got %s", actors[1].DisplayName)
+ }
+}
diff --git a/cloud/searching.go b/cloud/searching.go
new file mode 100644
index 00000000..4d015c4f
--- /dev/null
+++ b/cloud/searching.go
@@ -0,0 +1,38 @@
+package cloud
+
+import "fmt"
+
+type (
+ searchParam struct {
+ name string
+ value string
+ }
+
+ search []searchParam
+
+ searchF func(search) search
+)
+
+// WithMaxResults sets the max results to return
+func WithMaxResults(maxResults int) searchF {
+ return func(s search) search {
+ s = append(s, searchParam{name: "maxResults", value: fmt.Sprintf("%d", maxResults)})
+ return s
+ }
+}
+
+// WithAccountId sets the account id to search
+func WithAccountId(accountId string) searchF {
+ return func(s search) search {
+ s = append(s, searchParam{name: "accountId", value: accountId})
+ return s
+ }
+}
+
+// WithUsername sets the username to search
+func WithUsername(username string) searchF {
+ return func(s search) search {
+ s = append(s, searchParam{name: "username", value: username})
+ return s
+ }
+}
diff --git a/cloud/user.go b/cloud/user.go
index 3453a72e..844512e4 100644
--- a/cloud/user.go
+++ b/cloud/user.go
@@ -67,15 +67,6 @@ type ApplicationRole struct {
// Key `defaultGroupsDetails` missing - https://developer.atlassian.com/cloud/jira/platform/rest/v3/api-group-application-roles/#api-rest-api-3-applicationrole-key-get
}
-type userSearchParam struct {
- name string
- value string
-}
-
-type userSearch []userSearchParam
-
-type userSearchF func(userSearch) userSearch
-
// Get gets user info from Jira using its Account Id
//
// Jira API docs: https://developer.atlassian.com/cloud/jira/platform/rest/v2/#api-rest-api-2-user-get
@@ -209,58 +200,34 @@ func (s *UserService) GetCurrentUser(ctx context.Context) (*User, *Response, err
return &user, resp, nil
}
-// WithMaxResults sets the max results to return
-func WithMaxResults(maxResults int) userSearchF {
- return func(s userSearch) userSearch {
- s = append(s, userSearchParam{name: "maxResults", value: fmt.Sprintf("%d", maxResults)})
- return s
- }
-}
-
// WithStartAt set the start pager
-func WithStartAt(startAt int) userSearchF {
- return func(s userSearch) userSearch {
- s = append(s, userSearchParam{name: "startAt", value: fmt.Sprintf("%d", startAt)})
+func WithStartAt(startAt int) searchF {
+ return func(s search) search {
+ s = append(s, searchParam{name: "startAt", value: fmt.Sprintf("%d", startAt)})
return s
}
}
// WithActive sets the active users lookup
-func WithActive(active bool) userSearchF {
- return func(s userSearch) userSearch {
- s = append(s, userSearchParam{name: "includeActive", value: fmt.Sprintf("%t", active)})
+func WithActive(active bool) searchF {
+ return func(s search) search {
+ s = append(s, searchParam{name: "includeActive", value: fmt.Sprintf("%t", active)})
return s
}
}
// WithInactive sets the inactive users lookup
-func WithInactive(inactive bool) userSearchF {
- return func(s userSearch) userSearch {
- s = append(s, userSearchParam{name: "includeInactive", value: fmt.Sprintf("%t", inactive)})
- return s
- }
-}
-
-// WithUsername sets the username to search
-func WithUsername(username string) userSearchF {
- return func(s userSearch) userSearch {
- s = append(s, userSearchParam{name: "username", value: username})
- return s
- }
-}
-
-// WithAccountId sets the account id to search
-func WithAccountId(accountId string) userSearchF {
- return func(s userSearch) userSearch {
- s = append(s, userSearchParam{name: "accountId", value: accountId})
+func WithInactive(inactive bool) searchF {
+ return func(s search) search {
+ s = append(s, searchParam{name: "includeInactive", value: fmt.Sprintf("%t", inactive)})
return s
}
}
// WithProperty sets the property (Property keys are specified by path) to search
-func WithProperty(property string) userSearchF {
- return func(s userSearch) userSearch {
- s = append(s, userSearchParam{name: "property", value: property})
+func WithProperty(property string) searchF {
+ return func(s search) search {
+ s = append(s, searchParam{name: "property", value: property})
return s
}
}
@@ -272,8 +239,8 @@ func WithProperty(property string) userSearchF {
//
// TODO Double check this method if this works as expected, is using the latest API and the response is complete
// This double check effort is done for v2 - Remove this two lines if this is completed.
-func (s *UserService) Find(ctx context.Context, property string, tweaks ...userSearchF) ([]User, *Response, error) {
- search := []userSearchParam{
+func (s *UserService) Find(ctx context.Context, property string, tweaks ...searchF) ([]User, *Response, error) {
+ search := []searchParam{
{
name: "query",
value: property,
diff --git a/testing/mock-data/role_actors.json b/testing/mock-data/role_actors.json
new file mode 100644
index 00000000..9457ebc7
--- /dev/null
+++ b/testing/mock-data/role_actors.json
@@ -0,0 +1,35 @@
+{
+ "self": "https://your-domain.atlassian.net/rest/api/3/project/MKY/role/10360",
+ "name": "Developers",
+ "id": 10360,
+ "description": "A project role that represents developers in a project",
+ "actors": [
+ {
+ "id": 10240,
+ "displayName": "jira-developers",
+ "type": "atlassian-group-role-actor",
+ "name": "jira-developers",
+ "actorGroup": {
+ "name": "jira-developers",
+ "displayName": "jira-developers",
+ "groupId": "952d12c3-5b5b-4d04-bb32-44d383afc4b2"
+ }
+ },
+ {
+ "id": 10241,
+ "displayName": "Mia Krystof",
+ "type": "atlassian-user-role-actor",
+ "actorUser": {
+ "accountId": "5b10a2844c20165700ede21g"
+ }
+ }
+ ],
+ "scope": {
+ "type": "PROJECT",
+ "project": {
+ "id": "10000",
+ "key": "KEY",
+ "name": "Next Gen Project"
+ }
+ }
+}
\ No newline at end of file