From 6c988d2f42e8040b522a06db491b48c09573011b Mon Sep 17 00:00:00 2001 From: Dhruv Date: Wed, 31 Jan 2024 21:55:40 +0530 Subject: [PATCH] feat: added update delete routes --- src/api/page_api.rs | 53 ++++++++++++++-- src/api/user_api.rs | 2 +- src/config/jwt.rs | 2 +- src/main.rs | 7 +- src/models/mod.rs | 2 +- src/models/page_model.rs | 27 +++++++- src/repository/error.rs | 2 +- src/repository/mod.rs | 2 +- src/repository/mongodb_repo.rs | 113 +++++++++++++++++++++++++++++---- 9 files changed, 181 insertions(+), 29 deletions(-) diff --git a/src/api/page_api.rs b/src/api/page_api.rs index a419a11..0756d13 100644 --- a/src/api/page_api.rs +++ b/src/api/page_api.rs @@ -1,19 +1,26 @@ -use rocket::{get, http::Status, post, serde::json::Json, State}; +use mongodb::results::DeleteResult; +use rocket::{delete, get, http::Status, post, put, serde::json::Json, State}; use rocket_authorization::oauth::OAuth; use rocket_authorization::Credential; use crate::{ - models::page_model::{PageCreateRequest, PageCreateResponse, Page}, + models::page_model::{ + Page, PageCreateRequest, PageCreateResponse, PageUpdateRequest, PageUpdateResponse, + }, repository::mongodb_repo::MongoRepo, }; -#[post("/create-page", data="")] -pub fn create_page(auth: Credential, db: &State, new_page: Json) -> Result, Status> { - // get user from jwt token +#[post("/create-page", data = "")] +pub fn create_page( + auth: Credential, + db: &State, + new_page: Json, +) -> Result, Status> { + // get user from jwt token let token = &auth.token; println!("{:?}", token); - let new_page = PageCreateRequest { + let new_page = PageCreateRequest { title: new_page.title.clone(), content: new_page.content.clone(), slug: new_page.slug.clone(), @@ -33,3 +40,37 @@ pub fn get_page(db: &State, slug: &str, username: &str) -> Result", data = "")] +pub fn update_page( + auth: Credential, + db: &State, + id: &str, + new_page: Json, +) -> Result, Status> { + // get user from jwt token + let token = &auth.token; + + let new_page = PageUpdateRequest { + title: new_page.title.clone(), + content: new_page.content.clone(), + slug: new_page.slug.clone(), + published: new_page.published.clone(), + }; + + let page: Page = db.update_page(id, new_page, token).unwrap(); + Ok(Json(page)) +} + +#[delete("/delete-page/")] +pub fn delete_page( + auth: Credential, + db: &State, + id: &str, +) -> Result, Status> { + // get user from jwt token + let token = &auth.token; + + let page: DeleteResult = db.delete_page(id, token).unwrap(); + Ok(Json(page)) +} diff --git a/src/api/user_api.rs b/src/api/user_api.rs index a4d8a29..beba7b7 100644 --- a/src/api/user_api.rs +++ b/src/api/user_api.rs @@ -4,7 +4,7 @@ use rocket::{get, http::Status, post, serde::json::Json, State}; use crate::{ config::jwt::create_jwt, models::user_model::{LoginResponse, LoginUser, User, UserFromMongo}, - repository::{mongodb_repo::MongoRepo, error::UserError}, + repository::{error::UserError, mongodb_repo::MongoRepo}, }; #[post("/user", data = "")] diff --git a/src/config/jwt.rs b/src/config/jwt.rs index d3eb5bd..cc26fd7 100644 --- a/src/config/jwt.rs +++ b/src/config/jwt.rs @@ -1,5 +1,5 @@ use chrono::{Duration, Utc}; -use jsonwebtoken::{encode, decode,errors::Error, Algorithm, EncodingKey, Header, DecodingKey}; +use jsonwebtoken::{decode, encode, errors::Error, Algorithm, DecodingKey, EncodingKey, Header}; use super::auth::{Claims, SECRET}; diff --git a/src/main.rs b/src/main.rs index 13a5257..4e82dc5 100644 --- a/src/main.rs +++ b/src/main.rs @@ -2,7 +2,10 @@ pub mod api; pub mod config; pub mod models; pub mod repository; -use api::{user_api::{create_user, get_user, login}, page_api::{create_page, get_page}}; +use api::{ + page_api::{create_page, get_page, update_page, delete_page}, + user_api::{create_user, get_user, login}, +}; use repository::mongodb_repo::MongoRepo; use rocket::{get, http::Status, routes, serde::json::Json, Rocket}; @@ -17,6 +20,6 @@ async fn main() -> shuttle_rocket::ShuttleRocket { let rocket: Rocket = rocket::build() .manage(db) .mount("/", routes![index, create_user, get_user, login]) - .mount("/pages", routes![create_page, get_page]); + .mount("/pages", routes![create_page, get_page, update_page, delete_page]); Ok(rocket.into()) } diff --git a/src/models/mod.rs b/src/models/mod.rs index 5d41c5e..2603d56 100644 --- a/src/models/mod.rs +++ b/src/models/mod.rs @@ -1,2 +1,2 @@ -pub mod user_model; pub mod page_model; +pub mod user_model; diff --git a/src/models/page_model.rs b/src/models/page_model.rs index 407e970..920552d 100644 --- a/src/models/page_model.rs +++ b/src/models/page_model.rs @@ -8,7 +8,7 @@ pub struct Page { pub content: String, pub slug: String, pub published: bool, - pub user_id: ObjectId + pub user_id: ObjectId, } #[derive(Serialize, Deserialize, Debug)] @@ -25,12 +25,35 @@ pub struct PageCreateResponse { pub content: String, pub slug: String, pub published: bool, - pub user_id: ObjectId + pub user_id: ObjectId, } +#[derive(Serialize, Deserialize, Debug)] pub struct PageGetResponse { pub title: String, pub content: String, pub slug: String, pub published: bool, } + +#[derive(Serialize, Deserialize, Debug)] +pub struct PageUpdateRequest { + pub title: String, + pub content: String, + pub slug: String, + pub published: bool, +} + +#[derive(Serialize, Deserialize, Debug)] +pub struct PageUpdateResponse { + pub title: String, + pub content: String, + pub slug: String, + pub published: bool, +} + +#[derive(Deserialize)] +pub struct DeletePage { + pub _id: ObjectId, + pub user_id: ObjectId, +} diff --git a/src/repository/error.rs b/src/repository/error.rs index 9f2d53a..3908c5a 100644 --- a/src/repository/error.rs +++ b/src/repository/error.rs @@ -11,5 +11,5 @@ pub enum UserError { pub enum PageError { NotFound, AlreadyExists, - InternalError + InternalError, } diff --git a/src/repository/mod.rs b/src/repository/mod.rs index e7637cb..7f0645f 100644 --- a/src/repository/mod.rs +++ b/src/repository/mod.rs @@ -1,2 +1,2 @@ -pub mod mongodb_repo; pub mod error; +pub mod mongodb_repo; diff --git a/src/repository/mongodb_repo.rs b/src/repository/mongodb_repo.rs index bb321f9..ff175b3 100644 --- a/src/repository/mongodb_repo.rs +++ b/src/repository/mongodb_repo.rs @@ -1,10 +1,11 @@ use crate::config::auth::{hash_password, verify_password}; -use darkdown::converter::converter::Converter; use crate::config::jwt::decode_jwt; -use crate::models::page_model::{Page, PageCreateRequest, PageCreateResponse}; +use crate::models::page_model::{Page, PageCreateRequest, PageCreateResponse, PageUpdateRequest}; use crate::models::user_model::{User, UserFromMongo}; +use darkdown::converter::converter::Converter; use dotenv::dotenv; use mongodb::bson::extjson::de::Error; +use mongodb::results::DeleteResult; use mongodb::{ bson::{doc, oid::ObjectId}, results::InsertOneResult, @@ -13,7 +14,7 @@ use mongodb::{ use std::env; use std::str::FromStr; -use super::error::{UserError, PageError}; +use super::error::{PageError, UserError}; pub struct MongoRepo { col: Collection, @@ -70,7 +71,6 @@ impl MongoRepo { .ok() .expect("Error Finding User"); - if user_detail.is_some() { let user: UserFromMongo = user_detail.unwrap(); let is_valid = verify_password(password, user.password.as_str()); @@ -81,34 +81,35 @@ impl MongoRepo { } else { return Err(UserError::NotFound); } - - } // Page CRUD - pub fn create_page(&self, new_page: PageCreateRequest, token: &String) -> Result { + pub fn create_page( + &self, + new_page: PageCreateRequest, + token: &String, + ) -> Result { // get user id from jwt token let user_id = decode_jwt(token.as_str()).unwrap().sub; // let user_obj: ObjectId = ; let user_id = ObjectId::from_str(user_id.as_str()).unwrap(); - // create page + // create page // convert content from darkdown to html let darkdown_content = new_page.content.clone(); - let html_content:String = Converter::new().convert_to_html(darkdown_content.as_str()); + let html_content: String = Converter::new().convert_to_html(darkdown_content.as_str()); let page = Page { _id: ObjectId::new(), title: new_page.title.clone(), - content: html_content.clone(), + content: html_content.clone(), published: new_page.published.clone(), slug: new_page.slug.clone(), - user_id: user_id.clone() + user_id: user_id.clone(), }; - self - .page + self.page .insert_one(page, None) .ok() .expect("Error Creating Page"); @@ -140,10 +141,94 @@ impl MongoRepo { .find_one(filter, None) .ok() .expect("Error Finding Page"); - return Ok(page.unwrap()); + + if page.is_some() { + let page: Page = page.unwrap(); + return Ok(page); + } else { + return Err(PageError::NotFound); + } } else { return Err(PageError::NotFound); } } + pub fn update_page( + &self, + id: &str, + new_page: PageUpdateRequest, + token: &String, + ) -> Result { + #[warn(unused_variables)] + let user_id = decode_jwt(token.as_str()).unwrap().sub; + + let id = ObjectId::from_str(id).unwrap(); + let filter = doc! {"_id": id}; + let update = doc! {"$set": {"title": new_page.title, "content": new_page.content, "published": new_page.published, "slug": new_page.slug}}; + let page = self + .page + .find_one_and_update(filter, update, None) + .ok() + .expect("Error Updating Page"); + return Ok(page.unwrap()); + } + + pub async fn get_pages(&self, username: &str) -> Result, PageError> { + let filer = doc! { "username": username }; + let user = self + .col + .find_one(filer, None) + .ok() + .expect("Error Finding User"); + + if user.is_some() { + let user: UserFromMongo = user.unwrap(); + let user_id = user._id; + let filter = doc! {"user_id": user_id}; + let pages = self + .page + .find(filter, None) + .ok() + .expect("Error Finding Pages"); + + let serial: Vec> = pages.collect::>(); + let mut results: Vec = Vec::new(); + for page in serial { + results.push(page.unwrap()); + } + + return Ok(results); + } else { + return Err(PageError::NotFound); + } + } + pub fn delete_page(&self, id: &str, token: &String) -> Result { + let user_id = decode_jwt(token.as_str()).unwrap().sub; + let user_id = ObjectId::from_str(user_id.as_str()).unwrap(); + + let id = ObjectId::from_str(id).unwrap(); + let filter = doc! {"_id": id}; + + // get page and see if user_id matches + let page = self + .page + .find_one(filter.clone(), None) + .ok() + .expect("Error Finding Page"); + if page.is_none() { + return Err(PageError::NotFound); + } else { + let page: Page = page.unwrap(); + if page.user_id != user_id { + return Err(PageError::InternalError); + } + } + + let page = self + .page + .delete_one(filter, None) + .ok() + .expect("Error Deleting Page"); + Ok(page) + } }