use tracing::instrument; use crate::api::api_prelude::*; use crate::error::{Error, Result}; #[instrument] #[get("")] pub async fn list_applications(state: web::Data) -> Result { let apps: Vec = Application::find().all(&state.db).await.unwrap(); let count = apps.len(); Ok(HttpResponse::Ok().json(ListObjects::new(apps, count))) } #[instrument] #[post("")] pub async fn new_application( state: web::Data, data: web::Json, ) -> Result { let model = application::ActiveModel { id: NotSet, app_name: Set(data.0.app_name), description: Set(data.0.description), url: Set(data.0.url), active: Set(data.0.active), glyph: Set(data.0.glyph), application_category_id: Set(data.0.application_category_id), }; let app = model.insert(&state.db).await?; Ok(HttpResponse::Ok().json(app)) } #[instrument] #[get("{id}")] pub async fn get_applications( state: web::Data, id: web::Path, ) -> Result { let id = id.into_inner(); let res: Option = Application::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_applications( state: web::Data, data: web::Json, id: web::Path, ) -> Result { let id = id.into_inner(); let res: Option = Application::find_by_id(id).one(&state.db).await?; match res { Some(_app) => { let data = data.into_inner(); let ret = application::ActiveModel { id: Set(id), active: Set(data.active), app_name: Set(data.app_name), description: Set(data.description), url: Set(data.url), application_category_id: Set(data.application_category_id), glyph: Set(data.glyph), }; let model = ret.update(&state.db).await?; Ok(HttpResponse::Ok().json(model)) } None => Err(Error::not_found()), } } #[instrument] #[delete("{id}")] pub async fn delete_application( state: web::Data, id: web::Path, ) -> Result { Application::delete_many() .filter(application::Column::Id.eq(id.into_inner())) .exec(&state.db) .await?; Ok(HttpResponse::Ok().body("")) } /// Routes for the application endpoints. This binds up a scope with all endpoints for applications, to make it easier to add them to the server. pub fn routes() -> Scope { web::scope("/applications") .service(list_applications) .service(update_applications) .service(delete_application) .service(new_application) .service(get_applications) } #[cfg(test)] mod tests { use crate::api::test_prelude::*; use actix_web::http::Method; #[actix_rt::test] async fn test_list_applications() -> Result<()> { let state = setup_state().await?; application::ActiveModel { app_name: Set("Application 1".into()), url: Set("http://somewhere/".into()), active: Set(true), ..Default::default() } .insert(&state.db) .await?; application::ActiveModel { app_name: Set("Application 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/applications") .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_applications() -> Result<()> { let state = setup_state().await?; let model = application::ActiveModel { app_name: Set("Application 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/applications/{}", 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::application::Model); data.id = model.id; assert_eq!(model, data); assert_eq!(status, 200); Ok(()) } #[actix_rt::test] async fn test_new_application() -> Result<()> { let model = application::Model { id: 0, app_name: "Application 1".into(), glyph: Some("web".into()), url: "http://example.com".into(), description: Some("Some Application".into()), active: true, application_category_id: None, }; let state = setup_state().await?; let mut req = actix_web::test::TestRequest::with_uri("/api/applications") .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::application::Model); assert_eq!(model, data); assert_eq!(application::Entity::find().count(&state.db).await?, 1); Ok(()) } #[actix_rt::test] async fn test_update_application() -> Result<()> { let state = setup_state().await?; application::ActiveModel { app_name: Set("Application 1".into()), url: Set("http://somewhere/".into()), active: Set(true), ..Default::default() } .insert(&state.db) .await?; let mut model = application::ActiveModel { app_name: Set("Application 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/applications/{}", 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::application::Model); data.id = model.id; assert_eq!(model, data, "Check API"); let db_model = application::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_application() -> Result<()> { let state = setup_state().await?; let model = application::ActiveModel { app_name: Set("Application 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/applications/{}", model.id)) .method(Method::DELETE) .to_request(); let resp = call_endpoint!(req, state); assert_eq!(resp.status(), 200); assert_eq!(application::Entity::find().count(&state.db).await?, 0); Ok(()) } }