diff --git a/Dockerfile-admin b/Dockerfile-admin index fabc84a5..d43c2888 100644 --- a/Dockerfile-admin +++ b/Dockerfile-admin @@ -20,7 +20,7 @@ RUN go get -d -v ./admin && \ go build -v -buildmode=plugin -o repochecker/videos-rules.so ./repochecker/videos -FROM alpine:3.20 +FROM alpine:3.21 RUN apk add --no-cache \ ca-certificates \ diff --git a/Dockerfile-checker b/Dockerfile-checker index 9f2eb06c..1343fbd2 100644 --- a/Dockerfile-checker +++ b/Dockerfile-checker @@ -13,7 +13,7 @@ RUN go get -d -v ./checker && \ go build -v -buildvcs=false -o checker/checker ./checker -FROM alpine:3.20 +FROM alpine:3.21 WORKDIR /srv diff --git a/Dockerfile-dashboard b/Dockerfile-dashboard index a94c85ec..7c24e279 100644 --- a/Dockerfile-dashboard +++ b/Dockerfile-dashboard @@ -13,7 +13,7 @@ RUN go get -d -v ./dashboard && \ go build -v -buildvcs=false -o dashboard/dashboard ./dashboard -FROM alpine:3.20 +FROM alpine:3.21 EXPOSE 8082 diff --git a/Dockerfile-deploy b/Dockerfile-deploy index c6d672fc..99765543 100644 --- a/Dockerfile-deploy +++ b/Dockerfile-deploy @@ -1,4 +1,4 @@ -FROM alpine:3.20 +FROM alpine:3.21 EXPOSE 67/udp EXPOSE 69/udp diff --git a/Dockerfile-evdist b/Dockerfile-evdist index 3c42fc6d..1b9bffec 100644 --- a/Dockerfile-evdist +++ b/Dockerfile-evdist @@ -12,7 +12,7 @@ RUN go get -d -v ./evdist && \ go build -v -buildvcs=false -o evdist/evdist ./evdist -FROM alpine:3.20 +FROM alpine:3.21 WORKDIR /srv diff --git a/Dockerfile-generator b/Dockerfile-generator index 3ff63ecf..6b4c6a1d 100644 --- a/Dockerfile-generator +++ b/Dockerfile-generator @@ -13,7 +13,7 @@ RUN go get -d -v ./generator && \ go build -v -buildvcs=false -o generator/generator ./generator -FROM alpine:3.20 +FROM alpine:3.21 WORKDIR /srv diff --git a/Dockerfile-get-remote-files b/Dockerfile-get-remote-files index 19f88472..6a71caa4 100644 --- a/Dockerfile-get-remote-files +++ b/Dockerfile-get-remote-files @@ -15,7 +15,7 @@ RUN go get -d -v ./admin && \ go build -v -o get-remote-files ./admin/get-remote-files -FROM alpine:3.20 +FROM alpine:3.21 RUN apk add --no-cache \ ca-certificates diff --git a/Dockerfile-qa b/Dockerfile-qa index eeae2953..7e2e6488 100644 --- a/Dockerfile-qa +++ b/Dockerfile-qa @@ -25,7 +25,7 @@ RUN go get -d -v ./qa && \ go build -v -buildvcs=false -o qa/qa ./qa -FROM alpine:3.20 +FROM alpine:3.21 EXPOSE 8083 diff --git a/Dockerfile-receiver b/Dockerfile-receiver index 52d98620..49d15871 100644 --- a/Dockerfile-receiver +++ b/Dockerfile-receiver @@ -13,7 +13,7 @@ RUN go get -d -v ./receiver && \ go build -v -buildvcs=false -o ./receiver/receiver ./receiver -FROM alpine:3.20 +FROM alpine:3.21 EXPOSE 8080 diff --git a/Dockerfile-remote-challenge-sync-airbus b/Dockerfile-remote-challenge-sync-airbus index f5dfeca2..516dd6d1 100644 --- a/Dockerfile-remote-challenge-sync-airbus +++ b/Dockerfile-remote-challenge-sync-airbus @@ -13,7 +13,7 @@ RUN go get -d -v ./remote/challenge-sync-airbus && \ go build -v -buildvcs=false -o ./challenge-sync-airbus ./remote/challenge-sync-airbus -FROM alpine:3.20 +FROM alpine:3.21 RUN apk add --no-cache openssl ca-certificates diff --git a/Dockerfile-remote-scores-sync-zqds b/Dockerfile-remote-scores-sync-zqds index 772f7f53..1a5c68f8 100644 --- a/Dockerfile-remote-scores-sync-zqds +++ b/Dockerfile-remote-scores-sync-zqds @@ -13,7 +13,7 @@ RUN go get -d -v ./remote/scores-sync-zqds && \ go build -v -buildvcs=false -o ./scores-sync-zqds ./remote/scores-sync-zqds -FROM alpine:3.20 +FROM alpine:3.21 RUN apk add --no-cache openssl ca-certificates diff --git a/admin/api/exercice.go b/admin/api/exercice.go index cfdb450d..afe6b8d7 100644 --- a/admin/api/exercice.go +++ b/admin/api/exercice.go @@ -62,6 +62,8 @@ func declareExercicesRoutes(router *gin.RouterGroup) { apiFlagsRoutes.POST("/try", tryExerciceFlag) apiFlagsRoutes.DELETE("/", deleteExerciceFlag) apiFlagsRoutes.GET("/dependancies", showExerciceFlagDeps) + apiFlagsRoutes.GET("/statistics", showExerciceFlagStats) + apiFlagsRoutes.DELETE("/tries", deleteExerciceFlagTries) apiFlagsRoutes.GET("/choices/", listFlagChoices) apiFlagsChoicesRoutes := apiExercicesRoutes.Group("/choices/:cid") apiFlagsChoicesRoutes.Use(FlagChoiceHandler) @@ -77,6 +79,8 @@ func declareExercicesRoutes(router *gin.RouterGroup) { apiQuizRoutes.PUT("", updateExerciceQuiz) apiQuizRoutes.DELETE("", deleteExerciceQuiz) apiQuizRoutes.GET("/dependancies", showExerciceQuizDeps) + apiQuizRoutes.GET("/statistics", showExerciceQuizStats) + apiQuizRoutes.DELETE("/tries", deleteExerciceQuizTries) apiExercicesRoutes.GET("/tags", listExerciceTags) apiExercicesRoutes.POST("/tags", addExerciceTag) @@ -852,6 +856,60 @@ func showExerciceFlagDeps(c *gin.Context) { c.JSON(http.StatusOK, deps) } +func showExerciceFlagStats(c *gin.Context) { + exercice := c.MustGet("exercice").(*fic.Exercice) + flag := c.MustGet("flag-key").(*fic.FlagKey) + + 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 + } + + var completed int64 + + for _, hline := range history { + if hline["kind"].(string) == "flag_found" { + if *hline["secondary"].(*int) == flag.Id { + completed += 1 + } + } + } + + tries, err := flag.NbTries() + if err != nil { + log.Println("Unable to nbTries:", err.Error()) + c.AbortWithStatusJSON(http.StatusInternalServerError, gin.H{"errmsg": "An error occurs when retrieving flag tries"}) + return + } + + teams, err := flag.TeamsOnIt() + if err != nil { + log.Println("Unable to teamsOnIt:", err.Error()) + c.AbortWithStatusJSON(http.StatusInternalServerError, gin.H{"errmsg": "An error occurs when retrieving flag related teams"}) + return + } + + c.JSON(http.StatusOK, gin.H{ + "completed": completed, + "tries": tries, + "teams": teams, + }) +} + +func deleteExerciceFlagTries(c *gin.Context) { + flag := c.MustGet("flag-key").(*fic.FlagKey) + + err := flag.DeleteTries() + if err != nil { + c.AbortWithStatusJSON(http.StatusBadRequest, gin.H{"errmsg": err.Error()}) + return + } + + c.AbortWithStatusJSON(http.StatusOK, true) +} + func tryExerciceFlag(c *gin.Context) { flag := c.MustGet("flag-key").(*fic.FlagKey) @@ -895,6 +953,23 @@ func updateExerciceFlag(c *gin.Context) { flag.Help = uk.Help flag.IgnoreCase = uk.IgnoreCase flag.Multiline = uk.Multiline + flag.ChoicesCost = uk.ChoicesCost + flag.BonusGain = uk.BonusGain + + if uk.CaptureRe != nil && len(*uk.CaptureRe) > 0 { + if flag.CaptureRegexp != uk.CaptureRe && uk.Flag == "" { + c.AbortWithStatusJSON(http.StatusBadRequest, gin.H{"errmsg": "Pour changer la capture_regexp, vous devez rentrer la réponse attendue à nouveau, car le flag doit être recalculé."}) + return + } + flag.CaptureRegexp = uk.CaptureRe + } else { + if flag.CaptureRegexp != nil && uk.Flag == "" { + c.AbortWithStatusJSON(http.StatusBadRequest, gin.H{"errmsg": "Pour changer la capture_regexp, vous devez rentrer la réponse attendue à nouveau, car le flag doit être recalculé."}) + return + } + flag.CaptureRegexp = nil + } + if len(uk.Flag) > 0 { var err error flag.Checksum, err = flag.ComputeChecksum([]byte(uk.Flag)) @@ -906,14 +981,6 @@ func updateExerciceFlag(c *gin.Context) { } else { flag.Checksum = uk.Value } - flag.ChoicesCost = uk.ChoicesCost - flag.BonusGain = uk.BonusGain - - if uk.CaptureRe != nil && len(*uk.CaptureRe) > 0 { - flag.CaptureRegexp = uk.CaptureRe - } else { - flag.CaptureRegexp = nil - } if _, err := flag.Update(); err != nil { log.Println("Unable to updateExerciceFlag:", err.Error()) @@ -1022,6 +1089,60 @@ func showExerciceQuizDeps(c *gin.Context) { c.JSON(http.StatusOK, deps) } +func showExerciceQuizStats(c *gin.Context) { + exercice := c.MustGet("exercice").(*fic.Exercice) + quiz := c.MustGet("flag-quiz").(*fic.MCQ) + + 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 + } + + var completed int64 + + for _, hline := range history { + if hline["kind"].(string) == "mcq_found" { + if *hline["secondary"].(*int) == quiz.Id { + completed += 1 + } + } + } + + tries, err := quiz.NbTries() + if err != nil { + log.Println("Unable to nbTries:", err.Error()) + c.AbortWithStatusJSON(http.StatusInternalServerError, gin.H{"errmsg": "An error occurs when retrieving flag tries"}) + return + } + + teams, err := quiz.TeamsOnIt() + if err != nil { + log.Println("Unable to teamsOnIt:", err.Error()) + c.AbortWithStatusJSON(http.StatusInternalServerError, gin.H{"errmsg": "An error occurs when retrieving flag related teams"}) + return + } + + c.JSON(http.StatusOK, gin.H{ + "completed": completed, + "tries": tries, + "teams": teams, + }) +} + +func deleteExerciceQuizTries(c *gin.Context) { + quiz := c.MustGet("flag-quiz").(*fic.MCQ) + + err := quiz.DeleteTries() + if err != nil { + c.AbortWithStatusJSON(http.StatusBadRequest, gin.H{"errmsg": err.Error()}) + return + } + + c.AbortWithStatusJSON(http.StatusOK, true) +} + func updateExerciceQuiz(c *gin.Context) { quiz := c.MustGet("flag-quiz").(*fic.MCQ) diff --git a/admin/api/export.go b/admin/api/export.go index 32f43e79..aa24920a 100644 --- a/admin/api/export.go +++ b/admin/api/export.go @@ -3,9 +3,12 @@ package api import ( "archive/zip" "encoding/json" + "io" + "log" "net/http" "path" + "srs.epita.fr/fic-server/admin/sync" "srs.epita.fr/fic-server/libfic" "srs.epita.fr/fic-server/settings" @@ -59,6 +62,41 @@ func declareExportRoutes(router *gin.RouterGroup) { json.NewEncoder(f).Encode(challengeinfo) } + // Include partners' logos from challenge.json + if sync.GlobalImporter != nil { + if len(challengeinfo.MainLogo) > 0 { + for _, logo := range challengeinfo.MainLogo { + fd, closer, err := sync.OpenOrGetFile(sync.GlobalImporter, logo) + if err != nil { + log.Printf("Unable to archive main logo %q: %s", logo, err.Error()) + continue + } + + f, err := w.Create(path.Join("logo", path.Base(logo))) + if err == nil { + io.Copy(f, fd) + } + closer() + } + } + + if len(challengeinfo.Partners) > 0 { + for _, partner := range challengeinfo.Partners { + fd, closer, err := sync.OpenOrGetFile(sync.GlobalImporter, partner.Src) + if err != nil { + log.Printf("Unable to archive partner logo %q: %s", partner.Src, err.Error()) + continue + } + + f, err := w.Create(path.Join("partner", path.Base(partner.Src))) + if err == nil { + io.Copy(f, fd) + } + closer() + } + } + } + // my.json f, err = w.Create("my.json") if err == nil { diff --git a/admin/api/password.go b/admin/api/password.go index 2247e918..1941df38 100644 --- a/admin/api/password.go +++ b/admin/api/password.go @@ -34,6 +34,11 @@ func declarePasswordRoutes(router *gin.RouterGroup) { c.JSON(http.StatusOK, gin.H{"password": passwd}) }) + router.GET("/oauth-status", func(c *gin.Context) { + c.JSON(http.StatusOK, gin.H{ + "secret_defined": OidcSecret != "", + }) + }) router.GET("/dex.yaml", func(c *gin.Context) { cfg, err := genDexConfig() if err != nil { @@ -136,7 +141,7 @@ storage: web: http: 0.0.0.0:5556 frontend: - issuer: Challenge forensic + issuer: {{ .Name }} logoURL: {{ .LogoPath }} dir: /srv/dex/web/ oauth2: diff --git a/admin/api/team.go b/admin/api/team.go index e62f5da9..a0bea3bd 100644 --- a/admin/api/team.go +++ b/admin/api/team.go @@ -1,9 +1,9 @@ package api import ( + "encoding/json" "fmt" "log" - "math/rand" "net/http" "strconv" "strings" @@ -186,6 +186,9 @@ func declareTeamsRoutes(router *gin.RouterGroup) { declareTeamsPasswordRoutes(apiTeamsRoutes) declareTeamClaimsRoutes(apiTeamsRoutes) declareTeamCertificateRoutes(apiTeamsRoutes) + + // Import teams from cyberrange + router.POST("/cyberrange-teams.json", importTeamsFromCyberrange) } func TeamHandler(c *gin.Context) { @@ -292,6 +295,11 @@ func bindingTeams(c *gin.Context) { c.String(http.StatusOK, ret) } +type teamAssociation struct { + Association string `json:"association"` + TeamId int64 `json:"team_id"` +} + func allAssociations(c *gin.Context) { teams, err := fic.GetTeams() if err != nil { @@ -300,7 +308,7 @@ func allAssociations(c *gin.Context) { return } - var ret []string + var ret []teamAssociation for _, team := range teams { assocs, err := pki.GetTeamAssociations(TeamsDir, team.Id) @@ -310,13 +318,84 @@ func allAssociations(c *gin.Context) { } for _, a := range assocs { - ret = append(ret, a) + ret = append(ret, teamAssociation{a, team.Id}) } } c.JSON(http.StatusOK, ret) } +func importTeamsFromCyberrange(c *gin.Context) { + file, err := c.FormFile("file") + if err != nil { + c.JSON(http.StatusBadRequest, gin.H{"errmsg": "Failed to get file: " + err.Error()}) + return + } + + src, err := file.Open() + if err != nil { + c.JSON(http.StatusInternalServerError, gin.H{"errmsg": "Failed to open file: " + err.Error()}) + return + } + defer src.Close() + + var ut []fic.CyberrangeTeam + err = json.NewDecoder(src).Decode(&fic.CyberrangeAPIResponse{Data: &ut}) + if err != nil { + c.AbortWithStatusJSON(http.StatusBadRequest, gin.H{"errmsg": err.Error()}) + return + } + + teams, err := fic.GetTeams() + if err != nil { + c.AbortWithStatusJSON(http.StatusInternalServerError, gin.H{"errmsg": fmt.Sprintf("Impossible de récupérer la liste des équipes actuelles: %s", err.Error())}) + return + } + + for _, crteam := range ut { + var exist_team *fic.Team + for _, team := range teams { + if team.Name == crteam.Name && team.ExternalId == crteam.UUID { + exist_team = team + break + } + } + + if exist_team != nil { + exist_team.Name = crteam.Name + exist_team.ExternalId = crteam.UUID + _, err = exist_team.Update() + } else { + exist_team, err = fic.CreateTeam(crteam.Name, fic.RandomColor().ToRGB(), crteam.UUID) + } + + if err != nil { + c.AbortWithStatusJSON(http.StatusInternalServerError, gin.H{"errmsg": fmt.Sprintf("Impossible d'ajouter/de modifier l'équipe %v: %s", crteam, err.Error())}) + return + } + + // Import members + if c.DefaultQuery("nomembers", "0") != "" && len(crteam.Members) > 0 { + exist_team.ClearMembers() + + for _, member := range crteam.Members { + _, err = exist_team.AddMember(member.Name, "", member.Nickname, exist_team.Name) + if err != nil { + log.Printf("Unable to add member %q to team %s (tid=%d): %s", member.UUID, exist_team.Name, exist_team.Id, err.Error()) + } + } + } + } + + teams, err = fic.GetTeams() + if err != nil { + c.AbortWithStatusJSON(http.StatusInternalServerError, gin.H{"errmsg": fmt.Sprintf("Impossible de récupérer la liste des équipes après import: %s", err.Error())}) + return + } + + c.JSON(http.StatusOK, teams) +} + func createTeam(c *gin.Context) { var ut fic.Team err := c.ShouldBindJSON(&ut) @@ -326,11 +405,7 @@ func createTeam(c *gin.Context) { } if ut.Color == 0 { - ut.Color = fic.HSL{ - H: rand.Float64(), - S: 1, - L: 0.5, - }.ToRGB() + ut.Color = fic.RandomColor().ToRGB() } team, err := fic.CreateTeam(strings.TrimSpace(ut.Name), ut.Color, ut.ExternalId) diff --git a/admin/index.go b/admin/index.go index fa457641..506ff805 100644 --- a/admin/index.go +++ b/admin/index.go @@ -4,7 +4,7 @@ const indextpl = ` - Challenge Forensic - Administration + {{ .title }} - Administration diff --git a/go.mod b/go.mod index 234a0275..be18fa2e 100644 --- a/go.mod +++ b/go.mod @@ -1,16 +1,16 @@ module srs.epita.fr/fic-server -go 1.21 +go 1.23.0 -toolchain go1.23.4 +toolchain go1.24.1 require ( - github.com/BurntSushi/toml v1.4.0 - github.com/asticode/go-astisub v0.32.0 + github.com/BurntSushi/toml v1.5.0 + github.com/asticode/go-astisub v0.34.0 github.com/cenkalti/dominantcolor v1.0.3 github.com/gin-contrib/sessions v1.0.2 github.com/gin-gonic/gin v1.10.0 - github.com/go-git/go-git/v5 v5.13.1 + github.com/go-git/go-git/v5 v5.14.0 github.com/go-sql-driver/mysql v1.8.1 github.com/google/gopacket v1.1.19 github.com/studio-b12/gowebdav v0.10.0 @@ -18,17 +18,17 @@ require ( github.com/yuin/goldmark v1.7.8 gitlab.com/nyarla/go-crypt v0.0.0-20160106005555-d9a5dc2b789b go.uber.org/multierr v1.11.0 - golang.org/x/crypto v0.31.0 - golang.org/x/image v0.23.0 - golang.org/x/oauth2 v0.25.0 + golang.org/x/crypto v0.36.0 + golang.org/x/image v0.25.0 + golang.org/x/oauth2 v0.28.0 gopkg.in/fsnotify.v1 v1.4.7 ) require ( dario.cat/mergo v1.0.0 // indirect filippo.io/edwards25519 v1.1.0 // indirect - github.com/Microsoft/go-winio v0.6.1 // indirect - github.com/ProtonMail/go-crypto v1.1.3 // indirect + github.com/Microsoft/go-winio v0.6.2 // indirect + github.com/ProtonMail/go-crypto v1.1.5 // indirect github.com/acomagu/bufpipe v1.0.4 // indirect github.com/asticode/go-astikit v0.20.0 // indirect github.com/asticode/go-astits v1.8.0 // indirect @@ -37,23 +37,23 @@ require ( github.com/bytedance/sonic/loader v0.1.1 // indirect github.com/chenzhuoyu/base64x v0.0.0-20230717121745-296ad89f973d // indirect github.com/chenzhuoyu/iasm v0.9.1 // indirect - github.com/cloudflare/circl v1.3.7 // indirect + github.com/cloudflare/circl v1.6.0 // indirect github.com/cloudwego/base64x v0.1.4 // indirect github.com/cloudwego/iasm v0.2.0 // indirect - github.com/cyphar/filepath-securejoin v0.3.6 // indirect + github.com/cyphar/filepath-securejoin v0.4.1 // indirect github.com/disintegration/imaging v1.6.2 // indirect github.com/emirpasic/gods v1.18.1 // indirect github.com/fsnotify/fsnotify v1.6.0 // indirect github.com/gabriel-vasile/mimetype v1.4.3 // indirect github.com/gin-contrib/sse v0.1.0 // indirect github.com/go-git/gcfg v1.5.1-0.20230307220236-3a3c6141e376 // indirect - github.com/go-git/go-billy/v5 v5.6.1 // indirect + github.com/go-git/go-billy/v5 v5.6.2 // indirect github.com/go-playground/locales v0.14.1 // indirect github.com/go-playground/universal-translator v0.18.1 // indirect github.com/go-playground/validator/v10 v10.20.0 // indirect github.com/goccy/go-json v0.10.2 // indirect - github.com/golang/groupcache v0.0.0-20210331224755-41bb18bfe9da // indirect - github.com/golang/protobuf v1.5.3 // indirect + github.com/golang/groupcache v0.0.0-20241129210726-2c02b8208cf8 // indirect + github.com/golang/protobuf v1.5.4 // indirect github.com/gorilla/context v1.1.2 // indirect github.com/gorilla/securecookie v1.1.2 // indirect github.com/gorilla/sessions v1.2.2 // indirect @@ -69,20 +69,20 @@ require ( github.com/modern-go/concurrent v0.0.0-20180306012644-bacd9c7ef1dd // indirect github.com/modern-go/reflect2 v1.0.2 // indirect github.com/pelletier/go-toml/v2 v2.2.2 // indirect - github.com/pjbgf/sha1cd v0.3.0 // indirect + github.com/pjbgf/sha1cd v0.3.2 // indirect github.com/quasoft/memstore v0.0.0-20191010062613-2bce066d2b0b // indirect github.com/sergi/go-diff v1.3.2-0.20230802210424-5b0b94c5c0d3 // indirect - github.com/skeema/knownhosts v1.3.0 // indirect + github.com/skeema/knownhosts v1.3.1 // indirect github.com/twitchyliquid64/golang-asm v0.15.1 // indirect github.com/u2takey/go-utils v0.3.1 // indirect github.com/ugorji/go/codec v1.2.12 // indirect github.com/xanzy/ssh-agent v0.3.3 // indirect golang.org/x/arch v0.8.0 // indirect golang.org/x/mod v0.17.0 // indirect - golang.org/x/net v0.33.0 // indirect - golang.org/x/sync v0.10.0 // indirect - golang.org/x/sys v0.28.0 // indirect - golang.org/x/text v0.21.0 // indirect + golang.org/x/net v0.35.0 // indirect + golang.org/x/sync v0.12.0 // indirect + golang.org/x/sys v0.31.0 // indirect + golang.org/x/text v0.23.0 // indirect golang.org/x/tools v0.21.1-0.20240508182429-e35e4ccd0d2d // indirect google.golang.org/appengine v1.6.7 // indirect google.golang.org/protobuf v1.34.1 // indirect diff --git a/go.sum b/go.sum index d065fee7..a7747ce6 100644 --- a/go.sum +++ b/go.sum @@ -10,6 +10,8 @@ github.com/BurntSushi/toml v1.3.2 h1:o7IhLm0Msx3BaB+n3Ag7L8EVlByGnpq14C4YWiu/gL8 github.com/BurntSushi/toml v1.3.2/go.mod h1:CxXYINrC8qIiEnFrOxCa7Jy5BFHlXnUU2pbicEuybxQ= github.com/BurntSushi/toml v1.4.0 h1:kuoIxZQy2WRRk1pttg9asf+WVv6tWQuBNVmK8+nqPr0= github.com/BurntSushi/toml v1.4.0/go.mod h1:ukJfTF/6rtPPRCnwkur4qwRxa8vTRFBF0uk2lLoLwho= +github.com/BurntSushi/toml v1.5.0 h1:W5quZX/G/csjUnuI8SUYlsHs9M38FC7znL0lIO+DvMg= +github.com/BurntSushi/toml v1.5.0/go.mod h1:ukJfTF/6rtPPRCnwkur4qwRxa8vTRFBF0uk2lLoLwho= github.com/Microsoft/go-winio v0.4.14/go.mod h1:qXqCSQ3Xa7+6tgxaGTIe4Kpcdsi+P8jBhyzoq1bpyYA= github.com/Microsoft/go-winio v0.4.16 h1:FtSW/jqD+l4ba5iPBj9CODVtgfYAD8w2wS923g/cFDk= github.com/Microsoft/go-winio v0.4.16/go.mod h1:XB6nPKklQyQ7GC9LdcBEcBl8PF76WugXOPRXwdLnMv0= @@ -17,6 +19,8 @@ github.com/Microsoft/go-winio v0.5.2 h1:a9IhgEQBCUEk6QCdml9CiJGhAws+YwffDHEMp1VM github.com/Microsoft/go-winio v0.5.2/go.mod h1:WpS1mjBmmwHBEWmogvA2mj8546UReBk4v8QkMxJ6pZY= github.com/Microsoft/go-winio v0.6.1 h1:9/kr64B9VUZrLm5YYwbGtUJnMgqWVOdUAXu6Migciow= github.com/Microsoft/go-winio v0.6.1/go.mod h1:LRdKpFKfdobln8UmuiYcKPot9D2v6svN5+sAH+4kjUM= +github.com/Microsoft/go-winio v0.6.2 h1:F2VQgta7ecxGYO8k3ZZz3RS8fVIXVxONVUPlNERoyfY= +github.com/Microsoft/go-winio v0.6.2/go.mod h1:yd8OoFMLzJbo9gZq8j5qaps8bJ9aShtEA8Ipt1oGCvU= github.com/ProtonMail/go-crypto v0.0.0-20210428141323-04723f9f07d7 h1:YoJbenK9C67SkzkDfmQuVln04ygHj3vjZfd9FL+GmQQ= github.com/ProtonMail/go-crypto v0.0.0-20210428141323-04723f9f07d7/go.mod h1:z4/9nQmJSSwwds7ejkxaJwO37dru3geImFUdJlaLzQo= github.com/ProtonMail/go-crypto v0.0.0-20221026131551-cf6655e29de4 h1:ra2OtmuW0AE5csawV4YXMNGNQQXvLRps3z2Z59OPO+I= @@ -33,6 +37,8 @@ github.com/ProtonMail/go-crypto v1.0.0 h1:LRuvITjQWX+WIfr930YHG2HNfjR1uOfyf5vE0k github.com/ProtonMail/go-crypto v1.0.0/go.mod h1:EjAoLdwvbIOoOQr3ihjnSoLZRtE8azugULFRteWMNc0= github.com/ProtonMail/go-crypto v1.1.3 h1:nRBOetoydLeUb4nHajyO2bKqMLfWQ/ZPwkXqXxPxCFk= github.com/ProtonMail/go-crypto v1.1.3/go.mod h1:rA3QumHc/FZ8pAHreoekgiAbzpNsfQAosU5td4SnOrE= +github.com/ProtonMail/go-crypto v1.1.5 h1:eoAQfK2dwL+tFSFpr7TbOaPNUbPiJj4fLYwwGE1FQO4= +github.com/ProtonMail/go-crypto v1.1.5/go.mod h1:rA3QumHc/FZ8pAHreoekgiAbzpNsfQAosU5td4SnOrE= github.com/acomagu/bufpipe v1.0.3 h1:fxAGrHZTgQ9w5QqVItgzwj235/uYZYgbXitB+dLupOk= github.com/acomagu/bufpipe v1.0.3/go.mod h1:mxdxdup/WdsKVreO5GpW4+M/1CE2sMG4jeGJ2sYmHc4= github.com/acomagu/bufpipe v1.0.4 h1:e3H4WUzM3npvo5uv95QuJM3cQspFNtFBzvJ2oNjKIDQ= @@ -68,6 +74,8 @@ github.com/asticode/go-astisub v0.30.0 h1:z4k2Y+V+rlCE8qk3uw/nie56KXxJaL1/GwTP+9 github.com/asticode/go-astisub v0.30.0/go.mod h1:WTkuSzFB+Bp7wezuSf2Oxulj5A8zu2zLRVFf6bIFQK8= github.com/asticode/go-astisub v0.32.0 h1:i1RHVQyTxSAuX0X3YC5zIyWruVZorS3cDXxqxYa0qss= github.com/asticode/go-astisub v0.32.0/go.mod h1:WTkuSzFB+Bp7wezuSf2Oxulj5A8zu2zLRVFf6bIFQK8= +github.com/asticode/go-astisub v0.34.0 h1:owKNj0A9pc7YVW/rNy2MJZ1mf0L8DTdklZVfyZDhTWI= +github.com/asticode/go-astisub v0.34.0/go.mod h1:WTkuSzFB+Bp7wezuSf2Oxulj5A8zu2zLRVFf6bIFQK8= github.com/asticode/go-astits v1.8.0 h1:rf6aiiGn/QhlFjNON1n5plqF3Fs025XLUwiQ0NB6oZg= github.com/asticode/go-astits v1.8.0/go.mod h1:DkOWmBNQpnr9mv24KfZjq4JawCFX1FCqjLVGvO0DygQ= github.com/aws/aws-sdk-go v1.38.20 h1:QbzNx/tdfATbdKfubBpkt84OM6oBkxQZRw6+bW2GyeA= @@ -104,6 +112,8 @@ github.com/cloudflare/circl v1.3.3 h1:fE/Qz0QdIGqeWfnwq0RE0R7MI51s0M2E4Ga9kq5AEM github.com/cloudflare/circl v1.3.3/go.mod h1:5XYMA4rFBvNIrhs50XuiBJ15vF2pZn4nnUKZrLbUZFA= github.com/cloudflare/circl v1.3.7 h1:qlCDlTPz2n9fu58M0Nh1J/JzcFpfgkFHHX3O35r5vcU= github.com/cloudflare/circl v1.3.7/go.mod h1:sRTcRWXGLrKw6yIGJ+l7amYJFfAXbZG0kBSc8r4zxgA= +github.com/cloudflare/circl v1.6.0 h1:cr5JKic4HI+LkINy2lg3W2jF8sHCVTBncJr5gIIq7qk= +github.com/cloudflare/circl v1.6.0/go.mod h1:uddAzsPgqdMAYatqJ0lsjX1oECcQLIlRpzZh3pJrofs= github.com/cloudwego/base64x v0.1.4 h1:jwCgWpFanWmN8xoIUHa2rtzmkd5J2plF/dnLS6Xd/0Y= github.com/cloudwego/base64x v0.1.4/go.mod h1:0zlkT4Wn5C6NdauXdJRhSKRlJvmclQ1hhJgA0rcu/8w= github.com/cloudwego/iasm v0.2.0 h1:1KNIy1I1H9hNNFEEH3DVnI4UujN+1zjpuk6gwHLTssg= @@ -113,6 +123,8 @@ github.com/cyphar/filepath-securejoin v0.2.4 h1:Ugdm7cg7i6ZK6x3xDF1oEu1nfkyfH53E github.com/cyphar/filepath-securejoin v0.2.4/go.mod h1:aPGpWjXOXUn2NCNjFvBE6aRxGGx79pTxQpKOJNYHHl4= github.com/cyphar/filepath-securejoin v0.3.6 h1:4d9N5ykBnSp5Xn2JkhocYDkOpURL/18CYMpo6xB9uWM= github.com/cyphar/filepath-securejoin v0.3.6/go.mod h1:Sdj7gXlvMcPZsbhwhQ33GguGLDGQL7h7bg04C/+u9jI= +github.com/cyphar/filepath-securejoin v0.4.1 h1:JyxxyPEaktOD+GAnqIqTf9A8tHyAG22rowi7HkoSU1s= +github.com/cyphar/filepath-securejoin v0.4.1/go.mod h1:Sdj7gXlvMcPZsbhwhQ33GguGLDGQL7h7bg04C/+u9jI= github.com/davecgh/go-spew v1.1.0/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38= github.com/davecgh/go-spew v1.1.1 h1:vj9j/u1bqnvCEfJOwUhtlOARqs3+rkHYY13jYWTU97c= github.com/davecgh/go-spew v1.1.1/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38= @@ -168,6 +180,8 @@ github.com/go-git/go-billy/v5 v5.5.0 h1:yEY4yhzCDuMGSv83oGxiBotRzhwhNr8VZyphhiu+ github.com/go-git/go-billy/v5 v5.5.0/go.mod h1:hmexnoNsr2SJU1Ju67OaNz5ASJY3+sHgFRpCtpDCKow= github.com/go-git/go-billy/v5 v5.6.1 h1:u+dcrgaguSSkbjzHwelEjc0Yj300NUevrrPphk/SoRA= github.com/go-git/go-billy/v5 v5.6.1/go.mod h1:0AsLr1z2+Uksi4NlElmMblP5rPcDZNRCD8ujZCRR2BE= +github.com/go-git/go-billy/v5 v5.6.2 h1:6Q86EsPXMa7c3YZ3aLAQsMA0VlWmy43r6FHqa/UNbRM= +github.com/go-git/go-billy/v5 v5.6.2/go.mod h1:rcFC2rAsp/erv7CMz9GczHcuD0D32fWzH+MJAU+jaUU= github.com/go-git/go-git-fixtures/v4 v4.2.1 h1:n9gGL1Ct/yIw+nfsfr8s4+sbhT+Ncu2SubfXjIWgci8= github.com/go-git/go-git-fixtures/v4 v4.2.1/go.mod h1:K8zd3kDUAykwTdDCr+I0per6Y6vMiRR/nnVTBtavnB0= github.com/go-git/go-git-fixtures/v4 v4.3.1/go.mod h1:8LHG1a3SRW71ettAD/jW13h8c6AqjVSeL11RAdgaqpo= @@ -199,6 +213,10 @@ github.com/go-git/go-git/v5 v5.12.0 h1:7Md+ndsjrzZxbddRDZjF14qK+NN56sy6wkqaVrjZt github.com/go-git/go-git/v5 v5.12.0/go.mod h1:FTM9VKtnI2m65hNI/TenDDDnUf2Q9FHnXYjuz9i5OEY= github.com/go-git/go-git/v5 v5.13.1 h1:DAQ9APonnlvSWpvolXWIuV6Q6zXy2wHbN4cVlNR5Q+M= github.com/go-git/go-git/v5 v5.13.1/go.mod h1:qryJB4cSBoq3FRoBRf5A77joojuBcmPJ0qu3XXXVixc= +github.com/go-git/go-git/v5 v5.13.2 h1:7O7xvsK7K+rZPKW6AQR1YyNhfywkv7B8/FsP3ki6Zv0= +github.com/go-git/go-git/v5 v5.13.2/go.mod h1:hWdW5P4YZRjmpGHwRH2v3zkWcNl6HeXaXQEMGb3NJ9A= +github.com/go-git/go-git/v5 v5.14.0 h1:/MD3lCrGjCen5WfEAzKg00MJJffKhC8gzS80ycmCi60= +github.com/go-git/go-git/v5 v5.14.0/go.mod h1:Z5Xhoia5PcWA3NF8vRLURn9E5FRhSl7dGj9ItW3Wk5k= github.com/go-logr/logr v0.1.0/go.mod h1:ixOQHD9gLJUVQQ2ZOR7zLEifBX6tGkNJF4QyIY7sIas= github.com/go-playground/assert/v2 v2.0.1 h1:MsBgLAaY856+nPRTKrp3/OZK38U/wa0CcBYNjji3q3A= github.com/go-playground/assert/v2 v2.0.1/go.mod h1:VDjEfimB/XKnb+ZQfWdccd7VUvScMdVu0Titje2rxJ4= @@ -243,12 +261,15 @@ github.com/goccy/go-json v0.10.2/go.mod h1:6MelG93GURQebXPDq3khkgXZkazVtN9CRI+MG github.com/gogo/protobuf v1.3.1/go.mod h1:SlYgWuQ5SjCEi6WLHjHCa1yvBfUnHcTbrrZtXPKa29o= github.com/golang/groupcache v0.0.0-20210331224755-41bb18bfe9da h1:oI5xCqsCo564l8iNU+DwB5epxmsaqB+rhGL0m5jtYqE= github.com/golang/groupcache v0.0.0-20210331224755-41bb18bfe9da/go.mod h1:cIg4eruTrX1D+g88fzRXU5OdNfaM+9IcxsU14FzY7Hc= +github.com/golang/groupcache v0.0.0-20241129210726-2c02b8208cf8 h1:f+oWsMOmNPc8JmEHVZIycC7hBoQxHH9pNKQORJNozsQ= +github.com/golang/groupcache v0.0.0-20241129210726-2c02b8208cf8/go.mod h1:wcDNUvekVysuuOpQKo3191zZyTpiI6se1N1ULghS0sw= github.com/golang/protobuf v1.3.1/go.mod h1:6lQm79b+lXiMfvg/cZm0SGofjICqVBUtrP5yJMmIC1U= github.com/golang/protobuf v1.5.0/go.mod h1:FsONVRAS9T7sI+LIUmWTfcYkHO4aIWwzhcaSAoJOfIk= github.com/golang/protobuf v1.5.2 h1:ROPKBNFfQgOUMifHyP+KYbvpjbdoFNs+aK7DXlji0Tw= github.com/golang/protobuf v1.5.2/go.mod h1:XVQd3VNwM+JqD3oG2Ue2ip4fOMUkwXdXDdiuN0vRsmY= github.com/golang/protobuf v1.5.3 h1:KhyjKVUg7Usr/dYsdSqoFveMYd5ko72D+zANwlG1mmg= github.com/golang/protobuf v1.5.3/go.mod h1:XVQd3VNwM+JqD3oG2Ue2ip4fOMUkwXdXDdiuN0vRsmY= +github.com/golang/protobuf v1.5.4/go.mod h1:lnTiLA8Wa4RWRcIUkrtSVa5nRhsEGBg48fD6rSs7xps= github.com/google/go-cmp v0.3.0/go.mod h1:8QqcDgzrUqlUb/G2PQTWiueGozuR1884gddMywk6iLU= github.com/google/go-cmp v0.5.5/go.mod h1:v8dTdLbMG2kIc/vJvl+f65V22dbkXbowE6jgT/gNBxE= github.com/google/go-cmp v0.5.8 h1:e6P7q2lk1O+qJJb4BtCQXlK8vWEO8V1ZeuEdJNOqZyg= @@ -352,6 +373,8 @@ github.com/pjbgf/sha1cd v0.2.3 h1:uKQP/7QOzNtKYH7UTohZLcjF5/55EnTw0jO/Ru4jZwI= github.com/pjbgf/sha1cd v0.2.3/go.mod h1:HOK9QrgzdHpbc2Kzip0Q1yi3M2MFGPADtR6HjG65m5M= github.com/pjbgf/sha1cd v0.3.0 h1:4D5XXmUUBUl/xQ6IjCkEAbqXskkq/4O7LmGn0AqMDs4= github.com/pjbgf/sha1cd v0.3.0/go.mod h1:nZ1rrWOcGJ5uZgEEVL1VUM9iRQiZvWdbZjkKyFzPPsI= +github.com/pjbgf/sha1cd v0.3.2 h1:a9wb0bp1oC2TGwStyn0Umc/IGKQnEgF0vVaZ8QF8eo4= +github.com/pjbgf/sha1cd v0.3.2/go.mod h1:zQWigSxVmsHEZow5qaLtPYxpcKMMQpa09ixqBxuCS6A= github.com/pkg/diff v0.0.0-20210226163009-20ebb0f2a09e/go.mod h1:pJLUxLENpZxwdsKMEsNbx1VGcRFpLqf3715MtcvvzbA= github.com/pkg/errors v0.8.1/go.mod h1:bwawxfHBFNV+L2hUp1rHADufV3IMtnDRdf1r5NINEl0= github.com/pkg/errors v0.9.1 h1:FEBLx1zS214owpjy7qsBeixbURkuhQAwrK5UwLGTwt4= @@ -382,6 +405,8 @@ github.com/skeema/knownhosts v1.2.2 h1:Iug2P4fLmDw9f41PB6thxUkNUkJzB5i+1/exaj40L github.com/skeema/knownhosts v1.2.2/go.mod h1:xYbVRSPxqBZFrdmDyMmsOs+uX1UZC3nTN3ThzgDxUwo= github.com/skeema/knownhosts v1.3.0 h1:AM+y0rI04VksttfwjkSTNQorvGqmwATnvnAHpSgc0LY= github.com/skeema/knownhosts v1.3.0/go.mod h1:sPINvnADmT/qYH1kfv+ePMmOBTH6Tbl7b5LvTDjFK7M= +github.com/skeema/knownhosts v1.3.1 h1:X2osQ+RAjK76shCbvhHHHVl3ZlgDm8apHEHFqRjnBY8= +github.com/skeema/knownhosts v1.3.1/go.mod h1:r7KTdC8l4uxWRyK2TpQZ/1o5HaSzh06ePQNxPwTcfiY= github.com/spf13/afero v1.2.2/go.mod h1:9ZxEEn6pIJ8Rxe320qSDBk6AsU0r9pR7Q4OcevTdifk= github.com/stretchr/objx v0.1.0/go.mod h1:HFkY916IF+rwdDfMAkV7OtwuqBVzrE8GR6GFx+wExME= github.com/stretchr/objx v0.1.1/go.mod h1:HFkY916IF+rwdDfMAkV7OtwuqBVzrE8GR6GFx+wExME= @@ -542,6 +567,12 @@ golang.org/x/crypto v0.30.0 h1:RwoQn3GkWiMkzlX562cLB7OxWvjH1L8xutO2WoJcRoY= golang.org/x/crypto v0.30.0/go.mod h1:kDsLvtWBEx7MV9tJOj9bnXsPbxwJQ6csT/x4KIN4Ssk= golang.org/x/crypto v0.31.0 h1:ihbySMvVjLAeSH1IbfcRTkD/iNscyz8rGzjF/E5hV6U= golang.org/x/crypto v0.31.0/go.mod h1:kDsLvtWBEx7MV9tJOj9bnXsPbxwJQ6csT/x4KIN4Ssk= +golang.org/x/crypto v0.32.0 h1:euUpcYgM8WcP71gNpTqQCn6rC2t6ULUPiOzfWaXVVfc= +golang.org/x/crypto v0.32.0/go.mod h1:ZnnJkOaASj8g0AjIduWNlq2NRxL0PlBrbKVyZ6V/Ugc= +golang.org/x/crypto v0.33.0 h1:IOBPskki6Lysi0lo9qQvbxiQ+FvsCC/YWOecCHAixus= +golang.org/x/crypto v0.33.0/go.mod h1:bVdXmD7IV/4GdElGPozy6U7lWdRXA4qyRVGJV57uQ5M= +golang.org/x/crypto v0.36.0 h1:AnAEvhDddvBdpY+uR+MyHmuZzzNqXSe/GvuDeob5L34= +golang.org/x/crypto v0.36.0/go.mod h1:Y4J0ReaxCR1IMaabaSMugxJES1EpwhBHhv2bDHklZvc= golang.org/x/image v0.0.0-20191009234506-e7c1f5e7dbb8/go.mod h1:FeLwcggjj3mMvU+oOTbSwawSJRM1uh48EjtB4UJZlP0= golang.org/x/image v0.1.0 h1:r8Oj8ZA2Xy12/b5KZYj3tuv7NG/fBz3TwQVvpJ9l8Rk= golang.org/x/image v0.1.0/go.mod h1:iyPr49SD/G/TBxYVB/9RRtGUT5eNbo2u4NamWeQcD5c= @@ -589,6 +620,10 @@ golang.org/x/image v0.22.0 h1:UtK5yLUzilVrkjMAZAZ34DXGpASN8i8pj8g+O+yd10g= golang.org/x/image v0.22.0/go.mod h1:9hPFhljd4zZ1GNSIZJ49sqbp45GKK9t6w+iXvGqZUz4= golang.org/x/image v0.23.0 h1:HseQ7c2OpPKTPVzNjG5fwJsOTCiiwS4QdsYi5XU6H68= golang.org/x/image v0.23.0/go.mod h1:wJJBTdLfCCf3tiHa1fNxpZmUI4mmoZvwMCPP0ddoNKY= +golang.org/x/image v0.24.0 h1:AN7zRgVsbvmTfNyqIbbOraYL8mSwcKncEj8ofjgzcMQ= +golang.org/x/image v0.24.0/go.mod h1:4b/ITuLfqYq1hqZcjofwctIhi7sZh2WaCjvsBNjjya8= +golang.org/x/image v0.25.0 h1:Y6uW6rH1y5y/LK1J8BPWZtr6yZ7hrsy6hFrXjgsc2fQ= +golang.org/x/image v0.25.0/go.mod h1:tCAmOEGthTtkalusGp1g3xa2gke8J6c2N565dTyl9Rs= golang.org/x/lint v0.0.0-20200302205851-738671d3881b/go.mod h1:3xt1FjdF8hUf6vQPIChWIBhFzV8gjjsPE/fR3IyQdNY= golang.org/x/mod v0.1.1-0.20191105210325-c90efee705ee/go.mod h1:QqPTAvyqsEbceGzBzNggFXnrqF1CaUcvgkdR5Ot7KZg= golang.org/x/mod v0.6.0-dev.0.20220419223038-86c51ed26bb4/go.mod h1:jJ57K6gSWd91VN4djpZkiMVwK6gcyfeH4XE8wZrZaV4= @@ -657,6 +692,10 @@ golang.org/x/net v0.25.0 h1:d/OCCoBEUq33pjydKrGQhw7IlUPI2Oylr+8qLx49kac= golang.org/x/net v0.25.0/go.mod h1:JkAGAh7GEvH74S6FOH42FLoXpXbE/aqXSrIQjXgsiwM= golang.org/x/net v0.33.0 h1:74SYHlV8BIgHIFC/LrYkOGIwL19eTYXQ5wc6TBuO36I= golang.org/x/net v0.33.0/go.mod h1:HXLR5J+9DxmrqMwG9qjGCxZ+zKXxBru04zlTvWlWuN4= +golang.org/x/net v0.34.0 h1:Mb7Mrk043xzHgnRM88suvJFwzVrRfHEHJEl5/71CKw0= +golang.org/x/net v0.34.0/go.mod h1:di0qlW3YNM5oh6GqDGQr92MyTozJPmybPK4Ev/Gm31k= +golang.org/x/net v0.35.0 h1:T5GQRQb2y08kTAByq9L4/bz8cipCdA8FbRTXewonqY8= +golang.org/x/net v0.35.0/go.mod h1:EglIi67kWsHKlRzzVMUD93VMSWGFOMSZgxFjparz1Qk= golang.org/x/oauth2 v0.1.0 h1:isLCZuhj4v+tYv7eskaN4v/TM+A1begWWgyVJDdl1+Y= golang.org/x/oauth2 v0.1.0/go.mod h1:G9FE4dLTsbXUu90h/Pf85g4w1D+SSAgR+q46nJZ8M4A= golang.org/x/oauth2 v0.2.0 h1:GtQkldQ9m7yvzCL1V+LrYow3Khe0eJH0w7RbX/VbaIU= @@ -707,6 +746,10 @@ golang.org/x/oauth2 v0.24.0 h1:KTBBxWqUa0ykRPLtV69rRto9TLXcqYkeswu48x/gvNE= golang.org/x/oauth2 v0.24.0/go.mod h1:XYTD2NtWslqkgxebSiOHnXEap4TF09sJSc7H1sXbhtI= golang.org/x/oauth2 v0.25.0 h1:CY4y7XT9v0cRI9oupztF8AgiIu99L/ksR/Xp/6jrZ70= golang.org/x/oauth2 v0.25.0/go.mod h1:XYTD2NtWslqkgxebSiOHnXEap4TF09sJSc7H1sXbhtI= +golang.org/x/oauth2 v0.26.0 h1:afQXWNNaeC4nvZ0Ed9XvCCzXM6UHJG7iCg0W4fPqSBE= +golang.org/x/oauth2 v0.26.0/go.mod h1:XYTD2NtWslqkgxebSiOHnXEap4TF09sJSc7H1sXbhtI= +golang.org/x/oauth2 v0.28.0 h1:CrgCKl8PPAVtLnU3c+EDw6x11699EWlsDeWNWKdIOkc= +golang.org/x/oauth2 v0.28.0/go.mod h1:onh5ek6nERTohokkhCD/y2cV4Do3fxFHFuAejCkRWT8= golang.org/x/sync v0.0.0-20190423024810-112230192c58/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= golang.org/x/sync v0.0.0-20220722155255-886fb9371eb4/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= golang.org/x/sync v0.1.0/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= @@ -718,6 +761,10 @@ golang.org/x/sync v0.9.0 h1:fEo0HyrW1GIgZdpbhCRO0PkJajUS5H9IFUztCgEo2jQ= golang.org/x/sync v0.9.0/go.mod h1:Czt+wKu1gCyEFDUtn0jG5QVvpJ6rzVqr5aXyt9drQfk= golang.org/x/sync v0.10.0 h1:3NQrjDixjgGwUOCaF8w2+VYHv0Ve/vGYSbdkTa98gmQ= golang.org/x/sync v0.10.0/go.mod h1:Czt+wKu1gCyEFDUtn0jG5QVvpJ6rzVqr5aXyt9drQfk= +golang.org/x/sync v0.11.0 h1:GGz8+XQP4FvTTrjZPzNKTMFtSXH80RAzG+5ghFPgK9w= +golang.org/x/sync v0.11.0/go.mod h1:Czt+wKu1gCyEFDUtn0jG5QVvpJ6rzVqr5aXyt9drQfk= +golang.org/x/sync v0.12.0 h1:MHc5BpPuC30uJk597Ri8TV3CNZcTLu6B6z4lJy+g6Jw= +golang.org/x/sync v0.12.0/go.mod h1:1dzgHSNfp02xaA81J2MS99Qcpr2w7fw1gpm99rleRqA= golang.org/x/sys v0.0.0-20180905080454-ebe1bf3edb33/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY= golang.org/x/sys v0.0.0-20190215142949-d0b11bdaac8a/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY= golang.org/x/sys v0.0.0-20190412213103-97732733099d/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= @@ -798,6 +845,12 @@ golang.org/x/sys v0.27.0 h1:wBqf8DvsY9Y/2P8gAfPDEYNuS30J4lPHJxXSb/nJZ+s= golang.org/x/sys v0.27.0/go.mod h1:/VUhepiaJMQUp4+oa/7Zr1D23ma6VTLIYjOOTFZPUcA= golang.org/x/sys v0.28.0 h1:Fksou7UEQUWlKvIdsqzJmUmCX3cZuD2+P3XyyzwMhlA= golang.org/x/sys v0.28.0/go.mod h1:/VUhepiaJMQUp4+oa/7Zr1D23ma6VTLIYjOOTFZPUcA= +golang.org/x/sys v0.29.0 h1:TPYlXGxvx1MGTn2GiZDhnjPA9wZzZeGKHHmKhHYvgaU= +golang.org/x/sys v0.29.0/go.mod h1:/VUhepiaJMQUp4+oa/7Zr1D23ma6VTLIYjOOTFZPUcA= +golang.org/x/sys v0.30.0 h1:QjkSwP/36a20jFYWkSue1YwXzLmsV5Gfq7Eiy72C1uc= +golang.org/x/sys v0.30.0/go.mod h1:/VUhepiaJMQUp4+oa/7Zr1D23ma6VTLIYjOOTFZPUcA= +golang.org/x/sys v0.31.0 h1:ioabZlmFYtWhL+TRYpcnNlLwhyxaM9kWTDEmfnprqik= +golang.org/x/sys v0.31.0/go.mod h1:BJP2sWEmIv4KK5OTEluFJCKSidICx8ciO85XgH3Ak8k= golang.org/x/term v0.0.0-20201126162022-7de9c90e9dd1/go.mod h1:bj7SfCRtBDWHUb9snDiAeCFNEtKQo2Wmx5Cou7ajbmo= golang.org/x/term v0.0.0-20210927222741-03fcf44c2211/go.mod h1:jbD1KX2456YbFQfuXm/mYQcufACuNUgVhRMnK/tPxf8= golang.org/x/term v0.0.0-20220722155259-a9ba230a4035/go.mod h1:jbD1KX2456YbFQfuXm/mYQcufACuNUgVhRMnK/tPxf8= @@ -847,6 +900,10 @@ golang.org/x/text v0.20.0 h1:gK/Kv2otX8gz+wn7Rmb3vT96ZwuoxnQlY+HlJVj7Qug= golang.org/x/text v0.20.0/go.mod h1:D4IsuqiFMhST5bX19pQ9ikHC2GsaKyk/oF+pn3ducp4= golang.org/x/text v0.21.0 h1:zyQAAkrwaneQ066sspRyJaG9VNi/YJ1NfzcGB3hZ/qo= golang.org/x/text v0.21.0/go.mod h1:4IBbMaMmOPCJ8SecivzSH54+73PCFmPWxNTLm+vZkEQ= +golang.org/x/text v0.22.0 h1:bofq7m3/HAFvbF51jz3Q9wLg3jkvSPuiZu/pD1XwgtM= +golang.org/x/text v0.22.0/go.mod h1:YRoo4H8PVmsu+E3Ou7cqLVH8oXWIHVoX0jqUWALQhfY= +golang.org/x/text v0.23.0 h1:D71I7dUrlY+VX0gQShAThNGHFxZ13dGLBHQLVl1mJlY= +golang.org/x/text v0.23.0/go.mod h1:/BLNzu4aZCJ1+kcD0DNRotWKage4q2rGVAg4o22unh4= golang.org/x/time v0.0.0-20190308202827-9d24e82272b4/go.mod h1:tRJNPiyCQ0inRvYxbN9jk5I+vvW/OXSQhTDSoE431IQ= golang.org/x/tools v0.0.0-20180917221912-90fa682c2a6e/go.mod h1:n7NCudcB/nEzxVGmLbDWY5pfWTLqBcC2KZ6jyYvM4mQ= golang.org/x/tools v0.0.0-20181030221726-6c7e314b6563/go.mod h1:n7NCudcB/nEzxVGmLbDWY5pfWTLqBcC2KZ6jyYvM4mQ= diff --git a/libfic/cyberrange.go b/libfic/cyberrange.go new file mode 100644 index 00000000..b8aaa1c1 --- /dev/null +++ b/libfic/cyberrange.go @@ -0,0 +1,26 @@ +package fic + +import () + +type CyberrangeAPIResponse struct { + Data interface{} + CurrentPage int `json:"current_page"` + PerPage int `json:"per_page"` + LastPage int `json:"last_page"` + Total int `json:"total"` +} + +type CyberrangeTeam struct { + UUID string `json:"session_uuid"` + Members []CyberrangeTeamMember `json:"members"` + Name string `json:"name"` + Score int64 `json:"score"` + Rank int `json:"rank"` +} + +type CyberrangeTeamMember struct { + UUID string `json:"session_uuid"` + Name string `json:"name"` + Nickname string `json:"nickname"` + EMail string `json:"email"` +} diff --git a/libfic/db.go b/libfic/db.go index ae6826ae..0a96120e 100644 --- a/libfic/db.go +++ b/libfic/db.go @@ -414,6 +414,7 @@ CREATE TABLE IF NOT EXISTS exercice_solved( } if _, err := db.Exec(` CREATE TABLE IF NOT EXISTS exercice_tries( + id_try INTEGER NOT NULL PRIMARY KEY AUTO_INCREMENT, id_exercice INTEGER NOT NULL, id_team INTEGER NOT NULL, time TIMESTAMP NOT NULL, @@ -423,6 +424,26 @@ CREATE TABLE IF NOT EXISTS exercice_tries( FOREIGN KEY(id_exercice) REFERENCES exercices(id_exercice), FOREIGN KEY(id_team) REFERENCES teams(id_team) ) DEFAULT CHARACTER SET = utf8mb4 COLLATE = utf8mb4_unicode_ci; +`); err != nil { + return err + } + if _, err := db.Exec(` +CREATE TABLE IF NOT EXISTS exercice_tries_flags( + id_try INTEGER NOT NULL, + id_flag INTEGER NOT NULL, + FOREIGN KEY(id_try) REFERENCES exercice_tries(id_try) ON DELETE CASCADE, + FOREIGN KEY(id_flag) REFERENCES exercice_flags(id_flag) ON DELETE CASCADE +) DEFAULT CHARACTER SET = utf8mb4 COLLATE = utf8mb4_unicode_ci; +`); err != nil { + return err + } + if _, err := db.Exec(` +CREATE TABLE IF NOT EXISTS exercice_tries_mcq( + id_try INTEGER NOT NULL, + id_mcq INTEGER NOT NULL, + FOREIGN KEY(id_try) REFERENCES exercice_tries(id_try) ON DELETE CASCADE, + FOREIGN KEY(id_mcq) REFERENCES exercice_mcq(id_mcq) ON DELETE CASCADE +) DEFAULT CHARACTER SET = utf8mb4 COLLATE = utf8mb4_unicode_ci; `); err != nil { return err } diff --git a/libfic/exercice.go b/libfic/exercice.go index c9979fcb..d6b38121 100644 --- a/libfic/exercice.go +++ b/libfic/exercice.go @@ -3,6 +3,7 @@ package fic import ( "errors" "fmt" + "log" "math" "time" ) @@ -444,11 +445,25 @@ func (e *Exercice) GetOrdinal() (int, error) { } // NewTry registers a solving attempt for the given Team. -func (e *Exercice) NewTry(t *Team, cksum []byte) error { - if _, err := DBExec("INSERT INTO exercice_tries (id_exercice, id_team, time, cksum) VALUES (?, ?, ?, ?)", e.Id, t.Id, time.Now(), cksum); err != nil { - return err +func (e *Exercice) NewTry(t *Team, cksum []byte, flags ...Flag) (int64, error) { + if res, err := DBExec("INSERT INTO exercice_tries (id_exercice, id_team, time, cksum) VALUES (?, ?, ?, ?)", e.Id, t.Id, time.Now(), cksum); err != nil { + return 0, err } else { - return nil + return res.LastInsertId() + } +} + +func (e *Exercice) NewTryFlag(tryid int64, flags ...Flag) { + for _, flag := range flags { + if fk, ok := flag.(*FlagKey); ok { + if _, err := DBExec("INSERT INTO exercice_tries_flags (id_try, id_flag) VALUES (?, ?)", tryid, fk.Id); err != nil { + log.Println("Unable to add detailed try: ", err.Error()) + } + } else if fm, ok := flag.(*MCQ); ok { + if _, err := DBExec("INSERT INTO exercice_tries_mcq (id_try, id_mcq) VALUES (?, ?)", tryid, fm.Id); err != nil { + log.Println("Unable to add detailed try: ", err.Error()) + } + } } } @@ -550,7 +565,7 @@ func (e *Exercice) MCQSolved() (res []int64) { // CheckResponse, given both flags and MCQ responses, figures out if thoses are correct (or if they are previously solved). // In the meanwhile, CheckResponse registers good answers given (but it does not mark the challenge as solved at the end). func (e *Exercice) CheckResponse(cksum []byte, respflags map[int]string, respmcq map[int]bool, t *Team) (bool, error) { - if err := e.NewTry(t, cksum); err != nil { + if tryId, err := e.NewTry(t, cksum); err != nil { return false, err } else if flags, err := e.GetFlagKeys(); err != nil { return false, err @@ -565,6 +580,10 @@ func (e *Exercice) CheckResponse(cksum []byte, respflags map[int]string, respmcq // Check MCQs for _, mcq := range mcqs { + if mcq.HasOneEntry(respmcq) { + e.NewTryFlag(tryId, mcq) + } + if d := mcq.Check(respmcq); d > 0 { if !PartialValidation || t.HasPartiallySolved(mcq) == nil { valid = false @@ -589,15 +608,21 @@ func (e *Exercice) CheckResponse(cksum []byte, respflags map[int]string, respmcq for _, flag := range flags { if res, ok := respflags[flag.Id]; !ok && (!PartialValidation || t.HasPartiallySolved(flag) == nil) { valid = valid && flag.IsOptionnal() - } else if flag.Check([]byte(res)) != 0 { - if !PartialValidation || t.HasPartiallySolved(flag) == nil { - valid = valid && flag.IsOptionnal() + } else if ok { + if len(res) > 0 { + e.NewTryFlag(tryId, flag) } - } else { - err := flag.FoundBy(t) - if err == nil { - // err is unicity issue, probably flag already found - goodResponses += 1 + + if flag.Check([]byte(res)) != 0 { + if !PartialValidation || t.HasPartiallySolved(flag) == nil { + valid = valid && flag.IsOptionnal() + } + } else { + err := flag.FoundBy(t) + if err == nil { + // err is unicity issue, probably flag already found + goodResponses += 1 + } } } } diff --git a/libfic/exercice_history.go b/libfic/exercice_history.go index 63dab2dd..763c48d7 100644 --- a/libfic/exercice_history.go +++ b/libfic/exercice_history.go @@ -68,7 +68,8 @@ func (e *Exercice) AppendHistoryItem(tId int64, kind string, secondary *int64) e if kind == "tries" { bid := make([]byte, 5) binary.LittleEndian.PutUint32(bid, rand.Uint32()) - return (&Exercice{Id: e.Id}).NewTry(team, bid) + _, err = (&Exercice{Id: e.Id}).NewTry(team, bid) + return err } else if kind == "hint" && secondary != nil { return team.OpenHint(&EHint{Id: *secondary}) } else if kind == "wchoices" && secondary != nil { diff --git a/libfic/file.go b/libfic/file.go index 4e5bf37f..d39bb6b0 100644 --- a/libfic/file.go +++ b/libfic/file.go @@ -392,7 +392,12 @@ func (f *EFile) GetDepends() ([]Flag, error) { // CheckFileOnDisk recalculates the hash of the file on disk. func (f *EFile) CheckFileOnDisk() error { - if _, size, err := checkFileHash(path.Join(FilesDir, f.Path), f.Checksum); err != nil { + firstChecksum := f.Checksum + if len(f.ChecksumShown) > 0 { + firstChecksum = f.ChecksumShown + } + + if _, size, err := checkFileHash(path.Join(FilesDir, f.Path), firstChecksum); size > 0 && err != nil { return err } else if size == 0 { if _, _, err := checkFileHash(path.Join(FilesDir, f.Path+".gz"), f.Checksum); err != nil { @@ -400,9 +405,17 @@ func (f *EFile) CheckFileOnDisk() error { } else { return nil } - } else { - return nil + } else if err != nil { + return err } + + if _, err := os.Stat(path.Join(FilesDir, f.Path+".gz")); !os.IsNotExist(err) { + if _, _, err = checkFileHash(path.Join(FilesDir, f.Path+".gz"), f.Checksum); err != nil { + return err + } + } + + return nil } // GunzipFileOnDisk gunzip a compressed file. diff --git a/libfic/flag.go b/libfic/flag.go index 06373495..2e419bf1 100644 --- a/libfic/flag.go +++ b/libfic/flag.go @@ -14,6 +14,9 @@ type Flag interface { Check(val interface{}) int IsOptionnal() bool FoundBy(t *Team) error + NbTries() (int64, error) + TeamsOnIt() ([]int64, error) + DeleteTries() error } // GetFlag returns a list of flags comming with the challenge. diff --git a/libfic/flag_key.go b/libfic/flag_key.go index 905d1942..40da9348 100644 --- a/libfic/flag_key.go +++ b/libfic/flag_key.go @@ -230,6 +230,54 @@ func (k *FlagKey) RecoverId() (Flag, error) { } } +// NbTries returns the flag resolution statistics. +func (k *FlagKey) NbTries() (tries int64, err error) { + err = DBQueryRow("SELECT COUNT(*) AS tries FROM exercice_tries_flags WHERE id_flag = ?", k.Id).Scan(&tries) + return +} + +func (k *FlagKey) TeamsOnIt() ([]int64, error) { + if rows, err := DBQuery("SELECT DISTINCT M.id_team FROM exercice_tries_flags F INNER JOIN exercice_tries T ON T.id_try = F.id_try INNER JOIN teams M ON M.id_team = T.id_team WHERE id_flag = ?", k.Id); err != nil { + return nil, err + } else { + defer rows.Close() + + teams := []int64{} + for rows.Next() { + var idteam int64 + if err := rows.Scan(&idteam); err != nil { + return nil, err + } + teams = append(teams, idteam) + } + + return teams, nil + } +} + +func (k *FlagKey) DeleteTries() error { + if rows, err := DBQuery("SELECT id_try FROM exercice_tries_flags WHERE id_flag = ?", k.Id); err != nil { + return err + } else { + defer rows.Close() + + for rows.Next() { + var idtry int64 + err = rows.Scan(&idtry) + if err != nil { + return err + } + + _, err = DBExec("DELETE FROM exercice_tries WHERE id_try = ?", idtry) + if err != nil { + return err + } + } + + return nil + } +} + // AddFlagKey creates and fills a new struct Flag, from a hashed flag, and registers it into the database. func (k *FlagKey) Create(e *Exercice) (Flag, error) { // Check the regexp compile diff --git a/libfic/flag_label.go b/libfic/flag_label.go index 6d103f7f..eec13522 100644 --- a/libfic/flag_label.go +++ b/libfic/flag_label.go @@ -71,6 +71,18 @@ func (k *FlagLabel) RecoverId() (Flag, error) { } } +func (k *FlagLabel) NbTries() (int64, error) { + return 0, nil +} + +func (k *FlagLabel) TeamsOnIt() ([]int64, error) { + return nil, nil +} + +func (k *FlagLabel) DeleteTries() error { + return nil +} + // AddFlagLabel creates and fills a new struct Flag and registers it into the database. func (k *FlagLabel) Create(e *Exercice) (Flag, error) { if res, err := DBExec("INSERT INTO exercice_flag_labels (id_exercice, ordre, label, variant) VALUES (?, ?, ?, ?)", e.Id, k.Order, k.Label, k.Variant); err != nil { diff --git a/libfic/mcq.go b/libfic/mcq.go index 82315479..3129ec80 100644 --- a/libfic/mcq.go +++ b/libfic/mcq.go @@ -136,6 +136,54 @@ func (m *MCQ) RecoverId() (Flag, error) { } } +// NbTries returns the MCQ resolution statistics. +func (m *MCQ) NbTries() (tries int64, err error) { + err = DBQueryRow("SELECT COUNT(*) AS tries FROM exercice_tries_mcq WHERE id_mcq = ?", m.Id).Scan(&tries) + return +} + +func (m *MCQ) TeamsOnIt() ([]int64, error) { + if rows, err := DBQuery("SELECT DISTINCT M.id_team FROM exercice_tries_mcq F INNER JOIN exercice_tries T ON T.id_try = F.id_try INNER JOIN teams M ON M.id_team = T.id_team WHERE id_mcq = ?", m.Id); err != nil { + return nil, err + } else { + defer rows.Close() + + teams := []int64{} + for rows.Next() { + var idteam int64 + if err := rows.Scan(&idteam); err != nil { + return nil, err + } + teams = append(teams, idteam) + } + + return teams, nil + } +} + +func (m *MCQ) DeleteTries() error { + if rows, err := DBQuery("SELECT id_try FROM exercice_tries_mcq WHERE id_mcq = ?", m.Id); err != nil { + return err + } else { + defer rows.Close() + + for rows.Next() { + var idtry int64 + err = rows.Scan(&idtry) + if err != nil { + return err + } + + _, err = DBExec("DELETE FROM exercice_tries WHERE id_try = ?", idtry) + if err != nil { + return err + } + } + + return nil + } +} + // Create registers a MCQ into the database and recursively add its entries. func (m *MCQ) Create(e *Exercice) (Flag, error) { if res, err := DBExec("INSERT INTO exercice_mcq (id_exercice, ordre, title) VALUES (?, ?, ?)", e.Id, m.Order, m.Title); err != nil { @@ -207,7 +255,7 @@ func (m *MCQ) AddEntry(e *MCQ_entry) (*MCQ_entry, error) { // Update applies modifications back to the database. func (n *MCQ_entry) Update() (int64, error) { - if res, err := DBExec("UPDATE mcq_entries SET label = ?, response = ? WHERE id_mcq = ?", n.Label, n.Response, n.Id); err != nil { + if res, err := DBExec("UPDATE mcq_entries SET label = ?, response = ? WHERE id_mcq_entry = ?", n.Label, n.Response, n.Id); err != nil { return 0, err } else if nb, err := res.RowsAffected(); err != nil { return 0, err @@ -319,6 +367,24 @@ func (m *MCQ) IsOptionnal() bool { return false } +// Check if the given vals contains at least a response for the given MCQ. +func (m *MCQ) HasOneEntry(v interface{}) bool { + var vals map[int]bool + if va, ok := v.(map[int]bool); !ok { + return false + } else { + vals = va + } + + for _, n := range m.Entries { + if _, ok := vals[n.Id]; ok { + return true + } + } + + return false +} + // Check if the given vals are the expected ones to validate this flag. func (m *MCQ) Check(v interface{}) int { var vals map[int]bool diff --git a/libfic/utils.go b/libfic/utils.go index 0faf9e2c..42aecc90 100644 --- a/libfic/utils.go +++ b/libfic/utils.go @@ -3,6 +3,7 @@ package fic import ( "bytes" "crypto/md5" + "math/rand" "regexp" "strings" ) @@ -187,3 +188,11 @@ func (c HSL) ToRGB() (rgb uint32) { return r*65536 + g*256 + b } + +func RandomColor() HSL { + return HSL{ + H: rand.Float64(), + S: 1, + L: 0.5, + } +} diff --git a/qa/ui/package-lock.json b/qa/ui/package-lock.json index 091f2a05..da5a8832 100644 --- a/qa/ui/package-lock.json +++ b/qa/ui/package-lock.json @@ -8,7 +8,7 @@ "name": "qa", "version": "0.0.1", "dependencies": { - "@sveltestrap/sveltestrap": "^6.2.1", + "@sveltestrap/sveltestrap": "^7.0.0", "bootstrap": "^5.2.2", "bootstrap-icons": "^1.9.1" }, @@ -17,8 +17,8 @@ "@sveltejs/kit": "^2.0.0", "@sveltejs/vite-plugin-svelte": "^3.0.0", "eslint": "^9.0.0", - "eslint-config-prettier": "^9.0.0", - "eslint-plugin-svelte": "^2.35.1", + "eslint-config-prettier": "^10.0.0", + "eslint-plugin-svelte": "^3.0.0", "prettier": "^3.0.0", "prettier-plugin-svelte": "^3.1.2", "svelte": "^5.0.0", @@ -472,13 +472,13 @@ } }, "node_modules/@eslint/config-array": { - "version": "0.19.1", - "resolved": "https://registry.npmjs.org/@eslint/config-array/-/config-array-0.19.1.tgz", - "integrity": "sha512-fo6Mtm5mWyKjA/Chy1BYTdn5mGJoDNjC7C64ug20ADsRDGrA85bN3uK3MaKbeRkRuuIEAR5N33Jr1pbm411/PA==", + "version": "0.19.2", + "resolved": "https://registry.npmjs.org/@eslint/config-array/-/config-array-0.19.2.tgz", + "integrity": "sha512-GNKqxfHG2ySmJOBSHg7LxeUx4xpuCoFjacmlCoYWEbaPXLwvfIjixRI12xCQZeULksQb23uiA8F40w5TojpV7w==", "dev": true, "license": "Apache-2.0", "dependencies": { - "@eslint/object-schema": "^2.1.5", + "@eslint/object-schema": "^2.1.6", "debug": "^4.3.1", "minimatch": "^3.1.2" }, @@ -486,10 +486,20 @@ "node": "^18.18.0 || ^20.9.0 || >=21.1.0" } }, + "node_modules/@eslint/config-helpers": { + "version": "0.2.0", + "resolved": "https://registry.npmjs.org/@eslint/config-helpers/-/config-helpers-0.2.0.tgz", + "integrity": "sha512-yJLLmLexii32mGrhW29qvU3QBVTu0GUmEf/J4XsBtVhp4JkIUFN/BjWqTF63yRvGApIDpZm5fa97LtYtINmfeQ==", + "dev": true, + "license": "Apache-2.0", + "engines": { + "node": "^18.18.0 || ^20.9.0 || >=21.1.0" + } + }, "node_modules/@eslint/core": { - "version": "0.10.0", - "resolved": "https://registry.npmjs.org/@eslint/core/-/core-0.10.0.tgz", - "integrity": "sha512-gFHJ+xBOo4G3WRlR1e/3G8A6/KZAH6zcE/hkLRCZTi/B9avAG365QhFA8uOGzTMqgTghpn7/fSnscW++dpMSAw==", + "version": "0.12.0", + "resolved": "https://registry.npmjs.org/@eslint/core/-/core-0.12.0.tgz", + "integrity": "sha512-cmrR6pytBuSMTaBweKoGMwu3EiHiEC+DoyupPmlZ0HxBJBtIxwe+j/E4XPIKNx+Q74c8lXKPwYawBf5glsTkHg==", "dev": true, "license": "Apache-2.0", "dependencies": { @@ -500,9 +510,9 @@ } }, "node_modules/@eslint/eslintrc": { - "version": "3.2.0", - "resolved": "https://registry.npmjs.org/@eslint/eslintrc/-/eslintrc-3.2.0.tgz", - "integrity": "sha512-grOjVNN8P3hjJn/eIETF1wwd12DdnwFDoyceUJLYYdkpbwq3nLi+4fqrTAONx7XDALqlL220wC/RHSC/QTI/0w==", + "version": "3.3.1", + "resolved": "https://registry.npmjs.org/@eslint/eslintrc/-/eslintrc-3.3.1.tgz", + "integrity": "sha512-gtF186CXhIl1p4pJNGZw8Yc6RlshoePRvE0X91oPGb3vZ8pM3qOS9W9NGPat9LziaBV7XrJWGylNQXkGcnM3IQ==", "dev": true, "license": "MIT", "dependencies": { @@ -524,9 +534,9 @@ } }, "node_modules/@eslint/js": { - "version": "9.18.0", - "resolved": "https://registry.npmjs.org/@eslint/js/-/js-9.18.0.tgz", - "integrity": "sha512-fK6L7rxcq6/z+AaQMtiFTkvbHkBLNlwyRxHpKawP0x3u9+NC6MQTnFW+AdpwC6gfHTW0051cokQgtTN2FqlxQA==", + "version": "9.23.0", + "resolved": "https://registry.npmjs.org/@eslint/js/-/js-9.23.0.tgz", + "integrity": "sha512-35MJ8vCPU0ZMxo7zfev2pypqTwWTofFZO6m4KAtdoFhRpLJUpHTZZ+KB3C7Hb1d7bULYwO4lJXGCi5Se+8OMbw==", "dev": true, "license": "MIT", "engines": { @@ -534,9 +544,9 @@ } }, "node_modules/@eslint/object-schema": { - "version": "2.1.5", - "resolved": "https://registry.npmjs.org/@eslint/object-schema/-/object-schema-2.1.5.tgz", - "integrity": "sha512-o0bhxnL89h5Bae5T318nFoFzGy+YE5i/gGkoPAgkmTVdRKTiv3p8JHevPiPaMwoloKfEiiaHlawCqaZMqRm+XQ==", + "version": "2.1.6", + "resolved": "https://registry.npmjs.org/@eslint/object-schema/-/object-schema-2.1.6.tgz", + "integrity": "sha512-RBMg5FRL0I0gs51M/guSAj5/e14VQ4tpZnQNWwuDT66P14I43ItmPfIZRhO9fUVIPOAQXU47atlywZ/czoqFPA==", "dev": true, "license": "Apache-2.0", "engines": { @@ -544,13 +554,13 @@ } }, "node_modules/@eslint/plugin-kit": { - "version": "0.2.5", - "resolved": "https://registry.npmjs.org/@eslint/plugin-kit/-/plugin-kit-0.2.5.tgz", - "integrity": "sha512-lB05FkqEdUg2AA0xEbUz0SnkXT1LcCTa438W4IWTUh4hdOnVbQyOJ81OrDXsJk/LSiJHubgGEFoR5EHq1NsH1A==", + "version": "0.2.7", + "resolved": "https://registry.npmjs.org/@eslint/plugin-kit/-/plugin-kit-0.2.7.tgz", + "integrity": "sha512-JubJ5B2pJ4k4yGxaNLdbjrnk9d/iDz6/q8wOilpIowd6PJPgaxCuHBnBszq7Ce2TyMrywm5r4PnKm6V3iiZF+g==", "dev": true, "license": "Apache-2.0", "dependencies": { - "@eslint/core": "^0.10.0", + "@eslint/core": "^0.12.0", "levn": "^0.4.1" }, "engines": { @@ -610,9 +620,9 @@ } }, "node_modules/@humanwhocodes/retry": { - "version": "0.4.1", - "resolved": "https://registry.npmjs.org/@humanwhocodes/retry/-/retry-0.4.1.tgz", - "integrity": "sha512-c7hNEllBlenFTHBky65mhq8WD2kbN9Q6gk0bTk8lSBvc554jpXSkST1iePudpt7+A/AQvuHs9EMqjHDXMY1lrA==", + "version": "0.4.2", + "resolved": "https://registry.npmjs.org/@humanwhocodes/retry/-/retry-0.4.2.tgz", + "integrity": "sha512-xeO57FpIu4p1Ri3Jq/EXq4ClRm86dVF2z/+kvFnyqVYRavTZmaFaUBbWCOuuTh0o/g7DSsk6kc2vrS4Vl5oPOQ==", "dev": true, "license": "Apache-2.0", "engines": { @@ -689,9 +699,9 @@ } }, "node_modules/@rollup/rollup-android-arm-eabi": { - "version": "4.30.1", - "resolved": "https://registry.npmjs.org/@rollup/rollup-android-arm-eabi/-/rollup-android-arm-eabi-4.30.1.tgz", - "integrity": "sha512-pSWY+EVt3rJ9fQ3IqlrEUtXh3cGqGtPDH1FQlNZehO2yYxCHEX1SPsz1M//NXwYfbTlcKr9WObLnJX9FsS9K1Q==", + "version": "4.32.0", + "resolved": "https://registry.npmjs.org/@rollup/rollup-android-arm-eabi/-/rollup-android-arm-eabi-4.32.0.tgz", + "integrity": "sha512-G2fUQQANtBPsNwiVFg4zKiPQyjVKZCUdQUol53R8E71J7AsheRMV/Yv/nB8giOcOVqP7//eB5xPqieBYZe9bGg==", "cpu": [ "arm" ], @@ -703,9 +713,9 @@ ] }, "node_modules/@rollup/rollup-android-arm64": { - "version": "4.30.1", - "resolved": "https://registry.npmjs.org/@rollup/rollup-android-arm64/-/rollup-android-arm64-4.30.1.tgz", - "integrity": "sha512-/NA2qXxE3D/BRjOJM8wQblmArQq1YoBVJjrjoTSBS09jgUisq7bqxNHJ8kjCHeV21W/9WDGwJEWSN0KQ2mtD/w==", + "version": "4.32.0", + "resolved": "https://registry.npmjs.org/@rollup/rollup-android-arm64/-/rollup-android-arm64-4.32.0.tgz", + "integrity": "sha512-qhFwQ+ljoymC+j5lXRv8DlaJYY/+8vyvYmVx074zrLsu5ZGWYsJNLjPPVJJjhZQpyAKUGPydOq9hRLLNvh1s3A==", "cpu": [ "arm64" ], @@ -717,9 +727,9 @@ ] }, "node_modules/@rollup/rollup-darwin-arm64": { - "version": "4.30.1", - "resolved": "https://registry.npmjs.org/@rollup/rollup-darwin-arm64/-/rollup-darwin-arm64-4.30.1.tgz", - "integrity": "sha512-r7FQIXD7gB0WJ5mokTUgUWPl0eYIH0wnxqeSAhuIwvnnpjdVB8cRRClyKLQr7lgzjctkbp5KmswWszlwYln03Q==", + "version": "4.32.0", + "resolved": "https://registry.npmjs.org/@rollup/rollup-darwin-arm64/-/rollup-darwin-arm64-4.32.0.tgz", + "integrity": "sha512-44n/X3lAlWsEY6vF8CzgCx+LQaoqWGN7TzUfbJDiTIOjJm4+L2Yq+r5a8ytQRGyPqgJDs3Rgyo8eVL7n9iW6AQ==", "cpu": [ "arm64" ], @@ -731,9 +741,9 @@ ] }, "node_modules/@rollup/rollup-darwin-x64": { - "version": "4.30.1", - "resolved": "https://registry.npmjs.org/@rollup/rollup-darwin-x64/-/rollup-darwin-x64-4.30.1.tgz", - "integrity": "sha512-x78BavIwSH6sqfP2xeI1hd1GpHL8J4W2BXcVM/5KYKoAD3nNsfitQhvWSw+TFtQTLZ9OmlF+FEInEHyubut2OA==", + "version": "4.32.0", + "resolved": "https://registry.npmjs.org/@rollup/rollup-darwin-x64/-/rollup-darwin-x64-4.32.0.tgz", + "integrity": "sha512-F9ct0+ZX5Np6+ZDztxiGCIvlCaW87HBdHcozUfsHnj1WCUTBUubAoanhHUfnUHZABlElyRikI0mgcw/qdEm2VQ==", "cpu": [ "x64" ], @@ -745,9 +755,9 @@ ] }, "node_modules/@rollup/rollup-freebsd-arm64": { - "version": "4.30.1", - "resolved": "https://registry.npmjs.org/@rollup/rollup-freebsd-arm64/-/rollup-freebsd-arm64-4.30.1.tgz", - "integrity": "sha512-HYTlUAjbO1z8ywxsDFWADfTRfTIIy/oUlfIDmlHYmjUP2QRDTzBuWXc9O4CXM+bo9qfiCclmHk1x4ogBjOUpUQ==", + "version": "4.32.0", + "resolved": "https://registry.npmjs.org/@rollup/rollup-freebsd-arm64/-/rollup-freebsd-arm64-4.32.0.tgz", + "integrity": "sha512-JpsGxLBB2EFXBsTLHfkZDsXSpSmKD3VxXCgBQtlPcuAqB8TlqtLcbeMhxXQkCDv1avgwNjF8uEIbq5p+Cee0PA==", "cpu": [ "arm64" ], @@ -759,9 +769,9 @@ ] }, "node_modules/@rollup/rollup-freebsd-x64": { - "version": "4.30.1", - "resolved": "https://registry.npmjs.org/@rollup/rollup-freebsd-x64/-/rollup-freebsd-x64-4.30.1.tgz", - "integrity": "sha512-1MEdGqogQLccphhX5myCJqeGNYTNcmTyaic9S7CG3JhwuIByJ7J05vGbZxsizQthP1xpVx7kd3o31eOogfEirw==", + "version": "4.32.0", + "resolved": "https://registry.npmjs.org/@rollup/rollup-freebsd-x64/-/rollup-freebsd-x64-4.32.0.tgz", + "integrity": "sha512-wegiyBT6rawdpvnD9lmbOpx5Sph+yVZKHbhnSP9MqUEDX08G4UzMU+D87jrazGE7lRSyTRs6NEYHtzfkJ3FjjQ==", "cpu": [ "x64" ], @@ -773,9 +783,9 @@ ] }, "node_modules/@rollup/rollup-linux-arm-gnueabihf": { - "version": "4.30.1", - "resolved": "https://registry.npmjs.org/@rollup/rollup-linux-arm-gnueabihf/-/rollup-linux-arm-gnueabihf-4.30.1.tgz", - "integrity": "sha512-PaMRNBSqCx7K3Wc9QZkFx5+CX27WFpAMxJNiYGAXfmMIKC7jstlr32UhTgK6T07OtqR+wYlWm9IxzennjnvdJg==", + "version": "4.32.0", + "resolved": "https://registry.npmjs.org/@rollup/rollup-linux-arm-gnueabihf/-/rollup-linux-arm-gnueabihf-4.32.0.tgz", + "integrity": "sha512-3pA7xecItbgOs1A5H58dDvOUEboG5UfpTq3WzAdF54acBbUM+olDJAPkgj1GRJ4ZqE12DZ9/hNS2QZk166v92A==", "cpu": [ "arm" ], @@ -787,9 +797,9 @@ ] }, "node_modules/@rollup/rollup-linux-arm-musleabihf": { - "version": "4.30.1", - "resolved": "https://registry.npmjs.org/@rollup/rollup-linux-arm-musleabihf/-/rollup-linux-arm-musleabihf-4.30.1.tgz", - "integrity": "sha512-B8Rcyj9AV7ZlEFqvB5BubG5iO6ANDsRKlhIxySXcF1axXYUyqwBok+XZPgIYGBgs7LDXfWfifxhw0Ik57T0Yug==", + "version": "4.32.0", + "resolved": "https://registry.npmjs.org/@rollup/rollup-linux-arm-musleabihf/-/rollup-linux-arm-musleabihf-4.32.0.tgz", + "integrity": "sha512-Y7XUZEVISGyge51QbYyYAEHwpGgmRrAxQXO3siyYo2kmaj72USSG8LtlQQgAtlGfxYiOwu+2BdbPjzEpcOpRmQ==", "cpu": [ "arm" ], @@ -801,9 +811,9 @@ ] }, "node_modules/@rollup/rollup-linux-arm64-gnu": { - "version": "4.30.1", - "resolved": "https://registry.npmjs.org/@rollup/rollup-linux-arm64-gnu/-/rollup-linux-arm64-gnu-4.30.1.tgz", - "integrity": "sha512-hqVyueGxAj3cBKrAI4aFHLV+h0Lv5VgWZs9CUGqr1z0fZtlADVV1YPOij6AhcK5An33EXaxnDLmJdQikcn5NEw==", + "version": "4.32.0", + "resolved": "https://registry.npmjs.org/@rollup/rollup-linux-arm64-gnu/-/rollup-linux-arm64-gnu-4.32.0.tgz", + "integrity": "sha512-r7/OTF5MqeBrZo5omPXcTnjvv1GsrdH8a8RerARvDFiDwFpDVDnJyByYM/nX+mvks8XXsgPUxkwe/ltaX2VH7w==", "cpu": [ "arm64" ], @@ -815,9 +825,9 @@ ] }, "node_modules/@rollup/rollup-linux-arm64-musl": { - "version": "4.30.1", - "resolved": "https://registry.npmjs.org/@rollup/rollup-linux-arm64-musl/-/rollup-linux-arm64-musl-4.30.1.tgz", - "integrity": "sha512-i4Ab2vnvS1AE1PyOIGp2kXni69gU2DAUVt6FSXeIqUCPIR3ZlheMW3oP2JkukDfu3PsexYRbOiJrY+yVNSk9oA==", + "version": "4.32.0", + "resolved": "https://registry.npmjs.org/@rollup/rollup-linux-arm64-musl/-/rollup-linux-arm64-musl-4.32.0.tgz", + "integrity": "sha512-HJbifC9vex9NqnlodV2BHVFNuzKL5OnsV2dvTw6e1dpZKkNjPG6WUq+nhEYV6Hv2Bv++BXkwcyoGlXnPrjAKXw==", "cpu": [ "arm64" ], @@ -829,9 +839,9 @@ ] }, "node_modules/@rollup/rollup-linux-loongarch64-gnu": { - "version": "4.30.1", - "resolved": "https://registry.npmjs.org/@rollup/rollup-linux-loongarch64-gnu/-/rollup-linux-loongarch64-gnu-4.30.1.tgz", - "integrity": "sha512-fARcF5g296snX0oLGkVxPmysetwUk2zmHcca+e9ObOovBR++9ZPOhqFUM61UUZ2EYpXVPN1redgqVoBB34nTpQ==", + "version": "4.32.0", + "resolved": "https://registry.npmjs.org/@rollup/rollup-linux-loongarch64-gnu/-/rollup-linux-loongarch64-gnu-4.32.0.tgz", + "integrity": "sha512-VAEzZTD63YglFlWwRj3taofmkV1V3xhebDXffon7msNz4b14xKsz7utO6F8F4cqt8K/ktTl9rm88yryvDpsfOw==", "cpu": [ "loong64" ], @@ -843,9 +853,9 @@ ] }, "node_modules/@rollup/rollup-linux-powerpc64le-gnu": { - "version": "4.30.1", - "resolved": "https://registry.npmjs.org/@rollup/rollup-linux-powerpc64le-gnu/-/rollup-linux-powerpc64le-gnu-4.30.1.tgz", - "integrity": "sha512-GLrZraoO3wVT4uFXh67ElpwQY0DIygxdv0BNW9Hkm3X34wu+BkqrDrkcsIapAY+N2ATEbvak0XQ9gxZtCIA5Rw==", + "version": "4.32.0", + "resolved": "https://registry.npmjs.org/@rollup/rollup-linux-powerpc64le-gnu/-/rollup-linux-powerpc64le-gnu-4.32.0.tgz", + "integrity": "sha512-Sts5DST1jXAc9YH/iik1C9QRsLcCoOScf3dfbY5i4kH9RJpKxiTBXqm7qU5O6zTXBTEZry69bGszr3SMgYmMcQ==", "cpu": [ "ppc64" ], @@ -857,9 +867,9 @@ ] }, "node_modules/@rollup/rollup-linux-riscv64-gnu": { - "version": "4.30.1", - "resolved": "https://registry.npmjs.org/@rollup/rollup-linux-riscv64-gnu/-/rollup-linux-riscv64-gnu-4.30.1.tgz", - "integrity": "sha512-0WKLaAUUHKBtll0wvOmh6yh3S0wSU9+yas923JIChfxOaaBarmb/lBKPF0w/+jTVozFnOXJeRGZ8NvOxvk/jcw==", + "version": "4.32.0", + "resolved": "https://registry.npmjs.org/@rollup/rollup-linux-riscv64-gnu/-/rollup-linux-riscv64-gnu-4.32.0.tgz", + "integrity": "sha512-qhlXeV9AqxIyY9/R1h1hBD6eMvQCO34ZmdYvry/K+/MBs6d1nRFLm6BOiITLVI+nFAAB9kUB6sdJRKyVHXnqZw==", "cpu": [ "riscv64" ], @@ -871,9 +881,9 @@ ] }, "node_modules/@rollup/rollup-linux-s390x-gnu": { - "version": "4.30.1", - "resolved": "https://registry.npmjs.org/@rollup/rollup-linux-s390x-gnu/-/rollup-linux-s390x-gnu-4.30.1.tgz", - "integrity": "sha512-GWFs97Ruxo5Bt+cvVTQkOJ6TIx0xJDD/bMAOXWJg8TCSTEK8RnFeOeiFTxKniTc4vMIaWvCplMAFBt9miGxgkA==", + "version": "4.32.0", + "resolved": "https://registry.npmjs.org/@rollup/rollup-linux-s390x-gnu/-/rollup-linux-s390x-gnu-4.32.0.tgz", + "integrity": "sha512-8ZGN7ExnV0qjXa155Rsfi6H8M4iBBwNLBM9lcVS+4NcSzOFaNqmt7djlox8pN1lWrRPMRRQ8NeDlozIGx3Omsw==", "cpu": [ "s390x" ], @@ -885,9 +895,9 @@ ] }, "node_modules/@rollup/rollup-linux-x64-gnu": { - "version": "4.30.1", - "resolved": "https://registry.npmjs.org/@rollup/rollup-linux-x64-gnu/-/rollup-linux-x64-gnu-4.30.1.tgz", - "integrity": "sha512-UtgGb7QGgXDIO+tqqJ5oZRGHsDLO8SlpE4MhqpY9Llpzi5rJMvrK6ZGhsRCST2abZdBqIBeXW6WPD5fGK5SDwg==", + "version": "4.32.0", + "resolved": "https://registry.npmjs.org/@rollup/rollup-linux-x64-gnu/-/rollup-linux-x64-gnu-4.32.0.tgz", + "integrity": "sha512-VDzNHtLLI5s7xd/VubyS10mq6TxvZBp+4NRWoW+Hi3tgV05RtVm4qK99+dClwTN1McA6PHwob6DEJ6PlXbY83A==", "cpu": [ "x64" ], @@ -899,9 +909,9 @@ ] }, "node_modules/@rollup/rollup-linux-x64-musl": { - "version": "4.30.1", - "resolved": "https://registry.npmjs.org/@rollup/rollup-linux-x64-musl/-/rollup-linux-x64-musl-4.30.1.tgz", - "integrity": "sha512-V9U8Ey2UqmQsBT+xTOeMzPzwDzyXmnAoO4edZhL7INkwQcaW1Ckv3WJX3qrrp/VHaDkEWIBWhRwP47r8cdrOow==", + "version": "4.32.0", + "resolved": "https://registry.npmjs.org/@rollup/rollup-linux-x64-musl/-/rollup-linux-x64-musl-4.32.0.tgz", + "integrity": "sha512-qcb9qYDlkxz9DxJo7SDhWxTWV1gFuwznjbTiov289pASxlfGbaOD54mgbs9+z94VwrXtKTu+2RqwlSTbiOqxGg==", "cpu": [ "x64" ], @@ -913,9 +923,9 @@ ] }, "node_modules/@rollup/rollup-win32-arm64-msvc": { - "version": "4.30.1", - "resolved": "https://registry.npmjs.org/@rollup/rollup-win32-arm64-msvc/-/rollup-win32-arm64-msvc-4.30.1.tgz", - "integrity": "sha512-WabtHWiPaFF47W3PkHnjbmWawnX/aE57K47ZDT1BXTS5GgrBUEpvOzq0FI0V/UYzQJgdb8XlhVNH8/fwV8xDjw==", + "version": "4.32.0", + "resolved": "https://registry.npmjs.org/@rollup/rollup-win32-arm64-msvc/-/rollup-win32-arm64-msvc-4.32.0.tgz", + "integrity": "sha512-pFDdotFDMXW2AXVbfdUEfidPAk/OtwE/Hd4eYMTNVVaCQ6Yl8et0meDaKNL63L44Haxv4UExpv9ydSf3aSayDg==", "cpu": [ "arm64" ], @@ -927,9 +937,9 @@ ] }, "node_modules/@rollup/rollup-win32-ia32-msvc": { - "version": "4.30.1", - "resolved": "https://registry.npmjs.org/@rollup/rollup-win32-ia32-msvc/-/rollup-win32-ia32-msvc-4.30.1.tgz", - "integrity": "sha512-pxHAU+Zv39hLUTdQQHUVHf4P+0C47y/ZloorHpzs2SXMRqeAWmGghzAhfOlzFHHwjvgokdFAhC4V+6kC1lRRfw==", + "version": "4.32.0", + "resolved": "https://registry.npmjs.org/@rollup/rollup-win32-ia32-msvc/-/rollup-win32-ia32-msvc-4.32.0.tgz", + "integrity": "sha512-/TG7WfrCAjeRNDvI4+0AAMoHxea/USWhAzf9PVDFHbcqrQ7hMMKp4jZIy4VEjk72AAfN5k4TiSMRXRKf/0akSw==", "cpu": [ "ia32" ], @@ -941,9 +951,9 @@ ] }, "node_modules/@rollup/rollup-win32-x64-msvc": { - "version": "4.30.1", - "resolved": "https://registry.npmjs.org/@rollup/rollup-win32-x64-msvc/-/rollup-win32-x64-msvc-4.30.1.tgz", - "integrity": "sha512-D6qjsXGcvhTjv0kI4fU8tUuBDF/Ueee4SVX79VfNDXZa64TfCW1Slkb6Z7O1p7vflqZjcmOVdZlqf8gvJxc6og==", + "version": "4.32.0", + "resolved": "https://registry.npmjs.org/@rollup/rollup-win32-x64-msvc/-/rollup-win32-x64-msvc-4.32.0.tgz", + "integrity": "sha512-5hqO5S3PTEO2E5VjCePxv40gIgyS2KvO7E7/vvC/NbIW4SIRamkMr1hqj+5Y67fbBWv/bQLB6KelBQmXlyCjWA==", "cpu": [ "x64" ], @@ -954,6 +964,15 @@ "win32" ] }, + "node_modules/@sveltejs/acorn-typescript": { + "version": "1.0.5", + "resolved": "https://registry.npmjs.org/@sveltejs/acorn-typescript/-/acorn-typescript-1.0.5.tgz", + "integrity": "sha512-IwQk4yfwLdibDlrXVE04jTZYlLnwsTT2PIOQQGNLWfjavGifnk1JD1LcZjZaBTRcxZu2FfPfNLOE04DSu9lqtQ==", + "license": "MIT", + "peerDependencies": { + "acorn": "^8.9.0" + } + }, "node_modules/@sveltejs/adapter-static": { "version": "3.0.8", "resolved": "https://registry.npmjs.org/@sveltejs/adapter-static/-/adapter-static-3.0.8.tgz", @@ -965,25 +984,23 @@ } }, "node_modules/@sveltejs/kit": { - "version": "2.15.2", - "resolved": "https://registry.npmjs.org/@sveltejs/kit/-/kit-2.15.2.tgz", - "integrity": "sha512-p208T1kdM6zd8k4YXIUM60pLWQ8dZqehXSiqn4NulXHyHibX53uIAL2xtNL8GjxX2IVPqPRT978MwVYhCKExdQ==", + "version": "2.20.2", + "resolved": "https://registry.npmjs.org/@sveltejs/kit/-/kit-2.20.2.tgz", + "integrity": "sha512-Dv8TOAZC9vyfcAB9TMsvUEJsRbklRTeNfcYBPaeH6KnABJ99i3CvCB2eNx8fiiliIqe+9GIchBg4RodRH5p1BQ==", "dev": true, - "hasInstallScript": true, "license": "MIT", "dependencies": { "@types/cookie": "^0.6.0", "cookie": "^0.6.0", "devalue": "^5.1.0", - "esm-env": "^1.2.1", + "esm-env": "^1.2.2", "import-meta-resolve": "^4.1.0", "kleur": "^4.1.5", "magic-string": "^0.30.5", "mrmime": "^2.0.0", "sade": "^1.8.1", "set-cookie-parser": "^2.6.0", - "sirv": "^3.0.0", - "tiny-glob": "^0.2.9" + "sirv": "^3.0.0" }, "bin": { "svelte-kit": "svelte-kit.js" @@ -1039,9 +1056,9 @@ } }, "node_modules/@sveltestrap/sveltestrap": { - "version": "6.2.7", - "resolved": "https://registry.npmjs.org/@sveltestrap/sveltestrap/-/sveltestrap-6.2.7.tgz", - "integrity": "sha512-WwLLfAFUb42BGuRrf3Vbct30bQMzlEMMipN/MfxhjuLTmLQeW9muVJfPyvjtWS+mY+RjkSCoHvAp/ZobP1NLlQ==", + "version": "7.1.0", + "resolved": "https://registry.npmjs.org/@sveltestrap/sveltestrap/-/sveltestrap-7.1.0.tgz", + "integrity": "sha512-TpIx25kqLV+z+VD3yfqYayOI1IaCeWFbT0uqM6NfA4vQgDs9PjFwmjkU4YEAlV/ngs9e7xPmaRWE7lkrg4Miow==", "license": "MIT", "dependencies": { "@popperjs/core": "^2.11.8" @@ -1092,15 +1109,6 @@ "acorn": "^6.0.0 || ^7.0.0 || ^8.0.0" } }, - "node_modules/acorn-typescript": { - "version": "1.4.13", - "resolved": "https://registry.npmjs.org/acorn-typescript/-/acorn-typescript-1.4.13.tgz", - "integrity": "sha512-xsc9Xv0xlVfwp2o7sQ+GCQ1PgbkdcpWdTzrwXxO3xDMTAywVS3oXVOcOHuRjAPkS4P9b+yc/qNF15460v+jp4Q==", - "license": "MIT", - "peerDependencies": { - "acorn": ">=8.9.0" - } - }, "node_modules/ajv": { "version": "6.12.6", "resolved": "https://registry.npmjs.org/ajv/-/ajv-6.12.6.tgz", @@ -1408,22 +1416,23 @@ } }, "node_modules/eslint": { - "version": "9.18.0", - "resolved": "https://registry.npmjs.org/eslint/-/eslint-9.18.0.tgz", - "integrity": "sha512-+waTfRWQlSbpt3KWE+CjrPPYnbq9kfZIYUqapc0uBXyjTp8aYXZDsUH16m39Ryq3NjAVP4tjuF7KaukeqoCoaA==", + "version": "9.23.0", + "resolved": "https://registry.npmjs.org/eslint/-/eslint-9.23.0.tgz", + "integrity": "sha512-jV7AbNoFPAY1EkFYpLq5bslU9NLNO8xnEeQXwErNibVryjk67wHVmddTBilc5srIttJDBrB0eMHKZBFbSIABCw==", "dev": true, "license": "MIT", "dependencies": { "@eslint-community/eslint-utils": "^4.2.0", "@eslint-community/regexpp": "^4.12.1", - "@eslint/config-array": "^0.19.0", - "@eslint/core": "^0.10.0", - "@eslint/eslintrc": "^3.2.0", - "@eslint/js": "9.18.0", - "@eslint/plugin-kit": "^0.2.5", + "@eslint/config-array": "^0.19.2", + "@eslint/config-helpers": "^0.2.0", + "@eslint/core": "^0.12.0", + "@eslint/eslintrc": "^3.3.1", + "@eslint/js": "9.23.0", + "@eslint/plugin-kit": "^0.2.7", "@humanfs/node": "^0.16.6", "@humanwhocodes/module-importer": "^1.0.1", - "@humanwhocodes/retry": "^0.4.1", + "@humanwhocodes/retry": "^0.4.2", "@types/estree": "^1.0.6", "@types/json-schema": "^7.0.15", "ajv": "^6.12.4", @@ -1431,7 +1440,7 @@ "cross-spawn": "^7.0.6", "debug": "^4.3.2", "escape-string-regexp": "^4.0.0", - "eslint-scope": "^8.2.0", + "eslint-scope": "^8.3.0", "eslint-visitor-keys": "^4.2.0", "espree": "^10.3.0", "esquery": "^1.5.0", @@ -1468,9 +1477,9 @@ } }, "node_modules/eslint-compat-utils": { - "version": "0.5.1", - "resolved": "https://registry.npmjs.org/eslint-compat-utils/-/eslint-compat-utils-0.5.1.tgz", - "integrity": "sha512-3z3vFexKIEnjHE3zCMRo6fn/e44U7T1khUjg+Hp0ZQMCigh28rALD0nPFBcGZuiLC5rLZa2ubQHDRln09JfU2Q==", + "version": "0.6.4", + "resolved": "https://registry.npmjs.org/eslint-compat-utils/-/eslint-compat-utils-0.6.4.tgz", + "integrity": "sha512-/u+GQt8NMfXO8w17QendT4gvO5acfxQsAKirAt0LVxDnr2N8YLCVbregaNc/Yhp7NM128DwCaRvr8PLDfeNkQw==", "dev": true, "license": "MIT", "dependencies": { @@ -1484,9 +1493,9 @@ } }, "node_modules/eslint-config-prettier": { - "version": "9.1.0", - "resolved": "https://registry.npmjs.org/eslint-config-prettier/-/eslint-config-prettier-9.1.0.tgz", - "integrity": "sha512-NSWl5BFQWEPi1j4TjVNItzYV7dZXZ+wP6I6ZhrBGpChQhZRUaElihE9uRRkcbRnNb76UMKDF3r+WTmNcGPKsqw==", + "version": "10.1.1", + "resolved": "https://registry.npmjs.org/eslint-config-prettier/-/eslint-config-prettier-10.1.1.tgz", + "integrity": "sha512-4EQQr6wXwS+ZJSzaR5ZCrYgLxqvUjdXctaEtBqHcbkW944B1NQyO4qpdHQbXBONfwxXdkAY81HH4+LUfrg+zPw==", "dev": true, "license": "MIT", "bin": { @@ -1497,32 +1506,31 @@ } }, "node_modules/eslint-plugin-svelte": { - "version": "2.46.1", - "resolved": "https://registry.npmjs.org/eslint-plugin-svelte/-/eslint-plugin-svelte-2.46.1.tgz", - "integrity": "sha512-7xYr2o4NID/f9OEYMqxsEQsCsj4KaMy4q5sANaKkAb6/QeCjYFxRmDm2S3YC3A3pl1kyPZ/syOx/i7LcWYSbIw==", + "version": "3.3.3", + "resolved": "https://registry.npmjs.org/eslint-plugin-svelte/-/eslint-plugin-svelte-3.3.3.tgz", + "integrity": "sha512-imzGqIgWbfsb/CR14d3k3M8MiVNGet+l9mjPhvo1Rm0Nxi0rNn4/eELqyR8FWlgKBMlGkOp2kshRJm0xpxNfHQ==", "dev": true, "license": "MIT", "dependencies": { - "@eslint-community/eslint-utils": "^4.4.0", - "@jridgewell/sourcemap-codec": "^1.4.15", - "eslint-compat-utils": "^0.5.1", + "@eslint-community/eslint-utils": "^4.4.1", + "@jridgewell/sourcemap-codec": "^1.5.0", + "eslint-compat-utils": "^0.6.4", "esutils": "^2.0.3", "known-css-properties": "^0.35.0", - "postcss": "^8.4.38", + "postcss": "^8.4.49", "postcss-load-config": "^3.1.4", - "postcss-safe-parser": "^6.0.0", - "postcss-selector-parser": "^6.1.0", - "semver": "^7.6.2", - "svelte-eslint-parser": "^0.43.0" + "postcss-safe-parser": "^7.0.0", + "semver": "^7.6.3", + "svelte-eslint-parser": "^1.0.1" }, "engines": { - "node": "^14.17.0 || >=16.0.0" + "node": "^18.18.0 || ^20.9.0 || >=21.1.0" }, "funding": { "url": "https://github.com/sponsors/ota-meshi" }, "peerDependencies": { - "eslint": "^7.0.0 || ^8.0.0-0 || ^9.0.0-0", + "eslint": "^8.57.1 || ^9.0.0", "svelte": "^3.37.0 || ^4.0.0 || ^5.0.0" }, "peerDependenciesMeta": { @@ -1532,9 +1540,9 @@ } }, "node_modules/eslint-scope": { - "version": "8.2.0", - "resolved": "https://registry.npmjs.org/eslint-scope/-/eslint-scope-8.2.0.tgz", - "integrity": "sha512-PHlWUfG6lvPc3yvP5A4PNyBL1W8fkDUccmI21JUu/+GKZBoH/W5u6usENXUrWFRsyoW5ACUjFGgAFQp5gUlb/A==", + "version": "8.3.0", + "resolved": "https://registry.npmjs.org/eslint-scope/-/eslint-scope-8.3.0.tgz", + "integrity": "sha512-pUNxi75F8MJ/GdeKtVLSbYg4ZI34J6C0C7sbL4YOp2exGwen7ZsuBqKzUhXd0qMQ362yET3z+uPwKeg/0C2XCQ==", "dev": true, "license": "BSD-2-Clause", "dependencies": { @@ -1599,9 +1607,9 @@ } }, "node_modules/esrap": { - "version": "1.4.3", - "resolved": "https://registry.npmjs.org/esrap/-/esrap-1.4.3.tgz", - "integrity": "sha512-Xddc1RsoFJ4z9nR7W7BFaEPIp4UXoeQ0+077UdWLxbafMQFyU79sQJMk7kxNgRwQ9/aVgaKacCHC2pUACGwmYw==", + "version": "1.4.5", + "resolved": "https://registry.npmjs.org/esrap/-/esrap-1.4.5.tgz", + "integrity": "sha512-CjNMjkBWWZeHn+VX+gS8YvFwJ5+NDhg8aWZBSFJPR8qQduDNjbJodA2WcwCm7uQa5Rjqj+nZvVmceg1RbHFB9g==", "license": "MIT", "dependencies": { "@jridgewell/sourcemap-codec": "^1.4.15" @@ -1753,20 +1761,6 @@ "url": "https://github.com/sponsors/sindresorhus" } }, - "node_modules/globalyzer": { - "version": "0.1.0", - "resolved": "https://registry.npmjs.org/globalyzer/-/globalyzer-0.1.0.tgz", - "integrity": "sha512-40oNTM9UfG6aBmuKxk/giHn5nQ8RVz/SS4Ir6zgzOv9/qC3kKZ9v4etGTcJbEl/NyVQH7FGU7d+X1egr57Md2Q==", - "dev": true, - "license": "MIT" - }, - "node_modules/globrex": { - "version": "0.1.2", - "resolved": "https://registry.npmjs.org/globrex/-/globrex-0.1.2.tgz", - "integrity": "sha512-uHJgbwAMwNFf5mLst7IWLNg14x1CkeqglJb/K3doi4dw6q2IvAAmM/Y81kevy83wP+Sst+nutFTYOGg3d1lsxg==", - "dev": true, - "license": "MIT" - }, "node_modules/has-flag": { "version": "4.0.0", "resolved": "https://registry.npmjs.org/has-flag/-/has-flag-4.0.0.tgz", @@ -2144,9 +2138,9 @@ "license": "ISC" }, "node_modules/postcss": { - "version": "8.4.49", - "resolved": "https://registry.npmjs.org/postcss/-/postcss-8.4.49.tgz", - "integrity": "sha512-OCVPnIObs4N29kxTjzLfUryOkvZEq+pf8jTF0lg8E7uETuWHA+v7j3c/xJmiqpX450191LlmZfUKkXxkTry7nA==", + "version": "8.5.1", + "resolved": "https://registry.npmjs.org/postcss/-/postcss-8.5.1.tgz", + "integrity": "sha512-6oz2beyjc5VMn/KV1pPw8fliQkhBXrVn1Z3TVyqZxU8kZpzEKhBdmCFqI6ZbmGtamQvQGuU1sgPTk8ZrXDD7jQ==", "dev": true, "funding": [ { @@ -2164,7 +2158,7 @@ ], "license": "MIT", "dependencies": { - "nanoid": "^3.3.7", + "nanoid": "^3.3.8", "picocolors": "^1.1.1", "source-map-js": "^1.2.1" }, @@ -2203,20 +2197,30 @@ } }, "node_modules/postcss-safe-parser": { - "version": "6.0.0", - "resolved": "https://registry.npmjs.org/postcss-safe-parser/-/postcss-safe-parser-6.0.0.tgz", - "integrity": "sha512-FARHN8pwH+WiS2OPCxJI8FuRJpTVnn6ZNFiqAM2aeW2LwTHWWmWgIyKC6cUo0L8aeKiF/14MNvnpls6R2PBeMQ==", + "version": "7.0.1", + "resolved": "https://registry.npmjs.org/postcss-safe-parser/-/postcss-safe-parser-7.0.1.tgz", + "integrity": "sha512-0AioNCJZ2DPYz5ABT6bddIqlhgwhpHZ/l65YAYo0BCIn0xiDpsnTHz0gnoTGk0OXZW0JRs+cDwL8u/teRdz+8A==", "dev": true, + "funding": [ + { + "type": "opencollective", + "url": "https://opencollective.com/postcss/" + }, + { + "type": "tidelift", + "url": "https://tidelift.com/funding/github/npm/postcss-safe-parser" + }, + { + "type": "github", + "url": "https://github.com/sponsors/ai" + } + ], "license": "MIT", "engines": { - "node": ">=12.0" - }, - "funding": { - "type": "opencollective", - "url": "https://opencollective.com/postcss/" + "node": ">=18.0" }, "peerDependencies": { - "postcss": "^8.3.3" + "postcss": "^8.4.31" } }, "node_modules/postcss-scss": { @@ -2247,9 +2251,9 @@ } }, "node_modules/postcss-selector-parser": { - "version": "6.1.2", - "resolved": "https://registry.npmjs.org/postcss-selector-parser/-/postcss-selector-parser-6.1.2.tgz", - "integrity": "sha512-Q8qQfPiZ+THO/3ZrOrO0cJJKfpYCagtMUkXbnEfmgUjwXg6z/WBeOyS9APBBPCTSiDV+s4SwQGu8yFsiMRIudg==", + "version": "7.1.0", + "resolved": "https://registry.npmjs.org/postcss-selector-parser/-/postcss-selector-parser-7.1.0.tgz", + "integrity": "sha512-8sLjZwK0R+JlxlYcTuVnyT2v+htpdrjDOKuMcOVdYjt52Lh8hWRYpxBPoKx/Zg+bcjc3wx6fmQevMmUztS/ccA==", "dev": true, "license": "MIT", "dependencies": { @@ -2271,9 +2275,9 @@ } }, "node_modules/prettier": { - "version": "3.4.2", - "resolved": "https://registry.npmjs.org/prettier/-/prettier-3.4.2.tgz", - "integrity": "sha512-e9MewbtFo+Fevyuxn/4rrcDAaq0IYxPGLvObpQjiZBMAzB9IGmzlnG9RZy3FFas+eBMu2vA0CszMeduow5dIuQ==", + "version": "3.5.3", + "resolved": "https://registry.npmjs.org/prettier/-/prettier-3.5.3.tgz", + "integrity": "sha512-QQtaxnoDJeAkDvDKWCLiwIXkTgRhwYDEQCghU9Z6q03iyek/rxRh/2lC3HB7P8sWT2xC/y5JDctPLBIGzHKbhw==", "dev": true, "license": "MIT", "bin": { @@ -2318,9 +2322,9 @@ } }, "node_modules/rollup": { - "version": "4.30.1", - "resolved": "https://registry.npmjs.org/rollup/-/rollup-4.30.1.tgz", - "integrity": "sha512-mlJ4glW020fPuLi7DkM/lN97mYEZGWeqBnrljzN0gs7GLctqX3lNWxKQ7Gl712UAX+6fog/L3jh4gb7R6aVi3w==", + "version": "4.32.0", + "resolved": "https://registry.npmjs.org/rollup/-/rollup-4.32.0.tgz", + "integrity": "sha512-JmrhfQR31Q4AuNBjjAX4s+a/Pu/Q8Q9iwjWBsjRH1q52SPFE2NqRMK6fUZKKnvKO6id+h7JIRf0oYsph53eATg==", "dev": true, "license": "MIT", "dependencies": { @@ -2334,25 +2338,25 @@ "npm": ">=8.0.0" }, "optionalDependencies": { - "@rollup/rollup-android-arm-eabi": "4.30.1", - "@rollup/rollup-android-arm64": "4.30.1", - "@rollup/rollup-darwin-arm64": "4.30.1", - "@rollup/rollup-darwin-x64": "4.30.1", - "@rollup/rollup-freebsd-arm64": "4.30.1", - "@rollup/rollup-freebsd-x64": "4.30.1", - "@rollup/rollup-linux-arm-gnueabihf": "4.30.1", - "@rollup/rollup-linux-arm-musleabihf": "4.30.1", - "@rollup/rollup-linux-arm64-gnu": "4.30.1", - "@rollup/rollup-linux-arm64-musl": "4.30.1", - "@rollup/rollup-linux-loongarch64-gnu": "4.30.1", - "@rollup/rollup-linux-powerpc64le-gnu": "4.30.1", - "@rollup/rollup-linux-riscv64-gnu": "4.30.1", - "@rollup/rollup-linux-s390x-gnu": "4.30.1", - "@rollup/rollup-linux-x64-gnu": "4.30.1", - "@rollup/rollup-linux-x64-musl": "4.30.1", - "@rollup/rollup-win32-arm64-msvc": "4.30.1", - "@rollup/rollup-win32-ia32-msvc": "4.30.1", - "@rollup/rollup-win32-x64-msvc": "4.30.1", + "@rollup/rollup-android-arm-eabi": "4.32.0", + "@rollup/rollup-android-arm64": "4.32.0", + "@rollup/rollup-darwin-arm64": "4.32.0", + "@rollup/rollup-darwin-x64": "4.32.0", + "@rollup/rollup-freebsd-arm64": "4.32.0", + "@rollup/rollup-freebsd-x64": "4.32.0", + "@rollup/rollup-linux-arm-gnueabihf": "4.32.0", + "@rollup/rollup-linux-arm-musleabihf": "4.32.0", + "@rollup/rollup-linux-arm64-gnu": "4.32.0", + "@rollup/rollup-linux-arm64-musl": "4.32.0", + "@rollup/rollup-linux-loongarch64-gnu": "4.32.0", + "@rollup/rollup-linux-powerpc64le-gnu": "4.32.0", + "@rollup/rollup-linux-riscv64-gnu": "4.32.0", + "@rollup/rollup-linux-s390x-gnu": "4.32.0", + "@rollup/rollup-linux-x64-gnu": "4.32.0", + "@rollup/rollup-linux-x64-musl": "4.32.0", + "@rollup/rollup-win32-arm64-msvc": "4.32.0", + "@rollup/rollup-win32-ia32-msvc": "4.32.0", + "@rollup/rollup-win32-x64-msvc": "4.32.0", "fsevents": "~2.3.2" } }, @@ -2464,16 +2468,16 @@ } }, "node_modules/svelte": { - "version": "5.19.0", - "resolved": "https://registry.npmjs.org/svelte/-/svelte-5.19.0.tgz", - "integrity": "sha512-qvd2GvvYnJxS/MteQKFSMyq8cQrAAut28QZ39ySv9k3ggmhw4Au4Rfcsqva74i0xMys//OhbhVCNfXPrDzL/Bg==", + "version": "5.25.3", + "resolved": "https://registry.npmjs.org/svelte/-/svelte-5.25.3.tgz", + "integrity": "sha512-J9rcZ/xVJonAoESqVGHHZhrNdVbrCfkdB41BP6eiwHMoFShD9it3yZXApVYMHdGfCshBsZCKsajwJeBbS/M1zg==", "license": "MIT", "dependencies": { "@ampproject/remapping": "^2.3.0", "@jridgewell/sourcemap-codec": "^1.5.0", + "@sveltejs/acorn-typescript": "^1.0.5", "@types/estree": "^1.0.5", "acorn": "^8.12.1", - "acorn-typescript": "^1.4.13", "aria-query": "^5.3.1", "axobject-query": "^4.1.0", "clsx": "^2.1.1", @@ -2489,20 +2493,21 @@ } }, "node_modules/svelte-eslint-parser": { - "version": "0.43.0", - "resolved": "https://registry.npmjs.org/svelte-eslint-parser/-/svelte-eslint-parser-0.43.0.tgz", - "integrity": "sha512-GpU52uPKKcVnh8tKN5P4UZpJ/fUDndmq7wfsvoVXsyP+aY0anol7Yqo01fyrlaWGMFfm4av5DyrjlaXdLRJvGA==", + "version": "1.1.1", + "resolved": "https://registry.npmjs.org/svelte-eslint-parser/-/svelte-eslint-parser-1.1.1.tgz", + "integrity": "sha512-QLVGPIMDettl30qRHXU2VrPvVJKG8GsGstye7n8rFbEiu3gEARksuQg9Xu4GzubNxhGNM8stfBZkhyMbBQmjFA==", "dev": true, "license": "MIT", "dependencies": { - "eslint-scope": "^7.2.2", - "eslint-visitor-keys": "^3.4.3", - "espree": "^9.6.1", - "postcss": "^8.4.39", - "postcss-scss": "^4.0.9" + "eslint-scope": "^8.2.0", + "eslint-visitor-keys": "^4.0.0", + "espree": "^10.0.0", + "postcss": "^8.4.49", + "postcss-scss": "^4.0.9", + "postcss-selector-parser": "^7.0.0" }, "engines": { - "node": "^12.22.0 || ^14.17.0 || >=16.0.0" + "node": "^18.18.0 || ^20.9.0 || >=21.1.0" }, "funding": { "url": "https://github.com/sponsors/ota-meshi" @@ -2516,54 +2521,6 @@ } } }, - "node_modules/svelte-eslint-parser/node_modules/eslint-scope": { - "version": "7.2.2", - "resolved": "https://registry.npmjs.org/eslint-scope/-/eslint-scope-7.2.2.tgz", - "integrity": "sha512-dOt21O7lTMhDM+X9mB4GX+DZrZtCUJPL/wlcTqxyrx5IvO0IYtILdtrQGQp+8n5S0gwSVmOf9NQrjMOgfQZlIg==", - "dev": true, - "license": "BSD-2-Clause", - "dependencies": { - "esrecurse": "^4.3.0", - "estraverse": "^5.2.0" - }, - "engines": { - "node": "^12.22.0 || ^14.17.0 || >=16.0.0" - }, - "funding": { - "url": "https://opencollective.com/eslint" - } - }, - "node_modules/svelte-eslint-parser/node_modules/eslint-visitor-keys": { - "version": "3.4.3", - "resolved": "https://registry.npmjs.org/eslint-visitor-keys/-/eslint-visitor-keys-3.4.3.tgz", - "integrity": "sha512-wpc+LXeiyiisxPlEkUzU6svyS1frIO3Mgxj1fdy7Pm8Ygzguax2N3Fa/D/ag1WqbOprdI+uY6wMUl8/a2G+iag==", - "dev": true, - "license": "Apache-2.0", - "engines": { - "node": "^12.22.0 || ^14.17.0 || >=16.0.0" - }, - "funding": { - "url": "https://opencollective.com/eslint" - } - }, - "node_modules/svelte-eslint-parser/node_modules/espree": { - "version": "9.6.1", - "resolved": "https://registry.npmjs.org/espree/-/espree-9.6.1.tgz", - "integrity": "sha512-oruZaFkjorTpF32kDSI5/75ViwGeZginGGy2NoOSg3Q9bnwlnmDm4HLnkl0RE3n+njDXR037aY1+x58Z/zFdwQ==", - "dev": true, - "license": "BSD-2-Clause", - "dependencies": { - "acorn": "^8.9.0", - "acorn-jsx": "^5.3.2", - "eslint-visitor-keys": "^3.4.1" - }, - "engines": { - "node": "^12.22.0 || ^14.17.0 || >=16.0.0" - }, - "funding": { - "url": "https://opencollective.com/eslint" - } - }, "node_modules/svelte-hmr": { "version": "0.16.0", "resolved": "https://registry.npmjs.org/svelte-hmr/-/svelte-hmr-0.16.0.tgz", @@ -2577,17 +2534,6 @@ "svelte": "^3.19.0 || ^4.0.0" } }, - "node_modules/tiny-glob": { - "version": "0.2.9", - "resolved": "https://registry.npmjs.org/tiny-glob/-/tiny-glob-0.2.9.tgz", - "integrity": "sha512-g/55ssRPUjShh+xkfx9UPDXqhckHEsHr4Vd9zX55oSdGZc/MD0m3sferOkwWtp98bv+kcVfEHtRJgBVJzelrzg==", - "dev": true, - "license": "MIT", - "dependencies": { - "globalyzer": "0.1.0", - "globrex": "^0.1.2" - } - }, "node_modules/totalist": { "version": "3.0.1", "resolved": "https://registry.npmjs.org/totalist/-/totalist-3.0.1.tgz", @@ -2629,9 +2575,9 @@ "license": "MIT" }, "node_modules/vite": { - "version": "5.4.11", - "resolved": "https://registry.npmjs.org/vite/-/vite-5.4.11.tgz", - "integrity": "sha512-c7jFQRklXua0mTzneGW9QVyxFjUgwcihC4bXEtujIo2ouWCe1Ajt/amn2PCxYnhYfd5k09JX3SB7OYWFKYqj8Q==", + "version": "5.4.15", + "resolved": "https://registry.npmjs.org/vite/-/vite-5.4.15.tgz", + "integrity": "sha512-6ANcZRivqL/4WtwPGTKNaosuNJr5tWiftOC7liM7G9+rMb8+oeJeyzymDu4rTN93seySBmbjSfsS3Vzr19KNtA==", "dev": true, "license": "MIT", "dependencies": { diff --git a/qa/ui/package.json b/qa/ui/package.json index 44560547..fe82f6ea 100644 --- a/qa/ui/package.json +++ b/qa/ui/package.json @@ -14,8 +14,8 @@ "@sveltejs/kit": "^2.0.0", "@sveltejs/vite-plugin-svelte": "^3.0.0", "eslint": "^9.0.0", - "eslint-config-prettier": "^9.0.0", - "eslint-plugin-svelte": "^2.35.1", + "eslint-config-prettier": "^10.0.0", + "eslint-plugin-svelte": "^3.0.0", "prettier": "^3.0.0", "prettier-plugin-svelte": "^3.1.2", "svelte": "^5.0.0", @@ -25,6 +25,6 @@ "dependencies": { "bootstrap": "^5.2.2", "bootstrap-icons": "^1.9.1", - "@sveltestrap/sveltestrap": "^6.2.1" + "@sveltestrap/sveltestrap": "^7.0.0" } } diff --git a/remote/challenge-sync-airbus/api.go b/remote/challenge-sync-airbus/api.go index 10407945..9bd9ac3e 100644 --- a/remote/challenge-sync-airbus/api.go +++ b/remote/challenge-sync-airbus/api.go @@ -9,12 +9,14 @@ import ( "log" "net/http" "strconv" + + "srs.epita.fr/fic-server/libfic" ) type AirbusAPI struct { BaseURL string Token string - SessionID int64 + SessionUUID string InsecureSkipVerify bool } @@ -51,7 +53,7 @@ func (a *AirbusAPI) request(method, endpoint string, data io.Reader, out interfa if out != nil { jdec := json.NewDecoder(resp.Body) - if err := jdec.Decode(out); err != nil { + if err := jdec.Decode(&fic.CyberrangeAPIResponse{Data: out}); err != nil { return fmt.Errorf("an error occurs when trying to decode response: %w", err) } } @@ -87,7 +89,7 @@ type AirbusUser struct { } func (a *AirbusAPI) GetUsers() (users AirbusUserData, err error) { - err = a.request("GET", fmt.Sprintf("/sessions/%d/users", a.SessionID), nil, &users) + err = a.request("GET", fmt.Sprintf("/sessions/%s/users", a.SessionUUID), nil, &users) return } @@ -137,7 +139,7 @@ type AirbusChallenge struct { } func (a *AirbusAPI) GetChallenges() (challenges AirbusChallengeData, err error) { - err = a.request("GET", fmt.Sprintf("/v1/sessions/%d/challenges", a.SessionID), nil, &challenges) + err = a.request("GET", fmt.Sprintf("/v1/sessions/%s/challenges", a.SessionUUID), nil, &challenges) return } @@ -156,25 +158,23 @@ func (a *AirbusAPI) GetChallengeFromName(name string) (*AirbusChallenge, error) return nil, fmt.Errorf("unable to find challenge %q", name) } -func (a *AirbusAPI) ValidateChallengeFromUser(team *AirbusTeam, challengeId AirbusChallengeId) (err error) { - log.Printf("ValidateChallenge: %d, %s, %d", a.SessionID, challengeId.String(), team.Members[0].ID) +func (a *AirbusAPI) ValidateChallengeFromUser(team *fic.CyberrangeTeam, challengeId AirbusChallengeId) (err error) { + log.Printf("ValidateChallenge: %s, %s, %s", a.SessionUUID, challengeId.String(), team.Members[0].UUID) if dryRun { return } - err = a.request("GET", fmt.Sprintf("/v1/sessions/%d/%s/%d/validate", a.SessionID, challengeId.String(), team.Members[0].ID), nil, nil) + err = a.request("GET", fmt.Sprintf("/v1/sessions/%s/%s/%s/validate", a.SessionUUID, challengeId.String(), team.Members[0].UUID), nil, nil) return } type AirbusUserAwards struct { - UserId int64 `json:"gaming_user_id"` Message string `json:"name"` Value int64 `json:"value"` } -func (a *AirbusAPI) AwardUser(team *AirbusTeam, value int64, message string) (err error) { +func (a *AirbusAPI) AwardUser(team *fic.CyberrangeTeam, value int64, message string) (err error) { awards := AirbusUserAwards{ - UserId: team.Members[0].ID, Message: message, Value: value, } @@ -190,7 +190,7 @@ func (a *AirbusAPI) AwardUser(team *AirbusTeam, value int64, message string) (er return } - err = a.request("POST", fmt.Sprintf("/v1/sessions/%d/awards", a.SessionID), bytes.NewReader(marshalled), nil) + err = a.request("POST", fmt.Sprintf("/v1/sessions/%s/%s/awards", a.SessionUUID, team.Members[0].UUID), bytes.NewReader(marshalled), nil) if err != nil { return err } diff --git a/remote/challenge-sync-airbus/main.go b/remote/challenge-sync-airbus/main.go index 11a58959..895f563f 100644 --- a/remote/challenge-sync-airbus/main.go +++ b/remote/challenge-sync-airbus/main.go @@ -16,6 +16,8 @@ import ( "time" "gopkg.in/fsnotify.v1" + + "srs.epita.fr/fic-server/libfic" ) var ( @@ -77,12 +79,8 @@ func main() { fd.Close() } - if v, exists := os.LookupEnv("AIRBUS_SESSIONID"); exists { - var err error - api.SessionID, err = strconv.ParseInt(v, 10, 64) - if err != nil { - log.Fatal("AIRBUS_SESSIONID is invalid: ", err.Error()) - } + if v, exists := os.LookupEnv("AIRBUS_SESSION_UUID"); exists { + api.SessionUUID = v } else if v, exists := os.LookupEnv("AIRBUS_SESSION_NAME_FILE"); exists { fd, err := os.Open(v) if err != nil { @@ -101,15 +99,15 @@ func main() { for _, session := range sessions { if session.Name == v { - api.SessionID = session.ID + api.SessionUUID = session.UUID break } } - if api.SessionID == 0 { + if api.SessionUUID == "" { log.Fatal("Session ID not found") } else { - log.Println("Session ID discovered: ", api.SessionID) + log.Println("Session ID discovered: ", api.SessionUUID) } } else if v, exists := os.LookupEnv("AIRBUS_SESSION_NAME"); exists { sessions, err := api.GetSessions() @@ -117,17 +115,19 @@ func main() { log.Fatal("Unable to retrieve session: ", err) } + found := false for _, session := range sessions { if session.Name == v { - api.SessionID = session.ID + api.SessionUUID = session.UUID + found = true break } } - if api.SessionID == 0 { + if !found { log.Fatal("Session ID not found") } else { - log.Println("Session ID discovered: ", api.SessionID) + log.Println("Session ID discovered: ", api.SessionUUID) } } else { sessions, err := api.GetSessions() @@ -138,7 +138,7 @@ func main() { log.Println("Please define your AIRBUS_SESSIONID or AIRBUS_SESSION_NAME.") log.Println("Existing sessions are:") for _, session := range sessions { - log.Printf(" - %d: %q", session.ID, session.Name) + log.Printf(" - %s: %q", session.UUID, session.Name) } os.Exit(1) } @@ -156,11 +156,11 @@ func main() { } fmt.Println("## Airbus' registered teams:") - fmt.Println("-------------------------------------------") - fmt.Println(" ID | Name | Nb. | Score | Rank") - fmt.Println("-------------------------------------------") + fmt.Println("----------------------------------------------------------------------------------") + fmt.Println(" UUID | Name | Nb. | Score | Rank") + fmt.Println("----------------------------------------------------------------------------------") for _, team := range teams { - fmt.Printf("% 2d | % 15s | % 3d | % 5d | % 3d\n", team.ID, team.Name, len(team.Members), team.Score, team.Rank) + fmt.Printf(" %s | % 20s | % 3d | % 5d | % 3d\n", team.UUID, team.Name, len(team.Members), team.Score, team.Rank) } case "rank": teams, err := api.GetTeams() @@ -169,7 +169,7 @@ func main() { os.Exit(1) } - ranking := []*AirbusTeam{} + ranking := []*fic.CyberrangeTeam{} for _, team := range teams { tmp := team ranking = append(ranking, &tmp) @@ -178,11 +178,11 @@ func main() { sort.Sort(sort.Reverse(ByScore(ranking))) fmt.Println("## Airbus' ranking:") - fmt.Println("-------------------------------------") - fmt.Println(" Rank | Name | ID | Score") - fmt.Println("-------------------------------------") + fmt.Println("----------------------------------------------------------------------------") + fmt.Println(" Rank | Name | UUID | Score") + fmt.Println("----------------------------------------------------------------------------") for _, team := range ranking { - fmt.Printf("% 5d | % 15s |% 3d | % 5d\n", team.Rank, team.Name, team.ID, team.Score) + fmt.Printf("% 5d | % 20s | %s | % 5d\n", team.Rank, team.Name, team.UUID, team.Score) } case "get": teams, err := api.GetTeams() @@ -191,22 +191,18 @@ func main() { os.Exit(1) } - teamid, err := strconv.ParseInt(args[1], 10, 64) - if err != nil { - log.Println(err) - os.Exit(1) - } + teamid := args[1] for _, team := range teams { - if team.ID == teamid { - fmt.Printf("## Airbus' registered team %d:\n\nID: %d\nName: %s\nScore: %d\nRank: %d\nMembers:\n", teamid, team.ID, team.Name, team.Score, team.Rank) + if team.UUID == teamid { + fmt.Printf("## Airbus' registered team %s:\n\nUUID: %s\nName: %s\nScore: %d\nRank: %d\nMembers:\n", teamid, team.UUID, team.Name, team.Score, team.Rank) for _, member := range team.Members { - fmt.Printf(" - ID: %d\n Name: %s\n Nickname: %s\n E-mail: %s\n", member.ID, member.Name, member.Nickname, member.EMail) + fmt.Printf(" - UUID: %s\n Name: %s\n Nickname: %s\n E-mail: %s\n", member.UUID, member.Name, member.Nickname, member.EMail) } os.Exit(0) } } - fmt.Printf("Team %d not found. Use 'list' to view all existing teams\n", teamid) + fmt.Printf("Team %s not found. Use 'list' to view all existing teams\n", teamid) case "award": if len(args) < 3 { fmt.Println("award ") @@ -219,11 +215,7 @@ func main() { os.Exit(1) } - teamid, err := strconv.ParseInt(args[1], 10, 64) - if err != nil { - log.Println("Invalid team id", err) - os.Exit(1) - } + teamid := args[1] value, err := strconv.ParseInt(args[2], 10, 64) if err != nil { @@ -232,7 +224,7 @@ func main() { } for _, team := range teams { - if team.ID == teamid { + if team.UUID == teamid { err = api.AwardUser(&team, value, strings.Join(args[3:], " ")) if err != nil { log.Println("Unable to award team:", err) @@ -243,7 +235,7 @@ func main() { os.Exit(0) } } - fmt.Printf("Team %d not found. Use 'list' to view all existing teams\n", teamid) + fmt.Printf("Team %s not found. Use 'list' to view all existing teams\n", teamid) } os.Exit(0) diff --git a/remote/challenge-sync-airbus/session.go b/remote/challenge-sync-airbus/session.go index f10b8474..619a0853 100644 --- a/remote/challenge-sync-airbus/session.go +++ b/remote/challenge-sync-airbus/session.go @@ -1,12 +1,18 @@ package main -import () +import ( + "time" +) type Session struct { - Name string `json:"name"` - Status string `json:"status"` - ID int64 `json:"id"` - Mode string `json:"mode"` + Name string `json:"name"` + QuestionValidation string `json:"question_validation"` + Status string `json:"status"` + UUID string `json:"uuid"` + Mode string `json:"mode"` + Difficulty int `json:"difficulty"` + StartedAt time.Time `json:"start_at"` + FinishAt time.Time `json:"finish_at"` } func (a *AirbusAPI) GetSessions() (ret []Session, err error) { diff --git a/remote/challenge-sync-airbus/team.go b/remote/challenge-sync-airbus/team.go index dae56b99..6c0d357c 100644 --- a/remote/challenge-sync-airbus/team.go +++ b/remote/challenge-sync-airbus/team.go @@ -2,44 +2,27 @@ package main import ( "fmt" + + "srs.epita.fr/fic-server/libfic" ) -type AirbusTeam struct { - ID int64 `json:"id"` - Members []TeamMember `json:"members"` - Name string `json:"name"` - Score int64 `json:"score"` - Rank int `json:"rank"` -} - -type TeamMember struct { - ID int64 `json:"id"` - Name string `json:"name"` - Nickname string `json:"nickname"` - EMail string `json:"email"` -} - -type airbusDataTeam struct { - Data []AirbusTeam `json:"data"` -} - -func (a *AirbusAPI) GetTeams() ([]AirbusTeam, error) { - var data airbusDataTeam - err := a.request("GET", fmt.Sprintf("/v1/sessions/%d/teams", a.SessionID), nil, &data) +func (a *AirbusAPI) GetTeams() ([]fic.CyberrangeTeam, error) { + var data []fic.CyberrangeTeam + err := a.request("GET", fmt.Sprintf("/v1/sessions/%s/teams", a.SessionUUID), nil, &data) if err != nil { return nil, err } else { - return data.Data, nil + return data, nil } } -type ByRank []*AirbusTeam +type ByRank []*fic.CyberrangeTeam func (a ByRank) Len() int { return len(a) } func (a ByRank) Swap(i, j int) { a[i], a[j] = a[j], a[i] } func (a ByRank) Less(i, j int) bool { return a[i].Rank < a[j].Rank } -type ByScore []*AirbusTeam +type ByScore []*fic.CyberrangeTeam func (a ByScore) Len() int { return len(a) } func (a ByScore) Swap(i, j int) { a[i], a[j] = a[j], a[i] } diff --git a/remote/challenge-sync-airbus/teams.json b/remote/challenge-sync-airbus/teams.json deleted file mode 100644 index 45aea752..00000000 --- a/remote/challenge-sync-airbus/teams.json +++ /dev/null @@ -1,102 +0,0 @@ -[ - { - "name": "#D\u00e9fendonsEnsemble", - "score": 0 - }, - { - "name": "Les Pires Hat", - "score": 0 - }, - { - "name": "Esnarcotrafiquants", - "score": 0 - }, - { - "name": "Quarkslab", - "score": 0 - }, - { - "name": "HackademINT", - "score": 0 - }, - { - "name": "Phreaks 2600", - "score": 0 - }, - { - "name": "Rhackgondins", - "score": 0 - }, - { - "name": "Team France", - "score": 0 - }, - { - "name": "Hack UTT", - "score": 0 - }, - { - "name": "HDRF", - "score": 0 - }, - { - "name": "#199", - "score": 0 - }, - { - "name": "Hackday", - "score": 0 - }, - { - "name": "GCC", - "score": 0 - }, - { - "name": "Apeltek", - "score": 0 - }, - { - "name": "Hackvengers", - "score": 0 - }, - { - "name": "Guardia Cyber Squad", - "score": 0 - }, - { - "name": "F0r3nS0C", - "score": 0 - }, - { - "name": "Oteriack", - "score": 0 - }, - { - "name": "Cervelles de Canuts", - "score": 0 - }, - { - "name": "Next'H4ck", - "score": 0 - }, - { - "name": "Overflowl", - "score": 0 - }, - { - "name": "Capgemini Aces of Spades", - "score": 0 - }, - { - "name": "DLS", - "score": 0 - }, - { - "name": "ESGI", - "score": 0 - }, - { - "name": "0xECE", - "score": 0 - } -] diff --git a/remote/challenge-sync-airbus/timestamp.go b/remote/challenge-sync-airbus/timestamp.go index 858e7e68..41678319 100644 --- a/remote/challenge-sync-airbus/timestamp.go +++ b/remote/challenge-sync-airbus/timestamp.go @@ -5,6 +5,8 @@ import ( "log" "os" "time" + + "srs.epita.fr/fic-server/libfic" ) type TSValue struct { @@ -32,7 +34,7 @@ func loadTS(tspath string) (timestamp map[string]*TSValue, err error) { } } -func loadTSFromAPI(teams map[string]*AirbusTeam) (timestamp map[string]*TSValue, err error) { +func loadTSFromAPI(teams map[string]*fic.CyberrangeTeam) (timestamp map[string]*TSValue, err error) { now := time.Now() timestamp = map[string]*TSValue{} diff --git a/remote/challenge-sync-airbus/treat.go b/remote/challenge-sync-airbus/treat.go index 82f83c6c..fdb0ea8a 100644 --- a/remote/challenge-sync-airbus/treat.go +++ b/remote/challenge-sync-airbus/treat.go @@ -23,7 +23,7 @@ type Walker struct { Exercices AirbusExercicesBindings Teams map[string]fic.ExportedTeam RevTeams map[string]string - TeamBindings map[string]*AirbusTeam + TeamBindings map[string]*fic.CyberrangeTeam API AirbusAPI Coeff float64 } @@ -35,11 +35,11 @@ func (w *Walker) fetchTeams() error { } w.RevTeams = map[string]string{} - w.TeamBindings = map[string]*AirbusTeam{} + w.TeamBindings = map[string]*fic.CyberrangeTeam{} for tid, team := range w.Teams { for i, t := range teams { - if team.Name == t.Name || team.ExternalId == t.Name { + if team.Name == t.Name || team.ExternalId == t.Name || team.ExternalId == t.UUID { w.TeamBindings[tid] = &teams[i] break } @@ -143,7 +143,7 @@ func (w *Walker) WalkScore(path string, d os.DirEntry, err error) error { return nil } -func (w *Walker) TreatScoreGrid(path string, airbusTeam *AirbusTeam) error { +func (w *Walker) TreatScoreGrid(path string, airbusTeam *fic.CyberrangeTeam) error { // Read score grid fdscores, err := os.Open(path) if err != nil {