Skip to content

V5: Authenticated POST route to modify/submit campaigns #408

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Merged
merged 38 commits into from
Aug 9, 2021
Merged
Show file tree
Hide file tree
Changes from 8 commits
Commits
Show all changes
38 commits
Select commit Hold shift + click to select a range
3661ca2
committing current progress
simzzz May 28, 2021
413149f
Merge branch 'aip-61-adex-v5' into v5-modify-submit-campaigns
simzzz May 28, 2021
8c4d687
fixed some more errors
simzzz May 31, 2021
58c61aa
more error fixes
simzzz May 31, 2021
70ff87c
Progress w/out tests
simzzz Jun 8, 2021
f7dae5b
fixed typo
simzzz Jun 10, 2021
0f40016
Refactoring + changes to the way the remaining for all campaigns is r…
simzzz Jun 10, 2021
33f0e3e
added CampaignCreateResponse
simzzz Jun 10, 2021
084f6e6
Merge branch 'aip-61-adex-v5' into v5-modify-submit-campaigns
simzzz Jun 11, 2021
475b8db
More changes to budget/redis operations + fixed problems from PR review
simzzz Jun 11, 2021
60efa4a
more changes to updating remaining
simzzz Jun 11, 2021
1b8cd75
added regex for campaign update route
simzzz Jun 14, 2021
efb30f9
Merge branch 'issue-381-accounting-db' into v5-modify-submit-campaigns
simzzz Jun 15, 2021
57116cc
Accounting messages + First integration tests
simzzz Jun 15, 2021
f4e0949
fixed some unwraps
simzzz Jun 16, 2021
825d6cb
more fixes
simzzz Jun 22, 2021
5fd05db
Merge branch 'issue-382-campaign-routes' into v5-modify-submit-campaigns
simzzz Jun 22, 2021
067b3af
fixed remaining issues in PR
simzzz Jun 29, 2021
9fd4f4a
Included MGET for getting multiple remainings at once
simzzz Jun 30, 2021
9380089
fixed failing test
simzzz Jun 30, 2021
219e3f0
cargofmt + some refactoring + used MutatedCampaign object in more places
simzzz Jun 30, 2021
187d198
Merge branch 'issue-382-campaign-routes' into v5-modify-submit-campaigns
simzzz Jul 2, 2021
ad2d585
Finished with PR changes requested
simzzz Jul 6, 2021
4f23861
PR changes
simzzz Jul 9, 2021
0082a35
Merge branch 'issue-382-campaign-routes' into v5-modify-submit-campaigns
simzzz Jul 12, 2021
8fcef13
sentry - routes - modify campaign
elpiel Jul 13, 2021
b664dd1
sentry - db - campaign - fix doc comment
elpiel Jul 13, 2021
10deba9
sentry - mod test_util - setup_dummy_app helper fn
elpiel Aug 4, 2021
88c3243
sentry - db - campaign - CampaignRemaining redis struct
elpiel Aug 4, 2021
3ca6ab5
primitives - sentry - impl From<Campaign> for CreateCampaign
elpiel Aug 4, 2021
11dc715
primitives - validator - From<Address> for ValidatorID
elpiel Aug 4, 2021
07d9c74
primitives - sentry - accounting - Balances - add spender/earner
elpiel Aug 9, 2021
d80e109
sentry - Applicaiton - add CampaignRemaining to app
elpiel Aug 9, 2021
e1a245e
sentry - db - CampaignRemaining - MGET guard against empty vec of cam…
elpiel Aug 9, 2021
9a94c5f
sentry - routes - campaign create/modify - more checks & tests
elpiel Aug 9, 2021
5177217
sentry - db - make pub insert_accounting
elpiel Aug 9, 2021
75a5a5f
sentry - routes - campaign - get_delta_budget - fix logic & naming
elpiel Aug 9, 2021
19ccd17
Merge pull request #418 from AdExNetwork/redis-and-tests
elpiel Aug 9, 2021
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
12 changes: 12 additions & 0 deletions primitives/src/sentry.rs
Original file line number Diff line number Diff line change
Expand Up @@ -379,6 +379,18 @@ pub mod campaign_create {
}
}
}

