woodpecker/server/middleware/repo.go

116 lines
2.8 KiB
Go

package middleware
import (
"net/http"
"regexp"
"github.com/drone/drone/server/datastore"
"github.com/goji/context"
"github.com/zenazn/goji/web"
)
// SetRepo is a middleware function that retrieves
// the repository and stores in the context.
func SetRepo(c *web.C, h http.Handler) http.Handler {
fn := func(w http.ResponseWriter, r *http.Request) {
var (
ctx = context.FromC(*c)
host = c.URLParams["host"]
owner = c.URLParams["owner"]
name = c.URLParams["name"]
user = ToUser(c)
)
repo, err := datastore.GetRepoName(ctx, host, owner, name)
switch {
case err != nil && user == nil:
w.WriteHeader(http.StatusUnauthorized)
return
case err != nil && user != nil:
w.WriteHeader(http.StatusNotFound)
return
}
role, _ := datastore.GetPerm(ctx, user, repo)
RepoToC(c, repo)
RoleToC(c, role)
h.ServeHTTP(w, r)
}
return http.HandlerFunc(fn)
}
// RequireRepoRead is a middleware function that verifies
// the user has read access to the repository.
func RequireRepoRead(c *web.C, h http.Handler) http.Handler {
fn := func(w http.ResponseWriter, r *http.Request) {
var (
role = ToRole(c)
user = ToUser(c)
)
switch {
case role == nil:
w.WriteHeader(http.StatusInternalServerError)
case user == nil && role.Read == false:
w.WriteHeader(http.StatusUnauthorized)
return
case user == nil && role.Read == false:
w.WriteHeader(http.StatusUnauthorized)
return
case user != nil && role.Read == false:
w.WriteHeader(http.StatusNotFound)
return
}
h.ServeHTTP(w, r)
}
return http.HandlerFunc(fn)
}
// RequireRepoAdmin is a middleware function that verifies
// the user has admin access to the repository.
func RequireRepoAdmin(c *web.C, h http.Handler) http.Handler {
fn := func(w http.ResponseWriter, r *http.Request) {
var (
role = ToRole(c)
user = ToUser(c)
)
// Admin access is only rquired for POST, PUT, DELETE methods.
// If this is a GET request we can proceed immediately.
if r.Method == "GET" {
h.ServeHTTP(w, r)
return
}
switch {
case role == nil:
w.WriteHeader(http.StatusInternalServerError)
return
case user == nil && role.Admin == false:
w.WriteHeader(http.StatusUnauthorized)
return
case user != nil && role.Read == false && role.Admin == false:
w.WriteHeader(http.StatusNotFound)
return
case user != nil && role.Write == true && role.Admin == false:
if IsRebuild(r.URL.Path) {
h.ServeHTTP(w, r)
return
}
w.WriteHeader(http.StatusForbidden)
return
case user != nil && role.Read == true && role.Admin == false:
w.WriteHeader(http.StatusForbidden)
return
default:
h.ServeHTTP(w, r)
return
}
}
return http.HandlerFunc(fn)
}
func IsRebuild(path string) bool {
const pattern = `\/(.*)\/(.*)\/(.*)\/branches\/(.*)\/commits\/(.*)`
ok, _ := regexp.MatchString(pattern, path)
return ok
}