Improve error handling and handle errors in token
This commit is contained in:
parent
290fe238ac
commit
9d99f56385
16 changed files with 174 additions and 85 deletions
|
@ -270,7 +270,6 @@ func (h *Handlers) cookieExtractor(r *http.Request) (string, error) {
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return "", nil
|
return "", nil
|
||||||
}
|
}
|
||||||
|
|
||||||
if session.Values["token"] == nil {
|
if session.Values["token"] == nil {
|
||||||
return "", nil
|
return "", nil
|
||||||
}
|
}
|
||||||
|
@ -344,7 +343,10 @@ func (h *Handlers) get(w http.ResponseWriter, r *http.Request, model string, pat
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
format := r.URL.Query().Get("format")
|
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
|
return nil
|
||||||
}
|
}
|
||||||
|
@ -363,7 +365,10 @@ func (h *Handlers) post(w http.ResponseWriter, r *http.Request, model string, pa
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
format := renderer.GetContentFormat(r)
|
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
|
return nil
|
||||||
|
@ -385,7 +390,10 @@ func (h *Handlers) delete(w http.ResponseWriter, r *http.Request, model string,
|
||||||
json.NewEncoder(w).Encode(data)
|
json.NewEncoder(w).Encode(data)
|
||||||
} else {
|
} else {
|
||||||
format := renderer.GetContentFormat(r)
|
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
|
return nil
|
||||||
|
@ -399,10 +407,12 @@ func respondWithError(h *Handlers, w http.ResponseWriter, r *http.Request, err e
|
||||||
format = renderer.GetContentFormat(r)
|
format = renderer.GetContentFormat(r)
|
||||||
}
|
}
|
||||||
if h.Config.LogLevel > config.LOG_LEVEL_OFF {
|
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)
|
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 {
|
func (h *Handlers) Create(model interface{}) http.Handler {
|
||||||
|
@ -550,10 +560,6 @@ func (m *rootMiddleware) ServeHTTP(w http.ResponseWriter, r *http.Request) {
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
// This is where our error handling logic starts.
|
// 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 {
|
if err, ok := err.(*errors.Error); ok {
|
||||||
err.Referer = r.Header.Get("Referer")
|
err.Referer = r.Header.Get("Referer")
|
||||||
}
|
}
|
||||||
|
|
|
@ -7,8 +7,8 @@ import (
|
||||||
"strconv"
|
"strconv"
|
||||||
"time"
|
"time"
|
||||||
|
|
||||||
"git.andreafazzi.eu/andrea/oef/orm"
|
|
||||||
oef_errors "git.andreafazzi.eu/andrea/oef/errors"
|
oef_errors "git.andreafazzi.eu/andrea/oef/errors"
|
||||||
|
"git.andreafazzi.eu/andrea/oef/orm"
|
||||||
jwt "github.com/dgrijalva/jwt-go"
|
jwt "github.com/dgrijalva/jwt-go"
|
||||||
"github.com/gorilla/sessions"
|
"github.com/gorilla/sessions"
|
||||||
)
|
)
|
||||||
|
@ -25,17 +25,28 @@ type UserToken struct {
|
||||||
UserID string
|
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 {
|
func DefaultLogoutHandler(store *sessions.CookieStore) http.Handler {
|
||||||
fn := func(w http.ResponseWriter, r *http.Request) {
|
fn := func(w http.ResponseWriter, r *http.Request) {
|
||||||
session, err := store.Get(r, "login-session")
|
// session, err := store.Get(r, "login-session")
|
||||||
if err != nil {
|
// if err != nil {
|
||||||
http.Error(w, err.Error(), http.StatusInternalServerError)
|
// // http.Error(w, err.Error(), http.StatusInternalServerError)
|
||||||
return
|
// store.Set(w)
|
||||||
}
|
// return
|
||||||
|
// }
|
||||||
session.Values["token"] = []uint8{}
|
|
||||||
session.Save(r, w)
|
|
||||||
|
|
||||||
|
// session.Values["token"] = []uint8{}
|
||||||
|
// session.Save(r, w)
|
||||||
|
clearSession(w)
|
||||||
http.Redirect(w, r, "/", http.StatusSeeOther)
|
http.Redirect(w, r, "/", http.StatusSeeOther)
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
|
@ -18,8 +18,7 @@ import (
|
||||||
"strings"
|
"strings"
|
||||||
"time"
|
"time"
|
||||||
|
|
||||||
"git.andreafazzi.eu/andrea/oef/errors"
|
oef_errors "git.andreafazzi.eu/andrea/oef/errors"
|
||||||
|
|
||||||
"github.com/gocarina/gocsv"
|
"github.com/gocarina/gocsv"
|
||||||
"github.com/gorilla/schema"
|
"github.com/gorilla/schema"
|
||||||
"github.com/gorilla/sessions"
|
"github.com/gorilla/sessions"
|
||||||
|
@ -29,6 +28,7 @@ import (
|
||||||
|
|
||||||
type Renderer interface {
|
type Renderer interface {
|
||||||
Render(http.ResponseWriter, *http.Request, *sessions.CookieStore, interface{}, ...url.Values) error
|
Render(http.ResponseWriter, *http.Request, *sessions.CookieStore, interface{}, ...url.Values) error
|
||||||
|
WriteError(http.ResponseWriter, *http.Request, interface{})
|
||||||
}
|
}
|
||||||
|
|
||||||
type JSONRenderer struct{}
|
type JSONRenderer struct{}
|
||||||
|
@ -69,6 +69,10 @@ func NewJSONRenderer() (*JSONRenderer, error) {
|
||||||
return &JSONRenderer{}, nil
|
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 {
|
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")
|
w.Header().Set("Content-Type", "application/json; charset=utf-8")
|
||||||
if isErrorType(data) {
|
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{}) {
|
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 {
|
if ok {
|
||||||
t, ok = rend.templates[err.TemplateName]
|
t, ok = rend.templates[err.TemplateName]
|
||||||
if !ok {
|
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")
|
w.Header().Set("Content-Type", "text/html; charset=utf-8")
|
||||||
e := t.ExecuteTemplate(w, "error_not_authorized", err)
|
|
||||||
if e != nil {
|
if claims != nil {
|
||||||
panic(e)
|
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 {
|
func (rend *HTMLRenderer) Render(w http.ResponseWriter, r *http.Request, store *sessions.CookieStore, data interface{}, options ...url.Values) error {
|
||||||
var claims jwt.MapClaims
|
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)
|
claims = r.Context().Value("user").(*jwt.Token).Claims.(jwt.MapClaims)
|
||||||
}
|
}
|
||||||
|
|
||||||
if data != nil {
|
if err, ok := data.(*oef_errors.Error); ok {
|
||||||
err, ok := data.(*errors.Error)
|
// rend.writeError(w, r, &htmlTemplateData{data, nil, claims})
|
||||||
if ok {
|
return err
|
||||||
rend.writeError(w, r, &htmlTemplateData{data, nil, claims})
|
}
|
||||||
return err
|
|
||||||
}
|
|
||||||
|
|
||||||
t, ok := rend.templates[options[0]["tpl_content"][0]]
|
t, ok := rend.templates[options[0]["tpl_content"][0]]
|
||||||
if !ok {
|
if !ok {
|
||||||
err := fmt.Errorf("Template %s not found", options[0]["tpl_content"][0])
|
err := fmt.Errorf("Template %s not found", options[0]["tpl_content"][0])
|
||||||
rend.writeError(w, r, &htmlTemplateData{err, nil, claims})
|
// rend.writeError(w, r, &htmlTemplateData{err, nil, claims})
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
|
|
||||||
w.Header().Set("Content-Type", "text/html; charset=utf-8")
|
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 {
|
||||||
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})
|
||||||
rend.writeError(w, r, &htmlTemplateData{err, nil, claims})
|
return err
|
||||||
return err
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
return nil
|
return nil
|
||||||
|
|
|
@ -1,4 +1,4 @@
|
||||||
{{ define "content" }}
|
{{ define "content" }}
|
||||||
{{$options := `title: "Errore durante l'iscrizione della scuola"`}}
|
{{$options := `title: "Errore durante l'iscrizione di un partecipante"`}}
|
||||||
{{template "error" dict "options" ($options|yaml) "data" .Data}}
|
{{template "show_error" dict "options" ($options|yaml) "data" .Data}}
|
||||||
{{end}}
|
{{end}}
|
||||||
|
|
|
@ -1,4 +1,4 @@
|
||||||
{{ define "content" }}
|
{{ define "content" }}
|
||||||
{{$options := `title: "Errore nella creazione/aggiornamento di un partecipante"`}}
|
{{$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}}
|
{{end}}
|
||||||
|
|
|
@ -1,4 +1,13 @@
|
||||||
{{ define "content" }}
|
{{ define "content" }}
|
||||||
{{$options := `title: "Errore di autorizzazione"`}}
|
<div class="container">
|
||||||
{{template "error" dict "options" ($options|yaml) "data" .Data}}
|
<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}}
|
{{end}}
|
||||||
|
|
|
@ -1,4 +1,4 @@
|
||||||
{{ define "content" }}
|
{{ define "content" }}
|
||||||
{{$options := `title: "Errore nella gestione della prova di gara"`}}
|
{{$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}}
|
{{end}}
|
||||||
|
|
|
@ -1,4 +1,4 @@
|
||||||
{{ define "content" }}
|
{{ define "content" }}
|
||||||
{{$options := `title: "Errore nella creazione/aggiornamento di un partecipante"`}}
|
{{$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}}
|
{{end}}
|
||||||
|
|
|
@ -1,4 +1,4 @@
|
||||||
{{ define "content" }}
|
{{ define "content" }}
|
||||||
{{$options := `title: "Errore nell'apertura della prova di gara"`}}
|
{{$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}}
|
{{end}}
|
||||||
|
|
|
@ -1,4 +1,4 @@
|
||||||
{{ define "content" }}
|
{{ define "content" }}
|
||||||
{{$options := `title: "Errore nella creazione/aggiornamento di una scuola"`}}
|
{{$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}}
|
{{end}}
|
||||||
|
|
|
@ -1,4 +1,4 @@
|
||||||
{{ define "content" }}
|
{{ define "content" }}
|
||||||
{{$options := `title: "Errore durante l'iscrizione di una scuola"`}}
|
{{$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}}
|
{{end}}
|
||||||
|
|
|
@ -61,16 +61,6 @@
|
||||||
</ul>
|
</ul>
|
||||||
</div><!--/.nav-collapse -->
|
</div><!--/.nav-collapse -->
|
||||||
</nav>
|
</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">×</span>
|
|
||||||
</button>
|
|
||||||
</div>
|
|
||||||
{{end}}
|
|
||||||
{{- end -}}
|
|
||||||
<div class="base-template">
|
<div class="base-template">
|
||||||
{{ template "content" . }}
|
{{ template "content" . }}
|
||||||
</div>
|
</div>
|
||||||
|
|
|
@ -1,15 +1,55 @@
|
||||||
{{define "error"}}
|
{{- define "error" -}}
|
||||||
<div class="container">
|
<!DOCTYPE html>
|
||||||
<div class="alert alert-danger" role="alert">
|
<html lang="it">
|
||||||
<h4 class="alert-heading">
|
<head>
|
||||||
{{.data.Title}}
|
<meta charset="utf-8">
|
||||||
</h4>
|
<meta http-equiv="X-UA-Compatible" content="IE=edge">
|
||||||
{{.data}}
|
<meta name="viewport" content="width=device-width, initial-scale=1">
|
||||||
{{if .data.Referer}}
|
<link
|
||||||
Clicca {{.data.Referer|alertLink "qui"}} per tornare all'azione precedente.
|
rel="stylesheet"
|
||||||
{{end}}
|
href="https://stackpath.bootstrapcdn.com/bootstrap/4.4.1/css/bootstrap.min.css"
|
||||||
</div>
|
integrity="sha384-Vkoo8x4CGsO3+Hhxv8T/Q5PaXtkKtu6ug5TOeNV6gBiFeWPGFN9MuhOf23Q9Ifjh"
|
||||||
<p>
|
crossorigin="anonymous">
|
||||||
</p>
|
<link
|
||||||
</div>
|
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}}
|
{{end}}
|
||||||
|
|
15
templates/layout/show_error.html.tpl
Normal file
15
templates/layout/show_error.html.tpl
Normal 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}}
|
|
@ -127,6 +127,7 @@
|
||||||
<div class="row">
|
<div class="row">
|
||||||
<div class="col-md-12">
|
<div class="col-md-12">
|
||||||
<h2 class="karmen-relation-header">Suggerimenti</h2>
|
<h2 class="karmen-relation-header">Suggerimenti</h2>
|
||||||
|
{{if .Data.School}}
|
||||||
{{if le (len .Data.School.Participants) 1}}
|
{{if le (len .Data.School.Participants) 1}}
|
||||||
<p>
|
<p>
|
||||||
E' possibile iscrivere fino a due partecipanti alla gara (di diversa categoria).
|
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.
|
<strong>Iscrizione completa.</strong> Non è possibile aggiungere ulteriori partecipanti.
|
||||||
</div>
|
</div>
|
||||||
{{end}}
|
{{end}}
|
||||||
|
{{end}}
|
||||||
<div class="alert alert-danger text-justify">
|
<div class="alert alert-danger text-justify">
|
||||||
<span class="fa
|
<span class="fa
|
||||||
fa-exclamation-triangle mr-1">
|
fa-exclamation-triangle mr-1">
|
||||||
|
@ -155,9 +156,9 @@
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
</div>
|
|
||||||
</div>
|
</div>
|
||||||
{{end}}
|
</div>
|
||||||
|
{{end}}
|
||||||
|
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
|
|
|
@ -6,9 +6,6 @@
|
||||||
|
|
||||||
<div class="container">
|
<div class="container">
|
||||||
{{if $isSubscriber}}
|
{{if $isSubscriber}}
|
||||||
{{if .FlashMessages}}
|
|
||||||
<p>Si è verificato un errore. Clicca <a href="/logout">qui</a> per uscire da questa sessione.</p>
|
|
||||||
{{else}}
|
|
||||||
<p>
|
<p>
|
||||||
Grazie per aver iscritto la scuola <strong>{{.Data.Name}}</strong>
|
Grazie per aver iscritto la scuola <strong>{{.Data.Name}}</strong>
|
||||||
alle Olimpiadi di Economia e Finanza.
|
alle Olimpiadi di Economia e Finanza.
|
||||||
|
@ -27,7 +24,7 @@
|
||||||
utilizzare le credenziali ricevute per iscrivere gli studenti alla
|
utilizzare le credenziali ricevute per iscrivere gli studenti alla
|
||||||
competizione.
|
competizione.
|
||||||
</p>
|
</p>
|
||||||
{{end}}
|
|
||||||
{{else}}
|
{{else}}
|
||||||
|
|
||||||
{{$deletePath := ""}}
|
{{$deletePath := ""}}
|
||||||
|
|
Loading…
Reference in a new issue