Page Menu
Home
Phabricator
Search
Configure Global Search
Log In
Files
F3398845
D10215.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
D10215.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
@@ -5,6 +5,7 @@
use aws_sdk_dynamodb::model::AttributeValue;
use chrono::{DateTime, Utc};
+use tracing::warn;
use crate::{
constants::devices_table::*,
@@ -62,6 +63,15 @@
}
}
+impl From<DeviceListKeyAttribute> for AttributeValue {
+ fn from(value: DeviceListKeyAttribute) -> Self {
+ AttributeValue::S(format!(
+ "{DEVICE_LIST_KEY_PREFIX}{}",
+ value.0.to_rfc3339()
+ ))
+ }
+}
+
impl TryFrom<Option<AttributeValue>> for DeviceIDAttribute {
type Error = DBItemError;
fn try_from(value: Option<AttributeValue>) -> Result<Self, Self::Error> {
@@ -81,6 +91,33 @@
}
}
+impl TryFrom<Option<AttributeValue>> for DeviceListKeyAttribute {
+ type Error = DBItemError;
+ fn try_from(value: Option<AttributeValue>) -> Result<Self, Self::Error> {
+ let item_id = parse_string_attribute(ATTR_ITEM_ID, value)?;
+
+ // remove the device-list- prefix, then parse the timestamp
+ let timestamp: DateTime<Utc> = item_id
+ .strip_prefix(DEVICE_LIST_KEY_PREFIX)
+ .ok_or_else(|| DBItemError {
+ attribute_name: ATTR_ITEM_ID.to_string(),
+ attribute_value: Some(AttributeValue::S(item_id.clone())),
+ attribute_error: DBItemAttributeError::InvalidValue,
+ })
+ .and_then(|s| {
+ s.parse().map_err(|e| {
+ DBItemError::new(
+ ATTR_ITEM_ID.to_string(),
+ Some(AttributeValue::S(item_id.clone())),
+ DBItemAttributeError::InvalidTimestamp(e),
+ )
+ })
+ })?;
+
+ Ok(Self(timestamp))
+ }
+}
+
impl TryFrom<RawAttributes> for DeviceRow {
type Error = DBItemError;
@@ -227,3 +264,79 @@
})
}
}
+
+impl TryFrom<RawAttributes> for DeviceListRow {
+ type Error = DBItemError;
+
+ fn try_from(mut attrs: RawAttributes) -> Result<Self, Self::Error> {
+ let user_id =
+ parse_string_attribute(ATTR_USER_ID, attrs.remove(ATTR_USER_ID))?;
+ let DeviceListKeyAttribute(timestamp) =
+ attrs.remove(ATTR_ITEM_ID).try_into()?;
+
+ // validate timestamps are in sync
+ let timestamps_match = attrs
+ .remove(ATTR_TIMESTAMP)
+ .and_then(|attr| attr.as_n().ok().cloned())
+ .and_then(|val| val.parse::<i64>().ok())
+ .filter(|val| *val == timestamp.timestamp_millis())
+ .is_some();
+ if !timestamps_match {
+ warn!(
+ "DeviceList timestamp mismatch for (userID={}, itemID={})",
+ &user_id,
+ timestamp.to_rfc3339()
+ );
+ }
+
+ // this should be a list of strings
+ let device_ids = attrs
+ .remove(ATTR_DEVICE_IDS)
+ .ok_or_else(|| {
+ DBItemError::new(
+ ATTR_DEVICE_IDS.to_string(),
+ None,
+ DBItemAttributeError::Missing,
+ )
+ })?
+ .to_vec(ATTR_DEVICE_IDS)?
+ .iter()
+ .map(|v| v.to_string("device_ids[?]").cloned())
+ .collect::<Result<Vec<String>, DBItemError>>()?;
+
+ Ok(Self {
+ user_id,
+ timestamp,
+ device_ids,
+ })
+ }
+}
+
+impl From<DeviceListRow> for RawAttributes {
+ fn from(device_list: DeviceListRow) -> Self {
+ let mut attrs = HashMap::new();
+ attrs.insert(
+ ATTR_USER_ID.to_string(),
+ AttributeValue::S(device_list.user_id.clone()),
+ );
+ attrs.insert(
+ ATTR_ITEM_ID.to_string(),
+ DeviceListKeyAttribute(device_list.timestamp).into(),
+ );
+ attrs.insert(
+ ATTR_TIMESTAMP.to_string(),
+ AttributeValue::N(device_list.timestamp.timestamp_millis().to_string()),
+ );
+ attrs.insert(
+ ATTR_DEVICE_IDS.to_string(),
+ AttributeValue::L(
+ device_list
+ .device_ids
+ .into_iter()
+ .map(AttributeValue::S)
+ .collect(),
+ ),
+ );
+ attrs
+ }
+}
File Metadata
Details
Attached
Mime Type
text/plain
Expires
Tue, Dec 3, 12:44 AM (19 h, 14 m)
Storage Engine
blob
Storage Format
Raw Data
Storage Handle
2609504
Default Alt Text
D10215.diff (3 KB)
Attached To
Mode
D10215: [identity] Implemet attribute conversions for DeviceList row
Attached
Detach File
Event Timeline
Log In to Comment