diff --git a/config/default.toml b/config/default.toml new file mode 100644 index 0000000..c5b77d7 --- /dev/null +++ b/config/default.toml @@ -0,0 +1,33 @@ +debug = true +allow_registration = true +# source code of your copy of pages server. +source_code = "https://git.batsense.net/ForgeFlux/ftest" +support_email = "support@forgeflux.org" + +[server] +# The port at which you want Pages to listen to +port = 7000 +#IP address. Enter 0.0.0.0 to listen on all availale addresses +ip= "0.0.0.0" +# The number of worker threads that must be spun up by the Pages server. +# Minimum of two threads are advisable for top async performance but can work +# with one also. +workers = 2 +domain = "localhost" +cookie_secret = "94b2b2732626fdb7736229a7c777cb451e6304c147c4549f30" + +[database] +# This section deals with the database location and how to access it +# Please note that at the moment, we have support for only postgresqa. +# Example, if you are Batman, your config would be: +# hostname = "batcave.org" +# port = "5432" +# username = "batman" +# password = "somereallycomplicatedBatmanpassword" +hostname = "localhost" +port = "5432" +username = "postgres" +password = "password" +name = "postgres" +pool = 4 +database_type="postgres" # "postgres" diff --git a/config/librepages-nginx-config b/config/librepages-nginx-config new file mode 100644 index 0000000..0000153 --- /dev/null +++ b/config/librepages-nginx-config @@ -0,0 +1,21 @@ +server { + server_name HOSTNAME; + error_log /var/log/nginx/error.log; + + listen 443 ssl http2; + + location / { + proxy_pass http://127.0.0.1:12081; + proxy_set_header Host $host; + } +} + +server { + listen 80; + listen [::]:80; + server_name HOSTNAME; # change hostname + + location / { + return 301 https://$host$request_uri; + } +} diff --git a/src/settings.rs b/src/settings.rs new file mode 100644 index 0000000..87dac08 --- /dev/null +++ b/src/settings.rs @@ -0,0 +1,180 @@ +/* + * Copyright (C) 2022 Aravinth Manivannan + * + * 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 . + */ +use std::env; +use std::path::Path; + +use config::{Config, ConfigError, Environment, File}; +use derive_more::Display; +#[cfg(not(test))] +use tracing::warn; + +#[cfg(test)] +use std::println as warn; + +use serde::Deserialize; +use serde::Serialize; +use url::Url; + +use crate::errors::*; + +#[derive(Debug, Clone, Serialize, Deserialize)] +pub struct Server { + pub port: u32, + pub ip: String, + pub workers: Option, + pub cookie_secret: String, + pub domain: String, +} + +impl Server { + #[cfg(not(tarpaulin_include))] + pub fn get_ip(&self) -> String { + format!("{}:{}", self.ip, self.port) + } +} + +#[derive(Deserialize, Serialize, Display, Eq, PartialEq, Clone, Debug)] +#[serde(rename_all = "lowercase")] +pub enum DBType { + #[display(fmt = "postgres")] + Postgres, +} + +impl DBType { + fn from_url(url: &Url) -> Result { + match url.scheme() { + "postgres" => Ok(Self::Postgres), + _ => Err(ConfigError::Message("Unknown database type".into())), + } + } +} + +#[derive(Debug, Clone, Serialize, Deserialize)] +pub struct Database { + pub url: String, + pub pool: u32, + pub database_type: DBType, +} + +#[derive(Debug, Clone, Serialize, Deserialize)] +pub struct Settings { + pub allow_registration: bool, + pub support_email: String, + pub debug: bool, + pub server: Server, + pub source_code: String, + pub database: Database, +} + +#[cfg(not(tarpaulin_include))] +impl Settings { + pub fn new() -> ServiceResult { + let mut s = Config::builder(); + + const CURRENT_DIR: &str = "./config/default.toml"; + const ETC: &str = "/etc/liberapages/librepages/config.toml"; + + let mut read_file = false; + + if Path::new(ETC).exists() { + s = s.add_source(File::with_name(ETC)); + read_file = true; + } + if Path::new(CURRENT_DIR).exists() { + // merging default config from file + s = s.add_source(File::with_name(CURRENT_DIR)); + read_file = true; + } + + if let Ok(path) = env::var("FTEST_CONFIG") { + s = s.add_source(File::with_name(&path)); + read_file = true; + } + + if !read_file { + warn!("configuration file not found"); + } + + s = s.add_source(Environment::with_prefix("FTEST").separator("__")); + + match env::var("PORT") { + Ok(val) => { + s = s.set_override("server.port", val).unwrap(); + } + Err(e) => warn!("couldn't interpret PORT: {}", e), + } + + let intermediate_config = s.build_cloned().unwrap(); + + s = s + .set_override( + "database.url", + format!( + r"postgres://{}:{}@{}:{}/{}", + intermediate_config + .get::("database.username") + .expect("Couldn't access database username"), + intermediate_config + .get::("database.password") + .expect("Couldn't access database password"), + intermediate_config + .get::("database.hostname") + .expect("Couldn't access database hostname"), + intermediate_config + .get::("database.port") + .expect("Couldn't access database port"), + intermediate_config + .get::("database.name") + .expect("Couldn't access database name") + ), + ) + .expect("Couldn't set database url"); + + if let Ok(val) = env::var("DATABASE_URL") { + let url = Url::parse(&val).expect("couldn't parse Database URL"); + s = s.set_override("database.url", url.to_string()).unwrap(); + let database_type = DBType::from_url(&url).unwrap(); + s = s + .set_override("database.database_type", database_type.to_string()) + .unwrap(); + } + + let settings = s.build().unwrap().try_deserialize::().unwrap(); + settings.check_url(); + + Ok(settings) + } + + pub fn init(&self) { + fn create_dir_util(path: &Path) { + if path.exists() && path.is_file() { + panic!("Path is a file, should be a directory: {:?}", path); + } + + if !path.exists() { + std::fs::create_dir_all(path).unwrap(); + } + } + + // create_dir_util(Path::new(&self.page.base_path)); + } + + #[cfg(not(tarpaulin_include))] + fn check_url(&self) { + Url::parse(&self.source_code).expect("Please enter a URL for source_code in settings"); + } +}