package statuscake
import (
"encoding/json"
"fmt"
"net/url"
"strconv"
"strings"
"github.com/google/go-querystring/query"
)
//Ssl represent the data received by the API with GET
type Ssl struct {
ID string `json:"id" url:"id,omitempty"`
Domain string `json:"domain" url:"domain,omitempty"`
Checkrate int `json:"checkrate" url:"checkrate,omitempty"`
ContactGroupsC string ` url:"contact_groups,omitempty"`
AlertAt string `json:"alert_at" url:"alert_at,omitempty"`
AlertReminder bool `json:"alert_reminder" url:"alert_expiry,omitempty"`
AlertExpiry bool `json:"alert_expiry" url:"alert_reminder,omitempty"`
AlertBroken bool `json:"alert_broken" url:"alert_broken,omitempty"`
AlertMixed bool `json:"alert_mixed" url:"alert_mixed,omitempty"`
Paused bool `json:"paused"`
IssuerCn string `json:"issuer_cn"`
CertScore string `json:"cert_score"`
CipherScore string `json:"cipher_score"`
CertStatus string `json:"cert_status"`
Cipher string `json:"cipher"`
ValidFromUtc string `json:"valid_from_utc"`
ValidUntilUtc string `json:"valid_until_utc"`
MixedContent []map[string]string `json:"mixed_content"`
Flags map[string]bool `json:"flags"`
ContactGroups []string `json:"contact_groups"`
LastReminder int `json:"last_reminder"`
LastUpdatedUtc string `json:"last_updated_utc"`
}
//PartialSsl represent a ssl test creation or modification
type PartialSsl struct {
ID int
Domain string
Checkrate string
ContactGroupsC string
AlertAt string
AlertExpiry bool
AlertReminder bool
AlertBroken bool
AlertMixed bool
}
type createSsl struct {
ID int `url:"id,omitempty"`
Domain string `url:"domain" json:"domain"`
Checkrate jsonNumberString `url:"checkrate" json:"checkrate"`
ContactGroupsC string `url:"contact_groups" json:"contact_groups"`
AlertAt string `url:"alert_at" json:"alert_at"`
AlertExpiry bool `url:"alert_expiry" json:"alert_expiry"`
AlertReminder bool `url:"alert_reminder" json:"alert_reminder"`
AlertBroken bool `url:"alert_broken" json:"alert_broken"`
AlertMixed bool `url:"alert_mixed" json:"alert_mixed"`
}
func (cs *createSsl) fromPartial(p *PartialSsl) {
cs.ID = p.ID
cs.Domain = p.Domain
cs.Checkrate = jsonNumberString(p.Checkrate)
cs.ContactGroupsC = p.ContactGroupsC
cs.AlertAt = p.AlertAt
cs.AlertExpiry = p.AlertExpiry
cs.AlertReminder = p.AlertReminder
cs.AlertBroken = p.AlertBroken
cs.AlertMixed = p.AlertMixed
}
func (cs *createSsl) toPartial(p *PartialSsl) {
p.ID = cs.ID
p.Domain = cs.Domain
p.Checkrate = string(cs.Checkrate)
p.ContactGroupsC = cs.ContactGroupsC
p.AlertAt = cs.AlertAt
p.AlertExpiry = cs.AlertExpiry
p.AlertReminder = cs.AlertReminder
p.AlertBroken = cs.AlertBroken
p.AlertMixed = cs.AlertMixed
}
type updateSsl struct {
ID int `url:"id"`
Domain string `url:"domain" json:"domain"`
Checkrate jsonNumberString `url:"checkrate" json:"checkrate"`
ContactGroupsC string `url:"contact_groups" json:"contact_groups"`
AlertAt string `url:"alert_at" json:"alert_at"`
AlertExpiry bool `url:"alert_expiry" json:"alert_expiry"`
AlertReminder bool `url:"alert_reminder" json:"alert_reminder"`
AlertBroken bool `url:"alert_broken" json:"alert_broken"`
AlertMixed bool `url:"alert_mixed" json:"alert_mixed"`
}
func (us *updateSsl) fromPartial(p *PartialSsl) {
us.ID = p.ID
us.Domain = p.Domain
us.Checkrate = jsonNumberString(p.Checkrate)
us.ContactGroupsC = p.ContactGroupsC
us.AlertAt = p.AlertAt
us.AlertExpiry = p.AlertExpiry
us.AlertReminder = p.AlertReminder
us.AlertBroken = p.AlertBroken
us.AlertMixed = p.AlertMixed
}
func (us *updateSsl) toPartial(p *PartialSsl) {
p.ID = us.ID
p.Domain = us.Domain
p.Checkrate = string(us.Checkrate)
p.ContactGroupsC = us.ContactGroupsC
p.AlertAt = us.AlertAt
p.AlertExpiry = us.AlertExpiry
p.AlertReminder = us.AlertReminder
p.AlertBroken = us.AlertBroken
p.AlertMixed = us.AlertMixed
}
type sslUpdateResponse struct {
Success bool `json:"Success"`
Message interface{} `json:"Message"`
}
type sslCreateResponse struct {
Success bool `json:"Success"`
Message interface{} `json:"Message"`
Input createSsl `json:"Input"`
}
//Ssls represent the actions done with the API
type Ssls interface {
All() ([]*Ssl, error)
completeSsl(*PartialSsl) (*Ssl, error)
Detail(string) (*Ssl, error)
Update(*PartialSsl) (*Ssl, error)
UpdatePartial(*PartialSsl) (*PartialSsl, error)
Delete(ID string) error
CreatePartial(*PartialSsl) (*PartialSsl, error)
Create(*PartialSsl) (*Ssl, error)
}
func consolidateSsl(s *Ssl) {
(*s).ContactGroupsC = strings.Trim(strings.Join(strings.Fields(fmt.Sprint((*s).ContactGroups)), ","), "[]")
}
func findSsl(responses []*Ssl, id string) (*Ssl, error) {
var response *Ssl
for _, elem := range responses {
if (*elem).ID == id {
return elem, nil
}
}
return response, fmt.Errorf("%s Not found", id)
}
func (tt *ssls) completeSsl(s *PartialSsl) (*Ssl, error) {
full, err := tt.Detail(strconv.Itoa((*s).ID))
if err != nil {
return nil, err
}
(*full).ContactGroups = strings.Split((*s).ContactGroupsC, ",")
return full, nil
}
//Partial return a PartialSsl corresponding to the Ssl
func Partial(s *Ssl) (*PartialSsl, error) {
if s == nil {
return nil, fmt.Errorf("s is nil")
}
id, err := strconv.Atoi(s.ID)
if err != nil {
return nil, err
}
return &PartialSsl{
ID: id,
Domain: s.Domain,
Checkrate: strconv.Itoa(s.Checkrate),
ContactGroupsC: s.ContactGroupsC,
AlertReminder: s.AlertReminder,
AlertExpiry: s.AlertExpiry,
AlertBroken: s.AlertBroken,
AlertMixed: s.AlertMixed,
AlertAt: s.AlertAt,
}, nil
}
type ssls struct {
client apiClient
}
//NewSsls return a new ssls
func NewSsls(c apiClient) Ssls {
return &ssls{
client: c,
}
}
//All return a list of all the ssl from the API
func (tt *ssls) All() ([]*Ssl, error) {
rawResponse, err := tt.client.get("/SSL", nil)
if err != nil {
return nil, fmt.Errorf("Error getting StatusCake Ssl: %s", err.Error())
}
var getResponse []*Ssl
err = json.NewDecoder(rawResponse.Body).Decode(&getResponse)
if err != nil {
return nil, err
}
for ssl := range getResponse {
consolidateSsl(getResponse[ssl])
}
return getResponse, err
}
//Detail return the ssl corresponding to the id
func (tt *ssls) Detail(id string) (*Ssl, error) {
responses, err := tt.All()
if err != nil {
return nil, err
}
mySsl, errF := findSsl(responses, id)
if errF != nil {
return nil, errF
}
return mySsl, nil
}
//Update update the API with s and create one if s.ID=0 then return the corresponding Ssl
func (tt *ssls) Update(s *PartialSsl) (*Ssl, error) {
var err error
s, err = tt.UpdatePartial(s)
if err != nil {
return nil, err
}
return tt.completeSsl(s)
}
//UpdatePartial update the API with s and create one if s.ID=0 then return the corresponding PartialSsl
func (tt *ssls) UpdatePartial(s *PartialSsl) (*PartialSsl, error) {
if (*s).ID == 0 {
return tt.CreatePartial(s)
}
var v url.Values
{
us := updateSsl{}
us.fromPartial(s)
v, _ = query.Values(us)
}
rawResponse, err := tt.client.put("/SSL/Update", v)
if err != nil {
return nil, fmt.Errorf("Error creating StatusCake Ssl: %s", err.Error())
}
var updateResponse sslUpdateResponse
err = json.NewDecoder(rawResponse.Body).Decode(&updateResponse)
if err != nil {
return nil, err
}
if !updateResponse.Success {
return nil, fmt.Errorf("%s", updateResponse.Message.(string))
}
return s, nil
}
//Delete delete the ssl which ID is id
func (tt *ssls) Delete(id string) error {
_, err := tt.client.delete("/SSL/Update", url.Values{"id": {fmt.Sprint(id)}})
if err != nil {
return err
}
return nil
}
//Create create the ssl with the data in s and return the Ssl created
func (tt *ssls) Create(s *PartialSsl) (*Ssl, error) {
var err error
s, err = tt.CreatePartial(s)
if err != nil {
return nil, err
}
return tt.completeSsl(s)
}
//CreatePartial create the ssl with the data in s and return the PartialSsl created
func (tt *ssls) CreatePartial(s *PartialSsl) (*PartialSsl, error) {
(*s).ID = 0
var v url.Values
{
cs := createSsl{}
cs.fromPartial(s)
v, _ = query.Values(cs)
}
rawResponse, err := tt.client.put("/SSL/Update", v)
if err != nil {
return nil, fmt.Errorf("Error creating StatusCake Ssl: %s", err.Error())
}
var createResponse sslCreateResponse
err = json.NewDecoder(rawResponse.Body).Decode(&createResponse)
if err != nil {
return nil, err
}
if !createResponse.Success {
return nil, fmt.Errorf("%s", createResponse.Message.(string))
}
createResponse.Input.toPartial(s)
(*s).ID = int(createResponse.Message.(float64))
return s, nil
}