package models import ( "errors" "time" log "github.com/gophish/gophish/logger" "github.com/jinzhu/gorm" ) // Template models hold the attributes for an email template to be sent to targets type Template struct { Id int64 `json:"id" gorm:"column:id; primary_key:yes"` UserId int64 `json:"-" gorm:"column:user_id"` Name string `json:"name"` Subject string `json:"subject"` Text string `json:"text"` HTML string `json:"html" gorm:"column:html"` ModifiedDate time.Time `json:"modified_date"` Attachments []Attachment `json:"attachments"` } // ErrTemplateNameNotSpecified is thrown when a template name is not specified var ErrTemplateNameNotSpecified = errors.New("Template name not specified") // ErrTemplateMissingParameter is thrown when a needed parameter is not provided var ErrTemplateMissingParameter = errors.New("Need to specify at least plaintext or HTML content") // Validate checks the given template to make sure values are appropriate and complete func (t *Template) Validate() error { switch { case t.Name == "": return ErrTemplateNameNotSpecified case t.Text == "" && t.HTML == "": return ErrTemplateMissingParameter } // Test that the variables used in the template // validate with no issues vc := ValidationContext{ FromAddress: "foo@bar.com", BaseURL: "http://example.com", } td := Result{ BaseRecipient: BaseRecipient{ Email: "foo@bar.com", FirstName: "Foo", LastName: "Bar", Position: "Test", }, RId: "123456", } ptx, err := NewPhishingTemplateContext(vc, td.BaseRecipient, td.RId) if err != nil { return err } _, err = ExecuteTemplate(t.HTML, ptx) if err != nil { return err } _, err = ExecuteTemplate(t.Text, ptx) if err != nil { return err } return nil } // GetTemplates returns the templates owned by the given user. func GetTemplates(uid int64) ([]Template, error) { ts := []Template{} err := db.Where("user_id=?", uid).Find(&ts).Error if err != nil { log.Error(err) return ts, err } for i, _ := range ts { // Get Attachments err = db.Where("template_id=?", ts[i].Id).Find(&ts[i].Attachments).Error if err == nil && len(ts[i].Attachments) == 0 { ts[i].Attachments = make([]Attachment, 0) } if err != nil && err != gorm.ErrRecordNotFound { log.Error(err) return ts, err } } return ts, err } // GetTemplate returns the template, if it exists, specified by the given id and user_id. func GetTemplate(id int64, uid int64) (Template, error) { t := Template{} err := db.Where("user_id=? and id=?", uid, id).Find(&t).Error if err != nil { log.Error(err) return t, err } // Get Attachments err = db.Where("template_id=?", t.Id).Find(&t.Attachments).Error if err != nil && err != gorm.ErrRecordNotFound { log.Error(err) return t, err } if err == nil && len(t.Attachments) == 0 { t.Attachments = make([]Attachment, 0) } return t, err } // GetTemplateByName returns the template, if it exists, specified by the given name and user_id. func GetTemplateByName(n string, uid int64) (Template, error) { t := Template{} err := db.Where("user_id=? and name=?", uid, n).Find(&t).Error if err != nil { log.Error(err) return t, err } // Get Attachments err = db.Where("template_id=?", t.Id).Find(&t.Attachments).Error if err != nil && err != gorm.ErrRecordNotFound { log.Error(err) return t, err } if err == nil && len(t.Attachments) == 0 { t.Attachments = make([]Attachment, 0) } return t, err } // PostTemplate creates a new template in the database. func PostTemplate(t *Template) error { // Insert into the DB if err := t.Validate(); err != nil { return err } err = db.Save(t).Error if err != nil { log.Error(err) return err } // Save every attachment for i := range t.Attachments { t.Attachments[i].TemplateId = t.Id err := db.Save(&t.Attachments[i]).Error if err != nil { log.Error(err) return err } } return nil } // PutTemplate edits an existing template in the database. // Per the PUT Method RFC, it presumes all data for a template is provided. func PutTemplate(t *Template) error { if err := t.Validate(); err != nil { return err } // Delete all attachments, and replace with new ones err = db.Where("template_id=?", t.Id).Delete(&Attachment{}).Error if err != nil && err != gorm.ErrRecordNotFound { log.Error(err) return err } if err == gorm.ErrRecordNotFound { err = nil } for i, _ := range t.Attachments { t.Attachments[i].TemplateId = t.Id err := db.Save(&t.Attachments[i]).Error if err != nil { log.Error(err) return err } } // Save final template err = db.Where("id=?", t.Id).Save(t).Error if err != nil { log.Error(err) return err } return nil } // DeleteTemplate deletes an existing template in the database. // An error is returned if a template with the given user id and template id is not found. func DeleteTemplate(id int64, uid int64) error { // Delete attachments err := db.Where("template_id=?", id).Delete(&Attachment{}).Error if err != nil { log.Error(err) return err } // Finally, delete the template itself err = db.Where("user_id=?", uid).Delete(Template{Id: id}).Error if err != nil { log.Error(err) return err } return nil }