Compare commits

..

1 commit

Author SHA1 Message Date
0d348e2398 chore(deps): update dependency svelte to v5
Some checks failed
continuous-integration/drone/push Build is failing
2025-01-18 10:47:54 +00:00
58 changed files with 1000 additions and 1612 deletions

View file

@ -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.21
FROM alpine:3.20
RUN apk add --no-cache \
ca-certificates \

View file

@ -13,7 +13,7 @@ RUN go get -d -v ./checker && \
go build -v -buildvcs=false -o checker/checker ./checker
FROM alpine:3.21
FROM alpine:3.20
WORKDIR /srv

View file

@ -13,7 +13,7 @@ RUN go get -d -v ./dashboard && \
go build -v -buildvcs=false -o dashboard/dashboard ./dashboard
FROM alpine:3.21
FROM alpine:3.20
EXPOSE 8082

View file

@ -1,4 +1,4 @@
FROM alpine:3.21
FROM alpine:3.20
EXPOSE 67/udp
EXPOSE 69/udp

View file

@ -12,7 +12,7 @@ RUN go get -d -v ./evdist && \
go build -v -buildvcs=false -o evdist/evdist ./evdist
FROM alpine:3.21
FROM alpine:3.20
WORKDIR /srv

View file

@ -13,7 +13,7 @@ RUN go get -d -v ./generator && \
go build -v -buildvcs=false -o generator/generator ./generator
FROM alpine:3.21
FROM alpine:3.20
WORKDIR /srv

View file

@ -15,7 +15,7 @@ RUN go get -d -v ./admin && \
go build -v -o get-remote-files ./admin/get-remote-files
FROM alpine:3.21
FROM alpine:3.20
RUN apk add --no-cache \
ca-certificates

View file

@ -25,7 +25,7 @@ RUN go get -d -v ./qa && \
go build -v -buildvcs=false -o qa/qa ./qa
FROM alpine:3.21
FROM alpine:3.20
EXPOSE 8083

View file

@ -13,7 +13,7 @@ RUN go get -d -v ./receiver && \
go build -v -buildvcs=false -o ./receiver/receiver ./receiver
FROM alpine:3.21
FROM alpine:3.20
EXPOSE 8080

View file

@ -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.21
FROM alpine:3.20
RUN apk add --no-cache openssl ca-certificates

View file

@ -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.21
FROM alpine:3.20
RUN apk add --no-cache openssl ca-certificates

View file

@ -62,8 +62,6 @@ 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)
@ -79,8 +77,6 @@ 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)
@ -856,60 +852,6 @@ 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)
@ -953,23 +895,6 @@ 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))
@ -981,6 +906,14 @@ 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())
@ -1089,60 +1022,6 @@ 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)

View file

