auth/auth.go

This commit is contained in:
spsobole 2021-01-18 20:00:46 -07:00
parent b3f019793a
commit 813df834ab
5 changed files with 184 additions and 26 deletions

View File

@ -14,12 +14,12 @@ func handlerAuthenticated(c *snap.Context) {
}
func mustRunServer(auth auth.AuthManager) {
func mustRunServer(auth auth.Authenticator) {
srv := snap.New("127.0.0.1:9000", "./", nil)
srv.SetDebug(true)
srv.HandleFunc("/", handler)
srv.HandleFuncCustomAuth(auth,"/auth", handlerAuthenticated)
srv.HandleFuncCustomAuth(auth,"/auth", "", handlerAuthenticated)
srv.Serve()
}

1
go.mod
View File

@ -5,4 +5,5 @@ go 1.15
require (
git.thirdmartini.com/pub/fancylog v0.0.0-20180118031448-3f3ebedd6016
github.com/gorilla/mux v1.8.0
github.com/stretchr/testify v1.7.0
)

12
go.sum
View File

@ -1,3 +1,15 @@
git.thirdmartini.com/pub/fancylog v0.0.0-20180118031448-3f3ebedd6016 h1:egW0VTyAgD7FjG6iZKHBcHc7siCGjoxm1T71GecYUE4=
git.thirdmartini.com/pub/fancylog v0.0.0-20180118031448-3f3ebedd6016/go.mod h1:nxr8UYB5P+7cpJPpqcbhMjfqm+GH3VDZQs2dFWibA68=
github.com/davecgh/go-spew v1.1.0 h1:ZDRjVQ15GmhC3fiQ8ni8+OwkZQO4DARzQgrnXU1Liz8=
github.com/davecgh/go-spew v1.1.0/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38=
github.com/gorilla/mux v1.8.0 h1:i40aqfkR1h2SlN9hojwV5ZA91wcXFOvkdNIeFDP5koI=
github.com/gorilla/mux v1.8.0/go.mod h1:DVbg23sWSpFRCP0SfiEN6jmj59UnW/n46BH5rLB71So=
github.com/pmezard/go-difflib v1.0.0 h1:4DBwDE0NGyQoBHbLQYPwSUPoCMWR5BEzIk/f1lZbAQM=
github.com/pmezard/go-difflib v1.0.0/go.mod h1:iKH77koFhYxTK1pcRnkKkqfTogsbg7gZNVY4sRDYZ/4=
github.com/stretchr/objx v0.1.0 h1:4G4v2dO3VZwixGIRoQ5Lfboy6nUhCyYzaqnIAPPhYs4=
github.com/stretchr/objx v0.1.0/go.mod h1:HFkY916IF+rwdDfMAkV7OtwuqBVzrE8GR6GFx+wExME=
github.com/stretchr/testify v1.7.0 h1:nwc3DEeHmmLAfoZucVR881uASk0Mfjw8xYJ99tb5CcY=
github.com/stretchr/testify v1.7.0/go.mod h1:6Fq8oRcR53rry900zMqJjRRixrwX3KX962/h/Wwjteg=
gopkg.in/check.v1 v0.0.0-20161208181325-20d25e280405/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0=
gopkg.in/yaml.v3 v3.0.0-20200313102051-9f266ea9e77c h1:dUUwHk2QECo/6vqA44rthZ8ie2QXMNeKRTHCNY2nXvo=
gopkg.in/yaml.v3 v3.0.0-20200313102051-9f266ea9e77c/go.mod h1:K4uyk7z7BCEPqu6E+C64Yfv1cQ7kz7rIZviUmN+EgEM=

View File

@ -7,6 +7,7 @@ import (
"io/ioutil"
"net/http"
"os"
"path"
"path/filepath"
"strings"
"time"
@ -23,7 +24,7 @@ type Server struct {
path string
theme string
debug bool
auth auth.AuthManager
auth auth.Authenticator
router *mux.Router
templates string
cachedTmpl *template.Template
@ -45,14 +46,17 @@ func (s *Server) makeContext(auth *auth.AuthData, w http.ResponseWriter, r *http
return c
}
func (s *Server) authenticated(auth auth.AuthManager, handle func(c *Context)) http.HandlerFunc {
func (s *Server) authenticated(auth auth.Authenticator, redirect string, handle func(c *Context)) http.HandlerFunc {
return func(w http.ResponseWriter, r *http.Request) {
log.Debug("authenticated request: ", r.RequestURI)
rec, ok := auth.DoAuth(w, r)
if !ok {
http.Error(w, "Not authorized", 401)
if redirect != "" {
http.Redirect(w, r, redirect, http.StatusSeeOther)
} else {
http.Error(w, "Not authorized", http.StatusForbidden)
}
} else {
c := s.makeContext(rec, w, r)
handle(c)
@ -125,12 +129,6 @@ func (s *Server) loadTemplates() *template.Template {
if err != nil {
log.Println(err)
}
/*
_, err = tmpl.ParseFiles(path)
if err != nil {
log.Println(err)
}
*/
}
return err
})
@ -169,20 +167,20 @@ func (s *Server) renderError(w http.ResponseWriter, code int, msg string) {
w.Write([]byte(msg))
}
func (s *Server) HandleFuncAuthenticated(path string, f func(c *Context)) *mux.Route {
func (s *Server) HandleFuncAuthenticated(path,redirect string, f func(c *Context)) *mux.Route {
if s.auth == nil {
return nil
}
return s.router.HandleFunc(path, s.authenticated(s.auth, f))
return s.router.HandleFunc(path, s.authenticated(s.auth,redirect, f))
}
func (s *Server) HandleFuncCustomAuth(auth auth.AuthManager, path string, f func(c *Context)) *mux.Route {
func (s *Server) HandleFuncCustomAuth(auth auth.Authenticator, path, redirect string, f func(c *Context)) *mux.Route {
if auth == nil {
log.Warn("Nil auth on", path)
return nil
}
return s.router.HandleFunc(path, s.authenticated(auth, f))
return s.router.HandleFunc(path, s.authenticated(auth,redirect, f))
}
func (s *Server) HandleFunc(path string, f func(c *Context)) *mux.Route {
@ -196,12 +194,12 @@ func (s *Server) SetDebug(enable bool) {
func (s *Server) EnableStatus(path string) {
}
func (s *Server) SetTheme(theme string) {
s.theme = theme
func (s *Server) SetTheme(themePath string) {
s.theme = path.Clean(themePath)
}
func (s *Server) SetTemplatePath(path string) {
s.templates = path
func (s *Server) SetTemplatePath(tmplPath string) {
s.templates = path.Clean(tmplPath)
}
func (s *Server) Router() *mux.Router {
@ -239,17 +237,24 @@ func (s *Server) WithStaticFiles(prefix string, path string) *Server {
}
func (s *Server) WithTheme(themeURL string) *Server {
s.theme = themeURL
s.theme = path.Clean(themeURL)
return s
}
func (s *Server) WithDebug(debugURL string) *Server {
sub := s.router.PathPrefix("/sovereign/debug").Subrouter()
sub := s.router.PathPrefix(debugURL).Subrouter()
setupDebugHandler(sub)
return s
}
func New(address string, path string, auth auth.AuthManager) *Server {
func (s *Server) Dump() {
fmt.Printf( " Path: %s\n", s.path)
fmt.Printf( " Theme: %s\n", s.theme)
fmt.Printf( " Templates: %s\n", s.templates)
}
func New(address string, path string, auth auth.Authenticator) *Server {
s := Server{
router: mux.NewRouter(),
auth: auth,
@ -258,7 +263,5 @@ func New(address string, path string, auth auth.AuthManager) *Server {
templates: "templates",
theme: "/static/css/default.css",
}
//s.router.PathPrefix("/static/").Handler(http.StripPrefix("/static/", http.FileServer(http.Dir(s.path+"static/"))))
return &s
}

View File

@ -1,10 +1,152 @@
package snap
import (
"io/ioutil"
"net/http"
"net/http/httptest"
"testing"
"github.com/stretchr/testify/assert"
"git.thirdmartini.com/pub/snap/auth"
)
func TestServer(t *testing.T) {
var rootExpected = []byte(`
<html lang="en">
<head>
<link rel="stylesheet" href="/static/skin/css/normalize.css">
</head>
<body>
Test of things
</body>
</html>
`)
var testExpected = []byte(`
<html lang="en">
<head>
<link rel="stylesheet" href="/static/skin/css/normalize.css">
</head>
<body>
User: admin
</body>
</html>
`)
func handlerRoot(c *Context) {
c.RenderEx("index.html", nil)
}
func handlerLogin(c *Context) {
c.RenderEx("index.html", nil)
}
func handlerTest(c *Context) {
c.RenderEx("test.html", nil)
}
func doTestRequest(t *testing.T, req *http.Request) ([]byte, int, error){
resp, err := http.DefaultClient.Do(req)
assert.Nil(t, err)
assert.NotNil(t, resp)
data, err := ioutil.ReadAll(resp.Body)
resp.Body.Close()
assert.Nil(t, err)
return data, resp.StatusCode, err
}
func TestServer_BasicAuth(t *testing.T) {
auth := auth.NewBasicAuth()
auth.AddUser("admin", "admin", "test")
s := New("", "/test", auth)
s.SetDebug(true)
s.SetTemplatePath("test/templates")
s.WithStaticFiles("/static", "test/static" )
s.WithTheme("skin/")
s.HandleFunc("/", handlerRoot)
s.HandleFuncAuthenticated("/login", "", handlerLogin)
s.HandleFuncAuthenticated("/test", "", handlerTest)
s.Dump()
ts := httptest.NewServer(s.router)
defer ts.Close()
// Simple Get:/
req, err := http.NewRequest(http.MethodGet, ts.URL, nil)
assert.Nil(t, err)
data, code, err := doTestRequest(t, req)
assert.Nil(t, err)
assert.Equal(t, http.StatusOK, code)
assert.Equal(t, rootExpected, data)
// Check GOOD password
req, err = http.NewRequest(http.MethodGet, ts.URL +"/login", nil)
assert.Nil(t, err)
req.SetBasicAuth("admin","test")
data, code, err = doTestRequest(t, req)
assert.Nil(t, err)
assert.Equal(t, http.StatusOK, code)
assert.Equal(t, rootExpected, data)
// Check BAD password
req, err = http.NewRequest(http.MethodGet, ts.URL +"/login", nil)
assert.Nil(t, err)
req.SetBasicAuth("admin","badpass")
data, code, err = doTestRequest(t, req)
assert.Nil(t, err)
assert.Equal(t, http.StatusForbidden, code)
// Check GOOD password and context in templates
req, err = http.NewRequest(http.MethodGet, ts.URL +"/test", nil)
assert.Nil(t, err)
req.SetBasicAuth("admin","test")
data, code, err = doTestRequest(t, req)
assert.Nil(t, err)
assert.Equal(t, http.StatusOK, code)
assert.Equal(t, testExpected, data)
// Test Static Content
// Check GOOD password and context in templates
req, err = http.NewRequest(http.MethodGet, ts.URL +"/static/skin/skin.html", nil)
assert.Nil(t, err)
data, code, err = doTestRequest(t, req)
assert.Nil(t, err)
assert.Equal(t, http.StatusOK, code)
assert.Equal(t, []byte(`skin-file`), data)
}
func TestServer_TokenAuth(t *testing.T) {
auth := auth.NewTokenAuth()
auth.AddUser("admin", "admin", "1234567890")
s := New("", "/test", auth)
s.SetDebug(true)
s.SetTemplatePath("test/templates")
s.WithStaticFiles("/static", "test/static")
s.WithTheme("skin/")
s.HandleFunc("/", handlerRoot)
s.HandleFuncAuthenticated("/login", "", handlerLogin)
s.HandleFuncAuthenticated("/test", "", handlerTest)
s.Dump()
ts := httptest.NewServer(s.router)
defer ts.Close()
// Check GOOD password
req, err := http.NewRequest(http.MethodGet, ts.URL+"/login", nil)
assert.Nil(t, err)
req.Header.Add("token", "1234567890")
data, code, err := doTestRequest(t, req)
assert.Nil(t, err)
assert.Equal(t, http.StatusOK, code)
assert.Equal(t, rootExpected, data)
}