diff --git a/.config.json b/.config.json new file mode 100644 index 0000000..e5d1aef --- /dev/null +++ b/.config.json @@ -0,0 +1,13 @@ +{ + "static_dir": "./static/", + "bind_address": "0.0.0.0", + "non_ssl_port": 8000, + "ssl_enabled": false, + "ssl_port": null, + "ssl_cert": null, + "ssl_key": null, + "logger_pattern": "%t [%a] %s %{User-Agent}i %r", + "log_file": "logs.txt", + "salt": "PUT SOME TEXT FOR SALT", + "tenor_key": "GET API KEY FROM https://tenor.com AND PASTE HERE" +} diff --git a/.dockerignore b/.dockerignore index ea8c4bf..d0009f8 100644 --- a/.dockerignore +++ b/.dockerignore @@ -1 +1,3 @@ /target +/actix-web-middleware-redirect-https/ +/logs.txt diff --git a/.gitignore b/.gitignore index 5a32749..a546487 100644 --- a/.gitignore +++ b/.gitignore @@ -1,4 +1,5 @@ /target -/etc/config.json /localhost-key.pem /localhost.pem +/actix-web-middleware-redirect-https/ +/logs.txt diff --git a/Cargo.lock b/Cargo.lock index 9c70ab3..7d684dc 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -280,6 +280,16 @@ dependencies = [ "syn 1.0.85", ] +[[package]] +name = "actix-web-middleware-redirect-https" +version = "3.0.1" +source = "git+https://github.com/PiyushXCoder/actix-web-middleware-redirect-https.git#00234bef996e3373a73e34edd4c373984649f656" +dependencies = [ + "actix-service", + "actix-web", + "futures", +] + [[package]] name = "actix_derive" version = "0.6.0" @@ -374,7 +384,7 @@ version = "0.2.14" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "d9b39be18770d11421cdb1b9947a45dd3f37e93092cbf377614828a319d5fee8" dependencies = [ - "hermit-abi 0.1.19", + "hermit-abi", "libc", "winapi", ] @@ -499,11 +509,12 @@ dependencies = [ [[package]] name = "cc" -version = "1.0.72" +version = "1.0.83" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "22a9137b95ea06864e018375b72adfb7db6e6f68cfc8df5a04d00288050485ee" +checksum = "f1174fb0b6ec23863f8b971027804a42614e347eafb0a95bf0b12cdae21fc4d0" dependencies = [ "jobserver", + "libc", ] [[package]] @@ -645,40 +656,6 @@ dependencies = [ "cfg-if", ] -[[package]] -name = "env_logger" -version = "0.10.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "85cdab6a89accf66733ad5a1693a4dcced6aeff64602b634530dd73c1f3ee9f0" -dependencies = [ - "humantime", - "is-terminal", - "log", - "regex", - "termcolor", -] - -[[package]] -name = "errno" -version = "0.3.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "4bcfec3a70f97c962c307b2d2c56e358cf1d00b558d74262b5f929ee8cc7e73a" -dependencies = [ - "errno-dragonfly", - "libc", - "windows-sys", -] - -[[package]] -name = "errno-dragonfly" -version = "0.1.2" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "aa68f1b12764fab894d2755d2518754e71b4fd80ecfb822714a1206c2aab39bf" -dependencies = [ - "cc", - "libc", -] - [[package]] name = "flate2" version = "1.0.22" @@ -697,21 +674,6 @@ version = "1.0.7" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "3f9eec918d3f24069decb9af1554cad7c880e2da24a9afd88aca000531ab82c1" -[[package]] -name = "foreign-types" -version = "0.3.2" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "f6f339eb8adc052cd2ca78910fda869aefa38d22d5cb648e6485e4d3fc06f3b1" -dependencies = [ - "foreign-types-shared", -] - -[[package]] -name = "foreign-types-shared" -version = "0.1.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "00b0228411908ca8685dba7fc2cdd70ec9990a6e753e89b6ac91a84c40fbaf4b" - [[package]] name = "form_urlencoded" version = "1.0.1" @@ -878,12 +840,6 @@ dependencies = [ "libc", ] -[[package]] -name = "hermit-abi" -version = "0.3.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "fed44880c466736ef9a5c5b5facefb5ed0785676d0c02d612db14e54f0d84286" - [[package]] name = "http" version = "0.2.9" @@ -913,12 +869,6 @@ version = "1.0.2" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "c4a1e36c821dbe04574f602848a19f742f4fb3c98d40449f11bcad18d6b17421" -[[package]] -name = "humantime" -version = "2.1.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "9a3a5bfb195931eeb336b2a7b4d761daec841b97f947d34394601737a7bba5e4" - [[package]] name = "idna" version = "0.2.3" @@ -940,29 +890,6 @@ dependencies = [ "hashbrown", ] -[[package]] -name = "io-lifetimes" -version = "1.0.11" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "eae7b9aee968036d54dce06cebaefd919e4472e753296daccd6d344e3e2df0c2" -dependencies = [ - "hermit-abi 0.3.1", - "libc", - "windows-sys", -] - -[[package]] -name = "is-terminal" -version = "0.4.7" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "adcf93614601c8129ddf72e2d5633df827ba6551541c6d8c59520a371475be1f" -dependencies = [ - "hermit-abi 0.3.1", - "io-lifetimes", - "rustix", - "windows-sys", -] - [[package]] name = "itoa" version = "1.0.1" @@ -1001,15 +928,9 @@ checksum = "e2abad23fbc42b3700f2f279844dc832adb2b2eb069b2df918f455c4e18cc646" [[package]] name = "libc" -version = "0.2.146" +version = "0.2.151" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "f92be4933c13fd498862a9e02a3055f8a8d9c039ce33db97306fd5a6caa7f29b" - -[[package]] -name = "linux-raw-sys" -version = "0.3.8" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "ef53942eb7bf7ff43a617b3e2c1c4a5ecf5944a7c1bc12d7ee39bbb15e5c1519" +checksum = "302d7ab3130588088d277783b1e2d2e10c9e9e4a16dd9050e6ec93fb3e7048f4" [[package]] name = "local-channel" @@ -1057,21 +978,22 @@ dependencies = [ "actix-files", "actix-web", "actix-web-actors", + "actix-web-middleware-redirect-https", "anyhow", "awc", "base64", "clap", - "env_logger", "futures", "lazy_static", "log", - "openssl", "rand", "rustls", "rustls-pemfile", "serde", "serde_json", "sha2", + "simplelog", + "tokio", ] [[package]] @@ -1130,7 +1052,16 @@ version = "1.13.1" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "19e64526ebdee182341572e50e9ad03965aa510cd94427a4549448f285e957a1" dependencies = [ - "hermit-abi 0.1.19", + "hermit-abi", + "libc", +] + +[[package]] +name = "num_threads" +version = "0.1.6" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "2819ce041d2ee131036f4fc9d6ae7ae125a3a40e97ba64d04fe799ad9dabbb44" +dependencies = [ "libc", ] @@ -1149,33 +1080,6 @@ version = "1.18.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "dd8b5dd2ae5ed71462c540258bedcb51965123ad7e7ccf4b9a8cafaa4a63576d" -[[package]] -name = "openssl" -version = "0.10.38" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "0c7ae222234c30df141154f159066c5093ff73b63204dcda7121eb082fc56a95" -dependencies = [ - "bitflags", - "cfg-if", - "foreign-types", - "libc", - "once_cell", - "openssl-sys", -] - -[[package]] -name = "openssl-sys" -version = "0.9.72" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "7e46109c383602735fa0a2e48dd2b7c892b048e1bf69e5c3b1d804b7d9c203cb" -dependencies = [ - "autocfg", - "cc", - "libc", - "pkg-config", - "vcpkg", -] - [[package]] name = "os_str_bytes" version = "6.0.0" @@ -1379,20 +1283,6 @@ dependencies = [ "semver", ] -[[package]] -name = "rustix" -version = "0.37.20" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "b96e891d04aa506a6d1f318d2771bcb1c7dfda84e126660ace067c9b474bb2c0" -dependencies = [ - "bitflags", - "errno", - "io-lifetimes", - "libc", - "linux-raw-sys", - "windows-sys", -] - [[package]] name = "rustls" version = "0.20.8" @@ -1407,9 +1297,9 @@ dependencies = [ [[package]] name = "rustls-pemfile" -version = "1.0.2" +version = "1.0.4" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "d194b56d58803a43635bdc398cd17e383d6f71f9182b9a192c127ca42494a59b" +checksum = "1c74cae0a4cf6ccbbf5f359f08efdf8ee7e1dc532573bf0db71968cb56b1448c" dependencies = [ "base64", ] @@ -1516,6 +1406,17 @@ dependencies = [ "libc", ] +[[package]] +name = "simplelog" +version = "0.12.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "acee08041c5de3d5048c8b3f6f13fafb3026b24ba43c6a695a0c76179b844369" +dependencies = [ + "log", + "termcolor", + "time", +] + [[package]] name = "slab" version = "0.4.5" @@ -1588,6 +1489,8 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "ea9e1b3cf1243ae005d9e74085d4d542f3125458f3a81af210d901dcd7411efd" dependencies = [ "itoa", + "libc", + "num_threads", "serde", "time-core", "time-macros", @@ -1633,13 +1536,26 @@ dependencies = [ "bytes", "libc", "mio", + "num_cpus", "parking_lot", "pin-project-lite", "signal-hook-registry", "socket2", + "tokio-macros", "windows-sys", ] +[[package]] +name = "tokio-macros" +version = "2.1.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "630bdcf245f78637c13ec01ffae6187cca34625e8c63150d424b59e55af2675e" +dependencies = [ + "proc-macro2", + "quote", + "syn 2.0.18", +] + [[package]] name = "tokio-rustls" version = "0.23.4" @@ -1758,12 +1674,6 @@ dependencies = [ "percent-encoding", ] -[[package]] -name = "vcpkg" -version = "0.2.15" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "accd4ea62f7bb7a82fe23066fb0957d48ef677f6eeb8215f372f52e48bb32426" - [[package]] name = "version_check" version = "0.9.4" diff --git a/Cargo.toml b/Cargo.toml index 205933c..08c4f55 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -16,22 +16,21 @@ keywords = ["chat", "Chatting", "Talk", "Stranger"] actix = "0.13" actix-web = { version = "4", features = ["rustls"] } actix-web-actors = "4" +actix-web-middleware-redirect-https = { git = "https://github.com/PiyushXCoder/actix-web-middleware-redirect-https.git" } actix-broker = "0.4" actix-files = "0.6" awc = "3.1" -env_logger = "0.10" -openssl = "0.10" - clap = { version = "4", features = ["derive"] } lazy_static = "1.4" serde = { version = "1.0", features = ["serde_derive"] } serde_json = "1.0" rand = "0.8" futures = "0.3" - sha2 = "0.10" base64 = "0.21" log = "0.4" -rustls = "0.20" -rustls-pemfile = "1.0.2" anyhow = { version = "1.0.71", features = ["backtrace"] } +simplelog = "0.12.1" +tokio = { version = "1.5.0", features = ['rt', 'rt-multi-thread', 'macros'] } +rustls = "0.20" +rustls-pemfile = "1.0.4" diff --git a/Dockerfile b/Dockerfile index a003616..149801d 100644 --- a/Dockerfile +++ b/Dockerfile @@ -1,10 +1,8 @@ FROM rust:alpine3.18 AS build - -RUN apk add --no-cache musl-dev pkgconfig openssl-dev - +RUN cargo search --limit 0 && \ + apk add --no-cache musl-dev pkgconfig openssl-dev WORKDIR /app COPY . . - RUN cargo build --release @@ -12,23 +10,18 @@ RUN cargo build --release FROM alpine:3.18 -ARG RUNNER_GROUP_ID=local +ARG RUNNER_GROUP_ID=1000 ENV RUNNER_GROUP_ID=${RUNNER_GROUP_ID} -ARG RUNNER_USER_ID=local +ARG RUNNER_USER_ID=1000 ENV RUNNER_USER_ID=${RUNNER_USER_ID} -ARG APP=local -ENV APP=${APP} - -# RUN apk add --no-cache openssl - -RUN addgroup -g ${RUNNER_GROUP_ID} runner && adduser -G runner -u ${RUNNER_USER_ID} runner -D -USER runner - -COPY --from=build --chown=runner:runner /app/target/release/${APP} /app/app -COPY --from=build --chown=runner:runner /app/static /app/static +ENV APP=lupt +ENV RUST_LOG="actix_web=info" +USER ${RUNNER_USER_ID}:${RUNNER_GROUP_ID} WORKDIR /app - -CMD ./app --bind-address 0.0.0.0 --port 8000 --config-file /app/config.json --static-path /app/static +COPY --from=build --chown=${RUNNER_USER_ID}:${RUNNER_GROUP_ID} /app/target/release/${APP} app +COPY --from=build --chown=${RUNNER_USER_ID}:${RUNNER_GROUP_ID} /app/static static/ +COPY --from=build --chown=${RUNNER_USER_ID}:${RUNNER_GROUP_ID} [ "/app/.config.json", "config.json" ] +CMD RUST_LOG="${RUST_LOG}" ./app --config-file config.json diff --git a/docker-compose-dev.yml b/docker-compose-dev.yml new file mode 100644 index 0000000..58a467d --- /dev/null +++ b/docker-compose-dev.yml @@ -0,0 +1,18 @@ + +version: "3.2" +services: + web: + build: + context: . + args: + RUNNER_USER_ID: 1000 + RUNNER_GROUP_ID: 1000 + ports: + - ${PORT}:8000 + volumes: + - ${CONFIG}:/app/config.json + - ${LOG}:/app/logs.txt:rw + environment: + - RUST_LOG=actix_web=info + + diff --git a/docker-compose.yml b/docker-compose.yml index a09126a..02499fb 100644 --- a/docker-compose.yml +++ b/docker-compose.yml @@ -2,14 +2,12 @@ version: "3.2" services: web: - build: - context: . - args: - RUNNER_USER_ID: ${RUNNER_USER_ID} - RUNNER_GROUP_ID: ${RUNNER_GROUP_ID} - APP: ${APP} - + image: "ghcr.io/piyushxcoder/lupt:master" + restart: always ports: - - ${PORT}:8080 + - ${PORT}:8000 volumes: - ${CONFIG}:/app/config.json + - ${LOG}:/app/logs.txt:rw + environment: + - RUST_LOG=actix_web=info diff --git a/etc/config.json.example b/etc/config.json.example deleted file mode 100644 index 357ad21..0000000 --- a/etc/config.json.example +++ /dev/null @@ -1,10 +0,0 @@ -{ - "bind_address": "Address to start server. (For example: localhost:8000)", - "static_dir_path": "Directory to static html files to serve", - "logger_pattern": "https://docs.rs/actix-web/latest/actix_web/middleware/struct.Logger.html (For example: %t [%a] %s %{User-Agent}i %r)", - "salt": "PUT SOME TEXT FOR SALT", - "tenor_key": "GET API KEY FROM https://tenor.com AND PASTE HERE", - "allow_ssl": false, - "ssl_cert": "Path to ssl certificate", - "ssl_key": "Path to ssl key" -} diff --git a/src/chat_pinnd/user.rs b/src/chat_pinnd/user.rs index 4d2ccb2..97311b1 100644 --- a/src/chat_pinnd/user.rs +++ b/src/chat_pinnd/user.rs @@ -294,7 +294,6 @@ impl Handler for ChatPinnd { ); let log_count = kaksh.loog.len(); - drop(kaksh); if log_count == 0 { self.kaksh.remove(&msg.kaksh_kunjika); } diff --git a/src/config.rs b/src/config.rs index 35b6765..9ae9260 100644 --- a/src/config.rs +++ b/src/config.rs @@ -29,17 +29,21 @@ pub(crate) struct Args { #[derive(Deserialize)] pub(crate) struct ConfigFile { - pub(crate) bind_address: String, + pub(crate) static_dir: PathBuf, + + pub(crate) bind_address: String, + pub(crate) non_ssl_port: u16, + + pub(crate) ssl_enabled: bool, + pub(crate) ssl_port: Option, + pub(crate) ssl_cert: Option, + pub(crate) ssl_key: Option, - pub(crate) static_dir_path: PathBuf, pub(crate) logger_pattern: String, + pub(crate) log_file: PathBuf, pub(crate) salt: String, pub(crate) tenor_key: Option, - - pub(crate) allow_ssl: Option, - pub(crate) ssl_cert: Option, - pub(crate) ssl_key: Option, } pub(crate) fn generate() -> ConfigFile { diff --git a/src/main.rs b/src/main.rs index af181c8..e8dc918 100644 --- a/src/main.rs +++ b/src/main.rs @@ -36,7 +36,10 @@ use actix_web_actors::ws; use awc::Client; use config::CONFIG; use rustls::{Certificate, PrivateKey, ServerConfig}; +use rustls_pemfile::{certs, pkcs8_private_keys}; +use simplelog::*; use std::fs::File; +use std::io::BufReader; use ws_sansad::WsSansad; mod broker_messages; @@ -48,12 +51,30 @@ mod ws_sansad; #[actix_web::main] async fn main() -> std::io::Result<()> { - std::env::set_var("RUST_LOG", "info"); - env_logger::init(); - lazy_static::initialize(&CONFIG); - let main_server = HttpServer::new(move || { + CombinedLogger::init(vec![ + TermLogger::new( + LevelFilter::Warn, + Config::default(), + TerminalMode::Mixed, + ColorChoice::Auto, + ), + WriteLogger::new( + LevelFilter::Info, + Config::default(), + File::options() + .write(true) + .open(&CONFIG.log_file) + .unwrap_or_else(|_| { + println!("Creating new log file"); + File::create(&CONFIG.log_file).unwrap() + }), + ), + ]) + .unwrap(); + + let server = HttpServer::new(move || { let mut app = App::new() .wrap(Logger::new(&CONFIG.logger_pattern)) .service(web::resource("/ws/").route(web::get().to(ws_index))); @@ -66,56 +87,84 @@ async fn main() -> std::io::Result<()> { } } - app = app.service(fs::Files::new("/", &CONFIG.static_dir_path).index_file("index.html")); + app = app.service(fs::Files::new("/", &CONFIG.static_dir).index_file("index.html")); app }); - let main_server = if CONFIG.allow_ssl.unwrap_or(false) { - main_server + if CONFIG.ssl_enabled { + let server = server .bind_rustls( - &CONFIG.bind_address, - gen_rustls_server_config( + format!("{}:{}", CONFIG.bind_address, CONFIG.ssl_port.unwrap()), + load_rustls_config( CONFIG.ssl_key.clone().unwrap(), CONFIG.ssl_cert.clone().unwrap(), ), )? - .run() + .run(); + let redirect_server = create_redirect_server( + CONFIG.ssl_port.unwrap(), + CONFIG.non_ssl_port, + &CONFIG.bind_address, + ); + let (r1, r2) = tokio::join!(server, redirect_server); + r1.unwrap(); + r2.unwrap(); } else { - main_server.bind(&CONFIG.bind_address)?.run() - }; + server + .bind(format!("{}:{}", CONFIG.bind_address, CONFIG.non_ssl_port))? + .run() + .await?; + } - main_server.await + Ok(()) } -fn gen_rustls_server_config(key: String, cert: String) -> ServerConfig { - let mut br = std::io::BufReader::new(File::open(cert).unwrap()); - let certs = rustls_pemfile::certs(&mut br) +fn load_rustls_config(key: String, cert: String) -> rustls::ServerConfig { + // Load key files + let cert_file = &mut BufReader::new(File::open(cert).unwrap()); + let key_file = &mut BufReader::new(File::open(key).unwrap()); + + // Parse the certificate and set it in the configuration + let cert_chain = certs(cert_file) .unwrap() - .iter() - .map(|a| Certificate(a.to_owned())) + .into_iter() + .map(|a: Vec| rustls::Certificate(a)) .collect::>(); + let key = pkcs8_private_keys(key_file) + .unwrap() + .into_iter() + .map(|a: Vec| rustls::PrivateKey(a)) + .collect::>() + .first() + .unwrap() + .to_owned(); - let mut br = std::io::BufReader::new(File::open(key).unwrap()); - let private_key = rustls_pemfile::ec_private_keys(&mut br).unwrap_or( - rustls_pemfile::rsa_private_keys(&mut br) - .unwrap_or(rustls_pemfile::pkcs8_private_keys(&mut br).unwrap()), - ); - - let private_key = private_key.get(0).unwrap(); - - let private_key = PrivateKey(private_key.to_owned()); - - let config = ServerConfig::builder() - .with_safe_default_cipher_suites() - .with_safe_default_kx_groups() - .with_safe_default_protocol_versions() - .map_err(|e| anyhow!(e)) - .expect("Build TLS!") + // Create configuration + ServerConfig::builder() + .with_safe_defaults() .with_no_client_auth() - .with_single_cert(certs, private_key) - .map_err(|e| anyhow!(e)) - .expect("Add TLS certificates!"); - config + .with_single_cert(cert_chain, key) + .unwrap() +} + +async fn create_redirect_server( + ssl_port: u16, + non_ssl_port: u16, + bind_address: &str, +) -> std::io::Result<()> { + HttpServer::new(move || { + App::new().wrap( + actix_web_middleware_redirect_https::RedirectHTTPS::with_replacements(&[( + non_ssl_port.to_string(), + ssl_port.to_string(), + )]), + ) + }) + .bind(format!("{}:{}", bind_address, non_ssl_port))? + .run() + .await + .unwrap(); + Ok(()) } async fn ws_index(req: HttpRequest, stream: web::Payload) -> Result { diff --git a/src/ws_sansad/messages.rs b/src/ws_sansad/messages.rs index c362018..85b1d05 100644 --- a/src/ws_sansad/messages.rs +++ b/src/ws_sansad/messages.rs @@ -237,7 +237,6 @@ impl WsSansad { for id in ids { msg_id.push(id.as_str().unwrap().to_owned()); } - drop(ids); let kaksh_kunjika = match &self.isthiti { Isthiti::Kaksh(kaksh_kunjika) => kaksh_kunjika.to_owned(),