use tracing::instrument; use crate::api::api_prelude::*; use crate::error::{Error, Result}; #[instrument] #[get("")] pub async fn list_bookmark_categories(state: web::Data) -> Result { let cats: Vec = BookmarkCategory::find().all(&state.db).await.unwrap(); let count = cats.len(); Ok(HttpResponse::Ok().json(ListObjects::new(cats, count))) } #[instrument] #[post("")] pub async fn new_bookmark_category( state: web::Data, data: web::Json, ) -> Result { let model = bookmark_category::ActiveModel { id: NotSet, category_name: Set(data.0.category_name), glyph: Set(data.0.glyph), active: Set(data.0.active), }; let rec = model.insert(&state.db).await?; Ok(HttpResponse::Ok().json(rec)) } #[instrument] #[get("{id}")] pub async fn get_bookmark_category( state: web::Data, id: web::Path, ) -> Result { let id = id.into_inner(); let res: Option = BookmarkCategory::find_by_id(id).one(&state.db).await?; match res { Some(rec) => Ok(HttpResponse::Ok().json(rec)), None => Err(Error::not_found()), } } #[instrument] #[put("{id}")] pub async fn update_bookmark_category( state: web::Data, data: web::Json, id: web::Path, ) -> Result { let id = id.into_inner(); let res: Option = BookmarkCategory::find_by_id(id).one(&state.db).await?; match res { Some(_rec) => { let data = data.into_inner(); let ret = bookmark_category::ActiveModel { id: Set(id), active: Set(data.active), glyph: Set(data.glyph), category_name: Set(data.category_name), }; 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_category( state: web::Data, id: web::Path, ) -> Result { BookmarkCategory::delete_many() .filter(bookmark_category::Column::Id.eq(id.into_inner())) .exec(&state.db) .await?; Ok(HttpResponse::Ok().body("")) } #[instrument] #[get("{id}/bookmarks")] pub async fn bookmark_category_bookmarks( state: web::Data, id: web::Path, ) -> Result { let recs: Vec = Bookmark::find() .filter(bookmark::Column::BookmarkCategoryId.eq(id.into_inner())) .all(&state.db) .await .unwrap(); let count = recs.len(); Ok(HttpResponse::Ok().json(ListObjects::new(recs, count))) } /// 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("/bookmark_categories") .service(bookmark_category_bookmarks) .service(list_bookmark_categories) .service(update_bookmark_category) .service(delete_bookmark_category) .service(new_bookmark_category) .service(get_bookmark_category) } #[cfg(test)] mod tests { use crate::api::test_prelude::*; use actix_web::http::Method; #[actix_rt::test] async fn test_list_bookmark_categories() -> Result<()> { let state = setup_state().await?; bookmark_category::ActiveModel { category_name: Set("Bookmark 1".into()), active: Set(true), ..Default::default() } .insert(&state.db) .await?; bookmark_category::ActiveModel { category_name: Set("Bookmark 2".into()), active: Set(true), ..Default::default() } .insert(&state.db) .await?; let mut req = actix_web::test::TestRequest::with_uri("/api/bookmark_categories") .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_bookmark_categories() -> Result<()> { let state = setup_state().await?; let model = bookmark_category::ActiveModel { category_name: Set("Bookmark 1".into()), active: Set(true), ..Default::default() } .insert(&state.db) .await?; let mut req = actix_web::test::TestRequest::with_uri(&format!( "/api/bookmark_categories/{}", 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_category::Model); data.id = model.id; assert_eq!(model, data); assert_eq!(status, 200); Ok(()) } #[actix_rt::test] async fn test_new_bookmark_category() -> Result<()> { let model = bookmark_category::Model { id: 0, category_name: "Some name".into(), glyph: None, active: true, }; let state = setup_state().await?; let mut req = actix_web::test::TestRequest::with_uri("/api/bookmark_categories") .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_category::Model); assert_eq!(model, data); assert_eq!(bookmark_category::Entity::find().count(&state.db).await?, 1); Ok(()) } #[actix_rt::test] async fn test_update_bookmark_category() -> Result<()> { let state = setup_state().await?; bookmark_category::ActiveModel { category_name: Set("Some name".into()), active: Set(true), ..Default::default() } .insert(&state.db) .await?; let mut model = bookmark_category::ActiveModel { category_name: Set("Some name".into()), active: Set(true), ..Default::default() } .insert(&state.db) .await?; model.category_name = "Another name".into(); let mut req = actix_web::test::TestRequest::with_uri(&format!( "/api/bookmark_categories/{}", 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_category::Model); data.id = model.id; assert_eq!(model, data, "Check API"); let db_model = bookmark_category::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_category() -> Result<()> { let state = setup_state().await?; let model = bookmark_category::ActiveModel { category_name: Set("Some name".into()), active: Set(true), ..Default::default() } .insert(&state.db) .await?; let mut req = actix_web::test::TestRequest::with_uri(&format!( "/api/bookmark_categories/{}", model.id )) .method(Method::DELETE) .to_request(); let resp = call_endpoint!(req, state); assert_eq!(resp.status(), 200); assert_eq!(bookmark_category::Entity::find().count(&state.db).await?, 0); Ok(()) } #[actix_rt::test] async fn test_bookmark_categories_bookmarks() -> Result<()> { let state = setup_state().await?; let category = bookmark_category::ActiveModel { category_name: Set("Bookmark 1".into()), active: Set(true), ..Default::default() } .insert(&state.db) .await?; bookmark::ActiveModel { bookmark_name: Set("Bookmark 1".into()), url: Set("http://somewhere/".into()), active: Set(true), bookmark_category_id: Set(Some(category.id)), ..Default::default() } .insert(&state.db) .await?; bookmark::ActiveModel { bookmark_name: Set("Bookmark 2".into()), url: Set("http://somewhere/".into()), bookmark_category_id: Set(Some(category.id)), 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(&format!( "/api/bookmark_categories/{}/bookmarks", category.id )) .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(()) } }