2016-12-08 08:12:18 +00:00
package api
import (
2020-01-23 13:23:02 +00:00
"fmt"
2022-05-16 09:38:46 +00:00
"log"
"net/http"
2023-03-20 10:23:27 +00:00
"reflect"
2022-05-16 09:38:46 +00:00
"strconv"
2017-01-05 01:21:32 +00:00
"strings"
2019-02-03 21:30:29 +00:00
"time"
2016-12-08 08:12:18 +00:00
2017-11-27 01:45:33 +00:00
"srs.epita.fr/fic-server/admin/sync"
2018-03-09 18:07:08 +00:00
"srs.epita.fr/fic-server/libfic"
2016-12-15 23:51:56 +00:00
2022-05-16 09:38:46 +00:00
"github.com/gin-gonic/gin"
2016-12-08 08:12:18 +00:00
)
2022-05-16 09:38:46 +00:00
func declareGlobalExercicesRoutes ( router * gin . RouterGroup ) {
router . GET ( "/resolutions.json" , exportResolutionMovies )
router . GET ( "/exercices_stats.json" , getExercicesStats )
2022-05-24 19:25:27 +00:00
router . GET ( "/tags" , listTags )
2022-05-16 09:38:46 +00:00
}
func declareExercicesRoutes ( router * gin . RouterGroup ) {
router . GET ( "/exercices" , listExercices )
2023-06-06 13:19:53 +00:00
router . POST ( "/exercices" , createExercice )
2022-05-16 09:38:46 +00:00
apiExercicesRoutes := router . Group ( "/exercices/:eid" )
apiExercicesRoutes . Use ( ExerciceHandler )
apiExercicesRoutes . GET ( "" , showExercice )
apiExercicesRoutes . PUT ( "" , updateExercice )
apiExercicesRoutes . PATCH ( "" , partUpdateExercice )
apiExercicesRoutes . DELETE ( "" , deleteExercice )
apiExercicesRoutes . GET ( "/stats.json" , getExerciceStats )
apiExercicesRoutes . GET ( "/history.json" , getExerciceHistory )
2024-03-17 10:20:38 +00:00
apiHistoryRoutes := apiExercicesRoutes . Group ( "/history.json" )
apiHistoryRoutes . Use ( AssigneeCookieHandler )
apiHistoryRoutes . PUT ( "" , appendExerciceHistory )
apiHistoryRoutes . PATCH ( "" , updateExerciceHistory )
apiHistoryRoutes . DELETE ( "" , delExerciceHistory )
2022-05-16 09:38:46 +00:00
apiExercicesRoutes . GET ( "/hints" , listExerciceHints )
apiExercicesRoutes . POST ( "/hints" , createExerciceHint )
apiHintsRoutes := apiExercicesRoutes . Group ( "/hints/:hid" )
apiHintsRoutes . Use ( HintHandler )
apiHintsRoutes . GET ( "" , showExerciceHint )
apiHintsRoutes . PUT ( "" , updateExerciceHint )
apiHintsRoutes . DELETE ( "" , deleteExerciceHint )
apiHintsRoutes . GET ( "/dependancies" , showExerciceHintDeps )
apiExercicesRoutes . GET ( "/flags" , listExerciceFlags )
apiExercicesRoutes . POST ( "/flags" , createExerciceFlag )
apiFlagsRoutes := apiExercicesRoutes . Group ( "/flags/:kid" )
apiFlagsRoutes . Use ( FlagKeyHandler )
apiFlagsRoutes . GET ( "" , showExerciceFlag )
apiFlagsRoutes . PUT ( "" , updateExerciceFlag )
apiFlagsRoutes . POST ( "/try" , tryExerciceFlag )
apiFlagsRoutes . DELETE ( "/" , deleteExerciceFlag )
apiFlagsRoutes . GET ( "/dependancies" , showExerciceFlagDeps )
apiFlagsRoutes . GET ( "/choices/" , listFlagChoices )
apiFlagsChoicesRoutes := apiExercicesRoutes . Group ( "/choices/:cid" )
apiFlagsChoicesRoutes . Use ( FlagChoiceHandler )
apiFlagsChoicesRoutes . GET ( "" , showFlagChoice )
apiFlagsRoutes . POST ( "/choices/" , createFlagChoice )
apiFlagsChoicesRoutes . PUT ( "" , updateFlagChoice )
apiFlagsChoicesRoutes . DELETE ( "" , deleteFlagChoice )
apiQuizRoutes := apiExercicesRoutes . Group ( "/quiz/:qid" )
apiQuizRoutes . Use ( FlagQuizHandler )
apiExercicesRoutes . GET ( "/quiz" , listExerciceQuiz )
apiQuizRoutes . GET ( "" , showExerciceQuiz )
apiQuizRoutes . PUT ( "" , updateExerciceQuiz )
apiQuizRoutes . DELETE ( "" , deleteExerciceQuiz )
apiQuizRoutes . GET ( "/dependancies" , showExerciceQuizDeps )
apiExercicesRoutes . GET ( "/tags" , listExerciceTags )
apiExercicesRoutes . POST ( "/tags" , addExerciceTag )
apiExercicesRoutes . PUT ( "/tags" , updateExerciceTags )
declareFilesRoutes ( apiExercicesRoutes )
declareExerciceClaimsRoutes ( apiExercicesRoutes )
2018-11-18 21:44:23 +00:00
2019-09-06 23:25:42 +00:00
// Remote
2022-05-16 09:38:46 +00:00
router . GET ( "/remote/themes/:thid/exercices/:exid" , sync . ApiGetRemoteExercice )
router . GET ( "/remote/themes/:thid/exercices/:exid/hints" , sync . ApiGetRemoteExerciceHints )
router . GET ( "/remote/themes/:thid/exercices/:exid/flags" , sync . ApiGetRemoteExerciceFlags )
}
2022-05-24 19:25:51 +00:00
type Exercice struct {
* fic . Exercice
ForgeLink string ` json:"forge_link,omitempty" `
}
2022-05-16 09:38:46 +00:00
func ExerciceHandler ( c * gin . Context ) {
eid , err := strconv . ParseInt ( string ( c . Params . ByName ( "eid" ) ) , 10 , 32 )
if err != nil {
c . AbortWithStatusJSON ( http . StatusBadRequest , gin . H { "errmsg" : "Invalid exercice identifier" } )
return
}
var exercice * fic . Exercice
if theme , exists := c . Get ( "theme" ) ; exists {
exercice , err = theme . ( * fic . Theme ) . GetExercice ( int ( eid ) )
if err != nil {
c . AbortWithStatusJSON ( http . StatusNotFound , gin . H { "errmsg" : "Exercice not found" } )
return
}
} else {
exercice , err = fic . GetExercice ( eid )
if err != nil {
c . AbortWithStatusJSON ( http . StatusNotFound , gin . H { "errmsg" : "Exercice not found" } )
return
}
2022-10-29 15:03:57 +00:00
2024-03-15 16:46:50 +00:00
if exercice . IdTheme != nil {
theme , err = exercice . GetTheme ( )
if err != nil {
c . AbortWithStatusJSON ( http . StatusInternalServerError , gin . H { "errmsg" : "Unable to find the attached theme." } )
return
}
c . Set ( "theme" , theme )
} else {
c . Set ( "theme" , & fic . Theme { Path : sync . StandaloneExercicesDirectory } )
2022-10-29 15:03:57 +00:00
}
2022-05-16 09:38:46 +00:00
}
c . Set ( "exercice" , exercice )
c . Next ( )
}
func HintHandler ( c * gin . Context ) {
hid , err := strconv . ParseInt ( string ( c . Params . ByName ( "hid" ) ) , 10 , 32 )
if err != nil {
c . AbortWithStatusJSON ( http . StatusBadRequest , gin . H { "errmsg" : "Invalid hint identifier" } )
return
}
exercice := c . MustGet ( "exercice" ) . ( * fic . Exercice )
hint , err := exercice . GetHint ( hid )
if err != nil {
c . AbortWithStatusJSON ( http . StatusNotFound , gin . H { "errmsg" : "Hint not found" } )
return
}
c . Set ( "hint" , hint )
c . Next ( )
}
func FlagKeyHandler ( c * gin . Context ) {
kid , err := strconv . ParseInt ( string ( c . Params . ByName ( "kid" ) ) , 10 , 32 )
if err != nil {
c . AbortWithStatusJSON ( http . StatusBadRequest , gin . H { "errmsg" : "Invalid flag identifier" } )
return
}
var flag * fic . FlagKey
if exercice , exists := c . Get ( "exercice" ) ; exists {
flag , err = exercice . ( * fic . Exercice ) . GetFlagKey ( int ( kid ) )
if err != nil {
c . AbortWithStatusJSON ( http . StatusNotFound , gin . H { "errmsg" : "Flag not found" } )
return
}
} else {
flag , err = fic . GetFlagKey ( int ( kid ) )
if err != nil {
c . AbortWithStatusJSON ( http . StatusNotFound , gin . H { "errmsg" : "Flag not found" } )
return
}
}
c . Set ( "flag-key" , flag )
c . Next ( )
}
func FlagChoiceHandler ( c * gin . Context ) {
cid , err := strconv . ParseInt ( string ( c . Params . ByName ( "cid" ) ) , 10 , 32 )
if err != nil {
c . AbortWithStatusJSON ( http . StatusBadRequest , gin . H { "errmsg" : "Invalid choice identifier" } )
return
}
flagkey := c . MustGet ( "flag-key" ) . ( * fic . FlagKey )
choice , err := flagkey . GetChoice ( int ( cid ) )
if err != nil {
c . AbortWithStatusJSON ( http . StatusNotFound , gin . H { "errmsg" : "Choice not found" } )
return
}
c . Set ( "flag-choice" , choice )
c . Next ( )
}
func FlagQuizHandler ( c * gin . Context ) {
qid , err := strconv . ParseInt ( string ( c . Params . ByName ( "qid" ) ) , 10 , 64 )
if err != nil {
c . AbortWithStatusJSON ( http . StatusBadRequest , gin . H { "errmsg" : "Invalid quiz identifier" } )
return
}
var quiz * fic . MCQ
if exercice , exists := c . Get ( "exercice" ) ; exists {
quiz , err = exercice . ( * fic . Exercice ) . GetMCQById ( int ( qid ) )
if err != nil {
c . AbortWithStatusJSON ( http . StatusNotFound , gin . H { "errmsg" : "Quiz not found" } )
return
}
} else {
quiz , err = fic . GetMCQ ( int ( qid ) )
if err != nil {
c . AbortWithStatusJSON ( http . StatusNotFound , gin . H { "errmsg" : "Quiz not found" } )
return
}
}
c . Set ( "flag-quiz" , quiz )
c . Next ( )
2016-12-08 08:12:18 +00:00
}
2022-05-16 09:38:46 +00:00
func listExercices ( c * gin . Context ) {
if theme , exists := c . Get ( "theme" ) ; exists {
exercices , err := theme . ( * fic . Theme ) . GetExercices ( )
if err != nil {
log . Println ( "Unable to listThemedExercices:" , err . Error ( ) )
c . AbortWithStatusJSON ( http . StatusInternalServerError , gin . H { "errmsg" : "An error occurs during exercices listing." } )
return
}
c . JSON ( http . StatusOK , exercices )
} else {
exercices , err := fic . GetExercices ( )
if err != nil {
log . Println ( "Unable to listThemedExercices:" , err . Error ( ) )
c . AbortWithStatusJSON ( http . StatusInternalServerError , gin . H { "errmsg" : "An error occurs during exercices listing." } )
return
}
c . JSON ( http . StatusOK , exercices )
}
2016-12-08 08:12:18 +00:00
}
2022-05-24 19:25:27 +00:00
func listTags ( c * gin . Context ) {
exercices , err := fic . GetExercices ( )
if err != nil {
c . AbortWithStatusJSON ( http . StatusInternalServerError , gin . H { "errmsg" : err . Error ( ) } )
return
}
ret := map [ string ] [ ] * fic . Exercice { }
for _ , exercice := range exercices {
tags , err := exercice . GetTags ( )
if err != nil {
c . AbortWithStatusJSON ( http . StatusInternalServerError , gin . H { "errmsg" : err . Error ( ) } )
return
}
for _ , t := range tags {
if _ , ok := ret [ t ] ; ! ok {
ret [ t ] = [ ] * fic . Exercice { }
}
ret [ t ] = append ( ret [ t ] , exercice )
}
}
c . JSON ( http . StatusOK , ret )
}
2019-01-25 15:31:48 +00:00
// Generate the csv to export with:
2023-06-14 15:11:21 +00:00
//
// curl -s http://127.0.0.1:8081/api/resolutions.json | jq -r ".[] | [ .theme,.level,.title, @uri \"https://fic.srs.epita.fr/$(date +%Y)/\\(.videoURI)\" ] | join(\";\")"
2022-05-16 09:38:46 +00:00
func exportResolutionMovies ( c * gin . Context ) {
exercices , err := fic . GetExercices ( )
if err != nil {
c . AbortWithStatusJSON ( http . StatusInternalServerError , gin . H { "errmsg" : err . Error ( ) } )
return
}
export := [ ] map [ string ] string { }
for _ , exercice := range exercices {
2024-03-12 09:12:40 +00:00
var tname string
if exercice . IdTheme != nil {
theme , err := fic . GetTheme ( * exercice . IdTheme )
if err != nil {
c . AbortWithStatusJSON ( http . StatusInternalServerError , gin . H { "errmsg" : err . Error ( ) } )
return
}
tname = theme . Name
}
if len ( exercice . VideoURI ) > 0 {
2022-06-19 22:08:07 +00:00
level , _ := exercice . GetLevel ( )
2022-05-16 09:38:46 +00:00
export = append ( export , map [ string ] string {
2022-06-19 22:08:07 +00:00
"videoURI" : strings . Replace ( exercice . VideoURI , "$FILES$/" , "files/" , 1 ) ,
2024-03-12 09:12:40 +00:00
"theme" : tname ,
2022-05-16 09:38:46 +00:00
"title" : exercice . Title ,
2022-06-19 22:08:07 +00:00
"level" : fmt . Sprintf ( "%d" , level ) ,
2022-05-16 09:38:46 +00:00
} )
2019-01-25 15:31:48 +00:00
}
}
2022-05-16 09:38:46 +00:00
c . JSON ( http . StatusOK , export )
2019-01-25 15:31:48 +00:00
}
2020-04-15 05:39:38 +00:00
func loadFlags ( n func ( ) ( [ ] fic . Flag , error ) ) ( interface { } , error ) {
2020-01-23 13:23:02 +00:00
if flags , err := n ( ) ; err != nil {
return nil , err
} else {
var ret [ ] fic . Flag
for _ , flag := range flags {
2021-11-22 14:35:07 +00:00
if f , ok := flag . ( * fic . FlagKey ) ; ok {
2020-01-23 13:23:02 +00:00
if k , err := fic . GetFlagKey ( f . Id ) ; err != nil {
return nil , err
} else {
ret = append ( ret , k )
}
2021-11-22 14:35:07 +00:00
} else if f , ok := flag . ( * fic . MCQ ) ; ok {
2020-01-23 13:23:02 +00:00
if m , err := fic . GetMCQ ( f . Id ) ; err != nil {
return nil , err
} else {
ret = append ( ret , m )
}
} else {
2020-04-15 05:39:38 +00:00
return nil , fmt . Errorf ( "Flag type %T not implemented for this flag." , f )
2020-01-23 13:23:02 +00:00
}
}
return ret , nil
}
}
2022-05-16 09:38:46 +00:00
func listExerciceHints ( c * gin . Context ) {
exercice := c . MustGet ( "exercice" ) . ( * fic . Exercice )
hints , err := exercice . GetHints ( )
if err != nil {
log . Println ( "Unable to listExerciceHints:" , err . Error ( ) )
c . AbortWithStatusJSON ( http . StatusInternalServerError , gin . H { "errmsg" : "An error occurs when retrieving hints" } )
return
}
c . JSON ( http . StatusOK , hints )
2016-12-08 08:12:18 +00:00
}
2022-05-16 09:38:46 +00:00
func listExerciceFlags ( c * gin . Context ) {
exercice := c . MustGet ( "exercice" ) . ( * fic . Exercice )
flags , err := exercice . GetFlagKeys ( )
if err != nil {
log . Println ( "Unable to listExerciceFlags:" , err . Error ( ) )
c . AbortWithStatusJSON ( http . StatusInternalServerError , gin . H { "errmsg" : "An error occurs when retrieving exercice flags" } )
return
}
c . JSON ( http . StatusOK , flags )
2016-12-08 08:12:18 +00:00
}
2022-05-16 09:38:46 +00:00
func listFlagChoices ( c * gin . Context ) {
flag := c . MustGet ( "flag-key" ) . ( * fic . FlagKey )
choices , err := flag . GetChoices ( )
if err != nil {
log . Println ( "Unable to listFlagChoices:" , err . Error ( ) )
c . AbortWithStatusJSON ( http . StatusInternalServerError , gin . H { "errmsg" : "An error occurs when retrieving flag choices" } )
return
}
c . JSON ( http . StatusOK , choices )
2018-11-21 03:10:22 +00:00
}
2022-05-16 09:38:46 +00:00
func listExerciceQuiz ( c * gin . Context ) {
exercice := c . MustGet ( "exercice" ) . ( * fic . Exercice )
quiz , err := exercice . GetMCQ ( )
if err != nil {
log . Println ( "Unable to listExerciceQuiz:" , err . Error ( ) )
c . AbortWithStatusJSON ( http . StatusInternalServerError , gin . H { "errmsg" : "An error occurs when retrieving quiz list" } )
return
}
c . JSON ( http . StatusOK , quiz )
2017-12-17 01:50:01 +00:00
}
2022-05-16 09:38:46 +00:00
func showExercice ( c * gin . Context ) {
2022-05-24 19:25:51 +00:00
exercice := c . MustGet ( "exercice" ) . ( * fic . Exercice )
var forgelink string
if fli , ok := sync . GlobalImporter . ( sync . ForgeLinkedImporter ) ; ok {
if u , _ := fli . GetExerciceLink ( exercice ) ; u != nil {
forgelink = u . String ( )
}
}
c . JSON ( http . StatusOK , Exercice { exercice , forgelink } )
2016-12-26 00:14:46 +00:00
}
2016-12-08 08:12:18 +00:00
2022-05-16 09:38:46 +00:00
func getExerciceHistory ( c * gin . Context ) {
exercice := c . MustGet ( "exercice" ) . ( * fic . Exercice )
history , err := exercice . GetHistory ( )
if err != nil {
log . Println ( "Unable to getExerciceHistory:" , err . Error ( ) )
c . AbortWithStatusJSON ( http . StatusInternalServerError , gin . H { "errmsg" : "An error occurs when retrieving exercice history" } )
return
}
c . JSON ( http . StatusOK , history )
2019-02-03 21:30:29 +00:00
}
2020-01-28 13:01:13 +00:00
type exerciceStats struct {
2020-01-29 14:57:34 +00:00
IdExercice int64 ` json:"id_exercice,omitempty" `
TeamTries int64 ` json:"team_tries" `
TotalTries int64 ` json:"total_tries" `
SolvedCount int64 ` json:"solved_count" `
FlagSolved [ ] int64 ` json:"flag_solved" `
MCQSolved [ ] int64 ` json:"mcq_solved" `
2023-04-01 15:11:40 +00:00
CurrentGain int64 ` json:"current_gain" `
2020-01-28 13:01:13 +00:00
}
2022-05-16 09:38:46 +00:00
func getExerciceStats ( c * gin . Context ) {
e := c . MustGet ( "exercice" ) . ( * fic . Exercice )
2023-04-01 15:11:40 +00:00
current_gain := e . Gain
if fic . DiscountedFactor > 0 {
decoted_exercice , err := fic . GetDiscountedExercice ( e . Id )
if err == nil {
current_gain = decoted_exercice . Gain
} else {
log . Println ( "Unable to fetch decotedExercice:" , err . Error ( ) )
}
}
2022-05-16 09:38:46 +00:00
c . JSON ( http . StatusOK , exerciceStats {
2020-04-15 05:39:38 +00:00
TeamTries : e . TriedTeamCount ( ) ,
TotalTries : e . TriedCount ( ) ,
2020-01-28 13:01:13 +00:00
SolvedCount : e . SolvedCount ( ) ,
2020-04-15 05:39:38 +00:00
FlagSolved : e . FlagSolved ( ) ,
MCQSolved : e . MCQSolved ( ) ,
2023-04-01 15:11:40 +00:00
CurrentGain : current_gain ,
2022-05-16 09:38:46 +00:00
} )
2020-01-28 13:01:13 +00:00
}
2022-05-16 09:38:46 +00:00
func getExercicesStats ( c * gin . Context ) {
2023-04-01 15:11:40 +00:00
exercices , err := fic . GetDiscountedExercices ( )
2022-05-16 09:38:46 +00:00
if err != nil {
c . AbortWithStatusJSON ( http . StatusInternalServerError , gin . H { "errmsg" : err . Error ( ) } )
2023-06-14 16:46:30 +00:00
return
2020-01-29 14:57:34 +00:00
}
2022-05-16 09:38:46 +00:00
ret := [ ] exerciceStats { }
for _ , e := range exercices {
ret = append ( ret , exerciceStats {
IdExercice : e . Id ,
TeamTries : e . TriedTeamCount ( ) ,
TotalTries : e . TriedCount ( ) ,
SolvedCount : e . SolvedCount ( ) ,
FlagSolved : e . FlagSolved ( ) ,
MCQSolved : e . MCQSolved ( ) ,
2023-04-01 15:11:40 +00:00
CurrentGain : e . Gain ,
2022-05-16 09:38:46 +00:00
} )
}
c . JSON ( http . StatusOK , ret )
2020-01-29 14:57:34 +00:00
}
2024-03-17 10:20:38 +00:00
func AssigneeCookieHandler ( c * gin . Context ) {
myassignee , err := c . Cookie ( "myassignee" )
if err != nil {
c . AbortWithStatusJSON ( http . StatusBadRequest , gin . H { "errmsg" : "You must be authenticated to perform this action." } )
return
}
aid , err := strconv . ParseInt ( myassignee , 10 , 32 )
if err != nil {
c . AbortWithStatusJSON ( http . StatusBadRequest , gin . H { "errmsg" : "You must be authenticated to perform this action: invalid assignee identifier." } )
return
}
assignee , err := fic . GetAssignee ( aid )
if err != nil {
c . AbortWithStatusJSON ( http . StatusBadRequest , gin . H { "errmsg" : "You must be authenticated to perform this action: assignee not found." } )
return
}
c . Set ( "assignee" , assignee )
c . Next ( )
}
2019-02-03 21:30:29 +00:00
type uploadedExerciceHistory struct {
2019-07-05 20:28:56 +00:00
IdTeam int64 ` json:"team_id" `
2019-02-03 21:30:29 +00:00
Kind string
Time time . Time
Secondary * int64
2019-07-12 17:17:17 +00:00
Coeff float32
}
2024-03-17 09:19:35 +00:00
func appendExerciceHistory ( c * gin . Context ) {
exercice := c . MustGet ( "exercice" ) . ( * fic . Exercice )
2024-03-17 10:20:38 +00:00
myassignee := c . MustGet ( "assignee" ) . ( * fic . ClaimAssignee )
2024-03-17 09:19:35 +00:00
var uh uploadedExerciceHistory
err := c . ShouldBindJSON ( & uh )
if err != nil {
c . AbortWithStatusJSON ( http . StatusBadRequest , gin . H { "errmsg" : err . Error ( ) } )
return
}
err = exercice . AppendHistoryItem ( uh . IdTeam , uh . Kind , uh . Secondary )
if err != nil {
log . Println ( "Unable to appendExerciceHistory:" , err . Error ( ) )
c . AbortWithStatusJSON ( http . StatusInternalServerError , gin . H { "errmsg" : "An error occurs during history moditication." } )
return
}
2024-03-17 10:20:38 +00:00
log . Printf ( "AUDIT: %s performs an history append: %s for team %d, exercice %d and optional %v" , myassignee . Name , uh . Kind , uh . IdTeam , exercice . Id , uh . Secondary )
2024-03-17 09:19:35 +00:00
c . JSON ( http . StatusOK , uh )
}
2022-05-16 09:38:46 +00:00
func updateExerciceHistory ( c * gin . Context ) {
exercice := c . MustGet ( "exercice" ) . ( * fic . Exercice )
2024-03-17 10:20:38 +00:00
myassignee := c . MustGet ( "assignee" ) . ( * fic . ClaimAssignee )
2022-05-16 09:38:46 +00:00
2019-07-12 17:17:17 +00:00
var uh uploadedExerciceHistory
2022-05-16 09:38:46 +00:00
err := c . ShouldBindJSON ( & uh )
if err != nil {
c . AbortWithStatusJSON ( http . StatusBadRequest , gin . H { "errmsg" : err . Error ( ) } )
return
2019-07-12 17:17:17 +00:00
}
2022-05-16 09:38:46 +00:00
_ , err = exercice . UpdateHistoryItem ( uh . Coeff , uh . IdTeam , uh . Kind , uh . Time , uh . Secondary )
if err != nil {
log . Println ( "Unable to updateExerciceHistory:" , err . Error ( ) )
c . AbortWithStatusJSON ( http . StatusInternalServerError , gin . H { "errmsg" : "An error occurs during history update." } )
return
}
2024-03-17 10:20:38 +00:00
log . Printf ( "AUDIT: %s performs an history update: %s for team %d, exercice %d and optional %v, with coeff %f" , myassignee . Name , uh . Kind , uh . IdTeam , exercice . Id , uh . Secondary , uh . Coeff )
2022-05-16 09:38:46 +00:00
c . JSON ( http . StatusOK , uh )
2019-02-03 21:30:29 +00:00
}
2022-05-16 09:38:46 +00:00
func delExerciceHistory ( c * gin . Context ) {
exercice := c . MustGet ( "exercice" ) . ( * fic . Exercice )
2024-03-17 10:20:38 +00:00
myassignee := c . MustGet ( "assignee" ) . ( * fic . ClaimAssignee )
2022-05-16 09:38:46 +00:00
2019-02-03 21:30:29 +00:00
var uh uploadedExerciceHistory
2022-05-16 09:38:46 +00:00
err := c . ShouldBindJSON ( & uh )
if err != nil {
c . AbortWithStatusJSON ( http . StatusBadRequest , gin . H { "errmsg" : err . Error ( ) } )
return
}
_ , err = exercice . DelHistoryItem ( uh . IdTeam , uh . Kind , uh . Time , uh . Secondary )
if err != nil {
log . Println ( "Unable to delExerciceHistory:" , err . Error ( ) )
c . AbortWithStatusJSON ( http . StatusInternalServerError , gin . H { "errmsg" : "An error occurs during history deletion." } )
return
2019-02-03 21:30:29 +00:00
}
2024-03-17 10:20:38 +00:00
log . Printf ( "AUDIT: %s performs an history deletion: %s for team %d, exercice %d and optional %v" , myassignee . Name , uh . Kind , uh . IdTeam , exercice . Id , uh . Secondary )
2019-02-03 21:30:29 +00:00
2022-05-16 09:38:46 +00:00
c . JSON ( http . StatusOK , true )
2019-02-03 21:30:29 +00:00
}
2022-05-16 09:38:46 +00:00
func deleteExercice ( c * gin . Context ) {
exercice := c . MustGet ( "exercice" ) . ( * fic . Exercice )
_ , err := exercice . DeleteCascade ( )
if err != nil {
log . Println ( "Unable to deleteExercice:" , err . Error ( ) )
c . AbortWithStatusJSON ( http . StatusBadRequest , gin . H { "errmsg" : "An error occurs during exercice deletion" } )
return
}
c . JSON ( http . StatusOK , true )
2016-12-26 00:14:46 +00:00
}
2016-12-08 08:12:18 +00:00
2022-05-16 09:38:46 +00:00
func updateExercice ( c * gin . Context ) {
exercice := c . MustGet ( "exercice" ) . ( * fic . Exercice )
2016-12-26 00:14:46 +00:00
var ue fic . Exercice
2022-05-16 09:38:46 +00:00
err := c . ShouldBindJSON ( & ue )
if err != nil {
c . AbortWithStatusJSON ( http . StatusBadRequest , gin . H { "errmsg" : err . Error ( ) } )
return
2016-12-26 00:14:46 +00:00
}
2016-12-08 08:12:18 +00:00
2016-12-26 00:14:46 +00:00
ue . Id = exercice . Id
2016-12-08 08:12:18 +00:00
2016-12-26 00:14:46 +00:00
if len ( ue . Title ) == 0 {
2022-05-16 09:38:46 +00:00
c . AbortWithStatusJSON ( http . StatusBadRequest , gin . H { "errmsg" : "Exercice's title not filled" } )
return
2016-12-26 00:14:46 +00:00
}
if _ , err := ue . Update ( ) ; err != nil {
2022-05-16 09:38:46 +00:00
log . Println ( "Unable to updateExercice:" , err . Error ( ) )
c . AbortWithStatusJSON ( http . StatusBadRequest , gin . H { "errmsg" : "An error occurs during exercice update" } )
return
2016-12-08 08:12:18 +00:00
}
2016-12-26 00:14:46 +00:00
2022-05-16 09:38:46 +00:00
c . JSON ( http . StatusOK , ue )
2016-12-08 08:12:18 +00:00
}
2023-03-20 10:23:27 +00:00
type patchExercice struct {
Language * string ` json:"lang,omitempty" `
Title * string ` json:"title" `
Disabled * bool ` json:"disabled" `
WIP * bool ` json:"wip" `
URLId * string ` json:"urlid" `
Statement * string ` json:"statement" `
Overview * string ` json:"overview" `
Headline * string ` json:"headline" `
Finished * string ` json:"finished" `
Issue * string ` json:"issue" `
IssueKind * string ` json:"issuekind" `
Gain * int64 ` json:"gain" `
Coefficient * float64 ` json:"coefficient" `
}
2022-05-16 09:38:46 +00:00
func partUpdateExercice ( c * gin . Context ) {
exercice := c . MustGet ( "exercice" ) . ( * fic . Exercice )
2023-03-20 10:23:27 +00:00
var ue patchExercice
2022-05-16 09:38:46 +00:00
err := c . ShouldBindJSON ( & ue )
if err != nil {
c . AbortWithStatusJSON ( http . StatusBadRequest , gin . H { "errmsg" : err . Error ( ) } )
return
2018-11-21 00:19:13 +00:00
}
2023-03-20 10:23:27 +00:00
for _ , field := range reflect . VisibleFields ( reflect . TypeOf ( ue ) ) {
if ! reflect . ValueOf ( ue ) . FieldByName ( field . Name ) . IsNil ( ) {
reflect . ValueOf ( exercice ) . Elem ( ) . FieldByName ( field . Name ) . Set ( reflect . ValueOf ( reflect . ValueOf ( ue ) . FieldByName ( field . Name ) . Elem ( ) . Interface ( ) ) )
}
2018-11-21 00:19:13 +00:00
}
if _ , err := exercice . Update ( ) ; err != nil {
2022-05-16 09:38:46 +00:00
log . Println ( "Unable to partUpdateExercice:" , err . Error ( ) )
c . AbortWithStatusJSON ( http . StatusInternalServerError , gin . H { "errmsg" : "An error occurs during exercice update." } )
return
2018-11-21 00:19:13 +00:00
}
2022-05-16 09:38:46 +00:00
c . JSON ( http . StatusOK , exercice )
2018-11-21 00:19:13 +00:00
}
2022-05-16 09:38:46 +00:00
func createExercice ( c * gin . Context ) {
theme := c . MustGet ( "theme" ) . ( * fic . Theme )
2016-12-08 08:12:18 +00:00
// Create a new exercice
2016-12-26 00:14:46 +00:00
var ue fic . Exercice
2022-05-16 09:38:46 +00:00
err := c . ShouldBindJSON ( & ue )
if err != nil {
c . AbortWithStatusJSON ( http . StatusBadRequest , gin . H { "errmsg" : err . Error ( ) } )
return
2016-12-08 08:12:18 +00:00
}
if len ( ue . Title ) == 0 {
2022-05-16 09:38:46 +00:00
c . AbortWithStatusJSON ( http . StatusBadRequest , gin . H { "errmsg" : "Title not filled" } )
return
2016-12-08 08:12:18 +00:00
}
var depend * fic . Exercice = nil
if ue . Depend != nil {
if d , err := fic . GetExercice ( * ue . Depend ) ; err != nil {
2022-05-16 09:38:46 +00:00
log . Println ( "Unable to createExercice:" , err . Error ( ) )
c . AbortWithStatusJSON ( http . StatusInternalServerError , gin . H { "errmsg" : "An error occurs during exercice creation." } )
return
2016-12-08 08:12:18 +00:00
} else {
2021-11-22 14:35:07 +00:00
depend = d
2016-12-08 08:12:18 +00:00
}
}
2024-03-18 10:26:01 +00:00
exercice , err := theme . AddExercice ( ue . Title , ue . Authors , ue . Image , ue . BackgroundColor , ue . WIP , ue . URLId , ue . Path , ue . Statement , ue . Overview , ue . Headline , depend , ue . Gain , ue . VideoURI , ue . Resolution , ue . SeeAlso , ue . Finished )
2022-05-16 09:38:46 +00:00
if err != nil {
log . Println ( "Unable to createExercice:" , err . Error ( ) )
c . AbortWithStatusJSON ( http . StatusInternalServerError , gin . H { "errmsg" : "An error occurs during exercice creation." } )
return
}
c . JSON ( http . StatusOK , exercice )
2016-12-08 08:12:18 +00:00
}
2017-01-05 01:21:32 +00:00
type uploadedHint struct {
2018-03-09 18:07:08 +00:00
Title string
Path string
Content string
Cost int64
URI string
2017-01-05 01:21:32 +00:00
}
2022-05-16 09:38:46 +00:00
func createExerciceHint ( c * gin . Context ) {
exercice := c . MustGet ( "exercice" ) . ( * fic . Exercice )
2017-01-05 01:21:32 +00:00
var uh uploadedHint
2022-05-16 09:38:46 +00:00
err := c . ShouldBindJSON ( & uh )
if err != nil {
c . AbortWithStatusJSON ( http . StatusBadRequest , gin . H { "errmsg" : err . Error ( ) } )
return
2016-12-04 18:15:39 +00:00
}
2017-01-05 01:21:32 +00:00
if len ( uh . Content ) != 0 {
2022-05-16 09:38:46 +00:00
hint , err := exercice . AddHint ( uh . Title , uh . Content , uh . Cost )
if err != nil {
log . Println ( "Unable to AddHint in createExerciceHint:" , err . Error ( ) )
c . AbortWithStatusJSON ( http . StatusInternalServerError , gin . H { "errmsg" : "An error occurs when trying to add hint." } )
return
}
c . JSON ( http . StatusOK , hint )
2017-11-27 01:45:33 +00:00
} else if len ( uh . URI ) != 0 {
2022-05-16 09:38:46 +00:00
hint , err := sync . ImportFile ( sync . GlobalImporter , uh . URI ,
2017-11-27 01:45:33 +00:00
func ( filePath string , origin string ) ( interface { } , error ) {
2018-03-09 18:07:08 +00:00
return exercice . AddHint ( uh . Title , "$FILES" + strings . TrimPrefix ( filePath , fic . FilesDir ) , uh . Cost )
2017-01-05 01:21:32 +00:00
} )
2022-05-16 09:38:46 +00:00
if err != nil {
log . Println ( "Unable to AddHint (after ImportFile) in createExerciceHint:" , err . Error ( ) )
c . AbortWithStatusJSON ( http . StatusInternalServerError , gin . H { "errmsg" : "An error occurs when trying to add hint." } )
return
}
c . JSON ( http . StatusOK , hint )
2017-01-05 01:21:32 +00:00
} else {
2022-05-16 09:38:46 +00:00
c . AbortWithStatusJSON ( http . StatusBadRequest , gin . H { "errmsg" : "Hint's content not filled" } )
return
2016-12-04 18:15:39 +00:00
}
}
2016-12-27 20:08:36 +00:00
2022-05-16 09:38:46 +00:00
func showExerciceHint ( c * gin . Context ) {
c . JSON ( http . StatusOK , c . MustGet ( "hint" ) . ( * fic . EHint ) )
2016-12-27 20:08:36 +00:00
}
2022-05-16 09:38:46 +00:00
func showExerciceHintDeps ( c * gin . Context ) {
hint := c . MustGet ( "hint" ) . ( * fic . EHint )
deps , err := loadFlags ( hint . GetDepends )
if err != nil {
log . Println ( "Unable to loaddeps:" , err . Error ( ) )
c . AbortWithStatusJSON ( http . StatusInternalServerError , gin . H { "errmsg" : "An error occurs when trying to retrieve hint dependencies." } )
return
}
c . JSON ( http . StatusOK , deps )
2020-01-23 13:23:02 +00:00
}
2022-05-16 09:38:46 +00:00
func updateExerciceHint ( c * gin . Context ) {
hint := c . MustGet ( "hint" ) . ( * fic . EHint )
2016-12-27 20:08:36 +00:00
var uh fic . EHint
2022-05-16 09:38:46 +00:00
err := c . ShouldBindJSON ( & uh )
if err != nil {
c . AbortWithStatusJSON ( http . StatusBadRequest , gin . H { "errmsg" : err . Error ( ) } )
return
2016-12-27 20:08:36 +00:00
}
uh . Id = hint . Id
if len ( uh . Title ) == 0 {
2022-05-16 09:38:46 +00:00
c . AbortWithStatusJSON ( http . StatusBadRequest , gin . H { "errmsg" : "Hint's title not filled" } )
return
2016-12-27 20:08:36 +00:00
}
if _ , err := uh . Update ( ) ; err != nil {
2022-05-16 09:38:46 +00:00
log . Println ( "Unable to updateExerciceHint:" , err . Error ( ) )
c . AbortWithStatusJSON ( http . StatusInternalServerError , gin . H { "errmsg" : "An error occurs when trying to update hint." } )
return
2016-12-27 20:08:36 +00:00
}
2022-05-16 09:38:46 +00:00
c . JSON ( http . StatusOK , uh )
2016-12-27 20:08:36 +00:00
}
2022-05-16 09:38:46 +00:00
func deleteExerciceHint ( c * gin . Context ) {
hint := c . MustGet ( "hint" ) . ( * fic . EHint )
_ , err := hint . Delete ( )
if err != nil {
log . Println ( "Unable to deleteExerciceHint:" , err . Error ( ) )
c . AbortWithStatusJSON ( http . StatusInternalServerError , gin . H { "errmsg" : "An error occurs when trying to delete hint." } )
return
}
c . JSON ( http . StatusOK , true )
2016-12-27 20:08:36 +00:00
}
2018-09-24 08:00:17 +00:00
type uploadedFlag struct {
2022-01-21 07:28:39 +00:00
Type string
Label string
Placeholder string
2022-06-08 10:24:38 +00:00
Help string
2022-01-21 07:28:39 +00:00
IgnoreCase bool
Multiline bool
NoTrim bool
2024-03-27 10:24:54 +00:00
CaptureRe * string ` json:"capture_regexp" `
2022-01-21 07:28:39 +00:00
SortReGroups bool ` json:"sort_re_grps" `
Flag string
Value [ ] byte
2022-05-31 20:03:51 +00:00
ChoicesCost int32 ` json:"choices_cost" `
BonusGain int32 ` json:"bonus_gain" `
2017-12-12 04:06:34 +00:00
}
2022-05-16 09:38:46 +00:00
func createExerciceFlag ( c * gin . Context ) {
2018-09-24 08:00:17 +00:00
var uk uploadedFlag
2022-05-16 09:38:46 +00:00
err := c . ShouldBindJSON ( & uk )
if err != nil {
c . AbortWithStatusJSON ( http . StatusBadRequest , gin . H { "errmsg" : err . Error ( ) } )
return
2017-12-12 04:06:34 +00:00
}
2018-09-24 08:00:17 +00:00
if len ( uk . Flag ) == 0 {
2022-05-16 09:38:46 +00:00
c . AbortWithStatusJSON ( http . StatusBadRequest , gin . H { "errmsg" : "Flag not filled" } )
return
2017-12-12 04:06:34 +00:00
}
2018-11-16 19:46:19 +00:00
var vre * string = nil
2023-05-16 07:59:59 +00:00
if uk . CaptureRe != nil && len ( * uk . CaptureRe ) > 0 {
vre = uk . CaptureRe
2018-11-16 19:46:19 +00:00
}
2022-05-16 09:38:46 +00:00
exercice := c . MustGet ( "exercice" ) . ( * fic . Exercice )
2022-05-31 20:03:51 +00:00
flag , err := exercice . AddRawFlagKey ( uk . Label , uk . Type , uk . Placeholder , uk . IgnoreCase , uk . NoTrim , uk . Multiline , vre , uk . SortReGroups , [ ] byte ( uk . Flag ) , uk . ChoicesCost , uk . BonusGain )
2022-05-16 09:38:46 +00:00
if err != nil {
log . Println ( "Unable to createExerciceFlag:" , err . Error ( ) )
c . AbortWithStatusJSON ( http . StatusInternalServerError , gin . H { "errmsg" : "An error occurs when trying to create flag." } )
return
}
c . JSON ( http . StatusOK , flag )
2017-12-12 04:06:34 +00:00
}
2022-05-16 09:38:46 +00:00
func showExerciceFlag ( c * gin . Context ) {
c . JSON ( http . StatusOK , c . MustGet ( "flag-key" ) . ( * fic . FlagKey ) )
2016-12-27 20:08:36 +00:00
}
2022-05-16 09:38:46 +00:00
func showExerciceFlagDeps ( c * gin . Context ) {
flag := c . MustGet ( "flag-key" ) . ( * fic . FlagKey )
deps , err := loadFlags ( flag . GetDepends )
if err != nil {
log . Println ( "Unable to loaddeps:" , err . Error ( ) )
c . AbortWithStatusJSON ( http . StatusInternalServerError , gin . H { "errmsg" : "An error occurs when trying to retrieve hint dependencies." } )
return
}
c . JSON ( http . StatusOK , deps )
2020-01-23 13:23:02 +00:00
}
2022-05-16 09:38:46 +00:00
func tryExerciceFlag ( c * gin . Context ) {
flag := c . MustGet ( "flag-key" ) . ( * fic . FlagKey )
2018-12-08 02:13:16 +00:00
var uk uploadedFlag
2022-05-16 09:38:46 +00:00
err := c . ShouldBindJSON ( & uk )
if err != nil {
c . AbortWithStatusJSON ( http . StatusBadRequest , gin . H { "errmsg" : err . Error ( ) } )
return
2018-12-08 02:13:16 +00:00
}
if len ( uk . Flag ) == 0 {
2022-05-16 09:38:46 +00:00
c . AbortWithStatusJSON ( http . StatusBadRequest , gin . H { "errmsg" : "Empty submission" } )
return
2018-12-08 02:13:16 +00:00
}
2019-01-02 20:51:09 +00:00
if flag . Check ( [ ] byte ( uk . Flag ) ) == 0 {
2022-05-16 09:38:46 +00:00
c . AbortWithStatusJSON ( http . StatusOK , true )
return
2018-12-08 02:13:16 +00:00
}
2022-05-16 09:38:46 +00:00
c . AbortWithStatusJSON ( http . StatusBadRequest , gin . H { "errmsg" : "Bad submission" } )
2018-12-08 02:13:16 +00:00
}
2022-05-16 09:38:46 +00:00
func updateExerciceFlag ( c * gin . Context ) {
flag := c . MustGet ( "flag-key" ) . ( * fic . FlagKey )
2018-09-24 08:00:17 +00:00
var uk uploadedFlag
2022-05-16 09:38:46 +00:00
err := c . ShouldBindJSON ( & uk )
if err != nil {
c . AbortWithStatusJSON ( http . StatusBadRequest , gin . H { "errmsg" : err . Error ( ) } )
return
2016-12-27 20:08:36 +00:00
}
2017-12-12 04:06:34 +00:00
if len ( uk . Label ) == 0 {
2018-09-24 08:00:17 +00:00
flag . Label = "Flag"
2017-12-12 04:06:34 +00:00
} else {
2018-09-24 08:00:17 +00:00
flag . Label = uk . Label
2016-12-27 20:08:36 +00:00
}
2020-09-07 17:33:09 +00:00
flag . Placeholder = uk . Placeholder
2022-06-08 10:24:38 +00:00
flag . Help = uk . Help
2018-11-16 19:46:19 +00:00
flag . IgnoreCase = uk . IgnoreCase
2020-01-28 09:49:12 +00:00
flag . Multiline = uk . Multiline
2019-01-21 12:35:09 +00:00
if len ( uk . Flag ) > 0 {
var err error
flag . Checksum , err = flag . ComputeChecksum ( [ ] byte ( uk . Flag ) )
if err != nil {
2022-05-16 09:38:46 +00:00
log . Println ( "Unable to ComputeChecksum:" , err . Error ( ) )
c . AbortWithStatusJSON ( http . StatusInternalServerError , gin . H { "errmsg" : "Unable to compute flag checksum" } )
return
2019-01-21 12:35:09 +00:00
}
} else {
flag . Checksum = uk . Value
}
2018-12-02 22:18:32 +00:00
flag . ChoicesCost = uk . ChoicesCost
2022-05-31 20:03:51 +00:00
flag . BonusGain = uk . BonusGain
2018-11-16 19:46:19 +00:00
2023-05-16 07:59:59 +00:00
if uk . CaptureRe != nil && len ( * uk . CaptureRe ) > 0 {
flag . CaptureRegexp = uk . CaptureRe
2018-11-16 19:46:19 +00:00
} else {
2023-05-16 07:59:59 +00:00
flag . CaptureRegexp = nil
2018-11-16 19:46:19 +00:00
}
2018-01-26 09:57:15 +00:00
2018-09-24 08:00:17 +00:00
if _ , err := flag . Update ( ) ; err != nil {
2022-05-16 09:38:46 +00:00
log . Println ( "Unable to updateExerciceFlag:" , err . Error ( ) )
c . AbortWithStatusJSON ( http . StatusInternalServerError , gin . H { "errmsg" : "An error occurs when trying to update flag." } )
return
2016-12-27 20:08:36 +00:00
}
2022-05-16 09:38:46 +00:00
c . JSON ( http . StatusOK , flag )
2016-12-27 20:08:36 +00:00
}
2022-05-16 09:38:46 +00:00
func deleteExerciceFlag ( c * gin . Context ) {
flag := c . MustGet ( "flag-key" ) . ( * fic . FlagKey )
_ , err := flag . Delete ( )
if err != nil {
log . Println ( "Unable to deleteExerciceFlag:" , err . Error ( ) )
c . AbortWithStatusJSON ( http . StatusInternalServerError , gin . H { "errmsg" : "An error occurs when trying to delete flag." } )
return
}
c . JSON ( http . StatusOK , true )
2016-12-27 20:08:36 +00:00
}
2022-05-16 09:38:46 +00:00
func createFlagChoice ( c * gin . Context ) {
flag := c . MustGet ( "flag-key" ) . ( * fic . FlagKey )
2019-07-05 20:28:56 +00:00
var uc fic . FlagChoice
2022-05-16 09:38:46 +00:00
err := c . ShouldBindJSON ( & uc )
if err != nil {
c . AbortWithStatusJSON ( http . StatusBadRequest , gin . H { "errmsg" : err . Error ( ) } )
return
2018-11-21 03:10:22 +00:00
}
if len ( uc . Label ) == 0 {
uc . Label = uc . Value
}
2022-05-16 09:38:46 +00:00
choice , err := flag . AddChoice ( & uc )
if err != nil {
log . Println ( "Unable to createFlagChoice:" , err . Error ( ) )
c . AbortWithStatusJSON ( http . StatusInternalServerError , gin . H { "errmsg" : "Unable to create flag choice." } )
return
}
c . JSON ( http . StatusOK , choice )
2018-11-21 03:10:22 +00:00
}
2022-05-16 09:38:46 +00:00
func showFlagChoice ( c * gin . Context ) {
c . JSON ( http . StatusOK , c . MustGet ( "flag-choice" ) . ( * fic . FlagChoice ) )
2018-11-21 03:10:22 +00:00
}
2022-05-16 09:38:46 +00:00
func updateFlagChoice ( c * gin . Context ) {
choice := c . MustGet ( "flag-choice" ) . ( * fic . FlagChoice )
2019-07-05 20:28:56 +00:00
var uc fic . FlagChoice
2022-05-16 09:38:46 +00:00
err := c . ShouldBindJSON ( & uc )
if err != nil {
c . AbortWithStatusJSON ( http . StatusBadRequest , gin . H { "errmsg" : err . Error ( ) } )
return
2018-11-21 03:10:22 +00:00
}
if len ( uc . Label ) == 0 {
choice . Label = uc . Value
} else {
choice . Label = uc . Label
}
2020-01-28 09:49:12 +00:00
choice . Value = uc . Value
2018-11-21 03:10:22 +00:00
if _ , err := choice . Update ( ) ; err != nil {
2022-05-16 09:38:46 +00:00
log . Println ( "Unable to updateFlagChoice:" , err . Error ( ) )
c . AbortWithStatusJSON ( http . StatusInternalServerError , gin . H { "errmsg" : "Unable to update flag choice." } )
return
2018-11-21 03:10:22 +00:00
}
2022-05-16 09:38:46 +00:00
c . JSON ( http . StatusOK , choice )
2018-11-21 03:10:22 +00:00
}
2022-05-16 09:38:46 +00:00
func deleteFlagChoice ( c * gin . Context ) {
choice := c . MustGet ( "flag-choice" ) . ( * fic . FlagChoice )
_ , err := choice . Delete ( )
if err != nil {
log . Println ( "Unable to deleteExerciceChoice:" , err . Error ( ) )
c . AbortWithStatusJSON ( http . StatusInternalServerError , gin . H { "errmsg" : "An error occurs when trying to delete choice." } )
return
}
c . JSON ( http . StatusOK , true )
2018-11-21 03:10:22 +00:00
}
2022-05-16 09:38:46 +00:00
func showExerciceQuiz ( c * gin . Context ) {
c . JSON ( http . StatusOK , c . MustGet ( "flag-quiz" ) . ( * fic . MCQ ) )
2017-12-17 01:50:01 +00:00
}
2022-05-16 09:38:46 +00:00
func showExerciceQuizDeps ( c * gin . Context ) {
quiz := c . MustGet ( "flag-quiz" ) . ( * fic . MCQ )
deps , err := loadFlags ( quiz . GetDepends )
if err != nil {
log . Println ( "Unable to loaddeps:" , err . Error ( ) )
c . AbortWithStatusJSON ( http . StatusInternalServerError , gin . H { "errmsg" : "An error occurs when trying to retrieve quiz dependencies." } )
return
}
c . JSON ( http . StatusOK , deps )
2020-01-23 13:23:02 +00:00
}
2022-05-16 09:38:46 +00:00
func updateExerciceQuiz ( c * gin . Context ) {
quiz := c . MustGet ( "flag-quiz" ) . ( * fic . MCQ )
2018-06-24 16:12:26 +00:00
var uq fic . MCQ
2022-05-16 09:38:46 +00:00
err := c . ShouldBindJSON ( & uq )
if err != nil {
c . AbortWithStatusJSON ( http . StatusBadRequest , gin . H { "errmsg" : err . Error ( ) } )
return
2018-06-24 16:12:26 +00:00
}
quiz . Title = uq . Title
if _ , err := quiz . Update ( ) ; err != nil {
2022-05-16 09:38:46 +00:00
log . Println ( "Unable to updateExerciceQuiz:" , err . Error ( ) )
c . AbortWithStatusJSON ( http . StatusInternalServerError , gin . H { "errmsg" : "An error occurs when trying to update quiz." } )
return
2018-06-24 16:12:26 +00:00
}
// Update and remove old entries
var delete [ ] int
for i , cur := range quiz . Entries {
seen := false
for _ , next := range uq . Entries {
if cur . Id == next . Id {
seen = true
if cur . Label != next . Label || cur . Response != next . Response {
cur . Label = next . Label
cur . Response = next . Response
if _ , err := cur . Update ( ) ; err != nil {
2022-05-16 09:38:46 +00:00
log . Println ( "Unable to update MCQ entry:" , err . Error ( ) )
c . AbortWithStatusJSON ( http . StatusInternalServerError , gin . H { "errmsg" : "Unable to update some MCQ entry" } )
return
2018-06-24 16:12:26 +00:00
}
}
break
}
}
if seen == false {
if _ , err := cur . Delete ( ) ; err != nil {
2022-05-16 09:38:46 +00:00
log . Println ( "Unable to delete MCQ entry:" , err . Error ( ) )
c . AbortWithStatusJSON ( http . StatusInternalServerError , gin . H { "errmsg" : "Unable to delete some MCQ entry" } )
return
2018-06-24 16:12:26 +00:00
} else {
delete = append ( delete , i )
}
}
}
for n , i := range delete {
quiz . Entries = append ( quiz . Entries [ : i - n - 1 ] , quiz . Entries [ : i - n + 1 ] ... )
}
// Add new choices
for _ , choice := range uq . Entries {
if choice . Id == 0 {
2022-05-16 09:38:46 +00:00
if ch , err := quiz . AddEntry ( choice ) ; err != nil {
log . Println ( "Unable to add MCQ entry:" , err . Error ( ) )
c . AbortWithStatusJSON ( http . StatusInternalServerError , gin . H { "errmsg" : "Unable to add some MCQ entry" } )
return
2018-06-24 16:12:26 +00:00
} else {
2022-05-16 09:38:46 +00:00
quiz . Entries = append ( quiz . Entries , ch )
2018-06-24 16:12:26 +00:00
}
}
}
2022-05-16 09:38:46 +00:00
c . JSON ( http . StatusOK , quiz )
2018-06-24 16:12:26 +00:00
}
2022-05-16 09:38:46 +00:00
func deleteExerciceQuiz ( c * gin . Context ) {
quiz := c . MustGet ( "flag-quiz" ) . ( * fic . MCQ )
2018-06-24 16:12:26 +00:00
for _ , choice := range quiz . Entries {
if _ , err := choice . Delete ( ) ; err != nil {
2022-05-16 09:38:46 +00:00
log . Println ( "Unable to deleteExerciceQuiz (entry):" , err . Error ( ) )
c . AbortWithStatusJSON ( http . StatusInternalServerError , gin . H { "errmsg" : "An error occurs when trying to delete quiz entry." } )
return
2018-06-24 16:12:26 +00:00
}
}
2022-05-16 09:38:46 +00:00
_ , err := quiz . Delete ( )
if err != nil {
log . Println ( "Unable to deleteExerciceQuiz:" , err . Error ( ) )
c . AbortWithStatusJSON ( http . StatusInternalServerError , gin . H { "errmsg" : "An error occurs when trying to delete quiz." } )
return
}
c . JSON ( http . StatusOK , true )
2017-12-17 01:50:01 +00:00
}
2022-05-16 09:38:46 +00:00
func listExerciceTags ( c * gin . Context ) {
exercice := c . MustGet ( "exercice" ) . ( * fic . Exercice )
tags , err := exercice . GetTags ( )
if err != nil {
log . Println ( "Unable to listExerciceTags:" , err . Error ( ) )
c . AbortWithStatusJSON ( http . StatusInternalServerError , gin . H { "errmsg" : "An error occurs when trying to get tags." } )
return
}
c . JSON ( http . StatusOK , tags )
2018-11-18 21:44:23 +00:00
}
2022-05-16 09:38:46 +00:00
func addExerciceTag ( c * gin . Context ) {
exercice := c . MustGet ( "exercice" ) . ( * fic . Exercice )
2018-11-18 21:44:23 +00:00
var ut [ ] string
2022-05-16 09:38:46 +00:00
err := c . ShouldBindJSON ( & ut )
if err != nil {
c . AbortWithStatusJSON ( http . StatusBadRequest , gin . H { "errmsg" : err . Error ( ) } )
return
2018-11-18 21:44:23 +00:00
}
// TODO: a DB transaction should be done here: on error we should rollback
for _ , t := range ut {
if _ , err := exercice . AddTag ( t ) ; err != nil {
2022-05-16 09:38:46 +00:00
log . Println ( "Unable to addExerciceTag:" , err . Error ( ) )
c . AbortWithStatusJSON ( http . StatusInternalServerError , gin . H { "errmsg" : "An error occurs when trying to add some tag." } )
return
2018-11-18 21:44:23 +00:00
}
}
2022-05-16 09:38:46 +00:00
c . JSON ( http . StatusOK , ut )
2018-11-18 21:44:23 +00:00
}
2022-05-16 09:38:46 +00:00
func updateExerciceTags ( c * gin . Context ) {
exercice := c . MustGet ( "exercice" ) . ( * fic . Exercice )
2018-11-18 21:44:23 +00:00
exercice . WipeTags ( )
2022-05-16 09:38:46 +00:00
addExerciceTag ( c )
2018-11-18 21:44:23 +00:00
}