1) Verison of several crates
2) Sha2 is used now
3) Clap derive is being used
This commit is contained in:
Piyush मिश्रः 2022-01-19 18:37:52 +05:30
parent 46797ef2e2
commit 001eec8b50
5 changed files with 641 additions and 485 deletions

773
Cargo.lock generated

File diff suppressed because it is too large Load Diff

View File

@ -16,20 +16,20 @@ keywords = ["chat","Chatting","Talk","Stranger"]
actix = "0.10" actix = "0.10"
actix-web = { version = "3", features = ["openssl"] } actix-web = { version = "3", features = ["openssl"] }
actix-web-actors = "3" actix-web-actors = "3"
actix-broker = "0.3.1" actix-broker = "0.3"
actix-files = "0.5.0" actix-files = "0.5"
actix-ratelimit = "0.3.1" actix-ratelimit = "0.3"
actix-web-middleware-redirect-https = "3.0.1" actix-web-middleware-redirect-https = "3.0.1"
env_logger = "0.8.3" env_logger = "0.9"
openssl = "0.10.28" openssl = "0.10"
clap = "2.33.3" clap = { version = "3.0", features = ["derive"] }
lazy_static = "1.4.0" lazy_static = "1.4"
serde = "1.0.123" serde = "1.0"
serde_json = "1.0.62" serde_json = "1.0"
rand = "0.8.3" rand = "0.8"
tokio = { version = "1.5.0", features = ['rt', 'rt-multi-thread', 'macros']} tokio = { version = "1.5", features = ['rt', 'rt-multi-thread', 'macros'] }
sha1 = "0.6.0" sha2 = "0.10"
base64 = "0.13.0" base64 = "0.13"

View File

