diff --git a/build.gradle.kts b/build.gradle.kts index 39588ea..e79de0c 100644 --- a/build.gradle.kts +++ b/build.gradle.kts @@ -40,7 +40,6 @@ dependencies { implementation("io.vertx:vertx-launcher-application") implementation("io.vertx:vertx-web-client") implementation("io.vertx:vertx-config") - implementation("io.vertx:vertx-sql-client-templates") implementation("io.vertx:vertx-health-check") implementation("io.vertx:vertx-web") implementation("io.vertx:vertx-mysql-client") diff --git a/libs/vertx-sql-client-templates-5.0.12.jar b/libs/vertx-sql-client-templates-5.0.12.jar deleted file mode 100644 index f95cea5..0000000 Binary files a/libs/vertx-sql-client-templates-5.0.12.jar and /dev/null differ diff --git a/src/main/java/su/xserver/iikocon/MainVerticle.java b/src/main/java/su/xserver/iikocon/MainVerticle.java index 93bab00..14388f5 100644 --- a/src/main/java/su/xserver/iikocon/MainVerticle.java +++ b/src/main/java/su/xserver/iikocon/MainVerticle.java @@ -569,7 +569,7 @@ public class MainVerticle extends AbstractVerticle { return; } - if (!olapQueryService.isValidTableName(tableName)) { + if (olapQueryService.isValidTableName(tableName)) { rc.response().setStatusCode(400).end("Invalid tableName: must start with a letter and contain only letters and digits"); return; } @@ -606,7 +606,7 @@ public class MainVerticle extends AbstractVerticle { return; } - if (!olapQueryService.isValidTableName(tableName)) { + if (olapQueryService.isValidTableName(tableName)) { rc.response().setStatusCode(400).end("Invalid tableName: must start with a letter and contain only letters and digits"); return; } diff --git a/src/main/java/su/xserver/iikocon/iiko/OlapQueryService.java b/src/main/java/su/xserver/iikocon/iiko/OlapQueryService.java index 9074b44..c3707c4 100644 --- a/src/main/java/su/xserver/iikocon/iiko/OlapQueryService.java +++ b/src/main/java/su/xserver/iikocon/iiko/OlapQueryService.java @@ -6,15 +6,14 @@ import io.vertx.core.json.JsonObject; import io.vertx.sqlclient.Pool; import io.vertx.sqlclient.Row; import io.vertx.sqlclient.Tuple; -import io.vertx.sqlclient.templates.SqlTemplate; -import org.slf4j.Logger; -import org.slf4j.LoggerFactory; import su.xserver.iikocon.service.ExternalDataBaseService; +import java.time.LocalDate; +import java.time.ZoneOffset; +import java.time.ZonedDateTime; import java.util.*; public class OlapQueryService { - private static final Logger log = LoggerFactory.getLogger(OlapQueryService.class); private final Pool pool; private final ExternalDataBaseService externalDataBaseService; private final SqlGenerator sqlGenerator; @@ -62,17 +61,16 @@ public class OlapQueryService { public Future createQuery(String name, int dbConnectionId, JsonObject config, List restaurantIds, String generatedSql, boolean active) { JsonObject fullConfig = generateFullIikoJson(config); - Map params = Map.of( - "name", name, - "db_connection_id", dbConnectionId, - "config_json", config.encode(), - "full_config_json", fullConfig.encode(), - "sql_text", generatedSql != null ? generatedSql : "", - "active", active + String sql = "INSERT INTO olap_queries (name, db_connection_id, config_json, full_config_json, sql_text, active) VALUES (?, ?, ?, ?, ?, ?)"; + Tuple params = Tuple.of( + name, + dbConnectionId, + config.encode(), + fullConfig.encode(), + generatedSql != null ? generatedSql : "", + active ); - String sql = "INSERT INTO olap_queries (name, db_connection_id, config_json, full_config_json, sql_text, active) VALUES (#{name}, #{db_connection_id}, #{config_json}, #{full_config_json}, #{sql_text}, #{active})"; - return SqlTemplate.forUpdate(pool, sql) - .execute(params) + return pool.preparedQuery(sql).execute(params) .compose(rows -> getLastInsertId()) .compose(queryId -> linkRestaurants(queryId, restaurantIds).map(queryId)); } @@ -80,22 +78,23 @@ public class OlapQueryService { public Future updateQuery(int id, String name, int dbConnectionId, JsonObject config, List restaurantIds, String generatedSql, boolean active) { JsonObject fullConfig = generateFullIikoJson(config); - Map params = Map.of( - "id", id, - "name", name, - "db_connection_id", dbConnectionId, - "config_json", config.encode(), - "full_config_json", fullConfig.encode(), - "sql_text", generatedSql != null ? generatedSql : "", - "active", active + String sql = "UPDATE olap_queries SET name = ?, db_connection_id = ?, config_json = ?, full_config_json = ?, sql_text = ?, active = ? WHERE id = ?"; + Tuple params = Tuple.of( + name, + dbConnectionId, + config.encode(), + fullConfig.encode(), + generatedSql != null ? generatedSql : "", + active, + id ); - String sql = "UPDATE olap_queries SET name = #{name}, db_connection_id = #{db_connection_id}, config_json = #{config_json}, full_config_json = #{full_config_json}, sql_text = #{sql_text}, active = #{active} WHERE id = #{id}"; - return SqlTemplate.forUpdate(pool, sql) - .execute(params) + return pool.preparedQuery(sql).execute(params) .compose(v -> pool.query("DELETE FROM olap_query_restaurants WHERE query_id = " + id).execute() - .compose(del -> linkRestaurants(id, restaurantIds))).mapEmpty(); + .compose(del -> linkRestaurants(id, restaurantIds))) + .mapEmpty(); } + public JsonObject generateFullIikoJson(JsonObject clientConfig) { String reportType = clientConfig.getString("reportType", "SALES"); boolean buildSummary = clientConfig.getBoolean("buildSummary", false); @@ -153,17 +152,15 @@ public class OlapQueryService { } private JsonObject buildDateFilter(String reportType, String dateToStr, int daysBack) { - // Определяем корректную дату "до" (конец дня) - java.time.ZonedDateTime toDate; + ZonedDateTime toDate; if (dateToStr != null && !dateToStr.isEmpty()) { - toDate = java.time.LocalDate.parse(dateToStr).atStartOfDay(java.time.ZoneOffset.UTC); + toDate = LocalDate.parse(dateToStr).atStartOfDay(ZoneOffset.UTC); } else { - toDate = java.time.ZonedDateTime.now(java.time.ZoneOffset.UTC); + toDate = ZonedDateTime.now(ZoneOffset.UTC); } toDate = toDate.withHour(23).withMinute(59).withSecond(59).withNano(999_999_999); - java.time.ZonedDateTime fromDate = toDate.minusDays(Math.max(1, daysBack)) + ZonedDateTime fromDate = toDate.minusDays(Math.max(1, daysBack)) .withHour(0).withMinute(0).withSecond(0).withNano(0); - String filterKey = "TRANSACTIONS".equals(reportType) ? "DateTime.DateTyped" : "OpenDate.Typed"; return new JsonObject().put(filterKey, new JsonObject() .put("filterType", "DateRange") @@ -179,23 +176,19 @@ public class OlapQueryService { private Future linkRestaurants(int queryId, List restaurantIds) { if (restaurantIds == null || restaurantIds.isEmpty()) return Future.succeededFuture(); + String sql = "INSERT INTO olap_query_restaurants (query_id, restaurant_id) VALUES (?, ?)"; List> futures = new ArrayList<>(); for (Integer restId : restaurantIds) { - Map params = Map.of("query_id", queryId, "restaurant_id", restId); - futures.add(SqlTemplate.forUpdate(pool, - "INSERT INTO olap_query_restaurants (query_id, restaurant_id) VALUES (#{query_id}, #{restaurant_id})") - .execute(params).mapEmpty()); + futures.add(pool.preparedQuery(sql).execute(Tuple.of(queryId, restId)).mapEmpty()); } return Future.all(futures).mapEmpty(); } - // Удаление public Future deleteQuery(int id) { - return SqlTemplate.forUpdate(pool, "DELETE FROM olap_queries WHERE id = #{id}") - .execute(Map.of("id", id)).mapEmpty(); + String sql = "DELETE FROM olap_queries WHERE id = ?"; + return pool.preparedQuery(sql).execute(Tuple.of(id)).mapEmpty(); } - // Получить все запросы (без config_json, для списка) public Future getAllQueries() { String sql = """ SELECT q.id, q.name, q.db_connection_id, q.active, q.last_run, q.last_run_success, q.created, q.updated, @@ -226,13 +219,10 @@ public class OlapQueryService { }); } - - // Получить один запрос с полной конфигурацией public Future getQueryById(int id) { String querySql = "SELECT id, name, db_connection_id, config_json, sql_text, active, created, updated FROM olap_queries WHERE id = ?"; String restaurantsSql = "SELECT restaurant_id FROM olap_query_restaurants WHERE query_id = ?"; - - return pool.preparedQuery(querySql).execute(io.vertx.sqlclient.Tuple.of(id)) + return pool.preparedQuery(querySql).execute(Tuple.of(id)) .compose(rows -> { if (rows.size() == 0) return Future.succeededFuture(null); Row row = rows.iterator().next(); @@ -245,8 +235,7 @@ public class OlapQueryService { .put("active", row.getBoolean("active")) .put("created", row.getLocalDateTime("created") != null ? row.getLocalDateTime("created").toString() : null) .put("updated", row.getLocalDateTime("updated") != null ? row.getLocalDateTime("updated").toString() : null); - - return pool.preparedQuery(restaurantsSql).execute(io.vertx.sqlclient.Tuple.of(id)) + return pool.preparedQuery(restaurantsSql).execute(Tuple.of(id)) .map(restRows -> { JsonArray restIds = new JsonArray(); restRows.forEach(restRow -> restIds.add(restRow.getInteger("restaurant_id"))); @@ -262,7 +251,6 @@ public class OlapQueryService { return pool.preparedQuery(sql).execute(Tuple.of(success, queryId)).mapEmpty(); } - // Генерация SQL на основе конфигурации и ID подключения public Future generateSql(JsonObject config, int dbConnectionId) { return externalDataBaseService.findById(dbConnectionId) .compose(conn -> { @@ -278,9 +266,8 @@ public class OlapQueryService { } public boolean isValidTableName(String tableName) { - if (tableName == null) return false; + if (tableName == null) return true; String trimmed = tableName.trim(); - // Первый символ — английская буква, далее буквы или цифры - return trimmed.matches("^[A-Za-z][A-Za-z0-9]*$"); + return !trimmed.matches("^[A-Za-z][A-Za-z0-9]*$"); } } diff --git a/src/main/java/su/xserver/iikocon/service/ExternalDataBaseService.java b/src/main/java/su/xserver/iikocon/service/ExternalDataBaseService.java index b78a9f5..7d5d378 100644 --- a/src/main/java/su/xserver/iikocon/service/ExternalDataBaseService.java +++ b/src/main/java/su/xserver/iikocon/service/ExternalDataBaseService.java @@ -11,13 +11,9 @@ import io.vertx.jdbcclient.JDBCPool; import io.vertx.sqlclient.Pool; import io.vertx.sqlclient.PoolOptions; import io.vertx.sqlclient.Row; -import io.vertx.sqlclient.templates.SqlTemplate; +import io.vertx.sqlclient.Tuple; import su.xserver.iikocon.handler.AdminHandler; -import java.util.Collections; -import java.util.HashMap; -import java.util.Map; - public class ExternalDataBaseService { private final Pool pool; private final Vertx vertx; @@ -106,7 +102,7 @@ public class ExternalDataBaseService { CREATE TABLE IF NOT EXISTS external_database ( id INT AUTO_INCREMENT PRIMARY KEY, name VARCHAR(255) UNIQUE NOT NULL, - type VARCHAR(40) UNIQUE NOT NULL, + type VARCHAR(40) NOT NULL, host VARCHAR(255) NOT NULL, port INT NOT NULL, database VARCHAR(255) NOT NULL, @@ -120,18 +116,9 @@ public class ExternalDataBaseService { } public Future createDataBase(String name, String type, String host, int port, String database, String user, String password) { - Map params = Map.of( - "name", name, - "type", type, - "host", host, - "port", port, - "database", database, - "user", user, - "password", password - ); - return SqlTemplate.forUpdate(pool, - "INSERT INTO external_database (name, type, host, port, database, user, password) VALUES (#{name}, #{type}, #{host}, #{port}, #{database}, #{user}, #{password})") - .execute(params) + String sql = "INSERT INTO external_database (name, type, host, port, database, user, password) VALUES (?, ?, ?, ?, ?, ?, ?)"; + return pool.preparedQuery(sql) + .execute(Tuple.of(name, type, host, port, database, user, password)) .mapEmpty(); } @@ -159,45 +146,47 @@ public class ExternalDataBaseService { } public Future findById(int id) { - return SqlTemplate.forQuery(pool, - "SELECT id, name, type, host, port, database, user, password, created, updated FROM external_database WHERE id = #{id}") - .mapTo(row -> new JsonObject() - .put("id", row.getInteger("id")) - .put("name", row.getString("name")) - .put("type", row.getString("type")) - .put("host", row.getString("host")) - .put("port", row.getInteger("port")) - .put("database", row.getString("database")) - .put("user", row.getString("user")) - .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)) - .execute(Collections.singletonMap("id", id)) - .map(rows -> rows.iterator().hasNext() ? rows.iterator().next() : null); + String sql = "SELECT id, name, type, host, port, database, user, password, created, updated FROM external_database WHERE id = ?"; + return pool.preparedQuery(sql) + .execute(Tuple.of(id)) + .map(rows -> { + if (rows.iterator().hasNext()) { + Row row = rows.iterator().next(); + return new JsonObject() + .put("id", row.getInteger("id")) + .put("name", row.getString("name")) + .put("type", row.getString("type")) + .put("host", row.getString("host")) + .put("port", row.getInteger("port")) + .put("database", row.getString("database")) + .put("user", row.getString("user")) + .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); + } else { + return null; + } + }); } public Future updateDataBase(int id, String name, String type, String host, int port, String database, String user, String password) { - Map params = new HashMap<>(); - params.put("id", id); - params.put("name", name); - params.put("type", type); - params.put("host", host); - params.put("port", port); - params.put("database", database); - params.put("user", user); String sql; + Tuple params; if (password != null && !password.isEmpty()) { - params.put("password", password); - sql = "UPDATE external_database SET name = #{name}, type = #{type}, host = #{host}, port = #{port}, database = #{database}, user = #{user}, password = #{password} WHERE id = #{id}"; + sql = "UPDATE external_database SET name = ?, type = ?, host = ?, port = ?, database = ?, user = ?, password = ? WHERE id = ?"; + params = Tuple.of(name, type, host, port, database, user, password, id); } else { - sql = "UPDATE external_database SET name = #{name}, type = #{type}, host = #{host}, port = #{port}, database = #{database}, user = #{user} WHERE id = #{id}"; + sql = "UPDATE external_database SET name = ?, type = ?, host = ?, port = ?, database = ?, user = ? WHERE id = ?"; + params = Tuple.of(name, type, host, port, database, user, id); } - return SqlTemplate.forUpdate(pool, sql).execute(params).mapEmpty(); + return pool.preparedQuery(sql) + .execute(params) + .mapEmpty(); } public Future deleteDataBase(int id) { - return SqlTemplate.forUpdate(pool, "DELETE FROM external_database WHERE id = #{id}") - .execute(Collections.singletonMap("id", id)) + return pool.preparedQuery("DELETE FROM external_database WHERE id = ?") + .execute(Tuple.of(id)) .mapEmpty(); } diff --git a/src/main/java/su/xserver/iikocon/service/RestaurantService.java b/src/main/java/su/xserver/iikocon/service/RestaurantService.java index 990b377..3ee04d5 100644 --- a/src/main/java/su/xserver/iikocon/service/RestaurantService.java +++ b/src/main/java/su/xserver/iikocon/service/RestaurantService.java @@ -5,14 +5,11 @@ 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 io.vertx.sqlclient.Tuple; import java.nio.charset.StandardCharsets; import java.security.MessageDigest; import java.security.NoSuchAlgorithmException; -import java.util.Collections; -import java.util.HashMap; -import java.util.Map; public class RestaurantService { private final Pool pool; @@ -43,7 +40,7 @@ public class RestaurantService { CREATE TABLE IF NOT EXISTS restaurants ( id INT AUTO_INCREMENT PRIMARY KEY, name VARCHAR(255) UNIQUE NOT NULL, - login VARCHAR(255) UNIQUE NOT NULL, + login VARCHAR(255) NOT NULL, password VARCHAR(255) NOT NULL, host VARCHAR(255) NOT NULL, https BOOLEAN DEFAULT FALSE, @@ -56,15 +53,9 @@ public class RestaurantService { public Future createRestaurant(String name, String login, String password, String host, boolean https) { String hashedPassword = hashPassword(password); - Map params = Map.of( - "name", name, - "login", login, - "password", hashedPassword, - "host", host, - "https", https - ); - return SqlTemplate.forUpdate(pool, - "INSERT INTO restaurants (name, login, password, host, https) VALUES (#{name}, #{login}, #{password}, #{host}, #{https})") + String sql = "INSERT INTO restaurants (name, login, password, host, https) VALUES (?, ?, ?, ?, ?)"; + Tuple params = Tuple.of(name, login, hashedPassword, host, https); + return pool.preparedQuery(sql) .execute(params) .mapEmpty(); } @@ -91,42 +82,44 @@ public class RestaurantService { } public Future findById(int id) { - return SqlTemplate.forQuery(pool, - "SELECT id, name, login, password, https, host, created, updated FROM restaurants WHERE id = #{id}") - .mapTo(row -> new JsonObject() - .put("id", row.getInteger("id")) - .put("name", row.getString("name")) - .put("login", row.getString("login")) - .put("password", row.getString("password")) - .put("https", row.getBoolean("https")) - .put("host", row.getString("host")) - .put("created", row.getLocalDateTime("created") != null ? row.getLocalDateTime("created").toString() : null) - .put("updated", row.getLocalDateTime("updated") != null ? row.getLocalDateTime("updated").toString() : null)) - .execute(Collections.singletonMap("id", id)) - .map(rows -> rows.iterator().hasNext() ? rows.iterator().next() : null); + String sql = "SELECT id, name, login, password, https, host, created, updated FROM restaurants WHERE id = ?"; + return pool.preparedQuery(sql) + .execute(Tuple.of(id)) + .map(rows -> { + Row row = rows.iterator().hasNext() ? rows.iterator().next() : null; + if (row == null) return null; + return new JsonObject() + .put("id", row.getInteger("id")) + .put("name", row.getString("name")) + .put("login", row.getString("login")) + .put("password", row.getString("password")) + .put("https", row.getBoolean("https")) + .put("host", row.getString("host")) + .put("created", row.getLocalDateTime("created") != null ? row.getLocalDateTime("created").toString() : null) + .put("updated", row.getLocalDateTime("updated") != null ? row.getLocalDateTime("updated").toString() : null); + }); } public Future updateRestaurant(int id, String name, String login, String password, String host, boolean https) { - Map params = new HashMap<>(); - params.put("id", id); - params.put("name", name); - params.put("login", login); - params.put("host", host); - params.put("https", https); String sql; + Tuple params; if (password != null && !password.isEmpty()) { String hashedPassword = hashPassword(password); - params.put("password", hashedPassword); - sql = "UPDATE restaurants SET name = #{name}, login = #{login}, password = #{password}, host = #{host}, https = #{https} WHERE id = #{id}"; + sql = "UPDATE restaurants SET name = ?, login = ?, password = ?, host = ?, https = ? WHERE id = ?"; + params = Tuple.of(name, login, hashedPassword, host, https, id); } else { - sql = "UPDATE restaurants SET name = #{name}, login = #{login}, host = #{host}, https = #{https} WHERE id = #{id}"; + sql = "UPDATE restaurants SET name = ?, login = ?, host = ?, https = ? WHERE id = ?"; + params = Tuple.of(name, login, host, https, id); } - return SqlTemplate.forUpdate(pool, sql).execute(params).mapEmpty(); + return pool.preparedQuery(sql) + .execute(params) + .mapEmpty(); } public Future deleteRestaurant(int id) { - return SqlTemplate.forUpdate(pool, "DELETE FROM restaurants WHERE id = #{id}") - .execute(Collections.singletonMap("id", id)) + String sql = "DELETE FROM restaurants WHERE id = ?"; + return pool.preparedQuery(sql) + .execute(Tuple.of(id)) .mapEmpty(); } } diff --git a/src/main/java/su/xserver/iikocon/service/SettingsService.java b/src/main/java/su/xserver/iikocon/service/SettingsService.java index acd56b1..939eb67 100644 --- a/src/main/java/su/xserver/iikocon/service/SettingsService.java +++ b/src/main/java/su/xserver/iikocon/service/SettingsService.java @@ -4,10 +4,10 @@ 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.templates.SqlTemplate; +import io.vertx.sqlclient.Row; +import io.vertx.sqlclient.Tuple; import java.util.List; -import java.util.Map; public class SettingsService { private final Pool pool; @@ -136,16 +136,20 @@ public class SettingsService { } public Future get(String key) { - return SqlTemplate.forQuery(pool, "SELECT setting_value FROM app_settings WHERE setting_key = #{key}") - .execute(Map.of("key", key)) - .map(rows -> rows.iterator().hasNext() ? rows.iterator().next().getString("setting_value") : null); + String sql = "SELECT setting_value FROM app_settings WHERE setting_key = ?"; + return pool.preparedQuery(sql) + .execute(Tuple.of(key)) + .map(rows -> { + Row row = rows.iterator().hasNext() ? rows.iterator().next() : null; + return row != null ? row.getString("setting_value") : null; + }); } public Future set(String key, String value) { - return SqlTemplate.forUpdate(pool, - "INSERT INTO app_settings (setting_key, setting_value) VALUES (#{key}, #{value}) " + - "ON DUPLICATE KEY UPDATE setting_value = #{value}") - .execute(Map.of("key", key, "value", value)) + String sql = "INSERT INTO app_settings (setting_key, setting_value) VALUES (?, ?) " + + "ON DUPLICATE KEY UPDATE setting_value = ?"; + return pool.preparedQuery(sql) + .execute(Tuple.of(key, value, value)) .mapEmpty(); } diff --git a/src/main/java/su/xserver/iikocon/service/UserService.java b/src/main/java/su/xserver/iikocon/service/UserService.java index 18669e9..4e5e336 100644 --- a/src/main/java/su/xserver/iikocon/service/UserService.java +++ b/src/main/java/su/xserver/iikocon/service/UserService.java @@ -6,7 +6,6 @@ import io.vertx.core.json.JsonObject; import io.vertx.sqlclient.Pool; import io.vertx.sqlclient.Row; import io.vertx.sqlclient.Tuple; -import io.vertx.sqlclient.templates.SqlTemplate; import org.mindrot.jbcrypt.BCrypt; import java.util.*; @@ -44,18 +43,9 @@ public class UserService { public Future createUser(String login, String email, String password, String ip, boolean active, String role) { String hash = BCrypt.hashpw(password, BCrypt.gensalt()); - Map params = Map.of( - "login", login, - "email", email, - "password", hash, - "ip", ip, - "active", active, - "role", role - ); - return SqlTemplate.forUpdate(pool, - "INSERT INTO users (login, email, password, ip, active, role) VALUES (#{login}, #{email}, #{password}, #{ip}, #{active}, #{role})") - .execute(params) - .mapEmpty(); + String sql = "INSERT INTO users (login, email, password, ip, active, role) VALUES (?, ?, ?, ?, ?, ?)"; + Tuple params = Tuple.of(login, email, hash, ip, active, role); + return pool.preparedQuery(sql).execute(params).mapEmpty(); } public Future createUser(String login, String email, String password, String ip, boolean active) { @@ -67,8 +57,9 @@ public class UserService { } public Future setActive(int id, boolean active) { - return SqlTemplate.forUpdate(pool, "UPDATE users SET active = #{active} WHERE id = #{id}") - .execute(Map.of("id", id, "active", active)).mapEmpty(); + return pool.preparedQuery("UPDATE users SET active = ? WHERE id = ?") + .execute(Tuple.of(active, id)) + .mapEmpty(); } public Future findByLoginOrEmail(String loginOrEmail) { @@ -106,24 +97,30 @@ public class UserService { } public Future updateUser(int id, String login, String email, String password, String ip, String role) { - Map params = new HashMap<>(); - params.put("id", id); - params.put("login", login); - params.put("email", email); - params.put("ip", ip); - if (role != null) params.put("role", role); + List values = new ArrayList<>(); + values.add(login); + values.add(email); + values.add(ip); + if (role != null) { + values.add(role); + } String sql; if (password != null && !password.isEmpty()) { String hash = BCrypt.hashpw(password, BCrypt.gensalt()); - params.put("password", hash); - sql = "UPDATE users SET login = #{login}, email = #{email}, password = #{password}, ip = #{ip}" - + (role != null ? ", role = #{role}" : "") + " WHERE id = #{id}"; + sql = "UPDATE users SET login = ?, email = ?, password = ?, ip = ?" + + (role != null ? ", role = ?" : "") + " WHERE id = ?"; + values.add(2, hash); } else { - sql = "UPDATE users SET login = #{login}, email = #{email}, ip = #{ip}" - + (role != null ? ", role = #{role}" : "") + " WHERE id = #{id}"; + sql = "UPDATE users SET login = ?, email = ?, ip = ?" + + (role != null ? ", role = ?" : "") + " WHERE id = ?"; } - return SqlTemplate.forUpdate(pool, sql).execute(params).mapEmpty(); + + values.add(id); // для WHERE + + return pool.preparedQuery(sql) + .execute(Tuple.tuple(values)) + .mapEmpty(); } public Future updateUserIp(int userId, String ip) { @@ -133,54 +130,60 @@ public class UserService { } public Future deleteUser(int id) { - return SqlTemplate.forUpdate(pool, "DELETE FROM users WHERE id = #{id}") - .execute(Collections.singletonMap("id", id)) + return pool.preparedQuery("DELETE FROM users WHERE id = ?") + .execute(Tuple.of(id)) .mapEmpty(); } public Future getProfile(int userId) { - return SqlTemplate.forQuery(pool, - "SELECT id, login, email, role, language, ip, created, updated FROM users WHERE id = #{id}") - .mapTo(row -> new JsonObject() - .put("id", row.getInteger("id")) - .put("login", row.getString("login")) - .put("email", row.getString("email")) - .put("role", row.getString("role")) - .put("language", row.getString("language")) - .put("ip", row.getString("ip")) - .put("created", row.getLocalDateTime("created") != null ? row.getLocalDateTime("created").toString() : null) - .put("updated", row.getLocalDateTime("updated") != null ? row.getLocalDateTime("updated").toString() : null)) - .execute(Map.of("id", userId)) - .map(rows -> rows.iterator().hasNext() ? rows.iterator().next() : null); + String sql = "SELECT id, login, email, role, language, ip, created, updated FROM users WHERE id = ?"; + return pool.preparedQuery(sql) + .execute(Tuple.of(userId)) + .map(rows -> { + if (rows.size() == 0) return null; + Row row = rows.iterator().next(); + return new JsonObject() + .put("id", row.getInteger("id")) + .put("login", row.getString("login")) + .put("email", row.getString("email")) + .put("role", row.getString("role")) + .put("language", row.getString("language")) + .put("ip", row.getString("ip")) + .put("created", row.getLocalDateTime("created") != null ? row.getLocalDateTime("created").toString() : null) + .put("updated", row.getLocalDateTime("updated") != null ? row.getLocalDateTime("updated").toString() : null); + }); } public Future updateProfile(int userId, String email, String password, String language) { - Map params = new HashMap<>(); - params.put("id", userId); List setClauses = new ArrayList<>(); + List values = new ArrayList<>(); if (email != null) { - setClauses.add("email = #{email}"); - params.put("email", email); + setClauses.add("email = ?"); + values.add(email); } if (password != null && !password.isEmpty()) { String hash = BCrypt.hashpw(password, BCrypt.gensalt()); - setClauses.add("password = #{password}"); - params.put("password", hash); + setClauses.add("password = ?"); + values.add(hash); } if (language != null) { - setClauses.add("language = #{language}"); - params.put("language", language); + setClauses.add("language = ?"); + values.add(language); } if (setClauses.isEmpty()) { return Future.succeededFuture(); } - String sql = "UPDATE users SET " + String.join(", ", setClauses) + " WHERE id = #{id}"; - return SqlTemplate.forUpdate(pool, sql).execute(params).mapEmpty(); + values.add(userId); + String sql = "UPDATE users SET " + String.join(", ", setClauses) + " WHERE id = ?"; + + return pool.preparedQuery(sql) + .execute(Tuple.tuple(values)) + .mapEmpty(); } public boolean checkPassword(String plain, String hash) { diff --git a/src/main/java/su/xserver/iikocon/test/DateRangeSetup.java b/src/main/java/su/xserver/iikocon/test/DateRangeSetup.java index 287233b..2e8a4ad 100644 --- a/src/main/java/su/xserver/iikocon/test/DateRangeSetup.java +++ b/src/main/java/su/xserver/iikocon/test/DateRangeSetup.java @@ -18,13 +18,5 @@ public class DateRangeSetup { System.out.println("dateFrom=" + formattedDateFrom); System.out.println("dateTo=" + formattedDateTo); - System.out.println("CodeGenerator=" + CodeGenerator.generateCorporateCode()); - System.out.println("CodeGenerator=" + CodeGenerator.generateCorporateCode()); - System.out.println("CodeGenerator=" + CodeGenerator.generateCorporateCode()); - System.out.println("CodeGenerator=" + CodeGenerator.generateCorporateCode()); - System.out.println("CodeGenerator=" + CodeGenerator.generateCorporateCode()); - System.out.println("CodeGenerator=" + CodeGenerator.generateCorporateCode()); - System.out.println("CodeGenerator=" + CodeGenerator.generateCorporateCode()); - } }