package su.xserver.iikocon; import io.vertx.core.Future; import io.vertx.core.json.JsonArray; import io.vertx.core.json.JsonObject; import io.vertx.sqlclient.Pool; import io.vertx.sqlclient.Row; import io.vertx.sqlclient.templates.SqlTemplate; import org.mindrot.jbcrypt.BCrypt; import java.util.Collections; import java.util.HashMap; import java.util.Map; public class UserService { private final Pool pool; public UserService(Pool pool) { this.pool = pool; } public Future initDatabase() { String createTable = """ CREATE TABLE IF NOT EXISTS users ( id INT AUTO_INCREMENT PRIMARY KEY, login VARCHAR(255) UNIQUE NOT NULL, password VARCHAR(255) NOT NULL, created TIMESTAMP DEFAULT CURRENT_TIMESTAMP, updated TIMESTAMP DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP, ip VARCHAR(45) ) """; return pool.query(createTable).execute().mapEmpty(); } public Future countUsers() { return pool.query("SELECT COUNT(*) AS cnt FROM users") .execute() .map(rows -> rows.iterator().next().getLong("cnt")); } public Future createUser(String login, String password, String ip) { String hash = BCrypt.hashpw(password, BCrypt.gensalt()); Map params = new HashMap<>(); params.put("login", login); params.put("password", hash); params.put("ip", ip); return SqlTemplate.forUpdate(pool, "INSERT INTO users (login, password, ip) VALUES (#{login}, #{password}, #{ip})") .execute(params) .mapEmpty(); } public Future findByLogin(String login) { return SqlTemplate.forQuery(pool, "SELECT id, login, password, created, updated, ip FROM users WHERE login = #{login}") .mapTo(row -> new JsonObject() .put("id", row.getInteger("id")) .put("login", row.getString("login")) .put("password", row.getString("password")) .put("created", row.getLocalDateTime("created") != null ? row.getLocalDateTime("created").toString() : null) .put("updated", row.getLocalDateTime("updated") != null ? row.getLocalDateTime("updated").toString() : null) .put("ip", row.getString("ip"))) .execute(Collections.singletonMap("login", login)) .map(rows -> rows.iterator().hasNext() ? rows.iterator().next() : null); } public Future getAllUsers() { return pool.query("SELECT id, login, created, updated, ip FROM users ORDER BY id") .execute() .map(rows -> { JsonArray array = new JsonArray(); for (Row row : rows) { array.add(new JsonObject() .put("id", row.getInteger("id")) .put("login", row.getString("login")) .put("created", row.getLocalDateTime("created") != null ? row.getLocalDateTime("created").toString() : null) .put("updated", row.getLocalDateTime("updated") != null ? row.getLocalDateTime("updated").toString() : null) .put("ip", row.getString("ip"))); } return array; }); } public boolean checkPassword(String plain, String hash) { try { return BCrypt.checkpw(plain, hash); } catch (Exception e) { return false; } } }