diff options
author | zeripath <art27@cantab.net> | 2019-06-01 16:00:21 +0100 |
---|---|---|
committer | Lunny Xiao <xiaolunwen@gmail.com> | 2019-06-01 23:00:21 +0800 |
commit | 356854fc5f8d7d1a7e4d68c9e00929e9ce8aa867 (patch) | |
tree | bc250740ffe65de5cd9ce3389e004ca7723d5643 /cmd/serv.go | |
parent | 8a343dda39b187627db6ffb4c24a6e0ae615867b (diff) | |
download | gitea-356854fc5f8d7d1a7e4d68c9e00929e9ce8aa867.tar.gz gitea-356854fc5f8d7d1a7e4d68c9e00929e9ce8aa867.zip |
Move serv hook functionality & drop GitLogger (#6993)
* Move hook functionality internally
* Internalise serv logic
* Remove old internal paths
* finally remove the gitlogger
* Disallow push on archived repositories
* fix lint error
* Update modules/private/key.go
* Update routers/private/hook.go
* Update routers/private/hook.go
* Update routers/private/hook.go
* Updated routers/private/serv.go
* Fix LFS Locks over SSH
* rev-list needs to be run by the hook process
* fixup
* Improve git test
* Ensure that the lfs files are created with a different prefix
* Reduce the replication in git_test.go
* slight refactor
* Remove unnecessary "/"
* Restore ensureAnonymousClone
* Restore ensureAnonymousClone
* Run rev-list on server side
* Try passing in the alternative directories instead
* Mark test as skipped
* Improve git test
* Ensure that the lfs files are created with a different prefix
* Reduce the replication in git_test.go
* Remove unnecessary "/"
Diffstat (limited to 'cmd/serv.go')
-rw-r--r-- | cmd/serv.go | 173 |
1 files changed, 49 insertions, 124 deletions
diff --git a/cmd/serv.go b/cmd/serv.go index a30e02e7a2..aa068d4cf6 100644 --- a/cmd/serv.go +++ b/cmd/serv.go @@ -8,9 +8,11 @@ package cmd import ( "encoding/json" "fmt" + "net/http" + "net/url" "os" "os/exec" - "path/filepath" + "strconv" "strings" "time" @@ -68,7 +70,6 @@ func setup(logPath string) { log.DelLogger("console") setting.NewContext() checkLFSVersion() - log.NewGitLogger(filepath.Join(setting.LogRootPath, logPath)) } func parseCmd(cmd string) (string, string) { @@ -95,15 +96,14 @@ func fail(userMessage, logMessage string, args ...interface{}) { if !setting.ProdMode { fmt.Fprintf(os.Stderr, logMessage+"\n", args...) } - log.GitLogger.Fatal(logMessage, args...) return } - log.GitLogger.Close() os.Exit(1) } func runServ(c *cli.Context) error { + // FIXME: This needs to internationalised setup("serv.log") if setting.SSH.Disabled { @@ -116,9 +116,23 @@ func runServ(c *cli.Context) error { return nil } + keys := strings.Split(c.Args()[0], "-") + if len(keys) != 2 || keys[0] != "key" { + fail("Key ID format error", "Invalid key argument: %s", c.Args()[0]) + } + keyID := com.StrTo(keys[1]).MustInt64() + cmd := os.Getenv("SSH_ORIGINAL_COMMAND") if len(cmd) == 0 { - println("Hi there, You've successfully authenticated, but Gitea does not provide shell access.") + key, user, err := private.ServNoCommand(keyID) + if err != nil { + fail("Internal error", "Failed to check provided key: %v", err) + } + if key.Type == models.KeyTypeDeploy { + println("Hi there! You've successfully authenticated with the deploy key named " + key.Name + ", but Gitea does not provide shell access.") + } else { + println("Hi there: " + user.Name + "! You've successfully authenticated with the key named " + key.Name + ", but Gitea does not provide shell access.") + } println("If this is unexpected, please log in with password and setup Gitea under another user.") return nil } @@ -152,41 +166,19 @@ func runServ(c *cli.Context) error { fail("Error while trying to create PPROF_DATA_PATH", "Error while trying to create PPROF_DATA_PATH: %v", err) } - stopCPUProfiler := pprof.DumpCPUProfileForUsername(setting.PprofDataPath, username) + stopCPUProfiler, err := pprof.DumpCPUProfileForUsername(setting.PprofDataPath, username) + if err != nil { + fail("Internal Server Error", "Unable to start CPU profile: %v", err) + } defer func() { stopCPUProfiler() - pprof.DumpMemProfileForUsername(setting.PprofDataPath, username) + err := pprof.DumpMemProfileForUsername(setting.PprofDataPath, username) + if err != nil { + fail("Internal Server Error", "Unable to dump Mem Profile: %v", err) + } }() } - var ( - isWiki bool - unitType = models.UnitTypeCode - unitName = "code" - ) - if strings.HasSuffix(reponame, ".wiki") { - isWiki = true - unitType = models.UnitTypeWiki - unitName = "wiki" - reponame = reponame[:len(reponame)-5] - } - - os.Setenv(models.EnvRepoUsername, username) - if isWiki { - os.Setenv(models.EnvRepoIsWiki, "true") - } else { - os.Setenv(models.EnvRepoIsWiki, "false") - } - os.Setenv(models.EnvRepoName, reponame) - - repo, err := private.GetRepositoryByOwnerAndName(username, reponame) - if err != nil { - if strings.Contains(err.Error(), "Failed to get repository: repository does not exist") { - fail(accessDenied, "Repository does not exist: %s/%s", username, reponame) - } - fail("Internal error", "Failed to get repository: %v", err) - } - requestedMode, has := allowedCommands[verb] if !has { fail("Unknown git command", "Unknown git command %s", verb) @@ -202,97 +194,36 @@ func runServ(c *cli.Context) error { } } - // Prohibit push to mirror repositories. - if requestedMode > models.AccessModeRead && repo.IsMirror { - fail("mirror repository is read-only", "") - } - - // Allow anonymous clone for public repositories. - var ( - keyID int64 - user *models.User - ) - if requestedMode == models.AccessModeWrite || repo.IsPrivate || setting.Service.RequireSignInView { - keys := strings.Split(c.Args()[0], "-") - if len(keys) != 2 { - fail("Key ID format error", "Invalid key argument: %s", c.Args()[0]) - } - - key, err := private.GetPublicKeyByID(com.StrTo(keys[1]).MustInt64()) - if err != nil { - fail("Invalid key ID", "Invalid key ID[%s]: %v", c.Args()[0], err) - } - keyID = key.ID - - // Check deploy key or user key. - if key.Type == models.KeyTypeDeploy { - // Now we have to get the deploy key for this repo - deployKey, err := private.GetDeployKey(key.ID, repo.ID) - if err != nil { - fail("Key access denied", "Failed to access internal api: [key_id: %d, repo_id: %d]", key.ID, repo.ID) - } - - if deployKey == nil { - fail("Key access denied", "Deploy key access denied: [key_id: %d, repo_id: %d]", key.ID, repo.ID) - } - - if deployKey.Mode < requestedMode { - fail("Key permission denied", "Cannot push with read-only deployment key: %d to repo_id: %d", key.ID, repo.ID) - } - - // Update deploy key activity. - if err = private.UpdateDeployKeyUpdated(key.ID, repo.ID); err != nil { - fail("Internal error", "UpdateDeployKey: %v", err) - } - - // FIXME: Deploy keys aren't really the owner of the repo pushing changes - // however we don't have good way of representing deploy keys in hook.go - // so for now use the owner - os.Setenv(models.EnvPusherName, username) - os.Setenv(models.EnvPusherID, fmt.Sprintf("%d", repo.OwnerID)) - } else { - user, err = private.GetUserByKeyID(key.ID) - if err != nil { - fail("internal error", "Failed to get user by key ID(%d): %v", keyID, err) - } - - if !user.IsActive || user.ProhibitLogin { - fail("Your account is not active or has been disabled by Administrator", - "User %s is disabled and have no access to repository %s", - user.Name, repoPath) - } - - mode, err := private.CheckUnitUser(user.ID, repo.ID, user.IsAdmin, unitType) - if err != nil { - fail("Internal error", "Failed to check access: %v", err) - } else if *mode < requestedMode { - clientMessage := accessDenied - if *mode >= models.AccessModeRead { - clientMessage = "You do not have sufficient authorization for this action" - } - fail(clientMessage, - "User %s does not have level %v access to repository %s's "+unitName, - user.Name, requestedMode, repoPath) + results, err := private.ServCommand(keyID, username, reponame, requestedMode, verb, lfsVerb) + if err != nil { + if private.IsErrServCommand(err) { + errServCommand := err.(private.ErrServCommand) + if errServCommand.StatusCode != http.StatusInternalServerError { + fail("Unauthorized", errServCommand.Error()) + } else { + fail("Internal Server Error", errServCommand.Error()) } - - os.Setenv(models.EnvPusherName, user.Name) - os.Setenv(models.EnvPusherID, fmt.Sprintf("%d", user.ID)) } + fail("Internal Server Error", err.Error()) } + os.Setenv(models.EnvRepoIsWiki, strconv.FormatBool(results.IsWiki)) + os.Setenv(models.EnvRepoName, results.RepoName) + os.Setenv(models.EnvRepoUsername, results.OwnerName) + os.Setenv(models.EnvPusherName, username) + os.Setenv(models.EnvPusherID, strconv.FormatInt(results.UserID, 10)) + os.Setenv(models.ProtectedBranchRepoID, strconv.FormatInt(results.RepoID, 10)) //LFS token authentication if verb == lfsAuthenticateVerb { - url := fmt.Sprintf("%s%s/%s.git/info/lfs", setting.AppURL, username, repo.Name) + url := fmt.Sprintf("%s%s/%s.git/info/lfs", setting.AppURL, url.PathEscape(results.OwnerName), url.PathEscape(results.RepoName)) now := time.Now() claims := jwt.MapClaims{ - "repo": repo.ID, + "repo": results.RepoID, "op": lfsVerb, "exp": now.Add(setting.LFS.HTTPAuthExpiry).Unix(), "nbf": now.Unix(), - } - if user != nil { - claims["user"] = user.ID + "user": results.UserID, } token := jwt.NewWithClaims(jwt.SigningMethodHS256, claims) @@ -313,7 +244,6 @@ func runServ(c *cli.Context) error { if err != nil { fail("Internal error", "Failed to encode LFS json response: %v", err) } - return nil } @@ -329,13 +259,8 @@ func runServ(c *cli.Context) error { } else { gitcmd = exec.Command(verb, repoPath) } - if isWiki { - if err = private.InitWiki(repo.ID); err != nil { - fail("Internal error", "Failed to init wiki repo: %v", err) - } - } - os.Setenv(models.ProtectedBranchRepoID, fmt.Sprintf("%d", repo.ID)) + os.Setenv(models.ProtectedBranchRepoID, fmt.Sprintf("%d", results.RepoID)) gitcmd.Dir = setting.RepoRootPath gitcmd.Stdout = os.Stdout @@ -346,9 +271,9 @@ func runServ(c *cli.Context) error { } // Update user key activity. - if keyID > 0 { - if err = private.UpdatePublicKeyUpdated(keyID); err != nil { - fail("Internal error", "UpdatePublicKey: %v", err) + if results.KeyID > 0 { + if err = private.UpdatePublicKeyInRepo(results.KeyID, results.RepoID); err != nil { + fail("Internal error", "UpdatePublicKeyInRepo: %v", err) } } |