summaryrefslogtreecommitdiffstats
path: root/routers/repo/http.go
diff options
context:
space:
mode:
authorDenis Denisov <denji@users.noreply.github.com>2017-02-21 17:02:10 +0200
committerLunny Xiao <xiaolunwen@gmail.com>2017-02-21 23:02:10 +0800
commitfd941db246e66244ec81f43d74b8358c06173fd6 (patch)
treebe563ff04f3b809b2d11489447086d5251e9b55a /routers/repo/http.go
parentfe5ff8e4b2b3c951fa85572f3760ee2a396247ac (diff)
downloadgitea-fd941db246e66244ec81f43d74b8358c06173fd6.tar.gz
gitea-fd941db246e66244ec81f43d74b8358c06173fd6.zip
Protected branches system (#339)
* Protected branches system * Moved default branch to branches section (`:org/:reponame/settings/branches`). * Initial support Protected Branch. - Admin does not restrict - Owner not to limit - To write permission restrictions * reformat tmpl * finished the UI and add/delete protected branch response * remove unused comment * indent all the template files and remove ru translations since we use crowdin * fix the push bug
Diffstat (limited to 'routers/repo/http.go')
-rw-r--r--routers/repo/http.go97
1 files changed, 86 insertions, 11 deletions
diff --git a/routers/repo/http.go b/routers/repo/http.go
index 695e758cdb..780babd40d 100644
--- a/routers/repo/http.go
+++ b/routers/repo/http.go
@@ -42,10 +42,20 @@ func HTTP(ctx *context.Context) {
} else if service == "git-upload-pack" ||
strings.HasSuffix(ctx.Req.URL.Path, "git-upload-pack") {
isPull = true
+ } else if service == "git-upload-archive" ||
+ strings.HasSuffix(ctx.Req.URL.Path, "git-upload-archive") {
+ isPull = true
} else {
isPull = (ctx.Req.Method == "GET")
}
+ var accessMode models.AccessMode
+ if isPull {
+ accessMode = models.AccessModeRead
+ } else {
+ accessMode = models.AccessModeWrite
+ }
+
isWiki := false
if strings.HasSuffix(reponame, ".wiki") {
isWiki = true
@@ -146,17 +156,12 @@ func HTTP(ctx *context.Context) {
}
if !isPublicPull {
- var tp = models.AccessModeWrite
- if isPull {
- tp = models.AccessModeRead
- }
-
- has, err := models.HasAccess(authUser, repo, tp)
+ has, err := models.HasAccess(authUser, repo, accessMode)
if err != nil {
ctx.Handle(http.StatusInternalServerError, "HasAccess", err)
return
} else if !has {
- if tp == models.AccessModeRead {
+ if accessMode == models.AccessModeRead {
has, err = models.HasAccess(authUser, repo, models.AccessModeWrite)
if err != nil {
ctx.Handle(http.StatusInternalServerError, "HasAccess2", err)
@@ -232,9 +237,20 @@ func HTTP(ctx *context.Context) {
}
}
+ params := make(map[string]string)
+
+ if askAuth {
+ params[models.ProtectedBranchUserID] = fmt.Sprintf("%d", authUser.ID)
+ if err == nil {
+ params[models.ProtectedBranchAccessMode] = accessMode.String()
+ }
+ params[models.ProtectedBranchRepoID] = fmt.Sprintf("%d", repo.ID)
+ }
+
HTTPBackend(ctx, &serviceConfig{
UploadPack: true,
ReceivePack: true,
+ Params: params,
OnSucceed: callback,
})(ctx.Resp, ctx.Req.Request)
@@ -244,6 +260,7 @@ func HTTP(ctx *context.Context) {
type serviceConfig struct {
UploadPack bool
ReceivePack bool
+ Params map[string]string
OnSucceed func(rpc string, input []byte)
}
@@ -261,6 +278,42 @@ func (h *serviceHandler) setHeaderNoCache() {
h.w.Header().Set("Cache-Control", "no-cache, max-age=0, must-revalidate")
}
+func (h *serviceHandler) getBranch(input []byte) string {
+ var lastLine int64
+ var branchName string
+ for {
+ head := input[lastLine : lastLine+2]
+ if head[0] == '0' && head[1] == '0' {
+ size, err := strconv.ParseInt(string(input[lastLine+2:lastLine+4]), 16, 32)
+ if err != nil {
+ log.Error(4, "%v", err)
+ return branchName
+ }
+
+ if size == 0 {
+ //fmt.Println(string(input[lastLine:]))
+ break
+ }
+
+ line := input[lastLine : lastLine+size]
+ idx := bytes.IndexRune(line, '\000')
+ if idx > -1 {
+ line = line[:idx]
+ }
+
+ fields := strings.Fields(string(line))
+ if len(fields) >= 3 {
+ refFullName := fields[2]
+ branchName = strings.TrimPrefix(refFullName, git.BranchPrefix)
+ }
+ lastLine = lastLine + size
+ } else {
+ break
+ }
+ }
+ return branchName
+}
+
func (h *serviceHandler) setHeaderCacheForever() {
now := time.Now().Unix()
expires := now + 31536000
@@ -358,13 +411,15 @@ func serviceRPC(h serviceHandler, service string) {
h.w.WriteHeader(http.StatusUnauthorized)
return
}
+
h.w.Header().Set("Content-Type", fmt.Sprintf("application/x-git-%s-result", service))
var (
- reqBody = h.r.Body
- input []byte
- br io.Reader
- err error
+ reqBody = h.r.Body
+ input []byte
+ br io.Reader
+ err error
+ branchName string
)
// Handle GZIP.
@@ -385,11 +440,31 @@ func serviceRPC(h serviceHandler, service string) {
return
}
+ branchName = h.getBranch(input)
br = bytes.NewReader(input)
} else {
br = reqBody
}
+ // check protected branch
+ repoID, _ := strconv.ParseInt(h.cfg.Params[models.ProtectedBranchRepoID], 10, 64)
+ accessMode := models.ParseAccessMode(h.cfg.Params[models.ProtectedBranchAccessMode])
+ // skip admin or owner AccessMode
+ if accessMode == models.AccessModeWrite {
+ protectBranch, err := models.GetProtectedBranchBy(repoID, branchName)
+ if err != nil {
+ log.GitLogger.Error(2, "fail to get protected branch information: %v", err)
+ h.w.WriteHeader(http.StatusInternalServerError)
+ return
+ }
+
+ if protectBranch != nil {
+ log.GitLogger.Error(2, "protected branches can not be pushed to")
+ h.w.WriteHeader(http.StatusForbidden)
+ return
+ }
+ }
+
cmd := exec.Command("git", service, "--stateless-rpc", h.dir)
cmd.Dir = h.dir
cmd.Stdout = h.w