From 4fc00eaf23596fed6fcfb6df2836a88ad904a206 Mon Sep 17 00:00:00 2001 From: Imbus Date: Sat, 21 Oct 2023 01:55:27 +0200 Subject: [PATCH] Tidying up routes, query parameters for posts, better database api --- server/src/db.rs | 17 +++++++++++------ server/src/jwt.rs | 4 ---- server/src/routes/post.rs | 30 +++++++++++++++++++++++++----- server/src/routes/users.rs | 4 ---- server/src/state.rs | 4 +++- 5 files changed, 39 insertions(+), 20 deletions(-) diff --git a/server/src/db.rs b/server/src/db.rs index 65b74f4..710fb97 100644 --- a/server/src/db.rs +++ b/server/src/db.rs @@ -2,12 +2,17 @@ use crate::routes::{NewPost, Post}; use log::warn; use sqlx::SqlitePool; -// Gets all posts from the database -pub async fn db_get_posts(pool: &SqlitePool) -> Vec { - sqlx::query_as!(Post, "SELECT * FROM posts") - .fetch_all(pool) - .await - .unwrap() +// Gets the latest posts from the database, ordered by created_at +pub async fn db_get_latest_posts(pool: &SqlitePool, limit: i64, offset: i64) -> Vec { + sqlx::query_as!( + Post, + "SELECT * FROM posts ORDER BY created_at DESC LIMIT ? OFFSET ?", + limit, + offset + ) + .fetch_all(pool) + .await + .unwrap() } // Inserts a new post to the database diff --git a/server/src/jwt.rs b/server/src/jwt.rs index 2e4bc44..5989cf9 100755 --- a/server/src/jwt.rs +++ b/server/src/jwt.rs @@ -1,7 +1,3 @@ -// use crate::{ -// config::{DAYS_VALID, JWT_SECRET}, -// Claims, -// }; use jsonwebtoken::{ decode, encode, errors::Result as JwtResult, DecodingKey, EncodingKey, Header, Validation, }; diff --git a/server/src/routes/post.rs b/server/src/routes/post.rs index 0555e47..2b71ca1 100755 --- a/server/src/routes/post.rs +++ b/server/src/routes/post.rs @@ -1,7 +1,7 @@ -use crate::db::{db_get_posts, db_new_post}; +use crate::db::{db_get_latest_posts, db_new_post}; use crate::ServerState; -use actix_web::web::Data; +use actix_web::web::{Data, Query}; use actix_web::{get, post, web::Json, HttpResponse, Responder, Result}; use log::info; use serde::{Deserialize, Serialize}; @@ -27,6 +27,7 @@ pub struct Post { pub updated_at: chrono::NaiveDateTime, } +/// The user as it is stored in the database, with all the related metadata #[derive(Debug, Serialize, Deserialize, Clone, FromRow)] pub struct User { pub id: i64, @@ -36,11 +37,30 @@ pub struct User { pub updated_at: chrono::NaiveDateTime, } -#[get("/posts")] -pub async fn get_posts(state: Data) -> Result { - Ok(HttpResponse::Ok().json(db_get_posts(&state.pool).await)) +// These look like /posts?limit=10&offset=20 in the URL +// Note that these are optional +/// Query parameters for the /posts endpoint +#[derive(Debug, Serialize, Deserialize)] +struct QueryParams { + limit: Option, + offset: Option, } +/// Gets all posts from the database, query parameters are optional +/// If limit is not specified, it defaults to a sane value +#[get("/posts")] +pub async fn get_posts( + query: Query, + state: Data, +) -> Result { + if let (Some(lim), Some(ofs)) = (query.limit, query.offset) { + return Ok(HttpResponse::Ok() + .json(db_get_latest_posts(&state.pool, std::cmp::min(lim, 30), ofs).await)); + } + Ok(HttpResponse::Ok().json(db_get_latest_posts(&state.pool, 30, 0).await)) +} + +/// Creates a new post, requires a token in release mode #[post("/posts")] pub async fn new_post(new_post: Json, state: Data) -> Result { return match db_new_post(new_post.into_inner(), &state.pool).await { diff --git a/server/src/routes/users.rs b/server/src/routes/users.rs index e5cdec8..62f504b 100755 --- a/server/src/routes/users.rs +++ b/server/src/routes/users.rs @@ -74,10 +74,6 @@ pub async fn register( #[post("/login")] pub async fn login(data: Json, state: Data) -> Result { - // let q = "SELECT password FROM users WHERE username = ?"; - // let query = sqlx::query(q).bind(&data.username); - // let result = query.fetch_one(&state.pool).await.ok(); - let uname = data.username.clone(); let q = sqlx::query!("SELECT password FROM users WHERE username = ?", uname) .fetch_one(&state.pool) diff --git a/server/src/state.rs b/server/src/state.rs index fbda6c8..f43f91b 100644 --- a/server/src/state.rs +++ b/server/src/state.rs @@ -35,10 +35,12 @@ impl ServerState { async fn debug_setup(pool: &SqlitePool) -> Result<(), sqlx::Error> { use sqlx::query; - query!("INSERT INTO users (username, password) VALUES ('testuser', 'testpassword')",) + // Or ignore is just to silence the error if the user already exists + query!("INSERT OR IGNORE INTO users (username, password) VALUES ('testuser', 'testpassword')",) .execute(pool) .await?; + // This requires that the user with id 1 exists in the user table query!("INSERT INTO posts (user_id, content) VALUES (1, 'Hello world!')",) .execute(pool) .await?;