@ -3,12 +3,9 @@ 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"
@ -62,41 +59,6 @@ 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 {

View file

@ -34,11 +34,6 @@ 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 {
@ -141,7 +136,7 @@ storage:
web:
http: 0.0.0.0:5556
frontend:
issuer: {{ .Name }}
issuer: Challenge forensic
logoURL: {{ .LogoPath }}
dir: /srv/dex/web/
oauth2:

View file

@ -1,9 +1,9 @@
package api
import (
"encoding/json"
"fmt"
"log"
"math/rand"
"net/http"
"strconv"
"strings"
@ -186,9 +186,6 @@ 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) {
@ -295,11 +292,6 @@ 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 {
@ -308,7 +300,7 @@ func allAssociations(c *gin.Context) {
return
}
var ret []teamAssociation
var ret []string
for _, team := range teams {
assocs, err := pki.GetTeamAssociations(TeamsDir, team.Id)
@ -318,84 +310,13 @@ func allAssociations(c *gin.Context) {
}
for _, a := range assocs {
ret = append(ret, teamAssociation{a, team.Id})
ret = append(ret, a)
}
}
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)
@ -405,7 +326,11 @@ func createTeam(c *gin.Context) {
}
if ut.Color == 0 {
ut.Color = fic.RandomColor().ToRGB()
ut.Color = fic.HSL{
H: rand.Float64(),
S: 1,
L: 0.5,
}.ToRGB()
}
team, err := fic.CreateTeam(strings.TrimSpace(ut.Name), ut.Color, ut.ExternalId)

View file

@ -4,7 +4,7 @@ const indextpl = `<!DOCTYPE html>
<html ng-app="FICApp">
<head>
<meta charset="utf-8">
<title>{{ .title }} - Administration</title>
<title>Challenge Forensic - 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="{{ .title }}" src="{{ .logo }}" style="height: 30px">
<img alt="FIC" src="img/fic.png" 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">&Eacute;quipes</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('/pki')}"><a class="nav-link" href="pki">PKI</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="pointer-events: none; position: absolute;">
<div style="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>

View file

@ -6,7 +6,6 @@ import (
"errors"
"log"
"net/http"
"os"
"path"
"strings"
"text/template"
@ -26,24 +25,10 @@ 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, tplcfg); err != nil {
} 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 {
log.Fatal("An error occurs during template execution:", err)
} else {
indexPage = b.Bytes()
@ -65,9 +50,6 @@ 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)
})
@ -122,22 +104,8 @@ func declareStaticRoutes(router *gin.RouterGroup, cfg *settings.Settings, baseUR
})
router.GET("/files/*_", func(c *gin.Context) {
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)
// 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"))))
})
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"))))

View file

@ -25,10 +25,6 @@ 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"
@ -352,9 +348,6 @@ 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' }
@ -362,9 +355,6 @@ 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")
@ -621,18 +611,9 @@ 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)
@ -667,7 +648,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);
});
@ -741,9 +722,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("/");
@ -755,7 +736,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()
@ -778,20 +759,6 @@ 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: '<',
@ -853,10 +820,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, '',
@ -872,7 +839,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 () {
@ -885,7 +852,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 () {
@ -898,7 +865,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 () {
@ -925,49 +892,6 @@ 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);
@ -1052,6 +976,20 @@ 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) {
@ -1172,7 +1110,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 = [
@ -1291,8 +1229,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") {
@ -1300,8 +1238,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 !",
}
}
};
@ -1430,7 +1368,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({
@ -2317,9 +2255,9 @@ angular.module("FICApp")
}
$scope.saveFlag = function () {
if (this.flag.id) {
this.flag.$update().then(function() {}, function(error) { $scope.addToast('danger', 'Impossible de mettre à jour le flag :', error.data.errmsg); });
this.flag.$update();
} else {
this.flag.$save({ exerciceId: $routeParams.exerciceId }).then(function() {}, function(error) { $scope.addToast('danger', 'Impossible de créer le flag :', error.data.errmsg); });
this.flag.$save({ exerciceId: $routeParams.exerciceId });
}
$rootScope.staticFilesNeedUpdate++;
}
@ -2338,7 +2276,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);
@ -2407,18 +2345,6 @@ 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 });
@ -2456,18 +2382,6 @@ 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"];
@ -2494,6 +2408,22 @@ 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();
@ -2501,34 +2431,9 @@ 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"];

View file

@ -81,22 +81,6 @@ 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")

View file

@ -1,86 +0,0 @@
<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">&#11020;</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>

View file

@ -73,28 +73,12 @@
</div>
<div class="col-4">
<div ng-controller="ExerciceFlagDepsController" ng-init="init(flag)">
<strong>Dépendances&nbsp;:</strong>
Dépendances&nbsp;:
<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">
@ -184,22 +168,6 @@
<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>

View file

@ -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}}" target="_self" class="btn btn-sm btn-secondary col-auto"><span class="glyphicon glyphicon-download" aria-hidden="true"></span></a>
<a href="../files{{file.path}}" 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>

View file

@ -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" class="text-truncate" style="max-width: 30vw" title="{{ file[field] }}">
<td ng-repeat="field in fields">
{{ file[field] }}
<span ng-if="field == 'id' && file.err !== undefined && file.err !== true" title="{{ file.err }}" class="glyphicon glyphicon-exclamation-sign"></span>
</td>
<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>
{{ file.checksum | bto16 }}
<div ng-if="file.checksum_shown">{{ file.checksum_shown | bto16 }}</div>
</td>
</tr>
</tbody>

View file

@ -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-change="durationChange()" 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-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-change="durationChange(true)" 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-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="number" class="form-control form-control-sm" id="duration" ng-model="duration" ng-change="durationChange()" integer>
<input type="text" class="form-control form-control-sm" id="duration" ng-model="duration" 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.association" ng-repeat="(i,m) in allAssociations" ng-value="m.association">{{ m.association }}</option>
<option ng-selected="newdqa == m" ng-repeat="(i,m) in allAssociations" ng-value="m">{{ m }}</option>
</select>
</div>
<div class="col input-group">

View file

@ -1,19 +1,11 @@
<div class="d-flex justify-content-between align-items-center">
<h2>
&Eacute;quipes
</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>
<h2>
&Eacute;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>
<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">

View file

@ -279,7 +279,6 @@ func buildKeyFlag(exercice *fic.Exercice, flag ExerciceFlag, flagline int, defau
}
type importFlag struct {
origin ExerciceFlag
Line int
Flag fic.Flag
JustifyOf *fic.MCQ_entry
@ -393,9 +392,8 @@ 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,
Line: nline + 1,
Flag: addedFlag,
})
}
} else if flag.Type == "key" || strings.HasPrefix(flag.Type, "number") || flag.Type == "text" || flag.Type == "ucq" || flag.Type == "radio" || flag.Type == "vector" {
@ -403,7 +401,6 @@ 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,
@ -465,7 +462,6 @@ 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,
@ -483,9 +479,8 @@ func buildExerciceFlag(i Importer, exercice *fic.Exercice, flag ExerciceFlag, nl
}
ret = append([]importFlag{importFlag{
origin: flag,
Line: nline + 1,
Flag: &addedFlag,
Line: nline + 1,
Flag: &addedFlag,
}}, ret...)
}
return
@ -575,10 +570,6 @@ 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

View file

@ -238,21 +238,3 @@ 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
}

View file

@ -20,8 +20,6 @@ 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; }

View file

@ -21,8 +21,6 @@ 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

View file

@ -1,54 +1,54 @@
kernel:
#image: nemunaire/kernel:5.10.62-0b705d955f5e283f62583c4e227d64a7924c138f-amd64
image: linuxkit/kernel:6.6.71
image: linuxkit/kernel:6.6.13
cmdline: "console=ttyS0 console=tty0"
init:
- linuxkit/init:8eea386739975a43af558eec757a7dcb3a3d2e7b
- linuxkit/runc:667e7ea2c426a2460ca21e3da065a57dbb3369c9
- linuxkit/containerd:a988a1a8bcbacc2c0390ca0c08f949e2b4b5915d
- linuxkit/ca-certificates:7b32a26ca9c275d3ef32b11fe2a83dbd2aee2fdb
- linuxkit/getty:05eca453695984a69617f1f1f0bcdae7f7032967
- linuxkit/init:7135424f6836ee166d1199e88cfb95ee88efaf91
- linuxkit/runc:efcece75889aec4e2de0d95ba27ccc46438522b3
- linuxkit/containerd:ce79d5d4ab9c46f4763735c6e4ab5c51c3feb5d8
- linuxkit/ca-certificates:d4cc1b82c73d272e94d0e71ea375fe56b0c0626a
- linuxkit/getty:bae9e3d4861173bacf78f14a4fe44997a430d13b
- nemunaire/mdadm:04814350d71ba9417e1f861be1685de26adf7a67
- nemunaire/kexec:839b4eedfce02a56c581dec2383dc6faff120855
onboot:
- name: mod
image: linuxkit/modprobe:773ee174006ecbb412830e48889795bae40b62f9
image: linuxkit/modprobe:e3de97ac10970edee33faa78d9780117174bd1ac
command: ["/bin/sh", "-c", "modprobe xhci_pci ahci intel_lpss_pci i2c_i801 megaraid_sas tg3 bnxt_en"]
- name: sysctl
image: linuxkit/sysctl:5f56434b81004b50b47ed629b222619168c2bcdf
image: linuxkit/sysctl:c5f4b4895844b993dce4e8b35fd8263a6b557807
binds:
- /etc/sysctl.d/01-fic.conf:/etc/sysctl.d/01-fic.conf:ro
# Metadata
- name: metadata
image: linuxkit/metadata:4f81c0c3a2b245567fd7d32d799018c9614a9907
image: linuxkit/metadata:f35b5aafc7d19bb6a44a900840727902dad78e44
command: ["/usr/bin/metadata", "-v", "cdrom"]
# Filesystem
- name: swap
image: linuxkit/swap:f4b8ffef87c8c72165bd8a92b790ac252ccf1821
image: linuxkit/swap:8a1fd15d56b6ddf67d6d8ce25361178e1f36128b
command: ["/sbin/swapon", "/dev/sda3"]
- name: dm-crypt
image: linuxkit/dm-crypt:981fde241bb84616a5ba94c04cdefa1489431a25
image: linuxkit/dm-crypt:19fa6affe9da03afc91694e36d72a4924c65a0e0
command: ["/usr/bin/crypto", "-l", "crypt_fic", "/dev/sda4"]
binds:
- /dev:/dev
- /run/config/dm-crypt:/etc/dm-crypt
- name: mount
image: linuxkit/mount:cb8caa72248f7082fc2074ce843d53cdc15df04a
image: linuxkit/mount:4413ebd50bfbe026058e4a60463259cece2b8bb5
command: ["/usr/bin/mountie", "-device", "/dev/mapper/crypt_fic", "/var/lib/fic" ]
# Network
# - name: dhcpcd
# image: linuxkit/dhcpcd:157df9ef45a035f1542ec2270e374f18efef98a5
# image: linuxkit/dhcpcd:330839488cd122db3c44738e265c035c9729a963
# command: ["/sbin/dhcpcd", "--nobackground", "-f", "/dhcpcd.conf", "-1"]
# - name: ntp
# image: linuxkit/openntpd:f99c4117763480815553b72022b426639a13ce86
# image: linuxkit/openntpd:da26954c2f98a274091e5ed0bbdd2079a77a47c1
- name: synchro-ip-setup
image: linuxkit/ip:9696394a7d57b384ae919662ae162c9152029156
image: linuxkit/ip:af77c3f93143ff352a07ad5233d25a665012bcce
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:9696394a7d57b384ae919662ae162c9152029156
image: linuxkit/ip:af77c3f93143ff352a07ad5233d25a665012bcce
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:9696394a7d57b384ae919662ae162c9152029156
image: linuxkit/ip:af77c3f93143ff352a07ad5233d25a665012bcce
#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:9696394a7d57b384ae919662ae162c9152029156
image: linuxkit/ip:af77c3f93143ff352a07ad5233d25a665012bcce
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:9696394a7d57b384ae919662ae162c9152029156
image: linuxkit/ip:af77c3f93143ff352a07ad5233d25a665012bcce
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:9696394a7d57b384ae919662ae162c9152029156
image: linuxkit/ip:af77c3f93143ff352a07ad5233d25a665012bcce
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:9696394a7d57b384ae919662ae162c9152029156
image: linuxkit/ip:af77c3f93143ff352a07ad5233d25a665012bcce
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:9696394a7d57b384ae919662ae162c9152029156
image: linuxkit/ip:af77c3f93143ff352a07ad5233d25a665012bcce
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:9696394a7d57b384ae919662ae162c9152029156
image: linuxkit/ip:af77c3f93143ff352a07ad5233d25a665012bcce
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,26 +153,17 @@ 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:05eca453695984a69617f1f1f0bcdae7f7032967
# image: linuxkit/getty:bae9e3d4861173bacf78f14a4fe44997a430d13b
# env:
# - INSECURE=true
# Enable acpi to shutdown on power events
- name: acpid
image: linuxkit/acpid:6cb5575e487a8fcbd4c3eb6721c23299e6ea452f
image: linuxkit/acpid:6379700e2f3341250432e37a4cac36e35c7caac8
- name: rngd
image: linuxkit/rngd:1a18f2149e42a0a1cb9e7d37608a494342c26032
image: linuxkit/rngd:814d1a3a76e84eae01a94575c038fd22652f94e3
- name: db
image: mariadb:11
command: ["/bin/bash", "/usr/local/bin/docker-entrypoint.sh", "mariadbd"]
@ -237,7 +228,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
- /var/lib/fic/submissions:/srv/submissions:ro
- /var/lib/fic/sync:/srv/SYNC
- /var/lib/fic/teams:/srv/TEAMS
net: /run/netns/fic-admin
@ -278,10 +269,7 @@ 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
@ -373,6 +361,7 @@ 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

View file

@ -1,6 +1,6 @@
kernel:
#image: nemunaire/kernel:5.10.62-0b705d955f5e283f62583c4e227d64a7924c138f-amd64
image: linuxkit/kernel:6.6.71
image: linuxkit/kernel:6.6.13
cmdline: "console=ttyS0 console=tty0"
init:

View file

@ -1,50 +1,50 @@
kernel:
#image: nemunaire/kernel:5.10.62-0b705d955f5e283f62583c4e227d64a7924c138f-amd64
image: linuxkit/kernel:6.6.71
image: linuxkit/kernel:6.6.13
cmdline: "console=ttyS0 console=tty0"
init:
- linuxkit/init:8eea386739975a43af558eec757a7dcb3a3d2e7b
- linuxkit/runc:667e7ea2c426a2460ca21e3da065a57dbb3369c9
- linuxkit/containerd:a988a1a8bcbacc2c0390ca0c08f949e2b4b5915d
- linuxkit/ca-certificates:7b32a26ca9c275d3ef32b11fe2a83dbd2aee2fdb
- linuxkit/getty:05eca453695984a69617f1f1f0bcdae7f7032967
- linuxkit/init:7135424f6836ee166d1199e88cfb95ee88efaf91
- linuxkit/runc:efcece75889aec4e2de0d95ba27ccc46438522b3
- linuxkit/containerd:ce79d5d4ab9c46f4763735c6e4ab5c51c3feb5d8
- linuxkit/ca-certificates:d4cc1b82c73d272e94d0e71ea375fe56b0c0626a
- linuxkit/getty:bae9e3d4861173bacf78f14a4fe44997a430d13b
- nemunaire/mdadm:04814350d71ba9417e1f861be1685de26adf7a67
- nemunaire/kexec:839b4eedfce02a56c581dec2383dc6faff120855
- nemunaire/fic-frontend-ui:latest
onboot:
- name: mod
image: linuxkit/modprobe:773ee174006ecbb412830e48889795bae40b62f9
image: linuxkit/modprobe:e3de97ac10970edee33faa78d9780117174bd1ac
command: ["/bin/sh", "-c", "modprobe xhci_pci ahci intel_lpss_pci i2c_i801 megaraid_sas tg3 bnxt_en"]
- name: sysctl
image: linuxkit/sysctl:5f56434b81004b50b47ed629b222619168c2bcdf
image: linuxkit/sysctl:c5f4b4895844b993dce4e8b35fd8263a6b557807
# Metadata
- name: metadata
image: linuxkit/metadata:4f81c0c3a2b245567fd7d32d799018c9614a9907
image: linuxkit/metadata:f35b5aafc7d19bb6a44a900840727902dad78e44
command: ["/usr/bin/metadata", "-v", "cdrom"]
# Filesystem
- name: swap
image: linuxkit/swap:f4b8ffef87c8c72165bd8a92b790ac252ccf1821
image: linuxkit/swap:8a1fd15d56b6ddf67d6d8ce25361178e1f36128b
command: ["/sbin/swapon", "/dev/sda3"]
- name: dm-crypt
image: linuxkit/dm-crypt:981fde241bb84616a5ba94c04cdefa1489431a25
image: linuxkit/dm-crypt:19fa6affe9da03afc91694e36d72a4924c65a0e0
command: ["/usr/bin/crypto", "-l", "crypt_fic", "/dev/sda4"]
binds:
- /dev:/dev
- /run/config/dm-crypt:/etc/dm-crypt
- name: mount
image: linuxkit/mount:cb8caa72248f7082fc2074ce843d53cdc15df04a
image: linuxkit/mount:4413ebd50bfbe026058e4a60463259cece2b8bb5
command: ["/usr/bin/mountie", "-device", "/dev/mapper/crypt_fic", "/var/lib/fic" ]
# Network
# - name: ntp
# image: linuxkit/openntpd:f99c4117763480815553b72022b426639a13ce86
# image: linuxkit/openntpd:da26954c2f98a274091e5ed0bbdd2079a77a47c1
- name: nginx-ip-setup
image: linuxkit/ip:9696394a7d57b384ae919662ae162c9152029156
image: linuxkit/ip:af77c3f93143ff352a07ad5233d25a665012bcce
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:9696394a7d57b384ae919662ae162c9152029156
image: linuxkit/ip:af77c3f93143ff352a07ad5233d25a665012bcce
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:9696394a7d57b384ae919662ae162c9152029156
# image: linuxkit/ip:af77c3f93143ff352a07ad5233d25a665012bcce
# 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:9696394a7d57b384ae919662ae162c9152029156
image: linuxkit/ip:af77c3f93143ff352a07ad5233d25a665012bcce
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:9696394a7d57b384ae919662ae162c9152029156
image: linuxkit/ip:af77c3f93143ff352a07ad5233d25a665012bcce
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:9696394a7d57b384ae919662ae162c9152029156
image: linuxkit/ip:af77c3f93143ff352a07ad5233d25a665012bcce
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:9696394a7d57b384ae919662ae162c9152029156
image: linuxkit/ip:af77c3f93143ff352a07ad5233d25a665012bcce
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:9696394a7d57b384ae919662ae162c9152029156
image: linuxkit/ip:af77c3f93143ff352a07ad5233d25a665012bcce
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,35 +129,26 @@ onboot:
- /run/config/remote_sync/:/run/config/remote_sync/:ro
net: /run/netns/nginx
- name: firewall-sshd
image: linuxkit/ip:9696394a7d57b384ae919662ae162c9152029156
image: linuxkit/ip:af77c3f93143ff352a07ad5233d25a665012bcce
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:05eca453695984a69617f1f1f0bcdae7f7032967
# image: linuxkit/getty:bae9e3d4861173bacf78f14a4fe44997a430d13b
# env:
# - INSECURE=true
# Enable acpi to shutdown on power events
- name: acpid
image: linuxkit/acpid:6cb5575e487a8fcbd4c3eb6721c23299e6ea452f
image: linuxkit/acpid:6379700e2f3341250432e37a4cac36e35c7caac8
- name: rngd
image: linuxkit/rngd:1a18f2149e42a0a1cb9e7d37608a494342c26032
image: linuxkit/rngd:814d1a3a76e84eae01a94575c038fd22652f94e3
- name: dhcpcd
image: linuxkit/dhcpcd:157df9ef45a035f1542ec2270e374f18efef98a5
image: linuxkit/dhcpcd:330839488cd122db3c44738e265c035c9729a963
net: /run/netns/nginx
binds:
- /etc/dhcpcd.conf:/dhcpcd.conf:ro
@ -266,6 +257,7 @@ 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
@ -288,7 +280,7 @@ services:
# net: /run/netns/nginx
- name: dexidp
image: ghcr.io/dexidp/dex:v2.42.0
image: ghcr.io/dexidp/dex:v2.41.1
net: /run/netns/auth
binds:
- /etc/hosts:/etc/hosts:ro
@ -302,7 +294,7 @@ services:
mkdir:
- /var/lib/fic/dex
- name: vouch-proxy
image: quay.io/vouch/vouch-proxy:alpine-0.41
image: quay.io/vouch/vouch-proxy:alpine-0.39
env:
- VOUCH_CONFIG=/etc/vouch/config.yml
net: /run/netns/auth

View file

@ -1,15 +1,15 @@
kernel:
#image: nemunaire/kernel:5.10.62-0b705d955f5e283f62583c4e227d64a7924c138f-amd64
image: linuxkit/kernel:6.6.71
image: linuxkit/kernel:6.6.13
cmdline: "console=ttyS0 console=tty0"
init:
- nemunaire/mdadm:04814350d71ba9417e1f861be1685de26adf7a67
- nemunaire/syslinux:086f221f281d577d300949aa1094fb20c5cd90dc
- linuxkit/format:3fb088f60ed73ba4a15be41e44654b74112fd3f9
- linuxkit/dm-crypt:981fde241bb84616a5ba94c04cdefa1489431a25
- linuxkit/metadata:4f81c0c3a2b245567fd7d32d799018c9614a9907
- linuxkit/format:3c858f0cf42a2b14441bfb5c266b78f14d2b75a4
- linuxkit/dm-crypt:19fa6affe9da03afc91694e36d72a4924c65a0e0
- linuxkit/metadata:f35b5aafc7d19bb6a44a900840727902dad78e44
- alpine:latest
files:

View file

@ -1,12 +1,12 @@
kernel:
#image: nemunaire/kernel:5.10.62-0b705d955f5e283f62583c4e227d64a7924c138f-amd64
image: linuxkit/kernel:6.6.71
image: linuxkit/kernel:6.6.13
cmdline: "console=ttyS0 console=tty0"
init:
- nemunaire/mdadm:04814350d71ba9417e1f861be1685de26adf7a67
- linuxkit/metadata:4f81c0c3a2b245567fd7d32d799018c9614a9907
- linuxkit/metadata:f35b5aafc7d19bb6a44a900840727902dad78e44
- alpine:latest

File diff suppressed because it is too large Load diff

View file

@ -12,10 +12,10 @@
"@sveltejs/adapter-static": "^3.0.0",
"@sveltejs/kit": "^2.0.0",
"@sveltejs/vite-plugin-svelte": "^3.0.0",
"@sveltestrap/sveltestrap": "^7.0.0",
"@sveltestrap/sveltestrap": "^6.2.1",
"eslint": "^9.0.0",
"eslint-config-prettier": "^10.0.0",
"eslint-plugin-svelte": "^3.0.0",
"eslint-config-prettier": "^9.0.0",
"eslint-plugin-svelte": "^2.35.1",
"prettier": "^3.0.0",
"prettier-plugin-svelte": "^3.1.2",
"sass": "^1.51.0",

View file

@ -33,9 +33,9 @@
</h1>
<div style="min-width: 0">
<h4 class="fw-bold"><samp>{file.name}</samp></h4>
{#if file.disclaimer}
<div class="file-disclaimer text-warning">
{file.disclaimer}
{#if file.disclamer}
<div class="file-disclamer text-warning">
{file.disclamer}
</div>
{/if}
<nobr>
@ -61,10 +61,10 @@
{/if}
<style>
.file-disclaimer {
.file-disclamer {
display: none;
}
:global(.list-group-item:hover .file-disclaimer) {
:global(.list-group-item:hover .file-disclamer) {
display: block;
}
</style>

42
go.mod
View file

@ -1,16 +1,16 @@
module srs.epita.fr/fic-server
go 1.23.0
go 1.21
toolchain go1.24.1
toolchain go1.23.4
require (
github.com/BurntSushi/toml v1.5.0
github.com/asticode/go-astisub v0.34.0
github.com/BurntSushi/toml v1.4.0
github.com/asticode/go-astisub v0.32.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.14.0
github.com/go-git/go-git/v5 v5.13.1
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.36.0
golang.org/x/image v0.25.0
golang.org/x/oauth2 v0.28.0
golang.org/x/crypto v0.31.0
golang.org/x/image v0.23.0
golang.org/x/oauth2 v0.25.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.2 // indirect
github.com/ProtonMail/go-crypto v1.1.5 // indirect
github.com/Microsoft/go-winio v0.6.1 // indirect
github.com/ProtonMail/go-crypto v1.1.3 // 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.6.0 // indirect
github.com/cloudflare/circl v1.3.7 // indirect
github.com/cloudwego/base64x v0.1.4 // indirect
github.com/cloudwego/iasm v0.2.0 // indirect
github.com/cyphar/filepath-securejoin v0.4.1 // indirect
github.com/cyphar/filepath-securejoin v0.3.6 // 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.2 // indirect
github.com/go-git/go-billy/v5 v5.6.1 // 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-20241129210726-2c02b8208cf8 // indirect
github.com/golang/protobuf v1.5.4 // indirect
github.com/golang/groupcache v0.0.0-20210331224755-41bb18bfe9da // indirect
github.com/golang/protobuf v1.5.3 // 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.2 // indirect
github.com/pjbgf/sha1cd v0.3.0 // 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.1 // indirect
github.com/skeema/knownhosts v1.3.0 // 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.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/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/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
View file

@ -10,8 +10,6 @@ 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=
@ -19,8 +17,6 @@ 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=
@ -37,8 +33,6 @@ 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=
@ -74,8 +68,6 @@ 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=
@ -112,8 +104,6 @@ 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=
@ -123,8 +113,6 @@ 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=
@ -180,8 +168,6 @@ 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=
@ -213,10 +199,6 @@ 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=
@ -261,15 +243,12 @@ 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=
@ -373,8 +352,6 @@ 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=
@ -405,8 +382,6 @@ 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=
@ -567,12 +542,6 @@ 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=
@ -620,10 +589,6 @@ 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=
@ -692,10 +657,6 @@ 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=
@ -746,10 +707,6 @@ 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=
@ -761,10 +718,6 @@ 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=
@ -845,12 +798,6 @@ 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=
@ -900,10 +847,6 @@ 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=

View file

@ -1,26 +0,0 @@
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"`
}

View file

@ -414,7 +414,6 @@ 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,
@ -424,26 +423,6 @@ 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
}

View file

@ -3,7 +3,6 @@ package fic
import (
"errors"
"fmt"
"log"
"math"
"time"
)
@ -445,25 +444,11 @@ func (e *Exercice) GetOrdinal() (int, error) {
}
// NewTry registers a solving attempt for the given Team.
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
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
} else {
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())
}
}
return nil
}
}
@ -565,7 +550,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 tryId, err := e.NewTry(t, cksum); err != nil {
if err := e.NewTry(t, cksum); err != nil {
return false, err
} else if flags, err := e.GetFlagKeys(); err != nil {
return false, err
@ -580,10 +565,6 @@ 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
@ -608,21 +589,15 @@ 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 ok {
if len(res) > 0 {
e.NewTryFlag(tryId, flag)
} else if flag.Check([]byte(res)) != 0 {
if !PartialValidation || t.HasPartiallySolved(flag) == nil {
valid = valid && flag.IsOptionnal()
}
if flag.Check([]byte(res)) != 0 {
if !PartialValidation || t.HasPartiallySolved(flag) == nil {
valid = valid && flag.IsOptionnal()
}
} else {
err := flag.FoundBy(t)
if err == nil {
// err is unicity issue, probably flag already found
goodResponses += 1
}
} else {
err := flag.FoundBy(t)
if err == nil {
// err is unicity issue, probably flag already found
goodResponses += 1
}
}
}

View file

@ -68,8 +68,7 @@ func (e *Exercice) AppendHistoryItem(tId int64, kind string, secondary *int64) e
if kind == "tries" {
bid := make([]byte, 5)
binary.LittleEndian.PutUint32(bid, rand.Uint32())
_, err = (&Exercice{Id: e.Id}).NewTry(team, bid)
return err
return (&Exercice{Id: e.Id}).NewTry(team, bid)
} else if kind == "hint" && secondary != nil {
return team.OpenHint(&EHint{Id: *secondary})
} else if kind == "wchoices" && secondary != nil {

View file

@ -392,12 +392,7 @@ func (f *EFile) GetDepends() ([]Flag, error) {
// CheckFileOnDisk recalculates the hash of the file on disk.
func (f *EFile) CheckFileOnDisk() error {
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 {
if _, size, err := checkFileHash(path.Join(FilesDir, f.Path), f.Checksum); err != nil {
return err
} else if size == 0 {
if _, _, err := checkFileHash(path.Join(FilesDir, f.Path+".gz"), f.Checksum); err != nil {
@ -405,17 +400,9 @@ func (f *EFile) CheckFileOnDisk() error {
} else {
return nil
}
} else if err != nil {
return err
} else {
return nil
}
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.

View file

@ -14,9 +14,6 @@ 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.

View file

@ -230,54 +230,6 @@ 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

View file

@ -71,18 +71,6 @@ 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 {

View file

@ -136,54 +136,6 @@ 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 {
@ -255,7 +207,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_entry = ?", n.Label, n.Response, n.Id); err != nil {
if res, err := DBExec("UPDATE mcq_entries SET label = ?, response = ? WHERE id_mcq = ?", n.Label, n.Response, n.Id); err != nil {
return 0, err
} else if nb, err := res.RowsAffected(); err != nil {
return 0, err
@ -367,24 +319,6 @@ 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

View file

@ -3,7 +3,6 @@ package fic
import (
"bytes"
"crypto/md5"
"math/rand"
"regexp"
"strings"
)
@ -188,11 +187,3 @@ 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
View file

@ -8,7 +8,7 @@
"name": "qa",
"version": "0.0.1",
"dependencies": {
"@sveltestrap/sveltestrap": "^7.0.0",
"@sveltestrap/sveltestrap": "^6.2.1",
"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": "^10.0.0",
"eslint-plugin-svelte": "^3.0.0",
"eslint-config-prettier": "^9.0.0",
"eslint-plugin-svelte": "^2.35.1",
"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.2",
"resolved": "https://registry.npmjs.org/@eslint/config-array/-/config-array-0.19.2.tgz",
"integrity": "sha512-GNKqxfHG2ySmJOBSHg7LxeUx4xpuCoFjacmlCoYWEbaPXLwvfIjixRI12xCQZeULksQb23uiA8F40w5TojpV7w==",
"version": "0.19.1",
"resolved": "https://registry.npmjs.org/@eslint/config-array/-/config-array-0.19.1.tgz",
"integrity": "sha512-fo6Mtm5mWyKjA/Chy1BYTdn5mGJoDNjC7C64ug20ADsRDGrA85bN3uK3MaKbeRkRuuIEAR5N33Jr1pbm411/PA==",
"dev": true,
"license": "Apache-2.0",
"dependencies": {
"@eslint/object-schema": "^2.1.6",
"@eslint/object-schema": "^2.1.5",
"debug": "^4.3.1",
"minimatch": "^3.1.2"
},
@ -486,20 +486,10 @@
"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.12.0",
"resolved": "https://registry.npmjs.org/@eslint/core/-/core-0.12.0.tgz",
"integrity": "sha512-cmrR6pytBuSMTaBweKoGMwu3EiHiEC+DoyupPmlZ0HxBJBtIxwe+j/E4XPIKNx+Q74c8lXKPwYawBf5glsTkHg==",
"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==",
"dev": true,
"license": "Apache-2.0",
"dependencies": {
@ -510,9 +500,9 @@
}
},
"node_modules/@eslint/eslintrc": {
"version": "3.3.1",
"resolved": "https://registry.npmjs.org/@eslint/eslintrc/-/eslintrc-3.3.1.tgz",
"integrity": "sha512-gtF186CXhIl1p4pJNGZw8Yc6RlshoePRvE0X91oPGb3vZ8pM3qOS9W9NGPat9LziaBV7XrJWGylNQXkGcnM3IQ==",
"version": "3.2.0",
"resolved": "https://registry.npmjs.org/@eslint/eslintrc/-/eslintrc-3.2.0.tgz",
"integrity": "sha512-grOjVNN8P3hjJn/eIETF1wwd12DdnwFDoyceUJLYYdkpbwq3nLi+4fqrTAONx7XDALqlL220wC/RHSC/QTI/0w==",
"dev": true,
"license": "MIT",
"dependencies": {
@ -534,9 +524,9 @@
}
},
"node_modules/@eslint/js": {
"version": "9.23.0",
"resolved": "https://registry.npmjs.org/@eslint/js/-/js-9.23.0.tgz",
"integrity": "sha512-35MJ8vCPU0ZMxo7zfev2pypqTwWTofFZO6m4KAtdoFhRpLJUpHTZZ+KB3C7Hb1d7bULYwO4lJXGCi5Se+8OMbw==",
"version": "9.18.0",
"resolved": "https://registry.npmjs.org/@eslint/js/-/js-9.18.0.tgz",
"integrity": "sha512-fK6L7rxcq6/z+AaQMtiFTkvbHkBLNlwyRxHpKawP0x3u9+NC6MQTnFW+AdpwC6gfHTW0051cokQgtTN2FqlxQA==",
"dev": true,
"license": "MIT",
"engines": {
@ -544,9 +534,9 @@
}
},
"node_modules/@eslint/object-schema": {
"version": "2.1.6",
"resolved": "https://registry.npmjs.org/@eslint/object-schema/-/object-schema-2.1.6.tgz",
"integrity": "sha512-RBMg5FRL0I0gs51M/guSAj5/e14VQ4tpZnQNWwuDT66P14I43ItmPfIZRhO9fUVIPOAQXU47atlywZ/czoqFPA==",
"version": "2.1.5",
"resolved": "https://registry.npmjs.org/@eslint/object-schema/-/object-schema-2.1.5.tgz",
"integrity": "sha512-o0bhxnL89h5Bae5T318nFoFzGy+YE5i/gGkoPAgkmTVdRKTiv3p8JHevPiPaMwoloKfEiiaHlawCqaZMqRm+XQ==",
"dev": true,
"license": "Apache-2.0",
"engines": {
@ -554,13 +544,13 @@
}
},
"node_modules/@eslint/plugin-kit": {
"version": "0.2.7",
"resolved": "https://registry.npmjs.org/@eslint/plugin-kit/-/plugin-kit-0.2.7.tgz",
"integrity": "sha512-JubJ5B2pJ4k4yGxaNLdbjrnk9d/iDz6/q8wOilpIowd6PJPgaxCuHBnBszq7Ce2TyMrywm5r4PnKm6V3iiZF+g==",
"version": "0.2.5",
"resolved": "https://registry.npmjs.org/@eslint/plugin-kit/-/plugin-kit-0.2.5.tgz",
"integrity": "sha512-lB05FkqEdUg2AA0xEbUz0SnkXT1LcCTa438W4IWTUh4hdOnVbQyOJ81OrDXsJk/LSiJHubgGEFoR5EHq1NsH1A==",
"dev": true,
"license": "Apache-2.0",
"dependencies": {
"@eslint/core": "^0.12.0",
"@eslint/core": "^0.10.0",
"levn": "^0.4.1"
},
"engines": {
@ -620,9 +610,9 @@
}
},
"node_modules/@humanwhocodes/retry": {
"version": "0.4.2",
"resolved": "https://registry.npmjs.org/@humanwhocodes/retry/-/retry-0.4.2.tgz",
"integrity": "sha512-xeO57FpIu4p1Ri3Jq/EXq4ClRm86dVF2z/+kvFnyqVYRavTZmaFaUBbWCOuuTh0o/g7DSsk6kc2vrS4Vl5oPOQ==",
"version": "0.4.1",
"resolved": "https://registry.npmjs.org/@humanwhocodes/retry/-/retry-0.4.1.tgz",
"integrity": "sha512-c7hNEllBlenFTHBky65mhq8WD2kbN9Q6gk0bTk8lSBvc554jpXSkST1iePudpt7+A/AQvuHs9EMqjHDXMY1lrA==",
"dev": true,
"license": "Apache-2.0",
"engines": {
@ -699,9 +689,9 @@
}
},
"node_modules/@rollup/rollup-android-arm-eabi": {
"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==",
"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==",
"cpu": [
"arm"
],
@ -713,9 +703,9 @@
]
},
"node_modules/@rollup/rollup-android-arm64": {
"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==",
"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==",
"cpu": [
"arm64"
],
@ -727,9 +717,9 @@
]
},
"node_modules/@rollup/rollup-darwin-arm64": {
"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==",
"version": "4.30.1",
"resolved": "https://registry.npmjs.org/@rollup/rollup-darwin-arm64/-/rollup-darwin-arm64-4.30.1.tgz",
"integrity": "sha512-r7FQIXD7gB0WJ5mokTUgUWPl0eYIH0wnxqeSAhuIwvnnpjdVB8cRRClyKLQr7lgzjctkbp5KmswWszlwYln03Q==",
"cpu": [
"arm64"
],
@ -741,9 +731,9 @@
]
},
"node_modules/@rollup/rollup-darwin-x64": {
"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==",
"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==",
"cpu": [
"x64"
],
@ -755,9 +745,9 @@
]
},
"node_modules/@rollup/rollup-freebsd-arm64": {
"version": "4.32.0",
"resolved": "https://registry.npmjs.org/@rollup/rollup-freebsd-arm64/-/rollup-freebsd-arm64-4.32.0.tgz",
"integrity": "sha512-JpsGxLBB2EFXBsTLHfkZDsXSpSmKD3VxXCgBQtlPcuAqB8TlqtLcbeMhxXQkCDv1avgwNjF8uEIbq5p+Cee0PA==",
"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==",
"cpu": [
"arm64"
],
@ -769,9 +759,9 @@
]
},
"node_modules/@rollup/rollup-freebsd-x64": {
"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==",
"version": "4.30.1",
"resolved": "https://registry.npmjs.org/@rollup/rollup-freebsd-x64/-/rollup-freebsd-x64-4.30.1.tgz",
"integrity": "sha512-1MEdGqogQLccphhX5myCJqeGNYTNcmTyaic9S7CG3JhwuIByJ7J05vGbZxsizQthP1xpVx7kd3o31eOogfEirw==",
"cpu": [
"x64"
],
@ -783,9 +773,9 @@
]
},
"node_modules/@rollup/rollup-linux-arm-gnueabihf": {
"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==",
"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==",
"cpu": [
"arm"
],
@ -797,9 +787,9 @@
]
},
"node_modules/@rollup/rollup-linux-arm-musleabihf": {
"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==",
"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==",
"cpu": [
"arm"
],
@ -811,9 +801,9 @@
]
},
"node_modules/@rollup/rollup-linux-arm64-gnu": {
"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==",
"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==",
"cpu": [
"arm64"
],
@ -825,9 +815,9 @@
]
},
"node_modules/@rollup/rollup-linux-arm64-musl": {
"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==",
"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==",
"cpu": [
"arm64"
],
@ -839,9 +829,9 @@
]
},
"node_modules/@rollup/rollup-linux-loongarch64-gnu": {
"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==",
"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==",
"cpu": [
"loong64"
],
@ -853,9 +843,9 @@
]
},
"node_modules/@rollup/rollup-linux-powerpc64le-gnu": {
"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==",
"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==",
"cpu": [
"ppc64"
],
@ -867,9 +857,9 @@
]
},
"node_modules/@rollup/rollup-linux-riscv64-gnu": {
"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==",
"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==",
"cpu": [
"riscv64"
],
@ -881,9 +871,9 @@
]
},
"node_modules/@rollup/rollup-linux-s390x-gnu": {
"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==",
"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==",
"cpu": [
"s390x"
],
@ -895,9 +885,9 @@
]
},
"node_modules/@rollup/rollup-linux-x64-gnu": {
"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==",
"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==",
"cpu": [
"x64"
],
@ -909,9 +899,9 @@
]
},
"node_modules/@rollup/rollup-linux-x64-musl": {
"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==",
"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==",
"cpu": [
"x64"
],
@ -923,9 +913,9 @@
]
},
"node_modules/@rollup/rollup-win32-arm64-msvc": {
"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==",
"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==",
"cpu": [
"arm64"
],
@ -937,9 +927,9 @@
]
},
"node_modules/@rollup/rollup-win32-ia32-msvc": {
"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==",
"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==",
"cpu": [
"ia32"
],
@ -951,9 +941,9 @@
]
},
"node_modules/@rollup/rollup-win32-x64-msvc": {
"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==",
"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==",
"cpu": [
"x64"
],
@ -964,15 +954,6 @@
"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",
@ -984,23 +965,25 @@
}
},
"node_modules/@sveltejs/kit": {
"version": "2.20.2",
"resolved": "https://registry.npmjs.org/@sveltejs/kit/-/kit-2.20.2.tgz",
"integrity": "sha512-Dv8TOAZC9vyfcAB9TMsvUEJsRbklRTeNfcYBPaeH6KnABJ99i3CvCB2eNx8fiiliIqe+9GIchBg4RodRH5p1BQ==",
"version": "2.15.2",
"resolved": "https://registry.npmjs.org/@sveltejs/kit/-/kit-2.15.2.tgz",
"integrity": "sha512-p208T1kdM6zd8k4YXIUM60pLWQ8dZqehXSiqn4NulXHyHibX53uIAL2xtNL8GjxX2IVPqPRT978MwVYhCKExdQ==",
"dev": true,
"hasInstallScript": true,
"license": "MIT",
"dependencies": {
"@types/cookie": "^0.6.0",
"cookie": "^0.6.0",
"devalue": "^5.1.0",
"esm-env": "^1.2.2",
"esm-env": "^1.2.1",
"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"
"sirv": "^3.0.0",
"tiny-glob": "^0.2.9"
},
"bin": {
"svelte-kit": "svelte-kit.js"
@ -1056,9 +1039,9 @@
}
},
"node_modules/@sveltestrap/sveltestrap": {
"version": "7.1.0",
"resolved": "https://registry.npmjs.org/@sveltestrap/sveltestrap/-/sveltestrap-7.1.0.tgz",
"integrity": "sha512-TpIx25kqLV+z+VD3yfqYayOI1IaCeWFbT0uqM6NfA4vQgDs9PjFwmjkU4YEAlV/ngs9e7xPmaRWE7lkrg4Miow==",
"version": "6.2.7",
"resolved": "https://registry.npmjs.org/@sveltestrap/sveltestrap/-/sveltestrap-6.2.7.tgz",
"integrity": "sha512-WwLLfAFUb42BGuRrf3Vbct30bQMzlEMMipN/MfxhjuLTmLQeW9muVJfPyvjtWS+mY+RjkSCoHvAp/ZobP1NLlQ==",
"license": "MIT",
"dependencies": {
"@popperjs/core": "^2.11.8"
@ -1109,6 +1092,15 @@
"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",
@ -1416,23 +1408,22 @@
}
},
"node_modules/eslint": {
"version": "9.23.0",
"resolved": "https://registry.npmjs.org/eslint/-/eslint-9.23.0.tgz",
"integrity": "sha512-jV7AbNoFPAY1EkFYpLq5bslU9NLNO8xnEeQXwErNibVryjk67wHVmddTBilc5srIttJDBrB0eMHKZBFbSIABCw==",
"version": "9.18.0",
"resolved": "https://registry.npmjs.org/eslint/-/eslint-9.18.0.tgz",
"integrity": "sha512-+waTfRWQlSbpt3KWE+CjrPPYnbq9kfZIYUqapc0uBXyjTp8aYXZDsUH16m39Ryq3NjAVP4tjuF7KaukeqoCoaA==",
"dev": true,
"license": "MIT",
"dependencies": {
"@eslint-community/eslint-utils": "^4.2.0",
"@eslint-community/regexpp": "^4.12.1",
"@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",
"@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",
"@humanfs/node": "^0.16.6",
"@humanwhocodes/module-importer": "^1.0.1",
"@humanwhocodes/retry": "^0.4.2",
"@humanwhocodes/retry": "^0.4.1",
"@types/estree": "^1.0.6",
"@types/json-schema": "^7.0.15",
"ajv": "^6.12.4",
@ -1440,7 +1431,7 @@
"cross-spawn": "^7.0.6",
"debug": "^4.3.2",
"escape-string-regexp": "^4.0.0",
"eslint-scope": "^8.3.0",
"eslint-scope": "^8.2.0",
"eslint-visitor-keys": "^4.2.0",
"espree": "^10.3.0",
"esquery": "^1.5.0",
@ -1477,9 +1468,9 @@
}
},
"node_modules/eslint-compat-utils": {
"version": "0.6.4",
"resolved": "https://registry.npmjs.org/eslint-compat-utils/-/eslint-compat-utils-0.6.4.tgz",
"integrity": "sha512-/u+GQt8NMfXO8w17QendT4gvO5acfxQsAKirAt0LVxDnr2N8YLCVbregaNc/Yhp7NM128DwCaRvr8PLDfeNkQw==",
"version": "0.5.1",
"resolved": "https://registry.npmjs.org/eslint-compat-utils/-/eslint-compat-utils-0.5.1.tgz",
"integrity": "sha512-3z3vFexKIEnjHE3zCMRo6fn/e44U7T1khUjg+Hp0ZQMCigh28rALD0nPFBcGZuiLC5rLZa2ubQHDRln09JfU2Q==",
"dev": true,
"license": "MIT",
"dependencies": {
@ -1493,9 +1484,9 @@
}
},
"node_modules/eslint-config-prettier": {
"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==",
"version": "9.1.0",
"resolved": "https://registry.npmjs.org/eslint-config-prettier/-/eslint-config-prettier-9.1.0.tgz",
"integrity": "sha512-NSWl5BFQWEPi1j4TjVNItzYV7dZXZ+wP6I6ZhrBGpChQhZRUaElihE9uRRkcbRnNb76UMKDF3r+WTmNcGPKsqw==",
"dev": true,
"license": "MIT",
"bin": {
@ -1506,31 +1497,32 @@
}
},
"node_modules/eslint-plugin-svelte": {
"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==",
"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==",
"dev": true,
"license": "MIT",
"dependencies": {
"@eslint-community/eslint-utils": "^4.4.1",
"@jridgewell/sourcemap-codec": "^1.5.0",
"eslint-compat-utils": "^0.6.4",
"@eslint-community/eslint-utils": "^4.4.0",
"@jridgewell/sourcemap-codec": "^1.4.15",
"eslint-compat-utils": "^0.5.1",
"esutils": "^2.0.3",
"known-css-properties": "^0.35.0",
"postcss": "^8.4.49",
"postcss": "^8.4.38",
"postcss-load-config": "^3.1.4",
"postcss-safe-parser": "^7.0.0",
"semver": "^7.6.3",
"svelte-eslint-parser": "^1.0.1"
"postcss-safe-parser": "^6.0.0",
"postcss-selector-parser": "^6.1.0",
"semver": "^7.6.2",
"svelte-eslint-parser": "^0.43.0"
},
"engines": {
"node": "^18.18.0 || ^20.9.0 || >=21.1.0"
"node": "^14.17.0 || >=16.0.0"
},
"funding": {
"url": "https://github.com/sponsors/ota-meshi"
},
"peerDependencies": {
"eslint": "^8.57.1 || ^9.0.0",
"eslint": "^7.0.0 || ^8.0.0-0 || ^9.0.0-0",
"svelte": "^3.37.0 || ^4.0.0 || ^5.0.0"
},
"peerDependenciesMeta": {
@ -1540,9 +1532,9 @@
}
},
"node_modules/eslint-scope": {
"version": "8.3.0",
"resolved": "https://registry.npmjs.org/eslint-scope/-/eslint-scope-8.3.0.tgz",
"integrity": "sha512-pUNxi75F8MJ/GdeKtVLSbYg4ZI34J6C0C7sbL4YOp2exGwen7ZsuBqKzUhXd0qMQ362yET3z+uPwKeg/0C2XCQ==",
"version": "8.2.0",
"resolved": "https://registry.npmjs.org/eslint-scope/-/eslint-scope-8.2.0.tgz",
"integrity": "sha512-PHlWUfG6lvPc3yvP5A4PNyBL1W8fkDUccmI21JUu/+GKZBoH/W5u6usENXUrWFRsyoW5ACUjFGgAFQp5gUlb/A==",
"dev": true,
"license": "BSD-2-Clause",
"dependencies": {
@ -1607,9 +1599,9 @@
}
},
"node_modules/esrap": {
"version": "1.4.5",
"resolved": "https://registry.npmjs.org/esrap/-/esrap-1.4.5.tgz",
"integrity": "sha512-CjNMjkBWWZeHn+VX+gS8YvFwJ5+NDhg8aWZBSFJPR8qQduDNjbJodA2WcwCm7uQa5Rjqj+nZvVmceg1RbHFB9g==",
"version": "1.4.3",
"resolved": "https://registry.npmjs.org/esrap/-/esrap-1.4.3.tgz",
"integrity": "sha512-Xddc1RsoFJ4z9nR7W7BFaEPIp4UXoeQ0+077UdWLxbafMQFyU79sQJMk7kxNgRwQ9/aVgaKacCHC2pUACGwmYw==",
"license": "MIT",
"dependencies": {
"@jridgewell/sourcemap-codec": "^1.4.15"
@ -1761,6 +1753,20 @@
"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",
@ -2138,9 +2144,9 @@
"license": "ISC"
},
"node_modules/postcss": {
"version": "8.5.1",
"resolved": "https://registry.npmjs.org/postcss/-/postcss-8.5.1.tgz",
"integrity": "sha512-6oz2beyjc5VMn/KV1pPw8fliQkhBXrVn1Z3TVyqZxU8kZpzEKhBdmCFqI6ZbmGtamQvQGuU1sgPTk8ZrXDD7jQ==",
"version": "8.4.49",
"resolved": "https://registry.npmjs.org/postcss/-/postcss-8.4.49.tgz",
"integrity": "sha512-OCVPnIObs4N29kxTjzLfUryOkvZEq+pf8jTF0lg8E7uETuWHA+v7j3c/xJmiqpX450191LlmZfUKkXxkTry7nA==",
"dev": true,
"funding": [
{
@ -2158,7 +2164,7 @@
],
"license": "MIT",
"dependencies": {
"nanoid": "^3.3.8",
"nanoid": "^3.3.7",
"picocolors": "^1.1.1",
"source-map-js": "^1.2.1"
},
@ -2197,30 +2203,20 @@
}
},
"node_modules/postcss-safe-parser": {
"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==",
"version": "6.0.0",
"resolved": "https://registry.npmjs.org/postcss-safe-parser/-/postcss-safe-parser-6.0.0.tgz",
"integrity": "sha512-FARHN8pwH+WiS2OPCxJI8FuRJpTVnn6ZNFiqAM2aeW2LwTHWWmWgIyKC6cUo0L8aeKiF/14MNvnpls6R2PBeMQ==",
"dev": true,
"funding": [
{
"type": "opencollective",
"url": "https://opencollective.com/postcss/"
},
{
"type": "tidelift",
"url": "https://tidelift.com/funding/github/npm/postcss-safe-parser"
},
{
"type": "github",
"url": "https://github.com/sponsors/ai"
}
],
"license": "MIT",
"engines": {
"node": ">=18.0"
"node": ">=12.0"
},
"funding": {
"type": "opencollective",
"url": "https://opencollective.com/postcss/"
},
"peerDependencies": {
"postcss": "^8.4.31"
"postcss": "^8.3.3"
}
},
"node_modules/postcss-scss": {
@ -2251,9 +2247,9 @@
}
},
"node_modules/postcss-selector-parser": {
"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==",
"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==",
"dev": true,
"license": "MIT",
"dependencies": {
@ -2275,9 +2271,9 @@
}
},
"node_modules/prettier": {
"version": "3.5.3",
"resolved": "https://registry.npmjs.org/prettier/-/prettier-3.5.3.tgz",
"integrity": "sha512-QQtaxnoDJeAkDvDKWCLiwIXkTgRhwYDEQCghU9Z6q03iyek/rxRh/2lC3HB7P8sWT2xC/y5JDctPLBIGzHKbhw==",
"version": "3.4.2",
"resolved": "https://registry.npmjs.org/prettier/-/prettier-3.4.2.tgz",
"integrity": "sha512-e9MewbtFo+Fevyuxn/4rrcDAaq0IYxPGLvObpQjiZBMAzB9IGmzlnG9RZy3FFas+eBMu2vA0CszMeduow5dIuQ==",
"dev": true,
"license": "MIT",
"bin": {
@ -2322,9 +2318,9 @@
}
},
"node_modules/rollup": {
"version": "4.32.0",
"resolved": "https://registry.npmjs.org/rollup/-/rollup-4.32.0.tgz",
"integrity": "sha512-JmrhfQR31Q4AuNBjjAX4s+a/Pu/Q8Q9iwjWBsjRH1q52SPFE2NqRMK6fUZKKnvKO6id+h7JIRf0oYsph53eATg==",
"version": "4.30.1",
"resolved": "https://registry.npmjs.org/rollup/-/rollup-4.30.1.tgz",
"integrity": "sha512-mlJ4glW020fPuLi7DkM/lN97mYEZGWeqBnrljzN0gs7GLctqX3lNWxKQ7Gl712UAX+6fog/L3jh4gb7R6aVi3w==",
"dev": true,
"license": "MIT",
"dependencies": {
@ -2338,25 +2334,25 @@
"npm": ">=8.0.0"
},
"optionalDependencies": {
"@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",
"@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",
"fsevents": "~2.3.2"
}
},
@ -2468,16 +2464,16 @@
}
},
"node_modules/svelte": {
"version": "5.25.3",
"resolved": "https://registry.npmjs.org/svelte/-/svelte-5.25.3.tgz",
"integrity": "sha512-J9rcZ/xVJonAoESqVGHHZhrNdVbrCfkdB41BP6eiwHMoFShD9it3yZXApVYMHdGfCshBsZCKsajwJeBbS/M1zg==",
"version": "5.19.0",
"resolved": "https://registry.npmjs.org/svelte/-/svelte-5.19.0.tgz",
"integrity": "sha512-qvd2GvvYnJxS/MteQKFSMyq8cQrAAut28QZ39ySv9k3ggmhw4Au4Rfcsqva74i0xMys//OhbhVCNfXPrDzL/Bg==",
"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",
@ -2493,21 +2489,20 @@
}
},
"node_modules/svelte-eslint-parser": {
"version": "1.1.1",
"resolved": "https://registry.npmjs.org/svelte-eslint-parser/-/svelte-eslint-parser-1.1.1.tgz",
"integrity": "sha512-QLVGPIMDettl30qRHXU2VrPvVJKG8GsGstye7n8rFbEiu3gEARksuQg9Xu4GzubNxhGNM8stfBZkhyMbBQmjFA==",
"version": "0.43.0",
"resolved": "https://registry.npmjs.org/svelte-eslint-parser/-/svelte-eslint-parser-0.43.0.tgz",
"integrity": "sha512-GpU52uPKKcVnh8tKN5P4UZpJ/fUDndmq7wfsvoVXsyP+aY0anol7Yqo01fyrlaWGMFfm4av5DyrjlaXdLRJvGA==",
"dev": true,
"license": "MIT",
"dependencies": {
"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"
"eslint-scope": "^7.2.2",
"eslint-visitor-keys": "^3.4.3",
"espree": "^9.6.1",
"postcss": "^8.4.39",
"postcss-scss": "^4.0.9"
},
"engines": {
"node": "^18.18.0 || ^20.9.0 || >=21.1.0"
"node": "^12.22.0 || ^14.17.0 || >=16.0.0"
},
"funding": {
"url": "https://github.com/sponsors/ota-meshi"
@ -2521,6 +2516,54 @@
}
}
},
"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",
@ -2534,6 +2577,17 @@
"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",
@ -2575,9 +2629,9 @@
"license": "MIT"
},
"node_modules/vite": {
"version": "5.4.15",
"resolved": "https://registry.npmjs.org/vite/-/vite-5.4.15.tgz",
"integrity": "sha512-6ANcZRivqL/4WtwPGTKNaosuNJr5tWiftOC7liM7G9+rMb8+oeJeyzymDu4rTN93seySBmbjSfsS3Vzr19KNtA==",
"version": "5.4.11",
"resolved": "https://registry.npmjs.org/vite/-/vite-5.4.11.tgz",
"integrity": "sha512-c7jFQRklXua0mTzneGW9QVyxFjUgwcihC4bXEtujIo2ouWCe1Ajt/amn2PCxYnhYfd5k09JX3SB7OYWFKYqj8Q==",
"dev": true,
"license": "MIT",
"dependencies": {

View file

@ -14,8 +14,8 @@
"@sveltejs/kit": "^2.0.0",
"@sveltejs/vite-plugin-svelte": "^3.0.0",
"eslint": "^9.0.0",
"eslint-config-prettier": "^10.0.0",
"eslint-plugin-svelte": "^3.0.0",
"eslint-config-prettier": "^9.0.0",
"eslint-plugin-svelte": "^2.35.1",
"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": "^7.0.0"
"@sveltestrap/sveltestrap": "^6.2.1"
}
}

