liminal_server/auth_lys/
root_presence_start.rs1use std::sync::Arc;
12
13use super::root_presence::{LysRoot, RootPresence};
14use crate::ServerError;
15use crate::config::types::LysConfig;
16
17#[derive(Debug)]
19pub enum RootSlot {
20 Asked(Arc<RootPresence>),
22 Unasked {
24 cause: &'static str,
26 },
27}
28
29impl RootSlot {
30 #[must_use]
32 pub fn health(&self) -> (&'static str, Option<&'static str>) {
33 match self {
34 Self::Asked(root) => {
35 let answer = root.answer();
36 (answer.health(), answer.cause())
37 }
38 Self::Unasked { cause } => (LysRoot::NotAsked.health(), Some(cause)),
39 }
40 }
41}
42
43#[derive(Debug)]
45pub enum RootQuestion {
46 Owner,
48 AtStart(Arc<RootPresence>),
50 Unasked(&'static str),
52}
53
54pub fn root_question(
60 lys: &LysConfig,
61 handle: Option<tokio::runtime::Handle>,
62) -> Result<RootQuestion, ServerError> {
63 if lys.membership.is_some() || lys.grant_stream.is_some() {
64 return Ok(RootQuestion::Owner);
65 }
66 let Some(path) = lys.app_credential_path.as_ref() else {
67 return Ok(RootQuestion::Unasked("no_asking_credential"));
68 };
69 let Some(handle) = handle else {
70 return Ok(RootQuestion::Unasked("no_ask_runtime"));
71 };
72 let refused = |message: String| ServerError::ConfigValidation { message };
73 let credential = std::fs::read_to_string(path).map_err(|error| {
74 refused(format!(
75 "auth.lys.app_credential_path '{}' cannot be read: {}",
76 path.display(),
77 error.kind()
78 ))
79 })?;
80 let api = lys.api_url.as_deref().unwrap_or(&lys.issuer);
81 let root = RootPresence::new(&lys.network_id, api, credential.trim().to_owned(), handle)
82 .map_err(|_| refused("lys_root_question_invalid".to_owned()))?;
83 Ok(RootQuestion::AtStart(Arc::new(root)))
84}
85
86pub fn start(
93 lys: &LysConfig,
94 health: &crate::health::HealthServerHandle,
95 runtime: Option<&tokio::runtime::Runtime>,
96) -> Result<(), ServerError> {
97 match root_question(lys, runtime.map(|runtime| runtime.handle().clone()))? {
98 RootQuestion::Owner => Ok(()),
99 RootQuestion::Unasked(cause) => health.install_lys_root(RootSlot::Unasked { cause }),
100 RootQuestion::AtStart(root) => {
101 health.install_lys_root(RootSlot::Asked(Arc::clone(&root)))?;
102 root.ask_in_background();
103 Ok(())
104 }
105 }
106}