Protect responses from participants
This commit is contained in:
parent
6c1550e7fe
commit
b06eba6698
8 changed files with 122 additions and 3 deletions
|
@ -146,6 +146,10 @@ func (c *ConfigT) CreatePath(model interface{}, path, format string) string {
|
||||||
return path + "?" + c.query(model, CreateLabel, format).Encode()
|
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 {
|
func (c *ConfigT) DeletePath(model interface{}, path, format string) string {
|
||||||
return path + "?format=html"
|
return path + "?format=html"
|
||||||
}
|
}
|
||||||
|
@ -162,6 +166,10 @@ func (c *ConfigT) ReadPattern() PathPattern {
|
||||||
return c.Handlers.PathPatterns[actions[ReadLabel]]
|
return c.Handlers.PathPatterns[actions[ReadLabel]]
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func (c *ConfigT) UpdatePattern() PathPattern {
|
||||||
|
return c.Handlers.PathPatterns[actions[UpdateLabel]]
|
||||||
|
}
|
||||||
|
|
||||||
func (c *ConfigT) DeletePattern() PathPattern {
|
func (c *ConfigT) DeletePattern() PathPattern {
|
||||||
return c.Handlers.PathPatterns[actions[DeleteLabel]]
|
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)
|
tplContent = reflect.ModelNameLowerPlural(model)
|
||||||
case ReadLabel:
|
case ReadLabel:
|
||||||
tplContent = reflect.ModelNameLowerPlural(model) + "_show"
|
tplContent = reflect.ModelNameLowerPlural(model) + "_show"
|
||||||
|
case UpdateLabel:
|
||||||
|
tplContent = reflect.ModelNameLowerPlural(model) + "_add_update"
|
||||||
|
values.Add("update", "true")
|
||||||
}
|
}
|
||||||
|
|
||||||
values.Add("tpl_content", tplContent)
|
values.Add("tpl_content", tplContent)
|
||||||
|
|
|
@ -19,7 +19,10 @@ func (e *Error) Error() string {
|
||||||
var (
|
var (
|
||||||
RecordExists = errors.New("Record already exists!")
|
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{
|
SchoolExists = &Error{
|
||||||
TemplateName: "error_school_exists",
|
TemplateName: "error_school_exists",
|
||||||
|
|
|
@ -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)
|
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) {
|
func (h *Handlers) NewCreateRequest(model interface{}, path string, format string, method string, form url.Values) (*http.Request, error) {
|
||||||
var (
|
var (
|
||||||
request *http.Request
|
request *http.Request
|
||||||
|
@ -401,6 +415,26 @@ func (h *Handlers) Create(model interface{}) http.Handler {
|
||||||
return newRootMiddleware(h, fn)
|
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 {
|
func (h *Handlers) ReadAll(model interface{}) http.Handler {
|
||||||
fn := func(w http.ResponseWriter, r *http.Request) {
|
fn := func(w http.ResponseWriter, r *http.Request) {
|
||||||
h.get(w, r, reflect.ModelNameLowerPlural(model), h.Config.ReadAllPattern())
|
h.get(w, r, reflect.ModelNameLowerPlural(model), h.Config.ReadAllPattern())
|
||||||
|
|
|
@ -176,7 +176,7 @@ func (t *testSuite) BeforeAll() {
|
||||||
panic(err)
|
panic(err)
|
||||||
}
|
}
|
||||||
|
|
||||||
conf.LogLevel = config.LOG_LEVEL_OFF
|
conf.LogLevel = config.LOG_LEVEL_DEBUG
|
||||||
|
|
||||||
// Initialize the ORM
|
// 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() {
|
func (t *testSuite) TestUserModifier() {
|
||||||
id, err := subscribeSchoolAsSchool()
|
id, err := subscribeSchoolAsSchool()
|
||||||
t.Nil(err)
|
t.Nil(err)
|
||||||
|
|
|
@ -27,7 +27,7 @@ var (
|
||||||
"it": "Il tempo utile per consegnare la prova è scaduto.",
|
"it": "Il tempo utile per consegnare la prova è scaduto.",
|
||||||
},
|
},
|
||||||
"notAuthorized": map[string]string{
|
"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{
|
"schoolExists": map[string]string{
|
||||||
"it": "Una scuola con questo codice meccanografico è già presente nella base dati!",
|
"it": "Una scuola con questo codice meccanografico è già presente nella base dati!",
|
||||||
|
|
|
@ -261,6 +261,12 @@ func (model *Participant) Read(db *Database, args map[string]string, w http.Resp
|
||||||
|
|
||||||
id := args["id"]
|
id := args["id"]
|
||||||
|
|
||||||
|
if isParticipant(r) {
|
||||||
|
if id != getModelIDFromToken(r) {
|
||||||
|
return nil, errors.NotAuthorized
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
// School user can access to its participants only!
|
// School user can access to its participants only!
|
||||||
if isSchool(r) {
|
if isSchool(r) {
|
||||||
if err := db._db.Preload("School").First(&participant, id).Error; err != nil {
|
if err := db._db.Preload("School").First(&participant, id).Error; err != nil {
|
||||||
|
|
|
@ -141,6 +141,12 @@ func (model *Response) Read(db *Database, args map[string]string, w http.Respons
|
||||||
return nil, err
|
return nil, err
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if isParticipant(r) {
|
||||||
|
if strconv.Itoa(int(response.ParticipantID)) != getModelIDFromToken(r) {
|
||||||
|
return nil, errors.NotAuthorized
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
if response.AnswersIDs != "" {
|
if response.AnswersIDs != "" {
|
||||||
srIDs := strings.Split(response.AnswersIDs, " ")
|
srIDs := strings.Split(response.AnswersIDs, " ")
|
||||||
for _, srID := range srIDs {
|
for _, srID := range srIDs {
|
||||||
|
|
4
templates/error_not_authorized.html.tpl
Normal file
4
templates/error_not_authorized.html.tpl
Normal file
|
@ -0,0 +1,4 @@
|
||||||
|
{{ define "content" }}
|
||||||
|
{{$options := `title: "Errore di autorizzazione"`}}
|
||||||
|
{{template "error" dict "options" ($options|yaml) "data" .Data}}
|
||||||
|
{{end}}
|
Loading…
Reference in a new issue