From a28f108b8a67db4a6e454a7cfafbeb446f88bb96 Mon Sep 17 00:00:00 2001 From: Pierre-Olivier Mercier Date: Mon, 31 Oct 2022 18:52:29 +0100 Subject: [PATCH] db: Add a published attribute, filled by challenge.txt --- admin/api/file.go | 16 +++++++++++++-- admin/static/views/exercice.html | 4 ++++ admin/sync/exercice_defines.go | 21 ++++++++++++++++++++ admin/sync/exercice_files.go | 14 ++++++++++++- libfic/db.go | 1 + libfic/file.go | 34 ++++++++++++++++++-------------- libfic/team.go | 4 +++- 7 files changed, 75 insertions(+), 19 deletions(-) diff --git a/admin/api/file.go b/admin/api/file.go index d609b6a0..60ed0ce8 100644 --- a/admin/api/file.go +++ b/admin/api/file.go @@ -5,6 +5,7 @@ import ( "fmt" "log" "net/http" + "path/filepath" "strconv" "srs.epita.fr/fic-server/admin/sync" @@ -166,8 +167,14 @@ func createExerciceFile(c *gin.Context) { return } + paramsFiles, err := sync.GetExerciceFilesParams(sync.GlobalImporter, exercice.(*fic.Exercice)) + if err != nil { + c.AbortWithStatusJSON(http.StatusInternalServerError, gin.H{"errmsg": err.Error()}) + return + } + var uf uploadedFile - err := c.ShouldBindJSON(&uf) + err = c.ShouldBindJSON(&uf) if err != nil { c.AbortWithStatusJSON(http.StatusBadRequest, gin.H{"errmsg": err.Error()}) return @@ -178,7 +185,12 @@ func createExerciceFile(c *gin.Context) { if digest, err := hex.DecodeString(uf.Digest); err != nil { return nil, err } else { - return exercice.(*fic.Exercice).ImportFile(filePath, origin, digest, nil) + published := true + if f, exists := paramsFiles[filepath.Base(filePath)]; exists { + published = !f.Hidden + } + + return exercice.(*fic.Exercice).ImportFile(filePath, origin, digest, nil, published) } }) if err != nil { diff --git a/admin/static/views/exercice.html b/admin/static/views/exercice.html index a0977e02..5c60cf42 100644 --- a/admin/static/views/exercice.html +++ b/admin/static/views/exercice.html @@ -103,6 +103,10 @@ Taille : {{ file.size | size }} ‐ BLAKE2b : {{ file.checksum | cksum }} +
+ + +
Dépend de la validation de : aucun flag diff --git a/admin/sync/exercice_defines.go b/admin/sync/exercice_defines.go index d8fdaa0d..60ff08c9 100644 --- a/admin/sync/exercice_defines.go +++ b/admin/sync/exercice_defines.go @@ -28,6 +28,12 @@ type ExerciceUnlockFile struct { Filename string `toml:",omitempty"` } +// ExerciceFile defines attributes on files. +type ExerciceFile struct { + Filename string `toml:",omitempty"` + Hidden bool `toml:",omitempty"` +} + // ExerciceFlag holds informations about one flag. type ExerciceFlag struct { Id int64 @@ -66,6 +72,7 @@ type ExerciceFlagChoice struct { type ExerciceParams struct { Gain int64 Tags []string + Files []ExerciceFile `toml:"file"` Hints []ExerciceHintParams `toml:"hint"` Dependencies []ExerciceDependency `toml:"depend"` Flags []ExerciceFlag `toml:"flag"` @@ -127,3 +134,17 @@ func getExerciceParams(i Importer, exercice *fic.Exercice) (params ExerciceParam } return } + +func GetExerciceFilesParams(i Importer, exercice *fic.Exercice) (map[string]ExerciceFile, error) { + params, _, err := parseExerciceParams(i, exercice.Path) + if err != nil { + return nil, err + } + + paramsFiles := map[string]ExerciceFile{} + for _, f := range params.Files { + paramsFiles[f.Filename] = f + } + + return paramsFiles, nil +} diff --git a/admin/sync/exercice_files.go b/admin/sync/exercice_files.go index dc3bdf21..1e04d0aa 100644 --- a/admin/sync/exercice_files.go +++ b/admin/sync/exercice_files.go @@ -134,6 +134,12 @@ func SyncExerciceFiles(i Importer, exercice *fic.Exercice, exceptions *CheckExce errs = append(errs, err) } + paramsFiles, err := GetExerciceFilesParams(i, exercice) + if err != nil { + errs = append(errs, NewChallengeTxtError(exercice, 0, err)) + return + } + files, digests, berrs := BuildFilesListInto(i, exercice, "files") errs = append(errs, berrs...) @@ -147,7 +153,13 @@ func SyncExerciceFiles(i Importer, exercice *fic.Exercice, exceptions *CheckExce digest_shown = d } } - return exercice.ImportFile(filePath, origin, digests[fname], digest_shown) + + published := true + if f, exists := paramsFiles[fname]; exists { + published = !f.Hidden + } + + return exercice.ImportFile(filePath, origin, digests[fname], digest_shown, published) }); err != nil { errs = append(errs, NewFileError(exercice, fname, err)) continue diff --git a/libfic/db.go b/libfic/db.go index c31a5517..c1a52994 100644 --- a/libfic/db.go +++ b/libfic/db.go @@ -170,6 +170,7 @@ CREATE TABLE IF NOT EXISTS exercice_files( cksum BINARY(64) NOT NULL, cksum_shown BINARY(64), size BIGINT UNSIGNED NOT NULL, + published BOOLEAN NOT NULL DEFAULT 1, FOREIGN KEY(id_exercice) REFERENCES exercices(id_exercice) ) DEFAULT CHARACTER SET = utf8mb4 COLLATE = utf8mb4_unicode_ci; `); err != nil { diff --git a/libfic/file.go b/libfic/file.go index 615477cd..56cbdea4 100644 --- a/libfic/file.go +++ b/libfic/file.go @@ -44,6 +44,8 @@ type EFile struct { ChecksumShown []byte `json:"checksum_shown"` // Size contains the cached size of the file Size int64 `json:"size"` + // Published indicates if the file should be shown or not + Published bool `json:"published"` } // NewDummyFile creates an EFile, without any link to an actual Exercice File. @@ -58,12 +60,13 @@ func (e *Exercice) NewDummyFile(origin string, dest string, checksum []byte, siz Checksum: checksum, ChecksumShown: nil, Size: size, + Published: true, } } // GetFiles returns a list of all files living in the database. func GetFiles() ([]*EFile, error) { - if rows, err := DBQuery("SELECT id_file, id_exercice, origin, path, name, cksum, cksum_shown, size FROM exercice_files"); err != nil { + if rows, err := DBQuery("SELECT id_file, id_exercice, origin, path, name, cksum, cksum_shown, size, published FROM exercice_files"); err != nil { return nil, err } else { defer rows.Close() @@ -71,7 +74,7 @@ func GetFiles() ([]*EFile, error) { files := []*EFile{} for rows.Next() { f := &EFile{} - if err := rows.Scan(&f.Id, &f.IdExercice, &f.origin, &f.Path, &f.Name, &f.Checksum, &f.ChecksumShown, &f.Size); err != nil { + if err := rows.Scan(&f.Id, &f.IdExercice, &f.origin, &f.Path, &f.Name, &f.Checksum, &f.ChecksumShown, &f.Size, &f.Published); err != nil { return nil, err } files = append(files, f) @@ -87,13 +90,13 @@ func GetFiles() ([]*EFile, error) { // GetFile retrieves the file with the given id. func GetFile(id int64) (f *EFile, err error) { f = &EFile{} - err = DBQueryRow("SELECT id_file, origin, path, name, cksum, cksum_shown, size FROM exercice_files WHERE id_file = ?", id).Scan(&f.Id, &f.origin, &f.Path, &f.Name, &f.Checksum, &f.ChecksumShown, &f.Size) + err = DBQueryRow("SELECT id_file, origin, path, name, cksum, cksum_shown, size, published FROM exercice_files WHERE id_file = ?", id).Scan(&f.Id, &f.origin, &f.Path, &f.Name, &f.Checksum, &f.ChecksumShown, &f.Size, &f.Published) return } func (e *Exercice) GetFile(id int64) (f *EFile, err error) { f = &EFile{} - err = DBQueryRow("SELECT id_file, origin, path, name, cksum, cksum_shown, size FROM exercice_files WHERE id_file = ? AND id_exercice = ?", id, e.Id).Scan(&f.Id, &f.origin, &f.Path, &f.Name, &f.Checksum, &f.ChecksumShown, &f.Size) + err = DBQueryRow("SELECT id_file, origin, path, name, cksum, cksum_shown, size, published FROM exercice_files WHERE id_file = ? AND id_exercice = ?", id, e.Id).Scan(&f.Id, &f.origin, &f.Path, &f.Name, &f.Checksum, &f.ChecksumShown, &f.Size, &f.Published) return } @@ -102,7 +105,7 @@ func GetFileByPath(path string) (*EFile, error) { path = strings.TrimPrefix(path, FilesDir) f := &EFile{} - if err := DBQueryRow("SELECT id_file, origin, path, id_exercice, name, cksum, cksum_shown, size FROM exercice_files WHERE path = ?", path).Scan(&f.Id, &f.origin, &f.Path, &f.IdExercice, &f.Name, &f.Checksum, &f.ChecksumShown, &f.Size); err != nil { + if err := DBQueryRow("SELECT id_file, origin, path, id_exercice, name, cksum, cksum_shown, size, published FROM exercice_files WHERE path = ?", path).Scan(&f.Id, &f.origin, &f.Path, &f.IdExercice, &f.Name, &f.Checksum, &f.ChecksumShown, &f.Size, &f.Published); err != nil { return f, err } @@ -114,14 +117,14 @@ func (e *Exercice) GetFileByFilename(filename string) (f *EFile, err error) { filename = path.Base(filename) f = &EFile{} - err = DBQueryRow("SELECT id_file, origin, path, id_exercice, name, cksum, cksum_shown, size FROM exercice_files WHERE id_exercice = ? AND origin LIKE ?", e.Id, "%/"+filename).Scan(&f.Id, &f.origin, &f.Path, &f.IdExercice, &f.Name, &f.Checksum, &f.ChecksumShown, &f.Size) + err = DBQueryRow("SELECT id_file, origin, path, id_exercice, name, cksum, cksum_shown, size, published FROM exercice_files WHERE id_exercice = ? AND origin LIKE ?", e.Id, "%/"+filename).Scan(&f.Id, &f.origin, &f.Path, &f.IdExercice, &f.Name, &f.Checksum, &f.ChecksumShown, &f.Size, &f.Published) return } // GetFiles returns a list of files coming with the challenge. func (e *Exercice) GetFiles() ([]*EFile, error) { - if rows, err := DBQuery("SELECT id_file, origin, path, name, cksum, cksum_shown, size FROM exercice_files WHERE id_exercice = ?", e.Id); err != nil { + if rows, err := DBQuery("SELECT id_file, origin, path, name, cksum, cksum_shown, size, published FROM exercice_files WHERE id_exercice = ?", e.Id); err != nil { return nil, err } else { defer rows.Close() @@ -130,7 +133,7 @@ func (e *Exercice) GetFiles() ([]*EFile, error) { for rows.Next() { f := &EFile{} f.IdExercice = e.Id - if err := rows.Scan(&f.Id, &f.origin, &f.Path, &f.Name, &f.Checksum, &f.ChecksumShown, &f.Size); err != nil { + if err := rows.Scan(&f.Id, &f.origin, &f.Path, &f.Name, &f.Checksum, &f.ChecksumShown, &f.Size, &f.Published); err != nil { return nil, err } files = append(files, f) @@ -148,7 +151,7 @@ func (e *Exercice) GetFileByPath(path string) (*EFile, error) { path = strings.TrimPrefix(path, FilesDir) f := &EFile{} - if err := DBQueryRow("SELECT id_file, origin, path, name, cksum, cksum_shown, size FROM exercice_files WHERE id_exercice = ? AND path = ?", e.Id, path).Scan(&f.Id, &f.origin, &f.Path, &f.Name, &f.Checksum, &f.ChecksumShown, &f.Size); err != nil { + if err := DBQueryRow("SELECT id_file, origin, path, name, cksum, cksum_shown, size, published FROM exercice_files WHERE id_exercice = ? AND path = ?", e.Id, path).Scan(&f.Id, &f.origin, &f.Path, &f.Name, &f.Checksum, &f.ChecksumShown, &f.Size, &f.Published); err != nil { return nil, err } @@ -229,13 +232,13 @@ func checkFileHash(filePath string, digest []byte) (dgst []byte, size int64, err } // ImportFile registers (ou updates if it already exists in database) the file in database. -func (e *Exercice) ImportFile(filePath string, origin string, digest []byte, digestshown []byte) (interface{}, error) { +func (e *Exercice) ImportFile(filePath string, origin string, digest []byte, digestshown []byte, published bool) (interface{}, error) { if result512, size, err := checkFileHash(filePath, digest); !OptionalDigest && err != nil { return EFile{}, err } else { dPath := strings.TrimPrefix(filePath, FilesDir) if f, err := e.GetFileByPath(dPath); err != nil { - return e.AddFile(dPath, origin, path.Base(filePath), result512, digestshown, size) + return e.AddFile(dPath, origin, path.Base(filePath), result512, digestshown, size, published) } else { // Don't need to update Path and Name, because they are related to dPath @@ -244,6 +247,7 @@ func (e *Exercice) ImportFile(filePath string, origin string, digest []byte, dig f.Checksum = result512 f.ChecksumShown = digestshown f.Size = size + f.Published = published if _, err := f.Update(); err != nil { return nil, err @@ -255,19 +259,19 @@ func (e *Exercice) ImportFile(filePath string, origin string, digest []byte, dig } // AddFile creates and fills a new struct File and registers it into the database. -func (e *Exercice) AddFile(path string, origin string, name string, checksum []byte, checksumshown []byte, size int64) (*EFile, error) { - if res, err := DBExec("INSERT INTO exercice_files (id_exercice, origin, path, name, cksum, cksum_shown, size) VALUES (?, ?, ?, ?, ?, ?, ?)", e.Id, origin, path, name, checksum, checksumshown, size); err != nil { +func (e *Exercice) AddFile(path string, origin string, name string, checksum []byte, checksumshown []byte, size int64, published bool) (*EFile, error) { + if res, err := DBExec("INSERT INTO exercice_files (id_exercice, origin, path, name, cksum, cksum_shown, size, published) VALUES (?, ?, ?, ?, ?, ?, ?, ?)", e.Id, origin, path, name, checksum, checksumshown, size, published); err != nil { return nil, err } else if fid, err := res.LastInsertId(); err != nil { return nil, err } else { - return &EFile{fid, origin, path, e.Id, name, checksum, checksumshown, size}, nil + return &EFile{fid, origin, path, e.Id, name, checksum, checksumshown, size, published}, nil } } // Update applies modifications back to the database. func (f *EFile) Update() (int64, error) { - if res, err := DBExec("UPDATE exercice_files SET id_exercice = ?, origin = ?, path = ?, name = ?, cksum = ?, cksum_shown = ?, size = ? WHERE id_file = ?", f.IdExercice, f.origin, f.Path, f.Name, f.Checksum, f.ChecksumShown, f.Size, f.Id); err != nil { + if res, err := DBExec("UPDATE exercice_files SET id_exercice = ?, origin = ?, path = ?, name = ?, cksum = ?, cksum_shown = ?, size = ?, published = ? WHERE id_file = ?", f.IdExercice, f.origin, f.Path, f.Name, f.Checksum, f.ChecksumShown, f.Size, f.Published, f.Id); err != nil { return 0, err } else if nb, err := res.RowsAffected(); err != nil { return 0, err diff --git a/libfic/team.go b/libfic/team.go index 7b1b4ea7..25c3cffe 100644 --- a/libfic/team.go +++ b/libfic/team.go @@ -152,7 +152,9 @@ func (t *Team) HasAccess(e *Exercice) bool { // CanDownload checks if the Team has access to the given file. func (t *Team) CanDownload(f *EFile) bool { - if deps, err := f.GetDepends(); err != nil { + if !f.Published { + return false + } else if deps, err := f.GetDepends(); err != nil { log.Printf("Unable to retrieve file dependencies: %s\n", err) return false } else {