2014-03-25 03:31:33 +00:00
|
|
|
package models
|
|
|
|
|
|
|
|
import (
|
2015-02-21 06:11:22 +00:00
|
|
|
"errors"
|
2014-03-25 03:31:33 +00:00
|
|
|
"fmt"
|
|
|
|
"time"
|
2014-06-03 18:27:20 +00:00
|
|
|
|
|
|
|
"github.com/jinzhu/gorm"
|
2014-03-25 03:31:33 +00:00
|
|
|
)
|
|
|
|
|
|
|
|
//Campaign is a struct representing a created campaign
|
|
|
|
type Campaign struct {
|
2016-02-22 03:09:14 +00:00
|
|
|
Id int64 `json:"id"`
|
|
|
|
UserId int64 `json:"-"`
|
|
|
|
Name string `json:"name" sql:"not null"`
|
|
|
|
CreatedDate time.Time `json:"created_date"`
|
|
|
|
CompletedDate time.Time `json:"completed_date"`
|
|
|
|
TemplateId int64 `json:"-"`
|
|
|
|
Template Template `json:"template"`
|
|
|
|
PageId int64 `json:"-"`
|
|
|
|
Page Page `json:"page"`
|
|
|
|
Status string `json:"status"`
|
|
|
|
Results []Result `json:"results,omitempty"`
|
|
|
|
Groups []Group `json:"groups,omitempty"`
|
|
|
|
Events []Event `json:"timeline,omitemtpy"`
|
|
|
|
SMTPId int64 `json:"-"`
|
|
|
|
SMTP SMTP `json:"smtp"`
|
|
|
|
URL string `json:"url"`
|
2014-06-03 18:27:20 +00:00
|
|
|
}
|
|
|
|
|
2015-02-21 06:11:22 +00:00
|
|
|
// ErrCampaignNameNotSpecified indicates there was no template given by the user
|
|
|
|
var ErrCampaignNameNotSpecified = errors.New("Campaign name not specified")
|
|
|
|
|
|
|
|
// ErrGroupNotSpecified indicates there was no template given by the user
|
|
|
|
var ErrGroupNotSpecified = errors.New("No groups specified")
|
|
|
|
|
|
|
|
// ErrTemplateNotSpecified indicates there was no template given by the user
|
|
|
|
var ErrTemplateNotSpecified = errors.New("No email template specified")
|
|
|
|
|
2015-10-23 03:29:10 +00:00
|
|
|
// ErrPageNotSpecified indicates a landing page was not provided for the campaign
|
|
|
|
var ErrPageNotSpecified = errors.New("No landing page specified")
|
|
|
|
|
2016-02-21 18:05:40 +00:00
|
|
|
// ErrSMTPNotSpecified indicates a sending profile was not provided for the campaign
|
|
|
|
var ErrSMTPNotSpecified = errors.New("No sending profile specified")
|
|
|
|
|
2015-02-21 06:11:22 +00:00
|
|
|
// ErrTemplateNotFound indicates the template specified does not exist in the database
|
|
|
|
var ErrTemplateNotFound = errors.New("Template not found")
|
|
|
|
|
|
|
|
// ErrGroupnNotFound indicates a group specified by the user does not exist in the database
|
|
|
|
var ErrGroupNotFound = errors.New("Group not found")
|
|
|
|
|
2015-10-23 03:29:10 +00:00
|
|
|
// ErrPageNotFound indicates a page specified by the user does not exist in the database
|
|
|
|
var ErrPageNotFound = errors.New("Page not found")
|
|
|
|
|
2016-02-21 18:05:40 +00:00
|
|
|
// ErrSMTPNotFound indicates a sending profile specified by the user does not exist in the database
|
|
|
|
var ErrSMTPNotFound = errors.New("Sending profile not found")
|
|
|
|
|
2015-02-07 16:41:53 +00:00
|
|
|
// Validate checks to make sure there are no invalid fields in a submitted campaign
|
2015-02-21 06:11:22 +00:00
|
|
|
func (c *Campaign) Validate() error {
|
2014-06-03 18:27:20 +00:00
|
|
|
switch {
|
|
|
|
case c.Name == "":
|
2015-02-21 06:11:22 +00:00
|
|
|
return ErrCampaignNameNotSpecified
|
2014-06-03 18:27:20 +00:00
|
|
|
case len(c.Groups) == 0:
|
2015-02-21 06:11:22 +00:00
|
|
|
return ErrGroupNotSpecified
|
2014-06-03 18:27:20 +00:00
|
|
|
case c.Template.Name == "":
|
2015-02-21 06:11:22 +00:00
|
|
|
return ErrTemplateNotSpecified
|
2015-10-23 03:29:10 +00:00
|
|
|
case c.Page.Name == "":
|
|
|
|
return ErrPageNotSpecified
|
2016-02-21 18:05:40 +00:00
|
|
|
case c.SMTP.Name == "":
|
|
|
|
return ErrSMTPNotSpecified
|
2014-06-03 18:27:20 +00:00
|
|
|
}
|
2016-02-21 18:05:40 +00:00
|
|
|
return nil
|
2014-03-25 03:31:33 +00:00
|
|
|
}
|
|
|
|
|
2016-01-25 02:03:53 +00:00
|
|
|
// SendTestEmailRequest is the structure of a request
|
|
|
|
// to send a test email to test an SMTP connection
|
|
|
|
type SendTestEmailRequest struct {
|
|
|
|
Template Template `json:"template"`
|
|
|
|
Page Page `json:"page"`
|
|
|
|
SMTP SMTP `json:"smtp"`
|
|
|
|
URL string `json:"url"`
|
|
|
|
Tracker string `json:"tracker"`
|
|
|
|
TrackingURL string `json:"tracking_url"`
|
2016-02-18 03:09:19 +00:00
|
|
|
From string `json:"from"`
|
2016-01-25 02:03:53 +00:00
|
|
|
Target
|
|
|
|
}
|
|
|
|
|
|
|
|
// Validate ensures the SendTestEmailRequest structure
|
|
|
|
// is valid.
|
|
|
|
func (s *SendTestEmailRequest) Validate() error {
|
|
|
|
switch {
|
|
|
|
case s.Email == "":
|
|
|
|
return ErrEmailNotSpecified
|
2016-02-22 03:09:14 +00:00
|
|
|
}
|
2016-02-21 18:05:40 +00:00
|
|
|
return nil
|
2016-01-25 02:03:53 +00:00
|
|
|
}
|
|
|
|
|
2015-02-07 16:41:53 +00:00
|
|
|
// UpdateStatus changes the campaign status appropriately
|
2014-06-26 02:01:01 +00:00
|
|
|
func (c *Campaign) UpdateStatus(s string) error {
|
|
|
|
// This could be made simpler, but I think there's a bug in gorm
|
|
|
|
return db.Table("campaigns").Where("id=?", c.Id).Update("status", s).Error
|
|
|
|
}
|
|
|
|
|
2015-02-07 16:41:53 +00:00
|
|
|
// AddEvent creates a new campaign event in the database
|
2014-07-02 01:32:34 +00:00
|
|
|
func (c *Campaign) AddEvent(e Event) error {
|
2014-06-26 02:01:01 +00:00
|
|
|
e.CampaignId = c.Id
|
|
|
|
e.Time = time.Now()
|
|
|
|
return db.Debug().Save(&e).Error
|
|
|
|
}
|
|
|
|
|
2016-03-24 04:41:17 +00:00
|
|
|
// getDetails retrieves the related attributes of the campaign
|
|
|
|
// from the database. If the Events and the Results are not available,
|
|
|
|
// an error is returned. Otherwise, the attribute name is set to [Deleted],
|
|
|
|
// indicating the user deleted the attribute (template, smtp, etc.)
|
|
|
|
func (c *Campaign) getDetails() error {
|
|
|
|
err = db.Model(c).Related(&c.Results).Error
|
|
|
|
if err != nil {
|
|
|
|
Logger.Printf("%s: results not found for campaign\n", err)
|
|
|
|
return err
|
|
|
|
}
|
|
|
|
err = db.Model(c).Related(&c.Events).Error
|
|
|
|
if err != nil {
|
|
|
|
Logger.Printf("%s: events not found for campaign\n", err)
|
|
|
|
return err
|
|
|
|
}
|
|
|
|
err = db.Table("templates").Where("id=?", c.TemplateId).Find(&c.Template).Error
|
|
|
|
if err != nil {
|
|
|
|
if err != gorm.ErrRecordNotFound {
|
|
|
|
return err
|
|
|
|
}
|
|
|
|
c.Template = Template{Name: "[Deleted]"}
|
|
|
|
Logger.Printf("%s: template not found for campaign\n", err)
|
|
|
|
}
|
|
|
|
err = db.Table("pages").Where("id=?", c.PageId).Find(&c.Page).Error
|
|
|
|
if err != nil {
|
|
|
|
if err != gorm.ErrRecordNotFound {
|
|
|
|
return err
|
|
|
|
}
|
|
|
|
c.Page = Page{Name: "[Deleted]"}
|
|
|
|
Logger.Printf("%s: page not found for campaign\n", err)
|
|
|
|
}
|
|
|
|
err = db.Table("SMTP").Where("id=?", c.SMTPId).Find(&c.SMTP).Error
|
|
|
|
if err != nil {
|
|
|
|
// Check if the SMTP was deleted
|
|
|
|
if err != gorm.ErrRecordNotFound {
|
|
|
|
return err
|
|
|
|
}
|
|
|
|
c.SMTP = SMTP{Name: "[Deleted]"}
|
|
|
|
Logger.Printf("%s: sending profile not found for campaign\n", err)
|
|
|
|
}
|
|
|
|
return nil
|
|
|
|
}
|
|
|
|
|
2016-01-25 02:47:16 +00:00
|
|
|
// Event contains the fields for an event
|
|
|
|
// that occurs during the campaign
|
2014-06-21 17:19:49 +00:00
|
|
|
type Event struct {
|
|
|
|
Id int64 `json:"-"`
|
|
|
|
CampaignId int64 `json:"-"`
|
|
|
|
Email string `json:"email"`
|
|
|
|
Time time.Time `json:"time"`
|
2014-07-02 01:32:34 +00:00
|
|
|
Message string `json:"message"`
|
2016-02-01 01:50:41 +00:00
|
|
|
Details string `json:"details"`
|
2014-06-21 17:19:49 +00:00
|
|
|
}
|
|
|
|
|
2014-03-25 03:31:33 +00:00
|
|
|
// GetCampaigns returns the campaigns owned by the given user.
|
|
|
|
func GetCampaigns(uid int64) ([]Campaign, error) {
|
|
|
|
cs := []Campaign{}
|
2014-03-26 20:01:49 +00:00
|
|
|
err := db.Model(&User{Id: uid}).Related(&cs).Error
|
2014-03-26 04:53:51 +00:00
|
|
|
if err != nil {
|
|
|
|
fmt.Println(err)
|
|
|
|
}
|
2014-03-27 02:42:07 +00:00
|
|
|
for i, _ := range cs {
|
2016-03-24 04:41:17 +00:00
|
|
|
err = cs[i].getDetails()
|
2016-03-04 00:47:10 +00:00
|
|
|
if err != nil {
|
|
|
|
Logger.Println(err)
|
|
|
|
}
|
2014-03-25 03:31:33 +00:00
|
|
|
}
|
|
|
|
return cs, err
|
|
|
|
}
|
|
|
|
|
|
|
|
// GetCampaign returns the campaign, if it exists, specified by the given id and user_id.
|
|
|
|
func GetCampaign(id int64, uid int64) (Campaign, error) {
|
|
|
|
c := Campaign{}
|
2014-03-26 20:01:49 +00:00
|
|
|
err := db.Where("id = ?", id).Where("user_id = ?", uid).Find(&c).Error
|
2014-03-27 02:42:07 +00:00
|
|
|
if err != nil {
|
2016-01-17 05:51:01 +00:00
|
|
|
Logger.Printf("%s: campaign not found\n", err)
|
2014-03-25 03:31:33 +00:00
|
|
|
return c, err
|
|
|
|
}
|
2016-03-24 04:41:17 +00:00
|
|
|
err = c.getDetails()
|
2014-03-27 02:42:07 +00:00
|
|
|
return c, err
|
2014-03-25 03:31:33 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
// PostCampaign inserts a campaign and all associated records into the database.
|
|
|
|
func PostCampaign(c *Campaign, uid int64) error {
|
2015-02-21 06:11:22 +00:00
|
|
|
if err := c.Validate(); err != nil {
|
|
|
|
return err
|
|
|
|
}
|
2014-06-21 17:19:49 +00:00
|
|
|
// Fill in the details
|
2014-06-26 02:01:01 +00:00
|
|
|
c.UserId = uid
|
2014-06-21 17:19:49 +00:00
|
|
|
c.CreatedDate = time.Now()
|
|
|
|
c.CompletedDate = time.Time{}
|
2014-07-02 01:32:34 +00:00
|
|
|
c.Status = CAMPAIGN_QUEUED
|
2014-03-25 03:31:33 +00:00
|
|
|
// Check to make sure all the groups already exist
|
|
|
|
for i, g := range c.Groups {
|
|
|
|
c.Groups[i], err = GetGroupByName(g.Name, uid)
|
2016-03-09 04:37:55 +00:00
|
|
|
if err == gorm.ErrRecordNotFound {
|
2014-03-25 03:31:33 +00:00
|
|
|
Logger.Printf("Error - Group %s does not exist", g.Name)
|
2015-02-21 06:11:22 +00:00
|
|
|
return ErrGroupNotFound
|
2014-03-25 03:31:33 +00:00
|
|
|
} else if err != nil {
|
|
|
|
Logger.Println(err)
|
|
|
|
return err
|
|
|
|
}
|
|
|
|
}
|
2014-06-03 18:27:20 +00:00
|
|
|
// Check to make sure the template exists
|
|
|
|
t, err := GetTemplateByName(c.Template.Name, uid)
|
2016-03-09 04:37:55 +00:00
|
|
|
if err == gorm.ErrRecordNotFound {
|
2014-06-03 18:27:20 +00:00
|
|
|
Logger.Printf("Error - Template %s does not exist", t.Name)
|
2015-02-21 06:11:22 +00:00
|
|
|
return ErrTemplateNotFound
|
2014-06-03 18:27:20 +00:00
|
|
|
} else if err != nil {
|
|
|
|
Logger.Println(err)
|
|
|
|
return err
|
|
|
|
}
|
2014-06-05 04:54:46 +00:00
|
|
|
c.Template = t
|
2014-06-03 18:27:20 +00:00
|
|
|
c.TemplateId = t.Id
|
2015-10-23 03:29:10 +00:00
|
|
|
// Check to make sure the page exists
|
|
|
|
p, err := GetPageByName(c.Page.Name, uid)
|
2016-03-09 04:37:55 +00:00
|
|
|
if err == gorm.ErrRecordNotFound {
|
2015-10-23 03:29:10 +00:00
|
|
|
Logger.Printf("Error - Page %s does not exist", p.Name)
|
|
|
|
return ErrPageNotFound
|
|
|
|
} else if err != nil {
|
|
|
|
Logger.Println(err)
|
|
|
|
return err
|
|
|
|
}
|
|
|
|
c.Page = p
|
|
|
|
c.PageId = p.Id
|
2016-02-21 18:05:40 +00:00
|
|
|
// Check to make sure the sending profile exists
|
2016-02-22 03:09:14 +00:00
|
|
|
s, err := GetSMTPByName(c.SMTP.Name, uid)
|
2016-03-09 04:37:55 +00:00
|
|
|
if err == gorm.ErrRecordNotFound {
|
2016-02-22 03:09:14 +00:00
|
|
|
Logger.Printf("Error - Sending profile %s does not exist", s.Name)
|
|
|
|
return ErrPageNotFound
|
|
|
|
} else if err != nil {
|
|
|
|
Logger.Println(err)
|
|
|
|
return err
|
|
|
|
}
|
|
|
|
c.SMTP = s
|
|
|
|
c.SMTPId = s.Id
|
2014-03-25 03:31:33 +00:00
|
|
|
// Insert into the DB
|
2014-03-26 20:01:49 +00:00
|
|
|
err = db.Save(c).Error
|
2014-03-25 03:31:33 +00:00
|
|
|
if err != nil {
|
|
|
|
Logger.Println(err)
|
|
|
|
return err
|
|
|
|
}
|
2014-07-02 01:32:34 +00:00
|
|
|
err = c.AddEvent(Event{Message: "Campaign Created"})
|
2014-06-26 02:01:01 +00:00
|
|
|
if err != nil {
|
|
|
|
Logger.Println(err)
|
|
|
|
}
|
2014-03-25 03:31:33 +00:00
|
|
|
// Insert all the results
|
|
|
|
for _, g := range c.Groups {
|
|
|
|
// Insert a result for each target in the group
|
|
|
|
for _, t := range g.Targets {
|
2016-02-18 03:25:06 +00:00
|
|
|
r := &Result{Email: t.Email, Position: t.Position, Status: STATUS_SENDING, CampaignId: c.Id, UserId: c.UserId, FirstName: t.FirstName, LastName: t.LastName}
|
2014-07-02 01:32:34 +00:00
|
|
|
r.GenerateId()
|
2016-02-02 02:42:46 +00:00
|
|
|
err = db.Save(r).Error
|
2014-03-25 03:31:33 +00:00
|
|
|
if err != nil {
|
|
|
|
Logger.Printf("Error adding result record for target %s\n", t.Email)
|
|
|
|
Logger.Println(err)
|
|
|
|
}
|
2016-02-02 02:42:46 +00:00
|
|
|
c.Results = append(c.Results, *r)
|
2014-03-25 03:31:33 +00:00
|
|
|
}
|
|
|
|
}
|
|
|
|
return nil
|
|
|
|
}
|
|
|
|
|
2014-03-26 20:01:49 +00:00
|
|
|
//DeleteCampaign deletes the specified campaign
|
2014-03-25 03:31:33 +00:00
|
|
|
func DeleteCampaign(id int64) error {
|
2016-01-17 05:51:01 +00:00
|
|
|
Logger.Printf("Deleting campaign %d\n", id)
|
2014-03-26 20:01:49 +00:00
|
|
|
// Delete all the campaign results
|
2014-05-27 21:13:30 +00:00
|
|
|
err := db.Where("campaign_id=?", id).Delete(&Result{}).Error
|
2014-03-25 03:31:33 +00:00
|
|
|
if err != nil {
|
2014-03-26 04:53:51 +00:00
|
|
|
Logger.Println(err)
|
2014-03-25 03:31:33 +00:00
|
|
|
return err
|
|
|
|
}
|
2014-07-24 02:04:38 +00:00
|
|
|
err = db.Where("campaign_id=?", id).Delete(&Event{}).Error
|
|
|
|
if err != nil {
|
|
|
|
Logger.Println(err)
|
|
|
|
return err
|
|
|
|
}
|
2014-03-26 20:01:49 +00:00
|
|
|
// Delete the campaign
|
|
|
|
err = db.Delete(&Campaign{Id: id}).Error
|
2014-03-25 03:31:33 +00:00
|
|
|
if err != nil {
|
2014-03-26 04:53:51 +00:00
|
|
|
Logger.Panicln(err)
|
2014-03-25 03:31:33 +00:00
|
|
|
return err
|
|
|
|
}
|
|
|
|
return err
|
|
|
|
}
|