diff options
-rw-r--r-- | comments/Cargo.lock | 20 | ||||
-rw-r--r-- | comments/Cargo.toml | 5 | ||||
-rw-r--r-- | comments/migrations/1_capcha.sql | 6 | ||||
-rw-r--r-- | comments/src/main.rs | 35 | ||||
-rw-r--r-- | comments/templates/form.html | 3 |
5 files changed, 45 insertions, 24 deletions
diff --git a/comments/Cargo.lock b/comments/Cargo.lock index 1ed266e..1f2ab0b 100644 --- a/comments/Cargo.lock +++ b/comments/Cargo.lock @@ -95,7 +95,6 @@ checksum = "08b108ad2665fa3f6e6a517c3d80ec3e77d224c47d605167aefaa5d7ef97fa48" dependencies = [ "async-trait", "axum-core", - "axum-macros", "bitflags", "bytes", "futures-util", @@ -139,18 +138,6 @@ dependencies = [ ] [[package]] -name = "axum-macros" -version = "0.3.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "e4df0fc33ada14a338b799002f7e8657711422b25d4e16afb032708d6b185621" -dependencies = [ - "heck", - "proc-macro2", - "quote", - "syn", -] - -[[package]] name = "base-x" version = "0.2.11" source = "registry+https://github.com/rust-lang/crates.io-index" @@ -1164,6 +1151,7 @@ dependencies = [ "time", "tokio-stream", "url", + "uuid", "webpki", "webpki-roots", "whoami", @@ -1565,6 +1553,12 @@ dependencies = [ ] [[package]] +name = "uuid" +version = "0.8.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "bc5cf98d8186244414c848017f0e2676b3fcb46807f6668a97dfe67359a3c4b7" + +[[package]] name = "version_check" version = "0.9.4" source = "registry+https://github.com/rust-lang/crates.io-index" diff --git a/comments/Cargo.toml b/comments/Cargo.toml index 61b8a46..8773580 100644 --- a/comments/Cargo.toml +++ b/comments/Cargo.toml @@ -7,9 +7,8 @@ edition = "2021" [dependencies] askama = "0.11" -axum = { version="0.6", features = ["macros"] } +axum = { version="0.6" } serde = "1" -sqlx = { version = "0.5", features = ["runtime-tokio-rustls", "any", "postgres", "time"] } -# time = "0.3" +sqlx = { version = "0.5", features = ["runtime-tokio-rustls", "any", "postgres", "time", "uuid"] } tokio = { version = "1", features = ["full"] } diff --git a/comments/migrations/1_capcha.sql b/comments/migrations/1_capcha.sql new file mode 100644 index 0000000..c80a4bd --- /dev/null +++ b/comments/migrations/1_capcha.sql @@ -0,0 +1,6 @@ +create table if not exists capchas(question text not null, answer text not null, id uuid not null default gen_random_uuid()); +create unique index if not exists idx_capchas_id on capchas(id); +insert into capchas(question, answer) values ('What is 1 + 3?', '4'); +insert into capchas(question, answer) values ('If I have 3 apples and 4 pears, how many fruit do I have?', '7'); +insert into capchas(question, answer) values ('What is 3 squared?', '9'); +insert into capchas(question, answer) values ('What is the meaning of life, the universe, and everything?', '42'); diff --git a/comments/src/main.rs b/comments/src/main.rs index 312dafa..287b89e 100644 --- a/comments/src/main.rs +++ b/comments/src/main.rs @@ -14,12 +14,14 @@ use axum::{ http::StatusCode, routing::get, Router, - debug_handler, }; use serde::Deserialize; use sqlx::{ postgres::{PgPool, PgPoolOptions}, - types::time::OffsetDateTime, + types::{ + time::OffsetDateTime, + uuid::Uuid, + }, }; use std::{net::SocketAddr, time::Duration}; @@ -76,13 +78,20 @@ struct UrlQuery { #[derive(Template)] #[template(path = "form.html")] struct CommentForm { - url: String + url: String, + capcha_question: String, + capcha_id: Uuid, } async fn get_form( - Query(uq): Query<UrlQuery>, + State(ctx): State<Ctx>, + Query(uq): Query<UrlQuery> ) -> Result<String, (StatusCode, String)> { - let c = CommentForm{url: uq.url}; + let capcha = sqlx::query!("select id, question from capchas order by random() limit 1") + .fetch_one(&ctx.pool) + .await + .map_err(internal_error)?; + let c = CommentForm{url: uq.url, capcha_question: capcha.question, capcha_id: capcha.id}; let res = c.render().map_err(internal_error)?; Ok(res) } @@ -99,8 +108,8 @@ struct Comment { } async fn get_comments( - Query(uq): Query<UrlQuery>, - State(ctx): State<Ctx>) -> Result<String, (StatusCode,String)> { + State(ctx): State<Ctx>, + Query(uq): Query<UrlQuery>) -> Result<String, (StatusCode,String)> { let comments = sqlx::query!("select author,comment,ts from comments where url = $1", uq.url) .fetch_all(&ctx.pool) .await @@ -122,12 +131,22 @@ struct PostComment { url: String, author: String, comment: String, + capcha_id: String, + capcha_answer: String, } -#[debug_handler] async fn post_comments( State(ctx): State<Ctx>, Form(post_comment): Form<PostComment>) -> Result<Redirect,(StatusCode,String)> { + let capcha_id: Uuid = post_comment.capcha_id.parse() + .map_err(|_| {(StatusCode::BAD_REQUEST, "Invalid capcha_id".to_string())})?; + let ans: String = sqlx::query_as!("select answer from capchas where id = $1", capcha_id) + .fetch_one(&ctx.pool) + .await + .map_err(internal_error)?; + if post_comment.capcha_answer != ans { + return Err((StatusCode::BAD_REQUEST, "Capcha was wrong!".to_string())); + } sqlx::query!("insert into comments(url,author,comment) values($1, $2, $3)", post_comment.url, post_comment.author, post_comment.comment) .execute(&ctx.pool) .await diff --git a/comments/templates/form.html b/comments/templates/form.html index 90c065e..09fc81f 100644 --- a/comments/templates/form.html +++ b/comments/templates/form.html @@ -1,8 +1,11 @@ <form action="/api/comments"> <input type="hidden" name="url" value="{{ url }}"><br> + <input type="hidden" name="capcha_id" value="{{ capcha_id }}"><br> <label for="author">Name:</label><br> <input type="text" id="author" name="author"><br> <label for="comment">Comment:</label><br> <input type="text" id="comment" name="lname"> + <label for="capcha">{{ capcha_question }}</label> + <input type="text" id="capcha" name="capcha_answer"><br> <input type="submit" value="Submit"> </form> |