Added trivial basic HTTP auth for Chezy Champs. Replace with better scheme before general release.

This commit is contained in:
Patrick Fairbank
2014-08-27 13:04:31 -07:00
parent 4a5490c143
commit 1da27cab4a
13 changed files with 197 additions and 0 deletions

View File

@@ -291,6 +291,11 @@ func PitDisplayWebsocketHandler(w http.ResponseWriter, r *http.Request) {
// Renders the announcer display which shows team info and scores for the current match.
func AnnouncerDisplayHandler(w http.ResponseWriter, r *http.Request) {
if auth.Authorize(r) == "" {
auth.NotifyAuthRequired(w, r)
return
}
template := template.New("").Funcs(templateHelpers)
_, err := template.ParseFiles("templates/announcer_display.html", "templates/base.html")
if err != nil {
@@ -475,6 +480,11 @@ func AnnouncerDisplayWebsocketHandler(w http.ResponseWriter, r *http.Request) {
// Renders the scoring interface which enables input of scores in real-time.
func ScoringDisplayHandler(w http.ResponseWriter, r *http.Request) {
if auth.Authorize(r) == "" {
auth.NotifyAuthRequired(w, r)
return
}
vars := mux.Vars(r)
alliance := vars["alliance"]
if alliance != "red" && alliance != "blue" {
@@ -710,6 +720,11 @@ func ScoringDisplayWebsocketHandler(w http.ResponseWriter, r *http.Request) {
// Renders the referee interface for assigning fouls.
func RefereeDisplayHandler(w http.ResponseWriter, r *http.Request) {
if auth.Authorize(r) == "" {
auth.NotifyAuthRequired(w, r)
return
}
template := template.New("").Funcs(templateHelpers)
_, err := template.ParseFiles("templates/referee_display.html")
if err != nil {
@@ -1121,6 +1136,11 @@ func AllianceStationDisplayWebsocketHandler(w http.ResponseWriter, r *http.Reque
// Renders the FTA diagnostic display.
func FtaDisplayHandler(w http.ResponseWriter, r *http.Request) {
if auth.Authorize(r) == "" {
auth.NotifyAuthRequired(w, r)
return
}
template := template.New("").Funcs(templateHelpers)
_, err := template.ParseFiles("templates/fta_display.html", "templates/base.html")
if err != nil {

View File

@@ -38,6 +38,11 @@ var currentMatchType string
// Shows the match play control interface.
func MatchPlayHandler(w http.ResponseWriter, r *http.Request) {
if auth.Authorize(r) == "" {
auth.NotifyAuthRequired(w, r)
return
}
practiceMatches, err := buildMatchPlayList("practice")
if err != nil {
handleWebErr(w, err)
@@ -88,6 +93,11 @@ func MatchPlayHandler(w http.ResponseWriter, r *http.Request) {
}
func MatchPlayLoadHandler(w http.ResponseWriter, r *http.Request) {
if auth.Authorize(r) == "" {
auth.NotifyAuthRequired(w, r)
return
}
vars := mux.Vars(r)
matchId, _ := strconv.Atoi(vars["matchId"])
var match *Match
@@ -117,6 +127,11 @@ func MatchPlayLoadHandler(w http.ResponseWriter, r *http.Request) {
// Loads the results for the given match into the display buffer.
func MatchPlayShowResultHandler(w http.ResponseWriter, r *http.Request) {
if auth.Authorize(r) == "" {
auth.NotifyAuthRequired(w, r)
return
}
vars := mux.Vars(r)
matchId, _ := strconv.Atoi(vars["matchId"])
match, err := db.GetMatchById(matchId)

View File

@@ -26,6 +26,11 @@ type MatchReviewListItem struct {
// Shows the match review interface.
func MatchReviewHandler(w http.ResponseWriter, r *http.Request) {
if auth.Authorize(r) == "" {
auth.NotifyAuthRequired(w, r)
return
}
practiceMatches, err := buildMatchReviewList("practice")
if err != nil {
handleWebErr(w, err)
@@ -66,6 +71,11 @@ func MatchReviewHandler(w http.ResponseWriter, r *http.Request) {
// Shows the page to edit the results for a match.
func MatchReviewEditGetHandler(w http.ResponseWriter, r *http.Request) {
if auth.Authorize(r) == "" {
auth.NotifyAuthRequired(w, r)
return
}
match, matchResult, err := getMatchResultFromRequest(r)
if err != nil {
handleWebErr(w, err)
@@ -96,6 +106,11 @@ func MatchReviewEditGetHandler(w http.ResponseWriter, r *http.Request) {
// Updates the results for a match.
func MatchReviewEditPostHandler(w http.ResponseWriter, r *http.Request) {
if auth.Authorize(r) == "" {
auth.NotifyAuthRequired(w, r)
return
}
match, matchResult, err := getMatchResultFromRequest(r)
if err != nil {
handleWebErr(w, err)

View File

@@ -25,11 +25,20 @@ var cachedRankedTeams []*RankedTeam
// Shows the alliance selection page.
func AllianceSelectionGetHandler(w http.ResponseWriter, r *http.Request) {
if auth.Authorize(r) == "" {
auth.NotifyAuthRequired(w, r)
return
}
renderAllianceSelection(w, r, "")
}
// Updates the cache with the latest input from the client.
func AllianceSelectionPostHandler(w http.ResponseWriter, r *http.Request) {
if auth.Authorize(r) == "" {
auth.NotifyAuthRequired(w, r)
return
}
if !canModifyAllianceSelection() {
renderAllianceSelection(w, r, "Alliance selection has already been finalized.")
return
@@ -81,6 +90,11 @@ func AllianceSelectionPostHandler(w http.ResponseWriter, r *http.Request) {
// Sets up the empty alliances and populates the ranked team list.
func AllianceSelectionStartHandler(w http.ResponseWriter, r *http.Request) {
if auth.Authorize(r) == "" {
auth.NotifyAuthRequired(w, r)
return
}
if len(cachedAlliances) != 0 {
renderAllianceSelection(w, r, "Can't start alliance selection when it is already in progress.")
return
@@ -120,6 +134,11 @@ func AllianceSelectionStartHandler(w http.ResponseWriter, r *http.Request) {
// Resets the alliance selection process back to the starting point.
func AllianceSelectionResetHandler(w http.ResponseWriter, r *http.Request) {
if auth.Authorize(r) == "" {
auth.NotifyAuthRequired(w, r)
return
}
if !canModifyAllianceSelection() {
renderAllianceSelection(w, r, "Alliance selection has already been finalized.")
return
@@ -133,6 +152,11 @@ func AllianceSelectionResetHandler(w http.ResponseWriter, r *http.Request) {
// Saves the selected alliances to the database and generates the first round of elimination matches.
func AllianceSelectionFinalizeHandler(w http.ResponseWriter, r *http.Request) {
if auth.Authorize(r) == "" {
auth.NotifyAuthRequired(w, r)
return
}
if !canModifyAllianceSelection() {
renderAllianceSelection(w, r, "Alliance selection has already been finalized.")
return

View File

@@ -12,6 +12,11 @@ import (
// Shows the field configuration page.
func FieldGetHandler(w http.ResponseWriter, r *http.Request) {
if auth.Authorize(r) == "" {
auth.NotifyAuthRequired(w, r)
return
}
template, err := template.ParseFiles("templates/field.html", "templates/base.html")
if err != nil {
handleWebErr(w, err)
@@ -30,6 +35,11 @@ func FieldGetHandler(w http.ResponseWriter, r *http.Request) {
// Updates the display-station mapping for a single display.
func FieldPostHandler(w http.ResponseWriter, r *http.Request) {
if auth.Authorize(r) == "" {
auth.NotifyAuthRequired(w, r)
return
}
displayId := r.PostFormValue("displayId")
allianceStation := r.PostFormValue("allianceStation")
mainArena.allianceStationDisplays[displayId] = allianceStation
@@ -39,6 +49,11 @@ func FieldPostHandler(w http.ResponseWriter, r *http.Request) {
// Force-reloads all the websocket-connected displays.
func FieldReloadDisplaysHandler(w http.ResponseWriter, r *http.Request) {
if auth.Authorize(r) == "" {
auth.NotifyAuthRequired(w, r)
return
}
mainArena.reloadDisplaysNotifier.Notify(nil)
http.Redirect(w, r, "/setup/field", 302)
}

View File

@@ -13,6 +13,11 @@ import (
// Shows the lower third configuration page.
func LowerThirdsGetHandler(w http.ResponseWriter, r *http.Request) {
if auth.Authorize(r) == "" {
auth.NotifyAuthRequired(w, r)
return
}
template, err := template.ParseFiles("templates/lower_thirds.html", "templates/base.html")
if err != nil {
handleWebErr(w, err)
@@ -36,6 +41,11 @@ func LowerThirdsGetHandler(w http.ResponseWriter, r *http.Request) {
// Saves the new or modified lower third to the database and triggers showing it on the audience display.
func LowerThirdsPostHandler(w http.ResponseWriter, r *http.Request) {
if auth.Authorize(r) == "" {
auth.NotifyAuthRequired(w, r)
return
}
lowerThirdId, _ := strconv.Atoi(r.PostFormValue("id"))
lowerThird, err := db.GetLowerThirdById(lowerThirdId)
if err != nil {

View File

@@ -21,6 +21,11 @@ var cachedTeamFirstMatches map[int]string
// Shows the schedule editing page.
func ScheduleGetHandler(w http.ResponseWriter, r *http.Request) {
if auth.Authorize(r) == "" {
auth.NotifyAuthRequired(w, r)
return
}
if len(cachedScheduleBlocks) == 0 {
tomorrow := time.Now().AddDate(0, 0, 1)
location, _ := time.LoadLocation("Local")
@@ -33,6 +38,11 @@ func ScheduleGetHandler(w http.ResponseWriter, r *http.Request) {
// Generates the schedule and presents it for review without saving it to the database.
func ScheduleGeneratePostHandler(w http.ResponseWriter, r *http.Request) {
if auth.Authorize(r) == "" {
auth.NotifyAuthRequired(w, r)
return
}
r.ParseForm()
cachedMatchType = r.PostFormValue("matchType")
scheduleBlocks, err := getScheduleBlocks(r)
@@ -88,6 +98,11 @@ func ScheduleGeneratePostHandler(w http.ResponseWriter, r *http.Request) {
// Saves the generated schedule to the database.
func ScheduleSavePostHandler(w http.ResponseWriter, r *http.Request) {
if auth.Authorize(r) == "" {
auth.NotifyAuthRequired(w, r)
return
}
existingMatches, err := db.GetMatchesByType(cachedMatchType)
if err != nil {
handleWebErr(w, err)

View File

@@ -20,11 +20,20 @@ import (
// Shows the event settings editing page.
func SettingsGetHandler(w http.ResponseWriter, r *http.Request) {
if auth.Authorize(r) == "" {
auth.NotifyAuthRequired(w, r)
return
}
renderSettings(w, r, "")
}
// Saves the event settings.
func SettingsPostHandler(w http.ResponseWriter, r *http.Request) {
if auth.Authorize(r) == "" {
auth.NotifyAuthRequired(w, r)
return
}
eventSettings.Name = r.PostFormValue("name")
eventSettings.Code = r.PostFormValue("code")
match, _ := regexp.MatchString("^#([0-9A-Fa-f]{3}){1,2}$", r.PostFormValue("displayBackgroundColor"))
@@ -74,6 +83,11 @@ func SettingsPostHandler(w http.ResponseWriter, r *http.Request) {
// Sends a copy of the event database file to the client as a download.
func SaveDbHandler(w http.ResponseWriter, r *http.Request) {
if auth.Authorize(r) == "" {
auth.NotifyAuthRequired(w, r)
return
}
dbFile, err := os.Open(db.path)
defer dbFile.Close()
if err != nil {
@@ -88,6 +102,11 @@ func SaveDbHandler(w http.ResponseWriter, r *http.Request) {
// Accepts an event database file as an upload and loads it.
func RestoreDbHandler(w http.ResponseWriter, r *http.Request) {
if auth.Authorize(r) == "" {
auth.NotifyAuthRequired(w, r)
return
}
file, _, err := r.FormFile("databaseFile")
if err != nil {
renderSettings(w, r, "No database backup file was specified.")
@@ -131,6 +150,11 @@ func RestoreDbHandler(w http.ResponseWriter, r *http.Request) {
// Deletes all data except for the team list.
func ClearDbHandler(w http.ResponseWriter, r *http.Request) {
if auth.Authorize(r) == "" {
auth.NotifyAuthRequired(w, r)
return
}
err := db.TruncateMatches()
if err != nil {
handleWebErr(w, err)

View File

@@ -144,6 +144,7 @@ func postFileHttpResponse(path string, paramName string, file *bytes.Buffer) *ht
writer.Close()
recorder := httptest.NewRecorder()
req, _ := http.NewRequest("POST", path, body)
req.SetBasicAuth("chezychamps", "1234Five")
req.Header.Set("Content-Type", writer.FormDataContentType())
newHandler().ServeHTTP(recorder, req)
return recorder

View File

@@ -13,6 +13,11 @@ import (
// Shows the sponsor slides configuration page.
func SponsorSlidesGetHandler(w http.ResponseWriter, r *http.Request) {
if auth.Authorize(r) == "" {
auth.NotifyAuthRequired(w, r)
return
}
template, err := template.ParseFiles("templates/sponsor_slides.html", "templates/base.html")
if err != nil {
handleWebErr(w, err)
@@ -36,6 +41,11 @@ func SponsorSlidesGetHandler(w http.ResponseWriter, r *http.Request) {
// Saves the new or modified sponsor slides to the database.
func SponsorSlidesPostHandler(w http.ResponseWriter, r *http.Request) {
if auth.Authorize(r) == "" {
auth.NotifyAuthRequired(w, r)
return
}
sponsorSlideId, _ := strconv.Atoi(r.PostFormValue("id"))
sponsorSlide, err := db.GetSponsorSlideById(sponsorSlideId)
if err != nil {

View File

@@ -27,11 +27,20 @@ var officialTeamInfo map[int][]string
// Shows the team list.
func TeamsGetHandler(w http.ResponseWriter, r *http.Request) {
if auth.Authorize(r) == "" {
auth.NotifyAuthRequired(w, r)
return
}
renderTeams(w, r, false)
}
// Adds teams to the team list.
func TeamsPostHandler(w http.ResponseWriter, r *http.Request) {
if auth.Authorize(r) == "" {
auth.NotifyAuthRequired(w, r)
return
}
if !canModifyTeamList() {
renderTeams(w, r, true)
return
@@ -62,6 +71,11 @@ func TeamsPostHandler(w http.ResponseWriter, r *http.Request) {
// Clears the team list.
func TeamsClearHandler(w http.ResponseWriter, r *http.Request) {
if auth.Authorize(r) == "" {
auth.NotifyAuthRequired(w, r)
return
}
if !canModifyTeamList() {
renderTeams(w, r, true)
return
@@ -77,6 +91,11 @@ func TeamsClearHandler(w http.ResponseWriter, r *http.Request) {
// Shows the page to edit a team's fields.
func TeamEditGetHandler(w http.ResponseWriter, r *http.Request) {
if auth.Authorize(r) == "" {
auth.NotifyAuthRequired(w, r)
return
}
vars := mux.Vars(r)
teamId, _ := strconv.Atoi(vars["id"])
team, err := db.GetTeamById(teamId)
@@ -107,6 +126,11 @@ func TeamEditGetHandler(w http.ResponseWriter, r *http.Request) {
// Updates a team's fields.
func TeamEditPostHandler(w http.ResponseWriter, r *http.Request) {
if auth.Authorize(r) == "" {
auth.NotifyAuthRequired(w, r)
return
}
vars := mux.Vars(r)
teamId, _ := strconv.Atoi(vars["id"])
team, err := db.GetTeamById(teamId)
@@ -144,6 +168,11 @@ func TeamEditPostHandler(w http.ResponseWriter, r *http.Request) {
// Removes a team from the team list.
func TeamDeletePostHandler(w http.ResponseWriter, r *http.Request) {
if auth.Authorize(r) == "" {
auth.NotifyAuthRequired(w, r)
return
}
if !canModifyTeamList() {
renderTeams(w, r, true)
return
@@ -170,6 +199,11 @@ func TeamDeletePostHandler(w http.ResponseWriter, r *http.Request) {
// Publishes the team list to the web.
func TeamsPublishHandler(w http.ResponseWriter, r *http.Request) {
if auth.Authorize(r) == "" {
auth.NotifyAuthRequired(w, r)
return
}
err := PublishTeams()
if err != nil {
handleWebErr(w, err)
@@ -180,6 +214,11 @@ func TeamsPublishHandler(w http.ResponseWriter, r *http.Request) {
// Generates random WPA keys and saves them to the team models.
func TeamsGenerateWpaKeysHandler(w http.ResponseWriter, r *http.Request) {
if auth.Authorize(r) == "" {
auth.NotifyAuthRequired(w, r)
return
}
generateAllKeys := false
if all, ok := r.URL.Query()["all"]; ok {
generateAllKeys = all[0] == "true"

7
web.go
View File

@@ -6,6 +6,7 @@
package main
import (
"bitbucket.org/rj/httpauth-go"
"fmt"
"github.com/gorilla/mux"
"github.com/gorilla/websocket"
@@ -17,6 +18,7 @@ import (
const httpPort = 8080
var websocketUpgrader = websocket.Upgrader{ReadBufferSize: 1024, WriteBufferSize: 2014}
var auth = httpauth.NewBasic("Cheesy Arena", authenticate, nil)
// Helper functions that can be used inside templates.
var templateHelpers = template.FuncMap{
@@ -98,6 +100,11 @@ func ServeWebInterface() {
http.ListenAndServe(fmt.Sprintf(":%d", httpPort), nil)
}
func authenticate(user, password string) bool {
// TODO(patrick): Replace this with something better before general release.
return user == "chezychamps" && password == "1234Five"
}
func newHandler() http.Handler {
router := mux.NewRouter()
router.HandleFunc("/setup/settings", SettingsGetHandler).Methods("GET")

View File

@@ -28,6 +28,7 @@ func TestIndex(t *testing.T) {
func getHttpResponse(path string) *httptest.ResponseRecorder {
recorder := httptest.NewRecorder()
req, _ := http.NewRequest("GET", path, nil)
req.SetBasicAuth("chezychamps", "1234Five")
newHandler().ServeHTTP(recorder, req)
return recorder
}
@@ -35,6 +36,7 @@ func getHttpResponse(path string) *httptest.ResponseRecorder {
func postHttpResponse(path string, body string) *httptest.ResponseRecorder {
recorder := httptest.NewRecorder()
req, _ := http.NewRequest("POST", path, strings.NewReader(body))
req.SetBasicAuth("chezychamps", "1234Five")
req.Header.Set("Content-Type", "application/x-www-form-urlencoded; param=value")
newHandler().ServeHTTP(recorder, req)
return recorder