Fix tests
This commit is contained in:
parent
06f96f1ccc
commit
d85f66d256
4 changed files with 60 additions and 65 deletions
|
@ -3,17 +3,19 @@ package config
|
||||||
import (
|
import (
|
||||||
"fmt"
|
"fmt"
|
||||||
"io/ioutil"
|
"io/ioutil"
|
||||||
|
"net/url"
|
||||||
yaml "gopkg.in/yaml.v2"
|
|
||||||
|
|
||||||
"git.andreafazzi.eu/andrea/oef/reflect"
|
"git.andreafazzi.eu/andrea/oef/reflect"
|
||||||
|
yaml "gopkg.in/yaml.v2"
|
||||||
)
|
)
|
||||||
|
|
||||||
const (
|
const (
|
||||||
LOG_LEVEL_OFF = iota
|
LOG_LEVEL_OFF = iota
|
||||||
LOG_LEVEL_INFO
|
LOG_LEVEL_INFO
|
||||||
LOG_LEVEL_DEBUG
|
LOG_LEVEL_DEBUG
|
||||||
|
)
|
||||||
|
|
||||||
|
const (
|
||||||
CreateLabel = iota
|
CreateLabel = iota
|
||||||
ReadAllLabel
|
ReadAllLabel
|
||||||
ReadLabel
|
ReadLabel
|
||||||
|
@ -128,6 +130,20 @@ func (pp PathPattern) Path(model string) string {
|
||||||
return fmt.Sprintf(pp.PathPattern, model)
|
return fmt.Sprintf(pp.PathPattern, model)
|
||||||
}
|
}
|
||||||
|
|
||||||
func (c *ConfigT) ReadAllPath(model interface{}) string {
|
func (c *ConfigT) ReadAllPath(model interface{}, format string) string {
|
||||||
return fmt.Sprintf(c.Handlers.PathPatterns[actions[ReadAllLabel]].PathPattern, reflect.ModelName(model))
|
return fmt.Sprintf(c.Handlers.PathPatterns[actions[ReadAllLabel]].PathPattern, reflect.ModelNameLowerPlural(model)) + "?" + c.query(model, format).Encode()
|
||||||
|
}
|
||||||
|
|
||||||
|
func (c *ConfigT) ReadAllPattern() PathPattern {
|
||||||
|
return c.Handlers.PathPatterns[actions[ReadAllLabel]]
|
||||||
|
}
|
||||||
|
|
||||||
|
func (c *ConfigT) query(model interface{}, format string) url.Values {
|
||||||
|
values := make(url.Values)
|
||||||
|
|
||||||
|
values.Add("format", format)
|
||||||
|
values.Add("tpl_content", reflect.ModelNameLowerPlural(model))
|
||||||
|
values.Add("tpl_layout", "base") // FIXME: use config value
|
||||||
|
|
||||||
|
return values
|
||||||
}
|
}
|
||||||
|
|
|
@ -45,16 +45,14 @@ type Handlers struct {
|
||||||
JWTHeaderMiddleware *jwtmiddleware.JWTMiddleware
|
JWTHeaderMiddleware *jwtmiddleware.JWTMiddleware
|
||||||
|
|
||||||
Router *mux.Router
|
Router *mux.Router
|
||||||
}
|
|
||||||
|
|
||||||
var (
|
|
||||||
permissions map[string]map[string]bool
|
permissions map[string]map[string]bool
|
||||||
)
|
|
||||||
|
|
||||||
func init() {
|
|
||||||
permissions = make(map[string]map[string]bool, 0)
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// var (
|
||||||
|
// permissions map[string]map[string]bool
|
||||||
|
// )
|
||||||
|
|
||||||
// Generate CRUD handlers for models
|
// Generate CRUD handlers for models
|
||||||
func (h *Handlers) generateModelHandlers(r *mux.Router, model interface{}) {
|
func (h *Handlers) generateModelHandlers(r *mux.Router, model interface{}) {
|
||||||
// Install standard paths
|
// Install standard paths
|
||||||
|
@ -86,7 +84,7 @@ func (h *Handlers) generateModelHandlers(r *mux.Router, model interface{}) {
|
||||||
)))).Methods(pattern.Methods...)
|
)))).Methods(pattern.Methods...)
|
||||||
}
|
}
|
||||||
|
|
||||||
// Set permissions for HTML patterns
|
// Set permissions
|
||||||
|
|
||||||
for role, modelPermissions := range h.Config.Handlers.Permissions {
|
for role, modelPermissions := range h.Config.Handlers.Permissions {
|
||||||
for m, perm := range modelPermissions {
|
for m, perm := range modelPermissions {
|
||||||
|
@ -94,19 +92,19 @@ func (h *Handlers) generateModelHandlers(r *mux.Router, model interface{}) {
|
||||||
for _, p := range perm {
|
for _, p := range perm {
|
||||||
for _, pattern := range h.Config.Handlers.PathPatterns {
|
for _, pattern := range h.Config.Handlers.PathPatterns {
|
||||||
if pattern.Permission == p {
|
if pattern.Permission == p {
|
||||||
if permissions[role] == nil {
|
if h.permissions[role] == nil {
|
||||||
permissions[role] = make(map[string]bool)
|
h.permissions[role] = make(map[string]bool)
|
||||||
}
|
}
|
||||||
permissions[role][pattern.Path(reflect.ModelNameLowerPlural(model))] = true
|
h.permissions[role][pattern.Path(reflect.ModelNameLowerPlural(model))] = true
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
for _, pattern := range DefaultAPIPathPatterns {
|
for _, pattern := range DefaultAPIPathPatterns {
|
||||||
if pattern.Permission == p {
|
if pattern.Permission == p {
|
||||||
if permissions[role] == nil {
|
if h.permissions[role] == nil {
|
||||||
permissions[role] = make(map[string]bool)
|
h.permissions[role] = make(map[string]bool)
|
||||||
}
|
}
|
||||||
permissions[role][pattern.Path(reflect.ModelNameLowerPlural(model))] = true
|
h.permissions[role][pattern.Path(reflect.ModelNameLowerPlural(model))] = true
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -149,6 +147,8 @@ func NewHandlers(config *config.ConfigT, renderer map[string]renderer.Renderer,
|
||||||
SigningMethod: jwt.SigningMethodHS256,
|
SigningMethod: jwt.SigningMethodHS256,
|
||||||
})
|
})
|
||||||
|
|
||||||
|
handlers.permissions = make(map[string]map[string]bool)
|
||||||
|
|
||||||
r := mux.NewRouter()
|
r := mux.NewRouter()
|
||||||
|
|
||||||
// Authentication
|
// Authentication
|
||||||
|
@ -183,9 +183,8 @@ func NewHandlers(config *config.ConfigT, renderer map[string]renderer.Renderer,
|
||||||
return handlers
|
return handlers
|
||||||
}
|
}
|
||||||
|
|
||||||
func (h *Handlers) NewReadAllRequest(model interface{}) (*http.Request, error) {
|
func (h *Handlers) NewReadAllRequest(model interface{}, format string) (*http.Request, error) {
|
||||||
request, err := http.NewRequest("GET", h.Config.ReadAllPath(reflect.ModelNameLowerPlural(model)), nil)
|
return http.NewRequest("GET", h.Config.ReadAllPath(model, format), nil)
|
||||||
return request, err
|
|
||||||
}
|
}
|
||||||
|
|
||||||
func (h *Handlers) onError(w http.ResponseWriter, r *http.Request, err string) {
|
func (h *Handlers) onError(w http.ResponseWriter, r *http.Request, err string) {
|
||||||
|
@ -243,12 +242,12 @@ func (h *Handlers) setFlashMessage(w http.ResponseWriter, r *http.Request, key s
|
||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
|
|
||||||
func hasPermission(role, path string) bool {
|
func (h *Handlers) hasPermission(role, path string) bool {
|
||||||
if permissions[role] == nil {
|
if h.permissions[role] == nil {
|
||||||
return false
|
return false
|
||||||
}
|
}
|
||||||
|
|
||||||
return permissions[role][path]
|
return h.permissions[role][path]
|
||||||
}
|
}
|
||||||
|
|
||||||
func (h *Handlers) get(w http.ResponseWriter, r *http.Request, model string, pattern config.PathPattern) {
|
func (h *Handlers) get(w http.ResponseWriter, r *http.Request, model string, pattern config.PathPattern) {
|
||||||
|
@ -260,11 +259,10 @@ func (h *Handlers) get(w http.ResponseWriter, r *http.Request, model string, pat
|
||||||
} else {
|
} else {
|
||||||
claims := r.Context().Value("user").(*jwt.Token).Claims.(jwt.MapClaims)
|
claims := r.Context().Value("user").(*jwt.Token).Claims.(jwt.MapClaims)
|
||||||
role := claims["role"].(string)
|
role := claims["role"].(string)
|
||||||
if !hasPermission(role, pattern.Path(model)) {
|
if !h.hasPermission(role, pattern.Path(model)) {
|
||||||
h.setFlashMessage(w, r, "notAuthorized")
|
h.setFlashMessage(w, r, "notAuthorized")
|
||||||
h.Renderer[format].Render(w, r, h.CookieStore, fmt.Errorf("%s", "Errore di autorizzazione"))
|
h.Renderer[format].Render(w, r, h.CookieStore, fmt.Errorf("%s", "Errore di autorizzazione"))
|
||||||
} else {
|
} else {
|
||||||
|
|
||||||
data, err := getFn(h.Database, mux.Vars(r), w, r)
|
data, err := getFn(h.Database, mux.Vars(r), w, r)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
h.Renderer[format].Render(w, r, h.CookieStore, err)
|
h.Renderer[format].Render(w, r, h.CookieStore, err)
|
||||||
|
@ -291,7 +289,7 @@ func (h *Handlers) post(w http.ResponseWriter, r *http.Request, model string, pa
|
||||||
claims := r.Context().Value("user").(*jwt.Token).Claims.(jwt.MapClaims)
|
claims := r.Context().Value("user").(*jwt.Token).Claims.(jwt.MapClaims)
|
||||||
|
|
||||||
role := claims["role"].(string)
|
role := claims["role"].(string)
|
||||||
if !hasPermission(role, pattern.Path(model)) {
|
if !h.hasPermission(role, pattern.Path(model)) {
|
||||||
h.Renderer[respFormat].Render(w, r, h.CookieStore, fmt.Errorf("%s", "Errore di autorizzazione"))
|
h.Renderer[respFormat].Render(w, r, h.CookieStore, fmt.Errorf("%s", "Errore di autorizzazione"))
|
||||||
} else {
|
} else {
|
||||||
data, err = postFn(h.Database, mux.Vars(r), w, r)
|
data, err = postFn(h.Database, mux.Vars(r), w, r)
|
||||||
|
@ -320,7 +318,7 @@ func (h *Handlers) delete(w http.ResponseWriter, r *http.Request, model string,
|
||||||
claims := r.Context().Value("user").(*jwt.Token).Claims.(jwt.MapClaims)
|
claims := r.Context().Value("user").(*jwt.Token).Claims.(jwt.MapClaims)
|
||||||
|
|
||||||
role := claims["role"].(string)
|
role := claims["role"].(string)
|
||||||
if !hasPermission(role, pattern.Path(model)) {
|
if !h.hasPermission(role, pattern.Path(model)) {
|
||||||
h.Renderer[respFormat].Render(w, r, h.CookieStore, fmt.Errorf("%s", "Errore di autorizzazione"))
|
h.Renderer[respFormat].Render(w, r, h.CookieStore, fmt.Errorf("%s", "Errore di autorizzazione"))
|
||||||
} else {
|
} else {
|
||||||
postFn, err := h.Database.GetFunc(pattern.Path(model))
|
postFn, err := h.Database.GetFunc(pattern.Path(model))
|
||||||
|
@ -354,7 +352,7 @@ func (h *Handlers) ReadAll(model interface{}) http.Handler {
|
||||||
fn := func(w http.ResponseWriter, r *http.Request) {
|
fn := func(w http.ResponseWriter, r *http.Request) {
|
||||||
// Replace "api" prefix
|
// Replace "api" prefix
|
||||||
// pattern.PathPattern = strings.Replace(pattern.PathPattern, "/api", "", -1)
|
// pattern.PathPattern = strings.Replace(pattern.PathPattern, "/api", "", -1)
|
||||||
h.get(w, r, model, pattern)
|
h.get(w, r, reflect.ModelNameLowerPlural(model), h.Config.ReadAllPattern())
|
||||||
}
|
}
|
||||||
|
|
||||||
return http.HandlerFunc(fn)
|
return http.HandlerFunc(fn)
|
||||||
|
|
|
@ -3,11 +3,9 @@ package handlers
|
||||||
import (
|
import (
|
||||||
"context"
|
"context"
|
||||||
"encoding/json"
|
"encoding/json"
|
||||||
"fmt"
|
|
||||||
"log"
|
"log"
|
||||||
"net/http"
|
"net/http"
|
||||||
"net/http/httptest"
|
"net/http/httptest"
|
||||||
"strings"
|
|
||||||
"testing"
|
"testing"
|
||||||
"time"
|
"time"
|
||||||
|
|
||||||
|
@ -31,9 +29,11 @@ type testSuite struct {
|
||||||
prettytest.Suite
|
prettytest.Suite
|
||||||
}
|
}
|
||||||
|
|
||||||
func authenticate(request *http.Request, tokenString string, signingKey string) (*http.Request, error) {
|
func login(request *http.Request, handlers *Handlers, username string, password string) (*http.Request, error) {
|
||||||
|
|
||||||
|
tokenString := requestToken(handlers, username, password)
|
||||||
token, err := jwt.Parse(tokenString, func(token *jwt.Token) (interface{}, error) {
|
token, err := jwt.Parse(tokenString, func(token *jwt.Token) (interface{}, error) {
|
||||||
return []byte(signingKey), nil
|
return []byte(handlers.Config.Keys.JWTSigningKey), nil
|
||||||
})
|
})
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return nil, err
|
return nil, err
|
||||||
|
@ -44,17 +44,17 @@ func authenticate(request *http.Request, tokenString string, signingKey string)
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
func requestToken(db *orm.Database, handlers *Handlers) string {
|
func requestToken(handlers *Handlers, username string, password string) string {
|
||||||
req, err := http.NewRequest("GET", "/get_token", nil)
|
req, err := http.NewRequest("GET", "/get_token", nil)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
panic(err)
|
panic(err)
|
||||||
}
|
}
|
||||||
|
|
||||||
req.SetBasicAuth("admin", "admin")
|
req.SetBasicAuth(username, password)
|
||||||
|
|
||||||
rr := httptest.NewRecorder()
|
rr := httptest.NewRecorder()
|
||||||
|
|
||||||
handlers.GetToken(db, []byte(db.Config.Keys.JWTSigningKey)).ServeHTTP(rr, req)
|
handlers.GetToken(handlers.Database, []byte(handlers.Config.Keys.JWTSigningKey)).ServeHTTP(rr, req)
|
||||||
|
|
||||||
var data struct {
|
var data struct {
|
||||||
Token string
|
Token string
|
||||||
|
@ -95,7 +95,7 @@ func (t *testSuite) BeforeAll() {
|
||||||
for !connected {
|
for !connected {
|
||||||
var err error
|
var err error
|
||||||
|
|
||||||
time.Sleep(5 * time.Second)
|
time.Sleep(2 * time.Second)
|
||||||
|
|
||||||
db, err = orm.NewDatabase(conf, orm.Models)
|
db, err = orm.NewDatabase(conf, orm.Models)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
|
@ -148,46 +148,27 @@ func (t *testSuite) BeforeAll() {
|
||||||
conf.Handlers.APIPathPatterns = DefaultAPIPathPatterns
|
conf.Handlers.APIPathPatterns = DefaultAPIPathPatterns
|
||||||
|
|
||||||
handlers = NewHandlers(conf, renderer, db, orm.Models)
|
handlers = NewHandlers(conf, renderer, db, orm.Models)
|
||||||
token = requestToken(db, handlers)
|
|
||||||
}
|
}
|
||||||
|
|
||||||
func (t *testSuite) TestReadAllContests() {
|
func (t *testSuite) TestReadAllContests() {
|
||||||
req, err := handlers.NewReadAllRequest(&orm.Contest{})
|
req, err := handlers.NewReadAllRequest(&orm.Contest{}, "html")
|
||||||
|
|
||||||
if err != nil {
|
|
||||||
panic(err)
|
|
||||||
}
|
|
||||||
|
|
||||||
pattern := config.PathPattern{
|
|
||||||
"/%s",
|
|
||||||
"/%s?format=html&tpl_layout=base&tpl_content=%s",
|
|
||||||
[]string{"GET"}, PermissionReadAll,
|
|
||||||
}
|
|
||||||
|
|
||||||
rr := httptest.NewRecorder()
|
|
||||||
|
|
||||||
req, err = authenticate(req, token, conf.Keys.JWTSigningKey)
|
|
||||||
t.Nil(err)
|
t.Nil(err)
|
||||||
|
|
||||||
if err != nil {
|
req, err = login(req, handlers, "admin", "admin")
|
||||||
handlers.ReadAll(&Contest{}).ServeHTTP(rr, req)
|
t.Nil(err)
|
||||||
|
|
||||||
|
if !t.Failed() {
|
||||||
|
rr := httptest.NewRecorder()
|
||||||
|
|
||||||
|
handlers.ReadAll(&orm.Contest{}).ServeHTTP(rr, req)
|
||||||
t.Equal(http.StatusOK, rr.Code)
|
t.Equal(http.StatusOK, rr.Code)
|
||||||
|
|
||||||
if !t.Failed() {
|
if !t.Failed() {
|
||||||
doc, err := goquery.NewDocumentFromResponse(rr.Result())
|
doc, err := goquery.NewDocumentFromReader(rr.Body)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
log.Fatal(err)
|
log.Fatal(err)
|
||||||
}
|
}
|
||||||
|
t.Equal(2, doc.Find(".list-group-item").Size())
|
||||||
// Find the review items
|
|
||||||
doc.Find(".sidebar-reviews article .content-block").Each(func(i int, s *goquery.Selection) {
|
|
||||||
// For each item found, get the band and title
|
|
||||||
band := s.Find("a").Text()
|
|
||||||
title := s.Find("i").Text()
|
|
||||||
fmt.Printf("Review %d: %s - %s\n", i, band, title)
|
|
||||||
})
|
|
||||||
t.True(strings.Contains(rr.Body.String(), "JUNIOR Contest"))
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -92,7 +92,7 @@ func (c *Contest) ReadAll(db *Database, args map[string]string, w http.ResponseW
|
||||||
var contests []*Contest
|
var contests []*Contest
|
||||||
|
|
||||||
claims := r.Context().Value("user").(*jwt.Token).Claims.(jwt.MapClaims)
|
claims := r.Context().Value("user").(*jwt.Token).Claims.(jwt.MapClaims)
|
||||||
|
|
||||||
if claims["admin"].(bool) {
|
if claims["admin"].(bool) {
|
||||||
if err := db._db.Order("created_at").Find(&contests).Error; err != nil {
|
if err := db._db.Order("created_at").Find(&contests).Error; err != nil {
|
||||||
return nil, err
|
return nil, err
|
||||||
|
|
Loading…
Reference in a new issue