mirror of
https://github.com/go-gitea/gitea.git
synced 2026-01-15 00:14:59 +01:00
clean watches when make a repository private and check permission when send release emails (#36319)
This commit is contained in:
parent
1c1a7b8492
commit
8a98ac2213
@ -93,15 +93,21 @@ func init() {
|
||||
db.RegisterModel(new(Release))
|
||||
}
|
||||
|
||||
// LoadAttributes load repo and publisher attributes for a release
|
||||
func (r *Release) LoadAttributes(ctx context.Context) error {
|
||||
var err error
|
||||
if r.Repo == nil {
|
||||
r.Repo, err = GetRepositoryByID(ctx, r.RepoID)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
func (r *Release) LoadRepo(ctx context.Context) (err error) {
|
||||
if r.Repo != nil {
|
||||
return nil
|
||||
}
|
||||
|
||||
r.Repo, err = GetRepositoryByID(ctx, r.RepoID)
|
||||
return err
|
||||
}
|
||||
|
||||
// LoadAttributes load repo and publisher attributes for a release
|
||||
func (r *Release) LoadAttributes(ctx context.Context) (err error) {
|
||||
if err := r.LoadRepo(ctx); err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
if r.Publisher == nil {
|
||||
r.Publisher, err = user_model.GetUserByID(ctx, r.PublisherID)
|
||||
if err != nil {
|
||||
|
||||
@ -176,3 +176,13 @@ func WatchIfAuto(ctx context.Context, userID, repoID int64, isWrite bool) error
|
||||
}
|
||||
return watchRepoMode(ctx, watch, WatchModeAuto)
|
||||
}
|
||||
|
||||
// ClearRepoWatches clears all watches for a repository and from the user that watched it.
|
||||
// Used when a repository is set to private.
|
||||
func ClearRepoWatches(ctx context.Context, repoID int64) error {
|
||||
if _, err := db.Exec(ctx, "UPDATE `repository` SET num_watches = 0 WHERE id = ?", repoID); err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
return db.DeleteBeans(ctx, Watch{RepoID: repoID})
|
||||
}
|
||||
|
||||
@ -13,6 +13,7 @@ import (
|
||||
"code.gitea.io/gitea/modules/setting"
|
||||
|
||||
"github.com/stretchr/testify/assert"
|
||||
"github.com/stretchr/testify/require"
|
||||
)
|
||||
|
||||
func TestIsWatching(t *testing.T) {
|
||||
@ -119,3 +120,21 @@ func TestWatchIfAuto(t *testing.T) {
|
||||
assert.NoError(t, err)
|
||||
assert.Len(t, watchers, prevCount)
|
||||
}
|
||||
|
||||
func TestClearRepoWatches(t *testing.T) {
|
||||
assert.NoError(t, unittest.PrepareTestDatabase())
|
||||
|
||||
const repoID int64 = 1
|
||||
watchers, err := repo_model.GetRepoWatchersIDs(t.Context(), repoID)
|
||||
require.NoError(t, err)
|
||||
require.NotEmpty(t, watchers)
|
||||
|
||||
assert.NoError(t, repo_model.ClearRepoWatches(t.Context(), repoID))
|
||||
|
||||
watchers, err = repo_model.GetRepoWatchersIDs(t.Context(), repoID)
|
||||
assert.NoError(t, err)
|
||||
assert.Empty(t, watchers)
|
||||
|
||||
repo := unittest.AssertExistsAndLoadBean(t, &repo_model.Repository{ID: repoID})
|
||||
assert.Zero(t, repo.NumWatches)
|
||||
}
|
||||
|
||||
@ -7,9 +7,12 @@ import (
|
||||
"bytes"
|
||||
"context"
|
||||
"fmt"
|
||||
"slices"
|
||||
|
||||
access_model "code.gitea.io/gitea/models/perm/access"
|
||||
"code.gitea.io/gitea/models/renderhelper"
|
||||
repo_model "code.gitea.io/gitea/models/repo"
|
||||
"code.gitea.io/gitea/models/unit"
|
||||
user_model "code.gitea.io/gitea/models/user"
|
||||
"code.gitea.io/gitea/modules/log"
|
||||
"code.gitea.io/gitea/modules/markup/markdown"
|
||||
@ -44,6 +47,16 @@ func MailNewRelease(ctx context.Context, rel *repo_model.Release) {
|
||||
return
|
||||
}
|
||||
|
||||
if err := rel.LoadRepo(ctx); err != nil {
|
||||
log.Error("rel.LoadRepo: %v", err)
|
||||
return
|
||||
}
|
||||
|
||||
// delete publisher or any users with no permission
|
||||
recipients = slices.DeleteFunc(recipients, func(u *user_model.User) bool {
|
||||
return u.ID == rel.PublisherID || !access_model.CheckRepoUnitUser(ctx, rel.Repo, u, unit.TypeReleases)
|
||||
})
|
||||
|
||||
langMap := make(map[string][]*user_model.User)
|
||||
for _, user := range recipients {
|
||||
if user.ID != rel.PublisherID {
|
||||
|
||||
71
services/mailer/mail_release_test.go
Normal file
71
services/mailer/mail_release_test.go
Normal file
@ -0,0 +1,71 @@
|
||||
// Copyright 2026 The Gitea Authors. All rights reserved.
|
||||
// SPDX-License-Identifier: MIT
|
||||
|
||||
package mailer
|
||||
|
||||
import (
|
||||
"testing"
|
||||
|
||||
repo_model "code.gitea.io/gitea/models/repo"
|
||||
"code.gitea.io/gitea/models/unittest"
|
||||
user_model "code.gitea.io/gitea/models/user"
|
||||
"code.gitea.io/gitea/modules/setting"
|
||||
sender_service "code.gitea.io/gitea/services/mailer/sender"
|
||||
|
||||
"github.com/stretchr/testify/assert"
|
||||
"github.com/stretchr/testify/require"
|
||||
)
|
||||
|
||||
func TestMailNewReleaseFiltersUnauthorizedWatchers(t *testing.T) {
|
||||
assert.NoError(t, unittest.PrepareTestDatabase())
|
||||
|
||||
origMailService := setting.MailService
|
||||
origDomain := setting.Domain
|
||||
origAppName := setting.AppName
|
||||
origAppURL := setting.AppURL
|
||||
origTemplates := LoadedTemplates()
|
||||
defer func() {
|
||||
setting.MailService = origMailService
|
||||
setting.Domain = origDomain
|
||||
setting.AppName = origAppName
|
||||
setting.AppURL = origAppURL
|
||||
loadedTemplates.Store(origTemplates)
|
||||
}()
|
||||
|
||||
setting.MailService = &setting.Mailer{
|
||||
From: "Gitea",
|
||||
FromEmail: "noreply@example.com",
|
||||
}
|
||||
setting.Domain = "example.com"
|
||||
setting.AppName = "Gitea"
|
||||
setting.AppURL = "https://example.com/"
|
||||
prepareMailTemplates(string(tplNewReleaseMail), "{{.Subject}}", "<p>{{.Release.TagName}}</p>")
|
||||
|
||||
repo := unittest.AssertExistsAndLoadBean(t, &repo_model.Repository{ID: 2})
|
||||
require.True(t, repo.IsPrivate)
|
||||
|
||||
admin := unittest.AssertExistsAndLoadBean(t, &user_model.User{ID: 1})
|
||||
unauthorized := unittest.AssertExistsAndLoadBean(t, &user_model.User{ID: 5})
|
||||
|
||||
assert.NoError(t, repo_model.WatchRepo(t.Context(), admin, repo, true))
|
||||
assert.NoError(t, repo_model.WatchRepo(t.Context(), unauthorized, repo, true))
|
||||
|
||||
rel := unittest.AssertExistsAndLoadBean(t, &repo_model.Release{ID: 11})
|
||||
rel.Repo = nil
|
||||
rel.Publisher = unittest.AssertExistsAndLoadBean(t, &user_model.User{ID: rel.PublisherID})
|
||||
|
||||
var sent []*sender_service.Message
|
||||
origSend := SendAsync
|
||||
SendAsync = func(msgs ...*sender_service.Message) {
|
||||
sent = append(sent, msgs...)
|
||||
}
|
||||
defer func() {
|
||||
SendAsync = origSend
|
||||
}()
|
||||
|
||||
MailNewRelease(t.Context(), rel)
|
||||
|
||||
require.Len(t, sent, 1)
|
||||
assert.Equal(t, admin.EmailTo(), sent[0].To)
|
||||
assert.NotEqual(t, unauthorized.EmailTo(), sent[0].To)
|
||||
}
|
||||
@ -194,6 +194,10 @@ func MakeRepoPrivate(ctx context.Context, repo *repo_model.Repository) (err erro
|
||||
return err
|
||||
}
|
||||
|
||||
if err = repo_model.ClearRepoWatches(ctx, repo.ID); err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
// Create/Remove git-daemon-export-ok for git-daemon...
|
||||
if err := CheckDaemonExportOK(ctx, repo); err != nil {
|
||||
return err
|
||||
|
||||
@ -13,6 +13,7 @@ import (
|
||||
"code.gitea.io/gitea/models/unittest"
|
||||
|
||||
"github.com/stretchr/testify/assert"
|
||||
"github.com/stretchr/testify/require"
|
||||
)
|
||||
|
||||
func TestLinkedRepository(t *testing.T) {
|
||||
@ -70,3 +71,24 @@ func TestRepository_HasWiki(t *testing.T) {
|
||||
repo2 := unittest.AssertExistsAndLoadBean(t, &repo_model.Repository{ID: 2})
|
||||
assert.False(t, HasWiki(t.Context(), repo2))
|
||||
}
|
||||
|
||||
func TestMakeRepoPrivateClearsWatches(t *testing.T) {
|
||||
assert.NoError(t, unittest.PrepareTestDatabase())
|
||||
|
||||
repo := unittest.AssertExistsAndLoadBean(t, &repo_model.Repository{ID: 1})
|
||||
repo.IsPrivate = false
|
||||
|
||||
watchers, err := repo_model.GetRepoWatchersIDs(t.Context(), repo.ID)
|
||||
require.NoError(t, err)
|
||||
require.NotEmpty(t, watchers)
|
||||
|
||||
assert.NoError(t, MakeRepoPrivate(t.Context(), repo))
|
||||
|
||||
watchers, err = repo_model.GetRepoWatchersIDs(t.Context(), repo.ID)
|
||||
assert.NoError(t, err)
|
||||
assert.Empty(t, watchers)
|
||||
|
||||
updatedRepo := unittest.AssertExistsAndLoadBean(t, &repo_model.Repository{ID: repo.ID})
|
||||
assert.True(t, updatedRepo.IsPrivate)
|
||||
assert.Zero(t, updatedRepo.NumWatches)
|
||||
}
|
||||
|
||||
Loading…
x
Reference in New Issue
Block a user