Page Menu
Home
Phabricator
Search
Configure Global Search
Log In
Files
F3398775
D10220.diff
No One
Temporary
Actions
View File
Edit File
Delete File
View Transforms
Subscribe
Mute Notifications
Award Token
Flag For Later
Size
3 KB
Referenced Files
None
Subscribers
None
D10220.diff
View Options
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
@@ -13,6 +13,7 @@
use tracing::{error, warn};
use crate::{
+ client_service::FlattenedDeviceKeyUpload,
constants::{
devices_table::{self, *},
USERS_TABLE, USERS_TABLE_DEVICELIST_TIMESTAMP_ATTRIBUTE_NAME,
@@ -67,6 +68,34 @@
pub pre_key_signature: String,
}
+impl DeviceRow {
+ pub fn from_device_key_upload(
+ user_id: impl Into<String>,
+ upload: FlattenedDeviceKeyUpload,
+ social_proof: Option<String>,
+ ) -> Self {
+ Self {
+ user_id: user_id.into(),
+ device_id: upload.device_id_key,
+ device_type: DeviceType::from_str_name(upload.device_type.as_str_name())
+ .expect("DeviceType conversion failed. Identity client and server protos mismatch"),
+ device_key_info: IdentityKeyInfo {
+ key_payload: upload.key_payload,
+ key_payload_signature: upload.key_payload_signature,
+ social_proof,
+ },
+ content_prekey: PreKey {
+ pre_key: upload.content_prekey,
+ pre_key_signature: upload.content_prekey_signature,
+ },
+ notif_prekey: PreKey {
+ pre_key: upload.notif_prekey,
+ pre_key_signature: upload.notif_prekey_signature,
+ }
+ }
+ }
+}
+
impl DeviceListRow {
/// Generates new device list row from given devices
fn new(user_id: impl Into<String>, device_ids: Vec<String>) -> Self {
@@ -448,6 +477,51 @@
.map_err(Error::from)
}
+ /// Adds new device to user's device list. If the device already exists, the
+ /// operation fails. Transactionally generates new device list version.
+ pub async fn add_device(
+ &self,
+ user_id: impl Into<String>,
+ device_key_upload: FlattenedDeviceKeyUpload,
+ social_proof: Option<String>,
+ ) -> Result<(), Error> {
+ let user_id: String = user_id.into();
+ self
+ .transact_update_devicelist(&user_id, |ref mut device_ids| {
+ let new_device = DeviceRow::from_device_key_upload(
+ &user_id,
+ device_key_upload,
+ social_proof,
+ );
+
+ if device_ids.iter().any(|id| &new_device.device_id == id) {
+ warn!(
+ "Device already exists in user's device list \
+ (userID={}, deviceID={})",
+ &user_id, &new_device.device_id
+ );
+ return Err(Error::DeviceList(DeviceListError::DeviceAlreadyExists));
+ }
+ device_ids.push(new_device.device_id.clone());
+
+ // Put new device
+ let put_device = Put::builder()
+ .table_name(devices_table::NAME)
+ .set_item(Some(new_device.into()))
+ .condition_expression(
+ "attribute_not_exists(#user_id) AND attribute_not_exists(#item_id)",
+ )
+ .expression_attribute_names("#user_id", ATTR_USER_ID)
+ .expression_attribute_names("#item_id", ATTR_ITEM_ID)
+ .build();
+ let put_device_operation =
+ TransactWriteItem::builder().put(put_device).build();
+
+ Ok(put_device_operation)
+ })
+ .await
+ }
+
/// Performs a transactional update of the device list for the user. Afterwards
/// generates a new device list and updates the timestamp in the users table.
/// This is done in a transaction. Operation fails if the device list has been
diff --git a/services/identity/src/error.rs b/services/identity/src/error.rs
--- a/services/identity/src/error.rs
+++ b/services/identity/src/error.rs
@@ -23,6 +23,7 @@
#[derive(Debug, derive_more::Display, derive_more::Error)]
pub enum DeviceListError {
+ DeviceAlreadyExists,
ConcurrentUpdateError,
}
File Metadata
Details
Attached
Mime Type
text/plain
Expires
Tue, Dec 3, 12:28 AM (20 h, 26 s)
Storage Engine
blob
Storage Format
Raw Data
Storage Handle
2609446
Default Alt Text
D10220.diff (3 KB)
Attached To
Mode
D10220: [identity] Add function to add new device to the list
Attached
Detach File
Event Timeline
Log In to Comment