package main import ( "encoding/json" "strconv" "time" "github.com/julienschmidt/httprouter" ) func init() { router.POST("/api/surveys/:sid", apiAuthHandler(surveyAuthHandler(func(s Survey, u *User, body []byte) HTTPResponse { var responses []Response if err := json.Unmarshal(body, &responses); err != nil { return APIErrorResponse{err: err} } for _, response := range responses { if len(response.Answer) > 0 { if _, err := s.NewResponse(response.IdQuestion, u.Id, response.Answer); err != nil { return APIErrorResponse{err: err} } } } return APIResponse{true} }), loggedUser)) router.POST("/api/users/:uid/surveys/:sid", apiAuthHandler(func(u *User, ps httprouter.Params, body []byte) HTTPResponse { return surveyAuthHandler(func(s Survey, u *User, _ []byte) HTTPResponse { return userHandler(func(u User, _ []byte) HTTPResponse { var responses []Response if err := json.Unmarshal(body, &responses); err != nil { return APIErrorResponse{err: err} } for _, response := range responses { if len(response.Answer) > 0 { if _, err := s.NewResponse(response.IdQuestion, u.Id, response.Answer); err != nil { return APIErrorResponse{err: err} } } } return APIResponse{true} })(ps, body) })(u, ps, body) }, adminRestricted)) router.GET("/api/surveys/:sid/responses", apiAuthHandler(surveyAuthHandler( func(s Survey, u *User, _ []byte) HTTPResponse { return formatApiResponse(s.GetMyResponses(u, s.Corrected)) }), loggedUser)) router.GET("/api/users/:uid/surveys/:sid/responses", apiAuthHandler(func(u *User, ps httprouter.Params, body []byte) HTTPResponse { return surveyAuthHandler(func(s Survey, u *User, _ []byte) HTTPResponse { return userHandler(func(u User, _ []byte) HTTPResponse { return formatApiResponse(s.GetMyResponses(&u, s.Corrected)) })(ps, body) })(u, ps, body) }, adminRestricted)) router.GET("/api/surveys/:sid/responses/:rid", apiAuthHandler(responseAuthHandler( func(r Response, _ *User, _ []byte) HTTPResponse { return APIResponse{r} }), adminRestricted)) router.GET("/api/surveys/:sid/questions/:qid/responses", apiAuthHandler(questionAuthHandler( func(q Question, u *User, _ []byte) HTTPResponse { return formatApiResponse(q.GetResponses()) }), adminRestricted)) router.PUT("/api/surveys/:sid/questions/:qid/responses/:rid", apiAuthHandler(responseAuthHandler(func(current Response, u *User, body []byte) HTTPResponse { var new Response if err := json.Unmarshal(body, &new); err != nil { return APIErrorResponse{err: err} } if new.Score != nil && (current.Score == nil || *new.Score != *current.Score) { now := time.Now() new.IdCorrector = &u.Id new.TimeScored = &now } new.Id = current.Id new.IdUser = current.IdUser return formatApiResponse(new.Update()) }), adminRestricted)) } func responseHandler(f func(Response, []byte) HTTPResponse) func(httprouter.Params, []byte) HTTPResponse { return func(ps httprouter.Params, body []byte) HTTPResponse { var survey *Survey = nil if sid, err := strconv.Atoi(string(ps.ByName("sid"))); err == nil { if s, err := getSurvey(sid); err == nil { survey = &s } } if rid, err := strconv.Atoi(string(ps.ByName("rid"))); err != nil { return APIErrorResponse{err: err} } else if survey == nil { if response, err := getResponse(rid); err != nil { return APIErrorResponse{err: err} } else { return f(response, body) } } else { if response, err := survey.GetResponse(rid); err != nil { return APIErrorResponse{err: err} } else { return f(response, body) } } } } func responseAuthHandler(f func(Response, *User, []byte) HTTPResponse) func(*User, httprouter.Params, []byte) HTTPResponse { return func(u *User, ps httprouter.Params, body []byte) HTTPResponse { return responseHandler(func(r Response, body []byte) HTTPResponse { return f(r, u, body) })(ps, body) } } type Response struct { Id int64 `json:"id"` IdQuestion int64 `json:"id_question"` IdUser int64 `json:"id_user"` Answer string `json:"value"` TimeSubmit time.Time `json:"time_submit"` Score *int64 `json:"score,omitempty"` ScoreExplaination *string `json:"score_explaination,omitempty"` IdCorrector *int64 `json:"id_corrector,omitempty"` TimeScored *time.Time `json:"time_scored,omitempty"` } func (s *Survey) GetResponses() (responses []Response, err error) { if rows, errr := DBQuery("SELECT R.id_response, R.id_question, R.id_user, R.answer, R.time_submit, R.score, R.score_explanation, R.id_corrector, R.time_scored FROM survey_responses R INNER JOIN survey_quests Q ON Q.id_question = R.id_question WHERE Q.id_survey=?", s.Id); errr != nil { return nil, errr } else { defer rows.Close() for rows.Next() { var r Response if err = rows.Scan(&r.Id, &r.IdQuestion, &r.IdUser, &r.Answer, &r.TimeSubmit, &r.Score, &r.ScoreExplaination, &r.IdCorrector, &r.TimeScored); err != nil { return } responses = append(responses, r) } if err = rows.Err(); err != nil { return } return } } func (s *Survey) GetMyResponses(u *User, showScore bool) (responses []Response, err error) { if rows, errr := DBQuery("SELECT R.id_response, R.id_question, R.id_user, R.answer, R.time_submit, R.score, R.score_explanation, R.id_corrector, R.time_scored FROM survey_responses R INNER JOIN survey_quests Q ON Q.id_question = R.id_question WHERE Q.id_survey=? AND R.id_user=? ORDER BY time_submit DESC", s.Id, u.Id); errr != nil { return nil, errr } else { defer rows.Close() for rows.Next() { var r Response if err = rows.Scan(&r.Id, &r.IdQuestion, &r.IdUser, &r.Answer, &r.TimeSubmit, &r.Score, &r.ScoreExplaination, &r.IdCorrector, &r.TimeScored); err != nil { return } if !showScore { r.Score = nil r.ScoreExplaination = nil } responses = append(responses, r) } if err = rows.Err(); err != nil { return } return } } func (q *Question) GetResponses() (responses []Response, err error) { if rows, errr := DBQuery("SELECT id_response, id_question, S.id_user, answer, S.time_submit, score, score_explanation, id_corrector, time_scored FROM (SELECT id_user, MAX(time_submit) AS time_submit FROM survey_responses WHERE id_question=? GROUP BY id_user) R INNER JOIN survey_responses S ON S.id_user = R.id_user AND S.time_submit = R.time_submit AND S.id_question=?", q.Id, q.Id); errr != nil { return nil, errr } else { defer rows.Close() for rows.Next() { var r Response if err = rows.Scan(&r.Id, &r.IdQuestion, &r.IdUser, &r.Answer, &r.TimeSubmit, &r.Score, &r.ScoreExplaination, &r.IdCorrector, &r.TimeScored); err != nil { return } responses = append(responses, r) } if err = rows.Err(); err != nil { return } return } } func getResponse(id int) (r Response, err error) { err = DBQueryRow("SELECT id_response, id_question, id_user, answer, time_submit, score, score_explanation, id_corrector, time_scored FROM survey_responses WHERE id_response=?", id).Scan(&r.Id, &r.IdQuestion, &r.IdUser, &r.Answer, &r.TimeSubmit, &r.Score, &r.ScoreExplaination, &r.IdCorrector, &r.TimeScored) return } func (s *Survey) GetResponse(id int) (r Response, err error) { err = DBQueryRow("SELECT R.id_response, R.id_question, R.id_user, R.answer, R.time_submit, R.score, R.score_explanation, R.id_corrector, R.time_scored FROM survey_responses R INNER JOIN survey_quests Q ON Q.id_question = R.id_question WHERE R.id_response=? AND Q.id_survey=?", id, s.Id).Scan(&r.Id, &r.IdQuestion, &r.IdUser, &r.Answer, &r.TimeSubmit, &r.Score, &r.ScoreExplaination, &r.IdCorrector, &r.TimeScored) return } func (s *Survey) NewResponse(id_question int64, id_user int64, response string) (Response, error) { if res, err := DBExec("INSERT INTO survey_responses (id_question, id_user, answer, time_submit) VALUES (?, ?, ?, ?)", id_question, id_user, response, time.Now()); err != nil { return Response{}, err } else if rid, err := res.LastInsertId(); err != nil { return Response{}, err } else { return Response{rid, id_question, id_user, response, time.Now(), nil, nil, nil, nil}, nil } } func (r Response) Update() (Response, error) { _, err := DBExec("UPDATE survey_responses SET id_question = ?, id_user = ?, answer = ?, time_submit = ?, score = ?, score_explanation = ?, id_corrector = ?, time_scored = ? WHERE id_response = ?", r.IdQuestion, r.IdUser, r.Answer, r.TimeSubmit, r.Score, r.ScoreExplaination, r.IdCorrector, r.TimeScored, r.Id) return r, err } func (r Response) Delete() (int64, error) { if res, err := DBExec("DELETE FROM survey_responses WHERE id_response = ?", r.Id); err != nil { return 0, err } else if nb, err := res.RowsAffected(); err != nil { return 0, err } else { return nb, err } } func ClearResponses() (int64, error) { if res, err := DBExec("DELETE FROM survey_responses"); err != nil { return 0, err } else if nb, err := res.RowsAffected(); err != nil { return 0, err } else { return nb, err } }