Skip to content

Commit 64ee95f

Browse files
committed
[identity] Use DB conversion helpers from comm-lib
Summary: This finally resolves [[ https://linear.app/comm/issue/ENG-5476/use-comm-services-lib-database-utils-in-identity-service | ENG-5476 ]]. Used database conversion traits from comm-lib wherever possible. For some places, I introduced the `deprecated` attribute. This diff could grow too large. Depends on D10447 Test Plan: Identity compiles and runs. Commtest passes, also played with it manually. Reviewers: varun, michal Reviewed By: michal Subscribers: ashoat, tomek Differential Revision: https://phab.comm.dev/D10448
1 parent 81b299f commit 64ee95f

3 files changed

Lines changed: 41 additions & 126 deletions

File tree

services/identity/src/database.rs

Lines changed: 24 additions & 88 deletions
Original file line numberDiff line numberDiff line change
@@ -7,7 +7,10 @@ use comm_lib::aws::ddb::{
77
types::{AttributeValue, PutRequest, ReturnConsumedCapacity, WriteRequest},
88
};
99
use comm_lib::aws::{AwsConfig, DynamoDBClient};
10-
use comm_lib::database::{AttributeMap, DBItemAttributeError, DBItemError};
10+
use comm_lib::database::{
11+
AttributeExtractor, AttributeMap, DBItemAttributeError, DBItemError,
12+
TryFromAttribute,
13+
};
1114
use constant_time_eq::constant_time_eq;
1215
use std::collections::{HashMap, HashSet};
1316
use std::str::FromStr;
@@ -723,7 +726,7 @@ impl DatabaseClient {
723726
item: Some(mut item),
724727
..
725728
}) => {
726-
let created = parse_date_time_attribute(
729+
let created = DateTime::<Utc>::try_from_attr(
727730
ACCESS_TOKEN_TABLE_CREATED_ATTRIBUTE,
728731
item.remove(ACCESS_TOKEN_TABLE_CREATED_ATTRIBUTE),
729732
)?;
@@ -978,15 +981,13 @@ impl DatabaseClient {
978981
mut user: AttributeMap,
979982
get_one_time_keys: bool,
980983
) -> Result<Option<Devices>, Error> {
981-
let devices = parse_map_attribute(
982-
USERS_TABLE_DEVICES_ATTRIBUTE,
983-
user.remove(USERS_TABLE_DEVICES_ATTRIBUTE),
984-
)?;
984+
let devices: AttributeMap =
985+
user.take_attr(USERS_TABLE_DEVICES_ATTRIBUTE)?;
985986

986987
let mut devices_response = HashMap::with_capacity(devices.len());
987988
for (device_id_key, device_info) in devices {
988989
let device_info_map =
989-
parse_map_attribute(&device_id_key, Some(device_info))?;
990+
AttributeMap::try_from_attr(&device_id_key, Some(device_info))?;
990991

991992
let mut device_info_string_map = HashMap::new();
992993
for (attribute_name, attribute_value) in device_info_map {
@@ -1000,7 +1001,7 @@ impl DatabaseClient {
10001001
}
10011002

10021003
let attribute_value_str =
1003-
parse_string_attribute(&attribute_name, Some(attribute_value))?;
1004+
String::try_from_attr(&attribute_name, Some(attribute_value))?;
10041005
device_info_string_map.insert(attribute_name, attribute_value_str);
10051006
}
10061007

@@ -1036,12 +1037,10 @@ impl DatabaseClient {
10361037
.get_user_from_user_info(user_info.clone(), auth_type)
10371038
.await
10381039
{
1039-
Ok(Some(mut user)) => parse_string_attribute(
1040-
USERS_TABLE_PARTITION_KEY,
1041-
user.remove(USERS_TABLE_PARTITION_KEY),
1042-
)
1043-
.map(Some)
1044-
.map_err(Error::Attribute),
1040+
Ok(Some(mut user)) => user
1041+
.take_attr(USERS_TABLE_PARTITION_KEY)
1042+
.map(Some)
1043+
.map_err(Error::Attribute),
10451044
Ok(_) => Ok(None),
10461045
Err(e) => Err(e),
10471046
}
@@ -1056,10 +1055,7 @@ impl DatabaseClient {
10561055
.await
10571056
{
10581057
Ok(Some(mut user)) => {
1059-
let user_id = parse_string_attribute(
1060-
USERS_TABLE_PARTITION_KEY,
1061-
user.remove(USERS_TABLE_PARTITION_KEY),
1062-
)?;
1058+
let user_id = user.take_attr(USERS_TABLE_PARTITION_KEY)?;
10631059
let password_file = parse_registration_data_attribute(
10641060
user.remove(USERS_TABLE_REGISTRATION_ATTRIBUTE),
10651061
)?;
@@ -1115,10 +1111,9 @@ impl DatabaseClient {
11151111
let mut result = Vec::new();
11161112
if let Some(attributes) = scan_output.items {
11171113
for mut attribute in attributes {
1118-
if let Ok(username) = parse_string_attribute(
1119-
USERS_TABLE_USERNAME_ATTRIBUTE,
1120-
attribute.remove(USERS_TABLE_USERNAME_ATTRIBUTE),
1121-
) {
1114+
if let Ok(username) =
1115+
attribute.take_attr(USERS_TABLE_USERNAME_ATTRIBUTE)
1116+
{
11221117
result.push(username);
11231118
}
11241119
}
@@ -1178,19 +1173,14 @@ impl DatabaseClient {
11781173
return Ok(None);
11791174
};
11801175

1181-
let nonce = parse_string_attribute(
1182-
NONCE_TABLE_PARTITION_KEY,
1183-
item.remove(&NONCE_TABLE_PARTITION_KEY.to_string()),
1184-
)?;
1185-
1186-
let created = parse_date_time_attribute(
1176+
let nonce = item.take_attr(NONCE_TABLE_PARTITION_KEY)?;
1177+
let created = DateTime::<Utc>::try_from_attr(
11871178
NONCE_TABLE_CREATED_ATTRIBUTE,
1188-
item.remove(&NONCE_TABLE_CREATED_ATTRIBUTE.to_string()),
1179+
item.remove(NONCE_TABLE_CREATED_ATTRIBUTE),
11891180
)?;
1190-
1191-
let expiration_time = parse_date_time_attribute(
1181+
let expiration_time = DateTime::<Utc>::try_from_attr(
11921182
NONCE_TABLE_EXPIRATION_TIME_ATTRIBUTE,
1193-
item.remove(&NONCE_TABLE_EXPIRATION_TIME_ATTRIBUTE.to_string()),
1183+
item.remove(NONCE_TABLE_EXPIRATION_TIME_ATTRIBUTE),
11941184
)?;
11951185

11961186
Ok(Some(NonceData {
@@ -1326,27 +1316,6 @@ fn create_composite_primary_key(
13261316
primary_key
13271317
}
13281318

1329-
fn parse_date_time_attribute(
1330-
attribute_name: &str,
1331-
attribute: Option<AttributeValue>,
1332-
) -> Result<DateTime<Utc>, DBItemError> {
1333-
if let Some(AttributeValue::S(created)) = &attribute {
1334-
created.parse().map_err(|e| {
1335-
DBItemError::new(
1336-
attribute_name.to_string(),
1337-
attribute.into(),
1338-
DBItemAttributeError::InvalidTimestamp(e),
1339-
)
1340-
})
1341-
} else {
1342-
Err(DBItemError::new(
1343-
attribute_name.to_string(),
1344-
attribute.into(),
1345-
DBItemAttributeError::Missing,
1346-
))
1347-
}
1348-
}
1349-
13501319
fn parse_auth_type_attribute(
13511320
attribute: Option<AttributeValue>,
13521321
) -> Result<AuthType, DBItemError> {
@@ -1425,6 +1394,7 @@ fn parse_registration_data_attribute(
14251394
}
14261395
}
14271396

1397+
#[deprecated(note = "Use `comm_lib` counterpart instead")]
14281398
#[allow(dead_code)]
14291399
fn parse_map_attribute(
14301400
attribute_name: &str,
@@ -1460,40 +1430,6 @@ fn parse_map_attribute(
14601430
}
14611431
}
14621432

1463-
fn parse_string_attribute(
1464-
attribute_name: &str,
1465-
attribute_value: Option<AttributeValue>,
1466-
) -> Result<String, DBItemError> {
1467-
match attribute_value {
1468-
Some(AttributeValue::S(value)) => Ok(value),
1469-
Some(_) => {
1470-
error!(
1471-
attribute = attribute_name,
1472-
value = ?attribute_value,
1473-
error_type = "IncorrectType",
1474-
"Unexpected attribute type when parsing string attribute"
1475-
);
1476-
Err(DBItemError::new(
1477-
attribute_name.to_string(),
1478-
attribute_value.into(),
1479-
DBItemAttributeError::IncorrectType,
1480-
))
1481-
}
1482-
None => {
1483-
error!(
1484-
attribute = attribute_name,
1485-
error_type = "Missing",
1486-
"Attribute is missing"
1487-
);
1488-
Err(DBItemError::new(
1489-
attribute_name.to_string(),
1490-
attribute_value.into(),
1491-
DBItemAttributeError::Missing,
1492-
))
1493-
}
1494-
}
1495-
}
1496-
14971433
fn create_device_info(
14981434
flattened_device_key_upload: FlattenedDeviceKeyUpload,
14991435
social_proof: Option<String>,
@@ -1583,7 +1519,7 @@ mod tests {
15831519
fn validate_keys() {
15841520
// Taken from test user
15851521
let example_payload = r#"{\"notificationIdentityPublicKeys\":{\"curve25519\":\"DYmV8VdkjwG/VtC8C53morogNJhpTPT/4jzW0/cxzQo\",\"ed25519\":\"D0BV2Y7Qm36VUtjwyQTJJWYAycN7aMSJmhEsRJpW2mk\"},\"primaryIdentityPublicKeys\":{\"curve25519\":\"Y4ZIqzpE1nv83kKGfvFP6rifya0itRg2hifqYtsISnk\",\"ed25519\":\"cSlL+VLLJDgtKSPlIwoCZg0h0EmHlQoJC08uV/O+jvg\"}}"#;
1586-
let serialized_payload = KeyPayload::from_str(&example_payload).unwrap();
1522+
let serialized_payload = KeyPayload::from_str(example_payload).unwrap();
15871523

15881524
assert_eq!(
15891525
serialized_payload

services/identity/src/database/device_list.rs

Lines changed: 16 additions & 38 deletions
Original file line numberDiff line numberDiff line change
@@ -9,7 +9,10 @@ use comm_lib::{
99
TransactWriteItem, Update, WriteRequest,
1010
},
1111
},
12-
database::{AttributeMap, DBItemAttributeError, DBItemError, DynamoDBError},
12+
database::{
13+
AttributeExtractor, AttributeMap, DBItemAttributeError, DBItemError,
14+
DynamoDBError, TryFromAttribute,
15+
},
1316
};
1417
use tracing::{error, warn};
1518

@@ -20,13 +23,12 @@ use crate::{
2023
USERS_TABLE, USERS_TABLE_DEVICELIST_TIMESTAMP_ATTRIBUTE_NAME,
2124
USERS_TABLE_PARTITION_KEY,
2225
},
23-
database::parse_string_attribute,
2426
ddb_utils::AttributesOptionExt,
2527
error::{DeviceListError, Error, FromAttributeValue},
2628
grpc_services::protos::unauth::DeviceType,
2729
};
2830

29-
use super::{parse_date_time_attribute, DatabaseClient};
31+
use super::DatabaseClient;
3032

3133
#[derive(Clone, Debug)]
3234
pub struct DeviceRow {
@@ -119,7 +121,7 @@ impl From<DeviceListKeyAttribute> for AttributeValue {
119121
impl TryFrom<Option<AttributeValue>> for DeviceIDAttribute {
120122
type Error = DBItemError;
121123
fn try_from(value: Option<AttributeValue>) -> Result<Self, Self::Error> {
122-
let item_id = parse_string_attribute(ATTR_ITEM_ID, value)?;
124+
let item_id = String::try_from_attr(ATTR_ITEM_ID, value)?;
123125

124126
// remove the device- prefix
125127
let device_id = item_id
@@ -138,7 +140,7 @@ impl TryFrom<Option<AttributeValue>> for DeviceIDAttribute {
138140
impl TryFrom<Option<AttributeValue>> for DeviceListKeyAttribute {
139141
type Error = DBItemError;
140142
fn try_from(value: Option<AttributeValue>) -> Result<Self, Self::Error> {
141-
let item_id = parse_string_attribute(ATTR_ITEM_ID, value)?;
143+
let item_id = String::try_from_attr(ATTR_ITEM_ID, value)?;
142144

143145
// remove the device-list- prefix, then parse the timestamp
144146
let timestamp: DateTime<Utc> = item_id
@@ -166,12 +168,10 @@ impl TryFrom<AttributeMap> for DeviceRow {
166168
type Error = DBItemError;
167169

168170
fn try_from(mut attrs: AttributeMap) -> Result<Self, Self::Error> {
169-
let user_id =
170-
parse_string_attribute(ATTR_USER_ID, attrs.remove(ATTR_USER_ID))?;
171+
let user_id = attrs.take_attr(ATTR_USER_ID)?;
171172
let DeviceIDAttribute(device_id) = attrs.remove(ATTR_ITEM_ID).try_into()?;
172173

173-
let raw_device_type =
174-
parse_string_attribute(ATTR_DEVICE_TYPE, attrs.remove(ATTR_DEVICE_TYPE))?;
174+
let raw_device_type: String = attrs.take_attr(ATTR_DEVICE_TYPE)?;
175175
let device_type =
176176
DeviceType::from_str_name(&raw_device_type).ok_or_else(|| {
177177
DBItemError::new(
@@ -260,12 +260,8 @@ impl From<IdentityKeyInfo> for AttributeValue {
260260
impl TryFrom<AttributeMap> for IdentityKeyInfo {
261261
type Error = DBItemError;
262262
fn try_from(mut attrs: AttributeMap) -> Result<Self, Self::Error> {
263-
let key_payload =
264-
parse_string_attribute(ATTR_KEY_PAYLOAD, attrs.remove(ATTR_KEY_PAYLOAD))?;
265-
let key_payload_signature = parse_string_attribute(
266-
ATTR_KEY_PAYLOAD_SIGNATURE,
267-
attrs.remove(ATTR_KEY_PAYLOAD_SIGNATURE),
268-
)?;
263+
let key_payload = attrs.take_attr(ATTR_KEY_PAYLOAD)?;
264+
let key_payload_signature = attrs.take_attr(ATTR_KEY_PAYLOAD_SIGNATURE)?;
269265
// social proof is optional
270266
let social_proof = attrs
271267
.remove(ATTR_SOCIAL_PROOF)
@@ -296,12 +292,8 @@ impl From<PreKey> for AttributeValue {
296292
impl TryFrom<AttributeMap> for PreKey {
297293
type Error = DBItemError;
298294
fn try_from(mut attrs: AttributeMap) -> Result<Self, Self::Error> {
299-
let pre_key =
300-
parse_string_attribute(ATTR_PREKEY, attrs.remove(ATTR_PREKEY))?;
301-
let pre_key_signature = parse_string_attribute(
302-
ATTR_PREKEY_SIGNATURE,
303-
attrs.remove(ATTR_PREKEY_SIGNATURE),
304-
)?;
295+
let pre_key = attrs.take_attr(ATTR_PREKEY)?;
296+
let pre_key_signature = attrs.take_attr(ATTR_PREKEY_SIGNATURE)?;
305297
Ok(Self {
306298
pre_key,
307299
pre_key_signature,
@@ -313,8 +305,7 @@ impl TryFrom<AttributeMap> for DeviceListRow {
313305
type Error = DBItemError;
314306

315307
fn try_from(mut attrs: AttributeMap) -> Result<Self, Self::Error> {
316-
let user_id =
317-
parse_string_attribute(ATTR_USER_ID, attrs.remove(ATTR_USER_ID))?;
308+
let user_id = attrs.take_attr(ATTR_USER_ID)?;
318309
let DeviceListKeyAttribute(timestamp) =
319310
attrs.remove(ATTR_ITEM_ID).try_into()?;
320311

@@ -333,20 +324,7 @@ impl TryFrom<AttributeMap> for DeviceListRow {
333324
);
334325
}
335326

336-
// this should be a list of strings
337-
let device_ids = attrs
338-
.remove(ATTR_DEVICE_IDS)
339-
.ok_or_else(|| {
340-
DBItemError::new(
341-
ATTR_DEVICE_IDS.to_string(),
342-
None.into(),
343-
DBItemAttributeError::Missing,
344-
)
345-
})?
346-
.to_vec(ATTR_DEVICE_IDS)?
347-
.iter()
348-
.map(|v| v.to_string("device_ids[?]").cloned())
349-
.collect::<Result<Vec<String>, DBItemError>>()?;
327+
let device_ids: Vec<String> = attrs.take_attr(ATTR_DEVICE_IDS)?;
350328

351329
Ok(Self {
352330
user_id,
@@ -725,7 +703,7 @@ async fn get_current_devicelist_timestamp(
725703
return Ok(None);
726704
}
727705

728-
let timestamp = parse_date_time_attribute(
706+
let timestamp = DateTime::<Utc>::try_from_attr(
729707
USERS_TABLE_DEVICELIST_TIMESTAMP_ATTRIBUTE_NAME,
730708
raw_datetime,
731709
)?;

services/identity/src/error.rs

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -29,6 +29,7 @@ pub enum DeviceListError {
2929
ConcurrentUpdateError,
3030
}
3131

32+
#[deprecated(note = "Use comm-lib traits instead")]
3233
pub trait FromAttributeValue {
3334
fn to_vec(
3435
&self,

0 commit comments

Comments
 (0)