168 lines
6.3 KiB
Java
168 lines
6.3 KiB
Java
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);
|
||
}
|
||
}
|