Skip to content

Commit

Permalink
Update in use if not in use and if editor + tests fix and stuff
Browse files Browse the repository at this point in the history
  • Loading branch information
AlexanderManich committed Nov 29, 2023
1 parent 4dec063 commit c7f9c57
Show file tree
Hide file tree
Showing 6 changed files with 128 additions and 34 deletions.
53 changes: 45 additions & 8 deletions src/api/ecdar_api.rs
Original file line number Diff line number Diff line change
Expand Up @@ -16,13 +16,16 @@ use crate::api::{
server::server::Model,
};
use crate::database::{session_context::SessionContextTrait, user_context::UserContextTrait};
use crate::entities::{access, model, query, session, user};
use crate::entities::{access, in_use, model, query, session, user};
use chrono::{Duration, Utc};
use regex::Regex;
use sea_orm::SqlErr;
use serde_json;
use std::sync::Arc;
use tonic::{Code, Request, Response, Status};

const IN_USE_DURATION_MINUTES: i64 = 10;

#[derive(Clone)]
pub struct ConcreteEcdarApi {
contexts: ContextCollection,
Expand Down Expand Up @@ -58,7 +61,7 @@ pub async fn handle_session(
};
} else {
let mut session = match session_context
.get_by_refresh_token(request.token_string().unwrap())
.get_by_token(TokenType::RefreshToken, request.token_string().unwrap())
.await
{
Ok(Some(session)) => session,
Expand Down Expand Up @@ -114,7 +117,8 @@ impl EcdarApi for ConcreteEcdarApi {
.uid()
.ok_or(Status::internal("Could not get uid from request metadata"))?;

self.contexts
let access = self
.contexts
.access_context
.get_access_by_uid_and_model_id(uid, model_id)
.await
Expand All @@ -138,12 +142,45 @@ impl EcdarApi for ConcreteEcdarApi {
owner_id: model.owner_id,
};

let in_use = match self.contexts.in_use_context.get_by_id(model_id).await {
Ok(in_use) => {
matches!(in_use, Some(_in_use))
let mut in_use_bool = true;
match self.contexts.in_use_context.get_by_id(model_id).await {
Ok(Some(in_use)) => {
if in_use.latest_activity
<= (Utc::now().naive_utc() - Duration::minutes(IN_USE_DURATION_MINUTES))
{
in_use_bool = false;

if access.role == "Editor" {
let session = self
.contexts
.session_context
.get_by_token(TokenType::AccessToken, request.token_string().unwrap())
.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",
)
})?;

let in_use = in_use::Model {
model_id: in_use.model_id,
session_id: session.id,
latest_activity: Utc::now().naive_utc(),
};

self.contexts
.in_use_context
.update(in_use)
.await
.map_err(|err| Status::new(Code::Internal, err.to_string()))?;
}
}
}
Ok(None) => return Err(Status::new(Code::Internal, "No in use found for model")),
Err(err) => return Err(Status::new(Code::Internal, err.to_string())),
};
}

let queries = self
.contexts
Expand All @@ -169,7 +206,7 @@ impl EcdarApi for ConcreteEcdarApi {
Ok(Response::new(GetModelResponse {
model: Some(model),
queries,
in_use,
in_use: in_use_bool,
}))
}

Expand Down
36 changes: 24 additions & 12 deletions src/database/session_context.rs
Original file line number Diff line number Diff line change
@@ -1,35 +1,47 @@
use crate::api::auth::TokenType;
use crate::database::database_context::DatabaseContextTrait;
use crate::database::entity_context::EntityContextTrait;
use crate::entities::session;
use chrono::Local;
use sea_orm::prelude::async_trait::async_trait;
use sea_orm::ActiveValue::{Set, Unchanged};
use sea_orm::{ActiveModelTrait, ColumnTrait, DbErr, EntityTrait, NotSet, QueryFilter};
use std::sync::Arc;

use crate::database::database_context::DatabaseContextTrait;
use crate::database::entity_context::EntityContextTrait;
use crate::entities::session;

pub struct SessionContext {
db_context: Arc<dyn DatabaseContextTrait>,
}

#[async_trait]
pub trait SessionContextTrait: EntityContextTrait<session::Model> {
async fn get_by_refresh_token(
async fn get_by_token(
&self,
refresh_token: String,
token_type: TokenType,
token: String,
) -> Result<Option<session::Model>, DbErr>;
}

#[async_trait]
impl SessionContextTrait for SessionContext {
async fn get_by_refresh_token(
async fn get_by_token(
&self,
refresh_token: String,
token_type: TokenType,
token: String,
) -> Result<Option<session::Model>, DbErr> {
session::Entity::find()
.filter(session::Column::RefreshToken.eq(refresh_token))
.one(&self.db_context.get_connection())
.await
match token_type {
TokenType::AccessToken => {
session::Entity::find()
.filter(session::Column::AccessToken.eq(token))
.one(&self.db_context.get_connection())
.await
}
TokenType::RefreshToken => {
session::Entity::find()
.filter(session::Column::RefreshToken.eq(token))
.one(&self.db_context.get_connection())
.await
}
}
}
}

Expand Down
3 changes: 2 additions & 1 deletion src/tests/api/helpers.rs
Original file line number Diff line number Diff line change
@@ -1,5 +1,6 @@
#![cfg(test)]

use crate::api::auth::TokenType;
use crate::api::context_collection::ContextCollection;
use crate::api::ecdar_api::ConcreteEcdarApi;
use crate::api::hashing_context::HashingContextTrait;
Expand Down Expand Up @@ -150,7 +151,7 @@ mock! {
}
#[async_trait]
impl SessionContextTrait for SessionContext {
async fn get_by_refresh_token(&self, refresh_token: String) -> Result<Option<session::Model>, DbErr>;
async fn get_by_token(&self, token_type: TokenType, token: String) -> Result<Option<session::Model>, DbErr>;
}
}

Expand Down
55 changes: 48 additions & 7 deletions src/tests/api/model_logic.rs
Original file line number Diff line number Diff line change
@@ -1,9 +1,13 @@
use chrono::Utc;
use mockall::predicate;
use tonic::{Code, Request};

use crate::{
api::server::server::{ecdar_api_server::EcdarApi, GetModelRequest},
entities::{access, in_use, model, query},
api::{
auth::TokenType,
server::server::{ecdar_api_server::EcdarApi, GetModelRequest},
},
entities::{access, in_use, model, query, session},
tests::api::helpers::{get_mock_concrete_ecdar_api, get_mock_services},
};

Expand All @@ -28,7 +32,7 @@ async fn get_model_user_has_access_returns_ok() {
let in_use = in_use::Model {
model_id: Default::default(),
session_id: 0,
latest_activity: Default::default(),
latest_activity: Utc::now().naive_utc(),
};

let queries: Vec<query::Model> = vec![];
Expand Down Expand Up @@ -143,7 +147,7 @@ async fn get_model_is_in_use_is_true() {
let in_use = in_use::Model {
model_id: Default::default(),
session_id: 0,
latest_activity: Default::default(),
latest_activity: Utc::now().naive_utc(),
};

let queries: Vec<query::Model> = vec![];
Expand Down Expand Up @@ -201,6 +205,26 @@ async fn get_model_is_in_use_is_false() {
user_id: 1,
};

let in_use = in_use::Model {
model_id: 0,
session_id: 0,
latest_activity: Default::default(),
};

let updated_in_use = in_use::Model {
model_id: 0,
session_id: 1,
latest_activity: Default::default(),
};

let session = session::Model {
id: 0,
refresh_token: "refresh_token".to_owned(),
access_token: "access_token".to_owned(),
updated_at: Default::default(),
user_id: Default::default(),
};

let queries: Vec<query::Model> = vec![];

mock_services
Expand All @@ -219,16 +243,33 @@ async fn get_model_is_in_use_is_false() {
.in_use_context_mock
.expect_get_by_id()
.with(predicate::eq(0))
.returning(move |_| Ok(None));
.returning(move |_| Ok(Some(in_use.clone())));

mock_services
.session_context_mock
.expect_get_by_token()
.with(
predicate::eq(TokenType::AccessToken),
predicate::eq("access_token".to_owned()),
)
.returning(move |_, _| Ok(Some(session.clone())));

mock_services
.query_context_mock
.expect_get_all_by_model_id()
.with(predicate::eq(0))
.returning(move |_| Ok(queries.clone()));

mock_services
.in_use_context_mock
.expect_update()
.returning(move |_| Ok(updated_in_use.clone()));

let mut request = Request::new(GetModelRequest { id: 0 });

request
.metadata_mut()
.insert("authorization", "Bearer access_token".parse().unwrap());
request.metadata_mut().insert("uid", "0".parse().unwrap());

let api = get_mock_concrete_ecdar_api(mock_services);
Expand Down Expand Up @@ -259,7 +300,7 @@ async fn get_model_model_has_no_queries_queries_are_empty() {
let in_use = in_use::Model {
model_id: Default::default(),
session_id: 0,
latest_activity: Default::default(),
latest_activity: Utc::now().naive_utc(),
};

let queries: Vec<query::Model> = vec![];
Expand Down Expand Up @@ -320,7 +361,7 @@ async fn get_model_query_has_no_result_query_is_empty() {
let in_use = in_use::Model {
model_id: Default::default(),
session_id: 0,
latest_activity: Default::default(),
latest_activity: Utc::now().naive_utc(),
};

let query = query::Model {
Expand Down
11 changes: 7 additions & 4 deletions src/tests/api/session_logic.rs
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
use crate::api::ecdar_api::handle_session;
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 mockall::predicate;
Expand Down Expand Up @@ -30,9 +30,12 @@ async fn handle_session_updated_session_contains_correct_fields_returns_ok() {

mock_services
.session_context_mock
.expect_get_by_refresh_token()
.with(predicate::eq("old_refresh_token".to_string()))
.returning(move |_| Ok(Some(old_session.clone())));
.expect_get_by_token()
.with(
predicate::eq(TokenType::RefreshToken),
predicate::eq("old_refresh_token".to_string()),
)
.returning(move |_, _| Ok(Some(old_session.clone())));

mock_services
.session_context_mock
Expand Down
4 changes: 2 additions & 2 deletions src/tests/database/session_context.rs
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
use crate::tests::database::helpers::*;
use crate::{api::auth::TokenType, tests::database::helpers::*};
use sea_orm::{entity::prelude::*, IntoActiveModel};
use std::ops::Add;

Expand Down Expand Up @@ -350,7 +350,7 @@ async fn get_by_refresh_token_test() {
.unwrap();

let fetched_session = session_context
.get_by_refresh_token(session.refresh_token.clone())
.get_by_token(TokenType::RefreshToken, session.refresh_token.clone())
.await
.unwrap();

Expand Down

0 comments on commit c7f9c57

Please sign in to comment.