1
0
mirror of https://github.com/interviewstreet/go-jira.git synced 2025-02-09 13:36:58 +02:00

Merge pull request #62 from fkrauthan/master

Added basic auth support to the library
This commit is contained in:
Andy Grunwald 2017-02-12 12:51:59 +01:00 committed by GitHub
commit 3a142b6278
5 changed files with 198 additions and 17 deletions

View File

@ -70,9 +70,41 @@ func main() {
}
```
### Authenticate with session cookie
### Authenticate with jira
Some actions require an authenticated user.
#### Authenticate with basic auth
Here is an example with a basic auth authentification.
```go
package main
import (
"fmt"
"github.com/andygrunwald/go-jira"
)
func main() {
jiraClient, err := jira.NewClient(nil, "https://your.jira-instance.com/")
if err != nil {
panic(err)
}
jiraClient.Authentication.SetBasicAuth("username", "password")
issue, _, err := jiraClient.Issue.Get("SYS-5156", nil)
if err != nil {
panic(err)
}
fmt.Printf("%s: %+v\n", issue.Key, issue.Fields.Summary)
}
```
#### Authenticate with session cookie
Here is an example with a session cookie authentification.
```go

View File

@ -7,11 +7,27 @@ import (
"net/http"
)
const (
// HTTP Basic Authentication
authTypeBasic = 1
// HTTP Session Authentication
authTypeSession = 2
)
// AuthenticationService handles authentication for the JIRA instance / API.
//
// JIRA API docs: https://docs.atlassian.com/jira/REST/latest/#authentication
type AuthenticationService struct {
client *Client
// Authentication type
authType int
// Basic auth username
username string
// Basic auth password
password string
}
// Session represents a Session JSON response by the JIRA API.
@ -68,14 +84,26 @@ func (s *AuthenticationService) AcquireSessionCookie(username, password string)
}
s.client.session = session
s.authType = authTypeSession
return true, nil
}
// Authenticated reports if the current Client has an authenticated session with JIRA
func (s *AuthenticationService) SetBasicAuth(username, password string) {
s.username = username;
s.password = password;
s.authType = authTypeBasic;
}
// Authenticated reports if the current Client has authentication details for JIRA
func (s *AuthenticationService) Authenticated() bool {
if s != nil {
return s.client.session != nil
if s.authType == authTypeSession {
return s.client.session != nil
} else if s.authType == authTypeBasic {
return s.username != ""
}
}
return false
}
@ -84,7 +112,7 @@ func (s *AuthenticationService) Authenticated() bool {
//
// JIRA API docs: https://docs.atlassian.com/jira/REST/latest/#auth/1/session
func (s *AuthenticationService) Logout() error {
if s.client.session == nil {
if s.authType != authTypeSession || s.client.session == nil {
return fmt.Errorf("No user is authenticated yet.")
}
@ -116,7 +144,7 @@ func (s *AuthenticationService) GetCurrentUser() (*Session, error) {
if s == nil {
return nil, fmt.Errorf("AUthenticaiton Service is not instantiated")
}
if s.client.session == nil {
if s.authType != authTypeSession || s.client.session == nil {
return nil, fmt.Errorf("No user is authenticated yet")
}

View File

@ -74,6 +74,29 @@ func TestAuthenticationService_AcquireSessionCookie_Success(t *testing.T) {
if testClient.Authentication.Authenticated() != true {
t.Error("Expected true, but result was false")
}
if testClient.Authentication.authType != authTypeSession {
t.Error("Expected authType %d. Got %d", authTypeSession, testClient.Authentication.authType)
}
}
func TestAuthenticationService_SetBasicAuth(t *testing.T) {
setup()
defer teardown()
testClient.Authentication.SetBasicAuth("test-user", "test-password")
if testClient.Authentication.username != "test-user" {
t.Error("Expected username test-user. Got %s", testClient.Authentication.username)
}
if testClient.Authentication.password != "test-password" {
t.Error("Expected password test-password. Got %s", testClient.Authentication.password)
}
if testClient.Authentication.authType != authTypeBasic {
t.Error("Expected authType %d. Got %d", authTypeBasic, testClient.Authentication.authType)
}
}
func TestAuthenticationService_Authenticated(t *testing.T) {
@ -86,6 +109,30 @@ func TestAuthenticationService_Authenticated(t *testing.T) {
}
}
func TestAuthenticationService_Authenticated_WithBasicAuth(t *testing.T) {
setup()
defer teardown()
testClient.Authentication.SetBasicAuth("test-user", "test-password")
// Test before we've attempted to authenticate
if testClient.Authentication.Authenticated() != true {
t.Error("Expected true, but result was false")
}
}
func TestAuthenticationService_Authenticated_WithBasicAuthButNoUsername(t *testing.T) {
setup()
defer teardown()
testClient.Authentication.SetBasicAuth("", "test-password")
// Test before we've attempted to authenticate
if testClient.Authentication.Authenticated() != false {
t.Error("Expected false, but result was true")
}
}
func TestAithenticationService_GetUserInfo_AccessForbidden_Fail(t *testing.T) {
setup()
defer teardown()

48
jira.go
View File

@ -84,10 +84,18 @@ func (c *Client) NewRawRequest(method, urlStr string, body io.Reader) (*http.Req
req.Header.Set("Content-Type", "application/json")
// Set session cookie if there is one
if c.session != nil {
for _, cookie := range c.session.Cookies {
req.AddCookie(cookie)
// Set authentication information
if c.Authentication.authType == authTypeSession {
// Set session cookie if there is one
if c.session != nil {
for _, cookie := range c.session.Cookies {
req.AddCookie(cookie)
}
}
} else if c.Authentication.authType == authTypeBasic {
// Set basic auth information
if c.Authentication.username != "" {
req.SetBasicAuth(c.Authentication.username, c.Authentication.password)
}
}
@ -122,10 +130,18 @@ func (c *Client) NewRequest(method, urlStr string, body interface{}) (*http.Requ
req.Header.Set("Content-Type", "application/json")
// Set session cookie if there is one
if c.session != nil {
for _, cookie := range c.session.Cookies {
req.AddCookie(cookie)
// Set authentication information
if c.Authentication.authType == authTypeSession {
// Set session cookie if there is one
if c.session != nil {
for _, cookie := range c.session.Cookies {
req.AddCookie(cookie)
}
}
} else if c.Authentication.authType == authTypeBasic {
// Set basic auth information
if c.Authentication.username != "" {
req.SetBasicAuth(c.Authentication.username, c.Authentication.password)
}
}
@ -174,10 +190,18 @@ func (c *Client) NewMultiPartRequest(method, urlStr string, buf *bytes.Buffer) (
// Set required headers
req.Header.Set("X-Atlassian-Token", "nocheck")
// Set session cookie if there is one
if c.session != nil {
for _, cookie := range c.session.Cookies {
req.AddCookie(cookie)
// Set authentication information
if c.Authentication.authType == authTypeSession {
// Set session cookie if there is one
if c.session != nil {
for _, cookie := range c.session.Cookies {
req.AddCookie(cookie)
}
}
} else if c.Authentication.authType == authTypeBasic {
// Set basic auth information
if c.Authentication.username != "" {
req.SetBasicAuth(c.Authentication.username, c.Authentication.password)
}
}

View File

@ -201,6 +201,7 @@ func TestClient_NewRequest_SessionCookies(t *testing.T) {
cookie := &http.Cookie{Name: "testcookie", Value: "testvalue"}
c.session = &Session{Cookies: []*http.Cookie{cookie}}
c.Authentication.authType = authTypeSession
inURL := "rest/api/2/issue/"
inBody := &Issue{Key: "MESOS"}
@ -221,6 +222,28 @@ func TestClient_NewRequest_SessionCookies(t *testing.T) {
}
}
func TestClient_NewRequest_BasicAuth(t *testing.T) {
c, err := NewClient(nil, testJIRAInstanceURL)
if err != nil {
t.Errorf("An error occured. Expected nil. Got %+v.", err)
}
c.Authentication.SetBasicAuth("test-user", "test-password")
inURL := "rest/api/2/issue/"
inBody := &Issue{Key: "MESOS"}
req, err := c.NewRequest("GET", inURL, inBody)
if err != nil {
t.Errorf("An error occured. Expected nil. Got %+v.", err)
}
username, password, ok := req.BasicAuth()
if !ok || username != "test-user" || password != "test-password" {
t.Errorf("An error occured. Expected basic auth username %s and password %s. Got username %s and password %s.", "test-user", "test-password", username, password)
}
}
// If a nil body is passed to gerrit.NewRequest, make sure that nil is also passed to http.NewRequest.
// In most cases, passing an io.Reader that returns no content is fine,
// since there is no difference between an HTTP request body that is an empty string versus one that is not set at all.
@ -247,6 +270,7 @@ func TestClient_NewMultiPartRequest(t *testing.T) {
cookie := &http.Cookie{Name: "testcookie", Value: "testvalue"}
c.session = &Session{Cookies: []*http.Cookie{cookie}}
c.Authentication.authType = authTypeSession
inURL := "rest/api/2/issue/"
inBuf := bytes.NewBufferString("teststring")
@ -271,6 +295,32 @@ func TestClient_NewMultiPartRequest(t *testing.T) {
}
}
func TestClient_NewMultiPartRequest_BasicAuth(t *testing.T) {
c, err := NewClient(nil, testJIRAInstanceURL)
if err != nil {
t.Errorf("An error occured. Expected nil. Got %+v.", err)
}
c.Authentication.SetBasicAuth("test-user", "test-password")
inURL := "rest/api/2/issue/"
inBuf := bytes.NewBufferString("teststring")
req, err := c.NewMultiPartRequest("GET", inURL, inBuf)
if err != nil {
t.Errorf("An error occured. Expected nil. Got %+v.", err)
}
username, password, ok := req.BasicAuth()
if !ok || username != "test-user" || password != "test-password" {
t.Errorf("An error occured. Expected basic auth username %s and password %s. Got username %s and password %s.", "test-user", "test-password", username, password)
}
if req.Header.Get("X-Atlassian-Token") != "nocheck" {
t.Errorf("An error occured. Unexpected X-Atlassian-Token header value. Expected nocheck, actual %s.", req.Header.Get("X-Atlassian-Token"))
}
}
func TestClient_Do(t *testing.T) {
setup()
defer teardown()