Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Implement delete session endpoint + tests #77

Merged
merged 10 commits into from
Dec 6, 2023
23 changes: 19 additions & 4 deletions src/api/ecdar_api.rs
Original file line number Diff line number Diff line change
Expand Up @@ -117,10 +117,6 @@ impl EcdarApi for ConcreteEcdarApi {
todo!()
}

async fn delete_session(&self, _request: Request<()>) -> Result<Response<()>, 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,
Expand Down Expand Up @@ -1022,6 +1018,25 @@ 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<Response<()>, Status> {
let access_token = request
.token_string()
.ok_or(Status::unauthenticated("No access token provided"))?;

match self
.contexts
.session_context
.delete_by_token(TokenType::AccessToken, access_token)
.await
{
Ok(_) => Ok(Response::new(())),
Err(error) => Err(Status::new(Code::Internal, error.to_string())),
}
}
}

async fn check_editor_role_helper(
Expand Down
22 changes: 22 additions & 0 deletions src/database/session_context.rs
Original file line number Diff line number Diff line change
Expand Up @@ -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};
Expand All @@ -19,6 +20,12 @@ pub trait SessionContextTrait: EntityContextTrait<session::Model> {
token_type: TokenType,
token: String,
) -> Result<Option<session::Model>, DbErr>;

async fn delete_by_token(
&self,
token_type: TokenType,
token: String,
) -> Result<session::Model, DbErr>;
}

#[async_trait]
Expand All @@ -43,6 +50,21 @@ impl SessionContextTrait for SessionContext {
}
}
}

async fn delete_by_token(&self, token_type: TokenType, token: String) -> Result<Model, DbErr> {
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 {
Expand Down
1 change: 1 addition & 0 deletions src/tests/api/helpers.rs
Original file line number Diff line number Diff line change
Expand Up @@ -162,6 +162,7 @@ mock! {
#[async_trait]
impl SessionContextTrait for SessionContext {
async fn get_by_token(&self, token_type: TokenType, token: String) -> Result<Option<session::Model>, DbErr>;
async fn delete_by_token(&self, token_type: TokenType, token: String) -> Result<session::Model, DbErr>;
}
}

Expand Down
67 changes: 66 additions & 1 deletion src/tests/api/session_logic.rs
Original file line number Diff line number Diff line change
@@ -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;
Expand Down Expand Up @@ -134,3 +135,67 @@ 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_by_token()
.with(
predicate::eq(TokenType::AccessToken),
predicate::eq("test_token".to_string()),
)
.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(),
})
});

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_delete_by_token()
.with(
predicate::eq(TokenType::AccessToken),
predicate::eq("test_token".to_string()),
)
.returning(move |_, _| {
Err(DbErr::RecordNotFound(
"No session found with the provided access token".to_string(),
))
});

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::Internal);
}
Loading