Skip to content

Commit

Permalink
Add client support for VENs and Resources (#35)
Browse files Browse the repository at this point in the history
* Add client support for VENs and Resources

and centralize pagination iteration

Signed-off-by: Maximilian Pohl <[email protected]>

* Restructure client integration tests

Signed-off-by: Maximilian Pohl <[email protected]>

* Add db independent integration tests for VEN in client lib

Signed-off-by: Maximilian Pohl <[email protected]>

* Add resource integration tests

Signed-off-by: Maximilian Pohl <[email protected]>

* Active ignored tests

Signed-off-by: Maximilian Pohl <[email protected]>

---------

Signed-off-by: Maximilian Pohl <[email protected]>
  • Loading branch information
pohlm01 authored Oct 28, 2024
1 parent da1c536 commit 8ca5546
Show file tree
Hide file tree
Showing 32 changed files with 1,028 additions and 474 deletions.
5 changes: 3 additions & 2 deletions .github/workflows/checks.yml
Original file line number Diff line number Diff line change
Expand Up @@ -68,8 +68,9 @@ jobs:
run: |
docker compose up db --wait && \
cargo install sqlx-cli --no-default-features --features rustls,postgres && \
cargo sqlx migrate run --source openadr-vtn/migrations
cargo sqlx migrate run --source openadr-vtn/migrations && \
psql -U openadr -h localhost openadr < fixtures/test_user_credentials.sql
- name: cargo build
run: cargo build ${{ matrix.features }}

Expand Down
58 changes: 58 additions & 0 deletions Cargo.lock

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

2 changes: 2 additions & 0 deletions Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -59,3 +59,5 @@ quickcheck = "1.0.3"
sqlx = { version = "0.8.2", features = ["postgres", "runtime-tokio", "chrono", "migrate", "macros", "json"], default-features = false }
argon2 = "0.5.3"
dotenvy = "0.15.7"

serial_test = "3.1.1"
90 changes: 90 additions & 0 deletions fixtures/test_user_credentials.sql
Original file line number Diff line number Diff line change
@@ -0,0 +1,90 @@
-- create users
INSERT INTO "user" (id, reference, description, created, modified)
VALUES ('ven-manager',
'ven-manager',
'for automated test cases',
now(),
now());

INSERT INTO "user" (id, reference, description, created, modified)
VALUES ('user-manager',
'user-manager',
'for automated test cases',
now(),
now());

INSERT INTO "user" (id, reference, description, created, modified)
VALUES ('any-business',
'any-business',
'for automated test cases',
now(),
now());

INSERT INTO "user" (id, reference, description, created, modified)
VALUES ('business-1-user',
'business-1-user',
'for automated test cases',
now(),
now());

INSERT INTO "user" (id, reference, description, created, modified)
VALUES ('ven-1-user',
'ven-1-user',
'for automated test cases',
now(),
now());

-- associate roles to users
INSERT INTO ven_manager (user_id)
VALUES ('ven-manager');
INSERT INTO user_manager (user_id)
VALUES ('user-manager');
INSERT INTO any_business_user (user_id)
VALUES ('any-business');

INSERT INTO business (id)
VALUES ('business-1');
INSERT INTO user_business (user_id, business_id)
VALUES ('business-1-user', 'business-1');

INSERT INTO ven (id, created_date_time, modification_date_time, ven_name, attributes, targets)
VALUES ('ven-1',
now(),
now(),
'ven-1-name',
null,
null);

INSERT INTO user_ven (ven_id, user_id)
VALUES ('ven-1', 'ven-1-user');

-- create login credentials
INSERT INTO user_credentials (user_id, client_id, client_secret)
VALUES ('ven-manager',
'ven-manager',
--ven-manager
'$argon2id$v=19$m=16,t=2,p=1$NGxoR0w0MG1oQVhTNTlWYw$NaIKUON6vrNcM2jXzqwX5Q');

INSERT INTO user_credentials (user_id, client_id, client_secret)
VALUES ('user-manager',
'user-manager',
--user-manager
'$argon2id$v=19$m=16,t=2,p=1$eDRuSHFPUG16M09JNGo5WQ$LjaFZJVr2Qpna45k51yuhw');

INSERT INTO user_credentials (user_id, client_id, client_secret)
VALUES ('any-business',
'any-business',
--any-business
'$argon2id$v=19$m=16,t=2,p=1$WWJENTVTbEpYZkFjdlhOUQ$UXEQI8OPlnbtXwStitu6Vw');

INSERT INTO user_credentials (user_id, client_id, client_secret)
VALUES ('business-1-user',
'business-1',
--business-1
'$argon2id$v=19$m=16,t=2,p=1$bVlaZTI4QndaaERNa1Q5bg$0IjdRSjo601S9vHICOLRdQ');

INSERT INTO user_credentials (user_id, client_id, client_secret)
VALUES ('ven-1-user',
'ven-1',
--ven-1
'$argon2id$v=19$m=16,t=2,p=1$WGpkRFZGampQM0N3S0ZZVw$lO3AhXZYKu/Wsk3Z1NE/Aw');
6 changes: 5 additions & 1 deletion migrations/20240826084440_initial_scheme.sql
Original file line number Diff line number Diff line change
Expand Up @@ -118,13 +118,17 @@ create table resource
primary key,
created_date_time timestamptz not null,
modification_date_time timestamptz not null,
resource_name text not null unique,
resource_name text not null,
ven_id text not null references ven (id), -- TODO is this actually 'NOT NULL'?
attributes jsonb,
targets jsonb

);