View file

@ -9,14 +9,12 @@ import (
"log"
"net/http"
"strconv"
"srs.epita.fr/fic-server/libfic"
)
type AirbusAPI struct {
BaseURL string
Token string
SessionUUID string
SessionID int64
InsecureSkipVerify bool
}
@ -53,7 +51,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(&fic.CyberrangeAPIResponse{Data: out}); err != nil {
if err := jdec.Decode(out); err != nil {
return fmt.Errorf("an error occurs when trying to decode response: %w", err)
}
}
@ -89,7 +87,7 @@ type AirbusUser struct {
}
func (a *AirbusAPI) GetUsers() (users AirbusUserData, err error) {
err = a.request("GET", fmt.Sprintf("/sessions/%s/users", a.SessionUUID), nil, &users)
err = a.request("GET", fmt.Sprintf("/sessions/%d/users", a.SessionID), nil, &users)
return
}
@ -139,7 +137,7 @@ type AirbusChallenge struct {
}
func (a *AirbusAPI) GetChallenges() (challenges AirbusChallengeData, err error) {
err = a.request("GET", fmt.Sprintf("/v1/sessions/%s/challenges", a.SessionUUID), nil, &challenges)
err = a.request("GET", fmt.Sprintf("/v1/sessions/%d/challenges", a.SessionID), nil, &challenges)
return
}
@ -158,23 +156,25 @@ func (a *AirbusAPI) GetChallengeFromName(name string) (*AirbusChallenge, error)
return nil, fmt.Errorf("unable to find challenge %q", name)
}
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)
func (a *AirbusAPI) ValidateChallengeFromUser(team *AirbusTeam, challengeId AirbusChallengeId) (err error) {
log.Printf("ValidateChallenge: %d, %s, %d", a.SessionID, challengeId.String(), team.Members[0].ID)
if dryRun {
return
}
err = a.request("GET", fmt.Sprintf("/v1/sessions/%s/%s/%s/validate", a.SessionUUID, challengeId.String(), team.Members[0].UUID), nil, nil)
err = a.request("GET", fmt.Sprintf("/v1/sessions/%d/%s/%d/validate", a.SessionID, challengeId.String(), team.Members[0].ID), 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 *fic.CyberrangeTeam, value int64, message string) (err error) {
func (a *AirbusAPI) AwardUser(team *AirbusTeam, 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 *fic.CyberrangeTeam, value int64, message str
return
}
err = a.request("POST", fmt.Sprintf("/v1/sessions/%s/%s/awards", a.SessionUUID, team.Members[0].UUID), bytes.NewReader(marshalled), nil)
err = a.request("POST", fmt.Sprintf("/v1/sessions/%d/awards", a.SessionID), bytes.NewReader(marshalled), nil)
if err != nil {
return err
}

View file

@ -16,8 +16,6 @@ import (
"time"
"gopkg.in/fsnotify.v1"
"srs.epita.fr/fic-server/libfic"
)
var (
@ -79,8 +77,12 @@ func main() {
fd.Close()
}
if v, exists := os.LookupEnv("AIRBUS_SESSION_UUID"); exists {
api.SessionUUID = v
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())
}
} else if v, exists := os.LookupEnv("AIRBUS_SESSION_NAME_FILE"); exists {
fd, err := os.Open(v)
if err != nil {
@ -99,15 +101,15 @@ func main() {
for _, session := range sessions {
if session.Name == v {
api.SessionUUID = session.UUID
api.SessionID = session.ID
break
}
}
if api.SessionUUID == "" {
if api.SessionID == 0 {
log.Fatal("Session ID not found")
} else {
log.Println("Session ID discovered: ", api.SessionUUID)
log.Println("Session ID discovered: ", api.SessionID)
}
} else if v, exists := os.LookupEnv("AIRBUS_SESSION_NAME"); exists {
sessions, err := api.GetSessions()
@ -115,19 +117,17 @@ func main() {
log.Fatal("Unable to retrieve session: ", err)
}
found := false
for _, session := range sessions {
if session.Name == v {
api.SessionUUID = session.UUID
found = true
api.SessionID = session.ID
break
}
}
if !found {
if api.SessionID == 0 {
log.Fatal("Session ID not found")
} else {
log.Println("Session ID discovered: ", api.SessionUUID)
log.Println("Session ID discovered: ", api.SessionID)
}
} 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(" - %s: %q", session.UUID, session.Name)
log.Printf(" - %d: %q", session.ID, session.Name)
}
os.Exit(1)
}
@ -156,11 +156,11 @@ func main() {
}
fmt.Println("## Airbus' registered teams:")
fmt.Println("----------------------------------------------------------------------------------")
fmt.Println(" UUID | Name | Nb. | Score | Rank")
fmt.Println("----------------------------------------------------------------------------------")
fmt.Println("-------------------------------------------")
fmt.Println(" ID | Name | Nb. | Score | Rank")
fmt.Println("-------------------------------------------")
for _, team := range teams {
fmt.Printf(" %s | % 20s | % 3d | % 5d | % 3d\n", team.UUID, team.Name, len(team.Members), team.Score, team.Rank)
fmt.Printf("% 2d | % 15s | % 3d | % 5d | % 3d\n", team.ID, 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 := []*fic.CyberrangeTeam{}
ranking := []*AirbusTeam{}
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 | UUID | Score")
fmt.Println("----------------------------------------------------------------------------")
fmt.Println("-------------------------------------")
fmt.Println(" Rank | Name | ID | Score")
fmt.Println("-------------------------------------")
for _, team := range ranking {
fmt.Printf("% 5d | % 20s | %s | % 5d\n", team.Rank, team.Name, team.UUID, team.Score)
fmt.Printf("% 5d | % 15s |% 3d | % 5d\n", team.Rank, team.Name, team.ID, team.Score)
}
case "get":
teams, err := api.GetTeams()
@ -191,18 +191,22 @@ func main() {
os.Exit(1)
}
teamid := args[1]
teamid, err := strconv.ParseInt(args[1], 10, 64)
if err != nil {
log.Println(err)
os.Exit(1)
}
for _, team := range teams {
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)
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)
for _, member := range team.Members {
fmt.Printf(" - UUID: %s\n Name: %s\n Nickname: %s\n E-mail: %s\n", member.UUID, member.Name, member.Nickname, member.EMail)
fmt.Printf(" - ID: %d\n Name: %s\n Nickname: %s\n E-mail: %s\n", member.ID, member.Name, member.Nickname, member.EMail)
}
os.Exit(0)
}
}
fmt.Printf("Team %s not found. Use 'list' to view all existing teams\n", teamid)
fmt.Printf("Team %d not found. Use 'list' to view all existing teams\n", teamid)
case "award":
if len(args) < 3 {
fmt.Println("award <TEAM_ID> <VALUE> <MESSAGE>")
@ -215,7 +219,11 @@ func main() {
os.Exit(1)
}
teamid := args[1]
teamid, err := strconv.ParseInt(args[1], 10, 64)
if err != nil {
log.Println("Invalid team id", err)
os.Exit(1)
}
value, err := strconv.ParseInt(args[2], 10, 64)
if err != nil {
@ -224,7 +232,7 @@ func main() {
}
for _, team := range teams {
if team.UUID == teamid {
if team.ID == teamid {
err = api.AwardUser(&team, value, strings.Join(args[3:], " "))
if err != nil {
log.Println("Unable to award team:", err)
@ -235,7 +243,7 @@ func main() {
os.Exit(0)
}
}
fmt.Printf("Team %s not found. Use 'list' to view all existing teams\n", teamid)
fmt.Printf("Team %d not found. Use 'list' to view all existing teams\n", teamid)
}
os.Exit(0)

View file

@ -1,18 +1,12 @@
package main
import (
"time"
)
import ()
type Session struct {
Name string `json:"name"`
QuestionValidation string `json:"question_validation"`
Status string `json:"status"`
UUID string `json:"uuid"`
Mode string `json:"mode"`
Difficulty int `json:"difficulty"`
StartedAt time.Time `json:"start_at"`
FinishAt time.Time `json:"finish_at"`
Name string `json:"name"`
Status string `json:"status"`
ID int64 `json:"id"`
Mode string `json:"mode"`
}
func (a *AirbusAPI) GetSessions() (ret []Session, err error) {

View file

@ -2,27 +2,44 @@ package main
import (
"fmt"
"srs.epita.fr/fic-server/libfic"
)
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)
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)
if err != nil {
return nil, err
} else {
return data, nil
return data.Data, nil
}
}
type ByRank []*fic.CyberrangeTeam
type ByRank []*AirbusTeam
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 []*fic.CyberrangeTeam
type ByScore []*AirbusTeam
func (a ByScore) Len() int { return len(a) }
func (a ByScore) Swap(i, j int) { a[i], a[j] = a[j], a[i] }

View file

@ -0,0 +1,102 @@
[
{
"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
}
]

View file

@ -5,8 +5,6 @@ import (
"log"
"os"
"time"
"srs.epita.fr/fic-server/libfic"
)
type TSValue struct {
@ -34,7 +32,7 @@ func loadTS(tspath string) (timestamp map[string]*TSValue, err error) {
}
}
func loadTSFromAPI(teams map[string]*fic.CyberrangeTeam) (timestamp map[string]*TSValue, err error) {
func loadTSFromAPI(teams map[string]*AirbusTeam) (timestamp map[string]*TSValue, err error) {
now := time.Now()
timestamp = map[string]*TSValue{}

View file

@ -23,7 +23,7 @@ type Walker struct {
Exercices AirbusExercicesBindings
Teams map[string]fic.ExportedTeam
RevTeams map[string]string
TeamBindings map[string]*fic.CyberrangeTeam
TeamBindings map[string]*AirbusTeam
API AirbusAPI
Coeff float64
}
@ -35,11 +35,11 @@ func (w *Walker) fetchTeams() error {
}
w.RevTeams = map[string]string{}
w.TeamBindings = map[string]*fic.CyberrangeTeam{}
w.TeamBindings = map[string]*AirbusTeam{}
for tid, team := range w.Teams {
for i, t := range teams {
if team.Name == t.Name || team.ExternalId == t.Name || team.ExternalId == t.UUID {
if team.Name == t.Name || team.ExternalId == t.Name {
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 *fic.CyberrangeTeam) error {
func (w *Walker) TreatScoreGrid(path string, airbusTeam *AirbusTeam) error {
// Read score grid
fdscores, err := os.Open(path)
if err != nil {