Compare commits
65 commits
0d348e2398
...
821efbe41c
Author | SHA1 | Date | |
---|---|---|---|
821efbe41c | |||
cb0e0e2c24 | |||
6100f33e7c | |||
47f2004a4c | |||
faf74ec808 | |||
e42545416f | |||
3f5d6bb04b | |||
99c436ba9a | |||
a7d521fbdd | |||
0c53372618 | |||
84be750ce6 | |||
3881385c9e | |||
e44cac32ac | |||
485e6b0173 | |||
f1ada8ce99 | |||
7e301b8ecb | |||
4dcf1218d8 | |||
3f5b7b9ed7 | |||
bc0570c2c7 | |||
cd50a4b9d3 | |||
4734a8f047 | |||
dadb84e8f9 | |||
801042e5cf | |||
fca27b07fe | |||
3fc765ccfa | |||
590a55c395 | |||
b62369f89f | |||
cb4ceecbf5 | |||
98d9f2daf3 | |||
db1e2603fc | |||
0730a22daa | |||
3467ca6db5 | |||
910adb123a | |||
1551c11a00 | |||
ed3e6b66de | |||
c21fd098a0 | |||
7df675346c | |||
526d693ffd | |||
df8a759134 | |||
03e48b749c | |||
97f7e3fa59 | |||
e421c91ac2 | |||
baccc54d02 | |||
e8e87c9958 | |||
08a31898df | |||
b409fa6806 | |||
63b4cdc622 | |||
650f933993 | |||
603b226955 | |||
55e829fa64 | |||
45a0504c44 | |||
ad7489e558 | |||
57c3cd8fd6 | |||
24686a6a24 | |||
407b67f4c2 | |||
c28d974105 | |||
ffb69663b6 | |||
4ec4f47951 | |||
96707e3a29 | |||
a4001759f6 | |||
f15cd29f78 | |||
7e41ddd664 | |||
89b7710544 | |||
79ec20d11c | |||
09206df20a |
58 changed files with 1612 additions and 1000 deletions
|
@ -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 \
|
||||
|
|
|
@ -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
|
||||
|
||||
|
|
|
@ -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
|
||||
|
||||
|
|
|
@ -1,4 +1,4 @@
|
|||
FROM alpine:3.20
|
||||
FROM alpine:3.21
|
||||
|
||||
EXPOSE 67/udp
|
||||
EXPOSE 69/udp
|
||||
|
|
|
@ -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
|
||||
|
||||
|
|
|
@ -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
|
||||
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -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
|
||||
|
||||
|
|
|
@ -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
|
||||
|
||||
|
|
|
@ -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
|
||||
|
||||
|
|
|
@ -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
|
||||
|
||||
|
|
|
@ -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)
|
||||
|
||||
|
|
|
@ -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 {
|
||||
|
|
|
@ -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:
|
||||
|
|
|
@ -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)
|
||||
|
|
|
@ -4,7 +4,7 @@ const indextpl = `<!DOCTYPE html>
|
|||
<html ng-app="FICApp">
|
||||
<head>
|
||||
<meta charset="utf-8">
|
||||
<title>Challenge Forensic - Administration</title>
|
||||
<title>{{ .title }} - Administration</title>
|
||||
<link href="{{.urlbase}}css/bootstrap.min.css" type="text/css" rel="stylesheet">
|
||||
<link href="{{.urlbase}}css/glyphicon.css" type="text/css" rel="stylesheet" media="screen">
|
||||
<style>
|
||||
|
@ -86,7 +86,7 @@ const indextpl = `<!DOCTYPE html>
|
|||
<body class="bg-light text-dark">
|
||||
<nav class="navbar sticky-top navbar-expand-lg navbar-dark text-light" ng-class="{'bg-dark': settings.wip, 'bg-danger': !settings.wip}">
|
||||
<a class="navbar-brand" href=".">
|
||||
<img alt="FIC" src="img/fic.png" style="height: 30px">
|
||||
<img alt="{{ .title }}" src="{{ .logo }}" style="height: 30px">
|
||||
</a>
|
||||
<button class="navbar-toggler" type="button" data-toggle="collapse" data-target="#adminMenu" aria-controls="adminMenu" aria-expanded="false" aria-label="Toggle navigation">
|
||||
<span class="navbar-toggler-icon"></span>
|
||||
|
@ -95,7 +95,7 @@ const indextpl = `<!DOCTYPE html>
|
|||
<div class="collapse navbar-collapse" id="adminMenu">
|
||||
<ul class="navbar-nav mr-auto">
|
||||
<li class="nav-item" ng-class="{'active': $location.path().startsWith('/teams')}"><a class="nav-link" href="teams">Équipes</a></li>
|
||||
<li class="nav-item" ng-class="{'active': $location.path().startsWith('/pki')}"><a class="nav-link" href="pki">PKI</a></li>
|
||||
<li class="nav-item" ng-class="{'active': $location.path().startsWith('/auth')}"><a class="nav-link" href="auth">Authentification</a></li>
|
||||
<li class="nav-item" ng-class="{'active': $location.path().startsWith('/themes')}"><a class="nav-link" href="themes">Thèmes</a></li>
|
||||
<li class="nav-item" ng-class="{'active': $location.path().startsWith('/exercices')}"><a class="nav-link" href="exercices">Exercices</a></li>
|
||||
<li class="nav-item" ng-class="{'active': $location.path().startsWith('/public')}"><a class="nav-link" href="public/0">Public</a></li>
|
||||
|
@ -124,7 +124,7 @@ const indextpl = `<!DOCTYPE html>
|
|||
</div>
|
||||
|
||||
<span id="clock" class="navbar-text" ng-controller="CountdownController" ng-cloak>
|
||||
<div style="position: absolute;">
|
||||
<div style="pointer-events: none; position: absolute;">
|
||||
<div style="position: absolute;" id="circle1" class="circle-anim border-danger"></div>
|
||||
<div style="position: absolute;" id="circle2" class="circle-anim border-info"></div>
|
||||
</div>
|
||||
|
|
|
@ -6,6 +6,7 @@ import (
|
|||
"errors"
|
||||
"log"
|
||||
"net/http"
|
||||
"os"
|
||||
"path"
|
||||
"strings"
|
||||
"text/template"
|
||||
|
@ -25,10 +26,24 @@ var assets embed.FS
|
|||
var indexPage []byte
|
||||
|
||||
func genIndex(baseURL string) {
|
||||
tplcfg := map[string]string{
|
||||
"logo": "img/logo.png",
|
||||
"title": "Challenge",
|
||||
"urlbase": path.Clean(path.Join(baseURL+"/", "nuke"))[:len(path.Clean(path.Join(baseURL+"/", "nuke")))-4],
|
||||
}
|
||||
|
||||
ci, err := api.GetChallengeInfo()
|
||||
if err == nil && ci != nil {
|
||||
tplcfg["title"] = ci.Title
|
||||
if len(ci.MainLogo) > 0 {
|
||||
tplcfg["logo"] = "/files/logo/" + path.Base(ci.MainLogo[0])
|
||||
}
|
||||
}
|
||||
|
||||
b := bytes.NewBufferString("")
|
||||
if indexTmpl, err := template.New("index").Parse(indextpl); err != nil {
|
||||
log.Fatal("Cannot create template:", err)
|
||||
} else if err = indexTmpl.Execute(b, map[string]string{"urlbase": path.Clean(path.Join(baseURL+"/", "nuke"))[:len(path.Clean(path.Join(baseURL+"/", "nuke")))-4]}); err != nil {
|
||||
} else if err = indexTmpl.Execute(b, tplcfg); err != nil {
|
||||
log.Fatal("An error occurs during template execution:", err)
|
||||
} else {
|
||||
indexPage = b.Bytes()
|
||||
|
@ -50,6 +65,9 @@ func declareStaticRoutes(router *gin.RouterGroup, cfg *settings.Settings, baseUR
|
|||
router.GET("/", func(c *gin.Context) {
|
||||
serveIndex(c)
|
||||
})
|
||||
router.GET("/auth/*_", func(c *gin.Context) {
|
||||
serveIndex(c)
|
||||
})
|
||||
router.GET("/claims/*_", func(c *gin.Context) {
|
||||
serveIndex(c)
|
||||
})
|
||||
|
@ -104,8 +122,22 @@ func declareStaticRoutes(router *gin.RouterGroup, cfg *settings.Settings, baseUR
|
|||
})
|
||||
|
||||
router.GET("/files/*_", func(c *gin.Context) {
|
||||
// TODO: handle .gz file here
|
||||
http.ServeFile(c.Writer, c.Request, path.Join(fic.FilesDir, strings.TrimPrefix(c.Request.URL.Path, path.Join(baseURL, "files"))))
|
||||
filepath := path.Join(fic.FilesDir, strings.TrimPrefix(strings.TrimPrefix(c.Request.URL.Path, baseURL), "/files"))
|
||||
|
||||
if st, err := os.Stat(filepath); os.IsNotExist(err) || st.Size() == 0 {
|
||||
if st, err := os.Stat(filepath + ".gz"); err == nil {
|
||||
if fd, err := os.Open(filepath + ".gz"); err == nil {
|
||||
log.Println(filepath + ".gz")
|
||||
c.DataFromReader(http.StatusOK, st.Size(), "application/octet-stream", fd, map[string]string{
|
||||
"Content-Encoding": "gzip",
|
||||
})
|
||||
return
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
log.Println(filepath)
|
||||
c.File(filepath)
|
||||
})
|
||||
router.GET("/submissions/*_", func(c *gin.Context) {
|
||||
http.ServeFile(c.Writer, c.Request, path.Join(api.TimestampCheck, strings.TrimPrefix(c.Request.URL.Path, path.Join(baseURL, "submissions"))))
|
||||
|
|
|
@ -25,6 +25,10 @@ angular.module("FICApp", ["ngRoute", "ngResource", "ngSanitize"])
|
|||
controller: "SettingsController",
|
||||
templateUrl: "views/settings.html"
|
||||
})
|
||||
.when("/auth", {
|
||||
controller: "AuthController",
|
||||
templateUrl: "views/auth.html"
|
||||
})
|
||||
.when("/pki", {
|
||||
controller: "PKIController",
|
||||
templateUrl: "views/pki.html"
|
||||
|
@ -348,6 +352,9 @@ angular.module("FICApp")
|
|||
.factory("ExerciceFlagDeps", function ($resource) {
|
||||
return $resource("api/exercices/:exerciceId/flags/:flagId/dependancies", { exerciceId: '@idExercice', flagId: '@id' })
|
||||
})
|
||||
.factory("ExerciceFlagStats", function ($resource) {
|
||||
return $resource("api/exercices/:exerciceId/flags/:flagId/statistics", { exerciceId: '@idExercice', flagId: '@id' })
|
||||
})
|
||||
.factory("ExerciceMCQFlag", function ($resource) {
|
||||
return $resource("api/exercices/:exerciceId/quiz/:mcqId", { exerciceId: '@idExercice', mcqId: '@id' }, {
|
||||
update: { method: 'PUT' }
|
||||
|
@ -355,6 +362,9 @@ angular.module("FICApp")
|
|||
})
|
||||
.factory("ExerciceMCQDeps", function ($resource) {
|
||||
return $resource("api/exercices/:exerciceId/quiz/:mcqId/dependancies", { exerciceId: '@idExercice', mcqId: '@id' })
|
||||
})
|
||||
.factory("ExerciceMCQStats", function ($resource) {
|
||||
return $resource("api/exercices/:exerciceId/quiz/:mcqId/statistics", { exerciceId: '@idExercice', mcqId: '@id' })
|
||||
});
|
||||
|
||||
angular.module("FICApp")
|
||||
|
@ -611,9 +621,18 @@ angular.module("FICApp")
|
|||
|
||||
response.enableExerciceDepend = response.unlockedChallengeDepth >= 0;
|
||||
response.disabledsubmitbutton = response.disablesubmitbutton && response.disablesubmitbutton.length > 0;
|
||||
if (response.end) {
|
||||
$scope.duration = (response.end - response.start)/60000;
|
||||
}
|
||||
})
|
||||
$scope.challenge = SettingsChallenge.get();
|
||||
$scope.duration = 360;
|
||||
$scope.durationChange = function(endChanged) {
|
||||
if (endChanged)
|
||||
$scope.duration = (new Date($scope.config.end).getTime() - new Date($scope.config.start).getTime())/60000;
|
||||
else
|
||||
$scope.config.end = new Date(new Date($scope.config.start).getTime() + $scope.duration * 60000);
|
||||
}
|
||||
$scope.activateTime = "";
|
||||
$scope.challenge.$promise.then(function (c) {
|
||||
if (c.duration)
|
||||
|
@ -648,7 +667,7 @@ angular.module("FICApp")
|
|||
$scope.saveChallengeInfo = function () {
|
||||
this.challenge.duration = $scope.duration;
|
||||
this.challenge.$update(function (response) {
|
||||
$scope.addToast('success', 'Infos du challenge mises à jour avec succès !');
|
||||
$scope.addToast('success', 'Infos du challenge mises à jour avec succès !');
|
||||
}, function (response) {
|
||||
$scope.addToast('danger', 'An error occurs when saving challenge info:', response.data.errmsg);
|
||||
});
|
||||
|
@ -722,9 +741,9 @@ angular.module("FICApp")
|
|||
"teams": "En validant, vous supprimerez l'ensemble des équipes enregistreées.",
|
||||
"game": "En validant, vous supprimerez toutes les tentatives, les validations, ... faites par les équipes.",
|
||||
}
|
||||
$scope.addToast('warning', txts[type], 'Êtes-vous sûr de vouloir continuer ?',
|
||||
$scope.addToast('warning', txts[type], 'Êtes-vous sûr de vouloir continuer ?',
|
||||
function () {
|
||||
if (confirm("Êtes-vous vraiment sûr ?\n" + txts[type])) {
|
||||
if (confirm("Êtes-vous vraiment sûr ?\n" + txts[type])) {
|
||||
$http.post("api/reset", { "type": type }).then(function (time) {
|
||||
$scope.addToast('success', type + 'reseted');
|
||||
$location.url("/");
|
||||
|
@ -736,7 +755,7 @@ angular.module("FICApp")
|
|||
});
|
||||
};
|
||||
$scope.switchToProd = function () {
|
||||
$scope.addToast('warning', "Activer le mode challenge ?", "L'activation du mode challenge est temporaire (vous devriez plutôt relancer le daemon avec l'option `-4real`). Ce mode permet d'éviter les mauvaises manipulations et désactive le hook git de synchronisation automatique. Êtes-vous sûr de vouloir continuer ?",
|
||||
$scope.addToast('warning', "Activer le mode challenge ?", "L'activation du mode challenge est temporaire (vous devriez plutôt relancer le daemon avec l'option `-4real`). Ce mode permet d'éviter les mauvaises manipulations et désactive le hook git de synchronisation automatique. Êtes-vous sûr de vouloir continuer ?",
|
||||
function () {
|
||||
$http.put("api/prod", true).then(function (time) {
|
||||
$rootScope.refreshSettings()
|
||||
|
@ -759,6 +778,20 @@ angular.module("FICApp")
|
|||
});
|
||||
};
|
||||
})
|
||||
.component('teamLink', {
|
||||
bindings: {
|
||||
idTeam: '=',
|
||||
},
|
||||
controller: function (Team) {
|
||||
var ctrl = this;
|
||||
ctrl.team = {};
|
||||
|
||||
ctrl.$onInit = function () {
|
||||
ctrl.team = Team.get({teamId: ctrl.idTeam});
|
||||
};
|
||||
},
|
||||
template: `<a href="/teams/{{ $ctrl.idTeam }}">{{ $ctrl.team.name }}</a> `
|
||||
})
|
||||
.component('repositoryUptodate', {
|
||||
bindings: {
|
||||
repository: '<',
|
||||
|
@ -820,10 +853,10 @@ angular.module("FICApp")
|
|||
|
||||
$scope.deepSync = function (theme) {
|
||||
if (theme) {
|
||||
question = 'Faire une synchronisation intégrale du thème ' + theme.name + ' ?'
|
||||
question = 'Faire une synchronisation intégrale du thème ' + theme.name + ' ?'
|
||||
url = "api/sync/deep/" + theme.id
|
||||
} else {
|
||||
question = 'Faire une synchronisation intégrale ?'
|
||||
question = 'Faire une synchronisation intégrale ?'
|
||||
url = "api/sync/deep"
|
||||
}
|
||||
$scope.addToast('warning', question, '',
|
||||
|
@ -839,7 +872,7 @@ angular.module("FICApp")
|
|||
});
|
||||
};
|
||||
$scope.speedyDeepSync = function () {
|
||||
$scope.addToast('warning', 'Faire une synchronisation profonde rapide, sans s\'occuper des fichiers ?', '',
|
||||
$scope.addToast('warning', 'Faire une synchronisation profonde rapide, sans s\'occuper des fichiers ?', '',
|
||||
function () {
|
||||
$scope.deepSyncInProgress = true;
|
||||
$http.post("api/sync/speed").then(function () {
|
||||
|
@ -852,7 +885,7 @@ angular.module("FICApp")
|
|||
});
|
||||
};
|
||||
$scope.baseSync = function () {
|
||||
$scope.addToast('warning', 'Tirer les mises à jour du dépôt ?', '',
|
||||
$scope.addToast('warning', 'Tirer les mises à jour du dépôt ?', '',
|
||||
function () {
|
||||
$scope.deepSyncInProgress = true;
|
||||
$http.post("api/sync/base").then(function () {
|
||||
|
@ -865,7 +898,7 @@ angular.module("FICApp")
|
|||
});
|
||||
};
|
||||
$scope.syncVideos = function () {
|
||||
$scope.addToast('warning', 'Synchroniser les vidéos de résolution ?', 'ATTENTION il ne faut pas lancer cette synchronisation durant le challenge. Seulement une fois le challenge terminé, cela permet de rendre les vidéos accessibles dans l\'interface joueurs.',
|
||||
$scope.addToast('warning', 'Synchroniser les vidéos de résolution ?', 'ATTENTION il ne faut pas lancer cette synchronisation durant le challenge. Seulement une fois le challenge terminé, cela permet de rendre les vidéos accessibles dans l\'interface joueurs.',
|
||||
function () {
|
||||
$scope.deepSyncInProgress = true;
|
||||
$http.post("api/sync/videos").then(function () {
|
||||
|
@ -892,6 +925,49 @@ angular.module("FICApp")
|
|||
};
|
||||
})
|
||||
|
||||
.controller("AuthController", function ($scope, $http) {
|
||||
$scope.generateHtpasswd = function () {
|
||||
$http.post("api/htpasswd").then(function () {
|
||||
$scope.addToast('success', 'Fichier htpasswd généré avec succès');
|
||||
}, function (response) {
|
||||
$scope.addToast('danger', 'An error occurs when generating htpasswd file:', response.data.errmsg);
|
||||
});
|
||||
};
|
||||
$scope.removeHtpasswd = function () {
|
||||
$http.delete("api/htpasswd").then(function () {
|
||||
$scope.addToast('success', 'Fichier htpasswd supprimé avec succès');
|
||||
}, function (response) {
|
||||
$scope.addToast('danger', 'An error occurs when deleting htpasswd file:', response.data.errmsg);
|
||||
});
|
||||
};
|
||||
})
|
||||
|
||||
.controller("OAuthController", function ($scope, $http) {
|
||||
$scope.refreshOAuthStatus = function () {
|
||||
$http.get("api/oauth-status").then(function (res) {
|
||||
$scope.oauth_status = response.data;
|
||||
});
|
||||
|
||||
};
|
||||
|
||||
$scope.genDexCfg = function () {
|
||||
$http.post("api/dex.yaml").then(function () {
|
||||
$http.post("api/dex-password.tpl").then(function () {
|
||||
$scope.addToast('success', 'Dex config refreshed.', "Don't forget to reload/reboot frontend host.");
|
||||
}, function (response) {
|
||||
$scope.addToast('danger', 'An error occurs when generating dex password tpl:', response.data.errmsg);
|
||||
});
|
||||
}, function (response) {
|
||||
$scope.addToast('danger', 'An error occurs when generating dex config:', response.data.errmsg);
|
||||
});
|
||||
$http.post("api/vouch-proxy.yaml").then(function () {
|
||||
$scope.addToast('success', 'VouchProxy config refreshed.', "Don't forget to reload/reboot frontend host.");
|
||||
}, function (response) {
|
||||
$scope.addToast('danger', 'An error occurs when generating VouchProxy config:', response.data.errmsg);
|
||||
});
|
||||
}
|
||||
})
|
||||
|
||||
.controller("PKIController", function ($scope, $rootScope, Certificate, CACertificate, Team, $location, $http) {
|
||||
var ts = Date.now() - Date.now() % 86400000;
|
||||
var d = new Date(ts);
|
||||
|
@ -976,20 +1052,6 @@ angular.module("FICApp")
|
|||
$scope.addToast('danger', 'An error occurs when generating certificate:', response.data.errmsg);
|
||||
});
|
||||
};
|
||||
$scope.generateHtpasswd = function () {
|
||||
$http.post("api/htpasswd").then(function () {
|
||||
$scope.addToast('success', 'Fichier htpasswd généré avec succès');
|
||||
}, function (response) {
|
||||
$scope.addToast('danger', 'An error occurs when generating htpasswd file:', response.data.errmsg);
|
||||
});
|
||||
};
|
||||
$scope.removeHtpasswd = function () {
|
||||
$http.delete("api/htpasswd").then(function () {
|
||||
$scope.addToast('success', 'Fichier htpasswd supprimé avec succès');
|
||||
}, function (response) {
|
||||
$scope.addToast('danger', 'An error occurs when deleting htpasswd file:', response.data.errmsg);
|
||||
});
|
||||
};
|
||||
})
|
||||
|
||||
.controller("PublicController", function ($scope, $rootScope, $routeParams, $location, Scene, Theme, Teams, Exercice) {
|
||||
|
@ -1110,7 +1172,7 @@ angular.module("FICApp")
|
|||
},
|
||||
{
|
||||
type: "countdown",
|
||||
params: { color: "success", end: null, lead: "Go, go, go !", title: "Le challenge forensic va bientôt commencer !" },
|
||||
params: { color: "success", end: null, lead: "Go, go, go !", title: "Le challenge forensic va bientôt commencer !" },
|
||||
},
|
||||
];
|
||||
$scope.display.side = [
|
||||
|
@ -1229,8 +1291,8 @@ angular.module("FICApp")
|
|||
show: true,
|
||||
shadow: "#E8CF5C",
|
||||
end: new Date($rootScope.getSrvTime().getTime() + 1802000).toISOString(),
|
||||
before: "Heure joyeuse : chaque résolution compte double !",
|
||||
after: "Heure joyeuse terminée !",
|
||||
before: "Heure joyeuse : chaque résolution compte double !",
|
||||
after: "Heure joyeuse terminée !",
|
||||
}
|
||||
}
|
||||
else if (scene == "freehintquarter") {
|
||||
|
@ -1238,8 +1300,8 @@ angular.module("FICApp")
|
|||
show: true,
|
||||
shadow: "#3DD28F",
|
||||
end: new Date($rootScope.getSrvTime().getTime() + 902000).toISOString(),
|
||||
before: "Quart d'heure facile : indices dévoilés !",
|
||||
after: "Quart d'heure facile terminée !",
|
||||
before: "Quart d'heure facile : indices dévoilés !",
|
||||
after: "Quart d'heure facile terminée !",
|
||||
}
|
||||
}
|
||||
};
|
||||
|
@ -1368,7 +1430,7 @@ angular.module("FICApp")
|
|||
});
|
||||
};
|
||||
$scope.clearFilesDir = function () {
|
||||
$scope.addToast('warning', 'Êtes-vous sûr de vouloir continuer ?', "Ceci va supprimer tout le contenu du dossier FILES. Il s'agit des fichiers ci-dessous, il faudra refaire une synchronisation ensuite.",
|
||||
$scope.addToast('warning', 'Êtes-vous sûr de vouloir continuer ?', "Ceci va supprimer tout le contenu du dossier FILES. Il s'agit des fichiers ci-dessous, il faudra refaire une synchronisation ensuite.",
|
||||
function () {
|
||||
$scope.clearFilesWIP = true;
|
||||
$http({
|
||||
|
@ -2255,9 +2317,9 @@ angular.module("FICApp")
|
|||
}
|
||||
$scope.saveFlag = function () {
|
||||
if (this.flag.id) {
|
||||
this.flag.$update();
|
||||
this.flag.$update().then(function() {}, function(error) { $scope.addToast('danger', 'Impossible de mettre à jour le flag :', error.data.errmsg); });
|
||||
} else {
|
||||
this.flag.$save({ exerciceId: $routeParams.exerciceId });
|
||||
this.flag.$save({ exerciceId: $routeParams.exerciceId }).then(function() {}, function(error) { $scope.addToast('danger', 'Impossible de créer le flag :', error.data.errmsg); });
|
||||
}
|
||||
$rootScope.staticFilesNeedUpdate++;
|
||||
}
|
||||
|
@ -2276,7 +2338,7 @@ angular.module("FICApp")
|
|||
method: "POST"
|
||||
}).then(function (response) {
|
||||
flag.test_str = "";
|
||||
$scope.addToast('success', "Flag Ok !");
|
||||
$scope.addToast('success', "Flag Ok !");
|
||||
}, function (response) {
|
||||
flag.test_str = "";
|
||||
$scope.addToast('danger', 'An error occurs: ', response.data.errmsg);
|
||||
|
@ -2345,6 +2407,18 @@ angular.module("FICApp")
|
|||
}
|
||||
})
|
||||
|
||||
.controller("ExerciceFlagStatsController", function ($scope, $routeParams, ExerciceFlagStats, $http) {
|
||||
$scope.init = function (flag) {
|
||||
$scope.flag_id = flag.id;
|
||||
$scope.stats = ExerciceFlagStats.get({ exerciceId: $routeParams.exerciceId, flagId: flag.id });
|
||||
}
|
||||
$scope.deleteTries = function () {
|
||||
$http.delete(`/api/exercices/${$routeParams.exerciceId}/flags/${$scope.flag_id}/tries`).then(function () {
|
||||
$scope.stats = ExerciceFlagStats.get({ exerciceId: $routeParams.exerciceId, flagId: $scope.flag_id });
|
||||
});
|
||||
}
|
||||
})
|
||||
|
||||
.controller("ExerciceMCQFlagsController", function ($scope, ExerciceMCQFlag, $routeParams, $rootScope) {
|
||||
$scope.quiz = ExerciceMCQFlag.query({ exerciceId: $routeParams.exerciceId });
|
||||
|
||||
|
@ -2382,6 +2456,18 @@ angular.module("FICApp")
|
|||
}
|
||||
})
|
||||
|
||||
.controller("ExerciceMCQStatsController", function ($scope, $routeParams, ExerciceMCQStats, $http) {
|
||||
$scope.init = function (mcq) {
|
||||
$scope.mcq_id = mcq.id;
|
||||
$scope.stats = ExerciceMCQStats.get({ exerciceId: $routeParams.exerciceId, mcqId: mcq.id });
|
||||
}
|
||||
$scope.deleteTries = function () {
|
||||
$http.delete(`/api/exercices/${$routeParams.exerciceId}/quiz/${$scope.mcq_id}/tries`).then(function () {
|
||||
$scope.stats = ExerciceMCQStats.get({ exerciceId: $routeParams.exerciceId, mcqId: $scope.mcq_id });
|
||||
});
|
||||
}
|
||||
})
|
||||
|
||||
.controller("TeamsListController", function ($scope, $rootScope, Team, $location, $http) {
|
||||
$scope.teams = Team.query();
|
||||
$scope.fields = ["id", "name"];
|
||||
|
@ -2408,22 +2494,6 @@ angular.module("FICApp")
|
|||
}
|
||||
};
|
||||
|
||||
$scope.genDexCfg = function () {
|
||||
$http.post("api/dex.yaml").then(function () {
|
||||
$http.post("api/dex-password.tpl").then(function () {
|
||||
$scope.addToast('success', 'Dex config refreshed.', "Don't forget to reload/reboot frontend host.");
|
||||
}, function (response) {
|
||||
$scope.addToast('danger', 'An error occurs when generating dex password tpl:', response.data.errmsg);
|
||||
});
|
||||
}, function (response) {
|
||||
$scope.addToast('danger', 'An error occurs when generating dex config:', response.data.errmsg);
|
||||
});
|
||||
$http.post("api/vouch-proxy.yaml").then(function () {
|
||||
$scope.addToast('success', 'VouchProxy config refreshed.', "Don't forget to reload/reboot frontend host.");
|
||||
}, function (response) {
|
||||
$scope.addToast('danger', 'An error occurs when generating VouchProxy config:', response.data.errmsg);
|
||||
});
|
||||
}
|
||||
$scope.desactiveTeams = function () {
|
||||
$http.post("api/disableinactiveteams").then(function () {
|
||||
$scope.teams = Team.query();
|
||||
|
@ -2431,9 +2501,34 @@ angular.module("FICApp")
|
|||
$scope.addToast('danger', 'An error occurs when disabling inactive teams:', response.data.errmsg);
|
||||
});
|
||||
}
|
||||
$scope.refineTeamsColors = function () {
|
||||
$http.post("api/refine_colors").then(function () {
|
||||
$scope.teams = Team.query();
|
||||
}, function (response) {
|
||||
$scope.addToast('danger', 'An error occurs when updating teams:', response.data.errmsg);
|
||||
});
|
||||
}
|
||||
$scope.show = function (id) {
|
||||
$location.url("/teams/" + id);
|
||||
};
|
||||
$scope.triggerTeamsImport = function() {
|
||||
document.getElementById('crTeamsInput').click();
|
||||
};
|
||||
$scope.uploadFile = function() {
|
||||
var formData = new FormData();
|
||||
formData.append('file', $scope.selectedFile);
|
||||
|
||||
$http.post('api/cyberrange-teams.json', formData, {
|
||||
transformRequest: angular.identity,
|
||||
headers: {'Content-Type': undefined},
|
||||
}).then(function(response) {
|
||||
$scope.teams = response.data;
|
||||
$scope.addToast('success', 'Import des équipes', "L'import a été réalisé avec succès !");
|
||||
}, function(error) {
|
||||
console.log(error);
|
||||
$scope.addToast('danger', 'Import des équipes', error.data.errmsg);
|
||||
});
|
||||
};
|
||||
})
|
||||
.controller("TeamMembersController", function ($scope, TeamMember) {
|
||||
$scope.fields = ["firstname", "lastname", "nickname", "company"];
|
||||
|
|
|
@ -81,6 +81,22 @@ angular.module("FICApp")
|
|||
});
|
||||
}
|
||||
}
|
||||
}])
|
||||
.directive('fileModel', ['$parse', function ($parse) {
|
||||
return {
|
||||
restrict: 'A',
|
||||
link: function($scope, element, attrs) {
|
||||
var model = $parse(attrs.fileModel);
|
||||
var modelSetter = model.assign;
|
||||
|
||||
element.bind('change', function(){
|
||||
$scope.$apply(function(){
|
||||
modelSetter($scope, element[0].files[0]);
|
||||
$scope.uploadFile();
|
||||
});
|
||||
});
|
||||
}
|
||||
};
|
||||
}]);
|
||||
|
||||
angular.module("FICApp")
|
||||
|
|
86
admin/static/views/auth.html
Normal file
86
admin/static/views/auth.html
Normal file
|
@ -0,0 +1,86 @@
|
|||
<div class="d-flex justify-content-between align-items-center">
|
||||
<h2>
|
||||
Authentification
|
||||
</h2>
|
||||
<div>
|
||||
<div class="btn-group mr-1" role="group">
|
||||
<button type="button" ng-click="generateHtpasswd()" class="btn btn-sm btn-secondary"><span class="glyphicon glyphicon-save-file" aria-hidden="true"></span> Générer <code>fichtpasswd</code></button>
|
||||
<button type="button" ng-click="removeHtpasswd()" class="btn btn-sm btn-danger"><span class="glyphicon glyphicon-trash" aria-hidden="true"></span></button>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div ng-controller="OAuthController">
|
||||
<div class="d-flex justify-content-between align-items-center">
|
||||
<h3>
|
||||
OAuth 2
|
||||
<span class="badge badge-success" ng-if="oauth_status.secret_defined">Actif</span>
|
||||
<span class="badge badge-danger" ng-if="!oauth_status.secret_defined">Non configuré</span>
|
||||
</h3>
|
||||
<div>
|
||||
<button type="button" ng-click="genDexCfg()" class="btn btn-success mr-2"><span class="glyphicon glyphicon-refresh" aria-hidden="true"></span> DexIdP</button>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<hr>
|
||||
|
||||
<div ng-controller="PKIController">
|
||||
<div class="d-flex justify-content-between align-items-center">
|
||||
<h3>
|
||||
Autorité de certification
|
||||
<span class="badge badge-success" ng-if="ca.version">Générée</span>
|
||||
<span class="badge badge-danger" ng-if="!ca.version">Introuvable</span>
|
||||
</h3>
|
||||
<div>
|
||||
<a
|
||||
class="btn btn-primary"
|
||||
href="/pki"
|
||||
>
|
||||
<span class="glyphicon glyphicon-certificate" aria-hidden="true"></span>
|
||||
Gérer la PKI
|
||||
</a>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div class="alert alert-info" ng-if="!ca.version">
|
||||
<strong>Aucune CA n'a été générée pour le moment.</strong>
|
||||
</div>
|
||||
|
||||
<dl ng-if="ca.version">
|
||||
<ng-repeat ng-repeat="(k, v) in ca" class="row">
|
||||
<dt class="col-3 text-right">{{ k }}</dt>
|
||||
<dd class="col-9" ng-if="v.CommonName">/CN={{ v.CommonName }}/OU={{ v.OrganizationalUnit }}/O={{ v.Organization }}/L={{ v.Locality }}/P={{ v.Province }}/C={{ v.Country }}/</dd>
|
||||
<dd class="col-9" ng-if="!v.CommonName">{{ v }}</dd>
|
||||
</ng-repeat>
|
||||
</dl>
|
||||
</div>
|
||||
|
||||
<hr>
|
||||
|
||||
<div class="mb-4" ng-controller="AllTeamAssociationsController">
|
||||
<div class="d-flex justify-content-between align-items-center">
|
||||
<h3>
|
||||
Association utilisateurs et équipes
|
||||
</h3>
|
||||
<div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<table class="table table-sm table-hover" ng-controller="TeamsListController" >
|
||||
<tr>
|
||||
<th class="text-right">Utilisateur</th>
|
||||
<th></th>
|
||||
<th>Équipe</th>
|
||||
</tr>
|
||||
<tr ng-repeat="association in allAssociations">
|
||||
<td class="text-right">{{ association.association }}</td>
|
||||
<td class="text-center">⬌</td>
|
||||
<td ng-repeat="team in teams" ng-if="team.id == association.team_id">
|
||||
<a ng-href="teams/{{ team.id }}">
|
||||
{{ team.name }}
|
||||
</a>
|
||||
</td>
|
||||
</tr>
|
||||
</table>
|
||||
</div>
|
|
@ -73,12 +73,28 @@
|
|||
</div>
|
||||
<div class="col-4">
|
||||
<div ng-controller="ExerciceFlagDepsController" ng-init="init(flag)">
|
||||
Dépendances :
|
||||
<strong>Dépendances :</strong>
|
||||
<ul ng-if="deps.length > 0">
|
||||
<dependancy ng-repeat="dep in deps" dep="dep"></dependancy>
|
||||
</ul>
|
||||
<span ng-if="deps.length == 0"> sans</span>
|
||||
</div>
|
||||
<hr>
|
||||
<div ng-controller="ExerciceFlagStatsController" ng-init="init(flag)">
|
||||
<strong>Statistiques</strong>
|
||||
<ul>
|
||||
<li>Validés : {{ stats["completed"] }}</li>
|
||||
<li>
|
||||
Tentés : {{ stats["tries"] }}
|
||||
<button type="button" ng-click="deleteTries()" class="btn btn-sm btn-danger" ng-if="stats['tries'] > 0"><span class="glyphicon glyphicon-trash" aria-hidden="true"></span></button>
|
||||
</li>
|
||||
<li>
|
||||
Équipes :
|
||||
<span ng-if="stats['teams'].length == 0">aucune</span>
|
||||
<team-link ng-repeat="team in stats['teams']" id-team="team"></team-link>
|
||||
</li>
|
||||
</ul>
|
||||
</div>
|
||||
</div>
|
||||
<div class="col-4" ng-controller="ExerciceFlagChoicesController">
|
||||
<div class="btn-toolbar justify-content-end mb-2" role="toolbar">
|
||||
|
@ -168,6 +184,22 @@
|
|||
<dependancy ng-repeat="dep in deps" dep="dep"></dependancy>
|
||||
</ul>
|
||||
<span ng-if="deps.length == 0"> sans</span>
|
||||
<hr>
|
||||
<div ng-controller="ExerciceMCQStatsController" ng-init="init(q)">
|
||||
<strong>Statistiques</strong>
|
||||
<ul>
|
||||
<li>Validés : {{ stats["completed"] }}</li>
|
||||
<li>
|
||||
Tentés : {{ stats["tries"] }}
|
||||
<button type="button" ng-click="deleteTries()" class="btn btn-sm btn-danger" ng-if="stats['tries'] > 0"><span class="glyphicon glyphicon-trash" aria-hidden="true"></span></button>
|
||||
</li>
|
||||
<li>
|
||||
Équipes :
|
||||
<span ng-if="stats['teams'].length == 0">aucune</span>
|
||||
<team-link ng-repeat="team in stats['teams']" id-team="team"></team-link>
|
||||
</li>
|
||||
</ul>
|
||||
</div>
|
||||
</div>
|
||||
</form>
|
||||
</div>
|
||||
|
|
|
@ -100,7 +100,7 @@
|
|||
<form ng-submit="saveFile()" class="list-group-item bg-light text-dark" ng-repeat="file in files">
|
||||
<div class="row form-group">
|
||||
<input type="text" ng-model="file.name" class="col form-control form-control-sm" placeholder="Nom de fichier">
|
||||
<a href="../files{{file.path}}" class="btn btn-sm btn-secondary col-auto"><span class="glyphicon glyphicon-download" aria-hidden="true"></span></a>
|
||||
<a href="../files{{file.path}}" target="_self" class="btn btn-sm btn-secondary col-auto"><span class="glyphicon glyphicon-download" aria-hidden="true"></span></a>
|
||||
<button type="submit" class="btn btn-sm btn-success col-auto"><span class="glyphicon glyphicon-ok" aria-hidden="true"></span></button><br>
|
||||
<button type="button" ng-click="deleteFile()" class="btn btn-sm btn-danger col-auto"><span class="glyphicon glyphicon-remove" aria-hidden="true"></span></button>
|
||||
</div>
|
||||
|
|
|
@ -30,13 +30,13 @@
|
|||
<div class="spinner-border spinner-border-sm" role="status" ng-if="file.gunzipWIP"></div>
|
||||
</button>
|
||||
</td>
|
||||
<td ng-repeat="field in fields">
|
||||
<td ng-repeat="field in fields" class="text-truncate" style="max-width: 30vw" title="{{ file[field] }}">
|
||||
{{ file[field] }}
|
||||
<span ng-if="field == 'id' && file.err !== undefined && file.err !== true" title="{{ file.err }}" class="glyphicon glyphicon-exclamation-sign"></span>
|
||||
</td>
|
||||
<td>
|
||||
{{ file.checksum | bto16 }}
|
||||
<div ng-if="file.checksum_shown">{{ file.checksum_shown | bto16 }}</div>
|
||||
<td style="max-width: 100px">
|
||||
<div class="text-truncate" title="{{ file.checksum | bto16 }}">{{ file.checksum | bto16 }}</div>
|
||||
<div class="text-truncate" ng-if="file.checksum_shown" title="{{ file.checksum_shown | bto16 }}">{{ file.checksum_shown | bto16 }}</div>
|
||||
</td>
|
||||
</tr>
|
||||
</tbody>
|
||||
|
|
|
@ -35,7 +35,7 @@
|
|||
<label for="startTime" class="col-sm-3 col-form-label col-form-label-sm" ng-class="{'text-primary font-weight-bold': config.start != dist_config.start}">Début du challenge</label>
|
||||
<div class="col-sm-9">
|
||||
<div class="input-group">
|
||||
<input type="datetime-local" class="form-control form-control-sm" id="startTime" ng-model="config.start" ng-class="{'border-primary': config.start != dist_config.start}">
|
||||
<input type="datetime-local" class="form-control form-control-sm" id="startTime" ng-model="config.start" ng-change="durationChange()" ng-class="{'border-primary': config.start != dist_config.start}">
|
||||
<div class="input-group-append">
|
||||
<button ng-click="launchChallenge()" class="btn btn-sm btn-secondary" type="button"><span class="glyphicon glyphicon-play" aria-hidden="true"></span> Lancer le challenge</button>
|
||||
</div>
|
||||
|
@ -46,14 +46,14 @@
|
|||
<div class="form-group row">
|
||||
<label for="endTime" class="col-sm-3 col-form-label col-form-label-sm" ng-class="{'text-primary font-weight-bold': config.end != dist_config.end}">Fin du challenge</label>
|
||||
<div class="col-sm-6">
|
||||
<input type="datetime-local" class="form-control form-control-sm" id="endTime" ng-model="config.end" ng-class="{'border-primary': config.end != dist_config.end}">
|
||||
<input type="datetime-local" class="form-control form-control-sm" id="endTime" ng-model="config.end" ng-change="durationChange(true)" ng-class="{'border-primary': config.end != dist_config.end}">
|
||||
</div>
|
||||
<div class="col-sm-1 text-right">
|
||||
<label for="duration" class="col-form-label col-form-label-sm">Durée</label>
|
||||
</div>
|
||||
<div class="col-sm-2">
|
||||
<div class="input-group input-group-sm">
|
||||
<input type="text" class="form-control form-control-sm" id="duration" ng-model="duration" integer>
|
||||
<input type="number" class="form-control form-control-sm" id="duration" ng-model="duration" ng-change="durationChange()" integer>
|
||||
<div class="input-group-append">
|
||||
<span class="input-group-text">min</span>
|
||||
</div>
|
||||
|
@ -323,7 +323,7 @@
|
|||
<form class="row" ng-controller="AllTeamAssociationsController" ng-submit="addDelegatedQA()">
|
||||
<div class="col">
|
||||
<select class="form-control form-control-sm" ng-model="newdqa">
|
||||
<option ng-selected="newdqa == m" ng-repeat="(i,m) in allAssociations" ng-value="m">{{ m }}</option>
|
||||
<option ng-selected="newdqa == m.association" ng-repeat="(i,m) in allAssociations" ng-value="m.association">{{ m.association }}</option>
|
||||
</select>
|
||||
</div>
|
||||
<div class="col input-group">
|
||||
|
|
|
@ -1,11 +1,19 @@
|
|||
<div class="d-flex justify-content-between align-items-center">
|
||||
<h2>
|
||||
Équipes
|
||||
<button type="button" ng-click="show('new')" class="float-right btn btn-sm btn-primary"><span class="glyphicon glyphicon-plus" aria-hidden="true"></span> Ajouter une équipe</button>
|
||||
<button type="button" ng-click="show('print')" class="float-right btn btn-sm btn-secondary mr-2"><span class="glyphicon glyphicon-print" aria-hidden="true"></span> Imprimer les équipes</button>
|
||||
<button type="button" ng-click="show('export')" class="float-right btn btn-sm btn-secondary mr-2"><span class="glyphicon glyphicon-export" aria-hidden="true"></span> Statistiques générales</button>
|
||||
<button type="button" ng-click="desactiveTeams()" class="float-right btn btn-sm btn-danger mr-2" title="Cliquer pour marquer les équipes sans certificat comme inactives (et ainsi éviter que ses fichiers ne soient générés)"><span class="glyphicon glyphicon-leaf" aria-hidden="true"></span> Désactiver les équipes inactives</button>
|
||||
<button type="button" ng-click="genDexCfg()" class="float-right btn btn-sm btn-success mr-2"><span class="glyphicon glyphicon-refresh" aria-hidden="true"></span> DexIdP</button>
|
||||
</h2>
|
||||
<div>
|
||||
<button type="button" ng-click="show('new')" class="btn btn-sm btn-primary ml-1"><span class="glyphicon glyphicon-plus" aria-hidden="true"></span> Ajouter une équipe</button>
|
||||
<form class="d-inline">
|
||||
<input id="crTeamsInput" type="file" file-model="selectedFile" class="d-none" />
|
||||
<button type="button" ng-click="triggerTeamsImport()" class="btn btn-sm btn-secondary ml-1"><span class="glyphicon glyphicon-import" aria-hidden="true"></span> Import Cyberrange</button>
|
||||
</form>
|
||||
<button type="button" ng-click="show('print')" class="btn btn-sm btn-secondary ml-1" title="Imprimer les équipes et leurs membres"><span class="glyphicon glyphicon-print" aria-hidden="true"></span></button>
|
||||
<button type="button" ng-click="refineTeamsColors()" class="btn btn-sm btn-secondary ml-1" title="Réarranger automatiquement les couleurs des équipes pour maximiser le spectre utilisé"><span class="glyphicon glyphicon-adjust" aria-hidden="true"></span></button>
|
||||
<button type="button" ng-click="show('export')" class="btn btn-sm btn-secondary ml-1"><span class="glyphicon glyphicon-export" aria-hidden="true"></span> Statistiques générales</button>
|
||||
<button type="button" ng-click="desactiveTeams()" class="btn btn-sm btn-danger ml-1" title="Cliquer pour marquer les équipes sans certificat comme inactives (et ainsi éviter que ses fichiers ne soient générés)"><span class="glyphicon glyphicon-leaf" aria-hidden="true"></span> Désactiver les équipes inactives</button>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<p><input type="search" class="form-control" placeholder="Search" ng-model="query" ng-keypress="validateSearch($event)" autofocus></p>
|
||||
<table class="table table-hover table-bordered table-striped table-sm">
|
||||
|
|
|
@ -279,6 +279,7 @@ func buildKeyFlag(exercice *fic.Exercice, flag ExerciceFlag, flagline int, defau
|
|||
}
|
||||
|
||||
type importFlag struct {
|
||||
origin ExerciceFlag
|
||||
Line int
|
||||
Flag fic.Flag
|
||||
JustifyOf *fic.MCQ_entry
|
||||
|
@ -392,6 +393,7 @@ func buildExerciceFlag(i Importer, exercice *fic.Exercice, flag ExerciceFlag, nl
|
|||
errs = multierr.Append(errs, berrs)
|
||||
if addedFlag != nil {
|
||||
ret = append(ret, importFlag{
|
||||
origin: flag,
|
||||
Line: nline + 1,
|
||||
Flag: addedFlag,
|
||||
})
|
||||
|
@ -401,6 +403,7 @@ func buildExerciceFlag(i Importer, exercice *fic.Exercice, flag ExerciceFlag, nl
|
|||
errs = multierr.Append(errs, berrs)
|
||||
if addedFlag != nil {
|
||||
ret = append(ret, importFlag{
|
||||
origin: flag,
|
||||
Line: nline + 1,
|
||||
Flag: *addedFlag,
|
||||
Choices: choices,
|
||||
|
@ -462,6 +465,7 @@ func buildExerciceFlag(i Importer, exercice *fic.Exercice, flag ExerciceFlag, nl
|
|||
errs = multierr.Append(errs, berrs)
|
||||
if addedFlag != nil {
|
||||
ret = append(ret, importFlag{
|
||||
origin: flag,
|
||||
Line: nline + 1,
|
||||
Flag: *addedFlag,
|
||||
JustifyOf: entry,
|
||||
|
@ -479,6 +483,7 @@ func buildExerciceFlag(i Importer, exercice *fic.Exercice, flag ExerciceFlag, nl
|
|||
}
|
||||
|
||||
ret = append([]importFlag{importFlag{
|
||||
origin: flag,
|
||||
Line: nline + 1,
|
||||
Flag: &addedFlag,
|
||||
}}, ret...)
|
||||
|
@ -570,6 +575,10 @@ func CheckExerciceFlags(i Importer, exercice *fic.Exercice, files []string, exce
|
|||
if int64(fk.ChoicesCost) >= exercice.Gain {
|
||||
errs = multierr.Append(errs, NewFlagError(exercice, nil, flag.Line, fmt.Errorf("flag's choice_cost is higher than exercice gain")))
|
||||
}
|
||||
|
||||
if raw, ok := flag.origin.Raw.(string); ok && raw == fk.Placeholder {
|
||||
errs = multierr.Append(errs, NewFlagError(exercice, nil, flag.Line, fmt.Errorf("flag's placeholder and raw are identical")))
|
||||
}
|
||||
}
|
||||
|
||||
// Check dependency loop
|
||||
|
|
|
@ -238,3 +238,21 @@ func WriteFileContent(i Importer, URI string, content []byte) error {
|
|||
return fmt.Errorf("%t is not capable of writing", i)
|
||||
}
|
||||
}
|
||||
|
||||
func OpenOrGetFile(i Importer, URI string) (fd io.Reader, closer func() error, err error) {
|
||||
if strings.HasPrefix(URI, "$FILES$") {
|
||||
var fdc io.ReadCloser
|
||||
fdc, err = os.Open(path.Join(fic.FilesDir, strings.TrimPrefix(URI, "$FILES$/")))
|
||||
fd = fdc
|
||||
closer = fdc.Close
|
||||
} else {
|
||||
fd, err = GlobalImporter.GetFile(URI)
|
||||
if fdcloser, ok := fd.(io.ReadCloser); ok {
|
||||
closer = fdcloser.Close
|
||||
} else {
|
||||
closer = func() error { return nil }
|
||||
}
|
||||
}
|
||||
|
||||
return
|
||||
}
|
||||
|
|
|
@ -20,6 +20,8 @@ escape_newline () {
|
|||
sed 's/$/\\n/g' | tr -d '\n'
|
||||
}
|
||||
|
||||
which mkisofs > /dev/null 2> /dev/null || { echo "Please install genisoimage (Debian/Ubuntu) or cdrkit (Alpine)" >&2; exit 1; }
|
||||
|
||||
if [ $# -gt 0 ]
|
||||
then
|
||||
which jq > /dev/null 2> /dev/null || { echo "Please install jq" >&2; exit 1; }
|
||||
|
|
|
@ -21,6 +21,8 @@ OLD_KEY=$(cat /run/config/dm-crypt/key)
|
|||
[ "${NEW_KEY}" != "${OLD_KEY}" ] && {
|
||||
read -p "DM-CRYPT key changed in metadata, are you sure you want to erase it? (y/N) " V
|
||||
[ "$V" != "y" ] && [ "$V" != "Y" ] && while true; do
|
||||
mv /boot/imgs/fickit-metadata.iso /boot/imgs/fickit-metadata.iso.skipped
|
||||
cp /boot/imgs/fickit-metadata.iso.bak /boot/imgs/fickit-metadata.iso
|
||||
echo
|
||||
echo "Metadata drive not erased"
|
||||
echo
|
||||
|
|
|
@ -1,54 +1,54 @@
|
|||
kernel:
|
||||
#image: nemunaire/kernel:5.10.62-0b705d955f5e283f62583c4e227d64a7924c138f-amd64
|
||||
image: linuxkit/kernel:6.6.13
|
||||
image: linuxkit/kernel:6.6.71
|
||||
cmdline: "console=ttyS0 console=tty0"
|
||||
|
||||
init:
|
||||
- linuxkit/init:7135424f6836ee166d1199e88cfb95ee88efaf91
|
||||
- linuxkit/runc:efcece75889aec4e2de0d95ba27ccc46438522b3
|
||||
- linuxkit/containerd:ce79d5d4ab9c46f4763735c6e4ab5c51c3feb5d8
|
||||
- linuxkit/ca-certificates:d4cc1b82c73d272e94d0e71ea375fe56b0c0626a
|
||||
- linuxkit/getty:bae9e3d4861173bacf78f14a4fe44997a430d13b
|
||||
- linuxkit/init:8eea386739975a43af558eec757a7dcb3a3d2e7b
|
||||
- linuxkit/runc:667e7ea2c426a2460ca21e3da065a57dbb3369c9
|
||||
- linuxkit/containerd:a988a1a8bcbacc2c0390ca0c08f949e2b4b5915d
|
||||
- linuxkit/ca-certificates:7b32a26ca9c275d3ef32b11fe2a83dbd2aee2fdb
|
||||
- linuxkit/getty:05eca453695984a69617f1f1f0bcdae7f7032967
|
||||
- nemunaire/mdadm:04814350d71ba9417e1f861be1685de26adf7a67
|
||||
- nemunaire/kexec:839b4eedfce02a56c581dec2383dc6faff120855
|
||||
|
||||
onboot:
|
||||
- name: mod
|
||||
image: linuxkit/modprobe:e3de97ac10970edee33faa78d9780117174bd1ac
|
||||
image: linuxkit/modprobe:773ee174006ecbb412830e48889795bae40b62f9
|
||||
command: ["/bin/sh", "-c", "modprobe xhci_pci ahci intel_lpss_pci i2c_i801 megaraid_sas tg3 bnxt_en"]
|
||||
|
||||
- name: sysctl
|
||||
image: linuxkit/sysctl:c5f4b4895844b993dce4e8b35fd8263a6b557807
|
||||
image: linuxkit/sysctl:5f56434b81004b50b47ed629b222619168c2bcdf
|
||||
binds:
|
||||
- /etc/sysctl.d/01-fic.conf:/etc/sysctl.d/01-fic.conf:ro
|
||||
|
||||
# Metadata
|
||||
- name: metadata
|
||||
image: linuxkit/metadata:f35b5aafc7d19bb6a44a900840727902dad78e44
|
||||
image: linuxkit/metadata:4f81c0c3a2b245567fd7d32d799018c9614a9907
|
||||
command: ["/usr/bin/metadata", "-v", "cdrom"]
|
||||
|
||||
# Filesystem
|
||||
- name: swap
|
||||
image: linuxkit/swap:8a1fd15d56b6ddf67d6d8ce25361178e1f36128b
|
||||
image: linuxkit/swap:f4b8ffef87c8c72165bd8a92b790ac252ccf1821
|
||||
command: ["/sbin/swapon", "/dev/sda3"]
|
||||
- name: dm-crypt
|
||||
image: linuxkit/dm-crypt:19fa6affe9da03afc91694e36d72a4924c65a0e0
|
||||
image: linuxkit/dm-crypt:981fde241bb84616a5ba94c04cdefa1489431a25
|
||||
command: ["/usr/bin/crypto", "-l", "crypt_fic", "/dev/sda4"]
|
||||
binds:
|
||||
- /dev:/dev
|
||||
- /run/config/dm-crypt:/etc/dm-crypt
|
||||
- name: mount
|
||||
image: linuxkit/mount:4413ebd50bfbe026058e4a60463259cece2b8bb5
|
||||
image: linuxkit/mount:cb8caa72248f7082fc2074ce843d53cdc15df04a
|
||||
command: ["/usr/bin/mountie", "-device", "/dev/mapper/crypt_fic", "/var/lib/fic" ]
|
||||
|
||||
# Network
|
||||
# - name: dhcpcd
|
||||
# image: linuxkit/dhcpcd:330839488cd122db3c44738e265c035c9729a963
|
||||
# image: linuxkit/dhcpcd:157df9ef45a035f1542ec2270e374f18efef98a5
|
||||
# command: ["/sbin/dhcpcd", "--nobackground", "-f", "/dhcpcd.conf", "-1"]
|
||||
# - name: ntp
|
||||
# image: linuxkit/openntpd:da26954c2f98a274091e5ed0bbdd2079a77a47c1
|
||||
# image: linuxkit/openntpd:f99c4117763480815553b72022b426639a13ce86
|
||||
- name: synchro-ip-setup
|
||||
image: linuxkit/ip:af77c3f93143ff352a07ad5233d25a665012bcce
|
||||
image: linuxkit/ip:9696394a7d57b384ae919662ae162c9152029156
|
||||
command: ["/bin/sh", "-c", "ip a add 10.10.10.1/29 dev eth2; ip link set eth2 up;" ]
|
||||
net: new
|
||||
runtime:
|
||||
|
@ -57,7 +57,7 @@ onboot:
|
|||
bindNS:
|
||||
net: /run/netns/synchro
|
||||
- name: qa-ip-setup
|
||||
image: linuxkit/ip:af77c3f93143ff352a07ad5233d25a665012bcce
|
||||
image: linuxkit/ip:9696394a7d57b384ae919662ae162c9152029156
|
||||
command: ["/bin/sh", "-c", "ip link show eth1 2> /dev/null && { ip a add 10.10.10.1/29 dev eth1; ip link set eth1 up; }; ip a add 172.17.0.6/24 dev vethin-qa; ip link set vethin-qa up" ]
|
||||
net: new
|
||||
runtime:
|
||||
|
@ -69,7 +69,7 @@ onboot:
|
|||
bindNS:
|
||||
net: /run/netns/fic-qa
|
||||
- name: admin-ip-setup
|
||||
image: linuxkit/ip:af77c3f93143ff352a07ad5233d25a665012bcce
|
||||
image: linuxkit/ip:9696394a7d57b384ae919662ae162c9152029156
|
||||
#command: ["/bin/sh", "-c", "ip link add link eth3 name adminiface type vlan id 99; ip a add 172.16.99.219/24 dev adminiface; ip link set eth3 up; ip link set adminiface up; ip r add default via 172.16.99.1; ip a add 172.17.0.2/24 dev vethin-admin; ip link set vethin-admin up; ping -W 10 -c 1 172.16.99.1;" ]
|
||||
command: ["/bin/sh", "-c", "ip link set eth3 up; while read IP; do ip a add ${IP} dev eth3; done < /run/config/ip_config/backend-admin; ip r add default via $(cat /run/config/ip_config/backend-router); ip a add 172.17.0.2/24 dev vethin-admin; ip link set vethin-admin up; echo 'Waiting for' $(cat /run/config/ip_config/backend-router); ping -W 10 -c 1 $(cat /run/config/ip_config/backend-router); ip link show eth1 2> /dev/null && { ip a add 10.0.0.1/24 dev eth1; ip link set eth1 up; };" ]
|
||||
net: new
|
||||
|
@ -85,7 +85,7 @@ onboot:
|
|||
bindNS:
|
||||
net: /run/netns/fic-admin
|
||||
- name: checker-ip-setup
|
||||
image: linuxkit/ip:af77c3f93143ff352a07ad5233d25a665012bcce
|
||||
image: linuxkit/ip:9696394a7d57b384ae919662ae162c9152029156
|
||||
command: ["/bin/sh", "-c", "ip a add 172.17.0.3/24 dev vethin-checker; ip link set vethin-checker up;" ]
|
||||
net: new
|
||||
runtime:
|
||||
|
@ -96,7 +96,7 @@ onboot:
|
|||
bindNS:
|
||||
net: /run/netns/fic-checker
|
||||
- name: generator-ip-setup
|
||||
image: linuxkit/ip:af77c3f93143ff352a07ad5233d25a665012bcce
|
||||
image: linuxkit/ip:9696394a7d57b384ae919662ae162c9152029156
|
||||
command: ["/bin/sh", "-c", "ip a add 172.17.0.5/24 dev vethin-generat; ip link set vethin-generat up;" ]
|
||||
net: new
|
||||
runtime:
|
||||
|
@ -107,7 +107,7 @@ onboot:
|
|||
bindNS:
|
||||
net: /run/netns/fic-generator
|
||||
- name: mysql-ip-setup
|
||||
image: linuxkit/ip:af77c3f93143ff352a07ad5233d25a665012bcce
|
||||
image: linuxkit/ip:9696394a7d57b384ae919662ae162c9152029156
|
||||
command: ["/bin/sh", "-c", "ip a add 172.17.0.4/24 dev vethin-db; ip link set vethin-db up;" ]
|
||||
net: new
|
||||
runtime:
|
||||
|
@ -118,7 +118,7 @@ onboot:
|
|||
bindNS:
|
||||
net: /run/netns/db
|
||||
- name: bridge-setup
|
||||
image: linuxkit/ip:af77c3f93143ff352a07ad5233d25a665012bcce
|
||||
image: linuxkit/ip:9696394a7d57b384ae919662ae162c9152029156
|
||||
command: ["/bin/sh", "-c", "ip a add 172.17.0.1/24 dev br0; ip link set veth-admin master br0; ip link set veth-checker master br0; ip link set veth-generator master br0; ip link set veth-db master br0; ip link set veth-qa master br0; ip link set br0 up; ip link set veth-admin up; ip link set veth-checker up; ip link set veth-generator up; ip link set veth-db up; ip link set veth-qa up;" ]
|
||||
runtime:
|
||||
interfaces:
|
||||
|
@ -126,7 +126,7 @@ onboot:
|
|||
add: bridge
|
||||
|
||||
- name: firewall-synchro
|
||||
image: linuxkit/ip:af77c3f93143ff352a07ad5233d25a665012bcce
|
||||
image: linuxkit/ip:9696394a7d57b384ae919662ae162c9152029156
|
||||
command: ["/bin/bash", "-c", "/sbin/iptables-restore < /etc/iptables/rules-synchro.v4; /sbin/ip6tables-restore < /etc/iptables/rules.v6" ]
|
||||
binds:
|
||||
- /etc/iptables/rules-synchro.v4:/etc/iptables/rules-synchro.v4:ro
|
||||
|
@ -136,7 +136,7 @@ onboot:
|
|||
mkdir:
|
||||
- /var/lib/fic/teams
|
||||
- name: firewall-admin
|
||||
image: linuxkit/ip:af77c3f93143ff352a07ad5233d25a665012bcce
|
||||
image: linuxkit/ip:9696394a7d57b384ae919662ae162c9152029156
|
||||
command: ["/bin/bash", "-c", "/sbin/iptables-restore < /etc/iptables/rules-admin.v4; /sbin/ip6tables-restore < /etc/iptables/rules.v6" ]
|
||||
binds:
|
||||
- /etc/iptables/rules-admin.v4:/etc/iptables/rules-admin.v4:ro
|
||||
|
@ -153,17 +153,26 @@ onboot:
|
|||
mkdir:
|
||||
- /var/lib/fic/secrets
|
||||
|
||||
- name: create-ssh-keys
|
||||
image: nemunaire/rsync:a3d76b2dd0a9ad73be44dc77ad765b20d96a3285
|
||||
command: ["/bin/sh", "-c", "touch /etc/ssh/sshd_config && ssh-keygen -A"]
|
||||
binds:
|
||||
- /var/lib/fic/ssh:/etc/ssh
|
||||
runtime:
|
||||
mkdir:
|
||||
- /var/lib/fic/ssh
|
||||
|
||||
services:
|
||||
# - name: getty
|
||||
# image: linuxkit/getty:bae9e3d4861173bacf78f14a4fe44997a430d13b
|
||||
# image: linuxkit/getty:05eca453695984a69617f1f1f0bcdae7f7032967
|
||||
# env:
|
||||
# - INSECURE=true
|
||||
|
||||
# Enable acpi to shutdown on power events
|
||||
- name: acpid
|
||||
image: linuxkit/acpid:6379700e2f3341250432e37a4cac36e35c7caac8
|
||||
image: linuxkit/acpid:6cb5575e487a8fcbd4c3eb6721c23299e6ea452f
|
||||
- name: rngd
|
||||
image: linuxkit/rngd:814d1a3a76e84eae01a94575c038fd22652f94e3
|
||||
image: linuxkit/rngd:1a18f2149e42a0a1cb9e7d37608a494342c26032
|
||||
- name: db
|
||||
image: mariadb:11
|
||||
command: ["/bin/bash", "/usr/local/bin/docker-entrypoint.sh", "mariadbd"]
|
||||
|
@ -228,7 +237,7 @@ services:
|
|||
- /var/lib/fic/generator:/srv/GENERATOR:ro
|
||||
- /var/lib/fic/pki:/srv/PKI
|
||||
- /var/lib/fic/settings:/srv/SETTINGS
|
||||
- /var/lib/fic/submissions:/srv/submissions:ro
|
||||
- /var/lib/fic/submissions:/srv/submissions
|
||||
- /var/lib/fic/sync:/srv/SYNC
|
||||
- /var/lib/fic/teams:/srv/TEAMS
|
||||
net: /run/netns/fic-admin
|
||||
|
@ -269,7 +278,10 @@ services:
|
|||
binds:
|
||||
- /etc/hosts:/etc/hosts:ro
|
||||
- /var/lib/fic/generator:/srv/GENERATOR:ro
|
||||
# Uncomment this to disallow registrations
|
||||
- /var/lib/fic/teams:/srv/TEAMS:ro
|
||||
# Uncomment this to allow registrations
|
||||
#- /var/lib/fic/teams:/srv/TEAMS
|
||||
- /var/lib/fic/secrets/mysql_password:/run/secrets/mysql_password:ro
|
||||
- /var/lib/fic/settingsdist:/srv/SETTINGSDIST:ro
|
||||
- /var/lib/fic/submissions:/srv/submissions
|
||||
|
@ -361,7 +373,6 @@ services:
|
|||
- /var/lib/fic/files
|
||||
- /var/lib/fic/pki/shared
|
||||
- /var/lib/fic/settingsdist
|
||||
- /var/lib/fic/ssh
|
||||
- /var/lib/fic/submissions
|
||||
- /var/lib/fic/teams
|
||||
- /var/log/frontend
|
||||
|
|
|
@ -1,6 +1,6 @@
|
|||
kernel:
|
||||
#image: nemunaire/kernel:5.10.62-0b705d955f5e283f62583c4e227d64a7924c138f-amd64
|
||||
image: linuxkit/kernel:6.6.13
|
||||
image: linuxkit/kernel:6.6.71
|
||||
cmdline: "console=ttyS0 console=tty0"
|
||||
|
||||
init:
|
||||
|
|
|
@ -1,50 +1,50 @@
|
|||
kernel:
|
||||
#image: nemunaire/kernel:5.10.62-0b705d955f5e283f62583c4e227d64a7924c138f-amd64
|
||||
image: linuxkit/kernel:6.6.13
|
||||
image: linuxkit/kernel:6.6.71
|
||||
cmdline: "console=ttyS0 console=tty0"
|
||||
|
||||
init:
|
||||
- linuxkit/init:7135424f6836ee166d1199e88cfb95ee88efaf91
|
||||
- linuxkit/runc:efcece75889aec4e2de0d95ba27ccc46438522b3
|
||||
- linuxkit/containerd:ce79d5d4ab9c46f4763735c6e4ab5c51c3feb5d8
|
||||
- linuxkit/ca-certificates:d4cc1b82c73d272e94d0e71ea375fe56b0c0626a
|
||||
- linuxkit/getty:bae9e3d4861173bacf78f14a4fe44997a430d13b
|
||||
- linuxkit/init:8eea386739975a43af558eec757a7dcb3a3d2e7b
|
||||
- linuxkit/runc:667e7ea2c426a2460ca21e3da065a57dbb3369c9
|
||||
- linuxkit/containerd:a988a1a8bcbacc2c0390ca0c08f949e2b4b5915d
|
||||
- linuxkit/ca-certificates:7b32a26ca9c275d3ef32b11fe2a83dbd2aee2fdb
|
||||
- linuxkit/getty:05eca453695984a69617f1f1f0bcdae7f7032967
|
||||
- nemunaire/mdadm:04814350d71ba9417e1f861be1685de26adf7a67
|
||||
- nemunaire/kexec:839b4eedfce02a56c581dec2383dc6faff120855
|
||||
- nemunaire/fic-frontend-ui:latest
|
||||
|
||||
onboot:
|
||||
- name: mod
|
||||
image: linuxkit/modprobe:e3de97ac10970edee33faa78d9780117174bd1ac
|
||||
image: linuxkit/modprobe:773ee174006ecbb412830e48889795bae40b62f9
|
||||
command: ["/bin/sh", "-c", "modprobe xhci_pci ahci intel_lpss_pci i2c_i801 megaraid_sas tg3 bnxt_en"]
|
||||
|
||||
- name: sysctl
|
||||
image: linuxkit/sysctl:c5f4b4895844b993dce4e8b35fd8263a6b557807
|
||||
image: linuxkit/sysctl:5f56434b81004b50b47ed629b222619168c2bcdf
|
||||
|
||||
# Metadata
|
||||
- name: metadata
|
||||
image: linuxkit/metadata:f35b5aafc7d19bb6a44a900840727902dad78e44
|
||||
image: linuxkit/metadata:4f81c0c3a2b245567fd7d32d799018c9614a9907
|
||||
command: ["/usr/bin/metadata", "-v", "cdrom"]
|
||||
|
||||
# Filesystem
|
||||
- name: swap
|
||||
image: linuxkit/swap:8a1fd15d56b6ddf67d6d8ce25361178e1f36128b
|
||||
image: linuxkit/swap:f4b8ffef87c8c72165bd8a92b790ac252ccf1821
|
||||
command: ["/sbin/swapon", "/dev/sda3"]
|
||||
- name: dm-crypt
|
||||
image: linuxkit/dm-crypt:19fa6affe9da03afc91694e36d72a4924c65a0e0
|
||||
image: linuxkit/dm-crypt:981fde241bb84616a5ba94c04cdefa1489431a25
|
||||
command: ["/usr/bin/crypto", "-l", "crypt_fic", "/dev/sda4"]
|
||||
binds:
|
||||
- /dev:/dev
|
||||
- /run/config/dm-crypt:/etc/dm-crypt
|
||||
- name: mount
|
||||
image: linuxkit/mount:4413ebd50bfbe026058e4a60463259cece2b8bb5
|
||||
image: linuxkit/mount:cb8caa72248f7082fc2074ce843d53cdc15df04a
|
||||
command: ["/usr/bin/mountie", "-device", "/dev/mapper/crypt_fic", "/var/lib/fic" ]
|
||||
|
||||
# Network
|
||||
# - name: ntp
|
||||
# image: linuxkit/openntpd:da26954c2f98a274091e5ed0bbdd2079a77a47c1
|
||||
# image: linuxkit/openntpd:f99c4117763480815553b72022b426639a13ce86
|
||||
- name: nginx-ip-setup
|
||||
image: linuxkit/ip:af77c3f93143ff352a07ad5233d25a665012bcce
|
||||
image: linuxkit/ip:9696394a7d57b384ae919662ae162c9152029156
|
||||
command: ["/bin/sh", "-c", "ip a add 172.17.1.2/24 dev vethin-nginx; ip link set vethin-nginx up;" ]
|
||||
net: new
|
||||
runtime:
|
||||
|
@ -55,7 +55,7 @@ onboot:
|
|||
bindNS:
|
||||
net: /run/netns/nginx
|
||||
- name: frontal-ip-setup # without bonding
|
||||
image: linuxkit/ip:af77c3f93143ff352a07ad5233d25a665012bcce
|
||||
image: linuxkit/ip:9696394a7d57b384ae919662ae162c9152029156
|
||||
command: ["/bin/sh", "-c", "ip link set name bond-frontal eth3; ip link set bond-frontal up; while read IP; do ip a add ${IP} dev bond-frontal; done < /run/config/ip_config/frontend-players; ip r add default via $(cat /run/config/ip_config/frontend-router); ip link add link bond-frontal name internet type vlan id 4; ip a add 10.10.10.2/29 dev internet; ip link set internet up;" ]
|
||||
net: /run/netns/nginx
|
||||
binds:
|
||||
|
@ -67,7 +67,7 @@ onboot:
|
|||
- name: eth3
|
||||
# - name: eth4
|
||||
# - name: frontal-ip-setup # with bonding
|
||||
# image: linuxkit/ip:af77c3f93143ff352a07ad5233d25a665012bcce
|
||||
# image: linuxkit/ip:9696394a7d57b384ae919662ae162c9152029156
|
||||
# command: ["/bin/sh", "-c", "ip link set dev bond-frontal type bond mode balance-alb; ip link set bond-frontal up; ifenslave bond-frontal eth1 eth2 eth3 eth4; while read IP; do ip a add ${IP} dev bond-frontal; done < /run/config/ip_config/frontend-players; ip r add default via $(cat /run/config/ip_config/frontend-router); ip link add link bond-frontal name internet type vlan id 4; ip link set internet up; sysctl -w net.ipv4.ip_forward=1;" ]
|
||||
# net: /run/netns/nginx
|
||||
# binds:
|
||||
|
@ -81,7 +81,7 @@ onboot:
|
|||
# - name: bond-frontal
|
||||
# add: bond
|
||||
- name: receiver-ip-setup
|
||||
image: linuxkit/ip:af77c3f93143ff352a07ad5233d25a665012bcce
|
||||
image: linuxkit/ip:9696394a7d57b384ae919662ae162c9152029156
|
||||
command: ["/bin/sh", "-c", "ip a add 172.17.1.3/24 dev vethin-receiver; ip link set vethin-receiver up;" ]
|
||||
net: new
|
||||
runtime:
|
||||
|
@ -92,7 +92,7 @@ onboot:
|
|||
bindNS:
|
||||
net: /run/netns/fic-receiver
|
||||
- name: sshd-ip-setup
|
||||
image: linuxkit/ip:af77c3f93143ff352a07ad5233d25a665012bcce
|
||||
image: linuxkit/ip:9696394a7d57b384ae919662ae162c9152029156
|
||||
command: ["/bin/sh", "-c", "ip a add 10.10.10.2/29 dev eth2; ip link set eth2 up;" ]
|
||||
net: new
|
||||
runtime:
|
||||
|
@ -101,7 +101,7 @@ onboot:
|
|||
bindNS:
|
||||
net: /run/netns/sshd
|
||||
- name: auth-ip-setup
|
||||
image: linuxkit/ip:af77c3f93143ff352a07ad5233d25a665012bcce
|
||||
image: linuxkit/ip:9696394a7d57b384ae919662ae162c9152029156
|
||||
command: ["/bin/sh", "-c", "ip a add 172.17.1.4/24 dev vethin-auth; ip link set vethin-auth up;" ]
|
||||
net: new
|
||||
runtime:
|
||||
|
@ -112,7 +112,7 @@ onboot:
|
|||
bindNS:
|
||||
net: /run/netns/auth
|
||||
- name: bridge-setup
|
||||
image: linuxkit/ip:af77c3f93143ff352a07ad5233d25a665012bcce
|
||||
image: linuxkit/ip:9696394a7d57b384ae919662ae162c9152029156
|
||||
command: ["/bin/sh", "-c", "ip a add 172.17.1.1/24 dev br0; ip link set veth-nginx master br0; ip link set veth-receiver master br0; ip link set veth-auth master br0; ip link set br0 up; ip link set veth-nginx up; ip link set veth-receiver up; ip link set veth-auth up;" ]
|
||||
runtime:
|
||||
interfaces:
|
||||
|
@ -120,7 +120,7 @@ onboot:
|
|||
add: bridge
|
||||
|
||||
- name: firewall-frontal
|
||||
image: linuxkit/ip:af77c3f93143ff352a07ad5233d25a665012bcce
|
||||
image: linuxkit/ip:9696394a7d57b384ae919662ae162c9152029156
|
||||
command: ["/bin/bash", "-c", "/sbin/iptables-restore < /etc/iptables/rules-frontal.v4; /sbin/ip6tables-restore < /etc/iptables/rules.v6; [ -f /run/config/remote_sync/destination ] && /sbin/iptables -I OUTPUT 7 -o bond-frontal -d $(cat /run/config/remote_sync/destination | tr -d '\n') -p tcp -m tcp --dport https -j ACCEPT;" ]
|
||||
binds:
|
||||
- /etc/iptables/rules-frontal.v4:/etc/iptables/rules-frontal.v4:ro
|
||||
|
@ -129,26 +129,35 @@ onboot:
|
|||
- /run/config/remote_sync/:/run/config/remote_sync/:ro
|
||||
net: /run/netns/nginx
|
||||
- name: firewall-sshd
|
||||
image: linuxkit/ip:af77c3f93143ff352a07ad5233d25a665012bcce
|
||||
image: linuxkit/ip:9696394a7d57b384ae919662ae162c9152029156
|
||||
command: ["/bin/bash", "-c", "/sbin/iptables-restore < /etc/iptables/rules-sshd.v4; /sbin/ip6tables-restore < /etc/iptables/rules.v6" ]
|
||||
binds:
|
||||
- /etc/iptables/rules-sshd.v4:/etc/iptables/rules-sshd.v4:ro
|
||||
- /etc/iptables/rules.v6:/etc/iptables/rules.v6:ro
|
||||
net: /run/netns/sshd
|
||||
|
||||
- name: create-ssh-keys
|
||||
image: nemunaire/rsync:a3d76b2dd0a9ad73be44dc77ad765b20d96a3285
|
||||
command: ["/bin/sh", "-c", "touch /etc/ssh/sshd_config && ssh-keygen -A"]
|
||||
binds:
|
||||
- /var/lib/fic/ssh:/etc/ssh
|
||||
runtime:
|
||||
mkdir:
|
||||
- /var/lib/fic/ssh
|
||||
|
||||
services:
|
||||
# - name: getty
|
||||
# image: linuxkit/getty:bae9e3d4861173bacf78f14a4fe44997a430d13b
|
||||
# image: linuxkit/getty:05eca453695984a69617f1f1f0bcdae7f7032967
|
||||
# env:
|
||||
# - INSECURE=true
|
||||
|
||||
# Enable acpi to shutdown on power events
|
||||
- name: acpid
|
||||
image: linuxkit/acpid:6379700e2f3341250432e37a4cac36e35c7caac8
|
||||
image: linuxkit/acpid:6cb5575e487a8fcbd4c3eb6721c23299e6ea452f
|
||||
- name: rngd
|
||||
image: linuxkit/rngd:814d1a3a76e84eae01a94575c038fd22652f94e3
|
||||
image: linuxkit/rngd:1a18f2149e42a0a1cb9e7d37608a494342c26032
|
||||
- name: dhcpcd
|
||||
image: linuxkit/dhcpcd:330839488cd122db3c44738e265c035c9729a963
|
||||
image: linuxkit/dhcpcd:157df9ef45a035f1542ec2270e374f18efef98a5
|
||||
net: /run/netns/nginx
|
||||
binds:
|
||||
- /etc/dhcpcd.conf:/dhcpcd.conf:ro
|
||||
|
@ -257,7 +266,6 @@ services:
|
|||
- /var/lib/fic/files
|
||||
- /var/lib/fic/pki
|
||||
- /var/lib/fic/settingsdist
|
||||
- /var/lib/fic/ssh
|
||||
- /var/lib/fic/submissions
|
||||
- /var/lib/fic/teams
|
||||
|
||||
|
@ -280,7 +288,7 @@ services:
|
|||
# net: /run/netns/nginx
|
||||
|
||||
- name: dexidp
|
||||
image: ghcr.io/dexidp/dex:v2.41.1
|
||||
image: ghcr.io/dexidp/dex:v2.42.0
|
||||
net: /run/netns/auth
|
||||
binds:
|
||||
- /etc/hosts:/etc/hosts:ro
|
||||
|
@ -294,7 +302,7 @@ services:
|
|||
mkdir:
|
||||
- /var/lib/fic/dex
|
||||
- name: vouch-proxy
|
||||
image: quay.io/vouch/vouch-proxy:alpine-0.39
|
||||
image: quay.io/vouch/vouch-proxy:alpine-0.41
|
||||
env:
|
||||
- VOUCH_CONFIG=/etc/vouch/config.yml
|
||||
net: /run/netns/auth
|
||||
|
|
|
@ -1,15 +1,15 @@
|
|||
kernel:
|
||||
#image: nemunaire/kernel:5.10.62-0b705d955f5e283f62583c4e227d64a7924c138f-amd64
|
||||
image: linuxkit/kernel:6.6.13
|
||||
image: linuxkit/kernel:6.6.71
|
||||
cmdline: "console=ttyS0 console=tty0"
|
||||
|
||||
|
||||
init:
|
||||
- nemunaire/mdadm:04814350d71ba9417e1f861be1685de26adf7a67
|
||||
- nemunaire/syslinux:086f221f281d577d300949aa1094fb20c5cd90dc
|
||||
- linuxkit/format:3c858f0cf42a2b14441bfb5c266b78f14d2b75a4
|
||||
- linuxkit/dm-crypt:19fa6affe9da03afc91694e36d72a4924c65a0e0
|
||||
- linuxkit/metadata:f35b5aafc7d19bb6a44a900840727902dad78e44
|
||||
- linuxkit/format:3fb088f60ed73ba4a15be41e44654b74112fd3f9
|
||||
- linuxkit/dm-crypt:981fde241bb84616a5ba94c04cdefa1489431a25
|
||||
- linuxkit/metadata:4f81c0c3a2b245567fd7d32d799018c9614a9907
|
||||
- alpine:latest
|
||||
|
||||
files:
|
||||
|
|
|
@ -1,12 +1,12 @@
|
|||
kernel:
|
||||
#image: nemunaire/kernel:5.10.62-0b705d955f5e283f62583c4e227d64a7924c138f-amd64
|
||||
image: linuxkit/kernel:6.6.13
|
||||
image: linuxkit/kernel:6.6.71
|
||||
cmdline: "console=ttyS0 console=tty0"
|
||||
|
||||
|
||||
init:
|
||||
- nemunaire/mdadm:04814350d71ba9417e1f861be1685de26adf7a67
|
||||
- linuxkit/metadata:f35b5aafc7d19bb6a44a900840727902dad78e44
|
||||
- linuxkit/metadata:4f81c0c3a2b245567fd7d32d799018c9614a9907
|
||||
- alpine:latest
|
||||
|
||||
|
||||
|
|
602
frontend/fic/package-lock.json
generated
602
frontend/fic/package-lock.json
generated
File diff suppressed because it is too large
Load diff
|
@ -12,10 +12,10 @@
|
|||
"@sveltejs/adapter-static": "^3.0.0",
|
||||
"@sveltejs/kit": "^2.0.0",
|
||||
"@sveltejs/vite-plugin-svelte": "^3.0.0",
|
||||
"@sveltestrap/sveltestrap": "^6.2.1",
|
||||
"@sveltestrap/sveltestrap": "^7.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",
|
||||
"sass": "^1.51.0",
|
||||
|
|
|
@ -33,9 +33,9 @@
|
|||
</h1>
|
||||
<div style="min-width: 0">
|
||||
<h4 class="fw-bold"><samp>{file.name}</samp></h4>
|
||||
{#if file.disclamer}
|
||||
<div class="file-disclamer text-warning">
|
||||
{file.disclamer}
|
||||
{#if file.disclaimer}
|
||||
<div class="file-disclaimer text-warning">
|
||||
{file.disclaimer}
|
||||
</div>
|
||||
{/if}
|
||||
<nobr>
|
||||
|
@ -61,10 +61,10 @@
|
|||
{/if}
|
||||
|
||||
<style>
|
||||
.file-disclamer {
|
||||
.file-disclaimer {
|
||||
display: none;
|
||||
}
|
||||
:global(.list-group-item:hover .file-disclamer) {
|
||||
:global(.list-group-item:hover .file-disclaimer) {
|
||||
display: block;
|
||||
}
|
||||
</style>
|
||||
|
|
42
go.mod
42
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
|
||||
|
|
57
go.sum
57
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=
|
||||
|
|
26
libfic/cyberrange.go
Normal file
26
libfic/cyberrange.go
Normal file
|
@ -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"`
|
||||
}
|
21
libfic/db.go
21
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
|
||||
}
|
||||
|
|
|
@ -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,7 +608,12 @@ 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 {
|
||||
} else if ok {
|
||||
if len(res) > 0 {
|
||||
e.NewTryFlag(tryId, flag)
|
||||
}
|
||||
|
||||
if flag.Check([]byte(res)) != 0 {
|
||||
if !PartialValidation || t.HasPartiallySolved(flag) == nil {
|
||||
valid = valid && flag.IsOptionnal()
|
||||
}
|
||||
|
@ -601,6 +625,7 @@ func (e *Exercice) CheckResponse(cksum []byte, respflags map[int]string, respmcq
|
|||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if diff > 0 || goodResponses > 0 {
|
||||
e.UpdateTry(t, diff, goodResponses > 0)
|
||||
|
|
|
@ -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 {
|
||||
|
|
|
@ -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.
|
||||
|
|
|
@ -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.
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -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 {
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -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,
|
||||
}
|
||||
}
|
||||
|
|
480
qa/ui/package-lock.json
generated
480
qa/ui/package-lock.json
generated
|
@ -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,
|
||||
"license": "MIT",
|
||||
"engines": {
|
||||
"node": ">=12.0"
|
||||
},
|
||||
"funding": {
|
||||
"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": ">=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": {
|
||||
|
|
|
@ -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"
|
||||
}
|
||||
}
|
||||
|
|
|
@ -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
|
||||
}
|
||||
|
|
|
@ -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 <TEAM_ID> <VALUE> <MESSAGE>")
|
||||
|
@ -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)
|
||||
|
|
|
@ -1,12 +1,18 @@
|
|||
package main
|
||||
|
||||
import ()
|
||||
import (
|
||||
"time"
|
||||
)
|
||||
|
||||
type Session struct {
|
||||
Name string `json:"name"`
|
||||
QuestionValidation string `json:"question_validation"`
|
||||
Status string `json:"status"`
|
||||
ID int64 `json:"id"`
|
||||
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) {
|
||||
|
|
|
@ -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] }
|
||||
|
|
|
@ -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
|
||||
}
|
||||
]
|
|
@ -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{}
|
||||
|
||||
|
|
|
@ -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 {
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue