From bb2ce6b58973397d165d2eb3bf766d1f6227f923 Mon Sep 17 00:00:00 2001 From: Oskarowski Date: Sat, 26 Oct 2024 20:42:05 +0200 Subject: [PATCH 1/2] proper handling and sanitizing user inputs --- .prettierrc | 2 ++ dist/gameSettingsForm.js | 31 +++++++++++++++++++++ internal/handlers.go | 2 ++ internal/helpers.go | 38 +++++++++++++++++++++----- templates/game/game_settings_form.html | 18 ++++-------- 5 files changed, 72 insertions(+), 19 deletions(-) create mode 100644 dist/gameSettingsForm.js diff --git a/.prettierrc b/.prettierrc index a230de0..0ad8361 100644 --- a/.prettierrc +++ b/.prettierrc @@ -1,4 +1,6 @@ { + "tabWidth": 4, + "useTabs": false, "plugins": [ "prettier-plugin-go-template" ], diff --git a/dist/gameSettingsForm.js b/dist/gameSettingsForm.js new file mode 100644 index 0000000..9f46d39 --- /dev/null +++ b/dist/gameSettingsForm.js @@ -0,0 +1,31 @@ +/** + * Toggles the visibility of the input field with the given id based on the value of the given checkbox. + * If the checkbox is checked, the input field is hidden; otherwise, it is shown. + * @param {string} fieldId - The html id of the field to toggle. + * @param {HTMLInputElement} checkbox - The checkbox element that toggles the input field. + */ +function toggleFieldVisibility(fieldId, checkbox) { + const field = document.getElementById(fieldId); + field.style.display = checkbox.checked ? "none" : "block"; +} + +function adjustMinesInputFieldRange() { + const gridSizeValue = document.getElementById( + "grid-size-input-field", + ).value; + const minesInputField = document.getElementById("mines-input-field"); + + if (gridSizeValue) { + const maxMines = Math.floor(gridSizeValue ** 2 * 0.8); + minesInputField.min = 1; + minesInputField.max = maxMines; + minesInputField.placeholder = `Enter number of mines (max: ${maxMines})`; + } +} + +window.addEventListener("load", () => { + const gridSizeInputField = document.getElementById("grid-size-input-field"); + + const maxGridSizeBasedOnScreenSize = window.innerWidth < 768 ? 15 : 50; + gridSizeInputField.max = maxGridSizeBasedOnScreenSize; +}); diff --git a/internal/handlers.go b/internal/handlers.go index dc7307c..7e5d7ae 100644 --- a/internal/handlers.go +++ b/internal/handlers.go @@ -93,6 +93,7 @@ func (h *Handler) StartGame(w http.ResponseWriter, r *http.Request) { ErrorMessage: err.Error(), ShowCloseBtn: true, }) + log.Printf("Error parsing form: %v", err) return } @@ -109,6 +110,7 @@ func (h *Handler) StartGame(w http.ResponseWriter, r *http.Request) { ErrorMessage: formValidationErr.Error(), ShowCloseBtn: true, }) + log.Printf("Form validation error: %v", formValidationErr) return } diff --git a/internal/helpers.go b/internal/helpers.go index 61e5379..4ca195e 100644 --- a/internal/helpers.go +++ b/internal/helpers.go @@ -4,6 +4,7 @@ import ( "bytes" "context" "errors" + "fmt" "html/template" "math/rand" "minesweeper/internal/db" @@ -30,6 +31,13 @@ func GetTotalGamesCount(queries *db.Queries) (int64, error) { return count, nil } +const ( + MinGridSize = 2 + MaxGridSize = 50 + MinMinesRatio = 0.1 + MaxMinesRatio = 0.8 +) + type GameSettings struct { GridSize int MinesAmount int @@ -41,34 +49,50 @@ func ValidateGameSettingsForm(gridSizeStr, minesAmountStr, randomMinesStr, rando gridSizeErr, minesAmountErr error ) + // Check if grid size should be random or user-defined, if so check if it's within accepted bounds if randomGridSizeStr == "on" { - // TODO - load min and max grid size from config - gridSize = rand.Intn(10) + 5 // range(5, 15) + gridSize = rand.Intn(MaxGridSize-MinGridSize+1) + MinGridSize gridSizeErr = nil } else { gridSize, gridSizeErr = strconv.Atoi(gridSizeStr) + if gridSizeErr != nil { + return GameSettings{}, errors.New("invalid grid size: must be a proper grid size number") + } + + if gridSize < MinGridSize || gridSize > MaxGridSize { + return GameSettings{}, errors.New("grid size must be between 2 and 50") + } } + minMines := int(float64(gridSize*gridSize) * MinMinesRatio) + maxMines := int(float64(gridSize*gridSize) * MaxMinesRatio) + + // Check if mines amount should be random or user-defined, if so check if it's within accepted bounds if randomMinesStr == "on" { if gridSize > 0 { - minesAmount = rand.Intn((gridSize*gridSize)/2) + 1 + + minesAmount = rand.Intn((maxMines - minMines + 1)) + minMines minesAmountErr = nil } else { return GameSettings{}, errors.New("grid size must be valid when using random mines") } } else { minesAmount, minesAmountErr = strconv.Atoi(minesAmountStr) + + if minesAmountErr != nil { + return GameSettings{}, errors.New("invalid mines amount: must be a number") + } + + if minesAmount <= 0 || minesAmount > maxMines { + return GameSettings{}, fmt.Errorf("mines amount must be between 1 and %v of the grid size", maxMines) + } } if gridSizeErr != nil || minesAmountErr != nil { return GameSettings{}, errors.New("invalid input values") } - if gridSize <= 0 || minesAmount <= 0 { - return GameSettings{}, errors.New("the grid size and mines amount must be greater than 0") - } - return GameSettings{ GridSize: gridSize, MinesAmount: minesAmount, diff --git a/templates/game/game_settings_form.html b/templates/game/game_settings_form.html index ad4e63e..308fb78 100644 --- a/templates/game/game_settings_form.html +++ b/templates/game/game_settings_form.html @@ -29,6 +29,9 @@ name="grid-size" class="w-full px-3 py-2 border rounded focus:outline-none focus:ring-2 focus:ring-blue-500" placeholder="Enter grid size (e.g., 10)" + min="2" + max="50" + onchange="adjustMinesInputFieldRange(this)" /> @@ -70,6 +73,8 @@ name="mines-amount" class="w-full px-3 py-2 border rounded focus:outline-none focus:ring-2 focus:ring-blue-500" placeholder="Enter number of mines" + min="1" + max="1000" /> @@ -104,16 +109,5 @@ - + {{ end }} From d89949c9ba263ba40f0446bea2dc573f8f350601 Mon Sep 17 00:00:00 2001 From: Oskarowski Date: Sat, 26 Oct 2024 21:36:33 +0200 Subject: [PATCH 2/2] css is hard, limit game size to 22x22 --- dist/gameSettingsForm.js | 15 +++++++++++++-- internal/helpers.go | 2 +- templates/game/game_grid.html | 3 ++- templates/game/game_layout.html | 4 +--- templates/game/game_settings_form.html | 2 +- 5 files changed, 18 insertions(+), 8 deletions(-) diff --git a/dist/gameSettingsForm.js b/dist/gameSettingsForm.js index 9f46d39..66b545a 100644 --- a/dist/gameSettingsForm.js +++ b/dist/gameSettingsForm.js @@ -6,7 +6,14 @@ */ function toggleFieldVisibility(fieldId, checkbox) { const field = document.getElementById(fieldId); - field.style.display = checkbox.checked ? "none" : "block"; + if (checkbox.checked) { + // Clear the value and hide the field when checkbox is checked + field.value = ""; + adjustMinesInputFieldRange(); + field.style.display = "none"; + } else { + field.style.display = "block"; + } } function adjustMinesInputFieldRange() { @@ -20,12 +27,16 @@ function adjustMinesInputFieldRange() { minesInputField.min = 1; minesInputField.max = maxMines; minesInputField.placeholder = `Enter number of mines (max: ${maxMines})`; + } else { + minesInputField.min = 1; + minesInputField.max = 350; + minesInputField.placeholder = "Enter number of mines"; } } window.addEventListener("load", () => { const gridSizeInputField = document.getElementById("grid-size-input-field"); - const maxGridSizeBasedOnScreenSize = window.innerWidth < 768 ? 15 : 50; + const maxGridSizeBasedOnScreenSize = window.innerWidth < 768 ? 10 : 22; gridSizeInputField.max = maxGridSizeBasedOnScreenSize; }); diff --git a/internal/helpers.go b/internal/helpers.go index 4ca195e..8267bf2 100644 --- a/internal/helpers.go +++ b/internal/helpers.go @@ -33,7 +33,7 @@ func GetTotalGamesCount(queries *db.Queries) (int64, error) { const ( MinGridSize = 2 - MaxGridSize = 50 + MaxGridSize = 22 MinMinesRatio = 0.1 MaxMinesRatio = 0.8 ) diff --git a/templates/game/game_grid.html b/templates/game/game_grid.html index 836baf0..aa65ad1 100644 --- a/templates/game/game_grid.html +++ b/templates/game/game_grid.html @@ -1,6 +1,7 @@ {{ define "game_grid" }}
- + {{ if or $cell.IsRevealed $.GameFailed $.GameWon }} {{ if $cell.HasMine }} 💣 diff --git a/templates/game/game_layout.html b/templates/game/game_layout.html index 096128a..6b840a8 100644 --- a/templates/game/game_layout.html +++ b/templates/game/game_layout.html @@ -4,9 +4,7 @@ --grid-size: {{ .GridSize }}; display: grid; grid-template-columns: repeat(var(--grid-size), 1fr); - max-width: 100%; } -
@@ -42,7 +40,7 @@
{{ .GameGridHtml }}
diff --git a/templates/game/game_settings_form.html b/templates/game/game_settings_form.html index 308fb78..565f712 100644 --- a/templates/game/game_settings_form.html +++ b/templates/game/game_settings_form.html @@ -30,7 +30,7 @@ class="w-full px-3 py-2 border rounded focus:outline-none focus:ring-2 focus:ring-blue-500" placeholder="Enter grid size (e.g., 10)" min="2" - max="50" + max="22" onchange="adjustMinesInputFieldRange(this)" />