Skip to main content

opentalk_roomserver_types/
module_settings.rs

1// SPDX-License-Identifier: EUPL-1.2
2// SPDX-FileCopyrightText: OpenTalk Team <mail@opentalk.eu>
3
4use std::{collections::BTreeMap, fmt::Debug};
5
6use opentalk_types_common::{
7    modules::{ModuleId, module_id},
8    utils::ExampleData,
9};
10use serde::{Deserialize, Serialize, de::DeserializeOwned};
11use serde_json::json;
12
13pub trait SignalingModuleSettings: ExampleData + Serialize + DeserializeOwned + Debug {
14    const NAMESPACE: ModuleId;
15}
16
17/// A struct containing settings for multiple signaling modules, each associated with the module's
18/// namespace.
19#[derive(Default, Debug, Clone, Serialize, Deserialize, PartialEq, Eq)]
20#[serde(rename_all = "snake_case")]
21#[cfg_attr(feature = "utoipa", derive(utoipa::ToSchema), schema(example = json!(ModuleSettings::example_data())))]
22pub struct ModuleSettings(BTreeMap<ModuleId, serde_json::Value>);
23
24impl ModuleSettings {
25    /// Create a new empty [`ModuleSettings`].
26    pub fn new() -> Self {
27        Self(BTreeMap::new())
28    }
29
30    /// Get the settings for a specific module
31    pub fn get<T: SignalingModuleSettings>(&self) -> Result<Option<T>, serde_json::Error> {
32        self.0
33            .get(&T::NAMESPACE)
34            .map(|m| serde_json::from_value(m.clone()))
35            .transpose()
36    }
37
38    /// Set the settings for a specific module
39    ///
40    /// If an entry with the namespace already exists, it will be overwritten.
41    pub fn insert<T: SignalingModuleSettings>(
42        &mut self,
43        data: &T,
44    ) -> Result<(), serde_json::Error> {
45        self.0.insert(T::NAMESPACE, serde_json::to_value(data)?);
46        Ok(())
47    }
48
49    /// Insert an empty object for the specified module namespace
50    ///
51    /// This is useful for adding modules that don't require any settings.
52    pub fn insert_empty(&mut self, namespace: ModuleId) {
53        self.0
54            .insert(namespace, serde_json::Value::Object(serde_json::Map::new()));
55    }
56
57    /// Remove the settings for a specified module.
58    pub fn remove(&mut self, namespace: &ModuleId) -> Option<serde_json::Value> {
59        self.0.remove(namespace)
60    }
61
62    /// Retains only the entries specified by the predicate
63    pub fn retain<F>(&mut self, f: F)
64    where
65        F: FnMut(&ModuleId, &mut serde_json::Value) -> bool,
66    {
67        self.0.retain(f);
68    }
69
70    /// Returns an iterator over the module IDs in the settings
71    pub fn ids(&self) -> impl Iterator<Item = &ModuleId> {
72        self.0.keys()
73    }
74
75    /// Checks if specified module id is present in the settings
76    pub fn contains(&self, namespace: ModuleId) -> bool {
77        self.0.contains_key(&namespace)
78    }
79}
80
81impl ExampleData for ModuleSettings {
82    fn example_data() -> Self {
83        Self(BTreeMap::from([(
84            module_id!("livekit"),
85            json!({
86                "public_url": "http://localhost:7880",
87                "service_url": "http://localhost:7880",
88                "api_key": "devkey",
89                "api_secret": "secret",
90            }),
91        )]))
92    }
93}