Skip to content

Commit

Permalink
aggregator config api (client-side) (#340)
Browse files Browse the repository at this point in the history
---------

Co-authored-by: Tim Geoghegan <[email protected]>
  • Loading branch information
jbr and tgeoghegan authored Jul 31, 2023
1 parent ddcce58 commit a63b6b1
Show file tree
Hide file tree
Showing 27 changed files with 840 additions and 281 deletions.
1 change: 1 addition & 0 deletions Cargo.lock

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

6 changes: 4 additions & 2 deletions app/src/ApiClient.ts
Original file line number Diff line number Diff line change
Expand Up @@ -117,10 +117,8 @@ export interface Aggregator {
}

export interface NewAggregator {
role: Role;
name: string;
api_url: string;
dap_url: string;
bearer_token: string;
is_first_party?: boolean;
}
Expand Down Expand Up @@ -422,6 +420,10 @@ function errorToMessage({ message, code, params }: ValidationError) {
return "must be base64";
} else if (code === "same") {
return "must not be the same";
} else if (code === "token-not-recognized") {
return "bearer token not recognized";
} else if (code === "http-error") {
return "error connecting to url";
} else if (code === "enum" && Array.isArray(params.values)) {
return `must be one of these values: ${params.values.join(", ")}`;
} else if (code === "length") {
Expand Down
50 changes: 0 additions & 50 deletions app/src/aggregators/AggregatorForm.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -69,10 +69,8 @@ export function AggregatorForm({
errors={errors}
initialValues={
{
role: "either",
name: "",
api_url: "",
dap_url: "",
bearer_token: "",
is_first_party: showIsFirstParty ? true : undefined,
} as NewAggregator
Expand All @@ -86,10 +84,8 @@ export function AggregatorForm({
noValidate
autoComplete="off"
>
<RoleSelect {...props} />
<Name {...props} />
<ApiUrl {...props} />
<DapUrl {...props} />
<BearerToken {...props} />
{showIsFirstParty ? <IsFirstParty {...props} /> : null}
<Button
Expand Down Expand Up @@ -219,52 +215,6 @@ function ApiUrl(props: FormikProps<NewAggregator>) {
</FormGroup>
);
}
function DapUrl(props: FormikProps<NewAggregator>) {
return (
<FormGroup>
<FormLabel>DAP Url</FormLabel>

<FormControl
type="url"
onChange={props.handleChange}
onBlur={props.handleBlur}
value={props.values.dap_url}
isInvalid={!!props.errors.dap_url}
required
autoComplete="off"
placeholder="https://example.com"
pattern="https://.*"
name="dap_url"
/>
<FormControl.Feedback type="invalid">
{props.errors.dap_url}
</FormControl.Feedback>
</FormGroup>
);
}

function RoleSelect(props: FormikProps<NewAggregator>) {
return (
<FormGroup>
<FormLabel>Role</FormLabel>

<FormSelect
value={props.values.role}
isInvalid={!!props.errors.role}
onChange={props.handleChange}
onBlur={props.handleBlur}
name="role"
>
<option value="leader">Leader</option>
<option value="helper">Helper</option>
<option value="either">Either Leader or Helper</option>
</FormSelect>
<FormControl.Feedback type="invalid">
{props.errors.role}
</FormControl.Feedback>
</FormGroup>
);
}

function Breadcrumbs() {
return (
Expand Down
33 changes: 0 additions & 33 deletions cli/src/aggregators.rs
Original file line number Diff line number Diff line change
Expand Up @@ -2,45 +2,16 @@ use crate::{CliResult, Output};
use clap::Subcommand;
use divviup_client::{DivviupClient, NewAggregator, Url, Uuid};

#[derive(clap::ValueEnum, Clone, Debug)]
pub enum Role {
Either,
Leader,
Helper,
}

impl From<Role> for divviup_client::Role {
fn from(value: Role) -> Self {
match value {
Role::Either => Self::Either,
Role::Leader => Self::Leader,
Role::Helper => Self::Helper,
}
}
}

#[derive(Subcommand, Debug)]
pub enum AggregatorAction {
List,
Create {
/// Possible roles for this aggregator
///
/// Acceptable values: "Either", "Leader", or "Helper"
#[arg(short, long)]
role: Role,

/// Human-readable identifier for this aggregator
///
/// This can be changed later
#[arg(short, long)]
name: String,

/// DAP URL for this aggregator
///
/// must be https
#[arg(short, long)]
dap_url: Url,

/// API URL for this aggregator
///
/// must be https
Expand Down Expand Up @@ -79,19 +50,15 @@ impl AggregatorAction {
AggregatorAction::List => output.display(client.aggregators(account_id).await?),

AggregatorAction::Create {
role,
name,
dap_url,
api_url,
bearer_token,
} => output.display(
client
.create_aggregator(
account_id,
NewAggregator {
role: role.into(),
name,
dap_url,
api_url,
bearer_token,
},
Expand Down
4 changes: 2 additions & 2 deletions client/src/aggregator.rs
Original file line number Diff line number Diff line change
Expand Up @@ -27,13 +27,13 @@ pub struct Aggregator {
pub dap_url: Url,
pub api_url: Url,
pub is_first_party: bool,
pub vdafs: Vec<String>,
pub query_types: Vec<String>,
}

#[derive(Serialize, Deserialize, Debug, Clone, Eq, PartialEq)]
pub struct NewAggregator {
pub role: Role,
pub name: String,
pub dap_url: Url,
pub api_url: Url,
pub bearer_token: String,
}
4 changes: 1 addition & 3 deletions client/tests/aggregators.rs
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
mod harness;
use divviup_client::{DivviupClient, NewAggregator, Role};
use divviup_client::{DivviupClient, NewAggregator};
use harness::with_configured_client;
use std::sync::Arc;
use test_support::{assert_eq, test, *};
Expand Down Expand Up @@ -29,8 +29,6 @@ async fn create_aggregator(
.create_aggregator(
account.id,
NewAggregator {
role: Role::Either,
dap_url: "https://dap.url".parse().unwrap(),
api_url: "https://api.url".parse().unwrap(),
name: "my account name".into(),
bearer_token: "somebearertoken".into(),
Expand Down
1 change: 1 addition & 0 deletions migration/Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -13,6 +13,7 @@ path = "src/lib.rs"
async-std = { version = "1", features = ["attributes", "tokio1"] }
clap = { version = "4.3.19", features = ["env", "derive"] }
sea-orm = "0.11.3"
serde_json = "1.0.103"
thiserror = "1.0.44"
time = "0.3.23"
tracing = "0.1.37"
Expand Down
2 changes: 2 additions & 0 deletions migration/src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -14,6 +14,7 @@ mod m20230622_232534_make_aggregator_api_url_mandatory;
mod m20230626_183248_add_is_first_party_to_aggregators;
mod m20230630_175314_create_api_tokens;
mod m20230703_201332_add_additional_fields_to_api_tokens;
mod m20230725_220134_add_vdafs_and_query_types_to_aggregators;

pub struct Migrator;

Expand All @@ -35,6 +36,7 @@ impl MigratorTrait for Migrator {
Box::new(m20230626_183248_add_is_first_party_to_aggregators::Migration),
Box::new(m20230630_175314_create_api_tokens::Migration),
Box::new(m20230703_201332_add_additional_fields_to_api_tokens::Migration),
Box::new(m20230725_220134_add_vdafs_and_query_types_to_aggregators::Migration),
]
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,67 @@
use sea_orm_migration::prelude::*;
use serde_json::json;

#[derive(DeriveMigrationName)]
pub struct Migration;

#[async_trait::async_trait]
impl MigrationTrait for Migration {
async fn up(&self, db: &SchemaManager) -> Result<(), DbErr> {
db.alter_table(
TableAlterStatement::new()
.table(Aggregator::Table)
.add_column(ColumnDef::new(Aggregator::Vdafs).json().null())
.add_column(ColumnDef::new(Aggregator::QueryTypes).json().null())
.to_owned(),
)
.await?;

db.exec_stmt(
Query::update()
.table(Aggregator::Table)
.values([
(
Aggregator::Vdafs,
json!(["Prio3Count", "Prio3Sum", "Prio3Histogram"]).into(),
),
(
Aggregator::QueryTypes,
json!(["TimeInterval", "FixedSize"]).into(),
),
])
.to_owned(),
)
.await?;

db.alter_table(
TableAlterStatement::new()
.table(Aggregator::Table)
.modify_column(ColumnDef::new(Aggregator::Vdafs).not_null())
.modify_column(ColumnDef::new(Aggregator::QueryTypes).not_null())
.to_owned(),
)
.await?;

Ok(())
}

async fn down(&self, db: &SchemaManager) -> Result<(), DbErr> {
db.alter_table(
TableAlterStatement::new()
.table(Aggregator::Table)
.drop_column(Aggregator::Vdafs)
.drop_column(Aggregator::QueryTypes)
.to_owned(),
)
.await?;
Ok(())
}
}

/// Learn more at https://docs.rs/sea-query#iden
#[derive(Iden)]
enum Aggregator {
Table,
Vdafs,
QueryTypes,
}
16 changes: 4 additions & 12 deletions src/api_mocks.rs
Original file line number Diff line number Diff line change
@@ -1,12 +1,11 @@
use crate::handler::origin_router;
use trillium::{Conn, Handler};
use trillium::Handler;
use trillium_http::KnownHeaderName;
use trillium_logger::{
formatters::{method, status, url},
formatters::{method, request_header, status, url},
logger,
};
use trillium_macros::Handler;
use trillium_router::Router;

pub mod aggregator_api;
pub mod auth0;
Expand All @@ -28,12 +27,7 @@ impl ApiMocks {
"[mock] ",
method,
" ",
move |conn: &Conn, _| {
conn.headers()
.get_str(KnownHeaderName::Host)
.unwrap_or_default()
.to_string()
},
request_header(KnownHeaderName::Host),
" ",
url,
" ",
Expand All @@ -42,9 +36,7 @@ impl ApiMocks {
origin_router()
.with_handler(postmark_url, postmark::mock())
.with_handler(auth0_url, auth0::mock(auth0_url)),
// Add a path prefix before the aggregator API mock. Aggregator test fixtures must
// include this prefix in their URLs.
Router::new().all("prefix/*", aggregator_api::mock()),
aggregator_api::mock(),
)))
}
}
Loading

0 comments on commit a63b6b1

Please sign in to comment.