feat(güvenlik): giriş ve kayıtta Cloudflare Turnstile, IP başına 3 hatalı denemede 15 dk kilit

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
This commit is contained in:
2026-11-14 00:29:00 +03:00
parent 5cbf97d884
commit a2eff1a984
27 changed files with 1247 additions and 164 deletions
+52
View File
@@ -58,11 +58,63 @@ impl TestApp {
registration,
static_dir: None,
rates_refresh_minutes: 0,
turnstile_site_key: None,
turnstile_secret_key: None,
trust_proxy: true,
};
let router = routes::router(AppState::new(db.clone(), config));
Self { router, db }
}
/// Bot doğrulaması açık (ağsız sabit sonuç) bir uygulama: giriş/kayıt güvenlik testleri
pub async fn with_captcha(pass: bool) -> Self {
let app = Self::new().await;
dotenvy::dotenv().ok();
let config = Config {
mongodb_uri: std::env::var("MONGODB_URI").unwrap(),
jwt_secret: "test-jwt-secret-en-az-32-karakter-olmali!!".into(),
app_url: "http://localhost".into(),
port: 0,
registration: RegistrationMode::Open,
static_dir: None,
rates_refresh_minutes: 0,
turnstile_site_key: Some("test-site-key".into()),
turnstile_secret_key: Some("test-secret".into()),
trust_proxy: true,
};
let state = AppState::new(app.db.clone(), config)
.with_captcha(kakeibo::auth::captcha::Captcha::Fixed(pass));
Self {
router: routes::router(state),
db: app.db,
}
}
pub fn router_clone(&self) -> Router {
self.router.clone()
}
/// Ham istek (başlık eklemek için): (durum, gövde, çerez)
pub async fn send_with(
&self,
req: axum::http::Request<Body>,
) -> (StatusCode, Value, Option<String>) {
let res = self.router.clone().oneshot(req).await.unwrap();
let status = res.status();
let set_cookie = res
.headers()
.get(header::SET_COOKIE)
.and_then(|v| v.to_str().ok())
.and_then(|v| v.split(';').next())
.map(String::from);
let bytes = res.into_body().collect().await.unwrap().to_bytes();
(
status,
serde_json::from_slice(&bytes).unwrap_or(Value::Null),
set_cookie,
)
}
/// Test sonunda geçici veritabanını siler.
pub async fn cleanup(self) {
self.db.drop().await.ok();