use tracing::instrument; use crate::api::api_prelude::*; use crate::error::{Error, Result}; #[instrument] #[get("")] pub async fn list_bookmarks(state: web::Data) -> Result { let apps: Vec = Bookmark::find().all(&state.db).await.unwrap(); let count = apps.len(); Ok(HttpResponse::Ok().json(ListObjects::new(apps, count))) } #[instrument] #[post("")] pub async fn new_bookmark( state: web::Data, data: web::Json, ) -> Result { let model = bookmark::ActiveModel { id: NotSet, bookmark_name: Set(data.0.bookmark_name), url: Set(data.0.url), active: Set(data.0.active), bookmark_category_id: Set(data.0.bookmark_category_id), }; let app = model.insert(&state.db).await?; Ok(HttpResponse::Ok().json(app)) } #[instrument] #[get("{id}")] pub async fn get_bookmarks(state: web::Data, id: web::Path) -> Result { let id = id.into_inner(); let res: Option = Bookmark::find_by_id(id).one(&state.db).await?; match res { Some(app) => Ok(HttpResponse::Ok().json(app)), None => Err(Error::not_found()), } } #[instrument] #[put("{id}")] pub async fn update_bookmarks( state: web::Data, data: web::Json, id: web::Path, ) -> Result { let id = id.into_inner(); let res: Option = Bookmark::find_by_id(id).one(&state.db).await?; match res { Some(_app) => { let data = data.into_inner(); let ret = bookmark::ActiveModel { id: Set(id), active: Set(data.active), bookmark_name: Set(data.bookmark_name), url: Set(data.url), bookmark_category_id: Set(data.bookmark_category_id), }; let model = ret.update(&state.db).await?; Ok(HttpResponse::Ok().json(model)) } None => Err(Error::not_found()), } } #[instrument] #[delete("{id}")] pub async fn delete_bookmark( state: web::Data, id: web::Path, ) -> Result { Bookmark::delete_many() .filter(bookmark::Column::Id.eq(id.into_inner())) .exec(&state.db) .await?; Ok(HttpResponse::Ok().body("")) } /// Routes for the bookmark endpoints. This binds up a scope with all endpoints for bookmarks, to make it easier to add them to the server. pub fn routes() -> Scope { web::scope("/bookmarks") .service(list_bookmarks) .service(update_bookmarks) .service(delete_bookmark) .service(new_bookmark) .service(get_bookmarks) } #[cfg(test)] mod tests { use crate::api::test_prelude::*; use actix_web::http::Method; #[actix_rt::test] async fn test_list_bookmarks() -> Result<()> { let state = setup_state().await?; bookmark::ActiveModel { bookmark_name: Set("Bookmark 1".into()), url: Set("http://somewhere/".into()), active: Set(true), ..Default::default() } .insert(&state.db) .await?; bookmark::ActiveModel { bookmark_name: Set("Bookmark 2".into()), url: Set("http://somewhere/".into()), active: Set(true), ..Default::default() } .insert(&state.db) .await?; let mut req = actix_web::test::TestRequest::with_uri("/api/bookmarks") .method(Method::GET) .to_request(); let resp = call_endpoint!(req, state); assert_eq!(resp.status(), 200); let data = get_response!(resp, ListObjects); assert_eq!(2_usize, data.items.len()); Ok(()) } #[actix_rt::test] async fn test_get_bookmarks() -> Result<()> { let state = setup_state().await?; let model = bookmark::ActiveModel { bookmark_name: Set("Bookmark 1".into()), url: Set("http://somewhere/".into()), active: Set(true), ..Default::default() } .insert(&state.db) .await?; let mut req = actix_web::test::TestRequest::with_uri(&format!("/api/bookmarks/{}", model.id)) .method(Method::GET) .to_request(); let resp = call_endpoint!(req, state); let status = resp.status(); let mut data = get_response!(resp, crate::entity::bookmark::Model); data.id = model.id; assert_eq!(model, data); assert_eq!(status, 200); Ok(()) } #[actix_rt::test] async fn test_new_bookmark() -> Result<()> { let model = bookmark::Model { id: 0, bookmark_name: "Bookmark 1".into(), url: "http://example.com".into(), active: true, bookmark_category_id: None, }; let state = setup_state().await?; let mut req = actix_web::test::TestRequest::with_uri("/api/bookmarks") .method(Method::POST) .set_json(model.clone()) .to_request(); let resp = call_endpoint!(req, state); assert_eq!(resp.status(), 200); let data = get_response!(resp, crate::entity::bookmark::Model); assert_eq!(model, data); assert_eq!(bookmark::Entity::find().count(&state.db).await?, 1); Ok(()) } #[actix_rt::test] async fn test_update_bookmark() -> Result<()> { let state = setup_state().await?; bookmark::ActiveModel { bookmark_name: Set("Bookmark 1".into()), url: Set("http://somewhere/".into()), active: Set(true), ..Default::default() } .insert(&state.db) .await?; let mut model = bookmark::ActiveModel { bookmark_name: Set("Bookmark 2".into()), url: Set("http://somewhere/".into()), active: Set(true), ..Default::default() } .insert(&state.db) .await?; model.url = "http://updated.com".into(); let mut req = actix_web::test::TestRequest::with_uri(&format!("/api/bookmarks/{}", model.id)) .method(Method::PUT) .set_json(model.clone()) .to_request(); let resp = call_endpoint!(req, state); assert_eq!(resp.status(), 200); let mut data = get_response!(resp, crate::entity::bookmark::Model); data.id = model.id; assert_eq!(model, data, "Check API"); let db_model = bookmark::Entity::find_by_id(model.id) .one(&state.db) .await? .unwrap(); assert_eq!(db_model, model, "Check DB"); Ok(()) } #[actix_rt::test] async fn test_delete_bookmark() -> Result<()> { let state = setup_state().await?; let model = bookmark::ActiveModel { bookmark_name: Set("Bookmark 1".into()), url: Set("http://somewhere/".into()), active: Set(true), ..Default::default() } .insert(&state.db) .await?; let mut req = actix_web::test::TestRequest::with_uri(&format!("/api/bookmarks/{}", model.id)) .method(Method::DELETE) .to_request(); let resp = call_endpoint!(req, state); assert_eq!(resp.status(), 200); assert_eq!(bookmark::Entity::find().count(&state.db).await?, 0); Ok(()) } }