diff --git a/services/identity/src/database.rs b/services/identity/src/database.rs --- a/services/identity/src/database.rs +++ b/services/identity/src/database.rs @@ -7,6 +7,7 @@ types::{AttributeValue, PutRequest, ReturnConsumedCapacity, WriteRequest}, }; use comm_lib::aws::{AwsConfig, DynamoDBClient}; +use comm_lib::database::{AttributeMap, DBItemAttributeError, DBItemError}; use constant_time_eq::constant_time_eq; use std::collections::{HashMap, HashSet}; use std::str::FromStr; @@ -15,7 +16,7 @@ use crate::ddb_utils::{ create_one_time_key_partition_key, into_one_time_put_requests, OlmAccountType, }; -use crate::error::{consume_error, DBItemAttributeError, DBItemError, Error}; +use crate::error::{consume_error, Error}; use chrono::{DateTime, Utc}; use serde::{Deserialize, Serialize}; use tracing::{debug, error, info, warn}; @@ -90,7 +91,7 @@ Error::Attribute(DBItemError { attribute_name: USERS_TABLE_DEVICES_MAP_DEVICE_TYPE_ATTRIBUTE_NAME .to_string(), - attribute_value: Some(AttributeValue::N(value.0.to_string())), + attribute_value: Some(AttributeValue::N(value.0.to_string())).into(), attribute_error: DBItemAttributeError::InvalidValue, }) }) @@ -926,13 +927,16 @@ .get(USERS_TABLE_PARTITION_KEY) .ok_or(DBItemError { attribute_name: USERS_TABLE_PARTITION_KEY.to_string(), - attribute_value: None, + attribute_value: None.into(), attribute_error: DBItemAttributeError::Missing, })? .as_s() .map_err(|_| DBItemError { attribute_name: USERS_TABLE_PARTITION_KEY.to_string(), - attribute_value: first_item.get(USERS_TABLE_PARTITION_KEY).cloned(), + attribute_value: first_item + .get(USERS_TABLE_PARTITION_KEY) + .cloned() + .into(), attribute_error: DBItemAttributeError::IncorrectType, })?; let result = self.get_item_from_users_table(user_id).await?; @@ -971,7 +975,7 @@ async fn get_keys_for_user( &self, - mut user: HashMap, + mut user: AttributeMap, get_one_time_keys: bool, ) -> Result, Error> { let devices = parse_map_attribute( @@ -1330,14 +1334,14 @@ created.parse().map_err(|e| { DBItemError::new( attribute_name.to_string(), - attribute, + attribute.into(), DBItemAttributeError::InvalidTimestamp(e), ) }) } else { Err(DBItemError::new( attribute_name.to_string(), - attribute, + attribute.into(), DBItemAttributeError::Missing, )) } @@ -1352,14 +1356,14 @@ "wallet" => Ok(AuthType::Wallet), _ => Err(DBItemError::new( ACCESS_TOKEN_TABLE_AUTH_TYPE_ATTRIBUTE.to_string(), - attribute, + attribute.into(), DBItemAttributeError::IncorrectType, )), } } else { Err(DBItemError::new( ACCESS_TOKEN_TABLE_AUTH_TYPE_ATTRIBUTE.to_string(), - attribute, + attribute.into(), DBItemAttributeError::Missing, )) } @@ -1372,12 +1376,12 @@ Some(AttributeValue::Bool(valid)) => Ok(valid), Some(_) => Err(DBItemError::new( ACCESS_TOKEN_TABLE_VALID_ATTRIBUTE.to_string(), - attribute, + attribute.into(), DBItemAttributeError::IncorrectType, )), None => Err(DBItemError::new( ACCESS_TOKEN_TABLE_VALID_ATTRIBUTE.to_string(), - attribute, + attribute.into(), DBItemAttributeError::Missing, )), } @@ -1390,12 +1394,12 @@ Some(AttributeValue::S(token)) => Ok(token), Some(_) => Err(DBItemError::new( ACCESS_TOKEN_TABLE_TOKEN_ATTRIBUTE.to_string(), - attribute, + attribute.into(), DBItemAttributeError::IncorrectType, )), None => Err(DBItemError::new( ACCESS_TOKEN_TABLE_TOKEN_ATTRIBUTE.to_string(), - attribute, + attribute.into(), DBItemAttributeError::Missing, )), } @@ -1410,12 +1414,12 @@ } Some(_) => Err(DBItemError::new( USERS_TABLE_REGISTRATION_ATTRIBUTE.to_string(), - attribute, + attribute.into(), DBItemAttributeError::IncorrectType, )), None => Err(DBItemError::new( USERS_TABLE_REGISTRATION_ATTRIBUTE.to_string(), - attribute, + attribute.into(), DBItemAttributeError::Missing, )), } @@ -1425,7 +1429,7 @@ fn parse_map_attribute( attribute_name: &str, attribute_value: Option, -) -> Result, DBItemError> { +) -> Result { match attribute_value { Some(AttributeValue::M(map)) => Ok(map), Some(_) => { @@ -1437,7 +1441,7 @@ ); Err(DBItemError::new( attribute_name.to_string(), - attribute_value, + attribute_value.into(), DBItemAttributeError::IncorrectType, )) } @@ -1449,7 +1453,7 @@ ); Err(DBItemError::new( attribute_name.to_string(), - attribute_value, + attribute_value.into(), DBItemAttributeError::Missing, )) } @@ -1471,7 +1475,7 @@ ); Err(DBItemError::new( attribute_name.to_string(), - attribute_value, + attribute_value.into(), DBItemAttributeError::IncorrectType, )) } @@ -1483,7 +1487,7 @@ ); Err(DBItemError::new( attribute_name.to_string(), - attribute_value, + attribute_value.into(), DBItemAttributeError::Missing, )) } @@ -1493,7 +1497,7 @@ fn create_device_info( flattened_device_key_upload: FlattenedDeviceKeyUpload, social_proof: Option, -) -> HashMap { +) -> AttributeMap { let mut device_info = HashMap::from([ ( USERS_TABLE_DEVICES_MAP_DEVICE_TYPE_ATTRIBUTE_NAME.to_string(), 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 @@ -9,7 +9,7 @@ TransactWriteItem, Update, WriteRequest, }, }, - database::{AttributeMap, DynamoDBError}, + database::{AttributeMap, DBItemAttributeError, DBItemError, DynamoDBError}, }; use tracing::{error, warn}; @@ -22,10 +22,7 @@ }, database::parse_string_attribute, ddb_utils::AttributesOptionExt, - error::{ - DBItemAttributeError, DBItemError, DeviceListError, Error, - FromAttributeValue, - }, + error::{DeviceListError, Error, FromAttributeValue}, grpc_services::protos::unauth::DeviceType, }; @@ -129,7 +126,7 @@ .strip_prefix(DEVICE_ITEM_KEY_PREFIX) .ok_or_else(|| DBItemError { attribute_name: ATTR_ITEM_ID.to_string(), - attribute_value: Some(AttributeValue::S(item_id.clone())), + attribute_value: item_id.clone().into(), attribute_error: DBItemAttributeError::InvalidValue, })? .to_string(); @@ -148,14 +145,14 @@ .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_value: item_id.clone().into(), 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())), + item_id.clone().into(), DBItemAttributeError::InvalidTimestamp(e), ) }) @@ -179,7 +176,7 @@ DeviceType::from_str_name(&raw_device_type).ok_or_else(|| { DBItemError::new( ATTR_DEVICE_TYPE.to_string(), - Some(AttributeValue::S(raw_device_type)), + raw_device_type.into(), DBItemAttributeError::InvalidValue, ) })?; @@ -342,7 +339,7 @@ .ok_or_else(|| { DBItemError::new( ATTR_DEVICE_IDS.to_string(), - None, + None.into(), DBItemAttributeError::Missing, ) })? diff --git a/services/identity/src/ddb_utils.rs b/services/identity/src/ddb_utils.rs --- a/services/identity/src/ddb_utils.rs +++ b/services/identity/src/ddb_utils.rs @@ -1,9 +1,12 @@ use chrono::{DateTime, NaiveDateTime, Utc}; -use comm_lib::aws::ddb::types::{AttributeValue, PutRequest, WriteRequest}; +use comm_lib::{ + aws::ddb::types::{AttributeValue, PutRequest, WriteRequest}, + database::Value, +}; use std::collections::HashMap; use std::iter::IntoIterator; -use crate::error::{DBItemAttributeError, DBItemError}; +use comm_lib::database::{DBItemAttributeError, DBItemError}; #[derive(Copy, Clone, Debug)] pub enum OlmAccountType { @@ -74,7 +77,7 @@ ) -> Result { self.ok_or_else(|| DBItemError { attribute_name: attr_name.into(), - attribute_value: None, + attribute_value: None.into(), attribute_error: DBItemAttributeError::Missing, }) } 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 @@ -1,5 +1,6 @@ use comm_lib::aws::ddb::types::AttributeValue; use comm_lib::aws::DynamoDBError; +use comm_lib::database::{DBItemAttributeError, DBItemError, Value}; use std::collections::hash_map::HashMap; use std::fmt::{Display, Formatter, Result as FmtResult}; use tracing::error; @@ -28,47 +29,6 @@ ConcurrentUpdateError, } -#[derive(Debug, derive_more::Error, derive_more::Constructor)] -pub struct DBItemError { - pub attribute_name: String, - pub attribute_value: Option, - pub attribute_error: DBItemAttributeError, -} - -impl Display for DBItemError { - fn fmt(&self, f: &mut Formatter) -> FmtResult { - match &self.attribute_error { - DBItemAttributeError::Missing => { - write!(f, "Attribute {} is missing", self.attribute_name) - } - DBItemAttributeError::IncorrectType => write!( - f, - "Value for attribute {} has incorrect type: {:?}", - self.attribute_name, self.attribute_value - ), - error => write!( - f, - "Error regarding attribute {} with value {:?}: {}", - self.attribute_name, self.attribute_value, error - ), - } - } -} - -#[derive(Debug, derive_more::Display, derive_more::Error)] -pub enum DBItemAttributeError { - #[display(...)] - Missing, - #[display(...)] - IncorrectType, - #[display(...)] - InvalidTimestamp(chrono::ParseError), - #[display(...)] - ExpiredTimestamp, - #[display(...)] - InvalidValue, -} - pub trait FromAttributeValue { fn to_vec( &self, @@ -84,7 +44,7 @@ fn handle_attr_failure(value: &AttributeValue, attr_name: &str) -> DBItemError { DBItemError { attribute_name: attr_name.to_string(), - attribute_value: Some(value.clone()), + attribute_value: Value::AttributeValue(Some(value.clone())), attribute_error: DBItemAttributeError::IncorrectType, } } @@ -124,7 +84,7 @@ .get(key) .ok_or(DBItemError { attribute_name: key.to_string(), - attribute_value: None, + attribute_value: None.into(), attribute_error: DBItemAttributeError::Missing, })? .to_string(key) @@ -138,7 +98,7 @@ .get(key) .ok_or(DBItemError { attribute_name: key.to_string(), - attribute_value: None, + attribute_value: None.into(), attribute_error: DBItemAttributeError::Missing, })? .to_hashmap(key) @@ -149,7 +109,7 @@ .get(key) .ok_or(DBItemError { attribute_name: key.to_string(), - attribute_value: None, + attribute_value: None.into(), attribute_error: DBItemAttributeError::Missing, })? .to_vec(key) diff --git a/shared/comm-lib/src/database.rs b/shared/comm-lib/src/database.rs --- a/shared/comm-lib/src/database.rs +++ b/shared/comm-lib/src/database.rs @@ -35,7 +35,7 @@ MaxRetriesExceeded, } -#[derive(Debug)] +#[derive(Debug, derive_more::From)] pub enum Value { AttributeValue(Option), String(String), @@ -43,9 +43,9 @@ #[derive(Debug, derive_more::Error, derive_more::Constructor)] pub struct DBItemError { - attribute_name: String, - attribute_value: Value, - attribute_error: DBItemAttributeError, + pub attribute_name: String, + pub attribute_value: Value, + pub attribute_error: DBItemAttributeError, } impl Display for DBItemError { @@ -80,6 +80,10 @@ InvalidTimestamp(chrono::ParseError), #[display(...)] InvalidNumberFormat(ParseIntError), + #[display(...)] + ExpiredTimestamp, + #[display(...)] + InvalidValue, } /// Conversion trait for [`AttributeValue`]