1
0
Fork 0
forked from boyska/feedpanel
feedpanel/panelui/middleware.go

76 lines
1.4 KiB
Go

package panelui
import (
"context"
"net"
"net/http"
)
type ctxKey int
const (
keyUser = iota
)
//HeaderAuth is a Negroni-compatible Middleware
type HeaderAuth struct {
AllowedNames []string
AllowedIPs []net.IP
RequireUser bool
}
func _getSourceIP(req *http.Request) (net.IP, error) {
ip, _, err := net.SplitHostPort(req.RemoteAddr)
if err != nil {
return net.IP{}, err
}
userIP := net.ParseIP(ip)
if userIP == nil {
return net.IP{}, err
}
return userIP, nil
}
func (ha HeaderAuth) ServeHTTP(rw http.ResponseWriter, r *http.Request, next http.HandlerFunc) {
srcIP, err := _getSourceIP(r)
if err != nil {
rw.WriteHeader(501)
return
}
found := false
if len(ha.AllowedNames) == 0 && len(ha.AllowedIPs) == 0 {
found = true
}
if !found && len(ha.AllowedIPs) > 0 {
for _, allowedIP := range ha.AllowedIPs {
if allowedIP.Equal(srcIP) {
found = true
break
}
}
}
if !found && len(ha.AllowedNames) > 0 {
for _, name := range ha.AllowedNames {
nameips, err := net.LookupIP(name)
if err != nil {
continue
}
for _, allowedIP := range nameips {
if allowedIP.Equal(srcIP) {
found = true
break
}
}
}
}
user := r.Header.Get("X-Forwarded-User")
if !found || (ha.RequireUser && user == "") {
rw.WriteHeader(http.StatusUnauthorized)
return
}
ctx := r.Context()
ctx = context.WithValue(ctx, keyUser, user)
next(rw, r.WithContext(ctx))
return
}