admin: Handle team password
This commit is contained in:
parent
ed69dc6ba4
commit
5eeb1a6297
11 changed files with 299 additions and 40 deletions
|
|
@ -99,7 +99,8 @@ CREATE TABLE IF NOT EXISTS teams(
|
|||
name VARCHAR(255) NOT NULL,
|
||||
color INTEGER NOT NULL,
|
||||
active BOOLEAN NOT NULL DEFAULT 1,
|
||||
external_id VARCHAR(255) NOT NULL
|
||||
external_id VARCHAR(255) NOT NULL,
|
||||
password VARCHAR(255) NULL
|
||||
) DEFAULT CHARACTER SET = utf8mb4 COLLATE = utf8mb4_unicode_ci;
|
||||
`); err != nil {
|
||||
return err
|
||||
|
|
|
|||
31
libfic/password.go
Normal file
31
libfic/password.go
Normal file
|
|
@ -0,0 +1,31 @@
|
|||
package fic
|
||||
|
||||
import (
|
||||
"crypto/rand"
|
||||
"encoding/base64"
|
||||
"strings"
|
||||
)
|
||||
|
||||
func GeneratePassword() (password string, err error) {
|
||||
// This will make a 12 chars long password
|
||||
b := make([]byte, 9)
|
||||
|
||||
if _, err = rand.Read(b); err != nil {
|
||||
return
|
||||
}
|
||||
|
||||
password = base64.StdEncoding.EncodeToString(b)
|
||||
|
||||
// Avoid hard to read characters
|
||||
for _, i := range [][2]string{
|
||||
{"v", "*"}, {"u", "("},
|
||||
{"l", "%"}, {"1", "?"},
|
||||
{"o", "@"}, {"O", "!"}, {"0", ">"},
|
||||
// This one is to avoid problem with openssl
|
||||
{"/", "^"},
|
||||
} {
|
||||
password = strings.Replace(password, i[0], i[1], -1)
|
||||
}
|
||||
|
||||
return
|
||||
}
|
||||
|
|
@ -4,6 +4,8 @@ import (
|
|||
"log"
|
||||
"math"
|
||||
"time"
|
||||
|
||||
"golang.org/x/crypto/bcrypt"
|
||||
)
|
||||
|
||||
// UnlockedChallengeDepth is the number of challenges to unlock ahead (0: only the next one, -1: all)
|
||||
|
|
@ -14,15 +16,16 @@ var WChoiceCoefficient = 1.0
|
|||
|
||||
// Team represents a group of players, come to solve our challenges.
|
||||
type Team struct {
|
||||
Id int64 `json:"id"`
|
||||
Name string `json:"name"`
|
||||
Color uint32 `json:"color"`
|
||||
Active bool `json:"active"`
|
||||
ExternalId string `json:"external_id"`
|
||||
Id int64 `json:"id"`
|
||||
Name string `json:"name"`
|
||||
Color uint32 `json:"color"`
|
||||
Active bool `json:"active"`
|
||||
ExternalId string `json:"external_id"`
|
||||
Password *string `json:"password"`
|
||||
}
|
||||
|
||||
func getTeams(filter string) ([]Team, error) {
|
||||
if rows, err := DBQuery("SELECT id_team, name, color, active, external_id FROM teams " + filter); err != nil {
|
||||
if rows, err := DBQuery("SELECT id_team, name, color, active, external_id, password FROM teams " + filter); err != nil {
|
||||
return nil, err
|
||||
} else {
|
||||
defer rows.Close()
|
||||
|
|
@ -30,7 +33,7 @@ func getTeams(filter string) ([]Team, error) {
|
|||
var teams = make([]Team, 0)
|
||||
for rows.Next() {
|
||||
var t Team
|
||||
if err := rows.Scan(&t.Id, &t.Name, &t.Color, &t.Active, &t.ExternalId); err != nil {
|
||||
if err := rows.Scan(&t.Id, &t.Name, &t.Color, &t.Active, &t.ExternalId, &t.Password); err != nil {
|
||||
return nil, err
|
||||
}
|
||||
teams = append(teams, t)
|
||||
|
|
@ -56,7 +59,7 @@ func GetActiveTeams() ([]Team, error) {
|
|||
// GetTeam retrieves a Team from its identifier.
|
||||
func GetTeam(id int64) (Team, error) {
|
||||
var t Team
|
||||
if err := DBQueryRow("SELECT id_team, name, color, active, external_id FROM teams WHERE id_team = ?", id).Scan(&t.Id, &t.Name, &t.Color, &t.Active, &t.ExternalId); err != nil {
|
||||
if err := DBQueryRow("SELECT id_team, name, color, active, external_id, password FROM teams WHERE id_team = ?", id).Scan(&t.Id, &t.Name, &t.Color, &t.Active, &t.ExternalId, &t.Password); err != nil {
|
||||
return t, err
|
||||
}
|
||||
|
||||
|
|
@ -66,7 +69,7 @@ func GetTeam(id int64) (Team, error) {
|
|||
// GetTeamBySerial retrieves a Team from one of its associated certificates.
|
||||
func GetTeamBySerial(serial int64) (Team, error) {
|
||||
var t Team
|
||||
if err := DBQueryRow("SELECT T.id_team, T.name, T.color, T.active, T.external_id FROM certificates C INNER JOIN teams T ON T.id_team = C.id_team WHERE id_cert = ?", serial).Scan(&t.Id, &t.Name, &t.Color, &t.Active, &t.ExternalId); err != nil {
|
||||
if err := DBQueryRow("SELECT T.id_team, T.name, T.color, T.active, T.external_id, T.password FROM certificates C INNER JOIN teams T ON T.id_team = C.id_team WHERE id_cert = ?", serial).Scan(&t.Id, &t.Name, &t.Color, &t.Active, &t.ExternalId, &t.Password); err != nil {
|
||||
return t, err
|
||||
}
|
||||
|
||||
|
|
@ -80,13 +83,13 @@ func CreateTeam(name string, color uint32, externalId string) (Team, error) {
|
|||
} else if tid, err := res.LastInsertId(); err != nil {
|
||||
return Team{}, err
|
||||
} else {
|
||||
return Team{tid, name, color, true, ""}, nil
|
||||
return Team{tid, name, color, true, "", nil}, nil
|
||||
}
|
||||
}
|
||||
|
||||
// Update applies modifications back to the database.
|
||||
func (t Team) Update() (int64, error) {
|
||||
if res, err := DBExec("UPDATE teams SET name = ?, color = ?, active = ?, external_id = ? WHERE id_team = ?", t.Name, t.Color, t.Active, t.ExternalId, t.Id); err != nil {
|
||||
if res, err := DBExec("UPDATE teams SET name = ?, color = ?, active = ?, external_id = ?, password = ? WHERE id_team = ?", t.Name, t.Color, t.Active, t.ExternalId, t.Password, t.Id); err != nil {
|
||||
return 0, err
|
||||
} else if nb, err := res.RowsAffected(); err != nil {
|
||||
return 0, err
|
||||
|
|
@ -310,3 +313,18 @@ func (t Team) HasPartiallySolved(f Flag) (tm *time.Time) {
|
|||
}
|
||||
return
|
||||
}
|
||||
|
||||
// HashedPassword compute a bcrypt version of the team's password.
|
||||
func (t Team) HashedPassword() (string, error) {
|
||||
if t.Password == nil {
|
||||
if passwd, err := GeneratePassword(); err != nil {
|
||||
return "", err
|
||||
} else {
|
||||
h, err := bcrypt.GenerateFromPassword([]byte(passwd), bcrypt.DefaultCost)
|
||||
return string(h), err
|
||||
}
|
||||
}
|
||||
|
||||
h, err := bcrypt.GenerateFromPassword([]byte(*t.Password), bcrypt.DefaultCost)
|
||||
return string(h), err
|
||||
}
|
||||
|
|
|
|||
Reference in a new issue