Files
yggmail/internal/storage/sqlite3/table_users.go
Neil Alexander ceffe7612d Initial commit
2021-07-07 18:15:07 +01:00

77 lines
1.7 KiB
Go

package sqlite3
import (
"database/sql"
"fmt"
"golang.org/x/crypto/bcrypt"
)
type TableUsers struct {
db *sql.DB
getPassword *sql.Stmt
insertUser *sql.Stmt
}
const usersSchema = `
CREATE TABLE IF NOT EXISTS users (
username TEXT NOT NULL,
password TEXT NOT NULL,
PRIMARY KEY(username)
);
`
const usersGetPassword = `
SELECT password FROM users WHERE username = $1
`
const usersInsertUser = `
INSERT INTO users (username, password) VALUES($1, $2)
`
func NewTableUsers(db *sql.DB) (*TableUsers, error) {
t := &TableUsers{
db: db,
}
_, err := db.Exec(usersSchema)
if err != nil {
return nil, fmt.Errorf("db.Exec: %w", err)
}
t.getPassword, err = db.Prepare(usersGetPassword)
if err != nil {
return nil, fmt.Errorf("db.Prepare(getPassword): %w", err)
}
t.insertUser, err = db.Prepare(usersInsertUser)
if err != nil {
return nil, fmt.Errorf("db.Prepare(usersInsertUser): %w", err)
}
return t, nil
}
func (t *TableUsers) CreateUser(username, password string) error {
hash, err := bcrypt.GenerateFromPassword([]byte(password), bcrypt.DefaultCost)
if err != nil {
return fmt.Errorf("bcrypt.GenerateFromPassword: %w", err)
}
if _, err := t.insertUser.Exec(username, hash); err != nil {
return fmt.Errorf("t.insertUser.Exec: %w", err)
}
return nil
}
func (t *TableUsers) TryAuthenticate(username, password string) (bool, error) {
var dbPasswordHash []byte
err := t.getPassword.QueryRow(username).Scan(&dbPasswordHash)
if err == sql.ErrNoRows {
return false, nil
}
if err != nil {
return false, err
}
err = bcrypt.CompareHashAndPassword(dbPasswordHash, []byte(password))
if err == nil {
return true, nil
}
return false, err
}