diff options
author | KN4CK3R <admin@oldschoolhack.me> | 2024-03-04 09:16:03 +0100 |
---|---|---|
committer | GitHub <noreply@github.com> | 2024-03-04 08:16:03 +0000 |
commit | c337ff0ec70618ef2ead7850f90ab2a8458db192 (patch) | |
tree | cf4618cf7dc258018d5f9ec827b0fda4a9ebd196 /services/repository | |
parent | 8e12ba34bab7e728ac93ccfaecbe91e053ef1c89 (diff) | |
download | gitea-c337ff0ec70618ef2ead7850f90ab2a8458db192.tar.gz gitea-c337ff0ec70618ef2ead7850f90ab2a8458db192.zip |
Add user blocking (#29028)
Fixes #17453
This PR adds the abbility to block a user from a personal account or
organization to restrict how the blocked user can interact with the
blocker. The docs explain what's the consequence of blocking a user.
Screenshots:
![grafik](https://github.com/go-gitea/gitea/assets/1666336/4ed884f3-e06a-4862-afd3-3b8aa2488dc6)
![grafik](https://github.com/go-gitea/gitea/assets/1666336/ae6d4981-f252-4f50-a429-04f0f9f1cdf1)
![grafik](https://github.com/go-gitea/gitea/assets/1666336/ca153599-5b0f-4b4a-90fe-18bdfd6f0b6b)
---------
Co-authored-by: Lauris BH <lauris@nix.lv>
Diffstat (limited to 'services/repository')
-rw-r--r-- | services/repository/collaboration.go | 16 | ||||
-rw-r--r-- | services/repository/collaboration_test.go | 11 | ||||
-rw-r--r-- | services/repository/delete.go | 14 | ||||
-rw-r--r-- | services/repository/fork.go | 8 | ||||
-rw-r--r-- | services/repository/transfer.go | 12 |
5 files changed, 42 insertions, 19 deletions
diff --git a/services/repository/collaboration.go b/services/repository/collaboration.go index dccc124748..4a43ae2a28 100644 --- a/services/repository/collaboration.go +++ b/services/repository/collaboration.go @@ -11,13 +11,14 @@ import ( "code.gitea.io/gitea/models/db" access_model "code.gitea.io/gitea/models/perm/access" repo_model "code.gitea.io/gitea/models/repo" + user_model "code.gitea.io/gitea/models/user" ) // DeleteCollaboration removes collaboration relation between the user and repository. -func DeleteCollaboration(ctx context.Context, repo *repo_model.Repository, uid int64) (err error) { +func DeleteCollaboration(ctx context.Context, repo *repo_model.Repository, collaborator *user_model.User) (err error) { collaboration := &repo_model.Collaboration{ RepoID: repo.ID, - UserID: uid, + UserID: collaborator.ID, } ctx, committer, err := db.TxContext(ctx) @@ -31,20 +32,25 @@ func DeleteCollaboration(ctx context.Context, repo *repo_model.Repository, uid i } else if has == 0 { return committer.Commit() } + + if err := repo.LoadOwner(ctx); err != nil { + return err + } + if err = access_model.RecalculateAccesses(ctx, repo); err != nil { return err } - if err = repo_model.WatchRepo(ctx, uid, repo.ID, false); err != nil { + if err = repo_model.WatchRepo(ctx, collaborator, repo, false); err != nil { return err } - if err = models.ReconsiderWatches(ctx, repo, uid); err != nil { + if err = models.ReconsiderWatches(ctx, repo, collaborator); err != nil { return err } // Unassign a user from any issue (s)he has been assigned to in the repository - if err := models.ReconsiderRepoIssuesAssignee(ctx, repo, uid); err != nil { + if err := models.ReconsiderRepoIssuesAssignee(ctx, repo, collaborator); err != nil { return err } diff --git a/services/repository/collaboration_test.go b/services/repository/collaboration_test.go index c3d006bfd8..a2eb06b81a 100644 --- a/services/repository/collaboration_test.go +++ b/services/repository/collaboration_test.go @@ -9,6 +9,7 @@ import ( "code.gitea.io/gitea/models/db" repo_model "code.gitea.io/gitea/models/repo" "code.gitea.io/gitea/models/unittest" + user_model "code.gitea.io/gitea/models/user" "github.com/stretchr/testify/assert" ) @@ -16,13 +17,15 @@ import ( func TestRepository_DeleteCollaboration(t *testing.T) { assert.NoError(t, unittest.PrepareTestDatabase()) + user := unittest.AssertExistsAndLoadBean(t, &user_model.User{ID: 4}) repo := unittest.AssertExistsAndLoadBean(t, &repo_model.Repository{ID: 4}) + assert.NoError(t, repo.LoadOwner(db.DefaultContext)) - assert.NoError(t, DeleteCollaboration(db.DefaultContext, repo, 4)) - unittest.AssertNotExistsBean(t, &repo_model.Collaboration{RepoID: repo.ID, UserID: 4}) + assert.NoError(t, DeleteCollaboration(db.DefaultContext, repo, user)) + unittest.AssertNotExistsBean(t, &repo_model.Collaboration{RepoID: repo.ID, UserID: user.ID}) - assert.NoError(t, DeleteCollaboration(db.DefaultContext, repo, 4)) - unittest.AssertNotExistsBean(t, &repo_model.Collaboration{RepoID: repo.ID, UserID: 4}) + assert.NoError(t, DeleteCollaboration(db.DefaultContext, repo, user)) + unittest.AssertNotExistsBean(t, &repo_model.Collaboration{RepoID: repo.ID, UserID: user.ID}) unittest.CheckConsistencyFor(t, &repo_model.Repository{ID: repo.ID}) } diff --git a/services/repository/delete.go b/services/repository/delete.go index 08d6800ee7..1eeec27660 100644 --- a/services/repository/delete.go +++ b/services/repository/delete.go @@ -365,24 +365,26 @@ func removeRepositoryFromTeam(ctx context.Context, t *organization.Team, repo *r } } - teamUsers, err := organization.GetTeamUsersByTeamID(ctx, t.ID) + teamMembers, err := organization.GetTeamMembers(ctx, &organization.SearchMembersOptions{ + TeamID: t.ID, + }) if err != nil { - return fmt.Errorf("getTeamUsersByTeamID: %w", err) + return fmt.Errorf("GetTeamMembers: %w", err) } - for _, teamUser := range teamUsers { - has, err := access_model.HasAccess(ctx, teamUser.UID, repo) + for _, member := range teamMembers { + has, err := access_model.HasAccess(ctx, member.ID, repo) if err != nil { return err } else if has { continue } - if err = repo_model.WatchRepo(ctx, teamUser.UID, repo.ID, false); err != nil { + if err = repo_model.WatchRepo(ctx, member, repo, false); err != nil { return err } // Remove all IssueWatches a user has subscribed to in the repositories - if err := issues_model.RemoveIssueWatchersByRepoID(ctx, teamUser.UID, repo.ID); err != nil { + if err := issues_model.RemoveIssueWatchersByRepoID(ctx, member.ID, repo.ID); err != nil { return err } } diff --git a/services/repository/fork.go b/services/repository/fork.go index f9c13a109e..f074fd1082 100644 --- a/services/repository/fork.go +++ b/services/repository/fork.go @@ -53,6 +53,14 @@ type ForkRepoOptions struct { // ForkRepository forks a repository func ForkRepository(ctx context.Context, doer, owner *user_model.User, opts ForkRepoOptions) (*repo_model.Repository, error) { + if err := opts.BaseRepo.LoadOwner(ctx); err != nil { + return nil, err + } + + if user_model.IsUserBlockedBy(ctx, doer, opts.BaseRepo.Owner.ID) { + return nil, user_model.ErrBlockedUser + } + // Fork is prohibited, if user has reached maximum limit of repositories if !owner.CanForkRepo() { return nil, repo_model.ErrReachLimitOfRepo{ diff --git a/services/repository/transfer.go b/services/repository/transfer.go index 59a4eb260e..83d3032188 100644 --- a/services/repository/transfer.go +++ b/services/repository/transfer.go @@ -139,9 +139,9 @@ func transferOwnership(ctx context.Context, doer *user_model.User, newOwnerName } // Remove redundant collaborators. - collaborators, err := repo_model.GetCollaborators(ctx, repo.ID, db.ListOptions{}) + collaborators, _, err := repo_model.GetCollaborators(ctx, &repo_model.FindCollaborationOptions{RepoID: repo.ID}) if err != nil { - return fmt.Errorf("getCollaborators: %w", err) + return fmt.Errorf("GetCollaborators: %w", err) } // Dummy object. @@ -201,13 +201,13 @@ func transferOwnership(ctx context.Context, doer *user_model.User, newOwnerName return fmt.Errorf("decrease old owner repository count: %w", err) } - if err := repo_model.WatchRepo(ctx, doer.ID, repo.ID, true); err != nil { + if err := repo_model.WatchRepo(ctx, doer, repo, true); err != nil { return fmt.Errorf("watchRepo: %w", err) } // Remove watch for organization. if oldOwner.IsOrganization() { - if err := repo_model.WatchRepo(ctx, oldOwner.ID, repo.ID, false); err != nil { + if err := repo_model.WatchRepo(ctx, oldOwner, repo, false); err != nil { return fmt.Errorf("watchRepo [false]: %w", err) } } @@ -371,6 +371,10 @@ func StartRepositoryTransfer(ctx context.Context, doer, newOwner *user_model.Use return TransferOwnership(ctx, doer, newOwner, repo, teams) } + if user_model.IsUserBlockedBy(ctx, doer, newOwner.ID) { + return user_model.ErrBlockedUser + } + // If new owner is an org and user can create repos he can transfer directly too if newOwner.IsOrganization() { allowed, err := organization.CanCreateOrgRepo(ctx, newOwner.ID, doer.ID) |