Skip to content

Commit

Permalink
feat: delete provider (#329)
Browse files Browse the repository at this point in the history
  • Loading branch information
chris13524 authored May 20, 2024
1 parent d10790f commit 66b31e2
Show file tree
Hide file tree
Showing 10 changed files with 724 additions and 1 deletion.
54 changes: 54 additions & 0 deletions src/handlers/delete_apns.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,54 @@
use {
crate::{
error::Error::{self},
handlers::validate_tenant_request,
increment_counter,
state::AppState,
},
axum::{
extract::{Path, State},
http::HeaderMap,
},
hyper::StatusCode,
std::sync::Arc,
tracing::{error, instrument},
};

#[instrument(skip_all, name = "delete_apns_handler")]
pub async fn handler(
State(state): State<Arc<AppState>>,
Path(id): Path<String>,
headers: HeaderMap,
) -> Result<StatusCode, Error> {
// JWT verification
#[cfg(feature = "cloud")]
let jwt_verification_result =
validate_tenant_request(&state.jwt_validation_client, &headers, &id).await;

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

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

// Ensure tenant real
let _existing_tenant = state.tenant_store.get_tenant(&id).await?;

let new_tenant = state.tenant_store.update_tenant_delete_apns(&id).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_apns_updates);

Ok(StatusCode::NO_CONTENT)
}
54 changes: 54 additions & 0 deletions src/handlers/delete_fcm.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,54 @@
use {
crate::{
error::Error::{self},
handlers::validate_tenant_request,
increment_counter,
state::AppState,
},
axum::{
extract::{Path, State},
http::HeaderMap,
},
hyper::StatusCode,
std::sync::Arc,
tracing::{error, instrument},
};

#[instrument(skip_all, name = "delete_fcm_handler")]
pub async fn handler(
State(state): State<Arc<AppState>>,
Path(id): Path<String>,
headers: HeaderMap,
) -> Result<StatusCode, Error> {
// JWT token verification
#[cfg(feature = "cloud")]
let jwt_verification_result =
validate_tenant_request(&state.jwt_validation_client, &headers, &id).await;

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

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

// -- check if tenant is real
let _existing_tenant = state.tenant_store.get_tenant(&id).await?;

let new_tenant = state.tenant_store.update_tenant_delete_fcm(&id).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_updates);

Ok(StatusCode::NO_CONTENT)
}
54 changes: 54 additions & 0 deletions src/handlers/delete_fcm_v1.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,54 @@
use {
crate::{
error::Error::{self},
handlers::validate_tenant_request,
increment_counter,
state::AppState,
},
axum::{
extract::{Path, State},
http::HeaderMap,
},
hyper::StatusCode,
std::sync::Arc,
tracing::{debug, error, instrument},
};

#[instrument(skip_all, name = "delete_fcm_v1_handler")]
pub async fn handler(
State(state): State<Arc<AppState>>,
Path(id): Path<String>,
headers: HeaderMap,
) -> Result<StatusCode, Error> {
// JWT token verification
#[cfg(feature = "cloud")]
let jwt_verification_result =
validate_tenant_request(&state.jwt_validation_client, &headers, &id).await;

// -- check if tenant is real
let _existing_tenant = state.tenant_store.get_tenant(&id).await?;

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

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

let new_tenant = state.tenant_store.update_tenant_delete_fcm_v1(&id).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(StatusCode::NO_CONTENT)
}
6 changes: 6 additions & 0 deletions src/handlers/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -30,6 +30,12 @@ pub mod single_tenant_wrappers;
#[cfg(feature = "multitenant")]
pub mod create_tenant;
#[cfg(feature = "multitenant")]
pub mod delete_apns;
#[cfg(feature = "multitenant")]
pub mod delete_fcm;
#[cfg(feature = "multitenant")]
pub mod delete_fcm_v1;
#[cfg(feature = "multitenant")]
pub mod delete_tenant;
#[cfg(feature = "multitenant")]
pub mod get_tenant;
Expand Down
6 changes: 5 additions & 1 deletion src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -218,8 +218,11 @@ pub async fn bootstap(mut shutdown: broadcast::Receiver<()>, config: Config) ->
get(handlers::get_tenant::handler).delete(handlers::delete_tenant::handler),
)
.route("/:id/fcm", post(handlers::update_fcm::handler))
.route("/:id/fcm", delete(handlers::delete_fcm::handler))
.route("/:id/fcm_v1", post(handlers::update_fcm_v1::handler))
.route("/:id/fcm_v1", delete(handlers::delete_fcm_v1::handler))
.route("/:id/apns", post(handlers::update_apns::handler))
.route("/:id/apns", delete(handlers::delete_apns::handler))
.layer(
global_middleware.clone().layer(
CorsLayer::new()
Expand All @@ -233,7 +236,8 @@ pub async fn bootstap(mut shutdown: broadcast::Receiver<()>, config: Config) ->
.allow_origin(AllowOrigin::any())
.allow_headers([hyper::http::header::CONTENT_TYPE, hyper::http::header::AUTHORIZATION]),
),
);
)
.layer(axum::middleware::from_fn_with_state(state_arc.clone(), rate_limit_middleware));

