aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--cmd/hook.go125
-rw-r--r--cmd/serv.go173
-rw-r--r--docs/content/doc/advanced/logging-documentation.en-us.md16
-rw-r--r--integrations/internal_test.go44
-rw-r--r--models/helper_environment.go2
-rw-r--r--modules/log/log.go19
-rw-r--r--modules/pprof/pprof.go16
-rw-r--r--modules/private/branch.go67
-rw-r--r--modules/private/hook.go84
-rw-r--r--modules/private/internal.go49
-rw-r--r--modules/private/key.go118
-rw-r--r--modules/private/push_update.go40
-rw-r--r--modules/private/repository.go68
-rw-r--r--modules/private/serv.go106
-rw-r--r--modules/private/wiki.go33
-rw-r--r--routers/init.go2
-rw-r--r--routers/private/branch.go52
-rw-r--r--routers/private/hook.go209
-rw-r--r--routers/private/internal.go19
-rw-r--r--routers/private/key.go78
-rw-r--r--routers/private/push_update.go47
-rw-r--r--routers/private/repository.go83
-rw-r--r--routers/private/serv.go286
-rw-r--r--routers/private/wiki.go34
-rw-r--r--routers/repo/http.go8
25 files changed, 801 insertions, 977 deletions
diff --git a/cmd/hook.go b/cmd/hook.go
index f8bd34c4e9..b3e900afee 100644
--- a/cmd/hook.go
+++ b/cmd/hook.go
@@ -8,15 +8,14 @@ import (
"bufio"
"bytes"
"fmt"
+ "net/http"
"os"
"strconv"
"strings"
"code.gitea.io/gitea/models"
"code.gitea.io/gitea/modules/git"
- "code.gitea.io/gitea/modules/log"
"code.gitea.io/gitea/modules/private"
- "code.gitea.io/gitea/modules/util"
"github.com/urfave/cli"
)
@@ -62,12 +61,10 @@ func runHookPreReceive(c *cli.Context) error {
setup("hooks/pre-receive.log")
// the environment setted on serv command
- repoID, _ := strconv.ParseInt(os.Getenv(models.ProtectedBranchRepoID), 10, 64)
isWiki := (os.Getenv(models.EnvRepoIsWiki) == "true")
username := os.Getenv(models.EnvRepoUsername)
reponame := os.Getenv(models.EnvRepoName)
- userIDStr := os.Getenv(models.EnvPusherID)
- repoPath := models.RepoPath(username, reponame)
+ userID, _ := strconv.ParseInt(os.Getenv(models.EnvPusherID), 10, 64)
buf := bytes.NewBuffer(nil)
scanner := bufio.NewScanner(os.Stdin)
@@ -91,35 +88,19 @@ func runHookPreReceive(c *cli.Context) error {
// If the ref is a branch, check if it's protected
if strings.HasPrefix(refFullName, git.BranchPrefix) {
- branchName := strings.TrimPrefix(refFullName, git.BranchPrefix)
- protectBranch, err := private.GetProtectedBranchBy(repoID, branchName)
- if err != nil {
- fail("Internal error", fmt.Sprintf("retrieve protected branches information failed: %v", err))
- }
-
- if protectBranch != nil && protectBranch.IsProtected() {
- // check and deletion
- if newCommitID == git.EmptySHA {
- fail(fmt.Sprintf("branch %s is protected from deletion", branchName), "")
- }
-
- // detect force push
- if git.EmptySHA != oldCommitID {
- output, err := git.NewCommand("rev-list", "--max-count=1", oldCommitID, "^"+newCommitID).RunInDir(repoPath)
- if err != nil {
- fail("Internal error", "Fail to detect force push: %v", err)
- } else if len(output) > 0 {
- fail(fmt.Sprintf("branch %s is protected from force push", branchName), "")
- }
- }
-
- userID, _ := strconv.ParseInt(userIDStr, 10, 64)
- canPush, err := private.CanUserPush(protectBranch.ID, userID)
- if err != nil {
- fail("Internal error", "Fail to detect user can push: %v", err)
- } else if !canPush {
- fail(fmt.Sprintf("protected branch %s can not be pushed to", branchName), "")
- }
+ statusCode, msg := private.HookPreReceive(username, reponame, private.HookOptions{
+ OldCommitID: oldCommitID,
+ NewCommitID: newCommitID,
+ RefFullName: refFullName,
+ UserID: userID,
+ GitAlternativeObjectDirectories: os.Getenv(private.GitAlternativeObjectDirectories),
+ GitObjectDirectory: os.Getenv(private.GitObjectDirectory),
+ })
+ switch statusCode {
+ case http.StatusInternalServerError:
+ fail("Internal Server Error", msg)
+ case http.StatusForbidden:
+ fail(msg, "")
}
}
}
@@ -145,7 +126,6 @@ func runHookPostReceive(c *cli.Context) error {
setup("hooks/post-receive.log")
// the environment setted on serv command
- repoID, _ := strconv.ParseInt(os.Getenv(models.ProtectedBranchRepoID), 10, 64)
repoUser := os.Getenv(models.EnvRepoUsername)
isWiki := (os.Getenv(models.EnvRepoIsWiki) == "true")
repoName := os.Getenv(models.EnvRepoName)
@@ -172,64 +152,31 @@ func runHookPostReceive(c *cli.Context) error {
newCommitID := string(fields[1])
refFullName := string(fields[2])
- // Only trigger activity updates for changes to branches or
- // tags. Updates to other refs (eg, refs/notes, refs/changes,
- // or other less-standard refs spaces are ignored since there
- // may be a very large number of them).
- if strings.HasPrefix(refFullName, git.BranchPrefix) || strings.HasPrefix(refFullName, git.TagPrefix) {
- if err := private.PushUpdate(models.PushUpdateOptions{
- RefFullName: refFullName,
- OldCommitID: oldCommitID,
- NewCommitID: newCommitID,
- PusherID: pusherID,
- PusherName: pusherName,
- RepoUserName: repoUser,
- RepoName: repoName,
- }); err != nil {
- log.GitLogger.Error("Update: %v", err)
- }
- }
-
- if newCommitID != git.EmptySHA && strings.HasPrefix(refFullName, git.BranchPrefix) {
- branch := strings.TrimPrefix(refFullName, git.BranchPrefix)
- repo, pullRequestAllowed, err := private.GetRepository(repoID)
- if err != nil {
- log.GitLogger.Error("get repo: %v", err)
- break
- }
- if !pullRequestAllowed {
- break
- }
-
- baseRepo := repo
- if repo.IsFork {
- baseRepo = repo.BaseRepo
- }
-
- if !repo.IsFork && branch == baseRepo.DefaultBranch {
- break
- }
+ res, err := private.HookPostReceive(repoUser, repoName, private.HookOptions{
+ OldCommitID: oldCommitID,
+ NewCommitID: newCommitID,
+ RefFullName: refFullName,
+ UserID: pusherID,
+ UserName: pusherName,
+ })
- pr, err := private.ActivePullRequest(baseRepo.ID, repo.ID, baseRepo.DefaultBranch, branch)
- if err != nil {
- log.GitLogger.Error("get active pr: %v", err)
- break
- }
+ if res == nil {
+ fail("Internal Server Error", err)
+ }
- fmt.Fprintln(os.Stderr, "")
- if pr == nil {
- if repo.IsFork {
- branch = fmt.Sprintf("%s:%s", repo.OwnerName, branch)
- }
- fmt.Fprintf(os.Stderr, "Create a new pull request for '%s':\n", branch)
- fmt.Fprintf(os.Stderr, " %s/compare/%s...%s\n", baseRepo.HTMLURL(), util.PathEscapeSegments(baseRepo.DefaultBranch), util.PathEscapeSegments(branch))
- } else {
- fmt.Fprint(os.Stderr, "Visit the existing pull request:\n")
- fmt.Fprintf(os.Stderr, " %s/pulls/%d\n", baseRepo.HTMLURL(), pr.Index)
- }
- fmt.Fprintln(os.Stderr, "")
+ if res["message"] == false {
+ continue
}
+ fmt.Fprintln(os.Stderr, "")
+ if res["create"] == true {
+ fmt.Fprintf(os.Stderr, "Create a new pull request for '%s':\n", res["branch"])
+ fmt.Fprintf(os.Stderr, " %s\n", res["url"])
+ } else {
+ fmt.Fprint(os.Stderr, "Visit the existing pull request:\n")
+ fmt.Fprintf(os.Stderr, " %s\n", res["url"])
+ }
+ fmt.Fprintln(os.Stderr, "")
}
return nil
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)
}
}
diff --git a/docs/content/doc/advanced/logging-documentation.en-us.md b/docs/content/doc/advanced/logging-documentation.en-us.md
index df35786943..790e750084 100644
--- a/docs/content/doc/advanced/logging-documentation.en-us.md
+++ b/docs/content/doc/advanced/logging-documentation.en-us.md
@@ -27,7 +27,6 @@ log groups:
* The Router logger
* The Access logger
* The XORM logger
-* A logger called the `GitLogger` which is used during hooks.
There is also the go log logger.
@@ -180,21 +179,6 @@ which will not be inherited from the `[log]` or relevant
* `EXPRESSION` will default to `""`
* `PREFIX` will default to `""`
-### The Hook and Serv "GitLoggers"
-
-These are less well defined loggers. Essentially these should only be
-used within Gitea's subsystems and cannot be configured at present.
-
-They will write log files in:
-
-* `%(ROOT_PATH)/hooks/pre-receive.log`
-* `%(ROOT_PATH)/hooks/update.log`
-* `%(ROOT_PATH)/hooks/post-receive.log`
-* `%(ROOT_PATH)/serv.log`
-* `%(ROOT_PATH)/http.log`
-
-In the future these logs may be rationalised.
-
## Log outputs
Gitea provides 4 possible log outputs:
diff --git a/integrations/internal_test.go b/integrations/internal_test.go
deleted file mode 100644
index ee0c0d18f1..0000000000
--- a/integrations/internal_test.go
+++ /dev/null
@@ -1,44 +0,0 @@
-// Copyright 2017 The Gitea Authors. All rights reserved.
-// Use of this source code is governed by a MIT-style
-// license that can be found in the LICENSE file.
-
-package integrations
-
-import (
- "encoding/json"
- "fmt"
- "net/http"
- "testing"
-
- "code.gitea.io/gitea/models"
- "code.gitea.io/gitea/modules/setting"
- "code.gitea.io/gitea/modules/util"
-
- "github.com/stretchr/testify/assert"
-)
-
-func assertProtectedBranch(t *testing.T, repoID int64, branchName string, isErr, canPush bool) {
- reqURL := fmt.Sprintf("/api/internal/branch/%d/%s", repoID, util.PathEscapeSegments(branchName))
- req := NewRequest(t, "GET", reqURL)
- t.Log(reqURL)
- req.Header.Add("Authorization", fmt.Sprintf("Bearer %s", setting.InternalToken))
-
- resp := MakeRequest(t, req, NoExpectedStatus)
- if isErr {
- assert.EqualValues(t, http.StatusInternalServerError, resp.Code)
- } else {
- assert.EqualValues(t, http.StatusOK, resp.Code)
- var branch models.ProtectedBranch
- t.Log(resp.Body.String())
- assert.NoError(t, json.Unmarshal(resp.Body.Bytes(), &branch))
- assert.Equal(t, canPush, !branch.IsProtected())
- }
-}
-
-func TestInternal_GetProtectedBranch(t *testing.T) {
- prepareTestEnv(t)
-
- assertProtectedBranch(t, 1, "master", false, true)
- assertProtectedBranch(t, 1, "dev", false, true)
- assertProtectedBranch(t, 1, "lunny/dev", false, true)
-}
diff --git a/models/helper_environment.go b/models/helper_environment.go
index 737a9a68c3..199eb6062d 100644
--- a/models/helper_environment.go
+++ b/models/helper_environment.go
@@ -27,7 +27,7 @@ func PushingEnvironment(doer *User, repo *Repository) []string {
"GIT_COMMITTER_NAME="+sig.Name,
"GIT_COMMITTER_EMAIL="+sig.Email,
EnvRepoName+"="+repo.Name,
- EnvRepoUsername+"="+repo.OwnerName,
+ EnvRepoUsername+"="+repo.MustOwnerName(),
EnvRepoIsWiki+"="+isWiki,
EnvPusherName+"="+doer.Name,
EnvPusherID+"="+fmt.Sprintf("%d", doer.ID),
diff --git a/modules/log/log.go b/modules/log/log.go
index d18996d48d..8698e9eed3 100644
--- a/modules/log/log.go
+++ b/modules/log/log.go
@@ -5,9 +5,7 @@
package log
import (
- "fmt"
"os"
- "path"
"runtime"
"strings"
)
@@ -17,9 +15,7 @@ var (
DEFAULT = "default"
// NamedLoggers map of named loggers
NamedLoggers = make(map[string]*Logger)
- // GitLogger logger for git
- GitLogger *Logger
- prefix string
+ prefix string
)
// NewLogger create a logger for the default logger
@@ -72,19 +68,6 @@ func GetLogger(name string) *Logger {
return NamedLoggers[DEFAULT]
}
-// NewGitLogger create a logger for git
-// FIXME: use same log level as other loggers.
-func NewGitLogger(logPath string) {
- path := path.Dir(logPath)
-
- if err := os.MkdirAll(path, os.ModePerm); err != nil {
- Fatal("Failed to create dir %s: %v", path, err)
- }
-
- GitLogger = newLogger("git", 0)
- GitLogger.SetLogger("file", "file", fmt.Sprintf(`{"level":"TRACE","filename":"%s","rotate":true,"maxsize":%d,"daily":true,"maxdays":7,"compress":true,"compressionLevel":-1, "stacktraceLevel":"NONE"}`, logPath, 1<<28))
-}
-
// GetLevel returns the minimum logger level
func GetLevel() Level {
return NamedLoggers[DEFAULT].GetLevel()
diff --git a/modules/pprof/pprof.go b/modules/pprof/pprof.go
index e02c2d0f2a..b63904e713 100644
--- a/modules/pprof/pprof.go
+++ b/modules/pprof/pprof.go
@@ -9,34 +9,30 @@ import (
"io/ioutil"
"runtime"
"runtime/pprof"
-
- "code.gitea.io/gitea/modules/log"
)
// DumpMemProfileForUsername dumps a memory profile at pprofDataPath as memprofile_<username>_<temporary id>
-func DumpMemProfileForUsername(pprofDataPath, username string) {
+func DumpMemProfileForUsername(pprofDataPath, username string) error {
f, err := ioutil.TempFile(pprofDataPath, fmt.Sprintf("memprofile_%s_", username))
if err != nil {
- log.GitLogger.Fatal("Could not create memory profile: %v", err)
+ return err
}
defer f.Close()
runtime.GC() // get up-to-date statistics
- if err := pprof.WriteHeapProfile(f); err != nil {
- log.GitLogger.Fatal("Could not write memory profile: %v", err)
- }
+ return pprof.WriteHeapProfile(f)
}
// DumpCPUProfileForUsername dumps a CPU profile at pprofDataPath as cpuprofile_<username>_<temporary id>
// it returns the stop function which stops, writes and closes the CPU profile file
-func DumpCPUProfileForUsername(pprofDataPath, username string) func() {
+func DumpCPUProfileForUsername(pprofDataPath, username string) (func(), error) {
f, err := ioutil.TempFile(pprofDataPath, fmt.Sprintf("cpuprofile_%s_", username))
if err != nil {
- log.GitLogger.Fatal("Could not create cpu profile: %v", err)
+ return nil, err
}
pprof.StartCPUProfile(f)
return func() {
pprof.StopCPUProfile()
f.Close()
- }
+ }, nil
}
diff --git a/modules/private/branch.go b/modules/private/branch.go
deleted file mode 100644
index bbd0d4b697..0000000000
--- a/modules/private/branch.go
+++ /dev/null
@@ -1,67 +0,0 @@
-// Copyright 2017 The Gitea Authors. All rights reserved.
-// Use of this source code is governed by a MIT-style
-// license that can be found in the LICENSE file.
-
-package private
-
-import (
- "encoding/json"
- "fmt"
-
- "code.gitea.io/gitea/models"
- "code.gitea.io/gitea/modules/log"
- "code.gitea.io/gitea/modules/setting"
- "code.gitea.io/gitea/modules/util"
-)
-
-// GetProtectedBranchBy get protected branch information
-func GetProtectedBranchBy(repoID int64, branchName string) (*models.ProtectedBranch, error) {
- // Ask for running deliver hook and test pull request tasks.
- reqURL := setting.LocalURL + fmt.Sprintf("api/internal/branch/%d/%s", repoID, util.PathEscapeSegments(branchName))
- log.GitLogger.Trace("GetProtectedBranchBy: %s", reqURL)
-
- resp, err := newInternalRequest(reqURL, "GET").Response()
- if err != nil {
- return nil, err
- }
-
- var branch models.ProtectedBranch
- if err := json.NewDecoder(resp.Body).Decode(&branch); err != nil {
- return nil, err
- }
-
- defer resp.Body.Close()
-
- // All 2XX status codes are accepted and others will return an error
- if resp.StatusCode/100 != 2 {
- return nil, fmt.Errorf("Failed to get protected branch: %s", decodeJSONError(resp).Err)
- }
-
- return &branch, nil
-}
-
-// CanUserPush returns if user can push
-func CanUserPush(protectedBranchID, userID int64) (bool, error) {
- // Ask for running deliver hook and test pull request tasks.
- reqURL := setting.LocalURL + fmt.Sprintf("api/internal/protectedbranch/%d/%d", protectedBranchID, userID)
- log.GitLogger.Trace("CanUserPush: %s", reqURL)
-
- resp, err := newInternalRequest(reqURL, "GET").Response()
- if err != nil {
- return false, err
- }
-
- var canPush = make(map[string]interface{})
- if err := json.NewDecoder(resp.Body).Decode(&canPush); err != nil {
- return false, err
- }
-
- defer resp.Body.Close()
-
- // All 2XX status codes are accepted and others will return an error
- if resp.StatusCode/100 != 2 {
- return false, fmt.Errorf("Failed to retrieve push user: %s", decodeJSONError(resp).Err)
- }
-
- return canPush["can_push"].(bool), nil
-}
diff --git a/modules/private/hook.go b/modules/private/hook.go
new file mode 100644
index 0000000000..7e2a475d4b
--- /dev/null
+++ b/modules/private/hook.go
@@ -0,0 +1,84 @@
+// Copyright 2019 The Gitea Authors. All rights reserved.
+// Use of this source code is governed by a MIT-style
+// license that can be found in the LICENSE file.
+
+package private
+
+import (
+ "encoding/json"
+ "fmt"
+ "net/http"
+ "net/url"
+
+ "code.gitea.io/gitea/modules/setting"
+)
+
+// Git environment variables
+const (
+ GitAlternativeObjectDirectories = "GIT_ALTERNATE_OBJECT_DIRECTORIES"
+ GitObjectDirectory = "GIT_OBJECT_DIRECTORY"
+ GitQuarantinePath = "GIT_QUARANTINE_PATH"
+)
+
+// HookOptions represents the options for the Hook calls
+type HookOptions struct {
+ OldCommitID string
+ NewCommitID string
+ RefFullName string
+ UserID int64
+ UserName string
+ GitObjectDirectory string
+ GitAlternativeObjectDirectories string
+}
+
+// HookPreReceive check whether the provided commits are allowed
+func HookPreReceive(ownerName, repoName string, opts HookOptions) (int, string) {
+ reqURL := setting.LocalURL + fmt.Sprintf("api/internal/hook/pre-receive/%s/%s?old=%s&new=%s&ref=%s&userID=%d&gitObjectDirectory=%s&gitAlternativeObjectDirectories=%s",
+ url.PathEscape(ownerName),
+ url.PathEscape(repoName),
+ url.QueryEscape(opts.OldCommitID),
+ url.QueryEscape(opts.NewCommitID),
+ url.QueryEscape(opts.RefFullName),
+ opts.UserID,
+ url.QueryEscape(opts.GitObjectDirectory),
+ url.QueryEscape(opts.GitAlternativeObjectDirectories),
+ )
+
+ resp, err := newInternalRequest(reqURL, "GET").Response()
+ if err != nil {
+ return http.StatusInternalServerError, fmt.Sprintf("Unable to contact gitea: %v", err.Error())
+ }
+ defer resp.Body.Close()
+
+ if resp.StatusCode != http.StatusOK {
+ return resp.StatusCode, decodeJSONError(resp).Err
+ }
+
+ return http.StatusOK, ""
+}
+
+// HookPostReceive updates services and users
+func HookPostReceive(ownerName, repoName string, opts HookOptions) (map[string]interface{}, string) {
+ reqURL := setting.LocalURL + fmt.Sprintf("api/internal/hook/post-receive/%s/%s?old=%s&new=%s&ref=%s&userID=%d&username=%s",
+ url.PathEscape(ownerName),
+ url.PathEscape(repoName),
+ url.QueryEscape(opts.OldCommitID),
+ url.QueryEscape(opts.NewCommitID),
+ url.QueryEscape(opts.RefFullName),
+ opts.UserID,
+ url.QueryEscape(opts.UserName))
+
+ resp, err := newInternalRequest(reqURL, "GET").Response()
+ if err != nil {
+ return nil, fmt.Sprintf("Unable to contact gitea: %v", err.Error())
+ }
+ defer resp.Body.Close()
+
+ if resp.StatusCode != http.StatusOK {
+ return nil, decodeJSONError(resp).Err
+ }
+ res := map[string]interface{}{}
+ _ = json.NewDecoder(resp.Body).Decode(&res)
+
+ return res, ""
+}
diff --git a/modules/private/internal.go b/modules/private/internal.go
index 56852ce63c..b4fee2680f 100644
--- a/modules/private/internal.go
+++ b/modules/private/internal.go
@@ -10,11 +10,8 @@ import (
"fmt"
"net"
"net/http"
- "net/url"
- "code.gitea.io/gitea/models"
"code.gitea.io/gitea/modules/httplib"
- "code.gitea.io/gitea/modules/log"
"code.gitea.io/gitea/modules/setting"
)
@@ -51,49 +48,3 @@ func newInternalRequest(url, method string) *httplib.Request {
}
return req
}
-
-// CheckUnitUser check whether user could visit the unit of this repository
-func CheckUnitUser(userID, repoID int64, isAdmin bool, unitType models.UnitType) (*models.AccessMode, error) {
- reqURL := setting.LocalURL + fmt.Sprintf("api/internal/repositories/%d/user/%d/checkunituser?isAdmin=%t&unitType=%d", repoID, userID, isAdmin, unitType)
- log.GitLogger.Trace("CheckUnitUser: %s", reqURL)
-
- resp, err := newInternalRequest(reqURL, "GET").Response()
- if err != nil {
- return nil, err
- }
- defer resp.Body.Close()
-
- if resp.StatusCode != 200 {
- return nil, fmt.Errorf("Failed to CheckUnitUser: %s", decodeJSONError(resp).Err)
- }
-
- var a models.AccessMode
- if err := json.NewDecoder(resp.Body).Decode(&a); err != nil {
- return nil, err
- }
-
- return &a, nil
-}
-
-// GetRepositoryByOwnerAndName returns the repository by given ownername and reponame.
-func GetRepositoryByOwnerAndName(ownerName, repoName string) (*models.Repository, error) {
- reqURL := setting.LocalURL + fmt.Sprintf("api/internal/repo/%s/%s", url.PathEscape(ownerName), url.PathEscape(repoName))
- log.GitLogger.Trace("GetRepositoryByOwnerAndName: %s", reqURL)
-
- resp, err := newInternalRequest(reqURL, "GET").Response()
- if err != nil {
- return nil, err
- }
- defer resp.Body.Close()
-
- if resp.StatusCode != 200 {
- return nil, fmt.Errorf("Failed to get repository: %s", decodeJSONError(resp).Err)
- }
-
- var repo models.Repository
- if err := json.NewDecoder(resp.Body).Decode(&repo); err != nil {
- return nil, err
- }
-
- return &repo, nil
-}
diff --git a/modules/private/key.go b/modules/private/key.go
index 1c6511846b..ebc28eb871 100644
--- a/modules/private/key.go
+++ b/modules/private/key.go
@@ -5,127 +5,15 @@
package private
import (
- "encoding/json"
"fmt"
- "code.gitea.io/gitea/models"
- "code.gitea.io/gitea/modules/log"
"code.gitea.io/gitea/modules/setting"
)
-// UpdateDeployKeyUpdated update deploy key updates
-func UpdateDeployKeyUpdated(keyID int64, repoID int64) error {
- reqURL := setting.LocalURL + fmt.Sprintf("api/internal/repositories/%d/keys/%d/update", repoID, keyID)
- log.GitLogger.Trace("UpdateDeployKeyUpdated: %s", reqURL)
-
- resp, err := newInternalRequest(reqURL, "POST").Response()
- if err != nil {
- return err
- }
-
- defer resp.Body.Close()
-
- // All 2XX status codes are accepted and others will return an error
- if resp.StatusCode/100 != 2 {
- return fmt.Errorf("Failed to update deploy key: %s", decodeJSONError(resp).Err)
- }
- return nil
-}
-
-// GetDeployKey check if repo has deploy key
-func GetDeployKey(keyID, repoID int64) (*models.DeployKey, error) {
- reqURL := setting.LocalURL + fmt.Sprintf("api/internal/repositories/%d/keys/%d", repoID, keyID)
- log.GitLogger.Trace("GetDeployKey: %s", reqURL)
-
- resp, err := newInternalRequest(reqURL, "GET").Response()
- if err != nil {
- return nil, err
- }
- defer resp.Body.Close()
-
- switch resp.StatusCode {
- case 404:
- return nil, nil
- case 200:
- var dKey models.DeployKey
- if err := json.NewDecoder(resp.Body).Decode(&dKey); err != nil {
- return nil, err
- }
- return &dKey, nil
- default:
- return nil, fmt.Errorf("Failed to get deploy key: %s", decodeJSONError(resp).Err)
- }
-}
-
-// HasDeployKey check if repo has deploy key
-func HasDeployKey(keyID, repoID int64) (bool, error) {
- reqURL := setting.LocalURL + fmt.Sprintf("api/internal/repositories/%d/has-keys/%d", repoID, keyID)
- log.GitLogger.Trace("HasDeployKey: %s", reqURL)
-
- resp, err := newInternalRequest(reqURL, "GET").Response()
- if err != nil {
- return false, err
- }
- defer resp.Body.Close()
-
- if resp.StatusCode == 200 {
- return true, nil
- }
- return false, nil
-}
-
-// GetPublicKeyByID get public ssh key by his ID
-func GetPublicKeyByID(keyID int64) (*models.PublicKey, error) {
- reqURL := setting.LocalURL + fmt.Sprintf("api/internal/ssh/%d", keyID)
- log.GitLogger.Trace("GetPublicKeyByID: %s", reqURL)
-
- resp, err := newInternalRequest(reqURL, "GET").Response()
- if err != nil {
- return nil, err
- }
-
- defer resp.Body.Close()
-
- if resp.StatusCode != 200 {
- return nil, fmt.Errorf("Failed to get repository: %s", decodeJSONError(resp).Err)
- }
-
- var pKey models.PublicKey
- if err := json.NewDecoder(resp.Body).Decode(&pKey); err != nil {
- return nil, err
- }
- return &pKey, nil
-}
-
-// GetUserByKeyID get user attached to key
-func GetUserByKeyID(keyID int64) (*models.User, error) {
- reqURL := setting.LocalURL + fmt.Sprintf("api/internal/ssh/%d/user", keyID)
- log.GitLogger.Trace("GetUserByKeyID: %s", reqURL)
-
- resp, err := newInternalRequest(reqURL, "GET").Response()
- if err != nil {
- return nil, err
- }
- defer resp.Body.Close()
-
- if resp.StatusCode != 200 {
- return nil, fmt.Errorf("Failed to get user: %s", decodeJSONError(resp).Err)
- }
-
- var user models.User
- if err := json.NewDecoder(resp.Body).Decode(&user); err != nil {
- return nil, err
- }
-
- return &user, nil
-}
-
-// UpdatePublicKeyUpdated update public key updates
-func UpdatePublicKeyUpdated(keyID int64) error {
+// UpdatePublicKeyInRepo update public key and if necessary deploy key updates
+func UpdatePublicKeyInRepo(keyID, repoID int64) error {
// Ask for running deliver hook and test pull request tasks.
- reqURL := setting.LocalURL + fmt.Sprintf("api/internal/ssh/%d/update", keyID)
- log.GitLogger.Trace("UpdatePublicKeyUpdated: %s", reqURL)
-
+ reqURL := setting.LocalURL + fmt.Sprintf("api/internal/ssh/%d/update/%d", keyID, repoID)
resp, err := newInternalRequest(reqURL, "POST").Response()
if err != nil {
return err
diff --git a/modules/private/push_update.go b/modules/private/push_update.go
deleted file mode 100644
index f3071b63ad..0000000000
--- a/modules/private/push_update.go
+++ /dev/null
@@ -1,40 +0,0 @@
-// Copyright 2017 The Gitea Authors. All rights reserved.
-// Use of this source code is governed by a MIT-style
-// license that can be found in the LICENSE file.
-
-package private
-
-import (
- "encoding/json"
- "fmt"
-
- "code.gitea.io/gitea/models"
- "code.gitea.io/gitea/modules/log"
- "code.gitea.io/gitea/modules/setting"
-)
-
-// PushUpdate update publick key updates
-func PushUpdate(opt models.PushUpdateOptions) error {
- // Ask for running deliver hook and test pull request tasks.
- reqURL := setting.LocalURL + "api/internal/push/update"
- log.GitLogger.Trace("PushUpdate: %s", reqURL)
-
- body, err := json.Marshal(&opt)
- if err != nil {
- return err
- }
-
- resp, err := newInternalRequest(reqURL, "POST").Body(body).Response()
- if err != nil {
- return err
- }
-
- defer resp.Body.Close()
-
- // All 2XX status codes are accepted and others will return an error
- if resp.StatusCode/100 != 2 {
- return fmt.Errorf("Failed to update public key: %s", decodeJSONError(resp).Err)
- }
-
- return nil
-}
diff --git a/modules/private/repository.go b/modules/private/repository.go
deleted file mode 100644
index cf8ae68409..0000000000
--- a/modules/private/repository.go
+++ /dev/null
@@ -1,68 +0,0 @@
-// Copyright 2018 The Gitea Authors. All rights reserved.
-// Use of this source code is governed by a MIT-style
-// license that can be found in the LICENSE file.
-
-package private
-
-import (
- "encoding/json"
- "fmt"
- "net/url"
-
- "code.gitea.io/gitea/models"
- "code.gitea.io/gitea/modules/log"
- "code.gitea.io/gitea/modules/setting"
-)
-
-// GetRepository return the repository by its ID and a bool about if it's allowed to have PR
-func GetRepository(repoID int64) (*models.Repository, bool, error) {
- reqURL := setting.LocalURL + fmt.Sprintf("api/internal/repository/%d", repoID)
- log.GitLogger.Trace("GetRepository: %s", reqURL)
-
- resp, err := newInternalRequest(reqURL, "GET").Response()
- if err != nil {
- return nil, false, err
- }
-
- var repoInfo struct {
- Repository *models.Repository
- AllowPullRequest bool
- }
- if err := json.NewDecoder(resp.Body).Decode(&repoInfo); err != nil {
- return nil, false, err
- }
-
- defer resp.Body.Close()
-
- // All 2XX status codes are accepted and others will return an error
- if resp.StatusCode/100 != 2 {
- return nil, false, fmt.Errorf("failed to retrieve repository: %s", decodeJSONError(resp).Err)
- }
-
- return repoInfo.Repository, repoInfo.AllowPullRequest, nil
-}
-
-// ActivePullRequest returns an active pull request if it exists
-func ActivePullRequest(baseRepoID int64, headRepoID int64, baseBranch, headBranch string) (*models.PullRequest, error) {
- reqURL := setting.LocalURL + fmt.Sprintf("api/internal/active-pull-request?baseRepoID=%d&headRepoID=%d&baseBranch=%s&headBranch=%s", baseRepoID, headRepoID, url.QueryEscape(baseBranch), url.QueryEscape(headBranch))
- log.GitLogger.Trace("ActivePullRequest: %s", reqURL)
-
- resp, err := newInternalRequest(reqURL, "GET").Response()
- if err != nil {
- return nil, err
- }
-
- var pr *models.PullRequest
- if err := json.NewDecoder(resp.Body).Decode(&pr); err != nil {
- return nil, err
- }
-
- defer resp.Body.Close()
-
- // All 2XX status codes are accepted and others will return an error
- if resp.StatusCode/100 != 2 {
- return nil, fmt.Errorf("failed to retrieve pull request: %s", decodeJSONError(resp).Err)
- }
-
- return pr, nil
-}
diff --git a/modules/private/serv.go b/modules/private/serv.go
new file mode 100644
index 0000000000..5b4a27f116
--- /dev/null
+++ b/modules/private/serv.go
@@ -0,0 +1,106 @@
+// Copyright 2019 The Gitea Authors. All rights reserved.
+// Use of this source code is governed by a MIT-style
+// license that can be found in the LICENSE file.
+
+package private
+
+import (
+ "encoding/json"
+ "fmt"
+ "net/http"
+ "net/url"
+
+ "code.gitea.io/gitea/models"
+ "code.gitea.io/gitea/modules/setting"
+)
+
+// KeyAndOwner is the response from ServNoCommand
+type KeyAndOwner struct {
+ Key *models.PublicKey `json:"key"`
+ Owner *models.User `json:"user"`
+}
+
+// ServNoCommand returns information about the provided key
+func ServNoCommand(keyID int64) (*models.PublicKey, *models.User, error) {
+ reqURL := setting.LocalURL + fmt.Sprintf("api/internal/serv/none/%d",
+ keyID)
+ resp, err := newInternalRequest(reqURL, "GET").Response()
+ if err != nil {
+ return nil, nil, err
+ }
+ defer resp.Body.Close()
+ if resp.StatusCode != http.StatusOK {
+ return nil, nil, fmt.Errorf("%s", decodeJSONError(resp).Err)
+ }
+
+ var keyAndOwner KeyAndOwner
+ if err := json.NewDecoder(resp.Body).Decode(&keyAndOwner); err != nil {
+ return nil, nil, err
+ }
+ return keyAndOwner.Key, keyAndOwner.Owner, nil
+}
+
+// ServCommandResults are the results of a call to the private route serv
+type ServCommandResults struct {
+ IsWiki bool
+ IsDeployKey bool
+ KeyID int64
+ KeyName string
+ UserName string
+ UserID int64
+ OwnerName string
+ RepoName string
+ RepoID int64
+}
+
+// ErrServCommand is an error returned from ServCommmand.
+type ErrServCommand struct {
+ Results ServCommandResults
+ Type string
+ Err string
+ StatusCode int
+}
+
+func (err ErrServCommand) Error() string {
+ return err.Err
+}
+
+// IsErrServCommand checks if an error is a ErrServCommand.
+func IsErrServCommand(err error) bool {
+ _, ok := err.(ErrServCommand)
+ return ok
+}
+
+// ServCommand preps for a serv call
+func ServCommand(keyID int64, ownerName, repoName string, mode models.AccessMode, verbs ...string) (*ServCommandResults, error) {
+ reqURL := setting.LocalURL + fmt.Sprintf("api/internal/serv/command/%d/%s/%s?mode=%d",
+ keyID,
+ url.PathEscape(ownerName),
+ url.PathEscape(repoName),
+ mode)
+ for _, verb := range verbs {
+ if verb != "" {
+ reqURL += fmt.Sprintf("&verb=%s", url.QueryEscape(verb))
+ }
+ }
+
+ resp, err := newInternalRequest(reqURL, "GET").Response()
+ if err != nil {
+ return nil, err
+ }
+ defer resp.Body.Close()
+ if resp.StatusCode != http.StatusOK {
+ var errServCommand ErrServCommand
+ if err := json.NewDecoder(resp.Body).Decode(&errServCommand); err != nil {
+ return nil, err
+ }
+ errServCommand.StatusCode = resp.StatusCode
+ return nil, errServCommand
+ }
+ var results ServCommandResults
+ if err := json.NewDecoder(resp.Body).Decode(&results); err != nil {
+ return nil, err
+ }
+ return &results, nil
+
+}
diff --git a/modules/private/wiki.go b/modules/private/wiki.go
deleted file mode 100644
index 4ad0cc7c4e..0000000000
--- a/modules/private/wiki.go
+++ /dev/null
@@ -1,33 +0,0 @@
-// Copyright 2018 The Gitea Authors. All rights reserved.
-// Use of this source code is governed by a MIT-style
-// license that can be found in the LICENSE file.
-
-package private
-
-import (
- "fmt"
-
- "code.gitea.io/gitea/modules/log"
- "code.gitea.io/gitea/modules/setting"
-)
-
-// InitWiki initwiki via repo id
-func InitWiki(repoID int64) error {
- // Ask for running deliver hook and test pull request tasks.
- reqURL := setting.LocalURL + fmt.Sprintf("api/internal/repositories/%d/wiki/init", repoID)
- log.GitLogger.Trace("InitWiki: %s", reqURL)
-
- resp, err := newInternalRequest(reqURL, "GET").Response()
- if err != nil {
- return err
- }
-
- defer resp.Body.Close()
-
- // All 2XX status codes are accepted and others will return an error
- if resp.StatusCode/100 != 2 {
- return fmt.Errorf("Failed to init wiki: %s", decodeJSONError(resp).Err)
- }
-
- return nil
-}
diff --git a/routers/init.go b/routers/init.go
index cfeb928819..b3078b478a 100644
--- a/routers/init.go
+++ b/routers/init.go
@@ -5,7 +5,6 @@
package routers
import (
- "path"
"strings"
"time"
@@ -99,7 +98,6 @@ func GlobalInit() {
models.InitSyncMirrors()
models.InitDeliverHooks()
models.InitTestPullRequests()
- log.NewGitLogger(path.Join(setting.LogRootPath, "http.log"))
}
if models.EnableSQLite3 {
log.Info("SQLite3 Supported")
diff --git a/routers/private/branch.go b/routers/private/branch.go
deleted file mode 100644
index 448c61f1db..0000000000
--- a/routers/private/branch.go
+++ /dev/null
@@ -1,52 +0,0 @@
-// Copyright 2017 The Gitea Authors. All rights reserved.
-// Use of this source code is governed by a MIT-style
-// license that can be found in the LICENSE file.
-
-package private
-
-import (
- "code.gitea.io/gitea/models"
-
- macaron "gopkg.in/macaron.v1"
-)
-
-// GetProtectedBranchBy get protected branch information
-func GetProtectedBranchBy(ctx *macaron.Context) {
- repoID := ctx.ParamsInt64(":id")
- branchName := ctx.Params("*")
- protectBranch, err := models.GetProtectedBranchBy(repoID, branchName)
- if err != nil {
- ctx.JSON(500, map[string]interface{}{
- "err": err.Error(),
- })
- return
- } else if protectBranch != nil {
- ctx.JSON(200, protectBranch)
- } else {
- ctx.JSON(200, &models.ProtectedBranch{
- ID: 0,
- })
- }
-}
-
-// CanUserPush returns if user push
-func CanUserPush(ctx *macaron.Context) {
- pbID := ctx.ParamsInt64(":pbid")
- userID := ctx.ParamsInt64(":userid")
-
- protectBranch, err := models.GetProtectedBranchByID(pbID)
- if err != nil {
- ctx.JSON(500, map[string]interface{}{
- "err": err.Error(),
- })
- return
- } else if protectBranch != nil {
- ctx.JSON(200, map[string]interface{}{
- "can_push": protectBranch.CanUserPush(userID),
- })
- } else {
- ctx.JSON(200, map[string]interface{}{
- "can_push": false,
- })
- }
-}
diff --git a/routers/private/hook.go b/routers/private/hook.go
new file mode 100644
index 0000000000..700c8bf332
--- /dev/null
+++ b/routers/private/hook.go
@@ -0,0 +1,209 @@
+// Copyright 2019 The Gitea Authors. All rights reserved.
+// Use of this source code is governed by a MIT-style
+// license that can be found in the LICENSE file.
+
+// Package private includes all internal routes. The package name internal is ideal but Golang is not allowed, so we use private as package name instead.
+package private
+
+import (
+ "fmt"
+ "net/http"
+ "os"
+ "strings"
+
+ "code.gitea.io/gitea/models"
+ "code.gitea.io/gitea/modules/git"
+ "code.gitea.io/gitea/modules/log"
+ "code.gitea.io/gitea/modules/private"
+ "code.gitea.io/gitea/modules/util"
+
+ macaron "gopkg.in/macaron.v1"
+)
+
+// HookPreReceive checks whether a individual commit is acceptable
+func HookPreReceive(ctx *macaron.Context) {
+ ownerName := ctx.Params(":owner")
+ repoName := ctx.Params(":repo")
+ oldCommitID := ctx.QueryTrim("old")
+ newCommitID := ctx.QueryTrim("new")
+ refFullName := ctx.QueryTrim("ref")
+ userID := ctx.QueryInt64("userID")
+ gitObjectDirectory := ctx.QueryTrim("gitObjectDirectory")
+ gitAlternativeObjectDirectories := ctx.QueryTrim("gitAlternativeObjectDirectories")
+
+ branchName := strings.TrimPrefix(refFullName, git.BranchPrefix)
+ repo, err := models.GetRepositoryByOwnerAndName(ownerName, repoName)
+ if err != nil {
+ log.Error("Unable to get repository: %s/%s Error: %v", ownerName, repoName, err)
+ ctx.JSON(http.StatusInternalServerError, map[string]interface{}{
+ "err": err.Error(),
+ })
+ return
+ }
+ repo.OwnerName = ownerName
+ protectBranch, err := models.GetProtectedBranchBy(repo.ID, branchName)
+ if err != nil {
+ log.Error("Unable to get protected branch: %s in %-v Error: %v", branchName, repo, err)
+ ctx.JSON(500, map[string]interface{}{
+ "err": err.Error(),
+ })
+ return
+ }
+ if protectBranch != nil && protectBranch.IsProtected() {
+ // check and deletion
+ if newCommitID == git.EmptySHA {
+ log.Warn("Forbidden: Branch: %s in %-v is protected from deletion", branchName, repo)
+ ctx.JSON(http.StatusForbidden, map[string]interface{}{
+ "err": fmt.Sprintf("branch %s is protected from deletion", branchName),
+ })
+ return
+ }
+
+ // detect force push
+ if git.EmptySHA != oldCommitID {
+ env := append(os.Environ(),
+ private.GitAlternativeObjectDirectories+"="+gitAlternativeObjectDirectories,
+ private.GitObjectDirectory+"="+gitObjectDirectory,
+ private.GitQuarantinePath+"="+gitObjectDirectory,
+ )
+
+ output, err := git.NewCommand("rev-list", "--max-count=1", oldCommitID, "^"+newCommitID).RunInDirWithEnv(repo.RepoPath(), env)
+ if err != nil {
+ log.Error("Unable to detect force push between: %s and %s in %-v Error: %v", oldCommitID, newCommitID, repo, err)
+ ctx.JSON(http.StatusInternalServerError, map[string]interface{}{
+ "err": fmt.Sprintf("Fail to detect force push: %v", err),
+ })
+ return
+ } else if len(output) > 0 {
+ log.Warn("Forbidden: Branch: %s in %-v is protected from force push", branchName, repo)
+ ctx.JSON(http.StatusForbidden, map[string]interface{}{
+ "err": fmt.Sprintf("branch %s is protected from force push", branchName),
+ })
+ return
+
+ }
+ }
+
+ if !protectBranch.CanUserPush(userID) {
+ log.Warn("Forbidden: User %d cannot push to protected branch: %s in %-v", userID, branchName, repo)
+ ctx.JSON(http.StatusForbidden, map[string]interface{}{
+ "err": fmt.Sprintf("protected branch %s can not be pushed to", branchName),
+ })
+ return
+ }
+ }
+ ctx.PlainText(http.StatusOK, []byte("ok"))
+}
+
+// HookPostReceive updates services and users
+func HookPostReceive(ctx *macaron.Context) {
+ ownerName := ctx.Params(":owner")
+ repoName := ctx.Params(":repo")
+ oldCommitID := ctx.Query("old")
+ newCommitID := ctx.Query("new")
+ refFullName := ctx.Query("ref")
+ userID := ctx.QueryInt64("userID")
+ userName := ctx.Query("username")
+
+ branch := refFullName
+ if strings.HasPrefix(refFullName, git.BranchPrefix) {
+ branch = strings.TrimPrefix(refFullName, git.BranchPrefix)
+ } else if strings.HasPrefix(refFullName, git.TagPrefix) {
+ branch = strings.TrimPrefix(refFullName, git.TagPrefix)
+ }
+
+ // Only trigger activity updates for changes to branches or
+ // tags. Updates to other refs (eg, refs/notes, refs/changes,
+ // or other less-standard refs spaces are ignored since there
+ // may be a very large number of them).
+ if strings.HasPrefix(refFullName, git.BranchPrefix) || strings.HasPrefix(refFullName, git.TagPrefix) {
+ if err := models.PushUpdate(branch, models.PushUpdateOptions{
+ RefFullName: refFullName,
+ OldCommitID: oldCommitID,
+ NewCommitID: newCommitID,
+ PusherID: userID,
+ PusherName: userName,
+ RepoUserName: ownerName,
+ RepoName: repoName,
+ }); err != nil {
+ log.Error("Failed to Update: %s/%s Branch: %s Error: %v", ownerName, repoName, branch, err)
+ ctx.JSON(http.StatusInternalServerError, map[string]interface{}{
+ "err": fmt.Sprintf("Failed to Update: %s/%s Branch: %s Error: %v", ownerName, repoName, branch, err),
+ })
+ return
+ }
+ }
+
+ if newCommitID != git.EmptySHA && strings.HasPrefix(refFullName, git.BranchPrefix) {
+ repo, err := models.GetRepositoryByOwnerAndName(ownerName, repoName)
+ if err != nil {
+ log.Error("Failed to get repository: %s/%s Error: %v", ownerName, repoName, err)
+ ctx.JSON(http.StatusInternalServerError, map[string]interface{}{
+ "err": fmt.Sprintf("Failed to get repository: %s/%s Error: %v", ownerName, repoName, err),
+ })
+ return
+ }
+ repo.OwnerName = ownerName
+
+ pullRequestAllowed := repo.AllowsPulls()
+ if !pullRequestAllowed {
+ ctx.JSON(http.StatusOK, map[string]interface{}{
+ "message": false,
+ })
+ return
+ }
+
+ baseRepo := repo
+ if repo.IsFork {
+ if err := repo.GetBaseRepo(); err != nil {
+ log.Error("Failed to get Base Repository of Forked repository: %-v Error: %v", repo, err)
+ ctx.JSON(http.StatusInternalServerError, map[string]interface{}{
+ "err": fmt.Sprintf("Failed to get Base Repository of Forked repository: %-v Error: %v", repo, err),
+ })
+ return
+ }
+ baseRepo = repo.BaseRepo
+ }
+
+ if !repo.IsFork && branch == baseRepo.DefaultBranch {
+ ctx.JSON(http.StatusOK, map[string]interface{}{
+ "message": false,
+ })
+ return
+ }
+
+ pr, err := models.GetUnmergedPullRequest(repo.ID, baseRepo.ID, branch, baseRepo.DefaultBranch)
+ if err != nil && !models.IsErrPullRequestNotExist(err) {
+ log.Error("Failed to get active PR in: %-v Branch: %s to: %-v Branch: %s Error: %v", repo, branch, baseRepo, baseRepo.DefaultBranch, err)
+ ctx.JSON(http.StatusInternalServerError, map[string]interface{}{
+ "err": fmt.Sprintf(
+ "Failed to get active PR in: %-v Branch: %s to: %-v Branch: %s Error: %v", repo, branch, baseRepo, baseRepo.DefaultBranch, err),
+ })
+ return
+ }
+
+ if pr == nil {
+ if repo.IsFork {
+ branch = fmt.Sprintf("%s:%s", repo.OwnerName, branch)
+ }
+ ctx.JSON(http.StatusOK, map[string]interface{}{
+ "message": true,
+ "create": true,
+ "branch": branch,
+ "url": fmt.Sprintf("%s/compare/%s...%s", baseRepo.HTMLURL(), util.PathEscapeSegments(baseRepo.DefaultBranch), util.PathEscapeSegments(branch)),
+ })
+ } else {
+ ctx.JSON(http.StatusOK, map[string]interface{}{
+ "message": true,
+ "create": false,
+ "branch": branch,
+ "url": fmt.Sprintf("%s/pulls/%d", baseRepo.HTMLURL(), pr.Index),
+ })
+ }
+ return
+ }
+ ctx.JSON(http.StatusOK, map[string]interface{}{
+ "message": false,
+ })
+ return
+}
diff --git a/routers/private/internal.go b/routers/private/internal.go
index ee6e1274c3..11cea8b4b9 100644
--- a/routers/private/internal.go
+++ b/routers/private/internal.go
@@ -76,19 +76,10 @@ func CheckUnitUser(ctx *macaron.Context) {
// These APIs will be invoked by internal commands for example `gitea serv` and etc.
func RegisterRoutes(m *macaron.Macaron) {
m.Group("/", func() {
- m.Get("/ssh/:id", GetPublicKeyByID)
- m.Get("/ssh/:id/user", GetUserByKeyID)
- m.Post("/ssh/:id/update", UpdatePublicKey)
- m.Post("/repositories/:repoid/keys/:keyid/update", UpdateDeployKey)
- m.Get("/repositories/:repoid/user/:userid/checkunituser", CheckUnitUser)
- m.Get("/repositories/:repoid/has-keys/:keyid", HasDeployKey)
- m.Get("/repositories/:repoid/keys/:keyid", GetDeployKey)
- m.Get("/repositories/:repoid/wiki/init", InitWiki)
- m.Post("/push/update", PushUpdate)
- m.Get("/protectedbranch/:pbid/:userid", CanUserPush)
- m.Get("/repo/:owner/:repo", GetRepositoryByOwnerAndName)
- m.Get("/branch/:id/*", GetProtectedBranchBy)
- m.Get("/repository/:rid", GetRepository)
- m.Get("/active-pull-request", GetActivePullRequest)
+ m.Post("/ssh/:id/update/:repoid", UpdatePublicKeyInRepo)
+ m.Get("/hook/pre-receive/:owner/:repo", HookPreReceive)
+ m.Get("/hook/post-receive/:owner/:repo", HookPostReceive)
+ m.Get("/serv/none/:keyid", ServNoCommand)
+ m.Get("/serv/command/:keyid/:owner/:repo", ServCommand)
}, CheckInternalToken)
}
diff --git a/routers/private/key.go b/routers/private/key.go
index ee22f6ac48..f7212ec892 100644
--- a/routers/private/key.go
+++ b/routers/private/key.go
@@ -12,30 +12,10 @@ import (
macaron "gopkg.in/macaron.v1"
)
-// UpdateDeployKey update deploy key updates
-func UpdateDeployKey(ctx *macaron.Context) {
- repoID := ctx.ParamsInt64(":repoid")
- keyID := ctx.ParamsInt64(":keyid")
- deployKey, err := models.GetDeployKeyByRepo(keyID, repoID)
- if err != nil {
- ctx.JSON(500, map[string]interface{}{
- "err": err.Error(),
- })
- return
- }
- deployKey.UpdatedUnix = util.TimeStampNow()
- if err = models.UpdateDeployKeyCols(deployKey, "updated_unix"); err != nil {
- ctx.JSON(500, map[string]interface{}{
- "err": err.Error(),
- })
- return
- }
- ctx.PlainText(200, []byte("success"))
-}
-
-// UpdatePublicKey update publick key updates
-func UpdatePublicKey(ctx *macaron.Context) {
+// UpdatePublicKeyInRepo update public key and deploy key updates
+func UpdatePublicKeyInRepo(ctx *macaron.Context) {
keyID := ctx.ParamsInt64(":id")
+ repoID := ctx.ParamsInt64(":repoid")
if err := models.UpdatePublicKeyUpdated(keyID); err != nil {
ctx.JSON(500, map[string]interface{}{
"err": err.Error(),
@@ -43,60 +23,24 @@ func UpdatePublicKey(ctx *macaron.Context) {
return
}
- ctx.PlainText(200, []byte("success"))
-}
-
-//GetPublicKeyByID chainload to models.GetPublicKeyByID
-func GetPublicKeyByID(ctx *macaron.Context) {
- keyID := ctx.ParamsInt64(":id")
- key, err := models.GetPublicKeyByID(keyID)
- if err != nil {
- ctx.JSON(500, map[string]interface{}{
- "err": err.Error(),
- })
- return
- }
- ctx.JSON(200, key)
-}
-
-//GetUserByKeyID chainload to models.GetUserByKeyID
-func GetUserByKeyID(ctx *macaron.Context) {
- keyID := ctx.ParamsInt64(":id")
- user, err := models.GetUserByKeyID(keyID)
+ deployKey, err := models.GetDeployKeyByRepo(keyID, repoID)
if err != nil {
+ if models.IsErrDeployKeyNotExist(err) {
+ ctx.PlainText(200, []byte("success"))
+ return
+ }
ctx.JSON(500, map[string]interface{}{
"err": err.Error(),
})
return
}
- ctx.JSON(200, user)
-}
-
-//GetDeployKey chainload to models.GetDeployKey
-func GetDeployKey(ctx *macaron.Context) {
- repoID := ctx.ParamsInt64(":repoid")
- keyID := ctx.ParamsInt64(":keyid")
- dKey, err := models.GetDeployKeyByRepo(keyID, repoID)
- if err != nil {
- if models.IsErrDeployKeyNotExist(err) {
- ctx.JSON(404, []byte("not found"))
- return
- }
+ deployKey.UpdatedUnix = util.TimeStampNow()
+ if err = models.UpdateDeployKeyCols(deployKey, "updated_unix"); err != nil {
ctx.JSON(500, map[string]interface{}{
"err": err.Error(),
})
return
}
- ctx.JSON(200, dKey)
-}
-//HasDeployKey chainload to models.HasDeployKey
-func HasDeployKey(ctx *macaron.Context) {
- repoID := ctx.ParamsInt64(":repoid")
- keyID := ctx.ParamsInt64(":keyid")
- if models.HasDeployKey(keyID, repoID) {
- ctx.PlainText(200, []byte("success"))
- return
- }
- ctx.PlainText(404, []byte("not found"))
+ ctx.PlainText(200, []byte("success"))
}
diff --git a/routers/private/push_update.go b/routers/private/push_update.go
deleted file mode 100644
index 5c42f066ee..0000000000
--- a/routers/private/push_update.go
+++ /dev/null
@@ -1,47 +0,0 @@
-// Copyright 2017 The Gitea Authors. All rights reserved.
-// Use of this source code is governed by a MIT-style
-// license that can be found in the LICENSE file.
-
-package private
-
-import (
- "encoding/json"
- "strings"
-
- "code.gitea.io/gitea/models"
- "code.gitea.io/gitea/modules/git"
- "code.gitea.io/gitea/modules/log"
-
- macaron "gopkg.in/macaron.v1"
-)
-
-// PushUpdate update public key updates
-func PushUpdate(ctx *macaron.Context) {
- var opt models.PushUpdateOptions
- if err := json.NewDecoder(ctx.Req.Request.Body).Decode(&opt); err != nil {
- ctx.JSON(500, map[string]interface{}{
- "err": err.Error(),
- })
- return
- }
-
- branch := strings.TrimPrefix(opt.RefFullName, git.BranchPrefix)
- if len(branch) == 0 || opt.PusherID <= 0 {
- ctx.Error(404)
- log.Trace("PushUpdate: branch or secret is empty, or pusher ID is not valid")
- return
- }
-
- err := models.PushUpdate(branch, opt)
- if err != nil {
- if models.IsErrUserNotExist(err) {
- ctx.Error(404)
- } else {
- ctx.JSON(500, map[string]interface{}{
- "err": err.Error(),
- })
- }
- return
- }
- ctx.Status(202)
-}
diff --git a/routers/private/repository.go b/routers/private/repository.go
deleted file mode 100644
index 9f451bcf1d..0000000000
--- a/routers/private/repository.go
+++ /dev/null
@@ -1,83 +0,0 @@
-// Copyright 2018 The Gitea Authors. All rights reserved.
-// Use of this source code is governed by a MIT-style
-// license that can be found in the LICENSE file.
-
-package private
-
-import (
- "net/http"
-
- "code.gitea.io/gitea/models"
-
- macaron "gopkg.in/macaron.v1"
-)
-
-// GetRepository return the default branch of a repository
-func GetRepository(ctx *macaron.Context) {
- repoID := ctx.ParamsInt64(":rid")
- repository, err := models.GetRepositoryByID(repoID)
- repository.MustOwnerName()
- allowPulls := repository.AllowsPulls()
- // put it back to nil because json unmarshal can't unmarshal it
- repository.Units = nil
-
- if err != nil {
- ctx.JSON(http.StatusInternalServerError, map[string]interface{}{
- "err": err.Error(),
- })
- return
- }
-
- if repository.IsFork {
- repository.GetBaseRepo()
- if err != nil {
- ctx.JSON(http.StatusInternalServerError, map[string]interface{}{
- "err": err.Error(),
- })
- return
- }
- repository.BaseRepo.MustOwnerName()
- allowPulls = repository.BaseRepo.AllowsPulls()
- // put it back to nil because json unmarshal can't unmarshal it
- repository.BaseRepo.Units = nil
- }
-
- ctx.JSON(http.StatusOK, struct {
- Repository *models.Repository
- AllowPullRequest bool
- }{
- Repository: repository,
- AllowPullRequest: allowPulls,
- })
-}
-
-// GetActivePullRequest return an active pull request when it exists or an empty object
-func GetActivePullRequest(ctx *macaron.Context) {
- baseRepoID := ctx.QueryInt64("baseRepoID")
- headRepoID := ctx.QueryInt64("headRepoID")
- baseBranch := ctx.QueryTrim("baseBranch")
- if len(baseBranch) == 0 {
- ctx.JSON(http.StatusInternalServerError, map[string]interface{}{
- "err": "QueryTrim failed",
- })
- return
- }
-
- headBranch := ctx.QueryTrim("headBranch")
- if len(headBranch) == 0 {
- ctx.JSON(http.StatusInternalServerError, map[string]interface{}{
- "err": "QueryTrim failed",
- })
- return
- }
-
- pr, err := models.GetUnmergedPullRequest(headRepoID, baseRepoID, headBranch, baseBranch)
- if err != nil && !models.IsErrPullRequestNotExist(err) {
- ctx.JSON(http.StatusInternalServerError, map[string]interface{}{
- "err": err.Error(),
- })
- return
- }
-
- ctx.JSON(http.StatusOK, pr)
-}
diff --git a/routers/private/serv.go b/routers/private/serv.go
new file mode 100644
index 0000000000..68e4361e56
--- /dev/null
+++ b/routers/private/serv.go
@@ -0,0 +1,286 @@
+// Copyright 2019 The Gitea Authors. All rights reserved.
+// Use of this source code is governed by a MIT-style
+// license that can be found in the LICENSE file.
+
+// Package private includes all internal routes. The package name internal is ideal but Golang is not allowed, so we use private as package name instead.
+package private
+
+import (
+ "fmt"
+ "net/http"
+ "strings"
+
+ "code.gitea.io/gitea/models"
+ "code.gitea.io/gitea/modules/log"
+ "code.gitea.io/gitea/modules/private"
+ "code.gitea.io/gitea/modules/setting"
+
+ macaron "gopkg.in/macaron.v1"
+)
+
+// ServNoCommand returns information about the provided keyid
+func ServNoCommand(ctx *macaron.Context) {
+ keyID := ctx.ParamsInt64(":keyid")
+ if keyID <= 0 {
+ ctx.JSON(http.StatusBadRequest, map[string]interface{}{
+ "err": fmt.Sprintf("Bad key id: %d", keyID),
+ })
+ }
+ results := private.KeyAndOwner{}
+
+ key, err := models.GetPublicKeyByID(keyID)
+ if err != nil {
+ if models.IsErrKeyNotExist(err) {
+ ctx.JSON(http.StatusUnauthorized, map[string]interface{}{
+ "err": fmt.Sprintf("Cannot find key: %d", keyID),
+ })
+ return
+ }
+ log.Error("Unable to get public key: %d Error: %v", keyID, err)
+ ctx.JSON(http.StatusInternalServerError, map[string]interface{}{
+ "err": err.Error(),
+ })
+ return
+ }
+ results.Key = key
+
+ if key.Type == models.KeyTypeUser {
+ user, err := models.GetUserByID(key.OwnerID)
+ if err != nil {
+ if models.IsErrUserNotExist(err) {
+ ctx.JSON(http.StatusUnauthorized, map[string]interface{}{
+ "err": fmt.Sprintf("Cannot find owner with id: %d for key: %d", key.OwnerID, keyID),
+ })
+ return
+ }
+ log.Error("Unable to get owner with id: %d for public key: %d Error: %v", key.OwnerID, keyID, err)
+ ctx.JSON(http.StatusInternalServerError, map[string]interface{}{
+ "err": err.Error(),
+ })
+ return
+ }
+ results.Owner = user
+ }
+ ctx.JSON(http.StatusOK, &results)
+ return
+}
+
+// ServCommand returns information about the provided keyid
+func ServCommand(ctx *macaron.Context) {
+ // Although we provide the verbs we don't need them at present they're just for logging purposes
+ keyID := ctx.ParamsInt64(":keyid")
+ ownerName := ctx.Params(":owner")
+ repoName := ctx.Params(":repo")
+ mode := models.AccessMode(ctx.QueryInt("mode"))
+
+ // Set the basic parts of the results to return
+ results := private.ServCommandResults{
+ RepoName: repoName,
+ OwnerName: ownerName,
+ KeyID: keyID,
+ }
+
+ // Now because we're not translating things properly let's just default some Engish strings here
+ modeString := "read"
+ if mode > models.AccessModeRead {
+ modeString = "write to"
+ }
+
+ // The default unit we're trying to look at is code
+ unitType := models.UnitTypeCode
+
+ // Unless we're a wiki...
+ if strings.HasSuffix(repoName, ".wiki") {
+ // in which case we need to look at the wiki
+ unitType = models.UnitTypeWiki
+ // And we'd better munge the reponame and tell downstream we're looking at a wiki
+ results.IsWiki = true
+ results.RepoName = repoName[:len(repoName)-5]
+ }
+
+ // Now get the Repository and set the results section
+ repo, err := models.GetRepositoryByOwnerAndName(results.OwnerName, results.RepoName)
+ if err != nil {
+ if models.IsErrRepoNotExist(err) {
+ ctx.JSON(http.StatusNotFound, map[string]interface{}{
+ "results": results,
+ "type": "ErrRepoNotExist",
+ "err": fmt.Sprintf("Cannot find repository %s/%s", results.OwnerName, results.RepoName),
+ })
+ return
+ }
+ log.Error("Unable to get repository: %s/%s Error: %v", results.OwnerName, results.RepoName, err)
+ ctx.JSON(http.StatusInternalServerError, map[string]interface{}{
+ "results": results,
+ "type": "InternalServerError",
+ "err": fmt.Sprintf("Unable to get repository: %s/%s %v", results.OwnerName, results.RepoName, err),
+ })
+ return
+ }
+ repo.OwnerName = ownerName
+ results.RepoID = repo.ID
+
+ // We can shortcut at this point if the repo is a mirror
+ if mode > models.AccessModeRead && repo.IsMirror {
+ ctx.JSON(http.StatusUnauthorized, map[string]interface{}{
+ "results": results,
+ "type": "ErrMirrorReadOnly",
+ "err": fmt.Sprintf("Mirror Repository %s/%s is read-only", results.OwnerName, results.RepoName),
+ })
+ return
+ }
+
+ // Get the Public Key represented by the keyID
+ key, err := models.GetPublicKeyByID(keyID)
+ if err != nil {
+ if models.IsErrKeyNotExist(err) {
+ ctx.JSON(http.StatusUnauthorized, map[string]interface{}{
+ "results": results,
+ "type": "ErrKeyNotExist",
+ "err": fmt.Sprintf("Cannot find key: %d", keyID),
+ })
+ return
+ }
+ log.Error("Unable to get public key: %d Error: %v", keyID, err)
+ ctx.JSON(http.StatusInternalServerError, map[string]interface{}{
+ "results": results,
+ "type": "InternalServerError",
+ "err": fmt.Sprintf("Unable to get key: %d Error: %v", keyID, err),
+ })
+ return
+ }
+ results.KeyName = key.Name
+ results.KeyID = key.ID
+ results.UserID = key.OwnerID
+
+ // Deploy Keys have ownerID set to 0 therefore we can't use the owner
+ // So now we need to check if the key is a deploy key
+ // We'll keep hold of the deploy key here for permissions checking
+ var deployKey *models.DeployKey
+ var user *models.User
+ if key.Type == models.KeyTypeDeploy {
+ results.IsDeployKey = true
+
+ var err error
+ deployKey, err = models.GetDeployKeyByRepo(key.ID, repo.ID)
+ if err != nil {
+ if models.IsErrDeployKeyNotExist(err) {
+ ctx.JSON(http.StatusUnauthorized, map[string]interface{}{
+ "results": results,
+ "type": "ErrDeployKeyNotExist",
+ "err": fmt.Sprintf("Public (Deploy) Key: %d:%s is not authorized to %s %s/%s.", key.ID, key.Name, modeString, results.OwnerName, results.RepoName),
+ })
+ return
+ }
+ log.Error("Unable to get deploy for public (deploy) key: %d in %-v Error: %v", key.ID, repo, err)
+ ctx.JSON(http.StatusInternalServerError, map[string]interface{}{
+ "results": results,
+ "type": "InternalServerError",
+ "err": fmt.Sprintf("Unable to get Deploy Key for Public Key: %d:%s in %s/%s.", key.ID, key.Name, results.OwnerName, results.RepoName),
+ })
+ return
+ }
+ results.KeyName = deployKey.Name
+
+ // 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 of the repository
+ results.UserName = results.OwnerName
+ results.UserID = repo.OwnerID
+ } else {
+ // Get the user represented by the Key
+ var err error
+ user, err = models.GetUserByID(key.OwnerID)
+ if err != nil {
+ if models.IsErrUserNotExist(err) {
+ ctx.JSON(http.StatusUnauthorized, map[string]interface{}{
+ "results": results,
+ "type": "ErrUserNotExist",
+ "err": fmt.Sprintf("Public Key: %d:%s owner %d does not exist.", key.ID, key.Name, key.OwnerID),
+ })
+ return
+ }
+ log.Error("Unable to get owner: %d for public key: %d:%s Error: %v", key.OwnerID, key.ID, key.Name, err)
+ ctx.JSON(http.StatusInternalServerError, map[string]interface{}{
+ "results": results,
+ "type": "InternalServerError",
+ "err": fmt.Sprintf("Unable to get Owner: %d for Deploy Key: %d:%s in %s/%s.", key.OwnerID, key.ID, key.Name, ownerName, repoName),
+ })
+ return
+ }
+ results.UserName = user.Name
+ }
+
+ // Don't allow pushing if the repo is archived
+ if mode > models.AccessModeRead && repo.IsArchived {
+ ctx.JSON(http.StatusUnauthorized, map[string]interface{}{
+ "results": results,
+ "type": "ErrRepoIsArchived",
+ "err": fmt.Sprintf("Repo: %s/%s is archived.", results.OwnerName, results.RepoName),
+ })
+ return
+ }
+
+ // Permissions checking:
+ if mode > models.AccessModeRead || repo.IsPrivate || setting.Service.RequireSignInView {
+ if key.Type == models.KeyTypeDeploy {
+ if deployKey.Mode < mode {
+ ctx.JSON(http.StatusUnauthorized, map[string]interface{}{
+ "results": results,
+ "type": "ErrUnauthorized",
+ "err": fmt.Sprintf("Deploy Key: %d:%s is not authorized to %s %s/%s.", key.ID, key.Name, modeString, results.OwnerName, results.RepoName),
+ })
+ return
+ }
+ } else {
+ perm, err := models.GetUserRepoPermission(repo, user)
+ if err != nil {
+ log.Error("Unable to get permissions for %-v with key %d in %-v Error: %v", user, key.ID, repo, err)
+ ctx.JSON(http.StatusInternalServerError, map[string]interface{}{
+ "results": results,
+ "type": "InternalServerError",
+ "err": fmt.Sprintf("Unable to get permissions for user %d:%s with key %d in %s/%s Error: %v", user.ID, user.Name, key.ID, results.OwnerName, results.RepoName, err),
+ })
+ return
+ }
+
+ userMode := perm.UnitAccessMode(unitType)
+
+ if userMode < mode {
+ ctx.JSON(http.StatusUnauthorized, map[string]interface{}{
+ "results": results,
+ "type": "ErrUnauthorized",
+ "err": fmt.Sprintf("User: %d:%s with Key: %d:%s is not authorized to %s %s/%s.", user.ID, user.Name, key.ID, key.Name, modeString, ownerName, repoName),
+ })
+ return
+ }
+ }
+ }
+
+ // Finally if we're trying to touch the wiki we should init it
+ if results.IsWiki {
+ if err = repo.InitWiki(); err != nil {
+ log.Error("Failed to initialize the wiki in %-v Error: %v", repo, err)
+ ctx.JSON(http.StatusInternalServerError, map[string]interface{}{
+ "results": results,
+ "type": "InternalServerError",
+ "err": fmt.Sprintf("Failed to initialize the wiki in %s/%s Error: %v", ownerName, repoName, err),
+ })
+ return
+ }
+ }
+ log.Debug("Serv Results:\nIsWiki: %t\nIsDeployKey: %t\nKeyID: %d\tKeyName: %s\nUserName: %s\nUserID: %d\nOwnerName: %s\nRepoName: %s\nRepoID: %d",
+ results.IsWiki,
+ results.IsDeployKey,
+ results.KeyID,
+ results.KeyName,
+ results.UserName,
+ results.UserID,
+ results.OwnerName,
+ results.RepoName,
+ results.RepoID)
+
+ ctx.JSON(http.StatusOK, results)
+ // We will update the keys in a different call.
+ return
+}
diff --git a/routers/private/wiki.go b/routers/private/wiki.go
deleted file mode 100644
index 33bcbaf17e..0000000000
--- a/routers/private/wiki.go
+++ /dev/null
@@ -1,34 +0,0 @@
-// Copyright 2017 The Gitea Authors. All rights reserved.
-// Use of this source code is governed by a MIT-style
-// license that can be found in the LICENSE file.
-
-package private
-
-import (
- "code.gitea.io/gitea/models"
-
- macaron "gopkg.in/macaron.v1"
-)
-
-// InitWiki initilizes wiki via repo id
-func InitWiki(ctx *macaron.Context) {
- repoID := ctx.ParamsInt64("repoid")
-
- repo, err := models.GetRepositoryByID(repoID)
- if err != nil {
- ctx.JSON(500, map[string]interface{}{
- "err": err.Error(),
- })
- return
- }
-
- err = repo.InitWiki()
- if err != nil {
- ctx.JSON(500, map[string]interface{}{
- "err": err.Error(),
- })
- return
- }
-
- ctx.Status(202)
-}
diff --git a/routers/repo/http.go b/routers/repo/http.go
index fccecfb71d..214e2f3411 100644
--- a/routers/repo/http.go
+++ b/routers/repo/http.go
@@ -351,7 +351,7 @@ func gitCommand(dir string, args ...string) []byte {
cmd.Dir = dir
out, err := cmd.Output()
if err != nil {
- log.GitLogger.Error(fmt.Sprintf("%v - %s", err, out))
+ log.Error("%v - %s", err, out)
}
return out
}
@@ -409,7 +409,7 @@ func serviceRPC(h serviceHandler, service string) {
if h.r.Header.Get("Content-Encoding") == "gzip" {
reqBody, err = gzip.NewReader(reqBody)
if err != nil {
- log.GitLogger.Error("Fail to create gzip reader: %v", err)
+ log.Error("Fail to create gzip reader: %v", err)
h.w.WriteHeader(http.StatusInternalServerError)
return
}
@@ -428,7 +428,7 @@ func serviceRPC(h serviceHandler, service string) {
cmd.Stdin = reqBody
cmd.Stderr = &stderr
if err := cmd.Run(); err != nil {
- log.GitLogger.Error("Fail to serve RPC(%s): %v - %v", service, err, stderr)
+ log.Error("Fail to serve RPC(%s): %v - %v", service, err, stderr)
return
}
}
@@ -541,7 +541,7 @@ func HTTPBackend(ctx *context.Context, cfg *serviceConfig) http.HandlerFunc {
file := strings.Replace(r.URL.Path, m[1]+"/", "", 1)
dir, err := getGitRepoPath(m[1])
if err != nil {
- log.GitLogger.Error(err.Error())
+ log.Error(err.Error())
ctx.NotFound("HTTPBackend", err)
return
}