Updates all datetimes to use UTC on the backend. This includes a DB migration to convert existing dates.

Fixes #316
This commit is contained in:
Jordan Wright 2017-08-28 22:48:49 -05:00
parent 779e419ab4
commit 58a57589bd
11 changed files with 130 additions and 88 deletions

View file

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

View file

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

View file

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

View file

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

File diff suppressed because one or more lines are too long

File diff suppressed because one or more lines are too long

File diff suppressed because one or more lines are too long

View file

@ -282,7 +282,7 @@ function renderTimeline(data) {
' <div class="timeline-icon ' + statuses[event.message].label + '">' +
' <i class="fa ' + statuses[event.message].icon + '"></i></div>' +
' <div class="timeline-message">' + escapeHtml(event.message) +
' <span class="timeline-date">' + moment(event.time).format('MMMM Do YYYY h:mm a') + '</span>'
' <span class="timeline-date">' + moment.utc(event.time).local().format('MMMM Do YYYY h:mm a') + '</span>'
if (event.details) {
if (event.message == "Submitted Data") {
results += '<div class="timeline-replay-button"><button onclick="replay(' + i + ')" class="btn btn-success">'
@ -461,7 +461,7 @@ function poll() {
/* Update the timeline */
var timeline_series_data = []
$.each(campaign.timeline, function (i, event) {
var event_date = moment(event.time)
var event_date = moment.utc(event.time).local()
timeline_series_data.push({
email: event.email,
x: event_date.valueOf(),
@ -470,7 +470,7 @@ function poll() {
})
var timeline_series_data = []
$.each(campaign.timeline, function (i, event) {
var event_date = moment(event.time)
var event_date = moment.utc(event.time).local()
timeline_series_data.push({
email: event.email,
message: event.message,
@ -661,7 +661,7 @@ function load() {
});
// Setup the graphs
$.each(campaign.timeline, function (i, event) {
var event_date = moment(event.time)
var event_date = moment.utc(event.time).local()
timeline_series_data.push({
email: event.email,
message: event.message,

View file

@ -43,9 +43,10 @@ function launch() {
smtp: {
name: $("#profile").select2("data")[0].text
},
launch_date: moment($("#launch_date").val(), "MM/DD/YYYY hh:mm a").format(),
launch_date: moment($("#launch_date").val(), "MM/DD/YYYY hh:mm a").utc().format(),
groups: groups
}
console.log("Launching campaign at time: " + campaign.launch_date)
// Submit the campaign
api.campaigns.post(campaign)
.success(function (data) {
@ -310,6 +311,8 @@ $(document).ready(function() {
]
});
$.each(campaigns, function (i, campaign) {
console.log(campaign)
console.log(campaign.created_date)
label = labels[campaign.status] || "label-default";
//section for tooltips on the status of a campaign to show some quick stats

View file

@ -197,7 +197,7 @@ function generateStatsPieCharts(campaigns) {
function generateTimelineChart(campaigns) {
var overview_data = []
$.each(campaigns, function (i, campaign) {
var campaign_date = moment(campaign.created_date)
var campaign_date = moment.utc(campaign.created_date).local()
// Add it to the chart data
campaign.y = 0
// Clicked events also contain our data submitted events
@ -275,6 +275,11 @@ function generateTimelineChart(campaigns) {
}
$(document).ready(function () {
Highcharts.setOptions({
global: {
useUTC: false
}
})
api.campaigns.summary()
.success(function (data) {
$("#loading").hide()

View file

@ -36,7 +36,7 @@ func New() *Worker {
func (w *Worker) Start() {
Logger.Println("Background Worker Started Successfully - Waiting for Campaigns")
for t := range time.Tick(1 * time.Minute) {
cs, err := models.GetQueuedCampaigns(t)
cs, err := models.GetQueuedCampaigns(t.UTC())
// Not really sure of a clean way to catch errors per campaign...
if err != nil {
Logger.Println(err)