diff --git a/sqlx-data.json b/sqlx-data.json index 802c4e0..5090a5f 100644 --- a/sqlx-data.json +++ b/sqlx-data.json @@ -1,5 +1,18 @@ { "db": "PostgreSQL", + "03c9789e83a398bed96354924a0e63ccaa97bec667fda1b8277bb9afda9a6fcd": { + "query": "DELETE \n FROM survey_campaigns \n WHERE \n user_id = (\n SELECT \n ID \n FROM \n survey_admins \n WHERE \n name = $1\n )\n AND\n id = ($2)", + "describe": { + "columns": [], + "parameters": { + "Left": [ + "Text", + "Uuid" + ] + }, + "nullable": [] + } + }, "0d22134cc5076304b7895827f006ee8269cc500f400114a7472b83f0f1c568b5": { "query": "INSERT INTO survey_admins \n (name , password, secret) VALUES ($1, $2, $3)", "describe": { @@ -133,6 +146,27 @@ "nullable": [] } }, + "58ec3b8f98c27e13ec2732f8ee23f6eb9845ac5d9fd97b1e5c9f2eed4b1f5693": { + "query": "SELECT name \n FROM survey_campaigns\n WHERE \n id = $1\n AND\n user_id = (SELECT ID from survey_admins WHERE name = $2)", + "describe": { + "columns": [ + { + "ordinal": 0, + "name": "name", + "type_info": "Varchar" + } + ], + "parameters": { + "Left": [ + "Uuid", + "Text" + ] + }, + "nullable": [ + false + ] + } + }, "683707dbc847b37c58c29aaad0d1a978c9fe0657da13af99796e4461134b5a43": { "query": "UPDATE survey_admins set email = $1\n WHERE name = $2", "describe": { @@ -166,6 +200,32 @@ ] } }, + "70cc7bfc9b6ff5b68db70c069c0947d51bfc4a53cedc020016ee25ff98586c93": { + "query": "SELECT \n name, id\n FROM \n survey_campaigns \n WHERE\n user_id = (\n SELECT \n ID\n FROM \n survey_admins\n WHERE\n name = $1\n )", + "describe": { + "columns": [ + { + "ordinal": 0, + "name": "name", + "type_info": "Varchar" + }, + { + "ordinal": 1, + "name": "id", + "type_info": "Uuid" + } + ], + "parameters": { + "Left": [ + "Text" + ] + }, + "nullable": [ + false, + false + ] + } + }, "82feafc36533144e49ba374c8c47ca4aa0d6558a9803778ad28cfa7b62382c3e": { "query": "\n INSERT INTO survey_campaigns (\n user_id, ID, name, difficulties, created_at\n ) VALUES(\n (SELECT id FROM survey_admins WHERE name = $1),\n $2, $3, $4, $5\n );", "describe": { diff --git a/src/api/v1/admin/campaigns.rs b/src/api/v1/admin/campaigns.rs index 6a3da44..9496a33 100644 --- a/src/api/v1/admin/campaigns.rs +++ b/src/api/v1/admin/campaigns.rs @@ -20,27 +20,40 @@ use actix_identity::Identity; use actix_web::{web, HttpResponse, Responder}; use serde::{Deserialize, Serialize}; use sqlx::types::time::OffsetDateTime; +use uuid::Uuid; -use super::get_uuid; +use super::{get_admin_check_login, get_uuid}; use crate::errors::*; use crate::AppData; pub mod routes { pub struct Campaign { pub add: &'static str, + pub delete: &'static str, + // pub get_feedback: &'static str, + pub list: &'static str, } impl Campaign { pub const fn new() -> Campaign { let add = "/api/v1/admin/campaign/add"; - Campaign { add } + let delete = "/api/v1/admin/campaign/{uuid}/delete"; + // let get_feedback = "/api/v1/campaign/{uuid}/feedback"; + let list = "/api/v1/admin/campaign/list"; + + Campaign { add, delete, list } + } + // pub fn get_benches_route(&self, campaign_id: &str) -> String { + // self.get_feedback.replace("{uuid}", &campaign_id) + // } + + pub fn get_delete_route(&self, campaign_id: &str) -> String { + self.delete.replace("{uuid}", &campaign_id) } } } pub mod runners { - // use std::borrow::Cow; - use super::*; pub async fn add_runner( @@ -87,6 +100,218 @@ pub mod runners { } Ok(uuid) } + + pub async fn list_campaign_runner( + username: &str, + data: &AppData, + ) -> ServiceResult> { + struct ListCampaign { + name: String, + id: Uuid, + } + + let mut campaigns = sqlx::query_as!( + ListCampaign, + "SELECT + name, id + FROM + survey_campaigns + WHERE + user_id = ( + SELECT + ID + FROM + survey_admins + WHERE + name = $1 + )", + username + ) + .fetch_all(&data.db) + .await?; + + let mut list_resp = Vec::with_capacity(campaigns.len()); + campaigns.drain(0..).for_each(|c| { + list_resp.push(ListCampaignResp { + name: c.name, + uuid: c.id.to_string(), + }); + }); + + Ok(list_resp) + } + + // pub async fn get_benches( + // username: &str, + // uuid: &str, + // data: &AppData, + // ) -> ServiceResult { + // let uuid = Uuid::parse_str(uuid).map_err(|_| ServiceError::NotAnId)?; + // + // struct FeedbackInternal { + // time: OffsetDateTime, + // description: String, + // helpful: bool, + // } + // + // struct Name { + // name: String, + // } + // + // let name_fut = sqlx::query_as!( + // Name, + // "SELECT name + // FROM survey_campaigns + // WHERE uuid = $1 + // AND + // user_id = ( + // SELECT + // ID + // FROM + // kaizen_users + // WHERE + // name = $2 + // ) + // ", + // uuid, + // username + // ) + // .fetch_one(&data.db); //.await?; + // + // let feedback_fut = sqlx::query_as!( + // FeedbackInternal, + // "SELECT + // time, description, helpful + // FROM + // kaizen_feedbacks + // WHERE campaign_id = ( + // SELECT uuid + // FROM + // survey_campaigns + // WHERE + // uuid = $1 + // AND + // user_id = ( + // SELECT + // ID + // FROM + // kaizen_users + // WHERE + // name = $2 + // ) + // )", + // uuid, + // username + // ) + // .fetch_all(&data.db); + // let (name, mut feedbacks) = try_join!(name_fut, feedback_fut)?; + // //.await?; + // + // let mut feedback_resp = Vec::with_capacity(feedbacks.len()); + // feedbacks.drain(0..).for_each(|f| { + // feedback_resp.push(Feedback { + // time: f.time.unix_timestamp() as u64, + // description: f.description, + // helpful: f.helpful, + // }); + // }); + // + // Ok(GetFeedbackResp { + // feedbacks: feedback_resp, + // name: name.name, + // }) + // } + + pub async fn delete( + uuid: &Uuid, + username: &str, + data: &AppData, + ) -> ServiceResult<()> { + sqlx::query!( + "DELETE + FROM survey_campaigns + WHERE + user_id = ( + SELECT + ID + FROM + survey_admins + WHERE + name = $1 + ) + AND + id = ($2)", + username, + uuid + ) + .execute(&data.db) + .await?; + Ok(()) + } +} + +#[my_codegen::post( + path = "crate::V1_API_ROUTES.admin.campaign.delete", + wrap = "get_admin_check_login()" +)] +pub async fn delete( + id: Identity, + data: AppData, + path: web::Path, +) -> ServiceResult { + let username = id.identity().unwrap(); + let path = path.into_inner(); + let uuid = Uuid::parse_str(&path).map_err(|_| ServiceError::NotAnId)?; + runners::delete(&uuid, &username, &data).await?; + Ok(HttpResponse::Ok()) +} + +//#[derive(Serialize, Deserialize)] +//pub struct Feedback { +// pub time: u64, +// pub description: String, +// pub helpful: bool, +//} +// +//#[derive(Serialize, Deserialize)] +//pub struct GetFeedbackResp { +// pub name: String, +// pub feedbacks: Vec, +//} +// +//#[my_codegen::post( +// path = "crate::V1_API_ROUTES.campaign.get_feedback", +// wrap = "crate::CheckLogin" +//)] +//pub async fn get_feedback( +// id: Identity, +// data: AppData, +// path: web::Path, +//) -> ServiceResult { +// let username = id.identity().unwrap(); +// let path = path.into_inner(); +// let feedback_resp = runners::get_feedback(&username, &path, &data).await?; +// Ok(HttpResponse::Ok().json(feedback_resp)) +//} + +#[derive(Serialize, Deserialize)] +pub struct ListCampaignResp { + pub name: String, + pub uuid: String, +} + +#[my_codegen::post( + path = "crate::V1_API_ROUTES.admin.campaign.list", + wrap = "get_admin_check_login()" +)] +pub async fn list_campaign( + id: Identity, + data: AppData, +) -> ServiceResult { + let username = id.identity().unwrap(); + let list_resp = runners::list_campaign_runner(&username, &data).await?; + + Ok(HttpResponse::Ok().json(list_resp)) } #[derive(Serialize, Deserialize)] @@ -102,6 +327,9 @@ pub struct AddCapmaignResp { pub fn services(cfg: &mut web::ServiceConfig) { cfg.service(add); + cfg.service(delete); + cfg.service(list_campaign); + //cfg.service(get_feedback); } #[my_codegen::post(path = "crate::V1_API_ROUTES.admin.campaign.add")] @@ -123,6 +351,7 @@ async fn add( mod tests { use crate::api::v1::bench::Submission; use crate::data::Data; + use crate::errors::*; use crate::middleware::auth::GetLoginRoute; use crate::tests::*; use crate::*; @@ -197,5 +426,21 @@ mod tests { let _proof = submit_bench(&submit_payload, &campaign, survey_cookie, data.clone()).await; + + let list = list_campaings(data.clone(), cookies.clone()).await; + assert!(list.iter().any(|c| c.name == NAME)); + + bad_post_req_test_witout_payload( + NAME, + PASSWORD, + &V1_API_ROUTES.admin.campaign.delete.replace("{uuid}", NAME), + ServiceError::NotAnId, + ) + .await; + + delete_campaign(&campaign, data.clone(), cookies.clone()).await; + + let list = list_campaings(data.clone(), cookies.clone()).await; + assert!(!list.iter().any(|c| c.name == NAME)); } } diff --git a/src/tests.rs b/src/tests.rs index f2a35d6..93e49c6 100644 --- a/src/tests.rs +++ b/src/tests.rs @@ -27,7 +27,7 @@ use uuid::Uuid; use super::*; use crate::api::v1::admin::{ auth::runners::{Login, Register}, - campaigns::{AddCapmaign, AddCapmaignResp}, + campaigns::{AddCapmaign, AddCapmaignResp, ListCampaignResp}, }; use crate::api::v1::bench::{Bench, BenchConfig, Submission, SubmissionProof}; use crate::data::Data; @@ -177,28 +177,28 @@ pub async fn bad_post_req_test( //println!("{}", txt.error); assert_eq!(resp_err.error, format!("{}", err)); } -// -///// bad post req test without payload -//pub async fn bad_post_req_test_witout_payload( -// name: &str, -// password: &str, -// url: &str, -// err: ServiceError, -//) { -// let (data, _, signin_resp) = signin(name, password).await; -// let cookies = get_cookie!(signin_resp); -// let app = get_app!(data).await; -// -// let resp = test::call_service( -// &app, -// post_request!(url).cookie(cookies.clone()).to_request(), -// ) -// .await; -// assert_eq!(resp.status(), err.status_code()); -// let resp_err: ErrorToResponse = test::read_body_json(resp).await; -// //println!("{}", txt.error); -// assert_eq!(resp_err.error, format!("{}", err)); -//} + +/// bad post req test without payload +pub async fn bad_post_req_test_witout_payload( + name: &str, + password: &str, + url: &str, + err: ServiceError, +) { + let (data, _, signin_resp) = signin(name, password).await; + let cookies = get_cookie!(signin_resp); + let app = get_app!(data).await; + + let resp = test::call_service( + &app, + post_request!(url).cookie(cookies.clone()).to_request(), + ) + .await; + assert_eq!(resp.status(), err.status_code()); + let resp_err: ErrorToResponse = test::read_body_json(resp).await; + //println!("{}", txt.error); + assert_eq!(resp_err.error, format!("{}", err)); +} pub const DIFFICULTIES: [i32; 5] = [1, 2, 3, 4, 5]; @@ -255,35 +255,38 @@ pub async fn get_campaign_config( test::read_body_json(new_resp).await } -//pub async fn delete_campaign( -// camapign: &CreateResp, -// data: Arc, -// cookies: Cookie<'_>, -//) { -// let del_route = V1_API_ROUTES.campaign.get_delete_route(&camapign.uuid); -// let app = get_app!(data).await; -// let del_resp = -// test::call_service(&app, post_request!(&del_route).cookie(cookies).to_request()) -// .await; -// assert_eq!(del_resp.status(), StatusCode::OK); -//} -// -//pub async fn list_campaings( -// data: Arc, -// cookies: Cookie<'_>, -//) -> Vec { -// let app = get_app!(data).await; -// let list_resp = test::call_service( -// &app, -// post_request!(crate::V1_API_ROUTES.campaign.list) -// .cookie(cookies) -// .to_request(), -// ) -// .await; -// assert_eq!(list_resp.status(), StatusCode::OK); -// test::read_body_json(list_resp).await -//} -// +pub async fn delete_campaign( + camapign: &AddCapmaignResp, + data: Arc, + cookies: Cookie<'_>, +) { + let del_route = V1_API_ROUTES + .admin + .campaign + .get_delete_route(&camapign.campaign_id); + let app = get_app!(data).await; + let del_resp = + test::call_service(&app, post_request!(&del_route).cookie(cookies).to_request()) + .await; + assert_eq!(del_resp.status(), StatusCode::OK); +} + +pub async fn list_campaings( + data: Arc, + cookies: Cookie<'_>, +) -> Vec { + let app = get_app!(data).await; + let list_resp = test::call_service( + &app, + post_request!(crate::V1_API_ROUTES.admin.campaign.list) + .cookie(cookies) + .to_request(), + ) + .await; + assert_eq!(list_resp.status(), StatusCode::OK); + test::read_body_json(list_resp).await +} + pub async fn submit_bench( payload: &Submission, campaign: &AddCapmaignResp,