gophish/models/template.go

206 lines
5.2 KiB
Go

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
}