From 81ff21595cfd8c8c8e9350862b39865e1f5343e7 Mon Sep 17 00:00:00 2001 From: Klyachin Aleksey Date: Fri, 8 Oct 2021 21:34:14 +0300 Subject: [PATCH 01/11] New issue method: update remote issue link by ID --- issue.go | 24 ++++++++++++++++++++++++ issue_test.go | 40 ++++++++++++++++++++++++++++++++++++++++ 2 files changed, 64 insertions(+) diff --git a/issue.go b/issue.go index 3e898d70..5c6c8822 100644 --- a/issue.go +++ b/issue.go @@ -1531,3 +1531,27 @@ func (s *IssueService) AddRemoteLinkWithContext(ctx context.Context, issueID str func (s *IssueService) AddRemoteLink(issueID string, remotelink *RemoteLink) (*RemoteLink, *Response, error) { return s.AddRemoteLinkWithContext(context.Background(), issueID, remotelink) } + +// UpdateRemoteLinkWithContext updates a remote issue link by linkID. +// +// Jira API docs: https://developer.atlassian.com/cloud/jira/platform/rest/v2/api-group-issue-remote-links/#api-rest-api-2-issue-issueidorkey-remotelink-linkid-put +func (s *IssueService) UpdateRemoteLinkWithContext(ctx context.Context, issueID string, linkID int, remotelink *RemoteLink) (*Response, error) { + apiEndpoint := fmt.Sprintf("rest/api/2/issue/%s/remotelink/%d", issueID, linkID) + req, err := s.client.NewRequestWithContext(ctx, "PUT", apiEndpoint, remotelink) + if err != nil { + return nil, err + } + + resp, err := s.client.Do(req, nil) + if err != nil { + jerr := NewJiraError(resp, err) + return resp, jerr + } + + return resp, nil +} + +// UpdateRemoteLink wraps UpdateRemoteLinkWithContext using the background context. +func (s *IssueService) UpdateRemoteLink(issueID string, linkID int, remotelink *RemoteLink) (*Response, error) { + return s.UpdateRemoteLinkWithContext(context.Background(), issueID, linkID, remotelink) +} diff --git a/issue_test.go b/issue_test.go index 6664478f..64f4fa29 100644 --- a/issue_test.go +++ b/issue_test.go @@ -1855,6 +1855,46 @@ func TestIssueService_AddRemoteLink(t *testing.T) { } } +func TestIssueService_UpdateRemoteLink(t *testing.T) { + setup() + defer teardown() + testMux.HandleFunc("/rest/api/2/issue/100/remotelink/200", func(w http.ResponseWriter, r *http.Request) { + testMethod(t, r, "PUT") + testRequestURL(t, r, "/rest/api/2/issue/100/remotelink/200") + + w.WriteHeader(http.StatusNoContent) + }) + r := &RemoteLink{ + Application: &RemoteLinkApplication{ + Name: "My Acme Tracker", + Type: "com.acme.tracker", + }, + GlobalID: "system=http://www.mycompany.com/support&id=1", + Relationship: "causes", + Object: &RemoteLinkObject{ + Summary: "Customer support issue", + Icon: &RemoteLinkIcon{ + Url16x16: "http://www.mycompany.com/support/ticket.png", + Title: "Support Ticket", + }, + Title: "TSTSUP-111", + URL: "http://www.mycompany.com/support?id=1", + Status: &RemoteLinkStatus{ + Icon: &RemoteLinkIcon{ + Url16x16: "http://www.mycompany.com/support/resolved.png", + Title: "Case Closed", + Link: "http://www.mycompany.com/support?id=1&details=closed", + }, + Resolved: true, + }, + }, + } + _, err := testClient.Issue.UpdateRemoteLink("100", 200, r) + if err != nil { + t.Errorf("Error given: %s", err) + } +} + func TestTime_MarshalJSON(t *testing.T) { timeFormatParseFrom := "2006-01-02T15:04:05.999Z" testCases := []struct { From 60091ec56f1fadacd0b32e765c5310d72e2e83ff Mon Sep 17 00:00:00 2001 From: James Burke Date: Tue, 16 Nov 2021 11:04:55 +0100 Subject: [PATCH 02/11] fix: Accept strings as serviceDeskID see the issue for details on the reason for change closes issue #418 --- servicedesk.go | 18 ++++----- servicedesk_test.go | 93 +++++++++++++++++++++++++++++++++++++++++++++ 2 files changed, 102 insertions(+), 9 deletions(-) diff --git a/servicedesk.go b/servicedesk.go index c6c91473..2d942682 100644 --- a/servicedesk.go +++ b/servicedesk.go @@ -19,8 +19,8 @@ type ServiceDeskOrganizationDTO struct { // all organizations associated with a service desk. // // https://developer.atlassian.com/cloud/jira/service-desk/rest/api-group-organization/#api-rest-servicedeskapi-servicedesk-servicedeskid-organization-get -func (s *ServiceDeskService) GetOrganizationsWithContext(ctx context.Context, serviceDeskID int, start int, limit int, accountID string) (*PagedDTO, *Response, error) { - apiEndPoint := fmt.Sprintf("rest/servicedeskapi/servicedesk/%d/organization?start=%d&limit=%d", serviceDeskID, start, limit) +func (s *ServiceDeskService) GetOrganizationsWithContext(ctx context.Context, serviceDeskID interface{}, start int, limit int, accountID string) (*PagedDTO, *Response, error) { + apiEndPoint := fmt.Sprintf("rest/servicedeskapi/servicedesk/%v/organization?start=%d&limit=%d", serviceDeskID, start, limit) if accountID != "" { apiEndPoint += fmt.Sprintf("&accountId=%s", accountID) } @@ -43,7 +43,7 @@ func (s *ServiceDeskService) GetOrganizationsWithContext(ctx context.Context, se } // GetOrganizations wraps GetOrganizationsWithContext using the background context. -func (s *ServiceDeskService) GetOrganizations(serviceDeskID int, start int, limit int, accountID string) (*PagedDTO, *Response, error) { +func (s *ServiceDeskService) GetOrganizations(serviceDeskID interface{}, start int, limit int, accountID string) (*PagedDTO, *Response, error) { return s.GetOrganizationsWithContext(context.Background(), serviceDeskID, start, limit, accountID) } @@ -53,8 +53,8 @@ func (s *ServiceDeskService) GetOrganizations(serviceDeskID int, start int, limi // and the resource returns a 204 success code. // // https://developer.atlassian.com/cloud/jira/service-desk/rest/api-group-organization/#api-rest-servicedeskapi-servicedesk-servicedeskid-organization-post -func (s *ServiceDeskService) AddOrganizationWithContext(ctx context.Context, serviceDeskID int, organizationID int) (*Response, error) { - apiEndPoint := fmt.Sprintf("rest/servicedeskapi/servicedesk/%d/organization", serviceDeskID) +func (s *ServiceDeskService) AddOrganizationWithContext(ctx context.Context, serviceDeskID interface{}, organizationID int) (*Response, error) { + apiEndPoint := fmt.Sprintf("rest/servicedeskapi/servicedesk/%v/organization", serviceDeskID) organization := ServiceDeskOrganizationDTO{ OrganizationID: organizationID, @@ -76,7 +76,7 @@ func (s *ServiceDeskService) AddOrganizationWithContext(ctx context.Context, ser } // AddOrganization wraps AddOrganizationWithContext using the background context. -func (s *ServiceDeskService) AddOrganization(serviceDeskID int, organizationID int) (*Response, error) { +func (s *ServiceDeskService) AddOrganization(serviceDeskID interface{}, organizationID int) (*Response, error) { return s.AddOrganizationWithContext(context.Background(), serviceDeskID, organizationID) } @@ -86,8 +86,8 @@ func (s *ServiceDeskService) AddOrganization(serviceDeskID int, organizationID i // no change is made and the resource returns a 204 success code. // // https://developer.atlassian.com/cloud/jira/service-desk/rest/api-group-organization/#api-rest-servicedeskapi-servicedesk-servicedeskid-organization-delete -func (s *ServiceDeskService) RemoveOrganizationWithContext(ctx context.Context, serviceDeskID int, organizationID int) (*Response, error) { - apiEndPoint := fmt.Sprintf("rest/servicedeskapi/servicedesk/%d/organization", serviceDeskID) +func (s *ServiceDeskService) RemoveOrganizationWithContext(ctx context.Context, serviceDeskID interface{}, organizationID int) (*Response, error) { + apiEndPoint := fmt.Sprintf("rest/servicedeskapi/servicedesk/%v/organization", serviceDeskID) organization := ServiceDeskOrganizationDTO{ OrganizationID: organizationID, @@ -109,6 +109,6 @@ func (s *ServiceDeskService) RemoveOrganizationWithContext(ctx context.Context, } // RemoveOrganization wraps RemoveOrganizationWithContext using the background context. -func (s *ServiceDeskService) RemoveOrganization(serviceDeskID int, organizationID int) (*Response, error) { +func (s *ServiceDeskService) RemoveOrganization(serviceDeskID interface{}, organizationID int) (*Response, error) { return s.RemoveOrganizationWithContext(context.Background(), serviceDeskID, organizationID) } diff --git a/servicedesk_test.go b/servicedesk_test.go index 9e763740..2590f7cc 100644 --- a/servicedesk_test.go +++ b/servicedesk_test.go @@ -98,3 +98,96 @@ func TestServiceDeskService_RemoveOrganizations(t *testing.T) { t.Errorf("Error given: %s", err) } } + +func TestServiceDeskServiceStringServiceDeskID_GetOrganizations(t *testing.T) { + setup() + defer teardown() + testMux.HandleFunc("/rest/servicedeskapi/servicedesk/TEST/organization", func(w http.ResponseWriter, r *http.Request) { + testMethod(t, r, "GET") + testRequestURL(t, r, "/rest/servicedeskapi/servicedesk/TEST/organization") + + w.WriteHeader(http.StatusOK) + fmt.Fprint(w, `{ + "_expands": [], + "size": 3, + "start": 3, + "limit": 3, + "isLastPage": false, + "_links": { + "base": "https://your-domain.atlassian.net/rest/servicedeskapi", + "context": "context", + "next": "https://your-domain.atlassian.net/rest/servicedeskapi/servicedesk/TEST/organization?start=6&limit=3", + "prev": "https://your-domain.atlassian.net/rest/servicedeskapi/servicedesk/TEST/organization?start=0&limit=3" + }, + "values": [ + { + "id": "1", + "name": "Charlie Cakes Franchises", + "_links": { + "self": "https://your-domain.atlassian.net/rest/servicedeskapi/organization/1" + } + }, + { + "id": "2", + "name": "Atlas Coffee Co", + "_links": { + "self": "https://your-domain.atlassian.net/rest/servicedeskapi/organization/2" + } + }, + { + "id": "3", + "name": "The Adjustment Bureau", + "_links": { + "self": "https://your-domain.atlassian.net/rest/servicedeskapi/organization/3" + } + } + ] + }`) + }) + + orgs, _, err := testClient.ServiceDesk.GetOrganizations("TEST", 3, 3, "") + + if orgs == nil { + t.Error("Expected Organizations. Result is nil") + } else if orgs.Size != 3 { + t.Errorf("Expected size to be 3, but got %d", orgs.Size) + } + + if err != nil { + t.Errorf("Error given: %s", err) + } +} + +func TestServiceDeskServiceStringServiceDeskID_AddOrganizations(t *testing.T) { + setup() + defer teardown() + testMux.HandleFunc("/rest/servicedeskapi/servicedesk/TEST/organization", func(w http.ResponseWriter, r *http.Request) { + testMethod(t, r, "POST") + testRequestURL(t, r, "/rest/servicedeskapi/servicedesk/TEST/organization") + + w.WriteHeader(http.StatusNoContent) + }) + + _, err := testClient.ServiceDesk.AddOrganization("TEST", 1) + + if err != nil { + t.Errorf("Error given: %s", err) + } +} + +func TestServiceDeskServiceStringServiceDeskID_RemoveOrganizations(t *testing.T) { + setup() + defer teardown() + testMux.HandleFunc("/rest/servicedeskapi/servicedesk/TEST/organization", func(w http.ResponseWriter, r *http.Request) { + testMethod(t, r, "DELETE") + testRequestURL(t, r, "/rest/servicedeskapi/servicedesk/TEST/organization") + + w.WriteHeader(http.StatusNoContent) + }) + + _, err := testClient.ServiceDesk.RemoveOrganization("TEST", 1) + + if err != nil { + t.Errorf("Error given: %s", err) + } +} From 84ba530dff9784260c88886648b7ab95c2ef5357 Mon Sep 17 00:00:00 2001 From: Dick Appel Date: Tue, 23 Nov 2021 09:16:39 +0100 Subject: [PATCH 03/11] feat: added support for personal-access-tokens - added a new PATAuthTransport type that has a 'Token' attribute to hold your unique PAT - setting the Authorization header with the bearer token in the RoundTrip function. - added test to prove to the token gets passed via the header - bonus: fixed typo in existing test name --- authentication_test.go | 2 +- jira.go | 34 ++++++++++++++++++++++++++++++++++ jira_test.go | 23 +++++++++++++++++++++++ 3 files changed, 58 insertions(+), 1 deletion(-) diff --git a/authentication_test.go b/authentication_test.go index 431a7fdc..9235d080 100644 --- a/authentication_test.go +++ b/authentication_test.go @@ -133,7 +133,7 @@ func TestAuthenticationService_Authenticated_WithBasicAuthButNoUsername(t *testi } } -func TestAithenticationService_GetUserInfo_AccessForbidden_Fail(t *testing.T) { +func TestAuthenticationService_GetUserInfo_AccessForbidden_Fail(t *testing.T) { setup() defer teardown() testMux.HandleFunc("/rest/auth/1/session", func(w http.ResponseWriter, r *http.Request) { diff --git a/jira.go b/jira.go index 66046a45..b628ec67 100644 --- a/jira.go +++ b/jira.go @@ -382,6 +382,40 @@ func (t *BasicAuthTransport) transport() http.RoundTripper { return http.DefaultTransport } +// PATAuthTransport is an http.RoundTripper that authenticates all requests +// using the Personal Access Token specified. +type PATAuthTransport struct { + Token string + + // Transport is the underlying HTTP transport to use when making requests. + // It will default to http.DefaultTransport if nil. + Transport http.RoundTripper +} + +// RoundTrip implements the RoundTripper interface. We just add the +// basic auth and return the RoundTripper for this transport type. +func (t *PATAuthTransport) RoundTrip(req *http.Request) (*http.Response, error) { + req2 := cloneRequest(req) // per RoundTripper contract + req2.Header.Set("Authorization", "Bearer "+t.Token) + return t.transport().RoundTrip(req2) +} + +// Client returns an *http.Client that makes requests that are authenticated +// using HTTP Basic Authentication. This is a nice little bit of sugar +// so we can just get the client instead of creating the client in the calling code. +// If it's necessary to send more information on client init, the calling code can +// always skip this and set the transport itself. +func (t *PATAuthTransport) Client() *http.Client { + return &http.Client{Transport: t} +} + +func (t *PATAuthTransport) transport() http.RoundTripper { + if t.Transport != nil { + return t.Transport + } + return http.DefaultTransport +} + // CookieAuthTransport is an http.RoundTripper that authenticates all requests // using Jira's cookie-based authentication. // diff --git a/jira_test.go b/jira_test.go index 9f34dd78..3aedbd64 100644 --- a/jira_test.go +++ b/jira_test.go @@ -631,3 +631,26 @@ func TestJWTAuthTransport_HeaderContainsJWT(t *testing.T) { jwtClient, _ := NewClient(jwtTransport.Client(), testServer.URL) jwtClient.Issue.Get("TEST-1", nil) } + +func TestPATAuthTransport_HeaderContainsAuth(t *testing.T) { + setup() + defer teardown() + + token := "shhh, it's a token" + + patTransport := &PATAuthTransport{ + Token: token, + } + + testMux.HandleFunc("/", func(w http.ResponseWriter, r *http.Request) { + val := r.Header.Get("Authorization") + expected := "Bearer " + token + if val != expected { + t.Errorf("request does not contain bearer token in the Authorization header.") + } + }) + + client, _ := NewClient(patTransport.Client(), testServer.URL) + client.User.GetSelf() + +} From 1c05820d6f0d02af6d27d6521d543ec2df6fa092 Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Mon, 6 Dec 2021 04:11:42 +0000 Subject: [PATCH 04/11] chore(deps): bump github.com/golang-jwt/jwt/v4 from 4.1.0 to 4.2.0 Bumps [github.com/golang-jwt/jwt/v4](https://github.com/golang-jwt/jwt) from 4.1.0 to 4.2.0. - [Release notes](https://github.com/golang-jwt/jwt/releases) - [Changelog](https://github.com/golang-jwt/jwt/blob/main/VERSION_HISTORY.md) - [Commits](https://github.com/golang-jwt/jwt/compare/v4.1.0...v4.2.0) --- updated-dependencies: - dependency-name: github.com/golang-jwt/jwt/v4 dependency-type: direct:production update-type: version-update:semver-minor ... Signed-off-by: dependabot[bot] --- go.mod | 2 +- go.sum | 4 ++-- 2 files changed, 3 insertions(+), 3 deletions(-) diff --git a/go.mod b/go.mod index 899a8dcc..eec55379 100644 --- a/go.mod +++ b/go.mod @@ -4,7 +4,7 @@ go 1.15 require ( github.com/fatih/structs v1.1.0 - github.com/golang-jwt/jwt/v4 v4.1.0 + github.com/golang-jwt/jwt/v4 v4.2.0 github.com/google/go-cmp v0.5.6 github.com/google/go-querystring v1.1.0 github.com/pkg/errors v0.9.1 diff --git a/go.sum b/go.sum index 7db8a1a6..e88756da 100644 --- a/go.sum +++ b/go.sum @@ -1,7 +1,7 @@ github.com/fatih/structs v1.1.0 h1:Q7juDM0QtcnhCpeyLGQKyg4TOIghuNXrkL32pHAUMxo= github.com/fatih/structs v1.1.0/go.mod h1:9NiDSp5zOcgEDl+j00MP/WkGVPOlPRLejGD8Ga6PJ7M= -github.com/golang-jwt/jwt/v4 v4.1.0 h1:XUgk2Ex5veyVFVeLm0xhusUTQybEbexJXrvPNOKkSY0= -github.com/golang-jwt/jwt/v4 v4.1.0/go.mod h1:/xlHOz8bRuivTWchD4jCa+NbatV+wEUSzwAxVc6locg= +github.com/golang-jwt/jwt/v4 v4.2.0 h1:besgBTC8w8HjP6NzQdxwKH9Z5oQMZ24ThTrHp3cZ8eU= +github.com/golang-jwt/jwt/v4 v4.2.0/go.mod h1:/xlHOz8bRuivTWchD4jCa+NbatV+wEUSzwAxVc6locg= github.com/google/go-cmp v0.5.2/go.mod h1:v8dTdLbMG2kIc/vJvl+f65V22dbkXbowE6jgT/gNBxE= github.com/google/go-cmp v0.5.6 h1:BKbKCqvP6I+rmFHt06ZmyQtvB8xAkWdhFyr0ZUNZcxQ= github.com/google/go-cmp v0.5.6/go.mod h1:v8dTdLbMG2kIc/vJvl+f65V22dbkXbowE6jgT/gNBxE= From 3b2368d4cbfccff65fa493ea0a66a94785a80b1e Mon Sep 17 00:00:00 2001 From: Dick Appel Date: Tue, 21 Dec 2021 11:20:21 +0100 Subject: [PATCH 05/11] docs: added comment on Token field and ref to PAT documentation. --- jira.go | 2 ++ 1 file changed, 2 insertions(+) diff --git a/jira.go b/jira.go index b628ec67..a6e6b2e6 100644 --- a/jira.go +++ b/jira.go @@ -384,7 +384,9 @@ func (t *BasicAuthTransport) transport() http.RoundTripper { // PATAuthTransport is an http.RoundTripper that authenticates all requests // using the Personal Access Token specified. +// See here for more info: https://confluence.atlassian.com/enterprise/using-personal-access-tokens-1026032365.html type PATAuthTransport struct { + // Token is the key that was provided by Jira when creating the Personal Access Token. Token string // Transport is the underlying HTTP transport to use when making requests. From b4a9565fc236d40b3eeabc28026096ee44d74377 Mon Sep 17 00:00:00 2001 From: Tim Strijdhorst Date: Wed, 22 Dec 2021 16:13:20 +0100 Subject: [PATCH 06/11] %missing alias for import --- README.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/README.md b/README.md index b2b1edec..571d4c30 100644 --- a/README.md +++ b/README.md @@ -71,7 +71,7 @@ package main import ( "fmt" - "github.com/andygrunwald/go-jira" + jira "github.com/andygrunwald/go-jira" ) func main() { From f558a519334f5c49139646b361d8c2c9d48a3bf5 Mon Sep 17 00:00:00 2001 From: Breno Loyola Date: Thu, 30 Dec 2021 14:38:20 -0300 Subject: [PATCH 07/11] add missing min/max to BoardConfigurationColumn (#430) * feat: add missing min/max fields to BoardConfigurationColumn * fix: add omitempty to min/max in BoardConfigurationColumn --- board.go | 2 ++ board_test.go | 15 +++++++++++++++ mocks/board_configuration.json | 4 +++- 3 files changed, 20 insertions(+), 1 deletion(-) diff --git a/board.go b/board.go index 27516872..403d1566 100644 --- a/board.go +++ b/board.go @@ -117,6 +117,8 @@ type BoardConfigurationColumnConfig struct { type BoardConfigurationColumn struct { Name string `json:"name"` Status []BoardConfigurationColumnStatus `json:"statuses"` + Min int `json:"min,omitempty"` + Max int `json:"max,omitempty"` } // BoardConfigurationColumnStatus represents a status in the column configuration diff --git a/board_test.go b/board_test.go index 982f29bb..11a5dc2d 100644 --- a/board_test.go +++ b/board_test.go @@ -248,4 +248,19 @@ func TestBoardService_GetBoardConfigoration(t *testing.T) { t.Errorf("Expected 6 columns. go %d", len(boardConfiguration.ColumnConfig.Columns)) } + backlogColumn := boardConfiguration.ColumnConfig.Columns[0] + if backlogColumn.Min != 5 { + t.Errorf("Expected a min of 5 issues in backlog. Got %d", backlogColumn.Min) + } + if backlogColumn.Max != 30 { + t.Errorf("Expected a max of 30 issues in backlog. Got %d", backlogColumn.Max) + } + + inProgressColumn := boardConfiguration.ColumnConfig.Columns[2] + if inProgressColumn.Min != 0 { + t.Errorf("Expected a min of 0 issues in progress. Got %d", inProgressColumn.Min) + } + if inProgressColumn.Max != 0 { + t.Errorf("Expected a max of 0 issues in progress. Got %d", inProgressColumn.Max) + } } diff --git a/mocks/board_configuration.json b/mocks/board_configuration.json index 9a4c1ec3..0bb9b3db 100644 --- a/mocks/board_configuration.json +++ b/mocks/board_configuration.json @@ -26,7 +26,9 @@ "id": "10005", "self": "https://test.jira.org/rest/api/2/status/10005" } - ] + ], + "min": 5, + "max": 30 }, { "name": "Selected for development", From 17581f3e2a6dc1684c98298e12c96cb1b4470392 Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Thu, 20 Jan 2022 04:11:26 +0000 Subject: [PATCH 08/11] chore(deps): bump github.com/google/go-cmp from 0.5.6 to 0.5.7 Bumps [github.com/google/go-cmp](https://github.com/google/go-cmp) from 0.5.6 to 0.5.7. - [Release notes](https://github.com/google/go-cmp/releases) - [Commits](https://github.com/google/go-cmp/compare/v0.5.6...v0.5.7) --- updated-dependencies: - dependency-name: github.com/google/go-cmp dependency-type: direct:production update-type: version-update:semver-patch ... Signed-off-by: dependabot[bot] --- go.mod | 2 +- go.sum | 4 ++-- 2 files changed, 3 insertions(+), 3 deletions(-) diff --git a/go.mod b/go.mod index eec55379..6afbb7a8 100644 --- a/go.mod +++ b/go.mod @@ -5,7 +5,7 @@ go 1.15 require ( github.com/fatih/structs v1.1.0 github.com/golang-jwt/jwt/v4 v4.2.0 - github.com/google/go-cmp v0.5.6 + github.com/google/go-cmp v0.5.7 github.com/google/go-querystring v1.1.0 github.com/pkg/errors v0.9.1 github.com/trivago/tgo v1.0.7 diff --git a/go.sum b/go.sum index e88756da..008b8f7f 100644 --- a/go.sum +++ b/go.sum @@ -3,8 +3,8 @@ github.com/fatih/structs v1.1.0/go.mod h1:9NiDSp5zOcgEDl+j00MP/WkGVPOlPRLejGD8Ga github.com/golang-jwt/jwt/v4 v4.2.0 h1:besgBTC8w8HjP6NzQdxwKH9Z5oQMZ24ThTrHp3cZ8eU= github.com/golang-jwt/jwt/v4 v4.2.0/go.mod h1:/xlHOz8bRuivTWchD4jCa+NbatV+wEUSzwAxVc6locg= github.com/google/go-cmp v0.5.2/go.mod h1:v8dTdLbMG2kIc/vJvl+f65V22dbkXbowE6jgT/gNBxE= -github.com/google/go-cmp v0.5.6 h1:BKbKCqvP6I+rmFHt06ZmyQtvB8xAkWdhFyr0ZUNZcxQ= -github.com/google/go-cmp v0.5.6/go.mod h1:v8dTdLbMG2kIc/vJvl+f65V22dbkXbowE6jgT/gNBxE= +github.com/google/go-cmp v0.5.7 h1:81/ik6ipDQS2aGcBfIN5dHDB36BwrStyeAQquSYCV4o= +github.com/google/go-cmp v0.5.7/go.mod h1:n+brtR0CgQNWTVd5ZUFpTBC8YFBDLK/h/bpaJ8/DtOE= github.com/google/go-querystring v1.1.0 h1:AnCroh3fv4ZBgVIf1Iwtovgjaw/GiKJo8M8yD/fhyJ8= github.com/google/go-querystring v1.1.0/go.mod h1:Kcdr2DB4koayq7X8pmAG4sNG59So17icRSOU623lUBU= github.com/pkg/errors v0.9.1 h1:FEBLx1zS214owpjy7qsBeixbURkuhQAwrK5UwLGTwt4= From 3555edb9bbda729c1cee721a20abd4ff331e0e1e Mon Sep 17 00:00:00 2001 From: Chris Cunningham Date: Tue, 25 Jan 2022 10:51:00 -0400 Subject: [PATCH 09/11] adds missing struct omitempty tags to the Parent struct (#435) updates TestIssueFields_MarshalJSON_OmitsEmptyFields to check for ignored parent fields --- issue.go | 4 ++-- issue_test.go | 8 +++++++- 2 files changed, 9 insertions(+), 3 deletions(-) diff --git a/issue.go b/issue.go index 5c6c8822..084f130e 100644 --- a/issue.go +++ b/issue.go @@ -283,8 +283,8 @@ type Progress struct { // Parent represents the parent of a Jira issue, to be used with subtask issue types. type Parent struct { - ID string `json:"id,omitempty" structs:"id"` - Key string `json:"key,omitempty" structs:"key"` + ID string `json:"id,omitempty" structs:"id,omitempty"` + Key string `json:"key,omitempty" structs:"key,omitempty"` } // Time represents the Time definition of Jira as a time.Time of go diff --git a/issue_test.go b/issue_test.go index 64f4fa29..ceeff9a8 100644 --- a/issue_test.go +++ b/issue_test.go @@ -1031,6 +1031,7 @@ func TestIssueFields_MarshalJSON_OmitsEmptyFields(t *testing.T) { Name: "Story", }, Labels: []string{"aws-docker"}, + Parent: &Parent{Key: "FOO-300"}, } rawdata, err := json.Marshal(i) @@ -1050,6 +1051,12 @@ func TestIssueFields_MarshalJSON_OmitsEmptyFields(t *testing.T) { t.Error("Expected non nil error, received nil") } + // verify Parent nil values are being omitted + _, err = issuef.String("parent/id") + if err == nil { + t.Error("Expected non nil err, received nil") + } + // verify that the field that should be there, is. name, err := issuef.String("issuetype/name") if err != nil { @@ -1059,7 +1066,6 @@ func TestIssueFields_MarshalJSON_OmitsEmptyFields(t *testing.T) { if name != "Story" { t.Errorf("Expected Story, received %s", name) } - } func TestIssueFields_MarshalJSON_Success(t *testing.T) { From fe04db3d35d70c9384bfc86aa91942880d388b7f Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Thu, 10 Feb 2022 04:20:15 +0000 Subject: [PATCH 10/11] chore(deps): bump github.com/golang-jwt/jwt/v4 from 4.2.0 to 4.3.0 Bumps [github.com/golang-jwt/jwt/v4](https://github.com/golang-jwt/jwt) from 4.2.0 to 4.3.0. - [Release notes](https://github.com/golang-jwt/jwt/releases) - [Changelog](https://github.com/golang-jwt/jwt/blob/main/VERSION_HISTORY.md) - [Commits](https://github.com/golang-jwt/jwt/compare/v4.2.0...v4.3.0) --- updated-dependencies: - dependency-name: github.com/golang-jwt/jwt/v4 dependency-type: direct:production update-type: version-update:semver-minor ... Signed-off-by: dependabot[bot] --- go.mod | 2 +- go.sum | 4 ++-- 2 files changed, 3 insertions(+), 3 deletions(-) diff --git a/go.mod b/go.mod index 6afbb7a8..fd1ad0b3 100644 --- a/go.mod +++ b/go.mod @@ -4,7 +4,7 @@ go 1.15 require ( github.com/fatih/structs v1.1.0 - github.com/golang-jwt/jwt/v4 v4.2.0 + github.com/golang-jwt/jwt/v4 v4.3.0 github.com/google/go-cmp v0.5.7 github.com/google/go-querystring v1.1.0 github.com/pkg/errors v0.9.1 diff --git a/go.sum b/go.sum index 008b8f7f..937976ca 100644 --- a/go.sum +++ b/go.sum @@ -1,7 +1,7 @@ github.com/fatih/structs v1.1.0 h1:Q7juDM0QtcnhCpeyLGQKyg4TOIghuNXrkL32pHAUMxo= github.com/fatih/structs v1.1.0/go.mod h1:9NiDSp5zOcgEDl+j00MP/WkGVPOlPRLejGD8Ga6PJ7M= -github.com/golang-jwt/jwt/v4 v4.2.0 h1:besgBTC8w8HjP6NzQdxwKH9Z5oQMZ24ThTrHp3cZ8eU= -github.com/golang-jwt/jwt/v4 v4.2.0/go.mod h1:/xlHOz8bRuivTWchD4jCa+NbatV+wEUSzwAxVc6locg= +github.com/golang-jwt/jwt/v4 v4.3.0 h1:kHL1vqdqWNfATmA0FNMdmZNMyZI1U6O31X4rlIPoBog= +github.com/golang-jwt/jwt/v4 v4.3.0/go.mod h1:/xlHOz8bRuivTWchD4jCa+NbatV+wEUSzwAxVc6locg= github.com/google/go-cmp v0.5.2/go.mod h1:v8dTdLbMG2kIc/vJvl+f65V22dbkXbowE6jgT/gNBxE= github.com/google/go-cmp v0.5.7 h1:81/ik6ipDQS2aGcBfIN5dHDB36BwrStyeAQquSYCV4o= github.com/google/go-cmp v0.5.7/go.mod h1:n+brtR0CgQNWTVd5ZUFpTBC8YFBDLK/h/bpaJ8/DtOE= From 63d5e6d94c0ef5343271dc96d480618e68ddcdc4 Mon Sep 17 00:00:00 2001 From: Harendra Chhekur <820121223505e@gmail.com> Date: Fri, 18 Feb 2022 22:20:18 +0530 Subject: [PATCH 11/11] feat(auth): Bearer Auth Support (oauth 2.0) --- jira.go | 35 +++++++++++++++++++++++++++++++++++ 1 file changed, 35 insertions(+) diff --git a/jira.go b/jira.go index a6e6b2e6..d7df3114 100644 --- a/jira.go +++ b/jira.go @@ -382,6 +382,41 @@ func (t *BasicAuthTransport) transport() http.RoundTripper { return http.DefaultTransport } +// BearerAuthTransport is a http.RoundTripper that authenticates all requests +// using Jira's bearer (oauth 2.0 (3lo)) based authentication. +type BearerAuthTransport struct { + Token string + + // Transport is the underlying HTTP transport to use when making requests. + // It will default to http.DefaultTransport if nil. + Transport http.RoundTripper +} + +// RoundTrip implements the RoundTripper interface. We just add the +// bearer token and return the RoundTripper for this transport type. +func (t *BearerAuthTransport) RoundTrip(req *http.Request) (*http.Response, error) { + req2 := cloneRequest(req) // per RoundTripper contract + + req2.Header.Set("Authorization", fmt.Sprintf("Bearer %s", t.Token)) + return t.transport().RoundTrip(req2) +} + +// Client returns an *http.Client that makes requests that are authenticated +// using HTTP Basic Authentication. This is a nice little bit of sugar +// so we can just get the client instead of creating the client in the calling code. +// If it's necessary to send more information on client init, the calling code can +// always skip this and set the transport itself. +func (t *BearerAuthTransport) Client() *http.Client { + return &http.Client{Transport: t} +} + +func (t *BearerAuthTransport) transport() http.RoundTripper { + if t.Transport != nil { + return t.Transport + } + return http.DefaultTransport +} + // PATAuthTransport is an http.RoundTripper that authenticates all requests // using the Personal Access Token specified. // See here for more info: https://confluence.atlassian.com/enterprise/using-personal-access-tokens-1026032365.html