summaryrefslogtreecommitdiffstats
path: root/server
diff options
context:
space:
mode:
authorDessalines <tyhou13@gmx.com>2020-04-14 16:07:20 -0400
committerDessalines <tyhou13@gmx.com>2020-04-14 16:07:20 -0400
commit1336b4ed6023e7fcf0fd40be63569966ee4b1b45 (patch)
treee62e4422e0ba0430ea6d060f01d20dee22d6e564 /server
parentf040dac647d50c97e3f9ab8058563a7fe0f29261 (diff)
parent641e4c5d96d9d152bc75318b3ea08f789d920b2b (diff)
Merge branch 'dev' into federation
Diffstat (limited to 'server')
-rw-r--r--server/src/api/site.rs70
-rw-r--r--server/src/lib.rs4
-rw-r--r--server/src/main.rs1
-rw-r--r--server/src/routes/api.rs2
-rw-r--r--server/src/routes/index.rs3
-rw-r--r--server/src/settings.rs45
-rw-r--r--server/src/version.rs2
-rw-r--r--server/src/websocket/mod.rs2
-rw-r--r--server/src/websocket/server.rs10
9 files changed, 122 insertions, 17 deletions
diff --git a/server/src/api/site.rs b/server/src/api/site.rs
index ad45e8d1..4202fea0 100644
--- a/server/src/api/site.rs
+++ b/server/src/api/site.rs
@@ -97,6 +97,22 @@ pub struct TransferSite {
auth: String,
}
+#[derive(Serialize, Deserialize)]
+pub struct GetSiteConfig {
+ auth: String,
+}
+
+#[derive(Serialize, Deserialize)]
+pub struct GetSiteConfigResponse {
+ config_hjson: String,
+}
+
+#[derive(Serialize, Deserialize)]
+pub struct SaveSiteConfig {
+ config_hjson: String,
+ auth: String,
+}
+
impl Perform<ListCategoriesResponse> for Oper<ListCategories> {
fn perform(&self, conn: &PgConnection) -> Result<ListCategoriesResponse, Error> {
let _data: &ListCategories = &self.data;
@@ -514,3 +530,57 @@ impl Perform<GetSiteResponse> for Oper<TransferSite> {
})
}
}
+
+impl Perform<GetSiteConfigResponse> for Oper<GetSiteConfig> {
+ fn perform(&self, conn: &PgConnection) -> Result<GetSiteConfigResponse, Error> {
+ let data: &GetSiteConfig = &self.data;
+
+ let claims = match Claims::decode(&data.auth) {
+ Ok(claims) => claims.claims,
+ Err(_e) => return Err(APIError::err("not_logged_in").into()),
+ };
+
+ let user_id = claims.id;
+
+ // Only let admins read this
+ let admins = UserView::admins(&conn)?;
+ let admin_ids: Vec<i32> = admins.into_iter().map(|m| m.id).collect();
+
+ if !admin_ids.contains(&user_id) {
+ return Err(APIError::err("not_an_admin").into());
+ }
+
+ let config_hjson = Settings::read_config_file()?;
+
+ Ok(GetSiteConfigResponse { config_hjson })
+ }
+}
+
+impl Perform<GetSiteConfigResponse> for Oper<SaveSiteConfig> {
+ fn perform(&self, conn: &PgConnection) -> Result<GetSiteConfigResponse, Error> {
+ let data: &SaveSiteConfig = &self.data;
+
+ let claims = match Claims::decode(&data.auth) {
+ Ok(claims) => claims.claims,
+ Err(_e) => return Err(APIError::err("not_logged_in").into()),
+ };
+
+ let user_id = claims.id;
+
+ // Only let admins read this
+ let admins = UserView::admins(&conn)?;
+ let admin_ids: Vec<i32> = admins.into_iter().map(|m| m.id).collect();
+
+ if !admin_ids.contains(&user_id) {
+ return Err(APIError::err("not_an_admin").into());
+ }
+
+ // Make sure docker doesn't have :ro at the end of the volume, so its not a read-only filesystem
+ let config_hjson = match Settings::save_config_file(&data.config_hjson) {
+ Ok(config_hjson) => config_hjson,
+ Err(_e) => return Err(APIError::err("couldnt_update_site").into()),
+ };
+
+ Ok(GetSiteConfigResponse { config_hjson })
+ }
+}
diff --git a/server/src/lib.rs b/server/src/lib.rs
index e45311ee..2c78cfc2 100644
--- a/server/src/lib.rs
+++ b/server/src/lib.rs
@@ -115,7 +115,7 @@ pub fn send_email(
to_username: &str,
html: &str,
) -> Result<(), String> {
- let email_config = Settings::get().email.as_ref().ok_or("no_email_setup")?;
+ let email_config = Settings::get().email.ok_or("no_email_setup")?;
let email = Email::builder()
.to((to_email, to_username))
@@ -130,7 +130,7 @@ pub fn send_email(
} else {
SmtpClient::new(&email_config.smtp_server, ClientSecurity::None).unwrap()
}
- .hello_name(ClientId::Domain(Settings::get().hostname.to_owned()))
+ .hello_name(ClientId::Domain(Settings::get().hostname))
.smtp_utf8(true)
.authentication_mechanism(Mechanism::Plain)
.connection_reuse(ConnectionReuseParameters::ReuseUnlimited);
diff --git a/server/src/main.rs b/server/src/main.rs
index 59dc2cb7..88d62eb9 100644
--- a/server/src/main.rs
+++ b/server/src/main.rs
@@ -57,6 +57,7 @@ async fn main() -> Result<(), Error> {
// Create Http server with websocket support
Ok(
HttpServer::new(move || {
+ let settings = Settings::get();
App::new()
.wrap(middleware::Logger::default())
.data(pool.clone())
diff --git a/server/src/routes/api.rs b/server/src/routes/api.rs
index 29a360e4..36a55f96 100644
--- a/server/src/routes/api.rs
+++ b/server/src/routes/api.rs
@@ -52,6 +52,8 @@ pub fn config(cfg: &mut web::ServiceConfig) {
.route("/api/v1/site", web::post().to(route_post::<CreateSite, SiteResponse>))
.route("/api/v1/site", web::put().to(route_post::<EditSite, SiteResponse>))
.route("/api/v1/site/transfer", web::post().to(route_post::<TransferSite, GetSiteResponse>))
+ .route("/api/v1/site/config", web::get().to(route_get::<GetSiteConfig, GetSiteConfigResponse>))
+ .route("/api/v1/site/config", web::put().to(route_post::<SaveSiteConfig, GetSiteConfigResponse>))
.route("/api/v1/admin/add", web::post().to(route_post::<AddAdmin, AddAdminResponse>))
.route("/api/v1/user/ban", web::post().to(route_post::<BanUser, BanUserResponse>))
// User account actions
diff --git a/server/src/routes/index.rs b/server/src/routes/index.rs
index c1c363c9..2e192df4 100644
--- a/server/src/routes/index.rs
+++ b/server/src/routes/index.rs
@@ -33,6 +33,7 @@ pub fn config(cfg: &mut web::ServiceConfig) {
.route("/modlog/community/{community_id}", web::get().to(index))
.route("/modlog", web::get().to(index))
.route("/setup", web::get().to(index))
+ .route("/admin", web::get().to(index))
.route(
"/search/q/{q}/type/{type}/sort/{sort}/page/{page}",
web::get().to(index),
@@ -44,6 +45,6 @@ pub fn config(cfg: &mut web::ServiceConfig) {
async fn index() -> Result<NamedFile, actix_web::error::Error> {
Ok(NamedFile::open(
- Settings::get().front_end_dir.to_owned() + "/index.html",
+ Settings::get().front_end_dir + "/index.html",
)?)
}
diff --git a/server/src/settings.rs b/server/src/settings.rs
index 29d5966b..8c3cd6a1 100644
--- a/server/src/settings.rs
+++ b/server/src/settings.rs
@@ -1,12 +1,15 @@
use config::{Config, ConfigError, Environment, File};
+use failure::Error;
use serde::Deserialize;
use std::env;
+use std::fs;
use std::net::IpAddr;
+use std::sync::RwLock;
static CONFIG_FILE_DEFAULTS: &str = "config/defaults.hjson";
static CONFIG_FILE: &str = "config/config.hjson";
-#[derive(Debug, Deserialize)]
+#[derive(Debug, Deserialize, Clone)]
pub struct Settings {
pub setup: Option<Setup>,
pub database: Database,
@@ -20,7 +23,7 @@ pub struct Settings {
pub federation: Federation,
}
-#[derive(Debug, Deserialize)]
+#[derive(Debug, Deserialize, Clone)]
pub struct Setup {
pub admin_username: String,
pub admin_password: String,
@@ -28,7 +31,7 @@ pub struct Setup {
pub site_name: String,
}
-#[derive(Debug, Deserialize)]
+#[derive(Debug, Deserialize, Clone)]
pub struct RateLimitConfig {
pub message: i32,
pub message_per_second: i32,
@@ -38,7 +41,7 @@ pub struct RateLimitConfig {
pub register_per_second: i32,
}
-#[derive(Debug, Deserialize)]
+#[derive(Debug, Deserialize, Clone)]
pub struct EmailConfig {
pub smtp_server: String,
pub smtp_login: Option<String>,
@@ -47,7 +50,7 @@ pub struct EmailConfig {
pub use_tls: bool,
}
-#[derive(Debug, Deserialize)]
+#[derive(Debug, Deserialize, Clone)]
pub struct Database {
pub user: String,
pub password: String,
@@ -65,12 +68,10 @@ pub struct Federation {
}
lazy_static! {
- static ref SETTINGS: Settings = {
- match Settings::init() {
- Ok(c) => c,
- Err(e) => panic!("{}", e),
- }
- };
+ static ref SETTINGS: RwLock<Settings> = RwLock::new(match Settings::init() {
+ Ok(c) => c,
+ Err(e) => panic!("{}", e),
+ });
}
impl Settings {
@@ -96,8 +97,8 @@ impl Settings {
}
/// Returns the config as a struct.
- pub fn get() -> &'static Self {
- &SETTINGS
+ pub fn get() -> Self {
+ SETTINGS.read().unwrap().to_owned()
}
/// Returns the postgres connection url. If LEMMY_DATABASE_URL is set, that is used,
@@ -119,4 +120,22 @@ impl Settings {
pub fn api_endpoint(&self) -> String {
format!("{}/api/v1", self.hostname)
}
+
+ pub fn read_config_file() -> Result<String, Error> {
+ Ok(fs::read_to_string(CONFIG_FILE)?)
+ }
+
+ pub fn save_config_file(data: &str) -> Result<String, Error> {
+ fs::write(CONFIG_FILE, data)?;
+
+ // Reload the new settings
+ // From https://stackoverflow.com/questions/29654927/how-do-i-assign-a-string-to-a-mutable-static-variable/47181804#47181804
+ let mut new_settings = SETTINGS.write().unwrap();
+ *new_settings = match Settings::init() {
+ Ok(c) => c,
+ Err(e) => panic!("{}", e),
+ };
+
+ Self::read_config_file()
+ }
}
diff --git a/server/src/version.rs b/server/src/version.rs
index 1491a0a2..f02e9ae5 100644
--- a/server/src/version.rs
+++ b/server/src/version.rs
@@ -1 +1 @@
-pub const VERSION: &str = "v0.6.44";
+pub const VERSION: &str = "v0.6.49";
diff --git a/server/src/websocket/mod.rs b/server/src/websocket/mod.rs
index a1feede2..c7136423 100644
--- a/server/src/websocket/mod.rs
+++ b/server/src/websocket/mod.rs
@@ -46,4 +46,6 @@ pub enum UserOperation {
GetPrivateMessages,
UserJoin,
GetComments,
+ GetSiteConfig,
+ SaveSiteConfig,
}
diff --git a/server/src/websocket/server.rs b/server/src/websocket/server.rs
index f205c91e..faa8041c 100644
--- a/server/src/websocket/server.rs
+++ b/server/src/websocket/server.rs
@@ -708,6 +708,16 @@ fn parse_json_message(chat: &mut ChatServer, msg: StandardMessage) -> Result<Str
res.online = chat.sessions.len();
to_json_string(&user_operation, &res)
}
+ UserOperation::GetSiteConfig => {
+ let get_site_config: GetSiteConfig = serde_json::from_str(data)?;
+ let res = Oper::new(get_site_config).perform(&conn)?;
+ to_json_string(&user_operation, &res)
+ }
+ UserOperation::SaveSiteConfig => {
+ let save_site_config: SaveSiteConfig = serde_json::from_str(data)?;
+ let res = Oper::new(save_site_config).perform(&conn)?;
+ to_json_string(&user_operation, &res)
+ }
UserOperation::Search => {
do_user_operation::<Search, SearchResponse>(user_operation, data, &conn)
}