diff --git a/src/websocket_server.rs b/src/websocket_server.rs index 484cfac..d4b7f98 100644 --- a/src/websocket_server.rs +++ b/src/websocket_server.rs @@ -82,6 +82,7 @@ struct WebSocketLog { const WS_LOG_MAX_ENTRIES: usize = 50_000; const RIGHT_ADMIN: &str = "admin"; +const RIGHT_MAINADMIN: &str = "mainadmin"; const RIGHT_WORKER_SCHEDULE: &str = "worker_schedule_read"; async fn append_ws_log( @@ -704,23 +705,53 @@ async fn handle_connection( } fn user_can_read_worker_schedules(pool: &ConnectionPool, user_id_raw: &str) -> bool { - let uid = match user_id_raw.parse::() { - Ok(v) if v > 0 => v, - _ => return false, - }; - let mut conn = match pool.get() { Ok(c) => c, Err(_) => return false, }; + let uid = if let Ok(v) = user_id_raw.parse::() { + if v > 0 { v } else { return false; } + } else { + // Fallback: setUserId kann auch username/hashed_id aus dem Community-User sein. + let resolve_sql = r#" +SELECT id + FROM community."user" + WHERE LOWER(username) = LOWER($1::text) + OR LOWER(COALESCE(hashed_id, '')) = LOWER($1::text) + LIMIT 1; +"#; + if conn.prepare("ws_resolve_community_user_id", resolve_sql).is_err() { + return false; + } + let rows = match conn.execute("ws_resolve_community_user_id", &[&user_id_raw]) { + Ok(r) => r, + Err(_) => return false, + }; + let Some(row) = rows.first() else { + return false; + }; + row.get("id") + .and_then(|v| v.parse::().ok()) + .filter(|v| *v > 0) + .unwrap_or(-1) + }; + if uid <= 0 { + return false; + } + let sql = r#" SELECT EXISTS ( SELECT 1 FROM community.user_right ur JOIN "type".user_right tr ON tr.id = ur.right_type_id WHERE ur.user_id = $1::int - AND LOWER(COALESCE(tr.title, '')) IN ($2::text, $3::text) + AND ( + LOWER(TRIM(COALESCE(tr.title, ''))) = $2::text + OR LOWER(TRIM(COALESCE(tr.title, ''))) = $3::text + OR LOWER(TRIM(COALESCE(tr.title, ''))) = $4::text + OR LOWER(COALESCE(tr.title, '')) LIKE '%admin%' + ) ) AS allowed_direct, EXISTS ( SELECT 1 @@ -728,7 +759,12 @@ EXISTS ( JOIN community.user_right ur ON ur.user_id = fu.user_id JOIN "type".user_right tr ON tr.id = ur.right_type_id WHERE fu.id = $1::int - AND LOWER(COALESCE(tr.title, '')) IN ($2::text, $3::text) + AND ( + LOWER(TRIM(COALESCE(tr.title, ''))) = $2::text + OR LOWER(TRIM(COALESCE(tr.title, ''))) = $3::text + OR LOWER(TRIM(COALESCE(tr.title, ''))) = $4::text + OR LOWER(COALESCE(tr.title, '')) LIKE '%admin%' + ) ) AS allowed_falukant; "#; @@ -737,9 +773,10 @@ EXISTS ( } let admin = RIGHT_ADMIN.to_string(); let allowed_right = RIGHT_WORKER_SCHEDULE.to_string(); + let mainadmin = RIGHT_MAINADMIN.to_string(); let rows = match conn.execute( "ws_can_read_worker_schedules", - &[&uid, &admin, &allowed_right], + &[&uid, &admin, &allowed_right, &mainadmin], ) { Ok(r) => r, Err(_) => return false,