From 2e9ced343bf3ff17ddffc83ccedc9dd2ed2d6120 Mon Sep 17 00:00:00 2001 From: sabotack Date: Wed, 6 Dec 2023 11:38:21 +0100 Subject: [PATCH 1/9] Add delete_session method and update protobuf pointer --- Ecdar-ProtoBuf | 2 +- src/api/ecdar_api.rs | 30 ++++++++++++++++++++++++++++++ 2 files changed, 31 insertions(+), 1 deletion(-) diff --git a/Ecdar-ProtoBuf b/Ecdar-ProtoBuf index eb72c7b..2d9a9ac 160000 --- a/Ecdar-ProtoBuf +++ b/Ecdar-ProtoBuf @@ -1 +1 @@ -Subproject commit eb72c7b9591934749d7f8dbf40f23376d6fdfa80 +Subproject commit 2d9a9ac58eb5fec1a816acad76f0e3357f122a94 diff --git a/src/api/ecdar_api.rs b/src/api/ecdar_api.rs index 436283b..8d2d73d 100644 --- a/src/api/ecdar_api.rs +++ b/src/api/ecdar_api.rs @@ -835,6 +835,36 @@ impl EcdarApi for ConcreteEcdarApi { response: Some(query_result.into_inner()), })) } + + /// Deletes the requester's session, found by their access token. + /// + /// Returns the response that is received from Reveaal. + async fn delete_session( + &self, + _request: Request<()>, + ) -> Result, Status> { + let access_token = _request + .token_string() + .ok_or(Status::unauthenticated("No access token provided"))?; + + let session = self + .contexts + .session_context + .get_by_token(TokenType::AccessToken, access_token) + .await + .map_err(|err| Status::new(Code::Internal, err.to_string()))? + .ok_or_else(|| { + Status::new( + Code::Unauthenticated, + "No session found with given access token", + ) + })?; + + match self.contexts.session_context.delete(session.id).await { + Ok(_) => Ok(Response::new(())), + Err(error) => Err(Status::new(Code::Internal, error.to_string())), + } + } } async fn get_auth_find_user_helper( From 9b8df0f1789bec68f6a0d4ffcffe1046bad26f00 Mon Sep 17 00:00:00 2001 From: sabotack Date: Wed, 6 Dec 2023 11:38:36 +0100 Subject: [PATCH 2/9] cargo fmt --- src/api/ecdar_api.rs | 11 ++++------- 1 file changed, 4 insertions(+), 7 deletions(-) diff --git a/src/api/ecdar_api.rs b/src/api/ecdar_api.rs index 8d2d73d..94ca6e8 100644 --- a/src/api/ecdar_api.rs +++ b/src/api/ecdar_api.rs @@ -839,14 +839,11 @@ impl EcdarApi for ConcreteEcdarApi { /// Deletes the requester's session, found by their access token. /// /// Returns the response that is received from Reveaal. - async fn delete_session( - &self, - _request: Request<()>, - ) -> Result, Status> { + async fn delete_session(&self, _request: Request<()>) -> Result, Status> { let access_token = _request .token_string() .ok_or(Status::unauthenticated("No access token provided"))?; - + let session = self .contexts .session_context @@ -859,10 +856,10 @@ impl EcdarApi for ConcreteEcdarApi { "No session found with given access token", ) })?; - + match self.contexts.session_context.delete(session.id).await { Ok(_) => Ok(Response::new(())), - Err(error) => Err(Status::new(Code::Internal, error.to_string())), + Err(error) => Err(Status::new(Code::Internal, error.to_string())), } } } From a3c3d9d22af0b9b33a39758a5ad04f4d429842ad Mon Sep 17 00:00:00 2001 From: sabotack Date: Wed, 6 Dec 2023 12:13:29 +0100 Subject: [PATCH 3/9] Fix delete_session parameter naming --- src/api/ecdar_api.rs | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/api/ecdar_api.rs b/src/api/ecdar_api.rs index 94ca6e8..7b485b0 100644 --- a/src/api/ecdar_api.rs +++ b/src/api/ecdar_api.rs @@ -839,8 +839,8 @@ impl EcdarApi for ConcreteEcdarApi { /// Deletes the requester's session, found by their access token. /// /// Returns the response that is received from Reveaal. - async fn delete_session(&self, _request: Request<()>) -> Result, Status> { - let access_token = _request + async fn delete_session(&self, request: Request<()>) -> Result, Status> { + let access_token = request .token_string() .ok_or(Status::unauthenticated("No access token provided"))?; From 3402f5fdc4e1e1d60675d1991c550b9860ed0d63 Mon Sep 17 00:00:00 2001 From: sabotack Date: Wed, 6 Dec 2023 12:29:14 +0100 Subject: [PATCH 4/9] Add delete_session tests --- src/tests/api/session_logic.rs | 77 +++++++++++++++++++++++++++++++++- 1 file changed, 76 insertions(+), 1 deletion(-) diff --git a/src/tests/api/session_logic.rs b/src/tests/api/session_logic.rs index 4513531..589ea3d 100644 --- a/src/tests/api/session_logic.rs +++ b/src/tests/api/session_logic.rs @@ -1,7 +1,8 @@ +use crate::api::server::server::ecdar_api_server::EcdarApi; use crate::api::server::server::GetAuthTokenRequest; use crate::api::{auth::TokenType, ecdar_api::handle_session}; use crate::entities::session; -use crate::tests::api::helpers::get_mock_services; +use crate::tests::api::helpers::{get_mock_concrete_ecdar_api, get_mock_services}; use mockall::predicate; use sea_orm::DbErr; use std::str::FromStr; @@ -134,3 +135,77 @@ async fn handle_session_no_session_exists_creates_session_returns_err() { assert_eq!(res.unwrap_err().code(), Code::Internal); } + +#[tokio::test] +async fn delete_session_returns_ok() { + let mut mock_services = get_mock_services(); + + mock_services + .session_context_mock + .expect_delete() + .with(predicate::eq(1)) + .returning(move |_| { + Ok(session::Model { + id: 1, + refresh_token: Default::default(), + access_token: "test_token".to_string(), + updated_at: Default::default(), + user_id: Default::default(), + }) + }); + + mock_services + .session_context_mock + .expect_get_by_token() + .with( + predicate::eq(TokenType::AccessToken), + predicate::eq("test_token".to_string()), + ) + .returning(move |_, _| { + Ok(Some(session::Model { + id: 1, + refresh_token: Default::default(), + access_token: "test_token".to_string(), + updated_at: Default::default(), + user_id: Default::default(), + })) + }); + + let api = get_mock_concrete_ecdar_api(mock_services); + + let mut request = Request::new(()); + request.metadata_mut().insert( + "authorization", + metadata::MetadataValue::from_str("Bearer test_token").unwrap(), + ); + + let res = api.delete_session(request).await; + + assert!(res.is_ok()); +} + +#[tokio::test] +async fn delete_session_no_session_returns_err() { + let mut mock_services = get_mock_services(); + + mock_services + .session_context_mock + .expect_get_by_token() + .with( + predicate::eq(TokenType::AccessToken), + predicate::eq("test_token".to_string()), + ) + .returning(move |_, _| Ok(None)); + + let api = get_mock_concrete_ecdar_api(mock_services); + + let mut request = Request::new(()); + request.metadata_mut().insert( + "authorization", + metadata::MetadataValue::from_str("Bearer test_token").unwrap(), + ); + + let res = api.delete_session(request).await; + + assert_eq!(res.unwrap_err().code(), Code::Unauthenticated); +} From a0be3d26426b2ff63777cd3279fc7f00bae321f3 Mon Sep 17 00:00:00 2001 From: sabotack Date: Wed, 6 Dec 2023 13:01:59 +0100 Subject: [PATCH 5/9] Merge session_context from GetUsers --- src/database/session_context.rs | 22 ++++++++++++++++++++++ 1 file changed, 22 insertions(+) diff --git a/src/database/session_context.rs b/src/database/session_context.rs index 4709fc2..28d111c 100644 --- a/src/database/session_context.rs +++ b/src/database/session_context.rs @@ -2,6 +2,7 @@ use crate::api::auth::TokenType; use crate::database::database_context::DatabaseContextTrait; use crate::database::entity_context::EntityContextTrait; use crate::entities::session; +use crate::entities::session::Model; use chrono::Local; use sea_orm::prelude::async_trait::async_trait; use sea_orm::ActiveValue::{Set, Unchanged}; @@ -19,6 +20,12 @@ pub trait SessionContextTrait: EntityContextTrait { token_type: TokenType, token: String, ) -> Result, DbErr>; + + async fn delete_by_token( + &self, + token_type: TokenType, + token: String, + ) -> Result; } #[async_trait] @@ -43,6 +50,21 @@ impl SessionContextTrait for SessionContext { } } } + + async fn delete_by_token(&self, token_type: TokenType, token: String) -> Result { + let session = self + .get_by_token(token_type, token) + .await? + .ok_or(DbErr::RecordNotFound( + "No session found with the provided access token".into(), + ))?; + + session::Entity::delete_by_id(session.id) + .exec(&self.db_context.get_connection()) + .await?; + + Ok(session) + } } impl SessionContext { From a6d9bd316869940526c3631ffacc8471c5eedb14 Mon Sep 17 00:00:00 2001 From: sabotack Date: Wed, 6 Dec 2023 13:12:43 +0100 Subject: [PATCH 6/9] Add delete_by_token method to test helpers --- src/tests/api/helpers.rs | 1 + 1 file changed, 1 insertion(+) diff --git a/src/tests/api/helpers.rs b/src/tests/api/helpers.rs index 9308f7b..ce651a6 100644 --- a/src/tests/api/helpers.rs +++ b/src/tests/api/helpers.rs @@ -146,6 +146,7 @@ mock! { #[async_trait] impl SessionContextTrait for SessionContext { async fn get_by_token(&self, token_type: TokenType, token: String) -> Result, DbErr>; + async fn delete_by_token(&self, token_type: TokenType, token: String) -> Result; } } From 082e7ec8708c6cf3ffd0e34869a020ab5da289d1 Mon Sep 17 00:00:00 2001 From: sabotack Date: Wed, 6 Dec 2023 13:13:58 +0100 Subject: [PATCH 7/9] Use delete_by_token instead --- src/api/ecdar_api.rs | 14 +++----------- src/tests/api/session_logic.rs | 32 +++++++++++--------------------- 2 files changed, 14 insertions(+), 32 deletions(-) diff --git a/src/api/ecdar_api.rs b/src/api/ecdar_api.rs index 7b485b0..bde439a 100644 --- a/src/api/ecdar_api.rs +++ b/src/api/ecdar_api.rs @@ -844,20 +844,12 @@ impl EcdarApi for ConcreteEcdarApi { .token_string() .ok_or(Status::unauthenticated("No access token provided"))?; - let session = self + match self .contexts .session_context - .get_by_token(TokenType::AccessToken, access_token) + .delete_by_token(TokenType::AccessToken, access_token) .await - .map_err(|err| Status::new(Code::Internal, err.to_string()))? - .ok_or_else(|| { - Status::new( - Code::Unauthenticated, - "No session found with given access token", - ) - })?; - - match self.contexts.session_context.delete(session.id).await { + { Ok(_) => Ok(Response::new(())), Err(error) => Err(Status::new(Code::Internal, error.to_string())), } diff --git a/src/tests/api/session_logic.rs b/src/tests/api/session_logic.rs index 589ea3d..161d9d5 100644 --- a/src/tests/api/session_logic.rs +++ b/src/tests/api/session_logic.rs @@ -7,7 +7,7 @@ use mockall::predicate; use sea_orm::DbErr; use std::str::FromStr; use std::sync::Arc; -use tonic::{metadata, Code, Request}; +use tonic::{metadata, Code, Request, Status}; #[tokio::test] async fn handle_session_updated_session_contains_correct_fields_returns_ok() { @@ -142,33 +142,19 @@ async fn delete_session_returns_ok() { mock_services .session_context_mock - .expect_delete() - .with(predicate::eq(1)) - .returning(move |_| { - Ok(session::Model { - id: 1, - refresh_token: Default::default(), - access_token: "test_token".to_string(), - updated_at: Default::default(), - user_id: Default::default(), - }) - }); - - mock_services - .session_context_mock - .expect_get_by_token() + .expect_delete_by_token() .with( predicate::eq(TokenType::AccessToken), predicate::eq("test_token".to_string()), ) .returning(move |_, _| { - Ok(Some(session::Model { + Ok(session::Model { id: 1, refresh_token: Default::default(), access_token: "test_token".to_string(), updated_at: Default::default(), user_id: Default::default(), - })) + }) }); let api = get_mock_concrete_ecdar_api(mock_services); @@ -190,12 +176,16 @@ async fn delete_session_no_session_returns_err() { mock_services .session_context_mock - .expect_get_by_token() + .expect_delete_by_token() .with( predicate::eq(TokenType::AccessToken), predicate::eq("test_token".to_string()), ) - .returning(move |_, _| Ok(None)); + .returning(move |_, _| { + Err(DbErr::RecordNotFound( + "No session found with the provided access token".to_string(), + )) + }); let api = get_mock_concrete_ecdar_api(mock_services); @@ -207,5 +197,5 @@ async fn delete_session_no_session_returns_err() { let res = api.delete_session(request).await; - assert_eq!(res.unwrap_err().code(), Code::Unauthenticated); + assert_eq!(res.unwrap_err().code(), Code::Internal); } From b5d23d2718f1e448a30ea36481474f90e1fd0ba0 Mon Sep 17 00:00:00 2001 From: sabotack Date: Wed, 6 Dec 2023 14:46:24 +0100 Subject: [PATCH 8/9] Remove unused import --- src/tests/api/session_logic.rs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/tests/api/session_logic.rs b/src/tests/api/session_logic.rs index 161d9d5..774dab2 100644 --- a/src/tests/api/session_logic.rs +++ b/src/tests/api/session_logic.rs @@ -7,7 +7,7 @@ use mockall::predicate; use sea_orm::DbErr; use std::str::FromStr; use std::sync::Arc; -use tonic::{metadata, Code, Request, Status}; +use tonic::{metadata, Code, Request}; #[tokio::test] async fn handle_session_updated_session_contains_correct_fields_returns_ok() { From d7bf4cc6994e39026df562efffed0ebf9b8e55f8 Mon Sep 17 00:00:00 2001 From: sabotack Date: Wed, 6 Dec 2023 14:50:45 +0100 Subject: [PATCH 9/9] Remove duplicate method definition --- src/api/ecdar_api.rs | 4 ---- 1 file changed, 4 deletions(-) diff --git a/src/api/ecdar_api.rs b/src/api/ecdar_api.rs index cc69ae7..61553d0 100644 --- a/src/api/ecdar_api.rs +++ b/src/api/ecdar_api.rs @@ -117,10 +117,6 @@ impl EcdarApi for ConcreteEcdarApi { todo!() } - async fn delete_session(&self, _request: Request<()>) -> Result, Status> { - todo!() - } - /// Gets a Model and its queries from the database. /// /// If the Model is not in use, it will now be in use by the requestees session,