Support put a redefined token for Gitea actions command or API

This commit is contained in:
Lunny Xiao 2024-12-17 11:21:58 -08:00
parent 2d7e6e9482
commit cc18967e41
No known key found for this signature in database
GPG Key ID: C3B7C91B632F738A
7 changed files with 51 additions and 18 deletions

View File

@ -34,6 +34,12 @@ var (
Value: "", Value: "",
Usage: "{owner}[/{repo}] - leave empty for a global runner", Usage: "{owner}[/{repo}] - leave empty for a global runner",
}, },
&cli.StringFlag{
Name: "put-token",
Aliases: []string{"t"},
Value: "",
Usage: "[{token}] - leave empty will generate a new token, otherwise will update the token to database. The token MUST be a 40 digital string containing only 0-9 and a-f",
},
}, },
} }
) )
@ -45,8 +51,9 @@ func runGenerateActionsRunnerToken(c *cli.Context) error {
setting.MustInstalled() setting.MustInstalled()
scope := c.String("scope") scope := c.String("scope")
putToken := c.String("put-token")
respText, extra := private.GenerateActionsRunnerToken(ctx, scope) respText, extra := private.GenerateActionsRunnerToken(ctx, scope, putToken)
if extra.HasError() { if extra.HasError() {
return handleCliResponseExtra(extra) return handleCliResponseExtra(extra)
} }

View File

@ -70,17 +70,25 @@ func UpdateRunnerToken(ctx context.Context, r *ActionRunnerToken, cols ...string
// NewRunnerToken creates a new active runner token and invalidate all old tokens // NewRunnerToken creates a new active runner token and invalidate all old tokens
// ownerID will be ignored and treated as 0 if repoID is non-zero. // ownerID will be ignored and treated as 0 if repoID is non-zero.
func NewRunnerToken(ctx context.Context, ownerID, repoID int64) (*ActionRunnerToken, error) { func NewRunnerToken(ctx context.Context, ownerID, repoID int64, preDefinedToken string) (*ActionRunnerToken, error) {
if ownerID != 0 && repoID != 0 { if ownerID != 0 && repoID != 0 {
// It's trying to create a runner token that belongs to a repository, but OwnerID has been set accidentally. // It's trying to create a runner token that belongs to a repository, but OwnerID has been set accidentally.
// Remove OwnerID to avoid confusion; it's not worth returning an error here. // Remove OwnerID to avoid confusion; it's not worth returning an error here.
ownerID = 0 ownerID = 0
} }
token, err := util.CryptoRandomString(40) token := preDefinedToken
if token == "" {
var err error
token, err = util.CryptoRandomString(40)
if err != nil { if err != nil {
return nil, err return nil, err
} }
} else {
if len(token) != 40 || !util.IsRandomStringValid(token) {
return nil, util.NewInvalidArgumentErrorf("invalid token: %s", token)
}
}
runnerToken := &ActionRunnerToken{ runnerToken := &ActionRunnerToken{
OwnerID: ownerID, OwnerID: ownerID,
RepoID: repoID, RepoID: repoID,
@ -95,7 +103,7 @@ func NewRunnerToken(ctx context.Context, ownerID, repoID int64) (*ActionRunnerTo
return err return err
} }
_, err = db.GetEngine(ctx).Insert(runnerToken) _, err := db.GetEngine(ctx).Insert(runnerToken)
return err return err
}) })
} }

View File

