diff options
author | zeripath <art27@cantab.net> | 2021-09-27 19:07:19 +0100 |
---|---|---|
committer | GitHub <noreply@github.com> | 2021-09-27 19:07:19 +0100 |
commit | e8574f2f7d4648b5b3fda48f3e31599a6b9dd40b (patch) | |
tree | f7ea29c89e569ef8a17da14780512866c8916610 /models | |
parent | b5856c443729c6825618595a0e746202553aa95c (diff) | |
download | gitea-e8574f2f7d4648b5b3fda48f3e31599a6b9dd40b.tar.gz gitea-e8574f2f7d4648b5b3fda48f3e31599a6b9dd40b.zip |
Nicely handle missing user in collaborations (#17049)
* Nicely handle missing user in collaborations
It is possible to have a collaboration in a repository which refers to a no-longer
existing user. This causes the repository transfer to fail with an unusual error.
This PR makes `repo.getCollaborators()` nicely handle the missing user by ghosting
the collaboration but also adds consistency check. It also adds an
Access consistency check.
Fix #17044
Signed-off-by: Andrew Thornton <art27@cantab.net>
Co-authored-by: KN4CK3R <admin@oldschoolhack.me>
Diffstat (limited to 'models')
-rw-r--r-- | models/access.go | 3 | ||||
-rw-r--r-- | models/repo_collaboration.go | 16 | ||||
-rw-r--r-- | models/repo_transfer.go | 9 |
3 files changed, 23 insertions, 5 deletions
diff --git a/models/access.go b/models/access.go index 560234aae8..7bbc04bd45 100644 --- a/models/access.go +++ b/models/access.go @@ -230,6 +230,9 @@ func (repo *Repository) refreshCollaboratorAccesses(e db.Engine, accessMap map[i return fmt.Errorf("getCollaborations: %v", err) } for _, c := range collaborators { + if c.User.IsGhost() { + continue + } updateUserAccess(accessMap, c.User, c.Collaboration.Mode) } return nil diff --git a/models/repo_collaboration.go b/models/repo_collaboration.go index 08360c102d..bc9d0100ef 100644 --- a/models/repo_collaboration.go +++ b/models/repo_collaboration.go @@ -9,6 +9,7 @@ import ( "fmt" "code.gitea.io/gitea/models/db" + "code.gitea.io/gitea/modules/log" "code.gitea.io/gitea/modules/timeutil" "xorm.io/builder" @@ -88,16 +89,21 @@ func (repo *Repository) getCollaborators(e db.Engine, listOptions db.ListOptions return nil, fmt.Errorf("getCollaborations: %v", err) } - collaborators := make([]*Collaborator, len(collaborations)) - for i, c := range collaborations { + collaborators := make([]*Collaborator, 0, len(collaborations)) + for _, c := range collaborations { user, err := getUserByID(e, c.UserID) if err != nil { - return nil, err + if IsErrUserNotExist(err) { + log.Warn("Inconsistent DB: User: %d is listed as collaborator of %-v but does not exist", c.UserID, repo) + user = NewGhostUser() + } else { + return nil, err + } } - collaborators[i] = &Collaborator{ + collaborators = append(collaborators, &Collaborator{ User: user, Collaboration: c, - } + }) } return collaborators, nil } diff --git a/models/repo_transfer.go b/models/repo_transfer.go index fe50c1cc04..082c3d19dc 100644 --- a/models/repo_transfer.go +++ b/models/repo_transfer.go @@ -274,6 +274,14 @@ func TransferOwnership(doer *User, newOwnerName string, repo *Repository) (err e // Dummy object. collaboration := &Collaboration{RepoID: repo.ID} for _, c := range collaborators { + if c.IsGhost() { + collaboration.ID = c.Collaboration.ID + if _, err := sess.Delete(collaboration); err != nil { + return fmt.Errorf("remove collaborator '%d': %v", c.ID, err) + } + collaboration.ID = 0 + } + if c.ID != newOwner.ID { isMember, err := isOrganizationMember(sess, newOwner.ID, c.ID) if err != nil { @@ -286,6 +294,7 @@ func TransferOwnership(doer *User, newOwnerName string, repo *Repository) (err e if _, err := sess.Delete(collaboration); err != nil { return fmt.Errorf("remove collaborator '%d': %v", c.ID, err) } + collaboration.UserID = 0 } // Remove old team-repository relations. |