notegraf_web/
configuration.rs1use notegraf::notestore::BoxedNoteStore;
2use notegraf::{InMemoryStore, PostgreSQLStoreBuilder};
3use sqlx::postgres::PgConnectOptions;
4use sqlx::{ConnectOptions, Connection, Executor, PgConnection};
5use tracing::log::LevelFilter;
6use uuid::Uuid;
7
8#[derive(serde::Deserialize, Debug)]
9pub enum NoteStoreType {
10 InMemory,
11 PostgreSQL,
12}
13
14#[derive(serde::Deserialize, Debug)]
15pub struct Settings {
16 database: Option<DatabaseSettings>,
17 pub host: String,
18 pub port: u16,
19 pub debug: bool,
20 notestoretype: NoteStoreType,
21 populatetestdata: bool,
22 pub otlpendpoint: Option<String>,
23 pub loglevel: Option<String>,
24}
25
26impl Settings {
27 pub async fn get_note_store(
28 &self,
29 random_db: bool,
30 log_statement_filter: LevelFilter,
31 ) -> BoxedNoteStore<crate::NoteType> {
32 let store: BoxedNoteStore<crate::NoteType> = match self.notestoretype {
33 NoteStoreType::InMemory => Box::new(InMemoryStore::new()),
34 NoteStoreType::PostgreSQL => {
35 let database_settings = CONFIGURATION.database
36 .as_ref()
37 .expect("When notestoretype is set to PostgreSQL, you must configure the keys under database");
38 let mut db_options = if random_db {
39 let db_name = Uuid::new_v4().to_string();
40 let db_options = database_settings.options_without_db();
41 let mut connection = PgConnection::connect_with(&db_options)
42 .await
43 .expect("Failed to connect to Postgres");
44 connection
45 .execute(&*format!(r#"CREATE DATABASE "{}";"#, db_name))
46 .await
47 .expect("Failed to create database.");
48 db_options.database(&db_name)
49 } else {
50 database_settings.options()
51 };
52 db_options.log_statements(log_statement_filter);
53 Box::new(PostgreSQLStoreBuilder::new(db_options).build().await)
54 }
55 };
56 if cfg!(feature = "notetype_markdown") && self.populatetestdata {
57 notegraf::notestore::util::populate_test_data(&store).await;
58 }
59 store
60 }
61}
62
63#[derive(serde::Deserialize, Clone, Debug)]
64pub struct DatabaseSettings {
65 pub port: String,
66 pub host: String,
67 pub name: String,
68 pub username: Option<String>,
69 pub password: Option<String>,
70}
71
72impl DatabaseSettings {
73 pub fn options(&self) -> PgConnectOptions {
74 self.options_without_db().database(&self.name)
75 }
76
77 pub fn options_without_db(&self) -> PgConnectOptions {
78 let options = PgConnectOptions::new()
79 .host(&self.host)
80 .port(self.port.parse().expect("Failed to parse port number"));
81 if let Some(ref username) = self.username {
82 let password = self
83 .password
84 .as_ref()
85 .expect("Password expected when a username is set");
86 options.username(username).password(password)
87 } else {
88 options
89 }
90 }
91}
92
93lazy_static! {
94 pub static ref CONFIGURATION: Settings =
95 get_configuration().expect("Failed to read configuration.yml.");
96}
97
98pub fn get_configuration() -> Result<Settings, config::ConfigError> {
99 let config = config::Config::builder()
100 .set_default("debug", false)?
101 .set_default("host", "localhost")?
102 .set_default("populatetestdata", false)?
103 .add_source(config::File::with_name("configuration").required(false))
104 .add_source(
105 config::Environment::default()
106 .prefix("notegraf")
107 .separator("_"),
108 )
109 .build()?;
110 config.try_deserialize()
111}