Merge branch 'master' into 124-capture-passwords

pull/169/head^2^2
Jordan Wright 2016-02-25 20:02:15 -06:00
commit b0dd96d088
11 changed files with 133 additions and 45 deletions

View File

@ -30,6 +30,10 @@ var Store = sessions.NewCookieStore(
// ErrInvalidPassword is thrown when a user provides an incorrect password. // ErrInvalidPassword is thrown when a user provides an incorrect password.
var ErrInvalidPassword = errors.New("Invalid 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. // Login attempts to login the user given a request.
func Login(r *http.Request) (bool, error) { func Login(r *http.Request) (bool, error) {
username, password := r.FormValue("username"), r.FormValue("password") username, password := r.FormValue("username"), r.FormValue("password")
@ -61,6 +65,10 @@ func Register(r *http.Request) (bool, error) {
} }
u = models.User{} u = models.User{}
//If we've made it here, we should have a valid username given //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 //Let's create the password hash
h, err := bcrypt.GenerateFromPassword([]byte(password), bcrypt.DefaultCost) h, err := bcrypt.GenerateFromPassword([]byte(password), bcrypt.DefaultCost)
if err != nil { if err != nil {
@ -89,7 +97,11 @@ func ChangePassword(r *http.Request) error {
err := bcrypt.CompareHashAndPassword([]byte(u.Hash), []byte(c)) err := bcrypt.CompareHashAndPassword([]byte(u.Hash), []byte(c))
if err != nil { if err != nil {
return ErrInvalidPassword return ErrInvalidPassword
} else { }
// Check that the new password isn't blank
if n == "" {
return ErrEmptyPassword
}
// Generate the new hash // Generate the new hash
h, err := bcrypt.GenerateFromPassword([]byte(n), bcrypt.DefaultCost) h, err := bcrypt.GenerateFromPassword([]byte(n), bcrypt.DefaultCost)
if err != nil { if err != nil {
@ -101,4 +113,3 @@ func ChangePassword(r *http.Request) error {
} }
return nil return nil
} }
}

View File

@ -223,23 +223,18 @@ func Register(w http.ResponseWriter, r *http.Request) {
}) })
session.Save(r, w) session.Save(r, w)
http.Redirect(w, r, "/login", 302) http.Redirect(w, r, "/login", 302)
} else { return
// Check the error
m := ""
if err == models.ErrUsernameTaken {
m = "Username already taken"
} else {
m = "Unknown error - please try again"
Logger.Println(err)
} }
// Check the error
m := err.Error()
Logger.Println(err)
session.AddFlash(models.Flash{ session.AddFlash(models.Flash{
Type: "danger", Type: "danger",
Message: m, Message: m,
}) })
session.Save(r, w) session.Save(r, w)
http.Redirect(w, r, "/register", 302) http.Redirect(w, r, "/register", 302)
} return
} }
} }
@ -333,8 +328,9 @@ func Settings(w http.ResponseWriter, r *http.Request) {
msg.Success = false msg.Success = false
JSONResponse(w, msg, http.StatusBadRequest) JSONResponse(w, msg, http.StatusBadRequest)
return return
} else if err != nil { }
msg.Message = "Unknown Error Occured" if err != nil {
msg.Message = err.Error()
msg.Success = false msg.Success = false
JSONResponse(w, msg, http.StatusBadRequest) JSONResponse(w, msg, http.StatusBadRequest)
return return

View File

@ -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

View File

@ -72,6 +72,7 @@ type SendTestEmailRequest struct {
URL string `json:"url"` URL string `json:"url"`
Tracker string `json:"tracker"` Tracker string `json:"tracker"`
TrackingURL string `json:"tracking_url"` TrackingURL string `json:"tracking_url"`
From string `json:"from"`
Target Target
} }
@ -227,7 +228,7 @@ func PostCampaign(c *Campaign, uid int64) error {
for _, g := range c.Groups { for _, g := range c.Groups {
// Insert a result for each target in the group // Insert a result for each target in the group
for _, t := range g.Targets { 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() r.GenerateId()
err = db.Save(r).Error err = db.Save(r).Error
if err != nil { if err != nil {

View File

@ -30,6 +30,7 @@ type Result struct {
Email string `json:"email"` Email string `json:"email"`
FirstName string `json:"first_name"` FirstName string `json:"first_name"`
LastName string `json:"last_name"` LastName string `json:"last_name"`
Position string `json:"position"`
Status string `json:"status" sql:"not null"` Status string `json:"status" sql:"not null"`
IP string `json:"ip"` IP string `json:"ip"`
Latitude float64 `json:"latitude"` Latitude float64 `json:"latitude"`

View File

@ -82,6 +82,7 @@ func GetTemplateByName(n string, uid int64) (Template, error) {
err := db.Where("user_id=? and name=?", uid, n).Find(&t).Error err := db.Where("user_id=? and name=?", uid, n).Find(&t).Error
if err != nil { if err != nil {
Logger.Println(err) Logger.Println(err)
return t, err
} }
err = db.Where("template_id=?", t.Id).Find(&t.Attachments).Error err = db.Where("template_id=?", t.Id).Find(&t.Attachments).Error
if err != nil && err != gorm.RecordNotFound { if err != nil && err != gorm.RecordNotFound {

View File

@ -111,7 +111,9 @@ function exportAsCSV(scope) {
var dlLink = document.createElement('a'); var dlLink = document.createElement('a');
dlLink.href = csvURL; dlLink.href = csvURL;
dlLink.setAttribute('download', scope + '.csv'); dlLink.setAttribute('download', scope + '.csv');
document.body.appendChild(dlLink)
dlLink.click(); dlLink.click();
document.body.removeChild(dlLink)
} }
$("#exportButton").html(exportHTML) $("#exportButton").html(exportHTML)
} }

View File

@ -51,12 +51,13 @@ $(document).ready(function() {
} }
var average = 0 var average = 0
campaignTable = $("#campaignTable").DataTable({ campaignTable = $("#campaignTable").DataTable({
columnDefs: [ columnDefs: [{
{ orderable: false, targets: "no-sort" } orderable: false,
] targets: "no-sort"
}]
}); });
$.each(campaigns, function(i, campaign) { $.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"; var label = labels[campaign.status] || "label-default";
// Add it to the table // Add it to the table
campaignTable.row.add([ campaignTable.row.add([

View File

@ -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() { function load() {
/* /*
load() - Loads the current pages using the API load() - Loads the current pages using the API
@ -117,14 +127,18 @@ function load() {
pagesTable.row.add([ pagesTable.row.add([
page.name, page.name,
moment(page.modified_date).format('MMMM Do YYYY, h:mm:ss a'), moment(page.modified_date).format('MMMM Do YYYY, h:mm:ss a'),
"<div class='pull-right'><button class='btn btn-primary' data-toggle='modal' data-target='#newLandingPageModal' onclick='edit(" + i + ")'>\ "<div class='pull-right'><span data-toggle='modal' data-target='#newLandingPageModal'><button class='btn btn-primary' data-toggle='tooltip' data-placement='left' title='Edit Page' onclick='edit(" + i + ")'>\
<i class='fa fa-pencil'></i>\ <i class='fa fa-pencil'></i>\
</button>\ </button></span>\
<button class='btn btn-danger' onclick='deletePage(" + i + ")'>\ <span data-toggle='modal' data-target='#newLandingPageModal'><button class='btn btn-primary' data-toggle='tooltip' data-placement='left' title='Copy Page' onclick='copy(" + i + ")'>\
<i class='fa fa-copy'></i>\
</button></span>\
<button class='btn btn-danger' data-toggle='tooltip' data-placement='left' title='Delete Page' onclick='deletePage(" + i + ")'>\
<i class='fa fa-trash-o'></i>\ <i class='fa fa-trash-o'></i>\
</button></div>" </button></div>"
]).draw() ]).draw()
}) })
$('[data-toggle="tooltip"]').tooltip()
} else { } else {
$("#emptyMessage").show() $("#emptyMessage").show()
} }

View File

@ -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([
'<i class="fa ' + icon + '"></i>',
file.name,
'<span class="remove-row"><i class="fa fa-trash-o"></i></span>',
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() { function importEmail() {
raw = $("#email_content").val() raw = $("#email_content").val()
if (!raw) { if (!raw) {
@ -211,14 +260,18 @@ function load() {
templateTable.row.add([ templateTable.row.add([
template.name, template.name,
moment(template.modified_date).format('MMMM Do YYYY, h:mm:ss a'), moment(template.modified_date).format('MMMM Do YYYY, h:mm:ss a'),
"<div class='pull-right'><button class='btn btn-primary' data-toggle='modal' data-target='#modal' onclick='edit(" + i + ")'>\ "<div class='pull-right'><span data-toggle='modal' data-target='#modal'><button class='btn btn-primary' data-toggle='tooltip' data-placement='left' title='Edit Template' onclick='edit(" + i + ")'>\
<i class='fa fa-pencil'></i>\ <i class='fa fa-pencil'></i>\
</button>\ </button></span>\
<button class='btn btn-danger' onclick='deleteTemplate(" + i + ")'>\ <span data-toggle='modal' data-target='#modal'><button class='btn btn-primary' data-toggle='tooltip' data-placement='left' title='Copy Template' onclick='copy(" + i + ")'>\
<i class='fa fa-copy'></i>\
</button></span>\
<button class='btn btn-danger' data-toggle='tooltip' data-placement='left' title='Delete Template' onclick='deleteTemplate(" + i + ")'>\
<i class='fa fa-trash-o'></i>\ <i class='fa fa-trash-o'></i>\
</button></div>" </button></div>"
]).draw() ]).draw()
}) })
$('[data-toggle="tooltip"]').tooltip()
} else { } else {
$("#emptyMessage").show() $("#emptyMessage").show()
} }

View File

@ -178,9 +178,9 @@ func SendTestEmail(s *models.SendTestEmailRequest) error {
Logger.Println(err) Logger.Println(err)
return err return err
} }
ft := f.Name s.From = f.Name
if ft == "" { if s.From == "" {
ft = f.Address s.From = f.Address
} }
Logger.Println("Creating email using template") Logger.Println("Creating email using template")
// Parse the templates // Parse the templates