Wrote part of posts db boilerplate
parent
0da8eb127c
commit
f6e9039b59
|
@ -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(())
|
||||||
}
|
}
|
||||||
|
|
|
@ -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);
|
||||||
|
|
Reference in New Issue