Rename Exercice's Keys as Flags
This commit is contained in:
parent
f36e1c4e4d
commit
d21f3b0b83
18 changed files with 252 additions and 252 deletions
16
libfic/db.go
16
libfic/db.go
|
|
@ -156,8 +156,8 @@ CREATE TABLE IF NOT EXISTS exercice_hints(
|
|||
return err
|
||||
}
|
||||
if _, err := db.Exec(`
|
||||
CREATE TABLE IF NOT EXISTS exercice_keys(
|
||||
id_key INTEGER NOT NULL PRIMARY KEY AUTO_INCREMENT,
|
||||
CREATE TABLE IF NOT EXISTS exercice_flags(
|
||||
id_flag INTEGER NOT NULL PRIMARY KEY AUTO_INCREMENT,
|
||||
id_exercice INTEGER NOT NULL,
|
||||
type VARCHAR(255) NOT NULL,
|
||||
help VARCHAR(255) NOT NULL,
|
||||
|
|
@ -171,9 +171,9 @@ CREATE TABLE IF NOT EXISTS exercice_keys(
|
|||
if _, err := db.Exec(`
|
||||
CREATE TABLE IF NOT EXISTS exercice_files_deps(
|
||||
id_file INTEGER NOT NULL,
|
||||
id_key INTEGER NOT NULL,
|
||||
id_flag INTEGER NOT NULL,
|
||||
FOREIGN KEY(id_file) REFERENCES exercice_files(id_file),
|
||||
FOREIGN KEY(id_key) REFERENCES exercice_keys(id_key)
|
||||
FOREIGN KEY(id_flag) REFERENCES exercice_flags(id_flag)
|
||||
) DEFAULT CHARACTER SET = utf8 COLLATE = utf8_bin;
|
||||
`); err != nil {
|
||||
return err
|
||||
|
|
@ -212,12 +212,12 @@ CREATE TABLE IF NOT EXISTS mcq_found(
|
|||
return err
|
||||
}
|
||||
if _, err := db.Exec(`
|
||||
CREATE TABLE IF NOT EXISTS key_found(
|
||||
id_key INTEGER NOT NULL,
|
||||
CREATE TABLE IF NOT EXISTS flag_found(
|
||||
id_flag INTEGER NOT NULL,
|
||||
id_team INTEGER NOT NULL,
|
||||
time TIMESTAMP NOT NULL,
|
||||
CONSTRAINT uc_found UNIQUE (id_key,id_team),
|
||||
FOREIGN KEY(id_key) REFERENCES exercice_keys(id_key),
|
||||
CONSTRAINT uc_found UNIQUE (id_flag,id_team),
|
||||
FOREIGN KEY(id_flag) REFERENCES exercice_flags(id_flag),
|
||||
FOREIGN KEY(id_team) REFERENCES teams(id_team)
|
||||
) DEFAULT CHARACTER SET = utf8mb4 COLLATE = utf8mb4_unicode_ci;
|
||||
`); err != nil {
|
||||
|
|
|
|||
|
|
@ -260,15 +260,15 @@ func (e Exercice) TriedCount() 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(respkeys map[string]string, respmcq map[int64]bool, t Team) (bool, error) {
|
||||
func (e Exercice) CheckResponse(respflags map[string]string, respmcq map[int64]bool, t Team) (bool, error) {
|
||||
if err := e.NewTry(t); err != nil {
|
||||
return false, err
|
||||
} else if keys, err := e.GetKeys(); err != nil {
|
||||
} else if flags, err := e.GetFlags(); err != nil {
|
||||
return false, err
|
||||
} else if mcqs, err := e.GetMCQ(); err != nil {
|
||||
return false, err
|
||||
} else if len(keys) < 1 && len(mcqs) < 1 {
|
||||
return true, errors.New("Exercice with no key registered")
|
||||
} else if len(flags) < 1 && len(mcqs) < 1 {
|
||||
return true, errors.New("Exercice with no flag registered")
|
||||
} else {
|
||||
valid := true
|
||||
diff := 0
|
||||
|
|
@ -292,16 +292,16 @@ func (e Exercice) CheckResponse(respkeys map[string]string, respmcq map[int64]bo
|
|||
}
|
||||
}
|
||||
|
||||
// Check keys
|
||||
for _, key := range keys {
|
||||
if res, ok := respkeys[key.Label]; !ok {
|
||||
// Check flags
|
||||
for _, flag := range flags {
|
||||
if res, ok := respflags[flag.Label]; !ok {
|
||||
valid = false
|
||||
} else if !key.Check(res) {
|
||||
if !PartialValidation || t.HasPartiallySolved(key) == nil {
|
||||
} else if !flag.Check(res) {
|
||||
if !PartialValidation || t.HasPartiallySolved(flag) == nil {
|
||||
valid = false
|
||||
}
|
||||
} else {
|
||||
key.FoundBy(t)
|
||||
flag.FoundBy(t)
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -272,25 +272,25 @@ func (f EFile) GetOrigin() string {
|
|||
}
|
||||
|
||||
// AddDepend insert a new dependency to a given flag.
|
||||
func (f EFile) AddDepend(k Key) (err error) {
|
||||
_, err = DBExec("INSERT INTO exercice_files_deps (id_file, id_key) VALUES (?, ?)", f.Id, k.Id)
|
||||
func (f EFile) AddDepend(k Flag) (err error) {
|
||||
_, err = DBExec("INSERT INTO exercice_files_deps (id_file, id_flag) VALUES (?, ?)", f.Id, k.Id)
|
||||
return
|
||||
}
|
||||
|
||||
// GetDepends retrieve the flag's dependency list.
|
||||
func (f EFile) GetDepends() ([]Key, error) {
|
||||
if rows, err := DBQuery("SELECT id_key FROM exercice_files_deps WHERE id_file = ?", f.Id); err != nil {
|
||||
func (f EFile) GetDepends() ([]Flag, error) {
|
||||
if rows, err := DBQuery("SELECT id_flag FROM exercice_files_deps WHERE id_file = ?", f.Id); err != nil {
|
||||
return nil, err
|
||||
} else {
|
||||
defer rows.Close()
|
||||
|
||||
var deps = make([]Key, 0)
|
||||
var deps = make([]Flag, 0)
|
||||
for rows.Next() {
|
||||
var d int64
|
||||
if err := rows.Scan(&d); err != nil {
|
||||
return nil, err
|
||||
}
|
||||
deps = append(deps, Key{d, f.IdExercice, "", "", false, []byte{}})
|
||||
deps = append(deps, Flag{d, f.IdExercice, "", "", false, []byte{}})
|
||||
}
|
||||
if err := rows.Err(); err != nil {
|
||||
return nil, err
|
||||
|
|
|
|||
129
libfic/flag.go
Normal file
129
libfic/flag.go
Normal file
|
|
@ -0,0 +1,129 @@
|
|||
package fic
|
||||
|
||||
import (
|
||||
"time"
|
||||
|
||||
"golang.org/x/crypto/blake2b"
|
||||
)
|
||||
|
||||
|
||||
// Flag represents a flag's challenge, stored as hash.
|
||||
type Flag struct {
|
||||
Id int64 `json:"id"`
|
||||
// IdExercice is the identifier of the underlying challenge
|
||||
IdExercice int64 `json:"idExercice"`
|
||||
// Label is the title of the flag as displayed to players
|
||||
Label string `json:"label"`
|
||||
// Help is a small piece of text that aims to add useful information like flag format, ...
|
||||
Help string `json:"help"`
|
||||
// IgnoreCase indicates if the case is sensitive to case or not
|
||||
IgnoreCase bool `json:"ignorecase"`
|
||||
// Checksum is the expected hashed flag
|
||||
Checksum []byte `json:"value"`
|
||||
}
|
||||
|
||||
// GetFlags returns a list of flags comming with the challenge.
|
||||
func (e Exercice) GetFlags() ([]Flag, error) {
|
||||
if rows, err := DBQuery("SELECT id_flag, id_exercice, type, help, ignorecase, cksum FROM exercice_flags WHERE id_exercice = ?", e.Id); err != nil {
|
||||
return nil, err
|
||||
} else {
|
||||
defer rows.Close()
|
||||
|
||||
var flags = make([]Flag, 0)
|
||||
for rows.Next() {
|
||||
var k Flag
|
||||
k.IdExercice = e.Id
|
||||
|
||||
if err := rows.Scan(&k.Id, &k.IdExercice, &k.Label, &k.Help, &k.IgnoreCase, &k.Checksum); err != nil {
|
||||
return nil, err
|
||||
}
|
||||
flags = append(flags, k)
|
||||
}
|
||||
if err := rows.Err(); err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
return flags, nil
|
||||
}
|
||||
}
|
||||
|
||||
// getHashedFlag calculates the expected checksum for the given raw_value.
|
||||
func getHashedFlag(raw_value string) [blake2b.Size]byte {
|
||||
hash := blake2b.Sum512([]byte(raw_value))
|
||||
return hash
|
||||
}
|
||||
|
||||
// AddRawFlag creates and fills a new struct Flag, from a non-hashed flag, and registers it into the database.
|
||||
func (e Exercice) AddRawFlag(name string, help string, ignorecase bool, raw_value string) (Flag, error) {
|
||||
hash := getHashedFlag(raw_value)
|
||||
return e.AddFlag(name, help, ignorecase, hash[:])
|
||||
}
|
||||
|
||||
// AddFlag creates and fills a new struct Flag, from a hashed flag, and registers it into the database.
|
||||
func (e Exercice) AddFlag(name string, help string, ignorecase bool, checksum []byte) (Flag, error) {
|
||||
if res, err := DBExec("INSERT INTO exercice_flags (id_exercice, type, help, ignorecase, cksum) VALUES (?, ?, ?, ?, ?)", e.Id, name, help, ignorecase, checksum); err != nil {
|
||||
return Flag{}, err
|
||||
} else if kid, err := res.LastInsertId(); err != nil {
|
||||
return Flag{}, err
|
||||
} else {
|
||||
return Flag{kid, e.Id, name, help, ignorecase, checksum}, nil
|
||||
}
|
||||
}
|
||||
|
||||
// Update applies modifications back to the database.
|
||||
func (k Flag) Update() (int64, error) {
|
||||
if res, err := DBExec("UPDATE exercice_flags SET id_exercice = ?, type = ?, help = ?, ignorecase = ?, cksum = ? WHERE id_flag = ?", k.IdExercice, k.Label, k.Help, k.IgnoreCase, k.Checksum, k.Id); err != nil {
|
||||
return 0, err
|
||||
} else if nb, err := res.RowsAffected(); err != nil {
|
||||
return 0, err
|
||||
} else {
|
||||
return nb, err
|
||||
}
|
||||
}
|
||||
|
||||
// Delete the flag from the database.
|
||||
func (k Flag) Delete() (int64, error) {
|
||||
if _, err := DBExec("DELETE FROM exercice_files_deps WHERE id_flag = ?", k.Id); err != nil {
|
||||
return 0, err
|
||||
} else if res, err := DBExec("DELETE FROM exercice_flags WHERE id_flag = ?", k.Id); err != nil {
|
||||
return 0, err
|
||||
} else if nb, err := res.RowsAffected(); err != nil {
|
||||
return 0, err
|
||||
} else {
|
||||
return nb, err
|
||||
}
|
||||
}
|
||||
|
||||
// WipeFlags deletes flags coming with the challenge.
|
||||
func (e Exercice) WipeFlags() (int64, error) {
|
||||
if _, err := DBExec("DELETE FROM exercice_files_deps WHERE id_flag IN (SELECT id_flag FROM exercice_flags WHERE id_exercice = ?)", e.Id); err != nil {
|
||||
return 0, err
|
||||
} else if res, err := DBExec("DELETE FROM exercice_flags WHERE id_exercice = ?", e.Id); err != nil {
|
||||
return 0, err
|
||||
} else if nb, err := res.RowsAffected(); err != nil {
|
||||
return 0, err
|
||||
} else {
|
||||
return nb, err
|
||||
}
|
||||
}
|
||||
|
||||
// Check if the given val is the expected one for this flag.
|
||||
func (k Flag) Check(val string) bool {
|
||||
hash := getHashedFlag(val)
|
||||
if len(k.Checksum) != len(hash) {
|
||||
return false
|
||||
}
|
||||
|
||||
for i := range hash {
|
||||
if k.Checksum[i] != hash[i] {
|
||||
return false
|
||||
}
|
||||
}
|
||||
|
||||
return true
|
||||
}
|
||||
|
||||
// FoundBy registers in the database that the given Team solved the flag.
|
||||
func (k Flag) FoundBy(t Team) {
|
||||
DBExec("INSERT INTO flag_found (id_flag, id_team, time) VALUES (?, ?, ?)", k.Id, t.Id, time.Now())
|
||||
}
|
||||
129
libfic/key.go
129
libfic/key.go
|
|
@ -1,129 +0,0 @@
|
|||
package fic
|
||||
|
||||
import (
|
||||
"time"
|
||||
|
||||
"golang.org/x/crypto/blake2b"
|
||||
)
|
||||
|
||||
|
||||
// Key represents a flag's challenge, stored as hash.
|
||||
type Key struct {
|
||||
Id int64 `json:"id"`
|
||||
// IdExercice is the identifier of the underlying challenge
|
||||
IdExercice int64 `json:"idExercice"`
|
||||
// Label is the title of the flag as displayed to players
|
||||
Label string `json:"label"`
|
||||
// Help is a small piece of text that aims to add useful information like flag format, ...
|
||||
Help string `json:"help"`
|
||||
// IgnoreCase indicates if the case is sensitive to case or not
|
||||
IgnoreCase bool `json:"ignorecase"`
|
||||
// Checksum is the expected hashed flag
|
||||
Checksum []byte `json:"value"`
|
||||
}
|
||||
|
||||
// GetKeys returns a list of flags comming with the challenge.
|
||||
func (e Exercice) GetKeys() ([]Key, error) {
|
||||
if rows, err := DBQuery("SELECT id_key, id_exercice, type, help, ignorecase, cksum FROM exercice_keys WHERE id_exercice = ?", e.Id); err != nil {
|
||||
return nil, err
|
||||
} else {
|
||||
defer rows.Close()
|
||||
|
||||
var keys = make([]Key, 0)
|
||||
for rows.Next() {
|
||||
var k Key
|
||||
k.IdExercice = e.Id
|
||||
|
||||
if err := rows.Scan(&k.Id, &k.IdExercice, &k.Label, &k.Help, &k.IgnoreCase, &k.Checksum); err != nil {
|
||||
return nil, err
|
||||
}
|
||||
keys = append(keys, k)
|
||||
}
|
||||
if err := rows.Err(); err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
return keys, nil
|
||||
}
|
||||
}
|
||||
|
||||
// getHashedKey calculates the expected checksum for the given raw_value.
|
||||
func getHashedKey(raw_value string) [blake2b.Size]byte {
|
||||
hash := blake2b.Sum512([]byte(raw_value))
|
||||
return hash
|
||||
}
|
||||
|
||||
// AddRawKey creates and fills a new struct Key, from a non-hashed flag, and registers it into the database.
|
||||
func (e Exercice) AddRawKey(name string, help string, ignorecase bool, raw_value string) (Key, error) {
|
||||
hash := getHashedKey(raw_value)
|
||||
return e.AddKey(name, help, ignorecase, hash[:])
|
||||
}
|
||||
|
||||
// AddKey creates and fills a new struct Key, from a hashed flag, and registers it into the database.
|
||||
func (e Exercice) AddKey(name string, help string, ignorecase bool, checksum []byte) (Key, error) {
|
||||
if res, err := DBExec("INSERT INTO exercice_keys (id_exercice, type, help, ignorecase, cksum) VALUES (?, ?, ?, ?)", e.Id, name, help, ignorecase, checksum); err != nil {
|
||||
return Key{}, err
|
||||
} else if kid, err := res.LastInsertId(); err != nil {
|
||||
return Key{}, err
|
||||
} else {
|
||||
return Key{kid, e.Id, name, help, ignorecase, checksum}, nil
|
||||
}
|
||||
}
|
||||
|
||||
// Update applies modifications back to the database.
|
||||
func (k Key) Update() (int64, error) {
|
||||
if res, err := DBExec("UPDATE exercice_keys SET id_exercice = ?, type = ?, help = ?, ignorecase = ?, cksum = ? WHERE id_key = ?", k.IdExercice, k.Label, k.Help, k.Checksum, k.Id); err != nil {
|
||||
return 0, err
|
||||
} else if nb, err := res.RowsAffected(); err != nil {
|
||||
return 0, err
|
||||
} else {
|
||||
return nb, err
|
||||
}
|
||||
}
|
||||
|
||||
// Delete the flag from the database.
|
||||
func (k Key) Delete() (int64, error) {
|
||||
if _, err := DBExec("DELETE FROM exercice_files_deps WHERE id_key = ?", k.Id); err != nil {
|
||||
return 0, err
|
||||
} else if res, err := DBExec("DELETE FROM exercice_keys WHERE id_key = ?", k.Id); err != nil {
|
||||
return 0, err
|
||||
} else if nb, err := res.RowsAffected(); err != nil {
|
||||
return 0, err
|
||||
} else {
|
||||
return nb, err
|
||||
}
|
||||
}
|
||||
|
||||
// WipeKeys deletes keys coming with the challenge.
|
||||
func (e Exercice) WipeKeys() (int64, error) {
|
||||
if _, err := DBExec("DELETE FROM exercice_files_deps WHERE id_key IN (SELECT id_key FROM exercice_keys WHERE id_exercice = ?)", e.Id); err != nil {
|
||||
return 0, err
|
||||
} else if res, err := DBExec("DELETE FROM exercice_keys WHERE id_exercice = ?", e.Id); err != nil {
|
||||
return 0, err
|
||||
} else if nb, err := res.RowsAffected(); err != nil {
|
||||
return 0, err
|
||||
} else {
|
||||
return nb, err
|
||||
}
|
||||
}
|
||||
|
||||
// Check if the given val is the expected one for this flag.
|
||||
func (k Key) Check(val string) bool {
|
||||
hash := getHashedKey(val)
|
||||
if len(k.Checksum) != len(hash) {
|
||||
return false
|
||||
}
|
||||
|
||||
for i := range hash {
|
||||
if k.Checksum[i] != hash[i] {
|
||||
return false
|
||||
}
|
||||
}
|
||||
|
||||
return true
|
||||
}
|
||||
|
||||
// FoundBy registers in the database that the given Team solved the flag.
|
||||
func (k Key) FoundBy(t Team) {
|
||||
DBExec("INSERT INTO key_found (id_key, id_team, time) VALUES (?, ?, ?)", k.Id, t.Id, time.Now())
|
||||
}
|
||||
|
|
@ -29,15 +29,15 @@ func truncateTable(tables ...string) (error) {
|
|||
|
||||
// ResetGame resets all tables containing team attempts and solves.
|
||||
func ResetGame() (error) {
|
||||
return truncateTable("team_hints", "key_found", "mcq_found", "exercice_solved", "exercice_tries")
|
||||
return truncateTable("team_hints", "flag_found", "mcq_found", "exercice_solved", "exercice_tries")
|
||||
}
|
||||
|
||||
// ResetExercices wipes out all challenges (both attempts and statements).
|
||||
func ResetExercices() (error) {
|
||||
return truncateTable("team_hints", "exercice_files_deps", "exercice_files", "key_found", "exercice_keys", "exercice_solved", "exercice_tries", "exercice_hints", "mcq_found", "mcq_entries", "exercice_mcq", "exercices", "themes")
|
||||
return truncateTable("team_hints", "exercice_files_deps", "exercice_files", "flag_found", "exercice_flags", "exercice_solved", "exercice_tries", "exercice_hints", "mcq_found", "mcq_entries", "exercice_mcq", "exercices", "themes")
|
||||
}
|
||||
|
||||
// ResetTeams wipes out all teams, incluings members and attempts.
|
||||
func ResetTeams() (error) {
|
||||
return truncateTable("team_hints", "key_found", "mcq_found", "exercice_solved", "exercice_tries", "team_members", "teams")
|
||||
return truncateTable("team_hints", "flag_found", "mcq_found", "exercice_solved", "exercice_tries", "team_members", "teams")
|
||||
}
|
||||
|
|
|
|||
|
|
@ -209,9 +209,9 @@ func (t Team) GetSolvedRank(e Exercice) (nb int64, err error) {
|
|||
}
|
||||
}
|
||||
|
||||
// HasPartiallySolved checks if the Team already has unlocked the given key and returns the validation's timestamp.
|
||||
func (t Team) HasPartiallySolved(k Key) (tm *time.Time) {
|
||||
DBQueryRow("SELECT MIN(time) FROM key_found WHERE id_team = ? AND id_key = ?", t.Id, k.Id).Scan(&tm)
|
||||
// HasPartiallySolved checks if the Team already has unlocked the given flag and returns the validation's timestamp.
|
||||
func (t Team) HasPartiallySolved(f Flag) (tm *time.Time) {
|
||||
DBQueryRow("SELECT MIN(time) FROM flag_found WHERE id_team = ? AND id_flag = ?", t.Id, f.Id).Scan(&tm)
|
||||
return
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -8,7 +8,7 @@ import (
|
|||
func (t Team) GetHistory() ([]map[string]interface{}, error) {
|
||||
hist := make([]map[string]interface{}, 0)
|
||||
|
||||
if rows, err := DBQuery(`SELECT id_team, "tries" AS kind, time, E.id_exercice, E.title, NULL, NULL FROM exercice_tries T INNER JOIN exercices E ON E.id_exercice = T.id_exercice WHERE id_team = ? UNION SELECT id_team, "solved" AS kind, time, E.id_exercice, E.title, coefficient, NULL FROM exercice_solved S INNER JOIN exercices E ON E.id_exercice = S.id_exercice WHERE id_team = ? UNION SELECT id_team, "hint" AS kind, time, E.id_exercice, E.title, H.id_hint, H.title FROM team_hints T INNER JOIN exercice_hints H ON H.id_hint = T.id_hint INNER JOIN exercices E ON E.id_exercice = H.id_exercice WHERE id_team = ? UNION SELECT id_team, "key_found" AS kind, time, E.id_exercice, E.title, K.id_key, K.type FROM key_found F INNER JOIN exercice_keys K ON K.id_key = F.id_key INNER JOIN exercices E ON K.id_exercice = E.id_exercice WHERE id_team = ? ORDER BY time DESC`, t.Id, t.Id, t.Id, t.Id); err != nil {
|
||||
if rows, err := DBQuery(`SELECT id_team, "tries" AS kind, time, E.id_exercice, E.title, NULL, NULL FROM exercice_tries T INNER JOIN exercices E ON E.id_exercice = T.id_exercice WHERE id_team = ? UNION SELECT id_team, "solved" AS kind, time, E.id_exercice, E.title, coefficient, NULL FROM exercice_solved S INNER JOIN exercices E ON E.id_exercice = S.id_exercice WHERE id_team = ? UNION SELECT id_team, "hint" AS kind, time, E.id_exercice, E.title, H.id_hint, H.title FROM team_hints T INNER JOIN exercice_hints H ON H.id_hint = T.id_hint INNER JOIN exercices E ON E.id_exercice = H.id_exercice WHERE id_team = ? UNION SELECT id_team, "flag_found" AS kind, time, E.id_exercice, E.title, K.id_flag, K.type FROM flag_found F INNER JOIN exercice_flags K ON K.id_flag = F.id_flag INNER JOIN exercices E ON K.id_exercice = E.id_exercice WHERE id_team = ? ORDER BY time DESC`, t.Id, t.Id, t.Id, t.Id); err != nil {
|
||||
return nil, err
|
||||
} else {
|
||||
defer rows.Close()
|
||||
|
|
@ -64,8 +64,8 @@ func (t Team) DelHistoryItem(kind string, h time.Time, primary *int64, secondary
|
|||
} else {
|
||||
return nb, err
|
||||
}
|
||||
} else if kind == "key_found" && secondary != nil {
|
||||
if res, err := DBExec("DELETE FROM key_found WHERE id_team = ? AND time = ? AND id_key = ?", t.Id, h, *secondary); err != nil {
|
||||
} else if kind == "flag_found" && secondary != nil {
|
||||
if res, err := DBExec("DELETE FROM flag_found WHERE id_team = ? AND time = ? AND id_flag = ?", t.Id, h, *secondary); err != nil {
|
||||
return 0, err
|
||||
} else if nb, err := res.RowsAffected(); err != nil {
|
||||
return 0, err
|
||||
|
|
|
|||
|
|
@ -32,7 +32,7 @@ type myTeamExercice struct {
|
|||
Hints []myTeamHint `json:"hints,omitempty"`
|
||||
Gain int `json:"gain"`
|
||||
Files []myTeamFile `json:"files,omitempty"`
|
||||
Keys []string `json:"keys,omitempty"`
|
||||
Flags []string `json:"keys,omitempty"`
|
||||
SolvedMat []bool `json:"solved_matrix,omitempty"`
|
||||
MCQs []myTeamMCQ `json:"mcqs,omitempty"`
|
||||
SolveDist int64 `json:"solve_dist,omitempty"`
|
||||
|
|
@ -157,18 +157,18 @@ func MyJSONTeam(t *Team, started bool) (interface{}, error) {
|
|||
}
|
||||
}
|
||||
|
||||
// Expose exercice keys
|
||||
// Expose exercice flags
|
||||
|
||||
exercice.Keys = []string{}
|
||||
exercice.Flags = []string{}
|
||||
|
||||
if keys, err := e.GetKeys(); err != nil {
|
||||
if flags, err := e.GetFlags(); err != nil {
|
||||
return nil, err
|
||||
} else {
|
||||
for _, k := range keys {
|
||||
for _, k := range flags {
|
||||
if t == nil {
|
||||
exercice.Keys = append(exercice.Keys, fmt.Sprintf("%x", k.Checksum)+k.Label)
|
||||
exercice.Flags = append(exercice.Flags, fmt.Sprintf("%x", k.Checksum)+k.Label)
|
||||
} else {
|
||||
exercice.Keys = append(exercice.Keys, k.Label)
|
||||
exercice.Flags = append(exercice.Flags, k.Label)
|
||||
if PartialValidation {
|
||||
exercice.SolvedMat = append(exercice.SolvedMat, t.HasPartiallySolved(k) != nil)
|
||||
}
|
||||
|
|
|
|||
Reference in a new issue