From a5c8467bbb14731847cdf8c37cbde0c91827022a Mon Sep 17 00:00:00 2001 From: xengineering Date: Sat, 20 Jun 2026 17:07:47 +0200 Subject: Add Authenticate() This function validates a username and password against the database. --- password.go | 18 ++++++++++++++++++ password_test.go | 32 ++++++++++++++++++++++++++++++++ 2 files changed, 50 insertions(+) diff --git a/password.go b/password.go index 024ffd7..edbeb7a 100644 --- a/password.go +++ b/password.go @@ -2,6 +2,7 @@ package main import ( "database/sql" + "fmt" _ "github.com/mattn/go-sqlite3" "golang.org/x/crypto/bcrypt" @@ -28,3 +29,20 @@ func Register(db *sql.DB, username, password string) error { return err } + +func Authenticate(db *sql.DB, username, password string) error { + var hash []byte + err := Transaction(db, func(tx *sql.Tx) error { + row := tx.QueryRow( + `SELECT password_bcrypt from users WHERE username=?;`, + username, + ) + + return row.Scan(&hash) + }) + if err != nil { + return fmt.Errorf("Failed to get password hash from database: %w", err) + } + + return bcrypt.CompareHashAndPassword(hash, []byte(password)) +} diff --git a/password_test.go b/password_test.go index f540cc4..a0dfbc3 100644 --- a/password_test.go +++ b/password_test.go @@ -55,3 +55,35 @@ func TestRegister(t *testing.T) { }) } } + +func TestAuthenticate(t *testing.T) { + for _, p := range passwords { + t.Run(p.description, func(t *testing.T) { + db, _ := emptyDB(t) + + err := MigrateToLatest(db) + if err != nil { + t.Fatalf("Could not execute function to test: %v", err) + } + + hash, err := bcrypt.GenerateFromPassword([]byte(p.password), bcryptCost) + if err != nil { + t.Fatalf("Failed to generate test password hash: %v", err) + } + + _, err = db.Exec( + `INSERT INTO users (username, password_bcrypt) VALUES(?, ?);`, + p.username, + hash, + ) + if err != nil { + t.Fatalf("Failed to insert password hash: %v", err) + } + + err = Authenticate(db, p.username, p.password) + if err != nil { + t.Fatalf("Failed to authenticate: %v", err) + } + }) + } +} -- cgit v1.3.1