add Rate Limiter & fix

This commit is contained in:
2026-04-28 15:00:21 +03:00
parent 7a60bb15fe
commit 38cc75a688
5 changed files with 196 additions and 58 deletions

View File

@@ -18,10 +18,7 @@ import io.vertx.ext.web.sstore.redis.RedisSessionStore;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import su.xserver.iikocon.config.AppConfig;
import su.xserver.iikocon.handler.AdminHandler;
import su.xserver.iikocon.handler.AuthHandler;
import su.xserver.iikocon.handler.SecurityHandler;
import su.xserver.iikocon.handler.SetupHandler;
import su.xserver.iikocon.handler.*;
import su.xserver.iikocon.iiko.IikoOlapClient;
import su.xserver.iikocon.service.*;
@@ -63,12 +60,10 @@ public class MainVerticle extends AbstractVerticle {
db = new DataBaseService(vertx, config.database);
redis = new RedisService(vertx, config.redis);
// Инициализация сервисов
userService = new UserService(db.getPool());
restaurantService = new RestaurantService(db.getPool());
settingsService = new SettingsService(db.getPool());
// Инициализация БД (создание таблицы users)
userService.initDatabase().onFailure(err -> {
log.error("Failed to initialize database", err);
startPromise.fail(err);
@@ -125,7 +120,7 @@ public class MainVerticle extends AbstractVerticle {
SecurityHandler securityHandlers = new SecurityHandler(settingsService);
// Обработчики безопасности (порядок важен)
// Обработчики безопасности
router.route().handler(securityHandlers.hostValidator());
router.route().handler(securityHandlers.proxyHeadersHandler());
router.route().handler(securityHandlers.cspHeader());
@@ -161,6 +156,13 @@ public class MainVerticle extends AbstractVerticle {
}
});
// Rate Limiter Handler
RedisRateLimiter limiter = new RedisRateLimiter(
redis.getRedis(), 60, 60_000
);
router.route().handler(limiter);
// Health Checks
HealthCheckService healthCheckService = new HealthCheckService(vertx, redis, db);
healthCheckService.registerHealthCheck(router);
@@ -182,7 +184,6 @@ public class MainVerticle extends AbstractVerticle {
rc.response().setStatusCode(403).end(new JsonObject().put("error", "Registration is disabled").encode());
return;
}
// существующий код регистрации
JsonObject body = rc.body().asJsonObject();
String login = body.getString("login");
String email = body.getString("email");
@@ -197,7 +198,6 @@ public class MainVerticle extends AbstractVerticle {
.onFailure(err -> rc.response().setStatusCode(500).end(err.getMessage()));
}));
// В initRouter после настройки authHandler, до объявления /api/admin/*:
router.route("/api/profile").handler(authHandler::requireAuth);
router.get("/api/profile").handler(rc -> {
Integer userId = rc.session().get("userId");
@@ -218,29 +218,8 @@ public class MainVerticle extends AbstractVerticle {
})
.onFailure(err -> rc.response().setStatusCode(500).end(err.getMessage()));
});
router.put("/api/admin/language").handler(rc -> {
Integer userId = rc.session().get("userId");
JsonObject body = rc.body().asJsonObject();
String language = body.getString("language");
if (language == null || (!"en".equals(language) && !"ru".equals(language))) {
rc.response().setStatusCode(400).end("Invalid language");
return;
}
userService.updateLanguage(userId, language)
.onSuccess(v -> {
rc.session().put("language", language);
rc.response().end(new JsonObject().put("success", true).encode());
})
.onFailure(err -> rc.response().setStatusCode(500).end(err.getMessage()));
});
// Затем существующий блок router.route("/api/admin/*").handler(authHandler::requireAuth);
router.route("/api/admin/*").handler(authHandler::requireAuth);
// Добавить проверку роли для чувствительных эндпоинтов:
// router.route("/api/settings/meta*").handler(AdminHandler::requireAdmin);
// router.route("/api/admin/settings*").handler(AdminHandler::requireAdmin);
// router.route("/api/admin/active-sessions").handler(AdminHandler::requireAdmin);
router.get("/api/admin/users").handler(rc -> userService.getAllUsers().onComplete(ar -> {
if (ar.succeeded()) {
rc.response()
@@ -251,6 +230,7 @@ public class MainVerticle extends AbstractVerticle {
}
}));
router.route("/api/admin/users*").handler(AdminHandler::requireAdmin);
router.post("/api/admin/users").handler(rc -> {
JsonObject body = rc.body().asJsonObject();
String login = body.getString("login");
@@ -394,14 +374,12 @@ public class MainVerticle extends AbstractVerticle {
.onFailure(err -> rc.response().setStatusCode(500).end(err.getMessage()));
});
// Получение всех настроек
router.get("/api/settings").handler(rc -> {
settingsService.getPublicSettings()
.onSuccess(settings -> rc.response().putHeader("Content-Type", "application/json").end(settings.encode()))
.onFailure(err -> rc.response().setStatusCode(500).end());
});
// Получить метаданные всех настроек (для построения формы)
router.route("/api/admin/settings*").handler(AdminHandler::requireAdmin);
router.get("/api/admin/settings/meta").handler(rc -> {
settingsService.getMetadata()
@@ -409,14 +387,12 @@ public class MainVerticle extends AbstractVerticle {
.onFailure(err -> rc.response().setStatusCode(500).end(err.getMessage()));
});
// Получить все настройки со значениями по умолчанию
router.get("/api/admin/settings").handler(rc -> {
settingsService.getAllWithDefaults()
.onSuccess(settings -> rc.response().putHeader("Content-Type", "application/json").end(settings.encode()))
.onFailure(err -> rc.response().setStatusCode(500).end(err.getMessage()));
});
// Обновление настроек (админ)
router.put("/api/admin/settings").handler(rc -> {
JsonObject body = rc.body().asJsonObject();
List<Future<Void>> futures = new ArrayList<>(); // явно указываем тип Future<Void>