Fix tests

This commit is contained in:
Andrea Fazzi 2020-01-17 11:06:28 +01:00
parent 06f96f1ccc
commit d85f66d256
4 changed files with 60 additions and 65 deletions

View file

@ -3,17 +3,19 @@ package config
import (
"fmt"
"io/ioutil"
yaml "gopkg.in/yaml.v2"
"net/url"
"git.andreafazzi.eu/andrea/oef/reflect"
yaml "gopkg.in/yaml.v2"
)
const (
LOG_LEVEL_OFF = iota
LOG_LEVEL_INFO
LOG_LEVEL_DEBUG
)
const (
CreateLabel = iota
ReadAllLabel
ReadLabel
@ -128,6 +130,20 @@ func (pp PathPattern) Path(model string) string {
return fmt.Sprintf(pp.PathPattern, model)
}
func (c *ConfigT) ReadAllPath(model interface{}) string {
return fmt.Sprintf(c.Handlers.PathPatterns[actions[ReadAllLabel]].PathPattern, reflect.ModelName(model))
func (c *ConfigT) ReadAllPath(model interface{}, format string) string {
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
}

View file

@ -45,16 +45,14 @@ type Handlers struct {
JWTHeaderMiddleware *jwtmiddleware.JWTMiddleware
Router *mux.Router
}
var (
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
func (h *Handlers) generateModelHandlers(r *mux.Router, model interface{}) {
// Install standard paths
@ -86,7 +84,7 @@ func (h *Handlers) generateModelHandlers(r *mux.Router, model interface{}) {
)))).Methods(pattern.Methods...)
}
// Set permissions for HTML patterns
// Set permissions
for role, modelPermissions := range h.Config.Handlers.Permissions {
for m, perm := range modelPermissions {
@ -94,19 +92,19 @@ func (h *Handlers) generateModelHandlers(r *mux.Router, model interface{}) {
for _, p := range perm {
for _, pattern := range h.Config.Handlers.PathPatterns {
if pattern.Permission == p {
if permissions[role] == nil {
permissions[role] = make(map[string]bool)
if h.permissions[role] == nil {
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 {
if pattern.Permission == p {
if permissions[role] == nil {
permissions[role] = make(map[string]bool)
if h.permissions[role] == nil {
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,
})
handlers.permissions = make(map[string]map[string]bool)
r := mux.NewRouter()
// Authentication
@ -183,9 +183,8 @@ func NewHandlers(config *config.ConfigT, renderer map[string]renderer.Renderer,
return handlers
}
func (h *Handlers) NewReadAllRequest(model interface{}) (*http.Request, error) {
request, err := http.NewRequest("GET", h.Config.ReadAllPath(reflect.ModelNameLowerPlural(model)), nil)
return request, err
func (h *Handlers) NewReadAllRequest(model interface{}, format string) (*http.Request, error) {
return http.NewRequest("GET", h.Config.ReadAllPath(model, format), nil)
}
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
}
func hasPermission(role, path string) bool {
if permissions[role] == nil {
func (h *Handlers) hasPermission(role, path string) bool {
if h.permissions[role] == nil {
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) {
@ -260,11 +259,10 @@ func (h *Handlers) get(w http.ResponseWriter, r *http.Request, model string, pat
} else {
claims := r.Context().Value("user").(*jwt.Token).Claims.(jwt.MapClaims)
role := claims["role"].(string)
if !hasPermission(role, pattern.Path(model)) {
if !h.hasPermission(role, pattern.Path(model)) {
h.setFlashMessage(w, r, "notAuthorized")
h.Renderer[format].Render(w, r, h.CookieStore, fmt.Errorf("%s", "Errore di autorizzazione"))
} else {
data, err := getFn(h.Database, mux.Vars(r), w, r)
if err != nil {
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)
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"))
} else {
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)
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"))
} else {
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) {
// Replace "api" prefix
// 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)

View file

@ -3,11 +3,9 @@ package handlers
import (
"context"
"encoding/json"
"fmt"
"log"
"net/http"
"net/http/httptest"
"strings"
"testing"
"time"
@ -31,9 +29,11 @@ type testSuite struct {
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) {
return []byte(signingKey), nil
return []byte(handlers.Config.Keys.JWTSigningKey), nil
})
if err != nil {
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)
if err != nil {
panic(err)
}
req.SetBasicAuth("admin", "admin")
req.SetBasicAuth(username, password)
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 {
Token string
@ -95,7 +95,7 @@ func (t *testSuite) BeforeAll() {
for !connected {
var err error
time.Sleep(5 * time.Second)
time.Sleep(2 * time.Second)
db, err = orm.NewDatabase(conf, orm.Models)
if err != nil {
@ -148,46 +148,27 @@ func (t *testSuite) BeforeAll() {
conf.Handlers.APIPathPatterns = DefaultAPIPathPatterns
handlers = NewHandlers(conf, renderer, db, orm.Models)
token = requestToken(db, handlers)
}
func (t *testSuite) TestReadAllContests() {
req, err := handlers.NewReadAllRequest(&orm.Contest{})
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)
req, err := handlers.NewReadAllRequest(&orm.Contest{}, "html")
t.Nil(err)
if err != nil {
handlers.ReadAll(&Contest{}).ServeHTTP(rr, req)
req, err = login(req, handlers, "admin", "admin")
t.Nil(err)
if !t.Failed() {
rr := httptest.NewRecorder()
handlers.ReadAll(&orm.Contest{}).ServeHTTP(rr, req)
t.Equal(http.StatusOK, rr.Code)
if !t.Failed() {
doc, err := goquery.NewDocumentFromResponse(rr.Result())
doc, err := goquery.NewDocumentFromReader(rr.Body)
if err != nil {
log.Fatal(err)
}
// 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"))
t.Equal(2, doc.Find(".list-group-item").Size())
}
}