github.com/gophish/gophish@v0.12.2-0.20230915144530-8e7929441393/models/template.go (about)

     1  package models
     2  
     3  import (
     4  	"errors"
     5  	"net/mail"
     6  	"time"
     7  
     8  	log "github.com/gophish/gophish/logger"
     9  	"github.com/jinzhu/gorm"
    10  )
    11  
    12  // Template models hold the attributes for an email template to be sent to targets
    13  type Template struct {
    14  	Id             int64        `json:"id" gorm:"column:id; primary_key:yes"`
    15  	UserId         int64        `json:"-" gorm:"column:user_id"`
    16  	Name           string       `json:"name"`
    17  	EnvelopeSender string       `json:"envelope_sender"`
    18  	Subject        string       `json:"subject"`
    19  	Text           string       `json:"text"`
    20  	HTML           string       `json:"html" gorm:"column:html"`
    21  	ModifiedDate   time.Time    `json:"modified_date"`
    22  	Attachments    []Attachment `json:"attachments"`
    23  }
    24  
    25  // ErrTemplateNameNotSpecified is thrown when a template name is not specified
    26  var ErrTemplateNameNotSpecified = errors.New("Template name not specified")
    27  
    28  // ErrTemplateMissingParameter is thrown when a needed parameter is not provided
    29  var ErrTemplateMissingParameter = errors.New("Need to specify at least plaintext or HTML content")
    30  
    31  // Validate checks the given template to make sure values are appropriate and complete
    32  func (t *Template) Validate() error {
    33  	switch {
    34  	case t.Name == "":
    35  		return ErrTemplateNameNotSpecified
    36  	case t.Text == "" && t.HTML == "":
    37  		return ErrTemplateMissingParameter
    38  	case t.EnvelopeSender != "":
    39  		_, err := mail.ParseAddress(t.EnvelopeSender)
    40  		if err != nil {
    41  			return err
    42  		}
    43  	}
    44  	if err := ValidateTemplate(t.HTML); err != nil {
    45  		return err
    46  	}
    47  	if err := ValidateTemplate(t.Text); err != nil {
    48  		return err
    49  	}
    50  	for _, a := range t.Attachments {
    51  		if err := a.Validate(); err != nil {
    52  			return err
    53  		}
    54  	}
    55  
    56  	return nil
    57  }
    58  
    59  // GetTemplates returns the templates owned by the given user.
    60  func GetTemplates(uid int64) ([]Template, error) {
    61  	ts := []Template{}
    62  	err := db.Where("user_id=?", uid).Find(&ts).Error
    63  	if err != nil {
    64  		log.Error(err)
    65  		return ts, err
    66  	}
    67  	for i := range ts {
    68  		// Get Attachments
    69  		err = db.Where("template_id=?", ts[i].Id).Find(&ts[i].Attachments).Error
    70  		if err == nil && len(ts[i].Attachments) == 0 {
    71  			ts[i].Attachments = make([]Attachment, 0)
    72  		}
    73  		if err != nil && err != gorm.ErrRecordNotFound {
    74  			log.Error(err)
    75  			return ts, err
    76  		}
    77  	}
    78  	return ts, err
    79  }
    80  
    81  // GetTemplate returns the template, if it exists, specified by the given id and user_id.
    82  func GetTemplate(id int64, uid int64) (Template, error) {
    83  	t := Template{}
    84  	err := db.Where("user_id=? and id=?", uid, id).Find(&t).Error
    85  	if err != nil {
    86  		log.Error(err)
    87  		return t, err
    88  	}
    89  
    90  	// Get Attachments
    91  	err = db.Where("template_id=?", t.Id).Find(&t.Attachments).Error
    92  	if err != nil && err != gorm.ErrRecordNotFound {
    93  		log.Error(err)
    94  		return t, err
    95  	}
    96  	if err == nil && len(t.Attachments) == 0 {
    97  		t.Attachments = make([]Attachment, 0)
    98  	}
    99  	return t, err
   100  }
   101  
   102  // GetTemplateByName returns the template, if it exists, specified by the given name and user_id.
   103  func GetTemplateByName(n string, uid int64) (Template, error) {
   104  	t := Template{}
   105  	err := db.Where("user_id=? and name=?", uid, n).Find(&t).Error
   106  	if err != nil {
   107  		log.Error(err)
   108  		return t, err
   109  	}
   110  
   111  	// Get Attachments
   112  	err = db.Where("template_id=?", t.Id).Find(&t.Attachments).Error
   113  	if err != nil && err != gorm.ErrRecordNotFound {
   114  		log.Error(err)
   115  		return t, err
   116  	}
   117  	if err == nil && len(t.Attachments) == 0 {
   118  		t.Attachments = make([]Attachment, 0)
   119  	}
   120  	return t, err
   121  }
   122  
   123  // PostTemplate creates a new template in the database.
   124  func PostTemplate(t *Template) error {
   125  	// Insert into the DB
   126  	if err := t.Validate(); err != nil {
   127  		return err
   128  	}
   129  	err := db.Save(t).Error
   130  	if err != nil {
   131  		log.Error(err)
   132  		return err
   133  	}
   134  
   135  	// Save every attachment
   136  	for i := range t.Attachments {
   137  		t.Attachments[i].TemplateId = t.Id
   138  		err := db.Save(&t.Attachments[i]).Error
   139  		if err != nil {
   140  			log.Error(err)
   141  			return err
   142  		}
   143  	}
   144  	return nil
   145  }
   146  
   147  // PutTemplate edits an existing template in the database.
   148  // Per the PUT Method RFC, it presumes all data for a template is provided.
   149  func PutTemplate(t *Template) error {
   150  	if err := t.Validate(); err != nil {
   151  		return err
   152  	}
   153  	// Delete all attachments, and replace with new ones
   154  	err := db.Where("template_id=?", t.Id).Delete(&Attachment{}).Error
   155  	if err != nil && err != gorm.ErrRecordNotFound {
   156  		log.Error(err)
   157  		return err
   158  	}
   159  	if err == gorm.ErrRecordNotFound {
   160  		err = nil
   161  	}
   162  	for i := range t.Attachments {
   163  		t.Attachments[i].TemplateId = t.Id
   164  		err := db.Save(&t.Attachments[i]).Error
   165  		if err != nil {
   166  			log.Error(err)
   167  			return err
   168  		}
   169  	}
   170  
   171  	// Save final template
   172  	err = db.Where("id=?", t.Id).Save(t).Error
   173  	if err != nil {
   174  		log.Error(err)
   175  		return err
   176  	}
   177  	return nil
   178  }
   179  
   180  // DeleteTemplate deletes an existing template in the database.
   181  // An error is returned if a template with the given user id and template id is not found.
   182  func DeleteTemplate(id int64, uid int64) error {
   183  	// Delete attachments
   184  	err := db.Where("template_id=?", id).Delete(&Attachment{}).Error
   185  	if err != nil {
   186  		log.Error(err)
   187  		return err
   188  	}
   189  
   190  	// Finally, delete the template itself
   191  	err = db.Where("user_id=?", uid).Delete(Template{Id: id}).Error
   192  	if err != nil {
   193  		log.Error(err)
   194  		return err
   195  	}
   196  	return nil
   197  }