summaryrefslogtreecommitdiffstats
path: root/routers/private
diff options
context:
space:
mode:
authorzeripath <art27@cantab.net>2019-06-01 16:00:21 +0100
committerLunny Xiao <xiaolunwen@gmail.com>2019-06-01 23:00:21 +0800
commit356854fc5f8d7d1a7e4d68c9e00929e9ce8aa867 (patch)
treebc250740ffe65de5cd9ce3389e004ca7723d5643 /routers/private
parent8a343dda39b187627db6ffb4c24a6e0ae615867b (diff)
downloadgitea-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 'routers/private')
-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
8 files changed, 511 insertions, 297 deletions
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)
-}