feat(backend): ayarlar, MongoDB bağlantısı, Türkçe hata yapısı ve DB'li health check

- config.rs: ortam değişkenleri ve doğrulama
- db.rs: bağlantı + ping (5 sn zaman aşımı)
- error.rs: AppError → Türkçe JSON hata yanıtı
- /api/health: veritabanına erişilemezse 503

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
This commit is contained in:
2026-11-11 23:09:46 +03:00
parent 306c550b28
commit 125bb7f476
13 changed files with 2068 additions and 27 deletions
+63
View File
@@ -0,0 +1,63 @@
//! Ortam değişkenlerinden uygulama ayarlarını okur.
use std::env;
#[derive(Debug, Clone)]
pub struct Config {
pub mongodb_uri: String,
#[allow(dead_code)] // Faz 1 – Adım 3'te (JWT) kullanılacak
pub jwt_secret: String,
pub app_url: String,
pub port: u16,
}
#[derive(Debug, thiserror::Error)]
pub enum ConfigError {
#[error("{0} ortam değişkeni tanımlı değil (.env dosyasını kontrol edin)")]
Missing(&'static str),
#[error("{0} geçersiz: {1}")]
Invalid(&'static str, &'static str),
}
impl Config {
pub fn from_env() -> Result<Self, ConfigError> {
let mongodb_uri = required("MONGODB_URI")?;
let jwt_secret = required("JWT_SECRET")?;
if jwt_secret.len() < 32 {
return Err(ConfigError::Invalid(
"JWT_SECRET",
"en az 32 karakter olmalı (openssl rand -hex 32)",
));
}
let app_url = env::var("APP_URL").unwrap_or_else(|_| "http://localhost:5173".into());
let port = match env::var("PORT") {
Ok(p) => p
.parse()
.map_err(|_| ConfigError::Invalid("PORT", "sayı olmalı"))?,
Err(_) => 8080,
};
Ok(Self {
mongodb_uri,
jwt_secret,
app_url,
port,
})
}
/// Cookie'lerde `Secure` bayrağı yalnızca HTTPS'te açılır.
#[allow(dead_code)] // Faz 1 – Adım 3'te (kimlik doğrulama) kullanılacak
pub fn is_https(&self) -> bool {
self.app_url.starts_with("https://")
}
}
fn required(key: &'static str) -> Result<String, ConfigError> {
env::var(key)
.ok()
.filter(|v| !v.trim().is_empty())
.ok_or(ConfigError::Missing(key))
}