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 diesel::{insert_into, prelude::*, Insertable, PgConnection, Queryable};
use serde::Deserialize;
use uuid::Uuid;
use crate::{
@ -24,19 +25,27 @@ pub struct NewPost
pub section_id: Uuid,
pub title: Option<String>,
pub publish_date: NaiveDate,
pub content: String,
}
/// Returns all posts in the database; should be used with care as this method could quickly return
/// a large amount of data.
///
/// # Arguments
///
/// * `conn` - a reference to a database connection
pub fn all(conn: &PgConnection) -> RbResult<Vec<Post>>
#[derive(Deserialize, AsChangeset)]
#[table_name = "posts"]
pub struct PatchPost
{
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)
.map_err(|_| RbError::DbError("Couldn't get all posts."))
.map_err(|_| RbError::DbError("Couldn't query posts."))?)
}
/// 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
/// * `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)
.execute(conn)
.map_err(|_| RbError::DbError("Couldn't insert post."))?;
.get_result::<Post>(conn)
.map_err(|_| RbError::DbError("Couldn't insert post."))?)
// 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(())
}

View File

@ -26,15 +26,14 @@ impl<'r> FromRequest<'r> for Bearer<'r>
Some(val) => val,
};
if !header.starts_with("Bearer ") {
return Outcome::Forward(());
}
// Extract the jwt token from the header
if header.starts_with("Bearer ") {
match header.get(7..) {
Some(s) => Outcome::Success(Self(s)),
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
let claims: Claims = match bearer.verify_with_key(&key) {
Ok(claims) => claims,
match bearer.verify_with_key(&key) {
Ok(claims) => Outcome::Success(Self(claims)),
Err(_) => {
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
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))
}
}
}
/// Verifies the JWT belongs to an admin.
pub struct Admin(Claims);