Skip to content

Commit

Permalink
Merge branch 'master' into issue-284-product-naming
Browse files Browse the repository at this point in the history
* master:
  fix(tests): Fix TestIssueService_PostAttachment unit test
  style: Fix typos
  style: Make code go fmt conform
  chore(test): Remove unit testing log output for success cases (#293)
  feat(project): Add GitHub Actions testing workflow (#289)
  feat(context): Add support for context package
  fix(issue): IssueService.Search() with a not empty JQL triggers 400 bad request (#292)
  feat(IssueService): allow empty JQL (#268)
  style: Fix staticcheck (static analysis) errors for this library (#283)
  feat(project): Add workflow to greet new contributors (#288)
  feat(project): Add cronjob to check for stale issues (#287)
  feat(issues): Add GetEditMeta on issue
  feat: Add Names support on Issue struct (#278)
  • Loading branch information
andygrunwald committed May 12, 2020
2 parents 2da7787 + f6b1dca commit adfb2db
Show file tree
Hide file tree
Showing 39 changed files with 1,157 additions and 375 deletions.
12 changes: 12 additions & 0 deletions .github/workflows/greetings.yml
Original file line number Diff line number Diff line change
@@ -0,0 +1,12 @@
name: Greetings
on: [pull_request, issues]

jobs:
greeting:
runs-on: ubuntu-latest
steps:
- uses: actions/first-interaction@v1
with:
repo-token: ${{ secrets.GITHUB_TOKEN }}
issue-message: 'Hi! Thank you for taking the time to create your first issue! Really cool to see you here for the first time. Please give us a bit of time to review it.'
pr-message: 'Great! Thank you for taking the time to create your first pull request. It is always a pleasure to see people like you who spent time contributing. Please give us a bit of time to review it!'
19 changes: 19 additions & 0 deletions .github/workflows/stale.yml
Original file line number Diff line number Diff line change
@@ -0,0 +1,19 @@
name: "Close stale issues"
on:
schedule:
- cron: "0 4 * * *"

jobs:
stale:
runs-on: ubuntu-latest
steps:
- uses: actions/[email protected]
with:
repo-token: ${{ secrets.GITHUB_TOKEN }}
stale-issue-message: >
This issue has been automatically marked as stale because it has not had
recent activity in the last 60 days. It will be closed in 7 days if no further activity occurs.
Thank you for your contributions.
days-before-stale: 60
days-before-close: 7
stale-issue-label: stale
43 changes: 43 additions & 0 deletions .github/workflows/testing.yml
Original file line number Diff line number Diff line change
@@ -0,0 +1,43 @@
name: Tests

on:
push:
branches:
- master
pull_request:

jobs:
test:
name: Test and lint
strategy:
matrix:
go-version: [1.x, 1.13.x, 1.12.x]
platform: [ubuntu-latest, windows-latest]
runs-on: ${{ matrix.platform }}

steps:
- uses: actions/checkout@v2
- uses: actions/setup-go@v2
with:
go-version: 1.14

# Caching go modules to speed up the run
- uses: actions/cache@v1
with:
path: ~/go/pkg/mod
key: ${{ runner.os }}-go-${{ hashFiles('**/go.sum') }}
restore-keys: |
${{ runner.os }}-go-
- name: Run go fmt
if: runner.os != 'Windows'
run: diff -u <(echo -n) <(gofmt -d -s .)

- name: Run go vet
run: make vet

- name: Run staticcheck
run: make staticcheck

- name: Run Unit tests.
run: make test
63 changes: 42 additions & 21 deletions authentication.go
Original file line number Diff line number Diff line change
@@ -1,6 +1,7 @@
package jira

import (
"context"
"encoding/json"
"fmt"
"io/ioutil"
Expand Down Expand Up @@ -47,7 +48,7 @@ type Session struct {
Cookies []*http.Cookie
}

// AcquireSessionCookie creates a new session for a user in Jira.
// AcquireSessionCookieWithContext creates a new session for a user in Jira.
// Once a session has been successfully created it can be used to access any of Jira's remote APIs and also the web UI by passing the appropriate HTTP Cookie header.
// The header will by automatically applied to every API request.
// Note that it is generally preferrable to use HTTP BASIC authentication with the REST API.
Expand All @@ -56,7 +57,7 @@ type Session struct {
// Jira API docs: https://docs.atlassian.com/jira/REST/latest/#auth/1/session
//
// Deprecated: Use CookieAuthTransport instead
func (s *AuthenticationService) AcquireSessionCookie(username, password string) (bool, error) {
func (s *AuthenticationService) AcquireSessionCookieWithContext(ctx context.Context, username, password string) (bool, error) {
apiEndpoint := "rest/auth/1/session"
body := struct {
Username string `json:"username"`
Expand All @@ -66,7 +67,7 @@ func (s *AuthenticationService) AcquireSessionCookie(username, password string)
password,
}

req, err := s.client.NewRequest("POST", apiEndpoint, body)
req, err := s.client.NewRequestWithContext(ctx, "POST", apiEndpoint, body)
if err != nil {
return false, err
}
Expand All @@ -79,10 +80,10 @@ func (s *AuthenticationService) AcquireSessionCookie(username, password string)
}

if err != nil {
return false, fmt.Errorf("Auth at Jira instance failed (HTTP(S) request). %s", err)
return false, fmt.Errorf("auth at Jira instance failed (HTTP(S) request). %s", err)
}
if resp != nil && resp.StatusCode != 200 {
return false, fmt.Errorf("Auth at Jira instance failed (HTTP(S) request). Status code: %d", resp.StatusCode)
return false, fmt.Errorf("auth at Jira instance failed (HTTP(S) request). Status code: %d", resp.StatusCode)
}

s.client.session = session
Expand All @@ -91,6 +92,13 @@ func (s *AuthenticationService) AcquireSessionCookie(username, password string)
return true, nil
}

// AcquireSessionCookie wraps AcquireSessionCookieWithContext using the background context.
//
// Deprecated: Use CookieAuthTransport instead
func (s *AuthenticationService) AcquireSessionCookie(username, password string) (bool, error) {
return s.AcquireSessionCookieWithContext(context.Background(), username, password)
}

// SetBasicAuth sets username and password for the basic auth against the Jira instance.
//
// Deprecated: Use BasicAuthTransport instead
Expand All @@ -113,29 +121,29 @@ func (s *AuthenticationService) Authenticated() bool {
return false
}

// Logout logs out the current user that has been authenticated and the session in the client is destroyed.
// LogoutWithContext logs out the current user that has been authenticated and the session in the client is destroyed.
//
// Jira API docs: https://docs.atlassian.com/jira/REST/latest/#auth/1/session
//
// Deprecated: Use CookieAuthTransport to create base client. Logging out is as simple as not using the
// client anymore
func (s *AuthenticationService) Logout() error {
func (s *AuthenticationService) LogoutWithContext(ctx context.Context) error {
if s.authType != authTypeSession || s.client.session == nil {
return fmt.Errorf("no user is authenticated")
}

apiEndpoint := "rest/auth/1/session"
req, err := s.client.NewRequest("DELETE", apiEndpoint, nil)
req, err := s.client.NewRequestWithContext(ctx, "DELETE", apiEndpoint, nil)
if err != nil {
return fmt.Errorf("Creating the request to log the user out failed : %s", err)
return fmt.Errorf("creating the request to log the user out failed : %s", err)
}

resp, err := s.client.Do(req, nil)
if err != nil {
return fmt.Errorf("Error sending the logout request: %s", err)
return fmt.Errorf("error sending the logout request: %s", err)
}
if resp.StatusCode != 204 {
return fmt.Errorf("The logout was unsuccessful with status %d", resp.StatusCode)
return fmt.Errorf("the logout was unsuccessful with status %d", resp.StatusCode)
}

// If logout successful, delete session
Expand All @@ -145,43 +153,56 @@ func (s *AuthenticationService) Logout() error {

}

// GetCurrentUser gets the details of the current user.
// Logout wraps LogoutWithContext using the background context.
//
// Deprecated: Use CookieAuthTransport to create base client. Logging out is as simple as not using the
// client anymore
func (s *AuthenticationService) Logout() error {
return s.LogoutWithContext(context.Background())
}

// GetCurrentUserWithContext gets the details of the current user.
//
// Jira API docs: https://docs.atlassian.com/jira/REST/latest/#auth/1/session
func (s *AuthenticationService) GetCurrentUser() (*Session, error) {
func (s *AuthenticationService) GetCurrentUserWithContext(ctx context.Context) (*Session, error) {
if s == nil {
return nil, fmt.Errorf("AUthenticaiton Service is not instantiated")
return nil, fmt.Errorf("authentication Service is not instantiated")
}
if s.authType != authTypeSession || s.client.session == nil {
return nil, fmt.Errorf("No user is authenticated yet")
return nil, fmt.Errorf("no user is authenticated yet")
}

apiEndpoint := "rest/auth/1/session"
req, err := s.client.NewRequest("GET", apiEndpoint, nil)
req, err := s.client.NewRequestWithContext(ctx, "GET", apiEndpoint, nil)
if err != nil {
return nil, fmt.Errorf("Could not create request for getting user info : %s", err)
return nil, fmt.Errorf("could not create request for getting user info : %s", err)
}

resp, err := s.client.Do(req, nil)
if err != nil {
return nil, fmt.Errorf("Error sending request to get user info : %s", err)
return nil, fmt.Errorf("error sending request to get user info : %s", err)
}
if resp.StatusCode != 200 {
return nil, fmt.Errorf("Getting user info failed with status : %d", resp.StatusCode)
return nil, fmt.Errorf("getting user info failed with status : %d", resp.StatusCode)
}

defer resp.Body.Close()
ret := new(Session)
data, err := ioutil.ReadAll(resp.Body)
if err != nil {
return nil, fmt.Errorf("Couldn't read body from the response : %s", err)
return nil, fmt.Errorf("couldn't read body from the response : %s", err)
}

err = json.Unmarshal(data, &ret)

if err != nil {
return nil, fmt.Errorf("Could not unmarshall received user info : %s", err)
return nil, fmt.Errorf("could not unmarshall received user info : %s", err)
}

return ret, nil
}

// GetCurrentUser wraps GetCurrentUserWithContext using the background context.
func (s *AuthenticationService) GetCurrentUser() (*Session, error) {
return s.GetCurrentUserWithContext(context.Background())
}
24 changes: 12 additions & 12 deletions authentication_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -19,10 +19,10 @@ func TestAuthenticationService_AcquireSessionCookie_Failure(t *testing.T) {
if err != nil {
t.Errorf("Error in read body: %s", err)
}
if bytes.Index(b, []byte(`"username":"foo"`)) < 0 {
if !bytes.Contains(b, []byte(`"username":"foo"`)) {
t.Error("No username found")
}
if bytes.Index(b, []byte(`"password":"bar"`)) < 0 {
if !bytes.Contains(b, []byte(`"password":"bar"`)) {
t.Error("No password found")
}

Expand Down Expand Up @@ -53,10 +53,10 @@ func TestAuthenticationService_AcquireSessionCookie_Success(t *testing.T) {
if err != nil {
t.Errorf("Error in read body: %s", err)
}
if bytes.Index(b, []byte(`"username":"foo"`)) < 0 {
if !bytes.Contains(b, []byte(`"username":"foo"`)) {
t.Error("No username found")
}
if bytes.Index(b, []byte(`"password":"bar"`)) < 0 {
if !bytes.Contains(b, []byte(`"password":"bar"`)) {
t.Error("No password found")
}

Expand Down Expand Up @@ -144,10 +144,10 @@ func TestAithenticationService_GetUserInfo_AccessForbidden_Fail(t *testing.T) {
if err != nil {
t.Errorf("Error in read body: %s", err)
}
if bytes.Index(b, []byte(`"username":"foo"`)) < 0 {
if !bytes.Contains(b, []byte(`"username":"foo"`)) {
t.Error("No username found")
}
if bytes.Index(b, []byte(`"password":"bar"`)) < 0 {
if !bytes.Contains(b, []byte(`"password":"bar"`)) {
t.Error("No password found")
}

Expand Down Expand Up @@ -182,10 +182,10 @@ func TestAuthenticationService_GetUserInfo_NonOkStatusCode_Fail(t *testing.T) {
if err != nil {
t.Errorf("Error in read body: %s", err)
}
if bytes.Index(b, []byte(`"username":"foo"`)) < 0 {
if !bytes.Contains(b, []byte(`"username":"foo"`)) {
t.Error("No username found")
}
if bytes.Index(b, []byte(`"password":"bar"`)) < 0 {
if !bytes.Contains(b, []byte(`"password":"bar"`)) {
t.Error("No password found")
}

Expand Down Expand Up @@ -238,10 +238,10 @@ func TestAuthenticationService_GetUserInfo_Success(t *testing.T) {
if err != nil {
t.Errorf("Error in read body: %s", err)
}
if bytes.Index(b, []byte(`"username":"foo"`)) < 0 {
if !bytes.Contains(b, []byte(`"username":"foo"`)) {
t.Error("No username found")
}
if bytes.Index(b, []byte(`"password":"bar"`)) < 0 {
if !bytes.Contains(b, []byte(`"password":"bar"`)) {
t.Error("No password found")
}

Expand Down Expand Up @@ -280,10 +280,10 @@ func TestAuthenticationService_Logout_Success(t *testing.T) {
if err != nil {
t.Errorf("Error in read body: %s", err)
}
if bytes.Index(b, []byte(`"username":"foo"`)) < 0 {
if !bytes.Contains(b, []byte(`"username":"foo"`)) {
t.Error("No username found")
}
if bytes.Index(b, []byte(`"password":"bar"`)) < 0 {
if !bytes.Contains(b, []byte(`"password":"bar"`)) {
t.Error("No password found")
}

Expand Down
Loading

0 comments on commit adfb2db

Please sign in to comment.