summaryrefslogtreecommitdiffstats
path: root/routers/private
diff options
context:
space:
mode:
authorJohn Olheiser <42128690+jolheiser@users.noreply.github.com>2019-12-14 20:49:52 -0600
committerLunny Xiao <xiaolunwen@gmail.com>2019-12-15 10:49:52 +0800
commit6715677b2bf7a065d0184ea7f2647e70ca2598d4 (patch)
treeec2ed74b0eb153391bd46a9552923b2282867be5 /routers/private
parent47c24be293ac8b1b28310d2fb2be58b8191a5bae (diff)
downloadgitea-6715677b2bf7a065d0184ea7f2647e70ca2598d4.tar.gz
gitea-6715677b2bf7a065d0184ea7f2647e70ca2598d4.zip
Push to create repo (#8419)
* Refactor Signed-off-by: jolheiser <john.olheiser@gmail.com> * Add push-create to SSH serv Signed-off-by: jolheiser <john.olheiser@gmail.com> * Cannot push for another user unless admin Signed-off-by: jolheiser <john.olheiser@gmail.com> * Get owner in case admin pushes for another user Signed-off-by: jolheiser <john.olheiser@gmail.com> * Set new repo ID in result Signed-off-by: jolheiser <john.olheiser@gmail.com> * Update to service and use new org perms Signed-off-by: jolheiser <john.olheiser@gmail.com> * Move pushCreateRepo to services Signed-off-by: jolheiser <john.olheiser@gmail.com> * Fix import order Signed-off-by: jolheiser <john.olheiser@gmail.com> * Changes for @guillep2k * Check owner (not user) in SSH * Add basic tests for created repos (private, not empty) Signed-off-by: jolheiser <john.olheiser@gmail.com>
Diffstat (limited to 'routers/private')
-rw-r--r--routers/private/serv.go113
1 files changed, 83 insertions, 30 deletions
diff --git a/routers/private/serv.go b/routers/private/serv.go
index c4508b4cb5..64fd671309 100644
--- a/routers/private/serv.go
+++ b/routers/private/serv.go
@@ -14,6 +14,7 @@ import (
"code.gitea.io/gitea/modules/log"
"code.gitea.io/gitea/modules/private"
"code.gitea.io/gitea/modules/setting"
+ repo_service "code.gitea.io/gitea/services/repository"
"gitea.com/macaron/macaron"
)
@@ -98,44 +99,44 @@ func ServCommand(ctx *macaron.Context) {
}
// Now get the Repository and set the results section
+ repoExist := true
repo, err := models.GetRepositoryByOwnerAndName(results.OwnerName, results.RepoName)
if err != nil {
if models.IsErrRepoNotExist(err) {
- ctx.JSON(http.StatusNotFound, map[string]interface{}{
+ repoExist = false
+ } else {
+ 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": "ErrRepoNotExist",
- "err": fmt.Sprintf("Cannot find repository %s/%s", results.OwnerName, results.RepoName),
+ "type": "InternalServerError",
+ "err": fmt.Sprintf("Unable to get repository: %s/%s %v", results.OwnerName, results.RepoName, err),
})
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
- if repo.IsBeingCreated() {
- ctx.JSON(http.StatusInternalServerError, map[string]interface{}{
- "results": results,
- "type": "InternalServerError",
- "err": "Repository is being created, you could retry after it finished",
- })
- return
- }
+ if repoExist {
+ 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
+ if repo.IsBeingCreated() {
+ ctx.JSON(http.StatusInternalServerError, map[string]interface{}{
+ "results": results,
+ "type": "InternalServerError",
+ "err": "Repository is being created, you could retry after it finished",
+ })
+ return
+ }
+
+ // 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
@@ -161,6 +162,16 @@ func ServCommand(ctx *macaron.Context) {
results.KeyID = key.ID
results.UserID = key.OwnerID
+ // If repo doesn't exist, deploy key doesn't make sense
+ if !repoExist && key.Type == models.KeyTypeDeploy {
+ ctx.JSON(http.StatusNotFound, map[string]interface{}{
+ "results": results,
+ "type": "ErrRepoNotExist",
+ "err": fmt.Sprintf("Cannot find repository %s/%s", results.OwnerName, results.RepoName),
+ })
+ return
+ }
+
// 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
@@ -220,7 +231,7 @@ func ServCommand(ctx *macaron.Context) {
}
// Don't allow pushing if the repo is archived
- if mode > models.AccessModeRead && repo.IsArchived {
+ if repoExist && mode > models.AccessModeRead && repo.IsArchived {
ctx.JSON(http.StatusUnauthorized, map[string]interface{}{
"results": results,
"type": "ErrRepoIsArchived",
@@ -230,7 +241,7 @@ func ServCommand(ctx *macaron.Context) {
}
// Permissions checking:
- if mode > models.AccessModeRead || repo.IsPrivate || setting.Service.RequireSignInView {
+ if repoExist && (mode > models.AccessModeRead || repo.IsPrivate || setting.Service.RequireSignInView) {
if key.Type == models.KeyTypeDeploy {
if deployKey.Mode < mode {
ctx.JSON(http.StatusUnauthorized, map[string]interface{}{
@@ -265,6 +276,48 @@ func ServCommand(ctx *macaron.Context) {
}
}
+ // We already know we aren't using a deploy key
+ if !repoExist {
+ owner, err := models.GetUserByName(ownerName)
+ if err != nil {
+ ctx.JSON(http.StatusInternalServerError, map[string]interface{}{
+ "results": results,
+ "type": "InternalServerError",
+ "err": fmt.Sprintf("Unable to get owner: %s %v", results.OwnerName, err),
+ })
+ return
+ }
+
+ if owner.IsOrganization() && !setting.Repository.EnablePushCreateOrg {
+ ctx.JSON(http.StatusForbidden, map[string]interface{}{
+ "results": results,
+ "type": "ErrForbidden",
+ "err": "Push to create is not enabled for organizations.",
+ })
+ return
+ }
+ if !owner.IsOrganization() && !setting.Repository.EnablePushCreateUser {
+ ctx.JSON(http.StatusForbidden, map[string]interface{}{
+ "results": results,
+ "type": "ErrForbidden",
+ "err": "Push to create is not enabled for users.",
+ })
+ return
+ }
+
+ repo, err = repo_service.PushCreateRepo(user, owner, results.RepoName)
+ if err != nil {
+ log.Error("pushCreateRepo: %v", 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
+ }
+ results.RepoID = repo.ID
+ }
+
// Finally if we're trying to touch the wiki we should init it
if results.IsWiki {
if err = repo.InitWiki(); err != nil {