Skip to content

Commit

Permalink
chore: lots of boilerplate
Browse files Browse the repository at this point in the history
  • Loading branch information
chris13524 committed Apr 16, 2024
1 parent d700411 commit ca05a57
Show file tree
Hide file tree
Showing 24 changed files with 562 additions and 13 deletions.
1 change: 1 addition & 0 deletions .env.example
Original file line number Diff line number Diff line change
Expand Up @@ -35,6 +35,7 @@ TELEMETRY_PROMETHEUS_PORT=3001

# FCM
FCM_API_KEY=
FCM_V1_CREDENTIALS=

# APNS
APNS_CERTIFICATE= # base64 encoded .p12 APNS Certificate
Expand Down
3 changes: 2 additions & 1 deletion .env.single-tenant-example
Original file line number Diff line number Diff line change
Expand Up @@ -18,8 +18,9 @@ TELEMETRY_PROMETHEUS_PORT=3001

# FCM
FCM_API_KEY= # Firebase Cloud Messaging Server Key
FCM_V1_CREDENTIALS= # Firebase Cloud Messaging Service Account Credentials

# APNS
APNS_CERTIFICATE= # base64 encoded .p12 APNS Certificate
APNS_CERTIFICATE_PASSWORD= # Password for provided certificate
APNS_TOPIC= # bundle ID/app ID
APNS_TOPIC= # bundle ID/app ID
4 changes: 2 additions & 2 deletions .github/workflows/cd.yml
Original file line number Diff line number Diff line change
Expand Up @@ -81,7 +81,7 @@ jobs:
id: tf-apply
uses: WalletConnect/actions/terraform/apply/@1.0.3
env:
GRAFANA_AUTH: ${{ steps.grafana-get-key.outputs.key }}
TF_VAR_grafana_auth: ${{ steps.grafana-get-key.outputs.key }}
TF_VAR_grafana_endpoint: ${{ steps.grafana-get-details.outputs.endpoint }}
TF_VAR_cloud_api_key: ${{ secrets.CLOUD_API_KEY }}
TF_VAR_jwt_secret: ${{ secrets.JWT_SECRET }}
Expand Down Expand Up @@ -152,7 +152,7 @@ jobs:
id: tf-apply
uses: WalletConnect/actions/terraform/apply/@1.0.3
env:
GRAFANA_AUTH: ${{ steps.grafana-get-key.outputs.key }}
TF_VAR_grafana_auth: ${{ steps.grafana-get-key.outputs.key }}
TF_VAR_grafana_endpoint: ${{ steps.grafana-get-details.outputs.endpoint }}
TF_VAR_cloud_api_key: ${{ secrets.CLOUD_API_KEY }}
TF_VAR_jwt_secret: ${{ secrets.JWT_SECRET }}
Expand Down
1 change: 1 addition & 0 deletions .github/workflows/ci.yml
Original file line number Diff line number Diff line change
Expand Up @@ -170,6 +170,7 @@ jobs:
args: ${{ matrix.cargo.args }}
env:
ECHO_TEST_FCM_KEY: ${{ secrets.ECHO_TEST_FCM_KEY }}
ECHO_TEST_FCM_V1_CREDENTIALS: ${{ secrets.ECHO_TEST_FCM_V1_CREDENTIALS }}
ECHO_TEST_APNS_P8_KEY_ID: ${{ secrets.ECHO_TEST_APNS_P8_KEY_ID }}
ECHO_TEST_APNS_P8_TEAM_ID: ${{ secrets.ECHO_TEST_APNS_P8_TEAM_ID }}
ECHO_TEST_APNS_P8_PEM: ${{ secrets.ECHO_TEST_APNS_P8_PEM }}
Expand Down
2 changes: 1 addition & 1 deletion .github/workflows/ci_terraform.yml
Original file line number Diff line number Diff line change
Expand Up @@ -122,7 +122,7 @@ jobs:
id: tf-plan-staging
uses: WalletConnect/actions/terraform/plan/@1.0.3
env:
GRAFANA_AUTH: ${{ steps.grafana-get-key.outputs.key }}
TF_VAR_grafana_auth: ${{ steps.grafana-get-key.outputs.key }}
TF_VAR_grafana_endpoint: ${{ steps.grafana-get-details.outputs.endpoint }}
TF_VAR_cloud_api_key: ${{ secrets.CLOUD_API_KEY }}
TF_VAR_jwt_secret: ${{ secrets.JWT_SECRET }}
Expand Down
3 changes: 2 additions & 1 deletion Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -9,7 +9,8 @@ build = "build.rs"
resolver = "2"