Router::new()
.route("/health", get(handlers::health::handler).layer(
Expand Down
72 changes: 72 additions & 0 deletions src/stores/tenant.rs
Original file line number Diff line number Diff line change
Expand Up @@ -299,17 +299,20 @@ pub trait TenantStore {
async fn delete_tenant(&self, id: &str) -> Result<()>;
async fn create_tenant(&self, params: TenantUpdateParams) -> Result<Tenant>;
async fn update_tenant_fcm(&self, id: &str, params: TenantFcmUpdateParams) -> Result<Tenant>;
async fn update_tenant_delete_fcm(&self, id: &str) -> Result<Tenant>;
async fn update_tenant_fcm_v1(
&self,
id: &str,
params: TenantFcmV1UpdateParams,
) -> Result<Tenant>;
async fn update_tenant_delete_fcm_v1(&self, id: &str) -> Result<Tenant>;
async fn update_tenant_apns(&self, id: &str, params: TenantApnsUpdateParams) -> Result<Tenant>;
async fn update_tenant_apns_auth(
&self,
id: &str,
params: TenantApnsUpdateAuth,
) -> Result<Tenant>;
async fn update_tenant_delete_apns(&self, id: &str) -> Result<Tenant>;
async fn suspend_tenant(&self, id: &str, reason: &str) -> Result<()>;
async fn unsuspend_tenant(&self, id: &str) -> Result<()>;
}
Expand Down Expand Up @@ -373,6 +376,23 @@ impl TenantStore for PgPool {
Ok(res)
}

#[instrument(skip(self))]
async fn update_tenant_delete_fcm(&self, id: &str) -> Result<Tenant> {
let query = "
UPDATE public.tenants
SET updated_at = NOW(),
fcm_api_key = NULL
WHERE id = $1
RETURNING *
";
let res = sqlx::query_as::<sqlx::postgres::Postgres, Tenant>(query)
.bind(id)
.fetch_one(self)
.await?;

Ok(res)
}

#[instrument(skip(self))]
async fn update_tenant_fcm_v1(
&self,
Expand All @@ -391,6 +411,23 @@ impl TenantStore for PgPool {
Ok(res)
}

#[instrument(skip(self))]
async fn update_tenant_delete_fcm_v1(&self, id: &str) -> Result<Tenant> {
let query = "
UPDATE public.tenants
SET updated_at = NOW(),
fcm_v1_credentials = NULL
WHERE id = $1
RETURNING *
";
let res = sqlx::query_as::<sqlx::postgres::Postgres, Tenant>(query)
.bind(id)
.fetch_one(self)
.await?;

Ok(res)
}

#[instrument(skip(self))]
async fn update_tenant_apns(&self, id: &str, params: TenantApnsUpdateParams) -> Result<Tenant> {
let res = sqlx::query_as::<sqlx::postgres::Postgres, Tenant>(
Expand Down Expand Up @@ -443,6 +480,29 @@ impl TenantStore for PgPool {
Ok(res)
}

#[instrument(skip(self))]
async fn update_tenant_delete_apns(&self, id: &str) -> Result<Tenant> {
let query = "
UPDATE public.tenants
SET updated_at = NOW(),
apns_topic = NULL,
apns_type = NULL,
apns_certificate = NULL,
apns_certificate_password = NULL,
apns_pkcs8_pem = NULL,
apns_team_id = NULL,
apns_key_id = NULL
WHERE id = $1
RETURNING *
";
let res = sqlx::query_as::<sqlx::postgres::Postgres, Tenant>(query)
.bind(id)
.fetch_one(self)
.await?;

Ok(res)
}

#[instrument(skip(self))]
async fn suspend_tenant(&self, id: &str, reason: &str) -> Result<()> {
let mut query_builder = sqlx::QueryBuilder::new(
Expand Down Expand Up @@ -517,6 +577,10 @@ impl TenantStore for DefaultTenantStore {
panic!("Shouldn't have run in single tenant mode")
}

async fn update_tenant_delete_fcm(&self, _id: &str) -> Result<Tenant> {
panic!("Shouldn't have run in single tenant mode")
}

async fn update_tenant_fcm_v1(
&self,
_id: &str,
Expand All @@ -525,6 +589,10 @@ impl TenantStore for DefaultTenantStore {
panic!("Shouldn't have run in single tenant mode")
}

async fn update_tenant_delete_fcm_v1(&self, _id: &str) -> Result<Tenant> {
panic!("Shouldn't have run in single tenant mode")
}

async fn update_tenant_apns(
&self,
_id: &str,
Expand All @@ -541,6 +609,10 @@ impl TenantStore for DefaultTenantStore {
panic!("Shouldn't have run in single tenant mode")
}

async fn update_tenant_delete_apns(&self, _id: &str) -> Result<Tenant> {
panic!("Shouldn't have run in single tenant mode")
}

async fn suspend_tenant(&self, _id: &str, _reason: &str) -> Result<()> {
panic!("Shouldn't have run in single tenant mode")
}
Expand Down
Loading

0 comments on commit 66b31e2

Please sign in to comment.