123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293 |
- // Copyright 2022 The Gitea Authors. All rights reserved.
- // SPDX-License-Identifier: MIT
-
- package runner
-
- import (
- "context"
- "crypto/subtle"
- "errors"
- "strings"
-
- actions_model "code.gitea.io/gitea/models/actions"
- auth_model "code.gitea.io/gitea/models/auth"
- "code.gitea.io/gitea/modules/log"
- "code.gitea.io/gitea/modules/timeutil"
- "code.gitea.io/gitea/modules/util"
-
- "connectrpc.com/connect"
- "google.golang.org/grpc/codes"
- "google.golang.org/grpc/status"
- )
-
- const (
- uuidHeaderKey = "x-runner-uuid"
- tokenHeaderKey = "x-runner-token"
- // Deprecated: will be removed after Gitea 1.20 released.
- versionHeaderKey = "x-runner-version"
- )
-
- var withRunner = connect.WithInterceptors(connect.UnaryInterceptorFunc(func(unaryFunc connect.UnaryFunc) connect.UnaryFunc {
- return func(ctx context.Context, request connect.AnyRequest) (connect.AnyResponse, error) {
- methodName := getMethodName(request)
- if methodName == "Register" {
- return unaryFunc(ctx, request)
- }
- uuid := request.Header().Get(uuidHeaderKey)
- token := request.Header().Get(tokenHeaderKey)
- // TODO: version will be removed from request header after Gitea 1.20 released.
- // And Gitea will not try to read version from reuqest header
- version := request.Header().Get(versionHeaderKey)
-
- runner, err := actions_model.GetRunnerByUUID(ctx, uuid)
- if err != nil {
- if errors.Is(err, util.ErrNotExist) {
- return nil, status.Error(codes.Unauthenticated, "unregistered runner")
- }
- return nil, status.Error(codes.Internal, err.Error())
- }
- if subtle.ConstantTimeCompare([]byte(runner.TokenHash), []byte(auth_model.HashToken(token, runner.TokenSalt))) != 1 {
- return nil, status.Error(codes.Unauthenticated, "unregistered runner")
- }
-
- cols := []string{"last_online"}
-
- // TODO: version will be removed from request header after Gitea 1.20 released.
- // And Gitea will not try to read version from reuqest header
- version, _ = util.SplitStringAtByteN(version, 64)
- if !util.IsEmptyString(version) && runner.Version != version {
- runner.Version = version
- cols = append(cols, "version")
- }
- runner.LastOnline = timeutil.TimeStampNow()
- if methodName == "UpdateTask" || methodName == "UpdateLog" {
- runner.LastActive = timeutil.TimeStampNow()
- cols = append(cols, "last_active")
- }
- if err := actions_model.UpdateRunner(ctx, runner, cols...); err != nil {
- log.Error("can't update runner status: %v", err)
- }
-
- ctx = context.WithValue(ctx, runnerCtxKey{}, runner)
- return unaryFunc(ctx, request)
- }
- }))
-
- func getMethodName(req connect.AnyRequest) string {
- splits := strings.Split(req.Spec().Procedure, "/")
- if len(splits) > 0 {
- return splits[len(splits)-1]
- }
- return ""
- }
-
- type runnerCtxKey struct{}
-
- func GetRunner(ctx context.Context) *actions_model.ActionRunner {
- if v := ctx.Value(runnerCtxKey{}); v != nil {
- if r, ok := v.(*actions_model.ActionRunner); ok {
- return r
- }
- }
- return nil
- }
|