Page MenuHomePhabricator

D12350.id41434.diff
No OneTemporary

D12350.id41434.diff

diff --git a/services/identity/src/client_service.rs b/services/identity/src/client_service.rs
--- a/services/identity/src/client_service.rs
+++ b/services/identity/src/client_service.rs
@@ -147,6 +147,12 @@
message.username.clone(),
message.farcaster_id.clone(),
)?;
+ self
+ .check_device_id_taken(
+ &registration_state.flattened_device_key_upload,
+ None,
+ )
+ .await?;
let server_registration = comm_opaque2::server::Registration::new();
let server_message = server_registration
.start(
@@ -207,6 +213,12 @@
message.username.clone(),
None,
)?;
+ self
+ .check_device_id_taken(
+ &registration_state.flattened_device_key_upload,
+ None,
+ )
+ .await?;
let server_registration = comm_opaque2::server::Registration::new();
let server_message = server_registration
.start(
@@ -336,6 +348,9 @@
let flattened_device_key_upload =
construct_flattened_device_key_upload(&message)?;
+ self
+ .check_device_id_taken(&flattened_device_key_upload, Some(&user_id))
+ .await?;
let maybe_device_to_remove = self
.get_keyserver_device_to_remove(
@@ -502,6 +517,10 @@
));
};
+ self
+ .check_device_id_taken(&flattened_device_key_upload, Some(&user_id))
+ .await?;
+
self
.client
.add_user_device(
@@ -597,6 +616,9 @@
let flattened_device_key_upload =
construct_flattened_device_key_upload(&message)?;
+ self
+ .check_device_id_taken(&flattened_device_key_upload, None)
+ .await?;
let login_time = chrono::Utc::now();
@@ -682,6 +704,9 @@
let flattened_device_key_upload =
construct_flattened_device_key_upload(&message)?;
+ self
+ .check_device_id_taken(&flattened_device_key_upload, None)
+ .await?;
let initial_device_list = message.get_and_verify_initial_device_list()?;
let social_proof =
@@ -746,6 +771,10 @@
let nonce = challenge_response.verify_and_get_nonce(&device_id)?;
self.verify_and_remove_nonce(&nonce).await?;
+ self
+ .check_device_id_taken(&flattened_device_key_upload, Some(&user_id))
+ .await?;
+
let user_identity = self
.client
.get_user_identity(&user_id)
@@ -1081,6 +1110,40 @@
Ok(())
}
+ async fn check_device_id_taken(
+ &self,
+ key_upload: &FlattenedDeviceKeyUpload,
+ requesting_user_id: Option<&str>,
+ ) -> Result<(), tonic::Status> {
+ let device_id = key_upload.device_id_key.as_str();
+ let Some(existing_device_user_id) = self
+ .client
+ .find_user_id_for_device(device_id)
+ .await
+ .map_err(handle_db_error)?
+ else {
+ // device ID doesn't exist
+ return Ok(());
+ };
+
+ // allow already-existing device ID for the same user
+ match requesting_user_id {
+ Some(user_id) if user_id == existing_device_user_id => {
+ debug!(
+ "Found already-existing device {} for user {}",
+ device_id, user_id
+ );
+ Ok(())
+ }
+ _ => {
+ warn!("Device ID already exists: {device_id}");
+ Err(tonic::Status::already_exists(
+ tonic_status_messages::DEVICE_ID_ALREADY_EXISTS,
+ ))
+ }
+ }
+ }
+
async fn verify_and_remove_nonce(
&self,
nonce: &str,
diff --git a/services/identity/src/constants.rs b/services/identity/src/constants.rs
--- a/services/identity/src/constants.rs
+++ b/services/identity/src/constants.rs
@@ -230,6 +230,7 @@
pub const USERNAME_RESERVED: &str = "username_reserved";
pub const WALLET_ADDRESS_TAKEN: &str = "wallet_address_taken";
pub const WALLET_ADDRESS_NOT_RESERVED: &str = "wallet_address_not_reserved";
+ pub const DEVICE_ID_ALREADY_EXISTS: &str = "device_id_already_exists";
pub const USER_NOT_FOUND: &str = "user_not_found";
pub const INVALID_NONCE: &str = "invalid_nonce";
pub const NONCE_EXPIRED: &str = "nonce_expired";
diff --git a/services/identity/src/database/device_list.rs b/services/identity/src/database/device_list.rs
--- a/services/identity/src/database/device_list.rs
+++ b/services/identity/src/database/device_list.rs
@@ -746,11 +746,13 @@
Ok(user_devices_keys)
}
+ /// Find owner's user ID for given device ID. Useful for finding
+ /// devices table partition key.
#[tracing::instrument(skip_all)]
- pub async fn find_device_by_id(
+ pub async fn find_user_id_for_device(
&self,
device_id: &str,
- ) -> Result<Option<DeviceRow>, Error> {
+ ) -> Result<Option<String>, Error> {
let response = self
.client
.query()
@@ -785,15 +787,23 @@
return Err(Error::IllegalState);
}
- let Some(user_id) = results
+ let user_id = results
.pop()
.map(|mut attrs| attrs.take_attr::<String>(devices_table::ATTR_USER_ID))
- .transpose()?
- else {
+ .transpose()?;
+
+ Ok(user_id)
+ }
+
+ #[tracing::instrument(skip_all)]
+ pub async fn find_device_by_id(
+ &self,
+ device_id: &str,
+ ) -> Result<Option<DeviceRow>, Error> {
+ let Some(user_id) = self.find_user_id_for_device(device_id).await? else {
debug!("No device found with ID: {}", device_id);
return Ok(None);
};
-
self.get_device_data(user_id, device_id).await
}

File Metadata

Mime Type
text/plain
Expires
Sun, Nov 17, 4:20 AM (19 h, 36 m)
Storage Engine
blob
Storage Format
Raw Data
Storage Handle
2513235
Default Alt Text
D12350.id41434.diff (5 KB)

Event Timeline