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

@ -8,7 +8,7 @@ license = "GPL-3.0-only"
readme = "README.md"
repository = "https://github.com/PiyushXCoder/lupt"
homepage = "https://luptchat.in"
keywords = ["chat","Chatting","Talk","Stranger"]
keywords = ["chat", "Chatting", "Talk", "Stranger"]
# See more keys and their definitions at https://doc.rust-lang.org/cargo/reference/manifest.html
@ -16,20 +16,20 @@ keywords = ["chat","Chatting","Talk","Stranger"]
actix = "0.10"
actix-web = { version = "3", features = ["openssl"] }
actix-web-actors = "3"
actix-broker = "0.3.1"
actix-files = "0.5.0"
actix-ratelimit = "0.3.1"
actix-broker = "0.3"
actix-files = "0.5"
actix-ratelimit = "0.3"
actix-web-middleware-redirect-https = "3.0.1"
env_logger = "0.8.3"
openssl = "0.10.28"
env_logger = "0.9"
openssl = "0.10"
clap = "2.33.3"
lazy_static = "1.4.0"
clap = { version = "3.0", features = ["derive"] }
lazy_static = "1.4"
serde = "1.0.123"
serde_json = "1.0.62"
rand = "0.8.3"
tokio = { version = "1.5.0", features = ['rt', 'rt-multi-thread', 'macros']}
serde = "1.0"
serde_json = "1.0"
rand = "0.8"
tokio = { version = "1.5", features = ['rt', 'rt-multi-thread', 'macros'] }
sha1 = "0.6.0"
base64 = "0.13.0"
sha2 = "0.10"
base64 = "0.13"

View File

@ -15,101 +15,170 @@
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 std::{
fs::File,
io::{BufReader, ErrorKind as IOErrorKind},
path::PathBuf,
};
pub struct Config {
pub static_path: String,
pub bind_address: String,
pub port: String,
pub port_x: String,
pub config: ConfigFile,
#[derive(Parser)]
#[clap(author, version, about, long_about = None)]
pub(crate) struct Config {
/// Path of directory with index.html
#[clap(short, long, parse(from_os_str), value_name = "FILE")]
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)]
pub struct ConfigFile {
pub salt: String,
pub tenor_key: String,
pub ssl_cert: String,
pub ssl_key: String,
pub logger_pattern: String,
pub(crate) struct ConfigFile {
pub(crate) salt: String,
pub(crate) tenor_key: String,
pub(crate) ssl_cert: String,
pub(crate) ssl_key: String,
pub(crate) logger_pattern: String,
}
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.
const HELP_CONFIG_FILE: &'static str = "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
",
);
- 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,
pub(crate) fn generate() -> (Config, ConfigFile) {
let config: Config = Config::parse();
let config_file = File::open(&config.config_file);
if let Err(e) = config_file {
let mut app = Config::into_app();
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<()> {
std::env::set_var("RUST_LOG", "actix_web=info");
env_logger::init();
let config = config::Config::new();
let (config, config_file) = config::generate();
*SALT.write().unwrap() = config.config.salt;
*TENOR_API_KEY.write().unwrap() = config.config.tenor_key;
*SALT.write().unwrap() = config_file.salt;
*TENOR_API_KEY.write().unwrap() = config_file.tenor_key;
let ssl_builder = generate_ssl_builder(config.config.ssl_key, config.config.ssl_cert);
let logger_pattern = config.config.logger_pattern;
let ssl_builder = generate_ssl_builder(config_file.ssl_key, config_file.ssl_cert);
let logger_pattern = config_file.logger_pattern;
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 || {
App::new()
.wrap(
@ -112,21 +78,48 @@ async fn main() -> std::io::Result<()> {
.service(fs::Files::new("/", &static_path).index_file("index.html"))
});
if ssl_builder.is_some() && config.port_x != "" {
let srv = server
if ssl_builder.is_some() && config.port_ssl.is_some() {
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(
format!("{}:{}", config.bind_address, config.port),
format!("{}:{}", config.bind_address, config.port_ssl.unwrap()),
ssl_builder.unwrap(),
)?
.run();
tokio::try_join!(redirect.unwrap(), srv)?;
tokio::try_join!(redirect_server, server)?;
} else {
server
.bind(format!("{}:{}", config.bind_address, config.port))?
.run()
.await?;
}
Ok(())
}

View File

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