pipedash-web 0.3.0

REST API server for Pipedash
use std::sync::{
    Arc,
    PoisonError,
    RwLock as StdRwLock,
};

use pipedash_core::infrastructure::StorageManager;
use pipedash_core::CoreContext;
use tokio::sync::{
    Mutex,
    RwLock,
};

use crate::ws::WebSocketEventBus;

pub struct AppStateInner {
    pub core: Option<CoreContext>,
    pub storage_manager: Option<StorageManager>,
    pub setup_required: bool,
    pub config_error: Option<String>,
    pub token_store_ready: bool,
}

#[derive(Clone)]
pub struct AppState {
    pub inner: Arc<RwLock<AppStateInner>>,
    pub ws_event_bus: Arc<WebSocketEventBus>,
    pub setup_lock: Arc<Mutex<()>>,
    api_token: Arc<StdRwLock<Option<Arc<str>>>>,
}

impl AppState {
    pub fn setup_mode(ws_event_bus: Arc<WebSocketEventBus>) -> Self {
        Self {
            inner: Arc::new(RwLock::new(AppStateInner {
                core: None,
                storage_manager: None,
                setup_required: true,
                config_error: None,
                token_store_ready: false,
            })),
            ws_event_bus,
            setup_lock: Arc::default(),
            api_token: Arc::default(),
        }
    }

    pub fn config_error(ws_event_bus: Arc<WebSocketEventBus>, error: String) -> Self {
        Self {
            inner: Arc::new(RwLock::new(AppStateInner {
                core: None,
                storage_manager: None,
                setup_required: false,
                config_error: Some(error),
                token_store_ready: false,
            })),
            ws_event_bus,
            setup_lock: Arc::default(),
            api_token: Arc::default(),
        }
    }

    pub fn initialized(
        ws_event_bus: Arc<WebSocketEventBus>, core: CoreContext, storage_manager: StorageManager,
    ) -> Self {
        Self {
            inner: Arc::new(RwLock::new(AppStateInner {
                core: Some(core),
                storage_manager: Some(storage_manager),
                setup_required: false,
                config_error: None,
                token_store_ready: false,
            })),
            ws_event_bus,
            setup_lock: Arc::default(),
            api_token: Arc::default(),
        }
    }

    pub fn api_token(&self) -> Option<Arc<str>> {
        self.api_token
            .read()
            .unwrap_or_else(PoisonError::into_inner)
            .clone()
    }

    pub fn set_api_token(&self, token: &str) {
        *self
            .api_token
            .write()
            .unwrap_or_else(PoisonError::into_inner) = Some(token.into());
    }
}