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
AuthUsername string // User for user impersonation
AuthMemberHash string //Used for user impersonation
CompanyName string //Used for user impersonation
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
2018-07-07 00:29:53 +00:00
func NewSite ( site string , publicKey string , privateKey string , company 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 )
2018-07-27 03:30:23 +00:00
cwSite := Site { Site : site , AuthAPIKey : authString }
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
func NewSiteUserImpersonation ( site string , username string , password string , company string ) ( * Site , error ) {
//Need to post formdata to https://ndconnect.nextdigital.ca/v4_6_release/login/login.aspx
//username
//password
//companyname
//Will then receive a hash
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"
client := & http . Client { }
authReq , err := http . NewRequest ( "POST" , authURL . String ( ) , nil )
if err != nil {
return nil , fmt . Errorf ( "could not construct http request: %s" , err )
}
form := url . Values { }
form . Add ( "username" , username )
form . Add ( "password" , password )
form . Add ( "companyname" , company )
authReq . PostForm = form
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 )
}
cwSite := Site { Site : site , AuthUsername : username , AuthMemberHash : string ( body ) , CompanyName : company }
return & cwSite , nil
}