Backport #27902 by @earl-warren
- On user deletion, delete action runners that the user has created.
- Add a database consistency check to remove action runners that have
nonexistent belonging owner.
- Resolves https://codeberg.org/forgejo/forgejo/issues/1720
(cherry picked from commit 009ca7223d
)
Co-authored-by: Earl Warren <109468362+earl-warren@users.noreply.github.com>
Co-authored-by: Gusted <postmaster@gusted.xyz>
tags/v1.21.0
@@ -266,3 +266,27 @@ func CreateRunner(ctx context.Context, t *ActionRunner) error { | |||
_, err := db.GetEngine(ctx).Insert(t) | |||
return err | |||
} | |||
func CountRunnersWithoutBelongingOwner(ctx context.Context) (int64, error) { | |||
// Only affect action runners were a owner ID is set, as actions runners | |||
// could also be created on a repository. | |||
return db.GetEngine(ctx).Table("action_runner"). | |||
Join("LEFT", "user", "`action_runner`.owner_id = `user`.id"). | |||
Where("`action_runner`.owner_id != ?", 0). | |||
And(builder.IsNull{"`user`.id"}). | |||
Count(new(ActionRunner)) | |||
} | |||
func FixRunnersWithoutBelongingOwner(ctx context.Context) (int64, error) { | |||
subQuery := builder.Select("`action_runner`.id"). | |||
From("`action_runner`"). | |||
Join("LEFT", "user", "`action_runner`.owner_id = `user`.id"). | |||
Where(builder.Neq{"`action_runner`.owner_id": 0}). | |||
And(builder.IsNull{"`user`.id"}) | |||
b := builder.Delete(builder.In("id", subQuery)).From("`action_runner`") | |||
res, err := db.GetEngine(ctx).Exec(b) | |||
if err != nil { | |||
return 0, err | |||
} | |||
return res.RowsAffected() | |||
} |
@@ -6,6 +6,7 @@ package doctor | |||
import ( | |||
"context" | |||
actions_model "code.gitea.io/gitea/models/actions" | |||
activities_model "code.gitea.io/gitea/models/activities" | |||
"code.gitea.io/gitea/models/db" | |||
issues_model "code.gitea.io/gitea/models/issues" | |||
@@ -151,6 +152,12 @@ func checkDBConsistency(ctx context.Context, logger log.Logger, autofix bool) er | |||
Fixer: activities_model.FixActionCreatedUnixString, | |||
FixedMessage: "Set to zero", | |||
}, | |||
{ | |||
Name: "Action Runners without existing owner", | |||
Counter: actions_model.CountRunnersWithoutBelongingOwner, | |||
Fixer: actions_model.FixRunnersWithoutBelongingOwner, | |||
FixedMessage: "Removed", | |||
}, | |||
} | |||
// TODO: function to recalc all counters |
@@ -10,6 +10,7 @@ import ( | |||
_ "image/jpeg" // Needed for jpeg support | |||
actions_model "code.gitea.io/gitea/models/actions" | |||
activities_model "code.gitea.io/gitea/models/activities" | |||
asymkey_model "code.gitea.io/gitea/models/asymkey" | |||
auth_model "code.gitea.io/gitea/models/auth" | |||
@@ -90,6 +91,7 @@ func deleteUser(ctx context.Context, u *user_model.User, purge bool) (err error) | |||
&pull_model.AutoMerge{DoerID: u.ID}, | |||
&pull_model.ReviewState{UserID: u.ID}, | |||
&user_model.Redirect{RedirectUserID: u.ID}, | |||
&actions_model.ActionRunner{OwnerID: u.ID}, | |||
); err != nil { | |||
return fmt.Errorf("deleteBeans: %w", err) | |||
} |