From 7c374ec75648d0dfe845f49e72964ed34014b8f4 Mon Sep 17 00:00:00 2001
From: Paul Makles <paulmakles@gmail.com>
Date: Sun, 30 Aug 2020 17:48:30 +0100
Subject: [PATCH] Use flags for email / registration correctly.

---
 Cargo.lock              |  2 +-
 Cargo.toml              |  2 +-
 src/database/mod.rs     |  9 ++++---
 src/main.rs             | 10 +++++++-
 src/notifications/ws.rs | 15 +++++-------
 src/routes/account.rs   | 52 +++++++++++++++++++++++++++--------------
 src/routes/root.rs      | 11 +++++----
 src/util/captcha.rs     |  7 +++---
 src/util/variables.rs   | 41 +++++++++++++++++++++++++++++++-
 9 files changed, 106 insertions(+), 43 deletions(-)

diff --git a/Cargo.lock b/Cargo.lock
index 0c82027..d10c57f 100644
--- a/Cargo.lock
+++ b/Cargo.lock
@@ -2031,7 +2031,7 @@ dependencies = [
 
 [[package]]
 name = "revolt"
-version = "0.2.9"
+version = "0.2.10"
 dependencies = [
  "bcrypt",
  "bitfield",
diff --git a/Cargo.toml b/Cargo.toml
index 691b0df..c08634c 100644
--- a/Cargo.toml
+++ b/Cargo.toml
@@ -1,6 +1,6 @@
 [package]
 name = "revolt"
-version = "0.2.9"
+version = "0.2.10"
 authors = ["Paul Makles <paulmakles@gmail.com>"]
 edition = "2018"
 
diff --git a/src/database/mod.rs b/src/database/mod.rs
index d473952..1219f5b 100644
--- a/src/database/mod.rs
+++ b/src/database/mod.rs
@@ -1,13 +1,12 @@
-use mongodb::sync::{Client, Collection, Database};
-use std::env;
+use crate::util::variables::MONGO_URI;
 
+use mongodb::sync::{Client, Collection, Database};
 use once_cell::sync::OnceCell;
+
 static DBCONN: OnceCell<Client> = OnceCell::new();
 
 pub fn connect() {
-    let client =
-        Client::with_uri_str(&env::var("DB_URI").expect("DB_URI not in environment variables!"))
-            .expect("Failed to init db connection.");
+    let client = Client::with_uri_str(&MONGO_URI).expect("Failed to init db connection.");
 
     DBCONN.set(client).unwrap();
     migrations::run_migrations();
diff --git a/src/main.rs b/src/main.rs
index b10d6de..eb2307a 100644
--- a/src/main.rs
+++ b/src/main.rs
@@ -16,10 +16,18 @@ pub mod util;
 
 use rocket_cors::AllowedOrigins;
 use std::thread;
+use log::info;
 
 fn main() {
     dotenv::dotenv().ok();
-    env_logger::init();
+    env_logger::init_from_env(
+        env_logger::Env::default()
+            .filter_or("RUST_LOG", "info")
+    );
+
+    info!("Starting REVOLT server.");
+
+    util::variables::preflight_checks();
     database::connect();
     notifications::start_worker();
 
diff --git a/src/notifications/ws.rs b/src/notifications/ws.rs
index af00dbf..2274095 100644
--- a/src/notifications/ws.rs
+++ b/src/notifications/ws.rs
@@ -1,7 +1,7 @@
 use super::state::{self, StateResult};
+use crate::util::variables::WS_HOST;
 
 use serde_json::{from_str, json, Value};
-use std::env;
 use ulid::Ulid;
 use ws::{listen, CloseCode, Error, Handler, Handshake, Message, Result, Sender};
 
@@ -126,13 +126,10 @@ impl Handler for Server {
 pub fn launch_server() {
     state::init();
 
-    listen(
-        env::var("WS_HOST").unwrap_or("0.0.0.0:9000".to_string()),
-        |sender| Server {
-            sender,
-            user_id: None,
-            id: Ulid::new().to_string(),
-        },
-    )
+    listen(WS_HOST.to_string(), |sender| Server {
+        sender,
+        user_id: None,
+        id: Ulid::new().to_string(),
+    })
     .unwrap()
 }
diff --git a/src/routes/account.rs b/src/routes/account.rs
index 2369dfa..01c565e 100644
--- a/src/routes/account.rs
+++ b/src/routes/account.rs
@@ -1,6 +1,7 @@
 use super::Response;
 use crate::database;
 use crate::util::{captcha, email, gen_token};
+use crate::util::variables::{DISABLE_REGISTRATION, USE_EMAIL};
 
 use bcrypt::{hash, verify};
 use chrono::prelude::*;
@@ -33,7 +34,7 @@ pub fn create(info: Json<Create>) -> Response {
         return Response::BadRequest(json!({ "error": error }));
     }
 
-    if true {
+    if *DISABLE_REGISTRATION {
         return Response::BadRequest(json!({ "error": "Registration disabled." }));
     }
 
@@ -73,30 +74,45 @@ pub fn create(info: Json<Create>) -> Response {
         let access_token = gen_token(92);
         let code = gen_token(48);
 
+        let email_verification = match *USE_EMAIL {
+            true => doc! {
+                "verified": false,
+                "target": info.email.clone(),
+                "expiry": Bson::DateTime(Utc::now() + chrono::Duration::days(1)),
+                "rate_limit": Bson::DateTime(Utc::now() + chrono::Duration::minutes(1)),
+                "code": code.clone(),
+            },
+            false => doc! {
+                "verified": true
+            }
+        };
+
+        let id = Ulid::new().to_string();
         match col.insert_one(
             doc! {
-                "_id": Ulid::new().to_string(),
+                "_id": &id,
                 "email": info.email.clone(),
                 "username": info.username.clone(),
                 "display_name": info.username.clone(),
                 "password": hashed,
-                "access_token": access_token,
-                "email_verification": {
-                    "verified": false,
-                    "target": info.email.clone(),
-                    "expiry": Bson::DateTime(Utc::now() + chrono::Duration::days(1)),
-                    "rate_limit": Bson::DateTime(Utc::now() + chrono::Duration::minutes(1)),
-                    "code": code.clone(),
-                }
+                "access_token": &access_token,
+                "email_verification": email_verification
             },
             None,
         ) {
             Ok(_) => {
-                let sent = email::send_verification_email(info.email.clone(), code);
-
-                Response::Success(json!({
-                    "email_sent": sent,
-                }))
+                if *USE_EMAIL {
+                    let sent = email::send_verification_email(info.email.clone(), code);
+
+                    Response::Success(json!({
+                        "email_sent": sent,
+                    }))
+                } else {
+                    Response::Success(json!({
+                        "id": id,
+                        "access_token": access_token
+                    }))
+                }
             }
             Err(_) => {
                 Response::InternalServerError(json!({ "error": "Failed to create account." }))
@@ -147,8 +163,10 @@ pub fn verify_email(code: String) -> Response {
             )
             .expect("Failed to update user!");
 
-            if let Err(err) = email::send_welcome_email(target.to_string(), user.username) {
-                error!("Failed to send welcome email! {}", err);
+            if *USE_EMAIL {
+                if let Err(err) = email::send_welcome_email(target.to_string(), user.username) {
+                    error!("Failed to send welcome email! {}", err);
+                }
             }
 
             Response::Redirect(super::Redirect::to("https://app.revolt.chat"))
diff --git a/src/routes/root.rs b/src/routes/root.rs
index 124f095..3026701 100644
--- a/src/routes/root.rs
+++ b/src/routes/root.rs
@@ -1,5 +1,5 @@
 use super::Response;
-use crate::util::variables::{USE_EMAIL_VERIFICATION, USE_HCAPTCHA};
+use crate::util::variables::{USE_EMAIL, DISABLE_REGISTRATION, USE_HCAPTCHA};
 
 use mongodb::bson::doc;
 
@@ -7,15 +7,16 @@ use mongodb::bson::doc;
 #[get("/")]
 pub fn root() -> Response {
     Response::Success(json!({
-        "revolt": "0.2.9",
+        "revolt": "0.2.10",
         "version": {
             "major": 0,
             "minor": 2,
-            "patch": 9
+            "patch": 10
         },
         "features": {
-            "email_verification": USE_EMAIL_VERIFICATION.clone(),
-            "captcha": USE_HCAPTCHA.clone(),
+            "registration": !*DISABLE_REGISTRATION,
+            "captcha": *USE_HCAPTCHA,
+            "email": *USE_EMAIL,
         }
     }))
 }
diff --git a/src/util/captcha.rs b/src/util/captcha.rs
index d2dda33..3a484eb 100644
--- a/src/util/captcha.rs
+++ b/src/util/captcha.rs
@@ -1,7 +1,8 @@
+use crate::util::variables::{HCAPTCHA_KEY, USE_HCAPTCHA};
+
 use reqwest::blocking::Client;
 use serde::{Deserialize, Serialize};
 use std::collections::HashMap;
-use std::env;
 
 #[derive(Serialize, Deserialize)]
 struct CaptchaResponse {
@@ -9,10 +10,10 @@ struct CaptchaResponse {
 }
 
 pub fn verify(user_token: &Option<String>) -> Result<(), String> {
-    if let Ok(key) = env::var("HCAPTCHA_KEY") {
+    if *USE_HCAPTCHA {
         if let Some(token) = user_token {
             let mut map = HashMap::new();
-            map.insert("secret", key);
+            map.insert("secret", HCAPTCHA_KEY.to_string());
             map.insert("response", token.to_string());
 
             let client = Client::new();
diff --git a/src/util/variables.rs b/src/util/variables.rs
index 2965d9d..803d08b 100644
--- a/src/util/variables.rs
+++ b/src/util/variables.rs
@@ -1,11 +1,16 @@
+use log::warn;
 use std::env;
 
 lazy_static! {
+    // General Configuration
     pub static ref MONGO_URI: String =
         env::var("REVOLT_MONGO_URI").expect("Missing REVOLT_MONGO_URI environment variable.");
     pub static ref PUBLIC_URL: String =
         env::var("REVOLT_PUBLIC_URL").expect("Missing REVOLT_PUBLIC_URL environment variable.");
-    pub static ref USE_EMAIL_VERIFICATION: bool = env::var("REVOLT_USE_EMAIL_VERIFICATION").map_or(
+    
+    // Application Flags
+    pub static ref DISABLE_REGISTRATION: bool = env::var("REVOLT_DISABLE_REGISTRATION").map_or(false, |v| v == "*1");
+    pub static ref USE_EMAIL: bool = env::var("REVOLT_USE_EMAIL_VERIFICATION").map_or(
         env::var("REVOLT_SMTP_HOST").is_ok()
             && env::var("REVOLT_SMTP_USERNAME").is_ok()
             && env::var("REVOLT_SMTP_PASSWORD").is_ok()
@@ -13,6 +18,8 @@ lazy_static! {
         |v| v == *"1"
     );
     pub static ref USE_HCAPTCHA: bool = env::var("REVOLT_HCAPTCHA_KEY").is_ok();
+
+    // SMTP Settings
     pub static ref SMTP_HOST: String =
         env::var("REVOLT_SMTP_HOST").unwrap_or_else(|_| "".to_string());
     pub static ref SMTP_USERNAME: String =
@@ -20,8 +27,40 @@ lazy_static! {
     pub static ref SMTP_PASSWORD: String =
         env::var("SMTP_PASSWORD").unwrap_or_else(|_| "".to_string());
     pub static ref SMTP_FROM: String = env::var("SMTP_FROM").unwrap_or_else(|_| "".to_string());
+
+    // Application Settings
     pub static ref HCAPTCHA_KEY: String =
         env::var("REVOLT_HCAPTCHA_KEY").unwrap_or_else(|_| "".to_string());
     pub static ref WS_HOST: String =
         env::var("REVOLT_WS_HOST").unwrap_or_else(|_| "0.0.0.0:9999".to_string());
 }
+
+pub fn preflight_checks() {
+    if *USE_EMAIL == false {
+        #[cfg(not(debug_assertions))]
+        {
+            if !env::var("REVOLT_UNSAFE_NO_EMAIL")
+                .map_or(false, |v| v == *"1") {
+                panic!(
+                    "Not letting you run this in production, set REVOLT_UNSAFE_NO_EMAIL=1 to run."
+                );
+            }
+        }
+
+        #[cfg(debug_assertions)]
+        warn!("No SMTP settings specified! Remember to configure email.");
+    }
+
+    if *USE_HCAPTCHA == false {
+        #[cfg(not(debug_assertions))]
+        {
+            if !env::var("REVOLT_UNSAFE_NO_CAPTCHA")
+                .map_or(false, |v| v == *"1") {
+                panic!("Not letting you run this in production, set REVOLT_UNSAFE_NO_CAPTCHA=1 to run.");
+            }
+        }
+
+        #[cfg(debug_assertions)]
+        warn!("No Captcha key specified! Remember to add hCaptcha key.");
+    }
+}
-- 
GitLab