From b661b7ea8d664025ba31789a870401ca1ca8ed67 Mon Sep 17 00:00:00 2001 From: ATechnoHazard Date: Sat, 26 Sep 2020 17:37:32 +0530 Subject: [PATCH] pastes: add a route to update pastes Signed-off-by: ATechnoHazard --- src/api/catchers/mod.rs | 11 ++++++++ src/api/routes/paste.rs | 58 ++++++++++++++++++++++++++++++++------ src/core/paste/postgres.rs | 7 +++++ src/core/paste/service.rs | 6 ++++ 4 files changed, 73 insertions(+), 9 deletions(-) diff --git a/src/api/catchers/mod.rs b/src/api/catchers/mod.rs index f5457e8..22e8fe5 100644 --- a/src/api/catchers/mod.rs +++ b/src/api/catchers/mod.rs @@ -38,6 +38,17 @@ pub fn unprocessable_entity() -> status::Custom> { ) } +#[catch(403)] +pub fn forbidden() -> status::Custom> { + status::Custom( + Status::Forbidden, + Json(json!({ + "err":"forbidden", + "msg": "You are not allowed to modify this resource" + })), + ) +} + #[catch(500)] pub fn internal_server_error() -> status::Custom> { status::Custom( diff --git a/src/api/routes/paste.rs b/src/api/routes/paste.rs index 725235a..5276ce4 100644 --- a/src/api/routes/paste.rs +++ b/src/api/routes/paste.rs @@ -1,18 +1,14 @@ use std::ops::DerefMut; use diesel::result::Error; -use rocket::{ - http::{Cookies, Status}, - response::status, - Rocket, -}; +use rocket::{http::{Cookies, Status}, response::status, Rocket}; use rocket::response::status::Custom; use rocket_contrib::json::Json; use serde_json::Value; -use crate::api::catchers::{internal_server_error, not_found}; +use crate::api::catchers::{forbidden, internal_server_error, not_found, unprocessable_entity}; use crate::api::guards::db::DbConn; -use crate::core::paste::{entity::Paste, service::create_paste, service::fetch_paste}; +use crate::core::paste::{entity::Paste, service::{create_paste, fetch_paste, update_paste};}; use crate::core::users::service::{create_or_fetch_user, fetch_user}; use crate::utils::phonetic_key; use crate::utils::users::get_session_id; @@ -89,6 +85,50 @@ fn fetch(id: String, conn: DbConn, mut ck: Cookies) -> Custom> { }; } -pub fn fuel(rocket: Rocket) -> Rocket { - rocket.mount("/api/paste", routes![create, fetch]) +#[patch("/", data = "")] +fn update(mut paste: Json, conn: DbConn, mut ck: Cookies) -> Custom> { + // Check if frontend sent a session cookie + let user_id = get_session_id(&mut ck); + + // Create or fetch already existing user + let user = match fetch_user(user_id, &conn) { + Ok(user) => user, + Err(_) => { + return not_found(); + } + }; + + let new_paste = paste.deref_mut(); + + if new_paste.id.is_none() { + return not_found(); + } + + new_paste.belongs_to = match fetch_paste(new_paste.id.as_ref().unwrap().clone(), &conn) { + Ok(paste) => paste.belongs_to, + Err(_) => return internal_server_error() + }; + + if new_paste.belongs_to.is_some() { + if *new_paste.belongs_to.as_ref().unwrap() == user.id { + match update_paste(new_paste, &conn) { + Ok(_) => status::Custom( + Status::Created, + Json(json!({ + "msg": "Successfully created paste", + "paste_id": new_paste.id + })), + ), + Err(_) => internal_server_error(), + } + } else { + forbidden() + } + } else { + unprocessable_entity() + } +} + +pub fn fuel(rocket: Rocket) -> Rocket { + rocket.mount("/api/paste", routes![create, fetch, update]) } diff --git a/src/core/paste/postgres.rs b/src/core/paste/postgres.rs index 798ef8d..34df526 100644 --- a/src/core/paste/postgres.rs +++ b/src/core/paste/postgres.rs @@ -9,10 +9,17 @@ use super::entity::Paste; pub fn create_paste(paste: &Paste, conn: &PgConnection) -> Result { let rows = diesel::insert_into(pastes::table) .values(paste) + .on_conflict_do_nothing() .execute(conn)?; Ok(rows) } +pub fn update_paste(paste: &Paste, conn: &PgConnection) -> Result { + use crate::schema::pastes::dsl::*; + let updated_user = diesel::update(pastes.filter(id.eq(paste.id.as_ref().unwrap()))).set(paste).get_result(conn)?; + Ok(updated_user) +} + pub fn fetch_paste(id: String, conn: &PgConnection) -> Result { let paste = pastes::table.find(id).get_result::(conn)?; Ok(paste) diff --git a/src/core/paste/service.rs b/src/core/paste/service.rs index a182f80..75a0ed7 100644 --- a/src/core/paste/service.rs +++ b/src/core/paste/service.rs @@ -14,3 +14,9 @@ pub fn create_paste(paste: &mut Paste, conn: &PgConnection) -> Result { pub fn fetch_paste(id: String, conn: &PgConnection) -> Result { postgres::fetch_paste(id, conn) } + +pub fn update_paste(paste: &mut Paste, conn: &PgConnection) -> Result { + let re = RegexBuilder::new("^(https?://)?((([a-z\\d]([a-z\\d-]*[a-z\\d])*)\\.)+[a-z]{2,}|((\\d{1,3}\\.){3}\\d{1,3}))(:\\d+)?(/[-a-z\\d%_.~+]*)*(\\?[;&a-z\\d%_.~+=-]*)?(#[-a-z\\d_]*)?$").case_insensitive(true).build().unwrap(); + paste.is_url = Some(re.is_match(&*paste.content.clone())); + postgres::update_paste(paste, conn) +}