Improve error handling and handle errors in token

This commit is contained in:
Andrea Fazzi 2020-02-19 14:57:31 +01:00
parent 290fe238ac
commit 9d99f56385
16 changed files with 174 additions and 85 deletions

View file

@ -270,7 +270,6 @@ func (h *Handlers) cookieExtractor(r *http.Request) (string, error) {
if err != nil {
return "", nil
}
if session.Values["token"] == nil {
return "", nil
}
@ -344,7 +343,10 @@ func (h *Handlers) get(w http.ResponseWriter, r *http.Request, model string, pat
return err
}
format := r.URL.Query().Get("format")
h.Renderer[format].Render(w, r, h.CookieStore, data, r.URL.Query())
err = h.Renderer[format].Render(w, r, h.CookieStore, data, r.URL.Query())
if err != nil {
return err
}
return nil
}
@ -363,7 +365,10 @@ func (h *Handlers) post(w http.ResponseWriter, r *http.Request, model string, pa
}
} else {
format := renderer.GetContentFormat(r)
h.Renderer[format].Render(w, r, h.CookieStore, data.(orm.IDer).GetID())
err := h.Renderer[format].Render(w, r, h.CookieStore, data.(orm.IDer).GetID())
if err != nil {
return err
}
}
return nil
@ -385,7 +390,10 @@ func (h *Handlers) delete(w http.ResponseWriter, r *http.Request, model string,
json.NewEncoder(w).Encode(data)
} else {
format := renderer.GetContentFormat(r)
h.Renderer[format].Render(w, r, h.CookieStore, data.(orm.IDer).GetID())
err := h.Renderer[format].Render(w, r, h.CookieStore, data.(orm.IDer).GetID())
if err != nil {
return err
}
}
return nil
@ -399,10 +407,12 @@ func respondWithError(h *Handlers, w http.ResponseWriter, r *http.Request, err e
format = renderer.GetContentFormat(r)
}
if h.Config.LogLevel > config.LOG_LEVEL_OFF {
log.Println(err)
log.Println("Error:", err)
}
// FIXME: this call could be superflous when an error occurs
// in a template execution
w.WriteHeader(http.StatusInternalServerError)
h.Renderer[format].Render(w, r, h.CookieStore, err)
h.Renderer[format].WriteError(w, r, err)
}
func (h *Handlers) Create(model interface{}) http.Handler {
@ -550,10 +560,6 @@ func (m *rootMiddleware) ServeHTTP(w http.ResponseWriter, r *http.Request) {
return
}
// This is where our error handling logic starts.
if m.h.Config.LogLevel > config.LOG_LEVEL_OFF {
log.Printf("An error accured: %v", err) // Log the error.
}
if err, ok := err.(*errors.Error); ok {
err.Referer = r.Header.Get("Referer")
}

View file

@ -7,8 +7,8 @@ import (
"strconv"
"time"
"git.andreafazzi.eu/andrea/oef/orm"
oef_errors "git.andreafazzi.eu/andrea/oef/errors"
"git.andreafazzi.eu/andrea/oef/orm"
jwt "github.com/dgrijalva/jwt-go"
"github.com/gorilla/sessions"
)
@ -25,17 +25,28 @@ type UserToken struct {
UserID string
}
func clearSession(response http.ResponseWriter) {
cookie := &http.Cookie{
Name: "login-session",
Value: "",
Path: "/",
MaxAge: -1,
}
http.SetCookie(response, cookie)
}
func DefaultLogoutHandler(store *sessions.CookieStore) http.Handler {
fn := func(w http.ResponseWriter, r *http.Request) {
session, err := store.Get(r, "login-session")
if err != nil {
http.Error(w, err.Error(), http.StatusInternalServerError)
return
}
session.Values["token"] = []uint8{}
session.Save(r, w)
// session, err := store.Get(r, "login-session")
// if err != nil {
// // http.Error(w, err.Error(), http.StatusInternalServerError)
// store.Set(w)
// return
// }
// session.Values["token"] = []uint8{}
// session.Save(r, w)
clearSession(w)
http.Redirect(w, r, "/", http.StatusSeeOther)
}

View file

@ -18,8 +18,7 @@ import (
"strings"
"time"
"git.andreafazzi.eu/andrea/oef/errors"
oef_errors "git.andreafazzi.eu/andrea/oef/errors"
"github.com/gocarina/gocsv"
"github.com/gorilla/schema"
"github.com/gorilla/sessions"
@ -29,6 +28,7 @@ import (
type Renderer interface {
Render(http.ResponseWriter, *http.Request, *sessions.CookieStore, interface{}, ...url.Values) error
WriteError(http.ResponseWriter, *http.Request, interface{})
}
type JSONRenderer struct{}
@ -69,6 +69,10 @@ func NewJSONRenderer() (*JSONRenderer, error) {
return &JSONRenderer{}, nil
}
func (rend *JSONRenderer) WriteError(w http.ResponseWriter, r *http.Request, data interface{}) {
}
func (rend *JSONRenderer) Render(w http.ResponseWriter, r *http.Request, store *sessions.CookieStore, data interface{}, options ...url.Values) error {
w.Header().Set("Content-Type", "application/json; charset=utf-8")
if isErrorType(data) {
@ -180,9 +184,16 @@ func NewHTMLRenderer(templatePath string) (*HTMLRenderer, error) {
}
func (rend *HTMLRenderer) writeError(w http.ResponseWriter, r *http.Request, data interface{}) {
var t *template.Template
var (
t *template.Template
claims jwt.MapClaims
)
err, ok := data.(*htmlTemplateData).Data.(*errors.Error)
if r.Context().Value("user") != nil {
claims = r.Context().Value("user").(*jwt.Token).Claims.(jwt.MapClaims)
}
err, ok := data.(*oef_errors.Error)
if ok {
t, ok = rend.templates[err.TemplateName]
if !ok {
@ -197,12 +208,25 @@ func (rend *HTMLRenderer) writeError(w http.ResponseWriter, r *http.Request, dat
}
w.Header().Set("Content-Type", "text/html; charset=utf-8")
e := t.ExecuteTemplate(w, "error_not_authorized", err)
if e != nil {
panic(e)
if claims != nil {
e := t.ExecuteTemplate(w, "base", &htmlTemplateData{data, nil, claims})
if e != nil {
panic(e)
}
} else {
e := t.ExecuteTemplate(w, "error", &htmlTemplateData{data, nil, nil})
if e != nil {
panic(e)
}
}
}
func (rend *HTMLRenderer) WriteError(w http.ResponseWriter, r *http.Request, data interface{}) {
rend.writeError(w, r, data)
}
func (rend *HTMLRenderer) Render(w http.ResponseWriter, r *http.Request, store *sessions.CookieStore, data interface{}, options ...url.Values) error {
var claims jwt.MapClaims
@ -210,26 +234,22 @@ func (rend *HTMLRenderer) Render(w http.ResponseWriter, r *http.Request, store *
claims = r.Context().Value("user").(*jwt.Token).Claims.(jwt.MapClaims)
}
if data != nil {
err, ok := data.(*errors.Error)
if ok {
rend.writeError(w, r, &htmlTemplateData{data, nil, claims})
return err
}
if err, ok := data.(*oef_errors.Error); ok {
// rend.writeError(w, r, &htmlTemplateData{data, nil, claims})
return err
}
t, ok := rend.templates[options[0]["tpl_content"][0]]
if !ok {
err := fmt.Errorf("Template %s not found", options[0]["tpl_content"][0])
rend.writeError(w, r, &htmlTemplateData{err, nil, claims})
return err
}
t, ok := rend.templates[options[0]["tpl_content"][0]]
if !ok {
err := fmt.Errorf("Template %s not found", options[0]["tpl_content"][0])
// rend.writeError(w, r, &htmlTemplateData{err, nil, claims})
return err
}
w.Header().Set("Content-Type", "text/html; charset=utf-8")
if err := t.ExecuteTemplate(w, options[0]["tpl_layout"][0], &htmlTemplateData{data, options[0], claims}); err != nil {
rend.writeError(w, r, &htmlTemplateData{err, nil, claims})
return err
}
w.Header().Set("Content-Type", "text/html; charset=utf-8")
if err := t.ExecuteTemplate(w, options[0]["tpl_layout"][0], &htmlTemplateData{data, options[0], claims}); err != nil {
// rend.writeError(w, r, &htmlTemplateData{err, nil, claims})
return err
}
return nil

View file

@ -1,4 +1,4 @@
{{ define "content" }}
{{$options := `title: "Errore durante l'iscrizione della scuola"`}}
{{template "error" dict "options" ($options|yaml) "data" .Data}}
{{$options := `title: "Errore durante l'iscrizione di un partecipante"`}}
{{template "show_error" dict "options" ($options|yaml) "data" .Data}}
{{end}}

View file

@ -1,4 +1,4 @@
{{ define "content" }}
{{$options := `title: "Errore nella creazione/aggiornamento di un partecipante"`}}
{{template "error" dict "options" ($options|yaml) "data" .Data}}
{{template "show_error" dict "options" ($options|yaml) "data" .Data}}
{{end}}

View file

@ -1,4 +1,13 @@
{{ define "content" }}
{{$options := `title: "Errore di autorizzazione"`}}
{{template "error" dict "options" ($options|yaml) "data" .Data}}
<div class="container">
<div class="alert alert-danger" role="alert">
<h4 class="alert-heading">
Errore di autorizzazione
</h4>
{{.Data}}
Clicca {{"/logout"|alertLink "qui"}} per effettuare il logout e ritornare alla pagina di autenticazione.
</div>
<p>
</p>
</div>
{{end}}

View file

@ -1,4 +1,4 @@
{{ define "content" }}
{{$options := `title: "Errore nella gestione della prova di gara"`}}
{{template "error" dict "options" ($options|yaml) "data" .Data}}
{{template "show_error" dict "options" ($options|yaml) "data" .Data}}
{{end}}

View file

@ -1,4 +1,4 @@
{{ define "content" }}
{{$options := `title: "Errore nella creazione/aggiornamento di un partecipante"`}}
{{template "error" dict "options" ($options|yaml) "data" .Data}}
{{template "show_error" dict "options" ($options|yaml) "data" .Data}}
{{end}}

View file

@ -1,4 +1,4 @@
{{ define "content" }}
{{$options := `title: "Errore nell'apertura della prova di gara"`}}
{{template "error" dict "options" ($options|yaml) "data" .Data}}
{{template "show_error" dict "options" ($options|yaml) "data" .Data}}
{{end}}

View file

@ -1,4 +1,4 @@
{{ define "content" }}
{{$options := `title: "Errore nella creazione/aggiornamento di una scuola"`}}
{{template "error" dict "options" ($options|yaml) "data" .Data}}
{{template "show_error" dict "options" ($options|yaml) "data" .Data}}
{{end}}

View file

@ -1,4 +1,4 @@
{{ define "content" }}
{{$options := `title: "Errore durante l'iscrizione di una scuola"`}}
{{template "error" dict "options" ($options|yaml) "data" .Data}}
{{template "show_error" dict "options" ($options|yaml) "data" .Data}}
{{end}}

View file

@ -61,16 +61,6 @@
</ul>
</div><!--/.nav-collapse -->
</nav>
{{- if .FlashMessages -}}
{{range $message := .FlashMessages}}
<div class="alert alert-danger alert-dismissible fade show" role="alert">
<strong>Attenzione!</strong> {{$message}}
<button type="button" class="close" data-dismiss="alert" aria-label="Close">
<span aria-hidden="true">&times;</span>
</button>
</div>
{{end}}
{{- end -}}
<div class="base-template">
{{ template "content" . }}
</div>

View file

@ -1,15 +1,55 @@
{{define "error"}}
<div class="container">
<div class="alert alert-danger" role="alert">
<h4 class="alert-heading">
{{.data.Title}}
</h4>
{{.data}}
{{if .data.Referer}}
Clicca {{.data.Referer|alertLink "qui"}} per tornare all'azione precedente.
{{end}}
</div>
<p>
</p>
</div>
{{- define "error" -}}
<!DOCTYPE html>
<html lang="it">
<head>
<meta charset="utf-8">
<meta http-equiv="X-UA-Compatible" content="IE=edge">
<meta name="viewport" content="width=device-width, initial-scale=1">
<link
rel="stylesheet"
href="https://stackpath.bootstrapcdn.com/bootstrap/4.4.1/css/bootstrap.min.css"
integrity="sha384-Vkoo8x4CGsO3+Hhxv8T/Q5PaXtkKtu6ug5TOeNV6gBiFeWPGFN9MuhOf23Q9Ifjh"
crossorigin="anonymous">
<link
rel="stylesheet"
href="https://cdnjs.cloudflare.com/ajax/libs/font-awesome/5.11.2/css/all.css">
<link
rel="stylesheet"
href="https://cdn.jsdelivr.net/npm/bootstrap-select@1.13.9/dist/css/bootstrap-select.min.css">
<link rel="stylesheet" href="/styles.css" />
<title>Olimpiadi di Economia e Finanza - Piattaforma di gara</title>
</head>
<body data-spy="scroll">
<nav class="navbar navbar-expand-lg fixed-top navbar-dark bg-primary">
{{- $homeURL := "" -}}
<a class="navbar-brand" href="{{$homeURL}}">
<span class="fa fa-landmark"></span>
OEF 2020
</a>
<button type="button" class="navbar-toggler" data-toggle="collapse" data-target="#navbar" aria-expanded="false" aria-controls="navbar">
<span class="navbar-toggler-icon"></span>
</button>
</nav>
<div class="base-template">
{{ template "content" . }}
</div>
<script
src="https://code.jquery.com/jquery-3.4.1.min.js"
integrity="sha256-CSXorXvZcTkaix6Yvo6HppcZGetbYMGWSFlBw8HfCJo="
crossorigin="anonymous">
</script>
<script
src="https://cdn.jsdelivr.net/npm/popper.js@1.16.0/dist/umd/popper.min.js"
integrity="sha384-Q6E9RHvbIyZFJoft+2mJbHaEWldlvI9IOYy5n3zV9zzTtmI3UksdQRVvoxMfooAo"
crossorigin="anonymous">
</script>
<script
src="https://stackpath.bootstrapcdn.com/bootstrap/4.4.1/js/bootstrap.min.js"
integrity="sha384-wfSDF2E50Y2D1uUdj0O3uMBJnjuUD4Ih7YwaYd1iqfktj0Uod8GCExl3Og8ifwB6"
crossorigin="anonymous">
</script>
<script src="https://cdn.jsdelivr.net/npm/bootstrap-select@1.13.9/dist/js/bootstrap-select.min.js"></script>
<script src="/main.bundle.js"></script>
</body>
</html>
{{end}}

View file

@ -0,0 +1,15 @@
{{define "show_error"}}
<div class="container">
<div class="alert alert-danger" role="alert">
<h4 class="alert-heading">
{{.options.title}}
</h4>
{{.data}}
{{if .data.Referer}}
Clicca {{.data.Referer|alertLink "qui"}} per tornare all'azione precedente.
{{end}}
</div>
<p>
</p>
</div>
{{end}}

View file

@ -127,6 +127,7 @@
<div class="row">
<div class="col-md-12">
<h2 class="karmen-relation-header">Suggerimenti</h2>
{{if .Data.School}}
{{if le (len .Data.School.Participants) 1}}
<p>
E' possibile iscrivere fino a due partecipanti alla gara (di diversa categoria).
@ -141,7 +142,7 @@
<strong>Iscrizione completa.</strong> Non è possibile aggiungere ulteriori partecipanti.
</div>
{{end}}
{{end}}
<div class="alert alert-danger text-justify">
<span class="fa
fa-exclamation-triangle mr-1">
@ -155,9 +156,9 @@
</div>
</div>
</div>
</div>
{{end}}
</div>
{{end}}
</div>

View file

@ -6,9 +6,6 @@
<div class="container">
{{if $isSubscriber}}
{{if .FlashMessages}}
<p>Si è verificato un errore. Clicca <a href="/logout">qui</a> per uscire da questa sessione.</p>
{{else}}
<p>
Grazie per aver iscritto la scuola <strong>{{.Data.Name}}</strong>
alle Olimpiadi di Economia e Finanza.
@ -27,7 +24,7 @@
utilizzare le credenziali ricevute per iscrivere gli studenti alla
competizione.
</p>
{{end}}
{{else}}
{{$deletePath := ""}}