From 9bc4ce88ee53b9a75b4291fb5497413d5b732c3a Mon Sep 17 00:00:00 2001 From: Giteabot Date: Tue, 20 Oct 2026 13:27:42 -0700 Subject: [PATCH] fix: prevent system users from watching a repository (#39886) (#39895) Backport #39886 by @wxiaoguang fix #39884 Co-authored-by: wxiaoguang --- models/repo/watch.go | 3 +++ models/repo/watch_test.go | 14 ++++++++++---- 2 files changed, 13 insertions(+), 4 deletions(-) diff --git a/models/repo/watch.go b/models/repo/watch.go index ab8e9129dfa..3736ed3ca6e 100644 --- a/models/repo/watch.go +++ b/models/repo/watch.go @@ -112,6 +112,9 @@ func IsWatchingRepo(ctx context.Context, userID, repoID int64) bool { } func watchRepoByMode(ctx context.Context, watch *Watch, mode WatchMode) (err error) { + if watch.UserID <= 0 { + return nil + } if watch.Mode == mode { return nil } diff --git a/models/repo/watch_test.go b/models/repo/watch_test.go index b21f3b7ec3b..bf1388f985b 100644 --- a/models/repo/watch_test.go +++ b/models/repo/watch_test.go @@ -34,7 +34,7 @@ func TestGetWatchers(t *testing.T) { repo := unittest.AssertExistsAndLoadBean(t, &repo_model.Repository{ID: 1}) watches, err := repo_model.GetWatchers(t.Context(), repo.ID) assert.NoError(t, err) - // One watchers are inactive, thus minus 1 + // One watcher is inactive, thus minus 1 assert.Len(t, watches, repo.NumWatches-1) for _, watch := range watches { assert.Equal(t, repo.ID, watch.RepoID) @@ -90,24 +90,30 @@ func TestWatchIfAuto(t *testing.T) { setting.Service.AutoWatchOnChanges = true - // Must not add watch + // Must not add watch (user 8 has "don't watch" set) assert.NoError(t, repo_model.WatchIfAuto(t.Context(), 8, 1, true)) watchers, err = repo_model.GetRepoWatchers(t.Context(), repo.ID, db.ListOptions{Page: 1}) assert.NoError(t, err) assert.Len(t, watchers, prevCount) - // Should not add watch + // Should not add watch (read operation) assert.NoError(t, repo_model.WatchIfAuto(t.Context(), 12, 1, false)) watchers, err = repo_model.GetRepoWatchers(t.Context(), repo.ID, db.ListOptions{Page: 1}) assert.NoError(t, err) assert.Len(t, watchers, prevCount) - // Should add watch + // Should add watch (write operation) assert.NoError(t, repo_model.WatchIfAuto(t.Context(), 12, 1, true)) watchers, err = repo_model.GetRepoWatchers(t.Context(), repo.ID, db.ListOptions{Page: 1}) assert.NoError(t, err) assert.Len(t, watchers, prevCount+1) + // Should not add watch (system user should not be able to watch) + assert.NoError(t, repo_model.WatchIfAuto(t.Context(), user_model.ActionsUserID, 1, true)) + watchers, err = repo_model.GetRepoWatchers(t.Context(), repo.ID, db.ListOptions{Page: 1}) + assert.NoError(t, err) + assert.Len(t, watchers, prevCount+1) + // Should remove watch, inhibit from adding auto assert.NoError(t, repo_model.WatchRepoAuto(t.Context(), user12, repo, false)) watchers, err = repo_model.GetRepoWatchers(t.Context(), repo.ID, db.ListOptions{Page: 1})