@ -15,101 +15,170 @@
along with Lupt. If not, see <https://www.gnu.org/licenses/> along with Lupt. If not, see <https://www.gnu.org/licenses/>
*/ */
use clap::{App, Arg}; use clap::{ErrorKind as ClapErrorKind, IntoApp, Parser};
// use clap::{App, Arg};
use serde::{Deserialize, Serialize}; use serde::{Deserialize, Serialize};
use std::{
fs::File,
io::{BufReader, ErrorKind as IOErrorKind},
path::PathBuf,
};
pub struct Config { #[derive(Parser)]
pub static_path: String, #[clap(author, version, about, long_about = None)]
pub bind_address: String, pub(crate) struct Config {
pub port: String, /// Path of directory with index.html
pub port_x: String, #[clap(short, long, parse(from_os_str), value_name = "FILE")]
pub config: ConfigFile, pub(crate) static_path: PathBuf,
/// Address to bind for server
#[clap(short, long, value_name = "ADDRESS")]
pub(crate) bind_address: String,
/// Port to bind for http server
#[clap(short, long, value_name = "PORT")]
pub(crate) port: String,
/// Port to bind for https (ssl) server
#[clap(short = 'o', long, value_name = "PORT")]
pub(crate) port_ssl: Option<String>,
/// Path to config file
#[clap(short, long, parse(from_os_str), value_name = "FILE")]
pub(crate) config_file: PathBuf,
} }
#[derive(Serialize, Deserialize)] #[derive(Serialize, Deserialize)]
pub struct ConfigFile { pub(crate) struct ConfigFile {
pub salt: String, pub(crate) salt: String,
pub tenor_key: String, pub(crate) tenor_key: String,
pub ssl_cert: String, pub(crate) ssl_cert: String,
pub ssl_key: String, pub(crate) ssl_key: String,
pub logger_pattern: String, pub(crate) logger_pattern: String,
} }
impl Config { const HELP_CONFIG_FILE: &'static str = "Config File is corrupt.
pub fn new() -> Self {
let matches = App::new("Lupt (लुप्त)")
.version(env!("CARGO_PKG_VERSION"))
.author(env!("CARGO_PKG_AUTHORS"))
.about(env!("CARGO_PKG_DESCRIPTION"))
.arg(
Arg::with_name("bind_address")
.short("a")
.long("bind_address")
.value_name("ADDRESS")
.help("Address to bind for server")
.required(true)
.takes_value(true),
)
.arg(
Arg::with_name("port")
.short("p")
.long("port")
.value_name("PORT")
.help("Port to bind for server")
.required(true)
.takes_value(true),
)
.arg(
Arg::with_name("port_x")
.short("x")
.long("port_x")
.value_name("PORT")
.help("Port to bind for http if ssl is enabled to redirect to https")
.required(false)
.takes_value(true),
)
.arg(
Arg::with_name("static_path")
.short("s")
.long("static_path")
.value_name("DIR")
.help("Path of directory with index.html")
.required(true)
.takes_value(true),
)
.arg(
Arg::with_name("config")
.short("c")
.long("config")
.value_name("FILE")
.help("Path to config file")
.required(true)
.takes_value(true),
)
.get_matches();
let conf = matches.value_of("config").unwrap().to_owned();
let conf = std::fs::read_to_string(conf).expect("Failed to read config");
let config = serde_json::from_str::<ConfigFile>(&conf).expect(
r"
Config File is corrupt.
Config file must have following fields Config file must have following fields
- salt: Salt for hashing - salt: Salt for hashing
- tenor_key: Key of tenor gif api - tenor_key: Key of tenor gif api
- ssl_cert: Path to certificate of ssl - ssl_cert: Path to certificate of ssl
- ssl_key: Path to private key of ssl - ssl_key: Path to private key of ssl
- logger_pattern: Pattern to make log according to Actix Logger - logger_pattern: Pattern to make log according to Actix Logger";
",
);
Config { pub(crate) fn generate() -> (Config, ConfigFile) {
static_path: matches.value_of("static_path").unwrap().to_owned(), let config: Config = Config::parse();
bind_address: matches.value_of("bind_address").unwrap().to_owned(), let config_file = File::open(&config.config_file);
port: matches.value_of("port").unwrap().to_owned(), if let Err(e) = config_file {
port_x: matches.value_of("port_x").unwrap_or("").to_owned(), let mut app = Config::into_app();
config, match e.kind() {
IOErrorKind::NotFound => app
.error(ClapErrorKind::InvalidValue, "Error: Config file is missing")
.exit(),
_ => app
.error(
ClapErrorKind::InvalidValue,
format!("Error(Config File): {}", e.to_string()),
)
.exit(),
} }
} }
let reader = BufReader::new(config_file.unwrap());
let json: ConfigFile = match serde_json::from_reader(reader) {
Ok(read) => read,
Err(e) => {
let mut app = Config::into_app();
app.error(
ClapErrorKind::InvalidValue,
format!(
"Error(Config File): {}\n\n{}",
e.to_string(),
HELP_CONFIG_FILE
),
)
.exit();
} }
};
(config, json)
}
// impl Config {
// pub fn new() -> Self {
// let matches = App::new("Lupt (लुप्त)")
// .version(env!("CARGO_PKG_VERSION"))
// .author(env!("CARGO_PKG_AUTHORS"))
// .about(env!("CARGO_PKG_DESCRIPTION"))
// .arg(
// Arg::with_name("bind_address")
// .short("a")
// .long("bind_address")
// .value_name("ADDRESS")
// .help("Address to bind for server")
// .required(true)
// .takes_value(true),
// )
// .arg(
// Arg::with_name("port")
// .short("p")
// .long("port")
// .value_name("PORT")
// .help("Port to bind for server")
// .required(true)
// .takes_value(true),
// )
// .arg(
// Arg::with_name("port_x")
// .short("x")
// .long("port_x")
// .value_name("PORT")
// .help("Port to bind for http if ssl is enabled to redirect to https")
// .required(false)
// .takes_value(true),
// )
// .arg(
// Arg::with_name("static_path")
// .short("s")
// .long("static_path")
// .value_name("DIR")
// .help("Path of directory with index.html")
// .required(true)
// .takes_value(true),
// )
// .arg(
// Arg::with_name("config")
// .short("c")
// .long("config")
// .value_name("FILE")
// .help("Path to config file")
// .required(true)
// .takes_value(true),
// )
// .get_matches();
// let conf = matches.value_of("config").unwrap().to_owned();
// let conf = std::fs::read_to_string(conf).expect("Failed to read config");
// let config = serde_json::from_str::<ConfigFile>(&conf).expect(
// r"
// Config File is corrupt.
// Config file must have following fields
// - salt: Salt for hashing
// - tenor_key: Key of tenor gif api
// - ssl_cert: Path to certificate of ssl
// - ssl_key: Path to private key of ssl
// - logger_pattern: Pattern to make log according to Actix Logger
// ",
// );
// Config {
// static_path: matches.value_of("static_path").unwrap().to_owned(),
// bind_address: matches.value_of("bind_address").unwrap().to_owned(),
// port: matches.value_of("port").unwrap().to_owned(),
// port_x: matches.value_of("port_x").unwrap_or("").to_owned(),
// config,
// }
// }
// }

View File

