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 @@ -8,6 +8,7 @@ types::{AttributeValue, PutRequest, ReturnConsumedCapacity, WriteRequest}, }; use comm_lib::aws::AwsConfig; +use comm_lib::database::{AttributeMap, DBItemAttributeError, DBItemError}; use constant_time_eq::constant_time_eq; use std::collections::{HashMap, HashSet}; use std::str::FromStr; @@ -16,7 +17,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}; @@ -91,7 +92,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, }) }) @@ -1089,13 +1090,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?; @@ -1134,7 +1138,7 @@ async fn get_keys_for_user( &self, - mut user: HashMap, + mut user: AttributeMap, get_one_time_keys: bool, ) -> Result, Error> { let user_id = parse_string_attribute( @@ -1506,14 +1510,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, )) } @@ -1528,14 +1532,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, )) } @@ -1548,12 +1552,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, )), } @@ -1566,12 +1570,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, )), } @@ -1586,12 +1590,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, )), } @@ -1601,7 +1605,7 @@ fn parse_map_attribute( attribute_name: &str, attribute_value: Option, -) -> Result, DBItemError> { +) -> Result { match attribute_value { Some(AttributeValue::M(map)) => Ok(map), Some(_) => { @@ -1613,7 +1617,7 @@ ); Err(DBItemError::new( attribute_name.to_string(), - attribute_value, + attribute_value.into(), DBItemAttributeError::IncorrectType, )) } @@ -1625,7 +1629,7 @@ ); Err(DBItemError::new( attribute_name.to_string(), - attribute_value, + attribute_value.into(), DBItemAttributeError::Missing, )) } @@ -1647,7 +1651,7 @@ ); Err(DBItemError::new( attribute_name.to_string(), - attribute_value, + attribute_value.into(), DBItemAttributeError::IncorrectType, )) } @@ -1659,7 +1663,7 @@ ); Err(DBItemError::new( attribute_name.to_string(), - attribute_value, + attribute_value.into(), DBItemAttributeError::Missing, )) } @@ -1669,7 +1673,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 @@ DeleteRequest, Put, TransactWriteItem, Update, WriteRequest, }, }, - database::{AttributeMap, DynamoDBError}, + database::{AttributeMap, DBItemAttributeError, DBItemError, DynamoDBError}, }; use tracing::{error, warn}; @@ -29,10 +29,7 @@ }, database::parse_string_attribute, ddb_utils::AttributesOptionExt, - error::{ - DBItemAttributeError, DBItemError, DeviceListError, Error, - FromAttributeValue, - }, + error::{DeviceListError, Error, FromAttributeValue}, grpc_services::protos::unauth::DeviceType, }; @@ -151,7 +148,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: Some(AttributeValue::S(item_id.clone())).into(), attribute_error: DBItemAttributeError::InvalidValue, })? .to_string(); @@ -170,14 +167,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: Some(AttributeValue::S(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())), + Some(AttributeValue::S(item_id.clone())).into(), DBItemAttributeError::InvalidTimestamp(e), ) }) @@ -201,7 +198,7 @@ DeviceType::from_str_name(&raw_device_type).ok_or_else(|| { DBItemError::new( ATTR_DEVICE_TYPE.to_string(), - Some(AttributeValue::S(raw_device_type)), + Some(AttributeValue::S(raw_device_type)).into(), DBItemAttributeError::InvalidValue, ) })?; @@ -386,7 +383,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; @@ -29,47 +30,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, @@ -85,7 +45,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, } } @@ -125,7 +85,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) @@ -139,7 +99,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) @@ -150,7 +110,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`]