bitmine/src/handlers/settings.rs
2026-03-18 22:05:02 +03:00

319 lines
9.4 KiB
Rust

use crate::services::{bitrix24, redmine};
use askama::Template;
use axum::Form;
use axum::Json as AxumJson;
use axum::response::{Html, IntoResponse, Json};
use serde::{Deserialize, Serialize};
use serde_json::json;
use tower_sessions::Session;
#[derive(Template)]
#[template(path = "settings.html")]
pub struct SettingsTemplate {
pub redmine_url: String,
pub redmine_user_id: String,
pub bitrix_url: String,
pub bitrix_webhook: String,
pub error: Option<String>,
pub success: Option<String>,
}
#[derive(Debug, Deserialize, Serialize, Clone)]
pub struct UserSettings {
pub redmine_url: String,
pub redmine_api_key: String,
pub redmine_user_id: u32,
pub bitrix_url: String,
pub bitrix_webhook: String,
}
#[derive(Debug, Deserialize)]
pub struct SettingsForm {
pub redmine_url: Option<String>,
pub redmine_api_key: Option<String>,
pub redmine_user_id: Option<String>,
pub bitrix_url: Option<String>,
pub bitrix_webhook: Option<String>,
}
#[derive(Debug, Deserialize)]
pub struct TestConnectionForm {
pub redmine_url: Option<String>,
pub redmine_api_key: Option<String>,
pub redmine_user_id: Option<String>,
pub bitrix_url: Option<String>,
pub bitrix_webhook: Option<String>,
}
pub async fn settings_page(session: Session) -> impl IntoResponse {
let settings = session
.get::<UserSettings>("user_settings")
.await
.unwrap_or(None);
let template = SettingsTemplate {
redmine_url: settings
.as_ref()
.map(|s| s.redmine_url.clone())
.unwrap_or_default(),
redmine_user_id: settings
.as_ref()
.map(|s| s.redmine_user_id.to_string())
.unwrap_or_default(),
bitrix_url: settings
.as_ref()
.map(|s| s.bitrix_url.clone())
.unwrap_or_default(),
bitrix_webhook: settings
.as_ref()
.map(|s| s.bitrix_webhook.clone())
.unwrap_or_default(),
error: None,
success: None,
};
Html(
template
.render()
.unwrap_or_else(|e| format!("Error: {}", e)),
)
}
pub async fn save_settings(session: Session, Form(form): Form<SettingsForm>) -> impl IntoResponse {
let existing_settings = session
.get::<UserSettings>("user_settings")
.await
.unwrap_or(None);
let redmine_url = if let Some(url) = form.redmine_url {
if !url.is_empty() {
url.trim().trim_matches('"').to_string()
} else {
existing_settings
.as_ref()
.map(|s| s.redmine_url.clone())
.unwrap_or_default()
}
} else {
existing_settings
.as_ref()
.map(|s| s.redmine_url.clone())
.unwrap_or_default()
};
let redmine_api_key = if let Some(key) = form.redmine_api_key {
if !key.is_empty() {
key
} else {
existing_settings
.as_ref()
.map(|s| s.redmine_api_key.clone())
.unwrap_or_default()
}
} else {
existing_settings
.as_ref()
.map(|s| s.redmine_api_key.clone())
.unwrap_or_default()
};
let redmine_user_id: u32 = if let Some(id_str) = form.redmine_user_id {
if !id_str.is_empty() {
match id_str.parse() {
Ok(id) => id,
Err(_) => {
let template = SettingsTemplate {
redmine_url: redmine_url.clone(),
redmine_user_id: id_str,
bitrix_url: form.bitrix_url.clone().unwrap_or_default(),
bitrix_webhook: form.bitrix_webhook.clone().unwrap_or_default(),
error: Some("User ID должен быть числом".to_string()),
success: None,
};
return Html(
template
.render()
.unwrap_or_else(|e| format!("Error: {}", e)),
);
}
}
} else {
existing_settings
.as_ref()
.map(|s| s.redmine_user_id)
.unwrap_or(0)
}
} else {
existing_settings
.as_ref()
.map(|s| s.redmine_user_id)
.unwrap_or(0)
};
let bitrix_url = if let Some(url) = form.bitrix_url {
if !url.is_empty() {
url.trim().trim_matches('/').to_string()
} else {
existing_settings
.as_ref()
.map(|s| s.bitrix_url.clone())
.unwrap_or_default()
}
} else {
existing_settings
.as_ref()
.map(|s| s.bitrix_url.clone())
.unwrap_or_default()
};
let bitrix_webhook = if let Some(webhook) = form.bitrix_webhook {
if !webhook.is_empty() {
webhook.trim().trim_matches('/').to_string()
} else {
existing_settings
.as_ref()
.map(|s| s.bitrix_webhook.clone())
.unwrap_or_default()
}
} else {
existing_settings
.as_ref()
.map(|s| s.bitrix_webhook.clone())
.unwrap_or_default()
};
if redmine_url.is_empty() || redmine_api_key.is_empty() || redmine_user_id == 0 {
let template = SettingsTemplate {
redmine_url: redmine_url.clone(),
redmine_user_id: redmine_user_id.to_string(),
bitrix_url: bitrix_url.clone(),
bitrix_webhook: bitrix_webhook.clone(),
error: Some("Заполните все поля Redmine (URL, API Key, User ID)".to_string()),
success: None,
};
return Html(
template
.render()
.unwrap_or_else(|e| format!("Error: {}", e)),
);
}
let settings = UserSettings {
redmine_url: redmine_url.clone(),
redmine_api_key,
redmine_user_id,
bitrix_url: bitrix_url.clone(),
bitrix_webhook: bitrix_webhook.clone(),
};
if let Err(e) = session.insert("user_settings", settings.clone()).await {
let template = SettingsTemplate {
redmine_url,
redmine_user_id: redmine_user_id.to_string(),
bitrix_url,
bitrix_webhook,
error: Some(format!("Ошибка сохранения: {}", e)),
success: None,
};
return Html(
template
.render()
.unwrap_or_else(|e| format!("Error: {}", e)),
);
}
let template = SettingsTemplate {
redmine_url: settings.redmine_url,
redmine_user_id: settings.redmine_user_id.to_string(),
bitrix_url: settings.bitrix_url,
bitrix_webhook: settings.bitrix_webhook,
error: None,
success: Some("Настройки сохранены! Теперь можно загружать задачи.".to_string()),
};
Html(
template
.render()
.unwrap_or_else(|e| format!("Error: {}", e)),
)
}
pub async fn test_redmine_connection(
session: Session,
_form: AxumJson<TestConnectionForm>,
) -> impl IntoResponse {
let settings = match session
.get::<UserSettings>("user_settings")
.await
.unwrap_or(None)
{
Some(s) => s,
None => {
return Json(json!({
"success": false,
"message": "Сначала сохраните настройки"
}));
}
};
match redmine::test_connection(
&settings.redmine_api_key,
&settings.redmine_url,
settings.redmine_user_id,
)
.await
{
Ok(count) => Json(json!({
"success": true,
"message": format!("Подключение успешно! Найдено задач: {}", count),
"count": count
})),
Err(e) => Json(json!({
"success": false,
"message": format!("Ошибка: {}", e)
})),
}
}
pub async fn test_bitrix_connection(
session: Session,
_form: AxumJson<TestConnectionForm>,
) -> impl IntoResponse {
let settings = match session
.get::<UserSettings>("user_settings")
.await
.unwrap_or(None)
{
Some(s) => s,
None => {
return Json(json!({
"success": false,
"message": "Сначала сохраните настройки"
}));
}
};
if settings.bitrix_url.is_empty() || settings.bitrix_webhook.is_empty() {
return Json(json!({
"success": false,
"message": "Заполните настройки Bitrix24"
}));
}
match bitrix24::test_connection(&settings.bitrix_url, &settings.bitrix_webhook).await {
Ok(info) => {
let portal_name = info
.portal_name
.clone()
.unwrap_or_else(|| "Bitrix24".to_string());
Json(json!({
"success": true,
"message": format!("Подключение успешно! Портал: {}", portal_name),
"info": info
}))
}
Err(e) => Json(json!({
"success": false,
"message": format!("Ошибка: {}", e)
})),
}
}