Automatically remove Watches, Assignments, etc if user loses access due to being removed as collaborator or from a team (#10997)

* remove a user from being assigned to any issue/PR if (s)he is removed as a collaborator

* fix gender specific comment

* do not remove users that still have access to the repo if they are a member of a team that can access the repo

* add context to errors

* updates

* incorporate review fixes

* Update models/repo_collaboration.go

Co-Authored-By: 6543 <6543@obermui.de>

* Update models/repo_collaboration.go

Co-Authored-By: 6543 <6543@obermui.de>

* Fix Rebase Relict

* Fix & Impruve

* use xorm builder

* all in one session

* generalize reconsiderIssueAssignees

* Only Unwatch if have no access anymore

* prepare for reuse

* Same things if remove User from Team

* fix lint

* let mysql take time to react

* add description

* CI.restart()

* CI.restart()

Co-authored-by: Lanre Adelowo <yo@lanre.wtf>
Co-authored-by: techknowlogick <matti@mdranta.net>
Co-authored-by: Lauris BH <lauris@nix.lv>
This commit is contained in:
6543 2020-04-07 23:52:01 +02:00 committed by GitHub
parent d00ebf445b
commit 71979d9663
No known key found for this signature in database
GPG key ID: 4AEE18F83AFDEB23
4 changed files with 51 additions and 13 deletions

View file

@ -7,6 +7,8 @@ package models
import (
"fmt"
"xorm.io/builder"
)
// Collaboration represent the relation between an individual and a repository.
@ -189,14 +191,49 @@ func (repo *Repository) DeleteCollaboration(uid int64) (err error) {
return err
}
// Remove all IssueWatches a user has subscribed to in the repository
if err := removeIssueWatchersByRepoID(sess, uid, repo.ID); err != nil {
if err = repo.reconsiderWatches(sess, uid); err != nil {
return err
}
// Unassign a user from any issue (s)he has been assigned to in the repository
if err := repo.reconsiderIssueAssignees(sess, uid); err != nil {
return err
}
return sess.Commit()
}
func (repo *Repository) reconsiderIssueAssignees(e Engine, uid int64) error {
user, err := getUserByID(e, uid)
if err != nil {
return err
}
if canAssigned, err := canBeAssigned(e, user, repo, true); err != nil || canAssigned {
return err
}
if _, err := e.Where(builder.Eq{"assignee_id": uid}).
In("issue_id", builder.Select("id").From("issue").Where(builder.Eq{"repo_id": repo.ID})).
Delete(&IssueAssignees{}); err != nil {
return fmt.Errorf("Could not delete assignee[%d] %v", uid, err)
}
return nil
}
func (repo *Repository) reconsiderWatches(e Engine, uid int64) error {
if has, err := hasAccess(e, uid, repo); err != nil || has {
return err
}
if err := watchRepo(e, uid, repo.ID, false); err != nil {
return err
}
// Remove all IssueWatches a user has subscribed to in the repository
return removeIssueWatchersByRepoID(e, uid, repo.ID)
}
func (repo *Repository) getRepoTeams(e Engine) (teams []*Team, err error) {
return teams, e.
Join("INNER", "team_repo", "team_repo.team_id = team.id").