diff --git a/admin/main.go b/admin/main.go index 8f499c4b..523d8dd5 100644 --- a/admin/main.go +++ b/admin/main.go @@ -10,6 +10,7 @@ import ( "os/signal" "path" "path/filepath" + "strconv" "strings" "syscall" @@ -62,6 +63,8 @@ func StripPrefix(prefix string, h http.Handler) http.Handler { } func main() { + var err error + bind := "127.0.0.1:8081" cloudDAVBase := "" cloudUsername := "fic" cloudPassword := "" @@ -95,11 +98,53 @@ func main() { baseURL = v } if v, exists := os.LookupEnv("FIC_4REAL"); exists { - api.IsProductionEnv = v == "true" || v == "on" || v == "TRUE" || v == "ON" || v == "1" + api.IsProductionEnv, err = strconv.ParseBool(v) + if err != nil { + log.Fatal("Unable to parse FIC_4REAL variable:", err) + } + } + if v, exists := os.LookupEnv("FIC_ADMIN_BIND"); exists { + bind = v + } + if v, exists := os.LookupEnv("FIC_TIMESTAMPCHECK"); exists { + api.TimestampCheck = v + } + if v, exists := os.LookupEnv("FIC_SETTINGS"); exists { + settings.SettingsDir = v + } + if v, exists := os.LookupEnv("FIC_FILES"); exists { + fic.FilesDir = v + } + if v, exists := os.LookupEnv("FIC_SYNC_LOCALIMPORT"); exists { + localImporterDirectory = v + } + if v, exists := os.LookupEnv("FIC_SYNC_LOCALIMPORTSYMLINK"); exists { + localImporterSymlink, err = strconv.ParseBool(v) + if err != nil { + log.Fatal("Unable to parse FIC_SYNC_LOCALIMPORTSYMLINK variable:", err) + } + } + if v, exists := os.LookupEnv("FIC_SYNC_GIT_IMPORT_REMOTE"); exists { + gitImporterRemote = v + } + if v, exists := os.LookupEnv("FIC_SYNC_GIT_BRANCH"); exists { + gitImporterBranch = v + } + if v, exists := os.LookupEnv("FIC_OPTIONALDIGEST"); exists { + fic.OptionalDigest, err = strconv.ParseBool(v) + if err != nil { + log.Fatal("Unable to parse FIC_OPTIONALDIGEST variable:", err) + } + } + if v, exists := os.LookupEnv("FIC_STRONGDIGEST"); exists { + fic.StrongDigest, err = strconv.ParseBool(v) + if err != nil { + log.Fatal("Unable to parse FIC_STRONGDIGEST variable:", err) + } } // Read parameters from command line - var bind = flag.String("bind", "127.0.0.1:8081", "Bind port/socket") + flag.StringVar(&bind, "bind", bind, "Bind port/socket") var dsn = flag.String("dsn", fic.DSNGenerator(), "DSN to connect to the MySQL server") flag.StringVar(&baseURL, "baseurl", baseURL, "URL prepended to each URL") flag.StringVar(&api.TimestampCheck, "timestampCheck", api.TimestampCheck, "Path regularly touched by frontend to check time synchronisation") @@ -169,7 +214,6 @@ func main() { } // Sanitize options - var err error log.Println("Checking paths...") if staticDir != nil && *staticDir != "" { if sDir, err := filepath.Abs(*staticDir); err != nil { @@ -265,7 +309,7 @@ func main() { interrupt := make(chan os.Signal, 1) signal.Notify(interrupt, os.Interrupt, syscall.SIGTERM) - app := NewApp(config, baseURL, *bind) + app := NewApp(config, baseURL, bind) go app.Start() // Wait shutdown signal diff --git a/receiver/main.go b/receiver/main.go index f7f34fdd..9c3d96b5 100644 --- a/receiver/main.go +++ b/receiver/main.go @@ -17,12 +17,37 @@ import ( ) func main() { - var bind = flag.String("bind", "127.0.0.1:8080", "Bind port/socket") - var prefix = flag.String("prefix", "/", "Request path prefix to strip (from proxy)") - var teamsDir = flag.String("teams", "./TEAMS/", "Base directory where find existing teams") - flag.StringVar(&settings.SettingsDir, "settings", "./SETTINGSDIST", "Base directory where read settings") + bind := "127.0.0.1:8080" + prefix := "/" + teamsDir := "./TEAMS/" + settings.SettingsDir = "./SETTINGSDIST" + + // Read paremeters from environment + if v, exists := os.LookupEnv("FIC_BASEURL"); exists { + prefix = v + } + if v, exists := os.LookupEnv("FIC_RECEIVER_BIND"); exists { + bind = v + } + if v, exists := os.LookupEnv("FIC_SETTINGSDIST"); exists { + settings.SettingsDir = v + } + if v, exists := os.LookupEnv("FIC_STARTED_FILE"); exists { + startedFile = v + } + if v, exists := os.LookupEnv("FIC_SUBMISSIONS_DIRECTORY"); exists { + SubmissionDir = v + } + if v, exists := os.LookupEnv("FIC_TEAMS_DIRECTORY"); exists { + teamsDir = v + } + + flag.StringVar(&bind, "bind", bind, "Bind port/socket") + flag.StringVar(&prefix, "prefix", prefix, "Request path prefix to strip (from proxy)") + flag.StringVar(&teamsDir, "teams", teamsDir, "Base directory where find existing teams") + flag.StringVar(&settings.SettingsDir, "settings", settings.SettingsDir, "Base directory where read settings") flag.StringVar(&startedFile, "startedFile", startedFile, "Path to the file to create/remove whether or not the challenge is running") - flag.StringVar(&SubmissionDir, "submission", "./submissions/", "Base directory where save submissions") + flag.StringVar(&SubmissionDir, "submission", SubmissionDir, "Base directory where save submissions") var simulator = flag.String("simulator", "", "Team to simulate (for development only)") flag.StringVar(&staticDir, "static", staticDir, "Set to serve pages as well (for development only, use with -simulator)") flag.Parse() @@ -40,48 +65,48 @@ func main() { } } - *prefix = strings.TrimRight(*prefix, "/") + prefix = strings.TrimRight(prefix, "/") // Load configuration settings.LoadAndWatchSettings(path.Join(settings.SettingsDir, settings.SettingsFile), reloadSettings) // Register handlers - http.Handle(fmt.Sprintf("%s/chname", *prefix), http.StripPrefix(fmt.Sprintf("%s/chname", *prefix), submissionTeamChecker{"name change", ChNameHandler, *teamsDir, *simulator})) - http.Handle(fmt.Sprintf("%s/issue", *prefix), http.StripPrefix(fmt.Sprintf("%s/issue", *prefix), submissionTeamChecker{"issue", IssueHandler, *teamsDir, *simulator})) - http.Handle(fmt.Sprintf("%s/openhint/", *prefix), http.StripPrefix(fmt.Sprintf("%s/openhint/", *prefix), submissionTeamChecker{"opening hint", HintHandler, *teamsDir, *simulator})) - http.Handle(fmt.Sprintf("%s/wantchoices/", *prefix), http.StripPrefix(fmt.Sprintf("%s/wantchoices/", *prefix), submissionTeamChecker{"wantint choices", WantChoicesHandler, *teamsDir, *simulator})) - http.Handle(fmt.Sprintf("%s/registration", *prefix), http.StripPrefix(fmt.Sprintf("%s/registration", *prefix), submissionChecker{"registration", RegistrationHandler})) - http.Handle(fmt.Sprintf("%s/resolution/", *prefix), http.StripPrefix(fmt.Sprintf("%s/resolution/", *prefix), ResolutionHandler{})) - http.Handle(fmt.Sprintf("%s/reset_progress", *prefix), http.StripPrefix(fmt.Sprintf("%s/reset_progress", *prefix), submissionTeamChecker{"reset_progress", ResetProgressHandler, *teamsDir, *simulator})) - http.Handle(fmt.Sprintf("%s/submission/", *prefix), http.StripPrefix(fmt.Sprintf("%s/submission/", *prefix), submissionTeamChecker{"submission", SubmissionHandler, *teamsDir, *simulator})) + http.Handle(fmt.Sprintf("%s/chname", prefix), http.StripPrefix(fmt.Sprintf("%s/chname", prefix), submissionTeamChecker{"name change", ChNameHandler, teamsDir, *simulator})) + http.Handle(fmt.Sprintf("%s/issue", prefix), http.StripPrefix(fmt.Sprintf("%s/issue", prefix), submissionTeamChecker{"issue", IssueHandler, teamsDir, *simulator})) + http.Handle(fmt.Sprintf("%s/openhint/", prefix), http.StripPrefix(fmt.Sprintf("%s/openhint/", prefix), submissionTeamChecker{"opening hint", HintHandler, teamsDir, *simulator})) + http.Handle(fmt.Sprintf("%s/wantchoices/", prefix), http.StripPrefix(fmt.Sprintf("%s/wantchoices/", prefix), submissionTeamChecker{"wantint choices", WantChoicesHandler, teamsDir, *simulator})) + http.Handle(fmt.Sprintf("%s/registration", prefix), http.StripPrefix(fmt.Sprintf("%s/registration", prefix), submissionChecker{"registration", RegistrationHandler})) + http.Handle(fmt.Sprintf("%s/resolution/", prefix), http.StripPrefix(fmt.Sprintf("%s/resolution/", prefix), ResolutionHandler{})) + http.Handle(fmt.Sprintf("%s/reset_progress", prefix), http.StripPrefix(fmt.Sprintf("%s/reset_progress", prefix), submissionTeamChecker{"reset_progress", ResetProgressHandler, teamsDir, *simulator})) + http.Handle(fmt.Sprintf("%s/submission/", prefix), http.StripPrefix(fmt.Sprintf("%s/submission/", prefix), submissionTeamChecker{"submission", SubmissionHandler, teamsDir, *simulator})) if *simulator != "" { - if _, err := os.Stat(path.Join(*teamsDir, *simulator)); os.IsNotExist(err) { - log.Printf("WARNING: Team '%s' doesn't exist yet in %s.", *simulator, *teamsDir) + if _, err := os.Stat(path.Join(teamsDir, *simulator)); os.IsNotExist(err) { + log.Printf("WARNING: Team '%s' doesn't exist yet in %s.", *simulator, teamsDir) } // Serve team files - http.Handle(fmt.Sprintf("%s/wait.json", *prefix), http.StripPrefix(*prefix, http.FileServer(http.Dir(path.Join(*teamsDir, *simulator))))) - http.Handle(fmt.Sprintf("%s/my.json", *prefix), http.StripPrefix(*prefix, TeamMyServer{path.Join(*teamsDir, *simulator)})) + http.Handle(fmt.Sprintf("%s/wait.json", prefix), http.StripPrefix(prefix, http.FileServer(http.Dir(path.Join(teamsDir, *simulator))))) + http.Handle(fmt.Sprintf("%s/my.json", prefix), http.StripPrefix(prefix, TeamMyServer{path.Join(teamsDir, *simulator)})) // Serve generated content - http.Handle(fmt.Sprintf("%s/teams.json", *prefix), http.StripPrefix(*prefix, http.FileServer(http.Dir(*teamsDir)))) - http.Handle(fmt.Sprintf("%s/themes.json", *prefix), http.StripPrefix(*prefix, http.FileServer(http.Dir(*teamsDir)))) - http.Handle(fmt.Sprintf("%s/stats.json", *prefix), http.StripPrefix(*prefix, http.FileServer(http.Dir(*teamsDir)))) - http.Handle(fmt.Sprintf("%s/settings.json", *prefix), http.StripPrefix(*prefix, http.FileServer(http.Dir(settings.SettingsDir)))) + http.Handle(fmt.Sprintf("%s/teams.json", prefix), http.StripPrefix(prefix, http.FileServer(http.Dir(teamsDir)))) + http.Handle(fmt.Sprintf("%s/themes.json", prefix), http.StripPrefix(prefix, http.FileServer(http.Dir(teamsDir)))) + http.Handle(fmt.Sprintf("%s/stats.json", prefix), http.StripPrefix(prefix, http.FileServer(http.Dir(teamsDir)))) + http.Handle(fmt.Sprintf("%s/settings.json", prefix), http.StripPrefix(prefix, http.FileServer(http.Dir(settings.SettingsDir)))) // Serve static assets - http.Handle(fmt.Sprintf("%s/css/", *prefix), http.StripPrefix(*prefix, http.FileServer(http.Dir(staticDir)))) - http.Handle(fmt.Sprintf("%s/js/", *prefix), http.StripPrefix(*prefix, http.FileServer(http.Dir(staticDir)))) + http.Handle(fmt.Sprintf("%s/css/", prefix), http.StripPrefix(prefix, http.FileServer(http.Dir(staticDir)))) + http.Handle(fmt.Sprintf("%s/js/", prefix), http.StripPrefix(prefix, http.FileServer(http.Dir(staticDir)))) - http.Handle(fmt.Sprintf("%s/files/", *prefix), http.StripPrefix(*prefix, http.FileServer(http.Dir("FILES")))) + http.Handle(fmt.Sprintf("%s/files/", prefix), http.StripPrefix(prefix, http.FileServer(http.Dir("FILES")))) // Serve index - http.HandleFunc(fmt.Sprintf("%s/edit", *prefix), serveIndex) - http.HandleFunc(fmt.Sprintf("%s/rank", *prefix), serveIndex) - http.HandleFunc(fmt.Sprintf("%s/register", *prefix), serveIndex) - http.HandleFunc(fmt.Sprintf("%s/rules", *prefix), serveIndex) - http.HandleFunc(fmt.Sprintf("%s/videos", *prefix), serveIndex) + http.HandleFunc(fmt.Sprintf("%s/edit", prefix), serveIndex) + http.HandleFunc(fmt.Sprintf("%s/rank", prefix), serveIndex) + http.HandleFunc(fmt.Sprintf("%s/register", prefix), serveIndex) + http.HandleFunc(fmt.Sprintf("%s/rules", prefix), serveIndex) + http.HandleFunc(fmt.Sprintf("%s/videos", prefix), serveIndex) } // Prepare graceful shutdown @@ -89,7 +114,7 @@ func main() { signal.Notify(interrupt, os.Interrupt, syscall.SIGTERM) srv := &http.Server{ - Addr: *bind, + Addr: bind, ReadHeaderTimeout: 15 * time.Second, ReadTimeout: 15 * time.Second, WriteTimeout: 10 * time.Second, @@ -100,7 +125,7 @@ func main() { go func() { log.Fatal(srv.ListenAndServe()) }() - log.Println(fmt.Sprintf("Ready, listening on %s", *bind)) + log.Println(fmt.Sprintf("Ready, listening on %s", bind)) // Wait shutdown signal and touch timestamp ticker := time.NewTicker(time.Second) diff --git a/receiver/save.go b/receiver/save.go index a0a98ab9..7db69280 100644 --- a/receiver/save.go +++ b/receiver/save.go @@ -9,7 +9,7 @@ import ( "path" ) -var SubmissionDir string +var SubmissionDir = "./submissions/" var TmpSubmissionDir string func saveTeamFile(p string, w http.ResponseWriter, r *http.Request) bool {