2018-06-20 16:55:53 +00:00
package connectwise
import (
"encoding/base64"
"fmt"
2018-07-27 03:30:23 +00:00
"io/ioutil"
"net/http"
"net/url"
"strings"
2018-06-20 16:55:53 +00:00
)
2018-07-07 00:29:53 +00:00
//Site is a stuct containing the URL of the site and the API authorization token in the format that CW expects it.
type Site struct {
2018-07-27 03:30:23 +00:00
Site string
AuthAPIKey string //Preferable authentication method
2018-08-14 04:58:21 +00:00
CompanyName string //Used for user impersonation, but collected for API key as well so it can be accessed publicly later on if required
2018-07-27 03:30:23 +00:00
AuthUsername string // User for user impersonation
AuthMemberHash string //Used for user impersonation
2019-02-13 15:29:00 +00:00
ClientID string // Required as of 2019.02 https://developer.connectwise.com/ClientID
2018-08-14 04:58:21 +00:00
2018-06-20 16:55:53 +00:00
}
2018-07-08 17:21:07 +00:00
//Count is a struct used for unmarshalling JSON data when using the Count endpoints in Connectwise (eg: counting number of companies)
2018-07-08 06:59:32 +00:00
type Count struct {
Count int ` json:"count" `
}
2018-06-29 01:35:34 +00:00
//NewSite returns a pointer to a ConnectwiseSite struct with the site and auth string available for use in API requests
2019-02-13 15:29:00 +00:00
func NewSite ( site , publicKey , privateKey , company , clientID string ) * Site {
2018-06-23 00:47:39 +00:00
//The auth string must be formatted in this way when used in requests to the API
2018-06-20 16:55:53 +00:00
authString := fmt . Sprintf ( "%s+%s:%s" , company , publicKey , privateKey )
authString = base64 . StdEncoding . EncodeToString ( [ ] byte ( authString ) )
authString = fmt . Sprintf ( "Basic %s" , authString )
2019-02-13 15:29:00 +00:00
cwSite := Site { Site : site , AuthAPIKey : authString , CompanyName : company , ClientID : clientID }
2018-06-20 16:55:53 +00:00
return & cwSite
}
2018-07-27 03:30:23 +00:00
//NewSiteUserImpersonation is similar to NewSite but is used for user impersonation and instead of an API key takes the username and password
2019-02-13 15:29:00 +00:00
func NewSiteUserImpersonation ( site , username , password , company , clientID string ) ( * Site , error ) {
2018-07-27 03:30:23 +00:00
2018-07-27 04:31:47 +00:00
//We must retrieve a user hash which is good for 4 hours
2018-07-27 03:30:23 +00:00
authBaseURL := strings . TrimSuffix ( site , "/apis/3.0" )
authURL , err := url . Parse ( authBaseURL )
if err != nil {
return nil , fmt . Errorf ( "could not build url %s: %s" , authBaseURL , err )
}
authURL . Path += "/login/login.aspx"
2018-07-27 04:31:47 +00:00
form := url . Values { }
form . Add ( "username" , username )
form . Add ( "password" , password )
form . Add ( "companyname" , company )
2018-07-27 03:30:23 +00:00
client := & http . Client { }
2018-07-27 04:31:47 +00:00
authReq , err := http . NewRequest ( "POST" , authURL . String ( ) , strings . NewReader ( form . Encode ( ) ) )
2018-07-27 03:30:23 +00:00
if err != nil {
return nil , fmt . Errorf ( "could not construct http request: %s" , err )
}
authReq . Header . Set ( "Content-Type" , "application/x-www-form-urlencoded" )
resp , err := client . Do ( authReq )
if err != nil {
return nil , fmt . Errorf ( "could not perform http authentication request: %s" , err )
}
if resp . StatusCode != http . StatusOK {
return nil , fmt . Errorf ( "cw api returned unexpected http status %d - %s" , resp . StatusCode , resp . Status )
}
defer resp . Body . Close ( )
body , err := ioutil . ReadAll ( resp . Body )
if err != nil {
return nil , fmt . Errorf ( "could not read response body of request" )
}
if string ( body ) == "" {
return nil , fmt . Errorf ( "could not authenticate with connectwise as %s: authentication request sent to connectwise, but response body was empty" , username )
}
2018-07-27 04:31:47 +00:00
if string ( body ) == "CompanyFAIL" {
return nil , fmt . Errorf ( "could not authenticate with connectwise as %s: connectwise response body is %s" , username , string ( body ) )
}
2019-02-13 15:29:00 +00:00
cwSite := Site { Site : site , AuthUsername : username , AuthMemberHash : string ( body ) , CompanyName : company , ClientID : clientID }
2018-07-27 03:30:23 +00:00
return & cwSite , nil
}