// All editable fields stored in one place, used for checking when a budget is changed
// #[derive(Debug, Clone, Serialize, Deserialize, PartialEq)]
// pub struct CampaignState {
// pub budget: UnifiedNum,
// pub validators: Validators,
// pub title: Option<String>,
// pub pricing_bounds: Option<PricingBounds>,
// pub event_submission: Option<EventSubmission>,
// pub ad_units: Vec<AdUnit>,
// pub targeting_rules: Rules,
// }
}

#[cfg(feature = "postgres")]
Expand Down
2 changes: 1 addition & 1 deletion sentry/src/db.rs
Original file line number Diff line number Diff line change
Expand Up @@ -6,7 +6,7 @@ use tokio_postgres::NoTls;
use lazy_static::lazy_static;

pub mod analytics;
mod campaign;
pub mod campaign;
mod channel;
pub mod event_aggregate;
pub mod spendable;
Expand Down
58 changes: 52 additions & 6 deletions sentry/src/db/campaign.rs
Original file line number Diff line number Diff line change
Expand Up @@ -2,8 +2,6 @@ use crate::db::{DbPool, PoolError};
use primitives::Campaign;
use tokio_postgres::types::Json;

// TODO: Remove once we use this fn
#[allow(dead_code)]
pub async fn insert_campaign(pool: &DbPool, campaign: &Campaign) -> Result<bool, PoolError> {
let client = pool.get().await?;
let ad_units = Json(campaign.ad_units.clone());
Expand Down Expand Up @@ -38,9 +36,7 @@ pub async fn insert_campaign(pool: &DbPool, campaign: &Campaign) -> Result<bool,
/// SELECT id, channel, creator, budget, validators, title, pricing_bounds, event_submission, ad_units, targeting_rules, created, active_from, active_to FROM campaigns
/// WHERE id = $1
/// ```
// TODO: Remove once we use this fn
#[allow(dead_code)]
pub async fn fetch_campaign(pool: DbPool, campaign: &Campaign) -> Result<Campaign, PoolError> {
pub async fn fetch_campaign(pool: &DbPool, campaign: &Campaign) -> Result<Campaign, PoolError> {
let client = pool.get().await?;
let statement = client.prepare("SELECT id, channel, creator, budget, validators, title, pricing_bounds, event_submission, ad_units, targeting_rules, created, active_from, active_to FROM campaigns WHERE id = $1").await?;

Expand All @@ -49,6 +45,51 @@ pub async fn fetch_campaign(pool: DbPool, campaign: &Campaign) -> Result<Campaig
Ok(Campaign::from(&row))
}

pub async fn get_campaigns_for_channel(pool: &DbPool, campaign: &Campaign) -> Result<Vec<Campaign>, PoolError> {
let client = pool.get().await?;
let statement = client.prepare("SELECT id, channel, creator, budget, validators, title, pricing_bounds, event_submission, ad_units, targeting_rules, created, active_from, active_to FROM campaigns WHERE channel_id = $1").await?;

let row = client.query(&statement, &[&campaign.channel.id()]).await?;

let campaigns = row.into_iter().map(|c| Campaign::from(&c)).collect();
Ok(campaigns)
}

pub async fn campaign_exists(pool: &DbPool, campaign: &Campaign) -> Result<bool, PoolError> {
let client = pool.get().await?;
let statement = client
.prepare("SELECT EXISTS(SELECT 1 FROM campaigns WHERE id = $1)")
.await?;

let row = client.execute(&statement, &[&campaign.id]).await?;

let exists = row == 1;
Ok(exists)
}

pub async fn update_campaign_in_db(pool: &DbPool, campaign: &Campaign) -> Result<bool, PoolError> {
let client = pool.get().await?;
let statement = client
.prepare("UPDATE campaigns SET budget = $1, validators = $2, title = $3, pricing_bounds = $4, event_submission = $5, ad_units = $6, targeting_rules = $7 WHERE id = $8")
.await?;

let row = client
.execute(&statement, &[
&campaign.budget,
&campaign.validators,
&campaign.title,
&campaign.pricing_bounds,
&campaign.event_submission,
&campaign.ad_units,
&campaign.targeting_rules,
&campaign.id,
])
.await?;

let exists = row == 1;
Ok(exists)
}

#[cfg(test)]
mod test {
use primitives::{campaign::Campaign, util::tests::prep_db::DUMMY_CAMPAIGN};
Expand All @@ -72,7 +113,12 @@ mod test {

assert!(is_inserted);

let fetched_campaign: Campaign = fetch_campaign(db_pool.clone(), &campaign_for_testing)
let exists = campaign_exists(&db_pool.clone(), &campaign_for_testing)
.await
.expect("Should succeed");
assert!(exists);

let fetched_campaign: Campaign = fetch_campaign(&db_pool, &campaign_for_testing)
.await
.expect("Should fetch successfully");

Expand Down
27 changes: 26 additions & 1 deletion sentry/src/db/event_aggregate.rs
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,7 @@ use futures::pin_mut;
use primitives::{
sentry::{EventAggregate, MessageResponse},
validator::{ApproveState, Heartbeat, NewState},
Address, BigNum, Channel, ChannelId, ValidatorId,
Address, BigNum, Channel, ChannelId, ValidatorId, channel_v5::Channel as ChannelV5,
};
use std::{convert::TryFrom, ops::Add};
use tokio_postgres::{
Expand Down Expand Up @@ -58,6 +58,31 @@ pub async fn latest_new_state(
.map_err(PoolError::Backend)
}

pub async fn latest_new_state_v5(
pool: &DbPool,
channel: &ChannelV5,
state_root: &str,
) -> Result<Option<MessageResponse<NewState>>, PoolError> {
let client = pool.get().await?;

let select = client.prepare("SELECT \"from\", msg, received FROM validator_messages WHERE channel_id = $1 AND \"from\" = $2 AND msg ->> 'type' = 'NewState' AND msg->> 'stateRoot' = $3 ORDER BY received DESC LIMIT 1").await?;
let rows = client
.query(
&select,
&[
&channel.id(),
&channel.leader,
&state_root,
],
)
.await?;

rows.get(0)
.map(MessageResponse::<NewState>::try_from)
.transpose()
.map_err(PoolError::Backend)
}

pub async fn latest_heartbeats(
pool: &DbPool,
channel_id: &ChannelId,
Expand Down
24 changes: 24 additions & 0 deletions sentry/src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -21,6 +21,7 @@ use primitives::{Config, ValidatorId};
use redis::aio::MultiplexedConnection;
use regex::Regex;
use routes::analytics::{advanced_analytics, advertiser_analytics, analytics, publisher_analytics};
use routes::campaign::{create_campaign, update_campaign};
use routes::cfg::config;
use routes::channel::{
channel_list, channel_validate, create_channel, create_validator_messages, insert_events,
Expand All @@ -34,6 +35,7 @@ pub mod routes {
pub mod analytics;
pub mod cfg;
pub mod channel;
pub mod campaign;
pub mod event_aggregate;
pub mod validator_message;
}
Expand Down Expand Up @@ -150,6 +152,28 @@ impl<A: Adapter + 'static> Application<A> {

publisher_analytics(req, &self).await
}
// For creating campaigns
("/campaign", &Method::POST) => {
let req = match AuthRequired.call(req, &self).await {
Ok(req) => req,
Err(error) => {
return map_response_error(error);
}
};

create_campaign(req, &self).await
}
// For editing campaigns
("/campaign/:id", &Method::POST) => {
let req = match AuthRequired.call(req, &self).await {
Ok(req) => req,
Err(error) => {
return map_response_error(error);
}
};

update_campaign(req, &self).await
}
(route, _) if route.starts_with("/analytics") => analytics_router(req, &self).await,
// This is important becuase it prevents us from doing
// expensive regex matching for routes without /channel
Expand Down
Loading