Skip to content

Commit

Permalink
register missing push devices at login
Browse files Browse the repository at this point in the history
  • Loading branch information
stefan0xC committed Aug 22, 2023
1 parent 3d2df6c commit 69ae520
Show file tree
Hide file tree
Showing 4 changed files with 67 additions and 9 deletions.
14 changes: 7 additions & 7 deletions src/api/core/accounts.rs
Original file line number Diff line number Diff line change
Expand Up @@ -955,25 +955,25 @@ async fn post_device_token(uuid: &str, data: JsonUpcase<PushToken>, headers: Hea

#[put("/devices/identifier/<uuid>/token", data = "<data>")]
async fn put_device_token(uuid: &str, data: JsonUpcase<PushToken>, headers: Headers, mut conn: DbConn) -> EmptyResult {
if !CONFIG.push_enabled() {
return Ok(());
}

let data = data.into_inner().data;
let token = data.PushToken;
let mut device = match Device::find_by_uuid_and_user(&headers.device.uuid, &headers.user.uuid, &mut conn).await {
Some(device) => device,
None => err!(format!("Error: device {uuid} should be present before a token can be assigned")),
};
device.push_token = Some(token);
if device.push_uuid.is_none() {
/* only generate a new push_uuid if push is enabled, so we can call register_push_device later */
if device.push_uuid.is_none() && CONFIG.push_enabled() {
device.push_uuid = Some(uuid::Uuid::new_v4().to_string());
}
if let Err(e) = device.save(&mut conn).await {
err!(format!("An error occured while trying to save the device push token: {e}"));
}
if let Err(e) = register_push_device(headers.user.uuid, device).await {
err!(format!("An error occured while proceeding registration of a device: {e}"));

if CONFIG.push_enabled() {
if let Err(e) = register_push_device(device).await {
err!(format!("An error occured while proceeding registration of a device: {e}"));
}
}

Ok(())
Expand Down
4 changes: 4 additions & 0 deletions src/api/identity.rs
Original file line number Diff line number Diff line change
Expand Up @@ -12,6 +12,7 @@ use crate::{
core::accounts::{PreloginData, RegisterData, _prelogin, _register},
core::log_user_event,
core::two_factor::{duo, email, email::EmailTokenData, yubikey},
push::register_missing_push_devices_for_user,
ApiResult, EmptyResult, JsonResult, JsonUpcase,
},
auth::{generate_organization_api_key_login_claims, ClientHeaders, ClientIp},
Expand Down Expand Up @@ -206,6 +207,9 @@ async fn _password_login(
)
}

// Register possible missing push devices
register_missing_push_devices_for_user(&user.uuid, conn).await?;

let now = Utc::now().naive_utc();

if user.verified_at.is_none() && CONFIG.mail_enabled() && CONFIG.signups_verify() {
Expand Down
45 changes: 43 additions & 2 deletions src/api/push.rs
Original file line number Diff line number Diff line change
Expand Up @@ -72,15 +72,56 @@ async fn get_auth_push_token() -> ApiResult<String> {
Ok(push_token.access_token.clone())
}

pub async fn register_push_device(user_uuid: String, device: Device) -> EmptyResult {
pub async fn register_missing_push_devices_for_user(user_uuid: &str, conn: &mut crate::db::DbConn) -> EmptyResult {
if !CONFIG.push_enabled() {
return Ok(());
}

let devices = Device::find_unregistered_push_devices_by_user(user_uuid, conn).await;

if devices.is_empty() {
debug!("No push device needs to be registered.");
return Ok(());
}

// Prevent registration of too many devices at once.
if devices.len() > 2 {
debug!(
"You account has too many ({}) unregistered push devices. Consider cleaning up your devices table.",
devices.len()
);
return Ok(());
}

// find all mobile devices that have not been registered
for mut device in devices {
debug!("Registering Device {}", device.uuid);
// generate a random push_uuid so we know the device is registered
device.push_uuid = Some(uuid::Uuid::new_v4().to_string());
// set a push token in case it's empty
if device.push_token.is_none() {
debug!("Skipping device registration because of an empty push token.");
continue;
}
if let Err(e) = device.save(conn).await {
err!(format!("An error occured while trying to save the device push token: {e}"));
}
if let Err(e) = register_push_device(device).await {
err!(format!("An error occured while proceeding registration of a device: {e}"));
}
}
Ok(())
}

pub async fn register_push_device(device: Device) -> EmptyResult {
if !CONFIG.push_enabled() {
return Ok(());
}
let auth_push_token = get_auth_push_token().await?;

//Needed to register a device for push to bitwarden :
let data = json!({
"userId": user_uuid,
"userId": device.user_uuid,
"deviceId": device.push_uuid,
"identifier": device.uuid,
"type": device.atype,
Expand Down
13 changes: 13 additions & 0 deletions src/db/models/device.rs
Original file line number Diff line number Diff line change
Expand Up @@ -203,6 +203,19 @@ impl Device {
.from_db()
}}
}

pub async fn find_unregistered_push_devices_by_user(user_uuid: &str, conn: &mut DbConn) -> Vec<Self> {
db_run! { conn: {
devices::table
.filter(devices::user_uuid.eq(user_uuid))
.filter(devices::atype.eq(DeviceType::Android as i32).or(devices::atype.eq(DeviceType::Ios as i32)))
.filter(devices::push_uuid.is_null())
.load::<DeviceDb>(conn)
.expect("Error loading mobile devices")
.from_db()
}}
}

pub async fn find_push_devices_by_user(user_uuid: &str, conn: &mut DbConn) -> Vec<Self> {
db_run! { conn: {
devices::table
Expand Down

0 comments on commit 69ae520

Please sign in to comment.