-
Notifications
You must be signed in to change notification settings - Fork 16
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
feat: Validate user subscription data in autoendpoint (#160)
* Update autoendpoint so only one cadence version is used * Remove unnecessary Rc and Box in DynamoStorage and support Send + Sync DynamoDbClient and StatsdClient both are internally Arc, so clones are already cheap and refer to the same data. This change also makes DynamoStorage Send + Sync. * Autoendpoint: Connect to DynamoDB * Add DynamoStorage::get_user_channels * Read and validate user data in the Subscription extractor * Remove router_data from DynamoDbUser The associated validation is not included, so it is unused. Closes #156
- Loading branch information
1 parent
4d5b6ca
commit 8efa42c
Showing
10 changed files
with
194 additions
and
74 deletions.
There are no files selected for viewing
Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.
Oops, something went wrong.
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
|
@@ -5,3 +5,4 @@ pub mod notification; | |
pub mod notification_headers; | ||
pub mod subscription; | ||
pub mod token_info; | ||
pub mod user; |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,85 @@ | ||
//! User validations | ||
use crate::error::{ApiErrorKind, ApiResult}; | ||
use crate::server::ServerState; | ||
use autopush_common::db::{DynamoDbUser, DynamoStorage}; | ||
use cadence::{Counted, StatsdClient}; | ||
use futures::compat::Future01CompatExt; | ||
use uuid::Uuid; | ||
|
||
/// Valid `DynamoDbUser::router_type` values | ||
const VALID_ROUTERS: [&str; 5] = ["webpush", "gcm", "fcm", "apns", "adm"]; | ||
|
||
/// Perform some validations on the user, including: | ||
/// - Validate router type | ||
/// - (WebPush) Check that the subscription/channel exists | ||
/// - (WebPush) Drop user if inactive | ||
pub async fn validate_user( | ||
user: &DynamoDbUser, | ||
channel_id: &Uuid, | ||
state: &ServerState, | ||
) -> ApiResult<()> { | ||
if !VALID_ROUTERS.contains(&user.router_type.as_str()) { | ||
debug!("Unknown router type, dropping user"; "user" => ?user); | ||
drop_user(&user.uaid, &state.ddb, &state.metrics).await?; | ||
return Err(ApiErrorKind::NoSubscription.into()); | ||
} | ||
|
||
if user.router_type == "webpush" { | ||
validate_webpush_user(user, channel_id, &state.ddb, &state.metrics).await?; | ||
} | ||
|
||
Ok(()) | ||
} | ||
|
||
/// Make sure the user is not inactive and the subscription channel exists | ||
async fn validate_webpush_user( | ||
user: &DynamoDbUser, | ||
channel_id: &Uuid, | ||
ddb: &DynamoStorage, | ||
metrics: &StatsdClient, | ||
) -> ApiResult<()> { | ||
// Make sure the user is active (has a valid message table) | ||
let message_table = match user.current_month.as_ref() { | ||
Some(table) => table, | ||
None => { | ||
debug!("Missing `current_month` value, dropping user"; "user" => ?user); | ||
drop_user(&user.uaid, ddb, metrics).await?; | ||
return Err(ApiErrorKind::NoSubscription.into()); | ||
} | ||
}; | ||
|
||
if !ddb.message_table_names.contains(message_table) { | ||
debug!("User is inactive, dropping user"; "user" => ?user); | ||
drop_user(&user.uaid, ddb, metrics).await?; | ||
return Err(ApiErrorKind::NoSubscription.into()); | ||
} | ||
|
||
// Make sure the subscription channel exists | ||
let channel_ids = ddb | ||
.get_user_channels(&user.uaid, message_table) | ||
.compat() | ||
.await | ||
.map_err(ApiErrorKind::Database)?; | ||
|
||
if !channel_ids.contains(channel_id) { | ||
return Err(ApiErrorKind::NoSubscription.into()); | ||
} | ||
|
||
Ok(()) | ||
} | ||
|
||
/// Drop a user and increment associated metric | ||
async fn drop_user(uaid: &Uuid, ddb: &DynamoStorage, metrics: &StatsdClient) -> ApiResult<()> { | ||
metrics | ||
.incr_with_tags("updates.drop_user") | ||
.with_tag("errno", "102") | ||
.send(); | ||
|
||
ddb.drop_uaid(uaid) | ||
.compat() | ||
.await | ||
.map_err(ApiErrorKind::Database)?; | ||
|
||
Ok(()) | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Oops, something went wrong.