Working on better path patterns
This commit is contained in:
parent
22965dc1f4
commit
8a4afd970e
5 changed files with 122 additions and 65 deletions
|
@ -47,6 +47,11 @@ type Handlers struct {
|
|||
Static func() http.Handler
|
||||
Recover func(next http.Handler) http.Handler
|
||||
|
||||
PathPatterns []PathPattern
|
||||
APIPathPatterns []PathPattern
|
||||
|
||||
RolePermissions map[string]map[string][]int
|
||||
|
||||
CookieStore *sessions.CookieStore
|
||||
|
||||
JWTSigningKey []byte
|
||||
|
@ -89,27 +94,9 @@ func pluralizedModelName(s interface{}) string {
|
|||
|
||||
// Generate CRUD handlers for models
|
||||
func (h *Handlers) generateModelHandlers(r *mux.Router, model interface{}) {
|
||||
var (
|
||||
patterns []PathPattern = []PathPattern{
|
||||
PathPattern{"/%s", "", []string{"GET"}, PermissionReadAll},
|
||||
PathPattern{"/%s/{id}", "", []string{"GET"}, PermissionRead},
|
||||
PathPattern{"/%s/create/", "/%s/%d?format=html&tpl_layout=base&tpl_content=%s_show", []string{"GET", "POST"}, PermissionCreate},
|
||||
PathPattern{"/%s/{id}/update", "/%s/%d?format=html&tpl_layout=base&tpl_content=%s_show", []string{"GET", "POST"}, PermissionUpdate},
|
||||
PathPattern{"/%s/{id}/delete", "/%s?format=html&tpl_layout=base&tpl_content=%s", []string{"DELETE"}, PermissionDelete},
|
||||
}
|
||||
|
||||
apiPatterns []PathPattern
|
||||
)
|
||||
|
||||
// Generate API patterns prefixing "api" path
|
||||
|
||||
for _, p := range patterns {
|
||||
apiPatterns = append(apiPatterns, PathPattern{"/api" + p.PathPattern, "", p.Methods, p.Permission})
|
||||
}
|
||||
|
||||
// Install standard paths
|
||||
|
||||
for _, pattern := range patterns {
|
||||
for _, pattern := range DefaultPathPatterns {
|
||||
r.Handle(
|
||||
pattern.Path(
|
||||
pluralizedModelName(model),
|
||||
|
@ -124,7 +111,7 @@ func (h *Handlers) generateModelHandlers(r *mux.Router, model interface{}) {
|
|||
|
||||
// Install API paths
|
||||
|
||||
for _, pattern := range apiPatterns {
|
||||
for _, pattern := range h.APIPathPatterns {
|
||||
r.Handle(pattern.Path(
|
||||
pluralizedModelName(model),
|
||||
),
|
||||
|
@ -138,11 +125,11 @@ func (h *Handlers) generateModelHandlers(r *mux.Router, model interface{}) {
|
|||
|
||||
// Set permissions for HTML patterns
|
||||
|
||||
for role, modelPermissions := range RolePermissions {
|
||||
for role, modelPermissions := range h.RolePermissions {
|
||||
for m, perm := range modelPermissions {
|
||||
if m == modelName(model) {
|
||||
for _, p := range perm {
|
||||
for _, pattern := range patterns {
|
||||
for _, pattern := range h.PathPatterns {
|
||||
if pattern.Permission == p {
|
||||
if permissions[role] == nil {
|
||||
permissions[role] = make(map[string]bool)
|
||||
|
@ -151,7 +138,7 @@ func (h *Handlers) generateModelHandlers(r *mux.Router, model interface{}) {
|
|||
}
|
||||
}
|
||||
|
||||
for _, pattern := range apiPatterns {
|
||||
for _, pattern := range DefaultAPIPathPatterns {
|
||||
if pattern.Permission == p {
|
||||
if permissions[role] == nil {
|
||||
permissions[role] = make(map[string]bool)
|
||||
|
@ -167,7 +154,15 @@ func (h *Handlers) generateModelHandlers(r *mux.Router, model interface{}) {
|
|||
|
||||
}
|
||||
|
||||
func NewHandlers(config *config.ConfigT, renderer map[string]renderer.Renderer, db *orm.Database, models []interface{}) *Handlers {
|
||||
func NewHandlers(
|
||||
config *config.ConfigT,
|
||||
renderer map[string]renderer.Renderer,
|
||||
db *orm.Database,
|
||||
models []interface{},
|
||||
permissions map[string]map[string][]int,
|
||||
pathPatterns []PathPattern,
|
||||
apiPathPatterns []PathPattern,
|
||||
) *Handlers {
|
||||
handlers := new(Handlers)
|
||||
|
||||
handlers.Config = config
|
||||
|
@ -183,6 +178,11 @@ func NewHandlers(config *config.ConfigT, renderer map[string]renderer.Renderer,
|
|||
handlers.Home = DefaultHomeHandler
|
||||
handlers.GetToken = DefaultGetTokenHandler
|
||||
|
||||
handlers.RolePermissions = permissions
|
||||
|
||||
handlers.PathPatterns = pathPatterns
|
||||
handlers.APIPathPatterns = apiPathPatterns
|
||||
|
||||
handlers.JWTCookieMiddleware = jwtmiddleware.New(jwtmiddleware.Options{
|
||||
ValidationKeyGetter: func(token *jwt.Token) (interface{}, error) {
|
||||
return []byte(config.Keys.JWTSigningKey), nil
|
||||
|
@ -233,6 +233,12 @@ func NewHandlers(config *config.ConfigT, renderer map[string]renderer.Renderer,
|
|||
return handlers
|
||||
}
|
||||
|
||||
func (h *Handlers) NewReadAllRequest(model interface{}) (*http.Request, error) {
|
||||
name := inflection.Plural(orm.ModelName(model))
|
||||
request, err := http.NewRequest("GET", "/contests?format=html&tpl_layout=base&tpl_content=contests", nil)
|
||||
return request, err
|
||||
}
|
||||
|
||||
func (h *Handlers) onError(w http.ResponseWriter, r *http.Request, err string) {
|
||||
http.Redirect(w, r, "/login?tpl_layout=login&tpl_content=login", http.StatusTemporaryRedirect)
|
||||
}
|
||||
|
|
|
@ -110,7 +110,7 @@ func (t *testSuite) BeforeAll() {
|
|||
|
||||
// Initialize the renderers
|
||||
|
||||
htmlRenderer, err := renderer.NewHTMLRenderer("./testdata/templates/")
|
||||
htmlRenderer, err := renderer.NewHTMLRenderer("../templates/")
|
||||
if err != nil {
|
||||
panic(err)
|
||||
}
|
||||
|
@ -119,12 +119,38 @@ func (t *testSuite) BeforeAll() {
|
|||
"html": htmlRenderer,
|
||||
}
|
||||
|
||||
handlers = NewHandlers(conf, renderer, db, orm.Models)
|
||||
permissions := map[string]map[string][]int{
|
||||
"administrator": map[string][]int{
|
||||
"Contest": []int{PermissionCreate, PermissionRead, PermissionReadAll, PermissionUpdate, PermissionDelete},
|
||||
"Participant": []int{PermissionCreate, PermissionRead, PermissionReadAll, PermissionUpdate, PermissionDelete},
|
||||
"School": []int{PermissionCreate, PermissionRead, PermissionReadAll, PermissionUpdate, PermissionDelete},
|
||||
"Question": []int{PermissionCreate, PermissionRead, PermissionReadAll, PermissionUpdate, PermissionDelete},
|
||||
"Answer": []int{PermissionCreate, PermissionRead, PermissionReadAll, PermissionUpdate, PermissionDelete},
|
||||
"Response": []int{PermissionCreate, PermissionRead, PermissionReadAll, PermissionUpdate, PermissionDelete},
|
||||
},
|
||||
|
||||
"school": map[string][]int{
|
||||
"Participant": []int{PermissionCreate, PermissionRead, PermissionReadAll, PermissionUpdate, PermissionDelete},
|
||||
"School": []int{PermissionRead, PermissionUpdate},
|
||||
},
|
||||
|
||||
"participant": map[string][]int{
|
||||
"Participant": []int{PermissionRead},
|
||||
"Response": []int{PermissionUpdate, PermissionRead},
|
||||
},
|
||||
|
||||
"subscriber": map[string][]int{
|
||||
"School": []int{PermissionCreate, PermissionRead},
|
||||
},
|
||||
}
|
||||
|
||||
handlers = NewHandlers(conf, renderer, db, orm.Models, permissions)
|
||||
token = requestToken(db, handlers)
|
||||
}
|
||||
|
||||
func (t *testSuite) TestReadAllContests() {
|
||||
req, err := http.NewRequest("GET", "/contests?format=html&tpl_layout=base&tpl_content=contests", nil)
|
||||
req, err := RequestReadAll(&Contest{})
|
||||
// req, err := http.NewRequest("GET", "/contests?format=html&tpl_layout=base&tpl_content=contests", nil)
|
||||
if err != nil {
|
||||
panic(err)
|
||||
}
|
||||
|
@ -146,7 +172,7 @@ func (t *testSuite) TestReadAllContests() {
|
|||
t.Equal(http.StatusOK, rr.Code)
|
||||
|
||||
if !t.Failed() {
|
||||
doc, err := goquery.NewDocumentFromResponse(rr)
|
||||
doc, err := goquery.NewDocumentFromResponse(rr.Result())
|
||||
if err != nil {
|
||||
log.Fatal(err)
|
||||
}
|
||||
|
|
27
handlers/paths.go
Normal file
27
handlers/paths.go
Normal file
|
@ -0,0 +1,27 @@
|
|||
package handlers
|
||||
|
||||
const (
|
||||
PermissionCreate = iota
|
||||
PermissionRead
|
||||
PermissionReadAll
|
||||
PermissionUpdate
|
||||
PermissionDelete
|
||||
)
|
||||
|
||||
var (
|
||||
DefaultPathPatterns []PathPattern = []PathPattern{
|
||||
PathPattern{"/%s", "", []string{"GET"}, PermissionReadAll},
|
||||
PathPattern{"/%s/{id}", "", []string{"GET"}, PermissionRead},
|
||||
PathPattern{"/%s/create/", "/%s/%d?format=html&tpl_layout=base&tpl_content=%s_show", []string{"GET", "POST"}, PermissionCreate},
|
||||
PathPattern{"/%s/{id}/update", "/%s/%d?format=html&tpl_layout=base&tpl_content=%s_show", []string{"GET", "POST"}, PermissionUpdate},
|
||||
PathPattern{"/%s/{id}/delete", "/%s?format=html&tpl_layout=base&tpl_content=%s", []string{"DELETE"}, PermissionDelete},
|
||||
}
|
||||
|
||||
DefaultAPIPathPatterns []PathPattern = []PathPattern{
|
||||
PathPattern{"/api/%s", "", []string{"GET"}, PermissionReadAll},
|
||||
PathPattern{"/api/%s/{id}", "", []string{"GET"}, PermissionRead},
|
||||
PathPattern{"/api/%s/create/", "", []string{"GET", "POST"}, PermissionCreate},
|
||||
PathPattern{"/api/%s/{id}/update", "", []string{"GET", "POST"}, PermissionUpdate},
|
||||
PathPattern{"/api/%s/{id}/delete", "", []string{"DELETE"}, PermissionDelete},
|
||||
}
|
||||
)
|
|
@ -1,36 +0,0 @@
|
|||
package handlers
|
||||
|
||||
const (
|
||||
PermissionCreate = iota
|
||||
PermissionRead
|
||||
PermissionReadAll
|
||||
PermissionUpdate
|
||||
PermissionDelete
|
||||
)
|
||||
|
||||
var (
|
||||
RolePermissions map[string]map[string][]int = map[string]map[string][]int{
|
||||
"administrator": map[string][]int{
|
||||
"Contest": []int{PermissionCreate, PermissionRead, PermissionReadAll, PermissionUpdate, PermissionDelete},
|
||||
"Participant": []int{PermissionCreate, PermissionRead, PermissionReadAll, PermissionUpdate, PermissionDelete},
|
||||
"School": []int{PermissionCreate, PermissionRead, PermissionReadAll, PermissionUpdate, PermissionDelete},
|
||||
"Question": []int{PermissionCreate, PermissionRead, PermissionReadAll, PermissionUpdate, PermissionDelete},
|
||||
"Answer": []int{PermissionCreate, PermissionRead, PermissionReadAll, PermissionUpdate, PermissionDelete},
|
||||
"Response": []int{PermissionCreate, PermissionRead, PermissionReadAll, PermissionUpdate, PermissionDelete},
|
||||
},
|
||||
|
||||
"school": map[string][]int{
|
||||
"Participant": []int{PermissionCreate, PermissionRead, PermissionReadAll, PermissionUpdate, PermissionDelete},
|
||||
"School": []int{PermissionRead, PermissionUpdate},
|
||||
},
|
||||
|
||||
"participant": map[string][]int{
|
||||
"Participant": []int{PermissionRead},
|
||||
"Response": []int{PermissionUpdate, PermissionRead},
|
||||
},
|
||||
|
||||
"subscriber": map[string][]int{
|
||||
"School": []int{PermissionCreate, PermissionRead},
|
||||
},
|
||||
}
|
||||
)
|
36
main.go
36
main.go
|
@ -81,7 +81,41 @@ func main() {
|
|||
"html": htmlRenderer,
|
||||
"json": jsonRenderer,
|
||||
}
|
||||
if err := http.ListenAndServe(":3000", handlers.LoggingHandler(os.Stdout, oef_handlers.NewHandlers(conf, renderer, db, orm.Models).Router)); err != nil {
|
||||
|
||||
permissions := map[string]map[string][]int{
|
||||
"administrator": map[string][]int{
|
||||
"Contest": []int{oef_handlers.PermissionCreate, oef_handlers.PermissionRead, oef_handlers.PermissionReadAll, oef_handlers.PermissionUpdate, oef_handlers.PermissionDelete},
|
||||
"Participant": []int{oef_handlers.PermissionCreate, oef_handlers.PermissionRead, oef_handlers.PermissionReadAll, oef_handlers.PermissionUpdate, oef_handlers.PermissionDelete},
|
||||
"School": []int{oef_handlers.PermissionCreate, oef_handlers.PermissionRead, oef_handlers.PermissionReadAll, oef_handlers.PermissionUpdate, oef_handlers.PermissionDelete},
|
||||
"Question": []int{oef_handlers.PermissionCreate, oef_handlers.PermissionRead, oef_handlers.PermissionReadAll, oef_handlers.PermissionUpdate, oef_handlers.PermissionDelete},
|
||||
"Answer": []int{oef_handlers.PermissionCreate, oef_handlers.PermissionRead, oef_handlers.PermissionReadAll, oef_handlers.PermissionUpdate, oef_handlers.PermissionDelete},
|
||||
"Response": []int{oef_handlers.PermissionCreate, oef_handlers.PermissionRead, oef_handlers.PermissionReadAll, oef_handlers.PermissionUpdate, oef_handlers.PermissionDelete},
|
||||
},
|
||||
|
||||
"school": map[string][]int{
|
||||
"Participant": []int{oef_handlers.PermissionCreate, oef_handlers.PermissionRead, oef_handlers.PermissionReadAll, oef_handlers.PermissionUpdate, oef_handlers.PermissionDelete},
|
||||
"School": []int{oef_handlers.PermissionRead, oef_handlers.PermissionUpdate},
|
||||
},
|
||||
|
||||
"participant": map[string][]int{
|
||||
"Participant": []int{oef_handlers.PermissionRead},
|
||||
"Response": []int{oef_handlers.PermissionUpdate, oef_handlers.PermissionRead},
|
||||
},
|
||||
|
||||
"subscriber": map[string][]int{
|
||||
"School": []int{oef_handlers.PermissionCreate, oef_handlers.PermissionRead},
|
||||
},
|
||||
}
|
||||
|
||||
if err := http.ListenAndServe(":3000", handlers.LoggingHandler(os.Stdout, oef_handlers.NewHandlers(
|
||||
conf,
|
||||
renderer,
|
||||
db,
|
||||
orm.Models,
|
||||
permissions,
|
||||
handlers.DefaultPathPatterns,
|
||||
handlers.DefaultAPIPathPatterns,
|
||||
).Router)); err != nil {
|
||||
panic(err)
|
||||
}
|
||||
|
||||
|
|
Loading…
Reference in a new issue