Skip to content

Commit e8574f2

Browse files
zeripathKN4CK3R
andauthored
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 <[email protected]> Co-authored-by: KN4CK3R <[email protected]>
1 parent b5856c4 commit e8574f2

File tree

4 files changed

+161
-258
lines changed

4 files changed

+161
-258
lines changed

models/access.go

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -230,6 +230,9 @@ func (repo *Repository) refreshCollaboratorAccesses(e db.Engine, accessMap map[i
230230
return fmt.Errorf("getCollaborations: %v", err)
231231
}
232232
for _, c := range collaborators {
233+
if c.User.IsGhost() {
234+
continue
235+
}
233236
updateUserAccess(accessMap, c.User, c.Collaboration.Mode)
234237
}
235238
return nil

models/repo_collaboration.go

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

1111
"code.gitea.io/gitea/models/db"
12+
"code.gitea.io/gitea/modules/log"
1213
"code.gitea.io/gitea/modules/timeutil"
1314

1415
"xorm.io/builder"
@@ -88,16 +89,21 @@ func (repo *Repository) getCollaborators(e db.Engine, listOptions db.ListOptions
8889
return nil, fmt.Errorf("getCollaborations: %v", err)
8990
}
9091

91-
collaborators := make([]*Collaborator, len(collaborations))
92-
for i, c := range collaborations {
92+
collaborators := make([]*Collaborator, 0, len(collaborations))
93+
for _, c := range collaborations {
9394
user, err := getUserByID(e, c.UserID)
9495
if err != nil {
95-
return nil, err
96+
if IsErrUserNotExist(err) {
97+
log.Warn("Inconsistent DB: User: %d is listed as collaborator of %-v but does not exist", c.UserID, repo)
98+
user = NewGhostUser()
99+
} else {
100+
return nil, err
101+
}
96102
}
97-
collaborators[i] = &Collaborator{
103+
collaborators = append(collaborators, &Collaborator{
98104
User: user,
99105
Collaboration: c,
100-
}
106+
})
101107
}
102108
return collaborators, nil
103109
}

models/repo_transfer.go

Lines changed: 9 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -274,6 +274,14 @@ func TransferOwnership(doer *User, newOwnerName string, repo *Repository) (err e
274274
// Dummy object.
275275
collaboration := &Collaboration{RepoID: repo.ID}
276276
for _, c := range collaborators {
277+
if c.IsGhost() {
278+
collaboration.ID = c.Collaboration.ID
279+
if _, err := sess.Delete(collaboration); err != nil {
280+
return fmt.Errorf("remove collaborator '%d': %v", c.ID, err)
281+
}
282+
collaboration.ID = 0
283+
}
284+
277285
if c.ID != newOwner.ID {
278286
isMember, err := isOrganizationMember(sess, newOwner.ID, c.ID)
279287
if err != nil {
@@ -286,6 +294,7 @@ func TransferOwnership(doer *User, newOwnerName string, repo *Repository) (err e
286294
if _, err := sess.Delete(collaboration); err != nil {
287295
return fmt.Errorf("remove collaborator '%d': %v", c.ID, err)
288296
}
297+
collaboration.UserID = 0
289298
}
290299

291300
// Remove old team-repository relations.

0 commit comments

Comments
 (0)