Files
athens/pkg/middleware/validation.go
Federico Paolinelli c8b64fd258 Proxy 'admission controller' (#492)
* The proxy middleware calls an hook if set to check if the module needs
to be filtered

* Fixed error handling

* Added a middleware func that passes the log entry down to other
middlewares

* Split the filter middleware in two

* Moved validation middleware in its own file

* Renamed filter to middleware, all the middleware stuff in a single file

* Moved default hook to empty string

* Split tests of filter middleware from validation middleware

* Installed the validation middleware only if the hook is set

* Moved filter test to middleware test

* Fixed gofmt issue caused by manual merge

* Fixed wrong logrus import

* Removed logger from filter middleware

* Moved middleware functions to own package

* Removed unused argument, fixed errors

* Fixed gofmt errors

* Made middleware func private

* Changed debuglevel from string to enum

* Added comments to now public functions

* Changed module alias to a shorter one

* Removed white space

* Split middleware in separate files, injected the hook as param

* Removed commented code
2018-08-21 22:51:26 +02:00

80 lines
2.0 KiB
Go

package middleware
import (
"bytes"
"encoding/json"
"net/http"
"github.com/bketelsen/buffet"
"github.com/gobuffalo/buffalo"
"github.com/gomods/athens/pkg/errors"
"github.com/gomods/athens/pkg/log"
"github.com/gomods/athens/pkg/paths"
)
// NewValidationMiddleware builds a middleware function that performs validation checks by calling
// an external webhook
func NewValidationMiddleware(entry log.Entry, validatorHook string) buffalo.MiddlewareFunc {
const op errors.Op = "actions.ValidationMiddleware"
return func(next buffalo.Handler) buffalo.Handler {
return func(c buffalo.Context) error {
sp := buffet.SpanFromContext(c).SetOperationName("validationMiddleware")
defer sp.Finish()
mod, err := paths.GetModule(c)
if err != nil {
// if there is no module the path we are hitting is not one related to modules, like /
return next(c)
}
// not checking the error. Not all requests include a version
// i.e. list requests path is like /{module:.+}/@v/list with no version parameter
version, _ := paths.GetVersion(c)
if version != "" {
valid, err := validate(validatorHook, mod, version)
if err != nil {
entry.SystemErr(err)
return c.Render(http.StatusInternalServerError, nil)
}
if !valid {
return c.Render(http.StatusForbidden, nil)
}
}
return next(c)
}
}
}
type validationParams struct {
Module string
Version string
}
func validate(hook, mod, ver string) (bool, error) {
const op errors.Op = "actions.validate"
toVal := &validationParams{mod, ver}
jsonVal, err := json.Marshal(toVal)
if err != nil {
return false, errors.E(op, err)
}
resp, err := http.Post(hook, "application/json", bytes.NewBuffer(jsonVal))
if err != nil {
return false, errors.E(op, err)
}
switch {
case resp.StatusCode == http.StatusOK:
return true, nil
case resp.StatusCode == http.StatusForbidden:
return false, nil
default:
return false, errors.E(op, "Unexpected status code ", resp.StatusCode)
}
}