diff --git a/auth/auth.go b/auth/auth.go index af8327f5..9ce86a3b 100644 --- a/auth/auth.go +++ b/auth/auth.go @@ -30,6 +30,10 @@ var Store = sessions.NewCookieStore( // ErrInvalidPassword is thrown when a user provides an incorrect password. var ErrInvalidPassword = errors.New("Invalid Password") +// ErrEmptyPassword is thrown when a user provides a blank password to the register +// or change password functions +var ErrEmptyPassword = errors.New("Password cannot be blank") + // Login attempts to login the user given a request. func Login(r *http.Request) (bool, error) { username, password := r.FormValue("username"), r.FormValue("password") @@ -61,6 +65,10 @@ func Register(r *http.Request) (bool, error) { } u = models.User{} //If we've made it here, we should have a valid username given + // Check that the passsword isn't blank + if password == "" { + return false, ErrEmptyPassword + } //Let's create the password hash h, err := bcrypt.GenerateFromPassword([]byte(password), bcrypt.DefaultCost) if err != nil { @@ -89,16 +97,19 @@ func ChangePassword(r *http.Request) error { err := bcrypt.CompareHashAndPassword([]byte(u.Hash), []byte(c)) if err != nil { return ErrInvalidPassword - } else { - // Generate the new hash - h, err := bcrypt.GenerateFromPassword([]byte(n), bcrypt.DefaultCost) - if err != nil { - return err - } - u.Hash = string(h) - if err = models.PutUser(&u); err != nil { - return err - } - return nil } + // Check that the new password isn't blank + if n == "" { + return ErrEmptyPassword + } + // Generate the new hash + h, err := bcrypt.GenerateFromPassword([]byte(n), bcrypt.DefaultCost) + if err != nil { + return err + } + u.Hash = string(h) + if err = models.PutUser(&u); err != nil { + return err + } + return nil } diff --git a/controllers/route.go b/controllers/route.go index 22c163af..aa17cf78 100644 --- a/controllers/route.go +++ b/controllers/route.go @@ -223,23 +223,18 @@ func Register(w http.ResponseWriter, r *http.Request) { }) session.Save(r, w) http.Redirect(w, r, "/login", 302) - } else { - // Check the error - m := "" - if err == models.ErrUsernameTaken { - m = "Username already taken" - } else { - m = "Unknown error - please try again" - Logger.Println(err) - } - session.AddFlash(models.Flash{ - Type: "danger", - Message: m, - }) - session.Save(r, w) - http.Redirect(w, r, "/register", 302) + return } - + // Check the error + m := err.Error() + Logger.Println(err) + session.AddFlash(models.Flash{ + Type: "danger", + Message: m, + }) + session.Save(r, w) + http.Redirect(w, r, "/register", 302) + return } } @@ -333,8 +328,9 @@ func Settings(w http.ResponseWriter, r *http.Request) { msg.Success = false JSONResponse(w, msg, http.StatusBadRequest) return - } else if err != nil { - msg.Message = "Unknown Error Occured" + } + if err != nil { + msg.Message = err.Error() msg.Success = false JSONResponse(w, msg, http.StatusBadRequest) return diff --git a/db/migrations/20160217211342_0.1.2_create_from_col_results.sql b/db/migrations/20160217211342_0.1.2_create_from_col_results.sql new file mode 100644 index 00000000..42f828fe --- /dev/null +++ b/db/migrations/20160217211342_0.1.2_create_from_col_results.sql @@ -0,0 +1,8 @@ + +-- +goose Up +-- SQL in section 'Up' is executed when this migration is applied +ALTER TABLE results ADD COLUMN position VARCHAR(255); + +-- +goose Down +-- SQL section 'Down' is executed when this migration is rolled back + diff --git a/models/campaign.go b/models/campaign.go index b813d456..bd39074e 100644 --- a/models/campaign.go +++ b/models/campaign.go @@ -72,6 +72,7 @@ type SendTestEmailRequest struct { URL string `json:"url"` Tracker string `json:"tracker"` TrackingURL string `json:"tracking_url"` + From string `json:"from"` Target } @@ -227,7 +228,7 @@ func PostCampaign(c *Campaign, uid int64) error { for _, g := range c.Groups { // Insert a result for each target in the group for _, t := range g.Targets { - r := &Result{Email: t.Email, Status: STATUS_SENDING, CampaignId: c.Id, UserId: c.UserId, FirstName: t.FirstName, LastName: t.LastName} + r := &Result{Email: t.Email, Position: t.Position, Status: STATUS_SENDING, CampaignId: c.Id, UserId: c.UserId, FirstName: t.FirstName, LastName: t.LastName} r.GenerateId() err = db.Save(r).Error if err != nil { diff --git a/models/result.go b/models/result.go index c7ab8575..ef804adb 100644 --- a/models/result.go +++ b/models/result.go @@ -30,6 +30,7 @@ type Result struct { Email string `json:"email"` FirstName string `json:"first_name"` LastName string `json:"last_name"` + Position string `json:"position"` Status string `json:"status" sql:"not null"` IP string `json:"ip"` Latitude float64 `json:"latitude"` diff --git a/models/template.go b/models/template.go index cb5f12a6..c6027cc6 100644 --- a/models/template.go +++ b/models/template.go @@ -82,6 +82,7 @@ func GetTemplateByName(n string, uid int64) (Template, error) { err := db.Where("user_id=? and name=?", uid, n).Find(&t).Error if err != nil { Logger.Println(err) + return t, err } err = db.Where("template_id=?", t.Id).Find(&t.Attachments).Error if err != nil && err != gorm.RecordNotFound { diff --git a/static/js/app/campaign_results.js b/static/js/app/campaign_results.js index efba5e8b..3c1fbc44 100644 --- a/static/js/app/campaign_results.js +++ b/static/js/app/campaign_results.js @@ -111,7 +111,9 @@ function exportAsCSV(scope) { var dlLink = document.createElement('a'); dlLink.href = csvURL; dlLink.setAttribute('download', scope + '.csv'); + document.body.appendChild(dlLink) dlLink.click(); + document.body.removeChild(dlLink) } $("#exportButton").html(exportHTML) } diff --git a/static/js/app/dashboard.js b/static/js/app/dashboard.js index f997caaa..6827e8ec 100644 --- a/static/js/app/dashboard.js +++ b/static/js/app/dashboard.js @@ -14,7 +14,7 @@ function deleteCampaign(idx) { api.campaignId.delete(campaigns[idx].id) .success(function(data) { successFlash(data.message) - location.reload() + location.reload() }) } } @@ -51,12 +51,13 @@ $(document).ready(function() { } var average = 0 campaignTable = $("#campaignTable").DataTable({ - columnDefs: [ - { orderable: false, targets: "no-sort" } - ] - }); + columnDefs: [{ + orderable: false, + targets: "no-sort" + }] + }); $.each(campaigns, function(i, campaign) { - var campaign_date = moment(campaign.created_date).format('MMMM Do YYYY h:mm:ss a') + var campaign_date = moment(campaign.created_date).format('MMMM Do YYYY, h:mm:ss a') var label = labels[campaign.status] || "label-default"; // Add it to the table campaignTable.row.add([ diff --git a/static/js/app/landing_pages.js b/static/js/app/landing_pages.js index ccbc94db..e845bfdd 100644 --- a/static/js/app/landing_pages.js +++ b/static/js/app/landing_pages.js @@ -92,6 +92,16 @@ function edit(idx) { } } +function copy(idx) { + $("#modalSubmit").unbind('click').click(function() { + save(-1) + }) + $("#html_editor").ckeditor() + var page = pages[idx] + $("#name").val("Copy of " + page.name) + $("#html_editor").val(page.html) +} + function load() { /* load() - Loads the current pages using the API @@ -117,14 +127,18 @@ function load() { pagesTable.row.add([ page.name, moment(page.modified_date).format('MMMM Do YYYY, h:mm:ss a'), - "
\ - \ + \ +
" ]).draw() }) + $('[data-toggle="tooltip"]').tooltip() } else { $("#emptyMessage").show() } diff --git a/static/js/app/templates.js b/static/js/app/templates.js index b3e7245a..14906a11 100644 --- a/static/js/app/templates.js +++ b/static/js/app/templates.js @@ -165,6 +165,55 @@ function edit(idx) { }) } +function copy(idx) { + $("#modalSubmit").unbind('click').click(function() { + save(-1) + }) + $("#attachmentUpload").unbind('click').click(function() { + this.value = null + }) + $("#html_editor").ckeditor() + $("#attachmentsTable").show() + attachmentsTable = $('#attachmentsTable').DataTable({ + destroy: true, + "order": [ + [1, "asc"] + ], + columnDefs: [{ + orderable: false, + targets: "no-sort" + }, { + sClass: "datatable_hidden", + targets: [3, 4] + }] + }); + var template = { + attachments: [] + } + template = templates[idx] + $("#name").val("Copy of " + template.name) + $("#subject").val(template.subject) + $("#html_editor").val(template.html) + $("#text_editor").val(template.text) + $.each(template.attachments, function(i, file) { + var icon = icons[file.type] || "fa-file-o" + // Add the record to the modal + attachmentsTable.row.add([ + '', + file.name, + '', + file.content, + file.type || "application/octet-stream" + ]).draw() + }) + // Handle Deletion + $("#attachmentsTable").unbind('click').on("click", "span>i.fa-trash-o", function() { + attachmentsTable.row($(this).parents('tr')) + .remove() + .draw(); + }) +} + function importEmail() { raw = $("#email_content").val() if (!raw) { @@ -211,14 +260,18 @@ function load() { templateTable.row.add([ template.name, moment(template.modified_date).format('MMMM Do YYYY, h:mm:ss a'), - "
\ - \ + \ +
" ]).draw() }) + $('[data-toggle="tooltip"]').tooltip() } else { $("#emptyMessage").show() } diff --git a/worker/worker.go b/worker/worker.go index 904b2849..67259de3 100644 --- a/worker/worker.go +++ b/worker/worker.go @@ -178,9 +178,9 @@ func SendTestEmail(s *models.SendTestEmailRequest) error { Logger.Println(err) return err } - ft := f.Name - if ft == "" { - ft = f.Address + s.From = f.Name + if s.From == "" { + s.From = f.Address } Logger.Println("Creating email using template") // Parse the templates