diff --git a/controllers/api.go b/controllers/api.go index a9ec4f03..c1591ac9 100644 --- a/controllers/api.go +++ b/controllers/api.go @@ -203,7 +203,7 @@ func API_Groups(w http.ResponseWriter, r *http.Request) { JSONResponse(w, models.Response{Success: false, Message: "Group name already in use"}, http.StatusConflict) return } - g.ModifiedDate = time.Now() + g.ModifiedDate = time.Now().UTC() g.UserId = ctx.Get(r, "user_id").(int64) err = models.PostGroup(&g) if err != nil { @@ -256,7 +256,7 @@ func API_Groups_Id(w http.ResponseWriter, r *http.Request) { JSONResponse(w, models.Response{Success: false, Message: "Error: /:id and group_id mismatch"}, http.StatusInternalServerError) return } - g.ModifiedDate = time.Now() + g.ModifiedDate = time.Now().UTC() g.UserId = ctx.Get(r, "user_id").(int64) err = models.PutGroup(&g) if err != nil { @@ -305,7 +305,7 @@ func API_Templates(w http.ResponseWriter, r *http.Request) { JSONResponse(w, models.Response{Success: false, Message: "Template name already in use"}, http.StatusConflict) return } - t.ModifiedDate = time.Now() + t.ModifiedDate = time.Now().UTC() t.UserId = ctx.Get(r, "user_id").(int64) err = models.PostTemplate(&t) if err == models.ErrTemplateNameNotSpecified { @@ -354,7 +354,7 @@ func API_Templates_Id(w http.ResponseWriter, r *http.Request) { JSONResponse(w, models.Response{Success: false, Message: "Error: /:id and template_id mismatch"}, http.StatusBadRequest) return } - t.ModifiedDate = time.Now() + t.ModifiedDate = time.Now().UTC() t.UserId = ctx.Get(r, "user_id").(int64) err = models.PutTemplate(&t) if err != nil { @@ -390,7 +390,7 @@ func API_Pages(w http.ResponseWriter, r *http.Request) { Logger.Println(err) return } - p.ModifiedDate = time.Now() + p.ModifiedDate = time.Now().UTC() p.UserId = ctx.Get(r, "user_id").(int64) err = models.PostPage(&p) if err != nil { @@ -431,7 +431,7 @@ func API_Pages_Id(w http.ResponseWriter, r *http.Request) { JSONResponse(w, models.Response{Success: false, Message: "/:id and /:page_id mismatch"}, http.StatusBadRequest) return } - p.ModifiedDate = time.Now() + p.ModifiedDate = time.Now().UTC() p.UserId = ctx.Get(r, "user_id").(int64) err = models.PutPage(&p) if err != nil { @@ -467,7 +467,7 @@ func API_SMTP(w http.ResponseWriter, r *http.Request) { Logger.Println(err) return } - s.ModifiedDate = time.Now() + s.ModifiedDate = time.Now().UTC() s.UserId = ctx.Get(r, "user_id").(int64) err = models.PostSMTP(&s) if err != nil { @@ -513,7 +513,7 @@ func API_SMTP_Id(w http.ResponseWriter, r *http.Request) { JSONResponse(w, models.Response{Success: false, Message: err.Error()}, http.StatusBadRequest) return } - s.ModifiedDate = time.Now() + s.ModifiedDate = time.Now().UTC() s.UserId = ctx.Get(r, "user_id").(int64) err = models.PutSMTP(&s) if err != nil { diff --git a/db/db_mysql/migrations/20170828220440_0.4_utc_dates.sql b/db/db_mysql/migrations/20170828220440_0.4_utc_dates.sql new file mode 100644 index 00000000..3bbbb081 --- /dev/null +++ b/db/db_mysql/migrations/20170828220440_0.4_utc_dates.sql @@ -0,0 +1,16 @@ + +-- +goose Up +-- SQL in section 'Up' is executed when this migration is applied +UPDATE campaigns SET `created_date`=CONVERT_TZ(`created_date`, @@session.time_zone, '+00:00'); +UPDATE campaigns SET `completed_date`=CONVERT_TZ(`completed_date`, @@session.time_zone, '+00:00'); +UPDATE campaigns SET `launch_date`=CONVERT_TZ(`launch_date`, @@session.time_zone, '+00:00'); +UPDATE events SET `time`=CONVERT_TZ(`time`, @@session.time_zone, '+00:00'); +UPDATE groups SET `modified_date`=CONVERT_TZ(`modified_date`, @@session.time_zone, '+00:00'); +UPDATE templates SET `modified_date`=CONVERT_TZ(`modified_date`, @@session.time_zone, '+00:00'); +UPDATE pages SET `modified_date`=CONVERT_TZ(`modified_date`, @@session.time_zone, '+00:00'); +UPDATE smtp SET `modified_date`=CONVERT_TZ(`modified_date`, @@session.time_zone, '+00:00'); + + +-- +goose Down +-- SQL section 'Down' is executed when this migration is rolled back + diff --git a/db/db_sqlite3/migrations/20170827141312_0.4_utc_dates.sql b/db/db_sqlite3/migrations/20170827141312_0.4_utc_dates.sql new file mode 100644 index 00000000..1f853c6d --- /dev/null +++ b/db/db_sqlite3/migrations/20170827141312_0.4_utc_dates.sql @@ -0,0 +1,15 @@ + +-- +goose Up +-- SQL in section 'Up' is executed when this migration is applied +UPDATE campaigns SET created_date=STRFTIME('%Y-%m-%d %H:%M:%S+00:00', DATETIME(created_date, 'utc')); +UPDATE campaigns SET completed_date=STRFTIME('%Y-%m-%d %H:%M:%S+00:00', DATETIME(completed_date, 'utc')); +UPDATE campaigns SET launch_date=STRFTIME('%Y-%m-%d %H:%M:%S+00:00', DATETIME(launch_date, 'utc')); +UPDATE events SET `time`=STRFTIME('%Y-%m-%d %H:%M:%S+00:00', DATETIME(`time`, 'utc')); +UPDATE groups SET modified_date=STRFTIME('%Y-%m-%d %H:%M:%S+00:00', DATETIME(modified_date, 'utc')); +UPDATE templates SET modified_date=STRFTIME('%Y-%m-%d %H:%M:%S+00:00', DATETIME(modified_date, 'utc')); +UPDATE pages SET modified_date=STRFTIME('%Y-%m-%d %H:%M:%S+00:00', DATETIME(modified_date, 'utc')); +UPDATE smtp SET modified_date=STRFTIME('%Y-%m-%d %H:%M:%S+00:00', DATETIME(modified_date, 'utc')); + +-- +goose Down +-- SQL section 'Down' is executed when this migration is rolled back + diff --git a/models/campaign.go b/models/campaign.go index 5e294ed9..90136c10 100644 --- a/models/campaign.go +++ b/models/campaign.go @@ -140,7 +140,7 @@ func (c *Campaign) UpdateStatus(s string) error { // AddEvent creates a new campaign event in the database func (c *Campaign) AddEvent(e Event) error { e.CampaignId = c.Id - e.Time = time.Now() + e.Time = time.Now().UTC() return db.Debug().Save(&e).Error } @@ -226,7 +226,7 @@ func getCampaignStats(cid int64) (CampaignStats, error) { if err != nil { return s, err } - // Every opened email event implies the email was sent + // Every opened email event implies the email was sent s.EmailsSent += s.OpenedEmail err = query.Where("status=?", ERROR).Count(&s.Error).Error return s, err @@ -279,6 +279,7 @@ func GetCampaignSummaries(uid int64) (CampaignSummaries, error) { return overview, err } cs[i].Stats = s + Logger.Println(cs[i].CreatedDate.String()) } overview.Total = int64(len(cs)) overview.Campaigns = cs @@ -361,11 +362,13 @@ func PostCampaign(c *Campaign, uid int64) error { } // Fill in the details c.UserId = uid - c.CreatedDate = time.Now() + c.CreatedDate = time.Now().UTC() c.CompletedDate = time.Time{} c.Status = CAMPAIGN_CREATED if c.LaunchDate.IsZero() { - c.LaunchDate = time.Now() + c.LaunchDate = time.Now().UTC() + } else { + c.LaunchDate = c.LaunchDate.UTC() } // Check to make sure all the groups already exist for i, g := range c.Groups { @@ -479,7 +482,7 @@ func CompleteCampaign(id int64, uid int64) error { return nil } // Mark the campaign as complete - c.CompletedDate = time.Now() + c.CompletedDate = time.Now().UTC() c.Status = CAMPAIGN_COMPLETE err = db.Where("id=? and user_id=?", id, uid).Save(&c).Error if err != nil { diff --git a/static/js/dist/app/campaign_results.min.js b/static/js/dist/app/campaign_results.min.js index 608c3631..0913e25e 100644 --- a/static/js/dist/app/campaign_results.min.js +++ b/static/js/dist/app/campaign_results.min.js @@ -1 +1 @@ -function dismiss(){$("#modal\\.flashes").empty(),$("#modal").modal("hide"),$("#resultsTable").dataTable().DataTable().clear().draw()}function deleteCampaign(){swal({title:"Are you sure?",text:"This will delete the campaign. This can't be undone!",type:"warning",animation:!1,showCancelButton:!0,confirmButtonText:"Delete Campaign",confirmButtonColor:"#428bca",reverseButtons:!0,allowOutsideClick:!1,showLoaderOnConfirm:!0,preConfirm:function(){return new Promise(function(e,t){api.campaignId.delete(campaign.id).success(function(t){e()}).error(function(e){t(e.responseJSON.message)})})}}).then(function(){swal("Campaign Deleted!","This campaign has been deleted!","success"),$('button:contains("OK")').on("click",function(){location.href="/campaigns"})})}function completeCampaign(){swal({title:"Are you sure?",text:"Gophish will stop processing events for this campaign",type:"warning",animation:!1,showCancelButton:!0,confirmButtonText:"Complete Campaign",confirmButtonColor:"#428bca",reverseButtons:!0,allowOutsideClick:!1,showLoaderOnConfirm:!0,preConfirm:function(){return new Promise(function(e,t){api.campaignId.complete(campaign.id).success(function(t){e()}).error(function(e){t(e.responseJSON.message)})})}}).then(function(){swal("Campaign Completed!","This campaign has been completed!","success"),$("#complete_button")[0].disabled=!0,$("#complete_button").text("Completed!"),doPoll=!1})}function exportAsCSV(e){exportHTML=$("#exportButton").html();var t=null;switch(e){case"results":t=campaign.results;break;case"events":t=campaign.timeline}if(t){$("#exportButton").html('');var a=Papa.unparse(t,{}),i=new Blob([a],{type:"text/csv;charset=utf-8;"});if(navigator.msSaveBlob)navigator.msSaveBlob(i,e+".csv");else{var s=window.URL.createObjectURL(i),l=document.createElement("a");l.href=s,l.setAttribute("download",e+".csv"),document.body.appendChild(l),l.click(),document.body.removeChild(l)}$("#exportButton").html(exportHTML)}}function replay(e){function t(){form.attr({action:url}),form.appendTo("body").submit().remove()}request=campaign.timeline[e],details=JSON.parse(request.details),url=null,form=$("