Skip to content

Commit 4707d4b

Browse files
zeripathKN4CK3R
andauthored
Nicely handle missing user in collaborations (#17049) (#17166)
Backport #17049 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>
1 parent 4b8b214 commit 4707d4b

File tree

4 files changed

+155
-222
lines changed

4 files changed

+155
-222
lines changed

models/access.go

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -225,6 +225,9 @@ func (repo *Repository) refreshCollaboratorAccesses(e Engine, accessMap map[int6
225225
return fmt.Errorf("getCollaborations: %v", err)
226226
}
227227
for _, c := range collaborators {
228+
if c.User.IsGhost() {
229+
continue
230+
}
228231
updateUserAccess(accessMap, c.User, c.Collaboration.Mode)
229232
}
230233
return nil

models/repo_collaboration.go

Lines changed: 11 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -8,6 +8,7 @@ package models
88
import (
99
"fmt"
1010

11+
"code.gitea.io/gitea/modules/log"
1112
"code.gitea.io/gitea/modules/timeutil"
1213

1314
"xorm.io/builder"
@@ -83,16 +84,21 @@ func (repo *Repository) getCollaborators(e Engine, listOptions ListOptions) ([]*
8384
return nil, fmt.Errorf("getCollaborations: %v", err)
8485
}
8586

86-
collaborators := make([]*Collaborator, len(collaborations))
87-
for i, c := range collaborations {
87+
collaborators := make([]*Collaborator, 0, len(collaborations))
88+
for _, c := range collaborations {
8889
user, err := getUserByID(e, c.UserID)
8990
if err != nil {
90-
return nil, err
91+
if IsErrUserNotExist(err) {
92+
log.Warn("Inconsistent DB: User: %d is listed as collaborator of %-v but does not exist", c.UserID, repo)
93+
user = NewGhostUser()
94+
} else {
95+
return nil, err
96+
}
9197
}
92-
collaborators[i] = &Collaborator{
98+
collaborators = append(collaborators, &Collaborator{
9399
User: user,
94100
Collaboration: c,
95-
}
101+
})
96102
}
97103
return collaborators, nil
98104
}

models/repo_transfer.go

Lines changed: 9 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -269,6 +269,14 @@ func TransferOwnership(doer *User, newOwnerName string, repo *Repository) (err e
269269
// Dummy object.
270270
collaboration := &Collaboration{RepoID: repo.ID}
271271
for _, c := range collaborators {
272+
if c.IsGhost() {
273+
collaboration.ID = c.Collaboration.ID
274+
if _, err := sess.Delete(collaboration); err != nil {
275+
return fmt.Errorf("remove collaborator '%d': %v", c.ID, err)
276+
}
277+
collaboration.ID = 0
278+
}
279+
272280
if c.ID != newOwner.ID {
273281
isMember, err := isOrganizationMember(sess, newOwner.ID, c.ID)
274282
if err != nil {
@@ -281,6 +289,7 @@ func TransferOwnership(doer *User, newOwnerName string, repo *Repository) (err e
281289
if _, err := sess.Delete(collaboration); err != nil {
282290
return fmt.Errorf("remove collaborator '%d': %v", c.ID, err)
283291
}
292+
collaboration.UserID = 0
284293
}
285294

286295
// Remove old team-repository relations.

0 commit comments

Comments
 (0)