feat: added backend for site comments

This commit is contained in:
alzalia1 2025-09-23 21:51:00 +02:00
parent 4b1a899f05
commit af3dfba510
12 changed files with 359 additions and 2 deletions

1
.gitignore vendored
View file

@ -1,3 +1,4 @@
/target
/res
.env
database.db

231
Cargo.lock generated
View file

@ -7,6 +7,7 @@ name = "academic-back"
version = "0.1.0"
dependencies = [
"axum",
"diesel",
"dotenv",
"reqwest",
"serde",
@ -168,6 +169,85 @@ version = "0.8.7"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "773648b94d0e5d620f64f280777445740e61fe701025087ec8b57f45c791888b"
[[package]]
name = "darling"
version = "0.21.3"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "9cdf337090841a411e2a7f3deb9187445851f91b309c0c0a29e05f74a00a48c0"
dependencies = [
"darling_core",
"darling_macro",
]
[[package]]
name = "darling_core"
version = "0.21.3"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "1247195ecd7e3c85f83c8d2a366e4210d588e802133e1e355180a9870b517ea4"
dependencies = [
"fnv",
"ident_case",
"proc-macro2",
"quote",
"strsim",
"syn",
]
[[package]]
name = "darling_macro"
version = "0.21.3"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "d38308df82d1080de0afee5d069fa14b0326a88c14f15c5ccda35b4a6c414c81"
dependencies = [
"darling_core",
"quote",
"syn",
]
[[package]]
name = "deranged"
version = "0.5.3"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "d630bccd429a5bb5a64b5e94f693bfc48c9f8566418fda4c494cc94f911f87cc"
dependencies = [
"powerfmt",
]
[[package]]
name = "diesel"
version = "2.3.2"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "e8496eeb328dce26ee9d9b73275d396d9bddb433fa30106cf6056dd8c3c2764c"
dependencies = [
"diesel_derives",
"downcast-rs",
"libsqlite3-sys",
"sqlite-wasm-rs",
"time",
]
[[package]]
name = "diesel_derives"
version = "2.3.3"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "09af0e983035368439f1383011cd87c46f41da81d0f21dc3727e2857d5a43c8e"
dependencies = [
"diesel_table_macro_syntax",
"dsl_auto_type",
"proc-macro2",
"quote",
"syn",
]
[[package]]
name = "diesel_table_macro_syntax"
version = "0.3.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "fe2444076b48641147115697648dc743c2c00b61adade0f01ce67133c7babe8c"
dependencies = [
"syn",
]
[[package]]
name = "displaydoc"
version = "0.2.5"
@ -185,6 +265,32 @@ version = "0.15.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "77c90badedccf4105eca100756a0b1289e191f6fcbdadd3cee1d2f614f97da8f"
[[package]]
name = "downcast-rs"
version = "2.0.2"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "117240f60069e65410b3ae1bb213295bd828f707b5bec6596a1afc8793ce0cbc"
[[package]]
name = "dsl_auto_type"
version = "0.2.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "dd122633e4bef06db27737f21d3738fb89c8f6d5360d6d9d7635dda142a7757e"
dependencies = [
"darling",
"either",
"heck",
"proc-macro2",
"quote",
"syn",
]
[[package]]
name = "either"
version = "1.15.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "48c757948c5ede0e46177b7add2e67155f70e33c07fea8284df6576da70b3719"
[[package]]
name = "encoding_rs"
version = "0.8.35"
@ -252,6 +358,12 @@ dependencies = [
"percent-encoding",
]
[[package]]
name = "fragile"
version = "2.0.1"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "28dd6caf6059519a65843af8fe2a3ae298b14b80179855aeb4adc2c1934ee619"
[[package]]
name = "futures-channel"
version = "0.3.31"
@ -345,6 +457,12 @@ version = "0.15.5"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "9229cfe53dfd69f0609a49f65461bd93001ea1ef889cd5529dd176593f5338a1"
[[package]]
name = "heck"
version = "0.5.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "2304e00983f87ffb38b55b444b5e3b60a884b5d30c0fca7d82fe33449bbe55ea"
[[package]]
name = "http"
version = "1.3.1"
@ -558,6 +676,12 @@ dependencies = [
"zerovec",
]
[[package]]
name = "ident_case"
version = "1.0.1"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "b9e0384b61958566e926dc50660321d12159025e767c18e043daf26b70104c39"
[[package]]
name = "idna"
version = "1.1.0"
@ -638,6 +762,16 @@ version = "0.2.175"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "6a82ae493e598baaea5209805c49bbf2ea7de956d50d7da0da1164f9c6d28543"
[[package]]
name = "libsqlite3-sys"
version = "0.35.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "133c182a6a2c87864fe97778797e46c7e999672690dc9fa3ee8e241aa4a9c13f"
dependencies = [
"pkg-config",
"vcpkg",
]
[[package]]
name = "linux-raw-sys"
version = "0.9.4"
@ -721,6 +855,12 @@ dependencies = [
"tempfile",
]
[[package]]
name = "num-conv"
version = "0.1.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "51d515d32fb182ee37cda2ccdcb92950d6a3c2893aa280e540671c2cd0f3b1d9"
[[package]]
name = "object"
version = "0.36.7"
@ -836,6 +976,12 @@ dependencies = [
"zerovec",
]
[[package]]
name = "powerfmt"
version = "0.2.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "439ee305def115ba05938db6eb1644ff94165c5ab5e9420d1c1bcedbba909391"
[[package]]
name = "proc-macro2"
version = "1.0.101"
@ -1116,12 +1262,36 @@ dependencies = [
"windows-sys 0.59.0",
]
[[package]]
name = "sqlite-wasm-rs"
version = "0.4.3"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "0894a1b91dc660fbf1e6ea6f287562708e01ca1a18fa4e2c6dae0df5a05199c5"
dependencies = [
"fragile",
"js-sys",
"once_cell",
"parking_lot",
"thiserror",
"tokio",
"wasm-array-cp",
"wasm-bindgen",
"wasm-bindgen-futures",
"web-sys",
]
[[package]]
name = "stable_deref_trait"
version = "1.2.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "a8f112729512f8e442d81f95a8a7ddf2b7c6b8a1a6f509a95864142b30cab2d3"
[[package]]
name = "strsim"
version = "0.11.1"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "7da8b5736845d9f2fcb837ea5d9e2628564b3b043a70948a3f0b778838c5fb4f"
[[package]]
name = "subtle"
version = "2.6.1"
@ -1193,6 +1363,57 @@ dependencies = [
"windows-sys 0.59.0",
]
[[package]]
name = "thiserror"
version = "2.0.16"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "3467d614147380f2e4e374161426ff399c91084acd2363eaf549172b3d5e60c0"
dependencies = [
"thiserror-impl",
]
[[package]]
name = "thiserror-impl"
version = "2.0.16"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "6c5e1be1c48b9172ee610da68fd9cd2770e7a4056cb3fc98710ee6906f0c7960"
dependencies = [
"proc-macro2",
"quote",
"syn",
]
[[package]]
name = "time"
version = "0.3.44"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "91e7d9e3bb61134e77bde20dd4825b97c010155709965fedf0f49bb138e52a9d"
dependencies = [
"deranged",
"itoa",
"num-conv",
"powerfmt",
"serde",
"time-core",
"time-macros",
]
[[package]]
name = "time-core"
version = "0.1.6"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "40868e7c1d2f0b8d73e4a8c7f0ff63af4f6d19be117e90bd73eb1d62cf831c6b"
[[package]]
name = "time-macros"
version = "0.2.24"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "30cfb0125f12d9c277f35663a0a33f8c30190f4e4574868a330595412d34ebf3"
dependencies = [
"num-conv",
"time-core",
]
[[package]]
name = "tinystr"
version = "0.8.1"
@ -1399,6 +1620,16 @@ dependencies = [
"wit-bindgen",
]
[[package]]
name = "wasm-array-cp"
version = "0.1.1"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "bb633b3e235f0ebe0a35162adc1e0293fc4b7e3f3a6fc7b5374d80464267ff84"
dependencies = [
"js-sys",
"wasm-bindgen",
]
[[package]]
name = "wasm-bindgen"
version = "0.2.100"

View file

@ -12,3 +12,4 @@ serde_json = "1.0.143"
tokio = { version = "1.47.1", features = ["full"] }
tower = "0.5.2"
tower-http = { version = "0.6.6", features = ["cors"]}
diesel = { version = "2.2.0", features = ["sqlite", "returning_clauses_for_sqlite_3_35"] }

9
diesel.toml Normal file
View file

@ -0,0 +1,9 @@
# For documentation on how to configure this file,
# see https://diesel.rs/guides/configuring-diesel-cli
[print_schema]
file = "src/schema.rs"
custom_type_derives = ["diesel::query_builder::QueryId", "Clone"]
[migrations_directory]
dir = "/home/alzalia/Documents/gits/academic-back/migrations"

0
migrations/.diesel_lock Normal file
View file

0
migrations/.keep Normal file
View file

View file

@ -0,0 +1,2 @@
-- This file should undo anything in `up.sql`
DROP TABLE comments

View file

@ -0,0 +1,6 @@
-- Your SQL goes here
CREATE TABLE comments (
id INTEGER NOT NULL PRIMARY KEY AUTOINCREMENT,
author TEXT NOT NULL,
content TEXT NOT NULL
);

65
src/comments.rs Normal file
View file

@ -0,0 +1,65 @@
use crate::models::{Comment, CreateCommentRequest, NewComment};
use axum::Json;
use diesel::prelude::*;
use reqwest::StatusCode;
/*
* =================
* ====< UTILS >====
* =================
*/
pub fn establish_connection() -> Result<SqliteConnection, diesel::result::ConnectionError> {
let db_url = dotenv::var("DATABASE_URL").map_err(|_| {
diesel::result::ConnectionError::BadConnection("DATABASE_URL not set".into())
})?;
SqliteConnection::establish(&db_url)
}
pub fn create_comment(
conn: &mut SqliteConnection,
author: &str,
content: &str,
) -> Result<Comment, diesel::result::Error> {
use crate::schema::comments;
let new_comment = NewComment { author, content };
diesel::insert_into(comments::table)
.values(&new_comment)
.returning(Comment::as_returning())
.get_result(conn)
}
pub fn fetch_comments(conn: &mut SqliteConnection) -> Result<Vec<Comment>, diesel::result::Error> {
use crate::schema::comments::dsl::*;
comments.load::<Comment>(conn)
}
/*
* ==================
* ====< ROUTES >====
* ==================
*/
pub async fn post_comment(
Json(payload): Json<CreateCommentRequest>,
) -> (StatusCode, Json<Option<Comment>>) {
if let Ok(mut conn) = establish_connection() {
let new_comment = create_comment(&mut conn, &payload.author, &payload.content).unwrap();
(StatusCode::OK, Json(Some(new_comment)))
} else {
(StatusCode::INTERNAL_SERVER_ERROR, Json(None))
}
}
pub async fn get_comments() -> (StatusCode, Json<Option<Vec<Comment>>>) {
if let Ok(mut conn) = establish_connection()
&& let Ok(comments) = fetch_comments(&mut conn)
{
(StatusCode::OK, Json(Some(comments)))
} else {
(StatusCode::INTERNAL_SERVER_ERROR, Json(None))
}
}

View file

@ -1,13 +1,19 @@
use axum::{
Router,
http::{Method, header},
routing::get,
routing::{get, post},
};
use tower_http::cors::CorsLayer;
use crate::json_routes::{get_home, get_lessons, get_lessons_by_id, get_projects};
use crate::{
comments::{get_comments, post_comment},
json_routes::{get_home, get_lessons, get_lessons_by_id, get_projects},
};
mod comments;
mod json_routes;
pub mod models;
pub mod schema;
#[tokio::main]
async fn main() {
@ -31,6 +37,8 @@ async fn main() {
.route("/{lang}/projects", get(get_projects))
.route("/{lang}/lessons", get(get_lessons))
.route("/{lang}/lessons/{id}", get(get_lessons_by_id))
.route("/comments", get(get_comments))
.route("/comment/create", post(post_comment))
.layer(cors);
// run our app on port 6543

25
src/models.rs Normal file
View file

@ -0,0 +1,25 @@
use crate::schema::comments;
use diesel::prelude::*;
use serde::{Deserialize, Serialize};
#[derive(Queryable, Selectable, Serialize)]
#[diesel(table_name = comments)]
#[diesel(check_for_backend(diesel::sqlite::Sqlite))]
pub struct Comment {
pub id: i32,
pub author: String,
pub content: String,
}
#[derive(Insertable, Serialize, Deserialize)]
#[diesel(table_name = comments)]
pub struct NewComment<'a> {
pub author: &'a str,
pub content: &'a str,
}
#[derive(Deserialize)]
pub struct CreateCommentRequest {
pub author: String,
pub content: String,
}

9
src/schema.rs Normal file
View file

@ -0,0 +1,9 @@
// @generated automatically by Diesel CLI.
diesel::table! {
comments (id) {
id -> Integer,
author -> Text,
content -> Text,
}
}