diff --git a/internal/context/auth.go b/internal/context/auth.go index 021420c57..25625c3d1 100644 --- a/internal/context/auth.go +++ b/internal/context/auth.go @@ -137,8 +137,8 @@ func authenticatedUserID(c *macaron.Context, sess session.Store) (_ int64, isTok } return 0, false } - if err = db.AccessTokens.Save(c.Req.Context(), t); err != nil { - log.Error("UpdateAccessToken: %v", err) + if err = db.AccessTokens.Touch(c.Req.Context(), t.ID); err != nil { + log.Error("Failed to touch access token: %v", err) } return t.UserID, true } diff --git a/internal/db/access_tokens.go b/internal/db/access_tokens.go index bbb7b851c..83b5747d9 100644 --- a/internal/db/access_tokens.go +++ b/internal/db/access_tokens.go @@ -34,9 +34,8 @@ type AccessTokensStore interface { GetBySHA1(ctx context.Context, sha1 string) (*AccessToken, error) // List returns all access tokens belongs to given user. List(ctx context.Context, userID int64) ([]*AccessToken, error) - // Save persists all values of given access token. The Updated field is set to - // current time automatically. - Save(ctx context.Context, t *AccessToken) error + // Touch updates the updated time of the given access token to the current time. + Touch(ctx context.Context, id int64) error } var AccessTokens AccessTokensStore @@ -65,12 +64,6 @@ func (t *AccessToken) BeforeCreate(tx *gorm.DB) error { return nil } -// BeforeUpdate implements the GORM update hook. -func (t *AccessToken) BeforeUpdate(tx *gorm.DB) error { - t.UpdatedUnix = tx.NowFunc().Unix() - return nil -} - // AfterFind implements the GORM query hook. func (t *AccessToken) AfterFind(tx *gorm.DB) error { t.Created = time.Unix(t.CreatedUnix, 0).Local() @@ -116,7 +109,7 @@ func (db *accessTokens) Create(ctx context.Context, userID int64, name string) ( Sha1: sha256[:40], // To pass the column unique constraint, keep the length of SHA1. SHA256: sha256, } - if err = db.DB.WithContext(ctx).Create(accessToken).Error; err != nil { + if err = db.WithContext(ctx).Create(accessToken).Error; err != nil { return nil, err } @@ -166,6 +159,10 @@ func (db *accessTokens) List(ctx context.Context, userID int64) ([]*AccessToken, return tokens, db.WithContext(ctx).Where("uid = ?", userID).Order("id ASC").Find(&tokens).Error } -func (db *accessTokens) Save(ctx context.Context, t *AccessToken) error { - return db.DB.WithContext(ctx).Save(t).Error +func (db *accessTokens) Touch(ctx context.Context, id int64) error { + return db.WithContext(ctx). + Model(new(AccessToken)). + Where("id = ?", id). + UpdateColumn("updated_unix", db.NowFunc().Unix()). + Error } diff --git a/internal/db/access_tokens_test.go b/internal/db/access_tokens_test.go index 7c3024b18..38c41e2d3 100644 --- a/internal/db/access_tokens_test.go +++ b/internal/db/access_tokens_test.go @@ -61,7 +61,7 @@ func TestAccessTokens(t *testing.T) { {"DeleteByID", accessTokensDeleteByID}, {"GetBySHA1", accessTokensGetBySHA}, {"List", accessTokensList}, - {"Save", accessTokensSave}, + {"Touch", accessTokensTouch}, } { t.Run(tc.name, func(t *testing.T) { t.Cleanup(func() { @@ -169,7 +169,7 @@ func accessTokensList(t *testing.T, db *accessTokens) { assert.Equal(t, "user1_2", tokens[1].Name) } -func accessTokensSave(t *testing.T, db *accessTokens) { +func accessTokensTouch(t *testing.T, db *accessTokens) { ctx := context.Background() // Create an access token with name "Test" @@ -179,7 +179,7 @@ func accessTokensSave(t *testing.T, db *accessTokens) { // Updated field is zero now assert.True(t, token.Updated.IsZero()) - err = db.Save(ctx, token) + err = db.Touch(ctx, token.ID) require.NoError(t, err) // Get back from DB should have Updated set diff --git a/internal/db/mocks.go b/internal/db/mocks.go index 95c306953..eaecf7b6f 100644 --- a/internal/db/mocks.go +++ b/internal/db/mocks.go @@ -23,9 +23,9 @@ type MockAccessTokensStore struct { // ListFunc is an instance of a mock function object controlling the // behavior of the method List. ListFunc *AccessTokensStoreListFunc - // SaveFunc is an instance of a mock function object controlling the - // behavior of the method Save. - SaveFunc *AccessTokensStoreSaveFunc + // TouchFunc is an instance of a mock function object controlling the + // behavior of the method Touch. + TouchFunc *AccessTokensStoreTouchFunc } // NewMockAccessTokensStore creates a new mock of the AccessTokensStore @@ -53,8 +53,8 @@ func NewMockAccessTokensStore() *MockAccessTokensStore { return }, }, - SaveFunc: &AccessTokensStoreSaveFunc{ - defaultHook: func(context.Context, *AccessToken) (r0 error) { + TouchFunc: &AccessTokensStoreTouchFunc{ + defaultHook: func(context.Context, int64) (r0 error) { return }, }, @@ -86,9 +86,9 @@ func NewStrictMockAccessTokensStore() *MockAccessTokensStore { panic("unexpected invocation of MockAccessTokensStore.List") }, }, - SaveFunc: &AccessTokensStoreSaveFunc{ - defaultHook: func(context.Context, *AccessToken) error { - panic("unexpected invocation of MockAccessTokensStore.Save") + TouchFunc: &AccessTokensStoreTouchFunc{ + defaultHook: func(context.Context, int64) error { + panic("unexpected invocation of MockAccessTokensStore.Touch") }, }, } @@ -111,8 +111,8 @@ func NewMockAccessTokensStoreFrom(i AccessTokensStore) *MockAccessTokensStore { ListFunc: &AccessTokensStoreListFunc{ defaultHook: i.List, }, - SaveFunc: &AccessTokensStoreSaveFunc{ - defaultHook: i.Save, + TouchFunc: &AccessTokensStoreTouchFunc{ + defaultHook: i.Touch, }, } } @@ -553,35 +553,35 @@ func (c AccessTokensStoreListFuncCall) Results() []interface{} { return []interface{}{c.Result0, c.Result1} } -// AccessTokensStoreSaveFunc describes the behavior when the Save method of -// the parent MockAccessTokensStore instance is invoked. -type AccessTokensStoreSaveFunc struct { - defaultHook func(context.Context, *AccessToken) error - hooks []func(context.Context, *AccessToken) error - history []AccessTokensStoreSaveFuncCall +// AccessTokensStoreTouchFunc describes the behavior when the Touch method +// of the parent MockAccessTokensStore instance is invoked. +type AccessTokensStoreTouchFunc struct { + defaultHook func(context.Context, int64) error + hooks []func(context.Context, int64) error + history []AccessTokensStoreTouchFuncCall mutex sync.Mutex } -// Save delegates to the next hook function in the queue and stores the +// Touch delegates to the next hook function in the queue and stores the // parameter and result values of this invocation. -func (m *MockAccessTokensStore) Save(v0 context.Context, v1 *AccessToken) error { - r0 := m.SaveFunc.nextHook()(v0, v1) - m.SaveFunc.appendCall(AccessTokensStoreSaveFuncCall{v0, v1, r0}) +func (m *MockAccessTokensStore) Touch(v0 context.Context, v1 int64) error { + r0 := m.TouchFunc.nextHook()(v0, v1) + m.TouchFunc.appendCall(AccessTokensStoreTouchFuncCall{v0, v1, r0}) return r0 } -// SetDefaultHook sets function that is called when the Save method of the +// SetDefaultHook sets function that is called when the Touch method of the // parent MockAccessTokensStore instance is invoked and the hook queue is // empty. -func (f *AccessTokensStoreSaveFunc) SetDefaultHook(hook func(context.Context, *AccessToken) error) { +func (f *AccessTokensStoreTouchFunc) SetDefaultHook(hook func(context.Context, int64) error) { f.defaultHook = hook } // PushHook adds a function to the end of hook queue. Each invocation of the -// Save method of the parent MockAccessTokensStore instance invokes the hook -// at the front of the queue and discards it. After the queue is empty, the -// default hook function is invoked for any future action. -func (f *AccessTokensStoreSaveFunc) PushHook(hook func(context.Context, *AccessToken) error) { +// Touch method of the parent MockAccessTokensStore instance invokes the +// hook at the front of the queue and discards it. After the queue is empty, +// the default hook function is invoked for any future action. +func (f *AccessTokensStoreTouchFunc) PushHook(hook func(context.Context, int64) error) { f.mutex.Lock() f.hooks = append(f.hooks, hook) f.mutex.Unlock() @@ -589,20 +589,20 @@ func (f *AccessTokensStoreSaveFunc) PushHook(hook func(context.Context, *AccessT // SetDefaultReturn calls SetDefaultHook with a function that returns the // given values. -func (f *AccessTokensStoreSaveFunc) SetDefaultReturn(r0 error) { - f.SetDefaultHook(func(context.Context, *AccessToken) error { +func (f *AccessTokensStoreTouchFunc) SetDefaultReturn(r0 error) { + f.SetDefaultHook(func(context.Context, int64) error { return r0 }) } // PushReturn calls PushHook with a function that returns the given values. -func (f *AccessTokensStoreSaveFunc) PushReturn(r0 error) { - f.PushHook(func(context.Context, *AccessToken) error { +func (f *AccessTokensStoreTouchFunc) PushReturn(r0 error) { + f.PushHook(func(context.Context, int64) error { return r0 }) } -func (f *AccessTokensStoreSaveFunc) nextHook() func(context.Context, *AccessToken) error { +func (f *AccessTokensStoreTouchFunc) nextHook() func(context.Context, int64) error { f.mutex.Lock() defer f.mutex.Unlock() @@ -615,32 +615,32 @@ func (f *AccessTokensStoreSaveFunc) nextHook() func(context.Context, *AccessToke return hook } -func (f *AccessTokensStoreSaveFunc) appendCall(r0 AccessTokensStoreSaveFuncCall) { +func (f *AccessTokensStoreTouchFunc) appendCall(r0 AccessTokensStoreTouchFuncCall) { f.mutex.Lock() f.history = append(f.history, r0) f.mutex.Unlock() } -// History returns a sequence of AccessTokensStoreSaveFuncCall objects +// History returns a sequence of AccessTokensStoreTouchFuncCall objects // describing the invocations of this function. -func (f *AccessTokensStoreSaveFunc) History() []AccessTokensStoreSaveFuncCall { +func (f *AccessTokensStoreTouchFunc) History() []AccessTokensStoreTouchFuncCall { f.mutex.Lock() - history := make([]AccessTokensStoreSaveFuncCall, len(f.history)) + history := make([]AccessTokensStoreTouchFuncCall, len(f.history)) copy(history, f.history) f.mutex.Unlock() return history } -// AccessTokensStoreSaveFuncCall is an object that describes an invocation -// of method Save on an instance of MockAccessTokensStore. -type AccessTokensStoreSaveFuncCall struct { +// AccessTokensStoreTouchFuncCall is an object that describes an invocation +// of method Touch on an instance of MockAccessTokensStore. +type AccessTokensStoreTouchFuncCall struct { // Arg0 is the value of the 1st argument passed to this method // invocation. Arg0 context.Context // Arg1 is the value of the 2nd argument passed to this method // invocation. - Arg1 *AccessToken + Arg1 int64 // Result0 is the value of the 1st result returned from this method // invocation. Result0 error @@ -648,12 +648,12 @@ type AccessTokensStoreSaveFuncCall struct { // Args returns an interface slice containing the arguments of this // invocation. -func (c AccessTokensStoreSaveFuncCall) Args() []interface{} { +func (c AccessTokensStoreTouchFuncCall) Args() []interface{} { return []interface{}{c.Arg0, c.Arg1} } // Results returns an interface slice containing the results of this // invocation. -func (c AccessTokensStoreSaveFuncCall) Results() []interface{} { +func (c AccessTokensStoreTouchFuncCall) Results() []interface{} { return []interface{}{c.Result0} } diff --git a/internal/route/lfs/route.go b/internal/route/lfs/route.go index 78a45fde2..23ece92b1 100644 --- a/internal/route/lfs/route.go +++ b/internal/route/lfs/route.go @@ -82,8 +82,8 @@ func authenticate() macaron.Handler { } return } - if err = db.AccessTokens.Save(c.Req.Context(), token); err != nil { - log.Error("Failed to update access token: %v", err) + if err = db.AccessTokens.Touch(c.Req.Context(), token.ID); err != nil { + log.Error("Failed to touch access token: %v", err) } user, err = db.Users.GetByID(token.UserID) diff --git a/internal/route/repo/http.go b/internal/route/repo/http.go index 668c4cfa9..0d6632be1 100644 --- a/internal/route/repo/http.go +++ b/internal/route/repo/http.go @@ -142,8 +142,8 @@ func HTTPContexter() macaron.Handler { } return } - if err = db.AccessTokens.Save(c.Req.Context(), token); err != nil { - log.Error("Failed to update access token: %v", err) + if err = db.AccessTokens.Touch(c.Req.Context(), token.ID); err != nil { + log.Error("Failed to touch access token: %v", err) } authUser, err = db.Users.GetByID(token.UserID)