Skip to content

Commit

Permalink
Merge branch 'main' into 18-update-model-endpoint
Browse files Browse the repository at this point in the history
  • Loading branch information
sabotack committed Nov 29, 2023
2 parents a3eaa21 + c61116c commit bf58e41
Show file tree
Hide file tree
Showing 3 changed files with 181 additions and 14 deletions.
56 changes: 51 additions & 5 deletions src/api/ecdar_api.rs
Original file line number Diff line number Diff line change
Expand Up @@ -124,17 +124,63 @@ impl EcdarApi for ConcreteEcdarApi {
None => return Err(Status::invalid_argument("No components info provided")),
};

let model = model::Model {
let mut model = model::Model {
id: Default::default(),
name: message.clone().name,
components_info,
owner_id: uid,
};

match self.contexts.model_context.create(model).await {
Ok(model) => Ok(Response::new(CreateModelResponse { id: model.id })),
Err(error) => Err(Status::internal(error.to_string())),
}
model = match self.contexts.model_context.create(model).await {
Ok(model) => model,
Err(error) => {
return match error.sql_err() {
Some(SqlErr::UniqueConstraintViolation(e)) => {
let error_msg = match e.to_lowercase() {
_ if e.contains("name") => "A model with that name already exists",
_ => "Model already exists",
};
println!("{}", e);
Err(Status::already_exists(error_msg))
}
Some(SqlErr::ForeignKeyConstraintViolation(e)) => {
let error_msg = match e.to_lowercase() {
_ if e.contains("owner_id") => "No user with that id exists",
_ => "Could not create model",
};
println!("{}", e);
Err(Status::invalid_argument(error_msg))
}
_ => Err(Status::internal(error.to_string())),
};
}
};

let access = access::Model {
id: Default::default(),
role: "Editor".to_string(), //todo!("Use role enum")
model_id: model.clone().id,
user_id: uid,
};

let session = self
.contexts
.session_context
.get_by_token(TokenType::AccessToken, request.token_string().unwrap())
.await
.unwrap()
.unwrap();

let in_use = in_use::Model {
model_id: model.clone().id,
session_id: session.id,
latest_activity: Default::default(),
};

self.contexts.in_use_context.create(in_use).await.unwrap();
self.contexts.access_context.create(access).await.unwrap();

Ok(Response::new(CreateModelResponse { id: model.id }))
}

/// Updates a Model in the database given its id.
Expand Down
1 change: 1 addition & 0 deletions src/database/model_context.rs
Original file line number Diff line number Diff line change
Expand Up @@ -45,6 +45,7 @@ impl ModelContext {
ModelContext { db_context }
}
}

#[async_trait]
impl EntityContextTrait<model::Model> for ModelContext {
/// Used for creating a model::Model entity
Expand Down
138 changes: 129 additions & 9 deletions src/tests/api/model_logic.rs
Original file line number Diff line number Diff line change
Expand Up @@ -2,18 +2,138 @@ use std::str::FromStr;

use chrono::Utc;
use mockall::predicate;
use sea_orm::DbErr;
use tonic::{metadata, Code, Request};

use crate::{
api::{
auth::TokenType,
server::server::{
ecdar_api_server::EcdarApi, DeleteModelRequest, ModelInfo, UpdateModelRequest,
},
},
entities::{access, in_use, model, session},
tests::api::helpers::{get_mock_concrete_ecdar_api, get_mock_services},
use crate::api::auth::TokenType;
use crate::api::server::server::UpdateModelRequest;
use crate::api::server::server::{
ecdar_api_server::EcdarApi, ComponentsInfo, CreateModelRequest, DeleteModelRequest, ModelInfo,
};
use crate::entities::{access, in_use, model, session};
use crate::tests::api::helpers::{get_mock_concrete_ecdar_api, get_mock_services};

#[tokio::test]
async fn create_model_returns_ok() {
let mut mock_services = get_mock_services();

let uid = 0;

let components_info = ComponentsInfo {
components: vec![],
components_hash: 0,
};

let model = model::Model {
id: Default::default(),
name: Default::default(),
components_info: serde_json::to_value(components_info.clone()).unwrap(),
owner_id: uid,
};

let access = access::Model {
id: Default::default(),
role: "Editor".to_string(),
user_id: uid,
model_id: model.id,
};

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

let in_use = in_use::Model {
model_id: model.id,
session_id: session.id,
latest_activity: Default::default(),
};

mock_services
.model_context_mock
.expect_create()
.with(predicate::eq(model.clone()))
.returning(move |_| Ok(model.clone()));

mock_services
.access_context_mock
.expect_create()
.with(predicate::eq(access.clone()))
.returning(move |_| Ok(access.clone()));

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

mock_services
.in_use_context_mock
.expect_create()
.with(predicate::eq(in_use.clone()))
.returning(move |_| Ok(in_use.clone()));

let mut request = Request::new(CreateModelRequest {
name: Default::default(),
components_info: Option::from(components_info),
});

request
.metadata_mut()
.insert("uid", uid.to_string().parse().unwrap());

request.metadata_mut().insert(
"authorization",
metadata::MetadataValue::from_str("Bearer access_token").unwrap(),
);

let api = get_mock_concrete_ecdar_api(mock_services);

let res = api.create_model(request).await;

assert!(res.is_ok());
}

#[tokio::test]
async fn create_model_existing_name_returns_err() {
let mut mock_services = get_mock_services();

let uid = 0;

let model = model::Model {
id: Default::default(),
name: "model".to_string(),
components_info: Default::default(),
owner_id: uid,
};

mock_services
.model_context_mock
.expect_create()
.with(predicate::eq(model.clone()))
.returning(move |_| Err(DbErr::RecordNotInserted)); //todo!("Needs to be a SqlError with UniqueConstraintViolation with 'name' in message)

let mut request = Request::new(CreateModelRequest {
name: "model".to_string(),
components_info: Default::default(),
});

request
.metadata_mut()
.insert("uid", uid.to_string().parse().unwrap());

let api = get_mock_concrete_ecdar_api(mock_services);

let res = api.create_model(request).await;

assert_eq!(res.unwrap_err().code(), Code::InvalidArgument); //todo!("Needs to be code AlreadyExists when mocked Error is corrected)
}

#[tokio::test]
async fn delete_not_owner_returns_err() {
Expand Down

0 comments on commit bf58e41

Please sign in to comment.