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 {