diff --git a/config/config.go b/config/config.go index 0f42669e..97f5e9c6 100644 --- a/config/config.go +++ b/config/config.go @@ -146,6 +146,10 @@ func (c *ConfigT) CreatePath(model interface{}, path, format string) string { return path + "?" + c.query(model, CreateLabel, format).Encode() } +func (c *ConfigT) UpdatePath(model interface{}, path, format string) string { + return path + "?" + c.query(model, UpdateLabel, format).Encode() +} + func (c *ConfigT) DeletePath(model interface{}, path, format string) string { return path + "?format=html" } @@ -162,6 +166,10 @@ func (c *ConfigT) ReadPattern() PathPattern { return c.Handlers.PathPatterns[actions[ReadLabel]] } +func (c *ConfigT) UpdatePattern() PathPattern { + return c.Handlers.PathPatterns[actions[UpdateLabel]] +} + func (c *ConfigT) DeletePattern() PathPattern { return c.Handlers.PathPatterns[actions[DeleteLabel]] } @@ -180,6 +188,9 @@ func (c *ConfigT) query(model interface{}, action int, format string) url.Values tplContent = reflect.ModelNameLowerPlural(model) case ReadLabel: tplContent = reflect.ModelNameLowerPlural(model) + "_show" + case UpdateLabel: + tplContent = reflect.ModelNameLowerPlural(model) + "_add_update" + values.Add("update", "true") } values.Add("tpl_content", tplContent) diff --git a/errors/errors.go b/errors/errors.go index fa749a12..055783ea 100644 --- a/errors/errors.go +++ b/errors/errors.go @@ -19,7 +19,10 @@ func (e *Error) Error() string { var ( RecordExists = errors.New("Record already exists!") - NotAuthorized = errors.New(i18n.Authorization["notAuthorized"]["it"]) + NotAuthorized = &Error{ + TemplateName: "error_not_authorized", + Err: errors.New(i18n.Authorization["notAuthorized"]["it"]), + } SchoolExists = &Error{ TemplateName: "error_school_exists", diff --git a/handlers/handlers.go b/handlers/handlers.go index 44659f56..c5023b89 100644 --- a/handlers/handlers.go +++ b/handlers/handlers.go @@ -206,6 +206,20 @@ func (h *Handlers) NewReadRequest(model interface{}, path string, format string) return http.NewRequest("GET", h.Config.ReadPath(model, path, format), nil) } +func (h *Handlers) NewUpdateRequest(model interface{}, path string, format string, method string, form url.Values) (*http.Request, error) { + var ( + request *http.Request + err error + ) + switch method { + case "GET": + request, err = http.NewRequest("GET", h.Config.UpdatePath(model, path, format), nil) + case "POST": + request, err = http.NewRequest("POST", h.Config.UpdatePath(model, path, format), strings.NewReader(form.Encode())) + } + return request, err +} + func (h *Handlers) NewCreateRequest(model interface{}, path string, format string, method string, form url.Values) (*http.Request, error) { var ( request *http.Request @@ -401,6 +415,26 @@ func (h *Handlers) Create(model interface{}) http.Handler { return newRootMiddleware(h, fn) } +func (h *Handlers) Update(model interface{}) http.Handler { + fn := func(w http.ResponseWriter, r *http.Request) error { + switch r.Method { + case "GET": + err := h.get(w, r, reflect.ModelNameLowerPlural(model), h.Config.UpdatePattern()) + if err != nil { + return err + } + case "POST": + err := h.post(w, r, reflect.ModelNameLowerPlural(model), h.Config.UpdatePattern()) + if err != nil { + return err + } + } + return nil + } + + return newRootMiddleware(h, fn) +} + func (h *Handlers) ReadAll(model interface{}) http.Handler { fn := func(w http.ResponseWriter, r *http.Request) { h.get(w, r, reflect.ModelNameLowerPlural(model), h.Config.ReadAllPattern()) diff --git a/handlers/handlers_test.go b/handlers/handlers_test.go index 4d4e3faf..c15ae940 100644 --- a/handlers/handlers_test.go +++ b/handlers/handlers_test.go @@ -176,7 +176,7 @@ func (t *testSuite) BeforeAll() { panic(err) } - conf.LogLevel = config.LOG_LEVEL_OFF + conf.LogLevel = config.LOG_LEVEL_DEBUG // Initialize the ORM @@ -443,6 +443,61 @@ func (t *testSuite) TestSchoolSubscription() { } +func (t *testSuite) TestParticipantResponse() { + form := url.Values{} + form.Set("Singleresponses.0", "9") + + req, err := handlers.NewCreateRequest(&orm.School{}, "/responses/5/update", "html", "POST", form) + req.Header.Set("Content-Type", "application/x-www-form-urlencoded") + t.Nil(err) + + req, err = login(req, handlers, "RHOMAT9HZ", "9HzXOfJPje") + t.Nil(err) + + if !t.Failed() { + rr := httptest.NewRecorder() + + router := mux.NewRouter() + router.Handle("/responses/{id}/update", handlers.Update(&orm.Response{})) + router.ServeHTTP(rr, req) + + t.Equal(http.StatusSeeOther, rr.Code) + + if !t.Failed() { + req, err := handlers.NewReadRequest(&orm.Contest{}, "/responses/1", "html") + t.Nil(err) + + req, err = login(req, handlers, "admin", "admin") + t.Nil(err) + + rr = httptest.NewRecorder() + + router = mux.NewRouter() + router.Handle("/responses/{id}", handlers.Read(&orm.Response{})) + router.ServeHTTP(rr, req) + + t.Equal(http.StatusOK, rr.Code) + + log.Println(rr) + if !t.Failed() { + doc, err := goquery.NewDocumentFromReader(rr.Body) + if err != nil { + log.Fatal(err) + } + expected := "1" + ok := true + doc.Find("h1").Each(func(i int, s *goquery.Selection) { + if !strings.Contains(s.Text(), expected) { + ok = false + } + }) + t.True(ok) + } + } + } + +} + func (t *testSuite) TestUserModifier() { id, err := subscribeSchoolAsSchool() t.Nil(err) diff --git a/i18n/i18n.go b/i18n/i18n.go index 1cc325ff..32176f68 100644 --- a/i18n/i18n.go +++ b/i18n/i18n.go @@ -27,7 +27,7 @@ var ( "it": "Il tempo utile per consegnare la prova è scaduto.", }, "notAuthorized": map[string]string{ - "it": "Non si è autorizzati ad accedere a questa pagina", + "it": "Non si è autorizzati ad accedere a questa pagina.", }, "schoolExists": map[string]string{ "it": "Una scuola con questo codice meccanografico è già presente nella base dati!", diff --git a/orm/participant.go b/orm/participant.go index 45f3f1bd..ba25e762 100644 --- a/orm/participant.go +++ b/orm/participant.go @@ -261,6 +261,12 @@ func (model *Participant) Read(db *Database, args map[string]string, w http.Resp id := args["id"] + if isParticipant(r) { + if id != getModelIDFromToken(r) { + return nil, errors.NotAuthorized + } + } + // School user can access to its participants only! if isSchool(r) { if err := db._db.Preload("School").First(&participant, id).Error; err != nil { diff --git a/orm/response.go b/orm/response.go index a5244615..37084911 100644 --- a/orm/response.go +++ b/orm/response.go @@ -141,6 +141,12 @@ func (model *Response) Read(db *Database, args map[string]string, w http.Respons return nil, err } + if isParticipant(r) { + if strconv.Itoa(int(response.ParticipantID)) != getModelIDFromToken(r) { + return nil, errors.NotAuthorized + } + } + if response.AnswersIDs != "" { srIDs := strings.Split(response.AnswersIDs, " ") for _, srID := range srIDs { diff --git a/templates/error_not_authorized.html.tpl b/templates/error_not_authorized.html.tpl new file mode 100644 index 00000000..439c71cb --- /dev/null +++ b/templates/error_not_authorized.html.tpl @@ -0,0 +1,4 @@ +{{ define "content" }} +{{$options := `title: "Errore di autorizzazione"`}} +{{template "error" dict "options" ($options|yaml) "data" .Data}} +{{end}}