create unique index resource_ven_id_resource_name_uindex
on resource (ven_id, resource_name);


create table ven_program
(
program_id text not null references program (id) on delete cascade,
Expand Down
1 change: 1 addition & 0 deletions openadr-client/.env
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
DATABASE_URL=postgres://openadr@localhost/openadr
4 changes: 3 additions & 1 deletion openadr-client/Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -32,4 +32,6 @@ uuid.workspace = true
tokio = { workspace = true, features = ["full", "test-util"] }
openadr-vtn = { path = "../openadr-vtn", features = ["postgres"] }
mime.workspace = true
sqlx.workspace = true
sqlx.workspace = true
serial_test.workspace = true
dotenvy.workspace = true
2 changes: 1 addition & 1 deletion openadr-client/src/bin/cli.rs
Original file line number Diff line number Diff line change
Expand Up @@ -13,7 +13,7 @@ async fn main() -> Result<(), Box<dyn std::error::Error>> {
// let created_event = program
// .create_event(program.new_event().with_event_name("prices3").with_priority(0))
// .await?;
// let events = program.get_all_events().await?;
// let events = program.get_event_list(Filter::None).await?;
// let reports = events[0].get_all_reports().await?;
// let event = program.get_event(Target::Event("prices3")).await?;
// dbg!(events);
Expand Down
22 changes: 22 additions & 0 deletions openadr-client/src/error.rs
Original file line number Diff line number Diff line change
@@ -1,3 +1,5 @@
use reqwest::StatusCode;

/// Errors that can occur using the [`Client`](crate::Client)
#[derive(Debug)]
pub enum Error {
Expand All @@ -13,6 +15,26 @@ pub enum Error {
InvalidInterval,
}

impl Error {
pub fn is_conflict(&self) -> bool {
match self {
Error::Problem(openadr_wire::problem::Problem { status, .. }) => {
*status == StatusCode::CONFLICT
}
_ => false,
}
}

pub fn is_not_found(&self) -> bool {
match self {
Error::Problem(openadr_wire::problem::Problem { status, .. }) => {
*status == StatusCode::NOT_FOUND
}
_ => false,
}
}
}

impl From<reqwest::Error> for Error {
fn from(err: reqwest::Error) -> Self {
Error::Reqwest(err)
Expand Down
58 changes: 8 additions & 50 deletions openadr-client/src/event.rs
Original file line number Diff line number Diff line change
Expand Up @@ -46,11 +46,10 @@ impl EventClient {

/// Save any modifications of the event to the VTN
pub async fn update(&mut self) -> Result<()> {
let res = self
self.data = self
.client
.put(&format!("events/{}", self.id()), &self.data.content, &[])
.await?;
self.data = res;
Ok(())
}

Expand All @@ -62,12 +61,12 @@ impl EventClient {
}

/// Create a new report object
pub fn new_report(&self) -> ReportContent {
pub fn new_report(&self, client_name: String) -> ReportContent {
ReportContent {
object_type: Some(ReportObjectType::Report),
program_id: self.content().program_id.clone(),
event_id: self.id().clone(),
client_name: "".to_string(),
client_name,
report_name: None,
payload_descriptors: None,
resources: vec![],
Expand Down Expand Up @@ -115,51 +114,10 @@ impl EventClient {
.collect())
}

/// Get all reports from the VTN for a specific client, trying to paginate whenever possible
pub async fn get_client_reports(&self, client_name: &str) -> Result<Vec<ReportClient>> {
let page_size = self.client.default_page_size();
let mut reports = vec![];
let mut page = 0;
loop {
let received = self
.get_reports_req(Some(client_name), page * page_size, page_size)
.await?;
let received_all = received.len() < page_size;
for report in received {
reports.push(report);
}

if received_all {
break;
} else {
page += 1;
}
}

Ok(reports)
}

/// Get all reports from the VTN, trying to paginate whenever possible
pub async fn get_all_reports(&self) -> Result<Vec<ReportClient>> {
let page_size = self.client.default_page_size();
let mut reports = vec![];
let mut page = 0;
loop {
let received = self
.get_reports_req(None, page * page_size, page_size)
.await?;
let received_all = received.len() < page_size;
for report in received {
reports.push(report);
}

if received_all {
break;
} else {
page += 1;
}
}

Ok(reports)
/// Get all reports from the VTN, possibly filtered by `client_name`, trying to paginate whenever possible
pub async fn get_reports(&self, client_name: Option<&str>) -> Result<Vec<ReportClient>> {
self.client
.iterate_pages(|skip, limit| self.get_reports_req(client_name, skip, limit))
.await
}
}
Loading

0 comments on commit 8ca5546

Please sign in to comment.