Compare commits

...

6 commits

8 changed files with 101 additions and 23 deletions

2
.gitignore vendored
View file

@ -25,3 +25,5 @@ dist-ssr
*.env *.env
*.db* *.db*
*backup*

View file

@ -1,7 +1,7 @@
CREATE TABLE IF NOT EXISTS comments ( CREATE TABLE IF NOT EXISTS comments (
id BIGSERIAL PRIMARY KEY, id SERIAL PRIMARY KEY NOT NULL,
parent_post_id BIGINT NOT NULL, parent_post_id BIGINT NOT NULL,
parent_comment_id BIGINT, -- parent_comment_id BIGINT,
author_user_id BIGINT NOT NULL, author_user_id BIGINT NOT NULL,
content TEXT NOT NULL, content TEXT NOT NULL,
upvotes INTEGER NOT NULL DEFAULT 0, upvotes INTEGER NOT NULL DEFAULT 0,
@ -9,7 +9,7 @@ CREATE TABLE IF NOT EXISTS comments (
created_at TIMESTAMP NOT NULL DEFAULT CURRENT_TIMESTAMP, created_at TIMESTAMP NOT NULL DEFAULT CURRENT_TIMESTAMP,
updated_at TIMESTAMP NOT NULL DEFAULT CURRENT_TIMESTAMP, updated_at TIMESTAMP NOT NULL DEFAULT CURRENT_TIMESTAMP,
FOREIGN KEY (parent_post_id) REFERENCES posts (id), FOREIGN KEY (parent_post_id) REFERENCES posts (id),
FOREIGN KEY (parent_comment_id) REFERENCES comments (id), -- FOREIGN KEY (parent_comment_id) REFERENCES comments (id),
FOREIGN KEY (author_user_id) REFERENCES users (id) FOREIGN KEY (author_user_id) REFERENCES users (id)
); );
@ -43,5 +43,5 @@ FOR EACH ROW
EXECUTE FUNCTION comments_set_updated_at(); EXECUTE FUNCTION comments_set_updated_at();
CREATE INDEX comments_parent_post_id_index ON comments (parent_post_id); CREATE INDEX comments_parent_post_id_index ON comments (parent_post_id);
CREATE INDEX comments_parent_comment_id_index ON comments (parent_comment_id); -- CREATE INDEX comments_parent_comment_id_index ON comments (parent_comment_id);
CREATE INDEX comments_user_id_index ON comments (author_user_id); CREATE INDEX comments_user_id_index ON comments (author_user_id);

View file

@ -0,0 +1,62 @@
-- Description: This file creates the procedures and functions for adding users, posts, and comments.
-- Functions are commonly used for SELECT queries, while procedures are used for INSERT, UPDATE, and DELETE queries.
-- None of these seem to play very nice with sqlx for now, but they will surely be useful in the future.
-- Procedure for adding a user
CREATE OR REPLACE PROCEDURE add_user(
IN username_param TEXT,
IN password_param TEXT
)
LANGUAGE plpgsql
AS $$
BEGIN
INSERT INTO users (username, password)
VALUES (username_param, password_param);
END;
$$;
-- Procedure for adding a post
CREATE OR REPLACE PROCEDURE add_post(
IN user_id_param BIGINT,
IN content_param TEXT
)
LANGUAGE plpgsql
AS $$
BEGIN
INSERT INTO posts (user_id, content)
VALUES (user_id_param, content_param);
END;
$$;
-- Procedure for adding a comment
CREATE OR REPLACE PROCEDURE add_comment(
IN parent_post_id_param BIGINT,
-- IN parent_comment_id_param BIGINT,
IN author_user_id_param BIGINT,
IN content_param TEXT
)
LANGUAGE plpgsql
AS $$
BEGIN
INSERT INTO comments (parent_post_id, author_user_id, content)
VALUES (parent_post_id_param, author_user_id_param, content_param);
END;
$$;
-- Function for getting comments
CREATE OR REPLACE FUNCTION get_comments(
IN parent_post_id_param BIGINT,
IN limit_param BIGINT,
IN offset_param BIGINT
)
RETURNS SETOF comments AS $$
BEGIN
RETURN QUERY
SELECT *
FROM comments
WHERE parent_post_id = parent_post_id_param
ORDER BY created_at DESC
LIMIT limit_param
OFFSET offset_param;
END;
$$ LANGUAGE plpgsql;

View file

@ -9,14 +9,13 @@ use sqlx::PgPool;
pub async fn db_new_comment( pub async fn db_new_comment(
pool: &PgPool, pool: &PgPool,
parent_post_id: i64, parent_post_id: i64,
parent_comment_id: Option<i64>, // parent_comment_id: Option<i64>,
user_id: i64, user_id: i64,
content: &str, content: &str,
) -> bool { ) -> bool {
let insert_query = sqlx::query!( let insert_query = sqlx::query!(
"INSERT INTO comments (parent_post_id, parent_comment_id, author_user_id, content) VALUES ($1, $2, $3, $4)", "INSERT INTO comments (parent_post_id, author_user_id, content) VALUES ($1, $2, $3)",
parent_post_id, parent_post_id,
parent_comment_id,
user_id, user_id,
content content
) )
@ -40,7 +39,8 @@ pub async fn db_get_comments(
) -> Vec<PublicComment> { ) -> Vec<PublicComment> {
sqlx::query_as!( sqlx::query_as!(
PublicComment, PublicComment,
"SELECT id, parent_post_id, parent_comment_id, upvotes, downvotes, content, created_at, updated_at FROM comments WHERE parent_post_id = $1 ORDER BY created_at DESC LIMIT $2 OFFSET $3", "SELECT id, parent_post_id, upvotes, downvotes, content, created_at, updated_at
FROM comments WHERE parent_post_id = $1 ORDER BY created_at DESC LIMIT $2 OFFSET $3",
parent_post_id, parent_post_id,
limit, limit,
offset offset

View file

@ -20,7 +20,11 @@ use util::hex_string;
#[actix_web::main] #[actix_web::main]
async fn main() -> std::io::Result<()> { async fn main() -> std::io::Result<()> {
env_logger::Builder::from_env(env_logger::Env::default().default_filter_or("debug")).init(); let mut builder = env_logger::Builder::new();
builder
.filter(None, log::LevelFilter::Debug)
.filter_module("sqlx", log::LevelFilter::Warn)
.init();
let data = ServerState::new().await; let data = ServerState::new().await;
let capt_db = CaptchaState::new(); let capt_db = CaptchaState::new();
@ -49,7 +53,7 @@ async fn main() -> std::io::Result<()> {
App::new() App::new()
.wrap(cors) .wrap(cors)
.wrap(middleware::Compress::default()) .wrap(middleware::Compress::default())
.wrap(middleware::Logger::default()) .wrap(middleware::Logger::new("%s %r"))
.wrap(middleware::NormalizePath::trim()) .wrap(middleware::NormalizePath::trim())
.service( .service(
scope("/api") scope("/api")

View file

@ -24,6 +24,11 @@ pub async fn get_comments(
let comments = db_get_comments(&state.pool, post_id, limit, offset).await; let comments = db_get_comments(&state.pool, post_id, limit, offset).await;
if comments.is_empty() {
info!("No comments found for post {}", post_id);
return Ok(HttpResponse::NotFound().json("No comments found"));
}
Ok(HttpResponse::Ok().json(comments)) Ok(HttpResponse::Ok().json(comments))
} }
@ -60,14 +65,7 @@ pub async fn new_comment(
info!("Creating a new comment {:?}", &data); info!("Creating a new comment {:?}", &data);
let success = db_new_comment( let success = db_new_comment(&state.pool, data.parent_post_id, userid, &content).await;
&state.pool,
data.parent_post_id,
data.parent_comment_id,
userid,
&content,
)
.await;
match success { match success {
true => { true => {

View file

@ -105,6 +105,19 @@ async fn lipsum_setup(pool: &PgPool) -> Result<(), sqlx::Error> {
.execute(pool) .execute(pool)
.await?; .await?;
} }
// Insert a bunch of comments
for i in 1..101 {
for _ in 0..rng.gen_range(3..30) {
query!(
"INSERT INTO comments (author_user_id, parent_post_id, content) VALUES (1, $1, $2)",
i,
lipsum(rng.gen_range(10..100))
)
.execute(pool)
.await?;
}
}
} }
Ok(()) Ok(())

View file

@ -16,8 +16,8 @@ pub struct Comment {
pub parent_post_id: i64, pub parent_post_id: i64,
pub parent_comment_id: Option<i64>, pub parent_comment_id: Option<i64>,
pub author_user_id: i64, pub author_user_id: i64,
pub upvotes: i64, pub upvotes: i32,
pub downvotes: i64, pub downvotes: i32,
pub content: String, pub content: String,
pub created_at: chrono::NaiveDateTime, pub created_at: chrono::NaiveDateTime,
pub updated_at: chrono::NaiveDateTime, pub updated_at: chrono::NaiveDateTime,
@ -28,9 +28,8 @@ pub struct Comment {
pub struct PublicComment { pub struct PublicComment {
pub id: i64, pub id: i64,
pub parent_post_id: i64, pub parent_post_id: i64,
pub parent_comment_id: Option<i64>, pub upvotes: i32,
pub upvotes: i64, pub downvotes: i32,
pub downvotes: i64,
pub content: String, pub content: String,
pub created_at: chrono::NaiveDateTime, pub created_at: chrono::NaiveDateTime,
pub updated_at: chrono::NaiveDateTime, pub updated_at: chrono::NaiveDateTime,