diff --git a/questions.go b/questions.go index d742e1b..19a4a25 100644 --- a/questions.go +++ b/questions.go @@ -39,7 +39,7 @@ func declareAPIAuthQuestionsRoutes(router *gin.RouterGroup) { c.JSON(http.StatusOK, questions) } } else { - if s.Direct != nil && !u.IsAdmin { + if (!s.Shown || s.Direct != nil) && !u.IsAdmin { c.AbortWithStatusJSON(http.StatusForbidden, gin.H{"errmsg": "Not accessible"}) return } @@ -62,7 +62,24 @@ func declareAPIAuthQuestionsRoutes(router *gin.RouterGroup) { questionsRoutes.Use(questionHandler) questionsRoutes.GET("", func(c *gin.Context) { - c.JSON(http.StatusOK, c.MustGet("question").(*Question)) + q := c.MustGet("question").(*Question) + u := c.MustGet("LoggedUser").(*User) + + if !u.IsAdmin { + s, err := getSurvey(int(q.IdSurvey)) + if err != nil { + log.Println("Unable to getSurvey:", err) + c.AbortWithStatusJSON(http.StatusInternalServerError, gin.H{"errmsg": "An error occurs during survey retrieval. Please try again later."}) + return + } + + if !s.Shown || (s.Direct != nil && *s.Direct != q.Id) { + c.AbortWithStatusJSON(http.StatusForbidden, gin.H{"errmsg": "Not authorized"}) + return + } + } + + c.JSON(http.StatusOK, q) }) declareAPIAuthProposalsRoutes(questionsRoutes) @@ -154,8 +171,6 @@ func declareAPIAdminUserQuestionsRoutes(router *gin.RouterGroup) { } func questionHandler(c *gin.Context) { - u := c.MustGet("LoggedUser").(*User) - var survey *Survey if s, ok := c.Get("survey"); ok { survey = s.(*Survey) @@ -175,15 +190,6 @@ func questionHandler(c *gin.Context) { c.AbortWithStatusJSON(http.StatusNotFound, gin.H{"errmsg": "Question not found"}) return } - - s, err := getSurvey(int(question.IdSurvey)) - if err != nil { - log.Println("Unable to getSurvey:", err) - c.AbortWithStatusJSON(http.StatusInternalServerError, gin.H{"errmsg": "An error occurs during survey retrieval. Please try again later."}) - return - } - - survey = s } else { question, err = survey.GetQuestion(qid) if err != nil { @@ -192,15 +198,6 @@ func questionHandler(c *gin.Context) { } } - if !u.IsAdmin && (!survey.checkUserAccessToSurvey(u) || (survey.Direct != nil && *survey.Direct != question.Id)) { - c.AbortWithStatusJSON(http.StatusForbidden, gin.H{"errmsg": "Not authorized"}) - return - } - if !u.IsAdmin && survey.StartAvailability.After(time.Now()) { - c.AbortWithStatusJSON(http.StatusForbidden, gin.H{"errmsg": "Not accessible yet"}) - return - } - c.Set("question", question) c.Next() diff --git a/surveys.go b/surveys.go index 81a0185..48df3eb 100644 --- a/surveys.go +++ b/surveys.go @@ -62,22 +62,26 @@ func declareAPISurveysRoutes(router *gin.RouterGroup) { return } - c.JSON(http.StatusOK, c.MustGet("survey").(*Survey)) + s := c.MustGet("survey").(*Survey) + + if (s.Promo == u.Promo && (s.Group == "" || strings.Contains(u.Groups, ","+s.Group+",") && s.Shown)) || u.IsAdmin { + c.JSON(http.StatusOK, s) + } else { + c.AbortWithStatusJSON(http.StatusForbidden, gin.H{"errmsg": "Not accessible"}) + } }) } func declareAPIAuthSurveysRoutes(router *gin.RouterGroup) { surveysRoutes := router.Group("/surveys/:sid") surveysRoutes.Use(surveyHandler) - surveysRoutes.Use(surveyUserAccessHandler) surveysRoutes.GET("/score", func(c *gin.Context) { - loggedUser := c.MustGet("LoggedUser").(*User) var u *User if user, ok := c.Get("user"); ok { u = user.(*User) } else { - u = loggedUser + u = c.MustGet("LoggedUser").(*User) } s := c.MustGet("survey").(*Survey) @@ -89,29 +93,10 @@ func declareAPIAuthSurveysRoutes(router *gin.RouterGroup) { return } - if score != nil { - c.JSON(http.StatusOK, map[string]float64{"score": *score}) - } else if _, ok := c.Get("user"); !ok && loggedUser.IsAdmin { - // Admin retrieve mean score - scores, err := s.GetGrades() - if err != nil { - log.Printf("Unable to GetGrades(sid=%d): %s", s.Id, err.Error()) - c.AbortWithStatusJSON(http.StatusInternalServerError, gin.H{"errmsg": "An error occurs when trying to retrieve grades."}) - return - } - - *score = 0 - nbGrades := 0 - for _, s := range scores { - *score += *s - nbGrades += 1 - } - - *score /= float64(nbGrades) - - c.JSON(http.StatusOK, map[string]float64{"score": *score}) - } else { + if score == nil { c.JSON(http.StatusOK, map[string]string{"score": "N/A"}) + } else { + c.JSON(http.StatusOK, map[string]float64{"score": *score}) } } else { c.AbortWithStatusJSON(http.StatusForbidden, gin.H{"errmsg": "Not accessible"}) @@ -214,20 +199,18 @@ func surveyHandler(c *gin.Context) { } } -func (s *Survey) checkUserAccessToSurvey(u *User) bool { - return u.IsAdmin || (u.Promo == s.Promo && s.Shown && (s.Group == "" || strings.Contains(u.Groups, ","+s.Group+","))) -} - func surveyUserAccessHandler(c *gin.Context) { u := c.MustGet("LoggedUser").(*User) - s := c.MustGet("survey").(*Survey) + w := c.MustGet("survey").(*Survey) - if !s.checkUserAccessToSurvey(u) { + if u.IsAdmin { + c.Next() + } else if w.Shown && (w.Group == "" || strings.Contains(u.Groups, ","+w.Group+",")) { + c.Next() + } else { c.AbortWithStatusJSON(http.StatusNotFound, gin.H{"errmsg": "Survey not found."}) return } - - c.Next() } type Survey struct { diff --git a/ui/src/lib/components/AuthButton.svelte b/ui/src/components/AuthButton.svelte similarity index 100% rename from ui/src/lib/components/AuthButton.svelte rename to ui/src/components/AuthButton.svelte diff --git a/ui/src/lib/components/BuildState.svelte b/ui/src/components/BuildState.svelte similarity index 100% rename from ui/src/lib/components/BuildState.svelte rename to ui/src/components/BuildState.svelte diff --git a/ui/src/lib/components/Correction.svelte b/ui/src/components/Correction.svelte similarity index 100% rename from ui/src/lib/components/Correction.svelte rename to ui/src/components/Correction.svelte diff --git a/ui/src/lib/components/CorrectionPieChart.svelte b/ui/src/components/CorrectionPieChart.svelte similarity index 100% rename from ui/src/lib/components/CorrectionPieChart.svelte rename to ui/src/components/CorrectionPieChart.svelte diff --git a/ui/src/lib/components/CorrectionReference.svelte b/ui/src/components/CorrectionReference.svelte similarity index 98% rename from ui/src/lib/components/CorrectionReference.svelte rename to ui/src/components/CorrectionReference.svelte index 110f6f9..f1c51e1 100644 --- a/ui/src/lib/components/CorrectionReference.svelte +++ b/ui/src/components/CorrectionReference.svelte @@ -1,5 +1,5 @@ diff --git a/ui/src/lib/components/SubmissionStatus.svelte b/ui/src/components/SubmissionStatus.svelte similarity index 94% rename from ui/src/lib/components/SubmissionStatus.svelte rename to ui/src/components/SubmissionStatus.svelte index 5af55c9..b7ad14a 100644 --- a/ui/src/lib/components/SubmissionStatus.svelte +++ b/ui/src/components/SubmissionStatus.svelte @@ -1,8 +1,8 @@
diff --git a/ui/src/lib/components/UserKeys.svelte b/ui/src/components/UserKeys.svelte similarity index 97% rename from ui/src/lib/components/UserKeys.svelte rename to ui/src/components/UserKeys.svelte index f616b8e..7f383cb 100644 --- a/ui/src/lib/components/UserKeys.svelte +++ b/ui/src/components/UserKeys.svelte @@ -1,5 +1,5 @@ diff --git a/ui/src/lib/components/UserSurveys.svelte b/ui/src/components/UserSurveys.svelte similarity index 94% rename from ui/src/lib/components/UserSurveys.svelte rename to ui/src/components/UserSurveys.svelte index 5d9a8ed..dad0bb3 100644 --- a/ui/src/lib/components/UserSurveys.svelte +++ b/ui/src/components/UserSurveys.svelte @@ -1,8 +1,8 @@ diff --git a/ui/src/routes/grades/index.svelte b/ui/src/routes/grades/index.svelte index b016fbb..026f5ce 100644 --- a/ui/src/routes/grades/index.svelte +++ b/ui/src/routes/grades/index.svelte @@ -1,5 +1,5 @@ diff --git a/ui/src/routes/help.svelte b/ui/src/routes/help.svelte index e87598a..6b4a8c8 100644 --- a/ui/src/routes/help.svelte +++ b/ui/src/routes/help.svelte @@ -1,6 +1,6 @@
diff --git a/ui/src/routes/surveys/new.svelte b/ui/src/routes/surveys/new.svelte index 9aaf369..2a4f626 100644 --- a/ui/src/routes/surveys/new.svelte +++ b/ui/src/routes/surveys/new.svelte @@ -1,10 +1,10 @@ diff --git a/ui/src/routes/users/[uid]/index.svelte b/ui/src/routes/users/[uid]/index.svelte index d5c9e99..f6fbaee 100644 --- a/ui/src/routes/users/[uid]/index.svelte +++ b/ui/src/routes/users/[uid]/index.svelte @@ -9,11 +9,11 @@ diff --git a/ui/src/routes/works/new.svelte b/ui/src/routes/works/new.svelte index 3a635fb..efbcfd0 100644 --- a/ui/src/routes/works/new.svelte +++ b/ui/src/routes/works/new.svelte @@ -1,10 +1,10 @@ diff --git a/ui/src/lib/stores/toasts.js b/ui/src/stores/toasts.js similarity index 100% rename from ui/src/lib/stores/toasts.js rename to ui/src/stores/toasts.js diff --git a/ui/src/lib/stores/user.js b/ui/src/stores/user.js similarity index 100% rename from ui/src/lib/stores/user.js rename to ui/src/stores/user.js diff --git a/works.go b/works.go index 2ca25ee..3b0a106 100644 --- a/works.go +++ b/works.go @@ -43,11 +43,7 @@ func declareAPIWorksRoutes(router *gin.RouterGroup) { } else { for _, w := range works { if w.Group == "" || strings.Contains(u.Groups, ","+w.Group+",") { - // Remove informations not needed on front page for students - w.Promo = 0 w.Group = "" - w.DescriptionRaw = "" - response = append(response, w) } } @@ -83,10 +79,7 @@ func declareAPIWorksRoutes(router *gin.RouterGroup) { } else { for _, w := range works { if w.Group == "" || strings.Contains(u.Groups, ","+w.Group+",") { - // Remove informations not needed on front page for students - w.Promo = 0 w.Group = "" - response = append(response, w) } } @@ -200,7 +193,16 @@ func declareAPIAuthWorksRoutes(router *gin.RouterGroup) { worksRoutes.Use(workUserAccessHandler) worksRoutes.GET("", func(c *gin.Context) { - c.JSON(http.StatusOK, c.MustGet("work").(*Work)) + u := c.MustGet("LoggedUser").(*User) + w := c.MustGet("work").(*Work) + + if u.IsAdmin { + c.JSON(http.StatusOK, w) + } else if w.Shown && w.StartAvailability.Before(time.Now()) && (w.Group == "" || strings.Contains(u.Groups, ","+w.Group+",")) { + c.JSON(http.StatusOK, w) + } else { + c.AbortWithStatusJSON(http.StatusForbidden, gin.H{"errmsg": "Permission denied"}) + } }) // Grades related to works @@ -237,24 +239,18 @@ func workHandler(c *gin.Context) { } } -func (w *Work) checkUserAccessToWork(u *User) bool { - return u.IsAdmin || (u.Promo == w.Promo && w.Shown && (w.Group == "" || strings.Contains(u.Groups, ","+w.Group+","))) -} - func workUserAccessHandler(c *gin.Context) { u := c.MustGet("LoggedUser").(*User) w := c.MustGet("work").(*Work) - if !w.checkUserAccessToWork(u) { + if u.IsAdmin { + c.Next() + } else if w.Shown && (w.Group == "" || strings.Contains(u.Groups, ","+w.Group+",")) { + c.Next() + } else { c.AbortWithStatusJSON(http.StatusNotFound, gin.H{"errmsg": "Work not found."}) return } - if !u.IsAdmin && w.StartAvailability.After(time.Now()) { - c.AbortWithStatusJSON(http.StatusForbidden, gin.H{"errmsg": "Not accessible yet"}) - return - } - - c.Next() } type OneWork struct { @@ -295,14 +291,14 @@ func allWorks(cnd string, param ...interface{}) (items []*OneWork, err error) { type Work struct { Id int64 `json:"id"` Title string `json:"title"` - Promo uint `json:"promo,omitempty"` - Group string `json:"group,omitempty"` + Promo uint `json:"promo"` + Group string `json:"group"` Shown bool `json:"shown"` - Description string `json:"description,omitempty"` + Description string `json:"description"` DescriptionRaw string `json:"descr_raw,omitempty"` - Tag string `json:"tag,omitempty"` - SubmissionURL *string `json:"submission_url,omitempty"` - Corrected bool `json:"corrected,omitempty"` + Tag string `json:"tag"` + SubmissionURL *string `json:"submission_url"` + Corrected bool `json:"corrected"` StartAvailability time.Time `json:"start_availability"` EndAvailability time.Time `json:"end_availability"` }