Skip to content

Commit

Permalink
adjust application configuration parsing
Browse files Browse the repository at this point in the history
  • Loading branch information
thebino committed Jul 1, 2023
1 parent 641ee3b commit 29e18fe
Show file tree
Hide file tree
Showing 8 changed files with 353 additions and 36 deletions.
2 changes: 2 additions & 0 deletions Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -32,6 +32,7 @@ members = [
# define dependencies to be inherited by members of the workspace
[workspace.dependencies]
core_common = { path = "./crates/core_common" }
# core_oauth = { path = "./crates/core_oauth" }
core_photos = { path = "./crates/core_photos" }
core_activity_pub = { path = "./crates/core_activity_pub" }
activitypub_federation = "~0.4.0"
Expand All @@ -54,6 +55,7 @@ path = "../plugin_interface"
# core_api = { workspace = true }
core_common = { workspace = true }
core_photos = { workspace = true }
# core_oauth = { workspace = true }
core_activity_pub = { workspace = true }
# core_api_crud = { workspace = true }

Expand Down
89 changes: 89 additions & 0 deletions src/config/client.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,89 @@
/* Photos.network · A privacy first photo storage and sharing service for fediverse.
* Copyright (C) 2020 Photos network developers
*
* This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU Affero General Public License as
* published by the Free Software Foundation, either version 3 of the
* License, or (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU Affero General Public License for more details.
*
* You should have received a copy of the GNU Affero General Public License
* along with this program. If not, see <https://www.gnu.org/licenses/>.
*/

//! This represents an oauth client configuration
use std::fmt;

use serde::{Deserialize, Serialize};

#[derive(PartialEq, Debug, Deserialize, Serialize, Clone)]
pub struct OAuthClientConfig {
pub name: String,
pub client_id: String,
pub client_secret: String,
pub redirect_uris: Vec<String>
}

impl fmt::Display for OAuthClientConfig {
fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
write!(f,
"{}, redirect: {:?}", self.name, self.redirect_uris)
}
}

#[cfg(test)]
mod tests {
use super::*;

#[test]
fn test_full_deserialization() {
// given
let json = r#"{
"name": "Client",
"client_id": "clientId",
"client_secret": "clientSecret",
"redirect_uris": [
"https://demo.photos.network/callback",
"http://127.0.0.1:7777/callback",
"photosapp://authenticate"
]
}"#;

let data = OAuthClientConfig {
name: "Client".into(),
client_id: "clientId".into(),
client_secret: "clientSecret".into(),
redirect_uris: vec![
"https://demo.photos.network/callback".into(),
"http://127.0.0.1:7777/callback".into(),
"photosapp://authenticate".into()
]
};

assert_eq!(data, serde_json::from_str(json).unwrap());
}

#[test]
fn test_minimal_deserialization() {
// given
let json = r#"{
"name": "Client",
"client_id": "clientId",
"client_secret": "clientSecret",
"redirect_uris": []
}"#;

let data = OAuthClientConfig {
name: "Client".into(),
client_id: "clientId".into(),
client_secret: "clientSecret".into(),
redirect_uris: vec![]
};

assert_eq!(data, serde_json::from_str(json).unwrap());
}
}
133 changes: 133 additions & 0 deletions src/config/configuration.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,133 @@
/* Photos.network · A privacy first photo storage and sharing service for fediverse.
* Copyright (C) 2020 Photos network developers
*
* This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU Affero General Public License as
* published by the Free Software Foundation, either version 3 of the
* License, or (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU Affero General Public License for more details.
*
* You should have received a copy of the GNU Affero General Public License
* along with this program. If not, see <https://www.gnu.org/licenses/>.
*/

//! This defines the app configuration
use std::{fs, fmt};

use serde::Deserialize;
use tracing::info;

use super::{client::OAuthClientConfig, plugin::Plugin};


#[derive(Debug, PartialEq, Deserialize, Clone)]
pub struct Configuration {
pub internal_url: String,
pub external_url: String,
pub clients: Vec<OAuthClientConfig>,
pub plugins: Vec<Plugin>,
}

impl Configuration {
pub fn new(path: &str) -> Option<Self> {
info!("Load configuration file {}", path);
let data = fs::read_to_string(path).expect("Unable to read configuration file!");
let config: Configuration = serde_json::from_str(&data).expect("Configuration file could not be parsed as JSON!");

Some(config)
}
}