@ -11,14 +11,16 @@ import (
type GenerateTokenRequest struct { type GenerateTokenRequest struct {
Scope string Scope string
PutToken string
} }
// GenerateActionsRunnerToken calls the internal GenerateActionsRunnerToken function // GenerateActionsRunnerToken calls the internal GenerateActionsRunnerToken function
func GenerateActionsRunnerToken(ctx context.Context, scope string) (*ResponseText, ResponseExtra) { func GenerateActionsRunnerToken(ctx context.Context, scope, putToken string) (*ResponseText, ResponseExtra) {
reqURL := setting.LocalURL + "api/internal/actions/generate_actions_runner_token" reqURL := setting.LocalURL + "api/internal/actions/generate_actions_runner_token"
req := newInternalRequest(ctx, reqURL, "POST", GenerateTokenRequest{ req := newInternalRequest(ctx, reqURL, "POST", GenerateTokenRequest{
Scope: scope, Scope: scope,
PutToken: putToken,
}) })
return requestJSONResp(req, &ResponseText{}) return requestJSONResp(req, &ResponseText{})

View File

@ -78,6 +78,15 @@ func CryptoRandomInt(limit int64) (int64, error) {
const alphanumericalChars = "abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789" const alphanumericalChars = "abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789"
func IsRandomStringValid(s string) bool {
for _, c := range s {
if !strings.ContainsRune(alphanumericalChars, c) {
return false
}
}
return true
}
// CryptoRandomString generates a crypto random alphanumerical string, each byte is generated by [0,61] range // CryptoRandomString generates a crypto random alphanumerical string, each byte is generated by [0,61] range
func CryptoRandomString(length int64) (string, error) { func CryptoRandomString(length int64) (string, error) {
buf := make([]byte, length) buf := make([]byte, length)

View File

@ -19,14 +19,18 @@ type RegistrationToken struct {
} }
func GetRegistrationToken(ctx *context.APIContext, ownerID, repoID int64) { func GetRegistrationToken(ctx *context.APIContext, ownerID, repoID int64) {
token, err := actions_model.GetLatestRunnerToken(ctx, ownerID, repoID) putToken := ctx.FormString("put-token")
if errors.Is(err, util.ErrNotExist) || (token != nil && !token.IsActive) { var token *actions_model.ActionRunnerToken
token, err = actions_model.NewRunnerToken(ctx, ownerID, repoID) var err error
if putToken == "" {
token, err = actions_model.GetLatestRunnerToken(ctx, ownerID, repoID)
}
if putToken != "" || errors.Is(err, util.ErrNotExist) || (token != nil && !token.IsActive) {
token, err = actions_model.NewRunnerToken(ctx, ownerID, repoID, putToken)
} }
if err != nil { if err != nil {
ctx.InternalServerError(err) ctx.InternalServerError(err)
return return
} }
ctx.JSON(http.StatusOK, RegistrationToken{Token: token.Token}) ctx.JSON(http.StatusOK, RegistrationToken{Token: token.Token})
} }

View File

@ -41,9 +41,12 @@ func GenerateActionsRunnerToken(ctx *context.PrivateContext) {
}) })
} }
token, err := actions_model.GetLatestRunnerToken(ctx, owner, repo) var token *actions_model.ActionRunnerToken
if errors.Is(err, util.ErrNotExist) || (token != nil && !token.IsActive) { if genRequest.PutToken == "" {
token, err = actions_model.NewRunnerToken(ctx, owner, repo) token, err = actions_model.GetLatestRunnerToken(ctx, owner, repo)
}
if genRequest.PutToken != "" || errors.Is(err, util.ErrNotExist) || (token != nil && !token.IsActive) {
token, err = actions_model.NewRunnerToken(ctx, owner, repo, genRequest.PutToken)
if err != nil { if err != nil {
errMsg := fmt.Sprintf("error while creating runner token: %v", err) errMsg := fmt.Sprintf("error while creating runner token: %v", err)
log.Error("NewRunnerToken failed: %v", errMsg) log.Error("NewRunnerToken failed: %v", errMsg)

View File

@ -32,7 +32,7 @@ func RunnersList(ctx *context.Context, opts actions_model.FindRunnerOptions) {
var token *actions_model.ActionRunnerToken var token *actions_model.ActionRunnerToken
token, err = actions_model.GetLatestRunnerToken(ctx, opts.OwnerID, opts.RepoID) token, err = actions_model.GetLatestRunnerToken(ctx, opts.OwnerID, opts.RepoID)
if errors.Is(err, util.ErrNotExist) || (token != nil && !token.IsActive) { if errors.Is(err, util.ErrNotExist) || (token != nil && !token.IsActive) {
token, err = actions_model.NewRunnerToken(ctx, opts.OwnerID, opts.RepoID) token, err = actions_model.NewRunnerToken(ctx, opts.OwnerID, opts.RepoID, "")
if err != nil { if err != nil {
ctx.ServerError("CreateRunnerToken", err) ctx.ServerError("CreateRunnerToken", err)
return return
@ -131,7 +131,7 @@ func RunnerDetailsEditPost(ctx *context.Context, runnerID, ownerID, repoID int64
// RunnerResetRegistrationToken reset registration token // RunnerResetRegistrationToken reset registration token
func RunnerResetRegistrationToken(ctx *context.Context, ownerID, repoID int64, redirectTo string) { func RunnerResetRegistrationToken(ctx *context.Context, ownerID, repoID int64, redirectTo string) {
_, err := actions_model.NewRunnerToken(ctx, ownerID, repoID) _, err := actions_model.NewRunnerToken(ctx, ownerID, repoID, "")
if err != nil { if err != nil {
ctx.ServerError("ResetRunnerRegistrationToken", err) ctx.ServerError("ResetRunnerRegistrationToken", err)
return return