Files
iiko-connector/src/main/java/su/xserver/iikocon/UserService.java
2026-04-18 13:34:20 +03:00

168 lines
6.3 KiB
Java
Raw Blame History

This file contains ambiguous Unicode characters
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
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.Tuple;
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<Void> initDatabase() {
String createTable = """
CREATE TABLE IF NOT EXISTS users (
id INT AUTO_INCREMENT PRIMARY KEY,
login VARCHAR(255) UNIQUE NOT NULL,
email VARCHAR(255) UNIQUE NOT NULL,
password VARCHAR(255) NOT NULL,
active BOOLEAN DEFAULT FALSE,
ip VARCHAR(45),
created TIMESTAMP DEFAULT CURRENT_TIMESTAMP,
updated TIMESTAMP DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP
)
""";
return pool.query(createTable).execute().mapEmpty();
}
public Future<Long> countUsers() {
return pool.query("SELECT COUNT(*) AS cnt FROM users")
.execute()
.map(rows -> rows.iterator().next().getLong("cnt"));
}
public Future<Void> createUser(String login, String email, String password, String ip, boolean active) {
String hash = BCrypt.hashpw(password, BCrypt.gensalt());
Map<String, Object> params = Map.of(
"login", login,
"email", email,
"password", hash,
"ip", ip,
"active", active
);
return SqlTemplate.forUpdate(pool,
"INSERT INTO users (login, email, password, ip, active) VALUES (#{login}, #{email}, #{password}, #{ip}, #{active})")
.execute(params)
.mapEmpty();
}
// Существующий метод оставляем, но он будет создавать неактивного пользователя (active = false)
public Future<Void> createUser(String login, String email, String password, String ip) {
return createUser(login, email, password, ip, false);
}
public Future<Void> 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();
}
public Future<JsonObject> findByLoginOrEmail(String loginOrEmail) {
String sql = "SELECT id, login, email, password, active, ip, created, updated FROM users WHERE login = ? OR email = ?";
return pool.preparedQuery(sql)
.execute(Tuple.of(loginOrEmail, loginOrEmail))
.map(rows -> {
if (rows.size() == 0) {
return null;
}
Row row = rows.iterator().next();
return toJson(row);
});
}
public Future<JsonObject> findByEmail(String email) {
return SqlTemplate.forQuery(pool, "SELECT id, login, email, password, active, ip, created, updated FROM users WHERE email = #{email}")
.mapTo(this::toJson)
.execute(Map.of("email", email))
.map(rows -> rows.iterator().hasNext() ? rows.iterator().next() : null);
}
public Future<JsonObject> 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<JsonArray> getAllUsers() {
return pool.query("SELECT id, login, email, active, ip, created, updated 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("email", row.getString("email"))
.put("active", row.getBoolean("active"))
.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));
}
return array;
});
}
public Future<Void> updateUser(int id, String login, String email, String password, String ip) {
Map<String, Object> params = new HashMap<>();
params.put("id", id);
params.put("login", login);
params.put("email", email);
params.put("ip", ip);
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} WHERE id = #{id}";
} else {
sql = "UPDATE users SET login = #{login}, email = #{email}, ip = #{ip} WHERE id = #{id}";
}
return SqlTemplate.forUpdate(pool, sql).execute(params).mapEmpty();
}
public Future<Void> deleteUser(int id) {
return SqlTemplate.forUpdate(pool, "DELETE FROM users WHERE id = #{id}")
.execute(Collections.singletonMap("id", id))
.mapEmpty();
}
public boolean checkPassword(String plain, String hash) {
try {
return BCrypt.checkpw(plain, hash);
} catch (Exception e) {
return false;
}
}
private JsonObject toJson(Row row) {
return new JsonObject()
.put("id", row.getInteger("id"))
.put("login", row.getString("login"))
.put("email", row.getString("email"))
.put("password", row.getString("password")) // ← ДОБАВИТЬ ЭТУ СТРОКУ
.put("active", row.getBoolean("active"))
.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);
}
}