319 lines
9.4 KiB
Rust
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)
|
|
})),
|
|
}
|
|
}
|