diff options
author | John Olheiser <42128690+jolheiser@users.noreply.github.com> | 2019-12-14 20:49:52 -0600 |
---|---|---|
committer | Lunny Xiao <xiaolunwen@gmail.com> | 2019-12-15 10:49:52 +0800 |
commit | 6715677b2bf7a065d0184ea7f2647e70ca2598d4 (patch) | |
tree | ec2ed74b0eb153391bd46a9552923b2282867be5 /routers/private | |
parent | 47c24be293ac8b1b28310d2fb2be58b8191a5bae (diff) | |
download | gitea-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.go | 113 |
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 { |