diff --git a/pkg/api/short_url.go b/pkg/api/short_url.go index 2a2f9413ccb..e5e4e72e4c2 100644 --- a/pkg/api/short_url.go +++ b/pkg/api/short_url.go @@ -57,6 +57,11 @@ func (hs *HTTPServer) redirectFromShortURL(c *models.ReqContext) { return } + // Failure to update LastSeenAt should still allow to redirect + if err := hs.ShortURLService.UpdateLastSeenAt(c.Req.Context(), shortURL); err != nil { + hs.log.Error("Failed to update short URL last seen at", "error", err) + } + hs.log.Debug("Redirecting short URL", "path", shortURL.Path) c.Redirect(setting.ToAbsUrl(shortURL.Path), 302) } diff --git a/pkg/services/shorturls/short_url_service.go b/pkg/services/shorturls/short_url_service.go index b2694bc3f4f..5e8fb122b43 100644 --- a/pkg/services/shorturls/short_url_service.go +++ b/pkg/services/shorturls/short_url_service.go @@ -10,6 +10,8 @@ import ( "github.com/grafana/grafana/pkg/util" ) +var getTime = time.Now + func init() { registry.RegisterService(&ShortURLService{}) } @@ -42,6 +44,18 @@ func (s ShortURLService) GetShortURLByUID(ctx context.Context, user *models.Sign return &shortURL, nil } +func (s ShortURLService) UpdateLastSeenAt(ctx context.Context, shortURL *models.ShortUrl) error { + shortURL.LastSeenAt = getTime().Unix() + return s.SQLStore.WithTransactionalDbSession(ctx, func(dbSession *sqlstore.DBSession) error { + _, err := dbSession.ID(shortURL.Id).Update(shortURL) + if err != nil { + return err + } + + return nil + }) +} + func (s ShortURLService) CreateShortURL(ctx context.Context, user *models.SignedInUser, path string) (*models.ShortUrl, error) { now := time.Now().Unix() shortURL := models.ShortUrl{ diff --git a/pkg/services/shorturls/short_url_service_test.go b/pkg/services/shorturls/short_url_service_test.go index 64c93e37305..4cc2db24d1b 100644 --- a/pkg/services/shorturls/short_url_service_test.go +++ b/pkg/services/shorturls/short_url_service_test.go @@ -3,6 +3,7 @@ package shorturls import ( "context" "testing" + "time" "github.com/grafana/grafana/pkg/models" "github.com/grafana/grafana/pkg/services/sqlstore" @@ -27,6 +28,25 @@ func TestShortURLService(t *testing.T) { require.NoError(t, err) require.NotNil(t, existingShortURL) require.Equal(t, refPath, existingShortURL.Path) + + t.Run("and update last seen at", func(t *testing.T) { + origGetTime := getTime + t.Cleanup(func() { + getTime = origGetTime + }) + + expectedTime := time.Date(2020, time.November, 27, 6, 5, 1, 0, time.UTC) + getTime = func() time.Time { + return expectedTime + } + + err := service.UpdateLastSeenAt(context.Background(), existingShortURL) + require.NoError(t, err) + + updatedShortURL, err := service.GetShortURLByUID(context.Background(), user, existingShortURL.Uid) + require.NoError(t, err) + require.Equal(t, expectedTime.Unix(), updatedShortURL.LastSeenAt) + }) }) t.Run("User cannot look up nonexistent short URLs", func(t *testing.T) {