| @@ -0,0 +1,4 @@ | |||
| - | |||
| id: 1 | |||
| user_id: 4 | |||
| follow_id: 2 | |||
| @@ -26,6 +26,7 @@ | |||
| avatar_email: user2@example.com | |||
| num_repos: 2 | |||
| num_stars: 2 | |||
| num_followers: 1 | |||
| - | |||
| id: 3 | |||
| @@ -56,6 +57,7 @@ | |||
| avatar: avatar4 | |||
| avatar_email: user4@example.com | |||
| num_repos: 0 | |||
| num_following: 1 | |||
| - | |||
| id: 5 | |||
| @@ -72,6 +74,7 @@ | |||
| num_repos: 1 | |||
| allow_create_organization: false | |||
| is_active: true | |||
| num_following: 0 | |||
| - | |||
| id: 6 | |||
| @@ -1292,78 +1292,6 @@ func SearchUserByName(opts *SearchUserOptions) (users []*User, _ int64, _ error) | |||
| return users, count, sess.Find(&users) | |||
| } | |||
| // ___________ .__ .__ | |||
| // \_ _____/___ | | | | ______ _ __ | |||
| // | __)/ _ \| | | | / _ \ \/ \/ / | |||
| // | \( <_> ) |_| |_( <_> ) / | |||
| // \___ / \____/|____/____/\____/ \/\_/ | |||
| // \/ | |||
| // Follow represents relations of user and his/her followers. | |||
| type Follow struct { | |||
| ID int64 `xorm:"pk autoincr"` | |||
| UserID int64 `xorm:"UNIQUE(follow)"` | |||
| FollowID int64 `xorm:"UNIQUE(follow)"` | |||
| } | |||
| // IsFollowing returns true if user is following followID. | |||
| func IsFollowing(userID, followID int64) bool { | |||
| has, _ := x.Get(&Follow{UserID: userID, FollowID: followID}) | |||
| return has | |||
| } | |||
| // FollowUser marks someone be another's follower. | |||
| func FollowUser(userID, followID int64) (err error) { | |||
| if userID == followID || IsFollowing(userID, followID) { | |||
| return nil | |||
| } | |||
| sess := x.NewSession() | |||
| defer sessionRelease(sess) | |||
| if err = sess.Begin(); err != nil { | |||
| return err | |||
| } | |||
| if _, err = sess.Insert(&Follow{UserID: userID, FollowID: followID}); err != nil { | |||
| return err | |||
| } | |||
| if _, err = sess.Exec("UPDATE `user` SET num_followers = num_followers + 1 WHERE id = ?", followID); err != nil { | |||
| return err | |||
| } | |||
| if _, err = sess.Exec("UPDATE `user` SET num_following = num_following + 1 WHERE id = ?", userID); err != nil { | |||
| return err | |||
| } | |||
| return sess.Commit() | |||
| } | |||
| // UnfollowUser unmarks someone as another's follower. | |||
| func UnfollowUser(userID, followID int64) (err error) { | |||
| if userID == followID || !IsFollowing(userID, followID) { | |||
| return nil | |||
| } | |||
| sess := x.NewSession() | |||
| defer sessionRelease(sess) | |||
| if err = sess.Begin(); err != nil { | |||
| return err | |||
| } | |||
| if _, err = sess.Delete(&Follow{UserID: userID, FollowID: followID}); err != nil { | |||
| return err | |||
| } | |||
| if _, err = sess.Exec("UPDATE `user` SET num_followers = num_followers - 1 WHERE id = ?", followID); err != nil { | |||
| return err | |||
| } | |||
| if _, err = sess.Exec("UPDATE `user` SET num_following = num_following - 1 WHERE id = ?", userID); err != nil { | |||
| return err | |||
| } | |||
| return sess.Commit() | |||
| } | |||
| // GetStarredRepos returns the repos starred by a particular user | |||
| func GetStarredRepos(userID int64, private bool) ([]*Repository, error) { | |||
| sess := x.Where("star.uid=?", userID). | |||
| @@ -0,0 +1,71 @@ | |||
| // Copyright 2017 The Gitea Authors. All rights reserved. | |||
| // Use of this source code is governed by a MIT-style | |||
| // license that can be found in the LICENSE file. | |||
| package models | |||
| // Follow represents relations of user and his/her followers. | |||
| type Follow struct { | |||
| ID int64 `xorm:"pk autoincr"` | |||
| UserID int64 `xorm:"UNIQUE(follow)"` | |||
| FollowID int64 `xorm:"UNIQUE(follow)"` | |||
| } | |||
| // IsFollowing returns true if user is following followID. | |||
| func IsFollowing(userID, followID int64) bool { | |||
| has, _ := x.Get(&Follow{UserID: userID, FollowID: followID}) | |||
| return has | |||
| } | |||
| // FollowUser marks someone be another's follower. | |||
| func FollowUser(userID, followID int64) (err error) { | |||
| if userID == followID || IsFollowing(userID, followID) { | |||
| return nil | |||
| } | |||
| sess := x.NewSession() | |||
| defer sessionRelease(sess) | |||
| if err = sess.Begin(); err != nil { | |||
| return err | |||
| } | |||
| if _, err = sess.Insert(&Follow{UserID: userID, FollowID: followID}); err != nil { | |||
| return err | |||
| } | |||
| if _, err = sess.Exec("UPDATE `user` SET num_followers = num_followers + 1 WHERE id = ?", followID); err != nil { | |||
| return err | |||
| } | |||
| if _, err = sess.Exec("UPDATE `user` SET num_following = num_following + 1 WHERE id = ?", userID); err != nil { | |||
| return err | |||
| } | |||
| return sess.Commit() | |||
| } | |||
| // UnfollowUser unmarks someone as another's follower. | |||
| func UnfollowUser(userID, followID int64) (err error) { | |||
| if userID == followID || !IsFollowing(userID, followID) { | |||
| return nil | |||
| } | |||
| sess := x.NewSession() | |||
| defer sessionRelease(sess) | |||
| if err = sess.Begin(); err != nil { | |||
| return err | |||
| } | |||
| if _, err = sess.Delete(&Follow{UserID: userID, FollowID: followID}); err != nil { | |||
| return err | |||
| } | |||
| if _, err = sess.Exec("UPDATE `user` SET num_followers = num_followers - 1 WHERE id = ?", followID); err != nil { | |||
| return err | |||
| } | |||
| if _, err = sess.Exec("UPDATE `user` SET num_following = num_following - 1 WHERE id = ?", userID); err != nil { | |||
| return err | |||
| } | |||
| return sess.Commit() | |||
| } | |||
| @@ -0,0 +1,45 @@ | |||
| package models | |||
| import ( | |||
| "testing" | |||
| "github.com/stretchr/testify/assert" | |||
| ) | |||
| func TestIsFollowing(t *testing.T) { | |||
| assert.NoError(t, PrepareTestDatabase()) | |||
| assert.True(t, IsFollowing(4, 2)) | |||
| assert.False(t, IsFollowing(2, 4)) | |||
| assert.False(t, IsFollowing(5, NonexistentID)) | |||
| assert.False(t, IsFollowing(NonexistentID, 5)) | |||
| assert.False(t, IsFollowing(NonexistentID, NonexistentID)) | |||
| } | |||
| func TestFollowUser(t *testing.T) { | |||
| assert.NoError(t, PrepareTestDatabase()) | |||
| testSuccess := func(followerID, followedID int64) { | |||
| assert.NoError(t, FollowUser(followerID, followedID)) | |||
| AssertExistsAndLoadBean(t, &Follow{UserID: followerID, FollowID: followedID}) | |||
| } | |||
| testSuccess(4, 2) | |||
| testSuccess(5, 2) | |||
| assert.NoError(t, FollowUser(2, 2)) | |||
| CheckConsistencyFor(t, &User{}) | |||
| } | |||
| func TestUnfollowUser(t *testing.T) { | |||
| assert.NoError(t, PrepareTestDatabase()) | |||
| testSuccess := func(followerID, followedID int64) { | |||
| assert.NoError(t, UnfollowUser(followerID, followedID)) | |||
| AssertNotExistsBean(t, &Follow{UserID: followerID, FollowID: followedID}) | |||
| } | |||
| testSuccess(4, 2) | |||
| testSuccess(5, 2) | |||
| testSuccess(2, 2) | |||
| CheckConsistencyFor(t, &User{}) | |||
| } | |||