Skip to content

Commit

Permalink
add /api/v1/event/{id}/objective/{obj_id}/ballots and `/api/v1/even…
Browse files Browse the repository at this point in the history
…t/{id}/ballots` endpoints
  • Loading branch information
Mr-Leshiy committed May 31, 2023
1 parent cf63504 commit 6060584
Show file tree
Hide file tree
Showing 4 changed files with 282 additions and 4 deletions.
135 changes: 135 additions & 0 deletions src/cat-data-service/src/service/v1/event/ballots.rs
@@ -0,0 +1,135 @@
use crate::{
service::{handle_result, Error},
state::State,
};
use axum::{extract::Path, routing::get, Router};
use event_db::types::event::{ballot::ObjectiveBallots, EventId};
use std::sync::Arc;

pub fn ballots(state: Arc<State>) -> Router {
Router::new().route(
"/ballots",
get(move |path| async { handle_result(ballots_exec(path, state).await).await }),
)
}

async fn ballots_exec(
Path(event): Path<EventId>,
state: Arc<State>,
) -> Result<Vec<ObjectiveBallots>, Error> {
tracing::debug!("ballots_query, event: {0}", event.0,);

let ballot = state.event_db.get_event_ballots(event).await?;
Ok(ballot)
}

/// Need to setup and run a test event db instance
/// To do it you can use the following commands:
/// Prepare docker images
/// ```
/// earthly ./containers/event-db-migrations+docker --data=test
/// ```
/// Run event-db container
/// ```
/// docker-compose -f src/event-db/docker-compose.yml up migrations
/// ```
/// Also need establish `EVENT_DB_URL` env variable with the following value
/// ```
/// EVENT_DB_URL="postgres://catalyst-event-dev:CHANGE_ME@localhost/CatalystEventDev"
/// ```
/// https://github.com/input-output-hk/catalyst-core/tree/main/src/event-db/Readme.md
#[cfg(test)]
mod tests {
use super::*;
use crate::service::app;
use axum::{
body::{Body, HttpBody},
http::{Request, StatusCode},
};
use event_db::types::{
event::{
ballot::{
Ballot, BallotType, GroupVotePlans, ObjectiveChoices, ProposalBallot, VotePlan,
},
objective::ObjectiveId,
proposal::ProposalId,
},
registration::VoterGroupId,
};
use tower::ServiceExt;

#[tokio::test]
async fn ballots_test() {
let state = Arc::new(State::new(None).await.unwrap());
let app = app(state);

let request = Request::builder()
.uri(format!("/api/v1/event/{0}/ballots", 1))
.body(Body::empty())
.unwrap();
let response = app.clone().oneshot(request).await.unwrap();
assert_eq!(response.status(), StatusCode::OK);

assert_eq!(
serde_json::to_string(&vec![ObjectiveBallots {
objective_id: ObjectiveId(1),
ballots: vec![
ProposalBallot {
proposal_id: ProposalId(1),
ballot: Ballot {
choices: ObjectiveChoices(vec!["yes".to_string(), "no".to_string()]),
voteplans: GroupVotePlans(vec![
VotePlan {
chain_proposal_index: 10,
group: VoterGroupId("direct".to_string()),
ballot_type: BallotType("public".to_string()),
chain_voteplan_id: "1".to_string(),
encryption_key: None,
},
VotePlan {
chain_proposal_index: 12,
group: VoterGroupId("rep".to_string()),
ballot_type: BallotType("public".to_string()),
chain_voteplan_id: "2".to_string(),
encryption_key: None,
}
]),
},
},
ProposalBallot {
proposal_id: ProposalId(2),
ballot: Ballot {
choices: ObjectiveChoices(vec!["yes".to_string(), "no".to_string()]),
voteplans: GroupVotePlans(vec![
VotePlan {
chain_proposal_index: 11,
group: VoterGroupId("direct".to_string()),
ballot_type: BallotType("public".to_string()),
chain_voteplan_id: "1".to_string(),
encryption_key: None,
},
VotePlan {
chain_proposal_index: 13,
group: VoterGroupId("rep".to_string()),
ballot_type: BallotType("public".to_string()),
chain_voteplan_id: "2".to_string(),
encryption_key: None,
}
]),
},
},
ProposalBallot {
proposal_id: ProposalId(3),
ballot: Ballot {
choices: ObjectiveChoices(vec!["yes".to_string(), "no".to_string()]),
voteplans: GroupVotePlans(vec![]),
},
}
]
}],)
.unwrap(),
String::from_utf8(response.into_body().data().await.unwrap().unwrap().to_vec())
.unwrap()
);
}
}
8 changes: 5 additions & 3 deletions src/cat-data-service/src/service/v1/event/mod.rs
@@ -1,3 +1,4 @@
use super::LimitOffset;
use crate::{
service::{handle_result, Error},
state::State,
Expand All @@ -10,12 +11,12 @@ use axum::{
use event_db::types::event::{Event, EventId, EventSummary};
use std::sync::Arc;

use super::LimitOffset;

mod ballots;
mod objective;

pub fn event(state: Arc<State>) -> Router {
let objective = objective::objective(state.clone());
let ballots = ballots::ballots(state.clone());

Router::new()
.nest(
Expand All @@ -28,7 +29,8 @@ pub fn event(state: Arc<State>) -> Router {
move |path| async { handle_result(event_exec(path, state).await).await }
}),
)
.merge(objective),
.merge(objective)
.merge(ballots),
)
.route(
"/events",
Expand Down
136 changes: 136 additions & 0 deletions src/cat-data-service/src/service/v1/event/objective/ballots.rs
@@ -0,0 +1,136 @@
use crate::{
service::{handle_result, Error},
state::State,
};
use axum::{extract::Path, routing::get, Router};
use event_db::types::event::{ballot::ProposalBallot, objective::ObjectiveId, EventId};
use std::sync::Arc;

pub fn ballots(state: Arc<State>) -> Router {
Router::new().route(
"/ballots",
get(move |path| async { handle_result(ballots_exec(path, state).await).await }),
)
}

async fn ballots_exec(
Path((event, objective)): Path<(EventId, ObjectiveId)>,
state: Arc<State>,
) -> Result<Vec<ProposalBallot>, Error> {
tracing::debug!(
"ballots_query, event: {0}, objective: {1}",
event.0,
objective.0,
);

let ballot = state
.event_db
.get_objective_ballots(event, objective)
.await?;
Ok(ballot)
}

/// Need to setup and run a test event db instance
/// To do it you can use the following commands:
/// Prepare docker images
/// ```
/// earthly ./containers/event-db-migrations+docker --data=test
/// ```
/// Run event-db container
/// ```
/// docker-compose -f src/event-db/docker-compose.yml up migrations
/// ```
/// Also need establish `EVENT_DB_URL` env variable with the following value
/// ```
/// EVENT_DB_URL="postgres://catalyst-event-dev:CHANGE_ME@localhost/CatalystEventDev"
/// ```
/// https://github.com/input-output-hk/catalyst-core/tree/main/src/event-db/Readme.md
#[cfg(test)]
mod tests {
use super::*;
use crate::service::app;
use axum::{
body::{Body, HttpBody},
http::{Request, StatusCode},
};
use event_db::types::{
event::{
ballot::{Ballot, BallotType, GroupVotePlans, ObjectiveChoices, VotePlan},
proposal::ProposalId,
},
registration::VoterGroupId,
};
use tower::ServiceExt;

#[tokio::test]
async fn ballots_test() {
let state = Arc::new(State::new(None).await.unwrap());
let app = app(state);

let request = Request::builder()
.uri(format!("/api/v1/event/{0}/objective/{1}/ballots", 1, 1))
.body(Body::empty())
.unwrap();
let response = app.clone().oneshot(request).await.unwrap();
assert_eq!(response.status(), StatusCode::OK);

assert_eq!(
serde_json::to_string(&vec![
ProposalBallot {
proposal_id: ProposalId(1),
ballot: Ballot {
choices: ObjectiveChoices(vec!["yes".to_string(), "no".to_string()]),
voteplans: GroupVotePlans(vec![
VotePlan {
chain_proposal_index: 10,
group: VoterGroupId("direct".to_string()),
ballot_type: BallotType("public".to_string()),
chain_voteplan_id: "1".to_string(),
encryption_key: None,
},
VotePlan {
chain_proposal_index: 12,
group: VoterGroupId("rep".to_string()),
ballot_type: BallotType("public".to_string()),
chain_voteplan_id: "2".to_string(),
encryption_key: None,
}
]),
},
},
ProposalBallot {
proposal_id: ProposalId(2),
ballot: Ballot {
choices: ObjectiveChoices(vec!["yes".to_string(), "no".to_string()]),
voteplans: GroupVotePlans(vec![
VotePlan {
chain_proposal_index: 11,
group: VoterGroupId("direct".to_string()),
ballot_type: BallotType("public".to_string()),
chain_voteplan_id: "1".to_string(),
encryption_key: None,
},
VotePlan {
chain_proposal_index: 13,
group: VoterGroupId("rep".to_string()),
ballot_type: BallotType("public".to_string()),
chain_voteplan_id: "2".to_string(),
encryption_key: None,
}
]),
},
},
ProposalBallot {
proposal_id: ProposalId(3),
ballot: Ballot {
choices: ObjectiveChoices(vec!["yes".to_string(), "no".to_string()]),
voteplans: GroupVotePlans(vec![]),
},
}
])
.unwrap(),
String::from_utf8(response.into_body().data().await.unwrap().unwrap().to_vec())
.unwrap()
);
}
}
7 changes: 6 additions & 1 deletion src/cat-data-service/src/service/v1/event/objective/mod.rs
Expand Up @@ -10,15 +10,20 @@ use axum::{
use event_db::types::event::{objective::Objective, EventId};
use std::sync::Arc;

mod ballots;
mod proposal;
mod review_type;

pub fn objective(state: Arc<State>) -> Router {
let proposal = proposal::proposal(state.clone());
let review_type = review_type::review_type(state.clone());
let ballots = ballots::ballots(state.clone());

Router::new()
.nest("/objective/:objective", proposal.merge(review_type))
.nest(
"/objective/:objective",
proposal.merge(review_type).merge(ballots),
)
.route(
"/objectives",
get(move |path, query| async {
Expand Down

0 comments on commit 6060584

Please sign in to comment.