Cleanup protected branches when deleting users & teams (#19158)
* Clean up protected_branches when deleting user fixes #19094 * Clean up protected_branches when deleting teams * fix issue Co-authored-by: Lauris BH <lauris@nix.lv>
This commit is contained in:
parent
bfe2e3d562
commit
77d1c7bf2f
3 changed files with 103 additions and 2 deletions
|
@ -19,6 +19,7 @@ import (
|
||||||
user_model "code.gitea.io/gitea/models/user"
|
user_model "code.gitea.io/gitea/models/user"
|
||||||
"code.gitea.io/gitea/modules/log"
|
"code.gitea.io/gitea/modules/log"
|
||||||
"code.gitea.io/gitea/modules/setting"
|
"code.gitea.io/gitea/modules/setting"
|
||||||
|
"code.gitea.io/gitea/modules/util"
|
||||||
|
|
||||||
"xorm.io/builder"
|
"xorm.io/builder"
|
||||||
)
|
)
|
||||||
|
@ -776,9 +777,46 @@ func DeleteTeam(t *Team) error {
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// update branch protections
|
||||||
|
{
|
||||||
|
protections := make([]*ProtectedBranch, 0, 10)
|
||||||
|
err := sess.In("repo_id",
|
||||||
|
builder.Select("id").From("repository").Where(builder.Eq{"owner_id": t.OrgID})).
|
||||||
|
Find(&protections)
|
||||||
|
if err != nil {
|
||||||
|
return fmt.Errorf("findProtectedBranches: %v", err)
|
||||||
|
}
|
||||||
|
for _, p := range protections {
|
||||||
|
var matched1, matched2, matched3 bool
|
||||||
|
if len(p.WhitelistTeamIDs) != 0 {
|
||||||
|
p.WhitelistTeamIDs, matched1 = util.RemoveIDFromList(
|
||||||
|
p.WhitelistTeamIDs, t.ID)
|
||||||
|
}
|
||||||
|
if len(p.ApprovalsWhitelistTeamIDs) != 0 {
|
||||||
|
p.ApprovalsWhitelistTeamIDs, matched2 = util.RemoveIDFromList(
|
||||||
|
p.ApprovalsWhitelistTeamIDs, t.ID)
|
||||||
|
}
|
||||||
|
if len(p.MergeWhitelistTeamIDs) != 0 {
|
||||||
|
p.MergeWhitelistTeamIDs, matched3 = util.RemoveIDFromList(
|
||||||
|
p.MergeWhitelistTeamIDs, t.ID)
|
||||||
|
}
|
||||||
|
if matched1 || matched2 || matched3 {
|
||||||
|
if _, err = sess.ID(p.ID).Cols(
|
||||||
|
"whitelist_team_i_ds",
|
||||||
|
"merge_whitelist_team_i_ds",
|
||||||
|
"approvals_whitelist_team_i_ds",
|
||||||
|
).Update(p); err != nil {
|
||||||
|
return fmt.Errorf("updateProtectedBranches: %v", err)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if !t.IncludesAllRepositories {
|
||||||
if err := t.removeAllRepositories(ctx); err != nil {
|
if err := t.removeAllRepositories(ctx); err != nil {
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
|
}
|
||||||
|
|
||||||
// Delete team-user.
|
// Delete team-user.
|
||||||
if _, err := sess.
|
if _, err := sess.
|
||||||
|
|
|
@ -18,6 +18,7 @@ import (
|
||||||
user_model "code.gitea.io/gitea/models/user"
|
user_model "code.gitea.io/gitea/models/user"
|
||||||
"code.gitea.io/gitea/modules/setting"
|
"code.gitea.io/gitea/modules/setting"
|
||||||
"code.gitea.io/gitea/modules/structs"
|
"code.gitea.io/gitea/modules/structs"
|
||||||
|
"code.gitea.io/gitea/modules/util"
|
||||||
|
|
||||||
"xorm.io/builder"
|
"xorm.io/builder"
|
||||||
)
|
)
|
||||||
|
@ -120,6 +121,50 @@ func DeleteUser(ctx context.Context, u *user_model.User) (err error) {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// ***** START: Branch Protections *****
|
||||||
|
{
|
||||||
|
const batchSize = 50
|
||||||
|
for start := 0; ; start += batchSize {
|
||||||
|
protections := make([]*ProtectedBranch, 0, batchSize)
|
||||||
|
// @perf: We can't filter on DB side by u.ID, as those IDs are serialized as JSON strings.
|
||||||
|
// We could filter down with `WHERE repo_id IN (reposWithPushPermission(u))`,
|
||||||
|
// though that query will be quite complex and tricky to maintain (compare `getRepoAssignees()`).
|
||||||
|
// Also, as we didn't update branch protections when removing entries from `access` table,
|
||||||
|
// it's safer to iterate all protected branches.
|
||||||
|
if err = e.Limit(batchSize, start).Find(&protections); err != nil {
|
||||||
|
return fmt.Errorf("findProtectedBranches: %v", err)
|
||||||
|
}
|
||||||
|
if len(protections) == 0 {
|
||||||
|
break
|
||||||
|
}
|
||||||
|
for _, p := range protections {
|
||||||
|
var matched1, matched2, matched3 bool
|
||||||
|
if len(p.WhitelistUserIDs) != 0 {
|
||||||
|
p.WhitelistUserIDs, matched1 = util.RemoveIDFromList(
|
||||||
|
p.WhitelistUserIDs, u.ID)
|
||||||
|
}
|
||||||
|
if len(p.ApprovalsWhitelistUserIDs) != 0 {
|
||||||
|
p.ApprovalsWhitelistUserIDs, matched2 = util.RemoveIDFromList(
|
||||||
|
p.ApprovalsWhitelistUserIDs, u.ID)
|
||||||
|
}
|
||||||
|
if len(p.MergeWhitelistUserIDs) != 0 {
|
||||||
|
p.MergeWhitelistUserIDs, matched3 = util.RemoveIDFromList(
|
||||||
|
p.MergeWhitelistUserIDs, u.ID)
|
||||||
|
}
|
||||||
|
if matched1 || matched2 || matched3 {
|
||||||
|
if _, err = e.ID(p.ID).Cols(
|
||||||
|
"whitelist_user_i_ds",
|
||||||
|
"merge_whitelist_user_i_ds",
|
||||||
|
"approvals_whitelist_user_i_ds",
|
||||||
|
).Update(p); err != nil {
|
||||||
|
return fmt.Errorf("updateProtectedBranches: %v", err)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
// ***** END: Branch Protections *****
|
||||||
|
|
||||||
// ***** START: PublicKey *****
|
// ***** START: PublicKey *****
|
||||||
if _, err = e.Delete(&asymkey_model.PublicKey{OwnerID: u.ID}); err != nil {
|
if _, err = e.Delete(&asymkey_model.PublicKey{OwnerID: u.ID}); err != nil {
|
||||||
return fmt.Errorf("deletePublicKeys: %v", err)
|
return fmt.Errorf("deletePublicKeys: %v", err)
|
||||||
|
|
18
modules/util/slice.go
Normal file
18
modules/util/slice.go
Normal file
|
@ -0,0 +1,18 @@
|
||||||
|
// Copyright 2022 The Gitea Authors. All rights reserved.
|
||||||
|
// Use of this source code is governed by a MIT-style
|
||||||
|
// license that can be found in the LICENSE file.
|
||||||
|
|
||||||
|
package util
|
||||||
|
|
||||||
|
// RemoveIDFromList removes the given ID from the slice, if found.
|
||||||
|
// It does not preserve order, and assumes the ID is unique.
|
||||||
|
func RemoveIDFromList(list []int64, id int64) ([]int64, bool) {
|
||||||
|
n := len(list) - 1
|
||||||
|
for i, item := range list {
|
||||||
|
if item == id {
|
||||||
|
list[i] = list[n]
|
||||||
|
return list[:n], true
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return list, false
|
||||||
|
}
|
Reference in a new issue