mirror of
https://github.com/go-gitea/gitea.git
synced 2024-05-11 05:55:29 +00:00
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
This commit is contained in:
committed by
Lunny Xiao
parent
fe5ff8e4b2
commit
fd941db246
@@ -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
|
||||
|
Reference in New Issue
Block a user