Files
gitocean/models/forgejo_migrations/v14a_actions-approval-and-trust.go
T
Earl Warren bf7c63a2ae feat: add ActionUser model & fields to ActionRun
ActionUser is to keep track of pull requests posters that are
permanently trusted. It has a used field to track when it was last
used so records can be expired instead of accumulating forever.

ActionRun has new fields to make it possible to look them up given
either the pull request ID or the poster ID.
2025-11-06 11:07:38 +01:00

105 lines
3.3 KiB
Go

// Copyright 2025 The Forgejo Authors. All rights reserved.
// SPDX-License-Identifier: GPL-3.0-or-later
package forgejo_migrations
import (
"context"
actions_model "forgejo.org/models/actions"
"forgejo.org/models/db"
"forgejo.org/modules/log"
"forgejo.org/modules/timeutil"
"xorm.io/xorm"
)
func init() {
registerMigration(&Migration{
Description: "add actions approval and trust table and fields",
Upgrade: v14ActionsApprovalAndTrust,
})
}
func v14ActionsApprovalAndTrust(x *xorm.Engine) error {
if err := v14ActionsApprovalAndTrustCreateTableActionUser(x); err != nil {
return err
}
if err := v14ActionsApprovalAndTrustAddActionsRunFields(x); err != nil {
return err
}
return v14ActionsApprovalAndTrustPopulateTableActionUser(x)
}
func v14ActionsApprovalAndTrustCreateTableActionUser(x *xorm.Engine) error {
type ActionUser struct {
ID int64 `xorm:"pk autoincr"`
UserID int64 `xorm:"INDEX UNIQUE(action_user_index) REFERENCES(user, id)"`
RepoID int64 `xorm:"INDEX UNIQUE(action_user_index) REFERENCES(repository, id)"`
TrustedWithPullRequests bool
LastAccess timeutil.TimeStamp `xorm:"INDEX"`
}
return x.Sync(new(ActionUser))
}
func v14ActionsApprovalAndTrustAddActionsRunFields(x *xorm.Engine) error {
type ActionRun struct {
PullRequestPosterID int64
PullRequestID int64 `xorm:"index"`
}
_, err := x.SyncWithOptions(xorm.SyncOptions{IgnoreDropIndices: true}, new(ActionRun))
return err
}
type v14ActionsApprovalAndTrustTrusted struct {
RepoID int64
UserID int64
}
func v14ActionsApprovalAndTrustPopulateTableActionUser(x *xorm.Engine) error {
//
// Users approved once were trusted before and are trusted now.
//
// The admin will see they can revoke that trust when the user
// submits a new pull request.
//
// If the user does not submit any pull request, this trust will
// eventually be automatically revoked.
//
// The number of trusted users is assumed to be small enough to not require
// pagination, even on large instances.
//
log.Info("v14a_actions-approval-and-trust: search")
var trustedList []*v14ActionsApprovalAndTrustTrusted
if err := x.Table("`action_run`").
Select("DISTINCT `action_run`.`repo_id`, `action_run`.`trigger_user_id` AS `user_id`").
Join("INNER", "`repository`", "`repository`.`id` = `action_run`.`repo_id`").
Join("INNER", "`user`", "`user`.`id` = `action_run`.`trigger_user_id`").
Where("`action_run`.`approved_by` > 0 AND `action_run`.`trigger_user_id` > 0").
OrderBy("`action_run`.`repo_id`, `action_run`.`trigger_user_id`").
Find(&trustedList); err != nil {
return err
}
log.Info("v14a_actions-approval-and-trust: start adding %d users trusted with workflow runs", len(trustedList))
if err := db.WithTx(db.DefaultContext, func(ctx context.Context) error {
for _, trusted := range trustedList {
log.Debug("v14a_actions-approval-and-trust: repository %d trusts user %d", trusted.RepoID, trusted.UserID)
if err := actions_model.InsertActionUser(ctx, &actions_model.ActionUser{
RepoID: trusted.RepoID,
UserID: trusted.UserID,
TrustedWithPullRequests: true,
}); err != nil {
return err
}
}
return nil
}); err != nil {
return err
}
log.Info("v14a_actions-approval-and-trust: done adding %d users", len(trustedList))
return nil
}