From dbb37367854d108ebfffcac27837c0afac199a8e Mon Sep 17 00:00:00 2001 From: yp05327 <576951401@qq.com> Date: Thu, 4 May 2023 08:53:43 +0900 Subject: [PATCH] Fix incorrect webhook time and use relative-time to display it (#24477) Fixes #24414 After click replay this webhook, it will display `now` ![image](https://user-images.githubusercontent.com/18380374/235559399-05a23927-13f5-442d-8f10-2c7cd24022a0.png) --------- Co-authored-by: wxiaoguang Co-authored-by: Giteabot --- models/webhook/hooktask.go | 41 ++++++++++---------- models/webhook/webhook_test.go | 10 ++--- modules/timeutil/timestampnano.go | 28 +++++++++++++ services/webhook/deliver.go | 3 +- templates/repo/settings/webhook/history.tmpl | 2 +- 5 files changed, 57 insertions(+), 27 deletions(-) create mode 100644 modules/timeutil/timestampnano.go diff --git a/models/webhook/hooktask.go b/models/webhook/hooktask.go index 8688fe5de3..f9fc886826 100644 --- a/models/webhook/hooktask.go +++ b/models/webhook/hooktask.go @@ -12,6 +12,7 @@ import ( "code.gitea.io/gitea/modules/log" "code.gitea.io/gitea/modules/setting" api "code.gitea.io/gitea/modules/structs" + "code.gitea.io/gitea/modules/timeutil" webhook_module "code.gitea.io/gitea/modules/webhook" gouuid "github.com/google/uuid" @@ -40,15 +41,14 @@ type HookResponse struct { // HookTask represents a hook task. type HookTask struct { - ID int64 `xorm:"pk autoincr"` - HookID int64 `xorm:"index"` - UUID string `xorm:"unique"` - api.Payloader `xorm:"-"` - PayloadContent string `xorm:"LONGTEXT"` - EventType webhook_module.HookEventType - IsDelivered bool - Delivered int64 - DeliveredString string `xorm:"-"` + ID int64 `xorm:"pk autoincr"` + HookID int64 `xorm:"index"` + UUID string `xorm:"unique"` + api.Payloader `xorm:"-"` + PayloadContent string `xorm:"LONGTEXT"` + EventType webhook_module.HookEventType + IsDelivered bool + Delivered timeutil.TimeStampNano // History info. IsSucceed bool @@ -75,8 +75,6 @@ func (t *HookTask) BeforeUpdate() { // AfterLoad updates the webhook object upon setting a column func (t *HookTask) AfterLoad() { - t.DeliveredString = time.Unix(0, t.Delivered).Format("2006-01-02 15:04:05 MST") - if len(t.RequestContent) == 0 { return } @@ -115,12 +113,17 @@ func HookTasks(hookID int64, page int) ([]*HookTask, error) { // CreateHookTask creates a new hook task, // it handles conversion from Payload to PayloadContent. func CreateHookTask(ctx context.Context, t *HookTask) (*HookTask, error) { - data, err := t.Payloader.JSONPayload() - if err != nil { - return nil, err - } t.UUID = gouuid.New().String() - t.PayloadContent = string(data) + if t.Payloader != nil { + data, err := t.Payloader.JSONPayload() + if err != nil { + return nil, err + } + t.PayloadContent = string(data) + } + if t.Delivered == 0 { + t.Delivered = timeutil.TimeStampNanoNow() + } return t, db.Insert(ctx, t) } @@ -161,13 +164,11 @@ func ReplayHookTask(ctx context.Context, hookID int64, uuid string) (*HookTask, } } - newTask := &HookTask{ - UUID: gouuid.New().String(), + return CreateHookTask(ctx, &HookTask{ HookID: task.HookID, PayloadContent: task.PayloadContent, EventType: task.EventType, - } - return newTask, db.Insert(ctx, newTask) + }) } // FindUndeliveredHookTaskIDs will find the next 100 undelivered hook tasks with ID greater than the provided lowerID diff --git a/models/webhook/webhook_test.go b/models/webhook/webhook_test.go index 74f7aeaa03..e05dcaba01 100644 --- a/models/webhook/webhook_test.go +++ b/models/webhook/webhook_test.go @@ -12,6 +12,7 @@ import ( "code.gitea.io/gitea/models/unittest" "code.gitea.io/gitea/modules/json" api "code.gitea.io/gitea/modules/structs" + "code.gitea.io/gitea/modules/timeutil" "code.gitea.io/gitea/modules/util" webhook_module "code.gitea.io/gitea/modules/webhook" @@ -222,7 +223,6 @@ func TestUpdateHookTask(t *testing.T) { hook := unittest.AssertExistsAndLoadBean(t, &HookTask{ID: 1}) hook.PayloadContent = "new payload content" - hook.DeliveredString = "new delivered string" hook.IsDelivered = true unittest.AssertNotExistsBean(t, hook) assert.NoError(t, UpdateHookTask(hook)) @@ -235,7 +235,7 @@ func TestCleanupHookTaskTable_PerWebhook_DeletesDelivered(t *testing.T) { HookID: 3, Payloader: &api.PushPayload{}, IsDelivered: true, - Delivered: time.Now().UnixNano(), + Delivered: timeutil.TimeStampNanoNow(), } unittest.AssertNotExistsBean(t, hookTask) _, err := CreateHookTask(db.DefaultContext, hookTask) @@ -268,7 +268,7 @@ func TestCleanupHookTaskTable_PerWebhook_LeavesMostRecentTask(t *testing.T) { HookID: 4, Payloader: &api.PushPayload{}, IsDelivered: true, - Delivered: time.Now().UnixNano(), + Delivered: timeutil.TimeStampNanoNow(), } unittest.AssertNotExistsBean(t, hookTask) _, err := CreateHookTask(db.DefaultContext, hookTask) @@ -285,7 +285,7 @@ func TestCleanupHookTaskTable_OlderThan_DeletesDelivered(t *testing.T) { HookID: 3, Payloader: &api.PushPayload{}, IsDelivered: true, - Delivered: time.Now().AddDate(0, 0, -8).UnixNano(), + Delivered: timeutil.TimeStampNano(time.Now().AddDate(0, 0, -8).UnixNano()), } unittest.AssertNotExistsBean(t, hookTask) _, err := CreateHookTask(db.DefaultContext, hookTask) @@ -318,7 +318,7 @@ func TestCleanupHookTaskTable_OlderThan_LeavesTaskEarlierThanAgeToDelete(t *test HookID: 4, Payloader: &api.PushPayload{}, IsDelivered: true, - Delivered: time.Now().AddDate(0, 0, -6).UnixNano(), + Delivered: timeutil.TimeStampNano(time.Now().AddDate(0, 0, -6).UnixNano()), } unittest.AssertNotExistsBean(t, hookTask) _, err := CreateHookTask(db.DefaultContext, hookTask) diff --git a/modules/timeutil/timestampnano.go b/modules/timeutil/timestampnano.go new file mode 100644 index 0000000000..4a9f7955b9 --- /dev/null +++ b/modules/timeutil/timestampnano.go @@ -0,0 +1,28 @@ +// Copyright 2017 The Gitea Authors. All rights reserved. +// SPDX-License-Identifier: MIT + +package timeutil + +import ( + "time" + + "code.gitea.io/gitea/modules/setting" +) + +// TimeStampNano is for nano time in database, do not use it unless there is a real requirement. +type TimeStampNano int64 + +// TimeStampNanoNow returns now nano int64 +func TimeStampNanoNow() TimeStampNano { + return TimeStampNano(time.Now().UnixNano()) +} + +// AsTime convert timestamp as time.Time in Local locale +func (tsn TimeStampNano) AsTime() (tm time.Time) { + return tsn.AsTimeInLocation(setting.DefaultUILocation) +} + +// AsTimeInLocation convert timestamp as time.Time in Local locale +func (tsn TimeStampNano) AsTimeInLocation(loc *time.Location) time.Time { + return time.Unix(0, int64(tsn)).In(loc) +} diff --git a/services/webhook/deliver.go b/services/webhook/deliver.go index e389b1f9fe..31246c1555 100644 --- a/services/webhook/deliver.go +++ b/services/webhook/deliver.go @@ -25,6 +25,7 @@ import ( "code.gitea.io/gitea/modules/proxy" "code.gitea.io/gitea/modules/queue" "code.gitea.io/gitea/modules/setting" + "code.gitea.io/gitea/modules/timeutil" webhook_module "code.gitea.io/gitea/modules/webhook" "github.com/gobwas/glob" @@ -175,7 +176,7 @@ func Deliver(ctx context.Context, t *webhook_model.HookTask) error { // All code from this point will update the hook task defer func() { - t.Delivered = time.Now().UnixNano() + t.Delivered = timeutil.TimeStampNanoNow() if t.IsSucceed { log.Trace("Hook delivered: %s", t.UUID) } else if !w.IsActive { diff --git a/templates/repo/settings/webhook/history.tmpl b/templates/repo/settings/webhook/history.tmpl index 8eba5cde68..7020bf0ba4 100644 --- a/templates/repo/settings/webhook/history.tmpl +++ b/templates/repo/settings/webhook/history.tmpl @@ -21,7 +21,7 @@ {{.UUID}}
- {{.DeliveredString}} + {{TimeSince .Delivered.AsTime $.locale}}