diff --git a/src/routes/groups/{group_id}/mod.rs b/src/routes/groups/{group_id}/mod.rs index 1c00d54..d6f2908 100644 --- a/src/routes/groups/{group_id}/mod.rs +++ b/src/routes/groups/{group_id}/mod.rs @@ -11,6 +11,7 @@ use std::sync::Arc; use axum::{Extension, Json, Router, extract::{Path, State}}; +use reqwest::StatusCode; use crate::{ AppState, HTTPError, @@ -18,7 +19,7 @@ use crate::{ resources::{ access_policy::{AccessPolicyResourceType, ActionPermissionLevel}, action_log_entry::{ActionLogEntry, ActionLogEntryActorType, ActionLogEntryTargetResourceType, InitialActionLogEntryProperties}, app::App, app_authorization::AppAuthorization, group::Group, http_transaction::HTTPTransaction, server_log_entry::ServerLogEntry, user::User }, - utilities::route_handler_utilities::{AuthenticatedPrincipal, get_action_by_name, get_action_log_entry_expiration_timestamp, get_authenticated_principal, get_group_by_id, get_resource_hierarchy, get_uuid_from_string, verify_delegate_permissions, verify_principal_permissions} + utilities::{reusable_route_handlers::delete_resource, route_handler_utilities::{AuthenticatedPrincipal, get_action_by_name, get_action_log_entry_expiration_timestamp, get_authenticated_principal, get_group_by_id, get_resource_hierarchy, get_uuid_from_string, verify_delegate_permissions, verify_principal_permissions}} }; // #[path = "./access-policies/mod.rs"] @@ -66,37 +67,37 @@ async fn handle_get_group_request( } -// /// DELETE /groups/{group_id} -// /// -// /// Deletes an app by its ID. -// #[axum::debug_handler] -// async fn handle_delete_app_request( -// Path(group_id): Path, -// State(state): State, -// Extension(http_transaction): Extension>, -// Extension(authenticated_user): Extension>>, -// Extension(authenticated_app): Extension>>, -// Extension(authenticated_app_authorization): Extension>> -// ) -> Result { - -// let group_id = get_uuid_from_string(&group_id, "app", &http_transaction, &state.database_pool).await?; -// let response = delete_resource( -// State(state), -// Extension(http_transaction), -// Extension(authenticated_user), -// Extension(authenticated_app), -// Extension(authenticated_app_authorization), -// Some(&AccessPolicyResourceType::App), -// &group_id, -// "apps.delete", -// "app", -// &ActionLogEntryTargetResourceType::App, -// |group_id, database_pool| Box::new(App::get_by_id(group_id, database_pool)) -// ).await; - -// return response; +/// DELETE /groups/{group_id} +/// +/// Deletes a group by its ID. +#[axum::debug_handler] +async fn handle_delete_group_request( + Path(group_id): Path, + State(state): State, + Extension(http_transaction): Extension>, + Extension(authenticated_user): Extension>>, + Extension(authenticated_app): Extension>>, + Extension(authenticated_app_authorization): Extension>> +) -> Result { -// } + let group_id = get_uuid_from_string(&group_id, "group", &http_transaction, &state.database_pool).await?; + let response = delete_resource( + State(state), + Extension(http_transaction), + Extension(authenticated_user), + Extension(authenticated_app), + Extension(authenticated_app_authorization), + Some(&AccessPolicyResourceType::Group), + &group_id, + "groups.delete", + "group", + &ActionLogEntryTargetResourceType::Group, + |group_id, database_pool| Box::new(Group::get_by_id(group_id, database_pool)) + ).await; + + return response; + +} // /// PATCH /groups/{group_id} // /// @@ -184,7 +185,7 @@ pub fn get_router(state: AppState) -> Router { let router = Router::::new() .route("/groups/{group_id}", axum::routing::get(handle_get_group_request)) - // .route("/groups/{group_id}", axum::routing::delete(handle_delete_app_request)) + .route("/groups/{group_id}", axum::routing::delete(handle_delete_group_request)) // .route("/groups/{group_id}", axum::routing::patch(handle_patch_app_request)) .layer(axum::middleware::from_fn_with_state(state.clone(), authentication_middleware::authenticate_user)) .layer(axum::middleware::from_fn_with_state(state.clone(), authentication_middleware::authenticate_app)) diff --git a/src/routes/groups/{group_id}/tests.rs b/src/routes/groups/{group_id}/tests.rs index c8638bc..7474f0e 100644 --- a/src/routes/groups/{group_id}/tests.rs +++ b/src/routes/groups/{group_id}/tests.rs @@ -20,7 +20,7 @@ use crate::{ initialize_predefined_roles }, resources::{ - access_policy::ActionPermissionLevel, group::Group + ResourceError, access_policy::ActionPermissionLevel, group::Group }, tests::{TestEnvironment, TestSlashstepServerError} }; @@ -193,180 +193,180 @@ async fn verify_not_found_when_getting_resource_by_id() -> Result<(), TestSlashs } -// /// Verifies that the router can return a 204 status code if the action is successfully deleted. -// #[tokio::test] -// async fn verify_successful_deletion_when_deleting_by_id() -> Result<(), TestSlashstepServerError> { +/// Verifies that the router can return a 204 status code if the action is successfully deleted. +#[tokio::test] +async fn verify_successful_deletion_when_deleting_by_id() -> Result<(), TestSlashstepServerError> { -// let test_environment = TestEnvironment::new().await?; -// initialize_required_tables(&test_environment.database_pool).await?; -// initialize_predefined_actions(&test_environment.database_pool).await?; -// initialize_predefined_roles(&test_environment.database_pool).await?; + let test_environment = TestEnvironment::new().await?; + initialize_required_tables(&test_environment.database_pool).await?; + initialize_predefined_actions(&test_environment.database_pool).await?; + initialize_predefined_roles(&test_environment.database_pool).await?; + initialize_predefined_configurations(&test_environment.database_pool).await?; -// // Create the user and the session. -// let user = test_environment.create_random_user().await?; -// let session = test_environment.create_random_session(Some(&user.id)).await?; -// let json_web_token_private_key = get_json_web_token_private_key().await?; -// let session_token = session.generate_json_web_token(&json_web_token_private_key).await?; + // Create the user and the session. + let user = test_environment.create_random_user().await?; + let session = test_environment.create_random_session(Some(&user.id)).await?; + let json_web_token_private_key = get_json_web_token_private_key().await?; + let session_token = session.generate_json_web_token(&json_web_token_private_key).await?; -// // Grant access to the "groups.delete" action to the user. -// let delete_fields_action = Action::get_by_name("groups.delete", &test_environment.database_pool).await?; -// AccessPolicy::create(&InitialAccessPolicyProperties { -// action_id: delete_fields_action.id, -// permission_level: ActionPermissionLevel::User, -// is_inheritance_enabled: true, -// principal_type: AccessPolicyPrincipalType::User, -// principal_user_id: Some(user.id), -// scoped_resource_type: AccessPolicyResourceType::Server, -// ..Default::default() -// }, &test_environment.database_pool).await?; + // Grant access to the "groups.delete" action to the user. + let delete_groups_action = Action::get_by_name("groups.delete", &test_environment.database_pool).await?; + test_environment.create_server_access_policy(&user.id, &delete_groups_action.id, &ActionPermissionLevel::User).await?; -// // Set up the server and send the request. -// let group = test_environment.create_random_group().await?; -// let state = AppState { -// database_pool: test_environment.database_pool.clone(), -// }; -// let router = super::get_router(state.clone()) -// .with_state(state) -// .into_make_service_with_connect_info::(); -// let test_server = TestServer::new(router)?; -// let response = test_server.delete(&format!("/groups/{}", group.id)) -// .add_cookie(Cookie::new("sessionToken", format!("Bearer {}", session_token))) -// .await; + // Set up the server and send the request. + let group = test_environment.create_random_group().await?; + let state = AppState { + database_pool: test_environment.database_pool.clone(), + }; + let router = super::get_router(state.clone()) + .with_state(state) + .into_make_service_with_connect_info::(); + let test_server = TestServer::new(router)?; + let response = test_server.delete(&format!("/groups/{}", group.id)) + .add_cookie(Cookie::new("sessionToken", format!("Bearer {}", session_token))) + .await; -// assert_eq!(response.status_code(), StatusCode::NO_CONTENT); + assert_eq!(response.status_code(), StatusCode::NO_CONTENT); -// match App::get_by_id(&group.id, &test_environment.database_pool).await.expect_err("Expected an app not found error.") { + match Group::get_by_id(&group.id, &test_environment.database_pool).await.expect_err("Expected a group not found error.") { -// ResourceError::NotFoundError(_) => {}, + ResourceError::NotFoundError(_) => {}, -// error => return Err(TestSlashstepServerError::ResourceError(error)) + error => return Err(TestSlashstepServerError::ResourceError(error)) -// } + } -// return Ok(()); + return Ok(()); -// } +} -// /// Verifies that the router can return a 400 status code if the ID is not a UUID. -// #[tokio::test] -// async fn verify_uuid_when_deleting_by_id() -> Result<(), TestSlashstepServerError> { +/// Verifies that the router can return a 400 status code if the ID is not a UUID. +#[tokio::test] +async fn verify_uuid_when_deleting_by_id() -> Result<(), TestSlashstepServerError> { -// let test_environment = TestEnvironment::new().await?; -// initialize_required_tables(&test_environment.database_pool).await?; -// initialize_predefined_actions(&test_environment.database_pool).await?; -// initialize_predefined_roles(&test_environment.database_pool).await?; -// let state = AppState { -// database_pool: test_environment.database_pool.clone(), -// }; + let test_environment = TestEnvironment::new().await?; + initialize_required_tables(&test_environment.database_pool).await?; + initialize_predefined_actions(&test_environment.database_pool).await?; + initialize_predefined_roles(&test_environment.database_pool).await?; + initialize_predefined_configurations(&test_environment.database_pool).await?; -// let router = super::get_router(state.clone()) -// .with_state(state) -// .into_make_service_with_connect_info::(); -// let test_server = TestServer::new(router)?; + let state = AppState { + database_pool: test_environment.database_pool.clone(), + }; -// let response = test_server.delete("/groups/not-a-uuid") -// .await; + let router = super::get_router(state.clone()) + .with_state(state) + .into_make_service_with_connect_info::(); + let test_server = TestServer::new(router)?; + + let response = test_server.delete("/groups/not-a-uuid") + .await; -// assert_eq!(response.status_code(), StatusCode::BAD_REQUEST); -// return Ok(()); + assert_eq!(response.status_code(), StatusCode::BAD_REQUEST); + return Ok(()); -// } +} -// /// Verifies that the router can return a 401 status code if the user needs authentication. -// #[tokio::test] -// async fn verify_authentication_when_deleting_by_id() -> Result<(), TestSlashstepServerError> { +/// Verifies that the router can return a 401 status code if the user needs authentication. +#[tokio::test] +async fn verify_authentication_when_deleting_by_id() -> Result<(), TestSlashstepServerError> { -// let test_environment = TestEnvironment::new().await?; -// initialize_required_tables(&test_environment.database_pool).await?; -// initialize_predefined_actions(&test_environment.database_pool).await?; -// initialize_predefined_roles(&test_environment.database_pool).await?; + let test_environment = TestEnvironment::new().await?; + initialize_required_tables(&test_environment.database_pool).await?; + initialize_predefined_actions(&test_environment.database_pool).await?; + initialize_predefined_roles(&test_environment.database_pool).await?; + initialize_predefined_configurations(&test_environment.database_pool).await?; -// // Create a dummy app. -// let group = test_environment.create_random_group().await?; + // Create a dummy app. + let group = test_environment.create_random_group().await?; -// // Set up the server and send the request. -// let state = AppState { -// database_pool: test_environment.database_pool.clone(), -// }; -// let router = super::get_router(state.clone()) -// .with_state(state) -// .into_make_service_with_connect_info::(); -// let test_server = TestServer::new(router)?; -// let response = test_server.delete(&format!("/groups/{}", group.id)) -// .await; + // Set up the server and send the request. + let state = AppState { + database_pool: test_environment.database_pool.clone(), + }; + let router = super::get_router(state.clone()) + .with_state(state) + .into_make_service_with_connect_info::(); + let test_server = TestServer::new(router)?; + let response = test_server.delete(&format!("/groups/{}", group.id)) + .await; -// // Verify the response. -// assert_eq!(response.status_code(), StatusCode::UNAUTHORIZED); -// return Ok(()); + // Verify the response. + assert_eq!(response.status_code(), StatusCode::UNAUTHORIZED); + return Ok(()); -// } +} -// /// Verifies that the router can return a 403 status code if the user does not have permission to delete the resource. -// #[tokio::test] -// async fn verify_permission_when_deleting_by_id() -> Result<(), TestSlashstepServerError> { +/// Verifies that the router can return a 403 status code if the user does not have permission to delete the resource. +#[tokio::test] +async fn verify_permission_when_deleting_by_id() -> Result<(), TestSlashstepServerError> { -// let test_environment = TestEnvironment::new().await?; -// initialize_required_tables(&test_environment.database_pool).await?; -// initialize_predefined_actions(&test_environment.database_pool).await?; -// initialize_predefined_roles(&test_environment.database_pool).await?; + let test_environment = TestEnvironment::new().await?; + initialize_required_tables(&test_environment.database_pool).await?; + initialize_predefined_actions(&test_environment.database_pool).await?; + initialize_predefined_roles(&test_environment.database_pool).await?; + initialize_predefined_configurations(&test_environment.database_pool).await?; -// // Create the user and the session. -// let user = test_environment.create_random_user().await?; -// let session = test_environment.create_random_session(Some(&user.id)).await?; -// let json_web_token_private_key = get_json_web_token_private_key().await?; -// let session_token = session.generate_json_web_token(&json_web_token_private_key).await?; + // Create the user and the session. + let user = test_environment.create_random_user().await?; + let session = test_environment.create_random_session(Some(&user.id)).await?; + let json_web_token_private_key = get_json_web_token_private_key().await?; + let session_token = session.generate_json_web_token(&json_web_token_private_key).await?; -// // Create a dummy app. -// let group = test_environment.create_random_group().await?; + // Create a dummy group. + let group = test_environment.create_random_group().await?; -// // Set up the server and send the request. -// let state = AppState { -// database_pool: test_environment.database_pool.clone(), -// }; -// let router = super::get_router(state.clone()) -// .with_state(state) -// .into_make_service_with_connect_info::(); -// let test_server = TestServer::new(router)?; -// let response = test_server.delete(&format!("/groups/{}", group.id)) -// .add_cookie(Cookie::new("sessionToken", format!("Bearer {}", session_token))) -// .await; + // Set up the server and send the request. + let state = AppState { + database_pool: test_environment.database_pool.clone(), + }; + let router = super::get_router(state.clone()) + .with_state(state) + .into_make_service_with_connect_info::(); + let test_server = TestServer::new(router)?; + let response = test_server.delete(&format!("/groups/{}", group.id)) + .add_cookie(Cookie::new("sessionToken", format!("Bearer {}", session_token))) + .await; -// // Verify the response. -// assert_eq!(response.status_code(), StatusCode::FORBIDDEN); -// return Ok(()); + // Verify the response. + assert_eq!(response.status_code(), StatusCode::FORBIDDEN); + return Ok(()); -// } +} -// /// Verifies that the router can return a 404 status code if the resource does not exist. -// #[tokio::test] -// async fn verify_resource_exists_when_deleting_by_id() -> Result<(), TestSlashstepServerError> { +/// Verifies that the router can return a 404 status code if the resource does not exist. +#[tokio::test] +async fn verify_resource_exists_when_deleting_by_id() -> Result<(), TestSlashstepServerError> { -// let test_environment = TestEnvironment::new().await?; -// initialize_required_tables(&test_environment.database_pool).await?; + let test_environment = TestEnvironment::new().await?; + initialize_required_tables(&test_environment.database_pool).await?; + initialize_predefined_actions(&test_environment.database_pool).await?; + initialize_predefined_roles(&test_environment.database_pool).await?; + initialize_predefined_configurations(&test_environment.database_pool).await?; -// // Create the user and the session. -// let user = test_environment.create_random_user().await?; -// let session = test_environment.create_random_session(Some(&user.id)).await?; -// let json_web_token_private_key = get_json_web_token_private_key().await?; -// let session_token = session.generate_json_web_token(&json_web_token_private_key).await?; + // Create the user and the session. + let user = test_environment.create_random_user().await?; + let session = test_environment.create_random_session(Some(&user.id)).await?; + let json_web_token_private_key = get_json_web_token_private_key().await?; + let session_token = session.generate_json_web_token(&json_web_token_private_key).await?; -// // Set up the server and send the request. -// let state = AppState { -// database_pool: test_environment.database_pool.clone(), -// }; -// let router = super::get_router(state.clone()) -// .with_state(state) -// .into_make_service_with_connect_info::(); -// let test_server = TestServer::new(router)?; -// let response = test_server.delete(&format!("/groups/{}", uuid::Uuid::now_v7())) -// .add_cookie(Cookie::new("sessionToken", format!("Bearer {}", session_token))) -// .await; + // Set up the server and send the request. + let state = AppState { + database_pool: test_environment.database_pool.clone(), + }; + let router = super::get_router(state.clone()) + .with_state(state) + .into_make_service_with_connect_info::(); + let test_server = TestServer::new(router)?; + let response = test_server.delete(&format!("/groups/{}", uuid::Uuid::now_v7())) + .add_cookie(Cookie::new("sessionToken", format!("Bearer {}", session_token))) + .await; -// // Verify the response. -// assert_eq!(response.status_code(), StatusCode::NOT_FOUND); -// return Ok(()); + // Verify the response. + assert_eq!(response.status_code(), StatusCode::NOT_FOUND); + return Ok(()); -// } +} // /// Verifies that the router can return a 200 status code if the resource is successfully patched. // #[tokio::test]