package data import ( "database/sql" "fmt" "github.com/go-sql-driver/mysql" "golang.org/x/crypto/bcrypt" ) type DB struct { *sql.DB } func OpenDB(dbName string) (*DB, error) { var err error db := DB{DB: &sql.DB{}} cfg := mysql.NewConfig() cfg.DBName = dbName cfg.User, cfg.Passwd, err = getCredentials() if err != nil { return nil, fmt.Errorf("error reading user credentials for DB: %v", err) } db.DB, err = sql.Open("mysql", cfg.FormatDSN()) if err != nil { return nil, fmt.Errorf("error opening DB: %v", err) } if err = db.Ping(); err != nil { return nil, fmt.Errorf("error pinging DB: %v", err) } return &db, nil } func (db *DB) AddUser(user, pass, first, last string, writer, editor, admin bool) error { hashedPass, err := bcrypt.GenerateFromPassword([]byte(pass), bcrypt.DefaultCost) if err != nil { return fmt.Errorf("error creating password hash: %v", err) } if !permissionsOK(writer, editor, admin) { return fmt.Errorf("error with mutually exclusive permissions: writer = %v, editor = %v, admin = %v", writer, editor, admin) } query := ` INSERT INTO users (username, password, first_name, last_name, writer, editor, admin) VALUES (?, ?, ?, ?, ?, ?) ` _, err = db.Exec(query, user, hashedPass, first, last, writer, editor, admin) if err != nil { return fmt.Errorf("error inserting user into DB: %v", err) } return nil } func (db *DB) ChangePassword(id int64, oldPass, newPass string) error { var oldHashedPass string selectQuery := ` SELECT password FROM users WHERE id = ? ` row := db.QueryRow(selectQuery, id) if err := row.Scan(&oldHashedPass); err != nil { return fmt.Errorf("error reading password from DB: %v", err) } if err := bcrypt.CompareHashAndPassword([]byte(oldHashedPass), []byte(oldPass)); err != nil { return fmt.Errorf("error checking password: %v", err) } newHashedPass, err := bcrypt.GenerateFromPassword([]byte(newPass), bcrypt.DefaultCost) if err != nil { return fmt.Errorf("error creating password hash: %v", err) } updateQuery := ` UPDATE users SET password = ? WHERE id = ? ` _, err = db.Exec(updateQuery, newHashedPass, id) if err != nil { return fmt.Errorf("error updating password in DB: %v", err) } return nil }