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

Commit

Permalink
Simple filters based on VEN names
Browse files Browse the repository at this point in the history
  • Loading branch information
pohlm01 committed Sep 4, 2024
1 parent 8f114a1 commit f4b4e67
Show file tree
Hide file tree
Showing 5 changed files with 80 additions and 56 deletions.
18 changes: 11 additions & 7 deletions fixtures/programs.sql
Original file line number Diff line number Diff line change
Expand Up @@ -27,15 +27,19 @@ VALUES ('program-1',
'{
"start": "2024-07-25T08:31:10.776Z"
}',
'[{
"URL": "https://program-description-1.com"
}]',
'[
{
"URL": "https://program-description-1.com"
}
]',
false,
true,
'[{
"objectType": "EVENT_PAYLOAD_DESCRIPTOR",
"payloadType": "EXPORT_PRICE"
}]',
'[
{
"objectType": "EVENT_PAYLOAD_DESCRIPTOR",
"payloadType": "EXPORT_PRICE"
}
]',
'[
{
"type": "GROUP",
Expand Down
40 changes: 28 additions & 12 deletions openadr-vtn/src/data_source/postgres/event.rs
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
use crate::api::event::QueryParams;
use crate::data_source::postgres::{to_json_value, PgTargetsFilter};
use crate::data_source::postgres::{to_json_value, PgPermissionFilter, PgTargetsFilter};
use crate::data_source::{Crud, EventCrud};
use crate::error::AppError;
use crate::jwt::Claims;
Expand All @@ -10,7 +10,7 @@ use openadr_wire::target::TargetLabel;
use openadr_wire::Event;
use sqlx::PgPool;
use std::str::FromStr;
use tracing::error;
use tracing::{error, trace};

#[async_trait]
impl EventCrud for PgEventStorage {}
Expand Down Expand Up @@ -142,7 +142,7 @@ impl<'a> From<&'a QueryParams> for PostgresFilter<'a> {
.iter()
.map(|value| PgTargetsFilter {
label: label.as_str(),
value: [value.as_str()],
value: [value.clone()],
})
.collect()
}
Expand Down Expand Up @@ -193,14 +193,24 @@ impl Crud for PgEventStorage {
async fn retrieve(
&self,
id: &Self::Id,
_user: &Self::PermissionFilter,
user: &Self::PermissionFilter,
) -> Result<Self::Type, Self::Error> {
let permission_filter: PgPermissionFilter = user.into();
trace!(?permission_filter);

Ok(sqlx::query_as!(
PostgresEvent,
r#"
SELECT * FROM event WHERE id = $1
SELECT e.*
FROM event e
JOIN program p ON e.program_id = p.id
WHERE e.id = $1
AND (p.targets IS NULL OR $2::jsonb <@ p.targets) -- Filter for VEN ids
AND (e.targets IS NULL OR $2::jsonb <@ e.targets) -- Filter for VEN ids
"#,
id.as_str()
id.as_str(),
serde_json::to_value(permission_filter.ven_ids)
.map_err(AppError::SerdeJsonInternalServerError)?
)
.fetch_one(&self.db)
.await?
Expand All @@ -210,9 +220,13 @@ impl Crud for PgEventStorage {
async fn retrieve_all(
&self,
filter: &Self::Filter,
_user: &Self::PermissionFilter,
user: &Self::PermissionFilter,
) -> Result<Vec<Self::Type>, Self::Error> {
let pg_filter: PostgresFilter = filter.into();
trace!(?pg_filter);

let permission_filter: PgPermissionFilter = user.into();
trace!(?permission_filter);

Ok(sqlx::query_as!(
PostgresEvent,
Expand All @@ -221,18 +235,20 @@ impl Crud for PgEventStorage {
FROM event e
JOIN program p on p.id = e.program_id
WHERE ($1::text IS NULL OR program_id like $1)
AND ($2::text[] IS NULL OR TRUE) -- TODO filter for ven_names
AND ($3::text[] IS NULL OR event_name = ANY($3))
AND ($4::text[] IS NULL OR p.program_name = ANY($4))
AND ($5::jsonb = '[]'::jsonb OR $5::jsonb <@ e.targets)
AND ($2::text[] IS NULL OR event_name = ANY($2))
AND ($3::text[] IS NULL OR p.program_name = ANY($3))
AND ($4::jsonb = '[]'::jsonb OR $4::jsonb <@ e.targets)
AND (p.targets IS NULL OR $5::jsonb <@ p.targets) -- Filter for VEN ids
AND (e.targets IS NULL OR $5::jsonb <@ e.targets) -- Filter for VEN ids
OFFSET $6 LIMIT $7
"#,
pg_filter.program_id,
pg_filter.ven_names,
pg_filter.event_names,
pg_filter.program_names,
serde_json::to_value(pg_filter.targets)
.map_err(AppError::SerdeJsonInternalServerError)?,
serde_json::to_value(permission_filter.ven_ids)
.map_err(AppError::SerdeJsonInternalServerError)?,
pg_filter.skip,
pg_filter.limit
)
Expand Down
24 changes: 23 additions & 1 deletion openadr-vtn/src/data_source/postgres/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -4,7 +4,9 @@ use crate::data_source::postgres::report::PgReportStorage;
use crate::data_source::postgres::user::PgAuthSource;
use crate::data_source::{AuthSource, DataSource, EventCrud, ProgramCrud, ReportCrud};
use crate::error::AppError;
use crate::jwt::Claims;
use dotenvy::dotenv;
use openadr_wire::target::TargetLabel;
use serde::Serialize;
use sqlx::PgPool;
use std::sync::Arc;
Expand Down Expand Up @@ -79,5 +81,25 @@ struct PgTargetsFilter<'a> {
#[serde(rename = "type")]
label: &'a str,
#[serde(rename = "values")]
value: [&'a str; 1],
value: [String; 1],
}

#[derive(Debug)]
struct PgPermissionFilter<'a> {
ven_ids: Vec<PgTargetsFilter<'a>>,
}

impl From<&Claims> for PgPermissionFilter<'_> {
fn from(claims: &Claims) -> Self {
Self {
ven_ids: claims
.ven_ids()
.into_iter()
.map(|ven_id| PgTargetsFilter {
label: TargetLabel::VENName.as_str(),
value: [ven_id],
})
.collect(),
}
}
}
52 changes: 17 additions & 35 deletions openadr-vtn/src/data_source/postgres/program.rs
Original file line number Diff line number Diff line change
@@ -1,8 +1,8 @@
use crate::api::program::QueryParams;
use crate::data_source::postgres::{to_json_value, PgTargetsFilter};
use crate::data_source::postgres::{to_json_value, PgPermissionFilter, PgTargetsFilter};
use crate::data_source::{Crud, ProgramCrud};
use crate::error::AppError;
use crate::jwt::{BusinessIds, Claims};
use crate::jwt::Claims;
use axum::async_trait;
use chrono::{DateTime, Utc};
use openadr_wire::program::{ProgramContent, ProgramId};
Expand Down Expand Up @@ -129,26 +129,6 @@ struct PostgresFilter<'a> {
limit: i64,
}

#[derive(Debug)]
struct PgPermissionFilter {
business_ids: Option<Vec<String>>,
ven_ids: Vec<String>,
}

impl From<&Claims> for PgPermissionFilter {
fn from(claims: &Claims) -> Self {
let business_ids = match claims.business_ids() {
BusinessIds::Specific(v) => Some(v),
BusinessIds::Any => None,
};

Self {
business_ids,
ven_ids: claims.ven_ids(),
}
}
}

impl<'a> From<&'a QueryParams> for PostgresFilter<'a> {
fn from(query: &'a QueryParams) -> Self {
let mut filter = Self {
Expand All @@ -166,7 +146,7 @@ impl<'a> From<&'a QueryParams> for PostgresFilter<'a> {
.iter()
.map(|value| PgTargetsFilter {
label: label.as_str(),
value: [value.as_str()],
value: [value.clone()],
})
.collect()
}
Expand Down Expand Up @@ -230,15 +210,13 @@ impl Crud for PgProgramStorage {
PostgresProgram,
r#"
SELECT *
FROM program p
FROM program
WHERE id = $1
AND (
((jsonb_path_query_array(p.targets, '$[*].type') ? 'VEN_NAME')
AND ($2::text[] IS NULL OR jsonb_path_query_array(p.targets, '$[*].values[*]') ?| ($2)))
OR jsonb_path_query_array(p.targets, '$[*].type') ? 'VEN_NAME') IS NOT TRUE
AND (targets IS NULL OR $2::jsonb <@ targets) -- Filter for VEN ids
"#,
id.as_str(),
permission_filter.ven_ids.as_slice()
serde_json::to_value(permission_filter.ven_ids)
.map_err(AppError::SerdeJsonInternalServerError)?
)
.fetch_one(&self.db)
.await?
Expand All @@ -248,11 +226,14 @@ impl Crud for PgProgramStorage {
async fn retrieve_all(
&self,
filter: &Self::Filter,
_user: &Self::PermissionFilter,
user: &Self::PermissionFilter,
) -> Result<Vec<Self::Type>, Self::Error> {
let pg_filter: PostgresFilter = filter.into();
trace!(?pg_filter);

let permission_filter: PgPermissionFilter = user.into();
trace!(?permission_filter);

Ok(sqlx::query_as!(
PostgresProgram,
r#"
Expand All @@ -274,17 +255,18 @@ impl Crud for PgProgramStorage {
p.targets
FROM program p
LEFT JOIN event e on p.id = e.program_id
WHERE ($1::text[] IS NULL OR TRUE) -- TODO implement filtering based on VEN names
AND ($2::text[] IS NULL OR e.event_name = ANY($2))
AND ($3::text[] IS NULL OR p.program_name = ANY($3))
AND ($4::jsonb = '[]'::jsonb OR $4::jsonb <@ p.targets)
WHERE ($1::text[] IS NULL OR e.event_name = ANY($1))
AND ($2::text[] IS NULL OR p.program_name = ANY($2))
AND ($3::jsonb = '[]'::jsonb OR $3::jsonb <@ p.targets)
AND (p.targets IS NULL OR $4::jsonb <@ p.targets) -- Filter for VEN ids
OFFSET $5 LIMIT $6
"#,
pg_filter.ven_names,
pg_filter.event_names,
pg_filter.program_names,
serde_json::to_value(pg_filter.targets)
.map_err(AppError::SerdeJsonInternalServerError)?,
serde_json::to_value(permission_filter.ven_ids)
.map_err(AppError::SerdeJsonInternalServerError)?,
pg_filter.skip,
pg_filter.limit,
)
Expand Down
2 changes: 1 addition & 1 deletion openadr-wire/src/report.rs
Original file line number Diff line number Diff line change
Expand Up @@ -141,8 +141,8 @@ impl Resource {
/// An object that may be used to request a report from a VEN. See OpenADR REST User Guide for
/// detailed description of how configure a report request.
// TODO: replace "-1 means" with proper enum
#[derive(Clone, Debug, PartialEq, Serialize, Deserialize)]
#[skip_serializing_none]
#[derive(Clone, Debug, PartialEq, Serialize, Deserialize)]
#[serde(rename_all = "camelCase")]
pub struct ReportDescriptor {
/// Enumerated or private string signifying the nature of values.
Expand Down

0 comments on commit f4b4e67

Please sign in to comment.