streamline configuration

Signed-off-by: Alexey Aristov <aav@acm.org>
This commit is contained in:
Alexey Aristov
2025-08-27 15:24:30 +02:00
parent fa783cb694
commit 43a19d2f60
7 changed files with 61 additions and 55 deletions
Generated
+1
View File
@@ -1202,6 +1202,7 @@ dependencies = [
"serde_json",
"serde_with",
"size",
"strum",
"tokio",
"tokio-stream",
"tracing",
+1
View File
@@ -31,6 +31,7 @@ hulyrs = { git = "https://github.com/hcengineering/hulyrs.git", features = [
] }
secrecy = "0.10.3"
tokio-stream = "0.1"
strum = { version = "0.27.2", features = ["derive"] }
[[bin]]
name = "hulypulse"
+11 -5
View File
@@ -13,15 +13,14 @@
// limitations under the License.
//
use std::{path::Path, sync::LazyLock};
use secrecy::SecretString;
use serde::Deserialize;
use serde_with::formats::CommaSeparator;
use serde_with::{StringWithSeparator, serde_as};
use url::Url;
use std::{path::Path, sync::LazyLock};
use config::FileFormat;
#[derive(Deserialize, Debug, PartialEq)]
@@ -31,6 +30,13 @@ pub enum RedisMode {
Direct,
}
#[derive(Deserialize, Debug, PartialEq, strum::Display)]
#[serde(rename_all = "lowercase")]
pub enum BackendType {
Memory,
Redis,
}
#[serde_as]
#[derive(Deserialize, Debug)]
pub struct Config {
@@ -48,8 +54,8 @@ pub struct Config {
pub max_ttl: usize,
pub max_size: Option<usize>,
pub memory_mode: Option<bool>,
pub no_authorization: Option<bool>,
pub backend: BackendType,
pub no_authorization: bool,
}
pub static CONFIG: LazyLock<Config> = LazyLock::new(|| {
+3 -4
View File
@@ -9,9 +9,8 @@ redis_mode = "direct"
redis_service = "mymaster"
max_ttl = 3600
backend = "redis"
no_authorization = false
# optional settings
# memory_mode = true
# no_authorization = true
# max_size = 100
# max_size = 100
+4 -4
View File
@@ -507,22 +507,22 @@ pub async fn handler(
db: web::Data<Db>,
hub_state: web::Data<Arc<RwLock<HubState>>>,
) -> Result<HttpResponse, Error> {
let claims = if CONFIG.no_authorization == Some(true) {
None
} else {
let claims = if !CONFIG.no_authorization {
Some(
req.extensions()
.get::<Claims>()
.expect("Missing claims")
.to_owned(),
)
} else {
None
};
let session = WsSession {
db: db.get_ref().clone(),
hub_state: hub_state.get_ref().clone(),
id: new_session_id(),
claims: claims,
claims,
};
ws::start(session, &req, payload)
+40 -41
View File
@@ -67,19 +67,18 @@ async fn extract_claims(
token: Option<String>,
}
if CONFIG.no_authorization == Some(true) {
return next.call(request).await;
if !CONFIG.no_authorization {
let query = request.extract::<Query<QueryString>>().await?.into_inner();
let claims = if let Some(token) = query.token {
Claims::from_token(token, CONFIG.token_secret.expose_secret()).unwrap()
} else {
request.extract_claims(&CONFIG.token_secret)?
};
request.extensions_mut().insert(claims);
}
let query = request.extract::<Query<QueryString>>().await?.into_inner();
let claims = if let Some(token) = query.token {
Claims::from_token(token, CONFIG.token_secret.expose_secret()).unwrap()
} else {
request.extract_claims(&CONFIG.token_secret)?
};
request.extensions_mut().insert(claims);
next.call(request).await
}
@@ -87,22 +86,22 @@ async fn check_workspace(
mut request: ServiceRequest,
next: Next<impl MessageBody>,
) -> Result<ServiceResponse<impl MessageBody>, Error> {
if CONFIG.no_authorization.unwrap_or(false) {
return next.call(request).await;
}
if !CONFIG.no_authorization {
let workspace = Uuid::parse_str(&request.extract::<Path<String>>().await?);
let claims = request.extensions().get::<Claims>().cloned().unwrap();
let workspace = Uuid::parse_str(&request.extract::<Path<String>>().await?);
let claims = request.extensions().get::<Claims>().cloned().unwrap();
if claims.is_system() || Ok(claims.workspace.clone()) == workspace.clone().map(Some) {
next.call(request).await
if claims.is_system() || Ok(claims.workspace.clone()) == workspace.clone().map(Some) {
next.call(request).await
} else {
warn!(
expected = ?claims.workspace,
actual = ?workspace,
"Unauthorized request, workspace mismatch"
);
Err(actix_web::error::ErrorUnauthorized("Unauthorized").into())
}
} else {
warn!(
expected = ?claims.workspace,
actual = ?workspace,
"Unauthorized request, workspace mismatch"
);
Err(actix_web::error::ErrorUnauthorized("Unauthorized").into())
next.call(request).await
}
}
@@ -115,17 +114,21 @@ async fn main() -> anyhow::Result<()> {
// starting HubService
let hub_state = Arc::new(RwLock::new(HubState::default()));
let db_backend = if CONFIG.memory_mode == Some(true) {
let memory = MemoryBackend::new();
memory.spawn_ticker(hub_state.clone());
tracing::info!("Memory mode enabled");
Db::new_memory(memory, hub_state.clone())
} else {
let redis_client = redis::client().await?;
let redis_connection = redis_client.get_multiplexed_async_connection().await?;
tokio::spawn(crate::redis::receiver(redis_client, hub_state.clone()));
tracing::info!("Redis mode enabled");
Db::new_redis(redis_connection, hub_state.clone())
let db_backend = match CONFIG.backend {
config::BackendType::Memory => {
let memory = MemoryBackend::new();
memory.spawn_ticker(hub_state.clone());
tracing::info!("Memory mode enabled");
Db::new_memory(memory, hub_state.clone())
}
config::BackendType::Redis => {
let redis_client = redis::client().await?;
let redis_connection = redis_client.get_multiplexed_async_connection().await?;
tokio::spawn(crate::redis::receiver(redis_client, hub_state.clone()));
tracing::info!("Redis mode enabled");
Db::new_redis(redis_connection, hub_state.clone())
}
};
let socket = std::net::SocketAddr::new(CONFIG.bind_host.as_str().parse()?, CONFIG.bind_port);
@@ -180,11 +183,7 @@ async fn main() -> anyhow::Result<()> {
let count = hub_state.read().await.count();
Ok::<_, actix_web::Error>(HttpResponse::Ok().json(json!({
"memory_info": info,
"db_mode": if CONFIG.memory_mode == Some(true) {
"memory"
} else {
"redis"
},
"backend": CONFIG.backend.to_string().to_lowercase(),
"websockets": count,
"status": "OK",
})))
+1 -1
View File
@@ -24,7 +24,7 @@ pub fn check_workspace_core(claims_opt: Option<Claims>, key: &str) -> Result<(),
return Err("Invalid key: deprecated symbols");
}
if CONFIG.no_authorization == Some(true) {
if CONFIG.no_authorization {
return Ok(());
}