Wrote part of posts db boilerplate

develop
Jef Roosens 2021-09-26 18:36:15 +02:00
parent 0da8eb127c
commit f6e9039b59
Signed by: Jef Roosens
GPG Key ID: B580B976584B5F30
2 changed files with 51 additions and 29 deletions

View File

@ -1,5 +1,6 @@
use chrono::NaiveDate; use chrono::NaiveDate;
use diesel::{insert_into, prelude::*, Insertable, PgConnection, Queryable}; use diesel::{insert_into, prelude::*, Insertable, PgConnection, Queryable};
use serde::Deserialize;
use uuid::Uuid; use uuid::Uuid;
use crate::{ use crate::{
@ -24,19 +25,27 @@ pub struct NewPost
pub section_id: Uuid, pub section_id: Uuid,
pub title: Option<String>, pub title: Option<String>,
pub publish_date: NaiveDate, pub publish_date: NaiveDate,
pub content: String,
} }
/// Returns all posts in the database; should be used with care as this method could quickly return #[derive(Deserialize, AsChangeset)]
/// a large amount of data. #[table_name = "posts"]
/// pub struct PatchPost
/// # Arguments
///
/// * `conn` - a reference to a database connection
pub fn all(conn: &PgConnection) -> RbResult<Vec<Post>>
{ {
posts pub id: Option<Uuid>,
pub section_id: Option<Uuid>,
pub title: Option<String>,
pub publish_date: Option<NaiveDate>,
pub content: Option<String>,
}
pub fn get(conn: &PgConnection, offset_: u32, limit_: u32) -> RbResult<Vec<Post>>
{
Ok(posts
.offset(offset_.into())
.limit(limit_.into())
.load::<Post>(conn) .load::<Post>(conn)
.map_err(|_| RbError::DbError("Couldn't get all posts.")) .map_err(|_| RbError::DbError("Couldn't query posts."))?)
} }
/// Insert a new post into the database. /// Insert a new post into the database.
@ -45,14 +54,29 @@ pub fn all(conn: &PgConnection) -> RbResult<Vec<Post>>
/// ///
/// * `conn` - reference to a database connection /// * `conn` - reference to a database connection
/// * `new_post` - the new post object to insert /// * `new_post` - the new post object to insert
pub fn create(conn: &PgConnection, new_post: &NewPost) -> RbResult<()> pub fn create(conn: &PgConnection, new_post: &NewPost) -> RbResult<Post>
{ {
insert_into(posts) Ok(insert_into(posts)
.values(new_post) .values(new_post)
.execute(conn) .get_result::<Post>(conn)
.map_err(|_| RbError::DbError("Couldn't insert post."))?; .map_err(|_| RbError::DbError("Couldn't insert post."))?)
// TODO check for conflict? // TODO check for conflict?
}
pub fn update(conn: &PgConnection, post: &PatchPost) -> RbResult<Post>
{
Ok(diesel::update(posts)
.set(post)
.get_result::<Post>(conn)
.map_err(|_| RbError::DbError("Couldn't update post."))?)
}
pub fn delete(conn: &PgConnection, post_id: Uuid) -> RbResult<()>
{
diesel::delete(posts.filter(id.eq(post_id)))
.execute(conn)
.map_err(|_| RbError::DbError("Couldn't delete post."))?;
Ok(()) Ok(())
} }

View File

@ -26,15 +26,14 @@ impl<'r> FromRequest<'r> for Bearer<'r>
Some(val) => val, Some(val) => val,
}; };
if !header.starts_with("Bearer ") { if header.starts_with("Bearer ") {
return Outcome::Forward(());
}
// Extract the jwt token from the header
match header.get(7..) { match header.get(7..) {
Some(s) => Outcome::Success(Self(s)), Some(s) => Outcome::Success(Self(s)),
None => Outcome::Failure((Status::Unauthorized, Self::Error::AuthUnauthorized)), None => Outcome::Failure((Status::Unauthorized, Self::Error::AuthUnauthorized)),
} }
} else {
Outcome::Forward(())
}
} }
} }
@ -63,15 +62,14 @@ impl<'r> FromRequest<'r> for Jwt
)) ))
}, },
}; };
// Verify token using key // Verify token using key
let claims: Claims = match bearer.verify_with_key(&key) { match bearer.verify_with_key(&key) {
Ok(claims) => claims, Ok(claims) => Outcome::Success(Self(claims)),
Err(_) => { Err(_) => {
return Outcome::Failure((Status::Unauthorized, Self::Error::AuthUnauthorized)) return Outcome::Failure((Status::Unauthorized, Self::Error::AuthUnauthorized))
}, },
}; }
Outcome::Success(Self(claims))
} }
} }
@ -89,12 +87,12 @@ impl<'r> FromRequest<'r> for User
// Verify key hasn't yet expired // Verify key hasn't yet expired
if chrono::Utc::now().timestamp() > claims.exp { if chrono::Utc::now().timestamp() > claims.exp {
return Outcome::Failure((Status::Forbidden, Self::Error::AuthTokenExpired)); Outcome::Failure((Status::Forbidden, Self::Error::AuthTokenExpired))
} } else {
Outcome::Success(Self(claims)) Outcome::Success(Self(claims))
} }
} }
}
/// Verifies the JWT belongs to an admin. /// Verifies the JWT belongs to an admin.
pub struct Admin(Claims); pub struct Admin(Claims);