impl fmt::Display for Configuration {
fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
let clients = &self.clients;
let plugins = &self.plugins;

write!(f, "{{")?;
write!(f, "\n\tinternal: {}", self.internal_url)?;
write!(f, "\n\texternal: {}", self.external_url)?;

// clients
write!(f, "\n\tclients: [ ")?;
for (count, v) in clients.iter().enumerate() {
if count != 0 { write!(f, ", ")?; }
write!(f, "\n\t\t{}", v)?;
}
write!(f, "\n\t] ")?;

// plugins
write!(f, "\n\tplugins: [ ")?;
for (count, v) in plugins.iter().enumerate() {
if count != 0 { write!(f, ", ")?; }
write!(f, "\n\t\t{}", v)?;
}
write!(f, "\n\t]")?;
write!(f, "\n}}")
}
}


#[cfg(test)]
mod tests {
use super::*;
use serde_json::Map;

#[test]
fn test_full_deserialization() {
// given
let json = r#"{
"internal_url": "192.168.0.1",
"external_url": "demo.photos.network",
"clients": [
{
"name": "Client",
"client_id": "clientId",
"client_secret": "clientSecret",
"redirect_uris": []
}
],
"plugins": [
{
"name": "Plugin",
"config": {
"property1": null,
"property2": true,
"property3": "aBc",
"property4": 42
}
}
]
}"#;

let mut config = Map::new();
config.insert("property1".to_string(), serde_json::Value::Null);
config.insert("property2".to_string(), serde_json::Value::Bool(true));
config.insert("property3".to_string(), serde_json::Value::String("aBc".into()));
config.insert("property4".to_string(), serde_json::Value::Number(42.into()));

let data = Configuration {
internal_url: "192.168.0.1".into(),
external_url: "demo.photos.network".into(),
clients: vec![
OAuthClientConfig {
name: "Client".into(),
client_id: "clientId".into(),
client_secret: "clientSecret".into(),
redirect_uris: vec![]
}
],
plugins: vec![
Plugin {
name: "Plugin".into(),
config: Some(config),
}
]
};

assert_eq!(data, serde_json::from_str(json).unwrap());
}
}
36 changes: 3 additions & 33 deletions src/config/mod.rs
Original file line number Diff line number Diff line change
@@ -1,33 +1,3 @@

use std::fs;

use serde::Deserialize;
use serde_json::Map;
use tracing::{debug, info};

#[derive(Debug, Deserialize, Clone)]
pub struct Configuration {
pub internal_url: String,
pub external_url: String,
pub plugins: Vec<Plugin>,
}

#[derive(Debug, Deserialize, Clone)]
pub struct Plugin {
pub name: String,
pub config: Option<Map<String, serde_json::Value>>
}

impl Configuration {
pub fn new(path: &str) -> Option<Self> {
info!("Load configuration file {}", path);
let data = fs::read_to_string(path).expect("Unable to read configuration file!");
let config: Configuration = serde_json::from_str(&data).expect("Configuration file could not be parsed as JSON!");

debug!("internal: {}", config.internal_url);
debug!("external: {}", config.external_url);
debug!("plugins: {:?}", config.plugins);

Some(config)
}
}
pub mod client;
pub mod plugin;
pub mod configuration;
81 changes: 81 additions & 0 deletions src/config/plugin.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,81 @@
/* Photos.network · A privacy first photo storage and sharing service for fediverse.
* Copyright (C) 2020 Photos network developers
*
* This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU Affero General Public License as
* published by the Free Software Foundation, either version 3 of the
* License, or (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU Affero General Public License for more details.
*
* You should have received a copy of the GNU Affero General Public License
* along with this program. If not, see <https://www.gnu.org/licenses/>.
*/

//! This describes a plugin with a key-value pair configuration
use std::fmt;

use serde::{Deserialize};
use serde_json::Map;

#[derive(Debug, PartialEq, Deserialize, Clone)]
pub struct Plugin {
pub name: String,
pub config: Option<Map<String, serde_json::Value>>
}

impl fmt::Display for Plugin {
fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
write!(f, "{}", self.name)
}
}

#[cfg(test)]
mod tests {
use super::*;

#[test]
fn test_full_deserialization() {
// given
let json = r#"{
"name": "Plugin",
"config": {
"property1": null,
"property2": true,
"property3": "aBc",
"property4": 42
}
}"#;

let mut config = Map::new();
config.insert("property1".to_string(), serde_json::Value::Null);
config.insert("property2".to_string(), serde_json::Value::Bool(true));
config.insert("property3".to_string(), serde_json::Value::String("aBc".into()));
config.insert("property4".to_string(), serde_json::Value::Number(42.into()));

let data = Plugin {
name: "Plugin".into(),
config: Some(config),
};

assert_eq!(data, serde_json::from_str(json).unwrap());
}

#[test]
fn test_minimal_deserialization() {
// given
let json = r#"{
"name": "Plugin"
}"#;

let data = Plugin {
name: "Plugin".into(),
config: None,
};

assert_eq!(data, serde_json::from_str(json).unwrap());
}
}
Loading

0 comments on commit 29e18fe

Please sign in to comment.