New option to disallow team creation: join only
This commit is contained in:
parent
5d3ef96f3f
commit
64b9e9a251
6 changed files with 53 additions and 30 deletions
|
@ -178,6 +178,7 @@ func main() {
|
||||||
WChoiceCurCoefficient: 1,
|
WChoiceCurCoefficient: 1,
|
||||||
AllowRegistration: false,
|
AllowRegistration: false,
|
||||||
CanJoinTeam: false,
|
CanJoinTeam: false,
|
||||||
|
DenyTeamCreation: false,
|
||||||
DenyNameChange: false,
|
DenyNameChange: false,
|
||||||
AcceptNewIssue: true,
|
AcceptNewIssue: true,
|
||||||
EnableResolutionRoute: false,
|
EnableResolutionRoute: false,
|
||||||
|
|
|
@ -129,6 +129,13 @@
|
||||||
</label>
|
</label>
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
|
<div class="form-check">
|
||||||
|
<label class="custom-control custom-checkbox">
|
||||||
|
<input class="custom-control-input" type="checkbox" ng-model="config.denyTeamCreation" ng-disabled="!config.allowRegistration && !config.canJoinTeam">
|
||||||
|
<span class="custom-control-label">Interdire la création de nouvelles équipes</span>
|
||||||
|
</label>
|
||||||
|
</div>
|
||||||
|
|
||||||
<div class="form-check">
|
<div class="form-check">
|
||||||
<label class="custom-control custom-checkbox">
|
<label class="custom-control custom-checkbox">
|
||||||
<input class="custom-control-input" type="checkbox" ng-model="config.denyNameChange">
|
<input class="custom-control-input" type="checkbox" ng-model="config.denyNameChange">
|
||||||
|
|
|
@ -70,6 +70,7 @@ var skipInitialGeneration = false
|
||||||
func reloadSettings(config settings.FICSettings) {
|
func reloadSettings(config settings.FICSettings) {
|
||||||
allowRegistration = config.AllowRegistration
|
allowRegistration = config.AllowRegistration
|
||||||
canJoinTeam = config.CanJoinTeam
|
canJoinTeam = config.CanJoinTeam
|
||||||
|
denyTeamCreation = config.DenyTeamCreation
|
||||||
fic.HintCoefficient = config.HintCurCoefficient
|
fic.HintCoefficient = config.HintCurCoefficient
|
||||||
fic.WChoiceCoefficient = config.WChoiceCurCoefficient
|
fic.WChoiceCoefficient = config.WChoiceCurCoefficient
|
||||||
fic.ExerciceCurrentCoefficient = config.ExerciceCurCoefficient
|
fic.ExerciceCurrentCoefficient = config.ExerciceCurCoefficient
|
||||||
|
|
|
@ -18,6 +18,7 @@ import (
|
||||||
var (
|
var (
|
||||||
allowRegistration = false
|
allowRegistration = false
|
||||||
canJoinTeam = false
|
canJoinTeam = false
|
||||||
|
denyTeamCreation = false
|
||||||
)
|
)
|
||||||
|
|
||||||
type uTeamRegistration struct {
|
type uTeamRegistration struct {
|
||||||
|
@ -78,6 +79,8 @@ func treatRegistration(pathname string, team_id string) {
|
||||||
log.Printf("%s [WRN] %s\n", id, err)
|
log.Printf("%s [WRN] %s\n", id, err)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
} else if denyTeamCreation {
|
||||||
|
log.Printf("%s [ERR] Registration received, whereas team creation denied. Skipped.\n", id)
|
||||||
} else if validTeamName(nTeam.TeamName) {
|
} else if validTeamName(nTeam.TeamName) {
|
||||||
if team, err := fic.CreateTeam(nTeam.TeamName, uint32(rand.Int31n(16581376))); err != nil {
|
if team, err := fic.CreateTeam(nTeam.TeamName, uint32(rand.Int31n(16581376))); err != nil {
|
||||||
log.Printf("%s [ERR] Unable to register new team %s: %s\n", id, nTeam.TeamName, err)
|
log.Printf("%s [ERR] Unable to register new team %s: %s\n", id, nTeam.TeamName, err)
|
||||||
|
|
|
@ -9,9 +9,9 @@
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
<div class="jumbotron niceborder" style="text-indent: 1em" ng-if="settings.allowRegistration">
|
<div class="jumbotron niceborder" style="text-indent: 1em" ng-if="settings.allowRegistration && !settings.denyTeamCreation">
|
||||||
<p>
|
<p>
|
||||||
<strong>Félicitations ! vous êtes maintenant authentifié auprès de
|
<strong>Félicitations ! vous êtes maintenant authentifié·e auprès de
|
||||||
notre serveur !</strong>
|
notre serveur !</strong>
|
||||||
</p>
|
</p>
|
||||||
<p>
|
<p>
|
||||||
|
@ -76,9 +76,18 @@
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
<div class="jumbotron niceborder" style="text-indent: 1em" ng-if="settings.canJoinTeam">
|
<div class="jumbotron niceborder" style="text-indent: 1em" ng-if="settings.canJoinTeam">
|
||||||
<p>
|
<p ng-if="settings.denyTeamCreation">
|
||||||
|
<strong>Félicitations ! vous êtes maintenant authentifié·e auprès de
|
||||||
|
notre serveur !</strong>
|
||||||
|
</p>
|
||||||
|
<p ng-if="!settings.denyTeamCreation">
|
||||||
Si votre équipe est déjà créée, rejoignez-là !
|
Si votre équipe est déjà créée, rejoignez-là !
|
||||||
</p>
|
</p>
|
||||||
|
<p ng-if="settings.denyTeamCreation">
|
||||||
|
Vous n'êtes pas encore enregistré·e sur notre serveur. Afin de
|
||||||
|
pouvoir participer au challenge, nous vous remercions de bien vouloir
|
||||||
|
rejoindre votre équipe :
|
||||||
|
</p>
|
||||||
<form ng-submit="jsubmit()">
|
<form ng-submit="jsubmit()">
|
||||||
|
|
||||||
<div class="row">
|
<div class="row">
|
||||||
|
|
|
@ -8,8 +8,8 @@ import (
|
||||||
"os"
|
"os"
|
||||||
"os/signal"
|
"os/signal"
|
||||||
"path"
|
"path"
|
||||||
"time"
|
|
||||||
"syscall"
|
"syscall"
|
||||||
|
"time"
|
||||||
|
|
||||||
"gopkg.in/fsnotify.v1"
|
"gopkg.in/fsnotify.v1"
|
||||||
)
|
)
|
||||||
|
@ -23,52 +23,54 @@ var SettingsDir string = "./SETTINGS"
|
||||||
// FICSettings represents the settings panel.
|
// FICSettings represents the settings panel.
|
||||||
type FICSettings struct {
|
type FICSettings struct {
|
||||||
// Title is the displayed name of the challenge.
|
// Title is the displayed name of the challenge.
|
||||||
Title string `json:"title"`
|
Title string `json:"title"`
|
||||||
// Authors is the group name of people making the challenge.
|
// Authors is the group name of people making the challenge.
|
||||||
Authors string `json:"authors"`
|
Authors string `json:"authors"`
|
||||||
// VideoLink is the link to explaination videos when the challenge is over.
|
// VideoLink is the link to explaination videos when the challenge is over.
|
||||||
VideosLink string `json:"videoslink"`
|
VideosLink string `json:"videoslink"`
|
||||||
|
|
||||||
// Start is the departure time (expected or effective).
|
// Start is the departure time (expected or effective).
|
||||||
Start time.Time `json:"start"`
|
Start time.Time `json:"start"`
|
||||||
// End is the expected end time.
|
// End is the expected end time.
|
||||||
End time.Time `json:"end"`
|
End time.Time `json:"end"`
|
||||||
// Generation is a value used to regenerate static files.
|
// Generation is a value used to regenerate static files.
|
||||||
Generation time.Time `json:"generation"`
|
Generation time.Time `json:"generation"`
|
||||||
// ActivateTime is the time when the current file should be proceed.
|
// ActivateTime is the time when the current file should be proceed.
|
||||||
ActivateTime time.Time `json:"activateTime"`
|
ActivateTime time.Time `json:"activateTime"`
|
||||||
|
|
||||||
// FirstBlood is the coefficient applied to each first team who solve a challenge.
|
// FirstBlood is the coefficient applied to each first team who solve a challenge.
|
||||||
FirstBlood float64 `json:"firstBlood"`
|
FirstBlood float64 `json:"firstBlood"`
|
||||||
// SubmissionCostBase is a complex number representing the cost of each attempts.
|
// SubmissionCostBase is a complex number representing the cost of each attempts.
|
||||||
SubmissionCostBase float64 `json:"submissionCostBase"`
|
SubmissionCostBase float64 `json:"submissionCostBase"`
|
||||||
// ExerciceCurrentCoefficient is the current coefficient applied globaly to exercices.
|
// ExerciceCurrentCoefficient is the current coefficient applied globaly to exercices.
|
||||||
ExerciceCurCoefficient float64 `json:"exerciceCurrentCoefficient"`
|
ExerciceCurCoefficient float64 `json:"exerciceCurrentCoefficient"`
|
||||||
// HintCurrentCoefficient is the current coefficient applied to hint discovery.
|
// HintCurrentCoefficient is the current coefficient applied to hint discovery.
|
||||||
HintCurCoefficient float64 `json:"hintCurrentCoefficient"`
|
HintCurCoefficient float64 `json:"hintCurrentCoefficient"`
|
||||||
// WChoiceCurCoefficient is the current coefficient applied to wanted choices.
|
// WChoiceCurCoefficient is the current coefficient applied to wanted choices.
|
||||||
WChoiceCurCoefficient float64 `json:"wchoiceCurrentCoefficient"`
|
WChoiceCurCoefficient float64 `json:"wchoiceCurrentCoefficient"`
|
||||||
|
|
||||||
// AllowRegistration permits unregistered Team to register themselves.
|
// AllowRegistration permits unregistered Team to register themselves.
|
||||||
AllowRegistration bool `json:"allowRegistration"`
|
AllowRegistration bool `json:"allowRegistration"`
|
||||||
// CanJoinTeam permits unregistered account to join an already existing team.
|
// CanJoinTeam permits unregistered account to join an already existing team.
|
||||||
CanJoinTeam bool `json:"canJoinTeam"`
|
CanJoinTeam bool `json:"canJoinTeam"`
|
||||||
|
// DenyTeamCreation forces unregistered account to join a team, it's not possible to create a new team.
|
||||||
|
DenyTeamCreation bool `json:"denyTeamCreation"`
|
||||||
// DenyNameChange disallow Team to change their name.
|
// DenyNameChange disallow Team to change their name.
|
||||||
DenyNameChange bool `json:"denyNameChange"`
|
DenyNameChange bool `json:"denyNameChange"`
|
||||||
// AcceptNewIssue enables the reporting system.
|
// AcceptNewIssue enables the reporting system.
|
||||||
AcceptNewIssue bool `json:"acceptNewIssue"`
|
AcceptNewIssue bool `json:"acceptNewIssue"`
|
||||||
// EnableResolutionRoute activates the route displaying resolution movies.
|
// EnableResolutionRoute activates the route displaying resolution movies.
|
||||||
EnableResolutionRoute bool `json:"enableResolutionRoute"`
|
EnableResolutionRoute bool `json:"enableResolutionRoute"`
|
||||||
// PartialValidation validates each correct given answers, don't expect Team to give all correct answer in a try.
|
// PartialValidation validates each correct given answers, don't expect Team to give all correct answer in a try.
|
||||||
PartialValidation bool `json:"partialValidation"`
|
PartialValidation bool `json:"partialValidation"`
|
||||||
// UnlockedChallengeDepth don't show (or permit to solve) to team challenges they are not unlocked through dependancies.
|
// UnlockedChallengeDepth don't show (or permit to solve) to team challenges they are not unlocked through dependancies.
|
||||||
UnlockedChallengeDepth int `json:"unlockedChallengeDepth"`
|
UnlockedChallengeDepth int `json:"unlockedChallengeDepth"`
|
||||||
// SubmissionUniqueness don't count multiple times identical tries.
|
// SubmissionUniqueness don't count multiple times identical tries.
|
||||||
SubmissionUniqueness bool `json:"submissionUniqueness"`
|
SubmissionUniqueness bool `json:"submissionUniqueness"`
|
||||||
// DisplayAllFlags doesn't respect the predefined constraint existing between flags.
|
// DisplayAllFlags doesn't respect the predefined constraint existing between flags.
|
||||||
DisplayAllFlags bool `json:"displayAllFlags"`
|
DisplayAllFlags bool `json:"displayAllFlags"`
|
||||||
// EventKindness will ask browsers to delay notification interval.
|
// EventKindness will ask browsers to delay notification interval.
|
||||||
EventKindness bool `json:"eventKindness"`
|
EventKindness bool `json:"eventKindness"`
|
||||||
}
|
}
|
||||||
|
|
||||||
// ExistsSettings checks if the settings file can by found at the given path.
|
// ExistsSettings checks if the settings file can by found at the given path.
|
||||||
|
@ -125,7 +127,7 @@ func ForceRegeneration() error {
|
||||||
// Giving the location and a callback, this function will first call your reload function
|
// Giving the location and a callback, this function will first call your reload function
|
||||||
// before returning (if the file can be parsed); then it starts watching modifications made to
|
// before returning (if the file can be parsed); then it starts watching modifications made to
|
||||||
// this file. Your callback is then run each time the file is modified.
|
// this file. Your callback is then run each time the file is modified.
|
||||||
func LoadAndWatchSettings(settingsPath string, reload func (FICSettings)) {
|
func LoadAndWatchSettings(settingsPath string, reload func(FICSettings)) {
|
||||||
// First load of configuration if it exists
|
// First load of configuration if it exists
|
||||||
if _, err := os.Stat(settingsPath); !os.IsNotExist(err) {
|
if _, err := os.Stat(settingsPath); !os.IsNotExist(err) {
|
||||||
if config, err := ReadSettings(settingsPath); err != nil {
|
if config, err := ReadSettings(settingsPath); err != nil {
|
||||||
|
@ -138,7 +140,7 @@ func LoadAndWatchSettings(settingsPath string, reload func (FICSettings)) {
|
||||||
// Register SIGHUP
|
// Register SIGHUP
|
||||||
c := make(chan os.Signal, 1)
|
c := make(chan os.Signal, 1)
|
||||||
signal.Notify(c, syscall.SIGHUP)
|
signal.Notify(c, syscall.SIGHUP)
|
||||||
go func(){
|
go func() {
|
||||||
for range c {
|
for range c {
|
||||||
log.Println("SIGHUP received, reloading settings...")
|
log.Println("SIGHUP received, reloading settings...")
|
||||||
go tryReload(settingsPath, reload)
|
go tryReload(settingsPath, reload)
|
||||||
|
@ -158,7 +160,7 @@ func LoadAndWatchSettings(settingsPath string, reload func (FICSettings)) {
|
||||||
for {
|
for {
|
||||||
select {
|
select {
|
||||||
case ev := <-watcher.Events:
|
case ev := <-watcher.Events:
|
||||||
if path.Base(ev.Name) == SettingsFile && ev.Op & (fsnotify.Write | fsnotify.Create) != 0 {
|
if path.Base(ev.Name) == SettingsFile && ev.Op&(fsnotify.Write|fsnotify.Create) != 0 {
|
||||||
log.Println("Settings file changes, reloading it!")
|
log.Println("Settings file changes, reloading it!")
|
||||||
go tryReload(settingsPath, reload)
|
go tryReload(settingsPath, reload)
|
||||||
}
|
}
|
||||||
|
@ -170,7 +172,7 @@ func LoadAndWatchSettings(settingsPath string, reload func (FICSettings)) {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
func tryReload(settingsPath string, reload func (FICSettings)) {
|
func tryReload(settingsPath string, reload func(FICSettings)) {
|
||||||
if config, err := ReadSettings(settingsPath); err != nil {
|
if config, err := ReadSettings(settingsPath); err != nil {
|
||||||
log.Println("ERROR: Unable to read challenge settings:", err)
|
log.Println("ERROR: Unable to read challenge settings:", err)
|
||||||
} else if time.Until(config.ActivateTime) > 0 {
|
} else if time.Until(config.ActivateTime) > 0 {
|
||||||
|
|
Reference in a new issue