diff --git a/services/identity/src/constants.rs b/services/identity/src/constants.rs --- a/services/identity/src/constants.rs +++ b/services/identity/src/constants.rs @@ -11,10 +11,12 @@ pub const USERS_TABLE_REGISTRATION_ATTRIBUTE: &str = "pakeRegistrationData"; pub const USERS_TABLE_USERNAME_ATTRIBUTE: &str = "username"; pub const USERS_TABLE_DEVICES_ATTRIBUTE: &str = "devices"; +pub const USERS_TABLE_DEVICE_ATTRIBUTE_NAME: &str = "device"; pub const USERS_TABLE_DEVICES_MAP_ATTRIBUTE_NAME: &str = "signingPublicKey"; pub const USERS_TABLE_WALLET_ADDRESS_ATTRIBUTE: &str = "walletAddress"; pub const USERS_TABLE_USERNAME_INDEX: &str = "username-index"; pub const USERS_TABLE_WALLET_ADDRESS_INDEX: &str = "walletAddress-index"; +pub const USERS_TABLE_INITIALIZATION_INFO: &str = "initializationInfo"; pub const ACCESS_TOKEN_TABLE: &str = "identity-tokens"; pub const ACCESS_TOKEN_TABLE_PARTITION_KEY: &str = "userID"; 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 @@ -20,6 +20,7 @@ ACCESS_TOKEN_TABLE_VALID_ATTRIBUTE, NONCE_TABLE, NONCE_TABLE_CREATED_ATTRIBUTE, NONCE_TABLE_PARTITION_KEY, USERS_TABLE, USERS_TABLE_DEVICES_ATTRIBUTE, USERS_TABLE_DEVICES_MAP_ATTRIBUTE_NAME, + USERS_TABLE_DEVICE_ATTRIBUTE_NAME, USERS_TABLE_INITIALIZATION_INFO, USERS_TABLE_PARTITION_KEY, USERS_TABLE_REGISTRATION_ATTRIBUTE, USERS_TABLE_USERNAME_ATTRIBUTE, USERS_TABLE_USERNAME_INDEX, USERS_TABLE_WALLET_ADDRESS_ATTRIBUTE, USERS_TABLE_WALLET_ADDRESS_INDEX, @@ -70,6 +71,31 @@ } } + pub async fn get_session_initialization_info( + &self, + user_id: &str, + ) -> Result>>, Error> { + match self.get_item_from_users_table(user_id).await { + Ok(GetItemOutput { + item: Some(mut item), + .. + }) => parse_devices_attribute(item.remove(USERS_TABLE_DEVICES_ATTRIBUTE)) + .map(Some) + .map_err(Error::Attribute), + Ok(_) => { + info!("No item found for user {} in users table", user_id); + Ok(None) + } + Err(e) => { + error!( + "DynamoDB client failed to get session initialization info for user {}: {}", + user_id, e + ); + Err(e) + } + } + } + pub async fn update_users_table( &self, user_id: String, @@ -611,6 +637,55 @@ } } +fn parse_devices_attribute( + attribute: Option, +) -> Result>, DBItemError> { + let mut devices = HashMap::new(); + let ddb_devices = + parse_map_attribute(USERS_TABLE_DEVICES_ATTRIBUTE, attribute)?; + + for (signing_public_key, session_initialization_info) in ddb_devices { + let session_initialization_info_map = parse_map_attribute( + USERS_TABLE_DEVICE_ATTRIBUTE_NAME, + Some(session_initialization_info), + )?; + let mut inner_hash_map = HashMap::new(); + for (initialization_component_name, initialization_component_value) in + session_initialization_info_map + { + let initialization_piece_value_string = parse_string_attribute( + USERS_TABLE_INITIALIZATION_INFO, + Some(initialization_component_value), + )?; + inner_hash_map.insert( + initialization_component_name, + initialization_piece_value_string, + ); + } + devices.insert(signing_public_key, inner_hash_map); + } + Ok(devices) +} + +fn parse_map_attribute( + attribute_name: &'static str, + attribute_value: Option, +) -> Result, DBItemError> { + match attribute_value { + Some(AttributeValue::M(map)) => Ok(map), + Some(_) => Err(DBItemError::new( + attribute_name, + attribute_value, + DBItemAttributeError::IncorrectType, + )), + None => Err(DBItemError::new( + attribute_name, + attribute_value, + DBItemAttributeError::Missing, + )), + } +} + fn parse_string_attribute( attribute_name: &'static str, attribute_value: Option,