diff --git a/README.md b/README.md index 5f54073..76d56a3 100644 --- a/README.md +++ b/README.md @@ -18,10 +18,13 @@ ARGS: ... Set sites where comments will be posted OPTIONS: - -h, --help Print help information - -p, --port Set port where HTTP requests will be received [default: 8080] - -t, --testing Run in testing mode, with in-memory database(s) and permissive CORS policy - -V, --version Print version information + -e, --email-required Require email for comment submissions + -h, --help Print help information + -n, --name-required Require name for comment submissions + -p, --port Set port where HTTP requests will be received [default: 8080] + -t, --testing Run in testing mode, with in-memory database(s) and permissive CORS + policy + -V, --version Print version information ``` The sites must be prefixed with either `http://` or `https://`. Each site may only use one protocol, so the HTTP and HTTPS versions of each site are considered separate sites. You should redirect HTTPS to HTTP. @@ -34,6 +37,8 @@ soudan -p 8081 https://example.com https://example.org In addition, you can add the `-t`/`--testing` flag to run Soudan in testing mode. In this mode, Soudan stores all comments in a fresh in-memory database, and **all comments will be lost once Soudan is closed.** In addition, a permissive CORS policy is used to make testing easier. +Finally, you can also add the `-n`/`--name-required` and/or `-e`/`--email-required` flags to prevent anonymous comments. Keep in mind that the JavaScript in [soudan.js](demo/soudan.js) assumes that these flags are not set, so you would need to manually add the `required` flag to the name and email `` fields respectively. + ### Moderation Soudan does not have any spam filtering or moderation built in. However, going into the database manually to browse and remove comments is very easy. If you need an SQLite database browser, I'd recommend [DB Browser for SQLite](https://sqlitebrowser.org/). diff --git a/src/main.rs b/src/main.rs index d09a224..9e16000 100644 --- a/src/main.rs +++ b/src/main.rs @@ -16,6 +16,7 @@ use clap::Parser; struct AppState { databases: HashMap>, + arguments: Arguments, } #[derive(Default, Parser)] @@ -27,6 +28,10 @@ struct Arguments { sites: Vec, #[clap(short, long, help = "Run in testing mode, with in-memory database(s) and permissive CORS policy")] testing: bool, + #[clap(short, long, help = "Require name for comment submissions")] + name_required: bool, + #[clap(short, long, help = "Require email for comment submissions")] + email_required: bool, } fn get_db<'a>( @@ -96,6 +101,12 @@ async fn post_comment( if comment.validate().is_err() { return HttpResponse::BadRequest().reason("invalid comment field(s)").finish(); } + if comment.author.is_none() && data.arguments.name_required { + return HttpResponse::BadRequest().reason("name required").finish(); + } + if comment.email.is_none() && data.arguments.email_required { + return HttpResponse::BadRequest().reason("email required").finish(); + } let origin = match request.head().headers().get("Origin") { Some(origin) => match origin.to_str() { Ok(origin) => origin, @@ -191,15 +202,16 @@ async fn get_page_data(url: &str) -> Result, reqwest::Error> { #[actix_web::main] async fn main() -> Result<(), std::io::Error> { - let args = Arguments::parse(); + let arguments = Arguments::parse(); let mut databases = HashMap::new(); - for domain in args.sites.iter() { + for domain in arguments.sites.iter() { databases.insert( domain.to_owned(), - Mutex::new(Database::new(args.testing, domain).unwrap()), + Mutex::new(Database::new(arguments.testing, domain).unwrap()), ); } - let state = web::Data::new(AppState { databases }); + let port = arguments.port; + let state = web::Data::new(AppState { databases, arguments }); HttpServer::new(move || { App::new() .service(get_comments) @@ -207,18 +219,18 @@ async fn main() -> Result<(), std::io::Error> { .app_data(state.clone()) // Issue with CORS on POST requests, // keeping permissive for now - .wrap(Cors::permissive() /* if args.testing { + .wrap(Cors::permissive() /* if arguments.testing { Cors::permissive() } else { let mut cors = Cors::default() .allowed_methods(vec!["GET", "POST"]); - for domain in args.sites.iter() { + for domain in arguments.sites.iter() { cors = cors.allowed_origin(domain); } cors } */) }) - .bind(("127.0.0.1", args.port))? + .bind(("127.0.0.1", port))? .run() .await }