clean and check username and passw better, handle parseForm errors

This commit is contained in:
2026-02-08 21:56:47 -08:00
parent 32ccdcd5f3
commit 4d77999edb
3 changed files with 54 additions and 17 deletions

View File

@@ -207,6 +207,8 @@ func JsonToDB(jsonFile string, userId int) error {
continue continue
} }
// TODO: replace strings.Join with pgx copy
_, err = conn.Exec( _, err = conn.Exec(
context.Background(), context.Background(),
`INSERT INTO history (user_id, timestamp, song_name, artist, album_name, ms_played, platform) VALUES `+ `INSERT INTO history (user_id, timestamp, song_name, artist, album_name, ms_played, platform) VALUES `+

View File

@@ -24,6 +24,16 @@
Unable to create session. Please try again. Unable to create session. Please try again.
</div> </div>
{{end}} {{end}}
{{if eq .Error "userlength"}}
<div class="login-error">
Username length must be greater than 0.
</div>
{{end}}
{{if eq .Error "usertaken"}}
<div class="login-error">
Username must be unique. Please try again.
</div>
{{end}}
</form> </form>
</div> </div>
</body> </body>

View File

@@ -145,7 +145,7 @@ func getUserIdByUsername(ctx context.Context, username string) (int, error) {
} }
func hashPassword(pass []byte) (string, error) { func hashPassword(pass []byte) (string, error) {
if len(pass) < 8 || len(pass) > 64 { if len([]rune(string(pass))) < 8 || len(pass) > 64 {
return "", errors.New("Error: Password must be greater than 8 chars.") return "", errors.New("Error: Password must be greater than 8 chars.")
} }
hashedPassword, err := bcrypt.GenerateFromPassword(pass, bcrypt.DefaultCost) hashedPassword, err := bcrypt.GenerateFromPassword(pass, bcrypt.DefaultCost)
@@ -167,20 +167,29 @@ func verifyPassword(hashedPassword string, enteredPassword []byte) bool {
func createAccount(w http.ResponseWriter, r *http.Request) { func createAccount(w http.ResponseWriter, r *http.Request) {
if r.Method == "POST" { if r.Method == "POST" {
r.ParseForm() err := r.ParseForm()
username := r.FormValue("uname")
hashedPassword, err := hashPassword([]byte(r.FormValue("pass")))
if err != nil { if err != nil {
fmt.Fprintf(os.Stderr, "Error hashing password: %v\n", err) http.Error(w, err.Error(), http.StatusBadRequest)
http.Redirect(w, r, "/createaccount?error=length", http.StatusSeeOther)
return return
} }
err = db.CreateUsersTable() username := r.FormValue("uname")
if len([]rune(string(username))) == 0 {
http.Redirect(w, r, "/createaccount?error=userlength", http.StatusSeeOther)
return
}
var usertaken bool
err = db.Pool.QueryRow(r.Context(),
"SELECT EXISTS(SELECT 1 FROM users WHERE username = $1)", username).
Scan(&usertaken)
if usertaken == true {
http.Redirect(w, r, "/createaccount?error=usertaken", http.StatusSeeOther)
return
}
hashedPassword, err := hashPassword([]byte(r.FormValue("pass")))
if err != nil { if err != nil {
fmt.Fprintf(os.Stderr, "Error ensuring users table exists: %v\n", err) fmt.Fprintf(os.Stderr, "Error hashing password: %v\n", err)
http.Redirect(w, r, "/createaccount", http.StatusSeeOther) http.Redirect(w, r, "/createaccount?error=passlength", http.StatusSeeOther)
return return
} }
@@ -228,12 +237,20 @@ func createAccountPageHandler() http.HandlerFunc {
func loginSubmit(w http.ResponseWriter, r *http.Request) { func loginSubmit(w http.ResponseWriter, r *http.Request) {
if r.Method == "POST" { if r.Method == "POST" {
r.ParseForm() err := r.ParseForm()
if err != nil {
http.Error(w, err.Error(), http.StatusBadRequest)
return
}
username := r.FormValue("uname") username := r.FormValue("uname")
if username == "" {
http.Redirect(w, r, "/login?error=invalid-creds", http.StatusSeeOther)
return
}
password := r.FormValue("pass") password := r.FormValue("pass")
var storedPassword string var storedPassword string
err := db.Pool.QueryRow(r.Context(), "SELECT password FROM users WHERE username = $1;", username). err = db.Pool.QueryRow(r.Context(), "SELECT password FROM users WHERE username = $1;", username).
Scan(&storedPassword) Scan(&storedPassword)
if err != nil { if err != nil {
fmt.Fprintf(os.Stderr, "Cannot get password for entered username: %v\n", err) fmt.Fprintf(os.Stderr, "Cannot get password for entered username: %v\n", err)
@@ -355,11 +372,15 @@ func profilePageHandler() http.HandlerFunc {
func updateDuplicateEditsSetting(w http.ResponseWriter, r *http.Request) { func updateDuplicateEditsSetting(w http.ResponseWriter, r *http.Request) {
if r.Method == "POST" { if r.Method == "POST" {
r.ParseForm() err := r.ParseForm()
if err != nil {
http.Error(w, err.Error(), http.StatusBadRequest)
return
}
username := r.FormValue("username") username := r.FormValue("username")
allow := r.FormValue("allow") == "true" allow := r.FormValue("allow") == "true"
_, err := db.Pool.Exec( _, err = db.Pool.Exec(
r.Context(), r.Context(),
`UPDATE users SET allow_duplicate_edits = $1 WHERE username = $2;`, `UPDATE users SET allow_duplicate_edits = $1 WHERE username = $2;`,
allow, allow,
@@ -411,9 +432,13 @@ func importLastFMHandler(w http.ResponseWriter, r *http.Request) {
return return
} }
r.ParseForm() err = r.ParseForm()
lastfmUsername := r.FormValue("lastfm_username") if err != nil {
lastfmAPIKey := r.FormValue("lastfm_api_key") http.Error(w, err.Error(), http.StatusBadRequest)
return
}
lastfmUsername := template.HTMLEscapeString(r.FormValue("lastfm_username"))
lastfmAPIKey := template.HTMLEscapeString(r.FormValue("lastfm_api_key"))
if lastfmUsername == "" || lastfmAPIKey == "" { if lastfmUsername == "" || lastfmAPIKey == "" {
http.Error(w, "Missing required fields", http.StatusBadRequest) http.Error(w, "Missing required fields", http.StatusBadRequest)