diff --git a/src/api/ecdar_api.rs b/src/api/ecdar_api.rs index 7815549..fc715e8 100644 --- a/src/api/ecdar_api.rs +++ b/src/api/ecdar_api.rs @@ -605,6 +605,46 @@ impl EcdarApi for ConcreteEcdarApi { ) -> Result, Status> { let message = request.get_ref().clone(); + let uid = request + .uid() + .ok_or(Status::internal("Could not get uid from request metadata"))?; + + let user_access = self + .contexts + .access_context + .get_by_id(message.id) + .await + .map_err(|err| Status::new(Code::Internal, err.to_string()))? + .ok_or_else(|| { + Status::new( + Code::NotFound, + "No access entity found for user".to_string(), + ) + })?; + + check_editor_role_helper( + Arc::clone(&self.contexts.access_context), + uid, + user_access.model_id, + ) + .await?; + + let model = self + .contexts + .model_context + .get_by_id(user_access.model_id) + .await + .map_err(|err| Status::new(Code::Internal, err.to_string()))? + .ok_or_else(|| Status::new(Code::NotFound, "No model found for access".to_string()))?; + + // Check that the requester is not trying to delete the owner's access + if model.owner_id == message.id { + return Err(Status::new( + Code::PermissionDenied, + "You cannot delete the access entity for this user", + )); + } + match self.contexts.access_context.delete(message.id).await { Ok(_) => Ok(Response::new(())), Err(error) => match error { diff --git a/src/tests/api/access_logic.rs b/src/tests/api/access_logic.rs index 7c4ab30..d36490e 100644 --- a/src/tests/api/access_logic.rs +++ b/src/tests/api/access_logic.rs @@ -351,10 +351,54 @@ async fn delete_invalid_access_returns_err() { mock_services .access_context_mock .expect_delete() - .with(predicate::eq(1)) + .with(predicate::eq(2)) .returning(move |_| Err(DbErr::RecordNotFound("".to_string()))); - let request = Request::new(DeleteAccessRequest { id: 1 }); + mock_services + .access_context_mock + .expect_get_by_id() + .with(predicate::eq(2)) + .returning(move |_| { + Ok(Some(access::Model { + id: 1, + role: "Editor".to_string(), + model_id: 1, + user_id: 2, + })) + }); + + mock_services + .access_context_mock + .expect_get_access_by_uid_and_model_id() + .with(predicate::eq(1), predicate::eq(1)) + .returning(move |_, _| { + Ok(Some(access::Model { + id: 1, + role: "Editor".to_string(), + model_id: 1, + user_id: 1, + })) + }); + + mock_services + .model_context_mock + .expect_get_by_id() + .with(predicate::eq(1)) + .returning(move |_| { + Ok(Some(model::Model { + id: 1, + name: "test".to_string(), + owner_id: 1, + components_info: Default::default(), + })) + }); + + let mut request = Request::new(DeleteAccessRequest { id: 2 }); + + request.metadata_mut().insert( + "uid", + tonic::metadata::MetadataValue::from_str("1").unwrap(), + ); let api = get_mock_concrete_ecdar_api(mock_services); @@ -368,7 +412,7 @@ async fn delete_access_returns_ok() { let mut mock_services = get_mock_services(); let access = access::Model { - id: 1, + id: 2, role: "Editor".to_string(), model_id: Default::default(), user_id: Default::default(), @@ -377,10 +421,54 @@ async fn delete_access_returns_ok() { mock_services .access_context_mock .expect_delete() - .with(predicate::eq(1)) + .with(predicate::eq(2)) .returning(move |_| Ok(access.clone())); - let request = Request::new(DeleteAccessRequest { id: 1 }); + mock_services + .access_context_mock + .expect_get_by_id() + .with(predicate::eq(2)) + .returning(move |_| { + Ok(Some(access::Model { + id: 1, + role: "Editor".to_string(), + model_id: 1, + user_id: 2, + })) + }); + + mock_services + .access_context_mock + .expect_get_access_by_uid_and_model_id() + .with(predicate::eq(1), predicate::eq(1)) + .returning(move |_, _| { + Ok(Some(access::Model { + id: 1, + role: "Editor".to_string(), + model_id: 1, + user_id: 1, + })) + }); + + mock_services + .model_context_mock + .expect_get_by_id() + .with(predicate::eq(1)) + .returning(move |_| { + Ok(Some(model::Model { + id: 1, + name: "test".to_string(), + owner_id: 1, + components_info: Default::default(), + })) + }); + + let mut request = Request::new(DeleteAccessRequest { id: 2 }); + + request.metadata_mut().insert( + "uid", + tonic::metadata::MetadataValue::from_str("1").unwrap(), + ); let api = get_mock_concrete_ecdar_api(mock_services);