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
|
Static func() http.Handler
|
||||||
Recover func(next http.Handler) http.Handler
|
Recover func(next http.Handler) http.Handler
|
||||||
|
|
||||||
|
PathPatterns []PathPattern
|
||||||
|
APIPathPatterns []PathPattern
|
||||||
|
|
||||||
|
RolePermissions map[string]map[string][]int
|
||||||
|
|
||||||
CookieStore *sessions.CookieStore
|
CookieStore *sessions.CookieStore
|
||||||
|
|
||||||
JWTSigningKey []byte
|
JWTSigningKey []byte
|
||||||
|
@ -89,27 +94,9 @@ func pluralizedModelName(s interface{}) string {
|
||||||
|
|
||||||
// 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{}) {
|
||||||
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
|
// Install standard paths
|
||||||
|
|
||||||
for _, pattern := range patterns {
|
for _, pattern := range DefaultPathPatterns {
|
||||||
r.Handle(
|
r.Handle(
|
||||||
pattern.Path(
|
pattern.Path(
|
||||||
pluralizedModelName(model),
|
pluralizedModelName(model),
|
||||||
|
@ -124,7 +111,7 @@ func (h *Handlers) generateModelHandlers(r *mux.Router, model interface{}) {
|
||||||
|
|
||||||
// Install API paths
|
// Install API paths
|
||||||
|
|
||||||
for _, pattern := range apiPatterns {
|
for _, pattern := range h.APIPathPatterns {
|
||||||
r.Handle(pattern.Path(
|
r.Handle(pattern.Path(
|
||||||
pluralizedModelName(model),
|
pluralizedModelName(model),
|
||||||
),
|
),
|
||||||
|
@ -138,11 +125,11 @@ func (h *Handlers) generateModelHandlers(r *mux.Router, model interface{}) {
|
||||||
|
|
||||||
// Set permissions for HTML patterns
|
// Set permissions for HTML patterns
|
||||||
|
|
||||||
for role, modelPermissions := range RolePermissions {
|
for role, modelPermissions := range h.RolePermissions {
|
||||||
for m, perm := range modelPermissions {
|
for m, perm := range modelPermissions {
|
||||||
if m == modelName(model) {
|
if m == modelName(model) {
|
||||||
for _, p := range perm {
|
for _, p := range perm {
|
||||||
for _, pattern := range patterns {
|
for _, pattern := range h.PathPatterns {
|
||||||
if pattern.Permission == p {
|
if pattern.Permission == p {
|
||||||
if permissions[role] == nil {
|
if permissions[role] == nil {
|
||||||
permissions[role] = make(map[string]bool)
|
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 pattern.Permission == p {
|
||||||
if permissions[role] == nil {
|
if permissions[role] == nil {
|
||||||
permissions[role] = make(map[string]bool)
|
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 := new(Handlers)
|
||||||
|
|
||||||
handlers.Config = config
|
handlers.Config = config
|
||||||
|
@ -183,6 +178,11 @@ func NewHandlers(config *config.ConfigT, renderer map[string]renderer.Renderer,
|
||||||
handlers.Home = DefaultHomeHandler
|
handlers.Home = DefaultHomeHandler
|
||||||
handlers.GetToken = DefaultGetTokenHandler
|
handlers.GetToken = DefaultGetTokenHandler
|
||||||
|
|
||||||
|
handlers.RolePermissions = permissions
|
||||||
|
|
||||||
|
handlers.PathPatterns = pathPatterns
|
||||||
|
handlers.APIPathPatterns = apiPathPatterns
|
||||||
|
|
||||||
handlers.JWTCookieMiddleware = jwtmiddleware.New(jwtmiddleware.Options{
|
handlers.JWTCookieMiddleware = jwtmiddleware.New(jwtmiddleware.Options{
|
||||||
ValidationKeyGetter: func(token *jwt.Token) (interface{}, error) {
|
ValidationKeyGetter: func(token *jwt.Token) (interface{}, error) {
|
||||||
return []byte(config.Keys.JWTSigningKey), nil
|
return []byte(config.Keys.JWTSigningKey), nil
|
||||||
|
@ -233,6 +233,12 @@ func NewHandlers(config *config.ConfigT, renderer map[string]renderer.Renderer,
|
||||||
return handlers
|
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) {
|
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)
|
http.Redirect(w, r, "/login?tpl_layout=login&tpl_content=login", http.StatusTemporaryRedirect)
|
||||||
}
|
}
|
||||||
|
|
|
@ -110,7 +110,7 @@ func (t *testSuite) BeforeAll() {
|
||||||
|
|
||||||
// Initialize the renderers
|
// Initialize the renderers
|
||||||
|
|
||||||
htmlRenderer, err := renderer.NewHTMLRenderer("./testdata/templates/")
|
htmlRenderer, err := renderer.NewHTMLRenderer("../templates/")
|
||||||
if err != nil {
|
if err != nil {
|
||||||
panic(err)
|
panic(err)
|
||||||
}
|
}
|
||||||
|
@ -119,12 +119,38 @@ func (t *testSuite) BeforeAll() {
|
||||||
"html": htmlRenderer,
|
"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)
|
token = requestToken(db, handlers)
|
||||||
}
|
}
|
||||||
|
|
||||||
func (t *testSuite) TestReadAllContests() {
|
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 {
|
if err != nil {
|
||||||
panic(err)
|
panic(err)
|
||||||
}
|
}
|
||||||
|
@ -146,7 +172,7 @@ func (t *testSuite) TestReadAllContests() {
|
||||||
t.Equal(http.StatusOK, rr.Code)
|
t.Equal(http.StatusOK, rr.Code)
|
||||||
|
|
||||||
if !t.Failed() {
|
if !t.Failed() {
|
||||||
doc, err := goquery.NewDocumentFromResponse(rr)
|
doc, err := goquery.NewDocumentFromResponse(rr.Result())
|
||||||
if err != nil {
|
if err != nil {
|
||||||
log.Fatal(err)
|
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,
|
"html": htmlRenderer,
|
||||||
"json": jsonRenderer,
|
"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)
|
panic(err)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
Loading…
Reference in a new issue