mirror of
				https://github.com/go-gitea/gitea.git
				synced 2025-11-04 01:34:27 +00:00 
			
		
		
		
	Fix activity feed (#1779)
* Fix activity feed Preserve actions after user/repo name change * Add missing comment * Fix migration, and remove fields completely * Tests
This commit is contained in:
		@@ -6,7 +6,7 @@ DB_TYPE  = mysql
 | 
				
			|||||||
HOST     = 127.0.0.1:3306
 | 
					HOST     = 127.0.0.1:3306
 | 
				
			||||||
NAME     = testgitea
 | 
					NAME     = testgitea
 | 
				
			||||||
USER     = root
 | 
					USER     = root
 | 
				
			||||||
PASSWD   =
 | 
					PASSWD   = 
 | 
				
			||||||
SSL_MODE = disable
 | 
					SSL_MODE = disable
 | 
				
			||||||
PATH     = data/gitea.db
 | 
					PATH     = data/gitea.db
 | 
				
			||||||
 | 
					
 | 
				
			||||||
@@ -26,14 +26,14 @@ OFFLINE_MODE     = false
 | 
				
			|||||||
ENABLED = false
 | 
					ENABLED = false
 | 
				
			||||||
 | 
					
 | 
				
			||||||
[service]
 | 
					[service]
 | 
				
			||||||
REGISTER_EMAIL_CONFIRM     = false
 | 
					REGISTER_EMAIL_CONFIRM            = false
 | 
				
			||||||
ENABLE_NOTIFY_MAIL         = false
 | 
					ENABLE_NOTIFY_MAIL                = false
 | 
				
			||||||
DISABLE_REGISTRATION       = false
 | 
					DISABLE_REGISTRATION              = false
 | 
				
			||||||
ENABLE_CAPTCHA             = false
 | 
					ENABLE_CAPTCHA                    = false
 | 
				
			||||||
REQUIRE_SIGNIN_VIEW        = false
 | 
					REQUIRE_SIGNIN_VIEW               = false
 | 
				
			||||||
DEFAULT_KEEP_EMAIL_PRIVATE = false
 | 
					DEFAULT_KEEP_EMAIL_PRIVATE        = false
 | 
				
			||||||
DEFAULT_ALLOW_CREATE_ORGANIZATION = true
 | 
					DEFAULT_ALLOW_CREATE_ORGANIZATION = true
 | 
				
			||||||
NO_REPLY_ADDRESS           = noreply.example.org
 | 
					NO_REPLY_ADDRESS                  = noreply.example.org
 | 
				
			||||||
 | 
					
 | 
				
			||||||
[picture]
 | 
					[picture]
 | 
				
			||||||
DISABLE_GRAVATAR        = false
 | 
					DISABLE_GRAVATAR        = false
 | 
				
			||||||
@@ -53,5 +53,7 @@ LEVEL = Warn
 | 
				
			|||||||
LEVEL = Info
 | 
					LEVEL = Info
 | 
				
			||||||
 | 
					
 | 
				
			||||||
[security]
 | 
					[security]
 | 
				
			||||||
INSTALL_LOCK = true
 | 
					INSTALL_LOCK   = true
 | 
				
			||||||
SECRET_KEY   = 9pCviYTWSb
 | 
					SECRET_KEY     = 9pCviYTWSb
 | 
				
			||||||
 | 
					INTERNAL_TOKEN = eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJuYmYiOjE0OTU1NTE2MTh9.hhSVGOANkaKk3vfCd2jDOIww4pUk0xtg9JRde5UogyQ
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 
 | 
				
			|||||||
							
								
								
									
										144
									
								
								models/action.go
									
									
									
									
									
								
							
							
						
						
									
										144
									
								
								models/action.go
									
									
									
									
									
								
							@@ -70,20 +70,18 @@ func init() {
 | 
				
			|||||||
// repository. It implemented interface base.Actioner so that can be
 | 
					// repository. It implemented interface base.Actioner so that can be
 | 
				
			||||||
// used in template render.
 | 
					// used in template render.
 | 
				
			||||||
type Action struct {
 | 
					type Action struct {
 | 
				
			||||||
	ID           int64 `xorm:"pk autoincr"`
 | 
						ID          int64 `xorm:"pk autoincr"`
 | 
				
			||||||
	UserID       int64 `xorm:"INDEX"` // Receiver user id.
 | 
						UserID      int64 `xorm:"INDEX"` // Receiver user id.
 | 
				
			||||||
	OpType       ActionType
 | 
						OpType      ActionType
 | 
				
			||||||
	ActUserID    int64  `xorm:"INDEX"` // Action user id.
 | 
						ActUserID   int64       `xorm:"INDEX"` // Action user id.
 | 
				
			||||||
	ActUserName  string // Action user name.
 | 
						ActUser     *User       `xorm:"-"`
 | 
				
			||||||
	ActAvatar    string `xorm:"-"`
 | 
						RepoID      int64       `xorm:"INDEX"`
 | 
				
			||||||
	RepoID       int64  `xorm:"INDEX"`
 | 
						Repo        *Repository `xorm:"-"`
 | 
				
			||||||
	RepoUserName string
 | 
						RefName     string
 | 
				
			||||||
	RepoName     string
 | 
						IsPrivate   bool      `xorm:"INDEX NOT NULL DEFAULT false"`
 | 
				
			||||||
	RefName      string
 | 
						Content     string    `xorm:"TEXT"`
 | 
				
			||||||
	IsPrivate    bool      `xorm:"INDEX NOT NULL DEFAULT false"`
 | 
						Created     time.Time `xorm:"-"`
 | 
				
			||||||
	Content      string    `xorm:"TEXT"`
 | 
						CreatedUnix int64     `xorm:"INDEX"`
 | 
				
			||||||
	Created      time.Time `xorm:"-"`
 | 
					 | 
				
			||||||
	CreatedUnix  int64     `xorm:"INDEX"`
 | 
					 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
// BeforeInsert will be invoked by XORM before inserting a record
 | 
					// BeforeInsert will be invoked by XORM before inserting a record
 | 
				
			||||||
@@ -106,42 +104,71 @@ func (a *Action) GetOpType() int {
 | 
				
			|||||||
	return int(a.OpType)
 | 
						return int(a.OpType)
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					func (a *Action) loadActUser() {
 | 
				
			||||||
 | 
						if a.ActUser != nil {
 | 
				
			||||||
 | 
							return
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
						var err error
 | 
				
			||||||
 | 
						a.ActUser, err = GetUserByID(a.ActUserID)
 | 
				
			||||||
 | 
						if err == nil {
 | 
				
			||||||
 | 
							return
 | 
				
			||||||
 | 
						} else if IsErrUserNotExist(err) {
 | 
				
			||||||
 | 
							a.ActUser = NewGhostUser()
 | 
				
			||||||
 | 
						} else {
 | 
				
			||||||
 | 
							log.Error(4, "GetUserByID(%d): %v", a.ActUserID, err)
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					func (a *Action) loadRepo() {
 | 
				
			||||||
 | 
						if a.ActUser != nil {
 | 
				
			||||||
 | 
							return
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
						var err error
 | 
				
			||||||
 | 
						a.Repo, err = GetRepositoryByID(a.RepoID)
 | 
				
			||||||
 | 
						if err != nil {
 | 
				
			||||||
 | 
							log.Error(4, "GetRepositoryByID(%d): %v", a.RepoID, err)
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
// GetActUserName gets the action's user name.
 | 
					// GetActUserName gets the action's user name.
 | 
				
			||||||
func (a *Action) GetActUserName() string {
 | 
					func (a *Action) GetActUserName() string {
 | 
				
			||||||
	return a.ActUserName
 | 
						a.loadActUser()
 | 
				
			||||||
 | 
						return a.ActUser.Name
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
// ShortActUserName gets the action's user name trimmed to max 20
 | 
					// ShortActUserName gets the action's user name trimmed to max 20
 | 
				
			||||||
// chars.
 | 
					// chars.
 | 
				
			||||||
func (a *Action) ShortActUserName() string {
 | 
					func (a *Action) ShortActUserName() string {
 | 
				
			||||||
	return base.EllipsisString(a.ActUserName, 20)
 | 
						return base.EllipsisString(a.GetActUserName(), 20)
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
// GetRepoUserName returns the name of the action repository owner.
 | 
					// GetRepoUserName returns the name of the action repository owner.
 | 
				
			||||||
func (a *Action) GetRepoUserName() string {
 | 
					func (a *Action) GetRepoUserName() string {
 | 
				
			||||||
	return a.RepoUserName
 | 
						a.loadRepo()
 | 
				
			||||||
 | 
						return a.Repo.MustOwner().Name
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
// ShortRepoUserName returns the name of the action repository owner
 | 
					// ShortRepoUserName returns the name of the action repository owner
 | 
				
			||||||
// trimmed to max 20 chars.
 | 
					// trimmed to max 20 chars.
 | 
				
			||||||
func (a *Action) ShortRepoUserName() string {
 | 
					func (a *Action) ShortRepoUserName() string {
 | 
				
			||||||
	return base.EllipsisString(a.RepoUserName, 20)
 | 
						return base.EllipsisString(a.GetRepoUserName(), 20)
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
// GetRepoName returns the name of the action repository.
 | 
					// GetRepoName returns the name of the action repository.
 | 
				
			||||||
func (a *Action) GetRepoName() string {
 | 
					func (a *Action) GetRepoName() string {
 | 
				
			||||||
	return a.RepoName
 | 
						a.loadRepo()
 | 
				
			||||||
 | 
						return a.Repo.Name
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
// ShortRepoName returns the name of the action repository
 | 
					// ShortRepoName returns the name of the action repository
 | 
				
			||||||
// trimmed to max 33 chars.
 | 
					// trimmed to max 33 chars.
 | 
				
			||||||
func (a *Action) ShortRepoName() string {
 | 
					func (a *Action) ShortRepoName() string {
 | 
				
			||||||
	return base.EllipsisString(a.RepoName, 33)
 | 
						return base.EllipsisString(a.GetRepoName(), 33)
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
// GetRepoPath returns the virtual path to the action repository.
 | 
					// GetRepoPath returns the virtual path to the action repository.
 | 
				
			||||||
func (a *Action) GetRepoPath() string {
 | 
					func (a *Action) GetRepoPath() string {
 | 
				
			||||||
	return path.Join(a.RepoUserName, a.RepoName)
 | 
						return path.Join(a.GetRepoUserName(), a.GetRepoName())
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
// ShortRepoPath returns the virtual path to the action repository
 | 
					// ShortRepoPath returns the virtual path to the action repository
 | 
				
			||||||
@@ -205,13 +232,12 @@ func (a *Action) GetIssueContent() string {
 | 
				
			|||||||
 | 
					
 | 
				
			||||||
func newRepoAction(e Engine, u *User, repo *Repository) (err error) {
 | 
					func newRepoAction(e Engine, u *User, repo *Repository) (err error) {
 | 
				
			||||||
	if err = notifyWatchers(e, &Action{
 | 
						if err = notifyWatchers(e, &Action{
 | 
				
			||||||
		ActUserID:    u.ID,
 | 
							ActUserID: u.ID,
 | 
				
			||||||
		ActUserName:  u.Name,
 | 
							ActUser:   u,
 | 
				
			||||||
		OpType:       ActionCreateRepo,
 | 
							OpType:    ActionCreateRepo,
 | 
				
			||||||
		RepoID:       repo.ID,
 | 
							RepoID:    repo.ID,
 | 
				
			||||||
		RepoUserName: repo.Owner.Name,
 | 
							Repo:      repo,
 | 
				
			||||||
		RepoName:     repo.Name,
 | 
							IsPrivate: repo.IsPrivate,
 | 
				
			||||||
		IsPrivate:    repo.IsPrivate,
 | 
					 | 
				
			||||||
	}); err != nil {
 | 
						}); err != nil {
 | 
				
			||||||
		return fmt.Errorf("notify watchers '%d/%d': %v", u.ID, repo.ID, err)
 | 
							return fmt.Errorf("notify watchers '%d/%d': %v", u.ID, repo.ID, err)
 | 
				
			||||||
	}
 | 
						}
 | 
				
			||||||
@@ -227,14 +253,13 @@ func NewRepoAction(u *User, repo *Repository) (err error) {
 | 
				
			|||||||
 | 
					
 | 
				
			||||||
func renameRepoAction(e Engine, actUser *User, oldRepoName string, repo *Repository) (err error) {
 | 
					func renameRepoAction(e Engine, actUser *User, oldRepoName string, repo *Repository) (err error) {
 | 
				
			||||||
	if err = notifyWatchers(e, &Action{
 | 
						if err = notifyWatchers(e, &Action{
 | 
				
			||||||
		ActUserID:    actUser.ID,
 | 
							ActUserID: actUser.ID,
 | 
				
			||||||
		ActUserName:  actUser.Name,
 | 
							ActUser:   actUser,
 | 
				
			||||||
		OpType:       ActionRenameRepo,
 | 
							OpType:    ActionRenameRepo,
 | 
				
			||||||
		RepoID:       repo.ID,
 | 
							RepoID:    repo.ID,
 | 
				
			||||||
		RepoUserName: repo.Owner.Name,
 | 
							Repo:      repo,
 | 
				
			||||||
		RepoName:     repo.Name,
 | 
							IsPrivate: repo.IsPrivate,
 | 
				
			||||||
		IsPrivate:    repo.IsPrivate,
 | 
							Content:   oldRepoName,
 | 
				
			||||||
		Content:      oldRepoName,
 | 
					 | 
				
			||||||
	}); err != nil {
 | 
						}); err != nil {
 | 
				
			||||||
		return fmt.Errorf("notify watchers: %v", err)
 | 
							return fmt.Errorf("notify watchers: %v", err)
 | 
				
			||||||
	}
 | 
						}
 | 
				
			||||||
@@ -521,15 +546,14 @@ func CommitRepoAction(opts CommitRepoActionOptions) error {
 | 
				
			|||||||
 | 
					
 | 
				
			||||||
	refName := git.RefEndName(opts.RefFullName)
 | 
						refName := git.RefEndName(opts.RefFullName)
 | 
				
			||||||
	if err = NotifyWatchers(&Action{
 | 
						if err = NotifyWatchers(&Action{
 | 
				
			||||||
		ActUserID:    pusher.ID,
 | 
							ActUserID: pusher.ID,
 | 
				
			||||||
		ActUserName:  pusher.Name,
 | 
							ActUser:   pusher,
 | 
				
			||||||
		OpType:       opType,
 | 
							OpType:    opType,
 | 
				
			||||||
		Content:      string(data),
 | 
							Content:   string(data),
 | 
				
			||||||
		RepoID:       repo.ID,
 | 
							RepoID:    repo.ID,
 | 
				
			||||||
		RepoUserName: repo.MustOwner().Name,
 | 
							Repo:      repo,
 | 
				
			||||||
		RepoName:     repo.Name,
 | 
							RefName:   refName,
 | 
				
			||||||
		RefName:      refName,
 | 
							IsPrivate: repo.IsPrivate,
 | 
				
			||||||
		IsPrivate:    repo.IsPrivate,
 | 
					 | 
				
			||||||
	}); err != nil {
 | 
						}); err != nil {
 | 
				
			||||||
		return fmt.Errorf("NotifyWatchers: %v", err)
 | 
							return fmt.Errorf("NotifyWatchers: %v", err)
 | 
				
			||||||
	}
 | 
						}
 | 
				
			||||||
@@ -598,14 +622,13 @@ func CommitRepoAction(opts CommitRepoActionOptions) error {
 | 
				
			|||||||
 | 
					
 | 
				
			||||||
func transferRepoAction(e Engine, doer, oldOwner *User, repo *Repository) (err error) {
 | 
					func transferRepoAction(e Engine, doer, oldOwner *User, repo *Repository) (err error) {
 | 
				
			||||||
	if err = notifyWatchers(e, &Action{
 | 
						if err = notifyWatchers(e, &Action{
 | 
				
			||||||
		ActUserID:    doer.ID,
 | 
							ActUserID: doer.ID,
 | 
				
			||||||
		ActUserName:  doer.Name,
 | 
							ActUser:   doer,
 | 
				
			||||||
		OpType:       ActionTransferRepo,
 | 
							OpType:    ActionTransferRepo,
 | 
				
			||||||
		RepoID:       repo.ID,
 | 
							RepoID:    repo.ID,
 | 
				
			||||||
		RepoUserName: repo.Owner.Name,
 | 
							Repo:      repo,
 | 
				
			||||||
		RepoName:     repo.Name,
 | 
							IsPrivate: repo.IsPrivate,
 | 
				
			||||||
		IsPrivate:    repo.IsPrivate,
 | 
							Content:   path.Join(oldOwner.Name, repo.Name),
 | 
				
			||||||
		Content:      path.Join(oldOwner.Name, repo.Name),
 | 
					 | 
				
			||||||
	}); err != nil {
 | 
						}); err != nil {
 | 
				
			||||||
		return fmt.Errorf("notifyWatchers: %v", err)
 | 
							return fmt.Errorf("notifyWatchers: %v", err)
 | 
				
			||||||
	}
 | 
						}
 | 
				
			||||||
@@ -628,14 +651,13 @@ func TransferRepoAction(doer, oldOwner *User, repo *Repository) error {
 | 
				
			|||||||
 | 
					
 | 
				
			||||||
func mergePullRequestAction(e Engine, doer *User, repo *Repository, issue *Issue) error {
 | 
					func mergePullRequestAction(e Engine, doer *User, repo *Repository, issue *Issue) error {
 | 
				
			||||||
	return notifyWatchers(e, &Action{
 | 
						return notifyWatchers(e, &Action{
 | 
				
			||||||
		ActUserID:    doer.ID,
 | 
							ActUserID: doer.ID,
 | 
				
			||||||
		ActUserName:  doer.Name,
 | 
							ActUser:   doer,
 | 
				
			||||||
		OpType:       ActionMergePullRequest,
 | 
							OpType:    ActionMergePullRequest,
 | 
				
			||||||
		Content:      fmt.Sprintf("%d|%s", issue.Index, issue.Title),
 | 
							Content:   fmt.Sprintf("%d|%s", issue.Index, issue.Title),
 | 
				
			||||||
		RepoID:       repo.ID,
 | 
							RepoID:    repo.ID,
 | 
				
			||||||
		RepoUserName: repo.Owner.Name,
 | 
							Repo:      repo,
 | 
				
			||||||
		RepoName:     repo.Name,
 | 
							IsPrivate: repo.IsPrivate,
 | 
				
			||||||
		IsPrivate:    repo.IsPrivate,
 | 
					 | 
				
			||||||
	})
 | 
						})
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 
 | 
				
			|||||||
@@ -1,6 +1,7 @@
 | 
				
			|||||||
package models
 | 
					package models
 | 
				
			||||||
 | 
					
 | 
				
			||||||
import (
 | 
					import (
 | 
				
			||||||
 | 
						"path"
 | 
				
			||||||
	"strings"
 | 
						"strings"
 | 
				
			||||||
	"testing"
 | 
						"testing"
 | 
				
			||||||
 | 
					
 | 
				
			||||||
@@ -10,22 +11,21 @@ import (
 | 
				
			|||||||
)
 | 
					)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
func TestAction_GetRepoPath(t *testing.T) {
 | 
					func TestAction_GetRepoPath(t *testing.T) {
 | 
				
			||||||
	action := &Action{
 | 
						assert.NoError(t, PrepareTestDatabase())
 | 
				
			||||||
		RepoUserName: "username",
 | 
						repo := AssertExistsAndLoadBean(t, &Repository{}).(*Repository)
 | 
				
			||||||
		RepoName:     "reponame",
 | 
						owner := AssertExistsAndLoadBean(t, &User{ID: repo.OwnerID}).(*User)
 | 
				
			||||||
	}
 | 
						action := &Action{RepoID: repo.ID}
 | 
				
			||||||
	assert.Equal(t, "username/reponame", action.GetRepoPath())
 | 
						assert.Equal(t, path.Join(owner.Name, repo.Name), action.GetRepoPath())
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
func TestAction_GetRepoLink(t *testing.T) {
 | 
					func TestAction_GetRepoLink(t *testing.T) {
 | 
				
			||||||
	action := &Action{
 | 
						assert.NoError(t, PrepareTestDatabase())
 | 
				
			||||||
		RepoUserName: "username",
 | 
						repo := AssertExistsAndLoadBean(t, &Repository{}).(*Repository)
 | 
				
			||||||
		RepoName:     "reponame",
 | 
						owner := AssertExistsAndLoadBean(t, &User{ID: repo.OwnerID}).(*User)
 | 
				
			||||||
	}
 | 
						action := &Action{RepoID: repo.ID}
 | 
				
			||||||
	setting.AppSubURL = "/suburl/"
 | 
						setting.AppSubURL = "/suburl/"
 | 
				
			||||||
	assert.Equal(t, "/suburl/username/reponame", action.GetRepoLink())
 | 
						expected := path.Join(setting.AppSubURL, owner.Name, repo.Name)
 | 
				
			||||||
	setting.AppSubURL = ""
 | 
						assert.Equal(t, expected, action.GetRepoLink())
 | 
				
			||||||
	assert.Equal(t, "/username/reponame", action.GetRepoLink())
 | 
					 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
func TestNewRepoAction(t *testing.T) {
 | 
					func TestNewRepoAction(t *testing.T) {
 | 
				
			||||||
@@ -36,13 +36,12 @@ func TestNewRepoAction(t *testing.T) {
 | 
				
			|||||||
	repo.Owner = user
 | 
						repo.Owner = user
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	actionBean := &Action{
 | 
						actionBean := &Action{
 | 
				
			||||||
		OpType:       ActionCreateRepo,
 | 
							OpType:    ActionCreateRepo,
 | 
				
			||||||
		ActUserID:    user.ID,
 | 
							ActUserID: user.ID,
 | 
				
			||||||
		RepoID:       repo.ID,
 | 
							RepoID:    repo.ID,
 | 
				
			||||||
		ActUserName:  user.Name,
 | 
							ActUser:   user,
 | 
				
			||||||
		RepoName:     repo.Name,
 | 
							Repo:      repo,
 | 
				
			||||||
		RepoUserName: repo.Owner.Name,
 | 
							IsPrivate: repo.IsPrivate,
 | 
				
			||||||
		IsPrivate:    repo.IsPrivate,
 | 
					 | 
				
			||||||
	}
 | 
						}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	AssertNotExistsBean(t, actionBean)
 | 
						AssertNotExistsBean(t, actionBean)
 | 
				
			||||||
@@ -64,14 +63,13 @@ func TestRenameRepoAction(t *testing.T) {
 | 
				
			|||||||
	repo.LowerName = strings.ToLower(newRepoName)
 | 
						repo.LowerName = strings.ToLower(newRepoName)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	actionBean := &Action{
 | 
						actionBean := &Action{
 | 
				
			||||||
		OpType:       ActionRenameRepo,
 | 
							OpType:    ActionRenameRepo,
 | 
				
			||||||
		ActUserID:    user.ID,
 | 
							ActUserID: user.ID,
 | 
				
			||||||
		ActUserName:  user.Name,
 | 
							ActUser:   user,
 | 
				
			||||||
		RepoID:       repo.ID,
 | 
							RepoID:    repo.ID,
 | 
				
			||||||
		RepoName:     repo.Name,
 | 
							Repo:      repo,
 | 
				
			||||||
		RepoUserName: repo.Owner.Name,
 | 
							IsPrivate: repo.IsPrivate,
 | 
				
			||||||
		IsPrivate:    repo.IsPrivate,
 | 
							Content:   oldRepoName,
 | 
				
			||||||
		Content:      oldRepoName,
 | 
					 | 
				
			||||||
	}
 | 
						}
 | 
				
			||||||
	AssertNotExistsBean(t, actionBean)
 | 
						AssertNotExistsBean(t, actionBean)
 | 
				
			||||||
	assert.NoError(t, RenameRepoAction(user, oldRepoName, repo))
 | 
						assert.NoError(t, RenameRepoAction(user, oldRepoName, repo))
 | 
				
			||||||
@@ -232,13 +230,13 @@ func TestCommitRepoAction(t *testing.T) {
 | 
				
			|||||||
	pushCommits.Len = len(pushCommits.Commits)
 | 
						pushCommits.Len = len(pushCommits.Commits)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	actionBean := &Action{
 | 
						actionBean := &Action{
 | 
				
			||||||
		OpType:      ActionCommitRepo,
 | 
							OpType:    ActionCommitRepo,
 | 
				
			||||||
		ActUserID:   user.ID,
 | 
							ActUserID: user.ID,
 | 
				
			||||||
		ActUserName: user.Name,
 | 
							ActUser:   user,
 | 
				
			||||||
		RepoID:      repo.ID,
 | 
							RepoID:    repo.ID,
 | 
				
			||||||
		RepoName:    repo.Name,
 | 
							Repo:      repo,
 | 
				
			||||||
		RefName:     "refName",
 | 
							RefName:   "refName",
 | 
				
			||||||
		IsPrivate:   repo.IsPrivate,
 | 
							IsPrivate: repo.IsPrivate,
 | 
				
			||||||
	}
 | 
						}
 | 
				
			||||||
	AssertNotExistsBean(t, actionBean)
 | 
						AssertNotExistsBean(t, actionBean)
 | 
				
			||||||
	assert.NoError(t, CommitRepoAction(CommitRepoActionOptions{
 | 
						assert.NoError(t, CommitRepoAction(CommitRepoActionOptions{
 | 
				
			||||||
@@ -265,13 +263,12 @@ func TestTransferRepoAction(t *testing.T) {
 | 
				
			|||||||
	repo.Owner = user4
 | 
						repo.Owner = user4
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	actionBean := &Action{
 | 
						actionBean := &Action{
 | 
				
			||||||
		OpType:       ActionTransferRepo,
 | 
							OpType:    ActionTransferRepo,
 | 
				
			||||||
		ActUserID:    user2.ID,
 | 
							ActUserID: user2.ID,
 | 
				
			||||||
		ActUserName:  user2.Name,
 | 
							ActUser:   user2,
 | 
				
			||||||
		RepoID:       repo.ID,
 | 
							RepoID:    repo.ID,
 | 
				
			||||||
		RepoName:     repo.Name,
 | 
							Repo:      repo,
 | 
				
			||||||
		RepoUserName: repo.Owner.Name,
 | 
							IsPrivate: repo.IsPrivate,
 | 
				
			||||||
		IsPrivate:    repo.IsPrivate,
 | 
					 | 
				
			||||||
	}
 | 
						}
 | 
				
			||||||
	AssertNotExistsBean(t, actionBean)
 | 
						AssertNotExistsBean(t, actionBean)
 | 
				
			||||||
	assert.NoError(t, TransferRepoAction(user2, user2, repo))
 | 
						assert.NoError(t, TransferRepoAction(user2, user2, repo))
 | 
				
			||||||
@@ -290,13 +287,12 @@ func TestMergePullRequestAction(t *testing.T) {
 | 
				
			|||||||
	issue := AssertExistsAndLoadBean(t, &Issue{ID: 3, RepoID: repo.ID}).(*Issue)
 | 
						issue := AssertExistsAndLoadBean(t, &Issue{ID: 3, RepoID: repo.ID}).(*Issue)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	actionBean := &Action{
 | 
						actionBean := &Action{
 | 
				
			||||||
		OpType:       ActionMergePullRequest,
 | 
							OpType:    ActionMergePullRequest,
 | 
				
			||||||
		ActUserID:    user.ID,
 | 
							ActUserID: user.ID,
 | 
				
			||||||
		ActUserName:  user.Name,
 | 
							ActUser:   user,
 | 
				
			||||||
		RepoID:       repo.ID,
 | 
							RepoID:    repo.ID,
 | 
				
			||||||
		RepoName:     repo.Name,
 | 
							Repo:      repo,
 | 
				
			||||||
		RepoUserName: repo.Owner.Name,
 | 
							IsPrivate: repo.IsPrivate,
 | 
				
			||||||
		IsPrivate:    repo.IsPrivate,
 | 
					 | 
				
			||||||
	}
 | 
						}
 | 
				
			||||||
	AssertNotExistsBean(t, actionBean)
 | 
						AssertNotExistsBean(t, actionBean)
 | 
				
			||||||
	assert.NoError(t, MergePullRequestAction(user, repo, issue))
 | 
						assert.NoError(t, MergePullRequestAction(user, repo, issue))
 | 
				
			||||||
 
 | 
				
			|||||||
@@ -162,11 +162,5 @@ func (team *Team) checkForConsistency(t *testing.T) {
 | 
				
			|||||||
 | 
					
 | 
				
			||||||
func (action *Action) checkForConsistency(t *testing.T) {
 | 
					func (action *Action) checkForConsistency(t *testing.T) {
 | 
				
			||||||
	repo := AssertExistsAndLoadBean(t, &Repository{ID: action.RepoID}).(*Repository)
 | 
						repo := AssertExistsAndLoadBean(t, &Repository{ID: action.RepoID}).(*Repository)
 | 
				
			||||||
	owner := AssertExistsAndLoadBean(t, &User{ID: repo.OwnerID}).(*User)
 | 
					 | 
				
			||||||
	actor := AssertExistsAndLoadBean(t, &User{ID: action.ActUserID}).(*User)
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
	assert.Equal(t, repo.Name, action.RepoName, "action: %+v", action)
 | 
					 | 
				
			||||||
	assert.Equal(t, repo.IsPrivate, action.IsPrivate, "action: %+v", action)
 | 
						assert.Equal(t, repo.IsPrivate, action.IsPrivate, "action: %+v", action)
 | 
				
			||||||
	assert.Equal(t, owner.Name, action.RepoUserName, "action: %+v", action)
 | 
					 | 
				
			||||||
	assert.Equal(t, actor.Name, action.ActUserName, "action: %+v", action)
 | 
					 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 
 | 
				
			|||||||
@@ -3,10 +3,7 @@
 | 
				
			|||||||
  user_id: 2
 | 
					  user_id: 2
 | 
				
			||||||
  op_type: 12 # close issue
 | 
					  op_type: 12 # close issue
 | 
				
			||||||
  act_user_id: 2
 | 
					  act_user_id: 2
 | 
				
			||||||
  act_user_name: user2
 | 
					 | 
				
			||||||
  repo_id: 2
 | 
					  repo_id: 2
 | 
				
			||||||
  repo_user_name: user2
 | 
					 | 
				
			||||||
  repo_name: repo2
 | 
					 | 
				
			||||||
  is_private: true
 | 
					  is_private: true
 | 
				
			||||||
 | 
					
 | 
				
			||||||
-
 | 
					-
 | 
				
			||||||
@@ -14,10 +11,7 @@
 | 
				
			|||||||
  user_id: 3
 | 
					  user_id: 3
 | 
				
			||||||
  op_type: 2 # rename repo
 | 
					  op_type: 2 # rename repo
 | 
				
			||||||
  act_user_id: 3
 | 
					  act_user_id: 3
 | 
				
			||||||
  act_user_name: user3
 | 
					 | 
				
			||||||
  repo_id: 3
 | 
					  repo_id: 3
 | 
				
			||||||
  repo_user_name: user3
 | 
					 | 
				
			||||||
  repo_name: repo3
 | 
					 | 
				
			||||||
  is_private: true
 | 
					  is_private: true
 | 
				
			||||||
  content: oldRepoName
 | 
					  content: oldRepoName
 | 
				
			||||||
 | 
					
 | 
				
			||||||
@@ -26,8 +20,5 @@
 | 
				
			|||||||
  user_id: 11
 | 
					  user_id: 11
 | 
				
			||||||
  op_type: 1 # create repo
 | 
					  op_type: 1 # create repo
 | 
				
			||||||
  act_user_id: 11
 | 
					  act_user_id: 11
 | 
				
			||||||
  act_user_name: user11
 | 
					 | 
				
			||||||
  repo_id: 9
 | 
					  repo_id: 9
 | 
				
			||||||
  repo_user_name: user11
 | 
					 | 
				
			||||||
  repo_name: repo9
 | 
					 | 
				
			||||||
  is_private: false
 | 
					  is_private: false
 | 
				
			||||||
 
 | 
				
			|||||||
@@ -918,14 +918,13 @@ func NewIssue(repo *Repository, issue *Issue, labelIDs []int64, uuids []string)
 | 
				
			|||||||
	}
 | 
						}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	if err = NotifyWatchers(&Action{
 | 
						if err = NotifyWatchers(&Action{
 | 
				
			||||||
		ActUserID:    issue.Poster.ID,
 | 
							ActUserID: issue.Poster.ID,
 | 
				
			||||||
		ActUserName:  issue.Poster.Name,
 | 
							ActUser:   issue.Poster,
 | 
				
			||||||
		OpType:       ActionCreateIssue,
 | 
							OpType:    ActionCreateIssue,
 | 
				
			||||||
		Content:      fmt.Sprintf("%d|%s", issue.Index, issue.Title),
 | 
							Content:   fmt.Sprintf("%d|%s", issue.Index, issue.Title),
 | 
				
			||||||
		RepoID:       repo.ID,
 | 
							RepoID:    repo.ID,
 | 
				
			||||||
		RepoUserName: repo.Owner.Name,
 | 
							Repo:      repo,
 | 
				
			||||||
		RepoName:     repo.Name,
 | 
							IsPrivate: repo.IsPrivate,
 | 
				
			||||||
		IsPrivate:    repo.IsPrivate,
 | 
					 | 
				
			||||||
	}); err != nil {
 | 
						}); err != nil {
 | 
				
			||||||
		log.Error(4, "NotifyWatchers: %v", err)
 | 
							log.Error(4, "NotifyWatchers: %v", err)
 | 
				
			||||||
	}
 | 
						}
 | 
				
			||||||
 
 | 
				
			|||||||
@@ -329,13 +329,12 @@ func createComment(e *xorm.Session, opts *CreateCommentOptions) (_ *Comment, err
 | 
				
			|||||||
	// Compose comment action, could be plain comment, close or reopen issue/pull request.
 | 
						// Compose comment action, could be plain comment, close or reopen issue/pull request.
 | 
				
			||||||
	// This object will be used to notify watchers in the end of function.
 | 
						// This object will be used to notify watchers in the end of function.
 | 
				
			||||||
	act := &Action{
 | 
						act := &Action{
 | 
				
			||||||
		ActUserID:    opts.Doer.ID,
 | 
							ActUserID: opts.Doer.ID,
 | 
				
			||||||
		ActUserName:  opts.Doer.Name,
 | 
							ActUser:   opts.Doer,
 | 
				
			||||||
		Content:      fmt.Sprintf("%d|%s", opts.Issue.Index, strings.Split(opts.Content, "\n")[0]),
 | 
							Content:   fmt.Sprintf("%d|%s", opts.Issue.Index, strings.Split(opts.Content, "\n")[0]),
 | 
				
			||||||
		RepoID:       opts.Repo.ID,
 | 
							RepoID:    opts.Repo.ID,
 | 
				
			||||||
		RepoUserName: opts.Repo.Owner.Name,
 | 
							Repo:      opts.Repo,
 | 
				
			||||||
		RepoName:     opts.Repo.Name,
 | 
							IsPrivate: opts.Repo.IsPrivate,
 | 
				
			||||||
		IsPrivate:    opts.Repo.IsPrivate,
 | 
					 | 
				
			||||||
	}
 | 
						}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	// Check comment type.
 | 
						// Check comment type.
 | 
				
			||||||
 
 | 
				
			|||||||
@@ -114,6 +114,8 @@ var migrations = []Migration{
 | 
				
			|||||||
	NewMigration("add field for login source synchronization", addLoginSourceSyncEnabledColumn),
 | 
						NewMigration("add field for login source synchronization", addLoginSourceSyncEnabledColumn),
 | 
				
			||||||
	// v32 -> v33
 | 
						// v32 -> v33
 | 
				
			||||||
	NewMigration("add units for team", addUnitsToRepoTeam),
 | 
						NewMigration("add units for team", addUnitsToRepoTeam),
 | 
				
			||||||
 | 
						// v33 -> v34
 | 
				
			||||||
 | 
						NewMigration("remove columns from action", removeActionColumns),
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
// Migrate database to current version
 | 
					// Migrate database to current version
 | 
				
			||||||
 
 | 
				
			|||||||
							
								
								
									
										44
									
								
								models/migrations/v34.go
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										44
									
								
								models/migrations/v34.go
									
									
									
									
									
										Normal file
									
								
							@@ -0,0 +1,44 @@
 | 
				
			|||||||
 | 
					// Copyright 2017 Gitea. All rights reserved.
 | 
				
			||||||
 | 
					// Use of this source code is governed by a MIT-style
 | 
				
			||||||
 | 
					// license that can be found in the LICENSE file.
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					package migrations
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					import (
 | 
				
			||||||
 | 
						"fmt"
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						"code.gitea.io/gitea/modules/log"
 | 
				
			||||||
 | 
						"code.gitea.io/gitea/modules/setting"
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						"github.com/go-xorm/xorm"
 | 
				
			||||||
 | 
					)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					// ActionV34 describes the removed fields
 | 
				
			||||||
 | 
					type ActionV34 struct {
 | 
				
			||||||
 | 
						ActUserName  string `xorm:"-"`
 | 
				
			||||||
 | 
						RepoUserName string `xorm:"-"`
 | 
				
			||||||
 | 
						RepoName     string `xorm:"-"`
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					// TableName will be invoked by XORM to customize the table name
 | 
				
			||||||
 | 
					func (*ActionV34) TableName() string {
 | 
				
			||||||
 | 
						return "action"
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					func removeActionColumns(x *xorm.Engine) error {
 | 
				
			||||||
 | 
						switch {
 | 
				
			||||||
 | 
						case setting.UseSQLite3:
 | 
				
			||||||
 | 
							log.Warn("Unable to drop columns in SQLite")
 | 
				
			||||||
 | 
						case setting.UseMySQL, setting.UsePostgreSQL, setting.UseMSSQL, setting.UseTiDB:
 | 
				
			||||||
 | 
							if _, err := x.Exec("ALTER TABLE action DROP COLUMN act_user_name"); err != nil {
 | 
				
			||||||
 | 
								return fmt.Errorf("DROP COLUMN act_user_name: %v", err)
 | 
				
			||||||
 | 
							} else if _, err = x.Exec("ALTER TABLE action DROP COLUMN repo_user_name"); err != nil {
 | 
				
			||||||
 | 
								return fmt.Errorf("DROP COLUMN repo_user_name: %v", err)
 | 
				
			||||||
 | 
							} else if _, err = x.Exec("ALTER TABLE action DROP COLUMN repo_name"); err != nil {
 | 
				
			||||||
 | 
								return fmt.Errorf("DROP COLUMN repo_name: %v", err)
 | 
				
			||||||
 | 
							}
 | 
				
			||||||
 | 
						default:
 | 
				
			||||||
 | 
							log.Fatal(4, "Unrecognized DB")
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
						return nil
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
@@ -635,14 +635,13 @@ func NewPullRequest(repo *Repository, pull *Issue, labelIDs []int64, uuids []str
 | 
				
			|||||||
	}
 | 
						}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	if err = NotifyWatchers(&Action{
 | 
						if err = NotifyWatchers(&Action{
 | 
				
			||||||
		ActUserID:    pull.Poster.ID,
 | 
							ActUserID: pull.Poster.ID,
 | 
				
			||||||
		ActUserName:  pull.Poster.Name,
 | 
							ActUser:   pull.Poster,
 | 
				
			||||||
		OpType:       ActionCreatePullRequest,
 | 
							OpType:    ActionCreatePullRequest,
 | 
				
			||||||
		Content:      fmt.Sprintf("%d|%s", pull.Index, pull.Title),
 | 
							Content:   fmt.Sprintf("%d|%s", pull.Index, pull.Title),
 | 
				
			||||||
		RepoID:       repo.ID,
 | 
							RepoID:    repo.ID,
 | 
				
			||||||
		RepoUserName: repo.Owner.Name,
 | 
							Repo:      repo,
 | 
				
			||||||
		RepoName:     repo.Name,
 | 
							IsPrivate: repo.IsPrivate,
 | 
				
			||||||
		IsPrivate:    repo.IsPrivate,
 | 
					 | 
				
			||||||
	}); err != nil {
 | 
						}); err != nil {
 | 
				
			||||||
		log.Error(4, "NotifyWatchers: %v", err)
 | 
							log.Error(4, "NotifyWatchers: %v", err)
 | 
				
			||||||
	} else if err = pull.MailParticipants(); err != nil {
 | 
						} else if err = pull.MailParticipants(); err != nil {
 | 
				
			||||||
 
 | 
				
			|||||||
@@ -65,25 +65,50 @@ func retrieveFeeds(ctx *context.Context, ctxUser *models.User, userID, offset in
 | 
				
			|||||||
 | 
					
 | 
				
			||||||
	// Check access of private repositories.
 | 
						// Check access of private repositories.
 | 
				
			||||||
	feeds := make([]*models.Action, 0, len(actions))
 | 
						feeds := make([]*models.Action, 0, len(actions))
 | 
				
			||||||
	unameAvatars := map[string]string{
 | 
						userCache := map[int64]*models.User{ctxUser.ID: ctxUser}
 | 
				
			||||||
		ctxUser.Name: ctxUser.RelAvatarLink(),
 | 
						repoCache := map[int64]*models.Repository{}
 | 
				
			||||||
	}
 | 
					 | 
				
			||||||
	for _, act := range actions {
 | 
						for _, act := range actions {
 | 
				
			||||||
		// Cache results to reduce queries.
 | 
							// Cache results to reduce queries.
 | 
				
			||||||
		_, ok := unameAvatars[act.ActUserName]
 | 
							u, ok := userCache[act.ActUserID]
 | 
				
			||||||
		if !ok {
 | 
							if !ok {
 | 
				
			||||||
			u, err := models.GetUserByName(act.ActUserName)
 | 
								u, err = models.GetUserByID(act.ActUserID)
 | 
				
			||||||
			if err != nil {
 | 
								if err != nil {
 | 
				
			||||||
				if models.IsErrUserNotExist(err) {
 | 
									if models.IsErrUserNotExist(err) {
 | 
				
			||||||
					continue
 | 
										continue
 | 
				
			||||||
				}
 | 
									}
 | 
				
			||||||
				ctx.Handle(500, "GetUserByName", err)
 | 
									ctx.Handle(500, "GetUserByID", err)
 | 
				
			||||||
				return
 | 
									return
 | 
				
			||||||
			}
 | 
								}
 | 
				
			||||||
			unameAvatars[act.ActUserName] = u.RelAvatarLink()
 | 
								userCache[act.ActUserID] = u
 | 
				
			||||||
		}
 | 
							}
 | 
				
			||||||
 | 
							act.ActUser = u
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
							repo, ok := repoCache[act.RepoID]
 | 
				
			||||||
 | 
							if !ok {
 | 
				
			||||||
 | 
								repo, err = models.GetRepositoryByID(act.RepoID)
 | 
				
			||||||
 | 
								if err != nil {
 | 
				
			||||||
 | 
									if models.IsErrRepoNotExist(err) {
 | 
				
			||||||
 | 
										continue
 | 
				
			||||||
 | 
									}
 | 
				
			||||||
 | 
									ctx.Handle(500, "GetRepositoryByID", err)
 | 
				
			||||||
 | 
									return
 | 
				
			||||||
 | 
								}
 | 
				
			||||||
 | 
							}
 | 
				
			||||||
 | 
							act.Repo = repo
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
							repoOwner, ok := userCache[repo.OwnerID]
 | 
				
			||||||
 | 
							if !ok {
 | 
				
			||||||
 | 
								repoOwner, err = models.GetUserByID(repo.OwnerID)
 | 
				
			||||||
 | 
								if err != nil {
 | 
				
			||||||
 | 
									if models.IsErrUserNotExist(err) {
 | 
				
			||||||
 | 
										continue
 | 
				
			||||||
 | 
									}
 | 
				
			||||||
 | 
									ctx.Handle(500, "GetUserByID", err)
 | 
				
			||||||
 | 
									return
 | 
				
			||||||
 | 
								}
 | 
				
			||||||
 | 
							}
 | 
				
			||||||
 | 
							repo.Owner = repoOwner
 | 
				
			||||||
 | 
					
 | 
				
			||||||
		act.ActAvatar = unameAvatars[act.ActUserName]
 | 
					 | 
				
			||||||
		feeds = append(feeds, act)
 | 
							feeds = append(feeds, act)
 | 
				
			||||||
	}
 | 
						}
 | 
				
			||||||
	ctx.Data["Feeds"] = feeds
 | 
						ctx.Data["Feeds"] = feeds
 | 
				
			||||||
 
 | 
				
			|||||||
		Reference in New Issue
	
	Block a user