2019-11-04 15:00:46 +01:00
|
|
|
package handlers
|
|
|
|
|
|
|
|
import (
|
|
|
|
"encoding/json"
|
|
|
|
"fmt"
|
|
|
|
"io/ioutil"
|
|
|
|
"log"
|
|
|
|
"net/http"
|
2020-01-20 12:07:02 +01:00
|
|
|
"net/url"
|
2019-11-04 15:00:46 +01:00
|
|
|
"path/filepath"
|
|
|
|
"runtime/debug"
|
|
|
|
"strconv"
|
|
|
|
"strings"
|
|
|
|
|
2019-12-04 10:11:18 +01:00
|
|
|
"git.andreafazzi.eu/andrea/oef/config"
|
|
|
|
"git.andreafazzi.eu/andrea/oef/i18n"
|
2019-11-04 15:00:46 +01:00
|
|
|
"git.andreafazzi.eu/andrea/oef/orm"
|
2020-01-17 07:59:57 +01:00
|
|
|
"git.andreafazzi.eu/andrea/oef/reflect"
|
2019-11-04 15:00:46 +01:00
|
|
|
"git.andreafazzi.eu/andrea/oef/renderer"
|
|
|
|
|
2020-01-14 16:28:27 +01:00
|
|
|
jwtmiddleware "github.com/auth0/go-jwt-middleware"
|
2019-11-04 15:00:46 +01:00
|
|
|
jwt "github.com/dgrijalva/jwt-go"
|
|
|
|
"github.com/gorilla/mux"
|
2020-01-14 16:28:27 +01:00
|
|
|
"github.com/gorilla/sessions"
|
2019-11-04 15:00:46 +01:00
|
|
|
)
|
|
|
|
|
2020-01-14 09:43:27 +01:00
|
|
|
type Handlers struct {
|
2020-01-14 16:28:27 +01:00
|
|
|
Config *config.ConfigT
|
|
|
|
|
2020-01-15 11:27:00 +01:00
|
|
|
Database *orm.Database
|
|
|
|
Models []interface{}
|
2020-01-14 09:43:27 +01:00
|
|
|
|
2020-01-15 13:40:35 +01:00
|
|
|
Renderer map[string]renderer.Renderer
|
|
|
|
|
2020-01-15 11:27:00 +01:00
|
|
|
Login func(db *orm.Database, store *sessions.CookieStore, signingKey []byte) http.Handler
|
2020-01-14 16:28:27 +01:00
|
|
|
Logout func(store *sessions.CookieStore) http.Handler
|
2020-01-14 09:43:27 +01:00
|
|
|
Home func() http.Handler
|
2020-01-15 11:27:00 +01:00
|
|
|
GetToken func(db *orm.Database, signingKey []byte) http.Handler
|
2020-01-14 09:43:27 +01:00
|
|
|
Static func() http.Handler
|
|
|
|
Recover func(next http.Handler) http.Handler
|
|
|
|
|
2020-01-14 16:28:27 +01:00
|
|
|
CookieStore *sessions.CookieStore
|
|
|
|
|
|
|
|
JWTSigningKey []byte
|
|
|
|
JWTCookieMiddleware *jwtmiddleware.JWTMiddleware
|
|
|
|
JWTHeaderMiddleware *jwtmiddleware.JWTMiddleware
|
|
|
|
|
2020-01-14 09:43:27 +01:00
|
|
|
Router *mux.Router
|
|
|
|
|
2019-12-04 12:20:34 +01:00
|
|
|
permissions map[string]map[string]bool
|
2019-11-04 15:00:46 +01:00
|
|
|
}
|
|
|
|
|
|
|
|
// Generate CRUD handlers for models
|
2020-01-14 09:43:27 +01:00
|
|
|
func (h *Handlers) generateModelHandlers(r *mux.Router, model interface{}) {
|
2019-11-04 15:00:46 +01:00
|
|
|
// Install standard paths
|
|
|
|
|
2020-01-16 12:47:35 +01:00
|
|
|
for _, pattern := range DefaultPathPatterns {
|
2019-11-22 11:16:27 +01:00
|
|
|
r.Handle(
|
|
|
|
pattern.Path(
|
2020-01-17 07:59:57 +01:00
|
|
|
reflect.ModelNameLowerPlural(model),
|
2019-11-22 11:16:27 +01:00
|
|
|
),
|
2020-01-14 16:28:27 +01:00
|
|
|
h.JWTCookieMiddleware.Handler(
|
2020-01-14 09:43:27 +01:00
|
|
|
h.Recover(
|
|
|
|
h.modelHandler(
|
2020-01-17 07:59:57 +01:00
|
|
|
reflect.ModelNameLowerPlural(model),
|
2019-11-22 11:16:27 +01:00
|
|
|
pattern,
|
|
|
|
)))).Methods(pattern.Methods...)
|
2019-11-04 15:00:46 +01:00
|
|
|
}
|
|
|
|
|
|
|
|
// Install API paths
|
|
|
|
|
2020-01-17 07:59:57 +01:00
|
|
|
for _, pattern := range h.Config.Handlers.APIPathPatterns {
|
2019-11-22 11:16:27 +01:00
|
|
|
r.Handle(pattern.Path(
|
2020-01-17 07:59:57 +01:00
|
|
|
reflect.ModelNameLowerPlural(model),
|
2019-11-22 11:16:27 +01:00
|
|
|
),
|
2020-01-14 16:28:27 +01:00
|
|
|
h.JWTHeaderMiddleware.Handler(
|
2020-01-14 09:43:27 +01:00
|
|
|
h.Recover(
|
|
|
|
h.modelHandler(
|
2020-01-17 07:59:57 +01:00
|
|
|
reflect.ModelNameLowerPlural(model),
|
2019-11-22 11:16:27 +01:00
|
|
|
pattern,
|
|
|
|
)))).Methods(pattern.Methods...)
|
2019-11-04 15:00:46 +01:00
|
|
|
}
|
|
|
|
|
2020-01-17 11:06:28 +01:00
|
|
|
// Set permissions
|
2019-12-04 12:20:34 +01:00
|
|
|
|
2020-01-17 07:59:57 +01:00
|
|
|
for role, modelPermissions := range h.Config.Handlers.Permissions {
|
2019-12-04 12:20:34 +01:00
|
|
|
for m, perm := range modelPermissions {
|
2020-01-17 07:59:57 +01:00
|
|
|
if m == reflect.ModelName(model) {
|
2019-12-04 12:20:34 +01:00
|
|
|
for _, p := range perm {
|
2020-01-17 07:59:57 +01:00
|
|
|
for _, pattern := range h.Config.Handlers.PathPatterns {
|
2019-12-04 12:20:34 +01:00
|
|
|
if pattern.Permission == p {
|
2020-01-17 11:06:28 +01:00
|
|
|
if h.permissions[role] == nil {
|
|
|
|
h.permissions[role] = make(map[string]bool)
|
2019-12-04 12:20:34 +01:00
|
|
|
}
|
2020-01-17 11:06:28 +01:00
|
|
|
h.permissions[role][pattern.Path(reflect.ModelNameLowerPlural(model))] = true
|
2019-12-04 12:20:34 +01:00
|
|
|
}
|
|
|
|
}
|
2020-01-02 09:48:20 +01:00
|
|
|
|
2020-01-16 12:47:35 +01:00
|
|
|
for _, pattern := range DefaultAPIPathPatterns {
|
2020-01-02 09:48:20 +01:00
|
|
|
if pattern.Permission == p {
|
2020-01-17 11:06:28 +01:00
|
|
|
if h.permissions[role] == nil {
|
|
|
|
h.permissions[role] = make(map[string]bool)
|
2020-01-02 09:48:20 +01:00
|
|
|
}
|
2020-01-17 11:06:28 +01:00
|
|
|
h.permissions[role][pattern.Path(reflect.ModelNameLowerPlural(model))] = true
|
2020-01-02 09:48:20 +01:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2019-12-04 12:20:34 +01:00
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2019-11-04 15:00:46 +01:00
|
|
|
}
|
|
|
|
|
2020-01-17 07:59:57 +01:00
|
|
|
func NewHandlers(config *config.ConfigT, renderer map[string]renderer.Renderer, db *orm.Database, models []interface{}) *Handlers {
|
2020-01-14 09:43:27 +01:00
|
|
|
handlers := new(Handlers)
|
|
|
|
|
2020-01-14 16:28:27 +01:00
|
|
|
handlers.Config = config
|
2020-01-15 13:40:35 +01:00
|
|
|
|
|
|
|
handlers.Renderer = renderer
|
2020-01-15 11:27:00 +01:00
|
|
|
handlers.Database = db
|
2020-01-14 16:28:27 +01:00
|
|
|
|
|
|
|
handlers.CookieStore = sessions.NewCookieStore([]byte(config.Keys.CookieStoreKey))
|
|
|
|
|
2020-01-15 13:40:35 +01:00
|
|
|
handlers.Login = handlers.DefaultLoginHandler
|
2020-01-14 09:43:27 +01:00
|
|
|
handlers.Logout = DefaultLogoutHandler
|
|
|
|
handlers.Recover = DefaultRecoverHandler
|
|
|
|
handlers.Home = DefaultHomeHandler
|
|
|
|
handlers.GetToken = DefaultGetTokenHandler
|
|
|
|
|
2020-01-14 16:28:27 +01:00
|
|
|
handlers.JWTCookieMiddleware = jwtmiddleware.New(jwtmiddleware.Options{
|
|
|
|
ValidationKeyGetter: func(token *jwt.Token) (interface{}, error) {
|
|
|
|
return []byte(config.Keys.JWTSigningKey), nil
|
|
|
|
},
|
|
|
|
SigningMethod: jwt.SigningMethodHS256,
|
|
|
|
Extractor: handlers.cookieExtractor,
|
|
|
|
ErrorHandler: handlers.onError,
|
|
|
|
})
|
|
|
|
|
|
|
|
handlers.JWTHeaderMiddleware = jwtmiddleware.New(jwtmiddleware.Options{
|
|
|
|
ValidationKeyGetter: func(token *jwt.Token) (interface{}, error) {
|
2020-01-20 12:07:02 +01:00
|
|
|
return []byte(config.Keys.JWTSigningKey), nil
|
2020-01-14 16:28:27 +01:00
|
|
|
},
|
|
|
|
SigningMethod: jwt.SigningMethodHS256,
|
|
|
|
})
|
|
|
|
|
2020-01-17 11:06:28 +01:00
|
|
|
handlers.permissions = make(map[string]map[string]bool)
|
|
|
|
|
2019-11-04 15:00:46 +01:00
|
|
|
r := mux.NewRouter()
|
|
|
|
|
|
|
|
// Authentication
|
|
|
|
|
2020-01-15 11:27:00 +01:00
|
|
|
r.Handle("/login", handlers.Login(handlers.Database, handlers.CookieStore, []byte(config.Keys.JWTSigningKey)))
|
2020-01-14 16:28:27 +01:00
|
|
|
r.Handle("/logout", handlers.Logout(handlers.CookieStore))
|
2019-11-04 15:00:46 +01:00
|
|
|
|
2019-12-03 15:24:01 +01:00
|
|
|
// School subscription
|
|
|
|
|
2020-01-15 11:27:00 +01:00
|
|
|
r.Handle("/subscribe", handlers.Login(handlers.Database, handlers.CookieStore, []byte(config.Keys.JWTSigningKey)))
|
2019-12-03 15:24:01 +01:00
|
|
|
|
2020-01-14 09:43:27 +01:00
|
|
|
// Home
|
2019-11-04 15:00:46 +01:00
|
|
|
|
2020-01-14 16:28:27 +01:00
|
|
|
r.Handle("/", handlers.JWTCookieMiddleware.Handler(handlers.Recover(handlers.Home())))
|
2019-11-04 15:00:46 +01:00
|
|
|
|
|
|
|
// Generate CRUD handlers
|
|
|
|
|
|
|
|
for _, model := range models {
|
2020-01-14 09:43:27 +01:00
|
|
|
handlers.generateModelHandlers(r, model)
|
2019-11-04 15:00:46 +01:00
|
|
|
}
|
|
|
|
|
|
|
|
// Token handling
|
|
|
|
|
2020-01-15 11:27:00 +01:00
|
|
|
r.Handle("/get_token", handlers.GetToken(handlers.Database, []byte(config.Keys.JWTSigningKey)))
|
2019-11-04 15:00:46 +01:00
|
|
|
|
|
|
|
// Static file server
|
|
|
|
|
|
|
|
r.PathPrefix("/").Handler(http.FileServer(http.Dir("./dist/")))
|
|
|
|
|
2020-01-14 16:28:27 +01:00
|
|
|
handlers.Router = r
|
|
|
|
|
|
|
|
return handlers
|
2019-11-04 15:00:46 +01:00
|
|
|
}
|
|
|
|
|
2020-01-17 12:53:35 +01:00
|
|
|
func (h *Handlers) NewReadAllRequest(model interface{}, path string, format string) (*http.Request, error) {
|
|
|
|
return http.NewRequest("GET", h.Config.ReadAllPath(model, path, format), nil)
|
|
|
|
}
|
|
|
|
|
|
|
|
func (h *Handlers) NewReadRequest(model interface{}, path string, format string) (*http.Request, error) {
|
|
|
|
return http.NewRequest("GET", h.Config.ReadPath(model, path, format), nil)
|
|
|
|
}
|
|
|
|
|
2020-01-20 12:07:02 +01:00
|
|
|
func (h *Handlers) NewCreateRequest(model interface{}, path string, format string, method string, form url.Values) (*http.Request, error) {
|
2020-01-17 12:53:35 +01:00
|
|
|
var (
|
|
|
|
request *http.Request
|
|
|
|
err error
|
|
|
|
)
|
|
|
|
switch method {
|
|
|
|
case "GET":
|
|
|
|
request, err = http.NewRequest("GET", h.Config.CreatePath(model, path, format), nil)
|
|
|
|
case "POST":
|
2020-01-20 12:07:02 +01:00
|
|
|
request, err = http.NewRequest("POST", h.Config.CreatePath(model, path, format), strings.NewReader(form.Encode()))
|
2020-01-17 12:53:35 +01:00
|
|
|
}
|
|
|
|
return request, err
|
2020-01-16 12:47:35 +01:00
|
|
|
}
|
|
|
|
|
2020-01-14 16:28:27 +01:00
|
|
|
func (h *Handlers) onError(w http.ResponseWriter, r *http.Request, err string) {
|
2019-11-04 15:00:46 +01:00
|
|
|
http.Redirect(w, r, "/login?tpl_layout=login&tpl_content=login", http.StatusTemporaryRedirect)
|
|
|
|
}
|
|
|
|
|
|
|
|
func respondWithStaticFile(w http.ResponseWriter, filename string) error {
|
|
|
|
f, err := ioutil.ReadFile(filepath.Join("public/html", filename))
|
|
|
|
if err != nil {
|
|
|
|
return err
|
|
|
|
}
|
|
|
|
w.Write(f)
|
|
|
|
return nil
|
|
|
|
}
|
|
|
|
|
2020-01-14 16:28:27 +01:00
|
|
|
func (h *Handlers) cookieExtractor(r *http.Request) (string, error) {
|
|
|
|
session, err := h.CookieStore.Get(r, "login-session")
|
2019-11-04 15:00:46 +01:00
|
|
|
if err != nil {
|
|
|
|
return "", nil
|
|
|
|
}
|
|
|
|
|
|
|
|
if session.Values["token"] == nil {
|
|
|
|
return "", nil
|
|
|
|
}
|
|
|
|
|
|
|
|
token := session.Values["token"].([]uint8)
|
|
|
|
|
|
|
|
return string(token), nil
|
|
|
|
}
|
|
|
|
|
2020-01-14 09:43:27 +01:00
|
|
|
func DefaultRecoverHandler(next http.Handler) http.Handler {
|
2019-11-04 15:00:46 +01:00
|
|
|
fn := func(w http.ResponseWriter, r *http.Request) {
|
|
|
|
defer func() {
|
|
|
|
if err := recover(); err != nil {
|
|
|
|
panicMsg := fmt.Sprintf("PANIC: %v\n\n== STACKTRACE ==\n%s", err, debug.Stack())
|
|
|
|
log.Print(panicMsg)
|
|
|
|
http.Error(w, panicMsg, http.StatusInternalServerError)
|
|
|
|
}
|
|
|
|
}()
|
|
|
|
next.ServeHTTP(w, r)
|
|
|
|
}
|
|
|
|
return http.HandlerFunc(fn)
|
|
|
|
}
|
|
|
|
|
2020-01-14 16:28:27 +01:00
|
|
|
func (h *Handlers) setFlashMessage(w http.ResponseWriter, r *http.Request, key string) error {
|
|
|
|
session, err := h.CookieStore.Get(r, "flash-session")
|
2019-12-04 10:11:18 +01:00
|
|
|
if err != nil {
|
|
|
|
return err
|
|
|
|
}
|
2020-01-14 16:28:27 +01:00
|
|
|
session.AddFlash(i18n.FlashMessages[key][h.Config.Language])
|
2019-12-04 10:11:18 +01:00
|
|
|
err = session.Save(r, w)
|
|
|
|
if err != nil {
|
|
|
|
return err
|
|
|
|
}
|
|
|
|
return nil
|
|
|
|
}
|
|
|
|
|
2020-01-17 11:06:28 +01:00
|
|
|
func (h *Handlers) hasPermission(role, path string) bool {
|
|
|
|
if h.permissions[role] == nil {
|
2019-12-04 12:20:34 +01:00
|
|
|
return false
|
|
|
|
}
|
|
|
|
|
2020-01-17 11:06:28 +01:00
|
|
|
return h.permissions[role][path]
|
2019-12-04 12:20:34 +01:00
|
|
|
}
|
|
|
|
|
2020-01-17 07:59:57 +01:00
|
|
|
func (h *Handlers) get(w http.ResponseWriter, r *http.Request, model string, pattern config.PathPattern) {
|
2019-11-04 15:00:46 +01:00
|
|
|
format := r.URL.Query().Get("format")
|
2020-01-15 11:27:00 +01:00
|
|
|
getFn, err := h.Database.GetFunc(pattern.Path(model))
|
2019-11-04 15:00:46 +01:00
|
|
|
if err != nil {
|
|
|
|
log.Println("Error:", err)
|
2020-01-15 13:40:35 +01:00
|
|
|
respondWithError(h, w, r, err)
|
2019-11-04 15:00:46 +01:00
|
|
|
} else {
|
2019-12-04 10:11:18 +01:00
|
|
|
claims := r.Context().Value("user").(*jwt.Token).Claims.(jwt.MapClaims)
|
|
|
|
role := claims["role"].(string)
|
2020-01-17 11:06:28 +01:00
|
|
|
if !h.hasPermission(role, pattern.Path(model)) {
|
2020-01-14 16:28:27 +01:00
|
|
|
h.setFlashMessage(w, r, "notAuthorized")
|
2020-01-15 13:40:35 +01:00
|
|
|
h.Renderer[format].Render(w, r, h.CookieStore, fmt.Errorf("%s", "Errore di autorizzazione"))
|
2019-11-04 15:00:46 +01:00
|
|
|
} else {
|
2020-01-15 11:27:00 +01:00
|
|
|
data, err := getFn(h.Database, mux.Vars(r), w, r)
|
2019-12-04 10:11:18 +01:00
|
|
|
if err != nil {
|
2020-01-15 13:40:35 +01:00
|
|
|
h.Renderer[format].Render(w, r, h.CookieStore, err)
|
2019-12-04 10:11:18 +01:00
|
|
|
} else {
|
2020-01-15 13:40:35 +01:00
|
|
|
h.Renderer[format].Render(w, r, h.CookieStore, data, r.URL.Query())
|
2019-12-04 10:11:18 +01:00
|
|
|
}
|
2019-11-04 15:00:46 +01:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
}
|
|
|
|
|
2020-01-23 10:23:06 +01:00
|
|
|
func (h *Handlers) post(w http.ResponseWriter, r *http.Request, model string, pattern config.PathPattern) error {
|
2019-11-04 15:00:46 +01:00
|
|
|
var (
|
|
|
|
data interface{}
|
|
|
|
err error
|
|
|
|
)
|
|
|
|
|
|
|
|
respFormat := renderer.GetContentFormat(r)
|
2020-01-15 11:27:00 +01:00
|
|
|
postFn, err := h.Database.GetFunc(pattern.Path(model))
|
2019-11-04 15:00:46 +01:00
|
|
|
|
|
|
|
if err != nil {
|
2020-01-15 13:40:35 +01:00
|
|
|
respondWithError(h, w, r, err)
|
2019-11-04 15:00:46 +01:00
|
|
|
} else {
|
2019-12-19 13:56:54 +01:00
|
|
|
claims := r.Context().Value("user").(*jwt.Token).Claims.(jwt.MapClaims)
|
|
|
|
|
|
|
|
role := claims["role"].(string)
|
2020-01-17 11:06:28 +01:00
|
|
|
if !h.hasPermission(role, pattern.Path(model)) {
|
2020-01-15 13:40:35 +01:00
|
|
|
h.Renderer[respFormat].Render(w, r, h.CookieStore, fmt.Errorf("%s", "Errore di autorizzazione"))
|
2019-12-19 13:56:54 +01:00
|
|
|
} else {
|
2020-01-15 11:27:00 +01:00
|
|
|
data, err = postFn(h.Database, mux.Vars(r), w, r)
|
2019-12-19 13:56:54 +01:00
|
|
|
if err != nil {
|
2020-01-15 13:40:35 +01:00
|
|
|
respondWithError(h, w, r, err)
|
2019-12-19 13:56:54 +01:00
|
|
|
} else if pattern.RedirectPattern != "" {
|
|
|
|
if id := mux.Vars(r)["id"]; id != "" {
|
|
|
|
modelId, _ := strconv.Atoi(id)
|
|
|
|
http.Redirect(w, r, pattern.RedirectPath(model, uint(modelId)), http.StatusSeeOther)
|
|
|
|
} else {
|
|
|
|
http.Redirect(w, r, pattern.RedirectPath(model, data.(orm.IDer).GetID()), http.StatusSeeOther)
|
|
|
|
}
|
2019-11-04 15:00:46 +01:00
|
|
|
} else {
|
2020-01-15 13:40:35 +01:00
|
|
|
h.Renderer[respFormat].Render(w, r, h.CookieStore, data.(orm.IDer).GetID())
|
2019-11-04 15:00:46 +01:00
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2020-01-23 10:23:06 +01:00
|
|
|
return nil
|
|
|
|
|
2019-11-04 15:00:46 +01:00
|
|
|
}
|
|
|
|
|
2020-01-17 07:59:57 +01:00
|
|
|
func (h *Handlers) delete(w http.ResponseWriter, r *http.Request, model string, pattern config.PathPattern) {
|
2019-12-19 13:56:54 +01:00
|
|
|
var data interface{}
|
2019-11-04 15:00:46 +01:00
|
|
|
|
|
|
|
respFormat := renderer.GetContentFormat(r)
|
|
|
|
|
2019-12-19 13:56:54 +01:00
|
|
|
claims := r.Context().Value("user").(*jwt.Token).Claims.(jwt.MapClaims)
|
2019-11-04 15:00:46 +01:00
|
|
|
|
2019-12-19 13:56:54 +01:00
|
|
|
role := claims["role"].(string)
|
2020-01-17 11:06:28 +01:00
|
|
|
if !h.hasPermission(role, pattern.Path(model)) {
|
2020-01-15 13:40:35 +01:00
|
|
|
h.Renderer[respFormat].Render(w, r, h.CookieStore, fmt.Errorf("%s", "Errore di autorizzazione"))
|
2019-11-04 15:00:46 +01:00
|
|
|
} else {
|
2020-01-15 11:27:00 +01:00
|
|
|
postFn, err := h.Database.GetFunc(pattern.Path(model))
|
2019-12-19 13:56:54 +01:00
|
|
|
if err != nil {
|
2020-01-15 13:40:35 +01:00
|
|
|
h.Renderer[r.URL.Query().Get("format")].Render(w, r, h.CookieStore, err)
|
2019-12-19 13:56:54 +01:00
|
|
|
}
|
2020-01-15 11:27:00 +01:00
|
|
|
data, err = postFn(h.Database, mux.Vars(r), w, r)
|
2019-12-19 13:56:54 +01:00
|
|
|
if err != nil {
|
2020-01-15 13:40:35 +01:00
|
|
|
h.Renderer["html"].Render(w, r, h.CookieStore, err)
|
2019-12-19 13:56:54 +01:00
|
|
|
} else if pattern.RedirectPattern != "" {
|
|
|
|
var data struct {
|
|
|
|
RedirectUrl string `json:"redirect_url"`
|
|
|
|
}
|
|
|
|
data.RedirectUrl = pattern.RedirectPath(model)
|
|
|
|
|
|
|
|
w.Header().Set("Content-Type", "application/json")
|
|
|
|
json.NewEncoder(w).Encode(data)
|
|
|
|
} else {
|
2020-01-15 13:40:35 +01:00
|
|
|
h.Renderer[respFormat].Render(w, r, h.CookieStore, data.(orm.IDer).GetID())
|
2019-12-19 13:56:54 +01:00
|
|
|
}
|
2019-11-04 15:00:46 +01:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2020-01-15 13:40:35 +01:00
|
|
|
func respondWithError(h *Handlers, w http.ResponseWriter, r *http.Request, err error) {
|
2019-11-04 15:00:46 +01:00
|
|
|
respFormat := renderer.GetContentFormat(r)
|
|
|
|
w.WriteHeader(http.StatusInternalServerError)
|
2020-01-15 13:40:35 +01:00
|
|
|
h.Renderer[respFormat].Render(w, r, h.CookieStore, err)
|
2019-11-04 15:00:46 +01:00
|
|
|
}
|
|
|
|
|
2020-01-20 12:07:02 +01:00
|
|
|
func (h *Handlers) Create(model interface{}) http.Handler {
|
|
|
|
fn := func(w http.ResponseWriter, r *http.Request) {
|
|
|
|
h.post(w, r, reflect.ModelNameLowerPlural(model), h.Config.CreatePattern())
|
|
|
|
}
|
|
|
|
|
|
|
|
return http.HandlerFunc(fn)
|
|
|
|
}
|
|
|
|
|
2020-01-17 07:59:57 +01:00
|
|
|
func (h *Handlers) ReadAll(model interface{}) http.Handler {
|
|
|
|
fn := func(w http.ResponseWriter, r *http.Request) {
|
2020-01-17 11:06:28 +01:00
|
|
|
h.get(w, r, reflect.ModelNameLowerPlural(model), h.Config.ReadAllPattern())
|
2020-01-17 07:59:57 +01:00
|
|
|
}
|
|
|
|
|
|
|
|
return http.HandlerFunc(fn)
|
|
|
|
}
|
|
|
|
|
2020-01-17 12:11:13 +01:00
|
|
|
func (h *Handlers) Read(model interface{}) http.Handler {
|
|
|
|
fn := func(w http.ResponseWriter, r *http.Request) {
|
|
|
|
h.get(w, r, reflect.ModelNameLowerPlural(model), h.Config.ReadPattern())
|
|
|
|
}
|
|
|
|
|
|
|
|
return http.HandlerFunc(fn)
|
|
|
|
}
|
|
|
|
|
2020-01-17 07:59:57 +01:00
|
|
|
func (h *Handlers) modelHandler(model string, pattern config.PathPattern) http.Handler {
|
2019-11-04 15:00:46 +01:00
|
|
|
fn := func(w http.ResponseWriter, r *http.Request) {
|
|
|
|
|
2020-01-20 12:54:57 +01:00
|
|
|
// Replace the "api" prefix.
|
2019-11-04 15:00:46 +01:00
|
|
|
pattern.PathPattern = strings.Replace(pattern.PathPattern, "/api", "", -1)
|
|
|
|
|
|
|
|
switch r.Method {
|
|
|
|
case "GET":
|
2020-01-14 16:28:27 +01:00
|
|
|
h.get(w, r, model, pattern)
|
2019-11-04 15:00:46 +01:00
|
|
|
|
|
|
|
case "POST":
|
2020-01-15 11:27:00 +01:00
|
|
|
h.post(w, r, model, pattern)
|
2019-11-04 15:00:46 +01:00
|
|
|
|
|
|
|
case "DELETE":
|
2020-01-15 11:27:00 +01:00
|
|
|
h.delete(w, r, model, pattern)
|
2019-11-04 15:00:46 +01:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
return http.HandlerFunc(fn)
|
|
|
|
}
|
|
|
|
|
2020-01-14 09:43:27 +01:00
|
|
|
func DefaultHomeHandler() http.Handler {
|
2019-11-04 15:00:46 +01:00
|
|
|
fn := func(w http.ResponseWriter, r *http.Request) {
|
2019-11-22 11:16:27 +01:00
|
|
|
claims := r.Context().Value("user").(*jwt.Token).Claims.(jwt.MapClaims)
|
|
|
|
|
|
|
|
switch claims["role"] {
|
|
|
|
|
2019-12-03 15:24:01 +01:00
|
|
|
case "subscriber":
|
|
|
|
http.Redirect(
|
|
|
|
w,
|
|
|
|
r,
|
|
|
|
fmt.Sprintf(
|
|
|
|
"/schools/create/?format=html&tpl_layout=base&tpl_content=schools_add_update",
|
|
|
|
),
|
|
|
|
http.StatusSeeOther,
|
|
|
|
)
|
|
|
|
|
2019-11-22 11:16:27 +01:00
|
|
|
case "participant":
|
|
|
|
http.Redirect(
|
|
|
|
w,
|
|
|
|
r,
|
|
|
|
fmt.Sprintf(
|
|
|
|
"/participants/%s?format=html&tpl_layout=base&tpl_content=participants_show",
|
|
|
|
claims["user_id"].(string)),
|
|
|
|
http.StatusSeeOther,
|
|
|
|
)
|
|
|
|
|
|
|
|
case "school":
|
2019-12-03 15:24:01 +01:00
|
|
|
http.Redirect(
|
|
|
|
w,
|
|
|
|
r,
|
|
|
|
fmt.Sprintf(
|
|
|
|
"/schools/%s?format=html&tpl_layout=base&tpl_content=schools_show",
|
|
|
|
claims["user_id"].(string)),
|
|
|
|
http.StatusSeeOther,
|
|
|
|
)
|
2019-11-22 11:16:27 +01:00
|
|
|
|
|
|
|
default:
|
|
|
|
http.Redirect(
|
|
|
|
w,
|
|
|
|
r,
|
|
|
|
"/contests?format=html&tpl_layout=base&tpl_content=contests",
|
|
|
|
http.StatusSeeOther,
|
|
|
|
)
|
|
|
|
}
|
|
|
|
|
2019-11-04 15:00:46 +01:00
|
|
|
}
|
|
|
|
return http.HandlerFunc(fn)
|
|
|
|
}
|