Skip to content
This repository has been archived by the owner on Oct 3, 2024. It is now read-only.

Commit

Permalink
WIP ven tests
Browse files Browse the repository at this point in the history
  • Loading branch information
marlonbaeten committed Sep 24, 2024
1 parent 8703336 commit c9749a3
Show file tree
Hide file tree
Showing 5 changed files with 153 additions and 34 deletions.
84 changes: 78 additions & 6 deletions openadr-vtn/src/api/ven.rs
Original file line number Diff line number Diff line change
Expand Up @@ -24,11 +24,11 @@ use crate::{
pub async fn get_all(
State(ven_source): State<Arc<dyn VenCrud>>,
ValidatedQuery(query_params): ValidatedQuery<QueryParams>,
VenManagerUser(user): VenManagerUser,
User(user): User,
) -> AppResponse<Vec<Ven>> {
trace!(?query_params);

let vens = ven_source.retrieve_all(&query_params, &user).await?;
let vens = ven_source.retrieve_all(&query_params, &user.try_into()?).await?;

Ok(Json(vens))
}
Expand All @@ -46,7 +46,7 @@ pub async fn get(
return Err(AppError::Forbidden("User is not a VEN or VEN Manager"));
}

let ven = ven_source.retrieve(&id, &user).await?;
let ven = ven_source.retrieve(&id, &user.try_into()?).await?;

Ok(Json(ven))
}
Expand All @@ -56,7 +56,7 @@ pub async fn add(
VenManagerUser(user): VenManagerUser,
ValidatedJson(new_ven): ValidatedJson<VenContent>,
) -> Result<(StatusCode, Json<Ven>), AppError> {
let ven = ven_source.create(new_ven, &user).await?;
let ven = ven_source.create(new_ven, &user.try_into()?).await?;

Ok((StatusCode::CREATED, Json(ven)))
}
Expand All @@ -67,7 +67,7 @@ pub async fn edit(
VenManagerUser(user): VenManagerUser,
ValidatedJson(content): ValidatedJson<VenContent>,
) -> AppResponse<Ven> {
let ven = ven_source.update(&id, content, &user).await?;
let ven = ven_source.update(&id, content, &user.try_into()?).await?;

info!(%ven.id, ven.ven_name=ven.content.ven_name, "ven updated");

Expand All @@ -79,7 +79,7 @@ pub async fn delete(
Path(id): Path<VenId>,
VenManagerUser(user): VenManagerUser,
) -> AppResponse<Ven> {
let ven = ven_source.delete(&id, &user).await?;
let ven = ven_source.delete(&id, &user.try_into()?).await?;
info!(%id, "deleted ven");
Ok(Json(ven))
}
Expand Down Expand Up @@ -109,3 +109,75 @@ fn validate_target_type_value_pair(query: &QueryParams) -> Result<(), Validation
fn get_50() -> i64 {
50
}

#[cfg(test)]
mod tests {
use axum::{body::Body, http::{self, Request, Response}, Router};
use http_body_util::BodyExt;
use openadr_wire::Ven;
use serde::de::DeserializeOwned;
use sqlx::PgPool;
use tower::ServiceExt;

use crate::{api::test::jwt_test_token, data_source::PostgresStorage, jwt::{AuthRole, JwtManager}, state::AppState};

async fn request_all(
app: Router,
token: &str,
) -> Response<Body> {
app.oneshot(
Request::builder()
.method(http::Method::GET)
.uri("/vens")
.header(http::header::AUTHORIZATION, format!("Bearer {}", token))
.header(http::header::CONTENT_TYPE, mime::APPLICATION_JSON.as_ref())
.body(Body::empty())
.unwrap()
).await.unwrap()
}

async fn get_response_json<T: DeserializeOwned>(response: Response<Body>) -> T {
let body = response.into_body().collect().await.unwrap().to_bytes();

serde_json::from_slice(&body).unwrap()
}

fn test_state(db: PgPool) -> AppState {
let store = PostgresStorage::new(db).unwrap();
let jwt_manager = JwtManager::from_base64_secret("test").unwrap();

AppState::new(store, jwt_manager)
}

#[sqlx::test(fixtures("users", "vens"))]
async fn get_all_unfiletred(db: PgPool) {
let state = test_state(db);
let token = jwt_test_token(&state, vec![AuthRole::VenManager]);
let app = state.into_router();

let resp = request_all(app, &token).await;

assert_eq!(resp.status(), http::StatusCode::OK);
let vens: Vec<Ven> = get_response_json(resp).await;

assert_eq!(vens.len(), 2);
assert_eq!(vens[0].id.as_str(), "ven-2");
assert_eq!(vens[1].id.as_str(), "ven-1");
}


#[sqlx::test(fixtures("users", "vens"))]
async fn get_all_ven_user(db: PgPool) {
let state = test_state(db);
let token = jwt_test_token(&state, vec![AuthRole::VEN("ven-1".parse().unwrap())]);
let app = state.into_router();

let resp = request_all(app, &token).await;

assert_eq!(resp.status(), http::StatusCode::OK);
let vens: Vec<Ven> = get_response_json(resp).await;

assert_eq!(vens.len(), 1);
assert_eq!(vens[0].id.as_str(), "ven-1");
}
}
32 changes: 31 additions & 1 deletion openadr-vtn/src/data_source/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -133,14 +133,44 @@ pub trait EventCrud:
{
}


pub enum VenPermissions {
AllAllowed,
Specific(Vec<VenId>),
}

impl VenPermissions {
pub fn as_value(&self) -> Option<Vec<String>> {
match self {
VenPermissions::AllAllowed => None,
VenPermissions::Specific(ids) => Some(ids.iter().map(|id| id.to_string()).collect::<Vec<_>>()),
}
}
}


impl TryFrom<Claims> for VenPermissions {
type Error = AppError;

fn try_from(claims: Claims) -> Result<Self, Self::Error> {
if claims.is_ven_manager() {
Ok(VenPermissions::AllAllowed)
} else if claims.is_ven() {
Ok(VenPermissions::Specific(claims.ven_ids()))
} else {
Err(AppError::Forbidden("User not authorized to access this vens"))
}
}
}

pub trait VenCrud:
Crud<
Type = Ven,
Id = VenId,
NewType = VenContent,
Error = AppError,
Filter = crate::api::ven::QueryParams,
PermissionFilter = Claims,
PermissionFilter = VenPermissions,
>
{
}
Expand Down
1 change: 1 addition & 0 deletions openadr-vtn/src/data_source/postgres/resource.rs
Original file line number Diff line number Diff line change
Expand Up @@ -341,3 +341,4 @@ impl PgResourceStorage {
.collect::<Result<_, _>>()
}
}

Loading

0 comments on commit c9749a3

Please sign in to comment.