package userstore import ( "database/sql" "fmt" "time" "git.keks.cloud/kekskurse/miniauth/pkg/utils" "golang.org/x/crypto/bcrypt" ) type User struct { Username string CreatedAt time.Time UpdatedAt time.Time } func (s Store) UserWrite(username, password string) (int64, error) { query := "INSERT INTO users (username, password) VALUES (?, ?);" log := s.log.With().Str("func", "UserWrite").Str("query", query).Str("username", username).Logger() pwHash, err := bcrypt.GenerateFromPassword([]byte(password), bcrypt.DefaultCost) if err != nil { return 0, utils.WrapError(ErrCantEncryptPassword, err, log) } res, err := s.db.Exec(query, username, string(pwHash)) if err != nil { return 0, utils.WrapError(ErrCantExecuteQuery, err, log) } id, err := res.LastInsertId() if err != nil { return 0, utils.WrapError(ErrCantExecuteQuery, err, log) } return id, nil } func (s Store) UserCheckPassword(username, password string) (User, error) { query := fmt.Sprintf("SELECT %v FROM users WHERE username = ?", s.userGetFields()) log := s.log.With().Str("func", "UserLogin").Str("username", username).Str("query", query).Logger() var pwHash string row := s.db.QueryRow(query, username) user, pwHash, err := s.userScan(row) if err != nil { return User{}, utils.WrapError(ErrCantExecuteQuery, err, log) } err = bcrypt.CompareHashAndPassword([]byte(pwHash), []byte(password)) if err != nil { return User{}, utils.WrapError(ErrPasswordDontMatch, err, log) } return user, nil } func (s Store) userGetFields() string { return "username, password, created_at, updated_at" } func (s Store) userScan(row *sql.Row) (User, string, error) { u := User{} var pwHash string err := row.Scan(&u.Username, &pwHash, &u.CreatedAt, &u.UpdatedAt) if err != nil { return User{}, "", err } return u, pwHash, nil } func (s Store) UserExists(username string) (bool, error) { query := "SELECT COUNT(*) FROM users WHERE username = ?" log := s.log.With().Str("func", "UserExists").Str("query", query).Str("username", username).Logger() var count int err := s.db.QueryRow(query, username).Scan(&count) if err != nil { return true, utils.WrapError(ErrCantExecuteQuery, err, log) } if count == 0 { return false, nil } return true, nil } func (s Store) UserDelete(username string) error { query := "DELETE FROM users WHERE username = ?" log := s.log.With().Str("func", "UserExists").Str("query", query).Str("username", username).Logger() _, err := s.db.Exec(query, username) if err != nil { return utils.WrapError(ErrCantExecuteQuery, err, log) } return nil }