[features]
full= ["functional_tests", "multitenant", "analytics", "geoblock", "cloud"]
default = ["full"]
full = ["functional_tests", "multitenant", "analytics", "geoblock", "cloud"]
# Used to enable functional tests
functional_tests = []
# Multi-tenancy mode
Expand Down
2 changes: 1 addition & 1 deletion migrations/README.md
Original file line number Diff line number Diff line change
Expand Up @@ -8,4 +8,4 @@ This folder contains migrations for Echo Server and they are automatically calle
```

## Contributors
To create a new migration run `./new.sh [description]` to make a new migration
To create a new migration run `./new.sh [description]` to make a new migration
6 changes: 6 additions & 0 deletions src/config.rs
Original file line number Diff line number Diff line change
Expand Up @@ -61,6 +61,8 @@ pub struct Config {
// FCM
#[cfg(not(feature = "multitenant"))]
pub fcm_api_key: Option<String>,
#[cfg(not(feature = "multitenant"))]
pub fcm_v1_credentials: Option<String>,

// Multi-tenancy
pub tenant_database_url: String,
Expand Down Expand Up @@ -132,6 +134,10 @@ impl Config {
supported.push(ProviderKind::Fcm);
}

if self.fcm_v1_credentials.is_some() {
supported.push(ProviderKind::FcmV1);
}

// Only available in debug/testing
#[cfg(any(debug_assertions, test))]
supported.push(ProviderKind::Noop);
Expand Down
3 changes: 3 additions & 0 deletions src/error.rs
Original file line number Diff line number Diff line change
Expand Up @@ -37,6 +37,9 @@ pub enum Error {
#[error(transparent)]
Fcm(#[from] fcm::FcmError),

#[error(transparent)]
FcmV1(#[from] fcm_v1::Error),

#[error("FCM Responded with an error")]
FcmResponse(fcm::ErrorReason),

Expand Down
2 changes: 2 additions & 0 deletions src/handlers/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -46,6 +46,8 @@ pub mod health;
pub mod update_apns;
#[cfg(feature = "multitenant")]
pub mod update_fcm;
#[cfg(feature = "multitenant")]
pub mod update_fcm_v1;

pub const DECENTRALIZED_IDENTIFIER_PREFIX: &str = "did:key:";

Expand Down
1 change: 1 addition & 0 deletions src/handlers/push_message.rs
Original file line number Diff line number Diff line change
Expand Up @@ -463,6 +463,7 @@ pub async fn handler_internal(
// Provider specific metrics
match provider {
Provider::Fcm(_) => increment_counter!(state.metrics, sent_fcm_notifications),
Provider::FcmV1(_) => increment_counter!(state.metrics, sent_fcm_v1_notifications),
Provider::Apns(_) => increment_counter!(state.metrics, sent_apns_notifications),
#[cfg(any(debug_assertions, test))]
Provider::Noop(_) => {}
Expand Down
115 changes: 115 additions & 0 deletions src/handlers/update_fcm_v1.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,115 @@
use {
crate::{
error::{Error, Error::InvalidMultipartBody},
handlers::validate_tenant_request,
increment_counter,
state::AppState,
stores::tenant::TenantFcmV1UpdateParams,
},
axum::{
extract::{Multipart, Path, State},
http::HeaderMap,
Json,
},
serde::Serialize,
std::sync::Arc,
tracing::{error, instrument},
};

pub struct FcmV1UpdateBody {
credentials: String,
/// Used to ensure that at least one value has changed
value_changed_: bool,
}

#[derive(Serialize)]
pub struct UpdateTenantFcmV1Response {
success: bool,
}

#[instrument(skip_all, name = "update_fcm_v1_handler")]
pub async fn handler(
State(state): State<Arc<AppState>>,
Path(id): Path<String>,
headers: HeaderMap,
mut form_body: Multipart,
) -> Result<Json<UpdateTenantFcmV1Response>, Error> {
// -- check if tenant is real
let _existing_tenant = state.tenant_store.get_tenant(&id).await?;

// JWT token verification
#[cfg(feature = "cloud")]
let jwt_verification_result = validate_tenant_request(
&state.registry_client,
&state.gotrue_client,
&headers,
id.clone(),
None,
)
.await;

#[cfg(not(feature = "cloud"))]
let jwt_verification_result = validate_tenant_request(&state.gotrue_client, &headers);

if let Err(e) = jwt_verification_result {
error!(
tenant_id = %id,
err = ?e,
"JWT verification failed"
);
return Err(e);
}

// ---- retrieve body from form
let mut body = FcmV1UpdateBody {
credentials: Default::default(),
value_changed_: false,
};
while let Some(field) = form_body.next_field().await? {
let name = field.name().unwrap_or("unknown").to_string();
let data = field.text().await?;

if name.to_lowercase().as_str() == "credentials" {
body.credentials = data;
body.value_changed_ = true;
};
}
if !body.value_changed_ {
return Err(InvalidMultipartBody);
}

// ---- checks
// TODO
// let fcm_credentials = body.credentials.clone();
// let mut test_message_builder = fcm_v1::Message::new(&fcm_credentials, "wc-notification-test");
// test_message_builder.dry_run(true);
// let test_message = test_message_builder.finalize();
// let test_notification = fcm::Client::new().send(test_message).await;
// match test_notification {
// Err(e) => match e {
// FcmError::Unauthorized => Err(BadFcmApiKey),
// _ => Ok(()),
// },
// Ok(_) => Ok(()),
// }?;

// ---- handler
let update_body = TenantFcmV1UpdateParams {
fcm_v1_credentials: body.credentials,
};

let new_tenant = state
.tenant_store
.update_tenant_fcm_v1(&id, update_body)
.await?;

if new_tenant.suspended {
// If suspended, it can be restored now because valid credentials have been
// provided
state.tenant_store.unsuspend_tenant(&new_tenant.id).await?;
}

increment_counter!(state.metrics, tenant_fcm_v1_updates);

Ok(Json(UpdateTenantFcmV1Response { success: true }))
}
14 changes: 14 additions & 0 deletions src/metrics/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -19,13 +19,15 @@ pub struct Metrics {

pub received_notifications: Counter<u64>,
pub sent_fcm_notifications: Counter<u64>,
pub sent_fcm_v1_notifications: Counter<u64>,
pub sent_apns_notifications: Counter<u64>,

pub registered_clients: UpDownCounter<i64>,
pub registered_tenants: UpDownCounter<i64>,

pub tenant_apns_updates: Counter<u64>,
pub tenant_fcm_updates: Counter<u64>,
pub tenant_fcm_v1_updates: Counter<u64>,

pub tenant_suspensions: Counter<u64>,
pub client_suspensions: Counter<u64>,
Expand Down Expand Up @@ -71,6 +73,11 @@ impl Metrics {
.with_description("The number of notifications sent to FCM")
.init();

let sent_fcm_v1_notification_counter = meter
.u64_counter("sent_fcm_v1_notifications")
.with_description("The number of notifications sent to FCM")
.init();

let sent_apns_notification_counter = meter
.u64_counter("sent_apns_notifications")
.with_description("The number of notifications sent to APNS")
Expand All @@ -86,6 +93,11 @@ impl Metrics {
.with_description("The number of times tenants have updated their FCM")
.init();

let tenant_fcm_v1_updates_counter = meter
.u64_counter("tenant_fcm_v1_updates")
.with_description("The number of times tenants have updated their FCM")
.init();

let tenant_suspensions_counter = meter
.u64_counter("tenant_suspensions")
.with_description("The number of tenants that have been suspended")
Expand All @@ -101,10 +113,12 @@ impl Metrics {
registered_clients: clients_counter,
received_notifications: received_notification_counter,
sent_fcm_notifications: sent_fcm_notification_counter,
sent_fcm_v1_notifications: sent_fcm_v1_notification_counter,
sent_apns_notifications: sent_apns_notification_counter,
registered_tenants: tenants_counter,
tenant_apns_updates: tenant_apns_updates_counter,
tenant_fcm_updates: tenant_fcm_updates_counter,
tenant_fcm_v1_updates: tenant_fcm_v1_updates_counter,
tenant_suspensions: tenant_suspensions_counter,
client_suspensions: client_suspensions_counter,
})
Expand Down
Loading

0 comments on commit ca05a57

Please sign in to comment.