From a4001759f6a8669eb84b0b8f93aa11f87aada921 Mon Sep 17 00:00:00 2001 From: Pierre-Olivier Mercier Date: Tue, 14 Jan 2025 17:38:03 +0100 Subject: [PATCH 01/18] ui: Fix file disclaimer not showing --- .../fic/src/lib/components/ExerciceDownloads.svelte | 10 +++++----- 1 file changed, 5 insertions(+), 5 deletions(-) diff --git a/frontend/fic/src/lib/components/ExerciceDownloads.svelte b/frontend/fic/src/lib/components/ExerciceDownloads.svelte index c05a45a0..14ae7e7e 100644 --- a/frontend/fic/src/lib/components/ExerciceDownloads.svelte +++ b/frontend/fic/src/lib/components/ExerciceDownloads.svelte @@ -33,9 +33,9 @@

{file.name}

- {#if file.disclamer} -
- {file.disclamer} + {#if file.disclaimer} +
+ {file.disclaimer}
{/if} @@ -61,10 +61,10 @@ {/if} From 96707e3a2935bc142a77251fdaa7816b324884b7 Mon Sep 17 00:00:00 2001 From: Pierre-Olivier Mercier Date: Fri, 24 Jan 2025 15:14:29 +0100 Subject: [PATCH 02/18] configs: Detect mkisofs --- configs/gen_metadata.sh | 2 ++ 1 file changed, 2 insertions(+) diff --git a/configs/gen_metadata.sh b/configs/gen_metadata.sh index ccb2f4fe..f51984eb 100755 --- a/configs/gen_metadata.sh +++ b/configs/gen_metadata.sh @@ -20,6 +20,8 @@ escape_newline () { sed 's/$/\\n/g' | tr -d '\n' } +which mkisofs > /dev/null 2> /dev/null || { echo "Please install genisoimage (Debian/Ubuntu) or cdrkit (Alpine)" >&2; exit 1; } + if [ $# -gt 0 ] then which jq > /dev/null 2> /dev/null || { echo "Please install jq" >&2; exit 1; } From 4ec4f47951acc7ff918a15b047a1b2205178ae92 Mon Sep 17 00:00:00 2001 From: Pierre-Olivier Mercier Date: Fri, 24 Jan 2025 15:15:48 +0100 Subject: [PATCH 03/18] fickit: keep last metadata iso when dm-crypt key change --- configs/update_imgs.sh | 2 ++ 1 file changed, 2 insertions(+) diff --git a/configs/update_imgs.sh b/configs/update_imgs.sh index 13866c22..fa507cee 100644 --- a/configs/update_imgs.sh +++ b/configs/update_imgs.sh @@ -21,6 +21,8 @@ OLD_KEY=$(cat /run/config/dm-crypt/key) [ "${NEW_KEY}" != "${OLD_KEY}" ] && { read -p "DM-CRYPT key changed in metadata, are you sure you want to erase it? (y/N) " V [ "$V" != "y" ] && [ "$V" != "Y" ] && while true; do + mv /boot/imgs/fickit-metadata.iso /boot/imgs/fickit-metadata.iso.skipped + cp /boot/imgs/fickit-metadata.iso.bak /boot/imgs/fickit-metadata.iso echo echo "Metadata drive not erased" echo From ffb69663b6b4be9d76c520cee76102f30e74f8e3 Mon Sep 17 00:00:00 2001 From: Pierre-Olivier Mercier Date: Fri, 24 Jan 2025 19:09:57 +0100 Subject: [PATCH 04/18] fickit: Initiate sshd config with keys on first run --- fickit-backend.yml | 10 +++++++++- fickit-frontend.yml | 10 +++++++++- 2 files changed, 18 insertions(+), 2 deletions(-) diff --git a/fickit-backend.yml b/fickit-backend.yml index be0ecef7..16a57215 100644 --- a/fickit-backend.yml +++ b/fickit-backend.yml @@ -153,6 +153,15 @@ onboot: mkdir: - /var/lib/fic/secrets + - name: create-ssh-keys + image: nemunaire/rsync:a3d76b2dd0a9ad73be44dc77ad765b20d96a3285 + command: ["/bin/sh", "-c", "touch /etc/ssh/sshd_config && ssh-keygen -A"] + binds: + - /var/lib/fic/ssh:/etc/ssh + runtime: + mkdir: + - /var/lib/fic/ssh + services: # - name: getty # image: linuxkit/getty:bae9e3d4861173bacf78f14a4fe44997a430d13b @@ -361,7 +370,6 @@ services: - /var/lib/fic/files - /var/lib/fic/pki/shared - /var/lib/fic/settingsdist - - /var/lib/fic/ssh - /var/lib/fic/submissions - /var/lib/fic/teams - /var/log/frontend diff --git a/fickit-frontend.yml b/fickit-frontend.yml index d2c558a2..c50b9141 100644 --- a/fickit-frontend.yml +++ b/fickit-frontend.yml @@ -136,6 +136,15 @@ onboot: - /etc/iptables/rules.v6:/etc/iptables/rules.v6:ro net: /run/netns/sshd + - name: create-ssh-keys + image: nemunaire/rsync:a3d76b2dd0a9ad73be44dc77ad765b20d96a3285 + command: ["/bin/sh", "-c", "touch /etc/ssh/sshd_config && ssh-keygen -A"] + binds: + - /var/lib/fic/ssh:/etc/ssh + runtime: + mkdir: + - /var/lib/fic/ssh + services: # - name: getty # image: linuxkit/getty:bae9e3d4861173bacf78f14a4fe44997a430d13b @@ -257,7 +266,6 @@ services: - /var/lib/fic/files - /var/lib/fic/pki - /var/lib/fic/settingsdist - - /var/lib/fic/ssh - /var/lib/fic/submissions - /var/lib/fic/teams From c28d974105b3c766daa930e9da49f7b5fed0052c Mon Sep 17 00:00:00 2001 From: Pierre-Olivier Mercier Date: Fri, 24 Jan 2025 19:10:37 +0100 Subject: [PATCH 05/18] fickit: Update images --- fickit-prepare.yml | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/fickit-prepare.yml b/fickit-prepare.yml index 64f7b3ba..b8472acb 100644 --- a/fickit-prepare.yml +++ b/fickit-prepare.yml @@ -7,9 +7,9 @@ kernel: init: - nemunaire/mdadm:04814350d71ba9417e1f861be1685de26adf7a67 - nemunaire/syslinux:086f221f281d577d300949aa1094fb20c5cd90dc - - linuxkit/format:3c858f0cf42a2b14441bfb5c266b78f14d2b75a4 - - linuxkit/dm-crypt:19fa6affe9da03afc91694e36d72a4924c65a0e0 - - linuxkit/metadata:f35b5aafc7d19bb6a44a900840727902dad78e44 + - linuxkit/format:8f487d728959192289e0783784fc2b185eadbc82 + - linuxkit/dm-crypt:ad2a05dcffa28ef809a61aa27ba230c82f02f603 + - linuxkit/metadata:83cda7b43112b201613084ea8b7fab585b6e5549 - alpine:latest files: From 407b67f4c22402a0627b4ec0e152f8cbe8c20705 Mon Sep 17 00:00:00 2001 From: Pierre-Olivier Mercier Date: Fri, 24 Jan 2025 19:10:58 +0100 Subject: [PATCH 06/18] sync: Ensure placeholder and raw are not the same --- admin/sync/exercice_keys.go | 17 +++++++++++++---- 1 file changed, 13 insertions(+), 4 deletions(-) diff --git a/admin/sync/exercice_keys.go b/admin/sync/exercice_keys.go index 8404df86..d4a88f3c 100644 --- a/admin/sync/exercice_keys.go +++ b/admin/sync/exercice_keys.go @@ -279,6 +279,7 @@ func buildKeyFlag(exercice *fic.Exercice, flag ExerciceFlag, flagline int, defau } type importFlag struct { + origin ExerciceFlag Line int Flag fic.Flag JustifyOf *fic.MCQ_entry @@ -392,8 +393,9 @@ func buildExerciceFlag(i Importer, exercice *fic.Exercice, flag ExerciceFlag, nl errs = multierr.Append(errs, berrs) if addedFlag != nil { ret = append(ret, importFlag{ - Line: nline + 1, - Flag: addedFlag, + origin: flag, + 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" { @@ -401,6 +403,7 @@ func buildExerciceFlag(i Importer, exercice *fic.Exercice, flag ExerciceFlag, nl errs = multierr.Append(errs, berrs) if addedFlag != nil { ret = append(ret, importFlag{ + origin: flag, Line: nline + 1, Flag: *addedFlag, Choices: choices, @@ -462,6 +465,7 @@ func buildExerciceFlag(i Importer, exercice *fic.Exercice, flag ExerciceFlag, nl errs = multierr.Append(errs, berrs) if addedFlag != nil { ret = append(ret, importFlag{ + origin: flag, Line: nline + 1, Flag: *addedFlag, JustifyOf: entry, @@ -479,8 +483,9 @@ func buildExerciceFlag(i Importer, exercice *fic.Exercice, flag ExerciceFlag, nl } ret = append([]importFlag{importFlag{ - Line: nline + 1, - Flag: &addedFlag, + origin: flag, + Line: nline + 1, + Flag: &addedFlag, }}, ret...) } return @@ -570,6 +575,10 @@ func CheckExerciceFlags(i Importer, exercice *fic.Exercice, files []string, exce if int64(fk.ChoicesCost) >= exercice.Gain { errs = multierr.Append(errs, NewFlagError(exercice, nil, flag.Line, fmt.Errorf("flag's choice_cost is higher than exercice gain"))) } + + if raw, ok := flag.origin.Raw.(string); ok && raw == fk.Placeholder { + errs = multierr.Append(errs, NewFlagError(exercice, nil, flag.Line, fmt.Errorf("flag's placeholder and raw are identical"))) + } } // Check dependency loop From 24686a6a24bda8d194aa064ed7aee3b961ada939 Mon Sep 17 00:00:00 2001 From: Pierre-Olivier Mercier Date: Fri, 24 Jan 2025 23:47:35 +0100 Subject: [PATCH 07/18] admin: Fix check file on disk for compressed files --- admin/static/views/file-list.html | 8 ++++---- libfic/file.go | 19 ++++++++++++++++--- 2 files changed, 20 insertions(+), 7 deletions(-) diff --git a/admin/static/views/file-list.html b/admin/static/views/file-list.html index cd0d36a7..83a3242c 100644 --- a/admin/static/views/file-list.html +++ b/admin/static/views/file-list.html @@ -30,13 +30,13 @@
- + {{ file[field] }} - - {{ file.checksum | bto16 }} -
{{ file.checksum_shown | bto16 }}
+ +
{{ file.checksum | bto16 }}
+
{{ file.checksum_shown | bto16 }}
diff --git a/libfic/file.go b/libfic/file.go index 4e5bf37f..d39bb6b0 100644 --- a/libfic/file.go +++ b/libfic/file.go @@ -392,7 +392,12 @@ func (f *EFile) GetDepends() ([]Flag, error) { // CheckFileOnDisk recalculates the hash of the file on disk. func (f *EFile) CheckFileOnDisk() error { - if _, size, err := checkFileHash(path.Join(FilesDir, f.Path), f.Checksum); err != nil { + firstChecksum := f.Checksum + if len(f.ChecksumShown) > 0 { + firstChecksum = f.ChecksumShown + } + + if _, size, err := checkFileHash(path.Join(FilesDir, f.Path), firstChecksum); size > 0 && err != nil { return err } else if size == 0 { if _, _, err := checkFileHash(path.Join(FilesDir, f.Path+".gz"), f.Checksum); err != nil { @@ -400,9 +405,17 @@ func (f *EFile) CheckFileOnDisk() error { } else { return nil } - } else { - return nil + } else if err != nil { + return err } + + if _, err := os.Stat(path.Join(FilesDir, f.Path+".gz")); !os.IsNotExist(err) { + if _, _, err = checkFileHash(path.Join(FilesDir, f.Path+".gz"), f.Checksum); err != nil { + return err + } + } + + return nil } // GunzipFileOnDisk gunzip a compressed file. From 57c3cd8fd65a001024032a89967f28b82bd32ad6 Mon Sep 17 00:00:00 2001 From: Pierre-Olivier Mercier Date: Fri, 24 Jan 2025 23:48:14 +0100 Subject: [PATCH 08/18] admin: Fix mcq entry update --- libfic/mcq.go | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/libfic/mcq.go b/libfic/mcq.go index 82315479..04bf3fd9 100644 --- a/libfic/mcq.go +++ b/libfic/mcq.go @@ -207,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 = ?", n.Label, n.Response, n.Id); err != nil { + if res, err := DBExec("UPDATE mcq_entries SET label = ?, response = ? WHERE id_mcq_entry = ?", n.Label, n.Response, n.Id); err != nil { return 0, err } else if nb, err := res.RowsAffected(); err != nil { return 0, err From ad7489e5584d5f3bf952ff8abd25dcb79fc3a7dd Mon Sep 17 00:00:00 2001 From: Pierre-Olivier Mercier Date: Fri, 24 Jan 2025 23:49:00 +0100 Subject: [PATCH 09/18] admin: Start compute flag stats --- admin/api/exercice.go | 29 ++++++++++++++++++++++++++ admin/static/js/app.js | 9 ++++++++ admin/static/views/exercice-flags.html | 11 +++++++++- 3 files changed, 48 insertions(+), 1 deletion(-) diff --git a/admin/api/exercice.go b/admin/api/exercice.go index cfdb450d..c4fdaed9 100644 --- a/admin/api/exercice.go +++ b/admin/api/exercice.go @@ -62,6 +62,7 @@ func declareExercicesRoutes(router *gin.RouterGroup) { apiFlagsRoutes.POST("/try", tryExerciceFlag) apiFlagsRoutes.DELETE("/", deleteExerciceFlag) apiFlagsRoutes.GET("/dependancies", showExerciceFlagDeps) + apiFlagsRoutes.GET("/statistics", showExerciceFlagStats) apiFlagsRoutes.GET("/choices/", listFlagChoices) apiFlagsChoicesRoutes := apiExercicesRoutes.Group("/choices/:cid") apiFlagsChoicesRoutes.Use(FlagChoiceHandler) @@ -852,6 +853,34 @@ 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, tries, nteams int64 + + for _, hline := range history { + if hline["kind"].(string) == "flag_found" { + if *hline["secondary"].(*int) == flag.Id { + completed += 1 + } + } + } + + c.JSON(http.StatusOK, gin.H{ + "completed": completed, + "tries": tries, + "nteams": nteams, + }) +} + func tryExerciceFlag(c *gin.Context) { flag := c.MustGet("flag-key").(*fic.FlagKey) diff --git a/admin/static/js/app.js b/admin/static/js/app.js index 0753bbb0..2fa150f4 100644 --- a/admin/static/js/app.js +++ b/admin/static/js/app.js @@ -348,6 +348,9 @@ angular.module("FICApp") .factory("ExerciceFlagDeps", function ($resource) { return $resource("api/exercices/:exerciceId/flags/:flagId/dependancies", { exerciceId: '@idExercice', flagId: '@id' }) }) + .factory("ExerciceFlagStats", function ($resource) { + return $resource("api/exercices/:exerciceId/flags/:flagId/statistics", { exerciceId: '@idExercice', flagId: '@id' }) + }) .factory("ExerciceMCQFlag", function ($resource) { return $resource("api/exercices/:exerciceId/quiz/:mcqId", { exerciceId: '@idExercice', mcqId: '@id' }, { update: { method: 'PUT' } @@ -2345,6 +2348,12 @@ angular.module("FICApp") } }) + .controller("ExerciceFlagStatsController", function ($scope, $routeParams, ExerciceFlagStats) { + $scope.init = function (flag) { + $scope.stats = ExerciceFlagStats.get({ exerciceId: $routeParams.exerciceId, flagId: flag.id }); + } + }) + .controller("ExerciceMCQFlagsController", function ($scope, ExerciceMCQFlag, $routeParams, $rootScope) { $scope.quiz = ExerciceMCQFlag.query({ exerciceId: $routeParams.exerciceId }); diff --git a/admin/static/views/exercice-flags.html b/admin/static/views/exercice-flags.html index 3caf3add..b23556ca 100644 --- a/admin/static/views/exercice-flags.html +++ b/admin/static/views/exercice-flags.html @@ -73,12 +73,21 @@
- Dépendances : + Dépendances :
sans
+
+
+ Statistiques +
    +
  • Validés : {{ stats["completed"] }}
  • +
  • Tentés : {{ stats["tries"] }}
  • +
  • Équipes : {{ stats["nteams"] }}
  • +
+