go-cw/3.0/connectwise/connectwise.go

91 lines
2.9 KiB
Go

package connectwise
import (
"encoding/base64"
"fmt"
"io/ioutil"
"net/http"
"net/url"
"strings"
)
//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 {
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
}
//Count is a struct used for unmarshalling JSON data when using the Count endpoints in Connectwise (eg: counting number of companies)
type Count struct {
Count int `json:"count"`
}
//NewSite returns a pointer to a ConnectwiseSite struct with the site and auth string available for use in API requests
func NewSite(site string, publicKey string, privateKey string, company string) *Site {
//The auth string must be formatted in this way when used in requests to the API
authString := fmt.Sprintf("%s+%s:%s", company, publicKey, privateKey)
authString = base64.StdEncoding.EncodeToString([]byte(authString))
authString = fmt.Sprintf("Basic %s", authString)
cwSite := Site{Site: site, AuthAPIKey: authString}
return &cwSite
}
//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
}