@ -55,49 +55,15 @@ lazy_static! {
async fn main() -> std::io::Result<()> { async fn main() -> std::io::Result<()> {
std::env::set_var("RUST_LOG", "actix_web=info"); std::env::set_var("RUST_LOG", "actix_web=info");
env_logger::init(); env_logger::init();
let config = config::Config::new(); let (config, config_file) = config::generate();
*SALT.write().unwrap() = config.config.salt; *SALT.write().unwrap() = config_file.salt;
*TENOR_API_KEY.write().unwrap() = config.config.tenor_key; *TENOR_API_KEY.write().unwrap() = config_file.tenor_key;
let ssl_builder = generate_ssl_builder(config.config.ssl_key, config.config.ssl_cert); let ssl_builder = generate_ssl_builder(config_file.ssl_key, config_file.ssl_cert);
let logger_pattern = config.config.logger_pattern; let logger_pattern = config_file.logger_pattern;
let static_path = config.static_path; let static_path = config.static_path;
let mut redirect = None;
let port_x = config.port_x.clone();
let port = config.port.clone();
if ssl_builder.is_some() && config.port_x != "" {
redirect = Some(
HttpServer::new(move || {
App::new()
.wrap(
RateLimiter::new(
MemoryStoreActor::from(MemoryStore::new().clone()).start(),
)
.with_interval(std::time::Duration::from_secs(60))
.with_max_requests(100),
)
.wrap(
actix_web_middleware_redirect_https::RedirectHTTPS::with_replacements(&[(
port_x.clone(),
port.clone(),
)]),
)
.route(
"/",
web::get().to(|| {
HttpResponse::Ok()
.content_type("text/plain")
.body("Always HTTPS on non-default ports!")
}),
)
})
.bind(format!("{}:{}", config.bind_address, config.port_x))?
.run(),
);
}
let server = HttpServer::new(move || { let server = HttpServer::new(move || {
App::new() App::new()
.wrap( .wrap(
@ -112,21 +78,48 @@ async fn main() -> std::io::Result<()> {
.service(fs::Files::new("/", &static_path).index_file("index.html")) .service(fs::Files::new("/", &static_path).index_file("index.html"))
}); });
if ssl_builder.is_some() && config.port_x != "" { if ssl_builder.is_some() && config.port_ssl.is_some() {
let srv = server let port = config.port.clone();
let port_ssl = config.port_ssl.clone().unwrap();
let redirect_server = HttpServer::new(move || {
App::new()
.wrap(
RateLimiter::new(MemoryStoreActor::from(MemoryStore::new().clone()).start())
.with_interval(std::time::Duration::from_secs(60))
.with_max_requests(100),
)
.wrap(
actix_web_middleware_redirect_https::RedirectHTTPS::with_replacements(&[(
port.clone(),
port_ssl.clone(),
)]),
)
.route(
"/",
web::get().to(|| {
HttpResponse::Ok()
.content_type("text/plain")
.body("Always HTTPS on non-default ports!")
}),
)
})
.bind(format!("{}:{}", config.bind_address, config.port))?
.run();
let server = server
.bind_openssl( .bind_openssl(
format!("{}:{}", config.bind_address, config.port), format!("{}:{}", config.bind_address, config.port_ssl.unwrap()),
ssl_builder.unwrap(), ssl_builder.unwrap(),
)? )?
.run(); .run();
tokio::try_join!(redirect.unwrap(), srv)?;
tokio::try_join!(redirect_server, server)?;
} else { } else {
server server
.bind(format!("{}:{}", config.bind_address, config.port))? .bind(format!("{}:{}", config.bind_address, config.port))?
.run() .run()
.await?; .await?;
} }
Ok(()) Ok(())
} }

View File

@ -16,6 +16,7 @@
*/ */
use super::*; use super::*;
use sha2::{Digest, Sha224};
impl WsSansad { impl WsSansad {
/// Request to join to kaksh /// Request to join to kaksh
@ -53,9 +54,9 @@ impl WsSansad {
self.send_err_response(&val); self.send_err_response(&val);
return; return;
} }
let mut m = sha1::Sha1::new(); let mut hasher = Sha224::new();
m.update(format!("{}{}", kunjika, crate::SALT.read().unwrap()).as_bytes()); hasher.update(format!("{}{}", kunjika, crate::SALT.read().unwrap()).as_bytes());
let kunjika = base64::encode(m.digest().bytes())[..8].to_owned(); let kunjika = base64::encode(hasher.finalize())[..8].to_owned();
// Name // Name
let name = match val.get("name") { let name = match val.get("name") {
@ -158,9 +159,9 @@ impl WsSansad {
self.send_err_response(&val); self.send_err_response(&val);
return; return;
} }
let mut m = sha1::Sha1::new(); let mut hasher = Sha224::new();
m.update(format!("{}{}", kunjika, crate::SALT.read().unwrap()).as_bytes()); hasher.update(format!("{}{}", kunjika, crate::SALT.read().unwrap()).as_bytes());
let kunjika = base64::encode(m.digest().bytes())[..8].to_owned(); let kunjika = base64::encode(hasher.finalize())[..8].to_owned();
// Name // Name
let name = match val.get("name") { let name = match val.get("name") {