From 58332666a897596c3b699b7c91984f2a6ceff798 Mon Sep 17 00:00:00 2001 From: Lunny Xiao Date: Tue, 17 Dec 2024 19:16:06 -0800 Subject: [PATCH] Use a new command to set runner register token --- cmd/actions.go | 38 ++++++++++++++++++++++++++++--- models/actions/runner_token.go | 7 +++--- modules/private/actions.go | 22 +++++++++++++++--- routers/private/actions.go | 41 ++++++++++++++++++++++++++++++++++ routers/private/internal.go | 1 + 5 files changed, 99 insertions(+), 10 deletions(-) diff --git a/cmd/actions.go b/cmd/actions.go index a3ca370b5cb..846f647c220 100644 --- a/cmd/actions.go +++ b/cmd/actions.go @@ -19,6 +19,7 @@ var ( Usage: "Manage Gitea Actions", Subcommands: []*cli.Command{ subcmdActionsGenRunnerToken, + subcmdActionsSetRunnerToken, }, } @@ -34,8 +35,23 @@ var ( Value: "", Usage: "{owner}[/{repo}] - leave empty for a global runner", }, + }, + } + + subcmdActionsSetRunnerToken = &cli.Command{ + Name: "set-runner-token", + Usage: "Set a new token for a runner to as register token", + Action: runSetActionsRunnerToken, + Aliases: []string{"grt"}, + Flags: []cli.Flag{ &cli.StringFlag{ - Name: "put-token", + Name: "scope", + Aliases: []string{"s"}, + Value: "", + Usage: "{owner}[/{repo}] - leave empty for a global runner", + }, + &cli.StringFlag{ + Name: "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-9a-zA-Z]", @@ -51,9 +67,25 @@ func runGenerateActionsRunnerToken(c *cli.Context) error { setting.MustInstalled() scope := c.String("scope") - putToken := c.String("put-token") - respText, extra := private.GenerateActionsRunnerToken(ctx, scope, putToken) + respText, extra := private.GenerateActionsRunnerToken(ctx, scope) + if extra.HasError() { + return handleCliResponseExtra(extra) + } + _, _ = fmt.Printf("%s\n", respText.Text) + return nil +} + +func runSetActionsRunnerToken(c *cli.Context) error { + ctx, cancel := installSignals() + defer cancel() + + setting.MustInstalled() + + scope := c.String("scope") + putToken := c.String("token") + + respText, extra := private.SetActionsRunnerToken(ctx, scope, putToken) if extra.HasError() { return handleCliResponseExtra(extra) } diff --git a/models/actions/runner_token.go b/models/actions/runner_token.go index 024cc0e56a8..e5cbc2db448 100644 --- a/models/actions/runner_token.go +++ b/models/actions/runner_token.go @@ -84,11 +84,10 @@ func NewRunnerToken(ctx context.Context, ownerID, repoID int64, preDefinedToken if err != nil { return nil, err } - } else { - if len(token) != 40 || !util.IsRandomStringValid(token) { - return nil, util.NewInvalidArgumentErrorf("invalid token: %s", token) - } + } else if len(token) != 40 || !util.IsRandomStringValid(token) { + return nil, util.NewInvalidArgumentErrorf("invalid token: %s", token) } + runnerToken := &ActionRunnerToken{ OwnerID: ownerID, RepoID: repoID, diff --git a/modules/private/actions.go b/modules/private/actions.go index 1b1c019ce55..09135eb543f 100644 --- a/modules/private/actions.go +++ b/modules/private/actions.go @@ -15,12 +15,28 @@ type GenerateTokenRequest struct { } // GenerateActionsRunnerToken calls the internal GenerateActionsRunnerToken function -func GenerateActionsRunnerToken(ctx context.Context, scope, putToken string) (*ResponseText, ResponseExtra) { +func GenerateActionsRunnerToken(ctx context.Context, scope string) (*ResponseText, ResponseExtra) { reqURL := setting.LocalURL + "api/internal/actions/generate_actions_runner_token" req := newInternalRequest(ctx, reqURL, "POST", GenerateTokenRequest{ - Scope: scope, - PutToken: putToken, + Scope: scope, + }) + + return requestJSONResp(req, &ResponseText{}) +} + +type SetTokenRequest struct { + Scope string + Token string +} + +// SetActionsRunnerToken calls the internal GenerateActionsRunnerToken function +func SetActionsRunnerToken(ctx context.Context, scope, token string) (*ResponseText, ResponseExtra) { + reqURL := setting.LocalURL + "api/internal/actions/set_actions_runner_token" + + req := newInternalRequest(ctx, reqURL, "POST", SetTokenRequest{ + Scope: scope, + Token: token, }) return requestJSONResp(req, &ResponseText{}) diff --git a/routers/private/actions.go b/routers/private/actions.go index 76c82853157..8424c610d54 100644 --- a/routers/private/actions.go +++ b/routers/private/actions.go @@ -93,3 +93,44 @@ func parseScope(ctx *context.PrivateContext, scope string) (ownerID, repoID int6 repoID = r.ID return ownerID, repoID, nil } + +// SetActionsRunnerToken set a runner token for a given scope +func SetActionsRunnerToken(ctx *context.PrivateContext) { + var setRequest private.SetTokenRequest + rd := ctx.Req.Body + defer rd.Close() + + if err := json.NewDecoder(rd).Decode(&setRequest); err != nil { + log.Error("JSON Decode failed: %v", err) + ctx.JSON(http.StatusInternalServerError, private.Response{ + Err: err.Error(), + }) + return + } + + owner, repo, err := parseScope(ctx, setRequest.Scope) + if err != nil { + log.Error("parseScope failed: %v", err) + ctx.JSON(http.StatusInternalServerError, private.Response{ + Err: err.Error(), + }) + } + if setRequest.Token == "" { + ctx.JSON(http.StatusInternalServerError, private.Response{ + Err: "token is empty", + }) + return + } + + token, err := actions_model.NewRunnerToken(ctx, owner, repo, setRequest.Token) + if err != nil { + errMsg := fmt.Sprintf("error while creating runner token: %v", err) + log.Error("NewRunnerToken failed: %v", errMsg) + ctx.JSON(http.StatusInternalServerError, private.Response{ + Err: errMsg, + }) + return + } + + ctx.PlainText(http.StatusOK, token.Token) +} diff --git a/routers/private/internal.go b/routers/private/internal.go index 1fb72f13d9c..2600afb1cbf 100644 --- a/routers/private/internal.go +++ b/routers/private/internal.go @@ -82,6 +82,7 @@ func Routes() *web.Router { r.Post("/mail/send", SendEmail) r.Post("/restore_repo", RestoreRepo) r.Post("/actions/generate_actions_runner_token", GenerateActionsRunnerToken) + r.Post("/actions/set_actions_runner_token", SetActionsRunnerToken) r.Group("/repo", func() { // FIXME: it is not right to use context.Contexter here because all routes here should use PrivateContext