2015-09-03 12:25:21 +02:00
package jira
import (
2016-09-07 14:24:02 +02:00
"encoding/json"
2015-09-03 12:25:21 +02:00
"fmt"
2016-09-07 14:24:02 +02:00
"io/ioutil"
2016-05-27 12:01:54 +02:00
"net/http"
2015-09-03 12:25:21 +02:00
)
2017-02-09 00:37:57 +02:00
const (
// HTTP Basic Authentication
authTypeBasic = 1
// HTTP Session Authentication
authTypeSession = 2
)
2015-09-03 12:25:21 +02:00
// AuthenticationService handles authentication for the JIRA instance / API.
//
// JIRA API docs: https://docs.atlassian.com/jira/REST/latest/#authentication
type AuthenticationService struct {
client * Client
2017-02-09 00:37:57 +02:00
// Authentication type
authType int
// Basic auth username
username string
// Basic auth password
password string
2015-09-03 12:25:21 +02:00
}
// Session represents a Session JSON response by the JIRA API.
type Session struct {
2016-06-03 23:14:27 +02:00
Self string ` json:"self,omitempty" `
Name string ` json:"name,omitempty" `
Session struct {
2015-09-03 12:25:21 +02:00
Name string ` json:"name" `
Value string ` json:"value" `
} ` json:"session,omitempty" `
LoginInfo struct {
FailedLoginCount int ` json:"failedLoginCount" `
LoginCount int ` json:"loginCount" `
LastFailedLoginTime string ` json:"lastFailedLoginTime" `
PreviousLoginTime string ` json:"previousLoginTime" `
} ` json:"loginInfo" `
2016-06-03 23:14:27 +02:00
Cookies [ ] * http . Cookie
2015-09-03 12:25:21 +02:00
}
// AcquireSessionCookie 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.
// However, this resource may be used to mimic the behaviour of JIRA's log-in page (e.g. to display log-in errors to a user).
//
2016-03-27 14:24:48 +02:00
// JIRA API docs: https://docs.atlassian.com/jira/REST/latest/#auth/1/session
2015-09-03 12:25:21 +02:00
func ( s * AuthenticationService ) AcquireSessionCookie ( username , password string ) ( bool , error ) {
apiEndpoint := "rest/auth/1/session"
body := struct {
Username string ` json:"username" `
Password string ` json:"password" `
} {
username ,
password ,
}
req , err := s . client . NewRequest ( "POST" , apiEndpoint , body )
if err != nil {
return false , err
}
session := new ( Session )
resp , err := s . client . Do ( req , session )
2016-08-16 19:56:26 +02:00
2016-09-07 14:24:02 +02:00
if resp != nil {
session . Cookies = resp . Cookies ( )
}
2016-05-27 12:01:54 +02:00
2016-04-23 15:23:15 +02:00
if err != nil {
2015-09-03 12:25:21 +02:00
return false , fmt . Errorf ( "Auth at JIRA instance failed (HTTP(S) request). %s" , err )
}
2016-04-23 15:23:15 +02:00
if resp != nil && resp . StatusCode != 200 {
return false , fmt . Errorf ( "Auth at JIRA instance failed (HTTP(S) request). Status code: %d" , resp . StatusCode )
}
2015-09-03 12:25:21 +02:00
s . client . session = session
2017-02-09 00:37:57 +02:00
s . authType = authTypeSession
2015-09-03 12:25:21 +02:00
return true , nil
}
2017-05-01 15:06:18 +02:00
// SetBasicAuth sets username and password for the basic auth against the JIRA instance.
2017-02-09 00:37:57 +02:00
func ( s * AuthenticationService ) SetBasicAuth ( username , password string ) {
2017-05-01 14:59:27 +02:00
s . username = username
s . password = password
s . authType = authTypeBasic
2017-02-09 00:37:57 +02:00
}
// Authenticated reports if the current Client has authentication details for JIRA
2016-06-01 14:52:52 +02:00
func ( s * AuthenticationService ) Authenticated ( ) bool {
if s != nil {
2017-02-09 00:37:57 +02:00
if s . authType == authTypeSession {
return s . client . session != nil
} else if s . authType == authTypeBasic {
return s . username != ""
}
2016-06-01 14:52:52 +02:00
}
return false
}
2016-09-07 14:24:02 +02:00
// Logout 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
func ( s * AuthenticationService ) Logout ( ) error {
2017-02-09 00:37:57 +02:00
if s . authType != authTypeSession || s . client . session == nil {
2016-09-07 14:24:02 +02:00
return fmt . Errorf ( "No user is authenticated yet." )
}
apiEndpoint := "rest/auth/1/session"
req , err := s . client . NewRequest ( "DELETE" , apiEndpoint , nil )
if err != nil {
return fmt . Errorf ( "Creating the request to log the user out failed : %s" , err )
}
2016-10-03 13:33:46 +02:00
2016-09-07 14:24:02 +02:00
resp , err := s . client . Do ( req , nil )
if err != nil {
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 )
}
2017-05-01 15:03:03 +02:00
// If logout successful, delete session
2016-09-07 14:24:02 +02:00
s . client . session = nil
return nil
}
// GetCurrentUser 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 ) {
if s == nil {
return nil , fmt . Errorf ( "AUthenticaiton Service is not instantiated" )
}
2017-02-09 00:37:57 +02:00
if s . authType != authTypeSession || s . client . session == nil {
2016-09-07 14:24:02 +02:00
return nil , fmt . Errorf ( "No user is authenticated yet" )
}
apiEndpoint := "rest/auth/1/session"
req , err := s . client . NewRequest ( "GET" , apiEndpoint , nil )
if err != nil {
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 )
}
2016-09-27 13:26:07 +02:00
if resp . StatusCode != 200 {
return nil , fmt . Errorf ( "Getting user info failed with status : %d" , resp . StatusCode )
}
2016-09-07 14:24:02 +02:00
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 )
}
err = json . Unmarshal ( data , & ret )
if err != nil {
2017-05-01 14:59:27 +02:00
return nil , fmt . Errorf ( "Could not unmarshall received user info : %s" , err )
2016-09-07 14:24:02 +02:00
}
return ret , nil
}